hercules-3.07/000777 000765 000765 00000000000 11345533276 014760 5ustar00jmaynardjmaynard000000 000000 hercules-3.07/_TODO.txt000644 000765 000765 00000011720 11344073445 016416 0ustar00jmaynardjmaynard000000 000000 --------------------- HERCULES TODO IDEAS --------------------- (in absolutely *NO* particular order) BUG? 'cmdtgt' support needs re-worked to prevent e.g. DIAG8 commands from being erroneously sent to (processed by) the guest instead of by Hercules. Issue was raised by Martin Trübner [Martin@pi-sysprog.de] on the main Herc list on 2/12/2010: setting 'cmdtgt', while handy in regards to letting you issue panel commands directly to the guest without having to precede the command with a '.', also unfortunately causes "hypervisor" commands (i.e. Hercules commands) issued via DIAG8 to be processed as GUEST commands and not Hercules (hypervisor) commands! Oops! (see "panel_command" function in 'cmdtab.c' near line 390 in the "#ifdef OPTION_CMDTGT" block) The fix MIGHT be to have an "internal" "panel_command" function that all of our internal functions can use instead, which would set a flag to FORCE the 'cmdtab.c' logic to treat that specific call as "cmdtgt herc" instead? Also provide separate zip file containing .PDB files for download for Windows snapshots (but especially for final official Windows releases!) so that on the rare occasion that Hercules ever does crash we're able to determine exactly where the crash occurred. We cannot do that without the .PDB files! Design a more platform generic cpu features runtime check that checks for the availability of certain processor features and then points some sysblk function-pointers to the correct function. That way we can exploit certain features if they're available. Of course going through a function pointer may be too inefficient depending on where the function is being used, but depending on what the function (feature) provides it may end up being an overall gain than a loss. E.g. (WIN64): init_hostinfo: BOOL WINAPI IsProcessorFeaturePresent( PF_COMPARE_EXCHANGE128 ); _INTEGRAL_MAX_BITS (machdep.h ==> _InterlockedCompareExchange128 ==> cmpxchg16b) Support multiple command-line commands (i.e. cmdsep character). Design a way for users to define command synonyms. (dynmod?) Document all DIAGNOSE instruction support Trace (instruction and/or device) to file instead of to console. (Then new utility to format/display it offline). Windows block device support (i.e. ability to define an entire drive (Windows drive letter / partition) as a Hercules dasd) BUG: instruction tracing: control registers not being shown for some instructions which use/modify them. We need a better way to determine if FPRs/CRs/ARs should be traced or not. (New bits in INSTR table?) (see "display_inst_regs" function in "hscmisc.c") Full 2540 reader/punch support! mode=1 (normal), mode=2 (binary/"card image") hopper selection, etc. Ability to specify highlighting for console messages via regex pattern. Add MSVC support for 'MULTI_BYTE_ASSIST' (cpu.c "set_jump_pointers") ISSUE: there's the possibility for "socketpair" function to connect to some other socket other than the pair's listening socket due to some other socket on the host already listening for connections on INADDR_LOOPBACK. Fix is to change the "socketpair" function to use a starting port# and SO_REUSEADDR in a 'setsockopt' call and detect (HSO_errno == HSO_EADDRINUSE) return code in its 'bind' call and auto-retry again using next port# (in a loop). Refer to the "console_connection_handler" function for reference. Custom (dynmod?) default Code Page support DUMP command (Windows only) to create on-demand mini-dump. Device or facility per Gerhard Postpischil's 9/20/2007 suggestion that allows one to generate random "problems" (i/o errors, machine checks, etc) for better software error recovery testing. Add new "+rdbwd" 3590-device-only option to set flag in TapeCommands3590 table to allow/accept Read Backward CCW. (Requested by "herc_fun" = Charlie ) Add 'auto' option to MAXRATES command, to have it also issue the command automatically at the end of the interval (so you can monitor the rate). "Generic-ize" the 'qd' command so that it works for ANY device instead of just dasd devices. SenseId and RDC (Read Device Characteristics) information is valuable information to display for devices other than dasd! (e.g. tape devices for example) Add SRF (Suspend/Resume) support for tape devices. Add SRF (Suspend/Resume) support for CTC devices. BCTC support for sysplex'ing via GRS. Generic native host SCSI support (mostly for tape, but having it opens other interesting possibilities) QDIO/QETH (custom Herc device driver to directly update guest storage) Large block support in channel subsystem (blocks > 64K ==> 2MB maximum?) hercules-3.07/ABOUT-NLS000644 000765 000765 00000203620 11143760543 016201 0ustar00jmaynardjmaynard000000 000000 1 Notes on the Free Translation Project *************************************** Free software is going international! The Free Translation Project is a way to get maintainers of free software, translators, and users all together, so that free software will gradually become able to speak many languages. A few packages already provide translations for their messages. If you found this `ABOUT-NLS' file inside a distribution, you may assume that the distributed package does use GNU `gettext' internally, itself available at your nearest GNU archive site. But you do _not_ need to install GNU `gettext' prior to configuring, installing or using this package with messages translated. Installers will find here some useful hints. These notes also explain how users should proceed for getting the programs to use the available translations. They tell how people wanting to contribute and work on translations can contact the appropriate team. When reporting bugs in the `intl/' directory or bugs which may be related to internationalization, you should tell about the version of `gettext' which is used. The information can be found in the `intl/VERSION' file, in internationalized packages. 1.1 Quick configuration advice ============================== If you want to exploit the full power of internationalization, you should configure it using ./configure --with-included-gettext to force usage of internationalizing routines provided within this package, despite the existence of internationalizing capabilities in the operating system where this package is being installed. So far, only the `gettext' implementation in the GNU C library version 2 provides as many features (such as locale alias, message inheritance, automatic charset conversion or plural form handling) as the implementation here. It is also not possible to offer this additional functionality on top of a `catgets' implementation. Future versions of GNU `gettext' will very likely convey even more functionality. So it might be a good idea to change to GNU `gettext' as soon as possible. So you need _not_ provide this option if you are using GNU libc 2 or you have installed a recent copy of the GNU gettext package with the included `libintl'. 1.2 INSTALL Matters =================== Some packages are "localizable" when properly installed; the programs they contain can be made to speak your own native language. Most such packages use GNU `gettext'. Other packages have their own ways to internationalization, predating GNU `gettext'. By default, this package will be installed to allow translation of messages. It will automatically detect whether the system already provides the GNU `gettext' functions. If not, the included GNU `gettext' library will be used. This library is wholly contained within this package, usually in the `intl/' subdirectory, so prior installation of the GNU `gettext' package is _not_ required. Installers may use special options at configuration time for changing the default behaviour. The commands: ./configure --with-included-gettext ./configure --disable-nls will, respectively, bypass any pre-existing `gettext' to use the internationalizing routines provided within this package, or else, _totally_ disable translation of messages. When you already have GNU `gettext' installed on your system and run configure without an option for your new package, `configure' will probably detect the previously built and installed `libintl.a' file and will decide to use this. This might not be desirable. You should use the more recent version of the GNU `gettext' library. I.e. if the file `intl/VERSION' shows that the library which comes with this package is more recent, you should use ./configure --with-included-gettext to prevent auto-detection. The configuration process will not test for the `catgets' function and therefore it will not be used. The reason is that even an emulation of `gettext' on top of `catgets' could not provide all the extensions of the GNU `gettext' library. Internationalized packages usually have many `po/LL.po' files, where LL gives an ISO 639 two-letter code identifying the language. Unless translations have been forbidden at `configure' time by using the `--disable-nls' switch, all available translations are installed together with the package. However, the environment variable `LINGUAS' may be set, prior to configuration, to limit the installed set. `LINGUAS' should then contain a space separated list of two-letter codes, stating which languages are allowed. 1.3 Using This Package ====================== As a user, if your language has been installed for this package, you only have to set the `LANG' environment variable to the appropriate `LL_CC' combination. 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. 1.4 Translating Teams ===================== For the Free Translation Project to be a success, we need interested people who like their own language and write it well, and who are also able to synergize with other translators speaking the same language. Each translation team has its own mailing list. The up-to-date list of teams can be found at the Free Translation Project's homepage, `http://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. 1.5 Available Packages ====================== Languages are not equally supported in all packages. The following matrix shows the current state of internationalization, as of April 2005. The matrix shows, in regard of each package, for which languages PO files have been submitted to translation coordination, with a translation percentage of at least 50%. Ready PO files af am ar az be bg bs ca cs cy da de el en en_GB +-------------------------------------------------+ GNUnet | | a2ps | [] [] [] [] [] | aegis | () | ant-phone | () | anubis | [] | ap-utils | | aspell | [] [] [] [] | bash | [] [] | batchelor | [] | bfd | | bibshelf | [] | binutils | [] | bison | [] [] | bluez-pin | [] [] [] [] | clisp | [] [] | console-tools | [] [] | coreutils | [] [] [] [] | cpio | | cpplib | [] [] [] | darkstat | [] () [] | dialog | [] [] [] [] [] [] | diffutils | [] [] [] [] [] | doodle | [] | e2fsprogs | [] [] | enscript | [] [] [] [] | error | [] [] [] [] | fetchmail | [] () [] [] [] | fileutils | [] [] | findutils | [] [] [] | flex | [] [] [] | fslint | [] | gas | | gawk | [] [] [] | gbiff | [] | gcal | [] | gcc | [] | gettext-examples | [] [] [] [] | gettext-runtime | [] [] [] [] | gettext-tools | [] [] | gimp-print | [] [] [] [] | gip | | gliv | [] | glunarclock | | gmult | [] [] | gnubiff | () | gnucash | [] () () [] | gnucash-glossary | [] () | 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 | | gsasl | [] | gss | | gst-plugins | [] [] [] [] [] [] | gstreamer | [] [] [] [] [] | gtick | [] () | gtkspell | [] [] [] | hello | [] [] [] [] | id-utils | [] [] | impost | | indent | [] [] | iso_3166 | | iso_3166_1 | [] [] [] [] [] | iso_3166_2 | | iso_3166_3 | [] | iso_4217 | | iso_639 | | jpilot | [] | jtag | | jwhois | | kbd | [] [] [] [] | latrine | () | ld | [] | libc | [] [] [] [] [] | libextractor | | libgpewidget | [] [] [] | libgsasl | | libiconv | [] [] [] [] [] | libidn | | lifelines | [] () | lilypond | [] | lingoteach | | lynx | [] [] [] [] | m4 | [] [] [] [] | mailutils | [] | make | [] [] | man-db | [] () [] [] | minicom | [] [] | mysecretdiary | [] [] | nano | [] () [] | nano_1_0 | [] () [] [] | opcodes | [] | parted | [] [] [] [] | psmisc | | ptx | [] [] [] | pwdutils | | python | | radius | [] | recode | [] [] [] [] [] | rpm | [] [] | screem | | scrollkeeper | [] [] [] [] [] [] [] [] | sed | [] [] | sh-utils | [] [] | shared-mime-info | [] [] | sharutils | [] [] [] [] [] | silky | | skencil | [] () | sketch | [] () | solfege | [] | soundtracker | [] [] | sp | [] | stardict | [] | tar | | texinfo | [] [] | textutils | [] [] [] | tin | () () | tp-robot | [] | tuxpaint | [] [] [] [] [] [] [] | unicode-han-tra... | | unicode-transla... | | util-linux | [] [] [] [] | vorbis-tools | [] [] [] [] | wastesedge | () | wdiff | [] [] [] [] | wget | [] [] [] [] [] [] | xchat | [] [] [] [] | xkeyboard-config | | xpad | | +-------------------------------------------------+ af am ar az be bg bs ca cs cy da de el en en_GB 10 0 0 2 7 4 0 41 43 3 52 90 20 1 15 eo es et eu fa fi fr ga gl he hr hu id is it +-----------------------------------------------+ GNUnet | | a2ps | [] [] [] () | aegis | | ant-phone | [] | anubis | [] | ap-utils | [] | aspell | [] [] | bash | [] [] [] [] | batchelor | [] [] | bfd | [] | bibshelf | [] [] [] | binutils | [] [] | bison | [] [] [] [] [] [] | bluez-pin | [] [] [] [] [] [] | clisp | [] [] | console-tools | | coreutils | [] [] [] [] [] | cpio | [] [] | cpplib | [] [] | darkstat | [] () [] [] [] | dialog | [] [] [] [] [] [] [] [] | diffutils | [] [] [] [] [] [] [] [] [] [] | doodle | [] [] | e2fsprogs | [] [] [] | enscript | [] [] | error | [] [] [] [] [] | fetchmail | [] | fileutils | [] [] [] [] [] [] | findutils | [] [] [] [] [] | flex | [] [] [] | fslint | [] | gas | [] [] | gawk | [] [] [] [] | gbiff | [] | gcal | [] [] | gcc | [] | gettext-examples | [] [] [] [] | gettext-runtime | [] [] [] [] [] [] | gettext-tools | [] [] [] | gimp-print | [] [] | gip | [] [] [] | gliv | () | glunarclock | [] [] [] | gmult | [] [] [] | gnubiff | () () | gnucash | [] () [] | gnucash-glossary | [] [] | 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 | [] [] [] | gsasl | [] [] [] | gss | [] | gst-plugins | [] [] [] | gstreamer | [] | gtick | [] [] [] [] [] | gtkspell | [] [] [] [] [] [] | hello | [] [] [] [] [] [] [] [] [] [] [] [] [] [] | id-utils | [] [] [] [] | impost | [] [] | indent | [] [] [] [] [] [] [] [] [] [] [] | iso_3166 | [] [] [] | iso_3166_1 | [] [] [] [] [] [] [] | iso_3166_2 | [] | iso_3166_3 | [] | iso_4217 | [] [] [] | iso_639 | [] [] [] [] | jpilot | [] [] | jtag | [] | jwhois | [] [] [] [] [] | kbd | [] [] | latrine | [] [] [] | ld | [] [] | libc | [] [] [] [] [] | libextractor | | libgpewidget | [] [] [] [] [] | libgsasl | [] [] | libiconv | [] [] [] [] [] [] [] [] [] [] [] | libidn | [] [] | lifelines | () | lilypond | [] | lingoteach | [] [] [] | lynx | [] [] [] | m4 | [] [] [] [] | mailutils | [] [] | make | [] [] [] [] [] [] [] | man-db | () | minicom | [] [] [] [] | mysecretdiary | [] [] [] | nano | [] [] () [] [] | nano_1_0 | [] [] [] [] [] | opcodes | [] [] | parted | [] [] [] [] | psmisc | [] [] | ptx | [] [] [] [] [] [] [] [] [] | pwdutils | | python | | radius | [] [] | recode | [] [] [] [] [] [] [] [] | rpm | [] | screem | | scrollkeeper | [] [] [] | sed | [] [] [] [] [] | sh-utils | [] [] [] [] [] [] [] | shared-mime-info | [] [] [] [] [] [] | sharutils | [] [] [] [] [] [] [] | silky | [] | skencil | [] [] | sketch | [] [] | solfege | [] | soundtracker | [] [] [] | sp | [] | stardict | [] | tar | [] [] [] [] [] | texinfo | [] [] [] | textutils | [] [] [] [] [] | tin | [] () | tp-robot | [] [] | tuxpaint | [] [] [] [] [] [] [] [] [] | unicode-han-tra... | | unicode-transla... | [] [] | util-linux | [] [] [] [] [] [] | vorbis-tools | [] [] | wastesedge | () | wdiff | [] [] [] [] [] [] [] [] | wget | [] [] [] [] [] [] [] [] [] [] | xchat | [] [] [] [] [] | xkeyboard-config | | xpad | [] [] [] | +-----------------------------------------------+ eo es et eu fa fi fr ga gl he hr hu id is it 13 85 21 15 2 35 115 45 17 8 6 40 27 1 45 ja ko ku lg lt lv mk mn ms mt nb nl nn no nso +-----------------------------------------------+ GNUnet | | a2ps | () [] [] () | aegis | () | ant-phone | [] | anubis | [] [] [] | ap-utils | | aspell | [] [] | bash | [] | batchelor | [] | bfd | | bibshelf | | binutils | | bison | [] [] [] | bluez-pin | [] | clisp | [] | console-tools | | coreutils | [] [] | cpio | | cpplib | | darkstat | [] [] | dialog | [] | diffutils | [] [] [] | doodle | | e2fsprogs | | enscript | [] | error | [] | fetchmail | [] [] | fileutils | [] [] | findutils | [] | flex | [] [] | fslint | [] | gas | | gawk | [] [] | gbiff | [] | gcal | | gcc | | gettext-examples | [] [] | gettext-runtime | [] [] [] | gettext-tools | [] [] | gimp-print | [] [] | gip | [] | gliv | [] | glunarclock | [] [] | gmult | [] | gnubiff | | gnucash | () () [] | gnucash-glossary | [] | 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 | | gsasl | [] | gss | | gst-plugins | [] | gstreamer | [] | gtick | [] | gtkspell | [] [] | hello | [] [] [] [] [] [] [] [] | id-utils | [] | impost | | indent | [] [] | iso_3166 | [] | iso_3166_1 | [] [] | iso_3166_2 | [] | iso_3166_3 | [] | iso_4217 | [] [] [] | iso_639 | [] [] [] | jpilot | () () () | jtag | | jwhois | [] | kbd | [] | latrine | [] | ld | | libc | [] [] [] [] [] | libextractor | | libgpewidget | [] | libgsasl | [] | libiconv | [] | libidn | | lifelines | [] | lilypond | [] | lingoteach | [] | lynx | [] [] | m4 | [] [] | mailutils | | make | [] [] [] | man-db | () | minicom | [] | mysecretdiary | [] | nano | [] [] | nano_1_0 | [] [] [] | opcodes | [] | parted | [] [] | psmisc | [] [] | ptx | [] [] [] | pwdutils | | python | | radius | | recode | [] | rpm | [] [] | screem | [] | scrollkeeper | [] [] [] | sed | [] [] | sh-utils | [] [] | shared-mime-info | [] [] [] [] | sharutils | [] [] | silky | [] | skencil | | sketch | | solfege | [] [] | soundtracker | | sp | () | stardict | [] [] | tar | [] [] | texinfo | [] [] [] | textutils | [] [] [] | tin | | tp-robot | [] | tuxpaint | [] [] [] [] [] [] | unicode-han-tra... | | unicode-transla... | | util-linux | [] [] | vorbis-tools | [] | wastesedge | [] | wdiff | [] [] | wget | [] [] | xchat | [] [] [] [] | xkeyboard-config | [] | xpad | [] | +-----------------------------------------------+ ja ko ku lg lt lv mk mn ms mt nb nl nn no nso 33 11 1 1 1 2 2 3 11 0 15 96 7 5 0 or pa pl pt pt_BR rm ro ru rw sk sl sq sr sv ta +-------------------------------------------------+ GNUnet | | a2ps | () [] [] [] [] [] [] | aegis | () () | ant-phone | [] | anubis | [] [] [] | ap-utils | () | aspell | [] [] | bash | [] [] [] | batchelor | [] | bfd | | bibshelf | | binutils | [] [] | bison | [] [] [] [] [] | bluez-pin | [] [] [] [] [] [] [] [] | clisp | [] | console-tools | [] | coreutils | [] [] [] [] | cpio | [] [] | cpplib | | darkstat | [] [] [] [] [] [] | dialog | [] [] [] [] [] [] [] | diffutils | [] [] [] [] [] [] | doodle | [] | e2fsprogs | [] [] | enscript | [] [] [] [] | error | [] [] [] | fetchmail | [] () [] [] [] | fileutils | [] [] [] [] [] | findutils | [] [] [] [] [] [] | flex | [] [] [] [] [] | fslint | [] [] [] | gas | | gawk | [] [] [] [] | gbiff | [] | gcal | [] | gcc | | gettext-examples | [] [] [] [] [] [] | gettext-runtime | [] [] [] [] [] [] [] | gettext-tools | [] [] [] [] [] [] [] | gimp-print | [] [] | gip | [] [] [] | gliv | [] [] [] | glunarclock | [] [] [] [] [] [] | gmult | [] [] [] [] | gnubiff | () [] | gnucash | () [] [] [] [] | gnucash-glossary | [] [] [] | 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 | [] | gsasl | [] [] [] [] [] | gss | [] [] [] | gst-plugins | [] [] [] [] | gstreamer | [] [] [] [] | gtick | [] [] [] | gtkspell | [] [] [] [] [] [] | hello | [] [] [] [] [] [] [] | id-utils | [] [] [] [] | impost | | indent | [] [] [] [] [] [] | iso_3166 | [] [] [] [] [] | iso_3166_1 | [] [] [] [] | iso_3166_2 | | iso_3166_3 | [] [] [] | iso_4217 | [] [] | iso_639 | [] [] [] | jpilot | | jtag | [] | jwhois | [] [] [] () () | kbd | [] [] [] | latrine | [] [] | ld | [] | libc | [] [] [] [] [] | libextractor | [] | libgpewidget | [] [] [] [] [] [] | libgsasl | [] [] [] | libiconv | [] [] [] [] [] [] [] [] [] [] | libidn | [] () | lifelines | [] [] | lilypond | [] | lingoteach | [] | lynx | [] [] [] | m4 | [] [] [] [] [] | mailutils | [] [] [] | make | [] [] [] [] | man-db | [] [] | minicom | [] [] [] [] | mysecretdiary | [] [] [] [] | nano | [] [] [] | nano_1_0 | [] [] [] [] | opcodes | [] [] | parted | [] [] [] [] | psmisc | [] [] | ptx | [] [] [] [] [] [] | pwdutils | [] | python | | radius | [] [] | recode | [] [] [] [] [] [] | rpm | [] [] [] [] | screem | | scrollkeeper | [] [] [] [] [] [] [] | sed | [] [] [] [] [] [] [] [] | sh-utils | [] [] [] | shared-mime-info | [] [] [] [] [] | sharutils | [] [] [] | silky | [] | skencil | [] [] [] | sketch | [] [] [] | solfege | | soundtracker | [] [] | sp | | stardict | [] [] | tar | [] [] [] [] | texinfo | [] [] [] [] | textutils | [] [] [] | tin | | tp-robot | [] | tuxpaint | [] [] [] [] [] [] [] [] | unicode-han-tra... | | unicode-transla... | | util-linux | [] [] [] | vorbis-tools | [] [] | wastesedge | | wdiff | [] [] [] [] [] [] | wget | [] [] [] [] [] [] [] [] [] | xchat | [] [] [] [] [] [] | xkeyboard-config | | xpad | | +-------------------------------------------------+ or pa pl pt pt_BR rm ro ru rw sk sl sq sr sv ta 1 0 48 30 58 6 79 71 5 45 13 12 50 86 0 tg th tk tr uk ven vi wa xh zh_CN zh_TW zu +--------------------------------------------+ GNUnet | | 0 a2ps | [] [] [] | 19 aegis | | 0 ant-phone | [] | 4 anubis | [] | 9 ap-utils | () | 1 aspell | [] [] [] | 13 bash | | 10 batchelor | [] [] | 7 bfd | | 1 bibshelf | [] | 5 binutils | [] | 6 bison | [] | 17 bluez-pin | [] [] [] [] [] | 24 clisp | | 7 console-tools | [] | 4 coreutils | [] | 16 cpio | [] [] | 6 cpplib | [] [] | 7 darkstat | [] () () | 15 dialog | [] [] [] | 25 diffutils | [] [] [] [] | 28 doodle | [] | 5 e2fsprogs | [] | 8 enscript | [] | 12 error | [] [] [] | 16 fetchmail | [] | 12 fileutils | [] [] [] | 18 findutils | [] [] | 17 flex | [] [] | 15 fslint | [] | 7 gas | [] | 3 gawk | [] | 14 gbiff | | 4 gcal | [] | 5 gcc | [] | 3 gettext-examples | [] [] [] [] | 20 gettext-runtime | [] [] [] [] [] | 25 gettext-tools | [] [] [] | 17 gimp-print | [] | 11 gip | [] | 8 gliv | [] | 6 glunarclock | [] [] | 13 gmult | [] [] [] | 13 gnubiff | [] | 3 gnucash | () [] | 10 gnucash-glossary | [] | 8 gpe-aerial | [] [] | 13 gpe-beam | [] [] | 13 gpe-calendar | [] [] [] [] | 18 gpe-clock | [] [] [] [] | 17 gpe-conf | [] [] | 12 gpe-contacts | [] [] | 6 gpe-edit | [] [] [] [] | 15 gpe-go | [] [] | 11 gpe-login | [] [] [] [] [] | 18 gpe-ownerinfo | [] [] [] [] | 19 gpe-sketchbook | [] [] | 14 gpe-su | [] [] [] | 16 gpe-taskmanager | [] [] [] | 17 gpe-timesheet | [] [] [] [] | 17 gpe-today | [] [] [] [] [] | 19 gpe-todo | [] [] [] | 16 gphoto2 | [] [] | 17 gprof | [] [] | 10 gpsdrive | | 2 gramadoir | [] | 6 grep | [] [] [] [] | 32 gretl | | 4 gsasl | [] [] | 12 gss | [] | 5 gst-plugins | [] [] | 16 gstreamer | [] [] [] | 14 gtick | [] | 11 gtkspell | [] [] [] | 20 hello | [] [] [] [] | 37 id-utils | [] [] | 13 impost | [] | 3 indent | [] [] [] | 24 iso_3166 | [] [] [] | 12 iso_3166_1 | [] [] | 20 iso_3166_2 | | 2 iso_3166_3 | [] [] | 8 iso_4217 | [] [] | 10 iso_639 | [] [] | 12 jpilot | [] [] [] | 6 jtag | | 2 jwhois | [] [] [] | 12 kbd | [] [] | 12 latrine | [] [] | 8 ld | [] | 5 libc | [] [] | 22 libextractor | | 1 libgpewidget | [] [] | 17 libgsasl | [] | 7 libiconv | [] [] [] [] [] | 32 libidn | [] [] | 5 lifelines | | 4 lilypond | [] | 5 lingoteach | | 5 lynx | [] [] | 14 m4 | [] [] | 17 mailutils | [] | 7 make | [] [] | 18 man-db | | 5 minicom | | 11 mysecretdiary | [] [] | 12 nano | | 11 nano_1_0 | [] [] | 17 opcodes | [] | 7 parted | [] [] [] | 17 psmisc | [] | 7 ptx | [] [] | 23 pwdutils | | 1 python | | 0 radius | [] | 6 recode | [] [] | 22 rpm | [] [] | 11 screem | | 1 scrollkeeper | [] [] | 23 sed | [] [] | 19 sh-utils | [] | 15 shared-mime-info | [] [] | 19 sharutils | [] [] [] | 20 silky | | 3 skencil | | 6 sketch | | 6 solfege | | 4 soundtracker | [] | 8 sp | [] | 3 stardict | [] [] [] [] | 10 tar | [] [] | 13 texinfo | [] [] | 14 textutils | [] [] [] | 17 tin | | 1 tp-robot | [] [] | 7 tuxpaint | [] [] [] [] | 34 unicode-han-tra... | | 0 unicode-transla... | | 2 util-linux | [] [] | 17 vorbis-tools | [] | 10 wastesedge | | 1 wdiff | [] [] | 22 wget | [] [] [] [] | 31 xchat | [] [] [] | 22 xkeyboard-config | | 1 xpad | [] | 5 +--------------------------------------------+ 72 teams tg th tk tr uk ven vi wa xh zh_CN zh_TW zu 147 domains 0 0 1 78 29 0 71 16 0 41 20 0 1711 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 April 2005 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'. 1.6 Using `gettext' in new packages =================================== If you are writing a freely available program and want to internationalize it you are welcome to use GNU `gettext' in your package. Of course you have to respect the GNU Library General Public License which covers the use of the GNU `gettext' library. This means in particular that even non-free programs can use `libintl' as a shared library, whereas only free software can use `libintl' as a static library or use modified versions of `libintl'. Once the sources are changed appropriately and the setup can handle the use of `gettext' the only thing missing are the translations. The Free Translation Project is also available for packages which are not developed inside the GNU project. Therefore the information given above applies also for every other Free Software Project. Contact `translation@iro.umontreal.ca' to make the `.pot' files available to the translation teams. hercules-3.07/aclocal.m4000644 000765 000765 00000100134 11344713134 016603 0ustar00jmaynardjmaynard000000 000000 # generated automatically by aclocal 1.9.6 -*- Autoconf -*- # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, # 2005 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. # Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_AUTOMAKE_VERSION(VERSION) # ---------------------------- # Automake X.Y traces this macro to ensure aclocal.m4 has been # generated from the m4 files accompanying Automake X.Y. AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api_version="1.9"]) # AM_SET_CURRENT_AUTOMAKE_VERSION # ------------------------------- # Call AM_AUTOMAKE_VERSION so it can be traced. # This function is AC_REQUIREd by AC_INIT_AUTOMAKE. AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], [AM_AUTOMAKE_VERSION([1.9.6])]) # AM_AUX_DIR_EXPAND -*- Autoconf -*- # Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets # $ac_aux_dir to `$srcdir/foo'. In other projects, it is set to # `$srcdir', `$srcdir/..', or `$srcdir/../..'. # # Of course, Automake must honor this variable whenever it calls a # tool from the auxiliary directory. The problem is that $srcdir (and # therefore $ac_aux_dir as well) can be either absolute or relative, # depending on how configure is run. This is pretty annoying, since # it makes $ac_aux_dir quite unusable in subdirectories: in the top # source directory, any form will work fine, but in subdirectories a # relative path needs to be adjusted first. # # $ac_aux_dir/missing # fails when called from a subdirectory if $ac_aux_dir is relative # $top_srcdir/$ac_aux_dir/missing # fails if $ac_aux_dir is absolute, # fails when called from a subdirectory in a VPATH build with # a relative $ac_aux_dir # # The reason of the latter failure is that $top_srcdir and $ac_aux_dir # are both prefixed by $srcdir. In an in-source build this is usually # harmless because $srcdir is `.', but things will broke when you # start a VPATH build or use an absolute $srcdir. # # So we could use something similar to $top_srcdir/$ac_aux_dir/missing, # iff we strip the leading $srcdir from $ac_aux_dir. That would be: # am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` # and then we would define $MISSING as # MISSING="\${SHELL} $am_aux_dir/missing" # This will work as long as MISSING is not called from configure, because # unfortunately $(top_srcdir) has no meaning in configure. # However there are other variables, like CC, which are often used in # configure, and could therefore not use this "fixed" $ac_aux_dir. # # Another solution, used here, is to always expand $ac_aux_dir to an # absolute PATH. The drawback is that using absolute paths prevent a # configured tree to be moved without reconfiguration. AC_DEFUN([AM_AUX_DIR_EXPAND], [dnl Rely on autoconf to set up CDPATH properly. AC_PREREQ([2.50])dnl # expand $ac_aux_dir to an absolute path am_aux_dir=`cd $ac_aux_dir && pwd` ]) # AM_CONDITIONAL -*- Autoconf -*- # Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005 # Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 7 # AM_CONDITIONAL(NAME, SHELL-CONDITION) # ------------------------------------- # Define a conditional. AC_DEFUN([AM_CONDITIONAL], [AC_PREREQ(2.52)dnl ifelse([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl AC_SUBST([$1_TRUE]) AC_SUBST([$1_FALSE]) if $2; then $1_TRUE= $1_FALSE='#' else $1_TRUE='#' $1_FALSE= fi AC_CONFIG_COMMANDS_PRE( [if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then AC_MSG_ERROR([[conditional "$1" was never defined. Usually this means the macro was only invoked conditionally.]]) fi])]) # Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005 # Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 8 # There are a few dirty hacks below to avoid letting `AC_PROG_CC' be # written in clear, in which case automake, when reading aclocal.m4, # will think it sees a *use*, and therefore will trigger all it's # C support machinery. Also note that it means that autoscan, seeing # CC etc. in the Makefile, will ask for an AC_PROG_CC use... # _AM_DEPENDENCIES(NAME) # ---------------------- # See how the compiler implements dependency checking. # NAME is "CC", "CXX", "GCJ", or "OBJC". # We try a few techniques and use that to set a single cache variable. # # We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was # modified to invoke _AM_DEPENDENCIES(CC); we would have a circular # dependency, and given that the user is not expected to run this macro, # just rely on AC_PROG_CC. AC_DEFUN([_AM_DEPENDENCIES], [AC_REQUIRE([AM_SET_DEPDIR])dnl AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl AC_REQUIRE([AM_MAKE_INCLUDE])dnl AC_REQUIRE([AM_DEP_TRACK])dnl ifelse([$1], CC, [depcc="$CC" am_compiler_list=], [$1], CXX, [depcc="$CXX" am_compiler_list=], [$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'], [$1], GCJ, [depcc="$GCJ" am_compiler_list='gcc3 gcc'], [depcc="$$1" am_compiler_list=]) AC_CACHE_CHECK([dependency style of $depcc], [am_cv_$1_dependencies_compiler_type], [if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named `D' -- because `-MD' means `put the output # in D'. mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_$1_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` fi for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with # Solaris 8's {/usr,}/bin/sh. touch sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf case $depmode in nosideeffect) # after this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; none) break ;; esac # We check with `-c' and `-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle `-M -o', and we need to detect this. if depmode=$depmode \ source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_$1_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_$1_dependencies_compiler_type=none fi ]) AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) AM_CONDITIONAL([am__fastdep$1], [ test "x$enable_dependency_tracking" != xno \ && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) ]) # AM_SET_DEPDIR # ------------- # Choose a directory name for dependency files. # This macro is AC_REQUIREd in _AM_DEPENDENCIES AC_DEFUN([AM_SET_DEPDIR], [AC_REQUIRE([AM_SET_LEADING_DOT])dnl AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl ]) # AM_DEP_TRACK # ------------ AC_DEFUN([AM_DEP_TRACK], [AC_ARG_ENABLE(dependency-tracking, [ --disable-dependency-tracking speeds up one-time build --enable-dependency-tracking do not reject slow dependency extractors]) if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' fi AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) AC_SUBST([AMDEPBACKSLASH]) ]) # Generate code to set up dependency tracking. -*- Autoconf -*- # Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005 # Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. #serial 3 # _AM_OUTPUT_DEPENDENCY_COMMANDS # ------------------------------ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], [for mf in $CONFIG_FILES; do # Strip MF so we end up with the name of the file. mf=`echo "$mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile or not. # We used to match only the files named `Makefile.in', but # some people rename them; so instead we look at the file content. # Grep'ing the first line is not enough: some people post-process # each Makefile.in and add a new line on top of each file to say so. # So let's grep whole file. if grep '^#.*generated by automake' $mf > /dev/null 2>&1; then dirpart=`AS_DIRNAME("$mf")` else continue fi # Extract the definition of DEPDIR, am__include, and am__quote # from the Makefile without running `make'. DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` test -z "$DEPDIR" && continue am__include=`sed -n 's/^am__include = //p' < "$mf"` test -z "am__include" && continue am__quote=`sed -n 's/^am__quote = //p' < "$mf"` # When using ansi2knr, U may be empty or an underscore; expand it U=`sed -n 's/^U = //p' < "$mf"` # Find all dependency output files, they are included files with # $(DEPDIR) in their names. We invoke sed twice because it is the # simplest approach to changing $(DEPDIR) to its actual value in the # expansion. for file in `sed -n " s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do # Make sure the directory exists. test -f "$dirpart/$file" && continue fdir=`AS_DIRNAME(["$file"])` AS_MKDIR_P([$dirpart/$fdir]) # echo "creating $dirpart/$file" echo '# dummy' > "$dirpart/$file" done done ])# _AM_OUTPUT_DEPENDENCY_COMMANDS # AM_OUTPUT_DEPENDENCY_COMMANDS # ----------------------------- # This macro should only be invoked once -- use via AC_REQUIRE. # # This code is only required when automatic dependency tracking # is enabled. FIXME. This creates each `.P' file that we will # need in order to bootstrap the dependency handling code. AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], [AC_CONFIG_COMMANDS([depfiles], [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) ]) # Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005 # Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 8 # AM_CONFIG_HEADER is obsolete. It has been replaced by AC_CONFIG_HEADERS. AU_DEFUN([AM_CONFIG_HEADER], [AC_CONFIG_HEADERS($@)]) # Do all the work for Automake. -*- Autoconf -*- # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 # Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 12 # This macro actually does too much. Some checks are only needed if # your package does certain things. But this isn't really a big deal. # AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) # AM_INIT_AUTOMAKE([OPTIONS]) # ----------------------------------------------- # The call with PACKAGE and VERSION arguments is the old style # call (pre autoconf-2.50), which is being phased out. PACKAGE # and VERSION should now be passed to AC_INIT and removed from # the call to AM_INIT_AUTOMAKE. # We support both call styles for the transition. After # the next Automake release, Autoconf can make the AC_INIT # arguments mandatory, and then we can depend on a new Autoconf # release and drop the old call support. AC_DEFUN([AM_INIT_AUTOMAKE], [AC_PREREQ([2.58])dnl dnl Autoconf wants to disallow AM_ names. We explicitly allow dnl the ones we care about. m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl AC_REQUIRE([AC_PROG_INSTALL])dnl # test to see if srcdir already configured if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi AC_SUBST([CYGPATH_W]) # Define the identity of the package. dnl Distinguish between old-style and new-style calls. m4_ifval([$2], [m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl AC_SUBST([PACKAGE], [$1])dnl AC_SUBST([VERSION], [$2])], [_AM_SET_OPTIONS([$1])dnl AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl _AM_IF_OPTION([no-define],, [AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package]) AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])dnl # Some tools Automake needs. AC_REQUIRE([AM_SANITY_CHECK])dnl AC_REQUIRE([AC_ARG_PROGRAM])dnl AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version}) AM_MISSING_PROG(AUTOCONF, autoconf) AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version}) AM_MISSING_PROG(AUTOHEADER, autoheader) AM_MISSING_PROG(MAKEINFO, makeinfo) AM_PROG_INSTALL_SH AM_PROG_INSTALL_STRIP AC_REQUIRE([AM_PROG_MKDIR_P])dnl # We need awk for the "check" target. The system "awk" is bad on # some platforms. AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([AC_PROG_MAKE_SET])dnl AC_REQUIRE([AM_SET_LEADING_DOT])dnl _AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], [_AM_PROG_TAR([v7])])]) _AM_IF_OPTION([no-dependencies],, [AC_PROVIDE_IFELSE([AC_PROG_CC], [_AM_DEPENDENCIES(CC)], [define([AC_PROG_CC], defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl AC_PROVIDE_IFELSE([AC_PROG_CXX], [_AM_DEPENDENCIES(CXX)], [define([AC_PROG_CXX], defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl ]) ]) # When config.status generates a header, we must update the stamp-h file. # This file resides in the same directory as the config header # that is generated. The stamp files are numbered to have different names. # Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the # loop where config.status creates the headers, so we can generate # our stamp files there. AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], [# Compute $1's index in $config_headers. _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $1 | $1:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $1" >`AS_DIRNAME([$1])`/stamp-h[]$_am_stamp_count]) # Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_INSTALL_SH # ------------------ # Define $install_sh. AC_DEFUN([AM_PROG_INSTALL_SH], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl install_sh=${install_sh-"$am_aux_dir/install-sh"} AC_SUBST(install_sh)]) # Copyright (C) 2003, 2005 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 2 # Check whether the underlying file-system supports filenames # with a leading dot. For instance MS-DOS doesn't. AC_DEFUN([AM_SET_LEADING_DOT], [rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null AC_SUBST([am__leading_dot])]) # Add --enable-maintainer-mode option to configure. -*- Autoconf -*- # From Jim Meyering # Copyright (C) 1996, 1998, 2000, 2001, 2002, 2003, 2004, 2005 # Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 4 AC_DEFUN([AM_MAINTAINER_MODE], [AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles]) dnl maintainer-mode is disabled by default AC_ARG_ENABLE(maintainer-mode, [ --enable-maintainer-mode enable make rules and dependencies not useful (and sometimes confusing) to the casual installer], USE_MAINTAINER_MODE=$enableval, USE_MAINTAINER_MODE=no) AC_MSG_RESULT([$USE_MAINTAINER_MODE]) AM_CONDITIONAL(MAINTAINER_MODE, [test $USE_MAINTAINER_MODE = yes]) MAINT=$MAINTAINER_MODE_TRUE AC_SUBST(MAINT)dnl ] ) AU_DEFUN([jm_MAINTAINER_MODE], [AM_MAINTAINER_MODE]) # Check to see how 'make' treats includes. -*- Autoconf -*- # Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 3 # AM_MAKE_INCLUDE() # ----------------- # Check to see how make treats includes. AC_DEFUN([AM_MAKE_INCLUDE], [am_make=${MAKE-make} cat > confinc << 'END' am__doit: @echo done .PHONY: am__doit END # If we don't find an include directive, just comment out the code. AC_MSG_CHECKING([for style of include used by $am_make]) am__include="#" am__quote= _am_result=none # First try GNU make style include. echo "include confinc" > confmf # We grep out `Entering directory' and `Leaving directory' # messages which can occur if `w' ends up in MAKEFLAGS. # In particular we don't look at `^make:' because GNU make might # be invoked under some other name (usually "gmake"), in which # case it prints its new name instead of `make'. if test "`$am_make -s -f confmf 2> /dev/null | grep -v 'ing directory'`" = "done"; then am__include=include am__quote= _am_result=GNU fi # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then am__include=.include am__quote="\"" _am_result=BSD fi fi AC_SUBST([am__include]) AC_SUBST([am__quote]) AC_MSG_RESULT([$_am_result]) rm -f confinc confmf ]) # Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- # Copyright (C) 1997, 1999, 2000, 2001, 2003, 2005 # Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 4 # AM_MISSING_PROG(NAME, PROGRAM) # ------------------------------ AC_DEFUN([AM_MISSING_PROG], [AC_REQUIRE([AM_MISSING_HAS_RUN]) $1=${$1-"${am_missing_run}$2"} AC_SUBST($1)]) # AM_MISSING_HAS_RUN # ------------------ # Define MISSING if not defined so far and test if it supports --run. # If it does, set am_missing_run to use it, otherwise, to nothing. AC_DEFUN([AM_MISSING_HAS_RUN], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing" # Use eval to expand $SHELL if eval "$MISSING --run true"; then am_missing_run="$MISSING --run " else am_missing_run= AC_MSG_WARN([`missing' script is too old or missing]) fi ]) # Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_MKDIR_P # --------------- # Check whether `mkdir -p' is supported, fallback to mkinstalldirs otherwise. # # Automake 1.8 used `mkdir -m 0755 -p --' to ensure that directories # created by `make install' are always world readable, even if the # installer happens to have an overly restrictive umask (e.g. 077). # This was a mistake. There are at least two reasons why we must not # use `-m 0755': # - it causes special bits like SGID to be ignored, # - it may be too restrictive (some setups expect 775 directories). # # Do not use -m 0755 and let people choose whatever they expect by # setting umask. # # We cannot accept any implementation of `mkdir' that recognizes `-p'. # Some implementations (such as Solaris 8's) are not thread-safe: if a # parallel make tries to run `mkdir -p a/b' and `mkdir -p a/c' # concurrently, both version can detect that a/ is missing, but only # one can create it and the other will error out. Consequently we # restrict ourselves to GNU make (using the --version option ensures # this.) AC_DEFUN([AM_PROG_MKDIR_P], [if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then # We used to keeping the `.' as first argument, in order to # allow $(mkdir_p) to be used without argument. As in # $(mkdir_p) $(somedir) # where $(somedir) is conditionally defined. However this is wrong # for two reasons: # 1. if the package is installed by a user who cannot write `.' # make install will fail, # 2. the above comment should most certainly read # $(mkdir_p) $(DESTDIR)$(somedir) # so it does not work when $(somedir) is undefined and # $(DESTDIR) is not. # To support the latter case, we have to write # test -z "$(somedir)" || $(mkdir_p) $(DESTDIR)$(somedir), # so the `.' trick is pointless. mkdir_p='mkdir -p --' else # On NextStep and OpenStep, the `mkdir' command does not # recognize any option. It will interpret all options as # directories to create, and then abort because `.' already # exists. for d in ./-p ./--version; do test -d $d && rmdir $d done # $(mkinstalldirs) is defined by Automake if mkinstalldirs exists. if test -f "$ac_aux_dir/mkinstalldirs"; then mkdir_p='$(mkinstalldirs)' else mkdir_p='$(install_sh) -d' fi fi AC_SUBST([mkdir_p])]) # Helper functions for option handling. -*- Autoconf -*- # Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 3 # _AM_MANGLE_OPTION(NAME) # ----------------------- AC_DEFUN([_AM_MANGLE_OPTION], [[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) # _AM_SET_OPTION(NAME) # ------------------------------ # Set option NAME. Presently that only means defining a flag for this option. AC_DEFUN([_AM_SET_OPTION], [m4_define(_AM_MANGLE_OPTION([$1]), 1)]) # _AM_SET_OPTIONS(OPTIONS) # ---------------------------------- # OPTIONS is a space-separated list of Automake options. AC_DEFUN([_AM_SET_OPTIONS], [AC_FOREACH([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) # _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) # ------------------------------------------- # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. AC_DEFUN([_AM_IF_OPTION], [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) # Check to make sure that the build environment is sane. -*- Autoconf -*- # Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005 # Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 4 # AM_SANITY_CHECK # --------------- AC_DEFUN([AM_SANITY_CHECK], [AC_MSG_CHECKING([whether build environment is sane]) # Just in case sleep 1 echo timestamp > conftest.file # Do `set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null` if test "$[*]" = "X"; then # -L didn't work. set X `ls -t $srcdir/configure conftest.file` fi rm -f conftest.file if test "$[*]" != "X $srcdir/configure conftest.file" \ && test "$[*]" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken alias in your environment]) fi test "$[2]" = conftest.file ) then # Ok. : else AC_MSG_ERROR([newly created file is older than distributed files! Check your system clock]) fi AC_MSG_RESULT(yes)]) # Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_INSTALL_STRIP # --------------------- # One issue with vendor `install' (even GNU) is that you can't # specify the program used to strip binaries. This is especially # annoying in cross-compiling environments, where the build's strip # is unlikely to handle the host's binaries. # Fortunately install-sh will honor a STRIPPROG variable, so we # always use install-sh in `make install-strip', and initialize # STRIPPROG with the value of the STRIP variable (set by the user). AC_DEFUN([AM_PROG_INSTALL_STRIP], [AC_REQUIRE([AM_PROG_INSTALL_SH])dnl # Installed binaries are usually stripped using `strip' when the user # run `make install-strip'. However `strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the `STRIP' environment variable to overrule this program. dnl Don't test for $cross_compiling = yes, because it might be `maybe'. if test "$cross_compiling" != no; then AC_CHECK_TOOL([STRIP], [strip], :) fi INSTALL_STRIP_PROGRAM="\${SHELL} \$(install_sh) -c -s" AC_SUBST([INSTALL_STRIP_PROGRAM])]) # Check how to create a tarball. -*- Autoconf -*- # Copyright (C) 2004, 2005 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 2 # _AM_PROG_TAR(FORMAT) # -------------------- # Check how to create a tarball in format FORMAT. # FORMAT should be one of `v7', `ustar', or `pax'. # # Substitute a variable $(am__tar) that is a command # writing to stdout a FORMAT-tarball containing the directory # $tardir. # tardir=directory && $(am__tar) > result.tar # # Substitute a variable $(am__untar) that extract such # a tarball read from stdin. # $(am__untar) < result.tar AC_DEFUN([_AM_PROG_TAR], [# Always define AMTAR for backward compatibility. AM_MISSING_PROG([AMTAR], [tar]) m4_if([$1], [v7], [am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'], [m4_case([$1], [ustar],, [pax],, [m4_fatal([Unknown tar format])]) AC_MSG_CHECKING([how to create a $1 tar archive]) # Loop over all known methods to create a tar archive until one works. _am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' _am_tools=${am_cv_prog_tar_$1-$_am_tools} # Do not fold the above two line into one, because Tru64 sh and # Solaris sh will not grok spaces in the rhs of `-'. for _am_tool in $_am_tools do case $_am_tool in gnutar) for _am_tar in tar gnutar gtar; do AM_RUN_LOG([$_am_tar --version]) && break done am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' am__untar="$_am_tar -xf -" ;; plaintar) # Must skip GNU tar: if it does not support --format= it doesn't create # ustar tarball either. (tar --version) >/dev/null 2>&1 && continue am__tar='tar chf - "$$tardir"' am__tar_='tar chf - "$tardir"' am__untar='tar xf -' ;; pax) am__tar='pax -L -x $1 -w "$$tardir"' am__tar_='pax -L -x $1 -w "$tardir"' am__untar='pax -r' ;; cpio) am__tar='find "$$tardir" -print | cpio -o -H $1 -L' am__tar_='find "$tardir" -print | cpio -o -H $1 -L' am__untar='cpio -i -H $1 -d' ;; none) am__tar=false am__tar_=false am__untar=false ;; esac # If the value was cached, stop now. We just wanted to have am__tar # and am__untar set. test -n "${am_cv_prog_tar_$1}" && break # tar/untar a dummy directory, and stop if the command works rm -rf conftest.dir mkdir conftest.dir echo GrepMe > conftest.dir/file AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) rm -rf conftest.dir if test -s conftest.tar; then AM_RUN_LOG([$am__untar /dev/null 2>&1 && break fi done rm -rf conftest.dir AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) AC_MSG_RESULT([$am_cv_prog_tar_$1])]) AC_SUBST([am__tar]) AC_SUBST([am__untar]) ]) # _AM_PROG_TAR m4_include([autoconf/hercules.m4]) m4_include([autoconf/libtool.m4]) m4_include([autoconf/ltdl.m4]) m4_include([m4/gettext.m4]) m4_include([m4/iconv.m4]) m4_include([m4/lib-ld.m4]) m4_include([m4/lib-link.m4]) m4_include([m4/lib-prefix.m4]) m4_include([m4/nls.m4]) m4_include([m4/po.m4]) m4_include([m4/progtest.m4]) hercules-3.07/assist.c000644 000765 000765 00000057642 11157241226 016434 0ustar00jmaynardjmaynard000000 000000 /* ASSIST.C (c) Copyright Roger Bowler, 1999-2009 */ /* ESA/390 MVS Assist Routines */ // $Id: assist.c 5234 2009-03-03 19:32:50Z jj $ /*-------------------------------------------------------------------*/ /* This module contains routines which process the MVS Assist */ /* instructions described in the manual GA22-7079-01. */ /*-------------------------------------------------------------------*/ /* Instruction decode rework - Jan Jaeger */ /* Correct address wraparound - Jan Jaeger */ /* z/Architecture support - (c) Copyright Jan Jaeger, 1999-2009 */ /* Add dummy assist instruction - Jay Maynard, */ /* suggested by Brandon Hill */ // $Log$ // Revision 1.24 2007/06/23 00:04:03 ivan // Update copyright notices to include current year (2007) // // Revision 1.23 2006/12/20 04:26:19 gsmith // 19 Dec 2006 ip_all.pat - performance patch - Greg Smith // // Revision 1.22 2006/12/08 09:43:16 jj // Add CVS message log // #include "hstdinc.h" #if !defined(_HENGINE_DLL_) #define _HENGINE_DLL_ #endif #if !defined(_ASSIST_C_) #define _ASSIST_C_ #endif #include "hercules.h" #include "opcode.h" #include "inline.h" #if !defined(_ASSIST_C) #define _ASSIST_C /*-------------------------------------------------------------------*/ /* Control block offsets fixed by architecture */ /*-------------------------------------------------------------------*/ /* Prefixed storage area offsets */ #define PSALCPUA 0x2F4 /* Logical CPU address */ #define PSAHLHI 0x2F8 /* Locks held indicators */ /* Bit settings for PSAHLHI */ #define PSACMSLI 0x00000002 /* CMS lock held indicator */ #define PSALCLLI 0x00000001 /* Local lock held indicator */ /* Address space control block offsets */ #define ASCBLOCK 0x080 /* Local lock */ #define ASCBLSWQ 0x084 /* Local lock suspend queue */ /* Lock interface table offsets */ #define LITOLOC (-16) /* Obtain local error exit */ #define LITRLOC (-12) /* Release local error exit */ #define LITOCMS (-8) /* Obtain CMS error exit */ #define LITRCMS (-4) /* Release CMS error exit */ #endif /*!defined(_ASSIST_C)*/ #if !defined(FEATURE_S390_DAT) && !defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* E502 - Page Fix [SSE] */ /*-------------------------------------------------------------------*/ DEF_INST(fix_page) { int b1, b2; /* Values of base field */ VADR effective_addr1, effective_addr2; /* Effective addresses */ SSE(inst, regs, b1, effective_addr1, b2, effective_addr2); PRIV_CHECK(regs); PTT(PTT_CL_ERR,"*E502 PGFIX",effective_addr1,effective_addr2,regs->psw.IA_L); /*INCOMPLETE*/ } #endif /*!defined(FEATURE_S390_DAT) && !defined(FEATURE_ESAME)*/ /*-------------------------------------------------------------------*/ /* E503 - SVC assist [SSE] */ /*-------------------------------------------------------------------*/ DEF_INST(svc_assist) { int b1, b2; /* Values of base field */ VADR effective_addr1, effective_addr2; /* Effective addresses */ SSE(inst, regs, b1, effective_addr1, b2, effective_addr2); PRIV_CHECK(regs); PTT(PTT_CL_ERR,"*E503 SVCA",effective_addr1,effective_addr2,regs->psw.IA_L); /*INCOMPLETE: NO ACTION IS TAKEN, THE SVC IS UNASSISTED AND MVS WILL HAVE TO HANDLE THE SITUATION*/ } /*-------------------------------------------------------------------*/ /* E504 - Obtain Local Lock [SSE] */ /*-------------------------------------------------------------------*/ DEF_INST(obtain_local_lock) { int b1, b2; /* Values of base field */ VADR effective_addr1, effective_addr2; /* Effective addresses */ VADR ascb_addr; /* Virtual address of ASCB */ VADR lock_addr; /* Virtual addr of ASCBLOCK */ U32 hlhi_word; /* Highest lock held word */ VADR lit_addr; /* Virtual address of lock interface table */ U32 lock; /* Lock value */ U32 lcpa; /* Logical CPU address */ VADR newia; /* Unsuccessful branch addr */ int acc_mode = 0; /* access mode to use */ SSE(inst, regs, b1, effective_addr1, b2, effective_addr2); PRIV_CHECK(regs); /* Specification exception if operands are not on word boundary */ if ((effective_addr1 & 0x00000003) || (effective_addr2 & 0x00000003)) ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION); PERFORM_SERIALIZATION(regs); /* Obtain main-storage access lock */ OBTAIN_MAINLOCK(regs); if (ACCESS_REGISTER_MODE(®s->psw)) acc_mode = USE_PRIMARY_SPACE; /* Load ASCB address from first operand location */ ascb_addr = ARCH_DEP(vfetch4) ( effective_addr1, acc_mode, regs ); /* Load locks held bits from second operand location */ hlhi_word = ARCH_DEP(vfetch4) ( effective_addr2, acc_mode, regs ); /* Fetch our logical CPU address from PSALCPUA */ lcpa = ARCH_DEP(vfetch4) ( effective_addr2 - 4, acc_mode, regs ); lock_addr = (ascb_addr + ASCBLOCK) & ADDRESS_MAXWRAP(regs); /* Fetch the local lock from the ASCB */ lock = ARCH_DEP(vfetch4) ( lock_addr, acc_mode, regs ); /* Obtain the local lock if not already held by any CPU */ if (lock == 0 && (hlhi_word & PSALCLLI) == 0) { /* Store the unchanged value into the second operand to ensure suppression in the event of an access exception */ ARCH_DEP(vstore4) ( hlhi_word, effective_addr2, acc_mode, regs ); /* Store our logical CPU address in ASCBLOCK */ ARCH_DEP(vstore4) ( lcpa, lock_addr, acc_mode, regs ); /* Set the local lock held bit in the second operand */ hlhi_word |= PSALCLLI; ARCH_DEP(vstore4) ( hlhi_word, effective_addr2, acc_mode, regs ); /* Set register 13 to zero to indicate lock obtained */ regs->GR_L(13) = 0; } else { /* Fetch the lock interface table address from the second word of the second operand, and load the new instruction address and amode from LITOLOC */ lit_addr = ARCH_DEP(vfetch4) ( effective_addr2 + 4, acc_mode, regs ) + LITOLOC; lit_addr &= ADDRESS_MAXWRAP(regs); newia = ARCH_DEP(vfetch4) ( lit_addr, acc_mode, regs ); /* Save the link information in register 12 */ regs->GR_L(12) = PSW_IA(regs, 0); /* Copy LITOLOC into register 13 to signify obtain failure */ regs->GR_L(13) = newia; /* Update the PSW instruction address */ UPD_PSW_IA(regs, newia); } /* Release main-storage access lock */ RELEASE_MAINLOCK(regs); PERFORM_SERIALIZATION(regs); } /* end function obtain_local_lock */ /*-------------------------------------------------------------------*/ /* E505 - Release Local Lock [SSE] */ /*-------------------------------------------------------------------*/ DEF_INST(release_local_lock) { int b1, b2; /* Values of base field */ VADR effective_addr1, effective_addr2; /* Effective addresses */ VADR ascb_addr; /* Virtual address of ASCB */ VADR lock_addr; /* Virtual addr of ASCBLOCK */ VADR susp_addr; /* Virtual addr of ASCBLSWQ */ U32 hlhi_word; /* Highest lock held word */ VADR lit_addr; /* Virtual address of lock interface table */ U32 lock; /* Lock value */ U32 susp; /* Lock suspend queue */ U32 lcpa; /* Logical CPU address */ VADR newia; /* Unsuccessful branch addr */ int acc_mode = 0; /* access mode to use */ SSE(inst, regs, b1, effective_addr1, b2, effective_addr2); PRIV_CHECK(regs); /* Specification exception if operands are not on word boundary */ if ((effective_addr1 & 0x00000003) || (effective_addr2 & 0x00000003)) ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION); /* Obtain main-storage access lock */ OBTAIN_MAINLOCK(regs); if (ACCESS_REGISTER_MODE(®s->psw)) acc_mode = USE_PRIMARY_SPACE; /* Load ASCB address from first operand location */ ascb_addr = ARCH_DEP(vfetch4) ( effective_addr1, acc_mode, regs ); /* Load locks held bits from second operand location */ hlhi_word = ARCH_DEP(vfetch4) ( effective_addr2, acc_mode, regs ); /* Fetch our logical CPU address from PSALCPUA */ lcpa = ARCH_DEP(vfetch4) ( effective_addr2 - 4, acc_mode, regs ); /* Fetch the local lock and the suspend queue from the ASCB */ lock_addr = (ascb_addr + ASCBLOCK) & ADDRESS_MAXWRAP(regs); susp_addr = (ascb_addr + ASCBLSWQ) & ADDRESS_MAXWRAP(regs); lock = ARCH_DEP(vfetch4) ( lock_addr, acc_mode, regs ); susp = ARCH_DEP(vfetch4) ( susp_addr, acc_mode, regs ); /* Test if this CPU holds the local lock, and does not hold any CMS lock, and the local lock suspend queue is empty */ if (lock == lcpa && (hlhi_word & (PSALCLLI | PSACMSLI)) == PSALCLLI && susp == 0) { /* Store the unchanged value into the second operand to ensure suppression in the event of an access exception */ ARCH_DEP(vstore4) ( hlhi_word, effective_addr2, acc_mode, regs ); /* Set the local lock to zero */ ARCH_DEP(vstore4) ( 0, lock_addr, acc_mode, regs ); /* Clear the local lock held bit in the second operand */ hlhi_word &= ~PSALCLLI; ARCH_DEP(vstore4) ( hlhi_word, effective_addr2, acc_mode, regs ); /* Set register 13 to zero to indicate lock released */ regs->GR_L(13) = 0; } else { /* Fetch the lock interface table address from the second word of the second operand, and load the new instruction address and amode from LITRLOC */ lit_addr = ARCH_DEP(vfetch4) ( effective_addr2 + 4, acc_mode, regs ) + LITRLOC; lit_addr &= ADDRESS_MAXWRAP(regs); newia = ARCH_DEP(vfetch4) ( lit_addr, acc_mode, regs ); /* Save the link information in register 12 */ regs->GR_L(12) = PSW_IA(regs, 0); /* Copy LITRLOC into register 13 to signify release failure */ regs->GR_L(13) = newia; /* Update the PSW instruction address */ UPD_PSW_IA(regs, newia); } /* Release main-storage access lock */ RELEASE_MAINLOCK(regs); } /* end function release_local_lock */ /*-------------------------------------------------------------------*/ /* E506 - Obtain CMS Lock [SSE] */ /*-------------------------------------------------------------------*/ DEF_INST(obtain_cms_lock) { int b1, b2; /* Values of base field */ VADR effective_addr1, effective_addr2; /* Effective addresses */ VADR ascb_addr; /* Virtual address of ASCB */ U32 hlhi_word; /* Highest lock held word */ VADR lit_addr; /* Virtual address of lock interface table */ VADR lock_addr; /* Lock address */ int lock_arn; /* Lock access register */ U32 lock; /* Lock value */ VADR newia; /* Unsuccessful branch addr */ int acc_mode = 0; /* access mode to use */ SSE(inst, regs, b1, effective_addr1, b2, effective_addr2); PRIV_CHECK(regs); /* Specification exception if operands are not on word boundary */ if ((effective_addr1 & 0x00000003) || (effective_addr2 & 0x00000003)) ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION); PERFORM_SERIALIZATION(regs); /* General register 11 contains the lock address */ lock_addr = regs->GR_L(11) & ADDRESS_MAXWRAP(regs); lock_arn = 11; /* Obtain main-storage access lock */ OBTAIN_MAINLOCK(regs); if (ACCESS_REGISTER_MODE(®s->psw)) acc_mode = USE_PRIMARY_SPACE; /* Load ASCB address from first operand location */ ascb_addr = ARCH_DEP(vfetch4) ( effective_addr1, acc_mode, regs ); /* Load locks held bits from second operand location */ hlhi_word = ARCH_DEP(vfetch4) ( effective_addr2, acc_mode, regs ); /* Fetch the lock addressed by general register 11 */ lock = ARCH_DEP(vfetch4) ( lock_addr, acc_mode, regs ); /* Obtain the lock if not held by any ASCB, and if this CPU holds the local lock and does not hold a CMS lock */ if (lock == 0 && (hlhi_word & (PSALCLLI | PSACMSLI)) == PSALCLLI) { /* Store the unchanged value into the second operand to ensure suppression in the event of an access exception */ ARCH_DEP(vstore4) ( hlhi_word, effective_addr2, acc_mode, regs ); /* Store the ASCB address in the CMS lock */ ARCH_DEP(vstore4) ( ascb_addr, lock_addr, acc_mode, regs ); /* Set the CMS lock held bit in the second operand */ hlhi_word |= PSACMSLI; ARCH_DEP(vstore4) ( hlhi_word, effective_addr2, acc_mode, regs ); /* Set register 13 to zero to indicate lock obtained */ regs->GR_L(13) = 0; } else { /* Fetch the lock interface table address from the second word of the second operand, and load the new instruction address and amode from LITOCMS */ lit_addr = ARCH_DEP(vfetch4) ( effective_addr2 + 4, acc_mode, regs ) + LITOCMS; lit_addr &= ADDRESS_MAXWRAP(regs); newia = ARCH_DEP(vfetch4) ( lit_addr, acc_mode, regs ); /* Save the link information in register 12 */ regs->GR_L(12) = PSW_IA(regs, 0); /* Copy LITOCMS into register 13 to signify obtain failure */ regs->GR_L(13) = newia; /* Update the PSW instruction address */ UPD_PSW_IA(regs, newia); } /* Release main-storage access lock */ RELEASE_MAINLOCK(regs); PERFORM_SERIALIZATION(regs); } /* end function obtain_cms_lock */ /*-------------------------------------------------------------------*/ /* E507 - Release CMS Lock [SSE] */ /*-------------------------------------------------------------------*/ DEF_INST(release_cms_lock) { int b1, b2; /* Values of base field */ VADR effective_addr1, effective_addr2; /* Effective addresses */ VADR ascb_addr; /* Virtual address of ASCB */ U32 hlhi_word; /* Highest lock held word */ VADR lit_addr; /* Virtual address of lock interface table */ VADR lock_addr; /* Lock address */ int lock_arn; /* Lock access register */ U32 lock; /* Lock value */ U32 susp; /* Lock suspend queue */ VADR newia; /* Unsuccessful branch addr */ int acc_mode = 0; /* access mode to use */ SSE(inst, regs, b1, effective_addr1, b2, effective_addr2); PRIV_CHECK(regs); /* Specification exception if operands are not on word boundary */ if ((effective_addr1 & 0x00000003) || (effective_addr2 & 0x00000003)) ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION); /* General register 11 contains the lock address */ lock_addr = regs->GR_L(11) & ADDRESS_MAXWRAP(regs); lock_arn = 11; /* Obtain main-storage access lock */ OBTAIN_MAINLOCK(regs); if (ACCESS_REGISTER_MODE(®s->psw)) acc_mode = USE_PRIMARY_SPACE; /* Load ASCB address from first operand location */ ascb_addr = ARCH_DEP(vfetch4) ( effective_addr1, acc_mode, regs ); /* Load locks held bits from second operand location */ hlhi_word = ARCH_DEP(vfetch4) ( effective_addr2, acc_mode, regs ); /* Fetch the CMS lock and the suspend queue word */ lock = ARCH_DEP(vfetch4) ( lock_addr, acc_mode, regs ); susp = ARCH_DEP(vfetch4) ( lock_addr + 4, acc_mode, regs ); /* Test if current ASCB holds this lock, the locks held indicators show a CMS lock is held, and the lock suspend queue is empty */ if (lock == ascb_addr && (hlhi_word & PSACMSLI) && susp == 0) { /* Store the unchanged value into the second operand to ensure suppression in the event of an access exception */ ARCH_DEP(vstore4) ( hlhi_word, effective_addr2, acc_mode, regs ); /* Set the CMS lock to zero */ ARCH_DEP(vstore4) ( 0, lock_addr, acc_mode, regs ); /* Clear the CMS lock held bit in the second operand */ hlhi_word &= ~PSACMSLI; ARCH_DEP(vstore4) ( hlhi_word, effective_addr2, acc_mode, regs ); /* Set register 13 to zero to indicate lock released */ regs->GR_L(13) = 0; } else { /* Fetch the lock interface table address from the second word of the second operand, and load the new instruction address and amode from LITRCMS */ lit_addr = ARCH_DEP(vfetch4) ( effective_addr2 + 4, acc_mode, regs ) + LITRCMS; lit_addr &= ADDRESS_MAXWRAP(regs); newia = ARCH_DEP(vfetch4) ( lit_addr, acc_mode, regs ); /* Save the link information in register 12 */ regs->GR_L(12) = PSW_IA(regs, 0); /* Copy LITRCMS into register 13 to signify release failure */ regs->GR_L(13) = newia; /* Update the PSW instruction address */ UPD_PSW_IA(regs, newia); } /* Release main-storage access lock */ RELEASE_MAINLOCK(regs); } /* end function release_cms_lock */ #if !defined(FEATURE_TRACING) /*-------------------------------------------------------------------*/ /* E508 - Trace SVC Interruption [SSE] */ /*-------------------------------------------------------------------*/ DEF_INST(trace_svc_interruption) { int b1, b2; /* Values of base field */ VADR effective_addr1, effective_addr2; /* Effective addresses */ SSE(inst, regs, b1, effective_addr1, b2, effective_addr2); PRIV_CHECK(regs); /* Specification exception if operands are not on word boundary */ if ((effective_addr1 & 0x00000003) || (effective_addr2 & 0x00000003)) ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION); PTT(PTT_CL_ERR,"*E508 TRSVC",effective_addr1,effective_addr2,regs->psw.IA_L); /*INCOMPLETE: NO TRACE ENTRY IS GENERATED*/ } /*-------------------------------------------------------------------*/ /* E509 - Trace Program Interruption [SSE] */ /*-------------------------------------------------------------------*/ DEF_INST(trace_program_interruption) { int b1, b2; /* Values of base field */ VADR effective_addr1, effective_addr2; /* Effective addresses */ SSE(inst, regs, b1, effective_addr1, b2, effective_addr2); PRIV_CHECK(regs); /* Specification exception if operands are not on word boundary */ if ((effective_addr1 & 0x00000003) || (effective_addr2 & 0x00000003)) ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION); PTT(PTT_CL_ERR,"*E509 TRPGM",effective_addr1,effective_addr2,regs->psw.IA_L); /*INCOMPLETE: NO TRACE ENTRY IS GENERATED*/ } /*-------------------------------------------------------------------*/ /* E50A - Trace Initial SRB Dispatch [SSE] */ /*-------------------------------------------------------------------*/ DEF_INST(trace_initial_srb_dispatch) { int b1, b2; /* Values of base field */ VADR effective_addr1, effective_addr2; /* Effective addresses */ SSE(inst, regs, b1, effective_addr1, b2, effective_addr2); PRIV_CHECK(regs); /* Specification exception if operands are not on word boundary */ if ((effective_addr1 & 0x00000003) || (effective_addr2 & 0x00000003)) ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION); PTT(PTT_CL_ERR,"*E50A TRSRB",effective_addr1,effective_addr2,regs->psw.IA_L); /*INCOMPLETE: NO TRACE ENTRY IS GENERATED*/ } /*-------------------------------------------------------------------*/ /* E50B - Trace I/O Interruption [SSE] */ /*-------------------------------------------------------------------*/ DEF_INST(trace_io_interruption) { int b1, b2; /* Values of base field */ VADR effective_addr1, effective_addr2; /* Effective addresses */ SSE(inst, regs, b1, effective_addr1, b2, effective_addr2); PRIV_CHECK(regs); /* Specification exception if operands are not on word boundary */ if ((effective_addr1 & 0x00000003) || (effective_addr2 & 0x00000003)) ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION); PTT(PTT_CL_ERR,"*E50B TRIO",effective_addr1,effective_addr2,regs->psw.IA_L); /*INCOMPLETE: NO TRACE ENTRY IS GENERATED*/ } /*-------------------------------------------------------------------*/ /* E50C - Trace Task Dispatch [SSE] */ /*-------------------------------------------------------------------*/ DEF_INST(trace_task_dispatch) { int b1, b2; /* Values of base field */ VADR effective_addr1, effective_addr2; /* Effective addresses */ SSE(inst, regs, b1, effective_addr1, b2, effective_addr2); PRIV_CHECK(regs); /* Specification exception if operands are not on word boundary */ if ((effective_addr1 & 0x00000003) || (effective_addr2 & 0x00000003)) ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION); PTT(PTT_CL_ERR,"*E50C TRTSK",effective_addr1,effective_addr2,regs->psw.IA_L); /*INCOMPLETE: NO TRACE ENTRY IS GENERATED*/ } /*-------------------------------------------------------------------*/ /* E50D - Trace SVC Return [SSE] */ /*-------------------------------------------------------------------*/ DEF_INST(trace_svc_return) { int b1, b2; /* Values of base field */ VADR effective_addr1, effective_addr2; /* Effective addresses */ SSE(inst, regs, b1, effective_addr1, b2, effective_addr2); PRIV_CHECK(regs); /* Specification exception if operands are not on word boundary */ if ((effective_addr1 & 0x00000003) || (effective_addr2 & 0x00000003)) ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION); PTT(PTT_CL_ERR,"*E50D TRRTN",effective_addr1,effective_addr2,regs->psw.IA_L); /*INCOMPLETE: NO TRACE ENTRY IS GENERATED*/ } #endif /*!defined(FEATURE_TRACING)*/ #if !defined(_GEN_ARCH) #if defined(_ARCHMODE2) #define _GEN_ARCH _ARCHMODE2 #include "assist.c" #endif #if defined(_ARCHMODE3) #undef _GEN_ARCH #define _GEN_ARCH _ARCHMODE3 #include "assist.c" #endif #endif /*!defined(_GEN_ARCH)*/ hercules-3.07/autoconf/000777 000765 000765 00000000000 11345533270 016570 5ustar00jmaynardjmaynard000000 000000 hercules-3.07/awstape.c000644 000765 000765 00000071556 11321734033 016566 0ustar00jmaynardjmaynard000000 000000 /* AWSTAPE.C (c) Copyright Roger Bowler, 1999-2009 */ /* Hercules Tape Device Handler for AWSTAPE */ /* Original Author: Roger Bowler */ /* Prime Maintainer: Ivan Warren */ /* Secondary Maintainer: "Fish" (David B. Trout) */ // $Id: awstape.c 5587 2009-12-31 15:05:57Z rbowler $ /*-------------------------------------------------------------------*/ /* This module contains the AWSTAPE emulated tape format support. */ /* */ /* The subroutines in this module are called by the general tape */ /* device handler (tapedev.c) when the tape format is AWSTAPE. */ /* */ /* Messages issued by this module are prefixed HHCTA1nn */ /*-------------------------------------------------------------------*/ #include "hstdinc.h" #include "hercules.h" /* need Hercules control blocks */ #include "tapedev.h" /* Main tape handler header file */ //#define ENABLE_TRACING_STMTS // (Fish: DEBUGGING) #ifdef ENABLE_TRACING_STMTS #if !defined(DEBUG) #warning DEBUG required for ENABLE_TRACING_STMTS #endif // (TRACE, ASSERT, and VERIFY macros are #defined in hmacros.h) #else #undef TRACE #undef ASSERT #undef VERIFY #define TRACE 1 ? ((void)0) : logmsg #define ASSERT(a) #define VERIFY(a) ((void)(a)) #endif /*********************************************************************/ /* START OF ORIGINAL AWS FUNCTIONS (ISW Additions) */ /*********************************************************************/ /*-------------------------------------------------------------------*/ /* Close an AWSTAPE format file */ /* New Function added by ISW for consistency with other medias */ /*-------------------------------------------------------------------*/ void close_awstape (DEVBLK *dev) { if(dev->fd>=0) { logmsg (_("HHCTA101I %4.4X: AWS Tape %s closed\n"), dev->devnum, dev->filename); close(dev->fd); } strcpy(dev->filename, TAPE_UNLOADED); dev->fd=-1; dev->blockid = 0; dev->fenced = 0; return; } /*-------------------------------------------------------------------*/ /* Rewinds an AWS Tape format file */ /* New Function added by ISW for consistency with other medias */ /*-------------------------------------------------------------------*/ int rewind_awstape (DEVBLK *dev,BYTE *unitstat,BYTE code) { off_t rcoff; rcoff=lseek(dev->fd,0,SEEK_SET); if(rcoff<0) { build_senseX(TAPE_BSENSE_REWINDFAILED,dev,unitstat,code); return -1; } dev->nxtblkpos=0; dev->prvblkpos=-1; dev->curfilen=1; dev->blockid=0; dev->fenced = 0; return 0; } /*-------------------------------------------------------------------*/ /* Determines if a tape has passed a virtual EOT marker */ /* New Function added by ISW for consistency with other medias */ /*-------------------------------------------------------------------*/ int passedeot_awstape (DEVBLK *dev) { if(dev->nxtblkpos==0) { dev->eotwarning = 0; return 0; } if(dev->tdparms.maxsize==0) { dev->eotwarning = 0; return 0; } if(dev->nxtblkpos+dev->eotmargin > dev->tdparms.maxsize) { dev->eotwarning = 1; return 1; } dev->eotwarning = 0; return 0; } /*********************************************************************/ /* START OF ORIGINAL RB AWS FUNCTIONS */ /*********************************************************************/ /*-------------------------------------------------------------------*/ /* Open an AWSTAPE format file */ /* */ /* If successful, the file descriptor is stored in the device block */ /* and the return value is zero. Otherwise the return value is -1. */ /*-------------------------------------------------------------------*/ int open_awstape (DEVBLK *dev, BYTE *unitstat,BYTE code) { int rc = -1; /* Return code */ char pathname[MAX_PATH]; /* file path in host format */ /* Check for no tape in drive */ if (!strcmp (dev->filename, TAPE_UNLOADED)) { build_senseX(TAPE_BSENSE_TAPEUNLOADED,dev,unitstat,code); return -1; } /* Open the AWSTAPE file */ hostpath(pathname, dev->filename, sizeof(pathname)); if(!dev->tdparms.logical_readonly) { rc = open (pathname, O_RDWR | O_BINARY); } /* If file is read-only, attempt to open again */ if (dev->tdparms.logical_readonly || (rc < 0 && (EROFS == errno || EACCES == errno))) { dev->readonly = 1; rc = open (pathname, O_RDONLY | O_BINARY); } /* Check for successful open */ if (rc < 0) { logmsg (_("HHCTA102E %4.4X: Error opening %s: %s\n"), dev->devnum, dev->filename, strerror(errno)); strcpy(dev->filename, TAPE_UNLOADED); build_senseX(TAPE_BSENSE_TAPELOADFAIL,dev,unitstat,code); return -1; } /* Store the file descriptor in the device block */ dev->fd = rc; rc=rewind_awstape(dev,unitstat,code); return rc; } /* end function open_awstape */ /*-------------------------------------------------------------------*/ /* Read an AWSTAPE block header */ /* */ /* If successful, return value is zero, and buffer contains header. */ /* If error, return value is -1 and unitstat is set to CE+DE+UC */ /*-------------------------------------------------------------------*/ int readhdr_awstape (DEVBLK *dev, off_t blkpos, AWSTAPE_BLKHDR *buf, BYTE *unitstat,BYTE code) { int rc; /* Return code */ off_t rcoff; /* Return code from lseek() */ /* Reposition file to the requested block header */ rcoff = lseek (dev->fd, blkpos, SEEK_SET); if (rcoff < 0) { /* Handle seek error condition */ logmsg (_("HHCTA103E %4.4X: Error seeking to offset "I64_FMTX" " "in file %s: %s\n"), dev->devnum, blkpos, dev->filename, strerror(errno)); /* Set unit check with equipment check */ build_senseX(TAPE_BSENSE_LOCATEERR,dev,unitstat,code); return -1; } /* Read the 6-byte block header */ rc = read (dev->fd, buf, sizeof(AWSTAPE_BLKHDR)); /* Handle read error condition */ if (rc < 0) { logmsg (_("HHCTA104E %4.4X: Error reading block header " "at offset "I64_FMTX" in file %s: %s\n"), dev->devnum, blkpos, dev->filename, strerror(errno)); /* Set unit check with equipment check */ build_senseX(TAPE_BSENSE_READFAIL,dev,unitstat,code); return -1; } /* Handle end of file (uninitialized tape) condition */ if (rc == 0) { logmsg (_("HHCTA105E %4.4X: End of file (end of tape) " "at offset "I64_FMTX" in file %s\n"), dev->devnum, blkpos, dev->filename); /* Set unit exception with tape indicate (end of tape) */ build_senseX(TAPE_BSENSE_EMPTYTAPE,dev,unitstat,code); return -1; } /* Handle end of file within block header */ if (rc < (int)sizeof(AWSTAPE_BLKHDR)) { logmsg (_("HHCTA106E %4.4X: Unexpected end of file in block header " "at offset "I64_FMTX" in file %s\n"), dev->devnum, blkpos, dev->filename); build_senseX(TAPE_BSENSE_BLOCKSHORT,dev,unitstat,code); return -1; } /* Successful return */ return 0; } /* end function readhdr_awstape */ /*-------------------------------------------------------------------*/ /* Read a block from an AWSTAPE format file */ /* */ /* The block may be formed of one or more block segments each */ /* preceded by an AWSTAPE block header. The ENDREC flag in the */ /* block header indicates the final segment of the block. */ /* */ /* If successful, return value is block length read. */ /* If a tapemark was read, the return value is zero, and the */ /* current file number in the device block is incremented. */ /* If error, return value is -1 and unitstat is set to CE+DE+UC */ /*-------------------------------------------------------------------*/ int read_awstape (DEVBLK *dev, BYTE *buf, BYTE *unitstat,BYTE code) { int rc; /* Return code */ AWSTAPE_BLKHDR awshdr; /* AWSTAPE block header */ off_t blkpos; /* Offset of block header */ int blklen = 0; /* Total length of block */ U16 seglen; /* Data length of segment */ /* Initialize current block position */ blkpos = dev->nxtblkpos; /* Read block segments until end of block */ do { /* Read the 6-byte block header */ rc = readhdr_awstape (dev, blkpos, &awshdr, unitstat,code); if (rc < 0) return -1; /* Extract the segment length from the block header */ seglen = ((U16)(awshdr.curblkl[1]) << 8) | awshdr.curblkl[0]; /* Calculate the offset of the next block segment */ blkpos += sizeof(awshdr) + seglen; /* Check that block length will not exceed buffer size */ if (blklen + seglen > MAX_BLKLEN) { logmsg (_("HHCTA107E %4.4X: Block length exceeds %d " "at offset "I64_FMTX" in file %s\n"), dev->devnum, (int)MAX_BLKLEN, blkpos, dev->filename); /* Set unit check with data check */ build_senseX(TAPE_BSENSE_READFAIL,dev,unitstat,code); return -1; } /* Check that tapemark blocksize is zero */ if ((awshdr.flags1 & AWSTAPE_FLAG1_TAPEMARK) && blklen + seglen > 0) { logmsg (_("HHCTA108E %4.4X: Invalid tapemark " "at offset "I64_FMTX" in file %s\n"), dev->devnum, blkpos, dev->filename); /* Set unit check with data check */ build_senseX(TAPE_BSENSE_READFAIL,dev,unitstat,code); return -1; } /* Exit loop if this is a tapemark */ if (awshdr.flags1 & AWSTAPE_FLAG1_TAPEMARK) break; /* Read data block segment from tape file */ rc = read (dev->fd, buf+blklen, seglen); /* Handle read error condition */ if (rc < 0) { logmsg (_("HHCTA109E %4.4X: Error reading data block " "at offset "I64_FMTX" in file %s: %s\n"), dev->devnum, blkpos, dev->filename, strerror(errno)); /* Set unit check with equipment check */ build_senseX(TAPE_BSENSE_READFAIL,dev,unitstat,code); return -1; } /* Handle end of file within data block */ if (rc < seglen) { logmsg (_("HHCTA110E %4.4X: Unexpected end of file in data block " "at offset "I64_FMTX" in file %s\n"), dev->devnum, blkpos, dev->filename); /* Set unit check with data check and partial record */ build_senseX(TAPE_BSENSE_BLOCKSHORT,dev,unitstat,code); return -1; } /* Accumulate the total block length */ blklen += seglen; } while ((awshdr.flags1 & AWSTAPE_FLAG1_ENDREC) == 0); /* Calculate the offsets of the next and previous blocks */ dev->prvblkpos = dev->nxtblkpos; dev->nxtblkpos = blkpos; /* Increment the block number */ dev->blockid++; /* Increment file number and return zero if tapemark was read */ if (blklen == 0) { dev->curfilen++; return 0; /* UX will be set by caller */ } /* Return block length */ return blklen; } /* end function read_awstape */ /*-------------------------------------------------------------------*/ /* Write a block to an AWSTAPE format file */ /* */ /* If successful, return value is zero. */ /* If error, return value is -1 and unitstat is set to CE+DE+UC */ /*-------------------------------------------------------------------*/ int write_awstape (DEVBLK *dev, BYTE *buf, U16 blklen, BYTE *unitstat,BYTE code) { int rc; /* Return code */ off_t rcoff; /* Return code from lseek() */ AWSTAPE_BLKHDR awshdr; /* AWSTAPE block header */ off_t blkpos; /* Offset of block header */ U16 prvblkl; /* Length of previous block */ /* Initialize current block position and previous block length */ blkpos = dev->nxtblkpos; prvblkl = 0; /* Determine previous block length if not at start of tape */ if (dev->nxtblkpos > 0) { /* Reread the previous block header */ rc = readhdr_awstape (dev, dev->prvblkpos, &awshdr, unitstat,code); if (rc < 0) return -1; /* Extract the block length from the block header */ prvblkl = ((U16)(awshdr.curblkl[1]) << 8) | awshdr.curblkl[0]; /* Recalculate the offset of the next block */ blkpos = dev->prvblkpos + sizeof(awshdr) + prvblkl; } /* Reposition file to the new block header */ rcoff = lseek (dev->fd, blkpos, SEEK_SET); if (rcoff < 0) { /* Handle seek error condition */ logmsg (_("HHCTA111E %4.4X: Error seeking to offset "I64_FMTX" " "in file %s: %s\n"), dev->devnum, blkpos, dev->filename, strerror(errno)); /* Set unit check with equipment check */ build_senseX(TAPE_BSENSE_LOCATEERR,dev,unitstat,code); return -1; } /* ISW: Determine if we are passed maxsize */ if(dev->tdparms.maxsize>0) { if((off_t)(dev->nxtblkpos+blklen+sizeof(awshdr)) > dev->tdparms.maxsize) { build_senseX(TAPE_BSENSE_ENDOFTAPE,dev,unitstat,code); return -1; } } /* ISW: End of virtual physical EOT determination */ /* Build the 6-byte block header */ awshdr.curblkl[0] = blklen & 0xFF; awshdr.curblkl[1] = (blklen >> 8) & 0xFF; awshdr.prvblkl[0] = prvblkl & 0xFF; awshdr.prvblkl[1] = (prvblkl >>8) & 0xFF; awshdr.flags1 = AWSTAPE_FLAG1_NEWREC | AWSTAPE_FLAG1_ENDREC; awshdr.flags2 = 0; /* Write the block header */ rc = write (dev->fd, &awshdr, sizeof(awshdr)); if (rc < (int)sizeof(awshdr)) { if(errno==ENOSPC) { /* Disk FULL */ build_senseX(TAPE_BSENSE_ENDOFTAPE,dev,unitstat,code); logmsg (_("HHCTA112E %4.4X: Media full condition reached " "at offset "I64_FMTX" in file %s\n"), dev->devnum, blkpos, dev->filename); return -1; } /* Handle write error condition */ logmsg (_("HHCTA113E %4.4X: Error writing block header " "at offset "I64_FMTX" in file %s: %s\n"), dev->devnum, blkpos, dev->filename, strerror(errno)); /* Set unit check with equipment check */ build_senseX(TAPE_BSENSE_WRITEFAIL,dev,unitstat,code); return -1; } /* Calculate the offsets of the next and previous blocks */ dev->nxtblkpos = blkpos + sizeof(awshdr) + blklen; dev->prvblkpos = blkpos; /* Write the data block */ rc = write (dev->fd, buf, blklen); if (rc < blklen) { if(errno==ENOSPC) { /* Disk FULL */ build_senseX(TAPE_BSENSE_ENDOFTAPE,dev,unitstat,code); logmsg (_("HHCTA114E %4.4X: Media full condition reached " "at offset "I64_FMTX" in file %s\n"), dev->devnum, blkpos, dev->filename); return -1; } /* Handle write error condition */ logmsg (_("HHCTA115E %4.4X: Error writing data block " "at offset "I64_FMTX" in file %s: %s\n"), dev->devnum, blkpos, dev->filename, strerror(errno)); /* Set unit check with equipment check */ build_senseX(TAPE_BSENSE_WRITEFAIL,dev,unitstat,code); return -1; } dev->blockid++; /* Set new physical EOF */ do rc = ftruncate( dev->fd, dev->nxtblkpos ); while (EINTR == rc); if (rc != 0) { /* Handle write error condition */ logmsg (_("HHCTA116E %4.4X: Error writing data block " "at offset "I64_FMTX" in file %s: %s\n"), dev->devnum, blkpos, dev->filename, strerror(errno)); /* Set unit check with equipment check */ build_senseX(TAPE_BSENSE_WRITEFAIL,dev,unitstat,code); return -1; } /* Return normal status */ return 0; } /* end function write_awstape */ /*-------------------------------------------------------------------*/ /* Write a tapemark to an AWSTAPE format file */ /* */ /* If successful, return value is zero. */ /* If error, return value is -1 and unitstat is set to CE+DE+UC */ /*-------------------------------------------------------------------*/ int write_awsmark (DEVBLK *dev, BYTE *unitstat,BYTE code) { int rc; /* Return code */ off_t rcoff; /* Return code from lseek() */ AWSTAPE_BLKHDR awshdr; /* AWSTAPE block header */ off_t blkpos; /* Offset of block header */ U16 prvblkl; /* Length of previous block */ /* Initialize current block position and previous block length */ blkpos = dev->nxtblkpos; prvblkl = 0; /* Determine previous block length if not at start of tape */ if (dev->nxtblkpos > 0) { /* Reread the previous block header */ rc = readhdr_awstape (dev, dev->prvblkpos, &awshdr, unitstat,code); if (rc < 0) return -1; /* Extract the block length from the block header */ prvblkl = ((U16)(awshdr.curblkl[1]) << 8) | awshdr.curblkl[0]; /* Recalculate the offset of the next block */ blkpos = dev->prvblkpos + sizeof(awshdr) + prvblkl; } /* Reposition file to the new block header */ rcoff = lseek (dev->fd, blkpos, SEEK_SET); if (rcoff < 0) { /* Handle seek error condition */ logmsg (_("HHCTA117E %4.4X: Error seeking to offset "I64_FMTX" " "in file %s: %s\n"), dev->devnum, blkpos, dev->filename, strerror(errno)); build_senseX(TAPE_BSENSE_LOCATEERR,dev,unitstat,code); return -1; } /* ISW: Determine if we are passed maxsize */ if(dev->tdparms.maxsize>0) { if((off_t)(dev->nxtblkpos+sizeof(awshdr)) > dev->tdparms.maxsize) { build_senseX(TAPE_BSENSE_ENDOFTAPE,dev,unitstat,code); return -1; } } /* ISW: End of virtual physical EOT determination */ /* Build the 6-byte block header */ awshdr.curblkl[0] = 0; awshdr.curblkl[1] = 0; awshdr.prvblkl[0] = prvblkl & 0xFF; awshdr.prvblkl[1] = (prvblkl >>8) & 0xFF; awshdr.flags1 = AWSTAPE_FLAG1_TAPEMARK; awshdr.flags2 = 0; /* Write the block header */ rc = write (dev->fd, &awshdr, sizeof(awshdr)); if (rc < (int)sizeof(awshdr)) { /* Handle write error condition */ logmsg (_("HHCTA118E %4.4X: Error writing block header " "at offset "I64_FMTX" in file %s: %s\n"), dev->devnum, blkpos, dev->filename, strerror(errno)); build_senseX(TAPE_BSENSE_WRITEFAIL,dev,unitstat,code); return -1; } dev->blockid++; /* Calculate the offsets of the next and previous blocks */ dev->nxtblkpos = blkpos + sizeof(awshdr); dev->prvblkpos = blkpos; /* Set new physical EOF */ do rc = ftruncate( dev->fd, dev->nxtblkpos ); while (EINTR == rc); if (rc != 0) { /* Handle write error condition */ logmsg (_("HHCTA119E Error writing tape mark " "at offset "I64_FMTX" in file %s: %s\n"), blkpos, dev->filename, strerror(errno)); /* Set unit check with equipment check */ build_senseX(TAPE_BSENSE_WRITEFAIL,dev,unitstat,code); return -1; } /* Return normal status */ return 0; } /* end function write_awsmark */ /*-------------------------------------------------------------------*/ /* Synchronize an AWSTAPE format file (i.e. flush buffers to disk) */ /* */ /* If successful, return value is zero. */ /* If error, return value is -1 and unitstat is set to CE+DE+UC */ /*-------------------------------------------------------------------*/ int sync_awstape (DEVBLK *dev, BYTE *unitstat,BYTE code) { /* Unit check if tape is write-protected */ if (dev->readonly) { build_senseX(TAPE_BSENSE_WRITEPROTECT,dev,unitstat,code); return -1; } /* Perform sync. Return error on failure. */ if (fdatasync( dev->fd ) < 0) { /* Log the error */ logmsg (_("HHCTA120E %4.4X: Sync error on file %s: %s\n"), dev->devnum, dev->filename, strerror(errno)); /* Set unit check with equipment check */ build_senseX(TAPE_BSENSE_WRITEFAIL,dev,unitstat,code); return -1; } /* Return normal status */ return 0; } /* end function sync_awstape */ /*-------------------------------------------------------------------*/ /* Forward space over next block of AWSTAPE format file */ /* */ /* If successful, return value is the length of the block skipped. */ /* If the block skipped was a tapemark, the return value is zero, */ /* and the current file number in the device block is incremented. */ /* If error, return value is -1 and unitstat is set to CE+DE+UC */ /*-------------------------------------------------------------------*/ int fsb_awstape (DEVBLK *dev, BYTE *unitstat,BYTE code) { int rc; /* Return code */ AWSTAPE_BLKHDR awshdr; /* AWSTAPE block header */ off_t blkpos; /* Offset of block header */ int blklen = 0; /* Total length of block */ U16 seglen; /* Data length of segment */ /* Initialize current block position */ blkpos = dev->nxtblkpos; /* Read block segments until end of block */ do { /* Read the 6-byte block header */ rc = readhdr_awstape (dev, blkpos, &awshdr, unitstat,code); if (rc < 0) return -1; /* Extract the block length from the block header */ seglen = ((U16)(awshdr.curblkl[1]) << 8) | awshdr.curblkl[0]; /* Calculate the offset of the next block segment */ blkpos += sizeof(awshdr) + seglen; /* Accumulate the total block length */ blklen += seglen; /* Exit loop if this is a tapemark */ if (awshdr.flags1 & AWSTAPE_FLAG1_TAPEMARK) break; } while ((awshdr.flags1 & AWSTAPE_FLAG1_ENDREC) == 0); /* Calculate the offsets of the next and previous blocks */ dev->prvblkpos = dev->nxtblkpos; dev->nxtblkpos = blkpos; /* Increment current file number if tapemark was skipped */ if (blklen == 0) dev->curfilen++; dev->blockid++; /* Return block length or zero if tapemark */ return blklen; } /* end function fsb_awstape */ /*-------------------------------------------------------------------*/ /* Backspace to previous block of AWSTAPE format file */ /* */ /* If successful, return value is the length of the block. */ /* If the block is a tapemark, the return value is zero, */ /* and the current file number in the device block is decremented. */ /* If error, return value is -1 and unitstat is set to CE+DE+UC */ /*-------------------------------------------------------------------*/ int bsb_awstape (DEVBLK *dev, BYTE *unitstat,BYTE code) { int rc; /* Return code */ AWSTAPE_BLKHDR awshdr; /* AWSTAPE block header */ U16 curblkl; /* Length of current block */ U16 prvblkl; /* Length of previous block */ off_t blkpos; /* Offset of block header */ /* Unit check if already at start of tape */ if (dev->nxtblkpos == 0) { build_senseX(TAPE_BSENSE_LOADPTERR,dev,unitstat,code); return -1; } /* Backspace to previous block position */ blkpos = dev->prvblkpos; /* Read the 6-byte block header */ rc = readhdr_awstape (dev, blkpos, &awshdr, unitstat,code); if (rc < 0) return -1; /* Extract the block lengths from the block header */ curblkl = ((U16)(awshdr.curblkl[1]) << 8) | awshdr.curblkl[0]; prvblkl = ((U16)(awshdr.prvblkl[1]) << 8) | awshdr.prvblkl[0]; /* Calculate the offset of the previous block */ dev->prvblkpos = blkpos - sizeof(awshdr) - prvblkl; dev->nxtblkpos = blkpos; /* Decrement current file number if backspaced over tapemark */ if (curblkl == 0) dev->curfilen--; dev->blockid--; /* Return block length or zero if tapemark */ return curblkl; } /* end function bsb_awstape */ /*-------------------------------------------------------------------*/ /* Forward space to next logical file of AWSTAPE format file */ /* */ /* For AWSTAPE files, the forward space file operation is achieved */ /* by forward spacing blocks until positioned just after a tapemark. */ /* */ /* If successful, return value is zero, and the current file number */ /* in the device block is incremented by fsb_awstape. */ /* If error, return value is -1 and unitstat is set to CE+DE+UC */ /*-------------------------------------------------------------------*/ int fsf_awstape (DEVBLK *dev, BYTE *unitstat,BYTE code) { int rc; /* Return code */ while (1) { /* Forward space over next block */ rc = fsb_awstape (dev, unitstat,code); if (rc < 0) return -1; /* Exit loop if spaced over a tapemark */ if (rc == 0) break; } /* end while */ /* Return normal status */ return 0; } /* end function fsf_awstape */ /*-------------------------------------------------------------------*/ /* Backspace to previous logical file of AWSTAPE format file */ /* */ /* For AWSTAPE files, the backspace file operation is achieved */ /* by backspacing blocks until positioned just before a tapemark */ /* or until positioned at start of tape. */ /* */ /* If successful, return value is zero, and the current file number */ /* in the device block is decremented by bsb_awstape. */ /* If error, return value is -1 and unitstat is set to CE+DE+UC */ /*-------------------------------------------------------------------*/ int bsf_awstape (DEVBLK *dev, BYTE *unitstat,BYTE code) { int rc; /* Return code */ while (1) { /* Exit if now at start of tape */ if (dev->nxtblkpos == 0) { build_senseX(TAPE_BSENSE_LOADPTERR,dev,unitstat,code); return -1; } /* Backspace to previous block position */ rc = bsb_awstape (dev, unitstat,code); if (rc < 0) return -1; /* Exit loop if backspaced over a tapemark */ if (rc == 0) break; } /* end while */ /* Return normal status */ return 0; } /* end function bsf_awstape */ /*********************************************************************/ /* END OF ORIGINAL RB AWS FUNCTIONS */ /*********************************************************************/ hercules-3.07/bldcfg.c000644 000765 000765 00000177100 11321734033 016333 0ustar00jmaynardjmaynard000000 000000 /* BLDCFG.C (c) Copyright Roger Bowler, 1999-2009 */ /* ESA/390 Configuration Builder */ /* Interpretive Execution - (c) Copyright Jan Jaeger, 1999-2009 */ // $Id: bldcfg.c 5562 2009-12-24 14:29:38Z rbowler $ /*-------------------------------------------------------------------*/ /* This module builds the configuration tables for the Hercules */ /* ESA/390 emulator. It reads information about the processors */ /* and I/O devices from a configuration file. It allocates */ /* main storage and expanded storage, initializes control blocks, */ /* and creates detached threads to handle console attention */ /* requests and to maintain the TOD clock and CPU timers. */ /*-------------------------------------------------------------------*/ /*-------------------------------------------------------------------*/ /* Additional credits: */ /* TOD clock offset contributed by Jay Maynard */ /* Dynamic device attach/detach by Jan Jaeger */ /* OSTAILOR parameter by Jay Maynard */ /* PANRATE parameter by Reed H. Petty */ /* CPUPRIO parameter by Jan Jaeger */ /* HERCPRIO, TODPRIO, DEVPRIO parameters by Mark L. Gaubatz */ /* z/Architecture support - (c) Copyright Jan Jaeger, 1999-2009 */ /* $(DEFSYM) symbol substitution support by Ivan Warren */ /* Patch for ${var=def} symbol substitution (hax #26), */ /* and INCLUDE support (modified hax #27), */ /* contributed by Enrico Sorichetti based on */ /* original patches by "Hackules" */ /*-------------------------------------------------------------------*/ #include "hstdinc.h" #if !defined(_BLDCFG_C_) #define _BLDCFG_C_ #endif #if !defined(_HENGINE_DLL_) #define _HENGINE_DLL_ #endif #include "hercules.h" #include "devtype.h" #include "opcode.h" #include "hostinfo.h" #if defined(OPTION_FISHIO) #include "w32chan.h" #endif // defined(OPTION_FISHIO) #if defined( OPTION_TAPE_AUTOMOUNT ) #include "tapedev.h" #endif #if !defined(_GEN_ARCH) #if defined(_ARCHMODE3) #define _GEN_ARCH _ARCHMODE3 #include "bldcfg.c" #undef _GEN_ARCH #endif #if defined(_ARCHMODE2) #define _GEN_ARCH _ARCHMODE2 #include "bldcfg.c" #undef _GEN_ARCH #endif typedef struct _DEVARRAY { U16 cuu1; U16 cuu2; } DEVARRAY; typedef struct _DEVNUMSDESC { BYTE lcss; DEVARRAY *da; } DEVNUMSDESC; /*-------------------------------------------------------------------*/ /* Static data areas */ /*-------------------------------------------------------------------*/ #define MAX_INC_LEVEL 8 /* Maximum nest level */ static int inc_level; /* Current nesting level */ // following commented out ISW 20061009 : Not referenced anywhere. // static int inc_fname[MAX_INC_LEVEL]; /* filename (base or incl) */ static int inc_stmtnum[MAX_INC_LEVEL]; /* statement number */ static int inc_ignore_errors = 0; /* 1==ignore include errors */ #ifdef EXTERNALGUI static char buf[1024]; /* Config statement buffer */ #else /*!EXTERNALGUI*/ static char buf[256]; /* Config statement buffer */ #endif /*EXTERNALGUI*/ static char *keyword; /* -> Statement keyword */ static char *operand; /* -> First argument */ static int addargc; /* Number of additional args */ static char *addargv[MAX_ARGS]; /* Additional argument array */ /*-------------------------------------------------------------------*/ /* Subroutine to parse an argument string. The string that is passed */ /* is modified in-place by inserting null characters at the end of */ /* each argument found. The returned array of argument pointers */ /* then points to each argument found in the original string. Any */ /* argument that begins with '#' comment indicator causes early */ /* termination of the parsing and is not included in the count. Any */ /* argument found that starts with a quote or apostrophe causes */ /* all characters up to the next quote or apostrophe to be */ /* included as part of that argument. The quotes/apostrophes them- */ /* selves are not considered part of any argument and are ignored. */ /* p Points to string to be parsed. */ /* maxargc Maximum allowable number of arguments. (Prevents */ /* overflowing the pargv array) */ /* pargv Pointer to buffer for argument pointer array. */ /* pargc Pointer to number of arguments integer result. */ /* Returns number of arguments found. (same value as at *pargc) */ /*-------------------------------------------------------------------*/ DLL_EXPORT int parse_args (char* p, int maxargc, char** pargv, int* pargc) { for (*pargc = 0; *pargc < MAX_ARGS; ++*pargc) addargv[*pargc] = NULL; *pargc = 0; *pargv = NULL; while (*p && *pargc < maxargc) { while (*p && isspace(*p)) p++; if (!*p) break; // find start of arg if (*p == '#') break; // stop on comments *pargv = p; ++*pargc; // count new arg while (*p && !isspace(*p) && *p != '\"' && *p != '\'') p++; if (!*p) break; // find end of arg if (*p == '\"' || *p == '\'') { char delim = *p; if (p == *pargv) *pargv = p+1; while (*++p && *p != delim); if (!*p) break; // find end of quoted string } *p++ = 0; // mark end of arg pargv++; // next arg ptr } return *pargc; } void delayed_exit (int exit_code) { /* Delay exiting is to give the system * time to display the error message. */ fflush(stderr); fflush(stdout); usleep(100000); // hdl_shut(); do_shutdown(); fflush(stderr); fflush(stdout); usleep(100000); exit(exit_code); } /* storage configuration routine. To be moved *JJ */ static void config_storage(unsigned mainsize, unsigned xpndsize) { int off; /* Obtain main storage */ sysblk.mainsize = mainsize * 1024 * 1024ULL; sysblk.mainstor = calloc((size_t)(sysblk.mainsize + 8192), 1); if (sysblk.mainstor != NULL) sysblk.main_clear = 1; else sysblk.mainstor = malloc((size_t)(sysblk.mainsize + 8192)); if (sysblk.mainstor == NULL) { logmsg(_("HHCCF031S Cannot obtain %dMB main storage: %s\n"), mainsize, strerror(errno)); delayed_exit(1); } /* Trying to get mainstor aligned to the next 4K boundary - Greg */ off = (uintptr_t)sysblk.mainstor & 0xFFF; sysblk.mainstor += off ? 4096 - off : 0; /* Obtain main storage key array */ sysblk.storkeys = calloc((size_t)(sysblk.mainsize / STORAGE_KEY_UNITSIZE), 1); if (sysblk.storkeys == NULL) { sysblk.main_clear = 0; sysblk.storkeys = malloc((size_t)(sysblk.mainsize / STORAGE_KEY_UNITSIZE)); } if (sysblk.storkeys == NULL) { logmsg(_("HHCCF032S Cannot obtain storage key array: %s\n"), strerror(errno)); delayed_exit(1); } /* Initial power-on reset for main storage */ storage_clear(); #if 0 /*DEBUG-JJ-20/03/2000*/ /* Mark selected frames invalid for debugging purposes */ for (i = 64 ; i < (sysblk.mainsize / STORAGE_KEY_UNITSIZE); i += 2) if (i < (sysblk.mainsize / STORAGE_KEY_UNITSIZE) - 64) sysblk.storkeys[i] = STORKEY_BADFRM; else sysblk.storkeys[i++] = STORKEY_BADFRM; #endif if (xpndsize != 0) { #ifdef _FEATURE_EXPANDED_STORAGE /* Obtain expanded storage */ sysblk.xpndsize = xpndsize * (1024*1024 / XSTORE_PAGESIZE); sysblk.xpndstor = calloc(sysblk.xpndsize, XSTORE_PAGESIZE); if (sysblk.xpndstor) sysblk.xpnd_clear = 1; else sysblk.xpndstor = malloc((size_t)sysblk.xpndsize * XSTORE_PAGESIZE); if (sysblk.xpndstor == NULL) { logmsg(_("HHCCF033S Cannot obtain %dMB expanded storage: " "%s\n"), xpndsize, strerror(errno)); delayed_exit(1); } /* Initial power-on reset for expanded storage */ xstorage_clear(); #else /*!_FEATURE_EXPANDED_STORAGE*/ logmsg(_("HHCCF034W Expanded storage support not installed\n")); #endif /*!_FEATURE_EXPANDED_STORAGE*/ } /* end if(sysblk.xpndsize) */ } #if defined( OPTION_TAPE_AUTOMOUNT ) /*-------------------------------------------------------------------*/ /* Add directory to AUTOMOUNT allowed/disallowed directories list */ /* */ /* Input: tamdir pointer to work character array of at least */ /* MAX_PATH size containing an allowed/disallowed */ /* directory specification, optionally prefixed */ /* with the '+' or '-' indicator. */ /* */ /* ppTAMDIR address of TAMDIR ptr that upon successful */ /* completion is updated to point to the TAMDIR */ /* entry that was just successfully added. */ /* */ /* Output: upon success, ppTAMDIR is updated to point to the TAMDIR */ /* entry just added. Upon error, ppTAMDIR is set to NULL and */ /* the original input character array is set to the inter- */ /* mediate value being processed when the error occurred. */ /* */ /* Returns: 0 == success */ /* 1 == unresolvable path */ /* 2 == path inaccessible */ /* 3 == conflict w/previous */ /* 4 == duplicates previous */ /* 5 == out of memory */ /* */ /*-------------------------------------------------------------------*/ DLL_EXPORT int add_tamdir( char *tamdir, TAMDIR **ppTAMDIR ) { int rc, rej = 0; char dirwrk[ MAX_PATH ] = {0}; *ppTAMDIR = NULL; if (*tamdir == '-') { rej = 1; memmove (tamdir, tamdir+1, MAX_PATH); } else if (*tamdir == '+') { rej = 0; memmove (tamdir, tamdir+1, MAX_PATH); } /* Convert tamdir to absolute path ending with a slash */ #if defined(_MSVC_) /* (expand any embedded %var% environment variables) */ rc = expand_environ_vars( tamdir, dirwrk, MAX_PATH ); if (rc == 0) strlcpy (tamdir, dirwrk, MAX_PATH); #endif if (!realpath( tamdir, dirwrk )) return (1); /* ("unresolvable path") */ strlcpy (tamdir, dirwrk, MAX_PATH); /* Verify that the path is valid */ if (access( tamdir, R_OK | W_OK ) != 0) return (2); /* ("path inaccessible") */ /* Append trailing path separator if needed */ rc = strlen( tamdir ); if (tamdir[rc-1] != *PATH_SEP) strlcat (tamdir, PATH_SEP, MAX_PATH); /* Check for duplicate/conflicting specification */ for (*ppTAMDIR = sysblk.tamdir; *ppTAMDIR; *ppTAMDIR = (*ppTAMDIR)->next) { if (strfilenamecmp( tamdir, (*ppTAMDIR)->dir ) == 0) { if ((*ppTAMDIR)->rej != rej) return (3); /* ("conflict w/previous") */ else return (4); /* ("duplicates previous") */ } } /* Allocate new AUTOMOUNT directory entry */ *ppTAMDIR = malloc( sizeof(TAMDIR) ); if (!*ppTAMDIR) return (5); /* ("out of memory") */ /* Fill in the new entry... */ (*ppTAMDIR)->dir = strdup (tamdir); (*ppTAMDIR)->len = strlen (tamdir); (*ppTAMDIR)->rej = rej; (*ppTAMDIR)->next = NULL; /* Add new entry to end of existing list... */ if (sysblk.tamdir == NULL) sysblk.tamdir = *ppTAMDIR; else { TAMDIR *pTAMDIR = sysblk.tamdir; while (pTAMDIR->next) pTAMDIR = pTAMDIR->next; pTAMDIR->next = *ppTAMDIR; } /* Use first allowable dir as default */ if (rej == 0 && sysblk.defdir == NULL) sysblk.defdir = (*ppTAMDIR)->dir; return (0); /* ("success") */ } #endif /* OPTION_TAPE_AUTOMOUNT */ /*-------------------------------------------------------------------*/ /* Subroutine to read a statement from the configuration file */ /* The statement is then parsed into keyword, operand, and */ /* additional arguments. The output values are: */ /* keyword Points to first word of statement */ /* operand Points to second word of statement */ /* addargc Contains number of additional arguments */ /* addargv An array of pointers to each additional argument */ /* Returns 0 if successful, -1 if end of file */ /*-------------------------------------------------------------------*/ static int read_config (char *fname, FILE *fp) { int i; /* Array subscript */ int c; /* Character work area */ int stmtlen; /* Statement length */ #if defined( OPTION_ENHANCED_CONFIG_SYMBOLS ) int inc_dollar; /* >=0 Ndx of dollar */ int inc_lbrace; /* >=0 Ndx of lbrace + 1 */ int inc_colon; /* >=0 Ndx of colon */ int inc_equals; /* >=0 Ndx of equals */ char *inc_envvar; /* ->Environment variable */ #endif // defined( OPTION_ENHANCED_CONFIG_SYMBOLS ) int lstarted; /* Indicate if non-whitespace*/ /* has been seen yet in line */ char *cnfline; /* Pointer to copy of buffer */ #if defined(OPTION_CONFIG_SYMBOLS) char *buf1; /* Pointer to resolved buffer*/ #endif /*defined(OPTION_CONFIG_SYMBOLS)*/ #if defined( OPTION_ENHANCED_CONFIG_SYMBOLS ) inc_dollar = -1; inc_lbrace = -1; inc_colon = -1; inc_equals = -1; #endif // defined( OPTION_ENHANCED_CONFIG_SYMBOLS ) while (1) { /* Increment statement number */ inc_stmtnum[inc_level]++; /* Read next statement from configuration file */ for (stmtlen = 0, lstarted = 0; ;) { /* Read character from configuration file */ c = fgetc(fp); /* Check for I/O error */ if (ferror(fp)) { logmsg(_("HHCCF001S Error reading file %s line %d: %s\n"), fname, inc_stmtnum[inc_level], strerror(errno)); delayed_exit(1); } /* Check for end of file */ if (stmtlen == 0 && (c == EOF || c == '\x1A')) return -1; /* Check for end of line */ if (c == '\n' || c == EOF || c == '\x1A') break; /* Ignore nulls and carriage returns */ if (c == '\0' || c == '\r') continue; /* Check if it is a white space and no other character yet */ if(!lstarted && isspace(c)) continue; lstarted=1; /* Check that statement does not overflow buffer */ if (stmtlen >= (int)(sizeof(buf) - 1)) { logmsg(_("HHCCF002S File %s line %d is too long\n"), fname, inc_stmtnum[inc_level]); delayed_exit(1); } #if defined( OPTION_ENHANCED_CONFIG_SYMBOLS ) /* inc_dollar already processed? */ if (inc_dollar >= 0) { /* Left brace already processed? */ if (inc_lbrace >= 0) { /* End of variable spec? */ if (c == '}') { /* Terminate it */ buf[stmtlen] = '\0'; /* Terminate var name if we have a inc_colon specifier */ if (inc_colon >= 0) { buf[inc_colon] = '\0'; } /* Terminate var name if we have a default value */ if (inc_equals >= 0) { buf[inc_equals] = '\0'; } /* Reset statement index to start of variable */ stmtlen = inc_dollar; /* Get variable value */ inc_envvar = getenv (&buf[inc_lbrace]); /* Variable unset? */ if (inc_envvar == NULL) { /* Substitute default if specified */ if (inc_equals >= 0) { inc_envvar = &buf[inc_equals+1]; } } else // (environ variable defined) { /* Have ":=" specification? */ if (/*inc_colon >= 0 && */inc_equals >= 0) { /* Substitute default if value is NULL */ if (strlen (inc_envvar) == 0) { inc_envvar = &buf[inc_equals+1]; } } } /* Have a value? (environment or default) */ if (inc_envvar != NULL) { /* Check that statement does not overflow buffer */ if (stmtlen+strlen(inc_envvar) >= sizeof(buf) - 1) { logmsg(_("HHCCF002S File %s line %d is too long\n"), fname, inc_stmtnum[inc_level]); delayed_exit(1); } /* Copy to buffer and update index */ stmtlen += sprintf (&buf[stmtlen], "%s", inc_envvar); } /* Reset indexes */ inc_equals = -1; inc_colon = -1; inc_lbrace = -1; inc_dollar = -1; continue; } else if (c == ':' && inc_colon < 0 && inc_equals < 0) { /* Remember possible start of default specifier */ inc_colon = stmtlen; } else if (c == '=' && inc_equals < 0) { /* Remember possible start of default specifier */ inc_equals = stmtlen; } } else // (inc_lbrace < 0) { /* Remember start of variable name */ if (c == '{') { inc_lbrace = stmtlen + 1; } else { /* Reset inc_dollar specifier if immediately following character is not a left brace */ inc_dollar = -1; } } } else // (inc_dollar < 0) { /* Enter variable substitution state */ if (c == '$') { inc_dollar = stmtlen; } } #endif // defined( OPTION_ENHANCED_CONFIG_SYMBOLS ) /* Append character to buffer */ buf[stmtlen++] = c; } /* end for(stmtlen) */ /* Remove trailing blanks and tabs */ while (stmtlen > 0 && (buf[stmtlen-1] == SPACE || buf[stmtlen-1] == '\t')) stmtlen--; buf[stmtlen] = '\0'; /* Ignore comments and null statements */ if (stmtlen == 0 || buf[0] == '*' || buf[0] == '#') continue; cnfline = strdup(buf); /* Parse the statement just read */ #if defined(OPTION_CONFIG_SYMBOLS) /* Perform variable substitution */ /* First, set some 'dynamic' symbols to their own values */ set_symbol("CUU","$(CUU)"); set_symbol("cuu","$(cuu)"); set_symbol("CCUU","$(CCUU)"); set_symbol("ccuu","$(ccuu)"); buf1=resolve_symbol_string(buf); if(buf1!=NULL) { if(strlen(buf1)>=sizeof(buf)) { logmsg(_("HHCCF002S File %s line %d is too long\n"), fname, inc_stmtnum[inc_level]); free(buf1); delayed_exit(1); } strcpy(buf,buf1); } #endif /*defined(OPTION_CONFIG_SYMBOLS)*/ parse_args (buf, MAX_ARGS, addargv, &addargc); #if defined(OPTION_DYNAMIC_LOAD) if(config_command) { if( config_command(addargc, (char**)addargv, cnfline) ) { free(cnfline); continue; } } #endif /*defined(OPTION_DYNAMIC_LOAD)*/ if( !ProcessConfigCommand (addargc, (char**)addargv, cnfline) ) { free(cnfline); continue; } free(cnfline); /* Move the first two arguments to separate variables */ keyword = addargv[0]; operand = addargv[1]; addargc = (addargc > 2) ? (addargc-2) : (0); for (i = 0; i < MAX_ARGS; i++) { if (i < (MAX_ARGS-2)) addargv[i] = addargv[i+2]; else addargv[i] = NULL; } break; } /* end while */ return 0; } /* end function read_config */ static inline S64 lyear_adjust(int epoch) { int year, leapyear; U64 tod = hw_clock(); if(tod >= TOD_YEAR) { tod -= TOD_YEAR; year = (tod / TOD_4YEARS * 4) + 1; tod %= TOD_4YEARS; if((leapyear = tod / TOD_YEAR) == 4) year--; year += leapyear; } else year = 0; if(epoch > 0) return (((year % 4) != 0) && (((year % 4) - (epoch % 4)) <= 0)) ? -TOD_DAY : 0; else return (((year % 4) == 0 && (-epoch % 4) != 0) || ((year % 4) + (-epoch % 4) > 4)) ? TOD_DAY : 0; } DLL_EXPORT char *config_cnslport = "3270"; /*-------------------------------------------------------------------*/ /* Function to build system configuration */ /*-------------------------------------------------------------------*/ void build_config (char *fname) { int rc; /* Return code */ int i; /* Array subscript */ int scount; /* Statement counter */ int cpu; /* CPU number */ int count; /* Counter */ FILE *inc_fp[MAX_INC_LEVEL]; /* Configuration file pointer*/ char *sserial; /* -> CPU serial string */ char *smodel; /* -> CPU model string */ char *sversion; /* -> CPU version string */ char *smainsize; /* -> Main size string */ char *sxpndsize; /* -> Expanded size string */ char *smaxcpu; /* -> Maximum number of CPUs */ char *snumcpu; /* -> Number of CPUs */ char *snumvec; /* -> Number of VFs */ char *sengines; /* -> Processor engine types */ char *ssysepoch; /* -> System epoch */ char *syroffset; /* -> System year offset */ char *stzoffset; /* -> System timezone offset */ char *shercprio; /* -> Hercules base priority */ char *stodprio; /* -> Timer thread priority */ char *scpuprio; /* -> CPU thread priority */ char *sdevprio; /* -> Device thread priority */ char *slogofile; /* -> 3270 logo file */ #if defined(_FEATURE_ECPSVM) char *secpsvmlevel; /* -> ECPS:VM Keyword */ char *secpsvmlvl; /* -> ECPS:VM level (or 'no')*/ int ecpsvmac; /* -> ECPS:VM add'l arg cnt */ #endif /*defined(_FEATURE_ECPSVM)*/ #if defined(OPTION_SHARED_DEVICES) char *sshrdport; /* -> Shared device port nbr */ #endif /*defined(OPTION_SHARED_DEVICES)*/ U16 version = 0x00; /* CPU version code */ int dfltver = 1; /* Default version code */ U32 serial; /* CPU serial number */ U16 model; /* CPU model number */ unsigned mainsize; /* Main storage size (MB) */ unsigned xpndsize; /* Expanded storage size (MB)*/ U16 maxcpu; /* Maximum number of CPUs */ U16 numcpu; /* Number of CPUs */ U16 numvec; /* Number of VFs */ #if defined(OPTION_SHARED_DEVICES) U16 shrdport; /* Shared device port number */ #endif /*defined(OPTION_SHARED_DEVICES)*/ S32 sysepoch; /* System epoch year */ S32 tzoffset; /* System timezone offset */ S32 yroffset; /* System year offset */ S64 ly1960; /* Leap offset for 1960 epoch*/ int hercprio; /* Hercules base priority */ int todprio; /* Timer thread priority */ int cpuprio; /* CPU thread priority */ int devprio; /* Device thread priority */ DEVBLK *dev; /* -> Device Block */ char *sdevnum; /* -> Device number string */ char *sdevtype; /* -> Device type string */ int devtmax; /* Max number device threads */ #if defined(_FEATURE_ECPSVM) int ecpsvmavail; /* ECPS:VM Available flag */ int ecpsvmlevel; /* ECPS:VM declared level */ #endif /*defined(_FEATURE_ECPSVM)*/ BYTE c; /* Work area for sscanf */ char *styp; /* -> Engine type string */ char *styp_values[] = {"CP","CF","AP","IL","??","IP"}; /* type values */ BYTE ptyp; /* Processor engine type */ #ifdef OPTION_SELECT_KLUDGE int dummyfd[OPTION_SELECT_KLUDGE]; /* Dummy file descriptors -- this allows the console to get a low fd when the msg pipe is opened... prevents cygwin from thrashing in select(). sigh */ #endif char hlogofile[FILENAME_MAX+1] = ""; /* File name from HERCLOGO */ char pathname[MAX_PATH]; /* file path in host format */ /* Initialize SETMODE and set user authority */ SETMODE(INIT); #ifdef OPTION_SELECT_KLUDGE /* Reserve some fd's to be used later for the message pipes */ for (i = 0; i < OPTION_SELECT_KLUDGE; i++) dummyfd[i] = dup(fileno(stderr)); #endif /* Open the base configuration file */ hostpath(pathname, fname, sizeof(pathname)); inc_level = 0; inc_fp[inc_level] = fopen (pathname, "r"); if (inc_fp[inc_level] == NULL) { logmsg(_("HHCCF003S Open error file %s: %s\n"), fname, strerror(errno)); delayed_exit(1); } inc_stmtnum[inc_level] = 0; /* Set the default system parameter values */ serial = 0x000001; model = 0x0586; mainsize = 2; xpndsize = 0; maxcpu = 0; numcpu = 0; numvec = MAX_CPU_ENGINES; sysepoch = 1900; yroffset = 0; tzoffset = 0; #if defined(_390) sysblk.arch_mode = ARCH_390; #else sysblk.arch_mode = ARCH_370; #endif #if defined(_900) sysblk.arch_z900 = ARCH_900; #endif sysblk.pgminttr = OS_NONE; sysblk.timerint = DEFAULT_TIMER_REFRESH_USECS; #if defined( HTTP_SERVER_CONNECT_KLUDGE ) sysblk.http_server_kludge_msecs = 10; #endif // defined( HTTP_SERVER_CONNECT_KLUDGE ) hercprio = DEFAULT_HERCPRIO; todprio = DEFAULT_TOD_PRIO; cpuprio = DEFAULT_CPU_PRIO; devprio = DEFAULT_DEV_PRIO; devtmax = MAX_DEVICE_THREADS; sysblk.kaidle = KEEPALIVE_IDLE_TIME; sysblk.kaintv = KEEPALIVE_PROBE_INTERVAL; sysblk.kacnt = KEEPALIVE_PROBE_COUNT; #if defined(_FEATURE_ECPSVM) ecpsvmavail = 0; ecpsvmlevel = 20; #endif /*defined(_FEATURE_ECPSVM)*/ #if defined(OPTION_SHARED_DEVICES) shrdport = 0; #endif /*defined(OPTION_SHARED_DEVICES)*/ #if defined(_FEATURE_ASN_AND_LX_REUSE) sysblk.asnandlxreuse = 0; /* ASN And LX Reuse is defaulted to DISABLE */ #endif #ifdef PANEL_REFRESH_RATE sysblk.panrate = PANEL_REFRESH_RATE_SLOW; #endif /* Initialize locks, conditions, and attributes */ initialize_lock (&sysblk.todlock); initialize_lock (&sysblk.mainlock); sysblk.mainowner = LOCK_OWNER_NONE; initialize_lock (&sysblk.intlock); initialize_lock (&sysblk.iointqlk); sysblk.intowner = LOCK_OWNER_NONE; initialize_lock (&sysblk.sigplock); // initialize_detach_attr (&sysblk.detattr); // (moved to impl.c) // initialize_join_attr (&sysblk.joinattr); // (moved to impl.c) initialize_condition (&sysblk.cpucond); for (i = 0; i < MAX_CPU_ENGINES; i++) initialize_lock (&sysblk.cpulock[i]); initialize_condition (&sysblk.sync_cond); initialize_condition (&sysblk.sync_bc_cond); #if defined(OPTION_INSTRUCTION_COUNTING) initialize_lock (&sysblk.icount_lock); #endif #ifdef OPTION_PTTRACE ptt_trace_init (0, 1); #endif #if defined(OPTION_FISHIO) InitIOScheduler // initialize i/o scheduler... ( sysblk.arch_mode, // (for calling execute_ccw_chain) &sysblk.devprio, // (ptr to device thread priority) MAX_DEVICE_THREAD_IDLE_SECS, // (maximum device thread wait time) devtmax // (maximum #of device threads allowed) ); #else // !defined(OPTION_FISHIO) initialize_lock (&sysblk.ioqlock); initialize_condition (&sysblk.ioqcond); /* Set max number device threads */ sysblk.devtmax = devtmax; sysblk.devtwait = sysblk.devtnbr = sysblk.devthwm = sysblk.devtunavail = 0; #endif // defined(OPTION_FISHIO) /* Default the licence setting */ losc_set(PGM_PRD_OS_RESTRICTED); /* Default CPU type CP */ for (i = 0; i < MAX_CPU_ENGINES; i++) sysblk.ptyp[i] = SCCB_PTYP_CP; /* Cap the default priorities at zero if setuid not available */ #if !defined(NO_SETUID) if (sysblk.suid != 0) { #endif /*!defined(NO_SETUID)*/ if (hercprio < 0) hercprio = 0; if (todprio < 0) todprio = 0; if (cpuprio < 0) cpuprio = 0; if (devprio < 0) devprio = 0; #if !defined(NO_SETUID) } #endif /*!defined(NO_SETUID)*/ /*****************************************************************/ /* Parse configuration file system parameter statements... */ /*****************************************************************/ for (scount = 0; ; scount++) { /* Read next record from the configuration file */ while (inc_level >= 0 && read_config (fname, inc_fp[inc_level])) { fclose (inc_fp[inc_level--]); } if (inc_level < 0) { logmsg(_("HHCCF004S No device records in file %s\n"), fname); delayed_exit(1); } #if defined( OPTION_ENHANCED_CONFIG_INCLUDE ) if (strcasecmp (keyword, "ignore") == 0) { if (strcasecmp (operand, "include_errors") == 0) { logmsg( _("HHCCF081I %s Will ignore include errors .\n"), fname); inc_ignore_errors = 1 ; } continue ; } /* Check for include statement */ if (strcasecmp (keyword, "include") == 0) { if (++inc_level >= MAX_INC_LEVEL) { logmsg(_( "HHCCF082S Error in %s line %d: " "Maximum nesting level (%d) reached\n"), fname, inc_stmtnum[inc_level-1], MAX_INC_LEVEL); delayed_exit(1); } logmsg( _("HHCCF083I %s Including %s at %d.\n"), fname, operand, inc_stmtnum[inc_level-1]); hostpath(pathname, operand, sizeof(pathname)); inc_fp[inc_level] = fopen (pathname, "r"); if (inc_fp[inc_level] == NULL) { inc_level--; if ( inc_ignore_errors == 1 ) { logmsg(_("HHCCF084W %s Open error ignored file %s: %s\n"), fname, operand, strerror(errno)); continue ; } else { logmsg(_("HHCCF085S %s Open error file %s: %s\n"), fname, operand, strerror(errno)); delayed_exit(1); } } inc_stmtnum[inc_level] = 0; continue; } #endif // defined( OPTION_ENHANCED_CONFIG_INCLUDE ) /* Exit loop if first device statement found */ if (strlen(keyword) <= 4 && sscanf(keyword, "%x%c", &rc, &c) == 1) break; /* ISW */ /* Also exit if keyword contains '-', ',' or '.' */ /* Added because device statements may now be a compound device number specification */ if(strchr(keyword,'-')) { break; } if(strchr(keyword,'.')) { break; } if(strchr(keyword,',')) { break; } /* Also exit if keyword contains ':' (added by Harold Grovesteen jan2008) */ /* Added because device statements may now contain channel set or LCSS id */ if(strchr(keyword,':')) { break; } /* Clear the operand value pointers */ sserial = NULL; smodel = NULL; sversion = NULL; smainsize = NULL; sxpndsize = NULL; smaxcpu = NULL; snumcpu = NULL; snumvec = NULL; sengines = NULL; ssysepoch = NULL; syroffset = NULL; stzoffset = NULL; shercprio = NULL; stodprio = NULL; scpuprio = NULL; sdevprio = NULL; slogofile = NULL; #if defined(_FEATURE_ECPSVM) secpsvmlevel = NULL; secpsvmlvl = NULL; ecpsvmac = 0; #endif /*defined(_FEATURE_ECPSVM)*/ #if defined(OPTION_SHARED_DEVICES) sshrdport = NULL; #endif /*defined(OPTION_SHARED_DEVICES)*/ /* Check for old-style CPU statement */ if (scount == 0 && addargc == 5 && strlen(keyword) == 6 && sscanf(keyword, "%x%c", &rc, &c) == 1) { sserial = keyword; smodel = operand; smainsize = addargv[0]; sxpndsize = addargv[1]; config_cnslport = strdup(addargv[2]); snumcpu = addargv[3]; set_loadparm(addargv[4]); } else { if (strcasecmp (keyword, "cpuserial") == 0) { sserial = operand; } else if (strcasecmp (keyword, "cpumodel") == 0) { smodel = operand; } else if (strcasecmp (keyword, "mainsize") == 0) { smainsize = operand; } else if (strcasecmp (keyword, "xpndsize") == 0) { sxpndsize = operand; } else if (strcasecmp (keyword, "cnslport") == 0) { config_cnslport = strdup(operand); } else if (strcasecmp (keyword, "maxcpu") == 0) { smaxcpu = operand; } else if (strcasecmp (keyword, "numcpu") == 0) { snumcpu = operand; } else if (strcasecmp (keyword, "numvec") == 0) { snumvec = operand; } else if (strcasecmp (keyword, "engines") == 0) { sengines = operand; } else if (strcasecmp (keyword, "sysepoch") == 0) { ssysepoch = operand; if (addargc > 0) { syroffset = addargv[0]; addargc--; } } else if (strcasecmp (keyword, "yroffset") == 0) { syroffset = operand; } else if (strcasecmp (keyword, "tzoffset") == 0) { stzoffset = operand; } else if (strcasecmp (keyword, "cpuverid") == 0) { sversion = operand; } else if (strcasecmp (keyword, "hercprio") == 0) { shercprio = operand; } else if (strcasecmp (keyword, "todprio") == 0) { stodprio = operand; } else if (strcasecmp (keyword, "cpuprio") == 0) { scpuprio = operand; } else if (strcasecmp (keyword, "devprio") == 0) { sdevprio = operand; } else if (strcasecmp (keyword, "logofile") == 0) { logmsg(_("HHCCF061W Warning in %s line %d: " "LOGOFILE statement deprecated. Use HERCLOGO instead\n"), fname, inc_stmtnum[inc_level]); slogofile=operand; } else if (strcasecmp (keyword, "herclogo") == 0) { slogofile=operand; } #if defined(_FEATURE_ECPSVM) /* ECPS:VM support */ else if(strcasecmp(keyword, "ecps:vm") == 0) { secpsvmlevel=operand; secpsvmlvl=addargv[0]; ecpsvmac=addargc; logmsg(_("HHCCF061W Warning in %s line %d: " "ECPS:VM Statement deprecated. Use ECPSVM instead\n"), fname, inc_stmtnum[inc_level]); addargc=0; } else if(strcasecmp(keyword, "ecpsvm") == 0) { secpsvmlevel=operand; secpsvmlvl=addargv[0]; ecpsvmac=addargc; addargc=0; } #endif /*defined(_FEATURE_ECPSVM)*/ #if defined(OPTION_SHARED_DEVICES) else if (strcasecmp (keyword, "shrdport") == 0) { sshrdport = operand; } #endif /*defined(OPTION_SHARED_DEVICES)*/ else { logmsg( _("HHCCF008E Error in %s line %d: " "Syntax error: %s\n"), fname, inc_stmtnum[inc_level], keyword); operand = ""; addargc = 0; } /* Check for one and only one operand */ if (operand == NULL || addargc != 0) { logmsg( _("HHCCF009E Error in %s line %d: " "Incorrect number of operands\n"), fname, inc_stmtnum[inc_level]); } } /* end else (not old-style CPU statement) */ /* Parse CPU version number operand */ if (sversion != NULL) { if (strlen(sversion) != 2 || sscanf(sversion, "%hx%c", &version, &c) != 1 || version>255) { logmsg(_("HHCCF012S Error in %s line %d: " "%s is not a valid CPU version code\n"), fname, inc_stmtnum[inc_level], sversion); delayed_exit(1); } dfltver = 0; } /* Parse CPU serial number operand */ if (sserial != NULL) { if (strlen(sserial) != 6 || sscanf(sserial, "%x%c", &serial, &c) != 1) { logmsg(_("HHCCF051S Error in %s line %d: " "%s is not a valid serial number\n"), fname, inc_stmtnum[inc_level], sserial); delayed_exit(1); } } /* Parse CPU model number operand */ if (smodel != NULL) { if (strlen(smodel) != 4 || sscanf(smodel, "%hx%c", &model, &c) != 1) { logmsg(_("HHCCF012S Error in %s line %d: " "%s is not a valid CPU model\n"), fname, inc_stmtnum[inc_level], smodel); delayed_exit(1); } } /* Parse main storage size operand */ if (smainsize != NULL) { if (sscanf(smainsize, "%u%c", &mainsize, &c) != 1 || mainsize < 2 || (mainsize > 4095 && sizeof(sysblk.mainsize) < 8) || (mainsize > 4095 && sizeof(size_t) < 8)) { logmsg(_("HHCCF013S Error in %s line %d: " "Invalid main storage size %s\n"), fname, inc_stmtnum[inc_level], smainsize); delayed_exit(1); } } /* Parse expanded storage size operand */ if (sxpndsize != NULL) { if (sscanf(sxpndsize, "%u%c", &xpndsize, &c) != 1 || xpndsize > (0x100000000ULL / XSTORE_PAGESIZE) - 1 || (xpndsize > 4095 && sizeof(size_t) < 8)) { logmsg(_("HHCCF014S Error in %s line %d: " "Invalid expanded storage size %s\n"), fname, inc_stmtnum[inc_level], sxpndsize); delayed_exit(1); } } /* Parse Hercules priority operand */ if (shercprio != NULL) if (sscanf(shercprio, "%d%c", &hercprio, &c) != 1) { logmsg(_("HHCCF016S Error in %s line %d: " "Invalid Hercules process group thread priority %s\n"), fname, inc_stmtnum[inc_level], shercprio); delayed_exit(1); } #if !defined(NO_SETUID) if(sysblk.suid != 0 && hercprio < 0) { logmsg(_("HHCCF017W Hercules is not running as setuid root, " "cannot raise Hercules process group thread priority\n")); hercprio = 0; /* Set priority to Normal */ } #endif /*!defined(NO_SETUID)*/ sysblk.hercprio = hercprio; /* Parse TOD Clock priority operand */ if (stodprio != NULL) if (sscanf(stodprio, "%d%c", &todprio, &c) != 1) { logmsg(_("HHCCF016S Error in %s line %d: " "Invalid TOD Clock thread priority %s\n"), fname, inc_stmtnum[inc_level], stodprio); delayed_exit(1); } #if !defined(NO_SETUID) if(sysblk.suid != 0 && todprio < 0) { logmsg(_("HHCCF017W Hercules is not running as setuid root, " "cannot raise TOD Clock thread priority\n")); todprio = 0; /* Set priority to Normal */ } #endif /*!defined(NO_SETUID)*/ sysblk.todprio = todprio; /* Parse CPU thread priority operand */ if (scpuprio != NULL) if (sscanf(scpuprio, "%d%c", &cpuprio, &c) != 1) { logmsg(_("HHCCF016S Error in %s line %d: " "Invalid CPU thread priority %s\n"), fname, inc_stmtnum[inc_level], scpuprio); delayed_exit(1); } #if !defined(NO_SETUID) if(sysblk.suid != 0 && cpuprio < 0) { logmsg(_("HHCCF017W Hercules is not running as setuid root, " "cannot raise CPU priority\n")); cpuprio = 0; /* Set priority to Normal */ } #endif /*!defined(NO_SETUID)*/ sysblk.cpuprio = cpuprio; /* Parse Device thread priority operand */ if (sdevprio != NULL) if (sscanf(sdevprio, "%d%c", &devprio, &c) != 1) { logmsg(_("HHCCF016S Error in %s line %d: " "Invalid device thread priority %s\n"), fname, inc_stmtnum[inc_level], sdevprio); delayed_exit(1); } #if !defined(NO_SETUID) if(sysblk.suid != 0 && devprio < 0) logmsg(_("HHCCF017W Hercules is not running as setuid root, " "cannot raise device thread priority\n")); #endif /*!defined(NO_SETUID)*/ sysblk.devprio = devprio; /* Parse Device thread priority operand */ if (sdevprio != NULL) if (sscanf(sdevprio, "%d%c", &devprio, &c) != 1) { logmsg(_("HHCCF016S Error in %s line %d: " "Invalid device thread priority %s\n"), fname, inc_stmtnum[inc_level], sdevprio); delayed_exit(1); } #if !defined(NO_SETUID) if(sysblk.suid != 0 && devprio < 0) logmsg(_("HHCCF017W Hercules is not running as setuid root, " "cannot raise device thread priority\n")); #endif /*!defined(NO_SETUID)*/ sysblk.devprio = devprio; /* Parse maximum number of CPUs operand */ if (smaxcpu != NULL) { if (sscanf(smaxcpu, "%hu%c", &maxcpu, &c) != 1 || maxcpu < 1 || maxcpu > MAX_CPU_ENGINES) { fprintf(stderr, _("HHCCF021S Error in %s line %d: " "Invalid maximum number of CPUs %s\n"), fname, inc_stmtnum[inc_level], smaxcpu); delayed_exit(1); } } /* Parse number of CPUs operand */ if (snumcpu != NULL) { if (sscanf(snumcpu, "%hu%c", &numcpu, &c) != 1 || numcpu > MAX_CPU_ENGINES) { logmsg(_("HHCCF018S Error in %s line %d: " "Invalid number of CPUs %s\n"), fname, inc_stmtnum[inc_level], snumcpu); delayed_exit(1); } } sysblk.numcpu = numcpu ? numcpu : 1; /* Parse number of VFs operand */ if (snumvec != NULL) { #ifdef _FEATURE_VECTOR_FACILITY if (sscanf(snumvec, "%hu%c", &numvec, &c) != 1 || numvec > MAX_CPU_ENGINES) { logmsg(_("HHCCF019S Error in %s line %d: " "Invalid number of VFs %s\n"), fname, inc_stmtnum[inc_level], snumvec); delayed_exit(1); } #else /*!_FEATURE_VECTOR_FACILITY*/ logmsg(_("HHCCF020W Vector Facility support not configured\n")); #endif /*!_FEATURE_VECTOR_FACILITY*/ } sysblk.numvec = numvec; /* Parse processor engine types operand */ /* example: ENGINES 4*CP,AP,2*IP */ if (sengines != NULL) { styp = strtok(sengines,","); for (cpu = 0; styp != NULL; ) { count = 1; if (isdigit(styp[0])) { if (sscanf(styp, "%d%c", &count, &c) != 2 || c != '*' || count < 1) { logmsg(_("HHCCF074S Error in %s line %d: " "Invalid engine syntax %s\n"), fname, inc_stmtnum[inc_level], styp); delayed_exit(1); break; } styp = strchr(styp,'*') + 1; } if (strcasecmp(styp,"cp") == 0) ptyp = SCCB_PTYP_CP; else if (strcasecmp(styp,"cf") == 0) ptyp = SCCB_PTYP_ICF; else if (strcasecmp(styp,"il") == 0) ptyp = SCCB_PTYP_IFL; else if (strcasecmp(styp,"ap") == 0) ptyp = SCCB_PTYP_IFA; else if (strcasecmp(styp,"ip") == 0) ptyp = SCCB_PTYP_SUP; else { logmsg(_("HHCCF075S Error in %s line %d: " "Invalid engine type %s\n"), fname, inc_stmtnum[inc_level], styp); delayed_exit(1); break; } while (count-- > 0 && cpu < MAX_CPU_ENGINES) { logmsg("HHCCF077I Engine %d set to type %d (%s)\n", cpu, ptyp, styp_values[ptyp]); sysblk.ptyp[cpu++] = ptyp; } styp = strtok(NULL,","); } } /* Parse system epoch operand */ if (ssysepoch != NULL) { if (strlen(ssysepoch) != 4 || sscanf(ssysepoch, "%d%c", &sysepoch, &c) != 1 || sysepoch <= 1800 || sysepoch >= 2100) { logmsg(_("HHCCF022S Error in %s line %d: " "%s is not a valid system epoch.\n" " The only valid values are " "1801-2099\n"), fname, inc_stmtnum[inc_level], ssysepoch); delayed_exit(1); } } /* Parse year offset operand */ if (syroffset != NULL) { if (sscanf(syroffset, "%d%c", &yroffset, &c) != 1 || (yroffset < -142) || (yroffset > 142)) { logmsg(_("HHCCF070S Error in %s line %d: " "%s is not a valid year offset\n"), fname, inc_stmtnum[inc_level], syroffset); delayed_exit(1); } } /* Parse timezone offset operand */ if (stzoffset != NULL) { if (strlen(stzoffset) != 5 || sscanf(stzoffset, "%d%c", &tzoffset, &c) != 1 || (tzoffset < -2359) || (tzoffset > 2359)) { logmsg(_("HHCCF023S Error in %s line %d: " "%s is not a valid timezone offset\n"), fname, inc_stmtnum[inc_level], stzoffset); delayed_exit(1); } } /* Parse terminal logo option */ if (slogofile != NULL) { strncpy(hlogofile, slogofile, sizeof(hlogofile)-1); hlogofile[sizeof(hlogofile)-1] = '\0'; } #if defined(_FEATURE_ECPSVM) /* Parse ECPS:VM level */ if(secpsvmlevel != NULL) { while(1) /* Dummy while loop for break support */ { ecpsvmavail=0; ecpsvmlevel=0; if(strcasecmp(secpsvmlevel,"no")==0) { ecpsvmavail=0; break; } if(strcasecmp(secpsvmlevel,"yes")==0) { ecpsvmavail=1; ecpsvmlevel=20; break; } if(strcasecmp(secpsvmlevel,"level")==0) { ecpsvmavail=1; if(ecpsvmac==0) { logmsg(_("HHCCF062W Warning in %s line %d: " "Missing ECPSVM level value. 20 Assumed\n"), fname, inc_stmtnum[inc_level]); ecpsvmavail=1; ecpsvmlevel=20; break; } if (sscanf(secpsvmlvl, "%d%c", &ecpsvmlevel, &c) != 1) { logmsg(_("HHCCF051W Warning in %s line %d: " "Invalid ECPSVM level value : %s. 20 Assumed\n"), fname, inc_stmtnum[inc_level], secpsvmlevel); ecpsvmavail=1; ecpsvmlevel=20; break; } break; } ecpsvmavail=1; if (sscanf(secpsvmlevel, "%d%c", &ecpsvmlevel, &c) != 1) { logmsg(_("HHCCF051W Error in %s line %d: " "Invalid ECPSVM keyword : %s. NO Assumed\n"), fname, inc_stmtnum[inc_level], secpsvmlevel); ecpsvmavail=0; ecpsvmlevel=0; break; } else { logmsg(_("HHCCF063W Warning in %s line %d: " "Specifying ECPSVM level directly is deprecated. Use the 'LEVEL' keyword instead.\n"), fname, inc_stmtnum[inc_level]); break; } break; } sysblk.ecpsvm.available=ecpsvmavail; sysblk.ecpsvm.level=ecpsvmlevel; } #endif /*defined(_FEATURE_ECPSVM)*/ #if defined(OPTION_SHARED_DEVICES) /* Parse shared device port number operand */ if (sshrdport != NULL) { if (sscanf(sshrdport, "%hu%c", &shrdport, &c) != 1 || shrdport < 1024 ) { logmsg(_("HHCCF029S Error in %s line %d: " "Invalid SHRDPORT port number %s\n"), fname, inc_stmtnum[inc_level], sshrdport); delayed_exit(1); } } #endif /*defined(OPTION_SHARED_DEVICES)*/ } /* end for(scount) (end of configuration file statement loop) */ /* Read the logofile */ if (sysblk.logofile == NULL) /* LogoFile NOT passed in command line */ { if (hlogofile[0] != '\0') /* LogoFile SET in hercules config */ { readlogo(hlogofile); } else /* Try to Read Logo File using Default FileName */ { slogofile=getenv("HERCLOGO"); if (slogofile==NULL) { readlogo("herclogo.txt"); } else { readlogo(slogofile); } } /* Otherwise Use Internal LOGO */ } else /* LogoFile passed in command line */ { readlogo(sysblk.logofile); } #if defined( OPTION_TAPE_AUTOMOUNT ) /* Define default AUTOMOUNT directory if needed */ if (sysblk.tamdir && sysblk.defdir == NULL) { char cwd[ MAX_PATH ]; TAMDIR *pNewTAMDIR = malloc( sizeof(TAMDIR) ); if (!pNewTAMDIR) { logmsg( _("HHCCF900S Out of memory!\n")); delayed_exit(1); } VERIFY( getcwd( cwd, sizeof(cwd) ) != NULL ); rc = strlen( cwd ); if (cwd[rc-1] != *PATH_SEP) strlcat (cwd, PATH_SEP, sizeof(cwd)); pNewTAMDIR->dir = strdup (cwd); pNewTAMDIR->len = strlen (cwd); pNewTAMDIR->rej = 0; pNewTAMDIR->next = sysblk.tamdir; sysblk.tamdir = pNewTAMDIR; sysblk.defdir = pNewTAMDIR->dir; logmsg(_("HHCCF090I Default Allowed AUTOMOUNT directory = \"%s\"\n"), sysblk.defdir); } #endif /* OPTION_TAPE_AUTOMOUNT */ /* Set root mode in order to set priority */ SETMODE(ROOT); /* Set Hercules base priority */ if (setpriority(PRIO_PGRP, 0, hercprio)) logmsg (_("HHCCF064W Hercules set priority %d failed: %s\n"), hercprio, strerror(errno)); /* Back to user mode */ SETMODE(USER); /* Display Hercules thread information on control panel */ logmsg (_("HHCCF065I Hercules: tid="TIDPAT", pid=%d, pgid=%d, " "priority=%d\n"), thread_id(), getpid(), getpgrp(), getpriority(PRIO_PGRP,0)); #if defined(OPTION_SHARED_DEVICES) sysblk.shrdport = shrdport; #endif /*defined(OPTION_SHARED_DEVICES)*/ #if defined(_370) || defined(_390) if(dfltver) version = #if defined(_900) (sysblk.arch_mode == ARCH_900) ? 0x00 : #endif 0xFD; #endif /* Build CPU identifier */ sysblk.cpuid = ((U64)version << 56) | ((U64)serial << 32) | ((U64)model << 16); /* Reset the clock steering registers */ csr_reset(); /* Set up the system TOD clock offset: compute the number of * microseconds offset to 0000 GMT, 1 January 1900 */ if(sysepoch != 1900 && sysepoch != 1960) { if(sysepoch < 1960) logmsg(_("HHCCF072W SYSEPOCH %04d is deprecated. " "Please specify \"SYSEPOCH 1900 %s%d\".\n"), sysepoch, 1900-sysepoch > 0 ? "+" : "", 1900-sysepoch); else logmsg(_("HHCCF073W SYSEPOCH %04d is deprecated. " "Please specify \"SYSEPOCH 1960 %s%d\".\n"), sysepoch, 1960-sysepoch > 0 ? "+" : "", 1960-sysepoch); } if(sysepoch == 1960 || sysepoch == 1988) ly1960 = TOD_DAY; else ly1960 = 0; sysepoch -= 1900 + yroffset; set_tod_epoch(((sysepoch*365+(sysepoch/4))*-TOD_DAY)+lyear_adjust(sysepoch)+ly1960); sysblk.sysepoch = sysepoch; /* Set the timezone offset */ adjust_tod_epoch((tzoffset/100*3600+(tzoffset%100)*60)*16000000LL); /* Gabor Hoffer (performance option) */ copy_opcode_tables(); /*****************************************************************/ /* Parse configuration file device statements... */ /*****************************************************************/ while(1) { /* First two fields are device number and device type */ sdevnum = keyword; sdevtype = operand; if (sdevnum == NULL || sdevtype == NULL) { logmsg(_("HHCCF035S Error in %s line %d: " "Missing device number or device type\n"), fname, inc_stmtnum[inc_level]); delayed_exit(1); } /* Parse devnum */ rc=parse_and_attach_devices(sdevnum,sdevtype,addargc,addargv); if(rc==-2) { logmsg(_("HHCCF036S Error in %s line %d: " "%s is not a valid device number(s) specification\n"), fname, inc_stmtnum[inc_level], sdevnum); delayed_exit(1); } /* Read next device record from the configuration file */ #if defined( OPTION_ENHANCED_CONFIG_INCLUDE ) while (1) { while (inc_level >= 0 && read_config (fname, inc_fp[inc_level]) ) { fclose (inc_fp[inc_level--]); } if (inc_level < 0 || strcasecmp (keyword, "include") != 0) break; if (++inc_level >= MAX_INC_LEVEL) { logmsg(_( "HHCCF082S Error in %s line %d: " "Maximum nesting level (%d) reached\n"), fname, inc_stmtnum[inc_level-1], MAX_INC_LEVEL); delayed_exit(1); } logmsg( _("HHCCF083I %s Including %s at %d .\n"), fname, operand, inc_stmtnum[inc_level-1]); hostpath(pathname, operand, sizeof(pathname)); inc_fp[inc_level] = fopen (pathname, "r"); if (inc_fp[inc_level] == NULL) { inc_level--; if ( inc_ignore_errors == 1 ) { logmsg(_("HHCCF084W %s Open error ignored file %s: %s\n"), fname, operand, strerror(errno)); continue ; } else { logmsg(_("HHCCF085E %s Open error file %s: %s\n"), fname, operand, strerror(errno)); delayed_exit(1); } } inc_stmtnum[inc_level] = 0; continue; } if (inc_level < 0) #else // !defined( OPTION_ENHANCED_CONFIG_INCLUDE ) if (read_config (fname, inc_fp[inc_level])) #endif // defined( OPTION_ENHANCED_CONFIG_INCLUDE ) break; } /* end while(1) */ #if !defined( OPTION_ENHANCED_CONFIG_INCLUDE ) /* close configuration file */ rc = fclose(inc_fp[inc_level]); #endif // !defined( OPTION_ENHANCED_CONFIG_INCLUDE ) /* Now configure storage. We do this after processing the device * statements so the fork()ed hercifc process won't require as much * virtual storage. We will need to update all the devices too. */ config_storage(mainsize, xpndsize); for (dev = sysblk.firstdev; dev; dev = dev->nextdev) { dev->mainstor = sysblk.mainstor; dev->storkeys = sysblk.storkeys; dev->mainlim = sysblk.mainsize - 1; } #if defined(_FEATURE_REGION_RELOCATE) /* Initialize base zone storage view (SIE compat) */ for(i = 0; i < FEATURE_SIE_MAXZONES; i++) { sysblk.zpb[i].mso = 0; sysblk.zpb[i].msl = (sysblk.mainsize - 1) >> 20; if(sysblk.xpndsize) { sysblk.zpb[i].eso = 0; sysblk.zpb[i].esl = ((size_t)sysblk.xpndsize * XSTORE_PAGESIZE - 1) >> 20; } else { sysblk.zpb[i].eso = -1; sysblk.zpb[i].esl = -1; } } #endif /* Initialize dummy regs. * Dummy regs are used by the panel or gui when the target cpu * (sysblk.pcpu) is not configured (ie cpu_thread not started). */ sysblk.dummyregs.mainstor = sysblk.mainstor; sysblk.dummyregs.psa = (PSA*)sysblk.mainstor; sysblk.dummyregs.storkeys = sysblk.storkeys; sysblk.dummyregs.mainlim = sysblk.mainsize - 1; sysblk.dummyregs.dummy = 1; initial_cpu_reset (&sysblk.dummyregs); sysblk.dummyregs.arch_mode = sysblk.arch_mode; sysblk.dummyregs.hostregs = &sysblk.dummyregs; #ifdef OPTION_SELECT_KLUDGE /* Release the dummy file descriptors */ for (i = 0; i < OPTION_SELECT_KLUDGE; i++) close(dummyfd[i]); #endif /* Set default maximum number of CPUs */ #ifdef _FEATURE_CPU_RECONFIG sysblk.maxcpu = sysblk.arch_mode == ARCH_370 ? numcpu : MAX_CPU_ENGINES; #else sysblk.maxcpu = numcpu; #endif /*_FEATURE_CPU_RECONFIG*/ /* Set maximum number of CPUs to specified value */ if (maxcpu > 0) { sysblk.maxcpu = maxcpu; } /* Check that numcpu does not exceed maxcpu */ if (sysblk.numcpu > sysblk.maxcpu) { logmsg(_("HHCCF086S Error in %s: NUMCPU %d must not exceed MAXCPU %d\n"), fname, sysblk.numcpu, sysblk.maxcpu); delayed_exit(1); } /* Start the CPUs */ OBTAIN_INTLOCK(NULL); for(i = 0; i < numcpu; i++) configure_cpu(i); RELEASE_INTLOCK(NULL); } /* end function build_config */ #endif /*!defined(_GEN_ARCH)*/ hercules-3.07/bootstrap.c000644 000765 000765 00000036750 11321734033 017134 0ustar00jmaynardjmaynard000000 000000 /* BOOTSTRAP.C (c) Copyright Ivan Warren, 2003-2009 */ /* (c) Copyright "Fish" (David B. Trout), 2005-2009 */ /* Hercules executable main module */ // $Id: bootstrap.c 5586 2009-12-31 10:29:11Z rbowler $ /*-------------------------------------------------------------------*/ /* This module is the initial entry point of the Hercules emulator. */ /* The main() function performs platform-specific functions before */ /* calling the impl function which launches the emulator. */ /*-------------------------------------------------------------------*/ #include "hstdinc.h" #include "hercules.h" #if defined(HDL_USE_LIBTOOL) #include "ltdl.h" #endif #if !defined( _MSVC_ ) /*-------------------------------------------------------------------*/ /* For Unix-like platforms, the main() function: */ /* - sets the privilege level */ /* - initializes the LIBTOOL environment */ /* - passes control to the impl() function in impl.c */ /*-------------------------------------------------------------------*/ int main(int ac,char *av[]) { DROP_PRIVILEGES(CAP_SYS_NICE); SET_THREAD_NAME("bootstrap"); #if defined( OPTION_DYNAMIC_LOAD ) && defined( HDL_USE_LIBTOOL ) LTDL_SET_PRELOADED_SYMBOLS(); #endif exit(impl(ac,av)); } #else // defined( _MSVC_ ) /*-------------------------------------------------------------------*/ /* For Windows platforms, the main() function: */ /* - disables the standard CRT invalid parameter handler */ /* - requests a minimum resolution for periodic timers */ /* - sets up an exception trap */ /* - passes control to the impl() function in impl.c */ /* */ /* The purpose of the exception trap is to call a function which */ /* will write a minidump file in the event of a Hercules crash. */ /*-------------------------------------------------------------------*/ #pragma optimize( "", off ) typedef BOOL (MINIDUMPWRITEDUMPFUNC) ( HANDLE hProcess, DWORD ProcessId, HANDLE hDumpFile, MINIDUMP_TYPE DumpType, PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, PMINIDUMP_CALLBACK_INFORMATION CallbackParam ); static MINIDUMPWRITEDUMPFUNC* g_pfnMiniDumpWriteDumpFunc = NULL; static HMODULE g_hDbgHelpDll = NULL; // Global string buffers to prevent C4748 warning: "/GS can not protect // parameters and local variables from local buffer overrun because // optimizations are disabled in function" static WCHAR g_wszHercDrive [ 4 * _MAX_DRIVE ] = {0}; static WCHAR g_wszHercDir [ 4 * _MAX_DIR ] = {0}; static WCHAR g_wszFileDir [ 4 * _MAX_DIR ] = {0}; static WCHAR g_wszHercPath [ 4 * _MAX_PATH ] = {0}; static WCHAR g_wszDumpPath [ 4 * _MAX_PATH ] = {0}; static WCHAR g_wszFileName [ 4 * _MAX_FNAME ] = {0}; static TCHAR g_szSaveTitle[ 512 ] = {0}; static LPCTSTR g_pszTempTitle = _T("{98C1C303-2A9E-11d4-9FF5-0060677l8D04}"); // (forward reference) static void ProcessException( EXCEPTION_POINTERS* pExceptionPtrs ); // (helper macro) #ifndef ARRAYSIZE #define ARRAYSIZE(x) (sizeof(x)/sizeof(x[0])) #endif /////////////////////////////////////////////////////////////////////////////// #include #pragma comment( lib, "Winmm" ) int main(int ac,char *av[]) { int rc = 0; SET_THREAD_NAME("bootstrap"); // Disable default invalid crt parameter handling DISABLE_CRT_INVALID_PARAMETER_HANDLER(); // Request the highest possible time-interval accuracy... timeBeginPeriod( 1 ); // (one millisecond time interval accuracy) // If we're being debugged, then let the debugger // catch the exception. Otherwise, let our exception // handler catch it... if ( IsDebuggerPresent() ) // (are we being debugged?) { rc = impl(ac,av); // (yes, let debugger catch the exception) } else // (not being debugged; use our exception handler) { if (1 && (g_hDbgHelpDll = LoadLibrary(_T("DbgHelp.dll"))) && (g_pfnMiniDumpWriteDumpFunc = (MINIDUMPWRITEDUMPFUNC*) GetProcAddress( g_hDbgHelpDll, _T("MiniDumpWriteDump"))) ) { GetModuleFileNameW( NULL, g_wszHercPath, ARRAYSIZE(g_wszHercPath) ); _wsplitpath( g_wszHercPath, g_wszHercDrive, g_wszHercDir, NULL, NULL ); } SetErrorMode( SEM_NOGPFAULTERRORBOX ); __try { rc = impl(ac,av); // (Hercules, do your thing!) } __except ( fflush(stdout), fflush(stderr), _ftprintf( stderr, _T("]!OOPS!\n") ), fflush(stdout), fflush(stderr), Sleep(10), _tprintf( _T("\n\n") ), _tprintf( _T(" ***************\n") ), _tprintf( _T(" * OOPS! *\n") ), _tprintf( _T(" ***************\n") ), _tprintf( _T("\n") ), _tprintf( _T(" Hercules has crashed!\n") ), _tprintf( _T("\n") ), _tprintf( _T("(you may need to press ENTER if no 'oops!' dialog-box appears)\n") ), _tprintf( _T("\n") ), ProcessException( GetExceptionInformation() ), EXCEPTION_EXECUTE_HANDLER ) { rc = -1; // (indicate error) } } // Each call to "timeBeginPeriod" must be matched with a call to "timeEndPeriod" timeEndPeriod( 1 ); // (no longer care about accurate time intervals) return rc; } /////////////////////////////////////////////////////////////////////////////// static HWND FindConsoleHandle() { HWND hWnd; if (!GetConsoleTitle(g_szSaveTitle,ARRAYSIZE(g_szSaveTitle))) return NULL; if (!SetConsoleTitle(g_pszTempTitle)) return NULL; Sleep(20); hWnd = FindWindow(NULL,g_pszTempTitle); SetConsoleTitle(g_szSaveTitle); return hWnd; } /////////////////////////////////////////////////////////////////////////////// static BOOL CreateMiniDump( EXCEPTION_POINTERS* pExceptionPtrs ); static void ProcessException( EXCEPTION_POINTERS* pExceptionPtrs ) { UINT uiMBFlags = 0 | MB_SYSTEMMODAL | MB_TOPMOST | MB_SETFOREGROUND ; HWND hwndMBOwner = FindConsoleHandle(); if (!hwndMBOwner || !IsWindowVisible(hwndMBOwner)) hwndMBOwner = GetDesktopWindow(); if ( !g_pfnMiniDumpWriteDumpFunc ) { MessageBox ( hwndMBOwner, _T("The creation of a crash dump for analysis by the Hercules ") _T("development team is NOT possible\nbecause the required 'DbgHelp.dll' ") _T("is missing or is not installed or was otherwise not located.") ,_T("OOPS! Hercules has crashed!"), uiMBFlags | MB_ICONERROR | MB_OK ); return; } if ( IDYES == MessageBox ( hwndMBOwner, _T("The creation of a crash dump for further analysis by ") _T("the Hercules development team is strongly suggested.\n\n") _T("Would you like to create a crash dump for ") _T("the Hercules development team to analyze?") ,_T("OOPS! Hercules has crashed!"), uiMBFlags | MB_ICONERROR | MB_YESNO )) { if ( CreateMiniDump( pExceptionPtrs ) ) { MessageBox ( hwndMBOwner, _T("Please send the dump to the Hercules development team for analysis.") ,_T("Dump Complete"), uiMBFlags | MB_ICONEXCLAMATION | MB_OK ); } } } /////////////////////////////////////////////////////////////////////////////// // The following CreateMiniDump functions are based on // Oleg Starodumov's sample at http://www.debuginfo.com static void BuildUserStreams( MINIDUMP_USER_STREAM_INFORMATION* pMDUSI ); static BOOL CALLBACK MyMiniDumpCallback // (fwd ref) ( PVOID pParam, const PMINIDUMP_CALLBACK_INPUT pInput, PMINIDUMP_CALLBACK_OUTPUT pOutput ); static BOOL CreateMiniDump( EXCEPTION_POINTERS* pExceptionPtrs ) { BOOL bSuccess = FALSE; HANDLE hDumpFile; _wmakepath( g_wszDumpPath, g_wszHercDrive, g_wszHercDir, L"Hercules", L".dmp" ); _tprintf( _T("Creating crash dump \"%ls\"...\n"), g_wszDumpPath ); _tprintf( _T("Please wait; this may take a few minutes...\n") ); _tprintf( _T("(another message will appear when the dump is complete)\n") ); hDumpFile = CreateFileW ( g_wszDumpPath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL ); if ( hDumpFile && INVALID_HANDLE_VALUE != hDumpFile ) { // Create the minidump MINIDUMP_EXCEPTION_INFORMATION mdei; MINIDUMP_USER_STREAM_INFORMATION mdusi; MINIDUMP_CALLBACK_INFORMATION mci; MINIDUMP_TYPE mdt; BuildUserStreams( &mdusi ); mdei.ThreadId = GetCurrentThreadId(); mdei.ExceptionPointers = pExceptionPtrs; mdei.ClientPointers = FALSE; mci.CallbackRoutine = (MINIDUMP_CALLBACK_ROUTINE) MyMiniDumpCallback; mci.CallbackParam = 0; mdt = (MINIDUMP_TYPE) (0 | MiniDumpWithPrivateReadWriteMemory | MiniDumpWithDataSegs | MiniDumpWithHandleData // | MiniDumpWithFullMemoryInfo // | MiniDumpWithThreadInfo | MiniDumpWithUnloadedModules ); bSuccess = g_pfnMiniDumpWriteDumpFunc( GetCurrentProcess(), GetCurrentProcessId(), hDumpFile, mdt, (pExceptionPtrs != 0) ? &mdei : 0, &mdusi, &mci ); CloseHandle( hDumpFile ); if ( bSuccess ) { _tprintf( _T("Dump \"%ls\" created.\n"), g_wszDumpPath ); } else _tprintf( _T("MiniDumpWriteDump failed! Error: %u\n"), GetLastError() ); } else { _tprintf( _T("CreateFile failed! Error: %u\n"), GetLastError() ); } return bSuccess; } /////////////////////////////////////////////////////////////////////////////// // Build User Stream Arrays... #define MAX_MINIDUMP_USER_STREAMS (64) static char g_host_info_str [ 1024 ]; static MINIDUMP_USER_STREAM UserStreamArray [ MAX_MINIDUMP_USER_STREAMS ]; static void BuildUserStreams( MINIDUMP_USER_STREAM_INFORMATION* pMDUSI ) { const char** ppszBldInfoStr; int nNumBldInfoStrs; ULONG UserStreamCount; _ASSERTE( pMDUSI ); get_hostinfo_str( NULL, g_host_info_str, sizeof(g_host_info_str) ); nNumBldInfoStrs = get_buildinfo_strings( &ppszBldInfoStr ); UserStreamCount = min( (3+nNumBldInfoStrs), MAX_MINIDUMP_USER_STREAMS ); pMDUSI->UserStreamCount = UserStreamCount; pMDUSI->UserStreamArray = UserStreamArray; UserStreamCount = 0; if ( UserStreamCount < pMDUSI->UserStreamCount ) { UserStreamArray[UserStreamCount].Type = CommentStreamA; UserStreamArray[UserStreamCount].Buffer = VERSION; UserStreamArray[UserStreamCount].BufferSize = sizeof(VERSION); UserStreamCount++; } if ( UserStreamCount < pMDUSI->UserStreamCount ) { UserStreamArray[UserStreamCount].Type = CommentStreamA; UserStreamArray[UserStreamCount].Buffer = HERCULES_COPYRIGHT; UserStreamArray[UserStreamCount].BufferSize = sizeof(HERCULES_COPYRIGHT); UserStreamCount++; } if ( UserStreamCount < pMDUSI->UserStreamCount ) { UserStreamArray[UserStreamCount].Type = CommentStreamA; UserStreamArray[UserStreamCount].Buffer = g_host_info_str; UserStreamArray[UserStreamCount].BufferSize = strlen(g_host_info_str)+1; UserStreamCount++; } for (; nNumBldInfoStrs && UserStreamCount < pMDUSI->UserStreamCount; nNumBldInfoStrs--, UserStreamCount++, ppszBldInfoStr++ ) { UserStreamArray[UserStreamCount].Type = CommentStreamA; UserStreamArray[UserStreamCount].Buffer = (PVOID)*ppszBldInfoStr; UserStreamArray[UserStreamCount].BufferSize = strlen(*ppszBldInfoStr)+1; } } /////////////////////////////////////////////////////////////////////////////// // Custom minidump callback static BOOL IsDataSectionNeeded( const WCHAR* pwszModuleName ); // (fwd ref) static BOOL CALLBACK MyMiniDumpCallback ( PVOID pParam, const PMINIDUMP_CALLBACK_INPUT pInput, PMINIDUMP_CALLBACK_OUTPUT pOutput ) { BOOL bRet = FALSE; if ( !pInput || !pOutput ) return FALSE; switch ( pInput->CallbackType ) { case IncludeModuleCallback: { // Include the module into the dump bRet = TRUE; } break; case IncludeThreadCallback: { // Include the thread into the dump bRet = TRUE; } break; case ModuleCallback: { // Are data sections available for this module ? if ( pOutput->ModuleWriteFlags & ModuleWriteDataSeg ) { // Yes, but do we really need them? if ( !IsDataSectionNeeded( pInput->Module.FullPath ) ) pOutput->ModuleWriteFlags &= (~ModuleWriteDataSeg); } bRet = TRUE; } break; case ThreadCallback: { // Include all thread information into the minidump bRet = TRUE; } break; case ThreadExCallback: { // Include this information bRet = TRUE; } break; /* NOTE About MemoryCallback : * This is defined for DbgHelp > 6.1.. * Since "false" is returned, it has been commented out. * * Additionally, false is now returned by default. This * ensures that the callback function will operate correctly * even with future versions of the DbhHelp DLL. * -- Ivan */ // case MemoryCallback: // { // // We do not include any information here -> return FALSE // bRet = FALSE; // } // break; // Following default block added by ISW 2005/05/06 default: { // Do not return any information for unrecognized // callback types. bRet=FALSE; } break; // case CancelCallback: // break; } return bRet; } /////////////////////////////////////////////////////////////////////////////// // This function determines whether we need data sections of the given module static BOOL IsDataSectionNeeded( const WCHAR* pwszModuleName ) { BOOL bNeeded = FALSE; _ASSERTE( pwszModuleName ); _wsplitpath( pwszModuleName, NULL, g_wszFileDir, g_wszFileName, NULL ); if ( _wcsicmp( g_wszFileName, L"ntdll" ) == 0 ) { bNeeded = TRUE; } else if ( _wcsicmp( g_wszFileDir, g_wszHercDir ) == 0 ) { bNeeded = TRUE; } return bNeeded; } /////////////////////////////////////////////////////////////////////////////// #pragma optimize( "", on ) #endif // !defined( _MSVC_ ) hercules-3.07/build_pch.c000644 000765 000765 00000000627 11143760543 017051 0ustar00jmaynardjmaynard000000 000000 /* BUILD_PCH (c)Copyright Ivan Warren, 2005-2009 */ /* Dummy module for building pre-compiled header files */ // $Id: build_pch.c 5125 2009-01-23 12:01:44Z bernard $ // // $Log$ // Revision 1.5 2007/06/23 00:04:03 ivan // Update copyright notices to include current year (2007) // // Revision 1.4 2006/12/08 09:43:16 jj // Add CVS message log // #include "hstdinc.h" hercules-3.07/cache.c000644 000765 000765 00000037514 11143760543 016170 0ustar00jmaynardjmaynard000000 000000 /* CACHE.C (c)Copyright Greg Smith, 2002-2009 */ /* Dynamic cache manager for multi-threaded applications */ //FIXME ?? Dynamic resizing is disabled // $Id: cache.c 5125 2009-01-23 12:01:44Z bernard $ // // $Log$ // Revision 1.16 2007/06/23 00:04:03 ivan // Update copyright notices to include current year (2007) // // Revision 1.15 2006/12/08 09:43:16 jj // Add CVS message log // #include "hstdinc.h" #define _CACHE_C_ #define _HDASD_DLL_ #include "hercules.h" static CACHEBLK cacheblk[CACHE_MAX_INDEX]; /*-------------------------------------------------------------------*/ /* Public functions */ /*-------------------------------------------------------------------*/ int cache_nbr (int ix) { if (cache_check_ix(ix)) return -1; return cacheblk[ix].nbr; } int cache_busy (int ix) { if (cache_check_ix(ix)) return -1; return cacheblk[ix].busy; } int cache_empty (int ix) { if (cache_check_ix(ix)) return -1; return cacheblk[ix].empty; } int cache_waiters (int ix) { if (cache_check_ix(ix)) return -1; return cacheblk[ix].waiters; } long long cache_size (int ix) { if (cache_check_ix(ix)) return -1; return cacheblk[ix].size; } long long cache_hits (int ix) { if (cache_check_ix(ix)) return -1; return cacheblk[ix].hits; } long long cache_misses (int ix) { if (cache_check_ix(ix)) return -1; return cacheblk[ix].misses; } int cache_busy_percent (int ix) { if (cache_check_ix(ix)) return -1; return (cacheblk[ix].busy * 100) / cacheblk[ix].nbr; } int cache_empty_percent (int ix) { if (cache_check_ix(ix)) return -1; return (cacheblk[ix].empty * 100) / cacheblk[ix].nbr; } int cache_hit_percent (int ix) { long long total; if (cache_check_ix(ix)) return -1; total = cacheblk[ix].hits + cacheblk[ix].misses; if (total == 0) return -1; return (int)((cacheblk[ix].hits * 100) / total); } int cache_lookup (int ix, U64 key, int *o) { int i,p; if (o) *o = -1; if (cache_check_ix(ix)) return -1; /* `p' is the preferred index */ p = (int)(key % cacheblk[ix].nbr); if (cacheblk[ix].cache[p].key == key) { i = p; cacheblk[ix].fasthits++; } else { if (cache_isbusy(ix, p) || cacheblk[ix].age - cacheblk[ix].cache[p].age < 20) p = -2; for (i = 0; i < cacheblk[ix].nbr; i++) { if (cacheblk[ix].cache[i].key == key) break; if (o && !cache_isbusy(ix, i) && (*o < 0 || i == p || cacheblk[ix].cache[i].age < cacheblk[ix].cache[*o].age)) if (*o != p) *o = i; } } if (i >= cacheblk[ix].nbr) { i = -1; cacheblk[ix].misses++; } else cacheblk[ix].hits++; if (i < 0 && o && *o < 0) cache_adjust(ix,1); else cache_adjust(ix, 0); return i; } int cache_scan (int ix, CACHE_SCAN_RTN rtn, void *data) { int i; /* Cache index */ int rc; /* Return code */ int answer = -1; /* Answer from routine */ if (cache_check_ix(ix)) return -1; for (i = 0; i < cacheblk[ix].nbr; i++) { rc = (rtn)(&answer, ix, i, data); if (rc != 0) break; } return answer; } int cache_lock(int ix) { if (cache_check_cache(ix)) return -1; obtain_lock(&cacheblk[ix].lock); return 0; } int cache_unlock(int ix) { if (cache_check_ix(ix)) return -1; release_lock(&cacheblk[ix].lock); if (cacheblk[ix].empty == cacheblk[ix].nbr) cache_destroy(ix); return 0; } int cache_wait(int ix) { struct timeval now; struct timespec tm; if (cache_check_ix(ix)) return -1; if (cacheblk[ix].busy < cacheblk[ix].nbr) return 0; if (cache_adjust(ix, 1)) return 0; gettimeofday (&now, NULL); tm.tv_sec = now.tv_sec; tm.tv_nsec = (now.tv_usec + CACHE_WAITTIME) * 1000; tm.tv_sec += tm.tv_nsec / 1000000000; tm.tv_nsec = tm.tv_nsec % 1000000000; cacheblk[ix].waiters++; cacheblk[ix].waits++; #if 0 timed_wait_condition(&cacheblk[ix].waitcond, &cacheblk[ix].lock, &tm); #else wait_condition(&cacheblk[ix].waitcond, &cacheblk[ix].lock); #endif cacheblk[ix].waiters--; return 0; } U64 cache_getkey(int ix, int i) { if (cache_check(ix,i)) return (U64)-1; return cacheblk[ix].cache[i].key; } U64 cache_setkey(int ix, int i, U64 key) { U64 oldkey; int empty; if (cache_check(ix,i)) return (U64)-1; empty = cache_isempty(ix, i); oldkey = cacheblk[ix].cache[i].key; cacheblk[ix].cache[i].key = key; if (empty && !cache_isempty(ix, i)) cacheblk[ix].empty--; else if (!empty && cache_isempty(ix, i)) cacheblk[ix].empty++; return oldkey; } U32 cache_getflag(int ix, int i) { if (cache_check(ix,i)) return (U32)-1; return cacheblk[ix].cache[i].flag; } U32 cache_setflag(int ix, int i, U32 andbits, U32 orbits) { U32 oldflags; int empty; int busy; if (cache_check(ix,i)) return (U32)-1; empty = cache_isempty(ix, i); busy = cache_isbusy(ix, i); oldflags = cacheblk[ix].cache[i].flag; cacheblk[ix].cache[i].flag &= andbits; cacheblk[ix].cache[i].flag |= orbits; if (!cache_isbusy(ix, i) && cacheblk[ix].waiters > 0) signal_condition(&cacheblk[ix].waitcond); if (busy && !cache_isbusy(ix, i)) cacheblk[ix].busy--; else if (!busy && cache_isbusy(ix, i)) cacheblk[ix].busy++; if (empty && !cache_isempty(ix, i)) cacheblk[ix].empty--; else if (!empty && cache_isempty(ix, i)) cacheblk[ix].empty++; return oldflags; } U64 cache_getage(int ix, int i) { if (cache_check(ix,i)) return (U64)-1; return cacheblk[ix].cache[i].age; } U64 cache_setage(int ix, int i) { U64 oldage; int empty; if (cache_check(ix,i)) return (U64)-1; empty = cache_isempty(ix, i); oldage = cacheblk[ix].cache[i].age; cacheblk[ix].cache[i].age = ++cacheblk[ix].age; if (empty) cacheblk[ix].empty--; return oldage; } void *cache_getbuf(int ix, int i, int len) { if (cache_check(ix,i)) return NULL; if (len > 0 && cacheblk[ix].cache[i].buf != NULL && cacheblk[ix].cache[i].len < len) { cacheblk[ix].size -= cacheblk[ix].cache[i].len; free (cacheblk[ix].cache[i].buf); cacheblk[ix].cache[i].buf = NULL; cacheblk[ix].cache[i].len = 0; } if (cacheblk[ix].cache[i].buf == NULL && len > 0) cache_allocbuf (ix, i, len); return cacheblk[ix].cache[i].buf; } void *cache_setbuf(int ix, int i, void *buf, int len) { void *oldbuf; if (cache_check(ix,i)) return NULL; oldbuf = cacheblk[ix].cache[i].buf; cacheblk[ix].size -= cacheblk[ix].cache[i].len; cacheblk[ix].cache[i].buf = buf; cacheblk[ix].cache[i].len = len; cacheblk[ix].size += len; return oldbuf; } int cache_getlen(int ix, int i) { if (cache_check(ix,i)) return -1; return cacheblk[ix].cache[i].len; } int cache_getval(int ix, int i) { if (cache_check(ix,i)) return -1; return cacheblk[ix].cache[i].value; } int cache_setval(int ix, int i, int val) { int rc; if (cache_check(ix,i)) return -1; rc = cacheblk[ix].cache[i].value; cacheblk[ix].cache[i].value = val; return rc; } int cache_release(int ix, int i, int flag) { void *buf; int len; int empty; int busy; if (cache_check(ix,i)) return -1; empty = cache_isempty(ix, i); busy = cache_isbusy(ix, i); buf = cacheblk[ix].cache[i].buf; len = cacheblk[ix].cache[i].len; memset (&cacheblk[ix].cache[i], 0, sizeof(CACHE)); if ((flag & CACHE_FREEBUF) && buf != NULL) { free (buf); cacheblk[ix].size -= len; buf = NULL; len = 0; } cacheblk[ix].cache[i].buf = buf; cacheblk[ix].cache[i].len = len; if (cacheblk[ix].waiters > 0) signal_condition(&cacheblk[ix].waitcond); if (!empty) cacheblk[ix].empty++; if (busy) cacheblk[ix].busy--; return 0; } DLL_EXPORT int cache_cmd(int argc, char *argv[], char *cmdline) { int ix, i; UNREFERENCED(cmdline); UNREFERENCED(argc); UNREFERENCED(argv); for (ix = 0; ix < CACHE_MAX_INDEX; ix++) { if (cacheblk[ix].magic != CACHE_MAGIC) { logmsg ("cache[%d] ....... not created\n", ix); continue; } logmsg ("\n" "cache............ %10d\n" "nbr ............. %10d\n" "busy ............ %10d\n" "busy%% ........... %10d\n" "empty ........... %10d\n" "waiters ......... %10d\n" "waits ........... %10d\n" "buf size ........ %10" I64_FMT "d\n" "hits ............ %10" I64_FMT "d\n" "fast hits ....... %10" I64_FMT "d\n" "misses .......... %10" I64_FMT "d\n" "hit%% ............ %10d\n" "age ............. %10" I64_FMT "d\n" "last adjusted ... %s" "last wait ....... %s" "adjustments ..... %10d\n", ix, cacheblk[ix].nbr, cacheblk[ix].busy, cache_busy_percent(ix), cacheblk[ix].empty, cacheblk[ix].waiters, cacheblk[ix].waits, cacheblk[ix].size, cacheblk[ix].hits, cacheblk[ix].fasthits, cacheblk[ix].misses, cache_hit_percent(ix), cacheblk[ix].age, ctime(&cacheblk[ix].atime), ctime(&cacheblk[ix].wtime), cacheblk[ix].adjusts); if (argc > 1) for (i = 0; i < cacheblk[ix].nbr; i++) logmsg ("[%4d] %16.16" I64_FMT "x %8.8x %10p %6d %10" I64_FMT "d\n", i, cacheblk[ix].cache[i].key, cacheblk[ix].cache[i].flag, cacheblk[ix].cache[i].buf, cacheblk[ix].cache[i].len, cacheblk[ix].cache[i].age); } return 0; } /*-------------------------------------------------------------------*/ /* Private functions */ /*-------------------------------------------------------------------*/ static int cache_create (int ix) { cache_destroy (ix); cacheblk[ix].magic = CACHE_MAGIC; //FIXME See the note in cache.h about CACHE_DEFAULT_L2_NBR cacheblk[ix].nbr = ix != CACHE_L2 ? CACHE_DEFAULT_NBR : CACHE_DEFAULT_L2_NBR; cacheblk[ix].empty = cacheblk[ix].nbr; initialize_lock (&cacheblk[ix].lock); initialize_condition (&cacheblk[ix].waitcond); cacheblk[ix].cache = calloc (cacheblk[ix].nbr, sizeof(CACHE)); if (cacheblk[ix].cache == NULL) { logmsg (_("HHCCH001E calloc failed cache[%d] size %d: %s\n"), ix, cacheblk[ix].nbr * sizeof(CACHE), strerror(errno)); return -1; } return 0; } static int cache_destroy (int ix) { int i; if (cacheblk[ix].magic == CACHE_MAGIC) { destroy_lock (&cacheblk[ix].lock); destroy_condition (&cacheblk[ix].waitcond); if (cacheblk[ix].cache) { for (i = 0; i < cacheblk[ix].nbr; i++) cache_release(ix, i, CACHE_FREEBUF); free (cacheblk[ix].cache); } } memset(&cacheblk[ix], 0, sizeof(CACHEBLK)); return 0; } static int cache_check_ix(int ix) { if (ix < 0 || ix >= CACHE_MAX_INDEX) return -1; return 0; } static int cache_check_cache(int ix) { if (cache_check_ix(ix) || (cacheblk[ix].magic != CACHE_MAGIC && cache_create(ix))) return -1; return 0; } static int cache_check(int ix, int i) { if (cache_check_ix(ix) || i < 0 || i >= cacheblk[ix].nbr) return -1; return 0; } static int cache_isbusy(int ix, int i) { return ((cacheblk[ix].cache[i].flag & CACHE_BUSY) != 0); } static int cache_isempty(int ix, int i) { return (cacheblk[ix].cache[i].key == 0 && cacheblk[ix].cache[i].flag == 0 && cacheblk[ix].cache[i].age == 0); } static int cache_adjust(int ix, int n) { #if 0 time_t now; int busypct, hitpct, nbr, empty, sz; now = time(NULL); busypct = cache_busy_percent(ix); hitpct = cache_hit_percent(ix); nbr = cacheblk[ix].nbr; empty = cache_empty(ix); sz = cacheblk[ix].size; if (n == 0) { /* Normal adjustments */ if (now - cacheblk[ix].atime < CACHE_ADJUST_INTERVAL) return 0; cacheblk[ix].atime = now; /* Increase cache if a lot of busy entries */ if (((nbr <= CACHE_ADJUST_NUMBER || sz < CACHE_ADJUST_SIZE) && busypct >= CACHE_ADJUST_BUSY1) || busypct > CACHE_ADJUST_BUSY2) return cache_resize(ix, CACHE_ADJUST_RESIZE); /* Decrease cache if too many empty entries */ if (nbr > CACHE_ADJUST_NUMBER && empty >= CACHE_ADJUST_EMPTY) return cache_resize(ix, -CACHE_ADJUST_RESIZE); /* Increase cache if hit percentage is too low */ if (hitpct > 0) { if ((nbr <= CACHE_ADJUST_NUMBER && hitpct < CACHE_ADJUST_HIT1) || hitpct < CACHE_ADJUST_HIT2) return cache_resize(ix, CACHE_ADJUST_RESIZE); } /* Decrease cache if hit percentage is ok and not many busy */ if (hitpct >= CACHE_ADJUST_HIT3 && busypct <= CACHE_ADJUST_BUSY3 && cacheblk[ix].size >= CACHE_ADJUST_SIZE) return cache_resize(ix, -CACHE_ADJUST_RESIZE); } else { /* All cache entries are busy */ if (nbr <= CACHE_ADJUST_NUMBER) return cache_resize(ix, CACHE_ADJUST_RESIZE); /* Increase cache if previous wait within this interval */ if (now - cacheblk[ix].wtime <= CACHE_ADJUST_WAITTIME) { return cache_resize(ix, CACHE_ADJUST_RESIZE); } cacheblk[ix].wtime = now; } #else UNREFERENCED(ix); UNREFERENCED(n); #endif return 0; } #if 0 static int cache_resize (int ix, int n) { CACHE *cache; int i; if (n == 0) return 0; else if (n > 0) { /* Increase cache size */ cache = realloc (cacheblk[ix].cache, (cacheblk[ix].nbr + n) * sizeof(CACHE)); if (cache == NULL) { logmsg (_("HHCCH002W realloc increase failed cache[%d] size %d: %s\n"), ix, (cacheblk[ix].nbr + n) * sizeof(CACHE), strerror(errno)); return 0; } cacheblk[ix].cache = cache; for (i = cacheblk[ix].nbr; i < cacheblk[ix].nbr +n; i++) memset(&cacheblk[ix].cache[i], 0, sizeof(CACHE)); cacheblk[ix].nbr += n; cacheblk[ix].empty += n; cacheblk[ix].adjusts++; } else if (n < 0) { /* Decrease cache size */ for (i = cacheblk[ix].nbr - 1; i >= cacheblk[ix].nbr + n; i--) if (cache_isbusy(ix, i)) break; else cache_release(ix, i, CACHE_FREEBUF); n = cacheblk[ix].nbr - i + 1; if (n == 0) return 0; cache = realloc (cacheblk[ix].cache, (cacheblk[ix].nbr - n) * sizeof(CACHE)); if (cache == NULL) { logmsg (_("HHCCH003W realloc decrease failed cache[%d] size %d: %s\n"), ix, (cacheblk[ix].nbr - n) * sizeof(CACHE), strerror(errno)); return 0; } cacheblk[ix].cache = cache; cacheblk[ix].nbr -= n; cacheblk[ix].empty -= n; cacheblk[ix].adjusts++; } return 1; } #endif static void cache_allocbuf(int ix, int i, int len) { cacheblk[ix].cache[i].buf = calloc (len, 1); if (cacheblk[ix].cache[i].buf == NULL) { logmsg (_("HHCCH004W buf calloc failed cache[%d] size %d: %s\n"), ix, len, strerror(errno)); logmsg (_("HHCCH005W releasing inactive buffer space\n")); for (i = 0; i < cacheblk[ix].nbr; i++) if (!cache_isbusy(ix, i)) cache_release(ix, i, CACHE_FREEBUF); cacheblk[ix].cache[i].buf = calloc (len, 1); if (cacheblk[ix].cache[i].buf == NULL) { logmsg (_("HHCCH006E Unable to calloc buf cache[%d] size %d: %s\n"), ix, len, strerror(errno)); return; } } cacheblk[ix].cache[i].len = len; cacheblk[ix].size += len; } hercules-3.07/cache.h000644 000765 000765 00000042425 11143760543 016172 0ustar00jmaynardjmaynard000000 000000 /* CACHE.H (c)Copyright Greg Smith, 2002-2009 */ /* Buffer Cache Manager */ // $Id: cache.h 5125 2009-01-23 12:01:44Z bernard $ /*------------------------------------------------------------------- Description: Manages multiple caches in a multi-threaded environment. A cache is dynamically created and destroyed. It's size or number of entries is also dynamically determined. A cache entry contains an identifying `key', `flags' which indicate whether an entry is busy or not, and a `buf' which is a pointer to the cached object. Cache entry: The structure of a cache entry is: U64 key; U32 flag; int len; void *buf; int value; U64 age; The first 8 bits of the flag indicates if the entry is `busy' or not. If any of the first 8 bits are non-zero then the entry is considered `busy' and will not be stolen or otherwise reused. APIs: General query functions: int cache_nbr(int ix); [0] Number of entries int cache_busy(int ix); Number of busy entries int cache_empty(int ix); Number of empty entries [1] int cache_waiters(int ix); Number of waiters for a non-busy cache entry long long cache_size(int ix); Size of all allocated objects long long cache_hits(int ix); Number of successful lookups long long cache_misses(int ix); Number of unsuccessful lookups int cache_busy_percent(int ix); Percentage (0 .. 100) of entries that are busy int cache_empty_percent(int ix); Percentage of entries that are empty [1] int cache_hit_percent(int ix); Percentage of successful lookups to total lookups Notes [0] `ix' identifies the cache. This is an integer and is reserved in `cache.h' [1] An empty entry contains a zero key value. A valid key should not be all zeroes (0x0000000000000000) or all ones (0xffffffffffffffff). All ones is used to indicate an error circumstance. Entry specific functions: U64 cache_getkey(int ix, int i); [0] Return key for the specified cache entry U64 cache_setkey(int ix, int i, U64 key); Set the key for the specified cache entry; the old key is returned U32 cache_getflag(int ix, int i); Return the flag for the specified cache entry U32 cache_setflag(int ix, int i, U32 andbits, U32 orbits); Set the flag for the specified cache entry; first the `andbits' value is `and'ed against the entry then the `orbits' value is `or'ed against the entry. The old flag is returned. U64 cache_getage(int ix, int i); [1] Return age for the specified cache entry U64 cache_setage(int ix, int i); Set age for the specified cache entry void *cache_getbuf(int ix, int i, int len); Return address of the object buf for the cache entry. If `len' is non-zero, then if the current object is null or `len' is greater than the current object length then the old object is freed and a new object is obtained. void *cache_setbuf(int ix, int i, void *buf, int len); The old object address and length is replaced. The address of the old object is returned and can be freed using `free()'. int cache_getlen(int ix, int i); Return the length of the current object Notes [0] `i' is the index of the entry in cache `ix' [1] `age' is a sequentially incremented value and does not correspond to date or time Locking functions: int cache_lock(int ix); Obtain the lock for cache `ix'. If the cache does not exist then it will be created. Generally, the lock should be obtained when referencing cache entries and must be held when a cache entry status may change from `busy' to `not busy' or vice versa. Likewise, the lock must be held when a cache entry changes from `empty' to `not empty' or vice versa. int cache_unlock(int ix); Release the cache lock Search functions: int cache_lookup(int ix, U64 key, int *o); Search cache `ix' for entry matching `key'. If a non-NULL pointer `o' is provided, then the oldest or preferred cache entry index is returned that is available to be stolen. int cache_scan (int ix, int (rtn)(), void *data); Scan a cache routine entry by entry calling routine `rtn'. Parameters passed to the routine are `(int *answer, int ix, int i, void *data)' where `ix' is the cache index, `i' is the cache entry index and `data' is the value passed to cache_scan. `*answer' is initialized to -1 and can be set by the scan subroutine. This will be the value returned by cache_scan. If the routine returns a non-zero value then the scan is terminated. Other functions: int cache_wait(int ix); Wait for a non-busy cache entry to become available. Typically called after `cache_lookup' was unsuccessful and `*o' is -1. int cache_release(int ix, int i, int flag); Release the cache entry. If flag is CACHE_FREEBUF then the object buffer is also freed. int cache_cmd(int argc, char *argv[], char *cmdline); Interface with the cache command processor. This interface is subject to change. -------------------------------------------------------------------*/ // $Log$ // Revision 1.14 2007/06/23 00:04:03 ivan // Update copyright notices to include current year (2007) // // Revision 1.13 2006/12/08 09:43:16 jj // Add CVS message log // #ifndef _HERCULES_CACHE_H #define _HERCULES_CACHE_H 1 #include "hercules.h" #ifndef _CACHE_C_ #ifndef _HDASD_DLL_ #define CCH_DLL_IMPORT DLL_IMPORT #else /* _HDASD_DLL_ */ #define CCH_DLL_IMPORT extern #endif /* _HDASD_DLL_ */ #else #define CCH_DLL_IMPORT DLL_EXPORT #endif /*-------------------------------------------------------------------*/ /* Reserve cache indexes here */ /*-------------------------------------------------------------------*/ #define CACHE_MAX_INDEX 8 /* Max number caches [0..7] */ #define CACHE_DEVBUF 0 /* Device Buffer cache */ #define CACHE_L2 1 /* L2 cache */ #define CACHE_2 2 /* (available) */ #define CACHE_3 3 /* (available) */ #define CACHE_4 4 /* (available) */ #define CACHE_5 5 /* (available) */ #define CACHE_6 6 /* (available) */ #define CACHE_7 7 /* (available) */ #ifdef _CACHE_C_ /*-------------------------------------------------------------------*/ /* Cache entry */ /*-------------------------------------------------------------------*/ typedef struct _CACHE { /* Cache entry */ U64 key; /* Key */ U32 flag; /* Flags */ int len; /* Buffer length */ void *buf; /* Buffer address */ int value; /* Arbitrary value */ U64 age; /* Age */ } CACHE; /*-------------------------------------------------------------------*/ /* Cache header */ /*-------------------------------------------------------------------*/ typedef struct _CACHEBLK { /* Cache header */ int magic; /* Magic number */ int nbr; /* Number entries */ int busy; /* Number busy entries */ int empty; /* Number empty entries */ int waiters; /* Number waiters */ int waits; /* Number times waited */ long long size; /* Allocated buffer size */ long long hits; /* Number lookup hits */ long long fasthits; /* Number fast lookup hits */ long long misses; /* Number lookup misses */ U64 age; /* Age counter */ LOCK lock; /* Lock */ COND waitcond; /* Wait for available entry */ CACHE *cache; /* Cache table address */ time_t atime; /* Time last adjustment */ time_t wtime; /* Time last wait */ int adjusts; /* Number of adjustments */ } CACHEBLK; #endif /*-------------------------------------------------------------------*/ /* Flag definitions */ /*-------------------------------------------------------------------*/ #define CACHE_BUSY 0xFF000000 /* Busy bits */ #define CACHE_TYPE 0x000000FF /* Type bits */ #define CACHE_FREEBUF 1 /* Free buf on release */ #ifdef _CACHE_C_ #define CACHE_MAGIC 0x01CACE10 /* Magic number */ #define CACHE_DEFAULT_NBR 229 /* Initial entries (prime) */ //FIXME the line below increases the size for CACHE_L2. Since each // cckd device always has an active l2 entry this number // actually limits the number of cckd devices that can be // attached. // This is a workaround to increase the max number of devices #define CACHE_DEFAULT_L2_NBR 1031 /* Initial entries for L2 */ #define CACHE_WAITTIME 1000 /* Wait time for entry(usec) */ #define CACHE_ADJUST_INTERVAL 15 /* Adjustment interval (sec) */ #define CACHE_ADJUST_NUMBER 128 /* Uninhibited nbr entries */ #define CACHE_ADJUST_BUSY1 70 /* Increase when this busy 1 */ #define CACHE_ADJUST_BUSY2 80 /* Increase when this busy 2 */ #define CACHE_ADJUST_RESIZE 8 /* Nbr entries adjusted */ #define CACHE_ADJUST_EMPTY 16 /* Decrease this many empty */ #define CACHE_ADJUST_HIT1 60 /* Increase hit% this low 1 */ #define CACHE_ADJUST_HIT2 50 /* Increase hit% this low 2 */ #define CACHE_ADJUST_BUSY3 20 /* Decrease not this busy */ #define CACHE_ADJUST_HIT3 90 /* and hit% this high */ #define CACHE_ADJUST_SIZE (8*1024*1024)/* and size this high */ #define CACHE_ADJUST_WAITTIME 10 /* Increase last wait (sec) */ #endif /*-------------------------------------------------------------------*/ /* Functions */ /*-------------------------------------------------------------------*/ int cache_nbr(int ix); int cache_busy(int ix); int cache_empty(int ix); int cache_waiters(int ix); long long cache_size(int ix); long long cache_hits(int ix); long long cache_misses(int ix); int cache_busy_percent(int ix); int cache_empty_percent(int ix); int cache_hit_percent(int ix); int cache_lookup(int ix, U64 key, int *o); typedef int CACHE_SCAN_RTN (int *answer, int ix, int i, void *data); int cache_scan (int ix, CACHE_SCAN_RTN rtn, void *data); int cache_lock(int ix); int cache_unlock(int ix); int cache_wait(int ix); U64 cache_getkey(int ix, int i); U64 cache_setkey(int ix, int i, U64 key); U32 cache_getflag(int ix, int i); U32 cache_setflag(int ix, int i, U32 andbits, U32 orbits); U64 cache_getage(int ix, int i); U64 cache_setage(int ix, int i); void *cache_getbuf(int ix, int i, int len); void *cache_setbuf(int ix, int i, void *buf, int len); int cache_getlen(int ix, int i); int cache_getval(int ix, int i); int cache_setval(int ix, int i, int val); int cache_release(int ix, int i, int flag); CCH_DLL_IMPORT int cache_cmd(int argc, char *argv[], char *cmdline); #ifdef _CACHE_C_ static int cache_create (int ix); static int cache_destroy (int ix); static int cache_check_ix(int ix); static int cache_check_cache(int ix); static int cache_check(int ix, int i); static int cache_isbusy(int ix, int i); static int cache_isempty(int ix, int i); static int cache_adjust(int ix, int n); #if 0 static int cache_resize (int ix, int n); #endif static void cache_allocbuf(int ix, int i, int len); #endif /*-------------------------------------------------------------------*/ /* Specific cache definitions (until a better place is found) */ /*-------------------------------------------------------------------*/ /*-------------------------------------------------------------------*/ /* Device buffer definitions */ /*-------------------------------------------------------------------*/ #define CCKD_CACHE_ACTIVE 0x80000000 /* Active entry */ #define CCKD_CACHE_READING 0x40000000 /* Entry being read */ #define CCKD_CACHE_WRITING 0x20000000 /* Entry being written */ #define CCKD_CACHE_IOBUSY (CCKD_CACHE_READING|CCKD_CACHE_WRITING) #define CCKD_CACHE_IOWAIT 0x10000000 /* Waiters for i/o */ #define CCKD_CACHE_UPDATED 0x08000000 /* Buffer has been updated */ #define CCKD_CACHE_WRITE 0x04000000 /* Entry pending write */ #define CCKD_CACHE_USED 0x00800000 /* Entry has been used */ #define CKD_CACHE_ACTIVE 0x80000000 /* Active entry */ #define FBA_CACHE_ACTIVE 0x80000000 /* Active entry */ #define SHRD_CACHE_ACTIVE 0x80000000 /* Active entry */ #define DEVBUF_TYPE_SHARED 0x00000080 /* Shared entry type */ #define DEVBUF_TYPE_COMP 0x00000040 /* CCKD/CFBA entry type */ #define DEVBUF_TYPE_CKD 0x00000002 /* CKD entry type */ #define DEVBUF_TYPE_FBA 0x00000001 /* FBA entry type */ #define DEVBUF_TYPE_CCKD (DEVBUF_TYPE_COMP|DEVBUF_TYPE_CKD) #define DEVBUF_TYPE_CFBA (DEVBUF_TYPE_COMP|DEVBUF_TYPE_FBA) #define DEVBUF_TYPE_SCKD (DEVBUF_TYPE_SHARED|DEVBUF_TYPE_CKD) #define DEVBUF_TYPE_SFBA (DEVBUF_TYPE_SHARED|DEVBUF_TYPE_FBA) #define CCKD_CACHE_GETKEY(_ix, _devnum, _trk) \ do { \ (_devnum) = (U16)((cache_getkey(CACHE_DEVBUF,(_ix)) >> 32) & 0xFFFF); \ (_trk) = (U32)(cache_getkey(CACHE_DEVBUF,(_ix)) & 0xFFFFFFFF); \ } while (0) #define CCKD_CACHE_SETKEY(_devnum, _trk) \ ((U64)(((U64)(_devnum) << 32) | (U64)(_trk))) #define CKD_CACHE_GETKEY(_ix, _devnum, _trk) \ { \ (_devnum) = (U16)((cache_getkey(CACHE_DEVBUF,(_ix)) >> 32) & 0xFFFF); \ (_trk) = (U32)(cache_getkey(CACHE_DEVBUF,(_ix)) & 0xFFFFFFFF); \ } #define CKD_CACHE_SETKEY(_devnum, _trk) \ ((U64)(((U64)(_devnum) << 32) | (U64)(_trk))) #define FBA_CACHE_GETKEY(_ix, _devnum, _blkgrp) \ { \ (_devnum) = (U16)((cache_getkey(CACHE_DEVBUF,(_ix)) >> 32) & 0xFFFF); \ (_blkgrp) = (U32)(cache_getkey(CACHE_DEVBUF,(_ix)) & 0xFFFFFFFF); \ } #define FBA_CACHE_SETKEY(_devnum, _blkgrp) \ ((U64)(((U64)(_devnum) << 32) | (U64)(_blkgrp))) #define SHRD_CACHE_GETKEY(_ix, _devnum, _trk) \ { \ (_devnum) = (U16)((cache_getkey(CACHE_DEVBUF,(_ix)) >> 32) & 0xFFFF); \ (_trk) = (U32)(cache_getkey(CACHE_DEVBUF,(_ix)) & 0xFFFFFFFF); \ } #define SHRD_CACHE_SETKEY(_devnum, _trk) \ ((U64)(((U64)(_devnum) << 32) | (U64)(_trk))) /*-------------------------------------------------------------------*/ /* L2 definitions */ /*-------------------------------------------------------------------*/ #define L2_CACHE_ACTIVE 0x80000000 /* Active entry */ #define L2_CACHE_GETKEY(_ix, _sfx, _devnum, _trk) \ do { \ (_sfx) = (U16)((cache_getkey(CACHE_L2,(_ix)) >> 48) & 0xFFFF); \ (_devnum) = (U16)((cache_getkey(CACHE_L2,(_ix)) >> 32) & 0xFFFF); \ (_trk) = (U32)(cache_getkey(CACHE_L2,(_ix)) & 0xFFFFFFFF); \ } while (0) #define L2_CACHE_SETKEY(_sfx, _devnum, _trk) \ ((U64)(((U64)(_sfx) << 48) | ((U64)(_devnum) << 32) | (U64)(_trk))) #endif /* _HERCULES_CACHE_H */ hercules-3.07/cardpch.c000644 000765 000765 00000030717 11202676511 016524 0ustar00jmaynardjmaynard000000 000000 /* CARDPCH.C (c) Copyright Roger Bowler, 1999-2009 */ /* ESA/390 Card Punch Device Handler */ // $Id: cardpch.c 5309 2009-04-04 20:49:13Z rbowler $ /*-------------------------------------------------------------------*/ /* This module contains device handling functions for emulated */ /* System/370 card punch devices. */ /*-------------------------------------------------------------------*/ #include "hstdinc.h" #include "hercules.h" #include "devtype.h" /*-------------------------------------------------------------------*/ /* Internal macro definitions */ /*-------------------------------------------------------------------*/ #define CARD_LENGTH 80 #define HEX40 ((BYTE)0x40) /*-------------------------------------------------------------------*/ /* Subroutine to write data to the card punch */ /*-------------------------------------------------------------------*/ static void write_buffer (DEVBLK *dev, BYTE *buf, int len, BYTE *unitstat) { int rc; /* Return code */ /* Write data to the output file */ rc = write (dev->fd, buf, len); /* Equipment check if error writing to output file */ if (rc < len) { logmsg (_("HHCPU004E Error writing to %s: %s\n"), dev->filename, (errno == 0 ? "incomplete": strerror(errno))); dev->sense[0] = SENSE_EC; *unitstat = CSW_CE | CSW_DE | CSW_UC; return; } } /* end function write_buffer */ /*-------------------------------------------------------------------*/ /* Initialize the device handler */ /*-------------------------------------------------------------------*/ static int cardpch_init_handler (DEVBLK *dev, int argc, char *argv[]) { int i; /* Array subscript */ /* The first argument is the file name */ if (argc == 0 || strlen(argv[0]) > sizeof(dev->filename)-1) { logmsg (_("HHCPU001E File name missing or invalid\n")); return -1; } /* Save the file name in the device block */ strcpy (dev->filename, argv[0]); /* Initialize device dependent fields */ dev->fd = -1; dev->ascii = 0; dev->crlf = 0; dev->cardpos = 0; dev->cardrem = CARD_LENGTH; dev->notrunc = 0; if(!sscanf(dev->typname,"%hx",&(dev->devtype))) dev->devtype = 0x3525; /* Process the driver arguments */ for (i = 1; i < argc; i++) { if (strcasecmp(argv[i], "ascii") == 0) { dev->ascii = 1; continue; } if (strcasecmp(argv[i], "ebcdic") == 0) { dev->ascii = 0; continue; } if (strcasecmp(argv[i], "crlf") == 0) { dev->crlf = 1; continue; } if (strcasecmp(argv[i], "noclear") == 0) { dev->notrunc = 1; continue; } logmsg (_("HHCPU002E Invalid argument: %s\n"), argv[i]); return -1; } /* Set length of buffer */ dev->bufsize = CARD_LENGTH + 2; /* Set number of sense bytes */ dev->numsense = 1; /* Initialize the device identifier bytes */ dev->devid[0] = 0xFF; dev->devid[1] = 0x28; /* Control unit type is 2821-1 */ dev->devid[2] = 0x21; dev->devid[3] = 0x01; dev->devid[4] = dev->devtype >> 8; dev->devid[5] = dev->devtype & 0xFF; dev->devid[6] = 0x01; dev->numdevid = 7; /* Activate I/O tracing */ // dev->ccwtrace = 1; return 0; } /* end function cardpch_init_handler */ /*-------------------------------------------------------------------*/ /* Query the device definition */ /*-------------------------------------------------------------------*/ static void cardpch_query_device (DEVBLK *dev, char **class, int buflen, char *buffer) { BEGIN_DEVICE_CLASS_QUERY( "PCH", dev, class, buflen, buffer ); snprintf (buffer, buflen, "%s%s%s%s", dev->filename, (dev->ascii ? " ascii" : " ebcdic"), ((dev->ascii && dev->crlf) ? " crlf" : ""), (dev->notrunc ? " notrunc" : "")); } /* end function cardpch_query_device */ /*-------------------------------------------------------------------*/ /* Close the device */ /*-------------------------------------------------------------------*/ static int cardpch_close_device ( DEVBLK *dev ) { /* Close the device file */ if (dev->fd >= 0) close (dev->fd); dev->fd = -1; return 0; } /* end function cardpch_close_device */ /*-------------------------------------------------------------------*/ /* Execute a Channel Command Word */ /*-------------------------------------------------------------------*/ static void cardpch_execute_ccw (DEVBLK *dev, BYTE code, BYTE flags, BYTE chained, U16 count, BYTE prevcode, int ccwseq, BYTE *iobuf, BYTE *more, BYTE *unitstat, U16 *residual) { int rc; /* Return code */ int i; /* Loop counter */ int num; /* Number of bytes to move */ int open_flags; /* File open flags */ BYTE c; /* Output character */ char pathname[MAX_PATH]; /* file path in host format */ UNREFERENCED(prevcode); UNREFERENCED(ccwseq); /* Open the device file if necessary */ if (dev->fd < 0 && !IS_CCW_SENSE(code)) { hostpath(pathname, dev->filename, sizeof(pathname)); open_flags = O_WRONLY | O_CREAT /* | O_SYNC */ | O_BINARY; if (dev->notrunc != 1) { open_flags |= O_TRUNC; } rc = open (pathname, open_flags, S_IRUSR | S_IWUSR | S_IRGRP); if (rc < 0) { /* Handle open failure */ logmsg (_("HHCPU003E Error opening file %s: %s\n"), dev->filename, strerror(errno)); /* Set unit check with intervention required */ dev->sense[0] = SENSE_IR; *unitstat = CSW_CE | CSW_DE | CSW_UC; return; } dev->fd = rc; } /* Process depending on CCW opcode */ switch (code) { case 0x01: case 0x41: case 0x81: /*---------------------------------------------------------------*/ /* WRITE, FEED, SELECT STACKER */ /*---------------------------------------------------------------*/ /* Start a new record if not data-chained from previous CCW */ if ((chained & CCW_FLAGS_CD) == 0) { dev->cardpos = 0; dev->cardrem = CARD_LENGTH; } /* end if(!data-chained) */ /* Calculate number of bytes to write and set residual count */ num = (count < dev->cardrem) ? count : dev->cardrem; *residual = count - num; /* Copy data from channel buffer to card buffer */ for (i = 0; i < num; i++) { c = iobuf[i]; if (dev->ascii) { c = guest_to_host(c); if (!isprint(c)) c = SPACE; } dev->buf[dev->cardpos] = c; dev->cardpos++; dev->cardrem--; } /* end for(i) */ /* Perform end of record processing if not data-chaining */ if ((flags & CCW_FLAGS_CD) == 0) { if (dev->ascii) { /* Truncate trailing blanks from card buffer */ for (i = dev->cardpos; i > 0; i--) if (dev->buf[i-1] != SPACE) break; /* Append carriage return and line feed */ if (dev->crlf) dev->buf[i++] = '\r'; dev->buf[i++] = '\n'; } else { /* Pad card image with blanks */ for (i = dev->cardpos; i < CARD_LENGTH; i++) dev->buf[i] = HEX40; } /* Write card image */ write_buffer (dev, dev->buf, i, unitstat); if (*unitstat != 0) break; } /* end if(!data-chaining) */ /* Return normal status */ *unitstat = CSW_CE | CSW_DE; break; case 0x03: /*---------------------------------------------------------------*/ /* CONTROL NO-OPERATION */ /*---------------------------------------------------------------*/ *unitstat = CSW_CE | CSW_DE; break; case 0x04: /*---------------------------------------------------------------*/ /* SENSE */ /*---------------------------------------------------------------*/ /* Calculate residual byte count */ num = (count < dev->numsense) ? count : dev->numsense; *residual = count - num; if (count < dev->numsense) *more = 1; /* Copy device sense bytes to channel I/O buffer */ memcpy (iobuf, dev->sense, num); /* Clear the device sense bytes */ memset (dev->sense, 0, sizeof(dev->sense)); /* Return unit status */ *unitstat = CSW_CE | CSW_DE; break; case 0xE4: /*---------------------------------------------------------------*/ /* SENSE ID */ /*---------------------------------------------------------------*/ /* Calculate residual byte count */ num = (count < dev->numdevid) ? count : dev->numdevid; *residual = count - num; if (count < dev->numdevid) *more = 1; /* Copy device identifier bytes to channel I/O buffer */ memcpy (iobuf, dev->devid, num); /* Return unit status */ *unitstat = CSW_CE | CSW_DE; break; default: /*---------------------------------------------------------------*/ /* INVALID OPERATION */ /*---------------------------------------------------------------*/ /* Set command reject sense byte, and unit check status */ dev->sense[0] = SENSE_CR; *unitstat = CSW_CE | CSW_DE | CSW_UC; } /* end switch(code) */ } /* end function cardpch_execute_ccw */ #if defined(OPTION_DYNAMIC_LOAD) static #endif DEVHND cardpch_device_hndinfo = { &cardpch_init_handler, /* Device Initialisation */ &cardpch_execute_ccw, /* Device CCW execute */ &cardpch_close_device, /* Device Close */ &cardpch_query_device, /* Device Query */ NULL, /* Device Start channel pgm */ NULL, /* Device End channel pgm */ NULL, /* Device Resume channel pgm */ NULL, /* Device Suspend channel pgm */ NULL, /* Device Read */ NULL, /* Device Write */ NULL, /* Device Query used */ NULL, /* Device Reserve */ NULL, /* Device Release */ NULL, /* Device Attention */ NULL, /* Immediate CCW Codes */ NULL, /* Signal Adapter Input */ NULL, /* Signal Adapter Output */ NULL, /* Hercules suspend */ NULL /* Hercules resume */ }; /* Libtool static name colision resolution */ /* note : lt_dlopen will look for symbol & modulename_LTX_symbol */ #if !defined(HDL_BUILD_SHARED) && defined(HDL_USE_LIBTOOL) #define hdl_ddev hdt3525_LTX_hdl_ddev #define hdl_depc hdt3525_LTX_hdl_depc #define hdl_reso hdt3525_LTX_hdl_reso #define hdl_init hdt3525_LTX_hdl_init #define hdl_fini hdt3525_LTX_hdl_fini #endif #if defined(OPTION_DYNAMIC_LOAD) HDL_DEPENDENCY_SECTION; { HDL_DEPENDENCY(HERCULES); HDL_DEPENDENCY(DEVBLK); } END_DEPENDENCY_SECTION HDL_DEVICE_SECTION; { HDL_DEVICE(3525, cardpch_device_hndinfo ); } END_DEVICE_SECTION #endif hercules-3.07/cardrdr.c000644 000765 000765 00000071742 11143760542 016546 0ustar00jmaynardjmaynard000000 000000 /* CARDRDR.C (c) Copyright Roger Bowler, 1999-2009 */ /* ESA/390 Card Reader Device Handler */ // $Id: cardrdr.c 5125 2009-01-23 12:01:44Z bernard $ /*-------------------------------------------------------------------*/ /* This module contains device handling functions for emulated */ /* card reader devices. */ /*-------------------------------------------------------------------*/ // $Log$ // Revision 1.47 2007/11/21 22:54:13 fish // Use new BEGIN_DEVICE_CLASS_QUERY macro // // Revision 1.46 2007/06/23 00:04:03 ivan // Update copyright notices to include current year (2007) // // Revision 1.45 2006/12/28 16:13:28 fish // Fix PR# readers/104: "HHCRD011E Close error... No Error" in 'cardrdr_close_device' function. // // Revision 1.44 2006/12/08 09:43:17 jj // Add CVS message log // #include "hstdinc.h" #include "hercules.h" #include "devtype.h" #include "sockdev.h" #if defined(WIN32) && defined(OPTION_DYNAMIC_LOAD) && !defined(HDL_USE_LIBTOOL) && !defined(_MSVC_) SYSBLK *psysblk; #define sysblk (*psysblk) #endif /*-------------------------------------------------------------------*/ /* ISW 2003/03/07 */ /* 3505 Byte 1 Sense Codes */ /*-------------------------------------------------------------------*/ #define SENSE1_RDR_PERM 0x80 /* Permanent Err key depressed */ #define SENSE1_RDR_AUTORETRY 0x40 /* Don't know */ #define SENSE1_RDR_MOTIONMF 0x20 /* Motion Malfunction */ #define SENSE1_RDR_RAIC 0x10 /* Retry After Intreq Cleared */ /*-------------------------------------------------------------------*/ /* Internal macro definitions */ /*-------------------------------------------------------------------*/ #define CARD_SIZE 80 #define HEX40 ((BYTE)0x40) /*-------------------------------------------------------------------*/ /* Initialize the device handler */ /*-------------------------------------------------------------------*/ static int cardrdr_init_handler ( DEVBLK *dev, int argc, char *argv[] ) { int i; /* Array subscript */ int fc; /* File counter */ int sockdev = 0; if (dev->bs) { if (!unbind_device(dev)) { // (error message already issued) return -1; } } /* Initialize device dependent fields */ dev->fd = -1; dev->fh = NULL; dev->multifile = 0; dev->ebcdic = 0; dev->ascii = 0; dev->trunc = 0; dev->cardpos = 0; dev->cardrem = 0; dev->autopad = 0; if(!sscanf(dev->typname,"%hx",&(dev->devtype))) dev->devtype = 0x2501; fc = 0; if (dev->more_files) free (dev->more_files); dev->more_files = malloc(sizeof(char*) * (fc + 1)); if (!dev->more_files) { logmsg (_("HHCRD001E Out of memory\n")); return -1; } dev->more_files[fc] = NULL; /* Process the driver arguments starting with the SECOND argument. (The FIRST argument is the filename and is checked later further below.) */ for (i = 1; i < argc; i++) { /* sockdev means the device file is actually a connected socket instead of a disk file. The file name is the socket_spec (host:port) to listen for connections on. */ if (strcasecmp(argv[i], "sockdev") == 0) { sockdev = 1; continue; } /* multifile means to automatically open the next i/p file if multiple i/p files are defined. */ if (strcasecmp(argv[i], "multifile") == 0) { dev->multifile = 1; continue; } /* eof means that unit exception will be returned at end of file, instead of intervention required */ if (strcasecmp(argv[i], "eof") == 0) { dev->rdreof = 1; continue; } /* intrq means that intervention required will be returned at end of file, instead of unit exception */ if (strcasecmp(argv[i], "intrq") == 0) { dev->rdreof = 0; continue; } /* ebcdic means that the card image file consists of fixed length 80-byte EBCDIC card images with no line-end delimiters */ if (strcasecmp(argv[i], "ebcdic") == 0) { dev->ebcdic = 1; continue; } /* ascii means that the card image file consists of variable length ASCII records delimited by either line-feed or carriage-return line-feed sequences */ if (strcasecmp(argv[i], "ascii") == 0) { dev->ascii = 1; continue; } /* trunc means that records longer than 80 bytes will be silently truncated to 80 bytes when processing a variable length ASCII file. The default behaviour is to present a data check if an overlength record is encountered. The trunc option is ignored except when processing an ASCII card image file. */ if (strcasecmp(argv[i], "trunc") == 0) { dev->trunc = 1; continue; } /* autopad means that if reading fixed sized records * (ebcdic) and end of file is reached in the middle of * a record, the record is automatically padded to 80 bytes. */ if (strcasecmp(argv[i], "autopad") == 0) { dev->autopad = 1; continue; } // add additional file arguments if (strlen(argv[i]) > sizeof(dev->filename)-1) { logmsg (_("HHCRD002E File name too long (max=%ud): \"%s\"\n"), (unsigned int)sizeof(dev->filename)-1,argv[i]); return -1; } if (access(argv[i], R_OK | F_OK) != 0) { logmsg (_("HHCRD003E Unable to access file \"%s\": %s\n"), argv[i], strerror(errno)); return -1; } dev->more_files[fc++] = strdup(argv[i]); dev->more_files = realloc(dev->more_files, sizeof(char*) * (fc + 1)); if (!dev->more_files) { logmsg (_("HHCRD004E Out of memory\n")); return -1; } dev->more_files[fc] = NULL; } dev->current_file = dev->more_files; /* Check for conflicting arguments */ if (dev->ebcdic && dev->ascii) { logmsg (_("HHCRD005E Specify 'ascii' or 'ebcdic' (or neither) but" " not both\n")); return -1; } if (sockdev) { if (fc) { logmsg (_("HHCRD006E Only one filename (sock_spec) allowed for" " socket devices\n")); return -1; } // If neither ascii nor ebcdic is specified, default to ascii. // This is required for socket devices because the open logic, // if neither is specified, attempts to determine whether the data // is actually ascii or ebcdic by reading the 1st 160 bytes of // data and then rewinding to the beginning of the file afterwards. // Since you can't "rewind" a socket, we must therefore default // to one of them. if (!dev->ebcdic && !dev->ascii) { logmsg (_("HHCRD007I Defaulting to 'ascii' for socket device" " %4.4X\n"),dev->devnum); dev->ascii = 1; } } if (dev->multifile && !fc) { logmsg (_("HHCRD008W 'multifile' option ignored: only one file" " specified\n")); dev->multifile = 0; } /* The first argument is the file name */ if (argc > 0) { /* Check for valid file name */ if (strlen(argv[0]) > sizeof(dev->filename)-1) { logmsg (_("HHCRD009E File name too long (max=%ud): \"%s\"\n"), (unsigned int)sizeof(dev->filename)-1,argv[0]); return -1; } if (!sockdev) { /* Check for specification of no file mounted on reader */ if (argv[0][0] == '*') { dev->filename[0] = '\0'; } else if (access(argv[0], R_OK | F_OK) != 0) { logmsg (_("HHCRD010E Unable to access file \"%s\": %s\n"), argv[0], strerror(errno)); return -1; } } /* Save the file name in the device block */ strcpy (dev->filename, argv[0]); } else { dev->filename[0] = '\0'; } /* Set size of i/o buffer */ dev->bufsize = CARD_SIZE; /* Set number of sense bytes */ /* ISW 20030307 : Empirical knowledge : DOS/VS R34 Erep */ /* indicates 4 bytes in 3505 sense */ dev->numsense = 4; /* Initialize the device identifier bytes */ dev->devid[0] = 0xFF; dev->devid[1] = 0x28; /* Control unit type is 2821-1 */ dev->devid[2] = 0x21; dev->devid[3] = 0x01; dev->devid[4] = dev->devtype >> 8; dev->devid[5] = dev->devtype & 0xFF; dev->devid[6] = 0x01; dev->numdevid = 7; // If socket device, create a listening socket // to accept connections on. if (sockdev && !bind_device(dev,dev->filename)) { // (error message already issued) return -1; } return 0; } /* end function cardrdr_init_handler */ /*-------------------------------------------------------------------*/ /* Query the device definition */ /*-------------------------------------------------------------------*/ static void cardrdr_query_device (DEVBLK *dev, char **class, int buflen, char *buffer) { BEGIN_DEVICE_CLASS_QUERY( "RDR", dev, class, buflen, buffer ); snprintf (buffer, buflen, "%s%s%s%s%s%s%s%s", ((dev->filename[0] == '\0') ? "*" : (char *)dev->filename), (dev->bs ? " sockdev" : ""), (dev->multifile ? " multifile" : ""), (dev->ascii ? " ascii" : ""), (dev->ebcdic ? " ebcdic" : ""), (dev->autopad ? " autopad" : ""), ((dev->ascii && dev->trunc) ? " trunc" : ""), (dev->rdreof ? " eof" : " intrq")); } /* end function cardrdr_query_device */ /*-------------------------------------------------------------------*/ /* Close the device */ /*-------------------------------------------------------------------*/ static int cardrdr_close_device ( DEVBLK *dev ) { /* Close the device file */ if (0 || ( dev->bs && dev->fd >= 0 && close_socket( dev->fd ) < 0 ) || ( !dev->bs && dev->fh != NULL && fclose( dev->fh ) != 0 ) ) { int errnum = dev->bs ? get_HSO_errno() : errno; logmsg (_("HHCRD011E Close error on file \"%s\": %s\n"), dev->filename, strerror(errnum)); dev->fd = -1; dev->fh = NULL; return -1; } if (dev->bs && (dev->bs->clientip || dev->bs->clientname)) { logmsg (_("HHCRD012I %s (%s) disconnected from device %4.4X (%s)\n"), dev->bs->clientip, dev->bs->clientname, dev->devnum, dev->bs->spec); } dev->fd = -1; dev->fh = NULL; return 0; } /* end function cardrdr_close_device */ /*-------------------------------------------------------------------*/ /* Clear the card reader */ /*-------------------------------------------------------------------*/ static int clear_cardrdr ( DEVBLK *dev ) { /* Close the card image file */ if (cardrdr_close_device(dev) != 0) return -1; if (dev->bs) return 0; /* Clear the file name */ dev->filename[0] = '\0'; /* If next file is available, open it */ if (dev->current_file && *(dev->current_file)) { strcpy(dev->filename, *(dev->current_file++)); } else { /* Reset the device dependent flags */ dev->multifile = 0; dev->ascii = 0; dev->ebcdic = 0; // dev->rdreof = 0; dev->trunc = 0; dev->autopad = 0; } return 0; } /* end function clear_cardrdr */ /*-------------------------------------------------------------------*/ /* Open the card image file */ /*-------------------------------------------------------------------*/ static int open_cardrdr ( DEVBLK *dev, BYTE *unitstat ) { int rc; /* Return code */ int i; /* Array subscript */ int len; /* Length of data */ BYTE buf[160]; /* Auto-detection buffer */ char pathname[MAX_PATH]; /* file path in host format */ *unitstat = 0; // Socket device? if (dev->bs) { // Intervention required if no one has connected yet if (dev->fd == -1) { if(dev->rdreof) { *unitstat=CSW_CE|CSW_DE|CSW_UX; return -1; } dev->sense[0] = SENSE_IR; dev->sense[1] = SENSE1_RDR_RAIC; /* Retry when IntReq Cleared */ *unitstat = CSW_CE | CSW_DE | CSW_UC; return -1; } return 0; } /* Intervention required if device has no file name */ if (dev->filename[0] == '\0') { if(dev->rdreof) { *unitstat=CSW_CE|CSW_DE|CSW_UX; return -1; } dev->sense[0] = SENSE_IR; dev->sense[1] = SENSE1_RDR_RAIC; /* Retry when IntReq Cleared */ *unitstat = CSW_CE | CSW_DE | CSW_UC; return -1; } /* Open the device file */ hostpath(pathname, dev->filename, sizeof(pathname)); rc = open (pathname, O_RDONLY | O_BINARY); if (rc < 0) { /* Handle open failure */ logmsg (_("HHCRD013E Error opening file %s: %s\n"), dev->filename, strerror(errno)); /* Set unit check with equipment check */ dev->sense[0] = SENSE_EC; *unitstat = CSW_CE | CSW_DE | CSW_UC; return -1; } /* Save the file descriptor in the device block */ dev->fd = rc; dev->fh = fdopen(dev->fd, "rb"); /* If neither EBCDIC nor ASCII was specified, attempt to detect the format by inspecting the first 160 bytes */ if (dev->ebcdic == 0 && dev->ascii == 0) { /* Read first 160 bytes of file into the buffer */ len = fread(buf, 1, sizeof(buf), dev->fh); if (len < 0) { /* Handle read error condition */ logmsg (_("HHCRD014E Error reading file %s: %s\n"), dev->filename, strerror(errno)); /* Close the file */ fclose(dev->fh); dev->fd = -1; dev->fh = NULL; /* Set unit check with equipment check */ dev->sense[0] = SENSE_EC; *unitstat = CSW_CE | CSW_DE | CSW_UC; return -1; } /* Assume ASCII format if first 160 bytes contain only ASCII characters, carriage return, line feed, tab, or EOF */ for (i = 0, dev->ascii = 1; i < len && buf[i] != '\x1A'; i++) { if ((buf[i] < 0x20 || buf[i] > 0x7F) && buf[i] != '\r' && buf[i] != '\n' && buf[i] != '\t') { dev->ascii = 0; dev->ebcdic = 1; break; } } /* end for(i) */ /* Rewind to start of file */ rc = fseek (dev->fh, 0, SEEK_SET); if (rc < 0) { /* Handle seek error condition */ logmsg (_("HHCRD015E Seek error in file %s: %s\n"), dev->filename, strerror(errno)); /* Close the file */ fclose (dev->fh); dev->fd = -1; dev->fh = NULL; /* Set unit check with equipment check */ dev->sense[0] = SENSE_EC; *unitstat = CSW_CE | CSW_DE | CSW_UC; return -1; } } /* end if(auto-detect) */ ASSERT(dev->fd != -1 && dev->fh); return 0; } /* end function open_cardrdr */ /*-------------------------------------------------------------------*/ /* Read an 80-byte EBCDIC card image into the device buffer */ /*-------------------------------------------------------------------*/ static int read_ebcdic ( DEVBLK *dev, BYTE *unitstat ) { int rc; /* Return code */ /* Read 80 bytes of card image data into the device buffer */ if (dev->bs) rc = read_socket( dev->fd, dev->buf, CARD_SIZE ); else rc = fread(dev->buf, 1, CARD_SIZE, dev->fh); if ((rc > 0) && (rc < CARD_SIZE) && dev->autopad) { memset(&dev->buf[rc], 0, CARD_SIZE - rc); rc = CARD_SIZE; } else if /* Check for End of file */ (0 || ( dev->bs && rc <= 0) || (!dev->bs && feof(dev->fh)) ) { /* Return unit exception or intervention required */ if (dev->rdreof) { *unitstat = CSW_CE | CSW_DE | CSW_UX; } else { dev->sense[0] = SENSE_IR; dev->sense[1] = SENSE1_RDR_RAIC; /* Retry when IntReq Cleared */ *unitstat = CSW_CE | CSW_DE | CSW_UC; } /* Close the file and clear the file name and flags */ if (clear_cardrdr(dev) != 0) { /* Set unit check with equipment check */ dev->sense[0] = SENSE_EC; *unitstat = CSW_CE | CSW_DE | CSW_UC; return -1; } return -2; } /* Handle read error condition */ if (rc < CARD_SIZE) { if (rc < 0) logmsg (_("HHCRD016E Error reading file %s: %s\n"), dev->filename, strerror(errno)); else logmsg (_("HHCRD017E Unexpected end of file on %s\n"), dev->filename); /* Set unit check with equipment check */ dev->sense[0] = SENSE_EC; *unitstat = CSW_CE | CSW_DE | CSW_UC; return -1; } return 0; } /* end function read_ebcdic */ /*-------------------------------------------------------------------*/ /* Read a variable length ASCII card image into the device buffer */ /*-------------------------------------------------------------------*/ static int read_ascii ( DEVBLK *dev, BYTE *unitstat ) { int rc; /* Return code */ int i; /* Array subscript */ BYTE c = 0; /* Input character */ /* Prefill the card image with EBCDIC blanks */ memset (dev->buf, HEX40, CARD_SIZE); /* Read up to 80 bytes into device buffer */ for (i = 0; ; ) { /* Read next byte of card image */ if (dev->bs) { BYTE b; rc = read_socket( dev->fd, &b, 1 ); if (rc <= 0) rc = EOF; else c = b; } else { rc = getc(dev->fh); c = (BYTE)rc; } /* Handle end-of-file condition */ if (rc == EOF || c == '\x1A') { /* End of record if there is any data in buffer */ if (i > 0) break; /* Return unit exception or intervention required */ if (dev->rdreof) { *unitstat = CSW_CE | CSW_DE | CSW_UX; } else { dev->sense[0] = SENSE_IR; dev->sense[1] = SENSE1_RDR_RAIC; /* Retry when IntReq Cleared */ *unitstat = CSW_CE | CSW_DE | CSW_UC; } /* Close the file and clear the file name and flags */ if (clear_cardrdr(dev) != 0) { /* Set unit check with equipment check */ dev->sense[0] = SENSE_EC; *unitstat = CSW_CE | CSW_DE | CSW_UC; return -1; } return -2; } /* Handle read error condition */ if (rc < 0) { logmsg (_("HHCRD018E Error reading file %s: %s\n"), dev->filename, strerror(errno)); /* Set unit check with equipment check */ dev->sense[0] = SENSE_EC; *unitstat = CSW_CE | CSW_DE | CSW_UC; return -1; } /* Ignore carriage return */ if (c == '\r') continue; /* Line-feed indicates end of variable length record */ if (c == '\n') break; /* Expand tabs to spaces */ if (c == '\t') { do {i++;} while ((i & 7) && (i < CARD_SIZE)); continue; } /* Test for overlength record */ if (i >= CARD_SIZE) { /* Ignore excess characters if trunc option specified */ if (dev->trunc) continue; logmsg (_("HHCRD019E Card image exceeds %d bytes in file %s\n"), CARD_SIZE, dev->filename); /* Set unit check with data check */ dev->sense[0] = SENSE_DC; *unitstat = CSW_CE | CSW_DE | CSW_UC; return -1; } /* Convert character to EBCDIC and store in device buffer */ dev->buf[i++] = host_to_guest(c); } /* end for(i) */ return 0; } /* end function read_ascii */ /*-------------------------------------------------------------------*/ /* Execute a Channel Command Word */ /*-------------------------------------------------------------------*/ static void cardrdr_execute_ccw ( DEVBLK *dev, BYTE code, BYTE flags, BYTE chained, U16 count, BYTE prevcode, int ccwseq, BYTE *iobuf, BYTE *more, BYTE *unitstat, U16 *residual ) { int rc; /* Return code */ int num; /* Number of bytes to move */ UNREFERENCED(flags); UNREFERENCED(prevcode); UNREFERENCED(ccwseq); /* Open the device file if necessary */ if ( !IS_CCW_SENSE(code) && (dev->fd < 0 || (!dev->bs && !dev->fh))) { rc = open_cardrdr (dev, unitstat); if (rc) return; } /* Turn all read/feed commands into read, feed, select stacker 1 */ if ((code & 0x17) == 0x02) code = 0x02; /* Turn all feed-only commands into NOP. This is ugly, and should really be thought out more. --JRM */ if ((code & 0x37) == 0x23) code = 0x03; /* Process depending on CCW opcode */ switch (code) { case 0x02: /*---------------------------------------------------------------*/ /* READ */ /*---------------------------------------------------------------*/ /* Read next card if not data-chained from previous CCW */ if ((chained & CCW_FLAGS_CD) == 0) { for (;;) { /* Read ASCII or EBCDIC card image */ if (dev->ascii) rc = read_ascii (dev, unitstat); else rc = read_ebcdic (dev, unitstat); if (0 || rc != -2 || !dev->multifile || open_cardrdr (dev, unitstat) != 0 ) break; } /* Return error status if read was unsuccessful */ if (rc) break; /* Initialize number of bytes in current card */ dev->cardpos = 0; dev->cardrem = CARD_SIZE; } /* end if(!data-chained) */ /* Calculate number of bytes to read and set residual count */ num = (count < dev->cardrem) ? count : dev->cardrem; *residual = count - num; if (count < dev->cardrem) *more = 1; /* Copy data from card image buffer into channel buffer */ memcpy (iobuf, dev->buf + dev->cardpos, num); /* Update number of bytes remaining in card image buffer */ dev->cardpos += num; dev->cardrem -= num; /* Return normal status */ *unitstat = CSW_CE | CSW_DE; break; case 0x03: /*---------------------------------------------------------------*/ /* CONTROL NO-OPERATION */ /*---------------------------------------------------------------*/ *residual = 0; *unitstat = CSW_CE | CSW_DE; break; case 0x04: /*---------------------------------------------------------------*/ /* SENSE */ /*---------------------------------------------------------------*/ /* Calculate residual byte count */ num = (count < dev->numsense) ? count : dev->numsense; *residual = count - num; if (count < dev->numsense) *more = 1; /* If sense is clear AND filename = "" OR sockdev and fd=-1 */ /* Put an IR sense - so that an unsolicited sense can see the intreq */ if(dev->sense[0]==0) { if(dev->filename[0]==0x00 || (dev->bs && dev->fd==-1)) { dev->sense[0] = SENSE_IR; dev->sense[1] = SENSE1_RDR_RAIC; /* Retry when IntReq Cleared */ } } /* Copy device sense bytes to channel I/O buffer */ memcpy (iobuf, dev->sense, num); /* Clear the device sense bytes */ memset (dev->sense, 0, sizeof(dev->sense)); /* Return unit status */ *unitstat = CSW_CE | CSW_DE; break; case 0xE4: /*---------------------------------------------------------------*/ /* SENSE ID */ /*---------------------------------------------------------------*/ /* Calculate residual byte count */ num = (count < dev->numdevid) ? count : dev->numdevid; *residual = count - num; if (count < dev->numdevid) *more = 1; /* Copy device identifier bytes to channel I/O buffer */ memcpy (iobuf, dev->devid, num); /* Return unit status */ *unitstat = CSW_CE | CSW_DE; break; default: /*---------------------------------------------------------------*/ /* INVALID OPERATION */ /*---------------------------------------------------------------*/ /* Set command reject sense byte, and unit check status */ dev->sense[0] = SENSE_CR; *unitstat = CSW_CE | CSW_DE | CSW_UC; } /* end switch(code) */ } /* end function cardrdr_execute_ccw */ #if defined(OPTION_DYNAMIC_LOAD) static #endif DEVHND cardrdr_device_hndinfo = { &cardrdr_init_handler, /* Device Initialisation */ &cardrdr_execute_ccw, /* Device CCW execute */ &cardrdr_close_device, /* Device Close */ &cardrdr_query_device, /* Device Query */ NULL, /* Device Start channel pgm */ NULL, /* Device End channel pgm */ NULL, /* Device Resume channel pgm */ NULL, /* Device Suspend channel pgm */ NULL, /* Device Read */ NULL, /* Device Write */ NULL, /* Device Query used */ NULL, /* Device Reserve */ NULL, /* Device Release */ NULL, /* Device Attention */ NULL, /* Immediate CCW Codes */ NULL, /* Signal Adapter Input */ NULL, /* Signal Adapter Output */ NULL, /* Hercules suspend */ NULL /* Hercules resume */ }; /* Libtool static name colision resolution */ /* note : lt_dlopen will look for symbol & modulename_LTX_symbol */ #if !defined(HDL_BUILD_SHARED) && defined(HDL_USE_LIBTOOL) #define hdl_ddev hdt3505_LTX_hdl_ddev #define hdl_depc hdt3505_LTX_hdl_depc #define hdl_reso hdt3505_LTX_hdl_reso #define hdl_init hdt3505_LTX_hdl_init #define hdl_fini hdt3505_LTX_hdl_fini #endif #if defined(OPTION_DYNAMIC_LOAD) HDL_DEPENDENCY_SECTION; { HDL_DEPENDENCY(HERCULES); HDL_DEPENDENCY(DEVBLK); HDL_DEPENDENCY(SYSBLK); } END_DEPENDENCY_SECTION #if defined(WIN32) && !defined(HDL_USE_LIBTOOL) && !defined(_MSVC_) #undef sysblk HDL_RESOLVER_SECTION; { HDL_RESOLVE_PTRVAR( psysblk, sysblk ); } END_RESOLVER_SECTION #endif HDL_DEVICE_SECTION; { HDL_DEVICE(1442, cardrdr_device_hndinfo ); HDL_DEVICE(2501, cardrdr_device_hndinfo ); HDL_DEVICE(3505, cardrdr_device_hndinfo ); } END_DEVICE_SECTION #endif hercules-3.07/cckdcdsk.c000644 000765 000765 00000012652 11143760542 016671 0ustar00jmaynardjmaynard000000 000000 /* CCKDCDSK.C (c) Copyright Roger Bowler, 1999-2009 */ /* Perform chkdsk for a Compressed CKD Direct Access Storage */ /* Device file. */ // $Id: cckdcdsk.c 5125 2009-01-23 12:01:44Z bernard $ /*-------------------------------------------------------------------*/ /* Perform check function on a compressed ckd file */ /*-------------------------------------------------------------------*/ // $Log$ // Revision 1.45 2008/11/04 04:50:45 fish // Ensure consistent utility startup // // Revision 1.44 2008/09/09 23:45:27 fish // 0 - 4, not 3 // // Revision 1.43 2008/09/04 22:03:15 gsmith // Fix 64-bit length problem in cdsk_valid_trk - Tony Harminc // // Revision 1.42 2007/06/23 00:04:03 ivan // Update copyright notices to include current year (2007) // // Revision 1.41 2006/12/08 09:43:17 jj // Add CVS message log // #include "hstdinc.h" #include "hercules.h" int syntax (); /*-------------------------------------------------------------------*/ /* Main function for stand-alone chkdsk */ /*-------------------------------------------------------------------*/ int main (int argc, char *argv[]) { int i; /* Index */ int rc; /* Return code */ int level=1; /* Chkdsk level checking */ int ro=0; /* 1=Open readonly */ int force=0; /* 1=Check if OPENED bit on */ CCKDDASD_DEVHDR cdevhdr; /* Compressed CKD device hdr */ DEVBLK devblk; /* DEVBLK */ DEVBLK *dev=&devblk; /* -> DEVBLK */ INITIALIZE_UTILITY("cckdcdsk"); /* parse the arguments */ for (argc--, argv++ ; argc > 0 ; argc--, argv++) { if(**argv != '-') break; switch(argv[0][1]) { case '0': case '1': case '2': case '3': case '4': if (argv[0][2] != '\0') return syntax (); level = (argv[0][1] & 0xf); break; case 'f': if (argv[0][2] != '\0') return syntax (); force = 1; break; case 'r': if (argv[0][2] == 'o' && argv[0][3] == '\0') ro = 1; else return syntax (); break; case 'v': if (argv[0][2] != '\0') return syntax (); display_version (stderr, "Hercules cckd chkdsk program ", FALSE); return 0; default: return syntax (); } } if (argc < 1) return syntax (); for (i = 0; i < argc; i++) { memset (dev, 0, sizeof(DEVBLK)); dev->batch = 1; /* open the file */ hostpath(dev->filename, argv[i], sizeof(dev->filename)); dev->fd = open (dev->filename, ro ? O_RDONLY|O_BINARY : O_RDWR|O_BINARY); if (dev->fd < 0) { cckdumsg (dev, 700, "open error: %s\n", strerror(errno)); continue; } /* Check CCKD_OPENED bit if -f not specified */ if (!force) { if (lseek (dev->fd, CCKD_DEVHDR_POS, SEEK_SET) < 0) { cckdumsg (dev, 702, "lseek error offset 0x%" I64_FMT "x: %s\n", (long long)CCKD_DEVHDR_POS, strerror(errno)); close (dev->fd); continue; } if ((rc = read (dev->fd, &cdevhdr, CCKD_DEVHDR_SIZE)) < CCKD_DEVHDR_SIZE) { cckdumsg (dev, 703, "read error rc=%d offset 0x%" I64_FMT "x len %d: %s\n", rc, (long long)CCKD_DEVHDR_POS, CCKD_DEVHDR_SIZE, rc < 0 ? strerror(errno) : "incomplete"); close (dev->fd); continue; } if (cdevhdr.options & CCKD_OPENED) { cckdumsg (dev, 707, "OPENED bit is on, use -f\n"); close (dev->fd); continue; } } /* if (!force) */ rc = cckd_chkdsk (dev, level); close (dev->fd); } /* for each arg */ return 0; } /*-------------------------------------------------------------------*/ /* print syntax */ /*-------------------------------------------------------------------*/ int syntax() { fprintf (stderr, _("\ncckdcdsk [-v] [-f] [-level] [-ro] file1 [file2 ...]\n" "\n" " -v display version and exit\n" "\n" " -f force check even if OPENED bit is on\n" "\n" " level is a digit 0 - 4:\n" " -0 -- minimal checking (hdr, chdr, l1tab, l2tabs)\n" " -1 -- normal checking (hdr, chdr, l1tab, l2tabs, free spaces)\n" " -2 -- extra checking (hdr, chdr, l1tab, l2tabs, free spaces, trkhdrs)\n" " -3 -- maximal checking (hdr, chdr, l1tab, l2tabs, free spaces, trkimgs)\n" " -4 -- recover everything without using meta-data\n" "\n" " -ro open file readonly, no repairs\n" "\n")); return -1; } hercules-3.07/cckdcomp.c000644 000765 000765 00000012025 11143760543 016676 0ustar00jmaynardjmaynard000000 000000 /* CCKDCOMP.C (c) Copyright Roger Bowler, 1999-2009 */ /* Perform chkdsk for a Compressed CKD Direct Access Storage */ /* Device file. */ // $Id: cckdcomp.c 5125 2009-01-23 12:01:44Z bernard $ /*-------------------------------------------------------------------*/ /* Remove all free space on a compressed ckd file */ /*-------------------------------------------------------------------*/ // $Log$ // Revision 1.32 2008/11/04 04:50:45 fish // Ensure consistent utility startup // // Revision 1.31 2007/12/01 23:31:57 fish // Fix cckdcdsk/cckdcomp/cckdutil no message o/p issue // // Revision 1.30 2007/06/23 00:04:03 ivan // Update copyright notices to include current year (2007) // // Revision 1.29 2006/12/08 09:43:17 jj // Add CVS message log // #include "hstdinc.h" #include "hercules.h" int syntax (); /*-------------------------------------------------------------------*/ /* Main function for stand-alone compress */ /*-------------------------------------------------------------------*/ int main (int argc, char *argv[]) { int i; /* Index */ int rc; /* Return code */ int level=-1; /* Level for chkdsk */ int force=0; /* 1=Compress if OPENED set */ CCKDDASD_DEVHDR cdevhdr; /* Compressed CKD device hdr */ DEVBLK devblk; /* DEVBLK */ DEVBLK *dev=&devblk; /* -> DEVBLK */ INITIALIZE_UTILITY("cckdcomp"); /* parse the arguments */ for (argc--, argv++ ; argc > 0 ; argc--, argv++) { if(**argv != '-') break; switch(argv[0][1]) { case '0': case '1': case '2': case '3': if (argv[0][2] != '\0') return syntax (); level = (argv[0][1] & 0xf); break; case 'f': if (argv[0][2] != '\0') return syntax (); force = 1; break; case 'v': if (argv[0][2] != '\0') return syntax (); display_version (stderr, "Hercules cckd compress program ", FALSE); return 0; default: return syntax (); } } if (argc < 1) return syntax (); for (i = 0; i < argc; i++) { memset (dev, 0, sizeof(DEVBLK)); dev->batch = 1; /* open the file */ hostpath(dev->filename, argv[i], sizeof(dev->filename)); dev->fd = open (dev->filename, O_RDWR|O_BINARY); if (dev->fd < 0) { cckdumsg (dev, 700, "open error: %s\n", strerror(errno)); continue; } /* Check CCKD_OPENED bit if -f not specified */ if (!force) { if (lseek (dev->fd, CCKD_DEVHDR_POS, SEEK_SET) < 0) { cckdumsg (dev, 702, "lseek error offset 0x%" I64_FMT "x: %s\n", (long long)CCKD_DEVHDR_POS, strerror(errno)); close (dev->fd); continue; } if ((rc = read (dev->fd, &cdevhdr, CCKD_DEVHDR_SIZE)) < CCKD_DEVHDR_SIZE) { cckdumsg (dev, 703, "read error rc=%d offset 0x%" I64_FMT "x len %d: %s\n", rc, (long long)CCKD_DEVHDR_POS, CCKD_DEVHDR_SIZE, rc < 0 ? strerror(errno) : "incomplete"); close (dev->fd); continue; } if (cdevhdr.options & CCKD_OPENED) { cckdumsg (dev, 707, "OPENED bit is on, use -f\n"); close (dev->fd); continue; } } /* if (!force) */ /* call chkdsk */ if (cckd_chkdsk (dev, level) < 0) { cckdumsg (dev, 708, "chkdsk errors\n"); close (dev->fd); continue; } /* call compress */ rc = cckd_comp (dev); close (dev->fd); } /* for each arg */ return 0; } /*-------------------------------------------------------------------*/ /* print syntax */ /*-------------------------------------------------------------------*/ int syntax() { fprintf (stderr, "\ncckdcomp [-v] [-f] [-level] file1 [file2 ... ]\n" "\n" " -v display version and exit\n" "\n" " -f force check even if OPENED bit is on\n" "\n" " chkdsk level is a digit 0 - 3:\n" " -0 -- minimal checking\n" " -1 -- normal checking\n" " -2 -- intermediate checking\n" " -3 -- maximal checking\n" " default 0\n" "\n"); return -1; } hercules-3.07/cckddasd.c000644 000765 000765 00000613463 11143760544 016671 0ustar00jmaynardjmaynard000000 000000 /* CCKDDASD.C (c) Copyright Roger Bowler, 1999-2009 */ /* ESA/390 Compressed CKD Direct Access Storage Device Handler */ // $Id: cckddasd.c 5125 2009-01-23 12:01:44Z bernard $ /*-------------------------------------------------------------------*/ /* This module contains device functions for compressed emulated */ /* count-key-data direct access storage devices. */ /*-------------------------------------------------------------------*/ // $Log$ // Revision 1.146 2008/11/04 05:56:30 fish // Put ensure consistent create_thread ATTR usage change back in // // Revision 1.145 2008/11/03 15:31:58 rbowler // Back out consistent create_thread ATTR modification // // Revision 1.144 2008/10/18 09:32:20 fish // Ensure consistent create_thread ATTR usage // // Revision 1.143 2008/01/04 03:35:30 gsmith // Fix to sf- command - Thanks Christopher! // // Revision 1.142 2008/01/04 02:28:51 gsmith // sf commands update // // Revision 1.141 2007/06/23 00:04:03 ivan // Update copyright notices to include current year (2007) // // Revision 1.140 2006/12/08 09:43:17 jj // Add CVS message log // #include "hstdinc.h" #define _CCKDDASD_C_ #define _HDASD_DLL_ #include "hercules.h" #include "devtype.h" #include "opcode.h" /*-------------------------------------------------------------------*/ /* Internal functions */ /*-------------------------------------------------------------------*/ int cckddasd_init(int argc, BYTE *argv[]); int cckddasd_term(); int cckddasd_init_handler( DEVBLK *dev, int argc, char *argv[] ); int cckddasd_close_device(DEVBLK *dev); void cckddasd_start(DEVBLK *dev); void cckddasd_end(DEVBLK *dev); int cckd_open (DEVBLK *dev, int sfx, int flags, mode_t mode); int cckd_close (DEVBLK *dev, int sfx); int cckd_read (DEVBLK *dev, int sfx, off_t off, void *buf, size_t len); int cckd_write (DEVBLK *dev, int sfx, off_t off, void *buf, size_t len); int cckd_ftruncate(DEVBLK *dev, int sfx, off_t off); void *cckd_malloc(DEVBLK *dev, char *id, size_t size); void *cckd_calloc(DEVBLK *dev, char *id, size_t n, size_t size); void *cckd_free(DEVBLK *dev, char *id,void *p); int cckd_read_track(DEVBLK *dev, int trk, BYTE *unitstat); int cckd_update_track(DEVBLK *dev, int trk, int off, BYTE *buf, int len, BYTE *unitstat); int cckd_used(DEVBLK *dev); int cfba_read_block(DEVBLK *dev, int blkgrp, BYTE *unitstat); int cfba_write_block(DEVBLK *dev, int blkgrp, int off, BYTE *buf, int wrlen, BYTE *unitstat); int cfba_used(DEVBLK *dev); int cckd_read_trk(DEVBLK *dev, int trk, int ra, BYTE *unitstat); void cckd_readahead(DEVBLK *dev, int trk); int cckd_readahead_scan(int *answer, int ix, int i, void *data); void cckd_ra(); void cckd_flush_cache(DEVBLK *dev); int cckd_flush_cache_scan(int *answer, int ix, int i, void *data); void cckd_flush_cache_all(); void cckd_purge_cache(DEVBLK *dev); int cckd_purge_cache_scan(int *answer, int ix, int i, void *data); void cckd_writer(void *arg); int cckd_writer_scan(int *o, int ix, int i, void *data); off_t cckd_get_space(DEVBLK *dev, int *size, int flags); void cckd_rel_space(DEVBLK *dev, off_t pos, int len, int size); void cckd_flush_space(DEVBLK *dev); int cckd_read_chdr(DEVBLK *dev); int cckd_write_chdr(DEVBLK *dev); int cckd_read_l1(DEVBLK *dev); int cckd_write_l1(DEVBLK *dev); int cckd_write_l1ent(DEVBLK *dev, int l1x); int cckd_read_init(DEVBLK *dev); int cckd_read_fsp(DEVBLK *dev); int cckd_write_fsp(DEVBLK *dev); int cckd_read_l2(DEVBLK *dev, int sfx, int l1x); void cckd_purge_l2(DEVBLK *dev); int cckd_purge_l2_scan(int *answer, int ix, int i, void *data); int cckd_steal_l2(); int cckd_steal_l2_scan(int *answer, int ix, int i, void *data); int cckd_write_l2(DEVBLK *dev); int cckd_read_l2ent(DEVBLK *dev, CCKD_L2ENT *l2, int trk); int cckd_write_l2ent(DEVBLK *dev, CCKD_L2ENT *l2, int trk); int cckd_read_trkimg(DEVBLK *dev, BYTE *buf, int trk, BYTE *unitstat); int cckd_write_trkimg(DEVBLK *dev, BYTE *buf, int len, int trk, int flags); int cckd_harden(DEVBLK *dev); int cckd_trklen(DEVBLK *dev, BYTE *buf); int cckd_null_trk(DEVBLK *dev, BYTE *buf, int trk, int nullfmt); int cckd_check_null_trk (DEVBLK *dev, BYTE *buf, int trk, int len); int cckd_cchh(DEVBLK *dev, BYTE *buf, int trk); int cckd_validate(DEVBLK *dev, BYTE *buf, int trk, int len); char *cckd_sf_name(DEVBLK *dev, int sfx); int cckd_sf_init(DEVBLK *dev); int cckd_sf_new(DEVBLK *dev); DLL_EXPORT void *cckd_sf_add(void *data); DLL_EXPORT void *cckd_sf_remove(void *data); DLL_EXPORT void *cckd_sf_comp(void *data); DLL_EXPORT void *cckd_sf_chk(void *data); DLL_EXPORT void *cckd_sf_stats(void *data); int cckd_disable_syncio(DEVBLK *dev); void cckd_lock_devchain(int flag); void cckd_unlock_devchain(); void cckd_gcol(); int cckd_gc_percolate(DEVBLK *dev, unsigned int size); int cckd_gc_l2(DEVBLK *dev, BYTE *buf); DEVBLK *cckd_find_device_by_devnum (U16 devnum); BYTE *cckd_uncompress(DEVBLK *dev, BYTE *from, int len, int maxlen, int trk); int cckd_uncompress_zlib(DEVBLK *dev, BYTE *to, BYTE *from, int len, int maxlen); int cckd_uncompress_bzip2(DEVBLK *dev, BYTE *to, BYTE *from, int len, int maxlen); int cckd_compress(DEVBLK *dev, BYTE **to, BYTE *from, int len, int comp, int parm); int cckd_compress_none(DEVBLK *dev, BYTE **to, BYTE *from, int len, int parm); int cckd_compress_zlib(DEVBLK *dev, BYTE **to, BYTE *from, int len, int parm); int cckd_compress_bzip2(DEVBLK *dev, BYTE **to, BYTE *from, int len, int parm); void cckd_command_help(); void cckd_command_opts(); void cckd_command_stats(); void cckd_command_debug(); int cckd_command(char *op, int cmd); DLL_EXPORT void cckd_print_itrace(); void cckd_trace(DEVBLK *dev, char *msg, ...); /*-------------------------------------------------------------------*/ /* Definitions for sense data format codes and message codes */ /*-------------------------------------------------------------------*/ #define FORMAT_0 0 /* Program or System Checks */ #define FORMAT_1 1 /* Device Equipment Checks */ #define FORMAT_2 2 /* 3990 Equipment Checks */ #define FORMAT_3 3 /* 3990 Control Checks */ #define FORMAT_4 4 /* Data Checks */ #define FORMAT_5 5 /* Data Check + Displacement */ #define FORMAT_6 6 /* Usage Stats/Overrun Errors*/ #define FORMAT_7 7 /* Device Control Checks */ #define FORMAT_8 8 /* Device Equipment Checks */ #define FORMAT_9 9 /* Device Rd/Wrt/Seek Checks */ #define FORMAT_F 15 /* Cache Storage Checks */ #define MESSAGE_0 0 /* Message 0 */ #define MESSAGE_1 1 /* Message 1 */ #define MESSAGE_2 2 /* Message 2 */ #define MESSAGE_3 3 /* Message 3 */ #define MESSAGE_4 4 /* Message 4 */ #define MESSAGE_5 5 /* Message 5 */ #define MESSAGE_6 6 /* Message 6 */ #define MESSAGE_7 7 /* Message 7 */ #define MESSAGE_8 8 /* Message 8 */ #define MESSAGE_9 9 /* Message 9 */ #define MESSAGE_A 10 /* Message A */ #define MESSAGE_B 11 /* Message B */ #define MESSAGE_C 12 /* Message C */ #define MESSAGE_D 13 /* Message D */ #define MESSAGE_E 14 /* Message E */ #define MESSAGE_F 15 /* Message F */ /*-------------------------------------------------------------------*/ /* Data areas */ /*-------------------------------------------------------------------*/ static CCKD_L2ENT empty_l2[CKDDASD_NULLTRK_FMTMAX+1][256]; static BYTE eighthexFF[] = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}; DEVHND cckddasd_device_hndinfo; DEVHND cfbadasd_device_hndinfo; DLL_EXPORT CCKDBLK cckdblk; /* cckd global area */ /*-------------------------------------------------------------------*/ /* CCKD global initialization */ /*-------------------------------------------------------------------*/ int cckddasd_init (int argc, BYTE *argv[]) { int i, j; /* Loop indexes */ UNREFERENCED(argc); UNREFERENCED(argv); if (memcmp (&cckdblk.id, "CCKDBLK ", sizeof(cckdblk.id)) == 0) return 0; /* Clear the cckdblk */ memset(&cckdblk, 0, sizeof(CCKDBLK)); /* Initialize locks and conditions */ memcpy (&cckdblk.id, "CCKDBLK ", sizeof(cckdblk.id)); initialize_lock (&cckdblk.gclock); initialize_lock (&cckdblk.ralock); initialize_lock (&cckdblk.wrlock); initialize_lock (&cckdblk.devlock); initialize_condition (&cckdblk.gccond); initialize_condition (&cckdblk.racond); initialize_condition (&cckdblk.wrcond); initialize_condition (&cckdblk.devcond); initialize_condition (&cckdblk.termcond); /* Initialize some variables */ cckdblk.wrprio = 16; cckdblk.ranbr = CCKD_DEFAULT_RA_SIZE; cckdblk.ramax = CCKD_DEFAULT_RA; cckdblk.wrmax = CCKD_DEFAULT_WRITER; cckdblk.gcmax = CCKD_DEFAULT_GCOL; cckdblk.gcwait = CCKD_DEFAULT_GCOLWAIT; cckdblk.gcparm = CCKD_DEFAULT_GCOLPARM; cckdblk.readaheads = CCKD_DEFAULT_READAHEADS; cckdblk.freepend = CCKD_DEFAULT_FREEPEND; #ifdef HAVE_LIBZ cckdblk.comps |= CCKD_COMPRESS_ZLIB; #endif #ifdef CCKD_BZIP2 cckdblk.comps |= CCKD_COMPRESS_BZIP2; #endif cckdblk.comp = 0xff; cckdblk.compparm = -1; /* Initialize the readahead queue */ cckdblk.ra1st = cckdblk.ralast = -1; cckdblk.rafree = 0; for (i = 0; i < cckdblk.ranbr; i++) cckdblk.ra[i].next = i + 1; cckdblk.ra[cckdblk.ranbr - 1].next = -1; /* Clear the empty L2 tables */ for (i = 0; i <= CKDDASD_NULLTRK_FMTMAX; i++) for (j = 0; j < 256; j++) { empty_l2[i][j].pos = 0; empty_l2[i][j].len = empty_l2[i][j].size = i; } return 0; } /* end function cckddasd_init */ /*-------------------------------------------------------------------*/ /* CCKD dasd global termination */ /*-------------------------------------------------------------------*/ int cckddasd_term () { /* Terminate the readahead threads */ obtain_lock (&cckdblk.ralock); cckdblk.ramax = 0; if (cckdblk.ras) { broadcast_condition (&cckdblk.racond); wait_condition (&cckdblk.termcond, &cckdblk.ralock); } release_lock (&cckdblk.ralock); /* Terminate the garbage collection threads */ obtain_lock (&cckdblk.gclock); cckdblk.gcmax = 0; if (cckdblk.gcs) { broadcast_condition (&cckdblk.gccond); wait_condition (&cckdblk.termcond, &cckdblk.gclock); } release_lock (&cckdblk.gclock); /* Terminate the writer threads */ obtain_lock (&cckdblk.wrlock); cckdblk.wrmax = 0; if (cckdblk.wrs) { broadcast_condition (&cckdblk.wrcond); wait_condition (&cckdblk.termcond, &cckdblk.wrlock); } release_lock (&cckdblk.wrlock); memset(&cckdblk, 0, sizeof(CCKDBLK)); return 0; } /* end function cckddasd_term */ /*-------------------------------------------------------------------*/ /* CKD dasd initialization */ /*-------------------------------------------------------------------*/ int cckddasd_init_handler ( DEVBLK *dev, int argc, char *argv[] ) { CCKDDASD_EXT *cckd; /* -> cckd extension */ DEVBLK *dev2; /* -> device in cckd queue */ int i; /* Counter */ int fdflags; /* File flags */ UNREFERENCED(argc); UNREFERENCED(argv); /* Initialize the global cckd block if necessary */ if (memcmp (&cckdblk.id, "CCKDBLK ", sizeof(cckdblk.id))) cckddasd_init (0, NULL); /* Obtain area for cckd extension */ dev->cckd_ext = cckd = cckd_calloc (dev, "ext", 1, sizeof(CCKDDASD_EXT)); if (cckd == NULL) return -1; /* Initialize locks and conditions */ initialize_lock (&cckd->iolock); initialize_lock (&cckd->filelock); initialize_condition (&cckd->iocond); /* Initialize some variables */ obtain_lock (&cckd->filelock); cckd->l1x = cckd->sfx = cckd->l2active = -1; dev->cache = cckd->free1st = -1; cckd->fd[0] = dev->fd; fdflags = get_file_accmode_flags( dev->fd ); cckd->open[0] = (fdflags & O_RDWR) ? CCKD_OPEN_RW : CCKD_OPEN_RO; for (i = 1; i <= CCKD_MAX_SF; i++) { cckd->fd[i] = -1; cckd->open[i] = CCKD_OPEN_NONE; } cckd->maxsize = sizeof(off_t) > 4 ? 0xffffffffll : 0x7fffffffll; /* call the chkdsk function */ if (cckd_chkdsk (dev, 0) < 0) return -1; /* Perform initial read */ if (cckd_read_init (dev) < 0) return -1; if (cckd->fbadasd) dev->ckdtrksz = CFBA_BLOCK_SIZE; /* open the shadow files */ if (cckd_sf_init (dev) < 0) { logmsg (_("HHCCD101E %4.4X error initializing shadow files\n"), dev->devnum); return -1; } /* Update the device handler routines */ if (cckd->ckddasd) dev->hnd = &cckddasd_device_hndinfo; else dev->hnd = &cfbadasd_device_hndinfo; release_lock (&cckd->filelock); /* Insert the device into the cckd device queue */ cckd_lock_devchain(1); for (cckd = NULL, dev2 = cckdblk.dev1st; dev2; dev2 = cckd->devnext) cckd = dev2->cckd_ext; if (cckd) cckd->devnext = dev; else cckdblk.dev1st = dev; cckd_unlock_devchain(); cckdblk.batch = dev->batch; if (cckdblk.batch) { cckdblk.nostress = 1; cckdblk.freepend = 0; cckdblk.linuxnull = 1; } return 0; } /* end function cckddasd_init_handler */ /*-------------------------------------------------------------------*/ /* Close a Compressed CKD Device */ /*-------------------------------------------------------------------*/ int cckddasd_close_device (DEVBLK *dev) { CCKDDASD_EXT *cckd; /* -> cckd extension */ int i; /* Index */ cckd = dev->cckd_ext; /* Wait for readaheads to finish */ obtain_lock(&cckdblk.ralock); cckd->stopping = 1; while (cckd->ras) { release_lock(&cckdblk.ralock); usleep(1); obtain_lock(&cckdblk.ralock); } release_lock(&cckdblk.ralock); /* Flush the cache and wait for the writes to complete */ obtain_lock (&cckd->iolock); cckd->stopping = 1; cckd_flush_cache (dev); while (cckd->wrpending || cckd->ioactive) { cckd->iowaiters++; wait_condition (&cckd->iocond, &cckd->iolock); cckd->iowaiters--; cckd_flush_cache (dev); } broadcast_condition (&cckd->iocond); cckd_purge_cache (dev); cckd_purge_l2 (dev); dev->bufcur = dev->cache = -1; if (cckd->newbuf) cckd_free (dev, "newbuf", cckd->newbuf); release_lock (&cckd->iolock); /* Remove the device from the cckd queue */ cckd_lock_devchain(1); if (dev == cckdblk.dev1st) cckdblk.dev1st = cckd->devnext; else { DEVBLK *dev2 = cckdblk.dev1st; CCKDDASD_EXT *cckd2 = dev2->cckd_ext; while (cckd2->devnext != dev) { dev2 = cckd2->devnext; cckd2 = dev2->cckd_ext; } cckd2->devnext = cckd->devnext; } cckd_unlock_devchain(); /* harden the file */ obtain_lock (&cckd->filelock); cckd_harden (dev); /* close the shadow files */ for (i = 1; i <= cckd->sfn; i++) { cckd_close (dev, i); cckd->open[i] = 0; } /* free the level 1 tables */ for (i = 0; i <= cckd->sfn; i++) cckd->l1[i] = cckd_free (dev, "l1", cckd->l1[i]); /* reset the device handler */ if (cckd->ckddasd) dev->hnd = &ckddasd_device_hndinfo; else dev->hnd = &fbadasd_device_hndinfo; /* write some statistics */ if (!dev->batch) cckd_sf_stats (dev); release_lock (&cckd->filelock); /* free the cckd extension */ dev->cckd_ext= cckd_free (dev, "ext", cckd); if (dev->dasdsfn) free (dev->dasdsfn); dev->dasdsfn = NULL; close (dev->fd); dev->fd = -1; /* If no more devices then perform global termination */ if (cckdblk.dev1st == NULL) cckddasd_term (); return 0; } /* end function cckddasd_close_device */ /*-------------------------------------------------------------------*/ /* Compressed ckd start/resume channel program */ /*-------------------------------------------------------------------*/ void cckddasd_start (DEVBLK *dev) { CCKDDASD_EXT *cckd; /* -> cckd extension */ U16 devnum = 0; /* Last active device number */ int trk = 0; /* Last active track */ cckd = dev->cckd_ext; cckd_trace (dev, "start i/o file[%d] bufcur %d cache[%d]\n", cckd->sfn, dev->bufcur, dev->cache); /* Reset buffer offsets */ dev->bufoff = 0; dev->bufoffhi = cckd->ckddasd ? dev->ckdtrksz : CFBA_BLOCK_SIZE; /* Check for merge - synchronous i/o should be disabled */ obtain_lock(&cckd->iolock); if (cckd->merging) { cckd_trace (dev, "start i/o waiting for merge%s\n",""); while (cckd->merging) { cckd->iowaiters++; wait_condition (&cckd->iocond, &cckd->iolock); cckd->iowaiters--; } dev->bufcur = dev->cache = -1; } cckd->ioactive = 1; cache_lock(CACHE_DEVBUF); if (dev->cache >= 0) CCKD_CACHE_GETKEY(dev->cache, devnum, trk); /* Check if previous active entry is still valid and not busy */ if (dev->cache >= 0 && dev->devnum == devnum && dev->bufcur == trk && !(cache_getflag(CACHE_DEVBUF, dev->cache) & CCKD_CACHE_IOBUSY)) { /* Make the entry active again */ cache_setflag (CACHE_DEVBUF, dev->cache, ~0, CCKD_CACHE_ACTIVE); /* If the entry is pending write then change it to `updated' */ if (cache_getflag(CACHE_DEVBUF, dev->cache) & CCKD_CACHE_WRITE) { cache_setflag (CACHE_DEVBUF, dev->cache, ~CCKD_CACHE_WRITE, CCKD_CACHE_UPDATED); cckd->wrpending--; if (cckd->iowaiters && !cckd->wrpending) broadcast_condition (&cckd->iocond); } } else dev->bufcur = dev->cache = -1; cache_unlock (CACHE_DEVBUF); release_lock (&cckd->iolock); return; } /* end function cckddasd_start */ /*-------------------------------------------------------------------*/ /* Compressed ckd end/suspend channel program */ /*-------------------------------------------------------------------*/ void cckddasd_end (DEVBLK *dev) { CCKDDASD_EXT *cckd; /* -> cckd extension */ cckd = dev->cckd_ext; /* Update length if previous image was updated */ if (dev->bufupd && dev->bufcur >= 0 && dev->cache >= 0) { dev->buflen = cckd_trklen (dev, dev->buf); cache_setval (CACHE_DEVBUF, dev->cache, dev->buflen); } dev->bufupd = 0; cckd_trace (dev, "end i/o bufcur %d cache[%d] waiters %d\n", dev->bufcur, dev->cache, cckd->iowaiters); obtain_lock (&cckd->iolock); cckd->ioactive = 0; /* Make the current entry inactive */ if (dev->cache >= 0) { cache_lock (CACHE_DEVBUF); cache_setflag (CACHE_DEVBUF, dev->cache, ~CCKD_CACHE_ACTIVE, 0); cache_unlock (CACHE_DEVBUF); } /* Cause writers to start after first update */ if (cckd->updated && (cckdblk.wrs == 0 || cckd->iowaiters != 0)) cckd_flush_cache (dev); else if (cckd->iowaiters) broadcast_condition (&cckd->iocond); release_lock (&cckd->iolock); } /* end function cckddasd_end */ /*-------------------------------------------------------------------*/ /* Open a cckd file */ /* */ /* If O_CREAT is not set and mode is non-zero then the error message */ /* will be supressed. */ /*-------------------------------------------------------------------*/ int cckd_open (DEVBLK *dev, int sfx, int flags, mode_t mode) { CCKDDASD_EXT *cckd; /* -> cckd extension */ int err; /* 1 = issue error message */ char pathname[MAX_PATH]; /* file path in host format */ cckd = dev->cckd_ext; err = !((flags & O_CREAT) == 0 && mode != 0); if (cckd->fd[sfx] >= 0) cckd_close (dev, sfx); hostpath(pathname, cckd_sf_name (dev, sfx), sizeof(pathname)); cckd->fd[sfx] = open (pathname, flags, mode); if (sfx == 0) dev->fd = cckd->fd[sfx]; if (cckd->fd[sfx] >= 0) cckd->open[sfx] = flags & O_RDWR ? CCKD_OPEN_RW : cckd->open[sfx] == CCKD_OPEN_RW ? CCKD_OPEN_RD : CCKD_OPEN_RO; else { if (err) { logmsg (_("HHCCD130E %4.4X file[%d] %s open error: %s\n"), dev->devnum, sfx, cckd_sf_name (dev, sfx), strerror(errno)); cckd_trace (dev, "file[%d] fd[%d] open %s error flags %8.8x mode %8.8x\n", sfx, cckd->fd[sfx], cckd_sf_name (dev, sfx), flags, mode); cckd_print_itrace (); } cckd->open[sfx] = CCKD_OPEN_NONE; } cckd_trace (dev, "file[%d] fd[%d] open %s, flags %8.8x mode %8.8x\n", sfx, cckd->fd[sfx], cckd_sf_name (dev, sfx), flags, mode); return cckd->fd[sfx]; } /* end function cckd_open */ /*-------------------------------------------------------------------*/ /* Close a cckd file */ /*-------------------------------------------------------------------*/ int cckd_close (DEVBLK *dev, int sfx) { CCKDDASD_EXT *cckd; /* -> cckd extension */ int rc = 0; /* Return code */ cckd = dev->cckd_ext; cckd_trace (dev, "file[%d] fd[%d] close %s\n", sfx, cckd->fd[sfx], cckd_sf_name(dev, sfx)); if (cckd->fd[sfx] >= 0) rc = close (cckd->fd[sfx]); if (rc < 0) { logmsg (_("HHCCD130E %4.4X file[%d] close error: %s\n"), dev->devnum, sfx, strerror(errno)); cckd_print_itrace (); } cckd->fd[sfx] = -1; if (sfx == 0) dev->fd = -1; return rc; } /* end function cckd_close */ /*-------------------------------------------------------------------*/ /* Read from a cckd file */ /*-------------------------------------------------------------------*/ int cckd_read (DEVBLK *dev, int sfx, off_t off, void *buf, size_t len) { CCKDDASD_EXT *cckd; /* -> cckd extension */ int rc; /* Return code */ cckd = dev->cckd_ext; cckd_trace (dev, "file[%d] fd[%d] read, off 0x%" I64_FMT "x len %ld\n", sfx, cckd->fd[sfx], (long long)off, (long)len); /* Seek to specified offset */ if (lseek (cckd->fd[sfx], off, SEEK_SET) < 0) { logmsg (_("HHCCD130E %4.4X file[%d] lseek error, offset 0x%" I64_FMT "x: %s\n"), dev->devnum, sfx, (long long)off, strerror(errno)); cckd_print_itrace (); return -1; } /* Read the data */ rc = read (cckd->fd[sfx], buf, len); if (rc < (int)len) { if (rc < 0) logmsg (_("HHCCD130E %4.4X file[%d] read error, offset 0x%" I64_FMT "x: %s\n"), dev->devnum, sfx, (long long)off, strerror(errno)); else logmsg (_("HHCCD130E %4.4X file[%d] read incomplete, offset 0x%" I64_FMT "x: " "read %d expected %d\n"), dev->devnum, sfx, (long long)off, rc, len); cckd_print_itrace (); return -1; } return rc; } /* end function cckd_read */ /*-------------------------------------------------------------------*/ /* Write to a cckd file */ /*-------------------------------------------------------------------*/ int cckd_write (DEVBLK *dev, int sfx, off_t off, void *buf, size_t len) { CCKDDASD_EXT *cckd; /* -> cckd extension */ int rc = 0; /* Return code */ cckd = dev->cckd_ext; cckd_trace (dev, "file[%d] fd[%d] write, off 0x%" I64_FMT "x len %ld\n", sfx, cckd->fd[sfx], (long long)off, (long)len); /* Seek to specified offset */ if (lseek (cckd->fd[sfx], off, SEEK_SET) < 0) { logmsg (_("HHCCD130E %4.4X file[%d] lseek error, offset 0x%" I64_FMT "x: %s\n"), dev->devnum, sfx, (long long)off, strerror(errno)); return -1; } /* Write the data */ rc = write (cckd->fd[sfx], buf, len); if (rc < (int)len) { if (rc < 0) logmsg (_("HHCCD130E %4.4X file[%d] write error, offset 0x%" I64_FMT "x: %s\n"), dev->devnum, sfx, (long long)off, strerror(errno)); else logmsg (_("HHCCD130E %4.4X file[%d] write incomplete, offset 0x%" I64_FMT "x: " "wrote %d expected %d\n"), dev->devnum, sfx, (long long)off, rc, len); cckd_print_itrace (); return -1; } return rc; } /* end function cckd_write */ /*-------------------------------------------------------------------*/ /* Truncate a cckd file */ /*-------------------------------------------------------------------*/ int cckd_ftruncate(DEVBLK *dev, int sfx, off_t off) { CCKDDASD_EXT *cckd; /* -> cckd extension */ cckd = dev->cckd_ext; cckd_trace (dev, "file[%d] fd[%d] ftruncate, off 0x%" I64_FMT "x\n", sfx, cckd->fd[sfx], (long long)off); /* Truncate the file */ if (ftruncate (cckd->fd[sfx], off) < 0) { logmsg (_("HHCCD130E %4.4X file[%d] ftruncate error, offset 0x%" I64_FMT "x: %s\n"), dev->devnum, sfx, (long long)off, strerror(errno)); cckd_print_itrace (); return -1; } return 0; } /* end function cckd_ftruncate */ /*-------------------------------------------------------------------*/ /* malloc */ /*-------------------------------------------------------------------*/ void *cckd_malloc (DEVBLK *dev, char *id, size_t size) { void *p; /* Pointer */ p = malloc (size); cckd_trace (dev, "%s malloc %p len %ld\n", id, p, (long)size); if (p == NULL) { logmsg (_("HHCCD130E %4.4X malloc error, size %d: %s\n"), dev ? dev->devnum : 0, size, strerror(errno)); cckd_print_itrace (); } return p; } /* end function cckd_malloc */ /*-------------------------------------------------------------------*/ /* calloc */ /*-------------------------------------------------------------------*/ void *cckd_calloc (DEVBLK *dev, char *id, size_t n, size_t size) { void *p; /* Pointer */ p = calloc (n, size); cckd_trace (dev, "%s calloc %p len %ld\n", id, p, n*(long)size); if (p == NULL) { logmsg (_("HHCCD130E %4.4X calloc error, size %d: %s\n"), dev ? dev->devnum : 0, n*size, strerror(errno)); cckd_print_itrace (); } return p; } /* end function cckd_calloc */ /*-------------------------------------------------------------------*/ /* free */ /*-------------------------------------------------------------------*/ void *cckd_free (DEVBLK *dev, char *id, void *p) { cckd_trace (dev, "%s free %p\n", id, p); if (p) free (p); return NULL; } /* end function cckd_free */ /*-------------------------------------------------------------------*/ /* Compressed ckd read track image */ /*-------------------------------------------------------------------*/ int cckd_read_track (DEVBLK *dev, int trk, BYTE *unitstat) { CCKDDASD_EXT *cckd; /* -> cckd extension */ int rc; /* Return code */ int len; /* Compressed length */ BYTE *newbuf; /* Uncompressed buffer */ int cache; /* New active cache entry */ int syncio; /* Syncio indicator */ cckd = dev->cckd_ext; /* Update length if previous image was updated */ if (dev->bufupd && dev->bufcur >= 0 && dev->cache >= 0) { dev->buflen = cckd_trklen (dev, dev->buf); cache_setval (CACHE_DEVBUF, dev->cache, dev->buflen); } /* Turn off the synchronous I/O bit if trk overflow or trk 0 */ syncio = dev->syncio_active; if (dev->ckdtrkof || trk == 0) dev->syncio_active = 0; /* Reset buffer offsets */ dev->bufoff = 0; dev->bufoffhi = dev->ckdtrksz; /* Check if reading the same track image */ if (trk == dev->bufcur && dev->cache >= 0) { /* Track image may be compressed */ if ((dev->buf[0] & CCKD_COMPRESS_MASK) != 0 && (dev->buf[0] & dev->comps) == 0) { #if 0 /* Return if synchronous i/o */ if (dev->syncio_active) { cckd_trace (dev, "read trk %d syncio compressed\n", trk); cckdblk.stats_synciomisses++; dev->syncio_retry = 1; return -1; } #endif len = cache_getval(CACHE_DEVBUF, dev->cache); newbuf = cckd_uncompress (dev, dev->buf, len, dev->ckdtrksz, trk); if (newbuf == NULL) { ckd_build_sense (dev, SENSE_EC, 0, 0, FORMAT_1, MESSAGE_0); *unitstat = CSW_CE | CSW_DE | CSW_UC; dev->bufcur = dev->cache = -1; dev->syncio_active = syncio; return -1; } cache_setbuf (CACHE_DEVBUF, dev->cache, newbuf, dev->ckdtrksz); dev->buf = newbuf; dev->buflen = cckd_trklen (dev, newbuf); cache_setval (CACHE_DEVBUF, dev->cache, dev->buflen); dev->bufsize = cache_getlen (CACHE_DEVBUF, dev->cache); dev->bufupd = 0; cckd_trace (dev, "read trk %d uncompressed len %d\n", trk, dev->buflen); } dev->comp = dev->buf[0] & CCKD_COMPRESS_MASK; if (dev->comp != 0) dev->compoff = CKDDASD_TRKHDR_SIZE; return 0; } cckd_trace (dev, "read trk %d (%s)\n", trk, dev->syncio_active ? "synchronous" : "asynchronous"); /* read the new track */ dev->bufupd = 0; *unitstat = 0; cache = cckd_read_trk (dev, trk, 0, unitstat); if (cache < 0) { dev->bufcur = dev->cache = -1; return -1; } dev->cache = cache; dev->buf = cache_getbuf (CACHE_DEVBUF, dev->cache, 0); dev->bufcur = trk; dev->bufoff = 0; dev->bufoffhi = dev->ckdtrksz; dev->buflen = cache_getval (CACHE_DEVBUF, dev->cache); dev->bufsize = cache_getlen (CACHE_DEVBUF, dev->cache); dev->comp = dev->buf[0] & CCKD_COMPRESS_MASK; if (dev->comp != 0) dev->compoff = CKDDASD_TRKHDR_SIZE; /* If the image is compressed then call ourself recursively to cause the image to get uncompressed */ if (dev->comp != 0 && (dev->comp & dev->comps) == 0) rc = cckd_read_track (dev, trk, unitstat); else rc = 0; dev->syncio_active = syncio; return rc; } /* end function cckd_read_track */ /*-------------------------------------------------------------------*/ /* Compressed ckd update track image */ /*-------------------------------------------------------------------*/ int cckd_update_track (DEVBLK *dev, int trk, int off, BYTE *buf, int len, BYTE *unitstat) { CCKDDASD_EXT *cckd; /* -> cckd extension */ int rc; /* Return code */ cckd = dev->cckd_ext; /* Error if opened read-only */ if (dev->ckdrdonly && cckd->sfn == 0) { ckd_build_sense (dev, SENSE_EC, SENSE1_WRI, 0,FORMAT_1, MESSAGE_0); *unitstat = CSW_CE | CSW_DE | CSW_UC; dev->bufcur = dev->cache = -1; return -1; } /* If the track is not current or compressed then read it. `dev->comps' is set to zero forcing the read routine to uncompress the image. */ if (trk != dev->bufcur || (dev->buf[0] & CCKD_COMPRESS_MASK) != 0) { dev->comps = 0; rc = (dev->hnd->read) (dev, trk, unitstat); if (rc < 0) { dev->bufcur = dev->cache = -1; return -1; } } /* Invalid track format if going past buffer end */ if (off + len > dev->ckdtrksz) { ckd_build_sense (dev, 0, SENSE1_ITF, 0, 0, 0); *unitstat = CSW_CE | CSW_DE | CSW_UC; dev->bufcur = dev->cache = -1; return -1; } /* Copy the data into the buffer */ if (buf && len > 0) memcpy (dev->buf + off, buf, len); cckd_trace (dev, "updt trk %d offset %d length %d\n", trk, off, len); /* Update the cache entry */ cache_setflag (CACHE_DEVBUF, dev->cache, ~0, CCKD_CACHE_UPDATED | CCKD_CACHE_USED); cckd->updated = 1; /* Notify the shared server of the update */ if (!dev->bufupd) { dev->bufupd = 1; shared_update_notify (dev, trk); } return len; } /* end function cckd_update_track */ /*-------------------------------------------------------------------*/ /* Return used cylinders */ /*-------------------------------------------------------------------*/ int cckd_used (DEVBLK *dev) { CCKDDASD_EXT *cckd; /* -> cckd extension */ int rc; /* Return code */ int l1x, l2x; /* Lookup table indexes */ int sfx; /* Shadow file suffix */ CCKD_L2ENT l2; /* Copied level 2 entry */ cckd = dev->cckd_ext; obtain_lock (&cckd->filelock); /* Find the last used level 1 table entry */ for (l1x = cckd->cdevhdr[0].numl1tab - 1; l1x > 0; l1x--) { sfx = cckd->sfn; while (cckd->l1[sfx][l1x] == 0xffffffff && sfx > 0) sfx--; if (cckd->l1[sfx][l1x]) break; } /* Find the last used level 2 table entry */ for (l2x = 255; l2x >= 0; l2x--) { rc = cckd_read_l2ent (dev, &l2, l1x * 256 + l2x); if (rc < 0 || l2.pos != 0) break; } release_lock (&cckd->filelock); return (l1x * 256 + l2x + dev->ckdheads) / dev->ckdheads; } /*-------------------------------------------------------------------*/ /* Compressed fba read block(s) */ /*-------------------------------------------------------------------*/ int cfba_read_block (DEVBLK *dev, int blkgrp, BYTE *unitstat) { CCKDDASD_EXT *cckd; /* -> cckd extension */ int rc; /* Return code */ int cache; /* New active cache entry */ BYTE *cbuf; /* -> cache buffer */ BYTE *newbuf; /* Uncompressed buffer */ int len; /* Compressed length */ int maxlen; /* Size for cache entry */ cckd = dev->cckd_ext; if (dev->cache >= 0) cbuf = cache_getbuf (CACHE_DEVBUF, dev->cache, 0); else cbuf = NULL; maxlen = CFBA_BLOCK_SIZE + CKDDASD_TRKHDR_SIZE; /* Return if reading the same track image */ if (blkgrp == dev->bufcur && dev->cache >= 0) { /* Block group image may be compressed */ if ((cbuf[0] & CCKD_COMPRESS_MASK) != 0 && (cbuf[0] & dev->comps) == 0) { #if 0 /* Return if synchronous i/o */ if (dev->syncio_active) { cckd_trace (dev, "read blkgrp %d syncio compressed\n", blkgrp); cckdblk.stats_synciomisses++; dev->syncio_retry = 1; return -1; } #endif len = cache_getval(CACHE_DEVBUF, dev->cache) + CKDDASD_TRKHDR_SIZE; newbuf = cckd_uncompress (dev, cbuf, len, maxlen, blkgrp); if (newbuf == NULL) { dev->sense[0] = SENSE_EC; *unitstat = CSW_CE | CSW_DE | CSW_UC; dev->bufcur = dev->cache = -1; return -1; } cache_setbuf (CACHE_DEVBUF, dev->cache, newbuf, maxlen); cbuf = newbuf; dev->buf = newbuf + CKDDASD_TRKHDR_SIZE; dev->buflen = CFBA_BLOCK_SIZE; cache_setval (CACHE_DEVBUF, dev->cache, dev->buflen); dev->bufsize = cache_getlen (CACHE_DEVBUF, dev->cache); dev->bufupd = 0; cckd_trace (dev, "read bkgrp %d uncompressed len %d\n", blkgrp, dev->buflen); } dev->comp = cbuf[0] & CCKD_COMPRESS_MASK; return 0; } cckd_trace (dev, "read blkgrp %d (%s)\n", blkgrp, dev->syncio_active ? "synchronous" : "asynchronous"); /* Read the new blkgrp */ dev->bufupd = 0; *unitstat = 0; cache = cckd_read_trk (dev, blkgrp, 0, unitstat); if (cache < 0) { dev->bufcur = dev->cache = -1; return -1; } dev->cache = cache; cbuf = cache_getbuf (CACHE_DEVBUF, dev->cache, 0); dev->buf = cbuf + CKDDASD_TRKHDR_SIZE; dev->bufcur = blkgrp; dev->bufoff = 0; dev->bufoffhi = CFBA_BLOCK_SIZE; dev->buflen = CFBA_BLOCK_SIZE; cache_setval (CACHE_DEVBUF, dev->cache, dev->buflen); dev->bufsize = cache_getlen (CACHE_DEVBUF, dev->cache); dev->comp = cbuf[0] & CCKD_COMPRESS_MASK; /* If the image is compressed then call ourself recursively to cause the image to get uncompressed. This is because `bufcur' will match blkgrp and `comps' won't match `comp' */ if (dev->comp != 0 && (dev->comp & dev->comps) == 0) rc = cfba_read_block (dev, blkgrp, unitstat); else rc = 0; return rc; } /* end function cfba_read_block */ /*-------------------------------------------------------------------*/ /* Compressed fba write block(s) */ /*-------------------------------------------------------------------*/ int cfba_write_block (DEVBLK *dev, int blkgrp, int off, BYTE *buf, int len, BYTE *unitstat) { CCKDDASD_EXT *cckd; /* -> cckd extension */ int rc; /* Return code */ BYTE *cbuf; /* -> cache buffer */ cckd = dev->cckd_ext; if (dev->cache >= 0) cbuf = cache_getbuf (CACHE_DEVBUF, dev->cache, 0); else cbuf = NULL; /* Read the block group if it's not current or compressed. `dev->comps' is set to zero forcing the read routine to uncompress the image. */ if (blkgrp != dev->bufcur || (cbuf[0] & CCKD_COMPRESS_MASK) != 0) { dev->comps = 0; rc = (dev->hnd->read) (dev, blkgrp, unitstat); if (rc < 0) { dev->bufcur = dev->cache = -1; return -1; } } /* Copy the data into the buffer */ if (buf) memcpy (dev->buf + off, buf, len); /* Update the cache entry */ cache_setflag (CACHE_DEVBUF, dev->cache, ~0, CCKD_CACHE_UPDATED|CCKD_CACHE_USED); cckd->updated = 1; /* Notify the shared server of the update */ if (!dev->bufupd) { dev->bufupd = 1; shared_update_notify (dev, blkgrp); } return len; } /* end function cfba_write_block */ /*-------------------------------------------------------------------*/ /* Return used blocks */ /*-------------------------------------------------------------------*/ int cfba_used (DEVBLK *dev) { CCKDDASD_EXT *cckd; /* -> cckd extension */ int rc; /* Return code */ int l1x, l2x; /* Lookup table indexes */ int sfx; /* Shadow file suffix */ CCKD_L2ENT l2; /* Copied level 2 entry */ cckd = dev->cckd_ext; obtain_lock (&cckd->filelock); /* Find the last used level 1 table entry */ for (l1x = cckd->cdevhdr[0].numl1tab - 1; l1x > 0; l1x--) { sfx = cckd->sfn; while (cckd->l1[sfx][l1x] == 0xffffffff && sfx > 0) sfx--; if (cckd->l1[sfx][l1x]) break; } /* Find the last used level 2 table entry */ for (l2x = 255; l2x >= 0; l2x--) { rc = cckd_read_l2ent (dev, &l2, l1x * 256 + l2x); if (rc < 0 || l2.pos != 0) break; } release_lock (&cckd->filelock); return (l1x * 256 + l2x + CFBA_BLOCK_NUM) / CFBA_BLOCK_NUM; } /*-------------------------------------------------------------------*/ /* Read a track image */ /* */ /* This routine can be called by the i/o thread (`ra' == 0) or */ /* by readahead threads (0 < `ra' <= cckdblk.ramax). */ /* */ /*-------------------------------------------------------------------*/ int cckd_read_trk(DEVBLK *dev, int trk, int ra, BYTE *unitstat) { CCKDDASD_EXT *cckd; /* -> cckd extension */ int fnd; /* Cache index for hit */ int lru; /* Oldest unused cache index */ int len; /* Length of track image */ int maxlen; /* Length for buffer */ int curtrk = -1; /* Current track (at entry) */ U16 devnum; /* Device number */ U32 oldtrk; /* Stolen track number */ U32 flag; /* Cache flag */ BYTE *buf; /* Read buffer */ cckd = dev->cckd_ext; cckd_trace (dev, "%d rdtrk %d\n", ra, trk); maxlen = cckd->ckddasd ? dev->ckdtrksz : CFBA_BLOCK_SIZE + CKDDASD_TRKHDR_SIZE; if (!ra) obtain_lock (&cckd->iolock); cache_lock (CACHE_DEVBUF); /* Inactivate the old entry */ if (!ra) { curtrk = dev->bufcur; if (dev->cache >= 0) cache_setflag(CACHE_DEVBUF, dev->cache, ~CCKD_CACHE_ACTIVE, 0); dev->bufcur = dev->cache = -1; } cckd_read_trk_retry: /* scan the cache array for the track */ fnd = cache_lookup (CACHE_DEVBUF, CCKD_CACHE_SETKEY(dev->devnum, trk), &lru); /* check for cache hit */ if (fnd >= 0) { if (ra) /* readahead doesn't care about a cache hit */ { cache_unlock (CACHE_DEVBUF); return fnd; } /* If synchronous I/O and I/O is active then return with syncio_retry bit on */ if (dev->syncio_active) { if (cache_getflag(CACHE_DEVBUF, fnd) & CCKD_CACHE_IOBUSY) { cckd_trace (dev, "%d rdtrk[%d] %d syncio %s\n", ra, fnd, trk, cache_getflag(CACHE_DEVBUF, fnd) & CCKD_CACHE_READING ? "reading" : "writing"); cckdblk.stats_synciomisses++; dev->syncio_retry = 1; cache_unlock (CACHE_DEVBUF); release_lock (&cckd->iolock); return -1; } else cckdblk.stats_syncios++; } /* Mark the new entry active */ cache_setflag(CACHE_DEVBUF, fnd, ~0, CCKD_CACHE_ACTIVE | CCKD_CACHE_USED); cache_setage(CACHE_DEVBUF, fnd); /* If the entry is pending write then change it to `updated' */ if (cache_getflag(CACHE_DEVBUF, fnd) & CCKD_CACHE_WRITE) { cache_setflag(CACHE_DEVBUF, fnd, ~CCKD_CACHE_WRITE, CCKD_CACHE_UPDATED); cckd->wrpending--; if (cckd->iowaiters && !cckd->wrpending) broadcast_condition (&cckd->iocond); } buf = cache_getbuf(CACHE_DEVBUF, fnd, 0); cache_unlock (CACHE_DEVBUF); cckd_trace (dev, "%d rdtrk[%d] %d cache hit buf %p:%2.2x%2.2x%2.2x%2.2x%2.2x\n", ra, fnd, trk, buf, buf[0], buf[1], buf[2], buf[3], buf[4]); cckdblk.stats_switches++; cckd->switches++; cckdblk.stats_cachehits++; cckd->cachehits++; /* if read/write is in progress then wait for it to finish */ while (cache_getflag(CACHE_DEVBUF, fnd) & CCKD_CACHE_IOBUSY) { cckdblk.stats_iowaits++; cckd_trace (dev, "%d rdtrk[%d] %d waiting for %s\n", ra, fnd, trk, cache_getflag(CACHE_DEVBUF, fnd) & CCKD_CACHE_READING ? "read" : "write"); cache_setflag (CACHE_DEVBUF, fnd, ~0, CCKD_CACHE_IOWAIT); cckd->iowaiters++; wait_condition (&cckd->iocond, &cckd->iolock); cckd->iowaiters--; cache_setflag (CACHE_DEVBUF, fnd, ~CCKD_CACHE_IOWAIT, 0); cckd_trace (dev, "%d rdtrk[%d] %d io wait complete\n", ra, fnd, trk); } release_lock (&cckd->iolock); /* Asynchrously schedule readaheads */ if (curtrk > 0 && trk > curtrk && trk <= curtrk + 2) cckd_readahead (dev, trk); return fnd; } /* cache hit */ /* If not readahead and synchronous I/O then retry */ if (!ra && dev->syncio_active) { cache_unlock(CACHE_DEVBUF); release_lock (&cckd->iolock); cckd_trace (dev, "%d rdtrk[%d] %d syncio cache miss\n", ra, lru, trk); cckdblk.stats_synciomisses++; dev->syncio_retry = 1; return -1; } cckd_trace (dev, "%d rdtrk[%d] %d cache miss\n", ra, lru, trk); /* If no cache entry was stolen, then flush all outstanding writes. This requires us to release our locks. cache_wait should be called with only the cache_lock held. Fortunately, cache waits occur very rarely. */ if (lru < 0) /* No available entry to be stolen */ { cckd_trace (dev, "%d rdtrk[%d] %d no available cache entry\n", ra, lru, trk); cache_unlock (CACHE_DEVBUF); if (!ra) release_lock (&cckd->iolock); cckd_flush_cache_all(); cache_lock (CACHE_DEVBUF); cckdblk.stats_cachewaits++; cache_wait (CACHE_DEVBUF); if (!ra) { cache_unlock (CACHE_DEVBUF); obtain_lock (&cckd->iolock); cache_lock (CACHE_DEVBUF); } goto cckd_read_trk_retry; } CCKD_CACHE_GETKEY(lru, devnum, oldtrk); if (devnum != 0) { cckd_trace (dev, "%d rdtrk[%d] %d dropping %4.4X:%d from cache\n", ra, lru, trk, devnum, oldtrk); if (!(cache_getflag(CACHE_DEVBUF, lru) & CCKD_CACHE_USED)) { cckdblk.stats_readaheadmisses++; cckd->misses++; } } /* Initialize the entry */ cache_setkey(CACHE_DEVBUF, lru, CCKD_CACHE_SETKEY(dev->devnum, trk)); cache_setflag(CACHE_DEVBUF, lru, 0, CCKD_CACHE_READING); cache_setage(CACHE_DEVBUF, lru); cache_setval(CACHE_DEVBUF, lru, 0); if (!ra) { cckdblk.stats_switches++; cckd->switches++; cckdblk.stats_cachemisses++; cache_setflag(CACHE_DEVBUF, lru, ~0, CCKD_CACHE_ACTIVE|CCKD_CACHE_USED); } cache_setflag(CACHE_DEVBUF, lru, ~CACHE_TYPE, cckd->ckddasd ? DEVBUF_TYPE_CCKD : DEVBUF_TYPE_CFBA); buf = cache_getbuf(CACHE_DEVBUF, lru, maxlen); cckd_trace (dev, "%d rdtrk[%d] %d buf %p len %d\n", ra, lru, trk, buf, cache_getlen(CACHE_DEVBUF, lru)); cache_unlock (CACHE_DEVBUF); if (!ra) release_lock (&cckd->iolock); /* Asynchronously schedule readaheads */ if (!ra && curtrk > 0 && trk > curtrk && trk <= curtrk + 2) cckd_readahead (dev, trk); /* Clear the buffer if batch mode */ if (dev->batch) memset(buf, 0, maxlen); /* Read the track image */ obtain_lock (&cckd->filelock); len = cckd_read_trkimg (dev, buf, trk, unitstat); release_lock (&cckd->filelock); cache_setval (CACHE_DEVBUF, lru, len); obtain_lock (&cckd->iolock); /* Turn off the READING bit */ cache_lock (CACHE_DEVBUF); flag = cache_setflag(CACHE_DEVBUF, lru, ~CCKD_CACHE_READING, 0); cache_unlock (CACHE_DEVBUF); /* Wakeup other thread waiting for this read */ if (cckd->iowaiters && (flag & CCKD_CACHE_IOWAIT)) { cckd_trace (dev, "%d rdtrk[%d] %d signalling read complete\n", ra, lru, trk); broadcast_condition (&cckd->iocond); } release_lock (&cckd->iolock); if (ra) { cckdblk.stats_readaheads++; cckd->readaheads++; } cckd_trace (dev, "%d rdtrk[%d] %d complete buf %p:%2.2x%2.2x%2.2x%2.2x%2.2x\n", ra, lru, trk, buf, buf[0], buf[1], buf[2], buf[3], buf[4]); if (cache_busy_percent(CACHE_DEVBUF) > 80) cckd_flush_cache_all(); return lru; } /* end function cckd_read_trk */ /*-------------------------------------------------------------------*/ /* Schedule asynchronous readaheads */ /*-------------------------------------------------------------------*/ void cckd_readahead (DEVBLK *dev, int trk) { CCKDDASD_EXT *cckd; /* -> cckd extension */ int i, r; /* Indexes */ TID tid; /* Readahead thread id */ cckd = dev->cckd_ext; if (cckdblk.ramax < 1 || cckdblk.readaheads < 1) return; obtain_lock (&cckdblk.ralock); /* Scan the cache to see if the tracks are already there */ memset(cckd->ralkup, 0, sizeof(cckd->ralkup)); cckd->ratrk = trk; cache_lock(CACHE_DEVBUF); cache_scan(CACHE_DEVBUF, cckd_readahead_scan, dev); cache_unlock(CACHE_DEVBUF); /* Scan the queue to see if the tracks are already there */ for (r = cckdblk.ra1st; r >= 0; r = cckdblk.ra[r].next) if (cckdblk.ra[r].dev == dev) { i = cckdblk.ra[r].trk - trk; if (i > 0 && i <= cckdblk.readaheads) cckd->ralkup[i-1] = 1; } /* Queue the tracks to the readahead queue */ for (i = 1; i <= cckdblk.readaheads && cckdblk.rafree >= 0; i++) { if (cckd->ralkup[i-1]) continue; if (trk + i >= dev->ckdtrks) break; r = cckdblk.rafree; cckdblk.rafree = cckdblk.ra[r].next; if (cckdblk.ralast < 0) { cckdblk.ra1st = cckdblk.ralast = r; cckdblk.ra[r].prev = cckdblk.ra[r].next = -1; } else { cckdblk.ra[cckdblk.ralast].next = r; cckdblk.ra[r].prev = cckdblk.ralast; cckdblk.ra[r].next = -1; cckdblk.ralast = r; } cckdblk.ra[r].trk = trk + i; cckdblk.ra[r].dev = dev; } /* Schedule the readahead if any are pending */ if (cckdblk.ra1st >= 0) { if (cckdblk.rawaiting) signal_condition (&cckdblk.racond); else if (cckdblk.ras < cckdblk.ramax) create_thread (&tid, JOINABLE, cckd_ra, NULL, "cckd_ra"); } release_lock (&cckdblk.ralock); } /* end function cckd_readahead */ int cckd_readahead_scan (int *answer, int ix, int i, void *data) { CCKDDASD_EXT *cckd; /* -> cckd extension */ U16 devnum; /* Cached device number */ U32 trk; /* Cached track */ DEVBLK *dev = data; /* -> device block */ int k; /* Index */ UNREFERENCED(answer); UNREFERENCED(ix); cckd = dev->cckd_ext; CCKD_CACHE_GETKEY(i, devnum, trk); if (devnum == dev->devnum) { k = (int)trk - cckd->ratrk; if (k > 0 && k <= cckdblk.readaheads) cckd->ralkup[k-1] = 1; } return 0; } /*-------------------------------------------------------------------*/ /* Asynchronous readahead thread */ /*-------------------------------------------------------------------*/ void cckd_ra () { CCKDDASD_EXT *cckd; /* -> cckd extension */ DEVBLK *dev; /* Readahead devblk */ int trk; /* Readahead track */ int ra; /* Readahead index */ int r; /* Readahead queue index */ TID tid; /* Readahead thread id */ obtain_lock (&cckdblk.ralock); ra = ++cckdblk.ras; /* Return without messages if too many already started */ if (ra > cckdblk.ramax) { --cckdblk.ras; release_lock (&cckdblk.ralock); return; } if (!cckdblk.batch) { logmsg (_("HHCCD001I Readahead thread %d started: tid="TIDPAT", pid=%d\n"), ra, thread_id(), getpid()); } while (ra <= cckdblk.ramax) { if (cckdblk.ra1st < 0) { cckdblk.rawaiting++; wait_condition (&cckdblk.racond, &cckdblk.ralock); cckdblk.rawaiting--; } /* Possibly shutting down if no writes pending */ if (cckdblk.ra1st < 0) continue; r = cckdblk.ra1st; trk = cckdblk.ra[r].trk; dev = cckdblk.ra[r].dev; cckd = dev->cckd_ext; /* Requeue the 1st entry to the readahead free queue */ cckdblk.ra1st = cckdblk.ra[r].next; if (cckdblk.ra[r].next > -1) cckdblk.ra[cckdblk.ra[r].next].prev = -1; else cckdblk.ralast = -1; cckdblk.ra[r].next = cckdblk.rafree; cckdblk.rafree = r; /* Schedule the other readaheads if any are still pending */ if (cckdblk.ra1st) { if (cckdblk.rawaiting) signal_condition (&cckdblk.racond); else if (cckdblk.ras < cckdblk.ramax) create_thread (&tid, JOINABLE, cckd_ra, dev, "cckd_ra"); } if (!cckd || cckd->stopping || cckd->merging) continue; cckd->ras++; release_lock (&cckdblk.ralock); /* Read the readahead track */ cckd_read_trk (dev, trk, ra, NULL); obtain_lock (&cckdblk.ralock); cckd->ras--; } if (!cckdblk.batch) logmsg (_("HHCCD011I Readahead thread %d stopping: tid="TIDPAT", pid=%d\n"), ra, thread_id(), getpid()); --cckdblk.ras; if (!cckdblk.ras) signal_condition(&cckdblk.termcond); release_lock(&cckdblk.ralock); } /* end thread cckd_ra_thread */ /*-------------------------------------------------------------------*/ /* Flush updated cache entries for a device */ /* */ /* Caller holds the cckd->iolock */ /* cckdblk.wrlock then cache_lock is obtained and released */ /*-------------------------------------------------------------------*/ void cckd_flush_cache(DEVBLK *dev) { int rc; /* Return code */ TID tid; /* Writer thread id */ /* Scan cache for updated cache entries */ obtain_lock (&cckdblk.wrlock); cache_lock (CACHE_DEVBUF); rc = cache_scan (CACHE_DEVBUF, cckd_flush_cache_scan, dev); cache_unlock (CACHE_DEVBUF); /* Schedule the writer if any writes are pending */ if (cckdblk.wrpending) { if (cckdblk.wrwaiting) signal_condition (&cckdblk.wrcond); else if (cckdblk.wrs < cckdblk.wrmax) { create_thread (&tid, JOINABLE, cckd_writer, NULL, "cckd_writer"); } } release_lock (&cckdblk.wrlock); } int cckd_flush_cache_scan (int *answer, int ix, int i, void *data) { CCKDDASD_EXT *cckd; /* -> cckd extension */ U16 devnum; /* Cached device number */ U32 trk; /* Cached track */ DEVBLK *dev = data; /* -> device block */ UNREFERENCED(answer); cckd = dev->cckd_ext; CCKD_CACHE_GETKEY(i, devnum, trk); if ((cache_getflag(ix,i) & CACHE_BUSY) == CCKD_CACHE_UPDATED && dev->devnum == devnum) { cache_setflag (ix, i, ~CCKD_CACHE_UPDATED, CCKD_CACHE_WRITE); ++cckd->wrpending; ++cckdblk.wrpending; cckd_trace (dev, "flush file[%d] cache[%d] %4.4X trk %d\n", cckd->sfn, i, devnum, trk); } return 0; } void cckd_flush_cache_all() { CCKDDASD_EXT *cckd; /* -> cckd extension */ DEVBLK *dev = NULL; /* -> device block */ cckd_lock_devchain(0); for (dev = cckdblk.dev1st; dev; dev = cckd->devnext) { cckd = dev->cckd_ext; obtain_lock (&cckd->iolock); if (!cckd->merging && !cckd->stopping) cckd_flush_cache(dev); release_lock (&cckd->iolock); } cckd_unlock_devchain(); } /*-------------------------------------------------------------------*/ /* Purge cache entries for a device */ /* */ /* Caller holds the iolock */ /* cache_lock is obtained and released */ /*-------------------------------------------------------------------*/ void cckd_purge_cache(DEVBLK *dev) { /* Scan cache and purge entries */ cache_lock (CACHE_DEVBUF); cache_scan (CACHE_DEVBUF, cckd_purge_cache_scan, dev); cache_unlock (CACHE_DEVBUF); } int cckd_purge_cache_scan (int *answer, int ix, int i, void *data) { U16 devnum; /* Cached device number */ U32 trk; /* Cached track */ DEVBLK *dev = data; /* -> device block */ UNREFERENCED(answer); CCKD_CACHE_GETKEY(i, devnum, trk); if (dev->devnum == devnum) { cache_release (ix, i, 0); cckd_trace (dev, "purge cache[%d] %4.4X trk %d purged\n", i, devnum, trk); } return 0; } /*-------------------------------------------------------------------*/ /* Writer thread */ /*-------------------------------------------------------------------*/ void cckd_writer(void *arg) { DEVBLK *dev; /* Device block */ CCKDDASD_EXT *cckd; /* -> cckd extension */ int writer; /* Writer identifier */ int o; /* Cache entry found */ U16 devnum; /* Device number */ BYTE *buf; /* Buffer */ BYTE *bufp; /* Buffer to be written */ int len, bufl; /* Buffer lengths */ int trk; /* Track number */ int comp; /* Compression algorithm */ int parm; /* Compression parameter */ TID tid; /* Writer thead id */ U32 flag; /* Cache flag */ static char *compress[] = {"none", "zlib", "bzip2"}; BYTE buf2[65536]; /* Compress buffer */ UNREFERENCED(arg); #ifndef WIN32 /* Set writer priority just below cpu priority to mimimize the compression effect */ if(cckdblk.wrprio >= 0) setpriority (PRIO_PROCESS, 0, cckdblk.wrprio); #endif obtain_lock (&cckdblk.wrlock); writer = ++cckdblk.wrs; /* Return without messages if too many already started */ if (writer > cckdblk.wrmax) { --cckdblk.wrs; release_lock (&cckdblk.wrlock); return; } if (!cckdblk.batch) { logmsg (_("HHCCD002I Writer thread %d started: tid="TIDPAT", pid=%d\n"), writer, thread_id(), getpid()); } while (writer <= cckdblk.wrmax || cckdblk.wrpending) { /* Wait for work */ if (cckdblk.wrpending == 0) { cckdblk.wrwaiting++; wait_condition (&cckdblk.wrcond, &cckdblk.wrlock); cckdblk.wrwaiting--; } /* Scan the cache for the oldest pending write */ cache_lock (CACHE_DEVBUF); o = cache_scan (CACHE_DEVBUF, cckd_writer_scan, NULL); /* Possibly shutting down if no writes pending */ if (o < 0) { cache_unlock (CACHE_DEVBUF); cckdblk.wrpending = 0; continue; } cache_setflag (CACHE_DEVBUF, o, ~CCKD_CACHE_WRITE, CCKD_CACHE_WRITING); cache_unlock (CACHE_DEVBUF); /* Schedule the other writers if any writes are still pending */ cckdblk.wrpending--; if (cckdblk.wrpending) { if (cckdblk.wrwaiting) signal_condition (&cckdblk.wrcond); else if (cckdblk.wrs < cckdblk.wrmax) { create_thread (&tid, JOINABLE, cckd_writer, NULL, "cckd_writer"); } } release_lock (&cckdblk.wrlock); /* Prepare to compress */ CCKD_CACHE_GETKEY(o, devnum, trk); dev = cckd_find_device_by_devnum (devnum); cckd = dev->cckd_ext; buf = cache_getbuf(CACHE_DEVBUF, o, 0); len = cckd_trklen (dev, buf); comp = len < CCKD_COMPRESS_MIN ? CCKD_COMPRESS_NONE : cckdblk.comp == 0xff ? cckd->cdevhdr[cckd->sfn].compress : cckdblk.comp; parm = cckdblk.compparm < 0 ? cckd->cdevhdr[cckd->sfn].compress_parm : cckdblk.compparm; cckd_trace (dev, "%d wrtrk[%d] %d len %d buf %p:%2.2x%2.2x%2.2x%2.2x%2.2x\n", writer, o, trk, len, buf, buf[0], buf[1],buf[2],buf[3],buf[4]); /* Compress the image if not null */ if ((len = cckd_check_null_trk (dev, buf, trk, len)) > CKDDASD_NULLTRK_FMTMAX) { /* Stress adjustments */ if ((cache_waiters(CACHE_DEVBUF) || cache_busy(CACHE_DEVBUF) > 90) && !cckdblk.nostress) { cckdblk.stats_stresswrites++; comp = len < CCKD_STRESS_MINLEN ? CCKD_COMPRESS_NONE : CCKD_STRESS_COMP; parm = cache_busy(CACHE_DEVBUF) <= 95 ? CCKD_STRESS_PARM1 : CCKD_STRESS_PARM2; } /* Compress the track image */ cckd_trace (dev, "%d wrtrk[%d] %d comp %s parm %d\n", writer, o, trk, compress[comp], parm); bufp = (BYTE *)&buf2; bufl = cckd_compress(dev, &bufp, buf, len, comp, parm); cckd_trace (dev, "%d wrtrk[%d] %d compressed length %d\n", writer, o, trk, bufl); } else { bufp = buf; bufl = len; } obtain_lock (&cckd->filelock); /* Turn on read-write header bits if not already on */ if (!(cckd->cdevhdr[cckd->sfn].options & CCKD_OPENED)) { cckd->cdevhdr[cckd->sfn].options |= (CCKD_OPENED | CCKD_ORDWR); cckd_write_chdr (dev); } /* Write the track image */ cckd_write_trkimg (dev, bufp, bufl, trk, CCKD_SIZE_ANY); release_lock (&cckd->filelock); /* Schedule the garbage collector */ if (cckdblk.gcs < cckdblk.gcmax) create_thread (&tid, JOINABLE, cckd_gcol, NULL, "cckd_gcol"); obtain_lock (&cckd->iolock); cache_lock (CACHE_DEVBUF); flag = cache_setflag (CACHE_DEVBUF, o, ~CCKD_CACHE_WRITING, 0); cache_unlock (CACHE_DEVBUF); cckd->wrpending--; if (cckd->iowaiters && ((flag & CCKD_CACHE_IOWAIT) || !cckd->wrpending)) { cckd_trace (dev, "writer[%d] cache[%2.2d] %d signalling write complete\n", writer, o, trk); broadcast_condition (&cckd->iocond); } release_lock(&cckd->iolock); cckd_trace (dev, "%d wrtrk[%2.2d] %d complete flags:%8.8x\n", writer, o, trk, cache_getflag(CACHE_DEVBUF,o)); obtain_lock(&cckdblk.wrlock); } if (!cckdblk.batch) logmsg (_("HHCCD012I Writer thread %d stopping: tid="TIDPAT", pid=%d\n"), writer, thread_id(), getpid()); cckdblk.wrs--; if (cckdblk.wrs == 0) signal_condition(&cckdblk.termcond); release_lock(&cckdblk.wrlock); } /* end thread cckd_writer */ int cckd_writer_scan (int *o, int ix, int i, void *data) { UNREFERENCED(data); if ((cache_getflag(ix,i) & DEVBUF_TYPE_COMP) && (cache_getflag(ix,i) & CCKD_CACHE_WRITE) && (*o == -1 || cache_getage(ix, i) < cache_getage(ix, *o))) *o = i; return 0; } /*-------------------------------------------------------------------*/ /* Debug routine for checking the free space array */ /*-------------------------------------------------------------------*/ void cckd_chk_space(DEVBLK *dev) { #if 1 CCKDDASD_EXT *cckd; /* -> cckd extension */ int sfx; /* Shadow file index */ int err = 0, n = 0, i, p; size_t largest=0; size_t total=0; off_t fpos; cckd = dev->cckd_ext; sfx = cckd->sfn; p = -1; fpos = cckd->cdevhdr[sfx].free; for (i = cckd->free1st; i >= 0; i = cckd->free[i].next) { n++; total += cckd->free[i].len; if (n > cckd->freenbr) break; if (cckd->free[i].prev != p) err = 1; if (cckd->free[i].next >= 0) { if (fpos + cckd->free[i].len > cckd->free[i].pos) err = 1; } else { if (fpos + cckd->free[i].len > cckd->cdevhdr[sfx].size) err = 1; } if (cckd->free[i].pending == 0 && cckd->free[i].len > largest) largest = cckd->free[i].len; fpos = cckd->free[i].pos; p = i; } if (err || (cckd->cdevhdr[sfx].free != 0 && cckd->cdevhdr[sfx].free_number == 0) || (cckd->cdevhdr[sfx].free == 0 && cckd->cdevhdr[sfx].free_number != 0) || (n != cckd->cdevhdr[sfx].free_number) || (total != cckd->cdevhdr[sfx].free_total - cckd->cdevhdr[sfx].free_imbed) || (cckd->freelast != p) || (largest != cckd->cdevhdr[sfx].free_largest) ) { cckd_trace (dev, "cdevhdr[%d] size %10d used %10d free 0x%8.8x\n", sfx,cckd->cdevhdr[sfx].size,cckd->cdevhdr[sfx].used, cckd->cdevhdr[sfx].free); cckd_trace (dev, " nbr %10d total %10d imbed %10d largest %10d\n", cckd->cdevhdr[sfx].free_number, cckd->cdevhdr[sfx].free_total,cckd->cdevhdr[sfx].free_imbed, cckd->cdevhdr[sfx].free_largest); cckd_trace (dev, "free %p nbr %d 1st %d last %d avail %d\n", cckd->free,cckd->freenbr,cckd->free1st, cckd->freelast,cckd->freeavail); cckd_trace (dev, "found nbr %d total %ld largest %ld\n",n,(long)total,(long)largest); fpos = cckd->cdevhdr[sfx].free; for (n = 0, i = cckd->free1st; i >= 0; i = cckd->free[i].next) { if (++n > cckd->freenbr) break; cckd_trace (dev, "%4d: [%4d] prev[%4d] next[%4d] pos %8.8" I64_FMT "x len %8d %8.8" I64_FMT "x pend %d\n", n, i, cckd->free[i].prev, cckd->free[i].next, (long long)fpos, cckd->free[i].len, (long long)fpos + cckd->free[i].len, cckd->free[i].pending); fpos = cckd->free[i].pos; } cckd_print_itrace(); } #endif } /* end function cckd_chk_space */ /*-------------------------------------------------------------------*/ /* Get file space */ /*-------------------------------------------------------------------*/ off_t cckd_get_space(DEVBLK *dev, int *size, int flags) { CCKDDASD_EXT *cckd; /* -> cckd extension */ int i,p,n; /* Free space indexes */ int len2; /* Other lengths */ off_t fpos; /* Free space offset */ unsigned int flen; /* Free space size */ int sfx; /* Shadow file index */ int len; /* Requested length */ cckd = dev->cckd_ext; sfx = cckd->sfn; len = *size; if (flags & CCKD_L2SPACE) { flags |= CCKD_SIZE_EXACT; len = *size = CCKD_L2TAB_SIZE; } cckd_trace (dev, "get_space len %d largest %d flags 0x%2.2x\n", len, cckd->cdevhdr[sfx].free_largest, flags); if (len <= CKDDASD_NULLTRK_FMTMAX) return 0; if (!cckd->free) cckd_read_fsp (dev); len2 = len + CCKD_FREEBLK_SIZE; /* Get space at the end if no space is large enough */ if (len2 > (int)cckd->cdevhdr[sfx].free_largest && len != (int)cckd->cdevhdr[sfx].free_largest) { cckd_get_space_atend: fpos = (off_t)cckd->cdevhdr[sfx].size; if ((long long)(fpos + len) > cckd->maxsize) { logmsg (_("HHCCD102E %4.4X file[%d] get space error, size exceeds %lldM\n"), dev->devnum, sfx, (cckd->maxsize >> 20) + 1); return -1; } cckd->cdevhdr[sfx].size += len; cckd->cdevhdr[sfx].used += len; cckd_trace (dev, "get_space atend 0x%" I64_FMT "x len %d\n",(long long)fpos, len); return fpos; } /* Scan free space chain */ fpos = (off_t)cckd->cdevhdr[sfx].free; for (i = cckd->free1st; i >= 0; i = cckd->free[i].next) { if (cckd->free[i].pending == 0 && (len2 <= (int)cckd->free[i].len || len == (int)cckd->free[i].len) && ((flags & CCKD_L2SPACE) || fpos >= cckd->l2bounds)) break; fpos = (off_t)cckd->free[i].pos; } /* This can happen if largest comes before l2bounds */ if (i < 0) goto cckd_get_space_atend; flen = cckd->free[i].len; p = cckd->free[i].prev; n = cckd->free[i].next; /* * If `CCKD_SIZE_ANY' bit is set and the left over space is small * enough, then use the entire free space */ if ((flags & CCKD_SIZE_ANY) && flen <= cckd->freemin) *size = (int)flen; /* Remove the new space from free space */ if (*size < (int)flen) { cckd->free[i].len -= *size; if (p >= 0) cckd->free[p].pos += *size; else cckd->cdevhdr[sfx].free += *size; } else { cckd->cdevhdr[sfx].free_number--; /* Remove the free space entry from the chain */ if (p >= 0) { cckd->free[p].pos = cckd->free[i].pos; cckd->free[p].next = n; } else { cckd->cdevhdr[sfx].free = cckd->free[i].pos; cckd->free1st = n; } if (n >= 0) cckd->free[n].prev = p; else cckd->freelast = p; /* Add entry to the available queue */ cckd->free[i].next = cckd->freeavail; cckd->freeavail = i; } /* Find the largest free space if we got the largest */ if (flen >= cckd->cdevhdr[sfx].free_largest) { int i; cckd->cdevhdr[sfx].free_largest = 0; for (i = cckd->free1st; i >= 0; i = cckd->free[i].next) if (cckd->free[i].len > cckd->cdevhdr[sfx].free_largest && cckd->free[i].pending == 0) cckd->cdevhdr[sfx].free_largest = cckd->free[i].len; } /* Update free space stats */ cckd->cdevhdr[sfx].used += len; cckd->cdevhdr[sfx].free_total -= len; cckd->cdevhdr[sfx].free_imbed += *size - len; cckd_trace (dev, "get_space found 0x%" I64_FMT "x len %d size %d\n", (long long)fpos, len, *size); return fpos; } /* end function cckd_get_space */ /*-------------------------------------------------------------------*/ /* Release file space */ /*-------------------------------------------------------------------*/ void cckd_rel_space(DEVBLK *dev, off_t pos, int len, int size) { CCKDDASD_EXT *cckd; /* -> cckd extension */ int sfx; /* Shadow file index */ off_t ppos, npos; /* Prev/next free offsets */ int i, p, n; /* Free space indexes */ int pending; /* Calculated pending value */ int fsize = size; /* Free space size */ if (len <= CKDDASD_NULLTRK_FMTMAX || pos == 0 || pos == 0xffffffff) return; cckd = dev->cckd_ext; sfx = cckd->sfn; cckd_trace (dev, "rel_space offset %" I64_FMT "x len %d size %d\n", (long long)pos, len, size); if (!cckd->free) cckd_read_fsp (dev); // cckd_chk_space(dev); /* Scan free space chain */ ppos = -1; npos = cckd->cdevhdr[sfx].free; for (p = -1, n = cckd->free1st; n >= 0; n = cckd->free[n].next) { if (pos < npos) break; ppos = npos; npos = cckd->free[n].pos; p = n; } /* Calculate the `pending' value */ pending = cckdblk.freepend >= 0 ? cckdblk.freepend : 1 + (1 - cckdblk.fsync); /* If possible use previous adjacent free space otherwise get an available one */ if (p >= 0 && ppos + cckd->free[p].len == pos && cckd->free[p].pending == pending) { cckd->free[p].len += size; fsize = cckd->free[p].len; } else { /* Increase the size of the free space array if necessary */ if (cckd->freeavail < 0) { cckd->freeavail = cckd->freenbr; cckd->freenbr += 1024; cckd->free = realloc ( cckd->free, cckd->freenbr * CCKD_FREEBLK_ISIZE); for (i = cckd->freeavail; i < cckd->freenbr; i++) cckd->free[i].next = i + 1; cckd->free[i-1].next = -1; cckd->freemin = CCKD_FREE_MIN_SIZE + ((cckd->freenbr >> 10) * CCKD_FREE_MIN_INCR); } /* Get an available free space entry */ i = cckd->freeavail; cckd->freeavail = cckd->free[i].next; cckd->cdevhdr[sfx].free_number++; /* Update the new entry */ cckd->free[i].prev = p; cckd->free[i].next = n; cckd->free[i].len = size; cckd->free[i].pending = pending; /* Update the previous entry */ if (p >= 0) { cckd->free[i].pos = cckd->free[p].pos; cckd->free[p].pos = pos; cckd->free[p].next = i; } else { cckd->free[i].pos = cckd->cdevhdr[sfx].free; cckd->cdevhdr[sfx].free = pos; cckd->free1st = i; } /* Update the next entry */ if (n >= 0) cckd->free[n].prev = i; else cckd->freelast = i; } /* Update the free space statistics */ cckd->cdevhdr[sfx].used -= len; cckd->cdevhdr[sfx].free_total += len; cckd->cdevhdr[sfx].free_imbed -= size - len; if (!pending && (U32)fsize > cckd->cdevhdr[sfx].free_largest) cckd->cdevhdr[sfx].free_largest = (U32)fsize; // cckd_chk_space(dev); } /* end function cckd_rel_space */ /*-------------------------------------------------------------------*/ /* Flush pending free space */ /*-------------------------------------------------------------------*/ void cckd_flush_space(DEVBLK *dev) { CCKDDASD_EXT *cckd; /* -> cckd extension */ int p,i,n; /* Free free space indexes */ int sfx; /* Shadow file index */ U32 ppos, pos; /* Free space offsets */ cckd = dev->cckd_ext; sfx = cckd->sfn; cckd_trace (dev, "flush_space nbr %d\n",cckd->cdevhdr[sfx].free_number); /* Make sure the free space chain is built */ if (!cckd->free) cckd_read_fsp (dev); // cckd_chk_space(dev); if (cckd->cdevhdr[sfx].free_number == 0 || cckd->cdevhdr[sfx].free == 0) { cckd->cdevhdr[sfx].free_number = cckd->cdevhdr[sfx].free = 0; cckd->free1st = cckd->freelast = cckd->freeavail = -1; } pos = cckd->cdevhdr[sfx].free; ppos = p = -1; cckd->cdevhdr[sfx].free_number = cckd->cdevhdr[sfx].free_largest = 0; for (i = cckd->free1st; i >= 0; i = cckd->free[i].next) { /* Decrement the pending count */ if (cckd->free[i].pending) --cckd->free[i].pending; /* Combine adjacent free spaces */ while (pos + cckd->free[i].len == cckd->free[i].pos) { n = cckd->free[i].next; if (cckd->free[n].pending > cckd->free[i].pending + 1 || cckd->free[n].pending < cckd->free[i].pending) break; cckd->free[i].pos = cckd->free[n].pos; cckd->free[i].len += cckd->free[n].len; cckd->free[i].next = cckd->free[n].next; cckd->free[n].next = cckd->freeavail; cckd->freeavail = n; n = cckd->free[i].next; if (n >= 0) cckd->free[n].prev = i; } ppos = pos; pos = cckd->free[i].pos; cckd->cdevhdr[sfx].free_number++; if (cckd->free[i].len > cckd->cdevhdr[sfx].free_largest && !cckd->free[i].pending) cckd->cdevhdr[sfx].free_largest = cckd->free[i].len; p = i; } cckd->freelast = p; cckd_trace (dev, "rel_flush_space nbr %d (after merge)\n", cckd->cdevhdr[sfx].free_number); /* If the last free space is at the end of the file then release it */ if (p >= 0 && ppos + cckd->free[p].len == cckd->cdevhdr[sfx].size && !cckd->free[p].pending) { i = p; p = cckd->free[i].prev; cckd_trace (dev, "file[%d] rel_flush_space atend 0x%" I64_FMT "x len %d\n", sfx, (long long)ppos, cckd->free[i].len); /* Remove the entry from the chain */ if (p >= 0) { cckd->free[p].pos = 0; cckd->free[p].next = -1; } else { cckd->cdevhdr[sfx].free = 0; cckd->free1st = -1; } cckd->freelast = p; /* Add the entry to the available chain */ cckd->free[i].next = cckd->freeavail; cckd->freeavail = i; /* Update the device header */ cckd->cdevhdr[sfx].size -= cckd->free[i].len; cckd->cdevhdr[sfx].free_total -= cckd->free[i].len; cckd->cdevhdr[sfx].free_number--; if (cckd->free[i].len >= cckd->cdevhdr[sfx].free_largest) { cckd->cdevhdr[sfx].free_largest = 0; for (i = cckd->free1st; i >= 0; i = cckd->free[i].next) if (cckd->free[i].len > cckd->cdevhdr[sfx].free_largest && cckd->free[i].pending == 0) cckd->cdevhdr[sfx].free_largest = cckd->free[i].len; } /* Truncate the file */ cckd_ftruncate (dev, sfx, (off_t)cckd->cdevhdr[sfx].size); } /* Release space at end of the file */ // cckd_chk_space(dev); } /* end function cckd_flush_space */ /*-------------------------------------------------------------------*/ /* Read compressed dasd header */ /*-------------------------------------------------------------------*/ int cckd_read_chdr (DEVBLK *dev) { CCKDDASD_EXT *cckd; /* -> cckd extension */ int sfx; /* File index */ cckd = dev->cckd_ext; sfx = cckd->sfn; cckd_trace (dev, "file[%d] read_chdr\n", sfx); memset (&cckd->cdevhdr[sfx], 0, CCKDDASD_DEVHDR_SIZE); /* Read the device header */ if (cckd_read (dev, sfx, CKDDASD_DEVHDR_SIZE, &cckd->cdevhdr[sfx], CCKDDASD_DEVHDR_SIZE) < 0) return -1; /* Check endian format */ cckd->swapend[sfx] = 0; if ((cckd->cdevhdr[sfx].options & CCKD_BIGENDIAN) != cckd_endian()) { if (cckd->open[sfx] == CCKD_OPEN_RW) { if (cckd_swapend (dev) < 0) return -1; cckd_swapend_chdr (&cckd->cdevhdr[sfx]); } else { cckd->swapend[sfx] = 1; cckd_swapend_chdr (&cckd->cdevhdr[sfx]); } } /* Set default null format */ if (cckd->cdevhdr[sfx].nullfmt > CKDDASD_NULLTRK_FMTMAX) cckd->cdevhdr[sfx].nullfmt = 0; if (cckd->cdevhdr[sfx].nullfmt == 0 && dev->oslinux && dev->devtype == 0x3390) cckd->cdevhdr[sfx].nullfmt = CKDDASD_NULLTRK_FMT2; if (cckd->cdevhdr[sfx].nullfmt == CKDDASD_NULLTRK_FMT2) dev->oslinux = 1; return 0; } /* end function cckd_read_chdr */ /*-------------------------------------------------------------------*/ /* Write compressed dasd header */ /*-------------------------------------------------------------------*/ int cckd_write_chdr (DEVBLK *dev) { CCKDDASD_EXT *cckd; /* -> cckd extension */ int sfx; /* File index */ cckd = dev->cckd_ext; sfx = cckd->sfn; cckd_trace (dev, "file[%d] write_chdr\n", sfx); /* Set version.release.modlvl */ cckd->cdevhdr[sfx].vrm[0] = CCKD_VERSION; cckd->cdevhdr[sfx].vrm[1] = CCKD_RELEASE; cckd->cdevhdr[sfx].vrm[2] = CCKD_MODLVL; if (cckd_write (dev, sfx, CCKD_DEVHDR_POS, &cckd->cdevhdr[sfx], CCKD_DEVHDR_SIZE) < 0) return -1; return 0; } /* end function cckd_write_chdr */ /*-------------------------------------------------------------------*/ /* Read the level 1 table */ /*-------------------------------------------------------------------*/ int cckd_read_l1 (DEVBLK *dev) { CCKDDASD_EXT *cckd; /* -> cckd extension */ int sfx; /* File index */ int len; /* Length of level 1 table */ int i; /* Work integer */ cckd = dev->cckd_ext; sfx = cckd->sfn; cckd_trace (dev, "file[%d] read_l1 offset 0x%"I64_FMT"x\n", sfx, (U64)CCKD_L1TAB_POS); /* Free the old level 1 table if it exists */ cckd->l1[sfx] = cckd_free (dev, "l1", cckd->l1[sfx]); /* Allocate the level 1 table */ len = cckd->cdevhdr[sfx].numl1tab * CCKD_L1ENT_SIZE; if ((cckd->l1[sfx] = cckd_malloc (dev, "l1", len)) == NULL) return -1; memset(cckd->l1[sfx], sfx ? 0xFF : 0, len); /* Read the level 1 table */ if (cckd_read (dev, sfx, CCKD_L1TAB_POS, cckd->l1[sfx], len) < 0) return -1; /* Fix endianess */ if (cckd->swapend[sfx]) cckd_swapend_l1 (cckd->l1[sfx], cckd->cdevhdr[sfx].numl1tab); /* Determine bounds */ cckd->l2bounds = CCKD_L1TAB_POS + len; for (i = 0; i < cckd->cdevhdr[sfx].numl1tab; i++) if (cckd->l1[sfx][i] != 0 && cckd->l1[sfx][i] != 0xffffffff) cckd->l2bounds += CCKD_L2TAB_SIZE; /* Check if all l2 tables are within bounds */ cckd->l2ok = 1; for (i = 0; i < cckd->cdevhdr[sfx].numl1tab && cckd->l2ok; i++) if (cckd->l1[sfx][i] != 0 && cckd->l1[sfx][i] != 0xffffffff) if (cckd->l1[sfx][i] > cckd->l2bounds - CCKD_L2TAB_SIZE) cckd->l2ok = 0; return 0; } /* end function cckd_read_l1 */ /*-------------------------------------------------------------------*/ /* Write the level 1 table */ /*-------------------------------------------------------------------*/ int cckd_write_l1 (DEVBLK *dev) { CCKDDASD_EXT *cckd; /* -> cckd extension */ int sfx; /* File index */ int len; /* Length of level 1 table */ cckd = dev->cckd_ext; sfx = cckd->sfn; len = cckd->cdevhdr[sfx].numl1tab * CCKD_L1ENT_SIZE; cckd_trace (dev, "file[%d] write_l1 0x%"I64_FMT"x len %d\n", sfx, (U64)CCKD_L1TAB_POS, len); if (cckd_write (dev, sfx, CCKD_L1TAB_POS, cckd->l1[sfx], len) < 0) return -1; return 0; } /* end function cckd_write_l1 */ /*-------------------------------------------------------------------*/ /* Update a level 1 table entry */ /*-------------------------------------------------------------------*/ int cckd_write_l1ent (DEVBLK *dev, int l1x) { CCKDDASD_EXT *cckd; /* -> cckd extension */ int sfx; /* File index */ off_t off; /* Offset to l1 entry */ cckd = dev->cckd_ext; sfx = cckd->sfn; off = (off_t)(CCKD_L1TAB_POS + l1x * CCKD_L1ENT_SIZE); cckd_trace (dev, "file[%d] write_l1ent[%d] , 0x%" I64_FMT "x\n", sfx, l1x, (long long)off); if (cckd_write (dev, sfx, off, &cckd->l1[sfx][l1x], CCKD_L1ENT_SIZE) < 0) return -1; return 0; } /* end function cckd_write_l1ent */ /*-------------------------------------------------------------------*/ /* Initial read */ /*-------------------------------------------------------------------*/ int cckd_read_init (DEVBLK *dev) { CCKDDASD_EXT *cckd; /* -> cckd extension */ int sfx; /* File index */ CKDDASD_DEVHDR devhdr; /* Device header */ cckd = dev->cckd_ext; sfx = cckd->sfn; cckd_trace (dev, "file[%d] read_init\n", sfx); /* Read the device header */ if (cckd_read (dev, sfx, 0, &devhdr, CKDDASD_DEVHDR_SIZE) < 0) return -1; /* Check the device hdr */ if (sfx == 0 && memcmp (&devhdr.devid, "CKD_C370", 8) == 0) cckd->ckddasd = 1; else if (sfx == 0 && memcmp (&devhdr.devid, "FBA_C370", 8) == 0) cckd->fbadasd = 1; else if (!(sfx && memcmp (&devhdr.devid, "CKD_S370", 8) == 0 && cckd->ckddasd) && !(sfx && memcmp (&devhdr.devid, "FBA_S370", 8) == 0 && cckd->fbadasd)) { logmsg (_("HHCCD110E %4.4X file[%d] devhdr id error\n"), dev->devnum, sfx); return -1; } /* Read the compressed header */ if (cckd_read_chdr (dev) < 0) return -1; /* Read the level 1 table */ if (cckd_read_l1 (dev) < 0) return -1; return 0; } /* end function cckd_read_init */ /*-------------------------------------------------------------------*/ /* Read free space */ /*-------------------------------------------------------------------*/ int cckd_read_fsp (DEVBLK *dev) { CCKDDASD_EXT *cckd; /* -> cckd extension */ off_t fpos; /* Free space offset */ int sfx; /* File index */ int i; /* Index */ CCKD_FREEBLK freeblk; /* First freeblk read */ cckd = dev->cckd_ext; sfx = cckd->sfn; cckd_trace (dev, "file[%d] read_fsp number %d\n", sfx, cckd->cdevhdr[sfx].free_number); cckd->free = cckd_free (dev, "free", cckd->free); cckd->free1st = cckd->freelast = cckd->freeavail = -1; /* Get storage for the internal free space chain * in a multiple of 1024 entries */ cckd->freenbr = (cckd->cdevhdr[sfx].free_number + 1023) & ~0x3FF; if (cckd->freenbr) if ((cckd->free = cckd_calloc (dev, "free", cckd->freenbr, CCKD_FREEBLK_ISIZE)) == NULL) return -1; /* Build the doubly linked internal free space chain */ if (cckd->cdevhdr[sfx].free_number) { cckd->free1st = 0; /* Read the first freeblk to determine old/new format */ fpos = (off_t)cckd->cdevhdr[sfx].free; if (cckd_read (dev, sfx, fpos, &freeblk, CCKD_FREEBLK_SIZE) < 0) return -1; if (memcmp(&freeblk, "FREE_BLK", 8) == 0) { /* new format free space */ CCKD_FREEBLK *fsp; U32 ofree = cckd->cdevhdr[sfx].free; int n = cckd->cdevhdr[sfx].free_number * CCKD_FREEBLK_SIZE; if ((fsp = cckd_malloc (dev, "fsp", n)) == NULL) return -1; fpos += CCKD_FREEBLK_SIZE; if (cckd_read (dev, sfx, fpos, fsp, n) < 0) return -1; for (i = 0; i < cckd->cdevhdr[sfx].free_number; i++) { if (i == 0) cckd->cdevhdr[sfx].free = fsp[i].pos; else cckd->free[i-1].pos = fsp[i].pos; cckd->free[i].pos = 0; cckd->free[i].len = fsp[i].len; cckd->free[i].prev = i - 1; cckd->free[i].next = i + 1; } cckd->free[i-1].next = -1; cckd->freelast = i-1; fsp = cckd_free (dev, "fsp", fsp); /* truncate if new format free space was at the end */ if (ofree == cckd->cdevhdr[sfx].size) { fpos = (off_t)cckd->cdevhdr[sfx].size; cckd_ftruncate(dev, sfx, fpos); } } /* new format free space */ else { /* old format free space */ fpos = (off_t)cckd->cdevhdr[sfx].free; for (i = 0; i < cckd->cdevhdr[sfx].free_number; i++) { if (cckd_read (dev, sfx, fpos, &cckd->free[i], CCKD_FREEBLK_SIZE) < 0) return -1; cckd->free[i].prev = i - 1; cckd->free[i].next = i + 1; fpos = (off_t)cckd->free[i].pos; } cckd->free[i-1].next = -1; cckd->freelast = i-1; } /* old format free space */ } /* if (cckd->cdevhdr[sfx].free_number) */ /* Build singly linked chain of available free space entries */ if (cckd->cdevhdr[sfx].free_number < cckd->freenbr) { cckd->freeavail = cckd->cdevhdr[sfx].free_number; for (i = cckd->freeavail; i < cckd->freenbr; i++) cckd->free[i].next = i + 1; cckd->free[i-1].next = -1; } /* Set minimum free space size */ cckd->freemin = CCKD_FREE_MIN_SIZE + ((cckd->freenbr >> 10) * CCKD_FREE_MIN_INCR); return 0; } /* end function cckd_read_fsp */ /*-------------------------------------------------------------------*/ /* Write the free space */ /*-------------------------------------------------------------------*/ int cckd_write_fsp (DEVBLK *dev) { CCKDDASD_EXT *cckd; /* -> cckd extension */ off_t fpos; /* Free space offset */ U32 ppos; /* Previous free space offset*/ int sfx; /* File index */ int i, j, n; /* Work variables */ int rc; /* Return code */ CCKD_FREEBLK *fsp = NULL; /* -> new format free space */ cckd = dev->cckd_ext; sfx = cckd->sfn; if (cckd->free == NULL) return 0; cckd_trace (dev, "file[%d] write_fsp number %d\n", sfx, cckd->cdevhdr[sfx].free_number); /* get rid of pending free space */ for (i = 0; i < CCKD_MAX_FREEPEND; i++) cckd_flush_space(dev); /* sanity checks */ if (cckd->cdevhdr[sfx].free_number == 0 || cckd->cdevhdr[sfx].free == 0) { cckd->cdevhdr[sfx].free_number = cckd->cdevhdr[sfx].free = 0; cckd->free1st = cckd->freelast = cckd->freeavail = -1; } /* Write any free spaces */ if (cckd->cdevhdr[sfx].free) { /* size needed for new format free space */ n = (cckd->cdevhdr[sfx].free_number+1) * CCKD_FREEBLK_SIZE; /* look for existing free space to fit new format free space */ fpos = 0; for (i = cckd->free1st; i >= 0; i = cckd->free[i].next) if (n <= (int)cckd->free[i].len) break; if (i >= 0) fpos = cckd->free[i].prev < 0 ? (off_t)cckd->cdevhdr[sfx].free : (off_t)cckd->free[cckd->free[i].prev].pos; /* if no applicable space see if we can append to the file */ if (fpos == 0 && cckd->maxsize - cckd->cdevhdr[sfx].size >= n) fpos = (off_t)cckd->cdevhdr[sfx].size; if (fpos && (fsp = cckd_malloc (dev, "fsp", n)) == NULL) fpos = 0; if (fpos) { /* New format free space */ memcpy (&fsp[0], "FREE_BLK", 8); ppos = cckd->cdevhdr[sfx].free; for (i = cckd->free1st, j = 1; i >= 0; i = cckd->free[i].next) { fsp[j].pos = ppos; fsp[j++].len = cckd->free[i].len; ppos = cckd->free[i].pos; } rc = cckd_write (dev, sfx, fpos, fsp, n); fsp = cckd_free (dev, "fsp", fsp); if (rc < 0) return -1; cckd->cdevhdr[sfx].free = (U32)fpos; } /* new format free space */ else { /* Old format free space */ for (i = cckd->free1st; i >= 0; i = cckd->free[i].next) { if (cckd_write (dev, sfx, fpos, &cckd->free[i], CCKD_FREEBLK_SIZE) < 0) return -1; fpos = (off_t)cckd->free[i].pos; } } /* old format free space */ } /* if (cckd->cdevhdr[sfx].free) */ /* Free the free space array */ cckd->free = cckd_free (dev, "free", cckd->free); cckd->freenbr = 0; cckd->free1st = cckd->freelast = cckd->freeavail = -1; return 0; } /* end function cckd_write_fsp */ /*-------------------------------------------------------------------*/ /* Read a new level 2 table */ /*-------------------------------------------------------------------*/ int cckd_read_l2 (DEVBLK *dev, int sfx, int l1x) { CCKDDASD_EXT *cckd; /* -> cckd extension */ off_t off; /* L2 file offset */ int fnd; /* Found cache */ int lru; /* Oldest available cache */ CCKD_L2ENT *buf; /* -> Cache buffer */ int i; /* Loop index */ int nullfmt; /* Null track format */ cckd = dev->cckd_ext; nullfmt = cckd->cdevhdr[cckd->sfn].nullfmt; cckd_trace (dev, "file[%d] read_l2 %d active %d %d %d\n", sfx, l1x, cckd->sfx, cckd->l1x, cckd->l2active); /* Return if table is already active */ if (sfx == cckd->sfx && l1x == cckd->l1x) return 0; cache_lock(CACHE_L2); /* Inactivate the previous entry */ if (cckd->l2active >= 0) cache_setflag(CACHE_L2, cckd->l2active, ~L2_CACHE_ACTIVE, 0); cckd->l2 = NULL; cckd->l2active = cckd->sfx = cckd->l1x = -1; /* scan the cache array for the l2tab */ fnd = cache_lookup (CACHE_L2, L2_CACHE_SETKEY(sfx, dev->devnum, l1x), &lru); /* check for level 2 cache hit */ if (fnd >= 0) { cckd_trace (dev, "l2[%d,%d] cache[%d] hit\n", sfx, l1x, fnd); cache_setflag (CACHE_L2, fnd, 0, L2_CACHE_ACTIVE); cache_setage (CACHE_L2, fnd); cckdblk.stats_l2cachehits++; cache_unlock (CACHE_L2); cckd->sfx = sfx; cckd->l1x = l1x; cckd->l2 = cache_getbuf(CACHE_L2, fnd, 0); cckd->l2active = fnd; return 1; } cckd_trace (dev, "l2[%d,%d] cache[%d] miss\n", sfx, l1x, lru); /* Steal an entry if all are busy */ if (lru < 0) lru = cckd_steal_l2(); /* Make the entry active */ cache_setkey (CACHE_L2, lru, L2_CACHE_SETKEY(sfx, dev->devnum, l1x)); cache_setflag (CACHE_L2, lru, 0, L2_CACHE_ACTIVE); cache_setage (CACHE_L2, lru); buf = cache_getbuf(CACHE_L2, lru, CCKD_L2TAB_SIZE); cckdblk.stats_l2cachemisses++; cache_unlock (CACHE_L2); if (buf == NULL) return -1; /* Check for null table */ if (cckd->l1[sfx][l1x] == 0) { memset(buf, 0, CCKD_L2TAB_SIZE); if (nullfmt) for (i = 0; i < 256; i++) buf[i].len = buf[i].size = nullfmt; cckd_trace (dev, "l2[%d,%d] cache[%d] null fmt[%d]\n", sfx, l1x, lru, nullfmt); } else if (cckd->l1[sfx][l1x] == 0xffffffff) { memset(buf, 0xff, CCKD_L2TAB_SIZE); cckd_trace (dev, "l2[%d,%d] cache[%d] null 0xff\n", sfx, l1x, lru); } /* Read the new level 2 table */ else { off = (off_t)cckd->l1[sfx][l1x]; if (cckd_read (dev, sfx, off, buf, CCKD_L2TAB_SIZE) < 0) { cache_lock(CACHE_L2); cache_setflag(CACHE_L2, lru, 0, 0); cache_unlock(CACHE_L2); return -1; } if (cckd->swapend[sfx]) cckd_swapend_l2 (buf); cckd_trace (dev, "file[%d] cache[%d] l2[%d] read offset 0x%" I64_FMT "x\n", sfx, lru, l1x, (long long)cckd->l1[sfx][l1x]); cckd->l2reads[sfx]++; cckd->totl2reads++; cckdblk.stats_l2reads++; } cckd->sfx = sfx; cckd->l1x = l1x; cckd->l2 = buf; cckd->l2active = lru; return 0; } /* end function cckd_read_l2 */ /*-------------------------------------------------------------------*/ /* Purge all l2tab cache entries for a given device */ /*-------------------------------------------------------------------*/ void cckd_purge_l2 (DEVBLK *dev) { CCKDDASD_EXT *cckd; /* -> cckd extension */ cckd = dev->cckd_ext; cckd_trace (dev, "purge_l2%s\n", ""); cache_lock (CACHE_L2); cckd->l2active = cckd->sfx = cckd->l1x = -1; cckd->l2 = NULL; cache_scan (CACHE_L2, cckd_purge_l2_scan, dev); cache_unlock (CACHE_L2); } int cckd_purge_l2_scan (int *answer, int ix, int i, void *data) { U16 sfx; /* Cached suffix */ U16 devnum; /* Cached device number */ U32 l1x; /* Cached level 1 index */ DEVBLK *dev = data; /* -> device block */ UNREFERENCED(answer); L2_CACHE_GETKEY(i, sfx, devnum, l1x); if (dev == NULL || devnum == dev->devnum) { cckd_trace (dev, "purge l2cache[%d] %4.4X sfx %d ix %d purged\n", i, devnum, sfx, l1x); cache_release(ix, i, 0); } return 0; } /*-------------------------------------------------------------------*/ /* Steal an l2tab cache entry */ /*-------------------------------------------------------------------*/ int cckd_steal_l2 () { DEVBLK *dev; /* -> device block */ CCKDDASD_EXT *cckd; /* -> cckd extension */ int i; /* Stolen cache index */ U16 sfx; /* Cached suffix */ U16 devnum; /* Cached device number */ U32 l1x; /* Cached level 1 index */ i = cache_scan (CACHE_L2, cckd_steal_l2_scan, NULL); L2_CACHE_GETKEY(i, sfx, devnum, l1x); dev = cckd_find_device_by_devnum(devnum); cckd = dev->cckd_ext; cckd->l2active = cckd->sfx = cckd->l1x = -1; cckd->l2 = NULL; cache_release(CACHE_L2, i, 0); return i; } int cckd_steal_l2_scan (int *answer, int ix, int i, void *data) { UNREFERENCED(data); if (*answer < 0) *answer = i; else if (cache_getage(ix, i) < cache_getage(ix, *answer)) *answer = i; return 0; } /*-------------------------------------------------------------------*/ /* Write the current level 2 table */ /*-------------------------------------------------------------------*/ int cckd_write_l2 (DEVBLK *dev) { CCKDDASD_EXT *cckd; /* -> cckd extension */ int sfx,l1x; /* Lookup table indices */ off_t off, old_off; /* New/old L2 file offsets */ int size = CCKD_L2TAB_SIZE; /* L2 table size */ int fix; /* Null format type */ cckd = dev->cckd_ext; sfx = cckd->sfn; l1x = cckd->l1x; fix = cckd->cdevhdr[sfx].nullfmt; cckd->l2ok = 0; cckd_trace (dev, "file[%d] write_l2 %d\n", sfx, l1x); if (sfx < 0 || l1x < 0) return -1; old_off = (off_t)cckd->l1[sfx][l1x]; if (cckd->l1[sfx][l1x] == 0 || cckd->l1[sfx][l1x] == 0xffffffff) cckd->l2bounds += CCKD_L2TAB_SIZE; /* Write the L2 table if it's not empty */ if (memcmp(cckd->l2, &empty_l2[fix], CCKD_L2TAB_SIZE)) { if ((off = cckd_get_space (dev, &size, CCKD_L2SPACE)) < 0) return -1; if (cckd_write (dev, sfx, off, cckd->l2, CCKD_L2TAB_SIZE) < 0) return -1; } else { off = 0; cckd->l2bounds -= CCKD_L2TAB_SIZE; } /* Free the old L2 space */ cckd_rel_space (dev, old_off, CCKD_L2TAB_SIZE, CCKD_L2TAB_SIZE); /* Update level 1 table */ cckd->l1[sfx][l1x] = (U32)off; if (cckd_write_l1ent (dev, l1x) < 0) return -1; return 0; } /* end function cckd_write_l2 */ /*-------------------------------------------------------------------*/ /* Return a level 2 entry */ /*-------------------------------------------------------------------*/ int cckd_read_l2ent (DEVBLK *dev, CCKD_L2ENT *l2, int trk) { CCKDDASD_EXT *cckd; /* -> cckd extension */ int sfx,l1x,l2x; /* Lookup table indices */ cckd = dev->cckd_ext; l1x = trk >> 8; l2x = trk & 0xff; if (l2 != NULL) l2->pos = l2->len = l2->size = 0; for (sfx = cckd->sfn; sfx >= 0; sfx--) { cckd_trace (dev, "file[%d] l2[%d,%d] trk[%d] read_l2ent 0x%x\n", sfx, l1x, l2x, trk, cckd->l1[sfx][l1x]); /* Continue if l2 table not in this file */ if (cckd->l1[sfx][l1x] == 0xffffffff) continue; /* Read l2 table from this file */ if (cckd_read_l2 (dev, sfx, l1x) < 0) return -1; /* Exit loop if track is in this file */ if (cckd->l2[l2x].pos != 0xffffffff) break; } cckd_trace (dev, "file[%d] l2[%d,%d] trk[%d] read_l2ent 0x%x %d %d\n", sfx, l1x, l2x, trk, sfx >= 0 ? cckd->l2[l2x].pos : 0, sfx >= 0 ? cckd->l2[l2x].len : 0, sfx >= 0 ? cckd->l2[l2x].size : 0); if (l2 != NULL && sfx >= 0) { l2->pos = cckd->l2[l2x].pos; l2->len = cckd->l2[l2x].len; l2->size = cckd->l2[l2x].size; } return sfx; } /* end function cckd_read_l2ent */ /*-------------------------------------------------------------------*/ /* Update a level 2 entry */ /*-------------------------------------------------------------------*/ int cckd_write_l2ent (DEVBLK *dev, CCKD_L2ENT *l2, int trk) { CCKDDASD_EXT *cckd; /* -> cckd extension */ int sfx,l1x,l2x; /* Lookup table indices */ off_t off; /* L2 entry offset */ cckd = dev->cckd_ext; /* Error return if no available level 2 table */ if (!cckd->l2) return -1; sfx = cckd->sfn; l1x = trk >> 8; l2x = trk & 0xff; /* Copy the new entry if passed */ if (l2) memcpy (&cckd->l2[l2x], l2, CCKD_L2ENT_SIZE); cckd_trace (dev, "file[%d] l2[%d,%d] trk[%d] write_l2ent 0x%x %d %d\n", sfx, l1x, l2x, trk, cckd->l2[l2x].pos, cckd->l2[l2x].len, cckd->l2[l2x].size); /* If no level 2 table for this file, then write a new one */ if (cckd->l1[sfx][l1x] == 0 || cckd->l1[sfx][l1x] == 0xffffffff) return cckd_write_l2 (dev); /* Write the level 2 table entry */ off = (off_t)(cckd->l1[sfx][l1x] + l2x * CCKD_L2ENT_SIZE); if (cckd_write (dev, sfx, off, &cckd->l2[l2x], CCKD_L2ENT_SIZE) < 0) return -1; return 0; } /* end function cckd_write_l2ent */ /*-------------------------------------------------------------------*/ /* Read a track image */ /*-------------------------------------------------------------------*/ int cckd_read_trkimg (DEVBLK *dev, BYTE *buf, int trk, BYTE *unitstat) { CCKDDASD_EXT *cckd; /* -> cckd extension */ int rc; /* Return code */ int sfx; /* File index */ CCKD_L2ENT l2; /* Level 2 entry */ cckd = dev->cckd_ext; cckd_trace (dev, "trk[%d] read_trkimg\n", trk); /* Read level 2 entry for the track */ if ((sfx = cckd_read_l2ent (dev, &l2, trk)) < 0) goto cckd_read_trkimg_error; /* Read the track image or build a null track image */ if (l2.pos != 0) { rc = cckd_read (dev, sfx, (off_t)l2.pos, buf, (size_t)l2.len); if (rc < 0) goto cckd_read_trkimg_error; cckd->reads[sfx]++; cckd->totreads++; cckdblk.stats_reads++; cckdblk.stats_readbytes += rc; if (cckd->notnull == 0 && trk > 1) cckd->notnull = 1; } else rc = cckd_null_trk (dev, buf, trk, l2.len); /* Validate the track image */ if (cckd_cchh (dev, buf, trk) < 0) goto cckd_read_trkimg_error; return rc; cckd_read_trkimg_error: if (unitstat) { ckd_build_sense (dev, SENSE_EC, 0, 0, FORMAT_1, MESSAGE_0); *unitstat = CSW_CE | CSW_DE | CSW_UC; } return cckd_null_trk (dev, buf, trk, 0); } /* end function cckd_read_trkimg */ /*-------------------------------------------------------------------*/ /* Write a track image */ /*-------------------------------------------------------------------*/ int cckd_write_trkimg (DEVBLK *dev, BYTE *buf, int len, int trk, int flags) { CCKDDASD_EXT *cckd; /* -> cckd extension */ int rc; /* Return code */ off_t off; /* File offset */ CCKD_L2ENT l2, oldl2; /* Level 2 entries */ int sfx,l1x,l2x; /* Lookup table indices */ int after = 0; /* 1=New track after old */ int size; /* Size of new track */ cckd = dev->cckd_ext; sfx = cckd->sfn; l1x = trk >> 8; l2x = trk & 0xff; cckd_trace (dev, "file[%d] trk[%d] write_trkimg len %d buf %p:%2.2x%2.2x%2.2x%2.2x%2.2x\n", sfx, trk, len, buf, buf[0], buf[1], buf[2], buf[3], buf[4]); /* Validate the new track image */ if (cckd_cchh (dev, buf, trk) < 0) return -1; /* Get the level 2 table for the track in the active file */ if (cckd_read_l2 (dev, sfx, l1x) < 0) return -1; /* Save the level 2 entry for the track */ oldl2.pos = cckd->l2[l2x].pos; oldl2.len = cckd->l2[l2x].len; oldl2.size = cckd->l2[l2x].size; cckd_trace (dev, "file[%d] trk[%d] write_trkimg oldl2 0x%x %d %d\n", sfx, trk, oldl2.pos,oldl2.len,oldl2.size); /* Check if writing a null track */ len = cckd_check_null_trk(dev, buf, trk, len); if (len > CKDDASD_NULLTRK_FMTMAX) { /* Get space for the track image */ size = len; if ((off = cckd_get_space (dev, &size, flags)) < 0) return -1; l2.pos = (U32)off; l2.len = (U16)len; l2.size = (U16)size; if (oldl2.pos != 0 && oldl2.pos != 0xffffffff && oldl2.pos < l2.pos) after = 1; /* Write the track image */ if ((rc = cckd_write (dev, sfx, off, buf, len)) < 0) return -1; cckd->writes[sfx]++; cckd->totwrites++; cckdblk.stats_writes++; cckdblk.stats_writebytes += rc; } else { l2.pos = 0; l2.len = l2.size = (U16)len; } /* Update the level 2 entry */ if (cckd_write_l2ent (dev, &l2, trk) < 0) return -1; /* Release the previous space */ cckd_rel_space (dev, (off_t)oldl2.pos, (int)oldl2.len, (int)oldl2.size); /* `after' is 1 if the new offset is after the old offset */ return after; } /* end function cckd_write_trkimg */ /*-------------------------------------------------------------------*/ /* Harden the file */ /*-------------------------------------------------------------------*/ int cckd_harden(DEVBLK *dev) { CCKDDASD_EXT *cckd; /* -> cckd extension */ int rc=0; /* Return code */ cckd = dev->cckd_ext; if ((dev->ckdrdonly && cckd->sfn == 0) || cckd->open[cckd->sfn] != CCKD_OPEN_RW) return 0; cckd_trace (dev, "file[%d] harden\n", cckd->sfn); /* Write the compressed device header */ if (cckd_write_chdr (dev) < 0) rc = -1; /* Write the level 1 table */ if (cckd_write_l1 (dev) < 0) rc = -1; /* Write the free space chain */ if (cckd_write_fsp (dev) < 0) rc = -1; /* Re-write the compressed device header */ cckd->cdevhdr[cckd->sfn].options &= ~CCKD_OPENED; if (cckd_write_chdr (dev) < 0) rc = -1; if (cckdblk.fsync) fdatasync (cckd->fd[cckd->sfn]); return rc; } /* cckd_harden */ /*-------------------------------------------------------------------*/ /* Return length of an uncompressed track image */ /*-------------------------------------------------------------------*/ int cckd_trklen (DEVBLK *dev, BYTE *buf) { CCKDDASD_EXT *cckd; /* -> cckd extension */ int size; /* Track size */ cckd = dev->cckd_ext; if (cckd->fbadasd) return CKDDASD_TRKHDR_SIZE + CFBA_BLOCK_SIZE; for (size = CKDDASD_TRKHDR_SIZE; memcmp (&buf[size], &eighthexFF, 8) != 0; ) { if (size > dev->ckdtrksz) break; /* add length of count, key, and data fields */ size += CKDDASD_RECHDR_SIZE + buf[size+5] + (buf[size+6] << 8) + buf[size+7]; } /* add length for end-of-track indicator */ size += CKDDASD_RECHDR_SIZE; /* check for missing end-of-track indicator */ if (size > dev->ckdtrksz || memcmp (&buf[size-CKDDASD_RECHDR_SIZE], &eighthexFF, 8) != 0) { logmsg (_("HHCCD121E %4.4X file[%d] trklen err for %2.2x%2.2x%2.2x%2.2x%2.2x\n"), dev->devnum, cckd->sfn, buf[0], buf[1], buf[2], buf[3], buf[4]); size = -1; } return size; } /*-------------------------------------------------------------------*/ /* Build a null track */ /*-------------------------------------------------------------------*/ int cckd_null_trk(DEVBLK *dev, BYTE *buf, int trk, int nullfmt) { CCKDDASD_EXT *cckd; /* -> cckd extension */ int i; /* Loop counter */ CKDDASD_TRKHDR *trkhdr; /* -> Track header */ CKDDASD_RECHDR *rechdr; /* -> Record header */ U32 cyl; /* Cylinder number */ U32 head; /* Head number */ BYTE r; /* Record number */ BYTE *pos; /* -> Next position in buffer*/ int len; /* Length of null track */ cckd = dev->cckd_ext; if (nullfmt < 0 || nullfmt > CKDDASD_NULLTRK_FMTMAX) nullfmt = cckd->cdevhdr[cckd->sfn].nullfmt; // FIXME // Compatibility check for nullfmt bug and linux -- 18 May 2005 // Remove at some reasonable date in the future else if (nullfmt == 0 && cckd->cdevhdr[cckd->sfn].nullfmt == CKDDASD_NULLTRK_FMT2) nullfmt = CKDDASD_NULLTRK_FMT2; if (cckd->ckddasd) { /* cylinder and head calculations */ cyl = trk / dev->ckdheads; head = trk % dev->ckdheads; /* Build the track header */ trkhdr = (CKDDASD_TRKHDR*)buf; trkhdr->bin = 0; store_hw(&trkhdr->cyl, cyl); store_hw(&trkhdr->head, head); pos = buf + CKDDASD_TRKHDR_SIZE; /* Build record zero */ r = 0; rechdr = (CKDDASD_RECHDR*)pos; pos += CKDDASD_RECHDR_SIZE; store_hw(&rechdr->cyl, cyl); store_hw(&rechdr->head, head); rechdr->rec = r; rechdr->klen = 0; store_hw(&rechdr->dlen, 8); memset (pos, 0, 8); pos += 8; r++; /* Specific null track formatting */ if (nullfmt == CKDDASD_NULLTRK_FMT0) { rechdr = (CKDDASD_RECHDR*)pos; pos += CKDDASD_RECHDR_SIZE; store_hw(&rechdr->cyl, cyl); store_hw(&rechdr->head, head); rechdr->rec = r; rechdr->klen = 0; store_hw(&rechdr->dlen, 0); r++; } else if (nullfmt == CKDDASD_NULLTRK_FMT2) { for (i = 0; i < 12; i++) { rechdr = (CKDDASD_RECHDR*)pos; pos += CKDDASD_RECHDR_SIZE; store_hw(&rechdr->cyl, cyl); store_hw(&rechdr->head, head); rechdr->rec = r; rechdr->klen = 0; store_hw(&rechdr->dlen, 4096); r++; memset(pos, 0, 4096); pos += 4096; } } /* Build the end of track marker */ memcpy (pos, eighthexFF, 8); pos += 8; len = (int)(pos - buf); } else { memset (buf, 0, CFBA_BLOCK_SIZE + CKDDASD_TRKHDR_SIZE); store_fw(buf+1, trk); len = CFBA_BLOCK_SIZE + CKDDASD_TRKHDR_SIZE; } cckd_trace (dev, "null_trk %s %d format %d size %d\n", cckd->ckddasd ? "trk" : "blkgrp", trk, nullfmt, len); return len; } /* end function cckd_null_trk */ /*-------------------------------------------------------------------*/ /* Return a number 0 .. CKDDASD_NULLTRK_FMTMAX if track is null */ /* else return the original length */ /*-------------------------------------------------------------------*/ int cckd_check_null_trk (DEVBLK *dev, BYTE *buf, int trk, int len) { CCKDDASD_EXT *cckd; /* -> cckd extension */ int rc; /* Return code */ BYTE buf2[65536]; /* Null track buffer */ cckd = dev->cckd_ext; rc = len; if (len == CKDDASD_NULLTRK_SIZE0) rc = CKDDASD_NULLTRK_FMT0; else if (len == CKDDASD_NULLTRK_SIZE1) rc = CKDDASD_NULLTRK_FMT1; else if (len == CKDDASD_NULLTRK_SIZE2 && dev->oslinux && (!cckd->notnull || cckdblk.linuxnull)) { cckd_null_trk (dev, buf2, trk, 0); if (memcmp(buf, buf2, len) == 0) rc = CKDDASD_NULLTRK_FMT2; } return rc; } /*-------------------------------------------------------------------*/ /* Verify a track/block header and return track/block number */ /*-------------------------------------------------------------------*/ int cckd_cchh (DEVBLK *dev, BYTE *buf, int trk) { CCKDDASD_EXT *cckd; /* -> cckd extension */ U16 cyl; /* Cylinder */ U16 head; /* Head */ int t; /* Calculated track */ BYTE badcomp=0; /* 1=Unsupported compression */ static char *comp[] = {"none", "zlib", "bzip2"}; cckd = dev->cckd_ext; /* CKD dasd header verification */ if (cckd->ckddasd) { cyl = fetch_hw (buf + 1); head = fetch_hw (buf + 3); t = cyl * dev->ckdheads + head; if (cyl < dev->ckdcyls && head < dev->ckdheads && (trk == -1 || t == trk)) { if (buf[0] & ~cckdblk.comps) { if (buf[0] & ~CCKD_COMPRESS_MASK) { if (cckdblk.bytemsgs++ < 10) logmsg (_("HHCCD122E %4.4X file[%d] invalid byte 0 trk %d: " "buf %2.2x%2.2x%2.2x%2.2x%2.2x\n"), dev->devnum, cckd->sfn, t, buf[0],buf[1],buf[2],buf[3],buf[4]); buf[0] &= CCKD_COMPRESS_MASK; } } if (buf[0] & ~cckdblk.comps) badcomp = 1; else return t; } } /* FBA dasd header verification */ else { t = fetch_fw (buf + 1); if (t < dev->fbanumblk && (trk == -1 || t == trk)) { if (buf[0] & ~cckdblk.comps) { if (buf[0] & ~CCKD_COMPRESS_MASK) { logmsg (_("HHCCD123E %4.4X file[%d] invalid byte 0 blkgrp %d: " "buf %2.2x%2.2x%2.2x%2.2x%2.2x\n"), dev->devnum, cckd->sfn, t, buf[0],buf[1],buf[2],buf[3],buf[4]); buf[0] &= CCKD_COMPRESS_MASK; } } if (buf[0] & ~cckdblk.comps) badcomp = 1; else return t; } } if (badcomp) { logmsg (_("HHCCD124E %4.4X file[%d] invalid %s hdr %s %d: " "%s compression unsupported\n"), dev->devnum, cckd->sfn, cckd->ckddasd ? "trk" : "blk", cckd->ckddasd ? "trk" : "blk", t, comp[buf[0]]); } else { logmsg (_("HHCCD125E %4.4X file[%d] invalid %s hdr %s %d " "buf %p:%2.2x%2.2x%2.2x%2.2x%2.2x\n"), dev->devnum, cckd->sfn, cckd->ckddasd ? "trk" : "blk", cckd->ckddasd ? "trk" : "blk", trk, buf, buf[0], buf[1], buf[2], buf[3], buf[4]); cckd_print_itrace (); } return -1; } /* end function cckd_cchh */ /*-------------------------------------------------------------------*/ /* Validate a track image */ /*-------------------------------------------------------------------*/ int cckd_validate (DEVBLK *dev, BYTE *buf, int trk, int len) { CCKDDASD_EXT *cckd; /* -> cckd extension */ int cyl; /* Cylinder */ int head; /* Head */ char cchh[4],cchh2[4]; /* Cyl, head big-endian */ int r; /* Record number */ int sz; /* Track size */ int vlen; /* Validation length */ int kl,dl; /* Key/Data lengths */ cckd = dev->cckd_ext; if (buf == NULL || len < 0) return -1; cckd_trace (dev, "validating %s %d len %d %2.2x%2.2x%2.2x%2.2x%2.2x " "%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x\n", cckd->ckddasd ? "trk" : "blkgrp", trk, len, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7], buf[8], buf[9], buf[10], buf[11], buf[12]); /* FBA dasd check */ if (cckd->fbadasd) { if (len == CFBA_BLOCK_SIZE + CKDDASD_TRKHDR_SIZE || len == 0) return len; cckd_trace (dev, "validation failed: bad length%s\n",""); return -1; } /* cylinder and head calculations */ cyl = trk / dev->ckdheads; head = trk % dev->ckdheads; cchh[0] = cyl >> 8; cchh[1] = cyl & 0xFF; cchh[2] = head >> 8; cchh[3] = head & 0xFF; /* validate record 0 */ memcpy (cchh2, &buf[5], 4); cchh2[0] &= 0x7f; /* fix for ovflow */ if (/* memcmp (cchh, cchh2, 4) != 0 || */ buf[9] != 0 || buf[10] != 0 || buf[11] != 0 || buf[12] != 8) { cckd_trace (dev, "validation failed: bad r0%s\n",""); return -1; } /* validate records 1 thru n */ vlen = len > 0 ? len : dev->ckdtrksz; for (r = 1, sz = 21; sz + 8 <= vlen; sz += 8 + kl + dl, r++) { if (memcmp (&buf[sz], eighthexFF, 8) == 0) break; kl = buf[sz+5]; dl = buf[sz+6] * 256 + buf[sz+7]; /* fix for track overflow bit */ memcpy (cchh2, &buf[sz], 4); cchh2[0] &= 0x7f; /* fix for funny formatted vm disks */ /* if (r == 1) memcpy (cchh, cchh2, 4); */ if (/*memcmp (cchh, cchh2, 4) != 0 ||*/ buf[sz+4] == 0 || sz + 8 + kl + dl >= vlen) { cckd_trace (dev, "validation failed: bad r%d " "%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x\n", r, buf[sz], buf[sz+1], buf[sz+2], buf[sz+3], buf[sz+4], buf[sz+5], buf[sz+6], buf[sz+7]); return -1; } } sz += 8; if ((sz != len && len > 0) || sz > vlen) { cckd_trace (dev, "validation failed: no eot%s\n",""); return -1; } return sz; } /* end function cckd_validate */ /*-------------------------------------------------------------------*/ /* Return shadow file name */ /*-------------------------------------------------------------------*/ char *cckd_sf_name (DEVBLK *dev, int sfx) { /* Return base file name if index is 0 */ if (sfx == 0) return dev->filename; /* Error if no shadow file name specified or number exceeded */ if (dev->dasdsfn == NULL || sfx > CCKD_MAX_SF) return NULL; /* Set the suffix character in the shadow file name */ if (sfx > 0) *dev->dasdsfx = '0' + sfx; else *dev->dasdsfx = '*'; return dev->dasdsfn; } /* end function cckd_sf_name */ /*-------------------------------------------------------------------*/ /* Initialize shadow files */ /*-------------------------------------------------------------------*/ int cckd_sf_init (DEVBLK *dev) { CCKDDASD_EXT *cckd; /* -> cckd extension */ int rc; /* Return code */ int i; /* Index */ struct stat st; /* stat() buffer */ char pathname[MAX_PATH]; /* file path in host format */ cckd = dev->cckd_ext; /* return if no shadow files */ if (dev->dasdsfn == NULL) return 0; #if 1 /* Check for shadow file name collision */ for (i = 1; i <= CCKD_MAX_SF && dev->dasdsfn != NULL; i++) { DEVBLK *dev2; CCKDDASD_EXT *cckd2; int j; for (dev2 = cckdblk.dev1st; dev2; dev2 = cckd2->devnext) { cckd2 = dev2->cckd_ext; if (dev2 == dev) continue; for (j = 0; j <= CCKD_MAX_SF && dev2->dasdsfn != NULL; j++) { if (strcmp (cckd_sf_name(dev, i),cckd_sf_name(dev2, j)) == 0) { logmsg (_("HHCCD142E %4.4X file[%d] shadow file name %s\n" " collides with %4.4X file[%d] name %s\n"), dev->devnum, i, cckd_sf_name(dev, i), dev2->devnum, j, cckd_sf_name(dev2, j)); return -1; } } } } #endif /* open all existing shadow files */ for (cckd->sfn = 1; cckd->sfn <= CCKD_MAX_SF; cckd->sfn++) { hostpath(pathname, cckd_sf_name (dev, cckd->sfn), sizeof(pathname)); if (stat (pathname, &st) < 0) break; /* Try to open the shadow file read-write then read-only */ if (cckd_open (dev, cckd->sfn, O_RDWR|O_BINARY, 1) < 0) if (cckd_open (dev, cckd->sfn, O_RDONLY|O_BINARY, 0) < 0) break; /* Call the chkdsk function */ rc = cckd_chkdsk (dev, 0); if (rc < 0) return -1; /* Perform initial read */ rc = cckd_read_init (dev); } /* Backup to the last opened file number */ cckd->sfn--; /* If the last file was opened read-only then create a new one */ if (cckd->open[cckd->sfn] == CCKD_OPEN_RO) if (cckd_sf_new(dev) < 0) return -1; /* Re-open previous rdwr files rdonly */ for (i = 0; i < cckd->sfn; i++) { if (cckd->open[i] == CCKD_OPEN_RO) continue; if (cckd_open (dev, i, O_RDONLY|O_BINARY, 0) < 0) { logmsg (_("HHCCD151E %4.4X file[%d] error re-opening %s readonly\n %s\n"), dev->devnum, i, cckd_sf_name(dev, i), strerror(errno)); return -1; } } return 0; } /* end function cckd_sf_init */ /*-------------------------------------------------------------------*/ /* Create a new shadow file */ /*-------------------------------------------------------------------*/ int cckd_sf_new (DEVBLK *dev) { CCKDDASD_EXT *cckd; /* -> cckd extension */ int l1size; /* Size of level 1 table */ CKDDASD_DEVHDR devhdr; /* Device header */ cckd = dev->cckd_ext; cckd_trace (dev, "file[%d] sf_new %s\n", cckd->sfn+1, cckd_sf_name(dev, cckd->sfn+1) ? (char *)cckd_sf_name(dev, cckd->sfn+1) : "(none)"); /* Error if no shadow file name */ if (dev->dasdsfn == NULL) { logmsg (_("HHCCD161E %4.4X file[%d] no shadow file name\n"), dev->devnum, cckd->sfn+1); return -1; } /* Error if max number of shadow files exceeded */ if (cckd->sfn+1 == CCKD_MAX_SF) { logmsg (_("HHCCD161E %4.4X file[%d] max shadow files exceeded\n"), dev->devnum, cckd->sfn+1); return -1; } /* Harden the current file */ cckd_harden (dev); /* Open the new shadow file */ if (cckd_open(dev, cckd->sfn+1, O_RDWR|O_CREAT|O_EXCL|O_BINARY, S_IRUSR | S_IWUSR | S_IRGRP) < 0) return -1; /* Read previous file's device header */ if (cckd_read (dev, cckd->sfn, 0, &devhdr, CKDDASD_DEVHDR_SIZE) < 0) goto sf_new_error; /* Make sure identifier is CKD_S370 or FBA_S370 */ devhdr.devid[4] = 'S'; /* Write new file's device header */ if (cckd_write (dev, cckd->sfn+1, 0, &devhdr, CKDDASD_DEVHDR_SIZE) < 0) goto sf_new_error; /* Build the compressed device header */ memcpy (&cckd->cdevhdr[cckd->sfn+1], &cckd->cdevhdr[cckd->sfn], CCKDDASD_DEVHDR_SIZE); l1size = cckd->cdevhdr[cckd->sfn+1].numl1tab * CCKD_L1ENT_SIZE; cckd->cdevhdr[cckd->sfn+1].size = cckd->cdevhdr[cckd->sfn+1].used = CKDDASD_DEVHDR_SIZE + CCKDDASD_DEVHDR_SIZE + l1size; cckd->cdevhdr[cckd->sfn+1].free = cckd->cdevhdr[cckd->sfn+1].free_total = cckd->cdevhdr[cckd->sfn+1].free_largest = cckd->cdevhdr[cckd->sfn+1].free_number = cckd->cdevhdr[cckd->sfn+1].free_imbed = 0; /* Init the level 1 table */ if ((cckd->l1[cckd->sfn+1] = cckd_malloc (dev, "l1", l1size)) == NULL) goto sf_new_error; memset (cckd->l1[cckd->sfn+1], 0xff, l1size); /* Make the new file active */ cckd->sfn++; /* Harden the new file */ if (cckd_harden (dev) < 0) { cckd->sfn--; goto sf_new_error; } /* Re-read the l1 to set l2bounds, l2ok */ cckd_read_l1 (dev); return 0; sf_new_error: cckd->l1[cckd->sfn+1] = cckd_free(dev, "l1", cckd->l1[cckd->sfn+1]); cckd_close (dev, cckd->sfn+1); cckd->open[cckd->sfn+1] = CCKD_OPEN_NONE; unlink (cckd_sf_name (dev, cckd->sfn+1)); /* Re-read the l1 to set l2bounds, l2ok */ cckd_read_l1 (dev); return -1; } /* end function cckd_sf_new */ /*-------------------------------------------------------------------*/ /* Add a shadow file (sf+) */ /*-------------------------------------------------------------------*/ void *cckd_sf_add (void *data) { DEVBLK *dev = data; /* -> DEVBLK */ CCKDDASD_EXT *cckd; /* -> cckd extension */ int syncio; /* Saved syncio bit */ if (dev == NULL) { int n = 0; for (dev=sysblk.firstdev; dev; dev=dev->nextdev) if (dev->cckd_ext) { logmsg( _("HHCCD207I Adding device %d:%4.4X\n"), SSID_TO_LCSS(dev->ssid), dev->devnum ); cckd_sf_add (dev); n++; } logmsg( _("HHCCD092I %d devices processed\n"), n ); return NULL; } cckd = dev->cckd_ext; if (!cckd) { logmsg (_("HHCCD160E %4.4X not a cckd device\n"), dev->devnum); return NULL; } /* Disable synchronous I/O for the device */ syncio = cckd_disable_syncio(dev); /* Schedule updated track entries to be written */ obtain_lock (&cckd->iolock); if (cckd->merging) { dev->syncio = syncio; release_lock (&cckd->iolock); logmsg (_("HHCCD165W %4.4X error adding shadow file, " "sf command busy on device\n"), dev->devnum,cckd->sfn); return NULL; } cckd->merging = 1; cckd_flush_cache (dev); while (cckd->wrpending || cckd->ioactive) { cckd->iowaiters++; wait_condition (&cckd->iocond, &cckd->iolock); cckd->iowaiters--; cckd_flush_cache (dev); } cckd_purge_cache (dev); cckd_purge_l2 (dev); dev->bufcur = dev->cache = -1; release_lock (&cckd->iolock); /* Obtain control of the file */ obtain_lock (&cckd->filelock); /* Harden the current file */ cckd_harden (dev); /* Create a new shadow file */ if (cckd_sf_new (dev) < 0) { logmsg (_("HHCCD161E %4.4X file[%d] error adding shadow file\n"), dev->devnum, cckd->sfn+1); goto cckd_sf_add_exit; } /* Re-open the previous file if opened read-write */ if (cckd->open[cckd->sfn-1] == CCKD_OPEN_RW) cckd_open (dev, cckd->sfn-1, O_RDONLY|O_BINARY, 0); logmsg (_("HHCCD162I %4.4X file[%d] %s added\n"), dev->devnum, cckd->sfn, cckd_sf_name (dev, cckd->sfn)); cckd_sf_add_exit: /* Re-read the l1 to set l2bounds, l2ok */ cckd_read_l1 (dev); release_lock (&cckd->filelock); obtain_lock (&cckd->iolock); cckd->merging = 0; if (cckd->iowaiters) broadcast_condition (&cckd->iocond); dev->syncio = syncio; release_lock (&cckd->iolock); cckd_sf_stats (dev); return NULL; } /* end function cckd_sf_add */ /*-------------------------------------------------------------------*/ /* Remove a shadow file (sf-) */ /*-------------------------------------------------------------------*/ void *cckd_sf_remove (void *data) { DEVBLK *dev = data; /* -> DEVBLK */ CCKDDASD_EXT *cckd; /* -> cckd extension */ int syncio; /* Saved syncio bit */ int rc; /* Return code */ int from_sfx, to_sfx; /* From/to file index */ int fix; /* nullfmt index */ int add = 0; /* 1=Add shadow file back */ int l2updated = 0; /* 1=L2 table was updated */ int i,j; /* Loop indexes */ int merge, force; /* Flags */ off_t pos; /* File offset */ size_t len; /* Length to read/write */ int size; /* Image size */ int trk = -1; /* Track being read/written */ CCKD_L2ENT from_l2[256], /* Level 2 tables */ to_l2[256]; CCKD_L2ENT new_l2; /* New level 2 table entry */ BYTE buf[65536]; /* Buffer */ if (dev == NULL) { int n = 0; merge = cckdblk.sfmerge; force = cckdblk.sfforce; cckdblk.sfmerge = cckdblk.sfforce = 0; for (dev=sysblk.firstdev; dev; dev=dev->nextdev) if ((cckd = dev->cckd_ext)) { logmsg( _("HHCCD179I Merging device %d:%4.4X\n"), SSID_TO_LCSS(dev->ssid), dev->devnum ); cckd->sfmerge = merge; cckd->sfforce = force; cckd_sf_remove (dev); n++; } logmsg( _("HHCCD092I %d devices processed\n"), n ); return NULL; } cckd = dev->cckd_ext; if (!cckd) { logmsg (_("HHCCD170E %4.4X not a cckd device\n"), dev ? dev->devnum : 0); return NULL; } /* Set flags */ merge = cckd->sfmerge || cckd->sfforce; force = cckd->sfforce; cckd->sfmerge = cckd->sfforce = 0; cckd_trace (dev, "merge starting: %s %s\n", merge ? "merge" : "nomerge", force ? "force" : ""); /* Disable synchronous I/O for the device */ syncio = cckd_disable_syncio(dev); /* Schedule updated track entries to be written */ obtain_lock (&cckd->iolock); if (cckd->merging) { dev->syncio = syncio; release_lock (&cckd->iolock); logmsg (_("HHCCD175W %4.4X file[%d] merge failed, " "sf command busy on device\n"), dev->devnum,cckd->sfn); return NULL; } cckd->merging = 1; cckd_flush_cache (dev); while (cckd->wrpending || cckd->ioactive) { cckd->iowaiters++; wait_condition (&cckd->iocond, &cckd->iolock); cckd->iowaiters--; cckd_flush_cache (dev); } cckd_purge_cache (dev); cckd_purge_l2 (dev); dev->bufcur = dev->cache = -1; release_lock (&cckd->iolock); obtain_lock (&cckd->filelock); if (cckd->sfn == 0) { dev->syncio = syncio; release_lock (&cckd->filelock); logmsg (_("HHCCD171E %4.4X file[%d] cannot remove base file\n"), dev->devnum,cckd->sfn); return NULL; } from_sfx = cckd->sfn; to_sfx = cckd->sfn - 1; fix = cckd->cdevhdr[to_sfx].nullfmt; /* Harden the `from' file */ if (cckd_harden (dev) < 0) { logmsg (_("HHCCD174E %4.4X file[%d] not merged, " "file[%d] not hardened\n"), dev->devnum, from_sfx, from_sfx); goto sf_remove_exit; } /* Attempt to re-open the `to' file read-write */ cckd_close (dev, to_sfx); if (to_sfx > 0 || !dev->ckdrdonly || force) cckd_open (dev, to_sfx, O_RDWR|O_BINARY, 1); if (cckd->fd[to_sfx] < 0) { /* `from' file can't be opened read-write */ cckd_open (dev, to_sfx, O_RDONLY|O_BINARY, 0); if (merge) { logmsg (_("HHCCD172E %4.4X file[%d] not merged, " "file[%d] cannot be opened read-write%s\n"), dev->devnum, from_sfx, to_sfx, to_sfx == 0 && dev->ckdrdonly && !force ? ", try `force'" : ""); goto sf_remove_exit; } else add = 1; } else { /* `from' file opened read-write */ cckd->sfn = to_sfx; if (cckd_chkdsk (dev, 0) < 0) { cckd->sfn = from_sfx; logmsg (_("HHCCD173E %4.4X file[%d] not merged, " "file[%d] check failed\n"), dev->devnum, to_sfx, to_sfx); goto sf_remove_exit; } } cckd->sfn = to_sfx; /* Perform backwards merge */ if (merge) { cckd_trace (dev, "merging to file[%d]\n", to_sfx); /* Make the target file the active file */ cckd->sfn = to_sfx; cckd->cdevhdr[to_sfx].options |= (CCKD_OPENED | CCKD_ORDWR); /* Loop for each level 1 table entry */ for (i = 0; i < cckd->cdevhdr[from_sfx].numl1tab; i++) { l2updated = 0; /* Continue if from L2 doesn't exist */ if (cckd->l1[from_sfx][i] == 0xffffffff || (cckd->l1[from_sfx][i] == 0 && cckd->l1[to_sfx][i] == 0)) continue; trk = i*256; /* Read `from' l2 table */ if (cckd->l1[from_sfx][i] == 0) memset (&from_l2, 0, CCKD_L2TAB_SIZE); else { pos = (off_t)cckd->l1[from_sfx][i]; if (cckd_read(dev, from_sfx, pos, &from_l2, CCKD_L2TAB_SIZE) < 0) goto sf_merge_error; } /* Read `to' l2 table */ if (cckd->l1[to_sfx][i] == 0) memset (&to_l2, 0, CCKD_L2TAB_SIZE); else if (cckd->l1[to_sfx][i] == 0xffffffff) memset (&to_l2, 0xff, CCKD_L2TAB_SIZE); else { pos = (off_t)cckd->l1[to_sfx][i]; if (cckd_read(dev, to_sfx, pos, &to_l2, CCKD_L2TAB_SIZE) < 0) goto sf_merge_error; } /* Loop for each level 2 table entry */ for (j = 0; j < 256; j++) { trk = i*256 + j; /* Continue if from L2 entry doesn't exist */ if (from_l2[j].pos == 0xffffffff || (from_l2[j].pos == 0 && to_l2[j].pos == 0)) continue; /* Read the `from' track/blkgrp image */ len = (int)from_l2[j].len; if (len > CKDDASD_NULLTRK_FMTMAX) { pos = (off_t)from_l2[j].pos; if (cckd_read (dev, from_sfx, pos, buf, len) < 0) goto sf_merge_error; /* Get space for the `to' track/blkgrp image */ size = len; if ((pos = cckd_get_space (dev, &size, CCKD_SIZE_EXACT)) < 0) goto sf_merge_error; new_l2.pos = (U32)pos; new_l2.len = (U16)len; new_l2.size = (U16)size; /* Write the `to' track/blkgrp image */ if (cckd_write(dev, to_sfx, pos, buf, len) < 0) goto sf_merge_error; } else { new_l2.pos = 0; new_l2.len = new_l2.size = (U16)len; } /* Release space occupied by old `to' entry */ cckd_rel_space (dev, (off_t)to_l2[j].pos, (int)to_l2[j].len, (int)to_l2[j].size); /* Update `to' l2 table entry */ l2updated = 1; to_l2[j].pos = new_l2.pos; to_l2[j].len = new_l2.len; to_l2[j].size = new_l2.size; } /* for each level 2 table entry */ /* Update the `to' level 2 table */ if (l2updated) { l2updated = 0; pos = (off_t)cckd->l1[to_sfx][i]; if (memcmp (&to_l2, &empty_l2[fix], CCKD_L2TAB_SIZE) == 0) { cckd_rel_space (dev, pos, CCKD_L2TAB_SIZE, CCKD_L2TAB_SIZE); pos = 0; } else { size = CCKD_L2TAB_SIZE; if (pos == 0 || pos == (off_t)0xffffffff) if ((pos = cckd_get_space (dev, &size, CCKD_L2SPACE)) < 0) goto sf_merge_error; if (cckd_write(dev, to_sfx, pos, &to_l2, CCKD_L2TAB_SIZE) < 0) goto sf_merge_error; } /* `to' level 2 table not null */ /* Update the level 1 table index */ cckd->l1[to_sfx][i] = (U32)pos; /* Flush free space */ cckd_flush_space (dev); } /* Update level 2 table */ } /* For each level 1 table entry */ /* Validate the merge */ cckd_harden (dev); cckd_chkdsk (dev, 0); cckd_read_init (dev); } /* if merge */ /* Remove the old file */ cckd_close (dev, from_sfx); cckd->l1[from_sfx] = cckd_free (dev, "l1", cckd->l1[from_sfx]); memset (&cckd->cdevhdr[from_sfx], 0, CCKDDASD_DEVHDR_SIZE); rc = unlink (cckd_sf_name (dev, from_sfx)); /* Add the file back if necessary */ if (add) rc = cckd_sf_new (dev) ; logmsg (_("HHCCD181I %4.4X shadow file [%d] successfully %s\n"), dev->devnum, from_sfx, merge ? "merged" : add ? "re-added" : "removed"); sf_remove_exit: /* Re-read the l1 to set l2bounds, l2ok */ cckd_read_l1 (dev); release_lock (&cckd->filelock); obtain_lock (&cckd->iolock); cckd_purge_cache (dev); cckd_purge_l2 (dev); dev->bufcur = dev->cache = -1; cckd->merging = 0; if (cckd->iowaiters) broadcast_condition (&cckd->iocond); dev->syncio = syncio; cckd_trace (dev, "merge complete%s\n",""); release_lock (&cckd->iolock); cckd_sf_stats (dev); return NULL; sf_merge_error: if (trk < 0) logmsg (_("HHCCD180E %4.4X file[%d] not merged, error during merge\n"), dev->devnum, from_sfx); else logmsg (_("HHCCD180E %4.4X file[%d] not merged, error processing trk %d\n"), dev->devnum, from_sfx, trk); if (l2updated && cckd->l1[to_sfx][i] && cckd->l1[to_sfx][i] != 0xffffffff) { l2updated = 0; pos = (off_t)cckd->l1[to_sfx][i]; cckd_write(dev, to_sfx, pos, &to_l2, CCKD_L2TAB_SIZE); } cckd_harden(dev); cckd_chkdsk (dev, 2); cckd->sfn = from_sfx; cckd_harden(dev); cckd_chkdsk (dev, 2); goto sf_remove_exit; } /* end function cckd_sf_remove */ /*-------------------------------------------------------------------*/ /* Check and compress a shadow file (sfc) */ /*-------------------------------------------------------------------*/ void *cckd_sf_comp (void *data) { DEVBLK *dev = data; /* -> DEVBLK */ CCKDDASD_EXT *cckd; /* -> cckd extension */ int syncio; /* Saved syncio bit */ int rc; /* Return code */ if (dev == NULL) { int n = 0; for (dev=sysblk.firstdev; dev; dev=dev->nextdev) if (dev->cckd_ext) { logmsg( _("HHCCD207I Compressing device %d:%4.4X\n"), SSID_TO_LCSS(dev->ssid), dev->devnum ); cckd_sf_comp (dev); n++; } logmsg( _("HHCCD092I %d devices processed\n"), n ); return NULL; } cckd = dev->cckd_ext; if (!cckd) { logmsg (_("HHCCD205W %4.4X device is not a cckd device\n"), dev->devnum); return NULL; } /* Disable synchronous I/O for the device */ syncio = cckd_disable_syncio(dev); /* schedule updated track entries to be written */ obtain_lock (&cckd->iolock); if (cckd->merging) { dev->syncio = syncio; release_lock (&cckd->iolock); logmsg (_("HHCCD206W %4.4X file[%d] compress failed, " "sf command busy on device\n"), dev->devnum,cckd->sfn); return NULL; } cckd->merging = 1; cckd_flush_cache (dev); while (cckd->wrpending || cckd->ioactive) { cckd->iowaiters++; wait_condition (&cckd->iocond, &cckd->iolock); cckd->iowaiters--; cckd_flush_cache (dev); } cckd_purge_cache (dev); cckd_purge_l2 (dev); dev->bufcur = dev->cache = -1; release_lock (&cckd->iolock); /* obtain control of the file */ obtain_lock (&cckd->filelock); /* harden the current file */ cckd_harden (dev); /* Call the compress function */ rc = cckd_comp (dev); /* Perform initial read */ rc = cckd_read_init (dev); release_lock (&cckd->filelock); obtain_lock (&cckd->iolock); cckd->merging = 0; if (cckd->iowaiters) broadcast_condition (&cckd->iocond); dev->syncio = syncio; release_lock (&cckd->iolock); /* Display the shadow file statistics */ cckd_sf_stats (dev); return NULL; } /* end function cckd_sf_comp */ /*-------------------------------------------------------------------*/ /* Check a shadow file (sfk) */ /*-------------------------------------------------------------------*/ void *cckd_sf_chk (void *data) { DEVBLK *dev = data; /* -> DEVBLK */ CCKDDASD_EXT *cckd; /* -> cckd extension */ int syncio; /* Saved syncio bit */ int rc; /* Return code */ int level = 2; /* Check level */ if (dev == NULL) { int n = 0; level = cckdblk.sflevel; cckdblk.sflevel = 0; for (dev=sysblk.firstdev; dev; dev=dev->nextdev) if ((cckd = dev->cckd_ext)) { logmsg( _("HHCCD207I Checking device %d:%4.4X level %d\n"), SSID_TO_LCSS(dev->ssid), dev->devnum, level ); cckd->sflevel = level; cckd_sf_chk (dev); n++; } logmsg( _("HHCCD092I %d devices processed\n"), n ); return NULL; } cckd = dev->cckd_ext; if (!cckd) { logmsg (_("HHCCD205W %4.4X device is not a cckd device\n"), dev->devnum); return NULL; } level = cckd->sflevel; cckd->sflevel = 0; /* Disable synchronous I/O for the device */ syncio = cckd_disable_syncio(dev); /* schedule updated track entries to be written */ obtain_lock (&cckd->iolock); if (cckd->merging) { dev->syncio = syncio; release_lock (&cckd->iolock); logmsg (_("HHCCD206W %4.4X file[%d] check failed, " "sf command busy on device\n"), dev->devnum,cckd->sfn); return NULL; } cckd->merging = 1; cckd_flush_cache (dev); while (cckd->wrpending || cckd->ioactive) { cckd->iowaiters++; wait_condition (&cckd->iocond, &cckd->iolock); cckd->iowaiters--; cckd_flush_cache (dev); } cckd_purge_cache (dev); cckd_purge_l2 (dev); dev->bufcur = dev->cache = -1; release_lock (&cckd->iolock); /* obtain control of the file */ obtain_lock (&cckd->filelock); /* harden the current file */ cckd_harden (dev); /* Call the chkdsk function */ rc = cckd_chkdsk (dev, level); /* Perform initial read */ rc = cckd_read_init (dev); release_lock (&cckd->filelock); obtain_lock (&cckd->iolock); cckd->merging = 0; if (cckd->iowaiters) broadcast_condition (&cckd->iocond); dev->syncio = syncio; release_lock (&cckd->iolock); /* Display the shadow file statistics */ cckd_sf_stats (dev); return NULL; } /* end function cckd_sf_chk */ /*-------------------------------------------------------------------*/ /* Display shadow file statistics (sfd) */ /*-------------------------------------------------------------------*/ void *cckd_sf_stats (void *data) { DEVBLK *dev = data; /* -> DEVBLK */ CCKDDASD_EXT *cckd; /* -> cckd extension */ struct stat st; /* File information */ int i; /* Index */ int rc; /* Return code */ char *ost[] = {" ", "ro", "rd", "rw"}; unsigned long long size=0,free=0; /* Total size, free space */ int freenbr=0; /* Total number free spaces */ if (dev == NULL) { int n = 0; for (dev=sysblk.firstdev; dev; dev=dev->nextdev) if (dev->cckd_ext) { logmsg( _("HHCCD208I Displaying device %d:%4.4X\n"), SSID_TO_LCSS(dev->ssid), dev->devnum ); cckd_sf_stats (dev); n++; } logmsg( _("HHCCD092I %d devices processed\n"), n ); return NULL; } cckd = dev->cckd_ext; if (!cckd) { logmsg (_("HHCCD209W %4.4X device is not a cckd device\n")); return NULL; } // obtain_lock (&cckd->filelock); /* Calculate totals */ rc = fstat (cckd->fd[0], &st); for (i = 0; i <= cckd->sfn; i++) { if (!i) size = st.st_size; else size += cckd->cdevhdr[i].size; free += cckd->cdevhdr[i].free_total; freenbr += cckd->cdevhdr[i].free_number; } /* header */ logmsg (_("HHCCD210I size free nbr st reads writes l2reads hits switches\n")); if (cckd->readaheads || cckd->misses) logmsg (_("HHCCD211I readaheads misses\n")); logmsg (_("HHCCD212I --------------------------------------------------------------------\n")); /* total statistics */ logmsg (_("HHCCD213I [*] %10" I64_FMT "d %3" I64_FMT "d%% %4d %7d %7d %7d %7d %7d\n"), size, (free * 100) / size, freenbr, cckd->totreads, cckd->totwrites, cckd->totl2reads, cckd->cachehits, cckd->switches); if (cckd->readaheads || cckd->misses) logmsg (_("HHCCD214I %7d %7d\n"), cckd->readaheads, cckd->misses); /* base file statistics */ logmsg (_("HHCCD215I %s\n"), dev->filename); logmsg (_("HHCCD216I [0] %10" I64_FMT "d %3" I64_FMT "d%% %4d %s %7d %7d %7d\n"), (long long)st.st_size, (long long)((long long)((long long)cckd->cdevhdr[0].free_total * 100) / st.st_size), cckd->cdevhdr[0].free_number, ost[cckd->open[0]], cckd->reads[0], cckd->writes[0], cckd->l2reads[0]); if (dev->dasdsfn != NULL && CCKD_MAX_SF > 0) logmsg (_("HHCCD217I %s\n"), cckd_sf_name(dev, -1)); /* shadow file statistics */ for (i = 1; i <= cckd->sfn; i++) { logmsg (_("HHCCD218I [%d] %10" I64_FMT "d %3" I64_FMT "d%% %4d %s %7d %7d %7d\n"), i, (long long)cckd->cdevhdr[i].size, (long long)((long long)((long long)cckd->cdevhdr[i].free_total * 100) / cckd->cdevhdr[i].size), cckd->cdevhdr[i].free_number, ost[cckd->open[i]], cckd->reads[i], cckd->writes[i], cckd->l2reads[i]); } // release_lock (&cckd->filelock); return NULL; } /* end function cckd_sf_stats */ /*-------------------------------------------------------------------*/ /* Disable synchronous I/O for a device */ /*-------------------------------------------------------------------*/ int cckd_disable_syncio(DEVBLK *dev) { if (!dev->syncio) return 0; obtain_lock(&dev->lock); while (dev->syncio_active) { release_lock(&dev->lock); usleep(500); obtain_lock(&dev->lock); } dev->syncio = 0; release_lock(&dev->lock); cckd_trace (dev, "syncio disabled%s\n",""); return 1; } /*-------------------------------------------------------------------*/ /* Lock/unlock the device chain */ /*-------------------------------------------------------------------*/ void cckd_lock_devchain(int flag) { //struct timespec tm; //struct timeval now; //int timeout; obtain_lock(&cckdblk.devlock); while ((flag && cckdblk.devusers != 0) || (!flag && cckdblk.devusers < 0)) { //gettimeofday(&now,NULL); //tm.tv_sec = now.tv_sec + 2; //tm.tv_nsec = now.tv_usec * 1000; cckdblk.devwaiters++; wait_condition(&cckdblk.devcond, &cckdblk.devlock); //timeout = timed_wait_condition(&cckdblk.devcond, &cckdblk.devlock, &tm); //if (timeout) cckd_print_itrace(); cckdblk.devwaiters--; } if (flag) cckdblk.devusers--; else cckdblk.devusers++; release_lock(&cckdblk.devlock); } void cckd_unlock_devchain() { obtain_lock(&cckdblk.devlock); if (cckdblk.devusers < 0) cckdblk.devusers++; else cckdblk.devusers--; if (cckdblk.devusers == 0 && cckdblk.devwaiters) signal_condition(&cckdblk.devcond); release_lock(&cckdblk.devlock); } /*-------------------------------------------------------------------*/ /* Garbage Collection thread */ /*-------------------------------------------------------------------*/ void cckd_gcol() { int gcol; /* Identifier */ int rc; /* Return code */ DEVBLK *dev; /* -> device block */ CCKDDASD_EXT *cckd; /* -> cckd extension */ long long size, fsiz; /* File size, free size */ struct timeval tv_now; /* Time-of-day (as timeval) */ time_t tt_now; /* Time-of-day (as time_t) */ struct timespec tm; /* Time-of-day to wait */ int gc; /* Garbage collection state */ int gctab[5]= { /* default gcol parameters */ 4096, /* critical 50% - 100% */ 2048, /* severe 25% - 50% */ 1024, /* moderate 12.5% - 25% */ 512, /* light 6.3% - 12.5% */ 256}; /* none 0% - 6.3% */ //char *gcstates[] = {"critical","severe","moderate","light","none"}; obtain_lock (&cckdblk.gclock); gcol = ++cckdblk.gcs; /* Return without messages if too many already started */ if (gcol > cckdblk.gcmax) { --cckdblk.gcs; release_lock (&cckdblk.gclock); return; } if (!cckdblk.batch) { logmsg (_("HHCCD003I Garbage collector thread started: tid="TIDPAT", pid=%d \n"), thread_id(), getpid()); } while (gcol <= cckdblk.gcmax) { cckd_lock_devchain(0); /* Perform collection on each device */ for (dev = cckdblk.dev1st; dev; dev = cckd->devnext) { cckd = dev->cckd_ext; obtain_lock (&cckd->iolock); /* Bypass if merging or stopping */ if (cckd->merging || cckd->stopping) { release_lock (&cckd->iolock); continue; } /* Bypass if not opened read-write */ if (cckd->open[cckd->sfn] != CCKD_OPEN_RW) { release_lock (&cckd->iolock); continue; } /* Free newbuf if it hasn't been used */ if (!cckd->ioactive && !cckd->bufused && cckd->newbuf) cckd->newbuf = cckd_free (dev, "newbuf", cckd->newbuf); cckd->bufused = 0; /* If OPENED bit not on then flush if updated */ if (!(cckd->cdevhdr[cckd->sfn].options & CCKD_OPENED)) { if (cckd->updated) cckd_flush_cache (dev); release_lock (&cckd->iolock); continue; } /* Determine garbage state */ size = (long long)cckd->cdevhdr[cckd->sfn].size; fsiz = (long long)cckd->cdevhdr[cckd->sfn].free_total; if (fsiz >= (size = size/2)) gc = 0; else if (fsiz >= (size = size/2)) gc = 1; else if (fsiz >= (size = size/2)) gc = 2; else if (fsiz >= (size = size/2)) gc = 3; else gc = 4; /* Adjust the state based on the number of free spaces */ if (cckd->cdevhdr[cckd->sfn].free_number > 800 && gc > 0) gc--; if (cckd->cdevhdr[cckd->sfn].free_number > 1800 && gc > 0) gc--; if (cckd->cdevhdr[cckd->sfn].free_number > 3000) gc = 0; /* Set the size */ if (cckdblk.gcparm > 0) size = gctab[gc] << cckdblk.gcparm; else if (cckdblk.gcparm < 0) size = gctab[gc] >> abs(cckdblk.gcparm); else size = gctab[gc]; if (size > cckd->cdevhdr[cckd->sfn].used >> 10) size = cckd->cdevhdr[cckd->sfn].used >> 10; if (size < 64) size = 64; release_lock (&cckd->iolock); /* Call the garbage collector */ cckd_gc_percolate (dev, (unsigned int)size); /* Schedule any updated tracks to be written */ obtain_lock (&cckd->iolock); cckd_flush_cache (dev); while (cckdblk.fsync && cckd->wrpending) wait_condition (&cckd->iocond, &cckd->iolock); release_lock (&cckd->iolock); /* Sync the file */ if (cckdblk.fsync && cckd->lastsync + 10 <= tv_now.tv_sec) { obtain_lock (&cckd->filelock); rc = fdatasync (cckd->fd[cckd->sfn]); cckd->lastsync = tv_now.tv_sec; release_lock (&cckd->filelock); } /* Flush the free space */ if (cckd->cdevhdr[cckd->sfn].free_number) { obtain_lock (&cckd->filelock); cckd_flush_space (dev); release_lock (&cckd->filelock); } } /* for each cckd device */ cckd_unlock_devchain(); /* wait a bit */ gettimeofday (&tv_now, NULL); tm.tv_sec = tv_now.tv_sec + cckdblk.gcwait; tm.tv_nsec = tv_now.tv_usec * 1000; tt_now = tv_now.tv_sec + ((tv_now.tv_usec + 500000)/1000000); cckd_trace (dev, "gcol wait %d seconds at %s", cckdblk.gcwait, ctime (&tt_now)); timed_wait_condition (&cckdblk.gccond, &cckdblk.gclock, &tm); } if (!cckdblk.batch) logmsg (_("HHCCD013I Garbage collector thread stopping: tid="TIDPAT", pid=%d\n"), thread_id(), getpid()); cckdblk.gcs--; if (!cckdblk.gcs) signal_condition (&cckdblk.termcond); release_lock (&cckdblk.gclock); } /* end thread cckd_gcol */ /*-------------------------------------------------------------------*/ /* Garbage Collection -- Percolate algorithm */ /*-------------------------------------------------------------------*/ int cckd_gc_percolate(DEVBLK *dev, unsigned int size) { CCKDDASD_EXT *cckd; /* -> cckd extension */ int rc; /* Return code */ size_t moved = 0; /* Space moved */ int after = 0, a; /* New space after old */ int sfx; /* File index */ int i, j, l; /* Indexes */ int flags; /* Write trkimg flags */ off_t fpos, upos; /* File offsets */ size_t flen, ulen, len; /* Lengths */ int trk; /* Track number */ int l1x,l2x; /* Table Indexes */ CCKD_L2ENT l2; /* Copied level 2 entry */ BYTE buf[256*1024]; /* Buffer */ cckd = dev->cckd_ext; size = size << 10; /* Debug */ if (cckdblk.itracen) { cckd_trace (dev, "gcperc size %d 1st 0x%x nbr %d largest %u\n", size, cckd->cdevhdr[cckd->sfn].free, cckd->cdevhdr[cckd->sfn].free_number, cckd->cdevhdr[cckd->sfn].free_largest); fpos = (off_t)cckd->cdevhdr[cckd->sfn].free; for (i = cckd->free1st; i >= 0; i = cckd->free[i].next) { cckd_trace (dev, "gcperc free[%4d]:%8.8x end %8.8x len %10d%cpend %d\n", i,(int)fpos,(int)(fpos+cckd->free[i].len),(int)cckd->free[i].len, fpos+(int)cckd->free[i].len == (int)cckd->free[i].pos ? '*' : ' ',cckd->free[i].pending); fpos = cckd->free[i].pos; } } if (!cckd->l2ok) cckd_gc_l2(dev, buf); /* garbage collection cycle */ while (moved < size && after < 4) { obtain_lock (&cckd->filelock); sfx = cckd->sfn; /* Exit if no more free space */ if (cckd->cdevhdr[sfx].free_total == 0) { release_lock (&cckd->filelock); return moved; } /* Make sure the free space chain is built */ if (!cckd->free) cckd_read_fsp (dev); /* Find a space to start with */ l = -1; upos = ulen = flen = 0; fpos = cckd->cdevhdr[sfx].free; /* First non-pending free space */ for (i = cckd->free1st; i >= 0; i = cckd->free[i].next) { if (!cckd->free[i].pending) { flen += cckd->free[i].len; break; } fpos = cckd->free[i].pos; } /* Continue to largest if non-zero `after' */ for ( ; i >= 0 && after; i = cckd->free[i].next) { l = i; if (!cckd->free[i].pending) flen += cckd->free[i].len; if (cckd->free[i].len == cckd->cdevhdr[sfx].free_largest) break; fpos = cckd->free[i].pos; } /* Skip following free spaces */ for ( ; i >= 0; i = cckd->free[i].next) { if (!cckd->free[i].pending) flen += cckd->free[i].len; if (fpos + cckd->free[i].len != cckd->free[i].pos) break; fpos = cckd->free[i].pos; } /* Space preceding largest if largest is at the end */ if (i < 0 && l >= 0) { if (!cckd->free[l].pending) flen -= cckd->free[i].len; for (i = cckd->free[l].prev; i >= 0; i = cckd->free[i].prev) { fpos = cckd->free[i].prev >= 0 ? cckd->free[cckd->free[i].prev].pos : cckd->cdevhdr[sfx].free; if (fpos + cckd->free[i].len < cckd->free[i].pos) break; if (!cckd->free[i].pending) flen -= cckd->free[i].len; } } /* Calculate the offset/length of the used space. * If only imbedded free space is left, then start * with the first used space that is not an l2 table. */ if (i >= 0) { upos = fpos + cckd->free[i].len; ulen = (cckd->free[i].pos ? cckd->free[i].pos : cckd->cdevhdr[sfx].size) - upos; } else if (!cckd->cdevhdr[sfx].free_number && cckd->cdevhdr[sfx].free_imbed) { upos = (off_t)(CCKD_L1TAB_POS + cckd->cdevhdr[sfx].numl1tab * CCKD_L1ENT_SIZE); while (1) { for (i = 0; i < cckd->cdevhdr[sfx].numl1tab; i++) if (cckd->l1[sfx][i] == (U32)upos) break; if (i >= cckd->cdevhdr[sfx].numl1tab) break; upos += CCKD_L2TAB_SIZE; } ulen = cckd->cdevhdr[sfx].size - upos; } /* Return if no applicable used space */ if (ulen == 0) { cckd_trace (dev, "gcperc no applicable space, moved %ld\n",(long)moved); release_lock (&cckd->filelock); return moved; } /* Reduce ulen size to minimize `after' relocations */ if (ulen > flen + 65536) ulen = flen + 65536; if (ulen > sizeof(buf)) ulen = sizeof(buf); cckd_trace (dev, "gcperc selected space 0x%" I64_FMT "x len %ld\n", (long long)upos, (long)ulen); if (cckd_read (dev, sfx, upos, buf, ulen) < 0) goto cckd_gc_perc_error; /* Process each space in the buffer */ flags = cckd->cdevhdr[sfx].free_number < 100 ? CCKD_SIZE_EXACT : CCKD_SIZE_ANY; for (i = a = 0; i + CKDDASD_TRKHDR_SIZE <= (int)ulen; i += len) { /* Check for level 2 table */ for (j = 0; j < cckd->cdevhdr[sfx].numl1tab; j++) if (cckd->l1[sfx][j] == (U32)(upos + i)) break; if (j < cckd->cdevhdr[sfx].numl1tab) { /* Moving a level 2 table */ len = CCKD_L2TAB_SIZE; if (i + len > ulen) break; cckd_trace (dev, "gcperc move l2tab[%d] at pos 0x%" I64_FMT "x len %ld\n", j, (unsigned long long)(upos + i), (long)len); /* Make the level 2 table active */ if (cckd_read_l2 (dev, sfx, j) < 0) goto cckd_gc_perc_error; /* Write the level 2 table */ if (cckd_write_l2 (dev) < 0) goto cckd_gc_perc_error; } else { /* Moving a track image */ if ((trk = cckd_cchh (dev, buf + i, -1)) < 0) goto cckd_gc_perc_space_error; l1x = trk >> 8; l2x = trk & 0xff; /* Read the lookup entry for the track */ if (cckd_read_l2ent (dev, &l2, trk) < 0) goto cckd_gc_perc_error; if (l2.pos != (U32)(upos + i)) goto cckd_gc_perc_space_error; len = (int)l2.size; if (i + l2.len > (int)ulen) break; cckd_trace (dev, "gcperc move trk %d at pos 0x%" I64_FMT "x len %d\n", trk, (long long)(upos + i), (int)l2.len); /* Relocate the track image somewhere else */ if ((rc = cckd_write_trkimg (dev, buf + i, (int)l2.len, trk, flags)) < 0) goto cckd_gc_perc_error; a += rc; } } /* for each space in the used space */ /* Set `after' to 1 if first time space was relocated after */ after += after ? a : (a > 0); moved += i; cckdblk.stats_gcolmoves++; cckdblk.stats_gcolbytes += i; release_lock (&cckd->filelock); } /* while (moved < size) */ cckd_trace (dev, "gcperc moved %ld 1st 0x%x nbr %d\n", (long)moved, cckd->cdevhdr[cckd->sfn].free,cckd->cdevhdr[cckd->sfn].free_number); return moved; cckd_gc_perc_space_error: logmsg (_("HHCCD190E %4.4X file[%d] offset 0x%" I64_FMT "x unknown space: " "%2.2x%2.2x%2.2x%2.2x%2.2x\n"), dev->devnum,cckd->sfn,(long long)(upos + i), buf[i], buf[i+1],buf[i+2], buf[i+3], buf[i+4]); cckd->cdevhdr[cckd->sfn].options |= CCKD_SPERRS; cckd_print_itrace(); cckd_gc_perc_error: cckd_trace (dev, "gcperc exiting due to error, moved %ld\n", (long)moved); release_lock (&cckd->filelock); return moved; } /* end function cckd_gc_percolate */ /*-------------------------------------------------------------------*/ /* Garbage Collection -- Reposition level 2 tables */ /* */ /* General idea is to relocate all level 2 tables as close to the */ /* beginning of the file as possible. This can help speed up, for */ /* example, chkdsk processing. */ /* */ /* If any level 2 tables reside outside of the bounds (that is, if */ /* any level 2 table could be moved closer to the beginning of the */ /* file) then first we relocate all track images within the bounds. */ /* Note that cckd_get_space will not allocate space within the */ /* the bounds for track images. Next we try to relocate all level 2 */ /* tables outside the bounds. This may take a few iterations for */ /* the freed space within the bounds to become non-pending. */ /* */ /* The bounds can change as level 2 tables are added or removed. */ /* cckd_read_l1 sets the bounds and they are adjusted by */ /* cckd_write_l2. */ /*-------------------------------------------------------------------*/ int cckd_gc_l2(DEVBLK *dev, BYTE *buf) { CCKDDASD_EXT *cckd; /* -> cckd extension */ int sfx; /* Shadow file index */ int i, j; /* Work variables */ int trk; /* Track number */ int len; /* Track length */ off_t pos, fpos; /* File offsets */ cckd = dev->cckd_ext; obtain_lock (&cckd->filelock); sfx = cckd->sfn; if (cckd->l2ok || cckd->cdevhdr[cckd->sfn].free_total == 0) goto cckd_gc_l2_exit; /* Find any level 2 table out of bounds */ for (i = 0; i < cckd->cdevhdr[sfx].numl1tab; i++) if (cckd->l1[sfx][i] != 0 && cckd->l1[sfx][i] != 0xffffffff && cckd->l2bounds - CCKD_L2TAB_SIZE < (off_t)cckd->l1[sfx][i]) break; /* Return OK if no l2 tables out of bounds */ if (i >= cckd->cdevhdr[sfx].numl1tab) goto cckd_gc_l2_exit_ok; /* Relocate all track images within the bounds */ pos = CCKD_L1TAB_POS + (cckd->cdevhdr[sfx].numl1tab * CCKD_L1ENT_SIZE); i = cckd->free1st; fpos = (off_t)cckd->cdevhdr[sfx].free; while (pos < cckd->l2bounds) { if (i >= 0 && pos == fpos) { pos += cckd->free[i].len; fpos = (off_t)cckd->free[i].pos; i = cckd->free[i].next; j = 0; } else { for (j = 0; j < cckd->cdevhdr[sfx].numl1tab; j++) if (pos == (off_t)cckd->l1[sfx][j]) { pos += CCKD_L2TAB_SIZE; break; } } if (j >= cckd->cdevhdr[sfx].numl1tab) { /* Found a track to relocate */ if (cckd_read (dev, sfx, pos, buf, CKDDASD_TRKHDR_SIZE) < 0) goto cckd_gc_l2_exit; if ((trk = cckd_cchh (dev, buf, -1)) < 0) goto cckd_gc_l2_exit; cckd_trace (dev, "gc_l2 relocate trk[%d] offset 0x%x\n", trk, pos); if ((len = cckd_read_trkimg (dev, buf, trk, NULL)) < 0) goto cckd_gc_l2_exit; if (cckd_write_trkimg (dev, buf, len, trk, CCKD_SIZE_EXACT) < 0) goto cckd_gc_l2_exit; /* Start over */ pos = CCKD_L1TAB_POS + (cckd->cdevhdr[sfx].numl1tab * CCKD_L1ENT_SIZE); i = cckd->free1st; fpos = (off_t)cckd->cdevhdr[sfx].free; } } do { /* Find a level 2 table to relocate */ i = cckd->free1st; fpos = (off_t)cckd->cdevhdr[sfx].free; cckd_trace (dev, "gc_l2 first free[%d] pos 0x%x len %d pending %d\n", i, (int)fpos, i >= 0 ? (int)cckd->free[i].len : -1, i >= 0 ? cckd->free[i].pending : -1); if (i < 0 || fpos >= cckd->l2bounds || cckd->free[i].pending) goto cckd_gc_l2_exit; if (cckd->free[i].len < CCKD_L2TAB_SIZE || (cckd->free[i].len != CCKD_L2TAB_SIZE && cckd->free[i].len < CCKD_L2TAB_SIZE + CCKD_FREEBLK_SIZE ) ) { for (i = 0; i < cckd->cdevhdr[sfx].numl1tab; i++) if (fpos + cckd->free[i].len == (off_t)cckd->l1[sfx][i]) break; } else { for (i = 0; i < cckd->cdevhdr[sfx].numl1tab; i++) if (cckd->l2bounds - CCKD_L2TAB_SIZE < (off_t)cckd->l1[sfx][i] && cckd->l1[sfx][i] != 0xffffffff) break; } if (i < cckd->cdevhdr[sfx].numl1tab) { cckd_trace (dev, "gc_l2 relocate l2[%d] pos 0x%x\n", i, cckd->l1[sfx][i]); if (cckd_read_l2 (dev, sfx, i) < 0) goto cckd_gc_l2_exit; if (cckd_write_l2 (dev) < 0) goto cckd_gc_l2_exit; } } while (i < cckd->cdevhdr[sfx].numl1tab); cckd_gc_l2_exit: release_lock (&cckd->filelock); return 0; cckd_gc_l2_exit_ok: cckd_trace (dev, "gc_l2 ok%s\n", ""); cckd->l2ok = 1; goto cckd_gc_l2_exit; } /*-------------------------------------------------------------------*/ /* Find device by devnum */ /*-------------------------------------------------------------------*/ DEVBLK *cckd_find_device_by_devnum (U16 devnum) { DEVBLK *dev; CCKDDASD_EXT *cckd; cckd_lock_devchain (0); for (dev = cckdblk.dev1st; dev; dev = cckd->devnext) { if (dev->devnum == devnum) break; cckd = dev->cckd_ext; } cckd_unlock_devchain (); return dev; } /* end function cckd_find_device_by_devnum */ /*-------------------------------------------------------------------*/ /* Uncompress a track image */ /*-------------------------------------------------------------------*/ BYTE *cckd_uncompress (DEVBLK *dev, BYTE *from, int len, int maxlen, int trk) { CCKDDASD_EXT *cckd; BYTE *to = NULL; /* Uncompressed buffer */ int newlen; /* Uncompressed length */ BYTE comp; /* Compression type */ static char *compress[] = {"none", "zlib", "bzip2"}; cckd = dev->cckd_ext; cckd_trace (dev, "uncompress comp %d len %d maxlen %d trk %d\n", from[0] & CCKD_COMPRESS_MASK, len, maxlen, trk); /* Extract compression type */ comp = (from[0] & CCKD_COMPRESS_MASK); /* Get a buffer to uncompress into */ if (comp != CCKD_COMPRESS_NONE && cckd->newbuf == NULL) { cckd->newbuf = cckd_malloc (dev, "newbuf", maxlen); if (cckd->newbuf == NULL) return NULL; } /* Uncompress the track image */ switch (comp) { case CCKD_COMPRESS_NONE: newlen = cckd_trklen (dev, from); to = from; break; case CCKD_COMPRESS_ZLIB: to = cckd->newbuf; newlen = cckd_uncompress_zlib (dev, to, from, len, maxlen); break; case CCKD_COMPRESS_BZIP2: to = cckd->newbuf; newlen = cckd_uncompress_bzip2 (dev, to, from, len, maxlen); break; default: newlen = -1; break; } /* Validate the uncompressed track image */ newlen = cckd_validate (dev, to, trk, newlen); /* Return if successful */ if (newlen > 0) { if (to != from) { cckd->newbuf = from; cckd->bufused = 1; } return to; } /* Get a buffer now if we haven't gotten one */ if (cckd->newbuf == NULL) { cckd->newbuf = cckd_malloc (dev, "newbuf2", maxlen); if (cckd->newbuf == NULL) return NULL; } /* Try each uncompression routine in turn */ /* uncompressed */ newlen = cckd_trklen (dev, from); newlen = cckd_validate (dev, from, trk, newlen); if (newlen > 0) return from; /* zlib compression */ to = cckd->newbuf; newlen = cckd_uncompress_zlib (dev, to, from, len, maxlen); newlen = cckd_validate (dev, to, trk, newlen); if (newlen > 0) { cckd->newbuf = from; cckd->bufused = 1; return to; } /* bzip2 compression */ to = cckd->newbuf; newlen = cckd_uncompress_bzip2 (dev, to, from, len, maxlen); newlen = cckd_validate (dev, to, trk, newlen); if (newlen > 0) { cckd->newbuf = from; cckd->bufused = 1; return to; } /* Unable to uncompress */ logmsg (_("HHCCD193E %4.4X file[%d] uncompress error trk %d: %2.2x%2.2x%2.2x%2.2x%2.2x\n"), dev->devnum, cckd->sfn, trk, from[0], from[1], from[2], from[3], from[4]); if (comp & ~cckdblk.comps) logmsg (_("HHCCD194E %4.4X file[%d] %s compression not supported\n"), dev->devnum, cckd->sfn, compress[comp]); return NULL; } int cckd_uncompress_zlib (DEVBLK *dev, BYTE *to, BYTE *from, int len, int maxlen) { #if defined(HAVE_LIBZ) unsigned long newlen; int rc; UNREFERENCED(dev); memcpy (to, from, CKDDASD_TRKHDR_SIZE); newlen = maxlen - CKDDASD_TRKHDR_SIZE; rc = uncompress(&to[CKDDASD_TRKHDR_SIZE], &newlen, &from[CKDDASD_TRKHDR_SIZE], len - CKDDASD_TRKHDR_SIZE); if (rc == Z_OK) { newlen += CKDDASD_TRKHDR_SIZE; to[0] = 0; } else newlen = -1; cckd_trace (dev, "uncompress zlib newlen %d rc %d\n",(int)newlen,rc); return (int)newlen; #else UNREFERENCED(dev); UNREFERENCED(to); UNREFERENCED(from); UNREFERENCED(len); UNREFERENCED(maxlen); return -1; #endif } int cckd_uncompress_bzip2 (DEVBLK *dev, BYTE *to, BYTE *from, int len, int maxlen) { #if defined(CCKD_BZIP2) unsigned int newlen; int rc; UNREFERENCED(dev); memcpy (to, from, CKDDASD_TRKHDR_SIZE); newlen = maxlen - CKDDASD_TRKHDR_SIZE; rc = BZ2_bzBuffToBuffDecompress ( (void *)&to[CKDDASD_TRKHDR_SIZE], &newlen, (void *)&from[CKDDASD_TRKHDR_SIZE], len - CKDDASD_TRKHDR_SIZE, 0, 0); if (rc == BZ_OK) { newlen += CKDDASD_TRKHDR_SIZE; to[0] = 0; } else newlen = -1; cckd_trace (dev, "uncompress bz2 newlen %d rc %d\n",newlen,rc); return (int)newlen; #else UNREFERENCED(dev); UNREFERENCED(to); UNREFERENCED(from); UNREFERENCED(len); UNREFERENCED(maxlen); return -1; #endif } /*-------------------------------------------------------------------*/ /* Compress a track image */ /*-------------------------------------------------------------------*/ int cckd_compress (DEVBLK *dev, BYTE **to, BYTE *from, int len, int comp, int parm) { int newlen; switch (comp) { case CCKD_COMPRESS_NONE: newlen = cckd_compress_none (dev, to, from, len, parm); break; case CCKD_COMPRESS_ZLIB: newlen = cckd_compress_zlib (dev, to, from, len, parm); break; case CCKD_COMPRESS_BZIP2: newlen = cckd_compress_bzip2 (dev, to, from, len, parm); break; default: newlen = cckd_compress_bzip2 (dev, to, from, len, parm); break; } return newlen; } int cckd_compress_none (DEVBLK *dev, BYTE **to, BYTE *from, int len, int parm) { UNREFERENCED(dev); UNREFERENCED(parm); *to = from; from[0] = CCKD_COMPRESS_NONE; return len; } int cckd_compress_zlib (DEVBLK *dev, BYTE **to, BYTE *from, int len, int parm) { #if defined(HAVE_LIBZ) unsigned long newlen; int rc; BYTE *buf; UNREFERENCED(dev); buf = *to; from[0] = CCKD_COMPRESS_NONE; memcpy (buf, from, CKDDASD_TRKHDR_SIZE); buf[0] = CCKD_COMPRESS_ZLIB; newlen = 65535 - CKDDASD_TRKHDR_SIZE; rc = compress2 (&buf[CKDDASD_TRKHDR_SIZE], &newlen, &from[CKDDASD_TRKHDR_SIZE], len - CKDDASD_TRKHDR_SIZE, parm); newlen += CKDDASD_TRKHDR_SIZE; if (rc != Z_OK || (int)newlen >= len) { *to = from; newlen = len; } return (int)newlen; #else #if defined(CCKD_BZIP2) return cckd_compress_bzip2 (dev, to, from, len, parm); #else return cckd_compress_none (dev, to, from, len, parm); #endif #endif } int cckd_compress_bzip2 (DEVBLK *dev, BYTE **to, BYTE *from, int len, int parm) { #if defined(CCKD_BZIP2) unsigned int newlen; int rc; BYTE *buf; UNREFERENCED(dev); buf = *to; from[0] = CCKD_COMPRESS_NONE; memcpy (buf, from, CKDDASD_TRKHDR_SIZE); buf[0] = CCKD_COMPRESS_BZIP2; newlen = 65535 - CKDDASD_TRKHDR_SIZE; rc = BZ2_bzBuffToBuffCompress ( (void *)&buf[CKDDASD_TRKHDR_SIZE], &newlen, (void *)&from[CKDDASD_TRKHDR_SIZE], len - CKDDASD_TRKHDR_SIZE, parm >= 1 && parm <= 9 ? parm : 5, 0, 0); newlen += CKDDASD_TRKHDR_SIZE; if (rc != BZ_OK || newlen >= (unsigned int)len) { *to = from; newlen = len; } return newlen; #else return cckd_compress_zlib (dev, to, from, len, parm); #endif } /*-------------------------------------------------------------------*/ /* cckd command help */ /*-------------------------------------------------------------------*/ void cckd_command_help() { logmsg ("cckd command parameters:\n" "help\t\tDisplay help message\n" "stats\t\tDisplay cckd statistics\n" "opts\t\tDisplay cckd options\n" "comp=\t\tOverride compression\t\t(-1 .. 2)\n" "compparm=\tOverride compression parm\t\t(-1 .. 9)\n" "ra=\t\tSet number readahead threads\t\t(1 .. 9)\n" "raq=\t\tSet readahead queue size\t\t(0 .. 16)\n" "rat=\t\tSet number tracks to read ahead\t\t(0 .. 16)\n" "wr=\t\tSet number writer threads\t\t(1 .. 9)\n" "gcint=\tSet garbage collector interval (sec)\t(1 .. 60)\n" "gcparm=\tSet garbage collector parameter\t\t(-8 .. 8)\n" "\t\t (least agressive ... most aggressive)\n" "nostress=\t1=Disable stress writes\n" "freepend=\tSet free pending cycles\t\t\t(-1 .. 4)\n" "fsync=\t1=Enable fsync()\n" "trace=\tSet trace table size\t\t\t(0 .. 200000)\n" ); } /* end function cckd_command_help */ /*-------------------------------------------------------------------*/ /* cckd command stats */ /*-------------------------------------------------------------------*/ void cckd_command_opts() { logmsg ("comp=%d,compparm=%d,ra=%d,raq=%d,rat=%d," "wr=%d,gcint=%d,gcparm=%d,nostress=%d,\n" "\tfreepend=%d,fsync=%d,trace=%d,linuxnull=%d\n", cckdblk.comp == 0xff ? -1 : cckdblk.comp, cckdblk.compparm, cckdblk.ramax, cckdblk.ranbr, cckdblk.readaheads, cckdblk.wrmax, cckdblk.gcwait, cckdblk.gcparm, cckdblk.nostress, cckdblk.freepend, cckdblk.fsync, cckdblk.itracen, cckdblk.linuxnull); } /* end function cckd_command_opts */ /*-------------------------------------------------------------------*/ /* cckd command stats */ /*-------------------------------------------------------------------*/ void cckd_command_stats() { logmsg("reads....%10" I64_FMT "d Kbytes...%10" I64_FMT "d writes...%10" I64_FMT "d Kbytes...%10" I64_FMT "d\n" "readaheads%9" I64_FMT "d misses...%10" I64_FMT "d syncios..%10" I64_FMT "d misses...%10" I64_FMT "d\n" "switches.%10" I64_FMT "d l2 reads.%10" I64_FMT "d stress writes...%10" I64_FMT "d\n" "cachehits%10" I64_FMT "d misses...%10" I64_FMT "d l2 hits..%10" I64_FMT "d misses...%10" I64_FMT "d\n" "waits i/o......%10" I64_FMT "d cache....%10" I64_FMT "d\n" "garbage collector moves....%10" I64_FMT "d Kbytes...%10" I64_FMT "d\n", cckdblk.stats_reads, cckdblk.stats_readbytes >> 10, cckdblk.stats_writes, cckdblk.stats_writebytes >> 10, cckdblk.stats_readaheads, cckdblk.stats_readaheadmisses, cckdblk.stats_syncios, cckdblk.stats_synciomisses, cckdblk.stats_switches, cckdblk.stats_l2reads, cckdblk.stats_stresswrites, cckdblk.stats_cachehits, cckdblk.stats_cachemisses, cckdblk.stats_l2cachehits, cckdblk.stats_l2cachemisses, cckdblk.stats_iowaits, cckdblk.stats_cachewaits, cckdblk.stats_gcolmoves, cckdblk.stats_gcolbytes >> 10); } /* end function cckd_command_stats */ /*-------------------------------------------------------------------*/ /* cckd command debug */ /*-------------------------------------------------------------------*/ void cckd_command_debug() { } /*-------------------------------------------------------------------*/ /* cckd command processor */ /*-------------------------------------------------------------------*/ DLL_EXPORT int cckd_command(char *op, int cmd) { char *kw, *p, c = '\0', buf[256]; int val, opts = 0; /* Display help for null operand */ if (op == NULL) { if (memcmp (&cckdblk.id, "CCKDBLK ", sizeof(cckdblk.id)) == 0 && cmd) cckd_command_help(); return 0; } strcpy(buf, op); op = buf; /* Initialize the global cckd block if necessary */ if (memcmp (&cckdblk.id, "CCKDBLK ", sizeof(cckdblk.id))) cckddasd_init (0, NULL); while (op) { /* Operands are delimited by commas */ kw = op; op = strchr (op, ','); if (op) *op++ = '\0'; /* Check for keyword = value */ if ((p = strchr (kw, '='))) { *p++ = '\0'; sscanf (p, "%d%c", &val, &c); } else val = -77; /* Parse the keyword */ if (strcasecmp (kw, "stats") == 0) { if (!cmd) return 0; cckd_command_stats (); } else if (strcasecmp (kw, "opts") == 0) { if (!cmd) return 0; cckd_command_opts(); } else if (strcasecmp (kw, "debug") == 0) { if (!cmd) return 0; cckd_command_debug(); } else if (strcasecmp (kw, "comp") == 0) { if (val < -1 || (val & ~cckdblk.comps) || c != '\0') { logmsg ("Invalid value for comp=\n"); return -1; } else { cckdblk.comp = val < 0 ? 0xff : val; opts = 1; } } else if (strcasecmp (kw, "compparm") == 0) { if (val < -1 || val > 9 || c != '\0') { logmsg ("Invalid value for compparm=\n"); return -1; } else { cckdblk.compparm = val; opts = 1; } } else if (strcasecmp (kw, "ra") == 0) { if (val < CCKD_MIN_RA || val > CCKD_MAX_RA || c != '\0') { logmsg ("Invalid value for ra=\n"); return -1; } else { cckdblk.ramax = val; opts = 1; } } else if (strcasecmp (kw, "raq") == 0) { if (val < 0 || val > CCKD_MAX_RA_SIZE || c != '\0') { logmsg ("Invalid value for raq=\n"); return -1; } else { cckdblk.ranbr = val; opts = 1; } } else if (strcasecmp (kw, "rat") == 0) { if (val < 0 || val > CCKD_MAX_RA_SIZE || c != '\0') { logmsg ("Invalid value for rat=\n"); return -1; } else { cckdblk.readaheads = val; opts = 1; } } else if (strcasecmp (kw, "wr") == 0) { if (val < CCKD_MIN_WRITER || val > CCKD_MAX_WRITER || c != '\0') { logmsg ("Invalid value for wr=\n"); return -1; } else { cckdblk.wrmax = val; opts = 1; } } else if (strcasecmp (kw, "gcint") == 0) { if (val < 1 || val > 60 || c != '\0') { logmsg ("Invalid value for gcint=\n"); return -1; } else { cckdblk.gcwait = val; opts = 1; } } else if (strcasecmp (kw, "gcparm") == 0) { if (val < -8 || val > 8 || c != '\0') { logmsg ("Invalid value for gcparm=\n"); return -1; } else { cckdblk.gcparm = val; opts = 1; } } else if (strcasecmp (kw, "nostress") == 0) { if (val < 0 || val > 1 || c != '\0') { logmsg ("Invalid value for nostress=\n"); return -1; } else { cckdblk.nostress = val; opts = 1; } } else if (strcasecmp (kw, "freepend") == 0) { if (val < -1 || val > CCKD_MAX_FREEPEND || c != '\0') { logmsg ("Invalid value for freepend=\n"); return -1; } else { cckdblk.freepend = val; opts = 1; } } else if (strcasecmp (kw, "fsync") == 0) { if (val < 0 || val > 1 || c != '\0') { logmsg ("Invalid value for fsync=\n"); return -1; } else { cckdblk.fsync = val; opts = 1; } } else if (strcasecmp (kw, "trace") == 0) { if (val < 0 || val > CCKD_MAX_TRACE || c != '\0') { logmsg ("Invalid value for trace=\n"); return -1; } else { /* Disable tracing in case it's already active */ CCKD_TRACE *p = cckdblk.itrace; cckdblk.itrace = NULL; if (p) { SLEEP (1); cckdblk.itrace = cckdblk.itracep = cckdblk.itracex = NULL; cckdblk.itracen = 0; cckd_free (NULL, "trace", p); } /* Get a new trace table */ if (val > 0) { p = cckd_calloc (NULL, "trace", val, sizeof(CCKD_TRACE)); if (p) { cckdblk.itracen = val; cckdblk.itracex = p + val; cckdblk.itracep = p; cckdblk.itrace = p; } } opts = 1; } } else if (strcasecmp (kw, "linuxnull") == 0) { if (val < 0 || val > 1 || c != '\0') { logmsg ("Invalid value for linuxnull=\n"); return -1; } else { cckdblk.linuxnull = val; opts = 1; } } else if (strcasecmp (kw, "gcstart") == 0) { DEVBLK *dev; CCKDDASD_EXT *cckd; TID tid; int flag = 0; cckd_lock_devchain(0); for (dev = cckdblk.dev1st; dev; dev = cckd->devnext) { cckd = dev->cckd_ext; obtain_lock (&cckd->filelock); if (cckd->cdevhdr[cckd->sfn].free_total) { cckd->cdevhdr[cckd->sfn].options |= (CCKD_OPENED | CCKD_ORDWR); cckd_write_chdr (dev); flag = 1; } release_lock (&cckd->filelock); } cckd_unlock_devchain(); if (flag && cckdblk.gcs < cckdblk.gcmax) create_thread (&tid, JOINABLE, cckd_gcol, NULL, "cckd_gcol"); } else { logmsg ("cckd invalid keyword: %s\n",kw); if (!cmd) return -1; cckd_command_help (); op = NULL; } } if (cmd && opts) cckd_command_opts(); return 0; } /* end function cckd_command */ /*-------------------------------------------------------------------*/ /* Print internal trace */ /*-------------------------------------------------------------------*/ DLL_EXPORT void cckd_print_itrace() { CCKD_TRACE *i, *p; /* Trace table pointers */ if (!cckdblk.itrace) return; logmsg (_("HHCCD900I print_itrace\n")); i = cckdblk.itrace; cckdblk.itrace = NULL; SLEEP (1); p = cckdblk.itracep; if (p >= cckdblk.itracex) p = i; do { if (p[0] != '\0') logmsg ("%s", (char *)p); if (++p >= cckdblk.itracex) p = i; } while (p != cckdblk.itracep); memset (i, 0, cckdblk.itracen * sizeof(CCKD_TRACE)); cckdblk.itracep = i; cckdblk.itrace = i; } /* end function cckd_print_itrace */ /*-------------------------------------------------------------------*/ /* Write internal trace entry */ /*-------------------------------------------------------------------*/ void cckd_trace(DEVBLK *dev, char *msg, ...) { va_list vl; struct timeval tv; time_t t; char tbuf[64]; CCKD_TRACE *p; int l; if (dev && (dev->ccwtrace||dev->ccwstep)) { char *bfr; int sz=1024,rc; bfr=malloc(1024); va_start(vl,msg); while(1) { rc=vsnprintf(bfr,sz,msg,vl); if(rc<0) { free(bfr); bfr=NULL; break; } if(rcdevnum,bfr); } va_end(vl); } /* ISW FIXME : The following code has a potential */ /* for heap overrun (vsprintf) */ if (cckdblk.itrace) { gettimeofday(&tv, NULL); t = tv.tv_sec; strcpy(tbuf, ctime(&t)); tbuf[19] = '\0'; va_start(vl,msg); p = cckdblk.itracep++; if (p >= cckdblk.itracex) { p = cckdblk.itrace; cckdblk.itracep = p + 1; } if (p) { l = sprintf ((char *)p, "%s" "." "%6.6ld %4.4X:", tbuf+11, tv.tv_usec, dev ? dev->devnum : 0); vsprintf ((char *)p + l, msg, vl); } } } /* end function cckd_trace */ DEVHND cckddasd_device_hndinfo = { &ckddasd_init_handler, /* Device Initialisation */ &ckddasd_execute_ccw, /* Device CCW execute */ &cckddasd_close_device, /* Device Close */ &ckddasd_query_device, /* Device Query */ &cckddasd_start, /* Device Start channel pgm */ &cckddasd_end, /* Device End channel pgm */ &cckddasd_start, /* Device Resume channel pgm */ &cckddasd_end, /* Device Suspend channel pgm */ &cckd_read_track, /* Device Read */ &cckd_update_track, /* Device Write */ &cckd_used, /* Device Query used */ NULL, /* Device Reserve */ NULL, /* Device Release */ NULL, /* Device Attention */ NULL, /* Immediate CCW Codes */ NULL, /* Signal Adapter Input */ NULL, /* Signal Adapter Ouput */ &ckddasd_hsuspend, /* Hercules suspend */ &ckddasd_hresume /* Hercules resume */ }; DEVHND cfbadasd_device_hndinfo = { &fbadasd_init_handler, /* Device Initialisation */ &fbadasd_execute_ccw, /* Device CCW execute */ &cckddasd_close_device, /* Device Close */ &fbadasd_query_device, /* Device Query */ &cckddasd_start, /* Device Start channel pgm */ &cckddasd_end, /* Device End channel pgm */ &cckddasd_start, /* Device Resume channel pgm */ &cckddasd_end, /* Device Suspend channel pgm */ &cfba_read_block, /* Device Read */ &cfba_write_block, /* Device Write */ &cfba_used, /* Device Query used */ NULL, /* Device Reserve */ NULL, /* Device Release */ NULL, /* Device Attention */ NULL, /* Immediate CCW Codes */ NULL, /* Signal Adapter Input */ NULL, /* Signal Adapter Ouput */ &fbadasd_hsuspend, /* Hercules suspend */ &fbadasd_hresume /* Hercules resume */ }; hercules-3.07/cckddiag.c000644 000765 000765 00000066615 11321734033 016653 0ustar00jmaynardjmaynard000000 000000 /* CCKDDIAG.C (c) Copyright Roger Bowler, 1999-2009 */ /* CCKD diagnostic tool */ /* 2003-02-07 James M. Morrison initial implementation */ /* portions borrowed from cckdcdsk & other CCKD code */ // $Id: cckddiag.c 5540 2009-12-12 07:13:45Z bernard $ /*-------------------------------------------------------------------*/ /* Diagnostic tool to display various CCKD data */ /*-------------------------------------------------------------------*/ // $Log$ // Revision 1.28 2008/11/04 04:50:45 fish // Ensure consistent utility startup // // Revision 1.27 2008/06/22 05:54:30 fish // Fix print-formatting issue (mostly in tape modules) // that can sometimes, in certain circumstances, // cause herc to crash. (%8.8lx --> I32_FMTX, etc) // // Revision 1.26 2007/06/23 00:04:03 ivan // Update copyright notices to include current year (2007) // // Revision 1.25 2006/12/08 09:43:17 jj // Add CVS message log // #include "hstdinc.h" /* TODO: add FBA support or write cfbadiag */ #include "hercules.h" #include "dasdblks.h" /* data_dump */ typedef struct _CKD_RECSTAT { /* CKD DASD record stats */ int cc; /* CC cylinder # (relative zero) */ int hh; /* HH head # (relative zero) */ int r; /* Record # (relative zero) */ int kl; /* key length */ int dl; /* data length */ } CKD_RECSTAT; /*-------------------------------------------------------------------*/ /* Global data areas */ /*-------------------------------------------------------------------*/ CCKD_L1ENT *l1 = NULL; /* L1TAB */ CCKD_L2ENT *l2 = NULL; /* L2TAB */ void *tbuf = NULL; /* track header & data */ void *bulk = NULL; /* bulk data buffer */ int fd = 0; /* File descriptor */ static BYTE eighthexFF[] = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}; #ifdef DEBUG int debug = 1; // enable debug code #else int debug = 0; // disable debug code #endif int pausesnap = 0; // 1 = pause after snap (getc) /*-------------------------------------------------------------------*/ /* print syntax */ /*-------------------------------------------------------------------*/ int syntax() { fprintf (stdout, "\n" "cckddiag [options] file-name\n" "Valid options are one or more of the following:\n" " -v display version and exit\n" " -d display DEVHDR\n" " -c display CDEVHDR\n" " -1 display L1TAB (numeric one)\n" " -g enable debug output\n" "CKD track related options:\n" " -a cc hh display absolute CCHH data\n" " -r tt display relative TT data\n" " -2 display L2TAB related to -a or -r\n" " -t display track data\n" " -x hex display track key/data\n" "Offset option:\n" " -o oo ll hex display data at offset oo of length ll\n" "Further information: man 1 cckddiag\n" ); return -1; } /*-------------------------------------------------------------------*/ /* snap - display msg, dump data */ /*-------------------------------------------------------------------*/ /* Newline appended to message */ void snap(char *msg, void *data, int len) { int x; if (msg != NULL) fprintf(stdout, "%s\n", msg); data_dump(data, len); if (pausesnap) { fprintf(stdout, "Press enter to continue\n"); x = getc(stdin); } } /*-------------------------------------------------------------------*/ /* clean - cleanup before exit */ /*-------------------------------------------------------------------*/ void clean(void) { close(fd); free(l1); /* L1TAB buffer */ free(l2); /* L2TAB buffer */ free(tbuf); /* track and header buffer */ free(bulk); /* offset data buffer */ } /*-------------------------------------------------------------------*/ /* makbuf - allocate buffer, handle errors (exit if any) */ /*-------------------------------------------------------------------*/ void *makbuf(int len, char *label) { void *p; p = malloc(len); if (p == NULL) { fprintf(stdout, "malloc %s of length %d failed\n", label, len); clean(); exit(4); } if (debug) fprintf(stdout, "\n" "MAKBUF malloc %s buffer of %d bytes at %p\n", label, len, p); return p; } /*-------------------------------------------------------------------*/ /* readpos - common lseek and read invocation with error handling */ /*-------------------------------------------------------------------*/ /* This code exits on error rather than return to caller. */ int readpos( int fd, /* opened CCKD image file */ void *buf, /* buffer of size len */ off_t offset, /* offset into CCKD image to read */ size_t len /* length of data to read */ ) { if (debug) fprintf(stdout, "\nREADPOS seeking %d (0x%8.8X)\n", (int)offset, (unsigned int)offset); if (lseek(fd, offset, SEEK_SET) < 0) { fprintf(stdout, _("lseek to pos 0x%8.8x error: %s\n"), (unsigned int) offset, strerror(errno)); clean(); exit (1); } if (debug) fprintf(stdout, "READPOS reading buf addr "PTR_FMTx" length %"SIZE_T_FMT"d (0x"SIZE_T_FMTX")\n", (uintptr_t)buf, len, len); if (read(fd, buf, len) < (ssize_t)len) { fprintf(stdout, _("cckddiag: read error: %s\n"), strerror(errno)); clean(); exit (2); } return 0; } /*-------------------------------------------------------------------*/ /* decomptrk - decompress track data */ /*-------------------------------------------------------------------*/ int decomptrk( BYTE *ibuf, /* input buffer address */ int ibuflen, /* input buffer length */ BYTE *obuf, /* output buffer address */ int obuflen, /* output buffer length */ int heads, /* >=0 means CKD, else FBA */ int trk, /* relative track or block number */ char *msg /* addr of 80 byte msg buf or NULL */ ) /* ibuf points at CKDDASD_TRKHDR header followed by track data */ /* ibuflen specifies length of TRKHDR and data */ /* This code based on decompression logic in cdsk_valid_trk. */ /* Returns length of decompressed data or -1 on error. */ { #if defined( HAVE_LIBZ ) || defined( CCKD_BZIP2 ) int rc; /* Return code */ BYTE *bufp; /* Buffer pointer */ #endif size_t bufl; /* Buffer length */ #ifdef CCKD_BZIP2 unsigned int ubufl; /* when size_t != unsigned int */ #endif #if !defined( HAVE_LIBZ ) && !defined( CCKD_BZIP2 ) UNREFERENCED(heads); UNREFERENCED(trk); UNREFERENCED(msg); #endif memset(obuf, 0x00, obuflen); /* clear output buffer */ /* Uncompress the track/block image */ switch (ibuf[0] & CCKD_COMPRESS_MASK) { case CCKD_COMPRESS_NONE: bufl = (ibuflen < obuflen) ? ibuflen : obuflen; memcpy (obuf, ibuf, bufl); break; #ifdef HAVE_LIBZ case CCKD_COMPRESS_ZLIB: bufp = (BYTE *)obuf; memcpy (obuf, ibuf, CKDDASD_TRKHDR_SIZE); bufl = obuflen - CKDDASD_TRKHDR_SIZE; rc = uncompress(&obuf[CKDDASD_TRKHDR_SIZE], (void *)&bufl, &ibuf[CKDDASD_TRKHDR_SIZE], ibuflen); if (rc != Z_OK) { if (msg) snprintf(msg, 80, "%s %d uncompress error, rc=%d;" "%2.2x%2.2x%2.2x%2.2x%2.2x", heads >= 0 ? "trk" : "blk", trk, rc, ibuf[0], ibuf[1], ibuf[2], ibuf[3], ibuf[4]); return -1; } bufl += CKDDASD_TRKHDR_SIZE; break; #endif #ifdef CCKD_BZIP2 case CCKD_COMPRESS_BZIP2: bufp = obuf; memcpy(obuf, ibuf, CKDDASD_TRKHDR_SIZE); ubufl = obuflen - CKDDASD_TRKHDR_SIZE; rc = BZ2_bzBuffToBuffDecompress ( (char *)&obuf[CKDDASD_TRKHDR_SIZE], &ubufl, (char *)&ibuf[CKDDASD_TRKHDR_SIZE], ibuflen, 0, 0); if (rc != BZ_OK) { if (msg) snprintf(msg, 80, "%s %d decompress error, rc=%d;" "%2.2x%2.2x%2.2x%2.2x%2.2x", heads >= 0 ? "trk" : "blk", trk, rc, ibuf[0], ibuf[1], ibuf[2], ibuf[3], ibuf[4]); return -1; } bufl=ubufl; bufl += CKDDASD_TRKHDR_SIZE; break; #endif default: return -1; } /* switch (buf[0] & CCKD_COMPRESS_MASK) */ return bufl; } /*-------------------------------------------------------------------*/ /* show_ckd_count - display CKD dasd record COUNT field */ /*-------------------------------------------------------------------*/ /* RECHDR is stored in big-endian byte order. */ BYTE *show_ckd_count(CKDDASD_RECHDR *rh, int trk) { int cc, hh, r, kl, dl; BYTE *past; cc = (rh->cyl[0] << 8) | (rh->cyl[1]); hh = (rh->head[0] << 8) | (rh->head[1]); r = rh->rec; kl = rh->klen; dl = (rh->dlen[0] << 8) | (rh->dlen[1]); fprintf(stdout, "\n" "Track %d COUNT " "CC=%d HH=%d R=%d KL=%d DL=%d\n", trk, cc, hh, r, kl, dl); past = (BYTE *)rh + sizeof(CKDDASD_RECHDR); return past; } /*-------------------------------------------------------------------*/ /* show_ckd_key - display CKD dasd record KEY field */ /*-------------------------------------------------------------------*/ BYTE *show_ckd_key(CKDDASD_RECHDR *rh, BYTE *buf, int trk, int xop) { if (rh->klen && xop) { fprintf(stdout, "\nTrack %d R%d KEY (%d bytes)\n", trk, rh->rec, rh->klen); data_dump(buf, rh->klen); } return (BYTE *)buf + rh->klen; /* skip past KEY field */ } /*-------------------------------------------------------------------*/ /* show_ckd_data - display CKD dasd record DATA field */ /*-------------------------------------------------------------------*/ BYTE *show_ckd_data(CKDDASD_RECHDR *rh, BYTE *buf, int trk, int xop) { int dl; dl = (rh->dlen[0] << 8) | (rh->dlen[1]); if (dl && xop) { fprintf(stdout, "\nTrack %d R%d DATA (%d bytes)\n", trk, rh->rec, dl); data_dump(buf, dl); } return buf + dl; /* skip past DATA field */ } /*-------------------------------------------------------------------*/ /* showtrk - display track data */ /*-------------------------------------------------------------------*/ /* This code mimics selected logic in cdsk_valid_trk. */ void showtrk( CKDDASD_TRKHDR *buf, /* track header ptr */ int imglen, /* TRKHDR + track user data length */ int trk, /* relative track number */ int xop /* 1=dump key & data blks; 0=don't */ ) { BYTE buf2[64*1024]; /* max uncompressed buffer */ char msg[81]; /* error message buffer */ CKDDASD_RECHDR *rh; /* CCKD COUNT field */ BYTE *bufp; int len; if (debug) snap("\nSHOWTRK Compressed track header and data", buf, imglen); len = decomptrk( (BYTE *)buf, /* input buffer address */ imglen, /* input buffer length */ buf2, /* output buffer address */ sizeof(buf2), /* output buffer length */ 1, /* >=0 means CKD, else FBA */ trk, /* relative track or block number */ msg /* addr of message buffer */ ); if (debug) snap("\nSHOWTRK Decompressed track header and data", buf2, len); bufp = &buf2[sizeof(CKDDASD_TRKHDR)]; while (bufp < &buf2[sizeof(buf2)]) { rh = (CKDDASD_RECHDR *)bufp; if (memcmp((BYTE *)rh, &eighthexFF, 8) == 0) { fprintf(stdout, "\nEnd of Track\n"); break; } bufp = show_ckd_count(rh, trk); bufp = show_ckd_key(rh, bufp, trk, xop); bufp = show_ckd_data(rh, bufp, trk, xop); } } /*-------------------------------------------------------------------*/ /* offtify - given decimal or hex input string, return off_t */ /* Locale independent, does not check for overflow */ /* References and */ /*-------------------------------------------------------------------*/ /* Based on code in P. J. Plauger's "The Standard C Library" */ /* See page 34, in Chapter 2 (ctype.h) */ off_t offtify(char *s) { static const char xd[] = {"0123456789abcdefABCDEF"}; static const char xv[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 10, 11, 12, 13, 14, 15}; off_t v; char *p; p = s; if ( (*s == '0') && (*(s+1) == 'x') ) { s = s + 2; for (v = 0; isxdigit(*s); ++s) v = (v << 4) + xv[strchr(xd, *s) - xd]; if (debug) fprintf(stdout, "OFFTIFY string %s hex %8.8" I64_FMT "X decimal %" I64_FMT "d\n", p, (U64)v, (U64)v); return v; } else { /* decimal input */ v = (off_t) atoll(s); if (debug) fprintf(stdout, "OFFTIFY string %s decimal %" I64_FMT "X %" I64_FMT "d\n", p, (U64)v, (U64)v); return v; } } /*-------------------------------------------------------------------*/ /* Main function for CCKD diagnostics */ /*-------------------------------------------------------------------*/ int main (int argc, char *argv[]) { int cckd_diag_rc = 0; /* Program return code */ char *fn; /* File name */ CKDDASD_DEVHDR devhdr; /* [C]CKD device hdr */ CCKDDASD_DEVHDR cdevhdr; /* Compressed CKD device hdr */ CKDDEV *ckd=0; /* CKD DASD table entry */ FBADEV *fba=0; /* FBA DASD table entry */ int cmd_devhdr = 0; /* display DEVHDR */ int cmd_cdevhdr = 0; /* display CDEVHDR */ int cmd_l1tab = 0; /* display L1TAB */ int cmd_l2tab = 0; /* display L2TAB */ int cmd_trkdata = 0; /* display track data */ int cmd_hexdump = 0; /* display track data (hex) */ int cmd_offset = 0; /* 1 = display data at */ int op_offset = 0; /* op_offset of length */ int op_length = 0; /* op_length */ int cmd_cchh = 0; /* 1 = display CCHH data */ int op_cc = 0; /* CC = cylinder */ int op_hh = 0; /* HH = head */ int cmd_tt = 0; /* 1 = display TT data */ int op_tt = 0; /* relative track # */ int swapend; /* 1 = New endianess doesn't match machine endianess */ int n, trk=0, l1ndx=0, l2ndx=0; off_t l2taboff=0; /* offset to assoc. L2 table */ int ckddasd; /* 1=CKD dasd 0=FBA dasd */ int heads=0; /* Heads per cylinder */ int blks; /* Number fba blocks */ off_t trkhdroff=0; /* offset to assoc. trk hdr */ int imglen=0; /* track length */ char pathname[MAX_PATH]; /* file path in host format */ INITIALIZE_UTILITY("cckddiag"); /* parse the arguments */ argc--; argv++ ; while (argc > 0) { if(**argv != '-') break; switch(argv[0][1]) { case 'v': if (argv[0][2] != '\0') return syntax (); display_version (stdout, "Hercules CCKD diagnostic program\n", FALSE); return 0; case 'd': if (argv[0][2] != '\0') return syntax (); cmd_devhdr = 1; break; case 'c': if (argv[0][2] != '\0') return syntax (); cmd_cdevhdr = 1; break; case '1': if (argv[0][2] != '\0') return syntax (); cmd_l1tab = 1; break; case '2': if (argv[0][2] != '\0') return syntax (); cmd_l2tab = 1; break; case 'a': if (argv[0][2] != '\0') return syntax (); cmd_cchh = 1; argc--; argv++; op_cc = offtify(*argv); argc--; argv++; op_hh = offtify(*argv); break; case 'r': if (argv[0][2] != '\0') return syntax (); cmd_tt = 1; argc--; argv++; op_tt = offtify(*argv); break; case 'o': if (argv[0][2] != '\0') return syntax (); cmd_offset = 1; argc--; argv++; op_offset = offtify(*argv); argc--; argv++; op_length = offtify(*argv); break; case 't': if (argv[0][2] != '\0') return syntax (); cmd_trkdata = 1; break; case 'x': if (argv[0][2] != '\0') return syntax (); cmd_hexdump = 1; cmd_trkdata = 1; break; case 'g': if (argv[0][2] != '\0') return syntax (); debug = 1; break; default: return syntax (); } argc--; argv++; } if (argc != 1) return syntax (); fn = argv[0]; /* open the file */ hostpath(pathname, fn, sizeof(pathname)); fd = open(pathname, O_RDONLY | O_BINARY); if (fd < 0) { fprintf(stdout, _("cckddiag: error opening file %s: %s\n"), fn, strerror(errno)); return -1; } /*---------------------------------------------------------------*/ /* display DEVHDR - first 512 bytes of dasd image */ /*---------------------------------------------------------------*/ readpos(fd, &devhdr, 0, sizeof(devhdr)); if (cmd_devhdr) { fprintf(stdout, "\nDEVHDR - %"SIZE_T_FMT"d (decimal) bytes:\n", sizeof(devhdr)); data_dump(&devhdr, sizeof(devhdr)); } /*---------------------------------------------------------------*/ /* Determine CKD or FBA device type */ /*---------------------------------------------------------------*/ if (memcmp(devhdr.devid, "CKD_C370", 8) == 0 || memcmp(devhdr.devid, "CKD_S370", 8) == 0) { ckddasd = 1; ckd = dasd_lookup(DASD_CKDDEV, NULL, devhdr.devtype, 0); if (ckd == NULL) { fprintf(stdout, "DASD table entry not found for devtype 0x%2.2X\n", devhdr.devtype); clean(); exit(5); } } else if (memcmp(devhdr.devid, "FBA_C370", 8) == 0 || memcmp(devhdr.devid, "FBA_S370", 8) == 0) { ckddasd = 0; fba = dasd_lookup(DASD_FBADEV, NULL, devhdr.devtype, 0); if (fba == NULL) { fprintf(stdout, "DASD table entry not found for " "devtype 0x%2.2X\n", DEFAULT_FBA_TYPE); clean(); exit(6); } } else { fprintf(stdout, "incorrect header id\n"); clean(); return -1; } /*---------------------------------------------------------------*/ /* Set up device characteristics */ /*---------------------------------------------------------------*/ if (ckddasd) { heads = ((U32)(devhdr.heads[3]) << 24) | ((U32)(devhdr.heads[2]) << 16) | ((U32)(devhdr.heads[1]) << 8) | (U32)(devhdr.heads[0]); if (debug) fprintf(stdout, "\n%s device has %d heads/cylinder\n", ckd->name, heads); } else { blks = 0; #if 0 /* cdevhdr is uninitialized and blks is never referenced... */ blks = ((U32)(cdevhdr.cyls[0]) << 24) | ((U32)(cdevhdr.cyls[2]) << 16) | ((U32)(cdevhdr.cyls[1]) << 8) | (U32)(cdevhdr.cyls[0]); #endif } /*---------------------------------------------------------------*/ /* display CDEVHDR - follows DEVHDR */ /*---------------------------------------------------------------*/ readpos(fd, &cdevhdr, CKDDASD_DEVHDR_SIZE, sizeof(cdevhdr)); if (cmd_cdevhdr) { fprintf(stdout, "\nCDEVHDR - %"SIZE_T_FMT"d (decimal) bytes:\n", sizeof(cdevhdr)); data_dump(&cdevhdr, sizeof(cdevhdr)); } /*---------------------------------------------------------------*/ /* Find machine endian-ness */ /*---------------------------------------------------------------*/ /* cckd_endian() returns 1 for big-endian machines */ swapend = (cckd_endian() != ((cdevhdr.options & CCKD_BIGENDIAN) != 0)); /*---------------------------------------------------------------*/ /* display L1TAB - follows CDEVHDR */ /*---------------------------------------------------------------*/ /* swap numl1tab if needed */ n = cdevhdr.numl1tab; if (swapend) cckd_swapend4((char *)&n); l1 = makbuf(n * CCKD_L1ENT_SIZE, "L1TAB"); readpos(fd, l1, CCKD_L1TAB_POS, n * CCKD_L1ENT_SIZE); /* L1TAB itself is not adjusted for endian-ness */ if (cmd_l1tab) { fprintf(stdout, "\nL1TAB - %"SIZE_T_FMT"d (0x"SIZE_T_FMTX") bytes:\n", (n * CCKD_L1ENT_SIZE), (n * CCKD_L1ENT_SIZE)); data_dump(l1, n * CCKD_L1ENT_SIZE); } /*---------------------------------------------------------------*/ /* display OFFSET, LENGTH data */ /*---------------------------------------------------------------*/ if (cmd_offset) { bulk = makbuf(op_length, "BULK"); readpos(fd, bulk, op_offset, op_length); fprintf(stdout, "\nIMAGE OFFSET %d (0x%8.8X) " "of length %d (0x%8.8X) bytes:\n", op_offset, op_offset, op_length, op_length); data_dump(bulk, op_length); free(bulk); bulk = NULL; } /*---------------------------------------------------------------*/ /* FBA isn't supported here because I don't know much about FBA */ /*---------------------------------------------------------------*/ if ( (!ckddasd) && ((cmd_cchh) || (cmd_tt)) ) { fprintf(stdout, "CCHH/reltrk not supported for FBA\n"); clean(); exit(3); } /*---------------------------------------------------------------*/ /* Setup CCHH or relative track request */ /*---------------------------------------------------------------*/ if (ckddasd) { if (cmd_tt) { trk = op_tt; op_cc = trk / heads; op_hh = trk % heads; } else { trk = (op_cc * heads) + op_hh; } l1ndx = trk / cdevhdr.numl2tab; l2ndx = trk % cdevhdr.numl2tab; l2taboff = l1[l1ndx]; if (swapend) cckd_swapend4((char *)&l2taboff); } /*---------------------------------------------------------------*/ /* display CKD CCHH or relative track data */ /*---------------------------------------------------------------*/ if ((cmd_cchh) || (cmd_tt)) { fprintf(stdout, "CC %d HH %d = reltrk %d; " "L1 index = %d, L2 index = %d\n" "L1 index %d = L2TAB offset %d (0x%8.8X)\n", op_cc, op_hh, trk, l1ndx, l2ndx, l1ndx, (int)l2taboff, (int)l2taboff); l2 = makbuf(cdevhdr.numl2tab * sizeof(CCKD_L2ENT), "L2TAB"); readpos(fd, l2, l2taboff, cdevhdr.numl2tab * sizeof(CCKD_L2ENT)); if (cmd_l2tab) { fprintf(stdout, "\nL2TAB - %"SIZE_T_FMT"d (decimal) bytes\n", (cdevhdr.numl2tab * sizeof(CCKD_L2ENT))); data_dump(l2, (cdevhdr.numl2tab * sizeof(CCKD_L2ENT)) ); } fprintf(stdout, "\nL2 index %d = L2TAB entry %"SIZE_T_FMT"d bytes\n", l2ndx, sizeof(CCKD_L2ENT) ); data_dump(&l2[l2ndx], sizeof(CCKD_L2ENT) ); trkhdroff = l2[l2ndx].pos; imglen = l2[l2ndx].len; if (swapend) { cckd_swapend4((char *)&trkhdroff); cckd_swapend4((char *)&imglen); } fprintf(stdout, "\nTRKHDR offset %d (0x%8.8X); " "length %d (0x%4.4X)\n", (int)trkhdroff, (int)trkhdroff, imglen, imglen); tbuf = makbuf(imglen, "TRKHDR+DATA"); readpos(fd, tbuf, trkhdroff, imglen); fprintf(stdout, "\nTRKHDR track %d\n", trk); data_dump(tbuf, sizeof(CKDDASD_TRKHDR) ); if (cmd_trkdata) showtrk(tbuf, imglen, trk, cmd_hexdump); free(l2); free(tbuf); l2 = NULL; tbuf = NULL; } /* Close file, exit */ fprintf(stdout, "\n"); clean(); return cckd_diag_rc; } hercules-3.07/cckdfix.c000644 000765 000765 00000006310 11143760544 016527 0ustar00jmaynardjmaynard000000 000000 // $Id: cckdfix.c 4102 2006-12-08 09:43:35Z jj $ // // $Log$ #include "hercules.h" int main ( int argc, char *argv[]) { int fd; CKDDASD_DEVHDR devhdr; CCKDDASD_DEVHDR cdevhdr; int heads, cyls, devt; char pathname[MAX_PATH]; hostpath(pathname, argv[1], sizeof(pathname)); fd = open (pathname, O_RDWR|O_BINARY); if (fd < 0) return 1; read (fd, &devhdr, CKDDASD_DEVHDR_SIZE); read (fd, &cdevhdr, CCKDDASD_DEVHDR_SIZE); /* --------------------------------------- */ /* Device header updates */ /* --------------------------------------- */ /* device identifier */ // memcpy (devhdr.devid, "CKD_C370", 8); /* number of heads per cylinder must be in little-endian byte order */ // devhdr.heads[3] = (heads >> 24) & 0xFF; // devhdr.heads[2] = (heads >> 16) & 0xFF; // devhdr.heads[1] = (heads >> 8) & 0xFF; // devhdr.heads[0] = heads & 0xFF; /* device type -- last two digits */ // devhdr.devtype = devt; /* eg 0x90 for 3390 */ /* file sequence number; must be zero for compressed ckd dasd emulation */ // devhdr.fileseq = 0; /* highest cylinder on this file; must be zero for compressed ckd dasd emulation */ // devhdr.highcyl[0] = 0; // devhdr.highcyl[1] = 0; // memset (&devhdr.resv, 0, 492); /* --------------------------------------- */ /* Compressed device header updates */ /* --------------------------------------- */ /* version-release-modification level */ // cdevhdr.vrm[0] = CCKD_VERSION; // cdevhdr.vrm[0] = CCKD_RELEASE; // cdevhdr.vrm[0] = CCKD_MODLVL; /* options byte */ // cdevhdr.options = 0; // cdevhdr.options |= CCKD_NOFUDGE; // cdevhdr.options |= CCKD_BIGENDIAN; // cdevhdr.options |= CCKD_OPENED; /* lookup table sizes*/ // cdevhdr.numl1tab = (cyls * heads) >> 8; // if ((cyls * heads) & 0xff != 0) // cdevhdr.numl1tab++; // cdevhdr.numl2tab = 256; /* free space header -- set to zeroes to force cckdcdsk to rebuild the free space */ // cdevhdr.size = cdevhdr.used = cdevhdr.free = // cdevhdr.free_total = cdevhdr.free_largest = // cdevhdr.free_number = cdevhdr.free_imbed = 0; /* number of cylinders on the emulated device must be in little-endian byte order */ // cdevhdr.cyls[3] = (cyls >> 24) & 0xFF; // cdevhdr.cyls[2] = (cyls >> 16) & 0xFF; // cdevhdr.cyls[1] = (cyls >> 8) & 0xFF; // cdevhdr.cyls[0] = cyls & 0xFF; // cdevhdr.resv1 = 0; /* compression algorithm and parameter */ // cdevhdr.compress = CCKD_COMPRESS_NONE; // cdevhdr.compress_parm = 0; // cdevhdr.compress = CCKD_COMPRESS_ZLIB; // cdevhdr.compress_parm = Z_DEFAULT_COMPRESSION; // cdevhdr.compress = CCKD_COMPRESS_BZIP2; // cdevhdr.compress_parm = 5; // memset (&cdevhdr.resv2, 0, 464); lseek (fd, 0, SEEK_SET); write (fd, &devhdr, CKDDASD_DEVHDR_SIZE); write (fd, &cdevhdr, CCKDDASD_DEVHDR_SIZE); close (fd); return 0; } hercules-3.07/cckdswap.c000644 000765 000765 00000014443 11143760542 016717 0ustar00jmaynardjmaynard000000 000000 /* CCKDSWAP.C (c) Copyright Roger Bowler, 1999-2009 */ /* Swap the `endianess' of a compressed CKD file. */ // $Id: cckdswap.c 5125 2009-01-23 12:01:44Z bernard $ /*-------------------------------------------------------------------*/ /* This module changes the `endianess' of a compressed CKD file. */ /*-------------------------------------------------------------------*/ // $Log$ // Revision 1.22 2008/11/04 04:50:45 fish // Ensure consistent utility startup // // Revision 1.21 2007/06/23 00:04:03 ivan // Update copyright notices to include current year (2007) // // Revision 1.20 2006/12/08 09:43:17 jj // Add CVS message log // #include "hstdinc.h" #include "hercules.h" /*-------------------------------------------------------------------*/ /* Swap the `endianess' of cckd file */ /*-------------------------------------------------------------------*/ int syntax (); int main ( int argc, char *argv[]) { CKDDASD_DEVHDR devhdr; /* CKD device header */ CCKDDASD_DEVHDR cdevhdr; /* Compressed CKD device hdr */ int level = 0; /* Chkdsk level */ int force = 0; /* 1=swap if OPENED bit on */ int rc; /* Return code */ int i; /* Index */ int bigend; /* 1=big-endian file */ DEVBLK devblk; /* DEVBLK */ DEVBLK *dev=&devblk; /* -> DEVBLK */ INITIALIZE_UTILITY("cckdswap"); /* parse the arguments */ for (argc--, argv++ ; argc > 0 ; argc--, argv++) { if(**argv != '-') break; switch(argv[0][1]) { case '0': case '1': case '2': case '3': if (argv[0][2] != '\0') return syntax (); level = (argv[0][1] & 0xf); break; case 'f': if (argv[0][2] != '\0') return syntax (); force = 1; break; case 'v': if (argv[0][2] != '\0') return syntax (); display_version (stderr, "Hercules cckd swap program ", FALSE); return 0; default: return syntax (); } } if (argc < 1) return syntax (); for (i = 0; i < argc; i++) { memset (dev, 0, sizeof (DEVBLK)); dev->batch = 1; /* open the input file */ hostpath(dev->filename, argv[i], sizeof(dev->filename)); dev->fd = open (dev->filename, O_RDWR|O_BINARY); if (dev->fd < 0) { cckdumsg (dev, 700, "open error: %s\n", strerror(errno)); continue; } /* read the CKD device header */ if ((rc = read (dev->fd, &devhdr, CKDDASD_DEVHDR_SIZE)) < CKDDASD_DEVHDR_SIZE) { cckdumsg (dev, 703, "read error rc=%d offset 0x%" I64_FMT "x len %d: %s\n", rc, (long long)0, CKDDASD_DEVHDR_SIZE, rc < 0 ? strerror(errno) : "incomplete"); close (dev->fd); continue; } if (memcmp(devhdr.devid, "CKD_C370", 8) != 0 && memcmp(devhdr.devid, "CKD_S370", 8) != 0 && memcmp(devhdr.devid, "FBA_C370", 8) != 0 && memcmp(devhdr.devid, "FBA_S370", 8) != 0) { cckdumsg (dev, 999, "not a compressed dasd file\n"); close (dev->fd); continue; } /* read the compressed CKD device header */ if ((rc = read (dev->fd, &cdevhdr, CCKD_DEVHDR_SIZE)) < CCKD_DEVHDR_SIZE) { cckdumsg (dev, 703, "read error rc=%d offset 0x%" I64_FMT "x len %d: %s\n", rc, (long long)CCKD_DEVHDR_POS, CCKD_DEVHDR_SIZE, rc < 0 ? strerror(errno) : "incomplete"); close (dev->fd); continue; } /* Check the OPENED bit */ if (!force && (cdevhdr.options & CCKD_OPENED)) { cckdumsg (dev, 707, "OPENED bit is on, use -f\n"); close (dev->fd); continue; } /* get the byte order of the file */ bigend = (cdevhdr.options & CCKD_BIGENDIAN); /* call chkdsk */ if (cckd_chkdsk (dev, level) < 0) { cckdumsg (dev, 708, "chkdsk errors\n"); close (dev->fd); continue; } /* re-read the compressed CKD device header */ if (lseek (dev->fd, CCKD_DEVHDR_POS, SEEK_SET) < 0) { cckdumsg (dev, 702, "lseek error offset 0x%" I64_FMT "x: %s\n", (long long)CCKD_DEVHDR_POS, strerror(errno)); close (dev->fd); continue; } if ((rc = read (dev->fd, &cdevhdr, CCKD_DEVHDR_SIZE)) < CCKD_DEVHDR_SIZE) { cckdumsg (dev, 703, "read error rc=%d offset 0x%" I64_FMT "x len %d: %s\n", rc, (long long)CCKD_DEVHDR_POS, CCKD_DEVHDR_SIZE, rc < 0 ? strerror(errno) : "incomplete"); close (dev->fd); continue; } /* swap the byte order of the file if chkdsk didn't do it for us */ if (bigend == (cdevhdr.options & CCKD_BIGENDIAN)) { cckdumsg (dev, 101, "converting to %s\n", bigend ? "litle-endian" : "big-endian"); if (cckd_swapend (dev) < 0) cckdumsg (dev, 910, "error during swap\n"); } close (dev->fd); } /* for each arg */ return 0; } /* end main */ int syntax () { fprintf (stderr, "\ncckdswap [-v] [-f] file1 [file2 ... ]\n" "\n" " -v display version and exit\n" "\n" " -f force check even if OPENED bit is on\n" "\n" " chkdsk level is a digit 0 - 3:\n" " -0 -- minimal checking\n" " -1 -- normal checking\n" " -2 -- intermediate checking\n" " -3 -- maximal checking\n" " default 0\n" "\n"); return -1; } /* end function syntax */ hercules-3.07/cckdutil.c000644 000765 000765 00000301426 11143760542 016722 0ustar00jmaynardjmaynard000000 000000 /* CCKDUTIL.C (c) Copyright Roger Bowler, 1999-2009 */ /* ESA/390 Compressed CKD Common routines */ // $Id: cckdutil.c 5125 2009-01-23 12:01:44Z bernard $ /*-------------------------------------------------------------------*/ /* This module contains functions for compressed CKD devices */ /* used by more than 1 main program. */ /*-------------------------------------------------------------------*/ // $Log$ // Revision 1.57 2008/09/04 22:03:15 gsmith // Fix 64-bit length problem in cdsk_valid_trk - Tony Harminc // // Revision 1.56 2007/12/01 23:31:57 fish // Fix cckdcdsk/cckdcomp/cckdutil no message o/p issue // // Revision 1.55 2007/08/28 20:22:41 gsmith // cckdutil fix for 64-bit - zhackules // // Revision 1.54 2007/06/23 00:04:03 ivan // Update copyright notices to include current year (2007) // // Revision 1.53 2006/12/08 09:43:17 jj // Add CVS message log // #include "hstdinc.h" #define _CCKDUTIL_C_ #define _HDASD_DLL_ #include "hercules.h" #include "opcode.h" /*-------------------------------------------------------------------*/ typedef struct _SPCTAB { /* Space table */ BYTE typ; /* Type of space */ int val; /* Value for space */ U32 pos; /* Space offset */ U32 len; /* Space length */ U32 siz; /* Space size */ } SPCTAB; #define SPCTAB_NONE 0 /* Ignore this space entry */ #define SPCTAB_DEVHDR 1 /* Space is device header */ #define SPCTAB_CDEVHDR 2 /* Space is compressed hdr */ #define SPCTAB_L1 3 /* Space is level 1 table */ #define SPCTAB_L2 4 /* Space is level 2 table */ #define SPCTAB_TRK 5 /* Space is track image */ #define SPCTAB_BLKGRP 6 /* Space is blkgrp image */ #define SPCTAB_FREE 7 /* Space is free block */ #define SPCTAB_EOF 8 /* Space is end-of-file */ /*-------------------------------------------------------------------*/ /* Internal functions */ /*-------------------------------------------------------------------*/ static int comp_spctab_sort(const void *a, const void *b); static int cdsk_spctab_sort(const void *a, const void *b); static int cdsk_build_free_space(SPCTAB *spctab, int s); static int cdsk_valid_trk (int trk, BYTE *buf, int heads, int len); /*-------------------------------------------------------------------*/ /* Static data areas */ /*-------------------------------------------------------------------*/ static BYTE eighthexFF[] = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}; static char *spaces[] = { "none", "devhdr", "cdevhdr", "l1", "l2", "trk", "blkgrp", "free", "eof" }; static char *comps[] = { "none", "zlib", "bzip2" }; /*-------------------------------------------------------------------*/ /* Change the endianess of a compressed file */ /*-------------------------------------------------------------------*/ DLL_EXPORT int cckd_swapend (DEVBLK *dev) { CCKDDASD_EXT *cckd; /* -> cckd extension */ int fd; /* File descriptor */ int rc; /* Return code */ struct stat fst; /* File status buffer */ int i; /* Index */ int swapend; /* 1=swap space */ int len; /* Length */ off_t off, lopos, hipos; /* File offsets */ CCKD_DEVHDR cdevhdr; /* Compressed ckd header */ CCKD_L1ENT *l1 = NULL; /* Level 1 table */ CCKD_L2ENT l2[256]; /* Level 2 table */ CCKD_FREEBLK freeblk; /* Free block */ /* Get fd */ cckd = dev->cckd_ext; if (cckd == NULL) fd = dev->fd; else fd = cckd->fd[cckd->sfn]; /* Get file size */ if (fstat (fd, &fst) < 0) goto cswp_fstat_error; hipos = fst.st_size; /* Device header */ off = CCKD_DEVHDR_POS; if (lseek (fd, off, SEEK_SET) < 0) goto cswp_lseek_error; len = CCKD_DEVHDR_SIZE; if ((rc = read (fd, &cdevhdr, len)) != len) goto cswp_read_error; swapend = (cdevhdr.options & CCKD_BIGENDIAN) != cckd_endian(); cckd_swapend_chdr (&cdevhdr); cdevhdr.options |= CCKD_ORDWR; if (lseek (fd, off, SEEK_SET) < 0) goto cswp_lseek_error; if ((rc = write (fd, &cdevhdr, len)) != len) goto cswp_write_error; if (!swapend) cckd_swapend_chdr (&cdevhdr); /* l1 table */ len = cdevhdr.numl1tab * CCKD_L1ENT_SIZE; if ((l1 = malloc (len)) == NULL) goto cswp_malloc_error; off = CCKD_L1TAB_POS; if (lseek (fd, off, SEEK_SET) < 0) goto cswp_lseek_error; if ((rc = read (fd, l1, len)) != len) goto cswp_read_error; cckd_swapend_l1 (l1, (int)cdevhdr.numl1tab); if (lseek (fd, off, SEEK_SET) < 0) goto cswp_lseek_error; if ((rc = write (fd, l1, len)) != len) goto cswp_write_error; if (!swapend) cckd_swapend_l1 (l1, (int)cdevhdr.numl1tab); lopos = CCKD_L1TAB_POS + len; /* l2 tables */ for (i = 0; i < cdevhdr.numl1tab; i++) { if (l1[i] == 0 || l1[i] == 0xffffffff || l1[i] < lopos || l1[i] > hipos - CCKD_L2TAB_SIZE) continue; off = (off_t)l1[i]; if (lseek (fd, off, SEEK_SET) < 0) goto cswp_lseek_error; len = CCKD_L2TAB_SIZE; if ((rc = read (fd, l2, len)) != len) goto cswp_read_error; cckd_swapend_l2 (l2); if (lseek (fd, off, SEEK_SET) < 0) goto cswp_lseek_error; if ((rc = write (fd, l2, len)) != len) goto cswp_write_error; } free (l1); l1 = NULL; /* free space */ if (cdevhdr.free && cdevhdr.free >= lopos && cdevhdr.free <= hipos - CCKD_FREEBLK_SIZE) { off = (off_t)cdevhdr.free; if (lseek (fd, off, SEEK_SET) < 0) goto cswp_lseek_error; len = CCKD_FREEBLK_SIZE; if ((rc = read (fd, &freeblk, len)) != len) goto cswp_read_error; if (memcmp(&freeblk, "FREE_BLK", 8) == 0) { /* New format free space */ for (i = 0; i < cdevhdr.free_number; i++) { off += CCKD_FREEBLK_SIZE; if (off > hipos - CCKD_FREEBLK_SIZE) break; if (lseek (fd, off, SEEK_SET) < 0) goto cswp_lseek_error; if ((rc = read (fd, &freeblk, len)) != len) goto cswp_read_error; cckd_swapend_free (&freeblk); if (lseek (fd, off, SEEK_SET) < 0) goto cswp_lseek_error; if ((rc = write (fd, &freeblk, len)) != len) goto cswp_write_error; } /* for each free space */ } /* if new format free space */ else { /* Old format free space */ for (i = 0; i < cdevhdr.free_number; i++) { if (off < lopos || off > hipos - CCKD_FREEBLK_SIZE) break; if (lseek (fd, off, SEEK_SET) < 0) goto cswp_lseek_error; if ((rc = read (fd, &freeblk, len)) != len) goto cswp_read_error; cckd_swapend_free (&freeblk); if (lseek (fd, off, SEEK_SET) < 0) goto cswp_lseek_error; if ((rc = write (fd, &freeblk, len)) != len) goto cswp_write_error; if (!swapend) cckd_swapend_free (&freeblk); off = (off_t)freeblk.pos; } /* for each free space */ } /* else old format free space */ } /* if free space */ return 0; /* error exits */ cswp_fstat_error: cckdumsg (dev, 701, "fstat error: %s\n", strerror(errno)); goto cswp_error; cswp_lseek_error: cckdumsg (dev, 702, "lseek error, offset 0x%" I64_FMT "x: %s\n", (long long)off, strerror(errno)); goto cswp_error; cswp_read_error: cckdumsg (dev, 703, "read error rc=%d, offset 0x%" I64_FMT "x len %d: %s\n", rc, (long long)off, len, rc < 0 ? strerror(errno) : "incomplete"); goto cswp_error; cswp_write_error: cckdumsg (dev, 704, "write error rc=%d, offset 0x%" I64_FMT "x len %d: %s\n", rc, (long long)off, len, rc < 0 ? strerror(errno) : "incomplete"); goto cswp_error; cswp_malloc_error: cckdumsg (dev, 705, "malloc error, size %d: %s\n", len, strerror(errno)); goto cswp_error; cswp_error: if (l1) free(l1); return -1; } /*-------------------------------------------------------------------*/ /* Swap endian - compressed device header */ /*-------------------------------------------------------------------*/ DLL_EXPORT void cckd_swapend_chdr (CCKD_DEVHDR *cdevhdr) { /* fix the compressed ckd header */ cdevhdr->options ^= CCKD_BIGENDIAN; cckd_swapend4 ((char *) &cdevhdr->numl1tab); cckd_swapend4 ((char *) &cdevhdr->numl2tab); cckd_swapend4 ((char *) &cdevhdr->size); cckd_swapend4 ((char *) &cdevhdr->used); cckd_swapend4 ((char *) &cdevhdr->free); cckd_swapend4 ((char *) &cdevhdr->free_total); cckd_swapend4 ((char *) &cdevhdr->free_largest); cckd_swapend4 ((char *) &cdevhdr->free_number); cckd_swapend4 ((char *) &cdevhdr->free_imbed); cckd_swapend2 ((char *) &cdevhdr->compress_parm); } /*-------------------------------------------------------------------*/ /* Swap endian - level 1 table */ /*-------------------------------------------------------------------*/ DLL_EXPORT void cckd_swapend_l1 (CCKD_L1ENT *l1, int n) { int i; /* Index */ for (i = 0; i < n; i++) cckd_swapend4 ((char *) &l1[i]); } /*-------------------------------------------------------------------*/ /* Swap endian - level 2 table */ /*-------------------------------------------------------------------*/ DLL_EXPORT void cckd_swapend_l2 (CCKD_L2ENT *l2) { int i; /* Index */ for (i = 0; i < 256; i++) { cckd_swapend4 ((char *) &l2[i].pos); cckd_swapend2 ((char *) &l2[i].len); cckd_swapend2 ((char *) &l2[i].size); } } /*-------------------------------------------------------------------*/ /* Swap endian - free space entry */ /*-------------------------------------------------------------------*/ DLL_EXPORT void cckd_swapend_free (CCKD_FREEBLK *fb) { cckd_swapend4 ((char *) &fb->pos); cckd_swapend4 ((char *) &fb->len); } /*-------------------------------------------------------------------*/ /* Swap endian - 4 bytes */ /*-------------------------------------------------------------------*/ DLL_EXPORT void cckd_swapend4 (char *c) { char temp[4]; memcpy (&temp, c, 4); c[0] = temp[3]; c[1] = temp[2]; c[2] = temp[1]; c[3] = temp[0]; } /*-------------------------------------------------------------------*/ /* Swap endian - 2 bytes */ /*-------------------------------------------------------------------*/ DLL_EXPORT void cckd_swapend2 (char *c) { char temp[2]; memcpy (&temp, c, 2); c[0] = temp[1]; c[1] = temp[0]; } /*-------------------------------------------------------------------*/ /* Are we little or big endian? From Harbison&Steele. */ /*-------------------------------------------------------------------*/ DLL_EXPORT int cckd_endian() { union { long l; char c[sizeof (long)]; } u; u.l = 1; return u.c[sizeof (long) - 1] == 1 ? CCKD_BIGENDIAN : 0; } /*------------------------------------------------------------------- * Remove all free space from a compressed ckd file *-------------------------------------------------------------------*/ DLL_EXPORT int cckd_comp (DEVBLK *dev) { CCKDDASD_EXT *cckd; /* -> cckd extension */ int fd; /* File descriptor */ struct stat fst; /* File status buffer */ long long maxsize; /* Max cckd file size */ int rc; /* Return code */ off_t off; /* File offset */ off_t l2area; /* Boundary for l2 tables */ int len; /* Length */ int i, j, l, n; /* Work variables */ int relocate = 0; /* 1=spaces will be relocated*/ int l1size; /* l1 table size */ U32 next; /* offset of next space */ int s; /* space table index */ CKDDASD_DEVHDR devhdr; /* CKD device header */ CCKD_DEVHDR cdevhdr; /* CCKD device header */ CCKD_L1ENT *l1=NULL; /* -> l1 table */ CCKD_L2ENT **l2=NULL; /* -> l2 table array */ SPCTAB *spctab=NULL; /* -> space table */ BYTE *rbuf=NULL; /* Relocation buffer */ BYTE *p; /* -> relocation buffer */ int rlen=0; /* Relocation buffer length */ CCKD_L2ENT zero_l2[256]; /* Empty l2 table (zeros) */ CCKD_L2ENT ff_l2[256]; /* Empty l2 table (0xff's) */ BYTE buf[65536*4]; /* Buffer */ /*--------------------------------------------------------------- * Get fd *---------------------------------------------------------------*/ cckd = dev->cckd_ext; if (cckd == NULL) fd = dev->fd; else fd = cckd->fd[cckd->sfn]; /*--------------------------------------------------------------- * Get file statistics *---------------------------------------------------------------*/ if (fstat (fd, &fst) < 0) goto comp_fstat_error; maxsize = sizeof(off_t) == 4 ? 0x7fffffffll : 0xffffffffll; /*--------------------------------------------------------------- * Read device header *---------------------------------------------------------------*/ off = 0; if (lseek (fd, off, SEEK_SET) < 0) goto comp_lseek_error; len = CKDDASD_DEVHDR_SIZE; if ((rc = read (fd, &devhdr, len)) != len) goto comp_read_error; if (memcmp (devhdr.devid, "CKD_C370", 8) != 0 && memcmp (devhdr.devid, "CKD_S370", 8) != 0 && memcmp (devhdr.devid, "FBA_C370", 8) != 0 && memcmp (devhdr.devid, "FBA_S370", 8) != 0) { cckdumsg (dev, 999, "not a compressed dasd file\n"); goto comp_error; } comp_restart: /*--------------------------------------------------------------- * Read compressed device header *---------------------------------------------------------------*/ off = CCKD_DEVHDR_POS; if (lseek (fd, off, SEEK_SET) < 0) goto comp_lseek_error; len = CCKD_DEVHDR_SIZE; if ((rc = read (fd, &cdevhdr, len)) != len) goto comp_read_error; /*--------------------------------------------------------------- * Check the endianess of the file *---------------------------------------------------------------*/ if ((cdevhdr.options & CCKD_BIGENDIAN) != cckd_endian()) { cckdumsg (dev, 101, "converting to %s\n", cckd_endian() ? "big-endian" : "little-endian"); if (cckd_swapend (dev) < 0) goto comp_error; else goto comp_restart; } /*--------------------------------------------------------------- * Some header checks *---------------------------------------------------------------*/ if ((off_t)cdevhdr.size != fst.st_size || cdevhdr.size != cdevhdr.used || cdevhdr.free != 0 || cdevhdr.free_total != 0 || cdevhdr.free_largest != 0 || cdevhdr.free_number != 0 || cdevhdr.free_imbed != 0) relocate = 1; /*--------------------------------------------------------------- * Build empty l2 tables *---------------------------------------------------------------*/ memset (&zero_l2, 0, CCKD_L2TAB_SIZE); if (cdevhdr.nullfmt != 0) for (i = 0; i < 256; i++) zero_l2[i].len = zero_l2[i].size = cdevhdr.nullfmt; memset (&ff_l2, 0xff, CCKD_L2TAB_SIZE); /*--------------------------------------------------------------- * Read the l1 table *---------------------------------------------------------------*/ l1size = len = cdevhdr.numl1tab * CCKD_L1ENT_SIZE; if ((l1 = malloc (len)) == NULL) goto comp_malloc_error; off = CCKD_L1TAB_POS; if (lseek (fd, off, SEEK_SET) < 0) goto comp_lseek_error; if ((rc = read (fd, l1, len)) != len) goto comp_read_error; /*--------------------------------------------------------------- * Build the space table *---------------------------------------------------------------*/ n = 1 + 1 + 1 + cdevhdr.numl1tab + 1; for (i = 0; i < cdevhdr.numl1tab; i++) if (l1[i] != 0 && l1[i] != 0xffffffff) n += 256; len = sizeof(SPCTAB); if ((spctab = calloc (n, len)) == NULL) goto comp_calloc_error; s = 0; spctab[s].typ = SPCTAB_DEVHDR; spctab[s].val = -1; spctab[s].pos = 0; spctab[s].len = spctab[s].siz = CKDDASD_DEVHDR_SIZE; s++; spctab[s].typ = SPCTAB_CDEVHDR; spctab[s].val = -1; spctab[s].pos = CCKD_DEVHDR_POS; spctab[s].len = spctab[s].siz = CCKD_DEVHDR_SIZE; s++; spctab[s].typ = SPCTAB_L1; spctab[s].val = -1; spctab[s].pos = CCKD_L1TAB_POS; spctab[s].len = spctab[s].siz = l1size; s++; spctab[s].typ = SPCTAB_EOF; spctab[s].val = -1; spctab[s].pos = fst.st_size; spctab[s].len = spctab[s].siz = 0; s++; for (i = 0; i < cdevhdr.numl1tab; i++) if (l1[i] != 0 && l1[i] != 0xffffffff) { spctab[s].typ = SPCTAB_L2; spctab[s].val = i; spctab[s].pos = l1[i]; spctab[s].len = spctab[s].siz = CCKD_L2TAB_SIZE; s++; } qsort (spctab, s, sizeof(SPCTAB), comp_spctab_sort); /*--------------------------------------------------------------- * Read level 2 tables *---------------------------------------------------------------*/ n = cdevhdr.numl1tab; len = sizeof (void *); if ((l2 = calloc (n, len)) == NULL) goto comp_calloc_error; for (i = 0; spctab[i].typ != SPCTAB_EOF; i++) { if (spctab[i].typ != SPCTAB_L2) continue; l = spctab[i].val; len = CCKD_L2TAB_SIZE; if ((l2[l] = malloc (len)) == NULL) goto comp_malloc_error; off = (off_t)spctab[i].pos; if (lseek (fd, off, SEEK_SET) < 0) goto comp_lseek_error; if ((rc = read (fd, l2[l], len)) != len) goto comp_read_error; for (j = 0; j < 256; j++) { if (l2[l][j].pos == 0 || l2[l][j].pos == 0xffffffff) continue; spctab[s].typ = SPCTAB_TRK; spctab[s].val = spctab[i].val*256 + j; spctab[s].pos = l2[l][j].pos; spctab[s].len = l2[l][j].len; spctab[s].siz = l2[l][j].size; s++; } /* for each l2 entry */ /* check if empty l2 table */ if (memcmp (l2[l], &zero_l2, CCKD_L2TAB_SIZE) == 0 || memcmp (l2[l], &ff_l2, CCKD_L2TAB_SIZE) == 0) { l1[l] = l2[l][0].pos; /* 0x00000000 or 0xffffffff */ spctab[i].typ = SPCTAB_NONE; free (l2[l]); l2[l] = NULL; relocate = 1; } } /* for each space */ qsort (spctab, s, sizeof(SPCTAB), comp_spctab_sort); while (spctab[s-1].typ == SPCTAB_NONE) s--; /* set relocate flag if last space is free space */ if (spctab[s-2].pos + spctab[s-2].len != spctab[s-1].pos) relocate = 1; /*--------------------------------------------------------------- * relocate l2 tables in order *---------------------------------------------------------------*/ /* determine l2 area */ l2area = CCKD_L1TAB_POS + l1size; for (i = 0; i < cdevhdr.numl1tab; i++) { if (l1[i] == 0 || l1[i] == 0xffffffff) continue; if (l1[i] != l2area) relocate = 1; l2area += CCKD_L2TAB_SIZE; } /* quick return if all l2 tables are orderered and no free space */ if (!relocate) { for (i = 1; spctab[i].typ != SPCTAB_EOF; i++) if (spctab[i-1].pos + spctab[i-1].len != spctab[i].pos) break; if (spctab[i].typ == SPCTAB_EOF) { cckdumsg (dev, 103, "file already compressed\n"); goto comp_return_ok; } } /* file will be updated */ cdevhdr.options |= CCKD_ORDWR; /* calculate track size within the l2 area */ for (i = rlen = 0; spctab[i].pos < l2area; i++) if (spctab[i].typ == SPCTAB_TRK) rlen += sizeof(spctab[i].val) + sizeof(spctab[i].len) + spctab[i].len; /* read any tracks in the l2area into rbuf */ if ((len = rlen) > 0) { if ((rbuf = malloc (len)) == NULL) goto comp_malloc_error; for (i = 0, p = rbuf; spctab[i].pos < l2area; i++) { if (spctab[i].typ != SPCTAB_TRK) continue; memcpy (p, &spctab[i].val, sizeof(spctab[i].val)); p += sizeof(spctab[i].val); memcpy (p, &spctab[i].len, sizeof(spctab[i].len)); p += sizeof(spctab[i].len); off = (off_t)spctab[i].pos; if (lseek (fd, off, SEEK_SET) < 0) goto comp_lseek_error; len = spctab[i].len; if ((rc = read (fd, p, len)) != len) goto comp_read_error; p += len; spctab[i].typ = SPCTAB_NONE; } /* for each space in the l2 area */ qsort (spctab, s, sizeof(SPCTAB), comp_spctab_sort); while (spctab[s-1].typ == SPCTAB_NONE) s--; } /* if any tracks to relocate */ /* remove all l2 tables from the space table */ for (i = 0; spctab[i].typ != SPCTAB_EOF; i++) if (spctab[i].typ == SPCTAB_L2) spctab[i].typ = SPCTAB_NONE; qsort (spctab, s, sizeof(SPCTAB), comp_spctab_sort); while (spctab[s-1].typ == SPCTAB_NONE) s--; /* add all l2 tables at their ordered offsets */ off = CCKD_L1TAB_POS + l1size; for (i = 0; i < cdevhdr.numl1tab; i++) { if (l1[i] == 0 || l1[i] == 0xffffffff) continue; spctab[s].typ = SPCTAB_L2; spctab[s].val = i; spctab[s].pos = (U32)off; spctab[s].len = spctab[s].siz = CCKD_L2TAB_SIZE; s++; off += CCKD_L2TAB_SIZE; } qsort (spctab, s, sizeof(SPCTAB), comp_spctab_sort); /* set end-of-file position */ spctab[s-1].pos = spctab[s-2].pos + spctab[s-2].len; /*--------------------------------------------------------------- * Perform compression *---------------------------------------------------------------*/ /* move spaces left */ for (i = 0; spctab[i].typ != SPCTAB_EOF; i++) { /* ignore contiguous spaces */ if (spctab[i].pos + spctab[i].len == spctab[i+1].pos) continue; /* found a gap */ off = (off_t)spctab[i+1].pos; /* figure out how much we can read */ for (len = 0, j = i + 1; spctab[j].typ != SPCTAB_EOF; j++) { if (len + spctab[j].len > sizeof(buf)) break; next = spctab[j].pos + spctab[j].len; spctab[j].pos = spctab[i].pos + spctab[i].len + len; spctab[j].siz = spctab[j].len; len += spctab[j].len; if (next != spctab[j+1].pos) break; } /* search for contiguous spaces */ /* this can happen if the next space is end-of-file */ if (len == 0) continue; /* read the image(s) to be relocated */ if (lseek (fd, off, SEEK_SET) < 0) goto comp_lseek_error; if ((rc = read (fd, buf, len)) != len) goto comp_write_error; /* write the images */ off = (off_t)spctab[i].pos + spctab[i].len; if (lseek (fd, off, SEEK_SET) < 0) goto comp_lseek_error; if ((rc = write (fd, buf, len)) != len) goto comp_write_error; } /* adjust the size of the file */ spctab[s-1].pos = spctab[s-2].pos + spctab[s-2].len; /*--------------------------------------------------------------- * Write spaces relocated from the l2area to the end of the file *---------------------------------------------------------------*/ off = (off_t)spctab[s-1].pos; p = rbuf; while (rlen) { spctab[s].typ = SPCTAB_TRK; spctab[s].pos = (U32)off; memcpy (&spctab[s].val, p, sizeof(spctab[s].val)); p += sizeof(spctab[s].val); memcpy (&spctab[s].len, p, sizeof(spctab[s].len)); spctab[s].siz = spctab[s].len; p += sizeof(spctab[s].len); if (lseek (fd, off, SEEK_SET) < 0) goto comp_lseek_error; len = spctab[s].len; if ((rc = write (fd, p, len)) != len) goto comp_write_error; p += len; off += len; rlen -= len + sizeof(spctab[s].val) + sizeof(spctab[s].len); s++; } /* for each relocated space in l2area */ /* adjust the space table */ if (rbuf) { free (rbuf); rbuf = NULL; qsort (spctab, s, sizeof(SPCTAB), comp_spctab_sort); spctab[s-1].pos = spctab[s-2].pos + spctab[s-2].len; } /*--------------------------------------------------------------- * Update the device header *---------------------------------------------------------------*/ cdevhdr.size = cdevhdr.used = spctab[s-1].pos; cdevhdr.free = cdevhdr.free_total = cdevhdr.free_largest = cdevhdr.free_number = cdevhdr.free_imbed = 0; cdevhdr.vrm[0] = CCKD_VERSION; cdevhdr.vrm[1] = CCKD_RELEASE; cdevhdr.vrm[2] = CCKD_MODLVL; /*--------------------------------------------------------------- * Update the lookup tables *---------------------------------------------------------------*/ for (i = 0; spctab[i].typ != SPCTAB_EOF; i++) if (spctab[i].typ == SPCTAB_L2) l1[spctab[i].val] = spctab[i].pos; else if (spctab[i].typ == SPCTAB_TRK) { l = spctab[i].val / 256; j = spctab[i].val % 256; l2[l][j].pos = spctab[i].pos; l2[l][j].len = l2[l][j].size = spctab[i].len; } /*--------------------------------------------------------------- * Write the cdevhdr, l1 table and l2 tables *---------------------------------------------------------------*/ /* write cdevhdr */ off = CCKD_DEVHDR_POS; if (lseek (fd, off, SEEK_SET) < 0) goto comp_lseek_error; len = CCKD_DEVHDR_SIZE; if ((rc = write (fd, &cdevhdr, len)) != len) goto comp_write_error; /* write l1 table */ off = CCKD_L1TAB_POS; if (lseek (fd, off, SEEK_SET) < 0) goto comp_lseek_error; len = l1size; if ((rc = write (fd, l1, len)) != len) goto comp_write_error; /* write l2 tables */ for (i = 0; i < cdevhdr.numl1tab; i++) if (l1[i] != 0 && l1[i] != 0xffffffff) { off = (off_t)l1[i]; if (lseek (fd, off, SEEK_SET) < 0) goto comp_lseek_error; len = CCKD_L2TAB_SIZE; if ((rc = write (fd, l2[i], len)) != len) goto comp_lseek_error; } /* truncate the file */ off = (off_t)spctab[s-1].pos; if (off < fst.st_size) { ftruncate (fd, off); cckdumsg (dev, 102, "compress successful, %lld bytes released\n", (long long)fst.st_size - off); } else cckdumsg (dev, 102, "compress successful, L2 tables relocated\n"); /*--------------------------------------------------------------- * Return *---------------------------------------------------------------*/ comp_return_ok: rc = 0; comp_return: if (rbuf) free(rbuf); if (l2) { for (i = 0; i < cdevhdr.numl1tab; i++) if (l2[i]) free (l2[i]); free (l2); } if (l1) free (l1); if (spctab) free (spctab); return rc; /*--------------------------------------------------------------- * Error exits *---------------------------------------------------------------*/ comp_fstat_error: cckdumsg (dev, 701, "fstat error: %s\n", strerror(errno)); goto comp_error; comp_lseek_error: cckdumsg (dev, 702, "lseek error, offset 0x%" I64_FMT "x: %s\n", (long long)off, strerror(errno)); goto comp_error; comp_read_error: cckdumsg (dev, 703, "read error rc=%d, offset 0x%" I64_FMT "x len %d: %s\n", rc, (long long)off, len, rc < 0 ? strerror(errno) : "incomplete"); goto comp_error; comp_write_error: cckdumsg (dev, 704, "write error rc=%d, offset 0x%" I64_FMT "x len %d: %s\n", rc, (long long)off, len, rc < 0 ? strerror(errno) : "incomplete"); goto comp_error; comp_malloc_error: cckdumsg (dev, 705, "malloc error, size %d: %s\n", len, strerror(errno)); goto comp_error; comp_calloc_error: cckdumsg (dev, 706, "calloc error, size %d: %s\n", n*len, strerror(errno)); goto comp_error; comp_error: rc = -1; goto comp_return; } /* cckd_comp() */ /*------------------------------------------------------------------- * cckd_comp() space table sort *-------------------------------------------------------------------*/ static int comp_spctab_sort(const void *a, const void *b) { const SPCTAB *x = a, *y = b; if (x->typ == SPCTAB_NONE) return 1; else if (y->typ == SPCTAB_NONE) return -1; else if (x->typ == SPCTAB_EOF) return 1; else if (y->typ == SPCTAB_EOF) return -1; else if (x->pos < y->pos) return -1; else return 1; } /*------------------------------------------------------------------- * Perform check function on a compressed ckd file * * check levels * -1 devhdr, cdevhdr, l1 table * 0 devhdr, cdevhdr, l1 table, l2 tables * 1 devhdr, cdevhdr, l1 table, l2 tables, free spaces * 2 devhdr, cdevhdr, l1 table, l2 tables, free spaces, trkhdrs * 3 devhdr, cdevhdr, l1 table, l2 tables, free spaces, trkimgs * 4 devhdr, cdevhdr. Build everything else from recovery *-------------------------------------------------------------------*/ DLL_EXPORT int cckd_chkdsk(DEVBLK *dev, int level) { CCKDDASD_EXT *cckd; /* -> ckd extension */ int fd; /* file descriptor */ struct stat fst; /* file status information */ int fdflags; /* file descriptor flags */ long long maxsize; /* max cckd file size */ int ro; /* 1=file opened read-only */ int f, i, j, l, n; /* work integers */ int l1x, l2x; /* l1, l2 table indexes */ BYTE compmask[256]; /* compression byte mask 00 - supported 0x - valid, not supported ff - invalid */ off_t off; /* file offset */ int len; /* length to read */ int rc; /* function return code */ int comp; /* trkhdr compression byte[0]*/ int cyl; /* trkhdr cyl bytes[1-2]*/ int head; /* trkhdr head bytes[3-4]*/ int trk; /* trkhdr calculated trk */ int cyls; /* number cylinders */ int heads; /* number heads/cylinder */ int trks; /* number tracks */ unsigned int trksz; /* track size */ int blks; /* number fba blocks */ int blkgrp; /* current block group nbr */ int blkgrps; /* number fba block groups */ unsigned int blkgrpsz; /* fba block group size */ int trktyp; /* track type (TRK, BLKGRP) */ int ckddasd=0; /* 1=ckd */ int fbadasd=0; /* 1= fba */ int shadow=0; /* 0xff=shadow file */ int hdrerr=0; /* non-zero: header errors */ int fsperr=0; /* 1=rebuild free space */ int comperrs=0; /* 1=unsupported comp found */ int recovery=0; /* 1=perform track recovery */ int valid; /* 1=valid trk recovered */ int l1size; /* size of l1 table */ int swapend=0; /* 1=call cckd_swapend */ U32 lopos, hipos; /* low/high file positions */ int pass; /* recovery pass number (fba)*/ int s; /* space table index */ SPCTAB *spctab=NULL; /* -> space table */ BYTE *l2errs=NULL; /* l2 error table */ BYTE *rcvtab=NULL; /* recovered tracks */ CKDDASD_DEVHDR devhdr; /* device header */ CCKD_DEVHDR cdevhdr; /* compressed device header */ CCKD_DEVHDR cdevhdr2; /* compressed device header 2*/ CCKD_L1ENT *l1=NULL; /* -> level 1 table */ CCKD_L2ENT l2ent; /* level 2 entry */ CCKD_L2ENT l2tab[256]; /* level 2 table */ CCKD_L2ENT **l2=NULL; /* -> level 2 table array */ CCKD_L2ENT empty_l2[256]; /* Empty l2 table */ CCKD_FREEBLK freeblk; /* free block */ CCKD_FREEBLK *fsp=NULL; /* free blocks (new format) */ BYTE buf[4*65536]; /* buffer */ /* Get fd */ cckd = dev->cckd_ext; if (cckd == NULL) fd = dev->fd; else fd = cckd->fd[cckd->sfn]; /* Get some file information */ if ( fstat (fd, &fst) < 0 ) goto cdsk_fstat_error; hipos = fst.st_size; maxsize = sizeof(off_t) == 4 ? 0x7fffffffll : 0xffffffffll; fdflags = get_file_accmode_flags(fd); ro = (fdflags & O_RDWR) == 0; /* Build table for compression byte test */ memset (compmask, 0xff, 256); compmask[0] = 0; #if defined(HAVE_LIBZ) compmask[CCKD_COMPRESS_ZLIB] = 0; #else compmask[CCKD_COMPRESS_ZLIB] = 1; #endif #if defined(CCKD_BZIP2) compmask[CCKD_COMPRESS_BZIP2] = 0; #else compmask[CCKD_COMPRESS_BZIP2] = 2; #endif /*--------------------------------------------------------------- * Header checks *---------------------------------------------------------------*/ /* Read the device header */ off = 0; if ( lseek (fd, off, SEEK_SET) < 0) goto cdsk_lseek_error; len = CKDDASD_DEVHDR_SIZE; if ((rc = read (fd, &devhdr, len)) != len) goto cdsk_read_error; /* Device header checks */ if (memcmp(devhdr.devid, "CKD_C370", 8) == 0 || memcmp(devhdr.devid, "CKD_S370", 8) == 0 ) ckddasd = 1; else if (memcmp(devhdr.devid, "FBA_C370", 8) == 0 || memcmp(devhdr.devid, "FBA_S370", 8) == 0 ) fbadasd = 1; else { cckdumsg (dev, 999, "not a compressed dasd file\n"); goto cdsk_error; } if (memcmp(devhdr.devid, "CKD_S370", 8) == 0 || memcmp(devhdr.devid, "FBA_S370", 8) == 0 ) shadow = 0xff; trktyp = ckddasd ? SPCTAB_TRK : SPCTAB_BLKGRP; /* Read the cckd device header */ off = CCKD_DEVHDR_POS; if ( lseek (fd, off, SEEK_SET) < 0) goto cdsk_lseek_error; len = CCKD_DEVHDR_SIZE; if ((rc = read (fd, &cdevhdr, len)) != len) goto cdsk_read_error; /* Endianess check */ if ((cdevhdr.options & CCKD_BIGENDIAN) != cckd_endian()) { if (!ro) { cckdumsg (dev, 101, "converting to %s\n", cckd_endian() ? "big-endian" : "little-endian"); if (cckd_swapend (dev) < 0) goto cdsk_error; if (level < 0) level = 0; swapend = 0; } else swapend = 1; cckd_swapend_chdr (&cdevhdr); } /* ckd checks */ if (ckddasd) { CKDDEV *ckd; heads = (devhdr.heads[3] << 24) + (devhdr.heads[2] << 16) + (devhdr.heads[1] << 8) + (devhdr.heads[0]); cyls = (cdevhdr.cyls[3] << 24) + (cdevhdr.cyls[2] << 16) + (cdevhdr.cyls[1] << 8) + (cdevhdr.cyls[0]); trks = heads * cyls; trksz = (devhdr.trksize[3] << 24) + (devhdr.trksize[2] << 16) + (devhdr.trksize[1] << 8) + (devhdr.trksize[0]); /* ckd dasd lookup */ ckd = dasd_lookup (DASD_CKDDEV, NULL, devhdr.devtype, cyls); if (ckd == NULL) { cckdumsg (dev, 900, "dasd lookup error type=%2.2X cyls=%d\n", devhdr.devtype, cyls); goto cdsk_error; } /* track size check */ n = sizeof(CKDDASD_TRKHDR) + sizeof(CKDDASD_RECHDR) + 8 /* r0 length */ + sizeof(CKDDASD_RECHDR) + ckd->r1 /* max data length */ + sizeof(eighthexFF); n = ((n+511)/512)*512; if ((int)trksz != n) { cckdumsg (dev, 901, "bad trksize: %d, expecting %d\n", trksz, n); goto cdsk_error; } /* number of heads check */ if (heads != ckd->heads) { cckdumsg (dev, 902, "bad number of heads: %d, expecting %d\n", heads, ckd->heads); goto cdsk_error; } } /* if (ckddasd) */ /* fba checks */ else { /* Note: cyls & heads are setup for ckd type hdr checks */ blks = (cdevhdr.cyls[3] << 24) + (cdevhdr.cyls[2] << 16) + (cdevhdr.cyls[1] << 8) + (cdevhdr.cyls[0]); trks = blks / CFBA_BLOCK_NUM; if (blks % CFBA_BLOCK_NUM) trks++; trksz = CFBA_BLOCK_SIZE + CKDDASD_TRKHDR_SIZE; heads = 65536; cyls = trks / heads; if (trks % heads) cyls++; } /* fba variables */ blkgrps = trks; blkgrpsz = trksz; /* `numl1tab' check */ n = trks / 256; if (trks % 256) n++; if (cdevhdr.numl1tab != n && cdevhdr.numl1tab != n + 1) { cckdumsg (dev, 903, "bad `numl1tab': %d, expecting %d\n", cdevhdr.numl1tab, n); goto cdsk_error; } l1size = cdevhdr.numl1tab * CCKD_L1ENT_SIZE; if (CCKD_L1TAB_POS + l1size > fst.st_size) { cckdumsg (dev, 904, "file too small to contain L1 table: %d, need %d", fst.st_size, CCKD_L1TAB_POS + l1size); goto cdsk_error; } /* check level 2 if SPERRS bit on */ if (!ro && level < 2 && (cdevhdr.options & CCKD_SPERRS)) { level = 2; cckdumsg (dev, 600, "forcing check level %d; space error bit on\n", level); } /* cdevhdr inconsistencies check */ hdrerr = 0; hdrerr |= fst.st_size != (off_t)cdevhdr.size && cdevhdr.size != cdevhdr.free ? 0x0001 : 0; hdrerr |= cdevhdr.size != cdevhdr.used + cdevhdr.free_total ? 0x0002 : 0; hdrerr |= cdevhdr.free_largest > cdevhdr.free_total - cdevhdr.free_imbed ? 0x0004 : 0; hdrerr |= cdevhdr.free == 0 && cdevhdr.free_number != 0 ? 0x0008 : 0; hdrerr |= cdevhdr.free == 0 && cdevhdr.free_total != cdevhdr.free_imbed ? 0x0010 : 0; hdrerr |= cdevhdr.free != 0 && cdevhdr.free_total == 0 ? 0x0020 : 0; hdrerr |= cdevhdr.free != 0 && cdevhdr.free_number == 0 ? 0x0040 : 0; hdrerr |= cdevhdr.free_number == 0 && cdevhdr.free_total != cdevhdr.free_imbed ? 0x0080 : 0; hdrerr |= cdevhdr.free_number != 0 && cdevhdr.free_total <= cdevhdr.free_imbed ? 0x0100 : 0; hdrerr |= cdevhdr.free_imbed > cdevhdr.free_total ? 0x0200 : 0; /* Additional checking if header errors */ if (hdrerr != 0) { cckdumsg (dev, 601, "cdevhdr inconsistencies found, code=%4.4x\n", hdrerr); if (level < 1) { level = 1; cckdumsg (dev, 600, "forcing check level %d\n", level); } } /* Additional checking if not properly closed */ if (level < 1 && (cdevhdr.options & CCKD_OPENED)) { level = 1; cckdumsg (dev, 600, "forcing check level %d; file not closed\n", level); } /* Additional checking if last opened for read/write */ if (level < 0 && (cdevhdr.options & CCKD_ORDWR)) level = 0; /* Set check level -1 */ if (level == 0 && !dev->batch && !hdrerr && (cdevhdr.options & (CCKD_OPENED|CCKD_SPERRS)) == 0 && ((cdevhdr.options & (CCKD_ORDWR)) == 0 || ro)) level = -1; /* Build empty l2 table */ memset (&empty_l2, shadow, CCKD_L2TAB_SIZE); if (shadow == 0 && cdevhdr.nullfmt != 0) for (i = 0; i < 256; i++) empty_l2[i].len = empty_l2[i].size = cdevhdr.nullfmt; /*--------------------------------------------------------------- * read the level 1 table *---------------------------------------------------------------*/ len = l1size; if ((l1 = malloc (len)) == NULL) goto cdsk_error; off = CCKD_L1TAB_POS; if ( lseek (fd, off, SEEK_SET) < 0) goto cdsk_lseek_error; if ((rc = read (fd, l1, len)) != len) goto cdsk_read_error; if (swapend) cckd_swapend_l1 (l1, (int)cdevhdr.numl1tab); lopos = CCKD_L1TAB_POS + l1size; /*--------------------------------------------------------------- * initialize the space table *---------------------------------------------------------------*/ /* find number of non-null l1 entries */ for (i = n = 0; i < cdevhdr.numl1tab; i++) if (l1[i] != 0 && l1[i] != 0xffffffff) n++; if (level >= 4) n = cdevhdr.numl1tab; /* calculate max possible space table entries */ n = 1 + 1 + 1 // devhdr, cdevhdr, l1tab + n // l2tabs + (n * 256) // trk/blk images + (1 + n + (n * 256) + 1) // max possible free spaces + 1; // end-of-file /* obtain the space table */ len = sizeof(SPCTAB); if ((spctab = calloc (n, len)) == NULL) goto cdsk_calloc_error; /* populate the table with what we have */ s = 0; /* devhdr */ spctab[s].typ = SPCTAB_DEVHDR; spctab[s].val = -1; spctab[s].pos = 0; spctab[s].len = spctab[s].siz = CKDDASD_DEVHDR_SIZE; s++; /* cdevhdr */ spctab[s].typ = SPCTAB_CDEVHDR; spctab[s].val = -1; spctab[s].pos = CCKD_DEVHDR_POS; spctab[s].len = spctab[s].siz = CCKD_DEVHDR_SIZE; s++; /* l1 table */ spctab[s].typ = SPCTAB_L1; spctab[s].val = -1; spctab[s].pos = CCKD_L1TAB_POS; spctab[s].len = spctab[s].siz = l1size; s++; /* l2 tables */ for (i = 0; i < cdevhdr.numl1tab && level < 4; i++) { if (l1[i] == 0 || l1[i] == 0xffffffff) continue; spctab[s].typ = SPCTAB_L2; spctab[s].val = i; spctab[s].pos = l1[i]; spctab[s].len = spctab[s].siz = CCKD_L2TAB_SIZE; s++; } /* end-of-file */ spctab[s].typ = SPCTAB_EOF; spctab[s].val = -1; spctab[s].pos = (U32)fst.st_size; spctab[s].len = spctab[s].siz = 0; s++; qsort (spctab, s, sizeof(SPCTAB), cdsk_spctab_sort); /*--------------------------------------------------------------- * Quick return if level -1 *---------------------------------------------------------------*/ if (level < 0) { int err = 0; /* check for overlaps */ for (i = 0; spctab[i].typ != SPCTAB_EOF; i++) if (spctab[i].pos + spctab[i].siz > spctab[i+1].pos) err = 1; /* exit if no errors */ if (!err) goto cdsk_return_ok; } /*--------------------------------------------------------------- * obtain the l2errs table and recovery table *---------------------------------------------------------------*/ len = sizeof(BYTE); n = cdevhdr.numl1tab; if ((l2errs = calloc (n, len)) == NULL) goto cdsk_calloc_error; n = trks; if ((rcvtab = calloc (n, len)) == NULL) goto cdsk_calloc_error; /*--------------------------------------------------------------- * Special processing for level 4 (recover everything) *---------------------------------------------------------------*/ if (level == 4) { memset (l2errs, 1, cdevhdr.numl1tab); memset (rcvtab, 1, trks); goto cdsk_recovery; } /*--------------------------------------------------------------- * Read the level 2 tables *---------------------------------------------------------------*/ for (i = 0; spctab[i].typ != SPCTAB_EOF; i++) { if (spctab[i].typ != SPCTAB_L2 || spctab[i].pos < lopos || spctab[i].pos > hipos) continue; off = spctab[i].pos; if ( lseek (fd, off, SEEK_SET) < 0 ) goto cdsk_lseek_error; len = CCKD_L2TAB_SIZE; if ((rc = read (fd, l2tab, len)) != len) goto cdsk_read_error; if (swapend) cckd_swapend_l2 (l2tab); /* add trks/blkgrps to the space table */ for (j = 0; j < 256; j++) { if (l2tab[j].pos != 0 && l2tab[j].pos != 0xffffffff) { spctab[s].typ = trktyp; spctab[s].val = spctab[i].val * 256 + j; spctab[s].pos = l2tab[j].pos; spctab[s].len = l2tab[j].len; spctab[s].siz = l2tab[j].size; s++; } } } qsort (spctab, s, sizeof(SPCTAB), cdsk_spctab_sort); /*--------------------------------------------------------------- * Consistency checks. * * The space table is now populated with everything but free * space. Therefore we can infer what the free space should * be (ie gaps between allocated spaces). *---------------------------------------------------------------*/ lopos = CCKD_L1TAB_POS + l1size; hipos = fst.st_size; /* Make adjustment if new format free space is at the end */ len = spctab[s-1].pos - (spctab[s-2].pos + spctab[s-2].siz); if (len > 0 && cdevhdr.size == cdevhdr.free && cdevhdr.size + len == spctab[s-1].pos) { spctab[s-1].pos -= len; hipos -= len; } memset (&cdevhdr2, 0, CCKD_DEVHDR_SIZE); for (i = 0; spctab[i].typ != SPCTAB_EOF; i++) { /* Calculate gap size */ len = spctab[i+1].pos - (spctab[i].pos + spctab[i].siz); /* Update space statistics */ cdevhdr2.size += spctab[i].siz + len; cdevhdr2.used += spctab[i].len; if (len > 0) { cdevhdr2.free_number++; cdevhdr2.free_total += len; if (cdevhdr2.free_largest < (U32)len) cdevhdr2.free_largest = (U32)len; } if (spctab[i].typ == trktyp) { cdevhdr2.free_total += spctab[i].siz - spctab[i].len; cdevhdr2.free_imbed += spctab[i].siz - spctab[i].len; } /* ignore devhdr, cdevhdr and l1 (these are `out of bounds') */ if (spctab[i].typ == SPCTAB_DEVHDR || spctab[i].typ == SPCTAB_CDEVHDR || spctab[i].typ == SPCTAB_L1 ) continue; /* check if the space is out of bounds */ valid = (off_t)spctab[i].pos >= lopos && (off_t)spctab[i].pos + spctab[i].siz <= hipos; /* Overlap check */ if (len < 0 || !valid) { char space1[32], space2[32]; recovery = 1; /* issue error message */ j = sprintf(space1, "%s", spaces[spctab[i].typ]); if (spctab[i].val >= 0) sprintf(space1+j, "[%d]", spctab[i].val); j = sprintf(space2, "%s", spaces[spctab[i+1].typ]); if (spctab[i+1].val >= 0) sprintf(space2+j, "[%d]", spctab[i+1].val); if (!valid) cckdumsg(dev, 602, "%s offset 0x%" I32_FMT "x len %d is out of bounds\n", space1, spctab[i].pos, spctab[i].siz); else cckdumsg(dev, 603, "%s offset 0x%" I32_FMT "x len %d overlaps %s offset 0x%" I32_FMT "x\n", space1, spctab[i].pos, spctab[i].siz, space2, spctab[i+1].pos); /* setup recovery */ if (spctab[i].typ == SPCTAB_L2) { l2errs[spctab[i].val] = 1; /* Mark all tracks for the l2 for recovery */ memset (rcvtab + (spctab[i].val*256), 1, 256); } else if (spctab[i].typ == trktyp) rcvtab[spctab[i].val] = 1; if (spctab[i+1].typ == SPCTAB_L2 && valid) { l2errs[spctab[i+1].val] = 1; memset (rcvtab + (spctab[i+1].val*256), 1, 256); } else if (spctab[i+1].typ == trktyp && valid) rcvtab[spctab[i+1].val] = 1; } /* if overlap or out of bounds */ /* Check image l2 entry consistency */ else if (spctab[i].typ == trktyp && (spctab[i].len < CKDDASD_TRKHDR_SIZE || spctab[i].len > spctab[i].siz || spctab[i].len > trksz)) { recovery = 1; /* issue error message */ cckdumsg(dev, 604, "%s[%d] l2 inconsistency: len %d, size %d\n", spaces[trktyp], spctab[i].val, spctab[i].len, spctab[i].siz); /* setup recovery */ rcvtab[spctab[i].val] = 1; } /* if inconsistent l2 */ } /* for each space */ /* remove any l2 tables or tracks in error from the space table */ for (i = 0; recovery && spctab[i].typ != SPCTAB_EOF; i++) if ((spctab[i].typ == SPCTAB_L2 && l2errs[spctab[i].val]) || (spctab[i].typ == trktyp && rcvtab[spctab[i].val])) spctab[i].typ = SPCTAB_NONE; /* overlaps are serious */ if (recovery && level < 3) { level = 3; cckdumsg (dev, 600, "forcing check level %d\n", level); } /* Rebuild free space if any errors */ if (recovery || hdrerr || cdevhdr.size != cdevhdr2.size || cdevhdr.used != cdevhdr2.used || cdevhdr.free_number != cdevhdr2.free_number || cdevhdr.free_largest != cdevhdr2.free_largest || cdevhdr.free_total != cdevhdr2.free_total || cdevhdr.free_imbed != cdevhdr2.free_imbed ) fsperr = 1; /*--------------------------------------------------------------- * read the free space *---------------------------------------------------------------*/ lopos = CCKD_L1TAB_POS + l1size; hipos = fst.st_size; if (level >= 1 && !fsperr) { while (cdevhdr.free) // `while' so code can break { fsperr = 1; // be pessimistic fsp = NULL; /* Read the free space */ off = (off_t)cdevhdr.free; len = CCKD_FREEBLK_SIZE; if (off < lopos || off + CCKD_FREEBLK_SIZE > hipos || lseek (fd, off, SEEK_SET) < 0 || (rc = read (fd, &freeblk, len)) != len) break; if (memcmp (&freeblk, "FREE_BLK", 8) == 0) { /* new format free space */ len = cdevhdr.free_number * CCKD_FREEBLK_SIZE; if ((fsp = malloc(len)) == NULL || (rc = read (fd, fsp, len)) != len) break; for (i = 0; i < cdevhdr.free_number; i++) { if (swapend) cckd_swapend_free (&fsp[i]); spctab[s].typ = SPCTAB_FREE; spctab[s].val = -1; spctab[s].pos = fsp[i].pos; spctab[s].len = spctab[s].siz = fsp[i].len; /* Free space should be ascending */ if (spctab[s].pos < lopos || spctab[s].pos + spctab[s].siz > hipos) break; lopos = spctab[s].pos + spctab[s].siz; s++; } /* for each free space */ if (i >= cdevhdr.free_number) fsperr = 0; } /* new format free space */ else { /* old format free space */ off = (off_t)cdevhdr.free; len = CCKD_FREEBLK_SIZE; for (i = 0; i < cdevhdr.free_number; i++) { if (off < lopos || off > hipos) break; if (lseek (fd, off, SEEK_SET) < 0) goto cdsk_lseek_error; if ((rc = read (fd, &freeblk, len)) != len) goto cdsk_read_error; if (swapend) cckd_swapend_free (&freeblk); spctab[s].typ = SPCTAB_FREE; spctab[s].val = -1; spctab[s].pos = (U32)off; spctab[s].len = spctab[s].siz = freeblk.len; s++; lopos = off + freeblk.len; off = (off_t)freeblk.pos; } if (i >= cdevhdr.free_number && freeblk.pos == 0) fsperr = 0; } /* if old format free space */ if (fsp) free(fsp); fsp = NULL; /* Check for gaps/overlaps */ qsort (spctab, s, sizeof(SPCTAB), cdsk_spctab_sort); for (i = 0; !fsperr && spctab[i].typ != SPCTAB_EOF; i++) if (spctab[i].pos + spctab[i].siz != spctab[i+1].pos) fsperr = 1; break; } /* while (cdevhdr.free) */ } /* if (level >= 1 && !fsperr) */ if (fsperr) cckdumsg (dev, 610, "free space errors detected\n"); /*--------------------------------------------------------------- * Read track headers/images *---------------------------------------------------------------*/ cdsk_space_check: if (level >= 2) { for (i = 0; spctab[i].typ != SPCTAB_EOF; i++) { if (spctab[i].typ != trktyp) continue; /* read the header or image depending on the check level */ off = spctab[i].pos; if ( lseek (fd, off, SEEK_SET) < 0 ) goto cdsk_lseek_error; len = level < 3 ? CKDDASD_TRKHDR_SIZE : spctab[i].len; if ((rc = read (fd, buf, len)) != len) goto cdsk_read_error; /* Extract header info */ comp = buf[0]; cyl = fetch_hw (buf + 1); head = fetch_hw (buf + 3); trk = cyl * heads + head; /* Validate header info */ if (compmask[comp] == 0xff || cyl >= cyls || head >= heads || trk != spctab[i].val) { cckdumsg (dev, 620, "%s[%d] hdr error offset 0x%" I64_FMT "x: %2.2x%2.2x%2.2x%2.2x%2.2x\n", spaces[trktyp], spctab[i].val, (long long)off, buf[0],buf[1],buf[2],buf[3],buf[4]); /* recover this track */ rcvtab[spctab[i].val] = recovery = 1; spctab[i].typ = SPCTAB_NONE; /* Force level 3 checking */ if (level < 3) { level = 3; cckdumsg (dev, 600, "forcing check level %d\n", level); goto cdsk_space_check; } continue; } /* if invalid header info */ /* Check if compression supported */ if (compmask[comp]) { comperrs = 1; cckdumsg ( dev, 621, "%s[%d] compressed using %s, not supported\n", spaces[trktyp], trk, comps[compmask[comp]]); continue; } /* Validate the space if check level 3 */ if (level > 2) { if (!cdsk_valid_trk (trk, buf, heads, len)) { cckdumsg (dev, 622, "%s[%d] offset 0x%" I64_FMT "x len %d validation error\n", spaces[trktyp], trk, (long long)off, len); /* recover this track */ rcvtab[trk] = recovery = 1; spctab[i].typ = SPCTAB_NONE; } /* if invalid space */ else rcvtab[trk] = 0; } /* if level > 2 */ } /* for each space */ } /* if (level >= 2) */ /*--------------------------------------------------------------- * Recovery *---------------------------------------------------------------*/ cdsk_recovery: if (recovery || level == 4) { U32 flen, fpos; /*----------------------------------------------------------- * Phase 1 -- recover trk/blkgrp images *-----------------------------------------------------------*/ /* * Reset the end-of-file pos to the file size * It might have been changed if new format free space * occurred at the end of the file. */ qsort (spctab, s, sizeof(SPCTAB), cdsk_spctab_sort); while (spctab[s-1].typ == SPCTAB_NONE) s--; spctab[s-1].pos = fst.st_size; /* count number tracks to be recovered */ for (i = n = 0; i < trks; i++) if (rcvtab[i] == 1) n++; /*----------------------------------------------------------- * ckd recovery *-----------------------------------------------------------*/ if (ckddasd) { /* recovery loop */ s = cdsk_build_free_space (spctab, s); for (f = 0; spctab[f].typ != SPCTAB_EOF && n; ) { /* next free space if too small */ if (spctab[f].typ != SPCTAB_FREE || spctab[f].siz <= CKDDASD_TRKHDR_SIZE+8) { for (f = f + 1; spctab[f].typ != SPCTAB_EOF; f++) if (spctab[f].typ == SPCTAB_FREE) break; continue; } fpos = spctab[f].pos; flen = spctab[f].siz; /* length to read */ len = flen < sizeof(buf) ? flen : sizeof(buf); /* read the free space */ off = (off_t)fpos; if (lseek (fd, off, SEEK_SET) < 0) goto cdsk_lseek_error; if ((rc = read (fd, buf, len)) != len) goto cdsk_read_error; /* Scan the space for a trkhdr */ for (i = 0; i < len - (CKDDASD_TRKHDR_SIZE+8); i++) { /* Check compression byte */ if (compmask[buf[i]]) continue; /* Fetch possible trkhdr */ comp = buf[i]; cyl = fetch_hw (buf + i + 1); head = fetch_hw (buf + i + 3); trk = cyl * heads + head; /* Validate possible trkhdr */ if (cyl >= cyls || head >= heads || rcvtab[trk] != 1) continue; /* Quick validation for compress none */ if (comp == CCKD_COMPRESS_NONE && (fetch_hw (buf + i + 5) != cyl // r0 cyl || fetch_hw (buf + i + 7) != head // r0 head || buf[i + 9] != 0 // r0 record || buf[i + 10] != 0 // r0 key length || fetch_hw (buf + i + 11) != 8 // r0 data length ) ) continue; /* Quick validation for zlib */ else if (comp == CCKD_COMPRESS_ZLIB && fetch_hw(buf + i + 5) % 31 != 0) continue; /* Quick validation for bzip2 */ else if (comp == CCKD_COMPRESS_BZIP2 && (buf[i+5] != 'B' || buf[i+6] != 'Z')) continue; /* * If we are in `borrowed space' then start over * with the current position at the beginning */ if (flen > (U32)len && i > len - (int)trksz) break; /* Checks for comp none */ if (comp == CCKD_COMPRESS_NONE) { l = len - i; if ((l = cdsk_valid_trk (trk, buf+i, heads, -l))) goto cdsk_ckd_recover; else continue; } /* Check short `length' */ if (flen == (U32)len && (l = len - i) <= 1024) { if (cdsk_valid_trk (trk, buf+i, heads, l)) { while (cdsk_valid_trk (trk, buf+i, heads, --l)); l++; goto cdsk_ckd_recover; } } /* Scan for next trkhdr */ for (j = i + CKDDASD_TRKHDR_SIZE+8; j <= len - (CKDDASD_TRKHDR_SIZE+8); j++) { if (j - i > (int)trksz) break; if (compmask[buf[j]] != 0 || fetch_hw(buf+j+1) >= cyls || fetch_hw(buf+j+3) >= heads) continue; /* check uncompressed hdr */ if (buf[j] == CCKD_COMPRESS_NONE && (fetch_hw (buf+j+5) != fetch_hw(buf+j+1) || fetch_hw (buf+j+7) != fetch_hw(buf+j+3) || buf[j+9] != 0 || buf[j+10] != 0 || fetch_hw(buf+j+11) != 8)) continue; /* check zlib compressed header */ else if (buf[j] == CCKD_COMPRESS_ZLIB && fetch_hw(buf + j + 5) % 31 != 0) continue; /* check bzip2 compressed header */ else if (buf[j] == CCKD_COMPRESS_BZIP2 && (buf[j+5] != 'B' || buf[j+6] != 'Z')) continue; /* check to possible trkhdr */ l = j - i; if (cdsk_valid_trk (trk, buf+i, heads, l)) { #if 0 while (cdsk_valid_trk (trk, buf+i, heads, --l)); l++; #endif goto cdsk_ckd_recover; } } /* scan for next trkhdr */ /* Check `length' */ if (flen == (U32)len && (l = len - i) <= (int)trksz) { if (cdsk_valid_trk (trk, buf+i, heads, l)) { while (cdsk_valid_trk (trk, buf+i, heads, --l)); l++; goto cdsk_ckd_recover; } } /* Scan all lengths */ for (l = CKDDASD_TRKHDR_SIZE+8; i + l <= len; l++) { if (l > (int)trksz) break; if (cdsk_valid_trk (trk, buf+i, heads, l)) goto cdsk_ckd_recover; } /* for all lengths */ continue; cdsk_ckd_recover: cckdumsg (dev, 301, "%s[%d] recovered offset 0x%" I64_FMT "x len %d\n", spaces[trktyp], trk, (long long)off + i, l); n--; rcvtab[trk] = 2; /* add recovered track to the space table */ spctab[s].typ = trktyp; spctab[s].val = trk; spctab[s].pos = fpos + i; spctab[s].len = spctab[s].siz = l; s++; /* * adjust `i' knowing it will be incremented * in the `for' loop above. */ i += l - 1; } /* for each byte in the free space */ /* Adjust the free space for what we processed */ spctab[f].pos += i; spctab[f].len -= i; spctab[f].siz -= i; } /* for each free space */ } /* if ckddasd */ /*----------------------------------------------------------- * fba recovery *-----------------------------------------------------------*/ /* * FBA blkgrps are harder to recover than CKD tracks because * there is not any information within the blkgrp itself to * validate (unlike a track, which has count fields that * terminate in an end-of-track marker). * * On the first pass we recover all compressed blkgrps since * these are readily validated (they must uncompress to a * certain size, CFBA_BLOCK_SIZE+CKDDASD_TRKHDR_SIZE). We * also recover uncompressed blkgrps if they are followed by * a valid trkhdr (and don't occur to close to the beginning * of the file). * * On the second pass we recover all uncompressed blkgrps * that weren't recovered in the first pass. The only * criteria is that the compression byte is zero and the * 4 byte blkgrp number is in range and there are at least * CFBA_BLOCK_SIZE bytes following. */ for (pass = 0; fbadasd && pass < 2; pass++) { lopos = CCKD_L1TAB_POS + (cdevhdr.numl1tab * 4); if (pass == 0) lopos += (cdevhdr.numl1tab * CCKD_L2TAB_SIZE); /* recovery loop */ s = cdsk_build_free_space (spctab, s); for (f = 0; spctab[f].typ != SPCTAB_EOF && n > 0; ) { U32 flen, fpos; /* next free space if too small */ if (spctab[f].typ != SPCTAB_FREE || spctab[f].siz <= CKDDASD_TRKHDR_SIZE+8 || (pass == 1 && spctab[f].siz < blkgrpsz)) { for (f = f + 1; spctab[f].typ != SPCTAB_EOF; f++) if (spctab[f].typ == SPCTAB_FREE) break; continue; } fpos = spctab[f].pos; flen = spctab[f].siz; /* * calculate length to read * if flen > len then we only read part of the space */ len = flen < sizeof(buf) ? flen : sizeof(buf); /* read the free space */ off = (off_t)fpos; if (lseek (fd, off, SEEK_SET) < 0) goto cdsk_lseek_error; if ((rc = read (fd, buf, len)) != len) goto cdsk_read_error; /* Scan the space */ for (i = 0; i < len - (CKDDASD_TRKHDR_SIZE+8); i++) { /* For pass 1 the size left must be at least blkgrpsz */ if (pass == 1 && len - i < (int)blkgrpsz) break; /* Check compression byte */ if ((pass == 0 && compmask[buf[i]]) || (pass == 1 && buf[i] != CCKD_COMPRESS_NONE)) continue; /* Fetch possible trkhdr */ comp = buf[i]; blkgrp = fetch_fw (buf + i + 1); /* Validate possible trkhdr */ if (blkgrp < 0 || blkgrp >= blkgrps || rcvtab[blkgrp] != 1) continue; /* Validation for compress none */ if (comp == CCKD_COMPRESS_NONE && flen == (U32)len && len - i < (int)blkgrpsz) continue; /* Quick validation for zlib */ else if (comp == CCKD_COMPRESS_ZLIB && fetch_hw(buf + i + 5) % 31 != 0) continue; /* Quick validation for bzip2 */ else if (comp == CCKD_COMPRESS_BZIP2 && (buf[i+5] != 'B' || buf[i+6] != 'Z')) continue; /* * If we are in `borrowed space' then start over * with the current position at the beginning */ if (flen > (U32)len && i > len - (int)blkgrpsz) break; /* Checks for comp none */ if (comp == CCKD_COMPRESS_NONE) { l = blkgrpsz; if (len - i < (int)blkgrpsz || fpos + i < lopos) continue; if (len - i == (int)blkgrpsz && flen == (U32)len) goto cdsk_fba_recover; /* Pass 0 checks */ if (pass == 0 && (len - i - l < CKDDASD_TRKHDR_SIZE+8 || compmask[buf[i+l]] || fetch_fw (buf+i+l+1) >= (unsigned int)blkgrps) ) continue; goto cdsk_fba_recover; } /* The tests below are for pass 0 only */ if (pass == 1) continue; /* Check short `length' */ if (flen == (U32)len && (l = len - i) <= 1024) { if (cdsk_valid_trk (blkgrp, buf+i, heads, l)) { while (cdsk_valid_trk (blkgrp, buf+i, heads, --l)); l++; goto cdsk_fba_recover; } } /* Scan for next trkhdr */ for (j = i + CKDDASD_TRKHDR_SIZE+8; j <= len - (CKDDASD_TRKHDR_SIZE+8); j++) { if (j - i > (int)blkgrpsz) break; if (compmask[buf[j]] != 0 || fetch_fw(buf+j+1) >= (unsigned int)blkgrps) continue; /* check zlib compressed header */ if (buf[j] == CCKD_COMPRESS_ZLIB && fetch_hw(buf + j + 5) % 31 != 0) continue; /* check bzip2 compressed header */ else if (buf[j] == CCKD_COMPRESS_BZIP2 && (buf[j+5] != 'B' || buf[j+6] != 'Z')) continue; /* check to possible trkhdr */ l = j - i; if (cdsk_valid_trk (blkgrp, buf+i, heads, l)) { #if 0 while (cdsk_valid_trk (blkgrp, buf+i, heads, --l)); l++; #endif goto cdsk_fba_recover; } } /* scan for next trkhdr */ /* Check `length' */ l = len - i; if (flen == (U32)len && l <= (int)blkgrpsz) { if (cdsk_valid_trk (blkgrp, buf+i, heads, l)) { while (cdsk_valid_trk (blkgrp, buf+i, heads, --l)); l++; goto cdsk_fba_recover; } } /* Scan all lengths */ for (l = CKDDASD_TRKHDR_SIZE+8; i + l <= len; l++) { if (l > (int)blkgrpsz) break; if (cdsk_valid_trk (blkgrp, buf+i, heads, l)) goto cdsk_fba_recover; } /* for all lengths */ continue; cdsk_fba_recover: cckdumsg (dev, 301, "%s[%d] recovered offset 0x%" I64_FMT "x len %d\n", spaces[trktyp], blkgrp, (long long)off + i, l); n--; rcvtab[blkgrp] = 2; /* Enable recovery of comp 0 blkgrps for pass 0 */ if (fpos + i < lopos) lopos = fpos + i; /* add recovered block group to the space table */ spctab[s].typ = trktyp; spctab[s].val = blkgrp; spctab[s].pos = fpos + i; spctab[s].len = spctab[s].siz = l; s++; /* * adjust `i' knowing it will be incremented * in the `for' loop above. */ i += l - 1; } /* for each byte in the free space */ /* Adjust the free space for what we processed */ spctab[f].pos += i; spctab[f].len -= i; spctab[f].siz -= i; } /* for each free space */ } /* if fbadasd */ for (i = n = 0; i < trks; i++) if (rcvtab[i] == 2) n++; cckdumsg (dev, 300, "%d %s images recovered\n", n, spaces[trktyp]); /*----------------------------------------------------------- * Phase 2 -- rebuild affected l2 tables *-----------------------------------------------------------*/ /* * Make sure there's at least one non-zero `rcvtab' entry * for l2 tables in `l2errs'. Space validation may have * turned off all `rcvtab' entries for an l2. */ for (i = 0; i < cdevhdr.numl1tab; i++) if (l2errs[i]) rcvtab[i*256] = 1; /* Get storage for the l2 table array */ n = cdevhdr.numl1tab; len = sizeof(void *); if ((l2 = calloc (n, len)) == NULL) goto cdsk_calloc_error; /* Get storage for the rebuilt l2 tables */ len = CCKD_L2TAB_SIZE; for (i = 0; i < trks; i++) { l1x = i / 256; if (rcvtab[i] != 0 && l2[l1x] == NULL) { if ((l2[l1x] = malloc (len)) == NULL) goto cdsk_malloc_error; l1[l1x] = shadow ? 0xffffffff : 0; memcpy (l2[l1x], &empty_l2, len); } } /* Rebuild the l2 tables */ qsort (spctab, s, sizeof(SPCTAB), cdsk_spctab_sort); for (i = 0; spctab[i].typ != SPCTAB_EOF; i++) { if (spctab[i].typ == SPCTAB_L2 && l2[spctab[i].val]) spctab[i].typ = SPCTAB_NONE; else if (spctab[i].typ == trktyp && l2[spctab[i].val/256]) { l1x = spctab[i].val / 256; l2x = spctab[i].val % 256; l2[l1x][l2x].pos = spctab[i].pos; l2[l1x][l2x].len = spctab[i].len; l2[l1x][l2x].size = spctab[i].siz; } } /* for each space */ qsort (spctab, s, sizeof(SPCTAB), cdsk_spctab_sort); while (spctab[s-1].typ == SPCTAB_NONE) s--; /* Look for empty l2 tables */ for (i = 0; i < cdevhdr.numl1tab; i++) if (l2[i] != NULL && memcmp (l2[i], &empty_l2, CCKD_L2TAB_SIZE) == 0) { free (l2[i]); l2[i] = NULL; } /* * `s-1' indexes the SPCTAB_EOF space table entry. * Set its `pos' to the maximum allowed value to ensure * there will be free space for the rebuilt l2 tables. */ spctab[s-1].pos = (U32)maxsize; /* Build the free space */ s = cdsk_build_free_space (spctab, s); /* Find space for the rebuilt l2 tables */ for (i = j = 0; i < cdevhdr.numl1tab; i++) { if (l2[i] == NULL) continue; /* find a free space */ for ( ; spctab[j].typ != SPCTAB_EOF; j++) if (spctab[j].typ == SPCTAB_FREE && spctab[j].siz >= CCKD_L2TAB_SIZE) break; /* weird error if no space */ if (spctab[j].typ == SPCTAB_EOF) { cckdumsg (dev, 905, "not enough file space for recovery\n"); goto cdsk_error; } /* add l2 space */ l1[i] = spctab[j].pos; spctab[s].typ = SPCTAB_L2; spctab[s].val = i; spctab[s].pos = spctab[j].pos; spctab[s].len = spctab[s].siz = CCKD_L2TAB_SIZE; s++; /* adjust the free space */ spctab[j].pos += CCKD_L2TAB_SIZE; spctab[j].len -= CCKD_L2TAB_SIZE; spctab[j].siz -= CCKD_L2TAB_SIZE; } /* for each l2 table */ /*----------------------------------------------------------- * Phase 3 -- write l1 and l2 tables *-----------------------------------------------------------*/ if (ro) { cckdumsg (dev, 500, "recovery not completed, file opened read-only\n"); goto cdsk_error; } if (comperrs) { cckdumsg (dev, 501, "recovery not completed, missing compression\n"); goto cdsk_error; } /* Write the l1 table */ off = CCKD_L1TAB_POS; if (lseek (fd, off, SEEK_SET) < 0) goto cdsk_lseek_error; len = l1size; if ((rc = write (fd, l1, len)) != len) goto cdsk_write_error; /* Write l2 tables */ qsort (spctab, s, sizeof(SPCTAB), cdsk_spctab_sort); for (i = 0; spctab[i].typ != SPCTAB_EOF; i++) { l1x = spctab[i].val; if (spctab[i].typ != SPCTAB_L2 || l2[l1x] == NULL) continue; off = (off_t)l1[l1x]; if (lseek (fd, off, SEEK_SET) < 0) goto cdsk_lseek_error; len = CCKD_L2TAB_SIZE; if ((rc = write (fd, l2[l1x], len)) != len) goto cdsk_write_error; free (l2[l1x]); l2[l1x] = NULL; } /* for each space */ /* Free recovery related storage */ if (l2) { for (i = 0; i < cdevhdr.numl1tab; i++) if (l2[i]) free (l2[i]); free (l2); l2 = NULL; } free (l2errs); l2errs = NULL; free (rcvtab); rcvtab = NULL; /* Ensure we do free space recovery */ fsperr = 1; } /* if (recovery || level >= 4) */ /*--------------------------------------------------------------- * Rebuild free space *---------------------------------------------------------------*/ if (fsperr && ro) cckdumsg (dev, 502, "free space not rebuilt, file opened read-only\n"); else if (fsperr) { /*----------------------------------------------------------- * Phase 1 -- build the free space * make sure the last space isn't free space and * that each free space is long enough (8 bytes). *-----------------------------------------------------------*/ cdsk_fsperr_retry: s = cdsk_build_free_space (spctab, s); /* * spctab[s-1] is the SPCTAB_EOF entry. * if spctab[s-2] is SPCTAB_FREE then discard it */ if (spctab[s-2].typ == SPCTAB_FREE) { spctab[s-1].typ = SPCTAB_NONE; spctab[s-2].typ = SPCTAB_EOF; spctab[s-2].val = -1; spctab[s-2].len = spctab[s-2].siz = 0; s--; } /* * Check for short free spaces. * If found, shift left until the next free space or eof. */ for (i = 0; spctab[i].typ != SPCTAB_EOF; i++) if (spctab[i].typ == SPCTAB_FREE && spctab[i].siz < CCKD_FREEBLK_SIZE) break; if (spctab[i].typ != SPCTAB_EOF) { /* Shift following space left */ l = spctab[i++].siz; while (spctab[i].typ != SPCTAB_FREE && spctab[i].typ != SPCTAB_EOF) { /* Read the space and write shifted to the left */ off = (off_t)spctab[i].pos; if (lseek (fd, off, SEEK_SET) < 0) goto cdsk_lseek_error; len = spctab[i].siz; if ((rc = read (fd, buf, len)) != len) goto cdsk_read_error; off -= l; if (lseek (fd, off, SEEK_SET) < 0) goto cdsk_lseek_error; if ((rc = write (fd, buf, len)) != len) goto cdsk_write_error; spctab[i].pos -= l; /* Update the l2 or l1 table entry */ if (spctab[i].typ == trktyp) { l1x = spctab[i].val/256; l2x = spctab[i].val%256; off = (off_t)l1[l1x] + l2x * CCKD_L2ENT_SIZE; if (lseek (fd, off, SEEK_SET) < 0) goto cdsk_lseek_error; len = CCKD_L2ENT_SIZE; if ((rc = read (fd, &l2ent, len)) != len) goto cdsk_read_error; l2ent.pos -= l; if (lseek (fd, off, SEEK_SET) < 0) goto cdsk_lseek_error; if ((rc = write (fd, &l2ent, len)) != len) goto cdsk_write_error; } /* trk/blkgrp relocated */ else if (spctab[i].typ == SPCTAB_L2) l1[spctab[i].val] -= l; i++; } /* while not FREE space or EOF */ goto cdsk_fsperr_retry; } /* if short free space found */ /*----------------------------------------------------------- * Phase 2 -- rebuild free space statistics *-----------------------------------------------------------*/ cdevhdr.vrm[0] = CCKD_VERSION; cdevhdr.vrm[1] = CCKD_RELEASE; cdevhdr.vrm[2] = CCKD_MODLVL; cdevhdr.size = cdevhdr.used = cdevhdr.free = cdevhdr.free_total = cdevhdr.free_largest = cdevhdr.free_number = cdevhdr.free_imbed = 0; for (i = 0; spctab[i].typ != SPCTAB_EOF; i++) if (spctab[i].typ == SPCTAB_FREE) { cdevhdr.size += spctab[i].siz; if (spctab[i].siz > cdevhdr.free_largest) cdevhdr.free_largest = spctab[i].siz; cdevhdr.free_total += spctab[i].siz; cdevhdr.free_number++; } else { cdevhdr.size += spctab[i].siz; cdevhdr.used += spctab[i].len; cdevhdr.free_total += spctab[i].siz - spctab[i].len; cdevhdr.free_imbed += spctab[i].siz - spctab[i].len; } /*----------------------------------------------------------- * Phase 3 -- write the free space *-----------------------------------------------------------*/ if (cdevhdr.free_number) { /* size needed for new format free space */ len = (cdevhdr.free_number+1) * CCKD_FREEBLK_SIZE; /* look for existing free space to fit new format free space */ for (i = off = 0; !off && spctab[i].typ != SPCTAB_EOF; i++) if (spctab[i].typ == SPCTAB_FREE && len <= (int)spctab[i].siz) off = (off_t)spctab[i].pos; /* if no applicable space see if we can append to the file */ if (!off && maxsize - cdevhdr.size >= len) off = (off_t)cdevhdr.size; /* get free space buffer */ if (off && (fsp = malloc (len)) == NULL) off = 0; if (off) { /* new format free space */ memcpy (fsp, "FREE_BLK", 8); for (i = 0, j = 1; spctab[i].typ != SPCTAB_EOF; i++) if (spctab[i].typ == SPCTAB_FREE) { fsp[j].pos = spctab[i].pos; fsp[j++].len = spctab[i].siz; } /* Write the free space */ if (lseek (fd, off, SEEK_SET) < 0) goto cdsk_lseek_error; if ((rc = write (fd, fsp, len)) != len) goto cdsk_write_error; cdevhdr.free = (U32)off; free (fsp); fsp = NULL; } /* new format free space */ else { /* old format free space */ len = CCKD_FREEBLK_SIZE; for (i = 0; spctab[i].typ != SPCTAB_FREE; i++); cdevhdr.free = spctab[i].pos; off = (off_t)spctab[i].pos; freeblk.pos = 0; freeblk.len = spctab[i].siz; for (i = i + 1; spctab[i].typ != SPCTAB_EOF; i++) if (spctab[i].typ == SPCTAB_FREE) { freeblk.pos = spctab[i].pos; if (lseek (fd, off, SEEK_SET) < 0) goto cdsk_lseek_error; if (write (fd, &freeblk, len) != len) goto cdsk_write_error; off = (off_t)spctab[i].pos; freeblk.pos = 0; freeblk.len = spctab[i].len; } if (lseek (fd, off, SEEK_SET) < 0) goto cdsk_lseek_error; if (write (fd, &freeblk, len) != len) goto cdsk_write_error; } /* old format free space */ } /* if (cdevhdr.free_number) */ /* Write cdevhdr and l1 table */ off = CCKD_DEVHDR_POS; if (lseek (fd, off, SEEK_SET) < 0) goto cdsk_lseek_error; len = CCKD_DEVHDR_SIZE; if (write (fd, &cdevhdr, len) != len) goto cdsk_write_error; off = CCKD_L1TAB_POS; if (lseek (fd, off, SEEK_SET) < 0) goto cdsk_lseek_error; len = l1size; if (write (fd, l1, len) != len) goto cdsk_write_error; /* Truncate the file */ off = (off_t)cdevhdr.size; if (cdevhdr.free == cdevhdr.size) off += (cdevhdr.free_number+1) * CCKD_FREEBLK_SIZE; rc = ftruncate (fd, off); cckdumsg (dev, 104, "free space rebuilt\n"); } /* if (fsperr) */ /*--------------------------------------------------------------- * Return *---------------------------------------------------------------*/ cdsk_return_ok: rc = recovery ? 2 : fsperr ? 1 : 0; if (!ro && (cdevhdr.options & (CCKD_ORDWR|CCKD_OPENED|CCKD_SPERRS))) { /* * Leave the ORDWR bit on for now. This will prevent * old-format free space releases from doing a -1 check * on a file that has new-format free space */ #if 0 cdevhdr.options &= ~(CCKD_ORDWR|CCKD_OPENED|CCKD_SPERRS); #else cdevhdr.options &= ~(CCKD_OPENED|CCKD_SPERRS); #endif /* Set version.release.modlvl */ cdevhdr.vrm[0] = CCKD_VERSION; cdevhdr.vrm[1] = CCKD_RELEASE; cdevhdr.vrm[2] = CCKD_MODLVL; off = CCKD_DEVHDR_POS; if (lseek (fd, CCKD_DEVHDR_POS, SEEK_SET) >= 0) write (fd, &cdevhdr, CCKD_DEVHDR_SIZE); } cdsk_return: /* free all space */ if (l1) free (l1); if (spctab) free (spctab); if (l2errs) free (l2errs); if (rcvtab) free (rcvtab); if (fsp) free (fsp); if (l2) { for (i = 0; i < cdevhdr.numl1tab; i++) if (l2[i]) free (l2[i]); free (l2); } return rc; /*--------------------------------------------------------------- * Error exits *---------------------------------------------------------------*/ cdsk_fstat_error: cckdumsg (dev, 701, "fstat error: %s\n", strerror(errno)); goto cdsk_error; cdsk_lseek_error: cckdumsg (dev, 702, "lseek error offset 0x%" I64_FMT "x: %s\n", (long long)off, strerror(errno)); goto cdsk_error; cdsk_read_error: cckdumsg (dev, 703, "read error rc=%d offset 0x%" I64_FMT "x len %d: %s\n", rc, (long long)off, len, rc < 0 ? strerror(errno) : "incomplete"); goto cdsk_error; cdsk_write_error: cckdumsg (dev, 704, "write error rc=%d offset 0x%" I64_FMT "x len %d: %s\n", rc, (long long)off, len, rc < 0 ? strerror(errno) : "incomplete"); goto cdsk_error; cdsk_malloc_error: cckdumsg (dev, 705, "malloc error, size=%d: %s\n", len, strerror(errno)); goto cdsk_error; cdsk_calloc_error: cckdumsg (dev, 706, "calloc error, size=%d: %s\n", n*len, strerror(errno)); goto cdsk_error; cdsk_error: rc = -1; goto cdsk_return; } /* end function cckd_chkdsk */ /*------------------------------------------------------------------- * cckd_chkdsk() space table sort *-------------------------------------------------------------------*/ static int cdsk_spctab_sort(const void *a, const void *b) { const SPCTAB *x = a, *y = b; if (x->typ == SPCTAB_NONE) return 1; else if (y->typ == SPCTAB_NONE) return -1; else if (x->typ == SPCTAB_EOF) return 1; else if (y->typ == SPCTAB_EOF) return -1; else if (x->pos < y->pos) return -1; else return 1; } /* end function cdsk_spctab_sort */ /*-------------------------------------------------------------------*/ /* Build free space in the space table */ /*-------------------------------------------------------------------*/ static int cdsk_build_free_space(SPCTAB *spctab, int s) { int i; for (i = 0; i < s; i++) if (spctab[i].typ == SPCTAB_FREE) spctab[i].typ = SPCTAB_NONE; qsort (spctab, s, sizeof(SPCTAB), cdsk_spctab_sort); while (spctab[s-1].typ == SPCTAB_NONE) s--; for (i = 0; spctab[i].typ != SPCTAB_EOF; i++) if (spctab[i].pos + spctab[i].siz < spctab[i+1].pos) { spctab[s].typ = SPCTAB_FREE; spctab[s].val = -1; spctab[s].pos = spctab[i].pos + spctab[i].siz; spctab[s].len = spctab[s].siz = spctab[i+1].pos - spctab[s].pos; s++; } qsort (spctab, s, sizeof(SPCTAB), cdsk_spctab_sort); return s; } /*-------------------------------------------------------------------*/ /* Validate a track image */ /* */ /* If `len' is negative and compression is CCKD_COMPRESS_NONE then */ /* `len' indicates a buffer size containing the track image and the */ /* value returned is the actual track image length */ /*-------------------------------------------------------------------*/ static int cdsk_valid_trk (int trk, BYTE *buf, int heads, int len) { int i; /* Index */ int len2; /* Positive `len' */ int kl, dl; /* Key/Data lengths */ BYTE *bufp; /* Buffer pointer */ int bufl; /* Buffer length */ #ifdef HAVE_LIBZ uLongf zlen; #endif #ifdef CCKD_BZIP2 unsigned int bz2len; #endif #if defined(HAVE_LIBZ) || defined(CCKD_BZIP2) int rc; /* Return code */ BYTE buf2[65536]; /* Uncompressed buffer */ #endif /* Negative len only allowed for comp none */ len2 = len > 0 ? len : -len; if (len2 < CKDDASD_TRKHDR_SIZE + 8) return 0; /* Uncompress the track/block image */ switch (buf[0]) { case CCKD_COMPRESS_NONE: bufp = buf; bufl = len2; break; #ifdef HAVE_LIBZ case CCKD_COMPRESS_ZLIB: if (len < 0) return 0; bufp = (BYTE *)buf2; memcpy (buf2, buf, CKDDASD_TRKHDR_SIZE); zlen = sizeof(buf2) - CKDDASD_TRKHDR_SIZE; rc = uncompress (buf2 + CKDDASD_TRKHDR_SIZE, &zlen, buf + CKDDASD_TRKHDR_SIZE, len - CKDDASD_TRKHDR_SIZE); if (rc != Z_OK) return 0; bufl = (int)zlen + CKDDASD_TRKHDR_SIZE; break; #endif #ifdef CCKD_BZIP2 case CCKD_COMPRESS_BZIP2: if (len < 0) return 0; bufp = (BYTE *)buf2; memcpy (buf2, buf, CKDDASD_TRKHDR_SIZE); bz2len = sizeof(buf2) - CKDDASD_TRKHDR_SIZE; rc = BZ2_bzBuffToBuffDecompress ( (char *)&buf2[CKDDASD_TRKHDR_SIZE], &bz2len, (char *)&buf[CKDDASD_TRKHDR_SIZE], len - CKDDASD_TRKHDR_SIZE, 0, 0); if (rc != BZ_OK) return 0; bufl = (int)bz2len + CKDDASD_TRKHDR_SIZE; break; #endif default: return 0; } /* switch (buf[0]) */ /* fba check */ if (heads == 65536) { if (bufl != CFBA_BLOCK_SIZE + CKDDASD_TRKHDR_SIZE) return 0; else return len > 0 ? len : bufl; } /* Check length */ if (bufl <= 5 + 8 + 8 + 8 + 8) return 0; /* Check ha */ if (fetch_hw(bufp + 1) != trk / heads || fetch_hw(bufp + 3) != trk % heads) return 0; /* Check r0 */ if (fetch_hw(bufp + 1) != fetch_hw(bufp + 5) || fetch_hw(bufp + 3) != fetch_hw(bufp + 7) || bufp[9] != 0 || bufp[10] != 0 || fetch_hw(bufp +11) != 8) return 0; /* Check user records */ for (i = 21; i < bufl - 8; i += 8 + kl + dl) { if (fetch_hw(bufp + i + 2) >= heads || bufp[i + 4] == 0) break; kl = bufp[i + 5]; dl = fetch_hw(bufp + i + 6); } if (len < 0) bufl = i + 8; if (i != bufl - 8 || memcmp(bufp + i, eighthexFF, 8)) return 0; return len > 0 ? len : bufl; } /* end function cdsk_valid_trk */ /*-------------------------------------------------------------------*/ /* Message function */ /*-------------------------------------------------------------------*/ DLL_EXPORT void cckdumsg (DEVBLK *dev, int n, char *format, ...) { CCKDDASD_EXT *cckd; int sfx; int i; char *p; va_list vl; char msg[4096]; cckd = dev->cckd_ext; sfx = cckd ? cckd->sfn : -1; i = sprintf (msg, "HHCCU%3.3d%c ", n, n < 400 ? 'I' : n < 700 ? 'W' : 'E'); if (sfx >= 0) i += sprintf (msg+i, "%4.4X file[%d]: ", dev->devnum, sfx); else { if ((p = strrchr(dev->filename, '/')) == NULL && (p = strrchr(dev->filename, '\\')) == NULL) p = dev->filename; else p++; i += sprintf (msg+i, "%s: ", p); } va_start (vl, format); vsprintf (msg+i, format, vl); va_end (vl); if (dev->batch) fprintf(stdout,"%s",msg); else logmsg("%s",msg); } hercules-3.07/cgibin.c000644 000765 000765 00000120757 11344073445 016363 0ustar00jmaynardjmaynard000000 000000 /* CGIBIN.C (c)Copyright Jan Jaeger, 2002-2010 */ /* HTTP cgi-bin routines */ // $Id: cgibin.c 5645 2010-03-03 14:14:26Z rbowler $ /* This file contains all cgi routines that may be executed on the */ /* server (ie under control of a hercules thread) */ /* */ /* */ /* All cgi-bin routines are identified in the directory at the end */ /* of this file */ /* */ /* */ /* The cgi-bin routines may call the following HTTP service routines */ /* */ /* char *cgi_variable(WEBBLK *webblk, char *name); */ /* This call returns a pointer to the cgi variable requested */ /* or a NULL pointer if the variable is not found */ /* */ /* char *cgi_cookie(WEBBLK *webblk, char *name); */ /* This call returns a pointer to the cookie requested */ /* or a NULL pointer if the cookie is not found */ /* */ /* char *cgi_username(WEBBLK *webblk); */ /* Returns the username for which the user has been authenticated */ /* or NULL if not authenticated (refer to auth/noauth parameter */ /* on the HTTPPORT configuration statement) */ /* */ /* char *cgi_baseurl(WEBBLK *webblk); */ /* Returns the url as requested by the user */ /* */ /* */ /* void html_header(WEBBLK *webblk); */ /* Sets up the standard html header, and includes the */ /* html/header.htmlpart file. */ /* */ /* void html_footer(WEBBLK *webblk); */ /* Sets up the standard html footer, and includes the */ /* html/footer.htmlpart file. */ /* */ /* int html_include(WEBBLK *webblk, char *filename); */ /* Includes an html file */ /* */ /* */ /* Jan Jaeger - 28/03/2002 */ #include "hstdinc.h" #define _CGIBIN_C_ #define _HENGINE_DLL_ #include "hercules.h" #include "devtype.h" #include "opcode.h" #include "httpmisc.h" #if defined(OPTION_HTTP_SERVER) void cgibin_reg_control(WEBBLK *webblk) { int i; REGS *regs; regs = sysblk.regs[sysblk.pcpu]; if (!regs) regs = &sysblk.dummyregs; html_header(webblk); hprintf(webblk->sock, "

Control Registers

\n"); hprintf(webblk->sock, "
\n");
    if(regs->arch_mode != ARCH_900)
        for (i = 0; i < 16; i++)
            hprintf(webblk->sock, "CR%2.2d=%8.8X%s", i, regs->CR_L(i),
                ((i & 0x03) == 0x03) ? "\n" : "\t");
    else
        for (i = 0; i < 16; i++)
            hprintf(webblk->sock, "CR%1.1X=%16.16" I64_FMT "X%s", i,
                (U64)regs->CR_G(i), ((i & 0x03) == 0x03) ? "\n" : " ");

    hprintf(webblk->sock, "
\n"); html_footer(webblk); } void cgibin_reg_general(WEBBLK *webblk) { int i; REGS *regs; regs = sysblk.regs[sysblk.pcpu]; if (!regs) regs = &sysblk.dummyregs; html_header(webblk); hprintf(webblk->sock, "

General Registers

\n"); hprintf(webblk->sock, "
\n");
    if(regs->arch_mode != ARCH_900)
        for (i = 0; i < 16; i++)
            hprintf(webblk->sock, "GR%2.2d=%8.8X%s", i, regs->GR_L(i),
                ((i & 0x03) == 0x03) ? "\n" : "\t");
    else
        for (i = 0; i < 16; i++)
            hprintf(webblk->sock, "GR%1.1X=%16.16" I64_FMT "X%s", i,
                (U64)regs->GR_G(i), ((i & 0x03) == 0x03) ? "\n" : " ");

    hprintf(webblk->sock, "
\n"); html_footer(webblk); } // void copy_psw (REGS *regs, BYTE *addr); void cgibin_psw(WEBBLK *webblk) { REGS *regs; QWORD qword; /* quadword work area */ char *value; int autorefresh=0; int refresh_interval=5; regs = sysblk.regs[sysblk.pcpu]; if (!regs) regs = &sysblk.dummyregs; html_header(webblk); if (cgi_variable(webblk,"autorefresh")) autorefresh = 1; else if (cgi_variable(webblk,"norefresh")) autorefresh = 0; else if (cgi_variable(webblk,"refresh")) autorefresh = 1; if ((value = cgi_variable(webblk,"refresh_interval"))) refresh_interval = atoi(value); hprintf(webblk->sock, "

Program Status Word

\n"); hprintf(webblk->sock, "
\n"); if (!autorefresh) { hprintf(webblk->sock, "\n"); hprintf(webblk->sock, "Refresh Interval: "); hprintf(webblk->sock, "\n", refresh_interval); } else { hprintf(webblk->sock, "\n"); hprintf(webblk->sock, "Refresh Interval: %d\n", refresh_interval); hprintf(webblk->sock, "\n",refresh_interval); } hprintf(webblk->sock, "
\n"); hprintf(webblk->sock, "

\n"); if( regs->arch_mode != ARCH_900 ) { copy_psw (regs, qword); hprintf(webblk->sock, "PSW=%2.2X%2.2X%2.2X%2.2X %2.2X%2.2X%2.2X%2.2X\n", qword[0], qword[1], qword[2], qword[3], qword[4], qword[5], qword[6], qword[7]); } else { copy_psw (regs, qword); hprintf(webblk->sock, "PSW=%2.2X%2.2X%2.2X%2.2X %2.2X%2.2X%2.2X%2.2X " "%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X\n", qword[0], qword[1], qword[2], qword[3], qword[4], qword[5], qword[6], qword[7], qword[8], qword[9], qword[10], qword[11], qword[12], qword[13], qword[14], qword[15]); } if (autorefresh) { /* JavaScript to cause automatic page refresh */ hprintf(webblk->sock, "\n"); } html_footer(webblk); } void cgibin_syslog(WEBBLK *webblk) { int num_bytes; int logbuf_idx; char *logbuf_ptr; char *command; char *value; int autorefresh = 0; int refresh_interval = 5; int msgcount = 22; if ((command = cgi_variable(webblk,"command"))) { panel_command(command); // Wait a bit before proceeding in case // the command issues a lot of messages usleep(50000); } if((value = cgi_variable(webblk,"msgcount"))) msgcount = atoi(value); else if((value = cgi_cookie(webblk,"msgcount"))) msgcount = atoi(value); if ((value = cgi_variable(webblk,"refresh_interval"))) refresh_interval = atoi(value); if (cgi_variable(webblk,"autorefresh")) autorefresh = 1; else if (cgi_variable(webblk,"norefresh")) autorefresh = 0; else if (cgi_variable(webblk,"refresh")) autorefresh = 1; html_header(webblk); hprintf(webblk->sock,"\n", msgcount); hprintf(webblk->sock, "

Hercules System Log

\n"); hprintf(webblk->sock, "
\n");

    // Get the index to our desired starting message...

    logbuf_idx = msgcount ? log_line( msgcount ) : -1;

    // Now read the logfile starting at that index. The return
    // value is the total #of bytes of messages data there is.

    if ( (num_bytes = log_read( &logbuf_ptr, &logbuf_idx, LOG_NOBLOCK )) > 0 )
    {
        // Copy the message data to a work buffer for processing.
        // This is to allow for the possibility, however remote,
        // that the logfile buffer actually wraps around and over-
        // lays the message data we were going to display (which
        // could happen if there's a sudden flood of messages)

        int   sav_bytes  =         num_bytes;
        char *wrk_bufptr = malloc( num_bytes );

        if ( wrk_bufptr ) strncpy( wrk_bufptr,  logbuf_ptr, num_bytes );
        else                       wrk_bufptr = logbuf_ptr;

        // We need to convert certain characters that might
        // possibly be erroneously interpretted as HTML code

#define  AMP_LT    "<"       // (HTML code for '<')
#define  AMP_GT    ">"       // (HTML code for '>')
#define  AMP_AMP   "&"      // (HTML code for '&')

        while ( num_bytes-- )
        {
            switch ( *wrk_bufptr )
            {
            case '<':
                hwrite( webblk->sock, AMP_LT     , sizeof(AMP_LT) );
                break;
            case '>':
                hwrite( webblk->sock, AMP_GT     , sizeof(AMP_GT) );
                break;
            case '&':
                hwrite( webblk->sock, AMP_AMP    , sizeof(AMP_AMP));
                break;
            default:
                hwrite( webblk->sock, wrk_bufptr , 1              );
                break;
            }

            wrk_bufptr++;
        }

        // (free our work buffer if it's really ours)

        if ( ( wrk_bufptr -= sav_bytes ) != logbuf_ptr )
            free( wrk_bufptr );
    }

    hprintf(webblk->sock, "
\n"); hprintf(webblk->sock, "
Command:\n"); hprintf(webblk->sock, "\n"); hprintf(webblk->sock, "\n"); hprintf(webblk->sock, "\n",autorefresh ? "auto" : "no"); hprintf(webblk->sock, "\n",refresh_interval); hprintf(webblk->sock, "\n",msgcount); hprintf(webblk->sock, "
\n
\n"); hprintf(webblk->sock, "\n"); hprintf(webblk->sock, "
\n"); if(!autorefresh) { hprintf(webblk->sock, "\n"); hprintf(webblk->sock, "Refresh Interval: "); hprintf(webblk->sock, "\n", refresh_interval); } else { hprintf(webblk->sock, "\n"); hprintf(webblk->sock, "\n",refresh_interval); hprintf(webblk->sock, " Refresh Interval: %2d \n", refresh_interval); } hprintf(webblk->sock, "\n",msgcount); hprintf(webblk->sock, "
\n"); hprintf(webblk->sock, "
\n"); hprintf(webblk->sock, "Only show last "); hprintf(webblk->sock, "",msgcount); hprintf(webblk->sock, " lines (zero for all loglines)\n"); hprintf(webblk->sock, "\n",autorefresh ? "auto" : "no"); hprintf(webblk->sock, "\n",refresh_interval); hprintf(webblk->sock, "
\n"); if (autorefresh) { /* JavaScript to cause automatic page refresh */ hprintf(webblk->sock, "\n"); } html_footer(webblk); } void cgibin_debug_registers(WEBBLK *webblk) { int i, cpu = 0; int select_gr, select_cr, select_ar; char *value; REGS *regs; if((value = cgi_variable(webblk,"cpu"))) cpu = atoi(value); if((value = cgi_variable(webblk,"select_gr")) && *value == 'S') select_gr = 1; else select_gr = 0; if((value = cgi_variable(webblk,"select_cr")) && *value == 'S') select_cr = 1; else select_cr = 0; if((value = cgi_variable(webblk,"select_ar")) && *value == 'S') select_ar = 1; else select_ar = 0; /* Validate cpu number */ if (cpu < 0 || cpu >= MAX_CPU || !IS_CPU_ONLINE(cpu)) for (cpu = 0; cpu < MAX_CPU; cpu++) if(IS_CPU_ONLINE(cpu)) break; if(cpu < MAX_CPU) regs = sysblk.regs[cpu]; else regs = sysblk.regs[sysblk.pcpu]; if (!regs) regs = &sysblk.dummyregs; if((value = cgi_variable(webblk,"alter_gr")) && *value == 'A') { for(i = 0; i < 16; i++) { char regname[16]; sprintf(regname,"alter_gr%d",i); if((value = cgi_variable(webblk,regname))) { if(regs->arch_mode != ARCH_900) sscanf(value,"%"I32_FMT"x",&(regs->GR_L(i))); else sscanf(value,"%"I64_FMT"x",&(regs->GR_G(i))); } } } if((value = cgi_variable(webblk,"alter_cr")) && *value == 'A') { for(i = 0; i < 16; i++) { char regname[16]; sprintf(regname,"alter_cr%d",i); if((value = cgi_variable(webblk,regname))) { if(regs->arch_mode != ARCH_900) sscanf(value,"%"I32_FMT"x",&(regs->CR_L(i))); else sscanf(value,"%"I64_FMT"x",&(regs->CR_G(i))); } } } if((value = cgi_variable(webblk,"alter_ar")) && *value == 'A') { for(i = 0; i < 16; i++) { char regname[16]; sprintf(regname,"alter_ar%d",i); if((value = cgi_variable(webblk,regname))) sscanf(value,"%x",&(regs->AR(i))); } } html_header(webblk); hprintf(webblk->sock,"
\n" "\n" "\n" "\n" "\n" "\n" "\n", cpu, select_gr?'S':'H',select_cr?'S':'H',select_ar?'S':'H'); hprintf(webblk->sock,"Mode: %s\n",get_arch_mode_string(regs)); hprintf(webblk->sock,"
\n"); if(!select_gr) { hprintf(webblk->sock,"
\n" "\n" "\n" "\n" "\n" "
\n",cpu,select_cr?'S':'H',select_ar?'S':'H'); } else { hprintf(webblk->sock,"
\n" "\n" "\n" "\n" "\n" "
\n",cpu,select_cr?'S':'H',select_ar?'S':'H'); hprintf(webblk->sock,"
\n" "\n"); for(i = 0; i < 16; i++) { if(regs->arch_mode != ARCH_900) hprintf(webblk->sock,"%s\n%s", (i&3)==0?"\n":"",i,i,regs->GR_L(i),((i&3)==3)?"\n":""); else hprintf(webblk->sock,"%s\n%s", (i&3)==0?"\n":"",i,i,(U64)regs->GR_G(i),((i&3)==3)?"\n":""); } hprintf(webblk->sock,"
GR%d
GR%d
\n" "\n" "\n" "\n" "\n" "\n" "\n" "
\n",cpu,select_cr?'S':'H',select_ar?'S':'H'); } if(!select_cr) { hprintf(webblk->sock,"
\n" "\n" "\n" "\n" "\n" "
\n",cpu,select_gr?'S':'H',select_ar?'S':'H'); } else { hprintf(webblk->sock,"
\n" "\n" "\n" "\n" "\n" "
\n",cpu,select_gr?'S':'H',select_ar?'S':'H'); hprintf(webblk->sock,"
\n" "\n"); for(i = 0; i < 16; i++) { if(regs->arch_mode != ARCH_900) hprintf(webblk->sock,"%s\n%s", (i&3)==0?"\n":"",i,i,regs->CR_L(i),((i&3)==3)?"\n":""); else hprintf(webblk->sock,"%s\n%s", (i&3)==0?"\n":"",i,i,(U64)regs->CR_G(i),((i&3)==3)?"\n":""); } hprintf(webblk->sock,"
CR%d
CR%d
\n" "\n" "\n" "\n" "\n" "\n" "\n" "
\n",cpu,select_gr?'S':'H',select_ar?'S':'H'); } if(regs->arch_mode != ARCH_370) { if(!select_ar) { hprintf(webblk->sock,"
\n" "\n" "\n" "\n" "\n" "
\n",cpu,select_gr?'S':'H',select_cr?'S':'H'); } else { hprintf(webblk->sock,"
\n" "\n" "\n" "\n" "\n" "
\n",cpu,select_gr?'S':'H',select_cr?'S':'H'); hprintf(webblk->sock,"
\n" "\n"); for(i = 0; i < 16; i++) { hprintf(webblk->sock,"%s\n%s", (i&3)==0?"\n":"",i,i,regs->AR(i),((i&3)==3)?"\n":""); } hprintf(webblk->sock,"
AR%d
\n" "\n" "\n" "\n" "\n" "\n" "\n" "
\n",cpu,select_gr?'S':'H',select_cr?'S':'H'); } } html_footer(webblk); } void cgibin_debug_storage(WEBBLK *webblk) { int i, j; char *value; U32 addr = 0; /* INCOMPLETE * no storage alter * no storage type (abs/real/prim virt/sec virt/access reg virt) * no cpu selection for storage other then abs */ if((value = cgi_variable(webblk,"alter_a0"))) sscanf(value,"%x",&addr); addr &= ~0x0F; html_header(webblk); hprintf(webblk->sock,"
\n" "\n"); if(addr > sysblk.mainsize || (addr + 128) > sysblk.mainsize) addr = sysblk.mainsize - 128; for(i = 0; i < 128;) { if(i == 0) hprintf(webblk->sock,"\n" "\n" "\n", i + addr, i + addr); else hprintf(webblk->sock,"\n" "\n" "\n", i + addr); for(j = 0; j < 4; i += 4, j++) { U32 m; FETCH_FW(m,sysblk.mainstor + i + addr); hprintf(webblk->sock,"\n",i,m); } hprintf(webblk->sock,"\n"); } hprintf(webblk->sock,"
" "
%8.8X
\n" "
\n"); html_footer(webblk); } void cgibin_ipl(WEBBLK *webblk) { int i; char *value; DEVBLK *dev; U16 ipldev; int iplcpu; U32 doipl; html_header(webblk); hprintf(webblk->sock,"

Perform Initial Program Load

\n"); if(cgi_variable(webblk,"doipl")) doipl = 1; else doipl = 0; if((value = cgi_variable(webblk,"device"))) sscanf(value,"%hx",&ipldev); else ipldev = sysblk.ipldev; if((value = cgi_variable(webblk,"cpu"))) sscanf(value,"%x",&iplcpu); else iplcpu = sysblk.iplcpu; if((value = cgi_variable(webblk,"loadparm"))) set_loadparm(value); /* Validate CPU number */ if(iplcpu >= MAX_CPU) doipl = 0; if(!doipl) { /* Present IPL parameters */ hprintf(webblk->sock,"
\n" "\n" "\n"); hprintf(webblk->sock,"Loadparm:\n", str_loadparm()); hprintf(webblk->sock,"\n" "
\n"); } else { OBTAIN_INTLOCK(NULL); /* Perform IPL function */ if( load_ipl(0, ipldev, iplcpu,0) ) { hprintf(webblk->sock,"

IPL failed, see the " "system log " "for details

\n"); } else { hprintf(webblk->sock,"

IPL completed

\n"); } RELEASE_INTLOCK(NULL); } html_footer(webblk); } void cgibin_debug_device_list(WEBBLK *webblk) { DEVBLK *dev; char *class; html_header(webblk); hprintf(webblk->sock,"

Attached Device List

\n" "\n" "" "" "" "" "\n"); for(dev = sysblk.firstdev; dev; dev = dev->nextdev) if(dev->pmcw.flag5 & PMCW5_V) { (dev->hnd->query)(dev, &class, 0, NULL); hprintf(webblk->sock,"" "" "" "" "" "" "\n", dev->devnum, dev->subchan,dev->subchan, class, dev->devtype, (dev->fd > 2 ? "open " : ""), (dev->busy ? "busy " : ""), (IOPENDING(dev) ? "pending " : "")); } hprintf(webblk->sock,"
NumberSubchannelClassTypeStatus
%4.4X%4.4X%s%4.4X%s%s%s
\n"); html_footer(webblk); } void cgibin_debug_device_detail(WEBBLK *webblk) { DEVBLK *sel, *dev = NULL; char *value; int subchan; html_header(webblk); if((value = cgi_variable(webblk,"subchan")) && sscanf(value,"%x",&subchan) == 1) for(dev = sysblk.firstdev; dev; dev = dev->nextdev) if(dev->subchan == subchan) break; hprintf(webblk->sock,"

Subchannel Details

\n"); hprintf(webblk->sock,"
\n" "\n" "\n" "
\n"); if(dev) { hprintf(webblk->sock,"\n" "\n"); hprintf(webblk->sock,"\n"); hprintf(webblk->sock,"\n", dev->pmcw.intparm[0], dev->pmcw.intparm[1], dev->pmcw.intparm[2], dev->pmcw.intparm[3]); hprintf(webblk->sock,"" "" "" "" "" "" "" "" "" "" "" "\n"); hprintf(webblk->sock,"" "" "" "" "" "" "" "" "" "" "" "\n", ((dev->pmcw.flag4 & PMCW4_Q) >> 7), ((dev->pmcw.flag4 & PMCW4_ISC) >> 3), (dev->pmcw.flag4 & 1), ((dev->pmcw.flag5 >> 7) & 1), ((dev->pmcw.flag5 >> 6) & 1), ((dev->pmcw.flag5 >> 5) & 1), ((dev->pmcw.flag5 >> 4) & 1), ((dev->pmcw.flag5 >> 3) & 1), ((dev->pmcw.flag5 >> 2) & 1), ((dev->pmcw.flag5 >> 1) & 1), (dev->pmcw.flag5 & 1), dev->pmcw.devnum[0], dev->pmcw.devnum[1]); hprintf(webblk->sock,"" "" "" "\n"); hprintf(webblk->sock,"" "" "" "\n", dev->pmcw.lpm, dev->pmcw.pnom, dev->pmcw.lpum, dev->pmcw.pim); hprintf(webblk->sock,"" "" "\n"); hprintf(webblk->sock,"" "" "\n", dev->pmcw.mbi[0], dev->pmcw.mbi[1], dev->pmcw.pom, dev->pmcw.pam); hprintf(webblk->sock,"" "" "" "\n"); hprintf(webblk->sock,"" "" "" "\n", dev->pmcw.chpid[0], dev->pmcw.chpid[1], dev->pmcw.chpid[2], dev->pmcw.chpid[3]); hprintf(webblk->sock,"" "" "" "\n"); hprintf(webblk->sock,"" "" "" "\n", dev->pmcw.chpid[4], dev->pmcw.chpid[5], dev->pmcw.chpid[6], dev->pmcw.chpid[7]); hprintf(webblk->sock,"" "" "" "" "" "" "\n"); hprintf(webblk->sock,"" "" "" "" "" "" "\n", dev->pmcw.zone, (dev->pmcw.flag25 & PMCW25_VISC), (dev->pmcw.flag27 & PMCW27_I) >> 7, (dev->pmcw.flag27 & PMCW27_S)); hprintf(webblk->sock,"
" "

Path Management Control Word

" "
Interruption Parameter
%2.2X%2.2X%2.2X%2.2X
Q0ISC00AELMMMDTVDEVNUM
%d%d%d%d%d%d%d%d%d%d%d%2.2X%2.2X
LPMPNOMLPUMPIM
%2.2X%2.2X%2.2X%2.2X
MBIPOMPAM
%2.2X%2.2X%2.2X%2.2X
CHPID=0CHPID=1CHPID=2CHPID=3
%2.2X%2.2X%2.2X%2.2X
CHPID=4CHPID=5CHPID=6CHPID=7
%2.2X%2.2X%2.2X%2.2X
ZONE00000VISC00000000I000000S
%2.2X%d%d%d
\n"); } html_footer(webblk); } void cgibin_debug_misc(WEBBLK *webblk) { int zone; html_header(webblk); hprintf(webblk->sock,"

Miscellaneous Registers

\n"); hprintf(webblk->sock,"\n" "\n"); hprintf(webblk->sock,"" "" "" "" "" "" "\n"); for(zone = 0; zone < FEATURE_SIE_MAXZONES; zone++) { hprintf(webblk->sock,"" "" "" "" "" "" "\n", zone, #if defined(_FEATURE_SIE) (U32)sysblk.zpb[zone].mso << 20, ((U32)sysblk.zpb[zone].msl << 20) | 0xFFFFF, (U32)sysblk.zpb[zone].eso << 20, ((U32)sysblk.zpb[zone].esl << 20) | 0xFFFFF, (U32)sysblk.zpb[zone].mbo, sysblk.zpb[zone].mbk #else 0, 0, 0, 0, 0, 0 #endif ); } hprintf(webblk->sock,"
" "

Zone related Registers

" "
ZoneCS OriginCS LimitES OriginES LimitMeasurement BlockKey
%2.2X%8.8X%8.8X%8.8X%8.8X%8.8X%2.2X
\n"); hprintf(webblk->sock,"\n" "\n"); hprintf(webblk->sock,"" "\n"); hprintf(webblk->sock,"" "\n", (U32)sysblk.mbo, sysblk.mbk); hprintf(webblk->sock,"
" "

Alternate Measurement

" "
Measurement BlockKey
%8.8X%2.2X
\n"); hprintf(webblk->sock,"\n" "\n"); hprintf(webblk->sock,"\n", (U32)sysblk.addrlimval); hprintf(webblk->sock,"
" "

Address Limit Register

" "
%8.8X
\n"); html_footer(webblk); } void cgibin_configure_cpu(WEBBLK *webblk) { int i,j; html_header(webblk); hprintf(webblk->sock,"

Configure CPU

\n"); for(i = 0; i < MAX_CPU; i++) { char cpuname[8], *cpustate; int cpuonline = -1; sprintf(cpuname,"cpu%d",i); if((cpustate = cgi_variable(webblk,cpuname))) sscanf(cpustate,"%d",&cpuonline); OBTAIN_INTLOCK(NULL); switch(cpuonline) { case 0: if(IS_CPU_ONLINE(i)) deconfigure_cpu(i); break; case 1: if(!IS_CPU_ONLINE(i)) configure_cpu(i); break; } RELEASE_INTLOCK(NULL); } for(i = 0; i < MAX_CPU; i++) { hprintf(webblk->sock,"

CPU%4.4X\n" "

\n" "\n" "\n" "
\n"); } html_footer(webblk); } void cgibin_debug_version_info(WEBBLK *webblk) { html_header(webblk); hprintf(webblk->sock,"

Hercules Version Information

\n" "
\n");
    display_version_2(NULL,"Hercules HTTP Server ", TRUE,webblk->sock);
    hprintf(webblk->sock,"
\n"); html_footer(webblk); } #if defined(OPTION_MIPS_COUNTING) /* contributed by Tim Pinkawa [timpinkawa@gmail.com] */ void cgibin_xml_rates_info(WEBBLK *webblk) { hprintf(webblk->sock,"Expires: 0\n"); hprintf(webblk->sock,"Content-type: text/xml;\n\n"); /* XML document */ hprintf(webblk->sock,"\n"); hprintf(webblk->sock,"\n"); hprintf(webblk->sock,"\t%d\n", sysblk.arch_mode); hprintf(webblk->sock,"\t%.1d.%.2d\n", sysblk.mipsrate / 1000000, (sysblk.mipsrate % 1000000) / 10000); hprintf(webblk->sock,"\t%d\n", sysblk.siosrate); hprintf(webblk->sock,"\n"); } #endif /*defined(OPTION_MIPS_COUNTING)*/ /* The following table is the cgi-bin directory, which */ /* associates directory filenames with cgibin routines */ CGITAB cgidir[] = { { "tasks/syslog", &cgibin_syslog }, { "tasks/ipl", &cgibin_ipl }, { "configure/cpu", &cgibin_configure_cpu }, { "debug/registers", &cgibin_debug_registers }, { "debug/storage", &cgibin_debug_storage }, { "debug/misc", &cgibin_debug_misc }, { "debug/version_info", &cgibin_debug_version_info }, { "debug/device/list", &cgibin_debug_device_list }, { "debug/device/detail", &cgibin_debug_device_detail }, { "registers/general", &cgibin_reg_general }, { "registers/control", &cgibin_reg_control }, { "registers/psw", &cgibin_psw }, #if defined(OPTION_MIPS_COUNTING) { "xml/rates", &cgibin_xml_rates_info }, #endif /*defined(OPTION_MIPS_COUNTING)*/ { NULL, NULL } }; #endif /*defined(OPTION_HTTP_SERVER)*/ hercules-3.07/CHANGES000644 000765 000765 00000503240 11337307610 015743 0ustar00jmaynardjmaynard000000 000000 16 Feb 2010 Fix Conditional SSKE failing with Storage Key Assist - Ivan Warren 04 Feb 2010 - Fix building on 64-bit Macs under Snow Leopard - Jay Maynard 16 Dec 2009 Fix S/370 SIE guests - Ivan Warren 14 Jun 2009 uptime command - Fish 14 Jun 2009 Support expanded storage sizes exceeding 4GB (64-bit only) - Roger Bowler 05 Jun 2009 Visual Studio 2008 + makefile.bat x64 & runjobs support - Fish 02 Jun 2009 Miscellaneous minor hetget fixes - kerravon86 by Fish 02 Jun 2009 Configuration Topology Facility support for PTF and STSI - Fish 01 Jun 2009 socket printer support - Fish 01 Jun 2009 New TT32 pre-v3.3 header and stats - Fish 01 Jun 2009 Fix OMA (TDF) unloaded tape open bug - kerravon86 by Fish 01 Jun 2009 Support for non-default Windows tape device names - Fish 01 Jun 2009 Fix tape file extension neutrality special case - Fish 15 May 2009 Add 3705 device - Jay Maynard, for Max H. Parke 13 May 2009 Add TTY and 2741 support to 2703 - Jay Maynard, for Max H. Parke 03 May 2009 Disable SENSE ID CCW for 2311, 2314 subject to LEGACYSENSEID setting, change 2314 control unit from 2841 to 2314 - Kevin Leonard 27 Apr 2009 Fix scsitape open hang on *nix causing Machine Check - Fish by rbowler 19 Apr 2009 MAXCPU configuration statement - Roger Bowler 19 Apr 2009 CMPSC expand works optimized with absolute addresses - Bernard 17 Mar 2009 Changed "notrunc" to "noclear" and fix compile error on MSVC - Jay Maynard 15 Mar 2009 Added "notrunc" option to printer and punch devices to not truncate output file uopn opening - Jay Maynard 11 Mar 2009 CMPSC expand output cache implementation - Bernard van der Helm 01 Mar 2009 Complete DIAGNOSE X'24' and Implement DIAGNOSE X'210' - Harold Grovesteen 27 Feb 2009 >70% better CMPSC expand performance - Bernard van der Helm 22 Feb 2009 30% better CMPSC expand performance - Bernard van der Helm 20 Feb 2009 Implement VM DIAGNOSE X'260' - Harold Grovesteen 18 Feb 2009 Turbo CMPSC expand - >15% better performance - Bernard van der Helm 08 Feb 2009 Ability to build 64-bit executables for Windows - Roger Bowler 07 Feb 2009 MVCL & MVCLE now obey MP Concurrent Block Consistency rules - Ivan Warren 07 Feb 2009 Prevent restart on special engines - Bernard van der Helm 04 Feb 2009 Ensure unaligned LM/STM/LMG/STMG work on aligned constrained hosts - Ivan Warren 03 Feb 2009 Fix TPROT under SIE problem reported by 'pat' - Ivan Warren 23 Jan 2009 copyright notice - Bernard van der Helm 17 Jan 2009 Fix change recording on page crossing first op of MVC - Reported by Greg Price 08 Jan 2009 Cosmetic improvement to CPU type display on startup - Jay Maynard 07 Jan 2009 Remove --enable-universal-binary configure option; doesn't work on Leopard due to libtool compiler options - Jay Maynard 07 Jan 2009 Preliminary changes for 3.06 - Jay Maynard 07 Jan 2009 Added x86_64 assembler byteswap assists - Jay Maynard 07 Jan 2009 msghld command with clear option - Bernard van der Helm 07 Jan 2009 msghldsec command - Bernard van der Helm 02 Jan 2009 Integrated 3270 console fixes - Jan Jaeger 02 Jan 2009 DVD-RAM IPL and RAMSAVE support - Jan Jaeger 02 Jan 2009 Optional ECHO/NOECHO to Diag8cmd statement - Ivan Warren 31 Dec 2008 Integrated 3270 (SYSG) console - Roger Bowler 30 Dec 2008 Allow $(LPARNAME) in herclogo file - Roger Bowler 23 Dec 2008 Allow symbol substitution in OAT files - Roger Bowler 22 Dec 2008 Implement Compare And Swap And Store Facility 2 - Ivan Warren 21 Dec 2008 Diag 224 fix - Ivan Warren 21 Dec 2008 Various SERVC READ_xxx_INFO fixes for specialty engines - Ivan Warren 08 Dec 2008 Fix Issue with ESA Guest on z/Arch and >2GB Storage - Ivan Warren 06 Dec 2008 Enable STFLE in ESA/390 mode - Ivan Warren 04 Dec 2008 Add ability to configure group name in --enable-setuid-hercifc= - Roger Bowler 02 Dec 2008 Support for PANTITLE when console is an xterm window - Roger Bowler 24 Nov 2008 Add processor type IL for IFL on engines statement - Jan Jaeger 02 Nov 2008 Correction to dasdtab entries for 3375 and 3380 - Roger Bowler 01 Nov 2008 Fix tapedev gettapetype_bydata function for HET/AWS tapes that start with a tapemark -- Liam Cold [liamcold@yahoo.com] by Fish 26 Oct 2008 Store_is within CMPSC will zero the remaining bits in the working byte, just like other famous manufacturers will do. All former generated compressed code will expand correctly, don't worry!! But their can be a difference in the compressed output. (This is the case when bits are on, but those are the unused bits after the last index symbol). - Bernard van der Helm 24 Oct 2008 Fix RC file not processed nor HAO thread engaged if -d daemon mode - Fish 11 Oct 2008 Fix MSVC build failure when 'rebase' utility doesn't exist - Fish 07 Sep 2008 Fix zero ilc problem after branch trace - Greg 04 Sep 2008 Fix 64-bit length problem in cdsk_valid_trk - Tony Harminc by Greg 29 Aug 2008 Panel display extended cursor handling (Windows only) - Fish 29 Aug 2008 Fix message-keep logic (sticky/held messages) - Fish 29 Aug 2008 Fix some New Panel data input painting issues - Fish 23 Aug 2008 Implemented sticky and held messages completed - Bernard van der Helm 22 Aug 2008 Fix TOD clock race condition identified by Fred Feucht (fredfeucht) - by Marcin Cieslak [saper@system.pl] - Fish 21 Aug 2008 Fix i/o-interrupt-queue race condition - Fish 19 Aug 2008 Init LCS interface ASAP to fix wrong MAC being used - Fish 13 Aug 2008 Fix bad guest IA after host interrupt during branch trace - Greg 04 Aug 2008 DIAG308 function codes (still incomplete) - Roger Bowler 02 Aug 2008 Implement SCP message colors - Bernard van der Helm 29 Jul 2008 Fix buffer mgmt bug in hao_thread causing garbage - Fish 24 Jul 2008 Implementation of cmdtgt version 2 - Bernard van der Helm 20 Jul 2008 Implementation of cmdtgt command - Bernard van der Helm 18 Jul 2008 Fix PSF order 18 suborder 01 PSF and SSD length - Fish 17 Jul 2008 Fix LCS write FCS (Frame Check Sequence) and other bugs - Fish 16 Jul 2008 Increase time-interval accuracy to 1ms for Windows build - Fish 10 Jul 2008 panel support for scrolling up/down one line - Fish 08 Jul 2008 AUTOMOUNT redesign: support +allowed/-disallowed dirs and create associated 'automount' panel command - Fish 22 Jun 2008 Fix tape messages print format bug causing crash - Fish 28 May 2008 AUTOMOUNT fixed and enhanced so it actually works now - Fish 28 May 2008 Misleading VTAPE support renamed to AUTOMOUNT instead - Fish 24 May 2008 VTAPE automount support (CCW 0x4B + 0xE4) - Fish 22 May 2008 Attempt to fix my *nix SCSI tape BSR over tapemark bug identified by Bob Schneider [bschneider@pingdata.net] - Fish 22 May 2008 Tape file extension neutrality support - Fish 22 May 2008 Flex FakeTape support - Fish 22 May 2008 Fix read timeout bug in LCS logic - Fish 19 May 2008 PSF order 18 suborders (0E,41) and order 1D by Jacob Dekel - Roger Bowler 04 May 2008 Fix CGDR,CGXR to handle values exceeding 2G - Roger Bowler 25 Apr 2008 CGER result incorrect for values over 2G - Roger Bowler 22 Apr 2008 Correction to CXGR instruction - Roger Bowler 21 Apr 2008 CEGR result incorrect if source exceeds 6 digits - Roger Bowler 20 Apr 2008 CDGR result incorrect if source exceeds 14 digits - Roger Bowler 18 Apr 2008 Fix incorrect results from THDER,THDR instructions - Roger Bowler 16 Apr 2008 Fix condition code in LCEBR,LCDBR,LCXBR instructions - Roger Bowler 16 Apr 2008 Fix FIEBR,FIDBR,FIXBR to respect BFP rounding mode - Roger Bowler 08 Apr 2008 Add execute relative long instruction - Bernard van der Helm 31 Mar 2008 Fix SCSI tape i/o performance: now 10x faster! - Fish 30 Mar 2008 Fix SCSI tape EOV (end of volume) processing - Fish 29 Mar 2008 More complete/extensive 3490/3590 tape support - Fish 28 Mar 2008 Fix incorrect registers when cc=1 for TRTE,TRTRE - Roger Bowler 28 Mar 2008 Add generic, readblkid, locateblk tape media handler vectors - Fish 28 Mar 2008 SCSI --blkid-24 option - Fish 23 Mar 2008 Fix incorrect bit selection for RNSBG,RISBG,ROSBG,RXSBG - Roger Bowler 23 Mar 2008 Move With Optional Specifications Facility (MVCOS) - Roger Bowler 13 Mar 2008 Return Byte Mpx for Chan 0 according to GA22-7000-4 - Ivan Warren 12 Mar 2008 Fix residual read-only setting for tape device - Kevin Leonard 12 Mar 2008 Fix store operation of ASI, AGSI, ALSI and AGLSI - Jan Jaeger 08 Mar 2008 General Instructions Extension Facility - Roger Bowler 07 Mar 2008 Add pri, sec, home options [P|S|H] to "v" command - Paul Leisy 05 Mar 2008 Fix PLO fc=3 fc=19 and qword alignment chks - Paul Leisy 04 Mar 2008 Fix CFC cond code - fetch right operand size - Paul Leisy 04 Mar 2008 LEGACYSENSEID config stmt added - see hercconf.html - Ivan Warren 03 Mar 2008 Fix BSM/BASSM mode switch trace - Paul Leisy 02 Mar 2008 re-disable SenseID on 8809,3410,3420 (breaks MTS) - Ivan Warren 29 Feb 2008 Fix TRAP in z/arch mode - Paul Leisy 29 Feb 2008 Added feature parsing_enhancement_facility - Bernard 28 Feb 2008 Fix RP in z/arch mode and mode switch trace - Paul Leisy 27 Feb 2008 Added feature message_security_assist_extension_2 - Bernard 22 Feb 2008 Fix BSA pic06 in z/arch mode - Paul Leisy 20 Feb 2008 Fix BSA pic06/05 and branch to odd addrs pic06 - Paul Leisy 17 Feb 2008 Enable Posix 1003.1e capabilities to restrict setuid-0 programs to just the necessary privileges - Ivan Warren 15 Feb 2008 Fix PC, RP pic13, STCKE byte 0 and two PER bugs - Paul Leisy 12 Feb 2008 Fix 3880 SNSID length (thanks De!) - Greg 12 Feb 2008 Fixes for SPKA, BASR, TBEDR, PR - Paul Leisy 12 Feb 2008 dyngui tweaks: new def devlist fmt, new debug_cd_cmd hook - Fish 11 Feb 2008 Fixed intermediate errors cmpsc - Bernard 07 Feb 2008 Solaris build support by Jeff Savit - Roger Bowler 24 Jan 2008 Fix invalidate_tlbe processing - Paul Leisy by Greg 23 Jan 2008 Fix and optimize TR instruction - Greg 23 Jan 2008 Modifications for VS9 C++ 2008 Express by Charlie Brint - Roger Bowler 21 Jan 2008 Activate ETF3 and ETF2/ETF3-Enhancements in ESA/390 mode - Roger Bowler 21 Jan 2008 Permit Extended-Translation-Facility-3 to be activated in S/370 and ESA/390 modes - Roger Bowler 16 Jan 2008 Data exception for only UNPRECEDED nonzero bit34 ece entries - Fish 14 Jan 2008 Additional ISO-8859-1 to European EBCDIC codepages - Roger Bowler 11 Jan 2008 new 'ctc' command to enable/disable debug option on demand - Fish 03 Jan 2008 sf commands update - Greg Smith 01 Jan 2008 Data exception on nonzero bit34 in ece entry - Bernard van der Helm 31 Dec 2007 Data exceptions on fetching ece, cce and sd1 - Bernard van der Helm 31 Dec 2007 Data excep in CMPSC expansion psl and cls = 0 - Bernard van der Helm 29 Dec 2007 Some errors in UTF translation - Bernard van der Helm 29 Dec 2007 Tweak OPTION_MIPS_COUNTING tweak to prevent crash - Fish 24 Dec 2007 Compression check output, input swapped to input, output - Bernard van der Helm 11 Dec 2007 Enable SENSE ID CCW for 2703,3410,3420 10 Dec 2007 Tweaks to OPTION_MIPS_COUNTING processing - Greg 02 Dec 2007 Permit Extended-Translation-Facility-2 to be activated in S/370 mode - Roger Bowler 02 Dec 2007 Enable B9xx,EBxx opcodes in S/370 mode for ETF2 - Roger Bowler 02 Dec 2007 Permit Extended-Translation facility to be activated in S/370 mode - Roger Bowler 02 Dec 2007 Permit Compare-and-Move-Extended facility to be activated in S/370 mode - Roger Bowler 01 Dec 2007 Fix cckdcdsk/cckdcomp/cckdutil no message o/p issue - Fish 30 Nov 2007 Change all references to conmicro.cx to hercules-390.org - Jay Maynard 30 Nov 2007 Permit String-Instruction facility to be activated in S/370 mode - Roger Bowler 28 Nov 2007 Allow ALLOW DATA CHECK to precede LOAD UCS AND FOLD on 1403 for TSS/370 - Jay Maynard 22 Nov 2007 Store Doubleword Monitor Code for z/Arch on succesful MC - Ivan Warren 20 Nov 2007 LRE support (try #1) - Greg 18 Nov 2007 Activate Message-Security-Assist-Extension-1 facility in ESA/390 - Roger Bowler 18 Nov 2007 Permit Immediate-and-Relative facility to be activated in S/370 mode - Roger Bowler 16 Nov 2007 Add HFP-multiply-add/subtract facility to ESA/390 - Roger Bowler 15 Nov 2007 Correct PIC6 when loading DRM bits into FPC - Roger Bowler 15 Nov 2007 Correct CPSDR instruction - Roger Bowler 15 Nov 2007 Correct ESA/390 EPSW instruction - Roger Bowler 13 Nov 2007 Support for AWSTAPE segmented blocks - Roger Bowler 02 Nov 2007 Fix runaway CPU for self inflicted SIGP 9 - Ivan Warren 04 Sep 2007 Use integer arithmetic calculating cpupct - Greg 31 Aug 2007 Catch addr-excp when SIE DAT points outside Mainstore - Ivan Warren 28 Aug 2007 cckdutil fix for 64-bit - zhackules by Greg 28 Aug 2007 Fix many TUNSETIFF-EINVAL error messages - Greg 26 Aug 2007 Fix missed unfixed 31 Aug 2006 non-SCSI tape Locate bug - Fish 24 Aug 2007 Modify control registers by cr command - Roger Bowler 16 Aug 2007 Backout 28 Jul fix for LCS (fix was only meant for CTCI) - Fish 06 Aug 2007 Rework CPU execution loop - Greg 06 Aug 2007 Filled ipl, iplc, sysclear, sysreset in HELPTAB - Ivan Warren 06 Aug 2007 implement IPL PARM a la VM - Ivan Warren 29 Jul 2007 Fix PR# 34/tape bug causing crash if non-tape devinit - Fish 28 Jul 2007 Fix day-1 CTCI/LCS bug - Vince Weaver [vince@deater.net] by Fish 24 Jul 2007 Force command-reject (until we can get it coded right) for 3590 Medium Sense (x'C2') and Mode Sense (x'CF') - Fish 24 Jul 2007 Default to --blkid-32 and --no-erg for 3590 SCSI - Fish 24 Jul 2007 Fix tape Synchronize CCW (x'43') to do actual commit - Fish 24 Jul 2007 Fix Windows SCSI tape Locate and Read-Block-Id SNAFU - Fish 19 Jul 2007 Disable DIAG 308 Re-IPL feature until it is complete - Ivan Warren 21 Jun 2007 revert config_cpu.pat due to problems in testing - Greg 20 Jun 2007 3.05 release doc changes - Jay Maynard 18 Jun 2007 make 3990-6 default control unit for 3390 devices - Greg 18 Jun 2007 configure_cpu now returns when the CPU is fully configured - Greg 08 Jun 2007 Skip making CRW pending in S/370 mode - Kevin Leonard 06 Jun 2007 Fix SYNCHRONIZE_CPUS when numcpu > number of host processors - Greg 06 Jun 2007 Ignore suppress bit in FBA Locate CCW Byte 0 - H.U. - Ivan Warren 26 May 2007 Compare-and-Swap-and-Store feature - Roger Bowler 18 May 2007 Conditional SSKE feature - Roger Bowler 04 May 2007 Restore dasdtab.c RDC response circumvention to prevent command reject in DSF for X'0A' command to alternate track - Kevin Leonard 25 Apr 2007 Rename RSS instruction format as SSF - Roger Bowler 04 Apr 2007 Fix Locate Block & Read BlockId for SCSI tape inadvertently broken by 31 Aug 2006 preliminary 3590 support change - Fish 26 Mar 2007 Suppress spurious error messages from hercifc - Greg 25 Mar 2007 Ensure started_mask CPU bit is off for terminating cpu thread - Fish by Greg 20 Mar 2007 Redefine ACC_ and ACCTYPE_ macros - Greg 18 Mar 2007 Simplify MULTIPLE_CONTROLLED_DATA_SPACE tests - Greg 17 Mar 2007 Clarify load_address_space_designator code - Greg 16 Mar 2007 Reduce REGS copying by hscmisc.c - Greg 15 Mar 2007 Fix fba when the fba device is > 4G - Greg 10 Mar 2007 machdep.h updates - Greg 08 Mar 2007 concpy rework - Greg 08 Mar 2007 More tweaks to machdep.h i686 code - Greg 07 Mar 2007 Fix store_dw_i686 - Greg 07 Mar 2007 Fix fetch_dw_i686 - Greg 07 Mar 2007 Remove inline attr from vfetchx/vstorex _full functions - Greg 07 Mar 2007 Fix for SIE'd TPROT - Ivan Warren 06 Mar 2007 Fix ckd RDC response - Greg 27 Feb 2007 PR# misc/87 startup messages fix completion - Kevin Leonard 27 Feb 2007 Fix minor glitch in enhanced symbol substitution - Fish 26 Feb 2007 Extend original print-to-pipe parameter handling to support passing parms when path to filename also contains blanks - Fish 25 Feb 2007 Fix het_locate to continue on tapemark - herc_fun [os_390@hotmail.com] by Fish 25 Feb 2007 Fix crash in LCS close if devinit of incomplete group - Fish 18 Feb 2007 Add TIME and NOTIME synonyms for LOGOPT operands - Kevin Leonard 14 Feb 2007 Fix ckd RCD, SNSS, SNSID responses - Greg 13 Feb 2007 Treat DIAG X'9C' same as DIAG X'44' - Fish 08 Feb 2007 Don't log Sense Running State SIGP order - Fish 03 Feb 2007 Fix MVT tape CMDREJ error - Greg Smith 31 Jan 2007 Add LOGOPT init statement and panel command - Kevin Leonard 30 Jan 2007 Decimal Floating Point (DFP) facility - Roger Bowler 15 Jan 2007 ia32/x64 cmpxchgX assists fix/enhancements - Greg & Ivan 14 Jan 2007 Fix S370 only build - nerak60510 by Greg 11 Jan 2007 implement ccmask phase 1 - Bernard van der Helm 10 Jan 2007 Try to detect 3270 connections that have died - Fish 09 Jan 2007 Tweaks to sloppy fetch - Greg Smith 09 Jan 2007 Tweaks to cpuloop - Greg Smith 09 Jan 2007 Bypass mainlock if only 1 cpu started - Greg Smith 09 Jan 2007 Tweaks to lm/stm - Greg Smith 08 Jan 2007 Add dasdconv -q (quiet) option - Roger Bowler 04 Jan 2007 remove thunk calls for program_interrupt - Greg Smith 03 Jan 2007 single_cpu_dw fetch/store patch for ia32 - Greg Smith 03 Jan 2007 vstorex patch to vstore2, vstore4, vstore8 - Greg Smith 30 Dec 2006 Minor correction to PR# build_msc/103 fix - Fish 03 Jan 2007 Sloppy fetch - Greg Smith 02 Jan 2007 Fix deconfigure_cpu so power-off diagnoses work - Fish 31 Dec 2006 Fix PR# misc/94 for good this time! (hopefully) - Fish 31 Dec 2006 new 'cd' and 'pwd' commands to go with 'sh' command - Fish 31 Dec 2006 Fix cmdline tabbed filename-completion for MSVC - Fish 30 Dec 2006 Add ability to modify gpr reg values to gpr command - Fish 30 Dec 2006 PR# build_msc/103: fix MSVC diag 8 'sh' capture - Fish 27 Dec 2006 Permanently disable Microsoft's default Invalid CRT Parameter handling behavior - Fish 27 Dec 2006 PR# tape/100: Fix crash if bad filespec in OMA (TDF) - Fish 23 Dec 2006 Misc dyngui mods (64-bit regs, efficiency, etc) - Fish 23 Dec 2006 Fix integrated 1052/3215 for output with % - Ivan Warren 21 Dec 2006 Fix SIGP to do single logmsg - Greg Smith 21 Dec 2006 Range for s+, t+ - Greg Smith 20 Dec 2006 Fix instruction display in program interrupt - Greg Smith 20 Dec 2006 Clear FPC register during Initial CPU Reset - Roger Bowler 20 Dec 2006 Clear AR,FPR,VR regs during Clear Reset - Roger Bowler 19 Dec 2006 ip_all.pat - performance patch - Greg Smith 19 Dec 2006 Backout mainlockx.pat - possible SMP problmes - Greg Smith 19 Dec 2006 New FPC command to display FPC register - Roger Bowler 17 Dec 2006 Modify FPR command to display FP registers in pairs - Roger Bowler 17 Dec 2006 Display DXC in msg HHCCP014I for PIC7 - Roger Bowler 11 Dec 2006 Set tape blockid to U32 - (by "zazubek") - Ivan Warren 08 Dec 2006 Add model, plant and manufacturer config parameter - Bernard 06 Dec 2006 Include Mike Cowlishaw decNumber package - Roger Bowler 30 Nov 2006 Floating Point Support Enhancement feature - Roger Bowler 29 Nov 2006 Zero out GPRS on IPL Clear and System clear - Ivan Warren 29 Nov 2006 Begin Decimal Floating Point (DFP) framework - Roger Bowler 27 Nov 2006 Remove GNU dependencies from dasdlist - Bjoern A. Zeeb (rbowler) 26 Nov 2006 Move initialization hao before .rc processing - Bernard 22 Nov 2006 Fix aws/het files trailing garbage - Fish 19 Nov 2006 Fix small typo in qdio.c - Jan Jaeger 18 Nov 2006 Multi-byte opcode performance fix for ia32 - Greg Smith 09 Nov 2006 qd (query ckd dasd) panel command - Greg Smith 08 Nov 2006 Fix (hopefully) hang after resume - Greg Smith 08 Nov 2006 Fix Diag 204 RMF structure size - Ivan Warren Detected by "aleeuw2000" 06 Nov 2006 Update to instfetch processing - Greg Smith 06 Nov 2006 Fix ECPS:VM VTIMER processing - Ivan Warren 05 Nov 2006 OBTAIN_MAINLOCKx macros - Greg Smith 05 Nov 2006 Simplify PER processing - Greg Smith 04 Nov 2006 Added CGER, CGDR, CGXR - Bernard van der Helm 31 Oct 2006 Use accelerated byte swaps for x86_64 - Ivan Warren 30 Oct 2006 Reinstate dasdconv stdin option - Roger Bowler 27 Oct 2006 Reformatted dyncrypt.c, no functional change - Bernard 26 Oct 2006 make KM/KMC/KMAC/KIMD/KLMD compliant regarding stringent register checkings as per POP - Ivan Warren 25 Oct 2006 Performance enhancements suggested by Kees, part 1 distinguish between strict/non-strict load/store - Greg Smith 19 Oct 2006 Fix TUNSETIFF problem on linux 2.6.18 - Greg Smith 12 Oct 2006 Fix 370 and 390 only modes - Greg Smith 09 Oct 2006 Fix some compiler warnings - Ivan Warren 02 Oct 2006 Fix some interval timer processing issues - Ivan Warren 01 Oct 2006 minor(?) accuracy/efficiency tweaks to Win32 'gettimeofday' - Fish 30 Sep 2006 timer interval config stmt & panel cmd - Enrico Sorichetti by Fish 30 Sep 2006 Use nanosleep in timer_update_thread if available - Fish 28 Sep 2006 RSS instruction format and ECTG instruction - Jan Jaeger 26 Sep 2006 PR# misc/99: Config file "include " with "Enhanced" symbol substitution - Hackules by Enrico Sorichetti by Fish 26 Sep 2006 Fix ieee bfp to integer conversions - Jimmy by Greg Smith 23 Sep 2006 RO/RW/RING/NORING tape config options (replaces previous RO/NORING) - Kevin Leonard by Jay Maynard 22 Sep 2006 Fix possible loop in SERVC WRITE_EVENT_DATA - Jan Jaeger 22 Sep 2006 PR# misc/30: HAO (Hercules Automatic Operator) - Bernard van der Helm by Fish 21 Sep 2006 PR# misc/79: single device devlist & defsym command - Fish 20 Sep 2006 PR# misc/98: "Additive" OSTAILOR - Fish 20 Sep 2006 PR# misc/89: fix "HHCCP038E No SCP command" - Fish 19 Sep 2006 Added RO and NORING as synonyms for READONLY tape config option; fixed compilation if SCSI not supported - Jay Maynard 15 Sep 2006 PR# misc/96: fix premature .RC processing wrt CPUSTATE - Fish 06 Sep 2006 Win32 PCRE (Perl-Compatible Regular Expression) support - Fish 31 Aug 2006 Support emulating 3590 SCSI as 3480/3490's and vice versa - Fish 31 Aug 2006 Preliminary support for 3590 (partial and very incomplete) - Fish 24 Aug 2006 Set Windows default thread priorities same as other hosts - Fish 24 Aug 2006 Fix some addtl SCSI tape status related bugs [of my own!] - Fish 19 Aug 2006 Fix auto-scsi-mount bug causing too frequent drive queries - Fish 16 Aug 2006 C99 flexible arrays support - Fish 05 Aug 2006 Added addressing mode in panel - Bernard van der Helm 03 Aug 2006 Add official support for 3590 tape device types using 32-bit block-ids affecting LOCATE BLOCK, etc / BOT detection - Fish 03 Aug 2006 New conspawn keyword: 'startgui' to start Windows GUI application via ShellExecute to prevent hang at exit - Fish 01 Aug 2006 PR# misc/94: Sporadic missed .RC file processing - Fish 21 Jul 2006 Small change to ECPS:VM fix by P. Coghlan - Ivan Warren 21 Jul 2006 Several small bugfixes from Peter Coghlan - Jay Maynard 21 Jul 2006 read_socket and write_socket wrapper routines to fix short read problems for sockdev card readers (new source file hsocket.c) - Robert Styma and Jay Maynard 02 Jul 2006 PR# network/93: honor specified CTCI-W32 buffer sizes - Fish 28 Jun 2006 Fix doubled/duplicated startup 'version' logmsgs caused by PR# misc/87 when Herc is run in daemon/hercgui mode - Fish 25 Jun 2006 Fix seq dasdload blksize pad bug - Peter Sylvester [peter.sylvester@edelweb.fr] by Fish 23 Jun 2006 PR#s misc/21 and PR# network/62: HTTP Server: do 'shutdown' to gracefully close connection before closing the socket - Fish 22 Jun 2006 Back out incorrect modification to BFPREGPAIR macros - Roger Bowler 21 Jun 2006 Correct unresolved external symbol __imp__debug_tt32_tracing - Roger Bowler 21 Jun 2006 Correct BFPREGPAIR checks to prevent spurious 0C6 - Roger Bowler 18 Jun 2006 Add diagnose 0x308 - re-ipl - Bernard van der Helm 13 Jun 2006 Add diagnose 0x224 - CPU name array - Greg Smith 13 Jun 2006 Added diagnose 308 reipl. Not activated in feat900.h! - Bernard 11 Jun 2006 PR# tape/88: "SCSI tape issues": 1. WTM failures with some mfg/model drives (e.g. STK4890), 2. Spurious HHCTA073W for 'rewind-at-close' devtype - Fish 10 Jun 2006 PR# misc/87: Herc system startup message issuance problem - Fish 09 Jun 2006 PR# emul/91: Change FTELL, FSEEK, etc to lowercase - Fish 09 Jun 2006 Instr disassembly enhancement: display instruction name - Fish 07 Jun 2006 PR# misc/71: Incorrect disassembly of some instructions - Fish 05 Jun 2006 PR# misc/68: devinit w/no arguments == use original - Fish 05 Jun 2006 PR# dasd/81: DASDINIT option to bypass VOL1 creation - Fish 06 May 2006 Fix SYNCHRONIZE_CPUS bit-flag serialization issue - Fish 06 May 2006 Fix header-#include and stop-lan port-serialization issues causing some tuntap calls (e.g. set-macaddr) to fail - Fish 02 May 2006 PERFORM SUBSYSTEM FUNCTION and CONTROL ACCESS CCWs - Adrian Trenkwalder 02 May 2006 Fix for invalid bits in LOCATE BLOCK tape CCW - Adrian Trenkwalder 30 Apr 2006 Dyncrypt changed towards POP - Bernard van der Helm 27 Apr 2006 Fix halt_subchan to terminate suspended i/o - Greg Smith 26 Apr 2006 Fix AR tlb lookup in XC mode - Jan Jaeger 23 Apr 2006 PR# network/69: segfault @ incomplete LCS group attach - Fish 23 Apr 2006 Fix LCS port read delay / hercifc SIOCGIFFLAGS issue - Fish 21 Apr 2006 Apple OS X 10.4.6 TUNTAP_ClrIPAddr (ioctl(SIOCDIFADDR)) patch by Kees Verruijt [kees@verruijt.net] - Fish 21 Apr 2006 tt32 v3.1: replace tt32stats cmd with tt32 cmd - Fish 21 Apr 2006 tt32 v3.1: new "tuntap32_build_herc_iface_mac" function - Fish 21 Apr 2006 tt32 v3.1: new "_ex" functions - Fish 21 Apr 2006 LCS support for RARP frames - Fish 21 Apr 2006 TUNTAP_GetFlags: don't read LCS adapter until iface is IFF_UP (resolves "HHCLC042E port 00: Read error" issue) - Fish 19 Apr 2006 Re-fix panel refresh (fill_text, not erase_to_eol; sigh) - Fish 14 Apr 2006 RECFM bits in dasdblks.h (correction by Christophe Nillon) - Roger Bowler 12 Apr 2006 SYNCHRONIZE_CPUS macro in place of synchronize_broadcast - Greg 10 Apr 2006 Portability: change bitfield types from BYTE to u_int - Fish 09 Apr 2006 Transparently handle BSD sockaddr_in sin_len - Fish 09 Apr 2006 Un-"fix" panel.c refresh (sigh) - Fish 09 Apr 2006 Fix bug causing bogus routing table setup for CTCI - Bjoern Zeeb 09 Apr 2006 Added likely/unlikely statements dyncrypt.c - Bernard vd Helm 08 Apr 2006 Added likely/unlikely statements cmpsc.c - Bernard van der Helm 07 Apr 2006 New 'PANTITLE' config stmt to set console/panel title - Fish 06 Apr 2006 PR# 34/tape: prevent tape mount unless no tape mounted - Fish 06 Apr 2006 Missed a scsimount detach/devinit bug - Fish 06 Apr 2006 PR# 53/tape: Bus-Tech compressed AWS file support - Fish 06 Apr 2006 PR# 70/tape: AWS tapes 2GB filesize limitation - Fish 05 Apr 2006 PR# 18/tape: Herc very slow initializing if no tape in SCSI tape drive, PR# 48/tape: Tape mount/unmount messages still not handled correctly, fix bsr/fsr in light of 01 Apr 2006 w32stape fixes for utilities, tweak to auto-scsi-mount logic to eliminate(?) WIN32 drive query inefficiencies - Fish 05 Apr 2006 fix(?) panel.c to always refresh the New Panel display, fix minor New Panel device status painting glitch - Fish 01 Apr 2006 tapecopy: accept WIN32 "\\.\Tape0" filename, use blockid segment# for ext GUI progress msgs, rewind at exit - Fish 01 Apr 2006 Addt'l Win32 SCSI status fixes for utils; s/b ok now - Fish 27 Mar 2006 SCSI tape fixes (MAJOR COMMIT): (Fish) 1) serialize open/close processing 2) support "YES" as valid AUTO_SCSI_MOUNT specification (uses default interval value, currently 5 seconds) 3) "scsimount" panel command: a) support '0' and 'yes' b) don't issue "no active mount requests" for tape drives without display feature c) fix mount/unmount request detection 4) process 'rewind' option at CLOSE, not open (oops) 5) add devnum (with LCSS prefix) to most messages 6) attempt to fix *nix issue of 'EOF' status not being set when BSR/FSR spaces over a tapemark 7) reset 'blockid' to -1 and remove redundant update status call in BSF/FSF. 8) reset 'curfilen' to 0 in rewind_scsitape (and 'blockid' to -1 if rewind fails) 9) fix erase-gap and data-security-erase functions so they actually return an i/o status 10) start automount thread (if AUTO_SCSI_MOUNT is specified) when tape is determined to be not mounted regardless of whether drive/device-type has display-feature 11) remove premature open_scsitape call in tapedev_init_handler to reinstate original behavior of not opening the tape until needed by tapedev CCW processing (PR# tape/18 "slow startup") 12) in an effort to reduce the impact of slow tape status retrieval (that in addition to the above premature call to open_scsitape (which calls update_status_scsitape) was what was causing PR# tape/18 "slow startup"), a new tape status worker thread retrieval technique was designed which allows specifying a timeout value completely different from whatever one the host o/s may use (if any). 13) change message text in 'load_display' function to be more technically accurate and fix ReqAutoMount mount/unmount request detection to correct bogus mount/unmount messages 14) add support for Windows tape device names ("\\.\Tape0") 15) use blockid (as returned by Read Block Id CCW) *as-is* in LOCATE BLOCK CCW, 16) complete rewrite/overhaul of w32stape.c: a) remove rewind logic from open (now done by 'close_scsitape') b) properly track positioning status and setting of errno values after each i/o so that accuracy of device status & errno can be relied upon (e.g. BOT/EOF/EOT/EOD can now be properly detected) c) BSF/BSR fixed to move BACKWARDS, not forwards (oops) d) fix Read Block Id logic (MTIOCPOS) to return a more technically accurate position value (the actual one) 17) many minor editorial corrections (remove TRACE stmts, etc) 05 Mar 2006 hercules logo spec precedence fix by "Rodrigo" - Ivan Warren 01 Mar 2006 Customizable 3270 Logo screen. See README.HERCLOGO - Ivan Warren 28 Feb 2006 Generalize Multiple CSS device numbering for most statements and panel commands. Allow multiple devices on panel attach command. Multiple CSS support for suspend/resume - Ivan Warren 26 Feb 2006 Implement LCSS feature - Jan Jaeger 25 Feb 2006 cckd 0.3.1 - Greg Smith 24 Feb 2006 Skeletal last floating point instructions - Bernard van der Helm 21 Feb 2006 Fix string overrun when hitting tab at the wrong time - Bjoern Zeeb 18 Feb 2006 Reinstate byteswap.h check - Greg Smith 15 Feb 2006 Fixed spurious specification exception in CXFBR and CXGBR - Greg Smith, found by Pasi Pirhonen 11 Feb 2006 Added option s to dasdcat to preserve sequence numbers when generating card image output - Jay Maynard 10 Feb 2006 cckd specifies attr for create_thread - Greg Smith 08 Feb 2006 FreeBSD portability fixes - Mark Szlaga 06 Feb 2006 Codepage 1047 conversion tables - Kevin Leonard 03 Feb 2006 Fixed off-by-one-day bug with SYSEPOCH other than 1900; added new config parameter, YROFFSET, and limited SYSEPOCH to 1900 or 1960 - Jay Maynard 29 Jan 2006 Added 2305-2 and 2305-2 CKD disk and 2835 control unit definitions from CBT file 296 BLKDISK command - Jay Maynard 28 Jan 2006 Added floating point instr CEGR, CDGR and CXGR - Bernard van der Helm 24 Jan 2006 Export needed http server functions so people (like me!) can create cgi-bin dynamic modules if they want to - Fish 19 Jan 2006 Tweaks to SET_THREAD_NAME - Greg Smith 16 Jan 2006 Fix PLO_CSGR to call plo_csgr instead of plo_clgr - Greg Smith 15 Jan 2006 Fix stfl_data/adjust_stfl_data flag settings bug - Fish 15 Jan 2006 Fix 'CVB' overflow check bug in packed_to_binary - Fish 06 Jan 2006 Correct address wrapping in PLO - Jan Jaeger 06 Jan 2006 Change clocks panel command to snapshot all values used before formatting and printing for consistency - Jay Maynard 04 Jan 2006 Change semigraphical panel START and STOP buttons to issue startall and stopall, respectively - Jay Maynard 04 Jan 2006 Fix cckd_gc_l2 bug - Greg Smith 04 Jan 2006 Correct bit codes returned in query function with no MSA ext 1 - Bernard van der Helm 01 Jan 2006 CPU Timer rework - Jan Jaeger 31 Dec 2005 SET_THREAD_NAME for easier MSVC debugging - Fish 31 Dec 2005 Fix for Windows ..\relative path dasd files - Fish 31 Dec 2005 Add space as valid volser char, remove owner field check - Fish 29 Dec 2005 Fix bug causing semigraphical panel to always devinit the first device, regardless of what device was specified - Jay Maynard 29 Dec 2005 Add confirmations to semigraphical panel EXT and RST (external interrupt and restart) commands - Jay Maynard 29 Dec 2005 Fix bug in update_tod_clock preventing cpt from updating - Fish 29 Dec 2005 Fix cpustate display glitch in ipending command - Fish 29 Dec 2005 SIE XC interception fixes - Jan Jaeger 29 Dec 2005 Performance patch STCM, STCMY, STCMH - Bernard van der Helm 29 Dec 2005 Performance patch ICM, ICMY, ICMH - Bernard van der Helm 28 Dec 2005 Perform Timing Facility Function - Jan Jaeger / Bernard van der Helm 27 Dec 2005 Performance patch TM, TMH, TML, TMHH, TMHL, TMY - Bernard van der Helm 24 Dec 2005 Add IFL SCPINFO support for zLinux zipl code - Jan Jaeger 23 Dec 2005 Fix for Windows ..\relative path shadow files - Fish 11 Dec 2005 Correction to format 1 STIDP - Jan Jaeger 10 Dec 2005 Update FAQ software prerequisite sections - Roger Bowler 09 Dec 2005 MAX_CPU_ENGINES defaults to 8 for MSVC build too - Ivan Warren 08 Dec 2005 MAX_CPU_ENGINES now defaults to 8 instead of 2 - Greg Smith 06 Dec 2005 Accept ALRF as abbreviation for ASN_AND_LX_REUSE - Roger Bowler 06 Dec 2005 Fix leapyear issue in sysepoch and format_tod - Jan Jaeger 06 Dec 2005 More logmsg cleanup - Ivan Warren 04 Dec 2005 Added real time conversions to 'clocks' display - Jay Maynard 04 Dec 2005 va_copy 'va-list' copying macro - Fish 04 Dec 2005 tape close fixes (fixes tape devinit crash) - Fish 04 Dec 2005 Made PR# misc/56 fix compile on gcc 3 through an ugly hack - Jay Maynard 04 Dec 2005 CTCT fixes - Fish 04 Dec 2005 More proper PR# misc/56 fix (hopefully) - Fish 04 Dec 2005 Relax SYSEPOCH restrictions - Jan Jaeger 04 Dec 2005 New clock design - Jan Jaeger 04 Dec 2005 OS X portability fixes - Jay Maynard 04 Dec 2005 PR# misc/56: Brute force fix for segfault in some panel commands - Jay Maynard 04 Dec 2005 Fix error in sha-1 message digest - Roger Bowler 03 Dec 2005 Fix fillfnam.c problem debugged by bb5ch39t - Greg Smith 03 Dec 2005 PR# misc/29: SHCMDOPT shell command disablement cfg stmt - Fish 03 Dec 2005 Add crypto files to VS8 vcproj file - Fish 03 Dec 2005 Fix MSVC conspawn/shell cmd glitch: CREATE_NO_WINDOW - Fish 03 Dec 2005 Temp fix to allow up to 1031 cckd devices - Greg Smith 03 Dec 2005 CMPSC no siblings check after 4th/5th child - Bernard/Jacques Dilbert 02 Dec 2005 Added 'conspawn.exe' to MSVC build (for 'sh'ell cmd) - Fish 01 Dec 2005 Volker fix to MSVC makefile for VS 8.0 "manifest" files - Fish 01 Dec 2005 dyngui: SetCurrentDirectory support for shell commands - Fish 01 Dec 2005 Fix things so BOTH print-to-pipe AND 'sh'ell command work - Fish 29 Nov 2005 PR# build_msc/45, PR# printer/24: Poor man's fork for MSVC builds - Fish 28 Nov 2005 enable ATTR_REGPARM performance option for MSVC builds - Fish 28 Nov 2005 enable machine assists in machdep.h for MSVC VC7 compiler - Fish 28 Nov 2005 Fix concpy bug discovered by Fish - Greg Smith 27 Nov 2005 drop support for MSVC static/dll builds; keep only dllmod - Fish 27 Nov 2005 Drop support for makefile.msvc and makefile-dll.msvc - Roger Bowler 27 Nov 2005 Replace crypto support modules by BSD licensed versions - Roger Bowler 26 Nov 2005 Modify status line in panel.c for ESA/390 under z/SIE - Jan Jaeger 24 Nov 2005 Accept "z/Arch" as synonym for "ESAME" archmode - Fish 24 Nov 2005 hbyteswp.h: MSVC workaround for PR# emul/4 - Fish 24 Nov 2005 Fix some very minor glitches in new panel displays - Fish 24 Nov 2005 Report #of processors in hostinfo struct for non-MSVC - Fish 23 Nov 2005 Fix "LNK4099 libcmt.pdb not found" in MSVC static build - Roger Bowler 22 Nov 2005 dyninst module now built in MSVC DLL-MOD version - Ivan Warren 22 Nov 2005 Crypto module now built in MSVC DLL-MOD version - Ivan Warren 21 Nov 2005 Added skeletal ptff - Bernard van der Helm 21 Nov 2005 STSI MP fix - Greg 21 Nov 2005 diag204 fix, STSI capability fix - Jan Jaeger 20 Nov 2005 trace.c: minor fix to PR format-9 trace entry - Fish 20 Nov 2005 configure.ac, hstdinc.h: Apple OS X build fixes - Fish 20 Nov 2005 Correct cpu capability value in STSI - Fish 20 Nov 2005 Reject any intrusive diagnose when diag8cmd is off - Jan Jaeger 19 Nov 2005 Fix GCC 2.95 errors in hostinfo.c, bldcfg.c - Roger Bowler 19 Nov 2005 dyngui.c: show offline CPUs as OFFLINE - Fish 18 Nov 2005 Expand environment vars in httproot if msvc - Fish 18 Nov 2005 Add trailing [back]slash to httproot only if needed - Fish 18 Nov 2005 Fix crash in UpdateTargetCPU when NUMCPU=0 - Fish 18 Nov 2005 Refit Ivan's GCC 2.95 fix to sockdev.h - Roger Bowler 17 Nov 2005 TAPECONV support for 64K blocksize by Charlie Brint - Roger Bowler 17 Nov 2005 Allow compiling support for up to 32 CPUs - Ivan Warren 13 Nov 2005 Add CPU configuration option to http server - Jan Jaeger 11 Nov 2005 Variable size panel - Greg Smith 08 Nov 2005 Fix CPU reconfiguration identification in SCPIN - Jan Jaeger 06 Nov 2005 Store Clock Fast (STCKF) - Jan Jaeger 05 Nov 2005 New format CPUID for z/Arch mode - Jan Jaeger 04 Nov 2005 PER3 include BEAR in suspend/resume file - Roger Bowler 03 Nov 2005 Fix cpu percentage display - Greg Smith 03 Nov 2005 Fix SIE addressing mode issue - Jan Jaeger 02 Nov 2005 Activate FEATURE_PER3 - Roger Bowler 02 Nov 2005 PER3 instruction-fetching nullification - Roger Bowler 01 Nov 2005 hercules no longer depends on libgcrypt - Ivan Warren 01 Nov 2005 Reinstate libhercu/t/d as shlibs/dlls - Ivan Warren 01 Nov 2005 Allow SIE to be issued from HOME SPACE Mode host - Ivan Warren 01 Nov 2005 It was decided the "New Panel" screens should ALWAYS be grey/black REGARDLESS of what the user's default bg/fg term colors are set to; only the default startup panel should honor the user's settings. 01 Nov 2005 Clear high portion of Address Mask in ESAME LPSW - Ivan Warren 31 Oct 2005 PER3 Breaking Event Address Recording (BEAR) revised - Roger Bowler 29 Oct 2005 Final(?) console fg/bg default/color highlighting issue fix - Fish 29 Oct 2005 Fix STFLE SIE intercept - Jan Jaeger 29 Oct 2005 Fix stdout redirection - Jan Jaeger 27 Oct 2005 Fix segfault in SIGP against offline CPU - Jan Jaeger 26 Oct 2005 PER3 Breaking Event Address Recording (BEAR) framework - Roger Bowler 25 Oct 2005 Fix `size exceeds 4G' cckd error during dasdcopy - Greg Smith 25 Oct 2005 Reinstate SIGP code regressed by enhancements of 23 Oct - Roger Bowler 24 Oct 2005 Activate FEATURE_DAT_ENHANCEMENT_FACILITY_2 (LPTEA) - Roger Bowler 24 Oct 2005 LPTEA condition code setting - Roger Bowler 24 Oct 2005 Don't set iodelay to 800 if OSTAILOR LINUX - Greg Smith 23 Oct 2005 SIGP/IPL enhancements: add support for new Conditional Emergency and Sense Running State orders, add support for Set Architecture order parm code 2 and other associated fixes to SIGP processing (minor fixes to clear reset logic, "operator intervening" status; restructure ipl.c & add support for captured z/Arch PSW, add CPU# to registers display in hscmisc.c) - Fish 22 Oct 2005 ACCTYPE_LPTEA in translate_addr - Roger Bowler 22 Oct 2005 Fish's (x-n) bit-shifts (ALRF readability enhancement) - Roger Bowler 21 Oct 2005 Move inline functions from esame.c to inline.h - Roger Bowler 20 Oct 2005 Fix extra path separator issue in http_download - Fish 20 Oct 2005 "tasks/xmlrates" == 'cgibin_xml_rates_info()' contributed by Tim Pinkawa [timpinkawa@gmail.com] - Fish 20 Oct 2005 cckdutil.c: use LSEEK instead of lseek - Fish 19 Oct 2005 Add OSTAILOR z/OS - Roger Bowler 19 Oct 2005 Don't allow windows paths to confuse shared_ckd_init - Fish 18 Oct 2005 Setting of excarid for ASTE-instance exception (Fish) - Roger Bowler 15 Oct 2005 Fix panel color - Jay & Greg Smith 15 Oct 2005 Fix ASTE instance number handling in PC - Jan Jaeger 12 Oct 2005 cckd: gcol moves l2 tables to the front - Greg Smith 12 Oct 2005 cckd_comp improvements - Greg Smith 11 Oct 2005 Minor change in CU14, thanks Roger - Bernard van der Helm 10 Oct 2005 MIDAW list must not cross a page boundary - Roger Bowler 10 Oct 2005 IDTE instruction is RRF_RM format with unused M4 operand - Roger Bowler 07 Oct 2005 Display SIGP order number in addition to description - Roger Bowler 06 Oct 2005 Store Facility List Extended (STFLE) - Roger Bowler 06 Oct 2005 Implemented ETF2 enhancements, still having the flu - Bernard van der Helm 06 Oct 2005 Implemented ETF3 and crypto while having the flu - Bernard van der Helm 05 Oct 2005 Fix segfault in HSCH if device is startpending - Greg 05 Oct 2005 Activate FEATURE_EXTENDED_IMMEDIATE - Roger Bowler 05 Oct 2005 Corrections to FLOGR instruction - Roger Bowler 05 Oct 2005 MIDAW corrections - Roger Bowler 04 Oct 2005 merge FEATURE_LOAD_ADDITIONAL into FEATURE_EXTENDED_IMMEDIATE - Roger Bowler 04 Oct 2005 rename FEATURE_LOAD_PAGE_TABLE_ENTRY_ADDRESS as FEATURE_DAT_ENHANCEMENT_FACILITY_2 - Roger Bowler 04 Oct 2005 rename FEATURE_BRANCH_DETECTION as FEATURE_PER3 - Roger Bowler 04 Oct 2005 rename FEATURE_CPACF_ENHANCEMENTS as FEATURE_MESSAGE_SECURITY_ASSIST_EXTENSION_1 - Roger Bowler 22 Sep 2005 PR# tape/27: *proper* VC7 Large File Support - Fish 21 Sep 2005 Init cckd->l2active to -1 instead of 0 - Greg 21 Sep 2005 tweak concpy to avoid double byteswap - Fish 21 Sep 2005 Add inline assembler assists to startup buildinfo display - Fish 21 Sep 2005 sysblk.mipsrate now per second instead of millisecond, fix bug in timer_update_thread when elapsed < 1 millisec - Fish 20 Sep 2005 Fix divide_single fixed-point-divide-exception check - Greg 16 Sep 2005 PR# hercgui/22: issue dasdload REQCYL= progress msg sooner - Fish 16 Sep 2005 PR# tape/27: discard bug-ridden VC7 Large File Support - Fish 16 Sep 2005 startio should return cc 2 if startpending is on - Greg 16 Sep 2005 Changes to allow building via Cygwin if desired - Fish 16 Sep 2005 Bring MSVC branch up-to-date with head branch - Fish 05 Sep 2005 Correct SSID in Sense Subsystem Status and Read Device Characteristics - Roger Bowler 05 Sep 2005 Sense Subsystem Status for 3990 model 6 - Roger Bowler 04 Sep 2005 tt32_open: 'errno' clobber workaround - Fish 04 Sep 2005 tt32_get_default_iface: never return NULL to prevent crash - Fish 04 Sep 2005 Read Subsystem Data: Storage Paths, Subsystem Statistics - Roger Bowler 03 Sep 2005 Don't report #of host processors if not known - Fish 03 Sep 2005 w32ctca.c: LoadLibrary doesn't like forward slashes - Fish 03 Sep 2005 dasdconv: 1. HercGUI compatibility changes, 2. add -lfs option to create one very large output file - Fish 02 Sep 2005 Perform Subsystem Function CCW: Set Interface Id order - Roger Bowler 02 Sep 2005 ckddasd Read Subsystem Data CCW - Roger Bowler 31 Aug 2005 Fix some bugs in w32stape.c - Fish 1. w32_read_tape: was returning an error when a tapemark was read instead of simply returning 0 bytes read. 2. w32_internal_mtop: MTWEOF: changed to retry WriteTapemark with generic TAPE_FILEMARKS if TAPE_LONG_FILEMARKS fails. 31 Aug 2005 PR# tape/31: Merge Jay's tapecopy changes (that added support for copying from AWS i/p to SCSI o/p) from cvs head into the MSVC 'mingw_port' branch - Fish 30 Aug 2005 dasdtab entries for 3990 model 3 and 6 - Roger Bowler 30 Aug 2005 Add back support for 'CTCI-W32' format device statements, remove 28 Aug messages that say it's not supported - Fish 29 Aug 2005 PR# misc/12: support for Cygwin paths (e.g./cygdrive/x/) - Fish 28 Aug 2005 Tell about unsupported CTC emulations - Fish 28 Aug 2005 Tell where crash dump is going - Fish 18 Aug 2005 ostailor panel command; add display to pgmtrace command - Fish 17 Aug 2005 eliminate dupe "high water mark" code in panel/dyngui - Fish 17 Aug 2005 tapedev.c: fix locblock endianess issue in LOCATE BLOCK logic, add missing blockid increment in write_hetmark - Andy Styles [andy@styles.homeip.net] and John Decker [jdecker@oaksg.com] by Fish 17 Aug 2005 3390-54/3390-JJ support (65520 cyls) - beta - Greg Smith 16 Aug 2005 Added code to try and fix the old "console: DBG028: select: Bad file number" problem that still occassionally occurs, and added some code to try and detect what I believe to be the conditional that might be causing it (will this problem never end?!) - Fish 11 Aug 2005 STFL bits for ETF2/ETF3/STCKF-enhancement features - Roger Bowler 03 Aug 2005 ALS5: MIDAW facility - Roger Bowler 02 Aug 2005 Fix httproot ending slash issue - Fish 31 Jul 2005 ALS5: LT,LTG,LLC,LLH,LBR,LGBR,LHR,LGHR,LLCR,LLGCR,LLHR,LLGHR,FLOGR - Roger Bowler 31 Jul 2005 ALS5: NIHF,NILF,XIHF,XILF,IIHF,IILF,LLIHF,LLILF,OIHF,OILF - Roger Bowler 30 Jul 2005 ALS5: AFI,AGFI,ALFI,ALGFI,CFI,CGFI,CLFI,CLGFI,LGFI,SLFI,SLGFI - Roger Bowler 30 Jul 2005 ALS5 framework: LPTEA,STCKF,STFLE - Roger Bowler 30 Jul 2005 dasdcat/hetlib: add O_BINARY to open - Fish 29 Jul 2005 PR# misc/9: Cap reported mips/sios rates - Fish 29 Jul 2005 Add missing support for 'try_obtain_lock' to PTT tracing - Fish 29 Jul 2005 Reapply Ivan's 16 Mar 2005 console close logic update errone- ously negated trying to keep MSVC sync'ed with cvs head - Fish 28 Jul 2005 Fix MVCL clobber if ESAME but not amode64 - Greg Smith 28 Jul 2005 ALS5 framework: FEATURE_EXTENDED_IMMEDIATE - Roger Bowler 27 Jul 2005 ALS5 framework: FEATURE_HFP_UNNORMALIZED_EXTENSION - Roger Bowler 19 Jul 2005 concpy.pat - concurrent copy phase 1 - Greg Smith 05 Jul 2005 pttrace.c(ptt_pthread_print): remove erroneous assumption regarding size of timeval tv.tv_sec and time(time_t). Added "_USE_32BIT_TIME_T" to makefile-dllmod.msvc as VS8 workaround - Fish 05 Jul 2005 bootstrap.c: added addt'l verbage to "Oops!" message - Fish 05 Jul 2005 ASN-and-LX-reuse facility fixes to PC/PR/PT et al. instructions - Fish 04 Jul 2005 PR# emul/4: MSVC port puts garbage in bits 64-95 of ESAME PSW - Roger Bowler 03 Jul 2005 hstruct.h: CR_SIZE obsoleted - Fish 03 Jul 2005 bldcfg.c: Log run options - Fish 03 Jul 2005 Move DISABLE_CRT_INVALID_PARAMETER_HANDLER logic from console.c into w32util.c where it belongs - Fish 03 Jul 2005 w32util.c: Fix bug in w32_fseeki64 - Fish 03 Jul 2005 makefile-dllmod.msvc: VS8 support: _CRT_NONSTDC_NO_DEPRECATE, add pre-compiled header object file build_pch.obj to links - Fish 27 Jun 2005 Simplify machdep.h [7 patches] - Greg Smith 26 Jun 2005 Use "%"I64_FMT"X" instead of "%llX" for 64 bit values - Roger Bowler 24 Jun 2005 Fix autodetect failure in cardrdr - Roger Bowler 23 Jun 2005 Fix annoying dasdcat link error - Greg 18 Jun 2005 Fix "console: select: Bad file number" (FINAL?) - Fish "Generic"-ize OPTION_WAKEUP_SELECT_VIA_PIPE handling - Fish 15 Jun 2005 Fix ASN-and-LX-reuse facility incorrect linkage second table entry indexing bug in 'PC' (Program Call) instruction - Fish 10 Jun 2005 Fix panel not updating problem - Greg Smith 01 Jun 2005 Fix sf-xxx nomerge bug - Greg Smith 31 May 2005 Fix to fix for wrong null format track - Greg Smith 24 May 2005 Fix optimization typo in configure.ac - Fish 24 May 2005 _POSIX_SYNCHRONIZED_IO test for fdatasync in hmacros.h - Fish 23 May 2005 Fix detach_devblk crash if group member not allocated - Fish 23 May 2005 bootstrap: skip exception handler if being debugged - Fish 23 May 2005 Fix device trace (logdevtr) - Fish 23 May 2005 console tweaks; is Linux console still readable? - Fish 23 May 2005 Fix wrong null format track fix! - Fish 20 May 2005 Fix suspend if no zlib - Greg Smith 20 May 2005 Fix annoying hercifc loop when Hercules crashes - Greg Smith 20 May 2005 Fix wrong null format track - Reported by Gerald - Greg Smith 19 May 2005 savecore: fix help info and start/end range bug - Fish 19 May 2005 fix typo in 'set_console_cursor_shape', make minor Win32 tweak to tapedev.c filename handling. - Fish 18 May 2005 fix crash in panel.c when regs ptr changes after resume - Fish 17 May 2005 fix non-Win32 (e.g. Linux) console color issue (sorry!) - Fish 17 May 2005 ctci_close.pat - Let hercules terminate if CTCI device opened for non MSVC system - Greg 17 May 2005 color.pat - at least linux screen is now readable - Greg 14 May 2005 sysblk.shutfini, HTTP_SERVER_CONNECT_KLUDGE, fix my http server cgi var null termination bug. - Fish 12 May 2005 Removed ./intl directory (we no longer build libintl) gettextize to version 0.14.4 Added several missing files to Makefile.am in order to allow the source distribution to build with MSVC Move 'cause_crash' to hscutl (from w32utl) - Ivan Warren 11 May 2005 fix many serious bugs in the http server logic. - Fish 10 May 2005 dasdconv direct from .gz input file - Roger Bowler 09 May 2005 printer.c: add O_BINARY to open so crlf option works - Fish 09 May 2005 shared.c: skip error msg inapplicable to Win32 builds - Fish 09 May 2005 w32util.c: skip WSACleanup to prevent hang @ shutdown. - Fish 09 May 2005 w32util.c: allow multiple sets in w32_select - Fish 09 May 2005 machdep.h: remove bit functions, add fetch_dw/store_dw - Fish 07 May 2005 last minute fixes: bootstrap.c: don't #define ARRAYSIZE (not needed), tweak 'makefile.bat' so it works with our official build instructions (soon to be published). - Fish 06 May 2005 1. MSVC compiler optimization hints, 2. remove ftol2 from w32util, 3. create minidump in same directory as Hercules executable, 4. makefiles (all): finalize(?) build o/p dir names - Fish 06 May 2005 Comment out MemoryCallback type minidump callback - Ivan Warren 03 May 2005 1. makefile-dllmod.msvc: create .PDB files instead of /maps for 'Release' builds for crash dump analysis purposes, 2. bootstrap.c: crash-dump support for debugging - Fish 01 May 2005 1. lame 1st attempt @ msvc assists in machdep.h & hbyteswp.h 2. move MAX_CPU_ENGINES out of hercwind.h into makefile 3. change %3'rd arg of makefile.bat ==> MAX_CPU_ENGINES 30 Apr 2005 http server now works - Fish 25 Apr 2005 panel/gui tweaks, move maxrates to herc, fix logmsg - Fish 21 Apr 2005 SCSI Tape support - Fish 16 Apr 2005 Large File Support - Fish 15 Apr 2005 BZIP2 support - Fish 15 Apr 2005 Fix CTC heap block freeing @ shutdown issues - Fish 14 Apr 2005 Fix hangs at shutdown - Fish 10 Apr 2005 Get FISH_HANG working again (though I'm not sure why) - Fish 09 Apr 2005 panel.c: honor sysblk.panrate - Fish 08 Apr 2005 cardrdr.c: get socket reader working - Fish 08 Apr 2005 logger.c: don't timestamp logfile if daemon mode - Fish 08 Apr 2005 sockdev.c/hscmisc.c: fix crash at shutdown - Fish 05 Apr 2005 (various): change "LL_FMT" back to just %ll - Fish 05 Apr 2005 (various): use HSO_errno, close_socket, etc - Fish 04 Apr 2005 ecpsvm.c: obtain/release sysblk.intlock in SPT macro - Fish 04 Apr 2005 makefile-dllmod.msvc: VS8 support - Fish 04 Apr 2005 Fix '>>' issues in dasdtab.c and ieee.c - Fish 04 Apr 2005 configure.ac: defer error reporting until very end - Fish 04 Apr 2005 featall.h/logger.c: OPTION_TIMESTAMP_LOGFILE - Fish 30 Mar 2005 Remove bogus IFNAMSIZ definition from hercwind.h - Ivan Warren 24 Mar 2005 Do not assume sizeof(DW) always equals sizeof(U64) - Ivan Warren 16 Mar 2005 Update console close logic - Ivan Warren 13 Mar 2005 Split DLLs and HDL Ok - Ivan Warren 12 Mar 2005 dyngui (and thus HercGUI) now works w/OPTION_DYNAMIC_LOAD - Fish 11 Mar 2005 autodiscover zlib in winbuild\zlib\win32_32 - Ivan Warren 09 Mar 2005 Fix get/setpriority to use 'id_t' type - Fish 09 Mar 2005 Fixed optimization flags, added "batch build", debug builds now work, use XCOPY instead of COPY - Fish 07 Mar 2005 Precompiled headers - Ivan Warren 06 Mar 2005 w32ctca.c: always search the defined modules dir first (/usr/local/lib/hercules) when loading TunTap32.dll - Fish 06 Mar 2005 Fix a bug in my 64-bit changes to the CFC instruction - Fish 05 Mar 2005 DLL Build for MSVC - Ivan Warren 03 Mar 2005 VS .NET Build for DLL Build - Ivan Warren 25 Feb 2005 Another 3480-X'DB' Fix. Tape does not need to be ready for a X'DB' to work. Hinted by John Decker - Ivan Warren 25 Feb 2005 Fix het block count bug introduced by my earlier SCSI changes; John Decker (and Andy Styles) by Fish (thanks guys!) 03 Feb 2005 MinGW port finally works! (static only; no HercGUI (yet)) - Fish 22 Jan 2005 Added '*' comment command as official do-nothing command - Fish 13 Jan 2005 Optmization to instruction fetch for unrolled execute - Greg Smith 13 Jan 2005 AMD64 assembler assists - Bob Deblier by Greg 05 Jan 2005 Fix dasdcopy bug for output ckd file - Greg Smith 02 Jan 2005 Bug fix 14dec05 fixed - Bernard van der Helm 02 Jan 2005 Add integrated 1052/3215 consoles - Jan Jaeger 29 Dec 2004 3480 Modeset (X'DB') has 1 byte of data - Ivan Warren 28 Dec 2004 Set reserved VOL1 fields to blanks - Greg Smith 26 Dec 2004 Initialize guestsregs->ints_state in SIE - Greg Smith 25 Dev 2004 Allow use of 'symbols' for panel commands - Ivan Warren 24 Dec 2004 sie perf update attempt (again).. Merry Xmas - Ivan Warren 23 Dec 2004 Fix SCSI mountreq/unmountreq tests in ReqAutoMount - Fish 22 Dec 2004 Fix to cc in CUUTF and CUTFU instruction - Greg 22 Dec 2004 Fix minor benign glitch in breakpoint cmd - Fish 22 Dec 2004 Fix to TROT instruction in esame.c - Fish 22 Dec 2004 Make 'notimer' the pttrace default as per comments - Fish 22 Dec 2004 Mark Drummond channel.c tape read backwards fixes - Fish 19 Dec 2004 dasdinit VOL1 and linux vtoc tweaks - Greg Smith 16 Dec 2004 Fix BRXHG and BRXLG to branch backwards too - Greg Smith 14 Dec 2004 Ensure dyncrypt is built *AFTER* core - Ivan Warren 14 Dec 2004 cckd garbage collector fix - Greg Smith 14 Dec 2004 Bug in utf xlations, cc3 was never reached - Bernard van der Helm 10 Dec 2004 ppc assembler assists for cmpxchg1, cmpxchg4 - Greg Smith 08 Dec 2004 dasdinit -linux option support - Greg Smith 06 Dec 2004 Keep crx in sync with INST_SPACE - Jan Jaeger 04 Dec 2004 Make chkdsk faster if disk is readonly - Greg Smith 03 Dec 2004 Begin work on MinGW port - Fish 03 Dec 2004 Optimize clearing memory - Greg Smith 02 Dec 2004 Fix ref & change recording in relation to SSKE/RRBE - Jan Jaeger 02 Dec 2004 Fix SIE guest timer interrupt handling - Jan Jaeger 30 Nov 2004 Use SLEEP() to ensure sleep for `n' seconds - Greg Smith 30 Nov 2004 Get mainstor after device initialization - Greg Smith 29 Nov 2004 Fix reference and change recording in dat-off mode - Jan Jaeger 28 Nov 2004 Binary Floating Point feature completed - Roger Bowler 28 Nov 2004 TBEDR,TBDR instructions - Roger Bowler 26 Nov 2004 Improve stack access - Jan Jaeger 25 Nov 2004 Fix MCK in ECPS:VM - Ivan Warren 23 Nov 2004 Improve access register translation - Jan Jaeger 22 Nov 2004 Fix incorrect protection/access in ar mode - Jan Jaeger 21 Nov 2004 Correction to TRTR - Roger Bowler 20 Nov 2004 Add CHSC commands for linux/390 - Jan Jaeger 19 Nov 2004 Document OSTAILOR QUIET - Ivan Warren 18 Nov 2004 Fix zero ilc & pgm oldpsw problem - Jan Jaeger 18 Nov 2004 DIEBR,DIDBR instructions - Roger Bowler 18 Nov 2004 VPATH Build enablement - Ivan Warren 17 Nov 2004 Fix instruction operand trace display - Jan Jaeger 17 Nov 2004 MADBR,MADB,MAEBR,MAEB,MSDBR,MSDB,MSEBR,MSEB instructions - Roger Bow ler 16 Nov 2004 MXDBR,MXDB,MDEBR,MDEB instructions - Roger Bowler 15 Nov 2004 LDXBR,LEXBR,CXFBR,CXGBR,CFXBR,CGXBR instructions - Roger Bowler 14 Nov 2004 Fix AR-mode translation when alet is 2 - Greg Smith 13 Nov 2004 LXEB,LXEBR,LXDB,LXDBR instructions - Roger Bowler 01 Nov 2004 Simplify ALRF integration in LASP (Suggested by RB) - Ivan Warren 15 Oct 2004 Apply CKD Shadow file update to FBA devices - Ivan Warren 14 Oct 2004 Resolved pointers to signed/unsigned types issues revealed by gcc 4.0 pre-release experiments - Ivan Warren 12 Oct 2004 Tweak cckd free space processing - Greg Smith 12 Oct 2004 Fix broken suspend/resume - Greg Smith 11 Oct 2004 Changed libgcrypt requirement to 1.1.90 or better - Ivan Warren 10 Oct 2004 Repaired some deprecated warnings dyncrypt.c - Bernard van der Helm 07 Oct 2004 OPTION_WAKEUP_SELECT_VIA_PIPE - Ivan Warren by Fish 05 Oct 2004 cr_mask.pat - Fix SIE intercept logic for LCTL - Greg Smith 05 Oct 2004 no_ffs.pat - Remove ffs ia32 assembler assist - Greg Smith 01 Oct 2004 Fix segfault when IPLing with IPL CPU offline - Ivan Warren 29 Sep 2004 Fix load/store multiple change (21 Sep 2004) to actually improve performance - Greg Smith 28 Sep 2004 Fix directive inside macro problem in tapecopy.c - Greg Smith 28 Sep 2004 Fix resume-suspend logic in channel.c - Greg Smith 28 Sep 2004 Added iplc (IPL Clear), sysreset (System reset) and sysclear (System reset clear) panel commands - Ivan Warren 26 Sep 2004 Fix segfault when multiple ckd files for dasd volume - Greg Smith 26 Sep 2004 Fix segfault when no cckd shadow file - Greg Smith 24 Sep 2004 Remove (most) int/ptr mismatch warnings for 64 bit machines tentative x86_64 support in autoconf prevent redefining "ffs" if built-in (for non-ia32) - Ivan Warren 24 Sep 2004 Tapecopy: progress msgs for external gui -- Fish 23 Sep 2004 Restore '-Wall -W' flags to gcc, Pass along CFLAGS to configure Eliminated all but 8 warnings -- Ivan Warren 22 Sep 2004 Fix tapecopy -- Fish 21 Sep 2004 cckd `sf-xxx force' command, cckd rewrite - Greg Smith 21 Sep 2004 Performance enhancement for multi-byte opcodes - Greg Smith 21 Sep 2004 Performance enhancement for load/store multiple type instructions (LCTL STCTL LMD LMH LMG STCTG LCTLG STMG STMH LAMY LMY STAMY STMY LAM LM STAM STM) - Greg Smith 21 Sep 2004 Performance enhancement for BCR, BRC, BRCL - inspired by Bernard by Greg Smith 21 Sep 2004 Fix CKD sense codes - Tomas by Greg Smith 19 Sep 2004 Fix/enhance SCSI tape display/mount msgs - Fish 15 Sep 2004 Enable pentium4 specifics for gcc. Fixes - SIGFPE in CFEBR (due to possible bug in feclearexcept) - Allow use of assisted MEMCPY/MEMSET/etc.. for P4 - ./configure ... --host|--build=pentium4|i786- - Ivan Warren 12 Sep 2004 Fix crash in CTCI_Query when device group incomplete - Fish 06 Sep 2004 emulated positioning error fix for read blockid - Fish 05 Sep 2004 tapedev.c/scsiptape.h: blockid s/b maintained by media handlers, minor tweak to when scsi automount thread started, fthreads.h: change default fthreads mutex type from recursive to errorcheck to prevent unintended introduction of deadlock situations due to difference between Windows/Linux's threading model - Fish 05 Sep 2004 1. Fix deadlock introduced by me in scsitape.h, 2. rescind 30 Jul 2004 bldcfg.c fix that I'm told is actually contrary to a change/decision made by Jan back on 2003/03/20 that I was unaware of - Fish 02 Sep 2004 Re-enable build without dynamic loading suppt - Ivan Warren 28 Aug 2004 SCSI tape mods part 1 (cont'd): don't retreive tape status until it's actually needed for error determination - Fish 27 Aug 2004 Removed all conditional and cast lvalues to accomodate for gcc 3.4 and beyond - Ivan Warren 19 Aug 2004 Suspend/resume loadparm value - Christopher by Greg Smith 19 Aug 2004 cckd fix: Honor readonly option on sf- to base file - Greg Smith 18 Aug 2004 cckd fixes: possible sf- corruption, messages - Greg Smith 16 Aug 2004 DAT-enhancement facility: IDTE instruction - Roger Bowler 10 Aug 2004 Fix dasdcopy to large ckd file - Fish & Greg 04 Aug 2004 PIC1 all ALRF only instructions when ALRF disabled Also fix code limit for ESTA - Ivan Warren 30 Jul 2004 SCSI tape mods part 1: Auto-detect SCSI tape mounts - Fish 30 Jul 2004 Fix bug in bldcfg that was causing device initialization failures to not abort Herc statup as they should -- Fish 30 Jul 2004 Make config symbol sub more generalized - Ivan Warren 30 Jul 2004 SIE Perf boost patch correction for pending irpts - Ivan Warren 28 Jul 2004 Remove opctab from run_cpu stack - Greg Smith 28 Jul 2004 Some more SIE perf updates - Ivan Warren P/O Greg Smith 27 Jul 2004 SIE Perf boost. Look for string ISW20040727 to revert - Ivan Warren 27 Jul 2004 SR Fix affecting suspended CCWs - Ivan Warren P/O Greg Smith 26 Jul 2004 Hercules suspend/resume command support - Greg Smith 26 Jul 2004 Clear PSW Bit 12 when switching to ESAME via SIGP - Ivan Warren 26 Jul 2004 Added ASN_AND_LX_REUSE config statement - Ivan Warren 25 Jul 2004 cfba fixes (I hope) - Greg Smith 23 Jul 2004 DAT-enhancement facility: CSPG instruction - Roger Bowler 22 Jul 2004 Fix 370 address lookup for USE_REAL_ADDR - Greg Smith 22 Jul 2004 Activate ASN-and-LX-reuse facility - Roger Bowler 22 Jul 2004 ASN-and-LX-reuse facility: changes for LASP - Roger Bowler 22 Jul 2004 defsym fix and env var fallback - Ivan Warren 21 Jul 2004 Invalidate AIA for s370 on dat-mode change - Greg Smith 21 Jul 2004 ASN-and-LX-reuse facility: changes for BSG - Roger Bowler 20 Jul 2004 Updated CTC Device def stmt doc for TCP/IP - Ivan Warren 15 Jul 2004 Fixed tape "at loadpoint" sense issue - Ivan Warren 08 Jul 2004 cfba fixes - Greg Smith 08 Jul 2004 ASN-and-LX-reuse facility: SSAR, SSAIR - Roger Bowler 07 Jul 2004 ASN-and-LX-reuse facility: PT, PTI - Roger Bowler 01 Jul 2004 Fix error introduced into BCTR - Juergen & Greg 01 Jul 2004 Minor performance update macro ILC - Bernard van der Helm 29 Jun 2004 exilc.pat - Remove execflag check from INST_UPDATE_PSW - Greg 29 Jun 2004 noilc.pat - Calculate ILC on demand - Greg Smith 27 Jun 2004 pr.pat - Performance tweak for PR - Greg Smith 27 Jun 2004 cckdwrs.pat - Prevent extra writer threads from starting - Greg 26 Jun 2004 if.pat - Minor tweaks to instfetch - Greg Smith 26 Jun 2004 gen.pat - Performance tweaks to L,LM,SLA,SLR,ST,STM - Greg Smith 26 Jun 2004 tlbx2.pat - Fix real mode bug in tlbx.pat - Greg Smith 26 Jun 2004 iawrap2.pat - Fix performance bug in iawrap.pat - Greg Smith 24 Jun 2004 cckdhang.pat - Fix hang on shutdown if using cckd - Greg Smith 19 Jun 2004 lfs.pat - Allow large files if sizeof(off_t) > 4 - Fish & Greg 17 Jun 2004 iawrap.pat - Performance improvement for instruction address wrapping - Greg Smith 17 Jun 2004 ex4.pat - Performance improvement for 4 byte inst - Greg Smith 17 Jun 2004 tlbx.pat - accelerated address lookup improvements - Greg Smith 17 Jun 2004 Tuntap duplicate MAC address fix/workaround - Fish 15 Jun 2004 ASN-and-LX-reuse facility: PC number translation - Roger Bowler 14 Jun 2004 ASN-and-LX-reuse facility changes for PR - Roger Bowler 11 Jun 2004 Minor ETF3 optimalizations - Bernard van der Helm 10 Jun 2004 Prevent multiple console threads from being created - Fish 10 Jun 2004 ETF3 fixes Roger Bowler/Bernard van der Helm 10 Jun 2004 ipaddr/mask filtering support for terminal devices - Fish 08 Jun 2004 Extended translation facility 3 completed - Bernard van der Helm 05 Jun 2004 ASN-and-LX-reuse facility changes for ESTA,BAKR - Roger Bowler 05 Jun 2004 Added CU14, CU24 - Bernard van der Helm 04 Jun 2004 Fix startall bug (thanks Greg) - Fish 04 Jun 2004 Framework for ASN-and-LX-reuse facility,EPAIR,ESAIR - Roger Bowler 04 Jun 2004 Added TRTR + skeleton extended translation facility 3 - Bernard van der Helm 29 May 2004 dyngui.c: fix UpdateTargetCPU, new "maxrates" cmd - Fish 29 May 2004 Fixed stopall/startall - Fish 29 May 2004 Remove "fake loading of " in hercules.h - Fish 28 May 2004 TUNTAP_SetDestAddr: 'ifr_addr' (NOT 'ifr_dstaddr') - Fish 28 May 2004 ffs.pat - SMP fix for ffs macro - Greg Smith 24 May 2004 Mac OS X CTC support - Jay Maynard 24 May 2004 gcwait.pat, cckdfat.pat - cckd fixes - Greg Smith 22 May 2004 Fix crypto/Makefile.am warning about CFLAGS use - Ivan Warren 22 May 2004 Fix warning about CONTAINING_RECORD macro (linklist.h) - Fish 14 May 2004 libgcrypt API variations automagic integration - Greg & Ivan 13 May 2004 bc.pat - Yet another BC optimization - Greg Smith 13 May 2004 fetch_main_absolute.pat - Resolve absolute addresses only once for multiple addresses in the same page - Greg Smith 13 May 2004 sieregs.pat - Obtain guestregs on first execute of SIE - Greg Smith 13 May 2004 immed.pat - ni/xi/oi optimizations - Greg Smith 04 May 2004 cckdbuf.pat - cckd fixes - Greg Smith 17 Apr 2004 Correct merged PER guest interrupt propagation - Jan Jaeger 10 Apr 2004 Use signal shutdown on quit - Jan Jaeger 09 Apr 2004 PMCW QDIO bit no longer reserved - Jan Jaeger 08 Apr 2004 QDIO device handler changes - Jan Jaeger 08 Apr 2004 Correct false PIC 04 on TRAP2/4 instructions - Jan Jaeger 04 Apr 2004 Undo change 14 May - Bernard van der Helm 30 Mar 2004 Add debug entry point for watchdog signal - Jan Jaeger 26 Mar 2004 Program old PSW fix (ESAME) - Jan Jaeger 25 Mar 2004 Program old PSW fix (S/390) - Jan Jaeger 24 Mar 2004 More of Greg's CLC improvements + no direct SK manipulation when dealing with non-crossing MVCs - Ivan Warren 22 Mar 2004 Fix DXC codes in ieee.c - Jan Jaeger 21 Mar 2004 Fix false PIC 04's under SIE - Jan Jaeger 18 Mar 2004 re-enable ECPS:VM + VTIMER fix - Ivan Warren 17 Mar 2004 clc.pat - Optimize CLC - Ivan & Greg - Greg Smith 17 Mar 2004 l2m.pat - Tweaks to logical_to_main - Greg Smith 17 Mar 2004 protected.pat - Optimization for is_fetch_protected - Greg Smith 17 Mar 2004 prefixing.pat - Optimize APPLY_PREFIXING using xor - Greg Smith 14 Mar 2004 tlb1024.pat - Increase TLB size to 1024 - Greg Smith 14 Mar 2004 permode.pat - bit check for PER mode - Greg Smith 14 Mar 2004 maddr.pat - virtual address translation returns mainstor address - Greg Smith 11 Mar 2004 CLC performance improvement - Ivan Warren 10 Mar 2004 Changed MAXTTR in DASDLOAD.C to 50000 - Volker Bandke 08 Mar 2004 Optimised non crossing/non overlap MVCs with length 2,4,8,12 and 16 - Ivan Warren 06 Mar 2004 RR, RRE, RRF_* macro optimalization - Bernard van der Helm 05 Mar 2004 Restructure loadparm handling - Jan Jaeger 05 Mar 2004 Fix locking during ipl from web interface - Jan Jaeger 05 Mar 2004 LPAR name restructure - Jan Jaeger 05 Mar 2004 Initialize loadparm to blanks instead of dots - Jan Jaeger 28 Feb 2004 Simplify translate_addr() parameter list - Greg Smith 28 Feb 2004 vstore/vfetch updates for boundary crosses - Greg Smith 28 Feb 2004 Fix TB (B22C) under SIE - Greg Smith 27 Feb 2004 Special I/O processing for Immediate Commands - Ivan Warren 26 Feb 2004 Set iodelay correctly for 0 value; dasdtab comments - Greg Smith 25 Feb 2004 Don't set incorrect length on printer immediate CCWs - Jay Maynard 21 Feb 2004 Added system parameter lparname - Bernard van der Helm 16 Feb 2004 clc.pat - Optimize CLC - Greg Smith 16 Feb 2004 move_chars.pat - Optimize move_chars - Greg Smith 16 Feb 2004 radr.pat - Make type RADR type U32 for 32 bit machines - Greg Smith 16 Feb 2004 sie_mode.pat - Check sie_mode bit for sie mode regs - Greg Smith 16 Feb 2004 vfethc.pat - Optimize vfetchc - Greg Smith 16 Feb 2004 execflag.pat - Remove execflag from inst calls - Greg Smith 16 Feb 2004 skp.pat - Reduce setting storage key bits - Greg Smith 16 Feb 2004 psw.pat - Revise internal psw format - Greg Smith 07 Feb 2004 Device groups descriminators for console devices - Ivan Warren 07 Feb 2004 Update cpuints.h bit processing - Greg Smith 06 Feb 2004 Add SIE_STATNB macro - Jan Jaeger 06 Feb 2004 Correct SIE feature byte tests - Jan Jaeger 05 Feb 2004 Reverse armode patch - problems with XC mode - Greg Smith 05 Feb 2004 PR (Program Return) fix - Jan Jaeger 04 Feb 2004 Add SIE_STATE macro - Jan Jaeger 04 Feb 2004 Aff SIE_STATB macro - Jan Jaeger 04 Feb 2004 Change SIE host page protect logic - Jan Jaeger 03 Feb 2004 Fix segfault in ipl from CDROM - Jan Jaeger 02 Feb 2004 Fix instr display for SIE'd prog interrupt - Ivan Warren 01 Feb 2004 Breakpoint range, suggested by Binyamin Dissen - Greg Smith 31 Jan 2004 Fix possible CKD/FBA corruption - Karl-Heinz Lohner by Greg Smith 30 Jan 2004 LOGICAL_TO_ABS/logical_to_abs performance enhancement - Greg Smith 30 Jan 2004 vfetch/vstore, RR format Optimisation re-instate static/inline for IFETCH & LOGICAL - Ivan Warren 21 Jan 2004 Correct 'unloaded' tape processing - Ivan Warren 20 Jan 2004 Fix references to regs->inst to regs->ip - Greg Smith 19 Jan 2004 Return 'Already at BOT' sense on BSF when at BOT (Detected by Mark Drummond) - Ivan Warren 16 Jan 2004 Performance Enhancement: REGS on run_cpu stack - Greg Smith 16 Jan 2004 Performance Enhancement: instfetch - Greg Smith 14 Jan 2004 CPU reconfig fixes - Jan Jaeger 07 Jan 2004 DIAG 204 fix - Jan Jaeger 07 Jan 2004 Add log command to dynamically redirect system log - Jan Jaeger 19 Dec 2003 Correct Keyboard Shortcuts for pseudo-graphical Console - Volker Bandke, code by Marian Gasparovic 17 Dec 2003 Correct structure size boundaries for ARM compiles - Ivan Warren 12 Dec 2003 Clear tlb every 2^16 invalidations instead of 2^8 - Greg Smith 09 Dec 2003 Fix false PIC 05 on MVPG - Jan Jaeger 05 Dec 2003 Move IS_IC_TRACE check to slowloop in run_cpu - Greg Smith 05 Dec 2003 Clear regs->ve every 2^20 invalidations instead of 2^12 - Greg Smith 05 Dec 2003 Add "filename completion" shortcut via TAB character to panel.c - Volker Bandke, original code by Marian Gasparovic 04 Dec 2003 Add sclp reset to io reset - Jan Jaeger 01 Dec 2003 Signal Quiesce (shutdown) & ssd command - Jan Jaeger 29 Nov 2003 Fix race condition in console.c recv_3270_data causing 100% CPU utilization, zero MIPS" Hercules hang symptom (version in configure.ac version bumped to 3.00a.5) - Fish 29 Nov 2003 Fix "passing arg n of from incompatible pointer type" warnings in codepage.c, dat.h, stack.c, xstore.c - Fish 29 Nov 2003 Fix reset_channel_path - Mark Drummond by Greg Smith 28 Nov 2003 Flush Buffer On lost data condition in 2703 handler - Ivan Warren 27 Nov 2003 CTCI/LCS: fix enqueue full frame buffer loop; enable thread joining at LCS close - Fish 26 Nov 2003 Performance enhancements for CLM/ICM/STCM and XC - Greg Smith 26 Nov 2003 ia32 assists for virtual store memcpy - Greg Smith 26 Nov 2003 console.c: ignore "Negotiate About Window Size" from telnet client so e.g. WinNT telnet client works - Greg Price by Fish 26 Nov 2003 Add missing 'filename' initialization for CTCI devices - Fish 26 Nov 2003 Enable thread joining logic in logger_term - Fish 24 Nov 2003 Fixed fthreads: basically almost a complete rewrite, involving thread joining support and & mutex attribute support; version number in configure.ac bumped to 3.00a.3 - Fish 23 Nov 2003 TLB fixes - Greg Smith 18 Nov 2003 ptt trace updates - Fish & Greg Smith 17 Nov 2003 Bypass garbage collection if not opened read/write - Greg Smith 13 Nov 2003 Additional checks for pending attention interrupt - Greg Smith 11 Nov 2003 bumped configure.ac version to 3.00a.2 just for fun - Fish 11 Nov 2003 fix hst command history logic buffer overflow bug - Fish 11 Nov 2003 ieee.c floating point fixes: fix bug in FP_INFINITE, FP_NAN, and FP_ZERO handling for CFDBR, CFEBR, CGDBR, and CGEBR, fix int divide by zero crash preceded by msg "lbfpston: unexpectedly converting an Infinite" - Willem & Fish 10 Nov 2003 Clear attention interrupt pending during device reset - Greg Smith 08 Nov 2003 Added command history to panel.c - Volker Bandke, code by Marian Gas parovic 07 Nov 2003 Added optimization problem bypass for GCC 2.96 - Ivan Warren 30 Oct 2003 Added crypto functions - Bernard van der Helm / Jan Jaeger 24 Oct 2003 pttrace.c threads trace patch - Greg 22 Oct 2003 shared_server tolerates unix socket problems - Greg 20 Oct 2003 Prevent dyngui unload when gui active - Jan Jaeger 17 Oct 2003 Make sure 'init_hostinfo' called BEFORE 'display_version' - Fish 16 Oct 2003 Always updagte `ints_state' (except PER) with `intlock' held - Greg 13 Oct 2003 fix 'ipending' cmd to display ALL pending interrupts - Fish 13 Oct 2003 dequeue ALL i/o ints in device_reset - Fish 13 Oct 2003 impl.c: terminate w/HHCIN008S if dyngui.dll load fails - Fish 12 Oct 2003 dequeue i/o int fix in device_reset - Jan Jaeger 11 Oct 2003 Added verbose flag to display_version, and set to FALSE on standalone utilities - Jay Maynard 07 Oct 2003 Shared library fix for dyninst.c - Jan Jaeger 06 Oct 2003 Enable ia32 assembler assists for -fPIC - Greg Smith 02 Oct 2003 Issue warning message when restoring non-IEBCOPY xmit file using dasdload - Greg Smith 01 Oct 2003 Fix segmentation fault using NPTL threads and no console device is specified - Greg Smith 29 Sep 2003 Backout STUPID (dangerous) 16 Aug 2003 het changes now that configure.ac detects the bug that was causing it - Fish (I can't believe I did that; I must have been tired) 27 Sep 2003 Correct Makefile.am Transient variable names to not end with automake primaries - Ivan Warren 25 Sep 2003 PowerOff diagnose for 4361 & 937X processors - Tomas Masek by Fish 25 Sep 2003 Fix DASDCOPY bug copying too much to uncompressed FBA o/p - Fish 25 Sep 2003 Fix dasdtab entry for 3310 FBA device type - Fish 25 Sep 2003 Initial power-on reset for mainstor & expanded storage - Fish 25 Sep 2003 Resolve & verify HTTPROOT in config.c before startup - Fish 25 Sep 2003 Fix bug in fbadasd_init_handler causing DASDCOPY crash - Fish 21 Sep 2003 Complete overhaul to the build process (merge of libtool_exp) version set to 2.17.c0 - A Lot of People (commit by Ivan Warren) 21 Sep 2003 Added test for cygwin gcc alloca bug to configure.ac to fix issue of http server (and possibly other things) crashing - Fish 20 Sep 2003 Add disassemble command (u [r|v|p|h] addr range) - Jan Jaeger 16 Sep 2003 Tape read backward fixes contributed by Jay Jaeger - Fish 16 Sep 2003 Repair DEVPRIO handling - Mark L. Gaubatz 28 Aug 2003 Check mmap return value when allocating main storg - Ivan Warren 24 Aug 2003 fix for Asynch I/O Status stacking race condition - Ivan Warren 24 Aug 2003 Add modpath configuration statement - Jan Jaeger 22 Aug 2003 Remove setpriority from execute_ccw_chain and instead move it directly into the device thread itself - Fish 22 Aug 2003 Add support for strlcpy/strlcat and use in httpserv.c (please use where possible instead of strncpy/strncat) - Fish 22 Aug 2003 Define default priorities for WIN32 / non-WIN32 - Fish 20 Aug 2003 Correct interval timer references and resolution - Mark L. Gaubatz 19 Aug 2003 Make devlist command immune from DEVBLK chain sequence - Fish 19 Aug 2003 Windows "double memory consumption" fix contributed by Mark D. (golden_dog98 [golden_dog98@yahoo.com]) - Fish 19 Aug 2003 Committed Jim Pierson's "-g -O2" optimization flags fix - Fish 19 Aug 2003 Fix dasdtab to provide correct model numbers for sense ID on 3340-1 (35M) and 3340-2 (70M) - Ivan Warren 19 Aug 2003 Removed W32 only symbol from linux build in ctcadpt - Ivan Warren 19 Aug 2003 Fixed nested lock issue in LCS freezing on Linux - Ivan Warren 19 Aug 2003 Fixed herc crash when "attach" CTCI with no parm - Jim Pierson 19 Aug 2003 Allow Write Record 0 after Write Home Address on CKDs problem initially reported by Jay Jaeger(cube1us) - Ivan Warren 18 Aug 2003 Re-instated fast dev lookup as a cache facility Thanks Fish for the suggestions - Ivan Warren 17 Aug 2003 Added HERCPRIO, DEVPRIO and TODPRIO - Mark L. Gaubatz 17 Aug 2003 Disabled Fast devnum & subchan lookup because of some incompatibilities / reported by yvangamache - Ivan Warren 16 Aug 2003 fix tt32stats command when OPTION_DYNAMIC_LOAD - Fish 16 Aug 2003 fix CTCI segfault caused by bug in build_config when OPTION_CONFIG_SYMBOLS specified - Fish 16 Aug 2003 fix 'make install-strip' issue with dyn devices identified by yvangamache [yvangamache@hotmail.com] -- Fish 16 Aug 2003 copytape (hetupd.c), main (hetmap.c), het_read, het_write (hetlib.c): define global static I/O buffers to work around pre gcc 3.2 bug #8750 identified on "04 Jan 2003" - Fish http://gcc.gnu.org/bugzilla/show_bug.cgi?id=8750 15 Aug 2003 Compress ESAME psw in semi graphic panel - Jan Jaeger 14 Aug 2003 Updated dasdutil.c for HDL compatibility - Ivan Warren 14 Aug 2003 Added D/T 3422,3430 to hdteq & tapedev(hdt3420) - Ivan Warren 14 Aug 2003 Cosmetics : Correct HHCTE006A Prompt - Ivan Warren 14 Aug 2003 Fast Devnum & Subchannel lookup algorithm - Ivan Warren 11 Aug 2003 Dequeued IOINT struct off of sysblk.iointq during TIO/TSCH to prevent incorrect PCI/Final irpt reordering. OS360/MVT Now IPLs correctly. All changed marked with "ISW20030812" - Ivan Warren 08 Aug 2003 2.17.b2: fixed incorrectly typed thread functions - Fish all thread functions s/b "void *thread(void *arg)", not void thread(void *arg) or void *thread() or anything else 08 Aug 2003 Increased 2311 Alt Cyl count from 2 to 3 - Ivan Warren 07 Aug 2003 Codepage extensions (iconv) - Jan Jaeger 05 Aug 2003 Dynamic loadable device support - Jan Jaeger 01 Aug 2003 Created RELEASE.NOTES member - Fish 01 Aug 2003 Added Hercules VERSION to dyngui - Fish 01 Aug 2003 Various OMA tape processing fixes - Ivan Warren 29 Jul 2003 Fix shared device open to not set `connecting' bit on until after parameter verification - Greg Smith 26 Jul 2003 Minor change to codepage conversion logic - Jan Jaeger 21 Jul 2003 CVD fix by Viktor Shkamerda - Jan Jaeger 20 Jul 2003 Defer tuntap32 dll load to device alloc - Jan Jaeger 19 Jul 2003 THDER,THDR instructions - Roger Bowler 18 Jul 2003 NLS translation updates - Jan Jaeger 18 Jul 2003 Fix bug in config.c causing segfault on lcs devices - Fish 18 Jul 2003 Fix race conditions in console detach/close - Jan Jaeger 17 Jul 2003 Allow address:port on CNSLPORT statement - Jan Jaeger 17 Jul 2003 make console threads high priority, remove trylock - Fish 17 Jul 2003 logger_init: 1) consistent stdxxx dup'ing, 2) make logger_thread high priority - Fish 17 Jul 2003 Bugfix: destroy LOCK & COND in cache_destroy - Fish 16 Jul 2003 Allow specifying a native block device as an FBA * Linux only, <2Gb Only - Ivan Warren 15 Jul 2003 Fix s/370 testio race condition - Greg Smith as reported by Victor Shkamerda 14 Jul 2003 Fixes for compiler weirdness - Greg Smith 12 Jul 2003 Optimize HDL_FINDNXT call - Jan Jaeger 12 Jul 2003 Correct archmode check in cmpsc and featchk - Jan Jaeger 12 Jul 2003 Restructure service and facility features - Jan Jaeger 11 Jul 2003 Fix bogus HHCCT048E error message - Fish 11 Jul 2003 Fix "console: select: Bad file number" -- 2nd try - Fish 10 Jul 2003 fix tape label issue in hetinit.c & slib.c - Fish 10 Jul 2003 HFP Multiply-Add/Subtract Facility - Roger Bowler 09 Jul 2003 UC Only in status for CTL NO-OP on tape devices - Ivan Warren 09 Jul 2003 added check to configure.ac to ensure dynamic load support available if external-gui support requested on win32 - Fish 07 Jul 2003 configure.ac now correctly sets USE_DLLTOOL to false if OPTION_DYNAMIC_LOAD not possible (so dyninst/dyngui don't get built), and OPTION_DYNAMIC_LOAD and HDL_USE_LIBTOOL are now both handled automatically in configure.ac - Fish 07 Jul 2003 ECPS:VM config Statement and EVM panel command retired. both replaced with ECPSVM - Ivan Warren 07 Jul 2003 #undef OPTION_DYNAMIC_LOAD in featall.h if neither dlopen nor libtool is available - Fish 06 Jul 2003 LXR,LZER,LZDR,LZXR instructions - Roger Bowler 04 Jul 2003 Allow NUMCPU=0 - Jan Jaeger 03 Jul 2003 Long Displacement Facility - Roger Bowler 30 Jun 2003 Display all messages on shutdown - Jan Jaeger 30 Jun 2003 Removed incorrect locks in console attach/detach - Jan Jaeger 29 Jun 2003 Added shutdown logic - Jan Jaeger 28 Jun 2003 Fix "console: select: Bad file number" - Fish 28 Jun 2003 Updated hercinst.html with panel command info - Fish 28 Jun 2003 Loadable crypto support (US export regulations) - Jan Jaeger 27 Jun 2003 Allow unload reject in hdl final processing - Jan Jaeger 27 Jun 2003 Support dynamic loadable cgi routines - Jan Jaeger 27 Jun 2003 Panel.c + hsccmd.c: clear/reset screen before exiting - Fish 27 Jun 2003 Panel.c: 1) removed all external-gui logic, 2) long messages now wrap to the next screen line - Fish 27 Jun 2003 Fixed some "integer constant is too large for "long" type" warnings - Fish 27 Jun 2003 Added addt'l instructions/info to autogen.sh - Fish 27 Jun 2003 Added README.HDL to EXTRA_DIST in makefile.am - Fish 27 Jun 2003 Updated makefile.am to add Windows resource definitions to dyngui.dll - Fish 27 Jun 2003 Framework for ALS4 features - Roger Bowler 26 Jun 2003 Check for physical shared object when loading dll - Jan Jaeger 26 Jun 2003 Fix Win32 hdl case-sensitivity bug - Fish 26 Jun 2003 TT32 CTCI fixes: 1) fix ACCESS_VIOLATION caused by NULL ptr being returned by 'tt32_get_default_iface', 2) 'tt32stats_cmd' temporarily fixed by fixing bug in 'CTCI_Init' and adding temp workaround code to 'display_tt32_stats' function to work around bug in TunTap32.dll, 3) add some code to try and resolve bogus "HHCCT048E" message being issued at close/shutdown. 25 Jun 2003 shared device version/release checking - Greg Smith 25 Jun 2003 micro performance update in branch on condition - Bernard van der He lm 25 Jun 2003 Fix unlikely but serious fthreads bug in wait_condition - Fish 25 Jun 2003 Move external gui logic from panel_display to dyngui.c, and modify build process (makefile.am) to automatically build new dyngui.dll (and dyninst.dll too) - Fish 25 Jun 2003 Add dyninst qualifier to dynamic instr. symbol names - Jan Jaeger 23 Jun 2003 Fix interrupt queue problem in haltio - Fish (by Greg Smith) 17 Jun 2003 dyninst now supports dynamic instruction update - Jan Jaeger 15 Jun 2003 Add dynamic module preloading - Jan Jaeger 15 Jun 2003 Add version and dependency checks to dynamic loader - Jan Jaeger 11 Jun 2003 More message numbers - Greg Smith 05 Jun 2003 Dynamic loader support - Jan Jaeger 05 Jun 2003 Preliminary substitution capabilities in config file. Substitution format is $(varname). Current vars are cuu,ccuu,CUU,CCUU - Ivan Warren 04 Jun 2003 Device number specification extension. Device numbers are now CUU or CUU-CUU or CUU.count or CUU,CUU or a combination of the above - Ivan Warren 01 Jun 2003 Updated hercconf.html page to include ECPS:VM, 2703, 3410, 3490, 9347 D/T and explanation for 2703 parameters - Ivan Warren 29 May 2003 Correction to diagnose 0 to use real address - Jan Jaeger 28 May 2003 Use unix sockets for localhost shared devices - Greg Smith 26 May 2003 Yet another round for channel.c locking - Greg Smith 26 May 2003 Fixes and performance enhancements for shared devices - Greg Smith 23 May 2003 Locate Block logic fix - Ivan Warren, Suggested by *Anonymous* 23 May 2003 Provide command response in DIAG 8 resp buffer - Ivan Warren 22 May 2003 Add CPUVERID config statement to set version code - Jan Jaeger 22 May 2003 Add DIAG8CMD config statement to enable diag 8 commands - Jan Jaeger 21 May 2003 Fix spec exception in LPSW on incorrect amode settings - Jan Jaeger 19 May 2003 Close all FDs before forking hercifc - Ivan Warren 18 May 2003 Fix incorrect amask in LPSW in 64 bit mode - Jan Jaeger 15 May 2003 Fixed cygwin regparm bug check bug in configure.ac: __attribute__ ((regparm(3))) in wrong place - Fish 15 May 2003 Created "destroy_lock" and "destroy_condition" macros; added support destroying locks/conds to fthreads - Fish 15 May 2003 Fixed impl.c so FishHang doesn't crash - Fish 14 May 2003 Update in cmpsc.c store_ch - Scott Blackledge/Bernard van der Helm 09 May 2003 Update dasdtab.c 3380 entries - Jesper by Greg Smith 05 May 2003 Write zeroes at end of file to increase its size if ftruncate doesn't work - Greg Smith, suggested by Andy Kane 05 May 2003 Meaningful error messages for invalid or unsupported parms to dasdinit - Greg Smith, suggested by John Summerfield 05 May 2003 Meaningful error messages for unconfigured compression - Greg Smith, suggestions by John McKown & Davud Booher 05 May 2003 Allow arbitrary number cckd cylinders - Greg Smith, suggested by Romain Capron 05 May 2003 Remove cckd zlib dependencies - Greg Smith, suggested by John Summer field 28 Apr 2003 Changed 3270 Disconnect/Reconnect status presentation logic (should allow terminal disc/recon on MVS) - Ivan Warren 24 Apr 2003 Set PGID/Sense PGID/Assign/Unassign Corr to Tape Devices (fixes device Boxing when varied on twice) - Ivan Warren 23 Apr 2003 Shared devices fixes - Greg Smith 19 Apr 2003 Shared devices - Greg Smith 18 Apr 2003 270X Poll CCW Implementation - Ivan Warren 16 Apr 2003 Rework channel.c serialization - Greg Smith 16 Apr 2003 memrchr.[ch] added for Cygwin - Volker Bandke 15 Apr 2003 LCTL VM Assist - Ivan Warren 10 Apr 2003 DISP0/DISP1/DISP2 CP Assists - Ivan Warren 05 Apr 2003 Virtual Timer Assist - Ivan Warren 04 Apr 2003 Return IntReq on Card Read unsolicited Sense when the card reader is empty - Ivan Warren 03 Apr 2003 ECPS:VM SSM Correction, panel command rework (evm) and conditional debug messages - Ivan Warren 02 Apr 2003 Reordered int/dev locks in channel handler to avoid race conditions in certain situations - Ivan Warren 29 Mar 2003 Addl VM Assist support : SVC + SSM VM Assists new evmstat panel command No Timer Assist (do #CP SET ASSIST ON NOTMR) - Ivan Warren 27 Mar 2003 Initial minimal CPASSIST ECPS:VM/370 support - Ivan Warren 26 Mar 2003 Fix cckd locking problems, esp. during sf- and sfc - Greg Smith 26 Mar 2003 CKD now uses the same shared cache as cckd - Greg Smith 26 Mar 2003 Divorced cache management code from cckd code - Greg Smith 21 Mar 2003 BSC/2703 Line emulation - Ivan Warren 20 Mar 2003 Rework system logger functions - Jan Jaeger 19 Mar 2003 Tape : Present DE on IntReq for non-data motion CCWs Added deonirq=0|1 for 3410/3420 tapes in relation with MVS 3.8j issues - Ivan Warren 14 Mar 2003 Increased tbuf in het_write due specs compress2 - Bernard van der He lm 13 Mar 2003 Tape support update - see README.TAPE - Ivan Warren 13 Mar 2003 Call build_config even if NO_SIGABEND_HANDLER is defined - Ivan Warr en 13 Mar 2003 Define extgui in dasdseq for Windows build - Ivan Warren 13 Mar 2003 AEA invalidation reduction - Greg Smith 13 Mar 2003 Gabor performance patch - optimize AEA invalidation - Greg Smith 13 Mar 2003 detab dasdseq.c - Jim Morrison 13 Mar 2003 New dasdseq.c and man/dasdseq.1 - Jim Morrison 10 Mar 2003 New man/cckddiag.1 manpage - Jim Morrison 10 Mar 2003 New man/Makefile.am (manpage support) - Jim Morrison 10 Mar 2003 New man/cckd.4 manpage - Jim Morrison 08 Mar 2003 Remove panel/socketdevice dependency - Jan Jaeger 08 Mar 2003 Increased tape max blk sz to 64K-1 in hercules for DFDSS support - Ivan Warren 08 Mar 2003 Increased max block size to 64k-1 for tapecopy - Ivan Warren 08 Mar 2003 Set Byte 1 Bit 3 on IntReq for D/T 3505 to prevent Reader tasks from dying and filling ERDS + set sense size to 4 - Ivan Warren 08 Mar 2003 correct decomptrk() no-compression cckddiag - Jim Morrison 07 Mar 2003 correct cckddiag build for Win - Jim Morrison 06 Mar 2003 Add cckddiag to build - Jim Morrison 06 Mar 2003 Relax numl1tab check - Greg Smith 03 Mar 2003 New cckddiag command; CCKD diagnostic tool - Jim Morrison 03 Mar 2003 Relax CCKD track validation algorithm - Ivan Warren 02 Mar 2003 Set ref and change bits on store status - Jan Jaeger 01 Mar 2003 IA32 assemler reduction - Greg Smith 01 Mar 2003 Remove dead code - Greg Smith 01 Mar 2003 Fix to cckdload - somitcw (by Greg) 01 Mar 2003 More SMP fixes - Greg Smith 01 Mar 2003 Fix configuration parser error - Ivan Warren 27 Feb 2003 3390 jumbo (-27) definition - Adam Thornton (by Greg) 26 Feb 2003 Add util/cvslvlck cvs level check by Jim Morrison 26 Feb 2003 Add Signal Adapter instruction - Jan Jaeger 20 Feb 2003 FBA devtype update + script command support - Ivan Warren (by Greg) 08 Feb 2003 Fix dasdload message verbosity test (was backwards) - Jay Maynard 08 Feb 2003 Fix eof/intrq mode saving in card reader initialization, add * to specify no file loaded - Jay Maynard 04 Feb 2003 Fix to dasdutil.c convert_tt - Jim Morrison (by Greg) 04 Feb 2003 Correct condition code on SLB instructions - Jan Jaeger 01 Feb 2003 Add changes for Mac OS X support - Paul Scott 01 Feb 2003 Fix dasdinit wrong trk 0 size - Greg Smith + sidmuc 31 Jan 2003 Command reject if path assignment is not supported (non-3480 ASSIGN/UNASSIGN CCW opcodes 0xB7 & 0xC7 only in tapedev.c) imhotepio [freige@fibertel.com.ar] by Fish 28 Jan 2003 Obtain intlock during all psw loads - Greg Smith 27 Jan 2003 TS might not set byte to 0xff - Greg Smith 24 Jan 2003 Disable syncio for fba due to problems - Greg Smith + Ivan 22 Jan 2003 Flush updated active cache entry if no active i/o - Greg Smith + Iva n 22 Jan 2003 SMP updates - Greg Smith 22 Jan 2003 Fix for regparm attribute problem - Greg Smith 14 Jan 2003 relax stress write and readahead criteria - Greg Smith 12 Jan 2003 select() kludge for win32 for high cpu - Greg Smith 10 Jan 2003 Display a reasonable error message if a track image is probably compressed using a locally unsupported compression algorithm (such as bzip2) - Greg Smith 09 Jan 2003 Require `-f' option for cckdcdsk & cckdcomp if file has OPENED bit on - Greg Smith 09 Jan 2003 Correct & enable DAS for S/370 - Jan Jaeger 08 Jan 2003 Add dummy fix page S/370 MVS assist - Jan Jaeger 07 Jan 2003 Updated cckd utilities (cckddump & cckdload) - Greg Smith 07 Jan 2003 Fix/recover possible cckd corruption - Greg Smith 07 Jan 2003 Add Region Relocate, I/O- External- and Wait-assists - Jan Jaeger 06 Jan 2003 delay exit in config.c to give time to display message - Fish 06 Jan 2003 minor changes to tapedev.c read_omadesc function - John Summerfield 06 Jan 2003 Pre-init residual to zero in tapedev execute_ccw - freige@fibertel.com.ar by Fish 06 Jan 2003 Fix to 'unbind_device' to remove listening socket from panel thread's select list before closing it. - Fish 04 Jan 2003 CTCI_Init (ctc_ctci.c): malloc working CTCBLK to work around gcc 3.x bug caused by large vars allocated on stack - Fish 03 Jan 2003 Fix fthreads to behave as pthreads does regarding return codes (conform to SUS (Single UNIX Specification) rather than DCE (Distributed Computing Environment) semantics; affected CTCI logic's 'timed_wait_condition' return code tests) - Fish 03 Jan 2003 Added ARCHMODE to other "IPL failure" messages too - Fish 27 Dec 2002 Added comprehensive details to README.CVS document - Fish 27 Dec 2002 Fix bug ctc logic to accept MAC addr in lieu of IP addr - Fish 27 Dec 2002 Fix warning about IFC_IOCtl in tuntap.c - Fish 27 Dec 2002 obtain_lock not needed to signal_condition in ctc logic - Fish 27 Dec 2002 Use sched_yield (not usleep) if can't enqueue ctc frame - Fish 27 Dec 2002 Rewrote ParseMAC function to fix subtle bug - Fish 27 Dec 2002 Fixed tt32stats command to work with new LCS CTC logic - Fish 27 Dec 2002 Un-tabbed ctc source modules - Fish 15 Dec 2002 Renumbered messages in printer.c and console.c - Jay Maynard 15 Dec 2002 Streamlining Windows build processing, add P4 support - Volker Bandk e 12 Dec 2002 Main storage addressing cleanup - Jan Jaeger 09 Dec 2002 Fix windows comiple errors in hsccmd.c - Jim Pierson 05 Dec 2002 Various fixes and roll back of 30/6 performance mods - Jan Jaeger 26 Nov 2002 Missing devtype.c FBA entries - Greg Smith and Ivan 23 Nov 2002 Remove cckd/het zlib dependency - Greg Smith 16 Nov 2002 Add MVCLU and CLCLU instructions - Jan Jaeger 16 Nov 2002 Add TROO, TROT, TRTO and TRTT instructions - Jan Jaeger 15 Nov 2002 Add extended translation facility 2 to ESA/390 mode - Jan Jaeger 14 Nov 2002 Corrections to opcode table and disassembler - Jan Jaeger 14 Nov 2002 New CTC and LCS emulation - Jim Pierson 14 Nov 2002 Add SVCA to z/Architecture mode - Jan Jaeger 07 Nov 2002 Correct execution controls - Jan Jaeger 29 Oct 2002 Make card reader eof/intrq parameter persistent - Jay Maynard 29 Oct 2002 Correct devinit command to work when only one argument is given - Jay Maynard 29 Oct 2002 Ignore 7-track mode set commands for tape drives - Andy Norrie 27 Oct 2002 Fix dasdisup to accept one argument - Jay Maynard 13 Oct 2002 64bit cmpsc fixes - Bernard van der Helm 12 Oct 2002 CKD fix when offset >= 2G - Greg Smith 03 Okt 2002 PER fixes - Jan Jaeger 01 Okt 2002 Fix for SSK/ISK/RRB - Juergen Dobrinski 19 Sep 2002 Fix cckd thrash for large fragmentations - Greg Smith 19 Sep 2002 Fix console.c to wait for initdone to listen - Greg Smith 30 Aug 2002 Fix MVCL to update regs prior to possible program check - Greg Smith 26 Aug 2002 Added "noprompt" option to turn off input prompting for 1052/3215 consoles - Jay Maynard 25 Aug 2002 Fix cckd free space chain corruption when freeing space for a `type 1' null track - Greg Smith & Volker Bandke 08 Aug 2002 Increased cckd shutdown serialization - Greg Smith 08 Aug 2002 Add 'Send" button in syslog cgi - Adam Thornton by Jan Jaeger 08 Aug 2002 AEA invalidation performance enhancement - Gabor Hofi by Greg Smith 03 Aug 2002 Fix dasdload to ignore comments in CBT XMIT files - Roger Bowler 03 Aug 2002 Change automagic to make NLS support work - Volker Bandke 30 Jul 2002 Compressed dasd tweaks - Greg Smith 26 Jul 2002 Compressed dasd enhanced free pending processing - Greg Smith 22 Jul 2002 Performance tweaks - Gabor Hofi & Greg Smith 22 Jul 2002 cckd options `nofsync' and `fsyncwa' - Greg Smith 21 Jul 2002 Update ieee-w32.h to compile under current Cygwin - Greg Smith 19 Jul 2002 Fix to cpu utilization percentage - Greg Smith 17 Jul 2002 New utility dasdcopy.c; replaces ckd2cckd and cckd2ckd and adds fba2cfba and cfba2fba function - Greg Smith 16 Jul 2002 New 'hmccmds.c' source module #included by 'panel.c'. - Fish 14 Jul 2002 UNTABBED all .c/.h source files (NO EMBEDDED TABS, please!) - Fish 14 Jul 2002 ** MAJOR CLEANUP ** Added -W compile option to see ALL warnings and corrected most signed/unisgned and unreferenced warnings; only 'ckddasd', 'cckddasd' and 'cckdutil' remain to be cleaned up - Fish 13 Jul 2002 Fix dasdutil.c to correctly detecte write error in created_ckd_file - Volker Bandke 11 Jul 2002 File integrity fixes for compressed dasd - Greg Smith 11 Jul 2002 New optional HTTPROOT control file statement - Fish 09 Jul 2002 Minor fix to OPTION_CPU_UTILIZATION to fix FISH_HANG issue - Fish 02 Jul 2002 CTC fix for TurboLinux bug - Jim Pierson 02 Jul 2002 3287 printer support via TN3270 - Tomas Masek 02 Jul 2002 S/370 extended memory fixes - Tomas Masek 02 Jul 2002 Fixes to ckdtab in dasdtab.c - Greg Smith 02 Jul 2002 Correct Erase All Unprotected 3270 order - Tomas Fott 01 Jul 2002 Complete IPL function in web interface - Jan Jaeger 30 Jun 2002 Fix minor "inet_ntoa" bug in 'connect_client' function reported by Mark Gaubatz [Mark.Gaubatz@verizon.net] - Fish 30 Jun 2002 Fix some minor issues relating to tape device handling contributed by hackules (http://www.geocities.com/hackules390/): - Fish h31: Fixes a problem with HET tapes on CD. h23: A minor fix to tapedev that corrects the setting of the chunk size for HET files. h09: Fixes a small bug in tapedev.c where a backspace file operation could muck up position info if already positioned at the start of the file. 30 Jun 2002 Calculate percent CPU utilization - Fish 29 Jun 2002 Gabor Hoffer performance patch: part 3 - Fish 27 Jun 2002 Fix validation intercept when no S/370 mode installed - Jan Jaeger 27 Jun 2002 Fix scpinfo CHSC bit - Jan Jaeger 27 Jun 2002 Remove MVCL overlap logging - Jan Jaeger 27 Jun 2002 Fix operand access id - Jan Jaeger 27 Jun 2002 Fix keyaccess on PGOUT - Jan Jaeger 23 Jun 2002 Fix for `no shadow file name' messages - Greg Smith 23 Jun 2002 Gabor Hoffer's performance patch: parts 1 & 2 -- Fish 23 Jun 2002 Fixes/enhancements for cckd chkdsk - Greg Smith 20 Jun 2002 Fix arch mode id in store status function - Jan Jaeger 19 Jun 2002 Set manufacterer to HRC for STSI - Jan Jaeger 18 Jun 2002 FBA dasdtab updates - Tomas Masek by Greg Smith 18 Jun 2002 Fix NRF condition for CKD dasd - Greg Smith 17 Jun 2002 Fix segmentation fault during cckd compress - Greg Smith 15 Jun 2002 configure.ac: Cygwin stack bug workaround - Matt and Fish 15 Jun 2002 cfba chkdsk fix - Greg Smith 15 Jun 2002 ckd internal trace support - Greg Smith 14 Jun 2002 Remove cfba debugs - Greg Smith 14 Jun 2002 Set `more' if residual data after fba write - Tomas Masek by Greg Sm ith 13 Jun 2002 Another cfba fix (segmentation fault after detach while trace active ) - Greg Smith 13 Jun 2002 READ BACKWARD support for tapes added - Volker Bandke (Original patc h: Hax 28 by Hackules) 12 Jun 2002 cfba/cckd/ckd fixes - Greg Smith 05 Jun 2002 Increase 3270 buffer to 64K as adding IAC bytes may cause overflow - Jan Jaeger 02 Jun 2002 Created "hercnls.h" module and fixed some typos/warnings - Fish 30 May 2002 Preliminary cfba (compressed fba) support - Greg Smith 30 May 2002 Various dasd fixes - Greg Smith 24 May 2002 Fixes for the cckd updates - Greg Smith 18 May 2002 More updates for cckd - Greg Smith 15 May 2002 Fix for MVPG problem as reported by Guy Przytula - Jan Jaeger 14 May 2002 Updates for cckd - Greg Smith 14 May 2002 Fix S/370 timer problem - Valery Pogonchenko 13 May 2002 NLS support for cckd utilities - Jan Jaeger 11 May 2002 NLS support - Jan Jaeger 08 May 2002 Fixes for 3350 dasdload - Greg Smith 08 May 2002 CodePage converion table 850/273 - Gerd Petermann 05 May 2002 Add some NLS definitions - Jan Jaeger 05 May 2002 Merge Debian patch to ckd2cckd.c to permit compilation with gcc 3.0, where printf may be a macro - Matt Zimmerman 04 May 2002 Fix panel.c attach command bug identified by Kris Van Hees since no on else has yet - Fish 01 May 2002 3390-9 and large file support - Greg Smith 01 May 2002 CodePage support - Jan Jaeger 29 Apr 2002 Fix fthreads "trylock" for REAL this time - Fish 29 Apr 2002 Create console thread dynamically - Jan Jaeger 25 Apr 2002 Hot fix for fthreads "trylock" oversight - Fish 21 Apr 2002 Fix various backwards merge problems with cckd - Greg Smith 19 Apr 2002 Fix cckdcdsk return code bug - Fish 18 Apr 2002 Disable syncio retry during IPL - Greg Smith 15 Apr 2002 IEEE floating point (attempt) for Win32 - Greg Smith 13 Apr 2002 Add description to ctci-w32 error message (w32ctca) - Fish 13 Apr 2002 Fix bug in w32chan "devtmax" logic (TrimDeviceThreads) - Fish 13 Apr 2002 Fix some benign warnings - Fish 13 Apr 2002 Move RC file processing to a separate thread - Fish 12 Apr 2002 Fix TRAP storing incorrect PSW in trap save area - Jan Jaeger 12 Apr 2002 Fix false specification exception in RP (64bit only) - Jan Jaeger 11 Apr 2002 Build device type table and device handler tables - Jan Jaeger 08 Apr 2002 Remove cckd garbage collection messages - Greg Smith 08 Apr 2002 "&comments on|off" logic deleted; '*' now "talking" comments, '#' now silent comments (per Willem's suggestion). - Fish 08 Apr 2002 (RESCINDED): display_version via stdout instead of stderr; set stdout/stderr to unbuffered (if externalgui) instead - Fish 08 Apr 2002 RC file handling: 1) new 'pause nnn' .rc-file-only command to sleep for 1-999 seconds, 2) accept and display comments from either the keyboard or the .rc file, 3) control .rc file comments logging via new "&comments on|off" .rc-file-command, 4) use buffered "fgets" call to read .rc file for efficiency, 5) silently ignore CR's in .rc file for Windows compatibility, 6) prefix logged commands from .rc file with "> ". -- Fish 08 Apr 2002 parse_args (config.c): 1) not EXTERNALGUI dependent, 2) support embedded quoted strings (sf="path") - Fish 08 Apr 2002 Update message buffer in exgui mode - Jan Jaeger 05 Apr 2002 Support cookies to save settings - Jan Jaeger 02 Apr 2002 hercload.html updated for cckd utility support - Greg Smith 28 Mar 2002 HTTP server - Jan Jaeger 24 Mar 2002 Fix ADRFMT definition in cmspc.c - Bernard van der Helm 21 Mar 2002 Fix MVPG so it works with Expanded Storage - Paul Leisy 20 Mar 2002 Sequential files now supported by dasdload.c - Greg Smith 17 Mar 2002 Fix Read-Configuration-Data and Sense-ID CIW - Greg Smith 17 Mar 2002 Common DASD tables (dasdtab.c & dasdtab.h) - Greg Smith 17 Mar 2002 DASD utilities cckd support - Greg Smith 16 Mar 2002 Fixed benign warnings in ctcadpt.c & un-tabbed file - Fish 15 Mar 2002 Fixed automagic for building standalone dasd utilities - Volker Band ke 09 Mar 2002 Lan Channel Station (LCS) support 09 Mar 2002 Initial cckd dasd utilities support - Greg Smith 07 Mar 2002 More service signal updates for AO support - Jan Jaeger 05 Mar 2002 Add test_lock macro and enhance ipending command with lock status on various locks - Jan Jaeger 05 Mar 2002 Merge sigpbusy into sigplock - Jan Jaeger 05 Mar 2002 Allow print to pipe for Win32 (future print spooling) - Fish 05 Mar 2002 Fix print to pipe bug so broken pipe is detected - Fish 05 Mar 2002 stop/start printer support - Fish 04 Mar 2002 Fix load_hmc() with null filename - Jan Jaeger 04 Mar 2002 Support composite service signals - Jan Jaeger 03 Mar 2002 Remove ckd and cckd sysblk dependencies in prep for cckd dasd utility support - Greg Smith 02 Mar 2002 Display version info via stdout instead of stderr - Fish 02 Mar 2002 Added #include to hercules.h and some #ifdefs in a few places to fix some compiler warnings, and fixed a few minor typos here and there - Fish 02 Mar 2002 external gui support to dasdcat - Fish 01 Mar 2002 Fix and simplify cckd chkdsk default processing - Greg Smith 01 Mar 2002 Fix priority of PIC 13 for PT - Paul Leisy 01 Mar 2002 Fix cancel_subchan if OPTION_FISHIO - Greg Smith 28 Feb 2002 Allow for cr/lf in 3215 code and change ebcdic to ascii convertion table entry x'15' from x'b4' to x'0a' - Jan Jaeger 26 Feb 2002 `sf-xxx nomerge' rebuilds current shadow file if previous file is `read-only' - Greg Smith 26 Feb 2002 Set ILC=4 when an EX with PER is to an SVC - Paul Leisy 26 Feb 2002 Fix RP so it doesn't Space Switch in REAL mode - Paul Leisy 26 Feb 2002 Fix TRAP in GUEST so Change Bit not set on PIC 04 - Paul Leisy 25 Feb 2002 Don't signal CLKC/CPT interrupts if already pending - Greg Smith 24 Feb 2002 XSCH now removes i/o requests from the i/o queue - Jan Jaeger 24 Feb 2002 Fixes for CLMH, LCTLG and CVBG - Jan Jaeger 24 Feb 2002 Updates for cckd - Greg Smith 22 Feb 2002 IODELAY defaults to `800' if `OSTAILOR LINUX' - Greg Smith 22 Feb 2002 IODELAY kludge for linux - Greg Smith 22 Feb 2002 Allow comments in hercules.rc file (start with #) - Paul Leisy 22 Feb 2002 Correct BFP behavior in GUEST mode - Paul Leisy 22 Feb 2002 Fix missing PER in GUEST mode when HOST rupt icept - Paul Leisy 20 Feb 2002 Print to pipe - Roger Bowler 19 Feb 2002 Fix pending interrupts on other cpus channelset - Jan Jaeger 15 Feb 2002 Fix interval timer state retention - Jan Jaeger 13 Feb 2002 Fix TS intercept test - Paul Leisy 13 Feb 2002 Fix TXA for HOST PIC 04 fault on GUEST stack access - Paul Leisy 13 Feb 2002 Throw out Store PER when merged with null/supr rupts - Paul Leisy 13 Feb 2002 Make CS, CDS, CSP behave consistently: always store - Paul Leisy 11 Feb 2002 ISK, SSK missing 2k/4k check in 370 native - Paul Leisy 11 Feb 2002 Fix SIGP Initial Program Reset (S/370) - Jan Jaeger 08 Feb 2002 Fix RRB in 370 guest - Paul Leisy 06 Feb 2002 Fix cckdcdsk space/recovery/gap table malloc() - Greg Smith 05 Feb 2002 dasdinit utility support for specifying alternate cylinders - Fish 05 Feb 2002 dasdinit utility support for most every device type - Fish 05 Feb 2002 Asm assists for memory synchronization - Greg Smith 04 Feb 2002 Fix Ifetch PER flag in State Desc, Fix LCTL intercepts - Paul Leisy 04 Feb 2002 Fix very minor memory leaks in sockdev logic - Fish 03 Feb 2002 Close hercules configuration file after processing - Volker Bandke 03 Feb 2002 Added PGMPRDOS config parameter - Jay Maynard 03 Feb 2002 Performance tweaks - Greg Smith 01 Feb 2002 CTCI-W32 (Win32 CTCA protocol using WinPcap) - Fish 31 Jan 2002 Fix PER in guest for OPTION_CPU_UNROLL - Paul Leisy 30 Jan 2002 Fix SIE validity checks and intercepts - Paul Leisy 29 Jan 2002 Fix pending I/O interrupt when enabling I/O subclass - Jan Jaeger 28 Jan 2002 PER fix for BCTR and move #endif for FEATURE_PER2 - Paul Leisy 27 Jan 2002 Documentation updates for TCP/IP and Socket Readers - Roger Bowler 25 Jan 2002 Include Malcolm Beattie's dasdcat program - Roger Bowler 25 Jan 2002 More PER fixes for PR and addr wrap fix for MVCL - Paul Leisy 24 Jan 2002 PER fixes for PR and MVCL - Paul Leisy 20 Jan 2002 dasdinit can now create a cckd file - Greg Smith 17 Jan 2002 Add PER storage checks for TRAP accesses - Paul Leisy 17 Jan 2002 Fix PER rupt TEA for PC, PR and PT - Paul Leisy 16 Jan 2002 Synchronous I/O fixes - Greg Smith 15 Jan 2002 Add PER checks to MVCL - Paul Leisy 14 Jan 2002 Device subclass priority (try #1) - Greg Smith 14 Jan 2002 Improve cckd initialization time - Greg Smith 11 Jan 2002 Gabor Hoffers performance updates 11 Jan 2002 Fix ifetch performance so it works with PER - Juergen Dobrinski 06 Jan 2002 CMPSC kludge for Cygwin gcc faulty linkage - Greg Smith 05 Jan 2002 Make sure that {fthreads,w32chan}.c go into dist - Matt Zimmerman 02 Jan 2002 Change store of percode in PSA to use realregs->perc - Paul Leisy 02 Jan 2002 Fix stack and BCT per checks - Paul Leisy 02 Jan 2002 Don't set STORE PER when operand specified as REAL - Paul Leisy 30 Dec 2001 Fix for cckd and big-endian - Greg Smith 23 Dec 2001 OPTION_LPP_RESTRICT - Jan Jaeger 23 Dec 2001 Selective ArchMode build options - Jan Jaeger 18 Dec 2001 Make sure PC, PR, PT state switch when pending PER - Paul Leisy 18 Dec 2001 Fix up ILC for PR when PER interrupt - Paul Leisy 18 Dec 2001 Zero STD ID part of PER code for STURA - Paul Leisy 18 Dec 2001 For SSM, LPSW, purge Herc Op cache when PER bit on - Paul Leisy 18 Dec 2001 Move PERAID update to store accesses only - Paul Leisy 18 Dec 2001 Fix trace entry for BSG - Paul Leisy 18 Dec 2001 Add Branch PER check to BCT - Paul Leisy 18 Dec 2001 Add Store PER check to Stack accesses - Paul Leisy 18 Dec 2001 Check odd IA before IFetch PER - Paul Leisy 16 Dec 2001 Do not process PER in native BC mode - Jan Jaeger 16 Dec 2001 Correct PER for S/370 under SIE - Jan Jaeger 16 Dec 2001 Add missing obtain intlock to sie.c - Greg Smith 16 Dec 2001 Add channel set switching feature - Jan Jaeger 16 Dec 2001 Complete MP for S/370 - Jan Jaeger 14 Dec 2001 Fix BSM instruction for z/OS - Greg Smith 12 Dec 2001 Correct SIE intercept with concurrent PER indication - Jan Jaeger 09 Dec 2001 SIE PER enhancements - Jan Jaeger 06 Dec 2001 Basic PER implemention - Jan Jaeger 05 Dec 2001 Corrected ref and change bits on loadtext - Jan Jaeger 04 Dec 2001 Rewrite of trace including full 64 bit support - Jan Jaeger 28 Nov 2001 Reset device status in device_reset() for ckd dev - Jan Jaeger 28 Nov 2001 Alignment fixes for SPARC64 - Matt Zimmerman 28 Nov 2001 Bypass syncio if track overflow or data chaining - Valery Pogonchenko 28 Nov 2001 Remove SIGHUP usage - Jan Jaeger 28 Nov 2001 Fix interval timer - Jan Jaeger 28 Nov 2001 Fix unintended exit when CPU 0 is deconfigured - Matt Zimmerman 22 Nov 2001 Cancel Subchannel (XSCH) function and instruction - Jan Jaeger 21 Nov 2001 OPTION_SYNCIO *is* compatible with OPTION_FISHIO - Greg Smith 18 Nov 2001 Synchronous I/O - Greg Smith 18 Nov 2001 Add OPTION_IODELAY to bypass linux/zseries bug - Jan Jaeger 18 Nov 2001 Change OSTAILOR LINUX to reflect IEEE support - Jan Jaeger 18 Nov 2001 Add LCEBR/LCDBR/LCXBR IEEE float instructions - Jan Jaeger 16 Nov 2001 Reduce timer.c pthreads calls and logic isolation - Greg Smith 16 Nov 2001 Correct storage keys after ipl from cdrom - Jan Jaeger 16 Nov 2001 Added savecore command - Jan Jaeger 15 Nov 2001 RCHP and SCHM fixes for PIC 15 - Paul Leisy 13 Nov 2001 Fix MVPG so it gets PIC 04 when FPO on - Paul Leisy 13 Nov 2001 Fix CUSE when last byte is part of equality - Paul Leisy 13 Nov 2001 Fix halt and clear subchannel on CTC type devices - Jan Jaeger 13 Nov 2001 Fix logmsg macro to appear as a singular statement - Jan Jaeger 09 Nov 2001 Add HMC cdrom type IPL support - Jan Jaeger 09 Nov 2001 Fix hang in synchronize_broadcast - Greg Smith 09 Nov 2001 Make MODEL_DEPENDENT more specific with CS and STCM - Paul Leisy 08 Nov 2001 Correct/Remove OPTION_REDUCE_INVAL miss-spelling - Paul Leisy 05 Nov 2001 RP needs to INVALIDATE_AEA() since AR loaded - Paul Leisy 02 Nov 2001 Fix SQXR when iteration results are off by 1 - Paul Leisy 02 Nov 2001 Fix one IPTE bug by adding INVALIDATE_AxA() - Paul Leisy 31 Oct 2001 OPTION_FISHIO only if fthreads and not OPTION_SYNCIO - Fish 31 Oct 2001 'KillAllDeviceThreads' function disabled - Fish 31 Oct 2001 CTC Channel Command retry (contributed by Jim Pierson) - Fish 31 Oct 2001 Fix CFDR so overflow check done after rounding - Paul Leisy 31 Oct 2001 Fix MVCL so unused R1 and R2 bits zeroed - Paul Leisy 31 Oct 2001 Add "loadtext" panel command to load text decks - Paul Leisy 31 Oct 2001 Add "QUIET" ostailor option so all pgmtrace disabled - Paul Leisy 28 Oct 2001 Added WAKEUP_CPU call to stop/stopall commands in panel.c to fix "ipl rejected: All CPU's must be stopped" problem - Fish 28 Oct 2001 Various fixes to cardrdr.c - Fish 26 Oct 2001 Fix EX page cross, add INVALIDATA_AIA() - Juergen Dobrinski 25 Oct 2001 updated hercconf.html with new 'sockdev' reader option - Fish 25 Oct 2001 minor extgui tweak to better detect when cpu stopped - Fish 25 Oct 2001 rearranged DEVBLK structure (I hope it's better) - Fish 25 Oct 2001 sockdev no longer requires ascii only; ebcdic now ok - Fish 25 Oct 2001 Fix cardpch bug causing padding to fail on ebcdic o/p - Fish 25 Oct 2001 OPTION_BUFFERED_RDR rescinded/deprecated; using standard 'C' fread/getc, etc. instead (Thanks Matt & Willem) - Fish 22 Oct 2001 Fix another SQXR bug - Paul Leisy 17 Oct 2001 Big-endian support and endian conversion - Greg Smith 16 Oct 2001 OPTION_BUFFERED_RDR - Fish 16 Oct 2001 Hot Reader support (sockdev = socket devices) - Fish (mostly Malcolm Beattie's inspiration; implemented by me) 13 Oct 2001 synchronize_broadcast fix for SMP - Greg Smith 12 Oct 2001 Win32 fthreads (finally!) - Fish 11 Oct 2001 Remove Cygwin warnings displaying TID - Greg Smith 11 Oct 2001 SMP performance - phase 4 - I/O interrupt queue - Greg Smith 11 Oct 2001 cckd fixes - Greg Smith 11 Oct 2001 SMP performance - phase 3 - synchronize_broadcast enhanced - Greg Smith 11 Oct 2001 SMP performance - phase 2 - intcond for each CPU - Greg Smith 11 Oct 2001 SMP performance - phase 1 - remove usleep(1) by default from CS instructions - Greg Smith 10 Oct 2001 Define "signal_thread" macro as a 'nop' for WIN32 builds 10 Oct 2001 Add IS_CCW_SET_EXTENDED test to channel.c's write-ccw handling logic to fix a problem that was preventing TCP/IP in VM from working on CTC adapter devices (fix contributed by Kris Van Hees) 03 Oct 2001 Move INVALIDATE_AIA out of optimization - Juergen Dobrinski 02 Oct 2001 Fix MVPG to work in pageable guest - Paul Leisy 02 Oct 2001 Fix TRAP to work in pageable guest - Paul Leisy 28 Sep 2001 Fix MVCL bugs with new fast path code - Paul Leisy 28 Sep 2001 Restore change bit fixes to vstore.h - Paul Leisy 17 Sep 2001 Minor corrections to CEFR, CDFR, CXFR and MVPG - Jan Jaeger 13 Sep 2001 CXR setting wrong cc when fract=0 but char not - Paul Leisy 13 Sep 2001 Fix TRAP so page cross rupt does not set change bit - Paul Leisy 13 Sep 2001 MVPG missing TEA bit 29 and OP ACCESS ID on PIC 11 - Paul Leisy 13 Sep 2001 MVPG should report PIC 11 on Page Table Length violation - Paul Leis y 13 Sep 2001 Fix BSG so ALET=1 is always treated as subspace - Paul Leisy 06 Sep 2001 Add FPO crossing checks to all storage fetches - Paul Leisy 06 Sep 2001 Fix RP so trace entry finished on PIC 1C - Paul Leisy 30 Aug 2001 Fix Change Bit in Key so on page crossers with rupt it's not set. Done by using new acctype ACCTYPE_WRITE_SKP - Paul Leisy 28 Aug 2001 Change FPR display so if BASIC FP EXTENSIONS all displayed - Paul Le isy 28 Aug 2001 Change MVCLE cpu-determined length - Paul Leisy 26 Aug 2001 Added test for file-existance in cardrdr.c (code suggested by Richar d Snow) - Volker Bandke 24 Aug 2001 Add optional address parm to loadcore panel command - Michael Ackers on 23 Aug 2001 Fix general1.c so commented statements don't wrap to 2 lines - Paul Leisy 23 Aug 2001 LXD missing PIC 06 when R1 not valid - Paul Leisy 23 Aug 2001 CFXR needs to test overflow after rounding - Paul Leisy 23 Aug 2001 BSG failed to set subspace active in DUCT - Paul Leisy 20 Aug 2001 LKPG setting wrong cc - Paul Leisy 20 Aug 2001 Just set cc when r1=r2 for CUSE - Paul Leisy 20 Aug 2001 CUUTF wrong cc when len1 = 0 and len2 = 1 - Paul Leisy 20 Aug 2001 Fix SQXR div by 0 and others and SQDR hang - Paul Leisy 20 Aug 2001 Fix RP so ILC is correct for PIC 1C - Paul Leisy 20 Aug 2001 PLO needs INVALIDATE_AEA() when in AR mode - Paul Leisy 20 Aug 2001 CLM should get access rupts if mask = 0 - Paul Leisy 20 Aug 2001 PC was missing PIC 13 - Paul Leisy 06 Aug 2001 Machine check/checkstop/malfunction alert support for host exception/loop/wait errors - Jan Jaeger 03 Aug 2001 Fix CLST condition code when 2nd op = end char - Paul Leisy 03 Aug 2001 LCXR was not making true zero - Paul Leisy 03 Aug 2001 Fix BSG so excarid is correct on PIC 2B - Paul Leisy 03 Aug 2001 Fix TRAP so TEA bit 29 not set on key prot - Paul Leisy 03 Aug 2001 RP missing AND with ADDRESS_MAXWRAP - Paul Leisy 03 Aug 2001 CVB missing AND with ADDRESS_MAXWRAP - Paul Leisy 01 Aug 2001 PLO not saving ALET from parm list in AR when zero - Paul Leisy 01 Aug 2001 Fix CUTFU condition code when len1 = 0 - Paul Leisy 01 Aug 2001 Add stor-prot-override to TRAP accesses - Paul Leisy 01 Aug 2001 Fix CE and CDR cc when fraction is zero - Paul Leisy 01 Aug 2001 Change cpu-determined number for SRST - Paul Leisy 27 Jul 2001 BSA missing INVALIDATA_AEA, not ANDing CR3 - Paul Leisy 27 Jul 2001 TRAP missing key-ctl protection - Paul Leisy 24 Jul 2001 Add CPUPRIO config statement - Jan Jaeger 24 Jul 2001 Add SETMODE setuid support - Jan Jaeger 23 Jul 2001 RP not making trace entry - Paul Leisy 23 Jul 2001 TRAP not making trace entry - Paul Leisy 23 Jul 2001 Fix ILC when PR gets PIC 1C - Paul Leisy 23 Jul 2001 Change order of stores for PLO - Paul Leisy 23 Jul 2001 LCXR low order sign incorrect - Paul leisy 19 Jul 2001 Remove invalid guestpsw bypass fix - Jan Jaeger 17 Jul 2001 Fix BSA so PIC 16 does nullification - Paul Leisy 17 Jul 2001 Another fix to TRAP and page cross - Paul Leisy 17 Jul 2001 More fixes to CUTFU, CUUTF - Paul Leisy 13 Jul 2001 Correct excarid on MVPG PIC 04 - Paul Leisy 13 Jul 2001 Fix PR trace table entry - Paul Leisy 13 Jul 2001 CUTFU, CUUTF not setting cc=1 when len1=0 - Paul Leisy 13 Jul 2001 Further CMPSC fixes - Bernard van der Helm 12 Jul 2001 Fix CEFR when converting 0x80000000 - Paul leisy 12 Jul 2001 Fix BSG trace entry for 24bit mode - Paul Leisy 12 Jul 2001 Fix BSA so it traces when R2=0 - Paul Leisy 11 Jul 2001 "sh" shell command support for Win32 builds - Fish 11 Jul 2001 UPT fails to detect CC=3 condition - Paul Leisy 11 Jul 2001 Fix CXFR characteristic and LEXR shift amount - Paul Leisy 11 Jul 2001 Fix BSA load of CR3 and TAR wrong CC - Paul Leisy 10 Jul 2001 CUSE setting wrong cc & unused bits not cleared - Paul Leisy 10 Jul 2001 RP setting PROB bit in PSW - Paul Leisy 10 Jul 2001 BSG builds incorrect trace entry - Paul Leisy 10 Jul 2001 TRAP not set PRI mode, form_stack_entry miss PIC 04 - Paul Leisy 10 Jul 2001 switch PIC 07 and PIC 06 priority on MP - Paul Leisy 10 Jul 2001 EREG missing INVALIDATE_AEA - Paul Leisy 10 Jul 2001 PIC 04(ALE) and PIC 05(STE/PTE) wrong priority - Paul Leisy 10 Jul 2001 TRAP miss page cross and false PIC 04 - Paul Leisy 10 Jul 2001 CLCL missing gpr update on page cross rupt - Paul Leisy 10 Jul 2001 Make Assist ops use PRI addr in AR mode - Paul Leisy 10 Jul 2001 Load/Store psw use bits 24-31 - Paul Leisy 10 Jul 2001 Report PIC 06 on PR at end of inst - Paul Leisy 09 Jul 2001 Fix TRAP so it receives PIC13 in REAL - Paul Leisy 09 Jul 2001 Fix CUSE and MVST on page cross rupts - Paul Leisy 09 Jul 2001 Fix UPT so GPR5 updated after store - Paul Leisy 07 Jul 2001 Fix sporadic access violation at shutdown - Fish 05 Jul 2001 Restrict TODEPOCH to 1900, 1928, 1960, 1970, or 1988, and correct offset calculation - Michael Koehne 05 Jul 2001 Add unmount option to HET code - Michael Koehne 05 Jul 2001 Add quiet command to shut off status messages to panel - Michael Koehne 05 Jul 2001 Add ARCHMODE to HHC105I IPL failure message - Fish 05 Jul 2001 Add multifile parameter to card reader definition - Fish 05 Jul 2001 Increase panel command buffer length to 32K - Fish 21 Jun 2001 Add disassembly function - Jan Jaeger 20 Jun 2001 CMPSC armode fix - Bernard van der Helm 20 Jun 2001 CTCT CTC over TCP/IP support - Vic Cross 20 Jun 2001 Remove subchannel enabled check from console - Jan Jaeger 19 Jun 2001 Correct check for MVCL in different spaces - Jan Jaeger 19 Jun 2001 Prevent msg HHC611I during machine check - Jan Jaeger 19 Jun 2001 Enhance MVCL cc3 diagostics - Jan Jaeger 18 Jun 2001 Add missing obtain_lock(devlock) to halt function - Fish 18 Jun 2001 Reset channel path function - Jan Jaeger 17 Jun 2001 Address limit checking - Jan Jaeger 16 Jun 2001 Correctons to LPGFR/LNGFR/LCGFR - Jan Jaeger 16 Jun 2001 Fix index-symbol translation - Bernard van der Helm 16 Jun 2001 TLB implementation for z/Architecture - Jan Jaeger 15 Jun 2001 Fix interrupt key processing - Jan Jaeger 13 Jun 2001 Zero highbyte in 24 bit branch trace entry - Paul Leisy 13 Jun 2001 Correct attention processing on suspended devices - Jan Jaeger 13 Jun 2001 Clear DPS arrays during I/O reset - Jan Jaeger 13 Jun 2001 Fix false protection indication on MVPG - Paul Leisy 11 Jun 2001 Initialize conditions & locks earlier in init routine, including initializing cachelock (thanks Fish) - Greg Smith 11 Jun 2001 Correct excarid in ESAME mode - Jan Jaeger 10 Jun 2001 Correct tea on MVPG protection exception - Paul Leisy 10 Jun 2001 Correct halt subchannel function - Jan Jaeger 10 Jun 2001 Correct set pathgroup id ccw - Jan Jaeger 10 Jun 2001 Correct clear subchannel function - Jan Jaeger 09 Jun 2001 Fix CUTFU/CUUTF with zero op2 length - Paul Leisy 09 Jun 2001 Fix STSI condition code - Paul Leisy 09 Jun 2001 Add t+ckd/t-ckd ckd keytrace command - Valery Pogonchenko 03 Jun 2001 Fix TRAP save area access - Paul Leisy 03 Jun 2001 Fix priority of interruptions in stacking PC - Jan Jaeger 03 Jun 2001 Fix priority of interruptions in BAKR - Paul Leisy 03 Jun 2001 Fix typo in setting amode in BSA - Paul Leisy 02 Jun 2001 Moved IEEE option from featall.h to makefile.w32 - Jan Jaeger 02 Jun 2001 Correct tea on asx translation exception in PC - Paul Leisy 02 Jun 2001 Fix update of GR5 in UPT - Paul Leisy 01 Jun 2001 Clear effective and instruction address cache in BSG - Paul Leisy 01 Jun 2001 Correct TEA stid identification bits - Paul Leisy 31 May 2001 Correct TLB purging on SIE dispatch - Jan Jaeger 31 May 2001 IVSK SIE fix - Paul Leisy 30 May 2001 Added CHSC channel subsystem call instruction - Jan Jaeger 28 May 2001 Fix logic error in CPU interlocking - Jan Jaeger 28 May 2001 Wakeup waiting CPU when interrupt key is processed - Jan Jaeger 27 May 2001 Correct mainstorage interlocked update/reference - Jan Jaeger 26 May 2001 Add _REENTRANT and _THREAD_SAFE flags - Jan Jaeger 25 May 2001 Various multi processing and SIE fixes - Jan Jaeger 24 May 2001 Performance enhancements - Juergen Dobrinski 24 May 2001 Added CGEBR/CGDBR - Jan Jaeger 24 May 2001 Added CEGBR/CDGBR - Kris 23 May 2001 CKD 9345 support - Greg Smith 21 May 2001 Correct availability of N3 instructions in S/390 mode - Jan Jaeger 19 May 2001 Compression corrections - Bernard van der Helm 19 May 2001 Correct multiply/divide long - Jan Jaeger 19 May 2001 Correct RCP host address when nonzero MSO - Paul Leisy 18 May 2001 Correct CEFBR/CFEBR register use - Jan Jaeger 18 May 2001 Correct STOSM/STNSM interception - Paul Leisy 18 May 2001 Correct TRAP save area page crosser - Paul Leisy 18 May 2001 Correct operation exception interception - Paul Leisy 17 May 2001 Correct address wrap when SIE is interrupted - Jan Jaeger 17 May 2001 Correct specification exception interception - Jan Jaeger 16 May 2001 Correct CPU addr in PSA during external interrupts - Paul Leisy 15 May 2001 Correct STFL installed facility bit settings - Jan Jaeger 15 May 2001 Correct PR register update - Jan Jaeger 15 May 2001 Correct prefix storage key update in TPI - Jan Jaeger 15 May 2001 Correct TEA on STURA/LURA protection exception - Paul Leisy 09 May 2001 Correct TRT address wrap - Paul Leisy 08 May 2001 Fixes for RP instruction - Paul Leisy 08 May 2001 Fix gr15 in TRAP instruction - Paul Leisy 07 May 2001 CMPSC fix - Bernard van der Helm 07 May 2001 Correct false data exception in CVDG - Jan Jaeger 06 May 2001 Fix to Lock Page - Jan Jaeger 06 May 2001 Complete Storage Key Assist - Jan Jaeger 06 May 2001 Complete Move Page Facility 2 - Jan Jaeger 04 May 2001 Correct fbadasd.c syntax error - Greg Smith 04 May 2001 Correct RRB/RRBE rcpkey - Paul Leisy 03 May 2001 Try to open FBA emulated device readonly if open for readwrite failed. Allows Linux/390 to be installed from cdrom - Greg Smith 03 May 2001 Allow `readonly' to be specified for shadowed ckd or cckd devices. Base file will be opened O_RDONLY. - Greg Smith 03 May 2001 Enablement of ISKE/RRBE/SSKE in S/370 mode - Valery Pogonchenko 03 May 2001 Correction to oldpsw during ifetch - Jan Jaeger 30 Apr 2001 Correct SIE guest interrupt subclass enablement - Jan Jaeger 28 Apr 2001 Temporarily intercept move page (SIE) - Jan Jaeger 28 Apr 2001 Add move page to z/Arch - Jan Jaeger 28 Apr 2001 Fix RRBE RCP index error - Paul Leisy 27 Apr 2001 Fix STCM(G) with zero mask - Paul Leisy 26 Apr 2001 Change unsupported config statements erros to warnings - Jan Jaeger 26 Apr 2001 Correct old psw during ifetch exception - Paul Leisy 26 Apr 2001 Correct setting of fetch bit in SSKE under SIE - Paul Leisy 24 Apr 2001 Fixed ckd2cckd bug for multi-file ckd disks - Greg Smith 24 Apr 2001 Added error detection code to ckd2cckd and cckd2ckd - Greg Smith 24 Apr 2001 Fixed potential errors in cckd backwards merge (sf-) - Greg Smith 24 Apr 2001 Reduced CCKD_MAX_DFWQ_DEPTH to 8 for WIN32 otherwise 32 - Greg Smith 22 Apr 2001 cckd2ckd not stopping if -cyl specified - Greg Smith 22 Apr 2001 add ISKE, RRBE and SSKE to 370 mode - Valery Pogonchenko 22 Apr 2001 ckd fix Read Count setting index marker - Valery Pogonchenko 22 Apr 2001 ckd fix processing multitrack read ops - Valery Pogonchenko 22 Apr 2001 cmpsc fixes for expansion - Greg Smith 22 Apr 2001 Correct prefix alignment for ESA/390 guest in 64 bit mode SIE - Jan Jaeger 21 Apr 2001 Added support for muliple files in card reader 21 Apr 2001 Added support auto-padding of ebcdic files in card reader 21 Apr 2001 Added support for builtin tun driver of linux kernel 2.4.x 17 Apr 2001 Fix SSKE rcp guest ref and change bits - Paul Leisy 18 Apr 2001 Fix CPU TIMER interrupt processing - Jan Jaeger 17 Apr 2001 Device I/O thread throttling - Greg Smith & Fish 17 Apr 2001 Fix ISKE rcp index - Paul Leisy 16 Apr 2001 `-malign-double' removed from makefile - Greg Smith 16 Apr 2001 Read-track fix reintroduced after being deprecated - Greg Smith 16 Apr 2001 iobuf in channel.c is now malloc'ed to reduce out of memory errors under Cygwin - Greg Smith 16 Apr 2001 Reintroduced OPTION_NO_DEVICE_THREAD - Jan Jaeger 15 Apr 2001 featall.h: #define OPTION_NO_IEEE_SUPPORT for WIN32 builds ( has not been ported by CygWin yet) 13 Apr 2001 Correction to CVDG - Jan Jaeger 09 Apr 2001 Fix intlock access in clock and timer routines - Jan Jaeger 08 Apr 2001 Small optimization of vstore/vfetch - Jan Jaeger 08 Apr 2001 Correction to SIGP Set Architecture Mode - Jan Jaeger 08 Apr 2001 Small optimization of TPI - Jan Jaeger 08 Apr 2001 Correction to SCHM in 64 bit mode - Jan Jaeger 08 Apr 2001 Correction to TB in amode 64 - Jan Jaeger 06 Apr 2001 Read-track released dfwlock too soon when track found in dfw queue 04 Apr 2001 Sense/Set Path Group ID for DASD - Jan Jaeger 02 Apr 2001 Correction to register unstacking logic - Jan Jaeger 04 Apr 2001 #define MAX_DEVICE_THREAD_IDLE_SECS 300 02 Apr 2001 Fixed device_thread race condition in channel.c 02 Apr 2001 Added support for [Windows] External GUI 01 Apr 2001 Correction to Lock Page - Jan Jaeger 28 Mar 2001 Fix nullification problem in form_stack_entry - Jan Jaeger 27 Mar 2001 Fix exception access id in BSG - Jan Jaeger 27 Mar 2001 Fix exception access id during subspace replacement - Jan Jaeger 27 Mar 2001 Fix translation exception address in ESAME mode - Jan Jaeger 27 Mar 2001 Correction to ckd2cckd for small ckd files - Greg Smith 25 Mar 2001 Correction to LPQ/STPQ - Jan Jaeger 25 Mar 2001 Correction to MVCK/MVCP/MVCS - Jan Jaeger 25 Mar 2001 Dynamic device threads - Jan Jaeger 23 Mar 2001 Set `unit check' status when EOF CKD record read even if count field is zero - Greg Smith 23 Mar 2001 Bypass number of cylinder check in cckdcdsk.c - Greg Smith 22 Mar 2001 Implement XSTORE in ESAME mode - Jan Jaeger 22 Mar 2001 Implement fast interrupt processing for MCK and PER - Jan Jaeger 22 Mar 2001 Correct interruption identification word - Jan Jaeger 22 Mar 2001 Correct interrupt mask setting in LCTL/LTCLG - Jan Jaeger 22 Mar 2001 Correct SSM/STOSM spec exc in ESAME mode - Jan Jaeger 21 Mar 2001 Correct cache invalidation in PR - Greg Smith 20 Mar 2001 Correction to 64 bit SIGP initial_cpu_reset - Jan Jaeger 18 Mar 2001 Correction to stack types in ESAME mode - Jan Jaeger 18 Mar 2001 Correct LRA/LRAG segment table entry address on cc 3 - Jan Jaeger 18 Mar 2001 Correct address types in move char instructions - Jan Jaeger 18 Mar 2001 Correct subspace_replace address type - Jan Jaeger 16 Mar 2001 Fix to allow HET files to reside on read-only media - Leland Lucius 16 Mar 2001 Fix LPSW in ESAME mode - Jan Jaeger 15 Mar 2001 Compressed CKD utilities now tolerate VM weirdness - Greg Smith 15 Mar 2001 Alternate tracks for compressed CKD volumes - Greg Smith 15 Mar 2001 Utilities display versioning and copyright info - Greg Smith 15 Mar 2001 Invalidate AEA and AIA cache on SIE entry/exit - Jan Jaeger 15 Mar 2001 Present device end on terminating console session - Jan Jaeger 13 Mar 2001 Fix address types in assist/float/ieee instructions - Jan Jaeger 10 Mar 2001 Stop all CPU's in release_config - Jan Jaeger 10 Mar 2001 Fix CPU entering manual state on disabled wait - Jan Jaeger 10 Mar 2001 Various fixes to configurable features logic - Jan Jaeger 08 Mar 2001 Fix ESAME Add/Subtract/Multiply/Divide when both operands address same register - Jan Jaeger 07 Mar 2001 Correction to MLG/MLGR - Jan Jaeger 07 Mar 2001 Add sh panel command - Bernard van der Helm 07 Mar 2001 Add 9221 power-off diagnose - Jan Jaeger 05 Mar 2001 Correction to RP - Peter Stammbach 05 Mar 2001 Correction to DIAG204 - Jan Jaeger 05 Mar 2001 64 Bit fix to program_return_unstack - Jan Jaeger 05 Mar 2001 SIE corrections to EPSW and STFL - Jan Jaeger 05 Mar 2001 ESAME SIE SKA fix for SSKE/RRBE/ISKE - Jan Jaeger 04 Mar 2001 Multi architecture debug format enhancements - Peter Stammbach 03 Mar 2001 Correct store_psw during SIE interception - Jan Jaeger 03 Mar 2001 Correct trap control block - Roger Bowler 02 Mar 2001 Correction storage key updates by subchannels - Jan Jaeger 01 Mar 2001 Correction to TRAP2/TRAP4 - Paul Leisy 01 Mar 2001 Fix restart in ESAME mode - Jan Jaeger 01 Mar 2001 Correction to SIGP set architecture mode - Jan Jaeger 01 Mar 2001 SIE guest/host storage mapping corrections - Jan Jaeger 01 Mar 2001 Multi architecture fix for device threads - Juergen Dobrinski 28 Feb 2001 Correction to SIE interception parameters - Jan Jaeger 28 Feb 2001 Move Lock Page logic from dat.h to control.c - Jan Jaeger 27 Feb 2001 Add instructions marked N3 to ESA/390 - Jan Jaeger 27 Feb 2001 CVDG/CVBG instructions - Roger Bowler/Jan Jaeger 26 Feb 2001 Fix CDSG nullification on pagefault - Jan Jaeger 26 Feb 2001 Modification to 64 bit SIE - Jan Jaeger 25 Feb 2001 Fix PC/PT ltd origin in 64 bit mode - Jan Jaeger 25 Feb 2001 Improved interrupt processing - Valery Pogonchenko 25 Feb 2001 Fix private space bit to apply to real spaces - Jan Jaeger 25 Feb 2001 Add (incomplete) TRACG instruction - Jan Jaeger 25 Feb 2001 Correction to access register unstacking - Peter Stammbach 24 Feb 2001 Correction to 64bit IDAW's - Peter Stammbach 24 Feb 2001 cckd patches - Greg Smith 24 Feb 2001 Incorrect-Length-Indication-Suppression facility - Jan Jaeger 24 Feb 2001 Correction to interval timer Fix 22 Feb 2001 S/370 interval timer fixes - Mark Gaubatz 22 Feb 2001 64 bit Interpretive Execution (SIE) - Jan Jaeger 22 Feb 2001 Corrections to load_psw and store_psw - Jan Jaeger 22 Feb 2001 Improved address wrapping - Leland Lucius 20 Feb 2001 64 bit opcodes for PLO - Jan Jaeger 19 Feb 2001 Correction IPTE - Jan Jaeger 17 Feb 2001 Corrections to ISKE/IVSK/LCTL/RRBE/STCTL - Roger Bowler 16 Feb 2001 Fix ITF problem on 3390 compressed DASD - Greg Smith 16 Feb 2001 Fix to interception for paging exceptions in SIE - Paul Leisly 16 Feb 2001 IEEE float - Willem Konynenberg 16 Feb 2001 Further 64 bit panel updates - Roger Bowler 16 Feb 2001 Fix to LRA/LRAG - Roger Bowler 15 Feb 2001 64 bit fixes for CKSM, CLCLE, CUSE, CUUTF, CUTFU, TRE - Jan Jaeger 15 Feb 2001 Call s390_load_psw in LPSW in ESAME mode - Jan Jaeger 15 Feb 2001 Additional checking in load_psw in ESAME mode - Roger Bowler 14 Feb 2001 LPM fixes and display subchannel command - Nobumichi Kozawa 14 Feb 2001 64 bit support for panel.c - Roger Bowler 14 Feb 2001 Fix amode64 in load_psw - Ulrich Weigand 14 Feb 2001 64 bit correction to SRST - Jan Jaeger 14 Feb 2001 Correction to DL - Jan Jaeger 13 Feb 2001 Fix RLL/RLLG - Jan Jaeger 13 Feb 2001 Multiply logical (ML/MLR/MLG/MLGR) instructions - Vic Cross 13 Feb 2001 Correction to DL - Vic Cross 13 Feb 2001 Corrections to BRXHG and BRXLG - Jan Jaeger 13 Feb 2001 Add LGH instruction - Jan Jaeger 13 Feb 2001 Patch machine check for z/Arch compliance - Jan Jaeger 12 Feb 2001 Patch store status for z/Arch compliance - Jan Jaeger 11 Feb 2001 Correction to LRAG - Jan Jaeger 11 Feb 2001 Allow use of environment variables to override filenames of hercules.rc hercules.cnf and hercifc - Jan Jaeger 11 Feb 2001 Various floating additions inclusing EFPC/SRNM instructions, and data exception code specs - Roger Bowler 11 Feb 2001 Correction to pgmint instruction nullification - Jan Jaeger 10 Feb 2001 NLS support - Roger Bowler 09 Feb 2001 LFPC/SFPC/STFPC IEEE floating point instructions - Jan Jaeger 09 Feb 2001 Extended translation fac. 2 (PKA/PKU/UNPKA/UNPKU) - Roger Bowler 09 Feb 2001 Divide logical (DL/DLR/DLG/DLGR) instructions - Vic Cross 09 Feb 2001 Display instruction operands - Roger Bowler 09 Feb 2001 Fix to load_psw - Roger Bowler 08 Feb 2001 Add hercules.rc initialization file - Willem Konynenberg 08 Feb 2001 Fix SIE host interrupt IA backup - Jan Jaeger 08 Feb 2001 Fix SSKE RCP index error - Jan Jaeger 08 Feb 2001 TP instruction - Roger Bowler 06 Feb 2001 Tape datachaining patch - Brandon Hill 06 Feb 2001 Patch to bypass Cygwin stack problem (service.c) - Greg Smith 06 Feb 2001 Fixes for windows port - Volker Bandke 06 Feb 2001 SSK/ISK/RRB fix for 2K storage keys - Valery Pogonchenko/Jan Jaeger 06 Feb 2001 TRAP2 TRAP4 and RP instructions - Jan Jaeger 04 Feb 2001 Varous fixes for panel.c - Roger Bowler 04 Feb 2001 Interval Timer fix - Bob Abeles 04 Feb 2001 Deconfigure CPU's in release_config() - Greg Smith 04 Feb 2001 Change panel break command to 64 bit - Jan Jaeger 03 Feb 2001 Add ALCGR, SLBGR, ALCG, SLBG, ALCR, SLCR, ALC, SLB, AGF, ALGF, SGF, SGFR, AGFR, RRL, RRLG, MSGF, MSGFR, SLGFR instructions - Jan Jaeger 03 Feb 2001 Fix MVCLE instruction where op2 len > op1 len - Jan Jaeger 03 Feb 2001 Fix various sign/casting problems in esame.c - Jan Jaeger 03 Feb 2001 Change constant type in cmpsc.c to prevent warning - Jan Jaeger 03 Feb 2001 Fix S/370 interval timer - Valery Pogonchenko/Jay Maynard 03 Feb 2001 Correct sign on LLILH - Jan Jaeger 01 Feb 2001 Timer update correction - Valery Pogonchenko 01 Feb 2001 Documentation update - Roger Bowler 01 Feb 2001 Latest compressed CKD DASD release - Greg Smith 01 Feb 2001 Fixes to Divide Single instructions - Jan Jaeger 01 Feb 2001 64 bit fix to PLO instruction - Jan Jaeger 01 Feb 2001 64 bit fix to IPTE instruction - Jan Jaeger 01 Feb 2001 64 bit fix to SPX instruction - Jan Jaeger 01 Feb 2001 64 bit fix to LKPG instruction - Jan Jaeger 01 Feb 2001 Minor modification to SIGP instruction - Jan Jaeger 01 Feb 2001 Fix 64 bit binary math instructions - Jan Jaeger 31 Jan 2001 EPSW instruction - Roger Bowler 31 Jan 2001 Check unupdated instruction address for SAM24/31 - Roger Bowler 31 Jan 2001 ESAME DUCT format changes and BSA instruction - Roger Bowler 31 Jan 2001 ESAME ASN authorization and ALET translation - Roger Bowler 31 Jan 2001 Eliminate ASN tran.spec.exception for ESAME - Roger Bowler 29 Jan 2001 Correction to ESAME DAT - Jan Jaeger 29 Jan 2001 Fix MVCL/CLCL/MVCLE/CLCLE in 64 bit mode - Jan Jaeger 29 Jan 2001 Fix BAL/BAS type instructions in 64bit mode - Jan Jaeger 29 Jan 2001 Fix program interruption type in SAM24 and SAM31 - Jan Jaeger 29 Jan 2001 Correct typo in LMD 29 Jan 2001 ALGF/ALGFR instructions - Jan Jaeger 29 Jan 2001 Fix all relative instructions when target of execute - Jan Jaeger 29 Jan 2001 DSG/DSGF/DSGR/DSGFR instructions - Jan Jaeger 29 Jan 2001 EDMK ESAME fix - Jan Jaeger 28 Jan 2001 ASN translation patch - Roger Bowler 28 Jan 2001 Dummy SVC assist instruction - Jay Maynard/Brandon Hill 28 Jan 2001 Extended floating point - Peter Kuschnerus 28 Jan 2001 HET format tape support - Leland Lucius 28 Jan 2001 Unloaded tape drive support - Brandon Hill 27 Jan 2001 ESAME subspace replacement - Roger Bowler 26 Jan 2001 ESAME BSG/BAKR/PC/PR/PT instructions - Roger Bowler 24 Jan 2001 ESAME linkage stack operations - Roger Bowler 21 Jan 2001 EREGG instruction - Roger Bowler 20 Jan 2001 ESAME low-address protection - Roger Bowler 20 Jan 2001 Fix zero block length in ctcadpt.c - Roger Bowler 20 Jan 2001 LMD instruction - Roger Bowler 20 Jan 2001 Fix TB instruction in ESAME mode - Roger Bowler 20 Jan 2001 ESAME translation exception address - Roger Bowler 16 Jan 2001 Fix zero track overflow record - Roger Bowler 14 Jan 2001 ESAME DAT - Roger Bowler 11 Jan 2001 Format-2 2K/4K IDAW - Roger Bowler 11 Jan 2001 Add RRF/RXF/RSI instruction formats - Roger Bowler 11 Jan 2001 ESAME DAT table bit definitions - Roger Bowler 11 Jan 2001 ESAME interrupt codes - Roger Bowler 08 Jan 2001 Fix to ESTA and MSTA - Mario Bezzi 07 Jan 2001 Fix zero CCW count in ctcadpt.c - Roger Bowler 07 Jan 2001 Added BRASL, LARL, ESEA, STRAG, STPQ, LPQ, LLILH, LLILL, LLIHH, LLIHL, LLGH and LLGC instructions - Jan Jaeger 07 Jan 2001 Corrected LLGT and LLGTR instructions - Jan Jaeger 07 Jan 2001 Added 64 bit I/O and translation definitions - Jan Jaeger 05 Jan 2001 Reworked cmpsc.c - Bernard van der Helm 04 Jan 2001 Fix read-only aws tape - Roger Bowler 03 Jan 2001 Fix integrity problem in cckddasd.c - Greg Smith 02 Jan 2001 Fix multi architecture support in cmpsc.c - Jan Jaeger 02 Jan 2001 Fix psw ia backup during PSA access by SIE - Jan Jaeger 01 Jan 2001 Universal TUN/TAP Driver Networking support - Roger Bowler 01 Jan 2001 Fix HHC002I message in config.c - Roger Bowler 01 Jan 2001 Add OSTAILER VSE option - Roger Bowler 28 Dec 2000 Fix 4K storage key support for S/370 mode when using 2K page tables - Jan Jaeger 27 Dec 2000 2K/4K storage key support for SSK/SSKE/ISK/ISKE/RRB/RRBE instructions - Jan Jaeger 24 Dec 2000 Fully functional CMPSC instruction by Bernard van der Helm 23 Dec 2000 Various fixes to SIE - Jan Jaeger 23 Dec 2000 Multiple architecture support for SIE - Jan Jaeger 23 Dec 2000 Add OPTION_NO_DEVICE_THREAD 18 Dec 2000 Compressed CKD DASD release 2 - Greg Smith 18 Dec 2000 Fix deadlock in SIE host interrupt processing - Jan Jaeger 17 Dec 2000 Corrections to load reverse - Jan Jaeger 15 Dec 2000 Improved data typing - Jan Jaeger 13 Dec 2000 Add Load Reverse Facility (Jan Jaeger) 10 Dec 2000 Add Linux/390 interrupt patch 09 Dec 2000 Corrections to buffer positions in console.c - Roger Bowler 09 Dec 2000 Add absolute effective address buffer option (Jan Jaeger) 09 Dec 2000 Add absolute instruction address buffer option (Jan Jaeger) 03 Dec 2000 ALS-1 and ALS-2 support completion (Roger Bowler and Jan Jaeger) 02 Dec 2000 Included lates float fixes from Peter Kuschnerus 02 Dec 2000 Fix orienting bug in CKD DASD search CCW processing (Bob Abeles) 02 Dec 2000 Extended Translation (TRE,CUUTF,CUTFU instructions) - Roger Bowler 30 Nov 2000 Optimize vfetch and vstore operations - Jan Jaeger 25 Nov 2000 Add FETCH_xW and STORE_xW macros to optimize storage access and provide atomic store/fetch operations 22 Nov 2000 Optimize conditional branch instructions - Jan Jaeger 22 Nov 2000 Remove -fPIC compiler option (performance) - Jan Jaeger 20 Nov 2000 Revised instruction counting feature and icount panel command - Jan Jaeger 15 Nov 2000 Small fix to CHI - Jan Jaeger 11 Nov 2000 Prevent ESAME mode when ESA/390 is specifed - Jan Jaeger 5 Nov 2000 Added various new instructions in A5xx range - Jan Jaeger 29 Oct 2000 Correct AXR and SXR instruction results when significance exception raised (Peter Kuschnerus, with help from Mario Bezzi) 29 Oct 2000 Correct CD and CDR instruction condition code logic (Peter Kuschnerus) 29 Oct 2000 Do not generate support for square root instructions in 370 mode (Peter Kuschnerus) 28 Oct 2000 Added 64 Bit instructions - Jan Jaeger 21 Oct 2000 z/Architecture support - Jan Jaeger 14 Oct 2000 Some 64 Bit definitions - Jan Jaeger 07 Oct 2000 Add multi-architecture infrastructure in order to support multiple architectures - Jan Jaeger 07 Oct 2000 Compressed CKD DASD support (Greg Smith) 07 Oct 2000 DASD I/O optimizations (Greg Smith and Malcolm Beattie) 07 Oct 2000 Fix for random bug in MP instruction (Mario Bezzi) 07 Oct 2000 Treat all 3505 card reader read CCWs the same (Jay Maynard) 26 Sep 2000 STCRW instruction nullification correction - Jan Jaeger 05 Sep 2000 I/O rate meter on graphical panel (Valery Pogonchenko) 05 Sep 2000 Sense correction for track overflow processing (Valery Pogonchenko) 05 Sep 2000 Another fix for 64K segment length checking in 370 DAT (Jay Maynard, found by Mario Bezzi) 04 Sep 2000 Win32 portability changes (John Kozak) 04 Sep 2000 Fix for 64K segment length checking in 370 DAT (Jay Maynard, found by Mario Bezzi) 04 Sep 2000 Fix for TPI storing interrupt code when no interrupt pending (Jay Maynard, found by Greg Smith) 03 Sep 2000 Printer support for skip to channel 9 and 12 (Roger Bowler) 03 Sep 2000 Panel refresh rate command and PANRATE parameter (Reed Petty) 31 Aug 2000 Fix storage protection override on fetch (Jan Jaeger) 29 Aug 2000 ESA/390 (VM dataspace) SIE support (Jan Jaeger) 21 Aug 2000 Bugfix for MXR instruction (by Peter Kuschnerus) 19 Aug 2000 SIE Vector support (Jan Jaeger) 12 Aug 2000 Add CONCS, DISCS and RCHP instructions (Jan Jaeger) 12 Aug 2000 Add S/370 Mode support to SIE (Jan Jaeger) 08 Aug 2000 Fix flags on intermediate subchannel status (Jan Jaeger) 08 Aug 2000 Break SYSCONS output lines when too long (Jan Jaeger) 04 Aug 2000 Floating point instructions SQDR and SQER (by Peter Kuschnerus) 04 Aug 2000 Add Lock Page instruction (Jan Jaeger) 03 Aug 2000 Simplify logmsg and DEVTRACE macro definitions (Jay Maynard) 03 Aug 2000 Prevent incorrect length indication on CONTROL NOP CCW (Jay Maynard) 01 Aug 2000 Complete 370 HIO processing (Jay Maynard) 29 Jul 2000 Interpretive Execution (SIE) (Jan Jaeger) 29 Jul 2000 Set Address Limit (SAL) instruction (Jan Jaeger) 25 Jul 2000 Correct nullification of TPI and TSCH (Jan Jaeger) 25 Jul 2000 Add device locking to MSCH (Jan Jaeger) 25 Jul 2000 Correct TPROT instruction (Jan Jaeger) 22 Jul 2000 Correct address wrapping on assist instructions (Jan Jaeger) 22 Jul 2000 Change interrupt logic to use longjmp on all interrupts (Jan Jaeger) 22 Jul 2000 Clear remainder of ASTE when loading ASTE with ASF=0 in translace_asn (Jan Jaeger) 22 Jul 2000 Add PLO instruction (Jan Jaeger) 22 Jul 2000 Fix CLCL interruption problem (Jan Jaeger) 19 Jul 2000 Make ED and EDMK perform a trial run (Jan Jaeger) 16 Jul 2000 Fix address wraparound in MVO (Jan Jaeger) 15 Jul 2000 Fix CR15 corruption in form_stack_entry, fix nullification in form_stack_entry and unstack_registers (Jan Jaeger) 10 Jul 2000 Fix loss of interrupts in PR (Jan Jaeger) 22 Jul 2000 Track overflow processing fixes (by Jay Maynard, suggested by Valery Pogonchenko) 21 Jul 2000 Added TOD clock update to STCK, STCKE, DIAG 204, and TRACE processing (by Jay Maynard) 19 Jul 2000 Added support for 3340 and 3375 DASD (by Jay Maynard, with help from Rick Fochtman and David Cole) 18 Jul 2000 Corrected interval timer update increment (by Jay Maynard) 18 Jul 2000 Fixed READ DEVICE CHARACTERISTICS alternate track values for 3380 and 3390 DASD (by petermac@ase.com.au) 10 Jul 2000 Skeletal CMPSC instruction (by Bernard van der Helm) 07 Jul 2000 float.c optimization for new instruction decode and execution (by Peter Kuschnerus) 07 Jul 2000 Fix program check on TIC ccw (by Jan Jaeger) 07 Jul 2000 Fix program check on NOP ccw (by Jan Jaeger) 05 Jul 2000 Instruction decode & execution restructure (by Jan Jaeger) 05 Jul 2000 Added -fomit-frame-pointer to compiles for improved performance (by Jan Jaeger) 04 Jul 2000 Fix STCKE instruction (by Bernard van der Helm) 04 Jul 2000 Added track overflow processing for CKD DASD (by Jay Maynard) 04 Jul 2000 Makefile change to allow RPM building with RPM_BUILD_ROOT (by David Barth) 04 Jul 2000 Added NetBSD build definitions to makefile (by Soren Jorvang) 04 Jul 2000 Moved version definition to version.h and removed makefile dependency for source modules (by Jay Maynard) 04 Jul 2000 Package change: tarball now explodes into hercules- subdirectory (by Jay Maynard, suggested by Soren Jorvang) 23 Jun 2000 Fix backward going TOD clock (by Jan Jaeger) 23 Jun 2000 Suppress superflous HHC701/HHC702 messages (by Jan Jaeger) 23 Jun 2000 Rework cpu.c to decode instructions by macro (by Jan Jaeger) 23 Jun 2000 Bypass bug in IBM telnet client (by Jan Jaeger) 18 Jun 2000 3270 CCW processing improvements (by Jan Jaeger) 18 Jun 2000 OSTAILOR generalization, and new pgmtrace panel command (by Jan Jaeger) 18 Jun 2000 VM IUCV instruction correction and DIAGNOSE improvements (by Jan Jaeger) 18 Jun 2000 CPU timer and clock comparator improvements (by Jan Jaeger, after a suggestion by Willem Koynenberg) 18 Jun 2000 3480 READ BLOCK ID and LOCATE CCW support (by Brandon Hill) 18 Jun 2000 Networking support via virtual CTCA (by Willem Koynenberg) 18 Jun 2000 Restructured CPU execution, by function call instead of switch statement (by Mike Noel) 18 Jun 2000 Support for IEBCOPY sequential output datasets in dasdload (by Ronen Tzur) 18 Jun 2000 New dasdls command lists the VTOC of a CKD DASD volume (by Malcolm Beattie) 18 Jun 2000 New AWSTAPE handling commands: tapesplt, tapemap (by Jay Maynard) 18 Jun 2000 make install target to install in /usr/bin (by Jay Maynard) 03 Jun 2000 Still more multiprocessor improvements (by Jan Jaeger) 03 Jun 2000 Dynamic CPU reconfiguration (by Jan Jaeger) 03 Jun 2000 Basic vector facility (by Jan Jaeger) 03 Jun 2000 Floating point version 6 (by Peter Kuschnerus) 03 Jun 2000 READ AND RESET BUFFERED LOG CCW (X'A4') support (by Jay Maynard) 03 Jun 2000 WRITE SPECIAL CKD CCW (X'01') support (by Jay Maynard) 03 Jun 2000 FBA DASD model reporting fixes (by Jay Maynard) 21 May 2000 More multiprocessor improvements (by Jan Jaeger) 21 May 2000 New startall/stopall panel commands (by Jan Jaeger) 21 May 2000 STIDP stores processor address in first digit of CPU id (by Roger Bowler) 21 May 2000 Correction to IPTE instruction for S/370 (by Jay Maynard) 21 May 2000 Dummy HIO instruction for S/370 (by Jay Maynard) 21 May 2000 Support for emulated 0671 FBA DASD (by Jay Maynard) 21 May 2000 FBA device reserve/release CCW support (by Jay Maynard) 21 May 2000 New OSTAILOR configuration option allows selective suppression of program check messages (by Jay Maynard) 14 May 2000 Multiprocessor locking improvements (by Jan Jaeger) 14 May 2000 Machine check and channel report word (by Jan Jaeger) 14 May 2000 Store Channel Report Word (STCRW) instruction (by Jan Jaeger) 14 May 2000 New attach/detach/define commands to allow dynamic addition and deletion of devices from the configuration (by Jan Jaeger) 14 May 2000 Compare and Swap and Purge (CSP) instruction (by Jan Jaeger) 14 May 2000 Broadcasted purging (by Jan Jaeger) 14 May 2000 Fix LASP instruction SASN authorization using wrong AX if bits 29-31 are 010 and SASN \= PASN (by Mario Bezzi) 14 May 2000 Fix SAC instruction special operation exception setting secondary space mode when ASF=0 (by Mario Bezzi) 14 May 2000 Remove intdrag option and replace drag command by toddrag command 14 May 2000 New extpending flag to improve performance (originally contributed by Valery Pogonchenko and enhanced by Jan Jaeger) 14 May 2000 Allow longer host name in console connected message (by Jay Maynard) 14 May 2000 Floating point version 5 including fixes by Mario Bezzi (contributed by Peter Kuschnerus) 30 Apr 2000 Missing interrupt after CSCH instruction 30 Apr 2000 S/370 DAT support (contributed by Jay Maynard) 30 Apr 2000 Tape device sense byte improvements (by Jan Jaeger) 30 Apr 2000 Read Buffered Log (CCW X'24') for tape devices (by Jan Jaeger) 30 Apr 2000 Reject Sense ID CCW for 3420 tape devices (by Jan Jaeger) 30 Apr 2000 Suppress unprintable character in HMC messages (by Jan Jaeger) 30 Apr 2000 Suppress attention interrupt if subchannel not enabled (by Roger Bowler) 30 Apr 2000 New interrupt drag factor to improve performance (by Roger Bowler) 30 Apr 2000 New toddrag and intdrag config options and drag control panel command allow drag factors to be set (by Roger Bowler) 30 Apr 2000 Light optimization on CPU critical path (by Valery Pogonchenko) 30 Apr 2000 Eliminate fetch protection override in S/370 mode (by Valery Pogonchenko) 22 Apr 2000 Support for CKD DASD volumes exceeding 2GB such as 3390-3 (by Roger Bowler) 22 Apr 2000 3274-1D SELECT RB/RMP/RBP/WRT commands (by Roger Bowler) 22 Apr 2000 Support for 3270 14-bit SBA addressing and inbound SFE order (by Roger Bowler) 22 Apr 2000 Command reject if Write Structured Field CCW issued to a 3270 without extended attributes (by Roger Bowler) 22 Apr 2000 Fix missing CSW_IL indication when CCW count exhausted (by Roger Bowler) 22 Apr 2000 Do not set unit exception if CCW count is zero (by Jan Jaeger) 22 Apr 2000 Suppress space switch event program check messages (by Jan Jaeger) 22 Apr 2000 Branch tracing and cross memory tracing for BALR, BASR, BASSM, BAKR, BSA, BSG, SSAR, PC, PT, PR instructions (by Jan Jaeger) 22 Apr 2000 New diagnose instruction to stop CPU (by Jan Jaeger) 22 Apr 2000 Drag factor option slows down TOD clock, to decrease overhead on very slow machines (by Jan Jaeger) 22 Apr 2000 Correction to PR instruction (by Jan Jaeger) 22 Apr 2000 Correction to LASP instruction (by Jan Jaeger) 22 Apr 2000 Make CLCLE/MVCLE/CKSM instructions conditional features (by Jan Jaeger) 22 Apr 2000 Enable channel measurement mode (by Jan Jaeger) 22 Apr 2000 Modify program_check() to handle shadow registers correctly (by Jan Jaeger) 22 Apr 2000 Change DAT to favour PSTD in TEA, to give reduction in page fault path length (by Jan Jaeger) 22 Apr 2000 Avoid clearing registers at CPU reset (by Jan Jaeger) 22 Apr 2000 Leave GPR, AR and FPR intact during CPU reset for SADUMP (by Jan Jaeger) 22 Apr 2000 Zeroize field for called space identification in PC stack entry (by Jan Jaeger) 22 Apr 2000 New CCW X'8D' (Write Update Key and Data) required by STOW (by Jan Jaeger) 22 Apr 2000 Fix for 0B7 abend in D M=CHP command (by Jan Jaeger) 22 Apr 2000 Floating point version 4 including fixes by Valery Pogonchenko (contributed by Peter Kuschnerus) 22 Apr 2000 Fix incorrect second operand address in MVCIN instruction (by Roger Bowler) 22 Apr 2000 Correct sign of zero result in SRP instruction (by Roger Bowler) 22 Apr 2000 Erase Gap (CCW X'17') for tape devices (by Roger Bowler) 22 Apr 2000 Activate MIPS counter on control panel (by Dutch Owen) 22 Apr 2000 Suppress tracing of ISK, SCK, and DP instructions 30 Mar 2000 Fix program check 0032 due to wrong stack entry being updated 30 Mar 2000 Fix wrong SSTD loaded by LASP instruction (found by Jan Jaeger) 30 Mar 2000 Bypass main storage lock in single CP configuration (by Jan Jaeger) 30 Mar 2000 Fix incorrect condition code in PGIN instruction (by Jan Jaeger) 30 Mar 2000 Corrections to expanded storage instructions (by Jan Jaeger) 30 Mar 2000 New STCPS and SCHM instructions (by Jan Jaeger) 30 Mar 2000 Set more appropriate sense bytes for tape errors 28 Mar 2000 Fix incorrect unit exception on SCSI tape FSB/BSB CCW (reported by Daniel Rudin) 28 Mar 2000 Fix unit check on AWSTAPE write (reported by Axel Schwarzer) 28 Mar 2000 Close SCSI tape after tape is ejected 28 Mar 2000 Detect tapemark during SCSI tape FSB/BSB CCW 28 Mar 2000 Suppress HMC response prompt (by Jan Jaeger) 28 Mar 2000 Expanded storage support (by Jan Jaeger) 28 Mar 2000 Move Page Facility 2 28 Mar 2000 Correct signed length error in MVCK/MVCS/MVCP (by Jan Jaeger) 28 Mar 2000 Undetected CC=3 in SRP instruction 28 Mar 2000 Wrong remainder in DP instruction when dividend is less than divisor 28 Mar 2000 Specification exception in DP instruction should have higher priority than data exception 22 Mar 2000 FBA minidisk support 22 Mar 2000 Additional diagnose functions 22 Mar 2000 Allow real storage frames to be marked unusable (by Jan Jaeger) 18 Mar 2000 Address wraparound improvement (contributed by Jan Jaeger) 18 Mar 2000 Floating point version 3 (contributed by Peter Kuschnerus) 18 Mar 2000 Correction to SLDA/SRA instructions (contributed by Jan Jaeger) 18 Mar 2000 Recognize tabs and end-of-file character in ASCII cardrdr files 18 Mar 2000 Hercules-specific diagnose instructions (contributed by Jay Maynard) 18 Mar 2000 Correct missing timer interrupt when interval timer goes from zero to negative (thanks to Valery Pogonchenko) 18 Mar 2000 Enable HMC system console in S/370 mode 18 Mar 2000 Correct sign propagation in multiply instruction 18 Mar 2000 Reduce CPU thread priority (thanks to Steve Gay and Reed H.Petty) 01 Mar 2000 Add BSF/FSF/BSB/FSB CCW support for tape devices 01 Mar 2000 Allow final short block in OMA fixed block files 01 Mar 2000 Allow processing of read-only AWSTAPE files and SCSI tapes 01 Mar 2000 Skeleton ctcadpt module for future 3088 support 01 Mar 2000 Correctly nullify IC/NI/OI/XI/CLM/STCM/ICM/TRT instructions on page translation exception (thanks to Jan Jaeger) 01 Mar 2000 Improved floating point support (contributed by Peter Kuschnerus) 01 Mar 2000 Correct shift result when shift count exceeds 31 (thanks to Glen Herrmannsfeldt and Jay Maynard) 01 Mar 2000 Fix incorrect MVCL cc=3 when destination length is 1 19 Feb 2000 Prevent incorrect length indication on 3270 Select CCW 19 Feb 2000 2K storage protection for S/370 19 Feb 2000 Prevent wait for console port (thanks to Malcolm Beattie) 19 Feb 2000 Allow keyword parameters in configuration file 19 Feb 2000 New sysepoch and tzoffset parameters (thanks to Jay Maynard) 19 Feb 2000 Adjust TRACE and DIAG204 for extended TOD (thanks to Jan Jaeger) 19 Feb 2000 Set TOD clock in SCK instruction (thanks to Jan Jaeger) 15 Feb 2000 3270 read buffer fix for OS/360 NIP 15 Feb 2000 Floating point instructions (contributed by Peter Kuschnerus) 15 Feb 2000 Remove 32-bit pointer dependency from dasdload for Alpha 15 Feb 2000 HMC system console support (contributed by Jan Jaeger) 15 Feb 2000 Correct condition code after decimal overflow (thanks to Jan Jaeger) 15 Feb 2000 Set reference and change bits for PSA access (thanks to Jan Jaeger) 15 Feb 2000 New CRLF option for printer and card punch (default is now LF) 10 Feb 2000 Remove interval timer debugging message 10 Feb 2000 Fix hung console resulting from attention interrupt fix in 1.49 10 Feb 2000 Seek and Set Sector (CCW=27) for Itel 7330 DASD controller 10 Feb 2000 Correct SIGP handling of non-existent CPUs (thanks to Jan Jaeger) 10 Feb 2000 Extended TOD clock bit in processor features (thanks to Jan Jaeger) 10 Feb 2000 Alternate control panel help text (contributed by Dutch Owen) 10 Feb 2000 Card reader end of file option (thanks to Dutch Owen) 10 Feb 2000 Card reader ASCII/EBCDIC auto-detection 10 Feb 2000 Fix SIGP RESTART to target correct CPU (thanks to Jan Jaeger) 10 Feb 2000 Allow VTOC size and location to be specified for dasdload. 05 Feb 2000 Alternate control panel (contributed by Dutch Owen) 05 Feb 2000 Present attention interrupt when console connects 05 Feb 2000 Fix dasdload CVOL logic (thanks to Jay Maynard) 05 Feb 2000 Fix dasdload initialization of empty PDS 05 Feb 2000 Allow device size to be specified for dasdload Note: the volser record in the pack layout file must be changed to specify the device type and cylinder count; the device type is no longer specified on the command line. 05 Feb 2000 Add dummy Set Clock instruction (does nothing except set cc 0) 31 Jan 2000 Fix dasdload to handle note lists (prevent 32D abend) 31 Jan 2000 I/O interrupt performance enhancement 31 Jan 2000 Correctly detect overflow in signed Add/Subtract instructions 31 Jan 2000 Fix track overflow problem 31 Jan 2000 3270 Read Modified CCW 23 Jan 2000 Allow tn3270 or telnet client to connect to specific device number 23 Jan 2000 Align control panel instruction counter (thanks to Mario Bezzi) 23 Jan 2000 Ensure panel display does not corrupt TEA (by Jan Jaeger) 23 Jan 2000 STIDP incorrectly propagates high order bit of CPU model (fixed by Jan Jaeger) 23 Jan 2000 Fix byte-ordering problem with CKD DASD header on non-Intel machines (reported by Adam Thornton) 23 Jan 2000 STIDC instruction 23 Jan 2000 Extended TOD clock (STCKE and SCKPF instructions) 23 Jan 2000 3211 Load FCB and Diagnostic Read CCW 23 Jan 2000 3270 Read Buffer CCW 23 Jan 2000 Fix console.c to inhibit input while console has status pending 11 Jan 2000 HSCH instruction 11 Jan 2000 SIGP instruction 11 Jan 2000 Suppress tracing of page faults 11 Jan 2000 Display control registers and access registers after program check 11 Jan 2000 Add regs parameter to program_check function calls 11 Jan 2000 New panel command to perform store status function 11 Jan 2000 Suppress tracing of CCW file protect and end of cylinder errors 08 Jan 2000 Make MVCL/CLCL interruptible (contributed by Jan Jaeger) 08 Jan 2000 Diagnose 204 (contributed by Jan Jaeger) 08 Jan 2000 Read Channel Subsystem Info (contributed by Jan Jaeger) 08 Jan 2000 Fix incorrect register count in TRACE instruction 08 Jan 2000 Correct nullification of STM/LM/LAM/STAM/STCTL/LCTL/STCM and SS instructions whose operands cross a page boundary 08 Jan 2000 Suppression on Protection with Virtual-Address enhancement 08 Jan 2000 Select correct address space for MVCS/MVCP (fixed by Jan Jaeger) 08 Jan 2000 Correct registers after CLCL/CLCLE with non-zero condition code 08 Jan 2000 Defer clock comparator interrupt while instruction stepping 08 Jan 2000 Remove 32K limit on data chained write CCWs for non-CKD devices 08 Jan 2000 Correct overrun error on data chained write for FBA DASD 01 Jan 2000 Support for 9336 FBA DASD 01 Jan 2000 Read Replicated Data command for FBA DASD 01 Jan 2000 Prevent recursive program check after instruction fetch error 01 Jan 2000 Operand tracing for MVCL/CLCL and RRE instructions 27 Dec 1999 New control panel command: devlist 27 Dec 1999 Write Update Data (X'85') CCW for CKD devices 27 Dec 1999 Makefile changed to use $(CC) instead of cc 27 Dec 1999 Fix dat.c to prevent ASN translation specification exception (program check X'0017') if subspace group facility is installed and ASF is one 27 Dec 1999 Fix cpu.c to clear ILC before fetching instruction to prevent PSW being backed up if access error occurs during instruction fetch 27 Dec 1999 Correct program check ILC when instruction is nullified 27 Dec 1999 Obtain CPU model number for STIDP from configuration file (contributed by Jay Maynard) Note: if upgrading from an earlier release, you must change your hercules.cnf file to add a valid CPU model number after the CPU serial number 27 Dec 1999 Prevent wait after devinit (thanks to Jay Maynard) 27 Dec 1999 Open printer with O_SYNC to ensure buffers flushed (suggested by Daniel Seagraves) 27 Dec 1999 Fix xmem.c to prevent loop in program_call when loading 4-word ETE (thanks to Jan Jaeger) 27 Dec 1999 Improved TLB lookup (contributed by Jan Jaeger) 16 Dec 1999 New makefile builds both S/370 and ESA/390 executables: hercules-370 and hercules-390 (contributed by Jay Maynard) 16 Dec 1999 3480 Set Path Group Id and Unassign CCWs (contributed by Jan Jaeger) 16 Dec 1999 CFC and UPT instructions (contributed by Peter Kuschnerus) 16 Dec 1999 Card punch support 16 Dec 1999 Erase (X'11') CCW for CKD devices 16 Dec 1999 Correct setting of translation exception address 16 Dec 1999 Correct file mode when opening printer file 16 Dec 1999 Correct condition code for shift arithmetic instructions 07 Dec 1999 Set reference and change bits correctly for main storage accesses by channel, dat, xmem, stack, block, and service modules (thanks to Jan Jaeger) 07 Dec 1999 New devinit command (contributed by Jay Maynard) 07 Dec 1999 Reject control panel virtual storage display command if CR1=0 07 Dec 1999 Fix dasdload to correctly write EOF record for empty file and to correctly fill block overhead fields in format4 DSCB. 07 Dec 1999 Diagnose functions MSSFCALL and SCPEND (contributed by Jan Jaeger) 07 Dec 1999 Corrections to service.c and assist.c (contributed by Jan Jaeger) 07 Dec 1999 Alpha platform portability definitions (contributed by Jay Maynard) 07 Dec 1999 3480 Assign CCW (thanks to Rick McKelvy) 30 Nov 1999 New DASDISUP program performs OS/360 IEHIOSUP function 30 Nov 1999 Correct SCSW handling for suspend/resume 30 Nov 1999 Forward space file CCW for tape devices 30 Nov 1999 3480 load display CCW (contributed by Jan Jaeger) and sense path group id CCW (thanks to Rick McKelvy) 30 Nov 1999 Correct handling of OMA tape headers to correctly recognize tape mark and to align headers to 16-byte boundary 30 Nov 1999 EBCDIC character translation of CCW data displays 30 Nov 1999 Fix command reject for CKD read commands outside the domain of a locate record 24 Nov 1999 Concurrent sense 24 Nov 1999 I/O initial status interruption 24 Nov 1999 Channel program suspend/resume function and RSCH instruction 24 Nov 1999 Read Device Characteristics CCW for 3480 24 Nov 1999 Fix incorrect command reject on Sense Subsystem Status CCW 24 Nov 1999 Increase 3270 write buffer size to prevent console I/O error when using Zap function of ZZSA 24 Nov 1999 Fix very nasty error in dat.c causing wrong bytes to be fetched or stored when operand crosses page boundary 24 Nov 1999 Remove temporary fix to ckddasd.c introduced in 1.37 22 Nov 1999 New panel commands to allow storage alteration 22 Nov 1999 Fix incorrect I/O parameter on attention interrupt (Jan Jaeger) 22 Nov 1999 Clear PMCW correctly during I/O reset 22 Nov 1999 Change 3270 control unit type to 3274-1D (Jan Jaeger) 22 Nov 1999 Fix restart command broken by 1.37 19 Nov 1999 Storage range display 19 Nov 1999 EBCDIC character translation of storage displays 19 Nov 1999 New breakpoint command (contributed by Dan Horak) 19 Nov 1999 Messages go to log file as well as screen if stdout is redirected 19 Nov 1999 Fix missing interrupt caused by channel.c failing to obtain device lock before setting interrupt pending 19 Nov 1999 Fix incorrect cond code 1 in attention SCSW built by console.c 19 Nov 1999 New Read Channel Path Information service call 19 Nov 1999 Temporary fix to ckddasd.c multitrack search 19 Nov 1999 Addition of Read Device Characteristics and Sense Subsystem Status commands for CKD devices 19 Nov 1999 New DASDPDSU program to unload PDS members from a CKD volume 12 Nov 1999 Clear subchannel instruction 12 Nov 1999 Correct fault causing control panel display corruption 09 Nov 1999 Improved control panel user interface 09 Nov 1999 New control panel commands: start, stop, restart, ipl, loadparm 09 Nov 1999 New loadcore command to load disk image files 09 Nov 1999 S/370 interval timer 09 Nov 1999 Allow 31-bit mode linkage in lock instructions 09 Nov 1999 Support for PCI in ESA/390 mode as well as S/370 mode 09 Nov 1999 Correct problem causing false channel protection checks 29 Oct 1999 New DASDLOAD program to create a CKD volume from unloaded PDS files 29 Oct 1999 Correct CKD module to prevent record not found error on multitrack Read Count CCW 26 Oct 1999 Correct handling of REWIND command for AWSTAPE files 26 Oct 1999 Correct nasty bug in Subtract Logical instruction (thanks to Roland Goetschi for finding this bug) 26 Oct 1999 Ensure unique TOD clock values for Store Clock 26 Oct 1999 Correction to unstacking process for PR instruction 26 Oct 1999 Implementation of Read Multiple CKD command 18 Oct 1999 Support for virtual tapes in OMA (Optical Media Attach) format 18 Oct 1999 SCSI tape support (read-only) 18 Oct 1999 Minor corrections to CKD DASD support hercules-3.07/channel.c000644 000765 000765 00000413170 11344707123 016527 0ustar00jmaynardjmaynard000000 000000 /* CHANNEL.C (c) Copyright Roger Bowler, 1999-2009 */ /* ESA/390 Channel Emulator */ // $Id: channel.c 5654 2010-03-07 03:15:17Z fish $ /*-------------------------------------------------------------------*/ /* This module contains the channel subsystem functions for the */ /* Hercules S/370 and ESA/390 emulator. */ /*-------------------------------------------------------------------*/ /*-------------------------------------------------------------------*/ /* Additional credits: */ /* Measurement block support by Jan Jaeger */ /* Fix program check on NOP due to addressing - Jan Jaeger */ /* Fix program check on TIC as first ccw on RSCH - Jan Jaeger */ /* Fix PCI intermediate status flags - Jan Jaeger */ /* z/Architecture support - (c) Copyright Jan Jaeger, 1999-2009 */ /* 64-bit IDAW support - Roger Bowler v209 @IWZ*/ /* Incorrect-length-indication-suppression - Jan Jaeger */ /* Read backward support contributed by Hackules 13jun2002 */ /* Read backward fixes contributed by Jay Jaeger 16sep2003 */ /* MIDAW support - Roger Bowler 03aug2005 @MW*/ /*-------------------------------------------------------------------*/ // $Log$ // Revision 1.147 2008/11/04 05:56:30 fish // Put ensure consistent create_thread ATTR usage change back in // // Revision 1.146 2008/11/03 15:31:58 rbowler // Back out consistent create_thread ATTR modification // // Revision 1.145 2008/10/18 09:32:20 fish // Ensure consistent create_thread ATTR usage // // Revision 1.144 2008/08/21 18:34:45 fish // Fix i/o-interrupt-queue race condition // // Revision 1.143 2008/05/28 16:33:13 fish // (fix typo in comment; no code was changed) // // Revision 1.142 2008/03/29 08:36:46 fish // More complete/extensive 3490/3590 tape support // // Revision 1.141 2008/03/13 19:55:49 ivan // Return Byte Mpx in STIDC for Channel 0 according to GA22-7000-4 Page 192 Chapter 2 // // Revision 1.140 2007/08/07 19:47:59 ivan // Fix a couple of gcc-4.2 warnings // // Revision 1.139 2007/06/23 00:04:04 ivan // Update copyright notices to include current year (2007) // // Revision 1.138 2007/02/15 22:57:04 gsmith // Reset syncio_retry to zero appropriately for syncio type 2 devices // // Revision 1.137 2007/02/03 18:58:06 gsmith // Fix MVT tape CMDREJ error // // Revision 1.136 2007/01/16 01:45:33 gsmith // Tweaks to instruction stepping/tracing // // Revision 1.135 2007/01/09 03:29:02 ivan // Temporarily disable dev->crwpending test in channel.c[device_attention] to // enable dynamic I/O reconfig in S/370 mode. Interim solution ONLY ! // // Revision 1.134 2006/12/08 09:43:18 jj // Add CVS message log // #include "hstdinc.h" #include "hercules.h" #include "devtype.h" #include "opcode.h" #if defined(OPTION_FISHIO) #include "w32chan.h" #endif // defined(OPTION_FISHIO) void call_execute_ccw_chain(int arch_mode, void* pDevBlk); #ifdef OPTION_IODELAY_KLUDGE #define IODELAY(_dev) \ do { \ if (sysblk.iodelay > 0 && (_dev)->devchar[10] == 0x20) \ usleep(sysblk.iodelay); \ } while (0) #else #define IODELAY(_dev) #endif #undef CHADDRCHK #if defined(FEATURE_ADDRESS_LIMIT_CHECKING) #define CHADDRCHK(_addr,_dev) \ ( ((_addr) > (_dev)->mainlim) \ || ((dev->orb.flag5 & ORB5_A) \ && ((((_dev)->pmcw.flag5 & PMCW5_LM_LOW) \ && ((_addr) < sysblk.addrlimval)) \ || (((_dev)->pmcw.flag5 & PMCW5_LM_HIGH) \ && ((_addr) >= sysblk.addrlimval)) ) )) #else /*!defined(FEATURE_ADDRESS_LIMIT_CHECKING)*/ #define CHADDRCHK(_addr,_dev) \ ((_addr) > (_dev)->mainlim) #endif /*!defined(FEATURE_ADDRESS_LIMIT_CHECKING)*/ #if !defined(_CHANNEL_C) #define _CHANNEL_C /*-------------------------------------------------------------------*/ /* FORMAT I/O BUFFER DATA */ /*-------------------------------------------------------------------*/ static void format_iobuf_data (RADR addr, BYTE *area, DEVBLK *dev) /*@IWZ*/ { BYTE *a; /* -> Byte in main storage */ int i, j; /* Array subscripts */ BYTE c; /* Character work area */ area[0] = '\0'; if (addr <= dev->mainlim - 16) { a = dev->mainstor + addr; j = sprintf ((char *)area, "=>%2.2X%2.2X%2.2X%2.2X %2.2X%2.2X%2.2X%2.2X" " %2.2X%2.2X%2.2X%2.2X %2.2X%2.2X%2.2X%2.2X ", a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15]); for (i = 0; i < 16; i++) { c = guest_to_host(*a++); if (!isprint(c)) c = '.'; area[j++] = c; } area[j] = '\0'; } } /* end function format_iobuf_data */ /*-------------------------------------------------------------------*/ /* DISPLAY CHANNEL COMMAND WORD AND DATA */ /*-------------------------------------------------------------------*/ static void display_ccw (DEVBLK *dev, BYTE ccw[], U32 addr) { BYTE area[64]; /* Data display area */ format_iobuf_data (addr, area, dev); logmsg (_("HHCCP048I %4.4X:CCW=%2.2X%2.2X%2.2X%2.2X " "%2.2X%2.2X%2.2X%2.2X%s\n"), dev->devnum, ccw[0], ccw[1], ccw[2], ccw[3], ccw[4], ccw[5], ccw[6], ccw[7], area); } /* end function display_ccw */ /*-------------------------------------------------------------------*/ /* DISPLAY CHANNEL STATUS WORD */ /*-------------------------------------------------------------------*/ static void display_csw (DEVBLK *dev, BYTE csw[]) { logmsg (_("HHCCP049I %4.4X:Stat=%2.2X%2.2X Count=%2.2X%2.2X " "CCW=%2.2X%2.2X%2.2X\n"), dev->devnum, csw[4], csw[5], csw[6], csw[7], csw[1], csw[2], csw[3]); } /* end function display_csw */ /*-------------------------------------------------------------------*/ /* DISPLAY SUBCHANNEL STATUS WORD */ /*-------------------------------------------------------------------*/ static void display_scsw (DEVBLK *dev, SCSW scsw) { logmsg (_("HHCCP050I %4.4X:SCSW=%2.2X%2.2X%2.2X%2.2X " "Stat=%2.2X%2.2X Count=%2.2X%2.2X " "CCW=%2.2X%2.2X%2.2X%2.2X\n"), dev->devnum, scsw.flag0, scsw.flag1, scsw.flag2, scsw.flag3, scsw.unitstat, scsw.chanstat, scsw.count[0], scsw.count[1], scsw.ccwaddr[0], scsw.ccwaddr[1], scsw.ccwaddr[2], scsw.ccwaddr[3]); } /* end function display_scsw */ /*-------------------------------------------------------------------*/ /* STORE CHANNEL ID */ /*-------------------------------------------------------------------*/ int stchan_id (REGS *regs, U16 chan) { U32 chanid; /* Channel identifier word */ int devcount = 0; /* #of devices on channel */ DEVBLK *dev; /* -> Device control block */ PSA_3XX *psa; /* -> Prefixed storage area */ /* Find a device on specified channel */ for (dev = sysblk.firstdev; dev != NULL; dev = dev->nextdev) { /* Skip the device if not on specified channel */ if ((dev->devnum & 0xFF00) != chan || (dev->pmcw.flag5 & PMCW5_V) == 0 #if defined(FEATURE_CHANNEL_SWITCHING) || regs->chanset != dev->chanset #endif /*defined(FEATURE_CHANNEL_SWITCHING)*/ ) continue; /* Found device on the channel */ devcount++; break; } /* end for(dev) */ /* Exit with condition code 3 if no devices on channel */ if (devcount == 0) return 3; /* Construct the channel id word */ /* According to GA22-7000-4, Page 192, 2nd paragraph, * channel 0 is a Byte Multiplexor.. Return STIDC data * accordingly * ISW 20080313 */ if(!chan) { chanid = CHANNEL_MPX; } else { chanid = CHANNEL_BMX; } /* Store the channel id word at PSA+X'A8' */ psa = (PSA_3XX*)(regs->mainstor + regs->PX); STORE_FW(psa->chanid, chanid); /* Exit with condition code 0 indicating channel id stored */ return 0; } /* end function stchan_id */ /*-------------------------------------------------------------------*/ /* TEST CHANNEL */ /*-------------------------------------------------------------------*/ int testch (REGS *regs, U16 chan) { DEVBLK *dev; /* -> Device control block */ int devcount = 0; /* Number of devices found */ int cc = 0; /* Returned condition code */ /* Scan devices on the channel */ for (dev = sysblk.firstdev; dev != NULL; dev = dev->nextdev) { /* Skip the device if not on specified channel */ if ((dev->devnum & 0xFF00) != chan || (dev->pmcw.flag5 & PMCW5_V) == 0 #if defined(FEATURE_CHANNEL_SWITCHING) || regs->chanset != dev->chanset #endif /*defined(FEATURE_CHANNEL_SWITCHING)*/ ) continue; /* Increment device count on this channel */ devcount++; /* Test for pending interrupt */ if (IOPENDING(dev)) { cc = 1; break; } } /* Set condition code 3 if no devices found on the channel */ if (devcount == 0) cc = 3; return cc; } /* end function testch */ /*-------------------------------------------------------------------*/ /* TEST I/O */ /*-------------------------------------------------------------------*/ int testio (REGS *regs, DEVBLK *dev, BYTE ibyte) { int cc; /* Condition code */ PSA_3XX *psa; /* -> Prefixed storage area */ IOINT *ioint=NULL; UNREFERENCED(ibyte); if (dev->ccwtrace || dev->ccwstep) logmsg (_("HHCCP051I %4.4X: Test I/O\n"), dev->devnum); obtain_lock (&dev->lock); /* Test device status and set condition code */ if ((dev->busy && dev->ioactive == DEV_SYS_LOCAL) || dev->startpending) { /* Set condition code 2 if device is busy */ cc = 2; } else { if (IOPENDING(dev)) { /* Set condition code 1 if interrupt pending */ cc = 1; /* Store the channel status word at PSA+X'40' */ psa = (PSA_3XX*)(regs->mainstor + regs->PX); if (dev->pcipending) { memcpy (psa->csw, dev->pcicsw, 8); ioint=&dev->pciioint; } else { if(dev->pending) { memcpy (psa->csw, dev->csw, 8); ioint=&dev->ioint; } else { memcpy (psa->csw, dev->attncsw, 8); ioint=&dev->attnioint; } } /* Signal console thread to redrive select */ if (dev->console) { SIGNAL_CONSOLE_THREAD(); } if (dev->ccwtrace || dev->ccwstep) display_csw (dev, psa->csw); } else { /* Set condition code 1 if device is LCS CTC */ if ( dev->ctctype == CTC_LCS ) { cc = 1; dev->csw[4] = 0; dev->csw[5] = 0; psa = (PSA_3XX*)(regs->mainstor + regs->PX); memcpy (psa->csw, dev->csw, 8); if (dev->ccwtrace) { logmsg(_("HHCCP052I TIO modification executed CC=1\n")); display_csw (dev, dev->csw); } } else /* Set condition code 0 if device is available */ cc = 0; } } /* Dequeue the interrupt */ if(ioint) DEQUEUE_IO_INTERRUPT(ioint); release_lock (&dev->lock); /* Update interrupt status */ if(ioint) { OBTAIN_INTLOCK(regs); UPDATE_IC_IOPENDING(); RELEASE_INTLOCK(regs); } /* Return the condition code */ return cc; } /* end function testio */ /*-------------------------------------------------------------------*/ /* HALT I/O */ /*-------------------------------------------------------------------*/ int haltio (REGS *regs, DEVBLK *dev, BYTE ibyte) { int cc; /* Condition code */ PSA_3XX *psa; /* -> Prefixed storage area */ int pending = 0; /* New interrupt pending */ UNREFERENCED(ibyte); if (dev->ccwtrace || dev->ccwstep) logmsg (_("HHCCP053I %4.4X: Halt I/O\n"), dev->devnum); obtain_lock (&dev->lock); /* Test device status and set condition code */ if (dev->busy) { /* Invoke the provided halt_device routine @ISW */ /* if it has been provided by the handler @ISW */ /* code at init @ISW */ if(dev->halt_device!=NULL) /* @ISW */ { /* @ISW */ dev->halt_device(dev); /* @ISW */ cc=0; /* @ISW */ } /* @ISW */ else { /* Set condition code 2 if device is busy */ cc = 2; /* Tell channel and device to halt */ dev->scsw.flag2 |= SCSW2_FC_HALT; /* Clear pending interrupts */ dev->pending = dev->pcipending = dev->attnpending = 0; } } else if (!IOPENDING(dev) && dev->ctctype != CTC_LCS) { /* Set condition code 1 */ cc = 1; /* Store the channel status word at PSA+X'40' */ psa = (PSA_3XX*)(regs->mainstor + regs->PX); memcpy (psa->csw, dev->csw, 8); /* Set pending interrupt */ dev->pending = pending = 1; if (dev->ccwtrace || dev->ccwstep) display_csw (dev, dev->csw); } else { /* Set cc 1 if interrupt is not pending and LCS CTC */ if ( dev->ctctype == CTC_LCS ) { cc = 1; dev->csw[4] = 0; dev->csw[5] = 0; psa = (PSA_3XX*)(regs->mainstor + regs->PX); memcpy (psa->csw, dev->csw, 8); if (dev->ccwtrace) { logmsg(_("HHCCP054I HIO modification executed CC=1\n")); display_csw (dev, dev->csw); } } else /* Set condition code 0 if interrupt is pending */ cc = 0; } /* For 3270 device, clear any pending input */ if (dev->devtype == 0x3270) { dev->readpending = 0; dev->rlen3270 = 0; } /* Signal console thread to redrive select */ if (dev->console) { SIGNAL_CONSOLE_THREAD(); } /* Queue the interrupt */ if (pending) QUEUE_IO_INTERRUPT (&dev->ioint); release_lock (&dev->lock); /* Update interrupt status */ if (pending) { OBTAIN_INTLOCK(regs); UPDATE_IC_IOPENDING(); RELEASE_INTLOCK(regs); } /* Return the condition code */ return cc; } /* end function haltio */ /*-------------------------------------------------------------------*/ /* CANCEL SUBCHANNEL */ /*-------------------------------------------------------------------*/ /* Input */ /* regs -> CPU register context */ /* dev -> Device control block */ /* Return value */ /* The return value is the condition code for the XSCH */ /* 0=start function cancelled (not yet implemented) */ /* 1=status pending (no action taken) */ /* 2=function not applicable */ /*-------------------------------------------------------------------*/ int cancel_subchan (REGS *regs, DEVBLK *dev) { int cc; /* Condition code */ UNREFERENCED(regs); obtain_lock (&dev->lock); #if defined(_FEATURE_IO_ASSIST) if(SIE_MODE(regs) && (regs->siebk->zone != dev->pmcw.zone || !(dev->pmcw.flag27 & PMCW27_I))) { release_lock (&dev->lock); longjmp(regs->progjmp,SIE_INTERCEPT_INST); } #endif /* Check pending status */ if ((dev->pciscsw.flag3 & SCSW3_SC_PEND) || (dev->scsw.flag3 & SCSW3_SC_PEND) || (dev->attnscsw.flag3 & SCSW3_SC_PEND)) cc = 1; else { cc = 2; #if !defined(OPTION_FISHIO) obtain_lock(&sysblk.ioqlock); if(sysblk.ioq != NULL) { DEVBLK *tmp; /* special case for head of queue */ if(sysblk.ioq == dev) { /* Remove device from the i/o queue */ sysblk.ioq = dev->nextioq; cc = 0; } else { /* Search for device on i/o queue */ for(tmp = sysblk.ioq; tmp->nextioq != NULL && tmp->nextioq != dev; tmp = tmp->nextioq); /* Remove from queue if found */ if(tmp->nextioq == dev) { tmp->nextioq = tmp->nextioq->nextioq; cc = 0; } } /* Reset the device */ if(!cc) { /* Terminate suspended channel program */ if (dev->scsw.flag3 & SCSW3_AC_SUSP) { dev->suspended = 0; signal_condition (&dev->resumecond); } /* Reset the scsw */ dev->scsw.flag2 &= ~(SCSW2_AC_RESUM | SCSW2_FC_START | SCSW2_AC_START); dev->scsw.flag3 &= ~(SCSW3_AC_SUSP); } } release_lock(&sysblk.ioqlock); #endif /*!defined(OPTION_FISHIO)*/ } release_lock (&dev->lock); /* Return the condition code */ return cc; } /* end function cancel_subchan */ /*-------------------------------------------------------------------*/ /* TEST SUBCHANNEL */ /*-------------------------------------------------------------------*/ /* Input */ /* regs -> CPU register context */ /* dev -> Device control block */ /* Output */ /* irb -> Interruption response block */ /* Return value */ /* The return value is the condition code for the TSCH */ /* instruction: 0=status was pending and is now cleared, */ /* 1=no status was pending. The IRB is updated in both cases. */ /*-------------------------------------------------------------------*/ int test_subchan (REGS *regs, DEVBLK *dev, IRB *irb) { int cc; /* Condition code */ #if defined(_FEATURE_IO_ASSIST) UNREFERENCED(regs); #endif obtain_lock (&dev->lock); #if defined(_FEATURE_IO_ASSIST) if(SIE_MODE(regs) && (regs->siebk->zone != dev->pmcw.zone || !(dev->pmcw.flag27 & PMCW27_I))) { release_lock (&dev->lock); longjmp(regs->progjmp,SIE_INTERCEPT_INST); } #endif /* Return PCI SCSW if PCI status is pending */ if (dev->pciscsw.flag3 & SCSW3_SC_PEND) { #if defined(_FEATURE_IO_ASSIST) /* For I/O assisted devices we must intercept if type B status is present on the subchannel */ if(SIE_MODE(regs) && ( (regs->siebk->tschds & dev->pciscsw.unitstat) || (regs->siebk->tschsc & dev->pciscsw.chanstat) ) ) { dev->pmcw.flag27 &= ~PMCW27_I; release_lock (&dev->lock); longjmp(regs->progjmp,SIE_INTERCEPT_IOINST); } #endif /* Display the subchannel status word */ if (dev->ccwtrace || dev->ccwstep) display_scsw (dev, dev->pciscsw); /* Copy the PCI SCSW to the IRB */ irb->scsw = dev->pciscsw; /* Clear the ESW and ECW in the IRB */ memset (&irb->esw, 0, sizeof(ESW)); irb->esw.lpum = 0x80; memset (irb->ecw, 0, sizeof(irb->ecw)); /* Clear the pending PCI status */ dev->pciscsw.flag2 &= ~(SCSW2_FC | SCSW2_AC); dev->pciscsw.flag3 &= ~(SCSW3_SC); dev->pcipending = 0; /* Dequeue the interrupt */ DEQUEUE_IO_INTERRUPT(&dev->pciioint); release_lock (&dev->lock); /* Update interrupt status */ OBTAIN_INTLOCK(regs); UPDATE_IC_IOPENDING(); RELEASE_INTLOCK(regs); /* Return condition code 0 to indicate status was pending */ return 0; } /* end if(pcipending) */ /* Copy the subchannel status word to the IRB */ irb->scsw = dev->scsw; /* Copy the extended status word to the IRB */ irb->esw = dev->esw; /* Copy the extended control word to the IRB */ memcpy (irb->ecw, dev->ecw, sizeof(irb->ecw)); /* Test device status and set condition code */ if (dev->scsw.flag3 & SCSW3_SC_PEND) { #if defined(_FEATURE_IO_ASSIST) /* For I/O assisted devices we must intercept if type B status is present on the subchannel */ if(SIE_MODE(regs) && ( (regs->siebk->tschds & dev->scsw.unitstat) || (regs->siebk->tschsc & dev->scsw.chanstat) ) ) { dev->pmcw.flag27 &= ~PMCW27_I; release_lock (&dev->lock); longjmp(regs->progjmp,SIE_INTERCEPT_IOINST); } #endif /* Set condition code 0 for status pending */ cc = 0; /* Display the subchannel status word */ if (dev->ccwtrace || dev->ccwstep) display_scsw (dev, dev->scsw); /* [14.3.13] If status is anything other than intermediate with pending then clear the function control, activity control, status control, and path not-operational bits in the SCSW */ if ((dev->scsw.flag3 & SCSW3_SC) != (SCSW3_SC_INTER | SCSW3_SC_PEND)) { dev->scsw.flag2 &= ~(SCSW2_FC | SCSW2_AC); dev->scsw.flag3 &= ~(SCSW3_AC_SUSP); dev->scsw.flag1 &= ~(SCSW1_N); } else { /* [14.3.13] Clear the function control bits if function code is halt and the channel program is suspended */ if ((dev->scsw.flag2 & SCSW2_FC_HALT) && (dev->scsw.flag3 & SCSW3_AC_SUSP)) dev->scsw.flag2 &= ~(SCSW2_FC); /* [14.3.13] Clear the activity control bits if function code is start+halt and channel program is suspended */ if ((dev->scsw.flag2 & (SCSW2_FC_START | SCSW2_FC_HALT)) == (SCSW2_FC_START | SCSW2_FC_HALT) && (dev->scsw.flag3 & SCSW3_AC_SUSP)) { dev->scsw.flag2 &= ~(SCSW2_AC); dev->scsw.flag3 &= ~(SCSW3_AC_SUSP); dev->scsw.flag1 &= ~(SCSW1_N); } /* [14.3.13] Clear the resume pending bit if function code is start without halt and channel program suspended */ if ((dev->scsw.flag2 & (SCSW2_FC_START | SCSW2_FC_HALT)) == SCSW2_FC_START && (dev->scsw.flag3 & SCSW3_AC_SUSP)) { dev->scsw.flag2 &= ~(SCSW2_AC_RESUM); dev->scsw.flag1 &= ~(SCSW1_N); } } /* end if(INTER+PEND) */ /* Clear the status bits in the SCSW */ dev->scsw.flag3 &= ~(SCSW3_SC); } else { /* Test device status and set condition code */ if (dev->attnscsw.flag3 & SCSW3_SC_PEND) { #if defined(_FEATURE_IO_ASSIST) /* For I/O assisted devices we must intercept if type B status is present on the subchannel */ if(SIE_MODE(regs) && ( (regs->siebk->tschds & dev->attnscsw.unitstat) || (regs->siebk->tschsc & dev->attnscsw.chanstat) ) ) { dev->pmcw.flag27 &= ~PMCW27_I; release_lock (&dev->lock); longjmp(regs->progjmp,SIE_INTERCEPT_IOINST); } #endif /* Set condition code 0 for status pending */ cc = 0; /* Display the subchannel status word */ if (dev->ccwtrace || dev->ccwstep) display_scsw (dev, dev->attnscsw); /* Copy the ATTN SCSW to the IRB */ irb->scsw = dev->attnscsw; /* Clear the ESW and ECW in the IRB */ memset (&irb->esw, 0, sizeof(ESW)); irb->esw.lpum = 0x80; memset (irb->ecw, 0, sizeof(irb->ecw)); /* Clear the pending ATTN status */ dev->attnscsw.flag2 &= ~(SCSW2_FC | SCSW2_AC); dev->attnscsw.flag3 &= ~(SCSW3_SC); dev->attnpending = 0; /* Dequeue the interrupt */ DEQUEUE_IO_INTERRUPT(&dev->attnioint); release_lock (&dev->lock); /* Update interrupt status */ OBTAIN_INTLOCK(regs); UPDATE_IC_IOPENDING(); RELEASE_INTLOCK(regs); /* Signal console thread to redrive select */ if (dev->console) { SIGNAL_CONSOLE_THREAD(); } /* Return condition code 0 to indicate status was pending */ return 0; } else { /* Set condition code 1 if status not pending */ cc = 1; } } /* Dequeue the interrupt */ DEQUEUE_IO_INTERRUPT(&dev->ioint); release_lock (&dev->lock); /* Update interrupt status */ OBTAIN_INTLOCK(regs); UPDATE_IC_IOPENDING(); RELEASE_INTLOCK(regs); /* Signal console thread to redrive select */ if (dev->console) { SIGNAL_CONSOLE_THREAD(); } /* Return the condition code */ return cc; } /* end function test_subchan */ /*-------------------------------------------------------------------*/ /* CLEAR SUBCHANNEL */ /*-------------------------------------------------------------------*/ /* Input */ /* regs -> CPU register context */ /* dev -> Device control block */ /*-------------------------------------------------------------------*/ void clear_subchan (REGS *regs, DEVBLK *dev) { int pending = 0; UNREFERENCED(regs); if (dev->ccwtrace || dev->ccwstep) logmsg (_("HHCCP055I %4.4X: Clear subchannel\n"), dev->devnum); obtain_lock (&dev->lock); #if defined(_FEATURE_IO_ASSIST) if(SIE_MODE(regs) && (regs->siebk->zone != dev->pmcw.zone || !(dev->pmcw.flag27 & PMCW27_I))) { release_lock (&dev->lock); longjmp(regs->progjmp,SIE_INTERCEPT_INST); } #endif /* If the device is busy then signal the device to clear */ if ((dev->busy && dev->ioactive == DEV_SYS_LOCAL) || dev->startpending) { /* Set clear pending condition */ dev->scsw.flag2 |= SCSW2_FC_CLEAR | SCSW2_AC_CLEAR; /* Signal the subchannel to resume if it is suspended */ if (dev->scsw.flag3 & SCSW3_AC_SUSP) { dev->scsw.flag2 |= SCSW2_AC_RESUM; signal_condition (&dev->resumecond); } #if !defined(NO_SIGABEND_HANDLER) else { if( dev->ctctype ) signal_thread(dev->tid, SIGUSR2); } #endif /*!defined(NO_SIGABEND_HANDLER)*/ } else { /* [15.3.2] Perform clear function subchannel modification */ dev->pmcw.pom = 0xFF; dev->pmcw.lpum = 0x00; dev->pmcw.pnom = 0x00; /* [15.3.3] Perform clear function signaling and completion */ dev->scsw.flag0 = 0; dev->scsw.flag1 = 0; dev->scsw.flag2 &= ~(SCSW2_FC | SCSW2_AC); dev->scsw.flag2 |= SCSW2_FC_CLEAR; dev->scsw.flag3 &= (~(SCSW3_AC | SCSW3_SC))&0xff; dev->scsw.flag3 |= SCSW3_SC_PEND; store_fw (dev->scsw.ccwaddr, 0); dev->scsw.chanstat = 0; dev->scsw.unitstat = 0; store_hw (dev->scsw.count, 0); dev->pcipending = 0; dev->pending = 1; pending = 1; /* For 3270 device, clear any pending input */ if (dev->devtype == 0x3270) { dev->readpending = 0; dev->rlen3270 = 0; } /* Signal console thread to redrive select */ if (dev->console) { SIGNAL_CONSOLE_THREAD(); } } /* Queue any pending i/o interrupt */ if (pending) QUEUE_IO_INTERRUPT (&dev->ioint); release_lock (&dev->lock); /* Update interrupt status */ if (pending) { OBTAIN_INTLOCK(regs); UPDATE_IC_IOPENDING(); RELEASE_INTLOCK(regs); } } /* end function clear_subchan */ /*-------------------------------------------------------------------*/ /* HALT SUBCHANNEL */ /*-------------------------------------------------------------------*/ /* Input */ /* regs -> CPU register context */ /* dev -> Device control block */ /* Return value */ /* The return value is the condition code for the HSCH */ /* instruction: 0=Halt initiated, 1=Non-intermediate status */ /* pending, 2=Busy */ /*-------------------------------------------------------------------*/ int halt_subchan (REGS *regs, DEVBLK *dev) { int pending = 0; UNREFERENCED(regs); if (dev->ccwtrace || dev->ccwstep) logmsg (_("HHCCP056I %4.4X: Halt subchannel\n"), dev->devnum); obtain_lock (&dev->lock); #if defined(_FEATURE_IO_ASSIST) if(SIE_MODE(regs) && (regs->siebk->zone != dev->pmcw.zone || !(dev->pmcw.flag27 & PMCW27_I))) { release_lock (&dev->lock); longjmp(regs->progjmp,SIE_INTERCEPT_INST); } #endif /* Set condition code 1 if subchannel is status pending alone or is status pending with alert, primary, or secondary status */ if ((dev->scsw.flag3 & SCSW3_SC) == SCSW3_SC_PEND || ((dev->scsw.flag3 & SCSW3_SC_PEND) && (dev->scsw.flag3 & (SCSW3_SC_ALERT | SCSW3_SC_PRI | SCSW3_SC_SEC)))) { if (dev->ccwtrace || dev->ccwstep) logmsg (_("HHCCP057I %4.4X: Halt subchannel: cc=1\n"), dev->devnum); release_lock (&dev->lock); return 1; } /* Set condition code 2 if the halt function or the clear function is already in progress at the subchannel */ if (dev->scsw.flag2 & (SCSW2_AC_HALT | SCSW2_AC_CLEAR)) { if (dev->ccwtrace || dev->ccwstep) logmsg (_("HHCCP058I %4.4X: Halt subchannel: cc=2\n"), dev->devnum); release_lock (&dev->lock); return 2; } /* If the device is busy then signal subchannel to halt */ if ((dev->busy && dev->ioactive == DEV_SYS_LOCAL) || dev->startpending || dev->suspended) { /* Set halt pending condition and reset pending condition */ dev->scsw.flag2 |= (SCSW2_FC_HALT | SCSW2_AC_HALT); dev->scsw.flag3 &= ~SCSW3_SC_PEND; /* Clear any pending interrupt */ dev->pending = dev->pcipending = dev->attnpending = 0; /* Signal the subchannel to resume if it is suspended */ if (dev->scsw.flag3 & SCSW3_AC_SUSP) { dev->scsw.flag2 |= SCSW2_AC_RESUM; signal_condition (&dev->resumecond); } #if !defined(OPTION_FISHIO) /* Remove the device from the ioq if startpending */ obtain_lock(&sysblk.ioqlock); if(dev->startpending) { if(sysblk.ioq == dev) sysblk.ioq = dev->nextioq; else { DEVBLK *tmp; for(tmp = sysblk.ioq; tmp->nextioq != NULL && tmp->nextioq != dev; tmp = tmp->nextioq); if(tmp->nextioq == dev) tmp->nextioq = tmp->nextioq->nextioq; } } dev->startpending = 0; release_lock(&sysblk.ioqlock); #endif /*!defined(OPTION_FISHIO)*/ /* Invoke the provided halt_device routine @ISW */ /* if it has been provided by the handler @ISW */ /* code at init @ISW */ if(dev->halt_device!=NULL) /* @ISW */ { /* @ISW */ dev->halt_device(dev); /* @ISW */ } /* @ISW */ #if !defined(NO_SIGABEND_HANDLER) else { if( dev->ctctype && dev->tid) signal_thread(dev->tid, SIGUSR2); } #endif /*!defined(NO_SIGABEND_HANDLER)*/ } else { /* [15.4.2] Perform halt function signaling and completion */ dev->scsw.flag2 |= SCSW2_FC_HALT; dev->scsw.flag3 |= SCSW3_SC_PEND; dev->pcipending = 0; dev->pending = 1; pending = 1; /* For 3270 device, clear any pending input */ if (dev->devtype == 0x3270) { dev->readpending = 0; dev->rlen3270 = 0; } /* Signal console thread to redrive select */ if (dev->console) { SIGNAL_CONSOLE_THREAD(); } } /* Queue any pending i/o interrupt */ if (pending) QUEUE_IO_INTERRUPT (&dev->ioint); release_lock (&dev->lock); /* Update interrupt status */ if (pending) { OBTAIN_INTLOCK(regs); UPDATE_IC_IOPENDING(); RELEASE_INTLOCK(regs); } if (dev->ccwtrace || dev->ccwstep) logmsg (_("HHCCP059I %4.4X: Halt subchannel: cc=0\n"), dev->devnum); /* Return condition code zero */ return 0; } /* end function halt_subchan */ /*-------------------------------------------------------------------*/ /* RESUME SUBCHANNEL */ /*-------------------------------------------------------------------*/ /* Input */ /* regs -> CPU register context */ /* dev -> Device control block */ /* Return value */ /* The return value is the condition code for the RSCH */ /* instruction: 0=subchannel has been made resume pending, */ /* 1=status was pending, 2=resume not allowed */ /*-------------------------------------------------------------------*/ int resume_subchan (REGS *regs, DEVBLK *dev) { UNREFERENCED(regs); obtain_lock (&dev->lock); #if defined(_FEATURE_IO_ASSIST) if(SIE_MODE(regs) && (regs->siebk->zone != dev->pmcw.zone || !(dev->pmcw.flag27 & PMCW27_I))) { release_lock (&dev->lock); longjmp(regs->progjmp,SIE_INTERCEPT_INST); } #endif /* Set condition code 1 if subchannel has status pending */ if (dev->scsw.flag3 & SCSW3_SC_PEND) { if (dev->ccwtrace || dev->ccwstep) logmsg (_("HHCCP060I %4.4X: Resume subchannel: cc=1\n"), dev->devnum); release_lock (&dev->lock); return 1; } /* Set condition code 2 if subchannel has any function other than the start function alone, is already resume pending, or the ORB for the SSCH did not specify suspend control */ if ((dev->scsw.flag2 & SCSW2_FC) != SCSW2_FC_START || (dev->scsw.flag2 & SCSW2_AC_RESUM) || (dev->scsw.flag0 & SCSW0_S) == 0) { if (dev->ccwtrace || dev->ccwstep) logmsg (_("HHCCP061I %4.4X: Resume subchannel: cc=2\n"), dev->devnum); release_lock (&dev->lock); return 2; } /* Clear the path not-operational mask if in suspend state */ if (dev->scsw.flag3 & SCSW3_AC_SUSP) dev->pmcw.pnom = 0x00; /* Signal console thread to redrive select */ if (dev->console) { SIGNAL_CONSOLE_THREAD(); } /* Set the resume pending flag and signal the subchannel */ dev->scsw.flag2 |= SCSW2_AC_RESUM; signal_condition (&dev->resumecond); release_lock (&dev->lock); if (dev->ccwtrace || dev->ccwstep) logmsg (_("HHCCP062I %4.4X: Resume subchannel: cc=0\n"), dev->devnum); /* Return condition code zero */ return 0; } /* end function resume_subchan */ /*-------------------------------------------------------------------*/ /* Reset a device to initialized status */ /* */ /* Called by: */ /* channelset_reset */ /* chp_reset */ /* io_reset */ /* */ /* Caller holds `intlock' */ /*-------------------------------------------------------------------*/ void device_reset (DEVBLK *dev) { obtain_lock (&dev->lock); obtain_lock(&sysblk.iointqlk); DEQUEUE_IO_INTERRUPT_QLOCKED(&dev->ioint); DEQUEUE_IO_INTERRUPT_QLOCKED(&dev->pciioint); DEQUEUE_IO_INTERRUPT_QLOCKED(&dev->attnioint); release_lock(&sysblk.iointqlk); dev->busy = dev->reserved = dev->pending = dev->pcipending = dev->attnpending = dev->startpending = 0; dev->ioactive = DEV_SYS_NONE; if (dev->suspended) { dev->suspended = 0; signal_condition (&dev->resumecond); } if (dev->iowaiters) signal_condition (&dev->iocond); store_fw (dev->pmcw.intparm, 0); dev->pmcw.flag4 &= ~PMCW4_ISC; dev->pmcw.flag5 &= ~(PMCW5_E | PMCW5_LM | PMCW5_MM | PMCW5_D); dev->pmcw.pnom = 0; dev->pmcw.lpum = 0; store_hw (dev->pmcw.mbi, 0); dev->pmcw.flag27 &= ~PMCW27_S; #if defined(_FEATURE_IO_ASSIST) dev->pmcw.zone = 0; dev->pmcw.flag25 &= ~PMCW25_VISC; dev->pmcw.flag27 &= ~PMCW27_I; #endif memset (&dev->scsw, 0, sizeof(SCSW)); memset (&dev->pciscsw, 0, sizeof(SCSW)); memset (&dev->attnscsw, 0, sizeof(SCSW)); dev->readpending = 0; dev->crwpending = 0; dev->ckdxtdef = 0; dev->ckdsetfm = 0; dev->ckdlcount = 0; dev->ckdssi = 0; memset (dev->sense, 0, sizeof(dev->sense)); dev->sns_pending = 0; memset (dev->pgid, 0, sizeof(dev->pgid)); /* By Adrian - Reset drive password */ memset (dev->drvpwd, 0, sizeof(dev->drvpwd)); #if defined(_FEATURE_IO_ASSIST) dev->mainstor = sysblk.mainstor; dev->storkeys = sysblk.storkeys; dev->mainlim = sysblk.mainsize - 1; #endif dev->ioint.dev = dev; dev->ioint.pending = 1; dev->pciioint.dev = dev; dev->pciioint.pcipending = 1; dev->attnioint.dev = dev; dev->attnioint.attnpending = 1; #if defined(FEATURE_VM_BLOCKIO) if (dev->vmd250env) { free(dev->vmd250env); dev->vmd250env = 0 ; } #endif /* defined(FEATURE_VM_BLOCKIO) */ release_lock (&dev->lock); } /* end device_reset() */ /*-------------------------------------------------------------------*/ /* Reset all devices on a particular channelset */ /* */ /* Called by: */ /* SIGP_IMPL (control.c) */ /* SIGP_IPR (control.c) */ /*-------------------------------------------------------------------*/ void channelset_reset(REGS *regs) { DEVBLK *dev; /* -> Device control block */ int console = 0; /* 1 = console device reset */ /* Reset each device in the configuration */ for (dev = sysblk.firstdev; dev != NULL; dev = dev->nextdev) { if( regs->chanset == dev->chanset) { if (dev->console) console = 1; device_reset(dev); } } /* Signal console thread to redrive select */ if (console) SIGNAL_CONSOLE_THREAD(); } /* end function channelset_reset */ /*-------------------------------------------------------------------*/ /* Reset all devices on a particular chpid */ /* */ /* Called by: */ /* RHCP (Reset Channel Path) (io.c) */ /*-------------------------------------------------------------------*/ int chp_reset(REGS *regs, BYTE chpid) { DEVBLK *dev; /* -> Device control block */ int i; int operational = 3; int console = 0; OBTAIN_INTLOCK(regs); /* Reset each device in the configuration */ for (dev = sysblk.firstdev; dev != NULL; dev = dev->nextdev) { for(i = 0; i < 8; i++) { if((chpid == dev->pmcw.chpid[i]) && (dev->pmcw.pim & dev->pmcw.pam & dev->pmcw.pom & (0x80 >> i)) ) { operational = 0; if (dev->console) console = 1; device_reset(dev); } } } /* Signal console thread to redrive select */ if (console) SIGNAL_CONSOLE_THREAD(); RELEASE_INTLOCK(regs); return operational; } /* end function chp_reset */ /*-------------------------------------------------------------------*/ /* I/O RESET */ /* Resets status of all devices ready for IPL. Note that device */ /* positioning is not affected by I/O reset; thus the system can */ /* be IPLed from current position in a tape or card reader file. */ /* */ /* Caller holds `intlock' */ /*-------------------------------------------------------------------*/ void io_reset (void) { DEVBLK *dev; /* -> Device control block */ int console = 0; /* 1 = console device reset */ int i; /* reset sclp interface */ sclp_reset(); /* Connect each channel set to its home cpu */ for (i = 0; i < MAX_CPU; i++) if (IS_CPU_ONLINE(i)) sysblk.regs[i]->chanset = i < FEATURE_LCSS_MAX ? i : 0xFFFF; /* Reset each device in the configuration */ for (dev = sysblk.firstdev; dev != NULL; dev = dev->nextdev) { if (dev->console) console = 1; device_reset(dev); } /* No crws pending anymore */ OFF_IC_CHANRPT; /* Signal console thread to redrive select */ if (console) SIGNAL_CONSOLE_THREAD(); } /* end function io_reset */ #if !defined(OPTION_FISHIO) /*-------------------------------------------------------------------*/ /* Set a thread's priority to its proper value */ /*-------------------------------------------------------------------*/ void adjust_thread_priority(int *newprio) { /* Set root mode in order to set priority */ SETMODE(ROOT); /* Set device thread priority; ignore any errors */ setpriority(PRIO_PROCESS, 0, *newprio); /* Back to user mode */ SETMODE(USER); } /*-------------------------------------------------------------------*/ /* Execute a queued I/O */ /*-------------------------------------------------------------------*/ void *device_thread (void *arg) { char thread_name[32]; DEVBLK *dev; int current_priority; /* Current thread priority */ UNREFERENCED(arg); adjust_thread_priority(&sysblk.devprio); current_priority = getpriority(PRIO_PROCESS, 0); obtain_lock(&sysblk.ioqlock); sysblk.devtnbr++; if (sysblk.devtnbr > sysblk.devthwm) sysblk.devthwm = sysblk.devtnbr; while (1) { while ((dev=sysblk.ioq) != NULL) { snprintf ( thread_name, sizeof(thread_name), "device %4.4X thread", dev->devnum ); thread_name[sizeof(thread_name)-1]=0; SET_THREAD_NAME(thread_name); sysblk.ioq = dev->nextioq; dev->tid = thread_id(); /* Set priority to requested device priority */ if (dev->devprio != current_priority) adjust_thread_priority(&dev->devprio); current_priority = dev->devprio; release_lock (&sysblk.ioqlock); call_execute_ccw_chain(sysblk.arch_mode, dev); obtain_lock(&sysblk.ioqlock); dev->tid = 0; } SET_THREAD_NAME("idle device thread"); if (sysblk.devtmax < 0 || (sysblk.devtmax == 0 && sysblk.devtwait > 3) || (sysblk.devtmax > 0 && sysblk.devtnbr > sysblk.devtmax) || (sysblk.shutdown)) break; /* Wait for work to arrive */ sysblk.devtwait++; wait_condition (&sysblk.ioqcond, &sysblk.ioqlock); } sysblk.devtnbr--; release_lock (&sysblk.ioqlock); return NULL; } /* end function device_thread */ #endif // !defined(OPTION_FISHIO) #endif /*!defined(_CHANNEL_C)*/ /*-------------------------------------------------------------------*/ /* RAISE A PCI INTERRUPT */ /* This function is called during execution of a channel program */ /* whenever a CCW is fetched which has the CCW_FLAGS_PCI flag set */ /*-------------------------------------------------------------------*/ /* Input */ /* dev -> Device control block */ /* ccwkey = Key in which channel program is executing */ /* ccwfmt = CCW format (0 or 1) */ /* ccwaddr = Address of next CCW */ /* Output */ /* The PCI CSW or SCSW is saved in the device block, and the */ /* pcipending flag is set, and an I/O interrupt is scheduled. */ /*-------------------------------------------------------------------*/ static void ARCH_DEP(raise_pci) ( DEVBLK *dev, /* -> Device block */ BYTE ccwkey, /* Bits 0-3=key, 4-7=zeroes */ BYTE ccwfmt, /* CCW format (0 or 1) */ U32 ccwaddr) /* Main storage addr of CCW */ { #if !defined(FEATURE_CHANNEL_SUBSYSTEM) UNREFERENCED(ccwfmt); #endif IODELAY(dev); obtain_lock (&dev->lock); #ifdef FEATURE_S370_CHANNEL /* Save the PCI CSW replacing any previous pending PCI */ dev->pcicsw[0] = ccwkey; dev->pcicsw[1] = (ccwaddr & 0xFF0000) >> 16; dev->pcicsw[2] = (ccwaddr & 0xFF00) >> 8; dev->pcicsw[3] = ccwaddr & 0xFF; dev->pcicsw[4] = 0; dev->pcicsw[5] = CSW_PCI; dev->pcicsw[6] = 0; dev->pcicsw[7] = 0; #endif /*FEATURE_S370_CHANNEL*/ #ifdef FEATURE_CHANNEL_SUBSYSTEM dev->pciscsw.flag0 = ccwkey & SCSW0_KEY; dev->pciscsw.flag1 = (ccwfmt == 1 ? SCSW1_F : 0); dev->pciscsw.flag2 = SCSW2_FC_START; dev->pciscsw.flag3 = SCSW3_AC_SCHAC | SCSW3_AC_DEVAC | SCSW3_SC_INTER | SCSW3_SC_PEND; STORE_FW(dev->pciscsw.ccwaddr,ccwaddr); dev->pciscsw.unitstat = 0; dev->pciscsw.chanstat = CSW_PCI; store_hw (dev->pciscsw.count, 0); #endif /*FEATURE_CHANNEL_SUBSYSTEM*/ /* Queue the PCI pending interrupt */ QUEUE_IO_INTERRUPT(&dev->pciioint); release_lock (&dev->lock); /* Update interrupt status */ OBTAIN_INTLOCK(devregs(dev)); UPDATE_IC_IOPENDING(); RELEASE_INTLOCK(devregs(dev)); } /* end function raise_pci */ /*-------------------------------------------------------------------*/ /* FETCH A CHANNEL COMMAND WORD FROM MAIN STORAGE */ /*-------------------------------------------------------------------*/ static void ARCH_DEP(fetch_ccw) ( DEVBLK *dev, /* -> Device block */ BYTE ccwkey, /* Bits 0-3=key, 4-7=zeroes */ BYTE ccwfmt, /* CCW format (0 or 1) @IWZ*/ U32 ccwaddr, /* Main storage addr of CCW */ BYTE *code, /* Returned operation code */ U32 *addr, /* Returned data address */ BYTE *flags, /* Returned flags */ U16 *count, /* Returned data count */ BYTE *chanstat) /* Returned channel status */ { BYTE storkey; /* Storage key */ BYTE *ccw; /* CCW pointer */ UNREFERENCED_370(dev); *code=0; *count=0; *flags=0; *addr=0; /* Channel program check if CCW is not on a doubleword boundary or is outside limit of main storage */ if ( (ccwaddr & 0x00000007) || CHADDRCHK(ccwaddr, dev) ) { *chanstat = CSW_PROGC; return; } /* Channel protection check if CCW is fetch protected */ storkey = STORAGE_KEY(ccwaddr, dev); if (ccwkey != 0 && (storkey & STORKEY_FETCH) && (storkey & STORKEY_KEY) != ccwkey) { *chanstat = CSW_PROTC; return; } /* Set the main storage reference bit for the CCW location */ STORAGE_KEY(ccwaddr, dev) |= STORKEY_REF; /* Point to the CCW in main storage */ ccw = dev->mainstor + ccwaddr; /* Extract CCW opcode, flags, byte count, and data address */ if (ccwfmt == 0) { *code = ccw[0]; *addr = ((U32)(ccw[1]) << 16) | ((U32)(ccw[2]) << 8) | ccw[3]; *flags = ccw[4]; *count = ((U16)(ccw[6]) << 8) | ccw[7]; } else { *code = ccw[0]; *flags = ccw[1]; *count = ((U16)(ccw[2]) << 8) | ccw[3]; *addr = ((U32)(ccw[4]) << 24) | ((U32)(ccw[5]) << 16) | ((U32)(ccw[6]) << 8) | ccw[7]; } } /* end function fetch_ccw */ /*-------------------------------------------------------------------*/ /* FETCH AN INDIRECT DATA ADDRESS WORD FROM MAIN STORAGE */ /*-------------------------------------------------------------------*/ static void ARCH_DEP(fetch_idaw) ( DEVBLK *dev, /* -> Device block */ BYTE code, /* CCW operation code */ BYTE ccwkey, /* Bits 0-3=key, 4-7=zeroes */ BYTE idawfmt, /* IDAW format (1 or 2) @IWZ*/ U16 idapmask, /* IDA page size - 1 @IWZ*/ int idaseq, /* 0=1st IDAW */ U32 idawaddr, /* Main storage addr of IDAW */ RADR *addr, /* Returned IDAW content @IWZ*/ U16 *len, /* Returned IDA data length */ BYTE *chanstat) /* Returned channel status */ { RADR idaw; /* Contents of IDAW @IWZ*/ U32 idaw1; /* Format-1 IDAW @IWZ*/ U64 idaw2; /* Format-2 IDAW @IWZ*/ RADR idapage; /* Addr of next IDA page @IWZ*/ U16 idalen; /* #of bytes until next page */ BYTE storkey; /* Storage key */ UNREFERENCED_370(dev); *addr = 0; *len = 0; /* Channel program check if IDAW is not on correct @IWZ boundary or is outside limit of main storage */ if ((idawaddr & ((idawfmt == 2) ? 0x07 : 0x03)) /*@IWZ*/ || CHADDRCHK(idawaddr, dev) ) { *chanstat = CSW_PROGC; return; } /* Channel protection check if IDAW is fetch protected */ storkey = STORAGE_KEY(idawaddr, dev); if (ccwkey != 0 && (storkey & STORKEY_FETCH) && (storkey & STORKEY_KEY) != ccwkey) { *chanstat = CSW_PROTC; return; } /* Set the main storage reference bit for the IDAW location */ STORAGE_KEY(idawaddr, dev) |= STORKEY_REF; /* Fetch IDAW from main storage */ if (idawfmt == 2) /*@IWZ*/ { /*@IWZ*/ /* Fetch format-2 IDAW */ /*@IWZ*/ FETCH_DW(idaw2, dev->mainstor + idawaddr); /*@IWZ*/ #ifndef FEATURE_ESAME /*@IWZ*/ /* Channel program check in ESA/390 mode if the format-2 IDAW exceeds 2GB-1 */ /*@IWZ*/ if (idaw2 > 0x7FFFFFFF) /*@IWZ*/ { /*@IWZ*/ *chanstat = CSW_PROGC; /*@IWZ*/ return; /*@IWZ*/ } /*@IWZ*/ #endif /*!FEATURE_ESAME*/ /*@IWZ*/ /* Save contents of format-2 IDAW */ /*@IWZ*/ idaw = idaw2; /*@IWZ*/ } /*@IWZ*/ else /*@IWZ*/ { /*@IWZ*/ /* Fetch format-1 IDAW */ /*@IWZ*/ FETCH_FW(idaw1, dev->mainstor + idawaddr); /*@IWZ*/ /* Channel program check if bit 0 of the format-1 IDAW is not zero */ /*@IWZ*/ if (idaw1 & 0x80000000) /*@IWZ*/ { /*@IWZ*/ *chanstat = CSW_PROGC; /*@IWZ*/ return; /*@IWZ*/ } /*@IWZ*/ /* Save contents of format-1 IDAW */ /*@IWZ*/ idaw = idaw1; /*@IWZ*/ } /*@IWZ*/ /* Channel program check if IDAW data location is outside main storage */ if ( CHADDRCHK(idaw, dev) ) { *chanstat = CSW_PROGC; return; } /* Channel program check if IDAW data location is not on a page boundary, except for the first IDAW */ /*@IWZ*/ if (IS_CCW_RDBACK (code)) { if (idaseq > 0 && ((idaw+1) & idapmask) != 0) { *chanstat = CSW_PROGC; return; } /* Calculate address of next page boundary */ idapage = (idaw & ~idapmask); idalen = (idaw - idapage) + 1; /* Return the address and length for this IDAW */ *addr = idaw; *len = idalen; } else { if (idaseq > 0 && (idaw & idapmask) != 0) /*@IWZ*/ { *chanstat = CSW_PROGC; return; } /* Calculate address of next page boundary */ /*@IWZ*/ idapage = (idaw + idapmask + 1) & ~idapmask; /*@IWZ*/ idalen = idapage - idaw; /* Return the address and length for this IDAW */ *addr = idaw; *len = idalen; } } /* end function fetch_idaw */ #if defined(FEATURE_MIDAW) /*@MW*/ /*-------------------------------------------------------------------*/ /* FETCH A MODIFIED INDIRECT DATA ADDRESS WORD FROM MAIN STORAGE @MW*/ /*-------------------------------------------------------------------*/ static void ARCH_DEP(fetch_midaw) ( /*@MW*/ DEVBLK *dev, /* -> Device block */ BYTE code, /* CCW operation code */ BYTE ccwkey, /* Bits 0-3=key, 4-7=zeroes */ int midawseq, /* 0=1st MIDAW */ U32 midawadr, /* Main storage addr of MIDAW*/ RADR *addr, /* Returned MIDAW content */ U16 *len, /* Returned MIDAW data length*/ BYTE *flags, /* Returned MIDAW flags */ BYTE *chanstat) /* Returned channel status */ { U64 mword1, mword2; /* MIDAW high and low words */ RADR mdaddr; /* Data address from MIDAW */ U16 mcount; /* Count field from MIDAW */ BYTE mflags; /* Flags byte from MIDAW */ BYTE storkey; /* Storage key */ U16 maxlen; /* Maximum allowable length */ UNREFERENCED_370(dev); /* Channel program check if MIDAW is not on quadword boundary or is outside limit of main storage */ if ((midawadr & 0x0F) || CHADDRCHK(midawadr, dev) ) { *chanstat = CSW_PROGC; return; } /* Channel program check if MIDAW list crosses a page boundary */ if (midawseq > 0 && (midawadr & PAGEFRAME_BYTEMASK) == 0) { *chanstat = CSW_PROGC; return; } /* Channel protection check if MIDAW is fetch protected */ storkey = STORAGE_KEY(midawadr, dev); if (ccwkey != 0 && (storkey & STORKEY_FETCH) && (storkey & STORKEY_KEY) != ccwkey) { *chanstat = CSW_PROTC; return; } /* Set the main storage reference bit for the MIDAW location */ STORAGE_KEY(midawadr, dev) |= STORKEY_REF; /* Fetch MIDAW from main storage (MIDAW is quadword aligned and so cannot cross a page boundary) */ FETCH_DW(mword1, dev->mainstor + midawadr); FETCH_DW(mword2, dev->mainstor + midawadr + 8); /* Channel program check in reserved bits are non-zero */ if (mword1 & 0xFFFFFFFFFF000000ULL) { *chanstat = CSW_PROGC; return; } /* Extract fields from MIDAW */ mflags = mword1 >> 16; mcount = mword1 & 0xFFFF; mdaddr = (RADR)mword2; /* Channel program check if data transfer interrupt flag is set */ if (mflags & MIDAW_DTI) { *chanstat = CSW_PROGC; return; } /* Channel program check if MIDAW count is zero */ if (mcount == 0) { *chanstat = CSW_PROGC; return; } /* Channel program check if MIDAW data location is outside main storage */ if ( CHADDRCHK(mdaddr, dev) ) { *chanstat = CSW_PROGC; return; } /* Channel program check if skipping not in effect and the MIDAW data area crosses a page boundary */ maxlen = (IS_CCW_RDBACK(code)) ? mdaddr - (mdaddr & PAGEFRAME_PAGEMASK) + 1 : (mdaddr | PAGEFRAME_BYTEMASK) - mdaddr + 1 ; if ((mflags & MIDAW_SKIP) == 0 && mcount > maxlen) { *chanstat = CSW_PROGC; return; } /* Return the data address, length, flags for this MIDAW */ *addr = mdaddr; *len = mcount; *flags = mflags; } /* end function fetch_midaw */ /*@MW*/ #endif /*defined(FEATURE_MIDAW)*/ /*@MW*/ /*-------------------------------------------------------------------*/ /* COPY DATA BETWEEN CHANNEL I/O BUFFER AND MAIN STORAGE */ /*-------------------------------------------------------------------*/ static void ARCH_DEP(copy_iobuf) ( DEVBLK *dev, /* -> Device block */ BYTE code, /* CCW operation code */ BYTE flags, /* CCW flags */ U32 addr, /* Data address */ U16 count, /* Data count */ BYTE ccwkey, /* Protection key */ BYTE idawfmt, /* IDAW format (1 or 2) @IWZ*/ U16 idapmask, /* IDA page size - 1 @IWZ*/ BYTE *iobuf, /* -> Channel I/O buffer */ BYTE *chanstat) /* Returned channel status */ { U32 idawaddr; /* Main storage addr of IDAW */ U16 idacount; /* IDA bytes remaining */ int idaseq; /* IDA sequence number */ RADR idadata; /* IDA data address @IWZ*/ U16 idalen; /* IDA data length */ BYTE storkey; /* Storage key */ RADR page,startpage,endpage; /* Storage key pages */ BYTE readcmd; /* 1=READ, SENSE, or RDBACK */ BYTE area[64]; /* Data display area */ #if defined(FEATURE_MIDAW) /*@MW*/ int midawseq; /* MIDAW counter (0=1st) @MW*/ U32 midawptr; /* Real addr of MIDAW @MW*/ U16 midawrem; /* CCW bytes remaining @MW*/ U16 midawlen=0; /* MIDAW data length @MW*/ RADR midawdat=0; /* MIDAW data area addr @MW*/ BYTE midawflg; /* MIDAW flags @MW*/ #endif /*defined(FEATURE_MIDAW)*/ /*@MW*/ /* Exit if no bytes are to be copied */ if (count == 0) return; /* Set flag to indicate direction of data movement */ readcmd = IS_CCW_READ(code) || IS_CCW_SENSE(code) || IS_CCW_RDBACK(code); #if defined(FEATURE_MIDAW) /*@MW*/ /* Move data when modified indirect data addressing is used */ if (flags & CCW_FLAGS_MIDAW) { midawptr = addr; midawrem = count; midawflg = 0; for (midawseq = 0; midawrem > 0 && (midawflg & MIDAW_LAST) == 0; midawseq++) { /* Fetch MIDAW and set data address, length, flags */ ARCH_DEP(fetch_midaw) (dev, code, ccwkey, midawseq, midawptr, &midawdat, &midawlen, &midawflg, chanstat); /* Exit if fetch_midaw detected channel program check */ if (*chanstat != 0) return; /* Channel program check if MIDAW length exceeds the remaining CCW count */ if (midawlen > midawrem) { *chanstat = CSW_PROGC; return; } /* Perform data movement unless SKIP flag is set in MIDAW */ if ((midawflg & MIDAW_SKIP) ==0) { /* Note: MIDAW data area cannot cross a page boundary The fetch_midaw function enforces this restriction */ /* Channel protection check if MIDAW data location is fetch protected, or if location is store protected and command is READ, READ BACKWARD, or SENSE */ storkey = STORAGE_KEY(midawdat, dev); if (ccwkey != 0 && (storkey & STORKEY_KEY) != ccwkey && ((storkey & STORKEY_FETCH) || readcmd)) { *chanstat = CSW_PROTC; return; } /* Set the main storage reference and change bits */ STORAGE_KEY(midawdat, dev) |= (readcmd ? (STORKEY_REF|STORKEY_CHANGE) : STORKEY_REF); /* Copy data between main storage and channel buffer */ if (IS_CCW_RDBACK(code)) { midawdat = (midawdat - midawlen) + 1; memcpy (dev->mainstor + midawdat, iobuf + dev->curblkrem + midawrem - midawlen, midawlen); /* Decrement buffer pointer */ iobuf -= midawlen; } else { if (readcmd) memcpy (dev->mainstor + midawdat, iobuf, midawlen); else memcpy (iobuf, dev->mainstor + midawdat, midawlen); /* Increment buffer pointer */ iobuf += midawlen; } } /* end if(!MIDAW_FLAG_SKIP) */ /* Display the MIDAW if CCW tracing is on */ if (dev->ccwtrace || dev->ccwstep) { format_iobuf_data (midawdat, area, dev); logmsg ( _("HHCCP078I " "%4.4X:MIDAW=%2.2X %4.4"I16_FMT"X %16.16"I64_FMT"X\n" "%4.4X:------------- %s\n"), dev->devnum, midawflg, midawlen, (U64)midawdat, dev->devnum, area); } /* Decrement remaining count */ midawrem -= midawlen; /* Increment to next MIDAW address */ midawptr += 16; } /* end for(midawseq) */ /* Channel program check if sum of MIDAW lengths did not exhaust the CCW count */ if (midawrem > 0) { *chanstat = CSW_PROGC; return; } } /* end if(CCW_FLAGS_MIDAW) */ /*@MW*/ else /*@MW*/ #endif /*defined(FEATURE_MIDAW)*/ /*@MW*/ /* Move data when indirect data addressing is used */ if (flags & CCW_FLAGS_IDA) { idawaddr = addr; idacount = count; for (idaseq = 0; idacount > 0; idaseq++) { /* Fetch the IDAW and set IDA pointer and length */ ARCH_DEP(fetch_idaw) (dev, code, ccwkey, idawfmt, /*@IWZ*/ idapmask, idaseq, idawaddr, /*@IWZ*/ &idadata, &idalen, chanstat); /* Exit if fetch_idaw detected channel program check */ if (*chanstat != 0) return; /* Channel protection check if IDAW data location is fetch protected, or if location is store protected and command is READ, READ BACKWARD, or SENSE */ storkey = STORAGE_KEY(idadata, dev); if (ccwkey != 0 && (storkey & STORKEY_KEY) != ccwkey && ((storkey & STORKEY_FETCH) || readcmd)) { *chanstat = CSW_PROTC; return; } /* Reduce length if less than one page remaining */ if (idalen > idacount) idalen = idacount; /* Set the main storage reference and change bits */ STORAGE_KEY(idadata, dev) |= (readcmd ? (STORKEY_REF|STORKEY_CHANGE) : STORKEY_REF); /* Copy data between main storage and channel buffer */ if (IS_CCW_RDBACK(code)) { idadata = (idadata - idalen) + 1; memcpy (dev->mainstor + idadata, iobuf + dev->curblkrem + idacount - idalen, idalen); } else { if (readcmd) memcpy (dev->mainstor + idadata, iobuf, idalen); else memcpy (iobuf, dev->mainstor + idadata, idalen); /* JRJ: I believe that the following line of code code is suspect, because data chaining adds the used length later, as needed. Also, I note that this kind of thing is not done in non-IDA mode. Finally, since iobuf is not used for anything after this (in IDA mode), it probably doesn't hurt anything. */ /* rbowler: I disagree with the above comment. Here we are in a loop processing a list of IDAWs and it is necessary to update the iobuf pointer so that it is correctly positioned ready for the data to be read or written by the subsequent IDAW */ /* Increment buffer pointer */ iobuf += idalen; } /* Display the IDAW if CCW tracing is on */ if (dev->ccwtrace || dev->ccwstep) { format_iobuf_data (idadata, area, dev); if (idawfmt == 1) /*@IWZ*/ { /*@IWZ*/ logmsg ( _("HHCCP063I " /*@IWZ*/ "%4.4X:IDAW=%8.8"I32_FMT"X Len=%3.3"I16_FMT"X%s\n"), dev->devnum, (U32)idadata, idalen, /*@IWZ*/ area); /*@IWZ*/ } else { /*@IWZ*/ logmsg ( _("HHCCP064I " /*@IWZ*/ "%4.4X:IDAW=%16.16"I64_FMT"X Len=%4.4"I16_FMT"X\n" "%4.4X:---------------------%s\n"), /*@IWZ*/ dev->devnum, (U64)idadata, idalen, dev->devnum, area); /*@IWZ*/ } } /* Decrement remaining count, increment buffer pointer */ idacount -= idalen; /* Increment to next IDAW address */ idawaddr += (idawfmt == 1) ? 4 : 8; } /* end for(idaseq) */ } else { /* Non-IDA data addressing */ /* Point to start of data for read backward command */ if (IS_CCW_RDBACK (code)) { addr = addr - count + 1; } /* Channel program check if data is outside main storage */ if ( CHADDRCHK(addr, dev) || CHADDRCHK(addr + (count - 1), dev) ) { *chanstat = CSW_PROGC; return; } /* Channel protection check if any data is fetch protected, or if location is store protected and command is READ, READ BACKWARD, or SENSE */ startpage = addr; endpage = addr + (count - 1); for (page = startpage & STORAGE_KEY_PAGEMASK; page <= (endpage | STORAGE_KEY_BYTEMASK); page += STORAGE_KEY_PAGESIZE) { storkey = STORAGE_KEY(page, dev); if (ccwkey != 0 && (storkey & STORKEY_KEY) != ccwkey && ((storkey & STORKEY_FETCH) || readcmd)) { *chanstat = CSW_PROTC; return; } } /* end for(page) */ /* Set the main storage reference and change bits */ for (page = startpage & STORAGE_KEY_PAGEMASK; page <= (endpage | STORAGE_KEY_BYTEMASK); page += STORAGE_KEY_PAGESIZE) { STORAGE_KEY(page, dev) |= (readcmd ? (STORKEY_REF|STORKEY_CHANGE) : STORKEY_REF); } /* end for(page) */ /* Copy data between main storage and channel buffer */ if (readcmd) { if (IS_CCW_RDBACK(code)) { /* read backward - use END of buffer */ memcpy(dev->mainstor + addr,iobuf + dev->curblkrem, count); } else /* read forward */ { memcpy (dev->mainstor + addr, iobuf, count); } } else { memcpy (iobuf, dev->mainstor + addr, count); } } /* end if(!IDA) */ } /* end function copy_iobuf */ /*-------------------------------------------------------------------*/ /* DEVICE ATTENTION */ /* Raises an unsolicited interrupt condition for a specified device. */ /* Return value is 0 if successful, 1 if device is busy or pending */ /* or 3 if subchannel is not valid or not enabled */ /*-------------------------------------------------------------------*/ DLL_EXPORT int ARCH_DEP(device_attention) (DEVBLK *dev, BYTE unitstat) { obtain_lock (&dev->lock); if (dev->hnd->attention) (dev->hnd->attention) (dev); #ifdef FEATURE_CHANNEL_SUBSYSTEM /* If subchannel not valid and enabled, do not present interrupt */ if ((dev->pmcw.flag5 & PMCW5_V) == 0 || (dev->pmcw.flag5 & PMCW5_E) == 0) { release_lock (&dev->lock); return 3; } #endif /*FEATURE_CHANNEL_SUBSYSTEM*/ /* If device is already busy or interrupt pending */ if (dev->busy || IOPENDING(dev) || (dev->scsw.flag3 & SCSW3_SC_PEND)) { /* Resume the suspended device with attention set */ if(dev->scsw.flag3 & SCSW3_AC_SUSP) { dev->scsw.flag3 |= SCSW3_SC_ALERT | SCSW3_SC_PEND; dev->scsw.unitstat |= unitstat; dev->scsw.flag2 |= SCSW2_AC_RESUM; signal_condition(&dev->resumecond); release_lock (&dev->lock); if (dev->ccwtrace || dev->ccwstep) logmsg (_("HHCCP065I DEV%4.4X: attention signalled\n"), dev->devnum); return 0; } release_lock (&dev->lock); return 1; } if (dev->ccwtrace || dev->ccwstep) logmsg (_("HHCCP066I DEV%4.4X: attention\n"), dev->devnum); #ifdef FEATURE_S370_CHANNEL /* Set CSW for attention interrupt */ dev->attncsw[0] = 0; dev->attncsw[1] = 0; dev->attncsw[2] = 0; dev->attncsw[3] = 0; dev->attncsw[4] = unitstat; dev->attncsw[5] = 0; dev->attncsw[6] = 0; dev->attncsw[7] = 0; #endif /*FEATURE_S370_CHANNEL*/ #ifdef FEATURE_CHANNEL_SUBSYSTEM /* Set SCSW for attention interrupt */ dev->attnscsw.flag0 = 0; dev->attnscsw.flag1 = 0; dev->attnscsw.flag2 = 0; dev->attnscsw.flag3 = SCSW3_SC_ALERT | SCSW3_SC_PEND; store_fw (dev->attnscsw.ccwaddr, 0); dev->attnscsw.unitstat = unitstat; dev->attnscsw.chanstat = 0; store_hw (dev->attnscsw.count, 0); #endif /*FEATURE_CHANNEL_SUBSYSTEM*/ /* Queue the attention interrupt */ QUEUE_IO_INTERRUPT (&dev->attnioint); release_lock (&dev->lock); /* Update interrupt status */ OBTAIN_INTLOCK(devregs(dev)); UPDATE_IC_IOPENDING(); RELEASE_INTLOCK(devregs(dev)); return 0; } /* end function device_attention */ /*-------------------------------------------------------------------*/ /* START A CHANNEL PROGRAM */ /* This function is called by the SIO and SSCH instructions */ /*-------------------------------------------------------------------*/ /* Input */ /* dev -> Device control block */ /* orb -> Operation request block @IWZ*/ /* Output */ /* The I/O parameters are stored in the device block, and a */ /* thread is created to execute the CCW chain asynchronously. */ /* The return value is the condition code for the SIO or */ /* SSCH instruction. */ /* Note */ /* For S/370 SIO, only the protect key and CCW address are */ /* valid, all other ORB parameters are set to zero. */ /*-------------------------------------------------------------------*/ int ARCH_DEP(startio) (REGS *regs, DEVBLK *dev, ORB *orb) /*@IWZ*/ { int syncio; /* 1=Do synchronous I/O */ #if !defined(OPTION_FISHIO) int rc; /* Return code */ DEVBLK *previoq, *ioq; /* Device I/O queue pointers */ #endif // !defined(OPTION_FISHIO) obtain_lock (&dev->lock); dev->regs = NULL; dev->syncio_active = dev->syncio_retry = 0; #if defined(_FEATURE_IO_ASSIST) if(SIE_MODE(regs) && (regs->siebk->zone != dev->pmcw.zone || !(dev->pmcw.flag27 & PMCW27_I))) { release_lock (&dev->lock); longjmp(regs->progjmp,SIE_INTERCEPT_INST); } #endif #ifdef FEATURE_CHANNEL_SUBSYSTEM /* Return condition code 1 if status pending */ if ((dev->scsw.flag3 & SCSW3_SC_PEND) || (dev->pciscsw.flag3 & SCSW3_SC_PEND) || (dev->attnscsw.flag3 & SCSW3_SC_PEND)) { release_lock (&dev->lock); return 1; } #endif /*FEATURE_CHANNEL_SUBSYSTEM*/ /* Return condition code 2 if device is busy */ if ((dev->busy && dev->ioactive == DEV_SYS_LOCAL) || dev->startpending) { release_lock (&dev->lock); return 2; } /* Set the device busy indicator */ dev->busy = dev->startpending = 1; /* Initialize the subchannel status word */ memset (&dev->scsw, 0, sizeof(SCSW)); memset (&dev->pciscsw, 0, sizeof(SCSW)); memset (&dev->attnscsw, 0, sizeof(SCSW)); dev->scsw.flag0 = (orb->flag4 & SCSW0_KEY); /*@IWZ*/ if (orb->flag4 & ORB4_S) dev->scsw.flag0 |= SCSW0_S; /*@IWZ*/ if (orb->flag5 & ORB5_F) dev->scsw.flag1 |= SCSW1_F; /*@IWZ*/ if (orb->flag5 & ORB5_P) dev->scsw.flag1 |= SCSW1_P; /*@IWZ*/ if (orb->flag5 & ORB5_I) dev->scsw.flag1 |= SCSW1_I; /*@IWZ*/ if (orb->flag5 & ORB5_A) dev->scsw.flag1 |= SCSW1_A; /*@IWZ*/ if (orb->flag5 & ORB5_U) dev->scsw.flag1 |= SCSW1_U; /*@IWZ*/ /* Make the subchannel start-pending */ dev->scsw.flag2 = SCSW2_FC_START | SCSW2_AC_START; /* Copy the I/O parameter to the path management control word */ memcpy (dev->pmcw.intparm, orb->intparm, /*@IWZ*/ sizeof(dev->pmcw.intparm)); /*@IWZ*/ /* Signal console thread to redrive select */ if (dev->console) { SIGNAL_CONSOLE_THREAD(); } /* Store the start I/O parameters in the device block */ memcpy (&dev->orb, orb, sizeof(ORB)); /*@IWZ*/ /* Schedule the I/O. The various methods are a direct * correlation to the interest in the subject: * [1] Synchronous I/O. Attempts to complete the channel program * in the cpu thread to avoid any threads overhead. * [2] FishIO. Use native win32 APIs to coordinate I/O * thread scheduling. * [3] Device threads. Queue the I/O and signal a device thread. * Eliminates the overhead of thead creation/termination. * [4] Original. Create a thread to execute this I/O */ /* Determine if we can do synchronous I/O */ if (dev->syncio == 1) syncio = 1; else if (dev->syncio == 2 && fetch_fw(dev->orb.ccwaddr) < dev->mainlim) { dev->code = dev->mainstor[fetch_fw(dev->orb.ccwaddr)]; syncio = IS_CCW_TIC(dev->code) || IS_CCW_SENSE(dev->code) || IS_CCW_IMMEDIATE(dev); } else syncio = 0; if (syncio && dev->ioactive == DEV_SYS_NONE #ifdef OPTION_IODELAY_KLUDGE && sysblk.iodelay < 1 #endif /*OPTION_IODELAY_KLUDGE*/ ) { /* Initiate synchronous I/O */ dev->syncio_active = 1; dev->ioactive = DEV_SYS_LOCAL; dev->regs = regs; release_lock (&dev->lock); /* * `syncio' is set with intlock held. This allows * SYNCHRONIZE_CPUS to consider this CPU waiting while * performing synchronous i/o. */ if (regs->cpubit != sysblk.started_mask) { OBTAIN_INTLOCK(regs); regs->hostregs->syncio = 1; RELEASE_INTLOCK(regs); } call_execute_ccw_chain(sysblk.arch_mode, dev); /* Return if retry not required */ if (regs->hostregs->syncio) { OBTAIN_INTLOCK(regs); regs->hostregs->syncio = 0; RELEASE_INTLOCK(regs); } dev->regs = NULL; dev->syncio_active = 0; if (!dev->syncio_retry) return 0; /* * syncio_retry gets turned off after the execute ccw * device handler routine is called for the first time */ } else release_lock (&dev->lock); #if defined(OPTION_FISHIO) return ScheduleIORequest( dev, dev->devnum, &dev->devprio ); #else // !defined(OPTION_FISHIO) if (sysblk.devtmax >= 0) { /* Queue the I/O request */ obtain_lock (&sysblk.ioqlock); /* Insert the device into the I/O queue */ for (previoq = NULL, ioq = sysblk.ioq; ioq; ioq = ioq->nextioq) { if (dev->priority < ioq->priority) break; previoq = ioq; } dev->nextioq = ioq; if (previoq) previoq->nextioq = dev; else sysblk.ioq = dev; /* Signal a device thread if one is waiting, otherwise create a device thread if the maximum number hasn't been created */ if (sysblk.devtwait) { sysblk.devtwait--; signal_condition(&sysblk.ioqcond); } else if (sysblk.devtmax == 0 || sysblk.devtnbr < sysblk.devtmax) { rc = create_thread (&dev->tid, DETACHED, device_thread, NULL, "idle device thread"); if (rc != 0 && sysblk.devtnbr == 0) { logmsg (_("HHCCP067E %4.4X create_thread error: %s"), dev->devnum, strerror(errno)); release_lock (&sysblk.ioqlock); release_lock (&dev->lock); return 2; } } else sysblk.devtunavail++; release_lock (&sysblk.ioqlock); } else { char thread_name[32]; snprintf(thread_name,sizeof(thread_name), "execute %4.4X ccw chain",dev->devnum); thread_name[sizeof(thread_name)-1]=0; /* Execute the CCW chain on a separate thread */ if ( create_thread (&dev->tid, DETACHED, ARCH_DEP(execute_ccw_chain), dev, thread_name) ) { logmsg (_("HHCCP068E %4.4X create_thread error: %s"), dev->devnum, strerror(errno)); release_lock (&dev->lock); return 2; } } /* Return with condition code zero */ return 0; #endif // defined(OPTION_FISHIO) } /* end function startio */ /*-------------------------------------------------------------------*/ /* EXECUTE A CHANNEL PROGRAM */ /*-------------------------------------------------------------------*/ void *ARCH_DEP(execute_ccw_chain) (DEVBLK *dev) { int sysid = DEV_SYS_LOCAL; /* System Identifier */ U32 ccwaddr; /* Address of CCW @IWZ*/ U16 idapmask; /* IDA page size - 1 @IWZ*/ BYTE idawfmt; /* IDAW format (1 or 2) @IWZ*/ BYTE ccwfmt; /* CCW format (0 or 1) @IWZ*/ BYTE ccwkey; /* Bits 0-3=key, 4-7=zero@IWZ*/ BYTE opcode; /* CCW operation code */ BYTE flags; /* CCW flags */ U32 addr; /* CCW data address */ #ifdef FEATURE_CHANNEL_SUBSYSTEM U32 mbaddr; /* Measure block address */ MBK *mbk; /* Measure block */ U16 mbcount; /* Measure block count */ #endif /*FEATURE_CHANNEL_SUBSYSTEM*/ U16 count; /* CCW byte count */ BYTE *ccw; /* CCW pointer */ BYTE unitstat; /* Unit status */ BYTE chanstat; /* Channel status */ U16 residual; /* Residual byte count */ BYTE more; /* 1=Count exhausted */ BYTE tic = 0; /* Previous CCW was a TIC */ BYTE chain = 1; /* 1=Chain to next CCW */ BYTE tracethis = 0; /* 1=Trace this CCW only */ BYTE area[64]; /* Message area */ int bufpos = 0; /* Position in I/O buffer */ BYTE iobuf[65536]; /* Channel I/O buffer */ /* Wait for the device to become available */ obtain_lock (&dev->lock); if (!dev->syncio_active && dev->shared) { while (dev->ioactive != DEV_SYS_NONE && dev->ioactive != sysid) { dev->iowaiters++; wait_condition(&dev->iocond, &dev->lock); dev->iowaiters--; } dev->ioactive = sysid; dev->busy = 1; if (sysid == DEV_SYS_LOCAL) dev->startpending = 0; } else { dev->ioactive = DEV_SYS_LOCAL; dev->startpending = 0; } #ifdef FEATURE_CHANNEL_SUBSYSTEM /* For hercules `resume' resume suspended state */ if (dev->resumesuspended) { dev->resumesuspended=0; goto resume_suspend; } #endif release_lock (&dev->lock); /* Call the i/o start exit */ if (!dev->syncio_retry) if (dev->hnd->start) (dev->hnd->start) (dev); /* Extract the I/O parameters from the ORB */ /*@IWZ*/ FETCH_FW(ccwaddr, dev->orb.ccwaddr); /*@IWZ*/ ccwfmt = (dev->orb.flag5 & ORB5_F) ? 1 : 0; /*@IWZ*/ ccwkey = dev->orb.flag4 & ORB4_KEY; /*@IWZ*/ idawfmt = (dev->orb.flag5 & ORB5_H) ? 2 : 1; /*@IWZ*/ /* Determine IDA page size */ /*@IWZ*/ if (idawfmt == 2) /*@IWZ*/ { /*@IWZ*/ /* Page size is 2K or 4K depending on flag bit */ /*@IWZ*/ idapmask = /*@IWZ*/ (dev->orb.flag5 & ORB5_T) ? 0x7FF : 0xFFF; /*@IWZ*/ } else { /*@IWZ*/ /* Page size is always 2K for format-1 IDAW */ /*@IWZ*/ idapmask = 0x7FF; /*@IWZ*/ } /*@IWZ*/ /* Turn off the start pending bit in the SCSW */ dev->scsw.flag2 &= ~SCSW2_AC_START; /* Set the subchannel active and device active bits in the SCSW */ dev->scsw.flag3 |= (SCSW3_AC_SCHAC | SCSW3_AC_DEVAC); /* Check for retried synchronous I/O */ if (dev->syncio_retry) { dev->syncios--; dev->asyncios++; ccwaddr = dev->syncio_addr; dev->code = dev->prevcode; dev->prevcode = 0; dev->chained &= ~CCW_FLAGS_CD; dev->prev_chained = 0; logdevtr (dev, "asynchronous I/O ccw addr %8.8x\n", ccwaddr); } else { dev->chained = dev->prev_chained = dev->code = dev->prevcode = dev->ccwseq = 0; } /* Check for synchronous I/O */ if (dev->syncio_active) { dev->syncios++; logdevtr (dev, "synchronous I/O ccw addr %8.8x\n", ccwaddr); } #if defined(_FEATURE_IO_ASSIST) #define _IOA_MBO sysblk.zpb[dev->pmcw.zone].mbo #define _IOA_MBM sysblk.zpb[dev->pmcw.zone].mbm #define _IOA_MBK sysblk.zpb[dev->pmcw.zone].mbk #else /*defined(_FEATURE_IO_ASSIST)*/ #define _IOA_MBO sysblk.mbo #define _IOA_MBM sysblk.mbm #define _IOA_MBK sysblk.mbk #endif /*defined(_FEATURE_IO_ASSIST)*/ #ifdef FEATURE_CHANNEL_SUBSYSTEM /* Update the measurement block if applicable */ if (_IOA_MBM && (dev->pmcw.flag5 & PMCW5_MM_MBU)) { mbaddr = _IOA_MBO; mbaddr += (dev->pmcw.mbi[0] << 8 | dev->pmcw.mbi[1]) << 5; if ( !CHADDRCHK(mbaddr, dev) && (((STORAGE_KEY(mbaddr, dev) & STORKEY_KEY) == _IOA_MBK) || (_IOA_MBK == 0))) { STORAGE_KEY(mbaddr, dev) |= (STORKEY_REF | STORKEY_CHANGE); mbk = (MBK*)&dev->mainstor[mbaddr]; FETCH_HW(mbcount,mbk->srcount); mbcount++; STORE_HW(mbk->srcount,mbcount); } else { /* Generate subchannel logout indicating program check or protection check, and set the subchannel measurement-block-update-enable to zero */ dev->pmcw.flag5 &= ~PMCW5_MM_MBU; dev->esw.scl0 |= !CHADDRCHK(mbaddr, dev) ? SCL0_ESF_MBPTK : SCL0_ESF_MBPGK; /*INCOMPLETE*/ } } /* Generate an initial status I/O interruption if requested */ if ((dev->scsw.flag1 & SCSW1_I) && !dev->syncio_retry) { IODELAY(dev); /* do the delay NOW, before obtaining the INTLOCK */ obtain_lock (&dev->lock); /* Update the CCW address in the SCSW */ STORE_FW(dev->scsw.ccwaddr,ccwaddr); /* Set the zero condition-code flag in the SCSW */ dev->scsw.flag1 |= SCSW1_Z; /* Set intermediate status in the SCSW */ dev->scsw.flag3 = SCSW3_SC_INTER | SCSW3_SC_PEND; /* Queue the interrupt */ QUEUE_IO_INTERRUPT (&dev->ioint); release_lock (&dev->lock); /* Update interrupt status */ OBTAIN_INTLOCK(devregs(dev)); UPDATE_IC_IOPENDING(); RELEASE_INTLOCK(devregs(dev)); if (dev->ccwtrace || dev->ccwstep || tracethis) logmsg (_("HHCCP069I Device %4.4X initial status interrupt\n"), dev->devnum); } #endif /*FEATURE_CHANNEL_SUBSYSTEM*/ /* Execute the CCW chain */ /* On entry : No locks held */ while ( chain ) { /* Test for attention status from device */ if (dev->scsw.flag3 & SCSW3_SC_ALERT) { IODELAY(dev); /* Call the i/o end exit */ if (dev->hnd->end) (dev->hnd->end) (dev); obtain_lock (&dev->lock); /* Turn off busy bit, turn on pending bit */ dev->busy = 0; dev->pending = 1; /* Wake up any waiters if the device isn't reserved */ if (!dev->reserved) { dev->ioactive = DEV_SYS_NONE; if (dev->iowaiters) signal_condition (&dev->iocond); } /* Queue the pending interrupt */ QUEUE_IO_INTERRUPT (&dev->ioint); release_lock (&dev->lock); /* Update interrupt status */ OBTAIN_INTLOCK(devregs(dev)); UPDATE_IC_IOPENDING(); RELEASE_INTLOCK(devregs(dev)); if (dev->ccwtrace || dev->ccwstep || tracethis) logmsg (_("HHCCP070I Device %4.4X attention completed\n"), dev->devnum); return NULL; } /* end attention processing */ /* Test for clear subchannel request */ if (dev->scsw.flag2 & SCSW2_AC_CLEAR) { IODELAY(dev); /* Call the i/o end exit */ if (dev->hnd->end) (dev->hnd->end) (dev); obtain_lock (&dev->lock); /* [15.3.2] Perform clear function subchannel modification */ dev->pmcw.pom = 0xFF; dev->pmcw.lpum = 0x00; dev->pmcw.pnom = 0x00; /* [15.3.3] Perform clear function signaling and completion */ dev->scsw.flag0 = 0; dev->scsw.flag1 = 0; dev->scsw.flag2 &= ~((SCSW2_FC - SCSW2_FC_CLEAR) | SCSW2_AC); dev->scsw.flag3 &= (~(SCSW3_AC | SCSW3_SC))&0xff; dev->scsw.flag3 |= SCSW3_SC_PEND; store_fw (dev->scsw.ccwaddr, 0); dev->scsw.chanstat = 0; dev->scsw.unitstat = 0; store_hw (dev->scsw.count, 0); /* Turn off busy & pcipending bits, turn on pending bit */ dev->busy = dev->pcipending = 0; dev->pending = 1; /* Wake up any waiters if the device isn't reserved */ if (!dev->reserved) { dev->ioactive = DEV_SYS_NONE; if (dev->iowaiters) signal_condition (&dev->iocond); } /* For 3270 device, clear any pending input */ if (dev->devtype == 0x3270) { dev->readpending = 0; dev->rlen3270 = 0; } /* Signal console thread to redrive select */ if (dev->console) { SIGNAL_CONSOLE_THREAD(); } /* Queue the pending interrupt */ obtain_lock(&sysblk.iointqlk); DEQUEUE_IO_INTERRUPT_QLOCKED(&dev->pciioint); QUEUE_IO_INTERRUPT_QLOCKED(&dev->ioint); release_lock(&sysblk.iointqlk); release_lock (&dev->lock); /* Update interrupt status */ OBTAIN_INTLOCK(devregs(dev)); UPDATE_IC_IOPENDING(); RELEASE_INTLOCK(devregs(dev)); if (dev->ccwtrace || dev->ccwstep || tracethis) logmsg (_("HHCCP071I Device %4.4X clear completed\n"), dev->devnum); return NULL; } /* end perform clear subchannel */ /* Test for halt subchannel request */ if (dev->scsw.flag2 & SCSW2_AC_HALT) { IODELAY(dev); /* Call the i/o end exit */ if (dev->hnd->end) (dev->hnd->end) (dev); obtain_lock (&dev->lock); /* [15.4.2] Perform halt function signaling and completion */ dev->scsw.flag2 &= ~SCSW2_AC_HALT; dev->scsw.flag3 |= SCSW3_SC_PEND; dev->scsw.unitstat |= CSW_CE | CSW_DE; /* Turn off busy & pcipending bits, turn on pending bit */ dev->busy = dev->pcipending = 0; dev->pending = 1; /* Wake up any waiters if the device isn't reserved */ if (!dev->reserved) { dev->ioactive = DEV_SYS_NONE; if (dev->iowaiters) signal_condition (&dev->iocond); } /* For 3270 device, clear any pending input */ if (dev->devtype == 0x3270) { dev->readpending = 0; dev->rlen3270 = 0; } /* Signal console thread to redrive select */ if (dev->console) { SIGNAL_CONSOLE_THREAD(); } /* Queue the pending interrupt */ obtain_lock(&sysblk.iointqlk); DEQUEUE_IO_INTERRUPT_QLOCKED(&dev->pciioint); QUEUE_IO_INTERRUPT_QLOCKED(&dev->ioint); release_lock(&sysblk.iointqlk); release_lock (&dev->lock); /* Update interrupt status */ OBTAIN_INTLOCK(devregs(dev)); UPDATE_IC_IOPENDING(); RELEASE_INTLOCK(devregs(dev)); if (dev->ccwtrace || dev->ccwstep || tracethis) logmsg (_("HHCCP072I Device %4.4X halt completed\n"), dev->devnum); return NULL; } /* end perform halt subchannel */ /* Clear the channel status and unit status */ chanstat = 0; unitstat = 0; /* Fetch the next CCW */ ARCH_DEP(fetch_ccw) (dev, ccwkey, ccwfmt, ccwaddr, &opcode, &addr, &flags, &count, &chanstat); /* Point to the CCW in main storage */ ccw = dev->mainstor + ccwaddr; /* Increment to next CCW address */ if ((dev->chained & CCW_FLAGS_CD) == 0) dev->syncio_addr = ccwaddr; ccwaddr += 8; /* Update the CCW address in the SCSW */ STORE_FW(dev->scsw.ccwaddr,ccwaddr); /* Exit if fetch_ccw detected channel program check */ if (chanstat != 0) break; /* Display the CCW */ if (dev->ccwtrace || dev->ccwstep) display_ccw (dev, ccw, addr); /*----------------------------------------------*/ /* TRANSFER IN CHANNEL (TIC) command */ /*----------------------------------------------*/ if (IS_CCW_TIC(opcode)) { /* Channel program check if TIC-to-TIC */ if (tic) { chanstat = CSW_PROGC; break; } /* Channel program check if format-1 TIC reserved bits set*/ if (ccwfmt == 1 && (opcode != 0x08 || flags != 0 || count != 0)) { chanstat = CSW_PROGC; break; } /* Set new CCW address (leaving the values of chained and code untouched to allow data-chaining through TIC) */ tic = 1; ccwaddr = addr; chain = 1; continue; } /* end if TIC */ /*----------------------------------------------*/ /* Commands other than TRANSFER IN CHANNEL */ /*----------------------------------------------*/ /* Reset the TIC-to-TIC flag */ tic = 0; /* Update current CCW opcode, unless data chaining */ if ((dev->chained & CCW_FLAGS_CD) == 0) { dev->prevcode = dev->code; dev->code = opcode; } #if !defined(FEATURE_MIDAW) /*@MW*/ /* Channel program check if MIDAW not installed */ /*@MW*/ if (flags & CCW_FLAGS_MIDAW) /*@MW*/ { chanstat = CSW_PROGC; break; } #endif /*!defined(FEATURE_MIDAW)*/ /*@MW*/ #if defined(FEATURE_MIDAW) /*@MW*/ /* Channel program check if MIDAW not enabled in ORB */ /*@MW*/ if ((flags & CCW_FLAGS_MIDAW) && /*@MW*/ (dev->orb.flag7 & ORB7_D) == 0) /*@MW*/ { /*@MW*/ chanstat = CSW_PROGC; /*@MW*/ break; /*@MW*/ } /*@MW*/ /* Channel program check if MIDAW with SKIP or IDA */ /*@MW*/ if ((flags & CCW_FLAGS_MIDAW) && /*@MW*/ (flags & (CCW_FLAGS_SKIP | CCW_FLAGS_IDA))) /*@MW*/ { /*@MW*/ chanstat = CSW_PROGC; /*@MW*/ break; /*@MW*/ } /*@MW*/ #endif /*defined(FEATURE_MIDAW)*/ /*@MW*/ #ifdef FEATURE_S370_CHANNEL /* For S/370, channel program check if suspend flag is set */ if (flags & CCW_FLAGS_SUSP) { chanstat = CSW_PROGC; break; } #endif /*FEATURE_S370_CHANNEL*/ #ifdef FEATURE_CHANNEL_SUBSYSTEM /* Suspend channel program if suspend flag is set */ if (flags & CCW_FLAGS_SUSP) { /* Channel program check if the ORB suspend control bit was zero, or if this is a data chained CCW */ if ((dev->scsw.flag0 & SCSW0_S) == 0 || (dev->chained & CCW_FLAGS_CD)) { chanstat = CSW_PROGC; break; } /* Retry if synchronous I/O */ if (dev->syncio_active) { dev->syncio_retry = 1; return NULL; } IODELAY(dev); /* Call the i/o suspend exit */ if (dev->hnd->suspend) (dev->hnd->suspend) (dev); obtain_lock (&dev->lock); /* Suspend the device if not already resume pending */ if ((dev->scsw.flag2 & SCSW2_AC_RESUM) == 0) { /* Set the subchannel status word to suspended */ dev->scsw.flag3 = SCSW3_AC_SUSP | SCSW3_SC_INTER | SCSW3_SC_PEND; dev->scsw.unitstat = 0; dev->scsw.chanstat = 0; STORE_HW(dev->scsw.count,count); /* Generate I/O interrupt unless the ORB specified that suspend interrupts are to be suppressed */ if ((dev->scsw.flag1 & SCSW1_U) == 0) { /* Queue the interrupt */ QUEUE_IO_INTERRUPT(&dev->ioint); /* Update interrupt status */ release_lock (&dev->lock); OBTAIN_INTLOCK(devregs(dev)); UPDATE_IC_IOPENDING(); RELEASE_INTLOCK(devregs(dev)); obtain_lock (&dev->lock); } /* Wake up any waiters if the device isn't reserved */ if (!dev->reserved) { dev->ioactive = DEV_SYS_NONE; if (dev->iowaiters) signal_condition (&dev->iocond); } /* Signal console thread to redrive select */ if (dev->console) { SIGNAL_CONSOLE_THREAD(); } /* Turn on the `suspended' bit. This enables remote systems to use the device while we're waiting */ dev->suspended = 1; if (dev->ccwtrace || dev->ccwstep || tracethis) logmsg (_("HHCCP073I Device %4.4X suspended\n"), dev->devnum); // FIXME: Not a very elegant way to fix the suspend/resume problem dev->ccwaddr = ccwaddr; dev->idapmask = idapmask; dev->idawfmt = idawfmt; dev->ccwfmt = ccwfmt; dev->ccwkey = ccwkey; resume_suspend: ccwaddr = dev->ccwaddr; idapmask = dev->idapmask; idawfmt = dev->idawfmt; ccwfmt = dev->ccwfmt; ccwkey = dev->ccwkey; /* Suspend the device until resume instruction */ while (dev->suspended && (dev->scsw.flag2 & SCSW2_AC_RESUM) == 0) { wait_condition (&dev->resumecond, &dev->lock); } /* If the device has been reset then simply return */ if (!dev->suspended) { if (dev->ioactive == sysid) { dev->busy = 0; /* Wake up any waiters if the device isn't reserved */ if (!dev->reserved) { dev->ioactive = DEV_SYS_NONE; if (dev->iowaiters) signal_condition (&dev->iocond); } } release_lock (&dev->lock); return NULL; } /* Turn the `suspended' bit off */ dev->suspended = 0; /* Wait for the device to become available */ while (dev->ioactive != DEV_SYS_NONE && dev->ioactive != sysid) { dev->iowaiters++; wait_condition(&dev->iocond, &dev->lock); dev->iowaiters--; } dev->ioactive = sysid; dev->busy = 1; if (dev->ccwtrace || dev->ccwstep || tracethis) logmsg (_("HHCCP074I Device %4.4X resumed\n"), dev->devnum); /* Reset the suspended status in the SCSW */ dev->scsw.flag3 &= ~SCSW3_AC_SUSP; dev->scsw.flag3 |= (SCSW3_AC_SCHAC | SCSW3_AC_DEVAC); } /* Reset the resume pending flag */ dev->scsw.flag2 &= ~SCSW2_AC_RESUM; release_lock (&dev->lock); /* Call the i/o resume exit */ if (dev->hnd->resume) (dev->hnd->resume) (dev); /* Reset fields as if starting a new channel program */ dev->code = 0; tic = 0; chain = 1; dev->chained = 0; dev->prev_chained = 0; dev->prevcode = 0; dev->ccwseq = 0; bufpos = 0; dev->syncio_retry = 0; /* Go back and refetch the suspended CCW */ ccwaddr -= 8; continue; } /* end if(CCW_FLAGS_SUSP) */ #endif /*FEATURE_CHANNEL_SUBSYSTEM*/ /* Signal I/O interrupt if PCI flag is set */ if ((flags & CCW_FLAGS_PCI) && !dev->syncio_retry) { ARCH_DEP(raise_pci) (dev, ccwkey, ccwfmt, ccwaddr); /*@MW*/ } /* Channel program check if invalid count */ if (count == 0 && (ccwfmt == 0 || (flags & CCW_FLAGS_CD) || (dev->chained & CCW_FLAGS_CD))) { chanstat = CSW_PROGC; break; } /* Allow the device handler to determine whether this is an immediate CCW (i.e. CONTROL with no data transfer) */ dev->is_immed = IS_CCW_IMMEDIATE(dev); /* If synchronous I/O and a syncio 2 device and not an immediate CCW then retry asynchronously */ if (dev->syncio_active && dev->syncio == 2 && !dev->is_immed && !IS_CCW_SENSE(dev->code)) { dev->syncio_retry = 1; return NULL; } /* For WRITE and non-immediate CONTROL operations, copy data from main storage into channel buffer */ if ( IS_CCW_WRITE(dev->code) || ( IS_CCW_CONTROL(dev->code) && (!dev->is_immed))) { /* Channel program check if data exceeds buffer size */ if (bufpos + count > 65536) { chanstat = CSW_PROGC; break; } /* Copy data into channel buffer */ ARCH_DEP(copy_iobuf) (dev, dev->code, flags, addr, count, ccwkey, idawfmt, idapmask, /*@IWZ*/ iobuf + bufpos, &chanstat); if (chanstat != 0) break; /* Update number of bytes in channel buffer */ bufpos += count; /* If device handler has requested merging of data chained write CCWs, then collect data from all CCWs in chain before passing buffer to device handler */ if (dev->cdwmerge) { if (flags & CCW_FLAGS_CD) { /* If this is the first CCW in the data chain, then save the chaining flags from the previous CCW */ if ((dev->chained & CCW_FLAGS_CD) == 0) dev->prev_chained = dev->chained; /* Process next CCW in data chain */ dev->chained = CCW_FLAGS_CD; chain = 1; continue; } /* If this is the last CCW in the data chain, then restore the chaining flags from the previous CCW */ if (dev->chained & CCW_FLAGS_CD) dev->chained = dev->prev_chained; } /* end if(dev->cdwmerge) */ /* Reset the total count at end of data chain */ count = bufpos; bufpos = 0; } /* Set chaining flag */ chain = ( flags & (CCW_FLAGS_CD | CCW_FLAGS_CC) ) ? 1 : 0; /* Initialize residual byte count */ residual = count; more = 0; /* Channel program check if invalid CCW opcode */ if (!(IS_CCW_WRITE(dev->code) || IS_CCW_READ(dev->code) || IS_CCW_CONTROL(dev->code) || IS_CCW_SENSE(dev->code) || IS_CCW_RDBACK(dev->code))) { chanstat = CSW_PROGC; break; } /* Pass the CCW to the device handler for execution */ (dev->hnd->exec) (dev, dev->code, flags, dev->chained, count, dev->prevcode, dev->ccwseq, iobuf, &more, &unitstat, &residual); /* Check if synchronous I/O needs to be retried */ if (dev->syncio_active && dev->syncio_retry) return NULL; /* * NOTE: syncio_retry is left on for an asynchronous I/O until * after the first call to the execute ccw device handler. * This allows the device handler to realize that the I/O is * being retried asynchronously. */ dev->syncio_retry = 0; /* Check for Command Retry (suggested by Jim Pierson) */ if ( unitstat == ( CSW_CE | CSW_DE | CSW_UC | CSW_SM ) ) { chain = 1; ccwaddr -= 8; /* (retry same ccw again) */ continue; } /* For READ, SENSE, and READ BACKWARD operations, copy data from channel buffer to main storage, unless SKIP is set */ if ((flags & CCW_FLAGS_SKIP) == 0 && (IS_CCW_READ(dev->code) || IS_CCW_SENSE(dev->code) || IS_CCW_RDBACK(dev->code))) { ARCH_DEP(copy_iobuf) (dev, dev->code, flags, addr, count - residual, ccwkey, idawfmt, idapmask, /*@IWZ*/ iobuf, &chanstat); } /* Check for incorrect length */ if (residual != 0 || (more && ((flags & CCW_FLAGS_CD) == 0))) { /* Set incorrect length status if data chaining or or if suppress length indication flag is off for non-NOP CCWs */ if (((flags & CCW_FLAGS_CD) || (flags & CCW_FLAGS_SLI) == 0) && (!dev->is_immed) #if defined(FEATURE_INCORRECT_LENGTH_INDICATION_SUPPRESSION) /* Suppress incorrect length indication if CCW format is one and SLI mode is indicated in the ORB */ && !((dev->orb.flag5 & ORB5_F) && (dev->orb.flag5 & ORB5_U)) #endif /*defined(FEATURE_INCORRECT_LENGTH_INDICATION_SUPPRESSION)*/ ) chanstat |= CSW_IL; } /* Force tracing for this CCW if any unusual status occurred */ if ((chanstat & (CSW_PROGC | CSW_PROTC | CSW_CDC | CSW_CCC | CSW_ICC | CSW_CHC)) || ((unitstat & CSW_UC) && dev->sense[0] != 0)) { /* Trace the CCW if not already done */ if (!(dev->ccwtrace || dev->ccwstep || tracethis) && (CPU_STEPPING_OR_TRACING_ALL || sysblk.pgminttr || dev->ccwtrace || dev->ccwstep) ) display_ccw (dev, ccw, addr); /* Activate tracing for this CCW chain only if any trace is already active */ if(CPU_STEPPING_OR_TRACING_ALL || sysblk.pgminttr || dev->ccwtrace || dev->ccwstep) tracethis = 1; } /* Trace the results of CCW execution */ if (dev->ccwtrace || dev->ccwstep || tracethis) { /* Format data for READ or SENSE commands only */ if (IS_CCW_READ(dev->code) || IS_CCW_SENSE(dev->code) || IS_CCW_RDBACK(dev->code)) format_iobuf_data (addr, area, dev); else area[0] = '\0'; /* Display status and residual byte count */ logmsg (_("HHCCP075I %4.4X:Stat=%2.2X%2.2X Count=%4.4X %s\n"), dev->devnum, unitstat, chanstat, residual, area); /* Display sense bytes if unit check is indicated */ if (unitstat & CSW_UC) { logmsg (_("HHCCP076I %4.4X:Sense=%2.2X%2.2X%2.2X%2.2X " "%2.2X%2.2X%2.2X%2.2X %2.2X%2.2X%2.2X%2.2X " "%2.2X%2.2X%2.2X%2.2X %2.2X%2.2X%2.2X%2.2X " "%2.2X%2.2X%2.2X%2.2X\n"), dev->devnum, dev->sense[0], dev->sense[1], dev->sense[2], dev->sense[3], dev->sense[4], dev->sense[5], dev->sense[6], dev->sense[7], dev->sense[8], dev->sense[9], dev->sense[10], dev->sense[11], dev->sense[12], dev->sense[13], dev->sense[14], dev->sense[15], dev->sense[16], dev->sense[17], dev->sense[18], dev->sense[19], dev->sense[20], dev->sense[21], dev->sense[22], dev->sense[23]); if (dev->sense[0] != 0 || dev->sense[1] != 0) { logmsg (_("HHCCP077I %4.4X:Sense=%s%s%s%s%s%s%s%s" "%s%s%s%s%s%s%s%s\n"), dev->devnum, (dev->sense[0] & SENSE_CR) ? "CMDREJ " : "", (dev->sense[0] & SENSE_IR) ? "INTREQ " : "", (dev->sense[0] & SENSE_BOC) ? "BOC " : "", (dev->sense[0] & SENSE_EC) ? "EQC " : "", (dev->sense[0] & SENSE_DC) ? "DCK " : "", (dev->sense[0] & SENSE_OR) ? "OVR " : "", (dev->sense[0] & SENSE_CC) ? "CCK " : "", (dev->sense[0] & SENSE_OC) ? "OCK " : "", (dev->sense[1] & SENSE1_PER) ? "PER " : "", (dev->sense[1] & SENSE1_ITF) ? "ITF " : "", (dev->sense[1] & SENSE1_EOC) ? "EOC " : "", (dev->sense[1] & SENSE1_MTO) ? "MSG " : "", (dev->sense[1] & SENSE1_NRF) ? "NRF " : "", (dev->sense[1] & SENSE1_FP) ? "FP " : "", (dev->sense[1] & SENSE1_WRI) ? "WRI " : "", (dev->sense[1] & SENSE1_IE) ? "IE " : ""); } } } /* Increment CCW address if device returned status modifier */ if (unitstat & CSW_SM) ccwaddr += 8; /* Terminate the channel program if any unusual status */ if (chanstat != 0 || (unitstat & ~CSW_SM) != (CSW_CE | CSW_DE)) chain = 0; /* Update the chaining flags */ dev->chained = flags & (CCW_FLAGS_CD | CCW_FLAGS_CC); /* Update the CCW sequence number unless data chained */ if ((flags & CCW_FLAGS_CD) == 0) dev->ccwseq++; } /* end while(chain) */ IODELAY(dev); /* Call the i/o end exit */ if (dev->hnd->end) (dev->hnd->end) (dev); obtain_lock (&dev->lock); #ifdef FEATURE_S370_CHANNEL /* Build the channel status word */ dev->csw[0] = ccwkey & 0xF0; dev->csw[1] = (ccwaddr & 0xFF0000) >> 16; dev->csw[2] = (ccwaddr & 0xFF00) >> 8; dev->csw[3] = ccwaddr & 0xFF; dev->csw[4] = unitstat; dev->csw[5] = chanstat; dev->csw[6] = (residual & 0xFF00) >> 8; dev->csw[7] = residual & 0xFF; #endif /*FEATURE_S370_CHANNEL*/ #ifdef FEATURE_CHANNEL_SUBSYSTEM /* Complete the subchannel status word */ dev->scsw.flag3 &= ~(SCSW3_AC_SCHAC | SCSW3_AC_DEVAC); dev->scsw.flag3 |= (SCSW3_SC_PRI | SCSW3_SC_SEC | SCSW3_SC_PEND); STORE_FW(dev->scsw.ccwaddr,ccwaddr); dev->scsw.unitstat = unitstat; dev->scsw.chanstat = chanstat; STORE_HW(dev->scsw.count,residual); /* Set alert status if terminated by any unusual condition */ if (chanstat != 0 || unitstat != (CSW_CE | CSW_DE)) dev->scsw.flag3 |= SCSW3_SC_ALERT; /* Build the format-1 extended status word */ memset (&dev->esw, 0, sizeof(ESW)); dev->esw.lpum = 0x80; /* Clear the extended control word */ memset (dev->ecw, 0, sizeof(dev->ecw)); /* Return sense information if PMCW allows concurrent sense */ if ((unitstat & CSW_UC) && (dev->pmcw.flag27 & PMCW27_S)) { dev->scsw.flag1 |= SCSW1_E; dev->esw.erw0 |= ERW0_S; dev->esw.erw1 = (dev->numsense < (int)sizeof(dev->ecw)) ? dev->numsense : sizeof(dev->ecw); memcpy (dev->ecw, dev->sense, dev->esw.erw1 & ERW1_SCNT); memset (dev->sense, 0, sizeof(dev->sense)); dev->sns_pending = 0; } #endif /*FEATURE_CHANNEL_SUBSYSTEM*/ /* Wake up any waiters if the device isn't reserved */ if (!dev->reserved) { dev->ioactive = DEV_SYS_NONE; if (dev->iowaiters) signal_condition (&dev->iocond); } /* Signal console thread to redrive select */ if (dev->console) { SIGNAL_CONSOLE_THREAD(); } dev->busy = 0; /* Queue the interrupt */ QUEUE_IO_INTERRUPT (&dev->ioint); release_lock (&dev->lock); /* Present the interrupt */ OBTAIN_INTLOCK(devregs(dev)); if (dev->regs) dev->regs->hostregs->syncio = 0; UPDATE_IC_IOPENDING(); RELEASE_INTLOCK(devregs(dev)); return NULL; } /* end function execute_ccw_chain */ /*-------------------------------------------------------------------*/ /* TEST WHETHER INTERRUPTS ARE ENABLED FOR THE SPECIFIED DEVICE */ /* When configured for S/370 channels, the PSW system mask and/or */ /* the channel masks in control register 2 determine whether the */ /* device is enabled. When configured for the XA or ESA channel */ /* subsystem, the interrupt subclass masks in control register 6 */ /* determine eligability; the PSW system mask is not tested, because */ /* the TPI instruction can operate with I/O interrupts masked off. */ /* Returns non-zero if interrupts enabled, 0 if interrupts disabled. */ /*-------------------------------------------------------------------*/ /* I/O Assist: */ /* This routine must return: */ /* */ /* 0 - In the case of no pending interrupt */ /* SIE_NO_INTERCEPT - For a non-intercepted I/O interrupt */ /* SIE_INTERCEPT_IOINT - For an intercepted I/O interrupt */ /* SIE_INTERCEPT_IOINTP- For a pending I/O interception */ /* */ /* SIE_INTERCEPT_IOINT may only be returned to a guest */ /*-------------------------------------------------------------------*/ static inline int ARCH_DEP(interrupt_enabled) (REGS *regs, DEVBLK *dev) { int i; /* Interruption subclass */ /* Ignore this device if subchannel not valid */ if (!(dev->pmcw.flag5 & PMCW5_V)) return 0; #if defined(_FEATURE_IO_ASSIST) /* For I/O Assist the zone must match the guest zone */ if(SIE_MODE(regs) && regs->siebk->zone != dev->pmcw.zone) return 0; #endif #if defined(_FEATURE_IO_ASSIST) /* The interrupt interlock control bit must be on if not we must intercept */ if(SIE_MODE(regs) && !(dev->pmcw.flag27 & PMCW27_I)) return SIE_INTERCEPT_IOINT; #endif #ifdef FEATURE_S370_CHANNEL #if defined(FEATURE_CHANNEL_SWITCHING) /* Is this device on a channel connected to this CPU? */ if( #if defined(_FEATURE_IO_ASSIST) !SIE_MODE(regs) && #endif regs->chanset != dev->chanset) return 0; #endif /*defined(FEATURE_CHANNEL_SWITCHING)*/ /* Isolate the channel number */ i = dev->devnum >> 8; if (!ECMODE(®s->psw) && i < 6) { #if defined(_FEATURE_IO_ASSIST) /* We must always intercept in BC mode */ if(SIE_MODE(regs)) return SIE_INTERCEPT_IOINT; #endif /* For BC mode channels 0-5, test system mask bits 0-5 */ if ((regs->psw.sysmask & (0x80 >> i)) == 0) return 0; } else { /* For EC mode and channels 6-31, test system mask bit 6 */ if ((regs->psw.sysmask & PSW_IOMASK) == 0) return 0; /* If I/O mask is enabled, test channel masks in CR2 */ if (i > 31) i = 31; if ((regs->CR(2) & (0x80000000 >> i)) == 0) return #if defined(_FEATURE_IO_ASSIST) SIE_MODE(regs) ? SIE_INTERCEPT_IOINTP : #endif 0; } #endif /*FEATURE_S370_CHANNEL*/ #ifdef FEATURE_CHANNEL_SUBSYSTEM /* Ignore this device if subchannel not enabled */ if (!(dev->pmcw.flag5 & PMCW5_E)) return 0; /* Isolate the interruption subclass */ i = #if defined(_FEATURE_IO_ASSIST) /* For I/O Assisted devices use the guest (V)ISC */ SIE_MODE(regs) ? (dev->pmcw.flag25 & PMCW25_VISC) : #endif ((dev->pmcw.flag4 & PMCW4_ISC) >> 3); /* Test interruption subclass mask bit in CR6 */ if ((regs->CR_L(6) & (0x80000000 >> i)) == 0) return #if defined(_FEATURE_IO_ASSIST) SIE_MODE(regs) ? SIE_INTERCEPT_IOINTP : #endif 0; #endif /*FEATURE_CHANNEL_SUBSYSTEM*/ /* Interrupts are enabled for this device */ return SIE_NO_INTERCEPT; } /* end function interrupt_enabled */ /*-------------------------------------------------------------------*/ /* PRESENT PENDING I/O INTERRUPT */ /* Finds a device with a pending condition for which an interrupt */ /* is allowed by the CPU whose regs structure is passed as a */ /* parameter. Clears the interrupt condition and returns the */ /* I/O address and I/O interruption parameter (for channel subsystem)*/ /* or the I/O address and CSW (for S/370 channels). */ /* This routine does not perform a PSW switch. */ /* The CSW pointer is NULL in the case of TPI. */ /* The return value is the condition code for the TPI instruction: */ /* 0 if no allowable pending interrupt exists, otherwise 1. */ /* Note: The caller MUST hold the interrupt lock (sysblk.intlock). */ /*-------------------------------------------------------------------*/ /* I/O Assist: */ /* This routine must return: */ /* */ /* 0 - In the case of no pending interrupt */ /* SIE_NO_INTERCEPT - For a non-intercepted I/O interrupt */ /* SIE_INTERCEPT_IOINT - For an I/O interrupt which must intercept */ /* SIE_INTERCEPT_IOINTP- For a pending I/O interception */ /* */ /* SIE_INTERCEPT_IOINT may only be returned to a guest */ /*-------------------------------------------------------------------*/ int ARCH_DEP(present_io_interrupt) (REGS *regs, U32 *ioid, U32 *ioparm, U32 *iointid, BYTE *csw) { IOINT *io, *io2; /* -> I/O interrupt entry */ DEVBLK *dev; /* -> Device control block */ int icode = 0; /* Intercept code */ #if defined(FEATURE_S370_CHANNEL) BYTE *pendcsw; /* Pending CSW */ #endif UNREFERENCED_370(ioparm); UNREFERENCED_370(iointid); #if defined(_FEATURE_IO_ASSIST) UNREFERENCED_390(iointid); #endif UNREFERENCED_390(csw); UNREFERENCED_900(csw); /* Find a device with pending interrupt */ /* (N.B. devlock cannot be acquired while iointqlk held; iointqlk must be acquired after devlock) */ retry: dev = NULL; obtain_lock(&sysblk.iointqlk); for (io = sysblk.iointq; io != NULL; io = io->next) { /* Exit loop if enabled for interrupts from this device */ if ((icode = ARCH_DEP(interrupt_enabled)(regs, io->dev)) #if defined(_FEATURE_IO_ASSIST) && icode != SIE_INTERCEPT_IOINTP #endif ) { dev = io->dev; break; } /* See if another CPU can take this interrupt */ WAKEUP_CPU_MASK (sysblk.waiting_mask); } /* end for(io) */ #if defined(_FEATURE_IO_ASSIST) /* In the case of I/O assist, do a rescan, to see if there are any devices with pending subclasses for which we are not enabled, if so cause a interception */ if (io == NULL && SIE_MODE(regs)) { /* Find a device with a pending interrupt, regardless of the interrupt subclass mask */ ASSERT(dev == NULL); for (io = sysblk.iointq; io != NULL; io = io->next) { /* Exit loop if pending interrupts from this device */ if ((icode = ARCH_DEP(interrupt_enabled)(regs, io->dev))) { dev = io->dev; break; } } /* end for(io) */ } #endif release_lock(&sysblk.iointqlk); /* If no interrupt pending, exit with condition code 0 */ if (io == NULL) { ASSERT(dev == NULL); UPDATE_IC_IOPENDING(); return 0; } /* Obtain device lock for device with interrupt */ ASSERT(dev != NULL); obtain_lock (&dev->lock); /* Verify interrupt for this device still exists */ obtain_lock(&sysblk.iointqlk); for (io2 = sysblk.iointq; io2 != NULL && io2 != io; io2 = io2->next); if (io2 == NULL) { /* Our interrupt was dequeued; retry */ release_lock(&sysblk.iointqlk); release_lock (&dev->lock); goto retry; } #ifdef FEATURE_S370_CHANNEL /* Extract the I/O address and CSW */ *ioid = dev->devnum; if(io->pcipending) { pendcsw=dev->pcicsw; memcpy (csw, pendcsw , 8); } if(io->pending) { pendcsw=dev->csw; memcpy (csw, pendcsw , 8); } if(io->attnpending) { pendcsw=dev->attncsw; memcpy (csw, pendcsw , 8); } /* Display the channel status word */ if (dev->ccwtrace || dev->ccwstep) display_csw (dev, csw); #endif /*FEATURE_S370_CHANNEL*/ #ifdef FEATURE_CHANNEL_SUBSYSTEM /* Extract the I/O address and interrupt parameter */ *ioid = (dev->ssid << 16) | dev->subchan; FETCH_FW(*ioparm,dev->pmcw.intparm); #if defined(FEATURE_ESAME) || defined(_FEATURE_IO_ASSIST) *iointid = #if defined(_FEATURE_IO_ASSIST) /* For I/O Assisted devices use (V)ISC */ (SIE_MODE(regs)) ? (icode == SIE_NO_INTERCEPT) ? ((dev->pmcw.flag25 & PMCW25_VISC) << 27) : ((dev->pmcw.flag25 & PMCW25_VISC) << 27) | (dev->pmcw.zone << 16) | ((dev->pmcw.flag27 & PMCW27_I) << 8) : #endif ((dev->pmcw.flag4 & PMCW4_ISC) << 24) #if defined(_FEATURE_IO_ASSIST) | (dev->pmcw.zone << 16) | ((dev->pmcw.flag27 & PMCW27_I) << 8) #endif ; #endif /*defined(FEATURE_ESAME) || defined(_FEATURE_IO_ASSIST)*/ #endif /*FEATURE_CHANNEL_SUBSYSTEM*/ #if defined(_FEATURE_IO_ASSIST) /* Do not drain pending interrupts on intercept due to zero ISC mask */ if(!SIE_MODE(regs) || icode != SIE_INTERCEPT_IOINTP) #endif { if(!SIE_MODE(regs) || icode != SIE_NO_INTERCEPT) dev->pmcw.flag27 &= ~PMCW27_I; /* Dequeue the interrupt */ DEQUEUE_IO_INTERRUPT_QLOCKED(io); UPDATE_IC_IOPENDING_QLOCKED(); /* Signal console thread to redrive select */ if (dev->console) SIGNAL_CONSOLE_THREAD(); } release_lock(&sysblk.iointqlk); release_lock (&dev->lock); /* Exit with condition code indicating interrupt cleared */ return icode; } /* end function present_io_interrupt */ #if defined(_FEATURE_IO_ASSIST) int ARCH_DEP(present_zone_io_interrupt) (U32 *ioid, U32 *ioparm, U32 *iointid, BYTE zone) { IOINT *io; /* -> I/O interrupt entry */ DEVBLK *dev; /* -> Device control block */ typedef struct _DEVLIST { /* list of device block ptrs */ struct _DEVLIST *next; /* next list entry or NULL */ DEVBLK *dev; /* DEVBLK in requested zone */ U16 ssid; /* Subsystem ID incl. lcssid */ U16 subchan; /* Subchannel number */ FWORD intparm; /* Interruption parameter */ int visc; /* Guest Interrupt Subclass */ } DEVLIST; DEVLIST *pDEVLIST, *pPrevDEVLIST = NULL;/* (work) */ DEVLIST *pZoneDevs = NULL; /* devices in requested zone */ /* Gather devices within our zone with pending interrupt flagged */ for (dev = sysblk.firstdev; dev; dev = dev->nextdev) { obtain_lock (&dev->lock); if (1 /* Pending interrupt flagged */ && (dev->pending || dev->pcipending) /* Subchannel valid and enabled */ && ((dev->pmcw.flag5 & (PMCW5_E | PMCW5_V)) == (PMCW5_E | PMCW5_V)) /* Within requested zone */ && (dev->pmcw.zone == zone) ) { /* (save this device for further scrutiny) */ pDEVLIST = malloc( sizeof(DEVLIST) ); pDEVLIST->next = NULL; pDEVLIST->dev = dev; pDEVLIST->ssid = dev->ssid; pDEVLIST->subchan = dev->subchan; // pDEVLIST->intparm = dev->pmcw.intparm; memcpy( pDEVLIST->intparm, dev->pmcw.intparm, sizeof(pDEVLIST->intparm) ); pDEVLIST->visc = (dev->pmcw.flag25 & PMCW25_VISC); if (!pZoneDevs) pZoneDevs = pDEVLIST; if (pPrevDEVLIST) pPrevDEVLIST->next = pDEVLIST; pPrevDEVLIST = pDEVLIST; } release_lock (&dev->lock); } /* Exit with condition code 0 if no devices within our zone with a pending interrupt */ if (!pZoneDevs) return 0; /* Remove from our list those devices without a pending interrupt queued */ obtain_lock(&sysblk.iointqlk); for (pDEVLIST = pZoneDevs, pPrevDEVLIST = NULL; pDEVLIST;) { /* Search interrupt queue for this device */ for (io = sysblk.iointq; io != NULL && io->dev != pDEVLIST->dev; io = io->next); /* Is interrupt queued for this device? */ if (io == NULL) { /* No, remove it from our list */ if (!pPrevDEVLIST) { ASSERT(pDEVLIST == pZoneDevs); pZoneDevs = pDEVLIST->next; free(pDEVLIST); pDEVLIST = pZoneDevs; } else { pPrevDEVLIST->next = pDEVLIST->next; free(pDEVLIST); pDEVLIST = pPrevDEVLIST->next; } } else { /* Yes, go on to next list entry */ pPrevDEVLIST = pDEVLIST; pDEVLIST = pDEVLIST->next; } } release_lock(&sysblk.iointqlk); /* If no devices remain, exit with condition code 0 */ if (!pZoneDevs) return 0; /* Extract the I/O address and interrupt parameter for the first pending subchannel */ dev = pZoneDevs->dev; *ioid = (pZoneDevs->ssid << 16) | pZoneDevs->subchan; FETCH_FW(*ioparm,pZoneDevs->intparm); *iointid = (0x80000000 >> pZoneDevs->visc) | (zone << 16); pDEVLIST = pZoneDevs->next; free (pZoneDevs); /* Find all other pending subclasses */ while (pDEVLIST) { *iointid |= (0x80000000 >> pDEVLIST->visc); pPrevDEVLIST = pDEVLIST; pDEVLIST = pDEVLIST->next; free (pPrevDEVLIST); } /* Exit with condition code indicating interrupt pending */ return 1; } /* end function present_zone_io_interrupt */ #endif #if !defined(_GEN_ARCH) #if defined(_ARCHMODE2) #define _GEN_ARCH _ARCHMODE2 #include "channel.c" #endif #if defined(_ARCHMODE3) #undef _GEN_ARCH #define _GEN_ARCH _ARCHMODE3 #include "channel.c" #endif int device_attention (DEVBLK *dev, BYTE unitstat) { switch(sysblk.arch_mode) { #if defined(_370) case ARCH_370: /* Do NOT raise if initial power-on state */ /* * FIXME : The dev->crwpending test in S/370 * mode prevents any devices added * at run time after IPL from being * operational. The test has been * temporarily disabled until it is * either confirmed as being superfluous * or another solution is found. * ISW 20070109 */ /* if (dev->crwpending) return 3; */ return s370_device_attention(dev, unitstat); #endif #if defined(_390) case ARCH_390: return s390_device_attention(dev, unitstat); #endif #if defined(_900) case ARCH_900: return z900_device_attention(dev, unitstat); #endif } return 3; } void call_execute_ccw_chain(int arch_mode, void* pDevBlk) { switch (arch_mode) { #if defined(_370) case ARCH_370: s370_execute_ccw_chain((DEVBLK*)pDevBlk); break; #endif #if defined(_390) case ARCH_390: s390_execute_ccw_chain((DEVBLK*)pDevBlk); break; #endif #if defined(_900) case ARCH_900: z900_execute_ccw_chain((DEVBLK*)pDevBlk); break; #endif } } #endif /*!defined(_GEN_ARCH)*/ hercules-3.07/chsc.c000644 000765 000765 00000017127 11157241226 016040 0ustar00jmaynardjmaynard000000 000000 /* CHSC.C (c) Copyright Jan Jaeger, 2002-2009 */ /* Channel Subsystem Call */ /* Interpretive Execution - (c) Copyright Jan Jaeger, 1999-2009 */ /* z/Architecture support - (c) Copyright Jan Jaeger, 1999-2009 */ // $Id: chsc.c 5242 2009-03-05 21:33:26Z jj $ /*-------------------------------------------------------------------*/ /* This module implements channel subsystem interface functions */ /* for the Hercules ESA/390 emulator. */ /*-------------------------------------------------------------------*/ // $Log$ // Revision 1.12 2007/06/23 00:04:04 ivan // Update copyright notices to include current year (2007) // // Revision 1.11 2007/01/13 07:10:54 bernard // backout ccmask // // Revision 1.10 2007/01/12 15:20:59 bernard // ccmask phase 1 // // Revision 1.9 2006/12/08 09:43:18 jj // Add CVS message log // #include "hstdinc.h" #if !defined(_HENGINE_DLL_) #define _HENGINE_DLL_ #endif #if !defined(_CHSC_C_) #define _CHSC_C_ #endif #include "hercules.h" #include "opcode.h" #include "inline.h" #include "chsc.h" #if defined(FEATURE_CHSC) int ARCH_DEP(chsc_get_sch_desc) (CHSC_REQ *chsc_req, CHSC_RSP *chsc_rsp) { U16 req_len, sch, f_sch, l_sch, rsp_len; CHSC_REQ4 *chsc_req4 = (CHSC_REQ4 *)(chsc_req); CHSC_RSP4 *chsc_rsp4 = (CHSC_RSP4 *)(chsc_rsp); #if 0 { U16 resv1, resv2, resv3; FETCH_HW(resv1,chsc_req4->resv1); FETCH_HW(resv2,chsc_req4->resv2); FETCH_HW(resv3,chsc_req4->resv3); logmsg(D_("chsc_get_sch_desc: resv1=%4.4X resv2=%4.4X resv3=%4.4X\n"),resv1,resv2,resv3); } #endif FETCH_HW(f_sch,chsc_req4->f_sch); FETCH_HW(l_sch,chsc_req4->l_sch); /* Fetch length of request field */ FETCH_HW(req_len, chsc_req4->length); rsp_len = sizeof(CHSC_RSP) + ((1 + l_sch - f_sch) * sizeof(CHSC_RSP4)); if(l_sch < f_sch || rsp_len > (0x1000 - req_len)) { /* Set response field length */ STORE_HW(chsc_rsp->length,sizeof(CHSC_RSP)); /* Store request error */ STORE_HW(chsc_rsp->rsp,CHSC_REQ_ERRREQ); /* No reaon code */ STORE_FW(chsc_rsp->info,0); return 0; } for(sch = f_sch; sch <= l_sch; sch++, chsc_rsp4++) { DEVBLK *dev; memset(chsc_rsp4, 0x00, sizeof(CHSC_RSP4) ); // ZZ FIXME: Dunno how to put the proper lcss id in here... if((dev = find_device_by_subchan(0x00010000|sch))) { chsc_rsp4->sch_val = 1; if(dev->pmcw.flag5 & PMCW5_V) chsc_rsp4->dev_val = 1; chsc_rsp4->st = (dev->pmcw.flag25 & PMCW25_TYPE) >> 5; chsc_rsp4->unit_addr = dev->devnum & 0xff; STORE_HW(chsc_rsp4->devno,dev->devnum); chsc_rsp4->path_mask = dev->pmcw.pim; STORE_HW(chsc_rsp4->sch, sch); memcpy(chsc_rsp4->chpid, dev->pmcw.chpid, 8); } } /* Store response length */ STORE_HW(chsc_rsp->length,rsp_len); /* Store request OK */ STORE_HW(chsc_rsp->rsp,CHSC_REQ_OK); /* No reaon code */ STORE_FW(chsc_rsp->info,0); return 0; } int ARCH_DEP(chsc_get_css_info) (CHSC_REQ *chsc_req, CHSC_RSP *chsc_rsp) { CHSC_RSP10 *chsc_rsp10; U16 req_len, rsp_len; UNREFERENCED(chsc_req); chsc_rsp10 = (CHSC_RSP10 *)(chsc_rsp + 1); /* Fetch length of request field */ FETCH_HW(req_len, chsc_req->length); rsp_len = sizeof(CHSC_RSP) + sizeof(CHSC_RSP10); if(rsp_len > (0x1000 - req_len)) { /* Set response field length */ STORE_HW(chsc_rsp->length,sizeof(CHSC_RSP)); /* Store request error */ STORE_HW(chsc_rsp->rsp,CHSC_REQ_ERRREQ); /* No reaon code */ STORE_FW(chsc_rsp->info,0); return 0; } STORE_HW(chsc_rsp->length,rsp_len); memset(chsc_rsp10->general_char, 0x00, sizeof(chsc_rsp10->general_char)); memset(chsc_rsp10->chsc_char, 0x00, sizeof(chsc_rsp10->chsc_char)); chsc_rsp10->general_char[0][0] = 0 #if defined(FEATURE_REGION_RELOCATE) | 0x24 #endif #if defined(FEATURE_CANCEL_IO_FACILITY) | 0x02 #endif ; #if defined(FEATURE_QUEUED_DIRECT_IO) chsc_rsp10->general_char[1][1] = 0 | 0x40 /* Adapter Interruption Facility */ ; chsc_rsp10->chsc_char[3][1] = 0 | 0x10 /* Set Channel Subsystem Char */ | 0x08 /* Fast CHSCs */ ; chsc_rsp10->general_char[2][0] = 0 // | 0x10 /* OSA/FCP Thin interrupts */ ; chsc_rsp10->general_char[1][3] = 0 // | 0x80 /* AIF Time Delay Disablement Fac */ ; #endif /*defined(FEATURE_QUEUED_DIRECT_IO)*/ /* Store request OK */ STORE_HW(chsc_rsp->rsp,CHSC_REQ_OK); /* No reaon code */ STORE_FW(chsc_rsp->info,0); return 0; } /*-------------------------------------------------------------------*/ /* B25F CHSC - Channel Subsystem Call [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(channel_subsystem_call) { int r1, r2; /* register values */ VADR n; /* Unsigned work */ BYTE *mn; /* Unsigned work */ U16 req_len; /* Length of request */ U16 req; /* Request code */ CHSC_REQ *chsc_req; /* Request structure */ CHSC_RSP *chsc_rsp; /* Response structure*/ RRE(inst, regs, r1, r2); PRIV_CHECK(regs); SIE_INTERCEPT(regs); PTT(PTT_CL_INF,"CHSC",regs->GR_L(r1),regs->GR_L(r2),regs->psw.IA_L); n = regs->GR(r1) & ADDRESS_MAXWRAP(regs); if(n & 0xFFF) ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION); mn = MADDR(n, r1, regs, ACCTYPE_READ, regs->psw.pkey); chsc_req = (CHSC_REQ*)(mn); /* Fetch length of request field */ FETCH_HW(req_len, chsc_req->length); chsc_rsp = (CHSC_RSP*)((BYTE*)chsc_req + req_len); if((req_len < sizeof(CHSC_REQ)) || (req_len > (0x1000 - sizeof(CHSC_RSP)))) ARCH_DEP(program_interrupt) (regs, PGM_OPERAND_EXCEPTION); FETCH_HW(req,chsc_req->req); ARCH_DEP(validate_operand) (n, r1, 0, ACCTYPE_WRITE, regs); switch(req) { case CHSC_REQ_SCHDESC: regs->psw.cc = ARCH_DEP(chsc_get_sch_desc) (chsc_req, chsc_rsp); break; #if 0 case CHSC_REQ_CSSINFO: regs->psw.cc = ARCH_DEP(chsc_get_css_info) (chsc_req, chsc_rsp); break; #endif default: PTT(PTT_CL_ERR,"*CHSC",regs->GR_L(r1),regs->GR_L(r2),regs->psw.IA_L); if( HDC3(debug_chsc_unknown_request, chsc_rsp, chsc_req, regs) ) break; /* Set response field length */ STORE_HW(chsc_rsp->length,sizeof(CHSC_RSP)); /* Store unsupported command code */ STORE_HW(chsc_rsp->rsp,CHSC_REQ_INVALID); /* No reaon code */ STORE_FW(chsc_rsp->info,0); regs->psw.cc = 0; } } #endif /*defined(FEATURE_CHSC)*/ #if !defined(_GEN_ARCH) #if defined(_ARCHMODE2) #define _GEN_ARCH _ARCHMODE2 #include "chsc.c" #endif #if defined(_ARCHMODE3) #undef _GEN_ARCH #define _GEN_ARCH _ARCHMODE3 #include "chsc.c" #endif #endif /*!defined(_GEN_ARCH)*/ hercules-3.07/chsc.h000644 000765 000765 00000007202 11143760544 016042 0ustar00jmaynardjmaynard000000 000000 /* CHSC.H (c) Copyright Jan Jaeger, 1999-2000 */ /* Channel Subsystem interface fields */ // $Id: chsc.h 5125 2009-01-23 12:01:44Z bernard $ // // $Log$ // Revision 1.5 2007/06/23 00:04:04 ivan // Update copyright notices to include current year (2007) // // Revision 1.4 2006/12/08 09:43:18 jj // Add CVS message log // #if !defined(_CHSC_H) #define _CHSC_H // #if defined(FEATURE_CHSC) typedef struct _CHSC_REQ { HWORD length; /* Offset to response field */ HWORD req; /* Request code */ FWORD resv[3]; } CHSC_REQ; typedef struct _CHSC_REQ4 { HWORD length; /* Offset to response field */ HWORD req; /* Request code */ #define CHSC_REQ_SCHDESC 0x04 #define CHSC_REQ_CSSINFO 0x10 HWORD resv1; HWORD f_sch; /* First subchannel */ HWORD resv2; HWORD l_sch; /* Last subchannel */ FWORD resv3; } CHSC_REQ4; typedef struct _CHSC_RSP { HWORD length; /* Length of response field */ HWORD rsp; /* Reponse code */ #define CHSC_REQ_OK 0x0001 /* No error */ #define CHSC_REQ_INVALID 0x0002 /* Invalid request */ #define CHSC_REQ_ERRREQ 0x0003 /* Error in request block */ #define CHSC_REQ_NOTSUPP 0x0004 /* Request not supported */ FWORD info; } CHSC_RSP; typedef struct _CHSC_RSP4 { BYTE sch_val : 1; /* Subchannel valid */ BYTE dev_val : 1; /* Device number valid */ BYTE st : 3; /* Subchannel type */ #define CHSC_RSP4_ST_IO 0 /* I/O Subchannel; all fields have a meaning */ #define CHSC_RSP4_ST_CHSC 1 /* CHSC Subchannel only sch_val st and sch have a meaning */ #define CHSC_RSP4_ST_MSG 2 /* MSG Subchannel; all fields except unit_addr have a meaning */ #define CHSC_RPS4_ST_ADM 3 /* ADM Subchannel; Only sch_val st and sch have a meaning */ BYTE zeros : 3; BYTE unit_addr; /* Unit address */ HWORD devno; /* Device number */ BYTE path_mask; /* Valid path mask */ BYTE fla_valid_mask; /* Valid link mask */ HWORD sch; /* Subchannel number */ BYTE chpid[8]; /* Channel path array */ BYTE fla[8]; /* Full link address array */ } CHSC_RSP4; typedef struct _CHSC_RSP10 { FWORD general_char[510]; FWORD chsc_char[508]; /* ZZ: Linux/390 code indicates this field has a length of 518, however, that would mean that the entire CHSC request would be 4K + 16 in length which is probably an error - *JJ/10/10/04*/ } CHSC_RSP10; // #endif /*defined(FEATURE_CHSC)*/ #endif /*!defined(_CHSC_H)*/ hercules-3.07/ckddasd.c000644 000765 000765 00000656573 11202676512 016534 0ustar00jmaynardjmaynard000000 000000 /* CKDDASD.C (c) Copyright Roger Bowler, 1999-2009 */ /* ESA/390 CKD Direct Access Storage Device Handler */ // $Id: ckddasd.c 5337 2009-05-03 23:54:05Z kleonard $ /*-------------------------------------------------------------------*/ /* This module contains device handling functions for emulated */ /* count-key-data direct access storage devices. */ /*-------------------------------------------------------------------*/ /*-------------------------------------------------------------------*/ /* Additional credits: */ /* Write Update Key and Data CCW by Jan Jaeger */ /* Track overflow support added by Jay Maynard */ /* Track overflow fixes by Jay Maynard, suggested by Valery */ /* Pogonchenko */ /* Track overflow write fix by Roger Bowler, thanks to Valery */ /* Pogonchenko and Volker Bandke V1.71 16/01/2001 */ /*-------------------------------------------------------------------*/ // $Log$ // Revision 1.96 2009/01/23 11:43:35 bernard // copyright notice // // Revision 1.95 2008/12/01 21:31:02 rbowler // Show filename in msg HHCDA002E by enrico sorichetti // // Revision 1.94 2008/07/18 23:58:13 fish // Revert prior PSF order 18 length change; len s/b 12, not 16. // Bug is in S390 Linux dasd_eckd driver, not Hercules. // // Revision 1.93 2008/05/24 20:54:31 rbowler // Increase PSF-PRSD data length from 12 to 16 bytes (by Jacob Dekel) // // Revision 1.92 2008/05/19 16:40:54 rbowler // Modify PSF order 1D to not prepare subsystem data // // Revision 1.91 2008/05/19 15:40:04 rbowler // PSF order 18 suborders (0E,41) and order 1D by Jacob Dekel // // Revision 1.90 2008/01/07 22:59:11 rbowler // Additional LFS validity checks // // Revision 1.89 2007/11/25 19:30:21 gsmith // fix LRE length check, thanks Fish!! - Greg // // Revision 1.88 2007/11/21 22:54:13 fish // Use new BEGIN_DEVICE_CLASS_QUERY macro // // Revision 1.87 2007/11/21 00:31:38 gsmith // LRE support (try #1) // // Revision 1.86 2007/06/23 00:04:04 ivan // Update copyright notices to include current year (2007) // // Revision 1.85 2007/02/15 00:10:04 gsmith // Fix ckd RCD, SNSS, SNSID responses // // Revision 1.84 2006/12/08 09:43:18 jj // Add CVS message log // #include "hstdinc.h" #define _CKDDASD_C_ #define _HDASD_DLL_ #include "hercules.h" #include "devtype.h" #include "sr.h" /*-------------------------------------------------------------------*/ /* Bit definitions for File Mask */ /*-------------------------------------------------------------------*/ #define CKDMASK_WRCTL 0xC0 /* Write control bits... */ #define CKDMASK_WRCTL_INHWR0 0x00 /* ...inhibit write HA/R0 */ #define CKDMASK_WRCTL_INHWRT 0x40 /* ...inhibit all writes */ #define CKDMASK_WRCTL_ALLWRU 0x80 /* ...write update only */ #define CKDMASK_WRCTL_ALLWRT 0xC0 /* ...allow all writes */ #define CKDMASK_RESV 0x20 /* Reserved bits - must be 0 */ #define CKDMASK_SKCTL 0x18 /* Seek control bits... */ #define CKDMASK_SKCTL_ALLSKR 0x00 /* ...allow all seek/recalib */ #define CKDMASK_SKCTL_CYLHD 0x08 /* ...allow seek cyl/head */ #define CKDMASK_SKCTL_HEAD 0x10 /* ...allow seek head only */ #define CKDMASK_SKCTL_INHSMT 0x18 /* ...inhibit seek and MT */ #define CKDMASK_AAUTH 0x06 /* Access auth bits... */ #define CKDMASK_AAUTH_NORMAL 0x00 /* ...normal authorization */ #define CKDMASK_AAUTH_DSF 0x02 /* ...device support auth */ #define CKDMASK_AAUTH_DIAG 0x04 /* ...diagnostic auth */ #define CKDMASK_AAUTH_DSFNCR 0x06 /* ...device support with no correction or retry */ #define CKDMASK_PCI_FETCH 0x01 /* PCI fetch mode */ /*-------------------------------------------------------------------*/ /* Bit definitions for Define Extent global attributes byte */ /*-------------------------------------------------------------------*/ #define CKDGATR_ARCH 0xC0 /* Architecture mode... */ #define CKDGATR_ARCH_ECKD 0xC0 /* ...extended CKD mode */ #define CKDGATR_CKDCONV 0x20 /* CKD conversion mode */ #define CKDGATR_SSOP 0x1C /* Subsystem operation mode..*/ #define CKDGATR_SSOP_NORMAL 0x00 /* ...normal cache */ #define CKDGATR_SSOP_BYPASS 0x04 /* ...bypass cache */ #define CKDGATR_SSOP_INHIBIT 0x08 /* ...inhibit cache loading */ #define CKDGATR_SSOP_SEQACC 0x0C /* ...sequential access */ #define CKDGATR_SSOP_LOGGING 0x10 /* ...logging mode */ #define CKDGATR_USE_CACHE_FW 0x02 /* Use cache fast write */ #define CKDGATR_INH_DASD_FW 0x01 /* Inhibit DASD fast write */ /*-------------------------------------------------------------------*/ /* Bit definitions for Locate operation byte */ /*-------------------------------------------------------------------*/ #define CKDOPER_ORIENTATION 0xC0 /* Orientation bits... */ #define CKDOPER_ORIENT_COUNT 0x00 /* ...orient to count */ #define CKDOPER_ORIENT_HOME 0x40 /* ...orient to home address */ #define CKDOPER_ORIENT_DATA 0x80 /* ...orient to data area */ #define CKDOPER_ORIENT_INDEX 0xC0 /* ...orient to index */ #define CKDOPER_CODE 0x3F /* Operation code bits... */ #define CKDOPER_ORIENT 0x00 /* ...orient */ #define CKDOPER_WRITE 0x01 /* ...write data */ #define CKDOPER_FORMAT 0x03 /* ...format write */ #define CKDOPER_RDDATA 0x06 /* ...read data */ #define CKDOPER_WRTANY 0x09 /* ...write any */ #define CKDOPER_RDANY 0x0A /* ...read any */ #define CKDOPER_WRTTRK 0x0B /* ...write track */ #define CKDOPER_RDTRKS 0x0C /* ...read tracks */ #define CKDOPER_RDTSET 0x0E /* ...read track set */ #define CKDOPER_READ 0x16 /* ...read */ #define CKDOPER_EXTOP 0x3F /* ...extended operation */ /*-------------------------------------------------------------------*/ /* Bit definitions for Locate auxiliary byte */ /*-------------------------------------------------------------------*/ #define CKDLAUX_TLFVALID 0x80 /* TLF field is valid */ #define CKDLAUX_RESV 0x7E /* Reserved bits - must be 0 */ #define CKDLAUX_RDCNTSUF 0x01 /* Suffixed read count CCW */ /*-------------------------------------------------------------------*/ /* Definitions for ckdorient field in device block */ /*-------------------------------------------------------------------*/ #define CKDORIENT_NONE 0 /* Orientation unknown */ #define CKDORIENT_INDEX 1 /* Oriented after track hdr */ #define CKDORIENT_COUNT 2 /* Oriented after count field*/ #define CKDORIENT_KEY 3 /* Oriented after key field */ #define CKDORIENT_DATA 4 /* Oriented after data field */ #define CKDORIENT_EOT 5 /* Oriented after end of trk */ /* Path state byte for Sense Path Group ID command */ #define SPG_PATHSTAT 0xC0 /* Pathing status bits... */ #define SPG_PATHSTAT_RESET 0x00 /* ...reset */ #define SPG_PATHSTAT_RESV 0x40 /* ...reserved bit setting */ #define SPG_PATHSTAT_UNGROUPED 0x80 /* ...ungrouped */ #define SPG_PATHSTAT_GROUPED 0xC0 /* ...grouped */ #define SPG_PARTSTAT 0x30 /* Partitioning status bits..*/ #define SPG_PARTSTAT_IENABLED 0x00 /* ...implicitly enabled */ #define SPG_PARTSTAT_RESV 0x10 /* ...reserved bit setting */ #define SPG_PARTSTAT_DISABLED 0x20 /* ...disabled */ #define SPG_PARTSTAT_XENABLED 0x30 /* ...explicitly enabled */ #define SPG_PATHMODE 0x08 /* Path mode bit... */ #define SPG_PATHMODE_SINGLE 0x00 /* ...single path mode */ #define SPG_PATHMODE_RESV 0x08 /* ...reserved bit setting */ #define SPG_RESERVED 0x07 /* Reserved bits, must be 0 */ /* Function control byte for Set Path Group ID command */ #define SPG_SET_MULTIPATH 0x80 /* Set multipath mode */ #define SPG_SET_COMMAND 0x60 /* Set path command bits... */ #define SPG_SET_ESTABLISH 0x00 /* ...establish group */ #define SPG_SET_DISBAND 0x20 /* ...disband group */ #define SPG_SET_RESIGN 0x40 /* ...resign from group */ #define SPG_SET_COMMAND_RESV 0x60 /* ...reserved bit setting */ #define SPG_SET_RESV 0x1F /* Reserved bits, must be 0 */ /*-------------------------------------------------------------------*/ /* Bit definitions for Diagnostic Control subcommand byte */ /*-------------------------------------------------------------------*/ #define DIAGCTL_INHIBIT_WRITE 0x02 /* Inhibit Write */ #define DIAGCTL_SET_GUAR_PATH 0x04 /* Set Guaranteed Path */ #define DIAGCTL_ENABLE_WRITE 0x08 /* Enable Write */ #define DIAGCTL_3380_TC_MODE 0x09 /* 3380 Track Compat Mode */ #define DIAGCTL_INIT_SUBSYS 0x0B /* Diagnostic Init Subsys */ #define DIAGCTL_UNFENCE 0x0C /* Unfence */ #define DIAGCTL_ACCDEV_UNKCOND 0x0F /* Access Device Unknown Cond*/ #define DIAGCTL_MAINT_RESERVE 0x10 /* Media Maintenance Reserve */ #define DIAGCTL_MAINT_RELEASE 0x11 /* Media Maintenance Release */ #define DIAGCTL_MAINT_QUERY 0x12 /* Media Maintenance Query */ /*-------------------------------------------------------------------*/ /* Definitions for sense data format codes and message codes */ /*-------------------------------------------------------------------*/ #define FORMAT_0 0 /* Program or System Checks */ #define FORMAT_1 1 /* Device Equipment Checks */ #define FORMAT_2 2 /* 3990 Equipment Checks */ #define FORMAT_3 3 /* 3990 Control Checks */ #define FORMAT_4 4 /* Data Checks */ #define FORMAT_5 5 /* Data Check + Displacement */ #define FORMAT_6 6 /* Usage Stats/Overrun Errors*/ #define FORMAT_7 7 /* Device Control Checks */ #define FORMAT_8 8 /* Device Equipment Checks */ #define FORMAT_9 9 /* Device Rd/Wrt/Seek Checks */ #define FORMAT_F 15 /* Cache Storage Checks */ #define MESSAGE_0 0 /* Message 0 */ #define MESSAGE_1 1 /* Message 1 */ #define MESSAGE_2 2 /* Message 2 */ #define MESSAGE_3 3 /* Message 3 */ #define MESSAGE_4 4 /* Message 4 */ #define MESSAGE_5 5 /* Message 5 */ #define MESSAGE_6 6 /* Message 6 */ #define MESSAGE_7 7 /* Message 7 */ #define MESSAGE_8 8 /* Message 8 */ #define MESSAGE_9 9 /* Message 9 */ #define MESSAGE_A 10 /* Message A */ #define MESSAGE_B 11 /* Message B */ #define MESSAGE_C 12 /* Message C */ #define MESSAGE_D 13 /* Message D */ #define MESSAGE_E 14 /* Message E */ #define MESSAGE_F 15 /* Message F */ /*-------------------------------------------------------------------*/ /* Definitions for Read Configuration Data command */ /*-------------------------------------------------------------------*/ #define CONFIG_DATA_SIZE 256 /* Number of bytes returned by Read Config Data CCW */ /* * ISW20060207 * EXTENT_CHECK0 is just to shut up a stupid gcc 4 warning.. * It doesn't hurt otherwise * EXTENT_CHECK0(dev) is the same as EXTENT_CHECK(dev,0,0) */ #define EXTENT_CHECK0(_dev) ((_dev)->ckdxbcyl > 0 \ || ((_dev)->ckdxbcyl==0 && (_dev)->ckdxbhead>0)) #define EXTENT_CHECK(_dev, _cyl, _head) \ ( (_cyl) < (_dev)->ckdxbcyl || (_cyl) > (_dev)->ckdxecyl \ || ((_cyl) == (_dev)->ckdxbcyl && (_head) < (_dev)->ckdxbhead) \ || ((_cyl) == (_dev)->ckdxecyl && (_head) > (_dev)->ckdxehead) ) /*-------------------------------------------------------------------*/ /* Static data areas */ /*-------------------------------------------------------------------*/ static BYTE eighthexFF[] = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}; /*-------------------------------------------------------------------*/ /* Initialize the device handler */ /*-------------------------------------------------------------------*/ int ckddasd_init_handler ( DEVBLK *dev, int argc, char *argv[] ) { int rc; /* Return code */ struct stat statbuf; /* File information */ CKDDASD_DEVHDR devhdr; /* Device header */ CCKDDASD_DEVHDR cdevhdr; /* Compressed device header */ int i; /* Loop index */ int fileseq; /* File sequence number */ char *sfxptr; /* -> Last char of file name */ char sfxchar; /* Last char of file name */ int heads; /* #of heads in CKD file */ int trksize; /* Track size of CKD file */ int trks; /* #of tracks in CKD file */ int cyls; /* #of cylinders in CKD file */ int highcyl; /* Highest cyl# in CKD file */ char *cu = NULL; /* Specified control unit */ char *kw; /* Argument keyword */ int cckd=0; /* 1 if compressed CKD */ char pathname[MAX_PATH]; /* file path in host format */ if(!sscanf(dev->typname,"%hx",&(dev->devtype))) dev->devtype = 0x3380; /* The first argument is the file name */ if (argc == 0 || strlen(argv[0]) > sizeof(dev->filename)-1) { logmsg (_("HHCDA001E File name missing or invalid\n")); return -1; } /* Save the file name in the device block */ hostpath(pathname, argv[0], sizeof(pathname)); strcpy (dev->filename, pathname); /* Device is shareable */ dev->shared = 1; /* Check for possible remote device */ hostpath(pathname, dev->filename, sizeof(pathname)); if (stat(pathname, &statbuf) < 0) { rc = shared_ckd_init ( dev, argc, argv); if (rc < 0) { logmsg (_("HHCDA002E %4.4X:File not found or invalid '%s'\n"), dev->devnum,dev->filename); return -1; } else return rc; } /* Default to synchronous I/O */ dev->syncio = 1; /* No active track or cache entry */ dev->bufcur = dev->cache = -1; /* Locate and save the last character of the file name */ sfxptr = strrchr (dev->filename, '/'); if (sfxptr == NULL) sfxptr = dev->filename + 1; sfxptr = strchr (sfxptr, '.'); if (sfxptr == NULL) sfxptr = dev->filename + strlen(dev->filename); sfxptr--; sfxchar = *sfxptr; /* process the remaining arguments */ for (i = 1; i < argc; i++) { if (strcasecmp ("lazywrite", argv[i]) == 0) { dev->ckdnolazywr = 0; continue; } if (strcasecmp ("nolazywrite", argv[i]) == 0) { dev->ckdnolazywr = 1; continue; } if (strcasecmp ("fulltrackio", argv[i]) == 0 || strcasecmp ("fulltrkio", argv[i]) == 0 || strcasecmp ("ftio", argv[i]) == 0) { dev->ckdnolazywr = 0; continue; } if (strcasecmp ("nofulltrackio", argv[i]) == 0 || strcasecmp ("nofulltrkio", argv[i]) == 0 || strcasecmp ("noftio", argv[i]) == 0) { dev->ckdnolazywr = 1; continue; } if (strcasecmp ("readonly", argv[i]) == 0 || strcasecmp ("rdonly", argv[i]) == 0 || strcasecmp ("ro", argv[i]) == 0) { dev->ckdrdonly = 1; continue; } if (strcasecmp ("fakewrite", argv[i]) == 0 || strcasecmp ("fakewrt", argv[i]) == 0 || strcasecmp ("fw", argv[i]) == 0) { dev->ckdfakewr = 1; continue; } if (strlen (argv[i]) > 3 && memcmp ("sf=", argv[i], 3) == 0) { if ('\"' == argv[i][3]) argv[i]++; hostpath(pathname, argv[i]+3, sizeof(pathname)); dev->dasdsfn = strdup(pathname); if (dev->dasdsfn) { /* Set the pointer to the suffix character */ dev->dasdsfx = strrchr (dev->dasdsfn, '/'); if (dev->dasdsfx == NULL) dev->dasdsfx = dev->dasdsfn + 1; dev->dasdsfx = strchr (dev->dasdsfx, '.'); if (dev->dasdsfx == NULL) dev->dasdsfx = dev->dasdsfn + strlen(dev->dasdsfn); dev->dasdsfx--; } continue; } if (strlen (argv[i]) > 3 && memcmp("cu=", argv[i], 3) == 0) { kw = strtok (argv[i], "="); cu = strtok (NULL, " \t"); continue; } if (strcasecmp ("nosyncio", argv[i]) == 0 || strcasecmp ("nosyio", argv[i]) == 0) { dev->syncio = 0; continue; } if (strcasecmp ("syncio", argv[i]) == 0 || strcasecmp ("syio", argv[i]) == 0) { dev->syncio = 1; continue; } logmsg (_("HHCDA003E parameter %d is invalid: %s\n"), i + 1, argv[i]); return -1; } /* Initialize the total tracks and cylinders */ dev->ckdtrks = 0; dev->ckdcyls = 0; /* Open all of the CKD image files which comprise this volume */ if (dev->ckdrdonly) logmsg (_("HHCDA004I opening %s readonly%s\n"), dev->filename, dev->ckdfakewr ? " with fake writing" : ""); for (fileseq = 1;;) { /* Open the CKD image file */ hostpath(pathname, dev->filename, sizeof(pathname)); dev->fd = open (pathname, dev->ckdrdonly ? O_RDONLY|O_BINARY : O_RDWR|O_BINARY); if (dev->fd < 0) { /* Try read-only if shadow file present */ if (!dev->ckdrdonly && dev->dasdsfn != NULL) dev->fd = open (pathname, O_RDONLY|O_BINARY); if (dev->fd < 0) { logmsg (_("HHCDA005E %s open error: %s\n"), dev->filename, strerror(errno)); return -1; } } /* If shadow file, only one base file is allowed */ if (fileseq > 1 && dev->dasdsfn != NULL) { logmsg (_("HHCDA006E %s not in a single file for shadowing\n"), dev->filename); return -1; } /* Determine the device size */ rc = fstat (dev->fd, &statbuf); if (rc < 0) { logmsg (_("HHCDA007E %s fstat error: %s\n"), dev->filename, strerror(errno)); return -1; } /* Read the device header */ rc = read (dev->fd, &devhdr, CKDDASD_DEVHDR_SIZE); if (rc < (int)CKDDASD_DEVHDR_SIZE) { if (rc < 0) logmsg (_("HHCDA008E %s read error: %s\n"), dev->filename, strerror(errno)); else logmsg (_("HHCDA09E %s CKD header incomplete\n"), dev->filename); return -1; } /* Check the device header identifier */ if (memcmp(devhdr.devid, "CKD_P370", 8) != 0) { if (memcmp(devhdr.devid, "CKD_C370", 8) != 0) { logmsg (_("HHCDA010E %s CKD header invalid\n"), dev->filename); return -1; } else { cckd = 1; if (fileseq != 1) { logmsg (_("HHCDA011E %s Only 1 CCKD file allowed\n"), dev->filename); return -1; } } } /* Read the compressed device header */ if ( cckd ) { rc = read (dev->fd, &cdevhdr, CCKDDASD_DEVHDR_SIZE); if (rc < (int)CCKDDASD_DEVHDR_SIZE) { if (rc < 0) { logmsg (_("HHCDA012E %s read error: %s\n"), dev->filename, strerror(errno)); } else { logmsg (_("HHCDA013E %s CCKD header incomplete\n"), dev->filename); } return -1; } } /* Extract fields from device header */ heads = ((U32)(devhdr.heads[3]) << 24) | ((U32)(devhdr.heads[2]) << 16) | ((U32)(devhdr.heads[1]) << 8) | (U32)(devhdr.heads[0]); trksize = ((U32)(devhdr.trksize[3]) << 24) | ((U32)(devhdr.trksize[2]) << 16) | ((U32)(devhdr.trksize[1]) << 8) | (U32)(devhdr.trksize[0]); highcyl = ((U32)(devhdr.highcyl[1]) << 8) | (U32)(devhdr.highcyl[0]); if (cckd == 0) { if (dev->dasdcopy == 0) { trks = (statbuf.st_size - CKDDASD_DEVHDR_SIZE) / trksize; cyls = trks / heads; if (fileseq == 1 && highcyl == cyls) { devhdr.fileseq = 0; highcyl = 0; } } else { /* * For dasdcopy we get the number of cylinders and tracks from * the highcyl in the device header. The last file will have * a sequence number of 0xFF. */ cyls = highcyl - dev->ckdcyls + 1; trks = cyls * heads; if (devhdr.fileseq == 0xFF) { devhdr.fileseq = fileseq == 1 ? 0 : fileseq; highcyl = 0; devhdr.highcyl[0] = devhdr.highcyl[1] = 0; lseek (dev->fd, 0, SEEK_SET); rc = write (dev->fd, &devhdr, CKDDASD_DEVHDR_SIZE); } } } else { cyls = ((U32)(cdevhdr.cyls[3]) << 24) | ((U32)(cdevhdr.cyls[2]) << 16) | ((U32)(cdevhdr.cyls[1]) << 8) | (U32)(cdevhdr.cyls[0]); trks = cyls * heads; } /* Check for correct file sequence number */ if (devhdr.fileseq != fileseq && !(devhdr.fileseq == 0 && fileseq == 1)) { logmsg (_("HHCDA014E %s CKD file out of sequence\n"), dev->filename); return -1; } if (devhdr.fileseq > 0) { logmsg (_("HHCDA015I %s seq=%d cyls=%d-%d\n"), dev->filename, devhdr.fileseq, dev->ckdcyls, (highcyl > 0 ? highcyl : dev->ckdcyls + cyls - 1)); } /* Save device geometry of first file, or check that device geometry of subsequent files matches that of first file */ if (fileseq == 1) { dev->ckdheads = heads; dev->ckdtrksz = trksize; } else if (heads != dev->ckdheads || trksize != dev->ckdtrksz) { logmsg (_("HHCDA016E %s heads=%d trklen=%d, " "expected heads=%d trklen=%d\n"), dev->filename, heads, trksize, dev->ckdheads, dev->ckdtrksz); return -1; } /* Consistency check device header */ if (cckd == 0 && dev->dasdcopy == 0 && (cyls * heads != trks || ((off_t)trks * trksize) + CKDDASD_DEVHDR_SIZE != statbuf.st_size || (highcyl != 0 && highcyl != dev->ckdcyls + cyls - 1))) { logmsg (_("HHCDA017E %s CKD header inconsistent with file size\n"), dev->filename); return -1; } /* Check for correct high cylinder number */ if (highcyl != 0 && highcyl != dev->ckdcyls + cyls - 1) { logmsg (_("HHCDA018E %s CKD header high cylinder incorrect\n"), dev->filename); return -1; } /* Accumulate total volume size */ dev->ckdtrks += trks; dev->ckdcyls += cyls; /* Save file descriptor and high track number */ dev->ckdfd[fileseq-1] = dev->fd; dev->ckdhitrk[fileseq-1] = dev->ckdtrks; dev->ckdnumfd = fileseq; /* Exit loop if this is the last file */ if (highcyl == 0) break; /* Increment the file sequence number */ fileseq++; /* Alter the file name suffix ready for the next file */ *sfxptr = '0' + fileseq; /* Check that maximum files has not been exceeded */ if (fileseq > CKD_MAXFILES) { logmsg (_("HHCDA019E %s exceeds maximum %d CKD files\n"), dev->filename, CKD_MAXFILES); return -1; } } /* end for(fileseq) */ /* Restore the last character of the file name */ *sfxptr = sfxchar; /* Log the device geometry */ logmsg (_("HHCDA020I %s cyls=%d heads=%d tracks=%d trklen=%d\n"), dev->filename, dev->ckdcyls, dev->ckdheads, dev->ckdtrks, dev->ckdtrksz); /* Set number of sense bytes */ dev->numsense = 32; if ((dev->devtype == 0x2311 ) || (dev->devtype == 0x2314 ) || (dev->devtype == 0x2305 )) { dev->numsense = 6; } if ((dev->devtype == 0x3330 ) || (dev->devtype == 0x3340 ) || (dev->devtype == 0x3350 ) || (dev->devtype == 0x3375 ) || (dev->devtype == 0x3380 )) { dev->numsense = 24; } /* Locate the CKD dasd table entry */ dev->ckdtab = dasd_lookup (DASD_CKDDEV, NULL, dev->devtype, dev->ckdcyls); if (dev->ckdtab == NULL) { logmsg (_("HHCDA021E %4.4X device type %4.4X not found in dasd table\n"), dev->devnum, dev->devtype); return -1; } /* Locate the CKD control unit dasd table entry */ dev->ckdcu = dasd_lookup (DASD_CKDCU, cu ? cu : dev->ckdtab->cu, 0, 0); if (dev->ckdcu == NULL) { logmsg (_("HHCDA022E %4.4X control unit %s not found in dasd table\n"), dev->devnum, cu ? cu : dev->ckdtab->cu); return -1; } /* Set flag bit if 3990 controller */ if (dev->ckdcu->devt == 0x3990) dev->ckd3990 = 1; /* Build the devid area */ dev->numdevid = dasd_build_ckd_devid (dev->ckdtab, dev->ckdcu, (BYTE *)&dev->devid); /* Build the devchar area */ dev->numdevchar = dasd_build_ckd_devchar (dev->ckdtab, dev->ckdcu, (BYTE *)&dev->devchar, dev->ckdcyls); /* Clear the DPA */ memset(dev->pgid, 0, sizeof(dev->pgid)); /* Activate I/O tracing */ // dev->ccwtrace = 1; /* Request the channel to merge data chained write CCWs into a single buffer before passing data to the device handler */ dev->cdwmerge = 1; if (!cckd) return 0; else return cckddasd_init_handler(dev, argc, argv); } /* end function ckddasd_init_handler */ /*-------------------------------------------------------------------*/ /* Query the device definition */ /*-------------------------------------------------------------------*/ void ckddasd_query_device (DEVBLK *dev, char **class, int buflen, char *buffer) { BEGIN_DEVICE_CLASS_QUERY( "DASD", dev, class, buflen, buffer ); snprintf (buffer, buflen, "%s [%d cyls]", dev->filename, dev->ckdcyls); } /* end function ckddasd_query_device */ /*-------------------------------------------------------------------*/ /* Release cache entries */ /*-------------------------------------------------------------------*/ int ckddasd_purge_cache (int *answer, int ix, int i, void *data) { U16 devnum; /* Cached device number */ int trk; /* Cached track */ DEVBLK *dev = data; /* -> device block */ UNREFERENCED(answer); CKD_CACHE_GETKEY(i, devnum, trk); if (dev->devnum == devnum) cache_release (ix, i, CACHE_FREEBUF); return 0; } static int ckddasd_read_track (DEVBLK *dev, int trk, BYTE *unitstat); /*-------------------------------------------------------------------*/ /* Close the device */ /*-------------------------------------------------------------------*/ int ckddasd_close_device ( DEVBLK *dev ) { int i; /* Index */ BYTE unitstat; /* Unit Status */ /* Write the last track image if it's modified */ ckddasd_read_track (dev, -1, &unitstat); /* Free the cache */ cache_lock(CACHE_DEVBUF); cache_scan(CACHE_DEVBUF, ckddasd_purge_cache, dev); cache_unlock(CACHE_DEVBUF); if (!dev->batch) logmsg (_("HHCDA023I %4.4X cache hits %d, misses %d, waits %d\n"), dev->devnum, dev->cachehits, dev->cachemisses, dev->cachewaits); /* Close all of the CKD image files */ for (i = 0; i < dev->ckdnumfd; i++) if (dev->ckdfd[i] > 2) close (dev->ckdfd[i]); dev->buf = NULL; dev->bufsize = 0; return 0; } /* end function ckddasd_close_device */ /*-------------------------------------------------------------------*/ /* Read a track image at CCHH */ /*-------------------------------------------------------------------*/ static int ckd_read_cchh (DEVBLK *dev, int cyl, int head, BYTE *unitstat) { int rc; /* Return code */ int trk; /* Track number */ /* Command reject if seek position is outside volume */ if (cyl >= dev->ckdcyls || head >= dev->ckdheads) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_4); *unitstat = CSW_CE | CSW_DE | CSW_UC; return -1; } /* Calculate the track number */ trk = cyl * dev->ckdheads + head; /* Call the read exit */ rc = (dev->hnd->read) (dev, trk, unitstat); return rc; } /* end function ckd_read_cchh */ /*-------------------------------------------------------------------*/ /* Return track image length */ /*-------------------------------------------------------------------*/ static int ckd_trklen (DEVBLK *dev, BYTE *buf) { int sz; /* Size so far */ for (sz = CKDDASD_TRKHDR_SIZE; memcmp (buf + sz, &eighthexFF, 8) != 0; ) { /* add length of count, key, and data fields */ sz += CKDDASD_RECHDR_SIZE + buf[sz+5] + (buf[sz+6] << 8) + buf[sz+7]; if (sz > dev->ckdtrksz - 8) break; } /* add length for end-of-track indicator */ sz += CKDDASD_RECHDR_SIZE; if (sz > dev->ckdtrksz) sz = dev->ckdtrksz; return sz; } /*-------------------------------------------------------------------*/ /* Read a track image */ /*-------------------------------------------------------------------*/ static int ckddasd_read_track (DEVBLK *dev, int trk, BYTE *unitstat) { int rc; /* Return code */ int cyl; /* Cylinder */ int head; /* Head */ off_t offset; /* File offsets */ int i,o,f; /* Indexes */ int active; /* 1=Synchronous I/O active */ CKDDASD_TRKHDR *trkhdr; /* -> New track header */ logdevtr (dev, _("HHCDA024I read trk %d cur trk %d\n"), trk, dev->bufcur); /* Calculate cylinder and head */ cyl = trk / dev->ckdheads; head = trk % dev->ckdheads; /* Reset buffer offsets */ dev->bufoff = 0; dev->bufoffhi = dev->ckdtrksz; /* Return if reading the same track image */ if (trk >= 0 && trk == dev->bufcur) return 0; /* Turn off the synchronous I/O bit if trk overflow or trk 0 */ active = dev->syncio_active; if (dev->ckdtrkof || trk <= 0) dev->syncio_active = 0; /* Write the previous track image if modified */ if (dev->bufupd) { /* Retry if synchronous I/O */ if (dev->syncio_active) { dev->syncio_retry = 1; return -1; } logdevtr (dev, _("HHCDA025I read track: updating track %d\n"), dev->bufcur); dev->bufupd = 0; /* Seek to the old track image offset */ offset = (off_t)(dev->ckdtrkoff + dev->bufupdlo); offset = lseek (dev->fd, offset, SEEK_SET); if (offset < 0) { /* Handle seek error condition */ logmsg (_("HHCDA026E error writing trk %d: lseek error: %s\n"), dev->bufcur, strerror(errno)); ckd_build_sense (dev, SENSE_EC, 0, 0, FORMAT_1, MESSAGE_0); *unitstat = CSW_CE | CSW_DE | CSW_UC; cache_lock(CACHE_DEVBUF); cache_setflag(CACHE_DEVBUF, dev->cache, ~CKD_CACHE_ACTIVE, 0); cache_unlock(CACHE_DEVBUF); dev->bufupdlo = dev->bufupdhi = 0; dev->bufcur = dev->cache = -1; return -1; } /* Write the portion of the track image that was modified */ rc = write (dev->fd, &dev->buf[dev->bufupdlo], dev->bufupdhi - dev->bufupdlo); if (rc < dev->bufupdhi - dev->bufupdlo) { /* Handle seek error condition */ logmsg (_("HHCDA027E error writing trk %d: write error: %s\n"), dev->bufcur, strerror(errno)); ckd_build_sense (dev, SENSE_EC, 0, 0, FORMAT_1, MESSAGE_0); *unitstat = CSW_CE | CSW_DE | CSW_UC; cache_lock(CACHE_DEVBUF); cache_setflag(CACHE_DEVBUF, dev->cache, ~CKD_CACHE_ACTIVE, 0); cache_unlock(CACHE_DEVBUF); dev->bufupdlo = dev->bufupdhi = 0; dev->bufcur = dev->cache = -1; return -1; } dev->bufupdlo = dev->bufupdhi = 0; } cache_lock (CACHE_DEVBUF); /* Make the previous cache entry inactive */ if (dev->cache >= 0) cache_setflag(CACHE_DEVBUF, dev->cache, ~CKD_CACHE_ACTIVE, 0); dev->bufcur = dev->cache = -1; /* Return on special case when called by the close handler */ if (trk < 0) { cache_unlock (CACHE_DEVBUF); return 0; } ckd_read_track_retry: /* Search the cache */ i = cache_lookup (CACHE_DEVBUF, CKD_CACHE_SETKEY(dev->devnum, trk), &o); /* Cache hit */ if (i >= 0) { cache_setflag(CACHE_DEVBUF, i, ~0, CKD_CACHE_ACTIVE); cache_setage(CACHE_DEVBUF, i); cache_unlock(CACHE_DEVBUF); logdevtr (dev, _("HHCDA028I read trk %d cache hit, using cache[%d]\n"), trk, i); dev->cachehits++; dev->cache = i; dev->buf = cache_getbuf(CACHE_DEVBUF, dev->cache, 0); dev->bufcur = trk; dev->bufoff = 0; dev->bufoffhi = dev->ckdtrksz; dev->buflen = ckd_trklen (dev, dev->buf); dev->bufsize = cache_getlen(CACHE_DEVBUF, dev->cache); /* Set the file descriptor */ for (f = 0; f < dev->ckdnumfd; f++) if (trk < dev->ckdhitrk[f]) break; dev->fd = dev->ckdfd[f]; /* Calculate the track offset */ dev->ckdtrkoff = CKDDASD_DEVHDR_SIZE + (off_t)(trk - (f ? dev->ckdhitrk[f-1] : 0)) * dev->ckdtrksz; dev->syncio_active = active; return 0; } /* Retry if synchronous I/O */ if (dev->syncio_active) { cache_unlock(CACHE_DEVBUF); dev->syncio_retry = 1; return -1; } /* Wait if no available cache entry */ if (o < 0) { logdevtr (dev, _("HHCDA029I read trk %d no available cache entry, waiting\n"), trk); dev->cachewaits++; cache_wait(CACHE_DEVBUF); goto ckd_read_track_retry; } /* Cache miss */ logdevtr (dev, _("HHCDA030I read trk %d cache miss, using cache[%d]\n"), trk, o); dev->cachemisses++; /* Make this cache entry active */ cache_setkey (CACHE_DEVBUF, o, CKD_CACHE_SETKEY(dev->devnum, trk)); cache_setflag(CACHE_DEVBUF, o, 0, CKD_CACHE_ACTIVE|DEVBUF_TYPE_CKD); cache_setage (CACHE_DEVBUF, o); dev->buf = cache_getbuf(CACHE_DEVBUF, o, dev->ckdtrksz); cache_unlock (CACHE_DEVBUF); /* Set the file descriptor */ for (f = 0; f < dev->ckdnumfd; f++) if (trk < dev->ckdhitrk[f]) break; dev->fd = dev->ckdfd[f]; /* Calculate the track offset */ dev->ckdtrkoff = CKDDASD_DEVHDR_SIZE + (off_t)(trk - (f ? dev->ckdhitrk[f-1] : 0)) * dev->ckdtrksz; dev->syncio_active = active; logdevtr (dev, _("HHCDA031I read trk %d reading file %d offset %" I64_FMT "d len %d\n"), trk, f+1, (long long)dev->ckdtrkoff, dev->ckdtrksz); /* Seek to the track image offset */ offset = (off_t)dev->ckdtrkoff; offset = lseek (dev->fd, offset, SEEK_SET); if (offset < 0) { /* Handle seek error condition */ logmsg (_("HHCDA032E error reading trk %d: lseek error: %s\n"), trk, strerror(errno)); ckd_build_sense (dev, SENSE_EC, 0, 0, FORMAT_1, MESSAGE_0); *unitstat = CSW_CE | CSW_DE | CSW_UC; dev->bufcur = dev->cache = -1; cache_lock(CACHE_DEVBUF); cache_release(CACHE_DEVBUF, o, 0); cache_unlock(CACHE_DEVBUF); return -1; } /* Read the track image */ if (dev->dasdcopy == 0) { rc = read (dev->fd, dev->buf, dev->ckdtrksz); if (rc < dev->ckdtrksz) { /* Handle read error condition */ logmsg (_("HHCDA033E error reading trk %d: read error: %s\n"), trk, (rc < 0 ? strerror(errno) : "unexpected end of file")); ckd_build_sense (dev, SENSE_EC, 0, 0, FORMAT_1, MESSAGE_0); *unitstat = CSW_CE | CSW_DE | CSW_UC; dev->bufcur = dev->cache = -1; cache_lock(CACHE_DEVBUF); cache_release(CACHE_DEVBUF, o, 0); cache_unlock(CACHE_DEVBUF); return -1; } } else { trkhdr = (CKDDASD_TRKHDR *)dev->buf; trkhdr->bin = 0; trkhdr->cyl[0] = (cyl >> 8); trkhdr->cyl[1] = (cyl & 0xFF); trkhdr->head[0] = (head >> 8); trkhdr->head[1] = (head & 0xFF); memset (dev->buf + CKDDASD_TRKHDR_SIZE, 0xFF, 8); } /* Validate the track header */ logdevtr (dev, _("HHCDA034I read trk %d trkhdr %2.2x %2.2x%2.2x %2.2x%2.2x\n"), trk, dev->buf[0], dev->buf[1], dev->buf[2], dev->buf[3], dev->buf[4]); trkhdr = (CKDDASD_TRKHDR *)dev->buf; if (trkhdr->bin != 0 || trkhdr->cyl[0] != (cyl >> 8) || trkhdr->cyl[1] != (cyl & 0xFF) || trkhdr->head[0] != (head >> 8) || trkhdr->head[1] != (head & 0xFF)) { logmsg (_("HHCDA035E %4.4X invalid track header for cyl %d head %d " " %2.2x%2.2x%2.2x%2.2x%2.2x\n"), dev->devnum, cyl, head, trkhdr->bin,trkhdr->cyl[0],trkhdr->cyl[1],trkhdr->head[0],trkhdr->head[1]); ckd_build_sense (dev, 0, SENSE1_ITF, 0, 0, 0); *unitstat = CSW_CE | CSW_DE | CSW_UC; dev->bufcur = dev->cache = -1; cache_lock(CACHE_DEVBUF); cache_release(CACHE_DEVBUF, o, 0); cache_unlock(CACHE_DEVBUF); return -1; } dev->cache = o; dev->buf = cache_getbuf(CACHE_DEVBUF, dev->cache, 0); dev->bufcur = trk; dev->bufoff = 0; dev->bufoffhi = dev->ckdtrksz; dev->buflen = ckd_trklen (dev, dev->buf); dev->bufsize = cache_getlen(CACHE_DEVBUF, dev->cache); return 0; } /* end function ckdread_read_track */ /*-------------------------------------------------------------------*/ /* Update a track image */ /*-------------------------------------------------------------------*/ static int ckddasd_update_track (DEVBLK *dev, int trk, int off, BYTE *buf, int len, BYTE *unitstat) { int rc; /* Return code */ /* Immediately return if fake writing */ if (dev->ckdfakewr) return len; /* Error if opened read-only */ if (dev->ckdrdonly) { ckd_build_sense (dev, SENSE_EC, SENSE1_WRI, 0, FORMAT_1, MESSAGE_0); *unitstat = CSW_CE | CSW_DE | CSW_UC; return -1; } /* Read the track if it's not current */ if (trk != dev->bufcur) { rc = (dev->hnd->read) (dev, trk, unitstat); if (rc < 0) { dev->bufcur = dev->cache = -1; return -1; } } /* Invalid track format if going past buffer end */ if (off + len > dev->bufoffhi) { ckd_build_sense (dev, 0, SENSE1_ITF, 0, 0, 0); *unitstat = CSW_CE | CSW_DE | CSW_UC; return -1; } /* Copy the data into the buffer */ if (buf) memcpy (dev->buf + off, buf, len); /* Set low and high updated offsets */ if (!dev->bufupd || off < dev->bufupdlo) dev->bufupdlo = off; if (off + len > dev->bufupdhi) dev->bufupdhi = off + len; /* Indicate track image has been modified */ if (!dev->bufupd) { dev->bufupd = 1; shared_update_notify (dev, trk); } return len; } /* end function ckd_update_track */ /*-------------------------------------------------------------------*/ /* CKD start/resume channel program */ /*-------------------------------------------------------------------*/ void ckddasd_start (DEVBLK *dev) { /* Reset buffer offsets */ dev->bufoff = 0; dev->bufoffhi = dev->ckdtrksz; } /*-------------------------------------------------------------------*/ /* CKD end/suspend channel program */ /*-------------------------------------------------------------------*/ void ckddasd_end (DEVBLK *dev) { BYTE unitstat; /* Unit Status */ /* Write the last track image if it's modified */ ckddasd_read_track (dev, -1, &unitstat); } /*-------------------------------------------------------------------*/ /* Return used cylinders */ /*-------------------------------------------------------------------*/ static int ckddasd_used (DEVBLK *dev) { return dev->ckdcyls; } /*-------------------------------------------------------------------*/ /* Hercules suspend/resume text unit key values */ /*-------------------------------------------------------------------*/ #define SR_DEV_CKD_BUFCUR ( SR_DEV_CKD | 0x001 ) #define SR_DEV_CKD_BUFOFF ( SR_DEV_CKD | 0x002 ) #define SR_DEV_CKD_CURCYL ( SR_DEV_CKD | 0x003 ) #define SR_DEV_CKD_CURHEAD ( SR_DEV_CKD | 0x004 ) #define SR_DEV_CKD_CURREC ( SR_DEV_CKD | 0x005 ) #define SR_DEV_CKD_CURKL ( SR_DEV_CKD | 0x006 ) #define SR_DEV_CKD_ORIENT ( SR_DEV_CKD | 0x007 ) #define SR_DEV_CKD_CUROPER ( SR_DEV_CKD | 0x008 ) #define SR_DEV_CKD_CURDL ( SR_DEV_CKD | 0x009 ) #define SR_DEV_CKD_REM ( SR_DEV_CKD | 0x00a ) #define SR_DEV_CKD_POS ( SR_DEV_CKD | 0x00b ) #define SR_DEV_CKD_DXBLKSZ ( SR_DEV_CKD | 0x010 ) #define SR_DEV_CKD_DXBCYL ( SR_DEV_CKD | 0x011 ) #define SR_DEV_CKD_DXBHEAD ( SR_DEV_CKD | 0x012 ) #define SR_DEV_CKD_DXECYL ( SR_DEV_CKD | 0x013 ) #define SR_DEV_CKD_DXEHEAD ( SR_DEV_CKD | 0x014 ) #define SR_DEV_CKD_DXFMASK ( SR_DEV_CKD | 0x015 ) #define SR_DEV_CKD_DXGATTR ( SR_DEV_CKD | 0x016 ) #define SR_DEV_CKD_LRTRANLF ( SR_DEV_CKD | 0x020 ) #define SR_DEV_CKD_LROPER ( SR_DEV_CKD | 0x021 ) #define SR_DEV_CKD_LRAUX ( SR_DEV_CKD | 0x022 ) #define SR_DEV_CKD_LRCOUNT ( SR_DEV_CKD | 0x023 ) #define SR_DEV_CKD_3990 ( SR_DEV_CKD | 0x040 ) #define SR_DEV_CKD_XTDEF ( SR_DEV_CKD | 0x041 ) #define SR_DEV_CKD_SETFM ( SR_DEV_CKD | 0x042 ) #define SR_DEV_CKD_LOCAT ( SR_DEV_CKD | 0x043 ) #define SR_DEV_CKD_SPCNT ( SR_DEV_CKD | 0x044 ) #define SR_DEV_CKD_SEEK ( SR_DEV_CKD | 0x045 ) #define SR_DEV_CKD_SKCYL ( SR_DEV_CKD | 0x046 ) #define SR_DEV_CKD_RECAL ( SR_DEV_CKD | 0x047 ) #define SR_DEV_CKD_RDIPL ( SR_DEV_CKD | 0x048 ) #define SR_DEV_CKD_XMARK ( SR_DEV_CKD | 0x049 ) #define SR_DEV_CKD_HAEQ ( SR_DEV_CKD | 0x04a ) #define SR_DEV_CKD_IDEQ ( SR_DEV_CKD | 0x04b ) #define SR_DEV_CKD_KYEQ ( SR_DEV_CKD | 0x04c ) #define SR_DEV_CKD_WCKD ( SR_DEV_CKD | 0x04d ) #define SR_DEV_CKD_TRKOF ( SR_DEV_CKD | 0x04e ) #define SR_DEV_CKD_SSI ( SR_DEV_CKD | 0x04f ) #define SR_DEV_CKD_WRHA ( SR_DEV_CKD | 0x050 ) /*-------------------------------------------------------------------*/ /* Hercules suspend */ /*-------------------------------------------------------------------*/ int ckddasd_hsuspend(DEVBLK *dev, void *file) { if (dev->bufcur >= 0) { SR_WRITE_VALUE(file, SR_DEV_CKD_BUFCUR, dev->bufcur, sizeof(dev->bufcur)); SR_WRITE_VALUE(file, SR_DEV_CKD_BUFOFF, dev->bufoff, sizeof(dev->bufoff)); } SR_WRITE_VALUE(file, SR_DEV_CKD_CURCYL, dev->ckdcurcyl, sizeof(dev->ckdcurcyl)); SR_WRITE_VALUE(file, SR_DEV_CKD_CURHEAD, dev->ckdcurhead, sizeof(dev->ckdcurhead)); SR_WRITE_VALUE(file, SR_DEV_CKD_CURREC, dev->ckdcurrec, sizeof(dev->ckdcurrec)); SR_WRITE_VALUE(file, SR_DEV_CKD_CURKL, dev->ckdcurkl, sizeof(dev->ckdcurkl)); SR_WRITE_VALUE(file, SR_DEV_CKD_ORIENT, dev->ckdorient, sizeof(dev->ckdorient)); SR_WRITE_VALUE(file, SR_DEV_CKD_CUROPER, dev->ckdcuroper, sizeof(dev->ckdcuroper)); SR_WRITE_VALUE(file, SR_DEV_CKD_CURDL, dev->ckdcurdl, sizeof(dev->ckdcurdl)); SR_WRITE_VALUE(file, SR_DEV_CKD_REM, dev->ckdrem, sizeof(dev->ckdrem)); SR_WRITE_VALUE(file, SR_DEV_CKD_POS, dev->ckdpos, sizeof(dev->ckdpos)); SR_WRITE_VALUE(file, SR_DEV_CKD_DXBLKSZ, dev->ckdxblksz, sizeof(dev->ckdxblksz)); SR_WRITE_VALUE(file, SR_DEV_CKD_DXBCYL, dev->ckdxbcyl, sizeof(dev->ckdxbcyl)); SR_WRITE_VALUE(file, SR_DEV_CKD_DXBHEAD, dev->ckdxbhead, sizeof(dev->ckdxbhead)); SR_WRITE_VALUE(file, SR_DEV_CKD_DXECYL, dev->ckdxecyl, sizeof(dev->ckdxecyl)); SR_WRITE_VALUE(file, SR_DEV_CKD_DXEHEAD, dev->ckdxehead, sizeof(dev->ckdxehead)); SR_WRITE_VALUE(file, SR_DEV_CKD_DXFMASK, dev->ckdfmask, sizeof(dev->ckdfmask)); SR_WRITE_VALUE(file, SR_DEV_CKD_DXGATTR, dev->ckdxgattr, sizeof(dev->ckdxgattr)); SR_WRITE_VALUE(file, SR_DEV_CKD_LRTRANLF, dev->ckdltranlf, sizeof(dev->ckdltranlf)); SR_WRITE_VALUE(file, SR_DEV_CKD_LROPER, dev->ckdloper, sizeof(dev->ckdloper)); SR_WRITE_VALUE(file, SR_DEV_CKD_LRAUX, dev->ckdlaux, sizeof(dev->ckdlaux)); SR_WRITE_VALUE(file, SR_DEV_CKD_LRCOUNT, dev->ckdlcount, sizeof(dev->ckdlcount)); SR_WRITE_VALUE(file, SR_DEV_CKD_3990, dev->ckd3990, 1); SR_WRITE_VALUE(file, SR_DEV_CKD_XTDEF, dev->ckdxtdef, 1); SR_WRITE_VALUE(file, SR_DEV_CKD_SETFM, dev->ckdsetfm, 1); SR_WRITE_VALUE(file, SR_DEV_CKD_LOCAT, dev->ckdlocat, 1); SR_WRITE_VALUE(file, SR_DEV_CKD_SPCNT, dev->ckdspcnt, 1); SR_WRITE_VALUE(file, SR_DEV_CKD_SEEK, dev->ckdseek, 1); SR_WRITE_VALUE(file, SR_DEV_CKD_SKCYL, dev->ckdskcyl, 1); SR_WRITE_VALUE(file, SR_DEV_CKD_RECAL, dev->ckdrecal, 1); SR_WRITE_VALUE(file, SR_DEV_CKD_RDIPL, dev->ckdrdipl, 1); SR_WRITE_VALUE(file, SR_DEV_CKD_XMARK, dev->ckdxmark, 1); SR_WRITE_VALUE(file, SR_DEV_CKD_HAEQ, dev->ckdhaeq, 1); SR_WRITE_VALUE(file, SR_DEV_CKD_IDEQ, dev->ckdideq, 1); SR_WRITE_VALUE(file, SR_DEV_CKD_KYEQ, dev->ckdkyeq, 1); SR_WRITE_VALUE(file, SR_DEV_CKD_WCKD, dev->ckdwckd, 1); SR_WRITE_VALUE(file, SR_DEV_CKD_TRKOF, dev->ckdtrkof, 1); SR_WRITE_VALUE(file, SR_DEV_CKD_SSI, dev->ckdssi, 1); SR_WRITE_VALUE(file, SR_DEV_CKD_WRHA, dev->ckdwrha, 1); return 0; } /*-------------------------------------------------------------------*/ /* Hercules resume */ /*-------------------------------------------------------------------*/ int ckddasd_hresume(DEVBLK *dev, void *file) { u_int rc; size_t key, len; BYTE byte; do { SR_READ_HDR(file, key, len); switch (key) { case SR_DEV_CKD_BUFCUR: SR_READ_VALUE(file, len, &rc, sizeof(rc)); rc = (dev->hnd->read) ? (dev->hnd->read)(dev, rc, &byte) : -1; if ((int)rc < 0) return -1; break; case SR_DEV_CKD_BUFOFF: SR_READ_VALUE(file, len, &dev->bufoff, sizeof(dev->bufoff)); break; case SR_DEV_CKD_CURCYL: SR_READ_VALUE(file, len, &dev->ckdcurcyl, sizeof(dev->ckdcurcyl)); break; case SR_DEV_CKD_CURHEAD: SR_READ_VALUE(file, len, &dev->ckdcurhead, sizeof(dev->ckdcurhead)); break; case SR_DEV_CKD_CURREC: SR_READ_VALUE(file, len, &dev->ckdcurrec, sizeof(dev->ckdcurrec)); break; case SR_DEV_CKD_CURKL: SR_READ_VALUE(file, len, &dev->ckdcurkl, sizeof(dev->ckdcurkl)); break; case SR_DEV_CKD_ORIENT: SR_READ_VALUE(file, len, &dev->ckdorient, sizeof(dev->ckdorient)); break; case SR_DEV_CKD_CUROPER: SR_READ_VALUE(file, len, &dev->ckdcuroper, sizeof(dev->ckdcuroper)); break; case SR_DEV_CKD_CURDL: SR_READ_VALUE(file, len, &dev->ckdcurdl, sizeof(dev->ckdcurdl)); break; case SR_DEV_CKD_REM: SR_READ_VALUE(file, len, &dev->ckdrem, sizeof(dev->ckdrem)); break; case SR_DEV_CKD_POS: SR_READ_VALUE(file, len, &dev->ckdpos, sizeof(dev->ckdpos)); break; case SR_DEV_CKD_DXBLKSZ: SR_READ_VALUE(file, len, &dev->ckdxblksz, sizeof(dev->ckdxblksz)); break; case SR_DEV_CKD_DXBCYL: SR_READ_VALUE(file, len, &dev->ckdxbcyl, sizeof(dev->ckdxbcyl)); break; case SR_DEV_CKD_DXBHEAD: SR_READ_VALUE(file, len, &dev->ckdxbhead, sizeof(dev->ckdxbhead)); break; case SR_DEV_CKD_DXECYL: SR_READ_VALUE(file, len, &dev->ckdxecyl, sizeof(dev->ckdxecyl)); break; case SR_DEV_CKD_DXEHEAD: SR_READ_VALUE(file, len, &dev->ckdxehead, sizeof(dev->ckdxehead)); break; case SR_DEV_CKD_DXFMASK: SR_READ_VALUE(file, len, &dev->ckdfmask, sizeof(dev->ckdfmask)); break; case SR_DEV_CKD_DXGATTR: SR_READ_VALUE(file, len, &dev->ckdxgattr, sizeof(dev->ckdxgattr)); break; case SR_DEV_CKD_LRTRANLF: SR_READ_VALUE(file, len, &dev->ckdltranlf, sizeof(dev->ckdltranlf)); break; case SR_DEV_CKD_LROPER: SR_READ_VALUE(file, len, &dev->ckdloper, sizeof(dev->ckdloper)); break; case SR_DEV_CKD_LRAUX: SR_READ_VALUE(file, len, &dev->ckdlaux, sizeof(dev->ckdlaux)); break; case SR_DEV_CKD_LRCOUNT: SR_READ_VALUE(file, len, &dev->ckdltranlf, sizeof(dev->ckdltranlf)); break; case SR_DEV_CKD_3990: SR_READ_VALUE(file, len, &rc, sizeof(rc)); dev->ckd3990 = rc; break; case SR_DEV_CKD_XTDEF: SR_READ_VALUE(file, len, &rc, sizeof(rc)); dev->ckdxtdef = rc; break; case SR_DEV_CKD_SETFM: SR_READ_VALUE(file, len, &rc, sizeof(rc)); dev->ckdsetfm = rc; break; case SR_DEV_CKD_LOCAT: SR_READ_VALUE(file, len, &rc, sizeof(rc)); dev->ckdlocat = rc; break; case SR_DEV_CKD_SPCNT: SR_READ_VALUE(file, len, &rc, sizeof(rc)); dev->ckdspcnt = rc; break; case SR_DEV_CKD_SEEK: SR_READ_VALUE(file, len, &rc, sizeof(rc)); dev->ckdseek = rc; break; case SR_DEV_CKD_SKCYL: SR_READ_VALUE(file, len, &rc, sizeof(rc)); dev->ckdskcyl = rc; break; case SR_DEV_CKD_RECAL: SR_READ_VALUE(file, len, &rc, sizeof(rc)); dev->ckdrecal = rc; break; case SR_DEV_CKD_RDIPL: SR_READ_VALUE(file, len, &rc, sizeof(rc)); dev->ckdrdipl = rc; break; case SR_DEV_CKD_XMARK: SR_READ_VALUE(file, len, &rc, sizeof(rc)); dev->ckdxmark = rc; break; case SR_DEV_CKD_HAEQ: SR_READ_VALUE(file, len, &rc, sizeof(rc)); dev->ckdhaeq = rc; break; case SR_DEV_CKD_IDEQ: SR_READ_VALUE(file, len, &rc, sizeof(rc)); dev->ckdideq = rc; break; case SR_DEV_CKD_KYEQ: SR_READ_VALUE(file, len, &rc, sizeof(rc)); dev->ckdkyeq = rc; break; case SR_DEV_CKD_WCKD: SR_READ_VALUE(file, len, &rc, sizeof(rc)); dev->ckdwckd = rc; break; case SR_DEV_CKD_TRKOF: SR_READ_VALUE(file, len, &rc, sizeof(rc)); dev->ckdtrkof = rc; break; case SR_DEV_CKD_SSI: SR_READ_VALUE(file, len, &rc, sizeof(rc)); dev->ckdssi = rc; break; case SR_DEV_CKD_WRHA: SR_READ_VALUE(file, len, &rc, sizeof(rc)); dev->ckdwrha = rc; break; default: SR_READ_SKIP(file, len); break; } /* switch (key) */ } while ((key & SR_DEV_MASK) == SR_DEV_CKD); return 0; } /*-------------------------------------------------------------------*/ /* Build sense data */ /*-------------------------------------------------------------------*/ void ckd_build_sense ( DEVBLK *dev, BYTE sense0, BYTE sense1, BYTE sense2, BYTE format, BYTE message ) { int shift; /* num of bits to shift left 'high cyl' in sense6 */ /* Clear the sense bytes */ memset (dev->sense, 0, sizeof(dev->sense)); /* Sense bytes 0-2 are specified by caller */ dev->sense[0] = sense0; dev->sense[1] = sense1; dev->sense[2] = sense2; /* Sense byte 3 contains the residual locate record count if imprecise ending is indicated in sense byte 1 */ if (sense1 & SENSE1_IE) { if (dev->ckdtrkof) dev->sense[3] = dev->ckdcuroper; else dev->sense[3] = dev->ckdlcount; } /* Sense byte 4 is the physical device address */ dev->sense[4] = 0; if (dev->devtype == 0x2305) { /* 0x40=ONLINE 0x04=END OF CYL */ dev->sense[3] = (((dev->sense[1]) & 0x20) >> 3) | 0x40; } if (dev->devtype == 0x2311) { /* 0x80=READY, 0x40=ONLINE 0x08=ONLINE 0x04=END OF CYL */ dev->sense[3] = (((dev->sense[1]) & 0x20) >> 3) | 0xC8; } if (dev->devtype == 0x2314) { /* 0x40=ONLINE 0x04=END OF CYL */ dev->sense[3] = (((dev->sense[1]) & 0x20) >> 3) | 0x40; } if (dev->devtype == 0x3330) { /* bits 0-1 = controller address */ /* bits 2-7: drive A = 111000, B = 110001, ... H = 000111 */ dev->sense[4] = (dev->devnum & 0x07) | ((~(dev->devnum) & 0x07) << 3); } if (dev->devtype == 0x3340) { /* X'01' = 35 MB drive, X'02' = 70 MB drive (same as 'model') */ /* X'80' RPS feature installed */ dev->sense[2] |= 0x80 | dev->devid[6]; /* RPS + model */ /* drive A = bit 0 (0x80), ... drive H = bit 7 (0x01) */ dev->sense[4] = 0x80 >> (dev->devnum & 0x07); } if (dev->devtype == 0x3350) { /* drive 0 = bit 0 (0x80), ... drive 7 = bit 7 (0x01) */ dev->sense[4] = 0x80 >> (dev->devnum & 0x07); } if (dev->devtype == 0x3375) { /* bits 3-4 = controller address, bits 5-7 = device address */ dev->sense[4] = dev->devnum & 0x07; } if (dev->devtype == 0x3380) { /* bits 4-7 = device address */ dev->sense[4] = dev->devnum & 0x0F; } /* Sense byte 5 contains bits 8-15 of the cylinder address and sense byte 6 contains bits 4-7 of the cylinder address followed by bits 12-15 of the head address, unless the device has more than 4095 cylinders, in which case sense bytes 5 and 6 both contain X'FF' */ if (dev->ckdcyls > 4095) { dev->sense[5] = 0xFF; dev->sense[6] = 0xFF; } else { if ((dev->devtype == 0x2311 ) || (dev->devtype == 0x2314 ) || (dev->devtype == 0x2305 )) { } else { dev->sense[5] = dev->ckdcurcyl & 0xFF; /* sense byte 6 bits c = cyl high byte, h=head */ /* 0 1 2 3 4 5 6 7 shift */ /* 3330-1 - c - h h h h h 6 */ /* 3330-11 3350 - c c h h h h h 5 */ /* 3340 - c c - h h h h 5 */ /* 3375 c c - - h h h h 6 */ /* 3380 c c c c h h h h 4 */ switch (dev->devtype) { case 0x3330: if (dev->devid[6] == 0x01) shift = 6; /* 3330-1 */ else shift = 5; /* 3330-11 */ case 0x3340: case 0x3350: shift = 5; case 0x3375: shift = 6; default: shift = 4; } dev->sense[6] = ( (dev->ckdcurcyl >> 8) << shift ) | (dev->ckdcurhead & 0x1F); } } /* Sense byte 7 contains the format code and message type */ dev->sense[7] = (format << 4) | (message & 0x0F); /* Sense bytes 8-23 depend on the format code */ switch (format) { case FORMAT_4: /* Data check */ case FORMAT_5: /* Data check with displacement information */ /* Sense bytes 8-12 contain the CCHHR of the record in error */ dev->sense[8] = dev->ckdcurcyl >> 8; dev->sense[9] = dev->ckdcurcyl & 0xFF; dev->sense[10] = dev->ckdcurhead >> 8; dev->sense[11] = dev->ckdcurhead & 0xFF; dev->sense[12] = dev->ckdcurrec; break; } /* end switch(format) */ /* Sense byte 27 bit 0 indicates 24-byte compatability sense data*/ dev->sense[27] = 0x80; /* Sense bytes 29-30 contain the cylinder address */ dev->sense[29] = dev->ckdcurcyl >> 8; dev->sense[30] = dev->ckdcurcyl & 0xFF; /* Sense byte 31 contains the head address */ dev->sense[31] = dev->ckdcurhead & 0xFF; } /* end function ckd_build_sense */ /*-------------------------------------------------------------------*/ /* Seek to a specified cylinder and head */ /*-------------------------------------------------------------------*/ static int ckd_seek ( DEVBLK *dev, int cyl, int head, CKDDASD_TRKHDR *trkhdr, BYTE *unitstat ) { int rc; /* Return code */ logdevtr (dev, _("HHCDA038I seeking to cyl %d head %d\n"), cyl, head); /* Read the track image */ rc = ckd_read_cchh (dev, cyl, head, unitstat); if (rc < 0) return -1; /* Set device orientation fields */ dev->ckdcurcyl = cyl; dev->ckdcurhead = head; dev->ckdcurrec = 0; dev->ckdcurkl = 0; dev->ckdcurdl = 0; dev->ckdrem = 0; dev->ckdorient = CKDORIENT_INDEX; /* Copy the track header */ if (trkhdr) memcpy (trkhdr, &dev->buf[dev->bufoff], CKDDASD_TRKHDR_SIZE); /* Increment offset past the track header */ dev->bufoff += CKDDASD_TRKHDR_SIZE; return 0; } /* end function ckd_seek */ /*-------------------------------------------------------------------*/ /* Advance to next track for multitrack operation */ /*-------------------------------------------------------------------*/ static int mt_advance ( DEVBLK *dev, BYTE *unitstat, int trks ) { int rc; /* Return code */ int cyl; /* Next cyl for multitrack */ int head; /* Next head for multitrack */ /* File protect error if not within domain of Locate Record and file mask inhibits seek and multitrack operations */ if (dev->ckdlcount == 0 && (dev->ckdfmask & CKDMASK_SKCTL) == CKDMASK_SKCTL_INHSMT) { logdevtr (dev, _("HHCDA039E MT advance error: " "locate record %d file mask %2.2X\n"), dev->ckdlcount, dev->ckdfmask); if (dev->ckdtrkof) ckd_build_sense (dev, 0, SENSE1_FP | SENSE1_IE, 0, 0, 0); else ckd_build_sense (dev, 0, SENSE1_FP, 0, 0, 0); *unitstat = CSW_CE | CSW_DE | CSW_UC; return -1; } /* End of cylinder error if not within domain of Locate Record and current track is last track of cylinder */ if (dev->ckdlcount == 0 && dev->ckdcurhead + trks >= dev->ckdheads) { if (dev->ckdtrkof) ckd_build_sense (dev, 0, SENSE1_EOC | SENSE1_IE, 0, 0, 0); else ckd_build_sense (dev, 0, SENSE1_EOC, 0, 0, 0); *unitstat = CSW_CE | CSW_DE | CSW_UC; return -1; } /* Advance to next track */ cyl = dev->ckdcurcyl; head = dev->ckdcurhead + trks; while (head >= dev->ckdheads) { head -= dev->ckdheads; cyl++; } logdevtr (dev, _("HHCDA040I MT advance to cyl %d head %d\n"), cyl, head); /* File protect error if next track is outside the limits of the device or outside the defined extent */ if ( EXTENT_CHECK(dev, cyl, head) ) { if (dev->ckdtrkof) ckd_build_sense (dev, 0, SENSE1_FP | SENSE1_IE, 0, 0, 0); else ckd_build_sense (dev, 0, SENSE1_FP, 0, 0, 0); *unitstat = CSW_CE | CSW_DE | CSW_UC; return -1; } /* Seek to next track */ rc = ckd_seek (dev, cyl, head, NULL, unitstat); if (rc < 0) return -1; /* Successful return */ return 0; } /* end function mt_advance */ /*-------------------------------------------------------------------*/ /* Read count field */ /*-------------------------------------------------------------------*/ static int ckd_read_count ( DEVBLK *dev, BYTE code, CKDDASD_RECHDR *rechdr, BYTE *unitstat) { int rc; /* Return code */ int skipr0 = 0; /* 1=Skip record zero */ int cyl; /* Cylinder number for seek */ int head; /* Head number for seek */ char *orient[] = {"none", "index", "count", "key", "data", "eot"}; /* Skip record 0 for all operations except READ TRACK, READ R0, SEARCH ID EQUAL, SEARCH ID HIGH, SEARCH ID EQUAL OR HIGH, LOCATE RECORD, and WRITE CKD NEXT TRACK */ if (code != 0xDE && (code & 0x7F) != 0x16 && (code & 0x7F) != 0x31 && (code & 0x7F) != 0x51 && (code & 0x7F) != 0x71 && code != 0x47 && code != 0x4B && code != 0x9D) skipr0 = 1; logdevtr (dev, _("HHCDA041I read count orientation is %s\n"), orient[dev->ckdorient]); /* If orientation is at End-Of_Track then a multi-track advance failed previously during synchronous I/O */ if (dev->ckdorient == CKDORIENT_EOT) { rc = mt_advance (dev, unitstat, 1); if (rc < 0) return -1; } /* Search for next count field */ for ( ; ; ) { /* If oriented to count or key field, skip key and data */ if (dev->ckdorient == CKDORIENT_COUNT) dev->bufoff += dev->ckdcurkl + dev->ckdcurdl; else if (dev->ckdorient == CKDORIENT_KEY) dev->bufoff += dev->ckdcurdl; /* Make sure we don't copy past the end of the buffer */ if (dev->bufoff + CKDDASD_RECHDR_SIZE >= dev->bufoffhi) { /* Handle error condition */ logmsg (_("HHCDA042E attempt to read past end of track %d %d\n"), dev->bufoff, dev->bufoffhi); /* Set unit check with equipment check */ ckd_build_sense (dev, SENSE_EC, 0, 0, FORMAT_1, MESSAGE_0); *unitstat = CSW_CE | CSW_DE | CSW_UC; return -1; } /* Copy the record header (count field) */ memcpy (rechdr, &dev->buf[dev->bufoff], CKDDASD_RECHDR_SIZE); dev->bufoff += CKDDASD_RECHDR_SIZE; /* Set the device orientation fields */ dev->ckdcurrec = rechdr->rec; dev->ckdrem = 0; dev->ckdorient = CKDORIENT_COUNT; dev->ckdcurkl = rechdr->klen; dev->ckdcurdl = (rechdr->dlen[0] << 8) + rechdr->dlen[1]; dev->ckdtrkof = (rechdr->cyl[0] == 0xFF) ? 0 : rechdr->cyl[0] >> 7; logdevtr (dev, _("HHCDA043I cyl %d head %d record %d kl %d dl %d of %d\n"), dev->ckdcurcyl, dev->ckdcurhead, dev->ckdcurrec, dev->ckdcurkl, dev->ckdcurdl, dev->ckdtrkof); /* Skip record zero if user data record required */ if (skipr0 && rechdr->rec == 0) continue; /* Test for logical end of track and exit if not */ if (memcmp(rechdr, eighthexFF, 8) != 0) break; dev->ckdorient = CKDORIENT_EOT; /* For READ TRACK or READ MULTIPLE CKD, return with the end of track marker in the record header field */ if (code == 0xDE || code == 0x5E) break; /* End of track found, so terminate with no record found error if this is a LOCATE RECORD or WRITE CKD NEXT TRACK command; or if this is the second end of track in this channel program without an intervening read of the home address or data area and without an intervening write, sense, or control command -- -- except when multitrack READ or SEARCH [KEY?] command operates outside the domain of a locate record */ if (code == 0x47 || code == 0x4B || code == 0x9D || (dev->ckdxmark && !((dev->ckdlcount == 0) && ( (IS_CCW_READ(code) && (code&0x80)) || code==0xA9 || code==0xC9 || code==0xE9) ))) { ckd_build_sense (dev, 0, SENSE1_NRF, 0, 0, 0); *unitstat = CSW_CE | CSW_DE | CSW_UC; return -1; } /* Test for multitrack operation */ if ((code & 0x80) == 0) { /* If non-multitrack, return to start of current track */ cyl = dev->ckdcurcyl; head = dev->ckdcurhead; rc = ckd_seek (dev, cyl, head, NULL, unitstat); if (rc < 0) return -1; /* Set index marker found flag */ dev->ckdxmark = 1; } else { /* If multitrack, attempt to advance to next track */ rc = mt_advance (dev, unitstat, 1); if (rc < 0) return -1; /* Set index marker flag if non-search command */ if ((code & 0x7F) != 0x31 && (code & 0x7F) != 0x51 && (code & 0x7F) != 0x71 && (code & 0x7F) != 0x29 && (code & 0x7F) != 0x49 && (code & 0x7F) != 0x69) dev->ckdxmark = 1; } } /* end for */ return 0; } /* end function ckd_read_count */ /*-------------------------------------------------------------------*/ /* Read key field */ /*-------------------------------------------------------------------*/ static int ckd_read_key ( DEVBLK *dev, BYTE code, BYTE *buf, BYTE *unitstat) { int rc; /* Return code */ CKDDASD_RECHDR rechdr; /* CKD record header */ /* If not oriented to count field, read next count field */ if (dev->ckdorient != CKDORIENT_COUNT) { rc = ckd_read_count (dev, code, &rechdr, unitstat); if (rc < 0) return rc; } logdevtr (dev, _("HHCDA044I read key %d bytes\n"), dev->ckdcurkl); /* Read key field */ if (dev->ckdcurkl > 0) { if (dev->bufoffhi - dev->bufoff < dev->ckdcurkl) { /* Handle error condition */ logmsg (_("ckddasd: attempt to read past end of track\n")); /* Set unit check with equipment check */ ckd_build_sense (dev, SENSE_EC, 0, 0, FORMAT_1, MESSAGE_0); *unitstat = CSW_CE | CSW_DE | CSW_UC; return -1; } memcpy (buf, &dev->buf[dev->bufoff], dev->ckdcurkl); dev->bufoff += dev->ckdcurkl; } /* Set the device orientation fields */ dev->ckdrem = 0; dev->ckdorient = CKDORIENT_KEY; return 0; } /* end function ckd_read_key */ /*-------------------------------------------------------------------*/ /* Read data field */ /*-------------------------------------------------------------------*/ static int ckd_read_data ( DEVBLK *dev, BYTE code, BYTE *buf, BYTE *unitstat) { int rc; /* Return code */ CKDDASD_RECHDR rechdr; /* Record header */ /* If not oriented to count or key field, read next count field */ if (dev->ckdorient != CKDORIENT_COUNT && dev->ckdorient != CKDORIENT_KEY) { rc = ckd_read_count (dev, code, &rechdr, unitstat); if (rc < 0) return rc; } /* If oriented to count field, skip the key field */ if (dev->ckdorient == CKDORIENT_COUNT) dev->bufoff += dev->ckdcurkl; logdevtr (dev, _("HHCDA045I read data %d bytes\n"), dev->ckdcurdl); /* Read data field */ if (dev->ckdcurdl > 0) { if (dev->bufoff + dev->ckdcurdl >= dev->bufoffhi) { /* Handle error condition */ logmsg (_("HHCDA046E attempt to read past end of track\n")); /* Set unit check with equipment check */ ckd_build_sense (dev, SENSE_EC, 0, 0, FORMAT_1, MESSAGE_0); *unitstat = CSW_CE | CSW_DE | CSW_UC; return -1; } memcpy (buf, &dev->buf[dev->bufoff], dev->ckdcurdl); dev->bufoff += dev->ckdcurdl; } /* Set the device orientation fields */ dev->ckdrem = 0; dev->ckdorient = CKDORIENT_DATA; return 0; } /* end function ckd_read_data */ /*-------------------------------------------------------------------*/ /* Erase remainder of track */ /*-------------------------------------------------------------------*/ static int ckd_erase ( DEVBLK *dev, BYTE *buf, int len, int *size, BYTE *unitstat) { int rc; /* Return code */ CKDDASD_RECHDR rechdr; /* CKD record header */ int keylen; /* Key length */ int datalen; /* Data length */ int ckdlen; /* Count+key+data length */ /* If oriented to count or key field, skip key and data */ if (dev->ckdorient == CKDORIENT_COUNT) dev->bufoff += dev->ckdcurkl + dev->ckdcurdl; else if (dev->ckdorient == CKDORIENT_KEY) dev->bufoff += dev->ckdcurdl; /* Copy the count field from the buffer */ memset (&rechdr, 0, CKDDASD_RECHDR_SIZE); memcpy (&rechdr, buf, (len < CKDDASD_RECHDR_SIZE) ? len : CKDDASD_RECHDR_SIZE); /* Extract the key length and data length */ keylen = rechdr.klen; datalen = (rechdr.dlen[0] << 8) + rechdr.dlen[1]; /* Calculate total count key and data size */ ckdlen = CKDDASD_RECHDR_SIZE + keylen + datalen; /* Check that there is enough space on the current track to contain the complete erase plus an end of track marker */ if (dev->bufoff + ckdlen + 8 >= dev->bufoffhi) { /* Unit check with invalid track format */ ckd_build_sense (dev, 0, SENSE1_ITF, 0, 0, 0); *unitstat = CSW_CE | CSW_DE | CSW_UC; return -1; } /* Logically erase rest of track by writing end of track marker */ rc = (dev->hnd->write) (dev, dev->bufcur, dev->bufoff, eighthexFF, 8, unitstat); if (rc < 0) return -1; /* Return total count key and data size */ *size = ckdlen; /* Set the device orientation fields */ dev->ckdrem = 0; dev->ckdorient = CKDORIENT_DATA; return 0; } /* end function ckd_erase */ /*-------------------------------------------------------------------*/ /* Write count key and data fields */ /*-------------------------------------------------------------------*/ static int ckd_write_ckd ( DEVBLK *dev, BYTE *buf, int len, BYTE *unitstat, BYTE trk_ovfl) { int rc; /* Return code */ CKDDASD_RECHDR rechdr; /* CKD record header */ int recnum; /* Record number */ int keylen; /* Key length */ int datalen; /* Data length */ int ckdlen; /* Count+key+data length */ /* If oriented to count or key field, skip key and data */ if (dev->ckdorient == CKDORIENT_COUNT) dev->bufoff += dev->ckdcurkl + dev->ckdcurdl; else if (dev->ckdorient == CKDORIENT_KEY) dev->bufoff += dev->ckdcurdl; /* Copy the count field from the buffer */ memset (&rechdr, 0, CKDDASD_RECHDR_SIZE); memcpy (&rechdr, buf, (len < CKDDASD_RECHDR_SIZE) ? len : CKDDASD_RECHDR_SIZE); /* Extract the record number, key length and data length */ recnum = rechdr.rec; keylen = rechdr.klen; datalen = (rechdr.dlen[0] << 8) + rechdr.dlen[1]; /* Calculate total count key and data size */ ckdlen = CKDDASD_RECHDR_SIZE + keylen + datalen; if (dev->bufoff + ckdlen + 8 >= dev->bufoffhi) { /* Unit check with invalid track format */ ckd_build_sense (dev, 0, SENSE1_ITF, 0, 0, 0); *unitstat = CSW_CE | CSW_DE | CSW_UC; return -1; } /* Pad the I/O buffer with zeroes if necessary */ while (len < ckdlen) buf[len++] = '\0'; logdevtr (dev, _("HHCDA047I writing cyl %d head %d record %d kl %d dl %d\n"), dev->ckdcurcyl, dev->ckdcurhead, recnum, keylen, datalen); /* Set track overflow flag if called for */ if (trk_ovfl) { logdevtr (dev, _("HHCDA048I setting track overflow flag for " "cyl %d head %d record %d\n"), dev->ckdcurcyl, dev->ckdcurhead, recnum); buf[0] |= 0x80; } /* Write count key and data */ rc = (dev->hnd->write) (dev, dev->bufcur, dev->bufoff, buf, ckdlen, unitstat); if (rc < 0) return -1; dev->bufoff += ckdlen; /* Clear track overflow flag if we set it above */ if (trk_ovfl) { buf[0] &= 0x7F; } /* Logically erase rest of track by writing end of track marker */ rc = (dev->hnd->write) (dev, dev->bufcur, dev->bufoff, eighthexFF, 8, unitstat); if (rc < 0) return -1; /* Set the device orientation fields */ dev->ckdcurrec = recnum; dev->ckdcurkl = keylen; dev->ckdcurdl = datalen; dev->ckdrem = 0; dev->ckdorient = CKDORIENT_DATA; dev->ckdtrkof = trk_ovfl & 1; return 0; } /* end function ckd_write_ckd */ /*-------------------------------------------------------------------*/ /* Write key and data fields */ /*-------------------------------------------------------------------*/ static int ckd_write_kd ( DEVBLK *dev, BYTE *buf, int len, BYTE *unitstat) { int rc; /* Return code */ int kdlen; /* Key+data length */ /* Unit check if not oriented to count area */ if (dev->ckdorient != CKDORIENT_COUNT) { logmsg (_("HHCDA049E Write KD orientation error\n")); ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; return -1; } /* Calculate total key and data size */ kdlen = dev->ckdcurkl + dev->ckdcurdl; /* Pad the I/O buffer with zeroes if necessary */ while (len < kdlen) buf[len++] = '\0'; logdevtr (dev, _("HHCDA050I updating cyl %d head %d record %d kl %d dl %d\n"), dev->ckdcurcyl, dev->ckdcurhead, dev->ckdcurrec, dev->ckdcurkl, dev->ckdcurdl); /* Write key and data */ rc = (dev->hnd->write) (dev, dev->bufcur, dev->bufoff, buf, kdlen, unitstat); if (rc < 0) return -1; dev->bufoff += kdlen; /* Set the device orientation fields */ dev->ckdrem = 0; dev->ckdorient = CKDORIENT_DATA; return 0; } /* end function ckd_write_kd */ /*-------------------------------------------------------------------*/ /* Write data field */ /*-------------------------------------------------------------------*/ static int ckd_write_data ( DEVBLK *dev, BYTE *buf, int len, BYTE *unitstat) { int rc; /* Return code */ /* Unit check if not oriented to count or key areas */ if (dev->ckdorient != CKDORIENT_COUNT && dev->ckdorient != CKDORIENT_KEY) { logmsg (_("HHCDA051E Write data orientation error\n")); ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; return -1; } /* If oriented to count field, skip the key field */ if (dev->ckdorient == CKDORIENT_COUNT) dev->bufoff += dev->ckdcurkl; /* Pad the I/O buffer with zeroes if necessary */ while (len < dev->ckdcurdl) buf[len++] = '\0'; logdevtr (dev, _("HHCDA052I updating cyl %d head %d record %d dl %d\n"), dev->ckdcurcyl, dev->ckdcurhead, dev->ckdcurrec, dev->ckdcurdl); /* Write data */ rc = (dev->hnd->write) (dev, dev->bufcur, dev->bufoff, buf, dev->ckdcurdl, unitstat); if (rc < 0) return -1; dev->bufoff += dev->ckdcurdl; /* Set the device orientation fields */ dev->ckdrem = 0; dev->ckdorient = CKDORIENT_DATA; return 0; } /* end function ckd_write_data */ /*-------------------------------------------------------------------*/ /* Execute a Channel Command Word */ /*-------------------------------------------------------------------*/ void ckddasd_execute_ccw ( DEVBLK *dev, BYTE code, BYTE flags, BYTE chained, U16 count, BYTE prevcode, int ccwseq, BYTE *iobuf, BYTE *more, BYTE *unitstat, U16 *residual ) { int rc; /* Return code */ int i, j; /* Loop index */ CKDDASD_TRKHDR trkhdr; /* CKD track header (HA) */ CKDDASD_RECHDR rechdr; /* CKD record header (count) */ int size; /* Number of bytes available */ int num; /* Number of bytes to move */ int offset; /* Offset into buf for I/O */ int bin; /* Bin number */ int cyl; /* Cylinder number */ int head; /* Head number */ BYTE cchhr[5]; /* Search argument */ BYTE sector; /* Sector number */ BYTE key[256]; /* Key for search operations */ BYTE trk_ovfl; /* == 1 if track ovfl write */ /* If this is a data-chained READ, then return any data remaining in the buffer which was not used by the previous CCW */ if (chained & CCW_FLAGS_CD) { memmove (iobuf, iobuf + dev->ckdpos, dev->ckdrem); num = (count < dev->ckdrem) ? count : dev->ckdrem; *residual = count - num; if (count < dev->ckdrem) *more = 1; dev->ckdrem -= num; dev->ckdpos = num; *unitstat = CSW_CE | CSW_DE; return; } /* Command reject if data chaining and command is not READ */ if ((flags & CCW_FLAGS_CD) && code != 0x02 && code != 0x5E && (code & 0x7F) != 0x1E && (code & 0x7F) != 0x1A && (code & 0x7F) != 0x16 && (code & 0x7F) != 0x12 && (code & 0x7F) != 0x0E && (code & 0x7F) != 0x06) { logmsg(_("HHCDA053E Data chaining not supported for CCW %2.2X\n"), code); ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_1); *unitstat = CSW_CE | CSW_DE | CSW_UC; return; } /* Reset flags at start of CCW chain */ if (chained == 0 && !dev->syncio_retry) { dev->ckdlocat = 0; dev->ckdspcnt = 0; dev->ckdseek = 0; dev->ckdskcyl = 0; dev->ckdrecal = 0; dev->ckdrdipl = 0; dev->ckdfmask = 0; dev->ckdxmark = 0; dev->ckdhaeq = 0; dev->ckdideq = 0; dev->ckdkyeq = 0; dev->ckdwckd = 0; dev->ckdlcount = 0; dev->ckdlmask = 0; dev->ckdtrkof = 0; /* ISW20030819-1 : Clear Write HA flag */ dev->ckdwrha = 0; dev->ckdssdlen = 0; /* Set initial define extent parameters */ dev->ckdxtdef = 0; dev->ckdsetfm = 0; dev->ckdfmask = 0; dev->ckdxgattr = 0; dev->ckdxblksz = 0; dev->ckdxbcyl = 0; dev->ckdxbhead = 0; dev->ckdxecyl = dev->ckdcyls - 1; dev->ckdxehead = dev->ckdheads - 1; } /* Reset ckdlmask on retry of LRE */ else if (dev->syncio_retry && code == 0x4B) dev->ckdlmask = 0; dev->syncio_retry = 0; /* Reset index marker flag if sense or control command, or any write command (other search ID or search key), or any read command except read sector -- -- and except single track Read Count */ if (IS_CCW_SENSE(code) || IS_CCW_CONTROL(code) || (IS_CCW_WRITE(code) && (code & 0x7F) != 0x31 && (code & 0x7F) != 0x51 && (code & 0x7F) != 0x71 && (code & 0x7F) != 0x29 && (code & 0x7F) != 0x49 && (code & 0x7F) != 0x69) || (IS_CCW_READ(code) && code != 0x12 && (code & 0x7F) != 0x22)) dev->ckdxmark = 0; /* Note current operation for track overflow sense byte 3 */ dev->ckdcuroper = (IS_CCW_READ(code)) ? 6 : ((IS_CCW_WRITE(code)) ? 5 : 0); /* If subsystem data has been prepared in the channel buffer by a previous Perform Subsystem Function command, generate a command reject if next command is not Read Subsystem Data */ if (dev->ckdssdlen > 0 && code != 0x3E) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; return; } /* If within Locate Record Extended domain and not RT command reject with status that includes Unit Check (Command Reject, format X'02', Invalid Command Sequence) */ if (dev->ckdlmask && code != 0xDE) { ckd_build_sense (dev, SENSE_CR, 0, 0,FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; return; } /* Process depending on CCW opcode */ switch (code) { case 0x02: /*---------------------------------------------------------------*/ /* READ IPL */ /*---------------------------------------------------------------*/ /* Command reject if preceded by a Define Extent or Set File Mask, or within the domain of a Locate Record */ if (dev->ckdxtdef || dev->ckdsetfm || dev->ckdlcount > 0) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* No more define extend allowed */ dev->ckdxtdef = 1; dev->ckdsetfm = 1; /* Set locate record parameters */ dev->ckdloper = CKDOPER_ORIENT_DATA | CKDOPER_RDDATA; dev->ckdlaux = 0; dev->ckdlcount = 2; dev->ckdltranlf = 0; /* Seek to start of cylinder zero track zero */ rc = ckd_seek (dev, 0, 0, &trkhdr, unitstat); if (rc < 0) break; /* Read count field for first record following R0 */ rc = ckd_read_count (dev, code, &rechdr, unitstat); if (rc < 0) break; /* Calculate number of bytes to read and set residual count */ size = dev->ckdcurdl; num = (count < size) ? count : size; *residual = count - num; if (count < size) *more = 1; /* Read data field */ rc = ckd_read_data (dev, code, iobuf, unitstat); if (rc < 0) break; /* Set command processed flag */ dev->ckdrdipl = 1; /* Save size and offset of data not used by this CCW */ dev->ckdrem = size - num; dev->ckdpos = num; /* Return unit exception if data length is zero */ if (dev->ckdcurdl == 0) *unitstat = CSW_CE | CSW_DE | CSW_UX; else *unitstat = CSW_CE | CSW_DE; break; case 0x03: /*---------------------------------------------------------------*/ /* CONTROL NO-OPERATION */ /*---------------------------------------------------------------*/ /* Command reject if within the domain of a Locate Record */ if (dev->ckdlcount > 0) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Return normal status */ *unitstat = CSW_CE | CSW_DE; break; case 0x17: /*---------------------------------------------------------------*/ /* RESTORE */ /*---------------------------------------------------------------*/ /* Command reject if within the domain of a Locate Record */ if (dev->ckdlcount > 0) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Return normal status */ *unitstat = CSW_CE | CSW_DE; break; case 0xA6: //FIXME: 0xA6 ccw is undoc'd. We are treating it as 0x86 except // we will allow a DX ccw to follow. case 0x06: case 0x86: /*---------------------------------------------------------------*/ /* READ DATA */ /*---------------------------------------------------------------*/ /* For 3990, command reject if not preceded by Seek, Seek Cyl, Locate Record, Read IPL, or Recalibrate command */ if (dev->ckd3990 && dev->ckdseek == 0 && dev->ckdskcyl == 0 && dev->ckdlocat == 0 && dev->ckdrdipl == 0 && dev->ckdrecal == 0) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Check operation code if within domain of a Locate Record */ if (dev->ckdlcount > 0) { if (!((dev->ckdloper & CKDOPER_CODE) == CKDOPER_RDDATA || (dev->ckdloper & CKDOPER_CODE) == CKDOPER_RDANY || (dev->ckdloper & CKDOPER_CODE) == CKDOPER_READ)) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } } /* If not oriented to count or key field, read next count */ if (dev->ckdorient != CKDORIENT_COUNT && dev->ckdorient != CKDORIENT_KEY) { rc = ckd_read_count (dev, code, &rechdr, unitstat); if (rc < 0) break; } /* Calculate number of bytes to read and set residual count */ size = dev->ckdcurdl; num = (count < size) ? count : size; *residual = count - num; if (count < size) *more = 1; offset = 0; /* Read data field */ rc = ckd_read_data (dev, code, iobuf, unitstat); if (rc < 0) break; /* If track overflow, keep reading */ while (dev->ckdtrkof) { /* Advance to next track */ rc = mt_advance (dev, unitstat, 1); if (rc < 0) break; /* Read the first count field */ rc = ckd_read_count (dev, code, &rechdr, unitstat); if (rc < 0) break; /* Skip the key field if present */ if (dev->ckdcurkl > 0) dev->bufoff += dev->ckdcurkl; /* Set offset into buffer for this read */ offset += num; /* Account for size of this overflow record */ size = dev->ckdcurdl; num = (*residual < size) ? *residual : size; if (*residual < size) *more = 1; else *more = 0; *residual -= num; /* Read the next data field */ rc = ckd_read_data (dev, code, iobuf+offset, unitstat); if (rc < 0) break; } /* Bail out if track overflow produced I/O error */ if (rc < 0) break; /* Save size and offset of data not used by this CCW */ dev->ckdrem = size - num; dev->ckdpos = num; /* Return unit exception if data length is zero */ if (dev->ckdcurdl == 0) *unitstat = CSW_CE | CSW_DE | CSW_UX; else *unitstat = CSW_CE | CSW_DE; break; case 0x0E: case 0x8E: /*---------------------------------------------------------------*/ /* READ KEY AND DATA */ /*---------------------------------------------------------------*/ /* For 3990, command reject if not preceded by Seek, Seek Cyl, Locate Record, Read IPL, or Recalibrate command */ if (dev->ckd3990 && dev->ckdseek == 0 && dev->ckdskcyl == 0 && dev->ckdlocat == 0 && dev->ckdrdipl == 0 && dev->ckdrecal == 0) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Check operation code if within domain of a Locate Record */ if (dev->ckdlcount > 0) { /* * 3990 reference says LRE CKDOPER_RDANY "must be followed * by a sequence of multi-track Read Count, Read Count Key * and Data, or Read Data commands". That is, it doesn't * mention Read Key and Data. */ if (!((dev->ckdloper & CKDOPER_CODE) == CKDOPER_RDDATA /* || (dev->ckdloper & CKDOPER_CODE) == CKDOPER_RDANY */ || (dev->ckdloper & CKDOPER_CODE) == CKDOPER_READ)) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } } /* If not oriented to count field, read next count */ if (dev->ckdorient != CKDORIENT_COUNT) { rc = ckd_read_count (dev, code, &rechdr, unitstat); if (rc < 0) break; } /* Calculate number of bytes to read and set residual count */ size = dev->ckdcurkl + dev->ckdcurdl; num = (count < size) ? count : size; *residual = count - num; if (count < size) *more = 1; offset = dev->ckdcurkl; /* Read key field */ rc = ckd_read_key (dev, code, iobuf, unitstat); if (rc < 0) break; /* Read data field */ rc = ckd_read_data (dev, code, iobuf+dev->ckdcurkl, unitstat); if (rc < 0) break; /* If track overflow, keep reading */ while (dev->ckdtrkof) { /* Advance to next track */ rc = mt_advance (dev, unitstat, 1); if (rc < 0) break; /* Read the first count field */ rc = ckd_read_count (dev, code, &rechdr, unitstat); if (rc < 0) break; /* Skip the key field if present */ if (dev->ckdcurkl > 0) dev->bufoff += dev->ckdcurkl; /* Set offset into buffer for this read */ offset += num; /* Account for size of this overflow record */ size = dev->ckdcurdl; num = (*residual < size) ? *residual : size; if (*residual < size) *more = 1; else *more = 0; *residual -= num; /* Read the next data field */ rc = ckd_read_data (dev, code, iobuf+offset, unitstat); if (rc < 0) break; } /* Bail out if track overflow produced I/O error */ if (rc < 0) break; /* Save size and offset of data not used by this CCW */ dev->ckdrem = size - num; dev->ckdpos = num; /* Return unit exception if data length is zero */ if (dev->ckdcurdl == 0) *unitstat = CSW_CE | CSW_DE | CSW_UX; else *unitstat = CSW_CE | CSW_DE; break; case 0x12: case 0x92: /*---------------------------------------------------------------*/ /* READ COUNT */ /*---------------------------------------------------------------*/ /* For 3990, command reject if not preceded by Seek, Seek Cyl, Locate Record, Read IPL, or Recalibrate command */ if (dev->ckd3990 && dev->ckdseek == 0 && dev->ckdskcyl == 0 && dev->ckdlocat == 0 && dev->ckdrdipl == 0 && dev->ckdrecal == 0) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Check operation code if within domain of a Locate Record */ if (dev->ckdlcount > 0) { if (!((dev->ckdloper & CKDOPER_CODE) == CKDOPER_RDDATA || (dev->ckdloper & CKDOPER_CODE) == CKDOPER_RDANY || (dev->ckdloper & CKDOPER_CODE) == CKDOPER_READ || ((dev->ckdloper & CKDOPER_CODE) == CKDOPER_WRITE && (dev->ckdlaux & CKDLAUX_RDCNTSUF) && dev->ckdlcount == 1))) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } } /* Read next count field */ rc = ckd_read_count (dev, code, &rechdr, unitstat); if (rc < 0) break; /* Calculate number of bytes to read and set residual count */ size = CKDDASD_RECHDR_SIZE; num = (count < size) ? count : size; *residual = count - num; if (count < size) *more = 1; /* Copy count field to I/O buffer */ memcpy (iobuf, &rechdr, CKDDASD_RECHDR_SIZE); /* Turn off track overflow flag in read record header */ *iobuf &= 0x7F; /* Save size and offset of data not used by this CCW */ dev->ckdrem = size - num; dev->ckdpos = num; /* Return normal status */ *unitstat = CSW_CE | CSW_DE; break; case 0x16: case 0x96: /*---------------------------------------------------------------*/ /* READ RECORD ZERO */ /*---------------------------------------------------------------*/ /* For 3990, command reject if not preceded by Seek, Seek Cyl, Locate Record, Read IPL, or Recalibrate command */ if (dev->ckd3990 && dev->ckdseek == 0 && dev->ckdskcyl == 0 && dev->ckdlocat == 0 && dev->ckdrdipl == 0 && dev->ckdrecal == 0) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Check operation code if within domain of a Locate Record */ if (dev->ckdlcount > 0) { if (!((dev->ckdloper & CKDOPER_CODE) == CKDOPER_RDDATA || ((dev->ckdloper & CKDOPER_CODE) == CKDOPER_READ && ((dev->ckdloper & CKDOPER_ORIENTATION) == CKDOPER_ORIENT_HOME || (dev->ckdloper & CKDOPER_ORIENTATION) == CKDOPER_ORIENT_INDEX )))) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } } /* For multitrack operation outside domain of a Locate Record, attempt to advance to the next track before reading R0 */ if ((code & 0x80) && dev->ckdlcount == 0) { rc = mt_advance (dev, unitstat, 1); if (rc < 0) break; } /* Seek to beginning of track */ rc = ckd_seek (dev, dev->ckdcurcyl, dev->ckdcurhead, &trkhdr, unitstat); if (rc < 0) break; /* Read the count field for record zero */ rc = ckd_read_count (dev, code, &rechdr, unitstat); if (rc < 0) break; /* Calculate number of bytes to read and set residual count */ size = CKDDASD_RECHDR_SIZE + dev->ckdcurkl + dev->ckdcurdl; num = (count < size) ? count : size; *residual = count - num; if (count < size) *more = 1; /* Copy count field to I/O buffer */ memcpy (iobuf, &rechdr, CKDDASD_RECHDR_SIZE); /* Turn off track overflow flag in read record header */ *iobuf &= 0x7F; /* Read key field */ rc = ckd_read_key (dev, code, iobuf + CKDDASD_RECHDR_SIZE, unitstat); if (rc < 0) break; /* Read data field */ rc = ckd_read_data (dev, code, iobuf + CKDDASD_RECHDR_SIZE + dev->ckdcurkl, unitstat); if (rc < 0) break; /* Save size and offset of data not used by this CCW */ dev->ckdrem = size - num; dev->ckdpos = num; /* Return unit exception if data length is zero */ if (dev->ckdcurdl == 0) *unitstat = CSW_CE | CSW_DE | CSW_UX; else *unitstat = CSW_CE | CSW_DE; break; case 0x1A: case 0x9A: /*---------------------------------------------------------------*/ /* READ HOME ADDRESS */ /*---------------------------------------------------------------*/ /* For 3990, command reject if not preceded by Seek, Seek Cyl, Locate Record, Read IPL, or Recalibrate command */ if (dev->ckd3990 && dev->ckdseek == 0 && dev->ckdskcyl == 0 && dev->ckdlocat == 0 && dev->ckdrdipl == 0 && dev->ckdrecal == 0) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Check operation code if within domain of a Locate Record */ if (dev->ckdlcount > 0) { if (!((dev->ckdloper & CKDOPER_CODE) == CKDOPER_RDDATA || ((dev->ckdloper & CKDOPER_CODE) == CKDOPER_READ && (dev->ckdloper & CKDOPER_ORIENTATION) == CKDOPER_ORIENT_INDEX ))) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } } /* For multitrack operation outside domain of a Locate Record, attempt to advance to the next track before reading HA */ if ((code & 0x80) && dev->ckdlcount == 0) { rc = mt_advance (dev, unitstat, 1); if (rc < 0) break; } /* Seek to beginning of track */ rc = ckd_seek (dev, dev->ckdcurcyl, dev->ckdcurhead, &trkhdr, unitstat); if (rc < 0) break; /* Calculate number of bytes to read and set residual count */ size = CKDDASD_TRKHDR_SIZE; num = (count < size) ? count : size; *residual = count - num; if (count < size) *more = 1; /* Copy home address field to I/O buffer */ memcpy (iobuf, &trkhdr, CKDDASD_TRKHDR_SIZE); /* Save size and offset of data not used by this CCW */ dev->ckdrem = size - num; dev->ckdpos = num; /* Return normal status */ *unitstat = CSW_CE | CSW_DE; break; case 0x19: /*---------------------------------------------------------------*/ /* WRITE HOME ADDRESS */ /*---------------------------------------------------------------*/ /* For 3990, command reject if not preceded by Seek, Seek Cyl, Locate Record, Read IPL, or Recalibrate command */ if (dev->ckd3990 && dev->ckdseek == 0 && dev->ckdskcyl == 0 && dev->ckdlocat == 0 && dev->ckdrdipl == 0 && dev->ckdrecal == 0) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Check operation code if within domain of a Locate Record */ if (dev->ckdlcount > 0) { if (!((dev->ckdloper & CKDOPER_CODE) == CKDOPER_RDDATA || ((dev->ckdloper & CKDOPER_CODE) == CKDOPER_READ && (dev->ckdloper & CKDOPER_ORIENTATION) == CKDOPER_ORIENT_INDEX ))) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } } /* File protected if file mask does not allow Write HA */ if ((dev->ckdfmask & CKDMASK_WRCTL) != CKDMASK_WRCTL_ALLWRT) { ckd_build_sense (dev, 0, SENSE1_FP, 0, 0, 0); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Seek to beginning of track */ rc = ckd_seek (dev, dev->ckdcurcyl, dev->ckdcurhead, &trkhdr, unitstat); if (rc < 0) break; /* Calculate number of bytes to write and set residual count */ size = CKDDASD_TRKHDR_SIZE; num = (count < size) ? count : size; /* FIXME: what devices want 5 bytes, what ones want 7, and what ones want 11? Do this right when we figure that out */ /* ISW20030819-1 Indicate WRHA performed */ dev->ckdwrha=1; *residual = 0; /* Return normal status */ *unitstat = CSW_CE | CSW_DE; break; case 0x1E: case 0x9E: /*---------------------------------------------------------------*/ /* READ COUNT KEY AND DATA */ /*---------------------------------------------------------------*/ /* For 3990, command reject if not preceded by Seek, Seek Cyl, Locate Record, Read IPL, or Recalibrate command */ if (dev->ckd3990 && dev->ckdseek == 0 && dev->ckdskcyl == 0 && dev->ckdlocat == 0 && dev->ckdrdipl == 0 && dev->ckdrecal == 0) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Check operation code if within domain of a Locate Record */ if (dev->ckdlcount > 0) { if (!((dev->ckdloper & CKDOPER_CODE) == CKDOPER_RDDATA || (dev->ckdloper & CKDOPER_CODE) == CKDOPER_RDANY || (dev->ckdloper & CKDOPER_CODE) == CKDOPER_READ)) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } } /* Read next count field */ rc = ckd_read_count (dev, code, &rechdr, unitstat); if (rc < 0) break; /* Calculate number of bytes to read and set residual count */ size = CKDDASD_RECHDR_SIZE + dev->ckdcurkl + dev->ckdcurdl; num = (count < size) ? count : size; *residual = count - num; if (count < size) *more = 1; offset = CKDDASD_RECHDR_SIZE + dev->ckdcurkl; /* Copy count field to I/O buffer */ memcpy (iobuf, &rechdr, CKDDASD_RECHDR_SIZE); /* Turn off track overflow flag in read record header */ *iobuf &= 0x7F; /* Read key field */ rc = ckd_read_key (dev, code, iobuf + CKDDASD_RECHDR_SIZE, unitstat); if (rc < 0) break; /* Read data field */ rc = ckd_read_data (dev, code, iobuf + CKDDASD_RECHDR_SIZE + dev->ckdcurkl, unitstat); if (rc < 0) break; /* If track overflow, keep reading */ while (dev->ckdtrkof) { /* Advance to next track */ rc = mt_advance (dev, unitstat, 1); if (rc < 0) break; /* Read the first count field */ rc = ckd_read_count (dev, code, &rechdr, unitstat); if (rc < 0) break; /* Skip the key field if present */ if (dev->ckdcurkl > 0) dev->bufoff += dev->ckdcurkl; /* Set offset into buffer for this read */ offset += num; /* Account for size of this overflow record */ size = dev->ckdcurdl; num = (*residual < size) ? *residual : size; if (*residual < size) *more = 1; else *more = 0; *residual -= num; /* Read the next data field */ rc = ckd_read_data (dev, code, iobuf+offset, unitstat); if (rc < 0) break; } /* Bail out if track overflow produced I/O error */ if (rc < 0) break; /* Save size and offset of data not used by this CCW */ dev->ckdrem = size - num; dev->ckdpos = num; /* Return unit exception if data length is zero */ if (dev->ckdcurdl == 0) *unitstat = CSW_CE | CSW_DE | CSW_UX; else *unitstat = CSW_CE | CSW_DE; break; case 0x5E: /*---------------------------------------------------------------*/ /* READ MULTIPLE COUNT KEY AND DATA */ /*---------------------------------------------------------------*/ /* For 3990, command reject if not preceded by Seek, Seek Cyl, Locate Record, Read IPL, or Recalibrate */ if (dev->ckd3990 && dev->ckdseek == 0 && dev->ckdskcyl == 0 && dev->ckdlocat == 0 && dev->ckdrdipl == 0 && dev->ckdrecal == 0) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Command reject if within the domain of a Locate Record */ if (dev->ckdlcount > 0) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Read records into the I/O buffer until end of track */ for (size = 0; ; ) { /* Read next count field */ rc = ckd_read_count (dev, code, &rechdr, unitstat); if (rc < 0) break; /* Exit if end of track marker was read */ if (memcmp (&rechdr, eighthexFF, 8) == 0) break; /* Copy count field to I/O buffer */ memcpy (iobuf + size, &rechdr, CKDDASD_RECHDR_SIZE); size += CKDDASD_RECHDR_SIZE; /* Turn off track overflow flag */ *(iobuf + size) &= 0x7F; /* Read key field */ rc = ckd_read_key (dev, code, iobuf + size, unitstat); if (rc < 0) break; size += dev->ckdcurkl; /* Read data field */ rc = ckd_read_data (dev, code, iobuf + size, unitstat); if (rc < 0) break; size += dev->ckdcurdl; } /* end for(size) */ /* Set the residual count */ num = (count < size) ? count : size; *residual = count - num; if (count < size) *more = 1; /* Save size and offset of data not used by this CCW */ dev->ckdrem = size - num; dev->ckdpos = num; /* Return normal status */ *unitstat = CSW_CE | CSW_DE; break; case 0xDE: /*---------------------------------------------------------------*/ /* READ TRACK */ /*---------------------------------------------------------------*/ /* Command reject if not within the domain of a Locate Record that specifies a read tracks operation */ if (dev->ckdlcount == 0 || (((dev->ckdloper & CKDOPER_CODE) != CKDOPER_RDTRKS) && ((dev->ckdloper & CKDOPER_CODE) != CKDOPER_RDTSET))) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Command reject if not chained from a Locate Record command or from another Read Track command */ if (chained == 0 || (prevcode != 0x47 && prevcode != 0x4B && prevcode != 0xDE)) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Advance to next track if chained from previous read track */ if (prevcode == 0xDE) { j = 1; /* Skip tracks while hi bit off in ckdlmask */ if (dev->ckdlmask) { while (!(dev->ckdlmask & 0x8000)) { j++; dev->ckdlmask <<= 1; } } rc = mt_advance (dev, unitstat, j); if (rc < 0) break; } /* Shift read track set mask left a bit */ dev->ckdlmask <<= 1; /* Read each record on the track into the I/O buffer */ for (size = 0; ; ) { /* Read next count field */ rc = ckd_read_count (dev, code, &rechdr, unitstat); if (rc < 0) break; /* Copy count field to I/O buffer */ memcpy (iobuf + size, &rechdr, CKDDASD_RECHDR_SIZE); size += CKDDASD_RECHDR_SIZE; /* Turn off track overflow flag */ *(iobuf+size) &= 0x7F; /* Exit if end of track marker was read */ if (memcmp (&rechdr, eighthexFF, 8) == 0) break; /* Read key field */ rc = ckd_read_key (dev, code, iobuf + size, unitstat); if (rc < 0) break; size += dev->ckdcurkl; /* Read data field */ rc = ckd_read_data (dev, code, iobuf + size, unitstat); if (rc < 0) break; size += dev->ckdcurdl; } /* end for(size) */ /* Set the residual count */ num = (count < size) ? count : size; *residual = count - num; if (count < size) *more = 1; /* Save size and offset of data not used by this CCW */ dev->ckdrem = size - num; dev->ckdpos = num; /* Return normal status */ *unitstat = CSW_CE | CSW_DE; break; case 0x27: /*---------------------------------------------------------------*/ /* PERFORM SUBSYSTEM FUNCTION */ /*---------------------------------------------------------------*/ /* If the control unit is not a 3990 then CCW code 0x27 is treated as a SEEK AND SET SECTOR (Itel 7330 controller) */ if (dev->ckd3990 == 0) goto seek_0x27; /* Command reject if within the domain of a Locate Record */ if (dev->ckdlcount > 0) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Use the order code to determine the required count */ num = (count < 2) ? 2 : (iobuf[0] == 0x10) ? 14 : (iobuf[0] == 0x11 || iobuf[0] == 0x18) ? 12 : (iobuf[0] == 0x12) ? 5 : (iobuf[0] == 0x13 || iobuf[0] == 0x14) ? 4 : (iobuf[0] == 0x16) ? 4 : (iobuf[0] == 0x1D) ? 66 : (iobuf[0] == 0xB0) ? 4 : 2; /* Command reject if count is less than required */ if (count < num) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_3); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Set residual count */ *residual = count - num; #if 0 /* Command reject if SSI active */ if(dev->ckdssi) { /* Reset SSI condition */ dev->ckdssi = 0; ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_F); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } #endif /* Process depending on order code in byte 0 of data */ switch (iobuf[0]) { case 0x18: /* Prepare for Read Subsystem Data */ /* Command reject if bytes 1-5 not zero */ if (memcmp(&iobuf[1], "\x00\x00\x00\x00\x00", 5) != 0) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_4); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Process suborder code in byte 6 of data */ switch (iobuf[6]) { case 0x00: /* Storage path status */ /* Prepare storage path status record */ memset (iobuf, 0x00, 16); iobuf[0] = 0xC0; /* Storage path valid and attached */ iobuf[1] = 0x80; /* Logical paths configured bitmap */ iobuf[2] = 0x00; /* Channels enabled bitmap */ iobuf[3] = 0x00; /* Channels fenced bitmap */ iobuf[16] = 1; /* #logical paths thru cluster 0 */ /* Indicate the length of subsystem data prepared */ dev->ckdssdlen = (dev->ckdcu->code==0x15) ? 24 : 16; break; case 0x01: /* Subsystem statistics */ /* Indicate the length of subsystem data prepared */ dev->ckdssdlen = (iobuf[8]==0x00) ? 96 : 192; /* Prepare subsystem statistics record */ memset (iobuf, 0x00, dev->ckdssdlen); iobuf[1] = dev->devnum & 0xFF; iobuf[94] = (myssid >> 8) & 0xff; iobuf[95] = myssid & 0xff; break; case 0x0E: /* Unit address configuration */ /* Prepare unit address configuration record */ memset (iobuf, 0x00, 512); /* 256 pairs (UA type, base UA) */ /* Indicate the length of subsystem data prepared */ dev->ckdssdlen = 512; break; case 0x41: /* Feature codes */ /* Prepare feature codes record */ memset (iobuf, 0x00, 256); /* Indicate the length of subsystem data prepared */ dev->ckdssdlen = 256; break; default: /* Unknown suborder code */ ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_4); *unitstat = CSW_CE | CSW_DE | CSW_UC; } /* end switch(iobuf[6]) */ break; case 0x1B: /* Set Special Intercept Condition */ /* Command reject if not the first command in the chain or indeed if preceded by any command at all apart from Suspend Multipath Reconnection */ if (ccwseq > 1 || (chained && prevcode != 0x5B)) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Command reject if flag byte is not zero */ if (iobuf[1] != 0x00) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_4); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Command reject if any command is chained from this command */ if (flags & CCW_FLAGS_CC) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Mark Set Special Intercept inactive */ dev->ckdssi = 1; break; case 0x1D: /* Set Subsystem Characteristics */ /* Command reject if flag byte is not zero */ if (iobuf[1] != 0x00) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_4); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } break; case 0xB0: /* Set Interface Identifier */ /* Command reject if flag byte bits 0-5 are not zero or bits 6-7 are 11 or 10 */ if ((iobuf[1] & 0xFE) != 0x00) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_4); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Prepare subsystem data (node descriptor record) */ memset (iobuf, 0x00, 96); /* Bytes 0-31 contain the subsystem node descriptor */ store_fw(&iobuf[0], 0x00000100); sprintf ((char *)&iobuf[4], "00%4.4X HRCZZ000000000001", dev->ckdcu->devt); for (i = 4; i < 30; i++) iobuf[i] = host_to_guest(iobuf[i]); /* Bytes 32-63 contain node qualifier data */ store_fw(&iobuf[32],0x00000000); // flags+zeros store_fw(&iobuf[40],0x00000000); store_fw(&iobuf[40],0x41010000); // start range store_fw(&iobuf[44],0x41010001); // end range store_fw(&iobuf[48],0x41010010); // start range store_fw(&iobuf[52],0x41010011); // end range /* Bytes 64-95 contain a 2nd subsystem node descriptor */ iobuf[64] = 0x00; /* Indicate the length of subsystem data prepared */ dev->ckdssdlen = (iobuf[1] & 0x03) ? 32 : 96; break; default: /* Unknown order code */ ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_4); *unitstat = CSW_CE | CSW_DE | CSW_UC; } /* end switch(iobuf[0]) */ /* Exit if unit check has already been set */ if (*unitstat & CSW_UC) break; /* Return normal status */ *unitstat = CSW_CE | CSW_DE; break; seek_0x27: /* SEEK AND SET SECTOR (Itel 7330 controller only) */ case 0x07: /* SEEK */ case 0x0B: /* SEEK CYLINDER */ case 0x1B: /* SEEK HEAD */ /*---------------------------------------------------------------*/ /* SEEK */ /*---------------------------------------------------------------*/ /* Command reject if within the domain of a Locate Record */ if (dev->ckdlcount > 0) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* For 3990, command reject if Seek Head not preceded by Seek, Seek Cylinder, Locate Record, Read IPL, or Recalibrate */ if (code == 0x1B && dev->ckd3990 && dev->ckdseek == 0 && dev->ckdskcyl == 0 && dev->ckdlocat == 0 && dev->ckdrdipl == 0 && dev->ckdrecal == 0) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* File protected if file mask does not allow requested seek */ if (((code == 0x07 || code == 0x27) && (dev->ckdfmask & CKDMASK_SKCTL) != CKDMASK_SKCTL_ALLSKR) || (code == 0x0B && (dev->ckdfmask & CKDMASK_SKCTL) != CKDMASK_SKCTL_ALLSKR && (dev->ckdfmask & CKDMASK_SKCTL) != CKDMASK_SKCTL_CYLHD) || (code == 0x1B && (dev->ckdfmask & CKDMASK_SKCTL) == CKDMASK_SKCTL_INHSMT)) { ckd_build_sense (dev, 0, SENSE1_FP, 0, 0, 0); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Set residual count */ num = (count < 6) ? count : 6; *residual = count - num; /* Command reject if count is less than 6 */ if (count < 6) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_3); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Extract the BBCCHH seek address from the I/O buffer */ bin = (iobuf[0] << 8) | iobuf[1]; cyl = (iobuf[2] << 8) | iobuf[3]; head = (iobuf[4] << 8) | iobuf[5]; /* For Seek Head, use the current cylinder number */ if (code == 0x1B) cyl = dev->ckdcurcyl; /* Command reject if seek address is invalid */ if (bin != 0 || cyl >= dev->ckdcyls || head >= dev->ckdheads) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_4); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* File protected if outside defined extent */ if ( EXTENT_CHECK(dev, cyl, head) ) { ckd_build_sense (dev, 0, SENSE1_FP, 0, 0, 0); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Seek to specified cylinder and head */ rc = ckd_seek (dev, cyl, head, &trkhdr, unitstat); if (rc < 0) break; /* Set command processed flag */ dev->ckdseek = 1; /* Return normal status */ *unitstat = CSW_CE | CSW_DE; break; case 0x13: /*---------------------------------------------------------------*/ /* RECALIBRATE */ /*---------------------------------------------------------------*/ /* Command reject if recalibrate is issued to a 3390 */ if (dev->devtype == 0x3390) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_1); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Command reject if within the domain of a Locate Record */ if (dev->ckdlcount > 0) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* File protected if the file mask does not allow recalibrate, or if the file mask specifies diagnostic authorization */ if ((dev->ckdfmask & CKDMASK_SKCTL) != CKDMASK_SKCTL_ALLSKR || (dev->ckdfmask & CKDMASK_AAUTH) == CKDMASK_AAUTH_DIAG) { ckd_build_sense (dev, 0, SENSE1_FP, 0, 0, 0); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* File protected if cyl 0 head 0 is outside defined extent */ if ( EXTENT_CHECK0(dev) ) { ckd_build_sense (dev, 0, SENSE1_FP, 0, 0, 0); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Seek to cylinder 0 head 0 */ rc = ckd_seek (dev, 0, 0, &trkhdr, unitstat); if (rc < 0) break; /* Set command processed flag */ dev->ckdrecal = 1; /* Return normal status */ *unitstat = CSW_CE | CSW_DE; break; case 0x1F: /*---------------------------------------------------------------*/ /* SET FILE MASK */ /*---------------------------------------------------------------*/ /* Command reject if preceded by a Define Extent or Set File Mask, or within the domain of a Locate Record */ if (dev->ckdxtdef || dev->ckdsetfm || dev->ckdlcount > 0) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Set residual count */ num = (count < 1) ? count : 1; *residual = count - num; /* Command reject if count is less than 1 */ if (count < 1) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_3); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Extract the file mask from the I/O buffer */ dev->ckdfmask = iobuf[0]; logdevtr (dev, _("HHCDA054I set file mask %2.2X\n"), dev->ckdfmask); /* Command reject if file mask is invalid */ if ((dev->ckdfmask & CKDMASK_RESV) != 0) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_4); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Set command processed flag */ dev->ckdsetfm = 1; /* Return normal status */ *unitstat = CSW_CE | CSW_DE; break; case 0x22: /*---------------------------------------------------------------*/ /* READ SECTOR */ /*---------------------------------------------------------------*/ /* Command reject if non-RPS device */ if (dev->ckdtab->sectors == 0) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_1); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Command reject if within the domain of a Locate Record */ if (dev->ckdlcount > 0) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Set residual count */ num = (count < 1) ? count : 1; *residual = count - num; if (count < 1) *more = 1; /* Return sector number in I/O buffer */ iobuf[0] = 0; /* Return normal status */ *unitstat = CSW_CE | CSW_DE; break; case 0x23: /*---------------------------------------------------------------*/ /* SET SECTOR */ /*---------------------------------------------------------------*/ /* Command reject if non-RPS device */ if (dev->ckdtab->sectors == 0) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_1); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Command reject if within the domain of a Locate Record */ if (dev->ckdlcount > 0) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* For 3990, command reject if not preceded by Seek, Seek Cyl, Locate Record, Read IPL, or Recalibrate command */ if (dev->ckd3990 && dev->ckdseek == 0 && dev->ckdskcyl == 0 && dev->ckdlocat == 0 && dev->ckdrdipl == 0 && dev->ckdrecal == 0) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Set residual count */ num = (count < 1) ? count : 1; *residual = count - num; /* Command reject if count is less than 1 */ if (count < 1) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_3); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Return normal status */ *unitstat = CSW_CE | CSW_DE; break; case 0x29: case 0xA9: /* SEARCH KEY EQUAL */ case 0x49: case 0xC9: /* SEARCH KEY HIGH */ case 0x69: case 0xE9: /* SEARCH KEY EQUAL OR HIGH */ /*---------------------------------------------------------------*/ /* SEARCH KEY */ /*---------------------------------------------------------------*/ /* For 3990, command reject if not preceded by Seek, Seek Cyl, Locate Record, Read IPL, or Recalibrate command */ if (dev->ckd3990 && dev->ckdseek == 0 && dev->ckdskcyl == 0 && dev->ckdlocat == 0 && dev->ckdrdipl == 0 && dev->ckdrecal == 0) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Command reject if within the domain of a Locate Record */ if (dev->ckdlcount > 0) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Read next key */ rc = ckd_read_key (dev, code, key, unitstat); if (rc < 0) break; /* Calculate number of compare bytes and set residual count */ num = (count < dev->ckdcurkl) ? count : dev->ckdcurkl; *residual = count - num; /* Nothing to compare if key length is zero */ if (dev->ckdcurkl == 0) { *unitstat = CSW_CE | CSW_DE; break; } /* Compare key with search argument */ rc = memcmp(key, iobuf, num); /* Return status modifier if compare result matches */ if (((code & 0x20) && (rc == 0)) || ((code & 0x40) && (rc > 0))) *unitstat = CSW_SM | CSW_CE | CSW_DE; else *unitstat = CSW_CE | CSW_DE; #ifdef OPTION_CKD_KEY_TRACING /* If the search was successful, trace the first 8 bytes of the key, which will usually be a dataset name or member name and can provide useful debugging information */ if ((*unitstat & CSW_SM) && dev->ckdkeytrace && isprint(guest_to_host(iobuf[0]))) { BYTE module[45]; int i; for (i=0; i < (ssize_t)sizeof(module)-1 && i < num; i++) module[i] = guest_to_host(iobuf[i]); module[i] = '\0'; logmsg (_("HHCDA055I search key %s\n"), module); } #endif /*OPTION_CKD_KEY_TRACING*/ /* Set flag if entire key was equal for SEARCH KEY EQUAL */ if (rc == 0 && num == dev->ckdcurkl && (code & 0x7F) == 0x29) dev->ckdkyeq = 1; else dev->ckdkyeq = 0; break; case 0x31: case 0xB1: /* SEARCH ID EQUAL */ case 0x51: case 0xD1: /* SEARCH ID HIGH */ case 0x71: case 0xF1: /* SEARCH ID EQUAL OR HIGH */ /*---------------------------------------------------------------*/ /* SEARCH ID */ /*---------------------------------------------------------------*/ /* For 3990, command reject if not preceded by Seek, Seek Cyl, Locate Record, Read IPL, or Recalibrate command */ if (dev->ckd3990 && dev->ckdseek == 0 && dev->ckdskcyl == 0 && dev->ckdlocat == 0 && dev->ckdrdipl == 0 && dev->ckdrecal == 0) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Command reject if within the domain of a Locate Record */ if (dev->ckdlcount > 0) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Read next count field */ rc = ckd_read_count (dev, code, &rechdr, unitstat); if (rc < 0) break; /* Calculate number of compare bytes and set residual count */ num = (count < 5) ? count : 5; *residual = count - num; /* Turn off track overflow flag in record header if present */ rechdr.cyl[0] &= 0x7F; /* Compare count with search argument */ rc = memcmp(&rechdr, iobuf, num); /* Return status modifier if compare result matches */ if (((code & 0x20) && (rc == 0)) || ((code & 0x40) && (rc > 0))) *unitstat = CSW_SM | CSW_CE | CSW_DE; else *unitstat = CSW_CE | CSW_DE; /* Set flag if entire id compared equal for SEARCH ID EQUAL */ if (rc == 0 && num == 5 && (code & 0x7F) == 0x31) dev->ckdideq = 1; else dev->ckdideq = 0; break; case 0x39: case 0xB9: /*---------------------------------------------------------------*/ /* SEARCH HOME ADDRESS EQUAL */ /*---------------------------------------------------------------*/ /* For 3990, command reject if not preceded by Seek, Seek Cyl, Locate Record, Read IPL, or Recalibrate command */ if (dev->ckd3990 && dev->ckdseek == 0 && dev->ckdskcyl == 0 && dev->ckdlocat == 0 && dev->ckdrdipl == 0 && dev->ckdrecal == 0) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Command reject if within the domain of a Locate Record */ if (dev->ckdlcount > 0) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* For multitrack operation, advance to next track */ if (code & 0x80) { rc = mt_advance (dev, unitstat, 1); if (rc < 0) break; } /* Seek to beginning of track */ rc = ckd_seek (dev, dev->ckdcurcyl, dev->ckdcurhead, &trkhdr, unitstat); if (rc < 0) break; /* Calculate number of compare bytes and set residual count */ num = (count < 4) ? count : 4; *residual = count - num; /* Compare CCHH portion of track header with search argument */ rc = memcmp(&(trkhdr.cyl), iobuf, num); /* Return status modifier if compare result matches */ if (rc == 0) *unitstat = CSW_SM | CSW_CE | CSW_DE; else *unitstat = CSW_CE | CSW_DE; /* Set flag if entire home address compared equal */ if (rc == 0 && num == 4) dev->ckdhaeq = 1; else dev->ckdhaeq = 0; break; case 0x05: /*---------------------------------------------------------------*/ /* WRITE DATA */ /*---------------------------------------------------------------*/ /* Command reject if the current track is in the DSF area */ if (dev->ckdcurcyl >= dev->ckdcyls) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Command reject if not within the domain of a Locate Record and not preceded by either a Search ID Equal or Search Key Equal that compared equal on all bytes */ /*INCOMPLETE*/ /*Write CKD allows intervening Read/Write key and data commands, Write Data does not!!! Rethink the handling of these flags*/ if (dev->ckdlcount == 0 && dev->ckdideq == 0 && dev->ckdkyeq == 0) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Command reject if file mask inhibits all write commands */ if ((dev->ckdfmask & CKDMASK_WRCTL) == CKDMASK_WRCTL_INHWRT) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Check operation code if within domain of a Locate Record */ if (dev->ckdlcount > 0) { if (!(((dev->ckdloper & CKDOPER_CODE) == CKDOPER_WRITE && dev->ckdlcount == (dev->ckdlaux & CKDLAUX_RDCNTSUF) ? 2 : 1) || (dev->ckdloper & CKDOPER_CODE) == CKDOPER_WRTTRK)) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* If not operating in CKD conversion mode, check that the data length is equal to the transfer length factor, except when writing a R0 data area under the control of a Locate Record Write Track operation, in which case a transfer length factor of 8 is used instead */ if ((dev->ckdxgattr & CKDGATR_CKDCONV) == 0) { if ((dev->ckdloper & CKDOPER_CODE) == CKDOPER_WRTTRK && dev->ckdcurrec == 0) num = 8; else num = dev->ckdltranlf; if (dev->ckdcurdl != num) { /* Unit check with invalid track format */ ckd_build_sense (dev, 0, SENSE1_ITF, 0, 0, 0); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } } } /* end if(ckdlcount) */ /* If data length is zero, terminate with unit exception */ if (dev->ckdcurdl == 0) { *unitstat = CSW_CE | CSW_DE | CSW_UX; break; } /* Calculate number of bytes written and set residual count */ size = dev->ckdcurdl; num = (count < size) ? count : size; *residual = count - num; /* Write data */ rc = ckd_write_data (dev, iobuf, num, unitstat); if (rc < 0) break; /* If track overflow, keep writing */ offset = 0; while (dev->ckdtrkof) { /* Advance to next track */ rc = mt_advance (dev, unitstat, 1); if (rc < 0) break; /* Read the first count field */ rc = ckd_read_count (dev, code, &rechdr, unitstat); if (rc < 0) break; /* Set offset into buffer for this write */ offset += size; /* Account for size of this overflow record */ size = dev->ckdcurdl; num = (*residual < size) ? *residual : size; *residual -= num; /* Write the next data field */ rc = ckd_write_data (dev, iobuf+offset, num, unitstat); if (rc < 0) break; } /* Bail out if track overflow produced I/O error */ if (rc < 0) break; /* Return normal status */ *unitstat = CSW_CE | CSW_DE; break; case 0xA5: //FIXME: 0xA5 ccw is undoc'd. We are treating it as 0x85 except // we will allow a DX ccw to follow. case 0x85: /*---------------------------------------------------------------*/ /* WRITE UPDATE DATA */ /*---------------------------------------------------------------*/ /* Command reject if not within the domain of a Locate Record that specifies the Write Data operation code */ if (dev->ckdlcount == 0 || ((dev->ckdloper & CKDOPER_CODE) != CKDOPER_WRITE && (dev->ckdloper & CKDOPER_CODE) != CKDOPER_WRTANY)) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Orient to next user record count field */ if (dev->ckdorient != CKDORIENT_COUNT || dev->ckdcurrec == 0) { /* Read next count field */ rc = ckd_read_count (dev, code, &rechdr, unitstat); if (rc < 0) break; } /* If not operating in CKD conversion mode, check that the data length is equal to the transfer length factor */ if ((dev->ckdxgattr & CKDGATR_CKDCONV) == 0) { if (dev->ckdcurdl != dev->ckdltranlf) { /* Unit check with invalid track format */ ckd_build_sense (dev, 0, SENSE1_ITF, 0, 0, 0); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } } /* If data length is zero, terminate with unit exception */ if (dev->ckdcurdl == 0) { *unitstat = CSW_CE | CSW_DE | CSW_UX; break; } /* Calculate number of bytes written and set residual count */ size = dev->ckdcurdl; num = (count < size) ? count : size; *residual = count - num; /* Write data */ rc = ckd_write_data (dev, iobuf, num, unitstat); if (rc < 0) break; /* If track overflow, keep writing */ offset = 0; while (dev->ckdtrkof) { /* Advance to next track */ rc = mt_advance (dev, unitstat, 1); if (rc < 0) break; /* Read the first count field */ rc = ckd_read_count (dev, code, &rechdr, unitstat); if (rc < 0) break; /* Set offset into buffer for this write */ offset += size; /* Account for size of this overflow record */ size = dev->ckdcurdl; num = (*residual < size) ? *residual : size; *residual -= num; /* Write the next data field */ rc = ckd_write_data (dev, iobuf+offset, num, unitstat); if (rc < 0) break; } /* Bail out if track overflow produced I/O error */ if (rc < 0) break; /* Return normal status */ *unitstat = CSW_CE | CSW_DE; break; case 0x0D: /*---------------------------------------------------------------*/ /* WRITE KEY AND DATA */ /*---------------------------------------------------------------*/ /* Command reject if the current track is in the DSF area */ if (dev->ckdcurcyl >= dev->ckdcyls) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Command reject if not within the domain of a Locate Record and not preceded by a Search ID Equal that compared equal on all bytes */ /*INCOMPLETE*/ /*Write CKD allows intervening Read/Write key and data commands, Write Key Data does not!!! Rethink the handling of these flags*/ if (dev->ckdlcount == 0 && dev->ckdideq == 0) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Command reject if file mask inhibits all write commands */ if ((dev->ckdfmask & CKDMASK_WRCTL) == CKDMASK_WRCTL_INHWRT) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Check operation code if within domain of a Locate Record */ if (dev->ckdlcount > 0) { if (!(((dev->ckdloper & CKDOPER_CODE) == CKDOPER_WRITE && dev->ckdlcount == (dev->ckdlaux & CKDLAUX_RDCNTSUF) ? 2 : 1) || (dev->ckdloper & CKDOPER_CODE) == CKDOPER_WRTTRK)) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* If not operating in CKD conversion mode, check that the key + data length equals the transfer length factor */ if ((dev->ckdxgattr & CKDGATR_CKDCONV) == 0 && dev->ckdcurkl + dev->ckdcurdl != dev->ckdltranlf) { /* Unit check with invalid track format */ ckd_build_sense (dev, 0, SENSE1_ITF, 0, 0, 0); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } } /* end if(ckdlcount) */ /* If data length is zero, terminate with unit exception */ if (dev->ckdcurdl == 0) { *unitstat = CSW_CE | CSW_DE | CSW_UX; break; } /* Calculate number of bytes written and set residual count */ size = dev->ckdcurkl + dev->ckdcurdl; num = (count < size) ? count : size; *residual = count - num; /* Write key and data */ rc = ckd_write_kd (dev, iobuf, num, unitstat); if (rc < 0) break; /* If track overflow, keep writing */ offset = dev->ckdcurkl; while (dev->ckdtrkof) { /* Advance to next track */ rc = mt_advance (dev, unitstat, 1); if (rc < 0) break; /* Read the first count field */ rc = ckd_read_count (dev, code, &rechdr, unitstat); if (rc < 0) break; /* Set offset into buffer for this write */ offset += size; /* Account for size of this overflow record */ size = dev->ckdcurdl; num = (*residual < size) ? *residual : size; *residual -= num; /* Write the next data field */ rc = ckd_write_data (dev, iobuf+offset, num, unitstat); if (rc < 0) break; } /* Bail out if track overflow produced I/O error */ if (rc < 0) break; /* Return normal status */ *unitstat = CSW_CE | CSW_DE; break; case 0x8D: /*---------------------------------------------------------------*/ /* WRITE UPDATE KEY AND DATA */ /*---------------------------------------------------------------*/ /* Command reject if not within the domain of a Locate Record that specifies the Write Data operation code */ if (dev->ckdlcount == 0 || (dev->ckdloper & CKDOPER_CODE) != CKDOPER_WRITE) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Orient to next user record count field */ if (dev->ckdorient != CKDORIENT_COUNT || dev->ckdcurrec == 0) { /* Read next count field */ rc = ckd_read_count (dev, code, &rechdr, unitstat); if (rc < 0) break; } /* If not operating in CKD conversion mode, check that the data length is equal to the transfer length factor */ if ((dev->ckdxgattr & CKDGATR_CKDCONV) == 0) { if ((dev->ckdcurkl + dev->ckdcurdl) != dev->ckdltranlf) { /* Unit check with invalid track format */ ckd_build_sense (dev, 0, SENSE1_ITF, 0, 0, 0); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } } /* If data length is zero, terminate with unit exception */ if (dev->ckdcurdl == 0) { *unitstat = CSW_CE | CSW_DE | CSW_UX; break; } /* Calculate number of bytes written and set residual count */ size = dev->ckdcurkl + dev->ckdcurdl; num = (count < size) ? count : size; *residual = count - num; /* Write key and data */ rc = ckd_write_kd (dev, iobuf, num, unitstat); if (rc < 0) break; /* If track overflow, keep writing */ offset = dev->ckdcurkl; while (dev->ckdtrkof) { /* Advance to next track */ rc = mt_advance (dev, unitstat, 1); if (rc < 0) break; /* Read the first count field */ rc = ckd_read_count (dev, code, &rechdr, unitstat); if (rc < 0) break; /* Set offset into buffer for this write */ offset += size; /* Account for size of this overflow record */ size = dev->ckdcurdl; num = (*residual < size) ? *residual : size; *residual -= num; /* Write the next data field */ rc = ckd_write_data (dev, iobuf+offset, num, unitstat); if (rc < 0) break; } /* Bail out if track overflow produced I/O error */ if (rc < 0) break; /* Return normal status */ *unitstat = CSW_CE | CSW_DE; break; case 0x11: /*---------------------------------------------------------------*/ /* ERASE */ /*---------------------------------------------------------------*/ /* Command reject if the current track is in the DSF area */ if (dev->ckdcurcyl >= dev->ckdcyls) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Command reject if not within the domain of a Locate Record and not preceded by either a Search ID Equal or Search Key Equal that compared equal on all bytes, or a Write R0 or Write CKD not within the domain of a Locate Record */ if (dev->ckdlcount == 0 && dev->ckdideq == 0 && dev->ckdkyeq == 0 && dev->ckdwckd == 0) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Command reject if file mask does not permit Write CKD */ if ((dev->ckdfmask & CKDMASK_WRCTL) != CKDMASK_WRCTL_ALLWRT && (dev->ckdfmask & CKDMASK_WRCTL) != CKDMASK_WRCTL_INHWR0) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Check operation code if within domain of a Locate Record */ if (dev->ckdlcount > 0) { if ((dev->ckdloper & CKDOPER_CODE) != CKDOPER_WRTTRK) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } } /* Write end of track marker */ rc = ckd_erase (dev, iobuf, count, &size, unitstat); if (rc < 0) break; /* Calculate number of bytes used and set residual count */ num = (count < size) ? count : size; *residual = count - num; /* Return normal status */ *unitstat = CSW_CE | CSW_DE; break; case 0x15: /*---------------------------------------------------------------*/ /* WRITE RECORD ZERO */ /*---------------------------------------------------------------*/ /* Command reject if the current track is in the DSF area */ if (dev->ckdcurcyl >= dev->ckdcyls) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; logmsg("DEBUG : WR0 OUTSIDE PACK\n"); break; } /* Command reject if not within the domain of a Locate Record and not preceded by either a Search Home Address that compared equal on all 4 bytes, or a Write Home Address not within the domain of a Locate Record */ /* ISW20030819-1 : Added check for previously issued WRHA */ if (dev->ckdlcount == 0 && dev->ckdhaeq == 0 && dev->ckdwrha==0) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; logmsg("DEBUG : WR0 CASE 2\n"); break; } /* Command reject if file mask does not permit Write R0 */ if ((dev->ckdfmask & CKDMASK_WRCTL) != CKDMASK_WRCTL_ALLWRT) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; logmsg("DEBUG : WR0 BAD FM\n"); break; } /* Check operation code if within domain of a Locate Record */ if (dev->ckdlcount > 0) { if (!((dev->ckdloper & CKDOPER_CODE) == CKDOPER_FORMAT && ((dev->ckdloper & CKDOPER_ORIENTATION) == CKDOPER_ORIENT_HOME || (dev->ckdloper & CKDOPER_ORIENTATION) == CKDOPER_ORIENT_INDEX ))) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; logmsg("DEBUG : LOC REC 2\n"); break; } } /* Write R0 count key and data */ rc = ckd_write_ckd (dev, iobuf, count, unitstat, 0); if (rc < 0) break; /* Calculate number of bytes written and set residual count */ size = CKDDASD_RECHDR_SIZE + dev->ckdcurkl + dev->ckdcurdl; num = (count < size) ? count : size; *residual = count - num; /* Return normal status */ *unitstat = CSW_CE | CSW_DE; /* Set flag if Write R0 outside domain of a locate record */ if (dev->ckdlcount == 0) dev->ckdwckd = 1; else dev->ckdwckd = 0; break; case 0x1D: /* WRITE CKD */ case 0x01: /* WRITE SPECIAL CKD */ /*---------------------------------------------------------------*/ /* WRITE COUNT KEY AND DATA */ /*---------------------------------------------------------------*/ /* Command reject if the current track is in the DSF area */ if (dev->ckdcurcyl >= dev->ckdcyls) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Command reject if previous command was a Write R0 that assigned an alternate track - not implemented */ /* Command reject if not within the domain of a Locate Record and not preceded by either a Search ID Equal or Search Key Equal that compared equal on all bytes, or a Write R0 or Write CKD not within the domain of a Locate Record */ if (dev->ckdlcount == 0 && dev->ckdideq == 0 && dev->ckdkyeq == 0 && dev->ckdwckd == 0) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Command reject if file mask does not permit Write CKD */ if ((dev->ckdfmask & CKDMASK_WRCTL) != CKDMASK_WRCTL_ALLWRT && (dev->ckdfmask & CKDMASK_WRCTL) != CKDMASK_WRCTL_INHWR0) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Command reject if WRITE SPECIAL CKD to a 3380 or 3390 */ if ((code == 0x01) && ((dev->devtype == 0x3380) || (dev->devtype == 0x3390))) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Check operation code if within domain of a Locate Record */ if (dev->ckdlcount > 0) { if (!((dev->ckdloper & CKDOPER_CODE) == CKDOPER_FORMAT || (dev->ckdloper & CKDOPER_CODE) == CKDOPER_WRTTRK)) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } } /* Set track overflow flag if WRITE SPECIAL CKD */ trk_ovfl = (code==0x01) ? 1 : 0; /* Write count key and data */ rc = ckd_write_ckd (dev, iobuf, count, unitstat, trk_ovfl); if (rc < 0) break; /* Calculate number of bytes written and set residual count */ size = CKDDASD_RECHDR_SIZE + dev->ckdcurkl + dev->ckdcurdl; num = (count < size) ? count : size; *residual = count - num; /* Return normal status */ *unitstat = CSW_CE | CSW_DE; /* Set flag if Write CKD outside domain of a locate record */ if (dev->ckdlcount == 0) dev->ckdwckd = 1; else dev->ckdwckd = 0; break; case 0x9D: /*---------------------------------------------------------------*/ /* WRITE COUNT KEY AND DATA NEXT TRACK */ /*---------------------------------------------------------------*/ /* Command reject if not within the domain of a Locate Record that specifies a format write operation */ if (dev->ckdlcount == 0 || (dev->ckdloper & CKDOPER_CODE) != CKDOPER_FORMAT) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Command reject if not chained from a Write CKD or another Write CKD Next Track command */ if (chained == 0 || (prevcode != 0x1D && prevcode != 0x9D)) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Advance to next track */ rc = mt_advance (dev, unitstat, 1); if (rc < 0) break; /* Read the count field for record zero */ rc = ckd_read_count (dev, code, &rechdr, unitstat); if (rc < 0) break; /* Write count key and data */ rc = ckd_write_ckd (dev, iobuf, count, unitstat, 0); if (rc < 0) break; /* Calculate number of bytes written and set residual count */ size = CKDDASD_RECHDR_SIZE + dev->ckdcurkl + dev->ckdcurdl; num = (count < size) ? count : size; *residual = count - num; /* Return normal status */ *unitstat = CSW_CE | CSW_DE; break; case 0x47: /*---------------------------------------------------------------*/ /* LOCATE RECORD */ /*---------------------------------------------------------------*/ /* Calculate residual byte count */ num = (count < 16) ? count : 16; *residual = count - num; /* Control information length must be at least 16 bytes */ if (count < 16) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_3); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Command reject if within the domain of a Locate Record, or not preceded by a Define Extent or Read IPL command */ if (dev->ckdlcount > 0 || (dev->ckdxtdef == 0 && dev->ckdrdipl == 0)) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Byte 0 contains the locate record operation byte */ dev->ckdloper = iobuf[0]; /* Validate the locate record operation code (bits 2-7) */ if (!((dev->ckdloper & CKDOPER_CODE) == CKDOPER_ORIENT || (dev->ckdloper & CKDOPER_CODE) == CKDOPER_WRITE || (dev->ckdloper & CKDOPER_CODE) == CKDOPER_FORMAT || (dev->ckdloper & CKDOPER_CODE) == CKDOPER_RDDATA || (dev->ckdloper & CKDOPER_CODE) == CKDOPER_WRTTRK || (dev->ckdloper & CKDOPER_CODE) == CKDOPER_RDTRKS || (dev->ckdloper & CKDOPER_CODE) == CKDOPER_READ)) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_4); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Check for valid combination of orientation and opcode */ if ( ((dev->ckdloper & CKDOPER_ORIENTATION) == CKDOPER_ORIENT_HOME && !((dev->ckdloper & CKDOPER_CODE) == CKDOPER_ORIENT || (dev->ckdloper & CKDOPER_CODE) == CKDOPER_FORMAT || (dev->ckdloper & CKDOPER_CODE) == CKDOPER_RDDATA || (dev->ckdloper & CKDOPER_CODE) == CKDOPER_RDTRKS || (dev->ckdloper & CKDOPER_CODE) == CKDOPER_READ)) || ((dev->ckdloper & CKDOPER_ORIENTATION) == CKDOPER_ORIENT_DATA && !((dev->ckdloper & CKDOPER_CODE) == CKDOPER_ORIENT || (dev->ckdloper & CKDOPER_CODE) == CKDOPER_WRITE || (dev->ckdloper & CKDOPER_CODE) == CKDOPER_RDDATA || (dev->ckdloper & CKDOPER_CODE) == CKDOPER_READ)) || ((dev->ckdloper & CKDOPER_ORIENTATION) == CKDOPER_ORIENT_INDEX && !((dev->ckdloper & CKDOPER_CODE) == CKDOPER_FORMAT || (dev->ckdloper & CKDOPER_CODE) == CKDOPER_READ)) ) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_4); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Check for write operation on a read only disk */ if ( (dev->ckdrdonly && !dev->ckdfakewr && !dev->dasdsfn) && ((dev->ckdloper & CKDOPER_CODE) == CKDOPER_WRITE || (dev->ckdloper & CKDOPER_CODE) == CKDOPER_FORMAT || (dev->ckdloper & CKDOPER_CODE) == CKDOPER_WRTTRK) ) { ckd_build_sense (dev, SENSE_EC, SENSE1_WRI, 0, FORMAT_0, MESSAGE_4); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Byte 1 contains the locate record auxiliary byte */ dev->ckdlaux = iobuf[1]; /* Validate the auxiliary byte */ if ((dev->ckdlaux & CKDLAUX_RESV) != 0 || ((dev->ckdlaux & CKDLAUX_RDCNTSUF) && !((dev->ckdloper & CKDOPER_CODE) == CKDOPER_WRITE || (dev->ckdloper & CKDOPER_CODE) == CKDOPER_READ)) ) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_4); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Byte 2 must contain zeroes */ if (iobuf[2] != 0) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_4); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Byte 3 contains the locate record domain count */ dev->ckdlcount = iobuf[3]; /* Validate the locate record domain count */ if ( ((dev->ckdloper & CKDOPER_CODE) == CKDOPER_ORIENT && dev->ckdlcount != 0) || ((dev->ckdloper & CKDOPER_CODE) != CKDOPER_ORIENT && dev->ckdlcount == 0) || ((dev->ckdlaux & CKDLAUX_RDCNTSUF) && dev->ckdlcount < 2) ) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_4); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Bytes 4-7 contain the seek address */ cyl = (iobuf[4] << 8) | iobuf[5]; head = (iobuf[6] << 8) | iobuf[7]; /* Command reject if seek address is not valid */ if (cyl >= dev->ckdcyls || head >= dev->ckdheads) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_4); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* File protect error if seek address is outside extent */ if ( EXTENT_CHECK(dev, cyl, head) ) { ckd_build_sense (dev, 0, SENSE1_FP, 0, 0, 0); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Bytes 8-12 contain the search argument */ memcpy (cchhr, iobuf+8, 5); /* Byte 13 contains the sector number */ sector = iobuf[13]; /* Command reject if sector number is not valid */ if (sector != 0xFF && sector >= dev->ckdtab->sectors) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_4); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Bytes 14-15 contain the transfer length factor */ dev->ckdltranlf = (iobuf[14] << 8) | iobuf[15]; /* Validate the transfer length factor */ if ( ((dev->ckdlaux & CKDLAUX_TLFVALID) == 0 && dev->ckdltranlf != 0) || ((dev->ckdlaux & CKDLAUX_TLFVALID) && dev->ckdltranlf == 0) || dev->ckdltranlf > dev->ckdxblksz) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_4); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* If transfer length factor is not supplied then use the blocksize from the define extent command */ if ((dev->ckdlaux & CKDLAUX_TLFVALID) == 0) dev->ckdltranlf = dev->ckdxblksz; /* Seek to the required track */ rc = ckd_seek (dev, cyl, head, &trkhdr, unitstat); if (rc < 0) { if (dev->syncio_retry) dev->ckdlcount = 0; break; } /* Set normal status */ *unitstat = CSW_CE | CSW_DE; /* Perform search according to specified orientation */ switch ((dev->ckdloper & CKDOPER_ORIENTATION)) { case CKDOPER_ORIENT_HOME: /* For home orientation, compare the search CCHH with the CCHH in the track header */ if (memcmp (&(trkhdr.cyl), cchhr, 4) != 0) { ckd_build_sense (dev, 0, SENSE1_NRF, 0, 0, 0); *unitstat = CSW_CE | CSW_DE | CSW_UC; } break; case CKDOPER_ORIENT_COUNT: case CKDOPER_ORIENT_DATA: /* For count or data orientation, search the track for a count field matching the specified CCHHR */ while (1) { /* Read next count field and exit at end of track with sense data indicating no record found */ rc = ckd_read_count (dev, code, &rechdr, unitstat); if (rc < 0) break; /* Turn off track overflow flag */ rechdr.cyl[0] &= 0x7F; /* Compare the count field with the search CCHHR */ if (memcmp (&rechdr, cchhr, 5) == 0) break; // NOTE: Code like this breaks VM mini-disks !!! #if 0 if (memcmp (&rechdr, cchhr, 4) != 0) { logmsg ("HHCDA999E wrong recordheader: cc hh r=%d %d %d," "should be:cc hh r=%d %d %d\n", (rechdr.cyl[0] << 8) | rechdr.cyl[1], (rechdr.head[0] << 8) | rechdr.head[1], rechdr.rec, (cchhr[0] << 8) | cchhr[1], (cchhr[2] << 8) | cchhr[3], cchhr[4]); break; } #endif } /* end while */ } /* end switch(CKDOPER_ORIENTATION) */ /* Exit if search ended with error status */ if (*unitstat != (CSW_CE | CSW_DE)) break; /* Reorient past data if data orientation is specified */ if ((dev->ckdloper & CKDOPER_ORIENTATION) == CKDOPER_ORIENT_DATA) { /* Skip past key and data fields */ dev->bufoff += dev->ckdcurkl + dev->ckdcurdl; /* Set the device orientation fields */ dev->ckdrem = 0; dev->ckdorient = CKDORIENT_DATA; } /* Set locate record flag and return normal status */ dev->ckdlocat = 1; break; case 0x4B: /*---------------------------------------------------------------*/ /* LOCATE RECORD EXTENDED */ /*---------------------------------------------------------------*/ /* LRE only valid for 3990-6 */ if (dev->ckdcu->devt != 0x3990 || dev->ckdcu->model != 0xe9) { /* Set command reject sense byte, and unit check status */ ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_1); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* * The Storage Director initially requests 20 bytes of parameters * from the channel; if the channel provides fewer than 20 bytes, * execution is terminated with status that includes unit check * (Command Reject, format X'03', CCW byte count less than required). */ num = (count < 20) ? count : 20; *residual = count - num; if (count < 20) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_3); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* * If Locate Record Extended is received within a Locate Record * domain, execution is terminated with status that includes unit * check (Command Reject, format X'02', Invalid Command Sequence). */ if (dev->ckdlcount > 0) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* * If Locate Record Extended was not preceded by a Define Extent * or Read IPL command in the same channel program, execution is * terminated with status that includes unit check (Command Reject, * format X'02', Invalid Command Sequence). If any other operation * is specified, the command is terminated with status that * includes unit check (Command Reject, format X'02', Invalid * Command Sequence). */ //FIXME not sure what that last sentence means if (dev->ckdxtdef == 0 && dev->ckdrdipl == 0) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Byte 0 contains the locate record operation byte */ dev->ckdloper = iobuf[0]; /* Validate the locate record operation code (byte 0 bits 2-7) */ if ((dev->ckdloper & CKDOPER_CODE) != CKDOPER_WRITE && (dev->ckdloper & CKDOPER_CODE) != CKDOPER_FORMAT && (dev->ckdloper & CKDOPER_CODE) != CKDOPER_WRTTRK && (dev->ckdloper & CKDOPER_CODE) != CKDOPER_RDTRKS && (dev->ckdloper & CKDOPER_CODE) != CKDOPER_READ && (dev->ckdloper & CKDOPER_CODE) != CKDOPER_EXTOP) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_4); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Validate the locate record extended operation code (byte 17) */ if ((dev->ckdloper & CKDOPER_CODE) == CKDOPER_EXTOP) { if (iobuf[17] != CKDOPER_WRTANY && iobuf[17] != CKDOPER_RDANY && iobuf[17] != CKDOPER_RDTSET) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_4); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } dev->ckdloper &= CKDOPER_ORIENTATION; dev->ckdloper |= iobuf[17]; } else if (iobuf[17] != 0) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_4); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Check for write operation on a read only disk */ //FIXME Not sure if this is right here if ( (dev->ckdrdonly && !dev->ckdfakewr && !dev->dasdsfn) && ((dev->ckdloper & CKDOPER_CODE) == CKDOPER_WRITE || (dev->ckdloper & CKDOPER_CODE) == CKDOPER_WRTANY || (dev->ckdloper & CKDOPER_CODE) == CKDOPER_FORMAT || (dev->ckdloper & CKDOPER_CODE) == CKDOPER_WRTTRK) ) { ckd_build_sense (dev, SENSE_EC, SENSE1_WRI, 0, FORMAT_0, MESSAGE_4); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* * Check for valid combination of orientation and opcode * * +------------------------------------------------+ * | Operation Code Orientation Byte | * | Cnt HA Data Index 17 | * +------------------------------------------------+ * | Write Data 01 x 81 x 00 | * | Format Write 03 43 x C3 00 | * | Write Track 0B x x x 00 | * | Read Tracks 0C 4C x x 00 | * | Read 16 56 96 D6 00 | * | Write Any 3F x x x 09 | * | Read Any 3F x x x 0A | * | Read Trackset 3F 7F x x 0E | * +------------------------------------------------+ * | Note: x - Combination is not valid. | * +------------------------------------------------+ * Table: valid orientation + operation code values */ if (dev->ckdloper != 0x01 && dev->ckdloper != 0x81 && dev->ckdloper != 0x03 && dev->ckdloper != 0x43 && dev->ckdloper != 0xC3 && dev->ckdloper != 0x0B && dev->ckdloper != 0x0C && dev->ckdloper != 0x4C && dev->ckdloper != 0x16 && dev->ckdloper != 0x56 && dev->ckdloper != 0x96 && dev->ckdloper != 0xD6 && dev->ckdloper != 0x09 && dev->ckdloper != 0x0A && dev->ckdloper != 0x0E && dev->ckdloper != 0x4E) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_4); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* * Byte 1 is the Auxiliary Byte * bit 0 = 0 : Bytes 14-15 are unused * 1 : Bytes 14-15 contain a TLF that overrides the * blocksize specified by the DX parameter. * bits 1-6 : Must be zero * If any of these bits are '1', the LRE is terminated * with status that includes unit check (Command Reject, * format X'04', Invalid Parameter). * bit 7 = 0 : No Read Count CCW is suffixed to the LR domain * 1 : A Read Count CCW is suffixed to the LR domain */ if ((iobuf[1] & CKDLAUX_RESV) != 0) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_4); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* * A Read Count command may only be suffixed to the domain of a LRE * that specifies a Write Data (01), Write Any (09), Read Any (0A), * or Read (16) operation code; if bit 7 = '1' when any other * Operation code is specified, Locate Record Extended is terminated * with status that includes unit check (Command Reject, format * X'04', Invalid Parameter). */ if ((iobuf[1] & CKDLAUX_RDCNTSUF) && ((dev->ckdloper & CKDOPER_CODE) != CKDOPER_WRITE && (dev->ckdloper & CKDOPER_CODE) != CKDOPER_WRTANY && (dev->ckdloper & CKDOPER_CODE) != CKDOPER_RDANY && (dev->ckdloper & CKDOPER_CODE) != CKDOPER_READ)) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_4); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } dev->ckdlaux = iobuf[1]; /* Byte 2 must contain zeroes */ if (iobuf[2] != 0) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_4); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* * Byte 3 is the Count parameter. In general, the count parameter * specifies the number of records, or tracks to be operated on by * data transfer commands that follow Locate Record Extended. * Specific interpretation of the Count parameter depends upon the * operation code in byte 0. * * The Count must be nonzero. If Read Count Suffixing is specified * in a Locate Record, the count must be greater than 1. If the * Count is invalid, Locate Record Extended is terminated with * status that includes unit check (Command Reject, format X'04', * Invalid Parameter). */ if (iobuf[3] == 0 || ((dev->ckdlaux & CKDLAUX_RDCNTSUF) && iobuf[3] < 2)) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_4); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } dev->ckdlcount = iobuf[3]; /* * The value in bytes 4-7 must be a valid track address for the * device and must be within the extent boundaries specified by the * preceding Define Extent command. * * If the Seek Address is not valid for the device or if the Extended * Operation code is Write Any or Read Any and the seek address does * not specify a primary track, Locate Record Extended is terminated * with status that includes unit check (Command Reject, format X'04', * Invalid Parameter). If the Seek Address is not within the defined * extent, Locate Record Extended is terminated with status that * includes unit check (File Protected). */ cyl = fetch_hw(iobuf+4); head = fetch_hw(iobuf+6); if (cyl >= dev->ckdcyls || head >= dev->ckdheads) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_4); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } if ( EXTENT_CHECK(dev, cyl, head) ) { ckd_build_sense (dev, 0, SENSE1_FP, 0, 0, 0); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* * Bytes 8-12 specify a value to be used as a search argument for * the Locate Record Extended search operation. * * When the operation specified in byte 0 does not require * orientation to a specific record, no search operation is * performed and bytes 8-12 are ignored. When Home Address * orientation is specified, byte 12 is ignored. */ memcpy (cchhr, iobuf+8, 5); /* * Byte 13 contains a sector number to which the device is to be * positioned before the Storage Director establishes orientation. * * The sector number must be within the range of valid sector * numbers for the device. If the sector number is invalid, Locate * Record Extended is terminated with status that includes unit * check (Command Reject, format X'04', Invalid Parameter). * * A value of X'FF' is valid and specifies that sector positioning * is not to be performed prior to establishing orientation. */ if (iobuf[13] != 0xFF && iobuf[13] >= dev->ckdtab->sectors) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_4); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } sector = iobuf[13]; /* * When byte 1, bit 0 is '0', bytes 14-15 must contain zeros; if * bytes 14-15 are not zero, Locate Record Extended is terminated * with status that includes unit check (Command Reject, format * X'04', Invalid Parameter). * * When byte 1 bit 0 is '1', bytes 14-15 contain a Transfer Length * Factor (TLF). The Transfer Length Factor must be non-zero; if it * is zero, Locate Record Extended is terminated with status that * includes unit check (Command Reject, format X'04', Invalid * Parameter). * * If the Transfer Length Factor value is greater than the value * specified (or implied) in the Define Extent Blocksize parameter, * Locate Record Extended is terminated with status that includes * unit check (Command Reject, format X'04', Invalid Parameter). * * The Storage Director uses the TLF to determine the number of * data bytes to be requested from the channel for each write * command that follows a Locate Record Extended that specified the * Write Data (01) Operation code. The product of the value in * bytes 14-15 and the count parameter is used to determine the * total number of bytes to be transferred by data transfer commands * that are executed within the domain of a Locate Record Extended * that specified the Format Write (03), Write Track (0B), or * Read (16) Operation codes. * * The TLF value is not retained by the Storage Director after the * expiration of the Locate Record domain. * * If Locate Record Extended does not specify a Transfer Length * Factor, the Storage Director will use the value from the Define * Extent Blocksize parameter for any required data transfer length * calculation. */ if ((!(dev->ckdlaux & CKDLAUX_TLFVALID) && fetch_hw(iobuf+14)) || ( (dev->ckdlaux & CKDLAUX_TLFVALID) && !fetch_hw(iobuf+14)) || fetch_hw(iobuf+14) > dev->ckdxblksz) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_4); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } if ((dev->ckdlaux & CKDLAUX_TLFVALID) == 0) dev->ckdltranlf = dev->ckdxblksz; else dev->ckdltranlf = fetch_hw(iobuf+14); /* * Bytes 18-19 contain an unsigned 16-bit binary value that * specifies the total number of extended parameter bytes. The * format and content of the Extended Parameters are defined by * the Extended Operation code. * * The length for 3990 Mod 6 or 9390 for the Extended Operation * codes must be consistent with the Extended Operation code in * byte 17 as follows: * 09 0001 * 0A 0001 * 0E 0001 or 0002 * * If the operation code is any code other than those defined, the * extended parameter length count must be zero. If these conditions * are not met the Locate Record Extended is terminated with status * that includes unit check (Command Reject, format X'04', Invalid * Parameter). */ num = fetch_hw(iobuf+18); if ((iobuf[17] == CKDOPER_WRTANY && num != 1) || (iobuf[17] == CKDOPER_RDANY && num != 1) || (iobuf[17] == CKDOPER_RDTSET && (num != 1 && num != 2)) || (iobuf[17] != CKDOPER_WRTANY && iobuf[17] != CKDOPER_RDANY && iobuf[17] != CKDOPER_RDTSET && num)) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_4); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* * Request the extended parameter bytes from the channel. If the * channel provides fewer bytes, execution is terminated with status * that includes unit check (Command Reject, format X'03', CCW byte * count less than required). */ if (count < 20 + num) { *residual = 0; ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_3); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } *residual -= num; /* * For `Read Any' (0x0A) or `Write Any' (0x09) the extended * length must be one and the extended parameter value (set size) * must be one. Otherwise the Locate Record Extended command is * terminated with status that includes unit check (Command Reject, * format X'04', Invalid Parameter). */ if ((iobuf[17] == CKDOPER_WRTANY && iobuf[20] != 1) || (iobuf[17] == CKDOPER_RDANY && iobuf[20] != 1)) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_4); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* * Read Trackset - X'0E': The Read Trackset Operation Code prepares * the Storage Director to transfer all records from one or more * tracks to the channel. The tracks to be transferred are * specified by the Extended Parameter and the number of tracks to * be transferred is specified by the Count Parameter (byte 3). * * The maximum length of the Extended Parameter is specified in byte * 43 of the Device Characteristics Information. * * The Extended Parameter contains a bit map that represents a set * of sequentially addressed tracks within the defined extent. Each * bit in the parameter represent one track. A '1' bit indicates the * data associated with the corresponding track is to be read. A '0' * bit indicates the track is to be skipped. * * The first bit must be a '1' and represents the track whose * address is specified in the Seek Address parameter (bytes 4-7). * Subsequent bits represent consecutively addressed tracks in * ascending order. If the first bit is not a '1', the Locate Record * Extended command is terminated with status that includes unit * check (Command Reject, format X'04', Invalid Parameter). * * The number of '1' bits in the bit map must be equal to the value * in the count parameter (byte 3); otherwise Locate Record Extended * is terminated with status that includes unit check (Command * Reject, format X'04', Invalid Parameter). * * All tracks in the bit map represented by the '1' bits must be * contained within the defined extent; otherwise the Locate Record * Extended command is terminated with status that includes unit * check (File Protected). * * Track access is initiated using the Seek Address and Sector * Number parameters. * * When track access is completed, the search operation specified by * the Search Argument and the orientation modifiers (byte 0, bits * 0-1) is performed. * * Locate Record Extended must be followed by the number of Read * Track commands specified in the count parameter (byte 3). If any * other command sequence is detected within the Locate Record * domain, the non-conforming command will be rejected with status * that includes Unit Check (Command Reject, format X'02', Invalid * Command Sequence). */ if (iobuf[17] == CKDOPER_RDTSET) { U16 lastcyl, lasthead; U16 mask = iobuf[20] << 8; if (num > 1) mask |= iobuf[21]; if (!(mask & 0x8000)) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_4); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } dev->ckdlmask = mask; /* * Count the one bits in mask. There are elegant but obscure * ways to do this but just keeping it simple here. Plus we * also figure out the last track we will read. */ for (i = j = 0; mask; mask <<= 1) { j++; if (mask & 0x8000) i++; } /* Number of one bits must match count */ if (i != dev->ckdlcount) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_4); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Check extent of last track to be read */ lastcyl = cyl; lasthead = head + j - 1; while (lasthead >= dev->ckdheads) { lastcyl++; lasthead -= dev->ckdheads; } if ( EXTENT_CHECK(dev, lastcyl, lasthead) ) { ckd_build_sense (dev, 0, SENSE1_FP, 0, 0, 0); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } } /* Seek to the required track */ rc = ckd_seek (dev, cyl, head, &trkhdr, unitstat); if (rc < 0) { if (dev->syncio_retry) dev->ckdlcount = 0; break; } /* Set normal status */ *unitstat = CSW_CE | CSW_DE; /* Perform search according to specified orientation */ switch ((dev->ckdloper & CKDOPER_ORIENTATION)) { case CKDOPER_ORIENT_HOME: /* For home orientation, compare the search CCHH with the CCHH in the track header */ if (memcmp (&(trkhdr.cyl), cchhr, 4) != 0) { ckd_build_sense (dev, 0, SENSE1_NRF, 0, 0, 0); *unitstat = CSW_CE | CSW_DE | CSW_UC; } break; case CKDOPER_ORIENT_COUNT: case CKDOPER_ORIENT_DATA: /* For count or data orientation, search the track for a count field matching the specified CCHHR */ while (1) { /* Read next count field and exit at end of track with sense data indicating no record found */ rc = ckd_read_count (dev, code, &rechdr, unitstat); if (rc < 0) break; /* Turn off track overflow flag */ rechdr.cyl[0] &= 0x7F; /* For extended op code skip r0 */ if ((iobuf[0] & CKDOPER_CODE) == CKDOPER_EXTOP) { if (rechdr.rec != 0) break; } /* Compare the count field with the search CCHHR */ else if (memcmp (&rechdr, cchhr, 5) == 0) break; } /* end while */ } /* end switch(CKDOPER_ORIENTATION) */ /* Exit if search ended with error status */ if (*unitstat != (CSW_CE | CSW_DE)) break; /* Reorient past data if data orientation is specified */ if ((dev->ckdloper & CKDOPER_ORIENTATION) == CKDOPER_ORIENT_DATA) { /* Skip past key and data fields */ dev->bufoff += dev->ckdcurkl + dev->ckdcurdl; /* Set the device orientation fields */ dev->ckdrem = 0; dev->ckdorient = CKDORIENT_DATA; } /* Set locate record flag and return normal status */ dev->ckdlocat = 1; break; case 0x63: /*---------------------------------------------------------------*/ /* DEFINE EXTENT */ /*---------------------------------------------------------------*/ { U16 bcyl, bhead, ecyl, ehead, xblksz; BYTE fmask, xgattr; /* Calculate residual byte count */ num = (count < 16) ? count : 16; *residual = count - num; /* Control information length must be at least 16 bytes */ if (count < 16) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_3); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Command reject if within the domain of a Locate Record, or preceded by Define Extent, Space Count, or Set File Mask, or (for 3390 only) preceded by Read IPL */ if (dev->ckdlcount > 0 #if 0 || dev->ckdxtdef #endif || dev->ckdsetfm || dev->ckdspcnt || (dev->ckdrdipl && dev->devtype == 0x3390)) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Bytes 0-1 contain the file mask and global attributes */ fmask = iobuf[0]; xgattr = iobuf[1]; if(dev->ckdxtdef && (dev->ckdfmask != fmask || dev->ckdxgattr != xgattr) ) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } dev->ckdfmask = fmask; dev->ckdxgattr = xgattr; /* Validate the global attributes byte bits 0-1 */ if ((dev->ckdxgattr & CKDGATR_ARCH) != CKDGATR_ARCH_ECKD) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_4); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Validate the file mask */ if ((dev->ckdfmask & CKDMASK_RESV) != 0) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_4); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Bytes 2-3 contain the extent block size */ xblksz = (iobuf[2] << 8) | iobuf[3]; /* If extent block size is zero then use the maximum R0 record length (as returned in device characteristics bytes 44 and 45) plus 8 */ if (xblksz == 0) xblksz = dev->ckdtab->r0 + 8; if(dev->ckdxtdef && dev->ckdxblksz != xblksz ) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } dev->ckdxblksz = xblksz; /* Validate the extent block */ if (dev->ckdxblksz > dev->ckdtab->r0 + 8) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_4); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Bytes 4-6 must contain zeroes */ if (iobuf[4] != 0 || iobuf[5] != 0 || iobuf[6] != 0) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_4); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Bytes 8-11 contain the extent begin cylinder and head */ bcyl = (iobuf[8] << 8) | iobuf[9]; bhead = (iobuf[10] << 8) | iobuf[11]; /* Bytes 12-15 contain the extent end cylinder and head */ ecyl = (iobuf[12] << 8) | iobuf[13]; ehead = (iobuf[14] << 8) | iobuf[15]; /* Validate the extent description by checking that the ending track is not less than the starting track and that the extent does not exceed the already defined extent */ if ( bcyl > ecyl || (bcyl == ecyl && bhead > ehead) || EXTENT_CHECK(dev, bcyl, bhead) || EXTENT_CHECK(dev, ecyl, ehead) ) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, dev->ckdxtdef ? MESSAGE_2 : MESSAGE_4); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Define the new extent */ dev->ckdxbcyl = bcyl; dev->ckdxbhead = bhead; dev->ckdxecyl = ecyl; dev->ckdxehead = ehead; /* Set extent defined flag and return normal status */ dev->ckdxtdef = 1; *unitstat = CSW_CE | CSW_DE; break; } case 0x64: /*---------------------------------------------------------------*/ /* READ DEVICE CHARACTERISTICS */ /*---------------------------------------------------------------*/ /* Command reject if within the domain of a Locate Record */ if (dev->ckdlcount > 0) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Command reject if not 3380 or 3390 or 9345 */ if ((dev->devtype != 0x3380) && (dev->devtype != 0x3390) && (dev->devtype != 0x9345)) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Calculate residual byte count */ num = (count < dev->numdevchar) ? count : dev->numdevchar; *residual = count - num; if (count < dev->numdevchar) *more = 1; /* Copy device characteristics bytes to channel buffer */ memcpy (iobuf, dev->devchar, num); *unitstat = CSW_CE | CSW_DE; break; case 0x3E: /*---------------------------------------------------------------*/ /* READ SUBSYSTEM DATA */ /*---------------------------------------------------------------*/ /* Command reject if within the domain of a Locate Record, or if subsystem data has not been prepared in the channel buffer by a previous Perform Subsystem Function command */ if (dev->ckdlcount > 0 || dev->ckdssdlen == 0) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Calculate residual byte count */ num = (count < dev->ckdssdlen) ? count : dev->ckdssdlen; *residual = count - num; if (count < dev->ckdssdlen) *more = 1; /* Subsystem data is already in the channel buffer, so just return channel end and device end */ *unitstat = CSW_CE | CSW_DE; break; case 0x5B: /*---------------------------------------------------------------*/ /* SUSPEND MULTIPATH RECONNECTION */ /*---------------------------------------------------------------*/ /* Command reject if within the domain of a Locate Record */ if (dev->ckdlcount > 0) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Return normal status */ *unitstat = CSW_CE | CSW_DE; break; case 0xF3: /*---------------------------------------------------------------*/ /* DIAGNOSTIC CONTROL */ /*---------------------------------------------------------------*/ /* Command reject if SSI active */ if(dev->ckdssi) { /* Mark Set Special Intercept inactive */ dev->ckdssi = 0; ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_F); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Calculate residual byte count */ num = (count < 4) ? count : 4; *residual = count - num; /* Control information length must be at least 4 bytes */ if (count < 4) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_3); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Command reject if within the domain of a Locate Record */ if (dev->ckdlcount > 0) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Command reject if byte 0 does not contain a valid subcommand code, or if bytes 2-3 are not zero */ if (!(iobuf[0] == DIAGCTL_MAINT_QUERY // || iobuf[0] == DIAGCTL_MAINT_RESERVE // || iobuf[0] == DIAGCTL_MAINT_RELEASE // || iobuf[0] == DIAGCTL_INHIBIT_WRITE // || iobuf[0] == DIAGCTL_SET_GUAR_PATH // || iobuf[0] == DIAGCTL_ENABLE_WRITE // || iobuf[0] == DIAGCTL_3380_TC_MODE // || iobuf[0] == DIAGCTL_INIT_SUBSYS // || iobuf[0] == DIAGCTL_UNFENCE // || iobuf[0] == DIAGCTL_ACCDEV_UNKCOND ) || iobuf[2] != 0 || iobuf[3] != 0) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_4); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Command reject if file mask does not specify diagnostic or device support authorization */ if ((dev->ckdfmask & CKDMASK_AAUTH) == CKDMASK_AAUTH_NORMAL) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_5); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Return normal status */ *unitstat = CSW_CE | CSW_DE; break; case 0x94: /*---------------------------------------------------------------*/ /* DEVICE RELEASE */ /*---------------------------------------------------------------*/ /* Command reject if within the domain of a Locate Record, or preceded by Define Extent, Space Count, or Set File Mask, or (for 3390 only) preceded by Read IPL */ if (dev->ckdlcount > 0 || dev->ckdxtdef || dev->ckdspcnt || dev->ckdsetfm || (dev->ckdrdipl && dev->devtype == 0x3390)) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Call the release exit and mark the device not reserved */ if (dev->hnd->release) (dev->hnd->release) (dev); obtain_lock (&dev->lock); dev->reserved = 0; release_lock (&dev->lock); /* Perform the operation of a sense command */ goto sense; case 0x14: /* UNCONDITIONAL RESERVE */ case 0xB4: /* DEVICE RESERVE */ /*---------------------------------------------------------------*/ /* DEVICE RESERVE */ /*---------------------------------------------------------------*/ /* Command reject if within the domain of a Locate Record, or indeed if preceded by any command at all apart from Suspend Multipath Reconnection */ if (dev->ckdlcount > 0 || ccwseq > 1 || (chained && prevcode != 0x5B)) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Mark the device reserved and call the reserve exit */ obtain_lock (&dev->lock); dev->reserved = 1; release_lock (&dev->lock); if (dev->hnd->reserve) (dev->hnd->reserve) (dev); /* Perform the operation of a sense command */ goto sense; case 0x04: /*---------------------------------------------------------------*/ /* SENSE */ /*---------------------------------------------------------------*/ /* Command reject if within the domain of a Locate Record */ if (dev->ckdlcount > 0) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } sense: /* If sense bytes are cleared then build sense */ if ((dev->sense[0] == 0) & (dev->sense[1] == 0)) ckd_build_sense (dev, 0, 0, 0, 0, 0); /* Calculate residual byte count */ num = (count < dev->numsense) ? count : dev->numsense; *residual = count - num; if (count < dev->numsense) *more = 1; /* Copy device sense bytes to channel I/O buffer */ memcpy (iobuf, dev->sense, num); /* Clear the device sense bytes */ memset (dev->sense, 0, sizeof(dev->sense)); *unitstat = CSW_CE | CSW_DE; break; case 0xE4: /*---------------------------------------------------------------*/ /* SENSE ID */ /*---------------------------------------------------------------*/ /* If numdevid is 0, then 0xE4 Sense ID is not supported */ if (dev->numdevid == 0) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_1); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Command reject if within the domain of a Locate Record */ if (dev->ckdlcount > 0) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Calculate residual byte count */ num = (count < dev->numdevid) ? count : dev->numdevid; *residual = count - num; if (count < dev->numdevid) *more = 1; /* Copy device identifier bytes to channel I/O buffer */ memcpy (iobuf, dev->devid, num); /* Return unit status */ *unitstat = CSW_CE | CSW_DE; break; case 0x34: /*---------------------------------------------------------------*/ /* SENSE PATH GROUP ID */ /*---------------------------------------------------------------*/ /* Calculate residual byte count */ num = (count < 12) ? count : 12; *residual = count - num; if (count < 12) *more = 1; /* Byte 0 is the path group state byte */ iobuf[0] = SPG_PATHSTAT_RESET | SPG_PARTSTAT_IENABLED | SPG_PATHMODE_SINGLE; /* Bytes 1-11 contain the path group identifier */ memcpy (iobuf+1, dev->pgid, 11); /* Return unit status */ *unitstat = CSW_CE | CSW_DE; break; case 0xAF: /*---------------------------------------------------------------*/ /* SET PATH GROUP ID */ /*---------------------------------------------------------------*/ /* Calculate residual byte count */ num = (count < 12) ? count : 12; *residual = count - num; /* Control information length must be at least 12 bytes */ if (count < 12) { dev->sense[0] = SENSE_CR; *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Byte 0 is the path group state byte */ if ((iobuf[0] & SPG_SET_COMMAND) == SPG_SET_ESTABLISH) { /* Only accept the new pathgroup id when 1) it has not yet been set (ie contains zeros) or 2) It is set, but we are setting the same value */ if(memcmp(dev->pgid, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 11) && memcmp(dev->pgid, iobuf+1, 11)) { dev->sense[0] = SENSE_CR; *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Bytes 1-11 contain the path group identifier */ memcpy (dev->pgid, iobuf+1, 11); } /* Return unit status */ *unitstat = CSW_CE | CSW_DE; break; case 0x54: /*---------------------------------------------------------------*/ /* SENSE SUBSYSTEM STATUS */ /*---------------------------------------------------------------*/ /* Command reject if within the domain of a Locate Record, or if chained from any command unless the preceding command is Read Device Characteristics, Read Configuration Data, or a Suspend Multipath Reconnection command that was the first command in the chain */ if (dev->ckdlcount > 0 || (chained && prevcode != 0x64 && prevcode != 0xFA && prevcode != 0x5B) || (chained && prevcode == 0x5B && ccwseq > 1)) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Build the basic subsystem status data in the I/O area */ num = dasd_build_ckd_subsys_status (dev, iobuf, count); /* Calculate residual byte count */ *residual = count < num ? 0 : count - num; *more = count < num; /* Return unit status */ *unitstat = CSW_CE | CSW_DE; break; case 0xA4: /*---------------------------------------------------------------*/ /* READ AND RESET BUFFERED LOG */ /*---------------------------------------------------------------*/ /* Command reject if within the domain of a Locate Record, or if chained from any command unless the preceding command is Read Device Characteristics, Read Configuration Data, or a Suspend Multipath Reconnection command that was the first command in the chain */ if (dev->ckdlcount > 0 || (chained && prevcode != 0x64 && prevcode != 0xFA && prevcode != 0x5B) || (chained && prevcode == 0x5B && ccwseq > 1)) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Calculate residual byte count */ num = (count < 32) ? count : 32; *residual = count - num; if (count < 32) *more = 1; /* Build the buffered error log in the I/O area */ memset (iobuf, 0x00, 32); /* Return unit status */ *unitstat = CSW_CE | CSW_DE; break; case 0xFA: /*---------------------------------------------------------------*/ /* READ CONFIGURATION DATA */ /*---------------------------------------------------------------*/ /* Command reject if within the domain of a Locate Record */ if (dev->ckdlcount > 0) { ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_2); *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Build the configuration data area */ num = dasd_build_ckd_config_data (dev, iobuf, count); /* Calculate residual byte count */ *residual = count < num ? 0 : count - num; *more = count < num; /* Return unit status */ *unitstat = CSW_CE | CSW_DE; break; default: /*---------------------------------------------------------------*/ /* INVALID OPERATION */ /*---------------------------------------------------------------*/ /* Set command reject sense byte, and unit check status */ ckd_build_sense (dev, SENSE_CR, 0, 0, FORMAT_0, MESSAGE_1); *unitstat = CSW_CE | CSW_DE | CSW_UC; } /* end switch(code) */ /* Return if synchronous I/O needs to be retried asynchronously */ if (dev->syncio_retry) return; /* Reset the flags which ensure correct positioning for write commands */ /* Reset search HA flag if command was not SEARCH HA EQUAL or WRITE HA */ if ((code & 0x7F) != 0x39 && (code & 0x7F) != 0x19) dev->ckdhaeq = 0; /* Reset search id flag if command was not SEARCH ID EQUAL, READ/WRITE KEY AND DATA, or READ/WRITE DATA */ if ((code & 0x7F) != 0x31 && (code & 0x7F) != 0x0E && (code & 0x7F) != 0x0D && (code & 0x7F) != 0x06 && (code & 0x7F) != 0x05) dev->ckdideq = 0; /* Reset search key flag if command was not SEARCH KEY EQUAL or READ/WRITE DATA */ if ((code & 0x7F) != 0x29 && (code & 0x7F) != 0x06 && (code & 0x7F) != 0x05) dev->ckdkyeq = 0; /* Reset write CKD flag if command was not WRITE R0 or WRITE CKD */ if (code != 0x15 && code != 0x1D) dev->ckdwckd = 0; /* If within the domain of a locate record then decrement the count of CCWs remaining to be processed within the domain */ if (dev->ckdlcount > 0 && code != 0x047 && code != 0x4B) { /* Decrement the count of CCWs remaining in the domain */ dev->ckdlcount--; /* Command reject with incomplete domain if CCWs remain but command chaining is not specified */ if (dev->ckdlcount > 0 && (flags & CCW_FLAGS_CC) == 0 && code != 0x02) { ckd_build_sense (dev, SENSE_CR | SENSE_OC, 0, 0, 0, 0); *unitstat = CSW_CE | CSW_DE | CSW_UC; } } /* end if(ckdlcount) */ } /* end function ckddasd_execute_ccw */ DLL_EXPORT DEVHND ckddasd_device_hndinfo = { &ckddasd_init_handler, /* Device Initialisation */ &ckddasd_execute_ccw, /* Device CCW execute */ &ckddasd_close_device, /* Device Close */ &ckddasd_query_device, /* Device Query */ &ckddasd_start, /* Device Start channel pgm */ &ckddasd_end, /* Device End channel pgm */ &ckddasd_start, /* Device Resume channel pgm */ &ckddasd_end, /* Device Suspend channel pgm */ &ckddasd_read_track, /* Device Read */ &ckddasd_update_track, /* Device Write */ &ckddasd_used, /* Device Query used */ NULL, /* Device Reserve */ NULL, /* Device Release */ NULL, /* Device Attention */ NULL, /* Immediate CCW Codes */ NULL, /* Signal Adapter Input */ NULL, /* Signal Adapter Ouput */ &ckddasd_hsuspend, /* Hercules suspend */ &ckddasd_hresume /* Hercules resume */ }; hercules-3.07/clock.c000644 000765 000765 00000046054 11143760543 016217 0ustar00jmaynardjmaynard000000 000000 /* CLOCK.C (c) Copyright Jan Jaeger, 2000-2009 */ /* TOD Clock functions */ // $Id: clock.c 5124 2009-01-23 11:44:03Z bernard $ /* The emulated hardware clock is based on the host clock, adjusted */ /* by means of an offset and a steering rate. */ // $Log$ // Revision 1.43 2008/08/22 04:43:50 fish // Fix TOD clock race condition identified by Fred // Feucht -- by Marcin Cieslak [saper@system.pl] // // Revision 1.42 2007/11/21 22:55:49 fish // (untab) // // Revision 1.41 2007/06/23 00:04:04 ivan // Update copyright notices to include current year (2007) // // Revision 1.40 2006/12/08 09:43:18 jj // Add CVS message log // #include "hstdinc.h" #if !defined(_HENGINE_DLL_) #define _HENGINE_DLL_ #endif #include "hercules.h" #include "opcode.h" #include "inline.h" #include "sr.h" #if !defined(_CLOCK_C_) #define _CLOCK_C_ #include "clock.h" // static int clock_state = CC_CLOCK_SET; static CSR old; static CSR new; static CSR *current = &new; void csr_reset() { new.start_time = 0; new.base_offset = 0; new.fine_s_rate = 0; new.gross_s_rate = 0; current = &new; old = new; } static U64 universal_tod; static U64 universal_clock(void) /* really: any clock used as a base */ { struct timeval tv; gettimeofday (&tv, NULL); /* Load number of seconds since 00:00:00 01 Jan 1970 */ universal_tod = (U64)tv.tv_sec; universal_tod += SECONDS_IN_SEVENTY_YEARS; /* Convert to microseconds */ universal_tod = (universal_tod * 1000000) + tv.tv_usec; /* Shift left 4 bits so that bits 0-7=TOD Clock Epoch, bits 8-59=TOD Clock bits 0-51, bits 60-63=zero */ universal_tod <<= 4; return universal_tod; } /* The hercules hardware clock, based on the universal clock, but */ /* running at its own speed as optionally set by set_tod_steering() */ /* The hardware clock returns a unique value */ static double hw_steering = 0.0; /* Current TOD clock steering rate */ static U64 hw_episode; /* TOD of start of steering episode */ static S64 hw_offset = 0; /* Current offset between TOD and HW */ // static U64 hw_tod = 0; /* Globally defined in clock.h */ static inline U64 hw_adjust(U64 base_tod) { /* Apply hardware offset, this is the offset achieved by all previous steering episodes */ base_tod += hw_offset; /* Apply the steering offset from the current steering episode */ base_tod += (S64)(base_tod - hw_episode) * hw_steering; /* Ensure that the clock returns a unique value */ if(hw_tod < base_tod) return base_tod; else return hw_tod += 0x10; } U64 hw_clock(void) { U64 temp_tod; obtain_lock(&sysblk.todlock); /* Get the time of day (GMT) */ temp_tod = universal_clock(); /* Ajust speed and ensure uniqueness */ hw_tod = hw_adjust(temp_tod); release_lock(&sysblk.todlock); return hw_tod; } static U64 hw_clock_l(void) { hw_tod = hw_adjust(universal_clock()); return hw_tod; } /* set_tod_steering(double) sets a new steering rate. */ /* When a new steering episode begins, the offset is adjusted, */ /* and the new steering rate takes effect */ void set_tod_steering(double steering) { obtain_lock(&sysblk.todlock); hw_offset = hw_clock_l() - universal_tod; hw_episode = hw_tod; hw_steering = steering; release_lock(&sysblk.todlock); } /* Start a new episode */ static inline void start_new_episode() { hw_offset = hw_tod - universal_tod; hw_episode = hw_tod; new.start_time = hw_episode; hw_steering = ldexp(2,-44) * (S32)(new.fine_s_rate + new.gross_s_rate); current = &new; } /* Prepare for a new episode */ static inline void prepare_new_episode() { if(current == &new) { old = new; current = &old; } } /* Ajust the epoch for all active cpu's in the configuration */ static U64 adjust_epoch_cpu_all(U64 epoch) { int cpu; /* Update the TOD clock of all CPU's in the configuration as we simulate 1 shared TOD clock, and do not support the TOD clock sync check */ for (cpu = 0; cpu < MAX_CPU; cpu++) { obtain_lock(&sysblk.cpulock[cpu]); if (IS_CPU_ONLINE(cpu)) sysblk.regs[cpu]->tod_epoch = epoch; release_lock(&sysblk.cpulock[cpu]); } return epoch; } double get_tod_steering(void) { return hw_steering; } void set_tod_epoch(S64 epoch) { obtain_lock(&sysblk.todlock); csr_reset(); tod_epoch = epoch; release_lock(&sysblk.todlock); adjust_epoch_cpu_all(epoch); } void adjust_tod_epoch(S64 epoch) { obtain_lock(&sysblk.todlock); csr_reset(); tod_epoch += epoch; release_lock(&sysblk.todlock); adjust_epoch_cpu_all(tod_epoch); } void set_tod_clock(U64 tod) { set_tod_epoch(tod - hw_clock()); } S64 get_tod_epoch() { return tod_epoch; } static void set_gross_steering_rate(S32 gsr) { obtain_lock(&sysblk.todlock); prepare_new_episode(); new.gross_s_rate = gsr; release_lock(&sysblk.todlock); } static void set_fine_steering_rate(S32 fsr) { obtain_lock(&sysblk.todlock); prepare_new_episode(); new.fine_s_rate = fsr; release_lock(&sysblk.todlock); } static void set_tod_offset(S64 offset) { obtain_lock(&sysblk.todlock); prepare_new_episode(); new.base_offset = offset; release_lock(&sysblk.todlock); } static void adjust_tod_offset(S64 offset) { obtain_lock(&sysblk.todlock); prepare_new_episode(); new.base_offset = old.base_offset + offset; release_lock(&sysblk.todlock); } /* The cpu timer is internally kept as an offset to the hw_clock() * the cpu timer counts down as the clock approaches the timer epoch */ void set_cpu_timer(REGS *regs, S64 timer) { regs->cpu_timer = (timer >> 8) + hw_clock(); } S64 cpu_timer(REGS *regs) { S64 timer; timer = (regs->cpu_timer - hw_clock()) << 8; return timer; } U64 tod_clock(REGS *regs) { U64 current_tod; obtain_lock(&sysblk.todlock); current_tod = hw_clock_l(); /* If we are in the old episode, and the new episode has arrived then we must take action to start the new episode */ if(current == &old) start_new_episode(); /* Set the clock to the new updated value with offset applied */ current_tod += current->base_offset; tod_value = current_tod; release_lock(&sysblk.todlock); return current_tod + regs->tod_epoch; } #if defined(_FEATURE_INTERVAL_TIMER) #if defined(_FEATURE_ECPSVM) static inline S32 ecps_vtimer(REGS *regs) { return (S32)TOD_TO_ITIMER((S64)(regs->ecps_vtimer - hw_clock())); } static inline void set_ecps_vtimer(REGS *regs, S32 vtimer) { regs->ecps_vtimer = (U64)(hw_clock() + ITIMER_TO_TOD(vtimer)); regs->ecps_oldtmr = vtimer; } #endif /*defined(_FEATURE_ECPSVM)*/ S32 int_timer(REGS *regs) { return (S32)TOD_TO_ITIMER((S64)(regs->int_timer - hw_clock())); } void set_int_timer(REGS *regs, S32 itimer) { regs->int_timer = (U64)(hw_clock() + ITIMER_TO_TOD(itimer)); regs->old_timer = itimer; } int chk_int_timer(REGS *regs) { S32 itimer; int pending = 0; itimer = int_timer(regs); if(itimer < 0 && regs->old_timer >= 0) { ON_IC_ITIMER(regs); pending = 1; } #if defined(_FEATURE_ECPSVM) if(regs->ecps_vtmrpt) { itimer = ecps_vtimer(regs); if(itimer < 0 && regs->ecps_oldtmr >= 0) { ON_IC_ECPSVTIMER(regs); pending += 2; } } #endif /*defined(_FEATURE_ECPSVM)*/ return pending; } #endif /*defined(_FEATURE_INTERVAL_TIMER)*/ /*-------------------------------------------------------------------*/ /* Update TOD clock */ /* */ /* This function updates the TOD clock. */ /* */ /* This function is called by timer_update_thread and by cpu_thread */ /* instructions that manipulate any of the timer related entities */ /* (clock comparator, cpu timer and interval timer). */ /* */ /* Internal function `check_timer_event' is called which will signal */ /* any timer related interrupts to the appropriate cpu_thread. */ /* */ /* Callers *must* own the todlock and *must not* own the intlock. */ /* */ /* update_tod_clock() returns the tod delta, by which the cpu timer */ /* has been adjusted. */ /* */ /*-------------------------------------------------------------------*/ // static U64 tod_value; U64 update_tod_clock(void) { U64 new_clock; obtain_lock(&sysblk.todlock); new_clock = hw_clock_l(); /* If we are in the old episode, and the new episode has arrived then we must take action to start the new episode */ if(current == &old) start_new_episode(); /* Set the clock to the new updated value with offset applied */ new_clock += current->base_offset; tod_value = new_clock; release_lock(&sysblk.todlock); /* Update the timers and check if either a clock related event has become pending */ update_cpu_timer(); return new_clock; } #define SR_SYS_CLOCK_CURRENT_CSR ( SR_SYS_CLOCK | 0x001 ) #define SR_SYS_CLOCK_UNIVERSAL_TOD ( SR_SYS_CLOCK | 0x002 ) #define SR_SYS_CLOCK_HW_STEERING ( SR_SYS_CLOCK | 0x004 ) #define SR_SYS_CLOCK_HW_EPISODE ( SR_SYS_CLOCK | 0x005 ) #define SR_SYS_CLOCK_HW_OFFSET ( SR_SYS_CLOCK | 0x006 ) #define SR_SYS_CLOCK_OLD_CSR ( SR_SYS_CLOCK | 0x100 ) #define SR_SYS_CLOCK_OLD_CSR_START_TIME ( SR_SYS_CLOCK | 0x101 ) #define SR_SYS_CLOCK_OLD_CSR_BASE_OFFSET ( SR_SYS_CLOCK | 0x102 ) #define SR_SYS_CLOCK_OLD_CSR_FINE_S_RATE ( SR_SYS_CLOCK | 0x103 ) #define SR_SYS_CLOCK_OLD_CSR_GROSS_S_RATE ( SR_SYS_CLOCK | 0x104 ) #define SR_SYS_CLOCK_NEW_CSR ( SR_SYS_CLOCK | 0x200 ) #define SR_SYS_CLOCK_NEW_CSR_START_TIME ( SR_SYS_CLOCK | 0x201 ) #define SR_SYS_CLOCK_NEW_CSR_BASE_OFFSET ( SR_SYS_CLOCK | 0x202 ) #define SR_SYS_CLOCK_NEW_CSR_FINE_S_RATE ( SR_SYS_CLOCK | 0x203 ) #define SR_SYS_CLOCK_NEW_CSR_GROSS_S_RATE ( SR_SYS_CLOCK | 0x204 ) int clock_hsuspend(void *file) { int i; char buf[SR_MAX_STRING_LENGTH]; i = (current == &new); SR_WRITE_VALUE(file, SR_SYS_CLOCK_CURRENT_CSR, i, sizeof(i)); SR_WRITE_VALUE(file, SR_SYS_CLOCK_UNIVERSAL_TOD, universal_tod, sizeof(universal_tod)); snprintf(buf, sizeof(buf), "%f", hw_steering); SR_WRITE_STRING(file, SR_SYS_CLOCK_HW_STEERING, buf); SR_WRITE_VALUE(file, SR_SYS_CLOCK_HW_EPISODE, hw_episode, sizeof(hw_episode)); SR_WRITE_VALUE(file, SR_SYS_CLOCK_HW_OFFSET, hw_offset, sizeof(hw_offset)); SR_WRITE_VALUE(file, SR_SYS_CLOCK_OLD_CSR_START_TIME, old.start_time, sizeof(old.start_time)); SR_WRITE_VALUE(file, SR_SYS_CLOCK_OLD_CSR_BASE_OFFSET, old.base_offset, sizeof(old.base_offset)); SR_WRITE_VALUE(file, SR_SYS_CLOCK_OLD_CSR_FINE_S_RATE, old.fine_s_rate, sizeof(old.fine_s_rate)); SR_WRITE_VALUE(file, SR_SYS_CLOCK_OLD_CSR_GROSS_S_RATE, old.gross_s_rate, sizeof(old.gross_s_rate)); SR_WRITE_VALUE(file, SR_SYS_CLOCK_NEW_CSR_START_TIME, new.start_time, sizeof(new.start_time)); SR_WRITE_VALUE(file, SR_SYS_CLOCK_NEW_CSR_BASE_OFFSET, new.base_offset, sizeof(new.base_offset)); SR_WRITE_VALUE(file, SR_SYS_CLOCK_NEW_CSR_FINE_S_RATE, new.fine_s_rate, sizeof(new.fine_s_rate)); SR_WRITE_VALUE(file, SR_SYS_CLOCK_NEW_CSR_GROSS_S_RATE, new.gross_s_rate, sizeof(new.gross_s_rate)); return 0; } int clock_hresume(void *file) { size_t key, len; int i; float f; char buf[SR_MAX_STRING_LENGTH]; memset(&old, 0, sizeof(CSR)); memset(&new, 0, sizeof(CSR)); current = &new; universal_tod = 0; hw_steering = 0.0; hw_episode = 0; hw_offset = 0; do { SR_READ_HDR(file, key, len); switch (key) { case SR_SYS_CLOCK_CURRENT_CSR: SR_READ_VALUE(file, len, &i, sizeof(i)); current = i ? &new : &old; break; case SR_SYS_CLOCK_UNIVERSAL_TOD: SR_READ_VALUE(file, len, &universal_tod, sizeof(universal_tod)); break; case SR_SYS_CLOCK_HW_STEERING: SR_READ_STRING(file, buf, len); sscanf(buf, "%f",&f); hw_steering = f; break; case SR_SYS_CLOCK_HW_EPISODE: SR_READ_VALUE(file, len, &hw_episode, sizeof(hw_episode)); break; case SR_SYS_CLOCK_HW_OFFSET: SR_READ_VALUE(file, len, &hw_offset, sizeof(hw_offset)); break; case SR_SYS_CLOCK_OLD_CSR_START_TIME: SR_READ_VALUE(file, len, &old.start_time, sizeof(old.start_time)); break; case SR_SYS_CLOCK_OLD_CSR_BASE_OFFSET: SR_READ_VALUE(file, len, &old.base_offset, sizeof(old.base_offset)); break; case SR_SYS_CLOCK_OLD_CSR_FINE_S_RATE: SR_READ_VALUE(file, len, &old.fine_s_rate, sizeof(old.fine_s_rate)); break; case SR_SYS_CLOCK_OLD_CSR_GROSS_S_RATE: SR_READ_VALUE(file, len, &old.gross_s_rate, sizeof(old.gross_s_rate)); break; case SR_SYS_CLOCK_NEW_CSR_START_TIME: SR_READ_VALUE(file, len, &new.start_time, sizeof(new.start_time)); break; case SR_SYS_CLOCK_NEW_CSR_BASE_OFFSET: SR_READ_VALUE(file, len, &new.base_offset, sizeof(new.base_offset)); break; case SR_SYS_CLOCK_NEW_CSR_FINE_S_RATE: SR_READ_VALUE(file, len, &new.fine_s_rate, sizeof(new.fine_s_rate)); break; case SR_SYS_CLOCK_NEW_CSR_GROSS_S_RATE: SR_READ_VALUE(file, len, &new.gross_s_rate, sizeof(new.gross_s_rate)); break; default: SR_READ_SKIP(file, len); break; } } while ((key & SR_SYS_MASK) == SR_SYS_CLOCK); return 0; } #endif #if defined(FEATURE_INTERVAL_TIMER) static void ARCH_DEP(_store_int_timer_2) (REGS *regs,int getlock) { S32 itimer; S32 vtimer=0; FETCH_FW(itimer, regs->psa->inttimer); if(getlock) { OBTAIN_INTLOCK(regs->hostregs?regs:NULL); } if(itimer != regs->old_timer) { // ZZ logmsg(D_("Interval timer out of sync, core=%8.8X, internal=%8.8X\n"), itimer, regs->old_timer); set_int_timer(regs, itimer); } else { itimer=int_timer(regs); } STORE_FW(regs->psa->inttimer, itimer); #if defined(FEATURE_ECPSVM) if(regs->ecps_vtmrpt) { FETCH_FW(vtimer, regs->ecps_vtmrpt); if(vtimer != regs->ecps_oldtmr) { // ZZ logmsg(D_("ECPS vtimer out of sync, core=%8.8X, internal=%8.8X\n"), itimer, regs->ecps_vtimer); set_ecps_vtimer(regs, itimer); } else { vtimer=ecps_vtimer(regs); } STORE_FW(regs->ecps_vtmrpt, itimer); } #endif /*defined(FEATURE_ECPSVM)*/ /* ISW : Invoke chk_int_timer *before* setting old_timer */ /* however, the value must be one fetched *before* */ /* chk_int_timer was invoked otherwise a window */ /* exists during which the interval timer could go */ /* negative undetected */ chk_int_timer(regs); regs->old_timer = itimer; #if defined(FEATURE_ECPSVM) if(regs->ecps_vtmrpt) { regs->ecps_oldtmr = vtimer; } #endif /*defined(FEATURE_ECPSVM)*/ if(getlock) { RELEASE_INTLOCK(regs->hostregs?regs:NULL); } } DLL_EXPORT void ARCH_DEP(store_int_timer) (REGS *regs) { ARCH_DEP(_store_int_timer_2) (regs,1); } void ARCH_DEP(store_int_timer_nolock) (REGS *regs) { ARCH_DEP(_store_int_timer_2) (regs,0); } DLL_EXPORT void ARCH_DEP(fetch_int_timer) (REGS *regs) { S32 itimer; FETCH_FW(itimer, regs->psa->inttimer); OBTAIN_INTLOCK(regs->hostregs?regs:NULL); set_int_timer(regs, itimer); #if defined(FEATURE_ECPSVM) if(regs->ecps_vtmrpt) { FETCH_FW(itimer, regs->ecps_vtmrpt); set_ecps_vtimer(regs, itimer); } #endif /*defined(FEATURE_ECPSVM)*/ RELEASE_INTLOCK(regs->hostregs?regs:NULL); } #endif #if defined(FEATURE_TOD_CLOCK_STEERING) void ARCH_DEP(set_gross_s_rate) (REGS *regs) { S32 gsr; gsr = ARCH_DEP(vfetch4) (regs->GR(1) & ADDRESS_MAXWRAP(regs), 1, regs); set_gross_steering_rate(gsr); } void ARCH_DEP(set_fine_s_rate) (REGS *regs) { S32 fsr; fsr = ARCH_DEP(vfetch4) (regs->GR(1) & ADDRESS_MAXWRAP(regs), 1, regs); set_fine_steering_rate(fsr); } void ARCH_DEP(set_tod_offset) (REGS *regs) { S64 offset; offset = ARCH_DEP(vfetch8) (regs->GR(1) & ADDRESS_MAXWRAP(regs), 1, regs); set_tod_offset(offset >> 8); } void ARCH_DEP(adjust_tod_offset) (REGS *regs) { S64 offset; offset = ARCH_DEP(vfetch8) (regs->GR(1) & ADDRESS_MAXWRAP(regs), 1, regs); adjust_tod_offset(offset >> 8); } void ARCH_DEP(query_physical_clock) (REGS *regs) { ARCH_DEP(vstore8) (universal_clock() << 8, regs->GR(1) & ADDRESS_MAXWRAP(regs), 1, regs); } void ARCH_DEP(query_steering_information) (REGS *regs) { PTFFQSI qsi; obtain_lock(&sysblk.todlock); STORE_DW(qsi.physclk, universal_clock() << 8); STORE_DW(qsi.oldestart, old.start_time << 8); STORE_DW(qsi.oldebase, old.base_offset << 8); STORE_FW(qsi.oldfsr, old.fine_s_rate ); STORE_FW(qsi.oldgsr, old.gross_s_rate ); STORE_DW(qsi.newestart, new.start_time << 8); STORE_DW(qsi.newebase, new.base_offset << 8); STORE_FW(qsi.newfsr, new.fine_s_rate ); STORE_FW(qsi.newgsr, new.gross_s_rate ); release_lock(&sysblk.todlock); ARCH_DEP(vstorec) (&qsi, sizeof(qsi)-1, regs->GR(1) & ADDRESS_MAXWRAP(regs), 1, regs); } void ARCH_DEP(query_tod_offset) (REGS *regs) { PTFFQTO qto; obtain_lock(&sysblk.todlock); STORE_DW(qto.todoff, (hw_clock_l() - universal_tod) << 8); STORE_DW(qto.physclk, universal_tod << 8); STORE_DW(qto.ltodoff, current->base_offset << 8); STORE_DW(qto.todepoch, regs->tod_epoch << 8); release_lock(&sysblk.todlock); ARCH_DEP(vstorec) (&qto, sizeof(qto)-1, regs->GR(1) & ADDRESS_MAXWRAP(regs), 1, regs); } void ARCH_DEP(query_available_functions) (REGS *regs) { PTFFQAF qaf; STORE_FW(qaf.sb[0] , 0xF0000000); /* Functions 0x00..0x1F */ STORE_FW(qaf.sb[1] , 0x00000000); /* Functions 0x20..0x3F */ STORE_FW(qaf.sb[2] , 0xF0000000); /* Functions 0x40..0x5F */ STORE_FW(qaf.sb[3] , 0x00000000); /* Functions 0x60..0x7F */ ARCH_DEP(vstorec) (&qaf, sizeof(qaf)-1, regs->GR(1) & ADDRESS_MAXWRAP(regs), 1, regs); } #endif /*defined(FEATURE_TOD_CLOCK_STEERING)*/ #if !defined(_GEN_ARCH) #if defined(_ARCHMODE2) #define _GEN_ARCH _ARCHMODE2 #include "clock.c" #endif #if defined(_ARCHMODE3) #undef _GEN_ARCH #define _GEN_ARCH _ARCHMODE3 #include "clock.c" #endif #endif /*!defined(_GEN_ARCH)*/ hercules-3.07/clock.h000644 000765 000765 00000011110 11143760543 016205 0ustar00jmaynardjmaynard000000 000000 /* CLOCK.H (c) Copyright Jan Jaeger, 2000-2009 */ /* TOD Clock functions */ // $Id: clock.h 5125 2009-01-23 12:01:44Z bernard $ // // $Log$ // Revision 1.28 2007/12/11 15:03:10 rbowler // Fix untab columns // // Revision 1.27 2007/12/10 23:12:02 gsmith // Tweaks to OPTION_MIPS_COUNTING processing // // Revision 1.26 2007/11/21 22:55:49 fish // (untab) // // Revision 1.25 2007/06/23 00:04:04 ivan // Update copyright notices to include current year (2007) // // Revision 1.24 2006/12/08 09:43:18 jj // Add CVS message log // #if !defined(_CLOCK_C_) #define _CLOCK_EXTERN extern #else #undef _CLOCK_EXTERN #define _CLOCK_EXTERN #endif #if !defined(_CLOCK_H_) #define _CLOCK_H_ /* Clock Steering Registers */ typedef struct _CSR { U64 start_time; S64 base_offset; S32 fine_s_rate; S32 gross_s_rate; } CSR; void csr_reset(void); /* Reset cs registers */ void set_tod_steering(double); /* Set steering rate */ double get_tod_steering(void); /* Get steering rate */ U64 update_tod_clock(void); /* Update the TOD clock */ void update_cpu_timer(void); /* Update the CPU timer */ void set_tod_epoch(S64); /* Set TOD epoch */ void adjust_tod_epoch(S64); /* Adjust TOD epoch */ S64 get_tod_epoch(void); /* Get TOD epoch */ U64 hw_clock(void); /* Get hardware clock */ S64 cpu_timer(REGS *); /* Retrieve CPU timer */ void set_cpu_timer(REGS *, S64); /* Set CPU timer */ S32 int_timer(REGS *); /* Get interval timer */ void set_int_timer(REGS *, S32); /* Set interval timer */ U64 tod_clock(REGS *); /* Get TOD clock */ void set_tod_clock(U64); /* Set TOD clock */ int chk_int_timer(REGS *); /* Check int_timer pending */ int clock_hsuspend(void *file); /* Hercules suspend */ int clock_hresume(void *file); /* Hercules resume */ static __inline__ U64 host_tod(void) { struct timeval tv; gettimeofday (&tv, NULL); return (U64)tv.tv_sec*1000000 + tv.tv_usec; } #endif DLL_EXPORT void ARCH_DEP(store_int_timer) (REGS *); void ARCH_DEP(store_int_timer_nolock) (REGS *); DLL_EXPORT void ARCH_DEP(fetch_int_timer) (REGS *); void ARCH_DEP(set_gross_s_rate) (REGS *); void ARCH_DEP(set_fine_s_rate) (REGS *); void ARCH_DEP(set_tod_offset) (REGS *); void ARCH_DEP(adjust_tod_offset) (REGS *); void ARCH_DEP(query_physical_clock) (REGS *); void ARCH_DEP(query_steering_information) (REGS *); void ARCH_DEP(query_tod_offset) (REGS *); void ARCH_DEP(query_available_functions) (REGS *); _CLOCK_EXTERN U64 tod_value; /* Bits 0-7 TOD clock epoch */ /* Bits b-63 TOD bits 0-55 */ _CLOCK_EXTERN S64 tod_epoch; /* Bits 0-7 TOD clock epoch */ /* Bits 8-63 offset bits 0-55*/ _CLOCK_EXTERN U64 hw_tod; /* Hardware clock */ #define SECONDS_IN_SEVENTY_YEARS ((70*365 + 17) * 86400ULL) #define TOD_4YEARS (1461*24*60*60*16000000LL) #define TOD_LYEAR (366*24*60*60*16000000LL) #define TOD_YEAR (365*24*60*60*16000000LL) #define TOD_DAY (24*60*60*16000000LL) #define TOD_HOUR (60*60*16000000LL) #define TOD_MIN (60*16000000LL) #define TOD_SEC (16000000LL) #define TOD_USEC (16LL) #define ITIMER_TO_TOD(_units) \ ((S64)(625*((S64)(_units))/3)) #define TOD_TO_ITIMER(_units) \ ((S32)(3*(_units)/625)) #define TOD_CLOCK(_regs) \ (tod_value + (_regs)->tod_epoch) #define CPU_TIMER(_regs) \ ((S64)((_regs)->cpu_timer - hw_tod)) #define INT_TIMER(_regs) \ ((S32)TOD_TO_ITIMER((S64)((_regs)->int_timer - hw_tod))) #define ITIMER_ACCESS(_addr, _len) \ (unlikely(unlikely((_addr) < 84) && (((_addr) + (_len)) >= 80))) #undef ITIMER_UPDATE #undef ITIMER_SYNC #if defined(FEATURE_INTERVAL_TIMER) #define ITIMER_UPDATE(_addr, _len, _regs) \ do { \ if( ITIMER_ACCESS((_addr), (_len)) ) \ ARCH_DEP(fetch_int_timer) ((_regs)); \ } while(0) #define ITIMER_SYNC(_addr, _len, _regs) \ do { \ if( ITIMER_ACCESS((_addr), (_len)) ) \ ARCH_DEP(store_int_timer) ((_regs)); \ } while (0) #else #define ITIMER_UPDATE(_addr, _len, _regs) #define ITIMER_SYNC(_addr, _len, _regs) #endif hercules-3.07/cmdtab.c000644 000765 000765 00000032450 11301535254 016344 0ustar00jmaynardjmaynard000000 000000 /* CMDTAB.C (c) Copyright Roger Bowler, 1999-2009 */ /* (c) Copyright "Fish" (David B. Trout), 2002-2009 */ /* (c) Copyright Jan Jaeger, 2003-2009 */ /* Route all Hercules configuration statements */ /* and panel commands to the appropriate functions */ // $Id: cmdtab.c 5457 2009-09-01 16:29:56Z bernard $ // $Log$ // Revision 1.3 2009/01/19 12:16:57 rbowler // Fix dynamic linkage errors in cmdtab.c for MSVC // // Revision 1.2 2009/01/18 21:43:59 jj // Always display short help info, detailed info only if available // // Revision 1.1 2009/01/18 20:49:25 jj // Rework command table and move to separate source files // #include "hstdinc.h" #define _CMDTAB_C_ #define _HENGINE_DLL_ #include "hercules.h" #include "history.h" // Handle externally defined commands... // (for use in CMDTAB COMMAND entry further below) #define EXT_CMD(xxx_cmd) call_ ## xxx_cmd // (for defining routing function immediately below) #define CALL_EXT_CMD(xxx_cmd) \ int call_ ## xxx_cmd ( int argc, char *argv[], char *cmdline ) { \ return xxx_cmd ( argc, argv, cmdline ); } // Externally defined commands routing functions... CALL_EXT_CMD ( ptt_cmd ) CALL_EXT_CMD ( cache_cmd ) CALL_EXT_CMD ( shared_cmd ) /*-------------------------------------------------------------------*/ /* Create forward references for all commands in the command table */ /*-------------------------------------------------------------------*/ #define _FW_REF #define COMMAND(_stmt, _type, _func, _sdesc, _ldesc) \ int (_func)(int argc, char *argv[], char *cmdline); #define CMDABBR(_stmt, _abbr, _type, _func, _sdesc, _ldesc) \ int (_func)(int argc, char *argv[], char *cmdline); #include "cmdtab.h" #undef COMMAND #undef CMDABBR #undef _FW_REF typedef int CMDFUNC(int argc, char *argv[], char *cmdline); /* Layout of command routing table */ typedef struct _CMDTAB { const char *statement; /* statement */ const size_t statminlen; /* min abbreviation */ int type; /* statement type */ #define DISABLED 0x00 /* disabled statement */ #define CONFIG 0x01 /* config statement */ #define PANEL 0x02 /* command statement */ CMDFUNC *function; /* handler function */ const char *shortdesc; /* description */ const char *longdesc; /* detaled description */ } CMDTAB; #define COMMAND(_stmt, _type, _func, _sdesc, _ldesc) \ { (_stmt), (0), (_type), (_func), (_sdesc), (_ldesc) }, #define CMDABBR(_stmt, _abbr, _type, _func, _sdesc, _ldesc) \ { (_stmt), (_abbr), (_type), (_func), (_sdesc), (_ldesc) }, static CMDTAB cmdtab[] = { #include "cmdtab.h" COMMAND ( NULL, 0, NULL, NULL, NULL ) /* End of table */ }; /*-------------------------------------------------------------------*/ /* $zapcmd - internal debug - may cause havoc - use with caution */ /*-------------------------------------------------------------------*/ int zapcmd_cmd(int argc, char *argv[], char *cmdline) { CMDTAB* cmdent; int i; UNREFERENCED(cmdline); if (argc > 1) { for (cmdent = cmdtab; cmdent->statement; cmdent++) { if(!strcasecmp(argv[1], cmdent->statement)) { if(argc > 2) for(i = 2; i < argc; i++) { if(!strcasecmp(argv[i],"Cfg")) cmdent->type |= CONFIG; else if(!strcasecmp(argv[i],"NoCfg")) cmdent->type &= ~CONFIG; else if(!strcasecmp(argv[i],"Cmd")) cmdent->type |= PANEL; else if(!strcasecmp(argv[i],"NoCmd")) cmdent->type &= ~PANEL; else { logmsg(_("Invalid arg: %s: %s %s [(No)Cfg|(No)Cmd]\n"),argv[i],argv[0],argv[1]); return -1; } } else logmsg(_("%s: %s(%sCfg,%sCmd)\n"),argv[0],cmdent->statement, (cmdent->type&CONFIG)?"":"No",(cmdent->type&PANEL)?"":"No"); return 0; } } logmsg(_("%s: %s not in command table\n"),argv[0],argv[1]); return -1; } else logmsg(_("Usage: %s [(No)Cfg|(No)Cmd]\n"),argv[0]); return -1; } CMDT_DLL_IMPORT int ProcessConfigCommand (int argc, char **argv, char *cmdline) { CMDTAB* cmdent; if (argc) for (cmdent = cmdtab; cmdent->statement; cmdent++) if(cmdent->function && (cmdent->type & CONFIG)) if(!strcasecmp(argv[0], cmdent->statement)) return cmdent->function(argc, argv, cmdline); return -1; } /*-------------------------------------------------------------------*/ /* Main panel command processing function */ /*-------------------------------------------------------------------*/ int OnOffCommand(int argc, char *argv[], char *cmdline); int ShadowFile_cmd(int argc, char *argv[], char *cmdline); int cmd_argc; char* cmd_argv[MAX_ARGS]; int ProcessPanelCommand (char* pszCmdLine) { CMDTAB* pCmdTab = NULL; char* pszSaveCmdLine = NULL; char* cl = NULL; int rc = -1; int cmdl; if (!pszCmdLine || !*pszCmdLine) { /* [enter key] by itself: start the CPU (ignore if not instruction stepping) */ if (sysblk.inststep) rc = start_cmd(0,NULL,NULL); goto ProcessPanelCommandExit; } #if defined(OPTION_CONFIG_SYMBOLS) /* Perform variable substitution */ /* First, set some 'dynamic' symbols to their own values */ set_symbol("CUU","$(CUU)"); set_symbol("cuu","$(cuu)"); set_symbol("CCUU","$(CCUU)"); set_symbol("ccuu","$(ccuu)"); cl=resolve_symbol_string(pszCmdLine); #else cl=pszCmdLine; #endif /* Save unmodified copy of the command line in case its format is unusual and needs customized parsing. */ pszSaveCmdLine = strdup(cl); /* Parse the command line into its individual arguments... Note: original command line now sprinkled with nulls */ parse_args (cl, MAX_ARGS, cmd_argv, &cmd_argc); /* If no command was entered (i.e. they entered just a comment (e.g. "# comment")) then ignore their input */ if ( !cmd_argv[0] ) goto ProcessPanelCommandExit; #if defined(OPTION_DYNAMIC_LOAD) if(system_command) if((rc = system_command(cmd_argc, (char**)cmd_argv, pszSaveCmdLine))) goto ProcessPanelCommandExit; #endif /* Route standard formatted commands from our routing table... */ if (cmd_argc) for (pCmdTab = cmdtab; pCmdTab->function; pCmdTab++) { if(pCmdTab->function && (pCmdTab->type & PANEL)) { if (!pCmdTab->statminlen) { if(!strcasecmp(cmd_argv[0], pCmdTab->statement)) { rc = pCmdTab->function(cmd_argc, (char**)cmd_argv, pszSaveCmdLine); goto ProcessPanelCommandExit; } } else { cmdl=MAX(strlen(cmd_argv[0]),pCmdTab->statminlen); if(!strncasecmp(cmd_argv[0],pCmdTab->statement,cmdl)) { rc = pCmdTab->function(cmd_argc, (char**)cmd_argv, pszSaveCmdLine); goto ProcessPanelCommandExit; } } } } /* Route non-standard formatted commands... */ /* sf commands - shadow file add/remove/set/compress/display */ if (0 || !strncasecmp(pszSaveCmdLine,"sf+",3) || !strncasecmp(pszSaveCmdLine,"sf-",3) || !strncasecmp(pszSaveCmdLine,"sfc",3) || !strncasecmp(pszSaveCmdLine,"sfd",3) || !strncasecmp(pszSaveCmdLine,"sfk",3) ) { rc = ShadowFile_cmd(cmd_argc,(char**)cmd_argv,pszSaveCmdLine); goto ProcessPanelCommandExit; } /* x+ and x- commands - turn switches on or off */ if ('+' == pszSaveCmdLine[1] || '-' == pszSaveCmdLine[1]) { rc = OnOffCommand(cmd_argc,(char**)cmd_argv,pszSaveCmdLine); goto ProcessPanelCommandExit; } /* Error: unknown/unsupported command... */ ASSERT( cmd_argv[0] ); logmsg( _("HHCPN139E Command \"%s\" not found; enter '?' for list.\n"), cmd_argv[0] ); ProcessPanelCommandExit: /* Free our saved copy */ free(pszSaveCmdLine); #if defined(OPTION_CONFIG_SYMBOLS) if (cl != pszCmdLine) free(cl); #endif return rc; } /*-------------------------------------------------------------------*/ /* help command - display additional help for a given command */ /*-------------------------------------------------------------------*/ int HelpCommand(int argc, char *argv[], char *cmdline) { CMDTAB* pCmdTab; UNREFERENCED(cmdline); if (argc < 2) { logmsg( _("HHCPN140I Valid panel commands are...\n\n") ); logmsg( " %-9.9s %s \n", "Command", "Description..." ); logmsg( " %-9.9s %s \n", "-------", "-----------------------------------------------" ); /* List standard formatted commands from our routing table... */ for (pCmdTab = cmdtab; pCmdTab->statement; pCmdTab++) { if ( (pCmdTab->type & PANEL) && (pCmdTab->shortdesc)) logmsg( _(" %-9.9s %s \n"), pCmdTab->statement, pCmdTab->shortdesc ); } } else { for (pCmdTab = cmdtab; pCmdTab->statement; pCmdTab++) { if (!strcasecmp(pCmdTab->statement,argv[1]) && (pCmdTab->type & PANEL) ) { logmsg( _("%s: %s\n"),pCmdTab->statement,pCmdTab->shortdesc); if(pCmdTab->longdesc) logmsg( _("%s\n"),pCmdTab->longdesc ); return 0; } } logmsg( _("HHCPN142I Command %s not found - no help available\n"),argv[1]); return -1; } return 0; } int scr_recursion_level(); #if defined(OPTION_DYNAMIC_LOAD) DLL_EXPORT void *panel_command_r (void *cmdline) #else void *panel_command (void *cmdline) #endif { #define MAX_CMD_LEN (32768) char cmd[MAX_CMD_LEN]; /* Copy of panel command */ char *pCmdLine; unsigned i; int noredisp; pCmdLine = cmdline; ASSERT(pCmdLine); /* every command will be stored in history list */ /* except null commands and script commands */ if (*pCmdLine != 0 && scr_recursion_level() == 0) history_add(cmdline); /* Copy panel command to work area, skipping leading blanks */ /* If the command starts with a -, then strip it and indicate * we do not want command redisplay */ noredisp=0; while (*pCmdLine && isspace(*pCmdLine)) pCmdLine++; i = 0; while (*pCmdLine && i < (MAX_CMD_LEN-1)) { if(i==0 && *pCmdLine=='-') { noredisp=1; /* and remove blanks again.. */ while (*pCmdLine && isspace(*pCmdLine)) pCmdLine++; } else { cmd[i] = *pCmdLine; i++; } pCmdLine++; } cmd[i] = 0; /* Ignore null commands (just pressing enter) unless instruction stepping is enabled or commands are being sent to the SCP by default. */ if (!sysblk.inststep && (sysblk.cmdtgt == 0) && (0 == cmd[0])) return NULL; /* Echo the command to the control panel */ if(!noredisp) { logmsg( "%s\n", cmd); } #ifdef OPTION_CMDTGT /* check for herc, scp or pscp command */ /* Please note that cmdtgt is a hercules command! */ /* Changing the target to her in scp mode is done by using herc cmdtgt herc */ if(!strncasecmp(cmd, "herc ", 5) || !strncasecmp(cmd, "scp ", 4) || !strncasecmp(cmd, "pscp ", 5)) { ProcessPanelCommand(cmd); return NULL; } /* Send command to the selected command target */ switch(sysblk.cmdtgt) { case 0: // cmdtgt herc { /* Stay compatible */ #ifdef _FEATURE_SYSTEM_CONSOLE if(cmd[0] == '.' || cmd[0] == '!') { if(!cmd[1]) { cmd[1] = ' '; cmd[2] = 0; } scp_command(cmd + 1, cmd[0] == '!'); } else #endif /*_FEATURE_SYSTEM_CONSOLE*/ ProcessPanelCommand(cmd); break; } case 1: // cmdtgt scp { if(!cmd[0]) { cmd[0] = ' '; cmd[1] = 0; } scp_command(cmd, 0); break; } case 2: // cmdtgt pscp { if(!cmd[0]) { cmd[0] = ' '; cmd[1] = 0; } scp_command(cmd, 1); break; } } #else // OPTION_CMDTGT #ifdef _FEATURE_SYSTEM_CONSOLE if ('.' == cmd[0] || '!' == cmd[0]) { if (!cmd[1]) { cmd[1]=' '; cmd[2]=0; } scp_command (cmd+1, cmd[0] == '!'); return NULL; } #endif /*_FEATURE_SYSTEM_CONSOLE*/ ProcessPanelCommand(cmd); #endif // OPTION_CMDTGT return NULL; } hercules-3.07/cmdtab.h000644 000765 000765 00000110656 11344614732 016364 0ustar00jmaynardjmaynard000000 000000 /* CMDTAB.H (c) Copyright Roger Bowler, 1999-2009 */ /* (c) Copyright "Fish" (David B. Trout), 2002-2009 */ /* (c) Copyright Jan Jaeger, 2003-2009 */ /* Defines all Hercules Configuration statements */ /* and panel commands */ // $Id: cmdtab.h 5653 2010-03-06 17:03:20Z fish $ // command type function one-line description... // COMMAND ("sample" PANEL, sample_cmd, "short help text", "long help text" ) // COMMAND ("sample2" PANEL+CONFIG, sample2_cmd, "short help text", NULL ) // No long help provided // COMMAND ("sample3" CONFIG, sample3_cmd, NULL, NULL ) // No help provided at all // COMMAND ("sample4" DISABLED, sample4_cmd, NULL, NULL ) // Disabled command - generally debugging only COMMAND ( "help", PANEL, HelpCommand, "list all commands / command specific help", "Enter \"help cmd\" where cmd is the command you need help\n" "with. If the command has additional help text defined for it,\n" "it will be displayed. Help text is usually limited to explaining\n" "the format of the command and its various required or optional\n" "parameters and is not meant to replace reading the documentation.\n" ) COMMAND ( "?", PANEL, HelpCommand, "alias for help\n", NULL ) COMMAND ( "*", CONFIG+PANEL, comment_cmd, "Comment", NULL ) COMMAND ( "#", CONFIG+PANEL, comment_cmd, "Comment\n", NULL ) CMDABBR ( "message",1, PANEL, msg_cmd, "Display message on console a la VM", NULL ) CMDABBR ( "msg",1, PANEL, msg_cmd, "Alias for message", NULL ) COMMAND ( "msgnoh", PANEL, msgnoh_cmd, "Similar to \"message\" but no header\n", NULL ) COMMAND ( "hst", PANEL, History, "history of commands", "Format: \"hst | hst n | hst l\". Command \"hst l\" or \"hst 0\" displays\n" "list of last ten commands entered from command line\n" "hst n, where n is a positive number retrieves n-th command from list\n" "hst n, where n is a negative number retrieves n-th last command\n" "hst without an argument works exactly as hst -1, it retrieves last command\n" ) #if defined(OPTION_HAO) COMMAND ( "hao", PANEL, hao_cmd, "Hercules Automatic Operator", "Format: \"hao tgt | cmd | list | del | clear \".\n" " hao tgt : define target rule (regex pattern) to react on\n" " hao cmd : define command for previously defined rule\n" " hao list : list all rules/commands or only at index \n" " hao del : delete the rule at index \n" " hao clear : delete all rules (stops automatic operator)\n" ) #endif /* defined(OPTION_HAO) */ COMMAND ( "log", PANEL, log_cmd, "direct log output", NULL ) COMMAND ( "logopt", PANEL+CONFIG, logopt_cmd, "change log options", "Format: \"logopt [timestamp | notimestamp]\". Sets logging options.\n" "\"timestamp\" inserts a time stamp in front of each log message.\n" "\"notimestamp\" displays log messages with no time stamps. Entering\n" "the command with no arguments displays current logging options.\n" "\"timestamp\" and \"notimestamp\" may be abbreviated as \"time\"\n" "and \"notime\" respectively.\n" ) COMMAND ( "uptime", PANEL, uptime_cmd, "display how long Hercules has been running\n", NULL ) COMMAND ( "version", PANEL, version_cmd, "display version information\n", NULL ) COMMAND ( "quit", PANEL, quit_cmd, "terminate the emulator", NULL ) COMMAND ( "exit", PANEL, quit_cmd, "(synonym for 'quit')\n", NULL ) COMMAND ( "cpu", PANEL, cpu_cmd, "Define target cpu for panel display and commands\n", "Format: \"cpu hh\" where 'hh' is the hexadecimal cpu address of the cpu\n" "in your multiprocessor configuration which you wish all panel commands\n" "to apply to. For example, entering 'cpu 1F' followed by \"gpr\" will\n" "display the general purpose registers for cpu 31 of your configuration.\n" ) COMMAND ( "start", PANEL, start_cmd, "start CPU (or printer device if argument given)", "Entering the 'start' command by itself simply starts a stopped\n" "CPU, whereas 'start ' presses the virtual start button on\n" "printer device .\n" ) COMMAND ( "stop", PANEL, stop_cmd, "stop CPU (or printer device if argument given)\n", "Entering the 'stop' command by itself simply stops a running\n" "CPU, whereas 'stop ' presses the virtual stop button on\n" "printer device , usually causing an INTREQ.\n" ) COMMAND ( "startall", PANEL, startall_cmd, "start all CPU's", NULL ) COMMAND ( "stopall", PANEL, stopall_cmd, "stop all CPU's\n", NULL ) #ifdef _FEATURE_CPU_RECONFIG COMMAND ( "cf", PANEL, cf_cmd, "Configure current CPU online or offline", "Configure current CPU online or offline: Format-> \"cf [on|off]\"\n" "Where the 'current' CPU is defined as whatever CPU was defined as\n" "the panel command target cpu via the \"cpu\" panel command. (Refer\n" "to the 'cpu' command for further information) Entering 'cf' by itself\n" "simply displays the current online/offline status of the current cpu.\n" "Otherwise the current cpu is configured online or offline as specified.\n" "Use 'cfall' to configure/display all CPUs online/offline state.\n" ) COMMAND ( "cfall", PANEL, cfall_cmd, "configure all CPU's online or offline\n", NULL ) #endif #ifdef _FEATURE_SYSTEM_CONSOLE COMMAND ( ".reply", PANEL, g_cmd, "scp command", "To reply to a system control program (i.e. guest operating system)\n" "message that gets issued to the hercules console, prefix the reply\n" "with a period.\n" ) COMMAND ( "!message", PANEL, g_cmd, "scp priority messsage", "To enter a system control program (i.e. guest operating system)\n" "priority command on the hercules console, simply prefix the command\n" "with an exclamation point '!'.\n" ) COMMAND ( "ssd", PANEL, ssd_cmd, "signal shutdown\n", "The SSD (signal shutdown) command signals an imminent hypervisor shutdown to\n" "the guest. Guests who support this are supposed to perform a shutdown upon\n" "receiving this request.\n" "An implicit ssd command is given on a hercules \"quit\" command if the guest\n" "supports ssd. In that case hercules shutdown will be delayed until the guest\n" "has shutdown or a 2nd quit command is given.\n" ) #endif #ifdef OPTION_PTTRACE COMMAND ( "ptt", PANEL+CONFIG, EXT_CMD(ptt_cmd), "Set or display internal trace\n", "Format: \"ptt [options] [nnn]\"\n" "When specified with no operands, the ptt command displays the trace options\n" "and the contents of the internal trace table.\n" "When specified with operands, the ptt command sets the trace options and/or\n" "specifies which events are to be traced. If the last operand is numeric, it\n" "sets the size of the trace table and activates the trace.\n" "options:\n" " (no)error - error trace\n" " (no)control - control trace\n" " (no)prog - program interrupt trace\n" " (no)inter - interlock failure trace\n" " (no)sie - sie trace\n" " (no)signal - signaling trace\n" " (no)io - io trace\n" " (no)timer - timer trace\n" " (no)threads - thread trace\n" " (no)logger - logger trace\n" " (no)lock - lock trace buffer\n" " (no)tod - timestamp trace entries\n" " (no)wrap - wrap trace buffer\n" " to=nnn - trace buffer display timeout\n" " nnn - trace buffer size\n" ) #endif COMMAND ( "i", PANEL, i_cmd, "generate I/O attention interrupt for device", NULL ) COMMAND ( "ext", PANEL, ext_cmd, "generate external interrupt", NULL ) COMMAND ( "restart", PANEL, restart_cmd, "generate restart interrupt", NULL ) COMMAND ( "archmode", PANEL+CONFIG, archmode_cmd, "Set architecture mode", "Format: \"archmode [S/370 | ESA/390 | z/Arch | ESAME]\". Entering the command\n" "without any argument simply displays the current architecture mode. Entering\n" "the command with an argument sets the architecture mode to the specified value.\n" "Note: \"ESAME\" (Enterprise System Architecture, Modal Extensions) is simply a\n" "synonym for \"z/Arch\". (they are identical to each other and mean the same thing)\n" ) COMMAND ( "loadparm", PANEL+CONFIG, loadparm_cmd, "set IPL parameter\n", NULL ) COMMAND ( "lparname", PANEL+CONFIG, lparname_cmd, "set LPAR name\n", NULL ) COMMAND ( "lparnum", PANEL+CONFIG, lparnum_cmd, "set LPAR identification number\n", NULL ) #if defined(OPTION_SET_STSI_INFO) COMMAND ( "model", CONFIG, stsi_model_cmd,"Set STSI model code", NULL ) COMMAND ( "plant", CONFIG, stsi_plant_cmd,"Set STSI plant code", NULL ) COMMAND ( "manufacturer",CONFIG, stsi_mfct_cmd,"Set STSI manufacturer code\n", NULL ) #endif /* defined(OPTION_SET_STSI_INFO) */ COMMAND ( "pgmprdos", CONFIG, pgmprdos_cmd,"set LPP license setting\n", NULL ) COMMAND ( "codepage", CONFIG, codepage_cmd,"set codepage conversion table\n", NULL ) COMMAND ( "diag8cmd", CONFIG, diag8_cmd, "Set diag8 command option\n", NULL ) // The shcmdopt config statement should never be a command as it will introduce a possible integrity exposure *JJ COMMAND ( "shcmdopt", CONFIG, shcmdopt_cmd,"Set diag8 sh option\n", NULL ) COMMAND ( "legacysenseid",CONFIG, lsid_cmd, "set legacysenseid setting\n", NULL ) COMMAND ( "ipl", PANEL, ipl_cmd, "IPL Normal from device xxxx", "Format: \"ipl nnnn [parm xxxxxxxxxxxxxx]\"\n" "Performs the Initial Program Load manual control function. If the first operand\n" "'nnnn' is a 1- to 4-digit hexadecimal number, a CCW-type IPL is initiated from\n" "the indicated device number, and SCLP disk I/O is disabled.\n" "Otherwise a list-directed IPL is performed from the .ins file named 'nnnn', and\n" "SCLP disk I/O is enabled for the directory path where the .ins file is located.\n" "An optional 'parm' keyword followed by a string can also be passed to the IPL\n" "command processor. The string will be loaded into the low-order 32 bits of the\n" "general purpose registers (4 characters per register for up to 64 bytes).\n" "The PARM option behaves similarly to the VM IPL command.\n" ) COMMAND ( "iplc", PANEL, iplc_cmd, "IPL Clear from device xxxx", "Performs the Load Clear manual control function. See \"ipl\".\n" ) COMMAND ( "sysreset", PANEL, sysr_cmd, "issue SYSTEM Reset manual operation", "Performs the System Reset manual control function. A CPU and I/O\n" "subsystem reset are performed.\n" ) COMMAND ( "sysclear", PANEL, sysc_cmd, "issue SYSTEM Clear Reset manual operation", "Performs the System Reset Clear manual control function. Same as\n" "the \"sysreset\" command but also clears main storage to 0. Also, registers\n" "control registers, etc.. are reset to their initial value. At this\n" "point, the system is essentially in the same state as it was just after\n" "having been started\n" ) COMMAND ( "store", PANEL, store_cmd, "store CPU status at absolute zero\n", NULL ) COMMAND ( "sclproot", CONFIG+PANEL, sclproot_cmd, "set SCLP base directory", "Format: \"sclproot [path|NONE]\"\n" "Enables SCLP disk I/O for the specified directory path, or disables SCLP disk\n" "I/O if NONE is specified. A subsequent list-directed IPL resets the path to\n" "the location of the .ins file, and a CCW-type IPL disables SCLP disk I/O.\n" "If no operand is specified, sclproot displays the current setting.\n") #if defined(OPTION_HTTP_SERVER) COMMAND ( "httproot", CONFIG, httproot_cmd, "Set HTTP server root directory", NULL ) COMMAND ( "httpport", CONFIG, httpport_cmd, "Set HTTP server port\n", NULL ) #if defined( HTTP_SERVER_CONNECT_KLUDGE ) COMMAND ( "HTTP_SERVER_CONNECT_KLUDGE", CONFIG, httpskm_cmd, "HTTP_SERVER_CONNECT_KLUDGE", NULL ) #endif // defined( HTTP_SERVER_CONNECT_KLUDGE ) #endif /*defined(OPTION_HTTP_SERVER)*/ COMMAND ( "psw", PANEL, psw_cmd, "display or alter program status word", "Format: \"psw [operand ...]\" where 'operand ...' is one or more optional\n" "parameters which modify the contents of the Program Status Word:\n\n" " sm=xx system mask (2 hex digits)\n" " pk=n protection key (decimal 0 to 15)\n" " cmwp=x C/M/W/P bits (one hex digit)\n" " as=pri|sec|ar|home address-space\n" " cc=n condition code (decimal 0 to 3)\n" " pm=x program mask (one hex digit)\n" " am=24|31|64 addressing mode\n" " ia=xxx instruction address (1 to 16 hex digits)\n\n" "Enter \"psw\" by itself to display the current PSW without altering it.\n" ) COMMAND ( "gpr", PANEL, gpr_cmd, "display or alter general purpose registers", "Format: \"gpr [nn=xxxxxxxxxxxxxxxx]\" where 'nn' is the optional register\n" "number (0 to 15) and 'xxxxxxxxxxxxxxxx' is the register value in hexadecimal\n" "(1-8 hex digits for 32-bit registers or 1-16 hex digits for 64-bit registers).\n" "Enter \"gpr\" by itself to display the register values without altering them.\n" ) COMMAND ( "fpr", PANEL, fpr_cmd, "display floating point registers", NULL ) COMMAND ( "fpc", PANEL, fpc_cmd, "display floating point control register", NULL ) COMMAND ( "cr", PANEL, cr_cmd, "display or alter control registers", "Format: \"cr [nn=xxxxxxxxxxxxxxxx]\" where 'nn' is the optional control register\n" "number (0 to 15) and 'xxxxxxxxxxxxxxxx' is the control register value in hex\n" "(1-8 hex digits for 32-bit registers or 1-16 hex digits for 64-bit registers).\n" "Enter \"cr\" by itself to display the control registers without altering them.\n" ) COMMAND ( "ar", PANEL, ar_cmd, "display access registers", NULL ) COMMAND ( "pr", PANEL, pr_cmd, "display prefix register", NULL ) COMMAND ( "timerint", PANEL+CONFIG, timerint_cmd,"display or set timers update interval", NULL ) COMMAND ( "clocks", PANEL, clocks_cmd, "display tod clkc and cpu timer", NULL ) COMMAND ( "ipending", PANEL, ipending_cmd, "display pending interrupts", NULL ) COMMAND ( "ds", PANEL, ds_cmd, "display subchannel", NULL ) COMMAND ( "r", PANEL, r_cmd, "display or alter real storage", "Format: \"r addr[.len]\" or \"r addr-addr\" to display real\n" "storage, or \"r addr=value\" to alter real storage, where 'value'\n" "is a hex string of up to 32 pairs of digits.\n" ) COMMAND ( "v", PANEL, v_cmd, "display or alter virtual storage", "Format: \"v [P|S|H] addr[.len]\" or \"v [P|S|H] addr-addr\" to display virtual\n" "storage, or \"v [P|S|H] addr=value\" to alter virtual storage, where 'value'\n" "is a hex string of up to 32 pairs of digits. The optional 'P' or 'S' or 'H'\n" "will force Primary, Secondary, or Home translation instead of current PSW mode.\n" ) COMMAND ( "u", PANEL, u_cmd, "disassemble storage", NULL ) COMMAND ( "devtmax", PANEL+CONFIG, devtmax_cmd, "display or set max device threads", NULL ) COMMAND ( "k", PANEL, k_cmd, "display cckd internal trace\n", NULL ) COMMAND ( "attach", PANEL, attach_cmd, "configure device", "Format: \"attach devn type [arg...]\n" ) COMMAND ( "detach", PANEL, detach_cmd, "remove device", NULL ) COMMAND ( "define", PANEL, define_cmd, "rename device", "Format: \"define olddevn newdevn\"\n" ) COMMAND ( "devinit", PANEL, devinit_cmd, "reinitialize device", "Format: \"devinit devn [arg...]\"\n" "If no arguments are given then the same arguments are used\n" "as were used the last time the device was created/initialized.\n" ) COMMAND ( "devlist", PANEL, devlist_cmd, "list device or all devices\n", NULL ) COMMAND ( "qd", PANEL, qd_cmd, "query dasd\n", NULL ) COMMAND ( "mounted_tape_reinit", PANEL+CONFIG, mnttapri_cmd, "Control tape initilisation", NULL ) #if defined( OPTION_TAPE_AUTOMOUNT ) COMMAND ( "automount", PANEL+CONFIG, automount_cmd, "Show/Update allowable tape automount directories\n", "Format: \"automount { add | del | list }\"\n" "\n" "Adds or deletes entries from the list of allowable/unallowable tape\n" "automount directories, or lists all currently defined list entries,\n" "if any.\n" "\n" "The format of the directory operand for add/del operations is\n" "identical to that as described in the documentation for the AUTOMOUNT\n" "configuration file statement (i.e. prefix with '+' or '-' as needed).\n" "\n" "The automount feature is appropriately enabled or disabled for all tape\n" "devices as needed depending on the updated empty/non-empty list state.\n" ) #endif /* OPTION_TAPE_AUTOMOUNT */ #if defined( OPTION_SCSI_TAPE ) COMMAND ( "auto_scsi_mount", PANEL+CONFIG, ascsimnt_cmd, "Control SCSI tape mount", NULL ) COMMAND ( "scsimount", PANEL, scsimount_cmd, "automatic SCSI tape mounts\n", "Format: \"scsimount [ no | yes | 0-99 ]\".\n" "\n" "Displays or modifies the automatic SCSI tape mounts option.\n\n" "When entered without any operands, it displays the current interval\n" "and any pending tape mount requests. Entering 'no' (or 0 seconds)\n" "disables automount detection.\n" "\n" "Entering a value between 1-99 seconds (or 'yes') enables the option\n" "and specifies how often to query SCSI tape drives to automatically\n" "detect when a tape has been mounted (upon which an unsolicited\n" "device-attention interrupt will be presented to the guest operating\n" "system). 'yes' is equivalent to specifying a 5 second interval.\n" ) #endif /* defined( OPTION_SCSI_TAPE ) */ COMMAND ( "cd", PANEL, cd_cmd, "change directory", NULL ) COMMAND ( "pwd", PANEL, pwd_cmd, "print working directory", NULL ) COMMAND ( "sh", PANEL, sh_cmd, "shell command\n", "Format: \"sh command [args...]\" where 'command' is any valid shell\n" "command. The entered command and any arguments are passed as-is to the\n" "shell for processing and the results are displayed on the console.\n" ) COMMAND ( "cache", PANEL, EXT_CMD(cache_cmd), "cache command", NULL ) COMMAND ( "cckd", PANEL+CONFIG, cckd_cmd, "cckd command", NULL ) COMMAND ( "shrd", PANEL, EXT_CMD(shared_cmd), "shrd command", NULL ) COMMAND ( "conkpalv", PANEL+CONFIG, conkpalv_cmd, "Display/alter console TCP keep-alive settings", "Format: \"conkpalv (idle,intv,count)\" where 'idle', 'intv' and 'count' are the\n" "new values for the TCP keep-alive settings for console connections:\n" "- send probe when connection goes idle for 'idle' seconds\n" "- wait maximum of 'intv' seconds for a response to probe\n" "- disconnect after 'count' consecutive failed probes\n" "The format must be exactly as shown, with each value separated from the next by\n" "a single comma, no intervening spaces between them, surrounded by parenthesis.\n" "The command \"conkpalv\" without any operand displays the current values.\n" ) COMMAND ( "quiet", PANEL, quiet_cmd, "Toggle automatic refresh of panel display data\n", "'quiet' either disables automatic screen refreshing if it is\n" "currently enabled or enables it if it is currently disabled.\n" "When disabled you will no be able to see the response of any\n" "entered commands nor any messages issued by the system nor be\n" "able to scroll the display, etc. Basically all screen updating\n" "is disabled. Entering 'quiet' again re-enables screen updating.\n" ) COMMAND ( "t", PANEL, trace_cmd, "instruction trace", "Format: \"t addr-addr\" or \"t addr:addr\" or \"t addr.length\"\n" "sets the instruction tracing range (which is totally separate from\n" "the instruction stepping and breaking range).\n" "With or without a range, the t command displays whether instruction\n" "tracing is on or off and the range if any.\n" "The t command by itself does not activate instruction tracing.\n" "Use the t+ command to activate instruction tracing.\n" "\"t 0\" eliminates the range (all addresses will be traced).\n" ) COMMAND ( "t+", PANEL, trace_cmd, "instruction trace on", "Format: \"t+\" turns on instruction tracing. A range can be specified\n" "as for the \"t\" command, otherwise the existing range is used. If there\n" "is no range (or range was specified as 0) then all instructions will be\n" "traced.\n" ) COMMAND ( "t-", PANEL, trace_cmd, "instruction trace off", "Format: \"t-\" turns off instruction tracing.\n" ) COMMAND ( "t?", PANEL, trace_cmd, "instruction trace query", "Format: \"t?\" displays whether instruction tracing is on or off\n" "and the range if any.\n" ) COMMAND ( "s", PANEL, trace_cmd, "instruction stepping", "Format: \"s addr-addr\" or \"s addr:addr\" or \"s addr.length\"\n" "sets the instruction stepping and instruction breaking range,\n" "(which is totally separate from the instruction tracing range).\n" "With or without a range, the s command displays whether instruction\n" "stepping is on or off and the range if any.\n" "The s command by itself does not activate instruction stepping.\n" "Use the s+ command to activate instruction stepping.\n" "\"s 0\" eliminates the range (all addresses will be stepped).\n" ) COMMAND ( "s+", PANEL, trace_cmd, "instruction stepping on", "Format: \"s+\" turns on instruction stepping. A range can be specified\n" "as for the \"s\" command, otherwise the existing range is used. If there\n" "is no range (or range was specified as 0) then the range includes all\n" "addresses. When an instruction within the range is about to be executed,\n" "the CPU is temporarily stopped and the next instruction is displayed.\n" "You may then examine registers and/or storage, etc, before pressing Enter\n" "to execute the instruction and stop at the next instruction. To turn\n" "off instruction stepping and continue execution, enter the \"g\" command.\n" ) COMMAND ( "s-", PANEL, trace_cmd, "instruction stepping off", "Format: \"s-\" turns off instruction stepping.\n" ) COMMAND ( "s?", PANEL, trace_cmd, "instruction stepping query", "Format: \"s?\" displays whether instruction stepping is on or off\n" "and the range if any.\n" ) COMMAND ( "b", PANEL, trace_cmd, "set breakpoint", "Format: \"b addr\" or \"b addr-addr\" where 'addr' is the instruction\n" "address or range of addresses where you wish to halt execution. This\n" "command is synonymous with the \"s+\" command.\n" ) COMMAND ( "b+", PANEL, trace_cmd, "set breakpoint", NULL ) COMMAND ( "b-", PANEL, trace_cmd, "delete breakpoint", "Format: \"b-\" This command is the same as \"s-\"\n" ) COMMAND ( "g", PANEL, g_cmd, "turn off instruction stepping and start all CPUs\n", NULL ) COMMAND ( "ostailor", PANEL+CONFIG, ostailor_cmd, "trace program interrupts", "Format: \"ostailor quiet | os/390 | z/os | vm | vse | linux | null\". Specifies\n" "the intended operating system. The effect is to reduce control panel message\n" "traffic by selectively suppressing program check trace messages which are\n" "considered normal in the specified environment. 'quiet' suppresses all\n" "exception messages, whereas 'null' suppresses none of them. The other options\n" "suppress some messages and not others depending on the specified o/s. Prefix\n" "values with '+' to combine them with existing values or '-' to exclude them.\n" "SEE ALSO the 'pgmtrace' command which allows you to further fine tune\n" "the tracing of program interrupt exceptions.\n" ) COMMAND ( "pgmtrace", PANEL, pgmtrace_cmd, "trace program interrupts", "Format: \"pgmtrace [-]intcode\" where 'intcode' is any valid program\n" "interruption code in the range 0x01 to 0x40. Precede the interrupt code\n" "with a '-' to stop tracing of that particular program interruption.\n" ) COMMAND ( "savecore", PANEL, savecore_cmd, "save a core image to file", "Format: \"savecore filename [{start|*}] [{end|*}]\" where 'start' and 'end'\n" "define the starting and ending addresss of the range of real storage to be\n" "saved to file 'filename'. '*' for either the start address or end address\n" "(the default) means: \"the first/last byte of the first/last modified page\n" "as determined by the storage-key 'changed' bit\".\n" ) COMMAND ( "loadcore", PANEL, loadcore_cmd, "load a core image file", "Format: \"loadcore filename [address]\" where 'address' is the storage address\n" "of where to begin loading memory. The file 'filename' is presumed to be a pure\n" "binary image file previously created via the 'savecore' command. The default for\n" "'address' is 0 (begining of storage).\n" ) COMMAND ( "loadtext", PANEL, loadtext_cmd, "load a text deck file\n", "Format: \"loadtext filename [address]\". This command is essentially identical\n" "to the 'loadcore' command except that it loads a text deck file with \"TXT\"\n" "and \"END\" 80 byte records (i.e. an object deck).\n" ) #if defined(OPTION_DYNAMIC_LOAD) COMMAND ( "modpath", CONFIG, modpath_cmd, "set module load path", NULL ) COMMAND ( "ldmod", CONFIG+PANEL, ldmod_cmd, "load a module", NULL ) COMMAND ( "rmmod", PANEL, rmmod_cmd, "delete a module", NULL ) COMMAND ( "lsmod", PANEL, lsmod_cmd, "list dynamic modules", NULL ) COMMAND ( "lsdep", PANEL, lsdep_cmd, "list module dependencies\n", NULL ) #endif /*defined(OPTION_DYNAMIC_LOAD)*/ #ifdef OPTION_IODELAY_KLUDGE COMMAND ( "iodelay", PANEL+CONFIG, iodelay_cmd, "display or set I/O delay value", NULL ) #endif COMMAND ( "ctc", PANEL, ctc_cmd, "Enable/Disable CTC debugging", "Format: \"ctc debug { on | off } [ | ALL ]\".\n\n" "Enables/disables debug packet tracing for the specified CTCI/LCS\n" "device group(s) identified by or for all CTCI/LCS device\n" "groups if is not specified or specified as 'ALL'.\n" ) #if defined(OPTION_W32_CTCI) COMMAND ( "tt32", PANEL, tt32_cmd, "control/query CTCI-W32 functionality", "Format: \"tt32 debug | nodebug | stats \".\n" "\n" "Enables or disables global CTCI-W32 debug tracing\n" "or displays TunTap32 stats for the specified CTC device.\n" ) #endif COMMAND ( "toddrag", PANEL+CONFIG, toddrag_cmd, "display or set TOD clock drag factor", NULL ) #ifdef PANEL_REFRESH_RATE COMMAND ( "panrate", PANEL+CONFIG, panrate_cmd, "Display or set rate at which console refreshes", "Format: \"panrate [nnn | fast | slow]\". Sets or displays the panel refresh rate.\n" "panrate nnn sets the refresh rate to nnn milliseconds.\n" "panrate fast sets the refresh rate to " MSTRING(PANEL_REFRESH_RATE_FAST) " milliseconds.\n" "panrate slow sets the refresh rate to " MSTRING(PANEL_REFRESH_RATE_SLOW) " milliseconds.\n" "If no operand is specified, panrate displays the current refresh rate.\n") #endif COMMAND ( "pantitle", CONFIG, pantitle_cmd, "display or set console title", NULL ) #ifdef OPTION_MSGHLD COMMAND ( "msghld", PANEL, msghld_cmd, "Display or set the timeout of held messages", "Format: \"msghld [value | info | clear]\".\n" "value: timeout value of held message in seconds\n" "info: displays the timeout value\n" "clear: releases the held messages\n" ) #endif COMMAND ( "syncio", PANEL, syncio_cmd, "display syncio devices statistics", NULL ) #if defined(OPTION_INSTRUCTION_COUNTING) COMMAND ( "icount", PANEL, icount_cmd, "display individual instruction counts", NULL ) #endif #ifdef OPTION_MIPS_COUNTING COMMAND ( "maxrates", PANEL, maxrates_cmd, "display maximum observed MIPS/SIOS rate for the\n" " defined interval or define a new reporting interval\n", "Format: \"maxrates [nnnn]\" where 'nnnn' is the desired reporting\n" "interval in minutes. Acceptable values are from 1 to 1440. The default\n" "is 1440 minutes (one day). Entering \"maxrates\" by itself displays\n" "the current highest rates observed during the defined intervals.\n" ) #endif // OPTION_MIPS_COUNTING #if defined(_FEATURE_ASN_AND_LX_REUSE) COMMAND ( "asn_and_lx_reuse", CONFIG, alrf_cmd, "Enable/Disable ASN and LX reuse facility", NULL ) COMMAND ( "alrf" , CONFIG, alrf_cmd, "Alias for asn_and_lx_reuse\n", NULL ) #endif /* defined(_FEATURE_ASN_AND_LX_REUSE) */ #if defined(FISH_HANG) COMMAND ( "FishHangReport", PANEL, FishHangReport_cmd, "Display thread/lock/event objects (DEBUG)\n", "When built with --enable-fthreads --enable-fishhang, a detailed record of\n" "every thread, lock and event that is created is maintained for debugging purposes.\n" "If a lock is accessed before it has been initialized or if a thread exits while\n" "still holding a lock, etc (including deadlock situations), the FishHang logic will\n" "detect and report it. If you suspect one of hercules's threads is hung waiting for\n" "a condition to be signalled for example, entering \"FishHangReport\" will display\n" "the internal list of thread, locks and events to possibly help you determine where\n" "it's hanging and what event (condition) it's hung on.\n" ) #endif #if defined(OPTION_CONFIG_SYMBOLS) COMMAND ( "defsym", PANEL+CONFIG, defsym_cmd, "Define symbol", "Format: \"defsym symbol [value]\". Defines symbol 'symbol' to contain value 'value'.\n" "The symbol can then be the object of a substitution for later panel commands.\n" "If 'value' contains blanks or spaces, then it must be enclosed within quotes\n" "or apostrophes. For more detailed information regarding symbol substitution\n" "refer to the 'DEFSYM' configuration file statement in Hercules documentation.\n" "Enter \"defsym\" by itself to display the values of all defined symbols.\n" ) #endif COMMAND ( "script", PANEL, script_cmd, "Run a sequence of panel commands contained in a file", "Format: \"script filename [...filename...]\". Sequentially executes the commands contained\n" "within the file -filename-. The script file may also contain \"script\" commands,\n" "but the system ensures that no more than 10 levels of script are invoked at any\n" "one time (to avoid a recursion loop)\n" ) COMMAND ( "cscript", PANEL, cscript_cmd, "Cancels a running script thread\n", "Format: \"cscript\". This command will cancel the currently running script.\n" "if no script is running, no action is taken\n" ) #if defined(FEATURE_ECPSVM) COMMAND ( "evm", PANEL, evm_cmd_1, "ECPS:VM Commands (Deprecated)", "Format: \"evm\". This command is deprecated.\n" "use \"ecpsvm\" instead\n" ) COMMAND ( "ecpsvm", PANEL, evm_cmd, "ECPS:VM Commands\n", "Format: \"ecpsvm\". This command invokes ECPS:VM Subcommands.\n" "Type \"ecpsvm help\" to see a list of available commands\n" ) #endif COMMAND ( "aea", PANEL, aea_cmd, "Display AEA tables", NULL ) COMMAND ( "aia", PANEL, aia_cmd, "Display AIA fields", NULL ) COMMAND ( "tlb", PANEL, tlb_cmd, "Display TLB tables\n", NULL ) #if defined(SIE_DEBUG_PERFMON) COMMAND ( "spm", PANEL, spm_cmd, "SIE performance monitor\n", NULL ) #endif #if defined(OPTION_COUNTING) COMMAND ( "count", PANEL, count_cmd, "Display/clear overall instruction count\n", NULL ) #endif COMMAND ( "sizeof", PANEL, sizeof_cmd, "Display size of structures\n", NULL ) COMMAND ( "suspend", PANEL, suspend_cmd, "Suspend hercules", NULL ) COMMAND ( "resume", PANEL, resume_cmd, "Resume hercules\n", NULL ) COMMAND ( "herclogo", PANEL, herclogo_cmd, "Read a new hercules logo file\n", "Format: \"herclogo []\". Load a new logo file for 3270 terminal sessions\n" "If no filename is specified, the built-in logo is used instead\n" ) COMMAND ( "traceopt", CONFIG+PANEL, traceopt_cmd, "Instruction trace display options\n", "Format: \"traceopt [regsfirst | noregs | traditional]\". Determines how the\n" "registers are displayed during instruction tracing and stepping. Entering\n" "the command without any argument simply displays the current mode.\n" ) COMMAND ( "symptom", CONFIG, traceopt_cmd, "Alias for traceopt\n", NULL ) COMMAND ( "$zapcmd", CONFIG, zapcmd_cmd, NULL, NULL ) // enable/disable commands and config statements COMMAND ( "$test", DISABLED, test_cmd, NULL, NULL ) // enable in config with: $zapcmd $test cmd #ifdef OPTION_CMDTGT COMMAND ( "cmdtgt", PANEL, cmdtgt_cmd, "Specify the command target", "Format: \"cmdtgt [herc | scp | pscp | ?]\". Specify the command target.\n" ) COMMAND ( "herc", PANEL, herc_cmd, "Hercules command", "Format: \"herc [cmd]\". Send hercules cmd in any cmdtgt mode.\n" ) COMMAND ( "scp", PANEL, scp_cmd, "Send scp command", "Format: \"scp [cmd]\". Send scp cmd in any cmdtgt mode.\n" ) COMMAND ( "pscp", PANEL, prioscp_cmd, "Send prio message scp command\n", "Format: \"pscp [cmd]\". Send priority message cmd to scp in any cmdtgt mode.\n" ) #endif // OPTION_CMDTGT // The actual command table ends here, the next entries are just for help // as the associated command are processed as part of commandline parsing // and there are no forward references to be created #if !defined(_FW_REF) COMMAND ( "sf+dev", PANEL, NULL, "add shadow file", NULL ) COMMAND ( "sf-dev", PANEL, NULL, "delete shadow file", NULL ) COMMAND ( "sfc", PANEL, NULL, "compress shadow files", NULL ) COMMAND ( "sfk", PANEL, NULL, "Check shadow files", "Format: \"sfk{*|xxxx} [n]\". Performs a chkdsk on the active shadow file\n" "where xxxx is the device number (*=all cckd devices)\n" "and n is the optional check level (default is 2):\n" " -1 devhdr, cdevhdr, l1 table\n" " 0 devhdr, cdevhdr, l1 table, l2 tables\n" " 1 devhdr, cdevhdr, l1 table, l2 tables, free spaces\n" " 2 devhdr, cdevhdr, l1 table, l2 tables, free spaces, trkhdrs\n" " 3 devhdr, cdevhdr, l1 table, l2 tables, free spaces, trkimgs\n" " 4 devhdr, cdevhdr. Build everything else from recovery\n" "You probably don't want to use `4' unless you have a backup and are\n" "prepared to wait a long time.\n" ) COMMAND ( "sfd", PANEL, NULL, "display shadow file stats\n", NULL ) COMMAND ( "t{+/-}dev", PANEL, NULL, "turn CCW tracing on/off", NULL ) COMMAND ( "s{+/-}dev", PANEL, NULL, "turn CCW stepping on/off\n", NULL ) #ifdef OPTION_CKD_KEY_TRACING COMMAND ( "t{+/-}CKD", PANEL, NULL, "turn CKD_KEY tracing on/off\n", NULL ) #endif COMMAND ( "f{+/-}adr", PANEL, NULL, "mark frames unusable/usable\n", NULL ) #endif /*!defined(_FW_REF)*/ hercules-3.07/cmpsc.c000644 000765 000765 00000211227 11332367225 016225 0ustar00jmaynardjmaynard000000 000000 /*----------------------------------------------------------------------------*/ /* file: cmpsc.c */ /* */ /* Implementation of the S/390 compression call instruction described in */ /* SA22-7208-01: Data Compression within the Hercules S/390 emulator. */ /* This implementation couldn't be done without the test programs from */ /* Mario Bezzi. Thanks Mario! Also special thanks to Greg Smith who */ /* introduced iregs, needed when a page fault occurs. */ /* */ /* (c) Copyright Bernard van der Helm, 2000-2010 */ /* Noordwijkerhout, The Netherlands. */ /* */ /*----------------------------------------------------------------------------*/ // $Id: cmpsc.c 5601 2010-01-16 08:29:04Z bernard $ #include "hstdinc.h" #if !defined(_HENGINE_DLL_) #define _HENGINE_DLL_ #endif #if !defined(_CMPSC_C_) #define _CMPSC_C_ #endif #include "hercules.h" #include "opcode.h" #include "inline.h" #ifdef FEATURE_COMPRESSION /*============================================================================*/ /* Common */ /*============================================================================*/ /*----------------------------------------------------------------------------*/ /* Debugging options: */ /*----------------------------------------------------------------------------*/ #if 0 #define OPTION_CMPSC_DEBUG #define TRUEFALSE(boolean) ((boolean) ? "True" : "False") #endif /*----------------------------------------------------------------------------*/ /* After a succesful compression of characters to an index symbol or a */ /* succsful translation of an index symbol to characters, the registers must */ /* be updated. */ /*----------------------------------------------------------------------------*/ #define ADJUSTREGS(r, regs, iregs, len) \ {\ SET_GR_A((r), (iregs), (GR_A((r), (iregs)) + (len)) & ADDRESS_MAXWRAP((regs)));\ SET_GR_A((r) + 1, (iregs), GR_A((r) + 1, (iregs)) - (len));\ } /*----------------------------------------------------------------------------*/ /* Commit intermediate register */ /*----------------------------------------------------------------------------*/ #ifdef OPTION_CMPSC_DEBUG #define COMMITREGS(regs, iregs, r1, r2) \ __COMMITREGS((regs), (iregs), (r1), (r2)) \ logmsg("*** Regs committed\n"); #else #define COMMITREGS(regs, iregs, r1, r2) \ __COMMITREGS((regs), (iregs), (r1), (r2)) #endif #define __COMMITREGS(regs, iregs, r1, r2) \ {\ SET_GR_A(1, (regs), GR_A(1, (iregs)));\ SET_GR_A((r1), (regs), GR_A((r1), (iregs)));\ SET_GR_A((r1) + 1, (regs), GR_A((r1) + 1, (iregs)));\ SET_GR_A((r2), (regs), GR_A((r2), (iregs)));\ SET_GR_A((r2) + 1, (regs), GR_A((r2) + 1, (iregs)));\ } /*----------------------------------------------------------------------------*/ /* Commit intermediate register, except for GR1 */ /*----------------------------------------------------------------------------*/ #ifdef OPTION_CMPSC_DEBUG #define COMMITREGS2(regs, iregs, r1, r2) \ __COMMITREGS2((regs), (iregs), (r1), (r2)) \ logmsg("*** Regs committed\n"); #else #define COMMITREGS2(regs, iregs, r1, r2) \ __COMMITREGS2((regs), (iregs), (r1), (r2)) #endif #define __COMMITREGS2(regs, iregs, r1, r2) \ {\ SET_GR_A((r1), (regs), GR_A((r1), (iregs)));\ SET_GR_A((r1) + 1, (regs), GR_A((r1) + 1, (iregs)));\ SET_GR_A((r2), (regs), GR_A((r2), (iregs)));\ SET_GR_A((r2) + 1, (regs), GR_A((r2) + 1, (iregs)));\ } /*----------------------------------------------------------------------------*/ /* Initialize intermediate registers */ /*----------------------------------------------------------------------------*/ #define INITREGS(iregs, regs, r1, r2) \ { \ (iregs)->gr[1] = (regs)->gr[1]; \ (iregs)->gr[(r1)] = (regs)->gr[(r1)]; \ (iregs)->gr[(r1) + 1] = (regs)->gr[(r1) + 1]; \ (iregs)->gr[(r2)] = (regs)->gr[(r2)]; \ (iregs)->gr[(r2) + 1] = (regs)->gr[(r2) + 1]; \ } #if (__GEN_ARCH == 900) #undef INITREGS #define INITREGS(iregs, regs, r1, r2) \ { \ (iregs)->gr[1] = (regs)->gr[1]; \ (iregs)->gr[(r1)] = (regs)->gr[(r1)]; \ (iregs)->gr[(r1) + 1] = (regs)->gr[(r1) + 1]; \ (iregs)->gr[(r2)] = (regs)->gr[(r2)]; \ (iregs)->gr[(r2) + 1] = (regs)->gr[(r2) + 1]; \ (iregs)->psw.amode64 = (regs)->psw.amode64; \ } #endif /* defined(__GEN_ARCH == 900) */ /*----------------------------------------------------------------------------*/ /* General Purpose Register 0 macro's (GR0) */ /*----------------------------------------------------------------------------*/ /* cdss : compressed-data symbol size */ /* e : expansion operation */ /* f1 : format-1 sibling descriptors */ /* st : symbol-translation option */ /*----------------------------------------------------------------------------*/ #define GR0_cdss(regs) (((regs)->GR_L(0) & 0x0000F000) >> 12) #define GR0_e(regs) ((regs)->GR_L(0) & 0x00000100) #define GR0_f1(regs) ((regs)->GR_L(0) & 0x00000200) #define GR0_st(regs) ((regs)->GR_L(0) & 0x00010000) /*----------------------------------------------------------------------------*/ /* General Purpose Register 0 macro's (GR0) derived */ /*----------------------------------------------------------------------------*/ /* dcten : # dictionary entries */ /* dctsz : dictionary size */ /* smbsz : symbol size */ /*----------------------------------------------------------------------------*/ #define GR0_dcten(regs) (0x100 << GR0_cdss(regs)) #define GR0_dctsz(regs) (0x800 << GR0_cdss((regs))) #define GR0_smbsz(regs) (GR0_cdss((regs)) + 8) /*----------------------------------------------------------------------------*/ /* General Purpose Register 1 macro's (GR1) */ /*----------------------------------------------------------------------------*/ /* cbn : compressed-data bit number */ /* dictor: compression dictionary or expansion dictionary */ /* sttoff: symbol-translation-table offset */ /*----------------------------------------------------------------------------*/ #define GR1_cbn(regs) (((regs)->GR_L(1) & 0x00000007)) #define GR1_dictor(regs) (GR_A(1, regs) & ((GREG) 0xFFFFFFFFFFFFF000ULL)) #define GR1_sttoff(regs) (((regs)->GR_L(1) & 0x00000FF8) << 4) /*----------------------------------------------------------------------------*/ /* Sets the compressed bit number in GR1 */ /*----------------------------------------------------------------------------*/ #define GR1_setcbn(regs, cbn) ((regs)->GR_L(1) = ((regs)->GR_L(1) & 0xFFFFFFF8) | ((cbn) & 0x00000007)) /*----------------------------------------------------------------------------*/ /* Constants */ /*----------------------------------------------------------------------------*/ #define PROCESS_MAX 1048575 /* CPU-determined amount of data */ #define ECACHE_SIZE 32768 /* Expanded iss cache size */ /*----------------------------------------------------------------------------*/ /* Typedefs and prototypes */ /*----------------------------------------------------------------------------*/ #ifndef NO_2ND_COMPILE struct cc /* Compress context */ { BYTE *cce; /* Character entry under investigation */ BYTE *dest; /* Destination MADDR address */ BYTE *dict[32]; /* Dictionary MADDR addresses */ BYTE *edict[32]; /* Expansion dictionary MADDR addrs */ int f1; /* Indication format-1 sibling descr */ U16 is[8]; /* Cache for 8 index symbols */ unsigned ofst; /* Latest fetched offset */ unsigned smbsz; /* Symbol size */ BYTE *src; /* Source MADDR page address */ }; struct ec /* Expand context */ { BYTE *dest; /* Destination MADDR page address */ BYTE *dict[32]; /* Dictionary MADDR addresses */ BYTE ec[ECACHE_SIZE]; /* Expanded index symbol cache */ int eci[8192]; /* Index within cache for is */ int ecl[8192]; /* Size of expanded is */ int ecwm; /* Water mark */ BYTE oc[2080]; /* Output cache */ unsigned ocl; /* Output cache length */ unsigned smbsz; /* Symbol size */ BYTE *src; /* Source MADDR page address */ }; #endif /* #ifndef NO_2ND_COMPILE */ static void ARCH_DEP(compress)(int r1, int r2, REGS *regs, REGS *iregs); static void ARCH_DEP(expand)(int r1, int r2, REGS *regs, REGS *iregs); static void ARCH_DEP(expand_is)(REGS *regs, struct ec *ec, U16 is); static BYTE *ARCH_DEP(fetch_cce)(REGS *regs, struct cc *cc, unsigned index); static int ARCH_DEP(fetch_ch)(int r2, REGS *regs, REGS *iresg, struct cc *cc, BYTE *ch); static int ARCH_DEP(fetch_is)(int r2, REGS *regs, REGS *iregs, struct ec *ec, U16 *is); static void ARCH_DEP(fetch_iss)(int r2, REGS *regs, REGS *iregs, struct ec *ec, U16 is[8]); #ifdef OPTION_CMPSC_DEBUG static void print_cce(BYTE *cce); static void print_ece(BYTE *ece); static void print_sd(int f1, BYTE *sd1, BYTE *sd2); #endif static int ARCH_DEP(search_cce)(int r2, REGS *regs, REGS *iregs, struct cc *cc, BYTE *ch, U16 *is); static int ARCH_DEP(search_sd)(int r2, REGS *regs, REGS *iregs, struct cc *cc, BYTE *ch, U16 *is); static int ARCH_DEP(store_is)(int r1, int r2, REGS *regs, REGS *iregs, struct cc *cc, U16 is); static void ARCH_DEP(store_iss)(int r1, int r2, REGS *regs, REGS *iregs, struct cc *cc); static int ARCH_DEP(test_ec)(int r2, REGS *regs, REGS *iregs, struct cc *cc, BYTE *cce); static int ARCH_DEP(vstore)(int r1, REGS *regs, REGS *iregs, struct ec *ec, BYTE *buf, unsigned len); /*----------------------------------------------------------------------------*/ /* B263 CMPSC - Compression Call [RRE] */ /*----------------------------------------------------------------------------*/ DEF_INST(compression_call) { REGS iregs; /* Intermediate registers */ int r1; int r2; RRE(inst, regs, r1, r2); #ifdef OPTION_CMPSC_DEBUG logmsg("CMPSC: compression call\n"); logmsg(" r1 : GR%02d\n", r1); logmsg(" address : " F_VADR "\n", regs->GR(r1)); logmsg(" length : " F_GREG "\n", regs->GR(r1 + 1)); logmsg(" r2 : GR%02d\n", r2); logmsg(" address : " F_VADR "\n", regs->GR(r2)); logmsg(" length : " F_GREG "\n", regs->GR(r2 + 1)); logmsg(" GR00 : " F_GREG "\n", regs->GR(0)); logmsg(" st : %s\n", TRUEFALSE(GR0_st(regs))); logmsg(" cdss : %d\n", GR0_cdss(regs)); logmsg(" f1 : %s\n", TRUEFALSE(GR0_f1(regs))); logmsg(" e : %s\n", TRUEFALSE(GR0_e(regs))); logmsg(" GR01 : " F_GREG "\n", regs->GR(1)); logmsg(" dictor: " F_GREG "\n", GR1_dictor(regs)); logmsg(" sttoff: %08X\n", GR1_sttoff(regs)); logmsg(" cbn : %d\n", GR1_cbn(regs)); #endif /* Check the registers on even-odd pairs and valid compression-data symbol size */ if(unlikely(r1 & 0x01 || r2 & 0x01 || !GR0_cdss(regs) || GR0_cdss(regs) > 5)) ARCH_DEP(program_interrupt)(regs, PGM_SPECIFICATION_EXCEPTION); /* Check for empty input */ if(unlikely(!GR_A(r2 + 1, regs))) { regs->psw.cc = 0; return; } /* Check for empty output */ if(unlikely(!GR_A(r1 + 1, regs))) { regs->psw.cc = 1; return; } /* Set possible Data Exception code right away */ regs->dxc = DXC_DECIMAL; /* Initialize intermediate registers */ INITREGS(&iregs, regs, r1, r2); /* Now go to the requested function */ if(likely(GR0_e(regs))) ARCH_DEP(expand)(r1, r2, regs, &iregs); else ARCH_DEP(compress)(r1, r2, regs, &iregs); } /*============================================================================*/ /* Compress */ /*============================================================================*/ /*----------------------------------------------------------------------------*/ /* Compression Character Entry macro's (CCE) */ /*----------------------------------------------------------------------------*/ /* act : additional-extension-character count */ /* cct : child count */ /* cptr : child pointer; index of first child */ /* d : double-character entry */ /* x(i) : examine child bit for children 1 to 5 */ /* y(i) : examine child bit for 6th/13th and 7th/14th sibling */ /*----------------------------------------------------------------------------*/ #define CCE_act(cce) ((cce)[1] >> 5) #define CCE_cct(cce) ((cce)[0] >> 5) #define CCE_cptr(cce) ((((cce)[1] & 0x1f) << 8) | (cce)[2]) #define CCE_d(cce) ((cce)[1] & 0x20) #define CCE_x(cce, i) ((cce)[0] & (0x10 >> (i))) #define CCE_y(cce, i) ((cce)[1] & (0x80 >> (i))) /*----------------------------------------------------------------------------*/ /* Compression Character Entry macro's (CCE) derived */ /*----------------------------------------------------------------------------*/ /* cc(i) : child character */ /* ccc(i) : indication consecutive child character */ /* ccs : number of child characters */ /* ec(i) : additional extension character */ /* ecs : number of additional extension characters */ /* mcc : indication if siblings follow child characters */ /*----------------------------------------------------------------------------*/ #define CCE_cc(cce, i) ((cce)[3 + CCE_ecs((cce)) + (i)]) #define CCE_ccc(cce, i) (CCE_cc((cce), (i)) == CCE_cc((cce), 0)) #define CCE_ccs(cce) (CCE_cct((cce)) - (CCE_mcc((cce)) ? 1 : 0)) #define CCE_ec(cce, i) ((cce)[3 + (i)]) #define CCE_ecs(cce) ((CCE_cct((cce)) <= 1) ? CCE_act((cce)) : (CCE_d((cce)) ? 1 : 0)) #define CCE_mcc(cce) ((CCE_cct((cce)) + (CCE_d((cce)) ? 1 : 0) == 6)) /*----------------------------------------------------------------------------*/ /* Format-0 Sibling Descriptors macro's (SD0) */ /*----------------------------------------------------------------------------*/ /* sct : sibling count */ /* y(i) : examine child bit for siblings 1 to 5 */ /*----------------------------------------------------------------------------*/ #define SD0_sct(sd0) ((sd0)[0] >> 5) #define SD0_y(sd0, i) ((sd0)[0] & (0x10 >> (i))) /*----------------------------------------------------------------------------*/ /* Format-0 Sibling Descriptors macro's (SD0) derived */ /*----------------------------------------------------------------------------*/ /* ccc(i) : indication consecutive child character */ /* ecb(i) : examine child bit, if y then 6th/7th fetched from parent */ /* msc : indication if siblings follows last sibling */ /* sc(i) : sibling character */ /* scs : number of sibling characters */ /*----------------------------------------------------------------------------*/ #define SD0_ccc(sd0, i) (SD0_sc((sd0), (i)) == SD0_sc((sd0), 0)) #define SD0_ecb(sd0, i, cce, y) (((i) < 5) ? SD0_y((sd0), (i)) : (y) ? CCE_y((cce), ((i) - 5)) : 1) #define SD0_msc(sd0) (!SD0_sct((sd0))) #define SD0_sc(sd0, i) ((sd0)[1 + (i)]) #define SD0_scs(sd0) (SD0_msc((sd0)) ? 7 : SD0_sct((sd0))) /*----------------------------------------------------------------------------*/ /* Format-1 Sibling Descriptors macro's (SD1) */ /*----------------------------------------------------------------------------*/ /* sct : sibling count */ /* y(i) : examine child bit for sibling 1 to 12 */ /*----------------------------------------------------------------------------*/ #define SD1_sct(sd1) ((sd1)[0] >> 4) #define SD1_y(sd1, i) ((i) < 4 ? ((sd1)[0] & (0x08 >> (i))): ((sd1)[1] & (0x800 >> (i)))) /*----------------------------------------------------------------------------*/ /* Format-1 Sibling Descriptors macro's (SD1) derived */ /*----------------------------------------------------------------------------*/ /* ccc(i) : indication consecutive child character */ /* ecb(i) : examine child bit, if y then 13th/14th fetched from parent */ /* msc : indication if siblings follows last sibling */ /* sc(i) : sibling character */ /* scs : number of sibling characters */ /*----------------------------------------------------------------------------*/ #define SD1_ccc(sd1, sd2, i) (SD1_sc((sd1), (sd2), (i)) == SD1_sc((sd1), (sd2), 0)) #define SD1_ecb(sd1, i, cce, y) (((i) < 12) ? SD1_y((sd1), (i)) : (y) ? CCE_y((cce), ((i) - 12)) : 1) #define SD1_msc(sd1) ((SD1_sct((sd1)) == 15)) #define SD1_sc(sd1, sd2, i) ((i) < 6 ? (sd1)[2 + (i)] : (sd2)[(i) - 6]) #define SD1_scs(sd1) (SD1_msc((sd1)) ? 14 : SD1_sct((sd1))) /*----------------------------------------------------------------------------*/ /* Format independent sibling descriptor macro's */ /*----------------------------------------------------------------------------*/ #define SD_ccc(f1, sd1, sd2, i) ((f1) ? SD1_ccc((sd1), (sd2), (i)) : SD0_ccc((sd1), (i))) #define SD_ecb(f1, sd1, i, cce, y) ((f1) ? SD1_ecb((sd1), (i), (cce), (y)) : SD0_ecb((sd1), (i), (cce), (y))) #define SD_msc(f1, sd1) ((f1) ? SD1_msc((sd1)) : SD0_msc((sd1))) #define SD_sc(f1, sd1, sd2, i) ((f1) ? SD1_sc((sd1), (sd2), (i)) : SD0_sc((sd1), (i))) #define SD_scs(f1, sd1) ((f1) ? SD1_scs((sd1)) : SD0_scs((sd1))) /*============================================================================*/ /*----------------------------------------------------------------------------*/ /* compress */ /*----------------------------------------------------------------------------*/ static void ARCH_DEP(compress)(int r1, int r2, REGS *regs, REGS *iregs) { struct cc cc; /* Compression context */ BYTE ch; /* Character read */ GREG dictor; /* Dictionary origin */ int eos; /* indication end of source */ GREG exit_value; /* return cc=3 on this value */ int i; U16 is; /* Last matched index symbol */ GREG vaddr; /* Virtual address */ /* Initialize values */ dictor = GR1_dictor(regs); eos = 0; /* Initialize dictionary MADDR addresses */ vaddr = dictor; for(i = 0; i < (0x01 << GR0_cdss(regs)); i++) { cc.dict[i] = MADDR(vaddr, r2, regs, ACCTYPE_READ, regs->psw.pkey); vaddr += 0x800; } /* Initialize format-1 sibling descriptor indicator */ cc.f1 = GR0_f1(regs); /* Initialize expansion dictionary MADDR addresses */ if(cc.f1) { vaddr = dictor + GR0_dctsz(regs); for(i = 0; i < (0x01 << GR0_cdss(regs)); i++) { cc.edict[i] = MADDR(vaddr, r2, regs, ACCTYPE_READ, regs->psw.pkey); vaddr += 0x800; } } /* Initialize dest, source maddr page address and symbol size */ cc.dest = NULL; cc.ofst = 0; cc.smbsz = GR0_smbsz(regs); cc.src = NULL; /* Process individual index symbols until cbn bocomes zero */ if(unlikely(GR1_cbn(regs))) { #ifdef OPTION_CMPSC_DEBUG logmsg("Cbn not zero, process individual index symbols\n"); #endif while(likely(GR1_cbn(regs))) { /* Get the next character, return on end of source */ if(unlikely(ARCH_DEP(fetch_ch)(r2, regs, iregs, &cc, &ch))) return; /* Get the alphabet entry */ cc.cce = ARCH_DEP(fetch_cce)(regs, &cc, ch); /* We always match the alpabet entry, so set last match */ ADJUSTREGS(r2, regs, iregs, 1); /* Try to find a child in compression character entry */ is = ch; while(ARCH_DEP(search_cce)(r2, regs, iregs, &cc, &ch, &is)); /* Write the last match, this can be the alphabet entry */ if(unlikely(ARCH_DEP(store_is)(r1, r2, regs, iregs, &cc, is))) return; /* Commit registers, we have completed a full compression */ COMMITREGS(regs, iregs, r1, r2); } } /* Try to process the CPU-determined amount of data */ if(likely(GR_A(r2 + 1, regs) <= PROCESS_MAX)) exit_value = 0; else exit_value = GR_A(r2 + 1, regs) - PROCESS_MAX; /* Block processing, cbn stays zero */ while(likely(GR_A(r1 + 1, iregs) >= cc.smbsz && exit_value <= GR_A(r2 + 1, regs))) { for(i = 0; i < 8; i++) { /* Get the next character, return on end of source */ if(unlikely(ARCH_DEP(fetch_ch)(r2, regs, iregs, &cc, &ch))) { int j; /* Write individual found index symbols */ for(j = 0; j < i; j++) ARCH_DEP(store_is)(r1, r2, regs, iregs, &cc, cc.is[j]); COMMITREGS(regs, iregs, r1, r2); return; } /* Get the alphabet entry */ cc.cce = ARCH_DEP(fetch_cce)(regs, &cc, ch); /* We always match the alpabet entry, so set last match */ ADJUSTREGS(r2, regs, iregs, 1); /* Try to find a child in compression character entry */ is = ch; while(ARCH_DEP(search_cce)(r2, regs, iregs, &cc, &ch, &is)); /* Write the last match, this can be the alphabet entry */ cc.is[i] = is; #ifdef OPTION_CMPSC_DEBUG logmsg("compress : is %04X (%d)\n", is, i); #endif } ARCH_DEP(store_iss)(r1, r2, regs, iregs, &cc); /* Commit registers, we have completed a full compression */ COMMITREGS2(regs, iregs, r1, r2); } while(exit_value <= GR_A(r2 + 1, regs)) { /* Get the next character, return on end of source */ if(unlikely(ARCH_DEP(fetch_ch)(r2, regs, iregs, &cc, &ch))) return; /* Get the alphabet entry */ cc.cce = ARCH_DEP(fetch_cce)(regs, &cc, ch); /* We always match the alpabet entry, so set last match */ ADJUSTREGS(r2, regs, iregs, 1); /* Try to find a child in compression character entry */ is = ch; while(ARCH_DEP(search_cce)(r2, regs, iregs, &cc, &ch, &is)); /* Write the last match, this can be the alphabet entry */ if(unlikely(ARCH_DEP(store_is)(r1, r2, regs, iregs, &cc, is))) return; /* Commit registers, we have completed a full compression */ COMMITREGS(regs, iregs, r1, r2); } /* When reached end of source, return to caller */ if(likely(!GR_A(r2 + 1, regs))) return; /* Reached model dependent CPU processing amount */ regs->psw.cc = 3; #ifdef OPTION_CMPSC_DEBUG logmsg("compress : reached CPU determined amount of data\n"); #endif } /*----------------------------------------------------------------------------*/ /* fetch_cce (compression character entry) */ /*----------------------------------------------------------------------------*/ static BYTE *ARCH_DEP(fetch_cce)(REGS *regs, struct cc *cc, unsigned index) { BYTE *cce; unsigned cct; /* Child count */ index *= 8; cce = &cc->dict[index / 0x800][index % 0x800]; ITIMER_SYNC(GR1_dictor(regs) + index, 8 - 1, regs); #ifdef OPTION_CMPSC_DEBUG logmsg("fetch_cce: index %04X\n", index / 8); print_cce(cce); #endif cct = CCE_cct(cce); if(cct < 2) { if(unlikely(CCE_act(cce) > 4)) ARCH_DEP(program_interrupt)(regs, PGM_DATA_EXCEPTION); } else { if(!CCE_d(cce)) { if(unlikely(cct == 7)) ARCH_DEP(program_interrupt)(regs, PGM_DATA_EXCEPTION); } else { if(unlikely(cct > 5)) ARCH_DEP(program_interrupt)(regs, PGM_DATA_EXCEPTION); } } return(cce); } /*----------------------------------------------------------------------------*/ /* fetch_ch (character) */ /*----------------------------------------------------------------------------*/ static int ARCH_DEP(fetch_ch)(int r2, REGS *regs, REGS *iregs, struct cc *cc, BYTE *ch) { unsigned ofst; /* Offset within page */ /* Check for end of source condition */ if(unlikely(!GR_A(r2 + 1, iregs))) { #ifdef OPTION_CMPSC_DEBUG logmsg("fetch_ch : reached end of source\n"); #endif regs->psw.cc = 0; return(-1); } ofst = GR_A(r2, iregs) & 0x7ff; ITIMER_SYNC(GR_A(r2, iregs), 1 - 1, regs); /* Fingers crossed that we stay within current page */ if(unlikely(!cc->src || ofst < cc->ofst)) cc->src = MADDR((GR_A(r2, iregs) & ~0x7ff) & ADDRESS_MAXWRAP(regs), r2, regs, ACCTYPE_READ, regs->psw.pkey); *ch = cc->src[ofst]; cc->ofst = ofst; #ifdef OPTION_CMPSC_DEBUG logmsg("fetch_ch : %02X at " F_VADR "\n", *ch, GR_A(r2, iregs)); #endif return(0); } #ifndef NO_2ND_COMPILE #ifdef OPTION_CMPSC_DEBUG /*----------------------------------------------------------------------------*/ /* print_cce (compression character entry). */ /*----------------------------------------------------------------------------*/ static void print_cce(BYTE *cce) { int j; int prt_detail; logmsg(" cce : "); prt_detail = 0; for(j = 0; j < 8; j++) { if(!prt_detail && cce[j]) prt_detail = 1; logmsg("%02X", cce[j]); } logmsg("\n"); if(prt_detail) { logmsg(" cct : %d\n", CCE_cct(cce)); switch(CCE_cct(cce)) { case 0: { logmsg(" act : %d\n", (int) CCE_act(cce)); if(CCE_act(cce)) { logmsg(" ec(s) :"); for(j = 0; j < CCE_ecs(cce); j++) logmsg(" %02X", CCE_ec(cce, j)); logmsg("\n"); } break; } case 1: { logmsg(" x1 : %c\n", (int) (CCE_x(cce, 0) ? '1' : '0')); logmsg(" act : %d\n", (int) CCE_act(cce)); logmsg(" cptr : %04X\n", CCE_cptr(cce)); if(CCE_act(cce)) { logmsg(" ec(s) :"); for(j = 0; j < CCE_ecs(cce); j++) logmsg(" %02X", CCE_ec(cce, j)); logmsg("\n"); } logmsg(" cc : %02X\n", CCE_cc(cce, 0)); break; } default: { logmsg(" x1..x5 : "); for(j = 0; j < 5; j++) logmsg("%c", (int) (CCE_x(cce, j) ? '1' : '0')); logmsg("\n y1..y2 : "); for(j = 0; j < 2; j++) logmsg("%c", (int) (CCE_y(cce, j) ? '1' : '0')); logmsg("\n d : %s\n", TRUEFALSE(CCE_d(cce))); logmsg(" cptr : %04X\n", CCE_cptr(cce)); if(CCE_d(cce)) logmsg(" ec : %02X\n", CCE_ec(cce, 0)); logmsg(" ccs :"); for(j = 0; j < CCE_ccs(cce); j++) logmsg(" %02X", CCE_cc(cce, j)); logmsg("\n"); break; } } } } /*----------------------------------------------------------------------------*/ /* print_sd (sibling descriptor). */ /*----------------------------------------------------------------------------*/ static void print_sd(int f1, BYTE *sd1, BYTE *sd2) { int j; int prt_detail; if(f1) { logmsg(" sd1 : "); prt_detail = 0; for(j = 0; j < 8; j++) { if(!prt_detail && sd1[j]) prt_detail = 1; logmsg("%02X", sd1[j]); } for(j = 0; j < 8; j++) { if(!prt_detail && sd2[j]) prt_detail = 1; logmsg("%02X", sd2[j]); } logmsg("\n"); if(prt_detail) { logmsg(" sct : %d\n", SD1_sct(sd1)); logmsg(" y1..y12: "); for(j = 0; j < 12; j++) logmsg("%c", (SD1_y(sd1, j) ? '1' : '0')); logmsg("\n sc(s) :"); for(j = 0; j < SD1_scs(sd1); j++) logmsg(" %02X", SD1_sc(sd1, sd2, j)); logmsg("\n"); } } else { logmsg(" sd0 : "); prt_detail = 0; for(j = 0; j < 8; j++) { if(!prt_detail && sd1[j]) prt_detail = 1; logmsg("%02X", sd1[j]); } logmsg("\n"); if(prt_detail) { logmsg(" sct : %d\n", SD0_sct(sd1)); logmsg(" y1..y5 : "); for(j = 0; j < 5; j++) logmsg("%c", (SD0_y(sd1, j) ? '1' : '0')); logmsg("\n sc(s) :"); for(j = 0; j < SD0_scs(sd1); j++) logmsg(" %02X", SD0_sc(sd1, j)); logmsg("\n"); } } } #endif #endif /* #ifndef NO_2ND_COMPILE */ /*----------------------------------------------------------------------------*/ /* search_cce (compression character entry) */ /*----------------------------------------------------------------------------*/ static int ARCH_DEP(search_cce)(int r2, REGS *regs, REGS *iregs, struct cc *cc, BYTE *ch, U16 *is) { BYTE *ccce; /* child compression character entry */ int ccs; /* Number of child characters */ int i; /* child character index */ int ind_search_siblings; /* Indicator for searching siblings */ /* Initialize values */ ccs = CCE_ccs(cc->cce); /* Get the next character when there are children */ if(likely(ccs)) { if(ARCH_DEP(fetch_ch(r2, regs, iregs, cc, ch))) return(0); ind_search_siblings = 1; /* Now check all children in parent */ for(i = 0; i < ccs; i++) { /* Stop searching when child tested and no consecutive child character */ if(unlikely(!ind_search_siblings && !CCE_ccc(cc->cce, i))) return(0); /* Compare character with child */ if(unlikely(*ch == CCE_cc(cc->cce, i))) { /* Child is tested, so stop searching for siblings*/ ind_search_siblings = 0; /* Check if child should not be examined */ if(unlikely(!CCE_x(cc->cce, i))) { /* No need to examine child, found the last match */ ADJUSTREGS(r2, regs, iregs, 1); *is = CCE_cptr(cc->cce) + i; /* Index symbol is found, stop searching */ return(0); } /* Found a child get the character entry */ ccce = ARCH_DEP(fetch_cce)(regs, cc, CCE_cptr(cc->cce) + i); /* Check if additional extension characters match */ if(likely(ARCH_DEP(test_ec)(r2, regs, iregs, cc, ccce))) { /* Set last match */ ADJUSTREGS(r2, regs, iregs, CCE_ecs(ccce) + 1); *is = CCE_cptr(cc->cce) + i; #ifdef OPTION_CMPSC_DEBUG logmsg("search_cce index %04X parent\n", *is); #endif /* Found a matching child, make it parent */ cc->cce = ccce; /* We found a parent, keep searching */ return(1); } } } /* Are there siblings? */ if(likely(CCE_mcc(cc->cce))) return(ARCH_DEP(search_sd)(r2, regs, iregs, cc, ch, is)); } /* No siblings, write found index symbol */ return(0); } /*----------------------------------------------------------------------------*/ /* search_sd (sibling descriptor) */ /*----------------------------------------------------------------------------*/ static int ARCH_DEP(search_sd)(int r2, REGS *regs, REGS *iregs, struct cc *cc, BYTE *ch, U16 *is) { BYTE *ccce; /* Child compression character entry */ #ifdef FEATURE_INTERVAL_TIMER GREG dictor; /* Dictionary origin */ #endif int i; /* Sibling character index */ U16 index; /* Index within dictionary */ int ind_search_siblings; /* Indicator for keep searching */ int scs; /* Number of sibling characters */ BYTE *sd1; /* Sibling descriptor fmt-0|1 part 1 */ BYTE *sd2; /* Sibling descriptor fmt-1 part 2 */ int sd_ptr; /* Pointer to sibling descriptor */ int searched; /* Number of children searched */ int y_in_parent; /* Indicator if y bits are in parent */ /* Initialize values */ #ifdef FEATURE_INTERVAL_TIMER dictor = GR1_dictor(regs); #endif ind_search_siblings = 1; /* For the first sibling descriptor y bits are in the cce parent */ y_in_parent = 1; /* Sibling follows last possible child */ sd_ptr = CCE_ccs(cc->cce); /* set searched childs */ searched = sd_ptr; /* As long there are sibling characters */ do { /* Get the sibling descriptor */ index = (CCE_cptr(cc->cce) + sd_ptr) * 8; sd1 = &cc->dict[index / 0x800][index % 0x800]; ITIMER_SYNC(GR1_dictor(regs) + index, 8 - 1, regs); /* If format-1, get second half from the expansion dictionary */ if(cc->f1) { sd2 = &cc->edict[index / 0x800][index % 0x800]; ITIMER_SYNC(GR1_dictor(regs) + GR0_dctsz(regs) + index, 8 - 1, regs); #ifdef OPTION_CMPSC_DEBUG /* Print before possible exception */ logmsg("fetch_sd1: index %04X\n", CCE_cptr(cc->cce) + sd_ptr); print_sd(1, sd1, sd2); #endif /* Check for data exception */ if(unlikely(!SD1_sct(sd1))) ARCH_DEP(program_interrupt)((regs), PGM_DATA_EXCEPTION); } else { #ifdef OPTION_CMPSC_DEBUG logmsg("fetch_sd0: index %04X\n", CCE_cptr(cc->cce) + sd_ptr); print_sd(0, sd1, sd2); #endif } /* Check all children in sibling descriptor */ scs = SD_scs(cc->f1, sd1); for(i = 0; i < scs; i++) { /* Stop searching when child tested and no consecutive child character */ if(unlikely(!ind_search_siblings && !SD_ccc(cc->f1, sd1, sd2, i))) return(0); if(unlikely(*ch == SD_sc(cc->f1, sd1, sd2, i))) { /* Child is tested, so stop searching for siblings*/ ind_search_siblings = 0; /* Check if child should not be examined */ if(unlikely(!SD_ecb(cc->f1, sd1, i, cc->cce, y_in_parent))) { /* No need to examine child, found the last match */ ADJUSTREGS(r2, regs, iregs, 1); *is = CCE_cptr(cc->cce) + sd_ptr + i + 1; /* Index symbol found */ return(0); } /* Found a child get the character entry */ ccce = ARCH_DEP(fetch_cce)(regs, cc, CCE_cptr(cc->cce) + sd_ptr + i + 1); /* Check if additional extension characters match */ if(unlikely(ARCH_DEP(test_ec)(r2, regs, iregs, cc, ccce))) { /* Set last match */ ADJUSTREGS(r2, regs, iregs, CCE_ecs(ccce) + 1); *is = CCE_cptr(cc->cce) + sd_ptr + i + 1; #ifdef OPTION_CMPSC_DEBUG logmsg("search_sd: index %04X parent\n", *is); #endif /* Found a matching child, make it parent */ cc->cce = ccce; /* We found a parent */ return(1); } } } /* Next sibling follows last possible child */ sd_ptr += scs + 1; /* test for searching child 261 */ searched += scs; if(unlikely(searched > 260)) ARCH_DEP(program_interrupt)((regs), PGM_DATA_EXCEPTION); /* We get the next sibling descriptor, no y bits in parent for him */ y_in_parent = 0; } while(ind_search_siblings && SD_msc(cc->f1, sd1)); return(0); } /*----------------------------------------------------------------------------*/ /* store_is (index symbol) */ /*----------------------------------------------------------------------------*/ static int ARCH_DEP(store_is)(int r1, int r2, REGS *regs, REGS *iregs, struct cc *cc, U16 is) { unsigned cbn; /* Compressed-data bit number */ U32 set_mask; /* mask to set the bits */ BYTE work[3]; /* work bytes */ /* Initialize values */ cbn = GR1_cbn(iregs); /* Can we write an index or interchange symbol */ if(unlikely(GR_A(r1 + 1, iregs) < 2)) { if(unlikely(((cbn + cc->smbsz - 1) / 8) >= GR_A(r1 + 1, iregs))) { regs->psw.cc = 1; #ifdef OPTION_CMPSC_DEBUG logmsg("store_is : end of output buffer\n"); #endif return(-1); } } /* Check if symbol translation is requested */ if(unlikely(GR0_st(regs))) { /* Get the interchange symbol */ ARCH_DEP(vfetchc)(work, 1, (GR1_dictor(regs) + GR1_sttoff(regs) + is * 2) & ADDRESS_MAXWRAP(regs), r2, regs); #ifdef OPTION_CMPSC_DEBUG logmsg("store_is : %04X -> %02X%02X\n", is, work[0], work[1]); #endif /* set index_symbol to interchange symbol */ is = (work[0] << 8) + work[1]; } /* Allign set mask */ set_mask = ((U32) is) << (24 - cc->smbsz - cbn); /* Calculate first byte */ if(likely(cbn)) { work[0] = ARCH_DEP(vfetchb)(GR_A(r1, iregs) & ADDRESS_MAXWRAP(regs), r1, regs); work[0] |= (set_mask >> 16) & 0xff; } else work[0] = (set_mask >> 16) & 0xff; /* Calculate second byte */ work[1] = (set_mask >> 8) & 0xff; /* Calculate possible third byte and store */ if(unlikely((cc->smbsz + cbn) > 16)) { work[2] = set_mask & 0xff; ARCH_DEP(vstorec)(work, 2, GR_A(r1, iregs) & ADDRESS_MAXWRAP(regs), r1, regs); } else ARCH_DEP(vstorec)(work, 1, GR_A(r1, iregs) & ADDRESS_MAXWRAP(regs), r1, regs); /* Adjust destination registers */ ADJUSTREGS(r1, regs, iregs, (cbn + cc->smbsz) / 8); /* Calculate and set the new Compressed-data Bit Number */ GR1_setcbn(iregs, (cbn + cc->smbsz) % 8); #ifdef OPTION_CMPSC_DEBUG logmsg("store_is : %04X, cbn=%d, GR%02d=" F_VADR ", GR%02d=" F_GREG "\n", is, GR1_cbn(iregs), r1, iregs->GR(r1), r1 + 1, iregs->GR(r1 + 1)); #endif return(0); } /*----------------------------------------------------------------------------*/ /* store_iss (index symbols) */ /*----------------------------------------------------------------------------*/ static void ARCH_DEP(store_iss)(int r1, int r2, REGS *regs, REGS *iregs, struct cc *cc) { GREG dictor; /* dictionary origin */ int i; U16 *is; /* Index symbol array */ unsigned len1; /* Length in first page */ BYTE *main1; /* Address first page */ BYTE mem[13]; /* Build buffer */ unsigned ofst; /* Offset within page */ BYTE *sk; /* Storage key */ /* Check if symbol translation is requested */ if(unlikely(GR0_st(regs))) { dictor = GR1_dictor(regs) + GR1_sttoff(regs); for(i = 0; i < 8; i++) { /* Get the interchange symbol */ ARCH_DEP(vfetchc)(mem, 1, (dictor + cc->is[i] * 2) & ADDRESS_MAXWRAP(regs), r2, regs); #ifdef OPTION_CMPSC_DEBUG logmsg("store_iss: %04X -> %02X%02X\n", cc->is[i], mem[0], mem[1]); #endif /* set index_symbol to interchange symbol */ cc->is[i] = (mem[0] << 8) + mem[1]; } } /* Calculate buffer for 8 index symbols */ is = cc->is; switch(cc->smbsz) { case 9: /* 9-bits */ { /* 0 1 2 3 4 5 6 7 8 */ /* 01234567 01234567 01234567 01234567 01234567 01234567 01234567 01234567 01234567 */ /* 01234567 80123456 78012345 67801234 56780123 45678012 34567801 23456780 12345678 */ /* 0 1 2 3 4 5 6 7 */ mem[0] = ( (is[0] >> 1)); mem[1] = ((is[0] << 7) | (is[1] >> 2)) & 0xff; mem[2] = ((is[1] << 6) | (is[2] >> 3)) & 0xff; mem[3] = ((is[2] << 5) | (is[3] >> 4)) & 0xff; mem[4] = ((is[3] << 4) | (is[4] >> 5)) & 0xff; mem[5] = ((is[4] << 3) | (is[5] >> 6)) & 0xff; mem[6] = ((is[5] << 2) | (is[6] >> 7)) & 0xff; mem[7] = ((is[6] << 1) | (is[7] >> 8)) & 0xff; mem[8] = ((is[7]) ) & 0xff; break; } case 10: /* 10-bits */ { /* 0 1 2 3 4 5 6 7 8 9 */ /* 01234567 01234567 01234567 01234567 01234567 01234567 01234567 01234567 01234567 01234567 */ /* 01234567 89012345 67890123 45678901 23456789 01234567 89012345 67890123 45678901 23456789 */ /* 0 1 2 3 4 5 6 7 */ mem[0] = ( (is[0] >> 2)); mem[1] = ((is[0] << 6) | (is[1] >> 4)) & 0xff; mem[2] = ((is[1] << 4) | (is[2] >> 6)) & 0xff; mem[3] = ((is[2] << 2) | (is[3] >> 8)) & 0xff; mem[4] = ((is[3]) ) & 0xff; mem[5] = ( (is[4] >> 2)) & 0xff; mem[6] = ((is[4] << 6) | (is[5] >> 4)) & 0xff; mem[7] = ((is[5] << 4) | (is[6] >> 6)) & 0xff; mem[8] = ((is[6] << 2) | (is[7] >> 8)) & 0xff; mem[9] = ((is[7]) ) & 0xff; break; } case 11: /* 11-bits */ { /* 0 1 2 3 4 5 6 7 8 9 a */ /* 01234567 01234567 01234567 01234567 01234567 01234567 01234567 01234567 01234567 01234567 01234567 */ /* 01234567 89a01234 56789a01 23456789 a0123456 789a0123 456789a0 12345678 9a012345 6789a012 3456789a */ /* 0 1 2 3 4 5 6 7 */ mem[ 0] = ( (is[0] >> 3)); mem[ 1] = ((is[0] << 5) | (is[1] >> 6)) & 0xff; mem[ 2] = ((is[1] << 2) | (is[2] >> 9)) & 0xff; mem[ 3] = ( (is[2] >> 1)) & 0xff; mem[ 4] = ((is[2] << 7) | (is[3] >> 4)) & 0xff; mem[ 5] = ((is[3] << 4) | (is[4] >> 7)) & 0xff; mem[ 6] = ((is[4] << 1) | (is[5] >> 10)) & 0xff; mem[ 7] = ( (is[5] >> 2)) & 0xff; mem[ 8] = ((is[5] << 6) | (is[6] >> 5)) & 0xff; mem[ 9] = ((is[6] << 3) | (is[7] >> 8)) & 0xff; mem[10] = ((is[7]) ) & 0xff; break; } case 12: /* 12-bits */ { /* 0 1 2 3 4 5 6 7 8 9 a b */ /* 01234567 01234567 01234567 01234567 01234567 01234567 01234567 01234567 01234567 01234567 01234567 01234567 */ /* 01234567 89ab0123 456789ab 01234567 89ab0123 456789ab 01234567 89ab0123 456789ab 01234567 89ab0123 456789ab */ /* 0 1 2 3 4 5 6 7 */ mem[ 0] = ( (is[0] >> 4)); mem[ 1] = ((is[0] << 4) | (is[1] >> 8)) & 0xff; mem[ 2] = ((is[1]) ) & 0xff; mem[ 3] = ( (is[2] >> 4)) & 0xff; mem[ 4] = ((is[2] << 4) | (is[3] >> 8)) & 0xff; mem[ 5] = ((is[3]) ) & 0xff; mem[ 6] = ( (is[4] >> 4)) & 0xff; mem[ 7] = ((is[4] << 4) | (is[5] >> 8)) & 0xff; mem[ 8] = ((is[5]) ) & 0xff; mem[ 9] = ( (is[6] >> 4)) & 0xff; mem[10] = ((is[6] << 4) | (is[7] >> 8)) & 0xff; mem[11] = ((is[7]) ) & 0xff; break; } case 13: /* 13-bits */ { /* 0 1 2 3 4 5 6 7 8 9 a b c */ /* 01234567 01234567 01234567 01234567 01234567 01234567 01234567 01234567 01234567 01234567 01234567 01234567 01234567 */ /* 01234567 89abc012 3456789a bc012345 6789abc0 12345678 9abc0123 456789ab c0123456 789abc01 23456789 abc01234 56789abc */ /* 0 1 2 3 4 5 6 7 */ mem[ 0] = ( (is[0] >> 5)); mem[ 1] = ((is[0] << 3) | (is[1] >> 10)) & 0xff; mem[ 2] = ( (is[1] >> 2)) & 0xff; mem[ 3] = ((is[1] << 6) | (is[2] >> 7)) & 0xff; mem[ 4] = ((is[2] << 1) | (is[3] >> 12)) & 0xff; mem[ 5] = ( (is[3] >> 4)) & 0xff; mem[ 6] = ((is[3] << 4) | (is[4] >> 9)) & 0xff; mem[ 7] = ( (is[4] >> 1)) & 0xff; mem[ 8] = ((is[4] << 7) | (is[5] >> 6)) & 0xff; mem[ 9] = ((is[5] << 2) | (is[6] >> 11)) & 0xff; mem[10] = ( (is[6] >> 3)) & 0xff; mem[11] = ((is[6] << 5) | (is[7] >> 8)) & 0xff; mem[12] = ((is[7]) ) & 0xff; break; } } /* Fingers crossed that we stay within one page */ ofst = GR_A(r1, iregs) & 0x7ff; if(likely(ofst + cc->smbsz < 0x800)) { if(unlikely(!cc->dest)) cc->dest = MADDR((GR_A(r1, iregs) & ~0x7ff) & ADDRESS_MAXWRAP(regs), r1, regs, ACCTYPE_WRITE, regs->psw.pkey); memcpy(&cc->dest[ofst], mem, cc->smbsz); ITIMER_UPDATE(GR_A(r1, iregs), cc->smbsz - 1, regs); } else { /* We need 2 pages */ if(unlikely(!cc->dest)) main1 = MADDR((GR_A(r1, iregs) & ~0x7ff) & ADDRESS_MAXWRAP(regs), r1, regs, ACCTYPE_WRITE_SKP, regs->psw.pkey); else main1 = cc->dest; sk = regs->dat.storkey; len1 = 0x800 - ofst; cc->dest = MADDR((GR_A(r1, iregs) + len1) & ADDRESS_MAXWRAP(regs), r1, regs, ACCTYPE_WRITE, regs->psw.pkey); memcpy(&main1[ofst], mem, len1); memcpy(cc->dest, &mem[len1], cc->smbsz - len1 + 1); *sk |= (STORKEY_REF | STORKEY_CHANGE); } ADJUSTREGS(r1, regs, iregs, cc->smbsz); #ifdef OPTION_CMPSC_DEBUG logmsg("store_iss:"); for(i = 0; i < 8; i++) logmsg(" %04X", cc->is[i]); logmsg(", GR%02d=" F_VADR ", GR%02d=" F_GREG "\n", r1, iregs->GR(r1), r1 + 1, iregs->GR(r1 + 1)); #endif } /*----------------------------------------------------------------------------*/ /* test_ec (extension characters) */ /*----------------------------------------------------------------------------*/ static int ARCH_DEP(test_ec)(int r2, REGS *regs, REGS *iregs, struct cc *cc, BYTE *cce) { BYTE ch; int i; unsigned ofst; for(i = 0; i < CCE_ecs(cce); i++) { if(unlikely(GR_A(r2 + 1, iregs) <= (U32) i + 1)) return(0); ofst = (GR_A(r2, iregs) + i + 1) & 0x7ff; if(unlikely(!cc->src || ofst < cc->ofst)) ch = ARCH_DEP(vfetchb)((GR_A(r2, iregs) + i + 1) & ADDRESS_MAXWRAP(regs), r2, regs); else { ch = cc->src[ofst]; ITIMER_SYNC(GR_A(r2, iregs) + i + 1, 1 - 1, regs); } if(unlikely(ch != CCE_ec(cce, i))) return(0); } /* a perfect match */ return(1); } /*============================================================================*/ /* Expand */ /*============================================================================*/ /*----------------------------------------------------------------------------*/ /* Expansion Character Entry macro's (ECE) */ /*----------------------------------------------------------------------------*/ /* bit34 : indication of bits 3 and 4 (what else ;-) */ /* csl : complete symbol length */ /* ofst : offset from current position in output area */ /* pptr : predecessor pointer */ /* psl : partial symbol length */ /*----------------------------------------------------------------------------*/ #define ECE_bit34(ece) ((ece)[0] & 0x18) #define ECE_csl(ece) ((ece)[0] & 0x07) #define ECE_ofst(ece) ((ece)[7]) #define ECE_pptr(ece) ((((ece)[0] & 0x1f) << 8) | (ece)[1]) #define ECE_psl(ece) ((ece)[0] >> 5) /*----------------------------------------------------------------------------*/ /* expand */ /*----------------------------------------------------------------------------*/ static void ARCH_DEP(expand)(int r1, int r2, REGS *regs, REGS *iregs) { unsigned cw; /* Characters written */ int dcten; /* Number of different symbols */ struct ec ec; /* Expand cache */ int i; U16 is; /* Index symbol */ U16 iss[8]; /* Index symbols */ GREG vaddr; /* Virtual address */ /* Initialize values */ cw = 0; dcten = GR0_dcten(regs); /* Initialize destination dictionary address */ ec.dest = NULL; /* Initialize dictionary maddr addresses */ vaddr = GR1_dictor(regs); for(i = 0; i < (0x01 << GR0_cdss(regs)); i++) { ec.dict[i] = MADDR(vaddr, r2, regs, ACCTYPE_READ, regs->psw.pkey); vaddr += 0x800; } /* Initialize expanded index symbol cache and prefill with alphabet entries */ for(i = 0; i < 256; i++) /* Alphabet entries */ { ec.ec[i] = i; ec.eci[i] = i; ec.ecl[i] = 1; } for(i = 256; i < dcten; i++) /* Clear all other index symbols */ ec.ecl[i] = 0; ec.ecwm = 256; /* Set watermark after alphabet part */ /* Initialize source maddr page address and symbols size */ ec.smbsz = GR0_smbsz(regs); ec.src = NULL; /* Process individual index symbols until cbn becomes zero */ if(unlikely(GR1_cbn(regs))) { while(likely(GR1_cbn(regs))) { if(unlikely(ARCH_DEP(fetch_is)(r2, regs, iregs, &ec, &is))) return; if(likely(!ec.ecl[is])) { ec.ocl = 0; /* Initialize output cache */ ARCH_DEP(expand_is)(regs, &ec, is); if(unlikely(ARCH_DEP(vstore)(r1, regs, iregs, &ec, ec.oc, ec.ocl))) return; cw += ec.ocl; } else { if(unlikely(ARCH_DEP(vstore)(r1, regs, iregs, &ec, &ec.ec[ec.eci[is]], ec.ecl[is]))) return; cw += ec.ecl[is]; } } /* Commit, including GR1 */ COMMITREGS(regs, iregs, r1, r2); } /* Block processing, cbn stays zero */ while(likely(GR_A(r2 + 1, iregs) >= ec.smbsz && cw < PROCESS_MAX)) { ARCH_DEP(fetch_iss)(r2, regs, iregs, &ec, iss); ec.ocl = 0; /* Initialize output cache */ for(i = 0; i < 8; i++) { #ifdef OPTION_CMPSC_DEBUG logmsg("expand : is %04X (%d)\n", iss[i], i); #endif if(unlikely(!ec.ecl[iss[i]])) ARCH_DEP(expand_is)(regs, &ec, iss[i]); else { memcpy(&ec.oc[ec.ocl], &ec.ec[ec.eci[iss[i]]], ec.ecl[iss[i]]); ec.ocl += ec.ecl[iss[i]]; } } /* Write and commit, cbn unchanged, so no commit for GR1 needed */ if(unlikely(ARCH_DEP(vstore)(r1, regs, iregs, &ec, ec.oc, ec.ocl))) return; COMMITREGS2(regs, iregs, r1, r2); cw += ec.ocl; } if(unlikely(cw >= PROCESS_MAX)) { regs->psw.cc = 3; #ifdef OPTION_CMPSC_DEBUG logmsg("expand : reached CPU determined amount of data\n"); #endif return; } /* Process last index symbols, never mind about childs written */ while(likely(!ARCH_DEP(fetch_is)(r2, regs, iregs, &ec, &is))) { if(unlikely(!ec.ecl[is])) { ec.ocl = 0; /* Initialize output cache */ ARCH_DEP(expand_is)(regs, &ec, is); if(unlikely(ARCH_DEP(vstore)(r1, regs, iregs, &ec, ec.oc, ec.ocl))) return; } else { if(unlikely(ARCH_DEP(vstore)(r1, regs, iregs, &ec, &ec.ec[ec.eci[is]], ec.ecl[is]))) return; } } /* Commit, including GR1 */ COMMITREGS(regs, iregs, r1, r2); } /*----------------------------------------------------------------------------*/ /* expand_is (index symbol). */ /*----------------------------------------------------------------------------*/ static void ARCH_DEP(expand_is)(REGS *regs, struct ec *ec, U16 is) { int csl; /* Complete symbol length */ unsigned cw; /* Characters written */ U16 index; /* Index within dictionary */ #ifdef FEATURE_INTERVAL_TIMER GREG dictor; /* Dictionary origin */ #endif BYTE *ece; /* Expansion Character Entry */ int psl; /* Partial symbol length */ /* Initialize values */ cw = 0; #ifdef FEATURE_INTERVAL_TIMER dictor = GR1_dictor(regs); #endif /* Get expansion character entry */ index = is * 8; ece = &ec->dict[index / 0x800][index % 0x800]; ITIMER_SYNC(dictor + index, 8 - 1, regs); #ifdef OPTION_CMPSC_DEBUG logmsg("fetch_ece: index %04X\n", is); print_ece(ece); #endif /* Process preceded entries */ psl = ECE_psl(ece); while(likely(psl)) { /* Check data exception */ if(unlikely(psl > 5)) ARCH_DEP(program_interrupt)((regs), PGM_DATA_EXCEPTION); /* Count and check for writing child 261 */ cw += psl; if(unlikely(cw > 260)) ARCH_DEP(program_interrupt)((regs), PGM_DATA_EXCEPTION); /* Process extension characters in preceded entry */ memcpy(&ec->oc[ec->ocl + ECE_ofst(ece)], &ece[2], psl); /* Get preceding entry */ index = ECE_pptr(ece) * 8; ece = &ec->dict[index / 0x800][index % 0x800]; ITIMER_SYNC(dictor + index, 8 - 1, regs); #ifdef OPTION_CMPSC_DEBUG logmsg("fetch_ece: index %04X\n", ECE_pptr(ece)); print_ece(ece); #endif /* Calculate partial symbol length */ psl = ECE_psl(ece); } /* Check data exception */ csl = ECE_csl(ece); if(unlikely(!csl || ECE_bit34(ece))) ARCH_DEP(program_interrupt)((regs), PGM_DATA_EXCEPTION); /* Count and check for writing child 261 */ cw += csl; if(unlikely(cw > 260)) ARCH_DEP(program_interrupt)((regs), PGM_DATA_EXCEPTION); /* Process extension characters in unpreceded entry */ memcpy(&ec->oc[ec->ocl], &ece[1], csl); /* Place within cache */ if(likely(ec->ecwm + cw <= ECACHE_SIZE)) { memcpy(&ec->ec[ec->ecwm], &ec->oc[ec->ocl], cw); ec->eci[is] = ec->ecwm; ec->ecl[is] = cw; ec->ecwm += cw; } /* Commit in output buffer */ ec->ocl += cw; } /*----------------------------------------------------------------------------*/ /* fetch_is (index symbol) */ /*----------------------------------------------------------------------------*/ static int ARCH_DEP(fetch_is)(int r2, REGS *regs, REGS *iregs, struct ec *ec, U16 *is) { unsigned cbn; /* Compressed-data bit number */ U32 mask; BYTE work[3]; /* Initialize values */ cbn = GR1_cbn(iregs); /* Check if we can read an index symbol */ if(unlikely(GR_A(r2 + 1, iregs) < 2)) { if(unlikely(((cbn + ec->smbsz - 1) / 8) >= GR_A(r2 + 1, iregs))) { #ifdef OPTION_CMPSC_DEBUG logmsg("fetch_is : reached end of source\n"); #endif regs->psw.cc = 0; return(-1); } } /* Clear possible fetched 3rd byte */ work[2] = 0; ARCH_DEP(vfetchc)(&work, (ec->smbsz + cbn - 1) / 8, GR_A(r2, iregs) & ADDRESS_MAXWRAP(regs), r2, regs); /* Get the bits */ mask = work[0] << 16 | work[1] << 8 | work[2]; mask >>= (24 - ec->smbsz - cbn); mask &= 0xFFFF >> (16 - ec->smbsz); *is = mask; /* Adjust source registers */ ADJUSTREGS(r2, regs, iregs, (cbn + ec->smbsz) / 8); /* Calculate and set the new compressed-data bit number */ GR1_setcbn(iregs, (cbn + ec->smbsz) % 8); #ifdef OPTION_CMPSC_DEBUG logmsg("fetch_is : %04X, cbn=%d, GR%02d=" F_VADR ", GR%02d=" F_GREG "\n", *is, GR1_cbn(iregs), r2, iregs->GR(r2), r2 + 1, iregs->GR(r2 + 1)); #endif return(0); } /*----------------------------------------------------------------------------*/ /* fetch_iss */ /*----------------------------------------------------------------------------*/ static void ARCH_DEP(fetch_iss)(int r2, REGS *regs, REGS *iregs, struct ec *ec, U16 is[8]) { BYTE buf[13]; /* Buffer for 8 index symbols */ unsigned len1; /* Lenght in first page */ BYTE *mem; /* Pointer to maddr or buf */ unsigned ofst; /* Offset in first page */ /* Fingers crossed that we stay within one page */ ofst = GR_A(r2, iregs) & 0x7ff; if(unlikely(!ec->src)) ec->src = MADDR((GR_A(r2, iregs) & ~0x7ff) & ADDRESS_MAXWRAP(regs), r2, regs, ACCTYPE_READ, regs->psw.pkey); if(likely(ofst + ec->smbsz < 0x800)) { ITIMER_SYNC(GR_A(r2, iregs), ec->smbsz - 1, regs); mem = &ec->src[ofst]; } else { /* We need data spread over 2 pages */ len1 = 0x800 - ofst; memcpy(buf, &ec->src[ofst], len1); ec->src = MADDR((GR_A(r2, iregs) + len1) & ADDRESS_MAXWRAP(regs), r2, regs, ACCTYPE_READ, regs->psw.pkey); memcpy(&buf[len1], ec->src, ec->smbsz - len1 + 1); mem = buf; } /* Calculate the 8 index symbols */ switch(ec->smbsz) { case 9: /* 9-bits */ { /* 0 1 2 3 4 5 6 7 8 */ /* 012345670 123456701 234567012 345670123 456701234 567012345 670123456 701234567 */ /* 012345678 012345678 012345678 012345678 012345678 012345678 012345678 012345678 */ /* 0 1 2 3 4 5 6 7 */ is[0] = ((mem[0] << 1) | (mem[1] >> 7)); is[1] = ((mem[1] << 2) | (mem[2] >> 6)) & 0x01ff; is[2] = ((mem[2] << 3) | (mem[3] >> 5)) & 0x01ff; is[3] = ((mem[3] << 4) | (mem[4] >> 4)) & 0x01ff; is[4] = ((mem[4] << 5) | (mem[5] >> 3)) & 0x01ff; is[5] = ((mem[5] << 6) | (mem[6] >> 2)) & 0x01ff; is[6] = ((mem[6] << 7) | (mem[7] >> 1)) & 0x01ff; is[7] = ((mem[7] << 8) | (mem[8] )) & 0x01ff; break; } case 10: /* 10-bits */ { /* 0 1 2 3 4 5 6 7 8 9 */ /* 0123456701 2345670123 4567012345 6701234567 0123456701 2345670123 4567012345 6701234567 */ /* 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 */ /* 0 1 2 3 4 5 6 7 */ is[0] = ((mem[0] << 2) | (mem[1] >> 6)); is[1] = ((mem[1] << 4) | (mem[2] >> 4)) & 0x03ff; is[2] = ((mem[2] << 6) | (mem[3] >> 2)) & 0x03ff; is[3] = ((mem[3] << 8) | (mem[4] )) & 0x03ff; is[4] = ((mem[5] << 2) | (mem[6] >> 6)); is[5] = ((mem[6] << 4) | (mem[7] >> 4)) & 0x03ff; is[6] = ((mem[7] << 6) | (mem[8] >> 2)) & 0x03ff; is[7] = ((mem[8] << 8) | (mem[9] )) & 0x03ff; break; } case 11: /* 11-bits */ { /* 0 1 2 3 4 5 6 7 8 9 a */ /* 01234567012 34567012345 67012345670 12345670123 45670123456 70123456701 23456701234 56701234567 */ /* 0123456789a 0123456789a 0123456789a 0123456789a 0123456789a 0123456789a 0123456789a 0123456789a */ /* 0 1 2 3 4 5 6 7 */ is[0] = ((mem[0] << 3) | (mem[ 1] >> 5) ); is[1] = ((mem[1] << 6) | (mem[ 2] >> 2) ) & 0x07ff; is[2] = ((mem[2] << 9) | (mem[ 3] << 1) | (mem[4] >> 7)) & 0x07ff; is[3] = ((mem[4] << 4) | (mem[ 5] >> 4) ) & 0x07ff; is[4] = ((mem[5] << 7) | (mem[ 6] >> 1) ) & 0x07ff; is[5] = ((mem[6] << 10) | (mem[ 7] << 2) | (mem[8] >> 6)) & 0x07ff; is[6] = ((mem[8] << 5) | (mem[ 9] >> 3) ) & 0x07ff; is[7] = ((mem[9] << 8) | (mem[10] ) ) & 0x07ff; break; } case 12: /* 12-bits */ { /* 0 1 2 3 4 5 6 7 8 9 a b */ /* 012345670123 456701234567 012345670123 456701234567 012345670123 456701234567 012345670123 456701234567 */ /* 0123456789ab 0123456789ab 0123456789ab 0123456789ab 0123456789ab 0123456789ab 0123456789ab 0123456789ab */ /* 0 1 2 3 4 5 6 7 */ is[0] = ((mem[ 0] << 4) | (mem[ 1] >> 4)); is[1] = ((mem[ 1] << 8) | (mem[ 2] )) & 0x0fff; is[2] = ((mem[ 3] << 4) | (mem[ 4] >> 4)); is[3] = ((mem[ 4] << 8) | (mem[ 5] )) & 0x0fff; is[4] = ((mem[ 6] << 4) | (mem[ 7] >> 4)); is[5] = ((mem[ 7] << 8) | (mem[ 8] )) & 0x0fff; is[6] = ((mem[ 9] << 4) | (mem[10] >> 4)); is[7] = ((mem[10] << 8) | (mem[11] )) & 0x0fff; break; } case 13: /* 13-bits */ { /* 0 1 2 3 4 5 6 7 8 9 a b c */ /* 0123456701234 5670123456701 2345670123456 7012345670123 4567012345670 1234567012345 6701234567012 3456701234567 */ /* 0123456789abc 0123456789abc 0123456789abc 0123456789abc 0123456789abc 0123456789abc 0123456789abc 0123456789abc */ /* 0 1 2 3 4 5 6 7 */ is[0] = ((mem[ 0] << 5) | (mem[ 1] >> 3) ); is[1] = ((mem[ 1] << 10) | (mem[ 2] << 2) | (mem[ 3] >> 6)) & 0x1fff; is[2] = ((mem[ 3] << 7) | (mem[ 4] >> 1) ) & 0x1fff; is[3] = ((mem[ 4] << 12) | (mem[ 5] << 4) | (mem[ 6] >> 4)) & 0x1fff; is[4] = ((mem[ 6] << 9) | (mem[ 7] << 1) | (mem[ 8] >> 7)) & 0x1fff; is[5] = ((mem[ 8] << 6) | (mem[ 9] >> 2) ) & 0x1fff; is[6] = ((mem[ 9] << 11) | (mem[10] << 3) | (mem[11] >> 5)) & 0x1fff; is[7] = ((mem[11] << 8) | (mem[12] ) ) & 0x1fff; break; } } /* Adjust source registers */ ADJUSTREGS(r2, regs, iregs, ec->smbsz); #ifdef OPTION_CMPSC_DEBUG logmsg("fetch_iss: GR%02d=" F_VADR ", GR%02d=" F_GREG "\n", r2, iregs->GR(r2), r2 + 1, iregs->GR(r2 + 1)); #endif } #ifndef NO_2ND_COMPILE #ifdef OPTION_CMPSC_DEBUG /*----------------------------------------------------------------------------*/ /* print_ece (expansion character entry). */ /*----------------------------------------------------------------------------*/ static void print_ece(BYTE *ece) { int i; int prt_detail; logmsg(" ece : "); prt_detail = 0; for(i = 0; i < 8; i++) { if(!prt_detail && ece[i]) prt_detail = 1; logmsg("%02X", ece[i]); } logmsg("\n"); if(prt_detail) { if(ECE_psl(ece)) { logmsg(" psl : %d\n", ECE_psl(ece)); logmsg(" pptr : %04X\n", ECE_pptr(ece)); logmsg(" ecs :"); for(i = 0; i < ECE_psl(ece); i++) logmsg(" %02X", ece[i + 2]); logmsg("\n"); logmsg(" ofst : %02X\n", ECE_ofst(ece)); } else { logmsg(" psl : %d\n", ECE_psl(ece)); logmsg(" bit34 : %s\n", TRUEFALSE(ECE_bit34(ece))); logmsg(" csl : %d\n", ECE_csl(ece)); logmsg(" ecs :"); for(i = 0; i < ECE_csl(ece); i++) logmsg(" %02X", ece[i + 1]); logmsg("\n"); } } } #endif #endif /* #ifndef NO_2ND_COMPILE */ /*----------------------------------------------------------------------------*/ /* vstore */ /*----------------------------------------------------------------------------*/ static int ARCH_DEP(vstore)(int r1, REGS *regs, REGS *iregs, struct ec *ec, BYTE *buf, unsigned len) { unsigned len1; /* Length in first page */ unsigned len2; /* Length in second page */ BYTE *main1; /* Address first page */ unsigned ofst; /* Offset within page */ BYTE *sk; /* Storage key */ /* Check destination size */ if(unlikely(GR_A(r1 + 1, iregs) < len)) { #ifdef OPTION_CMPSC_DEBUG logmsg("vstore : Reached end of destination\n"); #endif /* Indicate end of destination */ regs->psw.cc = 1; return(-1); } #ifdef OPTION_CMPSC_DEBUG unsigned i; unsigned j; static BYTE pbuf[2060]; static unsigned plen = 2061; /* Impossible value */ if(plen == len && !memcmp(pbuf, buf, plen)) logmsg(F_GREG " - " F_GREG " Same buffer as previously shown\n", iregs->GR(r1), iregs->GR(r1) + len - 1); else { for(i = 0; i < len; i += 32) { logmsg(F_GREG, iregs->GR(r1) + i); if(i && i + 32 < len && !memcmp(&buf[i], &buf[i - 32], 32)) { for(j = i + 32; j + 32 < len && !memcmp(&buf[j], &buf[j - 32], 32); j += 32); if(j > 32) { logmsg(" - " F_GREG " Same line as above\n" F_GREG, iregs->GR(r1) + j - 32, iregs->GR(r1) + j); i = j; } } logmsg(": "); for(j = 0; j < 32; j++) { if(!(j % 8)) logmsg(" "); if(i + j >= len) logmsg(" "); else logmsg("%02X", buf[i + j]); } logmsg(" | "); for(j = 0; j < 32; j++) { if(i + j >= len) logmsg(" "); else { if(isprint(guest_to_host(buf[i + j]))) logmsg("%c", guest_to_host(buf[i + j])); else logmsg("."); } } logmsg(" |\n"); } memcpy(pbuf, buf, len); plen = len; } #endif /* Fingers crossed that we stay within one page */ ofst = GR_A(r1, iregs) & 0x7ff; if(likely(ofst + len < 0x800)) { if(unlikely(!ec->dest)) ec->dest = MADDR((GR_A(r1, iregs) & ~0x7ff) & ADDRESS_MAXWRAP(regs), r1, regs, ACCTYPE_WRITE, regs->psw.pkey); memcpy(&ec->dest[ofst], buf, len); ITIMER_UPDATE(GR_A(r1, iregs), len - 1, regs); } else { /* We need multiple pages */ if(unlikely(!ec->dest)) main1 = MADDR((GR_A(r1, iregs) & ~0x7ff) & ADDRESS_MAXWRAP(regs), r1, regs, ACCTYPE_WRITE_SKP, regs->psw.pkey); else main1 = ec->dest; sk = regs->dat.storkey; len1 = 0x800 - ofst; ec->dest = MADDR((GR_A(r1, iregs) + len1) & ADDRESS_MAXWRAP(regs), r1, regs, ACCTYPE_WRITE, regs->psw.pkey); memcpy(&main1[ofst], buf, len1); len2 = len - len1 + 1; while(len2) { memcpy(ec->dest, &buf[len1], (len2 > 0x800 ? 0x800 : len2)); *sk |= (STORKEY_REF | STORKEY_CHANGE); if(unlikely(len2 > 0x800)) { len1 += 0x800; len2 -= 0x800; ec->dest = MADDR((GR_A(r1, iregs) + len1) & ADDRESS_MAXWRAP(regs), r1, regs, ACCTYPE_WRITE, regs->psw.pkey); sk = regs->dat.storkey; } else len2 = 0; } } ADJUSTREGS(r1, regs, iregs, len); return(0); } #define NO_2ND_COMPILE #endif /* FEATURE_COMPRESSION */ #if !defined(_GEN_ARCH) #if defined(_ARCHMODE2) #define _GEN_ARCH _ARCHMODE2 #include "cmpsc.c" #endif #if defined(_ARCHMODE3) #undef _GEN_ARCH #define _GEN_ARCH _ARCHMODE3 #include "cmpsc.c" #endif #endif /*!defined(_GEN_ARCH) */ hercules-3.07/codepage.c000644 000765 000765 00000161203 11143760543 016665 0ustar00jmaynardjmaynard000000 000000 /* CODEPAGE.C (c) Copyright Jan Jaeger, 1999-2009 */ /* Code Page conversion */ // $Id: codepage.c 5125 2009-01-23 12:01:44Z bernard $ // // $Log$ // Revision 1.25 2008/01/14 17:25:16 rbowler // Additional ISO-8859-1 to European EBCDIC codepages // // Revision 1.24 2007/06/23 00:04:04 ivan // Update copyright notices to include current year (2007) // // Revision 1.23 2006/12/08 09:43:18 jj // Add CVS message log // #include "hstdinc.h" #define _CODEPAGE_C_ #define _HUTIL_DLL_ #include "hercules.h" static unsigned char ascii_to_ebcdic[] = { "\x00\x01\x02\x03\x37\x2D\x2E\x2F\x16\x05\x25\x0B\x0C\x0D\x0E\x0F" "\x10\x11\x12\x13\x3C\x3D\x32\x26\x18\x19\x1A\x27\x22\x1D\x35\x1F" "\x40\x5A\x7F\x7B\x5B\x6C\x50\x7D\x4D\x5D\x5C\x4E\x6B\x60\x4B\x61" "\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\x7A\x5E\x4C\x7E\x6E\x6F" "\x7C\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xD1\xD2\xD3\xD4\xD5\xD6" "\xD7\xD8\xD9\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xAD\xE0\xBD\x5F\x6D" "\x79\x81\x82\x83\x84\x85\x86\x87\x88\x89\x91\x92\x93\x94\x95\x96" "\x97\x98\x99\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xC0\x6A\xD0\xA1\x07" "\x68\xDC\x51\x42\x43\x44\x47\x48\x52\x53\x54\x57\x56\x58\x63\x67" "\x71\x9C\x9E\xCB\xCC\xCD\xDB\xDD\xDF\xEC\xFC\xB0\xB1\xB2\xB3\xB4" "\x45\x55\xCE\xDE\x49\x69\x04\x06\xAB\x08\xBA\xB8\xB7\xAA\x8A\x8B" "\x09\x0A\x14\xBB\x15\xB5\xB6\x17\x1B\xB9\x1C\x1E\xBC\x20\xBE\xBF" "\x21\x23\x24\x28\x29\x2A\x2B\x2C\x30\x31\xCA\x33\x34\x36\x38\xCF" "\x39\x3A\x3B\x3E\x41\x46\x4A\x4F\x59\x62\xDA\x64\x65\x66\x70\x72" "\x73\xE1\x74\x75\x76\x77\x78\x80\x8C\x8D\x8E\xEB\x8F\xED\xEE\xEF" "\x90\x9A\x9B\x9D\x9F\xA0\xAC\xAE\xAF\xFD\xFE\xFB\x3F\xEA\xFA\xFF" }; static unsigned char ebcdic_to_ascii[] = { "\x00\x01\x02\x03\xA6\x09\xA7\x7F\xA9\xB0\xB1\x0B\x0C\x0D\x0E\x0F" "\x10\x11\x12\x13\xB2\x0A\x08\xB7\x18\x19\x1A\xB8\xBA\x1D\xBB\x1F" "\xBD\xC0\x1C\xC1\xC2\x0A\x17\x1B\xC3\xC4\xC5\xC6\xC7\x05\x06\x07" "\xC8\xC9\x16\xCB\xCC\x1E\xCD\x04\xCE\xD0\xD1\xD2\x14\x15\xD3\xFC" "\x20\xD4\x83\x84\x85\xA0\xD5\x86\x87\xA4\xD6\x2E\x3C\x28\x2B\xD7" "\x26\x82\x88\x89\x8A\xA1\x8C\x8B\x8D\xD8\x21\x24\x2A\x29\x3B\x5E" "\x2D\x2F\xD9\x8E\xDB\xDC\xDD\x8F\x80\xA5\x7C\x2C\x25\x5F\x3E\x3F" "\xDE\x90\xDF\xE0\xE2\xE3\xE4\xE5\xE6\x60\x3A\x23\x40\x27\x3D\x22" "\xE7\x61\x62\x63\x64\x65\x66\x67\x68\x69\xAE\xAF\xE8\xE9\xEA\xEC" "\xF0\x6A\x6B\x6C\x6D\x6E\x6F\x70\x71\x72\xF1\xF2\x91\xF3\x92\xF4" "\xF5\x7E\x73\x74\x75\x76\x77\x78\x79\x7A\xAD\xA8\xF6\x5B\xF7\xF8" "\x9B\x9C\x9D\x9E\x9F\xB5\xB6\xAC\xAB\xB9\xAA\xB3\xBC\x5D\xBE\xBF" "\x7B\x41\x42\x43\x44\x45\x46\x47\x48\x49\xCA\x93\x94\x95\xA2\xCF" "\x7D\x4A\x4B\x4C\x4D\x4E\x4F\x50\x51\x52\xDA\x96\x81\x97\xA3\x98" "\x5C\xE1\x53\x54\x55\x56\x57\x58\x59\x5A\xFD\xEB\x99\xED\xEE\xEF" "\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\xFE\xFB\x9A\xF9\xFA\xFF" }; static unsigned char cp_437_to_037[] = { "\x00\x01\x02\x03\x37\x2D\x2E\x2F\x16\x05\x15\x0B\x0C\x0D\x0E\x0F" "\x10\x11\x12\x13\x3C\x3D\x32\x26\x18\x19\x3F\x27\x22\x1D\x1E\x1F" "\x40\x5A\x7F\x7B\x5B\x6C\x50\x7D\x4D\x5D\x5C\x4E\x6B\x60\x4B\x61" "\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\x7A\x5E\x4C\x7E\x6E\x6F" "\x7C\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xD1\xD2\xD3\xD4\xD5\xD6" "\xD7\xD8\xD9\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xBA\xE0\xBB\xB0\x6D" "\x79\x81\x82\x83\x84\x85\x86\x87\x88\x89\x91\x92\x93\x94\x95\x96" "\x97\x98\x99\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xC0\x4F\xD0\xA1\x07" "\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F" "\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F" "\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F" "\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F" "\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F" "\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F" "\x3F\x59\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F" "\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x90\x3F\x3F\x3F\x3F\xEA\x3F\xFF" }; static unsigned char cp_037_to_437[] = { "\x00\x01\x02\x03\x07\x09\x07\x7F\x07\x07\x07\x0B\x0C\x0D\x0E\x0F" "\x10\x11\x12\x13\x07\x0A\x08\x07\x18\x19\x07\x07\x07\x07\x07\x07" "\x07\x07\x1C\x07\x07\x0A\x17\x1B\x07\x07\x07\x07\x07\x05\x06\x07" "\x07\x07\x16\x07\x07\x07\x07\x04\x07\x07\x07\x07\x14\x15\x07\x1A" "\x20\xFF\x83\x84\x85\xA0\x07\x86\x87\xA4\x9B\x2E\x3C\x28\x2B\x7C" "\x26\x82\x88\x89\x8A\xA1\x8C\x07\x8D\xE1\x21\x24\x2A\x29\x3B\xAA" "\x2D\x2F\x07\x8E\x07\x07\x07\x8F\x80\xA5\x07\x2C\x25\x5F\x3E\x3F" "\x07\x90\x07\x07\x07\x07\x07\x07\x70\x60\x3A\x23\x40\x27\x3D\x22" "\x07\x61\x62\x63\x64\x65\x66\x67\x68\x69\xAE\xAF\x07\x07\x07\xF1" "\xF8\x6A\x6B\x6C\x6D\x6E\x6F\x70\x71\x72\xA6\xA7\x91\x07\x92\x07" "\xE6\x7E\x73\x74\x75\x76\x77\x78\x79\x7A\xAD\xAB\x07\x07\x07\x07" "\x5E\x9C\x9D\xFA\x07\x07\x07\xAC\xAB\x07\x5B\x5D\x07\x07\x07\x07" "\x7B\x41\x42\x43\x44\x45\x46\x47\x48\x49\x07\x93\x94\x95\xA2\x07" "\x7D\x4A\x4B\x4C\x4D\x4E\x4F\x50\x51\x52\x07\x96\x81\x97\xA3\x98" "\x5C\xF6\x53\x54\x55\x56\x57\x58\x59\x5A\xFD\x07\x99\x07\x07\x07" "\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x07\x07\x9A\x07\x07\x07" }; static unsigned char cp_437_to_500[] = { "\x00\x01\x02\x03\x37\x2D\x2E\x2F\x16\x05\x15\x0B\x0C\x0D\x0E\x0F" "\x10\x11\x12\x13\x3C\x3D\x32\x26\x18\x19\x3F\x27\x22\x1D\x1E\x1F" "\x40\x4F\x7F\x7B\x5B\x6C\x50\x7D\x4D\x5D\x5C\x4E\x6B\x60\x4B\x61" "\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\x7A\x5E\x4C\x7E\x6E\x6F" "\x7C\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xD1\xD2\xD3\xD4\xD5\xD6" "\xD7\xD8\xD9\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\x4A\xE0\x5A\x5F\x6D" "\x79\x81\x82\x83\x84\x85\x86\x87\x88\x89\x91\x92\x93\x94\x95\x96" "\x97\x98\x99\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xC0\xBB\xD0\xA1\x07" "\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F" "\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F" "\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F" "\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F" "\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F" "\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F" "\x3F\x59\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F" "\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x90\x3F\x3F\x3F\x3F\xEA\x3F\xFF" }; static unsigned char cp_500_to_437[] = { "\x00\x01\x02\x03\x07\x09\x07\x7F\x07\x07\x07\x0B\x0C\x0D\x0E\x0F" "\x10\x11\x12\x13\x07\x0A\x08\x07\x18\x19\x07\x07\x07\x07\x07\x07" "\x07\x07\x1C\x07\x07\x0A\x17\x1B\x07\x07\x07\x07\x07\x05\x06\x07" "\x07\x07\x16\x07\x07\x07\x07\x04\x07\x07\x07\x07\x14\x15\x07\x1A" "\x20\xFF\x83\x84\x85\xA0\x07\x86\x87\xA4\x5B\x2E\x3C\x28\x2B\x21" "\x26\x82\x88\x89\x8A\xA1\x8C\x07\x8D\xE1\x5D\x24\x2A\x29\x3B\x5E" "\x2D\x2F\x07\x8E\x07\x07\x07\x8F\x80\xA5\x07\x2C\x25\x5F\x3E\x3F" "\x07\x90\x07\x07\x07\x07\x07\x07\x70\x60\x3A\x23\x40\x27\x3D\x22" "\x07\x61\x62\x63\x64\x65\x66\x67\x68\x69\xAE\xAF\x07\x07\x07\xF1" "\xF8\x6A\x6B\x6C\x6D\x6E\x6F\x70\x71\x72\xA6\xA7\x91\x07\x92\x07" "\xE6\x7E\x73\x74\x75\x76\x77\x78\x79\x7A\xAD\xAB\x07\x07\x07\x07" "\x9B\x9C\x9D\xFA\x07\x07\x07\xAC\xAB\x07\xAA\x7C\x07\x07\x07\x07" "\x7B\x41\x42\x43\x44\x45\x46\x47\x48\x49\x07\x93\x94\x95\xA2\x07" "\x7D\x4A\x4B\x4C\x4D\x4E\x4F\x50\x51\x52\x07\x96\x81\x97\xA3\x98" "\x5C\xF6\x53\x54\x55\x56\x57\x58\x59\x5A\xFD\x07\x99\x07\x07\x07" "\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x07\x07\x9A\x07\x07\x07" }; static unsigned char cp_850_to_273[] = { "\x00\x01\x02\x03\x37\x2D\x2E\x2F\x16\x05\x25\x0B\x0C\x0D\x0E\x0F" "\x10\x11\x12\x13\x3C\x3D\x32\x26\x18\x19\x3F\x27\x1C\x1D\x1E\x1F" "\x40\x4F\x7F\x7B\x5B\x6C\x50\x7D\x4D\x5D\x5C\x4E\x6B\x60\x4B\x61" "\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\x7A\x5E\x4C\x7E\x6E\x6F" "\xB5\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xD1\xD2\xD3\xD4\xD5\xD6" "\xD7\xD8\xD9\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\x63\xEC\xFC\x5F\x6D" "\x79\x81\x82\x83\x84\x85\x86\x87\x88\x89\x91\x92\x93\x94\x95\x96" "\x97\x98\x99\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\x43\xBB\xDC\x59\x07" "\x68\xD0\x51\x42\xC0\x44\x47\x48\x52\x53\x54\x57\x56\x58\x4A\x67" "\x71\x9C\x9E\xCB\x6A\xCD\xDB\xDD\xDF\xE0\x5A\x70\xB1\x80\xBF\xFF" "\x45\x55\xCE\xDE\x49\x69\x9A\x9B\xAB\xAF\xBA\xB8\xB7\xAA\x8A\x8B" "\x2B\x2C\x09\x21\x28\x65\x62\x64\xB4\x38\x31\x34\x33\xB0\xB2\x24" "\x22\x17\x29\x06\x20\x2A\x46\x66\x1A\x35\x08\x39\x36\x30\x3A\x9F" "\x8C\xAC\x72\x73\x74\x0A\x75\x76\x77\x23\x15\x14\x04\xCC\x78\x3B" "\xEE\xA1\xEB\xED\xCF\xEF\xA0\x8E\xAE\xFE\xFB\xFD\x8D\xAD\xBC\xBE" "\xCA\x8F\x1B\xB9\xB6\x7C\xE1\x9D\x90\xBD\xB3\xDA\xFA\xEA\x3E\x41" }; static unsigned char cp_273_to_850[] = { "\x00\x01\x02\x03\xDC\x09\xC3\x7F\xCA\xB2\xD5\x0B\x0C\x0D\x0E\x0F" "\x10\x11\x12\x13\xDB\xDA\x08\xC1\x18\x19\xC8\xF2\x1C\x1D\x1E\x1F" "\xC4\xB3\xC0\xD9\xBF\x0A\x17\x1B\xB4\xC2\xC5\xB0\xB1\x05\x06\x07" "\xCD\xBA\x16\xBC\xBB\xC9\xCC\x04\xB9\xCB\xCE\xDF\x14\x15\xFE\x1A" "\x20\xFF\x83\x7B\x85\xA0\xC6\x86\x87\xA4\x8E\x2E\x3C\x28\x2B\x21" "\x26\x82\x88\x89\x8A\xA1\x8C\x8B\x8D\x7E\x9A\x24\x2A\x29\x3B\x5E" "\x2D\x2F\xB6\x5B\xB7\xB5\xC7\x8F\x80\xA5\x94\x2C\x25\x5F\x3E\x3F" "\x9B\x90\xD2\xD3\xD4\xD6\xD7\xD8\xDE\x60\x3A\x23\xF5\x27\x3D\x22" "\x9D\x61\x62\x63\x64\x65\x66\x67\x68\x69\xAE\xAF\xD0\xEC\xE7\xF1" "\xF8\x6A\x6B\x6C\x6D\x6E\x6F\x70\x71\x72\xA6\xA7\x91\xF7\x92\xCF" "\xE6\xE1\x73\x74\x75\x76\x77\x78\x79\x7A\xAD\xA8\xD1\xED\xE8\xA9" "\xBD\x9C\xBE\xFA\xB8\x40\xF4\xAC\xAB\xF3\xAA\x7C\xEE\xF9\xEF\x9E" "\x84\x41\x42\x43\x44\x45\x46\x47\x48\x49\xF0\x93\xDD\x95\xA2\xE4" "\x81\x4A\x4B\x4C\x4D\x4E\x4F\x50\x51\x52\xFB\x96\x7D\x97\xA3\x98" "\x99\xF6\x53\x54\x55\x56\x57\x58\x59\x5A\xFD\xE2\x5C\xE3\xE0\xE5" "\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\xFC\xEA\x5D\xEB\xE9\x9F" }; /* 819 (ISO-8859-1 Latin-1) to 273 (EBCDIC CECP Germany) */ static unsigned char cp_819_to_273[] = { /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ /* 0x */ "\x00\x01\x02\x03\x37\x2D\x2E\x2F\x16\x05\x15\x0B\x0C\x0D\x0E\x0F" /* 1x */ "\x10\x11\x12\x13\x3C\x3D\x32\x26\x18\x19\x3F\x27\x1C\x1D\x1E\x1F" /* 2x */ "\x40\x4F\x7F\x7B\x5B\x6C\x50\x7D\x4D\x5D\x5C\x4E\x6B\x60\x4B\x61" /* 3x */ "\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\x7A\x5E\x4C\x7E\x6E\x6F" /* 4x */ "\xB5\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xD1\xD2\xD3\xD4\xD5\xD6" /* 5x */ "\xD7\xD8\xD9\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\x63\xEC\xFC\x5F\x6D" /* 6x */ "\x79\x81\x82\x83\x84\x85\x86\x87\x88\x89\x91\x92\x93\x94\x95\x96" /* 7x */ "\x97\x98\x99\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\x43\xBB\xDC\x59\x07" /* 8x */ "\x04\x06\x08\x09\x0A\x14\x17\x1A\x1B\x20\x21\x22\x23\x24\x25\x28" /* 9x */ "\x29\x2A\x2B\x2C\x30\x31\x33\x34\x35\x36\x38\x39\x3A\x3B\x3E\xFF" /* Ax */ "\x41\xAA\xB0\xB1\x9F\xB2\xCC\x7C\xBD\xB4\x9A\x8A\xBA\xCA\xAF\xBC" /* Bx */ "\x90\x8F\xEA\xFA\xBE\xA0\xB6\xB3\x9D\xDA\x9B\x8B\xB7\xB8\xB9\xAB" /* Cx */ "\x64\x65\x62\x66\x4A\x67\x9E\x68\x74\x71\x72\x73\x78\x75\x76\x77" /* Dx */ "\xAC\x69\xED\xEE\xEB\xEF\xE0\xBF\x80\xFD\xFE\xFB\x5A\xAD\xAE\xA1" /* Ex */ "\x44\x45\x42\x46\xC0\x47\x9C\x48\x54\x51\x52\x53\x58\x55\x56\x57" /* Fx */ "\x8C\x49\xCD\xCE\xCB\xCF\x6A\xE1\x70\xDD\xDE\xDB\xD0\x8D\x8E\xDF" }; /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ static unsigned char cp_273_to_819[] = { /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ /* 0x */ "\x00\x01\x02\x03\x80\x09\x81\x7F\x82\x83\x84\x0B\x0C\x0D\x0E\x0F" /* 1x */ "\x10\x11\x12\x13\x85\x0A\x08\x86\x18\x19\x87\x88\x1C\x1D\x1E\x1F" /* 2x */ "\x89\x8A\x8B\x8C\x8D\x8E\x17\x1B\x8F\x90\x91\x92\x93\x05\x06\x07" /* 3x */ "\x94\x95\x16\x96\x97\x98\x99\x04\x9A\x9B\x9C\x9D\x14\x15\x9E\x1A" /* 4x */ "\x20\xA0\xE2\x7B\xE0\xE1\xE3\xE5\xE7\xF1\xC4\x2E\x3C\x28\x2B\x21" /* 5x */ "\x26\xE9\xEA\xEB\xE8\xED\xEE\xEF\xEC\x7E\xDC\x24\x2A\x29\x3B\x5E" /* 6x */ "\x2D\x2F\xC2\x5B\xC0\xC1\xC3\xC5\xC7\xD1\xF6\x2C\x25\x5F\x3E\x3F" /* 7x */ "\xF8\xC9\xCA\xCB\xC8\xCD\xCE\xCF\xCC\x60\x3A\x23\xA7\x27\x3D\x22" /* 8x */ "\xD8\x61\x62\x63\x64\x65\x66\x67\x68\x69\xAB\xBB\xF0\xFD\xFE\xB1" /* 9x */ "\xB0\x6A\x6B\x6C\x6D\x6E\x6F\x70\x71\x72\xAA\xBA\xE6\xB8\xC6\xA4" /* Ax */ "\xB5\xDF\x73\x74\x75\x76\x77\x78\x79\x7A\xA1\xBF\xD0\xDD\xDE\xAE" /* Bx */ "\xA2\xA3\xA5\xB7\xA9\x40\xB6\xBC\xBD\xBE\xAC\x7C\xAF\xA8\xB4\xD7" /* Cx */ "\xE4\x41\x42\x43\x44\x45\x46\x47\x48\x49\xAD\xF4\xA6\xF2\xF3\xF5" /* Dx */ "\xFC\x4A\x4B\x4C\x4D\x4E\x4F\x50\x51\x52\xB9\xFB\x7D\xF9\xFA\xFF" /* Ex */ "\xD6\xF7\x53\x54\x55\x56\x57\x58\x59\x5A\xB2\xD4\x5C\xD2\xD3\xD5" /* Fx */ "\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\xB3\xDB\x5D\xD9\xDA\x9F" }; /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ /* 819 (ISO-8859-1 Latin-1) to 277 (EBCDIC CECP Denmark, Norway) */ static unsigned char cp_819_to_277[] = { /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ /* 0x */ "\x00\x01\x02\x03\x37\x2D\x2E\x2F\x16\x05\x25\x0B\x0C\x0D\x0E\x0F" /* 1x */ "\x10\x11\x12\x13\x3C\x3D\x32\x26\x18\x19\x3F\x27\x1C\x1D\x1E\x1F" /* 2x */ "\x40\x4F\x7F\x4A\x67\x6C\x50\x7D\x4D\x5D\x5C\x4E\x6B\x60\x4B\x61" /* 3x */ "\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\x7A\x5E\x4C\x7E\x6E\x6F" /* 4x */ "\x80\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xD1\xD2\xD3\xD4\xD5\xD6" /* 5x */ "\xD7\xD8\xD9\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\x9E\xE0\x9F\x5F\x6D" /* 6x */ "\x79\x81\x82\x83\x84\x85\x86\x87\x88\x89\x91\x92\x93\x94\x95\x96" /* 7x */ "\x97\x98\x99\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\x9C\xBB\x47\xDC\x07" /* 8x */ "\x20\x21\x22\x23\x24\x15\x06\x17\x28\x29\x2A\x2B\x2C\x09\x0A\x1B" /* 9x */ "\x30\x31\x1A\x33\x34\x35\x36\x08\x38\x39\x3A\x3B\x04\x14\x3E\xFF" /* Ax */ "\x41\xAA\xB0\xB1\x5A\xB2\x70\xB5\xBD\xB4\x9A\x8A\xBA\xCA\xAF\xBC" /* Bx */ "\x90\x8F\xEA\xFA\xBE\xA0\xB6\xB3\x9D\xDA\x9B\x8B\xB7\xB8\xB9\xAB" /* Cx */ "\x64\x65\x62\x66\x63\x5B\x7B\x68\x74\x71\x72\x73\x78\x75\x76\x77" /* Dx */ "\xAC\x69\xED\xEE\xEB\xEF\xEC\xBF\x7C\xFD\xFE\xFB\xFC\xAD\xAE\x59" /* Ex */ "\x44\x45\x42\x46\x43\xD0\xC0\x48\x54\x51\x52\x53\x58\x55\x56\x57" /* Fx */ "\x8C\x49\xCD\xCE\xCB\xCF\xCC\xE1\x6A\xDD\xDE\xDB\xA1\x8D\x8E\xDF" }; /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ static unsigned char cp_277_to_819[] = { /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ /* 0x */ "\x00\x01\x02\x03\x9C\x09\x86\x7F\x97\x8D\x8E\x0B\x0C\x0D\x0E\x0F" /* 1x */ "\x10\x11\x12\x13\x9D\x85\x08\x87\x18\x19\x92\x8F\x1C\x1D\x1E\x1F" /* 2x */ "\x80\x81\x82\x83\x84\x0A\x17\x1B\x88\x89\x8A\x8B\x8C\x05\x06\x07" /* 3x */ "\x90\x91\x16\x93\x94\x95\x96\x04\x98\x99\x9A\x9B\x14\x15\x9E\x1A" /* 4x */ "\x20\xA0\xE2\xE4\xE0\xE1\xE3\x7D\xE7\xF1\x23\x2E\x3C\x28\x2B\x21" /* 5x */ "\x26\xE9\xEA\xEB\xE8\xED\xEE\xEF\xEC\xDF\xA4\xC5\x2A\x29\x3B\x5E" /* 6x */ "\x2D\x2F\xC2\xC4\xC0\xC1\xC3\x24\xC7\xD1\xF8\x2C\x25\x5F\x3E\x3F" /* 7x */ "\xA6\xC9\xCA\xCB\xC8\xCD\xCE\xCF\xCC\x60\x3A\xC6\xD8\x27\x3D\x22" /* 8x */ "\x40\x61\x62\x63\x64\x65\x66\x67\x68\x69\xAB\xBB\xF0\xFD\xFE\xB1" /* 9x */ "\xB0\x6A\x6B\x6C\x6D\x6E\x6F\x70\x71\x72\xAA\xBA\x7B\xB8\x5B\x5D" /* Ax */ "\xB5\xFC\x73\x74\x75\x76\x77\x78\x79\x7A\xA1\xBF\xD0\xDD\xDE\xAE" /* Bx */ "\xA2\xA3\xA5\xB7\xA9\xA7\xB6\xBC\xBD\xBE\xAC\x7C\xAF\xA8\xB4\xD7" /* Cx */ "\xE6\x41\x42\x43\x44\x45\x46\x47\x48\x49\xAD\xF4\xF6\xF2\xF3\xF5" /* Dx */ "\xE5\x4A\x4B\x4C\x4D\x4E\x4F\x50\x51\x52\xB9\xFB\x7E\xF9\xFA\xFF" /* Ex */ "\x5C\xF7\x53\x54\x55\x56\x57\x58\x59\x5A\xB2\xD4\xD6\xD2\xD3\xD5" /* Fx */ "\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\xB3\xDB\xDC\xD9\xDA\x9F" }; /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ /* 819 (ISO-8859-1 Latin-1) to 278 (EBCDIC CECP Finland, Sweden) */ static unsigned char cp_819_to_278[] = { /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ /* 0x */ "\x00\x01\x02\x03\x37\x2D\x2E\x2F\x16\x05\x15\x0B\x0C\x0D\x0E\x0F" /* 1x */ "\x10\x11\x12\x13\x3C\x3D\x32\x26\x18\x19\x3F\x27\x1C\x1D\x1E\x1F" /* 2x */ "\x40\x4F\x7F\x63\x67\x6C\x50\x7D\x4D\x5D\x5C\x4E\x6B\x60\x4B\x61" /* 3x */ "\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\x7A\x5E\x4C\x7E\x6E\x6F" /* 4x */ "\xEC\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xD1\xD2\xD3\xD4\xD5\xD6" /* 5x */ "\xD7\xD8\xD9\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xB5\x71\x9F\x5F\x6D" /* 6x */ "\x51\x81\x82\x83\x84\x85\x86\x87\x88\x89\x91\x92\x93\x94\x95\x96" /* 7x */ "\x97\x98\x99\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\x43\xBB\x47\xDC\x07" /* 8x */ "\x04\x06\x08\x09\x0A\x14\x17\x1A\x1B\x20\x21\x22\x23\x24\x25\x28" /* 9x */ "\x29\x2A\x2B\x2C\x30\x31\x33\x34\x35\x36\x38\x39\x3A\x3B\x3E\xFF" /* Ax */ "\x41\xAA\xB0\xB1\x5A\xB2\xCC\x4A\xBD\xB4\x9A\x8A\xBA\xCA\xAF\xBC" /* Bx */ "\x90\x8F\xEA\xFA\xBE\xA0\xB6\xB3\x9D\xDA\x9B\x8B\xB7\xB8\xB9\xAB" /* Cx */ "\x64\x65\x62\x66\x7B\x5B\x9E\x68\x74\xE0\x72\x73\x78\x75\x76\x77" /* Dx */ "\xAC\x69\xED\xEE\xEB\xEF\x7C\xBF\x80\xFD\xFE\xFB\xFC\xAD\xAE\x59" /* Ex */ "\x44\x45\x42\x46\xC0\xD0\x9C\x48\x54\x79\x52\x53\x58\x55\x56\x57" /* Fx */ "\x8C\x49\xCD\xCE\xCB\xCF\x6A\xE1\x70\xDD\xDE\xDB\xA1\x8D\x8E\xDF" }; /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ static unsigned char cp_278_to_819[] = { /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ /* 0x */ "\x00\x01\x02\x03\x80\x09\x81\x7F\x82\x83\x84\x0B\x0C\x0D\x0E\x0F" /* 1x */ "\x10\x11\x12\x13\x85\x0A\x08\x86\x18\x19\x87\x88\x1C\x1D\x1E\x1F" /* 2x */ "\x89\x8A\x8B\x8C\x8D\x8E\x17\x1B\x8F\x90\x91\x92\x93\x05\x06\x07" /* 3x */ "\x94\x95\x16\x96\x97\x98\x99\x04\x9A\x9B\x9C\x9D\x14\x15\x9E\x1A" /* 4x */ "\x20\xA0\xE2\x7B\xE0\xE1\xE3\x7D\xE7\xF1\xA7\x2E\x3C\x28\x2B\x21" /* 5x */ "\x26\x60\xEA\xEB\xE8\xED\xEE\xEF\xEC\xDF\xA4\xC5\x2A\x29\x3B\x5E" /* 6x */ "\x2D\x2F\xC2\x23\xC0\xC1\xC3\x24\xC7\xD1\xF6\x2C\x25\x5F\x3E\x3F" /* 7x */ "\xF8\x5C\xCA\xCB\xC8\xCD\xCE\xCF\xCC\xE9\x3A\xC4\xD6\x27\x3D\x22" /* 8x */ "\xD8\x61\x62\x63\x64\x65\x66\x67\x68\x69\xAB\xBB\xF0\xFD\xFE\xB1" /* 9x */ "\xB0\x6A\x6B\x6C\x6D\x6E\x6F\x70\x71\x72\xAA\xBA\xE6\xB8\xC6\x5D" /* Ax */ "\xB5\xFC\x73\x74\x75\x76\x77\x78\x79\x7A\xA1\xBF\xD0\xDD\xDE\xAE" /* Bx */ "\xA2\xA3\xA5\xB7\xA9\x5B\xB6\xBC\xBD\xBE\xAC\x7C\xAF\xA8\xB4\xD7" /* Cx */ "\xE4\x41\x42\x43\x44\x45\x46\x47\x48\x49\xAD\xF4\xA6\xF2\xF3\xF5" /* Dx */ "\xE5\x4A\x4B\x4C\x4D\x4E\x4F\x50\x51\x52\xB9\xFB\x7E\xF9\xFA\xFF" /* Ex */ "\xC9\xF7\x53\x54\x55\x56\x57\x58\x59\x5A\xB2\xD4\x40\xD2\xD3\xD5" /* Fx */ "\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\xB3\xDB\xDC\xD9\xDA\x9F" }; /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ /* 819 (ISO-8859-1 Latin-1) to 280 (EBCDIC CECP Italy) */ static unsigned char cp_819_to_280[] = { /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ /* 0x */ "\x00\x01\x02\x03\x37\x2D\x2E\x2F\x16\x05\x25\x0B\x0C\x0D\x0E\x0F" /* 1x */ "\x10\x11\x12\x13\x3C\x3D\x32\x26\x18\x19\x3F\x27\x1C\x1D\x1E\x1F" /* 2x */ "\x40\x4F\x7F\xB1\x5B\x6C\x50\x7D\x4D\x5D\x5C\x4E\x6B\x60\x4B\x61" /* 3x */ "\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\x7A\x5E\x4C\x7E\x6E\x6F" /* 4x */ "\xB5\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xD1\xD2\xD3\xD4\xD5\xD6" /* 5x */ "\xD7\xD8\xD9\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\x90\x48\x51\x5F\x6D" /* 6x */ "\xDD\x81\x82\x83\x84\x85\x86\x87\x88\x89\x91\x92\x93\x94\x95\x96" /* 7x */ "\x97\x98\x99\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\x44\xBB\x54\x58\x07" /* 8x */ "\x20\x21\x22\x23\x24\x15\x06\x17\x28\x29\x2A\x2B\x2C\x09\x0A\x1B" /* 9x */ "\x30\x31\x1A\x33\x34\x35\x36\x08\x38\x39\x3A\x3B\x04\x14\x3E\xFF" /* Ax */ "\x41\xAA\xB0\x7B\x9F\xB2\xCD\x7C\xBD\xB4\x9A\x8A\xBA\xCA\xAF\xBC" /* Bx */ "\x4A\x8F\xEA\xFA\xBE\xA0\xB6\xB3\x9D\xDA\x9B\x8B\xB7\xB8\xB9\xAB" /* Cx */ "\x64\x65\x62\x66\x63\x67\x9E\x68\x74\x71\x72\x73\x78\x75\x76\x77" /* Dx */ "\xAC\x69\xED\xEE\xEB\xEF\xEC\xBF\x80\xFD\xFE\xFB\xFC\xAD\xAE\x59" /* Ex */ "\xC0\x45\x42\x46\x43\x47\x9C\xE0\xD0\x5A\x52\x53\xA1\x55\x56\x57" /* Fx */ "\x8C\x49\x6A\xCE\xCB\xCF\xCC\xE1\x70\x79\xDE\xDB\xDC\x8D\x8E\xDF" }; /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ static unsigned char cp_280_to_819[] = { /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ /* 0x */ "\x00\x01\x02\x03\x9C\x09\x86\x7F\x97\x8D\x8E\x0B\x0C\x0D\x0E\x0F" /* 1x */ "\x10\x11\x12\x13\x9D\x85\x08\x87\x18\x19\x92\x8F\x1C\x1D\x1E\x1F" /* 2x */ "\x80\x81\x82\x83\x84\x0A\x17\x1B\x88\x89\x8A\x8B\x8C\x05\x06\x07" /* 3x */ "\x90\x91\x16\x93\x94\x95\x96\x04\x98\x99\x9A\x9B\x14\x15\x9E\x1A" /* 4x */ "\x20\xA0\xE2\xE4\x7B\xE1\xE3\xE5\x5C\xF1\xB0\x2E\x3C\x28\x2B\x21" /* 5x */ "\x26\x5D\xEA\xEB\x7D\xED\xEE\xEF\x7E\xDF\xE9\x24\x2A\x29\x3B\x5E" /* 6x */ "\x2D\x2F\xC2\xC4\xC0\xC1\xC3\xC5\xC7\xD1\xF2\x2C\x25\x5F\x3E\x3F" /* 7x */ "\xF8\xC9\xCA\xCB\xC8\xCD\xCE\xCF\xCC\xF9\x3A\xA3\xA7\x27\x3D\x22" /* 8x */ "\xD8\x61\x62\x63\x64\x65\x66\x67\x68\x69\xAB\xBB\xF0\xFD\xFE\xB1" /* 9x */ "\x5B\x6A\x6B\x6C\x6D\x6E\x6F\x70\x71\x72\xAA\xBA\xE6\xB8\xC6\xA4" /* Ax */ "\xB5\xEC\x73\x74\x75\x76\x77\x78\x79\x7A\xA1\xBF\xD0\xDD\xDE\xAE" /* Bx */ "\xA2\x23\xA5\xB7\xA9\x40\xB6\xBC\xBD\xBE\xAC\x7C\xAF\xA8\xB4\xD7" /* Cx */ "\xE0\x41\x42\x43\x44\x45\x46\x47\x48\x49\xAD\xF4\xF6\xA6\xF3\xF5" /* Dx */ "\xE8\x4A\x4B\x4C\x4D\x4E\x4F\x50\x51\x52\xB9\xFB\xFC\x60\xFA\xFF" /* Ex */ "\xE7\xF7\x53\x54\x55\x56\x57\x58\x59\x5A\xB2\xD4\xD6\xD2\xD3\xD5" /* Fx */ "\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\xB3\xDB\xDC\xD9\xDA\x9F" }; /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ /* 819 (ISO-8859-1 Latin-1) to 284 (EBCDIC CECP Spain) */ static unsigned char cp_819_to_284[] = { /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ /* 0x */ "\x00\x01\x02\x03\x37\x2D\x2E\x2F\x16\x05\x15\x0B\x0C\x0D\x0E\x0F" /* 1x */ "\x10\x11\x12\x13\x3C\x3D\x32\x26\x18\x19\x3F\x27\x1C\x1D\x1E\x1F" /* 2x */ "\x40\xBB\x7F\x69\x5B\x6C\x50\x7D\x4D\x5D\x5C\x4E\x6B\x60\x4B\x61" /* 3x */ "\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\x7A\x5E\x4C\x7E\x6E\x6F" /* 4x */ "\x7C\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xD1\xD2\xD3\xD4\xD5\xD6" /* 5x */ "\xD7\xD8\xD9\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\x4A\xE0\x5A\xBA\x6D" /* 6x */ "\x79\x81\x82\x83\x84\x85\x86\x87\x88\x89\x91\x92\x93\x94\x95\x96" /* 7x */ "\x97\x98\x99\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xC0\x4F\xD0\xBD\x07" /* 8x */ "\x04\x06\x08\x09\x0A\x14\x17\x1A\x1B\x20\x21\x22\x23\x24\x25\x28" /* 9x */ "\x29\x2A\x2B\x2C\x30\x31\x33\x34\x35\x36\x38\x39\x3A\x3B\x3E\xFF" /* Ax */ "\x41\xAA\xB0\xB1\x9F\xB2\x49\xB5\xA1\xB4\x9A\x8A\x5F\xCA\xAF\xBC" /* Bx */ "\x90\x8F\xEA\xFA\xBE\xA0\xB6\xB3\x9D\xDA\x9B\x8B\xB7\xB8\xB9\xAB" /* Cx */ "\x64\x65\x62\x66\x63\x67\x9E\x68\x74\x71\x72\x73\x78\x75\x76\x77" /* Dx */ "\xAC\x7B\xED\xEE\xEB\xEF\xEC\xBF\x80\xFD\xFE\xFB\xFC\xAD\xAE\x59" /* Ex */ "\x44\x45\x42\x46\x43\x47\x9C\x48\x54\x51\x52\x53\x58\x55\x56\x57" /* Fx */ "\x8C\x6A\xCD\xCE\xCB\xCF\xCC\xE1\x70\xDD\xDE\xDB\xDC\x8D\x8E\xDF" }; /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ static unsigned char cp_284_to_819[] = { /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ /* 0x */ "\x00\x01\x02\x03\x80\x09\x81\x7F\x82\x83\x84\x0B\x0C\x0D\x0E\x0F" /* 1x */ "\x10\x11\x12\x13\x85\x0A\x08\x86\x18\x19\x87\x88\x1C\x1D\x1E\x1F" /* 2x */ "\x89\x8A\x8B\x8C\x8D\x8E\x17\x1B\x8F\x90\x91\x92\x93\x05\x06\x07" /* 3x */ "\x94\x95\x16\x96\x97\x98\x99\x04\x9A\x9B\x9C\x9D\x14\x15\x9E\x1A" /* 4x */ "\x20\xA0\xE2\xE4\xE0\xE1\xE3\xE5\xE7\xA6\x5B\x2E\x3C\x28\x2B\x7C" /* 5x */ "\x26\xE9\xEA\xEB\xE8\xED\xEE\xEF\xEC\xDF\x5D\x24\x2A\x29\x3B\xAC" /* 6x */ "\x2D\x2F\xC2\xC4\xC0\xC1\xC3\xC5\xC7\x23\xF1\x2C\x25\x5F\x3E\x3F" /* 7x */ "\xF8\xC9\xCA\xCB\xC8\xCD\xCE\xCF\xCC\x60\x3A\xD1\x40\x27\x3D\x22" /* 8x */ "\xD8\x61\x62\x63\x64\x65\x66\x67\x68\x69\xAB\xBB\xF0\xFD\xFE\xB1" /* 9x */ "\xB0\x6A\x6B\x6C\x6D\x6E\x6F\x70\x71\x72\xAA\xBA\xE6\xB8\xC6\xA4" /* Ax */ "\xB5\xA8\x73\x74\x75\x76\x77\x78\x79\x7A\xA1\xBF\xD0\xDD\xDE\xAE" /* Bx */ "\xA2\xA3\xA5\xB7\xA9\xA7\xB6\xBC\xBD\xBE\x5E\x21\xAF\x7E\xB4\xD7" /* Cx */ "\x7B\x41\x42\x43\x44\x45\x46\x47\x48\x49\xAD\xF4\xF6\xF2\xF3\xF5" /* Dx */ "\x7D\x4A\x4B\x4C\x4D\x4E\x4F\x50\x51\x52\xB9\xFB\xFC\xF9\xFA\xFF" /* Ex */ "\x5C\xF7\x53\x54\x55\x56\x57\x58\x59\x5A\xB2\xD4\xD6\xD2\xD3\xD5" /* Fx */ "\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\xB3\xDB\xDC\xD9\xDA\x9F" }; /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ /* 819 (ISO-8859-1 Latin-1) to 285 (EBCDIC CECP UK) */ static unsigned char cp_819_to_285[] = { /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ /* 0x */ "\x00\x01\x02\x03\x37\x2D\x2E\x2F\x16\x05\x15\x0B\x0C\x0D\x0E\x0F" /* 1x */ "\x10\x11\x12\x13\x3C\x3D\x32\x26\x18\x19\x3F\x27\x1C\x1D\x1E\x1F" /* 2x */ "\x40\x5A\x7F\x7B\x4A\x6C\x50\x7D\x4D\x5D\x5C\x4E\x6B\x60\x4B\x61" /* 3x */ "\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\x7A\x5E\x4C\x7E\x6E\x6F" /* 4x */ "\x7C\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xD1\xD2\xD3\xD4\xD5\xD6" /* 5x */ "\xD7\xD8\xD9\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xB1\xE0\xBB\xBA\x6D" /* 6x */ "\x79\x81\x82\x83\x84\x85\x86\x87\x88\x89\x91\x92\x93\x94\x95\x96" /* 7x */ "\x97\x98\x99\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xC0\x4F\xD0\xBC\x07" /* 8x */ "\x04\x06\x08\x09\x0A\x14\x17\x1A\x1B\x20\x21\x22\x23\x24\x25\x28" /* 9x */ "\x29\x2A\x2B\x2C\x30\x31\x33\x34\x35\x36\x38\x39\x3A\x3B\x3E\xFF" /* Ax */ "\x41\xAA\xB0\x5B\x9F\xB2\x6A\xB5\xBD\xB4\x9A\x8A\x5F\xCA\xAF\xA1" /* Bx */ "\x90\x8F\xEA\xFA\xBE\xA0\xB6\xB3\x9D\xDA\x9B\x8B\xB7\xB8\xB9\xAB" /* Cx */ "\x64\x65\x62\x66\x63\x67\x9E\x68\x74\x71\x72\x73\x78\x75\x76\x77" /* Dx */ "\xAC\x69\xED\xEE\xEB\xEF\xEC\xBF\x80\xFD\xFE\xFB\xFC\xAD\xAE\x59" /* Ex */ "\x44\x45\x42\x46\x43\x47\x9C\x48\x54\x51\x52\x53\x58\x55\x56\x57" /* Fx */ "\x8C\x49\xCD\xCE\xCB\xCF\xCC\xE1\x70\xDD\xDE\xDB\xDC\x8D\x8E\xDF" }; /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ static unsigned char cp_285_to_819[] = { /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ /* 0x */ "\x00\x01\x02\x03\x80\x09\x81\x7F\x82\x83\x84\x0B\x0C\x0D\x0E\x0F" /* 1x */ "\x10\x11\x12\x13\x85\x0A\x08\x86\x18\x19\x87\x88\x1C\x1D\x1E\x1F" /* 2x */ "\x89\x8A\x8B\x8C\x8D\x8E\x17\x1B\x8F\x90\x91\x92\x93\x05\x06\x07" /* 3x */ "\x94\x95\x16\x96\x97\x98\x99\x04\x9A\x9B\x9C\x9D\x14\x15\x9E\x1A" /* 4x */ "\x20\xA0\xE2\xE4\xE0\xE1\xE3\xE5\xE7\xF1\x24\x2E\x3C\x28\x2B\x7C" /* 5x */ "\x26\xE9\xEA\xEB\xE8\xED\xEE\xEF\xEC\xDF\x21\xA3\x2A\x29\x3B\xAC" /* 6x */ "\x2D\x2F\xC2\xC4\xC0\xC1\xC3\xC5\xC7\xD1\xA6\x2C\x25\x5F\x3E\x3F" /* 7x */ "\xF8\xC9\xCA\xCB\xC8\xCD\xCE\xCF\xCC\x60\x3A\x23\x40\x27\x3D\x22" /* 8x */ "\xD8\x61\x62\x63\x64\x65\x66\x67\x68\x69\xAB\xBB\xF0\xFD\xFE\xB1" /* 9x */ "\xB0\x6A\x6B\x6C\x6D\x6E\x6F\x70\x71\x72\xAA\xBA\xE6\xB8\xC6\xA4" /* Ax */ "\xB5\xAF\x73\x74\x75\x76\x77\x78\x79\x7A\xA1\xBF\xD0\xDD\xDE\xAE" /* Bx */ "\xA2\x5B\xA5\xB7\xA9\xA7\xB6\xBC\xBD\xBE\x5E\x5D\x7E\xA8\xB4\xD7" /* Cx */ "\x7B\x41\x42\x43\x44\x45\x46\x47\x48\x49\xAD\xF4\xF6\xF2\xF3\xF5" /* Dx */ "\x7D\x4A\x4B\x4C\x4D\x4E\x4F\x50\x51\x52\xB9\xFB\xFC\xF9\xFA\xFF" /* Ex */ "\x5C\xF7\x53\x54\x55\x56\x57\x58\x59\x5A\xB2\xD4\xD6\xD2\xD3\xD5" /* Fx */ "\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\xB3\xDB\xDC\xD9\xDA\x9F" }; /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ /* 819 (ISO-8859-1 Latin-1) to 297 (EBCDIC CECP France) */ static unsigned char cp_819_to_297[] = { /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ /* 0x */ "\x00\x01\x02\x03\x37\x2D\x2E\x2F\x16\x05\x15\x0B\x0C\x0D\x0E\x0F" /* 1x */ "\x10\x11\x12\x13\x3C\x3D\x32\x26\x18\x19\x3F\x27\x1C\x1D\x1E\x1F" /* 2x */ "\x40\x4F\x7F\xB1\x5B\x6C\x50\x7D\x4D\x5D\x5C\x4E\x6B\x60\x4B\x61" /* 3x */ "\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\x7A\x5E\x4C\x7E\x6E\x6F" /* 4x */ "\x44\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xD1\xD2\xD3\xD4\xD5\xD6" /* 5x */ "\xD7\xD8\xD9\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\x90\x48\xB5\x5F\x6D" /* 6x */ "\xA0\x81\x82\x83\x84\x85\x86\x87\x88\x89\x91\x92\x93\x94\x95\x96" /* 7x */ "\x97\x98\x99\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\x51\xBB\x54\xBD\x07" /* 8x */ "\x04\x06\x08\x09\x0A\x14\x17\x1A\x1B\x20\x21\x22\x23\x24\x25\x28" /* 9x */ "\x29\x2A\x2B\x2C\x30\x31\x33\x34\x35\x36\x38\x39\x3A\x3B\x3E\xFF" /* Ax */ "\x41\xAA\xB0\x7B\x9F\xB2\xDD\x5A\xA1\xB4\x9A\x8A\xBA\xCA\xAF\xBC" /* Bx */ "\x4A\x8F\xEA\xFA\xBE\x79\xB6\xB3\x9D\xDA\x9B\x8B\xB7\xB8\xB9\xAB" /* Cx */ "\x64\x65\x62\x66\x63\x67\x9E\x68\x74\x71\x72\x73\x78\x75\x76\x77" /* Dx */ "\xAC\x69\xED\xEE\xEB\xEF\xEC\xBF\x80\xFD\xFE\xFB\xFC\xAD\xAE\x59" /* Ex */ "\x7C\x45\x42\x46\x43\x47\x9C\xE0\xD0\xC0\x52\x53\x58\x55\x56\x57" /* Fx */ "\x8C\x49\xCD\xCE\xCB\xCF\xCC\xE1\x70\x6A\xDE\xDB\xDC\x8D\x8E\xDF" }; /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ static unsigned char cp_297_to_819[] = { /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ /* 0x */ "\x00\x01\x02\x03\x80\x09\x81\x7F\x82\x83\x84\x0B\x0C\x0D\x0E\x0F" /* 1x */ "\x10\x11\x12\x13\x85\x0A\x08\x86\x18\x19\x87\x88\x1C\x1D\x1E\x1F" /* 2x */ "\x89\x8A\x8B\x8C\x8D\x8E\x17\x1B\x8F\x90\x91\x92\x93\x05\x06\x07" /* 3x */ "\x94\x95\x16\x96\x97\x98\x99\x04\x9A\x9B\x9C\x9D\x14\x15\x9E\x1A" /* 4x */ "\x20\xA0\xE2\xE4\x40\xE1\xE3\xE5\x5C\xF1\xB0\x2E\x3C\x28\x2B\x21" /* 5x */ "\x26\x7B\xEA\xEB\x7D\xED\xEE\xEF\xEC\xDF\xA7\x24\x2A\x29\x3B\x5E" /* 6x */ "\x2D\x2F\xC2\xC4\xC0\xC1\xC3\xC5\xC7\xD1\xF9\x2C\x25\x5F\x3E\x3F" /* 7x */ "\xF8\xC9\xCA\xCB\xC8\xCD\xCE\xCF\xCC\xB5\x3A\xA3\xE0\x27\x3D\x22" /* 8x */ "\xD8\x61\x62\x63\x64\x65\x66\x67\x68\x69\xAB\xBB\xF0\xFD\xFE\xB1" /* 9x */ "\x5B\x6A\x6B\x6C\x6D\x6E\x6F\x70\x71\x72\xAA\xBA\xE6\xB8\xC6\xA4" /* Ax */ "\x60\xA8\x73\x74\x75\x76\x77\x78\x79\x7A\xA1\xBF\xD0\xDD\xDE\xAE" /* Bx */ "\xA2\x23\xA5\xB7\xA9\x5D\xB6\xBC\xBD\xBE\xAC\x7C\xAF\x7E\xB4\xD7" /* Cx */ "\xE9\x41\x42\x43\x44\x45\x46\x47\x48\x49\xAD\xF4\xF6\xF2\xF3\xF5" /* Dx */ "\xE8\x4A\x4B\x4C\x4D\x4E\x4F\x50\x51\x52\xB9\xFB\xFC\xA6\xFA\xFF" /* Ex */ "\xE7\xF7\x53\x54\x55\x56\x57\x58\x59\x5A\xB2\xD4\xD6\xD2\xD3\xD5" /* Fx */ "\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\xB3\xDB\xDC\xD9\xDA\x9F" }; /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ /* 819 (ISO-8859-1 Latin-1) to 500 (EBCDIC CECP International) */ static unsigned char cp_819_to_500[] = { /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ /* 0x */ "\x00\x01\x02\x03\x37\x2D\x2E\x2F\x16\x05\x15\x0B\x0C\x0D\x0E\x0F" /* 1x */ "\x10\x11\x12\x13\x3C\x3D\x32\x26\x18\x19\x3F\x27\x1C\x1D\x1E\x1F" /* 2x */ "\x40\x4F\x7F\x7B\x5B\x6C\x50\x7D\x4D\x5D\x5C\x4E\x6B\x60\x4B\x61" /* 3x */ "\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\x7A\x5E\x4C\x7E\x6E\x6F" /* 4x */ "\x7C\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xD1\xD2\xD3\xD4\xD5\xD6" /* 5x */ "\xD7\xD8\xD9\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\x4A\xE0\x5A\x5F\x6D" /* 6x */ "\x79\x81\x82\x83\x84\x85\x86\x87\x88\x89\x91\x92\x93\x94\x95\x96" /* 7x */ "\x97\x98\x99\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xC0\xBB\xD0\xA1\x07" /* 8x */ "\x04\x06\x08\x09\x0A\x14\x17\x1A\x1B\x20\x21\x22\x23\x24\x25\x28" /* 9x */ "\x29\x2A\x2B\x2C\x30\x31\x33\x34\x35\x36\x38\x39\x3A\x3B\x3E\xFF" /* Ax */ "\x41\xAA\xB0\xB1\x9F\xB2\x6A\xB5\xBD\xB4\x9A\x8A\xBA\xCA\xAF\xBC" /* Bx */ "\x90\x8F\xEA\xFA\xBE\xA0\xB6\xB3\x9D\xDA\x9B\x8B\xB7\xB8\xB9\xAB" /* Cx */ "\x64\x65\x62\x66\x63\x67\x9E\x68\x74\x71\x72\x73\x78\x75\x76\x77" /* Dx */ "\xAC\x69\xED\xEE\xEB\xEF\xEC\xBF\x80\xFD\xFE\xFB\xFC\xAD\xAE\x59" /* Ex */ "\x44\x45\x42\x46\x43\x47\x9C\x48\x54\x51\x52\x53\x58\x55\x56\x57" /* Fx */ "\x8C\x49\xCD\xCE\xCB\xCF\xCC\xE1\x70\xDD\xDE\xDB\xDC\x8D\x8E\xDF" }; /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ static unsigned char cp_500_to_819[] = { /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ /* 0x */ "\x00\x01\x02\x03\x80\x09\x81\x7F\x82\x83\x84\x0B\x0C\x0D\x0E\x0F" /* 1x */ "\x10\x11\x12\x13\x85\x0A\x08\x86\x18\x19\x87\x88\x1C\x1D\x1E\x1F" /* 2x */ "\x89\x8A\x8B\x8C\x8D\x8E\x17\x1B\x8F\x90\x91\x92\x93\x05\x06\x07" /* 3x */ "\x94\x95\x16\x96\x97\x98\x99\x04\x9A\x9B\x9C\x9D\x14\x15\x9E\x1A" /* 4x */ "\x20\xA0\xE2\xE4\xE0\xE1\xE3\xE5\xE7\xF1\x5B\x2E\x3C\x28\x2B\x21" /* 5x */ "\x26\xE9\xEA\xEB\xE8\xED\xEE\xEF\xEC\xDF\x5D\x24\x2A\x29\x3B\x5E" /* 6x */ "\x2D\x2F\xC2\xC4\xC0\xC1\xC3\xC5\xC7\xD1\xA6\x2C\x25\x5F\x3E\x3F" /* 7x */ "\xF8\xC9\xCA\xCB\xC8\xCD\xCE\xCF\xCC\x60\x3A\x23\x40\x27\x3D\x22" /* 8x */ "\xD8\x61\x62\x63\x64\x65\x66\x67\x68\x69\xAB\xBB\xF0\xFD\xFE\xB1" /* 9x */ "\xB0\x6A\x6B\x6C\x6D\x6E\x6F\x70\x71\x72\xAA\xBA\xE6\xB8\xC6\xA4" /* Ax */ "\xB5\x7E\x73\x74\x75\x76\x77\x78\x79\x7A\xA1\xBF\xD0\xDD\xDE\xAE" /* Bx */ "\xA2\xA3\xA5\xB7\xA9\xA7\xB6\xBC\xBD\xBE\xAC\x7C\xAF\xA8\xB4\xD7" /* Cx */ "\x7B\x41\x42\x43\x44\x45\x46\x47\x48\x49\xAD\xF4\xF6\xF2\xF3\xF5" /* Dx */ "\x7D\x4A\x4B\x4C\x4D\x4E\x4F\x50\x51\x52\xB9\xFB\xFC\xF9\xFA\xFF" /* Ex */ "\x5C\xF7\x53\x54\x55\x56\x57\x58\x59\x5A\xB2\xD4\xD6\xD2\xD3\xD5" /* Fx */ "\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\xB3\xDB\xDC\xD9\xDA\x9F" }; /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ /* 437 to 1047 */ static unsigned char cp_437_to_1047[] = { /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ /* 0x */ "\x00\x01\x02\x03\x37\x2D\x2E\x2F\x16\x05\x25\x0B\x0C\x0D\x0E\x0F" /* 1x */ "\x10\x11\x12\x13\x3C\x3D\x32\x26\x18\x19\x1C\x27\x07\x1D\x1E\x1F" /* 2x */ "\x40\x5A\x7F\x7B\x5B\x6C\x50\x7D\x4D\x5D\x5C\x4E\x6B\x60\x4B\x61" /* 3x */ "\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\x7A\x5E\x4C\x7E\x6E\x6F" /* 4x */ "\x7C\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xD1\xD2\xD3\xD4\xD5\xD6" /* 5x */ "\xD7\xD8\xD9\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xAD\xE0\xBD\x5F\x6D" /* 6x */ "\x79\x81\x82\x83\x84\x85\x86\x87\x88\x89\x91\x92\x93\x94\x95\x96" /* 7x */ "\x97\x98\x99\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xC0\x4F\xD0\xA1\x3F" /* 8x */ "\x68\xDC\x51\x42\x43\x44\x47\x48\x52\x53\x54\x57\x56\x58\x63\x67" /* 9x */ "\x71\x9C\x9E\xCB\xCC\xCD\xDB\xDD\xDF\xEC\xFC\x4A\xB1\xB2\x3F\x3F" /* Ax */ "\x45\x55\xCE\xDE\x49\x69\x9A\x9B\xAB\x3F\xB0\xB8\xB7\xAA\x8A\x8B" /* Bx */ "\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F" /* Cx */ "\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F" /* Dx */ "\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F" /* Ex */ "\x3F\x59\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F" /* Fx */ "\x3F\x8F\x3F\x3F\x3F\x3F\xE1\x3F\x90\x3F\xB3\x3F\x3F\xEA\x3F\x41" }; /* 1047 to 437 */ static unsigned char cp_1047_to_437[] = { /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ /* 0x */ "\x00\x01\x02\x03\x07\x09\x07\x1C\x07\x07\x07\x0B\x0C\x0D\x0E\x0F" /* 1x */ "\x10\x11\x12\x13\x07\x07\x08\x07\x18\x19\x07\x07\x1A\x1D\x1E\x1F" /* 2x */ "\x07\x07\x07\x07\x07\x0A\x17\x1B\x07\x07\x07\x07\x07\x05\x06\x07" /* 3x */ "\x07\x07\x16\x07\x07\x07\x07\x04\x07\x07\x07\x07\x14\x15\x07\x7F" /* 4x */ "\x20\xFF\x83\x84\x85\xA0\x07\x86\x87\xA4\x9B\x2E\x3C\x28\x2B\x7C" /* 5x */ "\x26\x82\x88\x89\x8A\xA1\x8C\x8B\x8D\xE1\x21\x24\x2A\x29\x3B\x5E" /* 6x */ "\x2D\x2F\x07\x8E\x07\x07\x07\x8F\x80\xA5\x07\x2C\x25\x5F\x3E\x3F" /* 7x */ "\x07\x90\x07\x07\x07\x07\x07\x07\x07\x60\x3A\x23\x40\x27\x3D\x22" /* 8x */ "\x07\x61\x62\x63\x64\x65\x66\x67\x68\x69\xAE\xAF\x07\x07\x07\xF1" /* 9x */ "\xF8\x6A\x6B\x6C\x6D\x6E\x6F\x70\x71\x72\xA6\xA7\x91\x07\x92\x07" /* Ax */ "\x07\x7E\x73\x74\x75\x76\x77\x78\x79\x7A\xAD\xA8\x07\x5B\x07\x07" /* Bx */ "\xAA\x9C\x9D\xFA\x07\x07\x07\xAC\xAB\x07\x07\x07\x07\x5D\x07\x07" /* Cx */ "\x7B\x41\x42\x43\x44\x45\x46\x47\x48\x49\x07\x93\x94\x95\xA2\x07" /* Dx */ "\x7D\x4A\x4B\x4C\x4D\x4E\x4F\x50\x51\x52\x07\x96\x81\x97\xA3\x98" /* Ex */ "\x5C\xF6\x53\x54\x55\x56\x57\x58\x59\x5A\xFD\x07\x99\x07\x07\x07" /* Fx */ "\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x07\x07\x9A\x07\x07\x07" }; /* 819 to 1047 */ static unsigned char cp_819_to_1047[] = { /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ /* 0x */ "\x00\x01\x02\x03\x37\x2D\x2E\x2F\x16\x05\x25\x0B\x0C\x0D\x0E\x0F" /* 1x */ "\x10\x11\x12\x13\x3C\x3D\x32\x26\x18\x19\x3F\x27\x1C\x1D\x1E\x1F" /* 2x */ "\x40\x5A\x7F\x7B\x5B\x6C\x50\x7D\x4D\x5D\x5C\x4E\x6B\x60\x4B\x61" /* 3x */ "\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\x7A\x5E\x4C\x7E\x6E\x6F" /* 4x */ "\x7C\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xD1\xD2\xD3\xD4\xD5\xD6" /* 5x */ "\xD7\xD8\xD9\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xAD\xE0\xBD\x5F\x6D" /* 6x */ "\x79\x81\x82\x83\x84\x85\x86\x87\x88\x89\x91\x92\x93\x94\x95\x96" /* 7x */ "\x97\x98\x99\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xC0\x4F\xD0\xA1\x07" /* 8x */ "\x20\x21\x22\x23\x24\x15\x06\x17\x28\x29\x2A\x2B\x2C\x09\x0A\x1B" /* 9x */ "\x30\x31\x1A\x33\x34\x35\x36\x08\x38\x39\x3A\x3B\x04\x14\x3E\xFF" /* Ax */ "\x41\xAA\x4A\xB1\x9F\xB2\x6A\xB5\xBB\xB4\x9A\x8A\xB0\xCA\xAF\xBC" /* Bx */ "\x90\x8F\xEA\xFA\xBE\xA0\xB6\xB3\x9D\xDA\x9B\x8B\xB7\xB8\xB9\xAB" /* Cx */ "\x64\x65\x62\x66\x63\x67\x9E\x68\x74\x71\x72\x73\x78\x75\x76\x77" /* Dx */ "\xAC\x69\xED\xEE\xEB\xEF\xEC\xBF\x80\xFD\xFE\xFB\xFC\xBA\xAE\x59" /* Ex */ "\x44\x45\x42\x46\x43\x47\x9C\x48\x54\x51\x52\x53\x58\x55\x56\x57" /* Fx */ "\x8C\x49\xCD\xCE\xCB\xCF\xCC\xE1\x70\xDD\xDE\xDB\xDC\x8D\x8E\xDF" }; /* 1047 to 819 */ static unsigned char cp_1047_to_819[] = { /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ /* 0x */ "\x00\x01\x02\x03\x9C\x09\x86\x7F\x97\x8D\x8E\x0B\x0C\x0D\x0E\x0F" /* 1x */ "\x10\x11\x12\x13\x9D\x85\x08\x87\x18\x19\x92\x8F\x1C\x1D\x1E\x1F" /* 2x */ "\x80\x81\x82\x83\x84\x0A\x17\x1B\x88\x89\x8A\x8B\x8C\x05\x06\x07" /* 3x */ "\x90\x91\x16\x93\x94\x95\x96\x04\x98\x99\x9A\x9B\x14\x15\x9E\x1A" /* 4x */ "\x20\xA0\xE2\xE4\xE0\xE1\xE3\xE5\xE7\xF1\xA2\x2E\x3C\x28\x2B\x7C" /* 5x */ "\x26\xE9\xEA\xEB\xE8\xED\xEE\xEF\xEC\xDF\x21\x24\x2A\x29\x3B\x5E" /* 6x */ "\x2D\x2F\xC2\xC4\xC0\xC1\xC3\xC5\xC7\xD1\xA6\x2C\x25\x5F\x3E\x3F" /* 7x */ "\xF8\xC9\xCA\xCB\xC8\xCD\xCE\xCF\xCC\x60\x3A\x23\x40\x27\x3D\x22" /* 8x */ "\xD8\x61\x62\x63\x64\x65\x66\x67\x68\x69\xAB\xBB\xF0\xFD\xFE\xB1" /* 9x */ "\xB0\x6A\x6B\x6C\x6D\x6E\x6F\x70\x71\x72\xAA\xBA\xE6\xB8\xC6\xA4" /* Ax */ "\xB5\x7E\x73\x74\x75\x76\x77\x78\x79\x7A\xA1\xBF\xD0\x5B\xDE\xAE" /* Bx */ "\xAC\xA3\xA5\xB7\xA9\xA7\xB6\xBC\xBD\xBE\xDD\xA8\xAF\x5D\xB4\xD7" /* Cx */ "\x7B\x41\x42\x43\x44\x45\x46\x47\x48\x49\xAD\xF4\xF6\xF2\xF3\xF5" /* Dx */ "\x7D\x4A\x4B\x4C\x4D\x4E\x4F\x50\x51\x52\xB9\xFB\xFC\xF9\xFA\xFF" /* Ex */ "\x5C\xF7\x53\x54\x55\x56\x57\x58\x59\x5A\xB2\xD4\xD6\xD2\xD3\xD5" /* Fx */ "\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\xB3\xDB\xDC\xD9\xDA\x9F" }; /* 1252 to 1047 */ static unsigned char cp_1252_to_1047[] = { /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ /* 0x */ "\x00\x01\x02\x03\x37\x2D\x2E\x2F\x16\x05\x25\x0B\x0C\x0D\x0E\x0F" /* 1x */ "\x10\x11\x12\x13\x3C\x3D\x32\x26\x18\x19\x3F\x27\x1C\x1D\x1E\x1F" /* 2x */ "\x40\x5A\x7F\x7B\x5B\x6C\x50\x7D\x4D\x5D\x5C\x4E\x6B\x60\x4B\x61" /* 3x */ "\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\x7A\x5E\x4C\x7E\x6E\x6F" /* 4x */ "\x7C\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xD1\xD2\xD3\xD4\xD5\xD6" /* 5x */ "\xD7\xD8\xD9\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xAD\xE0\xBD\x5F\x6D" /* 6x */ "\x79\x81\x82\x83\x84\x85\x86\x87\x88\x89\x91\x92\x93\x94\x95\x96" /* 7x */ "\x97\x98\x99\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xC0\x4F\xD0\xA1\x07" /* 8x */ "\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F" /* 9x */ "\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x3F" /* Ax */ "\x41\xAA\x4A\xB1\x9F\xB2\x6A\xB5\xBB\xB4\x9A\x8A\xB0\xCA\xAF\xBC" /* Bx */ "\x90\x8F\xEA\xFA\xBE\xA0\xB6\xB3\x9D\xDA\x9B\x8B\xB7\xB8\xB9\xAB" /* Cx */ "\x64\x65\x62\x66\x63\x67\x9E\x68\x74\x71\x72\x73\x78\x75\x76\x77" /* Dx */ "\xAC\x69\xED\xEE\xEB\xEF\xEC\xBF\x80\xFD\xFE\xFB\xFC\xBA\xAE\x59" /* Ex */ "\x44\x45\x42\x46\x43\x47\x9C\x48\x54\x51\x52\x53\x58\x55\x56\x57" /* Fx */ "\x8C\x49\xCD\xCE\xCB\xCF\xCC\xE1\x70\xDD\xDE\xDB\xDC\x8D\x8E\xDF" }; /* 1047 to 1252 */ static unsigned char cp_1047_to_1252[] = { /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ /* 0x */ "\x00\x01\x02\x03\x07\x09\x07\x7F\x07\x07\x07\x0B\x0C\x0D\x0E\x0F" /* 1x */ "\x10\x11\x12\x13\x07\x07\x08\x07\x18\x19\x07\x07\x1C\x1D\x1E\x1F" /* 2x */ "\x07\x07\x07\x07\x07\x0A\x17\x1B\x07\x07\x07\x07\x07\x05\x06\x07" /* 3x */ "\x07\x07\x16\x07\x07\x07\x07\x04\x07\x07\x07\x07\x14\x15\x07\x1A" /* 4x */ "\x20\xA0\xE2\xE4\xE0\xE1\xE3\xE5\xE7\xF1\xA2\x2E\x3C\x28\x2B\x7C" /* 5x */ "\x26\xE9\xEA\xEB\xE8\xED\xEE\xEF\xEC\xDF\x21\x24\x2A\x29\x3B\x5E" /* 6x */ "\x2D\x2F\xC2\xC4\xC0\xC1\xC3\xC5\xC7\xD1\xA6\x2C\x25\x5F\x3E\x3F" /* 7x */ "\xF8\xC9\xCA\xCB\xC8\xCD\xCE\xCF\xCC\x60\x3A\x23\x40\x27\x3D\x22" /* 8x */ "\xD8\x61\x62\x63\x64\x65\x66\x67\x68\x69\xAB\xBB\xF0\xFD\xFE\xB1" /* 9x */ "\xB0\x6A\x6B\x6C\x6D\x6E\x6F\x70\x71\x72\xAA\xBA\xE6\xB8\xC6\xA4" /* Ax */ "\xB5\x7E\x73\x74\x75\x76\x77\x78\x79\x7A\xA1\xBF\xD0\x5B\xDE\xAE" /* Bx */ "\xAC\xA3\xA5\xB7\xA9\xA7\xB6\xBC\xBD\xBE\xDD\xA8\xAF\x5D\xB4\xD7" /* Cx */ "\x7B\x41\x42\x43\x44\x45\x46\x47\x48\x49\xAD\xF4\xF6\xF2\xF3\xF5" /* Dx */ "\x7D\x4A\x4B\x4C\x4D\x4E\x4F\x50\x51\x52\xB9\xFB\xFC\xF9\xFA\xFF" /* Ex */ "\x5C\xF7\x53\x54\x55\x56\x57\x58\x59\x5A\xB2\xD4\xD6\xD2\xD3\xD5" /* Fx */ "\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\xB3\xDB\xDC\xD9\xDA\x07" }; /* 850 to 1047 */ static unsigned char cp_850_to_1047[] = { /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ /* 0x */ "\x00\x01\x02\x03\x37\x2D\x2E\x2F\x16\x05\x25\x0B\x0C\x0D\x0E\x0F" /* 1x */ "\x10\x11\x12\x13\x3C\x3D\x32\x26\x18\x19\x3F\x27\x1C\x1D\x1E\x1F" /* 2x */ "\x40\x5A\x7F\x7B\x5B\x6C\x50\x7D\x4D\x5D\x5C\x4E\x6B\x60\x4B\x61" /* 3x */ "\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\x7A\x5E\x4C\x7E\x6E\x6F" /* 4x */ "\x7C\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xD1\xD2\xD3\xD4\xD5\xD6" /* 5x */ "\xD7\xD8\xD9\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xAD\xE0\xBD\x5F\x6D" /* 6x */ "\x79\x81\x82\x83\x84\x85\x86\x87\x88\x89\x91\x92\x93\x94\x95\x96" /* 7x */ "\x97\x98\x99\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xC0\x4F\xD0\xA1\x07" /* 8x */ "\x68\xDC\x51\x42\x43\x44\x47\x48\x52\x53\x54\x57\x56\x58\x63\x67" /* 9x */ "\x71\x9C\x9E\xCB\xCC\xCD\xDB\xDD\xDF\xEC\xFC\x70\xB1\x80\xBF\x3F" /* Ax */ "\x45\x55\xCE\xDE\x49\x69\x9A\x9B\xAB\xAF\xB0\xB8\xB7\xAA\x8A\x8B" /* Bx */ "\x3F\x3F\x3F\x3F\x3F\x65\x62\x64\xB4\x3F\x3F\x3F\x3F\x4A\xB2\x3F" /* Cx */ "\x3F\x3F\x3F\x3F\x3F\x3F\x46\x66\x3F\x3F\x3F\x3F\x3F\x3F\x3F\x9F" /* Dx */ "\x8C\xAC\x72\x73\x74\x3F\x75\x76\x77\x3F\x3F\x3F\x3F\x6A\x78\x3F" /* Ex */ "\xEE\x59\xEB\xED\xCF\xEF\xA0\x8E\xAE\xFE\xFB\xFD\x8D\xBA\xBC\xBE" /* Fx */ "\xCA\x8F\x3F\xB9\xB6\xB5\xE1\x9D\x90\xBB\xB3\xDA\xFA\xEA\x3F\x41" }; /* 1047 to 850 */ static unsigned char cp_1047_to_850[] = { /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ /* 0x */ "\x00\x01\x02\x03\x07\x09\x07\x7F\x07\x07\x07\x0B\x0C\x0D\x0E\x0F" /* 1x */ "\x10\x11\x12\x13\x07\x07\x08\x07\x18\x19\x07\x07\x1C\x1D\x1E\x1F" /* 2x */ "\x07\x07\x07\x07\x07\x0A\x17\x1B\x07\x07\x07\x07\x07\x05\x06\x07" /* 3x */ "\x07\x07\x16\x07\x07\x07\x07\x04\x07\x07\x07\x07\x14\x15\x07\x1A" /* 4x */ "\x20\xFF\x83\x84\x85\xA0\xC6\x86\x87\xA4\xBD\x2E\x3C\x28\x2B\x7C" /* 5x */ "\x26\x82\x88\x89\x8A\xA1\x8C\x8B\x8D\xE1\x21\x24\x2A\x29\x3B\x5E" /* 6x */ "\x2D\x2F\xB6\x8E\xB7\xB5\xC7\x8F\x80\xA5\xDD\x2C\x25\x5F\x3E\x3F" /* 7x */ "\x9B\x90\xD2\xD3\xD4\xD6\xD7\xD8\xDE\x60\x3A\x23\x40\x27\x3D\x22" /* 8x */ "\x9D\x61\x62\x63\x64\x65\x66\x67\x68\x69\xAE\xAF\xD0\xEC\xE7\xF1" /* 9x */ "\xF8\x6A\x6B\x6C\x6D\x6E\x6F\x70\x71\x72\xA6\xA7\x91\xF7\x92\xCF" /* Ax */ "\xE6\x7E\x73\x74\x75\x76\x77\x78\x79\x7A\xAD\xA8\xD1\x5B\xE8\xA9" /* Bx */ "\xAA\x9C\xBE\xFA\xB8\xF5\xF4\xAC\xAB\xF3\xED\xF9\xEE\x5D\xEF\x9E" /* Cx */ "\x7B\x41\x42\x43\x44\x45\x46\x47\x48\x49\xF0\x93\x94\x95\xA2\xE4" /* Dx */ "\x7D\x4A\x4B\x4C\x4D\x4E\x4F\x50\x51\x52\xFB\x96\x81\x97\xA3\x98" /* Ex */ "\x5C\xF6\x53\x54\x55\x56\x57\x58\x59\x5A\xFD\xE2\x99\xE3\xE0\xE5" /* Fx */ "\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\xFC\xEA\x9A\xEB\xE9\x07" }; typedef struct _CPCONV { char *name; unsigned char *h2g; unsigned char *g2h; } CPCONV; static CPCONV cpconv[] = { { "default", ascii_to_ebcdic, ebcdic_to_ascii }, { "437/037", cp_437_to_037, cp_037_to_437 }, { "437/500", cp_437_to_500, cp_500_to_437 }, { "850/273", cp_850_to_273, cp_273_to_850 }, { "819/273", cp_819_to_273, cp_273_to_819 }, { "819/277", cp_819_to_277, cp_277_to_819 }, { "819/278", cp_819_to_278, cp_278_to_819 }, { "819/280", cp_819_to_280, cp_280_to_819 }, { "819/284", cp_819_to_284, cp_284_to_819 }, { "819/285", cp_819_to_285, cp_285_to_819 }, { "819/297", cp_819_to_297, cp_297_to_819 }, { "819/500", cp_819_to_500, cp_500_to_819 }, { "437/1047", cp_437_to_1047, cp_1047_to_437 }, { "819/1047", cp_819_to_1047, cp_1047_to_819 }, { "1252/1047", cp_1252_to_1047, cp_1047_to_1252 }, { "850/1047", cp_850_to_1047, cp_1047_to_850 }, { NULL, ascii_to_ebcdic, ebcdic_to_ascii } }; static CPCONV *codepage_conv = cpconv; #if defined(HAVE_ICONV) static iconv_t codepage_g2h = NULL; static iconv_t codepage_h2g = NULL; static int set_iconv_cp(char *name) { char *codepage; char *fcp, *tcp; char *strtok_str; char ibyte, obyte; char *ibytes ,*obytes; size_t nibytes, nobytes; if(codepage_g2h) iconv_close(codepage_g2h); if(codepage_h2g) iconv_close(codepage_h2g); codepage_g2h = codepage_h2g = NULL; codepage = strdup(name); if(!(fcp = strtok_r(codepage,"/,:",&strtok_str))) { free(codepage); return -1; } if(!(tcp = strtok_r(NULL,"/,:",&strtok_str))) { free(codepage); return -1; } if((codepage_g2h = iconv_open (fcp,tcp)) == (iconv_t)(-1)) { codepage_g2h = NULL; free(codepage); return -1; } if((codepage_h2g = iconv_open (tcp,fcp)) == (iconv_t)(-1)) { iconv_close(codepage_g2h); codepage_g2h = codepage_h2g = NULL; free(codepage); return -1; } free(codepage); ibytes = &ibyte; obytes = &obyte; nibytes = nobytes = 1; if(iconv(codepage_g2h, (char**)&ibytes, &nibytes, &obytes, &nobytes) == (size_t)(-1) ) { iconv_close(codepage_g2h); iconv_close(codepage_h2g); codepage_g2h = codepage_h2g = NULL; return -1; } ibytes = &ibyte; obytes = &obyte; nibytes = nobytes = 1; if(iconv(codepage_h2g, (char**)&ibytes, &nibytes, &obytes, &nobytes) == (size_t)(-1) ) { iconv_close(codepage_g2h); iconv_close(codepage_h2g); codepage_g2h = codepage_h2g = NULL; return -1; } return 0; } #endif /*defined(HAVE_ICONV)*/ DLL_EXPORT void set_codepage(char *name) { if(name == NULL) if(!(name = getenv("HERCULES_CP"))) name = "default"; for(codepage_conv = cpconv; codepage_conv->name && strcasecmp(codepage_conv->name,name); codepage_conv++); if(codepage_conv->name) { #if 0 logmsg(_("HHCCF072I Using internal codepage conversion table %s\n"), name); #endif } else { #if defined(HAVE_ICONV) if(!set_iconv_cp(name)) { #if 0 logmsg(_("HHCCF072I Using external codepage conversion table %s\n"), name); #endif } else #endif /*defined(HAVE_ICONV)*/ logmsg(_("HHCCF051E Codepage conversion table %s is not defined\n"), name); } } DLL_EXPORT unsigned char host_to_guest (unsigned char byte) { #if defined(HAVE_ICONV) char obyte; char *gbyte = &obyte; char *hbyte = (char *)&byte; size_t inbytes = 1, outbytes = 1; if(codepage_h2g) { iconv(codepage_h2g, (char**)&hbyte, &inbytes, &gbyte, &outbytes); return obyte; } else #endif /*defined(HAVE_ICONV)*/ return (unsigned char)codepage_conv->h2g[(unsigned int)byte]; } DLL_EXPORT unsigned char guest_to_host (unsigned char byte) { #if defined(HAVE_ICONV) char obyte; char *hbyte = &obyte; char *gbyte = (char *)&byte; size_t inbytes = 1, outbytes = 1; if(codepage_g2h) { iconv(codepage_g2h, (char**)&gbyte, &inbytes, &hbyte, &outbytes); return obyte; } else #endif /*defined(HAVE_ICONV)*/ return codepage_conv->g2h[byte]; } hercules-3.07/codepage.h000644 000765 000765 00000001632 11143760543 016671 0ustar00jmaynardjmaynard000000 000000 /* CODEPAGE.H (c) Copyright Jan Jaeger, 1999-2009 */ /* Code Page conversion */ // $Id: codepage.h 5125 2009-01-23 12:01:44Z bernard $ // // $Log$ // Revision 1.11 2007/06/23 00:04:04 ivan // Update copyright notices to include current year (2007) // // Revision 1.10 2006/12/08 09:43:18 jj // Add CVS message log // #ifndef _HERCULES_CODEPAGE_H #define _HERCULES_CODEPAGE_H #include "hercules.h" #ifndef _CODEPAGE_C_ #ifndef _HUTIL_DLL_ #define COD_DLL_IMPORT DLL_IMPORT #else /* _HUTIL_DLL_ */ #define COD_DLL_IMPORT extern #endif /* _HUTIL_DLL_ */ #else /* _LOGGER_C_ */ #define COD_DLL_IMPORT DLL_EXPORT #endif /* _LOGGER_C_ */ COD_DLL_IMPORT void set_codepage(char *name); COD_DLL_IMPORT unsigned char host_to_guest (unsigned char byte); COD_DLL_IMPORT unsigned char guest_to_host (unsigned char byte); #endif /* _HERCULES_CODEPAGE_H */ hercules-3.07/comm3705.c000644 000765 000765 00000234353 11204560640 016371 0ustar00jmaynardjmaynard000000 000000 /***********************************************************************/ /* */ /* comm3705.c - (C) Copyright 2007 by MHP */ /* */ /* Loosely based on commadpt.c by Ivan Warren */ /* */ /* This module appears to the "host" as a 3705 communications */ /* controller running NCP. It does not attempt to provide an emulated */ /* execution environment for native 3705 code. */ /* */ /* Experimental release 0.02 Oct. 15, 2007 */ /* */ /* A very minimalistic SNA engine is implemented. All received SNA */ /* requests are responded to with a positive response. Also, there's */ /* enough code to enable a single SNA session to logon in LU1 (TTY) */ /* mode. */ /* */ /* FID1 is the only SNA header type supported. */ /* */ /* A large amount of required SNA functionality is not present in this */ /* release. There are no "state machines", "layers", "services", */ /* chaining*, pacing, brackets, etc.etc.etc. There are */ /* probably more bugs than working functions... Enjoy ;-) */ /* */ /* A better implementation might be to separate the SNA functions out */ /* into an independent process, with communications over a full-duplex */ /* TCP/IP socket... We might also get rid of all the magic constants...*/ /* */ /* New in release 0.02 - */ /* - VTAM switched (dial) support */ /* - New remote NCP capability */ /* - SNA 3270 (LU2) support (*with RU chaining) */ /* - fixes for some bugs in 0.01 */ /* New in release 0.03 - */ /* - don't process TTY lines until CR received */ /* New in release 0.04 - */ /* - make debug messages optional */ /* */ /* 73 DE KA1RBI */ /***********************************************************************/ #include "hstdinc.h" #include "hercules.h" #include "devtype.h" #include "opcode.h" #include "parser.h" #include "comm3705.h" #if defined(WIN32) && defined(OPTION_DYNAMIC_LOAD) && !defined(HDL_USE_LIBTOOL) && !defined(_MSVC_) SYSBLK *psysblk; #define sysblk (*psysblk) #endif #if !defined(min) #define min(a,b) (((a) <= (b)) ? (a) : (b)) #endif static void make_sna_requests2(COMMADPT*); static void make_sna_requests3(COMMADPT*); static void make_sna_requests4(COMMADPT*, int, BYTE); static void make_sna_requests5(COMMADPT*); static unsigned char R010201[3] = {0x01, 0x02, 0x01}; static unsigned char R010202[3] = {0x01, 0x02, 0x02}; static unsigned char R010203[3] = {0x01, 0x02, 0x03}; static unsigned char R010204[3] = {0x01, 0x02, 0x04}; static unsigned char R010205[3] = {0x01, 0x02, 0x05}; static unsigned char R01020A[3] = {0x01, 0x02, 0x0A}; static unsigned char R01020B[3] = {0x01, 0x02, 0x0B}; static unsigned char R01020F[3] = {0x01, 0x02, 0x0F}; static unsigned char R010211[3] = {0x01, 0x02, 0x11}; static unsigned char R010216[3] = {0x01, 0x02, 0x16}; static unsigned char R010217[3] = {0x01, 0x02, 0x17}; static unsigned char R010219[3] = {0x01, 0x02, 0x19}; static unsigned char R01021A[3] = {0x01, 0x02, 0x1A}; static unsigned char R01021B[3] = {0x01, 0x02, 0x1B}; static unsigned char R010280[3] = {0x01, 0x02, 0x80}; static unsigned char R010281[3] = {0x01, 0x02, 0x81}; static unsigned char R010284[3] = {0x01, 0x02, 0x84}; #define BUFPD 0x1C static BYTE commadpt_immed_command[256]= { 0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; /*---------------------------------------------------------------*/ /* PARSER TABLES */ /*---------------------------------------------------------------*/ static PARSER ptab[]={ {"lport","%s"}, {"lhost","%s"}, {"rport","%s"}, {"rhost","%s"}, {"dial","%s"}, {"rto","%s"}, {"pto","%s"}, {"eto","%s"}, {"switched","%s"}, {"lnctl","%s"}, {"debug","%s"}, {NULL,NULL} }; enum { COMMADPT_KW_LPORT=1, COMMADPT_KW_LHOST, COMMADPT_KW_RPORT, COMMADPT_KW_RHOST, COMMADPT_KW_DIAL, COMMADPT_KW_READTO, COMMADPT_KW_POLLTO, COMMADPT_KW_ENABLETO, COMMADPT_KW_SWITCHED, COMMADPT_KW_LNCTL, COMMADPT_KW_DEBUG } comm3705_kw; ////////////////////////////////////////////////////////////////////// // some code copied from console.c static HOST_INFO cons_hostinfo; /* Host info for this system */ /*-------------------------------------------------------------------*/ /* Telnet command definitions */ /*-------------------------------------------------------------------*/ #define BINARY 0 /* Binary Transmission */ #define IS 0 /* Used by terminal-type negotiation */ #define SEND 1 /* Used by terminal-type negotiation */ #define ECHO_OPTION 1 /* Echo option */ #define SUPPRESS_GA 3 /* Suppress go-ahead option */ #define TIMING_MARK 6 /* Timing mark option */ #define TERMINAL_TYPE 24 /* Terminal type option */ #define NAWS 31 /* Negotiate About Window Size */ #define EOR 25 /* End of record option */ #define EOR_MARK 239 /* End of record marker */ #define SE 240 /* End of subnegotiation parameters */ #define NOP 241 /* No operation */ #define DATA_MARK 242 /* The data stream portion of a Synch. This should always be accompanied by a TCP Urgent notification */ #define BRK 243 /* Break character */ #define IP 244 /* Interrupt Process */ #define AO 245 /* Abort Output */ #define AYT 246 /* Are You There */ #define EC 247 /* Erase character */ #define EL 248 /* Erase Line */ #define GA 249 /* Go ahead */ #define SB 250 /* Subnegotiation of indicated option */ #define WILL 251 /* Indicates the desire to begin performing, or confirmation that you are now performing, the indicated option */ #define WONT 252 /* Indicates the refusal to perform, or continue performing, the indicated option */ #define DO 253 /* Indicates the request that the other party perform, or confirmation that you are expecting the other party to perform, the indicated option */ #define DONT 254 /* Indicates the demand that the other party stop performing, or confirmation that you are no longer expecting the other party to perform, the indicated option */ #define IAC 255 /* Interpret as Command */ /*-------------------------------------------------------------------*/ /* 3270 definitions */ /*-------------------------------------------------------------------*/ /* 3270 remote commands */ #define R3270_EAU 0x6F /* Erase All Unprotected */ #define R3270_EW 0xF5 /* Erase/Write */ #define R3270_EWA 0x7E /* Erase/Write Alternate */ #define R3270_RB 0xF2 /* Read Buffer */ #define R3270_RM 0xF6 /* Read Modified */ #define R3270_RMA 0x6E /* Read Modified All */ #define R3270_WRT 0xF1 /* Write */ #define R3270_WSF 0xF3 /* Write Structured Field */ /* 3270 orders */ #define O3270_SBA 0x11 /* Set Buffer Address */ #define O3270_SF 0x1D /* Start Field */ #define O3270_SFE 0x29 /* Start Field Extended */ #define O3270_SA 0x28 /* Set Attribute */ #define O3270_IC 0x13 /* Insert Cursor */ #define O3270_MF 0x2C /* Modify Field */ #define O3270_PT 0x05 /* Program Tab */ #define O3270_RA 0x3C /* Repeat to Address */ #define O3270_EUA 0x12 /* Erase Unprotected to Addr */ #define O3270_GE 0x08 /* Graphic Escape */ /* Inbound structured fields */ #define SF3270_AID 0x88 /* Aid value of inbound SF */ #define SF3270_3270DS 0x80 /* SFID of 3270 datastream SF*/ /*-------------------------------------------------------------------*/ /* Internal macro definitions */ /*-------------------------------------------------------------------*/ /* DEBUG_LVL: 0 = none 1 = status 2 = headers 3 = buffers */ #define DEBUG_LVL 0 #if DEBUG_LVL == 0 #define TNSDEBUG1 1 ? ((void)0) : logmsg #define TNSDEBUG2 1 ? ((void)0) : logmsg #define TNSDEBUG3 1 ? ((void)0) : logmsg #endif #if DEBUG_LVL == 1 #define TNSDEBUG1 logmsg #define TNSDEBUG2 1 ? ((void)0) : logmsg #define TNSDEBUG3 1 ? ((void)0) : logmsg #endif #if DEBUG_LVL == 2 #define TNSDEBUG1 logmsg #define TNSDEBUG2 logmsg #define TNSDEBUG3 1 ? ((void)0) : logmsg #endif #if DEBUG_LVL == 3 #define TNSDEBUG1 logmsg #define TNSDEBUG2 logmsg #define TNSDEBUG3 logmsg #endif #define TNSERROR logmsg #define BUFLEN_3270 65536 /* 3270 Send/Receive buffer */ #define BUFLEN_1052 150 /* 1052 Send/Receive buffer */ #undef FIX_QWS_BUG_FOR_MCS_CONSOLES /*-------------------------------------------------------------------*/ /* SUBROUTINE TO TRACE THE CONTENTS OF AN ASCII MESSAGE PACKET */ /*-------------------------------------------------------------------*/ #if DEBUG_LVL == 3 static void packet_trace(BYTE *addr, int len) { int i, offset; BYTE c; BYTE print_chars[17]; for (offset=0; offset < len; ) { memset(print_chars,0,sizeof(print_chars)); logmsg("+%4.4X ", offset); for (i=0; i < 16; i++) { c = *addr++; if (offset < len) { logmsg("%2.2X", c); print_chars[i] = '.'; if (isprint(c)) print_chars[i] = c; c = guest_to_host(c); if (isprint(c)) print_chars[i] = c; } else { logmsg(" "); } offset++; if ((offset & 3) == 0) { logmsg(" "); } } /* end for(i) */ logmsg(" %s\n", print_chars); } /* end for(offset) */ } /* end function packet_trace */ #else #define packet_trace( _addr, _len) #endif #if 1 struct sockaddr_in * get_inet_socket(char *host_serv) { char *host = NULL; char *serv; struct sockaddr_in *sin; if((serv = strchr(host_serv,':'))) { *serv++ = '\0'; if(*host_serv) host = host_serv; } else serv = host_serv; if(!(sin = malloc(sizeof(struct sockaddr_in)))) return sin; sin->sin_family = AF_INET; if(host) { struct hostent *hostent; hostent = gethostbyname(host); if(!hostent) { logmsg(_("HHCGI001I Unable to determine IP address from %s\n"), host); free(sin); return NULL; } memcpy(&sin->sin_addr,*hostent->h_addr_list,sizeof(sin->sin_addr)); } else sin->sin_addr.s_addr = INADDR_ANY; if(serv) { if(!isdigit(*serv)) { struct servent *servent; servent = getservbyname(serv, "tcp"); if(!servent) { logmsg(_("HHCGI002I Unable to determine port number from %s\n"), host); free(sin); return NULL; } sin->sin_port = servent->s_port; } else sin->sin_port = htons(atoi(serv)); } else { logmsg(_("HHCGI003E Invalid parameter: %s\n"), host_serv); free(sin); return NULL; } return sin; } #endif /*-------------------------------------------------------------------*/ /* SUBROUTINE TO REMOVE ANY IAC SEQUENCES FROM THE DATA STREAM */ /* Returns the new length after deleting IAC commands */ /*-------------------------------------------------------------------*/ static int remove_iac (BYTE *buf, int len) { int m, n, c; for (m=0, n=0; m < len; ) { /* Interpret IAC commands */ if (buf[m] == IAC) { /* Treat IAC in last byte of buffer as IAC NOP */ c = (++m < len)? buf[m++] : NOP; /* Process IAC command */ switch (c) { case IAC: /* Insert single IAC in buffer */ buf[n++] = IAC; break; case BRK: /* Set ATTN indicator */ break; case IP: /* Set SYSREQ indicator */ break; case WILL: /* Skip option negotiation command */ case WONT: case DO: case DONT: m++; break; case SB: /* Skip until IAC SE sequence found */ for (; m < len; m++) { if (buf[m] != IAC) continue; if (++m >= len) break; if (buf[m] == SE) { m++; break; } } /* end for */ default: /* Ignore NOP or unknown command */ break; } /* end switch(c) */ } else { /* Copy data bytes */ if (n < m) buf[n] = buf[m]; m++; n++; } } /* end for */ if (n < m) { TNSDEBUG3("console: DBG001: %d IAC bytes removed, newlen=%d\n", m-n, n); packet_trace (buf, n); } return n; } /* end function remove_iac */ /*-------------------------------------------------------------------*/ /* SUBROUTINE TO DOUBLE UP ANY IAC BYTES IN THE DATA STREAM */ /* Returns the new length after inserting extra IAC bytes */ /*-------------------------------------------------------------------*/ static int double_up_iac (BYTE *buf, int len) { int m, n, x, newlen; /* Count the number of IAC bytes in the data */ for (x=0, n=0; n < len; n++) if (buf[n] == IAC) x++; /* Exit if nothing to do */ if (x == 0) return len; /* Insert extra IAC bytes backwards from the end of the buffer */ newlen = len + x; TNSDEBUG3("console: DBG002: %d IAC bytes added, newlen=%d\n", x, newlen); for (n=newlen, m=len; n > m; ) { buf[--n] = buf[--m]; if (buf[n] == IAC) buf[--n] = IAC; } packet_trace (buf, newlen); return newlen; } /* end function double_up_iac */ /*-------------------------------------------------------------------*/ /* SUBROUTINE TO TRANSLATE A NULL-TERMINATED STRING TO EBCDIC */ /*-------------------------------------------------------------------*/ static BYTE * translate_to_ebcdic (char *str) { int i; /* Array subscript */ BYTE c; /* Character work area */ for (i = 0; str[i] != '\0'; i++) { c = str[i]; str[i] = (isprint(c) ? host_to_guest(c) : SPACE); } return (BYTE *)str; } /* end function translate_to_ebcdic */ /*-------------------------------------------------------------------*/ /* SUBROUTINE TO SEND A DATA PACKET TO THE CLIENT */ /*-------------------------------------------------------------------*/ static int send_packet (int csock, BYTE *buf, int len, char *caption) { int rc; /* Return code */ if (caption != NULL) { TNSDEBUG2("console: DBG003: Sending %s\n", caption); packet_trace (buf, len); } rc = send (csock, buf, len, 0); if (rc < 0) { TNSERROR("console: DBG021: send: %s\n", strerror(HSO_errno)); return -1; } /* end if(rc) */ return 0; } /* end function send_packet */ /*-------------------------------------------------------------------*/ /* SUBROUTINE TO RECEIVE A DATA PACKET FROM THE CLIENT */ /* This subroutine receives bytes from the client. It stops when */ /* the receive buffer is full, or when the last two bytes received */ /* consist of the IAC character followed by a specified delimiter. */ /* If zero bytes are received, this means the client has closed the */ /* connection, and this is treated as an error. */ /* Input: */ /* csock is the socket number */ /* buf points to area to receive data */ /* reqlen is the number of bytes requested */ /* delim is the delimiter character (0=no delimiter) */ /* Output: */ /* buf is updated with data received */ /* The return value is the number of bytes received, or */ /* -1 if an error occurred. */ /*-------------------------------------------------------------------*/ static int recv_packet (int csock, BYTE *buf, int reqlen, BYTE delim) { int rc=0; /* Return code */ int rcvlen=0; /* Length of data received */ while (rcvlen < reqlen) { rc = recv (csock, buf + rcvlen, reqlen - rcvlen, 0); if (rc < 0) { TNSERROR("console: DBG022: recv: %s\n", strerror(HSO_errno)); return -1; } if (rc == 0) { TNSDEBUG1("console: DBG004: Connection closed by client\n"); return -1; } rcvlen += rc; if (delim != '\0' && rcvlen >= 2 && buf[rcvlen-2] == IAC && buf[rcvlen-1] == delim) break; } TNSDEBUG2("console: DBG005: Packet received length=%d\n", rcvlen); packet_trace (buf, rcvlen); return rcvlen; } /* end function recv_packet */ /*-------------------------------------------------------------------*/ /* SUBROUTINE TO RECEIVE A PACKET AND COMPARE WITH EXPECTED VALUE */ /*-------------------------------------------------------------------*/ static int expect (int csock, BYTE *expected, int len, char *caption) { int rc; /* Return code */ BYTE buf[512]; /* Receive buffer */ #if 1 /* TCP/IP for MVS returns the server sequence rather then the client sequence during bin negotiation 19/06/00 Jan Jaeger */ static BYTE do_bin[] = { IAC, DO, BINARY, IAC, WILL, BINARY }; static BYTE will_bin[] = { IAC, WILL, BINARY, IAC, DO, BINARY }; #endif UNREFERENCED(caption); rc = recv_packet (csock, buf, len, 0); if (rc < 0) return -1; #if 1 /* TCP/IP FOR MVS DOES NOT COMPLY TO RFC 1576 THIS IS A BYPASS */ if(memcmp(buf, expected, len) != 0 && !(len == sizeof(will_bin) && memcmp(expected, will_bin, len) == 0 && memcmp(buf, do_bin, len) == 0) ) #else if (memcmp(buf, expected, len) != 0) #endif { TNSDEBUG2("console: DBG006: Expected %s\n", caption); return -1; } TNSDEBUG2("console: DBG007: Received %s\n", caption); return 0; } /* end function expect */ /*-------------------------------------------------------------------*/ /* SUBROUTINE TO NEGOTIATE TELNET PARAMETERS */ /* This subroutine negotiates the terminal type with the client */ /* and uses the terminal type to determine whether the client */ /* is to be supported as a 3270 display console or as a 1052/3215 */ /* printer-keyboard console. */ /* */ /* Valid display terminal types are "IBM-NNNN", "IBM-NNNN-M", and */ /* "IBM-NNNN-M-E", where NNNN is 3270, 3277, 3278, 3279, 3178, 3179, */ /* or 3180, M indicates the screen size (2=25x80, 3=32x80, 4=43x80, */ /* 5=27x132, X=determined by Read Partition Query command), and */ /* -E is an optional suffix indicating that the terminal supports */ /* extended attributes. Displays are negotiated into tn3270 mode. */ /* An optional device number suffix (example: IBM-3270@01F) may */ /* be specified to request allocation to a specific device number. */ /* Valid 3270 printer type is "IBM-3287-1" */ /* */ /* Terminal types whose first four characters are not "IBM-" are */ /* handled as printer-keyboard consoles using telnet line mode. */ /* */ /* Input: */ /* csock Socket number for client connection */ /* Output: */ /* class D=3270 display console, K=printer-keyboard console */ /* P=3270 printer */ /* model 3270 model indicator (2,3,4,5,X) */ /* extatr 3270 extended attributes (Y,N) */ /* devn Requested device number, or FFFF=any device number */ /* Return value: */ /* 0=negotiation successful, -1=negotiation error */ /*-------------------------------------------------------------------*/ static int negotiate(int csock, BYTE *class, BYTE *model, BYTE *extatr, U16 *devn,char *group) { int rc; /* Return code */ char *termtype; /* Pointer to terminal type */ char *s; /* String pointer */ BYTE c; /* Trailing character */ U16 devnum; /* Requested device number */ BYTE buf[512]; /* Telnet negotiation buffer */ static BYTE do_term[] = { IAC, DO, TERMINAL_TYPE }; static BYTE will_term[] = { IAC, WILL, TERMINAL_TYPE }; static BYTE req_type[] = { IAC, SB, TERMINAL_TYPE, SEND, IAC, SE }; static BYTE type_is[] = { IAC, SB, TERMINAL_TYPE, IS }; static BYTE do_eor[] = { IAC, DO, EOR, IAC, WILL, EOR }; static BYTE will_eor[] = { IAC, WILL, EOR, IAC, DO, EOR }; static BYTE do_bin[] = { IAC, DO, BINARY, IAC, WILL, BINARY }; static BYTE will_bin[] = { IAC, WILL, BINARY, IAC, DO, BINARY }; #if 0 static BYTE do_tmark[] = { IAC, DO, TIMING_MARK }; static BYTE will_tmark[] = { IAC, WILL, TIMING_MARK }; static BYTE wont_sga[] = { IAC, WONT, SUPPRESS_GA }; static BYTE dont_sga[] = { IAC, DONT, SUPPRESS_GA }; #endif static BYTE wont_echo[] = { IAC, WONT, ECHO_OPTION }; static BYTE dont_echo[] = { IAC, DONT, ECHO_OPTION }; static BYTE will_naws[] = { IAC, WILL, NAWS }; /* Perform terminal-type negotiation */ rc = send_packet (csock, do_term, sizeof(do_term), "IAC DO TERMINAL_TYPE"); if (rc < 0) return -1; rc = expect (csock, will_term, sizeof(will_term), "IAC WILL TERMINAL_TYPE"); if (rc < 0) return -1; /* Request terminal type */ rc = send_packet (csock, req_type, sizeof(req_type), "IAC SB TERMINAL_TYPE SEND IAC SE"); if (rc < 0) return -1; rc = recv_packet (csock, buf, sizeof(buf)-2, SE); if (rc < 0) return -1; /* Ignore Negotiate About Window Size */ if (rc >= (int)sizeof(will_naws) && memcmp (buf, will_naws, sizeof(will_naws)) == 0) { memmove(buf, &buf[sizeof(will_naws)], (rc - sizeof(will_naws))); rc -= sizeof(will_naws); } if (rc < (int)(sizeof(type_is) + 2) || memcmp(buf, type_is, sizeof(type_is)) != 0 || buf[rc-2] != IAC || buf[rc-1] != SE) { TNSDEBUG2("console: DBG008: Expected IAC SB TERMINAL_TYPE IS\n"); return -1; } buf[rc-2] = '\0'; termtype = (char *)(buf + sizeof(type_is)); TNSDEBUG2("console: DBG009: Received IAC SB TERMINAL_TYPE IS %s IAC SE\n", termtype); /* Check terminal type string for device name suffix */ s = strchr (termtype, '@'); if(s!=NULL) { if(strlen(s)<16) { strlcpy(group,&s[1],16); } } else { group[0]=0; } if (s != NULL && sscanf (s, "@%hx%c", &devnum,&c) == 1) { *devn = devnum; group[0]=0; } else { *devn = 0xFFFF; } /* Test for non-display terminal type */ if (memcmp(termtype, "IBM-", 4) != 0) { #if 0 /* Perform line mode negotiation */ rc = send_packet (csock, do_tmark, sizeof(do_tmark), "IAC DO TIMING_MARK"); if (rc < 0) return -1; rc = expect (csock, will_tmark, sizeof(will_tmark), "IAC WILL TIMING_MARK"); if (rc < 0) return 0; rc = send_packet (csock, wont_sga, sizeof(wont_sga), "IAC WONT SUPPRESS_GA"); if (rc < 0) return -1; rc = expect (csock, dont_sga, sizeof(dont_sga), "IAC DONT SUPPRESS_GA"); if (rc < 0) return -1; #endif if (memcmp(termtype, "ANSI", 4) == 0) { rc = send_packet (csock, wont_echo, sizeof(wont_echo), "IAC WONT ECHO"); if (rc < 0) return -1; rc = expect (csock, dont_echo, sizeof(dont_echo), "IAC DONT ECHO"); if (rc < 0) return -1; } /* Return printer-keyboard terminal class */ *class = 'K'; *model = '-'; *extatr = '-'; return 0; } /* Determine display terminal model */ if (memcmp(termtype+4,"DYNAMIC",7) == 0) { *model = 'X'; *extatr = 'Y'; } else { if (!(memcmp(termtype+4, "3277", 4) == 0 || memcmp(termtype+4, "3270", 4) == 0 || memcmp(termtype+4, "3178", 4) == 0 || memcmp(termtype+4, "3278", 4) == 0 || memcmp(termtype+4, "3179", 4) == 0 || memcmp(termtype+4, "3180", 4) == 0 || memcmp(termtype+4, "3287", 4) == 0 || memcmp(termtype+4, "3279", 4) == 0)) return -1; *model = '2'; *extatr = 'N'; if (termtype[8]=='-') { if (termtype[9] < '1' || termtype[9] > '5') return -1; *model = termtype[9]; if (memcmp(termtype+4, "328",3) == 0) *model = '2'; if (memcmp(termtype+10, "-E", 2) == 0) *extatr = 'Y'; } } /* Perform end-of-record negotiation */ rc = send_packet (csock, do_eor, sizeof(do_eor), "IAC DO EOR IAC WILL EOR"); if (rc < 0) return -1; rc = expect (csock, will_eor, sizeof(will_eor), "IAC WILL EOR IAC DO EOR"); if (rc < 0) return -1; /* Perform binary negotiation */ rc = send_packet (csock, do_bin, sizeof(do_bin), "IAC DO BINARY IAC WILL BINARY"); if (rc < 0) return -1; rc = expect (csock, will_bin, sizeof(will_bin), "IAC WILL BINARY IAC DO BINARY"); if (rc < 0) return -1; /* Return display terminal class */ if (memcmp(termtype+4,"3287",4)==0) *class='P'; else *class = 'D'; return 0; } /* end function negotiate */ /*-------------------------------------------------------------------*/ /* NEW CLIENT CONNECTION */ /*-------------------------------------------------------------------*/ static int connect_client (int *csockp) /* returns 1 if 3270, else 0 */ { int rc; /* Return code */ size_t len; /* Data length */ int csock; /* Socket for conversation */ struct sockaddr_in client; /* Client address structure */ socklen_t namelen; /* Length of client structure*/ char *clientip; /* Addr of client ip address */ U16 devnum; /* Requested device number */ BYTE class; /* D=3270, P=3287, K=3215/1052 */ BYTE model; /* 3270 model (2,3,4,5,X) */ BYTE extended; /* Extended attributes (Y,N) */ char buf[256]; /* Message buffer */ char conmsg[256]; /* Connection message */ char devmsg[25]; /* Device message */ char hostmsg[256]; /* Host ID message */ char num_procs[16]; /* #of processors string */ char group[16]; /* Console group */ /* Load the socket address from the thread parameter */ csock = *csockp; /* Obtain the client's IP address */ namelen = sizeof(client); rc = getpeername (csock, (struct sockaddr *)&client, &namelen); /* Log the client's IP address and hostname */ clientip = strdup(inet_ntoa(client.sin_addr)); #if 0 // The following isn't really needed and hangs under unusual // network configuration settings and thus has been removed. { struct hostent* pHE; /* Addr of hostent structure */ char* clientname; /* Addr of client hostname */ pHE = gethostbyaddr ((unsigned char*)(&client.sin_addr), sizeof(client.sin_addr), AF_INET); if (pHE != NULL && pHE->h_name != NULL && pHE->h_name[0] != '\0') { clientname = (char*) pHE->h_name; } else { clientname = "host name unknown"; } TNSDEBUG1("console: DBG018: Received connection from %s (%s)\n", clientip, clientname); } #else TNSDEBUG1("console: DBG018: Received connection from %s\n", clientip ); #endif /* Negotiate telnet parameters */ rc = negotiate (csock, &class, &model, &extended, &devnum, group); if (rc != 0) { close_socket (csock); if (clientip) free(clientip); return 0; } /* Build connection message for client */ if ( cons_hostinfo.num_procs > 1 ) snprintf( num_procs, sizeof(num_procs), "MP=%d", cons_hostinfo.num_procs ); else strlcpy( num_procs, "UP", sizeof(num_procs) ); snprintf ( hostmsg, sizeof(hostmsg), "running on %s (%s-%s.%s %s %s)" ,cons_hostinfo.nodename ,cons_hostinfo.sysname ,cons_hostinfo.release ,cons_hostinfo.version ,cons_hostinfo.machine ,num_procs ); snprintf (conmsg, sizeof(conmsg), "Hercules version %s built on %s %s", VERSION, __DATE__, __TIME__); { snprintf (devmsg, sizeof(devmsg), "Connected to device %4.4X", 0); } logmsg (_("HHCTE009I Client %s connected to %4.4X device %4.4X\n"), clientip, 0x3270, 0); /* Send connection message to client */ if (class != 'K') { len = snprintf (buf, sizeof(buf), "\xF5\x40\x11\x40\x40\x1D\x60%s" "\x11\xC1\x50\x1D\x60%s" "\x11\xC2\x60\x1D\x60%s", translate_to_ebcdic(conmsg), translate_to_ebcdic(hostmsg), translate_to_ebcdic(devmsg)); if (len < sizeof(buf)) { buf[len++] = IAC; } else { ASSERT(FALSE); } if (len < sizeof(buf)) { buf[len++] = EOR_MARK; } else { ASSERT(FALSE); } } else { len = snprintf (buf, sizeof(buf), "%s\r\n%s\r\n%s\r\n", conmsg, hostmsg, devmsg); } if (class != 'P') /* do not write connection resp on 3287 */ { rc = send_packet (csock, (BYTE *)buf, len, "CONNECTION RESPONSE"); } return (class == 'D') ? 1 : 0; /* return 1 if 3270 */ } /* end function connect_client */ static void logdump(char *txt,DEVBLK *dev,BYTE *bfr,size_t sz) { size_t i; if(!dev->ccwtrace) { return; } logmsg(_("HHCCA300D %4.4X:%s\n"), dev->devnum, txt); logmsg(_("HHCCA300D %4.4X:%s : Dump of %d (%x) byte(s)\n"),dev->devnum,txt,sz,sz); for(i=0;idevnum,txt,i); } if(i%4==0) { logmsg(" "); } logmsg("%2.2X",bfr[i]); } logmsg("\nHHCCA300D "); for(i=0;ipoolarea = (BYTE*)calloc (numbufs, bufsize); if (!ca->poolarea) { return; } areap = ca->poolarea; for (i1 = 0; i1 < numbufs; i1++) { put_bufpool(&ca->freeq, areap); areap += (bufsize); } } static void free_bufpool(COMMADPT *ca) { ca->sendq = 0; ca->freeq = 0; if (ca->poolarea) { free(ca->poolarea); ca->poolarea = 0; } } /*-------------------------------------------------------------------*/ /* Free all private structures and buffers */ /*-------------------------------------------------------------------*/ static void commadpt_clean_device(DEVBLK *dev) { if(dev->commadpt!=NULL) { free(dev->commadpt); dev->commadpt=NULL; if(dev->ccwtrace) { logmsg(_("HHCCA300D %4.4X:clean : Control block freed\n"), dev->devnum); } } else { if(dev->ccwtrace) { logmsg(_("HHCCA300D %4.4X:clean : Control block not freed : not allocated\n"),dev->devnum); } } return; } /*-------------------------------------------------------------------*/ /* Allocate initial private structures */ /*-------------------------------------------------------------------*/ static int commadpt_alloc_device(DEVBLK *dev) { dev->commadpt=malloc(sizeof(COMMADPT)); if(dev->commadpt==NULL) { logmsg(_("HHCCA020E %4.4X:Memory allocation failure for main control block\n"), dev->devnum); return -1; } memset(dev->commadpt,0,sizeof(COMMADPT)); dev->commadpt->dev=dev; return 0; } /*-------------------------------------------------------------------*/ /* Parsing utilities */ /*-------------------------------------------------------------------*/ /*-------------------------------------------------------------------*/ /* commadpt_getport : returns a port number or -1 */ /*-------------------------------------------------------------------*/ static int commadpt_getport(char *txt) { int pno; struct servent *se; pno=atoi(txt); if(pno==0) { se=getservbyname(txt,"tcp"); if(se==NULL) { return -1; } pno=se->s_port; } return(pno); } /*-------------------------------------------------------------------*/ /* commadpt_getaddr : set an in_addr_t if ok, else return -1 */ /*-------------------------------------------------------------------*/ static int commadpt_getaddr(in_addr_t *ia,char *txt) { struct hostent *he; he=gethostbyname(txt); if(he==NULL) { return(-1); } memcpy(ia,he->h_addr_list[0],4); return(0); } static void connect_message(int sfd, int na, int flag) { int rc; struct sockaddr_in client; socklen_t namelen; char *ipaddr; char msgtext[256]; if (!sfd) return; namelen = sizeof(client); rc = getpeername (sfd, (struct sockaddr *)&client, &namelen); ipaddr = inet_ntoa(client.sin_addr); if (flag == 0) sprintf(msgtext, "%s:%d VTAM CONNECTION ACCEPTED - NETWORK NODE= %4.4X", ipaddr, (int)ntohs(client.sin_port), na); else sprintf(msgtext, "%s:%d VTAM CONNECTION TERMINATED", ipaddr, (int)ntohs(client.sin_port)); logmsg( _("%s\n"), msgtext); write(sfd, msgtext, strlen(msgtext)); write(sfd, "\r\n", 2); } static void commadpt_read_tty(COMMADPT *ca, BYTE * bfr, int len) // everything has been tortured to now do 3270 also { BYTE bfr3[3]; BYTE c; int i1; int eor=0; logdump("RECV",ca->dev, bfr,len); /* If there is a complete data record already in the buffer then discard it before reading more data For TTY, allow data to accumulate until CR is received */ if (ca->is_3270) { if (ca->inpbufl) { ca->rlen3270 = 0; ca->inpbufl = 0; } } for (i1 = 0; i1 < len; i1++) { c = (unsigned char) bfr[i1]; if (ca->telnet_opt) { ca->telnet_opt = 0; if(ca->dev->ccwtrace) logmsg(_("HHCCA300D %4.4X: Received TELNET CMD 0x%02x 0x%02x\n"), ca->dev->devnum, ca->telnet_cmd, c); bfr3[0] = 0xff; /* IAC */ /* set won't/don't for all received commands */ bfr3[1] = (ca->telnet_cmd == 0xfd) ? 0xfc : 0xfe; bfr3[2] = c; if (ca->sfd > 0) { write_socket(ca->sfd,bfr3,3); } if(ca->dev->ccwtrace) logmsg(_("HHCCA300D %4.4X: Sending TELNET CMD 0x%02x 0x%02x\n"), ca->dev->devnum, bfr3[1], bfr3[2]); continue; } if (ca->telnet_iac) { ca->telnet_iac = 0; if(ca->dev->ccwtrace) logmsg(_("HHCCA300D %4.4X: Received TELNET IAC 0x%02x\n"), ca->dev->devnum, c); switch (c) { case 0xFB: /* TELNET WILL option cmd */ case 0xFD: /* TELNET DO option cmd */ ca->telnet_opt = 1; ca->telnet_cmd = c; break; case 0xF4: /* TELNET interrupt */ if (!ca->telnet_int) { ca->telnet_int = 1; } break; case EOR_MARK: eor = 1; break; case 0xFF: /* IAC IAC */ ca->inpbuf[ca->rlen3270++] = 0xFF; break; } continue; } if (c == 0xFF) { /* TELNET IAC */ ca->telnet_iac = 1; continue; } else { ca->telnet_iac = 0; } if (!ca->is_3270) { if (c == 0x0D) // CR in TTY mode ? ca->eol_flag = 1; c = host_to_guest(c); // translate ASCII to EBCDIC for tty } ca->inpbuf[ca->rlen3270++] = c; } /* received data (rlen3270 > 0) is sufficient for 3270, but for TTY, eol_flag must also be set */ if ((ca->eol_flag || ca->is_3270) && ca->rlen3270) { ca->eol_flag = 0; if (ca->is_3270) { if (eor) { ca->inpbufl = remove_iac(ca->inpbuf, ca->rlen3270); ca->rlen3270 = 0; /* for next msg */ } } else { ca->inpbufl = ca->rlen3270; ca->rlen3270 = 0; /* for next msg */ } if(ca->dev->ccwtrace) logmsg(_("%4.4X: posted %d input bytes\n"),ca->dev->devnum,ca->inpbufl); } } static void *telnet_thread(void *vca) { COMMADPT *ca; int devnum; /* device number copy for convenience*/ int sockopt; /* Used for setsocketoption */ int ca_shutdown=0; /* Thread shutdown internal flag */ int rc; /* return code from various rtns */ struct sockaddr_in sin; /* bind socket address structure */ BYTE bfr[256]; ca=(COMMADPT*)vca; /* get a work copy of devnum (for messages) */ ca->sfd = 0; devnum=ca->devnum; ca->lfd=socket(AF_INET,SOCK_STREAM,0); if(!socket_is_socket(ca->lfd)) { logmsg(_("HHCCA003E %4.4X:Cannot obtain socket for incoming calls : %s\n"),devnum,strerror(HSO_errno)); ca->have_cthread=0; release_lock(&ca->lock); return NULL; } /* Reuse the address regardless of any */ /* spurious connection on that port */ sockopt=1; setsockopt(ca->lfd,SOL_SOCKET,SO_REUSEADDR,(GETSET_SOCKOPT_T*)&sockopt,sizeof(sockopt)); /* Bind the socket */ sin.sin_family=AF_INET; sin.sin_addr.s_addr=ca->lhost; sin.sin_port=htons(ca->lport); while(1) { rc=bind(ca->lfd,(struct sockaddr *)&sin,sizeof(sin)); if(rc<0) { logmsg(_("HHCCA018E %4.4X:Bind failed : %s\n"),devnum,strerror(HSO_errno)); ca_shutdown=1; break; } else { break; } } /* Start the listen */ if(!ca_shutdown) { listen(ca->lfd,10); logmsg(_("HHCCA005I %4.4X:Listening on port %d for incoming TCP connections\n"), devnum, ca->lport); } for (;;) { ca->sfd = 0; ca->sfd=accept(ca->lfd,NULL,0); if (ca->sfd < 1) continue; if (connect_client(&ca->sfd)) { ca->is_3270 = 1; } else { ca->is_3270 = 0; } socket_set_blocking_mode(ca->sfd,0); // set to non-blocking mode make_sna_requests4(ca, 0, (ca->is_3270) ? 0x02 : 0x01); // send REQCONT ca->hangup = 0; for (;;) { usleep(50000); if (ca->hangup) break; /* read_socket has changed from 3.04 to 3.06 - we need old way */ #ifdef _MSVC_ rc=recv(ca->sfd,bfr,256-BUFPD,0); #else rc=read(ca->sfd,bfr,256-BUFPD); #endif if (rc < 0) { if(0 #ifndef WIN32 || EAGAIN == errno #endif || HSO_EWOULDBLOCK == HSO_errno ) { continue; } break; // make_sna_requests4(ca, 1); // send REQDISCONT make_sna_requests5(ca); } if (rc == 0) { // make_sna_requests4(ca, 1); // send REQDISCONT make_sna_requests5(ca); break; } commadpt_read_tty(ca,bfr,rc); } close_socket(ca->sfd); ca->sfd = 0; } } /*-------------------------------------------------------------------*/ /* Communication Thread main loop */ /*-------------------------------------------------------------------*/ static void *commadpt_thread(void *vca) { COMMADPT *ca; /* Work CA Control Block Pointer */ int devnum; /* device number copy for convenience*/ int rc; /* return code from various rtns */ int ca_shutdown; /* Thread shutdown internal flag */ int init_signaled; /* Thread initialisation signaled */ /*---------------------END OF DECLARES---------------------------*/ /* fetch the commadpt structure */ ca=(COMMADPT *)vca; /* Obtain the CA lock */ obtain_lock(&ca->lock); /* get a work copy of devnum (for messages) */ devnum=ca->devnum; /* reset shutdown flag */ ca_shutdown=0; init_signaled=0; logmsg(_("HHCCA002I %4.4X:3705 Communication thread "TIDPAT" started\n"),devnum,thread_id()); for (;;) { release_lock(&ca->lock); usleep(50000 + (ca->unack_attn_count * 100000)); obtain_lock(&ca->lock); make_sna_requests2(ca); make_sna_requests3(ca); if (ca->sendq // attempt to fix hot i/o bug && ca->unack_attn_count < 6 ) { ca->unack_attn_count++; rc = device_attention(ca->dev, CSW_ATTN); if(ca->dev->ccwtrace) logmsg(_("%4.4X: Raised attention rc = %d\n"), ca->dev->devnum, rc); } } logmsg(_("HHCCA009I %4.4X:3705 utility thread terminated\n"),ca->devnum); release_lock(&ca->lock); return NULL; } /*-------------------------------------------------------------------*/ /* Halt currently executing I/O command */ /*-------------------------------------------------------------------*/ static void commadpt_halt(DEVBLK *dev) { if(!dev->busy) { return; } } /* The following 3 MSG functions ensure only 1 (one) */ /* hardcoded instance exist for the same numbered msg */ /* that is issued on multiple situations */ static void msg013e(DEVBLK *dev,char *kw,char *kv) { logmsg(_("HHCCA013E %4.4X:Incorrect %s specification %s\n"),dev->devnum,kw,kv); } /*-------------------------------------------------------------------*/ /* Device Initialisation */ /*-------------------------------------------------------------------*/ static int commadpt_init_handler (DEVBLK *dev, int argc, char *argv[]) { char thread_name[32]; char thread_name2[32]; int i; int rc; int pc; /* Parse code */ int errcnt; struct in_addr in_temp; int etospec; /* ETO= Specified */ union { int num; char text[80]; } res; dev->devtype=0x3705; if(dev->ccwtrace) { logmsg(_("HHCCA300D %4.4X:Initialisation starting\n"),dev->devnum); } if(dev->commadpt!=NULL) { commadpt_clean_device(dev); } rc=commadpt_alloc_device(dev); if(rc<0) { logmsg(_("HHCCA010I %4.4X:initialisation not performed\n"), dev->devnum); return(-1); } if(dev->ccwtrace) { logmsg(_("HHCCA300D %4.4X:Initialisation : Control block allocated\n"),dev->devnum); } errcnt=0; /* * Initialise ports & hosts */ dev->commadpt->sfd=-1; dev->commadpt->lport=0; dev->commadpt->debug_sna=0; etospec=0; for(i=0;idevnum,argv[i]); errcnt++; continue; } if(pc==0) { logmsg(_("HHCCA012E %4.4X:Unrecognized parameter %s\n"),dev->devnum,argv[i]); errcnt++; continue; } switch(pc) { case COMMADPT_KW_DEBUG: if (res.text[0] == 'y' || res.text[0] == 'Y') dev->commadpt->debug_sna = 1; else dev->commadpt->debug_sna = 0; break; case COMMADPT_KW_LPORT: rc=commadpt_getport(res.text); if(rc<0) { errcnt++; msg013e(dev,"LPORT",res.text); break; } dev->commadpt->lport=rc; break; case COMMADPT_KW_LHOST: if(strcmp(res.text,"*")==0) { dev->commadpt->lhost=INADDR_ANY; break; } rc=commadpt_getaddr(&dev->commadpt->lhost,res.text); if(rc!=0) { msg013e(dev,"LHOST",res.text); errcnt++; } break; default: break; } } if(errcnt>0) { logmsg(_("HHCCA021I %4.4X:Initialisation failed due to previous errors\n"),dev->devnum); return -1; } in_temp.s_addr=dev->commadpt->lhost; dev->bufsize=256; dev->numsense=2; memset(dev->sense,0,sizeof(dev->sense)); init_bufpool(dev->commadpt); dev->commadpt->devnum=dev->devnum; /* Initialize the CA lock */ initialize_lock(&dev->commadpt->lock); /* Initialise thread->I/O & halt initiation EVB */ initialize_condition(&dev->commadpt->ipc); initialize_condition(&dev->commadpt->ipc_halt); /* Allocate I/O -> Thread signaling pipe */ create_pipe(dev->commadpt->pipe); /* Point to the halt routine for HDV/HIO/HSCH handling */ dev->halt_device=commadpt_halt; /* Obtain the CA lock */ obtain_lock(&dev->commadpt->lock); /* Start the telnet worker thread */ /* Set thread-name for debugging purposes */ snprintf(thread_name2,sizeof(thread_name2), "commadpt %4.4X thread2",dev->devnum); thread_name2[sizeof(thread_name2)-1]=0; if(create_thread(&dev->commadpt->tthread,&sysblk.detattr,telnet_thread,dev->commadpt,thread_name2)) { logmsg(D_("HHCCA022E create_thread: %s\n"),strerror(errno)); release_lock(&dev->commadpt->lock); return -1; } /* Start the async worker thread */ /* Set thread-name for debugging purposes */ snprintf(thread_name,sizeof(thread_name), "commadpt %4.4X thread",dev->devnum); thread_name[sizeof(thread_name)-1]=0; if(create_thread(&dev->commadpt->cthread,&sysblk.detattr,commadpt_thread,dev->commadpt,thread_name)) { logmsg(D_("HHCCA022E create_thread: %s\n"),strerror(errno)); release_lock(&dev->commadpt->lock); return -1; } dev->commadpt->have_cthread=1; /* Release the CA lock */ release_lock(&dev->commadpt->lock); /* Indicate succesfull completion */ return 0; } /*-------------------------------------------------------------------*/ /* Query the device definition */ /*-------------------------------------------------------------------*/ static void commadpt_query_device (DEVBLK *dev, char **class, int buflen, char *buffer) { *class = "LINE"; snprintf(buffer,buflen,"Read count=%d, Write count=%d", dev->commadpt->read_ccw_count, dev->commadpt->write_ccw_count); } /*-------------------------------------------------------------------*/ /* Close the device */ /* Invoked by HERCULES shutdown & DEVINIT processing */ /*-------------------------------------------------------------------*/ static int commadpt_close_device ( DEVBLK *dev ) { if(dev->ccwtrace) { logmsg(_("HHCCA300D %4.4X:Closing down\n"),dev->devnum); } /* Obtain the CA lock */ obtain_lock(&dev->commadpt->lock); /* Terminate current I/O thread if necessary */ if(dev->busy) { commadpt_halt(dev); } free_bufpool(dev->commadpt); /* release the CA lock */ release_lock(&dev->commadpt->lock); /* Free all work storage */ commadpt_clean_device(dev); /* Indicate to hercules the device is no longer opened */ dev->fd=-1; if(dev->ccwtrace) { logmsg(_("HHCCA300D %4.4X:Closed down\n"),dev->devnum); } return 0; } void make_seq (COMMADPT * ca, BYTE * reqptr) { if (reqptr[4] == 0x38) { reqptr[6] = (unsigned char)(++ca->ncpa_sscp_seqn >> 8) & 0xff; reqptr[7] = (unsigned char)( ca->ncpa_sscp_seqn ) & 0xff; } else { reqptr[6] = (unsigned char)(++ca->ncpb_sscp_seqn >> 8) & 0xff; reqptr[7] = (unsigned char)( ca->ncpb_sscp_seqn ) & 0xff; } } static void format_sna (BYTE * requestp, char * tag, int devnum) { char fmtbuf[32]; char fmtbuf2[32]; char fmtbuf3[32]; char fmtbuf4[32]; char fmtbuf5[256]; char fmtbuf6[32]; char *ru_type=""; int len; sprintf(fmtbuf, "%02X%02X %02X%02X %02X%02X %02X%02X %02X%02X", requestp[0], requestp[1], requestp[2], requestp[3], requestp[4], requestp[5], requestp[6], requestp[7], requestp[8], requestp[9]); sprintf(fmtbuf2, "%02X%02X%02X", requestp[10], requestp[11], requestp[12]); len = (requestp[8] << 8) + requestp[9]; len -= 3; /* for len of ru only */ sprintf(fmtbuf3, "%02X", requestp[13]); sprintf(fmtbuf4, "%02X", requestp[14]); if (len > 1) strcat(fmtbuf3, fmtbuf4); sprintf(fmtbuf4, "%02X", requestp[15]); if (len > 2) strcat(fmtbuf3, fmtbuf4); if (requestp[13] == 0x11) ru_type = "ACTPU"; if (requestp[13] == 0x0D) ru_type = "ACTLU"; if (requestp[13] == 0x0E) ru_type = "DACTLU"; if (requestp[13] == 0x12) ru_type = "DACTPU"; if (requestp[13] == 0xA0) ru_type = "SDT"; if (requestp[13] == 0x31) ru_type = "BIND"; if (requestp[13] == 0x32) ru_type = "UNBIND"; if (!memcmp(&requestp[13], R010201, 3)) ru_type = "CONTACT"; if (!memcmp(&requestp[13], R010202, 3)) ru_type = "DISCONTACT"; if (!memcmp(&requestp[13], R010203, 3)) ru_type = "IPLINIT"; if (!memcmp(&requestp[13], R010204, 3)) ru_type = "IPLTEXT"; if (!memcmp(&requestp[13], R010205, 3)) ru_type = "IPLFINAL"; if (!memcmp(&requestp[13], R01020A, 3)) ru_type = "ACTLINK"; if (!memcmp(&requestp[13], R01020B, 3)) ru_type = "DACTLINK"; if (!memcmp(&requestp[13], R010211, 3)) { sprintf(fmtbuf6, "%s[%02x]", "SETCV", requestp[18]); ru_type = fmtbuf6; if ((requestp[10] & 0x80) != 0) ru_type = "SETCV"; } if (!memcmp(&requestp[13], R010280, 3)) ru_type = "CONTACTED"; if (!memcmp(&requestp[13], R010281, 3)) ru_type = "INOP"; if (!memcmp(&requestp[13], R010284, 3)) ru_type = "REQCONT"; if (!memcmp(&requestp[13], R01021B, 3)) ru_type = "REQDISCONT"; if (!memcmp(&requestp[13], R01021A, 3)) ru_type = "FNA"; if (!memcmp(&requestp[13], R01020F, 3)) ru_type = "ABCONN"; if (!memcmp(&requestp[13], R010219, 3)) ru_type = "ANA"; if (!memcmp(&requestp[13], R010216, 3)) ru_type = "ACTCONNIN"; if (!memcmp(&requestp[13], R010217, 3)) ru_type = "DACTCONNIN"; if ((requestp[10] & 0x08) == 0) ru_type = ""; sprintf(fmtbuf5, "%4.4X: %s: %s %s %-6.6s %s\n", devnum, tag, fmtbuf, fmtbuf2, fmtbuf3, ru_type); logmsg(fmtbuf5); } static void make_sna_requests2 (COMMADPT *ca) { BYTE *respbuf; BYTE *ru_ptr; int ru_size; void *eleptr; int bufp = 0; while (ca->inpbufl > 0) { eleptr = get_bufpool(&ca->freeq); if (!eleptr) { logmsg("no buffers trying to send SNA request2\n"); return; } respbuf = 4 + (BYTE*)eleptr; /* first do the ten-byte FID1 TH */ respbuf[0] = 0x1C; respbuf[1] = 0x00; respbuf[2] = ca->tso_addr0; // daf respbuf[3] = ca->tso_addr1; respbuf[4] = ca->lu_addr0; // oaf respbuf[5] = ca->lu_addr1; // oaf respbuf[6] = (unsigned char)(++ca->lu_lu_seqn >> 8) & 0xff; respbuf[7] = (unsigned char)( ca->lu_lu_seqn ) & 0xff; /* do RH */ respbuf[10] = 0x00; if (!bufp) { respbuf[10] |= 0x02; /* set first in chain */ } respbuf[11] = 0x90; respbuf[12] = 0x00; /* do RU */ // FIXME - max. ru_size should be based on BIND settings // A true fix would also require code changes to READ CCW processing // including possibly (gasp) segmenting long PIUs into multiple BTUs ru_size = min(256-(BUFPD+10+3),ca->inpbufl); ru_ptr = &respbuf[13]; if (!ca->bindflag) { // send as character-coded logon to SSCP if (ru_size > 0 && (ca->inpbuf[ca->inpbufl-1] == 0x0d || ca->inpbuf[ca->inpbufl-1] == 0x25)) { ru_size--; } if (ru_size > 0 && (ca->inpbuf[ca->inpbufl-1] == 0x0d || ca->inpbuf[ca->inpbufl-1] == 0x25)) { ru_size--; } respbuf[2] = ca->sscp_addr0; respbuf[3] = ca->sscp_addr1; respbuf[11] = 0x80; respbuf[12] = 0x00; } memcpy(ru_ptr, &ca->inpbuf[bufp], ru_size); bufp += ru_size; ca->inpbufl -= ru_size; if (!ca->is_3270) { ca->inpbufl = 0; } if (!ca->inpbufl) { respbuf[10] |= 0x01; /* set last in chain */ if (ca->bindflag) { respbuf[12] |= 0x20; /* set CD */ } } /* set length field in TH */ ru_size += 3; /* for RH */ respbuf[8] = (unsigned char)(ru_size >> 8) & 0xff; respbuf[9] = (unsigned char)(ru_size ) & 0xff; put_bufpool(&ca->sendq, eleptr); } /* end of while (ca->inpbufl > 0) */ } static void make_sna_requests3 (COMMADPT *ca) { BYTE *respbuf; BYTE *ru_ptr; int ru_size; void *eleptr; if (!ca->telnet_int) return; eleptr = get_bufpool(&ca->freeq); if (!eleptr) { logmsg("no buffers trying to send SNA request3\n"); return; } respbuf = 4 + (BYTE*)eleptr; /* first do the ten-byte FID1 TH */ respbuf[0] = 0x1D; respbuf[1] = 0x00; respbuf[2] = ca->tso_addr0; // daf respbuf[3] = ca->tso_addr1; respbuf[4] = ca->lu_addr0; // oaf respbuf[5] = ca->lu_addr1; // oaf respbuf[6] = 0x11; respbuf[7] = 0x11; /* do RH */ respbuf[10] = 0x4B; respbuf[11] = 0x80; respbuf[12] = 0x00; /* do RU */ ru_size = 0; ru_ptr = &respbuf[13]; ru_ptr[ru_size++] = 0xc9; // SIG ru_ptr[ru_size++] = 0x00; ru_ptr[ru_size++] = 0x01; ru_size += 3; /* for RH */ respbuf[8] = (unsigned char)(ru_size >> 8) & 0xff; respbuf[9] = (unsigned char)(ru_size ) & 0xff; put_bufpool(&ca->sendq, eleptr); ca->telnet_int = 0; } static void make_sna_requests4 (COMMADPT *ca, int flag, BYTE pu_type) { /* send type flag: 0=REQCONT 1=REQDISCONT */ BYTE *respbuf; BYTE *ru_ptr; int ru_size; void *eleptr; eleptr = get_bufpool(&ca->freeq); if (!eleptr) { logmsg("no buffers trying to send SNA request4\n"); return; } respbuf = 4 + (BYTE*)eleptr; /* first do the ten-byte FID1 TH */ respbuf[0] = 0x1C; respbuf[1] = 0x00; respbuf[2] = ca->sscp_addr0; // daf respbuf[3] = ca->sscp_addr1; // set oaf if (flag == 0) { respbuf[4] = ca->ncp_addr0; respbuf[5] = ca->ncp_addr1; make_seq(ca, respbuf); } else { respbuf[4] = ca->pu_addr0; respbuf[5] = ca->pu_addr1; respbuf[6] = 0x00; respbuf[7] = 0x01; } /* do RH */ respbuf[10] = 0x0b; respbuf[11] = 0x00; respbuf[12] = 0x00; /* do RU */ ru_size = 0; ru_ptr = &respbuf[13]; if (flag == 0) { ru_ptr[ru_size++] = 0x01; // REQCONT (REQUEST CONTACT) ru_ptr[ru_size++] = 0x02; ru_ptr[ru_size++] = 0x84; ru_ptr[ru_size++] = 0x40; // network address of link ru_ptr[ru_size++] = 0x01; ru_ptr[ru_size++] = pu_type; // PU type ru_ptr[ru_size++] = 0x00; ru_ptr[ru_size++] = 0x01; // IDBLK=017,IDNUM=00017 ru_ptr[ru_size++] = 0x70; ru_ptr[ru_size++] = 0x00; ru_ptr[ru_size++] = 0x17; } else { ru_ptr[ru_size++] = 0x01; // REQDISCONT (REQUEST DISCONTACT) ru_ptr[ru_size++] = 0x02; ru_ptr[ru_size++] = 0x1B; ru_ptr[ru_size++] = 0x00; } ru_size += 3; /* for RH */ respbuf[8] = (unsigned char)(ru_size >> 8) & 0xff; respbuf[9] = (unsigned char)(ru_size ) & 0xff; put_bufpool(&ca->sendq, eleptr); ca->telnet_int = 0; } static void make_sna_requests5 (COMMADPT *ca) { BYTE *respbuf; BYTE *ru_ptr; int ru_size; void *eleptr; eleptr = get_bufpool(&ca->freeq); if (!eleptr) { logmsg("no buffers trying to send SNA request5\n"); return; } respbuf = 4 + (BYTE*)eleptr; /* first do the ten-byte FID1 TH */ respbuf[0] = 0x1C; respbuf[1] = 0x00; respbuf[2] = ca->sscp_addr0; // daf respbuf[3] = ca->sscp_addr1; respbuf[4] = ca->ncp_addr0; // oaf respbuf[5] = ca->ncp_addr1; // set seq no. make_seq(ca, respbuf); /* do RH */ respbuf[10] = 0x0B; respbuf[11] = 0x00; respbuf[12] = 0x00; /* do RU */ ru_size = 0; ru_ptr = &respbuf[13]; ru_ptr[ru_size++] = 0x01; // INOP ru_ptr[ru_size++] = 0x02; ru_ptr[ru_size++] = 0x81; ru_ptr[ru_size++] = ca->pu_addr0; ru_ptr[ru_size++] = ca->pu_addr1; ru_ptr[ru_size++] = 0x01; // format/reason ru_size += 3; /* for RH */ respbuf[8] = (unsigned char)(ru_size >> 8) & 0xff; respbuf[9] = (unsigned char)(ru_size ) & 0xff; put_bufpool(&ca->sendq, eleptr); } void make_sna_requests (BYTE * requestp, COMMADPT *ca) { BYTE *respbuf; BYTE *ru_ptr; int ru_size; void *eleptr; if (memcmp(&requestp[13], R010201, 3)) return; // we only want to process CONTACT eleptr = get_bufpool(&ca->freeq); if (!eleptr) { logmsg("no buffers trying to send SNA request\n"); return; } respbuf = 4 + (BYTE*)eleptr; /* first do the ten-byte FID1 TH */ // respbuf[0] = requestp[0]; // respbuf[1] = requestp[1]; respbuf[0] = 0x1c; respbuf[1] = 0x00; respbuf[2] = requestp[4]; // daf respbuf[3] = requestp[5]; respbuf[4] = requestp[2]; // oaf respbuf[5] = requestp[3]; make_seq(ca, respbuf); /* do RH */ respbuf[10] = requestp[10]; respbuf[11] = requestp[11]; respbuf[11] = 0x00; respbuf[12] = requestp[12]; /* make a CONTACTED RU */ ru_size = 0; ru_ptr = &respbuf[13]; ru_ptr[ru_size++] = 0x01; ru_ptr[ru_size++] = 0x02; ru_ptr[ru_size++] = 0x80; ru_ptr[ru_size++] = requestp[16]; ru_ptr[ru_size++] = requestp[17]; ru_ptr[ru_size++] = 0x01; /* set length field in TH */ ru_size += 3; /* for RH */ respbuf[8] = (unsigned char)(ru_size >> 8) & 0xff; respbuf[9] = (unsigned char)(ru_size ) & 0xff; put_bufpool(&ca->sendq, eleptr); } void make_sna_response (BYTE * requestp, COMMADPT *ca) { BYTE *respbuf; BYTE *ru_ptr; int ru_size; void *eleptr; BYTE obuf[4096]; BYTE buf[BUFLEN_3270]; int amt; int i1; if ((requestp[10] & 0x80) != 0) return; // disregard if this is a resp. if ((requestp[10] & (unsigned char)0xfc) == 0x00 && requestp[2] == ca->lu_addr0 && requestp[3] == ca->lu_addr1 && ca->sfd > 0) { /* if type=data, and DAF matches up, and socket exists */ amt = (requestp[8] << 8) + requestp[9]; amt -= 3; if (ca->is_3270) { memcpy(buf, &requestp[13], amt); /* Double up any IAC bytes in the data */ amt = double_up_iac (buf, amt); /* Append telnet EOR marker at end of data */ if ((requestp[10] & 0x01) == 0x01) { /* if last-in-chain is set */ buf[amt++] = IAC; buf[amt++] = EOR_MARK; } /* Send the data to the client */ logdump ("SEND", ca->dev, buf, amt); write_socket(ca->sfd,buf,amt); } else { // convert data portion to ASCII and write to remote user if (amt > 0) { memcpy(obuf, &requestp[13], amt); for (i1=0; i1dev, obuf, amt); write_socket(ca->sfd,obuf,amt); } } } if ((requestp[11] & 0xf0) != 0x80) return; // disregard if not DR1 requested eleptr = get_bufpool(&ca->freeq); if (!eleptr) { logmsg("no buffers trying to send SNA response\n"); return; } respbuf = 4 + (BYTE*)eleptr; /* first do the ten-byte FID1 TH */ respbuf[0] = requestp[0]; respbuf[1] = requestp[1]; respbuf[2] = requestp[4]; // daf respbuf[3] = requestp[5]; respbuf[4] = requestp[2]; // oaf respbuf[5] = requestp[3]; respbuf[6] = requestp[6]; // seq # respbuf[7] = requestp[7]; /* do RH */ respbuf[10] = requestp[10]; respbuf[10] |= 0x83; // indicate this is a resp. respbuf[11] = requestp[11]; // respbuf[12] = requestp[12]; respbuf[12] = 0x00; /* do RU */ ru_size = 0; ru_ptr = &respbuf[13]; if ((requestp[10] & 0x08) != 0) ru_ptr[ru_size++] = requestp[13]; if (requestp[13] == 0x11 && requestp[14] == 0x02) { /* ACTPU (NCP)*/ ca->ncp_addr0 = requestp[2]; ca->ncp_addr1 = requestp[3]; // ca->ncp_sscp_seqn = 0; ru_ptr[ru_size++] = 0x02; if (requestp[2] == 0x40) { /* DAF subarea field = 8? */ ru_ptr[ru_size++] = 0xd4; /* DS CL8'MHPRMT1 ' - NCP load mod name */ ru_ptr[ru_size++] = 0xc8; ru_ptr[ru_size++] = 0xd7; ru_ptr[ru_size++] = 0xd9; ru_ptr[ru_size++] = 0xd4; ru_ptr[ru_size++] = 0xe3; ru_ptr[ru_size++] = 0xf1; ru_ptr[ru_size++] = 0x40; ca->ncpb_sscp_seqn = 0; } else { ru_ptr[ru_size++] = 0xd4; /* DS CL8'MHP3705 ' - NCP load mod name */ ru_ptr[ru_size++] = 0xc8; /* checked by host at ACTPU time */ ru_ptr[ru_size++] = 0xd7; ru_ptr[ru_size++] = 0xf3; ru_ptr[ru_size++] = 0xf7; ru_ptr[ru_size++] = 0xf0; ru_ptr[ru_size++] = 0xf5; ru_ptr[ru_size++] = 0x40; ca->ncpa_sscp_seqn = 0; } } if (requestp[13] == 0x11 && requestp[14] == 0x01) { /* ACTPU (PU)*/ ru_ptr[ru_size++] = 0x01; /* save daf as our own net addr */ ca->pu_addr0 = requestp[2]; ca->pu_addr1 = requestp[3]; } if (requestp[13] == 0x01) { /* 01XXXX Network Services */ ru_ptr[ru_size++] = requestp[14]; ru_ptr[ru_size++] = requestp[15]; } if (!memcmp(&requestp[13], R010219, 3) && ca->sfd > 0) { /* ANA */ if (!ca->is_3270) { connect_message(ca->sfd, (requestp[20] << 8) + requestp[21], 0); } } if (requestp[13] == 0x0D) { /* ACTLU */ /* save daf as our own net addr */ ca->lu_addr0 = requestp[2]; ca->lu_addr1 = requestp[3]; /* save oaf as our sscp net addr */ ca->sscp_addr0 = requestp[4]; ca->sscp_addr1 = requestp[5]; ca->lu_sscp_seqn = 0; ca->bindflag = 0; } if (requestp[13] == 0x0E || !memcmp(&requestp[13], R01020F, 3)) { // DACTLU or ABCONN if (!ca->is_3270) { connect_message(ca->sfd, 0, 1); } ca->hangup = 1; } if (requestp[13] == 0x31) { /* BIND */ /* save oaf from BIND request */ ca->tso_addr0 = requestp[4]; ca->tso_addr1 = requestp[5]; ca->lu_lu_seqn = 0; ca->bindflag = 1; } if (requestp[13] == 0x32 && requestp[14] != 0x02) { /* BIND */ ca->bindflag = 0; } #if 0 if (requestp[13] == 0x32 && requestp[14] == 0x01 && ca->sfd > 0) { /* UNBIND */ close_socket(ca->sfd); ca->sfd=-1; } #endif /* set length field in TH */ ru_size += 3; /* for RH */ respbuf[8] = (unsigned char)(ru_size >> 8) & 0xff; respbuf[9] = (unsigned char)(ru_size ) & 0xff; put_bufpool(&ca->sendq, eleptr); } /*-------------------------------------------------------------------*/ /* Execute a Channel Command Word */ /*-------------------------------------------------------------------*/ static void commadpt_execute_ccw (DEVBLK *dev, BYTE code, BYTE flags, BYTE chained, U16 count, BYTE prevcode, int ccwseq, BYTE *iobuf, BYTE *more, BYTE *unitstat, U16 *residual) { U32 num; /* Work : Actual CCW transfer count */ BYTE *piudata; int piusize; void *eleptr; UNREFERENCED(flags); UNREFERENCED(chained); UNREFERENCED(prevcode); UNREFERENCED(ccwseq); *residual = 0; /* * Obtain the COMMADPT lock */ if(dev->ccwtrace) { logmsg(_("HHCCA300D %4.4X:CCW Exec - Entry code = %x\n"),dev->devnum,code); } obtain_lock(&dev->commadpt->lock); switch (code) { /*---------------------------------------------------------------*/ /* BASIC SENSE */ /*---------------------------------------------------------------*/ case 0x04: dev->commadpt->unack_attn_count = 0; num=countnumsense?count:dev->numsense; *more=countnumsense?1:0; memcpy(iobuf,dev->sense,num); *residual=count-num; *unitstat=CSW_CE|CSW_DE; break; /*---------------------------------------------------------------*/ /* READ type CCWs */ /*---------------------------------------------------------------*/ case 0x02: /* READ */ dev->commadpt->read_ccw_count++; dev->commadpt->unack_attn_count = 0; *more = 0; make_sna_requests2(dev->commadpt); make_sna_requests3(dev->commadpt); eleptr = get_bufpool(&dev->commadpt->sendq); *residual=count; if (eleptr) { piudata = 4 + (BYTE*)eleptr; piusize = (piudata[8] << 8) + piudata[9]; piusize += 10; // for FID1 TH iobuf[0] = BUFPD; memcpy (&iobuf[BUFPD], piudata, piusize); *residual=count - (piusize + BUFPD); logdump("READ", dev, &iobuf[BUFPD], piusize); if (dev->commadpt->debug_sna) format_sna(piudata, "RD", dev->devnum); put_bufpool(&dev->commadpt->freeq, eleptr); } *unitstat=CSW_CE|CSW_DE; #if 0 if (dev->commadpt->sendq) { *unitstat|=CSW_ATTN; } #endif *unitstat|=CSW_UX; break; /*---------------------------------------------------------------*/ /* WRITE type CCWs */ /*---------------------------------------------------------------*/ case 0x09: /* WRITE BREAK */ case 0x01: /* WRITE */ dev->commadpt->write_ccw_count++; dev->commadpt->unack_attn_count = 0; logdump("WRITE", dev, iobuf, count); if ((iobuf[0] & 0xf0) == 0x10) { // if FID1 if (dev->commadpt->debug_sna) format_sna(iobuf, "WR", dev->devnum); make_sna_response(iobuf, dev->commadpt); make_sna_requests(iobuf, dev->commadpt); } *residual=0; *unitstat=CSW_CE|CSW_DE; #if 0 if (dev->commadpt->sendq) { *unitstat|=CSW_ATTN; *unitstat|=CSW_UX|CSW_ATTN; } #endif break; /*---------------------------------------------------------------*/ /* CCWs to be treated as NOPs */ /*---------------------------------------------------------------*/ case 0x03: /* NOP */ case 0x93: /* RESTART */ case 0x31: /* WS0 */ case 0x51: /* WS1 */ case 0x32: /* RS0 */ case 0x52: /* RS1 */ *residual=count; *unitstat=CSW_CE|CSW_DE; break; default: /*---------------------------------------------------------------*/ /* INVALID OPERATION */ /*---------------------------------------------------------------*/ /* Set command reject sense byte, and unit check status */ *unitstat=CSW_CE+CSW_DE+CSW_UC; dev->sense[0]=SENSE_CR; break; } release_lock(&dev->commadpt->lock); } /*---------------------------------------------------------------*/ /* DEVICE FUNCTION POINTERS */ /*---------------------------------------------------------------*/ #if defined(OPTION_DYNAMIC_LOAD) static #endif DEVHND com3705_device_hndinfo = { &commadpt_init_handler, /* Device Initialisation */ &commadpt_execute_ccw, /* Device CCW execute */ &commadpt_close_device, /* Device Close */ &commadpt_query_device, /* Device Query */ NULL, /* Device Start channel pgm */ NULL, /* Device End channel pgm */ NULL, /* Device Resume channel pgm */ NULL, /* Device Suspend channel pgm */ NULL, /* Device Read */ NULL, /* Device Write */ NULL, /* Device Query used */ NULL, /* Device Reserve */ NULL, /* Device Release */ NULL, /* Device Attention */ commadpt_immed_command, /* Immediate CCW Codes */ NULL, /* Signal Adapter Input */ NULL, /* Signal Adapter Output */ NULL, /* Hercules suspend */ NULL /* Hercules resume */ }; /* Libtool static name colision resolution */ /* note : lt_dlopen will look for symbol & modulename_LTX_symbol */ #if !defined(HDL_BUILD_SHARED) && defined(HDL_USE_LIBTOOL) #define hdl_ddev hdt3705_LTX_hdl_ddev #define hdl_depc hdt3705_LTX_hdl_depc #define hdl_reso hdt3705_LTX_hdl_reso #define hdl_init hdt3705_LTX_hdl_init #define hdl_fini hdt3705_LTX_hdl_fini #endif #if defined(OPTION_DYNAMIC_LOAD) HDL_DEPENDENCY_SECTION; { HDL_DEPENDENCY(HERCULES); HDL_DEPENDENCY(DEVBLK); HDL_DEPENDENCY(SYSBLK); } END_DEPENDENCY_SECTION; #if defined(WIN32) && !defined(HDL_USE_LIBTOOL) && !defined(_MSVC_) #undef sysblk HDL_RESOLVER_SECTION; { HDL_RESOLVE_PTRVAR( psysblk, sysblk ); } END_RESOLVER_SECTION; #endif HDL_DEVICE_SECTION; { HDL_DEVICE(3705, com3705_device_hndinfo ); } END_DEVICE_SECTION; #endif hercules-3.07/comm3705.h000644 000765 000765 00000004603 11203344516 016370 0ustar00jmaynardjmaynard000000 000000 #ifndef __COMM3705_H__ #define __COMM3705_H__ #include "hercules.h" struct COMMADPT { DEVBLK *dev; /* the devblk to which this CA is attched */ TID cthread; /* Thread used to control the socket */ TID tthread; /* Thread used to control the socket */ U16 lport; /* Local listening port */ in_addr_t lhost; /* Local listening address */ int sfd; /* Communication socket FD */ int lfd; /* Listen socket for DIAL=IN, INOUT & NO */ COND ipc; /* I/O <-> thread IPC condition EVB */ COND ipc_halt; /* I/O <-> thread IPC HALT special EVB */ LOCK lock; /* COMMADPT lock */ int pipe[2]; /* pipe used for I/O to thread signaling */ U16 devnum; /* devnum copy from DEVBLK */ U32 have_cthread:1, /* the comm thread is running */ haltpending:1, /* A request has been issued to halt current*/ /* CCW */ bindflag:1, telnet_opt:1, /* expecting telnet option char */ telnet_iac:1, /* expecting telnet command char */ telnet_int:1, /* telnet interrupt received */ hangup:1, /* host initated shutdown */ is_3270:1, /* 0=tty 1=3270 */ eol_flag:1, /* 1 = CR has been received */ debug_sna:1; /* 1 = write debug messages */ U32 rlen3270; /* amt of data in 3270 recv buf */ BYTE telnet_cmd; /* telnet command */ int read_ccw_count; int write_ccw_count; int unack_attn_count; int ncpa_sscp_seqn; int ncpb_sscp_seqn; int lu_sscp_seqn; int lu_lu_seqn; BYTE inpbuf[65536]; int inpbufl; void * freeq; void * sendq; BYTE * poolarea; BYTE sscp_addr0; BYTE sscp_addr1; BYTE ncp_addr0; BYTE ncp_addr1; BYTE pu_addr0; BYTE pu_addr1; BYTE lu_addr0; BYTE lu_addr1; BYTE tso_addr0; BYTE tso_addr1; }; #endif hercules-3.07/commadpt.c000644 000765 000765 00000361737 11202677677 016753 0ustar00jmaynardjmaynard000000 000000 /*-------------------------------------------------------------------*/ /* Hercules Communication Line Driver */ /* (c) 1999-2006 Roger Bowler & Others */ /* Use of this program is governed by the QPL License */ /* Original Author : Ivan Warren */ /* Prime Maintainer : Ivan Warren */ /*-------------------------------------------------------------------*/ // $Id: commadpt.c 5346 2009-05-14 02:19:35Z jmaynard $ // // $Log$ // Revision 1.46 2008/11/03 15:31:58 rbowler // Back out consistent create_thread ATTR modification // // Revision 1.45 2008/10/18 09:32:20 fish // Ensure consistent create_thread ATTR usage // // Revision 1.44 2008/03/04 01:10:29 ivan // Add LEGACYSENSEID config statement to allow X'E4' Sense ID on devices // that originally didn't support it. Defaults to off for compatibility reasons // // Revision 1.43 2008/02/15 22:51:39 rbowler // Move Solaris specific definition of INADDR_NONE to hostopts.h // // Revision 1.42 2008/02/07 00:29:04 rbowler // Solaris build support by Jeff Savit // // Revision 1.41 2007/12/14 17:48:52 rbowler // Enable SENSE ID CCW for 2703,3410,3420 // // Revision 1.40 2007/11/21 22:54:14 fish // Use new BEGIN_DEVICE_CLASS_QUERY macro // // Revision 1.39 2006/12/08 09:43:18 jj // Add CVS message log // /* ******************************************************************** TTY Mode Additions (c) Copyright, 2007 MHP Feb. 2007- Add support for 2703 Telegraph Terminal Control Type II (for use with TTY ASR 33/35 or compatible terminals). To enable TTY mode for a particular port, specify ``LNCTL=ASYNC'' in the hercules conf file. The host sends and receives bytes directly in ASCII, but bits are reversed from standard ASCII bit order. Lookup tables are used to perform the reversals on each byte, to make even parity for sending toward the host, and to skip certain noxious characters emitted by TSO/TCAM. This code contains minimal TELNET support. It accepts TELNET IP (Interrupt Process) which is mapped and transmitted to the host as a BREAK (ATTN) sequence. All TELNET commands are responded negatively. ***************************************************************** 2741 Mode Additions (c) Copyright, 2008 MHP 2741 mode is now working, though imperfectly as of yet. There is a new param (term=tty|2741) in the conf file to select termtype. Specify code=ebcd for EBCD, or code=corr for correspondence code. Also code=none to disable all translation. The code= option applies to 2741 mode only. Another new param (skip=) is a byte string, specified in hex, to specify "garbage" code points that are to be suppressed in output processing. This allows distinct lists to be used for different terminal types. Automatic translation to Uppercase is enabled by setting uctrans=yes . This is for both 2741 and TTY terminals. You can specify lnctl=tele2 for TTY and lnctl=ibm1 for 2741. Samples: 0045 2703 lport=32003 dial=IN lnctl=ibm1 term=2741 skip=5EDE code=ebcd 0045 2703 lport=32003 dial=IN lnctl=tele2 uctrans=yes term=tty skip=88C9DF For TCAM, if you are zapping device UCB's, the following type values seem to work: 55 10 40 13 - 2741 51 10 40 53 - TTY (3335) When running TCAM in 2741 mode if you experience A00 abends, the following zap (to member IEDQTCAM in 'SYS1.LINKLIB') may help NAME IEDQTCAM IEDQKA01 VER 0E38 012C REP 0E38 0101 The 2741 mode enables ordinary remote ASCII TELNET clients to connect. The translate tables were lifted from IEDQ27 and IEDQ28. Instead of translating directly between ASCII and the host's 2741-correspondence code, we add an intermediate EBCDIC step. This enables use of all pre- existing tables so I don't have to code any new ones :) Also, 2740 OS consoles should work. It may be necessary to modify the driver to end READ CCWs even when no data has been received (see comment) ******************************************************************** */ #include "hstdinc.h" #include "hercules.h" #include "devtype.h" #include "parser.h" #include "commadpt.h" #if defined(WIN32) && defined(OPTION_DYNAMIC_LOAD) && !defined(HDL_USE_LIBTOOL) && !defined(_MSVC_) SYSBLK *psysblk; #define sysblk (*psysblk) #endif /*-------------------------------------------------------------------*/ /* Ivan Warren 20040227 */ /* This table is used by channel.c to determine if a CCW code is an */ /* immediate command or not */ /* The tape is addressed in the DEVHND structure as 'DEVIMM immed' */ /* 0 : Command is NOT an immediate command */ /* 1 : Command is an immediate command */ /* Note : An immediate command is defined as a command which returns */ /* CE (channel end) during initialisation (that is, no data is */ /* actually transfered. In this case, IL is not indicated for a CCW */ /* Format 0 or for a CCW Format 1 when IL Suppression Mode is in */ /* effect */ /*-------------------------------------------------------------------*/ static BYTE commadpt_immed_command[256]= { 0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; COMMADPT_PEND_TEXT; /* Defined in commadpt.h */ /* Defines commadpt_pendccw_text array */ /*---------------------------------------------------------------*/ /* PARSER TABLES */ /*---------------------------------------------------------------*/ static PARSER ptab[]={ {"lport","%s"}, {"lhost","%s"}, {"rport","%s"}, {"rhost","%s"}, {"dial","%s"}, {"rto","%s"}, {"pto","%s"}, {"eto","%s"}, {"switched","%s"}, {"lnctl","%s"}, {"term","%s"}, {"code","%s"}, {"uctrans","%s"}, {"skip","%s"}, {NULL,NULL} }; enum { COMMADPT_KW_LPORT=1, COMMADPT_KW_LHOST, COMMADPT_KW_RPORT, COMMADPT_KW_RHOST, COMMADPT_KW_DIAL, COMMADPT_KW_READTO, COMMADPT_KW_POLLTO, COMMADPT_KW_ENABLETO, COMMADPT_KW_SWITCHED, COMMADPT_KW_LNCTL, COMMADPT_KW_TERM, COMMADPT_KW_CODE, COMMADPT_KW_UCTRANS, COMMADPT_KW_SKIP } commadpt_kw; static BYTE byte_reverse_table[256] = { 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 }; /* 2741 EBCD code tables */ /* directly copied from mvs src file iedq27 */ static BYTE xlate_table_ebcd_toebcdic[256] = { 0x3F, 0x40, 0xF1, 0x3F, 0xF2, 0x3F, 0x3F, 0xF3, 0xF4, 0x3F, 0x3F, 0xF5, 0x3F, 0xF6, 0xF7, 0x3F, 0xF8, 0x3F, 0x3F, 0xF9, 0x3F, 0xF0, 0x7B, 0x3F, 0x3F, 0x3F, 0x35, 0x3F, 0x36, 0x3F, 0x3F, 0x37, 0x7C, 0x3F, 0x3F, 0x61, 0x3F, 0xA2, 0xA3, 0x3F, 0x3F, 0xA4, 0xA5, 0x3F, 0xA6, 0x3F, 0x3F, 0xA7, 0x3F, 0xA8, 0xA9, 0x3F, 0x3F, 0x3F, 0x3F, 0x6B, 0x24, 0x3F, 0x3F, 0x25, 0x3F, 0x26, 0x27, 0x3F, 0x60, 0x3F, 0x3F, 0x91, 0x3F, 0x92, 0x93, 0x3F, 0x3F, 0x94, 0x95, 0x3F, 0x96, 0x3F, 0x3F, 0x97, 0x3F, 0x98, 0x99, 0x3F, 0x3F, 0x3F, 0x3F, 0x5B, 0x14, 0x3F, 0x3F, 0x15, 0x3F, 0x16, 0x17, 0x3F, 0x3F, 0x50, 0x81, 0x3F, 0x82, 0x3F, 0x3F, 0x83, 0x84, 0x3F, 0x3F, 0x85, 0x3F, 0x86, 0x87, 0x3F, 0x88, 0x3F, 0x3F, 0x89, 0x3F, 0x3F, 0x4B, 0x3F, 0x3F, 0x3F, 0x05, 0x3F, 0x06, 0x3F, 0x3F, 0x07, 0x3F, 0x40, 0x7E, 0x3F, 0x4C, 0x3F, 0x3F, 0x5E, 0x7A, 0x3F, 0x3F, 0x6C, 0x3F, 0x7D, 0x6E, 0x3F, 0x5C, 0x3F, 0x3F, 0x4D, 0x3F, 0x5D, 0x7F, 0x3F, 0x3F, 0x3F, 0x35, 0x3F, 0x36, 0x3F, 0x3F, 0x3F, 0x4A, 0x3F, 0x3F, 0x6F, 0x3F, 0xE2, 0xE3, 0x3F, 0x3F, 0xE4, 0xE5, 0x3F, 0xE6, 0x3F, 0x3F, 0xE7, 0x3F, 0xE8, 0xE9, 0x3F, 0x3F, 0x3F, 0x3F, 0x4F, 0x24, 0x3F, 0x3F, 0x25, 0x3F, 0x26, 0x27, 0x3F, 0x6D, 0x3F, 0x3F, 0xD1, 0x3F, 0xD2, 0xD3, 0x3F, 0x3F, 0xD4, 0xD5, 0x3F, 0xD6, 0x3F, 0x3F, 0xD7, 0x3F, 0xD8, 0xD9, 0x3F, 0x3F, 0x3F, 0x3F, 0x5A, 0x14, 0x3F, 0x3F, 0x15, 0x3F, 0x16, 0x17, 0x3F, 0x3F, 0x4E, 0xC1, 0x3F, 0xC2, 0x3F, 0x3F, 0xC3, 0xC4, 0x3F, 0x3F, 0xC5, 0x3F, 0xC6, 0xC7, 0x3F, 0xC8, 0x3F, 0x3F, 0xC9, 0x3F, 0x3F, 0x5F, 0x3F, 0x3F, 0x3F, 0x05, 0x3F, 0x06, 0x3F, 0x3F, 0x07 }; static BYTE xlate_table_ebcd_fromebcdic[256] = { 0x88, 0x88, 0x88, 0x88, 0x88, 0x7A, 0x7C, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x5B, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x58, 0x5B, 0x5D, 0x5E, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x38, 0x3B, 0x88, 0x3E, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x5E, 0x88, 0x88, 0x88, 0x1C, 0x1F, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x01, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0xA0, 0x76, 0x84, 0x93, 0xE1, 0xB7, 0x61, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0xD7, 0x57, 0x90, 0x95, 0x87, 0xF6, 0x40, 0x23, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x37, 0x8B, 0xC0, 0x8E, 0xA3, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x16, 0x20, 0x8D, 0x82, 0x96, 0x88, 0x62, 0x64, 0x67, 0x68, 0x6B, 0x6D, 0x6E, 0x70, 0x73, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x43, 0x45, 0x46, 0x49, 0x4A, 0x4C, 0x4F, 0x51, 0x52, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x25, 0x26, 0x29, 0x2A, 0x2C, 0x2F, 0x31, 0x32, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0xE2, 0xE4, 0xE7, 0xE8, 0xEB, 0xED, 0xEE, 0xF0, 0xF3, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0xC3, 0xC5, 0xC6, 0xC9, 0xCA, 0xCC, 0xCF, 0xD1, 0xD2, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0xA5, 0xA6, 0xA9, 0xAA, 0xAC, 0xAF, 0xB1, 0xB2, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x15, 0x02, 0x04, 0x07, 0x08, 0x0B, 0x0D, 0x0E, 0x10, 0x13, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88 }; /* 2741 correspondence code tables */ /* directly copied from mvs src file iedq28 */ static BYTE xlate_table_cc_toebcdic[256] = { 0x3F, 0x40, 0xF1, 0x3F, 0xF2, 0x3F, 0x3F, 0xF3, 0xF5, 0x3F, 0x3F, 0xF7, 0x3F, 0xF6, 0xF8, 0x3F, 0xF4, 0x3F, 0x3F, 0xF0, 0x3F, 0xA9, 0xF9, 0x3F, 0x3F, 0x34, 0x35, 0x3F, 0x36, 0x3F, 0x3F, 0x37, 0xA3, 0x3F, 0x3F, 0xA7, 0x3F, 0x95, 0xA4, 0x3F, 0x3F, 0x85, 0x84, 0x3F, 0x92, 0x3F, 0x3F, 0x83, 0x3F, 0x93, 0x88, 0x3F, 0x3F, 0x3F, 0x3F, 0x82, 0x24, 0x3F, 0x3F, 0x25, 0x3F, 0x26, 0x27, 0x3F, 0x5A, 0x3F, 0x3F, 0x94, 0x3F, 0x4B, 0xA5, 0x3F, 0x3F, 0x7D, 0x99, 0x3F, 0x89, 0x3F, 0x3F, 0x81, 0x3F, 0x96, 0xA2, 0x3F, 0x3F, 0x3F, 0x3F, 0xA6, 0x14, 0x3F, 0x3F, 0x15, 0x3F, 0x16, 0x17, 0x3F, 0x3F, 0x91, 0x87, 0x3F, 0x7E, 0x3F, 0x3F, 0x86, 0x97, 0x3F, 0x3F, 0x5E, 0x3F, 0x98, 0x6B, 0x3F, 0x61, 0x3F, 0x3F, 0xA8, 0x3F, 0x3F, 0x60, 0x3F, 0x3F, 0x04, 0x05, 0x3F, 0x06, 0x3F, 0x3F, 0x07, 0x3F, 0x40, 0x4F, 0x3F, 0x7C, 0x3F, 0x3F, 0x7B, 0x6C, 0x3F, 0x3F, 0x50, 0x3F, 0x4C, 0x5C, 0x3F, 0x5B, 0x3F, 0x3F, 0x5D, 0x3F, 0xE9, 0x4D, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x36, 0x3F, 0x3F, 0x37, 0xE3, 0x3F, 0x3F, 0xE7, 0x3F, 0xD5, 0xE4, 0x3F, 0x3F, 0xC5, 0xC4, 0x3F, 0xD2, 0x3F, 0x3F, 0xC3, 0x3F, 0xD3, 0xC8, 0x3F, 0x3F, 0x3F, 0x3F, 0xC2, 0x24, 0x3F, 0x3F, 0x25, 0x3F, 0x3F, 0x27, 0x3F, 0x6E, 0x3F, 0x3F, 0xD4, 0x3F, 0x4B, 0xE5, 0x3F, 0x3F, 0x7F, 0xD9, 0x3F, 0xC9, 0x3F, 0x3F, 0xC1, 0x3F, 0xD6, 0xE2, 0x3F, 0x3F, 0x3F, 0x3F, 0xE6, 0x14, 0x3F, 0x3F, 0x15, 0x3F, 0x16, 0x3F, 0x3F, 0x3F, 0xD1, 0xC7, 0x3F, 0x4E, 0x3F, 0x3F, 0xC6, 0xD7, 0x3F, 0x3F, 0x7A, 0x3F, 0xD8, 0x6B, 0x3F, 0x6F, 0x3F, 0x3F, 0xE8, 0x3F, 0x3F, 0x6D, 0x3F, 0x3F, 0x3F, 0x05, 0x3F, 0x06, 0x3F, 0x3F, 0x3F, }; static BYTE xlate_table_cc_fromebcdic[256] = { 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0x7A, 0x7C, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0x5B, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0x58, 0x5B, 0x5D, 0x5E, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0x38, 0x3B, 0xEB, 0x3E, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0x5E, 0xEB, 0x19, 0x1A, 0x1C, 0x1F, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0x01, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0x45, 0x8D, 0x96, 0xE4, 0x82, 0x8B, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0x40, 0x90, 0x8E, 0x93, 0x6B, 0xEB, 0x76, 0x70, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0x6E, 0x88, 0xF6, 0xC0, 0xF0, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0x87, 0x84, 0x49, 0x64, 0xC9, 0xEB, 0x4F, 0x37, 0x2F, 0x2A, 0x29, 0x67, 0x62, 0x32, 0x4C, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0x61, 0x2C, 0x31, 0x43, 0x25, 0x51, 0x68, 0x6D, 0x4A, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0x52, 0x20, 0x26, 0x46, 0x57, 0x23, 0x73, 0x15, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xCF, 0xB7, 0xAF, 0xAA, 0xA9, 0xE7, 0xE2, 0xB2, 0xCC, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xE1, 0xAC, 0xB1, 0xC3, 0xA5, 0xD1, 0xE8, 0xED, 0xCA, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xD2, 0xA0, 0xA6, 0xC6, 0xD7, 0xA3, 0xF3, 0x95, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0x13, 0x02, 0x04, 0x07, 0x10, 0x08, 0x0D, 0x0B, 0x0E, 0x16, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, }; static BYTE byte_parity_table [128] = { /* value: 0 = even parity, 1 = odd parity */ 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1 }; static void logdump(char *txt,DEVBLK *dev,BYTE *bfr,size_t sz) { size_t i; if(!dev->ccwtrace) { return; } logmsg(_("HHCCA300D %4.4X:%s : Status = TEXT=%s, TRANS=%s, TWS=%s\n"), dev->devnum, txt, dev->commadpt->in_textmode?"YES":"NO", dev->commadpt->in_xparmode?"YES":"NO", dev->commadpt->xparwwait?"YES":"NO"); logmsg(_("HHCCA300D %4.4X:%s : Dump of %d (%x) byte(s)\n"),dev->devnum,txt,sz,sz); for(i=0;idevnum,txt,i); } if(i%4==0) { logmsg(" "); } logmsg("%2.2X",bfr[i]); } logmsg("\n"); } /*-------------------------------------------------------------------*/ /* Handler utility routines */ /*-------------------------------------------------------------------*/ /*-------------------------------------------------------------------*/ /* Buffer ring management */ /*-------------------------------------------------------------------*/ /*-------------------------------------------------------------------*/ /* Buffer ring management : Init a buffer ring */ /*-------------------------------------------------------------------*/ void commadpt_ring_init(COMMADPT_RING *ring,size_t sz,int trace) { ring->bfr=malloc(sz); ring->sz=sz; ring->hi=0; ring->lo=0; ring->havedata=0; ring->overflow=0; if(trace) { logmsg("HCCCA999D : Ring buffer for ring %p allocated at %p\n", ring, ring->bfr); } } /*-------------------------------------------------------------------*/ /* Buffer ring management : Free a buffer ring */ /*-------------------------------------------------------------------*/ static void commadpt_ring_terminate(COMMADPT_RING *ring,int trace) { if(trace) { logmsg("HCCCA999D : Ring buffer for ring %p at %p freed\n", ring, ring->bfr); } if(ring->bfr!=NULL) { free(ring->bfr); ring->bfr=NULL; } ring->sz=0; ring->hi=0; ring->lo=0; ring->havedata=0; ring->overflow=0; } /*-------------------------------------------------------------------*/ /* Buffer ring management : Flush a buffer ring */ /*-------------------------------------------------------------------*/ static void commadpt_ring_flush(COMMADPT_RING *ring) { ring->hi=0; ring->lo=0; ring->havedata=0; ring->overflow=0; } /*-------------------------------------------------------------------*/ /* Buffer ring management : Queue a byte in the ring */ /*-------------------------------------------------------------------*/ inline static void commadpt_ring_push(COMMADPT_RING *ring,BYTE b) { ring->bfr[ring->hi++]=b; if(ring->hi>=ring->sz) { ring->hi=0; } if(ring->hi==ring->lo) { ring->overflow=1; } ring->havedata=1; } /*-------------------------------------------------------------------*/ /* Buffer ring management : Queue a byte array in the ring */ /*-------------------------------------------------------------------*/ inline static void commadpt_ring_pushbfr(COMMADPT_RING *ring,BYTE *b,size_t sz) { size_t i; for(i=0;ibfr[ring->lo++]; if(ring->lo>=ring->sz) { ring->lo=0; } if(ring->hi==ring->lo) { ring->havedata=0; } return b; } /*-------------------------------------------------------------------*/ /* Buffer ring management : Retrive a byte array from the ring */ /*-------------------------------------------------------------------*/ inline static size_t commadpt_ring_popbfr(COMMADPT_RING *ring,BYTE *b,size_t sz) { size_t i; for(i=0;ihavedata;i++) { b[i]=commadpt_ring_pop(ring); } return i; } /*-------------------------------------------------------------------*/ /* Free all private structures and buffers */ /*-------------------------------------------------------------------*/ static void commadpt_clean_device(DEVBLK *dev) { if(!dev) { /* * Shouldn't happen.. But during shutdown, some weird * things happen ! */ return; } if(dev->commadpt!=NULL) { commadpt_ring_terminate(&dev->commadpt->inbfr,dev->ccwtrace); commadpt_ring_terminate(&dev->commadpt->outbfr,dev->ccwtrace); commadpt_ring_terminate(&dev->commadpt->rdwrk,dev->ccwtrace); commadpt_ring_terminate(&dev->commadpt->pollbfr,dev->ccwtrace); /* release the CA lock */ release_lock(&dev->commadpt->lock); free(dev->commadpt); dev->commadpt=NULL; if(dev->ccwtrace) { logmsg(_("HHCCA300D %4.4X:clean : Control block freed\n"), dev->devnum); } } else { if(dev->ccwtrace) { logmsg(_("HHCCA300D %4.4X:clean : Control block not freed : not allocated\n"),dev->devnum); } } return; } /*-------------------------------------------------------------------*/ /* Allocate initial private structures */ /*-------------------------------------------------------------------*/ static int commadpt_alloc_device(DEVBLK *dev) { dev->commadpt=malloc(sizeof(COMMADPT)); if(dev->commadpt==NULL) { logmsg(_("HHCCA020E %4.4X:Memory allocation failure for main control block\n"), dev->devnum); return -1; } memset(dev->commadpt,0,sizeof(COMMADPT)); commadpt_ring_init(&dev->commadpt->inbfr,4096,dev->ccwtrace); commadpt_ring_init(&dev->commadpt->outbfr,4096,dev->ccwtrace); commadpt_ring_init(&dev->commadpt->pollbfr,4096,dev->ccwtrace); commadpt_ring_init(&dev->commadpt->rdwrk,65536,dev->ccwtrace); dev->commadpt->dev=dev; return 0; } /*-------------------------------------------------------------------*/ /* Parsing utilities */ /*-------------------------------------------------------------------*/ /*-------------------------------------------------------------------*/ /* commadpt_getport : returns a port number or -1 */ /*-------------------------------------------------------------------*/ static int commadpt_getport(char *txt) { int pno; struct servent *se; pno=atoi(txt); if(pno==0) { se=getservbyname(txt,"tcp"); if(se==NULL) { return -1; } pno=se->s_port; } return(pno); } /*-------------------------------------------------------------------*/ /* commadpt_getaddr : set an in_addr_t if ok, else return -1 */ /*-------------------------------------------------------------------*/ static int commadpt_getaddr(in_addr_t *ia,char *txt) { struct hostent *he; he=gethostbyname(txt); if(he==NULL) { return(-1); } memcpy(ia,he->h_addr_list[0],4); return(0); } /*-------------------------------------------------------------------*/ /* commadpt_connout : make a tcp outgoing call */ /* return values : 0 -> call succeeded or initiated */ /* <0 -> call failed */ /*-------------------------------------------------------------------*/ static int commadpt_connout(COMMADPT *ca) { int rc; char wbfr[256]; struct sockaddr_in sin; struct in_addr intmp; sin.sin_family=AF_INET; sin.sin_addr.s_addr=ca->rhost; sin.sin_port=htons(ca->rport); if(socket_is_socket(ca->sfd)) { close_socket(ca->sfd); ca->connect=0; } ca->sfd=socket(AF_INET,SOCK_STREAM,0); /* set socket to NON-blocking mode */ socket_set_blocking_mode(ca->sfd,0); rc=connect(ca->sfd,(struct sockaddr *)&sin,sizeof(sin)); if(rc<0) { if(HSO_errno==HSO_EINPROGRESS) { return(0); } else { strerror_r(HSO_errno,wbfr,256); intmp.s_addr=ca->rhost; logmsg(_("HHCCA001I %4.4X:Connect out to %s:%d failed during initial status : %s\n"), ca->devnum, inet_ntoa(intmp), ca->rport, wbfr); close_socket(ca->sfd); ca->connect=0; return(-1); } } ca->connect=1; return(0); } /*-------------------------------------------------------------------*/ /* commadpt_initiate_userdial : interpret DIAL data and initiate call*/ /* return values : 0 -> call succeeded or initiated */ /* <0 -> call failed */ /*-------------------------------------------------------------------*/ static int commadpt_initiate_userdial(COMMADPT *ca) { int dotcount; /* Number of seps (the 4th is the port separator) */ int i; /* work */ int cur; /* Current section */ in_addr_t destip; /* Destination IP address */ U16 destport; /* Destination TCP port */ int incdata; /* Incorrect dial data found */ int goteon; /* EON presence flag */ /* See the DIAL CCW portion in execute_ccw for dial format information */ incdata=0; goteon=0; dotcount=0; cur=0; destip=0; for(i=0;idialcount;i++) { if(goteon) { /* EON MUST be last data byte */ if(ca->dev->ccwtrace) { logmsg(_("HHCCA300D %4.4x : Found data beyond EON\n"),ca->devnum); } incdata=1; break; } switch(ca->dialdata[i]&0x0f) { case 0x0d: /* SEP */ if(dotcount<4) { if(cur>255) { incdata=1; if(ca->dev->ccwtrace) { logmsg(_("HHCCA300D %4.4x : Found incorrect IP address section at position %d\n"),ca->devnum,dotcount+1); logmsg(_("HHCCA300D %4.4x : %d greater than 255\n"),ca->devnum,cur); } break; } destip<<=8; destip+=cur; cur=0; dotcount++; } else { incdata=1; if(ca->dev->ccwtrace) { logmsg(_("HHCCA300D %4.4x : Too many separators in dial data\n"),ca->devnum); } break; } break; case 0x0c: /* EON */ goteon=1; break; /* A,B,E,F not valid */ case 0x0a: case 0x0b: case 0x0e: case 0x0f: incdata=1; if(ca->dev->ccwtrace) { logmsg(_("HHCCA300D %4.4x : Incorrect dial data byte %2.2x\n"),ca->devnum,ca->dialdata[i]); } break; default: cur*=10; cur+=ca->dialdata[i]&0x0f; break; } if(incdata) { break; } } if(incdata) { return -1; } if(dotcount<4) { if(ca->dev->ccwtrace) { logmsg(_("HHCCA300D %4.4x : Not enough separators (only %d found) in dial data\n"),ca->devnum,dotcount); } return -1; } if(cur>65535) { if(ca->dev->ccwtrace) { logmsg(_("HHCCA300D %4.4x : Destination TCP port %d exceeds maximum of 65535\n"),ca->devnum,cur); } return -1; } destport=cur; /* Update RHOST/RPORT */ ca->rport=destport; ca->rhost=destip; return(commadpt_connout(ca)); } static void connect_message(int sfd, int devnum, int term) { int rc; struct sockaddr_in client; socklen_t namelen; char *ipaddr; char msgtext[256]; namelen = sizeof(client); rc = getpeername (sfd, (struct sockaddr *)&client, &namelen); ipaddr = inet_ntoa(client.sin_addr); sprintf(msgtext, "%s:%d TERMINAL CONNECTED CUA=%4.4X TERM=%s", ipaddr, (int)ntohs(client.sin_port), devnum, (term == COMMADPT_TERM_TTY) ? "TTY" : "2741"); logmsg( _("%s\n"), msgtext); write(sfd, msgtext, strlen(msgtext)); write(sfd, "\r\n", 2); } /*-------------------------------------------------------------------*/ /* Communication Thread - Read socket data (after POLL request */ /*-------------------------------------------------------------------*/ static int commadpt_read_poll(COMMADPT *ca) { BYTE b; int rc; while((rc=read_socket(ca->sfd,&b,1))>0) { if(b==0x32) { continue; } if(b==0x37) { return(1); } } if(rc>0) { /* Store POLL IX in bfr followed by byte */ commadpt_ring_push(&ca->inbfr,ca->pollix); commadpt_ring_push(&ca->inbfr,b); return(2); } return(0); } static void commadpt_read_tty(COMMADPT *ca, BYTE * bfr, int len) { BYTE bfr2[256]; BYTE bfr3[3]; BYTE c; int i1; int o1; for (i1 = 0, o1 = 0; i1 < len; i1++) { c = (unsigned char) bfr[i1]; if (ca->telnet_opt) { ca->telnet_opt = 0; if(ca->dev->ccwtrace) logmsg(_("HHCCA300D %4.4X: Received TELNET CMD 0x%02x 0x%02x\n"), ca->dev->devnum, ca->telnet_cmd, c); bfr3[0] = 0xff; /* IAC */ /* set won't/don't for all received commands */ bfr3[1] = (ca->telnet_cmd == 0xfd) ? 0xfc : 0xfe; bfr3[2] = c; if(ca->dev->ccwtrace) logmsg(_("HHCCA300D %4.4X: Sending TELNET CMD 0x%02x 0x%02x\n"), ca->dev->devnum, bfr3[1], bfr3[2]); commadpt_ring_pushbfr(&ca->outbfr,bfr3,3); continue; } if (ca->telnet_iac) { ca->telnet_iac = 0; if(ca->dev->ccwtrace) logmsg(_("HHCCA300D %4.4X: Received TELNET IAC 0x%02x\n"), ca->dev->devnum, c); switch (c) { case 0xFB: /* TELNET WILL option cmd */ case 0xFD: /* TELNET DO option cmd */ ca->telnet_opt = 1; ca->telnet_cmd = c; break; case 0xF4: /* TELNET interrupt */ if (!ca->telnet_int) { ca->telnet_int = 1; commadpt_ring_flush(&ca->inbfr); commadpt_ring_flush(&ca->rdwrk); commadpt_ring_flush(&ca->outbfr); } break; } continue; } if (c == 0xFF) { /* TELNET IAC */ ca->telnet_iac = 1; continue; } else { ca->telnet_iac = 0; } if (c == 0x0a) continue; c &= 0x7f; if (ca->uctrans && c >= 'a' && c <= 'z') { c = toupper( c ); /* make uppercase */ } if (ca->term == COMMADPT_TERM_TTY) { #if 0 if (c == 0x0d) // char was CR ? #endif ca->eol_flag = 1; if (byte_parity_table[(unsigned int)(c & 0x7f)]) c |= 0x80; // make even parity bfr2[o1++] = byte_reverse_table[(unsigned int)(c & 0xff)]; } else { /* 2741 */ if (c == 0x0d) { // char was CR ? ca->eol_flag = 1; #if 0 continue; // ignore #endif } if (ca->code_table_fromebcdic) { // do only if code != none c = host_to_guest(c & 0x7f); // first translate to EBCDIC bfr2[o1++] = ca->code_table_fromebcdic[ c ]; // then to 2741 code } } } if (o1) { commadpt_ring_pushbfr(&ca->inbfr,bfr2,(size_t)o1); logdump("RCV2",ca->dev,bfr2,o1); ca->readcomp = 1; } } /*-------------------------------------------------------------------*/ /* Communication Thread - Read socket data */ /*-------------------------------------------------------------------*/ static void commadpt_read(COMMADPT *ca) { BYTE bfr[256]; int gotdata; int rc; gotdata=0; for (;;) { if (IS_BSC_LNCTL(ca)) { rc=read_socket(ca->sfd,bfr,256); } else { /* read_socket has changed from 3.04 to 3.06 - async needs old way */ /* is BSC similarly broken? */ #ifdef _MSVC_ rc=recv(ca->sfd,bfr,256,0); #else rc=read(ca->sfd,bfr,256); #endif } if (rc <= 0) break; logdump("RECV",ca->dev,bfr,rc); if (IS_ASYNC_LNCTL(ca)) { commadpt_read_tty(ca, bfr, rc); } else { commadpt_ring_pushbfr(&ca->inbfr,bfr,(size_t)rc); } /* end of else (async) */ gotdata=1; } if(!gotdata) { if(ca->connect) { ca->connect=0; close_socket(ca->sfd); ca->sfd=-1; if(ca->curpending!=COMMADPT_PEND_IDLE) { ca->curpending=COMMADPT_PEND_IDLE; signal_condition(&ca->ipc); } } } } /*-------------------------------------------------------------------*/ /* Communication Thread - Set TimeOut */ /*-------------------------------------------------------------------*/ static struct timeval *commadpt_setto(struct timeval *tv,int tmo) { if(tmo!=0) { if(tmo<0) { tv->tv_sec=0; tv->tv_usec=1; } else { tv->tv_sec=tmo/1000; tv->tv_usec=(tmo%1000)*1000; } return(tv); } return(NULL); } /*-------------------------------------------------------------------*/ /* Communication Thread main loop */ /*-------------------------------------------------------------------*/ static void *commadpt_thread(void *vca) { COMMADPT *ca; /* Work CA Control Block Pointer */ int sockopt; /* Used for setsocketoption */ struct sockaddr_in sin; /* bind socket address structure */ int devnum; /* device number copy for convenience*/ int rc; /* return code from various rtns */ struct timeval tv; /* select timeout structure */ struct timeval *seltv; /* ptr to the timeout structure */ fd_set rfd,wfd,xfd; /* SELECT File Descriptor Sets */ BYTE pipecom; /* Byte read from IPC pipe */ int tempfd; /* Temporary FileDesc holder */ BYTE b; /* Work data byte */ int writecont; /* Write contention active */ int soerr; /* getsockopt SOERROR value */ socklen_t soerrsz; /* Size for getsockopt */ int maxfd; /* highest FD for select */ int ca_shutdown; /* Thread shutdown internal flag */ int init_signaled; /* Thread initialisation signaled */ int pollact; /* A Poll Command is in progress */ int i; /* Ye Old Loop Counter */ int eintrcount=0; /* Number of times EINTR occured in */ /* a row.. Over 100 : Bail out ! */ /*---------------------END OF DECLARES---------------------------*/ /* fetch the commadpt structure */ ca=(COMMADPT *)vca; /* Obtain the CA lock */ obtain_lock(&ca->lock); /* get a work copy of devnum (for messages) */ devnum=ca->devnum; /* reset shutdown flag */ ca_shutdown=0; init_signaled=0; logmsg(_("HHCCA002I %4.4X:Line Communication thread "TIDPAT" started\n"),devnum,thread_id()); pollact=0; /* Initialise Poll activity flag */ /* Determine if we should listen */ /* if this is a DIAL=OUT only line, no listen is necessary */ if(ca->dolisten) { /* Create the socket for a listen */ ca->lfd=socket(AF_INET,SOCK_STREAM,0); if(!socket_is_socket(ca->lfd)) { logmsg(_("HHCCA003E %4.4X:Cannot obtain socket for incoming calls : %s\n"),devnum,strerror(HSO_errno)); ca->have_cthread=0; release_lock(&ca->lock); return NULL; } /* Turn blocking I/O off */ /* set socket to NON-blocking mode */ socket_set_blocking_mode(ca->lfd,0); /* Reuse the address regardless of any */ /* spurious connection on that port */ sockopt=1; setsockopt(ca->lfd,SOL_SOCKET,SO_REUSEADDR,(GETSET_SOCKOPT_T*)&sockopt,sizeof(sockopt)); /* Bind the socket */ sin.sin_family=AF_INET; sin.sin_addr.s_addr=ca->lhost; sin.sin_port=htons(ca->lport); while(1) { rc=bind(ca->lfd,(struct sockaddr *)&sin,sizeof(sin)); if(rc<0) { if(HSO_errno==HSO_EADDRINUSE) { logmsg(_("HHCCA004W %4.4X:Waiting 5 seconds for port %d to become available\n"),devnum,ca->lport); /* * Check for a shutdown condition on entry */ if(ca->curpending==COMMADPT_PEND_SHUTDOWN) { ca_shutdown=1; ca->curpending=COMMADPT_PEND_IDLE; signal_condition(&ca->ipc); break; } /* Set to wait 5 seconds or input on the IPC pipe */ /* whichever comes 1st */ if(!init_signaled) { ca->curpending=COMMADPT_PEND_IDLE; signal_condition(&ca->ipc); init_signaled=1; } FD_ZERO(&rfd); FD_ZERO(&wfd); FD_ZERO(&xfd); FD_SET(ca->pipe[1],&rfd); tv.tv_sec=5; tv.tv_usec=0; release_lock(&ca->lock); rc=select(ca->pipe[1]+1,&rfd,&wfd,&wfd,&tv); obtain_lock(&ca->lock); /* * Check for a shutdown condition again after the sleep */ if(ca->curpending==COMMADPT_PEND_SHUTDOWN) { ca_shutdown=1; ca->curpending=COMMADPT_PEND_IDLE; signal_condition(&ca->ipc); break; } if(rc!=0) { /* Ignore any other command at this stage */ read_pipe(ca->pipe[1],&b,1); ca->curpending=COMMADPT_PEND_IDLE; signal_condition(&ca->ipc); } } else { logmsg(_("HHCCA018E %4.4X:Bind failed : %s\n"),devnum,strerror(HSO_errno)); ca_shutdown=1; break; } } else { break; } } /* Start the listen */ if(!ca_shutdown) { listen(ca->lfd,10); logmsg(_("HHCCA005I %4.4X:Listening on port %d for incoming TCP connections\n"), devnum, ca->lport); ca->listening=1; } } if(!init_signaled) { ca->curpending=COMMADPT_PEND_IDLE; signal_condition(&ca->ipc); init_signaled=1; } /* The MAIN select loop */ /* It will listen on the following sockets : */ /* ca->lfd : The listen socket */ /* ca->sfd : * read : When a read, prepare or DIAL command is in effect * write : When a write contention occurs * ca->pipe[0] : Always * * A 3 Seconds timer is started for a read operation */ while(!ca_shutdown) { FD_ZERO(&rfd); FD_ZERO(&wfd); FD_ZERO(&xfd); maxfd=0; if(ca->listening) { FD_SET(ca->lfd,&rfd); maxfd=maxfdlfd?ca->lfd:maxfd; } seltv=NULL; if(ca->dev->ccwtrace) { logmsg(_("HHCCA300D %4.4X:cthread - Entry - DevExec = %s\n"),devnum,commadpt_pendccw_text[ca->curpending]); } writecont=0; switch(ca->curpending) { case COMMADPT_PEND_SHUTDOWN: ca_shutdown=1; break; case COMMADPT_PEND_IDLE: break; case COMMADPT_PEND_READ: if(!ca->connect) { ca->curpending=COMMADPT_PEND_IDLE; signal_condition(&ca->ipc); break; } if(ca->inbfr.havedata) { ca->curpending=COMMADPT_PEND_IDLE; signal_condition(&ca->ipc); break; } seltv=commadpt_setto(&tv,ca->rto); FD_SET(ca->sfd,&rfd); maxfd=maxfdsfd?ca->sfd:maxfd; break; case COMMADPT_PEND_POLL: /* Poll active check - provision for write contention */ /* pollact will be reset when NON syn data is received*/ /* or when the read times out */ /* Also prevents WRITE from exiting early */ if(!pollact && !writecont) { int gotenq; pollact=1; gotenq=0; /* Send SYN+SYN */ commadpt_ring_push(&ca->outbfr,0x32); commadpt_ring_push(&ca->outbfr,0x32); /* Fill the Output ring with POLL Data */ /* Up to 7 chars or ENQ */ for(i=0;i<7;i++) { if(!ca->pollbfr.havedata) { break; } ca->pollused++; b=commadpt_ring_pop(&ca->pollbfr); if(b!=0x2D) { commadpt_ring_push(&ca->outbfr,b); } else { gotenq=1; break; } } if(!gotenq) { if(ca->dev->ccwtrace) { logmsg(_("HHCCA300D %4.4X:Poll Command abort - Poll address >7 Bytes\n"),devnum); } ca->badpoll=1; ca->curpending=COMMADPT_PEND_IDLE; signal_condition(&ca->ipc); break; } b=commadpt_ring_pop(&ca->pollbfr); ca->pollix=b; seltv=commadpt_setto(&tv,ca->pto); } if(!writecont && ca->pto!=0) { /* Set tv value (have been set earlier) */ seltv=&tv; /* Set to read data still */ FD_SET(ca->sfd,&rfd); maxfd=maxfdsfd?ca->sfd:maxfd; } /* DO NOT BREAK - Continue with WRITE processing */ case COMMADPT_PEND_WRITE: if(!writecont) { while(ca->outbfr.havedata) { b=commadpt_ring_pop(&ca->outbfr); if(ca->dev->ccwtrace) { logmsg(_("HHCCA300D %4.4X:Writing 1 byte in socket : %2.2X\n"),ca->devnum,b); } rc=write_socket(ca->sfd,&b,1); if(rc!=1) { if(0 #ifndef WIN32 || EAGAIN == errno #endif || HSO_EWOULDBLOCK == HSO_errno ) { /* Contending for write */ writecont=1; FD_SET(ca->sfd,&wfd); maxfd=maxfdsfd?ca->sfd:maxfd; break; } else { close_socket(ca->sfd); ca->sfd=-1; ca->connect=0; ca->curpending=COMMADPT_PEND_IDLE; signal_condition(&ca->ipc); break; } } } if (IS_ASYNC_LNCTL(ca)) { /* Sleep for 0.01 sec - for faithful emulation we would * slow everything down to 110 or 150 baud or worse :) * Without this sleep, CPU use is excessive. */ usleep(10000); } } else { FD_SET(ca->sfd,&wfd); maxfd=maxfdsfd?ca->sfd:maxfd; } if(!writecont && !pollact) { ca->curpending=COMMADPT_PEND_IDLE; signal_condition(&ca->ipc); break; } break; case COMMADPT_PEND_DIAL: if(ca->connect) { ca->curpending=COMMADPT_PEND_IDLE; signal_condition(&ca->ipc); break; } rc=commadpt_initiate_userdial(ca); if(rc!=0 || (rc==0 && ca->connect)) { ca->curpending=COMMADPT_PEND_IDLE; signal_condition(&ca->ipc); break; } FD_SET(ca->sfd,&wfd); maxfd=maxfdsfd?ca->sfd:maxfd; break; case COMMADPT_PEND_ENABLE: if(ca->connect) { ca->curpending=COMMADPT_PEND_IDLE; signal_condition(&ca->ipc); break; } switch(ca->dialin+ca->dialout*2) { case 0: /* DIAL=NO */ /* callissued is set here when the call */ /* actually failed. But we want to time */ /* a bit for program issuing ENABLES in */ /* a tight loop */ if(ca->callissued) { seltv=commadpt_setto(&tv,ca->eto); break; } /* Issue a Connect out */ rc=commadpt_connout(ca); if(rc==0) { /* Call issued */ if(ca->connect) { /* Call completed already */ ca->curpending=COMMADPT_PEND_IDLE; signal_condition(&ca->ipc); } else { /* Call initiated - FD will be ready */ /* for writing when the connect ends */ /* getsockopt/SOERROR will tell if */ /* the call was sucessfull or not */ FD_SET(ca->sfd,&wfd); maxfd=maxfdsfd?ca->sfd:maxfd; ca->callissued=1; } } /* Call did not succeed */ /* Manual says : on a leased line, if DSR is not up */ /* the terminate enable after a timeout.. That is */ /* what the call just did (although the time out */ /* was probably instantaneous) */ /* This is the equivalent of the comm equipment */ /* being offline */ /* INITIATE A 3 SECOND TIMEOUT */ /* to prevent OSes from issuing a loop of ENABLES */ else { seltv=commadpt_setto(&tv,ca->eto); } break; default: case 3: /* DIAL=INOUT */ case 1: /* DIAL=IN */ /* Wait forever */ break; case 2: /* DIAL=OUT */ /* Makes no sense */ /* line must be enabled through a DIAL command */ ca->curpending=COMMADPT_PEND_IDLE; signal_condition(&ca->ipc); break; } /* For cases not DIAL=OUT, the listen is already started */ break; /* The CCW Executor says : DISABLE */ case COMMADPT_PEND_DISABLE: if(ca->connect) { close_socket(ca->sfd); ca->sfd=-1; ca->connect=0; } ca->curpending=COMMADPT_PEND_IDLE; signal_condition(&ca->ipc); break; /* A PREPARE has been issued */ case COMMADPT_PEND_PREPARE: if(!ca->connect || ca->inbfr.havedata) { ca->curpending=COMMADPT_PEND_IDLE; signal_condition(&ca->ipc); break; } FD_SET(ca->sfd,&rfd); maxfd=maxfdsfd?ca->sfd:maxfd; break; /* Don't know - shouldn't be here anyway */ default: break; } /* If the CA is shutting down, exit the loop now */ if(ca_shutdown) { ca->curpending=COMMADPT_PEND_IDLE; signal_condition(&ca->ipc); break; } /* Set the IPC pipe in the select */ FD_SET(ca->pipe[0],&rfd); /* The the MAX File Desc for Arg 1 of SELECT */ maxfd=maxfdpipe[0]?ca->pipe[0]:maxfd; maxfd++; /* Release the CA Lock before the select - all FDs addressed by the select are only */ /* handled by the thread, and communication from CCW Executor/others to this thread */ /* is via the pipe, which queues the info */ release_lock(&ca->lock); if(ca->dev->ccwtrace) { logmsg(_("HHCCA300D %4.4X:cthread - Select IN maxfd = %d / Devexec = %s\n"),devnum,maxfd,commadpt_pendccw_text[ca->curpending]); } rc=select(maxfd,&rfd,&wfd,&xfd,seltv); if(ca->dev->ccwtrace) { logmsg(_("HHCCA300D %4.4X:cthread - Select OUT rc=%d\n"),devnum,rc); } /* Get the CA lock back */ obtain_lock(&ca->lock); if(rc==-1) { if(errno==EINTR) { eintrcount++; if(eintrcount>100) { break; } continue; } logmsg(_("HHCCA006T %4.4X:Select failed : %s\n"),devnum,strerror(HSO_errno)); break; } eintrcount=0; /* Select timed out */ if(rc==0) { pollact=0; /* Poll not active */ if(ca->dev->ccwtrace) { logmsg(_("HHCCA300D %4.4X:cthread - Select TIME OUT\n"),devnum); } /* Reset Call issued flag */ ca->callissued=0; /* timeout condition */ signal_condition(&ca->ipc); ca->curpending=COMMADPT_PEND_IDLE; continue; } if(FD_ISSET(ca->pipe[0],&rfd)) { rc=read_pipe(ca->pipe[0],&pipecom,1); if(rc==0) { if(ca->dev->ccwtrace) { logmsg(_("HHCCA300D %4.4X:cthread - IPC Pipe closed\n"),devnum); } /* Pipe closed : terminate thread & release CA */ ca_shutdown=1; break; } if(ca->dev->ccwtrace) { logmsg(_("HHCCA300D %4.4X:cthread - IPC Pipe Data ; code = %d\n"),devnum,pipecom); } switch(pipecom) { case 0: /* redrive select */ /* occurs when a new CCW is being executed */ break; case 1: /* Halt current I/O */ ca->callissued=0; if(ca->curpending==COMMADPT_PEND_DIAL) { close_socket(ca->sfd); ca->sfd=-1; } ca->curpending=COMMADPT_PEND_IDLE; ca->haltpending=1; signal_condition(&ca->ipc); signal_condition(&ca->ipc_halt); /* Tell the halt initiator too */ break; default: break; } continue; } if(ca->connect) { if(FD_ISSET(ca->sfd,&rfd)) { int dopoll; dopoll=0; if(ca->dev->ccwtrace) { logmsg(_("HHCCA300D %4.4X:cthread - inbound socket data\n"),devnum); } if(pollact && IS_BSC_LNCTL(ca)) { switch(commadpt_read_poll(ca)) { case 0: /* Only SYNs received */ /* Continue the timeout */ dopoll=1; break; case 1: /* EOT Received */ /* Send next poll sequence */ pollact=0; dopoll=1; break; case 2: /* Something else received */ /* Index byte already stored in inbfr */ /* read the remaining data and return */ ca->pollsm=1; dopoll=0; break; default: /* Same as 0 */ dopoll=1; break; } } if(IS_ASYNC_LNCTL(ca) || !dopoll) { commadpt_read(ca); ca->curpending=COMMADPT_PEND_IDLE; signal_condition(&ca->ipc); continue; } } } if(ca->sfd>=0) { if(FD_ISSET(ca->sfd,&wfd)) { if(ca->dev->ccwtrace) { logmsg(_("HHCCA300D %4.4X:cthread - socket write available\n"),devnum); } switch(ca->curpending) { case COMMADPT_PEND_DIAL: case COMMADPT_PEND_ENABLE: /* Leased line enable call case */ soerrsz=sizeof(soerr); getsockopt(ca->sfd,SOL_SOCKET,SO_ERROR,(GETSET_SOCKOPT_T*)&soerr,&soerrsz); if(soerr==0) { ca->connect=1; } else { logmsg(_("HHCCA007W %4.4X:Outgoing call failed during %s command : %s\n"),devnum,commadpt_pendccw_text[ca->curpending],strerror(soerr)); if(ca->curpending==COMMADPT_PEND_ENABLE) { /* Ensure top of the loop doesn't restart a new call */ /* but starts a 3 second timer instead */ ca->callissued=1; } ca->connect=0; close_socket(ca->sfd); ca->sfd=-1; } signal_condition(&ca->ipc); ca->curpending=COMMADPT_PEND_IDLE; break; case COMMADPT_PEND_WRITE: writecont=0; break; default: break; } continue; } } /* Test for incoming call */ if(ca->listening) { if(FD_ISSET(ca->lfd,&rfd)) { logmsg(_("HHCCA008I %4.4X:cthread - Incoming Call\n"),devnum); tempfd=accept(ca->lfd,NULL,0); if(tempfd<0) { continue; } /* If the line is already connected, just close */ /* this call */ if(ca->connect) { close_socket(tempfd); continue; } /* Turn non-blocking I/O on */ /* set socket to NON-blocking mode */ socket_set_blocking_mode(tempfd,0); /* Check the line type & current operation */ /* if DIAL=IN or DIAL=INOUT or DIAL=NO */ if(ca->dialin || (ca->dialin+ca->dialout==0)) { /* check if ENABLE is in progress */ if(ca->curpending==COMMADPT_PEND_ENABLE) { /* Accept the call, indicate the line */ /* is connected and notify CCW exec */ ca->curpending=COMMADPT_PEND_IDLE; ca->connect=1; ca->sfd=tempfd; signal_condition(&ca->ipc); if (IS_ASYNC_LNCTL(ca)) { connect_message(ca->sfd, ca->devnum, ca->term); } continue; } /* if this is a leased line, accept the */ /* call anyway */ if(ca->dialin==0) { ca->connect=1; ca->sfd=tempfd; if (IS_ASYNC_LNCTL(ca)) { connect_message(ca->sfd, ca->devnum, ca->term); } continue; } } /* All other cases : just reject the call */ close_socket(tempfd); } } } ca->curpending=COMMADPT_PEND_CLOSED; /* Check if we already signaled the init process */ if(!init_signaled) { signal_condition(&ca->ipc); } /* The CA is shutting down - terminate the thread */ /* NOTE : the requestor was already notified upon */ /* detection of PEND_SHTDOWN. However */ /* the requestor will only run when the */ /* lock is released, because back */ /* notification was made while holding */ /* the lock */ logmsg(_("HHCCA009I %4.4X:BSC utility thread terminated\n"),ca->devnum); release_lock(&ca->lock); return NULL; } /*-------------------------------------------------------------------*/ /* Wakeup the comm thread */ /* Code : 0 -> Just wakeup the thread to redrive the select */ /* Code : 1 -> Halt the current executing I/O */ /*-------------------------------------------------------------------*/ static void commadpt_wakeup(COMMADPT *ca,BYTE code) { write_pipe(ca->pipe[1],&code,1); } /*-------------------------------------------------------------------*/ /* Wait for a copndition from the thread */ /* MUST HOLD the CA lock */ /*-------------------------------------------------------------------*/ static void commadpt_wait(DEVBLK *dev) { COMMADPT *ca; ca=dev->commadpt; wait_condition(&ca->ipc,&ca->lock); } /*-------------------------------------------------------------------*/ /* Halt currently executing I/O command */ /*-------------------------------------------------------------------*/ static void commadpt_halt(DEVBLK *dev) { if(!dev->busy) { return; } obtain_lock(&dev->commadpt->lock); commadpt_wakeup(dev->commadpt,1); /* Due to the mysteries of the host OS scheduling */ /* the wait_condition may or may not exit after */ /* the CCW executor thread relinquishes control */ /* This however should not be of any concern */ /* */ /* but returning from the wait guarantees that */ /* the working thread will (or has) notified */ /* the CCW executor to terminate the current I/O */ wait_condition(&dev->commadpt->ipc_halt,&dev->commadpt->lock); release_lock(&dev->commadpt->lock); } /* The following 3 MSG functions ensure only 1 (one) */ /* hardcoded instance exist for the same numbered msg */ /* that is issued on multiple situations */ static void msg013e(DEVBLK *dev,char *kw,char *kv) { logmsg(_("HHCCA013E %4.4X:Incorrect %s specification %s\n"),dev->devnum,kw,kv); } static void msg015e(DEVBLK *dev,char *dialt,char *kw) { logmsg(_("HHCCA015E %4.4X:Missing parameter : DIAL=%s and %s not specified\n"),dev->devnum,dialt,kw); } static void msg016w017i(DEVBLK *dev,char *dialt,char *kw,char *kv) { logmsg(_("HHCCA016W %4.4X:Conflicting parameter : DIAL=%s and %s=%s specified\n"),dev->devnum,dialt,kw,kv); logmsg(_("HHCCA017I %4.4X:RPORT parameter ignored\n"),dev->devnum); } /*-------------------------------------------------------------------*/ /* Device Initialisation */ /*-------------------------------------------------------------------*/ static int commadpt_init_handler (DEVBLK *dev, int argc, char *argv[]) { char thread_name[32]; int i; int ix; int rc; int pc; /* Parse code */ int errcnt; struct in_addr in_temp; char *dialt; char fmtbfr[64]; int etospec; /* ETO= Specified */ union { int num; char text[80]; } res; char bf[4]; dev->devtype=0x2703; if(dev->ccwtrace) { logmsg(_("HHCCA300D %4.4X:Initialisation starting\n"),dev->devnum); } rc=commadpt_alloc_device(dev); if(rc<0) { logmsg(_("HHCCA010I %4.4X:initialisation not performed\n"), dev->devnum); return(-1); } if(dev->ccwtrace) { logmsg(_("HHCCA300D %4.4X:Initialisation : Control block allocated\n"),dev->devnum); } errcnt=0; /* * Initialise ports & hosts */ dev->commadpt->sfd=-1; dev->commadpt->lport=0; dev->commadpt->rport=0; dev->commadpt->lhost=INADDR_ANY; dev->commadpt->rhost=INADDR_NONE; dev->commadpt->dialin=0; dev->commadpt->dialout=1; dev->commadpt->rto=3000; /* Read Time-Out in milis */ dev->commadpt->pto=3000; /* Poll Time-out in milis */ dev->commadpt->eto=10000; /* Enable Time-out in milis */ dev->commadpt->lnctl=COMMADPT_LNCTL_BSC; dev->commadpt->term=COMMADPT_TERM_TTY; dev->commadpt->uctrans=FALSE; dev->commadpt->code_table_toebcdic = xlate_table_ebcd_toebcdic; dev->commadpt->code_table_fromebcdic = xlate_table_ebcd_fromebcdic; memset(dev->commadpt->byte_skip_table, 0, 256); etospec=0; for(i=0;idevnum,argv[i]); errcnt++; continue; } if(pc==0) { logmsg(_("HHCCA012E %4.4X:Unrecognized parameter %s\n"),dev->devnum,argv[i]); errcnt++; continue; } switch(pc) { case COMMADPT_KW_LPORT: rc=commadpt_getport(res.text); if(rc<0) { errcnt++; msg013e(dev,"LPORT",res.text); break; } dev->commadpt->lport=rc; break; case COMMADPT_KW_LHOST: if(strcmp(res.text,"*")==0) { dev->commadpt->lhost=INADDR_ANY; break; } rc=commadpt_getaddr(&dev->commadpt->lhost,res.text); if(rc!=0) { msg013e(dev,"LHOST",res.text); errcnt++; } break; case COMMADPT_KW_RPORT: rc=commadpt_getport(res.text); if(rc<0) { errcnt++; msg013e(dev,"RPORT",res.text); break; } dev->commadpt->rport=rc; break; case COMMADPT_KW_RHOST: if(strcmp(res.text,"*")==0) { dev->commadpt->rhost=INADDR_NONE; break; } rc=commadpt_getaddr(&dev->commadpt->rhost,res.text); if(rc!=0) { msg013e(dev,"RHOST",res.text); errcnt++; } break; case COMMADPT_KW_READTO: dev->commadpt->rto=atoi(res.text); break; case COMMADPT_KW_POLLTO: dev->commadpt->pto=atoi(res.text); break; case COMMADPT_KW_ENABLETO: dev->commadpt->eto=atoi(res.text); etospec=1; break; case COMMADPT_KW_LNCTL: if(strcasecmp(res.text,"tele2")==0 || strcasecmp(res.text,"ibm1")==0 ) { dev->commadpt->lnctl = COMMADPT_LNCTL_ASYNC; dev->commadpt->rto=28000; /* Read Time-Out in milis */ } else if(strcasecmp(res.text,"bsc")) { dev->commadpt->lnctl = COMMADPT_LNCTL_BSC; } else { msg013e(dev,"LNCTL",res.text); } break; case COMMADPT_KW_TERM: if(strcasecmp(res.text,"tty")==0) { dev->commadpt->term = COMMADPT_TERM_TTY; } else if(strcasecmp(res.text,"2741")==0) { dev->commadpt->term = COMMADPT_TERM_2741; } else { msg013e(dev,"TERM",res.text); } break; case COMMADPT_KW_CODE: if(strcasecmp(res.text,"corr")==0) { dev->commadpt->code_table_toebcdic = xlate_table_cc_toebcdic; dev->commadpt->code_table_fromebcdic = xlate_table_cc_fromebcdic; } else if(strcasecmp(res.text,"ebcd")==0) { dev->commadpt->code_table_toebcdic = xlate_table_ebcd_toebcdic; dev->commadpt->code_table_fromebcdic = xlate_table_ebcd_fromebcdic; } else if(strcasecmp(res.text,"none")==0) { dev->commadpt->code_table_toebcdic = NULL; dev->commadpt->code_table_fromebcdic = NULL; } else { msg013e(dev,"CODE",res.text); } break; case COMMADPT_KW_UCTRANS: if(strcasecmp(res.text,"no")==0) { dev->commadpt->uctrans = FALSE; } else if(strcasecmp(res.text,"yes")==0) { dev->commadpt->uctrans = TRUE; } else { msg013e(dev,"UCTRANS",res.text); } break; case COMMADPT_KW_SKIP: if (strlen(res.text) < 2) break; for (i=0; i < (int)strlen(res.text); i+= 2) { bf[0] = res.text[i+0]; bf[1] = res.text[i+1]; bf[2] = 0; sscanf(bf, "%x", &ix); dev->commadpt->byte_skip_table[ix] = 1; } break; case COMMADPT_KW_SWITCHED: case COMMADPT_KW_DIAL: if(strcasecmp(res.text,"yes")==0 || strcmp(res.text,"1")==0 || strcasecmp(res.text,"inout")==0) { dev->commadpt->dialin=1; dev->commadpt->dialout=1; break; } if(strcasecmp(res.text,"no")==0 || strcmp(res.text,"0")==0) { dev->commadpt->dialin=0; dev->commadpt->dialout=0; break; } if(strcasecmp(res.text,"in")==0) { dev->commadpt->dialin=1; dev->commadpt->dialout=0; break; } if(strcasecmp(res.text,"out")==0) { dev->commadpt->dialin=0; dev->commadpt->dialout=1; break; } logmsg(_("HHCCA014E %4.4X:Incorrect switched/dial specification %s; defaulting to DIAL=OUT\n"),dev->devnum,res.text); dev->commadpt->dialin=0; dev->commadpt->dialout=0; break; default: break; } } /* * Check parameters consistency * when DIAL=NO : * lport must not be 0 * lhost may be anything * rport must not be 0 * rhost must not be INADDR_NONE * when DIAL=IN or DIAL=INOUT * lport must NOT be 0 * lhost may be anything * rport MUST be 0 * rhost MUST be INADDR_NONE * when DIAL=OUT * lport MUST be 0 * lhost MUST be INADDR_ANY * rport MUST be 0 * rhost MUST be INADDR_NONE */ switch(dev->commadpt->dialin+dev->commadpt->dialout*2) { case 0: dialt="NO"; break; case 1: dialt="IN"; break; case 2: dialt="OUT"; break; case 3: dialt="INOUT"; break; default: dialt="*ERR*"; break; } switch(dev->commadpt->dialin+dev->commadpt->dialout*2) { case 0: /* DIAL = NO */ dev->commadpt->eto=0; if(dev->commadpt->lport==0) { msg015e(dev,dialt,"LPORT"); errcnt++; } if(dev->commadpt->rport==0) { msg015e(dev,dialt,"RPORT"); errcnt++; } if(dev->commadpt->rhost==INADDR_NONE) { msg015e(dev,dialt,"RHOST"); errcnt++; } if(etospec) { snprintf(fmtbfr,sizeof(fmtbfr),"%d",dev->commadpt->eto); msg016w017i(dev,dialt,"ETO",fmtbfr); errcnt++; } dev->commadpt->eto=0; break; case 1: /* DIAL = IN */ case 3: /* DIAL = INOUT */ if(dev->commadpt->lport==0) { msg015e(dev,dialt,"LPORT"); errcnt++; } if(dev->commadpt->rport!=0) { snprintf(fmtbfr,sizeof(fmtbfr),"%d",dev->commadpt->rport); msg016w017i(dev,dialt,"RPORT",fmtbfr); } if(dev->commadpt->rhost!=INADDR_NONE) { in_temp.s_addr=dev->commadpt->rhost; msg016w017i(dev,dialt,"RHOST",inet_ntoa(in_temp)); dev->commadpt->rhost=INADDR_NONE; } break; case 2: /* DIAL = OUT */ if(dev->commadpt->lport!=0) { snprintf(fmtbfr,sizeof(fmtbfr),"%d",dev->commadpt->lport); msg016w017i(dev,dialt,"LPORT",fmtbfr); dev->commadpt->lport=0; } if(dev->commadpt->rport!=0) { snprintf(fmtbfr,sizeof(fmtbfr),"%d",dev->commadpt->rport); msg016w017i(dev,dialt,"RPORT",fmtbfr); dev->commadpt->rport=0; } if(dev->commadpt->lhost!=INADDR_ANY) /* Actually it's more like INADDR_NONE */ { in_temp.s_addr=dev->commadpt->lhost; msg016w017i(dev,dialt,"LHOST",inet_ntoa(in_temp)); dev->commadpt->lhost=INADDR_ANY; } if(dev->commadpt->rhost!=INADDR_NONE) { in_temp.s_addr=dev->commadpt->rhost; msg016w017i(dev,dialt,"RHOST",inet_ntoa(in_temp)); dev->commadpt->rhost=INADDR_NONE; } break; } if(errcnt>0) { logmsg(_("HHCCA021I %4.4X:Initialisation failed due to previous errors\n"),dev->devnum); return -1; } in_temp.s_addr=dev->commadpt->lhost; in_temp.s_addr=dev->commadpt->rhost; dev->bufsize=256; dev->numsense=2; memset(dev->sense,0,sizeof(dev->sense)); /* Initialise various flags & statuses */ dev->commadpt->enabled=0; dev->commadpt->connect=0; dev->fd=100; /* Ensures 'close' function called */ dev->commadpt->devnum=dev->devnum; dev->commadpt->telnet_opt=0; dev->commadpt->telnet_iac=0; dev->commadpt->telnet_int=0; dev->commadpt->eol_flag=0; dev->commadpt->telnet_cmd=0; /* Initialize the device identifier bytes */ dev->numdevid = sysblk.legacysenseid ? 7 : 0; dev->devid[0] = 0xFF; dev->devid[1] = dev->devtype >> 8; dev->devid[2] = dev->devtype & 0xFF; dev->devid[3] = 0x00; dev->devid[4] = dev->devtype >> 8; dev->devid[5] = dev->devtype & 0xFF; dev->devid[6] = 0x00; /* Initialize the CA lock */ initialize_lock(&dev->commadpt->lock); /* Initialise thread->I/O & halt initiation EVB */ initialize_condition(&dev->commadpt->ipc); initialize_condition(&dev->commadpt->ipc_halt); /* Allocate I/O -> Thread signaling pipe */ create_pipe(dev->commadpt->pipe); /* Point to the halt routine for HDV/HIO/HSCH handling */ dev->halt_device=commadpt_halt; /* Obtain the CA lock */ obtain_lock(&dev->commadpt->lock); /* Indicate listen required if DIAL!=OUT */ if(dev->commadpt->dialin || (!dev->commadpt->dialin && !dev->commadpt->dialout)) { dev->commadpt->dolisten=1; } else { dev->commadpt->dolisten=0; } /* Start the async worker thread */ /* Set thread-name for debugging purposes */ snprintf(thread_name,sizeof(thread_name), "commadpt %4.4X thread",dev->devnum); thread_name[sizeof(thread_name)-1]=0; dev->commadpt->curpending=COMMADPT_PEND_TINIT; if(create_thread(&dev->commadpt->cthread,DETACHED,commadpt_thread,dev->commadpt,thread_name)) { logmsg(D_("HHCCA022E create_thread: %s\n"),strerror(errno)); release_lock(&dev->commadpt->lock); return -1; } commadpt_wait(dev); if(dev->commadpt->curpending!=COMMADPT_PEND_IDLE) { logmsg(_("HHCCA019E %4.4x : BSC comm thread did not initialise\n"),dev->devnum); /* Release the CA lock */ release_lock(&dev->commadpt->lock); return -1; } dev->commadpt->have_cthread=1; /* Release the CA lock */ release_lock(&dev->commadpt->lock); /* Indicate succesfull completion */ return 0; } static char *commadpt_lnctl_names[]={ "NONE", "BSC", "ASYNC" }; /*-------------------------------------------------------------------*/ /* Query the device definition */ /*-------------------------------------------------------------------*/ static void commadpt_query_device (DEVBLK *dev, char **class, int buflen, char *buffer) { BEGIN_DEVICE_CLASS_QUERY( "LINE", dev, class, buflen, buffer ); snprintf(buffer,buflen,"%s STA=%s CN=%s, EIB=%s OP=%s", commadpt_lnctl_names[dev->commadpt->lnctl], dev->commadpt->enabled?"ENA":"DISA", dev->commadpt->connect?"YES":"NO", dev->commadpt->eibmode?"YES":"NO", commadpt_pendccw_text[dev->commadpt->curpending]); } /*-------------------------------------------------------------------*/ /* Close the device */ /* Invoked by HERCULES shutdown & DEVINIT processing */ /*-------------------------------------------------------------------*/ static int commadpt_close_device ( DEVBLK *dev ) { if(dev->ccwtrace) { logmsg(_("HHCCA300D %4.4X:Closing down\n"),dev->devnum); } /* Terminate current I/O thread if necessary */ if(dev->busy) { commadpt_halt(dev); } /* Obtain the CA lock */ obtain_lock(&dev->commadpt->lock); /* Terminate worker thread if it is still up */ if(dev->commadpt->have_cthread) { dev->commadpt->curpending=COMMADPT_PEND_SHUTDOWN; commadpt_wakeup(dev->commadpt,0); commadpt_wait(dev); dev->commadpt->cthread=(TID)-1; dev->commadpt->have_cthread=0; } /* Free all work storage */ /* The CA lock will be released by the cleanup routine */ commadpt_clean_device(dev); /* Indicate to hercules the device is no longer opened */ dev->fd=-1; if(dev->ccwtrace) { logmsg(_("HHCCA300D %4.4X:Closed down\n"),dev->devnum); } return 0; } /*-------------------------------------------------------------------*/ /* Execute a Channel Command Word */ /*-------------------------------------------------------------------*/ static void commadpt_execute_ccw (DEVBLK *dev, BYTE code, BYTE flags, BYTE chained, U16 count, BYTE prevcode, int ccwseq, BYTE *iobuf, BYTE *more, BYTE *unitstat, U16 *residual) { U32 num; /* Work : Actual CCW transfer count */ BYTE b; /* Input processing work variable : Current character */ BYTE setux; /* EOT kludge */ BYTE turnxpar; /* Write contains turn to transparent mode */ int i; /* work */ BYTE gotdle; /* Write routine DLE marker */ UNREFERENCED(flags); UNREFERENCED(chained); UNREFERENCED(prevcode); UNREFERENCED(ccwseq); *residual = 0; /* * Obtain the COMMADPT lock */ if(dev->ccwtrace) { logmsg(_("HHCCA300D %4.4X:CCW Exec - Entry code = %x\n"),dev->devnum,code); } obtain_lock(&dev->commadpt->lock); switch (code) { /*---------------------------------------------------------------*/ /* CONTROL NO-OP */ /*---------------------------------------------------------------*/ case 0x03: *residual=0; *unitstat=CSW_CE|CSW_DE; break; /*---------------------------------------------------------------*/ /* BASIC SENSE */ /*---------------------------------------------------------------*/ case 0x04: num=countnumsense?count:dev->numsense; *more=countnumsense?1:0; memcpy(iobuf,dev->sense,num); *residual=count-num; *unitstat=CSW_CE|CSW_DE; break; /*---------------------------------------------------------------*/ /* SENSE ID */ /*---------------------------------------------------------------*/ case 0xE4: /* Calculate residual byte count */ num = (count < dev->numdevid) ? count : dev->numdevid; *residual = count - num; *more = count < dev->numdevid ? 1 : 0; /* Copy device identifier bytes to channel I/O Buffer */ memcpy (iobuf, dev->devid, num); /* Return unit status */ *unitstat = CSW_CE | CSW_DE; break; /*---------------------------------------------------------------*/ /* ENABLE */ /*---------------------------------------------------------------*/ case 0x27: if(dev->commadpt->dialin+dev->commadpt->dialout*2==2) { /* Enable makes no sense on a dial out only line */ *unitstat=CSW_CE|CSW_DE|CSW_UC; dev->sense[0]=SENSE_IR; dev->sense[1]=0x2E; /* Simulate Failed Call In */ break; } if(dev->commadpt->connect) { /* Already connected */ dev->commadpt->enabled=1; *unitstat=CSW_CE|CSW_DE; break; } dev->commadpt->curpending=COMMADPT_PEND_ENABLE; commadpt_wakeup(dev->commadpt,0); commadpt_wait(dev); /* If the line is not connected now, then ENABLE failed */ if(dev->commadpt->connect) { *unitstat=CSW_CE|CSW_DE; dev->commadpt->enabled=1; /* Clean the input buffer */ commadpt_ring_flush(&dev->commadpt->inbfr); break; } if(dev->commadpt->haltpending) { *unitstat=CSW_CE|CSW_DE|CSW_UX; dev->commadpt->haltpending=0; break; } if(dev->commadpt->dialin) { *unitstat=CSW_CE|CSW_DE|CSW_UC; dev->sense[0]=SENSE_IR; dev->sense[1]=0x2e; } else { *unitstat=CSW_CE|CSW_DE|CSW_UC; dev->sense[0]=SENSE_IR; dev->sense[1]=0x21; } break; /*---------------------------------------------------------------*/ /* DISABLE */ /*---------------------------------------------------------------*/ case 0x2F: /* Reset some flags */ dev->commadpt->xparwwait=0; commadpt_ring_flush(&dev->commadpt->inbfr); /* Flush buffers */ commadpt_ring_flush(&dev->commadpt->outbfr); /* Flush buffers */ if((!dev->commadpt->dialin && !dev->commadpt->dialout) || !dev->commadpt->connect) { *unitstat=CSW_CE|CSW_DE; dev->commadpt->enabled=0; break; } dev->commadpt->curpending=COMMADPT_PEND_DISABLE; commadpt_wakeup(dev->commadpt,0); commadpt_wait(dev); dev->commadpt->enabled=0; *unitstat=CSW_CE|CSW_DE; break; /*---------------------------------------------------------------*/ /* SET MODE */ /*---------------------------------------------------------------*/ case 0x23: /* Transparent Write Wait State test */ if(dev->commadpt->xparwwait) { *unitstat=CSW_CE|CSW_DE|CSW_UC; dev->sense[0]=SENSE_CR; return; } num=1; *residual=count-num; *unitstat=CSW_CE|CSW_DE; if(dev->ccwtrace) { logmsg(_("HHCCA300D %4.4X Set Mode : %s\n"),dev->devnum,iobuf[0]&0x40 ? "EIB":"NO EIB"); } dev->commadpt->eibmode=(iobuf[0]&0x40)?1:0; break; /*---------------------------------------------------------------*/ /* POLL Command */ /*---------------------------------------------------------------*/ case 0x09: /* Transparent Write Wait State test */ if(dev->commadpt->xparwwait) { *unitstat=CSW_CE|CSW_DE|CSW_UC; dev->sense[0]=SENSE_CR; return; } /* Save POLL data */ commadpt_ring_flush(&dev->commadpt->pollbfr); commadpt_ring_pushbfr(&dev->commadpt->pollbfr,iobuf,count); /* Set some utility variables */ dev->commadpt->pollused=0; dev->commadpt->badpoll=0; /* Tell thread */ dev->commadpt->curpending=COMMADPT_PEND_POLL; commadpt_wakeup(dev->commadpt,0); commadpt_wait(dev); /* Flush the output & poll rings */ commadpt_ring_flush(&dev->commadpt->outbfr); commadpt_ring_flush(&dev->commadpt->pollbfr); /* Check for HALT */ if(dev->commadpt->haltpending) { *unitstat=CSW_CE|CSW_DE|CSW_UX; dev->commadpt->haltpending=0; break; } /* Check for bad poll data */ if(dev->commadpt->badpoll) { *unitstat=CSW_CE|CSW_DE|CSW_UC; dev->sense[0]=0x08; dev->sense[1]=0x84; break; } /* Determine remaining length */ *residual=count-dev->commadpt->pollused; /* Determine if SM should be set (succesfull or unsucessfull POLLs) */ /* exhausting poll data when all stations reported NO data */ /* does not set Status Modifier */ *unitstat=CSW_CE|CSW_DE|(dev->commadpt->pollsm?CSW_SM:0); /* NOTE : The index byte (and rest) are in the Input Ring */ break; /*---------------------------------------------------------------*/ /* DIAL */ /* Info on DIAL DATA : */ /* Dial character formats : */ /* x x x x 0 0 0 0 : 0 */ /* ........ */ /* x x x x 1 0 0 1 : 9 */ /* x x x x 1 1 0 0 : SEP */ /* x x x x 1 1 0 1 : EON */ /* EON is ignored */ /* format is : AAA/SEP/BBB/SEP/CCC/SEP/DDD/SEP/PPPP */ /* where A,B,C,D,P are numbers from 0 to 9 */ /* This perfoms an outgoing call to AAA.BBB.CCC.DDD port PPPP */ /*---------------------------------------------------------------*/ case 0x29: /* The line must have dial-out capability */ if(!dev->commadpt->dialout) { *unitstat=CSW_CE|CSW_DE|CSW_UC; dev->sense[0]=SENSE_CR; dev->sense[1]=0x04; break; } /* The line must be disabled */ if(dev->commadpt->enabled) { *unitstat=CSW_CE|CSW_DE|CSW_UC; dev->sense[0]=SENSE_CR; dev->sense[1]=0x05; break; } num=count>sizeof(dev->commadpt->dialdata) ? sizeof(dev->commadpt->dialdata) : count; memcpy(dev->commadpt->dialdata,iobuf,num); dev->commadpt->curpending=COMMADPT_PEND_DIAL; commadpt_wakeup(dev->commadpt,0); commadpt_wait(dev); *residual=count-num; if(dev->commadpt->haltpending) { *unitstat=CSW_CE|CSW_DE|CSW_UX; dev->commadpt->haltpending=0; break; } if(!dev->commadpt->connect) { *unitstat=CSW_CE|CSW_DE|CSW_UC; dev->sense[0]=SENSE_IR; dev->commadpt->enabled=0; } else { *unitstat=CSW_CE|CSW_DE; dev->commadpt->enabled=1; } break; /*---------------------------------------------------------------*/ /* READ */ /*---------------------------------------------------------------*/ case 0x02: case 0x0a: /* also INHIBIT */ setux=0; /* Check the line is enabled */ if(!dev->commadpt->enabled) { *unitstat=CSW_CE|CSW_DE|CSW_UC; dev->sense[0]=SENSE_CR; dev->sense[1]=0x06; break; } /* Transparent Write Wait State test */ if(dev->commadpt->xparwwait) { *unitstat=CSW_CE|CSW_DE|CSW_UC; dev->sense[0]=SENSE_CR; break; } /* Check for any remaining data in read work buffer */ if(dev->commadpt->readcomp) { if (IS_ASYNC_LNCTL(dev->commadpt)) { while (dev->commadpt->inbfr.havedata) { commadpt_ring_push(&dev->commadpt->rdwrk, commadpt_ring_pop(&dev->commadpt->inbfr)); } } if (( IS_BSC_LNCTL(dev->commadpt) && dev->commadpt->rdwrk.havedata) || (IS_ASYNC_LNCTL(dev->commadpt) && dev->commadpt->rdwrk.havedata && dev->commadpt->eol_flag)) { if(IS_ASYNC_LNCTL(dev->commadpt) && dev->commadpt->term == COMMADPT_TERM_2741) dev->commadpt->eol_flag = 0; num=commadpt_ring_popbfr(&dev->commadpt->rdwrk,iobuf,count); if(dev->commadpt->rdwrk.havedata) { *more=1; } *residual=count-num; *unitstat=CSW_CE|CSW_DE; if(IS_ASYNC_LNCTL(dev->commadpt) && dev->commadpt->term == COMMADPT_TERM_2741) *unitstat|=CSW_UX; // 2741 EOT break; } } if(IS_ASYNC_LNCTL(dev->commadpt) && dev->commadpt->telnet_int) { dev->commadpt->telnet_int = 0; *residual=count; *unitstat=CSW_CE|CSW_DE|CSW_UC; dev->sense[0]=SENSE_IR; break; } #if 0 // MHP TEST 2740 *residual=count; *unitstat=CSW_CE|CSW_DE; break; #endif if(dev->commadpt->datalostcond) { dev->commadpt->datalostcond=0; commadpt_ring_flush(&dev->commadpt->inbfr); *residual=count; *unitstat=CSW_CE|CSW_DE; break; } dev->commadpt->readcomp=0; *unitstat=0; num=0; /* The following is the BIG READ ROUTINE MESS */ /* the manual's indications on when to exit */ /* a read and what to transfer to the main */ /* storage is fuzzy (at best) */ /* */ /* The line input can be in 3 possible */ /* conditions : */ /* Transparent Text Mode */ /* Text Mode */ /* none of the above (initial status) */ /* transition from one mode to the other is */ /* also not very well documented */ /* so the following code is based on */ /* empirical knowledge and some interpretation*/ /* also... the logic should probably be */ /* rewritten */ /* We will remain in READ state with the thread */ /* as long as we haven't met a read ending condition */ while(1) { /* READ state */ dev->commadpt->curpending=COMMADPT_PEND_READ; /* Tell worker thread */ commadpt_wakeup(dev->commadpt,0); /* Wait for some data */ commadpt_wait(dev); /* If we are not connected, the read fails */ if(!dev->commadpt->connect) { *unitstat=CSW_DE|CSW_CE|CSW_UC; dev->sense[0]=SENSE_IR; break; } /* If the I/O was halted - indicate Unit Check */ if(dev->commadpt->haltpending) { *unitstat=CSW_CE|CSW_DE|CSW_UX; dev->commadpt->haltpending=0; break; } if (IS_ASYNC_LNCTL(dev->commadpt) && dev->commadpt->telnet_int) { dev->commadpt->telnet_int = 0; *residual=count; *unitstat=CSW_CE|CSW_DE|CSW_UC; dev->sense[0]=SENSE_IR; break; } /* If no data is present - 3 seconds have passed without */ /* receiving data (or a SYNC) */ /* (28 seconds for LNCTL_ASYNC) */ /* INHIBIT command does not time out */ if(!dev->commadpt->inbfr.havedata && code != 0x0a) { *unitstat=CSW_DE|CSW_CE|CSW_UC; dev->sense[0]=0x01; dev->sense[1]=0xe3; break; } if (IS_BSC_LNCTL(dev->commadpt)) { /* Start processing data flow here */ /* Pop bytes until we run out of data or */ /* until the processing indicates the read */ /* should now terminate */ while( dev->commadpt->inbfr.havedata && !dev->commadpt->readcomp) { /* fetch 1 byte from the input ring */ b=commadpt_ring_pop(&dev->commadpt->inbfr); if(!dev->commadpt->gotdle) { if(b==0x10) { dev->commadpt->gotdle=1; continue; } } if(dev->commadpt->in_textmode) { if(dev->commadpt->in_xparmode) { /* TRANSPARENT MODE READ */ if(dev->commadpt->gotdle) { switch(b) { case 0x10: commadpt_ring_push(&dev->commadpt->rdwrk,b); break; case 0x32: break; case 0x1F: /* ITB - Exit xparent, set EIB - do NOT exit read yet */ dev->commadpt->in_xparmode=0; commadpt_ring_push(&dev->commadpt->rdwrk,0x10); commadpt_ring_push(&dev->commadpt->rdwrk,b); if(dev->commadpt->eibmode) { commadpt_ring_push(&dev->commadpt->rdwrk,0); } break; case 0x26: /* ETB - Same as ITB but DO exit read now */ dev->commadpt->in_xparmode=0; commadpt_ring_push(&dev->commadpt->rdwrk,0x10); commadpt_ring_push(&dev->commadpt->rdwrk,b); if(dev->commadpt->eibmode) { commadpt_ring_push(&dev->commadpt->rdwrk,0); } dev->commadpt->readcomp=1; break; case 0x03: /* ETX - Same as ETB */ dev->commadpt->in_xparmode=0; commadpt_ring_push(&dev->commadpt->rdwrk,0x10); commadpt_ring_push(&dev->commadpt->rdwrk,b); if(dev->commadpt->eibmode) { commadpt_ring_push(&dev->commadpt->rdwrk,0); } dev->commadpt->readcomp=1; break; case 0x2D: /* ENQ */ dev->commadpt->in_xparmode=0; dev->commadpt->in_textmode=0; commadpt_ring_push(&dev->commadpt->rdwrk,0x10); commadpt_ring_push(&dev->commadpt->rdwrk,b); dev->commadpt->readcomp=1; break; default: commadpt_ring_push(&dev->commadpt->rdwrk,0x10); commadpt_ring_push(&dev->commadpt->rdwrk,b); break; } } else { commadpt_ring_push(&dev->commadpt->rdwrk,b); } } else { if(b!=0x32) { /* TEXT MODE READ */ if(dev->commadpt->gotdle) { switch(b) { case 0x02: /* STX */ dev->commadpt->in_xparmode=1; break; case 0x2D: /* ENQ */ dev->commadpt->readcomp=1; break; default: if((b&0xf0)==0x60 || (b&0xf0)==0x70) { dev->commadpt->readcomp=1; } break; } commadpt_ring_push(&dev->commadpt->rdwrk,0x10); commadpt_ring_push(&dev->commadpt->rdwrk,b); } else { switch(b) { case 0x2D: /* ENQ */ dev->commadpt->readcomp=1; dev->commadpt->in_textmode=0; commadpt_ring_push(&dev->commadpt->rdwrk,b); break; case 0x3D: /* NAK */ dev->commadpt->readcomp=1; commadpt_ring_push(&dev->commadpt->rdwrk,b); break; case 0x26: /* ETB */ case 0x03: /* ETX */ dev->commadpt->readcomp=1; dev->commadpt->in_textmode=0; commadpt_ring_push(&dev->commadpt->rdwrk,b); if(dev->commadpt->eibmode) { commadpt_ring_push(&dev->commadpt->rdwrk,0); } break; case 0x1F: /* ITB */ commadpt_ring_push(&dev->commadpt->rdwrk,b); if(dev->commadpt->eibmode) { commadpt_ring_push(&dev->commadpt->rdwrk,0); } break; default: commadpt_ring_push(&dev->commadpt->rdwrk,b); break; } } } } } else { if(b!=0x32) { if(dev->commadpt->gotdle) { if((b & 0xf0) == 0x60 || (b&0xf0)==0x70) { commadpt_ring_push(&dev->commadpt->rdwrk,0x10); commadpt_ring_push(&dev->commadpt->rdwrk,b); dev->commadpt->readcomp=1; } else { if(b==0x02) { commadpt_ring_push(&dev->commadpt->rdwrk,0x10); commadpt_ring_push(&dev->commadpt->rdwrk,b); dev->commadpt->in_textmode=1; dev->commadpt->in_xparmode=1; } } } else { switch(b) { case 0x37: /* EOT */ setux=1; dev->commadpt->readcomp=1; break; case 0x01: case 0x02: dev->commadpt->in_textmode=1; break; case 0x2D: /* ENQ */ dev->commadpt->readcomp=1; break; case 0x3D: /* NAK */ dev->commadpt->readcomp=1; break; default: break; } commadpt_ring_push(&dev->commadpt->rdwrk,b); } } } dev->commadpt->gotdle=0; } /* END WHILE - READ FROM DATA BUFFER */ } /* end of if (bsc) */ /* If readcomp is set, then we may exit the read loop */ if(dev->commadpt->readcomp) { if (IS_ASYNC_LNCTL(dev->commadpt)) { while (dev->commadpt->inbfr.havedata) { commadpt_ring_push(&dev->commadpt->rdwrk, commadpt_ring_pop(&dev->commadpt->inbfr)); } } /* end of if(async) */ if (( IS_BSC_LNCTL(dev->commadpt) && dev->commadpt->rdwrk.havedata) || (IS_ASYNC_LNCTL(dev->commadpt) && dev->commadpt->rdwrk.havedata && dev->commadpt->eol_flag)) { num=commadpt_ring_popbfr(&dev->commadpt->rdwrk,iobuf,count); if(dev->commadpt->rdwrk.havedata) { *more=1; } *residual=count-num; *unitstat=CSW_CE|CSW_DE|(setux?CSW_UX:0); logdump("Read",dev,iobuf,num); if(IS_ASYNC_LNCTL(dev->commadpt) && dev->commadpt->term == COMMADPT_TERM_2741) dev->commadpt->eol_flag = 0; break; } } } /* END WHILE - READ FROM THREAD */ break; /*---------------------------------------------------------------*/ /* WRITE */ /*---------------------------------------------------------------*/ case 0x01: case 0x0d: /* also CCW=BREAK */ logdump("Writ",dev,iobuf,count); *residual=count; /* Check if we have an opened path */ if(!dev->commadpt->connect) { *unitstat=CSW_CE|CSW_DE|CSW_UC; dev->sense[0]=SENSE_IR; break; } /* Check if the line has been enabled */ if(!dev->commadpt->enabled) { *unitstat=CSW_CE|CSW_DE|CSW_UC; dev->sense[0]=SENSE_CR; break; } /* read 1 byte to check for pending input */ i=read_socket(dev->commadpt->sfd,&b,1); if (IS_ASYNC_LNCTL(dev->commadpt)) { if(i>0) { logdump("RCV0",dev,&b,1); commadpt_read_tty(dev->commadpt,&b,1); } } else { if(i>0) { /* Push it in the communication input buffer ring */ commadpt_ring_push(&dev->commadpt->inbfr,b); } /* Set UX on write if line has pending inbound data */ if(dev->commadpt->inbfr.havedata) { dev->commadpt->datalostcond=1; *unitstat=CSW_CE|CSW_DE|CSW_UX; break; } } /* end of else (async) */ /* * Fill in the Write Buffer */ /* To start : not transparent mode, no DLE received yet */ turnxpar=0; gotdle=0; if(IS_ASYNC_LNCTL(dev->commadpt) && dev->commadpt->telnet_int /* ugly hack for TSO ATTN to fix IEA000I 0C3,IOE,01,0E40,40008900002C,,,TCAM */ && !(iobuf[0] == 0xdf && iobuf[1] == 0xdf && iobuf[2] == 0xdf && count == 3)) { dev->commadpt->telnet_int = 0; *residual=count; *unitstat=CSW_CE|CSW_DE|CSW_UC; dev->sense[0]=SENSE_IR; break; } /* Scan the I/O buffer */ for(i=0;icommadpt)) { if (dev->commadpt->byte_skip_table[b]) continue; if (dev->commadpt->term == COMMADPT_TERM_TTY) { b = byte_reverse_table[b] & 0x7f; } else { /* 2741 */ if (dev->commadpt->code_table_toebcdic) { // only if code != none b = dev->commadpt->code_table_toebcdic[b]; // first translate to EBCDIC b = guest_to_host(b) & 0x7f; // then EBCDIC to ASCII } } } else { /* line is BSC */ /* If we are in transparent mode, we must double the DLEs */ if(turnxpar) { /* Check for a DLE */ if(b==0x10) { /* put another one in the output buffer */ commadpt_ring_push(&dev->commadpt->outbfr,0x10); } } else /* non transparent mode */ { if(b==0x10) { gotdle=1; /* Indicate we have a DLE for next pass */ } else { /* If there was a DLE on previous pass */ if(gotdle) { /* check for DLE/ETX */ if(b==0x02) { /* Indicate transparent mode on */ turnxpar=1; } } } } } /* end of else (async) */ /* Put the current byte on the output ring */ commadpt_ring_push(&dev->commadpt->outbfr,b); } if (IS_BSC_LNCTL(dev->commadpt)) { /* If we had a DLE/STX, the line is now in Transparent Write Wait state */ /* meaning that no CCW codes except Write, No-Op, Sense are allowed */ /* (that's what the manual says.. I doubt DISABLE is disallowed) */ /* Anyway.. The program will have an opportunity to turn XPARENT mode */ /* off on the next CCW. */ /* CAVEAT : The manual doesn't say if the line remains in transparent */ /* Write Wait state if the next CCW doesn't start with DLE/ETX */ /* or DLE/ITB */ if(turnxpar) { dev->commadpt->xparwwait=1; } else { dev->commadpt->xparwwait=0; } } /* end of if(bsc line) */ /* Indicate to the worker thread the current operation is OUTPUT */ dev->commadpt->curpending=COMMADPT_PEND_WRITE; /* All bytes written out - residual = 0 */ *residual=0; /* Wake-up the worker thread */ commadpt_wakeup(dev->commadpt,0); /* Wait for operation completion */ commadpt_wait(dev); /* Check if the line is still connected */ if(!dev->commadpt->connect) { *unitstat=CSW_CE|CSW_DE|CSW_UC; dev->sense[0]=SENSE_IR; break; } /* Check if the I/O was interrupted */ if(dev->commadpt->haltpending) { *unitstat=CSW_CE|CSW_DE|CSW_UX; dev->commadpt->haltpending = 0; break; } *unitstat=CSW_CE|CSW_DE; break; /*---------------------------------------------------------------*/ /* PREPARE */ /* NOTE : DO NOT SET RESIDUAL to 0 : Otherwise, channel.c */ /* will reflect a channel prot check - residual */ /* should indicate NO data was transfered for this */ /* pseudo-read operation */ /*---------------------------------------------------------------*/ case 0x06: *residual=count; /* PREPARE not allowed unless line is enabled */ if(!dev->commadpt->enabled) { *unitstat=CSW_CE|CSW_DE|CSW_UC; dev->sense[0]=SENSE_CR; dev->sense[1]=0x06; break; } if (IS_ASYNC_LNCTL(dev->commadpt)) { *unitstat=CSW_CE|CSW_DE; if(dev->commadpt->haltpending) { dev->commadpt->haltpending=0; *unitstat |= CSW_UX; } break; } /* end of if(async) */ /* Transparent Write Wait State test */ if(dev->commadpt->xparwwait) { *unitstat=CSW_CE|CSW_DE|CSW_UC; dev->sense[0]=SENSE_CR; return; } /* If data is present, prepare ends immediatly */ if(dev->commadpt->inbfr.havedata) { *unitstat=CSW_CE|CSW_DE; break; } /* Indicate to the worker thread to notify us when data arrives */ dev->commadpt->curpending=COMMADPT_PEND_PREPARE; /* Wakeup worker thread */ commadpt_wakeup(dev->commadpt,0); /* Wait for completion */ commadpt_wait(dev); /* If I/O was halted (this one happens often) */ if(dev->commadpt->haltpending) { *unitstat=CSW_CE|CSW_DE|CSW_UX; dev->commadpt->haltpending=0; break; } /* Check if the line is still connected */ if(!dev->commadpt->connect) { *unitstat=CSW_CE|CSW_DE|CSW_UC; dev->sense[0]=SENSE_IR; break; } /* Normal Prepare exit condition - data is present in the input buffer */ *unitstat=CSW_CE|CSW_DE; break; default: /*---------------------------------------------------------------*/ /* INVALID OPERATION */ /*---------------------------------------------------------------*/ /* Set command reject sense byte, and unit check status */ *unitstat=CSW_CE+CSW_DE+CSW_UC; dev->sense[0]=SENSE_CR; break; } release_lock(&dev->commadpt->lock); } /*---------------------------------------------------------------*/ /* DEVICE FUNCTION POINTERS */ /*---------------------------------------------------------------*/ #if defined(OPTION_DYNAMIC_LOAD) static #endif DEVHND comadpt_device_hndinfo = { &commadpt_init_handler, /* Device Initialisation */ &commadpt_execute_ccw, /* Device CCW execute */ &commadpt_close_device, /* Device Close */ &commadpt_query_device, /* Device Query */ NULL, /* Device Start channel pgm */ NULL, /* Device End channel pgm */ NULL, /* Device Resume channel pgm */ NULL, /* Device Suspend channel pgm */ NULL, /* Device Read */ NULL, /* Device Write */ NULL, /* Device Query used */ NULL, /* Device Reserve */ NULL, /* Device Release */ NULL, /* Device Attention */ commadpt_immed_command, /* Immediate CCW Codes */ NULL, /* Signal Adapter Input */ NULL, /* Signal Adapter Output */ NULL, /* Hercules suspend */ NULL /* Hercules resume */ }; /* Libtool static name colision resolution */ /* note : lt_dlopen will look for symbol & modulename_LTX_symbol */ #if !defined(HDL_BUILD_SHARED) && defined(HDL_USE_LIBTOOL) #define hdl_ddev hdt2703_LTX_hdl_ddev #define hdl_depc hdt2703_LTX_hdl_depc #define hdl_reso hdt2703_LTX_hdl_reso #define hdl_init hdt2703_LTX_hdl_init #define hdl_fini hdt2703_LTX_hdl_fini #endif #if defined(OPTION_DYNAMIC_LOAD) HDL_DEPENDENCY_SECTION; { HDL_DEPENDENCY(HERCULES); HDL_DEPENDENCY(DEVBLK); HDL_DEPENDENCY(SYSBLK); } END_DEPENDENCY_SECTION #if defined(WIN32) && !defined(HDL_USE_LIBTOOL) && !defined(_MSVC_) #undef sysblk HDL_RESOLVER_SECTION; { HDL_RESOLVE_PTRVAR( psysblk, sysblk ); } END_RESOLVER_SECTION #endif HDL_DEVICE_SECTION; { HDL_DEVICE(2703, comadpt_device_hndinfo ); } END_DEVICE_SECTION #endif hercules-3.07/commadpt.h000644 000765 000765 00000015642 11321734033 016725 0ustar00jmaynardjmaynard000000 000000 /* COMMADPT.H (c)Copyright Ivan Warren, 2003-2009 */ /* Structure definitions for 2703 line driver */ // $Id: commadpt.h 5584 2009-12-30 22:16:28Z rbowler $ #ifndef __COMMADPT_H__ #define __COMMADPT_H__ #include "hercules.h" typedef struct _COMMADPT_RING { BYTE *bfr; size_t sz; size_t hi; size_t lo; u_int havedata:1; u_int overflow:1; } COMMADPT_RING; struct COMMADPT { DEVBLK *dev; /* the devblk to which this CA is attched */ BYTE lnctl; /* Line control used */ BYTE term; /* Terminal type */ BYTE* code_table_toebcdic; /* correspondence or EBCD code tables */ BYTE* code_table_fromebcdic; /* correspondence or EBCD code tables */ int rto; /* Read Time-Out */ int pto; /* Poll Time-Out */ int eto; /* Enable Time-Out */ TID cthread; /* Thread used to control the socket */ BYTE curpending; /* Current pending operation */ U16 lport; /* Local listening port */ in_addr_t lhost; /* Local listening address */ U16 rport; /* Remote TCP Port */ in_addr_t rhost; /* Remote connection IP address */ int sfd; /* Communication socket FD */ int lfd; /* Listen socket for DIAL=IN, INOUT & NO */ COND ipc; /* I/O <-> thread IPC condition EVB */ COND ipc_halt; /* I/O <-> thread IPC HALT special EVB */ LOCK lock; /* COMMADPT lock */ int pipe[2]; /* pipe used for I/O to thread signaling */ COMMADPT_RING inbfr; /* Input buffer ring */ COMMADPT_RING outbfr; /* Output buffer ring */ COMMADPT_RING pollbfr; /* Ring used for POLL data */ COMMADPT_RING rdwrk; /* Inbound data flow work ring */ U16 devnum; /* devnum copy from DEVBLK */ BYTE dialdata[32]; /* Dial data information */ U16 dialcount; /* data count for dial */ BYTE pollix; /* Next POLL Index */ U16 pollused; /* Count of Poll data used during Poll */ u_int enabled:1; /* An ENABLE CCW has been sucesfully issued */ u_int connect:1; /* A connection exists with the remote peer */ u_int eibmode:1; /* EIB Setmode issued */ u_int dialin:1; /* This is a SWITCHED DIALIN line */ u_int dialout:1; /* This is a SWITCHED DIALOUT line */ u_int have_cthread:1; /* the comm thread is running */ u_int dolisten:1; /* Start a listen */ u_int listening:1; /* Listening */ u_int haltpending:1; /* A request has been issued to halt current*/ /* CCW */ u_int xparwwait:1; /* Transparent Write Wait state : a Write */ /* was previously issued that turned the */ /* line into transparent mode. Anything */ /* else than another write, Sense or NO-OP */ /* is rejected with SENSE_CR */ /* This condition is reset upon receipt of */ /* DLE/ETX or DLE/ETB on a subsequent write */ u_int input_overrun:1; /* The input ring buffer has overwritten */ /* itself */ u_int in_textmode:1; /* Input buffer processing : text mode */ u_int in_xparmode:1; /* Input buffer processing : transparent */ u_int gotdle:1; /* DLE Received in inbound flow */ u_int pollsm:1; /* Issue Status Modifier on POLL Exit */ u_int badpoll:1; /* Bad poll data (>7 Bytes before ENQ) */ u_int callissued:1; /* The connect out for the DIAL/ENABLE */ /* has already been issued */ u_int readcomp:1; /* Data in the read buffer completes a read */ u_int datalostcond:1; /* Data Lost Condition Raised */ u_int telnet_opt:1; /* expecting telnet option char */ u_int telnet_iac:1; /* expecting telnet command char */ u_int telnet_int:1; /* telnet interrupt received */ u_int eol_flag:1; /* carriage return received flag */ u_int uctrans:1; /* Uppercase translate flag */ BYTE telnet_cmd; /* telnet command received */ BYTE byte_skip_table[256]; /* async: characters to suppress in output */ }; enum commadpt_lnctl { COMMADPT_LNCTL_BSC=1, /* BSC Line Control */ COMMADPT_LNCTL_ASYNC /* ASYNC Line Control */ }; enum commadpt_term { COMMADPT_TERM_TTY, /* TTY (TELE2) */ COMMADPT_TERM_2741, /* 2741 (IBM1) */ }; #define IS_BSC_LNCTL(ca) ((ca->lnctl == COMMADPT_LNCTL_BSC)) #define IS_ASYNC_LNCTL(ca) ((ca->lnctl == COMMADPT_LNCTL_ASYNC)) enum commadpt_pendccw { COMMADPT_PEND_IDLE=0, /* NO CCW currently executing */ COMMADPT_PEND_READ, /* A READ CCW is running */ COMMADPT_PEND_WRITE, /* A WRITE CCW is running */ COMMADPT_PEND_ENABLE, /* A ENABLE CCW is running */ COMMADPT_PEND_DIAL, /* A DIAL CCW is running */ COMMADPT_PEND_DISABLE, /* A DISABLE CCW is running */ COMMADPT_PEND_PREPARE, /* A PREPARE CCW is running */ COMMADPT_PEND_POLL, /* A POLL CCW Is Running */ COMMADPT_PEND_TINIT, /* */ COMMADPT_PEND_CLOSED, /* */ COMMADPT_PEND_SHUTDOWN /* */ }; #define COMMADPT_PEND_TEXT static char *commadpt_pendccw_text[]={\ "IDLE",\ "READ",\ "WRITE",\ "ENABLE",\ "DIAL",\ "DISABLE",\ "PREPARE",\ "POLL",\ "TINIT",\ "TCLOSED",\ "SHUTDOWN"} #endif hercules-3.07/con1052c.c000644 000765 000765 00000036135 11143760542 016354 0ustar00jmaynardjmaynard000000 000000 /* CON1052.C (c)Copyright Jan Jaeger, 2004-2009 */ /* Emulated 1052 on hercules console */ // $Id: con1052c.c 5125 2009-01-23 12:01:44Z bernard $ // // $Log$ // Revision 1.14 2007/11/21 22:54:14 fish // Use new BEGIN_DEVICE_CLASS_QUERY macro // // Revision 1.13 2007/06/23 16:13:54 jmaynard // Fixing two messages out of internationalization by removing redundant // carriage returns. // // Revision 1.12 2007/06/23 00:04:04 ivan // Update copyright notices to include current year (2007) // // Revision 1.11 2006/12/23 00:51:08 ivan // Fix logmsg() call in con1052c.c from logmsg(bfr) to logmsg("%s",bfr) to prevent // Write CCW data with embedded '%' characters to be interpreted as printf formating orders // // Revision 1.10 2006/12/08 09:43:18 jj // Add CVS message log // #include "hstdinc.h" #include "hercules.h" #include "devtype.h" #include "opcode.h" #include "sr.h" #if defined(OPTION_DYNAMIC_LOAD) && defined(WIN32) && !defined(HDL_USE_LIBTOOL) && !defined(_MSVC_) SYSBLK *psysblk; #define sysblk (*psysblk) void* (*panel_command) (void*); #endif #if defined(OPTION_DYNAMIC_LOAD) static void* con1052_panel_command (char *cmd); #endif #define BUFLEN_1052 150 /* 1052 Send/Receive buffer */ /*-------------------------------------------------------------------*/ /* Ivan Warren 20040227 */ /* This table is used by channel.c to determine if a CCW code is an */ /* immediate command or not */ /* The tape is addressed in the DEVHND structure as 'DEVIMM immed' */ /* 0 : Command is NOT an immediate command */ /* 1 : Command is an immediate command */ /* Note : An immediate command is defined as a command which returns */ /* CE (channel end) during initialisation (that is, no data is */ /* actually transfered. In this case, IL is not indicated for a CCW */ /* Format 0 or for a CCW Format 1 when IL Suppression Mode is in */ /* effect */ /*-------------------------------------------------------------------*/ static BYTE con1052_immed[256]= /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ { 0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0, /* 00 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 10 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 20 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 30 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 40 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 50 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 60 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 70 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 80 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 90 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* A0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* B0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* C0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* D0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* E0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; /* F0 */ /*-------------------------------------------------------------------*/ /* INITIALIZE THE 1052/3215 DEVICE HANDLER */ /*-------------------------------------------------------------------*/ static int con1052_init_handler ( DEVBLK *dev, int argc, char *argv[] ) { int ac=0; /* Integrated console is always connected */ dev->connected = 1; /* Set number of sense bytes */ dev->numsense = 1; /* Initialize device dependent fields */ dev->keybdrem = 0; /* Set length of print buffer */ dev->bufsize = BUFLEN_1052; /* Assume we want to prompt */ dev->prompt1052 = 1; /* Default command character is "/" */ strcpy(dev->filename,"/"); /* Is there an argument? */ if (argc > 0) { /* Look at the argument and set noprompt flag if specified. */ if (strcasecmp(argv[ac], "noprompt") == 0) { dev->prompt1052 = 0; ac++; argc--; } else strlcpy(dev->filename,argv[ac],sizeof(dev->filename)); } if(!sscanf(dev->typname,"%hx",&(dev->devtype))) dev->devtype = 0x1052; /* Initialize the device identifier bytes */ dev->devid[0] = 0xFF; dev->devid[1] = dev->devtype >> 8; dev->devid[2] = dev->devtype & 0xFF; dev->devid[3] = 0x00; dev->devid[4] = dev->devtype >> 8; dev->devid[5] = dev->devtype & 0xFF; dev->devid[6] = 0x00; dev->numdevid = 7; return 0; } /* end function con1052_init_handler */ /*-------------------------------------------------------------------*/ /* QUERY THE 1052/3215 DEVICE DEFINITION */ /*-------------------------------------------------------------------*/ static void con1052_query_device (DEVBLK *dev, char **class, int buflen, char *buffer) { BEGIN_DEVICE_CLASS_QUERY( "CON", dev, class, buflen, buffer ); snprintf(buffer, buflen, "*syscons cmdpref(%s)%s", dev->filename, !dev->prompt1052 ? " noprompt" : ""); } /* end function con1052_query_device */ /*-------------------------------------------------------------------*/ /* CLOSE THE 1052/3215 DEVICE HANDLER */ /*-------------------------------------------------------------------*/ static int con1052_close_device ( DEVBLK *dev ) { UNREFERENCED(dev); return 0; } /* end function con1052_close_device */ /*-------------------------------------------------------------------*/ /* EXECUTE A 1052/3215 CHANNEL COMMAND WORD */ /*-------------------------------------------------------------------*/ static void con1052_execute_ccw ( DEVBLK *dev, BYTE code, BYTE flags, BYTE chained, U16 count, BYTE prevcode, int ccwseq, BYTE *iobuf, BYTE *more, BYTE *unitstat, U16 *residual ) { int len; /* Length of data */ int num; /* Number of bytes to move */ BYTE c; /* Print character */ UNREFERENCED(chained); UNREFERENCED(prevcode); UNREFERENCED(ccwseq); /* Unit check with intervention required if no client connected */ if (dev->connected == 0 && !IS_CCW_SENSE(code)) { dev->sense[0] = SENSE_IR; *unitstat = CSW_UC; return; } /* Process depending on CCW opcode */ switch (code) { case 0x01: /*---------------------------------------------------------------*/ /* WRITE NO CARRIER RETURN */ /*---------------------------------------------------------------*/ case 0x09: /*---------------------------------------------------------------*/ /* WRITE AUTO CARRIER RETURN */ /*---------------------------------------------------------------*/ /* Calculate number of bytes to write and set residual count */ num = (count < BUFLEN_1052) ? count : BUFLEN_1052; *residual = count - num; /* Translate data in channel buffer to ASCII */ for (len = 0; len < num; len++) { c = guest_to_host(iobuf[len]); if (!isprint(c) && c != 0x0a && c != 0x0d) c = SPACE; iobuf[len] = c; } /* end for(len) */ /* Perform end of record processing if not data-chaining, and append carriage return and newline if required */ if ((flags & CCW_FLAGS_CD) == 0 // && code == 0x09 && len < BUFLEN_1052) iobuf[len++] = '\n'; iobuf[len] = '\0'; /* Send the data to the console */ logmsg("%s",(char *)iobuf); /* Return normal status */ *unitstat = CSW_CE | CSW_DE; break; case 0x03: /*---------------------------------------------------------------*/ /* CONTROL NO-OPERATION */ /*---------------------------------------------------------------*/ *unitstat = CSW_CE | CSW_DE; break; case 0x0A: /*---------------------------------------------------------------*/ /* READ INQUIRY */ /*---------------------------------------------------------------*/ /* Solicit console input if no data in the device buffer */ if (!dev->keybdrem) { /* Display prompting message on console if allowed */ if (dev->prompt1052) logmsg (_("HHC1C001A Enter input for console device %4.4X\n"), dev->devnum); obtain_lock(&dev->lock); dev->iowaiters++; wait_condition(&dev->iocond, &dev->lock); dev->iowaiters--; release_lock(&dev->lock); } /* Calculate number of bytes to move and residual byte count */ len = dev->keybdrem; num = (count < len) ? count : len; *residual = count - num; if (count < len) *more = 1; /* Copy data from device buffer to channel buffer */ memcpy (iobuf, dev->buf, num); /* If data chaining is specified, save remaining data */ if ((flags & CCW_FLAGS_CD) && len > count) { memmove (dev->buf, dev->buf + count, len - count); dev->keybdrem = len - count; } else { dev->keybdrem = 0; } /* Return normal status */ *unitstat = CSW_CE | CSW_DE; break; case 0x0B: /*---------------------------------------------------------------*/ /* AUDIBLE ALARM */ /*---------------------------------------------------------------*/ logmsg("\a"); /* *residual = 0; */ *unitstat = CSW_CE | CSW_DE; break; case 0x04: /*---------------------------------------------------------------*/ /* SENSE */ /*---------------------------------------------------------------*/ /* Calculate residual byte count */ num = (count < dev->numsense) ? count : dev->numsense; *residual = count - num; if (count < dev->numsense) *more = 1; /* Copy device sense bytes to channel I/O buffer */ memcpy (iobuf, dev->sense, num); /* Clear the device sense bytes */ memset (dev->sense, 0, sizeof(dev->sense)); /* Return unit status */ *unitstat = CSW_CE | CSW_DE; break; case 0xE4: /*---------------------------------------------------------------*/ /* SENSE ID */ /*---------------------------------------------------------------*/ /* Calculate residual byte count */ num = (count < dev->numdevid) ? count : dev->numdevid; *residual = count - num; if (count < dev->numdevid) *more = 1; /* Copy device identifier bytes to channel I/O buffer */ memcpy (iobuf, dev->devid, num); /* Return unit status */ *unitstat = CSW_CE | CSW_DE; break; default: /*---------------------------------------------------------------*/ /* INVALID OPERATION */ /*---------------------------------------------------------------*/ /* Set command reject sense byte, and unit check status */ dev->sense[0] = SENSE_CR; *unitstat = CSW_CE | CSW_DE | CSW_UC; } /* end switch(code) */ } /* end function con1052_execute_ccw */ #if defined(OPTION_DYNAMIC_LOAD) static #endif DEVHND con1052_device_hndinfo = { &con1052_init_handler, /* Device Initialisation */ &con1052_execute_ccw, /* Device CCW execute */ &con1052_close_device, /* Device Close */ &con1052_query_device, /* Device Query */ NULL, /* Device Start channel pgm */ NULL, /* Device End channel pgm */ NULL, /* Device Resume channel pgm */ NULL, /* Device Suspend channel pgm */ NULL, /* Device Read */ NULL, /* Device Write */ NULL, /* Device Query used */ NULL, /* Device Reserve */ NULL, /* Device Release */ NULL, /* Device Attention */ con1052_immed, /* Immediate CCW Codes */ NULL, /* Signal Adapter Input */ NULL, /* Signal Adapter Output */ NULL, /* Hercules suspend */ NULL /* Hercules resume */ }; #if defined(OPTION_DYNAMIC_LOAD) static void* con1052_panel_command (char *cmd) { DEVBLK *dev; char *input; int i; void* (*next_panel_command_handler)(char *cmd); for(dev = sysblk.firstdev; dev; dev = dev->nextdev) { if(dev->allocated && dev->hnd == &con1052_device_hndinfo && !strncasecmp(cmd,dev->filename,strlen(dev->filename)) ) { input = cmd + strlen(dev->filename); logmsg("%s(%4.4X) %s\n",dev->filename,dev->devnum, cmd+strlen(dev->filename) ); for(i = 0; i < dev->bufsize && input[i] != '\0'; i++) dev->buf[i] = isprint(input[i]) ? host_to_guest(input[i]) : SPACE; dev->keybdrem = dev->buflen = i; obtain_lock(&dev->lock); if(dev->iowaiters) { signal_condition(&dev->iocond); release_lock(&dev->lock); } else { release_lock(&dev->lock); device_attention (dev, CSW_ATTN); } return NULL; } } next_panel_command_handler = HDL_FINDNXT(con1052_panel_command); if (!next_panel_command_handler) return NULL; return next_panel_command_handler(cmd); } #endif /* Libtool static name colision resolution */ /* note : lt_dlopen will look for symbol & modulename_LTX_symbol */ #if !defined(HDL_BUILD_SHARED) && defined(HDL_USE_LIBTOOL) #define hdl_ddev hdt1052c_LTX_hdl_ddev #define hdl_depc hdt1052c_LTX_hdl_depc #define hdl_reso hdt1052c_LTX_hdl_reso #define hdl_init hdt1052c_LTX_hdl_init #define hdl_fini hdt1052c_LTX_hdl_fini #endif #if defined(OPTION_DYNAMIC_LOAD) HDL_DEPENDENCY_SECTION; { HDL_DEPENDENCY(HERCULES); HDL_DEPENDENCY(DEVBLK); HDL_DEPENDENCY(SYSBLK); } END_DEPENDENCY_SECTION #if defined(WIN32) && !defined(HDL_USE_LIBTOOL) && !defined(_MSVC_) #undef sysblk HDL_RESOLVER_SECTION; { HDL_RESOLVE_PTRVAR(psysblk, sysblk); HDL_RESOLVE(panel_command); } END_RESOLVER_SECTION #endif HDL_DEVICE_SECTION; { HDL_DEVICE(1052-C, con1052_device_hndinfo); HDL_DEVICE(3215-C, con1052_device_hndinfo); } END_DEVICE_SECTION HDL_REGISTER_SECTION; { HDL_REGISTER (panel_command, con1052_panel_command); } END_REGISTER_SECTION #endif hercules-3.07/config.c000644 000765 000765 00000125572 11344707123 016372 0ustar00jmaynardjmaynard000000 000000 /* CONFIG.C (c) Copyright Jan Jaeger, 2000-2009 */ /* Device configuration functions */ // $Id: config.c 5654 2010-03-07 03:15:17Z fish $ /*-------------------------------------------------------------------*/ /* The original configuration builder is now called bldcfg.c */ /*-------------------------------------------------------------------*/ // $Log$ // Revision 1.204 2009/01/15 17:36:43 jj // Change http server startup // // Revision 1.203 2008/11/04 05:56:31 fish // Put ensure consistent create_thread ATTR usage change back in // // Revision 1.202 2008/11/03 15:31:57 rbowler // Back out consistent create_thread ATTR modification // // Revision 1.201 2008/10/18 09:32:20 fish // Ensure consistent create_thread ATTR usage // // Revision 1.200 2008/07/08 05:35:49 fish // AUTOMOUNT redesign: support +allowed/-disallowed dirs // and create associated 'automount' panel command - Fish // // Revision 1.199 2007/06/23 00:04:04 ivan // Update copyright notices to include current year (2007) // // Revision 1.198 2007/06/22 02:22:50 gsmith // revert config_cpu.pat due to problems in testing // // Revision 1.197 2007/06/20 03:52:19 gsmith // configure_cpu now returns when the CPU is fully configured // // Revision 1.196 2007/06/09 02:10:04 kleonard // Skip making CRW pending in S/370 mode // // Revision 1.195 2007/02/03 18:58:06 gsmith // Fix MVT tape CMDREJ error // // Revision 1.194 2007/01/11 19:54:33 fish // Addt'l keep-alive mods: create associated supporting config-file stmt and panel command where individual customer-preferred values can be specified and/or dynamically modified. // // Revision 1.193 2007/01/02 18:53:33 fish // (fix comments only) // // Revision 1.192 2007/01/02 18:46:16 fish // Fix bug in deconfigure_cpu function & tweak power-off diagnose instructions so that they actually work properly now // // Revision 1.191 2006/12/08 09:43:18 jj // Add CVS message log // #include "hstdinc.h" #define _CONFIG_C_ #define _HENGINE_DLL_ #include "hercules.h" #include "opcode.h" #if !defined(_GEN_ARCH) #if defined(_ARCHMODE3) #define _GEN_ARCH _ARCHMODE3 #include "config.c" #undef _GEN_ARCH #endif #if defined(_ARCHMODE2) #define _GEN_ARCH _ARCHMODE2 #include "config.c" #undef _GEN_ARCH #endif #if defined(OPTION_FISHIO) #include "w32chan.h" #endif // defined(OPTION_FISHIO) /*-------------------------------------------------------------------*/ /* Function to terminate all CPUs and devices */ /*-------------------------------------------------------------------*/ void release_config() { DEVBLK *dev; int cpu; /* Deconfigure all CPU's */ OBTAIN_INTLOCK(NULL); for (cpu = 0; cpu < MAX_CPU_ENGINES; cpu++) if(IS_CPU_ONLINE(cpu)) deconfigure_cpu(cpu); RELEASE_INTLOCK(NULL); #if defined(OPTION_SHARED_DEVICES) /* Terminate the shared device listener thread */ if (sysblk.shrdtid) signal_thread (sysblk.shrdtid, SIGUSR2); #endif /* Detach all devices */ for (dev = sysblk.firstdev; dev != NULL; dev = dev->nextdev) if (dev->allocated) detach_subchan(SSID_TO_LCSS(dev->ssid), dev->subchan); #if !defined(OPTION_FISHIO) /* Terminate device threads */ obtain_lock (&sysblk.ioqlock); sysblk.devtwait=0; broadcast_condition (&sysblk.ioqcond); release_lock (&sysblk.ioqlock); #endif } /* end function release_config */ /*-------------------------------------------------------------------*/ /* Function to start a new CPU thread */ /* Caller MUST own the intlock */ /*-------------------------------------------------------------------*/ int configure_cpu(int cpu) { int i; char thread_name[16]; if(IS_CPU_ONLINE(cpu)) return -1; snprintf(thread_name,sizeof(thread_name),"cpu%d thread",cpu); thread_name[sizeof(thread_name)-1]=0; if ( create_thread (&sysblk.cputid[cpu], DETACHED, cpu_thread, &cpu, thread_name) ) { logmsg(_("HHCCF040E Cannot create CPU%4.4X thread: %s\n"), cpu, strerror(errno)); return -1; } /* Find out if we are a cpu thread */ for (i = 0; i < MAX_CPU_ENGINES; i++) if (sysblk.cputid[i] == thread_id()) break; if (i < MAX_CPU_ENGINES) sysblk.regs[i]->intwait = 1; /* Wait for CPU thread to initialize */ wait_condition (&sysblk.cpucond, &sysblk.intlock); if (i < MAX_CPU_ENGINES) sysblk.regs[i]->intwait = 0; return 0; } /* end function configure_cpu */ /*-------------------------------------------------------------------*/ /* Function to remove a CPU from the configuration */ /* This routine MUST be called with the intlock held */ /*-------------------------------------------------------------------*/ int deconfigure_cpu(int cpu) { int i; /* Find out if we are a cpu thread */ for (i = 0; i < MAX_CPU_ENGINES; i++) if (sysblk.cputid[i] == thread_id()) break; /* If we're NOT trying to deconfigure ourselves */ if (cpu != i) { if (!IS_CPU_ONLINE(cpu)) return -1; /* Deconfigure CPU */ sysblk.regs[cpu]->configured = 0; sysblk.regs[cpu]->cpustate = CPUSTATE_STOPPING; ON_IC_INTERRUPT(sysblk.regs[cpu]); /* Wake up CPU as it may be waiting */ WAKEUP_CPU (sysblk.regs[cpu]); /* (if we're a cpu thread) */ if (i < MAX_CPU_ENGINES) sysblk.regs[i]->intwait = 1; /* Wait for CPU thread to terminate */ wait_condition (&sysblk.cpucond, &sysblk.intlock); /* (if we're a cpu thread) */ if (i < MAX_CPU_ENGINES) sysblk.regs[i]->intwait = 0; join_thread (sysblk.cputid[cpu], NULL); detach_thread( sysblk.cputid[cpu] ); } else { /* Else we ARE trying to deconfigure ourselves */ sysblk.regs[cpu]->configured = 0; sysblk.regs[cpu]->cpustate = CPUSTATE_STOPPING; ON_IC_INTERRUPT(sysblk.regs[cpu]); } sysblk.cputid[cpu] = 0; return 0; } /* end function deconfigure_cpu */ /* 4 next functions used for fast device lookup cache management */ #if defined(OPTION_FAST_DEVLOOKUP) static void AddDevnumFastLookup(DEVBLK *dev,U16 lcss,U16 devnum) { unsigned int Channel; if(sysblk.devnum_fl==NULL) { sysblk.devnum_fl=(DEVBLK ***)malloc(sizeof(DEVBLK **)*256*FEATURE_LCSS_MAX); memset(sysblk.devnum_fl,0,sizeof(DEVBLK **)*256*FEATURE_LCSS_MAX); } Channel=(devnum & 0xff00)>>8 | ((lcss & (FEATURE_LCSS_MAX-1))<<8); if(sysblk.devnum_fl[Channel]==NULL) { sysblk.devnum_fl[Channel]=(DEVBLK **)malloc(sizeof(DEVBLK *)*256); memset(sysblk.devnum_fl[Channel],0,sizeof(DEVBLK *)*256); } sysblk.devnum_fl[Channel][devnum & 0xff]=dev; } static void AddSubchanFastLookup(DEVBLK *dev,U16 ssid, U16 subchan) { unsigned int schw; #if 0 logmsg(D_("DEBUG : ASFL Adding %d\n"),subchan); #endif if(sysblk.subchan_fl==NULL) { sysblk.subchan_fl=(DEVBLK ***)malloc(sizeof(DEVBLK **)*256*FEATURE_LCSS_MAX); memset(sysblk.subchan_fl,0,sizeof(DEVBLK **)*256*FEATURE_LCSS_MAX); } schw=((subchan & 0xff00)>>8)|(SSID_TO_LCSS(ssid)<<8); if(sysblk.subchan_fl[schw]==NULL) { sysblk.subchan_fl[schw]=(DEVBLK **)malloc(sizeof(DEVBLK *)*256); memset(sysblk.subchan_fl[schw],0,sizeof(DEVBLK *)*256); } sysblk.subchan_fl[schw][subchan & 0xff]=dev; } static void DelDevnumFastLookup(U16 lcss,U16 devnum) { unsigned int Channel; if(sysblk.devnum_fl==NULL) { return; } Channel=(devnum & 0xff00)>>8 | ((lcss & (FEATURE_LCSS_MAX-1))<<8); if(sysblk.devnum_fl[Channel]==NULL) { return; } sysblk.devnum_fl[Channel][devnum & 0xff]=NULL; } static void DelSubchanFastLookup(U16 ssid, U16 subchan) { unsigned int schw; #if 0 logmsg(D_("DEBUG : DSFL Removing %d\n"),subchan); #endif if(sysblk.subchan_fl==NULL) { return; } schw=((subchan & 0xff00)>>8)|(SSID_TO_LCSS(ssid) << 8); if(sysblk.subchan_fl[schw]==NULL) { return; } sysblk.subchan_fl[schw][subchan & 0xff]=NULL; } #endif DEVBLK *get_devblk(U16 lcss, U16 devnum) { DEVBLK *dev; DEVBLK**dvpp; if(lcss >= FEATURE_LCSS_MAX) lcss = 0; for (dev = sysblk.firstdev; dev != NULL; dev = dev->nextdev) if (!(dev->allocated) && dev->ssid == LCSS_TO_SSID(lcss)) break; if(!dev) { if (!(dev = (DEVBLK*)malloc(sizeof(DEVBLK)))) { logmsg (_("HHCCF043E Cannot obtain device block\n"), strerror(errno)); return NULL; } memset (dev, 0, sizeof(DEVBLK)); /* Initialize the device lock and conditions */ initialize_lock (&dev->lock); initialize_condition (&dev->resumecond); initialize_condition (&dev->iocond); #if defined(OPTION_SCSI_TAPE) initialize_lock (&dev->stape_getstat_lock); initialize_condition (&dev->stape_getstat_cond); initialize_condition (&dev->stape_exit_cond ); #endif /* Search for the last device block on the chain */ for (dvpp = &(sysblk.firstdev); *dvpp != NULL; dvpp = &((*dvpp)->nextdev)); /* Add the new device block to the end of the chain */ *dvpp = dev; dev->ssid = LCSS_TO_SSID(lcss); dev->subchan = sysblk.highsubchan[lcss]++; } /* Initialize the device block */ obtain_lock (&dev->lock); dev->group = NULL; dev->member = 0; dev->cpuprio = sysblk.cpuprio; dev->devprio = sysblk.devprio; dev->hnd = NULL; dev->devnum = devnum; dev->chanset = lcss; dev->fd = -1; dev->syncio = 0; dev->ioint.dev = dev; dev->ioint.pending = 1; dev->pciioint.dev = dev; dev->pciioint.pcipending = 1; dev->attnioint.dev = dev; dev->attnioint.attnpending = 1; dev->oslinux = sysblk.pgminttr == OS_LINUX; /* Initialize storage view */ dev->mainstor = sysblk.mainstor; dev->storkeys = sysblk.storkeys; dev->mainlim = sysblk.mainsize - 1; /* Initialize the path management control word */ memset (&dev->pmcw, 0, sizeof(PMCW)); dev->pmcw.devnum[0] = dev->devnum >> 8; dev->pmcw.devnum[1] = dev->devnum & 0xFF; dev->pmcw.lpm = 0x80; dev->pmcw.pim = 0x80; dev->pmcw.pom = 0xFF; dev->pmcw.pam = 0x80; dev->pmcw.chpid[0] = dev->devnum >> 8; #if defined(OPTION_SHARED_DEVICES) dev->shrdwait = -1; #endif /*defined(OPTION_SHARED_DEVICES)*/ #ifdef _FEATURE_CHANNEL_SUBSYSTEM /* Indicate a CRW is pending for this device */ #if defined(_370) if (sysblk.arch_mode != ARCH_370) #endif /*defined(_370)*/ dev->crwpending = 1; #endif /*_FEATURE_CHANNEL_SUBSYSTEM*/ #ifdef EXTERNALGUI if ( !dev->pGUIStat ) { dev->pGUIStat = malloc( sizeof(GUISTAT) ); dev->pGUIStat->pszOldStatStr = dev->pGUIStat->szStatStrBuff1; dev->pGUIStat->pszNewStatStr = dev->pGUIStat->szStatStrBuff2; *dev->pGUIStat->pszOldStatStr = 0; *dev->pGUIStat->pszNewStatStr = 0; } #endif /*EXTERNALGUI*/ /* Mark device valid */ dev->pmcw.flag5 |= PMCW5_V; dev->allocated = 1; return dev; } void ret_devblk(DEVBLK *dev) { /* Mark device invalid */ dev->allocated = 0; dev->pmcw.flag5 &= ~PMCW5_V; // compat ZZ deprecated release_lock(&dev->lock); } /*-------------------------------------------------------------------*/ /* Function to build a device configuration block */ /*-------------------------------------------------------------------*/ int attach_device (U16 lcss, U16 devnum, const char *type, int addargc, char *addargv[]) { DEVBLK *dev; /* -> Device block */ int rc; /* Return code */ int i; /* Loop index */ /* Check whether device number has already been defined */ if (find_device_by_devnum(lcss,devnum) != NULL) { logmsg (_("HHCCF041E Device %d:%4.4X already exists\n"), lcss,devnum); return 1; } /* obtain device block */ dev = get_devblk(lcss,devnum); if(!(dev->hnd = hdl_ghnd(type))) { logmsg (_("HHCCF042E Device type %s not recognized\n"), type); ret_devblk(dev); return 1; } dev->typname = strdup(type); /* Copy the arguments */ dev->argc = addargc; if (addargc) { dev->argv = malloc ( addargc * sizeof(BYTE *) ); for (i = 0; i < addargc; i++) if (addargv[i]) dev->argv[i] = strdup(addargv[i]); else dev->argv[i] = NULL; } else dev->argv = NULL; /* Call the device handler initialization function */ rc = (dev->hnd->init)(dev, addargc, addargv); if (rc < 0) { logmsg (_("HHCCF044E Initialization failed for device %4.4X\n"), devnum); for (i = 0; i < dev->argc; i++) if (dev->argv[i]) free(dev->argv[i]); if (dev->argv) free(dev->argv); free(dev->typname); ret_devblk(dev); return 1; } /* Obtain device data buffer */ if (dev->bufsize != 0) { dev->buf = malloc (dev->bufsize); if (dev->buf == NULL) { logmsg (_("HHCCF045E Cannot obtain buffer " "for device %4.4X: %s\n"), dev->devnum, strerror(errno)); for (i = 0; i < dev->argc; i++) if (dev->argv[i]) free(dev->argv[i]); if (dev->argv) free(dev->argv); free(dev->typname); ret_devblk(dev); return 1; } } /* Release device lock */ release_lock(&dev->lock); #ifdef _FEATURE_CHANNEL_SUBSYSTEM /* Signal machine check */ #if defined(_370) if (sysblk.arch_mode != ARCH_370) #endif machine_check_crwpend(); #endif /*_FEATURE_CHANNEL_SUBSYSTEM*/ /* if(lcss!=0 && sysblk.arch_mode==ARCH_370) { logmsg(_("HHCCF078W %d:%4.4X : Only devices on CSS 0 are usable in S/370 mode\n"),lcss,devnum); } */ return 0; } /* end function attach_device */ /*-------------------------------------------------------------------*/ /* Function to delete a device configuration block */ /*-------------------------------------------------------------------*/ static int detach_devblk (DEVBLK *dev) { int i; /* Loop index */ /* Obtain the device lock */ obtain_lock(&dev->lock); #if defined(OPTION_FAST_DEVLOOKUP) DelSubchanFastLookup(dev->ssid, dev->subchan); if(dev->pmcw.flag5 & PMCW5_V) DelDevnumFastLookup(SSID_TO_LCSS(dev->ssid),dev->devnum); #endif /* Close file or socket */ if ((dev->fd > 2) || dev->console) /* Call the device close handler */ (dev->hnd->close)(dev); for (i = 0; i < dev->argc; i++) if (dev->argv[i]) free(dev->argv[i]); if (dev->argv) free(dev->argv); free(dev->typname); #ifdef _FEATURE_CHANNEL_SUBSYSTEM /* Indicate a CRW is pending for this device */ #if defined(_370) if (sysblk.arch_mode != ARCH_370) #endif /*defined(_370)*/ dev->crwpending = 1; #endif /*_FEATURE_CHANNEL_SUBSYSTEM*/ // detach all devices in group if(dev->group) { int i; dev->group->memdev[dev->member] = NULL; if(dev->group->members) { dev->group->members = 0; for(i = 0; i < dev->group->acount; i++) { if(dev->group->memdev[i] && dev->group->memdev[i]->allocated) { detach_devblk(dev->group->memdev[i]); } } free(dev->group); } dev->group = NULL; } ret_devblk(dev); /* Zeroize the PMCW */ memset (&dev->pmcw, 0, sizeof(PMCW)); #ifdef _FEATURE_CHANNEL_SUBSYSTEM /* Signal machine check */ #if defined(_370) if (sysblk.arch_mode != ARCH_370) #endif machine_check_crwpend(); #endif /*_FEATURE_CHANNEL_SUBSYSTEM*/ return 0; } /* end function detach_device */ /*-------------------------------------------------------------------*/ /* Function to delete a device configuration block by subchannel */ /*-------------------------------------------------------------------*/ int detach_subchan (U16 lcss, U16 subchan) { DEVBLK *dev; /* -> Device block */ int rc; /* Find the device block */ dev = find_device_by_subchan ((LCSS_TO_SSID(lcss)<<16)|subchan); if (dev == NULL) { logmsg (_("HHCCF046E Subchannel %d:%4.4X does not exist\n"), lcss, subchan); return 1; } rc = detach_devblk( dev ); if(!rc) logmsg (_("HHCCF047I Subchannel %d:%4.4X detached\n"), lcss, subchan); return rc; } /*-------------------------------------------------------------------*/ /* Function to delete a device configuration block by device number */ /*-------------------------------------------------------------------*/ int detach_device (U16 lcss,U16 devnum) { DEVBLK *dev; /* -> Device block */ int rc; /* Find the device block */ dev = find_device_by_devnum (lcss,devnum); if (dev == NULL) { logmsg (_("HHCCF046E Device %d:%4.4X does not exist\n"), lcss, devnum); return 1; } rc = detach_devblk( dev ); if(!rc) logmsg (_("HHCCF047I Device %4.4X detached\n"), devnum); return rc; } /*-------------------------------------------------------------------*/ /* Function to rename a device configuration block */ /*-------------------------------------------------------------------*/ int define_device (U16 lcss, U16 olddevn,U16 newdevn) { DEVBLK *dev; /* -> Device block */ /* Find the device block */ dev = find_device_by_devnum (lcss, olddevn); if (dev == NULL) { logmsg (_("HHCCF048E Device %d:%4.4X does not exist\n"), lcss, olddevn); return 1; } /* Check that new device number does not already exist */ if (find_device_by_devnum(lcss, newdevn) != NULL) { logmsg (_("HHCCF049E Device %d:%4.4X already exists\n"), lcss, newdevn); return 1; } /* Obtain the device lock */ obtain_lock(&dev->lock); /* Update the device number in the DEVBLK */ dev->devnum = newdevn; /* Update the device number in the PMCW */ dev->pmcw.devnum[0] = newdevn >> 8; dev->pmcw.devnum[1] = newdevn & 0xFF; /* Disable the device */ dev->pmcw.flag5 &= ~PMCW5_E; #if defined(OPTION_FAST_DEVLOOKUP) DelDevnumFastLookup(lcss,olddevn); DelDevnumFastLookup(lcss,newdevn); #endif #ifdef _FEATURE_CHANNEL_SUBSYSTEM /* Indicate a CRW is pending for this device */ #if defined(_370) if (sysblk.arch_mode != ARCH_370) #endif /*defined(_370)*/ dev->crwpending = 1; #endif /*_FEATURE_CHANNEL_SUBSYSTEM*/ /* Release device lock */ release_lock(&dev->lock); #ifdef _FEATURE_CHANNEL_SUBSYSTEM /* Signal machine check */ #if defined(_370) if (sysblk.arch_mode != ARCH_370) #endif machine_check_crwpend(); #endif /*_FEATURE_CHANNEL_SUBSYSTEM*/ // logmsg (_("HHCCF050I Device %4.4X defined as %4.4X\n"), // olddevn, newdevn); return 0; } /* end function define_device */ /*-------------------------------------------------------------------*/ /* Function to group devblk's belonging to one device (eg OSA, LCS) */ /* */ /* group_device is intended to be called from within a device */ /* initialisation routine to group 1 or more devices to a logical */ /* device group. */ /* */ /* group_device will return true for the device that completes */ /* the device group. (ie the last device to join the group) */ /* */ /* when no group exists, and device group is called with a device */ /* count of zero, then no group will be created. Otherwise */ /* a new group will be created and the currently attaching device */ /* will be the first in the group. */ /* */ /* when a device in a group is detached, all devices in the group */ /* will be detached. The first device to be detached will enter */ /* its close routine with the group intact. Subsequent devices */ /* being detached will no longer have access to previously detached */ /* devices. */ /* */ /* Example of a fixed count device group: */ /* */ /* device_init(dev) */ /* { */ /* if( !device_group(dev, 2) ) */ /* return 0; */ /* */ /* ... all devices in the group have been attached, */ /* ... group initialisation may proceed. */ /* */ /* } */ /* */ /* */ /* Variable device group example: */ /* */ /* device_init(dev) */ /* { */ /* if( !group_device(dev, 0) && dev->group ) */ /* return 0; */ /* */ /* if( !device->group ) */ /* { */ /* ... process parameters to determine number of devices */ /* */ /* // Create group */ /* if( !group_device(dev, variable_count) ) */ /* return 0; */ /* } */ /* */ /* ... all devices in the group have been attached, */ /* ... group initialisation may proceed. */ /* } */ /* */ /* */ /* dev->group : pointer to DEVGRP structure or NULL */ /* dev->member : index into memdev array in DEVGRP structure for */ /* : current DEVBLK */ /* group->members : number of members in group */ /* group->acount : number active members in group */ /* group->memdev[] : array of DEVBLK pointers of member devices */ /* */ /* */ /* members will be equal to acount for a complete group */ /* */ /* */ /* Always: (for grouped devices) */ /* dev->group->memdev[dev->member] == dev */ /* */ /* */ /* Jan Jaeger, 23 Apr 2004 */ /*-------------------------------------------------------------------*/ DLL_EXPORT int group_device(DEVBLK *dev, int members) { DEVBLK *tmp; // Find a compatible group that is incomplete for (tmp = sysblk.firstdev; tmp != NULL && (!tmp->allocated // not allocated || !tmp->group // not a group device || strcmp(tmp->typname,dev->typname) // unequal type || (tmp->group->members == tmp->group->acount) ); // complete tmp = tmp->nextdev) ; if(tmp) { // Join Group dev->group = tmp->group; dev->member = dev->group->acount++; dev->group->memdev[dev->member] = dev; } else if(members) { // Allocate a new Group when requested dev->group = malloc(sizeof(DEVGRP) + members * sizeof(DEVBLK *)); dev->group->members = members; dev->group->acount = 1; dev->group->memdev[0] = dev; dev->member = 0; } return (dev->group && (dev->group->members == dev->group->acount)); } /*-------------------------------------------------------------------*/ /* Function to find a device block given the device number */ /*-------------------------------------------------------------------*/ DLL_EXPORT DEVBLK *find_device_by_devnum (U16 lcss,U16 devnum) { DEVBLK *dev; #if defined(OPTION_FAST_DEVLOOKUP) DEVBLK **devtab; int Chan; Chan=(devnum & 0xff00)>>8 | ((lcss & (FEATURE_LCSS_MAX-1))<<8); if(sysblk.devnum_fl!=NULL) { devtab=sysblk.devnum_fl[Chan]; if(devtab!=NULL) { dev=devtab[devnum & 0xff]; if(dev && dev->allocated && dev->pmcw.flag5 & PMCW5_V && dev->devnum==devnum) { return dev; } else { DelDevnumFastLookup(lcss,devnum); } } } #endif for (dev = sysblk.firstdev; dev != NULL; dev = dev->nextdev) if (dev->allocated && dev->devnum == devnum && lcss==SSID_TO_LCSS(dev->ssid) && dev->pmcw.flag5 & PMCW5_V) break; #if defined(OPTION_FAST_DEVLOOKUP) if(dev) { AddDevnumFastLookup(dev,lcss,devnum); } #endif return dev; } /* end function find_device_by_devnum */ /*-------------------------------------------------------------------*/ /* Function to find a device block given the subchannel number */ /*-------------------------------------------------------------------*/ DEVBLK *find_device_by_subchan (U32 ioid) { U16 subchan = ioid & 0xFFFF; DEVBLK *dev; #if defined(OPTION_FAST_DEVLOOKUP) unsigned int schw = ((subchan & 0xff00)>>8)|(IOID_TO_LCSS(ioid)<<8); #if 0 logmsg(D_("DEBUG : FDBS FL Looking for %d\n"),subchan); #endif if(sysblk.subchan_fl && sysblk.subchan_fl[schw] && sysblk.subchan_fl[schw][subchan & 0xff]) return sysblk.subchan_fl[schw][subchan & 0xff]; #endif #if 0 logmsg(D_("DEBUG : FDBS SL Looking for %8.8x\n"),ioid); #endif for (dev = sysblk.firstdev; dev != NULL; dev = dev->nextdev) if (dev->ssid == IOID_TO_SSID(ioid) && dev->subchan == subchan) break; #if defined(OPTION_FAST_DEVLOOKUP) if(dev) { AddSubchanFastLookup(dev, IOID_TO_SSID(ioid), subchan); } else { DelSubchanFastLookup(IOID_TO_SSID(ioid), subchan); } #endif return dev; } /* end function find_device_by_subchan */ /*-------------------------------------------------------------------*/ /* Returns a CPU register context for the device, or else NULL */ /*-------------------------------------------------------------------*/ REGS *devregs(DEVBLK *dev) { /* If a register context already exists then use it */ if (dev->regs) return dev->regs; /* Otherwise attempt to determine what it should be */ { int i; TID tid = thread_id(); /* Our own thread id */ for (i=0; i < MAX_CPU; i++) if (tid == sysblk.cputid[i]) /* Are we a cpu thread? */ return sysblk.regs[i]; /* yes, use its context */ } return NULL; /* Not CPU thread. Return NULL register context */ } /*-------------------------------------------------------------------*/ /* Internal device parsing structures */ /*-------------------------------------------------------------------*/ typedef struct _DEVARRAY { U16 cuu1; U16 cuu2; } DEVARRAY; typedef struct _DEVNUMSDESC { BYTE lcss; DEVARRAY *da; } DEVNUMSDESC; /*-------------------------------------------------------------------*/ /* Function to Parse a LCSS specification in a device number spec */ /* Syntax : [lcss:]Anything... */ /* Function args : */ /* const char * spec : Parsed string */ /* char **rest : Rest of string (or original str) */ /* Returns : */ /* int : 0 if not specified, 0<=nFEATURE_LCSS_MAX) { if(verbose) { logmsg(_("HHCCF077E Logical Channel Subsystem Identification %d exceeds maximum of %d\n"),lcssid,FEATURE_LCSS_MAX-1); } free(wrk); return -1; } *rest=malloc(strlen(r)+1); strcpy(*rest,r); free(wrk); return lcssid; } static int parse_single_devnum__INTERNAL(const char *spec, U16 *p_lcss, U16 *p_devnum, int verbose) { int rc; U16 lcss; char *r; char *strptr; rc=parse_lcss(spec,&r,verbose); if(rc<0) { return -1; } lcss=rc; rc=strtoul(r,&strptr,16); if(rc<0 || rc>0xffff || *strptr!=0) { if(verbose) { logmsg(_("HHCCF055E Incorrect device address specification near character %c\n"),*strptr); } free(r); return -1; } *p_devnum=rc; *p_lcss=lcss; return 0; } DLL_EXPORT int parse_single_devnum(const char *spec, U16 *lcss, U16 *devnum) { return parse_single_devnum__INTERNAL(spec,lcss,devnum,1); } int parse_single_devnum_silent(const char *spec, U16 *lcss, U16 *devnum) { return parse_single_devnum__INTERNAL(spec,lcss,devnum,0); } /*-------------------------------------------------------------------*/ /* Function to Parse compound device numbers */ /* Syntax : [lcss:]CCUU[-CUU][,CUU..][.nn][...] */ /* Examples : 200-23F */ /* 200,201 */ /* 200.16 */ /* 200-23F,280.8 */ /* etc... */ /* : is the LCSS id separator (only 0 or 1 allowed and it must be 1st*/ /* - is the range specification (from CUU to CUU) */ /* , is the separator */ /* . is the count indicator (nn is decimal) */ /* 1st parm is the specification string as specified above */ /* 2nd parm is the address of an array of DEVARRAY */ /* Return value : 0 - Parsing error, etc.. */ /* >0 - Size of da */ /* */ /* NOTE : A basic validity check is made for the following : */ /* All CUUs must belong on the same channel */ /* (this check is to eventually pave the way to a formal */ /* channel/cu/device architecture) */ /* no 2 identical CCUUs */ /* ex : 200,300 : WRONG */ /* 200.12,200.32 : WRONG */ /* 2FF.2 : WRONG */ /* NOTE : caller should free the array returned in da if the return */ /* value is not 0 */ /*-------------------------------------------------------------------*/ static size_t parse_devnums(const char *spec,DEVNUMSDESC *dd) { size_t gcount; /* Group count */ size_t i; /* Index runner */ char *grps; /* Pointer to current devnum group */ char *sc; /* Specification string copy */ DEVARRAY *dgrs; /* Device groups */ U16 cuu1,cuu2; /* CUUs */ char *strptr; /* strtoul ptr-ptr */ int basechan=0; /* Channel for all CUUs */ int duplicate; /* duplicated CUU indicator */ int badcuu; /* offending CUU */ int rc; /* Return code work var */ rc=parse_lcss(spec,&sc,1); if(rc<0) { return 0; } dd->lcss=rc; /* Split by ',' groups */ gcount=0; grps=strtok(sc,","); dgrs=NULL; while(grps!=NULL) { if(dgrs==NULL) { dgrs=malloc(sizeof(DEVARRAY)); } else { dgrs=realloc(dgrs,(sizeof(DEVARRAY))*(gcount+1)); } cuu1=strtoul(grps,&strptr,16); switch(*strptr) { case 0: /* Single CUU */ cuu2=cuu1; break; case '-': /* CUU Range */ cuu2=strtoul(&strptr[1],&strptr,16); if(*strptr!=0) { logmsg(_("HHCCF053E Incorrect second device number in device range near character %c\n"),*strptr); free(dgrs); free(sc); return(0); } break; case '.': /* CUU Count */ cuu2=cuu1+strtoul(&strptr[1],&strptr,10); cuu2--; if(*strptr!=0) { logmsg(_("HHCCF054E Incorrect Device count near character %c\n"),*strptr); free(dgrs); free(sc); return(0); } break; default: logmsg(_("HHCCF055E Incorrect device address specification near character %c\n"),*strptr); free(dgrs); free(sc); return(0); } /* Check cuu1 <= cuu2 */ if(cuu1>cuu2) { logmsg(_("HHCCF056E Incorrect device address range. %4.4X < %4.4X\n"),cuu2,cuu1); free(dgrs); free(sc); return(0); } if(gcount==0) { basechan=(cuu1 >> 8) & 0xff; } badcuu=-1; if(((cuu1 >> 8) & 0xff) != basechan) { badcuu=cuu1; } else { if(((cuu2 >> 8) & 0xff) != basechan) { badcuu=cuu2; } } if(badcuu>=0) { logmsg(_("HHCCF057E %4.4X is on wrong channel (1st device defined on channel %2.2X)\n"),badcuu,basechan); free(dgrs); free(sc); return(0); } /* Check for duplicates */ duplicate=0; for(i=0;i=dgrs[i].cuu1 && cuu1<=dgrs[i].cuu2) { duplicate=1; break; } /* check 2nd cuu not within existing range */ if(cuu2>=dgrs[i].cuu1 && cuu1<=dgrs[i].cuu2) { duplicate=1; break; } /* check current range doesn't completelly overlap existing range */ if(cuu1dgrs[i].cuu2) { duplicate=1; break; } } if(duplicate) { logmsg(_("HHCCF058E Some or all devices in %4.4X-%4.4X duplicate devices already defined\n"),cuu1,cuu2); free(dgrs); free(sc); return(0); } dgrs[gcount].cuu1=cuu1; dgrs[gcount].cuu2=cuu2; gcount++; grps=strtok(NULL,","); } free(sc); dd->da=dgrs; return(gcount); } int parse_and_attach_devices(const char *sdevnum, const char *sdevtype, int addargc, char **addargv) { DEVNUMSDESC dnd; int baddev; size_t devncount; DEVARRAY *da; int i; U16 devnum; int rc; #if defined(OPTION_CONFIG_SYMBOLS) int j; char **newargv; char **orig_newargv; #endif devncount=parse_devnums(sdevnum,&dnd); if(devncount==0) { return -2; } #if defined(OPTION_CONFIG_SYMBOLS) newargv=malloc(MAX_ARGS*sizeof(char *)); orig_newargv=malloc(MAX_ARGS*sizeof(char *)); #endif /* #if defined(OPTION_CONFIG_SYMBOLS) */ for(baddev=0,i=0;i<(int)devncount;i++) { da=dnd.da; for(devnum=da[i].cuu1;devnum<=da[i].cuu2;devnum++) { #if defined(OPTION_CONFIG_SYMBOLS) char wrkbfr[16]; snprintf(wrkbfr,sizeof(wrkbfr),"%3.3x",devnum); set_symbol("cuu",wrkbfr); snprintf(wrkbfr,sizeof(wrkbfr),"%4.4x",devnum); set_symbol("ccuu",wrkbfr); snprintf(wrkbfr,sizeof(wrkbfr),"%3.3X",devnum); set_symbol("CUU",wrkbfr); snprintf(wrkbfr,sizeof(wrkbfr),"%4.4X",devnum); set_symbol("CCUU",wrkbfr); snprintf(wrkbfr,sizeof(wrkbfr),"%d",dnd.lcss); set_symbol("CSS",wrkbfr); for(j=0;jMAX_LOGO_LINES) { break; } } fclose(lf); sysblk.herclogo=data; return 0; } DLL_EXPORT int parse_conkpalv(char* s, int* idle, int* intv, int* cnt ) { size_t n; char *p1, *p2, *p3, c; ASSERT(s && *s && idle && intv && cnt); if (!s || !*s || !idle || !intv || !cnt) return -1; // Format: "(idle,intv,cnt)". All numbers. No spaces. if (0 || (n = strlen(s)) < 7 || s[0] != '(' || s[n-1] != ')' ) return -1; // 1st sub-operand if (!(p1 = strchr(s+1, ','))) return -1; c = *p1; *p1 = 0; if ( strspn( s+1, "0123456789" ) != strlen(s+1) ) { *p1 = c; return -1; } *p1 = c; // 2nd sub-operand if (!(p2 = strchr(p1+1, ','))) return -1; c = *p2; *p2 = 0; if ( strspn( p1+1, "0123456789" ) != strlen(p1+1) ) { *p2 = c; return -1; } *p2 = c; // 3rd sub-operand if (!(p3 = strchr(p2+1, ')'))) return -1; c = *p3; *p3 = 0; if ( strspn( p2+1, "0123456789" ) != strlen(p2+1) ) { *p3 = c; return -1; } *p3 = c; // convert each to number c = *p1; *p1 = 0; *idle = atoi(s+1); *p1 = c; c = *p2; *p2 = 0; *intv = atoi(p1+1); *p2 = c; c = *p3; *p3 = 0; *cnt = atoi(p2+1); *p3 = c; // check results if (*idle <= 0 || INT_MAX == *idle) return -1; if (*intv <= 0 || INT_MAX == *intv) return -1; if (*cnt <= 0 || INT_MAX == *cnt ) return -1; return 0; } #endif /*!defined(_GEN_ARCH)*/ hercules-3.07/config.h.in000644 000765 000765 00000046520 11321734066 017000 0ustar00jmaynardjmaynard000000 000000 /* config.h.in. Generated from configure.ac by autoheader. */ /* Define if hercifc program is to be built */ #undef BUILD_HERCIFC /* Define if your gcc properly supports C99 flexible arrays */ #undef C99_FLEXIBLE_ARRAYS /* Define to enable bzip2 compression in emulated DASDs */ #undef CCKD_BZIP2 /* Define to provide additional information about this build */ #undef CUSTOM_BUILD_STRING /* Define to enable extra debugging code (TRACE/VERIFY/ASSERT macros) */ #undef DEBUG /* Define to 1 if translation of program messages to the user's native language is requested. */ #undef ENABLE_NLS /* Define to build interface to external Windows GUI */ #undef EXTERNALGUI /* Define to debug correct fthreads LOCK handling (requires fthreads) */ #undef FISH_HANG /* Define to 1 if you have the `alphasort' function. */ #undef HAVE_ALPHASORT /* Define to 1 if you have the `argz_append' function. */ #undef HAVE_ARGZ_APPEND /* Define to 1 if you have the `argz_create_sep' function. */ #undef HAVE_ARGZ_CREATE_SEP /* Define to 1 if you have the header file. */ #undef HAVE_ARGZ_H /* Define to 1 if you have the `argz_insert' function. */ #undef HAVE_ARGZ_INSERT /* Define to 1 if you have the `argz_next' function. */ #undef HAVE_ARGZ_NEXT /* Define to 1 if you have the `argz_stringify' function. */ #undef HAVE_ARGZ_STRINGIFY /* Define to 1 if you have the header file. */ #undef HAVE_ARPA_INET_H /* Define to 1 if you have the header file. */ #undef HAVE_ASSERT_H /* Define if your gcc properly supports __attribute__((regparm(n))) */ #undef HAVE_ATTR_REGPARM /* Define to 1 if you have the `bcopy' function. */ #undef HAVE_BCOPY /* Define to 1 if you have the header file. */ #undef HAVE_BYTESWAP_H /* Define to 1 if you have the header file. */ #undef HAVE_BZLIB_H /* Define to 1 if you have the MacOS X function CFLocaleCopyCurrent in the CoreFoundation framework. */ #undef HAVE_CFLOCALECOPYCURRENT /* Define to 1 if you have the MacOS X function CFPreferencesCopyAppValue in the CoreFoundation framework. */ #undef HAVE_CFPREFERENCESCOPYAPPVALUE /* Define to 1 if you have the `closedir' function. */ #undef HAVE_CLOSEDIR /* Define to 1 if you have the header file. */ #undef HAVE_CTYPE_H /* Define if the GNU dcgettext() function is already present or preinstalled. */ #undef HAVE_DCGETTEXT /* Define to 1 if you have the declaration of `IFNAMSIZ', and to 0 if you don't. */ #undef HAVE_DECL_IFNAMSIZ /* Define to 1 if you have the declaration of `LOGIN_NAME_MAX', and to 0 if you don't. */ #undef HAVE_DECL_LOGIN_NAME_MAX /* Define to 1 if you have the declaration of `MTEWARN', and to 0 if you don't. */ #undef HAVE_DECL_MTEWARN /* Define to 1 if you have the declaration of `SIGBUS', and to 0 if you don't. */ #undef HAVE_DECL_SIGBUS /* Define to 1 if you have the declaration of `SIGPIPE', and to 0 if you don't. */ #undef HAVE_DECL_SIGPIPE /* Define to 1 if you have the declaration of `SIGUSR1', and to 0 if you don't. */ #undef HAVE_DECL_SIGUSR1 /* Define to 1 if you have the declaration of `SIGUSR2', and to 0 if you don't. */ #undef HAVE_DECL_SIGUSR2 /* Define to 1 if you have the declaration of `SIOCADDRT', and to 0 if you don't. */ #undef HAVE_DECL_SIOCADDRT /* Define to 1 if you have the declaration of `SIOCDELRT', and to 0 if you don't. */ #undef HAVE_DECL_SIOCDELRT /* Define to 1 if you have the declaration of `SIOCDIFADDR', and to 0 if you don't. */ #undef HAVE_DECL_SIOCDIFADDR /* Define to 1 if you have the declaration of `SIOCSIFHWADDR', and to 0 if you don't. */ #undef HAVE_DECL_SIOCSIFHWADDR /* Define to 1 if you have the declaration of `SIOCSIFNETMASK', and to 0 if you don't. */ #undef HAVE_DECL_SIOCSIFNETMASK /* Define to 1 if you have the declaration of `_SC_NPROCESSORS_CONF', and to 0 if you don't. */ #undef HAVE_DECL__SC_NPROCESSORS_CONF /* Define to 1 if you have the declaration of `_SC_NPROCESSORS_ONLN', and to 0 if you don't. */ #undef HAVE_DECL__SC_NPROCESSORS_ONLN /* Define to 1 if you have the header file, and it defines `DIR'. */ #undef HAVE_DIRENT_H /* Define if you have the GNU dld library. */ #undef HAVE_DLD /* Define to 1 if you have the header file. */ #undef HAVE_DLD_H /* Define to 1 if you have the `dlerror' function. */ #undef HAVE_DLERROR /* Define to 1 if you have the header file. */ #undef HAVE_DLFCN_H /* Define to 1 if you have the header file. */ #undef HAVE_DL_H /* Define if you have the _dyld_func_lookup function. */ #undef HAVE_DYLD /* Define to 1 if you have the header file. */ #undef HAVE_ERRNO_H /* Define to 1 if the system has the type `error_t'. */ #undef HAVE_ERROR_T /* Define to 1 if you have the `fabsf' function. */ #undef HAVE_FABSF /* Define to 1 if you have the `fabsl' function. */ #undef HAVE_FABSL /* Define to 1 if you have the `fdatasync' function. */ #undef HAVE_FDATASYNC /* Define to 1 if the fdatasync function is supported. */ #undef HAVE_FDATASYNC_SUPPORTED /* Define to 1 if you have the header file. */ #undef HAVE_FENV_H /* Define to 1 if you have the `fmodl' function. */ #undef HAVE_FMODL /* Define to 1 if you have the `fork' function. */ #undef HAVE_FORK /* Define to 1 if you have the `frexpf' function. */ #undef HAVE_FREXPF /* Define to 1 if you have the `frexpl' function. */ #undef HAVE_FREXPL /* Define to 1 if fseeko (and presumably ftello) exists and is declared. */ #undef HAVE_FSEEKO /* Define to 1 if you have the `fsync' function. */ #undef HAVE_FSYNC /* Define to 1 if you have the `ftruncate' function. */ #undef HAVE_FTRUNCATE /* Define to 1 if you have the `geteuid' function. */ #undef HAVE_GETEUID /* Define to 1 if you have the `getlogin' function. */ #undef HAVE_GETLOGIN /* Define to 1 if you have the `getlogin_r' function. */ #undef HAVE_GETLOGIN_R /* Define to 1 if you have the `getopt_long' function. */ #undef HAVE_GETOPT_LONG /* Define to 1 if you have the `getpgrp' function. */ #undef HAVE_GETPGRP /* Define to 1 if you have the `getresuid' function. */ #undef HAVE_GETRESUID /* Define if the GNU gettext() function is already present or preinstalled. */ #undef HAVE_GETTEXT /* Define to 1 if you have the `gettimeofday' function. */ #undef HAVE_GETTIMEOFDAY /* Define to 1 if you have the `getuid' function. */ #undef HAVE_GETUID /* Define to 1 if you have the `iconv' function. */ #undef HAVE_ICONV /* Define to 1 if you have the header file. */ #undef HAVE_ICONV_H /* Define to 1 if the system has the type `id_t'. */ #undef HAVE_ID_T /* Define to 1 if you have the `index' function. */ #undef HAVE_INDEX /* Define to 1 if you have the `inet_aton' function. */ #undef HAVE_INET_ATON /* Define to 1 if you have the `InitializeCriticalSectionAndSpinCount' function. */ #undef HAVE_INITIALIZECRITICALSECTIONANDSPINCOUNT /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H /* Define to 1 if the system has the type `in_addr_t'. */ #undef HAVE_IN_ADDR_T /* Define to 1 if you have the `ldexpf' function. */ #undef HAVE_LDEXPF /* Define to 1 if you have the `ldexpl' function. */ #undef HAVE_LDEXPL /* Define to 1 if you have the `cap' library (-lcap). */ #undef HAVE_LIBCAP /* Define to 1 if you have the `dl' library (-ldl). */ #undef HAVE_LIBDL /* Define to 1 if you have the `iconv' library (-liconv). */ #undef HAVE_LIBICONV /* Define to 1 if you have the header file. */ #undef HAVE_LIBINTL_H /* Define to 1 if you have the `m' library (-lm). */ #undef HAVE_LIBM /* Define to 1 if you have the `msvcrt' library (-lmsvcrt). */ #undef HAVE_LIBMSVCRT /* Define to 1 if you have the `nsl' library (-lnsl). */ #undef HAVE_LIBNSL /* Define to 1 if you have the `pthread' library (-lpthread). */ #undef HAVE_LIBPTHREAD /* Define to 1 if you have the `resolv' library (-lresolv). */ #undef HAVE_LIBRESOLV /* Define to 1 if you have the `rt' library (-lrt). */ #undef HAVE_LIBRT /* Define to 1 if you have the `socket' library (-lsocket). */ #undef HAVE_LIBSOCKET /* Define to 1 if you have the `z' library (-lz). */ #undef HAVE_LIBZ /* Define to 1 if you have the header file. */ #undef HAVE_LINUX_IF_TUN_H /* Define to 1 if you have the header file. */ #undef HAVE_LOCALE_H /* Define to 1 if you have the header file. */ #undef HAVE_LTDL_H /* Define to 1 if you have the header file. */ #undef HAVE_MACH_O_DYLD_H /* Define to 1 if you have the header file. */ #undef HAVE_MALLOC_H /* Define to 1 if you have the header file. */ #undef HAVE_MATH_H /* Define to 1 if you have the `memcpy' function. */ #undef HAVE_MEMCPY /* Define to 1 if you have the `memmove' function. */ #undef HAVE_MEMMOVE /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H /* Define to 1 if you have the `memrchr' function. */ #undef HAVE_MEMRCHR /* Define to 1 if you have the `nanosleep' function. */ #undef HAVE_NANOSLEEP /* Define to 1 if you have the header file, and it defines `DIR'. */ #undef HAVE_NDIR_H /* Define to 1 if you have the header file. */ #undef HAVE_NETDB_H /* Define to 1 if you have the header file. */ #undef HAVE_NETINET_IN_H /* Define to 1 if you have the header file. */ #undef HAVE_NETINET_TCP_H /* Define to 1 if you have the header file. */ #undef HAVE_NET_IF_H /* Define to 1 if you have the header file. */ #undef HAVE_NET_ROUTE_H /* Define to 1 if you have the `opendir' function. */ #undef HAVE_OPENDIR /* Define to 1 if you have the `pipe' function. */ #undef HAVE_PIPE /* Define if libtool can extract symbol lists from object files. */ #undef HAVE_PRELOADED_SYMBOLS /* Define to 1 if you have the header file. */ #undef HAVE_PWD_H /* Define to 1 if you have the `readdir' function. */ #undef HAVE_READDIR /* Define to 1 if you have the `realpath' function. */ #undef HAVE_REALPATH /* Define to 1 if you have the header file. */ #undef HAVE_REGEX_H /* Define to 1 if you have the `rindex' function. */ #undef HAVE_RINDEX /* Define to 1 if you have the `rint' function. */ #undef HAVE_RINT /* Define to 1 if you have the `scandir' function. */ #undef HAVE_SCANDIR /* Define to 1 if you have the header file. */ #undef HAVE_SCHED_H /* Define to 1 if you have the `sched_yield' function. */ #undef HAVE_SCHED_YIELD /* Define to 1 if you have the `setresuid' function. */ #undef HAVE_SETRESUID /* Define to 1 if you have the `setreuid' function. */ #undef HAVE_SETREUID /* Define if you have the shl_load function. */ #undef HAVE_SHL_LOAD /* Define to 1 if you have the header file. */ #undef HAVE_SIGNAL_H /* Define to 1 if you have the `sleep' function. */ #undef HAVE_SLEEP /* Define to 1 if you have the `socketpair' function. */ #undef HAVE_SOCKETPAIR /* Define to 1 if the system has the type `socklen_t'. */ #undef HAVE_SOCKLEN_T /* Define to 1 if you have the `sqrtl' function. */ #undef HAVE_SQRTL /* Define to 1 if you have the header file. */ #undef HAVE_STDINT_H /* Define to 1 if you have the header file. */ #undef HAVE_STDIO_H /* Define to 1 if you have the header file. */ #undef HAVE_STDLIB_H /* Define to 1 if you have the `strchr' function. */ #undef HAVE_STRCHR /* Define to 1 if you have the `strcmp' function. */ #undef HAVE_STRCMP /* Define to 1 if you have the `strerror_r' function. */ #undef HAVE_STRERROR_R /* Define to 1 if you have the header file. */ #undef HAVE_STRINGS_H /* Define to 1 if you have the header file. */ #undef HAVE_STRING_H /* Define to 1 if you have the `strlcat' function. */ #undef HAVE_STRLCAT /* Define to 1 if you have the `strlcpy' function. */ #undef HAVE_STRLCPY /* Define to 1 if you have the `strrchr' function. */ #undef HAVE_STRRCHR /* Define to 1 if you have the `strsignal' function. */ #undef HAVE_STRSIGNAL /* Define to 1 if you have the `strtok_r' function. */ #undef HAVE_STRTOK_R /* Define to 1 if `s_addr' is member of `struct in_addr'. */ #undef HAVE_STRUCT_IN_ADDR_S_ADDR /* Define to 1 if `sa_sigaction' is member of `struct sigaction'. */ #undef HAVE_STRUCT_SIGACTION_SA_SIGACTION /* Define to 1 if `sin_len' is member of `struct sockaddr_in'. */ #undef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN /* Define to 1 if `tv_nsec' is member of `struct timespec'. */ #undef HAVE_STRUCT_TIMESPEC_TV_NSEC /* Define to 1 if you have the `sysconf' function. */ #undef HAVE_SYSCONF /* Define to 1 if you have the header file. */ #undef HAVE_SYS_CAPABILITY_H /* Define to 1 if you have the header file, and it defines `DIR'. */ #undef HAVE_SYS_DIR_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_DL_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_IOCTL_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_MMAN_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_MOUNT_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_MTIO_H /* Define to 1 if you have the header file, and it defines `DIR'. */ #undef HAVE_SYS_NDIR_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_PARAM_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_PRCTL_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_RESOURCE_H /* Define to 1 if you have the `sys_siglist' function. */ #undef HAVE_SYS_SIGLIST /* Define to 1 if you have the header file. */ #undef HAVE_SYS_SOCKET_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STAT_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TYPES_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_UIO_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_UN_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_UTSNAME_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_WAIT_H /* Define to 1 if you have the header file. */ #undef HAVE_TERMIOS_H /* Define to 1 if you have the header file. */ #undef HAVE_TIME_H /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H /* Define to 1 if the system has the type `useconds_t'. */ #undef HAVE_USECONDS_T /* Define to 1 if you have the `usleep' function. */ #undef HAVE_USLEEP /* Define to 1 if the system has the type `u_char'. */ #undef HAVE_U_CHAR /* Define to 1 if the system has the type `u_int'. */ #undef HAVE_U_INT /* Define to 1 if the system has the type `u_int8_t'. */ #undef HAVE_U_INT8_T /* Define to 1 if the system has the type `u_long'. */ #undef HAVE_U_LONG /* Define to 1 if the system has the type `u_short'. */ #undef HAVE_U_SHORT /* Define to 1 if you have the `vsscanf' function. */ #undef HAVE_VSSCANF /* Define to 1 if you have the header file. */ #undef HAVE_ZLIB_H /* Define to indicate shared libraries are being used */ #undef HDL_BUILD_SHARED /* Define to cause dynamic loader to use libtool instead of dlopen */ #undef HDL_USE_LIBTOOL /* Directory where to find NLS data */ #undef HERC_LOCALEDIR /* Define to enable bzip2 compression in emulated tapes */ #undef HET_BZIP2 /* Define as const if the declaration of iconv() needs const. */ #undef ICONV_CONST /* Define if the OS needs help to load dependent libraries for dlopen(). */ #undef LTDL_DLOPEN_DEPLIBS /* Define to the sub-directory in which libtool stores uninstalled libraries. */ #undef LTDL_OBJDIR /* Define to the name of the environment variable that determines the dynamic library search path. */ #undef LTDL_SHLIBPATH_VAR /* Define to the extension used for shared libraries, say, ".so". */ #undef LTDL_SHLIB_EXT /* Define to the system default library search path. */ #undef LTDL_SYSSEARCHPATH /* Defines the maximum number of emulated CPU engines */ #undef MAX_CPU_ENGINES /* Directory where HERCULES modules are installed */ #undef MODULESDIR /* Define to indicate optreset exists */ #undef NEED_GETOPT_OPTRESET /* Define to indicate a wrapper for getopt is needed */ #undef NEED_GETOPT_WRAPPER /* Define if dlsym() requires a leading underscore in symbol names. */ #undef NEED_USCORE /* Define if 'gettimeofday' returns non-unique values */ #undef NON_UNIQUE_GETTIMEOFDAY /* Define to disable assembler routines for byte swapping */ #undef NO_ASM_BYTESWAP /* Define to disable IEEE floating point support */ #undef NO_IEEE_SUPPORT /* Define to disable setuid operation */ #undef NO_SETUID /* Define to disable sigabend_handler (please describe this better) */ #undef NO_SIGABEND_HANDLER /* Define to enable posix draft 1003.1e capabilities */ #undef OPTION_CAPABILITIES /* Define to enable symbolic substitutions in configuration file */ #undef OPTION_CONFIG_SYMBOLS /* Define to enable Hercules Dynamic Loader feature */ #undef OPTION_DYNAMIC_LOAD /* Define to enable enhanced-mode 'include' file support in configuration file */ #undef OPTION_ENHANCED_CONFIG_INCLUDE /* Define to enable enhanced-mode symbolic substitutions in configuration file */ #undef OPTION_ENHANCED_CONFIG_SYMBOLS /* Define to use included threads implementation (fthreads) */ #undef OPTION_FTHREADS /* Define to enable Hercules Automatic Operator feature */ #undef OPTION_HAO /* Name of package */ #undef PACKAGE /* Define to the address where bug reports for this package should be sent. */ #undef PACKAGE_BUGREPORT /* Define to the full name of this package. */ #undef PACKAGE_NAME /* Define to the full name and version of this package. */ #undef PACKAGE_STRING /* Define to the one symbol short name of this package. */ #undef PACKAGE_TARNAME /* Define to the version of this package. */ #undef PACKAGE_VERSION /* Directory where the HTTP server will find documents */ #undef PKGDATADIR /* The size of `int', as computed by sizeof. */ #undef SIZEOF_INT /* The size of `int *', as computed by sizeof. */ #undef SIZEOF_INT_P /* The size of `long', as computed by sizeof. */ #undef SIZEOF_LONG /* The size of `off_t', as computed by sizeof. */ #undef SIZEOF_OFF_T /* The size of `size_t', as computed by sizeof. */ #undef SIZEOF_SIZE_T /* The size of `struct bytestruct', as computed by sizeof. */ #undef SIZEOF_STRUCT_BYTESTRUCT /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS /* Define if 'struct timespec' defined in */ #undef TIMESPEC_IN_SYS_TYPES_H /* Define if 'struct timespec' defined in */ #undef TIMESPEC_IN_TIME_H /* Version number of package */ #undef VERSION /* Define when building under Win32 (MinGW or Cygwin) */ #undef WIN32 /* Define to 1 if your processor stores words with the most significant byte first (like Motorola and SPARC, unlike Intel and VAX). */ #undef WORDS_BIGENDIAN /* Define missing macro on apple darwin (osx) platform */ #undef _BSD_SOCKLEN_T_ /* Number of bits in a file offset, on hosts where this is settable. */ #undef _FILE_OFFSET_BITS /* Define to 1 if non-Intel architecture (gettext) */ #undef _INTL_REDIRECT_MACROS /* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */ #undef _LARGEFILE_SOURCE /* Define for large files, on AIX-style hosts. */ #undef _LARGE_FILES /* Define to empty if `const' does not conform to ANSI C. */ #undef const /* Define to a type to use for `error_t' if it is not otherwise available. */ #undef error_t /* Define to `long int' if does not define. */ #undef off_t hercules-3.07/configure000755 000765 000765 00005307657 11344713142 016701 0ustar00jmaynardjmaynard000000 000000 #! /bin/sh # From configure.ac Revision: 5638 . # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.61. # # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, # 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## --------------------- ## ## M4sh Initialization. ## ## --------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in *posix*) set -o posix ;; esac fi # PATH needs CR # 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 # Support unset when possible. if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then as_unset=unset else as_unset=false fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) as_nl=' ' IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. case $0 in *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 { (exit 1); exit 1; } fi # Work around bugs in pre-3.0 UWIN ksh. for as_var in ENV MAIL MAILPATH do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var done 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) >/dev/null 2>&1 && $as_unset $as_var fi done # Required to use basename. if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi # 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'` # CDPATH. $as_unset CDPATH if test "x$CONFIG_SHELL" = x; then if (eval ":") 2>/dev/null; then as_have_required=yes else as_have_required=no fi if test $as_have_required = yes && (eval ": (as_func_return () { (exit \$1) } as_func_success () { as_func_return 0 } as_func_failure () { as_func_return 1 } as_func_ret_success () { return 0 } as_func_ret_failure () { return 1 } exitcode=0 if as_func_success; then : else exitcode=1 echo as_func_success failed. fi if as_func_failure; then exitcode=1 echo as_func_failure succeeded. fi if as_func_ret_success; then : else exitcode=1 echo as_func_ret_success failed. fi if as_func_ret_failure; then exitcode=1 echo as_func_ret_failure succeeded. fi if ( set x; as_func_ret_success y && test x = \"\$1\" ); then : else exitcode=1 echo positional parameters were not saved. fi test \$exitcode = 0) || { (exit 1); exit 1; } ( as_lineno_1=\$LINENO as_lineno_2=\$LINENO test \"x\$as_lineno_1\" != \"x\$as_lineno_2\" && test \"x\`expr \$as_lineno_1 + 1\`\" = \"x\$as_lineno_2\") || { (exit 1); exit 1; } ") 2> /dev/null; then : else as_candidate_shells= 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=. case $as_dir in /*) for as_base in sh bash ksh sh5; do as_candidate_shells="$as_candidate_shells $as_dir/$as_base" done;; esac done IFS=$as_save_IFS for as_shell in $as_candidate_shells $SHELL; do # Try only shells that exist, to save several forks. if { test -f "$as_shell" || test -f "$as_shell.exe"; } && { ("$as_shell") 2> /dev/null <<\_ASEOF if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in *posix*) set -o posix ;; esac fi : _ASEOF }; then CONFIG_SHELL=$as_shell as_have_required=yes if { "$as_shell" 2> /dev/null <<\_ASEOF if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in *posix*) set -o posix ;; esac fi : (as_func_return () { (exit $1) } as_func_success () { as_func_return 0 } as_func_failure () { as_func_return 1 } as_func_ret_success () { return 0 } as_func_ret_failure () { return 1 } exitcode=0 if as_func_success; then : else exitcode=1 echo as_func_success failed. fi if as_func_failure; then exitcode=1 echo as_func_failure succeeded. fi if as_func_ret_success; then : else exitcode=1 echo as_func_ret_success failed. fi if as_func_ret_failure; then exitcode=1 echo as_func_ret_failure succeeded. fi if ( set x; as_func_ret_success y && test x = "$1" ); then : else exitcode=1 echo positional parameters were not saved. fi test $exitcode = 0) || { (exit 1); exit 1; } ( as_lineno_1=$LINENO as_lineno_2=$LINENO test "x$as_lineno_1" != "x$as_lineno_2" && test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2") || { (exit 1); exit 1; } _ASEOF }; then break fi fi done if test "x$CONFIG_SHELL" != x; then for as_var in BASH_ENV ENV do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var done export CONFIG_SHELL exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"} fi if test $as_have_required = no; then echo This script requires a shell more modern than all the echo shells that I found on your system. Please install a echo modern shell, or manually run the script under such a echo shell if you do have one. { (exit 1); exit 1; } fi fi fi (eval "as_func_return () { (exit \$1) } as_func_success () { as_func_return 0 } as_func_failure () { as_func_return 1 } as_func_ret_success () { return 0 } as_func_ret_failure () { return 1 } exitcode=0 if as_func_success; then : else exitcode=1 echo as_func_success failed. fi if as_func_failure; then exitcode=1 echo as_func_failure succeeded. fi if as_func_ret_success; then : else exitcode=1 echo as_func_ret_success failed. fi if as_func_ret_failure; then exitcode=1 echo as_func_ret_failure succeeded. fi if ( set x; as_func_ret_success y && test x = \"\$1\" ); then : else exitcode=1 echo positional parameters were not saved. fi test \$exitcode = 0") || { echo No shell found that supports shell functions. echo Please tell autoconf@gnu.org about your system, echo including any error possibly output before this echo message } as_lineno_1=$LINENO as_lineno_2=$LINENO test "x$as_lineno_1" != "x$as_lineno_2" && test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || { # 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 after each line using $LINENO; the second 'sed' # does the real work. The second script uses 'N' to pair each # line-number line with the line containing $LINENO, 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 # scripts with optimization help from Paolo Bonzini. Blame Lee # E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { 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 sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in -n*) case `echo 'x\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. *) ECHO_C='\c';; esac;; *) ECHO_N='-n';; esac if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir fi echo >conf$$.file if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -p'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -p' 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$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p=: else test -d ./-p && rmdir ./-p as_mkdir_p=false fi if test -x / >/dev/null 2>&1; then as_test_x='test -x' else if ls -dL / >/dev/null 2>&1; then as_ls_L_option=L else as_ls_L_option= fi as_test_x=' eval sh -c '\'' if test -d "$1"; then test -d "$1/."; else case $1 in -*)set "./$1";; esac; case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in ???[sx]*):;;*)false;;esac;fi '\'' sh ' fi as_executable_p=$as_test_x # 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'" # Check that we are running under the correct shell. SHELL=${CONFIG_SHELL-/bin/sh} case X$ECHO in X*--fallback-echo) # Remove one level of quotation (which was required for Make). ECHO=`echo "$ECHO" | sed 's,\\\\\$\\$0,'$0','` ;; esac echo=${ECHO-echo} if test "X$1" = X--no-reexec; then # Discard the --no-reexec flag, and continue. shift elif test "X$1" = X--fallback-echo; then # Avoid inline document here, it may be left over : elif test "X`($echo '\t') 2>/dev/null`" = 'X\t' ; then # Yippee, $echo works! : else # Restart under the correct shell. exec $SHELL "$0" --no-reexec ${1+"$@"} fi if test "X$1" = X--fallback-echo; then # used as fallback echo shift cat </dev/null && echo_test_string="`eval $cmd`" && (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null then break fi done fi if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then : else # The Solaris, AIX, and Digital Unix default echo programs unquote # backslashes. This makes it impossible to quote backslashes using # echo "$something" | sed 's/\\/\\\\/g' # # So, first we look for a working echo in the user's PATH. lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for dir in $PATH /usr/ucb; do IFS="$lt_save_ifs" if (test -f $dir/echo || test -f $dir/echo$ac_exeext) && test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' && echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then echo="$dir/echo" break fi done IFS="$lt_save_ifs" if test "X$echo" = Xecho; then # We didn't find a better echo, so look for alternatives. if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' && echo_testing_string=`(print -r "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then # This shell has a builtin print -r that does the trick. echo='print -r' elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) && test "X$CONFIG_SHELL" != X/bin/ksh; then # If we have ksh, try running configure again with it. ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh} export ORIGINAL_CONFIG_SHELL CONFIG_SHELL=/bin/ksh export CONFIG_SHELL exec $CONFIG_SHELL "$0" --no-reexec ${1+"$@"} else # Try using printf. echo='printf %s\n' if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then # Cool, printf works : elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` && test "X$echo_testing_string" = 'X\t' && echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL export CONFIG_SHELL SHELL="$CONFIG_SHELL" export SHELL echo="$CONFIG_SHELL $0 --fallback-echo" elif echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` && test "X$echo_testing_string" = 'X\t' && echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then echo="$CONFIG_SHELL $0 --fallback-echo" else # maybe with a smaller string... prev=: for cmd in 'echo test' 'sed 2q "$0"' 'sed 10q "$0"' 'sed 20q "$0"' 'sed 50q "$0"'; do if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null then break fi prev="$cmd" done if test "$prev" != 'sed 50q "$0"'; then echo_test_string=`eval $prev` export echo_test_string exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "$0" ${1+"$@"} else # Oops. We lost completely, so just stick with echo. echo=echo fi fi fi fi fi fi # Copy echo and quote the copy suitably for passing to libtool from # the Makefile, instead of quoting the original, which is used later. ECHO=$echo if test "X$ECHO" = "X$CONFIG_SHELL $0 --fallback-echo"; then ECHO="$CONFIG_SHELL \\\$\$0 --fallback-echo" fi tagnames=${tagnames+${tagnames},}CXX tagnames=${tagnames+${tagnames},}F77 exec 7<&0 &1 # 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` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= SHELL=${CONFIG_SHELL-/bin/sh} # Identity of this package. PACKAGE_NAME= PACKAGE_TARNAME= PACKAGE_VERSION= PACKAGE_STRING= PACKAGE_BUGREPORT= ac_unique_file="hercules.h" # Factoring default headers for most tests. ac_includes_default="\ #include #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_STDLIB_H # include # endif #endif #ifdef HAVE_STRING_H # if !defined STDC_HEADERS && defined HAVE_MEMORY_H # include # endif # include #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif" 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 datarootdir datadir sysconfdir sharedstatedir localstatedir includedir oldincludedir docdir infodir htmldir dvidir pdfdir psdir libdir localedir mandir DEFS ECHO_C ECHO_N ECHO_T LIBS build_alias host_alias target_alias INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO install_sh STRIP INSTALL_STRIP_PROGRAM mkdir_p AWK SET_MAKE am__leading_dot AMTAR am__tar am__untar MAINTAINER_MODE_TRUE MAINTAINER_MODE_FALSE MAINT build build_cpu build_vendor build_os host host_cpu host_vendor host_os CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CCDEPMODE am__fastdepCC_TRUE am__fastdepCC_FALSE modexecdir GREP EGREP LN_S ECHO AR RANLIB DLLTOOL AS OBJDUMP CPP CXX CXXFLAGS ac_ct_CXX CXXDEPMODE am__fastdepCXX_TRUE am__fastdepCXX_FALSE CXXCPP F77 FFLAGS ac_ct_F77 LIBTOOL INSTALL_LTDL_TRUE INSTALL_LTDL_FALSE CONVENIENCE_LTDL_TRUE CONVENIENCE_LTDL_FALSE LIBADD_DL LIBTOOL_DEPS MKINSTALLDIRS USE_NLS MSGFMT GMSGFMT XGETTEXT MSGMERGE INTL_MACOSX_LIBS LIBICONV LTLIBICONV INTLLIBS LIBINTL LTLIBINTL POSUB OPTION_DYNAMIC_LOAD_TRUE OPTION_DYNAMIC_LOAD_FALSE BUILD_FTHREADS_TRUE BUILD_FTHREADS_FALSE BUILD_FISHHANG_TRUE BUILD_FISHHANG_FALSE BUILD_HERCIFC_TRUE BUILD_HERCIFC_FALSE SETUID_HERCIFC_TRUE SETUID_HERCIFC_FALSE HERCIFC_GROUPSET_TRUE HERCIFC_GROUPSET_FALSE HERCIFC_GROUPNAME BUILD_SHARED_TRUE BUILD_SHARED_FALSE USE_DLLTOOL_TRUE USE_DLLTOOL_FALSE LIBOBJS LTLIBOBJS' ac_subst_files='' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS CPP CXX CXXFLAGS CCC CXXCPP F77 FFLAGS' # 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. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_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 ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_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'` 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 ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -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'` 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; }; } 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 directory names. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir do eval ac_val=\$$ac_var case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 { (exit 1); exit 1; }; } 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 ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || { echo "$as_me: error: Working directory cannot be determined" >&2 { (exit 1); exit 1; }; } test "X$ac_ls_di" = "X$ac_pwd_ls_di" || { echo "$as_me: error: pwd does not report name of working directory" >&2 { (exit 1); exit 1; }; } # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$0" || $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 test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2 { (exit 1); exit 1; }; } fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || { echo "$as_me: error: $ac_msg" >&2 { (exit 1); exit 1; }; } pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures 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 \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/PACKAGE] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF Program names: --program-prefix=PREFIX prepend PREFIX to installed program names --program-suffix=SUFFIX append SUFFIX to installed program names --program-transform-name=PROGRAM run sed PROGRAM on installed program names 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-maintainer-mode enable make rules and dependencies not useful (and sometimes confusing) to the casual installer --disable-dependency-tracking speeds up one-time build --enable-dependency-tracking do not reject slow dependency extractors --enable-static[=PKGS] build static libraries [default=no] --enable-shared[=PKGS] build shared libraries [default=yes] --enable-fast-install[=PKGS] optimize for fast installation [default=yes] --disable-libtool-lock avoid locking (might break parallel builds) --enable-ltdl-install install libltdl --disable-nls do not use Native Language Support --disable-rpath do not hardcode runtime library paths --disable-largefile omit support for large files --disable-dynamic-load disable dynamic loader option --enable-cckd-bzip2 enable bzip2 compression for emulated dasd --enable-het-bzip2 enable bzip2 compression for emulated tapes --enable-debug enable debugging (TRACE/VERIFY/ASSERT macros) --enable-optimization=yes|no|FLAGS enable automatic optimization, or specify flags --disable-configsymbols disable symbolic substitutions in configuration file --disable-enhanced-configsymbols disable enhanced-mode symbolic substitutions in configuration file --disable-enhanced-configincludes disable enhanced-mode 'include' file support in configuration file --disable-automatic-operator disable Hercules Automatic Operator feature --disable-external-gui disable external Windows GUI interface --disable-fthreads disable use of fish threads instead of posix threads --enable-fishhang debug correct lock handling (fthreads only) --enable-multi-cpu=yes|no|NUMBER enable/disable multi-cpu support (1-64, default 8) --disable-capabilities disable fine grained privileges --enable-custom=STRING provide a custom description for this build --enable-setuid-hercifc=yes|no|GROUPNAME install hercifc as setuid root, and allow execution by users in group GROUPNAME --enable-getoptwrapper force use of the getopt wrapper kludge Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-gnu-ld assume the C compiler uses GNU ld [default=no] --with-pic try to use only PIC/non-PIC objects [default=use both] --with-tags[=TAGS] include additional configurations [automatic] --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-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 LIBS libraries to pass to the linker, e.g. -l CPPFLAGS C/C++/Objective C preprocessor flags, e.g. -I if you have headers in a nonstandard directory CPP C preprocessor CXX C++ compiler command CXXFLAGS C++ compiler flags CXXCPP C++ preprocessor F77 Fortran 77 compiler command FFLAGS Fortran 77 compiler flags Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for guested configure. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF configure generated by GNU Autoconf 2.61 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by $as_me, which was generated by GNU Autoconf 2.61. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. echo "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`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_arg'" ;; 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: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo cat <<\_ASBOX ## ---------------- ## ## Cache variables. ## ## ---------------- ## _ASBOX echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5 echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( *) $as_unset $ac_var ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo cat <<\_ASBOX ## ----------------- ## ## Output variables. ## ## ----------------- ## _ASBOX echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then cat <<\_ASBOX ## ------------------- ## ## File substitutions. ## ## ------------------- ## _ASBOX echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then cat <<\_ASBOX ## ----------- ## ## confdefs.h. ## ## ----------- ## _ASBOX echo cat confdefs.h echo fi test "$ac_signal" != 0 && echo "$as_me: caught signal $ac_signal" echo "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h # 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 -n "$CONFIG_SITE"; then set x "$CONFIG_SITE" elif test "x$prefix" != xNONE; then set x "$prefix/share/config.site" "$prefix/etc/config.site" else set x "$ac_default_prefix/share/config.site" \ "$ac_default_prefix/etc/config.site" fi shift for ac_site_file 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 $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { 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, version, bugreport email, etc) # (the version of this configure.ac) ac_aux_dir= for ac_dir in autoconf "$srcdir"/autoconf; 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 autoconf \"$srcdir\"/autoconf" >&5 echo "$as_me: error: cannot find install-sh or install.sh in autoconf \"$srcdir\"/autoconf" >&2;} { (exit 1); exit 1; }; } fi # These three variables are undocumented and unsupported, # and are intended to be withdrawn in a future Autoconf release. # They can cause serious problems if a builder's source tree is in a directory # whose full name contains unusual characters. ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. # (directory containing auxillary build tools) am__api_version="1.9" # 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 { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$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 IFS=$as_save_IFS fi if test "${ac_cv_path_install+set}" = set; then INSTALL=$ac_cv_path_install else # As a last resort, use the slow shell script. Don't cache a # value for INSTALL within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. INSTALL=$ac_install_sh fi fi { 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' { echo "$as_me:$LINENO: checking whether build environment is sane" >&5 echo $ECHO_N "checking whether build environment is sane... $ECHO_C" >&6; } # Just in case sleep 1 echo timestamp > conftest.file # Do `set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null` if test "$*" = "X"; then # -L didn't work. set X `ls -t $srcdir/configure conftest.file` fi rm -f conftest.file if test "$*" != "X $srcdir/configure conftest.file" \ && test "$*" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". { { echo "$as_me:$LINENO: error: ls -t appears to fail. Make sure there is not a broken alias in your environment" >&5 echo "$as_me: error: ls -t appears to fail. Make sure there is not a broken alias in your environment" >&2;} { (exit 1); exit 1; }; } fi test "$2" = conftest.file ) then # Ok. : else { { echo "$as_me:$LINENO: error: newly created file is older than distributed files! Check your system clock" >&5 echo "$as_me: error: newly created file is older than distributed files! Check your system clock" >&2;} { (exit 1); exit 1; }; } fi { echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6; } test "$program_prefix" != NONE && program_transform_name="s&^&$program_prefix&;$program_transform_name" # Use a double $ so make ignores it. test "$program_suffix" != NONE && program_transform_name="s&\$&$program_suffix&;$program_transform_name" # Double any \ or $. echo might interpret backslashes. # By default was `s,x,x', remove it if useless. cat <<\_ACEOF >conftest.sed s/[\\$]/&&/g;s/;s,x,x,$// _ACEOF program_transform_name=`echo $program_transform_name | sed -f conftest.sed` rm -f conftest.sed # expand $ac_aux_dir to an absolute path am_aux_dir=`cd $ac_aux_dir && pwd` test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing" # Use eval to expand $SHELL if eval "$MISSING --run true"; then am_missing_run="$MISSING --run " else am_missing_run= { echo "$as_me:$LINENO: WARNING: \`missing' script is too old or missing" >&5 echo "$as_me: WARNING: \`missing' script is too old or missing" >&2;} fi if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then # We used to keeping the `.' as first argument, in order to # allow $(mkdir_p) to be used without argument. As in # $(mkdir_p) $(somedir) # where $(somedir) is conditionally defined. However this is wrong # for two reasons: # 1. if the package is installed by a user who cannot write `.' # make install will fail, # 2. the above comment should most certainly read # $(mkdir_p) $(DESTDIR)$(somedir) # so it does not work when $(somedir) is undefined and # $(DESTDIR) is not. # To support the latter case, we have to write # test -z "$(somedir)" || $(mkdir_p) $(DESTDIR)$(somedir), # so the `.' trick is pointless. mkdir_p='mkdir -p --' else # On NextStep and OpenStep, the `mkdir' command does not # recognize any option. It will interpret all options as # directories to create, and then abort because `.' already # exists. for d in ./-p ./--version; do test -d $d && rmdir $d done # $(mkinstalldirs) is defined by Automake if mkinstalldirs exists. if test -f "$ac_aux_dir/mkinstalldirs"; then mkdir_p='$(mkinstalldirs)' else mkdir_p='$(install_sh) -d' fi fi for ac_prog in gawk mawk nawk awk do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_AWK+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$AWK"; then ac_cv_prog_AWK="$AWK" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_AWK="$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AWK=$ac_cv_prog_AWK if test -n "$AWK"; then { echo "$as_me:$LINENO: result: $AWK" >&5 echo "${ECHO_T}$AWK" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi test -n "$AWK" && break done { echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5 echo $ECHO_N "checking whether ${MAKE-make} sets \$(MAKE)... $ECHO_C" >&6; } set x ${MAKE-make}; ac_make=`echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` if { as_var=ac_cv_prog_make_${ac_make}_set; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.make <<\_ACEOF SHELL = /bin/sh all: @echo '@@@%%%=$(MAKE)=@@@%%%' _ACEOF # GNU make sometimes prints "make[1]: Entering...", which would confuse us. case `${MAKE-make} -f conftest.make 2>/dev/null` in *@@@%%%=?*=@@@%%%*) eval ac_cv_prog_make_${ac_make}_set=yes;; *) eval ac_cv_prog_make_${ac_make}_set=no;; esac rm -f conftest.make fi if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then { 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 rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null # test to see if srcdir already configured if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then { { echo "$as_me:$LINENO: error: source directory already configured; run \"make distclean\" there first" >&5 echo "$as_me: error: source directory already configured; run \"make distclean\" there first" >&2;} { (exit 1); exit 1; }; } fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi # Define the identity of the package. PACKAGE=hercules VERSION=3.07 cat >>confdefs.h <<_ACEOF #define PACKAGE "$PACKAGE" _ACEOF cat >>confdefs.h <<_ACEOF #define VERSION "$VERSION" _ACEOF # Some tools Automake needs. ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} install_sh=${install_sh-"$am_aux_dir/install-sh"} # Installed binaries are usually stripped using `strip' when the user # run `make install-strip'. However `strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the `STRIP' environment variable to overrule this program. if test "$cross_compiling" != no; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_STRIP+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then { echo "$as_me:$LINENO: result: $STRIP" >&5 echo "${ECHO_T}$STRIP" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi fi if test -z "$ac_cv_prog_STRIP"; then ac_ct_STRIP=$STRIP # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 { 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_STRIP+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_STRIP"; then ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_STRIP="strip" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP if test -n "$ac_ct_STRIP"; then { echo "$as_me:$LINENO: result: $ac_ct_STRIP" >&5 echo "${ECHO_T}$ac_ct_STRIP" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi if test "x$ac_ct_STRIP" = x; then STRIP=":" else case $cross_compiling:$ac_tool_warned in yes:) { echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools whose name does not start with the host triplet. If you think this configuration is useful to you, please write to autoconf@gnu.org." >&5 echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools whose name does not start with the host triplet. If you think this configuration is useful to you, please write to autoconf@gnu.org." >&2;} ac_tool_warned=yes ;; esac STRIP=$ac_ct_STRIP fi else STRIP="$ac_cv_prog_STRIP" fi fi INSTALL_STRIP_PROGRAM="\${SHELL} \$(install_sh) -c -s" # We need awk for the "check" target. The system "awk" is bad on # some platforms. # Always define AMTAR for backward compatibility. AMTAR=${AMTAR-"${am_missing_run}tar"} am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -' # (the version of our software package) ac_config_headers="$ac_config_headers config.h" # (the file the resulting configure script will produce) { echo "$as_me:$LINENO: checking whether to enable maintainer-specific portions of Makefiles" >&5 echo $ECHO_N "checking whether to enable maintainer-specific portions of Makefiles... $ECHO_C" >&6; } # Check whether --enable-maintainer-mode was given. if test "${enable_maintainer_mode+set}" = set; then enableval=$enable_maintainer_mode; USE_MAINTAINER_MODE=$enableval else USE_MAINTAINER_MODE=no fi { echo "$as_me:$LINENO: result: $USE_MAINTAINER_MODE" >&5 echo "${ECHO_T}$USE_MAINTAINER_MODE" >&6; } if test $USE_MAINTAINER_MODE = yes; then MAINTAINER_MODE_TRUE= MAINTAINER_MODE_FALSE='#' else MAINTAINER_MODE_TRUE='#' MAINTAINER_MODE_FALSE= fi MAINT=$MAINTAINER_MODE_TRUE # Make sure we can run config.sub. $SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || { { echo "$as_me:$LINENO: error: cannot run $SHELL $ac_aux_dir/config.sub" >&5 echo "$as_me: error: cannot run $SHELL $ac_aux_dir/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_build_alias=$build_alias test "x$ac_build_alias" = x && ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` test "x$ac_build_alias" = x && { { 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=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $ac_build_alias failed" >&5 echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $ac_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; } case $ac_cv_build in *-*-*) ;; *) { { echo "$as_me:$LINENO: error: invalid value of canonical build" >&5 echo "$as_me: error: invalid value of canonical build" >&2;} { (exit 1); exit 1; }; };; esac build=$ac_cv_build ac_save_IFS=$IFS; IFS='-' set x $ac_cv_build shift build_cpu=$1 build_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: build_os=$* IFS=$ac_save_IFS case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac { 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 if test "x$host_alias" = x; then ac_cv_host=$ac_cv_build else ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&5 echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&2;} { (exit 1); exit 1; }; } fi fi { echo "$as_me:$LINENO: result: $ac_cv_host" >&5 echo "${ECHO_T}$ac_cv_host" >&6; } case $ac_cv_host in *-*-*) ;; *) { { echo "$as_me:$LINENO: error: invalid value of canonical host" >&5 echo "$as_me: error: invalid value of canonical host" >&2;} { (exit 1); exit 1; }; };; esac host=$ac_cv_host ac_save_IFS=$IFS; IFS='-' set x $ac_cv_host shift host_cpu=$1 host_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: host_os=$* IFS=$ac_save_IFS case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac # (sets $host_cpu, $host_vendor, and $host_os) ############################################################################### # Programs section... ############################################################################### #HC_PROG_CC() # ((( DEPRECATED ))) # # CFLAGS *MUST* BE SET 1ST - BEFORE CALL AC_PROG_CC OTHERWISE AUTOCONF TRIES TO IMPOSE # ITS OWN CHOICES... # FIXME : # Unfortunatelly, these are gcc flags.. so going to have # to find something better... # CFLAGS="$CFLAGS -W -Wall" 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 IFS=$as_save_IFS 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 IFS=$as_save_IFS 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 if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools whose name does not start with the host triplet. If you think this configuration is useful to you, please write to autoconf@gnu.org." >&5 echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools whose name does not start with the host triplet. If you think this configuration is useful to you, please write to autoconf@gnu.org." >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 IFS=$as_save_IFS 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 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { 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.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 IFS=$as_save_IFS 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.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 IFS=$as_save_IFS 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 if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools whose name does not start with the host triplet. If you think this configuration is useful to you, please write to autoconf@gnu.org." >&5 echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools whose name does not start with the host triplet. If you think this configuration is useful to you, please write to autoconf@gnu.org." >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi 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` { (ac_try="$ac_compiler --version >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compiler --version >&5") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { (ac_try="$ac_compiler -v >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compiler -v >&5") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { (ac_try="$ac_compiler -V >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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[^ ]*//'` # # List of possible output files, starting from the most likely. # The algorithm is not robust to junk in `.', hence go to wildcards (a.*) # only as a last resort. b.out is created by i960 compilers. ac_files='a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out' # # The IRIX 6 linker writes into existing files which may not be # executable, retaining their permissions. Remove them first so a # subsequent execution test works. ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { (ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link_default") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an `-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else ac_file='' fi { echo "$as_me:$LINENO: result: $ac_file" >&5 echo "${ECHO_T}$ac_file" >&6; } if test -z "$ac_file"; then 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 # Check that 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' { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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 that 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 { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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 | *.map | *.inf | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` 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 { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf ) ;; *) 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 { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core 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 { 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 ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" 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 { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_prog_cc_g=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 CFLAGS="" 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 { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" 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 { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_prog_cc_g=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { 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 ISO C89" >&5 echo $ECHO_N "checking for $CC option to accept ISO C89... $ECHO_C" >&6; } if test "${ac_cv_prog_cc_c89+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_prog_cc_c89=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 -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_prog_cc_c89=$ac_arg else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { echo "$as_me:$LINENO: result: none needed" >&5 echo "${ECHO_T}none needed" >&6; } ;; xno) { echo "$as_me:$LINENO: result: unsupported" >&5 echo "${ECHO_T}unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { echo "$as_me:$LINENO: result: $ac_cv_prog_cc_c89" >&5 echo "${ECHO_T}$ac_cv_prog_cc_c89" >&6; } ;; esac ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu DEPDIR="${am__leading_dot}deps" ac_config_commands="$ac_config_commands depfiles" am_make=${MAKE-make} cat > confinc << 'END' am__doit: @echo done .PHONY: am__doit END # If we don't find an include directive, just comment out the code. { echo "$as_me:$LINENO: checking for style of include used by $am_make" >&5 echo $ECHO_N "checking for style of include used by $am_make... $ECHO_C" >&6; } am__include="#" am__quote= _am_result=none # First try GNU make style include. echo "include confinc" > confmf # We grep out `Entering directory' and `Leaving directory' # messages which can occur if `w' ends up in MAKEFLAGS. # In particular we don't look at `^make:' because GNU make might # be invoked under some other name (usually "gmake"), in which # case it prints its new name instead of `make'. if test "`$am_make -s -f confmf 2> /dev/null | grep -v 'ing directory'`" = "done"; then am__include=include am__quote= _am_result=GNU fi # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then am__include=.include am__quote="\"" _am_result=BSD fi fi { echo "$as_me:$LINENO: result: $_am_result" >&5 echo "${ECHO_T}$_am_result" >&6; } rm -f confinc confmf # Check whether --enable-dependency-tracking was given. if test "${enable_dependency_tracking+set}" = set; then enableval=$enable_dependency_tracking; fi if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' fi if test "x$enable_dependency_tracking" != xno; then AMDEP_TRUE= AMDEP_FALSE='#' else AMDEP_TRUE='#' AMDEP_FALSE= fi depcc="$CC" am_compiler_list= { echo "$as_me:$LINENO: checking dependency style of $depcc" >&5 echo $ECHO_N "checking dependency style of $depcc... $ECHO_C" >&6; } if test "${am_cv_CC_dependencies_compiler_type+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named `D' -- because `-MD' means `put the output # in D'. mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_CC_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with # Solaris 8's {/usr,}/bin/sh. touch sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf case $depmode in nosideeffect) # after this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; none) break ;; esac # We check with `-c' and `-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle `-M -o', and we need to detect this. if depmode=$depmode \ source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_CC_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_CC_dependencies_compiler_type=none fi fi { echo "$as_me:$LINENO: result: $am_cv_CC_dependencies_compiler_type" >&5 echo "${ECHO_T}$am_cv_CC_dependencies_compiler_type" >&6; } CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then am__fastdepCC_TRUE= am__fastdepCC_FALSE='#' else am__fastdepCC_TRUE='#' am__fastdepCC_FALSE= fi # (back to using this again) # ----------------------------------------------------------------------------- # PROGRAMMING NOTE: The below 'AC_SUBST' macro causes AC_OUTPUT to replace # all instances of "@xxxxxx@" in input files with the value that the shell # variable "xxxxxx" has when AC_OUTPUT is called. Thus, the variable name # used ("modexecdir" in our case) *is* significant and cannot be changed # unless you change the "@modexecdir@" strings in all of the input files. # ----------------------------------------------------------------------------- modexecdir=${libdir}/${PACKAGE} # ----------------------------------------------------------------------------- # # AC_LIBTOOL_DLOPEN # # Enable checking for dlopen support. This macro should be used if the # package makes use of the '-dlopen' and '-dlpreopen' flags, otherwise # libtool will assume that the system does not support dlopening. The # macro must be called before AC_PROG_LIBTOOL. # # ----------------------------------------------------------------------------- # (we need libtool's dlopen support) # ----------------------------------------------------------------------------- # # AC_LIBTOOL_WIN32_DLL # # This macro should be used if the package has been ported to build # clean dlls on win32 platforms. Usually this means that any library # data items are exported with __declspec(dllexport) and imported with # __declspec(dllimport). If this macro is not used, libtool will assume # that the package libraries are not dll clean and will build only static # libraries on win32 hosts. # # This macro must be called before AC_PROG_LIBTOOL, and provision must # be made to pass '-no-undefined' to libtool in link mode from the package # Makefile. Naturally, if you pass '-no-undefined', you must ensure that # all the library symbols really are defined at link time! # # ----------------------------------------------------------------------------- # (we need Win32 support in libtool) # ----------------------------------------------------------------------------- # See: 'AC_PROG_LIBTOOL' below. # ----------------------------------------------------------------------------- # Check whether --enable-static was given. if test "${enable_static+set}" = set; then enableval=$enable_static; p=${PACKAGE-default} case $enableval in yes) enable_static=yes ;; no) enable_static=no ;; *) enable_static=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_static=yes fi done IFS="$lt_save_ifs" ;; esac else enable_static=no fi # (forces libtool to build shared # libraries instead of static ones) # ----------------------------------------------------------------------------- # AC_PROG_LIBTOOL # # Add support for the '--enable-shared' and '--disable-shared' # configure flags. By default, this macro turns on shared libraries # if they are available, and also enables static libraries if they # don't conflict with the shared libraries. You can modify these # defaults by calling either the AC_DISABLE_SHARED or AC_DISABLE_STATIC # macros. # # Hercules REQUIRES shared libraries (i.e. DLLs), so we do indeed use # the AC_DISABLE_STATIC macro above. # # ----------------------------------------------------------------------------- # Check whether --enable-shared was given. if test "${enable_shared+set}" = set; then enableval=$enable_shared; p=${PACKAGE-default} case $enableval in yes) enable_shared=yes ;; no) enable_shared=no ;; *) enable_shared=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_shared=yes fi done IFS="$lt_save_ifs" ;; esac else enable_shared=yes fi # Check whether --enable-fast-install was given. if test "${enable_fast_install+set}" = set; then enableval=$enable_fast_install; p=${PACKAGE-default} case $enableval in yes) enable_fast_install=yes ;; no) enable_fast_install=no ;; *) enable_fast_install=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_fast_install=yes fi done IFS="$lt_save_ifs" ;; esac else enable_fast_install=yes fi { echo "$as_me:$LINENO: checking for a sed that does not truncate output" >&5 echo $ECHO_N "checking for a sed that does not truncate output... $ECHO_C" >&6; } if test "${lt_cv_path_SED+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else # Loop through the user's path and test for sed and gsed. # Then use that list of sed's as ones to test for truncation. as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for lt_ac_prog in sed gsed; do for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" fi done done done lt_ac_max=0 lt_ac_count=0 # Add /usr/xpg4/bin/sed as it is typically found on Solaris # along with /bin/sed that truncates output. for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do test ! -f $lt_ac_sed && break cat /dev/null > conftest.in lt_ac_count=0 echo $ECHO_N "0123456789$ECHO_C" >conftest.in # Check for GNU sed and select it if it is found. if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then lt_cv_path_SED=$lt_ac_sed break fi while true; do cat conftest.in conftest.in >conftest.tmp mv conftest.tmp conftest.in cp conftest.in conftest.nl echo >>conftest.nl $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break cmp -s conftest.out conftest.nl || break # 10000 chars as input seems more than enough test $lt_ac_count -gt 10 && break lt_ac_count=`expr $lt_ac_count + 1` if test $lt_ac_count -gt $lt_ac_max; then lt_ac_max=$lt_ac_count lt_cv_path_SED=$lt_ac_sed fi done done SED=$lt_cv_path_SED fi { echo "$as_me:$LINENO: result: $SED" >&5 echo "${ECHO_T}$SED" >&6; } { echo "$as_me:$LINENO: checking for grep that handles long lines and -e" >&5 echo $ECHO_N "checking for grep that handles long lines and -e... $ECHO_C" >&6; } if test "${ac_cv_path_GREP+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else # Extract the first word of "grep ggrep" to use in msg output if test -z "$GREP"; then set dummy grep ggrep; ac_prog_name=$2 if test "${ac_cv_path_GREP+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_path_GREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in grep ggrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue # Check for GNU ac_path_GREP and select it if it is found. # Check for GNU $ac_path_GREP case `"$ac_path_GREP" --version 2>&1` in *GNU*) ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; *) ac_count=0 echo $ECHO_N "0123456789$ECHO_C" >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" echo 'GREP' >> "conftest.nl" "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break ac_count=`expr $ac_count + 1` if test $ac_count -gt ${ac_path_GREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_GREP_found && break 3 done done done IFS=$as_save_IFS fi GREP="$ac_cv_path_GREP" if test -z "$GREP"; then { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5 echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;} { (exit 1); exit 1; }; } fi else ac_cv_path_GREP=$GREP fi fi { echo "$as_me:$LINENO: result: $ac_cv_path_GREP" >&5 echo "${ECHO_T}$ac_cv_path_GREP" >&6; } GREP="$ac_cv_path_GREP" { echo "$as_me:$LINENO: checking for egrep" >&5 echo $ECHO_N "checking for egrep... $ECHO_C" >&6; } if test "${ac_cv_path_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_path_EGREP="$GREP -E" else # Extract the first word of "egrep" to use in msg output if test -z "$EGREP"; then set dummy egrep; ac_prog_name=$2 if test "${ac_cv_path_EGREP+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_path_EGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in egrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue # Check for GNU ac_path_EGREP and select it if it is found. # Check for GNU $ac_path_EGREP case `"$ac_path_EGREP" --version 2>&1` in *GNU*) ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; *) ac_count=0 echo $ECHO_N "0123456789$ECHO_C" >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" echo 'EGREP' >> "conftest.nl" "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break ac_count=`expr $ac_count + 1` if test $ac_count -gt ${ac_path_EGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_EGREP_found && break 3 done done done IFS=$as_save_IFS fi EGREP="$ac_cv_path_EGREP" if test -z "$EGREP"; then { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5 echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;} { (exit 1); exit 1; }; } fi else ac_cv_path_EGREP=$EGREP fi fi fi { echo "$as_me:$LINENO: result: $ac_cv_path_EGREP" >&5 echo "${ECHO_T}$ac_cv_path_EGREP" >&6; } EGREP="$ac_cv_path_EGREP" # Check whether --with-gnu-ld was given. if test "${with_gnu_ld+set}" = set; then withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes else with_gnu_ld=no fi 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 $CC" >&5 echo $ECHO_N "checking for ld used by $CC... $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. [\\/]* | ?:[\\/]*) re_direlt='/[^/][^/]*/\.\./' # Canonicalize the pathname of ld ac_prog=`echo $ac_prog| $SED 's%\\\\%/%g'` while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do ac_prog=`echo $ac_prog| $SED "s%$re_direlt%/%"` done test -z "$LD" && LD="$ac_prog" ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test "$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 "${lt_cv_path_LD+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -z "$LD"; then lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD="$ac_dir/$ac_prog" # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some GNU ld's only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &5 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 "${lt_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}$lt_cv_prog_gnu_ld" >&6; } with_gnu_ld=$lt_cv_prog_gnu_ld { echo "$as_me:$LINENO: checking for $LD option to reload object files" >&5 echo $ECHO_N "checking for $LD option to reload object files... $ECHO_C" >&6; } if test "${lt_cv_ld_reload_flag+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else lt_cv_ld_reload_flag='-r' fi { echo "$as_me:$LINENO: result: $lt_cv_ld_reload_flag" >&5 echo "${ECHO_T}$lt_cv_ld_reload_flag" >&6; } reload_flag=$lt_cv_ld_reload_flag case $reload_flag in "" | " "*) ;; *) reload_flag=" $reload_flag" ;; esac reload_cmds='$LD$reload_flag -o $output$reload_objs' { echo "$as_me:$LINENO: checking for BSD-compatible nm" >&5 echo $ECHO_N "checking for BSD-compatible nm... $ECHO_C" >&6; } if test "${lt_cv_path_NM+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$NM"; then # Let the user override the test. lt_cv_path_NM="$NM" else lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH /usr/ccs/bin /usr/ucb /bin; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. tmp_nm="$ac_dir/${ac_tool_prefix}nm" if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then # Check to see if the nm accepts a BSD-compat flag. # Adding the `sed 1q' prevents false positives on HP-UX, which says: # nm: unknown option "B" ignored # Tru64's nm complains that /dev/null is an invalid object file case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in */dev/null* | *'Invalid file or object type'*) lt_cv_path_NM="$tmp_nm -B" break ;; *) case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in */dev/null*) lt_cv_path_NM="$tmp_nm -p" break ;; *) lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but continue # so that we can try to find one that supports BSD flags ;; esac esac fi done IFS="$lt_save_ifs" test -z "$lt_cv_path_NM" && lt_cv_path_NM=nm fi fi { echo "$as_me:$LINENO: result: $lt_cv_path_NM" >&5 echo "${ECHO_T}$lt_cv_path_NM" >&6; } NM="$lt_cv_path_NM" { echo "$as_me:$LINENO: checking whether ln -s works" >&5 echo $ECHO_N "checking whether ln -s works... $ECHO_C" >&6; } LN_S=$as_ln_s if test "$LN_S" = "ln -s"; then { echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6; } else { echo "$as_me:$LINENO: result: no, using $LN_S" >&5 echo "${ECHO_T}no, using $LN_S" >&6; } fi { echo "$as_me:$LINENO: checking how to recognise dependent libraries" >&5 echo $ECHO_N "checking how to recognise dependent libraries... $ECHO_C" >&6; } if test "${lt_cv_deplibs_check_method+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else lt_cv_file_magic_cmd='$MAGIC_CMD' lt_cv_file_magic_test_file= lt_cv_deplibs_check_method='unknown' # Need to set the preceding variable on all platforms that support # interlibrary dependencies. # 'none' -- dependencies not supported. # `unknown' -- same as none, but documents that we really don't know. # 'pass_all' -- all dependencies passed with no checks. # 'test_compile' -- check by making test program. # 'file_magic [[regex]]' -- check by looking for files in library path # which responds to the $file_magic_cmd with a given extended regex. # If you have `file' or equivalent on your system and you're not sure # whether `pass_all' will *always* work, you probably want this one. case $host_os in aix4* | aix5*) lt_cv_deplibs_check_method=pass_all ;; beos*) lt_cv_deplibs_check_method=pass_all ;; bsdi4*) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' lt_cv_file_magic_cmd='/usr/bin/file -L' lt_cv_file_magic_test_file=/shlib/libc.so ;; cygwin* | mingw* | pw32*) # win32_libid is a shell function defined in ltmain.sh lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='win32_libid' ;; darwin* | rhapsody*) # this will be overwritten by pass_all, but leave it in just in case lt_cv_deplibs_check_method='file_magic Mach-O dynamically linked shared library' lt_cv_file_magic_cmd='/usr/bin/file -L' case "$host_os" in rhapsody* | darwin1.[012]) lt_cv_file_magic_test_file=`/System/Library/Frameworks/System.framework/System` ;; *) # Darwin 1.3 on lt_cv_file_magic_test_file='/usr/lib/libSystem.dylib' ;; esac lt_cv_deplibs_check_method=pass_all ;; freebsd* | kfreebsd*-gnu) if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then case $host_cpu in i*86 ) # Not sure whether the presence of OpenBSD here was a mistake. # Let's accept both of them until this is cleared up. lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD)/i[3-9]86 (compact )?demand paged shared library' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` ;; esac else lt_cv_deplibs_check_method=pass_all fi ;; gnu*) lt_cv_deplibs_check_method=pass_all ;; hpux10.20* | hpux11*) lt_cv_file_magic_cmd=/usr/bin/file case "$host_cpu" in ia64*) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64' lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so ;; hppa*64*) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]' lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl ;; *) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9].[0-9]) shared library' lt_cv_file_magic_test_file=/usr/lib/libc.sl ;; esac ;; irix5* | irix6* | nonstopux*) case $host_os in irix5* | nonstopux*) # this will be overridden with pass_all, but let us keep it just in case lt_cv_deplibs_check_method="file_magic ELF 32-bit MSB dynamic lib MIPS - version 1" ;; *) case $LD in *-32|*"-32 ") libmagic=32-bit;; *-n32|*"-n32 ") libmagic=N32;; *-64|*"-64 ") libmagic=64-bit;; *) libmagic=never-match;; esac # this will be overridden with pass_all, but let us keep it just in case lt_cv_deplibs_check_method="file_magic ELF ${libmagic} MSB mips-[1234] dynamic lib MIPS - version 1" ;; esac lt_cv_file_magic_test_file=`echo /lib${libsuff}/libc.so*` lt_cv_deplibs_check_method=pass_all ;; # This must be Linux ELF. linux*) case $host_cpu in alpha* | hppa* | i*86 | ia64* | m68* | mips* | powerpc* | sparc* | s390* | sh*) lt_cv_deplibs_check_method=pass_all ;; *) # glibc up to 2.1.1 does not perform some relocations on ARM lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' ;; esac lt_cv_file_magic_test_file=`echo /lib/libc.so* /lib/libc-*.so` ;; netbsd*) if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$' fi ;; newos6*) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=/usr/lib/libnls.so ;; nto-qnx*) lt_cv_deplibs_check_method=unknown ;; openbsd*) lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB shared object' else lt_cv_deplibs_check_method='file_magic OpenBSD.* shared library' fi ;; osf3* | osf4* | osf5*) # this will be overridden with pass_all, but let us keep it just in case lt_cv_deplibs_check_method='file_magic COFF format alpha shared library' lt_cv_file_magic_test_file=/shlib/libc.so lt_cv_deplibs_check_method=pass_all ;; sco3.2v5*) lt_cv_deplibs_check_method=pass_all ;; solaris*) lt_cv_deplibs_check_method=pass_all lt_cv_file_magic_test_file=/lib/libc.so ;; sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) case $host_vendor in motorola) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` ;; ncr) lt_cv_deplibs_check_method=pass_all ;; sequent) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' ;; sni) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib" lt_cv_file_magic_test_file=/lib/libc.so ;; siemens) lt_cv_deplibs_check_method=pass_all ;; esac ;; sysv5OpenUNIX8* | sysv5UnixWare7* | sysv5uw[78]* | unixware7* | sysv4*uw2*) lt_cv_deplibs_check_method=pass_all ;; esac fi { echo "$as_me:$LINENO: result: $lt_cv_deplibs_check_method" >&5 echo "${ECHO_T}$lt_cv_deplibs_check_method" >&6; } file_magic_cmd=$lt_cv_file_magic_cmd deplibs_check_method=$lt_cv_deplibs_check_method test -z "$deplibs_check_method" && deplibs_check_method=unknown # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # Allow CC to be a program name with arguments. compiler=$CC # Check whether --enable-libtool-lock was given. if test "${enable_libtool_lock+set}" = set; then enableval=$enable_libtool_lock; fi test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes # Some flags need to be propagated to the compiler or linker for good # libtool support. case $host in ia64-*-hpux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext 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 case `/usr/bin/file conftest.$ac_objext` in *ELF-32*) HPUX_IA64_MODE="32" ;; *ELF-64*) HPUX_IA64_MODE="64" ;; esac fi rm -rf conftest* ;; *-*-irix6*) # Find out which ABI we are using. echo '#line 4470 "configure"' > conftest.$ac_ext 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 if test "$lt_cv_prog_gnu_ld" = yes; then case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -melf32bsmip" ;; *N32*) LD="${LD-ld} -melf32bmipn32" ;; *64-bit*) LD="${LD-ld} -melf64bmip" ;; esac else case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -32" ;; *N32*) LD="${LD-ld} -n32" ;; *64-bit*) LD="${LD-ld} -64" ;; esac fi fi rm -rf conftest* ;; x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext 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 case "`/usr/bin/file conftest.o`" in *32-bit*) case $host in x86_64-*linux*) LD="${LD-ld} -m elf_i386" ;; ppc64-*linux*|powerpc64-*linux*) LD="${LD-ld} -m elf32ppclinux" ;; s390x-*linux*) LD="${LD-ld} -m elf_s390" ;; sparc64-*linux*) LD="${LD-ld} -m elf32_sparc" ;; esac ;; *64-bit*) case $host in x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; ppc*-*linux*|powerpc*-*linux*) LD="${LD-ld} -m elf64ppc" ;; s390*-*linux*) LD="${LD-ld} -m elf64_s390" ;; sparc*-*linux*) LD="${LD-ld} -m elf64_sparc" ;; esac ;; esac fi rm -rf conftest* ;; *-*-sco3.2v5*) # On SCO OpenServer 5, we need -belf to get full-featured binaries. SAVE_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -belf" { echo "$as_me:$LINENO: checking whether the C compiler needs -belf" >&5 echo $ECHO_N "checking whether the C compiler needs -belf... $ECHO_C" >&6; } if test "${lt_cv_cc_needs_belf+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu cat >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 { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then lt_cv_cc_needs_belf=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 lt_cv_cc_needs_belf=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu fi { echo "$as_me:$LINENO: result: $lt_cv_cc_needs_belf" >&5 echo "${ECHO_T}$lt_cv_cc_needs_belf" >&6; } if test x"$lt_cv_cc_needs_belf" != x"yes"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf CFLAGS="$SAVE_CFLAGS" fi ;; *-*-cygwin* | *-*-mingw* | *-*-pw32*) if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args. set dummy ${ac_tool_prefix}dlltool; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_DLLTOOL+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$DLLTOOL"; then ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DLLTOOL=$ac_cv_prog_DLLTOOL if test -n "$DLLTOOL"; then { echo "$as_me:$LINENO: result: $DLLTOOL" >&5 echo "${ECHO_T}$DLLTOOL" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi fi if test -z "$ac_cv_prog_DLLTOOL"; then ac_ct_DLLTOOL=$DLLTOOL # Extract the first word of "dlltool", so it can be a program name with args. set dummy dlltool; ac_word=$2 { 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_DLLTOOL+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_DLLTOOL"; then ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_DLLTOOL="dlltool" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL if test -n "$ac_ct_DLLTOOL"; then { echo "$as_me:$LINENO: result: $ac_ct_DLLTOOL" >&5 echo "${ECHO_T}$ac_ct_DLLTOOL" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi if test "x$ac_ct_DLLTOOL" = x; then DLLTOOL="false" else case $cross_compiling:$ac_tool_warned in yes:) { echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools whose name does not start with the host triplet. If you think this configuration is useful to you, please write to autoconf@gnu.org." >&5 echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools whose name does not start with the host triplet. If you think this configuration is useful to you, please write to autoconf@gnu.org." >&2;} ac_tool_warned=yes ;; esac DLLTOOL=$ac_ct_DLLTOOL fi else DLLTOOL="$ac_cv_prog_DLLTOOL" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}as", so it can be a program name with args. set dummy ${ac_tool_prefix}as; 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_AS+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$AS"; then ac_cv_prog_AS="$AS" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_AS="${ac_tool_prefix}as" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AS=$ac_cv_prog_AS if test -n "$AS"; then { echo "$as_me:$LINENO: result: $AS" >&5 echo "${ECHO_T}$AS" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi fi if test -z "$ac_cv_prog_AS"; then ac_ct_AS=$AS # Extract the first word of "as", so it can be a program name with args. set dummy as; 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_AS+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_AS"; then ac_cv_prog_ac_ct_AS="$ac_ct_AS" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_AS="as" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_AS=$ac_cv_prog_ac_ct_AS if test -n "$ac_ct_AS"; then { echo "$as_me:$LINENO: result: $ac_ct_AS" >&5 echo "${ECHO_T}$ac_ct_AS" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi if test "x$ac_ct_AS" = x; then AS="false" else case $cross_compiling:$ac_tool_warned in yes:) { echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools whose name does not start with the host triplet. If you think this configuration is useful to you, please write to autoconf@gnu.org." >&5 echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools whose name does not start with the host triplet. If you think this configuration is useful to you, please write to autoconf@gnu.org." >&2;} ac_tool_warned=yes ;; esac AS=$ac_ct_AS fi else AS="$ac_cv_prog_AS" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. set dummy ${ac_tool_prefix}objdump; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_OBJDUMP+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$OBJDUMP"; then ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OBJDUMP=$ac_cv_prog_OBJDUMP if test -n "$OBJDUMP"; then { echo "$as_me:$LINENO: result: $OBJDUMP" >&5 echo "${ECHO_T}$OBJDUMP" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi fi if test -z "$ac_cv_prog_OBJDUMP"; then ac_ct_OBJDUMP=$OBJDUMP # Extract the first word of "objdump", so it can be a program name with args. set dummy objdump; ac_word=$2 { 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_OBJDUMP+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_OBJDUMP"; then ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_OBJDUMP="objdump" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP if test -n "$ac_ct_OBJDUMP"; then { echo "$as_me:$LINENO: result: $ac_ct_OBJDUMP" >&5 echo "${ECHO_T}$ac_ct_OBJDUMP" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi if test "x$ac_ct_OBJDUMP" = x; then OBJDUMP="false" else case $cross_compiling:$ac_tool_warned in yes:) { echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools whose name does not start with the host triplet. If you think this configuration is useful to you, please write to autoconf@gnu.org." >&5 echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools whose name does not start with the host triplet. If you think this configuration is useful to you, please write to autoconf@gnu.org." >&2;} ac_tool_warned=yes ;; esac OBJDUMP=$ac_ct_OBJDUMP fi else OBJDUMP="$ac_cv_prog_OBJDUMP" fi ;; esac need_locks="$enable_libtool_lock" 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 how to run the C preprocessor" >&5 echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6; } # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if test "${ac_cv_prog_CPP+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else # Double quotes because CPP needs to be expanded for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" do ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat >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 { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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 && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.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 nonexistent 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 { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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 && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.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_CPP=$CPP fi CPP=$ac_cv_prog_CPP else ac_cv_prog_CPP=$CPP fi { echo "$as_me:$LINENO: result: $CPP" >&5 echo "${ECHO_T}$CPP" >&6; } ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat >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 { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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 && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.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 nonexistent 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 { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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 && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.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 \"$CPP\" fails sanity check See \`config.log' for more details." >&5 echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details." >&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 { 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 { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat >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 -r 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 -r 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 #include #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) return 2; return 0; } _ACEOF rm -f conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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 core.conftest.* 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 # 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 { as_var=$as_ac_Header; eval "test \"\${$as_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. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core conftest.err conftest.$ac_objext conftest.$ac_ext fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 for ac_header in dlfcn.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core 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 { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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 && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.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_c_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;} ;; esac { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 ac_ext=cpp 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 -z "$CXX"; then if test -n "$CCC"; then CXX=$CCC else if test -n "$ac_tool_prefix"; then for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 IFS=$as_save_IFS 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 g++ c++ gpp aCC CC cxx cc++ cl.exe 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 IFS=$as_save_IFS 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 if test "x$ac_ct_CXX" = x; then CXX="g++" else case $cross_compiling:$ac_tool_warned in yes:) { echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools whose name does not start with the host triplet. If you think this configuration is useful to you, please write to autoconf@gnu.org." >&5 echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools whose name does not start with the host triplet. If you think this configuration is useful to you, please write to autoconf@gnu.org." >&2;} ac_tool_warned=yes ;; esac CXX=$ac_ct_CXX fi fi fi 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` { (ac_try="$ac_compiler --version >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compiler --version >&5") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { (ac_try="$ac_compiler -v >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compiler -v >&5") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { (ac_try="$ac_compiler -V >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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 { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core 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 { 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 ac_save_cxx_werror_flag=$ac_cxx_werror_flag ac_cxx_werror_flag=yes ac_cv_prog_cxx_g=no CXXFLAGS="-g" 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 { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_prog_cxx_g=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 CXXFLAGS="" 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 { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cxx_werror_flag=$ac_save_cxx_werror_flag CXXFLAGS="-g" 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 { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_prog_cxx_g=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cxx_werror_flag=$ac_save_cxx_werror_flag 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 ac_ext=cpp 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 depcc="$CXX" am_compiler_list= { echo "$as_me:$LINENO: checking dependency style of $depcc" >&5 echo $ECHO_N "checking dependency style of $depcc... $ECHO_C" >&6; } if test "${am_cv_CXX_dependencies_compiler_type+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named `D' -- because `-MD' means `put the output # in D'. mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_CXX_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with # Solaris 8's {/usr,}/bin/sh. touch sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf case $depmode in nosideeffect) # after this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; none) break ;; esac # We check with `-c' and `-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle `-M -o', and we need to detect this. if depmode=$depmode \ source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_CXX_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_CXX_dependencies_compiler_type=none fi fi { echo "$as_me:$LINENO: result: $am_cv_CXX_dependencies_compiler_type" >&5 echo "${ECHO_T}$am_cv_CXX_dependencies_compiler_type" >&6; } CXXDEPMODE=depmode=$am_cv_CXX_dependencies_compiler_type if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CXX_dependencies_compiler_type" = gcc3; then am__fastdepCXX_TRUE= am__fastdepCXX_FALSE='#' else am__fastdepCXX_TRUE='#' am__fastdepCXX_FALSE= fi ac_ext=cpp 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 { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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 && { test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || test ! -s conftest.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 nonexistent 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 { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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 && { test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || test ! -s conftest.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 { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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 && { test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || test ! -s conftest.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 nonexistent 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 { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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 && { test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || test ! -s conftest.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=cpp 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 ac_ext=f ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5' ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_f77_compiler_gnu if test -n "$ac_tool_prefix"; then for ac_prog in g77 xlf f77 frt pgf77 cf77 fort77 fl32 af77 xlf90 f90 pgf90 pghpf epcf90 gfortran g95 xlf95 f95 fort ifort ifc efc pgf95 lf95 ftn 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_F77+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$F77"; then ac_cv_prog_F77="$F77" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_F77="$ac_tool_prefix$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi F77=$ac_cv_prog_F77 if test -n "$F77"; then { echo "$as_me:$LINENO: result: $F77" >&5 echo "${ECHO_T}$F77" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi test -n "$F77" && break done fi if test -z "$F77"; then ac_ct_F77=$F77 for ac_prog in g77 xlf f77 frt pgf77 cf77 fort77 fl32 af77 xlf90 f90 pgf90 pghpf epcf90 gfortran g95 xlf95 f95 fort ifort ifc efc pgf95 lf95 ftn 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_F77+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_F77"; then ac_cv_prog_ac_ct_F77="$ac_ct_F77" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_F77="$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_F77=$ac_cv_prog_ac_ct_F77 if test -n "$ac_ct_F77"; then { echo "$as_me:$LINENO: result: $ac_ct_F77" >&5 echo "${ECHO_T}$ac_ct_F77" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi test -n "$ac_ct_F77" && break done if test "x$ac_ct_F77" = x; then F77="" else case $cross_compiling:$ac_tool_warned in yes:) { echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools whose name does not start with the host triplet. If you think this configuration is useful to you, please write to autoconf@gnu.org." >&5 echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools whose name does not start with the host triplet. If you think this configuration is useful to you, please write to autoconf@gnu.org." >&2;} ac_tool_warned=yes ;; esac F77=$ac_ct_F77 fi fi # Provide some information about the compiler. echo "$as_me:$LINENO: checking for Fortran 77 compiler version" >&5 ac_compiler=`set X $ac_compile; echo $2` { (ac_try="$ac_compiler --version >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compiler --version >&5") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { (ac_try="$ac_compiler -v >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compiler -v >&5") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { (ac_try="$ac_compiler -V >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compiler -V >&5") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } rm -f a.out # If we don't use `.F' as extension, the preprocessor is not run on the # input file. (Note that this only needs to work for GNU compilers.) ac_save_ext=$ac_ext ac_ext=F { echo "$as_me:$LINENO: checking whether we are using the GNU Fortran 77 compiler" >&5 echo $ECHO_N "checking whether we are using the GNU Fortran 77 compiler... $ECHO_C" >&6; } if test "${ac_cv_f77_compiler_gnu+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF program main #ifndef __GNUC__ choke me #endif end _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_f77_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_f77_compiler_gnu=$ac_compiler_gnu fi { echo "$as_me:$LINENO: result: $ac_cv_f77_compiler_gnu" >&5 echo "${ECHO_T}$ac_cv_f77_compiler_gnu" >&6; } ac_ext=$ac_save_ext ac_test_FFLAGS=${FFLAGS+set} ac_save_FFLAGS=$FFLAGS FFLAGS= { echo "$as_me:$LINENO: checking whether $F77 accepts -g" >&5 echo $ECHO_N "checking whether $F77 accepts -g... $ECHO_C" >&6; } if test "${ac_cv_prog_f77_g+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else FFLAGS=-g cat >conftest.$ac_ext <<_ACEOF program main end _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_f77_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_prog_f77_g=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_prog_f77_g=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_prog_f77_g" >&5 echo "${ECHO_T}$ac_cv_prog_f77_g" >&6; } if test "$ac_test_FFLAGS" = set; then FFLAGS=$ac_save_FFLAGS elif test $ac_cv_prog_f77_g = yes; then if test "x$ac_cv_f77_compiler_gnu" = xyes; then FFLAGS="-g -O2" else FFLAGS="-g" fi else if test "x$ac_cv_f77_compiler_gnu" = xyes; then FFLAGS="-O2" else FFLAGS= fi fi G77=`test $ac_compiler_gnu = yes && echo yes` 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 # Autoconf 2.13's AC_OBJEXT and AC_EXEEXT macros only works for C compilers! # find the maximum length of command line arguments { echo "$as_me:$LINENO: checking the maximum length of command line arguments" >&5 echo $ECHO_N "checking the maximum length of command line arguments... $ECHO_C" >&6; } if test "${lt_cv_sys_max_cmd_len+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else i=0 testring="ABCD" case $build_os in msdosdjgpp*) # On DJGPP, this test can blow up pretty badly due to problems in libc # (any single argument exceeding 2000 bytes causes a buffer overrun # during glob expansion). Even if it were fixed, the result of this # check would be larger than it should be. lt_cv_sys_max_cmd_len=12288; # 12K is about right ;; gnu*) # Under GNU Hurd, this test is not required because there is # no limit to the length of command line arguments. # Libtool will interpret -1 as no limit whatsoever lt_cv_sys_max_cmd_len=-1; ;; cygwin* | mingw*) # On Win9x/ME, this test blows up -- it succeeds, but takes # about 5 minutes as the teststring grows exponentially. # Worse, since 9x/ME are not pre-emptively multitasking, # you end up with a "frozen" computer, even though with patience # the test eventually succeeds (with a max line length of 256k). # Instead, let's just punt: use the minimum linelength reported by # all of the supported platforms: 8192 (on NT/2K/XP). lt_cv_sys_max_cmd_len=8192; ;; amigaos*) # On AmigaOS with pdksh, this test takes hours, literally. # So we just punt and use a minimum line length of 8192. lt_cv_sys_max_cmd_len=8192; ;; *) # If test is not a shell built-in, we'll probably end up computing a # maximum length that is only half of the actual maximum length, but # we can't tell. while (test "X"`$CONFIG_SHELL $0 --fallback-echo "X$testring" 2>/dev/null` \ = "XX$testring") >/dev/null 2>&1 && new_result=`expr "X$testring" : ".*" 2>&1` && lt_cv_sys_max_cmd_len=$new_result && test $i != 17 # 1/2 MB should be enough do i=`expr $i + 1` testring=$testring$testring done testring= # Add a significant safety factor because C++ compilers can tack on massive # amounts of additional arguments before passing them to the linker. # It appears as though 1/2 is a usable value. lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` ;; esac fi if test -n $lt_cv_sys_max_cmd_len ; then { echo "$as_me:$LINENO: result: $lt_cv_sys_max_cmd_len" >&5 echo "${ECHO_T}$lt_cv_sys_max_cmd_len" >&6; } else { echo "$as_me:$LINENO: result: none" >&5 echo "${ECHO_T}none" >&6; } fi # Check for command to grab the raw symbol name followed by C symbol from nm. { echo "$as_me:$LINENO: checking command to parse $NM output from $compiler object" >&5 echo $ECHO_N "checking command to parse $NM output from $compiler object... $ECHO_C" >&6; } if test "${lt_cv_sys_global_symbol_pipe+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else # These are sane defaults that work on at least a few old systems. # [They come from Ultrix. What could be older than Ultrix?!! ;)] # Character class describing NM global symbol codes. symcode='[BCDEGRST]' # Regexp to match symbols that can be accessed directly from C. sympat='\([_A-Za-z][_A-Za-z0-9]*\)' # Transform the above into a raw symbol and a C symbol. symxfrm='\1 \2\3 \3' # Transform an extracted symbol line into a proper C declaration lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern int \1;/p'" # Transform an extracted symbol line into symbol name and symbol address lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode \([^ ]*\) \([^ ]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" # Define system-specific variables. case $host_os in aix*) symcode='[BCDT]' ;; cygwin* | mingw* | pw32*) symcode='[ABCDGISTW]' ;; hpux*) # Its linker distinguishes data from code symbols if test "$host_cpu" = ia64; then symcode='[ABCDEGRST]' fi lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" ;; irix* | nonstopux*) symcode='[BCDEGRST]' ;; osf*) symcode='[BCDEGQRST]' ;; solaris* | sysv5*) symcode='[BDT]' ;; sysv4) symcode='[DFNSTU]' ;; esac # Handle CRLF in mingw tool chain opt_cr= case $build_os in mingw*) opt_cr=`echo 'x\{0,1\}' | tr x '\015'` # option cr in regexp ;; esac # If we're using GNU nm, then use its standard symbol codes. case `$NM -V 2>&1` in *GNU* | *'with BFD'*) symcode='[ABCDGISTW]' ;; esac # Try without a prefix undercore, then with it. for ac_symprfx in "" "_"; do # Write the raw and C identifiers. lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*\($ac_symprfx\)$sympat$opt_cr$/$symxfrm/p'" # Check to see that the pipe works correctly. pipe_works=no rm -f conftest* cat > conftest.$ac_ext <&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then # Now try to grab the symbols. nlist=conftest.nm if { (eval echo "$as_me:$LINENO: \"$NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist\"") >&5 (eval $NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && test -s "$nlist"; then # Try sorting and uniquifying the output. if sort "$nlist" | uniq > "$nlist"T; then mv -f "$nlist"T "$nlist" else rm -f "$nlist"T fi # Make sure that we snagged all the symbols we need. if grep ' nm_test_var$' "$nlist" >/dev/null; then if grep ' nm_test_func$' "$nlist" >/dev/null; then cat < conftest.$ac_ext #ifdef __cplusplus extern "C" { #endif EOF # Now generate the symbol file. eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | grep -v main >> conftest.$ac_ext' cat <> conftest.$ac_ext #if defined (__STDC__) && __STDC__ # define lt_ptr_t void * #else # define lt_ptr_t char * # define const #endif /* The mapping between symbol names and symbols. */ const struct { const char *name; lt_ptr_t address; } lt_preloaded_symbols[] = { EOF $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (lt_ptr_t) \&\2},/" < "$nlist" | grep -v main >> conftest.$ac_ext cat <<\EOF >> conftest.$ac_ext {0, (lt_ptr_t) 0} }; #ifdef __cplusplus } #endif EOF # Now try linking the two files. mv conftest.$ac_objext conftstm.$ac_objext lt_save_LIBS="$LIBS" lt_save_CFLAGS="$CFLAGS" LIBS="conftstm.$ac_objext" CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag" 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); } && test -s conftest${ac_exeext}; then pipe_works=yes fi LIBS="$lt_save_LIBS" CFLAGS="$lt_save_CFLAGS" else echo "cannot find nm_test_func in $nlist" >&5 fi else echo "cannot find nm_test_var in $nlist" >&5 fi else echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5 fi else echo "$progname: failed program was:" >&5 cat conftest.$ac_ext >&5 fi rm -f conftest* conftst* # Do not use the global_symbol_pipe unless it works. if test "$pipe_works" = yes; then break else lt_cv_sys_global_symbol_pipe= fi done fi if test -z "$lt_cv_sys_global_symbol_pipe"; then lt_cv_sys_global_symbol_to_cdecl= fi if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then { echo "$as_me:$LINENO: result: failed" >&5 echo "${ECHO_T}failed" >&6; } else { echo "$as_me:$LINENO: result: ok" >&5 echo "${ECHO_T}ok" >&6; } fi { echo "$as_me:$LINENO: checking for objdir" >&5 echo $ECHO_N "checking for objdir... $ECHO_C" >&6; } if test "${lt_cv_objdir+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else rm -f .libs 2>/dev/null mkdir .libs 2>/dev/null if test -d .libs; then lt_cv_objdir=.libs else # MS-DOS does not allow filenames that begin with a dot. lt_cv_objdir=_libs fi rmdir .libs 2>/dev/null fi { echo "$as_me:$LINENO: result: $lt_cv_objdir" >&5 echo "${ECHO_T}$lt_cv_objdir" >&6; } objdir=$lt_cv_objdir case $host_os in aix3*) # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi ;; esac # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. Xsed='sed -e s/^X//' sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\([\\"\\`\\\\]\)/\\\1/g' # Sed substitution to delay expansion of an escaped shell variable in a # double_quote_subst'ed string. delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' # Sed substitution to avoid accidental globbing in evaled expressions no_glob_subst='s/\*/\\\*/g' # Constants: rm="rm -f" # Global variables: default_ofile=libtool can_build_shared=yes # All known linkers require a `.a' archive for static linking (except M$VC, # which needs '.lib'). libext=a ltmain="$ac_aux_dir/ltmain.sh" ofile="$default_ofile" with_gnu_ld="$lt_cv_prog_gnu_ld" if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args. set dummy ${ac_tool_prefix}ar; 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_AR+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$AR"; then ac_cv_prog_AR="$AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_AR="${ac_tool_prefix}ar" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AR=$ac_cv_prog_AR if test -n "$AR"; then { echo "$as_me:$LINENO: result: $AR" >&5 echo "${ECHO_T}$AR" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi fi if test -z "$ac_cv_prog_AR"; then ac_ct_AR=$AR # Extract the first word of "ar", so it can be a program name with args. set dummy ar; 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_AR+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_AR"; then ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_AR="ar" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_AR=$ac_cv_prog_ac_ct_AR if test -n "$ac_ct_AR"; then { echo "$as_me:$LINENO: result: $ac_ct_AR" >&5 echo "${ECHO_T}$ac_ct_AR" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi if test "x$ac_ct_AR" = x; then AR="false" else case $cross_compiling:$ac_tool_warned in yes:) { echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools whose name does not start with the host triplet. If you think this configuration is useful to you, please write to autoconf@gnu.org." >&5 echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools whose name does not start with the host triplet. If you think this configuration is useful to you, please write to autoconf@gnu.org." >&2;} ac_tool_warned=yes ;; esac AR=$ac_ct_AR fi else AR="$ac_cv_prog_AR" fi 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 IFS=$as_save_IFS 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 IFS=$as_save_IFS 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 if test "x$ac_ct_RANLIB" = x; then RANLIB=":" else case $cross_compiling:$ac_tool_warned in yes:) { echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools whose name does not start with the host triplet. If you think this configuration is useful to you, please write to autoconf@gnu.org." >&5 echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools whose name does not start with the host triplet. If you think this configuration is useful to you, please write to autoconf@gnu.org." >&2;} ac_tool_warned=yes ;; esac RANLIB=$ac_ct_RANLIB fi else RANLIB="$ac_cv_prog_RANLIB" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_STRIP+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then { echo "$as_me:$LINENO: result: $STRIP" >&5 echo "${ECHO_T}$STRIP" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi fi if test -z "$ac_cv_prog_STRIP"; then ac_ct_STRIP=$STRIP # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 { 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_STRIP+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_STRIP"; then ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_STRIP="strip" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP if test -n "$ac_ct_STRIP"; then { echo "$as_me:$LINENO: result: $ac_ct_STRIP" >&5 echo "${ECHO_T}$ac_ct_STRIP" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi if test "x$ac_ct_STRIP" = x; then STRIP=":" else case $cross_compiling:$ac_tool_warned in yes:) { echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools whose name does not start with the host triplet. If you think this configuration is useful to you, please write to autoconf@gnu.org." >&5 echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools whose name does not start with the host triplet. If you think this configuration is useful to you, please write to autoconf@gnu.org." >&2;} ac_tool_warned=yes ;; esac STRIP=$ac_ct_STRIP fi else STRIP="$ac_cv_prog_STRIP" fi old_CC="$CC" old_CFLAGS="$CFLAGS" # Set sane defaults for various variables test -z "$AR" && AR=ar test -z "$AR_FLAGS" && AR_FLAGS=cru test -z "$AS" && AS=as test -z "$CC" && CC=cc test -z "$LTCC" && LTCC=$CC test -z "$DLLTOOL" && DLLTOOL=dlltool test -z "$LD" && LD=ld test -z "$LN_S" && LN_S="ln -s" test -z "$MAGIC_CMD" && MAGIC_CMD=file test -z "$NM" && NM=nm test -z "$SED" && SED=sed test -z "$OBJDUMP" && OBJDUMP=objdump test -z "$RANLIB" && RANLIB=: test -z "$STRIP" && STRIP=: test -z "$ac_objext" && ac_objext=o # Determine commands to create old-style static archives. old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs$old_deplibs' old_postinstall_cmds='chmod 644 $oldlib' old_postuninstall_cmds= if test -n "$RANLIB"; then case $host_os in openbsd*) old_postinstall_cmds="\$RANLIB -t \$oldlib~$old_postinstall_cmds" ;; *) old_postinstall_cmds="\$RANLIB \$oldlib~$old_postinstall_cmds" ;; esac old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" fi # Only perform the check for file, if the check method requires it case $deplibs_check_method in file_magic*) if test "$file_magic_cmd" = '$MAGIC_CMD'; then { echo "$as_me:$LINENO: checking for ${ac_tool_prefix}file" >&5 echo $ECHO_N "checking for ${ac_tool_prefix}file... $ECHO_C" >&6; } if test "${lt_cv_path_MAGIC_CMD+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else case $MAGIC_CMD in [\\/*] | ?:[\\/]*) lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD="$MAGIC_CMD" lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" for ac_dir in $ac_dummy; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/${ac_tool_prefix}file; then lt_cv_path_MAGIC_CMD="$ac_dir/${ac_tool_prefix}file" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex="`expr \"$deplibs_check_method\" : \"file_magic \(.*\)\"`" MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org EOF fi ;; esac fi break fi done IFS="$lt_save_ifs" MAGIC_CMD="$lt_save_MAGIC_CMD" ;; esac fi MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if test -n "$MAGIC_CMD"; then { echo "$as_me:$LINENO: result: $MAGIC_CMD" >&5 echo "${ECHO_T}$MAGIC_CMD" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi if test -z "$lt_cv_path_MAGIC_CMD"; then if test -n "$ac_tool_prefix"; then { echo "$as_me:$LINENO: checking for file" >&5 echo $ECHO_N "checking for file... $ECHO_C" >&6; } if test "${lt_cv_path_MAGIC_CMD+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else case $MAGIC_CMD in [\\/*] | ?:[\\/]*) lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD="$MAGIC_CMD" lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" for ac_dir in $ac_dummy; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/file; then lt_cv_path_MAGIC_CMD="$ac_dir/file" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex="`expr \"$deplibs_check_method\" : \"file_magic \(.*\)\"`" MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org EOF fi ;; esac fi break fi done IFS="$lt_save_ifs" MAGIC_CMD="$lt_save_MAGIC_CMD" ;; esac fi MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if test -n "$MAGIC_CMD"; then { echo "$as_me:$LINENO: result: $MAGIC_CMD" >&5 echo "${ECHO_T}$MAGIC_CMD" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi else MAGIC_CMD=: fi fi fi ;; esac enable_dlopen=yes enable_win32_dll=yes # Check whether --enable-libtool-lock was given. if test "${enable_libtool_lock+set}" = set; then enableval=$enable_libtool_lock; fi test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes # Check whether --with-pic was given. if test "${with_pic+set}" = set; then withval=$with_pic; pic_mode="$withval" else pic_mode=default fi test -z "$pic_mode" && pic_mode=default # Use C for the default configuration in the libtool script tagname= lt_save_CC="$CC" ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu # Source file extension for C test sources. ac_ext=c # Object file extension for compiled C test sources. objext=o objext=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;\n" # Code to be used in simple link tests lt_simple_link_test_code='int main(){return(0);}\n' # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # Allow CC to be a program name with arguments. compiler=$CC # # Check for any special shared library compilation flags. # lt_prog_cc_shlib= if test "$GCC" = no; then case $host_os in sco3.2v5*) lt_prog_cc_shlib='-belf' ;; esac fi if test -n "$lt_prog_cc_shlib"; then { echo "$as_me:$LINENO: WARNING: \`$CC' requires \`$lt_prog_cc_shlib' to build shared libraries" >&5 echo "$as_me: WARNING: \`$CC' requires \`$lt_prog_cc_shlib' to build shared libraries" >&2;} if echo "$old_CC $old_CFLAGS " | grep "[ ]$lt_prog_cc_shlib[ ]" >/dev/null; then : else { echo "$as_me:$LINENO: WARNING: add \`$lt_prog_cc_shlib' to the CC or CFLAGS env variable and reconfigure" >&5 echo "$as_me: WARNING: add \`$lt_prog_cc_shlib' to the CC or CFLAGS env variable and reconfigure" >&2;} lt_cv_prog_cc_can_build_shared=no fi fi # # Check to make sure the static flag actually works. # { echo "$as_me:$LINENO: checking if $compiler static flag $lt_prog_compiler_static works" >&5 echo $ECHO_N "checking if $compiler static flag $lt_prog_compiler_static works... $ECHO_C" >&6; } if test "${lt_prog_compiler_static_works+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else lt_prog_compiler_static_works=no save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $lt_prog_compiler_static" printf "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&5 else lt_prog_compiler_static_works=yes fi fi $rm conftest* LDFLAGS="$save_LDFLAGS" fi { echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works" >&5 echo "${ECHO_T}$lt_prog_compiler_static_works" >&6; } if test x"$lt_prog_compiler_static_works" = xyes; then : else lt_prog_compiler_static= fi ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... lt_prog_compiler_no_builtin_flag= if test "$GCC" = yes; then lt_prog_compiler_no_builtin_flag=' -fno-builtin' { echo "$as_me:$LINENO: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 echo $ECHO_N "checking if $compiler supports -fno-rtti -fno-exceptions... $ECHO_C" >&6; } if test "${lt_cv_prog_compiler_rtti_exceptions+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else lt_cv_prog_compiler_rtti_exceptions=no ac_outfile=conftest.$ac_objext printf "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-fno-rtti -fno-exceptions" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:7435: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:7439: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings if test ! -s conftest.err; then lt_cv_prog_compiler_rtti_exceptions=yes fi fi $rm conftest* fi { echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 echo "${ECHO_T}$lt_cv_prog_compiler_rtti_exceptions" >&6; } if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions" else : fi fi lt_prog_compiler_wl= lt_prog_compiler_pic= lt_prog_compiler_static= { echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5 echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6; } if test "$GCC" = yes; then lt_prog_compiler_wl='-Wl,' lt_prog_compiler_static='-static' case $host_os in aix*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static='-Bstatic' fi ;; amigaos*) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4' ;; beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | pw32* | os2*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_prog_compiler_pic='-DDLL_EXPORT' ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files lt_prog_compiler_pic='-fno-common' ;; msdosdjgpp*) # Just because we use GCC doesn't mean we suddenly get shared libraries # on systems that don't support them. lt_prog_compiler_can_build_shared=no enable_shared=no ;; sysv4*MP*) if test -d /usr/nec; then lt_prog_compiler_pic=-Kconform_pic fi ;; hpux*) # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case "$host_cpu" in hppa*64*|ia64*) # +Z the default ;; *) lt_prog_compiler_pic='-fPIC' ;; esac ;; *) lt_prog_compiler_pic='-fPIC' ;; esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in aix*) lt_prog_compiler_wl='-Wl,' if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static='-Bstatic' else lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp' fi ;; mingw* | pw32* | os2*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_prog_compiler_pic='-DDLL_EXPORT' ;; hpux9* | hpux10* | hpux11*) lt_prog_compiler_wl='-Wl,' # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case "$host_cpu" in hppa*64*|ia64*) # +Z the default ;; *) lt_prog_compiler_pic='+Z' ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? lt_prog_compiler_static='${wl}-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) lt_prog_compiler_wl='-Wl,' # PIC (with -KPIC) is the default. lt_prog_compiler_static='-non_shared' ;; newsos6) lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; linux*) case $CC in icc* | ecc*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-static' ;; ccc*) lt_prog_compiler_wl='-Wl,' # All Alpha code is PIC. lt_prog_compiler_static='-non_shared' ;; esac ;; osf3* | osf4* | osf5*) lt_prog_compiler_wl='-Wl,' # All OSF/1 code is PIC. lt_prog_compiler_static='-non_shared' ;; sco3.2v5*) lt_prog_compiler_pic='-Kpic' lt_prog_compiler_static='-dn' ;; solaris*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; sunos4*) lt_prog_compiler_wl='-Qoption ld ' lt_prog_compiler_pic='-PIC' lt_prog_compiler_static='-Bstatic' ;; sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec ;then lt_prog_compiler_pic='-Kconform_pic' lt_prog_compiler_static='-Bstatic' fi ;; uts4*) lt_prog_compiler_pic='-pic' lt_prog_compiler_static='-Bstatic' ;; *) lt_prog_compiler_can_build_shared=no ;; esac fi { echo "$as_me:$LINENO: result: $lt_prog_compiler_pic" >&5 echo "${ECHO_T}$lt_prog_compiler_pic" >&6; } # # Check to make sure the PIC flag actually works. # if test -n "$lt_prog_compiler_pic"; then { echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5 echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic works... $ECHO_C" >&6; } if test "${lt_prog_compiler_pic_works+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else lt_prog_compiler_pic_works=no ac_outfile=conftest.$ac_objext printf "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$lt_prog_compiler_pic -DPIC" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:7668: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:7672: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings if test ! -s conftest.err; then lt_prog_compiler_pic_works=yes fi fi $rm conftest* fi { echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works" >&5 echo "${ECHO_T}$lt_prog_compiler_pic_works" >&6; } if test x"$lt_prog_compiler_pic_works" = xyes; then case $lt_prog_compiler_pic in "" | " "*) ;; *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;; esac else lt_prog_compiler_pic= lt_prog_compiler_can_build_shared=no fi fi case "$host_os" in # For platforms which do not support PIC, -DPIC is meaningless: *djgpp*) lt_prog_compiler_pic= ;; *) lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC" ;; esac { echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5 echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6; } if test "${lt_cv_prog_compiler_c_o+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else lt_cv_prog_compiler_c_o=no $rm -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out printf "$lt_simple_compile_test_code" > conftest.$ac_ext # According to Tom Tromey, Ian Lance Taylor reported there are C compilers # that will create temporary files in the current directory regardless of # the output directory. Thus, making CWD read-only will cause this test # to fail, enabling locking or at least warning the user not to do parallel # builds. chmod -w . lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:7735: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:7739: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings if test ! -s out/conftest.err; then lt_cv_prog_compiler_c_o=yes fi fi chmod u+w . $rm conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files $rm out/* && rmdir out cd .. rmdir conftest $rm conftest* fi { echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o" >&5 echo "${ECHO_T}$lt_cv_prog_compiler_c_o" >&6; } hard_links="nottested" if test "$lt_cv_prog_compiler_c_o" = no && test "$need_locks" != no; then # do not overwrite the value of need_locks provided by the user { echo "$as_me:$LINENO: checking if we can lock with hard links" >&5 echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6; } hard_links=yes $rm conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no { echo "$as_me:$LINENO: result: $hard_links" >&5 echo "${ECHO_T}$hard_links" >&6; } if test "$hard_links" = no; then { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} need_locks=warn fi else need_locks=no fi { echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5 echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6; } runpath_var= allow_undefined_flag= enable_shared_with_static_runtimes=no archive_cmds= archive_expsym_cmds= old_archive_From_new_cmds= old_archive_from_expsyms_cmds= export_dynamic_flag_spec= whole_archive_flag_spec= thread_safe_flag_spec= hardcode_libdir_flag_spec= hardcode_libdir_flag_spec_ld= hardcode_libdir_separator= hardcode_direct=no hardcode_minus_L=no hardcode_shlibpath_var=unsupported link_all_deplibs=unknown hardcode_automatic=no module_cmds= module_expsym_cmds= always_export_symbols=no export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list include_expsyms= # exclude_expsyms can be an extended regexp of symbols to exclude # it will be wrapped by ` (' and `)$', so one must not match beginning or # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', # as well as any symbol that contains `d'. exclude_expsyms="_GLOBAL_OFFSET_TABLE_" # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. extract_expsyms_cmds= 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 # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='${wl}' # See if GNU ld supports shared libraries. 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 cat <&2 *** Warning: the GNU linker, at least up to release 2.9.1, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you *** really care for shared libraries, you may want to modify your PATH *** so that a non-GNU linker is found, and then restart. EOF fi ;; amigaos*) archive_cmds='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes # 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't use # them. ld_shlibs=no ;; beos*) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then allow_undefined_flag=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else ld_shlibs=no fi ;; cygwin* | mingw* | pw32*) # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless, # as there is no search path for DLLs. hardcode_libdir_flag_spec='-L$libdir' allow_undefined_flag=unsupported always_export_symbols=no enable_shared_with_static_runtimes=yes export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGS] /s/.* \([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW] /s/.* //'\'' | sort | uniq > $export_symbols' if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib' else ld_shlibs=no fi ;; netbsd*) if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' fi ;; solaris* | sysv5*) if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then ld_shlibs=no cat <&2 *** Warning: The releases 2.8.* of the GNU linker cannot reliably *** create shared libraries on Solaris systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.9.1 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. EOF elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; sunos4*) archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= hardcode_direct=yes hardcode_shlibpath_var=no ;; *) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; esac if test "$ld_shlibs" = yes; then runpath_var=LD_RUN_PATH hardcode_libdir_flag_spec='${wl}--rpath ${wl}$libdir' export_dynamic_flag_spec='${wl}--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else whole_archive_flag_spec= fi fi else # PORTME fill in a description of your system's linker (not GNU ld) case $host_os in aix3*) allow_undefined_flag=unsupported always_export_symbols=yes archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. hardcode_minus_L=yes if test "$GCC" = yes && test -z "$link_static_flag"; 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 exp_sym_flag='-Bexport' no_entry_flag="" else # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm if $NM -V 2>&1 | grep 'GNU' > /dev/null; then export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' else export_symbols_cmds='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # 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 exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. archive_cmds='' hardcode_direct=yes hardcode_libdir_separator=':' link_all_deplibs=yes if test "$GCC" = yes; then case $host_os in aix4.012|aix4.012.*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && \ strings "$collect2name" | grep resolve_lib_name >/dev/null then # We have reworked collect2 hardcode_direct=yes else # We have old collect2 hardcode_direct=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking hardcode_minus_L=yes hardcode_libdir_flag_spec='-L$libdir' hardcode_libdir_separator= fi esac shared_flag='-shared' else # not using gcc if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi fi # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. always_export_symbols=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. allow_undefined_flag='-berok' # Determine the default libpath from the value encoded in an empty executable. 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 { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'` # Check for a 64-bit object if we didn't find anything. if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'`; fi else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" archive_expsym_cmds="\$CC"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' allow_undefined_flag="-z nodefs" archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an empty executable. 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 { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'` # Check for a 64-bit object if we didn't find anything. if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'`; fi else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. no_undefined_flag=' ${wl}-bernotok' allow_undefined_flag=' ${wl}-berok' # -bexpall does not export symbols beginning with underscore (_) always_export_symbols=yes # Exported symbols can be pulled into shared objects from archives whole_archive_flag_spec=' ' archive_cmds_need_lc=yes # This is similar to how AIX traditionally builds it's shared libraries. archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; amigaos*) archive_cmds='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes # see comment about different semantics on the GNU ld section ld_shlibs=no ;; bsdi4*) export_dynamic_flag_spec=-rdynamic ;; 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=' ' allow_undefined_flag=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext=".dll" # FIXME: Setting linknames here is a bad hack. archive_cmds='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. old_archive_From_new_cmds='true' # FIXME: Should let the user specify the lib program. old_archive_cmds='lib /OUT:$oldlib$oldobjs$old_deplibs' fix_srcfile_path='`cygpath -w "$srcfile"`' enable_shared_with_static_runtimes=yes ;; darwin* | rhapsody*) if test "$GXX" = yes ; then archive_cmds_need_lc=no case "$host_os" in rhapsody* | darwin1.[012]) allow_undefined_flag='-undefined suppress' ;; *) # Darwin 1.3 on if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then allow_undefined_flag='-flat_namespace -undefined suppress' else case ${MACOSX_DEPLOYMENT_TARGET} in 10.[012]) allow_undefined_flag='-flat_namespace -undefined suppress' ;; 10.*) allow_undefined_flag='-undefined dynamic_lookup' ;; esac fi ;; esac lt_int_apple_cc_single_mod=no output_verbose_link_cmd='echo' if $CC -dumpspecs 2>&1 | grep 'single_module' >/dev/null ; then lt_int_apple_cc_single_mod=yes fi if test "X$lt_int_apple_cc_single_mod" = Xyes ; then archive_cmds='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' else archive_cmds='$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring' fi module_cmds='$CC ${wl}-bind_at_load $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's if test "X$lt_int_apple_cc_single_mod" = Xyes ; then archive_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' else archive_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' fi module_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' hardcode_direct=no hardcode_automatic=yes hardcode_shlibpath_var=unsupported whole_archive_flag_spec='-all_load $convenience' link_all_deplibs=yes else ld_shlibs=no fi ;; dgux*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-L$libdir' hardcode_shlibpath_var=no ;; freebsd1*) ld_shlibs=no ;; # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little # extra space). freebsd2.2*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_minus_L=yes hardcode_shlibpath_var=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd* | kfreebsd*-gnu) archive_cmds='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; hpux9*) if test "$GCC" = yes; then archive_cmds='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else archive_cmds='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' fi hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: hardcode_direct=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes export_dynamic_flag_spec='${wl}-E' ;; hpux10* | hpux11*) if test "$GCC" = yes -a "$with_gnu_ld" = no; then case "$host_cpu" in hppa*64*|ia64*) archive_cmds='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; *) archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case "$host_cpu" in hppa*64*|ia64*) archive_cmds='$LD -b +h $soname -o $lib $libobjs $deplibs $linker_flags' ;; *) archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' ;; esac fi if test "$with_gnu_ld" = no; then case "$host_cpu" in hppa*64*) hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_flag_spec_ld='+b $libdir' hardcode_libdir_separator=: hardcode_direct=no hardcode_shlibpath_var=no ;; ia64*) hardcode_libdir_flag_spec='-L$libdir' hardcode_direct=no hardcode_shlibpath_var=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 export_dynamic_flag_spec='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) if test "$GCC" = yes; then archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' hardcode_libdir_flag_spec_ld='-rpath $libdir' fi hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: link_all_deplibs=yes ;; netbsd*) if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; newsos6) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: hardcode_shlibpath_var=no ;; openbsd*) hardcode_direct=yes hardcode_shlibpath_var=no if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='${wl}-rpath,$libdir' export_dynamic_flag_spec='${wl}-E' else case $host_os in openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-R$libdir' ;; *) archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='${wl}-rpath,$libdir' ;; esac fi ;; os2*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes allow_undefined_flag=unsupported archive_cmds='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' old_archive_From_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' ;; osf3*) if test "$GCC" = yes; then allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else allow_undefined_flag=' -expect_unresolved \*' archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' fi hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag if test "$GCC" = yes; then allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' else allow_undefined_flag=' -expect_unresolved \*' archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~ $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib~$rm $lib.exp' # Both c and cxx compiler support -rpath directly hardcode_libdir_flag_spec='-rpath $libdir' fi hardcode_libdir_separator=: ;; sco3.2v5*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var=no export_dynamic_flag_spec='${wl}-Bexport' runpath_var=LD_RUN_PATH hardcode_runpath_var=yes ;; solaris*) no_undefined_flag=' -z text' if test "$GCC" = yes; then archive_cmds='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp' else archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' fi hardcode_libdir_flag_spec='-R$libdir' hardcode_shlibpath_var=no case $host_os in solaris2.[0-5] | solaris2.[0-5].*) ;; *) # Supported since Solaris 2.6 (maybe 2.5.1?) whole_archive_flag_spec='-z allextract$convenience -z defaultextract' ;; esac link_all_deplibs=yes ;; sunos4*) if test "x$host_vendor" = xsequent; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi hardcode_libdir_flag_spec='-L$libdir' hardcode_direct=yes hardcode_minus_L=yes hardcode_shlibpath_var=no ;; sysv4) case $host_vendor in sni) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes # is this really true??? ;; siemens) ## LD is ld it makes a PLAMLIB ## CC just makes a GrossModule. archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' reload_cmds='$CC -r -o $output$reload_objs' hardcode_direct=no ;; motorola) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=no #Motorola manual says yes, but my tests say they lie ;; esac runpath_var='LD_RUN_PATH' hardcode_shlibpath_var=no ;; sysv4.3*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var=no export_dynamic_flag_spec='-Bexport' ;; sysv4*MP*) if test -d /usr/nec; then archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes ld_shlibs=yes fi ;; sysv4.2uw2*) archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_minus_L=no hardcode_shlibpath_var=no hardcode_runpath_var=yes runpath_var=LD_RUN_PATH ;; sysv5OpenUNIX8* | sysv5UnixWare7* | sysv5uw[78]* | unixware7*) no_undefined_flag='${wl}-z ${wl}text' if test "$GCC" = yes; then archive_cmds='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$CC -G ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' fi runpath_var='LD_RUN_PATH' hardcode_shlibpath_var=no ;; sysv5*) no_undefined_flag=' -z text' # $CC -shared without GNU ld will not create a library from C++ # object files and a static libstdc++, better avoid it by now archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' hardcode_libdir_flag_spec= hardcode_shlibpath_var=no runpath_var='LD_RUN_PATH' ;; uts4*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-L$libdir' hardcode_shlibpath_var=no ;; *) ld_shlibs=no ;; esac fi { echo "$as_me:$LINENO: result: $ld_shlibs" >&5 echo "${ECHO_T}$ld_shlibs" >&6; } test "$ld_shlibs" = no && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test "$GCC" = yes; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi # # Do we need to explicitly link libc? # case "x$archive_cmds_need_lc" in x|xyes) # Assume -lc should be added archive_cmds_need_lc=yes if test "$enable_shared" = yes && test "$GCC" = yes; then case $archive_cmds in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. { echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5 echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6; } $rm conftest* printf "$lt_simple_compile_test_code" > conftest.$ac_ext 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); } 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$lt_prog_compiler_wl compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$allow_undefined_flag allow_undefined_flag= if { (eval echo "$as_me:$LINENO: \"$archive_cmds 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5 (eval $archive_cmds 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } then archive_cmds_need_lc=no else archive_cmds_need_lc=yes fi allow_undefined_flag=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $rm conftest* { echo "$as_me:$LINENO: result: $archive_cmds_need_lc" >&5 echo "${ECHO_T}$archive_cmds_need_lc" >&6; } ;; esac fi ;; esac { echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5 echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6; } library_names_spec= libname_spec='lib$name' soname_spec= shrext=".so" postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" if test "$GCC" = yes; then sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown case $host_os in aix3*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='${libname}${release}${shared_ext}$major' ;; aix4* | aix5*) version_type=linux need_lib_prefix=no need_version=no hardcode_into_libs=yes if test "$host_cpu" = ia64; then # AIX 5 supports IA64 library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line `#! .'. This would cause the generated library to # depend on `.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[01] | aix4.[01].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then : else can_build_shared=no fi ;; esac # AIX (on Power*) has no versioning support, so currently we can not hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. if test "$aix_use_runtimelinking" = yes; then # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' else # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='${libname}${release}.a $libname.a' soname_spec='${libname}${release}${shared_ext}$major' fi shlibpath_var=LIBPATH fi ;; amigaos*) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; beos*) library_names_spec='${libname}${shared_ext}' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi4*) version_type=linux need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32*) version_type=windows shrext=".dll" need_version=no need_lib_prefix=no case $GCC,$host_os in yes,cygwin* | yes,mingw* | yes,pw32*) library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $rm \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" ;; mingw*) # MinGW DLLs use traditional 'lib' prefix soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then # It is most probably a Windows format PATH printed by # mingw gcc, but we are running on Cygwin. Gcc prints its search # path with ; separators, and with drive letters. We can handle the # drive letters (cygwin fileutils understands them), so leave them, # especially as we might pass files found there to a mingw objdump, # which wouldn't understand a cygwinified path. Ahh. sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/./-/g'`${versuffix}${shared_ext}' ;; esac ;; *) library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' ;; esac dynamic_linker='Win32 ld.exe' # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext' soname_spec='${libname}${release}${major}$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext='$(test .$module = .yes && echo .so || echo .dylib)' # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same. if test "$GCC" = yes; then sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"` else sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib' fi sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd1*) dynamic_linker=no ;; kfreebsd*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='GNU ld.so' ;; freebsd*) objformat=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout` version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2*) shlibpath_overrides_runpath=yes ;; freebsd3.01* | freebsdelf3.01*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; *) # from 3.2 on shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; esac ;; gnu*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case "$host_cpu" in ia64*) shrext='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' if test "X$HPUX_IA64_MODE" = X32; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" fi sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; hppa*64*) shrext='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555. postinstall_cmds='chmod 555 $lib' ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test "$lt_cv_prog_gnu_ld" = yes; then version_type=linux else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; # This must be Linux ELF. linux*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; nto-qnx*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; openbsd*) version_type=sunos need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then case $host_os in openbsd2.[89] | openbsd2.[89].*) shlibpath_overrides_runpath=no ;; *) shlibpath_overrides_runpath=yes ;; esac else shlibpath_overrides_runpath=yes fi ;; os2*) libname_spec='$name' shrext=".dll" need_lib_prefix=no library_names_spec='$libname${shared_ext} $libname.a' dynamic_linker='OS/2 ld.exe' shlibpath_var=LIBPATH ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" ;; sco3.2v5*) version_type=osf soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH ;; solaris*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test "$with_gnu_ld" = yes; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no export_dynamic_flag_spec='${wl}-Blargedynsym' runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec ;then version_type=linux library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' soname_spec='$libname${shared_ext}.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; uts4*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac { echo "$as_me:$LINENO: result: $dynamic_linker" >&5 echo "${ECHO_T}$dynamic_linker" >&6; } test "$dynamic_linker" = no && can_build_shared=no { echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5 echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6; } hardcode_action= if test -n "$hardcode_libdir_flag_spec" || \ test -n "$runpath_var " || \ test "X$hardcode_automatic"="Xyes" ; then # We can hardcode non-existant directories. if test "$hardcode_direct" != no && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, )" != no && test "$hardcode_minus_L" != no; then # Linking always hardcodes the temporary library directory. hardcode_action=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. hardcode_action=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. hardcode_action=unsupported fi { echo "$as_me:$LINENO: result: $hardcode_action" >&5 echo "${ECHO_T}$hardcode_action" >&6; } if test "$hardcode_action" = relink; then # Fast installation is not supported enable_fast_install=no elif test "$shlibpath_overrides_runpath" = yes || test "$enable_shared" = no; then # Fast installation is not necessary enable_fast_install=needless fi striplib= old_striplib= { echo "$as_me:$LINENO: checking whether stripping libraries is possible" >&5 echo $ECHO_N "checking whether stripping libraries is possible... $ECHO_C" >&6; } if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" test -z "$striplib" && striplib="$STRIP --strip-unneeded" # # # The following section is a PATCH to overcome the # stripped import library issues under cygwin case $host_os in cygwin*) striplib= { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } ;; *) { echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6; } ;; esac # # # AC_MSG_RESULT([yes]) # # else # FIXME - insert some real tests, host_os isn't really good enough case $host_os in darwin*) if test -n "$STRIP" ; then striplib="$STRIP -x" { echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi ;; *) { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } ;; esac fi if test "x$enable_dlopen" != xyes; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown else lt_cv_dlopen=no lt_cv_dlopen_libs= case $host_os in beos*) lt_cv_dlopen="load_add_on" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; mingw* | pw32*) lt_cv_dlopen="LoadLibrary" lt_cv_dlopen_libs= ;; cygwin*) lt_cv_dlopen="dlopen" lt_cv_dlopen_libs= ;; darwin*) # if libdl is installed we need to link against it { echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5 echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6; } if test "${ac_cv_lib_dl_dlopen+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $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 GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_dl_dlopen=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_dl_dlopen=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5 echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6; } if test $ac_cv_lib_dl_dlopen = yes; then lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" else lt_cv_dlopen="dyld" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes fi ;; *) { echo "$as_me:$LINENO: checking for shl_load" >&5 echo $ECHO_N "checking for shl_load... $ECHO_C" >&6; } if test "${ac_cv_func_shl_load+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 shl_load to an innocuous variant, in case declares shl_load. For example, HP-UX 11i declares gettimeofday. */ #define shl_load innocuous_shl_load /* System header to define __stub macros and hopefully few prototypes, which can conflict with char shl_load (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef shl_load /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char shl_load (); /* 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_shl_load || defined __stub___shl_load choke me #endif int main () { return shl_load (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_func_shl_load=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func_shl_load=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_func_shl_load" >&5 echo "${ECHO_T}$ac_cv_func_shl_load" >&6; } if test $ac_cv_func_shl_load = yes; then lt_cv_dlopen="shl_load" else { echo "$as_me:$LINENO: checking for shl_load in -ldld" >&5 echo $ECHO_N "checking for shl_load in -ldld... $ECHO_C" >&6; } if test "${ac_cv_lib_dld_shl_load+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $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 GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char shl_load (); int main () { return shl_load (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_dld_shl_load=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_dld_shl_load=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_dld_shl_load" >&5 echo "${ECHO_T}$ac_cv_lib_dld_shl_load" >&6; } if test $ac_cv_lib_dld_shl_load = yes; then lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-dld" else { echo "$as_me:$LINENO: checking for dlopen" >&5 echo $ECHO_N "checking for dlopen... $ECHO_C" >&6; } if test "${ac_cv_func_dlopen+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 dlopen to an innocuous variant, in case declares dlopen. For example, HP-UX 11i declares gettimeofday. */ #define dlopen innocuous_dlopen /* System header to define __stub macros and hopefully few prototypes, which can conflict with char dlopen (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef dlopen /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); /* 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_dlopen || defined __stub___dlopen choke me #endif int main () { return dlopen (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_func_dlopen=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func_dlopen=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_func_dlopen" >&5 echo "${ECHO_T}$ac_cv_func_dlopen" >&6; } if test $ac_cv_func_dlopen = yes; then lt_cv_dlopen="dlopen" else { echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5 echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6; } if test "${ac_cv_lib_dl_dlopen+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $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 GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_dl_dlopen=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_dl_dlopen=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5 echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6; } if test $ac_cv_lib_dl_dlopen = yes; then lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" else { echo "$as_me:$LINENO: checking for dlopen in -lsvld" >&5 echo $ECHO_N "checking for dlopen in -lsvld... $ECHO_C" >&6; } if test "${ac_cv_lib_svld_dlopen+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsvld $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 GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_svld_dlopen=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_svld_dlopen=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_svld_dlopen" >&5 echo "${ECHO_T}$ac_cv_lib_svld_dlopen" >&6; } if test $ac_cv_lib_svld_dlopen = yes; then lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld" else { echo "$as_me:$LINENO: checking for dld_link in -ldld" >&5 echo $ECHO_N "checking for dld_link in -ldld... $ECHO_C" >&6; } if test "${ac_cv_lib_dld_dld_link+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $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 GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dld_link (); int main () { return dld_link (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_dld_dld_link=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_dld_dld_link=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_dld_dld_link" >&5 echo "${ECHO_T}$ac_cv_lib_dld_dld_link" >&6; } if test $ac_cv_lib_dld_dld_link = yes; then lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld" fi fi fi fi fi fi ;; esac if test "x$lt_cv_dlopen" != xno; then enable_dlopen=yes else enable_dlopen=no fi case $lt_cv_dlopen in dlopen) save_CPPFLAGS="$CPPFLAGS" test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" save_LDFLAGS="$LDFLAGS" eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" save_LIBS="$LIBS" LIBS="$lt_cv_dlopen_libs $LIBS" { echo "$as_me:$LINENO: checking whether a program can dlopen itself" >&5 echo $ECHO_N "checking whether a program can dlopen itself... $ECHO_C" >&6; } if test "${lt_cv_dlopen_self+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test "$cross_compiling" = yes; then : lt_cv_dlopen_self=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext < #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif #ifdef __cplusplus extern "C" void exit (int); #endif void fnord() { int i=42;} int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; /* dlclose (self); */ } exit (status); } EOF 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); } && test -s conftest${ac_exeext} 2>/dev/null; then (./conftest; exit; ) 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; x$lt_unknown|x*) lt_cv_dlopen_self=no ;; esac else : # compilation failed lt_cv_dlopen_self=no fi fi rm -fr conftest* fi { echo "$as_me:$LINENO: result: $lt_cv_dlopen_self" >&5 echo "${ECHO_T}$lt_cv_dlopen_self" >&6; } if test "x$lt_cv_dlopen_self" = xyes; then LDFLAGS="$LDFLAGS $link_static_flag" { echo "$as_me:$LINENO: checking whether a statically linked program can dlopen itself" >&5 echo $ECHO_N "checking whether a statically linked program can dlopen itself... $ECHO_C" >&6; } if test "${lt_cv_dlopen_self_static+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test "$cross_compiling" = yes; then : lt_cv_dlopen_self_static=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext < #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif #ifdef __cplusplus extern "C" void exit (int); #endif void fnord() { int i=42;} int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; /* dlclose (self); */ } exit (status); } EOF 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); } && test -s conftest${ac_exeext} 2>/dev/null; then (./conftest; exit; ) 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; x$lt_unknown|x*) lt_cv_dlopen_self_static=no ;; esac else : # compilation failed lt_cv_dlopen_self_static=no fi fi rm -fr conftest* fi { echo "$as_me:$LINENO: result: $lt_cv_dlopen_self_static" >&5 echo "${ECHO_T}$lt_cv_dlopen_self_static" >&6; } fi CPPFLAGS="$save_CPPFLAGS" LDFLAGS="$save_LDFLAGS" LIBS="$save_LIBS" ;; esac case $lt_cv_dlopen_self in yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; *) enable_dlopen_self=unknown ;; esac case $lt_cv_dlopen_self_static in yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; *) enable_dlopen_self_static=unknown ;; esac fi # Report which librarie types wil actually be built { echo "$as_me:$LINENO: checking if libtool supports shared libraries" >&5 echo $ECHO_N "checking if libtool supports shared libraries... $ECHO_C" >&6; } { echo "$as_me:$LINENO: result: $can_build_shared" >&5 echo "${ECHO_T}$can_build_shared" >&6; } { echo "$as_me:$LINENO: checking whether to build shared libraries" >&5 echo $ECHO_N "checking whether to build shared libraries... $ECHO_C" >&6; } test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case "$host_os" in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix4*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; darwin* | rhapsody*) if test "$GCC" = yes; then archive_cmds_need_lc=no case "$host_os" in rhapsody* | darwin1.[012]) allow_undefined_flag='-undefined suppress' ;; *) # Darwin 1.3 on if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then allow_undefined_flag='-flat_namespace -undefined suppress' else case ${MACOSX_DEPLOYMENT_TARGET} in 10.[012]) allow_undefined_flag='-flat_namespace -undefined suppress' ;; 10.*) allow_undefined_flag='-undefined dynamic_lookup' ;; esac fi ;; esac output_verbose_link_cmd='echo' archive_cmds='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs$compiler_flags -install_name $rpath/$soname $verstring' module_cmds='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's archive_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs$compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' module_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' hardcode_direct=no hardcode_automatic=yes hardcode_shlibpath_var=unsupported whole_archive_flag_spec='-all_load $convenience' link_all_deplibs=yes else ld_shlibs=no fi ;; esac { echo "$as_me:$LINENO: result: $enable_shared" >&5 echo "${ECHO_T}$enable_shared" >&6; } { echo "$as_me:$LINENO: checking whether to build static libraries" >&5 echo $ECHO_N "checking whether to build static libraries... $ECHO_C" >&6; } # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes { echo "$as_me:$LINENO: result: $enable_static" >&5 echo "${ECHO_T}$enable_static" >&6; } # The else clause should only fire when bootstrapping the # libtool distribution, otherwise you forgot to ship ltmain.sh # with your package, and you will get complaints that there are # no rules to generate ltmain.sh. if test -f "$ltmain"; then # See if we are running on zsh, and set the options which allow our commands through # without removal of \ escapes. if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi # Now quote all the things that may contain metacharacters while being # careful not to overquote the AC_SUBSTed values. We take copies of the # variables and quote the copies for generation of the libtool script. for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC NM SED SHELL \ libname_spec library_names_spec soname_spec extract_expsyms_cmds \ old_striplib striplib file_magic_cmd finish_cmds finish_eval \ deplibs_check_method reload_flag reload_cmds need_locks \ lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \ lt_cv_sys_global_symbol_to_c_name_address \ sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ old_postinstall_cmds old_postuninstall_cmds \ compiler \ CC \ LD \ lt_prog_compiler_wl \ lt_prog_compiler_pic \ lt_prog_compiler_static \ lt_prog_compiler_no_builtin_flag \ export_dynamic_flag_spec \ thread_safe_flag_spec \ whole_archive_flag_spec \ enable_shared_with_static_runtimes \ old_archive_cmds \ old_archive_from_new_cmds \ predep_objects \ postdep_objects \ predeps \ postdeps \ compiler_lib_search_path \ archive_cmds \ archive_expsym_cmds \ postinstall_cmds \ postuninstall_cmds \ old_archive_from_expsyms_cmds \ allow_undefined_flag \ no_undefined_flag \ export_symbols_cmds \ hardcode_libdir_flag_spec \ hardcode_libdir_flag_spec_ld \ hardcode_libdir_separator \ hardcode_automatic \ module_cmds \ module_expsym_cmds \ lt_cv_prog_compiler_c_o \ exclude_expsyms \ include_expsyms; do case $var in old_archive_cmds | \ old_archive_from_new_cmds | \ archive_cmds | \ archive_expsym_cmds | \ module_cmds | \ module_expsym_cmds | \ old_archive_from_expsyms_cmds | \ export_symbols_cmds | \ extract_expsyms_cmds | reload_cmds | finish_cmds | \ postinstall_cmds | postuninstall_cmds | \ old_postinstall_cmds | old_postuninstall_cmds | \ sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) # Double-quote double-evaled strings. eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" ;; *) eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" ;; esac done case $lt_echo in *'\$0 --fallback-echo"') lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'` ;; esac cfgfile="${ofile}T" trap "$rm \"$cfgfile\"; exit 1" 1 2 15 $rm -f "$cfgfile" { echo "$as_me:$LINENO: creating $ofile" >&5 echo "$as_me: creating $ofile" >&6;} cat <<__EOF__ >> "$cfgfile" #! $SHELL # `$echo "$cfgfile" | sed 's%^.*/%%'` - Provide generalized library-building support services. # Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP) # NOTE: Changes made to this file will be lost: look at ltmain.sh. # # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 # Free Software Foundation, Inc. # # This file is part of GNU Libtool: # 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. # A sed program that does not truncate output. SED=$lt_SED # Sed that helps us avoid accidentally triggering echo(1) options like -n. Xsed="$SED -e s/^X//" # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. if test "X\${CDPATH+set}" = Xset; then CDPATH=:; export CDPATH; fi # The names of the tagged configurations supported by this script. available_tags= # ### BEGIN LIBTOOL CONFIG # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # Shell to use when invoking shell scripts. SHELL=$lt_SHELL # Whether or not to build shared libraries. build_libtool_libs=$enable_shared # Whether or not to build static libraries. build_old_libs=$enable_static # Whether or not to add -lc for building shared libraries. build_libtool_need_lc=$archive_cmds_need_lc # Whether or not to disallow shared libs when runtime libs are static allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes # Whether or not to optimize for fast installation. fast_install=$enable_fast_install # The host system. host_alias=$host_alias host=$host # An echo program that does not interpret backslashes. echo=$lt_echo # The archiver. AR=$lt_AR AR_FLAGS=$lt_AR_FLAGS # A C compiler. LTCC=$lt_LTCC # A language-specific compiler. CC=$lt_compiler # Is the compiler the GNU C compiler? with_gcc=$GCC # An ERE matcher. EGREP=$lt_EGREP # The linker used to build libraries. LD=$lt_LD # Whether we need hard or soft links. LN_S=$lt_LN_S # A BSD-compatible nm program. NM=$lt_NM # A symbol stripping program STRIP=$STRIP # Used to examine libraries when file_magic_cmd begins "file" MAGIC_CMD=$MAGIC_CMD # Used on cygwin: DLL creation program. DLLTOOL="$DLLTOOL" # Used on cygwin: object dumper. OBJDUMP="$OBJDUMP" # Used on cygwin: assembler. AS="$AS" # The name of the directory that contains temporary libtool files. objdir=$objdir # How to create reloadable object files. reload_flag=$lt_reload_flag reload_cmds=$lt_reload_cmds # How to pass a linker flag through the compiler. wl=$lt_lt_prog_compiler_wl # Object file suffix (normally "o"). objext="$ac_objext" # Old archive suffix (normally "a"). libext="$libext" # Shared library suffix (normally ".so"). shrext='$shrext' # Executable file suffix (normally ""). exeext="$exeext" # Additional compiler flags for building library objects. pic_flag=$lt_lt_prog_compiler_pic pic_mode=$pic_mode # What is the maximum length of a command? max_cmd_len=$lt_cv_sys_max_cmd_len # Does compiler simultaneously support -c and -o options? compiler_c_o=$lt_lt_cv_prog_compiler_c_o # Must we lock files when doing compilation ? need_locks=$lt_need_locks # Do we need the lib prefix for modules? need_lib_prefix=$need_lib_prefix # Do we need a version for libraries? need_version=$need_version # Whether dlopen is supported. dlopen_support=$enable_dlopen # Whether dlopen of programs is supported. dlopen_self=$enable_dlopen_self # Whether dlopen of statically linked programs is supported. dlopen_self_static=$enable_dlopen_self_static # Compiler flag to prevent dynamic linking. link_static_flag=$lt_lt_prog_compiler_static # Compiler flag to turn off builtin functions. no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag # Compiler flag to allow reflexive dlopens. export_dynamic_flag_spec=$lt_export_dynamic_flag_spec # Compiler flag to generate shared objects directly from archives. whole_archive_flag_spec=$lt_whole_archive_flag_spec # Compiler flag to generate thread-safe objects. thread_safe_flag_spec=$lt_thread_safe_flag_spec # Library versioning type. version_type=$version_type # Format of library name prefix. libname_spec=$lt_libname_spec # List of archive names. First name is the real one, the rest are links. # The last name is the one that the linker finds with -lNAME. library_names_spec=$lt_library_names_spec # The coded name of the library, if different from the real name. soname_spec=$lt_soname_spec # Commands used to build and install an old-style archive. RANLIB=$lt_RANLIB old_archive_cmds=$lt_old_archive_cmds old_postinstall_cmds=$lt_old_postinstall_cmds old_postuninstall_cmds=$lt_old_postuninstall_cmds # Create an old-style archive from a shared archive. old_archive_from_new_cmds=$lt_old_archive_from_new_cmds # Create a temporary old-style archive to link instead of a shared archive. old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds # Commands used to build and install a shared archive. archive_cmds=$lt_archive_cmds archive_expsym_cmds=$lt_archive_expsym_cmds postinstall_cmds=$lt_postinstall_cmds postuninstall_cmds=$lt_postuninstall_cmds # Commands used to build a loadable module (assumed same as above if empty) module_cmds=$lt_module_cmds module_expsym_cmds=$lt_module_expsym_cmds # Commands to strip libraries. old_striplib=$lt_old_striplib striplib=$lt_striplib # Dependencies to place before the objects being linked to create a # shared library. predep_objects=$lt_predep_objects # Dependencies to place after the objects being linked to create a # shared library. postdep_objects=$lt_postdep_objects # Dependencies to place before the objects being linked to create a # shared library. predeps=$lt_predeps # Dependencies to place after the objects being linked to create a # shared library. postdeps=$lt_postdeps # The library search path used internally by the compiler when linking # a shared library. compiler_lib_search_path=$lt_compiler_lib_search_path # Method to check whether dependent libraries are shared objects. deplibs_check_method=$lt_deplibs_check_method # Command to use when deplibs_check_method == file_magic. file_magic_cmd=$lt_file_magic_cmd # Flag that allows shared libraries with undefined symbols to be built. allow_undefined_flag=$lt_allow_undefined_flag # Flag that forces no undefined symbols. no_undefined_flag=$lt_no_undefined_flag # Commands used to finish a libtool library installation in a directory. finish_cmds=$lt_finish_cmds # Same as above, but a single script fragment to be evaled but not shown. finish_eval=$lt_finish_eval # Take the output of nm and produce a listing of raw symbols and C names. global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe # Transform the output of nm in a proper C declaration global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl # Transform the output of nm in a C name address pair global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address # This is the shared library runtime path variable. runpath_var=$runpath_var # This is the shared library path variable. shlibpath_var=$shlibpath_var # Is shlibpath searched before the hard-coded library search path? shlibpath_overrides_runpath=$shlibpath_overrides_runpath # How to hardcode a shared library path into an executable. hardcode_action=$hardcode_action # Whether we should hardcode library paths into libraries. hardcode_into_libs=$hardcode_into_libs # Flag to hardcode \$libdir into a binary during linking. # This must work even if \$libdir does not exist. hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec # If ld is used when linking, flag to hardcode \$libdir into # a binary during linking. This must work even if \$libdir does # not exist. hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld # Whether we need a single -rpath flag with a separated argument. hardcode_libdir_separator=$lt_hardcode_libdir_separator # Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the # resulting binary. hardcode_direct=$hardcode_direct # Set to yes if using the -LDIR flag during linking hardcodes DIR into the # resulting binary. hardcode_minus_L=$hardcode_minus_L # Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into # the resulting binary. hardcode_shlibpath_var=$hardcode_shlibpath_var # Set to yes if building a shared library automatically hardcodes DIR into the library # and all subsequent libraries and executables linked against it. hardcode_automatic=$hardcode_automatic # Variables whose values should be saved in libtool wrapper scripts and # restored at relink time. variables_saved_for_relink="$variables_saved_for_relink" # Whether libtool must link a program against all its dependency libraries. link_all_deplibs=$link_all_deplibs # Compile-time system search path for libraries sys_lib_search_path_spec=$lt_sys_lib_search_path_spec # Run-time system search path for libraries sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec # Fix the shell variable \$srcfile for the compiler. fix_srcfile_path="$fix_srcfile_path" # Set to yes if exported symbols are required. always_export_symbols=$always_export_symbols # The commands to list exported symbols. export_symbols_cmds=$lt_export_symbols_cmds # The commands to extract the exported symbol list from a shared archive. extract_expsyms_cmds=$lt_extract_expsyms_cmds # Symbols that should not be listed in the preloaded symbols. exclude_expsyms=$lt_exclude_expsyms # Symbols that must always be exported. include_expsyms=$lt_include_expsyms # ### END LIBTOOL CONFIG __EOF__ case $host_os in aix3*) cat <<\EOF >> "$cfgfile" # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi EOF ;; esac # We use sed instead of cat because bash on DJGPP gets confused if # if finds mixed CR/LF and LF-only lines. Since sed operates in # text mode, it properly converts lines to CR/LF. This bash problem # is reportedly fixed, but why not run on old versions too? sed '$q' "$ltmain" >> "$cfgfile" || (rm -f "$cfgfile"; exit 1) mv -f "$cfgfile" "$ofile" || \ (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") chmod +x "$ofile" else # If there is no Makefile yet, we rely on a make rule to execute # `config.status --recheck' to rerun these tests and create the # libtool script then. test -f Makefile && make "$ltmain" fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu CC="$lt_save_CC" # Check whether --with-tags was given. if test "${with_tags+set}" = set; then withval=$with_tags; tagnames="$withval" fi if test -f "$ltmain" && test -n "$tagnames"; then if test ! -f "${ofile}"; then { echo "$as_me:$LINENO: WARNING: output file \`$ofile' does not exist" >&5 echo "$as_me: WARNING: output file \`$ofile' does not exist" >&2;} fi if test -z "$LTCC"; then eval "`$SHELL ${ofile} --config | grep '^LTCC='`" if test -z "$LTCC"; then { echo "$as_me:$LINENO: WARNING: output file \`$ofile' does not look like a libtool script" >&5 echo "$as_me: WARNING: output file \`$ofile' does not look like a libtool script" >&2;} else { echo "$as_me:$LINENO: WARNING: using \`LTCC=$LTCC', extracted from \`$ofile'" >&5 echo "$as_me: WARNING: using \`LTCC=$LTCC', extracted from \`$ofile'" >&2;} fi fi # Extract list of available tagged configurations in $ofile. # Note that this assumes the entire list is on one line. available_tags=`grep "^available_tags=" "${ofile}" | $SED -e 's/available_tags=\(.*$\)/\1/' -e 's/\"//g'` lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for tagname in $tagnames; do IFS="$lt_save_ifs" # Check whether tagname contains only valid characters case `$echo "X$tagname" | $Xsed -e 's:[-_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890,/]::g'` in "") ;; *) { { echo "$as_me:$LINENO: error: invalid tag name: $tagname" >&5 echo "$as_me: error: invalid tag name: $tagname" >&2;} { (exit 1); exit 1; }; } ;; esac if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "${ofile}" > /dev/null then { { echo "$as_me:$LINENO: error: tag name \"$tagname\" already exists" >&5 echo "$as_me: error: tag name \"$tagname\" already exists" >&2;} { (exit 1); exit 1; }; } fi # Update the list of available tags. if test -n "$tagname"; then echo appending configuration tag \"$tagname\" to $ofile case $tagname in CXX) if test -n "$CXX" && test "X$CXX" != "Xno"; then ac_ext=cpp 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 archive_cmds_need_lc_CXX=no allow_undefined_flag_CXX= always_export_symbols_CXX=no archive_expsym_cmds_CXX= export_dynamic_flag_spec_CXX= hardcode_direct_CXX=no hardcode_libdir_flag_spec_CXX= hardcode_libdir_flag_spec_ld_CXX= hardcode_libdir_separator_CXX= hardcode_minus_L_CXX=no hardcode_automatic_CXX=no module_cmds_CXX= module_expsym_cmds_CXX= link_all_deplibs_CXX=unknown old_archive_cmds_CXX=$old_archive_cmds no_undefined_flag_CXX= whole_archive_flag_spec_CXX= enable_shared_with_static_runtimes_CXX=no # Dependencies to place before and after the object being linked: predep_objects_CXX= postdep_objects_CXX= predeps_CXX= postdeps_CXX= compiler_lib_search_path_CXX= # Source file extension for C++ test sources. ac_ext=cc # Object file extension for compiled C++ test sources. objext=o objext_CXX=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;\n" # Code to be used in simple link tests lt_simple_link_test_code='int main(int, char *) { return(0); }\n' # ltmain only uses $CC for tagged configurations so make sure $CC is set. # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # Allow CC to be a program name with arguments. compiler=$CC # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_LD=$LD lt_save_GCC=$GCC GCC=$GXX lt_save_with_gnu_ld=$with_gnu_ld lt_save_path_LD=$lt_cv_path_LD if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx else unset lt_cv_prog_gnu_ld fi if test -n "${lt_cv_path_LDCXX+set}"; then lt_cv_path_LD=$lt_cv_path_LDCXX else unset lt_cv_path_LD fi test -z "${LDCXX+set}" || LD=$LDCXX CC=${CXX-"c++"} compiler=$CC compiler_CXX=$CC cc_basename=`$echo X"$compiler" | $Xsed -e 's%^.*/%%'` # We don't want -fno-exception wen compiling C++ code, so set the # no_builtin_flag separately if test "$GXX" = yes; then lt_prog_compiler_no_builtin_flag_CXX=' -fno-builtin' else lt_prog_compiler_no_builtin_flag_CXX= fi if test "$GXX" = yes; then # Set up default GNU C++ configuration # Check whether --with-gnu-ld was given. if test "${with_gnu_ld+set}" = set; then withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes else with_gnu_ld=no fi 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 $CC" >&5 echo $ECHO_N "checking for ld used by $CC... $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. [\\/]* | ?:[\\/]*) re_direlt='/[^/][^/]*/\.\./' # Canonicalize the pathname of ld ac_prog=`echo $ac_prog| $SED 's%\\\\%/%g'` while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do ac_prog=`echo $ac_prog| $SED "s%$re_direlt%/%"` done test -z "$LD" && LD="$ac_prog" ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test "$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 "${lt_cv_path_LD+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -z "$LD"; then lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD="$ac_dir/$ac_prog" # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some GNU ld's only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &5 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 "${lt_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}$lt_cv_prog_gnu_ld" >&6; } with_gnu_ld=$lt_cv_prog_gnu_ld # Check if GNU C++ uses GNU ld as the underlying linker, since the # archiving commands below assume that GNU ld is being used. if test "$with_gnu_ld" = yes; then archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' hardcode_libdir_flag_spec_CXX='${wl}--rpath ${wl}$libdir' export_dynamic_flag_spec_CXX='${wl}--export-dynamic' # If archive_cmds runs LD, not CC, wlarc should be empty # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to # investigate it a little bit more. (MM) wlarc='${wl}' # ancient GNU ld didn't support --whole-archive et. al. if eval "`$CC -print-prog-name=ld` --help 2>&1" | \ grep 'no-whole-archive' > /dev/null; then whole_archive_flag_spec_CXX="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else whole_archive_flag_spec_CXX= fi else with_gnu_ld=no wlarc= # A generic and very simple default shared library creation # command for GNU C++ for the case where it uses the native # linker, instead of GNU ld. If possible, this setting should # overridden to take advantage of the native linker features on # the platform it is being used on. archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' fi # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' else GXX=no with_gnu_ld=no wlarc= fi # PORTME: fill in a description of your system's C++ link characteristics { echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5 echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6; } ld_shlibs_CXX=yes case $host_os in aix3*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; 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 exp_sym_flag='-Bexport' no_entry_flag="" else aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[23]|aix4.[23].*|aix5*) for ld_flag in $LDFLAGS; do case $ld_flag in *-brtl*) aix_use_runtimelinking=yes break ;; esac done esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. archive_cmds_CXX='' hardcode_direct_CXX=yes hardcode_libdir_separator_CXX=':' link_all_deplibs_CXX=yes if test "$GXX" = yes; then case $host_os in aix4.012|aix4.012.*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && \ strings "$collect2name" | grep resolve_lib_name >/dev/null then # We have reworked collect2 hardcode_direct_CXX=yes else # We have old collect2 hardcode_direct_CXX=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking hardcode_minus_L_CXX=yes hardcode_libdir_flag_spec_CXX='-L$libdir' hardcode_libdir_separator_CXX= fi esac shared_flag='-shared' else # not using gcc if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi fi # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. always_export_symbols_CXX=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. allow_undefined_flag_CXX='-berok' # Determine the default libpath from the value encoded in an empty executable. 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 { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'` # Check for a 64-bit object if we didn't find anything. if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'`; fi else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi hardcode_libdir_flag_spec_CXX='${wl}-blibpath:$libdir:'"$aix_libpath" archive_expsym_cmds_CXX="\$CC"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then hardcode_libdir_flag_spec_CXX='${wl}-R $libdir:/usr/lib:/lib' allow_undefined_flag_CXX="-z nodefs" archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an empty executable. 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 { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'` # Check for a 64-bit object if we didn't find anything. if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'`; fi else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi hardcode_libdir_flag_spec_CXX='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. no_undefined_flag_CXX=' ${wl}-bernotok' allow_undefined_flag_CXX=' ${wl}-berok' # -bexpall does not export symbols beginning with underscore (_) always_export_symbols_CXX=yes # Exported symbols can be pulled into shared objects from archives whole_archive_flag_spec_CXX=' ' archive_cmds_need_lc_CXX=yes # This is similar to how AIX traditionally builds it's shared libraries. archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; chorus*) case $cc_basename in *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac ;; cygwin* | mingw* | pw32*) # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, CXX) is actually meaningless, # as there is no search path for DLLs. hardcode_libdir_flag_spec_CXX='-L$libdir' allow_undefined_flag_CXX=unsupported always_export_symbols_CXX=no enable_shared_with_static_runtimes_CXX=yes if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... archive_expsym_cmds_CXX='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib' else ld_shlibs_CXX=no fi ;; darwin* | rhapsody*) if test "$GXX" = yes; then archive_cmds_need_lc_CXX=no case "$host_os" in rhapsody* | darwin1.[012]) allow_undefined_flag_CXX='-undefined suppress' ;; *) # Darwin 1.3 on if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then allow_undefined_flag_CXX='-flat_namespace -undefined suppress' else case ${MACOSX_DEPLOYMENT_TARGET} in 10.[012]) allow_undefined_flag_CXX='-flat_namespace -undefined suppress' ;; 10.*) allow_undefined_flag_CXX='-undefined dynamic_lookup' ;; esac fi ;; esac lt_int_apple_cc_single_mod=no output_verbose_link_cmd='echo' if $CC -dumpspecs 2>&1 | grep 'single_module' >/dev/null ; then lt_int_apple_cc_single_mod=yes fi if test "X$lt_int_apple_cc_single_mod" = Xyes ; then archive_cmds_CXX='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' else archive_cmds_CXX='$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring' fi module_cmds_CXX='$CC ${wl}-bind_at_load $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's if test "X$lt_int_apple_cc_single_mod" = Xyes ; then archive_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' else archive_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' fi module_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' hardcode_direct_CXX=no hardcode_automatic_CXX=yes hardcode_shlibpath_var_CXX=unsupported whole_archive_flag_spec_CXX='-all_load $convenience' link_all_deplibs_CXX=yes else ld_shlibs_CXX=no fi ;; dgux*) case $cc_basename in ec++) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; ghcx) # Green Hills C++ Compiler # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac ;; freebsd12*) # C++ shared libraries reported to be fairly broken before switch to ELF ld_shlibs_CXX=no ;; freebsd-elf*) archive_cmds_need_lc_CXX=no ;; freebsd* | kfreebsd*-gnu) # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF # conventions ld_shlibs_CXX=yes ;; gnu*) ;; hpux9*) hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir' hardcode_libdir_separator_CXX=: export_dynamic_flag_spec_CXX='${wl}-E' hardcode_direct_CXX=yes hardcode_minus_L_CXX=yes # Not in the search PATH, # but as the default # location of the library. case $cc_basename in CC) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; aCC) archive_cmds_CXX='$rm $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | egrep "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' ;; *) if test "$GXX" = yes; then archive_cmds_CXX='$rm $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else # FIXME: insert proper C++ library support ld_shlibs_CXX=no fi ;; esac ;; hpux10*|hpux11*) if test $with_gnu_ld = no; then case "$host_cpu" in hppa*64*) hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir' hardcode_libdir_flag_spec_ld_CXX='+b $libdir' hardcode_libdir_separator_CXX=: ;; ia64*) hardcode_libdir_flag_spec_CXX='-L$libdir' ;; *) hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir' hardcode_libdir_separator_CXX=: export_dynamic_flag_spec_CXX='${wl}-E' ;; esac fi case "$host_cpu" in hppa*64*) hardcode_direct_CXX=no hardcode_shlibpath_var_CXX=no ;; ia64*) hardcode_direct_CXX=no hardcode_shlibpath_var_CXX=no hardcode_minus_L_CXX=yes # Not in the search PATH, # but as the default # location of the library. ;; *) hardcode_direct_CXX=yes hardcode_minus_L_CXX=yes # Not in the search PATH, # but as the default # location of the library. ;; esac case $cc_basename in CC) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; aCC) case "$host_cpu" in hppa*64*|ia64*) archive_cmds_CXX='$LD -b +h $soname -o $lib $linker_flags $libobjs $deplibs' ;; *) archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' ;; *) if test "$GXX" = yes; then if test $with_gnu_ld = no; then case "$host_cpu" in ia64*|hppa*64*) archive_cmds_CXX='$LD -b +h $soname -o $lib $linker_flags $libobjs $deplibs' ;; *) archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac fi else # FIXME: insert proper C++ library support ld_shlibs_CXX=no fi ;; esac ;; irix5* | irix6*) case $cc_basename in CC) # SGI C++ archive_cmds_CXX='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib' # Archives containing C++ object files must be created using # "CC -ar", where "CC" is the IRIX C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. old_archive_cmds_CXX='$CC -ar -WR,-u -o $oldlib $oldobjs' ;; *) if test "$GXX" = yes; then if test "$with_gnu_ld" = no; then archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib' else archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` -o $lib' fi fi link_all_deplibs_CXX=yes ;; esac hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator_CXX=: ;; linux*) case $cc_basename in KCC) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' archive_expsym_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | grep "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' hardcode_libdir_flag_spec_CXX='${wl}--rpath,$libdir' export_dynamic_flag_spec_CXX='${wl}--export-dynamic' # Archives containing C++ object files must be created using # "CC -Bstatic", where "CC" is the KAI C++ compiler. old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs' ;; icpc) # Intel C++ with_gnu_ld=yes archive_cmds_need_lc_CXX=no archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' export_dynamic_flag_spec_CXX='${wl}--export-dynamic' whole_archive_flag_spec_CXX='${wl}--whole-archive$convenience ${wl}--no-whole-archive' ;; cxx) # Compaq C++ archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols' runpath_var=LD_RUN_PATH hardcode_libdir_flag_spec_CXX='-rpath $libdir' hardcode_libdir_separator_CXX=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' ;; esac ;; lynxos*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; m88k*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; mvs*) case $cc_basename in cxx) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac ;; netbsd*) if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then archive_cmds_CXX='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' wlarc= hardcode_libdir_flag_spec_CXX='-R$libdir' hardcode_direct_CXX=yes hardcode_shlibpath_var_CXX=no fi # Workaround some broken pre-1.5 toolchains output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' ;; osf3*) case $cc_basename in KCC) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' hardcode_libdir_separator_CXX=: # Archives containing C++ object files must be created using # "CC -Bstatic", where "CC" is the KAI C++ compiler. old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs' ;; RCC) # Rational C++ 2.4.1 # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; cxx) allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*' archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && echo ${wl}-set_version $verstring` -update_registry ${objdir}/so_locations -o $lib' hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator_CXX=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' ;; *) if test "$GXX" = yes && test "$with_gnu_ld" = no; then allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*' archive_cmds_CXX='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib' hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator_CXX=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' else # FIXME: insert proper C++ library support ld_shlibs_CXX=no fi ;; esac ;; osf4* | osf5*) case $cc_basename in KCC) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' hardcode_libdir_separator_CXX=: # Archives containing C++ object files must be created using # the KAI C++ compiler. old_archive_cmds_CXX='$CC -o $oldlib $oldobjs' ;; RCC) # Rational C++ 2.4.1 # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; cxx) allow_undefined_flag_CXX=' -expect_unresolved \*' archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib' archive_expsym_cmds_CXX='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ echo "-hidden">> $lib.exp~ $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname -Wl,-input -Wl,$lib.exp `test -n "$verstring" && echo -set_version $verstring` -update_registry $objdir/so_locations -o $lib~ $rm $lib.exp' hardcode_libdir_flag_spec_CXX='-rpath $libdir' hardcode_libdir_separator_CXX=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' ;; *) if test "$GXX" = yes && test "$with_gnu_ld" = no; then allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*' archive_cmds_CXX='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib' hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator_CXX=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' else # FIXME: insert proper C++ library support ld_shlibs_CXX=no fi ;; esac ;; psos*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; sco*) archive_cmds_need_lc_CXX=no case $cc_basename in CC) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac ;; sunos4*) case $cc_basename in CC) # Sun C++ 4.x # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; lcc) # Lucid # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac ;; solaris*) case $cc_basename in CC) # Sun C++ 4.2, 5.x and Centerline C++ no_undefined_flag_CXX=' -zdefs' archive_cmds_CXX='$CC -G${allow_undefined_flag} -nolib -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' archive_expsym_cmds_CXX='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $CC -G${allow_undefined_flag} -nolib ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' hardcode_libdir_flag_spec_CXX='-R$libdir' hardcode_shlibpath_var_CXX=no case $host_os in solaris2.0-5 | solaris2.0-5.*) ;; *) # The C++ compiler is used as linker so we must use $wl # flag to pass the commands to the underlying system # linker. # Supported since Solaris 2.6 (maybe 2.5.1?) whole_archive_flag_spec_CXX='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' ;; esac link_all_deplibs_CXX=yes # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -G $CFLAGS -v conftest.$objext 2>&1 | grep "\-[LR]"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs' ;; gcx) # Green Hills C++ Compiler archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' # The C++ compiler must be used to create the archive. old_archive_cmds_CXX='$CC $LDFLAGS -archive -o $oldlib $oldobjs' ;; *) # GNU C++ compiler with Solaris linker if test "$GXX" = yes && test "$with_gnu_ld" = no; then no_undefined_flag_CXX=' ${wl}-z ${wl}defs' if $CC --version | grep -v '^2\.7' > /dev/null; then archive_cmds_CXX='$CC -shared -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' archive_expsym_cmds_CXX='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $CC -shared -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd="$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\"" else # g++ 2.7 appears to require `-G' NOT `-shared' on this # platform. archive_cmds_CXX='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' archive_expsym_cmds_CXX='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd="$CC -G $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\"" fi hardcode_libdir_flag_spec_CXX='${wl}-R $wl$libdir' fi ;; esac ;; sysv5OpenUNIX8* | sysv5UnixWare7* | sysv5uw[78]* | unixware7*) archive_cmds_need_lc_CXX=no ;; tandem*) case $cc_basename in NCC) # NonStop-UX NCC 3.20 # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac ;; vxworks*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac { echo "$as_me:$LINENO: result: $ld_shlibs_CXX" >&5 echo "${ECHO_T}$ld_shlibs_CXX" >&6; } test "$ld_shlibs_CXX" = no && can_build_shared=no GCC_CXX="$GXX" LD_CXX="$LD" ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... cat > conftest.$ac_ext <&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then # Parse the compiler output and extract the necessary # objects, libraries and library flags. # Sentinel used to keep track of whether or not we are before # the conftest object file. pre_test_object_deps_done=no # The `*' in the case matches for architectures that use `case' in # $output_verbose_cmd can trigger glob expansion during the loop # eval without this substitution. output_verbose_link_cmd="`$echo \"X$output_verbose_link_cmd\" | $Xsed -e \"$no_glob_subst\"`" for p in `eval $output_verbose_link_cmd`; do case $p in -L* | -R* | -l*) # Some compilers place space between "-{L,R}" and the path. # Remove the space. if test $p = "-L" \ || test $p = "-R"; then prev=$p continue else prev= fi if test "$pre_test_object_deps_done" = no; then case $p in -L* | -R*) # Internal compiler library paths should come after those # provided the user. The postdeps already come after the # user supplied libs so there is no need to process them. if test -z "$compiler_lib_search_path_CXX"; then compiler_lib_search_path_CXX="${prev}${p}" else compiler_lib_search_path_CXX="${compiler_lib_search_path_CXX} ${prev}${p}" fi ;; # The "-l" case would never come before the object being # linked, so don't bother handling this case. esac else if test -z "$postdeps_CXX"; then postdeps_CXX="${prev}${p}" else postdeps_CXX="${postdeps_CXX} ${prev}${p}" fi fi ;; *.$objext) # This assumes that the test object file only shows up # once in the compiler output. if test "$p" = "conftest.$objext"; then pre_test_object_deps_done=yes continue fi if test "$pre_test_object_deps_done" = no; then if test -z "$predep_objects_CXX"; then predep_objects_CXX="$p" else predep_objects_CXX="$predep_objects_CXX $p" fi else if test -z "$postdep_objects_CXX"; then postdep_objects_CXX="$p" else postdep_objects_CXX="$postdep_objects_CXX $p" fi fi ;; *) ;; # Ignore the rest. esac done # Clean up. rm -f a.out a.exe else echo "libtool.m4: error: problem compiling CXX test program" fi $rm -f confest.$objext case " $postdeps_CXX " in *" -lc "*) archive_cmds_need_lc_CXX=no ;; esac lt_prog_compiler_wl_CXX= lt_prog_compiler_pic_CXX= lt_prog_compiler_static_CXX= { echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5 echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6; } # C++ specific cases for pic, static, wl, etc. if test "$GXX" = yes; then lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_static_CXX='-static' case $host_os in aix*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static_CXX='-Bstatic' fi ;; amigaos*) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. lt_prog_compiler_pic_CXX='-m68020 -resident32 -malways-restore-a4' ;; beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | os2* | pw32*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_prog_compiler_pic_CXX='-DDLL_EXPORT' ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files lt_prog_compiler_pic_CXX='-fno-common' ;; *djgpp*) # DJGPP does not support shared libraries at all lt_prog_compiler_pic_CXX= ;; sysv4*MP*) if test -d /usr/nec; then lt_prog_compiler_pic_CXX=-Kconform_pic fi ;; hpux*) # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case "$host_cpu" in hppa*64*|ia64*) ;; *) lt_prog_compiler_pic_CXX='-fPIC' ;; esac ;; *) lt_prog_compiler_pic_CXX='-fPIC' ;; esac else case $host_os in aix4* | aix5*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static_CXX='-Bstatic' else lt_prog_compiler_static_CXX='-bnso -bI:/lib/syscalls.exp' fi ;; chorus*) case $cc_basename in cxch68) # Green Hills C++ Compiler # _LT_AC_TAGVAR(lt_prog_compiler_static, CXX)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" ;; esac ;; dgux*) case $cc_basename in ec++) lt_prog_compiler_pic_CXX='-KPIC' ;; ghcx) # Green Hills C++ Compiler lt_prog_compiler_pic_CXX='-pic' ;; *) ;; esac ;; freebsd* | kfreebsd*-gnu) # FreeBSD uses GNU C++ ;; hpux9* | hpux10* | hpux11*) case $cc_basename in CC) lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_static_CXX="${ac_cv_prog_cc_wl}-a ${ac_cv_prog_cc_wl}archive" if test "$host_cpu" != ia64; then lt_prog_compiler_pic_CXX='+Z' fi ;; aCC) lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_static_CXX="${ac_cv_prog_cc_wl}-a ${ac_cv_prog_cc_wl}archive" case "$host_cpu" in hppa*64*|ia64*) # +Z the default ;; *) lt_prog_compiler_pic_CXX='+Z' ;; esac ;; *) ;; esac ;; irix5* | irix6* | nonstopux*) case $cc_basename in CC) lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_static_CXX='-non_shared' # CC pic flag -KPIC is the default. ;; *) ;; esac ;; linux*) case $cc_basename in KCC) # KAI C++ Compiler lt_prog_compiler_wl_CXX='--backend -Wl,' lt_prog_compiler_pic_CXX='-fPIC' ;; icpc) # Intel C++ lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_pic_CXX='-KPIC' lt_prog_compiler_static_CXX='-static' ;; cxx) # Compaq C++ # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. lt_prog_compiler_pic_CXX= lt_prog_compiler_static_CXX='-non_shared' ;; *) ;; esac ;; lynxos*) ;; m88k*) ;; mvs*) case $cc_basename in cxx) lt_prog_compiler_pic_CXX='-W c,exportall' ;; *) ;; esac ;; netbsd*) ;; osf3* | osf4* | osf5*) case $cc_basename in KCC) lt_prog_compiler_wl_CXX='--backend -Wl,' ;; RCC) # Rational C++ 2.4.1 lt_prog_compiler_pic_CXX='-pic' ;; cxx) # Digital/Compaq C++ lt_prog_compiler_wl_CXX='-Wl,' # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. lt_prog_compiler_pic_CXX= lt_prog_compiler_static_CXX='-non_shared' ;; *) ;; esac ;; psos*) ;; sco*) case $cc_basename in CC) lt_prog_compiler_pic_CXX='-fPIC' ;; *) ;; esac ;; solaris*) case $cc_basename in CC) # Sun C++ 4.2, 5.x and Centerline C++ lt_prog_compiler_pic_CXX='-KPIC' lt_prog_compiler_static_CXX='-Bstatic' lt_prog_compiler_wl_CXX='-Qoption ld ' ;; gcx) # Green Hills C++ Compiler lt_prog_compiler_pic_CXX='-PIC' ;; *) ;; esac ;; sunos4*) case $cc_basename in CC) # Sun C++ 4.x lt_prog_compiler_pic_CXX='-pic' lt_prog_compiler_static_CXX='-Bstatic' ;; lcc) # Lucid lt_prog_compiler_pic_CXX='-pic' ;; *) ;; esac ;; tandem*) case $cc_basename in NCC) # NonStop-UX NCC 3.20 lt_prog_compiler_pic_CXX='-KPIC' ;; *) ;; esac ;; unixware*) ;; vxworks*) ;; *) lt_prog_compiler_can_build_shared_CXX=no ;; esac fi { echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_CXX" >&5 echo "${ECHO_T}$lt_prog_compiler_pic_CXX" >&6; } # # Check to make sure the PIC flag actually works. # if test -n "$lt_prog_compiler_pic_CXX"; then { echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works" >&5 echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works... $ECHO_C" >&6; } if test "${lt_prog_compiler_pic_works_CXX+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else lt_prog_compiler_pic_works_CXX=no ac_outfile=conftest.$ac_objext printf "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$lt_prog_compiler_pic_CXX -DPIC" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:12131: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:12135: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings if test ! -s conftest.err; then lt_prog_compiler_pic_works_CXX=yes fi fi $rm conftest* fi { echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works_CXX" >&5 echo "${ECHO_T}$lt_prog_compiler_pic_works_CXX" >&6; } if test x"$lt_prog_compiler_pic_works_CXX" = xyes; then case $lt_prog_compiler_pic_CXX in "" | " "*) ;; *) lt_prog_compiler_pic_CXX=" $lt_prog_compiler_pic_CXX" ;; esac else lt_prog_compiler_pic_CXX= lt_prog_compiler_can_build_shared_CXX=no fi fi case "$host_os" in # For platforms which do not support PIC, -DPIC is meaningless: *djgpp*) lt_prog_compiler_pic_CXX= ;; *) lt_prog_compiler_pic_CXX="$lt_prog_compiler_pic_CXX -DPIC" ;; esac { echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5 echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6; } if test "${lt_cv_prog_compiler_c_o_CXX+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else lt_cv_prog_compiler_c_o_CXX=no $rm -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out printf "$lt_simple_compile_test_code" > conftest.$ac_ext # According to Tom Tromey, Ian Lance Taylor reported there are C compilers # that will create temporary files in the current directory regardless of # the output directory. Thus, making CWD read-only will cause this test # to fail, enabling locking or at least warning the user not to do parallel # builds. chmod -w . lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:12198: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:12202: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings if test ! -s out/conftest.err; then lt_cv_prog_compiler_c_o_CXX=yes fi fi chmod u+w . $rm conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files $rm out/* && rmdir out cd .. rmdir conftest $rm conftest* fi { echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o_CXX" >&5 echo "${ECHO_T}$lt_cv_prog_compiler_c_o_CXX" >&6; } hard_links="nottested" if test "$lt_cv_prog_compiler_c_o_CXX" = no && test "$need_locks" != no; then # do not overwrite the value of need_locks provided by the user { echo "$as_me:$LINENO: checking if we can lock with hard links" >&5 echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6; } hard_links=yes $rm conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no { echo "$as_me:$LINENO: result: $hard_links" >&5 echo "${ECHO_T}$hard_links" >&6; } if test "$hard_links" = no; then { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} need_locks=warn fi else need_locks=no fi { echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5 echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6; } export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' case $host_os in aix4* | aix5*) # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm if $NM -V 2>&1 | grep 'GNU' > /dev/null; then export_symbols_cmds_CXX='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' else export_symbols_cmds_CXX='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' fi ;; pw32*) export_symbols_cmds_CXX="$ltdll_cmds" ;; cygwin* | mingw*) export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGS] /s/.* \([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW] /s/.* //'\'' | sort | uniq > $export_symbols' ;; *) export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' ;; esac { echo "$as_me:$LINENO: result: $ld_shlibs_CXX" >&5 echo "${ECHO_T}$ld_shlibs_CXX" >&6; } test "$ld_shlibs_CXX" = no && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test "$GCC" = yes; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi # # Do we need to explicitly link libc? # case "x$archive_cmds_need_lc_CXX" in x|xyes) # Assume -lc should be added archive_cmds_need_lc_CXX=yes if test "$enable_shared" = yes && test "$GCC" = yes; then case $archive_cmds_CXX in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. { echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5 echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6; } $rm conftest* printf "$lt_simple_compile_test_code" > conftest.$ac_ext 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); } 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$lt_prog_compiler_wl_CXX compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$allow_undefined_flag_CXX allow_undefined_flag_CXX= if { (eval echo "$as_me:$LINENO: \"$archive_cmds_CXX 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5 (eval $archive_cmds_CXX 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } then archive_cmds_need_lc_CXX=no else archive_cmds_need_lc_CXX=yes fi allow_undefined_flag_CXX=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $rm conftest* { echo "$as_me:$LINENO: result: $archive_cmds_need_lc_CXX" >&5 echo "${ECHO_T}$archive_cmds_need_lc_CXX" >&6; } ;; esac fi ;; esac { echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5 echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6; } library_names_spec= libname_spec='lib$name' soname_spec= shrext=".so" postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" if test "$GCC" = yes; then sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown case $host_os in aix3*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='${libname}${release}${shared_ext}$major' ;; aix4* | aix5*) version_type=linux need_lib_prefix=no need_version=no hardcode_into_libs=yes if test "$host_cpu" = ia64; then # AIX 5 supports IA64 library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line `#! .'. This would cause the generated library to # depend on `.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[01] | aix4.[01].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then : else can_build_shared=no fi ;; esac # AIX (on Power*) has no versioning support, so currently we can not hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. if test "$aix_use_runtimelinking" = yes; then # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' else # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='${libname}${release}.a $libname.a' soname_spec='${libname}${release}${shared_ext}$major' fi shlibpath_var=LIBPATH fi ;; amigaos*) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; beos*) library_names_spec='${libname}${shared_ext}' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi4*) version_type=linux need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32*) version_type=windows shrext=".dll" need_version=no need_lib_prefix=no case $GCC,$host_os in yes,cygwin* | yes,mingw* | yes,pw32*) library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $rm \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" ;; mingw*) # MinGW DLLs use traditional 'lib' prefix soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then # It is most probably a Windows format PATH printed by # mingw gcc, but we are running on Cygwin. Gcc prints its search # path with ; separators, and with drive letters. We can handle the # drive letters (cygwin fileutils understands them), so leave them, # especially as we might pass files found there to a mingw objdump, # which wouldn't understand a cygwinified path. Ahh. sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/./-/g'`${versuffix}${shared_ext}' ;; esac ;; *) library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' ;; esac dynamic_linker='Win32 ld.exe' # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext' soname_spec='${libname}${release}${major}$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext='$(test .$module = .yes && echo .so || echo .dylib)' # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same. if test "$GCC" = yes; then sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"` else sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib' fi sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd1*) dynamic_linker=no ;; kfreebsd*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='GNU ld.so' ;; freebsd*) objformat=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout` version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2*) shlibpath_overrides_runpath=yes ;; freebsd3.01* | freebsdelf3.01*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; *) # from 3.2 on shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; esac ;; gnu*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case "$host_cpu" in ia64*) shrext='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' if test "X$HPUX_IA64_MODE" = X32; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" fi sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; hppa*64*) shrext='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555. postinstall_cmds='chmod 555 $lib' ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test "$lt_cv_prog_gnu_ld" = yes; then version_type=linux else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; # This must be Linux ELF. linux*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; nto-qnx*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; openbsd*) version_type=sunos need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then case $host_os in openbsd2.[89] | openbsd2.[89].*) shlibpath_overrides_runpath=no ;; *) shlibpath_overrides_runpath=yes ;; esac else shlibpath_overrides_runpath=yes fi ;; os2*) libname_spec='$name' shrext=".dll" need_lib_prefix=no library_names_spec='$libname${shared_ext} $libname.a' dynamic_linker='OS/2 ld.exe' shlibpath_var=LIBPATH ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" ;; sco3.2v5*) version_type=osf soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH ;; solaris*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test "$with_gnu_ld" = yes; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no export_dynamic_flag_spec='${wl}-Blargedynsym' runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec ;then version_type=linux library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' soname_spec='$libname${shared_ext}.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; uts4*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac { echo "$as_me:$LINENO: result: $dynamic_linker" >&5 echo "${ECHO_T}$dynamic_linker" >&6; } test "$dynamic_linker" = no && can_build_shared=no { echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5 echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6; } hardcode_action_CXX= if test -n "$hardcode_libdir_flag_spec_CXX" || \ test -n "$runpath_var CXX" || \ test "X$hardcode_automatic_CXX"="Xyes" ; then # We can hardcode non-existant directories. if test "$hardcode_direct_CXX" != no && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, CXX)" != no && test "$hardcode_minus_L_CXX" != no; then # Linking always hardcodes the temporary library directory. hardcode_action_CXX=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. hardcode_action_CXX=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. hardcode_action_CXX=unsupported fi { echo "$as_me:$LINENO: result: $hardcode_action_CXX" >&5 echo "${ECHO_T}$hardcode_action_CXX" >&6; } if test "$hardcode_action_CXX" = relink; then # Fast installation is not supported enable_fast_install=no elif test "$shlibpath_overrides_runpath" = yes || test "$enable_shared" = no; then # Fast installation is not necessary enable_fast_install=needless fi striplib= old_striplib= { echo "$as_me:$LINENO: checking whether stripping libraries is possible" >&5 echo $ECHO_N "checking whether stripping libraries is possible... $ECHO_C" >&6; } if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" test -z "$striplib" && striplib="$STRIP --strip-unneeded" # # # The following section is a PATCH to overcome the # stripped import library issues under cygwin case $host_os in cygwin*) striplib= { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } ;; *) { echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6; } ;; esac # # # AC_MSG_RESULT([yes]) # # else # FIXME - insert some real tests, host_os isn't really good enough case $host_os in darwin*) if test -n "$STRIP" ; then striplib="$STRIP -x" { echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi ;; *) { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } ;; esac fi if test "x$enable_dlopen" != xyes; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown else lt_cv_dlopen=no lt_cv_dlopen_libs= case $host_os in beos*) lt_cv_dlopen="load_add_on" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; mingw* | pw32*) lt_cv_dlopen="LoadLibrary" lt_cv_dlopen_libs= ;; cygwin*) lt_cv_dlopen="dlopen" lt_cv_dlopen_libs= ;; darwin*) # if libdl is installed we need to link against it { echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5 echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6; } if test "${ac_cv_lib_dl_dlopen+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $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 GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_dl_dlopen=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_dl_dlopen=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5 echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6; } if test $ac_cv_lib_dl_dlopen = yes; then lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" else lt_cv_dlopen="dyld" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes fi ;; *) { echo "$as_me:$LINENO: checking for shl_load" >&5 echo $ECHO_N "checking for shl_load... $ECHO_C" >&6; } if test "${ac_cv_func_shl_load+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 shl_load to an innocuous variant, in case declares shl_load. For example, HP-UX 11i declares gettimeofday. */ #define shl_load innocuous_shl_load /* System header to define __stub macros and hopefully few prototypes, which can conflict with char shl_load (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef shl_load /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char shl_load (); /* 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_shl_load || defined __stub___shl_load choke me #endif int main () { return shl_load (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_func_shl_load=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func_shl_load=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_func_shl_load" >&5 echo "${ECHO_T}$ac_cv_func_shl_load" >&6; } if test $ac_cv_func_shl_load = yes; then lt_cv_dlopen="shl_load" else { echo "$as_me:$LINENO: checking for shl_load in -ldld" >&5 echo $ECHO_N "checking for shl_load in -ldld... $ECHO_C" >&6; } if test "${ac_cv_lib_dld_shl_load+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $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 GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char shl_load (); int main () { return shl_load (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_dld_shl_load=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_dld_shl_load=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_dld_shl_load" >&5 echo "${ECHO_T}$ac_cv_lib_dld_shl_load" >&6; } if test $ac_cv_lib_dld_shl_load = yes; then lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-dld" else { echo "$as_me:$LINENO: checking for dlopen" >&5 echo $ECHO_N "checking for dlopen... $ECHO_C" >&6; } if test "${ac_cv_func_dlopen+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 dlopen to an innocuous variant, in case declares dlopen. For example, HP-UX 11i declares gettimeofday. */ #define dlopen innocuous_dlopen /* System header to define __stub macros and hopefully few prototypes, which can conflict with char dlopen (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef dlopen /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); /* 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_dlopen || defined __stub___dlopen choke me #endif int main () { return dlopen (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_func_dlopen=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func_dlopen=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_func_dlopen" >&5 echo "${ECHO_T}$ac_cv_func_dlopen" >&6; } if test $ac_cv_func_dlopen = yes; then lt_cv_dlopen="dlopen" else { echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5 echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6; } if test "${ac_cv_lib_dl_dlopen+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $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 GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_dl_dlopen=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_dl_dlopen=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5 echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6; } if test $ac_cv_lib_dl_dlopen = yes; then lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" else { echo "$as_me:$LINENO: checking for dlopen in -lsvld" >&5 echo $ECHO_N "checking for dlopen in -lsvld... $ECHO_C" >&6; } if test "${ac_cv_lib_svld_dlopen+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsvld $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 GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_svld_dlopen=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_svld_dlopen=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_svld_dlopen" >&5 echo "${ECHO_T}$ac_cv_lib_svld_dlopen" >&6; } if test $ac_cv_lib_svld_dlopen = yes; then lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld" else { echo "$as_me:$LINENO: checking for dld_link in -ldld" >&5 echo $ECHO_N "checking for dld_link in -ldld... $ECHO_C" >&6; } if test "${ac_cv_lib_dld_dld_link+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $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 GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dld_link (); int main () { return dld_link (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_dld_dld_link=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_dld_dld_link=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_dld_dld_link" >&5 echo "${ECHO_T}$ac_cv_lib_dld_dld_link" >&6; } if test $ac_cv_lib_dld_dld_link = yes; then lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld" fi fi fi fi fi fi ;; esac if test "x$lt_cv_dlopen" != xno; then enable_dlopen=yes else enable_dlopen=no fi case $lt_cv_dlopen in dlopen) save_CPPFLAGS="$CPPFLAGS" test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" save_LDFLAGS="$LDFLAGS" eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" save_LIBS="$LIBS" LIBS="$lt_cv_dlopen_libs $LIBS" { echo "$as_me:$LINENO: checking whether a program can dlopen itself" >&5 echo $ECHO_N "checking whether a program can dlopen itself... $ECHO_C" >&6; } if test "${lt_cv_dlopen_self+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test "$cross_compiling" = yes; then : lt_cv_dlopen_self=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext < #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif #ifdef __cplusplus extern "C" void exit (int); #endif void fnord() { int i=42;} int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; /* dlclose (self); */ } exit (status); } EOF 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); } && test -s conftest${ac_exeext} 2>/dev/null; then (./conftest; exit; ) 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; x$lt_unknown|x*) lt_cv_dlopen_self=no ;; esac else : # compilation failed lt_cv_dlopen_self=no fi fi rm -fr conftest* fi { echo "$as_me:$LINENO: result: $lt_cv_dlopen_self" >&5 echo "${ECHO_T}$lt_cv_dlopen_self" >&6; } if test "x$lt_cv_dlopen_self" = xyes; then LDFLAGS="$LDFLAGS $link_static_flag" { echo "$as_me:$LINENO: checking whether a statically linked program can dlopen itself" >&5 echo $ECHO_N "checking whether a statically linked program can dlopen itself... $ECHO_C" >&6; } if test "${lt_cv_dlopen_self_static+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test "$cross_compiling" = yes; then : lt_cv_dlopen_self_static=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext < #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif #ifdef __cplusplus extern "C" void exit (int); #endif void fnord() { int i=42;} int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; /* dlclose (self); */ } exit (status); } EOF 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); } && test -s conftest${ac_exeext} 2>/dev/null; then (./conftest; exit; ) 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; x$lt_unknown|x*) lt_cv_dlopen_self_static=no ;; esac else : # compilation failed lt_cv_dlopen_self_static=no fi fi rm -fr conftest* fi { echo "$as_me:$LINENO: result: $lt_cv_dlopen_self_static" >&5 echo "${ECHO_T}$lt_cv_dlopen_self_static" >&6; } fi CPPFLAGS="$save_CPPFLAGS" LDFLAGS="$save_LDFLAGS" LIBS="$save_LIBS" ;; esac case $lt_cv_dlopen_self in yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; *) enable_dlopen_self=unknown ;; esac case $lt_cv_dlopen_self_static in yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; *) enable_dlopen_self_static=unknown ;; esac fi # The else clause should only fire when bootstrapping the # libtool distribution, otherwise you forgot to ship ltmain.sh # with your package, and you will get complaints that there are # no rules to generate ltmain.sh. if test -f "$ltmain"; then # See if we are running on zsh, and set the options which allow our commands through # without removal of \ escapes. if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi # Now quote all the things that may contain metacharacters while being # careful not to overquote the AC_SUBSTed values. We take copies of the # variables and quote the copies for generation of the libtool script. for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC NM SED SHELL \ libname_spec library_names_spec soname_spec extract_expsyms_cmds \ old_striplib striplib file_magic_cmd finish_cmds finish_eval \ deplibs_check_method reload_flag reload_cmds need_locks \ lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \ lt_cv_sys_global_symbol_to_c_name_address \ sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ old_postinstall_cmds old_postuninstall_cmds \ compiler_CXX \ CC_CXX \ LD_CXX \ lt_prog_compiler_wl_CXX \ lt_prog_compiler_pic_CXX \ lt_prog_compiler_static_CXX \ lt_prog_compiler_no_builtin_flag_CXX \ export_dynamic_flag_spec_CXX \ thread_safe_flag_spec_CXX \ whole_archive_flag_spec_CXX \ enable_shared_with_static_runtimes_CXX \ old_archive_cmds_CXX \ old_archive_from_new_cmds_CXX \ predep_objects_CXX \ postdep_objects_CXX \ predeps_CXX \ postdeps_CXX \ compiler_lib_search_path_CXX \ archive_cmds_CXX \ archive_expsym_cmds_CXX \ postinstall_cmds_CXX \ postuninstall_cmds_CXX \ old_archive_from_expsyms_cmds_CXX \ allow_undefined_flag_CXX \ no_undefined_flag_CXX \ export_symbols_cmds_CXX \ hardcode_libdir_flag_spec_CXX \ hardcode_libdir_flag_spec_ld_CXX \ hardcode_libdir_separator_CXX \ hardcode_automatic_CXX \ module_cmds_CXX \ module_expsym_cmds_CXX \ lt_cv_prog_compiler_c_o_CXX \ exclude_expsyms_CXX \ include_expsyms_CXX; do case $var in old_archive_cmds_CXX | \ old_archive_from_new_cmds_CXX | \ archive_cmds_CXX | \ archive_expsym_cmds_CXX | \ module_cmds_CXX | \ module_expsym_cmds_CXX | \ old_archive_from_expsyms_cmds_CXX | \ export_symbols_cmds_CXX | \ extract_expsyms_cmds | reload_cmds | finish_cmds | \ postinstall_cmds | postuninstall_cmds | \ old_postinstall_cmds | old_postuninstall_cmds | \ sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) # Double-quote double-evaled strings. eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" ;; *) eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" ;; esac done case $lt_echo in *'\$0 --fallback-echo"') lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'` ;; esac cfgfile="$ofile" cat <<__EOF__ >> "$cfgfile" # ### BEGIN LIBTOOL TAG CONFIG: $tagname # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # Shell to use when invoking shell scripts. SHELL=$lt_SHELL # Whether or not to build shared libraries. build_libtool_libs=$enable_shared # Whether or not to build static libraries. build_old_libs=$enable_static # Whether or not to add -lc for building shared libraries. build_libtool_need_lc=$archive_cmds_need_lc_CXX # Whether or not to disallow shared libs when runtime libs are static allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_CXX # Whether or not to optimize for fast installation. fast_install=$enable_fast_install # The host system. host_alias=$host_alias host=$host # An echo program that does not interpret backslashes. echo=$lt_echo # The archiver. AR=$lt_AR AR_FLAGS=$lt_AR_FLAGS # A C compiler. LTCC=$lt_LTCC # A language-specific compiler. CC=$lt_compiler_CXX # Is the compiler the GNU C compiler? with_gcc=$GCC_CXX # An ERE matcher. EGREP=$lt_EGREP # The linker used to build libraries. LD=$lt_LD_CXX # Whether we need hard or soft links. LN_S=$lt_LN_S # A BSD-compatible nm program. NM=$lt_NM # A symbol stripping program STRIP=$STRIP # Used to examine libraries when file_magic_cmd begins "file" MAGIC_CMD=$MAGIC_CMD # Used on cygwin: DLL creation program. DLLTOOL="$DLLTOOL" # Used on cygwin: object dumper. OBJDUMP="$OBJDUMP" # Used on cygwin: assembler. AS="$AS" # The name of the directory that contains temporary libtool files. objdir=$objdir # How to create reloadable object files. reload_flag=$lt_reload_flag reload_cmds=$lt_reload_cmds # How to pass a linker flag through the compiler. wl=$lt_lt_prog_compiler_wl_CXX # Object file suffix (normally "o"). objext="$ac_objext" # Old archive suffix (normally "a"). libext="$libext" # Shared library suffix (normally ".so"). shrext='$shrext' # Executable file suffix (normally ""). exeext="$exeext" # Additional compiler flags for building library objects. pic_flag=$lt_lt_prog_compiler_pic_CXX pic_mode=$pic_mode # What is the maximum length of a command? max_cmd_len=$lt_cv_sys_max_cmd_len # Does compiler simultaneously support -c and -o options? compiler_c_o=$lt_lt_cv_prog_compiler_c_o_CXX # Must we lock files when doing compilation ? need_locks=$lt_need_locks # Do we need the lib prefix for modules? need_lib_prefix=$need_lib_prefix # Do we need a version for libraries? need_version=$need_version # Whether dlopen is supported. dlopen_support=$enable_dlopen # Whether dlopen of programs is supported. dlopen_self=$enable_dlopen_self # Whether dlopen of statically linked programs is supported. dlopen_self_static=$enable_dlopen_self_static # Compiler flag to prevent dynamic linking. link_static_flag=$lt_lt_prog_compiler_static_CXX # Compiler flag to turn off builtin functions. no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_CXX # Compiler flag to allow reflexive dlopens. export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_CXX # Compiler flag to generate shared objects directly from archives. whole_archive_flag_spec=$lt_whole_archive_flag_spec_CXX # Compiler flag to generate thread-safe objects. thread_safe_flag_spec=$lt_thread_safe_flag_spec_CXX # Library versioning type. version_type=$version_type # Format of library name prefix. libname_spec=$lt_libname_spec # List of archive names. First name is the real one, the rest are links. # The last name is the one that the linker finds with -lNAME. library_names_spec=$lt_library_names_spec # The coded name of the library, if different from the real name. soname_spec=$lt_soname_spec # Commands used to build and install an old-style archive. RANLIB=$lt_RANLIB old_archive_cmds=$lt_old_archive_cmds_CXX old_postinstall_cmds=$lt_old_postinstall_cmds old_postuninstall_cmds=$lt_old_postuninstall_cmds # Create an old-style archive from a shared archive. old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_CXX # Create a temporary old-style archive to link instead of a shared archive. old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_CXX # Commands used to build and install a shared archive. archive_cmds=$lt_archive_cmds_CXX archive_expsym_cmds=$lt_archive_expsym_cmds_CXX postinstall_cmds=$lt_postinstall_cmds postuninstall_cmds=$lt_postuninstall_cmds # Commands used to build a loadable module (assumed same as above if empty) module_cmds=$lt_module_cmds_CXX module_expsym_cmds=$lt_module_expsym_cmds_CXX # Commands to strip libraries. old_striplib=$lt_old_striplib striplib=$lt_striplib # Dependencies to place before the objects being linked to create a # shared library. predep_objects=$lt_predep_objects_CXX # Dependencies to place after the objects being linked to create a # shared library. postdep_objects=$lt_postdep_objects_CXX # Dependencies to place before the objects being linked to create a # shared library. predeps=$lt_predeps_CXX # Dependencies to place after the objects being linked to create a # shared library. postdeps=$lt_postdeps_CXX # The library search path used internally by the compiler when linking # a shared library. compiler_lib_search_path=$lt_compiler_lib_search_path_CXX # Method to check whether dependent libraries are shared objects. deplibs_check_method=$lt_deplibs_check_method # Command to use when deplibs_check_method == file_magic. file_magic_cmd=$lt_file_magic_cmd # Flag that allows shared libraries with undefined symbols to be built. allow_undefined_flag=$lt_allow_undefined_flag_CXX # Flag that forces no undefined symbols. no_undefined_flag=$lt_no_undefined_flag_CXX # Commands used to finish a libtool library installation in a directory. finish_cmds=$lt_finish_cmds # Same as above, but a single script fragment to be evaled but not shown. finish_eval=$lt_finish_eval # Take the output of nm and produce a listing of raw symbols and C names. global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe # Transform the output of nm in a proper C declaration global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl # Transform the output of nm in a C name address pair global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address # This is the shared library runtime path variable. runpath_var=$runpath_var # This is the shared library path variable. shlibpath_var=$shlibpath_var # Is shlibpath searched before the hard-coded library search path? shlibpath_overrides_runpath=$shlibpath_overrides_runpath # How to hardcode a shared library path into an executable. hardcode_action=$hardcode_action_CXX # Whether we should hardcode library paths into libraries. hardcode_into_libs=$hardcode_into_libs # Flag to hardcode \$libdir into a binary during linking. # This must work even if \$libdir does not exist. hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_CXX # If ld is used when linking, flag to hardcode \$libdir into # a binary during linking. This must work even if \$libdir does # not exist. hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_CXX # Whether we need a single -rpath flag with a separated argument. hardcode_libdir_separator=$lt_hardcode_libdir_separator_CXX # Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the # resulting binary. hardcode_direct=$hardcode_direct_CXX # Set to yes if using the -LDIR flag during linking hardcodes DIR into the # resulting binary. hardcode_minus_L=$hardcode_minus_L_CXX # Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into # the resulting binary. hardcode_shlibpath_var=$hardcode_shlibpath_var_CXX # Set to yes if building a shared library automatically hardcodes DIR into the library # and all subsequent libraries and executables linked against it. hardcode_automatic=$hardcode_automatic_CXX # Variables whose values should be saved in libtool wrapper scripts and # restored at relink time. variables_saved_for_relink="$variables_saved_for_relink" # Whether libtool must link a program against all its dependency libraries. link_all_deplibs=$link_all_deplibs_CXX # Compile-time system search path for libraries sys_lib_search_path_spec=$lt_sys_lib_search_path_spec # Run-time system search path for libraries sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec # Fix the shell variable \$srcfile for the compiler. fix_srcfile_path="$fix_srcfile_path_CXX" # Set to yes if exported symbols are required. always_export_symbols=$always_export_symbols_CXX # The commands to list exported symbols. export_symbols_cmds=$lt_export_symbols_cmds_CXX # The commands to extract the exported symbol list from a shared archive. extract_expsyms_cmds=$lt_extract_expsyms_cmds # Symbols that should not be listed in the preloaded symbols. exclude_expsyms=$lt_exclude_expsyms_CXX # Symbols that must always be exported. include_expsyms=$lt_include_expsyms_CXX # ### END LIBTOOL TAG CONFIG: $tagname __EOF__ else # If there is no Makefile yet, we rely on a make rule to execute # `config.status --recheck' to rerun these tests and create the # libtool script then. test -f Makefile && make "$ltmain" fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu CC=$lt_save_CC LDCXX=$LD LD=$lt_save_LD GCC=$lt_save_GCC with_gnu_ldcxx=$with_gnu_ld with_gnu_ld=$lt_save_with_gnu_ld lt_cv_path_LDCXX=$lt_cv_path_LD lt_cv_path_LD=$lt_save_path_LD lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld else tagname="" fi ;; F77) if test -n "$F77" && test "X$F77" != "Xno"; then ac_ext=f ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5' ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_f77_compiler_gnu archive_cmds_need_lc_F77=no allow_undefined_flag_F77= always_export_symbols_F77=no archive_expsym_cmds_F77= export_dynamic_flag_spec_F77= hardcode_direct_F77=no hardcode_libdir_flag_spec_F77= hardcode_libdir_flag_spec_ld_F77= hardcode_libdir_separator_F77= hardcode_minus_L_F77=no hardcode_automatic_F77=no module_cmds_F77= module_expsym_cmds_F77= link_all_deplibs_F77=unknown old_archive_cmds_F77=$old_archive_cmds no_undefined_flag_F77= whole_archive_flag_spec_F77= enable_shared_with_static_runtimes_F77=no # Source file extension for f77 test sources. ac_ext=f # Object file extension for compiled f77 test sources. objext=o objext_F77=$objext # Code to be used in simple compile tests lt_simple_compile_test_code=" subroutine t\n return\n end\n" # Code to be used in simple link tests lt_simple_link_test_code=" program t\n end\n" # ltmain only uses $CC for tagged configurations so make sure $CC is set. # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # Allow CC to be a program name with arguments. compiler=$CC # Allow CC to be a program name with arguments. lt_save_CC="$CC" CC=${F77-"f77"} compiler=$CC compiler_F77=$CC cc_basename=`$echo X"$compiler" | $Xsed -e 's%^.*/%%'` { echo "$as_me:$LINENO: checking if libtool supports shared libraries" >&5 echo $ECHO_N "checking if libtool supports shared libraries... $ECHO_C" >&6; } { echo "$as_me:$LINENO: result: $can_build_shared" >&5 echo "${ECHO_T}$can_build_shared" >&6; } { echo "$as_me:$LINENO: checking whether to build shared libraries" >&5 echo $ECHO_N "checking whether to build shared libraries... $ECHO_C" >&6; } test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case "$host_os" in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix4*) test "$enable_shared" = yes && enable_static=no ;; esac { echo "$as_me:$LINENO: result: $enable_shared" >&5 echo "${ECHO_T}$enable_shared" >&6; } { echo "$as_me:$LINENO: checking whether to build static libraries" >&5 echo $ECHO_N "checking whether to build static libraries... $ECHO_C" >&6; } # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes { echo "$as_me:$LINENO: result: $enable_static" >&5 echo "${ECHO_T}$enable_static" >&6; } test "$ld_shlibs_F77" = no && can_build_shared=no GCC_F77="$G77" LD_F77="$LD" lt_prog_compiler_wl_F77= lt_prog_compiler_pic_F77= lt_prog_compiler_static_F77= { echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5 echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6; } if test "$GCC" = yes; then lt_prog_compiler_wl_F77='-Wl,' lt_prog_compiler_static_F77='-static' case $host_os in aix*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static_F77='-Bstatic' fi ;; amigaos*) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. lt_prog_compiler_pic_F77='-m68020 -resident32 -malways-restore-a4' ;; beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | pw32* | os2*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_prog_compiler_pic_F77='-DDLL_EXPORT' ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files lt_prog_compiler_pic_F77='-fno-common' ;; msdosdjgpp*) # Just because we use GCC doesn't mean we suddenly get shared libraries # on systems that don't support them. lt_prog_compiler_can_build_shared_F77=no enable_shared=no ;; sysv4*MP*) if test -d /usr/nec; then lt_prog_compiler_pic_F77=-Kconform_pic fi ;; hpux*) # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case "$host_cpu" in hppa*64*|ia64*) # +Z the default ;; *) lt_prog_compiler_pic_F77='-fPIC' ;; esac ;; *) lt_prog_compiler_pic_F77='-fPIC' ;; esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in aix*) lt_prog_compiler_wl_F77='-Wl,' if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static_F77='-Bstatic' else lt_prog_compiler_static_F77='-bnso -bI:/lib/syscalls.exp' fi ;; mingw* | pw32* | os2*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_prog_compiler_pic_F77='-DDLL_EXPORT' ;; hpux9* | hpux10* | hpux11*) lt_prog_compiler_wl_F77='-Wl,' # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case "$host_cpu" in hppa*64*|ia64*) # +Z the default ;; *) lt_prog_compiler_pic_F77='+Z' ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? lt_prog_compiler_static_F77='${wl}-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) lt_prog_compiler_wl_F77='-Wl,' # PIC (with -KPIC) is the default. lt_prog_compiler_static_F77='-non_shared' ;; newsos6) lt_prog_compiler_pic_F77='-KPIC' lt_prog_compiler_static_F77='-Bstatic' ;; linux*) case $CC in icc* | ecc*) lt_prog_compiler_wl_F77='-Wl,' lt_prog_compiler_pic_F77='-KPIC' lt_prog_compiler_static_F77='-static' ;; ccc*) lt_prog_compiler_wl_F77='-Wl,' # All Alpha code is PIC. lt_prog_compiler_static_F77='-non_shared' ;; esac ;; osf3* | osf4* | osf5*) lt_prog_compiler_wl_F77='-Wl,' # All OSF/1 code is PIC. lt_prog_compiler_static_F77='-non_shared' ;; sco3.2v5*) lt_prog_compiler_pic_F77='-Kpic' lt_prog_compiler_static_F77='-dn' ;; solaris*) lt_prog_compiler_wl_F77='-Wl,' lt_prog_compiler_pic_F77='-KPIC' lt_prog_compiler_static_F77='-Bstatic' ;; sunos4*) lt_prog_compiler_wl_F77='-Qoption ld ' lt_prog_compiler_pic_F77='-PIC' lt_prog_compiler_static_F77='-Bstatic' ;; sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) lt_prog_compiler_wl_F77='-Wl,' lt_prog_compiler_pic_F77='-KPIC' lt_prog_compiler_static_F77='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec ;then lt_prog_compiler_pic_F77='-Kconform_pic' lt_prog_compiler_static_F77='-Bstatic' fi ;; uts4*) lt_prog_compiler_pic_F77='-pic' lt_prog_compiler_static_F77='-Bstatic' ;; *) lt_prog_compiler_can_build_shared_F77=no ;; esac fi { echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_F77" >&5 echo "${ECHO_T}$lt_prog_compiler_pic_F77" >&6; } # # Check to make sure the PIC flag actually works. # if test -n "$lt_prog_compiler_pic_F77"; then { echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic_F77 works" >&5 echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic_F77 works... $ECHO_C" >&6; } if test "${lt_prog_compiler_pic_works_F77+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else lt_prog_compiler_pic_works_F77=no ac_outfile=conftest.$ac_objext printf "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$lt_prog_compiler_pic_F77" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:14448: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:14452: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings if test ! -s conftest.err; then lt_prog_compiler_pic_works_F77=yes fi fi $rm conftest* fi { echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works_F77" >&5 echo "${ECHO_T}$lt_prog_compiler_pic_works_F77" >&6; } if test x"$lt_prog_compiler_pic_works_F77" = xyes; then case $lt_prog_compiler_pic_F77 in "" | " "*) ;; *) lt_prog_compiler_pic_F77=" $lt_prog_compiler_pic_F77" ;; esac else lt_prog_compiler_pic_F77= lt_prog_compiler_can_build_shared_F77=no fi fi case "$host_os" in # For platforms which do not support PIC, -DPIC is meaningless: *djgpp*) lt_prog_compiler_pic_F77= ;; *) lt_prog_compiler_pic_F77="$lt_prog_compiler_pic_F77" ;; esac { echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5 echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6; } if test "${lt_cv_prog_compiler_c_o_F77+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else lt_cv_prog_compiler_c_o_F77=no $rm -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out printf "$lt_simple_compile_test_code" > conftest.$ac_ext # According to Tom Tromey, Ian Lance Taylor reported there are C compilers # that will create temporary files in the current directory regardless of # the output directory. Thus, making CWD read-only will cause this test # to fail, enabling locking or at least warning the user not to do parallel # builds. chmod -w . lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:14515: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:14519: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings if test ! -s out/conftest.err; then lt_cv_prog_compiler_c_o_F77=yes fi fi chmod u+w . $rm conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files $rm out/* && rmdir out cd .. rmdir conftest $rm conftest* fi { echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o_F77" >&5 echo "${ECHO_T}$lt_cv_prog_compiler_c_o_F77" >&6; } hard_links="nottested" if test "$lt_cv_prog_compiler_c_o_F77" = no && test "$need_locks" != no; then # do not overwrite the value of need_locks provided by the user { echo "$as_me:$LINENO: checking if we can lock with hard links" >&5 echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6; } hard_links=yes $rm conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no { echo "$as_me:$LINENO: result: $hard_links" >&5 echo "${ECHO_T}$hard_links" >&6; } if test "$hard_links" = no; then { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} need_locks=warn fi else need_locks=no fi { echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5 echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6; } runpath_var= allow_undefined_flag_F77= enable_shared_with_static_runtimes_F77=no archive_cmds_F77= archive_expsym_cmds_F77= old_archive_From_new_cmds_F77= old_archive_from_expsyms_cmds_F77= export_dynamic_flag_spec_F77= whole_archive_flag_spec_F77= thread_safe_flag_spec_F77= hardcode_libdir_flag_spec_F77= hardcode_libdir_flag_spec_ld_F77= hardcode_libdir_separator_F77= hardcode_direct_F77=no hardcode_minus_L_F77=no hardcode_shlibpath_var_F77=unsupported link_all_deplibs_F77=unknown hardcode_automatic_F77=no module_cmds_F77= module_expsym_cmds_F77= always_export_symbols_F77=no export_symbols_cmds_F77='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list include_expsyms_F77= # exclude_expsyms can be an extended regexp of symbols to exclude # it will be wrapped by ` (' and `)$', so one must not match beginning or # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', # as well as any symbol that contains `d'. exclude_expsyms_F77="_GLOBAL_OFFSET_TABLE_" # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. extract_expsyms_cmds= 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_F77=yes if test "$with_gnu_ld" = yes; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='${wl}' # See if GNU ld supports shared libraries. case $host_os in aix3* | aix4* | aix5*) # On AIX/PPC, the GNU linker is very broken if test "$host_cpu" != ia64; then ld_shlibs_F77=no cat <&2 *** Warning: the GNU linker, at least up to release 2.9.1, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you *** really care for shared libraries, you may want to modify your PATH *** so that a non-GNU linker is found, and then restart. EOF fi ;; amigaos*) archive_cmds_F77='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec_F77='-L$libdir' hardcode_minus_L_F77=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't use # them. ld_shlibs_F77=no ;; beos*) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then allow_undefined_flag_F77=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME archive_cmds_F77='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else ld_shlibs_F77=no fi ;; cygwin* | mingw* | pw32*) # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, F77) is actually meaningless, # as there is no search path for DLLs. hardcode_libdir_flag_spec_F77='-L$libdir' allow_undefined_flag_F77=unsupported always_export_symbols_F77=no enable_shared_with_static_runtimes_F77=yes export_symbols_cmds_F77='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGS] /s/.* \([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW] /s/.* //'\'' | sort | uniq > $export_symbols' if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... archive_expsym_cmds_F77='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib' else ld_shlibs=no fi ;; netbsd*) if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then archive_cmds_F77='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' fi ;; solaris* | sysv5*) if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then ld_shlibs_F77=no cat <&2 *** Warning: The releases 2.8.* of the GNU linker cannot reliably *** create shared libraries on Solaris systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.9.1 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. EOF elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs_F77=no fi ;; sunos4*) archive_cmds_F77='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= hardcode_direct_F77=yes hardcode_shlibpath_var_F77=no ;; *) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs_F77=no fi ;; esac if test "$ld_shlibs_F77" = yes; then runpath_var=LD_RUN_PATH hardcode_libdir_flag_spec_F77='${wl}--rpath ${wl}$libdir' export_dynamic_flag_spec_F77='${wl}--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then whole_archive_flag_spec_F77="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else whole_archive_flag_spec_F77= fi fi else # PORTME fill in a description of your system's linker (not GNU ld) case $host_os in aix3*) allow_undefined_flag_F77=unsupported always_export_symbols_F77=yes archive_expsym_cmds_F77='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. hardcode_minus_L_F77=yes if test "$GCC" = yes && test -z "$link_static_flag"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. hardcode_direct_F77=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 exp_sym_flag='-Bexport' no_entry_flag="" else # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm if $NM -V 2>&1 | grep 'GNU' > /dev/null; then export_symbols_cmds_F77='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' else export_symbols_cmds_F77='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # 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 exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. archive_cmds_F77='' hardcode_direct_F77=yes hardcode_libdir_separator_F77=':' link_all_deplibs_F77=yes if test "$GCC" = yes; then case $host_os in aix4.012|aix4.012.*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && \ strings "$collect2name" | grep resolve_lib_name >/dev/null then # We have reworked collect2 hardcode_direct_F77=yes else # We have old collect2 hardcode_direct_F77=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking hardcode_minus_L_F77=yes hardcode_libdir_flag_spec_F77='-L$libdir' hardcode_libdir_separator_F77= fi esac shared_flag='-shared' else # not using gcc if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi fi # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. always_export_symbols_F77=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. allow_undefined_flag_F77='-berok' # Determine the default libpath from the value encoded in an empty executable. cat >conftest.$ac_ext <<_ACEOF program main end _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_f77_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'` # Check for a 64-bit object if we didn't find anything. if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'`; fi else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi hardcode_libdir_flag_spec_F77='${wl}-blibpath:$libdir:'"$aix_libpath" archive_expsym_cmds_F77="\$CC"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then hardcode_libdir_flag_spec_F77='${wl}-R $libdir:/usr/lib:/lib' allow_undefined_flag_F77="-z nodefs" archive_expsym_cmds_F77="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an empty executable. cat >conftest.$ac_ext <<_ACEOF program main end _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_f77_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'` # Check for a 64-bit object if we didn't find anything. if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'`; fi else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi hardcode_libdir_flag_spec_F77='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. no_undefined_flag_F77=' ${wl}-bernotok' allow_undefined_flag_F77=' ${wl}-berok' # -bexpall does not export symbols beginning with underscore (_) always_export_symbols_F77=yes # Exported symbols can be pulled into shared objects from archives whole_archive_flag_spec_F77=' ' archive_cmds_need_lc_F77=yes # This is similar to how AIX traditionally builds it's shared libraries. archive_expsym_cmds_F77="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; amigaos*) archive_cmds_F77='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec_F77='-L$libdir' hardcode_minus_L_F77=yes # see comment about different semantics on the GNU ld section ld_shlibs_F77=no ;; bsdi4*) export_dynamic_flag_spec_F77=-rdynamic ;; 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_F77=' ' allow_undefined_flag_F77=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext=".dll" # FIXME: Setting linknames here is a bad hack. archive_cmds_F77='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. old_archive_From_new_cmds_F77='true' # FIXME: Should let the user specify the lib program. old_archive_cmds_F77='lib /OUT:$oldlib$oldobjs$old_deplibs' fix_srcfile_path='`cygpath -w "$srcfile"`' enable_shared_with_static_runtimes_F77=yes ;; darwin* | rhapsody*) if test "$GXX" = yes ; then archive_cmds_need_lc_F77=no case "$host_os" in rhapsody* | darwin1.[012]) allow_undefined_flag_F77='-undefined suppress' ;; *) # Darwin 1.3 on if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then allow_undefined_flag_F77='-flat_namespace -undefined suppress' else case ${MACOSX_DEPLOYMENT_TARGET} in 10.[012]) allow_undefined_flag_F77='-flat_namespace -undefined suppress' ;; 10.*) allow_undefined_flag_F77='-undefined dynamic_lookup' ;; esac fi ;; esac lt_int_apple_cc_single_mod=no output_verbose_link_cmd='echo' if $CC -dumpspecs 2>&1 | grep 'single_module' >/dev/null ; then lt_int_apple_cc_single_mod=yes fi if test "X$lt_int_apple_cc_single_mod" = Xyes ; then archive_cmds_F77='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' else archive_cmds_F77='$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring' fi module_cmds_F77='$CC ${wl}-bind_at_load $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's if test "X$lt_int_apple_cc_single_mod" = Xyes ; then archive_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' else archive_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' fi module_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' hardcode_direct_F77=no hardcode_automatic_F77=yes hardcode_shlibpath_var_F77=unsupported whole_archive_flag_spec_F77='-all_load $convenience' link_all_deplibs_F77=yes else ld_shlibs_F77=no fi ;; dgux*) archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec_F77='-L$libdir' hardcode_shlibpath_var_F77=no ;; freebsd1*) ld_shlibs_F77=no ;; # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little # extra space). freebsd2.2*) archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' hardcode_libdir_flag_spec_F77='-R$libdir' hardcode_direct_F77=yes hardcode_shlibpath_var_F77=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2*) archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_direct_F77=yes hardcode_minus_L_F77=yes hardcode_shlibpath_var_F77=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd* | kfreebsd*-gnu) archive_cmds_F77='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec_F77='-R$libdir' hardcode_direct_F77=yes hardcode_shlibpath_var_F77=no ;; hpux9*) if test "$GCC" = yes; then archive_cmds_F77='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else archive_cmds_F77='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' fi hardcode_libdir_flag_spec_F77='${wl}+b ${wl}$libdir' hardcode_libdir_separator_F77=: hardcode_direct_F77=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L_F77=yes export_dynamic_flag_spec_F77='${wl}-E' ;; hpux10* | hpux11*) if test "$GCC" = yes -a "$with_gnu_ld" = no; then case "$host_cpu" in hppa*64*|ia64*) archive_cmds_F77='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; *) archive_cmds_F77='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case "$host_cpu" in hppa*64*|ia64*) archive_cmds_F77='$LD -b +h $soname -o $lib $libobjs $deplibs $linker_flags' ;; *) archive_cmds_F77='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' ;; esac fi if test "$with_gnu_ld" = no; then case "$host_cpu" in hppa*64*) hardcode_libdir_flag_spec_F77='${wl}+b ${wl}$libdir' hardcode_libdir_flag_spec_ld_F77='+b $libdir' hardcode_libdir_separator_F77=: hardcode_direct_F77=no hardcode_shlibpath_var_F77=no ;; ia64*) hardcode_libdir_flag_spec_F77='-L$libdir' hardcode_direct_F77=no hardcode_shlibpath_var_F77=no # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L_F77=yes ;; *) hardcode_libdir_flag_spec_F77='${wl}+b ${wl}$libdir' hardcode_libdir_separator_F77=: hardcode_direct_F77=yes export_dynamic_flag_spec_F77='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L_F77=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) if test "$GCC" = yes; then archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else archive_cmds_F77='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' hardcode_libdir_flag_spec_ld_F77='-rpath $libdir' fi hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator_F77=: link_all_deplibs_F77=yes ;; netbsd*) if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else archive_cmds_F77='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi hardcode_libdir_flag_spec_F77='-R$libdir' hardcode_direct_F77=yes hardcode_shlibpath_var_F77=no ;; newsos6) archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct_F77=yes hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator_F77=: hardcode_shlibpath_var_F77=no ;; openbsd*) hardcode_direct_F77=yes hardcode_shlibpath_var_F77=no if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then archive_cmds_F77='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec_F77='${wl}-rpath,$libdir' export_dynamic_flag_spec_F77='${wl}-E' else case $host_os in openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec_F77='-R$libdir' ;; *) archive_cmds_F77='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec_F77='${wl}-rpath,$libdir' ;; esac fi ;; os2*) hardcode_libdir_flag_spec_F77='-L$libdir' hardcode_minus_L_F77=yes allow_undefined_flag_F77=unsupported archive_cmds_F77='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' old_archive_From_new_cmds_F77='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' ;; osf3*) if test "$GCC" = yes; then allow_undefined_flag_F77=' ${wl}-expect_unresolved ${wl}\*' archive_cmds_F77='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else allow_undefined_flag_F77=' -expect_unresolved \*' archive_cmds_F77='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' fi hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator_F77=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag if test "$GCC" = yes; then allow_undefined_flag_F77=' ${wl}-expect_unresolved ${wl}\*' archive_cmds_F77='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir' else allow_undefined_flag_F77=' -expect_unresolved \*' archive_cmds_F77='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' archive_expsym_cmds_F77='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~ $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib~$rm $lib.exp' # Both c and cxx compiler support -rpath directly hardcode_libdir_flag_spec_F77='-rpath $libdir' fi hardcode_libdir_separator_F77=: ;; sco3.2v5*) archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var_F77=no export_dynamic_flag_spec_F77='${wl}-Bexport' runpath_var=LD_RUN_PATH hardcode_runpath_var=yes ;; solaris*) no_undefined_flag_F77=' -z text' if test "$GCC" = yes; then archive_cmds_F77='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_F77='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp' else archive_cmds_F77='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' archive_expsym_cmds_F77='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' fi hardcode_libdir_flag_spec_F77='-R$libdir' hardcode_shlibpath_var_F77=no case $host_os in solaris2.[0-5] | solaris2.[0-5].*) ;; *) # Supported since Solaris 2.6 (maybe 2.5.1?) whole_archive_flag_spec_F77='-z allextract$convenience -z defaultextract' ;; esac link_all_deplibs_F77=yes ;; sunos4*) if test "x$host_vendor" = xsequent; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. archive_cmds_F77='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds_F77='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi hardcode_libdir_flag_spec_F77='-L$libdir' hardcode_direct_F77=yes hardcode_minus_L_F77=yes hardcode_shlibpath_var_F77=no ;; sysv4) case $host_vendor in sni) archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct_F77=yes # is this really true??? ;; siemens) ## LD is ld it makes a PLAMLIB ## CC just makes a GrossModule. archive_cmds_F77='$LD -G -o $lib $libobjs $deplibs $linker_flags' reload_cmds_F77='$CC -r -o $output$reload_objs' hardcode_direct_F77=no ;; motorola) archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct_F77=no #Motorola manual says yes, but my tests say they lie ;; esac runpath_var='LD_RUN_PATH' hardcode_shlibpath_var_F77=no ;; sysv4.3*) archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var_F77=no export_dynamic_flag_spec_F77='-Bexport' ;; sysv4*MP*) if test -d /usr/nec; then archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var_F77=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes ld_shlibs_F77=yes fi ;; sysv4.2uw2*) archive_cmds_F77='$LD -G -o $lib $libobjs $deplibs $linker_flags' hardcode_direct_F77=yes hardcode_minus_L_F77=no hardcode_shlibpath_var_F77=no hardcode_runpath_var=yes runpath_var=LD_RUN_PATH ;; sysv5OpenUNIX8* | sysv5UnixWare7* | sysv5uw[78]* | unixware7*) no_undefined_flag_F77='${wl}-z ${wl}text' if test "$GCC" = yes; then archive_cmds_F77='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds_F77='$CC -G ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' fi runpath_var='LD_RUN_PATH' hardcode_shlibpath_var_F77=no ;; sysv5*) no_undefined_flag_F77=' -z text' # $CC -shared without GNU ld will not create a library from C++ # object files and a static libstdc++, better avoid it by now archive_cmds_F77='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' archive_expsym_cmds_F77='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' hardcode_libdir_flag_spec_F77= hardcode_shlibpath_var_F77=no runpath_var='LD_RUN_PATH' ;; uts4*) archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec_F77='-L$libdir' hardcode_shlibpath_var_F77=no ;; *) ld_shlibs_F77=no ;; esac fi { echo "$as_me:$LINENO: result: $ld_shlibs_F77" >&5 echo "${ECHO_T}$ld_shlibs_F77" >&6; } test "$ld_shlibs_F77" = no && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test "$GCC" = yes; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi # # Do we need to explicitly link libc? # case "x$archive_cmds_need_lc_F77" in x|xyes) # Assume -lc should be added archive_cmds_need_lc_F77=yes if test "$enable_shared" = yes && test "$GCC" = yes; then case $archive_cmds_F77 in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. { echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5 echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6; } $rm conftest* printf "$lt_simple_compile_test_code" > conftest.$ac_ext 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); } 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$lt_prog_compiler_wl_F77 compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$allow_undefined_flag_F77 allow_undefined_flag_F77= if { (eval echo "$as_me:$LINENO: \"$archive_cmds_F77 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5 (eval $archive_cmds_F77 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } then archive_cmds_need_lc_F77=no else archive_cmds_need_lc_F77=yes fi allow_undefined_flag_F77=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $rm conftest* { echo "$as_me:$LINENO: result: $archive_cmds_need_lc_F77" >&5 echo "${ECHO_T}$archive_cmds_need_lc_F77" >&6; } ;; esac fi ;; esac { echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5 echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6; } library_names_spec= libname_spec='lib$name' soname_spec= shrext=".so" postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" if test "$GCC" = yes; then sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown case $host_os in aix3*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='${libname}${release}${shared_ext}$major' ;; aix4* | aix5*) version_type=linux need_lib_prefix=no need_version=no hardcode_into_libs=yes if test "$host_cpu" = ia64; then # AIX 5 supports IA64 library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line `#! .'. This would cause the generated library to # depend on `.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[01] | aix4.[01].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then : else can_build_shared=no fi ;; esac # AIX (on Power*) has no versioning support, so currently we can not hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. if test "$aix_use_runtimelinking" = yes; then # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' else # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='${libname}${release}.a $libname.a' soname_spec='${libname}${release}${shared_ext}$major' fi shlibpath_var=LIBPATH fi ;; amigaos*) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; beos*) library_names_spec='${libname}${shared_ext}' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi4*) version_type=linux need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32*) version_type=windows shrext=".dll" need_version=no need_lib_prefix=no case $GCC,$host_os in yes,cygwin* | yes,mingw* | yes,pw32*) library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $rm \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" ;; mingw*) # MinGW DLLs use traditional 'lib' prefix soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then # It is most probably a Windows format PATH printed by # mingw gcc, but we are running on Cygwin. Gcc prints its search # path with ; separators, and with drive letters. We can handle the # drive letters (cygwin fileutils understands them), so leave them, # especially as we might pass files found there to a mingw objdump, # which wouldn't understand a cygwinified path. Ahh. sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/./-/g'`${versuffix}${shared_ext}' ;; esac ;; *) library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' ;; esac dynamic_linker='Win32 ld.exe' # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext' soname_spec='${libname}${release}${major}$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext='$(test .$module = .yes && echo .so || echo .dylib)' # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same. if test "$GCC" = yes; then sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"` else sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib' fi sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd1*) dynamic_linker=no ;; kfreebsd*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='GNU ld.so' ;; freebsd*) objformat=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout` version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2*) shlibpath_overrides_runpath=yes ;; freebsd3.01* | freebsdelf3.01*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; *) # from 3.2 on shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; esac ;; gnu*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case "$host_cpu" in ia64*) shrext='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' if test "X$HPUX_IA64_MODE" = X32; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" fi sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; hppa*64*) shrext='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555. postinstall_cmds='chmod 555 $lib' ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test "$lt_cv_prog_gnu_ld" = yes; then version_type=linux else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; # This must be Linux ELF. linux*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; nto-qnx*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; openbsd*) version_type=sunos need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then case $host_os in openbsd2.[89] | openbsd2.[89].*) shlibpath_overrides_runpath=no ;; *) shlibpath_overrides_runpath=yes ;; esac else shlibpath_overrides_runpath=yes fi ;; os2*) libname_spec='$name' shrext=".dll" need_lib_prefix=no library_names_spec='$libname${shared_ext} $libname.a' dynamic_linker='OS/2 ld.exe' shlibpath_var=LIBPATH ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" ;; sco3.2v5*) version_type=osf soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH ;; solaris*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test "$with_gnu_ld" = yes; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no export_dynamic_flag_spec='${wl}-Blargedynsym' runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec ;then version_type=linux library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' soname_spec='$libname${shared_ext}.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; uts4*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac { echo "$as_me:$LINENO: result: $dynamic_linker" >&5 echo "${ECHO_T}$dynamic_linker" >&6; } test "$dynamic_linker" = no && can_build_shared=no { echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5 echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6; } hardcode_action_F77= if test -n "$hardcode_libdir_flag_spec_F77" || \ test -n "$runpath_var F77" || \ test "X$hardcode_automatic_F77"="Xyes" ; then # We can hardcode non-existant directories. if test "$hardcode_direct_F77" != no && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, F77)" != no && test "$hardcode_minus_L_F77" != no; then # Linking always hardcodes the temporary library directory. hardcode_action_F77=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. hardcode_action_F77=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. hardcode_action_F77=unsupported fi { echo "$as_me:$LINENO: result: $hardcode_action_F77" >&5 echo "${ECHO_T}$hardcode_action_F77" >&6; } if test "$hardcode_action_F77" = relink; then # Fast installation is not supported enable_fast_install=no elif test "$shlibpath_overrides_runpath" = yes || test "$enable_shared" = no; then # Fast installation is not necessary enable_fast_install=needless fi striplib= old_striplib= { echo "$as_me:$LINENO: checking whether stripping libraries is possible" >&5 echo $ECHO_N "checking whether stripping libraries is possible... $ECHO_C" >&6; } if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" test -z "$striplib" && striplib="$STRIP --strip-unneeded" # # # The following section is a PATCH to overcome the # stripped import library issues under cygwin case $host_os in cygwin*) striplib= { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } ;; *) { echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6; } ;; esac # # # AC_MSG_RESULT([yes]) # # else # FIXME - insert some real tests, host_os isn't really good enough case $host_os in darwin*) if test -n "$STRIP" ; then striplib="$STRIP -x" { echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi ;; *) { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } ;; esac fi # The else clause should only fire when bootstrapping the # libtool distribution, otherwise you forgot to ship ltmain.sh # with your package, and you will get complaints that there are # no rules to generate ltmain.sh. if test -f "$ltmain"; then # See if we are running on zsh, and set the options which allow our commands through # without removal of \ escapes. if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi # Now quote all the things that may contain metacharacters while being # careful not to overquote the AC_SUBSTed values. We take copies of the # variables and quote the copies for generation of the libtool script. for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC NM SED SHELL \ libname_spec library_names_spec soname_spec extract_expsyms_cmds \ old_striplib striplib file_magic_cmd finish_cmds finish_eval \ deplibs_check_method reload_flag reload_cmds need_locks \ lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \ lt_cv_sys_global_symbol_to_c_name_address \ sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ old_postinstall_cmds old_postuninstall_cmds \ compiler_F77 \ CC_F77 \ LD_F77 \ lt_prog_compiler_wl_F77 \ lt_prog_compiler_pic_F77 \ lt_prog_compiler_static_F77 \ lt_prog_compiler_no_builtin_flag_F77 \ export_dynamic_flag_spec_F77 \ thread_safe_flag_spec_F77 \ whole_archive_flag_spec_F77 \ enable_shared_with_static_runtimes_F77 \ old_archive_cmds_F77 \ old_archive_from_new_cmds_F77 \ predep_objects_F77 \ postdep_objects_F77 \ predeps_F77 \ postdeps_F77 \ compiler_lib_search_path_F77 \ archive_cmds_F77 \ archive_expsym_cmds_F77 \ postinstall_cmds_F77 \ postuninstall_cmds_F77 \ old_archive_from_expsyms_cmds_F77 \ allow_undefined_flag_F77 \ no_undefined_flag_F77 \ export_symbols_cmds_F77 \ hardcode_libdir_flag_spec_F77 \ hardcode_libdir_flag_spec_ld_F77 \ hardcode_libdir_separator_F77 \ hardcode_automatic_F77 \ module_cmds_F77 \ module_expsym_cmds_F77 \ lt_cv_prog_compiler_c_o_F77 \ exclude_expsyms_F77 \ include_expsyms_F77; do case $var in old_archive_cmds_F77 | \ old_archive_from_new_cmds_F77 | \ archive_cmds_F77 | \ archive_expsym_cmds_F77 | \ module_cmds_F77 | \ module_expsym_cmds_F77 | \ old_archive_from_expsyms_cmds_F77 | \ export_symbols_cmds_F77 | \ extract_expsyms_cmds | reload_cmds | finish_cmds | \ postinstall_cmds | postuninstall_cmds | \ old_postinstall_cmds | old_postuninstall_cmds | \ sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) # Double-quote double-evaled strings. eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" ;; *) eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" ;; esac done case $lt_echo in *'\$0 --fallback-echo"') lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'` ;; esac cfgfile="$ofile" cat <<__EOF__ >> "$cfgfile" # ### BEGIN LIBTOOL TAG CONFIG: $tagname # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # Shell to use when invoking shell scripts. SHELL=$lt_SHELL # Whether or not to build shared libraries. build_libtool_libs=$enable_shared # Whether or not to build static libraries. build_old_libs=$enable_static # Whether or not to add -lc for building shared libraries. build_libtool_need_lc=$archive_cmds_need_lc_F77 # Whether or not to disallow shared libs when runtime libs are static allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_F77 # Whether or not to optimize for fast installation. fast_install=$enable_fast_install # The host system. host_alias=$host_alias host=$host # An echo program that does not interpret backslashes. echo=$lt_echo # The archiver. AR=$lt_AR AR_FLAGS=$lt_AR_FLAGS # A C compiler. LTCC=$lt_LTCC # A language-specific compiler. CC=$lt_compiler_F77 # Is the compiler the GNU C compiler? with_gcc=$GCC_F77 # An ERE matcher. EGREP=$lt_EGREP # The linker used to build libraries. LD=$lt_LD_F77 # Whether we need hard or soft links. LN_S=$lt_LN_S # A BSD-compatible nm program. NM=$lt_NM # A symbol stripping program STRIP=$STRIP # Used to examine libraries when file_magic_cmd begins "file" MAGIC_CMD=$MAGIC_CMD # Used on cygwin: DLL creation program. DLLTOOL="$DLLTOOL" # Used on cygwin: object dumper. OBJDUMP="$OBJDUMP" # Used on cygwin: assembler. AS="$AS" # The name of the directory that contains temporary libtool files. objdir=$objdir # How to create reloadable object files. reload_flag=$lt_reload_flag reload_cmds=$lt_reload_cmds # How to pass a linker flag through the compiler. wl=$lt_lt_prog_compiler_wl_F77 # Object file suffix (normally "o"). objext="$ac_objext" # Old archive suffix (normally "a"). libext="$libext" # Shared library suffix (normally ".so"). shrext='$shrext' # Executable file suffix (normally ""). exeext="$exeext" # Additional compiler flags for building library objects. pic_flag=$lt_lt_prog_compiler_pic_F77 pic_mode=$pic_mode # What is the maximum length of a command? max_cmd_len=$lt_cv_sys_max_cmd_len # Does compiler simultaneously support -c and -o options? compiler_c_o=$lt_lt_cv_prog_compiler_c_o_F77 # Must we lock files when doing compilation ? need_locks=$lt_need_locks # Do we need the lib prefix for modules? need_lib_prefix=$need_lib_prefix # Do we need a version for libraries? need_version=$need_version # Whether dlopen is supported. dlopen_support=$enable_dlopen # Whether dlopen of programs is supported. dlopen_self=$enable_dlopen_self # Whether dlopen of statically linked programs is supported. dlopen_self_static=$enable_dlopen_self_static # Compiler flag to prevent dynamic linking. link_static_flag=$lt_lt_prog_compiler_static_F77 # Compiler flag to turn off builtin functions. no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_F77 # Compiler flag to allow reflexive dlopens. export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_F77 # Compiler flag to generate shared objects directly from archives. whole_archive_flag_spec=$lt_whole_archive_flag_spec_F77 # Compiler flag to generate thread-safe objects. thread_safe_flag_spec=$lt_thread_safe_flag_spec_F77 # Library versioning type. version_type=$version_type # Format of library name prefix. libname_spec=$lt_libname_spec # List of archive names. First name is the real one, the rest are links. # The last name is the one that the linker finds with -lNAME. library_names_spec=$lt_library_names_spec # The coded name of the library, if different from the real name. soname_spec=$lt_soname_spec # Commands used to build and install an old-style archive. RANLIB=$lt_RANLIB old_archive_cmds=$lt_old_archive_cmds_F77 old_postinstall_cmds=$lt_old_postinstall_cmds old_postuninstall_cmds=$lt_old_postuninstall_cmds # Create an old-style archive from a shared archive. old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_F77 # Create a temporary old-style archive to link instead of a shared archive. old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_F77 # Commands used to build and install a shared archive. archive_cmds=$lt_archive_cmds_F77 archive_expsym_cmds=$lt_archive_expsym_cmds_F77 postinstall_cmds=$lt_postinstall_cmds postuninstall_cmds=$lt_postuninstall_cmds # Commands used to build a loadable module (assumed same as above if empty) module_cmds=$lt_module_cmds_F77 module_expsym_cmds=$lt_module_expsym_cmds_F77 # Commands to strip libraries. old_striplib=$lt_old_striplib striplib=$lt_striplib # Dependencies to place before the objects being linked to create a # shared library. predep_objects=$lt_predep_objects_F77 # Dependencies to place after the objects being linked to create a # shared library. postdep_objects=$lt_postdep_objects_F77 # Dependencies to place before the objects being linked to create a # shared library. predeps=$lt_predeps_F77 # Dependencies to place after the objects being linked to create a # shared library. postdeps=$lt_postdeps_F77 # The library search path used internally by the compiler when linking # a shared library. compiler_lib_search_path=$lt_compiler_lib_search_path_F77 # Method to check whether dependent libraries are shared objects. deplibs_check_method=$lt_deplibs_check_method # Command to use when deplibs_check_method == file_magic. file_magic_cmd=$lt_file_magic_cmd # Flag that allows shared libraries with undefined symbols to be built. allow_undefined_flag=$lt_allow_undefined_flag_F77 # Flag that forces no undefined symbols. no_undefined_flag=$lt_no_undefined_flag_F77 # Commands used to finish a libtool library installation in a directory. finish_cmds=$lt_finish_cmds # Same as above, but a single script fragment to be evaled but not shown. finish_eval=$lt_finish_eval # Take the output of nm and produce a listing of raw symbols and C names. global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe # Transform the output of nm in a proper C declaration global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl # Transform the output of nm in a C name address pair global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address # This is the shared library runtime path variable. runpath_var=$runpath_var # This is the shared library path variable. shlibpath_var=$shlibpath_var # Is shlibpath searched before the hard-coded library search path? shlibpath_overrides_runpath=$shlibpath_overrides_runpath # How to hardcode a shared library path into an executable. hardcode_action=$hardcode_action_F77 # Whether we should hardcode library paths into libraries. hardcode_into_libs=$hardcode_into_libs # Flag to hardcode \$libdir into a binary during linking. # This must work even if \$libdir does not exist. hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_F77 # If ld is used when linking, flag to hardcode \$libdir into # a binary during linking. This must work even if \$libdir does # not exist. hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_F77 # Whether we need a single -rpath flag with a separated argument. hardcode_libdir_separator=$lt_hardcode_libdir_separator_F77 # Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the # resulting binary. hardcode_direct=$hardcode_direct_F77 # Set to yes if using the -LDIR flag during linking hardcodes DIR into the # resulting binary. hardcode_minus_L=$hardcode_minus_L_F77 # Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into # the resulting binary. hardcode_shlibpath_var=$hardcode_shlibpath_var_F77 # Set to yes if building a shared library automatically hardcodes DIR into the library # and all subsequent libraries and executables linked against it. hardcode_automatic=$hardcode_automatic_F77 # Variables whose values should be saved in libtool wrapper scripts and # restored at relink time. variables_saved_for_relink="$variables_saved_for_relink" # Whether libtool must link a program against all its dependency libraries. link_all_deplibs=$link_all_deplibs_F77 # Compile-time system search path for libraries sys_lib_search_path_spec=$lt_sys_lib_search_path_spec # Run-time system search path for libraries sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec # Fix the shell variable \$srcfile for the compiler. fix_srcfile_path="$fix_srcfile_path_F77" # Set to yes if exported symbols are required. always_export_symbols=$always_export_symbols_F77 # The commands to list exported symbols. export_symbols_cmds=$lt_export_symbols_cmds_F77 # The commands to extract the exported symbol list from a shared archive. extract_expsyms_cmds=$lt_extract_expsyms_cmds # Symbols that should not be listed in the preloaded symbols. exclude_expsyms=$lt_exclude_expsyms_F77 # Symbols that must always be exported. include_expsyms=$lt_include_expsyms_F77 # ### END LIBTOOL TAG CONFIG: $tagname __EOF__ else # If there is no Makefile yet, we rely on a make rule to execute # `config.status --recheck' to rerun these tests and create the # libtool script then. test -f Makefile && make "$ltmain" fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu CC="$lt_save_CC" else tagname="" fi ;; GCJ) if test -n "$GCJ" && test "X$GCJ" != "Xno"; then # Source file extension for Java test sources. ac_ext=java # Object file extension for compiled Java test sources. objext=o objext_GCJ=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="class foo {}\n" # Code to be used in simple link tests lt_simple_link_test_code='public class conftest { public static void main(String argv) {}; }\n' # ltmain only uses $CC for tagged configurations so make sure $CC is set. # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # Allow CC to be a program name with arguments. compiler=$CC # Allow CC to be a program name with arguments. lt_save_CC="$CC" CC=${GCJ-"gcj"} compiler=$CC compiler_GCJ=$CC # GCJ did not exist at the time GCC didn't implicitly link libc in. archive_cmds_need_lc_GCJ=no ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... lt_prog_compiler_no_builtin_flag_GCJ= if test "$GCC" = yes; then lt_prog_compiler_no_builtin_flag_GCJ=' -fno-builtin' { echo "$as_me:$LINENO: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 echo $ECHO_N "checking if $compiler supports -fno-rtti -fno-exceptions... $ECHO_C" >&6; } if test "${lt_cv_prog_compiler_rtti_exceptions+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else lt_cv_prog_compiler_rtti_exceptions=no ac_outfile=conftest.$ac_objext printf "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-fno-rtti -fno-exceptions" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:16520: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:16524: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings if test ! -s conftest.err; then lt_cv_prog_compiler_rtti_exceptions=yes fi fi $rm conftest* fi { echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 echo "${ECHO_T}$lt_cv_prog_compiler_rtti_exceptions" >&6; } if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then lt_prog_compiler_no_builtin_flag_GCJ="$lt_prog_compiler_no_builtin_flag_GCJ -fno-rtti -fno-exceptions" else : fi fi lt_prog_compiler_wl_GCJ= lt_prog_compiler_pic_GCJ= lt_prog_compiler_static_GCJ= { echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5 echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6; } if test "$GCC" = yes; then lt_prog_compiler_wl_GCJ='-Wl,' lt_prog_compiler_static_GCJ='-static' case $host_os in aix*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static_GCJ='-Bstatic' fi ;; amigaos*) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. lt_prog_compiler_pic_GCJ='-m68020 -resident32 -malways-restore-a4' ;; beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | pw32* | os2*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_prog_compiler_pic_GCJ='-DDLL_EXPORT' ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files lt_prog_compiler_pic_GCJ='-fno-common' ;; msdosdjgpp*) # Just because we use GCC doesn't mean we suddenly get shared libraries # on systems that don't support them. lt_prog_compiler_can_build_shared_GCJ=no enable_shared=no ;; sysv4*MP*) if test -d /usr/nec; then lt_prog_compiler_pic_GCJ=-Kconform_pic fi ;; hpux*) # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case "$host_cpu" in hppa*64*|ia64*) # +Z the default ;; *) lt_prog_compiler_pic_GCJ='-fPIC' ;; esac ;; *) lt_prog_compiler_pic_GCJ='-fPIC' ;; esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in aix*) lt_prog_compiler_wl_GCJ='-Wl,' if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static_GCJ='-Bstatic' else lt_prog_compiler_static_GCJ='-bnso -bI:/lib/syscalls.exp' fi ;; mingw* | pw32* | os2*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_prog_compiler_pic_GCJ='-DDLL_EXPORT' ;; hpux9* | hpux10* | hpux11*) lt_prog_compiler_wl_GCJ='-Wl,' # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case "$host_cpu" in hppa*64*|ia64*) # +Z the default ;; *) lt_prog_compiler_pic_GCJ='+Z' ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? lt_prog_compiler_static_GCJ='${wl}-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) lt_prog_compiler_wl_GCJ='-Wl,' # PIC (with -KPIC) is the default. lt_prog_compiler_static_GCJ='-non_shared' ;; newsos6) lt_prog_compiler_pic_GCJ='-KPIC' lt_prog_compiler_static_GCJ='-Bstatic' ;; linux*) case $CC in icc* | ecc*) lt_prog_compiler_wl_GCJ='-Wl,' lt_prog_compiler_pic_GCJ='-KPIC' lt_prog_compiler_static_GCJ='-static' ;; ccc*) lt_prog_compiler_wl_GCJ='-Wl,' # All Alpha code is PIC. lt_prog_compiler_static_GCJ='-non_shared' ;; esac ;; osf3* | osf4* | osf5*) lt_prog_compiler_wl_GCJ='-Wl,' # All OSF/1 code is PIC. lt_prog_compiler_static_GCJ='-non_shared' ;; sco3.2v5*) lt_prog_compiler_pic_GCJ='-Kpic' lt_prog_compiler_static_GCJ='-dn' ;; solaris*) lt_prog_compiler_wl_GCJ='-Wl,' lt_prog_compiler_pic_GCJ='-KPIC' lt_prog_compiler_static_GCJ='-Bstatic' ;; sunos4*) lt_prog_compiler_wl_GCJ='-Qoption ld ' lt_prog_compiler_pic_GCJ='-PIC' lt_prog_compiler_static_GCJ='-Bstatic' ;; sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) lt_prog_compiler_wl_GCJ='-Wl,' lt_prog_compiler_pic_GCJ='-KPIC' lt_prog_compiler_static_GCJ='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec ;then lt_prog_compiler_pic_GCJ='-Kconform_pic' lt_prog_compiler_static_GCJ='-Bstatic' fi ;; uts4*) lt_prog_compiler_pic_GCJ='-pic' lt_prog_compiler_static_GCJ='-Bstatic' ;; *) lt_prog_compiler_can_build_shared_GCJ=no ;; esac fi { echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_GCJ" >&5 echo "${ECHO_T}$lt_prog_compiler_pic_GCJ" >&6; } # # Check to make sure the PIC flag actually works. # if test -n "$lt_prog_compiler_pic_GCJ"; then { echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic_GCJ works" >&5 echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic_GCJ works... $ECHO_C" >&6; } if test "${lt_prog_compiler_pic_works_GCJ+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else lt_prog_compiler_pic_works_GCJ=no ac_outfile=conftest.$ac_objext printf "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$lt_prog_compiler_pic_GCJ" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:16753: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:16757: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings if test ! -s conftest.err; then lt_prog_compiler_pic_works_GCJ=yes fi fi $rm conftest* fi { echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works_GCJ" >&5 echo "${ECHO_T}$lt_prog_compiler_pic_works_GCJ" >&6; } if test x"$lt_prog_compiler_pic_works_GCJ" = xyes; then case $lt_prog_compiler_pic_GCJ in "" | " "*) ;; *) lt_prog_compiler_pic_GCJ=" $lt_prog_compiler_pic_GCJ" ;; esac else lt_prog_compiler_pic_GCJ= lt_prog_compiler_can_build_shared_GCJ=no fi fi case "$host_os" in # For platforms which do not support PIC, -DPIC is meaningless: *djgpp*) lt_prog_compiler_pic_GCJ= ;; *) lt_prog_compiler_pic_GCJ="$lt_prog_compiler_pic_GCJ" ;; esac { echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5 echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6; } if test "${lt_cv_prog_compiler_c_o_GCJ+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else lt_cv_prog_compiler_c_o_GCJ=no $rm -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out printf "$lt_simple_compile_test_code" > conftest.$ac_ext # According to Tom Tromey, Ian Lance Taylor reported there are C compilers # that will create temporary files in the current directory regardless of # the output directory. Thus, making CWD read-only will cause this test # to fail, enabling locking or at least warning the user not to do parallel # builds. chmod -w . lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:16820: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:16824: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings if test ! -s out/conftest.err; then lt_cv_prog_compiler_c_o_GCJ=yes fi fi chmod u+w . $rm conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files $rm out/* && rmdir out cd .. rmdir conftest $rm conftest* fi { echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o_GCJ" >&5 echo "${ECHO_T}$lt_cv_prog_compiler_c_o_GCJ" >&6; } hard_links="nottested" if test "$lt_cv_prog_compiler_c_o_GCJ" = no && test "$need_locks" != no; then # do not overwrite the value of need_locks provided by the user { echo "$as_me:$LINENO: checking if we can lock with hard links" >&5 echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6; } hard_links=yes $rm conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no { echo "$as_me:$LINENO: result: $hard_links" >&5 echo "${ECHO_T}$hard_links" >&6; } if test "$hard_links" = no; then { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} need_locks=warn fi else need_locks=no fi { echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5 echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6; } runpath_var= allow_undefined_flag_GCJ= enable_shared_with_static_runtimes_GCJ=no archive_cmds_GCJ= archive_expsym_cmds_GCJ= old_archive_From_new_cmds_GCJ= old_archive_from_expsyms_cmds_GCJ= export_dynamic_flag_spec_GCJ= whole_archive_flag_spec_GCJ= thread_safe_flag_spec_GCJ= hardcode_libdir_flag_spec_GCJ= hardcode_libdir_flag_spec_ld_GCJ= hardcode_libdir_separator_GCJ= hardcode_direct_GCJ=no hardcode_minus_L_GCJ=no hardcode_shlibpath_var_GCJ=unsupported link_all_deplibs_GCJ=unknown hardcode_automatic_GCJ=no module_cmds_GCJ= module_expsym_cmds_GCJ= always_export_symbols_GCJ=no export_symbols_cmds_GCJ='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list include_expsyms_GCJ= # exclude_expsyms can be an extended regexp of symbols to exclude # it will be wrapped by ` (' and `)$', so one must not match beginning or # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', # as well as any symbol that contains `d'. exclude_expsyms_GCJ="_GLOBAL_OFFSET_TABLE_" # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. extract_expsyms_cmds= 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_GCJ=yes if test "$with_gnu_ld" = yes; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='${wl}' # See if GNU ld supports shared libraries. case $host_os in aix3* | aix4* | aix5*) # On AIX/PPC, the GNU linker is very broken if test "$host_cpu" != ia64; then ld_shlibs_GCJ=no cat <&2 *** Warning: the GNU linker, at least up to release 2.9.1, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you *** really care for shared libraries, you may want to modify your PATH *** so that a non-GNU linker is found, and then restart. EOF fi ;; amigaos*) archive_cmds_GCJ='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec_GCJ='-L$libdir' hardcode_minus_L_GCJ=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't use # them. ld_shlibs_GCJ=no ;; beos*) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then allow_undefined_flag_GCJ=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME archive_cmds_GCJ='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else ld_shlibs_GCJ=no fi ;; cygwin* | mingw* | pw32*) # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, GCJ) is actually meaningless, # as there is no search path for DLLs. hardcode_libdir_flag_spec_GCJ='-L$libdir' allow_undefined_flag_GCJ=unsupported always_export_symbols_GCJ=no enable_shared_with_static_runtimes_GCJ=yes export_symbols_cmds_GCJ='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGS] /s/.* \([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW] /s/.* //'\'' | sort | uniq > $export_symbols' if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... archive_expsym_cmds_GCJ='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib' else ld_shlibs=no fi ;; netbsd*) if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then archive_cmds_GCJ='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' fi ;; solaris* | sysv5*) if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then ld_shlibs_GCJ=no cat <&2 *** Warning: The releases 2.8.* of the GNU linker cannot reliably *** create shared libraries on Solaris systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.9.1 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. EOF elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs_GCJ=no fi ;; sunos4*) archive_cmds_GCJ='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= hardcode_direct_GCJ=yes hardcode_shlibpath_var_GCJ=no ;; *) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs_GCJ=no fi ;; esac if test "$ld_shlibs_GCJ" = yes; then runpath_var=LD_RUN_PATH hardcode_libdir_flag_spec_GCJ='${wl}--rpath ${wl}$libdir' export_dynamic_flag_spec_GCJ='${wl}--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then whole_archive_flag_spec_GCJ="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else whole_archive_flag_spec_GCJ= fi fi else # PORTME fill in a description of your system's linker (not GNU ld) case $host_os in aix3*) allow_undefined_flag_GCJ=unsupported always_export_symbols_GCJ=yes archive_expsym_cmds_GCJ='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. hardcode_minus_L_GCJ=yes if test "$GCC" = yes && test -z "$link_static_flag"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. hardcode_direct_GCJ=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 exp_sym_flag='-Bexport' no_entry_flag="" else # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm if $NM -V 2>&1 | grep 'GNU' > /dev/null; then export_symbols_cmds_GCJ='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' else export_symbols_cmds_GCJ='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # 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 exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. archive_cmds_GCJ='' hardcode_direct_GCJ=yes hardcode_libdir_separator_GCJ=':' link_all_deplibs_GCJ=yes if test "$GCC" = yes; then case $host_os in aix4.012|aix4.012.*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && \ strings "$collect2name" | grep resolve_lib_name >/dev/null then # We have reworked collect2 hardcode_direct_GCJ=yes else # We have old collect2 hardcode_direct_GCJ=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking hardcode_minus_L_GCJ=yes hardcode_libdir_flag_spec_GCJ='-L$libdir' hardcode_libdir_separator_GCJ= fi esac shared_flag='-shared' else # not using gcc if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi fi # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. always_export_symbols_GCJ=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. allow_undefined_flag_GCJ='-berok' # Determine the default libpath from the value encoded in an empty executable. 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 { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'` # Check for a 64-bit object if we didn't find anything. if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'`; fi else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi hardcode_libdir_flag_spec_GCJ='${wl}-blibpath:$libdir:'"$aix_libpath" archive_expsym_cmds_GCJ="\$CC"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then hardcode_libdir_flag_spec_GCJ='${wl}-R $libdir:/usr/lib:/lib' allow_undefined_flag_GCJ="-z nodefs" archive_expsym_cmds_GCJ="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an empty executable. 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 { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'` # Check for a 64-bit object if we didn't find anything. if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'`; fi else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi hardcode_libdir_flag_spec_GCJ='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. no_undefined_flag_GCJ=' ${wl}-bernotok' allow_undefined_flag_GCJ=' ${wl}-berok' # -bexpall does not export symbols beginning with underscore (_) always_export_symbols_GCJ=yes # Exported symbols can be pulled into shared objects from archives whole_archive_flag_spec_GCJ=' ' archive_cmds_need_lc_GCJ=yes # This is similar to how AIX traditionally builds it's shared libraries. archive_expsym_cmds_GCJ="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; amigaos*) archive_cmds_GCJ='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec_GCJ='-L$libdir' hardcode_minus_L_GCJ=yes # see comment about different semantics on the GNU ld section ld_shlibs_GCJ=no ;; bsdi4*) export_dynamic_flag_spec_GCJ=-rdynamic ;; 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_GCJ=' ' allow_undefined_flag_GCJ=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext=".dll" # FIXME: Setting linknames here is a bad hack. archive_cmds_GCJ='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. old_archive_From_new_cmds_GCJ='true' # FIXME: Should let the user specify the lib program. old_archive_cmds_GCJ='lib /OUT:$oldlib$oldobjs$old_deplibs' fix_srcfile_path='`cygpath -w "$srcfile"`' enable_shared_with_static_runtimes_GCJ=yes ;; darwin* | rhapsody*) if test "$GXX" = yes ; then archive_cmds_need_lc_GCJ=no case "$host_os" in rhapsody* | darwin1.[012]) allow_undefined_flag_GCJ='-undefined suppress' ;; *) # Darwin 1.3 on if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then allow_undefined_flag_GCJ='-flat_namespace -undefined suppress' else case ${MACOSX_DEPLOYMENT_TARGET} in 10.[012]) allow_undefined_flag_GCJ='-flat_namespace -undefined suppress' ;; 10.*) allow_undefined_flag_GCJ='-undefined dynamic_lookup' ;; esac fi ;; esac lt_int_apple_cc_single_mod=no output_verbose_link_cmd='echo' if $CC -dumpspecs 2>&1 | grep 'single_module' >/dev/null ; then lt_int_apple_cc_single_mod=yes fi if test "X$lt_int_apple_cc_single_mod" = Xyes ; then archive_cmds_GCJ='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' else archive_cmds_GCJ='$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring' fi module_cmds_GCJ='$CC ${wl}-bind_at_load $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's if test "X$lt_int_apple_cc_single_mod" = Xyes ; then archive_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' else archive_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' fi module_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' hardcode_direct_GCJ=no hardcode_automatic_GCJ=yes hardcode_shlibpath_var_GCJ=unsupported whole_archive_flag_spec_GCJ='-all_load $convenience' link_all_deplibs_GCJ=yes else ld_shlibs_GCJ=no fi ;; dgux*) archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec_GCJ='-L$libdir' hardcode_shlibpath_var_GCJ=no ;; freebsd1*) ld_shlibs_GCJ=no ;; # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little # extra space). freebsd2.2*) archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' hardcode_libdir_flag_spec_GCJ='-R$libdir' hardcode_direct_GCJ=yes hardcode_shlibpath_var_GCJ=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2*) archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_direct_GCJ=yes hardcode_minus_L_GCJ=yes hardcode_shlibpath_var_GCJ=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd* | kfreebsd*-gnu) archive_cmds_GCJ='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec_GCJ='-R$libdir' hardcode_direct_GCJ=yes hardcode_shlibpath_var_GCJ=no ;; hpux9*) if test "$GCC" = yes; then archive_cmds_GCJ='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else archive_cmds_GCJ='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' fi hardcode_libdir_flag_spec_GCJ='${wl}+b ${wl}$libdir' hardcode_libdir_separator_GCJ=: hardcode_direct_GCJ=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L_GCJ=yes export_dynamic_flag_spec_GCJ='${wl}-E' ;; hpux10* | hpux11*) if test "$GCC" = yes -a "$with_gnu_ld" = no; then case "$host_cpu" in hppa*64*|ia64*) archive_cmds_GCJ='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; *) archive_cmds_GCJ='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case "$host_cpu" in hppa*64*|ia64*) archive_cmds_GCJ='$LD -b +h $soname -o $lib $libobjs $deplibs $linker_flags' ;; *) archive_cmds_GCJ='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' ;; esac fi if test "$with_gnu_ld" = no; then case "$host_cpu" in hppa*64*) hardcode_libdir_flag_spec_GCJ='${wl}+b ${wl}$libdir' hardcode_libdir_flag_spec_ld_GCJ='+b $libdir' hardcode_libdir_separator_GCJ=: hardcode_direct_GCJ=no hardcode_shlibpath_var_GCJ=no ;; ia64*) hardcode_libdir_flag_spec_GCJ='-L$libdir' hardcode_direct_GCJ=no hardcode_shlibpath_var_GCJ=no # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L_GCJ=yes ;; *) hardcode_libdir_flag_spec_GCJ='${wl}+b ${wl}$libdir' hardcode_libdir_separator_GCJ=: hardcode_direct_GCJ=yes export_dynamic_flag_spec_GCJ='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L_GCJ=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) if test "$GCC" = yes; then archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else archive_cmds_GCJ='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' hardcode_libdir_flag_spec_ld_GCJ='-rpath $libdir' fi hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator_GCJ=: link_all_deplibs_GCJ=yes ;; netbsd*) if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else archive_cmds_GCJ='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi hardcode_libdir_flag_spec_GCJ='-R$libdir' hardcode_direct_GCJ=yes hardcode_shlibpath_var_GCJ=no ;; newsos6) archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct_GCJ=yes hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator_GCJ=: hardcode_shlibpath_var_GCJ=no ;; openbsd*) hardcode_direct_GCJ=yes hardcode_shlibpath_var_GCJ=no if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then archive_cmds_GCJ='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec_GCJ='${wl}-rpath,$libdir' export_dynamic_flag_spec_GCJ='${wl}-E' else case $host_os in openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec_GCJ='-R$libdir' ;; *) archive_cmds_GCJ='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec_GCJ='${wl}-rpath,$libdir' ;; esac fi ;; os2*) hardcode_libdir_flag_spec_GCJ='-L$libdir' hardcode_minus_L_GCJ=yes allow_undefined_flag_GCJ=unsupported archive_cmds_GCJ='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' old_archive_From_new_cmds_GCJ='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' ;; osf3*) if test "$GCC" = yes; then allow_undefined_flag_GCJ=' ${wl}-expect_unresolved ${wl}\*' archive_cmds_GCJ='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else allow_undefined_flag_GCJ=' -expect_unresolved \*' archive_cmds_GCJ='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' fi hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator_GCJ=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag if test "$GCC" = yes; then allow_undefined_flag_GCJ=' ${wl}-expect_unresolved ${wl}\*' archive_cmds_GCJ='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir' else allow_undefined_flag_GCJ=' -expect_unresolved \*' archive_cmds_GCJ='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' archive_expsym_cmds_GCJ='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~ $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib~$rm $lib.exp' # Both c and cxx compiler support -rpath directly hardcode_libdir_flag_spec_GCJ='-rpath $libdir' fi hardcode_libdir_separator_GCJ=: ;; sco3.2v5*) archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var_GCJ=no export_dynamic_flag_spec_GCJ='${wl}-Bexport' runpath_var=LD_RUN_PATH hardcode_runpath_var=yes ;; solaris*) no_undefined_flag_GCJ=' -z text' if test "$GCC" = yes; then archive_cmds_GCJ='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_GCJ='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp' else archive_cmds_GCJ='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' archive_expsym_cmds_GCJ='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' fi hardcode_libdir_flag_spec_GCJ='-R$libdir' hardcode_shlibpath_var_GCJ=no case $host_os in solaris2.[0-5] | solaris2.[0-5].*) ;; *) # Supported since Solaris 2.6 (maybe 2.5.1?) whole_archive_flag_spec_GCJ='-z allextract$convenience -z defaultextract' ;; esac link_all_deplibs_GCJ=yes ;; sunos4*) if test "x$host_vendor" = xsequent; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. archive_cmds_GCJ='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds_GCJ='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi hardcode_libdir_flag_spec_GCJ='-L$libdir' hardcode_direct_GCJ=yes hardcode_minus_L_GCJ=yes hardcode_shlibpath_var_GCJ=no ;; sysv4) case $host_vendor in sni) archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct_GCJ=yes # is this really true??? ;; siemens) ## LD is ld it makes a PLAMLIB ## CC just makes a GrossModule. archive_cmds_GCJ='$LD -G -o $lib $libobjs $deplibs $linker_flags' reload_cmds_GCJ='$CC -r -o $output$reload_objs' hardcode_direct_GCJ=no ;; motorola) archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct_GCJ=no #Motorola manual says yes, but my tests say they lie ;; esac runpath_var='LD_RUN_PATH' hardcode_shlibpath_var_GCJ=no ;; sysv4.3*) archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var_GCJ=no export_dynamic_flag_spec_GCJ='-Bexport' ;; sysv4*MP*) if test -d /usr/nec; then archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var_GCJ=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes ld_shlibs_GCJ=yes fi ;; sysv4.2uw2*) archive_cmds_GCJ='$LD -G -o $lib $libobjs $deplibs $linker_flags' hardcode_direct_GCJ=yes hardcode_minus_L_GCJ=no hardcode_shlibpath_var_GCJ=no hardcode_runpath_var=yes runpath_var=LD_RUN_PATH ;; sysv5OpenUNIX8* | sysv5UnixWare7* | sysv5uw[78]* | unixware7*) no_undefined_flag_GCJ='${wl}-z ${wl}text' if test "$GCC" = yes; then archive_cmds_GCJ='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds_GCJ='$CC -G ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' fi runpath_var='LD_RUN_PATH' hardcode_shlibpath_var_GCJ=no ;; sysv5*) no_undefined_flag_GCJ=' -z text' # $CC -shared without GNU ld will not create a library from C++ # object files and a static libstdc++, better avoid it by now archive_cmds_GCJ='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' archive_expsym_cmds_GCJ='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' hardcode_libdir_flag_spec_GCJ= hardcode_shlibpath_var_GCJ=no runpath_var='LD_RUN_PATH' ;; uts4*) archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec_GCJ='-L$libdir' hardcode_shlibpath_var_GCJ=no ;; *) ld_shlibs_GCJ=no ;; esac fi { echo "$as_me:$LINENO: result: $ld_shlibs_GCJ" >&5 echo "${ECHO_T}$ld_shlibs_GCJ" >&6; } test "$ld_shlibs_GCJ" = no && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test "$GCC" = yes; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi # # Do we need to explicitly link libc? # case "x$archive_cmds_need_lc_GCJ" in x|xyes) # Assume -lc should be added archive_cmds_need_lc_GCJ=yes if test "$enable_shared" = yes && test "$GCC" = yes; then case $archive_cmds_GCJ in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. { echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5 echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6; } $rm conftest* printf "$lt_simple_compile_test_code" > conftest.$ac_ext 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); } 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$lt_prog_compiler_wl_GCJ compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$allow_undefined_flag_GCJ allow_undefined_flag_GCJ= if { (eval echo "$as_me:$LINENO: \"$archive_cmds_GCJ 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5 (eval $archive_cmds_GCJ 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } then archive_cmds_need_lc_GCJ=no else archive_cmds_need_lc_GCJ=yes fi allow_undefined_flag_GCJ=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $rm conftest* { echo "$as_me:$LINENO: result: $archive_cmds_need_lc_GCJ" >&5 echo "${ECHO_T}$archive_cmds_need_lc_GCJ" >&6; } ;; esac fi ;; esac { echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5 echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6; } library_names_spec= libname_spec='lib$name' soname_spec= shrext=".so" postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" if test "$GCC" = yes; then sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown case $host_os in aix3*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='${libname}${release}${shared_ext}$major' ;; aix4* | aix5*) version_type=linux need_lib_prefix=no need_version=no hardcode_into_libs=yes if test "$host_cpu" = ia64; then # AIX 5 supports IA64 library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line `#! .'. This would cause the generated library to # depend on `.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[01] | aix4.[01].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then : else can_build_shared=no fi ;; esac # AIX (on Power*) has no versioning support, so currently we can not hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. if test "$aix_use_runtimelinking" = yes; then # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' else # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='${libname}${release}.a $libname.a' soname_spec='${libname}${release}${shared_ext}$major' fi shlibpath_var=LIBPATH fi ;; amigaos*) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; beos*) library_names_spec='${libname}${shared_ext}' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi4*) version_type=linux need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32*) version_type=windows shrext=".dll" need_version=no need_lib_prefix=no case $GCC,$host_os in yes,cygwin* | yes,mingw* | yes,pw32*) library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $rm \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" ;; mingw*) # MinGW DLLs use traditional 'lib' prefix soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then # It is most probably a Windows format PATH printed by # mingw gcc, but we are running on Cygwin. Gcc prints its search # path with ; separators, and with drive letters. We can handle the # drive letters (cygwin fileutils understands them), so leave them, # especially as we might pass files found there to a mingw objdump, # which wouldn't understand a cygwinified path. Ahh. sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/./-/g'`${versuffix}${shared_ext}' ;; esac ;; *) library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' ;; esac dynamic_linker='Win32 ld.exe' # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext' soname_spec='${libname}${release}${major}$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext='$(test .$module = .yes && echo .so || echo .dylib)' # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same. if test "$GCC" = yes; then sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"` else sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib' fi sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd1*) dynamic_linker=no ;; kfreebsd*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='GNU ld.so' ;; freebsd*) objformat=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout` version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2*) shlibpath_overrides_runpath=yes ;; freebsd3.01* | freebsdelf3.01*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; *) # from 3.2 on shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; esac ;; gnu*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case "$host_cpu" in ia64*) shrext='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' if test "X$HPUX_IA64_MODE" = X32; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" fi sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; hppa*64*) shrext='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555. postinstall_cmds='chmod 555 $lib' ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test "$lt_cv_prog_gnu_ld" = yes; then version_type=linux else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; # This must be Linux ELF. linux*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; nto-qnx*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; openbsd*) version_type=sunos need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then case $host_os in openbsd2.[89] | openbsd2.[89].*) shlibpath_overrides_runpath=no ;; *) shlibpath_overrides_runpath=yes ;; esac else shlibpath_overrides_runpath=yes fi ;; os2*) libname_spec='$name' shrext=".dll" need_lib_prefix=no library_names_spec='$libname${shared_ext} $libname.a' dynamic_linker='OS/2 ld.exe' shlibpath_var=LIBPATH ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" ;; sco3.2v5*) version_type=osf soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH ;; solaris*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test "$with_gnu_ld" = yes; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no export_dynamic_flag_spec='${wl}-Blargedynsym' runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec ;then version_type=linux library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' soname_spec='$libname${shared_ext}.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; uts4*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac { echo "$as_me:$LINENO: result: $dynamic_linker" >&5 echo "${ECHO_T}$dynamic_linker" >&6; } test "$dynamic_linker" = no && can_build_shared=no { echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5 echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6; } hardcode_action_GCJ= if test -n "$hardcode_libdir_flag_spec_GCJ" || \ test -n "$runpath_var GCJ" || \ test "X$hardcode_automatic_GCJ"="Xyes" ; then # We can hardcode non-existant directories. if test "$hardcode_direct_GCJ" != no && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, GCJ)" != no && test "$hardcode_minus_L_GCJ" != no; then # Linking always hardcodes the temporary library directory. hardcode_action_GCJ=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. hardcode_action_GCJ=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. hardcode_action_GCJ=unsupported fi { echo "$as_me:$LINENO: result: $hardcode_action_GCJ" >&5 echo "${ECHO_T}$hardcode_action_GCJ" >&6; } if test "$hardcode_action_GCJ" = relink; then # Fast installation is not supported enable_fast_install=no elif test "$shlibpath_overrides_runpath" = yes || test "$enable_shared" = no; then # Fast installation is not necessary enable_fast_install=needless fi striplib= old_striplib= { echo "$as_me:$LINENO: checking whether stripping libraries is possible" >&5 echo $ECHO_N "checking whether stripping libraries is possible... $ECHO_C" >&6; } if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" test -z "$striplib" && striplib="$STRIP --strip-unneeded" # # # The following section is a PATCH to overcome the # stripped import library issues under cygwin case $host_os in cygwin*) striplib= { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } ;; *) { echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6; } ;; esac # # # AC_MSG_RESULT([yes]) # # else # FIXME - insert some real tests, host_os isn't really good enough case $host_os in darwin*) if test -n "$STRIP" ; then striplib="$STRIP -x" { echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi ;; *) { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } ;; esac fi if test "x$enable_dlopen" != xyes; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown else lt_cv_dlopen=no lt_cv_dlopen_libs= case $host_os in beos*) lt_cv_dlopen="load_add_on" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; mingw* | pw32*) lt_cv_dlopen="LoadLibrary" lt_cv_dlopen_libs= ;; cygwin*) lt_cv_dlopen="dlopen" lt_cv_dlopen_libs= ;; darwin*) # if libdl is installed we need to link against it { echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5 echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6; } if test "${ac_cv_lib_dl_dlopen+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $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 GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_dl_dlopen=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_dl_dlopen=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5 echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6; } if test $ac_cv_lib_dl_dlopen = yes; then lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" else lt_cv_dlopen="dyld" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes fi ;; *) { echo "$as_me:$LINENO: checking for shl_load" >&5 echo $ECHO_N "checking for shl_load... $ECHO_C" >&6; } if test "${ac_cv_func_shl_load+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 shl_load to an innocuous variant, in case declares shl_load. For example, HP-UX 11i declares gettimeofday. */ #define shl_load innocuous_shl_load /* System header to define __stub macros and hopefully few prototypes, which can conflict with char shl_load (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef shl_load /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char shl_load (); /* 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_shl_load || defined __stub___shl_load choke me #endif int main () { return shl_load (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_func_shl_load=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func_shl_load=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_func_shl_load" >&5 echo "${ECHO_T}$ac_cv_func_shl_load" >&6; } if test $ac_cv_func_shl_load = yes; then lt_cv_dlopen="shl_load" else { echo "$as_me:$LINENO: checking for shl_load in -ldld" >&5 echo $ECHO_N "checking for shl_load in -ldld... $ECHO_C" >&6; } if test "${ac_cv_lib_dld_shl_load+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $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 GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char shl_load (); int main () { return shl_load (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_dld_shl_load=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_dld_shl_load=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_dld_shl_load" >&5 echo "${ECHO_T}$ac_cv_lib_dld_shl_load" >&6; } if test $ac_cv_lib_dld_shl_load = yes; then lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-dld" else { echo "$as_me:$LINENO: checking for dlopen" >&5 echo $ECHO_N "checking for dlopen... $ECHO_C" >&6; } if test "${ac_cv_func_dlopen+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 dlopen to an innocuous variant, in case declares dlopen. For example, HP-UX 11i declares gettimeofday. */ #define dlopen innocuous_dlopen /* System header to define __stub macros and hopefully few prototypes, which can conflict with char dlopen (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef dlopen /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); /* 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_dlopen || defined __stub___dlopen choke me #endif int main () { return dlopen (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_func_dlopen=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func_dlopen=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_func_dlopen" >&5 echo "${ECHO_T}$ac_cv_func_dlopen" >&6; } if test $ac_cv_func_dlopen = yes; then lt_cv_dlopen="dlopen" else { echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5 echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6; } if test "${ac_cv_lib_dl_dlopen+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $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 GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_dl_dlopen=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_dl_dlopen=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5 echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6; } if test $ac_cv_lib_dl_dlopen = yes; then lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" else { echo "$as_me:$LINENO: checking for dlopen in -lsvld" >&5 echo $ECHO_N "checking for dlopen in -lsvld... $ECHO_C" >&6; } if test "${ac_cv_lib_svld_dlopen+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsvld $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 GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_svld_dlopen=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_svld_dlopen=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_svld_dlopen" >&5 echo "${ECHO_T}$ac_cv_lib_svld_dlopen" >&6; } if test $ac_cv_lib_svld_dlopen = yes; then lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld" else { echo "$as_me:$LINENO: checking for dld_link in -ldld" >&5 echo $ECHO_N "checking for dld_link in -ldld... $ECHO_C" >&6; } if test "${ac_cv_lib_dld_dld_link+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $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 GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dld_link (); int main () { return dld_link (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_dld_dld_link=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_dld_dld_link=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_dld_dld_link" >&5 echo "${ECHO_T}$ac_cv_lib_dld_dld_link" >&6; } if test $ac_cv_lib_dld_dld_link = yes; then lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld" fi fi fi fi fi fi ;; esac if test "x$lt_cv_dlopen" != xno; then enable_dlopen=yes else enable_dlopen=no fi case $lt_cv_dlopen in dlopen) save_CPPFLAGS="$CPPFLAGS" test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" save_LDFLAGS="$LDFLAGS" eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" save_LIBS="$LIBS" LIBS="$lt_cv_dlopen_libs $LIBS" { echo "$as_me:$LINENO: checking whether a program can dlopen itself" >&5 echo $ECHO_N "checking whether a program can dlopen itself... $ECHO_C" >&6; } if test "${lt_cv_dlopen_self+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test "$cross_compiling" = yes; then : lt_cv_dlopen_self=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext < #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif #ifdef __cplusplus extern "C" void exit (int); #endif void fnord() { int i=42;} int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; /* dlclose (self); */ } exit (status); } EOF 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); } && test -s conftest${ac_exeext} 2>/dev/null; then (./conftest; exit; ) 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; x$lt_unknown|x*) lt_cv_dlopen_self=no ;; esac else : # compilation failed lt_cv_dlopen_self=no fi fi rm -fr conftest* fi { echo "$as_me:$LINENO: result: $lt_cv_dlopen_self" >&5 echo "${ECHO_T}$lt_cv_dlopen_self" >&6; } if test "x$lt_cv_dlopen_self" = xyes; then LDFLAGS="$LDFLAGS $link_static_flag" { echo "$as_me:$LINENO: checking whether a statically linked program can dlopen itself" >&5 echo $ECHO_N "checking whether a statically linked program can dlopen itself... $ECHO_C" >&6; } if test "${lt_cv_dlopen_self_static+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test "$cross_compiling" = yes; then : lt_cv_dlopen_self_static=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext < #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif #ifdef __cplusplus extern "C" void exit (int); #endif void fnord() { int i=42;} int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; /* dlclose (self); */ } exit (status); } EOF 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); } && test -s conftest${ac_exeext} 2>/dev/null; then (./conftest; exit; ) 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; x$lt_unknown|x*) lt_cv_dlopen_self_static=no ;; esac else : # compilation failed lt_cv_dlopen_self_static=no fi fi rm -fr conftest* fi { echo "$as_me:$LINENO: result: $lt_cv_dlopen_self_static" >&5 echo "${ECHO_T}$lt_cv_dlopen_self_static" >&6; } fi CPPFLAGS="$save_CPPFLAGS" LDFLAGS="$save_LDFLAGS" LIBS="$save_LIBS" ;; esac case $lt_cv_dlopen_self in yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; *) enable_dlopen_self=unknown ;; esac case $lt_cv_dlopen_self_static in yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; *) enable_dlopen_self_static=unknown ;; esac fi # The else clause should only fire when bootstrapping the # libtool distribution, otherwise you forgot to ship ltmain.sh # with your package, and you will get complaints that there are # no rules to generate ltmain.sh. if test -f "$ltmain"; then # See if we are running on zsh, and set the options which allow our commands through # without removal of \ escapes. if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi # Now quote all the things that may contain metacharacters while being # careful not to overquote the AC_SUBSTed values. We take copies of the # variables and quote the copies for generation of the libtool script. for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC NM SED SHELL \ libname_spec library_names_spec soname_spec extract_expsyms_cmds \ old_striplib striplib file_magic_cmd finish_cmds finish_eval \ deplibs_check_method reload_flag reload_cmds need_locks \ lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \ lt_cv_sys_global_symbol_to_c_name_address \ sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ old_postinstall_cmds old_postuninstall_cmds \ compiler_GCJ \ CC_GCJ \ LD_GCJ \ lt_prog_compiler_wl_GCJ \ lt_prog_compiler_pic_GCJ \ lt_prog_compiler_static_GCJ \ lt_prog_compiler_no_builtin_flag_GCJ \ export_dynamic_flag_spec_GCJ \ thread_safe_flag_spec_GCJ \ whole_archive_flag_spec_GCJ \ enable_shared_with_static_runtimes_GCJ \ old_archive_cmds_GCJ \ old_archive_from_new_cmds_GCJ \ predep_objects_GCJ \ postdep_objects_GCJ \ predeps_GCJ \ postdeps_GCJ \ compiler_lib_search_path_GCJ \ archive_cmds_GCJ \ archive_expsym_cmds_GCJ \ postinstall_cmds_GCJ \ postuninstall_cmds_GCJ \ old_archive_from_expsyms_cmds_GCJ \ allow_undefined_flag_GCJ \ no_undefined_flag_GCJ \ export_symbols_cmds_GCJ \ hardcode_libdir_flag_spec_GCJ \ hardcode_libdir_flag_spec_ld_GCJ \ hardcode_libdir_separator_GCJ \ hardcode_automatic_GCJ \ module_cmds_GCJ \ module_expsym_cmds_GCJ \ lt_cv_prog_compiler_c_o_GCJ \ exclude_expsyms_GCJ \ include_expsyms_GCJ; do case $var in old_archive_cmds_GCJ | \ old_archive_from_new_cmds_GCJ | \ archive_cmds_GCJ | \ archive_expsym_cmds_GCJ | \ module_cmds_GCJ | \ module_expsym_cmds_GCJ | \ old_archive_from_expsyms_cmds_GCJ | \ export_symbols_cmds_GCJ | \ extract_expsyms_cmds | reload_cmds | finish_cmds | \ postinstall_cmds | postuninstall_cmds | \ old_postinstall_cmds | old_postuninstall_cmds | \ sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) # Double-quote double-evaled strings. eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" ;; *) eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" ;; esac done case $lt_echo in *'\$0 --fallback-echo"') lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'` ;; esac cfgfile="$ofile" cat <<__EOF__ >> "$cfgfile" # ### BEGIN LIBTOOL TAG CONFIG: $tagname # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # Shell to use when invoking shell scripts. SHELL=$lt_SHELL # Whether or not to build shared libraries. build_libtool_libs=$enable_shared # Whether or not to build static libraries. build_old_libs=$enable_static # Whether or not to add -lc for building shared libraries. build_libtool_need_lc=$archive_cmds_need_lc_GCJ # Whether or not to disallow shared libs when runtime libs are static allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_GCJ # Whether or not to optimize for fast installation. fast_install=$enable_fast_install # The host system. host_alias=$host_alias host=$host # An echo program that does not interpret backslashes. echo=$lt_echo # The archiver. AR=$lt_AR AR_FLAGS=$lt_AR_FLAGS # A C compiler. LTCC=$lt_LTCC # A language-specific compiler. CC=$lt_compiler_GCJ # Is the compiler the GNU C compiler? with_gcc=$GCC_GCJ # An ERE matcher. EGREP=$lt_EGREP # The linker used to build libraries. LD=$lt_LD_GCJ # Whether we need hard or soft links. LN_S=$lt_LN_S # A BSD-compatible nm program. NM=$lt_NM # A symbol stripping program STRIP=$STRIP # Used to examine libraries when file_magic_cmd begins "file" MAGIC_CMD=$MAGIC_CMD # Used on cygwin: DLL creation program. DLLTOOL="$DLLTOOL" # Used on cygwin: object dumper. OBJDUMP="$OBJDUMP" # Used on cygwin: assembler. AS="$AS" # The name of the directory that contains temporary libtool files. objdir=$objdir # How to create reloadable object files. reload_flag=$lt_reload_flag reload_cmds=$lt_reload_cmds # How to pass a linker flag through the compiler. wl=$lt_lt_prog_compiler_wl_GCJ # Object file suffix (normally "o"). objext="$ac_objext" # Old archive suffix (normally "a"). libext="$libext" # Shared library suffix (normally ".so"). shrext='$shrext' # Executable file suffix (normally ""). exeext="$exeext" # Additional compiler flags for building library objects. pic_flag=$lt_lt_prog_compiler_pic_GCJ pic_mode=$pic_mode # What is the maximum length of a command? max_cmd_len=$lt_cv_sys_max_cmd_len # Does compiler simultaneously support -c and -o options? compiler_c_o=$lt_lt_cv_prog_compiler_c_o_GCJ # Must we lock files when doing compilation ? need_locks=$lt_need_locks # Do we need the lib prefix for modules? need_lib_prefix=$need_lib_prefix # Do we need a version for libraries? need_version=$need_version # Whether dlopen is supported. dlopen_support=$enable_dlopen # Whether dlopen of programs is supported. dlopen_self=$enable_dlopen_self # Whether dlopen of statically linked programs is supported. dlopen_self_static=$enable_dlopen_self_static # Compiler flag to prevent dynamic linking. link_static_flag=$lt_lt_prog_compiler_static_GCJ # Compiler flag to turn off builtin functions. no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_GCJ # Compiler flag to allow reflexive dlopens. export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_GCJ # Compiler flag to generate shared objects directly from archives. whole_archive_flag_spec=$lt_whole_archive_flag_spec_GCJ # Compiler flag to generate thread-safe objects. thread_safe_flag_spec=$lt_thread_safe_flag_spec_GCJ # Library versioning type. version_type=$version_type # Format of library name prefix. libname_spec=$lt_libname_spec # List of archive names. First name is the real one, the rest are links. # The last name is the one that the linker finds with -lNAME. library_names_spec=$lt_library_names_spec # The coded name of the library, if different from the real name. soname_spec=$lt_soname_spec # Commands used to build and install an old-style archive. RANLIB=$lt_RANLIB old_archive_cmds=$lt_old_archive_cmds_GCJ old_postinstall_cmds=$lt_old_postinstall_cmds old_postuninstall_cmds=$lt_old_postuninstall_cmds # Create an old-style archive from a shared archive. old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_GCJ # Create a temporary old-style archive to link instead of a shared archive. old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_GCJ # Commands used to build and install a shared archive. archive_cmds=$lt_archive_cmds_GCJ archive_expsym_cmds=$lt_archive_expsym_cmds_GCJ postinstall_cmds=$lt_postinstall_cmds postuninstall_cmds=$lt_postuninstall_cmds # Commands used to build a loadable module (assumed same as above if empty) module_cmds=$lt_module_cmds_GCJ module_expsym_cmds=$lt_module_expsym_cmds_GCJ # Commands to strip libraries. old_striplib=$lt_old_striplib striplib=$lt_striplib # Dependencies to place before the objects being linked to create a # shared library. predep_objects=$lt_predep_objects_GCJ # Dependencies to place after the objects being linked to create a # shared library. postdep_objects=$lt_postdep_objects_GCJ # Dependencies to place before the objects being linked to create a # shared library. predeps=$lt_predeps_GCJ # Dependencies to place after the objects being linked to create a # shared library. postdeps=$lt_postdeps_GCJ # The library search path used internally by the compiler when linking # a shared library. compiler_lib_search_path=$lt_compiler_lib_search_path_GCJ # Method to check whether dependent libraries are shared objects. deplibs_check_method=$lt_deplibs_check_method # Command to use when deplibs_check_method == file_magic. file_magic_cmd=$lt_file_magic_cmd # Flag that allows shared libraries with undefined symbols to be built. allow_undefined_flag=$lt_allow_undefined_flag_GCJ # Flag that forces no undefined symbols. no_undefined_flag=$lt_no_undefined_flag_GCJ # Commands used to finish a libtool library installation in a directory. finish_cmds=$lt_finish_cmds # Same as above, but a single script fragment to be evaled but not shown. finish_eval=$lt_finish_eval # Take the output of nm and produce a listing of raw symbols and C names. global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe # Transform the output of nm in a proper C declaration global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl # Transform the output of nm in a C name address pair global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address # This is the shared library runtime path variable. runpath_var=$runpath_var # This is the shared library path variable. shlibpath_var=$shlibpath_var # Is shlibpath searched before the hard-coded library search path? shlibpath_overrides_runpath=$shlibpath_overrides_runpath # How to hardcode a shared library path into an executable. hardcode_action=$hardcode_action_GCJ # Whether we should hardcode library paths into libraries. hardcode_into_libs=$hardcode_into_libs # Flag to hardcode \$libdir into a binary during linking. # This must work even if \$libdir does not exist. hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_GCJ # If ld is used when linking, flag to hardcode \$libdir into # a binary during linking. This must work even if \$libdir does # not exist. hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_GCJ # Whether we need a single -rpath flag with a separated argument. hardcode_libdir_separator=$lt_hardcode_libdir_separator_GCJ # Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the # resulting binary. hardcode_direct=$hardcode_direct_GCJ # Set to yes if using the -LDIR flag during linking hardcodes DIR into the # resulting binary. hardcode_minus_L=$hardcode_minus_L_GCJ # Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into # the resulting binary. hardcode_shlibpath_var=$hardcode_shlibpath_var_GCJ # Set to yes if building a shared library automatically hardcodes DIR into the library # and all subsequent libraries and executables linked against it. hardcode_automatic=$hardcode_automatic_GCJ # Variables whose values should be saved in libtool wrapper scripts and # restored at relink time. variables_saved_for_relink="$variables_saved_for_relink" # Whether libtool must link a program against all its dependency libraries. link_all_deplibs=$link_all_deplibs_GCJ # Compile-time system search path for libraries sys_lib_search_path_spec=$lt_sys_lib_search_path_spec # Run-time system search path for libraries sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec # Fix the shell variable \$srcfile for the compiler. fix_srcfile_path="$fix_srcfile_path_GCJ" # Set to yes if exported symbols are required. always_export_symbols=$always_export_symbols_GCJ # The commands to list exported symbols. export_symbols_cmds=$lt_export_symbols_cmds_GCJ # The commands to extract the exported symbol list from a shared archive. extract_expsyms_cmds=$lt_extract_expsyms_cmds # Symbols that should not be listed in the preloaded symbols. exclude_expsyms=$lt_exclude_expsyms_GCJ # Symbols that must always be exported. include_expsyms=$lt_include_expsyms_GCJ # ### END LIBTOOL TAG CONFIG: $tagname __EOF__ else # If there is no Makefile yet, we rely on a make rule to execute # `config.status --recheck' to rerun these tests and create the # libtool script then. test -f Makefile && make "$ltmain" fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu CC="$lt_save_CC" else tagname="" fi ;; RC) # Source file extension for RC test sources. ac_ext=rc # Object file extension for compiled RC test sources. objext=o objext_RC=$objext # Code to be used in simple compile tests lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }\n' # Code to be used in simple link tests lt_simple_link_test_code="$lt_simple_compile_test_code" # ltmain only uses $CC for tagged configurations so make sure $CC is set. # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # Allow CC to be a program name with arguments. compiler=$CC # Allow CC to be a program name with arguments. lt_save_CC="$CC" CC=${RC-"windres"} compiler=$CC compiler_RC=$CC lt_cv_prog_compiler_c_o_RC=yes # The else clause should only fire when bootstrapping the # libtool distribution, otherwise you forgot to ship ltmain.sh # with your package, and you will get complaints that there are # no rules to generate ltmain.sh. if test -f "$ltmain"; then # See if we are running on zsh, and set the options which allow our commands through # without removal of \ escapes. if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi # Now quote all the things that may contain metacharacters while being # careful not to overquote the AC_SUBSTed values. We take copies of the # variables and quote the copies for generation of the libtool script. for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC NM SED SHELL \ libname_spec library_names_spec soname_spec extract_expsyms_cmds \ old_striplib striplib file_magic_cmd finish_cmds finish_eval \ deplibs_check_method reload_flag reload_cmds need_locks \ lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \ lt_cv_sys_global_symbol_to_c_name_address \ sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ old_postinstall_cmds old_postuninstall_cmds \ compiler_RC \ CC_RC \ LD_RC \ lt_prog_compiler_wl_RC \ lt_prog_compiler_pic_RC \ lt_prog_compiler_static_RC \ lt_prog_compiler_no_builtin_flag_RC \ export_dynamic_flag_spec_RC \ thread_safe_flag_spec_RC \ whole_archive_flag_spec_RC \ enable_shared_with_static_runtimes_RC \ old_archive_cmds_RC \ old_archive_from_new_cmds_RC \ predep_objects_RC \ postdep_objects_RC \ predeps_RC \ postdeps_RC \ compiler_lib_search_path_RC \ archive_cmds_RC \ archive_expsym_cmds_RC \ postinstall_cmds_RC \ postuninstall_cmds_RC \ old_archive_from_expsyms_cmds_RC \ allow_undefined_flag_RC \ no_undefined_flag_RC \ export_symbols_cmds_RC \ hardcode_libdir_flag_spec_RC \ hardcode_libdir_flag_spec_ld_RC \ hardcode_libdir_separator_RC \ hardcode_automatic_RC \ module_cmds_RC \ module_expsym_cmds_RC \ lt_cv_prog_compiler_c_o_RC \ exclude_expsyms_RC \ include_expsyms_RC; do case $var in old_archive_cmds_RC | \ old_archive_from_new_cmds_RC | \ archive_cmds_RC | \ archive_expsym_cmds_RC | \ module_cmds_RC | \ module_expsym_cmds_RC | \ old_archive_from_expsyms_cmds_RC | \ export_symbols_cmds_RC | \ extract_expsyms_cmds | reload_cmds | finish_cmds | \ postinstall_cmds | postuninstall_cmds | \ old_postinstall_cmds | old_postuninstall_cmds | \ sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) # Double-quote double-evaled strings. eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" ;; *) eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" ;; esac done case $lt_echo in *'\$0 --fallback-echo"') lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'` ;; esac cfgfile="$ofile" cat <<__EOF__ >> "$cfgfile" # ### BEGIN LIBTOOL TAG CONFIG: $tagname # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # Shell to use when invoking shell scripts. SHELL=$lt_SHELL # Whether or not to build shared libraries. build_libtool_libs=$enable_shared # Whether or not to build static libraries. build_old_libs=$enable_static # Whether or not to add -lc for building shared libraries. build_libtool_need_lc=$archive_cmds_need_lc_RC # Whether or not to disallow shared libs when runtime libs are static allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_RC # Whether or not to optimize for fast installation. fast_install=$enable_fast_install # The host system. host_alias=$host_alias host=$host # An echo program that does not interpret backslashes. echo=$lt_echo # The archiver. AR=$lt_AR AR_FLAGS=$lt_AR_FLAGS # A C compiler. LTCC=$lt_LTCC # A language-specific compiler. CC=$lt_compiler_RC # Is the compiler the GNU C compiler? with_gcc=$GCC_RC # An ERE matcher. EGREP=$lt_EGREP # The linker used to build libraries. LD=$lt_LD_RC # Whether we need hard or soft links. LN_S=$lt_LN_S # A BSD-compatible nm program. NM=$lt_NM # A symbol stripping program STRIP=$STRIP # Used to examine libraries when file_magic_cmd begins "file" MAGIC_CMD=$MAGIC_CMD # Used on cygwin: DLL creation program. DLLTOOL="$DLLTOOL" # Used on cygwin: object dumper. OBJDUMP="$OBJDUMP" # Used on cygwin: assembler. AS="$AS" # The name of the directory that contains temporary libtool files. objdir=$objdir # How to create reloadable object files. reload_flag=$lt_reload_flag reload_cmds=$lt_reload_cmds # How to pass a linker flag through the compiler. wl=$lt_lt_prog_compiler_wl_RC # Object file suffix (normally "o"). objext="$ac_objext" # Old archive suffix (normally "a"). libext="$libext" # Shared library suffix (normally ".so"). shrext='$shrext' # Executable file suffix (normally ""). exeext="$exeext" # Additional compiler flags for building library objects. pic_flag=$lt_lt_prog_compiler_pic_RC pic_mode=$pic_mode # What is the maximum length of a command? max_cmd_len=$lt_cv_sys_max_cmd_len # Does compiler simultaneously support -c and -o options? compiler_c_o=$lt_lt_cv_prog_compiler_c_o_RC # Must we lock files when doing compilation ? need_locks=$lt_need_locks # Do we need the lib prefix for modules? need_lib_prefix=$need_lib_prefix # Do we need a version for libraries? need_version=$need_version # Whether dlopen is supported. dlopen_support=$enable_dlopen # Whether dlopen of programs is supported. dlopen_self=$enable_dlopen_self # Whether dlopen of statically linked programs is supported. dlopen_self_static=$enable_dlopen_self_static # Compiler flag to prevent dynamic linking. link_static_flag=$lt_lt_prog_compiler_static_RC # Compiler flag to turn off builtin functions. no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_RC # Compiler flag to allow reflexive dlopens. export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_RC # Compiler flag to generate shared objects directly from archives. whole_archive_flag_spec=$lt_whole_archive_flag_spec_RC # Compiler flag to generate thread-safe objects. thread_safe_flag_spec=$lt_thread_safe_flag_spec_RC # Library versioning type. version_type=$version_type # Format of library name prefix. libname_spec=$lt_libname_spec # List of archive names. First name is the real one, the rest are links. # The last name is the one that the linker finds with -lNAME. library_names_spec=$lt_library_names_spec # The coded name of the library, if different from the real name. soname_spec=$lt_soname_spec # Commands used to build and install an old-style archive. RANLIB=$lt_RANLIB old_archive_cmds=$lt_old_archive_cmds_RC old_postinstall_cmds=$lt_old_postinstall_cmds old_postuninstall_cmds=$lt_old_postuninstall_cmds # Create an old-style archive from a shared archive. old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_RC # Create a temporary old-style archive to link instead of a shared archive. old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_RC # Commands used to build and install a shared archive. archive_cmds=$lt_archive_cmds_RC archive_expsym_cmds=$lt_archive_expsym_cmds_RC postinstall_cmds=$lt_postinstall_cmds postuninstall_cmds=$lt_postuninstall_cmds # Commands used to build a loadable module (assumed same as above if empty) module_cmds=$lt_module_cmds_RC module_expsym_cmds=$lt_module_expsym_cmds_RC # Commands to strip libraries. old_striplib=$lt_old_striplib striplib=$lt_striplib # Dependencies to place before the objects being linked to create a # shared library. predep_objects=$lt_predep_objects_RC # Dependencies to place after the objects being linked to create a # shared library. postdep_objects=$lt_postdep_objects_RC # Dependencies to place before the objects being linked to create a # shared library. predeps=$lt_predeps_RC # Dependencies to place after the objects being linked to create a # shared library. postdeps=$lt_postdeps_RC # The library search path used internally by the compiler when linking # a shared library. compiler_lib_search_path=$lt_compiler_lib_search_path_RC # Method to check whether dependent libraries are shared objects. deplibs_check_method=$lt_deplibs_check_method # Command to use when deplibs_check_method == file_magic. file_magic_cmd=$lt_file_magic_cmd # Flag that allows shared libraries with undefined symbols to be built. allow_undefined_flag=$lt_allow_undefined_flag_RC # Flag that forces no undefined symbols. no_undefined_flag=$lt_no_undefined_flag_RC # Commands used to finish a libtool library installation in a directory. finish_cmds=$lt_finish_cmds # Same as above, but a single script fragment to be evaled but not shown. finish_eval=$lt_finish_eval # Take the output of nm and produce a listing of raw symbols and C names. global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe # Transform the output of nm in a proper C declaration global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl # Transform the output of nm in a C name address pair global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address # This is the shared library runtime path variable. runpath_var=$runpath_var # This is the shared library path variable. shlibpath_var=$shlibpath_var # Is shlibpath searched before the hard-coded library search path? shlibpath_overrides_runpath=$shlibpath_overrides_runpath # How to hardcode a shared library path into an executable. hardcode_action=$hardcode_action_RC # Whether we should hardcode library paths into libraries. hardcode_into_libs=$hardcode_into_libs # Flag to hardcode \$libdir into a binary during linking. # This must work even if \$libdir does not exist. hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_RC # If ld is used when linking, flag to hardcode \$libdir into # a binary during linking. This must work even if \$libdir does # not exist. hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_RC # Whether we need a single -rpath flag with a separated argument. hardcode_libdir_separator=$lt_hardcode_libdir_separator_RC # Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the # resulting binary. hardcode_direct=$hardcode_direct_RC # Set to yes if using the -LDIR flag during linking hardcodes DIR into the # resulting binary. hardcode_minus_L=$hardcode_minus_L_RC # Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into # the resulting binary. hardcode_shlibpath_var=$hardcode_shlibpath_var_RC # Set to yes if building a shared library automatically hardcodes DIR into the library # and all subsequent libraries and executables linked against it. hardcode_automatic=$hardcode_automatic_RC # Variables whose values should be saved in libtool wrapper scripts and # restored at relink time. variables_saved_for_relink="$variables_saved_for_relink" # Whether libtool must link a program against all its dependency libraries. link_all_deplibs=$link_all_deplibs_RC # Compile-time system search path for libraries sys_lib_search_path_spec=$lt_sys_lib_search_path_spec # Run-time system search path for libraries sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec # Fix the shell variable \$srcfile for the compiler. fix_srcfile_path="$fix_srcfile_path_RC" # Set to yes if exported symbols are required. always_export_symbols=$always_export_symbols_RC # The commands to list exported symbols. export_symbols_cmds=$lt_export_symbols_cmds_RC # The commands to extract the exported symbol list from a shared archive. extract_expsyms_cmds=$lt_extract_expsyms_cmds # Symbols that should not be listed in the preloaded symbols. exclude_expsyms=$lt_exclude_expsyms_RC # Symbols that must always be exported. include_expsyms=$lt_include_expsyms_RC # ### END LIBTOOL TAG CONFIG: $tagname __EOF__ else # If there is no Makefile yet, we rely on a make rule to execute # `config.status --recheck' to rerun these tests and create the # libtool script then. test -f Makefile && make "$ltmain" fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu CC="$lt_save_CC" ;; *) { { echo "$as_me:$LINENO: error: Unsupported tag name: $tagname" >&5 echo "$as_me: error: Unsupported tag name: $tagname" >&2;} { (exit 1); exit 1; }; } ;; esac # Append the new tag name to the list of available tags. if test -n "$tagname" ; then available_tags="$available_tags $tagname" fi fi done IFS="$lt_save_ifs" # Now substitute the updated list of available tags. if eval "sed -e 's/^available_tags=.*\$/available_tags=\"$available_tags\"/' \"$ofile\" > \"${ofile}T\""; then mv "${ofile}T" "$ofile" chmod +x "$ofile" else rm -f "${ofile}T" { { echo "$as_me:$LINENO: error: unable to update list of available tagged configurations." >&5 echo "$as_me: error: unable to update list of available tagged configurations." >&2;} { (exit 1); exit 1; }; } fi fi # This can be used to rebuild libtool when needed LIBTOOL_DEPS="$ac_aux_dir/ltmain.sh" # Always use our own libtool. LIBTOOL='$(SHELL) $(top_builddir)/libtool' # Prevent multiple expansion # (we build libtool for ourselves) # ----------------------------------------------------------------------------- # # AC_LIB_LTDL # # Even though libltdl is installed together with libtool, you may wish # to include libltdl in the distribution of your package, for the convenience # of users of your package that don't have libtool or libltdl installed. # # The most simplistic way to add libltdl to your package is to copy the # source files, 'ltdl.c' and 'ltdl.h', to a source directory withing your # package and to build and link them along with the rest of your sources. # # To do this, you must add a call to the 'AC_LIB_LTDL' macro to your package's # 'configure.in' to perform the required configure time checks in order that # 'ltdl.o' is built correctly. # # This method does have its problems though: if you try to link the package # binaries with an installed libltdl, or a library which depends on libltdl, # you may have problems with duplicate symbol definitions. # # In order to enable this flavor of libltdl, you should add the line # 'AC_LIBLTDL_CONVENIENCE' to your `configure.in', before 'AC_PROG_LIBTOOL'. # # In order to select the installable version of libltdl, you should add a # call of the macro 'AC_LIBLTDL_INSTALLABLE' to your 'configure.in' before # 'AC_PROG_LIBTOOL'. This macro will check whether libltdl is already # installed and, if not, request the libltdl embedded in your package to be # built and installed. # # Whatever macro you use, it is up to you to ensure that your 'configure.in' # will configure libltdl, using 'AC_CONFIG_SUBDIRS', and that your 'Makefile's # will start sub-makes within libltdl's directory, using automake's SUBDIRS, # for example. Both macros define the shell variables LIBLTDL, to the link flag # that you should use to link with libltdl, and LTDLINCL, to the preprocessor # flag that you should use to compile with programs that include 'ltdl.h'. It # is up to you to use 'AC_SUBST' to ensure that this variable will be available # in 'Makefile's, or add them to variables that are 'AC_SUBST'ed by default, # such as LIBS and CPPFLAGS. # # So, when you want to link a program with libltdl, be it a convenience, # installed or installable library, just compile with '$(LTDLINCL)' and link # it with '$(LIBLTDL)', using libtool. # # You should probably also add 'AC_LIBTOOL_DLOPEN' to your 'configure.in' before # 'AC_PROG_LIBTOOL', otherwise libtool will assume no dlopening mechanism is # supported, and revert to dlpreopening, which is probably not what you want. # # The following example shows you how to embed the convenience libltdl # in your package. In order to use the installable variant just replace # 'AC_LIBLTDL_CONVENIENCE' with 'AC_LIBLTDL_INSTALLABLE'. We assume that libltdl # was embedded using 'libtoolize --ltdl': # # configure.in: # # ... # dnl Enable building of the convenience library # dnl and set LIBLTDL accordingly # AC_LIBLTDL_CONVENIENCE # dnl Substitute LTDLINCL and LIBLTDL in the Makefiles # AC_SUBST(LTDLINCL) # AC_SUBST(LIBLTDL) # dnl Check for dlopen support # AC_LIBTOOL_DLOPEN # dnl Configure libtool # AC_PROG_LIBTOOL # dnl Configure libltdl # AC_CONFIG_SUBDIRS(libltdl) # ... # # Makefile.am: # # ... # SUBDIRS = libltdl # # INCLUDES = $(LTDLINCL) # # myprog_LDFLAGS = -export-dynamic # # The quotes around -dlopen below fool automake <= 1.4 into accepting it # myprog_LDADD = $(LIBLTDL) "-dlopen" self "-dlopen" foo1.la # myprog_DEPENDENCIES = $(LIBLTDL) foo1.la # ... # # ----------------------------------------------------------------------------- { 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 cs; /* SunOS 4.1.1 cc rejects this. */ char const *const *pcpcc; char **ppc; /* NEC SVR4.0.2 mips cc rejects this. */ struct point {int x, y;}; static struct point const zero = {0,0}; /* AIX XL C 1.02.0.0 rejects this. It does not let you subtract one const X* pointer from another in an arm of an if-expression whose if-part is not a constant expression */ const char *g = "string"; pcpcc = &g + (g ? g-g : 0); /* HPUX 7.0 cc rejects these. */ ++pcpcc; ppc = (char**) pcpcc; pcpcc = (char const *const *) ppc; { /* SCO 3.2v4 cc rejects this. */ char *t; char const *s = 0 ? (char *) 0 : (char const *) 0; *t++ = 0; if (s) return 0; } { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ int x[] = {25, 17}; const int *foo = &x[0]; ++foo; } { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ typedef const int *iptr; iptr p = 0; ++p; } { /* AIX XL C 1.02.0.0 rejects this 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; if (!foo) return 0; } return !cs[0] && !zero.x; #endif ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core 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 ac_header_dirent=no for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h; do as_ac_Header=`echo "ac_cv_header_dirent_$ac_hdr" | $as_tr_sh` { echo "$as_me:$LINENO: checking for $ac_hdr that defines DIR" >&5 echo $ECHO_N "checking for $ac_hdr that defines DIR... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_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. */ #include #include <$ac_hdr> int main () { if ((DIR *) 0) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core conftest.err conftest.$ac_objext conftest.$ac_ext fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&6; } if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_hdr" | $as_tr_cpp` 1 _ACEOF ac_header_dirent=$ac_hdr; break fi done # Two versions of opendir et al. are in -ldir and -lx on SCO Xenix. if test $ac_header_dirent = dirent.h; then { echo "$as_me:$LINENO: checking for library containing opendir" >&5 echo $ECHO_N "checking for library containing opendir... $ECHO_C" >&6; } if test "${ac_cv_search_opendir+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_func_search_save_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 GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char opendir (); int main () { return opendir (); ; return 0; } _ACEOF for ac_lib in '' dir; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_search_opendir=$ac_res else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext if test "${ac_cv_search_opendir+set}" = set; then break fi done if test "${ac_cv_search_opendir+set}" = set; then : else ac_cv_search_opendir=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_search_opendir" >&5 echo "${ECHO_T}$ac_cv_search_opendir" >&6; } ac_res=$ac_cv_search_opendir if test "$ac_res" != no; then test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi else { echo "$as_me:$LINENO: checking for library containing opendir" >&5 echo $ECHO_N "checking for library containing opendir... $ECHO_C" >&6; } if test "${ac_cv_search_opendir+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_func_search_save_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 GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char opendir (); int main () { return opendir (); ; return 0; } _ACEOF for ac_lib in '' x; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_search_opendir=$ac_res else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext if test "${ac_cv_search_opendir+set}" = set; then break fi done if test "${ac_cv_search_opendir+set}" = set; then : else ac_cv_search_opendir=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_search_opendir" >&5 echo "${ECHO_T}$ac_cv_search_opendir" >&6; } ac_res=$ac_cv_search_opendir if test "$ac_res" != no; then test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi fi # Check whether --enable-ltdl-install was given. if test "${enable_ltdl_install+set}" = set; then enableval=$enable_ltdl_install; fi if test x"${enable_ltdl_install-no}" != xno; then INSTALL_LTDL_TRUE= INSTALL_LTDL_FALSE='#' else INSTALL_LTDL_TRUE='#' INSTALL_LTDL_FALSE= fi if test x"${enable_ltdl_convenience-no}" != xno; then CONVENIENCE_LTDL_TRUE= CONVENIENCE_LTDL_FALSE='#' else CONVENIENCE_LTDL_TRUE='#' CONVENIENCE_LTDL_FALSE= fi { echo "$as_me:$LINENO: checking which extension is used for loadable modules" >&5 echo $ECHO_N "checking which extension is used for loadable modules... $ECHO_C" >&6; } if test "${libltdl_cv_shlibext+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else module=yes eval libltdl_cv_shlibext=$shrext_cmds fi { echo "$as_me:$LINENO: result: $libltdl_cv_shlibext" >&5 echo "${ECHO_T}$libltdl_cv_shlibext" >&6; } if test -n "$libltdl_cv_shlibext"; then cat >>confdefs.h <<_ACEOF #define LTDL_SHLIB_EXT "$libltdl_cv_shlibext" _ACEOF fi { echo "$as_me:$LINENO: checking which variable specifies run-time library path" >&5 echo $ECHO_N "checking which variable specifies run-time library path... $ECHO_C" >&6; } if test "${libltdl_cv_shlibpath_var+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else libltdl_cv_shlibpath_var="$shlibpath_var" fi { echo "$as_me:$LINENO: result: $libltdl_cv_shlibpath_var" >&5 echo "${ECHO_T}$libltdl_cv_shlibpath_var" >&6; } if test -n "$libltdl_cv_shlibpath_var"; then cat >>confdefs.h <<_ACEOF #define LTDL_SHLIBPATH_VAR "$libltdl_cv_shlibpath_var" _ACEOF fi { echo "$as_me:$LINENO: checking for the default library search path" >&5 echo $ECHO_N "checking for the default library search path... $ECHO_C" >&6; } if test "${libltdl_cv_sys_search_path+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else libltdl_cv_sys_search_path="$sys_lib_dlsearch_path_spec" fi { echo "$as_me:$LINENO: result: $libltdl_cv_sys_search_path" >&5 echo "${ECHO_T}$libltdl_cv_sys_search_path" >&6; } if test -n "$libltdl_cv_sys_search_path"; then sys_search_path= for dir in $libltdl_cv_sys_search_path; do if test -z "$sys_search_path"; then sys_search_path="$dir" else sys_search_path="$sys_search_path$PATH_SEPARATOR$dir" fi done cat >>confdefs.h <<_ACEOF #define LTDL_SYSSEARCHPATH "$sys_search_path" _ACEOF fi { echo "$as_me:$LINENO: checking for objdir" >&5 echo $ECHO_N "checking for objdir... $ECHO_C" >&6; } if test "${libltdl_cv_objdir+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else libltdl_cv_objdir="$objdir" if test -n "$objdir"; then : else rm -f .libs 2>/dev/null mkdir .libs 2>/dev/null if test -d .libs; then libltdl_cv_objdir=.libs else # MS-DOS does not allow filenames that begin with a dot. libltdl_cv_objdir=_libs fi rmdir .libs 2>/dev/null fi fi { echo "$as_me:$LINENO: result: $libltdl_cv_objdir" >&5 echo "${ECHO_T}$libltdl_cv_objdir" >&6; } cat >>confdefs.h <<_ACEOF #define LTDL_OBJDIR "$libltdl_cv_objdir/" _ACEOF { echo "$as_me:$LINENO: checking whether libtool supports -dlopen/-dlpreopen" >&5 echo $ECHO_N "checking whether libtool supports -dlopen/-dlpreopen... $ECHO_C" >&6; } if test "${libltdl_cv_preloaded_symbols+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$lt_cv_sys_global_symbol_pipe"; then libltdl_cv_preloaded_symbols=yes else libltdl_cv_preloaded_symbols=no fi fi { echo "$as_me:$LINENO: result: $libltdl_cv_preloaded_symbols" >&5 echo "${ECHO_T}$libltdl_cv_preloaded_symbols" >&6; } if test x"$libltdl_cv_preloaded_symbols" = xyes; then cat >>confdefs.h <<\_ACEOF #define HAVE_PRELOADED_SYMBOLS 1 _ACEOF fi LIBADD_DL= 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 shl_load" >&5 echo $ECHO_N "checking for shl_load... $ECHO_C" >&6; } if test "${ac_cv_func_shl_load+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 shl_load to an innocuous variant, in case declares shl_load. For example, HP-UX 11i declares gettimeofday. */ #define shl_load innocuous_shl_load /* System header to define __stub macros and hopefully few prototypes, which can conflict with char shl_load (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef shl_load /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char shl_load (); /* 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_shl_load || defined __stub___shl_load choke me #endif int main () { return shl_load (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_func_shl_load=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func_shl_load=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_func_shl_load" >&5 echo "${ECHO_T}$ac_cv_func_shl_load" >&6; } if test $ac_cv_func_shl_load = yes; then cat >>confdefs.h <<\_ACEOF #define HAVE_SHL_LOAD 1 _ACEOF else { echo "$as_me:$LINENO: checking for shl_load in -ldld" >&5 echo $ECHO_N "checking for shl_load in -ldld... $ECHO_C" >&6; } if test "${ac_cv_lib_dld_shl_load+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $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 GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char shl_load (); int main () { return shl_load (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_dld_shl_load=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_dld_shl_load=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_dld_shl_load" >&5 echo "${ECHO_T}$ac_cv_lib_dld_shl_load" >&6; } if test $ac_cv_lib_dld_shl_load = yes; then cat >>confdefs.h <<\_ACEOF #define HAVE_SHL_LOAD 1 _ACEOF LIBADD_DL="$LIBADD_DL -ldld" else { echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5 echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6; } if test "${ac_cv_lib_dl_dlopen+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $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 GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_dl_dlopen=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_dl_dlopen=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5 echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6; } if test $ac_cv_lib_dl_dlopen = yes; then cat >>confdefs.h <<\_ACEOF #define HAVE_LIBDL 1 _ACEOF LIBADD_DL="-ldl" libltdl_cv_lib_dl_dlopen="yes" else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #if HAVE_DLFCN_H # include #endif int main () { dlopen(0, 0); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then cat >>confdefs.h <<\_ACEOF #define HAVE_LIBDL 1 _ACEOF libltdl_cv_func_dlopen="yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { echo "$as_me:$LINENO: checking for dlopen in -lsvld" >&5 echo $ECHO_N "checking for dlopen in -lsvld... $ECHO_C" >&6; } if test "${ac_cv_lib_svld_dlopen+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsvld $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 GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_svld_dlopen=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_svld_dlopen=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_svld_dlopen" >&5 echo "${ECHO_T}$ac_cv_lib_svld_dlopen" >&6; } if test $ac_cv_lib_svld_dlopen = yes; then cat >>confdefs.h <<\_ACEOF #define HAVE_LIBDL 1 _ACEOF LIBADD_DL="-lsvld" libltdl_cv_func_dlopen="yes" else { echo "$as_me:$LINENO: checking for dld_link in -ldld" >&5 echo $ECHO_N "checking for dld_link in -ldld... $ECHO_C" >&6; } if test "${ac_cv_lib_dld_dld_link+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $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 GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dld_link (); int main () { return dld_link (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_dld_dld_link=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_dld_dld_link=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_dld_dld_link" >&5 echo "${ECHO_T}$ac_cv_lib_dld_dld_link" >&6; } if test $ac_cv_lib_dld_dld_link = yes; then cat >>confdefs.h <<\_ACEOF #define HAVE_DLD 1 _ACEOF LIBADD_DL="$LIBADD_DL -ldld" else { echo "$as_me:$LINENO: checking for _dyld_func_lookup" >&5 echo $ECHO_N "checking for _dyld_func_lookup... $ECHO_C" >&6; } if test "${ac_cv_func__dyld_func_lookup+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 _dyld_func_lookup to an innocuous variant, in case declares _dyld_func_lookup. For example, HP-UX 11i declares gettimeofday. */ #define _dyld_func_lookup innocuous__dyld_func_lookup /* System header to define __stub macros and hopefully few prototypes, which can conflict with char _dyld_func_lookup (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef _dyld_func_lookup /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char _dyld_func_lookup (); /* 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__dyld_func_lookup || defined __stub____dyld_func_lookup choke me #endif int main () { return _dyld_func_lookup (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_func__dyld_func_lookup=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func__dyld_func_lookup=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_func__dyld_func_lookup" >&5 echo "${ECHO_T}$ac_cv_func__dyld_func_lookup" >&6; } if test $ac_cv_func__dyld_func_lookup = yes; then cat >>confdefs.h <<\_ACEOF #define HAVE_DYLD 1 _ACEOF fi fi fi fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi fi fi if test x"$libltdl_cv_func_dlopen" = xyes || test x"$libltdl_cv_lib_dl_dlopen" = xyes then lt_save_LIBS="$LIBS" LIBS="$LIBS $LIBADD_DL" for ac_func in dlerror 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 { as_var=$as_ac_var; eval "test \"\${$as_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 GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $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 #endif int main () { return $ac_func (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; 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 core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi ac_res=`eval echo '${'$as_ac_var'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 LIBS="$lt_save_LIBS" 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 _ prefix in compiled symbols" >&5 echo $ECHO_N "checking for _ prefix in compiled symbols... $ECHO_C" >&6; } if test "${ac_cv_sys_symbol_underscore+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_sys_symbol_underscore=no cat > conftest.$ac_ext <&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then # Now try to grab the symbols. ac_nlist=conftest.nm if { (eval echo "$as_me:$LINENO: \"$NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $ac_nlist\"") >&5 (eval $NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $ac_nlist) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && test -s "$ac_nlist"; then # See whether the symbols have a leading underscore. if grep '^. _nm_test_func' "$ac_nlist" >/dev/null; then ac_cv_sys_symbol_underscore=yes else if grep '^. nm_test_func ' "$ac_nlist" >/dev/null; then : else echo "configure: cannot find nm_test_func in $ac_nlist" >&5 fi fi else echo "configure: cannot run $lt_cv_sys_global_symbol_pipe" >&5 fi else echo "configure: failed program was:" >&5 cat conftest.c >&5 fi rm -rf conftest* fi { echo "$as_me:$LINENO: result: $ac_cv_sys_symbol_underscore" >&5 echo "${ECHO_T}$ac_cv_sys_symbol_underscore" >&6; } if test x"$ac_cv_sys_symbol_underscore" = xyes; then if test x"$libltdl_cv_func_dlopen" = xyes || test x"$libltdl_cv_lib_dl_dlopen" = xyes ; then { echo "$as_me:$LINENO: checking whether we have to add an underscore for dlsym" >&5 echo $ECHO_N "checking whether we have to add an underscore for dlsym... $ECHO_C" >&6; } if test "${libltdl_cv_need_uscore+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else libltdl_cv_need_uscore=unknown save_LIBS="$LIBS" LIBS="$LIBS $LIBADD_DL" if test "$cross_compiling" = yes; then : libltdl_cv_need_uscore=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext < #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif #ifdef __cplusplus extern "C" void exit (int); #endif void fnord() { int i=42;} int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; /* dlclose (self); */ } exit (status); } EOF 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); } && test -s conftest${ac_exeext} 2>/dev/null; then (./conftest; exit; ) 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) libltdl_cv_need_uscore=no ;; x$lt_dlneed_uscore) libltdl_cv_need_uscore=yes ;; x$lt_unknown|x*) ;; esac else : # compilation failed fi fi rm -fr conftest* LIBS="$save_LIBS" fi { echo "$as_me:$LINENO: result: $libltdl_cv_need_uscore" >&5 echo "${ECHO_T}$libltdl_cv_need_uscore" >&6; } fi fi if test x"$libltdl_cv_need_uscore" = xyes; then cat >>confdefs.h <<\_ACEOF #define NEED_USCORE 1 _ACEOF fi { echo "$as_me:$LINENO: checking whether deplibs are loaded by dlopen" >&5 echo $ECHO_N "checking whether deplibs are loaded by dlopen... $ECHO_C" >&6; } if test "${libltdl_cv_sys_dlopen_deplibs+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else # PORTME does your system automatically load deplibs for dlopen? # or its logical equivalent (e.g. shl_load for HP-UX < 11) # For now, we just catch OSes we know something about -- in the # future, we'll try test this programmatically. libltdl_cv_sys_dlopen_deplibs=unknown case "$host_os" in aix3*|aix4.1.*|aix4.2.*) # Unknown whether this is true for these versions of AIX, but # we want this `case' here to explicitly catch those versions. libltdl_cv_sys_dlopen_deplibs=unknown ;; aix[45]*) libltdl_cv_sys_dlopen_deplibs=yes ;; darwin*) # Assuming the user has installed a libdl from somewhere, this is true # If you are looking for one http://www.opendarwin.org/projects/dlcompat libltdl_cv_sys_dlopen_deplibs=yes ;; kfreebsd*-gnu) libltdl_cv_sys_dlopen_deplibs=yes ;; gnu*) libltdl_cv_sys_dlopen_deplibs=yes ;; hpux10*|hpux11*) libltdl_cv_sys_dlopen_deplibs=yes ;; irix[12345]*|irix6.[01]*) # Catch all versions of IRIX before 6.2, and indicate that we don't # know how it worked for any of those versions. libltdl_cv_sys_dlopen_deplibs=unknown ;; irix*) # The case above catches anything before 6.2, and it's known that # at 6.2 and later dlopen does load deplibs. libltdl_cv_sys_dlopen_deplibs=yes ;; linux*) libltdl_cv_sys_dlopen_deplibs=yes ;; netbsd*) libltdl_cv_sys_dlopen_deplibs=yes ;; openbsd*) libltdl_cv_sys_dlopen_deplibs=yes ;; osf[1234]*) # dlopen did load deplibs (at least at 4.x), but until the 5.x series, # it did *not* use an RPATH in a shared library to find objects the # library depends on, so we explictly say `no'. libltdl_cv_sys_dlopen_deplibs=no ;; osf5.0|osf5.0a|osf5.1) # dlopen *does* load deplibs and with the right loader patch applied # it even uses RPATH in a shared library to search for shared objects # that the library depends on, but there's no easy way to know if that # patch is installed. Since this is the case, all we can really # say is unknown -- it depends on the patch being installed. If # it is, this changes to `yes'. Without it, it would be `no'. libltdl_cv_sys_dlopen_deplibs=unknown ;; osf*) # the two cases above should catch all versions of osf <= 5.1. Read # the comments above for what we know about them. # At > 5.1, deplibs are loaded *and* any RPATH in a shared library # is used to find them so we can finally say `yes'. libltdl_cv_sys_dlopen_deplibs=yes ;; solaris*) libltdl_cv_sys_dlopen_deplibs=yes ;; esac fi { echo "$as_me:$LINENO: result: $libltdl_cv_sys_dlopen_deplibs" >&5 echo "${ECHO_T}$libltdl_cv_sys_dlopen_deplibs" >&6; } if test "$libltdl_cv_sys_dlopen_deplibs" != yes; then cat >>confdefs.h <<\_ACEOF #define LTDL_DLOPEN_DEPLIBS 1 _ACEOF fi for ac_header in argz.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core 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 { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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 && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.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_c_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;} ;; esac { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 error_t" >&5 echo $ECHO_N "checking for error_t... $ECHO_C" >&6; } if test "${ac_cv_type_error_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. */ #if HAVE_ARGZ_H # include #endif typedef error_t ac__type_new_; int main () { if ((ac__type_new_ *) 0) return 0; if (sizeof (ac__type_new_)) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_type_error_t=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_type_error_t=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_type_error_t" >&5 echo "${ECHO_T}$ac_cv_type_error_t" >&6; } if test $ac_cv_type_error_t = yes; then cat >>confdefs.h <<_ACEOF #define HAVE_ERROR_T 1 _ACEOF else cat >>confdefs.h <<\_ACEOF #define error_t int _ACEOF fi for ac_func in argz_append argz_create_sep argz_insert argz_next argz_stringify 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 { as_var=$as_ac_var; eval "test \"\${$as_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 GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $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 #endif int main () { return $ac_func (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; 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 core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi ac_res=`eval echo '${'$as_ac_var'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 for ac_header in assert.h ctype.h errno.h malloc.h memory.h stdlib.h \ stdio.h unistd.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core 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 { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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 && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.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_c_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;} ;; esac { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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_header in dl.h sys/dl.h dld.h mach-o/dyld.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core 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 { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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 && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.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_c_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;} ;; esac { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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_header in string.h strings.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core 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 { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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 && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.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_c_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;} ;; esac { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 break fi done for ac_func in strchr index 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 { as_var=$as_ac_var; eval "test \"\${$as_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 GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $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 #endif int main () { return $ac_func (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; 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 core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi ac_res=`eval echo '${'$as_ac_var'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&6; } if test `eval echo '${'$as_ac_var'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF break fi done for ac_func in strrchr rindex 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 { as_var=$as_ac_var; eval "test \"\${$as_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 GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $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 #endif int main () { return $ac_func (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; 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 core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi ac_res=`eval echo '${'$as_ac_var'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&6; } if test `eval echo '${'$as_ac_var'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF break fi done for ac_func in memcpy bcopy 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 { as_var=$as_ac_var; eval "test \"\${$as_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 GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $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 #endif int main () { return $ac_func (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; 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 core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi ac_res=`eval echo '${'$as_ac_var'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&6; } if test `eval echo '${'$as_ac_var'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF break fi done for ac_func in memmove strcmp 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 { as_var=$as_ac_var; eval "test \"\${$as_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 GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $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 #endif int main () { return $ac_func (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; 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 core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi ac_res=`eval echo '${'$as_ac_var'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 for ac_func in closedir opendir readdir 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 { as_var=$as_ac_var; eval "test \"\${$as_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 GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $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 #endif int main () { return $ac_func (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; 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 core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi ac_res=`eval echo '${'$as_ac_var'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 # (we need the ltdl libtool library) # (see PROGRAMMING NOTE above) # ----------------------------------------------------------------------------- # (See comments in the 'AC_CHECK_LIB' Libraries section further below) # ----------------------------------------------------------------------------- { echo "$as_me:$LINENO: (use of lt_dlopen forced by Hercules Dynamic Loader requirement) " >&5 echo "$as_me: (use of lt_dlopen forced by Hercules Dynamic Loader requirement) " >&6;} hc_cv_have_lt_dlopen=yes 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 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 echo "$as_me: trying $ac_dir/$ac_word..." >&5 if $ac_dir/$ac_word --statistics /dev/null >&5 2>&1 && (if $ac_dir/$ac_word --statistics /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi); then ac_cv_path_MSGFMT="$ac_dir/$ac_word$ac_exec_ext" break 2 fi fi done done IFS="$ac_save_IFS" test -z "$ac_cv_path_MSGFMT" && ac_cv_path_MSGFMT=":" ;; esac fi MSGFMT="$ac_cv_path_MSGFMT" if test "$MSGFMT" != ":"; then { 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 IFS=$as_save_IFS test -z "$ac_cv_path_GMSGFMT" && ac_cv_path_GMSGFMT="$MSGFMT" ;; esac fi GMSGFMT=$ac_cv_path_GMSGFMT if test -n "$GMSGFMT"; then { 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 echo "$as_me: trying $ac_dir/$ac_word..." >&5 if $ac_dir/$ac_word --omit-header --copyright-holder= --msgid-bugs-address= /dev/null >&5 2>&1 && (if $ac_dir/$ac_word --omit-header --copyright-holder= --msgid-bugs-address= /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi); then ac_cv_path_XGETTEXT="$ac_dir/$ac_word$ac_exec_ext" break 2 fi fi done done IFS="$ac_save_IFS" test -z "$ac_cv_path_XGETTEXT" && ac_cv_path_XGETTEXT=":" ;; esac fi XGETTEXT="$ac_cv_path_XGETTEXT" if test "$XGETTEXT" != ":"; then { 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 echo "$as_me: trying $ac_dir/$ac_word..." >&5 if $ac_dir/$ac_word --update -q /dev/null /dev/null >&5 2>&1; then ac_cv_path_MSGMERGE="$ac_dir/$ac_word$ac_exec_ext" break 2 fi fi done done IFS="$ac_save_IFS" test -z "$ac_cv_path_MSGMERGE" && ac_cv_path_MSGMERGE=":" ;; esac fi MSGMERGE="$ac_cv_path_MSGMERGE" if test "$MSGMERGE" != ":"; then { 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" if test "X$prefix" = "XNONE"; then acl_final_prefix="$ac_default_prefix" else acl_final_prefix="$prefix" fi if test "X$exec_prefix" = "XNONE"; then acl_final_exec_prefix='${prefix}' else acl_final_exec_prefix="$exec_prefix" fi acl_save_prefix="$prefix" prefix="$acl_final_prefix" eval acl_final_exec_prefix=\"$acl_final_exec_prefix\" prefix="$acl_save_prefix" # Check whether --with-gnu-ld was given. if test "${with_gnu_ld+set}" = set; then withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes else with_gnu_ld=no fi # Prepare PATH_SEPARATOR. # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then echo "#! /bin/sh" >conf$$.sh echo "exit 0" >>conf$$.sh chmod +x conf$$.sh if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then PATH_SEPARATOR=';' else PATH_SEPARATOR=: fi rm -f conf$$.sh fi ac_prog=ld if test "$GCC" = yes; then # Check if gcc -print-prog-name=ld gives a path. { 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 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 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* | gnu* | k*bsd*-gnu) haveit=yes;; esac fi fi if test -z "$haveit"; then for x in $CPPFLAGS $INCICONV; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" if test "X$x" = "X-I$additional_includedir"; then haveit=yes break fi done if test -z "$haveit"; then if test -d "$additional_includedir"; then INCICONV="${INCICONV}${INCICONV:+ }-I$additional_includedir" fi fi fi fi fi if test -n "$found_la"; then save_libdir="$libdir" case "$found_la" in */* | *\\*) . "$found_la" ;; *) . "./$found_la" ;; esac libdir="$save_libdir" for dep in $dependency_libs; do case "$dep" in -L*) additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'` if test "X$additional_libdir" != "X/usr/lib"; then haveit= if test "X$additional_libdir" = "X/usr/local/lib"; then if test -n "$GCC"; then case $host_os in linux* | gnu* | k*bsd*-gnu) haveit=yes;; esac fi fi if test -z "$haveit"; then haveit= for x in $LDFLAGS $LIBICONV; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" if test "X$x" = "X-L$additional_libdir"; then haveit=yes break fi done if test -z "$haveit"; then if test -d "$additional_libdir"; then LIBICONV="${LIBICONV}${LIBICONV:+ }-L$additional_libdir" fi fi haveit= for x in $LDFLAGS $LTLIBICONV; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" if test "X$x" = "X-L$additional_libdir"; then haveit=yes break fi done if test -z "$haveit"; then if test -d "$additional_libdir"; then LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-L$additional_libdir" fi fi fi fi ;; -R*) dir=`echo "X$dep" | sed -e 's/^X-R//'` if test "$enable_rpath" != no; then haveit= for x in $rpathdirs; do if test "X$x" = "X$dir"; then haveit=yes break fi done if test -z "$haveit"; then rpathdirs="$rpathdirs $dir" fi haveit= for x in $ltrpathdirs; do if test "X$x" = "X$dir"; then haveit=yes break fi done if test -z "$haveit"; then ltrpathdirs="$ltrpathdirs $dir" fi fi ;; -l*) names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'` ;; *.la) names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'` ;; *) LIBICONV="${LIBICONV}${LIBICONV:+ }$dep" LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }$dep" ;; esac done fi else LIBICONV="${LIBICONV}${LIBICONV:+ }-l$name" LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-l$name" fi fi fi done done if test "X$rpathdirs" != "X"; then if test -n "$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 CFPreferencesCopyAppValue" >&5 echo $ECHO_N "checking for CFPreferencesCopyAppValue... $ECHO_C" >&6; } if test "${gt_cv_func_CFPreferencesCopyAppValue+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else gt_save_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$CPPFLAGS -I/System/Library/Frameworks/CoreFoundation.framework/Headers" gt_save_LIBS="$LIBS" LIBS="$LIBS -framework CoreFoundation" 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 () { CFPreferencesCopyAppValue(NULL, NULL) ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then gt_cv_func_CFPreferencesCopyAppValue=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 gt_cv_func_CFPreferencesCopyAppValue=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext CPPFLAGS="$gt_save_CPPFLAGS" LIBS="$gt_save_LIBS" fi { echo "$as_me:$LINENO: result: $gt_cv_func_CFPreferencesCopyAppValue" >&5 echo "${ECHO_T}$gt_cv_func_CFPreferencesCopyAppValue" >&6; } if test $gt_cv_func_CFPreferencesCopyAppValue = yes; then cat >>confdefs.h <<\_ACEOF #define HAVE_CFPREFERENCESCOPYAPPVALUE 1 _ACEOF fi { echo "$as_me:$LINENO: checking for CFLocaleCopyCurrent" >&5 echo $ECHO_N "checking for CFLocaleCopyCurrent... $ECHO_C" >&6; } if test "${gt_cv_func_CFLocaleCopyCurrent+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else gt_save_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$CPPFLAGS -I/System/Library/Frameworks/CoreFoundation.framework/Headers" gt_save_LIBS="$LIBS" LIBS="$LIBS -framework CoreFoundation" 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 () { CFLocaleCopyCurrent(); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then gt_cv_func_CFLocaleCopyCurrent=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 gt_cv_func_CFLocaleCopyCurrent=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext CPPFLAGS="$gt_save_CPPFLAGS" LIBS="$gt_save_LIBS" fi { echo "$as_me:$LINENO: result: $gt_cv_func_CFLocaleCopyCurrent" >&5 echo "${ECHO_T}$gt_cv_func_CFLocaleCopyCurrent" >&6; } if test $gt_cv_func_CFLocaleCopyCurrent = yes; then cat >>confdefs.h <<\_ACEOF #define HAVE_CFLOCALECOPYCURRENT 1 _ACEOF fi INTL_MACOSX_LIBS= if test $gt_cv_func_CFPreferencesCopyAppValue = yes || test $gt_cv_func_CFLocaleCopyCurrent = yes; then INTL_MACOSX_LIBS="-Wl,-framework -Wl,CoreFoundation" fi { 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 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; } LIBINTL= LTLIBINTL= POSUB= if test "$USE_NLS" = "yes"; then gt_use_preinstalled_gnugettext=no { 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 * gettext ("") + _nl_msg_cat_cntr + *_nl_domain_bindings ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; 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 core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ 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 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 { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then am_cv_func_iconv=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ 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 { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; 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 core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ 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 use_additional=yes acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval additional_includedir=\"$includedir\" eval additional_libdir=\"$libdir\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" # Check whether --with-libintl-prefix was given. if test "${with_libintl_prefix+set}" = set; then withval=$with_libintl_prefix; if test "X$withval" = "Xno"; then use_additional=no else if test "X$withval" = "X"; then acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval additional_includedir=\"$includedir\" eval additional_libdir=\"$libdir\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" else additional_includedir="$withval/include" additional_libdir="$withval/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* | gnu* | k*bsd*-gnu) haveit=yes;; esac fi fi if test -z "$haveit"; then for x in $CPPFLAGS $INCINTL; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" if test "X$x" = "X-I$additional_includedir"; then haveit=yes break fi done if test -z "$haveit"; then if test -d "$additional_includedir"; then INCINTL="${INCINTL}${INCINTL:+ }-I$additional_includedir" fi fi fi fi fi if test -n "$found_la"; then save_libdir="$libdir" case "$found_la" in */* | *\\*) . "$found_la" ;; *) . "./$found_la" ;; esac libdir="$save_libdir" for dep in $dependency_libs; do case "$dep" in -L*) additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'` if test "X$additional_libdir" != "X/usr/lib"; then haveit= if test "X$additional_libdir" = "X/usr/local/lib"; then if test -n "$GCC"; then case $host_os in linux* | gnu* | k*bsd*-gnu) haveit=yes;; esac fi fi if test -z "$haveit"; then haveit= for x in $LDFLAGS $LIBINTL; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" if test "X$x" = "X-L$additional_libdir"; then haveit=yes break fi done if test -z "$haveit"; then if test -d "$additional_libdir"; then LIBINTL="${LIBINTL}${LIBINTL:+ }-L$additional_libdir" fi fi haveit= for x in $LDFLAGS $LTLIBINTL; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" if test "X$x" = "X-L$additional_libdir"; then haveit=yes break fi done if test -z "$haveit"; then if test -d "$additional_libdir"; then LTLIBINTL="${LTLIBINTL}${LTLIBINTL:+ }-L$additional_libdir" fi fi fi fi ;; -R*) dir=`echo "X$dep" | sed -e 's/^X-R//'` if test "$enable_rpath" != no; then haveit= for x in $rpathdirs; do if test "X$x" = "X$dir"; then haveit=yes break fi done if test -z "$haveit"; then rpathdirs="$rpathdirs $dir" fi haveit= for x in $ltrpathdirs; do if test "X$x" = "X$dir"; then haveit=yes break fi done if test -z "$haveit"; then ltrpathdirs="$ltrpathdirs $dir" fi fi ;; -l*) names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'` ;; *.la) names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'` ;; *) LIBINTL="${LIBINTL}${LIBINTL:+ }$dep" LTLIBINTL="${LTLIBINTL}${LTLIBINTL:+ }$dep" ;; esac done fi else LIBINTL="${LIBINTL}${LIBINTL:+ }-l$name" LTLIBINTL="${LTLIBINTL}${LTLIBINTL:+ }-l$name" fi fi fi done done if test "X$rpathdirs" != "X"; then if test -n "$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 (const char *); int main () { bindtextdomain ("", ""); return * gettext ("") + _nl_msg_cat_cntr + *_nl_expand_alias ("") ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; 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 core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ 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 (const char *); int main () { bindtextdomain ("", ""); return * gettext ("") + _nl_msg_cat_cntr + *_nl_expand_alias ("") ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; 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 core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ 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 -n "$INTL_MACOSX_LIBS"; then if test "$gt_use_preinstalled_gnugettext" = "yes" \ || test "$nls_cv_use_gnu_gettext" = "yes"; then LIBINTL="$LIBINTL $INTL_MACOSX_LIBS" LTLIBINTL="$LTLIBINTL $INTL_MACOSX_LIBS" fi fi if test "$gt_use_preinstalled_gnugettext" = "yes" \ || test "$nls_cv_use_gnu_gettext" = "yes"; then 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 INTLLIBS="$LIBINTL" # 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 { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then am_cv_func_iconv=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ 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 { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; 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 core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ 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 { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core conftest.err conftest.$ac_objext conftest.$ac_ext am_cv_proto_iconv="extern size_t iconv (iconv_t cd, $am_cv_proto_iconv_arg1 char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);" fi am_cv_proto_iconv=`echo "$am_cv_proto_iconv" | tr -s ' ' | sed -e 's/( /(/'` { 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 if test "$lt_cv_prog_gnu_ld" = "yes"; then LDFLAGS="$LDFLAGS -Wl,--warn-common" fi # (add duplicate symbols option to LDFLAGS) # ----------------------------------------------------------------------------- # The following is a "global error" flag used to defer aborting configure # until after ALL errors have been detected/reported. # ----------------------------------------------------------------------------- hc_error=no ############################################################################### # Autoheader templates ############################################################################### # All AC_DEFINE() macros used within autoconf (to define pre-processor vars # used during the actual build process) must have corresponding AH_TEMPLATE # statements coded somewhere. We place them all here simply for convenience. ############################################################################### # OS-specific settings that we can't figure out any other way (yet) ############################################################################### # # Determine what type of host we're building on... # case "$host_os" in linux*) hc_cv_is_nix=yes hc_cv_is_windows=no hc_cv_is_mingw32=no hc_cv_is_apple=no ;; mingw*) hc_cv_is_nix=no hc_cv_is_windows=yes hc_cv_is_mingw32=yes hc_cv_is_apple=no ;; cygwin*) hc_cv_is_nix=no hc_cv_is_windows=yes hc_cv_is_mingw32=no hc_cv_is_apple=no ;; darwin*) if test $host_vendor = apple; then hc_cv_is_nix=no hc_cv_is_windows=no hc_cv_is_mingw32=no hc_cv_is_apple=yes else hc_cv_is_nix=no hc_cv_is_windows=no hc_cv_is_mingw32=no hc_cv_is_apple=no fi ;; *bsd*) hc_cv_is_nix=yes hc_cv_is_windows=no hc_cv_is_mingw32=no hc_cv_is_apple=no ;; *) hc_cv_is_nix=no hc_cv_is_windows=no hc_cv_is_mingw32=no hc_cv_is_apple=no ;; esac #------------------------------------------------------# # Hard-coded host-operating-system-specific settings # # that we have no other/easy way to figure out... # #------------------------------------------------------# if test "$hc_cv_is_nix" = "yes"; then hc_cv_build_hercifc=yes hc_cv_non_unique_gettimeofday=no elif test "$hc_cv_is_windows" = "yes"; then hc_cv_build_hercifc=no hc_cv_non_unique_gettimeofday=yes elif test "$hc_cv_is_apple" = "yes"; then hc_cv_build_hercifc=yes hc_cv_non_unique_gettimeofday=no else hc_cv_build_hercifc=no hc_cv_non_unique_gettimeofday=no fi ############################################################################### # Checks for REQUIRED (non-optional) header files... ############################################################################### # PROGRAMMING NOTE: We use 'AC_CHECK_HEADER' here (singular) since we don't # care whether 'HAVE_XXX' gets #defined or not since, because these are re- # quired headers, if any of them are not found, we abort and thus we don't # need to have any 'HAVE_XXX' pre-processor #defined entered into config.h # (because we can't build Herc at all if any of them don't happen to exist) if test "${ac_cv_header_ctype_h+set}" = set; then { echo "$as_me:$LINENO: checking for ctype.h" >&5 echo $ECHO_N "checking for ctype.h... $ECHO_C" >&6; } if test "${ac_cv_header_ctype_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi { echo "$as_me:$LINENO: result: $ac_cv_header_ctype_h" >&5 echo "${ECHO_T}$ac_cv_header_ctype_h" >&6; } else # Is the header compilable? { echo "$as_me:$LINENO: checking ctype.h usability" >&5 echo $ECHO_N "checking ctype.h 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 _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core 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 ctype.h presence" >&5 echo $ECHO_N "checking ctype.h 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 _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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 && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.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_c_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: ctype.h: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: ctype.h: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: ctype.h: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: ctype.h: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: ctype.h: present but cannot be compiled" >&5 echo "$as_me: WARNING: ctype.h: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: ctype.h: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: ctype.h: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: ctype.h: see the Autoconf documentation" >&5 echo "$as_me: WARNING: ctype.h: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: ctype.h: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: ctype.h: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: ctype.h: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: ctype.h: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: ctype.h: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: ctype.h: in the future, the compiler will take precedence" >&2;} ;; esac { echo "$as_me:$LINENO: checking for ctype.h" >&5 echo $ECHO_N "checking for ctype.h... $ECHO_C" >&6; } if test "${ac_cv_header_ctype_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_header_ctype_h=$ac_header_preproc fi { echo "$as_me:$LINENO: result: $ac_cv_header_ctype_h" >&5 echo "${ECHO_T}$ac_cv_header_ctype_h" >&6; } fi if test $ac_cv_header_ctype_h = yes; then : else { echo "$as_me:$LINENO: result: ERROR: Required header 'ctype.h' not found " >&5 echo "${ECHO_T}ERROR: Required header 'ctype.h' not found " >&6; }; hc_error=yes fi if test "${ac_cv_header_errno_h+set}" = set; then { echo "$as_me:$LINENO: checking for errno.h" >&5 echo $ECHO_N "checking for errno.h... $ECHO_C" >&6; } if test "${ac_cv_header_errno_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi { echo "$as_me:$LINENO: result: $ac_cv_header_errno_h" >&5 echo "${ECHO_T}$ac_cv_header_errno_h" >&6; } else # Is the header compilable? { echo "$as_me:$LINENO: checking errno.h usability" >&5 echo $ECHO_N "checking errno.h 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 _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core 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 errno.h presence" >&5 echo $ECHO_N "checking errno.h 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 _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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 && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.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_c_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: errno.h: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: errno.h: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: errno.h: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: errno.h: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: errno.h: present but cannot be compiled" >&5 echo "$as_me: WARNING: errno.h: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: errno.h: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: errno.h: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: errno.h: see the Autoconf documentation" >&5 echo "$as_me: WARNING: errno.h: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: errno.h: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: errno.h: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: errno.h: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: errno.h: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: errno.h: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: errno.h: in the future, the compiler will take precedence" >&2;} ;; esac { echo "$as_me:$LINENO: checking for errno.h" >&5 echo $ECHO_N "checking for errno.h... $ECHO_C" >&6; } if test "${ac_cv_header_errno_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_header_errno_h=$ac_header_preproc fi { echo "$as_me:$LINENO: result: $ac_cv_header_errno_h" >&5 echo "${ECHO_T}$ac_cv_header_errno_h" >&6; } fi if test $ac_cv_header_errno_h = yes; then : else { echo "$as_me:$LINENO: result: ERROR: Required header 'errno.h' not found " >&5 echo "${ECHO_T}ERROR: Required header 'errno.h' not found " >&6; }; hc_error=yes fi if test "${ac_cv_header_fcntl_h+set}" = set; then { echo "$as_me:$LINENO: checking for fcntl.h" >&5 echo $ECHO_N "checking for fcntl.h... $ECHO_C" >&6; } if test "${ac_cv_header_fcntl_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi { echo "$as_me:$LINENO: result: $ac_cv_header_fcntl_h" >&5 echo "${ECHO_T}$ac_cv_header_fcntl_h" >&6; } else # Is the header compilable? { echo "$as_me:$LINENO: checking fcntl.h usability" >&5 echo $ECHO_N "checking fcntl.h 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 _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core 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 fcntl.h presence" >&5 echo $ECHO_N "checking fcntl.h 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 _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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 && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.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_c_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: fcntl.h: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: fcntl.h: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: fcntl.h: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: fcntl.h: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: fcntl.h: present but cannot be compiled" >&5 echo "$as_me: WARNING: fcntl.h: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: fcntl.h: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: fcntl.h: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: fcntl.h: see the Autoconf documentation" >&5 echo "$as_me: WARNING: fcntl.h: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: fcntl.h: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: fcntl.h: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: fcntl.h: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: fcntl.h: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: fcntl.h: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: fcntl.h: in the future, the compiler will take precedence" >&2;} ;; esac { echo "$as_me:$LINENO: checking for fcntl.h" >&5 echo $ECHO_N "checking for fcntl.h... $ECHO_C" >&6; } if test "${ac_cv_header_fcntl_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_header_fcntl_h=$ac_header_preproc fi { echo "$as_me:$LINENO: result: $ac_cv_header_fcntl_h" >&5 echo "${ECHO_T}$ac_cv_header_fcntl_h" >&6; } fi if test $ac_cv_header_fcntl_h = yes; then : else { echo "$as_me:$LINENO: result: ERROR: Required header 'fcntl.h' not found " >&5 echo "${ECHO_T}ERROR: Required header 'fcntl.h' not found " >&6; }; hc_error=yes fi if test "${ac_cv_header_limits_h+set}" = set; then { echo "$as_me:$LINENO: checking for limits.h" >&5 echo $ECHO_N "checking for limits.h... $ECHO_C" >&6; } if test "${ac_cv_header_limits_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi { echo "$as_me:$LINENO: result: $ac_cv_header_limits_h" >&5 echo "${ECHO_T}$ac_cv_header_limits_h" >&6; } else # Is the header compilable? { echo "$as_me:$LINENO: checking limits.h usability" >&5 echo $ECHO_N "checking limits.h 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 _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core 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 limits.h presence" >&5 echo $ECHO_N "checking limits.h 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 _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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 && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.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_c_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: limits.h: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: limits.h: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: limits.h: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: limits.h: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: limits.h: present but cannot be compiled" >&5 echo "$as_me: WARNING: limits.h: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: limits.h: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: limits.h: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: limits.h: see the Autoconf documentation" >&5 echo "$as_me: WARNING: limits.h: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: limits.h: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: limits.h: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: limits.h: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: limits.h: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: limits.h: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: limits.h: in the future, the compiler will take precedence" >&2;} ;; esac { echo "$as_me:$LINENO: checking for limits.h" >&5 echo $ECHO_N "checking for limits.h... $ECHO_C" >&6; } if test "${ac_cv_header_limits_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_header_limits_h=$ac_header_preproc fi { echo "$as_me:$LINENO: result: $ac_cv_header_limits_h" >&5 echo "${ECHO_T}$ac_cv_header_limits_h" >&6; } fi if test $ac_cv_header_limits_h = yes; then : else { echo "$as_me:$LINENO: result: ERROR: Required header 'limits.h' not found " >&5 echo "${ECHO_T}ERROR: Required header 'limits.h' not found " >&6; }; hc_error=yes fi if test "${ac_cv_header_setjmp_h+set}" = set; then { echo "$as_me:$LINENO: checking for setjmp.h" >&5 echo $ECHO_N "checking for setjmp.h... $ECHO_C" >&6; } if test "${ac_cv_header_setjmp_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi { echo "$as_me:$LINENO: result: $ac_cv_header_setjmp_h" >&5 echo "${ECHO_T}$ac_cv_header_setjmp_h" >&6; } else # Is the header compilable? { echo "$as_me:$LINENO: checking setjmp.h usability" >&5 echo $ECHO_N "checking setjmp.h 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 _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core 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 setjmp.h presence" >&5 echo $ECHO_N "checking setjmp.h 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 _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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 && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.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_c_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: setjmp.h: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: setjmp.h: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: setjmp.h: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: setjmp.h: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: setjmp.h: present but cannot be compiled" >&5 echo "$as_me: WARNING: setjmp.h: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: setjmp.h: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: setjmp.h: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: setjmp.h: see the Autoconf documentation" >&5 echo "$as_me: WARNING: setjmp.h: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: setjmp.h: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: setjmp.h: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: setjmp.h: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: setjmp.h: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: setjmp.h: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: setjmp.h: in the future, the compiler will take precedence" >&2;} ;; esac { echo "$as_me:$LINENO: checking for setjmp.h" >&5 echo $ECHO_N "checking for setjmp.h... $ECHO_C" >&6; } if test "${ac_cv_header_setjmp_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_header_setjmp_h=$ac_header_preproc fi { echo "$as_me:$LINENO: result: $ac_cv_header_setjmp_h" >&5 echo "${ECHO_T}$ac_cv_header_setjmp_h" >&6; } fi if test $ac_cv_header_setjmp_h = yes; then : else { echo "$as_me:$LINENO: result: ERROR: Required header 'setjmp.h' not found " >&5 echo "${ECHO_T}ERROR: Required header 'setjmp.h' not found " >&6; }; hc_error=yes fi if test "${ac_cv_header_stdarg_h+set}" = set; then { echo "$as_me:$LINENO: checking for stdarg.h" >&5 echo $ECHO_N "checking for stdarg.h... $ECHO_C" >&6; } if test "${ac_cv_header_stdarg_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi { echo "$as_me:$LINENO: result: $ac_cv_header_stdarg_h" >&5 echo "${ECHO_T}$ac_cv_header_stdarg_h" >&6; } else # Is the header compilable? { echo "$as_me:$LINENO: checking stdarg.h usability" >&5 echo $ECHO_N "checking stdarg.h 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 _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core 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 stdarg.h presence" >&5 echo $ECHO_N "checking stdarg.h 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 _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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 && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.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_c_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: stdarg.h: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: stdarg.h: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: stdarg.h: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: stdarg.h: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: stdarg.h: present but cannot be compiled" >&5 echo "$as_me: WARNING: stdarg.h: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: stdarg.h: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: stdarg.h: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: stdarg.h: see the Autoconf documentation" >&5 echo "$as_me: WARNING: stdarg.h: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: stdarg.h: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: stdarg.h: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: stdarg.h: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: stdarg.h: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: stdarg.h: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: stdarg.h: in the future, the compiler will take precedence" >&2;} ;; esac { echo "$as_me:$LINENO: checking for stdarg.h" >&5 echo $ECHO_N "checking for stdarg.h... $ECHO_C" >&6; } if test "${ac_cv_header_stdarg_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_header_stdarg_h=$ac_header_preproc fi { echo "$as_me:$LINENO: result: $ac_cv_header_stdarg_h" >&5 echo "${ECHO_T}$ac_cv_header_stdarg_h" >&6; } fi if test $ac_cv_header_stdarg_h = yes; then : else { echo "$as_me:$LINENO: result: ERROR: Required header 'stdarg.h' not found " >&5 echo "${ECHO_T}ERROR: Required header 'stdarg.h' not found " >&6; }; hc_error=yes fi if test "${ac_cv_header_stdio_h+set}" = set; then { echo "$as_me:$LINENO: checking for stdio.h" >&5 echo $ECHO_N "checking for stdio.h... $ECHO_C" >&6; } if test "${ac_cv_header_stdio_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi { echo "$as_me:$LINENO: result: $ac_cv_header_stdio_h" >&5 echo "${ECHO_T}$ac_cv_header_stdio_h" >&6; } else # Is the header compilable? { echo "$as_me:$LINENO: checking stdio.h usability" >&5 echo $ECHO_N "checking stdio.h 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 _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core 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 stdio.h presence" >&5 echo $ECHO_N "checking stdio.h 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 _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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 && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.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_c_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: stdio.h: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: stdio.h: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: stdio.h: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: stdio.h: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: stdio.h: present but cannot be compiled" >&5 echo "$as_me: WARNING: stdio.h: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: stdio.h: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: stdio.h: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: stdio.h: see the Autoconf documentation" >&5 echo "$as_me: WARNING: stdio.h: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: stdio.h: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: stdio.h: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: stdio.h: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: stdio.h: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: stdio.h: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: stdio.h: in the future, the compiler will take precedence" >&2;} ;; esac { echo "$as_me:$LINENO: checking for stdio.h" >&5 echo $ECHO_N "checking for stdio.h... $ECHO_C" >&6; } if test "${ac_cv_header_stdio_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_header_stdio_h=$ac_header_preproc fi { echo "$as_me:$LINENO: result: $ac_cv_header_stdio_h" >&5 echo "${ECHO_T}$ac_cv_header_stdio_h" >&6; } fi if test $ac_cv_header_stdio_h = yes; then : else { echo "$as_me:$LINENO: result: ERROR: Required header 'stdio.h' not found " >&5 echo "${ECHO_T}ERROR: Required header 'stdio.h' not found " >&6; }; hc_error=yes fi if test "${ac_cv_header_stdlib_h+set}" = set; then { echo "$as_me:$LINENO: checking for stdlib.h" >&5 echo $ECHO_N "checking for stdlib.h... $ECHO_C" >&6; } if test "${ac_cv_header_stdlib_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi { echo "$as_me:$LINENO: result: $ac_cv_header_stdlib_h" >&5 echo "${ECHO_T}$ac_cv_header_stdlib_h" >&6; } else # Is the header compilable? { echo "$as_me:$LINENO: checking stdlib.h usability" >&5 echo $ECHO_N "checking stdlib.h 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 _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core 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 stdlib.h presence" >&5 echo $ECHO_N "checking stdlib.h 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 _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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 && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.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_c_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: stdlib.h: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: stdlib.h: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: stdlib.h: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: stdlib.h: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: stdlib.h: present but cannot be compiled" >&5 echo "$as_me: WARNING: stdlib.h: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: stdlib.h: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: stdlib.h: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: stdlib.h: see the Autoconf documentation" >&5 echo "$as_me: WARNING: stdlib.h: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: stdlib.h: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: stdlib.h: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: stdlib.h: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: stdlib.h: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: stdlib.h: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: stdlib.h: in the future, the compiler will take precedence" >&2;} ;; esac { echo "$as_me:$LINENO: checking for stdlib.h" >&5 echo $ECHO_N "checking for stdlib.h... $ECHO_C" >&6; } if test "${ac_cv_header_stdlib_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_header_stdlib_h=$ac_header_preproc fi { echo "$as_me:$LINENO: result: $ac_cv_header_stdlib_h" >&5 echo "${ECHO_T}$ac_cv_header_stdlib_h" >&6; } fi if test $ac_cv_header_stdlib_h = yes; then : else { echo "$as_me:$LINENO: result: ERROR: Required header 'stdlib.h' not found " >&5 echo "${ECHO_T}ERROR: Required header 'stdlib.h' not found " >&6; }; hc_error=yes fi if test "${ac_cv_header_string_h+set}" = set; then { echo "$as_me:$LINENO: checking for string.h" >&5 echo $ECHO_N "checking for string.h... $ECHO_C" >&6; } if test "${ac_cv_header_string_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi { echo "$as_me:$LINENO: result: $ac_cv_header_string_h" >&5 echo "${ECHO_T}$ac_cv_header_string_h" >&6; } else # Is the header compilable? { echo "$as_me:$LINENO: checking string.h usability" >&5 echo $ECHO_N "checking string.h 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 _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core 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 string.h presence" >&5 echo $ECHO_N "checking string.h 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 _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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 && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.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_c_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: string.h: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: string.h: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: string.h: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: string.h: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: string.h: present but cannot be compiled" >&5 echo "$as_me: WARNING: string.h: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: string.h: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: string.h: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: string.h: see the Autoconf documentation" >&5 echo "$as_me: WARNING: string.h: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: string.h: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: string.h: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: string.h: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: string.h: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: string.h: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: string.h: in the future, the compiler will take precedence" >&2;} ;; esac { echo "$as_me:$LINENO: checking for string.h" >&5 echo $ECHO_N "checking for string.h... $ECHO_C" >&6; } if test "${ac_cv_header_string_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_header_string_h=$ac_header_preproc fi { echo "$as_me:$LINENO: result: $ac_cv_header_string_h" >&5 echo "${ECHO_T}$ac_cv_header_string_h" >&6; } fi if test $ac_cv_header_string_h = yes; then : else { echo "$as_me:$LINENO: result: ERROR: Required header 'string.h' not found " >&5 echo "${ECHO_T}ERROR: Required header 'string.h' not found " >&6; }; hc_error=yes fi if test "${ac_cv_header_time_h+set}" = set; then { echo "$as_me:$LINENO: checking for time.h" >&5 echo $ECHO_N "checking for time.h... $ECHO_C" >&6; } if test "${ac_cv_header_time_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi { echo "$as_me:$LINENO: result: $ac_cv_header_time_h" >&5 echo "${ECHO_T}$ac_cv_header_time_h" >&6; } else # Is the header compilable? { echo "$as_me:$LINENO: checking time.h usability" >&5 echo $ECHO_N "checking time.h 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 _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core 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 time.h presence" >&5 echo $ECHO_N "checking time.h 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 _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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 && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.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_c_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: time.h: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: time.h: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: time.h: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: time.h: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: time.h: present but cannot be compiled" >&5 echo "$as_me: WARNING: time.h: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: time.h: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: time.h: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: time.h: see the Autoconf documentation" >&5 echo "$as_me: WARNING: time.h: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: time.h: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: time.h: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: time.h: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: time.h: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: time.h: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: time.h: in the future, the compiler will take precedence" >&2;} ;; esac { echo "$as_me:$LINENO: checking for time.h" >&5 echo $ECHO_N "checking for time.h... $ECHO_C" >&6; } if test "${ac_cv_header_time_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_header_time_h=$ac_header_preproc fi { echo "$as_me:$LINENO: result: $ac_cv_header_time_h" >&5 echo "${ECHO_T}$ac_cv_header_time_h" >&6; } fi if test $ac_cv_header_time_h = yes; then : else { echo "$as_me:$LINENO: result: ERROR: Required header 'time.h' not found " >&5 echo "${ECHO_T}ERROR: Required header 'time.h' not found " >&6; }; hc_error=yes fi if test "${ac_cv_header_unistd_h+set}" = set; then { echo "$as_me:$LINENO: checking for unistd.h" >&5 echo $ECHO_N "checking for unistd.h... $ECHO_C" >&6; } if test "${ac_cv_header_unistd_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi { echo "$as_me:$LINENO: result: $ac_cv_header_unistd_h" >&5 echo "${ECHO_T}$ac_cv_header_unistd_h" >&6; } else # Is the header compilable? { echo "$as_me:$LINENO: checking unistd.h usability" >&5 echo $ECHO_N "checking unistd.h 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 _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core 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 unistd.h presence" >&5 echo $ECHO_N "checking unistd.h 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 _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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 && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.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_c_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: unistd.h: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: unistd.h: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: unistd.h: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: unistd.h: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: unistd.h: present but cannot be compiled" >&5 echo "$as_me: WARNING: unistd.h: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: unistd.h: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: unistd.h: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: unistd.h: see the Autoconf documentation" >&5 echo "$as_me: WARNING: unistd.h: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: unistd.h: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: unistd.h: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: unistd.h: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: unistd.h: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: unistd.h: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: unistd.h: in the future, the compiler will take precedence" >&2;} ;; esac { echo "$as_me:$LINENO: checking for unistd.h" >&5 echo $ECHO_N "checking for unistd.h... $ECHO_C" >&6; } if test "${ac_cv_header_unistd_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_header_unistd_h=$ac_header_preproc fi { echo "$as_me:$LINENO: result: $ac_cv_header_unistd_h" >&5 echo "${ECHO_T}$ac_cv_header_unistd_h" >&6; } fi if test $ac_cv_header_unistd_h = yes; then : else { echo "$as_me:$LINENO: result: ERROR: Required header 'unistd.h' not found " >&5 echo "${ECHO_T}ERROR: Required header 'unistd.h' not found " >&6; }; hc_error=yes fi if test "${ac_cv_header_sys_stat_h+set}" = set; then { echo "$as_me:$LINENO: checking for sys/stat.h" >&5 echo $ECHO_N "checking for sys/stat.h... $ECHO_C" >&6; } if test "${ac_cv_header_sys_stat_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi { echo "$as_me:$LINENO: result: $ac_cv_header_sys_stat_h" >&5 echo "${ECHO_T}$ac_cv_header_sys_stat_h" >&6; } else # Is the header compilable? { echo "$as_me:$LINENO: checking sys/stat.h usability" >&5 echo $ECHO_N "checking sys/stat.h 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 _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core 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 sys/stat.h presence" >&5 echo $ECHO_N "checking sys/stat.h 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 _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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 && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.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_c_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: sys/stat.h: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: sys/stat.h: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: sys/stat.h: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: sys/stat.h: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: sys/stat.h: present but cannot be compiled" >&5 echo "$as_me: WARNING: sys/stat.h: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: sys/stat.h: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: sys/stat.h: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: sys/stat.h: see the Autoconf documentation" >&5 echo "$as_me: WARNING: sys/stat.h: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: sys/stat.h: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: sys/stat.h: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: sys/stat.h: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: sys/stat.h: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: sys/stat.h: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: sys/stat.h: in the future, the compiler will take precedence" >&2;} ;; esac { echo "$as_me:$LINENO: checking for sys/stat.h" >&5 echo $ECHO_N "checking for sys/stat.h... $ECHO_C" >&6; } if test "${ac_cv_header_sys_stat_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_header_sys_stat_h=$ac_header_preproc fi { echo "$as_me:$LINENO: result: $ac_cv_header_sys_stat_h" >&5 echo "${ECHO_T}$ac_cv_header_sys_stat_h" >&6; } fi if test $ac_cv_header_sys_stat_h = yes; then : else { echo "$as_me:$LINENO: result: ERROR: Required header 'sys/stat.h' not found " >&5 echo "${ECHO_T}ERROR: Required header 'sys/stat.h' not found " >&6; }; hc_error=yes fi if test "${ac_cv_header_sys_time_h+set}" = set; then { echo "$as_me:$LINENO: checking for sys/time.h" >&5 echo $ECHO_N "checking for sys/time.h... $ECHO_C" >&6; } if test "${ac_cv_header_sys_time_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi { echo "$as_me:$LINENO: result: $ac_cv_header_sys_time_h" >&5 echo "${ECHO_T}$ac_cv_header_sys_time_h" >&6; } else # Is the header compilable? { echo "$as_me:$LINENO: checking sys/time.h usability" >&5 echo $ECHO_N "checking sys/time.h 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 _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core 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 sys/time.h presence" >&5 echo $ECHO_N "checking sys/time.h 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 _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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 && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.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_c_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: sys/time.h: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: sys/time.h: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: sys/time.h: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: sys/time.h: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: sys/time.h: present but cannot be compiled" >&5 echo "$as_me: WARNING: sys/time.h: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: sys/time.h: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: sys/time.h: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: sys/time.h: see the Autoconf documentation" >&5 echo "$as_me: WARNING: sys/time.h: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: sys/time.h: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: sys/time.h: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: sys/time.h: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: sys/time.h: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: sys/time.h: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: sys/time.h: in the future, the compiler will take precedence" >&2;} ;; esac { echo "$as_me:$LINENO: checking for sys/time.h" >&5 echo $ECHO_N "checking for sys/time.h... $ECHO_C" >&6; } if test "${ac_cv_header_sys_time_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_header_sys_time_h=$ac_header_preproc fi { echo "$as_me:$LINENO: result: $ac_cv_header_sys_time_h" >&5 echo "${ECHO_T}$ac_cv_header_sys_time_h" >&6; } fi if test $ac_cv_header_sys_time_h = yes; then : else { echo "$as_me:$LINENO: result: ERROR: Required header 'sys/time.h' not found " >&5 echo "${ECHO_T}ERROR: Required header 'sys/time.h' not found " >&6; }; hc_error=yes fi if test "${ac_cv_header_sys_types_h+set}" = set; then { echo "$as_me:$LINENO: checking for sys/types.h" >&5 echo $ECHO_N "checking for sys/types.h... $ECHO_C" >&6; } if test "${ac_cv_header_sys_types_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi { echo "$as_me:$LINENO: result: $ac_cv_header_sys_types_h" >&5 echo "${ECHO_T}$ac_cv_header_sys_types_h" >&6; } else # Is the header compilable? { echo "$as_me:$LINENO: checking sys/types.h usability" >&5 echo $ECHO_N "checking sys/types.h 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 _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core 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 sys/types.h presence" >&5 echo $ECHO_N "checking sys/types.h 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 _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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 && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.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_c_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: sys/types.h: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: sys/types.h: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: sys/types.h: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: sys/types.h: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: sys/types.h: present but cannot be compiled" >&5 echo "$as_me: WARNING: sys/types.h: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: sys/types.h: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: sys/types.h: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: sys/types.h: see the Autoconf documentation" >&5 echo "$as_me: WARNING: sys/types.h: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: sys/types.h: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: sys/types.h: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: sys/types.h: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: sys/types.h: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: sys/types.h: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: sys/types.h: in the future, the compiler will take precedence" >&2;} ;; esac { echo "$as_me:$LINENO: checking for sys/types.h" >&5 echo $ECHO_N "checking for sys/types.h... $ECHO_C" >&6; } if test "${ac_cv_header_sys_types_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_header_sys_types_h=$ac_header_preproc fi { echo "$as_me:$LINENO: result: $ac_cv_header_sys_types_h" >&5 echo "${ECHO_T}$ac_cv_header_sys_types_h" >&6; } fi if test $ac_cv_header_sys_types_h = yes; then : else { echo "$as_me:$LINENO: result: ERROR: Required header 'sys/types.h' not found " >&5 echo "${ECHO_T}ERROR: Required header 'sys/types.h' not found " >&6; }; hc_error=yes fi # PROGRAMMING NOTE: the pthread.h header only required if this is not # an fthreads build. Thus we delay aborting until later once we know # (if this is a windows build; otherwise we abort right away) if test "${ac_cv_header_pthread_h+set}" = set; then { echo "$as_me:$LINENO: checking for pthread.h" >&5 echo $ECHO_N "checking for pthread.h... $ECHO_C" >&6; } if test "${ac_cv_header_pthread_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi { echo "$as_me:$LINENO: result: $ac_cv_header_pthread_h" >&5 echo "${ECHO_T}$ac_cv_header_pthread_h" >&6; } else # Is the header compilable? { echo "$as_me:$LINENO: checking pthread.h usability" >&5 echo $ECHO_N "checking pthread.h 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 _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core 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 pthread.h presence" >&5 echo $ECHO_N "checking pthread.h 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 _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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 && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.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_c_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: pthread.h: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: pthread.h: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: pthread.h: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: pthread.h: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: pthread.h: present but cannot be compiled" >&5 echo "$as_me: WARNING: pthread.h: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: pthread.h: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: pthread.h: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: pthread.h: see the Autoconf documentation" >&5 echo "$as_me: WARNING: pthread.h: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: pthread.h: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: pthread.h: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: pthread.h: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: pthread.h: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: pthread.h: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: pthread.h: in the future, the compiler will take precedence" >&2;} ;; esac { echo "$as_me:$LINENO: checking for pthread.h" >&5 echo $ECHO_N "checking for pthread.h... $ECHO_C" >&6; } if test "${ac_cv_header_pthread_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_header_pthread_h=$ac_header_preproc fi { echo "$as_me:$LINENO: result: $ac_cv_header_pthread_h" >&5 echo "${ECHO_T}$ac_cv_header_pthread_h" >&6; } fi if test $ac_cv_header_pthread_h = yes; then hc_cv_have_pthread_h=yes else if test "$hc_cv_is_windows" = "yes"; then hc_cv_alt_pthread_location=/usr/Pthreads { echo "$as_me:$LINENO: looking for pthread.h in ${hc_cv_alt_pthread_location} " >&5 echo "$as_me: looking for pthread.h in ${hc_cv_alt_pthread_location} " >&6;} hc_temp=$CFLAGS CFLAGS="$CFLAGS -I${hc_cv_alt_pthread_location}" if test "${ac_cv_header_pthread_h+set}" = set; then { echo "$as_me:$LINENO: checking for pthread.h" >&5 echo $ECHO_N "checking for pthread.h... $ECHO_C" >&6; } if test "${ac_cv_header_pthread_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi { echo "$as_me:$LINENO: result: $ac_cv_header_pthread_h" >&5 echo "${ECHO_T}$ac_cv_header_pthread_h" >&6; } else # Is the header compilable? { echo "$as_me:$LINENO: checking pthread.h usability" >&5 echo $ECHO_N "checking pthread.h 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 _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core 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 pthread.h presence" >&5 echo $ECHO_N "checking pthread.h 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 _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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 && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.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_c_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: pthread.h: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: pthread.h: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: pthread.h: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: pthread.h: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: pthread.h: present but cannot be compiled" >&5 echo "$as_me: WARNING: pthread.h: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: pthread.h: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: pthread.h: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: pthread.h: see the Autoconf documentation" >&5 echo "$as_me: WARNING: pthread.h: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: pthread.h: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: pthread.h: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: pthread.h: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: pthread.h: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: pthread.h: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: pthread.h: in the future, the compiler will take precedence" >&2;} ;; esac { echo "$as_me:$LINENO: checking for pthread.h" >&5 echo $ECHO_N "checking for pthread.h... $ECHO_C" >&6; } if test "${ac_cv_header_pthread_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_header_pthread_h=$ac_header_preproc fi { echo "$as_me:$LINENO: result: $ac_cv_header_pthread_h" >&5 echo "${ECHO_T}$ac_cv_header_pthread_h" >&6; } fi if test $ac_cv_header_pthread_h = yes; then hc_cv_have_pthread_h=yes else hc_cv_have_pthread_h=no fi CFLAGS=$hc_temp else { echo "$as_me:$LINENO: result: ERROR: Required header 'pthread.h' not found " >&5 echo "${ECHO_T}ERROR: Required header 'pthread.h' not found " >&6; } hc_error=yes fi fi cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5 echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( *) $as_unset $ac_var ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes (double-quote # substitution turns \\\\ into \\, and sed turns \\ into \). sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then test "x$cache_file" != "x/dev/null" && { echo "$as_me:$LINENO: updating cache $cache_file" >&5 echo "$as_me: updating cache $cache_file" >&6;} cat confcache >$cache_file else { echo "$as_me:$LINENO: not updating unwritable cache $cache_file" >&5 echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache ############################################################################### # Checks for optional (non-required) header files... ############################################################################### # PROGRAMMING NOTE: We use 'AC_CHECK_HEADERS' here (plural) to cause autoconf # to automatically add a #define/#undef 'HAVE_XXX' statement into config.h to # let us know whether the header exists on this system or not (since, because # these are optional headers, we are still able to successfully build Herc if # they don't happen to exist). The 'hc_cv_have_xxx' variables are only defined # in case other parts of configure.ac need to know whether the header exists # or not without having to do their own AC_CHECK_HEADERS (since we've already # done it). #------------------------------------------------------------------------------ # PROGRAMMING NOTE: on Darwin sys/socket.h must be included before # net/if.h, net/route.h, or netinet/in.h can be #included, and on OS X 10.3 # (but not 10.4) sys/types.h must be #included before sys/socket.h. Thus # the below four header checks are treated specially. If we ever drop support # for OS X 10.3, a lot of this cruft can be removed, not just here but # anywhere we find ourselves manually including sys/types.h. # PROGRAMMING NOTE: on *BSD sys/socket.h must be included before net/if.h, # net/route.h, or netinet/in.h can be #included. for ac_header in sys/socket.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 { as_var=$as_ac_Header; eval "test \"\${$as_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. */ #include #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core conftest.err conftest.$ac_objext conftest.$ac_ext fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&6; } if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF hc_cv_have_sys_socket_h=yes else hc_cv_have_sys_socket_h=no fi done for ac_header in net/if.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 { as_var=$as_ac_Header; eval "test \"\${$as_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. */ #include #if HAVE_SYS_SOCKET_H #include #endif #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core conftest.err conftest.$ac_objext conftest.$ac_ext fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&6; } if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF hc_cv_have_net_if_h=yes else hc_cv_have_net_if_h=no fi done for ac_header in netinet/in.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 { as_var=$as_ac_Header; eval "test \"\${$as_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. */ #include #if HAVE_SYS_SOCKET_H #include #endif #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core conftest.err conftest.$ac_objext conftest.$ac_ext fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&6; } if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF hc_cv_have_netinet_in_h=yes else hc_cv_have_netinet_in_h=no fi done for ac_header in netinet/tcp.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 { as_var=$as_ac_Header; eval "test \"\${$as_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. */ #include #if HAVE_SYS_SOCKET_H #include #endif #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core conftest.err conftest.$ac_objext conftest.$ac_ext fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&6; } if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF hc_cv_have_netinet_tcp_h=yes else hc_cv_have_netinet_tcp_h=no fi done for ac_header in net/route.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 { as_var=$as_ac_Header; eval "test \"\${$as_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. */ #include #if HAVE_SYS_SOCKET_H #include #endif #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core conftest.err conftest.$ac_objext conftest.$ac_ext fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&6; } if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF hc_cv_have_net_route_h=yes else hc_cv_have_net_route_h=no fi done #------------------------------------------------------------------------------ for ac_header in arpa/inet.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core 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 { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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 && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.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_c_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;} ;; esac { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 hc_cv_have_arpa_inet_h=yes else hc_cv_have_arpa_inet_h=no fi done for ac_header in linux/if_tun.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core 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 { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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 && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.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_c_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;} ;; esac { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 hc_cv_have_linux_if_tun_h=yes else hc_cv_have_linux_if_tun_h=no fi done for ac_header in sys/ioctl.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core 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 { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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 && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.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_c_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;} ;; esac { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 hc_cv_have_sys_ioctl_h=yes else hc_cv_have_sys_ioctl_h=no fi done for ac_header in sys/mman.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core 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 { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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 && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.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_c_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;} ;; esac { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 hc_cv_have_sys_mman_h=yes else hc_cv_have_sys_mman_h=no fi done #------------------------------------------------------------------------------ # PROGRAMMING NOTE: on *BSD systems sys/param.h must be #included before # sys/mount.h as it contains the #define of NGROUPS. for ac_header in sys/param.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core 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 { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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 && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.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_c_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;} ;; esac { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 hc_cv_have_sys_param_h=yes else hc_cv_have_sys_param_h=no fi done for ac_header in sys/mount.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 { as_var=$as_ac_Header; eval "test \"\${$as_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. */ #if HAVE_SYS_PARAM_H #include #endif #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core conftest.err conftest.$ac_objext conftest.$ac_ext fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&6; } if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF hc_cv_have_sys_mount_h=yes else hc_cv_have_sys_mount_h=no fi done #------------------------------------------------------------------------------ for ac_header in sys/mtio.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core 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 { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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 && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.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_c_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;} ;; esac { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 hc_cv_have_sys_mtio_h=yes else hc_cv_have_sys_mtio_h=no fi done for ac_header in sys/resource.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core 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 { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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 && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.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_c_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;} ;; esac { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 hc_cv_have_sys_resource_h=yes else hc_cv_have_sys_resource_h=no fi done for ac_header in sys/uio.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core 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 { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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 && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.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_c_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;} ;; esac { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 hc_cv_have_sys_uio_h=yes else hc_cv_have_sys_uio_h=no fi done for ac_header in sys/utsname.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core 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 { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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 && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.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_c_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;} ;; esac { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 hc_cv_have_sys_utsname_h=yes else hc_cv_have_sys_utsname_h=no fi done for ac_header in sys/wait.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core 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 { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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 && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.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_c_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;} ;; esac { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 hc_cv_have_sys_wait_h=yes else hc_cv_have_sys_wait_h=no fi done for ac_header in sys/un.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core 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 { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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 && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.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_c_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;} ;; esac { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 hc_cv_have_sys_un_h=yes else hc_cv_have_sys_un_h=no fi done for ac_header in byteswap.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core 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 { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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 && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.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_c_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;} ;; esac { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 hc_cv_have_byteswap_h=yes else hc_cv_have_byteswap_h=no fi done for ac_header in bzlib.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core 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 { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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 && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.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_c_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;} ;; esac { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 hc_cv_have_bzlib_h=yes else hc_cv_have_bzlib_h=no fi done for ac_header in dlfcn.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core 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 { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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 && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.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_c_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;} ;; esac { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 hc_cv_have_dlfcn_h=yes else hc_cv_have_dlfcn_h=no fi done for ac_header in fenv.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core 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 { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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 && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.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_c_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;} ;; esac { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 hc_cv_have_fenv_h=yes else hc_cv_have_fenv_h=no fi done for ac_header in inttypes.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core 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 { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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 && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.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_c_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;} ;; esac { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 hc_cv_have_inttypes_h=yes else hc_cv_have_inttypes_h=no fi done for ac_header in iconv.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core 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 { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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 && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.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_c_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;} ;; esac { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 hc_cv_have_iconv_h=yes else hc_cv_have_iconv_h=no fi done for ac_header in libintl.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core 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 { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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 && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.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_c_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;} ;; esac { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 hc_cv_have_libintl_h=yes else hc_cv_have_libintl_h=no fi done for ac_header in locale.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core 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 { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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 && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.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_c_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;} ;; esac { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 hc_cv_have_locale_h=yes else hc_cv_have_locale_h=no fi done for ac_header in ltdl.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core 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 { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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 && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.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_c_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;} ;; esac { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 hc_cv_have_ltdl_h=yes else hc_cv_have_ltdl_h=no fi done for ac_header in malloc.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core 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 { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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 && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.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_c_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;} ;; esac { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 hc_cv_have_malloc_h=yes else hc_cv_have_malloc_h=no fi done for ac_header in math.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core 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 { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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 && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.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_c_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;} ;; esac { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 hc_cv_have_math_h=yes else hc_cv_have_math_h=no fi done for ac_header in netdb.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core 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 { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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 && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.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_c_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;} ;; esac { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 hc_cv_have_netdb_h=yes else hc_cv_have_netdb_h=no fi done for ac_header in pwd.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core 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 { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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 && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.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_c_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;} ;; esac { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 hc_cv_have_pwd_h=yes else hc_cv_have_pwd_h=no fi done for ac_header in regex.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core 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 { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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 && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.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_c_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;} ;; esac { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 hc_cv_have_regex_h=yes else hc_cv_have_regex_h=no fi done for ac_header in sched.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core 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 { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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 && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.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_c_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;} ;; esac { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 hc_cv_have_sched_h=yes else hc_cv_have_sched_h=no fi done for ac_header in signal.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core 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 { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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 && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.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_c_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;} ;; esac { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 hc_cv_have_signal_h=yes else hc_cv_have_signal_h=no fi done for ac_header in termios.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core 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 { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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 && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.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_c_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;} ;; esac { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 hc_cv_have_termios_h=yes else hc_cv_have_termios_h=no fi done for ac_header in time.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core 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 { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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 && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.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_c_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;} ;; esac { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 hc_cv_have_time_h=yes else hc_cv_have_time_h=no fi done for ac_header in zlib.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core 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 { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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 && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.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_c_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;} ;; esac { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 hc_cv_have_zlib_h=yes else hc_cv_have_zlib_h=no fi done for ac_header in sys/capability.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core 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 { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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 && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.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_c_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;} ;; esac { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 hc_cv_have_sys_capa_h=yes else hc_cv_have_sys_capa_h=no fi done for ac_header in sys/prctl.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core 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 { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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 && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.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_c_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;} ;; esac { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 hc_cv_have_sys_prctl_h=yes else hc_cv_have_sys_prctl_h=no fi done cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5 echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( *) $as_unset $ac_var ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes (double-quote # substitution turns \\\\ into \\, and sed turns \\ into \). sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then test "x$cache_file" != "x/dev/null" && { echo "$as_me:$LINENO: updating cache $cache_file" >&5 echo "$as_me: updating cache $cache_file" >&6;} cat confcache >$cache_file else { echo "$as_me:$LINENO: not updating unwritable cache $cache_file" >&5 echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache ############################################################################### # Checks for declarations... ############################################################################### # PROGRAMMING NOTE: For declaration checks, you need to be careful to use the # following test in your program: # # #if defined(HAVE_DECL_XXXX) && !HAVE_DECL_XXXXX # ...code to handle not declared case... # #endif # # This is because UNLIKE other 'AC_CHECK' macros, when a SYMBOL isn't DECLared, # "HAVE_DECL_XXXX" is #defined to '0' instead of leaving "HAVE_DECL_XXXX" #undefined. # (e.g. #defined to 1 if you have the declaration and #defined to 0 if you don't) { echo "$as_me:$LINENO: checking whether SIGUSR1 is declared" >&5 echo $ECHO_N "checking whether SIGUSR1 is declared... $ECHO_C" >&6; } if test "${ac_cv_have_decl_SIGUSR1+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 SIGUSR1 (void) SIGUSR1; #endif ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_have_decl_SIGUSR1=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_have_decl_SIGUSR1=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_have_decl_SIGUSR1" >&5 echo "${ECHO_T}$ac_cv_have_decl_SIGUSR1" >&6; } if test $ac_cv_have_decl_SIGUSR1 = yes; then cat >>confdefs.h <<_ACEOF #define HAVE_DECL_SIGUSR1 1 _ACEOF hc_cv_have_sigusr1=yes else cat >>confdefs.h <<_ACEOF #define HAVE_DECL_SIGUSR1 0 _ACEOF hc_cv_have_sigusr1=no fi { echo "$as_me:$LINENO: checking whether SIGUSR2 is declared" >&5 echo $ECHO_N "checking whether SIGUSR2 is declared... $ECHO_C" >&6; } if test "${ac_cv_have_decl_SIGUSR2+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 SIGUSR2 (void) SIGUSR2; #endif ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_have_decl_SIGUSR2=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_have_decl_SIGUSR2=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_have_decl_SIGUSR2" >&5 echo "${ECHO_T}$ac_cv_have_decl_SIGUSR2" >&6; } if test $ac_cv_have_decl_SIGUSR2 = yes; then cat >>confdefs.h <<_ACEOF #define HAVE_DECL_SIGUSR2 1 _ACEOF hc_cv_have_sigusr2=yes else cat >>confdefs.h <<_ACEOF #define HAVE_DECL_SIGUSR2 0 _ACEOF hc_cv_have_sigusr2=no fi { echo "$as_me:$LINENO: checking whether SIGPIPE is declared" >&5 echo $ECHO_N "checking whether SIGPIPE is declared... $ECHO_C" >&6; } if test "${ac_cv_have_decl_SIGPIPE+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 SIGPIPE (void) SIGPIPE; #endif ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_have_decl_SIGPIPE=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_have_decl_SIGPIPE=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_have_decl_SIGPIPE" >&5 echo "${ECHO_T}$ac_cv_have_decl_SIGPIPE" >&6; } if test $ac_cv_have_decl_SIGPIPE = yes; then cat >>confdefs.h <<_ACEOF #define HAVE_DECL_SIGPIPE 1 _ACEOF hc_cv_have_sigpipe=yes else cat >>confdefs.h <<_ACEOF #define HAVE_DECL_SIGPIPE 0 _ACEOF hc_cv_have_sigpipe=no fi { echo "$as_me:$LINENO: checking whether SIGBUS is declared" >&5 echo $ECHO_N "checking whether SIGBUS is declared... $ECHO_C" >&6; } if test "${ac_cv_have_decl_SIGBUS+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 SIGBUS (void) SIGBUS; #endif ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_have_decl_SIGBUS=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_have_decl_SIGBUS=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_have_decl_SIGBUS" >&5 echo "${ECHO_T}$ac_cv_have_decl_SIGBUS" >&6; } if test $ac_cv_have_decl_SIGBUS = yes; then cat >>confdefs.h <<_ACEOF #define HAVE_DECL_SIGBUS 1 _ACEOF hc_cv_have_sigbus=yes else cat >>confdefs.h <<_ACEOF #define HAVE_DECL_SIGBUS 0 _ACEOF hc_cv_have_sigbus=no fi { echo "$as_me:$LINENO: checking whether IFNAMSIZ is declared" >&5 echo $ECHO_N "checking whether IFNAMSIZ is declared... $ECHO_C" >&6; } if test "${ac_cv_have_decl_IFNAMSIZ+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 #if HAVE_SYS_SOCKET_H #include #endif int main () { #ifndef IFNAMSIZ (void) IFNAMSIZ; #endif ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_have_decl_IFNAMSIZ=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_have_decl_IFNAMSIZ=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_have_decl_IFNAMSIZ" >&5 echo "${ECHO_T}$ac_cv_have_decl_IFNAMSIZ" >&6; } if test $ac_cv_have_decl_IFNAMSIZ = yes; then cat >>confdefs.h <<_ACEOF #define HAVE_DECL_IFNAMSIZ 1 _ACEOF hc_cv_have_ifnamsiz=yes else cat >>confdefs.h <<_ACEOF #define HAVE_DECL_IFNAMSIZ 0 _ACEOF hc_cv_have_ifnamsiz=no fi { echo "$as_me:$LINENO: checking whether LOGIN_NAME_MAX is declared" >&5 echo $ECHO_N "checking whether LOGIN_NAME_MAX is declared... $ECHO_C" >&6; } if test "${ac_cv_have_decl_LOGIN_NAME_MAX+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 LOGIN_NAME_MAX (void) LOGIN_NAME_MAX; #endif ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_have_decl_LOGIN_NAME_MAX=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_have_decl_LOGIN_NAME_MAX=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_have_decl_LOGIN_NAME_MAX" >&5 echo "${ECHO_T}$ac_cv_have_decl_LOGIN_NAME_MAX" >&6; } if test $ac_cv_have_decl_LOGIN_NAME_MAX = yes; then cat >>confdefs.h <<_ACEOF #define HAVE_DECL_LOGIN_NAME_MAX 1 _ACEOF hc_cv_have_login_name_max=yes else cat >>confdefs.h <<_ACEOF #define HAVE_DECL_LOGIN_NAME_MAX 0 _ACEOF hc_cv_have_login_name_max=no fi { echo "$as_me:$LINENO: checking whether _SC_NPROCESSORS_CONF is declared" >&5 echo $ECHO_N "checking whether _SC_NPROCESSORS_CONF is declared... $ECHO_C" >&6; } if test "${ac_cv_have_decl__SC_NPROCESSORS_CONF+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 _SC_NPROCESSORS_CONF (void) _SC_NPROCESSORS_CONF; #endif ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_have_decl__SC_NPROCESSORS_CONF=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_have_decl__SC_NPROCESSORS_CONF=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_have_decl__SC_NPROCESSORS_CONF" >&5 echo "${ECHO_T}$ac_cv_have_decl__SC_NPROCESSORS_CONF" >&6; } if test $ac_cv_have_decl__SC_NPROCESSORS_CONF = yes; then cat >>confdefs.h <<_ACEOF #define HAVE_DECL__SC_NPROCESSORS_CONF 1 _ACEOF hc_cv_have_sc_nprocessors_conf=yes else cat >>confdefs.h <<_ACEOF #define HAVE_DECL__SC_NPROCESSORS_CONF 0 _ACEOF hc_cv_have_sc_nprocessors_conf=no fi { echo "$as_me:$LINENO: checking whether _SC_NPROCESSORS_ONLN is declared" >&5 echo $ECHO_N "checking whether _SC_NPROCESSORS_ONLN is declared... $ECHO_C" >&6; } if test "${ac_cv_have_decl__SC_NPROCESSORS_ONLN+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 _SC_NPROCESSORS_ONLN (void) _SC_NPROCESSORS_ONLN; #endif ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_have_decl__SC_NPROCESSORS_ONLN=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_have_decl__SC_NPROCESSORS_ONLN=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_have_decl__SC_NPROCESSORS_ONLN" >&5 echo "${ECHO_T}$ac_cv_have_decl__SC_NPROCESSORS_ONLN" >&6; } if test $ac_cv_have_decl__SC_NPROCESSORS_ONLN = yes; then cat >>confdefs.h <<_ACEOF #define HAVE_DECL__SC_NPROCESSORS_ONLN 1 _ACEOF hc_cv_have_sc_nprocessors_onln=yes else cat >>confdefs.h <<_ACEOF #define HAVE_DECL__SC_NPROCESSORS_ONLN 0 _ACEOF hc_cv_have_sc_nprocessors_onln=no fi { echo "$as_me:$LINENO: checking whether SIOCSIFNETMASK is declared" >&5 echo $ECHO_N "checking whether SIOCSIFNETMASK is declared... $ECHO_C" >&6; } if test "${ac_cv_have_decl_SIOCSIFNETMASK+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 SIOCSIFNETMASK (void) SIOCSIFNETMASK; #endif ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_have_decl_SIOCSIFNETMASK=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_have_decl_SIOCSIFNETMASK=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_have_decl_SIOCSIFNETMASK" >&5 echo "${ECHO_T}$ac_cv_have_decl_SIOCSIFNETMASK" >&6; } if test $ac_cv_have_decl_SIOCSIFNETMASK = yes; then cat >>confdefs.h <<_ACEOF #define HAVE_DECL_SIOCSIFNETMASK 1 _ACEOF hc_cv_have_siocsifnetmask=yes else cat >>confdefs.h <<_ACEOF #define HAVE_DECL_SIOCSIFNETMASK 0 _ACEOF hc_cv_have_siocsifnetmask=no fi { echo "$as_me:$LINENO: checking whether SIOCSIFHWADDR is declared" >&5 echo $ECHO_N "checking whether SIOCSIFHWADDR is declared... $ECHO_C" >&6; } if test "${ac_cv_have_decl_SIOCSIFHWADDR+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 SIOCSIFHWADDR (void) SIOCSIFHWADDR; #endif ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_have_decl_SIOCSIFHWADDR=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_have_decl_SIOCSIFHWADDR=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_have_decl_SIOCSIFHWADDR" >&5 echo "${ECHO_T}$ac_cv_have_decl_SIOCSIFHWADDR" >&6; } if test $ac_cv_have_decl_SIOCSIFHWADDR = yes; then cat >>confdefs.h <<_ACEOF #define HAVE_DECL_SIOCSIFHWADDR 1 _ACEOF hc_cv_have_siocsifhwaddr=yes else cat >>confdefs.h <<_ACEOF #define HAVE_DECL_SIOCSIFHWADDR 0 _ACEOF hc_cv_have_siocsifhwaddr=no fi { echo "$as_me:$LINENO: checking whether SIOCADDRT is declared" >&5 echo $ECHO_N "checking whether SIOCADDRT is declared... $ECHO_C" >&6; } if test "${ac_cv_have_decl_SIOCADDRT+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 SIOCADDRT (void) SIOCADDRT; #endif ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_have_decl_SIOCADDRT=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_have_decl_SIOCADDRT=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_have_decl_SIOCADDRT" >&5 echo "${ECHO_T}$ac_cv_have_decl_SIOCADDRT" >&6; } if test $ac_cv_have_decl_SIOCADDRT = yes; then cat >>confdefs.h <<_ACEOF #define HAVE_DECL_SIOCADDRT 1 _ACEOF hc_cv_have_siocaddrt=yes else cat >>confdefs.h <<_ACEOF #define HAVE_DECL_SIOCADDRT 0 _ACEOF hc_cv_have_siocaddrt=no fi { echo "$as_me:$LINENO: checking whether SIOCDELRT is declared" >&5 echo $ECHO_N "checking whether SIOCDELRT is declared... $ECHO_C" >&6; } if test "${ac_cv_have_decl_SIOCDELRT+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 SIOCDELRT (void) SIOCDELRT; #endif ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_have_decl_SIOCDELRT=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_have_decl_SIOCDELRT=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_have_decl_SIOCDELRT" >&5 echo "${ECHO_T}$ac_cv_have_decl_SIOCDELRT" >&6; } if test $ac_cv_have_decl_SIOCDELRT = yes; then cat >>confdefs.h <<_ACEOF #define HAVE_DECL_SIOCDELRT 1 _ACEOF hc_cv_have_siocdelrt=yes else cat >>confdefs.h <<_ACEOF #define HAVE_DECL_SIOCDELRT 0 _ACEOF hc_cv_have_siocdelrt=no fi { echo "$as_me:$LINENO: checking whether SIOCDIFADDR is declared" >&5 echo $ECHO_N "checking whether SIOCDIFADDR is declared... $ECHO_C" >&6; } if test "${ac_cv_have_decl_SIOCDIFADDR+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 SIOCDIFADDR (void) SIOCDIFADDR; #endif ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_have_decl_SIOCDIFADDR=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_have_decl_SIOCDIFADDR=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_have_decl_SIOCDIFADDR" >&5 echo "${ECHO_T}$ac_cv_have_decl_SIOCDIFADDR" >&6; } if test $ac_cv_have_decl_SIOCDIFADDR = yes; then cat >>confdefs.h <<_ACEOF #define HAVE_DECL_SIOCDIFADDR 1 _ACEOF hc_cv_have_siocdifaddr=yes else cat >>confdefs.h <<_ACEOF #define HAVE_DECL_SIOCDIFADDR 0 _ACEOF hc_cv_have_siocdifaddr=no fi if test "$hc_cv_have_sys_mtio_h" == "yes"; then { echo "$as_me:$LINENO: checking whether MTEWARN is declared" >&5 echo $ECHO_N "checking whether MTEWARN is declared... $ECHO_C" >&6; } if test "${ac_cv_have_decl_MTEWARN+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 MTEWARN (void) MTEWARN; #endif ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_have_decl_MTEWARN=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_have_decl_MTEWARN=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_have_decl_MTEWARN" >&5 echo "${ECHO_T}$ac_cv_have_decl_MTEWARN" >&6; } if test $ac_cv_have_decl_MTEWARN = yes; then cat >>confdefs.h <<_ACEOF #define HAVE_DECL_MTEWARN 1 _ACEOF hc_cv_have_mtewarn=yes else cat >>confdefs.h <<_ACEOF #define HAVE_DECL_MTEWARN 0 _ACEOF hc_cv_have_mtewarn=no fi else hc_cv_have_mtewarn=no fi cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5 echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( *) $as_unset $ac_var ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes (double-quote # substitution turns \\\\ into \\, and sed turns \\ into \). sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then test "x$cache_file" != "x/dev/null" && { echo "$as_me:$LINENO: updating cache $cache_file" >&5 echo "$as_me: updating cache $cache_file" >&6;} cat confcache >$cache_file else { echo "$as_me:$LINENO: not updating unwritable cache $cache_file" >&5 echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache ############################################################################### # Checks for types... ############################################################################### { echo "$as_me:$LINENO: checking for u_int8_t" >&5 echo $ECHO_N "checking for u_int8_t... $ECHO_C" >&6; } if test "${ac_cv_type_u_int8_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 typedef u_int8_t ac__type_new_; int main () { if ((ac__type_new_ *) 0) return 0; if (sizeof (ac__type_new_)) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_type_u_int8_t=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_type_u_int8_t=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_type_u_int8_t" >&5 echo "${ECHO_T}$ac_cv_type_u_int8_t" >&6; } if test $ac_cv_type_u_int8_t = yes; then cat >>confdefs.h <<_ACEOF #define HAVE_U_INT8_T 1 _ACEOF hc_cv_have_u_int8_t=yes else hc_cv_have_u_int8_t=no fi { echo "$as_me:$LINENO: checking for useconds_t" >&5 echo $ECHO_N "checking for useconds_t... $ECHO_C" >&6; } if test "${ac_cv_type_useconds_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 typedef useconds_t ac__type_new_; int main () { if ((ac__type_new_ *) 0) return 0; if (sizeof (ac__type_new_)) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_type_useconds_t=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_type_useconds_t=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_type_useconds_t" >&5 echo "${ECHO_T}$ac_cv_type_useconds_t" >&6; } if test $ac_cv_type_useconds_t = yes; then cat >>confdefs.h <<_ACEOF #define HAVE_USECONDS_T 1 _ACEOF hc_cv_have_useconds_t=yes else hc_cv_have_useconds_t=no fi { echo "$as_me:$LINENO: checking for id_t" >&5 echo $ECHO_N "checking for id_t... $ECHO_C" >&6; } if test "${ac_cv_type_id_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 typedef id_t ac__type_new_; int main () { if ((ac__type_new_ *) 0) return 0; if (sizeof (ac__type_new_)) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_type_id_t=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_type_id_t=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_type_id_t" >&5 echo "${ECHO_T}$ac_cv_type_id_t" >&6; } if test $ac_cv_type_id_t = yes; then cat >>confdefs.h <<_ACEOF #define HAVE_ID_T 1 _ACEOF hc_cv_have_id_t=yes else hc_cv_have_id_t=no fi { echo "$as_me:$LINENO: checking for u_char" >&5 echo $ECHO_N "checking for u_char... $ECHO_C" >&6; } if test "${ac_cv_type_u_char+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 #if HAVE_SYS_SOCKET_H #include #endif typedef u_char ac__type_new_; int main () { if ((ac__type_new_ *) 0) return 0; if (sizeof (ac__type_new_)) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_type_u_char=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_type_u_char=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_type_u_char" >&5 echo "${ECHO_T}$ac_cv_type_u_char" >&6; } if test $ac_cv_type_u_char = yes; then cat >>confdefs.h <<_ACEOF #define HAVE_U_CHAR 1 _ACEOF hc_cv_have_u_char=yes else hc_cv_have_u_char=no fi { echo "$as_me:$LINENO: checking for u_short" >&5 echo $ECHO_N "checking for u_short... $ECHO_C" >&6; } if test "${ac_cv_type_u_short+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 #if HAVE_SYS_SOCKET_H #include #endif typedef u_short ac__type_new_; int main () { if ((ac__type_new_ *) 0) return 0; if (sizeof (ac__type_new_)) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_type_u_short=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_type_u_short=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_type_u_short" >&5 echo "${ECHO_T}$ac_cv_type_u_short" >&6; } if test $ac_cv_type_u_short = yes; then cat >>confdefs.h <<_ACEOF #define HAVE_U_SHORT 1 _ACEOF hc_cv_have_u_short=yes else hc_cv_have_u_short=no fi { echo "$as_me:$LINENO: checking for u_int" >&5 echo $ECHO_N "checking for u_int... $ECHO_C" >&6; } if test "${ac_cv_type_u_int+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 #if HAVE_SYS_SOCKET_H #include #endif typedef u_int ac__type_new_; int main () { if ((ac__type_new_ *) 0) return 0; if (sizeof (ac__type_new_)) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_type_u_int=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_type_u_int=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_type_u_int" >&5 echo "${ECHO_T}$ac_cv_type_u_int" >&6; } if test $ac_cv_type_u_int = yes; then cat >>confdefs.h <<_ACEOF #define HAVE_U_INT 1 _ACEOF hc_cv_have_u_int=yes else hc_cv_have_u_int=no fi { echo "$as_me:$LINENO: checking for u_long" >&5 echo $ECHO_N "checking for u_long... $ECHO_C" >&6; } if test "${ac_cv_type_u_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. */ #include #if HAVE_SYS_SOCKET_H #include #endif typedef u_long ac__type_new_; int main () { if ((ac__type_new_ *) 0) return 0; if (sizeof (ac__type_new_)) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_type_u_long=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_type_u_long=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_type_u_long" >&5 echo "${ECHO_T}$ac_cv_type_u_long" >&6; } if test $ac_cv_type_u_long = yes; then cat >>confdefs.h <<_ACEOF #define HAVE_U_LONG 1 _ACEOF hc_cv_have_u_long=yes else hc_cv_have_u_long=no fi { echo "$as_me:$LINENO: checking for in_addr_t" >&5 echo $ECHO_N "checking for in_addr_t... $ECHO_C" >&6; } if test "${ac_cv_type_in_addr_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 #if HAVE_SYS_SOCKET_H #include #endif #if HAVE_NETINET_IN_H #include #endif typedef in_addr_t ac__type_new_; int main () { if ((ac__type_new_ *) 0) return 0; if (sizeof (ac__type_new_)) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_type_in_addr_t=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_type_in_addr_t=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_type_in_addr_t" >&5 echo "${ECHO_T}$ac_cv_type_in_addr_t" >&6; } if test $ac_cv_type_in_addr_t = yes; then cat >>confdefs.h <<_ACEOF #define HAVE_IN_ADDR_T 1 _ACEOF hc_cv_have_in_addr_t=yes else hc_cv_have_in_addr_t=no fi { echo "$as_me:$LINENO: checking for socklen_t" >&5 echo $ECHO_N "checking for socklen_t... $ECHO_C" >&6; } if test "${ac_cv_type_socklen_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 #if HAVE_SYS_SOCKET_H #include #endif typedef socklen_t ac__type_new_; int main () { if ((ac__type_new_ *) 0) return 0; if (sizeof (ac__type_new_)) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_type_socklen_t=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_type_socklen_t=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_type_socklen_t" >&5 echo "${ECHO_T}$ac_cv_type_socklen_t" >&6; } if test $ac_cv_type_socklen_t = yes; then cat >>confdefs.h <<_ACEOF #define HAVE_SOCKLEN_T 1 _ACEOF hc_cv_have_socklen_t=yes else hc_cv_have_socklen_t=no fi cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5 echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( *) $as_unset $ac_var ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes (double-quote # substitution turns \\\\ into \\, and sed turns \\ into \). sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then test "x$cache_file" != "x/dev/null" && { echo "$as_me:$LINENO: updating cache $cache_file" >&5 echo "$as_me: updating cache $cache_file" >&6;} cat confcache >$cache_file else { echo "$as_me:$LINENO: not updating unwritable cache $cache_file" >&5 echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache ############################################################################### # Checks for libraries... ############################################################################### # PROGRAMMING NOTE: we require libtool (or, optionally, dlltool (a less power- # ful (flexible) libtool-like tool for Windows platforms) in order to support # OPTION_DYNAMIC_LOAD. This is a relatively safe requirement since we provide # a version of libtool with Hercules (and build it as part of the preliminary # autoconf processing; see the 'Programs' section above). However, we need to # keep the below check for 'dlopen' anyway since we prefer that libtool use it # instead of its own equivalent (lt_dlopen) if it's available. { echo "$as_me:$LINENO: checking for _pipe in -lmsvcrt" >&5 echo $ECHO_N "checking for _pipe in -lmsvcrt... $ECHO_C" >&6; } if test "${ac_cv_lib_msvcrt__pipe__________+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lmsvcrt $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 GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char _pipe (); int main () { return _pipe (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_msvcrt__pipe__________=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_msvcrt__pipe__________=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_msvcrt__pipe__________" >&5 echo "${ECHO_T}$ac_cv_lib_msvcrt__pipe__________" >&6; } if test $ac_cv_lib_msvcrt__pipe__________ = yes; then cat >>confdefs.h <<_ACEOF #define HAVE_LIBMSVCRT 1 _ACEOF LIBS="-lmsvcrt $LIBS" fi { echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5 echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6; } if test "${ac_cv_lib_dl_dlopen_________+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $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 GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_dl_dlopen_________=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_dl_dlopen_________=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen_________" >&5 echo "${ECHO_T}$ac_cv_lib_dl_dlopen_________" >&6; } if test $ac_cv_lib_dl_dlopen_________ = yes; then cat >>confdefs.h <<_ACEOF #define HAVE_LIBDL 1 _ACEOF LIBS="-ldl $LIBS" fi { echo "$as_me:$LINENO: checking for sqrt in -lm" >&5 echo $ECHO_N "checking for sqrt in -lm... $ECHO_C" >&6; } if test "${ac_cv_lib_m_sqrt___________+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lm $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 GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char sqrt (); int main () { return sqrt (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_m_sqrt___________=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_m_sqrt___________=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_m_sqrt___________" >&5 echo "${ECHO_T}$ac_cv_lib_m_sqrt___________" >&6; } if test $ac_cv_lib_m_sqrt___________ = yes; then cat >>confdefs.h <<_ACEOF #define HAVE_LIBM 1 _ACEOF LIBS="-lm $LIBS" fi { 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 $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 GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char connect (); int main () { return connect (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; 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 core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ 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 cat >>confdefs.h <<_ACEOF #define HAVE_LIBSOCKET 1 _ACEOF LIBS="-lsocket $LIBS" fi { 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 GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char gethostbyname (); int main () { return gethostbyname (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; 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 core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ 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 cat >>confdefs.h <<_ACEOF #define HAVE_LIBNSL 1 _ACEOF LIBS="-lnsl $LIBS" fi { echo "$as_me:$LINENO: checking for inet_aton in -lresolv" >&5 echo $ECHO_N "checking for inet_aton in -lresolv... $ECHO_C" >&6; } if test "${ac_cv_lib_resolv_inet_aton______+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lresolv $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 GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char inet_aton (); int main () { return inet_aton (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_resolv_inet_aton______=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_resolv_inet_aton______=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_resolv_inet_aton______" >&5 echo "${ECHO_T}$ac_cv_lib_resolv_inet_aton______" >&6; } if test $ac_cv_lib_resolv_inet_aton______ = yes; then cat >>confdefs.h <<_ACEOF #define HAVE_LIBRESOLV 1 _ACEOF LIBS="-lresolv $LIBS" fi { echo "$as_me:$LINENO: checking for uncompress in -lz" >&5 echo $ECHO_N "checking for uncompress in -lz... $ECHO_C" >&6; } if test "${ac_cv_lib_z_uncompress_____+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lz $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 GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char uncompress (); int main () { return uncompress (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_z_uncompress_____=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_z_uncompress_____=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_z_uncompress_____" >&5 echo "${ECHO_T}$ac_cv_lib_z_uncompress_____" >&6; } if test $ac_cv_lib_z_uncompress_____ = yes; then cat >>confdefs.h <<_ACEOF #define HAVE_LIBZ 1 _ACEOF LIBS="-lz $LIBS" fi { echo "$as_me:$LINENO: checking for BZ2_bzBuffToBuffDecompress in -lbz2" >&5 echo $ECHO_N "checking for BZ2_bzBuffToBuffDecompress in -lbz2... $ECHO_C" >&6; } if test "${ac_cv_lib_bz2_BZ2_bzBuffToBuffDecompress+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lbz2 $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 GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char BZ2_bzBuffToBuffDecompress (); int main () { return BZ2_bzBuffToBuffDecompress (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_bz2_BZ2_bzBuffToBuffDecompress=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_bz2_BZ2_bzBuffToBuffDecompress=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_bz2_BZ2_bzBuffToBuffDecompress" >&5 echo "${ECHO_T}$ac_cv_lib_bz2_BZ2_bzBuffToBuffDecompress" >&6; } if test $ac_cv_lib_bz2_BZ2_bzBuffToBuffDecompress = yes; then hc_cv_have_libbz2=yes else hc_cv_have_libbz2=no fi { echo "$as_me:$LINENO: checking for iconv in -liconv" >&5 echo $ECHO_N "checking for iconv in -liconv... $ECHO_C" >&6; } if test "${ac_cv_lib_iconv_iconv__________+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-liconv $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 GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char iconv (); int main () { return iconv (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_iconv_iconv__________=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_iconv_iconv__________=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_iconv_iconv__________" >&5 echo "${ECHO_T}$ac_cv_lib_iconv_iconv__________" >&6; } if test $ac_cv_lib_iconv_iconv__________ = yes; then cat >>confdefs.h <<_ACEOF #define HAVE_LIBICONV 1 _ACEOF LIBS="-liconv $LIBS" fi # jbs 10/15/2003 Solaris requires -lrt for sched_yield() and fdatasync() { echo "$as_me:$LINENO: checking for sched_yield in -lrt" >&5 echo $ECHO_N "checking for sched_yield in -lrt... $ECHO_C" >&6; } if test "${ac_cv_lib_rt_sched_yield____+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lrt $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 GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char sched_yield (); int main () { return sched_yield (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_rt_sched_yield____=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_rt_sched_yield____=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_rt_sched_yield____" >&5 echo "${ECHO_T}$ac_cv_lib_rt_sched_yield____" >&6; } if test $ac_cv_lib_rt_sched_yield____ = yes; then cat >>confdefs.h <<_ACEOF #define HAVE_LIBRT 1 _ACEOF LIBS="-lrt $LIBS" fi # rbowler 2008/03/10 rev 1.196 Solaris 2.9 requires -lpthread { echo "$as_me:$LINENO: checking for pthread_create in -lpthread" >&5 echo $ECHO_N "checking for pthread_create in -lpthread... $ECHO_C" >&6; } if test "${ac_cv_lib_pthread_pthread_create_+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lpthread $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 GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char pthread_create (); int main () { return pthread_create (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_pthread_pthread_create_=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_pthread_pthread_create_=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_pthread_pthread_create_" >&5 echo "${ECHO_T}$ac_cv_lib_pthread_pthread_create_" >&6; } if test $ac_cv_lib_pthread_pthread_create_ = yes; then cat >>confdefs.h <<_ACEOF #define HAVE_LIBPTHREAD 1 _ACEOF LIBS="-lpthread $LIBS" fi cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5 echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( *) $as_unset $ac_var ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes (double-quote # substitution turns \\\\ into \\, and sed turns \\ into \). sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then test "x$cache_file" != "x/dev/null" && { echo "$as_me:$LINENO: updating cache $cache_file" >&5 echo "$as_me: updating cache $cache_file" >&6;} cat confcache >$cache_file else { echo "$as_me:$LINENO: not updating unwritable cache $cache_file" >&5 echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache ############################################################################### # Checks for library functions... ############################################################################### # PROGRAMMING NOTE: AC_CHECK_LIB should be called first for the below # library function checks to ensure the library where the function is # defined gets added to the LIBS library search variable... ############################################################################### for ac_func in iconv 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 { as_var=$as_ac_var; eval "test \"\${$as_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 GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $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 #endif int main () { return $ac_func (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; 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 core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi ac_res=`eval echo '${'$as_ac_var'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 for ac_func in memrchr 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 { as_var=$as_ac_var; eval "test \"\${$as_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 GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $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 #endif int main () { return $ac_func (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; 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 core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi ac_res=`eval echo '${'$as_ac_var'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 for ac_func in getopt_long 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 { as_var=$as_ac_var; eval "test \"\${$as_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 GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $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 #endif int main () { return $ac_func (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; 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 core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi ac_res=`eval echo '${'$as_ac_var'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 for ac_func in sqrtl ldexpl fabsl fmodl frexpl 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 { as_var=$as_ac_var; eval "test \"\${$as_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 GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $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 #endif int main () { return $ac_func (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; 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 core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi ac_res=`eval echo '${'$as_ac_var'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 for ac_func in ldexpf frexpf fabsf rint 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 { as_var=$as_ac_var; eval "test \"\${$as_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 GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $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 #endif int main () { return $ac_func (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; 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 core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi ac_res=`eval echo '${'$as_ac_var'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 for ac_func in strlcpy strlcat 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 { as_var=$as_ac_var; eval "test \"\${$as_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 GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $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 #endif int main () { return $ac_func (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; 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 core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi ac_res=`eval echo '${'$as_ac_var'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 for ac_func in strerror_r 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 { as_var=$as_ac_var; eval "test \"\${$as_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 GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $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 #endif int main () { return $ac_func (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; 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 core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi ac_res=`eval echo '${'$as_ac_var'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 for ac_func in strsignal 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 { as_var=$as_ac_var; eval "test \"\${$as_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 GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $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 #endif int main () { return $ac_func (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; 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 core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi ac_res=`eval echo '${'$as_ac_var'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&6; } if test `eval echo '${'$as_ac_var'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF hc_cv_have_strsignal=yes else hc_cv_have_strsignal=no fi done for ac_func in sys_siglist 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 { as_var=$as_ac_var; eval "test \"\${$as_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 GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $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 #endif int main () { return $ac_func (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; 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 core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi ac_res=`eval echo '${'$as_ac_var'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 for ac_func in InitializeCriticalSectionAndSpinCount 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 { as_var=$as_ac_var; eval "test \"\${$as_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 GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $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 #endif int main () { return $ac_func (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; 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 core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi ac_res=`eval echo '${'$as_ac_var'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 for ac_func in sleep usleep nanosleep 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 { as_var=$as_ac_var; eval "test \"\${$as_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 GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $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 #endif int main () { return $ac_func (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; 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 core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi ac_res=`eval echo '${'$as_ac_var'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 for ac_func in sched_yield 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 { as_var=$as_ac_var; eval "test \"\${$as_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 GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $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 #endif int main () { return $ac_func (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; 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 core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi ac_res=`eval echo '${'$as_ac_var'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 for ac_func in strtok_r 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 { as_var=$as_ac_var; eval "test \"\${$as_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 GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $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 #endif int main () { return $ac_func (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; 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 core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi ac_res=`eval echo '${'$as_ac_var'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 for ac_func in pipe 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 { as_var=$as_ac_var; eval "test \"\${$as_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 GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $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 #endif int main () { return $ac_func (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; 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 core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi ac_res=`eval echo '${'$as_ac_var'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 for ac_func in gettimeofday 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 { as_var=$as_ac_var; eval "test \"\${$as_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 GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $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 #endif int main () { return $ac_func (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; 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 core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi ac_res=`eval echo '${'$as_ac_var'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 for ac_func in getpgrp 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 { as_var=$as_ac_var; eval "test \"\${$as_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 GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $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 #endif int main () { return $ac_func (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; 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 core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi ac_res=`eval echo '${'$as_ac_var'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 for ac_func in scandir alphasort 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 { as_var=$as_ac_var; eval "test \"\${$as_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 GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $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 #endif int main () { return $ac_func (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; 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 core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi ac_res=`eval echo '${'$as_ac_var'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 for ac_func in getlogin getlogin_r 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 { as_var=$as_ac_var; eval "test \"\${$as_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 GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $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 #endif int main () { return $ac_func (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; 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 core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi ac_res=`eval echo '${'$as_ac_var'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 for ac_func in realpath 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 { as_var=$as_ac_var; eval "test \"\${$as_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 GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $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 #endif int main () { return $ac_func (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; 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 core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi ac_res=`eval echo '${'$as_ac_var'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 for ac_func in fdatasync fsync ftruncate 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 { as_var=$as_ac_var; eval "test \"\${$as_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 GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $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 #endif int main () { return $ac_func (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; 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 core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi ac_res=`eval echo '${'$as_ac_var'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 for ac_func in inet_aton 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 { as_var=$as_ac_var; eval "test \"\${$as_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 GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $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 #endif int main () { return $ac_func (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; 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 core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi ac_res=`eval echo '${'$as_ac_var'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 for ac_func in fork socketpair 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 { as_var=$as_ac_var; eval "test \"\${$as_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 GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $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 #endif int main () { return $ac_func (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; 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 core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi ac_res=`eval echo '${'$as_ac_var'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 for ac_func in sysconf 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 { as_var=$as_ac_var; eval "test \"\${$as_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 GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $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 #endif int main () { return $ac_func (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; 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 core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi ac_res=`eval echo '${'$as_ac_var'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&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 for ac_func in vsscanf 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 { as_var=$as_ac_var; eval "test \"\${$as_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 GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $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 #endif int main () { return $ac_func (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; 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 core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi ac_res=`eval echo '${'$as_ac_var'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&6; } if test `eval echo '${'$as_ac_var'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF hc_cv_have_vsscanf=yes else hc_cv_have_vsscanf=no fi done for ac_func in setresuid getresuid 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 { as_var=$as_ac_var; eval "test \"\${$as_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 GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $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 #endif int main () { return $ac_func (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; 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 core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi ac_res=`eval echo '${'$as_ac_var'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&6; } if test `eval echo '${'$as_ac_var'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF hc_cv_have_getset_uid=yes else hc_cv_have_getset_uid=no; break fi done if test "$hc_cv_have_getset_uid" != "yes"; then for ac_func in setreuid geteuid getuid 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 { as_var=$as_ac_var; eval "test \"\${$as_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 GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $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 #endif int main () { return $ac_func (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; 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 core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi ac_res=`eval echo '${'$as_ac_var'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&6; } if test `eval echo '${'$as_ac_var'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF hc_cv_have_getset_uid=yes else hc_cv_have_getset_uid=no; break fi done fi # FIXME: Disabled because some builtin ffs seem to be causing a problem. # (gcc 3.4 barfs on certain 'march=' settings?) #AC_CHECK_FUNCS( ffs ) # For OS X 10.6 autoconf defines HAVE_FDATASYNC even though there is # no function prototype declared for fdatasync() and unistd.h contains # define _POSIX_SYNCHRONIZED_IO (-1) which indicates that fdatasync is # not supported. So to decide whether fdatasync really can be used, we # create a new symbol HAVE_FDATASYNC_SUPPORTED which is defined only if # HAVE_FDATASYNC is defined and _POSIX_SYNCHRONIZED_IO is not negative. { echo "$as_me:$LINENO: checking whether fdatasync is supported" >&5 echo $ECHO_N "checking whether fdatasync is supported... $ECHO_C" >&6; } if test "${ac_cv_func_fdatasync_supported+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 () { #if !defined(HAVE_FDATASYNC) #error fdatasync is not defined on this platform #endif #if defined(_POSIX_SYNCHRONIZED_IO) && (_POSIX_SYNCHRONIZED_IO+0 < 0) #error fdatasync is not supported on this platform #endif ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_func_fdatasync_supported=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func_fdatasync_supported=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_func_fdatasync_supported" >&5 echo "${ECHO_T}$ac_cv_func_fdatasync_supported" >&6; } if test "x${ac_cv_func_fdatasync_supported}" = "xyes"; then cat >>confdefs.h <<\_ACEOF #define HAVE_FDATASYNC_SUPPORTED 1 _ACEOF fi cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5 echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( *) $as_unset $ac_var ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes (double-quote # substitution turns \\\\ into \\, and sed turns \\ into \). sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then test "x$cache_file" != "x/dev/null" && { echo "$as_me:$LINENO: updating cache $cache_file" >&5 echo "$as_me: updating cache $cache_file" >&6;} cat confcache >$cache_file else { echo "$as_me:$LINENO: not updating unwritable cache $cache_file" >&5 echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache ############################################################################### # Checks for structures and structure members... ############################################################################### { echo "$as_me:$LINENO: checking for struct sockaddr_in.sin_len" >&5 echo $ECHO_N "checking for struct sockaddr_in.sin_len... $ECHO_C" >&6; } if test "${ac_cv_member_struct_sockaddr_in_sin_len+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 #if HAVE_SYS_SOCKET_H #include #endif #if HAVE_NETINET_IN_H #include #endif int main () { static struct sockaddr_in ac_aggr; if (ac_aggr.sin_len) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_member_struct_sockaddr_in_sin_len=yes 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 #if HAVE_SYS_SOCKET_H #include #endif #if HAVE_NETINET_IN_H #include #endif int main () { static struct sockaddr_in ac_aggr; if (sizeof ac_aggr.sin_len) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_member_struct_sockaddr_in_sin_len=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_member_struct_sockaddr_in_sin_len=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_member_struct_sockaddr_in_sin_len" >&5 echo "${ECHO_T}$ac_cv_member_struct_sockaddr_in_sin_len" >&6; } if test $ac_cv_member_struct_sockaddr_in_sin_len = yes; then cat >>confdefs.h <<_ACEOF #define HAVE_STRUCT_SOCKADDR_IN_SIN_LEN 1 _ACEOF hc_cv_have_sockaddr_in_sin_len=yes else hc_cv_have_sockaddr_in_sin_len=no fi { echo "$as_me:$LINENO: checking for struct in_addr.s_addr" >&5 echo $ECHO_N "checking for struct in_addr.s_addr... $ECHO_C" >&6; } if test "${ac_cv_member_struct_in_addr_s_addr+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 #if HAVE_SYS_SOCKET_H #include #endif #if HAVE_NETINET_IN_H #include #endif int main () { static struct in_addr ac_aggr; if (ac_aggr.s_addr) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_member_struct_in_addr_s_addr=yes 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 #if HAVE_SYS_SOCKET_H #include #endif #if HAVE_NETINET_IN_H #include #endif int main () { static struct in_addr ac_aggr; if (sizeof ac_aggr.s_addr) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_member_struct_in_addr_s_addr=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_member_struct_in_addr_s_addr=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_member_struct_in_addr_s_addr" >&5 echo "${ECHO_T}$ac_cv_member_struct_in_addr_s_addr" >&6; } if test $ac_cv_member_struct_in_addr_s_addr = yes; then cat >>confdefs.h <<_ACEOF #define HAVE_STRUCT_IN_ADDR_S_ADDR 1 _ACEOF hc_cv_have_in_addr_s_addr=yes else hc_cv_have_in_addr_s_addr=no fi { echo "$as_me:$LINENO: checking for struct sigaction.sa_sigaction" >&5 echo $ECHO_N "checking for struct sigaction.sa_sigaction... $ECHO_C" >&6; } if test "${ac_cv_member_struct_sigaction_sa_sigaction+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 () { static struct sigaction ac_aggr; if (ac_aggr.sa_sigaction) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_member_struct_sigaction_sa_sigaction=yes 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 struct sigaction ac_aggr; if (sizeof ac_aggr.sa_sigaction) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_member_struct_sigaction_sa_sigaction=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_member_struct_sigaction_sa_sigaction=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_member_struct_sigaction_sa_sigaction" >&5 echo "${ECHO_T}$ac_cv_member_struct_sigaction_sa_sigaction" >&6; } if test $ac_cv_member_struct_sigaction_sa_sigaction = yes; then cat >>confdefs.h <<_ACEOF #define HAVE_STRUCT_SIGACTION_SA_SIGACTION 1 _ACEOF hc_cv_have_sa_sigaction=yes else hc_cv_have_sa_sigaction=no fi { echo "$as_me:$LINENO: checking for struct timespec.tv_nsec" >&5 echo $ECHO_N "checking for struct timespec.tv_nsec... $ECHO_C" >&6; } if test "${ac_cv_member_struct_timespec_tv_nsec+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 () { static struct timespec ac_aggr; if (ac_aggr.tv_nsec) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_member_struct_timespec_tv_nsec=yes 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 struct timespec ac_aggr; if (sizeof ac_aggr.tv_nsec) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_member_struct_timespec_tv_nsec=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_member_struct_timespec_tv_nsec=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_member_struct_timespec_tv_nsec" >&5 echo "${ECHO_T}$ac_cv_member_struct_timespec_tv_nsec" >&6; } if test $ac_cv_member_struct_timespec_tv_nsec = yes; then cat >>confdefs.h <<_ACEOF #define HAVE_STRUCT_TIMESPEC_TV_NSEC 1 _ACEOF hc_cv_timespec_in_sys_types_h=yes hc_cv_timespec_in_time_h=no else { echo "$as_me:$LINENO: checking for struct timespec.tv_nsec" >&5 echo $ECHO_N "checking for struct timespec.tv_nsec... $ECHO_C" >&6; } if test "${ac_cv_member_struct_timespec_tv_nsec+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 () { static struct timespec ac_aggr; if (ac_aggr.tv_nsec) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_member_struct_timespec_tv_nsec=yes 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 struct timespec ac_aggr; if (sizeof ac_aggr.tv_nsec) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_member_struct_timespec_tv_nsec=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_member_struct_timespec_tv_nsec=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_member_struct_timespec_tv_nsec" >&5 echo "${ECHO_T}$ac_cv_member_struct_timespec_tv_nsec" >&6; } if test $ac_cv_member_struct_timespec_tv_nsec = yes; then cat >>confdefs.h <<_ACEOF #define HAVE_STRUCT_TIMESPEC_TV_NSEC 1 _ACEOF hc_cv_timespec_in_sys_types_h=no hc_cv_timespec_in_time_h=yes else hc_cv_timespec_in_sys_types_h=no hc_cv_timespec_in_time_h=no fi fi cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5 echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( *) $as_unset $ac_var ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes (double-quote # substitution turns \\\\ into \\, and sed turns \\ into \). sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then test "x$cache_file" != "x/dev/null" && { echo "$as_me:$LINENO: updating cache $cache_file" >&5 echo "$as_me: updating cache $cache_file" >&6;} cat confcache >$cache_file else { echo "$as_me:$LINENO: not updating unwritable cache $cache_file" >&5 echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache ############################################################################### # Checks for compiler characteristics... ############################################################################### { echo "$as_me:$LINENO: checking whether byte ordering is bigendian" >&5 echo $ECHO_N "checking whether byte ordering is bigendian... $ECHO_C" >&6; } if test "${ac_cv_c_bigendian+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else # See if sys/param.h defines the BYTE_ORDER macro. 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 () { #if ! (defined BYTE_ORDER && defined BIG_ENDIAN && defined LITTLE_ENDIAN \ && BYTE_ORDER && BIG_ENDIAN && LITTLE_ENDIAN) bogus endian macros #endif ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then # It does; now see whether it defined to BIG_ENDIAN or not. 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 () { #if BYTE_ORDER != BIG_ENDIAN not big endian #endif ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_c_bigendian=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_c_bigendian=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # It does not; compile a test program. if test "$cross_compiling" = yes; then # try to guess the endianness by grepping values into an object file ac_cv_c_bigendian=unknown cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ short int ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 }; short int ascii_ii[] = { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 }; void _ascii () { char *s = (char *) ascii_mm; s = (char *) ascii_ii; } short int ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; short int ebcdic_mm[] = { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; void _ebcdic () { char *s = (char *) ebcdic_mm; s = (char *) ebcdic_ii; } int main () { _ascii (); _ebcdic (); ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then if grep BIGenDianSyS conftest.$ac_objext >/dev/null ; then ac_cv_c_bigendian=yes fi if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then if test "$ac_cv_c_bigendian" = unknown; then ac_cv_c_bigendian=no else # finding both strings is unlikely to happen, but who knows? ac_cv_c_bigendian=unknown fi fi else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext 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 () { /* Are we little or big endian? From Harbison&Steele. */ union { long int l; char c[sizeof (long int)]; } u; u.l = 1; return u.c[sizeof (long int) - 1] == 1; ; return 0; } _ACEOF rm -f conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_try") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_c_bigendian=no 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_bigendian=yes fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_c_bigendian" >&5 echo "${ECHO_T}$ac_cv_c_bigendian" >&6; } case $ac_cv_c_bigendian in yes) cat >>confdefs.h <<\_ACEOF #define WORDS_BIGENDIAN 1 _ACEOF ;; no) ;; *) { { echo "$as_me:$LINENO: error: unknown endianness presetting ac_cv_c_bigendian=no (or yes) will help" >&5 echo "$as_me: error: unknown endianness presetting ac_cv_c_bigendian=no (or yes) will help" >&2;} { (exit 1); exit 1; }; } ;; esac # PROGRAMMING NOTE: Okay, this is stupid. If there are any trailing spaces # following the type we're checking the size of, then they're converted to # underscores in the 'SIZEOF_XXXX' that gets #defined! For example, doing a # AC_CHECK_SIZEOF( int ) yields: #define SIZEOF_INT____ 4 !!!!!!!!!!!!! # So... the below AC_CHECK_SIZEOF macros must NOT have any spaces in them!! { echo "$as_me:$LINENO: checking for int" >&5 echo $ECHO_N "checking for int... $ECHO_C" >&6; } if test "${ac_cv_type_int+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 typedef int ac__type_new_; int main () { if ((ac__type_new_ *) 0) return 0; if (sizeof (ac__type_new_)) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_type_int=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_type_int=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_type_int" >&5 echo "${ECHO_T}$ac_cv_type_int" >&6; } # The cast to long int works around a bug in the HP C Compiler # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. # This bug is HP SR number 8606223364. { echo "$as_me:$LINENO: checking size of int" >&5 echo $ECHO_N "checking size of int... $ECHO_C" >&6; } if test "${ac_cv_sizeof_int+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else 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. */ $ac_includes_default typedef int ac__type_sizeof_; int main () { static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) >= 0)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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. */ $ac_includes_default typedef int ac__type_sizeof_; int main () { static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) <= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core 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. */ $ac_includes_default typedef int ac__type_sizeof_; int main () { static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) < 0)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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. */ $ac_includes_default typedef int ac__type_sizeof_; int main () { static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) >= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core 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 core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext # Binary search between lo and hi bounds. while test "x$ac_lo" != "x$ac_hi"; do 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. */ $ac_includes_default typedef int ac__type_sizeof_; int main () { static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) <= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core conftest.err conftest.$ac_objext conftest.$ac_ext done case $ac_lo in ?*) ac_cv_sizeof_int=$ac_lo;; '') if test "$ac_cv_type_int" = yes; then { { echo "$as_me:$LINENO: error: cannot compute sizeof (int) See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute sizeof (int) See \`config.log' for more details." >&2;} { (exit 77); exit 77; }; } else ac_cv_sizeof_int=0 fi ;; esac 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 typedef int ac__type_sizeof_; static long int longval () { return (long int) (sizeof (ac__type_sizeof_)); } static unsigned long int ulongval () { return (long int) (sizeof (ac__type_sizeof_)); } #include #include int main () { FILE *f = fopen ("conftest.val", "w"); if (! f) return 1; if (((long int) (sizeof (ac__type_sizeof_))) < 0) { long int i = longval (); if (i != ((long int) (sizeof (ac__type_sizeof_)))) return 1; fprintf (f, "%ld\n", i); } else { unsigned long int i = ulongval (); if (i != ((long int) (sizeof (ac__type_sizeof_)))) return 1; fprintf (f, "%lu\n", i); } return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF rm -f conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_try") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_sizeof_int=`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 ) if test "$ac_cv_type_int" = yes; then { { echo "$as_me:$LINENO: error: cannot compute sizeof (int) See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute sizeof (int) See \`config.log' for more details." >&2;} { (exit 77); exit 77; }; } else ac_cv_sizeof_int=0 fi fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi rm -f conftest.val fi { echo "$as_me:$LINENO: result: $ac_cv_sizeof_int" >&5 echo "${ECHO_T}$ac_cv_sizeof_int" >&6; } cat >>confdefs.h <<_ACEOF #define SIZEOF_INT $ac_cv_sizeof_int _ACEOF { echo "$as_me:$LINENO: checking for long" >&5 echo $ECHO_N "checking for long... $ECHO_C" >&6; } if test "${ac_cv_type_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. */ $ac_includes_default typedef long ac__type_new_; int main () { if ((ac__type_new_ *) 0) return 0; if (sizeof (ac__type_new_)) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_type_long=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_type_long=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_type_long" >&5 echo "${ECHO_T}$ac_cv_type_long" >&6; } # The cast to long int works around a bug in the HP C Compiler # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. # This bug is HP SR number 8606223364. { echo "$as_me:$LINENO: checking size of long" >&5 echo $ECHO_N "checking size of long... $ECHO_C" >&6; } if test "${ac_cv_sizeof_long+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else 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. */ $ac_includes_default typedef long ac__type_sizeof_; int main () { static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) >= 0)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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. */ $ac_includes_default typedef long ac__type_sizeof_; int main () { static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) <= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core 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. */ $ac_includes_default typedef long ac__type_sizeof_; int main () { static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) < 0)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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. */ $ac_includes_default typedef long ac__type_sizeof_; int main () { static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) >= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core 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 core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext # Binary search between lo and hi bounds. while test "x$ac_lo" != "x$ac_hi"; do 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. */ $ac_includes_default typedef long ac__type_sizeof_; int main () { static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) <= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core conftest.err conftest.$ac_objext conftest.$ac_ext done case $ac_lo in ?*) ac_cv_sizeof_long=$ac_lo;; '') if test "$ac_cv_type_long" = yes; then { { echo "$as_me:$LINENO: error: cannot compute sizeof (long) See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute sizeof (long) See \`config.log' for more details." >&2;} { (exit 77); exit 77; }; } else ac_cv_sizeof_long=0 fi ;; esac 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 typedef long ac__type_sizeof_; static long int longval () { return (long int) (sizeof (ac__type_sizeof_)); } static unsigned long int ulongval () { return (long int) (sizeof (ac__type_sizeof_)); } #include #include int main () { FILE *f = fopen ("conftest.val", "w"); if (! f) return 1; if (((long int) (sizeof (ac__type_sizeof_))) < 0) { long int i = longval (); if (i != ((long int) (sizeof (ac__type_sizeof_)))) return 1; fprintf (f, "%ld\n", i); } else { unsigned long int i = ulongval (); if (i != ((long int) (sizeof (ac__type_sizeof_)))) return 1; fprintf (f, "%lu\n", i); } return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF rm -f conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_try") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_sizeof_long=`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 ) if test "$ac_cv_type_long" = yes; then { { echo "$as_me:$LINENO: error: cannot compute sizeof (long) See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute sizeof (long) See \`config.log' for more details." >&2;} { (exit 77); exit 77; }; } else ac_cv_sizeof_long=0 fi fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi rm -f conftest.val fi { echo "$as_me:$LINENO: result: $ac_cv_sizeof_long" >&5 echo "${ECHO_T}$ac_cv_sizeof_long" >&6; } cat >>confdefs.h <<_ACEOF #define SIZEOF_LONG $ac_cv_sizeof_long _ACEOF { 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 typedef size_t ac__type_new_; int main () { if ((ac__type_new_ *) 0) return 0; if (sizeof (ac__type_new_)) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core 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; } # The cast to long int works around a bug in the HP C Compiler # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. # This bug is HP SR number 8606223364. { echo "$as_me:$LINENO: checking size of size_t" >&5 echo $ECHO_N "checking size of size_t... $ECHO_C" >&6; } if test "${ac_cv_sizeof_size_t+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else 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. */ $ac_includes_default typedef size_t ac__type_sizeof_; int main () { static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) >= 0)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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. */ $ac_includes_default typedef size_t ac__type_sizeof_; int main () { static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) <= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core 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. */ $ac_includes_default typedef size_t ac__type_sizeof_; int main () { static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) < 0)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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. */ $ac_includes_default typedef size_t ac__type_sizeof_; int main () { static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) >= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core 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 core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext # Binary search between lo and hi bounds. while test "x$ac_lo" != "x$ac_hi"; do 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. */ $ac_includes_default typedef size_t ac__type_sizeof_; int main () { static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) <= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core conftest.err conftest.$ac_objext conftest.$ac_ext done case $ac_lo in ?*) ac_cv_sizeof_size_t=$ac_lo;; '') if test "$ac_cv_type_size_t" = yes; then { { echo "$as_me:$LINENO: error: cannot compute sizeof (size_t) See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute sizeof (size_t) See \`config.log' for more details." >&2;} { (exit 77); exit 77; }; } else ac_cv_sizeof_size_t=0 fi ;; esac 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 typedef size_t ac__type_sizeof_; static long int longval () { return (long int) (sizeof (ac__type_sizeof_)); } static unsigned long int ulongval () { return (long int) (sizeof (ac__type_sizeof_)); } #include #include int main () { FILE *f = fopen ("conftest.val", "w"); if (! f) return 1; if (((long int) (sizeof (ac__type_sizeof_))) < 0) { long int i = longval (); if (i != ((long int) (sizeof (ac__type_sizeof_)))) return 1; fprintf (f, "%ld\n", i); } else { unsigned long int i = ulongval (); if (i != ((long int) (sizeof (ac__type_sizeof_)))) return 1; fprintf (f, "%lu\n", i); } return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF rm -f conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_try") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_sizeof_size_t=`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 ) if test "$ac_cv_type_size_t" = yes; then { { echo "$as_me:$LINENO: error: cannot compute sizeof (size_t) See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute sizeof (size_t) See \`config.log' for more details." >&2;} { (exit 77); exit 77; }; } else ac_cv_sizeof_size_t=0 fi fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi rm -f conftest.val fi { echo "$as_me:$LINENO: result: $ac_cv_sizeof_size_t" >&5 echo "${ECHO_T}$ac_cv_sizeof_size_t" >&6; } cat >>confdefs.h <<_ACEOF #define SIZEOF_SIZE_T $ac_cv_sizeof_size_t _ACEOF { echo "$as_me:$LINENO: checking for int *" >&5 echo $ECHO_N "checking for int *... $ECHO_C" >&6; } if test "${ac_cv_type_int_p+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 typedef int * ac__type_new_; int main () { if ((ac__type_new_ *) 0) return 0; if (sizeof (ac__type_new_)) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_type_int_p=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_type_int_p=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_type_int_p" >&5 echo "${ECHO_T}$ac_cv_type_int_p" >&6; } # The cast to long int works around a bug in the HP C Compiler # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. # This bug is HP SR number 8606223364. { echo "$as_me:$LINENO: checking size of int *" >&5 echo $ECHO_N "checking size of int *... $ECHO_C" >&6; } if test "${ac_cv_sizeof_int_p+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else 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. */ $ac_includes_default typedef int * ac__type_sizeof_; int main () { static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) >= 0)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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. */ $ac_includes_default typedef int * ac__type_sizeof_; int main () { static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) <= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core 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. */ $ac_includes_default typedef int * ac__type_sizeof_; int main () { static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) < 0)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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. */ $ac_includes_default typedef int * ac__type_sizeof_; int main () { static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) >= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core 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 core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext # Binary search between lo and hi bounds. while test "x$ac_lo" != "x$ac_hi"; do 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. */ $ac_includes_default typedef int * ac__type_sizeof_; int main () { static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) <= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core conftest.err conftest.$ac_objext conftest.$ac_ext done case $ac_lo in ?*) ac_cv_sizeof_int_p=$ac_lo;; '') if test "$ac_cv_type_int_p" = yes; then { { echo "$as_me:$LINENO: error: cannot compute sizeof (int *) See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute sizeof (int *) See \`config.log' for more details." >&2;} { (exit 77); exit 77; }; } else ac_cv_sizeof_int_p=0 fi ;; esac 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 typedef int * ac__type_sizeof_; static long int longval () { return (long int) (sizeof (ac__type_sizeof_)); } static unsigned long int ulongval () { return (long int) (sizeof (ac__type_sizeof_)); } #include #include int main () { FILE *f = fopen ("conftest.val", "w"); if (! f) return 1; if (((long int) (sizeof (ac__type_sizeof_))) < 0) { long int i = longval (); if (i != ((long int) (sizeof (ac__type_sizeof_)))) return 1; fprintf (f, "%ld\n", i); } else { unsigned long int i = ulongval (); if (i != ((long int) (sizeof (ac__type_sizeof_)))) return 1; fprintf (f, "%lu\n", i); } return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF rm -f conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_try") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_sizeof_int_p=`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 ) if test "$ac_cv_type_int_p" = yes; then { { echo "$as_me:$LINENO: error: cannot compute sizeof (int *) See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute sizeof (int *) See \`config.log' for more details." >&2;} { (exit 77); exit 77; }; } else ac_cv_sizeof_int_p=0 fi fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi rm -f conftest.val fi { echo "$as_me:$LINENO: result: $ac_cv_sizeof_int_p" >&5 echo "${ECHO_T}$ac_cv_sizeof_int_p" >&6; } cat >>confdefs.h <<_ACEOF #define SIZEOF_INT_P $ac_cv_sizeof_int_p _ACEOF { 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 typedef off_t ac__type_new_; int main () { if ((ac__type_new_ *) 0) return 0; if (sizeof (ac__type_new_)) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core 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; } # The cast to long int works around a bug in the HP C Compiler # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. # This bug is HP SR number 8606223364. { echo "$as_me:$LINENO: checking size of off_t" >&5 echo $ECHO_N "checking size of off_t... $ECHO_C" >&6; } if test "${ac_cv_sizeof_off_t+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else 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. */ $ac_includes_default typedef off_t ac__type_sizeof_; int main () { static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) >= 0)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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. */ $ac_includes_default typedef off_t ac__type_sizeof_; int main () { static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) <= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core 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. */ $ac_includes_default typedef off_t ac__type_sizeof_; int main () { static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) < 0)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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. */ $ac_includes_default typedef off_t ac__type_sizeof_; int main () { static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) >= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core 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 core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext # Binary search between lo and hi bounds. while test "x$ac_lo" != "x$ac_hi"; do 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. */ $ac_includes_default typedef off_t ac__type_sizeof_; int main () { static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) <= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core conftest.err conftest.$ac_objext conftest.$ac_ext done case $ac_lo in ?*) ac_cv_sizeof_off_t=$ac_lo;; '') if test "$ac_cv_type_off_t" = yes; then { { echo "$as_me:$LINENO: error: cannot compute sizeof (off_t) See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute sizeof (off_t) See \`config.log' for more details." >&2;} { (exit 77); exit 77; }; } else ac_cv_sizeof_off_t=0 fi ;; esac 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 typedef off_t ac__type_sizeof_; static long int longval () { return (long int) (sizeof (ac__type_sizeof_)); } static unsigned long int ulongval () { return (long int) (sizeof (ac__type_sizeof_)); } #include #include int main () { FILE *f = fopen ("conftest.val", "w"); if (! f) return 1; if (((long int) (sizeof (ac__type_sizeof_))) < 0) { long int i = longval (); if (i != ((long int) (sizeof (ac__type_sizeof_)))) return 1; fprintf (f, "%ld\n", i); } else { unsigned long int i = ulongval (); if (i != ((long int) (sizeof (ac__type_sizeof_)))) return 1; fprintf (f, "%lu\n", i); } return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF rm -f conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_try") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_sizeof_off_t=`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 ) if test "$ac_cv_type_off_t" = yes; then { { echo "$as_me:$LINENO: error: cannot compute sizeof (off_t) See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute sizeof (off_t) See \`config.log' for more details." >&2;} { (exit 77); exit 77; }; } else ac_cv_sizeof_off_t=0 fi fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi rm -f conftest.val fi { echo "$as_me:$LINENO: result: $ac_cv_sizeof_off_t" >&5 echo "${ECHO_T}$ac_cv_sizeof_off_t" >&6; } cat >>confdefs.h <<_ACEOF #define SIZEOF_OFF_T $ac_cv_sizeof_off_t _ACEOF #----------------------------------# # Structure alignment/size test # #----------------------------------# { echo "$as_me:$LINENO: begin check: whether byte structs are aligned/rounded by default... " >&5 echo "$as_me: begin check: whether byte structs are aligned/rounded by default... " >&6;} cat > conftest.h << __EOF #include struct bytestruct { unsigned char a; }; __EOF { echo "$as_me:$LINENO: checking for struct bytestruct" >&5 echo $ECHO_N "checking for struct bytestruct... $ECHO_C" >&6; } if test "${ac_cv_type_struct_bytestruct+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 "conftest.h" typedef struct bytestruct ac__type_new_; int main () { if ((ac__type_new_ *) 0) return 0; if (sizeof (ac__type_new_)) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_type_struct_bytestruct=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_type_struct_bytestruct=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_type_struct_bytestruct" >&5 echo "${ECHO_T}$ac_cv_type_struct_bytestruct" >&6; } # The cast to long int works around a bug in the HP C Compiler # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. # This bug is HP SR number 8606223364. { echo "$as_me:$LINENO: checking size of struct bytestruct" >&5 echo $ECHO_N "checking size of struct bytestruct... $ECHO_C" >&6; } if test "${ac_cv_sizeof_struct_bytestruct+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else 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 "conftest.h" typedef struct bytestruct ac__type_sizeof_; int main () { static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) >= 0)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 "conftest.h" typedef struct bytestruct ac__type_sizeof_; int main () { static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) <= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core 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 "conftest.h" typedef struct bytestruct ac__type_sizeof_; int main () { static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) < 0)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 "conftest.h" typedef struct bytestruct ac__type_sizeof_; int main () { static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) >= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core 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 core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext # Binary search between lo and hi bounds. while test "x$ac_lo" != "x$ac_hi"; do 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 "conftest.h" typedef struct bytestruct ac__type_sizeof_; int main () { static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) <= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core conftest.err conftest.$ac_objext conftest.$ac_ext done case $ac_lo in ?*) ac_cv_sizeof_struct_bytestruct=$ac_lo;; '') if test "$ac_cv_type_struct_bytestruct" = yes; then { { echo "$as_me:$LINENO: error: cannot compute sizeof (struct bytestruct) See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute sizeof (struct bytestruct) See \`config.log' for more details." >&2;} { (exit 77); exit 77; }; } else ac_cv_sizeof_struct_bytestruct=0 fi ;; 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 "conftest.h" typedef struct bytestruct ac__type_sizeof_; static long int longval () { return (long int) (sizeof (ac__type_sizeof_)); } static unsigned long int ulongval () { return (long int) (sizeof (ac__type_sizeof_)); } #include #include int main () { FILE *f = fopen ("conftest.val", "w"); if (! f) return 1; if (((long int) (sizeof (ac__type_sizeof_))) < 0) { long int i = longval (); if (i != ((long int) (sizeof (ac__type_sizeof_)))) return 1; fprintf (f, "%ld\n", i); } else { unsigned long int i = ulongval (); if (i != ((long int) (sizeof (ac__type_sizeof_)))) return 1; fprintf (f, "%lu\n", i); } return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF rm -f conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_try") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_sizeof_struct_bytestruct=`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 ) if test "$ac_cv_type_struct_bytestruct" = yes; then { { echo "$as_me:$LINENO: error: cannot compute sizeof (struct bytestruct) See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute sizeof (struct bytestruct) See \`config.log' for more details." >&2;} { (exit 77); exit 77; }; } else ac_cv_sizeof_struct_bytestruct=0 fi fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi rm -f conftest.val fi { echo "$as_me:$LINENO: result: $ac_cv_sizeof_struct_bytestruct" >&5 echo "${ECHO_T}$ac_cv_sizeof_struct_bytestruct" >&6; } cat >>confdefs.h <<_ACEOF #define SIZEOF_STRUCT_BYTESTRUCT $ac_cv_sizeof_struct_bytestruct _ACEOF if test "$ac_cv_sizeof_struct_bytestruct" = "1"; then hc_cv_byte_structs_aligned_and_rounded_by_default=no hc_cv_byte_structs_always_aligned_and_rounded=no else # The sizeof our test structure is not '1'. # The compiler is rounding the size of the # structure upward to some predefined value. hc_cv_byte_structs_aligned_and_rounded_by_default=yes # If there's no way to request the compiler # to not do that, then we can't build Herc. case "$host_cpu-$GCC" in arm*-yes|xscale*-yes|sh*-yes|pxa*-yes) hc_cv_byte_structs_always_aligned_and_rounded=no ;; *) hc_cv_byte_structs_always_aligned_and_rounded=yes ;; esac fi { echo "$as_me:$LINENO: results: byte structs are aligned/rounded by default... ${hc_cv_byte_structs_aligned_and_rounded_by_default} " >&5 echo "$as_me: results: byte structs are aligned/rounded by default... ${hc_cv_byte_structs_aligned_and_rounded_by_default} " >&6;} if test "$hc_cv_byte_structs_always_aligned_and_rounded" = "yes"; then { echo "$as_me:$LINENO: result: ERROR: Size of structures are aligned/rounded and we don't know how to tell the compiler otherwise " >&5 echo "${ECHO_T}ERROR: Size of structures are aligned/rounded and we don't know how to tell the compiler otherwise " >&6; } hc_error=yes fi #------------------------------# # Check if this is GCC 2.96 # #------------------------------# { echo "$as_me:$LINENO: checking if this is the broken 2.96 version of GCC" >&5 echo $ECHO_N "checking if this is the broken 2.96 version of GCC... $ECHO_C" >&6; } if test "${hc_cv_is_gcc_2_96+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test "$GCC" = "yes"; then cat >conftest.$ac_ext <<_ACEOF #if __GNUC__ == 2 && __GNUC_MINOR__ == 96 yes; #else int no; #endif _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then hc_cv_is_gcc_2_96=no else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 hc_cv_is_gcc_2_96=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext else hc_cv_is_gcc_2_96=no fi fi { echo "$as_me:$LINENO: result: $hc_cv_is_gcc_2_96" >&5 echo "${ECHO_T}$hc_cv_is_gcc_2_96" >&6; } #----------------------------------------------# # Check C99 if flexible arrays are supported # #----------------------------------------------# # The logic to test whether C99 flexible # # arrays are supported is defined in the # # 'HC_C99_FLEXIBLE_ARRAYS' macro in the # # 'hercules.m4' file in the 'autoconf' sub- # # directory, and issues the AC_DEFINE for # # 'C99_FLEXIBLE_ARRAYS' if it's supported # # and also sets '$hc_cv_c99_flexible_array'. # #----------------------------------------------# { echo "$as_me:$LINENO: checking C99 struct flexible arrays support" >&5 echo $ECHO_N "checking C99 struct flexible arrays support... $ECHO_C" >&6; } if test "${hc_cv_c99_flexible_array+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else # Initialize to unknown hc_cv_c99_flexible_array=no cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include typedef struct { int foo; char bar[]; } FOOBAR; int main () { int main(int argc, char *argv[]) { FOOBAR* p = calloc( 1, sizeof(FOOBAR) + 16 ); return 0; } ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then hc_cv_c99_flexible_array=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 hc_cv_c99_flexible_array=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $hc_cv_c99_flexible_array" >&5 echo "${ECHO_T}$hc_cv_c99_flexible_array" >&6; } if test "$hc_cv_c99_flexible_array" = "yes"; then cat >>confdefs.h <<\_ACEOF #define C99_FLEXIBLE_ARRAYS 1 _ACEOF fi #--------------------------------------------------------# # Check if GCC supports '__attribute__ ((regparm(n)))' # #--------------------------------------------------------# # Note: even though at the moment GCC only supports regparm # on i386 or greater machines, that could change at any time # in the future so we don't bother checking for it. if test "$GCC" = "yes"; then { echo "$as_me:$LINENO: checking whether '__attribute__ ((regparm(n)))' is supported" >&5 echo $ECHO_N "checking whether '__attribute__ ((regparm(n)))' is supported... $ECHO_C" >&6; } if test "${hc_cv_regparm_attr_supported+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else hc_temp="$CFLAGS" CFLAGS="-Wall -Werror" cat >conftest.$ac_ext <<_ACEOF void conftest() __attribute__ ((regparm(1))); _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then hc_cv_regparm_attr_supported=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 hc_cv_regparm_attr_supported=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CFLAGS="$hc_temp" fi { echo "$as_me:$LINENO: result: $hc_cv_regparm_attr_supported" >&5 echo "${ECHO_T}$hc_cv_regparm_attr_supported" >&6; } else hc_cv_regparm_attr_supported=no fi #---------------------------------------------------# # Test for GCC '__attribute__ ((regparm(3)))' bug # #---------------------------------------------------# if test "$GCC" = "yes" && test "$hc_cv_regparm_attr_supported" = "yes"; then { echo "$as_me:$LINENO: checking whether '__attribute__ ((regparm(3)))' is broken" >&5 echo $ECHO_N "checking whether '__attribute__ ((regparm(3)))' is broken... $ECHO_C" >&6; } if test "${hc_cv_regparm_attr_broke+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else hc_temp="$CFLAGS" CFLAGS="-O3 -fomit-frame-pointer" if test "$cross_compiling" = yes; then hc_cv_regparm_attr_broke=yes else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Fish: Test for reparms bug caused by alloca bug# 8750 Ref: */ struct REGS { int a, b, c, d; char e[50000]; }; typedef struct REGS REGS; #define ATTR_REGPARM __attribute__ (( regparm(3) )) int func1 ( int a, int b, int c, REGS *regs ) ATTR_REGPARM; int func2 ( int a, int b, int c, REGS *regs ) ATTR_REGPARM; REGS global_regs; int main() { return func1( 1, 2, 3, &global_regs ); } int ATTR_REGPARM func1 ( int a, int b, int c, REGS *regs ) { REGS stack_regs; regs=regs; /* (quiet compiler warning) */ if ( func2( a, b, c, &stack_regs ) == 0 ) return 0; /* pass */ return 1; /* fail */ } int ATTR_REGPARM func2 ( int a, int b, int c, REGS *regs ) { regs=regs; /* (quiet compiler warning) */ if ( 1==a && 2==b && 3==c ) return 0; /* pass */ return 1; /* fail */ } _ACEOF rm -f conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_try") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then hc_cv_regparm_attr_broke=no 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 ) hc_cv_regparm_attr_broke=yes fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi CFLAGS="$hc_temp" fi { echo "$as_me:$LINENO: result: $hc_cv_regparm_attr_broke" >&5 echo "${ECHO_T}$hc_cv_regparm_attr_broke" >&6; } else hc_cv_regparm_attr_broke=no fi #------------------------------------------------------# # Test for GCC builtin alloca bug# 8750 # # # #------------------------------------------------------# if test "$GCC" = "yes"; then { echo "$as_me:$LINENO: checking whether '__builtin_alloca' is broken" >&5 echo $ECHO_N "checking whether '__builtin_alloca' is broken... $ECHO_C" >&6; } if test "${hc_cv_builtin_alloca_broke+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else hc_temp=$CFLAGS CFLAGS="-g -O2 -fomit-frame-pointer" if test "$cross_compiling" = yes; then hc_cv_builtin_alloca_broke=yes else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Fish: Test for gcc builtin alloca bug# 8750 Required(?!) (not sure) compiler options: -g -O2 -fomit-frame-pointer */ int foo () { char a[50000+16]; memset(a,0xCD,50000); a[50000]=0; return strlen(a); } int main() { return ( foo() != 50000 ); } _ACEOF rm -f conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_try") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then hc_cv_builtin_alloca_broke=no 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 ) hc_cv_builtin_alloca_broke=yes fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi CFLAGS=$hc_temp fi { echo "$as_me:$LINENO: result: $hc_cv_builtin_alloca_broke" >&5 echo "${ECHO_T}$hc_cv_builtin_alloca_broke" >&6; } else hc_cv_builtin_alloca_broke=no fi #------------------------------------------------------------# # Check for OS X gcc preprocessor macro argument count bug # #------------------------------------------------------------# if test "$GCC" = "yes"; then { echo "$as_me:$LINENO: checking whether preprocessor macro argument counting broken" >&5 echo $ECHO_N "checking whether preprocessor macro argument counting broken... $ECHO_C" >&6; } if test "${hc_cv_pp_macro_arg_counting_broke+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else hc_temp="$CFLAGS" CFLAGS="-Wall -Werror" cat >conftest.$ac_ext <<_ACEOF #include #define MACRO(_x,_args...) printf(_x, ## _args) int main( int argc, char **argv, char **arge ) { MACRO( "bare printf\n" ); return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then hc_cv_pp_macro_arg_counting_broke=no else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 hc_cv_pp_macro_arg_counting_broke=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CFLAGS="$hc_temp" fi { echo "$as_me:$LINENO: result: $hc_cv_pp_macro_arg_counting_broke" >&5 echo "${ECHO_T}$hc_cv_pp_macro_arg_counting_broke" >&6; } else hc_cv_pp_macro_arg_counting_broke=no fi #------------------------------------------------------------# # Check if traditional preprocessor is the K&R C type... # #------------------------------------------------------------# # # Apple's latest GCC documentation reveals: # # ... the -traditional-cpp option has changed. # In Apple GCC 3.1 and earlier Apple GCC compilers, # -traditional-cpp was used to toggle between the # standard GNU GCC preprocessor and Apple's own # preprocessor, "cpp-precomp". The GNU GCC compiler # interpreted -traditional-cpp differently on all # other platforms. Since cpp-precomp has been removed # for Apple's GCC 3.3 compiler, the standard GNU # meaning of -traditional-cpp has been restored. By # default, the GCC 3.3 preprocessor conforms to the # ISO C standard. Using the -tradtional-cpp option # means the C preprocessor should instead try to # emulate the old "K&R C". # #------------------------------------------------------------# if test "$GCC" = "yes"; then { echo "$as_me:$LINENO: checking whether '-traditional-cpp' is K&R C preprocessor" >&5 echo $ECHO_N "checking whether '-traditional-cpp' is K&R C preprocessor... $ECHO_C" >&6; } if test "${hc_cv_traditional_cpp_is_K_AND_R_C_type+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else hc_temp="$CFLAGS" CFLAGS="-Wall -Werror -traditional-cpp" # Note: The test program MUST start in column 1! Otherwise, the compilation # will fail when it's not supposed to. cat >conftest.$ac_ext <<_ACEOF /* If the following gets an error, then the "traditional" preprocessor is K&R C type. Otherwise if it compiles WITHOUT error the the "traditional" preprocessor is NOT the K&R C type. */ #if 1 #include // comment/etc... #endif int main( int, char**, char** ) { return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then hc_cv_traditional_cpp_is_K_AND_R_C_type=no else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 hc_cv_traditional_cpp_is_K_AND_R_C_type=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CFLAGS="$hc_temp" fi { echo "$as_me:$LINENO: result: $hc_cv_traditional_cpp_is_K_AND_R_C_type" >&5 echo "${ECHO_T}$hc_cv_traditional_cpp_is_K_AND_R_C_type" >&6; } else hc_cv_traditional_cpp_is_K_AND_R_C_type=no fi #-----------------------------------------------------------# # Check whether byte-swapping can be done using assembler # #-----------------------------------------------------------# { echo "$as_me:$LINENO: checking whether byte-swapping can be done using assembler " >&5 echo $ECHO_N "checking whether byte-swapping can be done using assembler ... $ECHO_C" >&6; } # (use our own byteswap assembler routines are i486+ only) # use system's byteswap routines if present... case "$host_cpu" in i486|i586|i686|i786|x86_64) hc_cv_asm_byteswap=yes ;; *) hc_cv_asm_byteswap=$hc_cv_have_byteswap_h ;; esac { echo "$as_me:$LINENO: result: $hc_cv_asm_byteswap " >&5 echo "${ECHO_T}$hc_cv_asm_byteswap " >&6; } #----------------------------------------------# # Check whether -pthread needed for pthreads # #----------------------------------------------# { echo "$as_me:$LINENO: checking whether ${CC-cc} accepts -pthread " >&5 echo $ECHO_N "checking whether ${CC-cc} accepts -pthread ... $ECHO_C" >&6; } echo 'void f(){}' >conftest.c if test -z "`${CC-cc} -pthread -c conftest.c 2>&1`"; then hc_cv_dash_pthread_needed=yes else hc_cv_dash_pthread_needed=no fi { echo "$as_me:$LINENO: result: $hc_cv_dash_pthread_needed " >&5 echo "${ECHO_T}$hc_cv_dash_pthread_needed " >&6; } #------------------------------------------------------------------ # The logic to test whether optreset is needed for getopt use is # defined in the 'HC_CHECK_NEED_GETOPT_OPTRESET' macro in the # 'hercules.m4' file in the autoconf directory, and issues the # AC_DEFINE for 'NEED_GETOPT_OPTRESET' if it's needed (and also # sets the '$hc_cv_need_getopt_optreset' variable appropriately). #------------------------------------------------------------------ { echo "$as_me:$LINENO: checking whether 'optreset' needed for 'getopt' use" >&5 echo $ECHO_N "checking whether 'optreset' needed for 'getopt' use... $ECHO_C" >&6; } if test "${hc_cv_need_getopt_optreset+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 () { extern int optreset; optreset=1; getopt(0,0,0); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then hc_cv_need_getopt_optreset=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 hc_cv_need_getopt_optreset=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $hc_cv_need_getopt_optreset" >&5 echo "${ECHO_T}$hc_cv_need_getopt_optreset" >&6; } if test "$hc_cv_need_getopt_optreset" = "yes"; then cat >>confdefs.h <<\_ACEOF #define NEED_GETOPT_OPTRESET 1 _ACEOF fi cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5 echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( *) $as_unset $ac_var ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes (double-quote # substitution turns \\\\ into \\, and sed turns \\ into \). sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then test "x$cache_file" != "x/dev/null" && { echo "$as_me:$LINENO: updating cache $cache_file" >&5 echo "$as_me: updating cache $cache_file" >&6;} cat confcache >$cache_file else { echo "$as_me:$LINENO: not updating unwritable cache $cache_file" >&5 echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache ############################################################################### # Checks for system services... ############################################################################### # Check whether --enable-largefile was given. if test "${enable_largefile+set}" = set; then enableval=$enable_largefile; fi if test "$enable_largefile" != no; then { echo "$as_me:$LINENO: checking for special C compiler options needed for large files" >&5 echo $ECHO_N "checking for special C compiler options needed for large files... $ECHO_C" >&6; } if test "${ac_cv_sys_largefile_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_sys_largefile_CC=no if test "$GCC" != yes; then ac_save_CC=$CC while :; do # IRIX 6.2 and later do not support large files by default, # so use the C compiler's -n32 option if that helps. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include /* Check that off_t can represent 2**63 - 1 correctly. We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ #define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f core conftest.err conftest.$ac_objext CC="$CC -n32" rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_sys_largefile_CC=' -n32'; break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f core conftest.err conftest.$ac_objext break done CC=$ac_save_CC rm -f conftest.$ac_ext fi fi { echo "$as_me:$LINENO: result: $ac_cv_sys_largefile_CC" >&5 echo "${ECHO_T}$ac_cv_sys_largefile_CC" >&6; } if test "$ac_cv_sys_largefile_CC" != no; then CC=$CC$ac_cv_sys_largefile_CC fi { echo "$as_me:$LINENO: checking for _FILE_OFFSET_BITS value needed for large files" >&5 echo $ECHO_N "checking for _FILE_OFFSET_BITS value needed for large files... $ECHO_C" >&6; } if test "${ac_cv_sys_file_offset_bits+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else 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 /* Check that off_t can represent 2**63 - 1 correctly. We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ #define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_sys_file_offset_bits=no; break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f core 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. */ #define _FILE_OFFSET_BITS 64 #include /* Check that off_t can represent 2**63 - 1 correctly. We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ #define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_sys_file_offset_bits=64; break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_sys_file_offset_bits=unknown break done fi { echo "$as_me:$LINENO: result: $ac_cv_sys_file_offset_bits" >&5 echo "${ECHO_T}$ac_cv_sys_file_offset_bits" >&6; } case $ac_cv_sys_file_offset_bits in #( no | unknown) ;; *) cat >>confdefs.h <<_ACEOF #define _FILE_OFFSET_BITS $ac_cv_sys_file_offset_bits _ACEOF ;; esac rm -f -r conftest* if test $ac_cv_sys_file_offset_bits = unknown; then { echo "$as_me:$LINENO: checking for _LARGE_FILES value needed for large files" >&5 echo $ECHO_N "checking for _LARGE_FILES value needed for large files... $ECHO_C" >&6; } if test "${ac_cv_sys_large_files+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else 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 /* Check that off_t can represent 2**63 - 1 correctly. We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ #define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_sys_large_files=no; break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f core 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. */ #define _LARGE_FILES 1 #include /* Check that off_t can represent 2**63 - 1 correctly. We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ #define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_sys_large_files=1; break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_sys_large_files=unknown break done fi { echo "$as_me:$LINENO: result: $ac_cv_sys_large_files" >&5 echo "${ECHO_T}$ac_cv_sys_large_files" >&6; } case $ac_cv_sys_large_files in #( no | unknown) ;; *) cat >>confdefs.h <<_ACEOF #define _LARGE_FILES $ac_cv_sys_large_files _ACEOF ;; esac rm -f -r conftest* fi fi { 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 typedef off_t ac__type_new_; int main () { if ((ac__type_new_ *) 0) return 0; if (sizeof (ac__type_new_)) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 core 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 int _ACEOF fi { echo "$as_me:$LINENO: checking for _LARGEFILE_SOURCE value needed for large files" >&5 echo $ECHO_N "checking for _LARGEFILE_SOURCE value needed for large files... $ECHO_C" >&6; } if test "${ac_cv_sys_largefile_source+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else 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 () { return fseeko (stdin, 0, 0) && (fseeko) (stdin, 0, 0); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_sys_largefile_source=no; break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext 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. */ #define _LARGEFILE_SOURCE 1 #include int main () { return fseeko (stdin, 0, 0) && (fseeko) (stdin, 0, 0); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_sys_largefile_source=1; break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext ac_cv_sys_largefile_source=unknown break done fi { echo "$as_me:$LINENO: result: $ac_cv_sys_largefile_source" >&5 echo "${ECHO_T}$ac_cv_sys_largefile_source" >&6; } case $ac_cv_sys_largefile_source in #( no | unknown) ;; *) cat >>confdefs.h <<_ACEOF #define _LARGEFILE_SOURCE $ac_cv_sys_largefile_source _ACEOF ;; esac rm -f -r conftest* # We used to try defining _XOPEN_SOURCE=500 too, to work around a bug # in glibc 2.1.3, but that breaks too many other things. # If you want fseeko and ftello with glibc, upgrade to a fixed glibc. if test $ac_cv_sys_largefile_source != unknown; then cat >>confdefs.h <<\_ACEOF #define HAVE_FSEEKO 1 _ACEOF fi cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5 echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( *) $as_unset $ac_var ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes (double-quote # substitution turns \\\\ into \\, and sed turns \\ into \). sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then test "x$cache_file" != "x/dev/null" && { echo "$as_me:$LINENO: updating cache $cache_file" >&5 echo "$as_me: updating cache $cache_file" >&6;} cat confcache >$cache_file else { echo "$as_me:$LINENO: not updating unwritable cache $cache_file" >&5 echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache ############################################################################### # AC_CONFIG_FILES( [file...] )... ############################################################################### cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5 echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( *) $as_unset $ac_var ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes (double-quote # substitution turns \\\\ into \\, and sed turns \\ into \). sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then test "x$cache_file" != "x/dev/null" && { echo "$as_me:$LINENO: updating cache $cache_file" >&5 echo "$as_me: updating cache $cache_file" >&6;} cat confcache >$cache_file else { echo "$as_me:$LINENO: not updating unwritable cache $cache_file" >&5 echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache ############################################################################### # Set flags according to user-specified --enable-xxxxx build options ############################################################################### # PROGRAMMING NOTE: some of these values default to previously determined # values (e.g. cckd-bzip2 for example defaults to whether libbz2 exists), # so this section MUST [unfortunately] come AFTER the above sections. This # does have the unfortunate side effect of not detecting invalid options # right away like one would normally expect/want. The only way around that # would be to perform two checks (one at the beginning and then one again # later on), but that approach was rejected since it would tend to make our # configure.ac script less clean (simple and straightforward). # Check whether --enable-dynamic-load was given. if test "${enable_dynamic_load+set}" = set; then enableval=$enable_dynamic_load; case "${enableval}" in yes) hc_cv_opt_dynamic_load=yes ;; no) hc_cv_opt_dynamic_load=no ;; *) { echo "$as_me:$LINENO: result: ERROR: invalid 'dynamic-load' option " >&5 echo "${ECHO_T}ERROR: invalid 'dynamic-load' option " >&6; } hc_error=yes ;; esac else hc_cv_opt_dynamic_load=yes fi # Check whether --enable-cckd-bzip2 was given. if test "${enable_cckd_bzip2+set}" = set; then enableval=$enable_cckd_bzip2; case "${enableval}" in yes) hc_cv_opt_cckd_bzip2=yes ;; no) hc_cv_opt_cckd_bzip2=no ;; *) { echo "$as_me:$LINENO: result: ERROR: invalid 'cckd-bzip2' option " >&5 echo "${ECHO_T}ERROR: invalid 'cckd-bzip2' option " >&6; } hc_error=yes ;; esac else hc_cv_opt_cckd_bzip2=$hc_cv_have_libbz2 fi # Check whether --enable-het-bzip2 was given. if test "${enable_het_bzip2+set}" = set; then enableval=$enable_het_bzip2; case "${enableval}" in yes) hc_cv_opt_het_bzip2=yes ;; no) hc_cv_opt_het_bzip2=no ;; *) { echo "$as_me:$LINENO: result: ERROR: invalid 'het-bzip2' option " >&5 echo "${ECHO_T}ERROR: invalid 'het-bzip2' option " >&6; } hc_error=yes ;; esac else hc_cv_opt_het_bzip2=$hc_cv_have_libbz2 fi # Check whether --enable-debug was given. if test "${enable_debug+set}" = set; then enableval=$enable_debug; case "${enableval}" in yes) hc_cv_opt_debug=yes ;; no) hc_cv_opt_debug=no ;; *) { echo "$as_me:$LINENO: result: ERROR: invalid 'debug' option " >&5 echo "${ECHO_T}ERROR: invalid 'debug' option " >&6; } hc_error=yes ;; esac else hc_cv_opt_debug=no fi # Check whether --enable-optimization was given. if test "${enable_optimization+set}" = set; then enableval=$enable_optimization; hc_cv_opt_optimization=${enableval} else hc_cv_opt_optimization=yes fi # Check whether --enable-configsymbols was given. if test "${enable_configsymbols+set}" = set; then enableval=$enable_configsymbols; case "${enableval}" in yes) hc_cv_opt_configsymbols=yes ;; no) hc_cv_opt_configsymbols=no ;; *) { echo "$as_me:$LINENO: result: ERROR: invalid 'configsymbols' option " >&5 echo "${ECHO_T}ERROR: invalid 'configsymbols' option " >&6; } hc_error=yes ;; esac else hc_cv_opt_configsymbols=yes fi # Check whether --enable-enhanced-configsymbols was given. if test "${enable_enhanced_configsymbols+set}" = set; then enableval=$enable_enhanced_configsymbols; case "${enableval}" in yes) hc_cv_opt_enhanced_configsymbols=yes ;; no) hc_cv_opt_enhanced_configsymbols=no ;; *) { echo "$as_me:$LINENO: result: ERROR: invalid 'enhanced-configsymbols' option " >&5 echo "${ECHO_T}ERROR: invalid 'enhanced-configsymbols' option " >&6; } hc_error=yes ;; esac else hc_cv_opt_enhanced_configsymbols=yes fi # Check whether --enable-enhanced-configincludes was given. if test "${enable_enhanced_configincludes+set}" = set; then enableval=$enable_enhanced_configincludes; case "${enableval}" in yes) hc_cv_opt_enhanced_configincludes=yes ;; no) hc_cv_opt_enhanced_configincludes=no ;; *) { echo "$as_me:$LINENO: result: ERROR: invalid 'enhanced-configincludes' option " >&5 echo "${ECHO_T}ERROR: invalid 'enhanced-configincludes' option " >&6; } hc_error=yes ;; esac else hc_cv_opt_enhanced_configincludes=yes fi # Check whether --enable-automatic-operator was given. if test "${enable_automatic_operator+set}" = set; then enableval=$enable_automatic_operator; case "${enableval}" in yes) hc_cv_opt_auto_oper=yes ;; no) hc_cv_opt_auto_oper=no ;; *) { echo "$as_me:$LINENO: result: ERROR: invalid 'automatic-operator' option " >&5 echo "${ECHO_T}ERROR: invalid 'automatic-operator' option " >&6; } hc_error=yes ;; esac else hc_cv_opt_auto_oper=$hc_cv_have_regex_h fi # Check whether --enable-external-gui was given. if test "${enable_external_gui+set}" = set; then enableval=$enable_external_gui; case "${enableval}" in yes) hc_cv_opt_external_gui=yes ;; no) hc_cv_opt_external_gui=no ;; *) { echo "$as_me:$LINENO: result: ERROR: invalid 'external-gui' option " >&5 echo "${ECHO_T}ERROR: invalid 'external-gui' option " >&6; } hc_error=yes ;; esac else hc_cv_opt_external_gui=$hc_cv_is_windows fi # Check whether --enable-fthreads was given. if test "${enable_fthreads+set}" = set; then enableval=$enable_fthreads; case "${enableval}" in yes) hc_cv_opt_fthreads=yes ;; no) hc_cv_opt_fthreads=no ;; *) { echo "$as_me:$LINENO: result: ERROR: invalid 'fthreads' option " >&5 echo "${ECHO_T}ERROR: invalid 'fthreads' option " >&6; } hc_error=yes ;; esac else hc_cv_opt_fthreads=$hc_cv_is_windows fi # Check whether --enable-fishhang was given. if test "${enable_fishhang+set}" = set; then enableval=$enable_fishhang; case "${enableval}" in yes) hc_cv_opt_fishhang=yes ;; no) hc_cv_opt_fishhang=no ;; *) { echo "$as_me:$LINENO: result: ERROR: invalid 'fishhang' option " >&5 echo "${ECHO_T}ERROR: invalid 'fishhang' option " >&6; } hc_error=yes ;; esac else hc_cv_opt_fishhang=no fi # Check whether --enable-multi-cpu was given. if test "${enable_multi_cpu+set}" = set; then enableval=$enable_multi_cpu; case "${enableval}" in yes) hc_cv_opt_num_cpu_engines=8 ;; no) hc_cv_opt_num_cpu_engines=1 ;; *) if test 0 -lt "${enableval}" -a 64 -ge "${enableval}" then hc_cv_opt_num_cpu_engines=${enableval} else { echo "$as_me:$LINENO: result: ERROR: invalid 'multi-cpu' option " >&5 echo "${ECHO_T}ERROR: invalid 'multi-cpu' option " >&6; } hc_error=yes fi ;; esac else hc_cv_opt_num_cpu_engines=8 fi # Check whether --enable-capabilities was given. if test "${enable_capabilities+set}" = set; then enableval=$enable_capabilities; case "${enableval}" in yes) hc_cv_opt_capabilities=yes ;; no) hc_cv_opt_capabilities=no ;; *) { echo "$as_me:$LINENO: result: ERROR: invalid 'capabilities' option " >&5 echo "${ECHO_T}ERROR: invalid 'capabilities' option " >&6; } hc_error=yes ;; esac else hc_cv_opt_capabilities=hc_cv_have_sys_capability fi # only include libcap if needed if test "$hc_cv_opt_capabilities" = "yes"; then { echo "$as_me:$LINENO: checking for cap_set_proc in -lcap" >&5 echo $ECHO_N "checking for cap_set_proc in -lcap... $ECHO_C" >&6; } if test "${ac_cv_lib_cap_cap_set_proc+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lcap $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 GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char cap_set_proc (); int main () { return cap_set_proc (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_cap_cap_set_proc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_cap_cap_set_proc=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_cap_cap_set_proc" >&5 echo "${ECHO_T}$ac_cv_lib_cap_cap_set_proc" >&6; } if test $ac_cv_lib_cap_cap_set_proc = yes; then cat >>confdefs.h <<_ACEOF #define HAVE_LIBCAP 1 _ACEOF LIBS="-lcap $LIBS" fi fi # Force disable capabilities support if library is missing if test "$ac_cv_lib_cap_cap_set_proc" = "no"; then hc_cv_opt_capabilities="no" fi # Force disable capabilities support if sys/capability.h header is missing if test "$hc_cv_have_sys_capa_h" = "no"; then hc_cv_opt_capabilities="no" fi # Force disable capabilities support if sys/prctl.h header is missing if test "$hc_cv_have_sys_prctl_h" = "no"; then hc_cv_opt_capabilities="no" fi # Check whether --enable-custom was given. if test "${enable_custom+set}" = set; then enableval=$enable_custom; hc_cv_opt_custom_build_str=${enableval} fi if test "$hc_cv_build_hercifc" = "yes"; then # Check whether --enable-setuid-hercifc was given. if test "${enable_setuid_hercifc+set}" = set; then enableval=$enable_setuid_hercifc; case "${enableval}" in yes) hc_cv_opt_setuid_hercifc=yes ;; no) hc_cv_opt_setuid_hercifc=no ;; *) hc_cv_opt_setuid_hercifc=yes hc_cv_hercifc_groupname=${enableval} ;; esac else hc_cv_opt_setuid_hercifc=no fi hc_cv_setuid_hercifc=$hc_cv_opt_setuid_hercifc else hc_cv_setuid_hercifc=no fi #----------------------------------------------------------------- # The handling of AC_ARG_ENABLE for "--enable-getoptwrapper" # is defined within the 'HC_ARG_ENABLE_GETOPTWRAPPER' macro # coded in the 'hercules.m4' file in the autoconf directory # and issues the AC_DEFINE for NEED_GETOPT_WRAPPER if needed # (and sets the '$hc_cv_need_getopt_wrapper' variable too). #----------------------------------------------------------------- # Check whether --enable-getoptwrapper was given. if test "${enable_getoptwrapper+set}" = set; then enableval=$enable_getoptwrapper; case "${enableval}" in yes) hc_cv_opt_getoptwrapper=yes ;; no) hc_cv_opt_getoptwrapper=no ;; auto) hc_cv_opt_getoptwrapper=auto ;; *) hc_cv_opt_getoptwrapper=auto ;; esac else hc_cv_opt_getoptwrapper=auto fi { echo "$as_me:$LINENO: checking whether getopt wrapper kludge is necessary" >&5 echo $ECHO_N "checking whether getopt wrapper kludge is necessary... $ECHO_C" >&6; } if test "$hc_cv_opt_getoptwrapper" != "auto"; then hc_cv_need_getopt_wrapper="$hc_cv_opt_getoptwrapper" hc_cv_need_getopt_wrapper_result_msg="$hc_cv_opt_getoptwrapper (forced)" else if test $(./libtool --features | fgrep "enable shared libraries" | wc -l) -ne 1; then # Libtool doesn't support shared libraries, # and thus our wrapper kludge is not needed. hc_cv_need_getopt_wrapper=no hc_cv_need_getopt_wrapper_result_msg=no else rm -f libconftest* rm -f .libs/libconftest* cat > conftest1.c << DUPGETOPT1 /* Test program that needs getopt, called by another program which itself needs getopt. Will the linker complain about duplicate symbols for getopt? We'll soon find out! */ extern char *optarg; extern int optind; int test1() { int i; char *c; i=optind; c=optarg; getopt(0,0,0); return 0; } DUPGETOPT1 cat > conftest2.c << DUPGETOPT2 /* Test program that not only needs getopt, but also calls another program which also needs getopt. Will linker complain about duplicate symbols for getopt? Let's see. */ extern char *optarg; extern int optind; extern int test2(); int test2() { int i; char *c; i=optind; c=optarg; getopt(0,0,0); test1(); return 0; } DUPGETOPT2 ./libtool --mode=compile ${CC-cc} conftest1.c -c -o conftest1.lo > /dev/null 2>&1 ./libtool --mode=compile ${CC-cc} conftest2.c -c -o conftest2.lo > /dev/null 2>&1 ./libtool --mode=link ${CC-cc} -shared -rpath /lib -no-undefined conftest1.lo -o libconftest1.la > /dev/null 2>&1 ./libtool --mode=link ${CC-cc} -shared -rpath /lib -no-undefined conftest2.lo libconftest1.la -o libconftest2.la > /dev/null 2>&1 if test $? = 0; then hc_cv_need_getopt_wrapper=no hc_cv_need_getopt_wrapper_result_msg=no else hc_cv_need_getopt_wrapper=yes hc_cv_need_getopt_wrapper_result_msg=yes fi rm -f *conftest* rm -f .libs/*conftest* fi fi { echo "$as_me:$LINENO: result: $hc_cv_need_getopt_wrapper_result_msg" >&5 echo "${ECHO_T}$hc_cv_need_getopt_wrapper_result_msg" >&6; } if test "$hc_cv_need_getopt_wrapper" = "yes"; then cat >>confdefs.h <<\_ACEOF #define NEED_GETOPT_WRAPPER 1 _ACEOF fi #---------------------------------------------------------------- # Note: '$enable_shared' is automatically set by LIBTOOL, # unless the user overrides it via --disable-shared. #---------------------------------------------------------------- hc_cv_hdl_build_shared=$enable_shared cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5 echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( *) $as_unset $ac_var ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes (double-quote # substitution turns \\\\ into \\, and sed turns \\ into \). sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then test "x$cache_file" != "x/dev/null" && { echo "$as_me:$LINENO: updating cache $cache_file" >&5 echo "$as_me: updating cache $cache_file" >&6;} cat confcache >$cache_file else { echo "$as_me:$LINENO: not updating unwritable cache $cache_file" >&5 echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache ############################################################################### # Final default settings, final sanity / error checks... ############################################################################### if test "$hc_cv_build_hercifc" = "yes"; then if test "$hc_cv_have_linux_if_tun_h" != "yes"; then if test "$hc_cv_have_net_if_h" != "yes"; then { echo "$as_me:$LINENO: result: ERROR: Required headers 'linux/if_tun.h' or 'net/if.h' not found " >&5 echo "${ECHO_T}ERROR: Required headers 'linux/if_tun.h' or 'net/if.h' not found " >&6; } hc_error=yes fi fi if test "$hc_cv_have_net_route_h" != "yes"; then { echo "$as_me:$LINENO: result: ERROR: Required header 'net/route_h' not found " >&5 echo "${ECHO_T}ERROR: Required header 'net/route_h' not found " >&6; } hc_error=yes fi fi #------------------------------------------------------------------------------ # signal.h is only required if strsignal function isn't available since if # the strsignal function isn't available, we use our builtin which needs it. # The presumption that if the strsignal function is found, then the signal.h # header will also be found seems to be a fairly safe assumption to make IMO. if test "$hc_cv_have_strsignal" != "yes" && test "$hc_cv_have_signal_h" != "yes"; then { echo "$as_me:$LINENO: result: ERROR: Required header 'signal.h' not found " >&5 echo "${ECHO_T}ERROR: Required header 'signal.h' not found " >&6; } hc_error=yes fi #------------------------------------------------------------------------------ if test "$hc_cv_have_vsscanf" != "yes"; then { echo "$as_me:$LINENO: result: ERROR: Required function 'vsscanf' not found " >&5 echo "${ECHO_T}ERROR: Required function 'vsscanf' not found " >&6; } hc_error=yes fi #------------------------------------------------------------------------------ if test "$hc_cv_have_inttypes_h" != "yes" && test "$hc_cv_have_u_int8_t" != "yes"; then { echo "$as_me:$LINENO: result: ERROR: unable to find fixed-size data types " >&5 echo "${ECHO_T}ERROR: unable to find fixed-size data types " >&6; } hc_error=yes fi #------------------------------------------------------------------------------ if test "$hc_cv_opt_cckd_bzip2" = "yes" || test "$hc_cv_opt_het_bzip2" = "yes"; then if test "$hc_cv_have_libbz2" != "yes"; then { echo "$as_me:$LINENO: result: ERROR: bzip2 compression requested but libbz2 library not found " >&5 echo "${ECHO_T}ERROR: bzip2 compression requested but libbz2 library not found " >&6; } hc_error=yes fi if test "$hc_cv_have_bzlib_h" != "yes"; then { echo "$as_me:$LINENO: result: ERROR: bzip2 compression requested but 'bzlib.h' header not found " >&5 echo "${ECHO_T}ERROR: bzip2 compression requested but 'bzlib.h' header not found " >&6; } hc_error=yes fi fi #------------------------------------------------------------------------------ if test "$hc_cv_opt_dynamic_load" = "yes"; then if test "$hc_cv_have_lt_dlopen" != "yes" && test "$hc_cv_have_dlopen" != "yes"; then { echo "$as_me:$LINENO: result: ERROR: dynamic-load requires libtool or dlltool " >&5 echo "${ECHO_T}ERROR: dynamic-load requires libtool or dlltool " >&6; } hc_error=yes fi fi #------------------------------------------------------------------------------ if test "$hc_cv_opt_auto_oper" = "yes" && test "$hc_cv_have_regex_h" != "yes"; then { echo "$as_me:$LINENO: result: ERROR: automatic-operator requested but 'regex.h' header not found " >&5 echo "${ECHO_T}ERROR: automatic-operator requested but 'regex.h' header not found " >&6; } hc_error=yes fi #------------------------------------------------------------------------------ if test "$hc_cv_opt_external_gui" = "yes" && test "$hc_cv_opt_dynamic_load" != "yes"; then { echo "$as_me:$LINENO: result: ERROR: external-gui requires dynamic-load " >&5 echo "${ECHO_T}ERROR: external-gui requires dynamic-load " >&6; } hc_error=yes fi #------------------------------------------------------------------------------ if test "$hc_cv_opt_fthreads" = "yes" && test "$hc_cv_is_windows" != "yes"; then { echo "$as_me:$LINENO: result: ERROR: fthreads is only for Windows platforms " >&5 echo "${ECHO_T}ERROR: fthreads is only for Windows platforms " >&6; } hc_error=yes fi if test "$hc_cv_have_pthread_h" != "yes" && test "$hc_cv_opt_fthreads" != "yes"; then { echo "$as_me:$LINENO: result: ERROR: unable to find pthread.h " >&5 echo "${ECHO_T}ERROR: unable to find pthread.h " >&6; } hc_error=yes fi #------------------------------------------------------------------------------ if test "$hc_cv_opt_fishhang" = "yes" && test "$hc_cv_opt_fthreads" != "yes"; then { echo "$as_me:$LINENO: result: ERROR: fishhang requires fthreads " >&5 echo "${ECHO_T}ERROR: fishhang requires fthreads " >&6; } hc_error=yes fi #------------------------------------------------------------------------------ if test "$hc_cv_is_apple" = "yes" && test "$hc_cv_pp_macro_arg_counting_broke" = "yes" && test "$hc_cv_traditional_cpp_is_K_AND_R_C_type" = "yes"; then { echo "$as_me:$LINENO: result: ERROR: macro argument counting broken and cannot use -traditional-cpp option to work around it " >&5 echo "${ECHO_T}ERROR: macro argument counting broken and cannot use -traditional-cpp option to work around it " >&6; } hc_error=yes fi #------------------------------------------------------------------------------ # If any errors have been detected, then abort the configure at this time #------------------------------------------------------------------------------ if test "$hc_error" != "no"; then { { echo "$as_me:$LINENO: error: Please correct the above error(s) and try again " >&5 echo "$as_me: error: Please correct the above error(s) and try again " >&2;} { (exit 1); exit 1; }; } fi cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5 echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( *) $as_unset $ac_var ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes (double-quote # substitution turns \\\\ into \\, and sed turns \\ into \). sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then test "x$cache_file" != "x/dev/null" && { echo "$as_me:$LINENO: updating cache $cache_file" >&5 echo "$as_me: updating cache $cache_file" >&6;} cat confcache >$cache_file else { echo "$as_me:$LINENO: not updating unwritable cache $cache_file" >&5 echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache ############################################################################### # Act on the results of all of the above... ############################################################################### # AUTOMATIC DETERMINATION OF OPTIMIZATION FLAGS # # If they specified 'no' then don't optimize. # If they specified 'yes' then determine what flags we should use. # If they didn't specify, then optimize only if this is NOT a debug build. # Otherwise use whatever flags they specified as-is. { echo "$as_me:$LINENO: checking for what optimization flags to use " >&5 echo $ECHO_N "checking for what optimization flags to use ... $ECHO_C" >&6; } case "$hc_cv_opt_optimization" in no) hc_cv_auto_optimize=no ;; yes) hc_cv_auto_optimize=yes ;; *) if test "x$hc_cv_opt_optimization" = "x"; then if test "$hc_cv_opt_debug" = "yes"; then hc_cv_auto_optimize=no else hc_cv_auto_optimize=yes fi else hc_cv_auto_optimize=no hc_cv_optimization_flags="$hc_cv_opt_optimization" fi ;; esac if test "$hc_cv_auto_optimize" = "yes"; then if test "$hc_cv_builtin_alloca_broke" != "yes" && test "$hc_cv_opt_debug" != "yes"; then hc_cv_optimization_flags="-O3" fi hc_cv_is_intel_x86_arch=no case "$host_cpu-$GCC" in x86_64-yes) hc_cv_is_intel_x86_arch=yes hc_cv_intel_cpu_type=k8 ;; i386-yes|i486-yes|i586-yes|i686-yes|i786-yes) hc_cv_is_intel_x86_arch=yes if test $host_cpu = i786; then hc_cv_intel_cpu_type=pentium4 else if test $host_cpu = i686 && test "hc_cv_is_gcc_2_96" = "yes"; then hc_cv_intel_cpu_type=i586 else hc_cv_intel_cpu_type=$host_cpu fi fi ;; arm-yes) hc_cv_is_intel_x86_arch=no hc_cv_optimization_flags="$hc_cv_optimization_flags -frename-registers" ;; xscale-yes|arm*-yes) hc_cv_is_intel_x86_arch=no hc_cv_optimization_flags="$hc_cv_optimization_flags -mcpu=$host_cpu -mtune=$host_cpu -frename-registers" ;; esac if test "$hc_cv_is_intel_x86_arch" = "yes"; then hc_cv_optimization_flags="$hc_cv_optimization_flags -march=$hc_cv_intel_cpu_type" if test "$hc_cv_builtin_alloca_broke" != "yes" && test "$hc_cv_opt_debug" != "yes"; then hc_cv_optimization_flags="$hc_cv_optimization_flags -fomit-frame-pointer" else hc_cv_optimization_flags="$hc_cv_optimization_flags -fno-omit-frame-pointer" fi fi fi if test "x$hc_cv_optimization_flags" = "x"; then { echo "$as_me:$LINENO: result: (none) " >&5 echo "${ECHO_T}(none) " >&6; } else { echo "$as_me:$LINENO: result: $hc_cv_optimization_flags " >&5 echo "${ECHO_T}$hc_cv_optimization_flags " >&6; } fi cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5 echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( *) $as_unset $ac_var ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes (double-quote # substitution turns \\\\ into \\, and sed turns \\ into \). sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then test "x$cache_file" != "x/dev/null" && { echo "$as_me:$LINENO: updating cache $cache_file" >&5 echo "$as_me: updating cache $cache_file" >&6;} cat confcache >$cache_file else { echo "$as_me:$LINENO: not updating unwritable cache $cache_file" >&5 echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache ############################################################################### # DONE! -- Define our OUTPUT values and then exit... ############################################################################### # This is ugly... Someone PLEASE fix this (if possible)... # # The object is to get the value of PKGDATADIR into config.h, # but this is the only way I've found to do so. All of this # rigamarole is needed because ${datadir} doesn't expand to the # desired data directory. If there's a better way to get there, # PLEASE replace this. -- JRM # # If DESTPREFIX is set, we're doing an RPM build, and we want to # use that value. If it's not set, and prefix is set and not equal # to NONE, then we'll use that. If prefix is NONE, then default to # /usr/local. Note: This prefix has /share/locale, /share/$PACKAGE, # or /lib/$PACKAGE appended in the next step, so it must NOT have # those components included in $DESTPREFIX itself. if test "x${DESTPREFIX}" = "x"; then if test "x$prefix" = "xNONE"; then DESTPREFIX="/usr/local" else DESTPREFIX="${prefix}" fi fi case "x${libdir}" in *lib64*) DESTLIBS="lib64" ;; *) DESTLIBS="lib" ;; esac MODULESDIR="${DESTPREFIX}/${DESTLIBS}/${PACKAGE}" PKGDATADIR="${DESTPREFIX}/share/${PACKAGE}" HERC_LOCALEDIR="${DESTPREFIX}/share/locale" #--------------------------------------------------------------# # (place only AC_DEFINE_UNQUOTED here; place AC_DEFINE below) # #--------------------------------------------------------------# if test "x$hc_cv_opt_custom_build_str" != "x"; then cat >>confdefs.h <<_ACEOF #define CUSTOM_BUILD_STRING "${hc_cv_opt_custom_build_str}" _ACEOF fi cat >>confdefs.h <<_ACEOF #define MODULESDIR "${MODULESDIR}" _ACEOF cat >>confdefs.h <<_ACEOF #define PKGDATADIR "${PKGDATADIR}" _ACEOF cat >>confdefs.h <<_ACEOF #define HERC_LOCALEDIR "${HERC_LOCALEDIR}" _ACEOF cat >>confdefs.h <<_ACEOF #define MAX_CPU_ENGINES ${hc_cv_opt_num_cpu_engines} _ACEOF cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5 echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( *) $as_unset $ac_var ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes (double-quote # substitution turns \\\\ into \\, and sed turns \\ into \). sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then test "x$cache_file" != "x/dev/null" && { echo "$as_me:$LINENO: updating cache $cache_file" >&5 echo "$as_me: updating cache $cache_file" >&6;} cat confcache >$cache_file else { echo "$as_me:$LINENO: not updating unwritable cache $cache_file" >&5 echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache { echo "$as_me:$LINENO: " >&5 echo "$as_me: " >&6;} { echo "$as_me:$LINENO: Package destination directory prefixes: " >&5 echo "$as_me: Package destination directory prefixes: " >&6;} { echo "$as_me:$LINENO: " >&5 echo "$as_me: " >&6;} { echo "$as_me:$LINENO: Libraries: ${MODULESDIR} " >&5 echo "$as_me: Libraries: ${MODULESDIR} " >&6;} { echo "$as_me:$LINENO: Data: ${PKGDATADIR} " >&5 echo "$as_me: Data: ${PKGDATADIR} " >&6;} { echo "$as_me:$LINENO: Locale: ${HERC_LOCALEDIR} " >&5 echo "$as_me: Locale: ${HERC_LOCALEDIR} " >&6;} { echo "$as_me:$LINENO: " >&5 echo "$as_me: " >&6;} #---------------------------------------------------------------# # (place only AC_DEFINE here; place AC_DEFINE_UNQUOTED above) # #---------------------------------------------------------------# test "$hc_cv_opt_debug" = "yes" && cat >>confdefs.h <<\_ACEOF #define DEBUG 1 _ACEOF test "$hc_cv_have_inttypes_h" = "yes" && cat >>confdefs.h <<\_ACEOF #define HAVE_INTTYPES_H 1 _ACEOF test "$hc_cv_have_u_int8_t" = "yes" && cat >>confdefs.h <<\_ACEOF #define HAVE_U_INT 1 _ACEOF test "$hc_cv_opt_configsymbols" = "yes" && cat >>confdefs.h <<\_ACEOF #define OPTION_CONFIG_SYMBOLS 1 _ACEOF test "$hc_cv_opt_enhanced_configsymbols" = "yes" && cat >>confdefs.h <<\_ACEOF #define OPTION_ENHANCED_CONFIG_SYMBOLS 1 _ACEOF test "$hc_cv_opt_enhanced_configincludes" = "yes" && cat >>confdefs.h <<\_ACEOF #define OPTION_ENHANCED_CONFIG_INCLUDE 1 _ACEOF test "$hc_cv_opt_auto_oper" = "yes" && cat >>confdefs.h <<\_ACEOF #define OPTION_HAO 1 _ACEOF test "$hc_cv_opt_dynamic_load" = "yes" && cat >>confdefs.h <<\_ACEOF #define OPTION_DYNAMIC_LOAD 1 _ACEOF test "$hc_cv_opt_fthreads" = "yes" && cat >>confdefs.h <<\_ACEOF #define OPTION_FTHREADS 1 _ACEOF test "$hc_cv_opt_fishhang" = "yes" && cat >>confdefs.h <<\_ACEOF #define FISH_HANG 1 _ACEOF test "$hc_cv_hdl_build_shared" = "yes" && cat >>confdefs.h <<\_ACEOF #define HDL_BUILD_SHARED 1 _ACEOF test "$hc_cv_have_lt_dlopen" = "yes" && cat >>confdefs.h <<\_ACEOF #define HDL_USE_LIBTOOL 1 _ACEOF test "$hc_cv_is_windows" = "yes" && cat >>confdefs.h <<\_ACEOF #define WIN32 1 _ACEOF test "$hc_cv_opt_external_gui" = "yes" && cat >>confdefs.h <<\_ACEOF #define EXTERNALGUI 1 _ACEOF test "$hc_cv_opt_cckd_bzip2" = "yes" && cat >>confdefs.h <<\_ACEOF #define CCKD_BZIP2 1 _ACEOF test "$hc_cv_opt_het_bzip2" = "yes" && cat >>confdefs.h <<\_ACEOF #define HET_BZIP2 1 _ACEOF test "$hc_cv_timespec_in_sys_types_h" = "yes" && cat >>confdefs.h <<\_ACEOF #define TIMESPEC_IN_SYS_TYPES_H 1 _ACEOF test "$hc_cv_timespec_in_time_h" = "yes" && cat >>confdefs.h <<\_ACEOF #define TIMESPEC_IN_TIME_H 1 _ACEOF test "$hc_cv_have_getset_uid" != "yes" && cat >>confdefs.h <<\_ACEOF #define NO_SETUID 1 _ACEOF test "$hc_cv_asm_byteswap" != "yes" && cat >>confdefs.h <<\_ACEOF #define NO_ASM_BYTESWAP 1 _ACEOF test "$hc_cv_non_unique_gettimeofday" = "yes" && cat >>confdefs.h <<\_ACEOF #define NON_UNIQUE_GETTIMEOFDAY 1 _ACEOF test "$hc_cv_build_hercifc" = "yes" && cat >>confdefs.h <<\_ACEOF #define BUILD_HERCIFC 1 _ACEOF test "$hc_cv_opt_capabilities" = "yes" && cat >>confdefs.h <<\_ACEOF #define OPTION_CAPABILITIES 1 _ACEOF if test $hc_cv_have_sa_sigaction != yes || test $hc_cv_have_sigusr1 != yes || test $hc_cv_have_sigusr2 != yes || test $hc_cv_have_sigpipe != yes || test $hc_cv_have_sigbus != yes; then cat >>confdefs.h <<\_ACEOF #define NO_SIGABEND_HANDLER 1 _ACEOF fi if test "$hc_cv_regparm_attr_supported" = "yes" && test "$hc_cv_regparm_attr_broke" != "yes"; then cat >>confdefs.h <<\_ACEOF #define HAVE_ATTR_REGPARM 1 _ACEOF fi if test "$hc_cv_is_windows" != "yes" && test "$hc_cv_have_fenv_h" != "yes"; then cat >>confdefs.h <<\_ACEOF #define NO_IEEE_SUPPORT 1 _ACEOF fi if test "$hc_cv_is_apple" = "yes"; then cat >>confdefs.h <<\_ACEOF #define _INTL_REDIRECT_MACROS 1 _ACEOF # # TODO?? # # Do whatever is necessary to get the following symbol defined # so the included libltdl will be built and used... # ## AC_PROVIDE_AC_LIBTOOL_DLOPEN() fi #--------------------------------------------------# # CPPFLAGS (pre-processor flags) # #--------------------------------------------------# if test "$hc_cv_is_apple" = "yes" && test "$hc_cv_pp_macro_arg_counting_broke" = "yes"; then CPPFLAGS="${CPPFLAGS} -traditional-cpp -Wno-endif-labels" fi #--------------------------------------------------# # CFLAGS (compiler flags) # #--------------------------------------------------# if test "$hc_cv_is_windows" = "yes"; then if test "$hc_cv_have_pthread_h" = "yes" && test "x$hc_cv_alt_pthread_location" != "x"; then CFLAGS="$CFLAGS -I${hc_cv_alt_pthread_location}" fi CFLAGS="$CFLAGS -Wno-format" fi if test "$hc_cv_byte_structs_aligned_and_rounded_by_default" = "yes"; then #=============================================================== # the following requests 8-bit (byte) struct boundary alignment #=============================================================== CFLAGS="$CFLAGS -mstructure-size-boundary=8" fi test "x$hc_cv_optimization_flags" != "x" && CFLAGS="$CFLAGS $hc_cv_optimization_flags" #--------------------------------------------------# # LIBS (linker flags) # #--------------------------------------------------# test "$hc_cv_dash_pthread_needed" = "yes" && LIBS="$LIBS -pthread" test "$hc_cv_have_libbz2" = "yes" && LIBS="$LIBS -lbz2" # ---------------------- MINGW32 ---------------------- test "$hc_cv_is_mingw32" = "yes" && LIBS="$LIBS -lmsvcrt" test "$hc_cv_is_mingw32" = "yes" && LIBS="$LIBS -lws2_32" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5 echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( *) $as_unset $ac_var ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes (double-quote # substitution turns \\\\ into \\, and sed turns \\ into \). sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then test "x$cache_file" != "x/dev/null" && { echo "$as_me:$LINENO: updating cache $cache_file" >&5 echo "$as_me: updating cache $cache_file" >&6;} cat confcache >$cache_file else { echo "$as_me:$LINENO: not updating unwritable cache $cache_file" >&5 echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache #--------------------------------------------------------------------------------# # Pass certain values/settings as makefile variables to automake (makefile.am) # #--------------------------------------------------------------------------------# if test "$hc_cv_opt_dynamic_load" = "yes" ; then OPTION_DYNAMIC_LOAD_TRUE= OPTION_DYNAMIC_LOAD_FALSE='#' else OPTION_DYNAMIC_LOAD_TRUE='#' OPTION_DYNAMIC_LOAD_FALSE= fi if test "$hc_cv_opt_fthreads" = "yes" ; then BUILD_FTHREADS_TRUE= BUILD_FTHREADS_FALSE='#' else BUILD_FTHREADS_TRUE='#' BUILD_FTHREADS_FALSE= fi if test "$hc_cv_opt_fishhang" = "yes" ; then BUILD_FISHHANG_TRUE= BUILD_FISHHANG_FALSE='#' else BUILD_FISHHANG_TRUE='#' BUILD_FISHHANG_FALSE= fi if test "$hc_cv_build_hercifc" = "yes" ; then BUILD_HERCIFC_TRUE= BUILD_HERCIFC_FALSE='#' else BUILD_HERCIFC_TRUE='#' BUILD_HERCIFC_FALSE= fi if test "$hc_cv_setuid_hercifc" = "yes" ; then SETUID_HERCIFC_TRUE= SETUID_HERCIFC_FALSE='#' else SETUID_HERCIFC_TRUE='#' SETUID_HERCIFC_FALSE= fi if test "x$hc_cv_hercifc_groupname" != "x" ; then HERCIFC_GROUPSET_TRUE= HERCIFC_GROUPSET_FALSE='#' else HERCIFC_GROUPSET_TRUE='#' HERCIFC_GROUPSET_FALSE= fi if test "x$hc_cv_hercifc_groupname" != "x"; then HERCIFC_GROUPNAME=${hc_cv_hercifc_groupname} fi # Building of shared libraries is forced, and we force use of libtool too. if test "$hc_cv_hdl_build_shared" = "yes" ; then BUILD_SHARED_TRUE= BUILD_SHARED_FALSE='#' else BUILD_SHARED_TRUE='#' BUILD_SHARED_FALSE= fi if test "$hc_cv_is_windows" = "yes" ; then USE_DLLTOOL_TRUE= USE_DLLTOOL_FALSE='#' else USE_DLLTOOL_TRUE='#' USE_DLLTOOL_FALSE= fi cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5 echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( *) $as_unset $ac_var ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes (double-quote # substitution turns \\\\ into \\, and sed turns \\ into \). sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then test "x$cache_file" != "x/dev/null" && { echo "$as_me:$LINENO: updating cache $cache_file" >&5 echo "$as_me: updating cache $cache_file" >&6;} cat confcache >$cache_file else { echo "$as_me:$LINENO: not updating unwritable cache $cache_file" >&5 echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache ac_config_files="$ac_config_files Makefile util/Makefile html/Makefile crypto/Makefile po/Makefile.in po/Makefile man/Makefile m4/Makefile decNumber/Makefile" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5 echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( *) $as_unset $ac_var ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes (double-quote # substitution turns \\\\ into \\, and sed turns \\ into \). sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then test "x$cache_file" != "x/dev/null" && { echo "$as_me:$LINENO: updating cache $cache_file" >&5 echo "$as_me: updating cache $cache_file" >&6;} cat confcache >$cache_file else { echo "$as_me:$LINENO: not updating unwritable cache $cache_file" >&5 echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' DEFS=-DHAVE_CONFIG_H ac_libobjs= ac_ltlibobjs= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`echo "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. ac_libobjs="$ac_libobjs \${LIBOBJDIR}$ac_i\$U.$ac_objext" ac_ltlibobjs="$ac_ltlibobjs \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs if test -z "${MAINTAINER_MODE_TRUE}" && test -z "${MAINTAINER_MODE_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"MAINTAINER_MODE\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"MAINTAINER_MODE\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"AMDEP\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"AMDEP\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"am__fastdepCC\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"am__fastdepCC\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${am__fastdepCXX_TRUE}" && test -z "${am__fastdepCXX_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"am__fastdepCXX\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"am__fastdepCXX\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${INSTALL_LTDL_TRUE}" && test -z "${INSTALL_LTDL_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"INSTALL_LTDL\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"INSTALL_LTDL\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${CONVENIENCE_LTDL_TRUE}" && test -z "${CONVENIENCE_LTDL_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"CONVENIENCE_LTDL\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"CONVENIENCE_LTDL\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${OPTION_DYNAMIC_LOAD_TRUE}" && test -z "${OPTION_DYNAMIC_LOAD_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"OPTION_DYNAMIC_LOAD\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"OPTION_DYNAMIC_LOAD\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${BUILD_FTHREADS_TRUE}" && test -z "${BUILD_FTHREADS_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"BUILD_FTHREADS\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"BUILD_FTHREADS\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${BUILD_FISHHANG_TRUE}" && test -z "${BUILD_FISHHANG_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"BUILD_FISHHANG\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"BUILD_FISHHANG\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${BUILD_HERCIFC_TRUE}" && test -z "${BUILD_HERCIFC_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"BUILD_HERCIFC\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"BUILD_HERCIFC\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${SETUID_HERCIFC_TRUE}" && test -z "${SETUID_HERCIFC_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"SETUID_HERCIFC\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"SETUID_HERCIFC\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${HERCIFC_GROUPSET_TRUE}" && test -z "${HERCIFC_GROUPSET_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"HERCIFC_GROUPSET\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"HERCIFC_GROUPSET\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${BUILD_SHARED_TRUE}" && test -z "${BUILD_SHARED_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"BUILD_SHARED\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"BUILD_SHARED\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${USE_DLLTOOL_TRUE}" && test -z "${USE_DLLTOOL_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"USE_DLLTOOL\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"USE_DLLTOOL\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi : ${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 more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in *posix*) set -o posix ;; esac fi # PATH needs CR # 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 # Support unset when possible. if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then as_unset=unset else as_unset=false fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) as_nl=' ' IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. case $0 in *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 { (exit 1); exit 1; } fi # Work around bugs in pre-3.0 UWIN ksh. for as_var in ENV MAIL MAILPATH do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var done 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) >/dev/null 2>&1 && $as_unset $as_var fi done # Required to use basename. if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi # 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'` # CDPATH. $as_unset CDPATH as_lineno_1=$LINENO as_lineno_2=$LINENO test "x$as_lineno_1" != "x$as_lineno_2" && test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || { # 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 after each line using $LINENO; the second 'sed' # does the real work. The second script uses 'N' to pair each # line-number line with the line containing $LINENO, 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 # scripts with optimization help from Paolo Bonzini. Blame Lee # E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { 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 sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in -n*) case `echo 'x\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. *) ECHO_C='\c';; esac;; *) ECHO_N='-n';; esac if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir fi echo >conf$$.file if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -p'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -p' 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$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p=: else test -d ./-p && rmdir ./-p as_mkdir_p=false fi if test -x / >/dev/null 2>&1; then as_test_x='test -x' else if ls -dL / >/dev/null 2>&1; then as_ls_L_option=L else as_ls_L_option= fi as_test_x=' eval sh -c '\'' if test -d "$1"; then test -d "$1/."; else case $1 in -*)set "./$1";; esac; case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in ???[sx]*):;;*)false;;esac;fi '\'' sh ' fi as_executable_p=$as_test_x # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 # Save the log message, to keep $[0] and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by $as_me, which was generated by GNU Autoconf 2.61. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF cat >>$CONFIG_STATUS <<_ACEOF # Files that config.status was made for. config_files="$ac_config_files" config_headers="$ac_config_headers" config_commands="$ac_config_commands" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF ac_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 and configuration settings, 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 --header=FILE[:TEMPLATE] instantiate the configuration header FILE Configuration files: $config_files Configuration headers: $config_headers Configuration commands: $config_commands Report bugs to ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF ac_cs_version="\\ config.status configured by $0, generated by GNU Autoconf 2.61, with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\" Copyright (C) 2006 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' INSTALL='$INSTALL' _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 ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) echo "$ac_cs_version"; exit ;; --debug | --debu | --deb | --de | --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;; --he | --h) # Conflict between --help and --header { 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 ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) { 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" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF if \$ac_cs_recheck; then echo "running CONFIG_SHELL=$SHELL $SHELL $0 "$ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6 CONFIG_SHELL=$SHELL export CONFIG_SHELL exec $SHELL "$0"$ac_configure_args \$ac_configure_extra_args --no-create --no-recursion fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX echo "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF # # INIT-COMMANDS # AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" # Capture the value of obsolete ALL_LINGUAS because we need it to compute # POFILES, UPDATEPOFILES, DUMMYPOFILES, GMOFILES, CATALOGS. But hide it # from automake. 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 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; "default-1") CONFIG_COMMANDS="$CONFIG_COMMANDS default-1" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; "util/Makefile") CONFIG_FILES="$CONFIG_FILES util/Makefile" ;; "html/Makefile") CONFIG_FILES="$CONFIG_FILES html/Makefile" ;; "crypto/Makefile") CONFIG_FILES="$CONFIG_FILES crypto/Makefile" ;; "po/Makefile.in") CONFIG_FILES="$CONFIG_FILES po/Makefile.in" ;; "po/Makefile") CONFIG_FILES="$CONFIG_FILES po/Makefile" ;; "man/Makefile") CONFIG_FILES="$CONFIG_FILES man/Makefile" ;; "m4/Makefile") CONFIG_FILES="$CONFIG_FILES m4/Makefile" ;; "decNumber/Makefile") CONFIG_FILES="$CONFIG_FILES decNumber/Makefile" ;; *) { { 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_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= trap 'exit_status=$? { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$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 "./confXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || { echo "$me: cannot create a temporary directory in ." >&2 { (exit 1); exit 1; } } # # Set up the sed scripts for 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 _ACEOF ac_delim='%!_!# ' for ac_last_try in false false false false false :; do cat >conf$$subs.sed <<_ACEOF SHELL!$SHELL$ac_delim PATH_SEPARATOR!$PATH_SEPARATOR$ac_delim PACKAGE_NAME!$PACKAGE_NAME$ac_delim PACKAGE_TARNAME!$PACKAGE_TARNAME$ac_delim PACKAGE_VERSION!$PACKAGE_VERSION$ac_delim PACKAGE_STRING!$PACKAGE_STRING$ac_delim PACKAGE_BUGREPORT!$PACKAGE_BUGREPORT$ac_delim exec_prefix!$exec_prefix$ac_delim prefix!$prefix$ac_delim program_transform_name!$program_transform_name$ac_delim bindir!$bindir$ac_delim sbindir!$sbindir$ac_delim libexecdir!$libexecdir$ac_delim datarootdir!$datarootdir$ac_delim datadir!$datadir$ac_delim sysconfdir!$sysconfdir$ac_delim sharedstatedir!$sharedstatedir$ac_delim localstatedir!$localstatedir$ac_delim includedir!$includedir$ac_delim oldincludedir!$oldincludedir$ac_delim docdir!$docdir$ac_delim infodir!$infodir$ac_delim htmldir!$htmldir$ac_delim dvidir!$dvidir$ac_delim pdfdir!$pdfdir$ac_delim psdir!$psdir$ac_delim libdir!$libdir$ac_delim localedir!$localedir$ac_delim mandir!$mandir$ac_delim DEFS!$DEFS$ac_delim ECHO_C!$ECHO_C$ac_delim ECHO_N!$ECHO_N$ac_delim ECHO_T!$ECHO_T$ac_delim LIBS!$LIBS$ac_delim build_alias!$build_alias$ac_delim host_alias!$host_alias$ac_delim target_alias!$target_alias$ac_delim INSTALL_PROGRAM!$INSTALL_PROGRAM$ac_delim INSTALL_SCRIPT!$INSTALL_SCRIPT$ac_delim INSTALL_DATA!$INSTALL_DATA$ac_delim CYGPATH_W!$CYGPATH_W$ac_delim PACKAGE!$PACKAGE$ac_delim VERSION!$VERSION$ac_delim ACLOCAL!$ACLOCAL$ac_delim AUTOCONF!$AUTOCONF$ac_delim AUTOMAKE!$AUTOMAKE$ac_delim AUTOHEADER!$AUTOHEADER$ac_delim MAKEINFO!$MAKEINFO$ac_delim install_sh!$install_sh$ac_delim STRIP!$STRIP$ac_delim INSTALL_STRIP_PROGRAM!$INSTALL_STRIP_PROGRAM$ac_delim mkdir_p!$mkdir_p$ac_delim AWK!$AWK$ac_delim SET_MAKE!$SET_MAKE$ac_delim am__leading_dot!$am__leading_dot$ac_delim AMTAR!$AMTAR$ac_delim am__tar!$am__tar$ac_delim am__untar!$am__untar$ac_delim MAINTAINER_MODE_TRUE!$MAINTAINER_MODE_TRUE$ac_delim MAINTAINER_MODE_FALSE!$MAINTAINER_MODE_FALSE$ac_delim MAINT!$MAINT$ac_delim build!$build$ac_delim build_cpu!$build_cpu$ac_delim build_vendor!$build_vendor$ac_delim build_os!$build_os$ac_delim host!$host$ac_delim host_cpu!$host_cpu$ac_delim host_vendor!$host_vendor$ac_delim host_os!$host_os$ac_delim CC!$CC$ac_delim CFLAGS!$CFLAGS$ac_delim LDFLAGS!$LDFLAGS$ac_delim CPPFLAGS!$CPPFLAGS$ac_delim ac_ct_CC!$ac_ct_CC$ac_delim EXEEXT!$EXEEXT$ac_delim OBJEXT!$OBJEXT$ac_delim DEPDIR!$DEPDIR$ac_delim am__include!$am__include$ac_delim am__quote!$am__quote$ac_delim AMDEP_TRUE!$AMDEP_TRUE$ac_delim AMDEP_FALSE!$AMDEP_FALSE$ac_delim AMDEPBACKSLASH!$AMDEPBACKSLASH$ac_delim CCDEPMODE!$CCDEPMODE$ac_delim am__fastdepCC_TRUE!$am__fastdepCC_TRUE$ac_delim am__fastdepCC_FALSE!$am__fastdepCC_FALSE$ac_delim modexecdir!$modexecdir$ac_delim GREP!$GREP$ac_delim EGREP!$EGREP$ac_delim LN_S!$LN_S$ac_delim ECHO!$ECHO$ac_delim AR!$AR$ac_delim RANLIB!$RANLIB$ac_delim DLLTOOL!$DLLTOOL$ac_delim AS!$AS$ac_delim OBJDUMP!$OBJDUMP$ac_delim CPP!$CPP$ac_delim CXX!$CXX$ac_delim _ACEOF if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 97; then break elif $ac_last_try; then { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 echo "$as_me: error: could not make $CONFIG_STATUS" >&2;} { (exit 1); exit 1; }; } else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done ac_eof=`sed -n '/^CEOF[0-9]*$/s/CEOF/0/p' conf$$subs.sed` if test -n "$ac_eof"; then ac_eof=`echo "$ac_eof" | sort -nru | sed 1q` ac_eof=`expr $ac_eof + 1` fi cat >>$CONFIG_STATUS <<_ACEOF cat >"\$tmp/subs-1.sed" <<\CEOF$ac_eof /@[a-zA-Z_][a-zA-Z_0-9]*@/!b _ACEOF sed ' s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g s/^/s,@/; s/!/@,|#_!!_#|/ :n t n s/'"$ac_delim"'$/,g/; t s/$/\\/; p N; s/^.*\n//; s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g; b n ' >>$CONFIG_STATUS >$CONFIG_STATUS <<_ACEOF CEOF$ac_eof _ACEOF ac_delim='%!_!# ' for ac_last_try in false false false false false :; do cat >conf$$subs.sed <<_ACEOF CXXFLAGS!$CXXFLAGS$ac_delim ac_ct_CXX!$ac_ct_CXX$ac_delim CXXDEPMODE!$CXXDEPMODE$ac_delim am__fastdepCXX_TRUE!$am__fastdepCXX_TRUE$ac_delim am__fastdepCXX_FALSE!$am__fastdepCXX_FALSE$ac_delim CXXCPP!$CXXCPP$ac_delim F77!$F77$ac_delim FFLAGS!$FFLAGS$ac_delim ac_ct_F77!$ac_ct_F77$ac_delim LIBTOOL!$LIBTOOL$ac_delim INSTALL_LTDL_TRUE!$INSTALL_LTDL_TRUE$ac_delim INSTALL_LTDL_FALSE!$INSTALL_LTDL_FALSE$ac_delim CONVENIENCE_LTDL_TRUE!$CONVENIENCE_LTDL_TRUE$ac_delim CONVENIENCE_LTDL_FALSE!$CONVENIENCE_LTDL_FALSE$ac_delim LIBADD_DL!$LIBADD_DL$ac_delim LIBTOOL_DEPS!$LIBTOOL_DEPS$ac_delim MKINSTALLDIRS!$MKINSTALLDIRS$ac_delim USE_NLS!$USE_NLS$ac_delim MSGFMT!$MSGFMT$ac_delim GMSGFMT!$GMSGFMT$ac_delim XGETTEXT!$XGETTEXT$ac_delim MSGMERGE!$MSGMERGE$ac_delim INTL_MACOSX_LIBS!$INTL_MACOSX_LIBS$ac_delim LIBICONV!$LIBICONV$ac_delim LTLIBICONV!$LTLIBICONV$ac_delim INTLLIBS!$INTLLIBS$ac_delim LIBINTL!$LIBINTL$ac_delim LTLIBINTL!$LTLIBINTL$ac_delim POSUB!$POSUB$ac_delim OPTION_DYNAMIC_LOAD_TRUE!$OPTION_DYNAMIC_LOAD_TRUE$ac_delim OPTION_DYNAMIC_LOAD_FALSE!$OPTION_DYNAMIC_LOAD_FALSE$ac_delim BUILD_FTHREADS_TRUE!$BUILD_FTHREADS_TRUE$ac_delim BUILD_FTHREADS_FALSE!$BUILD_FTHREADS_FALSE$ac_delim BUILD_FISHHANG_TRUE!$BUILD_FISHHANG_TRUE$ac_delim BUILD_FISHHANG_FALSE!$BUILD_FISHHANG_FALSE$ac_delim BUILD_HERCIFC_TRUE!$BUILD_HERCIFC_TRUE$ac_delim BUILD_HERCIFC_FALSE!$BUILD_HERCIFC_FALSE$ac_delim SETUID_HERCIFC_TRUE!$SETUID_HERCIFC_TRUE$ac_delim SETUID_HERCIFC_FALSE!$SETUID_HERCIFC_FALSE$ac_delim HERCIFC_GROUPSET_TRUE!$HERCIFC_GROUPSET_TRUE$ac_delim HERCIFC_GROUPSET_FALSE!$HERCIFC_GROUPSET_FALSE$ac_delim HERCIFC_GROUPNAME!$HERCIFC_GROUPNAME$ac_delim BUILD_SHARED_TRUE!$BUILD_SHARED_TRUE$ac_delim BUILD_SHARED_FALSE!$BUILD_SHARED_FALSE$ac_delim USE_DLLTOOL_TRUE!$USE_DLLTOOL_TRUE$ac_delim USE_DLLTOOL_FALSE!$USE_DLLTOOL_FALSE$ac_delim LIBOBJS!$LIBOBJS$ac_delim LTLIBOBJS!$LTLIBOBJS$ac_delim _ACEOF if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 48; then break elif $ac_last_try; then { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 echo "$as_me: error: could not make $CONFIG_STATUS" >&2;} { (exit 1); exit 1; }; } else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done ac_eof=`sed -n '/^CEOF[0-9]*$/s/CEOF/0/p' conf$$subs.sed` if test -n "$ac_eof"; then ac_eof=`echo "$ac_eof" | sort -nru | sed 1q` ac_eof=`expr $ac_eof + 1` fi cat >>$CONFIG_STATUS <<_ACEOF cat >"\$tmp/subs-2.sed" <<\CEOF$ac_eof /@[a-zA-Z_][a-zA-Z_0-9]*@/!b end _ACEOF sed ' s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g s/^/s,@/; s/!/@,|#_!!_#|/ :n t n s/'"$ac_delim"'$/,g/; t s/$/\\/; p N; s/^.*\n//; s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g; b n ' >>$CONFIG_STATUS >$CONFIG_STATUS <<_ACEOF :end s/|#_!!_#|//g CEOF$ac_eof _ACEOF # 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 cat >>$CONFIG_STATUS <<\_ACEOF fi # test -n "$CONFIG_FILES" for ac_tag in :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) { { echo "$as_me:$LINENO: error: Invalid tag $ac_tag." >&5 echo "$as_me: error: Invalid tag $ac_tag." >&2;} { (exit 1); exit 1; }; };; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || { { echo "$as_me:$LINENO: error: cannot find input file: $ac_f" >&5 echo "$as_me: error: cannot find input file: $ac_f" >&2;} { (exit 1); exit 1; }; };; esac ac_file_inputs="$ac_file_inputs $ac_f" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input="Generated from "`IFS=: echo $* | sed 's|^[^:]*/||;s|:[^:]*/|, |g'`" by configure." if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { echo "$as_me:$LINENO: creating $ac_file" >&5 echo "$as_me: creating $ac_file" >&6;} fi case $ac_tag in *:-:* | *:-) cat >"$tmp/stdin";; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` { as_dir="$ac_dir" case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || { { echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5 echo "$as_me: error: cannot create directory $as_dir" >&2;} { (exit 1); exit 1; }; }; } ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # case $INSTALL in [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; esac _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= case `sed -n '/datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p ' $ac_file_inputs` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { echo "$as_me:$LINENO: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF 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&@top_builddir@&$ac_top_builddir_sub&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t s&@INSTALL@&$ac_INSTALL&;t t $ac_datarootdir_hack " $ac_file_inputs | sed -f "$tmp/subs-1.sed" | sed -f "$tmp/subs-2.sed" >$tmp/out test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } && { echo "$as_me:$LINENO: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined." >&5 echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined." >&2;} rm -f "$tmp/stdin" case $ac_file in -) cat "$tmp/out"; rm -f "$tmp/out";; *) rm -f "$ac_file"; mv "$tmp/out" $ac_file;; esac ;; :H) # # CONFIG_HEADER # _ACEOF # Transform confdefs.h into a sed script `conftest.defines', that # substitutes the proper values into config.h.in to produce config.h. rm -f conftest.defines conftest.tail # First, append a space to every undef/define line, to ease matching. echo 's/$/ /' >conftest.defines # Then, protect against being on the right side of a sed subst, or in # an unquoted here document, in config.status. If some macros were # called several times there might be several #defines for the same # symbol, which is useless. But do not sort them, since the last # AC_DEFINE must be honored. ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* # These sed commands are passed to sed as "A NAME B PARAMS C VALUE D", where # NAME is the cpp macro being defined, VALUE is the value it is being given. # PARAMS is the parameter list in the macro definition--in most cases, it's # just an empty string. ac_dA='s,^\\([ #]*\\)[^ ]*\\([ ]*' ac_dB='\\)[ (].*,\\1define\\2' ac_dC=' ' ac_dD=' ,' uniq confdefs.h | sed -n ' t rset :rset s/^[ ]*#[ ]*define[ ][ ]*// t ok d :ok s/[\\&,]/\\&/g s/^\('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/ '"$ac_dA"'\1'"$ac_dB"'\2'"${ac_dC}"'\3'"$ac_dD"'/p s/^\('"$ac_word_re"'\)[ ]*\(.*\)/'"$ac_dA"'\1'"$ac_dB$ac_dC"'\2'"$ac_dD"'/p ' >>conftest.defines # Remove the space that was appended to ease matching. # Then replace #undef with comments. This is necessary, for # example, in the case of _POSIX_SOURCE, which is predefined and required # on some systems where configure will not decide to define it. # (The regexp can be short, since the line contains either #define or #undef.) echo 's/ $// s,^[ #]*u.*,/* & */,' >>conftest.defines # Break up conftest.defines: ac_max_sed_lines=50 # First sed command is: sed -f defines.sed $ac_file_inputs >"$tmp/out1" # Second one is: sed -f defines.sed "$tmp/out1" >"$tmp/out2" # Third one will be: sed -f defines.sed "$tmp/out2" >"$tmp/out1" # et cetera. ac_in='$ac_file_inputs' ac_out='"$tmp/out1"' ac_nxt='"$tmp/out2"' while : do # Write a here document: cat >>$CONFIG_STATUS <<_ACEOF # First, check the format of the line: cat >"\$tmp/defines.sed" <<\\CEOF /^[ ]*#[ ]*undef[ ][ ]*$ac_word_re[ ]*\$/b def /^[ ]*#[ ]*define[ ][ ]*$ac_word_re[( ]/b def b :def _ACEOF sed ${ac_max_sed_lines}q conftest.defines >>$CONFIG_STATUS echo 'CEOF sed -f "$tmp/defines.sed"' "$ac_in >$ac_out" >>$CONFIG_STATUS ac_in=$ac_out; ac_out=$ac_nxt; ac_nxt=$ac_in sed 1,${ac_max_sed_lines}d conftest.defines >conftest.tail grep . conftest.tail >/dev/null || break rm -f conftest.defines mv conftest.tail conftest.defines done rm -f conftest.defines conftest.tail echo "ac_result=$ac_in" >>$CONFIG_STATUS cat >>$CONFIG_STATUS <<\_ACEOF if test x"$ac_file" != x-; then echo "/* $configure_input */" >"$tmp/config.h" cat "$ac_result" >>"$tmp/config.h" if diff $ac_file "$tmp/config.h" >/dev/null 2>&1; then { echo "$as_me:$LINENO: $ac_file is unchanged" >&5 echo "$as_me: $ac_file is unchanged" >&6;} else rm -f $ac_file mv "$tmp/config.h" $ac_file fi else echo "/* $configure_input */" cat "$ac_result" fi rm -f "$tmp/out12" # Compute $ac_file's index in $config_headers. _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $ac_file | $ac_file:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $ac_file" >`$as_dirname -- $ac_file || $as_expr X$ac_file : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X$ac_file : 'X\(//\)[^/]' \| \ X$ac_file : 'X\(//\)$' \| \ X$ac_file : 'X\(/\)' \| . 2>/dev/null || echo X$ac_file | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'`/stamp-h$_am_stamp_count ;; :C) { echo "$as_me:$LINENO: executing $ac_file commands" >&5 echo "$as_me: executing $ac_file commands" >&6;} ;; esac case $ac_file$ac_mode in "depfiles":C) test x"$AMDEP_TRUE" != x"" || for mf in $CONFIG_FILES; do # Strip MF so we end up with the name of the file. mf=`echo "$mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile or not. # We used to match only the files named `Makefile.in', but # some people rename them; so instead we look at the file content. # Grep'ing the first line is not enough: some people post-process # each Makefile.in and add a new line on top of each file to say so. # So let's grep whole file. if grep '^#.*generated by automake' $mf > /dev/null 2>&1; then dirpart=`$as_dirname -- "$mf" || $as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$mf" : 'X\(//\)[^/]' \| \ X"$mf" : 'X\(//\)$' \| \ X"$mf" : 'X\(/\)' \| . 2>/dev/null || echo X"$mf" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` else continue fi # Extract the definition of DEPDIR, am__include, and am__quote # from the Makefile without running `make'. DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` test -z "$DEPDIR" && continue am__include=`sed -n 's/^am__include = //p' < "$mf"` test -z "am__include" && continue am__quote=`sed -n 's/^am__quote = //p' < "$mf"` # When using ansi2knr, U may be empty or an underscore; expand it U=`sed -n 's/^U = //p' < "$mf"` # Find all dependency output files, they are included files with # $(DEPDIR) in their names. We invoke sed twice because it is the # simplest approach to changing $(DEPDIR) to its actual value in the # expansion. for file in `sed -n " s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do # Make sure the directory exists. test -f "$dirpart/$file" && continue fdir=`$as_dirname -- "$file" || $as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$file" : 'X\(//\)[^/]' \| \ X"$file" : 'X\(//\)$' \| \ X"$file" : 'X\(/\)' \| . 2>/dev/null || echo X"$file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` { as_dir=$dirpart/$fdir case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || { { echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5 echo "$as_me: error: cannot create directory $as_dir" >&2;} { (exit 1); exit 1; }; }; } # echo "creating $dirpart/$file" echo '# dummy' > "$dirpart/$file" done done ;; "default-1":C) for ac_file in $CONFIG_FILES; do # Support "outfile[:infile[:infile...]]" case "$ac_file" in *:*) ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; esac # PO directories have a Makefile.in generated from Makefile.in.in. case "$ac_file" in */Makefile.in) # Adjust a relative srcdir. ac_dir=`echo "$ac_file"|sed 's%/[^/][^/]*$%%'` ac_dir_suffix="/`echo "$ac_dir"|sed 's%^\./%%'`" ac_dots=`echo "$ac_dir_suffix"|sed 's%/[^/]*%../%g'` # In autoconf-2.13 it is called $ac_given_srcdir. # In autoconf-2.50 it is called $srcdir. test -n "$ac_given_srcdir" || ac_given_srcdir="$srcdir" case "$ac_given_srcdir" in .) top_srcdir=`echo $ac_dots|sed 's%/$%%'` ;; /*) top_srcdir="$ac_given_srcdir" ;; *) top_srcdir="$ac_dots$ac_given_srcdir" ;; esac # Treat a directory as a PO directory if and only if it has a # POTFILES.in file. This allows packages to have multiple PO # directories under different names or in different locations. if test -f "$ac_given_srcdir/$ac_dir/POTFILES.in"; then rm -f "$ac_dir/POTFILES" test -n "$as_me" && echo "$as_me: creating $ac_dir/POTFILES" || echo "creating $ac_dir/POTFILES" cat "$ac_given_srcdir/$ac_dir/POTFILES.in" | sed -e "/^#/d" -e "/^[ ]*\$/d" -e "s,.*, $top_srcdir/& \\\\," | sed -e "\$s/\(.*\) \\\\/\1/" > "$ac_dir/POTFILES" POMAKEFILEDEPS="POTFILES.in" # ALL_LINGUAS, POFILES, UPDATEPOFILES, DUMMYPOFILES, GMOFILES depend # on $ac_dir but don't depend on user-specified configuration # parameters. if test -f "$ac_given_srcdir/$ac_dir/LINGUAS"; then # The LINGUAS file contains the set of available languages. if test -n "$OBSOLETE_ALL_LINGUAS"; then test -n "$as_me" && echo "$as_me: setting ALL_LINGUAS in configure.in is obsolete" || echo "setting ALL_LINGUAS in configure.in is obsolete" fi ALL_LINGUAS_=`sed -e "/^#/d" -e "s/#.*//" "$ac_given_srcdir/$ac_dir/LINGUAS"` # Hide the ALL_LINGUAS assigment from automake. 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 # for ac_tag { (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 ############################################################################### # (end-of-file) ############################################################################### hercules-3.07/configure.ac000644 000765 000765 00000220606 11344715214 017241 0ustar00jmaynardjmaynard000000 000000 ############################################################################### # CONFIGURE.AC: Process this file with AutoConf to produce a configure script. ############################################################################### # $Id: configure.ac 5657 2010-03-07 12:22:25Z jmaynard $ # AC is AutoConfigure, AM is AutoMake, and AH is AutoHeader. The # 'HC_XXXX..' macros are custom Hercules autoconf macros defined # in the 'hercules.m4' file in the 'autoconf' subdirectory. AC_INIT(hercules.h) # (package, version, bugreport email, etc) AC_REVISION($Revision: 5657 $) # (the version of this configure.ac) AC_CONFIG_AUX_DIR(autoconf) # (directory containing auxillary build tools) AM_INIT_AUTOMAKE(hercules,3.07) # (the version of our software package) AM_CONFIG_HEADER(config.h) # (the file the resulting configure script will produce) AM_MAINTAINER_MODE() AC_CANONICAL_HOST() # (sets $host_cpu, $host_vendor, and $host_os) ############################################################################### # Programs section... ############################################################################### #HC_PROG_CC() # ((( DEPRECATED ))) # # CFLAGS *MUST* BE SET 1ST - BEFORE CALL AC_PROG_CC OTHERWISE AUTOCONF TRIES TO IMPOSE # ITS OWN CHOICES... # FIXME : # Unfortunatelly, these are gcc flags.. so going to have # to find something better... # CFLAGS="$CFLAGS -W -Wall" AC_PROG_CC() # (back to using this again) # ----------------------------------------------------------------------------- # PROGRAMMING NOTE: The below 'AC_SUBST' macro causes AC_OUTPUT to replace # all instances of "@xxxxxx@" in input files with the value that the shell # variable "xxxxxx" has when AC_OUTPUT is called. Thus, the variable name # used ("modexecdir" in our case) *is* significant and cannot be changed # unless you change the "@modexecdir@" strings in all of the input files. # ----------------------------------------------------------------------------- modexecdir=${libdir}/${PACKAGE} AC_SUBST(modexecdir) # ----------------------------------------------------------------------------- # # AC_LIBTOOL_DLOPEN # # Enable checking for dlopen support. This macro should be used if the # package makes use of the '-dlopen' and '-dlpreopen' flags, otherwise # libtool will assume that the system does not support dlopening. The # macro must be called before AC_PROG_LIBTOOL. # # ----------------------------------------------------------------------------- AC_LIBTOOL_DLOPEN() # (we need libtool's dlopen support) # ----------------------------------------------------------------------------- # # AC_LIBTOOL_WIN32_DLL # # This macro should be used if the package has been ported to build # clean dlls on win32 platforms. Usually this means that any library # data items are exported with __declspec(dllexport) and imported with # __declspec(dllimport). If this macro is not used, libtool will assume # that the package libraries are not dll clean and will build only static # libraries on win32 hosts. # # This macro must be called before AC_PROG_LIBTOOL, and provision must # be made to pass '-no-undefined' to libtool in link mode from the package # Makefile. Naturally, if you pass '-no-undefined', you must ensure that # all the library symbols really are defined at link time! # # ----------------------------------------------------------------------------- AC_LIBTOOL_WIN32_DLL() # (we need Win32 support in libtool) # ----------------------------------------------------------------------------- # See: 'AC_PROG_LIBTOOL' below. # ----------------------------------------------------------------------------- AC_DISABLE_STATIC() # (forces libtool to build shared # libraries instead of static ones) # ----------------------------------------------------------------------------- # AC_PROG_LIBTOOL # # Add support for the '--enable-shared' and '--disable-shared' # configure flags. By default, this macro turns on shared libraries # if they are available, and also enables static libraries if they # don't conflict with the shared libraries. You can modify these # defaults by calling either the AC_DISABLE_SHARED or AC_DISABLE_STATIC # macros. # # Hercules REQUIRES shared libraries (i.e. DLLs), so we do indeed use # the AC_DISABLE_STATIC macro above. # # ----------------------------------------------------------------------------- AC_PROG_LIBTOOL() # (we build libtool for ourselves) # ----------------------------------------------------------------------------- # # AC_LIB_LTDL # # Even though libltdl is installed together with libtool, you may wish # to include libltdl in the distribution of your package, for the convenience # of users of your package that don't have libtool or libltdl installed. # # The most simplistic way to add libltdl to your package is to copy the # source files, 'ltdl.c' and 'ltdl.h', to a source directory withing your # package and to build and link them along with the rest of your sources. # # To do this, you must add a call to the 'AC_LIB_LTDL' macro to your package's # 'configure.in' to perform the required configure time checks in order that # 'ltdl.o' is built correctly. # # This method does have its problems though: if you try to link the package # binaries with an installed libltdl, or a library which depends on libltdl, # you may have problems with duplicate symbol definitions. # # In order to enable this flavor of libltdl, you should add the line # 'AC_LIBLTDL_CONVENIENCE' to your `configure.in', before 'AC_PROG_LIBTOOL'. # # In order to select the installable version of libltdl, you should add a # call of the macro 'AC_LIBLTDL_INSTALLABLE' to your 'configure.in' before # 'AC_PROG_LIBTOOL'. This macro will check whether libltdl is already # installed and, if not, request the libltdl embedded in your package to be # built and installed. # # Whatever macro you use, it is up to you to ensure that your 'configure.in' # will configure libltdl, using 'AC_CONFIG_SUBDIRS', and that your 'Makefile's # will start sub-makes within libltdl's directory, using automake's SUBDIRS, # for example. Both macros define the shell variables LIBLTDL, to the link flag # that you should use to link with libltdl, and LTDLINCL, to the preprocessor # flag that you should use to compile with programs that include 'ltdl.h'. It # is up to you to use 'AC_SUBST' to ensure that this variable will be available # in 'Makefile's, or add them to variables that are 'AC_SUBST'ed by default, # such as LIBS and CPPFLAGS. # # So, when you want to link a program with libltdl, be it a convenience, # installed or installable library, just compile with '$(LTDLINCL)' and link # it with '$(LIBLTDL)', using libtool. # # You should probably also add 'AC_LIBTOOL_DLOPEN' to your 'configure.in' before # 'AC_PROG_LIBTOOL', otherwise libtool will assume no dlopening mechanism is # supported, and revert to dlpreopening, which is probably not what you want. # # The following example shows you how to embed the convenience libltdl # in your package. In order to use the installable variant just replace # 'AC_LIBLTDL_CONVENIENCE' with 'AC_LIBLTDL_INSTALLABLE'. We assume that libltdl # was embedded using 'libtoolize --ltdl': # # configure.in: # # ... # dnl Enable building of the convenience library # dnl and set LIBLTDL accordingly # AC_LIBLTDL_CONVENIENCE # dnl Substitute LTDLINCL and LIBLTDL in the Makefiles # AC_SUBST(LTDLINCL) # AC_SUBST(LIBLTDL) # dnl Check for dlopen support # AC_LIBTOOL_DLOPEN # dnl Configure libtool # AC_PROG_LIBTOOL # dnl Configure libltdl # AC_CONFIG_SUBDIRS(libltdl) # ... # # Makefile.am: # # ... # SUBDIRS = libltdl # # INCLUDES = $(LTDLINCL) # # myprog_LDFLAGS = -export-dynamic # # The quotes around -dlopen below fool automake <= 1.4 into accepting it # myprog_LDADD = $(LIBLTDL) "-dlopen" self "-dlopen" foo1.la # myprog_DEPENDENCIES = $(LIBLTDL) foo1.la # ... # # ----------------------------------------------------------------------------- AC_LIB_LTDL() # (we need the ltdl libtool library) AC_SUBST([LIBTOOL_DEPS]) # (see PROGRAMMING NOTE above) # ----------------------------------------------------------------------------- # (See comments in the 'AC_CHECK_LIB' Libraries section further below) # ----------------------------------------------------------------------------- AC_MSG_NOTICE( [(use of lt_dlopen forced by Hercules Dynamic Loader requirement)] ) hc_cv_have_lt_dlopen=yes AM_GNU_GETTEXT([external]) # AM_ICONV HC_LD_DISALLOWDUPS() # (add duplicate symbols option to LDFLAGS) # ----------------------------------------------------------------------------- # The following is a "global error" flag used to defer aborting configure # until after ALL errors have been detected/reported. # ----------------------------------------------------------------------------- hc_error=no ############################################################################### # Autoheader templates ############################################################################### # All AC_DEFINE() macros used within autoconf (to define pre-processor vars # used during the actual build process) must have corresponding AH_TEMPLATE # statements coded somewhere. We place them all here simply for convenience. AH_TEMPLATE( [CUSTOM_BUILD_STRING], [Define to provide additional information about this build] ) AH_TEMPLATE( [MAX_CPU_ENGINES], [Defines the maximum number of emulated CPU engines] ) AH_TEMPLATE( [PKGDATADIR], [Directory where the HTTP server will find documents] ) AH_TEMPLATE( [HERC_LOCALEDIR], [Directory where to find NLS data] ) AH_TEMPLATE( [MODULESDIR], [Directory where HERCULES modules are installed] ) AH_TEMPLATE( [DEBUG], [Define to enable extra debugging code (TRACE/VERIFY/ASSERT macros)] ) AH_TEMPLATE( [C99_FLEXIBLE_ARRAYS], [Define if your gcc properly supports C99 flexible arrays] ) AH_TEMPLATE( [HAVE_ATTR_REGPARM], [Define if your gcc properly supports __attribute__((regparm(n)))] ) AH_TEMPLATE( [NO_ASM_BYTESWAP], [Define to disable assembler routines for byte swapping] ) AH_TEMPLATE( [NO_IEEE_SUPPORT], [Define to disable IEEE floating point support] ) AH_TEMPLATE( [NO_SETUID], [Define to disable setuid operation] ) AH_TEMPLATE( [NO_SIGABEND_HANDLER], [Define to disable sigabend_handler (please describe this better)] ) AH_TEMPLATE( [NON_UNIQUE_GETTIMEOFDAY], [Define if 'gettimeofday' returns non-unique values] ) AH_TEMPLATE( [NEED_GETOPT_WRAPPER], [Define to indicate a wrapper for getopt is needed] ) AH_TEMPLATE( [NEED_GETOPT_OPTRESET], [Define to indicate optreset exists] ) AH_TEMPLATE( [HAVE_INTTYPES_H], [Define if inttypes.h header file is present on your system] ) AH_TEMPLATE( [HAVE_U_INT], [Define if your system uses u_int8_t, etc, instead of uint8_t] ) AH_TEMPLATE( [OPTION_CONFIG_SYMBOLS], [Define to enable symbolic substitutions in configuration file] ) AH_TEMPLATE( [OPTION_ENHANCED_CONFIG_SYMBOLS], [Define to enable enhanced-mode symbolic substitutions in configuration file] ) AH_TEMPLATE( [OPTION_ENHANCED_CONFIG_INCLUDE], [Define to enable enhanced-mode 'include' file support in configuration file] ) AH_TEMPLATE( [OPTION_HAO], [Define to enable Hercules Automatic Operator feature] ) AH_TEMPLATE( [OPTION_DYNAMIC_LOAD], [Define to enable Hercules Dynamic Loader feature] ) AH_TEMPLATE( [HDL_BUILD_SHARED], [Define to indicate shared libraries are being used] ) AH_TEMPLATE( [HDL_USE_LIBTOOL], [Define to cause dynamic loader to use libtool instead of dlopen] ) AH_TEMPLATE( [BUILD_HERCIFC], [Define if hercifc program is to be built] ) AH_TEMPLATE( [WIN32], [Define when building under Win32 (MinGW or Cygwin)] ) AH_TEMPLATE( [EXTERNALGUI], [Define to build interface to external Windows GUI] ) AH_TEMPLATE( [OPTION_FTHREADS], [Define to use included threads implementation (fthreads)] ) AH_TEMPLATE( [FISH_HANG], [Define to debug correct fthreads LOCK handling (requires fthreads)] ) AH_TEMPLATE( [TIMESPEC_IN_TIME_H], [Define if 'struct timespec' defined in ] ) AH_TEMPLATE( [TIMESPEC_IN_SYS_TYPES_H], [Define if 'struct timespec' defined in ] ) AH_TEMPLATE( [_BSD_SOCKLEN_T_], [Define missing macro on apple darwin (osx) platform] ) AH_TEMPLATE( [_INTL_REDIRECT_MACROS], [Define to 1 if non-Intel architecture (gettext)] ) AH_TEMPLATE( [CCKD_BZIP2], [Define to enable bzip2 compression in emulated DASDs] ) AH_TEMPLATE( [HET_BZIP2], [Define to enable bzip2 compression in emulated tapes] ) AH_TEMPLATE( [OPTION_CAPABILITIES], [Define to enable posix draft 1003.1e capabilities] ) ############################################################################### # OS-specific settings that we can't figure out any other way (yet) ############################################################################### # # Determine what type of host we're building on... # case "$host_os" in linux*) hc_cv_is_nix=yes hc_cv_is_windows=no hc_cv_is_mingw32=no hc_cv_is_apple=no ;; mingw*) hc_cv_is_nix=no hc_cv_is_windows=yes hc_cv_is_mingw32=yes hc_cv_is_apple=no ;; cygwin*) hc_cv_is_nix=no hc_cv_is_windows=yes hc_cv_is_mingw32=no hc_cv_is_apple=no ;; darwin*) if test $host_vendor = apple; then hc_cv_is_nix=no hc_cv_is_windows=no hc_cv_is_mingw32=no hc_cv_is_apple=yes else hc_cv_is_nix=no hc_cv_is_windows=no hc_cv_is_mingw32=no hc_cv_is_apple=no fi ;; *bsd*) hc_cv_is_nix=yes hc_cv_is_windows=no hc_cv_is_mingw32=no hc_cv_is_apple=no ;; *) hc_cv_is_nix=no hc_cv_is_windows=no hc_cv_is_mingw32=no hc_cv_is_apple=no ;; esac #------------------------------------------------------# # Hard-coded host-operating-system-specific settings # # that we have no other/easy way to figure out... # #------------------------------------------------------# if test "$hc_cv_is_nix" = "yes"; then hc_cv_build_hercifc=yes hc_cv_non_unique_gettimeofday=no elif test "$hc_cv_is_windows" = "yes"; then hc_cv_build_hercifc=no hc_cv_non_unique_gettimeofday=yes elif test "$hc_cv_is_apple" = "yes"; then hc_cv_build_hercifc=yes hc_cv_non_unique_gettimeofday=no else hc_cv_build_hercifc=no hc_cv_non_unique_gettimeofday=no fi ############################################################################### # Checks for REQUIRED (non-optional) header files... ############################################################################### # PROGRAMMING NOTE: We use 'AC_CHECK_HEADER' here (singular) since we don't # care whether 'HAVE_XXX' gets #defined or not since, because these are re- # quired headers, if any of them are not found, we abort and thus we don't # need to have any 'HAVE_XXX' pre-processor #defined entered into config.h # (because we can't build Herc at all if any of them don't happen to exist) AC_CHECK_HEADER( ctype.h, [], [ AC_MSG_RESULT( [ERROR: Required header 'ctype.h' not found] ); hc_error=yes ] ) AC_CHECK_HEADER( errno.h, [], [ AC_MSG_RESULT( [ERROR: Required header 'errno.h' not found] ); hc_error=yes ] ) AC_CHECK_HEADER( fcntl.h, [], [ AC_MSG_RESULT( [ERROR: Required header 'fcntl.h' not found] ); hc_error=yes ] ) AC_CHECK_HEADER( limits.h, [], [ AC_MSG_RESULT( [ERROR: Required header 'limits.h' not found] ); hc_error=yes ] ) AC_CHECK_HEADER( setjmp.h, [], [ AC_MSG_RESULT( [ERROR: Required header 'setjmp.h' not found] ); hc_error=yes ] ) AC_CHECK_HEADER( stdarg.h, [], [ AC_MSG_RESULT( [ERROR: Required header 'stdarg.h' not found] ); hc_error=yes ] ) AC_CHECK_HEADER( stdio.h, [], [ AC_MSG_RESULT( [ERROR: Required header 'stdio.h' not found] ); hc_error=yes ] ) AC_CHECK_HEADER( stdlib.h, [], [ AC_MSG_RESULT( [ERROR: Required header 'stdlib.h' not found] ); hc_error=yes ] ) AC_CHECK_HEADER( string.h, [], [ AC_MSG_RESULT( [ERROR: Required header 'string.h' not found] ); hc_error=yes ] ) AC_CHECK_HEADER( time.h, [], [ AC_MSG_RESULT( [ERROR: Required header 'time.h' not found] ); hc_error=yes ] ) AC_CHECK_HEADER( unistd.h, [], [ AC_MSG_RESULT( [ERROR: Required header 'unistd.h' not found] ); hc_error=yes ] ) AC_CHECK_HEADER( sys/stat.h, [], [ AC_MSG_RESULT( [ERROR: Required header 'sys/stat.h' not found] ); hc_error=yes ] ) AC_CHECK_HEADER( sys/time.h, [], [ AC_MSG_RESULT( [ERROR: Required header 'sys/time.h' not found] ); hc_error=yes ] ) AC_CHECK_HEADER( sys/types.h, [], [ AC_MSG_RESULT( [ERROR: Required header 'sys/types.h' not found] ); hc_error=yes ] ) # PROGRAMMING NOTE: the pthread.h header only required if this is not # an fthreads build. Thus we delay aborting until later once we know # (if this is a windows build; otherwise we abort right away) AC_CHECK_HEADER( pthread.h, [hc_cv_have_pthread_h=yes], [ if test "$hc_cv_is_windows" = "yes"; then hc_cv_alt_pthread_location=/usr/Pthreads AC_MSG_NOTICE( [looking for pthread.h in ${hc_cv_alt_pthread_location}] ) hc_temp=$CFLAGS CFLAGS="$CFLAGS -I${hc_cv_alt_pthread_location}" AC_CHECK_HEADER( pthread.h, [hc_cv_have_pthread_h=yes], [hc_cv_have_pthread_h=no] ) CFLAGS=$hc_temp else AC_MSG_RESULT( [ERROR: Required header 'pthread.h' not found] ) hc_error=yes fi ] ) AC_CACHE_SAVE() ############################################################################### # Checks for optional (non-required) header files... ############################################################################### # PROGRAMMING NOTE: We use 'AC_CHECK_HEADERS' here (plural) to cause autoconf # to automatically add a #define/#undef 'HAVE_XXX' statement into config.h to # let us know whether the header exists on this system or not (since, because # these are optional headers, we are still able to successfully build Herc if # they don't happen to exist). The 'hc_cv_have_xxx' variables are only defined # in case other parts of configure.ac need to know whether the header exists # or not without having to do their own AC_CHECK_HEADERS (since we've already # done it). #------------------------------------------------------------------------------ # PROGRAMMING NOTE: on Darwin sys/socket.h must be included before # net/if.h, net/route.h, or netinet/in.h can be #included, and on OS X 10.3 # (but not 10.4) sys/types.h must be #included before sys/socket.h. Thus # the below four header checks are treated specially. If we ever drop support # for OS X 10.3, a lot of this cruft can be removed, not just here but # anywhere we find ourselves manually including sys/types.h. # PROGRAMMING NOTE: on *BSD sys/socket.h must be included before net/if.h, # net/route.h, or netinet/in.h can be #included. AC_CHECK_HEADERS( sys/socket.h, [hc_cv_have_sys_socket_h=yes], [hc_cv_have_sys_socket_h=no], [ #include ] ) AC_CHECK_HEADERS( net/if.h, [hc_cv_have_net_if_h=yes], [hc_cv_have_net_if_h=no], [ #include #if HAVE_SYS_SOCKET_H #include #endif ] ) AC_CHECK_HEADERS( netinet/in.h, [hc_cv_have_netinet_in_h=yes], [hc_cv_have_netinet_in_h=no], [ #include #if HAVE_SYS_SOCKET_H #include #endif ] ) AC_CHECK_HEADERS( netinet/tcp.h, [hc_cv_have_netinet_tcp_h=yes], [hc_cv_have_netinet_tcp_h=no], [ #include #if HAVE_SYS_SOCKET_H #include #endif ] ) AC_CHECK_HEADERS( net/route.h, [hc_cv_have_net_route_h=yes], [hc_cv_have_net_route_h=no], [ #include #if HAVE_SYS_SOCKET_H #include #endif ] ) #------------------------------------------------------------------------------ AC_CHECK_HEADERS( arpa/inet.h, [hc_cv_have_arpa_inet_h=yes], [hc_cv_have_arpa_inet_h=no] ) AC_CHECK_HEADERS( linux/if_tun.h, [hc_cv_have_linux_if_tun_h=yes], [hc_cv_have_linux_if_tun_h=no] ) AC_CHECK_HEADERS( sys/ioctl.h, [hc_cv_have_sys_ioctl_h=yes], [hc_cv_have_sys_ioctl_h=no] ) AC_CHECK_HEADERS( sys/mman.h, [hc_cv_have_sys_mman_h=yes], [hc_cv_have_sys_mman_h=no] ) #------------------------------------------------------------------------------ # PROGRAMMING NOTE: on *BSD systems sys/param.h must be #included before # sys/mount.h as it contains the #define of NGROUPS. AC_CHECK_HEADERS( sys/param.h, [hc_cv_have_sys_param_h=yes], [hc_cv_have_sys_param_h=no] ) AC_CHECK_HEADERS( sys/mount.h, [hc_cv_have_sys_mount_h=yes], [hc_cv_have_sys_mount_h=no], [ #if HAVE_SYS_PARAM_H #include #endif ] ) #------------------------------------------------------------------------------ AC_CHECK_HEADERS( sys/mtio.h, [hc_cv_have_sys_mtio_h=yes], [hc_cv_have_sys_mtio_h=no] ) AC_CHECK_HEADERS( sys/resource.h, [hc_cv_have_sys_resource_h=yes], [hc_cv_have_sys_resource_h=no] ) AC_CHECK_HEADERS( sys/uio.h, [hc_cv_have_sys_uio_h=yes], [hc_cv_have_sys_uio_h=no] ) AC_CHECK_HEADERS( sys/utsname.h, [hc_cv_have_sys_utsname_h=yes], [hc_cv_have_sys_utsname_h=no] ) AC_CHECK_HEADERS( sys/wait.h, [hc_cv_have_sys_wait_h=yes], [hc_cv_have_sys_wait_h=no] ) AC_CHECK_HEADERS( sys/un.h, [hc_cv_have_sys_un_h=yes], [hc_cv_have_sys_un_h=no] ) AC_CHECK_HEADERS( byteswap.h, [hc_cv_have_byteswap_h=yes], [hc_cv_have_byteswap_h=no] ) AC_CHECK_HEADERS( bzlib.h, [hc_cv_have_bzlib_h=yes], [hc_cv_have_bzlib_h=no] ) AC_CHECK_HEADERS( dlfcn.h, [hc_cv_have_dlfcn_h=yes], [hc_cv_have_dlfcn_h=no] ) AC_CHECK_HEADERS( fenv.h, [hc_cv_have_fenv_h=yes], [hc_cv_have_fenv_h=no] ) AC_CHECK_HEADERS( inttypes.h, [hc_cv_have_inttypes_h=yes], [hc_cv_have_inttypes_h=no] ) AC_CHECK_HEADERS( iconv.h, [hc_cv_have_iconv_h=yes], [hc_cv_have_iconv_h=no] ) AC_CHECK_HEADERS( libintl.h, [hc_cv_have_libintl_h=yes], [hc_cv_have_libintl_h=no] ) AC_CHECK_HEADERS( locale.h, [hc_cv_have_locale_h=yes], [hc_cv_have_locale_h=no] ) AC_CHECK_HEADERS( ltdl.h, [hc_cv_have_ltdl_h=yes], [hc_cv_have_ltdl_h=no] ) AC_CHECK_HEADERS( malloc.h, [hc_cv_have_malloc_h=yes], [hc_cv_have_malloc_h=no] ) AC_CHECK_HEADERS( math.h, [hc_cv_have_math_h=yes], [hc_cv_have_math_h=no] ) AC_CHECK_HEADERS( netdb.h, [hc_cv_have_netdb_h=yes], [hc_cv_have_netdb_h=no] ) AC_CHECK_HEADERS( pwd.h, [hc_cv_have_pwd_h=yes], [hc_cv_have_pwd_h=no] ) AC_CHECK_HEADERS( regex.h, [hc_cv_have_regex_h=yes], [hc_cv_have_regex_h=no] ) AC_CHECK_HEADERS( sched.h, [hc_cv_have_sched_h=yes], [hc_cv_have_sched_h=no] ) AC_CHECK_HEADERS( signal.h, [hc_cv_have_signal_h=yes], [hc_cv_have_signal_h=no] ) AC_CHECK_HEADERS( termios.h, [hc_cv_have_termios_h=yes], [hc_cv_have_termios_h=no] ) AC_CHECK_HEADERS( time.h, [hc_cv_have_time_h=yes], [hc_cv_have_time_h=no] ) AC_CHECK_HEADERS( zlib.h, [hc_cv_have_zlib_h=yes], [hc_cv_have_zlib_h=no] ) AC_CHECK_HEADERS( sys/capability.h, [hc_cv_have_sys_capa_h=yes], [hc_cv_have_sys_capa_h=no] ) AC_CHECK_HEADERS( sys/prctl.h, [hc_cv_have_sys_prctl_h=yes], [hc_cv_have_sys_prctl_h=no] ) AC_CACHE_SAVE() ############################################################################### # Checks for declarations... ############################################################################### # PROGRAMMING NOTE: For declaration checks, you need to be careful to use the # following test in your program: # # #if defined(HAVE_DECL_XXXX) && !HAVE_DECL_XXXXX # ...code to handle not declared case... # #endif # # This is because UNLIKE other 'AC_CHECK' macros, when a SYMBOL isn't DECLared, # "HAVE_DECL_XXXX" is #defined to '0' instead of leaving "HAVE_DECL_XXXX" #undefined. # (e.g. #defined to 1 if you have the declaration and #defined to 0 if you don't) AC_CHECK_DECLS( SIGUSR1, [hc_cv_have_sigusr1=yes], [hc_cv_have_sigusr1=no], [#include ] ) AC_CHECK_DECLS( SIGUSR2, [hc_cv_have_sigusr2=yes], [hc_cv_have_sigusr2=no], [#include ] ) AC_CHECK_DECLS( SIGPIPE, [hc_cv_have_sigpipe=yes], [hc_cv_have_sigpipe=no], [#include ] ) AC_CHECK_DECLS( SIGBUS, [hc_cv_have_sigbus=yes], [hc_cv_have_sigbus=no], [#include ] ) AC_CHECK_DECLS( IFNAMSIZ, [hc_cv_have_ifnamsiz=yes], [hc_cv_have_ifnamsiz=no], [ #include #if HAVE_SYS_SOCKET_H #include #endif ] ) AC_CHECK_DECLS( LOGIN_NAME_MAX, [hc_cv_have_login_name_max=yes], [hc_cv_have_login_name_max=no], [#include ] ) AC_CHECK_DECLS( _SC_NPROCESSORS_CONF, [hc_cv_have_sc_nprocessors_conf=yes], [hc_cv_have_sc_nprocessors_conf=no], [#include ] ) AC_CHECK_DECLS( _SC_NPROCESSORS_ONLN, [hc_cv_have_sc_nprocessors_onln=yes], [hc_cv_have_sc_nprocessors_onln=no], [#include ] ) AC_CHECK_DECLS( SIOCSIFNETMASK, [hc_cv_have_siocsifnetmask=yes], [hc_cv_have_siocsifnetmask=no], [#include ] ) AC_CHECK_DECLS( SIOCSIFHWADDR, [hc_cv_have_siocsifhwaddr=yes], [hc_cv_have_siocsifhwaddr=no], [#include ] ) AC_CHECK_DECLS( SIOCADDRT, [hc_cv_have_siocaddrt=yes], [hc_cv_have_siocaddrt=no], [#include ] ) AC_CHECK_DECLS( SIOCDELRT, [hc_cv_have_siocdelrt=yes], [hc_cv_have_siocdelrt=no], [#include ] ) AC_CHECK_DECLS( SIOCDIFADDR, [hc_cv_have_siocdifaddr=yes], [hc_cv_have_siocdifaddr=no], [#include ] ) if test "$hc_cv_have_sys_mtio_h" == "yes"; then AC_CHECK_DECLS( MTEWARN, [hc_cv_have_mtewarn=yes], [hc_cv_have_mtewarn=no], [#include ] ) else hc_cv_have_mtewarn=no fi AC_CACHE_SAVE() ############################################################################### # Checks for types... ############################################################################### AC_CHECK_TYPES( u_int8_t, [hc_cv_have_u_int8_t=yes], [hc_cv_have_u_int8_t=no] ) AC_CHECK_TYPES( useconds_t, [hc_cv_have_useconds_t=yes], [hc_cv_have_useconds_t=no] ) AC_CHECK_TYPES( id_t, [hc_cv_have_id_t=yes], [hc_cv_have_id_t=no] ) AC_CHECK_TYPES( u_char, [hc_cv_have_u_char=yes], [hc_cv_have_u_char=no], [ #include #if HAVE_SYS_SOCKET_H #include #endif ] ) AC_CHECK_TYPES( u_short, [hc_cv_have_u_short=yes], [hc_cv_have_u_short=no], [ #include #if HAVE_SYS_SOCKET_H #include #endif ] ) AC_CHECK_TYPES( u_int, [hc_cv_have_u_int=yes], [hc_cv_have_u_int=no], [ #include #if HAVE_SYS_SOCKET_H #include #endif ] ) AC_CHECK_TYPES( u_long, [hc_cv_have_u_long=yes], [hc_cv_have_u_long=no], [ #include #if HAVE_SYS_SOCKET_H #include #endif ] ) AC_CHECK_TYPES( in_addr_t, [hc_cv_have_in_addr_t=yes], [hc_cv_have_in_addr_t=no], [ #include #if HAVE_SYS_SOCKET_H #include #endif #if HAVE_NETINET_IN_H #include #endif ] ) AC_CHECK_TYPES( socklen_t, [hc_cv_have_socklen_t=yes], [hc_cv_have_socklen_t=no], [ #include #if HAVE_SYS_SOCKET_H #include #endif ] ) AC_CACHE_SAVE() ############################################################################### # Checks for libraries... ############################################################################### # PROGRAMMING NOTE: we require libtool (or, optionally, dlltool (a less power- # ful (flexible) libtool-like tool for Windows platforms) in order to support # OPTION_DYNAMIC_LOAD. This is a relatively safe requirement since we provide # a version of libtool with Hercules (and build it as part of the preliminary # autoconf processing; see the 'Programs' section above). However, we need to # keep the below check for 'dlopen' anyway since we prefer that libtool use it # instead of its own equivalent (lt_dlopen) if it's available. AC_CHECK_LIB( msvcrt, _pipe ) AC_CHECK_LIB( dl, dlopen ) AC_CHECK_LIB( m, sqrt ) AC_CHECK_LIB( socket, connect ) AC_CHECK_LIB( nsl, gethostbyname ) AC_CHECK_LIB( resolv, inet_aton ) AC_CHECK_LIB( z, uncompress ) AC_CHECK_LIB( bz2, BZ2_bzBuffToBuffDecompress, [ hc_cv_have_libbz2=yes ], [ hc_cv_have_libbz2=no ] ) AC_CHECK_LIB( iconv, iconv ) # jbs 10/15/2003 Solaris requires -lrt for sched_yield() and fdatasync() AC_CHECK_LIB( rt, sched_yield ) # rbowler 2008/03/10 rev 1.196 Solaris 2.9 requires -lpthread AC_CHECK_LIB( pthread,pthread_create ) AC_CACHE_SAVE() ############################################################################### # Checks for library functions... ############################################################################### # PROGRAMMING NOTE: AC_CHECK_LIB should be called first for the below # library function checks to ensure the library where the function is # defined gets added to the LIBS library search variable... ############################################################################### AC_CHECK_FUNCS( iconv ) AC_CHECK_FUNCS( memrchr ) AC_CHECK_FUNCS( getopt_long ) AC_CHECK_FUNCS( sqrtl ldexpl fabsl fmodl frexpl ) AC_CHECK_FUNCS( ldexpf frexpf fabsf rint ) AC_CHECK_FUNCS( strlcpy strlcat ) AC_CHECK_FUNCS( strerror_r ) AC_CHECK_FUNCS( strsignal, [hc_cv_have_strsignal=yes], [hc_cv_have_strsignal=no] ) AC_CHECK_FUNCS( sys_siglist ) AC_CHECK_FUNCS( InitializeCriticalSectionAndSpinCount ) AC_CHECK_FUNCS( sleep usleep nanosleep ) AC_CHECK_FUNCS( sched_yield ) AC_CHECK_FUNCS( strtok_r ) AC_CHECK_FUNCS( pipe ) AC_CHECK_FUNCS( gettimeofday ) AC_CHECK_FUNCS( getpgrp ) AC_CHECK_FUNCS( scandir alphasort ) AC_CHECK_FUNCS( getlogin getlogin_r ) AC_CHECK_FUNCS( realpath ) AC_CHECK_FUNCS( fdatasync fsync ftruncate ) AC_CHECK_FUNCS( inet_aton ) AC_CHECK_FUNCS( fork socketpair ) AC_CHECK_FUNCS( sysconf ) AC_CHECK_FUNCS( vsscanf, [hc_cv_have_vsscanf=yes], [hc_cv_have_vsscanf=no] ) AC_CHECK_FUNCS( setresuid getresuid, [hc_cv_have_getset_uid=yes], [hc_cv_have_getset_uid=no; break] ) if test "$hc_cv_have_getset_uid" != "yes"; then AC_CHECK_FUNCS( setreuid geteuid getuid, [hc_cv_have_getset_uid=yes], [hc_cv_have_getset_uid=no; break] ) fi # FIXME: Disabled because some builtin ffs seem to be causing a problem. # (gcc 3.4 barfs on certain 'march=' settings?) #AC_CHECK_FUNCS( ffs ) # For OS X 10.6 autoconf defines HAVE_FDATASYNC even though there is # no function prototype declared for fdatasync() and unistd.h contains # define _POSIX_SYNCHRONIZED_IO (-1) which indicates that fdatasync is # not supported. So to decide whether fdatasync really can be used, we # create a new symbol HAVE_FDATASYNC_SUPPORTED which is defined only if # HAVE_FDATASYNC is defined and _POSIX_SYNCHRONIZED_IO is not negative. AC_CACHE_CHECK([whether fdatasync is supported],[ac_cv_func_fdatasync_supported],[ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include ]],[[ #if !defined(HAVE_FDATASYNC) #error fdatasync is not defined on this platform #endif #if defined(_POSIX_SYNCHRONIZED_IO) && (_POSIX_SYNCHRONIZED_IO+0 < 0) #error fdatasync is not supported on this platform #endif ]])], [ac_cv_func_fdatasync_supported=yes], [ac_cv_func_fdatasync_supported=no]) ]) AS_IF([test "x${ac_cv_func_fdatasync_supported}" = "xyes"], [AC_DEFINE([HAVE_FDATASYNC_SUPPORTED],[1],[Define to 1 if the fdatasync function is supported.])]) AC_CACHE_SAVE() ############################################################################### # Checks for structures and structure members... ############################################################################### AC_CHECK_MEMBERS( [struct sockaddr_in.sin_len], [hc_cv_have_sockaddr_in_sin_len=yes ], [hc_cv_have_sockaddr_in_sin_len=no ], [ #include #if HAVE_SYS_SOCKET_H #include #endif #if HAVE_NETINET_IN_H #include #endif ] ) AC_CHECK_MEMBERS( [struct in_addr.s_addr], [hc_cv_have_in_addr_s_addr=yes ], [hc_cv_have_in_addr_s_addr=no ], [ #include #if HAVE_SYS_SOCKET_H #include #endif #if HAVE_NETINET_IN_H #include #endif ] ) AC_CHECK_MEMBERS( [struct sigaction.sa_sigaction], [hc_cv_have_sa_sigaction=yes ], [hc_cv_have_sa_sigaction=no ], [#include ] ) AC_CHECK_MEMBERS( [struct timespec.tv_nsec], [ hc_cv_timespec_in_sys_types_h=yes hc_cv_timespec_in_time_h=no ], [ AC_CHECK_MEMBERS( [struct timespec.tv_nsec], [ hc_cv_timespec_in_sys_types_h=no hc_cv_timespec_in_time_h=yes ], [ hc_cv_timespec_in_sys_types_h=no hc_cv_timespec_in_time_h=no ], [#include ] ) ], [#include ] ) AC_CACHE_SAVE() ############################################################################### # Checks for compiler characteristics... ############################################################################### AC_C_BIGENDIAN() # PROGRAMMING NOTE: Okay, this is stupid. If there are any trailing spaces # following the type we're checking the size of, then they're converted to # underscores in the 'SIZEOF_XXXX' that gets #defined! For example, doing a # AC_CHECK_SIZEOF( int ) yields: #define SIZEOF_INT____ 4 !!!!!!!!!!!!! # So... the below AC_CHECK_SIZEOF macros must NOT have any spaces in them!! AC_CHECK_SIZEOF(int) AC_CHECK_SIZEOF(long) AC_CHECK_SIZEOF(size_t) AC_CHECK_SIZEOF(int *) AC_CHECK_SIZEOF(off_t) #----------------------------------# # Structure alignment/size test # #----------------------------------# AC_MSG_NOTICE( [begin check: whether byte structs are aligned/rounded by default...] ) cat > conftest.h << __EOF #include struct bytestruct { unsigned char a; }; __EOF AC_CHECK_SIZEOF( struct bytestruct, [], [#include "conftest.h"] ) if test "$ac_cv_sizeof_struct_bytestruct" = "1"; then hc_cv_byte_structs_aligned_and_rounded_by_default=no hc_cv_byte_structs_always_aligned_and_rounded=no else # The sizeof our test structure is not '1'. # The compiler is rounding the size of the # structure upward to some predefined value. hc_cv_byte_structs_aligned_and_rounded_by_default=yes # If there's no way to request the compiler # to not do that, then we can't build Herc. case "$host_cpu-$GCC" in arm*-yes|xscale*-yes|sh*-yes|pxa*-yes) hc_cv_byte_structs_always_aligned_and_rounded=no ;; *) hc_cv_byte_structs_always_aligned_and_rounded=yes ;; esac fi AC_MSG_NOTICE( [results: byte structs are aligned/rounded by default... ${hc_cv_byte_structs_aligned_and_rounded_by_default}] ) if test "$hc_cv_byte_structs_always_aligned_and_rounded" = "yes"; then AC_MSG_RESULT( [ERROR: Size of structures are aligned/rounded and we don't know how to tell the compiler otherwise] ) hc_error=yes fi #------------------------------# # Check if this is GCC 2.96 # #------------------------------# AC_CACHE_CHECK( [if this is the broken 2.96 version of GCC], [hc_cv_is_gcc_2_96], [ if test "$GCC" = "yes"; then AC_COMPILE_IFELSE( [ #if __GNUC__ == 2 && __GNUC_MINOR__ == 96 yes; #else int no; #endif ], [hc_cv_is_gcc_2_96=no], [hc_cv_is_gcc_2_96=yes] ) else hc_cv_is_gcc_2_96=no fi ] ) #----------------------------------------------# # Check C99 if flexible arrays are supported # #----------------------------------------------# # The logic to test whether C99 flexible # # arrays are supported is defined in the # # 'HC_C99_FLEXIBLE_ARRAYS' macro in the # # 'hercules.m4' file in the 'autoconf' sub- # # directory, and issues the AC_DEFINE for # # 'C99_FLEXIBLE_ARRAYS' if it's supported # # and also sets '$hc_cv_c99_flexible_array'. # #----------------------------------------------# HC_C99_FLEXIBLE_ARRAYS() #--------------------------------------------------------# # Check if GCC supports '__attribute__ ((regparm(n)))' # #--------------------------------------------------------# # Note: even though at the moment GCC only supports regparm # on i386 or greater machines, that could change at any time # in the future so we don't bother checking for it. if test "$GCC" = "yes"; then AC_CACHE_CHECK( [whether '__attribute__ ((regparm(n)))' is supported], [hc_cv_regparm_attr_supported], [ hc_temp="$CFLAGS" CFLAGS="-Wall -Werror" AC_COMPILE_IFELSE( [ void conftest() __attribute__ ((regparm(1))); ], [hc_cv_regparm_attr_supported=yes], [hc_cv_regparm_attr_supported=no] ) CFLAGS="$hc_temp" ] ) else hc_cv_regparm_attr_supported=no fi #---------------------------------------------------# # Test for GCC '__attribute__ ((regparm(3)))' bug # #---------------------------------------------------# if test "$GCC" = "yes" && test "$hc_cv_regparm_attr_supported" = "yes"; then AC_CACHE_CHECK( [whether '__attribute__ ((regparm(3)))' is broken], [hc_cv_regparm_attr_broke], [ hc_temp="$CFLAGS" CFLAGS="-O3 -fomit-frame-pointer" AC_TRY_RUN( [ /* Fish: Test for reparms bug caused by alloca bug# 8750 Ref: */ struct REGS { int a, b, c, d; char e[50000]; }; typedef struct REGS REGS; #define ATTR_REGPARM __attribute__ (( regparm(3) )) int func1 ( int a, int b, int c, REGS *regs ) ATTR_REGPARM; int func2 ( int a, int b, int c, REGS *regs ) ATTR_REGPARM; REGS global_regs; int main() { return func1( 1, 2, 3, &global_regs ); } int ATTR_REGPARM func1 ( int a, int b, int c, REGS *regs ) { REGS stack_regs; regs=regs; /* (quiet compiler warning) */ if ( func2( a, b, c, &stack_regs ) == 0 ) return 0; /* pass */ return 1; /* fail */ } int ATTR_REGPARM func2 ( int a, int b, int c, REGS *regs ) { regs=regs; /* (quiet compiler warning) */ if ( 1==a && 2==b && 3==c ) return 0; /* pass */ return 1; /* fail */ } ], [hc_cv_regparm_attr_broke=no], [hc_cv_regparm_attr_broke=yes], [hc_cv_regparm_attr_broke=yes] ) CFLAGS="$hc_temp" ] ) else hc_cv_regparm_attr_broke=no fi #------------------------------------------------------# # Test for GCC builtin alloca bug# 8750 # # # #------------------------------------------------------# if test "$GCC" = "yes"; then AC_CACHE_CHECK( [whether '__builtin_alloca' is broken], [hc_cv_builtin_alloca_broke], [ hc_temp=$CFLAGS CFLAGS="-g -O2 -fomit-frame-pointer" AC_TRY_RUN( [ /* Fish: Test for gcc builtin alloca bug# 8750 Required(?!) (not sure) compiler options: -g -O2 -fomit-frame-pointer */ int foo () { char a[50000+16]; memset(a,0xCD,50000); a[50000]=0; return strlen(a); } int main() { return ( foo() != 50000 ); } ], [hc_cv_builtin_alloca_broke=no], [hc_cv_builtin_alloca_broke=yes], [hc_cv_builtin_alloca_broke=yes] ) CFLAGS=$hc_temp ] ) else hc_cv_builtin_alloca_broke=no fi #------------------------------------------------------------# # Check for OS X gcc preprocessor macro argument count bug # #------------------------------------------------------------# if test "$GCC" = "yes"; then AC_CACHE_CHECK( [whether preprocessor macro argument counting broken], [hc_cv_pp_macro_arg_counting_broke], [ hc_temp="$CFLAGS" CFLAGS="-Wall -Werror" AC_COMPILE_IFELSE( [ #include #define MACRO(_x,_args...) printf(_x, ## _args) int main( int argc, char **argv, char **arge ) { MACRO( "bare printf\n" ); return 0; } ], [hc_cv_pp_macro_arg_counting_broke=no], [hc_cv_pp_macro_arg_counting_broke=yes] ) CFLAGS="$hc_temp" ] ) else hc_cv_pp_macro_arg_counting_broke=no fi #------------------------------------------------------------# # Check if traditional preprocessor is the K&R C type... # #------------------------------------------------------------# # # Apple's latest GCC documentation reveals: # # ... the -traditional-cpp option has changed. # In Apple GCC 3.1 and earlier Apple GCC compilers, # -traditional-cpp was used to toggle between the # standard GNU GCC preprocessor and Apple's own # preprocessor, "cpp-precomp". The GNU GCC compiler # interpreted -traditional-cpp differently on all # other platforms. Since cpp-precomp has been removed # for Apple's GCC 3.3 compiler, the standard GNU # meaning of -traditional-cpp has been restored. By # default, the GCC 3.3 preprocessor conforms to the # ISO C standard. Using the -tradtional-cpp option # means the C preprocessor should instead try to # emulate the old "K&R C". # #------------------------------------------------------------# if test "$GCC" = "yes"; then AC_CACHE_CHECK( [whether '-traditional-cpp' is K&R C preprocessor], [hc_cv_traditional_cpp_is_K_AND_R_C_type], [ hc_temp="$CFLAGS" CFLAGS="-Wall -Werror -traditional-cpp" # Note: The test program MUST start in column 1! Otherwise, the compilation # will fail when it's not supposed to. AC_COMPILE_IFELSE( [ /* If the following gets an error, then the "traditional" preprocessor is K&R C type. Otherwise if it compiles WITHOUT error the the "traditional" preprocessor is NOT the K&R C type. */ #if 1 #include // comment/etc... #endif int main( int, char**, char** ) { return 0; } ], [hc_cv_traditional_cpp_is_K_AND_R_C_type=no], [hc_cv_traditional_cpp_is_K_AND_R_C_type=yes] ) CFLAGS="$hc_temp" ] ) else hc_cv_traditional_cpp_is_K_AND_R_C_type=no fi #-----------------------------------------------------------# # Check whether byte-swapping can be done using assembler # #-----------------------------------------------------------# AC_MSG_CHECKING( [whether byte-swapping can be done using assembler] ) # (use our own byteswap assembler routines are i486+ only) # use system's byteswap routines if present... case "$host_cpu" in i486|i586|i686|i786|x86_64) hc_cv_asm_byteswap=yes ;; *) hc_cv_asm_byteswap=$hc_cv_have_byteswap_h ;; esac AC_MSG_RESULT( [$hc_cv_asm_byteswap] ) #----------------------------------------------# # Check whether -pthread needed for pthreads # #----------------------------------------------# AC_MSG_CHECKING( [whether ${CC-cc} accepts -pthread] ) echo 'void f(){}' >conftest.c if test -z "`${CC-cc} -pthread -c conftest.c 2>&1`"; then hc_cv_dash_pthread_needed=yes else hc_cv_dash_pthread_needed=no fi AC_MSG_RESULT( [$hc_cv_dash_pthread_needed] ) #------------------------------------------------------------------ # The logic to test whether optreset is needed for getopt use is # defined in the 'HC_CHECK_NEED_GETOPT_OPTRESET' macro in the # 'hercules.m4' file in the autoconf directory, and issues the # AC_DEFINE for 'NEED_GETOPT_OPTRESET' if it's needed (and also # sets the '$hc_cv_need_getopt_optreset' variable appropriately). #------------------------------------------------------------------ HC_CHECK_NEED_GETOPT_OPTRESET() AC_CACHE_SAVE() ############################################################################### # Checks for system services... ############################################################################### AC_SYS_LARGEFILE() AC_TYPE_OFF_T() AC_FUNC_FSEEKO() AC_CACHE_SAVE() ############################################################################### # AC_CONFIG_FILES( [file...] )... ############################################################################### AC_CACHE_SAVE() ############################################################################### # Set flags according to user-specified --enable-xxxxx build options ############################################################################### # PROGRAMMING NOTE: some of these values default to previously determined # values (e.g. cckd-bzip2 for example defaults to whether libbz2 exists), # so this section MUST [unfortunately] come AFTER the above sections. This # does have the unfortunate side effect of not detecting invalid options # right away like one would normally expect/want. The only way around that # would be to perform two checks (one at the beginning and then one again # later on), but that approach was rejected since it would tend to make our # configure.ac script less clean (simple and straightforward). AC_ARG_ENABLE( dynamic-load, AC_HELP_STRING([--disable-dynamic-load], [disable dynamic loader option] ), [ case "${enableval}" in yes) hc_cv_opt_dynamic_load=yes ;; no) hc_cv_opt_dynamic_load=no ;; *) AC_MSG_RESULT( [ERROR: invalid 'dynamic-load' option] ) hc_error=yes ;; esac ], [hc_cv_opt_dynamic_load=yes] ) AC_ARG_ENABLE( cckd-bzip2, AC_HELP_STRING( [--enable-cckd-bzip2], [enable bzip2 compression for emulated dasd] ), [ case "${enableval}" in yes) hc_cv_opt_cckd_bzip2=yes ;; no) hc_cv_opt_cckd_bzip2=no ;; *) AC_MSG_RESULT( [ERROR: invalid 'cckd-bzip2' option] ) hc_error=yes ;; esac ], [hc_cv_opt_cckd_bzip2=$hc_cv_have_libbz2] ) AC_ARG_ENABLE( het-bzip2, AC_HELP_STRING( [--enable-het-bzip2], [enable bzip2 compression for emulated tapes] ), [ case "${enableval}" in yes) hc_cv_opt_het_bzip2=yes ;; no) hc_cv_opt_het_bzip2=no ;; *) AC_MSG_RESULT( [ERROR: invalid 'het-bzip2' option] ) hc_error=yes ;; esac ], [hc_cv_opt_het_bzip2=$hc_cv_have_libbz2] ) AC_ARG_ENABLE( debug, AC_HELP_STRING( [--enable-debug], [enable debugging (TRACE/VERIFY/ASSERT macros)] ), [ case "${enableval}" in yes) hc_cv_opt_debug=yes ;; no) hc_cv_opt_debug=no ;; *) AC_MSG_RESULT( [ERROR: invalid 'debug' option] ) hc_error=yes ;; esac ], [hc_cv_opt_debug=no] ) AC_ARG_ENABLE( optimization, AC_HELP_STRING( [--enable-optimization=yes|no|FLAGS], [enable automatic optimization, or specify flags] ), [ hc_cv_opt_optimization=${enableval} ], [hc_cv_opt_optimization=yes] ) AC_ARG_ENABLE( configsymbols, AC_HELP_STRING( [--disable-configsymbols], [disable symbolic substitutions in configuration file] ), [ case "${enableval}" in yes) hc_cv_opt_configsymbols=yes ;; no) hc_cv_opt_configsymbols=no ;; *) AC_MSG_RESULT( [ERROR: invalid 'configsymbols' option] ) hc_error=yes ;; esac ], [hc_cv_opt_configsymbols=yes] ) AC_ARG_ENABLE( enhanced-configsymbols, AC_HELP_STRING( [--disable-enhanced-configsymbols], [disable enhanced-mode symbolic substitutions in configuration file] ), [ case "${enableval}" in yes) hc_cv_opt_enhanced_configsymbols=yes ;; no) hc_cv_opt_enhanced_configsymbols=no ;; *) AC_MSG_RESULT( [ERROR: invalid 'enhanced-configsymbols' option] ) hc_error=yes ;; esac ], [hc_cv_opt_enhanced_configsymbols=yes] ) AC_ARG_ENABLE( enhanced-configincludes, AC_HELP_STRING( [--disable-enhanced-configincludes], [disable enhanced-mode 'include' file support in configuration file] ), [ case "${enableval}" in yes) hc_cv_opt_enhanced_configincludes=yes ;; no) hc_cv_opt_enhanced_configincludes=no ;; *) AC_MSG_RESULT( [ERROR: invalid 'enhanced-configincludes' option] ) hc_error=yes ;; esac ], [hc_cv_opt_enhanced_configincludes=yes] ) AC_ARG_ENABLE( automatic-operator, AC_HELP_STRING( [--disable-automatic-operator], [disable Hercules Automatic Operator feature] ), [ case "${enableval}" in yes) hc_cv_opt_auto_oper=yes ;; no) hc_cv_opt_auto_oper=no ;; *) AC_MSG_RESULT( [ERROR: invalid 'automatic-operator' option] ) hc_error=yes ;; esac ], [hc_cv_opt_auto_oper=$hc_cv_have_regex_h] ) AC_ARG_ENABLE( external-gui, AC_HELP_STRING( [--disable-external-gui], [disable external Windows GUI interface] ), [ case "${enableval}" in yes) hc_cv_opt_external_gui=yes ;; no) hc_cv_opt_external_gui=no ;; *) AC_MSG_RESULT( [ERROR: invalid 'external-gui' option] ) hc_error=yes ;; esac ], [hc_cv_opt_external_gui=$hc_cv_is_windows] ) AC_ARG_ENABLE( fthreads, AC_HELP_STRING( [--disable-fthreads], [disable use of fish threads instead of posix threads] ), [ case "${enableval}" in yes) hc_cv_opt_fthreads=yes ;; no) hc_cv_opt_fthreads=no ;; *) AC_MSG_RESULT( [ERROR: invalid 'fthreads' option] ) hc_error=yes ;; esac ], [hc_cv_opt_fthreads=$hc_cv_is_windows] ) AC_ARG_ENABLE( fishhang, AC_HELP_STRING( [--enable-fishhang], [debug correct lock handling (fthreads only)] ), [ case "${enableval}" in yes) hc_cv_opt_fishhang=yes ;; no) hc_cv_opt_fishhang=no ;; *) AC_MSG_RESULT( [ERROR: invalid 'fishhang' option] ) hc_error=yes ;; esac ], [hc_cv_opt_fishhang=no] ) AC_ARG_ENABLE( multi-cpu, AC_HELP_STRING( [--enable-multi-cpu=yes|no|NUMBER], [enable/disable multi-cpu support (1-64, default 8)] ), [ case "${enableval}" in yes) hc_cv_opt_num_cpu_engines=8 ;; no) hc_cv_opt_num_cpu_engines=1 ;; *) if test 0 -lt "${enableval}" -a 64 -ge "${enableval}" then hc_cv_opt_num_cpu_engines=${enableval} else AC_MSG_RESULT( [ERROR: invalid 'multi-cpu' option] ) hc_error=yes fi ;; esac ], [hc_cv_opt_num_cpu_engines=8] ) AC_ARG_ENABLE( capabilities, AC_HELP_STRING([--disable-capabilities], [disable fine grained privileges] ), [ case "${enableval}" in yes) hc_cv_opt_capabilities=yes ;; no) hc_cv_opt_capabilities=no ;; *) AC_MSG_RESULT( [ERROR: invalid 'capabilities' option] ) hc_error=yes ;; esac ], [hc_cv_opt_capabilities=hc_cv_have_sys_capability] ) # only include libcap if needed if test "$hc_cv_opt_capabilities" = "yes"; then AC_CHECK_LIB(cap,cap_set_proc) fi # Force disable capabilities support if library is missing if test "$ac_cv_lib_cap_cap_set_proc" = "no"; then hc_cv_opt_capabilities="no" fi # Force disable capabilities support if sys/capability.h header is missing if test "$hc_cv_have_sys_capa_h" = "no"; then hc_cv_opt_capabilities="no" fi # Force disable capabilities support if sys/prctl.h header is missing if test "$hc_cv_have_sys_prctl_h" = "no"; then hc_cv_opt_capabilities="no" fi AC_ARG_ENABLE( custom, AC_HELP_STRING( [--enable-custom=STRING], [provide a custom description for this build] ), [ hc_cv_opt_custom_build_str=${enableval} ] ) if test "$hc_cv_build_hercifc" = "yes"; then AC_ARG_ENABLE( setuid-hercifc, AC_HELP_STRING( [--enable-setuid-hercifc=yes|no|GROUPNAME], [install hercifc as setuid root, and allow execution by users in group GROUPNAME] ), [ case "${enableval}" in yes) hc_cv_opt_setuid_hercifc=yes ;; no) hc_cv_opt_setuid_hercifc=no ;; *) hc_cv_opt_setuid_hercifc=yes hc_cv_hercifc_groupname=${enableval} ;; esac ], [hc_cv_opt_setuid_hercifc=no] ) hc_cv_setuid_hercifc=$hc_cv_opt_setuid_hercifc else hc_cv_setuid_hercifc=no fi #----------------------------------------------------------------- # The handling of AC_ARG_ENABLE for "--enable-getoptwrapper" # is defined within the 'HC_ARG_ENABLE_GETOPTWRAPPER' macro # coded in the 'hercules.m4' file in the autoconf directory # and issues the AC_DEFINE for NEED_GETOPT_WRAPPER if needed # (and sets the '$hc_cv_need_getopt_wrapper' variable too). #----------------------------------------------------------------- HC_ARG_ENABLE_GETOPTWRAPPER() #---------------------------------------------------------------- # Note: '$enable_shared' is automatically set by LIBTOOL, # unless the user overrides it via --disable-shared. #---------------------------------------------------------------- hc_cv_hdl_build_shared=$enable_shared AC_CACHE_SAVE() ############################################################################### # Final default settings, final sanity / error checks... ############################################################################### if test "$hc_cv_build_hercifc" = "yes"; then if test "$hc_cv_have_linux_if_tun_h" != "yes"; then if test "$hc_cv_have_net_if_h" != "yes"; then AC_MSG_RESULT( [ERROR: Required headers 'linux/if_tun.h' or 'net/if.h' not found] ) hc_error=yes fi fi if test "$hc_cv_have_net_route_h" != "yes"; then AC_MSG_RESULT( [ERROR: Required header 'net/route_h' not found] ) hc_error=yes fi fi #------------------------------------------------------------------------------ # signal.h is only required if strsignal function isn't available since if # the strsignal function isn't available, we use our builtin which needs it. # The presumption that if the strsignal function is found, then the signal.h # header will also be found seems to be a fairly safe assumption to make IMO. if test "$hc_cv_have_strsignal" != "yes" && test "$hc_cv_have_signal_h" != "yes"; then AC_MSG_RESULT( [ERROR: Required header 'signal.h' not found] ) hc_error=yes fi #------------------------------------------------------------------------------ if test "$hc_cv_have_vsscanf" != "yes"; then AC_MSG_RESULT( [ERROR: Required function 'vsscanf' not found] ) hc_error=yes fi #------------------------------------------------------------------------------ if test "$hc_cv_have_inttypes_h" != "yes" && test "$hc_cv_have_u_int8_t" != "yes"; then AC_MSG_RESULT( [ERROR: unable to find fixed-size data types] ) hc_error=yes fi #------------------------------------------------------------------------------ if test "$hc_cv_opt_cckd_bzip2" = "yes" || test "$hc_cv_opt_het_bzip2" = "yes"; then if test "$hc_cv_have_libbz2" != "yes"; then AC_MSG_RESULT( [ERROR: bzip2 compression requested but libbz2 library not found] ) hc_error=yes fi if test "$hc_cv_have_bzlib_h" != "yes"; then AC_MSG_RESULT( [ERROR: bzip2 compression requested but 'bzlib.h' header not found] ) hc_error=yes fi fi #------------------------------------------------------------------------------ if test "$hc_cv_opt_dynamic_load" = "yes"; then if test "$hc_cv_have_lt_dlopen" != "yes" && test "$hc_cv_have_dlopen" != "yes"; then AC_MSG_RESULT( [ERROR: dynamic-load requires libtool or dlltool] ) hc_error=yes fi fi #------------------------------------------------------------------------------ if test "$hc_cv_opt_auto_oper" = "yes" && test "$hc_cv_have_regex_h" != "yes"; then AC_MSG_RESULT( [ERROR: automatic-operator requested but 'regex.h' header not found] ) hc_error=yes fi #------------------------------------------------------------------------------ if test "$hc_cv_opt_external_gui" = "yes" && test "$hc_cv_opt_dynamic_load" != "yes"; then AC_MSG_RESULT( [ERROR: external-gui requires dynamic-load] ) hc_error=yes fi #------------------------------------------------------------------------------ if test "$hc_cv_opt_fthreads" = "yes" && test "$hc_cv_is_windows" != "yes"; then AC_MSG_RESULT( [ERROR: fthreads is only for Windows platforms] ) hc_error=yes fi if test "$hc_cv_have_pthread_h" != "yes" && test "$hc_cv_opt_fthreads" != "yes"; then AC_MSG_RESULT( [ERROR: unable to find pthread.h] ) hc_error=yes fi #------------------------------------------------------------------------------ if test "$hc_cv_opt_fishhang" = "yes" && test "$hc_cv_opt_fthreads" != "yes"; then AC_MSG_RESULT( [ERROR: fishhang requires fthreads] ) hc_error=yes fi #------------------------------------------------------------------------------ if test "$hc_cv_is_apple" = "yes" && test "$hc_cv_pp_macro_arg_counting_broke" = "yes" && test "$hc_cv_traditional_cpp_is_K_AND_R_C_type" = "yes"; then AC_MSG_RESULT( [ERROR: macro argument counting broken and cannot use -traditional-cpp option to work around it] ) hc_error=yes fi #------------------------------------------------------------------------------ # If any errors have been detected, then abort the configure at this time #------------------------------------------------------------------------------ if test "$hc_error" != "no"; then AC_MSG_ERROR( [Please correct the above error(s) and try again] ) fi AC_CACHE_SAVE() ############################################################################### # Act on the results of all of the above... ############################################################################### # AUTOMATIC DETERMINATION OF OPTIMIZATION FLAGS # # If they specified 'no' then don't optimize. # If they specified 'yes' then determine what flags we should use. # If they didn't specify, then optimize only if this is NOT a debug build. # Otherwise use whatever flags they specified as-is. AC_MSG_CHECKING( [for what optimization flags to use] ) case "$hc_cv_opt_optimization" in no) hc_cv_auto_optimize=no ;; yes) hc_cv_auto_optimize=yes ;; *) if test "x$hc_cv_opt_optimization" = "x"; then if test "$hc_cv_opt_debug" = "yes"; then hc_cv_auto_optimize=no else hc_cv_auto_optimize=yes fi else hc_cv_auto_optimize=no hc_cv_optimization_flags="$hc_cv_opt_optimization" fi ;; esac if test "$hc_cv_auto_optimize" = "yes"; then if test "$hc_cv_builtin_alloca_broke" != "yes" && test "$hc_cv_opt_debug" != "yes"; then hc_cv_optimization_flags="-O3" fi hc_cv_is_intel_x86_arch=no case "$host_cpu-$GCC" in x86_64-yes) hc_cv_is_intel_x86_arch=yes hc_cv_intel_cpu_type=k8 ;; i386-yes|i486-yes|i586-yes|i686-yes|i786-yes) hc_cv_is_intel_x86_arch=yes if test $host_cpu = i786; then hc_cv_intel_cpu_type=pentium4 else if test $host_cpu = i686 && test "hc_cv_is_gcc_2_96" = "yes"; then hc_cv_intel_cpu_type=i586 else hc_cv_intel_cpu_type=$host_cpu fi fi ;; arm-yes) hc_cv_is_intel_x86_arch=no hc_cv_optimization_flags="$hc_cv_optimization_flags -frename-registers" ;; xscale-yes|arm*-yes) hc_cv_is_intel_x86_arch=no hc_cv_optimization_flags="$hc_cv_optimization_flags -mcpu=$host_cpu -mtune=$host_cpu -frename-registers" ;; esac if test "$hc_cv_is_intel_x86_arch" = "yes"; then hc_cv_optimization_flags="$hc_cv_optimization_flags -march=$hc_cv_intel_cpu_type" if test "$hc_cv_builtin_alloca_broke" != "yes" && test "$hc_cv_opt_debug" != "yes"; then hc_cv_optimization_flags="$hc_cv_optimization_flags -fomit-frame-pointer" else hc_cv_optimization_flags="$hc_cv_optimization_flags -fno-omit-frame-pointer" fi fi fi if test "x$hc_cv_optimization_flags" = "x"; then AC_MSG_RESULT( [(none)] ) else AC_MSG_RESULT( [$hc_cv_optimization_flags] ) fi AC_CACHE_SAVE() ############################################################################### # DONE! -- Define our OUTPUT values and then exit... ############################################################################### # This is ugly... Someone PLEASE fix this (if possible)... # # The object is to get the value of PKGDATADIR into config.h, # but this is the only way I've found to do so. All of this # rigamarole is needed because ${datadir} doesn't expand to the # desired data directory. If there's a better way to get there, # PLEASE replace this. -- JRM # # If DESTPREFIX is set, we're doing an RPM build, and we want to # use that value. If it's not set, and prefix is set and not equal # to NONE, then we'll use that. If prefix is NONE, then default to # /usr/local. Note: This prefix has /share/locale, /share/$PACKAGE, # or /lib/$PACKAGE appended in the next step, so it must NOT have # those components included in $DESTPREFIX itself. if test "x${DESTPREFIX}" = "x"; then if test "x$prefix" = "xNONE"; then DESTPREFIX="/usr/local" else DESTPREFIX="${prefix}" fi fi case "x${libdir}" in *lib64*) DESTLIBS="lib64" ;; *) DESTLIBS="lib" ;; esac MODULESDIR="${DESTPREFIX}/${DESTLIBS}/${PACKAGE}" PKGDATADIR="${DESTPREFIX}/share/${PACKAGE}" HERC_LOCALEDIR="${DESTPREFIX}/share/locale" #--------------------------------------------------------------# # (place only AC_DEFINE_UNQUOTED here; place AC_DEFINE below) # #--------------------------------------------------------------# if test "x$hc_cv_opt_custom_build_str" != "x"; then AC_DEFINE_UNQUOTED( [CUSTOM_BUILD_STRING], "${hc_cv_opt_custom_build_str}" ) fi AC_DEFINE_UNQUOTED( [MODULESDIR], "${MODULESDIR}" ) AC_DEFINE_UNQUOTED( [PKGDATADIR], "${PKGDATADIR}" ) AC_DEFINE_UNQUOTED( [HERC_LOCALEDIR], "${HERC_LOCALEDIR}" ) AC_DEFINE_UNQUOTED( [MAX_CPU_ENGINES], ${hc_cv_opt_num_cpu_engines} ) AC_CACHE_SAVE() AC_MSG_NOTICE( [ ] ) AC_MSG_NOTICE( [ Package destination directory prefixes: ] ) AC_MSG_NOTICE( [ ] ) AC_MSG_NOTICE( [ Libraries: ${MODULESDIR} ] ) AC_MSG_NOTICE( [ Data: ${PKGDATADIR} ] ) AC_MSG_NOTICE( [ Locale: ${HERC_LOCALEDIR} ] ) AC_MSG_NOTICE( [ ] ) #---------------------------------------------------------------# # (place only AC_DEFINE here; place AC_DEFINE_UNQUOTED above) # #---------------------------------------------------------------# test "$hc_cv_opt_debug" = "yes" && AC_DEFINE(DEBUG) test "$hc_cv_have_inttypes_h" = "yes" && AC_DEFINE(HAVE_INTTYPES_H) test "$hc_cv_have_u_int8_t" = "yes" && AC_DEFINE(HAVE_U_INT) test "$hc_cv_opt_configsymbols" = "yes" && AC_DEFINE(OPTION_CONFIG_SYMBOLS) test "$hc_cv_opt_enhanced_configsymbols" = "yes" && AC_DEFINE(OPTION_ENHANCED_CONFIG_SYMBOLS) test "$hc_cv_opt_enhanced_configincludes" = "yes" && AC_DEFINE(OPTION_ENHANCED_CONFIG_INCLUDE) test "$hc_cv_opt_auto_oper" = "yes" && AC_DEFINE(OPTION_HAO) test "$hc_cv_opt_dynamic_load" = "yes" && AC_DEFINE(OPTION_DYNAMIC_LOAD) test "$hc_cv_opt_fthreads" = "yes" && AC_DEFINE(OPTION_FTHREADS) test "$hc_cv_opt_fishhang" = "yes" && AC_DEFINE(FISH_HANG) test "$hc_cv_hdl_build_shared" = "yes" && AC_DEFINE(HDL_BUILD_SHARED) test "$hc_cv_have_lt_dlopen" = "yes" && AC_DEFINE(HDL_USE_LIBTOOL) test "$hc_cv_is_windows" = "yes" && AC_DEFINE(WIN32) test "$hc_cv_opt_external_gui" = "yes" && AC_DEFINE(EXTERNALGUI) test "$hc_cv_opt_cckd_bzip2" = "yes" && AC_DEFINE(CCKD_BZIP2) test "$hc_cv_opt_het_bzip2" = "yes" && AC_DEFINE(HET_BZIP2) test "$hc_cv_timespec_in_sys_types_h" = "yes" && AC_DEFINE(TIMESPEC_IN_SYS_TYPES_H) test "$hc_cv_timespec_in_time_h" = "yes" && AC_DEFINE(TIMESPEC_IN_TIME_H) test "$hc_cv_have_getset_uid" != "yes" && AC_DEFINE(NO_SETUID) test "$hc_cv_asm_byteswap" != "yes" && AC_DEFINE(NO_ASM_BYTESWAP) test "$hc_cv_non_unique_gettimeofday" = "yes" && AC_DEFINE(NON_UNIQUE_GETTIMEOFDAY) test "$hc_cv_build_hercifc" = "yes" && AC_DEFINE(BUILD_HERCIFC) test "$hc_cv_opt_capabilities" = "yes" && AC_DEFINE(OPTION_CAPABILITIES) if test $hc_cv_have_sa_sigaction != yes || test $hc_cv_have_sigusr1 != yes || test $hc_cv_have_sigusr2 != yes || test $hc_cv_have_sigpipe != yes || test $hc_cv_have_sigbus != yes; then AC_DEFINE(NO_SIGABEND_HANDLER) fi if test "$hc_cv_regparm_attr_supported" = "yes" && test "$hc_cv_regparm_attr_broke" != "yes"; then AC_DEFINE(HAVE_ATTR_REGPARM) fi if test "$hc_cv_is_windows" != "yes" && test "$hc_cv_have_fenv_h" != "yes"; then AC_DEFINE(NO_IEEE_SUPPORT) fi if test "$hc_cv_is_apple" = "yes"; then AC_DEFINE(_INTL_REDIRECT_MACROS) # # TODO?? # # Do whatever is necessary to get the following symbol defined # so the included libltdl will be built and used... # ## AC_PROVIDE_AC_LIBTOOL_DLOPEN() fi #--------------------------------------------------# # CPPFLAGS (pre-processor flags) # #--------------------------------------------------# if test "$hc_cv_is_apple" = "yes" && test "$hc_cv_pp_macro_arg_counting_broke" = "yes"; then CPPFLAGS="${CPPFLAGS} -traditional-cpp -Wno-endif-labels" fi #--------------------------------------------------# # CFLAGS (compiler flags) # #--------------------------------------------------# if test "$hc_cv_is_windows" = "yes"; then if test "$hc_cv_have_pthread_h" = "yes" && test "x$hc_cv_alt_pthread_location" != "x"; then CFLAGS="$CFLAGS -I${hc_cv_alt_pthread_location}" fi CFLAGS="$CFLAGS -Wno-format" fi if test "$hc_cv_byte_structs_aligned_and_rounded_by_default" = "yes"; then #=============================================================== # the following requests 8-bit (byte) struct boundary alignment #=============================================================== CFLAGS="$CFLAGS -mstructure-size-boundary=8" fi test "x$hc_cv_optimization_flags" != "x" && CFLAGS="$CFLAGS $hc_cv_optimization_flags" #--------------------------------------------------# # LIBS (linker flags) # #--------------------------------------------------# test "$hc_cv_dash_pthread_needed" = "yes" && LIBS="$LIBS -pthread" test "$hc_cv_have_libbz2" = "yes" && LIBS="$LIBS -lbz2" # ---------------------- MINGW32 ---------------------- test "$hc_cv_is_mingw32" = "yes" && LIBS="$LIBS -lmsvcrt" test "$hc_cv_is_mingw32" = "yes" && LIBS="$LIBS -lws2_32" AC_CACHE_SAVE() #--------------------------------------------------------------------------------# # Pass certain values/settings as makefile variables to automake (makefile.am) # #--------------------------------------------------------------------------------# AM_CONDITIONAL( OPTION_DYNAMIC_LOAD, [ test "$hc_cv_opt_dynamic_load" = "yes" ] ) AM_CONDITIONAL( BUILD_FTHREADS, [ test "$hc_cv_opt_fthreads" = "yes" ] ) AM_CONDITIONAL( BUILD_FISHHANG, [ test "$hc_cv_opt_fishhang" = "yes" ] ) AM_CONDITIONAL( BUILD_HERCIFC, [ test "$hc_cv_build_hercifc" = "yes" ] ) AM_CONDITIONAL( SETUID_HERCIFC, [ test "$hc_cv_setuid_hercifc" = "yes" ] ) AM_CONDITIONAL( HERCIFC_GROUPSET, [ test "x$hc_cv_hercifc_groupname" != "x"] ) if test "x$hc_cv_hercifc_groupname" != "x"; then HERCIFC_GROUPNAME=${hc_cv_hercifc_groupname} AC_SUBST(HERCIFC_GROUPNAME) fi # Building of shared libraries is forced, and we force use of libtool too. AM_CONDITIONAL( BUILD_SHARED, [ test "$hc_cv_hdl_build_shared" = "yes" ] ) AM_CONDITIONAL( USE_DLLTOOL, [ test "$hc_cv_is_windows" = "yes" ] ) AC_CACHE_SAVE() AC_OUTPUT( [ Makefile util/Makefile html/Makefile crypto/Makefile po/Makefile.in po/Makefile man/Makefile m4/Makefile decNumber/Makefile] ) ############################################################################### # (end-of-file) ############################################################################### hercules-3.07/console.c000644 000765 000765 00000376663 11335365456 016611 0ustar00jmaynardjmaynard000000 000000 /* CONSOLE.C (c)Copyright Roger Bowler, 1999-2009 */ /* ESA/390 Console Device Handler */ // $Id: console.c 5608 2010-02-07 09:36:35Z fish $ /*-------------------------------------------------------------------*/ /* This module contains device handling functions for console */ /* devices for the Hercules ESA/390 emulator. */ /* */ /* Telnet support is provided for two classes of console device: */ /* - local non-SNA 3270 display consoles via tn3270 */ /* - local non-SNA 3270 printers via tn3270 */ /* - 1052 and 3215 console printer keyboards via regular telnet */ /*-------------------------------------------------------------------*/ /*-------------------------------------------------------------------*/ /* This module also takes care of the differences between the */ /* remote 3270 and local non-SNA 3270 devices. In particular */ /* the support of command chaining, which is not supported on */ /* the remote 3270 implementation on which telnet 3270 is based. */ /* In the local non-SNA environment a chained read or write will */ /* continue at the buffer address where the previous command ended. */ /* In order to achieve this, this module will keep track of the */ /* buffer location, and adjust the buffer address on chained read */ /* and write operations. */ /* 03/06/00 Jan Jaeger. */ /*-------------------------------------------------------------------*/ /*-------------------------------------------------------------------*/ /* Add code to bypass bug in telnet client from TCP/IP for OS/390 */ /* where telnet responds with the server response rather then the */ /* client response as documented in RFC1576. */ /* 20/06/00 Jan Jaeger. */ /*-------------------------------------------------------------------*/ /*-------------------------------------------------------------------*/ /* Corrections to buffer position calculations in find_buffer_pos */ /* and get_screen_pos subroutines (symptom: message IEE305I) */ /* 09/12/00 Roger Bowler. */ /*-------------------------------------------------------------------*/ /*-------------------------------------------------------------------*/ /* When using VTAM with local non-SNA 3270 devices, ensure that */ /* enough bufferspace is available when doing IND$FILE type */ /* filetransfers. Code IOBUF=(,3992) in ATCSTRxx, and/or BUFNUM=xxx */ /* on the LBUILD LOCAL statement defining the 3270 device. JJ */ /* */ /*-------------------------------------------------------------------*/ /*-------------------------------------------------------------------*/ /* Ignore "Negotiate About Window Size" client option (for now) so */ /* WinNT version of telnet works. -- Greg Price (implemted by Fish) */ /*-------------------------------------------------------------------*/ // $Log$ // Revision 1.104 2009/01/02 19:21:50 jj // DVD-RAM IPL // RAMSAVE // SYSG Integrated 3270 console fixes // // Revision 1.103 2008/12/30 15:40:01 rbowler // Allow $(LPARNAME) in herclogo file // // Revision 1.102 2008/12/29 13:02:38 rbowler // herclogo symbol $(ccuu) should display lower case device number // // Revision 1.101 2008/12/29 12:55:12 rbowler // Duplicate SYSG console definition message issued incorrectly // // Revision 1.100 2008/12/28 21:05:08 rbowler // Integrated 3270 (SYSG) console attn/read commands // // Revision 1.99 2008/12/28 15:30:09 jj // SYSG and SYSA mods // // Revision 1.98 2008/12/27 23:34:37 rbowler // Integrated 3270 (SYSG) console send command // // Revision 1.97 2008/11/04 05:56:31 fish // Put ensure consistent create_thread ATTR usage change back in // // Revision 1.96 2008/11/03 15:31:57 rbowler // Back out consistent create_thread ATTR modification // // Revision 1.95 2008/10/18 09:32:20 fish // Ensure consistent create_thread ATTR usage // // Revision 1.94 2007/11/21 22:54:14 fish // Use new BEGIN_DEVICE_CLASS_QUERY macro // // Revision 1.93 2007/06/23 16:13:54 jmaynard // Fixing two messages out of internationalization by removing redundant // carriage returns. // // Revision 1.92 2007/06/23 00:04:04 ivan // Update copyright notices to include current year (2007) // // Revision 1.91 2007/01/11 19:54:33 fish // Addt'l keep-alive mods: create associated supporting config-file stmt and panel command where individual customer-preferred values can be specified and/or dynamically modified. // // Revision 1.90 2007/01/10 15:35:49 rbowler // Consoles cannot connect after rev 1.88 // // Revision 1.89 2007/01/10 15:12:11 rbowler // Console keepalive for Unix // // Revision 1.88 2007/01/10 09:32:39 fish // Enable connection keep-alive to try and detect 3270 clients that // have died (MSVC only right now; don't know how to do it on *nix) // // Revision 1.87 2006/12/08 09:43:18 jj // Add CVS message log // #include "hstdinc.h" #include "hercules.h" #include "devtype.h" #include "opcode.h" #include "sr.h" #if defined(WIN32) && defined(OPTION_DYNAMIC_LOAD) && !defined(HDL_USE_LIBTOOL) && !defined(_MSVC_) SYSBLK *psysblk; #define sysblk (*psysblk) #define config_cnslport (*config_cnslport) static #else #if defined(OPTION_DYNAMIC_LOAD) && defined(_MSVC_) DLL_IMPORT #else extern #endif #endif char *config_cnslport; /*-------------------------------------------------------------------*/ /* Ivan Warren 20040227 */ /* This table is used by channel.c to determine if a CCW code is an */ /* immediate command or not */ /* The tape is addressed in the DEVHND structure as 'DEVIMM immed' */ /* 0 : Command is NOT an immediate command */ /* 1 : Command is an immediate command */ /* Note : An immediate command is defined as a command which returns */ /* CE (channel end) during initialisation (that is, no data is */ /* actually transfered. In this case, IL is not indicated for a CCW */ /* Format 0 or for a CCW Format 1 when IL Suppression Mode is in */ /* effect */ /*-------------------------------------------------------------------*/ static BYTE constty_immed[256]= /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ { 0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0, /* 00 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 10 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 20 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 30 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 40 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 50 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 60 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 70 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 80 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 90 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* A0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* B0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* C0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* D0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* E0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; /* F0 */ static BYTE loc3270_immed[256]= /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ { 0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,1, /* 00 */ 0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0, /* 10 */ 0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0, /* 20 */ 0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0, /* 30 */ 0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0, /* 40 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 50 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 60 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 70 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 80 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 90 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* A0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* B0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* C0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* D0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* E0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; /* F0 */ /*-------------------------------------------------------------------*/ /* Telnet command definitions */ /*-------------------------------------------------------------------*/ #define BINARY 0 /* Binary Transmission */ #define IS 0 /* Used by terminal-type negotiation */ #define SEND 1 /* Used by terminal-type negotiation */ #define ECHO_OPTION 1 /* Echo option */ #define SUPPRESS_GA 3 /* Suppress go-ahead option */ #define TIMING_MARK 6 /* Timing mark option */ #define TERMINAL_TYPE 24 /* Terminal type option */ #define NAWS 31 /* Negotiate About Window Size */ #define EOR 25 /* End of record option */ #define EOR_MARK 239 /* End of record marker */ #define SE 240 /* End of subnegotiation parameters */ #define NOP 241 /* No operation */ #define DATA_MARK 242 /* The data stream portion of a Synch. This should always be accompanied by a TCP Urgent notification */ #define BRK 243 /* Break character */ #define IP 244 /* Interrupt Process */ #define AO 245 /* Abort Output */ #define AYT 246 /* Are You There */ #define EC 247 /* Erase character */ #define EL 248 /* Erase Line */ #define GA 249 /* Go ahead */ #define SB 250 /* Subnegotiation of indicated option */ #define WILL 251 /* Indicates the desire to begin performing, or confirmation that you are now performing, the indicated option */ #define WONT 252 /* Indicates the refusal to perform, or continue performing, the indicated option */ #define DO 253 /* Indicates the request that the other party perform, or confirmation that you are expecting the other party to perform, the indicated option */ #define DONT 254 /* Indicates the demand that the other party stop performing, or confirmation that you are no longer expecting the other party to perform, the indicated option */ #define IAC 255 /* Interpret as Command */ /*-------------------------------------------------------------------*/ /* 3270 definitions */ /*-------------------------------------------------------------------*/ /* 3270 local commands (CCWs) */ #define L3270_EAU 0x0F /* Erase All Unprotected */ #define L3270_EW 0x05 /* Erase/Write */ #define L3270_EWA 0x0D /* Erase/Write Alternate */ #define L3270_RB 0x02 /* Read Buffer */ #define L3270_RM 0x06 /* Read Modified */ #define L3270_WRT 0x01 /* Write */ #define L3270_WSF 0x11 /* Write Structured Field */ #define L3270_NOP 0x03 /* No Operation */ #define L3270_SELRM 0x0B /* Select RM */ #define L3270_SELRB 0x1B /* Select RB */ #define L3270_SELRMP 0x2B /* Select RMP */ #define L3270_SELRBP 0x3B /* Select RBP */ #define L3270_SELWRT 0x4B /* Select WRT */ #define L3270_SENSE 0x04 /* Sense */ #define L3270_SENSEID 0xE4 /* Sense ID */ /* 3270 remote commands */ #define R3270_EAU 0x6F /* Erase All Unprotected */ #define R3270_EW 0xF5 /* Erase/Write */ #define R3270_EWA 0x7E /* Erase/Write Alternate */ #define R3270_RB 0xF2 /* Read Buffer */ #define R3270_RM 0xF6 /* Read Modified */ #define R3270_RMA 0x6E /* Read Modified All */ #define R3270_WRT 0xF1 /* Write */ #define R3270_WSF 0xF3 /* Write Structured Field */ /* 3270 orders */ #define O3270_SBA 0x11 /* Set Buffer Address */ #define O3270_SF 0x1D /* Start Field */ #define O3270_SFE 0x29 /* Start Field Extended */ #define O3270_SA 0x28 /* Set Attribute */ #define O3270_IC 0x13 /* Insert Cursor */ #define O3270_MF 0x2C /* Modify Field */ #define O3270_PT 0x05 /* Program Tab */ #define O3270_RA 0x3C /* Repeat to Address */ #define O3270_EUA 0x12 /* Erase Unprotected to Addr */ #define O3270_GE 0x08 /* Graphic Escape */ /* Inbound structured fields */ #define SF3270_AID 0x88 /* Aid value of inbound SF */ #define SF3270_3270DS 0x80 /* SFID of 3270 datastream SF*/ /* 12 bit 3270 buffer address code conversion table */ static BYTE sba_code[] = { "\x40\xC1\xC2\xC3\xC4\xC5\xC6\xC7" "\xC8\xC9\x4A\x4B\x4C\x4D\x4E\x4F" "\x50\xD1\xD2\xD3\xD4\xD5\xD6\xD7" "\xD8\xD9\x5A\x5B\x5C\x5D\x5E\x5F" "\x60\x61\xE2\xE3\xE4\xE5\xE6\xE7" "\xE8\xE9\x6A\x6B\x6C\x6D\x6E\x6F" "\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7" "\xF8\xF9\x7A\x7B\x7C\x7D\x7E\x7F" }; /*-------------------------------------------------------------------*/ /* Internal macro definitions */ /*-------------------------------------------------------------------*/ /* DEBUG_LVL: 0 = none 1 = status 2 = headers 3 = buffers */ #define DEBUG_LVL 0 #if DEBUG_LVL == 0 #define TNSDEBUG1 1 ? ((void)0) : logmsg #define TNSDEBUG2 1 ? ((void)0) : logmsg #define TNSDEBUG3 1 ? ((void)0) : logmsg #endif #if DEBUG_LVL == 1 #define TNSDEBUG1 logmsg #define TNSDEBUG2 1 ? ((void)0) : logmsg #define TNSDEBUG3 1 ? ((void)0) : logmsg #endif #if DEBUG_LVL == 2 #define TNSDEBUG1 logmsg #define TNSDEBUG2 logmsg #define TNSDEBUG3 1 ? ((void)0) : logmsg #endif #if DEBUG_LVL == 3 #define TNSDEBUG1 logmsg #define TNSDEBUG2 logmsg #define TNSDEBUG3 logmsg #endif #define TNSERROR logmsg #define BUFLEN_3270 65536 /* 3270 Send/Receive buffer */ #define BUFLEN_1052 150 /* 1052 Send/Receive buffer */ #undef FIX_QWS_BUG_FOR_MCS_CONSOLES /*-------------------------------------------------------------------*/ /* Static data areas */ /*-------------------------------------------------------------------*/ static HOST_INFO cons_hostinfo; /* Host info for this system */ /*-------------------------------------------------------------------*/ /* SUBROUTINE TO TRACE THE CONTENTS OF AN ASCII MESSAGE PACKET */ /*-------------------------------------------------------------------*/ #if DEBUG_LVL == 3 static void packet_trace(BYTE *addr, int len) { int i, offset; BYTE c; BYTE print_chars[17]; for (offset=0; offset < len; ) { memset(print_chars,0,sizeof(print_chars)); logmsg("+%4.4X ", offset); for (i=0; i < 16; i++) { c = *addr++; if (offset < len) { logmsg("%2.2X", c); print_chars[i] = '.'; if (isprint(c)) print_chars[i] = c; c = guest_to_host(c); if (isprint(c)) print_chars[i] = c; } else { logmsg(" "); } offset++; if ((offset & 3) == 0) { logmsg(" "); } } /* end for(i) */ logmsg(" %s\n", print_chars); } /* end for(offset) */ } /* end function packet_trace */ #else #define packet_trace( _addr, _len) #endif #if 1 struct sockaddr_in * get_inet_socket(char *host_serv) { char *host = NULL; char *serv; struct sockaddr_in *sin; if((serv = strchr(host_serv,':'))) { *serv++ = '\0'; if(*host_serv) host = host_serv; } else serv = host_serv; if(!(sin = malloc(sizeof(struct sockaddr_in)))) return sin; sin->sin_family = AF_INET; if(host) { struct hostent *hostent; hostent = gethostbyname(host); if(!hostent) { logmsg(_("HHCGI001I Unable to determine IP address from %s\n"), host); free(sin); return NULL; } memcpy(&sin->sin_addr,*hostent->h_addr_list,sizeof(sin->sin_addr)); } else sin->sin_addr.s_addr = INADDR_ANY; if(serv) { if(!isdigit(*serv)) { struct servent *servent; servent = getservbyname(serv, "tcp"); if(!servent) { logmsg(_("HHCGI002I Unable to determine port number from %s\n"), host); free(sin); return NULL; } sin->sin_port = servent->s_port; } else sin->sin_port = htons(atoi(serv)); } else { logmsg(_("HHCGI003E Invalid parameter: %s\n"), host_serv); free(sin); return NULL; } return sin; } #endif /*-------------------------------------------------------------------*/ /* SUBROUTINE TO REMOVE ANY IAC SEQUENCES FROM THE DATA STREAM */ /* Returns the new length after deleting IAC commands */ /*-------------------------------------------------------------------*/ static int remove_iac (BYTE *buf, int len) { int m, n, c; for (m=0, n=0; m < len; ) { /* Interpret IAC commands */ if (buf[m] == IAC) { /* Treat IAC in last byte of buffer as IAC NOP */ c = (++m < len)? buf[m++] : NOP; /* Process IAC command */ switch (c) { case IAC: /* Insert single IAC in buffer */ buf[n++] = IAC; break; case BRK: /* Set ATTN indicator */ break; case IP: /* Set SYSREQ indicator */ break; case WILL: /* Skip option negotiation command */ case WONT: case DO: case DONT: m++; break; case SB: /* Skip until IAC SE sequence found */ for (; m < len; m++) { if (buf[m] != IAC) continue; if (++m >= len) break; if (buf[m] == SE) { m++; break; } } /* end for */ default: /* Ignore NOP or unknown command */ break; } /* end switch(c) */ } else { /* Copy data bytes */ if (n < m) buf[n] = buf[m]; m++; n++; } } /* end for */ if (n < m) { TNSDEBUG3("console: DBG001: %d IAC bytes removed, newlen=%d\n", m-n, n); packet_trace (buf, n); } return n; } /* end function remove_iac */ /*-------------------------------------------------------------------*/ /* SUBROUTINE TO DOUBLE UP ANY IAC BYTES IN THE DATA STREAM */ /* Returns the new length after inserting extra IAC bytes */ /*-------------------------------------------------------------------*/ static int double_up_iac (BYTE *buf, int len) { int m, n, x, newlen; /* Count the number of IAC bytes in the data */ for (x=0, n=0; n < len; n++) if (buf[n] == IAC) x++; /* Exit if nothing to do */ if (x == 0) return len; /* Insert extra IAC bytes backwards from the end of the buffer */ newlen = len + x; TNSDEBUG3("console: DBG002: %d IAC bytes added, newlen=%d\n", x, newlen); for (n=newlen, m=len; n > m; ) { buf[--n] = buf[--m]; if (buf[n] == IAC) buf[--n] = IAC; } packet_trace (buf, newlen); return newlen; } /* end function double_up_iac */ /*-------------------------------------------------------------------*/ /* SUBROUTINE TO TRANSLATE A NULL-TERMINATED STRING TO EBCDIC */ /*-------------------------------------------------------------------*/ static BYTE * translate_to_ebcdic (char *str) { int i; /* Array subscript */ BYTE c; /* Character work area */ for (i = 0; str[i] != '\0'; i++) { c = str[i]; str[i] = (isprint(c) ? host_to_guest(c) : SPACE); } return (BYTE *)str; } /* end function translate_to_ebcdic */ /*-------------------------------------------------------------------*/ /* SUBROUTINE TO SEND A DATA PACKET TO THE CLIENT */ /*-------------------------------------------------------------------*/ static int send_packet (int csock, BYTE *buf, int len, char *caption) { int rc; /* Return code */ if (caption != NULL) { TNSDEBUG2("console: DBG003: Sending %s\n", caption); packet_trace (buf, len); } rc = send (csock, buf, len, 0); if (rc < 0) { TNSERROR("console: DBG021: send: %s\n", strerror(HSO_errno)); return -1; } /* end if(rc) */ return 0; } /* end function send_packet */ /*-------------------------------------------------------------------*/ /* SUBROUTINE TO RECEIVE A DATA PACKET FROM THE CLIENT */ /* This subroutine receives bytes from the client. It stops when */ /* the receive buffer is full, or when the last two bytes received */ /* consist of the IAC character followed by a specified delimiter. */ /* If zero bytes are received, this means the client has closed the */ /* connection, and this is treated as an error. */ /* Input: */ /* csock is the socket number */ /* buf points to area to receive data */ /* reqlen is the number of bytes requested */ /* delim is the delimiter character (0=no delimiter) */ /* Output: */ /* buf is updated with data received */ /* The return value is the number of bytes received, or */ /* -1 if an error occurred. */ /*-------------------------------------------------------------------*/ static int recv_packet (int csock, BYTE *buf, int reqlen, BYTE delim) { int rc=0; /* Return code */ int rcvlen=0; /* Length of data received */ while (rcvlen < reqlen) { rc = recv (csock, buf + rcvlen, reqlen - rcvlen, 0); if (rc < 0) { TNSERROR("console: DBG022: recv: %s\n", strerror(HSO_errno)); return -1; } if (rc == 0) { TNSDEBUG1("console: DBG004: Connection closed by client\n"); return -1; } rcvlen += rc; if (delim != '\0' && rcvlen >= 2 && buf[rcvlen-2] == IAC && buf[rcvlen-1] == delim) break; } TNSDEBUG2("console: DBG005: Packet received length=%d\n", rcvlen); packet_trace (buf, rcvlen); return rcvlen; } /* end function recv_packet */ /*-------------------------------------------------------------------*/ /* SUBROUTINE TO RECEIVE A PACKET AND COMPARE WITH EXPECTED VALUE */ /*-------------------------------------------------------------------*/ static int expect (int csock, BYTE *expected, int len, char *caption) { int rc; /* Return code */ BYTE buf[512]; /* Receive buffer */ #if 1 /* TCP/IP for MVS returns the server sequence rather then the client sequence during bin negotiation 19/06/00 Jan Jaeger */ static BYTE do_bin[] = { IAC, DO, BINARY, IAC, WILL, BINARY }; static BYTE will_bin[] = { IAC, WILL, BINARY, IAC, DO, BINARY }; #endif UNREFERENCED(caption); rc = recv_packet (csock, buf, len, 0); if (rc < 0) return -1; #if 1 /* TCP/IP FOR MVS DOES NOT COMPLY TO RFC 1576 THIS IS A BYPASS */ if(memcmp(buf, expected, len) != 0 && !(len == sizeof(will_bin) && memcmp(expected, will_bin, len) == 0 && memcmp(buf, do_bin, len) == 0) ) #else if (memcmp(buf, expected, len) != 0) #endif { TNSDEBUG2("console: DBG006: Expected %s\n", caption); return -1; } TNSDEBUG2("console: DBG007: Received %s\n", caption); return 0; } /* end function expect */ /*-------------------------------------------------------------------*/ /* SUBROUTINE TO NEGOTIATE TELNET PARAMETERS */ /* This subroutine negotiates the terminal type with the client */ /* and uses the terminal type to determine whether the client */ /* is to be supported as a 3270 display console or as a 1052/3215 */ /* printer-keyboard console. */ /* */ /* Valid display terminal types are "IBM-NNNN", "IBM-NNNN-M", and */ /* "IBM-NNNN-M-E", where NNNN is 3270, 3277, 3278, 3279, 3178, 3179, */ /* or 3180, M indicates the screen size (2=25x80, 3=32x80, 4=43x80, */ /* 5=27x132, X=determined by Read Partition Query command), and */ /* -E is an optional suffix indicating that the terminal supports */ /* extended attributes. Displays are negotiated into tn3270 mode. */ /* An optional device number suffix (example: IBM-3270@01F) may */ /* be specified to request allocation to a specific device number. */ /* Valid 3270 printer type is "IBM-3287-1" */ /* */ /* Terminal types whose first four characters are not "IBM-" are */ /* handled as printer-keyboard consoles using telnet line mode. */ /* */ /* Input: */ /* csock Socket number for client connection */ /* Output: */ /* class D=3270 display console, K=printer-keyboard console */ /* P=3270 printer */ /* model 3270 model indicator (2,3,4,5,X) */ /* extatr 3270 extended attributes (Y,N) */ /* devn Requested device number, or FFFF=any device number */ /* Return value: */ /* 0=negotiation successful, -1=negotiation error */ /*-------------------------------------------------------------------*/ static int negotiate(int csock, BYTE *class, BYTE *model, BYTE *extatr, U16 *devn,char *group) { int rc; /* Return code */ char *termtype; /* Pointer to terminal type */ char *s; /* String pointer */ BYTE c; /* Trailing character */ U16 devnum; /* Requested device number */ BYTE buf[512]; /* Telnet negotiation buffer */ static BYTE do_term[] = { IAC, DO, TERMINAL_TYPE }; static BYTE will_term[] = { IAC, WILL, TERMINAL_TYPE }; static BYTE req_type[] = { IAC, SB, TERMINAL_TYPE, SEND, IAC, SE }; static BYTE type_is[] = { IAC, SB, TERMINAL_TYPE, IS }; static BYTE do_eor[] = { IAC, DO, EOR, IAC, WILL, EOR }; static BYTE will_eor[] = { IAC, WILL, EOR, IAC, DO, EOR }; static BYTE do_bin[] = { IAC, DO, BINARY, IAC, WILL, BINARY }; static BYTE will_bin[] = { IAC, WILL, BINARY, IAC, DO, BINARY }; #if 0 static BYTE do_tmark[] = { IAC, DO, TIMING_MARK }; static BYTE will_tmark[] = { IAC, WILL, TIMING_MARK }; static BYTE wont_sga[] = { IAC, WONT, SUPPRESS_GA }; static BYTE dont_sga[] = { IAC, DONT, SUPPRESS_GA }; #endif static BYTE wont_echo[] = { IAC, WONT, ECHO_OPTION }; static BYTE dont_echo[] = { IAC, DONT, ECHO_OPTION }; static BYTE will_naws[] = { IAC, WILL, NAWS }; /* Perform terminal-type negotiation */ rc = send_packet (csock, do_term, sizeof(do_term), "IAC DO TERMINAL_TYPE"); if (rc < 0) return -1; rc = expect (csock, will_term, sizeof(will_term), "IAC WILL TERMINAL_TYPE"); if (rc < 0) return -1; /* Request terminal type */ rc = send_packet (csock, req_type, sizeof(req_type), "IAC SB TERMINAL_TYPE SEND IAC SE"); if (rc < 0) return -1; rc = recv_packet (csock, buf, sizeof(buf)-2, SE); if (rc < 0) return -1; /* Ignore Negotiate About Window Size */ if (rc >= (int)sizeof(will_naws) && memcmp (buf, will_naws, sizeof(will_naws)) == 0) { memmove(buf, &buf[sizeof(will_naws)], (rc - sizeof(will_naws))); rc -= sizeof(will_naws); } if (rc < (int)(sizeof(type_is) + 2) || memcmp(buf, type_is, sizeof(type_is)) != 0 || buf[rc-2] != IAC || buf[rc-1] != SE) { TNSDEBUG2("console: DBG008: Expected IAC SB TERMINAL_TYPE IS\n"); return -1; } buf[rc-2] = '\0'; termtype = (char *)(buf + sizeof(type_is)); TNSDEBUG2("console: DBG009: Received IAC SB TERMINAL_TYPE IS %s IAC SE\n", termtype); /* Check terminal type string for device name suffix */ s = strchr (termtype, '@'); if(s!=NULL) { if(strlen(s)<16) { strlcpy(group,&s[1],16); } } else { group[0]=0; } if (s != NULL && sscanf (s, "@%hx%c", &devnum,&c) == 1) { *devn = devnum; group[0]=0; } else { *devn = 0xFFFF; } /* Test for non-display terminal type */ if (memcmp(termtype, "IBM-", 4) != 0) { #if 0 /* Perform line mode negotiation */ rc = send_packet (csock, do_tmark, sizeof(do_tmark), "IAC DO TIMING_MARK"); if (rc < 0) return -1; rc = expect (csock, will_tmark, sizeof(will_tmark), "IAC WILL TIMING_MARK"); if (rc < 0) return 0; rc = send_packet (csock, wont_sga, sizeof(wont_sga), "IAC WONT SUPPRESS_GA"); if (rc < 0) return -1; rc = expect (csock, dont_sga, sizeof(dont_sga), "IAC DONT SUPPRESS_GA"); if (rc < 0) return -1; #endif if (memcmp(termtype, "ANSI", 4) == 0) { rc = send_packet (csock, wont_echo, sizeof(wont_echo), "IAC WONT ECHO"); if (rc < 0) return -1; rc = expect (csock, dont_echo, sizeof(dont_echo), "IAC DONT ECHO"); if (rc < 0) return -1; } /* Return printer-keyboard terminal class */ *class = 'K'; *model = '-'; *extatr = '-'; return 0; } /* Determine display terminal model */ if (memcmp(termtype+4,"DYNAMIC",7) == 0) { *model = 'X'; *extatr = 'Y'; } else { if (!(memcmp(termtype+4, "3277", 4) == 0 || memcmp(termtype+4, "3270", 4) == 0 || memcmp(termtype+4, "3178", 4) == 0 || memcmp(termtype+4, "3278", 4) == 0 || memcmp(termtype+4, "3179", 4) == 0 || memcmp(termtype+4, "3180", 4) == 0 || memcmp(termtype+4, "3287", 4) == 0 || memcmp(termtype+4, "3279", 4) == 0)) return -1; *model = '2'; *extatr = 'N'; if (termtype[8]=='-') { if (termtype[9] < '1' || termtype[9] > '5') return -1; *model = termtype[9]; if (memcmp(termtype+4, "328",3) == 0) *model = '2'; if (memcmp(termtype+10, "-E", 2) == 0) *extatr = 'Y'; } } /* Perform end-of-record negotiation */ rc = send_packet (csock, do_eor, sizeof(do_eor), "IAC DO EOR IAC WILL EOR"); if (rc < 0) return -1; rc = expect (csock, will_eor, sizeof(will_eor), "IAC WILL EOR IAC DO EOR"); if (rc < 0) return -1; /* Perform binary negotiation */ rc = send_packet (csock, do_bin, sizeof(do_bin), "IAC DO BINARY IAC WILL BINARY"); if (rc < 0) return -1; rc = expect (csock, will_bin, sizeof(will_bin), "IAC WILL BINARY IAC DO BINARY"); if (rc < 0) return -1; /* Return display terminal class */ if (memcmp(termtype+4,"3287",4)==0) *class='P'; else *class = 'D'; return 0; } /* end function negotiate */ /*-------------------------------------------------------------------*/ /* SUBROUTINE TO RECEIVE 3270 DATA FROM THE CLIENT */ /* This subroutine receives bytes from the client and appends them */ /* to any data already in the 3270 receive buffer. */ /* If zero bytes are received, this means the client has closed the */ /* connection, and attention and unit check status is returned. */ /* If the buffer is filled before receiving end of record, then */ /* attention and unit check status is returned. */ /* If the data ends with IAC followed by EOR_MARK, then the data */ /* is scanned to remove any IAC sequences, attention status is */ /* returned, and the read pending indicator is set. */ /* If the data accumulated in the buffer does not yet constitute a */ /* complete record, then zero status is returned, and a further */ /* call must be made to this subroutine when more data is available. */ /*-------------------------------------------------------------------*/ static BYTE recv_3270_data (DEVBLK *dev) { int rc; /* Return code */ int eor = 0; /* 1=End of record received */ /* If there is a complete data record already in the buffer then discard it before reading more data */ if (dev->readpending) { dev->rlen3270 = 0; dev->readpending = 0; } /* The following chunk of code was added to try and catch a race condition that may or may no longer still exist. */ TNSDEBUG1("console: DBG031: verifying data is available...\n"); { fd_set readset; struct timeval tv = {0,0}; /* (non-blocking poll) */ FD_ZERO( &readset ); FD_SET( dev->fd, &readset ); while ( (rc = select ( dev->fd+1, &readset, NULL, NULL, &tv )) < 0 && HSO_EINTR == HSO_errno ) ; /* NOP (keep retrying if EINTR) */ if (rc < 0) { TNSERROR("console: DBG032: select failed: %s\n", strerror(HSO_errno)); return 0; } ASSERT(rc <= 1); if (!FD_ISSET(dev->fd, &readset)) { ASSERT(rc == 0); TNSDEBUG1("console: DBG033: no data available; returning 0...\n"); return 0; } ASSERT(rc == 1); } TNSDEBUG1("console: DBG034: data IS available; attempting recv...\n"); /* Receive bytes from client */ rc = recv (dev->fd, dev->buf + dev->rlen3270, BUFLEN_3270 - dev->rlen3270, 0); if (rc < 0) { if ( HSO_ECONNRESET == HSO_errno ) logmsg( _( "HHCTE014I %4.4X device %4.4X client %s connection reset\n" ), dev->devtype, dev->devnum, inet_ntoa(dev->ipaddr) ); else TNSERROR("console: DBG023: recv: %s\n", strerror(HSO_errno)); dev->sense[0] = SENSE_EC; return (CSW_ATTN | CSW_UC); } /* If zero bytes were received then client has closed connection */ if (rc == 0) { logmsg (_("HHCTE007I %4.4X device %4.4X client %s connection closed\n"), dev->devtype, dev->devnum, inet_ntoa(dev->ipaddr)); dev->sense[0] = SENSE_IR; return (CSW_ATTN | CSW_UC | CSW_DE); } /* Update number of bytes in receive buffer */ dev->rlen3270 += rc; /* Check whether Attn indicator was received */ if (dev->rlen3270 >= 2 && dev->buf[dev->rlen3270 - 2] == IAC && dev->buf[dev->rlen3270 - 1] == BRK) eor = 1; /* Check whether SysRq indicator was received */ if (dev->rlen3270 >= 2 && dev->buf[dev->rlen3270 - 2] == IAC && dev->buf[dev->rlen3270 - 1] == IP) eor = 1; /* Check whether end of record marker was received */ if (dev->rlen3270 >= 2 && dev->buf[dev->rlen3270 - 2] == IAC && dev->buf[dev->rlen3270 - 1] == EOR_MARK) eor = 1; /* If record is incomplete, test for buffer full */ if (eor == 0 && dev->rlen3270 >= BUFLEN_3270) { TNSDEBUG1("console: DBG010: 3270 buffer overflow\n"); dev->sense[0] = SENSE_DC; return (CSW_ATTN | CSW_UC); } /* Return zero status if record is incomplete */ if (eor == 0) return 0; /* Trace the complete 3270 data packet */ TNSDEBUG2("console: DBG011: Packet received length=%d\n", dev->rlen3270); packet_trace (dev->buf, dev->rlen3270); /* Strip off the telnet EOR marker */ dev->rlen3270 -= 2; /* Remove any embedded IAC commands */ dev->rlen3270 = remove_iac (dev->buf, dev->rlen3270); /* Set the read pending indicator and return attention status */ dev->readpending = 1; return (CSW_ATTN); } /* end function recv_3270_data */ /*-------------------------------------------------------------------*/ /* SUBROUTINE TO SOLICIT 3270 DATA FROM THE CLIENT */ /* This subroutine sends a Read or Read Modified command to the */ /* client and then receives the data into the 3270 receive buffer. */ /* This subroutine is called by loc3270_execute_ccw as a result of */ /* processing a Read Buffer CCW, or a Read Modified CCW when no */ /* data is waiting in the 3270 read buffer. It waits until the */ /* client sends end of record. Certain tn3270 clients fail to */ /* flush their buffer until the user presses an attention key; */ /* these clients cause this routine to hang and are not supported. */ /* Since this routine is only called while a channel program is */ /* active on the device, we can rely on the dev->busy flag to */ /* prevent the connection thread from issuing a read and capturing */ /* the incoming data intended for this routine. */ /* The caller MUST hold the device lock. */ /* Returns zero status if successful, or unit check if error. */ /*-------------------------------------------------------------------*/ static BYTE solicit_3270_data (DEVBLK *dev, BYTE cmd) { int rc; /* Return code */ int len; /* Data length */ BYTE buf[32]; /* tn3270 write buffer */ /* Clear the inbound buffer of any unsolicited data accumulated by the connection thread */ dev->rlen3270 = 0; dev->readpending = 0; /* Construct a 3270 read command in the outbound buffer */ len = 0; buf[len++] = cmd; /* Append telnet EOR marker to outbound buffer */ buf[len++] = IAC; buf[len++] = EOR_MARK; /* Send the 3270 read command to the client */ rc = send_packet(dev->fd, buf, len, "3270 Read Command"); if (rc < 0) { dev->sense[0] = SENSE_DC; return (CSW_UC); } /* Receive response data from the client */ do { len = dev->rlen3270; rc = recv_3270_data (dev); TNSDEBUG2("console: DBG012: read buffer: %d bytes received\n", dev->rlen3270 - len); } while(rc == 0); /* Close the connection if an error occurred */ if (rc & CSW_UC) { dev->connected = 0; dev->fd = -1; dev->sense[0] = SENSE_DC; return (CSW_UC); } /* Return zero status to indicate response received */ return 0; } /* end function solicit_3270_data */ /*-------------------------------------------------------------------*/ /* SUBROUTINE TO RECEIVE 1052/3215 DATA FROM THE CLIENT */ /* This subroutine receives keyboard input characters from the */ /* client, and appends the characters to any data already in the */ /* keyboard buffer. */ /* If zero bytes are received, this means the client has closed the */ /* connection, and attention and unit check status is returned. */ /* If the buffer is filled before receiving end of record, then */ /* attention and unit check status is returned. */ /* If a break indication (control-C, IAC BRK, or IAC IP) is */ /* received, the attention and unit exception status is returned. */ /* When carriage return and line feed (CRLF) is received, then */ /* the CRLF is discarded, the data in the keyboard buffer is */ /* translated to EBCDIC, the read pending indicator is set, and */ /* attention status is returned. */ /* If CRLF has not yet been received, then zero status is returned, */ /* and a further call must be made to this subroutine when more */ /* data is available. */ /*-------------------------------------------------------------------*/ static BYTE recv_1052_data (DEVBLK *dev) { int num; /* Number of bytes received */ int i; /* Array subscript */ BYTE buf[BUFLEN_1052]; /* Receive buffer */ BYTE c; /* Character work area */ /* Receive bytes from client */ num = recv (dev->fd, buf, BUFLEN_1052, 0); /* Return unit check if error on receive */ if (num < 0) { TNSERROR("console: DBG024: recv: %s\n", strerror(HSO_errno)); dev->sense[0] = SENSE_EC; return (CSW_ATTN | CSW_UC); } /* If zero bytes were received then client has closed connection */ if (num == 0) { logmsg (_("HHCTE008I Device %4.4X connection closed by client %s\n"), dev->devnum, inet_ntoa(dev->ipaddr)); dev->sense[0] = SENSE_IR; return (CSW_ATTN | CSW_UC); } /* Trace the bytes received */ TNSDEBUG2("console: DBG013: Bytes received length=%d\n", num); packet_trace (buf, num); /* Copy received bytes to keyboard buffer */ for (i = 0; i < num; i++) { /* Decrement keyboard buffer pointer if backspace received */ if (buf[i] == 0x08) { if (dev->keybdrem > 0) dev->keybdrem--; continue; } /* Return unit exception if control-C received */ if (buf[i] == 0x03) { dev->keybdrem = 0; return (CSW_ATTN | CSW_UX); } /* Return unit check if buffer is full */ if (dev->keybdrem >= BUFLEN_1052) { TNSDEBUG1("console: DBG014: Console keyboard buffer overflow\n"); dev->keybdrem = 0; dev->sense[0] = SENSE_EC; return (CSW_ATTN | CSW_UC); } /* Copy character to keyboard buffer */ dev->buf[dev->keybdrem++] = buf[i]; /* Decrement keyboard buffer pointer if telnet erase character sequence received */ if (dev->keybdrem >= 2 && dev->buf[dev->keybdrem - 2] == IAC && dev->buf[dev->keybdrem - 1] == EC) { dev->keybdrem -= 2; if (dev->keybdrem > 0) dev->keybdrem--; continue; } /* Zeroize keyboard buffer pointer if telnet erase line sequence received */ if (dev->keybdrem >= 2 && dev->buf[dev->keybdrem - 2] == IAC && dev->buf[dev->keybdrem - 1] == EL) { dev->keybdrem = 0; continue; } /* Zeroize keyboard buffer pointer if telnet carriage return sequence received */ if (dev->keybdrem >= 2 && dev->buf[dev->keybdrem - 2] == '\r' && dev->buf[dev->keybdrem - 1] == '\0') { dev->keybdrem = 0; continue; } /* Return unit exception if telnet break sequence received */ if (dev->keybdrem >= 2 && dev->buf[dev->keybdrem - 2] == IAC && (dev->buf[dev->keybdrem - 1] == BRK || dev->buf[dev->keybdrem - 1] == IP)) { dev->keybdrem = 0; return (CSW_ATTN | CSW_UX); } /* Return unit check with overrun if telnet CRLF sequence received and more data follows the CRLF */ if (dev->keybdrem >= 2 && dev->buf[dev->keybdrem - 2] == '\r' && dev->buf[dev->keybdrem - 1] == '\n' && i < num - 1) { TNSDEBUG1("console: DBG015: Console keyboard buffer overrun\n"); dev->keybdrem = 0; dev->sense[0] = SENSE_OR; return (CSW_ATTN | CSW_UC); } } /* end for(i) */ /* Return zero status if CRLF was not yet received */ if (dev->keybdrem < 2 || dev->buf[dev->keybdrem - 2] != '\r' || dev->buf[dev->keybdrem - 1] != '\n') return 0; /* Trace the complete keyboard data packet */ TNSDEBUG2("console: DBG016: Packet received length=%d\n", dev->keybdrem); packet_trace (dev->buf, dev->keybdrem); /* Strip off the CRLF sequence */ dev->keybdrem -= 2; /* Translate the keyboard buffer to EBCDIC */ for (i = 0; i < dev->keybdrem; i++) { c = dev->buf[i]; dev->buf[i] = (isprint(c) ? host_to_guest(c) : SPACE); } /* end for(i) */ /* Trace the EBCDIC input data */ TNSDEBUG2("console: DBG017: Input data line length=%d\n", dev->keybdrem); packet_trace (dev->buf, dev->keybdrem); /* Return attention status */ return (CSW_ATTN); } /* end function recv_1052_data */ /* The following code and functions are here * to build a more fancy logo */ #define SF_ATTR_PROTECTED 0x20 #define SF_ATTR_NUMERIC 0x10 /* One of */ #define SF_ATTR_WDISPNSEL 0x00 #define SF_ATTR_WDISPSEL 0x04 #define SF_ATTR_HIGHLIGHT 0x08 #define SF_ATTR_INVISIBLE 0x0C #define SF_ATTR_MDT 0x01 /* static char *herclogo[]={ " HHH HHH The S/370, ESA/390 and z/Architecture", " HHH HHH Emulator", " HHH HHH", " HHH HHH EEEE RRR CCC U U L EEEE SSS", " HHHHHHHHHHHHHHHH E R R C U U L E S", " HHHHHHHHHHHHHHHH EEE RRR C U U L EEE SS", " HHHHHHHHHHHHHHHH E R R C U U L E S", " HHH HHH EEEE R R CCC UU LLLL EEEE SSS ", " HHH HHH", " HHH HHH", " HHH HHH My PC thinks it's a MAINFRAME", "", " Copyright (C) 1999-2010 Roger Bowler, Jan Jaeger, and others"}; */ static char *herclogo[]={ "@ALIGN NONE", "@SBA 0,0", "@SF P", "Hercules Version :", "@SF HP", "$(VERSION)", "@NL", "@SF P", "Host name :", "@SF HP", "$(HOSTNAME)", "@NL", "@SF P", "Host OS :", "@SF HP", "$(HOSTOS)-$(HOSTOSREL) $(HOSTOSVER)", "@NL", "@SF P", "Host Architecture :", "@SF HP", "$(HOSTARCH)", "@NL", "@SF P", "Processors :", "@SF HP", "$(HOSTNUMCPUS)", "@NL", "@SF P", "Chanl Subsys :", "@SF HP", "$(CSS)", "@NL", "@SF P", "Device number :", "@SF HP", "$(CCUU)", "@NL", "@SF P", "Subchannel :", "@SF HP", "$(SUBCHAN)", "@SF P", "@ALIGN LEFT", "", "", " HHH HHH The S/370, ESA/390 and z/Architecture", " HHH HHH Emulator", " HHH HHH", " HHH HHH EEEE RRR CCC U U L EEEE SSS", " HHHHHHHHHHHHHHHH E R R C U U L E S", " HHHHHHHHHHHHHHHH EEE RRR C U U L EEE SS", " HHHHHHHHHHHHHHHH E R R C U U L E S", " HHH HHH EEEE R R CCC UU LLLL EEEE SSS", " HHH HHH", " HHH HHH", " HHH HHH My PC thinks it's a MAINFRAME", "", " Copyright (C) 1999-2010 Roger Bowler, Jan Jaeger, and others"}; #define LOGO_BUFFERSIZE 256; static char *buffer_addchar(char *b,size_t *l,size_t *al,char c) { size_t len; size_t alen; len=*l; alen=*al; if(len>=alen) { if(!alen) { alen=LOGO_BUFFERSIZE; b=malloc(alen); if(!b) { return NULL; } } else { alen+=LOGO_BUFFERSIZE; b=realloc(b,alen); if(!b) { return NULL; } } } b[len++]=c; *al=alen; *l=len; return b; } static char *buffer_addstring(char *b,size_t *l,size_t *al,char *s) { size_t i; for(i=0;s[i]!=0;i++) { b=buffer_addchar(b,l,al,s[i]); if(!b) { return NULL; } } return b; } static char *buffer_addsba(char *b,size_t *l,size_t *al,int x, int y) { int pos; pos=x*80+y; b=buffer_addchar(b,l,al,0x11); if(!b) return NULL; b=buffer_addchar(b,l,al,sba_code[pos>>6]); if(!b) return NULL; b=buffer_addchar(b,l,al,sba_code[pos & 0x3f]); return b; } static char *buffer_addsf(char *b,size_t *l,size_t *al,int a) { b=buffer_addchar(b,l,al,0x1d); if(!b) return NULL; b=buffer_addchar(b,l,al,sba_code[a & 0x3f]); return b; } #define ALIGN_NONE 0 #define ALIGN_CENTER 1 #define ALIGN_LEFT 2 #define ALIGN_RIGHT 3 static char *build_logo(char **logodata,size_t logosize,size_t *blen) { size_t len; size_t alen; char *bfr; char *cline; size_t i,j; char *verb; char *rest; int xpos,ypos; int attr; int align; char *wrk; bfr=NULL; len=0; alen=0; bfr=buffer_addchar(bfr,&len,&alen,0xf5); bfr=buffer_addchar(bfr,&len,&alen,0x42); if(bfr==NULL) { return NULL; } align=ALIGN_NONE; xpos=0; ypos=0; attr=SF_ATTR_PROTECTED; for(i=0;i Device block */ size_t len; /* Data length */ int csock; /* Socket for conversation */ struct sockaddr_in client; /* Client address structure */ socklen_t namelen; /* Length of client structure*/ char *clientip; /* Addr of client ip address */ U16 devnum; /* Requested device number */ BYTE class; /* D=3270, P=3287, K=3215/1052 */ BYTE model; /* 3270 model (2,3,4,5,X) */ BYTE extended; /* Extended attributes (Y,N) */ char buf[1920]; /* Message buffer */ char conmsg[256]; /* Connection message */ char devmsg[64]; /* Device message */ char hostmsg[256]; /* Host ID message */ char num_procs[16]; /* #of processors string */ char rejmsg[256]; /* Rejection message */ char group[16]; /* Console group */ size_t logoheight; char *logobfr; char *logoout; logobfr=NULL; /* Load the socket address from the thread parameter */ csock = *csockp; /* Obtain the client's IP address */ namelen = sizeof(client); rc = getpeername (csock, (struct sockaddr *)&client, &namelen); /* Log the client's IP address and hostname */ clientip = strdup(inet_ntoa(client.sin_addr)); #if 0 // The following isn't really needed and hangs under unusual // network configuration settings and thus has been removed. { struct hostent* pHE; /* Addr of hostent structure */ char* clientname; /* Addr of client hostname */ pHE = gethostbyaddr ((unsigned char*)(&client.sin_addr), sizeof(client.sin_addr), AF_INET); if (pHE != NULL && pHE->h_name != NULL && pHE->h_name[0] != '\0') { clientname = (char*) pHE->h_name; } else { clientname = "host name unknown"; } TNSDEBUG1("console: DBG018: Received connection from %s (%s)\n", clientip, clientname); } #else TNSDEBUG1("console: DBG018: Received connection from %s\n", clientip ); #endif /* Negotiate telnet parameters */ rc = negotiate (csock, &class, &model, &extended, &devnum, group); if (rc != 0) { close_socket (csock); if (clientip) free(clientip); return NULL; } /* Look for an available console device */ for (dev = sysblk.firstdev; dev != NULL; dev = dev->nextdev) { /* Loop if the device is invalid */ if ( !dev->allocated ) continue; /* Loop if non-matching device type */ if (class == 'D' && dev->devtype != 0x3270) continue; if (class == 'P' && dev->devtype != 0x3287) continue; if (class == 'K' && dev->devtype != 0x1052 && dev->devtype != 0x3215) continue; /* Loop if a specific device number was requested and this device is not the requested device number */ if (devnum != 0xFFFF && dev->devnum != devnum) continue; /* Loop if no specific devnum was requested * AND * a group was requested OR the device is in a group * AND * The groups match * this device is not in that device group */ if(devnum==0xFFFF && (group[0] || dev->filename[0])) { if(strncmp(group,dev->filename,16)!=0) { continue; } } /* Obtain the device lock */ obtain_lock (&dev->lock); /* Test for available device */ if (dev->connected == 0) { /* Check ipaddr mask to see if client allowed on this device */ if ( (client.sin_addr.s_addr & dev->acc_ipmask) != dev->acc_ipaddr ) { release_lock (&dev->lock); if ( 0xFFFF == devnum ) /* If they did NOT request a spe- */ continue; /* cifc devnum, then keep looking */ dev = NULL; /* Otherwise they did, */ break; /* but it's not available */ } /* Claim this device for the client */ dev->connected = 1; dev->fd = csock; dev->ipaddr = client.sin_addr; dev->mod3270 = model; dev->eab3270 = (extended == 'Y' ? 1 : 0); /* Reset the console device */ dev->readpending = 0; dev->rlen3270 = 0; dev->keybdrem = 0; memset (&dev->scsw, 0, sizeof(SCSW)); memset (&dev->pciscsw, 0, sizeof(SCSW)); dev->busy = dev->reserved = dev->suspended = dev->pending = dev->pcipending = dev->attnpending = 0; release_lock (&dev->lock); break; } /* Release the device lock */ release_lock (&dev->lock); } /* end for(dev) */ /* Build connection message for client */ if ( cons_hostinfo.num_procs > 1 ) snprintf( num_procs, sizeof(num_procs), "MP=%d", cons_hostinfo.num_procs ); else strlcpy( num_procs, "UP", sizeof(num_procs) ); snprintf ( hostmsg, sizeof(hostmsg), "running on %s (%s-%s.%s %s %s)" ,cons_hostinfo.nodename ,cons_hostinfo.sysname ,cons_hostinfo.release ,cons_hostinfo.version ,cons_hostinfo.machine ,num_procs ); snprintf (conmsg, sizeof(conmsg), "Hercules version %s built on %s %s", VERSION, __DATE__, __TIME__); /* Reject the connection if no available console device */ if (dev == NULL) { /* Build the rejection message */ if (devnum == 0xFFFF) { if(!group[0]) { snprintf (rejmsg, sizeof(rejmsg), "Connection rejected, no available %s device", (class=='D' ? "3270" : (class=='P' ? "3287" : "1052 or 3215"))); } else { snprintf (rejmsg, sizeof(rejmsg), "Connection rejected, no available %s devices in the %s group", (class=='D' ? "3270" : (class=='P' ? "3287" : "1052 or 3215")),group); } } else { snprintf (rejmsg, sizeof(rejmsg), "Connection rejected, device %4.4X unavailable", devnum); } TNSDEBUG1( "DBG019: %s\n", rejmsg); /* Send connection rejection message to client */ if (class != 'K') { len = snprintf (buf, sizeof(buf), "\xF5\x40\x11\x40\x40\x1D\x60%s" "\x11\xC1\x50\x1D\x60%s" "\x11\xC2\x60\x1D\x60%s", translate_to_ebcdic(conmsg), translate_to_ebcdic(hostmsg), translate_to_ebcdic(rejmsg)); if (len < sizeof(buf)) { buf[len++] = IAC; } else { ASSERT(FALSE); } if (len < sizeof(buf)) { buf[len++] = EOR_MARK; } else { ASSERT(FALSE); } } else { len = snprintf (buf, sizeof(buf), "%s\r\n%s\r\n%s\r\n", conmsg, hostmsg, rejmsg); } if (class != 'P') /* do not write connection resp on 3287 */ { rc = send_packet (csock, (BYTE *)buf, len, "CONNECTION RESPONSE"); } /* Close the connection and terminate the thread */ SLEEP (5); close_socket (csock); if (clientip) free(clientip); return NULL; } else { snprintf (devmsg, sizeof(devmsg), "Connected to device %d:%4.4X", SSID_TO_LCSS(dev->ssid), dev->devnum); } logmsg (_("HHCTE009I Client %s connected to %4.4X device %d:%4.4X\n"), clientip, dev->devtype, SSID_TO_LCSS(dev->ssid), dev->devnum); /* Send connection message to client */ if (class != 'K') { #if defined(OPTION_CONFIG_SYMBOLS) set_symbol("VERSION",VERSION); set_symbol("BDATE",__DATE__); set_symbol("BTIME",__TIME__); set_symbol("HOSTNAME",cons_hostinfo.nodename); set_symbol("HOSTOS",cons_hostinfo.sysname); set_symbol("HOSTOSREL",cons_hostinfo.release); set_symbol("HOSTOSVER",cons_hostinfo.version); set_symbol("HOSTARCH",cons_hostinfo.machine); set_symbol("HOSTNUMCPUS",num_procs); set_symbol("LPARNAME",str_lparname()); snprintf(conmsg,sizeof(conmsg),"%3.3X",dev->devnum); set_symbol("CUU",conmsg); snprintf(conmsg,sizeof(conmsg),"%3.3x",dev->devnum); set_symbol("cuu",conmsg); snprintf(conmsg,sizeof(conmsg),"%4.4X",dev->devnum); #if defined(_FEATURE_INTEGRATED_3270_CONSOLE) if (dev == sysblk.sysgdev) strncpy(conmsg,"SYSG",sizeof(conmsg)); #endif /*defined(_FEATURE_INTEGRATED_3270_CONSOLE)*/ set_symbol("CCUU",conmsg); snprintf(conmsg,sizeof(conmsg),"%4.4x",dev->devnum); set_symbol("ccuu",conmsg); snprintf(conmsg,sizeof(conmsg),"%d",SSID_TO_LCSS(dev->ssid)); set_symbol("CSS",conmsg); snprintf(conmsg,sizeof(conmsg),"%4.4X",dev->subchan); set_symbol("SUBCHAN",conmsg); #endif // defined(OPTION_CONFIG_SYMBOLS) if(sysblk.herclogo!=NULL) { logobfr=build_logo(sysblk.herclogo,sysblk.logolines,&len); } else { logoheight=sizeof(herclogo)/sizeof(char *); logobfr=build_logo(herclogo,logoheight,&len); } logoout=logobfr; } else { len = snprintf (buf, sizeof(buf), "%s\r\n%s\r\n%s\r\n", conmsg, hostmsg, devmsg); logoout=buf; } if (class != 'P') /* do not write connection resp on 3287 */ { rc = send_packet (csock, (BYTE *)logoout, len, "CONNECTION RESPONSE"); } if(logobfr) { free(logobfr); } /* Raise attention interrupt for the device, IF... (1) this is NOT a 3287 printer device, -AND- (2) this is NOT the System-370 mode initial power-on state and it is not the SYSG console */ if (class != 'P' #if defined(_FEATURE_INTEGRATED_3270_CONSOLE) && dev != sysblk.sysgdev #endif /*defined(_FEATURE_INTEGRATED_3270_CONSOLE)*/ && !INITIAL_POWERON_370()) device_attention (dev, CSW_DE); /* Try to detect dropped connections */ socket_keepalive( csock, sysblk.kaidle, sysblk.kaintv, sysblk.kacnt ); /* Signal connection thread to redrive its select loop */ SIGNAL_CONSOLE_THREAD(); if (clientip) free(clientip); return NULL; } /* end function connect_client */ /*-------------------------------------------------------------------*/ /* CONSOLE CONNECTION AND ATTENTION HANDLER THREAD */ /*-------------------------------------------------------------------*/ static int console_cnslcnt = 0; /* count of connected terms */ static LOCK console_lock; /* console_cnslcnt lock */ static int did_init = 0; /* console_lock initialized */ static void console_shutdown(void * unused) { UNREFERENCED(unused); obtain_lock( &console_lock ); { console_cnslcnt = 0; SIGNAL_CONSOLE_THREAD(); } release_lock( &console_lock ); } static void * console_connection_handler (void *arg) { int rc = 0; /* Return code */ int lsock; /* Socket for listening */ int csock; /* Socket for conversation */ struct sockaddr_in *server; /* Server address structure */ fd_set readset; /* Read bit map for select */ int maxfd; /* Highest fd for select */ int optval; /* Argument for setsockopt */ TID tidneg; /* Negotiation thread id */ DEVBLK *dev; /* -> Device block */ BYTE unitstat; /* Status after receive data */ UNREFERENCED(arg); hdl_adsc("console_shutdown",console_shutdown, NULL); /* Display thread started message on control panel */ logmsg (_("HHCTE001I Console connection thread started: " "tid="TIDPAT", pid=%d\n"), thread_id(), getpid()); /* Get information about this system */ init_hostinfo( &cons_hostinfo ); /* Obtain a socket */ lsock = socket (AF_INET, SOCK_STREAM, 0); if (lsock < 0) { TNSERROR("console: DBG025: socket: %s\n", strerror(HSO_errno)); return NULL; } /* Allow previous instance of socket to be reused */ optval = 1; setsockopt (lsock, SOL_SOCKET, SO_REUSEADDR, (GETSET_SOCKOPT_T*)&optval, sizeof(optval)); /* Prepare the sockaddr structure for the bind */ if(!( server = get_inet_socket(config_cnslport) )) { logmsg(_("HHCTE010E CNSLPORT statement invalid: %s\n"), config_cnslport); return NULL; } /* Attempt to bind the socket to the port */ do { rc = bind (lsock, (struct sockaddr *)server, sizeof(struct sockaddr_in)); if (rc == 0 || HSO_errno != HSO_EADDRINUSE) break; logmsg (_("HHCTE002W Waiting for port %u to become free\n"), ntohs(server->sin_port)); SLEEP(10); } while (console_cnslcnt); if (rc != 0) { TNSERROR("console: DBG026: bind: %s\n", strerror(HSO_errno)); return NULL; } /* Put the socket into listening state */ if ((rc = listen (lsock, 10)) < 0) { TNSERROR("console: DBG027: listen: %s\n", strerror(HSO_errno)); return NULL; } logmsg (_("HHCTE003I Waiting for console connection on port %u\n"), ntohs(server->sin_port)); /* Handle connection requests and attention interrupts */ for (;;) { /* Check if time to exit */ int time_to_exit; obtain_lock( &console_lock ); time_to_exit = console_cnslcnt <= 0 ? 1 : 0; release_lock( &console_lock ); if (time_to_exit) break; /* Initialize the select parameters */ FD_ZERO ( &readset ); maxfd=INT_MIN; FD_SET ( lsock, &readset ); maxfd = lsock; SUPPORT_WAKEUP_CONSOLE_SELECT_VIA_PIPE( maxfd, &readset ); /* Include the socket for each valid connected console */ for (dev = sysblk.firstdev; dev != NULL; dev = dev->nextdev) { if ( !dev->allocated) continue; obtain_lock( &dev->lock ); { if ( dev->console ) { if ( dev->connected ) { /* VERIFY that the file descriptor is valid. If it's NOT, then IGNORE this console device since it's thus obvious that SOMETHING has gone wrong SOMEWHERE at some point! (some sort of race condition SOMEWHERE, obviously) */ if (dev->fd < 0) { // Ah-HA! We may have FINALLY found (or at // least have gotten a little bit closer to // finding) the ROOT CAUSE of our problematic // "DBG028 select: Bad FIle Number" problem! logmsg ( "\n" "*********** DBG028 CONSOLE BUG ***********\n" "device %4.4X: 'connected', but dev->fd = -1\n" "\n" ,dev->devnum ); dev->connected = 0; // (since it's not connected!) } else { /* Add it to our read set only if it's not busy nor interrupt pending */ if (1 && (!dev->busy || (dev->scsw.flag3 & SCSW3_AC_SUSP)) && !IOPENDING(dev) && !(dev->scsw.flag3 & SCSW3_SC_PEND) ) { FD_SET (dev->fd, &readset); if (dev->fd > maxfd) maxfd = dev->fd; } } } else // ( !dev->connected ) { if ( dev->fd >= 0 ) { close_socket ( dev->fd ); dev->fd = -1; } } /* if (dev->connected) */ } /* if (dev->console) */ } release_lock( &dev->lock ); } /* end for(dev) */ /* Wait for a file descriptor to become ready */ rc = select ( maxfd+1, &readset, NULL, NULL, NULL ); /* Clear the pipe signal if necessary */ RECV_CONSOLE_THREAD_PIPE_SIGNAL(); /* Log select errors */ if (rc < 0 ) { int select_errno = HSO_errno; // (preserve orig errno) static int issue_errmsg = 1; // (prevents msgs flood) if (EBADF == select_errno) { // Don't issue message more frequently // than once every second or so, just in // case the condition that's causing it // keeps reoccurring over and over... static struct timeval prev = {0,0}; struct timeval curr; struct timeval diff; gettimeofday( &curr, NULL ); timeval_subtract( &prev, &curr, &diff ); // Has it been longer than one second // since we last issued this message? if (diff.tv_sec >= 1) { issue_errmsg = 1; prev.tv_sec = curr.tv_sec; prev.tv_usec = curr.tv_usec; } else issue_errmsg = 0; // (prevents msgs flood) } else issue_errmsg = 1; if ( issue_errmsg && EINTR != select_errno ) { TNSERROR("console: DBG028: select: %s\n", strerror(select_errno)); usleep(50000); // (wait a bit; maybe it'll fix itself??) } continue; } /* If a client connection request has arrived then accept it */ if (FD_ISSET(lsock, &readset)) { /* Accept a connection and create conversation socket */ csock = accept (lsock, NULL, NULL); if (csock < 0) { TNSERROR("console: DBG029: accept: %s\n", strerror(HSO_errno)); continue; } /* Create a thread to complete the client connection */ if ( create_thread (&tidneg, DETACHED, connect_client, &csock, "connect_client") ) { TNSERROR("console: DBG030: connect_client create_thread: %s\n", strerror(errno)); close_socket (csock); } } /* end if(FD_ISSET(lsock, &readset)) */ /* Check if any connected client has data ready to send */ for (dev = sysblk.firstdev; dev != NULL; dev = dev->nextdev) { /* Obtain the device lock */ obtain_lock (&dev->lock); /* Test for valid connected console with data available */ if (1 && dev->allocated && dev->console && dev->connected && (!dev->busy || (dev->scsw.flag3 & SCSW3_AC_SUSP)) && !( IOPENDING(dev) || (dev->scsw.flag3 & SCSW3_SC_PEND) ) && FD_ISSET (dev->fd, &readset) ) { /* Receive console input data from the client */ if ((dev->devtype == 0x3270) || (dev->devtype == 0x3287)) unitstat = recv_3270_data (dev); else unitstat = recv_1052_data (dev); /* Nothing more to do if incomplete record received */ if (unitstat == 0) { release_lock (&dev->lock); continue; } /* Close the connection if an error occurred */ if (unitstat & CSW_UC) { close_socket (dev->fd); dev->fd = -1; dev->connected = 0; } /* Indicate that data is available at the device */ if(dev->rlen3270) dev->readpending = 1; /* Release the device lock */ release_lock (&dev->lock); /* Raise attention interrupt for the device */ /* Do NOT raise attention interrupt for 3287 */ /* Otherwise zVM loops after ENABLE ccuu */ /* Following 5 lines are repeated on Hercules console: */ /* console: sending 3270 data */ /* +0000 F5C2FFEF */ /* console: Packet received length=7 */ /* +0000 016CD902 00FFEF */ /* I do not know what is this */ /* console: CCUU attention requests raised */ /* Do not raise attention interrupt for the SYSG console */ /* Do NOT raise attention interrupt if this is */ /* the System-370 mode initial power-on state */ if (1 && dev->connected && dev->devtype != 0x3287 #if defined(_FEATURE_INTEGRATED_3270_CONSOLE) && dev != sysblk.sysgdev #endif /*defined(_FEATURE_INTEGRATED_3270_CONSOLE)*/ && !INITIAL_POWERON_370() ) { rc = device_attention (dev, unitstat); /* Trace the attention request */ TNSDEBUG2("console: DBG020: " "%4.4X attention request %s; rc=%d\n", dev->devnum, (rc == 0 ? "raised" : "rejected"), rc); } #if defined(_FEATURE_INTEGRATED_3270_CONSOLE) /* For the SYSG console, generate an external interrupt */ if (dev == sysblk.sysgdev && dev->connected) { sclp_sysg_attention(); } #endif /*defined(_FEATURE_INTEGRATED_3270_CONSOLE)*/ continue; /* (note: dev->lock already released) */ } /* end if(data available) */ /* Release the device lock */ release_lock (&dev->lock); } /* end for(dev) */ } /* end for */ /* Close all connected terminals */ for (dev = sysblk.firstdev; dev != NULL; dev = dev->nextdev) { /* Obtain the device lock */ obtain_lock (&dev->lock); /* Test for connected console with data available */ if (dev->console && dev->fd>=0) { close_socket(dev->fd); dev->connected=0; dev->fd=-1; } release_lock (&dev->lock); } /* Close the listening socket */ close_socket (lsock); free(server); logmsg (_("HHCTE004I Console connection thread terminated\n")); sysblk.cnsltid = 0; return NULL; } /* end function console_connection_handler */ static int console_initialise() { int rc = 0; if (!did_init) { did_init = 1; initialize_lock( &console_lock ); } obtain_lock( &console_lock ); { console_cnslcnt++; if (!sysblk.cnsltid) { if ( create_thread (&sysblk.cnsltid, DETACHED, console_connection_handler, NULL, "console_connection_handler") ) { logmsg (_("HHCTE005E Cannot create console thread: %s\n"), strerror(errno)); rc = 1; } } } release_lock( &console_lock ); return rc; } static void console_remove(DEVBLK *dev) { obtain_lock( &console_lock ); { dev->connected = 0; dev->console = 0; dev->fd = -1; if (console_cnslcnt <= 0) logmsg(_("** BUG! console_remove() error! **\n")); else console_cnslcnt--; SIGNAL_CONSOLE_THREAD(); } release_lock( &console_lock ); } /*-------------------------------------------------------------------*/ /* INITIALIZE THE 3270 DEVICE HANDLER */ /*-------------------------------------------------------------------*/ static int loc3270_init_handler ( DEVBLK *dev, int argc, char *argv[] ) { int ac = 0; /* Indicate that this is a console device */ dev->console = 1; /* Reset device dependent flags */ dev->connected = 0; /* Set number of sense bytes */ dev->numsense = 1; /* Set the size of the device buffer */ dev->bufsize = BUFLEN_3270; if(!sscanf(dev->typname,"%hx",&(dev->devtype))) dev->devtype = 0x3270; #if defined(_FEATURE_INTEGRATED_3270_CONSOLE) /* Extra initialisation for the SYSG console */ if (strcasecmp(dev->typname,"SYSG") == 0) { dev->pmcw.flag5 &= ~PMCW5_V; // Not a regular device if (sysblk.sysgdev != NULL) { logmsg(_("HHCTE017E Device %4.4X: Duplicate SYSG console definition\n"), dev->devnum); return -1; } } #endif /*defined(_FEATURE_INTEGRATED_3270_CONSOLE)*/ /* Initialize the device identifier bytes */ dev->devid[0] = 0xFF; dev->devid[1] = 0x32; /* Control unit type is 3274-1D */ dev->devid[2] = 0x74; dev->devid[3] = 0x1D; dev->devid[4] = 0x32; /* Device type is 3278-2 */ if ((dev->devtype & 0xFF)==0x70) { dev->devid[5] = 0x78; dev->devid[6] = 0x02; } else { dev->devid[5] = dev->devtype & 0xFF; /* device type is 3287-1 */ dev->devid[6] = 0x01; } dev->numdevid = 7; dev->filename[0] = 0; dev->acc_ipaddr = 0; dev->acc_ipmask = 0; if (argc > 0) // group name? { if ('*' == argv[ac][0] && '\0' == argv[ac][1]) ; // NOP (not really a group name; an '*' is // simply used as an argument place holder) else strlcpy(dev->filename,argv[ac],sizeof(dev->filename)); argc--; ac++; if (argc > 0) // ip address? { if ((dev->acc_ipaddr = inet_addr(argv[ac])) == (in_addr_t)(-1)) { logmsg(_("HHCTE011E Device %4.4X: Invalid IP address: %s\n"), dev->devnum, argv[ac]); return -1; } else { argc--; ac++; if (argc > 0) // ip addr mask? { if ((dev->acc_ipmask = inet_addr(argv[ac])) == (in_addr_t)(-1)) { logmsg(_("HHCTE012E Device %4.4X: Invalid mask value: %s\n"), dev->devnum, argv[ac]); return -1; } else { argc--; ac++; if (argc > 0) // too many args? { logmsg(_("HHCTE013E Device %4.4X: Extraneous argument(s): %s...\n"), dev->devnum, argv[ac] ); return -1; } } } else dev->acc_ipmask = (in_addr_t)(-1); } } } #if defined(_FEATURE_INTEGRATED_3270_CONSOLE) /* Extra initialisation for the SYSG console */ if (strcasecmp(dev->typname,"SYSG") == 0) { /* Save the address of the SYSG console devblk */ sysblk.sysgdev = dev; } #endif /*defined(_FEATURE_INTEGRATED_3270_CONSOLE)*/ return console_initialise(); } /* end function loc3270_init_handler */ /*-------------------------------------------------------------------*/ /* QUERY THE 3270 DEVICE DEFINITION */ /*-------------------------------------------------------------------*/ static void loc3270_query_device (DEVBLK *dev, char **class, int buflen, char *buffer) { BEGIN_DEVICE_CLASS_QUERY( "DSP", dev, class, buflen, buffer ); if (dev->connected) { snprintf (buffer, buflen, "%s", inet_ntoa(dev->ipaddr)); } else { char acc[48]; if (dev->acc_ipaddr || dev->acc_ipmask) { char ip [16]; char mask [16]; struct in_addr xxxx; xxxx.s_addr = dev->acc_ipaddr; snprintf( ip, sizeof( ip ), "%s", inet_ntoa( xxxx )); xxxx.s_addr = dev->acc_ipmask; snprintf( mask, sizeof( mask ), "%s", inet_ntoa( xxxx )); snprintf( acc, sizeof( acc ), "%s mask %s", ip, mask ); } else acc[0] = 0; if (dev->filename[0]) { snprintf(buffer, buflen, "GROUP=%s%s%s", dev->filename, acc[0] ? " " : "", acc); } else { if (acc[0]) { snprintf(buffer, buflen, "* %s", acc); } else buffer[0] = 0; } } } /* end function loc3270_query_device */ /*-------------------------------------------------------------------*/ /* CLOSE THE 3270 DEVICE HANDLER */ /*-------------------------------------------------------------------*/ static int loc3270_close_device ( DEVBLK *dev ) { #if defined(_FEATURE_INTEGRATED_3270_CONSOLE) /* Clear the pointer to the SYSG console */ if (dev == sysblk.sysgdev) { sysblk.sysgdev = NULL; } #endif /*defined(_FEATURE_INTEGRATED_3270_CONSOLE)*/ console_remove(dev); return 0; } /* end function loc3270_close_device */ /*-------------------------------------------------------------------*/ /* 3270 Hercules Suspend/Resume text units */ /*-------------------------------------------------------------------*/ #define SR_DEV_3270_BUF ( SR_DEV_3270 | 0x001 ) #define SR_DEV_3270_EWA ( SR_DEV_3270 | 0x002 ) #define SR_DEV_3270_POS ( SR_DEV_3270 | 0x003 ) /*-------------------------------------------------------------------*/ /* 3270 Hercules Suspend Routine */ /*-------------------------------------------------------------------*/ static int loc3270_hsuspend(DEVBLK *dev, void *file) { size_t rc, len; BYTE buf[BUFLEN_3270]; if (!dev->connected) return 0; SR_WRITE_VALUE(file, SR_DEV_3270_POS, dev->pos3270, sizeof(dev->pos3270)); SR_WRITE_VALUE(file, SR_DEV_3270_EWA, dev->ewa3270, 1); obtain_lock(&dev->lock); rc = solicit_3270_data (dev, R3270_RB); if (rc == 0 && dev->rlen3270 > 0 && dev->rlen3270 <= BUFLEN_3270) { len = dev->rlen3270; memcpy (buf, dev->buf, len); } else len = 0; release_lock(&dev->lock); if (len) SR_WRITE_BUF(file, SR_DEV_3270_BUF, buf, len); return 0; } /*-------------------------------------------------------------------*/ /* 3270 Hercules Resume Routine */ /*-------------------------------------------------------------------*/ static int loc3270_hresume(DEVBLK *dev, void *file) { size_t rc, key, len, rbuflen = 0, pos = 0; BYTE *rbuf = NULL, buf[BUFLEN_3270]; do { SR_READ_HDR(file, key, len); switch (key) { case SR_DEV_3270_POS: SR_READ_VALUE(file, len, &pos, sizeof(pos)); break; case SR_DEV_3270_EWA: SR_READ_VALUE(file, len, &rc, sizeof(rc)); dev->ewa3270 = rc; break; case SR_DEV_3270_BUF: rbuflen = len; rbuf = malloc(len); if (rbuf == NULL) { logmsg(_("HHCTE090E %4.4X malloc() failed for resume buf: %s\n"), dev->devnum, strerror(errno)); return 0; } SR_READ_BUF(file, rbuf, rbuflen); break; default: SR_READ_SKIP(file, len); break; } /* switch (key) */ } while ((key & SR_DEV_MASK) == SR_DEV_3270); /* Dequeue any I/O interrupts for this device */ DEQUEUE_IO_INTERRUPT(&dev->ioint); DEQUEUE_IO_INTERRUPT(&dev->pciioint); DEQUEUE_IO_INTERRUPT(&dev->attnioint); /* Restore the 3270 screen image if connected and buf was provided */ if (dev->connected && rbuf && rbuflen > 3) { obtain_lock(&dev->lock); /* Construct buffer to send to the 3270 */ len = 0; buf[len++] = dev->ewa3270 ? R3270_EWA : R3270_EW; buf[len++] = 0xC2; memcpy (&buf[len], &rbuf[3], rbuflen - 3); len += rbuflen - 3; buf[len++] = O3270_SBA; buf[len++] = rbuf[1]; buf[len++] = rbuf[2]; buf[len++] = O3270_IC; /* Double up any IAC's in the data */ len = double_up_iac (buf, len); /* Append telnet EOR marker */ buf[len++] = IAC; buf[len++] = EOR_MARK; /* Restore the 3270 screen */ rc = send_packet(dev->fd, buf, len, "3270 data"); dev->pos3270 = pos; release_lock(&dev->lock); } if (rbuf) free(rbuf); return 0; } /*-------------------------------------------------------------------*/ /* INITIALIZE THE 1052/3215 DEVICE HANDLER */ /*-------------------------------------------------------------------*/ static int constty_init_handler ( DEVBLK *dev, int argc, char *argv[] ) { int ac=0; /* Indicate that this is a console device */ dev->console = 1; /* Set number of sense bytes */ dev->numsense = 1; /* Initialize device dependent fields */ dev->keybdrem = 0; /* Set length of print buffer */ dev->bufsize = BUFLEN_1052; /* Assume we want to prompt */ dev->prompt1052 = 1; /* Is there an argument? */ if (argc > 0) { /* Look at the argument and set noprompt flag if specified. */ if (strcasecmp(argv[ac], "noprompt") == 0) { dev->prompt1052 = 0; ac++; argc--; } // (else it's a group name...) } if(!sscanf(dev->typname,"%hx",&(dev->devtype))) dev->devtype = 0x1052; /* Initialize the device identifier bytes */ dev->devid[0] = 0xFF; dev->devid[1] = dev->devtype >> 8; dev->devid[2] = dev->devtype & 0xFF; dev->devid[3] = 0x00; dev->devid[4] = dev->devtype >> 8; dev->devid[5] = dev->devtype & 0xFF; dev->devid[6] = 0x00; dev->numdevid = 7; dev->filename[0] = 0; dev->acc_ipaddr = 0; dev->acc_ipmask = 0; if (argc > 0) // group name? { if ('*' == argv[ac][0] && '\0' == argv[ac][1]) ; // NOP (not really a group name; an '*' is // simply used as an argument place holder) else strlcpy(dev->filename,argv[ac],sizeof(dev->filename)); argc--; ac++; if (argc > 0) // ip address? { if ((dev->acc_ipaddr = inet_addr(argv[ac])) == (in_addr_t)(-1)) { logmsg(_("HHCTE011E Device %4.4X: Invalid IP address: %s\n"), dev->devnum, argv[ac]); return -1; } else { argc--; ac++; if (argc > 0) // ip addr mask? { if ((dev->acc_ipmask = inet_addr(argv[ac])) == (in_addr_t)(-1)) { logmsg(_("HHCTE012E Device %4.4X: Invalid mask value: %s\n"), dev->devnum, argv[ac]); return -1; } else { argc--; ac++; if (argc > 0) // too many args? { logmsg(_("HHCTE013E Device %4.4X: Extraneous argument(s): %s...\n"), dev->devnum, argv[ac] ); return -1; } } } else dev->acc_ipmask = (in_addr_t)(-1); } } } return console_initialise(); } /* end function constty_init_handler */ /*-------------------------------------------------------------------*/ /* QUERY THE 1052/3215 DEVICE DEFINITION */ /*-------------------------------------------------------------------*/ static void constty_query_device (DEVBLK *dev, char **class, int buflen, char *buffer) { BEGIN_DEVICE_CLASS_QUERY( "CON", dev, class, buflen, buffer ); if (dev->connected) { snprintf (buffer, buflen, "%s%s", inet_ntoa(dev->ipaddr), dev->prompt1052 ? "" : " noprompt"); } else { char acc[48]; if (dev->acc_ipaddr || dev->acc_ipmask) { char ip [16]; char mask [16]; struct in_addr xxxx; xxxx.s_addr = dev->acc_ipaddr; snprintf( ip, sizeof( ip ), "%s", inet_ntoa( xxxx )); xxxx.s_addr = dev->acc_ipmask; snprintf( mask, sizeof( mask ), "%s", inet_ntoa( xxxx )); snprintf( acc, sizeof( acc ), "%s mask %s", ip, mask ); } else acc[0] = 0; if (dev->filename[0]) { snprintf(buffer, buflen, "GROUP=%s%s%s%s", dev->filename, !dev->prompt1052 ? " noprompt" : "", acc[0] ? " " : "", acc); } else { if (acc[0]) { if (!dev->prompt1052) snprintf(buffer, buflen, "noprompt %s", acc); else snprintf(buffer, buflen, "* %s", acc); } else { if (!dev->prompt1052) strlcpy(buffer,"noprompt",buflen); else buffer[0] = 0; } } } } /* end function constty_query_device */ /*-------------------------------------------------------------------*/ /* CLOSE THE 1052/3215 DEVICE HANDLER */ /*-------------------------------------------------------------------*/ static int constty_close_device ( DEVBLK *dev ) { console_remove(dev); return 0; } /* end function constty_close_device */ /*-------------------------------------------------------------------*/ /* SUBROUTINE TO ADVANCE TO NEXT CHAR OR ORDER IN A 3270 DATA STREAM */ /* Input: */ /* buf Buffer containing 3270 data stream */ /* off Offset in buffer of current character or order */ /* pos Position on screen of current character or order */ /* Output: */ /* off Offset in buffer of next character or order */ /* pos Position on screen of next character or order */ /*-------------------------------------------------------------------*/ static void next_3270_pos (BYTE *buf, int *off, int *pos) { int i; /* Copy the offset and advance the offset by 1 byte */ i = (*off)++; /* Advance the offset past the argument bytes and set position */ switch (buf[i]) { /* The Repeat to Address order has 3 argument bytes (or in case of a Graphics Escape 4 bytes) and sets the screen position */ case O3270_RA: *off += (buf[i+3] == O3270_GE) ? 4 : 3; if ((buf[i+1] & 0xC0) == 0x00) *pos = (buf[i+1] << 8) | buf[i+2]; else *pos = ((buf[i+1] & 0x3F) << 6) | (buf[i+2] & 0x3F); break; /* The Start Field Extended and Modify Field orders have a count byte followed by a variable number of type- attribute pairs, and advance the screen position by 1 */ case O3270_SFE: case O3270_MF: *off += (1 + 2*buf[i+1]); (*pos)++; break; /* The Set Buffer Address and Erase Unprotected to Address orders have 2 argument bytes and set the screen position */ case O3270_SBA: case O3270_EUA: *off += 2; if ((buf[i+1] & 0xC0) == 0x00) *pos = (buf[i+1] << 8) | buf[i+2]; else *pos = ((buf[i+1] & 0x3F) << 6) | (buf[i+2] & 0x3F); break; /* The Set Attribute order has 2 argument bytes and does not change the screen position */ case O3270_SA: *off += 2; break; /* Insert Cursor and Program Tab have no argument bytes and do not change the screen position */ case O3270_IC: case O3270_PT: break; /* The Start Field and Graphics Escape orders have one argument byte, and advance the screen position by 1 */ case O3270_SF: case O3270_GE: (*off)++; (*pos)++; break; /* All other characters advance the screen position by 1 */ default: (*pos)++; break; } /* end switch */ } /* end function next_3270_pos */ /*-------------------------------------------------------------------*/ /* SUBROUTINE TO FIND A GIVEN SCREEN POSITION IN A 3270 READ BUFFER */ /* Input: */ /* buf Buffer containing an inbound 3270 data stream */ /* size Number of bytes in buffer */ /* pos Screen position whose offset in buffer is desired */ /* Return value: */ /* Offset in buffer of the character or order corresponding to */ /* the given screen position, or zero if position not found. */ /*-------------------------------------------------------------------*/ static int find_buffer_pos (BYTE *buf, int size, int pos) { int wpos; /* Current screen position */ int woff; /* Current offset in buffer */ /* Screen position 0 is at offset 3 in the device buffer, following the AID and cursor address bytes */ wpos = 0; woff = 3; while (woff < size) { /* Exit if desired screen position has been reached */ if (wpos >= pos) { // logmsg (_("console: Pos %4.4X reached at %4.4X\n"), // wpos, woff); #ifdef FIX_QWS_BUG_FOR_MCS_CONSOLES /* There is a bug in QWS3270 when used to emulate an MCS console with EAB. At position 1680 the Read Buffer contains two 6-byte SFE orders (12 bytes) preceding the entry area, whereas MCS expects the entry area to start 4 bytes after screen position 1680 in the buffer. The bypass is to add 8 to the calculated buffer offset if this appears to be an MCS console read buffer command */ if (pos == 0x0690 && buf[woff] == O3270_SFE && buf[woff+6] == O3270_SFE) { woff += 8; // logmsg (_("console: Pos %4.4X adjusted to %4.4X\n"), // wpos, woff); } #endif /*FIX_QWS_BUG_FOR_MCS_CONSOLES*/ return woff; } /* Process next character or order, update screen position */ next_3270_pos (buf, &woff, &wpos); } /* end while */ /* Return offset zero if the position cannot be determined */ return 0; } /* end function find_buffer_pos */ /*-------------------------------------------------------------------*/ /* SUBROUTINE TO UPDATE THE CURRENT SCREEN POSITION */ /* Input: */ /* pos Current screen position */ /* buf Pointer to the byte in the 3270 data stream */ /* corresponding to the current screen position */ /* size Number of bytes remaining in buffer */ /* Output: */ /* pos Updated screen position after end of buffer */ /*-------------------------------------------------------------------*/ static void get_screen_pos (int *pos, BYTE *buf, int size) { int woff = 0; /* Current offset in buffer */ while (woff < size) { /* Process next character or order, update screen position */ next_3270_pos (buf, &woff, pos); } /* end while */ } /* end function get_screen_pos */ /*-------------------------------------------------------------------*/ /* EXECUTE A 3270 CHANNEL COMMAND WORD */ /*-------------------------------------------------------------------*/ static void loc3270_execute_ccw ( DEVBLK *dev, BYTE code, BYTE flags, BYTE chained, U16 count, BYTE prevcode, int ccwseq, BYTE *iobuf, BYTE *more, BYTE *unitstat, U16 *residual ) { int rc; /* Return code */ int num; /* Number of bytes to copy */ int len; /* Data length */ int aid; /* First read: AID present */ U32 off; /* Offset in device buffer */ BYTE cmd; /* tn3270 command code */ BYTE buf[BUFLEN_3270]; /* tn3270 write buffer */ UNREFERENCED(prevcode); UNREFERENCED(ccwseq); /* Clear the current screen position at start of CCW chain */ if (!chained) dev->pos3270 = 0; /* Unit check with intervention required if no client connected */ if (!dev->connected && !IS_CCW_SENSE(code)) { dev->sense[0] = SENSE_IR; /* *unitstat = CSW_CE | CSW_DE | CSW_UC; */ *unitstat = CSW_UC; /* *ISW3274DR* (as per GA23-0218-11 3.1.3.2.2 Table 5-5) */ return; } /* Process depending on CCW opcode */ switch (code) { case L3270_NOP: /*---------------------------------------------------------------*/ /* CONTROL NO-OPERATION */ /*---------------------------------------------------------------*/ /* Reset the buffer address */ dev->pos3270 = 0; *unitstat = CSW_CE | CSW_DE; break; case L3270_SELRM: case L3270_SELRB: case L3270_SELRMP: case L3270_SELRBP: case L3270_SELWRT: /*---------------------------------------------------------------*/ /* SELECT */ /*---------------------------------------------------------------*/ /* Reset the buffer address */ dev->pos3270 = 0; /* *residual = 0; */ *unitstat = CSW_CE | CSW_DE; break; case L3270_EAU: /*---------------------------------------------------------------*/ /* ERASE ALL UNPROTECTED */ /*---------------------------------------------------------------*/ dev->pos3270 = 0; cmd = R3270_EAU; goto write; case L3270_WRT: /*---------------------------------------------------------------*/ /* WRITE */ /*---------------------------------------------------------------*/ cmd = R3270_WRT; goto write; case L3270_EW: /*---------------------------------------------------------------*/ /* ERASE/WRITE */ /*---------------------------------------------------------------*/ dev->pos3270 = 0; cmd = R3270_EW; dev->ewa3270 = 0; goto write; case L3270_EWA: /*---------------------------------------------------------------*/ /* ERASE/WRITE ALTERNATE */ /*---------------------------------------------------------------*/ dev->pos3270 = 0; cmd = R3270_EWA; dev->ewa3270 = 1; goto write; case L3270_WSF: /*---------------------------------------------------------------*/ /* WRITE STRUCTURED FIELD */ /*---------------------------------------------------------------*/ /* Process WSF command if device has extended attributes */ if (dev->eab3270) { dev->pos3270 = 0; cmd = R3270_WSF; goto write; } /* Operation check, device does not have extended attributes */ dev->sense[0] = SENSE_OC; *unitstat = CSW_CE | CSW_DE | CSW_UC; break; write: /*---------------------------------------------------------------*/ /* All write commands, and the EAU control command, come here */ /*---------------------------------------------------------------*/ /* Initialize the data length */ len = 0; /* Calculate number of bytes to move and residual byte count */ num = sizeof(buf) / 2; num = (count < num) ? count : num; if(cmd == R3270_EAU) num = 0; *residual = count - num; /* Move the 3270 command code to the first byte of the buffer unless data-chained from previous CCW */ if ((chained & CCW_FLAGS_CD) == 0) { buf[len++] = cmd; /* If this is a chained write then we start at the current buffer address rather then the cursor address. If the first action the datastream takes is not a positioning action then insert a SBA to position to the current buffer address */ if(chained && cmd == R3270_WRT && dev->pos3270 != 0 && iobuf[1] != O3270_SBA && iobuf[1] != O3270_RA && iobuf[1] != O3270_EUA) { /* Copy the write control character and adjust buffer */ buf[len++] = *iobuf++; num--; /* Insert the SBA order */ buf[len++] = O3270_SBA; if(dev->pos3270 < 4096) { buf[len++] = sba_code[dev->pos3270 >> 6]; buf[len++] = sba_code[dev->pos3270 & 0x3F]; } else { buf[len++] = dev->pos3270 >> 8; buf[len++] = dev->pos3270 & 0xFF; } } /* if(iobuf[0] != SBA, RA or EUA) */ /* Save the screen position at completion of the write. This is necessary in case a Read Buffer command is chained from another write or read, this does not apply for the write structured field command */ if(cmd != R3270_WSF) get_screen_pos (&dev->pos3270, iobuf+1, num-1); } /* if(!data_chained) */ else /* if(data_chained) */ if(cmd != R3270_WSF) get_screen_pos (&dev->pos3270, iobuf, num); /* Copy data from channel buffer to device buffer */ memcpy (buf + len, iobuf, num); len += num; /* Double up any IAC bytes in the data */ len = double_up_iac (buf, len); /* Append telnet EOR marker at end of data */ if ((flags & CCW_FLAGS_CD) == 0) { buf[len++] = IAC; buf[len++] = EOR_MARK; } /* Send the data to the client */ rc = send_packet(dev->fd, buf, len, "3270 data"); if (rc < 0) { dev->sense[0] = SENSE_DC; *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Return normal status */ *unitstat = CSW_CE | CSW_DE; break; case L3270_RB: /*---------------------------------------------------------------*/ /* READ BUFFER */ /*---------------------------------------------------------------*/ /* Obtain the device lock */ obtain_lock (&dev->lock); /* AID is only present during the first read */ aid = dev->readpending != 2; /* Receive buffer data from client if not data chained */ if ((chained & CCW_FLAGS_CD) == 0) { /* Send read buffer command to client and await response */ rc = solicit_3270_data (dev, R3270_RB); if (rc & CSW_UC) { *unitstat = CSW_CE | CSW_DE | CSW_UC; release_lock (&dev->lock); break; } /* Set AID in buffer flag */ aid = 1; /* Save the AID of the current inbound transmission */ dev->aid3270 = dev->buf[0]; if(dev->pos3270 != 0 && dev->aid3270 != SF3270_AID) { /* Find offset in buffer of current screen position */ off = find_buffer_pos (dev->buf, dev->rlen3270, dev->pos3270); /* Shift out unwanted characters from buffer */ num = (dev->rlen3270 > off ? dev->rlen3270 - off : 0); memmove (dev->buf + 3, dev->buf + off, num); dev->rlen3270 = 3 + num; } } /* end if(!CCW_FLAGS_CD) */ /* Calculate number of bytes to move and residual byte count */ len = dev->rlen3270; num = (count < len) ? count : len; *residual = count - num; if (count < len) *more = 1; /* Save the screen position at completion of the read. This is necessary in case a Read Buffer command is chained from another write or read. */ if(dev->aid3270 != SF3270_AID) { if(aid) get_screen_pos(&dev->pos3270, dev->buf+3, num-3); else get_screen_pos(&dev->pos3270, dev->buf, num); } /* Indicate that the AID bytes have been skipped */ if(dev->readpending == 1) dev->readpending = 2; /* Copy data from device buffer to channel buffer */ memcpy (iobuf, dev->buf, num); /* If data chaining is specified, save remaining data */ if ((flags & CCW_FLAGS_CD) && len > count) { memmove (dev->buf, dev->buf + count, len - count); dev->rlen3270 = len - count; } else { dev->rlen3270 = 0; dev->readpending = 0; } /* Return normal status */ *unitstat = CSW_CE | CSW_DE; /* Release the device lock */ release_lock (&dev->lock); /* Signal connection thread to redrive its select loop */ SIGNAL_CONSOLE_THREAD(); break; case L3270_RM: /*---------------------------------------------------------------*/ /* READ MODIFIED */ /*---------------------------------------------------------------*/ /* Obtain the device lock */ obtain_lock (&dev->lock); /* AID is only present during the first read */ aid = dev->readpending != 2; /* If not data chained from previous Read Modified CCW, and if the connection thread has not already accumulated a complete Read Modified record in the inbound buffer, then solicit a Read Modified operation at the client */ if ((chained & CCW_FLAGS_CD) == 0 && !dev->readpending) { /* Send read modified command to client, await response */ rc = solicit_3270_data (dev, R3270_RM); if (rc & CSW_UC) { *unitstat = CSW_CE | CSW_DE | CSW_UC; release_lock (&dev->lock); break; } /* Set AID in buffer flag */ aid = 1; dev->aid3270 = dev->buf[0]; if(dev->pos3270 != 0 && dev->aid3270 != SF3270_AID) { /* Find offset in buffer of current screen position */ off = find_buffer_pos (dev->buf, dev->rlen3270, dev->pos3270); /* Shift out unwanted characters from buffer */ num = (dev->rlen3270 > off ? dev->rlen3270 - off : 0); memmove (dev->buf + 3, dev->buf + off, num); dev->rlen3270 = 3 + num; } } /* end if(!CCW_FLAGS_CD) */ /* Calculate number of bytes to move and residual byte count */ len = dev->rlen3270; num = (count < len) ? count : len; *residual = count - num; if (count < len) *more = 1; /* Save the screen position at completion of the read. This is necessary in case a Read Buffer command is chained from another write or read. */ if(dev->aid3270 != SF3270_AID) { if(aid) get_screen_pos(&dev->pos3270, dev->buf+3, num-3); else get_screen_pos(&dev->pos3270, dev->buf, num); } /* Indicate that the AID bytes have been skipped */ if(dev->readpending == 1) dev->readpending = 2; /* Copy data from device buffer to channel buffer */ memcpy (iobuf, dev->buf, num); /* If data chaining is specified, save remaining data */ if ((flags & CCW_FLAGS_CD) && len > count) { memmove (dev->buf, dev->buf + count, len - count); dev->rlen3270 = len - count; } else { dev->rlen3270 = 0; dev->readpending = 0; } /* Set normal status */ *unitstat = CSW_CE | CSW_DE; /* Release the device lock */ release_lock (&dev->lock); /* Signal connection thread to redrive its select loop */ SIGNAL_CONSOLE_THREAD(); break; case L3270_SENSE: /*---------------------------------------------------------------*/ /* SENSE */ /*---------------------------------------------------------------*/ /* Calculate residual byte count */ num = (count < dev->numsense) ? count : dev->numsense; *residual = count - num; if (count < dev->numsense) *more = 1; /* Copy device sense bytes to channel I/O buffer */ memcpy (iobuf, dev->sense, num); /* Clear the device sense bytes */ memset (dev->sense, 0, sizeof(dev->sense)); /* Reset the buffer address */ dev->pos3270 = 0; /* Return unit status */ *unitstat = CSW_CE | CSW_DE; break; case L3270_SENSEID: /*---------------------------------------------------------------*/ /* SENSE ID */ /*---------------------------------------------------------------*/ /* Calculate residual byte count */ num = (count < dev->numdevid) ? count : dev->numdevid; *residual = count - num; if (count < dev->numdevid) *more = 1; /* Copy device identifier bytes to channel I/O buffer */ memcpy (iobuf, dev->devid, num); /* Reset the buffer address */ dev->pos3270 = 0; /* Return unit status */ *unitstat = CSW_CE | CSW_DE; break; default: /*---------------------------------------------------------------*/ /* INVALID OPERATION */ /*---------------------------------------------------------------*/ /* Set command reject sense byte, and unit check status */ dev->sense[0] = SENSE_CR; *unitstat = CSW_CE | CSW_DE | CSW_UC; } /* end switch(code) */ } /* end function loc3270_execute_ccw */ /*-------------------------------------------------------------------*/ /* EXECUTE A 1052/3215 CHANNEL COMMAND WORD */ /*-------------------------------------------------------------------*/ static void constty_execute_ccw ( DEVBLK *dev, BYTE code, BYTE flags, BYTE chained, U16 count, BYTE prevcode, int ccwseq, BYTE *iobuf, BYTE *more, BYTE *unitstat, U16 *residual ) { int rc; /* Return code */ int len; /* Length of data */ int num; /* Number of bytes to move */ BYTE c; /* Print character */ BYTE stat; /* Unit status */ UNREFERENCED(chained); UNREFERENCED(prevcode); UNREFERENCED(ccwseq); /* Unit check with intervention required if no client connected */ if (dev->connected == 0 && !IS_CCW_SENSE(code)) { dev->sense[0] = SENSE_IR; *unitstat = CSW_UC; return; } /* Process depending on CCW opcode */ switch (code) { case 0x01: /*---------------------------------------------------------------*/ /* WRITE NO CARRIER RETURN */ /*---------------------------------------------------------------*/ case 0x09: /*---------------------------------------------------------------*/ /* WRITE AUTO CARRIER RETURN */ /*---------------------------------------------------------------*/ /* Calculate number of bytes to write and set residual count */ num = (count < BUFLEN_1052) ? count : BUFLEN_1052; *residual = count - num; /* Translate data in channel buffer to ASCII */ for (len = 0; len < num; len++) { c = guest_to_host(iobuf[len]); if (!isprint(c) && c != 0x0a && c != 0x0d) c = SPACE; iobuf[len] = c; } /* end for(len) */ ASSERT(len == num); /* Perform end of record processing if not data-chaining */ if ((flags & CCW_FLAGS_CD) == 0) { /* Append carriage return and newline if required */ if (code == 0x09) { if (len < BUFLEN_1052) iobuf[len++] = '\r'; if (len < BUFLEN_1052) iobuf[len++] = '\n'; } } /* end if(!data-chaining) */ /* Send the data to the client */ rc = send_packet (dev->fd, iobuf, len, NULL); if (rc < 0) { dev->sense[0] = SENSE_EC; *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Return normal status */ *unitstat = CSW_CE | CSW_DE; break; case 0x03: /*---------------------------------------------------------------*/ /* CONTROL NO-OPERATION */ /*---------------------------------------------------------------*/ *unitstat = CSW_CE | CSW_DE; break; case 0x0A: /*---------------------------------------------------------------*/ /* READ INQUIRY */ /*---------------------------------------------------------------*/ /* Solicit console input if no data in the device buffer */ if (!dev->keybdrem) { /* Display prompting message on console if allowed */ if (dev->prompt1052) { snprintf ((char *)dev->buf, dev->bufsize, _("HHCTE006A Enter input for console device %4.4X\n"), dev->devnum); len = strlen((char *)dev->buf); rc = send_packet (dev->fd, dev->buf, len, NULL); if (rc < 0) { dev->sense[0] = SENSE_EC; *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } } /* Accumulate client input data into device buffer */ while (1) { /* Receive client data and increment dev->keybdrem */ stat = recv_1052_data (dev); /* Exit if error or end of line */ if (stat != 0) break; } /* end while */ /* Exit if error status */ if (stat != CSW_ATTN) { *unitstat = (CSW_CE | CSW_DE) | (stat & ~CSW_ATTN); break; } } /* Calculate number of bytes to move and residual byte count */ len = dev->keybdrem; num = (count < len) ? count : len; *residual = count - num; if (count < len) *more = 1; /* Copy data from device buffer to channel buffer */ memcpy (iobuf, dev->buf, num); /* If data chaining is specified, save remaining data */ if ((flags & CCW_FLAGS_CD) && len > count) { memmove (dev->buf, dev->buf + count, len - count); dev->keybdrem = len - count; } else { dev->keybdrem = 0; } /* Return normal status */ *unitstat = CSW_CE | CSW_DE; break; case 0x0B: /*---------------------------------------------------------------*/ /* AUDIBLE ALARM */ /*---------------------------------------------------------------*/ rc = send_packet (dev->fd, (BYTE *)"\a", 1, NULL); /* *residual = 0; */ *unitstat = CSW_CE | CSW_DE; break; case 0x04: /*---------------------------------------------------------------*/ /* SENSE */ /*---------------------------------------------------------------*/ /* Calculate residual byte count */ num = (count < dev->numsense) ? count : dev->numsense; *residual = count - num; if (count < dev->numsense) *more = 1; /* Copy device sense bytes to channel I/O buffer */ memcpy (iobuf, dev->sense, num); /* Clear the device sense bytes */ memset (dev->sense, 0, sizeof(dev->sense)); /* Return unit status */ *unitstat = CSW_CE | CSW_DE; break; case 0xE4: /*---------------------------------------------------------------*/ /* SENSE ID */ /*---------------------------------------------------------------*/ /* Calculate residual byte count */ num = (count < dev->numdevid) ? count : dev->numdevid; *residual = count - num; if (count < dev->numdevid) *more = 1; /* Copy device identifier bytes to channel I/O buffer */ memcpy (iobuf, dev->devid, num); /* Return unit status */ *unitstat = CSW_CE | CSW_DE; break; default: /*---------------------------------------------------------------*/ /* INVALID OPERATION */ /*---------------------------------------------------------------*/ /* Set command reject sense byte, and unit check status */ dev->sense[0] = SENSE_CR; *unitstat = CSW_CE | CSW_DE | CSW_UC; } /* end switch(code) */ } /* end function constty_execute_ccw */ #if defined(OPTION_DYNAMIC_LOAD) static #endif DEVHND constty_device_hndinfo = { &constty_init_handler, /* Device Initialisation */ &constty_execute_ccw, /* Device CCW execute */ &constty_close_device, /* Device Close */ &constty_query_device, /* Device Query */ NULL, /* Device Start channel pgm */ NULL, /* Device End channel pgm */ NULL, /* Device Resume channel pgm */ NULL, /* Device Suspend channel pgm */ NULL, /* Device Read */ NULL, /* Device Write */ NULL, /* Device Query used */ NULL, /* Device Reserve */ NULL, /* Device Release */ NULL, /* Device Attention */ constty_immed, /* Immediate CCW Codes */ NULL, /* Signal Adapter Input */ NULL, /* Signal Adapter Output */ NULL, /* Hercules suspend */ NULL /* Hercules resume */ }; /* Libtool static name colision resolution */ /* note : lt_dlopen will look for symbol & modulename_LTX_symbol */ #if !defined(HDL_BUILD_SHARED) && defined(HDL_USE_LIBTOOL) #define hdl_ddev hdt3270_LTX_hdl_ddev #define hdl_depc hdt3270_LTX_hdl_depc #define hdl_reso hdt3270_LTX_hdl_reso #define hdl_init hdt3270_LTX_hdl_init #define hdl_fini hdt3270_LTX_hdl_fini #endif #if defined(OPTION_DYNAMIC_LOAD) static #endif DEVHND loc3270_device_hndinfo = { &loc3270_init_handler, /* Device Initialisation */ &loc3270_execute_ccw, /* Device CCW execute */ &loc3270_close_device, /* Device Close */ &loc3270_query_device, /* Device Query */ NULL, /* Device Start channel pgm */ NULL, /* Device End channel pgm */ NULL, /* Device Resume channel pgm */ NULL, /* Device Suspend channel pgm */ NULL, /* Device Read */ NULL, /* Device Write */ NULL, /* Device Query used */ NULL, /* Device Reserve */ NULL, /* Device Release */ NULL, /* Device Attention */ loc3270_immed, /* Immediate CCW Codes */ NULL, /* Signal Adapter Input */ NULL, /* Signal Adapter Output */ &loc3270_hsuspend, /* Hercules suspend */ &loc3270_hresume /* Hercules resume */ }; #if defined(OPTION_DYNAMIC_LOAD) HDL_DEPENDENCY_SECTION; { HDL_DEPENDENCY(HERCULES); HDL_DEPENDENCY(DEVBLK); HDL_DEPENDENCY(SYSBLK); } END_DEPENDENCY_SECTION #if defined(WIN32) && !defined(HDL_USE_LIBTOOL) && !defined(_MSVC_) #undef sysblk #undef config_cnslport HDL_RESOLVER_SECTION; { HDL_RESOLVE_PTRVAR( psysblk, sysblk ); HDL_RESOLVE( config_cnslport ); } END_RESOLVER_SECTION #endif HDL_DEVICE_SECTION { HDL_DEVICE(1052, constty_device_hndinfo ); HDL_DEVICE(3215, constty_device_hndinfo ); HDL_DEVICE(3270, loc3270_device_hndinfo ); HDL_DEVICE(3287, loc3270_device_hndinfo ); #if defined(_FEATURE_INTEGRATED_3270_CONSOLE) HDL_DEVICE(SYSG, loc3270_device_hndinfo ); #endif /*defined(_FEATURE_INTEGRATED_3270_CONSOLE)*/ } END_DEVICE_SECTION #endif hercules-3.07/conspawn.c000644 000765 000765 00000017466 11143760543 016761 0ustar00jmaynardjmaynard000000 000000 /*-------------------------------------------------------------------*/ /* CONSPAWN.C (c) "Fish" (David B. Trout), 2005-2006 */ /* This program is spawned by Hercules as a result of */ /* the 'sh' (shell) command. It's purpose is to simply */ /* call the host's shell (command interpreter) program */ /* with the arguments supplied (usually to invoke yet */ /* another program), redirecting the results back to */ /* Hercules for display. NOTE that this program does */ /* not perform the actual stdio redirection itself, but */ /* rather relies on Hercules to have set that up before */ /* invoking this program. */ /*-------------------------------------------------------------------*/ // $Id: conspawn.c 5147 2009-02-01 21:27:16Z rbowler $ // // $Log$ // Revision 1.3 2006/12/08 09:43:18 jj // Add CVS message log // #include "hstdinc.h" #define PGMNAME "conspawn" int main(int argc, char* argv[]) { int i, k, rc; char* p; #ifdef _MSVC_ #pragma comment(lib,"shell32.lib") // (need ShellExecute) // -------------------------------------------------------- // PROGRAMMING NOTE: We MUST use "ShellExecute" for Windows // GUI programs since: 1) GUI programs don't use stdio, // 2) they never exit until the user manually closes them. // // Erroneously using the 'system()' function to start a GUI // program causes HercGUI to hang at PowerOff as it waits // for its child process to close its stdio handles which // GUI programs never do until they exit (which they never // do until the user manually closes them). // // The reason this phenomenon occurs even though Hercules // does indeed close ITS OWN stdio handles when it ends is // because its child processes that it creates ALSO inherit // the same stdio handles! (I.e. the GUI programs that Herc // starts end up never closing "Herc's" [inherited] stdio // handles, which are the same handles that HercGUI waits // on! Thus GUI programs started by Herc using the 'system' // API end up hanging HercGUI! (during Herc PowerOff)) // // Thus, for GUI apps, we MUST use "ShellExecute" here // to prevent HercGUI from hanging at PowerOff. Also note // that this hang obviously does not occur when Hercules // is run in command-line (non-HercGUI) mode even when // the 'system()' API is erroneously used, since Herc is // obviously (duh!) not being run under the control of an // external GUI in such a situation. -- Fish, Aug. 2006 // -------------------------------------------------------- if (argc >= 2 && strcasecmp(argv[1],"startgui") == 0) { //////////////////////////////////////////////////////// // Windows GUI program; no stdio; use 'ShellExecute'... //////////////////////////////////////////////////////// // REFERENCE: upon entry: // argv[0] "conspawn" // argv[1] "startgui" // argv[2] (program to start) // argv[3..n] (arguments for program) HWND hwnd = NULL; LPCTSTR lpOperation = NULL; LPCTSTR lpFile = argv[2]; LPCTSTR lpParameters = NULL; LPCTSTR lpDirectory = NULL; INT nShowCmd = SW_SHOWNORMAL; char* pszErrMsg = NULL; // Build arguments string from passed args... for (i=3, k=0; i < argc; i++) k += strlen(argv[i]) + 1; if (k) { // (allocate room for arguments string) if (!(p = malloc(sizeof(char)*k))) { errno = ENOMEM; perror( PGMNAME ); return -1; } *p = 0; // (build arguments string from args) for (i=3; i < argc; ++i) { strcat(p,argv[i]); if (i != (argc-1)) strcat(p," "); } lpParameters = p; } else p = NULL; rc = (intptr_t) ShellExecute( hwnd, lpOperation, lpFile, lpParameters, lpDirectory, nShowCmd ); if (p) free(p); if ( rc > 32) return 0; // rc > greater than 32 == success... // rc <= less than or equal 32 == error... switch (rc) { case 0: pszErrMsg = "The operating system is out of memory or resources"; break; case SE_ERR_FNF: pszErrMsg = "The specified file was not found"; break; case SE_ERR_PNF: pszErrMsg = "The specified path was not found"; break; case SE_ERR_ACCESSDENIED: pszErrMsg = "The operating system denied access to the specified file"; break; case ERROR_BAD_FORMAT: pszErrMsg = "The .exe file is invalid (non-Microsoft Win32 .exe or error in .exe image)"; break; case SE_ERR_OOM: pszErrMsg = "There was not enough memory to complete the operation"; break; case SE_ERR_DLLNOTFOUND: pszErrMsg = "The specified dynamic-link library (DLL) was not found"; break; case SE_ERR_SHARE: pszErrMsg = "A sharing violation occurred"; break; case SE_ERR_ASSOCINCOMPLETE: pszErrMsg = "The file name association is incomplete or invalid"; break; case SE_ERR_DDETIMEOUT: pszErrMsg = "The DDE transaction could not be completed because the request timed out"; break; case SE_ERR_DDEFAIL: pszErrMsg = "The DDE transaction failed"; break; case SE_ERR_DDEBUSY: pszErrMsg = "The Dynamic Data Exchange (DDE) transaction could not be completed because other DDE transactions were being processed"; break; case SE_ERR_NOASSOC: pszErrMsg = "There is no application associated with the given file name extension. This error will also be returned if you attempt to print a file that is not printable"; break; default: printf(PGMNAME": ShellExecute(\"%s\", \"%s\",...) failed: Unknown error; rc=%d (0x%08.8X).\n", lpFile, lpParameters, rc, rc ); return -1; } printf( PGMNAME": ShellExecute(\"%s\", \"%s\",...) failed: %s.\n", lpFile, lpParameters, pszErrMsg ); return -1; } #endif // _MSVC_ //////////////////////////////////////////////////////// // Command line program using stdio; use 'system()'... //////////////////////////////////////////////////////// // Re-build a complete command line from passed args... for (i=1, k=0; i < argc; i++) k += strlen(argv[i]) + 1; if (!k) { errno = EINVAL; perror( PGMNAME ); printf( PGMNAME": Usage: command [args]\n"); return -1; } // (allocate room for command line) if (!(p = malloc(sizeof(char)*k))) { errno = ENOMEM; perror( PGMNAME ); return -1; } *p = 0; // (rebuild command-line from args) for (i=1; i < argc; ++i) { strcat(p,argv[i]); if (i != (argc-1)) strcat(p," "); } // Ask system() to process command line... // NOTE: the below call WILL NOT RETURN // until the program being called exits! rc = system(p); free(p); // -------------------------------------------------------- // PROGRAMMING NOTE: only rc == -1 need be reported since, // if the command interpreter called a batch/cmd file for // example, it could have set its own custom return code. // // Only -1 means the system() call itself failed, which // is the only thing that actually needs to be reported. // -------------------------------------------------------- if ( -1 == rc ) perror( PGMNAME ); return rc; } hercules-3.07/control.c000644 000765 000765 00001007012 11337307610 016571 0ustar00jmaynardjmaynard000000 000000 /* CONTROL.C (c) Copyright Roger Bowler, 1994-2010 */ /* ESA/390 CPU Emulator */ /* Interpretive Execution - (c) Copyright Jan Jaeger, 1999-2009 */ /* z/Architecture support - (c) Copyright Jan Jaeger, 1999-2009 */ // $Id: control.c 5636 2010-02-16 14:30:20Z ivan $ /*-------------------------------------------------------------------*/ /* This module implements all control instructions of the */ /* S/370 and ESA/390 architectures, as described in the manuals */ /* GA22-7000-03 System/370 Principles of Operation */ /* SA22-7201-06 ESA/390 Principles of Operation */ /*-------------------------------------------------------------------*/ /*-------------------------------------------------------------------*/ /* Additional credits: */ /* Bad frame support by Jan Jaeger */ /* Branch tracing by Jan Jaeger */ /* CSP instructions by Jan Jaeger */ /* Instruction decode by macros - Jan Jaeger */ /* Prevent TOD from going backwards in time - Jan Jaeger */ /* Instruction decode rework - Jan Jaeger */ /* PR may lose pending interrupts - Jan Jaeger */ /* Modifications for Interpretive Execution (SIE) by Jan Jaeger */ /* ESAME low-address protection - Roger Bowler */ /* ESAME linkage stack operations - Roger Bowler */ /* ESAME BSA instruction - Roger Bowler v209c*/ /* ASN-and-LX-reuse facility - Roger Bowler June 2004*/ /* SIGP orders 11,12.2,13,15 - Fish Oct 2005*/ /*-------------------------------------------------------------------*/ #include "hstdinc.h" #if !defined(_HENGINE_DLL_) #define _HENGINE_DLL_ #endif #if !defined(_CONTROL_C_) #define _CONTROL_C_ #endif #include "hercules.h" #include "opcode.h" #include "inline.h" #if defined(OPTION_FISHIO) #include "w32chan.h" #endif // defined(OPTION_FISHIO) /* Temporary debug */ extern int ipending_cmd(int,void *,void *); #if defined(FEATURE_BRANCH_AND_SET_AUTHORITY) /*-------------------------------------------------------------------*/ /* B25A BSA - Branch and Set Authority [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(branch_and_set_authority) { int r1, r2; /* Values of R fields */ U32 ducto; /* DUCT origin */ U32 duct_pkrp; /* DUCT PKM/Key/RA/P word */ RADR duct_reta; /* DUCT return address/amode */ BYTE key; /* New PSW key */ #ifdef FEATURE_TRACING CREG newcr12 = 0; /* CR12 upon completion */ #endif /*FEATURE_TRACING*/ RRE(inst, regs, r1, r2); /* Special operation exception if ASF is not enabled */ if (!ASF_ENABLED(regs)) ARCH_DEP(program_interrupt) (regs, PGM_SPECIAL_OPERATION_EXCEPTION); #if defined(_FEATURE_SIE) if(SIE_STATB(regs, IC1, BSA)) longjmp(regs->progjmp, SIE_INTERCEPT_INST); #endif /*defined(_FEATURE_SIE)*/ /* Load real address of dispatchable unit control table */ ducto = regs->CR(2) & CR2_DUCTO; /* Apply low-address protection to stores into the DUCT */ if (ARCH_DEP(is_low_address_protected) (ducto, regs)) { #ifdef FEATURE_SUPPRESSION_ON_PROTECTION regs->TEA = (ducto & STORAGE_KEY_PAGEMASK); regs->excarid = 0; #endif /*FEATURE_SUPPRESSION_ON_PROTECTION*/ ARCH_DEP(program_interrupt) (regs, PGM_PROTECTION_EXCEPTION); } /* Convert DUCT real address to absolute address */ ducto = APPLY_PREFIXING (ducto, regs->PX); /* Program check if DUCT origin address is invalid */ if (ducto > regs->mainlim) ARCH_DEP(program_interrupt) (regs, PGM_ADDRESSING_EXCEPTION); #if defined(FEATURE_ESAME) /* For ESAME, load the PKM/Key/RA/P from DUCT word 5, and load the return address and amode from DUCT words 8 and 9 (note: the DUCT cannot cross a page boundary) */ duct_pkrp = ARCH_DEP(fetch_fullword_absolute) (ducto+20, regs); duct_reta = ARCH_DEP(fetch_doubleword_absolute) (ducto+32, regs); #else /*!defined(FEATURE_ESAME)*/ /* For ESA/390, load the PKM/Key/RA/P from DUCT word 9, and load the return address and amode from DUCT word 8 (note: the DUCT cannot cross a page boundary) */ duct_pkrp = ARCH_DEP(fetch_fullword_absolute) (ducto+36, regs); duct_reta = ARCH_DEP(fetch_fullword_absolute) (ducto+32, regs); #endif /*!defined(FEATURE_ESAME)*/ /* Perform base authority or reduced authority operation */ if ((duct_pkrp & DUCT_RA) == 0) { /* In base authority state R2 cannot specify register zero */ if (r2 == 0) ARCH_DEP(program_interrupt) (regs, PGM_SPECIAL_OPERATION_EXCEPTION); #ifdef FEATURE_TRACING /* Perform tracing */ if (regs->CR(12) & CR12_BRTRACE) newcr12 = ARCH_DEP(trace_br) (regs->GR_L(r2) & 0x80000000, regs->GR_L(r2), regs); #endif /*FEATURE_TRACING*/ /* Obtain the new PSW key from R1 register bits 24-27 */ key = regs->GR_L(r1) & 0x000000F0; /* Privileged operation exception if in problem state and current PSW key mask does not permit new key value */ if (PROBSTATE(®s->psw) && ((regs->CR(3) << (key >> 4)) & 0x80000000) == 0 ) ARCH_DEP(program_interrupt) (regs, PGM_PRIVILEGED_OPERATION_EXCEPTION); /* Save current PSW amode and instruction address */ #if defined(FEATURE_ESAME) if (regs->psw.amode64) { duct_reta = PSW_IA(regs, 0); } else #endif /*!defined(FEATURE_ESAME)*/ { duct_reta = PSW_IA(regs, 0) & DUCT_IA31; if (regs->psw.amode) duct_reta |= DUCT_AM31; } /* Save current PSW key mask, PSW key, and problem state */ duct_pkrp = (regs->CR(3) & CR3_KEYMASK) | regs->psw.pkey; if (PROBSTATE(®s->psw)) duct_pkrp |= DUCT_PROB; /* Set the reduced authority bit */ duct_pkrp |= DUCT_RA; #if defined(FEATURE_ESAME) /* For ESAME, store the PKM/Key/RA/P into DUCT word 5, and store the return address and amode into DUCT words 8 and 9 (note: the DUCT cannot cross a page boundary) */ ARCH_DEP(store_fullword_absolute) (duct_pkrp, ducto+20, regs); ARCH_DEP(store_doubleword_absolute) (duct_reta, ducto+32, regs); #else /*!defined(FEATURE_ESAME)*/ /* For ESA/390, store the PKM/Key/RA/P into DUCT word 9, and store the return address and amode into DUCT word 8 (note: the DUCT cannot cross a page boundary) */ ARCH_DEP(store_fullword_absolute) (duct_pkrp, ducto+36, regs); ARCH_DEP(store_fullword_absolute) (duct_reta, ducto+32, regs); #endif /*!defined(FEATURE_ESAME)*/ /* Load new PSW key and PSW key mask from R1 register */ regs->psw.pkey = key; regs->CR_LHH(3) &= regs->GR_LHH(r1); /* Set the problem state bit in the current PSW */ regs->psw.states |= BIT(PSW_PROB_BIT); /* Set the breaking event address register */ SET_BEAR_REG(regs, regs->ip - 4); /* Set PSW instruction address and amode from R2 register */ #if defined(FEATURE_ESAME) if (regs->psw.amode64) { UPD_PSW_IA(regs, regs->GR_G(r2)); } else #endif /*defined(FEATURE_ESAME)*/ if (regs->GR_L(r2) & 0x80000000) { #if defined(FEATURE_ESAME) regs->psw.amode64 = 0; #endif /*defined(FEATURE_ESAME)*/ regs->psw.amode = 1; regs->psw.AMASK = AMASK31; UPD_PSW_IA(regs, regs->GR_L(r2)); } else { #if defined(FEATURE_ESAME) regs->psw.amode64 = #endif /*defined(FEATURE_ESAME)*/ regs->psw.amode = 0; regs->psw.AMASK = AMASK24; UPD_PSW_IA(regs, regs->GR_L(r2)); } } /* end if(BSA-ba) */ else { /* BSA-ra */ /* In reduced authority state R2 must specify register zero */ if (r2 != 0) ARCH_DEP(program_interrupt) (regs, PGM_SPECIAL_OPERATION_EXCEPTION); #ifdef FEATURE_TRACING /* Perform tracing */ if (regs->CR(12) & CR12_BRTRACE) newcr12 = ARCH_DEP(trace_br) (duct_reta & DUCT_AM31, duct_reta &DUCT_IA31, regs); #endif /*FEATURE_TRACING*/ /* Set the breaking event address register */ SET_BEAR_REG(regs, regs->ip - 4); /* If R1 is non-zero, save the current PSW addressing mode and instruction address in the R1 register */ if (r1 != 0) { #if defined(FEATURE_ESAME) if (regs->psw.amode64) { regs->GR_G(r1) = PSW_IA(regs, 0); } else #endif /*defined(FEATURE_ESAME)*/ { regs->GR_L(r1) = PSW_IA(regs, 0); if (regs->psw.amode) regs->GR_L(r1) |= 0x80000000; } } /* Restore PSW amode and instruction address from the DUCT */ #if defined(FEATURE_ESAME) if (regs->psw.amode64) { UPD_PSW_IA(regs, duct_reta); } else #endif /*defined(FEATURE_ESAME)*/ { regs->psw.amode = (duct_reta & DUCT_AM31) ? 1 : 0; regs->psw.AMASK = regs->psw.amode ? AMASK31 : AMASK24; UPD_PSW_IA(regs, duct_reta & DUCT_IA31); } /* Restore the PSW key mask from the DUCT */ regs->CR_L(3) &= 0x0000FFFF; regs->CR_L(3) |= duct_pkrp & DUCT_PKM; /* Restore the PSW key from the DUCT */ regs->psw.pkey = duct_pkrp & DUCT_KEY; /* Restore the problem state bit from the DUCT */ if (duct_pkrp & DUCT_PROB) regs->psw.states |= BIT(PSW_PROB_BIT); else regs->psw.states &= ~BIT(PSW_PROB_BIT); /* Reset the reduced authority bit in the DUCT */ duct_pkrp &= ~DUCT_RA; #if defined(FEATURE_ESAME) ARCH_DEP(store_fullword_absolute) (duct_pkrp, ducto+20, regs); #else /*!defined(FEATURE_ESAME)*/ ARCH_DEP(store_fullword_absolute) (duct_pkrp, ducto+36, regs); #endif /*!defined(FEATURE_ESAME)*/ /* Specification exception if the PSW is now invalid. */ /* (Since UPD_PSW_IA used above masks off inval bits */ /* in psw.IA, test duct_reta for invalid bits). */ if ((duct_reta & 1) #if defined(FEATURE_ESAME) || (regs->psw.amode64 == 0 && regs->psw.amode == 0 && (duct_reta & 0x7F000000))) #else /*!defined(FEATURE_ESAME)*/ || (regs->psw.amode == 0 && duct_reta > 0x00FFFFFF)) #endif /*!defined(FEATURE_ESAME)*/ { /* program_interrupt will invoke INVALIDATE_AIA which */ /* will apply address mask to psw.IA if aie valid. */ regs->aie = NULL; regs->psw.IA = duct_reta; regs->psw.zeroilc = 1; ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION); } } /* end if(BSA-ra) */ #ifdef FEATURE_TRACING /* Update trace table address if branch tracing is on */ if (regs->CR(12) & CR12_BRTRACE) regs->CR(12) = newcr12; #endif /*FEATURE_TRACING*/ /* Check for Successful Branch PER event */ PER_SB(regs, regs->psw.IA); } /* end DEF_INST(branch_and_set_authority) */ #endif /*defined(FEATURE_BRANCH_AND_SET_AUTHORITY)*/ #if defined(FEATURE_SUBSPACE_GROUP) /*-------------------------------------------------------------------*/ /* B258 BSG - Branch in Subspace Group [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(branch_in_subspace_group) { int r1, r2; /* Values of R fields */ U32 alet; /* Destination subspace ALET */ U32 dasteo=0; /* Destination ASTE origin */ U32 daste[16]; /* ASN second table entry */ RADR ducto; /* DUCT origin */ U32 duct0; /* DUCT word 0 */ U32 duct1; /* DUCT word 1 */ U32 duct3; /* DUCT word 3 */ RADR abs; /* Absolute address */ BYTE *mn; /* Mainstor address */ VADR newia; /* New instruction address */ U16 xcode; /* Exception code */ #ifdef FEATURE_TRACING CREG newcr12 = 0; /* CR12 upon completion */ #endif /*FEATURE_TRACING*/ CREG inst_cr; /* Instruction CR */ RRE(inst, regs, r1, r2); SIE_XC_INTERCEPT(regs); /* Special operation exception if DAT is off or ASF not enabled */ if (REAL_MODE(&(regs->psw)) || !ASF_ENABLED(regs)) ARCH_DEP(program_interrupt) (regs, PGM_SPECIAL_OPERATION_EXCEPTION); inst_cr = regs->CR(regs->aea_ar[USE_INST_SPACE]); #ifdef FEATURE_TRACING /* Perform tracing */ if (regs->CR(12) & CR12_ASNTRACE) newcr12 = ARCH_DEP(trace_bsg) ((r2 == 0) ? 0 : regs->AR(r2), regs->GR_L(r2), regs); else if (regs->CR(12) & CR12_BRTRACE) newcr12 = ARCH_DEP(trace_br) (regs->GR_L(r2) & 0x80000000, regs->GR_L(r2), regs); #endif /*FEATURE_TRACING*/ /* Load real address of dispatchable unit control table */ ducto = regs->CR(2) & CR2_DUCTO; /* Apply low-address protection to stores into the DUCT */ if (ARCH_DEP(is_low_address_protected) (ducto, regs)) { #ifdef FEATURE_SUPPRESSION_ON_PROTECTION regs->TEA = (ducto & STORAGE_KEY_PAGEMASK); regs->excarid = 0; #endif /*FEATURE_SUPPRESSION_ON_PROTECTION*/ ARCH_DEP(program_interrupt) (regs, PGM_PROTECTION_EXCEPTION); } /* Convert DUCT real address to absolute address */ ducto = APPLY_PREFIXING (ducto, regs->PX); /* Program check if DUCT origin address is invalid */ if (ducto > regs->mainlim) ARCH_DEP(program_interrupt) (regs, PGM_ADDRESSING_EXCEPTION); /* Fetch DUCT words 0, 1, and 3 from absolute storage (note: the DUCT cannot cross a page boundary) */ mn = FETCH_MAIN_ABSOLUTE (ducto, regs, 16); duct0 = fetch_fw (mn); duct1 = fetch_fw (mn+4); duct3 = fetch_fw (mn+12); /* Special operation exception if the current primary ASTE origin is not the same as the base ASTE for the dispatchable unit */ if ((regs->CR_L(5) & CR5_PASTEO) != (duct0 & DUCT0_BASTEO)) ARCH_DEP(program_interrupt) (regs, PGM_SPECIAL_OPERATION_EXCEPTION); /* Obtain the destination ALET from the R2 access register, except that register zero means destination ALET is zero */ alet = (r2 == 0) ? 0 : regs->AR(r2); /* Perform special ALET translation to obtain destination ASTE */ switch (alet) { case ALET_PRIMARY: /* Branch to base space */ /* Load the base space ASTE origin from the DUCT */ dasteo = duct0 & DUCT0_BASTEO; /* Convert the ASTE origin to an absolute address */ abs = APPLY_PREFIXING (dasteo, regs->PX); /* Program check if ASTE origin address is invalid */ if (abs > regs->mainlim) ARCH_DEP(program_interrupt) (regs, PGM_ADDRESSING_EXCEPTION); /* Fetch destination ASTE words 2 and 3 from absolute storage (note: the ASTE cannot cross a page boundary) */ mn = FETCH_MAIN_ABSOLUTE (abs, regs, 16); daste[2] = fetch_fw (mn+8); daste[3] = fetch_fw (mn+12); break; case ALET_SECONDARY: /* Branch to last-used subspace */ /* Load the subspace ASTE origin from the DUCT */ dasteo = duct1 & DUCT1_SSASTEO; /* Special operation exception if SSASTEO is zero */ if (dasteo == 0) ARCH_DEP(program_interrupt) (regs, PGM_SPECIAL_OPERATION_EXCEPTION); /* Convert the ASTE origin to an absolute address */ abs = APPLY_PREFIXING (dasteo, regs->PX); /* Program check if ASTE origin address is invalid */ if (abs > regs->mainlim) ARCH_DEP(program_interrupt) (regs, PGM_ADDRESSING_EXCEPTION); /* Fetch subspace ASTE words 0, 2, 3, and 5 from absolute storage (note: the ASTE cannot cross a page boundary) */ mn = FETCH_MAIN_ABSOLUTE (abs, regs, 24); daste[0] = fetch_fw (mn); daste[2] = fetch_fw (mn+8); daste[3] = fetch_fw (mn+12); daste[5] = fetch_fw (mn+20); /* ASTE validity exception if ASTE invalid bit is one */ if (daste[0] & ASTE0_INVALID) { regs->excarid = r2; ARCH_DEP(program_interrupt) (regs, PGM_ASTE_VALIDITY_EXCEPTION); } /* ASTE sequence exception if the subspace ASTE sequence number does not match the sequence number in the DUCT */ if ((daste[5] & ASTE5_ASTESN) != (duct3 & DUCT3_SSASTESN)) { regs->excarid = r2; ARCH_DEP(program_interrupt) (regs, PGM_ASTE_SEQUENCE_EXCEPTION); } break; default: /* ALET not 0 or 1 */ /* Perform special ART to obtain destination ASTE */ xcode = ARCH_DEP(translate_alet) (alet, 0, ACCTYPE_BSG, regs, &dasteo, daste); /* Program check if ALET translation error */ if (xcode != 0) { regs->excarid = r2; ARCH_DEP(program_interrupt) (regs, xcode); } /* Special operation exception if the destination ASTE is the base space of a different subspace group */ if (dasteo != (duct0 & DUCT0_BASTEO) && ((ASTE_AS_DESIGNATOR(daste) & SSGROUP_BIT) == 0 || (daste[0] & ASTE0_BASE) )) ARCH_DEP(program_interrupt) (regs, PGM_SPECIAL_OPERATION_EXCEPTION); } /* end switch(alet) */ /* Update the primary STD (or ASCE) from the destination ASTE */ if ((dasteo == (duct0 & DUCT0_BASTEO)) && (alet != ALET_SECONDARY)) { /* When the destination ASTE is the base space, replace the primary STD (or ASCE) by the STD (or ASCE) in the ASTE */ regs->CR(1) = ASTE_AS_DESIGNATOR(daste); } else { /* When the destination ASTE is a subspace, replace the primary STD or ASCE by the STD or ASTE in the ASTE, except for the space-switch event and storage alteration event bits, which remain unchanged */ regs->CR(1) &= (SSEVENT_BIT | SAEVENT_BIT); regs->CR(1) |= (ASTE_AS_DESIGNATOR(daste) & ~((RADR)(SSEVENT_BIT | SAEVENT_BIT))); } /* Compute the branch address from the R2 operand */ newia = regs->GR(r2); /* If R1 is non-zero, save the current PSW addressing mode and instruction address in the R1 register */ if (r1 != 0) { #if defined(FEATURE_ESAME) if (regs->psw.amode64) regs->GR_G(r1) = PSW_IA(regs, 0); else #endif /*!defined(FEATURE_ESAME)*/ regs->GR_L(r1) = PSW_IA(regs, 0) | (regs->psw.amode ? 0x80000000 : 0); } /* Update the breaking event address register */ SET_BEAR_REG(regs, regs->ip - 4); #if defined(FEATURE_ESAME) if (regs->psw.amode64 == 0 && (newia & 0x80000000)) #else /*!defined(FEATURE_ESAME)*/ if (newia & 0x80000000) #endif /*!defined(FEATURE_ESAME)*/ { regs->psw.amode = 1; regs->psw.AMASK = AMASK31; } else { regs->psw.amode = 0; regs->psw.AMASK = AMASK24; } /* Set mode and branch to address specified by R2 operand */ UPD_PSW_IA(regs, newia); /* Set the SSTD (or SASCE) equal to PSTD (or PASCE) */ regs->CR(7) = regs->CR(1); /* Set SASN equal to PASN */ regs->CR_LHL(3) = regs->CR_LHL(4); /* When ASN-and-LX-reuse is installed and enabled by CR0, set the SASTEIN in CR3 equal to the PASTEIN in CR4 */ if (ASN_AND_LX_REUSE_ENABLED(regs)) { regs->CR_H(3) = regs->CR_H(4); } /* end if (ASN_AND_LX_REUSE_ENABLED) */ /* Reset the subspace fields in the DUCT */ if (alet == ALET_SECONDARY) { /* When the destination ASTE specifies a subspace by means of ALET 1, set the subspace active bit in the DUCT */ duct1 |= DUCT1_SA; ARCH_DEP(store_fullword_absolute) (duct1, ducto+4, regs); } else if (dasteo == (duct0 & DUCT0_BASTEO)) { /* When the destination ASTE is the base space, reset the subspace active bit in the DUCT */ duct1 &= ~DUCT1_SA; ARCH_DEP(store_fullword_absolute) (duct1, ducto+4, regs); } else { /* When the destination ASTE specifies a subspace by means of an ALET other than ALET 1, set the subspace active bit and store the subspace ASTE origin in the DUCT */ duct1 = DUCT1_SA | dasteo; ARCH_DEP(store_fullword_absolute) (duct1, ducto+4, regs); /* Set the subspace ASTE sequence number in the DUCT equal to the destination ASTE sequence number */ duct3 = daste[5]; ARCH_DEP(store_fullword_absolute) (duct3, ducto+12, regs); } #ifdef FEATURE_TRACING /* Update trace table address if ASN tracing or branch tracing */ if (regs->CR(12) & (CR12_ASNTRACE | CR12_BRTRACE)) regs->CR(12) = newcr12; #endif /*FEATURE_TRACING*/ SET_AEA_COMMON(regs); if (inst_cr != regs->CR(regs->aea_ar[USE_INST_SPACE])) INVALIDATE_AIA(regs); /* Check for Successful Branch PER event */ PER_SB(regs, regs->psw.IA); } /* end DEF_INST(branch_in_subspace_group) */ #endif /*defined(FEATURE_SUBSPACE_GROUP)*/ #if defined(FEATURE_LINKAGE_STACK) /*-------------------------------------------------------------------*/ /* B240 BAKR - Branch and Stack Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(branch_and_stack) { int r1, r2; /* Values of R fields */ VADR n1, n2; /* Operand values */ #ifdef FEATURE_TRACING VADR n = 0; /* Work area */ #endif /*FEATURE_TRACING*/ RRE(inst, regs, r1, r2); SIE_XC_INTERCEPT(regs); #if defined(_FEATURE_SIE) if(SIE_STATB(regs, IC3, BAKR)) longjmp(regs->progjmp, SIE_INTERCEPT_INST); #endif /*defined(_FEATURE_SIE)*/ /* [5.12.3]/ Fig 10-2 Special operation exception if ASF is not enabled, or if DAT is off, or if not primary-space mode or AR-mode */ if (!ASF_ENABLED(regs) || REAL_MODE(®s->psw) || SPACE_BIT(®s->psw)) ARCH_DEP(program_interrupt) (regs, PGM_SPECIAL_OPERATION_EXCEPTION); /* Obtain the return address and addressing mode from the R1 register, or use updated PSW if R1 is zero */ if ( r1 != 0 ) { n1 = regs->GR(r1); #if defined(FEATURE_ESAME) if ( (n1 & 0x01) == 0 ) n1 &= (n1 & 0x80000000) ? 0xFFFFFFFF : 0x00FFFFFF; #else /*!defined(FEATURE_ESAME)*/ if ( (n1 & 0x80000000) == 0 ) n1 &= 0x00FFFFFF; #endif /*!defined(FEATURE_ESAME)*/ } else { n1 = PSW_IA(regs, 0); #if defined(FEATURE_ESAME) if ( regs->psw.amode64 ) n1 |= 0x01; else #endif /*defined(FEATURE_ESAME)*/ if ( regs->psw.amode ) n1 |= 0x80000000; } /* Obtain the branch address from the R2 register, or use the updated PSW instruction address if R2 is zero */ n2 = (r2 != 0) ? regs->GR(r2) : PSW_IA(regs, 0); n2 &= ADDRESS_MAXWRAP(regs); /* Set the addressing mode bit in the branch address */ #if defined(FEATURE_ESAME) if ( regs->psw.amode64 ) n2 |= 0x01; else #endif /*defined(FEATURE_ESAME)*/ if ( regs->psw.amode ) n2 |= 0x80000000; #ifdef FEATURE_TRACING /* Form the branch trace entry */ if((regs->CR(12) & CR12_BRTRACE) && (r2 != 0)) n = ARCH_DEP(trace_br)(regs->psw.amode, regs->GR_L(r2), regs); #endif /*FEATURE_TRACING*/ /* Form the linkage stack entry */ ARCH_DEP(form_stack_entry) (LSED_UET_BAKR, n1, n2, 0, 0, regs); #ifdef FEATURE_TRACING /* Update CR12 to reflect the new branch trace entry */ if((regs->CR(12) & CR12_BRTRACE) && (r2 != 0)) regs->CR(12) = n; #endif /*FEATURE_TRACING*/ /* Execute the branch unless R2 specifies register 0 */ if ( r2 != 0 ) { UPDATE_BEAR(regs, -4); UPD_PSW_IA(regs, regs->GR(r2)); PER_SB(regs, regs->psw.IA); } } /* end DEF_INST(branch_and_stack) */ #endif /*defined(FEATURE_LINKAGE_STACK)*/ #if defined(FEATURE_BROADCASTED_PURGING) /*-------------------------------------------------------------------*/ /* B250 CSP - Compare and Swap and Purge [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_and_swap_and_purge) { int r1, r2; /* Values of R fields */ U64 n2; /* virtual address of op2 */ BYTE *main2; /* mainstor address of op2 */ U32 old; /* old value */ RRE(inst, regs, r1, r2); PRIV_CHECK(regs); ODD_CHECK(r1, regs); #if defined(_FEATURE_SIE) if(SIE_STATB(regs,IC0, IPTECSP)) longjmp(regs->progjmp, SIE_INTERCEPT_INST); #endif /*defined(_FEATURE_SIE)*/ #if defined(_FEATURE_SIE) if(SIE_MODE(regs) && regs->sie_scao) { STORAGE_KEY(regs->sie_scao, regs) |= STORKEY_REF; if(regs->mainstor[regs->sie_scao] & 0x80) longjmp(regs->progjmp, SIE_INTERCEPT_INST); } #endif /*defined(_FEATURE_SIE)*/ /* Perform serialization before starting operation */ PERFORM_SERIALIZATION (regs); /* Obtain 2nd operand address from r2 */ n2 = regs->GR(r2) & 0xFFFFFFFFFFFFFFFCULL & ADDRESS_MAXWRAP(regs); main2 = MADDR (n2, r2, regs, ACCTYPE_WRITE, regs->psw.pkey); old = CSWAP32 (regs->GR_L(r1)); /* Obtain main-storage access lock */ OBTAIN_MAINLOCK(regs); /* Attempt to exchange the values */ regs->psw.cc = cmpxchg4 (&old, CSWAP32(regs->GR_L(r1+1)), main2); /* Release main-storage access lock */ RELEASE_MAINLOCK(regs); if (regs->psw.cc == 0) { /* Perform requested funtion specified as per request code in r2 */ if (regs->GR_L(r2) & 3) { OBTAIN_INTLOCK(regs); SYNCHRONIZE_CPUS(regs); if (regs->GR_L(r2) & 1) ARCH_DEP(purge_tlb_all)(); if (regs->GR_L(r2) & 2) ARCH_DEP(purge_alb_all)(); RELEASE_INTLOCK(regs); } } else { PTT(PTT_CL_CSF,"*CSP",regs->GR_L(r1),regs->GR_L(r2),regs->psw.IA_L); /* Otherwise yield */ regs->GR_L(r1) = CSWAP32(old); if (sysblk.cpus > 1) sched_yield(); } /* Perform serialization after completing operation */ PERFORM_SERIALIZATION (regs); } /* end DEF_INST(compare_and_swap_and_purge) */ #endif /*defined(FEATURE_BROADCASTED_PURGING)*/ /*-------------------------------------------------------------------*/ /* 83 DIAG - Diagnose [RS] */ /*-------------------------------------------------------------------*/ DEF_INST(diagnose) { int r1, r3; /* Register numbers */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ RS(inst, regs, r1, r3, b2, effective_addr2); #if defined(FEATURE_ECPSVM) if(ecpsvm_dodiag(regs,r1,r3,b2,effective_addr2)==0) { return; } #endif #ifdef FEATURE_HERCULES_DIAGCALLS if ( #if defined(_FEATURE_SIE) !SIE_MODE(regs) && #endif /* defined(_FEATURE_SIE) */ effective_addr2 != 0xF08) #endif PRIV_CHECK(regs); SIE_INTERCEPT(regs); PTT(PTT_CL_INF,"DIAG",regs->GR_L(r1),regs->GR_L(r3),(U32)(effective_addr2 & 0xffffff)); /* Process diagnose instruction */ ARCH_DEP(diagnose_call) (effective_addr2, b2, r1, r3, regs); /* Perform serialization and checkpoint-synchronization */ PERFORM_SERIALIZATION (regs); PERFORM_CHKPT_SYNC (regs); #ifdef FEATURE_HERCULES_DIAGCALLS RETURN_INTCHECK(regs); #endif } /* end DEF_INST(diagnose) */ #if defined(FEATURE_DUAL_ADDRESS_SPACE) /*-------------------------------------------------------------------*/ /* B226 EPAR - Extract Primary ASN [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(extract_primary_asn) { int r1, r2; /* Values of R fields */ RRE(inst, regs, r1, r2); SIE_XC_INTERCEPT(regs); /* Special operation exception if DAT is off */ if ( (regs->psw.sysmask & PSW_DATMODE) == 0 ) ARCH_DEP(program_interrupt) (regs, PGM_SPECIAL_OPERATION_EXCEPTION); /* Privileged operation exception if in problem state and the extraction-authority control bit is zero */ if ( PROBSTATE(®s->psw) && (regs->CR(0) & CR0_EXT_AUTH) == 0 ) ARCH_DEP(program_interrupt) (regs, PGM_PRIVILEGED_OPERATION_EXCEPTION); /* Load R1 bits 48-63 with PASN from control register 4 bits 48-63 and zeroize R1 bits 32-47 */ regs->GR_L(r1) = regs->CR_LHL(4); } /* end DEF_INST(extract_primary_asn) */ #endif /*defined(FEATURE_DUAL_ADDRESS_SPACE)*/ #if defined(FEATURE_ASN_AND_LX_REUSE) /*-------------------------------------------------------------------*/ /* B99A EPAIR - Extract Primary ASN and Instance [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(extract_primary_asn_and_instance) { int r1, r2; /* Values of R fields */ /* Operation exception if ASN-and-LX-reuse is not enabled */ if(!sysblk.asnandlxreuse) { ARCH_DEP(operation_exception)(inst,regs); } RRE(inst, regs, r1, r2); SIE_XC_INTERCEPT(regs); /* Special operation exception if DAT is off */ if ( (regs->psw.sysmask & PSW_DATMODE) == 0 ) ARCH_DEP(program_interrupt) (regs, PGM_SPECIAL_OPERATION_EXCEPTION); /* Privileged operation exception if in problem state and the extraction-authority control bit is zero */ if ( PROBSTATE(®s->psw) && (regs->CR(0) & CR0_EXT_AUTH) == 0 ) ARCH_DEP(program_interrupt) (regs, PGM_PRIVILEGED_OPERATION_EXCEPTION); /* Load R1 bits 48-63 with PASN from control register 4 bits 48-63 and zeroize R1 bits 32-47 */ regs->GR_L(r1) = regs->CR_LHL(4); /* Load R1 bits 0-31 with PASTEIN from control register 4 bits 0-31 */ regs->GR_H(r1) = regs->CR_H(4); } /* end DEF_INST(extract_primary_asn_and_instance) */ #endif /*defined(FEATURE_ASN_AND_LX_REUSE)*/ #if defined(FEATURE_DUAL_ADDRESS_SPACE) /*-------------------------------------------------------------------*/ /* B227 ESAR - Extract Secondary ASN [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(extract_secondary_asn) { int r1, r2; /* Values of R fields */ RRE(inst, regs, r1, r2); SIE_XC_INTERCEPT(regs); /* Special operation exception if DAT is off */ if ( (regs->psw.sysmask & PSW_DATMODE) == 0 ) ARCH_DEP(program_interrupt) (regs, PGM_SPECIAL_OPERATION_EXCEPTION); /* Privileged operation exception if in problem state and the extraction-authority control bit is zero */ if ( PROBSTATE(®s->psw) && (regs->CR(0) & CR0_EXT_AUTH) == 0 ) ARCH_DEP(program_interrupt) (regs, PGM_PRIVILEGED_OPERATION_EXCEPTION); /* Load R1 bits 48-63 with SASN from control register 3 bits 48-63 and zeroize R1 bits 32-47 */ regs->GR_L(r1) = regs->CR_LHL(3); } /* end DEF_INST(extract_secondary_asn) */ #endif /*defined(FEATURE_DUAL_ADDRESS_SPACE)*/ #if defined(FEATURE_ASN_AND_LX_REUSE) /*-------------------------------------------------------------------*/ /* B99B ESAIR - Extract Secondary ASN and Instance [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(extract_secondary_asn_and_instance) { int r1, r2; /* Values of R fields */ /* Operation exception if ASN-and-LX-reuse is not enabled */ if(!sysblk.asnandlxreuse) { ARCH_DEP(operation_exception)(inst,regs); } RRE(inst, regs, r1, r2); SIE_XC_INTERCEPT(regs); /* Special operation exception if DAT is off */ if ( (regs->psw.sysmask & PSW_DATMODE) == 0 ) ARCH_DEP(program_interrupt) (regs, PGM_SPECIAL_OPERATION_EXCEPTION); /* Privileged operation exception if in problem state and the extraction-authority control bit is zero */ if ( PROBSTATE(®s->psw) && (regs->CR(0) & CR0_EXT_AUTH) == 0 ) ARCH_DEP(program_interrupt) (regs, PGM_PRIVILEGED_OPERATION_EXCEPTION); /* Load R1 bits 48-63 with SASN from control register 3 bits 48-63 and zeroize R1 bits 32-47 */ regs->GR_L(r1) = regs->CR_LHL(3); /* Load R1 bits 0-31 with SASTEIN from control register 3 bits 0-31 */ regs->GR_H(r1) = regs->CR_H(3); } /* end DEF_INST(extract_secondary_asn_and_instance) */ #endif /*defined(FEATURE_ASN_AND_LX_REUSE)*/ #if defined(FEATURE_LINKAGE_STACK) /*-------------------------------------------------------------------*/ /* B249 EREG - Extract Stacked Registers [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(extract_stacked_registers) { int r1, r2; /* Values of R fields */ LSED lsed; /* Linkage stack entry desc. */ VADR lsea; /* Linkage stack entry addr */ RRE(inst, regs, r1, r2); SIE_XC_INTERCEPT(regs); /* Find the virtual address of the entry descriptor of the current state entry in the linkage stack */ lsea = ARCH_DEP(locate_stack_entry) (0, &lsed, regs); /* Load registers from the stack entry */ ARCH_DEP(unstack_registers) (0, lsea, r1, r2, regs); } #endif /*defined(FEATURE_LINKAGE_STACK)*/ #if defined(FEATURE_LINKAGE_STACK) /*-------------------------------------------------------------------*/ /* B24A ESTA - Extract Stacked State [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(extract_stacked_state) { int r1, r2; /* Values of R fields */ BYTE code; /* Extraction code */ LSED lsed; /* Linkage stack entry desc. */ VADR lsea; /* Linkage stack entry addr */ int max_esta_code; RRE(inst, regs, r1, r2); SIE_XC_INTERCEPT(regs); if (REAL_MODE(®s->psw) || SECONDARY_SPACE_MODE(®s->psw) || !ASF_ENABLED(regs)) ARCH_DEP(program_interrupt) (regs, PGM_SPECIAL_OPERATION_EXCEPTION); /* Load the extraction code from low-order byte of R2 register */ code = regs->GR_LHLCL(r2); #if defined(FEATURE_ASN_AND_LX_REUSE) max_esta_code=sysblk.asnandlxreuse?5:4; #elif defined(FEATURE_ESAME) max_esta_code=4; #else /*!defined(FEATURE_ESAME)*/ max_esta_code=3; #endif /*!defined(FEATURE_ESAME)*/ /* Program check if r1 is odd, or if extraction code is invalid */ if ((r1 & 1) || code > max_esta_code) ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION); /* Find the virtual address of the entry descriptor of the current state entry in the linkage stack */ lsea = ARCH_DEP(locate_stack_entry) (0, &lsed, regs); /* Load general register pair from state entry */ ARCH_DEP(stack_extract) (lsea, r1, code, regs); /* Set condition code depending on entry type */ regs->psw.cc = ((lsed.uet & LSED_UET_ET) == LSED_UET_PC) ? 1 : 0; } #endif /*defined(FEATURE_LINKAGE_STACK)*/ #if defined(FEATURE_DUAL_ADDRESS_SPACE) /*-------------------------------------------------------------------*/ /* B224 IAC - Insert Address Space Control [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(insert_address_space_control) { int r1, r2; /* Values of R fields */ RRE(inst, regs, r1, r2); /* Special operation exception if DAT is off */ if ( REAL_MODE(&(regs->psw)) #if defined(FEATURE_MULTIPLE_CONTROLLED_DATA_SPACE) /* Except in XC mode */ && !SIE_STATB(regs, MX, XC) #endif /*defined(FEATURE_MULTIPLE_CONTROLLED_DATA_SPACE)*/ ) ARCH_DEP(program_interrupt) (regs, PGM_SPECIAL_OPERATION_EXCEPTION); /* Privileged operation exception if in problem state and the extraction-authority control bit is zero */ if ( PROBSTATE(®s->psw) && !(regs->CR(0) & CR0_EXT_AUTH) #if defined(FEATURE_MULTIPLE_CONTROLLED_DATA_SPACE) /* Ignore extraction control in XC mode */ && !SIE_STATB(regs, MX, XC) #endif /*defined(FEATURE_MULTIPLE_CONTROLLED_DATA_SPACE)*/ ) ARCH_DEP(program_interrupt) (regs, PGM_PRIVILEGED_OPERATION_EXCEPTION); /* Extract the address-space control bits from the PSW */ regs->psw.cc = (AR_BIT(®s->psw) << 1) | SPACE_BIT(®s->psw); /* Insert address-space mode into register bits 22-23 */ regs->GR_LHLCH(r1) = regs->psw.cc; } #endif /*defined(FEATURE_DUAL_ADDRESS_SPACE)*/ /*-------------------------------------------------------------------*/ /* B20B IPK - Insert PSW Key [S] */ /*-------------------------------------------------------------------*/ DEF_INST(insert_psw_key) { int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ S(inst, regs, b2, effective_addr2); /* Privileged operation exception if in problem state and the extraction-authority control bit is zero */ if ( PROBSTATE(®s->psw) && (regs->CR(0) & CR0_EXT_AUTH) == 0 ) ARCH_DEP(program_interrupt) (regs, PGM_PRIVILEGED_OPERATION_EXCEPTION); /* Insert PSW key into bits 24-27 of general register 2 and set bits 28-31 of general register 2 to zero */ regs->GR_LHLCL(2) = regs->psw.pkey & 0xF0; } #if defined(FEATURE_BASIC_STORAGE_KEYS) /*-------------------------------------------------------------------*/ /* 09 ISK - Insert Storage Key [RR] */ /*-------------------------------------------------------------------*/ DEF_INST(insert_storage_key) { int r1, r2; /* Values of R fields */ RADR n; /* Absolute storage addr */ #if defined(_FEATURE_SIE) BYTE storkey; #endif /*defined(_FEATURE_SIE)*/ RR(inst, regs, r1, r2); PRIV_CHECK(regs); #if defined(FEATURE_4K_STORAGE_KEYS) || defined(_FEATURE_SIE) if( #if defined(_FEATURE_SIE) && !defined(FEATURE_4K_STORAGE_KEYS) SIE_MODE(regs) && #endif !(regs->CR(0) & CR0_STORKEY_4K) ) ARCH_DEP(program_interrupt) (regs, PGM_SPECIAL_OPERATION_EXCEPTION); #endif /* Program check if R2 bits 28-31 are not zeroes */ if ( regs->GR_L(r2) & 0x0000000F ) ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION); /* Load 2K block address from R2 register */ n = regs->GR_L(r2) & 0x00FFF800; /* Convert real address to absolute address */ n = APPLY_PREFIXING (n, regs->PX); /* Addressing exception if block is outside main storage */ if ( n > regs->mainlim ) ARCH_DEP(program_interrupt) (regs, PGM_ADDRESSING_EXCEPTION); #if defined(_FEATURE_SIE) if(SIE_MODE(regs)) { if(SIE_STATB(regs, IC2, ISKE)) longjmp(regs->progjmp, SIE_INTERCEPT_INST); if(!regs->sie_pref) { #if defined(_FEATURE_STORAGE_KEY_ASSIST) if(SIE_STATB(regs, RCPO0, SKA) && SIE_STATB(regs, RCPO2, RCPBY)) { SIE_TRANSLATE(&n, ACCTYPE_SIE, regs); #if !defined(_FEATURE_2K_STORAGE_KEYS) regs->GR_LHLCL(r1) = STORAGE_KEY(n, regs) & 0xFE; #else regs->GR_LHLCL(r1) = (STORAGE_KEY1(n, regs) | STORAGE_KEY2(n, regs)) & 0xFE; #endif } else #endif /*defined(_FEATURE_STORAGE_KEY_ASSIST)*/ { RADR rcpa; BYTE rcpkey; #if defined(_FEATURE_STORAGE_KEY_ASSIST) if(SIE_STATB(regs, RCPO0, SKA)) { /* guest absolute to host PTE addr */ if (SIE_TRANSLATE_ADDR (regs->sie_mso + n, USE_PRIMARY_SPACE, regs->hostregs, ACCTYPE_PTE)) longjmp(regs->progjmp, SIE_INTERCEPT_INST); /* Convert real address to absolute address */ rcpa = APPLY_PREFIXING (regs->hostregs->dat.raddr, regs->hostregs->PX); /* The reference and change byte is located directly beyond the page table and is located at offset 1 in the entry. S/370 mode cannot be emulated in ESAME mode, so no provision is made for ESAME mode tables */ rcpa += 1025; } else #endif /*defined(_FEATURE_STORAGE_KEY_ASSIST)*/ { /* Obtain address of the RCP area from the state desc */ rcpa = regs->sie_rcpo &= 0x7FFFF000; /* frame index as byte offset to 4K keys in RCP area */ rcpa += n >> 12; /* host primary to host absolute */ rcpa = SIE_LOGICAL_TO_ABS (rcpa, USE_PRIMARY_SPACE, regs->hostregs, ACCTYPE_SIE, 0); } /* fetch the RCP key */ rcpkey = regs->mainstor[rcpa]; STORAGE_KEY(rcpa, regs) |= STORKEY_REF; /* The storage key is obtained by logical or or the real and guest RC bits */ storkey = rcpkey & (STORKEY_REF | STORKEY_CHANGE); /* guest absolute to host real */ if (SIE_TRANSLATE_ADDR (regs->sie_mso + n, USE_PRIMARY_SPACE, regs->hostregs, ACCTYPE_SIE)) #if defined(_FEATURE_STORAGE_KEY_ASSIST) { /* In case of storage key assist obtain the key and fetch bit from the PGSTE */ if(SIE_STATB(regs, RCPO0, SKA)) regs->GR_LHLCL(r1) = storkey | (regs->mainstor[rcpa-1] & (STORKEY_KEY | STORKEY_FETCH)); else longjmp(regs->progjmp, SIE_INTERCEPT_INST); } else #else /*!defined(_FEATURE_STORAGE_KEY_ASSIST)*/ longjmp(regs->progjmp, SIE_INTERCEPT_INST); #endif /*defined(_FEATURE_STORAGE_KEY_ASSIST)*/ { /* host real to host absolute */ n = APPLY_PREFIXING(regs->hostregs->dat.raddr, regs->hostregs->PX); #if !defined(_FEATURE_2K_STORAGE_KEYS) regs->GR_LHLCL(r1) = storkey | (STORAGE_KEY(n, regs) & 0xFE); #else regs->GR_LHLCL(r1) = storkey | ((STORAGE_KEY1(n, regs) | STORAGE_KEY2(n, regs)) & 0xFE); #endif } } } else /* !sie_pref */ #if !defined(_FEATURE_2K_STORAGE_KEYS) regs->GR_LHLCL(r1) = STORAGE_KEY(n, regs) & 0xFE; #else regs->GR_LHLCL(r1) = (STORAGE_KEY1(n, regs) | STORAGE_KEY2(n, regs)) & 0xFE; #endif } else /* !SIE_MODE */ #endif /*defined(_FEATURE_SIE)*/ /* Insert the storage key into R1 register bits 24-31 */ #if defined(_FEATURE_2K_STORAGE_KEYS) regs->GR_LHLCL(r1) = STORAGE_KEY(n, regs) & 0xFE; #else regs->GR_LHLCL(r1) = (STORAGE_KEY1(n, regs) | STORAGE_KEY2(n, regs)) & 0xFE; #endif /* In BC mode, clear bits 29-31 of R1 register */ if ( !ECMODE(®s->psw) ) regs->GR_LHLCL(r1) &= 0xF8; // /*debug*/logmsg("ISK storage block %8.8X key %2.2X\n", // regs->GR_L(r2), regs->GR_L(r1) & 0xFE); } #endif /*defined(FEATURE_BASIC_STORAGE_KEYS)*/ #if defined(FEATURE_EXTENDED_STORAGE_KEYS) /*-------------------------------------------------------------------*/ /* B229 ISKE - Insert Storage Key Extended [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(insert_storage_key_extended) { int r1, r2; /* Values of R fields */ RADR n; /* Workarea */ #if defined(_FEATURE_SIE) BYTE storkey; #endif /*defined(_FEATURE_SIE)*/ RRE(inst, regs, r1, r2); PRIV_CHECK(regs); /* Load 4K block address from R2 register */ n = regs->GR(r2) & ADDRESS_MAXWRAP_E(regs); /* Convert real address to absolute address */ n = APPLY_PREFIXING (n, regs->PX); /* Addressing exception if block is outside main storage */ if ( n > regs->mainlim ) ARCH_DEP(program_interrupt) (regs, PGM_ADDRESSING_EXCEPTION); #if defined(_FEATURE_SIE) if(SIE_MODE(regs)) { if(SIE_STATB(regs, IC2, ISKE)) longjmp(regs->progjmp, SIE_INTERCEPT_INST); if(!regs->sie_pref) { #if defined(_FEATURE_STORAGE_KEY_ASSIST) if((SIE_STATB(regs, RCPO0, SKA) #if defined(_FEATURE_ZSIE) || (regs->hostregs->arch_mode == ARCH_900) #endif /*defined(_FEATURE_ZSIE)*/ ) && SIE_STATB(regs, RCPO2, RCPBY)) { SIE_TRANSLATE(&n, ACCTYPE_SIE, regs); /* Insert the storage key into R1 register bits 24-31 */ #if !defined(_FEATURE_2K_STORAGE_KEYS) regs->GR_LHLCL(r1) = STORAGE_KEY(n, regs) & 0xFE; #else regs->GR_LHLCL(r1) = (STORAGE_KEY1(n, regs) | STORAGE_KEY2(n, regs)) & 0xFE; #endif } else #endif /*defined(_FEATURE_STORAGE_KEY_ASSIST)*/ { RADR rcpa; BYTE rcpkey; #if defined(_FEATURE_STORAGE_KEY_ASSIST) if(SIE_STATB(regs, RCPO0, SKA) #if defined(_FEATURE_ZSIE) || (regs->hostregs->arch_mode == ARCH_900) #endif /*defined(_FEATURE_ZSIE)*/ ) { /* guest absolute to host PTE addr */ if (SIE_TRANSLATE_ADDR (regs->sie_mso + n, USE_PRIMARY_SPACE, regs->hostregs, ACCTYPE_PTE)) longjmp(regs->progjmp, SIE_INTERCEPT_INST); /* Convert real address to absolute address */ rcpa = APPLY_PREFIXING (regs->hostregs->dat.raddr, regs->hostregs->PX); /* For ESA/390 the RCP byte entry is at offset 1 in a four byte entry directly beyond the page table, for ESAME mode, this entry is eight bytes long */ rcpa += regs->hostregs->arch_mode == ARCH_900 ? 2049 : 1025; } else #endif /*defined(_FEATURE_STORAGE_KEY_ASSIST)*/ { #if defined(FEATURE_MULTIPLE_CONTROLLED_DATA_SPACE) if(SIE_STATB(regs, MX, XC)) longjmp(regs->progjmp, SIE_INTERCEPT_INST); #endif /*defined(FEATURE_MULTIPLE_CONTROLLED_DATA_SPACE)*/ /* Obtain address of the RCP area from the state desc */ rcpa = regs->sie_rcpo &= 0x7FFFF000; /* frame index as byte offset to 4K keys in RCP area */ rcpa += n >> 12; /* host primary to host absolute */ rcpa = SIE_LOGICAL_TO_ABS (rcpa, USE_PRIMARY_SPACE, regs->hostregs, ACCTYPE_SIE, 0); } /* fetch the RCP key */ rcpkey = regs->mainstor[rcpa]; STORAGE_KEY(rcpa, regs) |= STORKEY_REF; /* The storage key is obtained by logical or or the real and guest RC bits */ storkey = rcpkey & (STORKEY_REF | STORKEY_CHANGE); /* guest absolute to host real */ if (SIE_TRANSLATE_ADDR (regs->sie_mso + n, USE_PRIMARY_SPACE, regs->hostregs, ACCTYPE_SIE)) #if defined(_FEATURE_STORAGE_KEY_ASSIST) { /* In case of storage key assist obtain the key and fetch bit from the PGSTE */ if(SIE_STATB(regs, RCPO0, SKA)) regs->GR_LHLCL(r1) = storkey | (regs->mainstor[rcpa-1] & (STORKEY_KEY | STORKEY_FETCH)); else longjmp(regs->progjmp, SIE_INTERCEPT_INST); } else #else /*!defined(_FEATURE_STORAGE_KEY_ASSIST)*/ longjmp(regs->progjmp, SIE_INTERCEPT_INST); #endif /*defined(_FEATURE_STORAGE_KEY_ASSIST)*/ { /* host real to host absolute */ n = APPLY_PREFIXING(regs->hostregs->dat.raddr, regs->hostregs->PX); /* Insert the storage key into R1 register bits 24-31 */ #if !defined(_FEATURE_2K_STORAGE_KEYS) regs->GR_LHLCL(r1) = storkey | (STORAGE_KEY(n, regs) & 0xFE); #else regs->GR_LHLCL(r1) = storkey | ((STORAGE_KEY1(n, regs) | STORAGE_KEY2(n, regs)) & 0xFE); #endif } } } else /* sie_pref */ /* Insert the storage key into R1 register bits 24-31 */ #if !defined(_FEATURE_2K_STORAGE_KEYS) regs->GR_LHLCL(r1) = STORAGE_KEY(n, regs) & 0xFE; #else regs->GR_LHLCL(r1) = (STORAGE_KEY1(n, regs) | STORAGE_KEY2(n, regs)) & 0xFE; #endif } else /* !SIE_MODE */ #endif /*defined(_FEATURE_SIE)*/ /* Insert the storage key into R1 register bits 24-31 */ #if !defined(_FEATURE_2K_STORAGE_KEYS) regs->GR_LHLCL(r1) = STORAGE_KEY(n, regs) & 0xFE; #else regs->GR_LHLCL(r1) = (STORAGE_KEY1(n, regs) | STORAGE_KEY2(n, regs)) & 0xFE; #endif } /* end DEF_INST(insert_storage_key_extended) */ #endif /*defined(FEATURE_EXTENDED_STORAGE_KEYS)*/ #if defined(FEATURE_DUAL_ADDRESS_SPACE) /*-------------------------------------------------------------------*/ /* B223 IVSK - Insert Virtual Storage Key [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(insert_virtual_storage_key) { int r1, r2; /* Values of R fields */ VADR effective_addr; /* Virtual storage addr */ RADR n; /* 32-bit operand values */ #if defined(_FEATURE_STORAGE_KEY_ASSIST) int sr; /* SIE_TRANSLATE_ADDR rc */ #endif /*defined(_FEATURE_STORAGE_KEY_ASSIST)*/ RRE(inst, regs, r1, r2); /* Special operation exception if DAT is off */ if ( (regs->psw.sysmask & PSW_DATMODE) == 0 ) ARCH_DEP(program_interrupt) (regs, PGM_SPECIAL_OPERATION_EXCEPTION); /* Privileged operation exception if in problem state and the extraction-authority control bit is zero */ if ( PROBSTATE(®s->psw) && (regs->CR(0) & CR0_EXT_AUTH) == 0 ) ARCH_DEP(program_interrupt) (regs, PGM_PRIVILEGED_OPERATION_EXCEPTION); /* Load virtual storage address from R2 register */ effective_addr = regs->GR(r2) & ADDRESS_MAXWRAP(regs); /* Translate virtual address to real address */ if (ARCH_DEP(translate_addr) (effective_addr, r2, regs, ACCTYPE_IVSK)) ARCH_DEP(program_interrupt) (regs, regs->dat.xcode); /* Convert real address to absolute address */ n = APPLY_PREFIXING (regs->dat.raddr, regs->PX); /* Addressing exception if block is outside main storage */ if ( n > regs->mainlim ) ARCH_DEP(program_interrupt) (regs, PGM_ADDRESSING_EXCEPTION); #if defined(_FEATURE_STORAGE_KEY_ASSIST) /* When running under SIE, and the guest absolute address is paged out, then obtain the storage key from the SPGTE rather then causing a host page fault. */ if(SIE_MODE(regs) && !regs->sie_pref && (SIE_STATB(regs, RCPO0, SKA) #if defined(_FEATURE_ZSIE) || (regs->hostregs->arch_mode == ARCH_900) #endif /*defined(_FEATURE_ZSIE)*/ ) && !SIE_FEATB(regs, RCPO2, RCPBY)) { /* guest absolute to host absolute addr or PTE addr in case of rc2 */ sr = SIE_TRANSLATE_ADDR (regs->sie_mso + n, USE_PRIMARY_SPACE, regs->hostregs, ACCTYPE_SIE); n = APPLY_PREFIXING (regs->hostregs->dat.raddr, regs->hostregs->PX); if(sr != 0 && sr != 2) ARCH_DEP(program_interrupt) (regs->hostregs, regs->hostregs->dat.xcode); if(sr == 2) { /* For ESA/390 the RCP byte entry is at offset 0 in a four byte entry directly beyond the page table, for ESAME mode, this entry is eight bytes long */ n += regs->hostregs->arch_mode == ARCH_900 ? 2048 : 1024; /* Insert PGSTE key bits 0-4 into R1 register bits 56-60 and set bits 61-63 to zeroes */ regs->GR_LHLCL(r1) = regs->mainstor[n] & 0xF8; } else /* Insert storage key bits 0-4 into R1 register bits 56-60 and set bits 61-63 to zeroes */ regs->GR_LHLCL(r1) = STORAGE_KEY(n, regs) & 0xF8; } else #endif /*defined(_FEATURE_STORAGE_KEY_ASSIST)*/ { SIE_TRANSLATE(&n, ACCTYPE_SIE, regs); /* Insert storage key bits 0-4 into R1 register bits 56-60 and set bits 61-63 to zeroes */ regs->GR_LHLCL(r1) = STORAGE_KEY(n, regs) & 0xF8; } } /* end DEF_INST(insert_virtual_storage_key) */ #endif /*defined(FEATURE_DUAL_ADDRESS_SPACE)*/ /*-------------------------------------------------------------------*/ /* B221 IPTE - Invalidate Page Table Entry [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(invalidate_page_table_entry) { int r1, r2; /* Values of R fields */ RRE(inst, regs, r1, r2); PRIV_CHECK(regs); #if defined(_FEATURE_SIE) if(SIE_STATB(regs, IC0, IPTECSP)) longjmp(regs->progjmp, SIE_INTERCEPT_INST); #endif /*defined(_FEATURE_SIE)*/ /* Perform serialization before operation */ PERFORM_SERIALIZATION (regs); OBTAIN_INTLOCK(regs); SYNCHRONIZE_CPUS(regs); #if defined(_FEATURE_SIE) if(SIE_MODE(regs) && regs->sie_scao) { STORAGE_KEY(regs->sie_scao, regs) |= STORKEY_REF; if(regs->mainstor[regs->sie_scao] & 0x80) { RELEASE_INTLOCK(regs); longjmp(regs->progjmp, SIE_INTERCEPT_INST); } regs->mainstor[regs->sie_scao] |= 0x80; STORAGE_KEY(regs->sie_scao, regs) |= (STORKEY_REF|STORKEY_CHANGE); } #endif /*defined(_FEATURE_SIE)*/ /* Invalidate page table entry */ ARCH_DEP(invalidate_pte) (inst[1], r1, r2, regs); #if defined(_FEATURE_SIE) if(SIE_MODE(regs) && regs->sie_scao) { regs->mainstor[regs->sie_scao] &= 0x7F; STORAGE_KEY(regs->sie_scao, regs) |= (STORKEY_REF|STORKEY_CHANGE); } #endif /*defined(_FEATURE_SIE)*/ RELEASE_INTLOCK(regs); } /* DEF_INST(invalidate_page_table_entry) */ #if defined(FEATURE_DUAL_ADDRESS_SPACE) /*-------------------------------------------------------------------*/ /* E500 LASP - Load Address Space Parameters [SSE] */ /*-------------------------------------------------------------------*/ DEF_INST(load_address_space_parameters) { int b1, b2; /* Values of base field */ VADR effective_addr1, effective_addr2; /* Effective addresses */ U64 dreg; U32 sastein_d = 0; /* Designated SASTEIN */ U32 pastein_d = 0; /* Designated PASTEIN */ U32 sastein_new = 0; /* New SASTEIN */ U32 pastein_new = 0; /* New PASTEIN */ U16 pkm_d; /* Designated PKM */ U16 sasn_d; /* Designated SASN */ U16 ax_d; /* Designated AX */ U16 pasn_d; /* Designated PASN */ U32 aste[16]; /* ASN second table entry */ RADR pstd; /* Primary STD */ RADR sstd; /* Secondary STD */ U32 ltd; /* Linkage table designation */ U32 pasteo=0; /* Primary ASTE origin */ U32 sasteo=0; /* Secondary ASTE origin */ U16 ax; /* Authorisation index */ #ifdef FEATURE_SUBSPACE_GROUP U16 xcode; /* Exception code */ #endif /*FEATURE_SUBSPACE_GROUP*/ CREG inst_cr; /* Instruction CR */ SSE(inst, regs, b1, effective_addr1, b2, effective_addr2); SIE_XC_INTERCEPT(regs); PRIV_CHECK(regs); /* Special operation exception if ASN translation control (bit 12 of control register 14) is zero */ if ( (regs->CR(14) & CR14_ASN_TRAN) == 0 ) ARCH_DEP(program_interrupt) (regs, PGM_SPECIAL_OPERATION_EXCEPTION); DW_CHECK(effective_addr1, regs); #if defined(_FEATURE_SIE) if(SIE_STATB(regs, IC2, LASP)) longjmp(regs->progjmp, SIE_INTERCEPT_INST); #endif /*defined(_FEATURE_SIE)*/ inst_cr = regs->CR(regs->aea_ar[USE_INST_SPACE]); /* Fetch LASP parameters from first operand location (note that the storage-operand references for LASP may be multiple-access references) */ if (ASN_AND_LX_REUSE_ENABLED(regs)) { /* When ASN-and-LX-reuse is installed and enabled by CR0, the first operand consists of two doublewords */ /* The first doubleword contains the SASTEIN-d (32 bits), PKM-d (16 bits), and SASN-d (16 bits) */ dreg = ARCH_DEP(vfetch8) ( effective_addr1, b1, regs ); sastein_d = (dreg >> 32); pkm_d = (dreg >> 16) & 0xFFFF; sasn_d = dreg & 0xFFFF; /* The second doubleword contains the PASTEIN-d (32 bits), AX-d (16 bits), and PASN-d (16 bits) */ effective_addr1 += 8; effective_addr1 &= ADDRESS_MAXWRAP(regs); dreg = ARCH_DEP(vfetch8) ( effective_addr1, b1, regs ); pastein_d = (dreg >> 32); ax_d = (dreg >> 16) & 0xFFFF; pasn_d = dreg & 0xFFFF; } else /* !ASN_AND_LX_REUSE_ENABLED */ { /* When ASN-and-LX-reuse is not installed or not enabled, the first operand is one doubleword containing the PKM-d, SASN-d, AX-d, and PASN-d (16 bits each) */ dreg = ARCH_DEP(vfetch8) ( effective_addr1, b1, regs ); pkm_d = (dreg >> 48) & 0xFFFF; sasn_d = (dreg >> 32) & 0xFFFF; ax_d = (dreg >> 16) & 0xFFFF; pasn_d = dreg & 0xFFFF; } /* end else !ASN_AND_LX_REUSE_ENABLED */ /* PASN translation */ /* Perform PASN translation if PASN not equal to current PASN, or if LASP function bit 29 is set */ if ((effective_addr2 & 0x00000004) || pasn_d != regs->CR_LHL(4) ) { /* Translate PASN and return condition code 1 if AFX- or ASX-translation exception condition */ if (ARCH_DEP(translate_asn) (pasn_d, regs, &pasteo, aste)) { regs->psw.cc = 1; return; } /* When ASN-and-LX-reuse is installed and enabled by CR0, condition code 1 is also set if the PASTEIN-d does not equal the ASTEIN in word 11 of the ASTE */ if (ASN_AND_LX_REUSE_ENABLED(regs) && pastein_d != aste[11]) { regs->psw.cc = 1; return; } /* end if(ASN_AND_LX_REUSE_ENABLED && pastein_d!=aste[11]) */ /* Obtain new PSTD and LTD from ASTE */ pstd = ASTE_AS_DESIGNATOR(aste); ltd = ASTE_LT_DESIGNATOR(aste); ax = (aste[1] & ASTE1_AX) >> 16; /* When ASN-and-LX-reuse is installed and enabled by CR0, set the new PASTEIN equal to the PASTEIN-d */ if (ASN_AND_LX_REUSE_ENABLED(regs)) pastein_new = pastein_d; #ifdef FEATURE_SUBSPACE_GROUP /* Perform subspace replacement on new PSTD */ pstd = ARCH_DEP(subspace_replace) (pstd, pasteo, &xcode, regs); /* Return with condition code 1 if ASTE exception recognized */ if (xcode != 0) { regs->psw.cc = 1; return; } #endif /*FEATURE_SUBSPACE_GROUP*/ /* Return with condition code 3 if either current STD or new STD indicates a space switch event */ if ((regs->CR(1) & SSEVENT_BIT) || (ASTE_AS_DESIGNATOR(aste) & SSEVENT_BIT)) { regs->psw.cc = 3; return; } } else { /* Load current PSTD and LTD or PASTEO */ pstd = regs->CR(1); ltd = regs->CR_L(5); /* ZZZ1 NOT SURE ABOUT THE MEANING OF THIS CODE: REFER TO ZZZ2 */ pasteo = regs->CR_L(5); /* ZZZ1 NOT SURE ABOUT THE MEANING OF THIS CODE: REFER TO ZZZ2 */ ax = (regs->CR(4) & CR4_AX) >> 16; /* When ASN-and-LX-reuse is installed and enabled by CR0, load the current PASTEIN */ if (ASN_AND_LX_REUSE_ENABLED(regs)) pastein_new = regs->CR_H(4); } /* If bit 30 of the LASP function bits is zero, use the current AX instead of the AX specified in the first operand */ if ((effective_addr2 & 0x00000002)) ax = ax_d; /* SASN translation */ /* If new SASN = new PASN then set new SSTD = new PSTD, also set the new SASTEIN equal to new PASTEIN when ASN-and-LX-reuse is installed and enabled by CR0 */ if (sasn_d == pasn_d) { sstd = pstd; if (ASN_AND_LX_REUSE_ENABLED(regs)) sastein_new = pastein_new; } else { /* If new SASN = current SASN, and bit 29 of the LASP function bits is 0, and bit 31 of the LASP function bits is 1, use current SSTD/SASCE in control register 7, also use current SASTEIN if ASN-and-LX-reuse is installed and enabled by CR0 */ if (!(effective_addr2 & 0x00000004) && (effective_addr2 & 0x00000001) && (sasn_d == regs->CR_LHL(3))) { sstd = regs->CR(7); if (ASN_AND_LX_REUSE_ENABLED(regs)) sastein_new = regs->CR_H(3); } else { /* Translate SASN and return condition code 2 if AFX- or ASX-translation exception condition */ if (ARCH_DEP(translate_asn) (sasn_d, regs, &sasteo, aste)) { regs->psw.cc = 2; return; } /* When ASN-and-LX-reuse is installed and enabled by CR0, condition code 2 is also set if the SASTEIN-d does not equal the ASTEIN in word 11 of the ASTE */ if (ASN_AND_LX_REUSE_ENABLED(regs) && sastein_d != aste[11]) { regs->psw.cc = 2; return; } /* end if(ASN_AND_LX_REUSE_ENABLED && sastein_d!=aste[11]) */ /* Obtain new SSTD or SASCE from secondary ASTE */ sstd = ASTE_AS_DESIGNATOR(aste); /* When ASN-and-LX-reuse is installed and enabled by CR0, set the new SASTEIN equal to the SASTEIN-d */ if (ASN_AND_LX_REUSE_ENABLED(regs)) sastein_new = sastein_d; #ifdef FEATURE_SUBSPACE_GROUP /* Perform subspace replacement on new SSTD */ sstd = ARCH_DEP(subspace_replace) (sstd, sasteo, &xcode, regs); /* Return condition code 2 if ASTE exception recognized */ if (xcode != 0) { regs->psw.cc = 2; return; } #endif /*FEATURE_SUBSPACE_GROUP*/ /* Perform SASN authorization if bit 31 of the LASP function bits is 0 */ if (!(effective_addr2 & 0x00000001)) { /* Condition code 2 if SASN authorization fails */ if (ARCH_DEP(authorize_asn) (ax, aste, ATE_SECONDARY, regs)) { regs->psw.cc = 2; return; } } /* end if(SASN authorization) */ } /* end if(SASN translation) */ } /* end if(SASN = PASN) */ /* Perform control-register loading */ regs->CR(1) = pstd; regs->CR_LHH(3) = pkm_d; regs->CR_LHL(3) = sasn_d; regs->CR_LHH(4) = ax; regs->CR_LHL(4) = pasn_d; regs->CR_L(5) = ASF_ENABLED(regs) ? pasteo : ltd; /* ZZZ2 NOT SURE ABOUT THE MEANING OF THIS CODE: REFER TO ZZZ1 */ regs->CR(7) = sstd; if (ASN_AND_LX_REUSE_ENABLED(regs)) { regs->CR_H(3) = sastein_new; regs->CR_H(4) = pastein_new; } /* end if(ASN_AND_LX_REUSE_ENABLED) */ SET_AEA_COMMON(regs); if (inst_cr != regs->CR(regs->aea_ar[USE_INST_SPACE])) INVALIDATE_AIA(regs); /* Return condition code zero */ regs->psw.cc = 0; } /* end DEF_INST(load_address_space_parameters) */ #endif /*defined(FEATURE_DUAL_ADDRESS_SPACE)*/ /*-------------------------------------------------------------------*/ /* B7 LCTL - Load Control [RS] */ /*-------------------------------------------------------------------*/ DEF_INST(load_control) { int r1, r3; /* Register numbers */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ int i, m, n; /* Integer work areas */ U32 *p1, *p2 = NULL; /* Mainstor pointers */ U16 updated = 0; /* Updated control regs */ RS(inst, regs, r1, r3, b2, effective_addr2); #if defined(FEATURE_ECPSVM) if(ecpsvm_dolctl(regs,r1,r3,b2,effective_addr2)==0) { return; } #endif PRIV_CHECK(regs); FW_CHECK(effective_addr2, regs); /* Calculate number of regs to load */ n = ((r3 - r1) & 0xF) + 1; ITIMER_SYNC(effective_addr2,(n*4)-1,regs); #if defined(_FEATURE_SIE) if (SIE_MODE(regs)) { U16 cr_mask = fetch_hw (regs->siebk->lctl_ctl); for (i = 0; i < n; i++) if (cr_mask & BIT(15 - ((r1 + i) & 0xF))) longjmp(regs->progjmp, SIE_INTERCEPT_INST); } #endif /*defined(_FEATURE_SIE)*/ /* Calculate number of words to next boundary */ m = (0x800 - (effective_addr2 & 0x7ff)) >> 2; /* Address of operand beginning */ p1 = (U32*)MADDR(effective_addr2, b2, regs, ACCTYPE_READ, regs->psw.pkey); /* Get address of next page if boundary crossed */ if (unlikely (m < n)) p2 = (U32*)MADDR(effective_addr2 + (m*4), b2, regs, ACCTYPE_READ, regs->psw.pkey); else m = n; /* Copy from operand beginning */ for (i = 0; i < m; i++, p1++) { regs->CR_L((r1 + i) & 0xF) = fetch_fw (p1); updated |= BIT((r1 + i) & 0xF); } /* Copy from next page */ for ( ; i < n; i++, p2++) { regs->CR_L((r1 + i) & 0xF) = fetch_fw (p2); updated |= BIT((r1 + i) & 0xF); } /* Actions based on updated control regs */ SET_IC_MASK(regs); #if __GEN_ARCH == 370 if (updated & BIT(1)) { SET_AEA_COMMON(regs); INVALIDATE_AIA(regs); } #else if (updated & (BIT(1) | BIT(7) | BIT(13))) SET_AEA_COMMON(regs); if (updated & BIT(regs->aea_ar[USE_INST_SPACE])) INVALIDATE_AIA(regs); #endif if (updated & BIT(9)) { OBTAIN_INTLOCK(regs); SET_IC_PER(regs); RELEASE_INTLOCK(regs); if (EN_IC_PER_SA(regs)) ARCH_DEP(invalidate_tlb)(regs,~(ACC_WRITE|ACC_CHECK)); } RETURN_INTCHECK(regs); } /* end DEF_INST(load_control) */ /*-------------------------------------------------------------------*/ /* 82 LPSW - Load Program Status Word [S] */ /*-------------------------------------------------------------------*/ DEF_INST(load_program_status_word) { int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ DBLWRD dword; int rc; #if defined(FEATURE_ESAME) int amode64; #endif /*defined(FEATURE_ESAME)*/ S(inst, regs, b2, effective_addr2); #if defined(FEATURE_ECPSVM) if(ecpsvm_dolpsw(regs,b2,effective_addr2)==0) { return; } #endif PRIV_CHECK(regs); DW_CHECK(effective_addr2, regs); #if defined(_FEATURE_SIE) if(SIE_STATB(regs, IC1, LPSW)) longjmp(regs->progjmp, SIE_INTERCEPT_INST); #endif /*defined(_FEATURE_SIE)*/ /* Perform serialization and checkpoint synchronization */ PERFORM_SERIALIZATION (regs); PERFORM_CHKPT_SYNC (regs); /* Fetch new PSW from operand address */ STORE_DW ( dword, ARCH_DEP(vfetch8) ( effective_addr2, b2, regs ) ); /* Set the breaking event address register */ SET_BEAR_REG(regs, regs->ip - 4); /* Load updated PSW (ESA/390 Format in ESAME mode) */ #if !defined(FEATURE_ESAME) if ((rc = ARCH_DEP(load_psw) ( regs, dword ))) ARCH_DEP(program_interrupt) (regs, rc); #else /*defined(FEATURE_ESAME)*/ /* Make the PSW valid for ESA/390 mode after first saving our amode64 flag */ amode64 = dword[3] & 0x01; dword[3] &= ~0x01; /* Now call 's390_load_psw' to load our ESA/390 PSW for us */ rc = s390_load_psw ( regs, dword ); /* PROGRAMMING NOTE: z/Arch (ESAME) only supports the loading of ESA/390 mode (Extended Control mode (i.e. EC mode)) PSWs via the LPSW instruction. Thus the above 's390_load_psw' call has already checked to make sure bit 12 -- the EC mode bit (otherwise also known as the 'NOTESAME' bit) -- was set when the PSW was loaded (otherwise it would not have even returned and instead would have thrown a PGM_SPECIFICATION_EXCEPTION). Since we're actually executing in z/Arch (ESAME) mode though we now need to turn that bit off (since it's not supposed to be on for z/Arch (ESAME) mode) as explained in the Principles of Operations manual for the LPSW instruction. */ regs->psw.states &= ~BIT(PSW_NOTESAME_BIT); /* Restore the amode64 flag setting and set the actual correct AMASK value according to it (if we need to) since we had to force non-amode64 further above to get the 's390_load_psw' function to work right without erroneously program-checking. */ if((regs->psw.amode64 = amode64)) { regs->psw.AMASK = AMASK64; /* amode31 bit must be set when amode64 is set */ if(!regs->psw.amode) { regs->psw.zeroilc = 1; ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION); } } else /* Clear the high word of the address mask since the 's390_load_psw' function didn't do that for us */ regs->psw.AMASK_H = 0; /* Check for Load PSW success/failure */ if (rc) ARCH_DEP(program_interrupt) (regs, rc); /* Clear the high word of the instruction address since the 's390_load_psw' function didn't do that for us */ regs->psw.IA_H = 0; #endif /*defined(FEATURE_ESAME)*/ /* Perform serialization and checkpoint synchronization */ PERFORM_SERIALIZATION (regs); PERFORM_CHKPT_SYNC (regs); RETURN_INTCHECK(regs); } /* end DEF_INST(load_program_status_word) */ /*-------------------------------------------------------------------*/ /* B1 LRA - Load Real Address [RX] */ /*-------------------------------------------------------------------*/ DEF_INST(load_real_address) { int r1; /* Register number */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ RX(inst, regs, r1, b2, effective_addr2); ARCH_DEP(load_real_address_proc) (regs, r1, b2, effective_addr2); } /* end DEF_INST(load_real_address) */ /*-------------------------------------------------------------------*/ /* Common processing routine for the LRA and LRAY instructions */ /*-------------------------------------------------------------------*/ void ARCH_DEP(load_real_address_proc) (REGS *regs, int r1, int b2, VADR effective_addr2) { int cc; /* Condition code */ SIE_XC_INTERCEPT(regs); PRIV_CHECK(regs); /* Translate the effective address to a real address */ cc = ARCH_DEP(translate_addr) (effective_addr2, b2, regs, ACCTYPE_LRA); /* If ALET exception or ASCE-type or region translation exception, set exception code in R1 bits 48-63, set bit 32 of R1, and set condition code 3 */ if (cc > 3) { regs->GR_L(r1) = 0x80000000 | regs->dat.xcode; cc = 3; } else { /* Set r1 and condition code as returned by translate_addr */ #if defined(FEATURE_ESAME) if (regs->psw.amode64 && cc != 3) { regs->GR_G(r1) = regs->dat.raddr; } else { if (regs->dat.raddr <= 0x7FFFFFFF) { regs->GR_L(r1) = regs->dat.raddr; } else { /* Special handling if in 24-bit or 31-bit mode and the returned address exceeds 2GB, or if cc=3 and the returned address exceeds 2GB */ if (cc == 0) { /* Real address exceeds 2GB */ ARCH_DEP(program_interrupt) (regs, PGM_SPECIAL_OPERATION_EXCEPTION); } /* Condition code is 1, 2, or 3, and the returned table entry address exceeds 2GB. Convert to condition code 3 and return the exception code which will be X'0010' or X'0011' */ regs->GR_L(r1) = 0x80000000 | regs->dat.xcode; cc = 3; } /* end else(regs->dat.raddr) */ } /* end else(amode) */ #else /*!defined(FEATURE_ESAME)*/ regs->GR_L(r1) = regs->dat.raddr; #endif /*!defined(FEATURE_ESAME)*/ } /* end else(cc) */ regs->psw.cc = cc; } /* end ARCH_DEP(load_real_address_proc) */ /*-------------------------------------------------------------------*/ /* B24B LURA - Load Using Real Address [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(load_using_real_address) { int r1, r2; /* Values of R fields */ RADR n; /* Unsigned work */ RRE(inst, regs, r1, r2); PRIV_CHECK(regs); /* R2 register contains operand real storage address */ n = regs->GR(r2) & ADDRESS_MAXWRAP(regs); /* Program check if operand not on fullword boundary */ FW_CHECK(n, regs); /* Load R1 register from second operand */ regs->GR_L(r1) = ARCH_DEP(vfetch4) ( n, USE_REAL_ADDR, regs ); } #if defined(FEATURE_LOCK_PAGE) /*-------------------------------------------------------------------*/ /* B262 LKPG - Lock Page [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(lock_page) { int r1, r2; /* Values of R fields */ VADR n2; /* effective addr of r2 */ RADR rpte; /* PTE real address */ CREG pte; /* Page Table Entry */ RRE(inst, regs, r1, r2); PRIV_CHECK(regs); if(REAL_MODE(&(regs->psw))) ARCH_DEP(program_interrupt) (regs, PGM_SPECIAL_OPERATION_EXCEPTION); if(regs->GR_L(0) & LKPG_GPR0_RESV) ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION); n2 = regs->GR(r2) & ADDRESS_MAXWRAP(regs); /* Access to PTE must be serialized */ OBTAIN_MAINLOCK(regs); /* Return condition code 3 if translation exception */ if (ARCH_DEP(translate_addr) (n2, r2, regs, ACCTYPE_PTE) == 0) { rpte = APPLY_PREFIXING (regs->dat.raddr, regs->PX); pte = #if defined(FEATURE_ESAME) ARCH_DEP(fetch_doubleword_absolute) (rpte, regs); #else /*!defined(FEATURE_ESAME)*/ ARCH_DEP(fetch_fullword_absolute) (rpte, regs); #endif /*!defined(FEATURE_ESAME)*/ if(regs->GR_L(0) & LKPG_GPR0_LOCKBIT) { /* Lock request */ if(!(pte & PAGETAB_PGLOCK)) { /* Return condition code 3 if translation exception */ if(ARCH_DEP(translate_addr) (n2, r2, regs, ACCTYPE_LRA)) { regs->psw.cc = 3; RELEASE_MAINLOCK(regs); return; } pte |= PAGETAB_PGLOCK; #if defined(FEATURE_ESAME) ARCH_DEP(store_doubleword_absolute) (pte, rpte, regs); #else /*!defined(FEATURE_ESAME)*/ ARCH_DEP(store_fullword_absolute) (pte, rpte, regs); #endif /*!defined(FEATURE_ESAME)*/ regs->GR(r1) = regs->dat.raddr; regs->psw.cc = 0; } else regs->psw.cc = 1; } else { /* Unlock reguest */ if(pte & PAGETAB_PGLOCK) { pte &= ~((U64)PAGETAB_PGLOCK); #if defined(FEATURE_ESAME) ARCH_DEP(store_doubleword_absolute) (pte, rpte, regs); #else /*!defined(FEATURE_ESAME)*/ ARCH_DEP(store_fullword_absolute) (pte, rpte, regs); #endif /*!defined(FEATURE_ESAME)*/ regs->psw.cc = 0; } else regs->psw.cc = 1; } } else regs->psw.cc = 3; RELEASE_MAINLOCK(regs); } /* end DEF_INST(lock_page) */ #endif /*defined(FEATURE_LOCK_PAGE)*/ #if defined(FEATURE_LINKAGE_STACK) /*-------------------------------------------------------------------*/ /* B247 MSTA - Modify Stacked State [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(modify_stacked_state) { int r1, unused; /* Values of R fields */ U32 m1, m2; /* Modify values */ LSED lsed; /* Linkage stack entry desc. */ VADR lsea; /* Linkage stack entry addr */ RRE(inst, regs, r1, unused); SIE_XC_INTERCEPT(regs); if (REAL_MODE(®s->psw) || SECONDARY_SPACE_MODE(®s->psw) || !ASF_ENABLED(regs)) ARCH_DEP(program_interrupt) (regs, PGM_SPECIAL_OPERATION_EXCEPTION); ODD_CHECK(r1, regs); /* Find the virtual address of the entry descriptor of the current state entry in the linkage stack */ lsea = ARCH_DEP(locate_stack_entry) (0, &lsed, regs); /* Load values from rightmost 32 bits of R1 and R1+1 registers */ m1 = regs->GR_L(r1); m2 = regs->GR_L(r1+1); /* Store two 32-bit values into modifiable area of state entry */ ARCH_DEP(stack_modify) (lsea, m1, m2, regs); } #endif /*defined(FEATURE_LINKAGE_STACK)*/ #if defined(FEATURE_DUAL_ADDRESS_SPACE) /*-------------------------------------------------------------------*/ /* DA MVCP - Move to Primary [SS] */ /*-------------------------------------------------------------------*/ DEF_INST(move_to_primary) { int r1, r3; /* Register numbers */ int b1, b2; /* Values of base registers */ VADR effective_addr1, effective_addr2; /* Effective addresses */ int cc; /* Condition code */ int k; /* Integer workarea */ GREG l; /* Unsigned workarea */ SS(inst, regs, r1, r3, b1, effective_addr1, b2, effective_addr2); SIE_XC_INTERCEPT(regs); /* Program check if secondary space control (CR0 bit 5) is 0, or if DAT is off, or if in AR mode or home-space mode */ if ((regs->CR(0) & CR0_SEC_SPACE) == 0 || REAL_MODE(®s->psw) || AR_BIT(®s->psw)) ARCH_DEP(program_interrupt) (regs, PGM_SPECIAL_OPERATION_EXCEPTION); /* Load true length from R1 register */ l = GR_A(r1,regs); /* If the true length does not exceed 256, set condition code zero, otherwise set cc=3 and use effective length of 256 */ if (l <= 256) cc = 0; else { cc = 3; l = 256; } /* Load secondary space key from R3 register bits 24-27 */ k = regs->GR_L(r3) & 0xF0; /* Program check if in problem state and key mask in CR3 bits 0-15 is not 1 for the specified key */ if ( PROBSTATE(®s->psw) && ((regs->CR(3) << (k >> 4)) & 0x80000000) == 0 ) ARCH_DEP(program_interrupt) (regs, PGM_PRIVILEGED_OPERATION_EXCEPTION); /* Move characters from secondary address space to primary address space using secondary key for second operand */ if (l > 0) ARCH_DEP(move_chars) (effective_addr1, USE_PRIMARY_SPACE, regs->psw.pkey, effective_addr2, USE_SECONDARY_SPACE, k, l-1, regs); /* Set condition code */ regs->psw.cc = cc; } #endif /*defined(FEATURE_DUAL_ADDRESS_SPACE)*/ #if defined(FEATURE_DUAL_ADDRESS_SPACE) /*-------------------------------------------------------------------*/ /* DB MVCS - Move to Secondary [SS] */ /*-------------------------------------------------------------------*/ DEF_INST(move_to_secondary) { int r1, r3; /* Register numbers */ int b1, b2; /* Values of base registers */ VADR effective_addr1, effective_addr2; /* Effective addresses */ int cc; /* Condition code */ int k; /* Integer workarea */ GREG l; /* Unsigned workarea */ SS(inst, regs, r1, r3, b1, effective_addr1, b2, effective_addr2); SIE_XC_INTERCEPT(regs); /* Program check if secondary space control (CR0 bit 5) is 0, or if DAT is off, or if in AR mode or home-space mode */ if ((regs->CR(0) & CR0_SEC_SPACE) == 0 || REAL_MODE(®s->psw) || AR_BIT(®s->psw)) ARCH_DEP(program_interrupt) (regs, PGM_SPECIAL_OPERATION_EXCEPTION); /* Load true length from R1 register */ l = GR_A(r1,regs); /* If the true length does not exceed 256, set condition code zero, otherwise set cc=3 and use effective length of 256 */ if (l <= 256) cc = 0; else { cc = 3; l = 256; } /* Load secondary space key from R3 register bits 24-27 */ k = regs->GR_L(r3) & 0xF0; /* Program check if in problem state and key mask in CR3 bits 0-15 is not 1 for the specified key */ if ( PROBSTATE(®s->psw) && ((regs->CR(3) << (k >> 4)) & 0x80000000) == 0 ) ARCH_DEP(program_interrupt) (regs, PGM_PRIVILEGED_OPERATION_EXCEPTION); /* Move characters from primary address space to secondary address space using secondary key for first operand */ if (l > 0) ARCH_DEP(move_chars) (effective_addr1, USE_SECONDARY_SPACE, k, effective_addr2, USE_PRIMARY_SPACE, regs->psw.pkey, l-1, regs); /* Set condition code */ regs->psw.cc = cc; } #endif /*defined(FEATURE_DUAL_ADDRESS_SPACE)*/ /*-------------------------------------------------------------------*/ /* E50F MVCDK - Move with Destination Key [SSE] */ /*-------------------------------------------------------------------*/ DEF_INST(move_with_destination_key) { int b1, b2; /* Values of base registers */ VADR effective_addr1, effective_addr2; /* Effective addresses */ int k, l; /* Integer workarea */ SSE(inst, regs, b1, effective_addr1, b2, effective_addr2); /* Load operand length-1 from register 0 bits 24-31 */ l = regs->GR_L(0) & 0xFF; /* Load destination key from register 1 bits 24-27 */ k = regs->GR_L(1) & 0xF0; /* Program check if in problem state and key mask in CR3 bits 0-15 is not 1 for the specified key */ if ( PROBSTATE(®s->psw) && ((regs->CR(3) << (k >> 4)) & 0x80000000) == 0 ) ARCH_DEP(program_interrupt) (regs, PGM_PRIVILEGED_OPERATION_EXCEPTION); /* Move characters using destination key for operand 1 */ ARCH_DEP(move_chars) (effective_addr1, b1, k, effective_addr2, b2, regs->psw.pkey, l, regs); } #if defined(FEATURE_DUAL_ADDRESS_SPACE) /*-------------------------------------------------------------------*/ /* D9 MVCK - Move with Key [SS] */ /*-------------------------------------------------------------------*/ DEF_INST(move_with_key) { int r1, r3; /* Register numbers */ int b1, b2; /* Values of base registers */ VADR effective_addr1, effective_addr2; /* Effective addresses */ int cc; /* Condition code */ int k; /* Integer workarea */ GREG l; /* Unsigned workarea */ SS(inst, regs, r1, r3, b1, effective_addr1, b2, effective_addr2); /* Load true length from R1 register */ l = GR_A(r1,regs); /* If the true length does not exceed 256, set condition code zero, otherwise set cc=3 and use effective length of 256 */ if (l <= 256) cc = 0; else { cc = 3; l = 256; } /* Load source key from R3 register bits 24-27 */ k = regs->GR_L(r3) & 0xF0; /* Program check if in problem state and key mask in CR3 bits 0-15 is not 1 for the specified key */ if ( PROBSTATE(®s->psw) && ((regs->CR(3) << (k >> 4)) & 0x80000000) == 0 ) ARCH_DEP(program_interrupt) (regs, PGM_PRIVILEGED_OPERATION_EXCEPTION); /* Move characters using source key for second operand */ if (l > 0) ARCH_DEP(move_chars) (effective_addr1, b1, regs->psw.pkey, effective_addr2, b2, k, l-1, regs); /* Set condition code */ regs->psw.cc = cc; } #endif /*defined(FEATURE_DUAL_ADDRESS_SPACE)*/ #if defined(FEATURE_MOVE_WITH_OPTIONAL_SPECIFICATIONS) /*-------------------------------------------------------------------*/ /* C8x0 MVCOS - Move with Optional Specifications [SSF] */ /*-------------------------------------------------------------------*/ DEF_INST(move_with_optional_specifications) { int r3; /* Register number */ int b1, b2; /* Base register numbers */ VADR effective_addr1, effective_addr2; /* Effective addresses */ int kbit1, kbit2, abit1, abit2; /* Key and AS validity bits */ int key1, key2; /* Access keys in bits 0-3 */ int asc1, asc2; /* AS controls (same as PSW) */ int cc; /* Condition code */ GREG len; /* Effective length */ int space1, space2; /* Address space modifiers */ SSF(inst, regs, b1, effective_addr1, b2, effective_addr2, r3); SIE_XC_INTERCEPT(regs); /* Program check if DAT is off */ if (REAL_MODE(®s->psw)) ARCH_DEP(program_interrupt) (regs, PGM_SPECIAL_OPERATION_EXCEPTION); /* Extract the access key and address-space control for operand 1 */ abit1 = regs->GR_LHH(0) & 0x0001; kbit1 = (regs->GR_LHH(0) & 0x0002) >> 1; asc1 = regs->GR_LHH(0) & 0x00C0; key1 = (regs->GR_LHH(0) & 0xF000) >> 8; /* Extract the access key and address-space control for operand 2 */ abit2 = regs->GR_LHL(0) & 0x0001; kbit2 = (regs->GR_LHL(0) & 0x0002) >> 1; asc2 = regs->GR_LHL(0) & 0x00C0; key2 = (regs->GR_LHL(0) & 0xF000) >> 8; /* Use PSW address-space control for operand 1 if A bit is zero */ if (abit1 == 0) asc1 = regs->psw.asc; /* Use PSW address-space control for operand 2 if A bit is zero */ if (abit2 == 0) asc2 = regs->psw.asc; /* Use PSW key for operand 1 if K bit is zero */ if (kbit1 == 0) key1 = regs->psw.pkey; /* Use PSW key for operand 2 if K bit is zero */ if (kbit2 == 0) key2 = regs->psw.pkey; /* Program check if home-space mode is specified for operand 1 and PSW indicates problem state */ if (abit1 && asc1 == PSW_HOME_SPACE_MODE && PROBSTATE(®s->psw)) ARCH_DEP(program_interrupt) (regs, PGM_SPECIAL_OPERATION_EXCEPTION); /* Program check if secondary space control (CR0 bit 5/37) is 0, and secondary space mode is specified or implied for either operand */ if ((regs->CR(0) & CR0_SEC_SPACE) == 0 && (asc1 == PSW_SECONDARY_SPACE_MODE || asc2 == PSW_SECONDARY_SPACE_MODE)) ARCH_DEP(program_interrupt) (regs, PGM_SPECIAL_OPERATION_EXCEPTION); /* Program check if in problem state and the key mask in CR3 is zero for the specified or implied access key for either operand */ if (PROBSTATE(®s->psw) && ( ((regs->CR(3) << (key1 >> 4)) & 0x80000000) == 0 || ((regs->CR(3) << (key2 >> 4)) & 0x80000000) == 0 )) ARCH_DEP(program_interrupt) (regs, PGM_PRIVILEGED_OPERATION_EXCEPTION); /* Load true length from R3 register */ len = GR_A(r3,regs); /* If the true length does not exceed 4096, set condition code zero, otherwise set cc=3 and use effective length of 4096 */ if (len <= 4096) cc = 0; else { cc = 3; len = 4096; } /* Set the address space modifier for operand 1 */ space1 = (asc1 == PSW_PRIMARY_SPACE_MODE) ? USE_PRIMARY_SPACE : (asc1 == PSW_SECONDARY_SPACE_MODE) ? USE_SECONDARY_SPACE : (asc1 == PSW_ACCESS_REGISTER_MODE) ? USE_ARMODE | b1 : (asc1 == PSW_HOME_SPACE_MODE) ? USE_HOME_SPACE : 0; /* Set the address space modifier for operand 2 */ space2 = (asc2 == PSW_PRIMARY_SPACE_MODE) ? USE_PRIMARY_SPACE : (asc2 == PSW_SECONDARY_SPACE_MODE) ? USE_SECONDARY_SPACE : (asc2 == PSW_ACCESS_REGISTER_MODE) ? USE_ARMODE | b2 : (asc2 == PSW_HOME_SPACE_MODE) ? USE_HOME_SPACE : 0; /* Perform the move */ ARCH_DEP(move_charx) (effective_addr1, space1, key1, effective_addr2, space2, key2, len, regs); /* Set the condition code */ regs->psw.cc = cc; } /* end DEF_INST(move_with_optional_specifications) */ #endif /*defined(FEATURE_MOVE_WITH_OPTIONAL_SPECIFICATIONS)*/ /*-------------------------------------------------------------------*/ /* E50E MVCSK - Move with Source Key [SSE] */ /*-------------------------------------------------------------------*/ DEF_INST(move_with_source_key) { int b1, b2; /* Values of base registers */ VADR effective_addr1, effective_addr2; /* Effective addresses */ int k, l; /* Integer workarea */ SSE(inst, regs, b1, effective_addr1, b2, effective_addr2); /* Load operand length-1 from register 0 bits 24-31 */ l = regs->GR_L(0) & 0xFF; /* Load source key from register 1 bits 24-27 */ k = regs->GR_L(1) & 0xF0; /* Program check if in problem state and key mask in CR3 bits 0-15 is not 1 for the specified key */ if ( PROBSTATE(®s->psw) && ((regs->CR(3) << (k >> 4)) & 0x80000000) == 0 ) ARCH_DEP(program_interrupt) (regs, PGM_PRIVILEGED_OPERATION_EXCEPTION); /* Move characters using source key for second operand */ ARCH_DEP(move_chars) (effective_addr1, b1, regs->psw.pkey, effective_addr2, b2, k, l, regs); } #if defined(FEATURE_DUAL_ADDRESS_SPACE) /*-------------------------------------------------------------------*/ /* B218 PC - Program Call [S] */ /*-------------------------------------------------------------------*/ DEF_INST(program_call) { int b2; /* Base of effective addr */ U32 pcnum; /* Program call number */ U32 pctea; /* TEA in case of program chk*/ VADR effective_addr2; /* Effective address */ RADR abs; /* Absolute address */ BYTE *mn; /* Mainstor address */ RADR pstd; /* Primary STD or ASCE */ U32 oldpstd; /* Old Primary STD or ASCE */ U32 ltdesig; /* Linkage table designation (LTD or LFTD) */ U32 pasteo=0; /* Primary ASTE origin */ RADR lto; /* Linkage table origin */ U32 ltl; /* Linkage table length */ U32 lte; /* Linkage table entry */ RADR lfto; /* Linkage first table origin*/ U32 lftl; /* Linkage first table length*/ U32 lfte; /* Linkage first table entry */ RADR lsto; /* Linkage second table orig */ U32 lste[2]; /* Linkage second table entry*/ RADR eto; /* Entry table origin */ U32 etl; /* Entry table length */ U32 ete[8]; /* Entry table entry */ int numwords; /* ETE size (4 or 8 words) */ int i; /* Array subscript */ int ssevent = 0; /* 1=space switch event */ U32 aste[16]; /* ASN second table entry */ U32 akm; /* Bits 0-15=AKM, 16-31=zero */ U16 xcode; /* Exception code */ U16 pasn; /* Primary ASN */ U16 oldpasn; /* Old Primary ASN */ #if defined(FEATURE_LINKAGE_STACK) U32 csi; /* Called-space identifier */ VADR retn; /* Return address and amode */ #endif /*defined(FEATURE_LINKAGE_STACK)*/ #ifdef FEATURE_TRACING CREG newcr12 = 0; /* CR12 upon completion */ #endif /*FEATURE_TRACING*/ #if defined(FEATURE_ESAME) CREG savecr12 = 0; /* CR12 save */ #endif /*FEATURE_ESAME*/ S(inst, regs, b2, effective_addr2); SIE_XC_INTERCEPT(regs); #if defined(_FEATURE_SIE) if(SIE_STATB(regs, IC2, PC)) longjmp(regs->progjmp, SIE_INTERCEPT_INST); #endif /*defined(_FEATURE_SIE)*/ /* Perform serialization and checkpoint-synchronization */ PERFORM_SERIALIZATION (regs); PERFORM_CHKPT_SYNC (regs); /* Load the PC number from the operand address */ if (!ASN_AND_LX_REUSE_ENABLED(regs)) { /* When ASN-and-LX-reuse is not installed or not enabled, the PC number is the low-order 20 bits of the operand address and the translation exception identification is the 20-bit PC number with 12 high order zeroes appended to the left */ pcnum = effective_addr2 & (PC_LX | PC_EX); pctea = pcnum; } else /* ASN_AND_LX_REUSE_ENABLED */ { /* When ASN-and-LX-reuse is installed and enabled by CR0, the PC number is loaded from the low-order 20 bits of the operand address (bits 44-63) if bit 44 is zero, otherwise a 31-bit PC number is constructed using bits 32-43 (LFX1) of the operand address concatenated with bits 45-63 (LFX2, LSX,EX) of the operand address. The translation exception identification is either the 20 bit PC number with 12 high order zeroes, or, if bit 44 is one, is the entire 32 bits of the effective address including the 1 in bit 44 */ if ((effective_addr2 & PC_BIT44) == 0) { pcnum = effective_addr2 & (PC_LFX2 | PC_LSX | PC_EX); pctea = pcnum; } else { pcnum = ((effective_addr2 & PC_LFX1) >> 1) | (effective_addr2 & (PC_LFX2 | PC_LSX | PC_EX)); pctea = effective_addr2 & 0xFFFFFFFF; } } /* end ASN_AND_LX_REUSE_ENABLED */ /* Special operation exception if DAT is off, or if in secondary space mode or home space mode */ if (REAL_MODE(&(regs->psw)) || SPACE_BIT(®s->psw)) ARCH_DEP(program_interrupt) (regs, PGM_SPECIAL_OPERATION_EXCEPTION); /* Save CR4 and CR1 in case of space switch */ oldpasn = regs->CR(4) & CR4_PASN; oldpstd = regs->CR(1); /* [5.5.3.1] Load the linkage table designation */ if (!ASF_ENABLED(regs)) { /* Special operation exception if in AR mode */ if (ACCESS_REGISTER_MODE(&(regs->psw))) ARCH_DEP(program_interrupt) (regs, PGM_SPECIAL_OPERATION_EXCEPTION); /* Obtain the LTD from control register 5 */ ltdesig = regs->CR_L(5); } else { /* Obtain the primary ASTE origin from control register 5 */ pasteo = regs->CR_L(5) & CR5_PASTEO; /* Convert the PASTE origin to an absolute address */ abs = APPLY_PREFIXING (pasteo, regs->PX); /* Program check if PASTE is outside main storage */ if (abs > regs->mainlim) ARCH_DEP(program_interrupt) (regs, PGM_ADDRESSING_EXCEPTION); /* Fetch primary ASTE words 3 or 6 from absolute storage (note: the ASTE cannot cross a page boundary) */ #if !defined(FEATURE_ESAME) aste[3] = ARCH_DEP(fetch_fullword_absolute) (abs+12, regs); #else /*defined(FEATURE_ESAME)*/ aste[6] = ARCH_DEP(fetch_fullword_absolute) (abs+24, regs); #endif /*defined(FEATURE_ESAME)*/ /* Load LTD or LFTD from primary ASTE word 3 or 6 */ ltdesig = ASTE_LT_DESIGNATOR(aste); } /* Note: When ASN-and-LX-reuse is installed and enabled by CR0, ltdesig is an LFTD, otherwise it is an LTD */ /* Special operation exception if subsystem linkage control bit in linkage table designation is zero */ if ((ltdesig & LTD_SSLINK) == 0) ARCH_DEP(program_interrupt) (regs, PGM_SPECIAL_OPERATION_EXCEPTION); #ifdef FEATURE_TRACING /* Form trace entry if ASN tracing is active */ if (regs->CR(12) & CR12_ASNTRACE) newcr12 = ARCH_DEP(trace_pc) (pctea, regs); #endif /*FEATURE_TRACING*/ /* [5.5.3.2] Linkage table lookup */ if (!ASN_AND_LX_REUSE_ENABLED(regs)) { /* Extract the linkage table origin and length from the LTD */ lto = ltdesig & LTD_LTO; ltl = ltdesig & LTD_LTL; /* Program check if linkage index outside the linkage table */ if (ltl < ((pcnum & PC_LX) >> 13)) { regs->TEA = pctea; ARCH_DEP(program_interrupt) (regs, PGM_LX_TRANSLATION_EXCEPTION); } /* Calculate the address of the linkage table entry */ lto += (pcnum & PC_LX) >> 6; lto &= 0x7FFFFFFF; /* Program check if linkage table entry outside real storage */ if (lto > regs->mainlim) ARCH_DEP(program_interrupt) (regs, PGM_ADDRESSING_EXCEPTION); /* Fetch linkage table entry from real storage. All bytes must be fetched concurrently as observed by other CPUs */ lto = APPLY_PREFIXING (lto, regs->PX); lte = ARCH_DEP(fetch_fullword_absolute)(lto, regs); /* Program check if the LX invalid bit is set */ if (lte & LTE_INVALID) { regs->TEA = pctea; ARCH_DEP(program_interrupt) (regs, PGM_LX_TRANSLATION_EXCEPTION); } /* Extract the entry table origin and length from the LTE */ eto = lte & LTE_ETO; etl = lte & LTE_ETL; } else /* ASN_AND_LX_REUSE_ENABLED */ { /* Extract linkage first table origin and length from LFTD */ lfto = ltdesig & LFTD_LFTO; lftl = ltdesig & LFTD_LFTL; /* If the linkage first index exceeds the length of the linkage first table, then generate a program check. The index exceeds the table length if the LFX1 (which is now in bits 1-12 of the 32-bit PC number) exceeds the LFTL. Since the LFTL is only 8 bits, this also implies that the first 4 bits of the LFX1 (originally bits 32-35 of the operand address) must always be 0. The LFX1 was loaded from bits 32-43 of the operand address if bit 44 of the operand address was 1, otherwise LFX1 is zero. However, when bit 44 of the effective address is zero, the LFTL (Linkage-First-Table Length) is ignored. */ if ((effective_addr2 & PC_BIT44) && lftl < (pcnum >> 19)) { regs->TEA = pctea; ARCH_DEP(program_interrupt) (regs, PGM_LFX_TRANSLATION_EXCEPTION); } /* Calculate the address of the linkage first table entry (it is always a 31-bit address even in ESAME) */ lfto += (pcnum & ((PC_LFX1>>1)|PC_LFX2)) >> (13-2); lfto &= 0x7FFFFFFF; /* Program check if the LFTE address is outside real storage */ if (lfto > regs->mainlim) ARCH_DEP(program_interrupt) (regs, PGM_ADDRESSING_EXCEPTION); /* Fetch linkage first table entry from real storage. All bytes must be fetched concurrently as observed by other CPUs */ lfto = APPLY_PREFIXING (lfto, regs->PX); lfte = ARCH_DEP(fetch_fullword_absolute)(lfto, regs); /* Program check if the LFX invalid bit is set */ if (lfte & LFTE_INVALID) { regs->TEA = pctea; ARCH_DEP(program_interrupt) (regs, PGM_LFX_TRANSLATION_EXCEPTION); } /* Extract the linkage second table origin from the LFTE */ lsto = lfte & LFTE_LSTO; /* Calculate the address of the linkage second table entry (it is always a 31-bit address even in ESAME) */ lsto += (pcnum & PC_LSX) >> (8-3); lsto &= 0x7FFFFFFF; /* Program check if the LSTE address is outside real storage */ if (lsto > regs->mainlim) ARCH_DEP(program_interrupt) (regs, PGM_ADDRESSING_EXCEPTION); /* Fetch the linkage second table entry from real storage. The LSTE is 2 fullwords and cannot cross a page boundary. All 8 bytes of the LSTE must be fetched concurrently as observed by other CPUs */ abs = APPLY_PREFIXING (lsto, regs->PX); mn = FETCH_MAIN_ABSOLUTE (abs, regs, 2 * 4); lste[0] = fetch_fw (mn); lste[1] = fetch_fw (mn + 4); /* Program check if the LSX invalid bit is set */ if (lste[0] & LSTE0_INVALID) { regs->TEA = pctea; ARCH_DEP(program_interrupt) (regs, PGM_LSX_TRANSLATION_EXCEPTION); } /* Program check if the LSTESN in word 1 of the LSTE is non-zero and not equal to bits 0-31 of register 15 */ if (lste[1] != 0 && regs->GR_H(15) != lste[1]) { regs->TEA = pctea; ARCH_DEP(program_interrupt) (regs, PGM_LSTE_SEQUENCE_EXCEPTION); } /* Extract the entry table origin and length from the LSTE */ eto = lste[0] & LSTE0_ETO; etl = lste[0] & LSTE0_ETL; } /* end ASN_AND_LX_REUSE_ENABLED */ /* [5.5.3.3] Entry table lookup */ /* Program check if entry index is outside the entry table */ if (etl < ((pcnum & PC_EX) >> (8-6))) { regs->TEA = pctea; ARCH_DEP(program_interrupt) (regs, PGM_EX_TRANSLATION_EXCEPTION); } /* Calculate the starting address of the entry table entry (it is always a 31-bit address even in ESAME) */ eto += (pcnum & PC_EX) << (ASF_ENABLED(regs) ? 5 : 4); eto &= 0x7FFFFFFF; /* Determine the size of the entry table entry */ numwords = ASF_ENABLED(regs) ? 8 : 4; /* Program check if entry table entry is outside main storage */ abs = APPLY_PREFIXING (eto, regs->PX); if (abs > regs->mainlim - (numwords * 4)) ARCH_DEP(program_interrupt) (regs, PGM_ADDRESSING_EXCEPTION); /* Fetch the 4- or 8-word entry table entry from real storage. Each fullword of the ETE must be fetched concurrently as observed by other CPUs. The entry table entry cannot cross a page boundary. */ mn = FETCH_MAIN_ABSOLUTE (abs, regs, numwords * 4); for (i = 0; i < numwords; i++) { ete[i] = fetch_fw (mn); mn += 4; } /* Clear remaining words if fewer than 8 words were loaded */ while (i < 8) ete[i++] = 0; /* Program check if basic program call in AR mode */ if ((ete[4] & ETE4_T) == 0 && AR_BIT(®s->psw)) ARCH_DEP(program_interrupt) (regs, PGM_SPECIAL_OPERATION_EXCEPTION); #if defined(FEATURE_ESAME) /* Program check if basic program call is attempting to switch into or out of 64-bit addressing mode */ if ((ete[4] & ETE4_T) == 0 && ((ete[4] & ETE4_G) ? 1 : 0) != regs->psw.amode64) ARCH_DEP(program_interrupt) (regs, PGM_SPECIAL_OPERATION_EXCEPTION); #endif /*defined(FEATURE_ESAME)*/ /* Program check if resulting addressing mode is 24 and the entry instruction address is not a 24-bit address */ if ((ete[1] & ETE1_AMODE) == 0 #if defined(FEATURE_ESAME) && (ete[4] & ETE4_G) == 0 #endif /*defined(FEATURE_ESAME)*/ && (ete[1] & ETE1_EIA) > 0x00FFFFFF) ARCH_DEP(program_interrupt) (regs, PGM_PC_TRANSLATION_SPECIFICATION_EXCEPTION); /* Obtain the authorization key mask from the entry table */ #if defined(FEATURE_ESAME) akm = ete[2] & ETE2_AKM; #else /*!defined(FEATURE_ESAME)*/ akm = ete[0] & ETE0_AKM; #endif /*!defined(FEATURE_ESAME)*/ /* Program check if in problem state and the PKM in control register 3 produces zero when ANDed with the AKM in the ETE */ if (PROBSTATE(®s->psw) && ((regs->CR(3) & CR3_KEYMASK) & akm) == 0) ARCH_DEP(program_interrupt) (regs, PGM_PRIVILEGED_OPERATION_EXCEPTION); /* Obtain the new primary ASN from the entry table */ #if defined(FEATURE_ESAME) pasn = ete[2] & ETE2_ASN; #else /*!defined(FEATURE_ESAME)*/ pasn = ete[0] & ETE0_ASN; #endif /*!defined(FEATURE_ESAME)*/ /* Obtain the ASTE if ASN is non-zero */ if (pasn != 0) { /* Program check if ASN translation control is zero */ if ((regs->CR(14) & CR14_ASN_TRAN) == 0) ARCH_DEP(program_interrupt) (regs, PGM_SPECIAL_OPERATION_EXCEPTION); /* For ESA/390 when ASF control is not enabled, the ASTE is obtained by ASN translation. For ESAME, and for ESA/390 when ASF control is enabled, the ASTE is loaded using the ASTE real address from the entry table */ if (!ASF_ENABLED(regs)) { /* Perform ASN translation to obtain ASTE */ xcode = ARCH_DEP(translate_asn) (pasn, regs, &pasteo, aste); /* Program check if ASN translation exception */ if (xcode != 0) ARCH_DEP(program_interrupt) (regs, xcode); } else { /* Load the ASTE origin from the entry table */ pasteo = ete[5] & ETE5_ASTE; /* Convert the ASTE origin to an absolute address */ abs = APPLY_PREFIXING (pasteo, regs->PX); /* Program check if ASTE origin address is invalid */ if (abs > regs->mainlim) ARCH_DEP(program_interrupt) (regs, PGM_ADDRESSING_EXCEPTION); /* Fetch the 16-word ASTE from absolute storage (note: the ASTE cannot cross a page boundary) */ mn = FETCH_MAIN_ABSOLUTE (abs, regs, 64); for (i = 0; i < 16; i++) { aste[i] = fetch_fw (mn); mn += 4; } /* ASX translation exception if ASTE invalid bit is one */ if (aste[0] & ASTE0_INVALID) { regs->TEA = pasn; ARCH_DEP(program_interrupt) (regs, PGM_ASX_TRANSLATION_EXCEPTION); } } /* Obtain the new PSTD or PASCE from the ASTE */ pstd = ASTE_AS_DESIGNATOR(aste); #ifdef FEATURE_SUBSPACE_GROUP /* Perform subspace replacement on new PSTD */ pstd = ARCH_DEP(subspace_replace) (pstd, pasteo, NULL, regs); #endif /*FEATURE_SUBSPACE_GROUP*/ } /* end if(PC-ss) */ else { /* PC-cp */ /* For PC to current primary, load current primary STD */ pstd = regs->CR(1); } /* end if(PC-cp) */ /* Perform basic or stacking program call */ if ((ete[4] & ETE4_T) == 0) { /* For basic PC, load linkage info into general register 14 */ #if defined(FEATURE_ESAME) if (regs->psw.amode64) regs->GR_G(14) = PSW_IA(regs, 0) | PROBSTATE(®s->psw); else regs->GR_L(14) = (regs->psw.amode ? 0x80000000 : 0) | PSW_IA(regs, 0) | PROBSTATE(®s->psw); #else /*!defined(FEATURE_ESAME)*/ regs->GR_L(14) = (regs->psw.amode ? 0x80000000 : 0) | PSW_IA(regs, 0) | PROBSTATE(®s->psw); #endif /*!defined(FEATURE_ESAME)*/ /* Set the breaking event address register */ SET_BEAR_REG(regs, regs->ip - 4); /* Update the PSW from the entry table */ #if defined(FEATURE_ESAME) if (regs->psw.amode64) UPD_PSW_IA(regs , ((U64)(ete[0]) << 32) | (U64)(ete[1] & 0xFFFFFFFE)); else { regs->psw.amode = (ete[1] & ETE1_AMODE) ? 1 : 0; regs->psw.AMASK = regs->psw.amode ? AMASK31 : AMASK24; UPD_PSW_IA(regs, ete[1] & ETE1_EIA); } #else /*!defined(FEATURE_ESAME)*/ regs->psw.amode = (ete[1] & ETE1_AMODE) ? 1 : 0; regs->psw.AMASK = regs->psw.amode ? AMASK31 : AMASK24; UPD_PSW_IA(regs, ete[1] & ETE1_EIA); #endif /*!defined(FEATURE_ESAME)*/ if (ete[1] & ETE1_PROB) regs->psw.states |= BIT(PSW_PROB_BIT); else regs->psw.states &= ~BIT(PSW_PROB_BIT); /* Load the current PKM and PASN into general register 3 */ regs->GR_L(3) = (regs->CR(3) & CR3_KEYMASK) | (regs->CR(4) & CR4_PASN); /* OR the EKM into the current PKM */ regs->CR(3) |= (ete[3] & ETE3_EKM); /* Load the entry parameter into general register 4 */ #if defined(FEATURE_ESAME) if (regs->psw.amode64) regs->GR_H(4) = ete[6]; regs->GR_L(4) = ete[7]; #else /*!defined(FEATURE_ESAME)*/ regs->GR_L(4) = ete[2]; #endif /*!defined(FEATURE_ESAME)*/ } /* end if(basic PC) */ else #if defined(FEATURE_LINKAGE_STACK) { /* stacking PC */ /* ESA/390 POP Fig 10-17 8.B.11 */ if (!ASF_ENABLED(regs)) ARCH_DEP(program_interrupt) (regs, PGM_SPECIAL_OPERATION_EXCEPTION); #ifdef FEATURE_TRACING #if defined(FEATURE_ESAME) /* Add a mode trace entry when switching in/out of 64 bit mode */ if((regs->CR(12) & CR12_MTRACE) && (regs->psw.amode64 != ((ete[4] & ETE4_G) ? 1 : 0))) { /* since ASN trace might be made already, need to save current CR12 and use newcr12 for this second entry */ if (!newcr12) newcr12 = regs->CR(12); savecr12 = regs->CR(12); regs->CR(12) = newcr12; newcr12 = ARCH_DEP(trace_ms) (0, 0, regs); regs->CR(12) = savecr12; } #endif /*defined(FEATURE_ESAME)*/ #endif /*FEATURE_TRACING*/ /* Set the called-space identification */ if (pasn == 0) csi = 0; else if (ASN_AND_LX_REUSE_ENABLED(regs)) csi = pasn << 16 | (aste[11] & 0x0000FFFF); else csi = pasn << 16 | (aste[5] & 0x0000FFFF); /* Set the addressing mode bits in the return address */ retn = PSW_IA(regs, 0); #if defined(FEATURE_ESAME) if ( regs->psw.amode64 ) retn |= 0x01; else #endif /*defined(FEATURE_ESAME)*/ if ( regs->psw.amode ) retn |= 0x80000000; #if defined(FEATURE_ESAME) /* Set the high-order bit of the PC number if the resulting addressing mode is 64-bit */ if (ete[4] & ETE4_G) pcnum |= 0x80000000; #endif /*defined(FEATURE_ESAME)*/ /* Perform the stacking process */ ARCH_DEP(form_stack_entry) (LSED_UET_PC, retn, 0, csi, pcnum, regs); /* Set the breaking event address register */ SET_BEAR_REG(regs, regs->ip - 4); /* Update the PSW from the entry table */ #if defined(FEATURE_ESAME) if (ete[4] & ETE4_G) { regs->psw.amode64 = 1; regs->psw.amode = 1; regs->psw.AMASK = AMASK64; UPD_PSW_IA(regs, ((U64)(ete[0]) << 32) | (U64)(ete[1] & 0xFFFFFFFE)); } else { regs->psw.amode64 = 0; regs->psw.amode = (ete[1] & ETE1_AMODE) ? 1 : 0; regs->psw.AMASK = regs->psw.amode ? AMASK31 : AMASK24; UPD_PSW_IA(regs, ete[1] & ETE1_EIA); } #else /*!defined(FEATURE_ESAME)*/ regs->psw.amode = (ete[1] & ETE1_AMODE) ? 1 : 0; regs->psw.AMASK = regs->psw.amode ? AMASK31 : AMASK24; UPD_PSW_IA(regs, ete[1] & ETE1_EIA); #endif /*!defined(FEATURE_ESAME)*/ if (ete[1] & ETE1_PROB) regs->psw.states |= BIT(PSW_PROB_BIT); else regs->psw.states &= ~BIT(PSW_PROB_BIT); /* Replace the PSW key by the entry key if the K bit is set */ if (ete[4] & ETE4_K) { regs->psw.pkey = (ete[4] & ETE4_EK) >> 16; } /* Replace the PSW key mask by the EKM if the M bit is set, otherwise OR the EKM into the current PSW key mask */ if (ete[4] & ETE4_M) regs->CR_LHH(3) = 0; regs->CR(3) |= (ete[3] & ETE3_EKM); /* Replace the EAX key by the EEAX if the E bit is set */ if (ete[4] & ETE4_E) { regs->CR_LHH(8) = (ete[4] & ETE4_EEAX); } /* Set the access mode according to the C bit */ if (ete[4] & ETE4_C) regs->psw.asc |= BIT(PSW_AR_BIT); else regs->psw.asc &= ~BIT(PSW_AR_BIT); /* Load the entry parameter into general register 4 */ #if defined(FEATURE_ESAME) if (regs->psw.amode64) regs->GR_H(4) = ete[6]; regs->GR_L(4) = ete[7]; #else /*!defined(FEATURE_ESAME)*/ regs->GR_L(4) = ete[2]; #endif /*!defined(FEATURE_ESAME)*/ } /* end if(stacking PC) */ #else /*!defined(FEATURE_LINKAGE_STACK)*/ ARCH_DEP(program_interrupt) (regs, PGM_PC_TRANSLATION_SPECIFICATION_EXCEPTION); #endif /*!defined(FEATURE_LINKAGE_STACK)*/ /* If new ASN is zero, perform program call to current primary */ if (pasn == 0) { /* Set SASN equal to PASN */ regs->CR_LHL(3) = regs->CR_LHL(4); /* Set SSTD equal to PSTD */ regs->CR(7) = regs->CR(1); /* When ASN-and-LX-reuse is installed and enabled, set the SASTEIN equal to the PASTEIN */ if (ASN_AND_LX_REUSE_ENABLED(regs)) regs->CR_H(3) = regs->CR_H(4); } /* end if(PC-cp) */ else { /* Program call with space switching */ /* Set SASN and SSTD equal to current PASN and PSTD */ regs->CR_LHL(3) = regs->CR_LHL(4); regs->CR(7) = regs->CR(1); /* When ASN-and-LX-reuse is installed and enabled, set the SASTEIN equal to the current PASTEIN */ if (ASN_AND_LX_REUSE_ENABLED(regs)) regs->CR_H(3) = regs->CR_H(4); /* Set flag if either the current or new PSTD indicates a space switch event */ if ((regs->CR(1) & SSEVENT_BIT) || (pstd & SSEVENT_BIT) ) { /* Indicate space-switch event required */ ssevent = 1; } /* Obtain new AX from the ASTE and new PASN from the ET */ regs->CR_L(4) = (aste[1] & ASTE1_AX) | pasn; /* When ASN-and-LX-reuse is installed and enabled, obtain the new PASTEIN from the new primary ASTE */ if (ASN_AND_LX_REUSE_ENABLED(regs)) regs->CR_H(4) = aste[11]; /* Load the new primary STD or ASCE */ regs->CR(1) = pstd; /* Update control register 5 with the new PASTEO or LTD */ regs->CR_L(5) = ASF_ENABLED(regs) ? pasteo : ASTE_LT_DESIGNATOR(aste); #if defined(FEATURE_LINKAGE_STACK) /* For stacking PC when the S-bit in the entry table is one, set SASN and SSTD equal to new PASN and PSTD */ if ((ete[4] & ETE4_T) && (ete[4] & ETE4_S)) { regs->CR_LHL(3) = regs->CR_LHL(4); regs->CR(7) = regs->CR(1); /* When ASN-and-LX-reuse is installed and enabled, also set the SASTEIN equal to the new PASTEIN */ if (ASN_AND_LX_REUSE_ENABLED(regs)) regs->CR_H(3) = regs->CR_H(4); } #endif /*defined(FEATURE_LINKAGE_STACK)*/ } /* end if(PC-ss) */ #ifdef FEATURE_TRACING /* Update trace table address if ASN or Mode switch made trace entry */ if (newcr12) regs->CR(12) = newcr12; #endif /*FEATURE_TRACING*/ /* Update cpu states */ SET_IC_MASK(regs); SET_AEA_MODE(regs); // psw.asc may be updated SET_AEA_COMMON(regs); // cr[1], cr[7] may be updated INVALIDATE_AIA(regs); /* Check for Successful Branch PER event */ PER_SB(regs, regs->psw.IA); /* Generate space switch event if required */ if ( ssevent || (pasn != 0 && IS_IC_PER(regs)) ) { /* [6.5.2.34] Set the translation exception address equal to the old primary ASN, with the high-order bit set if the old primary space-switch-event control bit is one */ regs->TEA = oldpasn; if (oldpstd & SSEVENT_BIT) regs->TEA |= TEA_SSEVENT; ARCH_DEP(program_interrupt) (regs, PGM_SPACE_SWITCH_EVENT); } /* Perform serialization and checkpoint-synchronization */ PERFORM_SERIALIZATION (regs); PERFORM_CHKPT_SYNC (regs); } /* end DEF_INST(program_call) */ #endif /*defined(FEATURE_DUAL_ADDRESS_SPACE)*/ #if defined(FEATURE_LINKAGE_STACK) /*-------------------------------------------------------------------*/ /* 0101 PR - Program Return [E] */ /*-------------------------------------------------------------------*/ DEF_INST(program_return) { REGS newregs; /* Copy of CPU registers */ int etype; /* Entry type unstacked */ int ssevent = 0; /* 1=space switch event */ RADR alsed; /* Absolute addr of LSED of previous stack entry */ LSED *lsedp; /* -> LSED in main storage */ U32 aste[16]; /* ASN second table entry */ U32 pasteo=0; /* Primary ASTE origin */ U32 sasteo=0; /* Secondary ASTE origin */ U16 oldpasn; /* Original primary ASN */ U32 oldpstd; /* Original primary STD */ U16 pasn = 0; /* New primary ASN */ U16 sasn; /* New secondary ASN */ U16 ax; /* Authorization index */ U16 xcode; /* Exception code */ int rc; /* return code from load_psw */ E(inst, regs); UNREFERENCED(inst); SIE_XC_INTERCEPT(regs); #if defined(_FEATURE_SIE) if(SIE_STATB(regs, IC3, PR)) longjmp(regs->progjmp, SIE_INTERCEPT_INST); #endif /*defined(_FEATURE_SIE)*/ /* Perform serialization and checkpoint-synchronization */ PERFORM_SERIALIZATION (regs); PERFORM_CHKPT_SYNC (regs); INVALIDATE_AIA(regs); /* Create a working copy of the CPU registers... */ memcpy( &newregs, regs, sysblk.regs_copy_len ); /* Now INVALIDATE ALL TLB ENTRIES in our working copy.. */ memset( &newregs.tlb.vaddr, 0, TLBN * sizeof(DW) ); newregs.tlbID = 1; /* Set the breaking event address register in the copy */ SET_BEAR_REG(&newregs, newregs.ip - (newregs.execflag ? newregs.exrl ? 6 : 4 : 2)); /* Save the primary ASN (CR4) and primary STD (CR1) */ oldpasn = regs->CR_LHL(4); oldpstd = regs->CR(1); /* Perform the unstacking process */ etype = ARCH_DEP(program_return_unstack) (&newregs, &alsed, &rc); #ifdef FEATURE_TRACING #if defined(FEATURE_ESAME) /* If unstacked entry was a BAKR: */ /* Add a mode trace entry when switching in/out of 64 bit mode */ if((etype == LSED_UET_BAKR) && (regs->CR(12) & CR12_MTRACE) && (regs->psw.amode64 != newregs.psw.amode64)) newregs.CR(12) = ARCH_DEP(trace_ms) (0, 0, regs); #endif /*defined(FEATURE_ESAME)*/ #endif /*FEATURE_TRACING*/ /* Perform PR-cp or PR-ss if unstacked entry was a program call */ if (etype == LSED_UET_PC) { /* Extract the new primary ASN from CR4 bits 16-31 */ pasn = newregs.CR_LHL(4); #ifdef FEATURE_TRACING /* Perform tracing if ASN tracing is on */ if (regs->CR(12) & CR12_ASNTRACE) newregs.CR(12) = ARCH_DEP(trace_pr) (&newregs, regs); #if defined(FEATURE_ESAME) else /* Add a mode trace entry when switching in/out of 64 bit mode */ if((regs->CR(12) & CR12_MTRACE) && (regs->psw.amode64 != newregs.psw.amode64)) newregs.CR(12) = ARCH_DEP(trace_ms) (0, 0, regs); #endif /*defined(FEATURE_ESAME)*/ #endif /*FEATURE_TRACING*/ /* Perform PASN translation if new PASN not equal old PASN */ if (pasn != oldpasn) { /* Special operation exception if ASN translation control (control register 14 bit 12) is zero */ if ((regs->CR(14) & CR14_ASN_TRAN) == 0) ARCH_DEP(program_interrupt) (&newregs, PGM_SPECIAL_OPERATION_EXCEPTION); /* Translate new primary ASN to obtain ASTE */ xcode = ARCH_DEP(translate_asn) (pasn, &newregs, &pasteo, aste); /* Program check if ASN translation exception */ if (xcode != 0) ARCH_DEP(program_interrupt) (&newregs, xcode); /* When ASN-and-LX-reuse is installed and enabled by CR0, the PASTEIN previously loaded from the state entry (by the program_return_unstack procedure) into the high word of CR4 must equal the ASTEIN in word 11 of the ASTE */ if (ASN_AND_LX_REUSE_ENABLED(regs)) { if (newregs.CR_H(4) != aste[11]) { /* Set bit 2 of the exception access identification to indicate that the program check occurred during PASN translation in a PR instruction */ newregs.excarid = 0x20; ARCH_DEP(program_interrupt) (&newregs, PGM_ASTE_INSTANCE_EXCEPTION); } } /* end if(ASN_AND_LX_REUSE_ENABLED) */ /* Obtain new PSTD (or PASCE) and AX from the ASTE */ newregs.CR(1) = ASTE_AS_DESIGNATOR(aste); newregs.CR_LHH(4) = 0; newregs.CR_L(4) |= aste[1] & ASTE1_AX; /* Load CR5 with the primary ASTE origin address */ newregs.CR_L(5) = pasteo; #ifdef FEATURE_SUBSPACE_GROUP /* Perform subspace replacement on new PSTD */ newregs.CR(1) = ARCH_DEP(subspace_replace) (newregs.CR(1), pasteo, NULL, &newregs); #endif /*FEATURE_SUBSPACE_GROUP*/ /* Space switch if either current PSTD or new PSTD space-switch-event control bit is set to 1 */ if ((regs->CR(1) & SSEVENT_BIT) || (newregs.CR(1) & SSEVENT_BIT)) { /* Indicate space-switch event required */ ssevent = 1; } else { /* space-switch event maybe - if PER event */ ssevent = 2; } } /* end if(pasn!=oldpasn) */ /* Extract the new secondary ASN from CR3 bits 16-31 */ sasn = newregs.CR_LHL(3); /* Set SSTD = PSTD if new SASN is equal to new PASN */ if (sasn == pasn) { newregs.CR(7) = newregs.CR(1); } else /* sasn != pasn */ { /* Perform SASN translation */ /* Special operation exception if ASN translation control (control register 14 bit 12) is zero */ if ((regs->CR(14) & CR14_ASN_TRAN) == 0) ARCH_DEP(program_interrupt) (&newregs, PGM_SPECIAL_OPERATION_EXCEPTION); /* Translate new secondary ASN to obtain ASTE */ xcode = ARCH_DEP(translate_asn) (sasn, &newregs, &sasteo, aste); /* Program check if ASN translation exception */ if (xcode != 0) ARCH_DEP(program_interrupt) (&newregs, xcode); /* When ASN-and-LX-reuse is installed and enabled by CR0, the SASTEIN previously loaded from the state entry (by the program_return_unstack procedure) into the high word of CR3 must equal the ASTEIN in word 11 of the ASTE */ if (ASN_AND_LX_REUSE_ENABLED(regs)) { if (newregs.CR_H(3) != aste[11]) { /* Set bit 3 of the exception access identification to indicate that the program check occurred during SASN translation in a PR instruction */ newregs.excarid = 0x10; ARCH_DEP(program_interrupt) (&newregs, PGM_ASTE_INSTANCE_EXCEPTION); } } /* end if(ASN_AND_LX_REUSE_ENABLED) */ /* Obtain new SSTD or SASCE from secondary ASTE */ newregs.CR(7) = ASTE_AS_DESIGNATOR(aste); /* Perform SASN authorization using new AX */ ax = newregs.CR_LHH(4); if (ARCH_DEP(authorize_asn) (ax, aste, ATE_SECONDARY, &newregs)) { newregs.TEA = sasn; ARCH_DEP(program_interrupt) (&newregs, PGM_SECONDARY_AUTHORITY_EXCEPTION); } #ifdef FEATURE_SUBSPACE_GROUP /* Perform subspace replacement on new SSTD */ newregs.CR(7) = ARCH_DEP(subspace_replace) (newregs.CR(7), sasteo, NULL, &newregs); #endif /*FEATURE_SUBSPACE_GROUP*/ } /* end else(sasn!=pasn) */ } /* end if(LSED_UET_PC) */ /* Update the updated CPU registers from the working copy */ memcpy(&(regs->psw), &(newregs.psw), sizeof(newregs.psw)); memcpy(regs->gr, newregs.gr, sizeof(newregs.gr)); memcpy(regs->cr, newregs.cr, sizeof(newregs.cr)); memcpy(regs->ar, newregs.ar, sizeof(newregs.ar)); regs->bear = newregs.bear; /* Set the main storage reference and change bits */ STORAGE_KEY(alsed, regs) |= (STORKEY_REF | STORKEY_CHANGE); /* [5.12.4.4] Clear the next entry size field of the linkage stack entry now pointed to by control register 15 */ lsedp = (LSED*)(regs->mainstor + alsed); lsedp->nes[0] = 0; lsedp->nes[1] = 0; #if defined(FEATURE_PER) /* Copy PER info from working copy to real copy of registers */ if (IS_IC_PER_SA(&newregs)) { ON_IC_PER_SA(regs); regs->perc = newregs.perc; } PER_SB(regs, regs->psw.IA); #endif /*defined(FEATURE_PER)*/ /* Update cpu states */ SET_IC_MASK(regs); SET_AEA_MODE(regs); // psw has been updated SET_AEA_COMMON(regs); // control regs been updated /* Generate space switch event if required */ if ( ssevent == 1 || (ssevent == 2 && IS_IC_PER(regs)) ) { /* [6.5.2.34] Set translation exception address equal to old primary ASN, and set high-order bit if old primary space-switch-event control bit is one */ regs->TEA = oldpasn; if (oldpstd & SSEVENT_BIT) regs->TEA |= TEA_SSEVENT; ARCH_DEP(program_interrupt) (regs, PGM_SPACE_SWITCH_EVENT); } if (rc) /* if new psw has bad format */ { ARCH_DEP(program_interrupt) (regs, rc); } /* Perform serialization and checkpoint-synchronization */ PERFORM_SERIALIZATION (regs); PERFORM_CHKPT_SYNC (regs); RETURN_INTCHECK(regs); } /* end DEF_INST(program_return) */ #endif /*defined(FEATURE_LINKAGE_STACK)*/ #if defined(FEATURE_DUAL_ADDRESS_SPACE) /*-------------------------------------------------------------------*/ /* Common processing routine for the PT and PTI instructions */ /*-------------------------------------------------------------------*/ void ARCH_DEP(program_transfer_proc) (REGS *regs, int r1, int r2, int pti_instruction) { U16 pkm; /* New program key mask */ U16 pasn; /* New primary ASN */ U16 oldpasn; /* Old primary ASN */ int amode; /* New amode */ VADR ia; /* New instruction address */ int prob; /* New problem state bit */ RADR abs; /* Absolute address */ U32 ltd; /* Linkage table designation */ U32 pasteo=0; /* Primary ASTE origin */ U32 aste[16]; /* ASN second table entry */ CREG pstd; /* Primary STD */ U32 oldpstd; /* Old Primary STD */ U16 ax; /* Authorization index */ U16 xcode; /* Exception code */ int ssevent = 0; /* 1=space switch event */ #ifdef FEATURE_TRACING CREG newcr12 = 0; /* CR12 upon completion */ #endif /*FEATURE_TRACING*/ SIE_XC_INTERCEPT(regs); #if defined(_FEATURE_SIE) if(SIE_STATB(regs, IC2, PT)) longjmp(regs->progjmp, SIE_INTERCEPT_INST); #endif /*defined(_FEATURE_SIE)*/ /* Perform serialization and checkpoint-synchronization */ PERFORM_SERIALIZATION (regs); PERFORM_CHKPT_SYNC (regs); /* Special operation exception if DAT is off, or not in primary space mode */ if (REAL_MODE(&(regs->psw)) || !PRIMARY_SPACE_MODE(&(regs->psw))) ARCH_DEP(program_interrupt) (regs, PGM_SPECIAL_OPERATION_EXCEPTION); /* Special operation exception if subsystem linkage control bit in CR5 is zero (when ASF is off)*/ if (!ASF_ENABLED(regs) && !(regs->CR_L(5) & LTD_SSLINK)) ARCH_DEP(program_interrupt) (regs, PGM_SPECIAL_OPERATION_EXCEPTION); /* Save the primary ASN (CR4) and primary STD (CR1) */ oldpasn = regs->CR_LHL(4); oldpstd = regs->CR(1); /* Extract the PSW key mask from R1 register bits 0-15 */ pkm = regs->GR_LHH(r1); /* Extract the ASN from R1 register bits 16-31 */ pasn = regs->GR_LHL(r1); #ifdef FEATURE_TRACING /* Build trace entry if ASN tracing is on */ if (regs->CR(12) & CR12_ASNTRACE) newcr12 = ARCH_DEP(trace_pt) (pti_instruction, pasn, regs->GR(r2), regs); #endif /*FEATURE_TRACING*/ /* Determine instruction address, amode, and problem state */ #if defined(FEATURE_ESAME) if (regs->psw.amode64) { /* In 64-bit address mode, extract instruction address from R2 register bits 0-62, and leave address mode unchanged */ ia = regs->GR_G(r2) & 0xFFFFFFFFFFFFFFFEULL; amode = regs->psw.amode; } else #endif /*defined(FEATURE_ESAME)*/ { /* In 31- or 24-bit mode, extract new amode from R2 bit 0 */ amode = (regs->GR_L(r2) & 0x80000000) ? 1 : 0; /* Extract the instruction address from R2 bits 1-30 */ ia = regs->GR_L(r2) & 0x7FFFFFFE; } /* Extract the problem state bit from R2 register bit 31 */ prob = regs->GR_L(r2) & 0x00000001; /* [5.5.3.1] Load the linkage table designation */ if (!ASF_ENABLED(regs)) { /* Obtain the LTD from control register 5 */ ltd = regs->CR_L(5); } else { /* Obtain the primary ASTE origin from control register 5 */ pasteo = regs->CR_L(5) & CR5_PASTEO; /* Convert the PASTE origin to an absolute address */ abs = APPLY_PREFIXING (pasteo, regs->PX); /* Program check if PASTE is outside main storage */ if (abs > regs->mainlim) ARCH_DEP(program_interrupt) (regs, PGM_ADDRESSING_EXCEPTION); /* Fetch primary ASTE words 3 and 6 from absolute storage (note: the ASTE cannot cross a page boundary) */ #if !defined(FEATURE_ESAME) aste[3] = ARCH_DEP(fetch_fullword_absolute) (abs+12, regs); #else /*defined(FEATURE_ESAME)*/ aste[6] = ARCH_DEP(fetch_fullword_absolute) (abs+24, regs); #endif /*defined(FEATURE_ESAME)*/ /* Load LTD from primary ASTE word 3 or 6 */ ltd = ASTE_LT_DESIGNATOR(aste); } /* Special operation exception if subsystem linkage control bit in linkage table designation is zero */ if ((ltd & LTD_SSLINK) == 0) ARCH_DEP(program_interrupt) (regs, PGM_SPECIAL_OPERATION_EXCEPTION); /* Privileged operation exception if in problem state and problem bit indicates a change to supervisor state */ if (PROBSTATE(®s->psw) && prob == 0) ARCH_DEP(program_interrupt) (regs, PGM_PRIVILEGED_OPERATION_EXCEPTION); /* Specification exception if new amode is 24-bit and new instruction address is not a 24-bit address */ if (amode == 0 && ia > 0x00FFFFFF) ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION); /* Space switch if ASN not equal to current PASN */ if ( pasn != regs->CR_LHL(4) ) { /* Special operation exception if ASN translation control (control register 14 bit 12) is zero */ if ((regs->CR(14) & CR14_ASN_TRAN) == 0) ARCH_DEP(program_interrupt) (regs, PGM_SPECIAL_OPERATION_EXCEPTION); /* Translate ASN and generate program check if AFX- or ASX-translation exception condition */ xcode = ARCH_DEP(translate_asn) (pasn, regs, &pasteo, aste); if (xcode != 0) ARCH_DEP(program_interrupt) (regs, xcode); /* For PT-ss only, generate a special operation exception if ASN-and-LX-reuse is enabled and the reusable-ASN bit in the ASTE is one */ if (pti_instruction == 0 && ASN_AND_LX_REUSE_ENABLED(regs) && (aste[1] & ASTE1_RA) != 0) { ARCH_DEP(program_interrupt) (regs, PGM_SPECIAL_OPERATION_EXCEPTION); } /* end if (PT && ASN_AND_LX_REUSE_ENABLED && ASTE1_RA) */ /* For PTI-ss only, generate a special operation exception if the controlled-ASN bit in the ASTE is one and the CPU was in problem state at the beginning of the operation */ if (pti_instruction && (aste[1] & ASTE1_CA) != 0 && PROBSTATE(®s->psw)) { ARCH_DEP(program_interrupt) (regs, PGM_SPECIAL_OPERATION_EXCEPTION); } /* end if (PT && ASTE1_CA && PROBSTATE) */ /* For PTI-ss only, generate an ASTE instance exception if the ASTEIN in bits 0-31 of the R1 register does not equal the ASTEIN in the ASTE*/ if (pti_instruction && aste[11] != regs->GR_H(r1)) { /* Set bit 2 of the exception access identification to indicate that the program check occurred during PASN translation in a PTI instruction */ regs->excarid = 0x20; ARCH_DEP(program_interrupt) (regs, PGM_ASTE_INSTANCE_EXCEPTION); } /* end if (PT && ASTE11_ASTEIN != GR_H(r1)) */ /* Perform primary address space authorization using current authorization index */ ax = regs->CR_LHH(4); if (ARCH_DEP(authorize_asn) (ax, aste, ATE_PRIMARY, regs)) { regs->TEA = pasn; ARCH_DEP(program_interrupt) (regs, PGM_PRIMARY_AUTHORITY_EXCEPTION); } /* Obtain new primary STD or ASCE from the ASTE */ pstd = ASTE_AS_DESIGNATOR(aste); #ifdef FEATURE_SUBSPACE_GROUP /* Perform subspace replacement on new PSTD */ pstd = ARCH_DEP(subspace_replace) (pstd, pasteo, NULL, regs); #endif /*FEATURE_SUBSPACE_GROUP*/ /* Space switch if either current PSTD or new PSTD space-switch-event control bit is set to 1 */ if ((regs->CR(1) & SSEVENT_BIT) || (pstd & SSEVENT_BIT)) { /* Indicate space-switch event required */ ssevent = 1; } else { ssevent = 2; /* maybe, if PER is pending */ } /* Load new primary STD or ASCE into control register 1 */ regs->CR(1) = pstd; /* Load new AX and PASN into control register 4 */ regs->CR_L(4) = (aste[1] & ASTE1_AX) | pasn; /* Load new PASTEO or LTD into control register 5 */ regs->CR_L(5) = ASF_ENABLED(regs) ? pasteo : ASTE_LT_DESIGNATOR(aste); /* For PTI-ss, and for PT-ss when ASN-and-LX-reuse is enabled, load the new PASTEIN into CR4 from ASTE11_ASTEIN */ if (pti_instruction || ASN_AND_LX_REUSE_ENABLED(regs)) { regs->CR_H(4) = aste[11]; } /* end if (PTI || ASN_AND_LX_REUSE_ENABLED) */ } /* end if(PT-ss or PTI-ss) */ else { /* For PT-cp or PTI-cp use current primary STD or ASCE */ pstd = regs->CR(1); } #ifdef FEATURE_TRACING /* Update trace table address if ASN tracing is on */ if (regs->CR(12) & CR12_ASNTRACE) regs->CR(12) = newcr12; #endif /*FEATURE_TRACING*/ /* Check for Successful Branch PER event */ PER_SB(regs, ia); /* Set the breaking event address register */ SET_BEAR_REG(regs, regs->ip - 4); /* Replace PSW amode, instruction address, and problem state bit */ regs->psw.amode = amode; UPD_PSW_IA(regs, ia); if (prob) regs->psw.states |= BIT(PSW_PROB_BIT); else regs->psw.states &= ~BIT(PSW_PROB_BIT); regs->psw.AMASK = #if defined(FEATURE_ESAME) regs->psw.amode64 ? AMASK64 : #endif /*defined(FEATURE_ESAME)*/ regs->psw.amode ? AMASK31 : AMASK24; /* AND control register 3 bits 0-15 with the supplied PKM value and replace the SASN in CR3 bits 16-31 with new PASN */ regs->CR_LHH(3) &= pkm; regs->CR_LHL(3) = pasn; /* For PTI, and also for PT when ASN-and-LX-reuse is enabled, set the SASTEIN in CR3 equal to the new PASTEIN in CR4 */ if (pti_instruction || ASN_AND_LX_REUSE_ENABLED(regs)) { regs->CR_H(3) = regs->CR_H(4); } /* end if (PTI || ASN_AND_LX_REUSE_ENABLED) */ /* Set secondary STD or ASCE equal to new primary STD or ASCE */ regs->CR(7) = pstd; /* Update cpu states */ SET_IC_MASK(regs); SET_AEA_COMMON(regs); INVALIDATE_AIA(regs); /* Generate space switch event if required */ if ( ssevent == 1 || (ssevent == 2 && IS_IC_PER(regs)) ) { /* [6.5.2.34] Set the translation exception address equal to the old primary ASN, with the high-order bit set if the old primary space-switch-event control bit is one */ regs->TEA = oldpasn; if (oldpstd & SSEVENT_BIT) regs->TEA |= TEA_SSEVENT; ARCH_DEP(program_interrupt) (regs, PGM_SPACE_SWITCH_EVENT); } /* Perform serialization and checkpoint-synchronization */ PERFORM_SERIALIZATION (regs); PERFORM_CHKPT_SYNC (regs); } /* end ARCH_DEP(program_transfer_proc) */ /*-------------------------------------------------------------------*/ /* B228 PT - Program Transfer [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(program_transfer) { int r1, r2; /* Values of R fields */ RRE(inst, regs, r1, r2); ARCH_DEP(program_transfer_proc) (regs, r1, r2, 0); } /* end DEF_INST(program_transfer) */ #endif /*defined(FEATURE_DUAL_ADDRESS_SPACE)*/ #if defined(FEATURE_ASN_AND_LX_REUSE) /*-------------------------------------------------------------------*/ /* B99E PTI - Program Transfer with Instance [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(program_transfer_with_instance) { int r1, r2; /* Values of R fields */ if(!sysblk.asnandlxreuse) { ARCH_DEP(operation_exception)(inst,regs); } RRE(inst, regs, r1, r2); ARCH_DEP(program_transfer_proc) (regs, r1, r2, 1); } /* end DEF_INST(program_transfer_with_instance) */ #endif /*defined(FEATURE_ASN_AND_LX_REUSE)*/ #if defined(FEATURE_ACCESS_REGISTERS) /*-------------------------------------------------------------------*/ /* B248 PALB - Purge ALB [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(purge_accesslist_lookaside_buffer) { int r1, r2; /* Register values (unused) */ RRE(inst, regs, r1, r2); #if defined(FEATURE_MULTIPLE_CONTROLLED_DATA_SPACE) /* This instruction is executed as a no-operation in XC mode */ if(SIE_STATB(regs, MX, XC)) return; #endif /*defined(FEATURE_MULTIPLE_CONTROLLED_DATA_SPACE)*/ PRIV_CHECK(regs); #if defined(_FEATURE_SIE) if(SIE_STATB(regs, IC1, PXLB)) longjmp(regs->progjmp, SIE_INTERCEPT_INST); #endif /*defined(_FEATURE_SIE)*/ /* Purge the ART lookaside buffer for this CPU */ ARCH_DEP(purge_alb) (regs); } #endif /*defined(FEATURE_ACCESS_REGISTERS)*/ /*-------------------------------------------------------------------*/ /* B20D PTLB - Purge TLB [S] */ /*-------------------------------------------------------------------*/ DEF_INST(purge_translation_lookaside_buffer) { int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ S(inst, regs, b2, effective_addr2); #if defined(FEATURE_MULTIPLE_CONTROLLED_DATA_SPACE) /* This instruction is executed as a no-operation in XC mode */ if(SIE_STATB(regs, MX, XC)) return; #endif /*defined(FEATURE_MULTIPLE_CONTROLLED_DATA_SPACE)*/ PRIV_CHECK(regs); #if defined(_FEATURE_SIE) if(SIE_STATB(regs, IC1, PXLB)) longjmp(regs->progjmp, SIE_INTERCEPT_INST); #endif /*defined(_FEATURE_SIE)*/ /* Purge the translation lookaside buffer for this CPU */ ARCH_DEP(purge_tlb) (regs); } #if defined(FEATURE_BASIC_STORAGE_KEYS) /*-------------------------------------------------------------------*/ /* B213 RRB - Reset Reference Bit [S] */ /*-------------------------------------------------------------------*/ DEF_INST(reset_reference_bit) { int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ RADR n; /* Absolute storage addr */ BYTE storkey; /* Storage key */ S(inst, regs, b2, effective_addr2); #if defined(FEATURE_4K_STORAGE_KEYS) || defined(_FEATURE_SIE) if( #if defined(_FEATURE_SIE) && !defined(FEATURE_4K_STORAGE_KEYS) SIE_MODE(regs) && #endif !(regs->CR(0) & CR0_STORKEY_4K) ) ARCH_DEP(program_interrupt) (regs, PGM_SPECIAL_OPERATION_EXCEPTION); #endif PRIV_CHECK(regs); /* Load 2K block real address from operand address */ n = effective_addr2 & 0x00FFF800; /* Convert real address to absolute address */ n = APPLY_PREFIXING (n, regs->PX); /* Addressing exception if block is outside main storage */ if ( n > regs->mainlim ) ARCH_DEP(program_interrupt) (regs, PGM_ADDRESSING_EXCEPTION); #if defined(_FEATURE_SIE) if(SIE_MODE(regs)) { if(SIE_STATB(regs, IC2, RRBE)) longjmp(regs->progjmp, SIE_INTERCEPT_INST); if(!regs->sie_pref) { #if defined(_FEATURE_STORAGE_KEY_ASSIST) if(SIE_STATB(regs, RCPO0, SKA) && SIE_STATB(regs, RCPO2, RCPBY)) { SIE_TRANSLATE(&n, ACCTYPE_SIE, regs); #if !defined(_FEATURE_2K_STORAGE_KEYS) storkey = STORAGE_KEY(n, regs); #else storkey = STORAGE_KEY1(n, regs) | STORAGE_KEY2(n, regs); #endif /* Reset the reference bit in the storage key */ #if !defined(_FEATURE_2K_STORAGE_KEYS) STORAGE_KEY(n, regs) &= ~(STORKEY_REF); #else STORAGE_KEY1(n, regs) &= ~(STORKEY_REF); STORAGE_KEY2(n, regs) &= ~(STORKEY_REF); #endif } else #endif /*defined(_FEATURE_STORAGE_KEY_ASSIST)*/ { BYTE rcpkey, realkey; RADR ra; RADR rcpa; #if defined(_FEATURE_STORAGE_KEY_ASSIST) if(SIE_STATB(regs, RCPO0, SKA)) { /* guest absolute to host PTE addr */ if (SIE_TRANSLATE_ADDR (regs->sie_mso + n, USE_PRIMARY_SPACE, regs->hostregs, ACCTYPE_PTE)) longjmp(regs->progjmp, SIE_INTERCEPT_INST); /* Convert real address to absolute address */ rcpa = APPLY_PREFIXING (regs->hostregs->dat.raddr, regs->hostregs->PX); /* The reference and change byte is located directly beyond the page table and is located at offset 1 in the entry. S/370 mode cannot be emulated in ESAME mode, so no provision is made for ESAME mode tables */ rcpa += 1025; } else #endif /*defined(_FEATURE_STORAGE_KEY_ASSIST)*/ { /* Obtain address of the RCP area from the state desc */ rcpa = regs->sie_rcpo &= 0x7FFFF000; /* frame index as byte offset to 4K keys in RCP area */ rcpa += n >> 12; /* host primary to host absolute */ rcpa = SIE_LOGICAL_TO_ABS (rcpa, USE_PRIMARY_SPACE, regs->hostregs, ACCTYPE_SIE, 0); } /* fetch the RCP key */ rcpkey = regs->mainstor[rcpa]; STORAGE_KEY(rcpa, regs) |= STORKEY_REF; if (!SIE_TRANSLATE_ADDR (regs->sie_mso + n, USE_PRIMARY_SPACE, regs->hostregs, ACCTYPE_SIE)) { ra = APPLY_PREFIXING(regs->hostregs->dat.raddr, regs->hostregs->PX); #if !defined(_FEATURE_2K_STORAGE_KEYS) realkey = STORAGE_KEY(ra, regs) #else realkey = (STORAGE_KEY1(ra, regs) | STORAGE_KEY2(ra, regs)) #endif & (STORKEY_REF | STORKEY_CHANGE); /* Reset reference and change bits in storage key */ #if !defined(_FEATURE_2K_STORAGE_KEYS) STORAGE_KEY(ra, regs) &= ~(STORKEY_REF | STORKEY_CHANGE); #else STORAGE_KEY1(ra, regs) &= ~(STORKEY_REF | STORKEY_CHANGE); STORAGE_KEY2(ra, regs) &= ~(STORKEY_REF | STORKEY_CHANGE); #endif } else realkey = 0; /* The storage key is obtained by logical or or the real and guest RC bits */ storkey = realkey | (rcpkey & (STORKEY_REF | STORKEY_CHANGE)); /* or with host set */ rcpkey |= realkey << 4; /* Put storage key in guest set */ rcpkey |= storkey; /* reset the reference bit */ rcpkey &= ~(STORKEY_REF); regs->mainstor[rcpa] = rcpkey; STORAGE_KEY(rcpa, regs) |= (STORKEY_REF|STORKEY_CHANGE); } } else /* regs->sie_perf */ { #if defined(_FEATURE_2K_STORAGE_KEYS) storkey = STORAGE_KEY(n, regs); #else storkey = STORAGE_KEY1(n, regs) | STORAGE_KEY2(n, regs); #endif /* Reset the reference bit in the storage key */ #if defined(_FEATURE_2K_STORAGE_KEYS) STORAGE_KEY(n, regs) &= ~(STORKEY_REF); #else STORAGE_KEY1(n, regs) &= ~(STORKEY_REF); STORAGE_KEY2(n, regs) &= ~(STORKEY_REF); #endif } } else #endif /*defined(_FEATURE_SIE)*/ { #if !defined(_FEATURE_2K_STORAGE_KEYS) storkey = STORAGE_KEY(n, regs); #else storkey = STORAGE_KEY1(n, regs) | STORAGE_KEY2(n, regs); #endif /* Reset the reference bit in the storage key */ #if !defined(_FEATURE_2K_STORAGE_KEYS) STORAGE_KEY(n, regs) &= ~(STORKEY_REF); #else STORAGE_KEY1(n, regs) &= ~(STORKEY_REF); STORAGE_KEY2(n, regs) &= ~(STORKEY_REF); #endif } /* Set the condition code according to the original state of the reference and change bits in the storage key */ regs->psw.cc = ((storkey & STORKEY_REF) ? 2 : 0) | ((storkey & STORKEY_CHANGE) ? 1 : 0); /* If the storage key had the REF bit on then perform * accelerated lookup invalidations on all CPUs * so that the REF bit will be set when referenced next. */ if (storkey & STORKEY_REF) STORKEY_INVALIDATE(regs, n); } #endif /*defined(FEATURE_BASIC_STORAGE_KEYS)*/ #if defined(FEATURE_EXTENDED_STORAGE_KEYS) /*-------------------------------------------------------------------*/ /* B22A RRBE - Reset Reference Bit Extended [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(reset_reference_bit_extended) { int r1, r2; /* Register values */ RADR n; /* Abs frame addr stor key */ BYTE storkey; /* Storage key */ RRE(inst, regs, r1, r2); PRIV_CHECK(regs); /* Load 4K block address from R2 register */ n = regs->GR(r2) & ADDRESS_MAXWRAP_E(regs); /* Convert real address to absolute address */ n = APPLY_PREFIXING (n, regs->PX); /* Addressing exception if block is outside main storage */ if ( n > regs->mainlim ) ARCH_DEP(program_interrupt) (regs, PGM_ADDRESSING_EXCEPTION); #if defined(_FEATURE_SIE) if(SIE_MODE(regs)) { if(SIE_STATB(regs, IC2, RRBE)) longjmp(regs->progjmp, SIE_INTERCEPT_INST); if(!regs->sie_pref) { #if defined(_FEATURE_STORAGE_KEY_ASSIST) if((SIE_STATB(regs, RCPO0, SKA) #if defined(_FEATURE_ZSIE) || (regs->hostregs->arch_mode == ARCH_900) #endif /*defined(_FEATURE_ZSIE)*/ ) && SIE_STATB(regs, RCPO2, RCPBY)) { SIE_TRANSLATE(&n, ACCTYPE_SIE, regs); #if !defined(_FEATURE_2K_STORAGE_KEYS) storkey = STORAGE_KEY(n, regs); #else storkey = STORAGE_KEY1(n, regs) | (STORAGE_KEY2(n, regs) & (STORKEY_REF|STORKEY_CHANGE)) #endif ; /* Reset the reference bit in the storage key */ #if !defined(_FEATURE_2K_STORAGE_KEYS) STORAGE_KEY(n, regs) &= ~(STORKEY_REF); #else STORAGE_KEY1(n, regs) &= ~(STORKEY_REF); STORAGE_KEY2(n, regs) &= ~(STORKEY_REF); #endif } else #endif /*defined(_FEATURE_STORAGE_KEY_ASSIST)*/ { BYTE rcpkey, realkey; RADR ra; RADR rcpa; #if defined(_FEATURE_STORAGE_KEY_ASSIST) if(SIE_STATB(regs, RCPO0, SKA) #if defined(_FEATURE_ZSIE) || (regs->hostregs->arch_mode == ARCH_900) #endif /*defined(_FEATURE_ZSIE)*/ ) { /* guest absolute to host PTE addr */ if (SIE_TRANSLATE_ADDR (regs->sie_mso + n, USE_PRIMARY_SPACE, regs->hostregs, ACCTYPE_PTE)) longjmp(regs->progjmp, SIE_INTERCEPT_INST); /* Convert real address to absolute address */ rcpa = APPLY_PREFIXING (regs->hostregs->dat.raddr, regs->hostregs->PX); /* For ESA/390 the RCP byte entry is at offset 1 in a four byte entry directly beyond the page table, for ESAME mode, this entry is eight bytes long */ rcpa += regs->hostregs->arch_mode == ARCH_900 ? 2049 : 1025; } else #endif /*defined(_FEATURE_STORAGE_KEY_ASSIST)*/ { #if defined(FEATURE_MULTIPLE_CONTROLLED_DATA_SPACE) if(SIE_STATB(regs, MX, XC)) longjmp(regs->progjmp, SIE_INTERCEPT_INST); #endif /*defined(FEATURE_MULTIPLE_CONTROLLED_DATA_SPACE)*/ /* Obtain address of the RCP area from the state desc */ rcpa = regs->sie_rcpo &= 0x7FFFF000; /* frame index as byte offset to 4K keys in RCP area */ rcpa += n >> 12; /* host primary to host absolute */ rcpa = SIE_LOGICAL_TO_ABS (rcpa, USE_PRIMARY_SPACE, regs->hostregs, ACCTYPE_SIE, 0); } /* fetch the RCP key */ rcpkey = regs->mainstor[rcpa]; STORAGE_KEY(rcpa, regs) |= STORKEY_REF; if (!SIE_TRANSLATE_ADDR (regs->sie_mso + n, USE_PRIMARY_SPACE, regs->hostregs, ACCTYPE_SIE)) { ra = APPLY_PREFIXING(regs->hostregs->dat.raddr, regs->hostregs->PX); #if !defined(_FEATURE_2K_STORAGE_KEYS) realkey = STORAGE_KEY(ra, regs) & (STORKEY_REF | STORKEY_CHANGE); #else realkey = (STORAGE_KEY1(ra, regs) | STORAGE_KEY2(ra, regs)) & (STORKEY_REF | STORKEY_CHANGE); #endif /* Reset the reference and change bits in the real machine storage key */ #if !defined(_FEATURE_2K_STORAGE_KEYS) STORAGE_KEY(ra, regs) &= ~(STORKEY_REF | STORKEY_CHANGE); #else STORAGE_KEY1(ra, regs) &= ~(STORKEY_REF | STORKEY_CHANGE); STORAGE_KEY2(ra, regs) &= ~(STORKEY_REF | STORKEY_CHANGE); #endif } else realkey = 0; /* The storage key is obtained by logical or or the real and guest RC bits */ storkey = realkey | (rcpkey & (STORKEY_REF | STORKEY_CHANGE)); /* or with host set */ rcpkey |= realkey << 4; /* Put storage key in guest set */ rcpkey |= storkey; /* reset the reference bit */ rcpkey &= ~(STORKEY_REF); regs->mainstor[rcpa] = rcpkey; STORAGE_KEY(rcpa, regs) |= (STORKEY_REF|STORKEY_CHANGE); } } else { #if !defined(_FEATURE_2K_STORAGE_KEYS) storkey = STORAGE_KEY(n, regs); #else storkey = STORAGE_KEY1(n, regs) | (STORAGE_KEY2(n, regs) & (STORKEY_REF|STORKEY_CHANGE)) #endif ; /* Reset the reference bit in the storage key */ #if !defined(_FEATURE_2K_STORAGE_KEYS) STORAGE_KEY(n, regs) &= ~(STORKEY_REF); #else STORAGE_KEY1(n, regs) &= ~(STORKEY_REF); STORAGE_KEY2(n, regs) &= ~(STORKEY_REF); #endif } } else #endif /*defined(_FEATURE_SIE)*/ { #if !defined(_FEATURE_2K_STORAGE_KEYS) storkey = STORAGE_KEY(n, regs); #else storkey = STORAGE_KEY1(n, regs) | (STORAGE_KEY2(n, regs) & (STORKEY_REF|STORKEY_CHANGE)) #endif ; /* Reset the reference bit in the storage key */ #if !defined(_FEATURE_2K_STORAGE_KEYS) STORAGE_KEY(n, regs) &= ~(STORKEY_REF); #else STORAGE_KEY1(n, regs) &= ~(STORKEY_REF); STORAGE_KEY2(n, regs) &= ~(STORKEY_REF); #endif } /* Set the condition code according to the original state of the reference and change bits in the storage key */ regs->psw.cc = ((storkey & STORKEY_REF) ? 2 : 0) | ((storkey & STORKEY_CHANGE) ? 1 : 0); /* If the storage key had the REF bit on then perform * accelerated looup invalidations on all CPUs * so that the REF bit will be set when referenced next. */ if (storkey & STORKEY_REF) STORKEY_INVALIDATE(regs, n); } /* end DEF_INST(reset_reference_bit_extended) */ #endif /*defined(FEATURE_EXTENDED_STORAGE_KEYS)*/ #if defined(FEATURE_DUAL_ADDRESS_SPACE) /*-------------------------------------------------------------------*/ /* B219 SAC - Set Address Space Control [S] */ /* B279 SACF - Set Address Space Control Fast [S] */ /*-------------------------------------------------------------------*/ DEF_INST(set_address_space_control) { int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ BYTE mode; /* New addressing mode */ BYTE oldmode; /* Current addressing mode */ int ssevent = 0; /* 1=space switch event */ S(inst, regs, b2, effective_addr2); #if defined(FEATURE_SET_ADDRESS_SPACE_CONTROL_FAST) if(inst[1] == 0x19) // SAC only #endif /*defined(FEATURE_SET_ADDRESS_SPACE_CONTROL_FAST)*/ { /* Perform serialization and checkpoint-synchronization */ PERFORM_SERIALIZATION (regs); PERFORM_CHKPT_SYNC (regs); } /* Isolate bits 20-23 of effective address */ mode = (effective_addr2 & 0x00000F00) >> 8; /* Special operation exception if DAT is off or secondary-space control bit is zero */ if ((REAL_MODE(&(regs->psw)) || (regs->CR(0) & CR0_SEC_SPACE) == 0) #if defined(FEATURE_MULTIPLE_CONTROLLED_DATA_SPACE) && !SIE_STATB(regs, MX, XC) #endif /*defined(FEATURE_MULTIPLE_CONTROLLED_DATA_SPACE)*/ ) ARCH_DEP(program_interrupt) (regs, PGM_SPECIAL_OPERATION_EXCEPTION); /* Privileged operation exception if setting home-space mode while in problem state */ if (mode == 3 && PROBSTATE(®s->psw)) ARCH_DEP(program_interrupt) (regs, PGM_PRIVILEGED_OPERATION_EXCEPTION); /* Special operation exception if setting AR mode and address-space function control bit is zero */ if (mode == 2 && !ASF_ENABLED(regs)) ARCH_DEP(program_interrupt) (regs, PGM_SPECIAL_OPERATION_EXCEPTION); /* Specification exception if mode is invalid */ if (mode > 3 #if defined(FEATURE_MULTIPLE_CONTROLLED_DATA_SPACE) /* Secondary and Home space mode are not supported in XC mode */ || ( SIE_STATB(regs, MX, XC) && (mode == 1 || mode == 3) ) #endif /*defined(FEATURE_MULTIPLE_CONTROLLED_DATA_SPACE)*/ ) ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION); /* Save the current address-space control bits */ oldmode = (AR_BIT(®s->psw) << 1) | SPACE_BIT(®s->psw); /* Reset the address-space control bits in the PSW */ if (mode & 1) regs->psw.asc |= BIT(PSW_SPACE_BIT); else regs->psw.asc &= ~BIT(PSW_SPACE_BIT); if (mode & 2) regs->psw.asc |= BIT(PSW_AR_BIT); else regs->psw.asc &= ~BIT(PSW_AR_BIT); TEST_SET_AEA_MODE(regs); /* If switching into or out of home-space mode, and also: primary space-switch-event control bit is set; or home space-switch-event control bit is set; or PER event is to be indicated then indicate a space-switch-event */ if (((oldmode != 3 && mode == 3) || (oldmode == 3 && mode != 3)) && (regs->CR(1) & SSEVENT_BIT || regs->CR(13) & SSEVENT_BIT || OPEN_IC_PER(regs) )) { /* Indicate space-switch event required */ ssevent = 1; /* [6.5.2.34] Set the translation exception address */ if (mode == 3) { /* When switching into home-space mode, set the translation exception address equal to the primary ASN, with the high-order bit set equal to the value of the primary space-switch-event control bit */ regs->TEA = regs->CR_LHL(4); if (regs->CR(1) & SSEVENT_BIT) regs->TEA |= TEA_SSEVENT; } else { /* When switching out of home-space mode, set the translation exception address equal to zero, with the high-order bit set equal to the value of the home space-switch-event control bit */ regs->TEA = 0; if (regs->CR(13) & SSEVENT_BIT) regs->TEA |= TEA_SSEVENT; } } /* Generate a space-switch-event if indicated */ if (ssevent) ARCH_DEP(program_interrupt) (regs, PGM_SPACE_SWITCH_EVENT); #if defined(FEATURE_SET_ADDRESS_SPACE_CONTROL_FAST) if(inst[1] == 0x19) // SAC only #endif /*defined(FEATURE_SET_ADDRESS_SPACE_CONTROL_FAST)*/ { /* Perform serialization and checkpoint-synchronization */ PERFORM_SERIALIZATION (regs); PERFORM_CHKPT_SYNC (regs); } } #endif /*defined(FEATURE_DUAL_ADDRESS_SPACE)*/ /*-------------------------------------------------------------------*/ /* B204 SCK - Set Clock [S] */ /*-------------------------------------------------------------------*/ DEF_INST(set_clock) { int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ U64 dreg; /* Clock value */ S(inst, regs, b2, effective_addr2); SIE_INTERCEPT(regs); PRIV_CHECK(regs); DW_CHECK(effective_addr2, regs); /* Fetch new TOD clock value from operand address */ dreg = ARCH_DEP(vfetch8) ( effective_addr2, b2, regs); /* Set the clock epoch register */ set_tod_clock(dreg >> 8); /* reset the clock comparator pending flag according to the setting of the tod clock */ OBTAIN_INTLOCK(regs); if( tod_clock(regs) > regs->clkc ) ON_IC_CLKC(regs); else OFF_IC_CLKC(regs); RELEASE_INTLOCK(regs); /* Return condition code zero */ regs->psw.cc = 0; RETURN_INTCHECK(regs); // /*debug*/logmsg("Set TOD clock=%16.16" I64_FMT "X\n", dreg); } /*-------------------------------------------------------------------*/ /* B206 SCKC - Set Clock Comparator [S] */ /*-------------------------------------------------------------------*/ DEF_INST(set_clock_comparator) { int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ U64 dreg; /* Clock value */ S(inst, regs, b2, effective_addr2); PRIV_CHECK(regs); DW_CHECK(effective_addr2, regs); #if defined(_FEATURE_SIE) if(SIE_STATB(regs, IC3, SCKC)) longjmp(regs->progjmp, SIE_INTERCEPT_INST); #endif /*defined(_FEATURE_SIE)*/ /* Fetch clock comparator value from operand location */ dreg = ARCH_DEP(vfetch8) ( effective_addr2, b2, regs ); // /*debug*/logmsg("Set clock comparator=%16.16" I64_FMT "X\n", dreg); dreg >>= 8; OBTAIN_INTLOCK(regs); regs->clkc = dreg; /* reset the clock comparator pending flag according to the setting of the tod clock */ if( tod_clock(regs) > dreg ) ON_IC_CLKC(regs); else OFF_IC_CLKC(regs); RELEASE_INTLOCK(regs); RETURN_INTCHECK(regs); } #if defined(FEATURE_EXTENDED_TOD_CLOCK) /*-------------------------------------------------------------------*/ /* 0107 SCKPF - Set Clock Programmable Field [E] */ /*-------------------------------------------------------------------*/ DEF_INST(set_clock_programmable_field) { E(inst, regs); UNREFERENCED(inst); PRIV_CHECK(regs); /* Program check if register 0 bits 0-15 are not zeroes */ if ( regs->GR_LHH(0) ) ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION); /* Set TOD programmable register from register 0 */ regs->todpr = regs->GR_LHL(0); } #endif /*defined(FEATURE_EXTENDED_TOD_CLOCK)*/ /*-------------------------------------------------------------------*/ /* B208 SPT - Set CPU Timer [S] */ /*-------------------------------------------------------------------*/ DEF_INST(set_cpu_timer) { int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ S64 dreg; /* Timer value */ S(inst, regs, b2, effective_addr2); PRIV_CHECK(regs); DW_CHECK(effective_addr2, regs); #if defined(_FEATURE_SIE) if(SIE_STATB(regs, IC3, SPT)) longjmp(regs->progjmp, SIE_INTERCEPT_INST); #endif /*defined(_FEATURE_SIE)*/ /* Fetch the CPU timer value from operand location */ dreg = ARCH_DEP(vfetch8) ( effective_addr2, b2, regs ); OBTAIN_INTLOCK(regs); set_cpu_timer(regs, dreg); /* reset the cpu timer pending flag according to its value */ if( CPU_TIMER(regs) < 0 ) ON_IC_PTIMER(regs); else OFF_IC_PTIMER(regs); RELEASE_INTLOCK(regs); // /*debug*/logmsg("Set CPU timer=%16.16" I64_FMT "X\n", dreg); RETURN_INTCHECK(regs); } /*-------------------------------------------------------------------*/ /* B210 SPX - Set Prefix [S] */ /*-------------------------------------------------------------------*/ DEF_INST(set_prefix) { int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ RADR n; /* Prefix value */ S(inst, regs, b2, effective_addr2); PRIV_CHECK(regs); SIE_INTERCEPT(regs); FW_CHECK(effective_addr2, regs); /* Perform serialization before fetching the operand */ PERFORM_SERIALIZATION (regs); /* Load new prefix value from operand address */ n = ARCH_DEP(vfetch4) ( effective_addr2, b2, regs ); /* Isolate bits 1-19 for ESA/390 or 1-18 for ESAME of new prefix value */ n &= PX_MASK; /* Program check if prefix is invalid absolute address */ if ( n > regs->mainlim ) ARCH_DEP(program_interrupt) (regs, PGM_ADDRESSING_EXCEPTION); /* Load new value into prefix register */ regs->PX = n; /* Set pointer to active PSA structure */ regs->psa = (PSA_3XX*)(regs->mainstor + regs->PX); /* Invalidate the ALB and TLB */ ARCH_DEP(purge_tlb) (regs); #if defined(FEATURE_ACCESS_REGISTERS) ARCH_DEP(purge_alb) (regs); #endif /*defined(FEATURE_ACCESS_REGISTERS)*/ /* Perform serialization after completing the operation */ PERFORM_SERIALIZATION (regs); } /*-------------------------------------------------------------------*/ /* B20A SPKA - Set PSW Key from Address [S] */ /*-------------------------------------------------------------------*/ DEF_INST(set_psw_key_from_address) { int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ int n; /* Storage key workarea */ BYTE pkey; /* Original key */ S(inst, regs, b2, effective_addr2); pkey = regs->psw.pkey; /* Isolate the key from bits 24-27 of effective address */ n = effective_addr2 & 0x000000F0; /* Privileged operation exception if in problem state and the corresponding PSW key mask bit is zero */ if ( PROBSTATE(®s->psw) && ((regs->CR(3) << (n >> 4)) & 0x80000000) == 0 ) ARCH_DEP(program_interrupt) (regs, PGM_PRIVILEGED_OPERATION_EXCEPTION); /* Set PSW key */ regs->psw.pkey = n; INVALIDATE_AIA(regs); } #if defined(FEATURE_DUAL_ADDRESS_SPACE) /*-------------------------------------------------------------------*/ /* Common processing routine for the SSAR and SSAIR instructions */ /*-------------------------------------------------------------------*/ void ARCH_DEP(set_secondary_asn_proc) (REGS *regs, int r1, int r2, int ssair_instruction) { U16 sasn; /* New Secondary ASN */ RADR sstd; /* Secondary STD */ U32 sasteo=0; /* Secondary ASTE origin */ U32 aste[16]; /* ASN second table entry */ U32 sastein; /* New Secondary ASTEIN */ U16 xcode; /* Exception code */ U16 ax; /* Authorization index */ #ifdef FEATURE_TRACING CREG newcr12 = 0; /* CR12 upon completion */ #endif /*FEATURE_TRACING*/ UNREFERENCED(r2); SIE_XC_INTERCEPT(regs); /* Perform serialization and checkpoint-synchronization */ PERFORM_SERIALIZATION (regs); PERFORM_CHKPT_SYNC (regs); /* Special operation exception if ASN translation control (bit 12 of control register 14) is zero or DAT is off */ if ((regs->CR(14) & CR14_ASN_TRAN) == 0 || REAL_MODE(&(regs->psw))) ARCH_DEP(program_interrupt) (regs, PGM_SPECIAL_OPERATION_EXCEPTION); /* Load the new ASN from R1 register bits 16-31 */ sasn = regs->GR_LHL(r1); #ifdef FEATURE_TRACING /* Form trace entry if ASN tracing is on */ if (regs->CR(12) & CR12_ASNTRACE) newcr12 = ARCH_DEP(trace_ssar) (ssair_instruction, sasn, regs); #endif /*FEATURE_TRACING*/ /* Test for SSAR/SSAIR to current primary */ if ( sasn == regs->CR_LHL(4) ) { /* Set new secondary STD equal to primary STD */ sstd = regs->CR(1); /* Set new secondary ASTEIN equal to primary ASTEIN */ sastein = regs->CR_H(4); } /* end if(SSAR-cp or SSAIR-cp) */ else { /* SSAR/SSAIR with space-switch */ /* Perform ASN translation to obtain ASTE */ xcode = ARCH_DEP(translate_asn) (sasn, regs, &sasteo, aste); /* Program check if ASN translation exception */ if (xcode != 0) ARCH_DEP(program_interrupt) (regs, xcode); /* For SSAR-ss only, generate a special operation exception if ASN-and-LX-reuse is enabled and the reusable-ASN bit in the ASTE is one */ if (ssair_instruction == 0 && ASN_AND_LX_REUSE_ENABLED(regs) && (aste[1] & ASTE1_RA) != 0) { ARCH_DEP(program_interrupt) (regs, PGM_SPECIAL_OPERATION_EXCEPTION); } /* end if (SSAR && ASN_AND_LX_REUSE_ENABLED && ASTE1_RA) */ /* For SSAIR-ss only, generate a special operation exception if the controlled-ASN bit in the ASTE is one and the CPU is in problem state */ if (ssair_instruction && (aste[1] & ASTE1_CA) != 0 && PROBSTATE(®s->psw)) { ARCH_DEP(program_interrupt) (regs, PGM_SPECIAL_OPERATION_EXCEPTION); } /* end if (SSAIR && ASTE1_CA && PROBSTATE) */ /* For SSAIR-ss only, generate an ASTE instance exception if the ASTEIN in bits 0-31 of the R1 register does not equal the ASTEIN in the ASTE */ if (ssair_instruction && aste[11] != regs->GR_H(r1)) { /* Set bit 3 of the exception access identification to indicate that the program check occurred during SASN translation in a SSAIR instruction */ regs->excarid = 0x10; ARCH_DEP(program_interrupt) (regs, PGM_ASTE_INSTANCE_EXCEPTION); } /* end if (SSAIR && ASTE11_ASTEIN != GR_H(r1)) */ /* Perform ASN authorization using current AX */ ax = regs->CR_LHH(4); if (ARCH_DEP(authorize_asn) (ax, aste, ATE_SECONDARY, regs)) { regs->TEA = sasn; ARCH_DEP(program_interrupt) (regs, PGM_SECONDARY_AUTHORITY_EXCEPTION); } /* Load new secondary STD or ASCE from the ASTE */ sstd = ASTE_AS_DESIGNATOR(aste); /* Load new secondary ASTEIN from the ASTE */ sastein = aste[11]; #ifdef FEATURE_SUBSPACE_GROUP /* Perform subspace replacement on new SSTD */ sstd = ARCH_DEP(subspace_replace) (sstd, sasteo, NULL, regs); #endif /*FEATURE_SUBSPACE_GROUP*/ } /* end if(SSAR-ss or SSAIR-ss) */ #ifdef FEATURE_TRACING /* Update trace table address if ASN tracing is on */ if (regs->CR(12) & CR12_ASNTRACE) regs->CR(12) = newcr12; #endif /*FEATURE_TRACING*/ /* Load the new secondary ASN into control register 3 */ regs->CR_LHL(3) = sasn; /* Load the new secondary STD into control register 7 */ regs->CR(7) = sstd; /* For SSAIR, and for SSAR when ASN-and-LX-reuse is enabled, load the new secondary ASTEIN into control register 3 */ if (ssair_instruction || ASN_AND_LX_REUSE_ENABLED(regs)) { regs->CR_H(3) = sastein; } /* end if (SSAIR || ASN_AND_LX_REUSE_ENABLED) */ /* Perform serialization and checkpoint-synchronization */ PERFORM_SERIALIZATION (regs); PERFORM_CHKPT_SYNC (regs); } /* end ARCH_DEP(set_secondary_asn_proc) */ /*-------------------------------------------------------------------*/ /* B225 SSAR - Set Secondary ASN [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(set_secondary_asn) { int r1, r2; /* Values of R fields */ RRE(inst, regs, r1, r2); ARCH_DEP(set_secondary_asn_proc) (regs, r1, r2, 0); } /* end DEF_INST(set_secondary_asn) */ #endif /*defined(FEATURE_DUAL_ADDRESS_SPACE)*/ #if defined(FEATURE_ASN_AND_LX_REUSE) /*-------------------------------------------------------------------*/ /* B99F SSAIR - Set Secondary ASN with Instance [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(set_secondary_asn_with_instance) { int r1, r2; /* Values of R fields */ if(!sysblk.asnandlxreuse) { ARCH_DEP(operation_exception)(inst,regs); } RRE(inst, regs, r1, r2); ARCH_DEP(set_secondary_asn_proc) (regs, r1, r2, 1); } /* end DEF_INST(set_secondary_asn_with_instance) */ #endif /*defined(FEATURE_ASN_AND_LX_REUSE)*/ #if defined(FEATURE_BASIC_STORAGE_KEYS) /*-------------------------------------------------------------------*/ /* 08 SSK - Set Storage Key [RR] */ /*-------------------------------------------------------------------*/ DEF_INST(set_storage_key) { int r1, r2; /* Values of R fields */ RADR n; /* Absolute storage addr */ RR(inst, regs, r1, r2); PRIV_CHECK(regs); #if defined(FEATURE_4K_STORAGE_KEYS) || defined(_FEATURE_SIE) if( #if defined(_FEATURE_SIE) && !defined(FEATURE_4K_STORAGE_KEYS) SIE_MODE(regs) && #endif !(regs->CR(0) & CR0_STORKEY_4K) ) ARCH_DEP(program_interrupt) (regs, PGM_SPECIAL_OPERATION_EXCEPTION); #endif /* Program check if R2 bits 28-31 are not zeroes */ if ( regs->GR_L(r2) & 0x0000000F ) ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION); /* Load 2K block address from R2 register */ n = regs->GR_L(r2) & 0x00FFF800; /* Convert real address to absolute address */ n = APPLY_PREFIXING (n, regs->PX); /* Addressing exception if block is outside main storage */ if ( n > regs->mainlim ) ARCH_DEP(program_interrupt) (regs, PGM_ADDRESSING_EXCEPTION); #if defined(_FEATURE_SIE) if(SIE_MODE(regs)) { if(SIE_STATB(regs, IC2, SSKE)) longjmp(regs->progjmp, SIE_INTERCEPT_INST); if(!regs->sie_pref) { #if defined(_FEATURE_STORAGE_KEY_ASSIST) if(SIE_STATB(regs, RCPO0, SKA) && SIE_STATB(regs, RCPO2, RCPBY)) { SIE_TRANSLATE(&n, ACCTYPE_SIE, regs); } else #endif /*defined(_FEATURE_STORAGE_KEY_ASSIST)*/ { int sr; BYTE realkey, rcpkey; RADR rcpa; #if defined(_FEATURE_STORAGE_KEY_ASSIST) if(SIE_STATB(regs, RCPO0, SKA)) { /* guest absolute to host PTE addr */ if (SIE_TRANSLATE_ADDR (regs->sie_mso + n, USE_PRIMARY_SPACE, regs->hostregs, ACCTYPE_PTE)) longjmp(regs->progjmp, SIE_INTERCEPT_INST); /* Convert real address to absolute address */ rcpa = APPLY_PREFIXING (regs->hostregs->dat.raddr, regs->hostregs->PX); /* The reference and change byte is located directly beyond the page table and is located at offset 1 in the entry. S/370 mode cannot be emulated in ESAME mode, so no provision is made for ESAME mode tables */ rcpa += 1025; } else #endif /*defined(_FEATURE_STORAGE_KEY_ASSIST)*/ { /* Obtain address of the RCP area from the state desc */ rcpa = regs->sie_rcpo &= 0x7FFFF000; /* frame index as byte offset to 4K keys in RCP area */ rcpa += n >> 12; /* host primary to host absolute */ rcpa = SIE_LOGICAL_TO_ABS (rcpa, USE_PRIMARY_SPACE, regs->hostregs, ACCTYPE_SIE, 0); } /* guest absolute to host real */ sr = SIE_TRANSLATE_ADDR (regs->sie_mso + n, USE_PRIMARY_SPACE, regs->hostregs, ACCTYPE_SIE); if (sr #if defined(_FEATURE_STORAGE_KEY_ASSIST) && !SIE_FEATB(regs, RCPO0, SKA) #endif /*defined(_FEATURE_STORAGE_KEY_ASSIST)*/ ) longjmp(regs->progjmp, SIE_INTERCEPT_INST); #if defined(_FEATURE_STORAGE_KEY_ASSIST) if (sr) realkey = 0; else #endif /*defined(_FEATURE_STORAGE_KEY_ASSIST)*/ { /* host real to host absolute */ n = APPLY_PREFIXING(regs->hostregs->dat.raddr, regs->hostregs->PX); realkey = #if !defined(_FEATURE_2K_STORAGE_KEYS) STORAGE_KEY(n, regs) #else (STORAGE_KEY1(n, regs) | STORAGE_KEY2(n, regs)) #endif & (STORKEY_REF | STORKEY_CHANGE); } /* fetch the RCP key */ rcpkey = regs->mainstor[rcpa]; STORAGE_KEY(rcpa, regs) |= STORKEY_REF; /* or with host set */ rcpkey |= realkey << 4; /* or new settings with guest set */ rcpkey &= ~(STORKEY_REF | STORKEY_CHANGE); rcpkey |= regs->GR_L(r1) & (STORKEY_REF | STORKEY_CHANGE); regs->mainstor[rcpa] = rcpkey; STORAGE_KEY(rcpa, regs) |= (STORKEY_REF|STORKEY_CHANGE); #if defined(_FEATURE_STORAGE_KEY_ASSIST) /* Insert key in new storage key */ if(SIE_STATB(regs, RCPO0, SKA)) regs->mainstor[rcpa-1] = regs->GR_LHLCL(r1) & (STORKEY_KEY | STORKEY_FETCH); if(!sr) #endif /*defined(_FEATURE_STORAGE_KEY_ASSIST)*/ { #if !defined(_FEATURE_2K_STORAGE_KEYS) STORAGE_KEY(n, regs) &= STORKEY_BADFRM; STORAGE_KEY(n, regs) |= regs->GR_LHLCL(r1) & (STORKEY_KEY | STORKEY_FETCH); #else STORAGE_KEY1(n, regs) &= STORKEY_BADFRM; STORAGE_KEY1(n, regs) |= regs->GR_LHLCL(r1) & (STORKEY_KEY | STORKEY_FETCH); STORAGE_KEY2(n, regs) &= STORKEY_BADFRM; STORAGE_KEY2(n, regs) |= regs->GR_LHLCL(r1) & (STORKEY_KEY | STORKEY_FETCH); #endif } } } else { /* Update the storage key from R1 register bits 24-30 */ #if !defined(_FEATURE_2K_STORAGE_KEYS) STORAGE_KEY(n, regs) &= STORKEY_BADFRM; STORAGE_KEY(n, regs) |= regs->GR_LHLCL(r1) & ~(STORKEY_BADFRM); #else STORAGE_KEY1(n, regs) &= STORKEY_BADFRM; STORAGE_KEY1(n, regs) |= regs->GR_LHLCL(r1) & ~(STORKEY_BADFRM); STORAGE_KEY2(n, regs) &= STORKEY_BADFRM; STORAGE_KEY2(n, regs) |= regs->GR_LHLCL(r1) & ~(STORKEY_BADFRM); #endif } } else #endif /*defined(_FEATURE_SIE)*/ { /* Update the storage key from R1 register bits 24-30 */ #if defined(_FEATURE_2K_STORAGE_KEYS) STORAGE_KEY(n, regs) &= STORKEY_BADFRM; STORAGE_KEY(n, regs) |= regs->GR_LHLCL(r1) & ~(STORKEY_BADFRM); #else STORAGE_KEY1(n, regs) &= STORKEY_BADFRM; STORAGE_KEY1(n, regs) |= regs->GR_LHLCL(r1) & ~(STORKEY_BADFRM); STORAGE_KEY2(n, regs) &= STORKEY_BADFRM; STORAGE_KEY2(n, regs) |= regs->GR_LHLCL(r1) & ~(STORKEY_BADFRM); #endif } STORKEY_INVALIDATE(regs, n); // /*debug*/logmsg("SSK storage block %8.8X key %2.2X\n", // /*debug*/ regs->GR_L(r2), regs->GR_LHLCL(r1) & 0xFE); } /* end DEF_INST(set_storage_key) */ #endif /*defined(FEATURE_BASIC_STORAGE_KEYS)*/ #if defined(FEATURE_EXTENDED_STORAGE_KEYS) #if defined(FEATURE_CONDITIONAL_SSKE) /*-------------------------------------------------------------------*/ /* SUBROUTINE TO PERFORM CONDITIONAL SSKE PROCESSING */ /* Input: */ /* regs Register context */ /* r1 Register number field from SSKE instruction */ /* m3 Mask field from SSKE instruction */ /* skey Contents of storage key before modification */ /* Output (when conditional SSKE is not indicated): */ /* r1 register and condition code remain unchanged; */ /* The function return value is 0. */ /* Output (when conditional SSKE is indicated): */ /* r1 register bits 48-55 contain original storage key; */ /* - if storage key is to be updated, the condition code */ /* is set to 1 and the function return value is 0; */ /* - if storage key update is to be bypassed, the condition */ /* code is set to 0 and the function return value is 1; */ /*-------------------------------------------------------------------*/ static inline int ARCH_DEP(conditional_sske_procedure) (REGS *regs, int r1, int m3, BYTE skey) { /* Perform normal SSKE if MR and MC bits are both zero */ if ((m3 & (SSKE_MASK_MR | SSKE_MASK_MC)) == 0) return 0; /* Perform conditional SSKE if either MR or MC bits are set */ /* Insert storage key into R1 register bits 48-55 */ regs->GR_LHLCH(r1) = skey & ~(STORKEY_BADFRM); /* If storage key and fetch bit do not equal new values in R1 register bits 56-60 then set condition code 1 and return to SSKE to update storage key */ if ((regs->GR_LHLCH(r1) & (STORKEY_KEY | STORKEY_FETCH)) != (regs->GR_LHLCL(r1) & (STORKEY_KEY | STORKEY_FETCH))) { regs->psw.cc = 1; return 0; } /* If both MR and MC mask bits are one then set condition code 0 and leave storage key unchanged */ if ((m3 & (SSKE_MASK_MR | SSKE_MASK_MC)) == (SSKE_MASK_MR | SSKE_MASK_MC)) { regs->psw.cc = 0; return 1; } /* If MR bit is zero and reference bit is equal to bit 61 of R1 register then set condition code 0 and leave storage key unchanged */ if ((m3 & SSKE_MASK_MR) == 0 && ((regs->GR_LHLCH(r1) & STORKEY_REF) == (regs->GR_LHLCL(r1) & STORKEY_REF))) { regs->psw.cc = 0; return 1; } /* If MC bit is zero and the change bit is equal to bit 62 of R1 register then set condition code 0 and leave storage key unchanged */ if ((m3 & SSKE_MASK_MC) == 0 && ((regs->GR_LHLCH(r1) & STORKEY_CHANGE) == (regs->GR_LHLCL(r1) & STORKEY_CHANGE))) { regs->psw.cc = 0; return 1; } /* Set condition code 1 and let SSKE update storage key */ regs->psw.cc = 1; return 0; } /* end function conditional_sske_procedure */ #endif /*defined(FEATURE_CONDITIONAL_SSKE)*/ #endif /*defined(FEATURE_EXTENDED_STORAGE_KEYS)*/ #if defined(FEATURE_EXTENDED_STORAGE_KEYS) /*-------------------------------------------------------------------*/ /* B22B SSKE - Set Storage Key extended [RRF] */ /*-------------------------------------------------------------------*/ DEF_INST(set_storage_key_extended) { int r1, r2; /* Register numbers */ int m3; /* Mask field */ RADR n; /* Abs frame addr stor key */ RRF_M(inst, regs, r1, r2, m3); PRIV_CHECK(regs); /* Load 4K block address from R2 register */ n = regs->GR(r2) & ADDRESS_MAXWRAP_E(regs); /* Perform serialization and checkpoint-synchronization */ PERFORM_SERIALIZATION (regs); PERFORM_CHKPT_SYNC (regs); /* Convert real address to absolute address */ n = APPLY_PREFIXING (n, regs->PX); /* Addressing exception if block is outside main storage */ if ( n > regs->mainlim ) ARCH_DEP(program_interrupt) (regs, PGM_ADDRESSING_EXCEPTION); #if defined(_FEATURE_SIE) if(SIE_MODE(regs)) { if(SIE_STATB(regs, IC2, SSKE)) longjmp(regs->progjmp, SIE_INTERCEPT_INST); if(!regs->sie_pref) { #if defined(_FEATURE_STORAGE_KEY_ASSIST) if ((SIE_STATB(regs, RCPO0, SKA) #if defined(_FEATURE_ZSIE) || (regs->hostregs->arch_mode == ARCH_900) #endif /*defined(_FEATURE_ZSIE)*/ ) && SIE_STATB(regs, RCPO2, RCPBY)) { SIE_TRANSLATE(&n, ACCTYPE_SIE, regs); } else #endif /*defined(_FEATURE_STORAGE_KEY_ASSIST)*/ { int sr; BYTE realkey, rcpkey, protkey; RADR rcpa; #if defined(_FEATURE_STORAGE_KEY_ASSIST) if(SIE_STATB(regs, RCPO0, SKA) #if defined(_FEATURE_ZSIE) || (regs->hostregs->arch_mode == ARCH_900) #endif /*defined(_FEATURE_ZSIE)*/ ) { /* guest absolute to host PTE addr */ if (SIE_TRANSLATE_ADDR (regs->sie_mso + n, USE_PRIMARY_SPACE, regs->hostregs, ACCTYPE_PTE)) longjmp(regs->progjmp, SIE_INTERCEPT_INST); /* Convert real address to absolute address */ rcpa = APPLY_PREFIXING (regs->hostregs->dat.raddr, regs->hostregs->PX); /* For ESA/390 the RCP byte entry is at offset 1 in a four byte entry directly beyond the page table, for ESAME mode, this entry is eight bytes long */ rcpa += regs->hostregs->arch_mode == ARCH_900 ? 2049 : 1025; } else #endif /*defined(_FEATURE_STORAGE_KEY_ASSIST)*/ { #if defined(FEATURE_MULTIPLE_CONTROLLED_DATA_SPACE) if(SIE_STATB(regs, MX, XC)) longjmp(regs->progjmp, SIE_INTERCEPT_INST); #endif /*defined(FEATURE_MULTIPLE_CONTROLLED_DATA_SPACE)*/ /* Obtain address of the RCP area from the state desc */ rcpa = regs->sie_rcpo &= 0x7FFFF000; /* frame index as byte offset to 4K keys in RCP area */ rcpa += n >> 12; /* host primary to host absolute */ rcpa = SIE_LOGICAL_TO_ABS (rcpa, USE_PRIMARY_SPACE, regs->hostregs, ACCTYPE_SIE, 0); } /* guest absolute to host real */ sr = SIE_TRANSLATE_ADDR (regs->sie_mso + n, USE_PRIMARY_SPACE, regs->hostregs, ACCTYPE_SIE); if (sr #if defined(_FEATURE_STORAGE_KEY_ASSIST) && !(SIE_FEATB(regs, RCPO0, SKA) #if defined(_FEATURE_ZSIE) || (regs->hostregs->arch_mode == ARCH_900) #endif /*defined(_FEATURE_ZSIE)*/ ) #endif /*defined(_FEATURE_STORAGE_KEY_ASSIST)*/ ) longjmp(regs->progjmp, SIE_INTERCEPT_INST); /* fetch the RCP key */ rcpkey = regs->mainstor[rcpa]; /* set the reference bit in the RCP key */ STORAGE_KEY(rcpa, regs) |= STORKEY_REF; #if defined(_FEATURE_STORAGE_KEY_ASSIST) if(sr) { realkey = 0; protkey = rcpkey & (STORKEY_REF | STORKEY_CHANGE); /* rcpa-1 is correct here - would have been SIE Intercepted otherwise */ protkey |= regs->mainstor[rcpa-1] & (STORKEY_KEY | STORKEY_FETCH); } else #endif /*defined(_FEATURE_STORAGE_KEY_ASSIST)*/ { /* host real to host absolute */ n = APPLY_PREFIXING(regs->hostregs->dat.raddr, regs->hostregs->PX); protkey = #if !defined(_FEATURE_2K_STORAGE_KEYS) STORAGE_KEY(n, regs) #else (STORAGE_KEY1(n, regs) | STORAGE_KEY2(n, regs)) #endif ; realkey = protkey & (STORKEY_REF | STORKEY_CHANGE); } #if defined(FEATURE_CONDITIONAL_SSKE) /* Perform conditional SSKE procedure */ if (ARCH_DEP(conditional_sske_procedure)(regs, r1, m3, protkey)) return; #endif /*defined(FEATURE_CONDITIONAL_SSKE)*/ /* or with host set */ rcpkey |= realkey << 4; /* insert new settings of the guest set */ rcpkey &= ~(STORKEY_REF | STORKEY_CHANGE); rcpkey |= regs->GR_LHLCL(r1) & (STORKEY_REF | STORKEY_CHANGE); regs->mainstor[rcpa] = rcpkey; STORAGE_KEY(rcpa, regs) |= (STORKEY_REF|STORKEY_CHANGE); #if defined(_FEATURE_STORAGE_KEY_ASSIST) /* Insert key in new storage key */ if(SIE_STATB(regs, RCPO0, SKA) #if defined(_FEATURE_ZSIE) || (regs->hostregs->arch_mode == ARCH_900) #endif /*defined(_FEATURE_ZSIE)*/ ) regs->mainstor[rcpa-1] = regs->GR_LHLCL(r1) & (STORKEY_KEY | STORKEY_FETCH); if(!sr) #endif /*defined(_FEATURE_STORAGE_KEY_ASSIST)*/ { #if !defined(_FEATURE_2K_STORAGE_KEYS) STORAGE_KEY(n, regs) &= STORKEY_BADFRM; STORAGE_KEY(n, regs) |= regs->GR_LHLCL(r1) & (STORKEY_KEY | STORKEY_FETCH); #else STORAGE_KEY1(n, regs) &= STORKEY_BADFRM; STORAGE_KEY1(n, regs) |= regs->GR_LHLCL(r1) & (STORKEY_KEY | STORKEY_FETCH); STORAGE_KEY2(n, regs) &= STORKEY_BADFRM; STORAGE_KEY2(n, regs) |= regs->GR_LHLCL(r1) & (STORKEY_KEY | STORKEY_FETCH); #endif } } } else { #if defined(FEATURE_CONDITIONAL_SSKE) /* Perform conditional SSKE procedure */ if (ARCH_DEP(conditional_sske_procedure)(regs, r1, m3, #if defined(FEATURE_4K_STORAGE_KEYS) && !defined(_FEATURE_2K_STORAGE_KEYS) STORAGE_KEY(n, regs) #else (STORAGE_KEY1(n, regs) | STORAGE_KEY2(n, regs)) #endif )) return; #endif /*defined(FEATURE_CONDITIONAL_SSKE)*/ /* Update the storage key from R1 register bits 24-30 */ #if !defined(_FEATURE_2K_STORAGE_KEYS) STORAGE_KEY(n, regs) &= STORKEY_BADFRM; STORAGE_KEY(n, regs) |= regs->GR_LHLCL(r1) & ~(STORKEY_BADFRM); #else STORAGE_KEY1(n, regs) &= STORKEY_BADFRM; STORAGE_KEY1(n, regs) |= regs->GR_LHLCL(r1) & ~(STORKEY_BADFRM); STORAGE_KEY2(n, regs) &= STORKEY_BADFRM; STORAGE_KEY2(n, regs) |= regs->GR_LHLCL(r1) & ~(STORKEY_BADFRM); #endif } } else #endif /*defined(_FEATURE_SIE)*/ { #if defined(FEATURE_CONDITIONAL_SSKE) /* Perform conditional SSKE procedure */ if (ARCH_DEP(conditional_sske_procedure)(regs, r1, m3, #if defined(FEATURE_4K_STORAGE_KEYS) && !defined(_FEATURE_2K_STORAGE_KEYS) STORAGE_KEY(n, regs) #else (STORAGE_KEY1(n, regs) | STORAGE_KEY2(n, regs)) #endif )) return; #endif /*defined(FEATURE_CONDITIONAL_SSKE)*/ /* Update the storage key from R1 register bits 24-30 */ #if defined(FEATURE_4K_STORAGE_KEYS) && !defined(_FEATURE_2K_STORAGE_KEYS) STORAGE_KEY(n, regs) &= STORKEY_BADFRM; STORAGE_KEY(n, regs) |= regs->GR_LHLCL(r1) & ~(STORKEY_BADFRM); #else STORAGE_KEY1(n, regs) &= STORKEY_BADFRM; STORAGE_KEY1(n, regs) |= regs->GR_LHLCL(r1) & ~(STORKEY_BADFRM); STORAGE_KEY2(n, regs) &= STORKEY_BADFRM; STORAGE_KEY2(n, regs) |= regs->GR_LHLCL(r1) & ~(STORKEY_BADFRM); #endif } /* Perform serialization and checkpoint-synchronization */ PERFORM_SERIALIZATION (regs); PERFORM_CHKPT_SYNC (regs); /* Invalidate AIA/AEA so that the REF and CHANGE bits will be set when referenced next */ STORKEY_INVALIDATE(regs, n); } /* end DEF_INST(set_storage_key_extended) */ #endif /*defined(FEATURE_EXTENDED_STORAGE_KEYS)*/ /*-------------------------------------------------------------------*/ /* 80 SSM - Set System Mask [S] */ /*-------------------------------------------------------------------*/ DEF_INST(set_system_mask) { int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ S(inst, regs, b2, effective_addr2); /* * ECPS:VM - Before checking for prob/priv * Check CR6 to see if S-ASSIST is requested * * If we can process it, then do it */ #if defined(FEATURE_ECPSVM) if(ecpsvm_dossm(regs,b2,effective_addr2)==0) { return; } #endif PRIV_CHECK(regs); /* Special operation exception if SSM-suppression is active */ if ( (regs->CR(0) & CR0_SSM_SUPP) #if defined(FEATURE_MULTIPLE_CONTROLLED_DATA_SPACE) /* SSM-suppression is ignored in XC mode */ && !SIE_STATB(regs, MX, XC) #endif /*defined(FEATURE_MULTIPLE_CONTROLLED_DATA_SPACE)*/ ) ARCH_DEP(program_interrupt) (regs, PGM_SPECIAL_OPERATION_EXCEPTION); #if defined(_FEATURE_SIE) if(SIE_STATB(regs, IC1, SSM)) longjmp(regs->progjmp, SIE_INTERCEPT_INST); #endif /*defined(_FEATURE_SIE)*/ /* Load new system mask value from operand address */ regs->psw.sysmask = ARCH_DEP(vfetchb) ( effective_addr2, b2, regs ); #if defined(FEATURE_MULTIPLE_CONTROLLED_DATA_SPACE) /* DAT must be off in XC mode */ if(SIE_STATB(regs, MX, XC) && (regs->psw.sysmask & PSW_DATMODE) ) ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION); #endif /*defined(FEATURE_MULTIPLE_CONTROLLED_DATA_SPACE)*/ /* For ECMODE, bits 0 and 2-4 of system mask must be zero */ if ((regs->psw.sysmask & 0xB8) != 0 #if defined(FEATURE_BCMODE) && ECMODE(®s->psw) #endif /*defined(FEATURE_BCMODE)*/ ) ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION); SET_IC_MASK(regs); TEST_SET_AEA_MODE(regs); RETURN_INTCHECK(regs); } /* end DEF_INST(set_system_mask) */ /*-------------------------------------------------------------------*/ /* AE SIGP - Signal Processor [RS] */ /*-------------------------------------------------------------------*/ DEF_INST(signal_procesor) { int r1, r3; /* Register numbers */ int b2; /* effective address base */ VADR effective_addr2; /* effective address */ REGS *tregs; /* -> Target CPU registers */ GREG parm; /* Signal parameter */ GREG status = 0; /* Signal status */ RADR abs; /* Absolute address */ U16 cpad; /* Target CPU address */ BYTE order; /* SIGP order code */ #if defined(_900) || defined(FEATURE_ESAME) || defined(FEATURE_HERCULES_DIAGCALLS) int cpu; /* cpu number */ int set_arch = 0; /* Need to switch mode */ #endif /*defined(_900) || defined(FEATURE_ESAME)*/ size_t log_sigp = 0; /* Log SIGP instruction flag */ char log_buf[128]; /* Log buffer */ static char *ordername[] = { /* 0x00 */ "Unassigned", /* 0x01 SIGP_SENSE */ "Sense", /* 0x02 SIGP_EXTCALL */ "External call", /* 0x03 SIGP_EMERGENCY */ "Emergency signal", /* 0x04 SIGP_START */ "Start", /* 0x05 SIGP_STOP */ "Stop", /* 0x06 SIGP_RESTART */ "Restart", /* 0x07 SIGP_IPR */ "Initial program reset", /* 0x08 SIGP_PR */ "Program reset", /* 0x09 SIGP_STOPSTORE */ "Stop and store status", /* 0x0A SIGP_IMPL */ "Initial microprogram load", /* 0x0B SIGP_INITRESET */ "Initial CPU reset", /* 0x0C SIGP_RESET */ "CPU reset", /* 0x0D SIGP_SETPREFIX */ "Set prefix", /* 0x0E SIGP_STORE */ "Store status", /* 0x0F */ "Unassigned", /* 0x10 */ "Unassigned", /* 0x11 SIGP_STOREX */ "Store extended status at address", /* 0x12 SIGP_SETARCH */ "Set architecture mode", /* 0x13 SIGP_COND_EMERGENCY */ "Conditional emergency", /* 0x14 */ "Unassigned", /* 0x15 SIGP_SENSE_RUNNING_STATE */ "Sense running state" }; RS(inst, regs, r1, r3, b2, effective_addr2); PRIV_CHECK(regs); SIE_INTERCEPT(regs); PTT(PTT_CL_SIG,"SIGP",regs->GR_L(r1),regs->GR_L(r3),(U32)(effective_addr2 & 0xffffffff)); /* Perform serialization before starting operation */ PERFORM_SERIALIZATION (regs); /* Load the order code from operand address bits 24-31 */ order = effective_addr2 & 0xFF; /* Load the target CPU address from R3 bits 16-31 */ cpad = (order != SIGP_SETARCH) ? regs->GR_LHL(r3) : regs->cpuad; /* Load the parameter from R1 (if R1 odd), or R1+1 (if even) */ parm = (r1 & 1) ? regs->GR_L(r1) : regs->GR_L(r1+1); /* Return condition code 3 if target CPU does not exist */ if (cpad >= MAX_CPU) { PTT(PTT_CL_ERR,"*SIGP",regs->GR_L(r1),regs->GR_L(r3),(U32)(effective_addr2 & 0xffffffff)); regs->psw.cc = 3; return; } /* Issuing Sense to an offline CPU that is >= numcpu or HI_CPU is not now considered unusual especially since we have increased the default max CPU number to 8 */ if (order == SIGP_SENSE && !IS_CPU_ONLINE(cpad) && cpad >= sysblk.numcpu && cpad >= HI_CPU) { PTT(PTT_CL_ERR,"*SIGP",regs->GR_L(r1),regs->GR_L(r3),(U32)(effective_addr2 & 0xffffffff)); regs->psw.cc = 3; return; } /* Trace SIGP unless Sense, External Call, Emergency Signal, Sense Running State, or the target CPU is configured offline */ if ((order > LOG_SIGPORDER && order != SIGP_SENSE_RUNNING_STATE) || !IS_CPU_ONLINE(cpad)) { log_sigp = snprintf ( log_buf, sizeof(log_buf), "CPU%4.4X: SIGP %s (%2.2X) CPU%4.4X, PARM "F_GREG, regs->cpuad, order >= sizeof(ordername) / sizeof(ordername[0]) ? "Unassigned" : ordername[order], order, cpad, parm); } /* [4.9.2.1] Claim the use of the CPU signaling and response facility, and return condition code 2 if the facility is busy. The sigplock is held while the facility is in use by any CPU. */ if(try_obtain_lock (&sysblk.sigplock)) { regs->psw.cc = 2; if (log_sigp) logmsg("%s: CC 2\n",log_buf); return; } /* Obtain the interrupt lock */ OBTAIN_INTLOCK(regs); /* If the cpu is not part of the configuration then return cc3 Initial CPU reset may IML a processor that is currently not part of the configuration, ie configure the cpu implicitly online */ if (order != SIGP_INITRESET #if defined(FEATURE_S370_CHANNEL) && order != SIGP_IMPL #endif /*defined(FEATURE_S370_CHANNEL)*/ && !IS_CPU_ONLINE(cpad)) { RELEASE_INTLOCK(regs); release_lock(&sysblk.sigplock); regs->psw.cc = 3; if (log_sigp) logmsg("%s: CC 3\n",log_buf); return; } /* Point to the target CPU -- may be NULL if INITRESET or IMPL */ tregs = sysblk.regs[cpad]; /* Except for the reset orders, return condition code 2 if the target CPU is executing a previous start, stop, restart, stop and store status, set prefix, or store status order */ if ((order != SIGP_RESET #if defined(FEATURE_S370_CHANNEL) && order != SIGP_IMPL && order != SIGP_IPR #endif /*defined(FEATURE_S370_CHANNEL)*/ && order != SIGP_INITRESET) && (tregs) && (tregs->cpustate == CPUSTATE_STOPPING || IS_IC_RESTART(tregs))) { RELEASE_INTLOCK(regs); release_lock(&sysblk.sigplock); regs->psw.cc = 2; if (log_sigp) logmsg("%s: CC 2\n",log_buf); sched_yield(); return; } /* The operator-intervening condition, when present, can be indicated in response to all orders, and is indicated in response to sense if it precludes the acceptance of any of the installed orders (which is always true in our case), but cannot arise as a result of a SIGP instruction executed by a CPU addressing itself. */ if (1 && order != SIGP_SENSE // if this isn't a sense, && cpad != regs->cpuad // and we're not addressing ourselves, && (tregs) && tregs->opinterv // and operator intervening condition... ) { // ...then we cannot proceed status |= SIGP_STATUS_OPERATOR_INTERVENING; } else /* (order == SIGP_SENSE || cpad == regs->cpuad || ((tregs) && !tregs->opinterv)) */ /* Process signal according to order code */ switch (order) { case SIGP_SENSE: /* Set status bit 24 if external call interrupt pending */ if (IS_IC_EXTCALL(tregs)) status |= SIGP_STATUS_EXTERNAL_CALL_PENDING; /* Set status bit 25 if target CPU is stopped */ if (tregs->cpustate != CPUSTATE_STARTED) status |= SIGP_STATUS_STOPPED; /* Test for checkstop state */ if(tregs->checkstop) status |= SIGP_STATUS_CHECK_STOP; /* Test for operator intervening state */ if(cpad != regs->cpuad && tregs->opinterv) status |= SIGP_STATUS_OPERATOR_INTERVENING; break; case SIGP_EXTCALL: /* Test for checkstop state */ if(tregs->checkstop) { status |= SIGP_STATUS_CHECK_STOP; break; } /* Exit with status bit 24 set if a previous external call interrupt is still pending in the target CPU */ if (IS_IC_EXTCALL(tregs)) { status |= SIGP_STATUS_EXTERNAL_CALL_PENDING; break; } /* Raise an external call interrupt pending condition */ ON_IC_EXTCALL(tregs); tregs->extccpu = regs->cpuad; break; #if defined(_900) || defined(FEATURE_ESAME) case SIGP_COND_EMERGENCY: /* Test for checkstop state */ if(tregs->checkstop) status |= SIGP_STATUS_CHECK_STOP; else { U16 check_asn = (parm & 0xFFFF); SET_PSW_IA(tregs); if (0 /* PSW disabled for external interruptions, I/O interruptions, or both */ || (!(tregs->psw.sysmask & PSW_EXTMASK) || !(tregs->psw.sysmask & PSW_IOMASK)) /* CPU in wait state and the PSW instruction address not zero */ || ( WAITSTATE( &tregs->psw ) && tregs->psw.IA ) /* CPU not in wait state and check_asn value equals an ASN of the CPU (primary, secondary or both) -- regardless of the setting of PSW bits 16-17 */ || (1 && !WAITSTATE( &tregs->psw ) && (check_asn == tregs->CR_LHL(3) || check_asn == tregs->CR_LHL(4)) ) ) { /* Raise an emergency signal interrupt pending condition */ tregs->emercpu[regs->cpuad] = 1; ON_IC_EMERSIG(tregs); } else status |= SIGP_STATUS_INCORRECT_STATE; } break; #endif /* defined(_900) || defined(FEATURE_ESAME) */ case SIGP_EMERGENCY: /* Test for checkstop state */ if(tregs->checkstop) { status |= SIGP_STATUS_CHECK_STOP; break; } /* Raise an emergency signal interrupt pending condition */ ON_IC_EMERSIG(tregs); tregs->emercpu[regs->cpuad] = 1; break; case SIGP_START: /* Test for checkstop state */ if(tregs->checkstop) { status |= SIGP_STATUS_CHECK_STOP; break; } /* Restart the target CPU if it is in the stopped state */ tregs->cpustate = CPUSTATE_STARTED; break; case SIGP_STOP: /* Test for checkstop state */ if(tregs->checkstop) { status |= SIGP_STATUS_CHECK_STOP; break; } /* Put the the target CPU into the stopping state */ tregs->cpustate = CPUSTATE_STOPPING; ON_IC_INTERRUPT(tregs); break; case SIGP_RESTART: /* Test for checkstop state */ if(tregs->checkstop) { status |= SIGP_STATUS_CHECK_STOP; break; } /* Make restart interrupt pending in the target CPU */ ON_IC_RESTART(tregs); /* Set cpustate to stopping. If the restart is successful, then the cpustate will be set to started in cpu.c */ if(tregs->cpustate == CPUSTATE_STOPPED) tregs->cpustate = CPUSTATE_STOPPING; break; case SIGP_STOPSTORE: /* Test for checkstop state */ if(tregs->checkstop) { status |= SIGP_STATUS_CHECK_STOP; break; } /* Indicate store status is required when stopped */ ON_IC_STORSTAT(tregs); /* Put the the target CPU into the stopping state */ tregs->cpustate = CPUSTATE_STOPPING; ON_IC_INTERRUPT(tregs); break; #if defined(FEATURE_S370_CHANNEL) case SIGP_IMPL: case SIGP_IPR: #endif /* defined(FEATURE_S370_CHANNEL) */ case SIGP_INITRESET: if (!IS_CPU_ONLINE(cpad)) { configure_cpu(cpad); if (!IS_CPU_ONLINE(cpad)) { status |= SIGP_STATUS_OPERATOR_INTERVENING; break; } tregs = sysblk.regs[cpad]; } #if defined(FEATURE_S370_CHANNEL) if (order == SIGP_IMPL || order == SIGP_IPR) channelset_reset(tregs); #endif /* defined(FEATURE_S370_CHANNEL) */ /* Signal initial CPU reset function */ tregs->sigpireset = 1; tregs->cpustate = CPUSTATE_STOPPING; ON_IC_INTERRUPT(tregs); break; #if defined(FEATURE_S370_CHANNEL) case SIGP_PR: channelset_reset(tregs); /* fallthrough*/ #endif /* defined(FEATURE_S370_CHANNEL) */ case SIGP_RESET: /* Signal CPU reset function */ tregs->sigpreset = 1; tregs->cpustate = CPUSTATE_STOPPING; ON_IC_INTERRUPT(tregs); break; case SIGP_SETPREFIX: /* Test for checkstop state */ if(tregs->checkstop) { status |= SIGP_STATUS_CHECK_STOP; break; } /* Exit with operator intervening if the status is stopping, such that a retry can be attempted */ if(tregs->cpustate == CPUSTATE_STOPPING) { status |= SIGP_STATUS_OPERATOR_INTERVENING; break; } /* Exit with status bit 22 set if CPU is not stopped */ if (tregs->cpustate != CPUSTATE_STOPPED) { status |= SIGP_STATUS_INCORRECT_STATE; break; } /* Obtain new prefix from parameter register bits 1-19 or bits 1-18 in ESAME mode */ abs = parm & PX_MASK; /* Exit with status bit 23 set if new prefix is invalid */ if (abs > regs->mainlim) { status |= SIGP_STATUS_INVALID_PARAMETER; break; } /* Load new value into prefix register of target CPU */ tregs->PX = abs; /* Set pointer to active PSA structure */ tregs->psa = (PSA_3XX*)(tregs->mainstor + tregs->PX); /* Invalidate the ALB and TLB of the target CPU */ ARCH_DEP(purge_tlb) (tregs); #if defined(FEATURE_ACCESS_REGISTERS) ARCH_DEP(purge_alb) (tregs); #endif /*defined(FEATURE_ACCESS_REGISTERS)*/ /* Perform serialization and checkpoint-sync on target CPU */ // perform_serialization (tregs); // perform_chkpt_sync (tregs); break; case SIGP_STORE: /* Test for checkstop state */ if(tregs->checkstop) { status |= SIGP_STATUS_CHECK_STOP; break; } /* Exit with operator intervening if the status is stopping, such that a retry can be attempted */ if(tregs->cpustate == CPUSTATE_STOPPING) { status |= SIGP_STATUS_OPERATOR_INTERVENING; break; } /* Exit with status bit 22 set if CPU is not stopped */ if (tregs->cpustate != CPUSTATE_STOPPED) { status |= SIGP_STATUS_INCORRECT_STATE; break; } /* Obtain status address from parameter register bits 1-22 */ abs = parm & 0x7FFFFE00; /* Exit with status bit 23 set if status address invalid */ if (abs > regs->mainlim) { status |= SIGP_STATUS_INVALID_PARAMETER; break; } /* Store status at specified main storage address */ ARCH_DEP(store_status) (tregs, abs); /* Perform serialization and checkpoint-sync on target CPU */ // perform_serialization (tregs); // perform_chkpt_sync (tregs); break; #if defined(_390) case SIGP_STOREX: { #if !defined(FEATURE_BASIC_FP_EXTENSIONS) status |= SIGP_STATUS_INVALID_ORDER; #else /* defined(FEATURE_BASIC_FP_EXTENSIONS) */ RADR absx; /* abs addr of extended save area */ /* Test for checkstop state */ if(tregs->checkstop) status |= SIGP_STATUS_CHECK_STOP; /* Check if CPU is not stopped */ if (tregs->cpustate != CPUSTATE_STOPPED) status |= SIGP_STATUS_INCORRECT_STATE; /* Only proceed if no conditions exist to preclude the acceptance of this signal-processor order */ if (!status) { /* Obtain status address from parameter register bits 1-22 */ abs = parm & 0x7FFFFE00; /* Exit with status bit 23 set if status address invalid */ if (abs > regs->mainlim) status |= SIGP_STATUS_INVALID_PARAMETER; else { /* Fetch the address of the extended save area */ absx = ARCH_DEP(fetch_fullword_absolute) (abs+212, tregs); absx &= 0x7FFFF000; /* Invalid parameter if extended save area address invalid */ if (absx > regs->mainlim) status |= SIGP_STATUS_INVALID_PARAMETER; else { int i; // (work) /* Store status at specified main storage address */ ARCH_DEP(store_status) (tregs, abs ); /* Store extended status at specified main storage address */ for (i = 0; i < 32; i++) STORE_FW( tregs->mainstor + absx + (i*4), tregs->fpr[i] ); STORE_FW( tregs->mainstor + absx + 128, tregs->fpc ); STORE_FW( tregs->mainstor + absx + 132, 0 ); STORE_FW( tregs->mainstor + absx + 136, 0 ); STORE_FW( tregs->mainstor + absx + 140, 0 ); /* Perform serialization and checkpoint-sync on target CPU */ // perform_serialization (tregs); // perform_chkpt_sync (tregs); } } } #endif /* defined(FEATURE_BASIC_FP_EXTENSIONS) */ } break; #endif /* defined(_390) */ #if defined(_900) || defined(FEATURE_ESAME) || defined(FEATURE_HERCULES_DIAGCALLS) case SIGP_SETARCH: /* CPU must have ESAME support */ if(!sysblk.arch_z900) status = SIGP_STATUS_INVALID_ORDER; PERFORM_SERIALIZATION (regs); PERFORM_CHKPT_SYNC (regs); for (cpu = 0; cpu < MAX_CPU; cpu++) if (IS_CPU_ONLINE(cpu) && sysblk.regs[cpu]->cpustate != CPUSTATE_STOPPED && sysblk.regs[cpu]->cpuad != regs->cpuad) status |= SIGP_STATUS_INCORRECT_STATE; if(!status) { switch(parm & 0xFF) { #if defined(_900) || defined(FEATURE_ESAME) case 0: // from: -- z/Arch --to--> 390 if(sysblk.arch_mode == ARCH_390) status = SIGP_STATUS_INVALID_PARAMETER; else { sysblk.arch_mode = ARCH_390; set_arch = 1; INVALIDATE_AIA(regs); regs->captured_zpsw = regs->psw; regs->psw.states |= BIT(PSW_NOTESAME_BIT); regs->PX_L &= 0x7FFFE000; for (cpu = 0; cpu < MAX_CPU; cpu++) { if (IS_CPU_ONLINE(cpu) && sysblk.regs[cpu]->cpuad != regs->cpuad) { INVALIDATE_AIA(sysblk.regs[cpu]); sysblk.regs[cpu]->captured_zpsw = sysblk.regs[cpu]->psw; sysblk.regs[cpu]->psw.states |= BIT(PSW_NOTESAME_BIT); sysblk.regs[cpu]->PX_L &= 0x7FFFE000; } } } break; case 1: // from: -- 390 --to--> z/Arch if(sysblk.arch_mode == ARCH_900) status = SIGP_STATUS_INVALID_PARAMETER; else { sysblk.arch_mode = ARCH_900; set_arch = 1; INVALIDATE_AIA(regs); regs->psw.states &= ~BIT(PSW_NOTESAME_BIT); regs->psw.IA_H = 0; regs->PX_G &= 0x7FFFE000; for (cpu = 0; cpu < MAX_CPU; cpu++) { if (IS_CPU_ONLINE(cpu) && sysblk.regs[cpu]->cpuad != regs->cpuad) { INVALIDATE_AIA(sysblk.regs[cpu]); sysblk.regs[cpu]->psw.states &= ~BIT(PSW_NOTESAME_BIT); sysblk.regs[cpu]->psw.IA_H = 0; sysblk.regs[cpu]->PX_G &= 0x7FFFE000; } } } break; case 2: // restore CAPTURED z/Arch PSW... if(sysblk.arch_mode == ARCH_900) status = SIGP_STATUS_INVALID_PARAMETER; else { sysblk.arch_mode = ARCH_900; set_arch = 1; INVALIDATE_AIA(regs); regs->psw.states &= ~BIT(PSW_NOTESAME_BIT); regs->psw.IA_H = 0; regs->PX_G &= 0x7FFFE000; for (cpu = 0; cpu < MAX_CPU; cpu++) { if (IS_CPU_ONLINE(cpu) && sysblk.regs[cpu]->cpuad != regs->cpuad) { INVALIDATE_AIA(sysblk.regs[cpu]); sysblk.regs[cpu]->psw = sysblk.regs[cpu]->captured_zpsw; sysblk.regs[cpu]->PX_G &= 0x7FFFE000; } } } break; #endif // defined(_900) || defined(FEATURE_ESAME) #if defined(FEATURE_HERCULES_DIAGCALLS) case 37: if(sysblk.arch_mode == ARCH_370) status = SIGP_STATUS_INVALID_PARAMETER; else { sysblk.arch_mode = ARCH_370; set_arch = 1; } break; #endif /*defined(FEATURE_HERCULES_DIAGCALLS)*/ default: PTT(PTT_CL_ERR,"*SIGP",regs->GR_L(r1),regs->GR_L(r3),(U32)(effective_addr2 & 0xffffffff)); status |= SIGP_STATUS_INVALID_PARAMETER; } /* end switch(parm & 0xFF) */ } /* end if(!status) */ sysblk.dummyregs.arch_mode = sysblk.arch_mode; #if defined(OPTION_FISHIO) ios_arch_mode = sysblk.arch_mode; #endif // defined(OPTION_FISHIO) /* Invalidate the ALB and TLB */ ARCH_DEP(purge_tlb) (regs); #if defined(FEATURE_ACCESS_REGISTERS) ARCH_DEP(purge_alb) (tregs); #endif /*defined(FEATURE_ACCESS_REGISTERS)*/ PERFORM_SERIALIZATION (regs); PERFORM_CHKPT_SYNC (regs); break; #endif /*defined(_900) || defined(FEATURE_ESAME) || defined(FEATURE_HERCULES_DIAGCALLS)*/ #if defined(FEATURE_SENSE_RUNNING_STATUS) case SIGP_SENSE_RUNNING_STATE: if (tregs->cpustate != CPUSTATE_STARTED) status = SIGP_STATUS_NOT_RUNNING; break; #endif /*defined(FEATURE_SENSE_RUNNING_STATUS)*/ default: PTT(PTT_CL_ERR,"*SIGP",regs->GR_L(r1),regs->GR_L(r3),(U32)(effective_addr2 & 0xffffffff)); status = SIGP_STATUS_INVALID_ORDER; } /* end switch(order) */ /* Release the use of the signalling and response facility */ release_lock(&sysblk.sigplock); /* Wake up the target CPU */ if (IS_CPU_ONLINE(cpad)) WAKEUP_CPU (sysblk.regs[cpad]); /* Release the interrupt lock */ RELEASE_INTLOCK(regs); /* If status is non-zero, load the status word into the R1 register and return condition code 1 */ if (status != 0) { regs->GR_L(r1) = status; regs->psw.cc = 1; } else regs->psw.cc = 0; /* Log the results if we're interested in this particular SIGP */ if (log_sigp) { if (regs->psw.cc == 0) logmsg("%s: CC 0\n",log_buf); else logmsg("%s: CC 1 STATUS %8.8X\n",log_buf, (U32)status); } /* Perform serialization after completing operation */ PERFORM_SERIALIZATION (regs); #if defined(_900) || defined(FEATURE_ESAME) || defined(FEATURE_HERCULES_DIAGCALLS) if(set_arch) { OBTAIN_INTLOCK(regs); longjmp(regs->archjmp, 0); } #endif /*defined(_900) || defined(FEATURE_ESAME)*/ RETURN_INTCHECK(regs); } /*-------------------------------------------------------------------*/ /* B207 STCKC - Store Clock Comparator [S] */ /*-------------------------------------------------------------------*/ DEF_INST(store_clock_comparator) { int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ U64 dreg; /* Clock value */ S(inst, regs, b2, effective_addr2); PRIV_CHECK(regs); DW_CHECK(effective_addr2, regs); #if defined(_FEATURE_SIE) if(SIE_STATB(regs, IC3, SCKC)) longjmp(regs->progjmp, SIE_INTERCEPT_INST); #endif /*defined(_FEATURE_SIE)*/ /* Obtain the interrupt lock */ OBTAIN_INTLOCK(regs); /* Save clock comparator value */ dreg = regs->clkc; /* reset the clock comparator pending flag according to the setting of the tod clock */ if( tod_clock(regs) > dreg ) { ON_IC_CLKC(regs); /* Roll back the instruction and take the timer interrupt if we have a pending CPU timer and we are enabled for such interrupts *JJ */ if( OPEN_IC_CLKC(regs) ) { RELEASE_INTLOCK(regs); UPD_PSW_IA(regs, PSW_IA(regs, -4)); RETURN_INTCHECK(regs); } } else OFF_IC_CLKC(regs); RELEASE_INTLOCK(regs); /* Store clock comparator value at operand location */ ARCH_DEP(vstore8) ((dreg << 8), effective_addr2, b2, regs ); // /*debug*/logmsg("Store clock comparator=%16.16" I64_FMT "X\n", dreg); RETURN_INTCHECK(regs); } /*-------------------------------------------------------------------*/ /* B6 STCTL - Store Control [RS] */ /*-------------------------------------------------------------------*/ DEF_INST(store_control) { int r1, r3; /* Register numbers */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ int i, m, n; /* Integer work areas */ U32 *p1, *p2 = NULL; /* Mainstor pointers */ RS(inst, regs, r1, r3, b2, effective_addr2); #if defined(FEATURE_ECPSVM) if(ecpsvm_dostctl(regs,r1,r3,b2,effective_addr2)==0) { return; } #endif PRIV_CHECK(regs); FW_CHECK(effective_addr2, regs); #if defined(_FEATURE_SIE) if(SIE_STATB(regs, IC1, STCTL)) longjmp(regs->progjmp, SIE_INTERCEPT_INST); #endif /*defined(_FEATURE_SIE)*/ /* Calculate number of regs to store */ n = ((r3 - r1) & 0xF) + 1; /* Calculate number of words to next boundary */ m = (0x800 - (effective_addr2 & 0x7ff)) >> 2; /* Address of operand beginning */ p1 = (U32*)MADDR(effective_addr2, b2, regs, ACCTYPE_WRITE, regs->psw.pkey); /* Get address of next page if boundary crossed */ if (unlikely (m < n)) p2 = (U32*)MADDR(effective_addr2 + (m*4), b2, regs, ACCTYPE_WRITE, regs->psw.pkey); else m = n; /* Store at operand beginning */ for (i = 0; i < m; i++) store_fw (p1++, regs->CR_L((r1 + i) & 0xF)); /* Store on next page */ for ( ; i < n; i++) store_fw (p2++, regs->CR_L((r1 + i) & 0xF)); ITIMER_UPDATE(effective_addr2,(n*4)-1,regs); } /* end DEF_INST(store_control) */ /*-------------------------------------------------------------------*/ /* B212 STAP - Store CPU Address [S] */ /*-------------------------------------------------------------------*/ DEF_INST(store_cpu_address) { int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ S(inst, regs, b2, effective_addr2); PRIV_CHECK(regs); SIE_INTERCEPT(regs); ODD_CHECK(effective_addr2, regs); /* Store CPU address at operand address */ ARCH_DEP(vstore2) ( regs->cpuad, effective_addr2, b2, regs ); } /*-------------------------------------------------------------------*/ /* B202 STIDP - Store CPU ID [S] */ /*-------------------------------------------------------------------*/ DEF_INST(store_cpu_id) { int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ U64 dreg; /* Double word workarea */ S(inst, regs, b2, effective_addr2); PRIV_CHECK(regs); SIE_INTERCEPT(regs); DW_CHECK(effective_addr2, regs); /* Load the CPU ID */ dreg = sysblk.cpuid; /* If LPARNUM is two digits, build a format 1 CPU ID */ if (sysblk.lparnuml == 2) { /* Overlay first two digits of CPU ID by LPARNUM */ dreg &= 0xFF00FFFFFFFFFFFFULL; dreg |= ((U64)(sysblk.lparnum & 0xFF) << 48); /* Indicate format 1 CPU ID */ dreg |= 0x8000ULL; } /* If LPARNUM is one digit, build a format 0 CPU ID */ else if (sysblk.lparnuml == 1) { /* Overlay first digit of CPU ID by processor id and overlay second digit of CPU ID by LPARNUM */ dreg &= 0xFF00FFFFFFFFFFFFULL; dreg |= ((U64)(regs->cpuad & 0x0F) << 52) | ((U64)(sysblk.lparnum & 0x0F) << 48); } /* If LPARNUM is not specified, build basic mode CPU ID */ else { /* If first digit of serial is zero, insert processor id */ if ((dreg & 0x00F0000000000000ULL) == 0) dreg |= (U64)(regs->cpuad & 0x0F) << 52; } #if defined(FEATURE_ESAME) /* For ESAME, set version code in CPU ID bits 0-7 to zero */ dreg &= 0x00FFFFFFFFFFFFFFULL; #endif /*defined(FEATURE_ESAME)*/ /* Store CPU ID at operand address */ ARCH_DEP(vstore8) ( dreg, effective_addr2, b2, regs ); } /*-------------------------------------------------------------------*/ /* B209 STPT - Store CPU Timer [S] */ /*-------------------------------------------------------------------*/ DEF_INST(store_cpu_timer) { int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ S64 dreg; /* Double word workarea */ S(inst, regs, b2, effective_addr2); PRIV_CHECK(regs); DW_CHECK(effective_addr2, regs); #if defined(_FEATURE_SIE) if(SIE_STATB(regs, IC3, SPT)) longjmp(regs->progjmp, SIE_INTERCEPT_INST); #endif /*defined(_FEATURE_SIE)*/ OBTAIN_INTLOCK(regs); /* Save the CPU timer value */ dreg = cpu_timer(regs); /* reset the cpu timer pending flag according to its value */ if( CPU_TIMER(regs) < 0 ) { ON_IC_PTIMER(regs); /* Roll back the instruction and take the timer interrupt if we have a pending CPU timer and we are enabled for such interrupts *JJ */ if( OPEN_IC_PTIMER(regs) ) { RELEASE_INTLOCK(regs); UPD_PSW_IA(regs, PSW_IA(regs, -4)); RETURN_INTCHECK(regs); } } else OFF_IC_PTIMER(regs); RELEASE_INTLOCK(regs); /* Store CPU timer value at operand location */ ARCH_DEP(vstore8) ( dreg, effective_addr2, b2, regs ); // /*debug*/logmsg("Store CPU timer=%16.16" I64_FMT "X\n", dreg); RETURN_INTCHECK(regs); } /*-------------------------------------------------------------------*/ /* B211 STPX - Store Prefix [S] */ /*-------------------------------------------------------------------*/ DEF_INST(store_prefix) { int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ S(inst, regs, b2, effective_addr2); PRIV_CHECK(regs); SIE_INTERCEPT(regs); FW_CHECK(effective_addr2, regs); /* Store prefix register at operand address */ ARCH_DEP(vstore4) ( regs->PX, effective_addr2, b2, regs ); } /*-------------------------------------------------------------------*/ /* Calculate CPU capability indicator for STSI instruction */ /* */ /* The CPU capability indicator is 32-bit value which is calculated */ /* dynamically. A lower value indicates a faster CPU. The value may */ /* be either an unsigned binary integer or a floating point number. */ /* If bits 0-8 are zero, it is an integer in the range 0 to 2**23-1. */ /* If bits 0-8 are nonzero, is is a 32-bit short BFP number. */ /*-------------------------------------------------------------------*/ #if !defined(_STSI_CAPABILITY) #define _STSI_CAPABILITY static inline U32 stsi_capability (REGS *regs) { U64 dreg; /* work doubleword */ struct rusage usage; /* RMF type data */ #define SUSEC_PER_MIPS 48 /* One MIPS eq 48 SU */ getrusage(RUSAGE_SELF,&usage); dreg = (U64)(usage.ru_utime.tv_sec + usage.ru_stime.tv_sec); dreg = (dreg * 1000000) + (usage.ru_utime.tv_usec + usage.ru_stime.tv_usec); dreg = INSTCOUNT(regs) / (dreg ? dreg : 1); dreg *= SUSEC_PER_MIPS; return 0x800000 / (dreg ? dreg : 1); } /* end function stsi_capability */ #endif /*!defined(_STSI_CAPABILITY)*/ #ifdef FEATURE_STORE_SYSTEM_INFORMATION /*-------------------------------------------------------------------*/ /* B27D STSI - Store System Information [S] */ /*-------------------------------------------------------------------*/ DEF_INST(store_system_information) { int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ BYTE *m; /* Mainstor address */ int i; U16 offset; /* Offset into control block */ SYSIB111 *sysib111; /* Basic machine conf */ SYSIB121 *sysib121; /* Basic machine CPU */ SYSIB122 *sysib122; /* Basic machine CPUs */ SYSIB221 *sysib221; /* LPAR CPU */ SYSIB222 *sysib222; /* LPAR CPUs */ #if 0 SYSIB322 *sysib322; /* VM CPUs */ SYSIBVMDB *sysib322; /* VM description block */ #endif #if defined(FEATURE_CONFIGURATION_TOPOLOGY_FACILITY) SYSIB1512 *sysib1512; /* Configuration Topology */ TLECPU *tlecpu; /* CPU TLE Type */ U64 cpumask; /* work */ int cputype; /* work */ #endif /*defined(FEATURE_CONFIGURATION_TOPOLOGY_FACILITY)*/ /* "0 1 2 3 4 5 6 7" */ static BYTE hexebcdic[16] = { 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7, /* "8 9 A B C D E F" */ 0xF8,0xF9,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6 }; #define STSI_CAPABILITY stsi_capability(regs) S(inst, regs, b2, effective_addr2); PRIV_CHECK(regs); SIE_INTERCEPT(regs); PTT(PTT_CL_INF,"STSI",regs->GR_L(0),regs->GR_L(1),(U32)(effective_addr2 & 0xffffffff)); #if defined(DEBUG_STSI) logmsg("control.c: STSI %d.%d.%d ia="F_VADR" sysib="F_VADR"\n", (regs->GR_L(0) & STSI_GPR0_FC_MASK) >> 28, regs->GR_L(0) & STSI_GPR0_SEL1_MASK, regs->GR_L(1) & STSI_GPR1_SEL2_MASK, PSW_IA(regs,-4), effective_addr2); #endif /*DEBUG_STSI*/ /* Check function code */ if((regs->GR_L(0) & STSI_GPR0_FC_MASK) > STSI_GPR0_FC_LPAR #if defined(FEATURE_CONFIGURATION_TOPOLOGY_FACILITY) && (regs->GR_L(0) & STSI_GPR0_FC_MASK) != STSI_GPR0_FC_CURRINFO #endif /*defined(FEATURE_CONFIGURATION_TOPOLOGY_FACILITY)*/ ) { PTT(PTT_CL_ERR,"*STSI",regs->GR_L(0),regs->GR_L(1),(U32)(effective_addr2 & 0xffffffff)); #ifdef DEBUG_STSI logmsg("control.c: STSI cc=3 function code invalid\n"); #endif /*DEBUG_STSI*/ regs->psw.cc = 3; return; } /* Program check if reserved bits not zero */ if(regs->GR_L(0) & STSI_GPR0_RESERVED || regs->GR_L(1) & STSI_GPR1_RESERVED) ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION); /* Return current level if function code is zero */ if((regs->GR_L(0) & STSI_GPR0_FC_MASK) == STSI_GPR0_FC_CURRNUM) { regs->GR_L(0) |= STSI_GPR0_FC_LPAR; #ifdef DEBUG_STSI logmsg("control.c: STSI cc=0 R0=%8.8X\n", regs->GR_L(0)); #endif /*DEBUG_STSI*/ regs->psw.cc = 0; return; } /* Program check if operand not on a page boundary */ if ( effective_addr2 & 0x00000FFF ) ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION); /* Return with cc3 if selector codes invalid */ /* Func- tion Selec- Selec- Code tor 1 tor 2 Information Requested about ---- ----- ----- ---------------------------- 1 1 1 Basic-machine configuration 1 2 1 Basic-machine CPU 1 2 2 Basic-machine CPUs 2 2 1 Logical-partition CPU 2 2 2 Logical-partition CPUs 3 2 2 Virtual-machine CPUs 15 1 2 Topology information of current configuration */ if (0 || ((regs->GR_L(0) & STSI_GPR0_FC_MASK) == STSI_GPR0_FC_BASIC && (0 || (regs->GR_L(0) & STSI_GPR0_SEL1_MASK) == 0 || (regs->GR_L(0) & STSI_GPR0_SEL1_MASK) > 2 || (regs->GR_L(1) & STSI_GPR1_SEL2_MASK) == 0 || (regs->GR_L(1) & STSI_GPR1_SEL2_MASK) > 2 ) ) || ((regs->GR_L(0) & STSI_GPR0_FC_MASK) == STSI_GPR0_FC_LPAR && (0 || (regs->GR_L(0) & STSI_GPR0_SEL1_MASK) != 2 || (regs->GR_L(1) & STSI_GPR1_SEL2_MASK) == 0 || (regs->GR_L(1) & STSI_GPR1_SEL2_MASK) > 2 ) ) || ((regs->GR_L(0) & STSI_GPR0_FC_MASK) == STSI_GPR0_FC_VM && (0 || (regs->GR_L(0) & STSI_GPR0_SEL1_MASK) != 2 || (regs->GR_L(1) & STSI_GPR1_SEL2_MASK) != 2 ) ) #if defined(FEATURE_CONFIGURATION_TOPOLOGY_FACILITY) || ((regs->GR_L(0) & STSI_GPR0_FC_MASK) == STSI_GPR0_FC_CURRINFO && (0 || (regs->GR_L(0) & STSI_GPR0_SEL1_MASK) != 1 || (regs->GR_L(1) & STSI_GPR1_SEL2_MASK) != 2 ) ) #endif /*defined(FEATURE_CONFIGURATION_TOPOLOGY_FACILITY)*/ ) { PTT(PTT_CL_ERR,"*STSI",regs->GR_L(0),regs->GR_L(1),(U32)(effective_addr2 & 0xffffffff)); #ifdef DEBUG_STSI logmsg("control.c: STSI cc=3 selector codes invalid\n"); #endif /*DEBUG_STSI*/ regs->psw.cc = 3; return; } /* Obtain absolute address of main storage block, check protection, and set reference and change bits */ m = MADDR (effective_addr2, b2, regs, ACCTYPE_WRITE, regs->psw.pkey); switch(regs->GR_L(0) & STSI_GPR0_FC_MASK) { case STSI_GPR0_FC_BASIC: switch(regs->GR_L(0) & STSI_GPR0_SEL1_MASK) { case 1: switch(regs->GR_L(1) & STSI_GPR1_SEL2_MASK) { case 1: /* Basic-machine configuration */ sysib111 = (SYSIB111*)(m); memset(sysib111, 0x00, MAX(sizeof(SYSIB111),64*4)); sysib111->flag1 |= SYSIB111_PFLAG; get_manufacturer(sysib111->manufact); get_model(sysib111->model); for(i = 0; i < 4; i++) sysib111->type[i] = hexebcdic[(sysblk.cpuid >> (28 - (i*4))) & 0x0F]; get_modelcapa(sysib111->modcapaid); if (sysib111->modcapaid[0] == '\0') memcpy(sysib111->modcapaid, sysib111->model, sizeof(sysib111->model)); get_modelperm(sysib111->mpci); get_modeltemp(sysib111->mtci); memset(sysib111->seqc,0xF0,sizeof(sysib111->seqc)); for(i = 0; i < 6; i++) sysib111->seqc[(sizeof(sysib111->seqc) - 6) + i] = hexebcdic[(sysblk.cpuid >> (52 - (i*4))) & 0x0F]; get_plant(sysib111->plant); STORE_FW(sysib111->mcaprating, STSI_CAPABILITY); STORE_FW(sysib111->mpcaprating, STSI_CAPABILITY); STORE_FW(sysib111->mtcaprating, STSI_CAPABILITY); for(i=0;i<5;i++) { sysib111->typepct[i] = 100; } regs->psw.cc = 0; break; default: PTT(PTT_CL_ERR,"*STSI",regs->GR_L(0),regs->GR_L(1),(U32)(effective_addr2 & 0xffffffff)); regs->psw.cc = 3; } /* selector 2 */ break; case 2: switch(regs->GR_L(1) & STSI_GPR1_SEL2_MASK) { case 1: /* Basic-machine Current CPU */ sysib121 = (SYSIB121*)(m); memset(sysib121, 0x00, MAX(sizeof(SYSIB121),64*4)); memset(sysib121->seqc,0xF0,sizeof(sysib121->seqc)); for(i = 0; i < 6; i++) sysib121->seqc[(sizeof(sysib121->seqc) - 6) + i] = hexebcdic[sysblk.cpuid >> (52 - (i*4)) & 0x0F]; get_plant(sysib121->plant); STORE_HW(sysib121->cpuad,regs->cpuad); regs->psw.cc = 0; break; case 2: /* Basic-machine All CPUs */ sysib122 = (SYSIB122*)(m); memset(sysib122, 0x00, MAX(sizeof(SYSIB122),64*4)); sysib122->format = 1; offset = (U16)(sysib122->accap - (BYTE*)sysib122); STORE_HW(sysib122->accoff, offset); STORE_FW(sysib122->sccap, STSI_CAPABILITY); STORE_FW(sysib122->cap, STSI_CAPABILITY); STORE_HW(sysib122->totcpu, MAX_CPU); STORE_HW(sysib122->confcpu, sysblk.cpus); STORE_HW(sysib122->sbcpu, MAX_CPU - sysblk.cpus); get_mpfactors((BYTE*)sysib122->mpfact); STORE_FW(sysib122->accap, STSI_CAPABILITY); get_mpfactors((BYTE*)sysib122->ampfact); regs->psw.cc = 0; break; default: PTT(PTT_CL_ERR,"*STSI",regs->GR_L(0),regs->GR_L(1),(U32)(effective_addr2 & 0xffffffff)); regs->psw.cc = 3; } /* selector 2 */ break; default: PTT(PTT_CL_ERR,"*STSI",regs->GR_L(0),regs->GR_L(1),(U32)(effective_addr2 & 0xffffffff)); regs->psw.cc = 3; } /* selector 1 */ break; case STSI_GPR0_FC_LPAR: switch(regs->GR_L(0) & STSI_GPR0_SEL1_MASK) { case 2: switch(regs->GR_L(1) & STSI_GPR1_SEL2_MASK) { case 1: /* Logical-partition Current CPU */ sysib221 = (SYSIB221 *)(m); memset(sysib221, 0x00, MAX(sizeof(SYSIB221),64*4)); memset(sysib221->seqc,0xF0,sizeof(sysib111->seqc)); for(i = 0; i < 6; i++) sysib221->seqc[(sizeof(sysib221->seqc) - 6) + i] = hexebcdic[(sysblk.cpuid >> (52 - (i*4))) & 0x0F]; get_plant(sysib221->plant); STORE_HW(sysib221->lcpuid,regs->cpuad); STORE_HW(sysib221->cpuad,regs->cpuad); regs->psw.cc = 0; break; case 2: /* Logical-partition All CPUs */ sysib222 = (SYSIB222 *)(m); memset(sysib222, 0x00, MAX(sizeof(SYSIB222),64*4)); STORE_HW(sysib222->lparnum,1); sysib222->lcpuc = SYSIB222_LCPUC_SHARED; STORE_HW(sysib222->totcpu,MAX_CPU); STORE_HW(sysib222->confcpu,sysblk.cpus); STORE_HW(sysib222->sbcpu,MAX_CPU - sysblk.cpus); get_lparname(sysib222->lparname); STORE_FW(sysib222->lparcaf,1000); /* Full capability factor */ STORE_FW(sysib222->mdep[0],1000); /* ZZ nonzero value */ STORE_FW(sysib222->mdep[1],1000); /* ZZ nonzero value */ STORE_HW(sysib222->shrcpu,sysblk.cpus); regs->psw.cc = 0; break; default: PTT(PTT_CL_ERR,"*STSI",regs->GR_L(0),regs->GR_L(1),(U32)(effective_addr2 & 0xffffffff)); regs->psw.cc = 3; } /* selector 2 */ break; default: PTT(PTT_CL_ERR,"*STSI",regs->GR_L(0),regs->GR_L(1),(U32)(effective_addr2 & 0xffffffff)); regs->psw.cc = 3; } /* selector 1 */ break; #if defined(FEATURE_CONFIGURATION_TOPOLOGY_FACILITY) case STSI_GPR0_FC_CURRINFO: switch(regs->GR_L(0) & STSI_GPR0_SEL1_MASK) { case 1: switch(regs->GR_L(1) & STSI_GPR1_SEL2_MASK) { case 2: /* Topology information of current configuration */ sysib1512 = (SYSIB1512 *)(m); memset(sysib1512, 0x00, sizeof(SYSIB1512)); // PROGRAMMING NOTE: we only support horizontal polarization, // not vertical. sysib1512->mnest = 1; sysib1512->mag[5] = sysblk.cpus; tlecpu = (TLECPU *)(sysib1512->tles); /* For each type of CPU... */ for (cputype = 0; cputype <= SCCB_PTYP_MAX; cputype++) { /* For each CPU of this type */ cpumask = 0; for (i=0; i < sysblk.hicpu; i++) { if (1 && sysblk.regs[i] && sysblk.regs[i]->configured && sysblk.ptyp[i] == cputype ) { /* Initialize new TLE for this type */ if (!cpumask) { memset(tlecpu, 0x00, sizeof(TLECPU)); tlecpu->nl = 0; tlecpu->flags = CPUTLE_FLAG_DEDICATED; tlecpu->cpuadorg = 0; tlecpu->cputype = cputype; } /* Update CPU mask field for this type */ cpumask |= 0x8000000000000000ULL >> sysblk.regs[i]->cpuad; } } /* Bump to next TLE */ if (cpumask) { STORE_DW( &tlecpu->cpumask, cpumask ); tlecpu++; } } /* Save the length of this System Information Block */ STORE_HW(sysib1512->len,(U16)((BYTE*)tlecpu - (BYTE*)sysib1512)); /* Successful completion */ regs->psw.cc = 0; /* Clear topology-change-report-pending condition */ OBTAIN_INTLOCK(NULL); sysblk.topchnge = 0; RELEASE_INTLOCK(NULL); break; default: PTT(PTT_CL_ERR,"*STSI",regs->GR_L(0),regs->GR_L(1),(U32)(effective_addr2 & 0xffffffff)); regs->psw.cc = 3; } /* selector 2 */ break; default: PTT(PTT_CL_ERR,"*STSI",regs->GR_L(0),regs->GR_L(1),(U32)(effective_addr2 & 0xffffffff)); regs->psw.cc = 3; } /* selector 1 */ break; #endif /*defined(FEATURE_CONFIGURATION_TOPOLOGY_FACILITY)*/ default: PTT(PTT_CL_ERR,"*STSI",regs->GR_L(0),regs->GR_L(1),(U32)(effective_addr2 & 0xffffffff)); regs->psw.cc = 3; } /* function code */ #ifdef DEBUG_STSI /* Display results of STSI */ logmsg("control.c: STSI cc=%d\n", regs->psw.cc); for (i=0; i<256; i+=16, m+=16) { BYTE c, s[17]; int j; for (j=0; j<16; j++) { c = guest_to_host(m[j]); s[j] = isprint(c) ? c : '.'; } s[j] = '\0'; logmsg("+%2.2X %2.2X%2.2X%2.2X%2.2X %2.2X%2.2X%2.2X%2.2X " "%2.2X%2.2X%2.2X%2.2X %2.2X%2.2X%2.2X%2.2X *%s*\n", i,m[0],m[1],m[2],m[3],m[4],m[5],m[6],m[7], m[8],m[9],m[10],m[11],m[12],m[13],m[14],m[15],s); } #endif /*DEBUG_STSI*/ } /* end DEF_INST(store_system_information) */ #endif /*FEATURE_STORE_SYSTEM_INFORMATION*/ /*-------------------------------------------------------------------*/ /* AC STNSM - Store Then And Systen Mask [SI] */ /*-------------------------------------------------------------------*/ DEF_INST(store_then_and_system_mask) { BYTE i2; /* Immediate byte of opcode */ int b1; /* Base of effective addr */ VADR effective_addr1; /* Effective address */ SI(inst, regs, i2, b1, effective_addr1); #ifdef FEATURE_ECPSVM if(ecpsvm_dostnsm(regs,b1,effective_addr1,i2)==0) { return; } #endif PRIV_CHECK(regs); #if defined(_FEATURE_SIE) if(SIE_STATB(regs, IC1, STNSM)) longjmp(regs->progjmp, SIE_INTERCEPT_INST); #endif /*defined(_FEATURE_SIE)*/ /* Store current system mask value into storage operand */ ARCH_DEP(vstoreb) ( regs->psw.sysmask, effective_addr1, b1, regs ); /* AND system mask with immediate operand */ regs->psw.sysmask &= i2; SET_IC_MASK(regs); TEST_SET_AEA_MODE(regs); RETURN_INTCHECK(regs); } /* end DEF_INST(store_then_and_system_mask) */ /*-------------------------------------------------------------------*/ /* AD STOSM - Store Then Or Systen Mask [SI] */ /*-------------------------------------------------------------------*/ DEF_INST(store_then_or_system_mask) { BYTE i2; /* Immediate byte of opcode */ int b1; /* Base of effective addr */ VADR effective_addr1; /* Effective address */ SI(inst, regs, i2, b1, effective_addr1); #ifdef FEATURE_ECPSVM if(ecpsvm_dostosm(regs,b1,effective_addr1,i2)==0) { return; } #endif PRIV_CHECK(regs); #if defined(_FEATURE_SIE) if(SIE_STATB(regs, IC1, STOSM)) longjmp(regs->progjmp, SIE_INTERCEPT_INST); #endif /*defined(_FEATURE_SIE)*/ /* Store current system mask value into storage operand */ ARCH_DEP(vstoreb) ( regs->psw.sysmask, effective_addr1, b1, regs ); /* OR system mask with immediate operand */ regs->psw.sysmask |= i2; #if defined(FEATURE_MULTIPLE_CONTROLLED_DATA_SPACE) /* DAT must be off in XC mode */ if(SIE_STATB(regs, MX, XC) && (regs->psw.sysmask & PSW_DATMODE) ) ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION); #endif /*defined(FEATURE_MULTIPLE_CONTROLLED_DATA_SPACE)*/ /* For ECMODE, bits 0 and 2-4 of system mask must be zero */ if ( #if defined(FEATURE_BCMODE) ECMODE(®s->psw) && #endif /*defined(FEATURE_BCMODE)*/ (regs->psw.sysmask & 0xB8) != 0) ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION); SET_IC_MASK(regs); TEST_SET_AEA_MODE(regs); RETURN_INTCHECK(regs); } /* end DEF_INST(store_then_or_system_mask) */ /*-------------------------------------------------------------------*/ /* B246 STURA - Store Using Real Address [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(store_using_real_address) { int r1, r2; /* Values of R fields */ RADR n; /* Unsigned work */ RRE(inst, regs, r1, r2); PRIV_CHECK(regs); /* R2 register contains operand real storage address */ n = regs->GR(r2) & ADDRESS_MAXWRAP(regs); /* Program check if operand not on fullword boundary */ FW_CHECK(n, regs); /* Store R1 register at second operand location */ ARCH_DEP(vstore4) (regs->GR_L(r1), n, USE_REAL_ADDR, regs ); #if defined(FEATURE_PER2) /* Storage alteration must be enabled for STURA to be recognised */ if( EN_IC_PER_SA(regs) && EN_IC_PER_STURA(regs) ) { ON_IC_PER_SA(regs) ; ON_IC_PER_STURA(regs) ; regs->perc &= 0xFFFC; /* zero STD ID part of PER code */ } #endif /*defined(FEATURE_PER2)*/ } /* end DEF_INST(store_using_real_address) */ #if defined(FEATURE_ACCESS_REGISTERS) /*-------------------------------------------------------------------*/ /* B24C TAR - Test Access [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(test_access) { int r1, r2; /* Values of R fields */ U32 asteo; /* Real address of ASTE */ U32 aste[16]; /* ASN second table entry */ RRE(inst, regs, r1, r2); /* Program check if ASF control bit is zero */ if (!ASF_ENABLED(regs)) ARCH_DEP(program_interrupt) (regs, PGM_SPECIAL_OPERATION_EXCEPTION); /* Set condition code 0 if ALET value is 0 */ if (regs->AR(r1) == ALET_PRIMARY) { regs->psw.cc = 0; return; } /* Set condition code 3 if ALET value is 1 */ if (regs->AR(r1) == ALET_SECONDARY) { regs->psw.cc = 3; return; } /* Perform ALET translation using EAX value from register R2 bits 0-15, and set condition code 3 if exception */ if (ARCH_DEP(translate_alet) (regs->AR(r1), regs->GR_LHH(r2), ACCTYPE_TAR, #if defined(FEATURE_MULTIPLE_CONTROLLED_DATA_SPACE) SIE_STATB(regs, MX, XC) ? regs->hostregs : #endif /*defined(FEATURE_MULTIPLE_CONTROLLED_DATA_SPACE)*/ regs, &asteo, aste)) { regs->psw.cc = 3; return; } /* Set condition code 1 or 2 according to whether the ALET designates the DUCT or the PASTE */ regs->psw.cc = (regs->AR(r1) & ALET_PRI_LIST) ? 2 : 1; } #endif /*defined(FEATURE_ACCESS_REGISTERS)*/ #if defined(FEATURE_TEST_BLOCK) /*-------------------------------------------------------------------*/ /* B22C TB - Test Block [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(test_block) { int r1, r2; /* Values of R fields */ RADR n; /* Real address */ RRE(inst, regs, r1, r2); PRIV_CHECK(regs); #if defined(FEATURE_REGION_RELOCATE) if(SIE_STATNB(regs, MX, RRF) && !regs->sie_pref) #endif SIE_INTERCEPT(regs); /* Load 4K block address from R2 register */ n = regs->GR(r2) & ADDRESS_MAXWRAP_E(regs); n &= XSTORE_PAGEMASK; /* 4K boundary */ /* Perform serialization */ PERFORM_SERIALIZATION (regs); /* Addressing exception if block is outside main storage */ if ( n > regs->mainlim ) ARCH_DEP(program_interrupt) (regs, PGM_ADDRESSING_EXCEPTION); /* Protection exception if low-address protection is set */ if (ARCH_DEP(is_low_address_protected) (n, regs)) { #ifdef FEATURE_SUPPRESSION_ON_PROTECTION regs->TEA = (n & STORAGE_KEY_PAGEMASK); regs->excarid = 0; #endif /*FEATURE_SUPPRESSION_ON_PROTECTION*/ ARCH_DEP(program_interrupt) (regs, PGM_PROTECTION_EXCEPTION); } /* Convert real address to absolute address */ n = APPLY_PREFIXING (n, regs->PX); /* Clear the 4K block to zeroes */ memset (regs->mainstor + n, 0x00, PAGEFRAME_PAGESIZE); /* Set condition code 0 if storage usable, 1 if unusable */ if (STORAGE_KEY(n, regs) & STORKEY_BADFRM) regs->psw.cc = 1; else regs->psw.cc = 0; /* Perform serialization */ PERFORM_SERIALIZATION (regs); /* Clear general register 0 */ SET_GR_A(0, regs, 0); } #endif /*defined(FEATURE_TEST_BLOCK)*/ /*-------------------------------------------------------------------*/ /* E501 TPROT - Test Protection [SSE] */ /*-------------------------------------------------------------------*/ DEF_INST(test_protection) { int b1, b2; /* Values of base registers */ VADR effective_addr1, effective_addr2; /* Effective addresses */ RADR aaddr; /* Absolute address */ BYTE skey; /* Storage key */ BYTE akey; /* Access key */ SSE(inst, regs, b1, effective_addr1, b2, effective_addr2); PRIV_CHECK(regs); #if defined(_FEATURE_SIE) if(SIE_STATB(regs, IC2, TPROT)) longjmp(regs->progjmp, SIE_INTERCEPT_INST); #endif /*defined(_FEATURE_SIE)*/ /* Convert logical address to real address */ if (REAL_MODE(®s->psw)) { regs->dat.protect = 0; regs->dat.raddr = effective_addr1; } else { /* Return condition code 3 if translation exception */ if (ARCH_DEP(translate_addr) (effective_addr1, b1, regs, ACCTYPE_TPROT)) { regs->psw.cc = 3; return; } } /* Convert real address to absolute address */ aaddr = APPLY_PREFIXING (regs->dat.raddr, regs->PX); /* Program check if absolute address is outside main storage */ if (aaddr > regs->mainlim) ARCH_DEP(program_interrupt) (regs, PGM_ADDRESSING_EXCEPTION); #if defined(_FEATURE_SIE) if(SIE_MODE(regs) && !regs->sie_pref) { /* Under SIE TPROT also indicates if the host is using page protection */ /* Translate to real address - eventually using an access register if the guest is in XC mode */ if (SIE_TRANSLATE_ADDR (regs->sie_mso + aaddr, b1>0 && MULTIPLE_CONTROLLED_DATA_SPACE(regs) ? b1 : USE_PRIMARY_SPACE, regs->hostregs, ACCTYPE_SIE)) longjmp(regs->progjmp, SIE_INTERCEPT_INST); /* Convert host real address to host absolute address */ aaddr = APPLY_PREFIXING (regs->hostregs->dat.raddr, regs->hostregs->PX); if (aaddr > regs->hostregs->mainlim) ARCH_DEP(program_interrupt) (regs, PGM_ADDRESSING_EXCEPTION); } #endif /*defined(_FEATURE_SIE)*/ /* Load access key from operand 2 address bits 24-27 */ akey = effective_addr2 & 0xF0; /* Load the storage key for the absolute address */ skey = STORAGE_KEY(aaddr, regs); /* Return condition code 2 if location is fetch protected */ if (ARCH_DEP(is_fetch_protected) (effective_addr1, skey, akey, regs)) regs->psw.cc = 2; else /* Return condition code 1 if location is store protected */ if (ARCH_DEP(is_store_protected) (effective_addr1, skey, akey, regs)) regs->psw.cc = 1; else /* Return condition code 0 if location is not protected */ regs->psw.cc = 0; } #if defined(FEATURE_TRACING) /*-------------------------------------------------------------------*/ /* 99 TRACE - Trace [RS] */ /*-------------------------------------------------------------------*/ DEF_INST(trace) { int r1, r3; /* Register numbers */ int b2; /* effective address base */ VADR effective_addr2; /* effective address */ #if defined(FEATURE_TRACING) U32 op; /* Operand */ #endif /*defined(FEATURE_TRACING)*/ RS(inst, regs, r1, r3, b2, effective_addr2); PRIV_CHECK(regs); FW_CHECK(effective_addr2, regs); #if defined(FEATURE_TRACING) /* Exit if explicit tracing (control reg 12 bit 31) is off */ if ( (regs->CR(12) & CR12_EXTRACE) == 0 ) return; /* Fetch the trace operand */ op = ARCH_DEP(vfetch4) ( effective_addr2, b2, regs ); /* Exit if bit zero of the trace operand is one */ if ( (op & 0x80000000) ) return; /* Perform serialization and checkpoint-synchronization */ PERFORM_SERIALIZATION (regs); PERFORM_CHKPT_SYNC (regs); regs->CR(12) = ARCH_DEP(trace_tr) (r1, r3, op, regs); #endif /*defined(FEATURE_TRACING)*/ /* Perform serialization and checkpoint-synchronization */ PERFORM_SERIALIZATION (regs); PERFORM_CHKPT_SYNC (regs); } #endif /*defined(FEATURE_TRACING)*/ #if !defined(_GEN_ARCH) #if defined(_ARCHMODE2) #define _GEN_ARCH _ARCHMODE2 #include "control.c" #endif #if defined(_ARCHMODE3) #undef _GEN_ARCH #define _GEN_ARCH _ARCHMODE3 #include "control.c" #endif #endif /*!defined(_GEN_ARCH)*/ hercules-3.07/COPYRIGHT000644 000765 000765 00000000537 11143760543 016247 0ustar00jmaynardjmaynard000000 000000 All materials in this distribution are copyrighted by Roger Bowler and others. Hercules may be distributed under the terms of the Q Public License Version 1.0 Please refer to: http://www.hercules-390.org/herclic.html for details. In the context of this license, the initial developers of the software are Roger Bowler, Jan Jaeger, and Jay Maynard. hercules-3.07/cpu.c000644 000765 000765 00000217703 11321734033 015705 0ustar00jmaynardjmaynard000000 000000 /* CPU.C (c) Copyright Roger Bowler, 1994-2009 */ /* ESA/390 CPU Emulator */ /* Interpretive Execution - (c) Copyright Jan Jaeger, 1999-2009 */ /* z/Architecture support - (c) Copyright Jan Jaeger, 1999-2009 */ // $Id: cpu.c 5553 2009-12-23 17:34:16Z ivan $ /*-------------------------------------------------------------------*/ /* This module implements the CPU instruction execution function of */ /* the S/370 and ESA/390 architectures, as described in the manuals */ /* GA22-7000-03 System/370 Principles of Operation */ /* SA22-7201-06 ESA/390 Principles of Operation */ /* SA22-7832-00 z/Architecture Principles of Operation */ /*-------------------------------------------------------------------*/ /*-------------------------------------------------------------------*/ /* Additional credits: */ /* Nullification corrections by Jan Jaeger */ /* Set priority by Reed H. Petty from an idea by Steve Gay */ /* Corrections to program check by Jan Jaeger */ /* Light optimization on critical path by Valery Pogonchenko */ /* OSTAILOR parameter by Jay Maynard */ /* CPU timer and clock comparator interrupt improvements by */ /* Jan Jaeger, after a suggestion by Willem Konynenberg */ /* Instruction decode rework - Jan Jaeger */ /* Modifications for Interpretive Execution (SIE) by Jan Jaeger */ /* Basic FP extensions support - Peter Kuschnerus v209*/ /* ASN-and-LX-reuse facility - Roger Bowler, June 2004 @ALR*/ /*-------------------------------------------------------------------*/ // $Log$ // Revision 1.209 2009/01/23 11:46:20 bernard // copyright notice // // Revision 1.208 2009/01/09 23:25:59 ivan // Fix monitor code location when the monitor call occurs during the interception of a z/Arch SIE guest // // Revision 1.207 2008/12/21 02:51:58 ivan // Place the configuration in system check-stop state when a READ SCP INFO // is issued from a CPU that is not a CP Engine. // // Revision 1.206 2008/12/05 11:26:00 jj // Fix SIE psw update when host interrupt occurs durng guest processing // // Revision 1.205 2008/11/04 05:56:31 fish // Put ensure consistent create_thread ATTR usage change back in // // Revision 1.204 2008/11/03 15:31:57 rbowler // Back out consistent create_thread ATTR modification // // Revision 1.203 2008/10/18 09:32:20 fish // Ensure consistent create_thread ATTR usage // // Revision 1.202 2008/10/07 22:24:35 gsmith // Fix zero ilc problem after branch trace // // Revision 1.201 2008/08/13 21:21:55 gsmith // Fix bad guest IA after host interrupt during branch trace // // Revision 1.200 2008/04/11 14:28:15 bernard // Integrate regs->exrl into base Hercules code. // // Revision 1.199 2008/04/09 07:35:32 bernard // allign to Rogers terminal ;-) // // Revision 1.198 2008/04/08 17:12:29 bernard // Added execute relative long instruction // // Revision 1.197 2008/02/19 11:49:19 ivan // - Move setting of CPU priority after spwaning timer thread // - Added support for Posix 1003.1e capabilities // // Revision 1.196 2008/02/12 18:23:39 jj // 1. SPKA was missing protection check (PIC04) because // AIA regs were not purged. // // 2. BASR with branch trace and PIC16, the pgm old was pointing // 2 bytes before the BASR. // // 3. TBEDR , TBDR using R1 as source, should be R2. // // 4. PR with page crossing stack (1st page invalid) and PSW real // in stack, missed the PIC 11. Fixed by invoking abs_stck_addr // for previous stack entry descriptor before doing the load_psw. // // Revision 1.195 2007/12/10 23:12:02 gsmith // Tweaks to OPTION_MIPS_COUNTING processing // // Revision 1.194 2007/12/07 12:08:51 rbowler // Enable B9xx,EBxx opcodes in S/370 mode for ETF2 (correction) // // Revision 1.193 2007/12/02 16:22:09 rbowler // Enable B9xx,EBxx opcodes in S/370 mode for ETF2 // // Revision 1.192 2007/11/22 03:49:01 ivan // Store Monitor code DOUBLEWORD when MC invoked under z/Architecture // (previously only a fullword was stored) // // Revision 1.191 2007/11/18 22:18:51 rbowler // Permit FEATURE_IMMEDIATE_AND_RELATIVE to be activated in S/370 mode // // Revision 1.190 2007/11/02 20:19:20 ivan // Remove longjmp in process_interrupt() when cpu is STOPPING and a store status // was requested - leads to a CPU in the STOPPED state that is still executing // instructions. // // Revision 1.189 2007/08/06 22:14:53 gsmith // process_interrupt returns if nothing happens // // Revision 1.188 2007/08/06 22:14:07 gsmith // rework CPU execution loop // // Revision 1.187 2007/08/06 22:12:49 gsmith // cpu thread exitjmp // // Revision 1.186 2007/08/06 22:10:47 gsmith // reposition process_trace for readability // // Revision 1.185 2007/06/23 00:04:05 ivan // Update copyright notices to include current year (2007) // // Revision 1.184 2007/06/22 02:22:50 gsmith // revert config_cpu.pat due to problems in testing // // Revision 1.183 2007/06/20 03:52:19 gsmith // configure_cpu now returns when the CPU is fully configured // // Revision 1.182 2007/06/06 22:14:57 gsmith // Fix SYNCHRONIZE_CPUS when numcpu > number of host processors - Greg // // Revision 1.181 2007/04/09 23:07:42 gsmith // call cpu_uninit() on run_cpu exit // // Revision 1.180 2007/03/25 04:20:36 gsmith // Ensure started_mask CPU bit is off for terminating cpu thread - Fish by Greg // // Revision 1.179 2007/03/13 01:43:37 gsmith // Synchronize started cpu // // Revision 1.178 2007/01/16 01:45:33 gsmith // Tweaks to instruction stepping/tracing // // Revision 1.177 2007/01/09 23:18:21 gsmith // Tweaks to cpuloop // // Revision 1.176 2007/01/04 23:12:03 gsmith // remove thunk calls for program_interrupt // // Revision 1.175 2007/01/04 01:08:41 gsmith // 03 Jan 2007 single_cpu_dw fetch/store patch for ia32 // // Revision 1.174 2007/01/03 14:21:41 rbowler // Reinstate semantics of 'g' command changed by hsccmd rev 1.197 // // Revision 1.173 2006/12/30 16:15:57 gsmith // 2006 Dec 30 Fix cpu_init to call set_jump_pointers for all arches // // Revision 1.172 2006/12/21 22:39:38 gsmith // 21 Dec 2006 Range for s+, t+ - Greg Smith // // Revision 1.171 2006/12/21 01:45:01 gsmith // 20 Dec 2006 Fix instruction display in program interrupt - Greg Smithh // // Revision 1.170 2006/12/20 23:37:29 rbowler // ip_pat cpu.c rev 1.168 duplicated 2 lines from rev 1.167 // // Revision 1.169 2006/12/20 10:52:08 rbowler // cpu.c(294) : warning C4101: 'ip' : unreferenced local variable // // Revision 1.168 2006/12/20 04:26:19 gsmith // 19 Dec 2006 ip_all.pat - performance patch - Greg Smith // // Revision 1.167 2006/12/17 21:54:24 rbowler // Display DXC in msg HHCCP014I for PIC7 // // Revision 1.166 2006/12/08 09:43:19 jj // Add CVS message log // #include "hstdinc.h" #if !defined(_HENGINE_DLL_) #define _HENGINE_DLL_ #endif #if !defined(_CPU_C_) #define _CPU_C_ #endif #include "hercules.h" #include "opcode.h" #include "inline.h" /*-------------------------------------------------------------------*/ /* Put a CPU in check-stop state */ /* Must hold the system intlock */ /*-------------------------------------------------------------------*/ void ARCH_DEP(checkstop_cpu)(REGS *regs) { regs->cpustate=CPUSTATE_STOPPING; regs->checkstop=1; ON_IC_INTERRUPT(regs); } /*-------------------------------------------------------------------*/ /* Put all the CPUs in the configuration in check-stop state */ /*-------------------------------------------------------------------*/ void ARCH_DEP(checkstop_config)(void) { int i; for(i=0;ipsw.zeroilc) SET_PSW_IA(regs); #if defined(FEATURE_BCMODE) if ( ECMODE(®s->psw) ) { #endif /*defined(FEATURE_BCMODE)*/ #if !defined(FEATURE_ESAME) STORE_FW ( addr, ( (regs->psw.sysmask << 24) | ((regs->psw.pkey | regs->psw.states) << 16) | ( ( (regs->psw.asc) | (regs->psw.cc << 4) | (regs->psw.progmask) ) << 8 ) | regs->psw.zerobyte ) ); if(unlikely(regs->psw.zeroilc)) STORE_FW ( addr + 4, regs->psw.IA | (regs->psw.amode ? 0x80000000 : 0) ); else STORE_FW ( addr + 4, ( (regs->psw.IA & ADDRESS_MAXWRAP(regs)) | (regs->psw.amode ? 0x80000000 : 0) ) ); #endif /*!defined(FEATURE_ESAME)*/ #if defined(FEATURE_BCMODE) } else { STORE_FW ( addr, ( (regs->psw.sysmask << 24) | ((regs->psw.pkey | regs->psw.states) << 16) | (regs->psw.intcode) ) ); if(unlikely(regs->psw.zeroilc)) STORE_FW ( addr + 4, ( ( (REAL_ILC(regs) << 5) | (regs->psw.cc << 4) | regs->psw.progmask ) << 24 ) | regs->psw.IA ); else STORE_FW ( addr + 4, ( ( (REAL_ILC(regs) << 5) | (regs->psw.cc << 4) | regs->psw.progmask ) << 24 ) | (regs->psw.IA & ADDRESS_MAXWRAP(regs)) ); } #elif defined(FEATURE_ESAME) STORE_FW ( addr, ( (regs->psw.sysmask << 24) | ((regs->psw.pkey | regs->psw.states) << 16) | ( ( (regs->psw.asc) | (regs->psw.cc << 4) | (regs->psw.progmask) ) << 8 ) | (regs->psw.amode64 ? 0x01 : 0) | regs->psw.zerobyte ) ); STORE_FW ( addr + 4, ( (regs->psw.amode ? 0x80000000 : 0 ) | regs->psw.zeroword ) ); STORE_DW ( addr + 8, regs->psw.IA_G ); #endif /*defined(FEATURE_ESAME)*/ } /* end function ARCH_DEP(store_psw) */ /*-------------------------------------------------------------------*/ /* Load current PSW from a specified address in main storage */ /* Returns 0 if valid, 0x0006 if specification exception */ /*-------------------------------------------------------------------*/ int ARCH_DEP(load_psw) (REGS *regs, BYTE *addr) { INVALIDATE_AIA(regs); regs->psw.zeroilc = 1; regs->psw.sysmask = addr[0]; regs->psw.pkey = (addr[1] & 0xF0); regs->psw.states = (addr[1] & 0x0F); #if defined(FEATURE_BCMODE) if ( ECMODE(®s->psw) ) { #endif /*defined(FEATURE_BCMODE)*/ SET_IC_ECMODE_MASK(regs); /* Processing for EC mode PSW */ regs->psw.intcode = 0; regs->psw.asc = (addr[2] & 0xC0); regs->psw.cc = (addr[2] & 0x30) >> 4; regs->psw.progmask = (addr[2] & 0x0F); regs->psw.amode = (addr[4] & 0x80) ? 1 : 0; #if defined(FEATURE_ESAME) regs->psw.zerobyte = addr[3] & 0xFE; regs->psw.amode64 = addr[3] & 0x01; regs->psw.zeroword = fetch_fw(addr+4) & 0x7FFFFFFF; regs->psw.IA = fetch_dw (addr + 8); regs->psw.AMASK = regs->psw.amode64 ? AMASK64 : regs->psw.amode ? AMASK31 : AMASK24; #else /*!defined(FEATURE_ESAME)*/ regs->psw.zerobyte = addr[3]; regs->psw.amode64 = 0; regs->psw.IA = fetch_fw(addr + 4) & 0x7FFFFFFF; regs->psw.AMASK = regs->psw.amode ? AMASK31 : AMASK24; #endif /*!defined(FEATURE_ESAME)*/ /* Bits 0 and 2-4 of system mask must be zero */ if ((addr[0] & 0xB8) != 0) return PGM_SPECIFICATION_EXCEPTION; #if defined(FEATURE_ESAME) /* For ESAME, bit 12 must be zero */ if (NOTESAME(®s->psw)) return PGM_SPECIFICATION_EXCEPTION; /* Bits 24-30 must be zero */ if (regs->psw.zerobyte) return PGM_SPECIFICATION_EXCEPTION; /* Bits 33-63 must be zero */ if ( regs->psw.zeroword ) return PGM_SPECIFICATION_EXCEPTION; #else /*!defined(FEATURE_ESAME)*/ /* Bits 24-31 must be zero */ if ( regs->psw.zerobyte ) return PGM_SPECIFICATION_EXCEPTION; /* For ESA/390, bit 12 must be one */ if (!ECMODE(®s->psw)) return PGM_SPECIFICATION_EXCEPTION; #endif /*!defined(FEATURE_ESAME)*/ #ifndef FEATURE_DUAL_ADDRESS_SPACE /* If DAS feature not installed then bit 16 must be zero */ if (SPACE_BIT(®s->psw)) return PGM_SPECIFICATION_EXCEPTION; #endif /*!FEATURE_DUAL_ADDRESS_SPACE*/ #ifndef FEATURE_ACCESS_REGISTERS /* If not ESA/370 or ESA/390 then bit 17 must be zero */ if (AR_BIT(®s->psw)) return PGM_SPECIFICATION_EXCEPTION; #endif /*!FEATURE_ACCESS_REGISTERS*/ /* Check validity of amode and instruction address */ #if defined(FEATURE_ESAME) /* For ESAME, bit 32 cannot be zero if bit 31 is one */ if (regs->psw.amode64 && !regs->psw.amode) return PGM_SPECIFICATION_EXCEPTION; /* If bit 32 is zero then IA cannot exceed 24 bits */ if (!regs->psw.amode && regs->psw.IA > 0x00FFFFFF) return PGM_SPECIFICATION_EXCEPTION; /* If bit 31 is zero then IA cannot exceed 31 bits */ if (!regs->psw.amode64 && regs->psw.IA > 0x7FFFFFFF) return PGM_SPECIFICATION_EXCEPTION; #else /*!defined(FEATURE_ESAME)*/ #ifdef FEATURE_BIMODAL_ADDRESSING /* For 370-XA, ESA/370, and ESA/390, if amode=24, bits 33-39 must be zero */ if (!regs->psw.amode && regs->psw.IA > 0x00FFFFFF) return PGM_SPECIFICATION_EXCEPTION; #else /*!FEATURE_BIMODAL_ADDRESSING*/ /* For S/370, bits 32-39 must be zero */ if (addr[4] != 0x00) return PGM_SPECIFICATION_EXCEPTION; #endif /*!FEATURE_BIMODAL_ADDRESSING*/ #endif /*!defined(FEATURE_ESAME)*/ #if defined(FEATURE_BCMODE) } else { SET_IC_BCMODE_MASK(regs); /* Processing for S/370 BC mode PSW */ regs->psw.intcode = fetch_hw (addr + 2); regs->psw.cc = (addr[4] & 0x30) >> 4; regs->psw.progmask = (addr[4] & 0x0F); FETCH_FW(regs->psw.IA, addr + 4); regs->psw.IA &= 0x00FFFFFF; regs->psw.AMASK = AMASK24; regs->psw.zerobyte = 0; regs->psw.asc = 0; regs->psw.amode64 = regs->psw.amode = 0; } #endif /*defined(FEATURE_BCMODE)*/ #if defined(FEATURE_MULTIPLE_CONTROLLED_DATA_SPACE) /* Bits 5 and 16 must be zero in XC mode */ if( SIE_STATB(regs, MX, XC) && ( (regs->psw.sysmask & PSW_DATMODE) || SPACE_BIT(®s->psw)) ) return PGM_SPECIFICATION_EXCEPTION; #endif /*defined(FEATURE_MULTIPLE_CONTROLLED_DATA_SPACE)*/ regs->psw.zeroilc = 0; /* Check for wait state PSW */ if (WAITSTATE(®s->psw) && CPU_STEPPING_OR_TRACING_ALL) { logmsg (_("HHCCP043I Wait state PSW loaded: ")); display_psw (regs); } TEST_SET_AEA_MODE(regs); return 0; } /* end function ARCH_DEP(load_psw) */ /*-------------------------------------------------------------------*/ /* Load program interrupt new PSW */ /*-------------------------------------------------------------------*/ void (ATTR_REGPARM(2) ARCH_DEP(program_interrupt)) (REGS *regs, int pcode) { PSA *psa; /* -> Prefixed storage area */ REGS *realregs; /* True regs structure */ RADR px; /* host real address of pfx */ int code; /* pcode without PER ind. */ int ilc; /* instruction length */ #if defined(FEATURE_ESAME) /** FIXME : SEE ISW20090110-1 */ void *zmoncode=NULL; /* special reloc for z/Arch */ /* FIXME : zmoncode not being initialized here raises a potentially non-initialized warning in GCC.. can't find why. ISW 2009/02/04 */ /* mon call SIE intercept */ #endif #if defined(FEATURE_INTERPRETIVE_EXECUTION) int sie_ilc=0; /* SIE instruction length */ #endif #if defined(_FEATURE_SIE) int nointercept; /* True for virtual pgmint */ #endif /*defined(_FEATURE_SIE)*/ #if defined(OPTION_FOOTPRINT_BUFFER) U32 n; #endif /*defined(OPTION_FOOTPRINT_BUFFER)*/ char dxcstr[8]={0}; /* " DXC=xx" if data excptn */ static char *pgmintname[] = { /* 01 */ "Operation exception", /* 02 */ "Privileged-operation exception", /* 03 */ "Execute exception", /* 04 */ "Protection exception", /* 05 */ "Addressing exception", /* 06 */ "Specification exception", /* 07 */ "Data exception", /* 08 */ "Fixed-point-overflow exception", /* 09 */ "Fixed-point-divide exception", /* 0A */ "Decimal-overflow exception", /* 0B */ "Decimal-divide exception", /* 0C */ "HFP-exponent-overflow exception", /* 0D */ "HFP-exponent-underflow exception", /* 0E */ "HFP-significance exception", /* 0F */ "HFP-floating-point-divide exception", /* 10 */ "Segment-translation exception", /* 11 */ "Page-translation exception", /* 12 */ "Translation-specification exception", /* 13 */ "Special-operation exception", /* 14 */ "Pseudo-page-fault exception", /* 15 */ "Operand exception", /* 16 */ "Trace-table exception", /* 17 */ "ASN-translation exception", /* 18 */ "Page access exception", /* 19 */ "Vector/Crypto operation exception", /* 1A */ "Page state exception", /* 1B */ "Page transition exception", /* 1C */ "Space-switch event", /* 1D */ "Square-root exception", /* 1E */ "Unnormalized-operand exception", /* 1F */ "PC-translation specification exception", /* 20 */ "AFX-translation exception", /* 21 */ "ASX-translation exception", /* 22 */ "LX-translation exception", /* 23 */ "EX-translation exception", /* 24 */ "Primary-authority exception", /* 25 */ "Secondary-authority exception", /* 26 */ "LFX-translation exception", /*@ALR*/ /* 27 */ "LSX-translation exception", /*@ALR*/ /* 28 */ "ALET-specification exception", /* 29 */ "ALEN-translation exception", /* 2A */ "ALE-sequence exception", /* 2B */ "ASTE-validity exception", /* 2C */ "ASTE-sequence exception", /* 2D */ "Extended-authority exception", /* 2E */ "LSTE-sequence exception", /*@ALR*/ /* 2F */ "ASTE-instance exception", /*@ALR*/ /* 30 */ "Stack-full exception", /* 31 */ "Stack-empty exception", /* 32 */ "Stack-specification exception", /* 33 */ "Stack-type exception", /* 34 */ "Stack-operation exception", /* 35 */ "Unassigned exception", /* 36 */ "Unassigned exception", /* 37 */ "Unassigned exception", /* 38 */ "ASCE-type exception", /* 39 */ "Region-first-translation exception", /* 3A */ "Region-second-translation exception", /* 3B */ "Region-third-translation exception", /* 3C */ "Unassigned exception", /* 3D */ "Unassigned exception", /* 3E */ "Unassigned exception", /* 3F */ "Unassigned exception", /* 40 */ "Monitor event" }; /* 26 */ /* was "Page-fault-assist exception", */ /* 27 */ /* was "Control-switch exception", */ /* If called with ghost registers (ie from hercules command then ignore all interrupt handling and report the error to the caller */ if(regs->ghostregs) longjmp(regs->progjmp, pcode); PTT(PTT_CL_PGM,"*PROG",pcode,(U32)(regs->TEA & 0xffffffff),regs->psw.IA_L); /* program_interrupt() may be called with a shadow copy of the regs structure, realregs is the pointer to the real structure which must be used when loading/storing the psw, or backing up the instruction address in case of nullification */ #if defined(_FEATURE_SIE) realregs = SIE_MODE(regs) ? sysblk.regs[regs->cpuad]->guestregs : sysblk.regs[regs->cpuad]; #else /*!defined(_FEATURE_SIE)*/ realregs = sysblk.regs[regs->cpuad]; #endif /*!defined(_FEATURE_SIE)*/ /* Prevent machine check when in (almost) interrupt loop */ realregs->instcount++; /* Release any locks */ if (sysblk.intowner == realregs->cpuad) RELEASE_INTLOCK(realregs); if (sysblk.mainowner == realregs->cpuad) RELEASE_MAINLOCK(realregs); /* Ensure psw.IA is set and aia invalidated */ INVALIDATE_AIA(realregs); #if defined(FEATURE_INTERPRETIVE_EXECUTION) if(realregs->sie_active) INVALIDATE_AIA(realregs->guestregs); #endif /*defined(FEATURE_INTERPRETIVE_EXECUTION)*/ /* Set instruction length (ilc) */ ilc = realregs->psw.zeroilc ? 0 : REAL_ILC(realregs); if (realregs->psw.ilc == 0 && !realregs->psw.zeroilc) { /* This can happen if BALR, BASR, BASSM or BSM program checks during trace */ ilc = realregs->execflag ? realregs->exrl ? 6 : 4 : 2; realregs->ip += ilc; realregs->psw.IA += ilc; realregs->psw.ilc = ilc; } #if defined(FEATURE_INTERPRETIVE_EXECUTION) if(realregs->sie_active) { sie_ilc = realregs->guestregs->psw.zeroilc ? 0 : REAL_ILC(realregs->guestregs); if (realregs->guestregs->psw.ilc == 0 && !realregs->guestregs->psw.zeroilc) { sie_ilc = realregs->guestregs->execflag ? realregs->guestregs->exrl ? 6 : 4 : 2; realregs->guestregs->psw.ilc = sie_ilc; } } #endif /*defined(FEATURE_INTERPRETIVE_EXECUTION)*/ /* Set `execflag' to 0 in case EXecuted instruction program-checked */ realregs->execflag = 0; #if defined(FEATURE_INTERPRETIVE_EXECUTION) if(realregs->sie_active) realregs->guestregs->execflag = 0; #endif /*defined(FEATURE_INTERPRETIVE_EXECUTION)*/ /* Unlock the main storage lock if held */ if (realregs->cpuad == sysblk.mainowner) RELEASE_MAINLOCK(realregs); /* Remove PER indication from program interrupt code such that interrupt code specific tests may be done. The PER indication will be stored in the PER handling code */ code = pcode & ~PGM_PER_EVENT; /* If this is a concurrent PER event then we must add the PER bit to the interrupts code */ if( OPEN_IC_PER(realregs) ) pcode |= PGM_PER_EVENT; /* Perform serialization and checkpoint synchronization */ PERFORM_SERIALIZATION (realregs); PERFORM_CHKPT_SYNC (realregs); #if defined(FEATURE_INTERPRETIVE_EXECUTION) /* Host protection and addressing exceptions must be reflected to the guest */ if(realregs->sie_active && (code == PGM_PROTECTION_EXCEPTION || code == PGM_ADDRESSING_EXCEPTION #if defined(_FEATURE_MULTIPLE_CONTROLLED_DATA_SPACE) || code == PGM_ALET_SPECIFICATION_EXCEPTION || code == PGM_ALEN_TRANSLATION_EXCEPTION || code == PGM_ALE_SEQUENCE_EXCEPTION || code == PGM_EXTENDED_AUTHORITY_EXCEPTION #endif /*defined(_FEATURE_MULTIPLE_CONTROLLED_DATA_SPACE)*/ ) ) { #if defined(SIE_DEBUG) logmsg(_("program_int() passing to guest code=%4.4X\n"),pcode); #endif /*defined(SIE_DEBUG)*/ realregs->guestregs->TEA = realregs->TEA; realregs->guestregs->excarid = realregs->excarid; realregs->guestregs->opndrid = realregs->opndrid; #if defined(_FEATURE_PROTECTION_INTERCEPTION_CONTROL) realregs->guestregs->hostint = 1; #endif /*defined(_FEATURE_PROTECTION_INTERCEPTION_CONTROL)*/ (realregs->guestregs->program_interrupt) (realregs->guestregs, pcode); } #endif /*defined(FEATURE_INTERPRETIVE_EXECUTION)*/ /* Back up the PSW for exceptions which cause nullification, unless the exception occurred during instruction fetch */ if ((code == PGM_PAGE_TRANSLATION_EXCEPTION || code == PGM_SEGMENT_TRANSLATION_EXCEPTION #if defined(FEATURE_ESAME) || code == PGM_ASCE_TYPE_EXCEPTION || code == PGM_REGION_FIRST_TRANSLATION_EXCEPTION || code == PGM_REGION_SECOND_TRANSLATION_EXCEPTION || code == PGM_REGION_THIRD_TRANSLATION_EXCEPTION #endif /*defined(FEATURE_ESAME)*/ || code == PGM_TRACE_TABLE_EXCEPTION || code == PGM_AFX_TRANSLATION_EXCEPTION || code == PGM_ASX_TRANSLATION_EXCEPTION || code == PGM_LX_TRANSLATION_EXCEPTION || code == PGM_LFX_TRANSLATION_EXCEPTION /*@ALR*/ || code == PGM_LSX_TRANSLATION_EXCEPTION /*@ALR*/ || code == PGM_LSTE_SEQUENCE_EXCEPTION /*@ALR*/ || code == PGM_EX_TRANSLATION_EXCEPTION || code == PGM_PRIMARY_AUTHORITY_EXCEPTION || code == PGM_SECONDARY_AUTHORITY_EXCEPTION || code == PGM_ALEN_TRANSLATION_EXCEPTION || code == PGM_ALE_SEQUENCE_EXCEPTION || code == PGM_ASTE_VALIDITY_EXCEPTION || code == PGM_ASTE_SEQUENCE_EXCEPTION || code == PGM_ASTE_INSTANCE_EXCEPTION /*@ALR*/ || code == PGM_EXTENDED_AUTHORITY_EXCEPTION || code == PGM_STACK_FULL_EXCEPTION || code == PGM_STACK_EMPTY_EXCEPTION || code == PGM_STACK_SPECIFICATION_EXCEPTION || code == PGM_STACK_TYPE_EXCEPTION || code == PGM_STACK_OPERATION_EXCEPTION || code == PGM_VECTOR_OPERATION_EXCEPTION) && !realregs->instinvalid) { realregs->psw.IA -= ilc; realregs->psw.IA &= ADDRESS_MAXWRAP(realregs); #if defined(FEATURE_INTERPRETIVE_EXECUTION) /* When in SIE mode the guest instruction causing this host exception must also be nullified */ if(realregs->sie_active && !realregs->guestregs->instinvalid) { realregs->guestregs->psw.IA -= sie_ilc; realregs->guestregs->psw.IA &= ADDRESS_MAXWRAP(realregs->guestregs); } #endif /*defined(FEATURE_INTERPRETIVE_EXECUTION)*/ } /* The OLD PSW must be incremented on the following exceptions during instfetch */ if(realregs->instinvalid && ( code == PGM_PROTECTION_EXCEPTION || code == PGM_ADDRESSING_EXCEPTION || code == PGM_SPECIFICATION_EXCEPTION || code == PGM_TRANSLATION_SPECIFICATION_EXCEPTION )) { realregs->psw.IA += ilc; realregs->psw.IA &= ADDRESS_MAXWRAP(realregs); } /* Store the interrupt code in the PSW */ realregs->psw.intcode = pcode; /* Call debugger if active */ HDC2(debug_program_interrupt, regs, pcode); /* Trace program checks other then PER event */ if(code && (CPU_STEPPING_OR_TRACING(realregs, ilc) || sysblk.pgminttr & ((U64)1 << ((code - 1) & 0x3F)))) { BYTE *ip; #if defined(OPTION_FOOTPRINT_BUFFER) if(!(sysblk.insttrace || sysblk.inststep)) for(n = sysblk.footprptr[realregs->cpuad] + 1 ; n != sysblk.footprptr[realregs->cpuad]; n++, n &= OPTION_FOOTPRINT_BUFFER - 1) ARCH_DEP(display_inst) (&sysblk.footprregs[realregs->cpuad][n], sysblk.footprregs[realregs->cpuad][n].inst); #endif /*defined(OPTION_FOOTPRINT_BUFFER)*/ logmsg(_("HHCCP014I ")); #if defined(_FEATURE_SIE) if(SIE_MODE(realregs)) logmsg(_("SIE: ")); #endif /*defined(_FEATURE_SIE)*/ #if defined(SIE_DEBUG) logmsg (MSTRING(_GEN_ARCH) " "); #endif /*defined(SIE_DEBUG)*/ if (code == PGM_DATA_EXCEPTION) sprintf(dxcstr, " DXC=%2.2X", regs->dxc); logmsg (_("CPU%4.4X: %s CODE=%4.4X ILC=%d%s\n"), realregs->cpuad, pgmintname[ (code - 1) & 0x3F], pcode, ilc, dxcstr); /* Calculate instruction pointer */ ip = realregs->instinvalid ? NULL : (realregs->ip - ilc < realregs->aip) ? realregs->inst : realregs->ip - ilc; ARCH_DEP(display_inst) (realregs, ip); } realregs->instinvalid = 0; #if defined(FEATURE_INTERPRETIVE_EXECUTION) /* If this is a host exception in SIE state then leave SIE */ if(realregs->sie_active) ARCH_DEP(sie_exit) (realregs, SIE_HOST_PGMINT); #endif /*defined(FEATURE_INTERPRETIVE_EXECUTION)*/ /* Absolute address of prefix page */ px = realregs->PX; /* If under SIE use translated to host absolute prefix */ #if defined(_FEATURE_SIE) if(SIE_MODE(regs)) px = regs->sie_px; #endif #if defined(_FEATURE_SIE) if(!SIE_MODE(regs) || /* Interception is mandatory for the following exceptions */ ( #if defined(_FEATURE_PROTECTION_INTERCEPTION_CONTROL) !(code == PGM_PROTECTION_EXCEPTION && (!SIE_FEATB(regs, EC2, PROTEX) || realregs->hostint)) #else /*!defined(_FEATURE_PROTECTION_INTERCEPTION_CONTROL)*/ code != PGM_PROTECTION_EXCEPTION #endif /*!defined(_FEATURE_PROTECTION_INTERCEPTION_CONTROL)*/ #if defined (_FEATURE_PER2) && !((pcode & PGM_PER_EVENT) && SIE_FEATB(regs, M, GPE)) #endif /* defined (_FEATURE_PER2) */ && code != PGM_ADDRESSING_EXCEPTION && code != PGM_SPECIFICATION_EXCEPTION && code != PGM_SPECIAL_OPERATION_EXCEPTION #ifdef FEATURE_VECTOR_FACILITY && code != PGM_VECTOR_OPERATION_EXCEPTION #endif /*FEATURE_VECTOR_FACILITY*/ #if defined(FEATURE_MULTIPLE_CONTROLLED_DATA_SPACE) && !(code == PGM_ALEN_TRANSLATION_EXCEPTION && SIE_FEATB(regs, MX, XC)) && !(code == PGM_ALE_SEQUENCE_EXCEPTION && SIE_FEATB(regs, MX, XC)) && !(code == PGM_EXTENDED_AUTHORITY_EXCEPTION && SIE_FEATB(regs, MX, XC)) #endif /*defined(FEATURE_MULTIPLE_CONTROLLED_DATA_SPACE)*/ /* And conditional for the following exceptions */ && !(code == PGM_OPERATION_EXCEPTION && SIE_FEATB(regs, IC0, OPEREX)) && !(code == PGM_PRIVILEGED_OPERATION_EXCEPTION && SIE_FEATB(regs, IC0, PRIVOP)) #ifdef FEATURE_BASIC_FP_EXTENSIONS && !(code == PGM_DATA_EXCEPTION && (regs->dxc == 1 || regs->dxc == 2) && (regs->CR(0) & CR0_AFP) && !(regs->hostregs->CR(0) & CR0_AFP)) #endif /*FEATURE_BASIC_FP_EXTENSIONS*/ /* Or all exceptions if requested as such */ && !SIE_FEATB(regs, IC0, PGMALL) ) ) { #endif /*defined(_FEATURE_SIE)*/ /* Set the main storage reference and change bits */ STORAGE_KEY(px, regs) |= (STORKEY_REF | STORKEY_CHANGE); /* Point to PSA in main storage */ psa = (void*)(regs->mainstor + px); #if defined(_FEATURE_SIE) #if defined(FEATURE_ESAME) /** FIXME : SEE ISW20090110-1 */ if(code == PGM_MONITOR_EVENT) { zmoncode=psa->moncode; } #endif nointercept = 1; } else { /* This is a guest interruption interception so point to the interruption parm area in the state descriptor rather then the PSA, except for the operation exception */ if(code != PGM_OPERATION_EXCEPTION) { psa = (void*)(regs->hostregs->mainstor + SIE_STATE(regs) + SIE_IP_PSA_OFFSET); /* Set the main storage reference and change bits */ STORAGE_KEY(SIE_STATE(regs), regs->hostregs) |= (STORKEY_REF | STORKEY_CHANGE); #if defined(FEATURE_ESAME) /** FIXME : SEE ISW20090110-1 */ if(code == PGM_MONITOR_EVENT) { PSA *_psa; _psa=(void *)(regs->hostregs->mainstor + SIE_STATE(regs) + SIE_II_PSA_OFFSET); zmoncode=_psa->ioid; } #endif } else { /* Point to PSA in main storage */ psa = (void*)(regs->mainstor + px); /* Set the main storage reference and change bits */ STORAGE_KEY(px, regs) |= (STORKEY_REF | STORKEY_CHANGE); } nointercept = 0; } #endif /*defined(_FEATURE_SIE)*/ #if defined(_FEATURE_PER) /* Handle PER or concurrent PER event */ /* Throw out Stor Alter PER if merged with nullified/suppressed rupt */ if ( IS_IC_PER_SA(realregs) && !IS_IC_PER_STURA(realregs) && (realregs->ip[0] != 0x0E) && !(code == 0x00 || code == 0x06 || code == 0x08 || code == 0x0A || code == 0x0C || code == 0x0D || code == 0x0E || code == 0x1C || code == 0x40) ) OFF_IC_PER_SA(realregs); if( OPEN_IC_PER(realregs) ) { if( CPU_STEPPING_OR_TRACING(realregs, ilc) ) logmsg(_("HHCCP015I CPU%4.4X PER event: code=%4.4X perc=%2.2X " "addr=" F_VADR "\n"), regs->cpuad, pcode, IS_IC_PER(realregs) >> 16, (realregs->psw.IA - ilc) & ADDRESS_MAXWRAP(realregs) ); realregs->perc |= OPEN_IC_PER(realregs) >> ((32 - IC_CR9_SHIFT) - 16); /* Positions 14 and 15 contain zeros if a storage alteration event was not indicated */ //FIXME: is this right?? if( !(OPEN_IC_PER_SA(realregs)) || (OPEN_IC_PER_STURA(realregs)) ) realregs->perc &= 0xFFFC; STORE_HW(psa->perint, realregs->perc); STORE_W(psa->peradr, realregs->peradr); if( IS_IC_PER_SA(realregs) && ACCESS_REGISTER_MODE(&realregs->psw) ) psa->perarid = realregs->peraid; #if defined(_FEATURE_SIE) /* Reset PER pending indication */ if(nointercept) OFF_IC_PER(realregs); #endif } else { pcode &= 0xFF7F; } #endif /*defined(_FEATURE_PER)*/ #if defined(FEATURE_BCMODE) /* For ECMODE, store extended interrupt information in PSA */ if ( ECMODE(&realregs->psw) ) #endif /*defined(FEATURE_BCMODE)*/ { /* Store the program interrupt code at PSA+X'8C' */ psa->pgmint[0] = 0; psa->pgmint[1] = ilc; STORE_HW(psa->pgmint + 2, pcode); /* Store the exception access identification at PSA+160 */ if ( code == PGM_PAGE_TRANSLATION_EXCEPTION || code == PGM_SEGMENT_TRANSLATION_EXCEPTION #if defined(FEATURE_ESAME) || code == PGM_ASCE_TYPE_EXCEPTION || code == PGM_REGION_FIRST_TRANSLATION_EXCEPTION || code == PGM_REGION_SECOND_TRANSLATION_EXCEPTION || code == PGM_REGION_THIRD_TRANSLATION_EXCEPTION #endif /*defined(FEATURE_ESAME)*/ || code == PGM_ALEN_TRANSLATION_EXCEPTION || code == PGM_ALE_SEQUENCE_EXCEPTION || code == PGM_ASTE_VALIDITY_EXCEPTION || code == PGM_ASTE_SEQUENCE_EXCEPTION || code == PGM_ASTE_INSTANCE_EXCEPTION /*@ALR*/ || code == PGM_EXTENDED_AUTHORITY_EXCEPTION #ifdef FEATURE_SUPPRESSION_ON_PROTECTION || code == PGM_PROTECTION_EXCEPTION #endif /*FEATURE_SUPPRESSION_ON_PROTECTION*/ ) { psa->excarid = regs->excarid; if(regs->TEA | TEA_MVPG) psa->opndrid = regs->opndrid; realregs->opndrid = 0; } #if defined(FEATURE_ESAME) /* Store the translation exception address at PSA+168 */ if ( code == PGM_PAGE_TRANSLATION_EXCEPTION || code == PGM_SEGMENT_TRANSLATION_EXCEPTION || code == PGM_ASCE_TYPE_EXCEPTION || code == PGM_REGION_FIRST_TRANSLATION_EXCEPTION || code == PGM_REGION_SECOND_TRANSLATION_EXCEPTION || code == PGM_REGION_THIRD_TRANSLATION_EXCEPTION #ifdef FEATURE_SUPPRESSION_ON_PROTECTION || code == PGM_PROTECTION_EXCEPTION #endif /*FEATURE_SUPPRESSION_ON_PROTECTION*/ ) { STORE_DW(psa->TEA_G, regs->TEA); } /* Store the translation exception address at PSA+172 */ if ( code == PGM_AFX_TRANSLATION_EXCEPTION || code == PGM_ASX_TRANSLATION_EXCEPTION || code == PGM_PRIMARY_AUTHORITY_EXCEPTION || code == PGM_SECONDARY_AUTHORITY_EXCEPTION || code == PGM_SPACE_SWITCH_EVENT || code == PGM_LX_TRANSLATION_EXCEPTION || code == PGM_LFX_TRANSLATION_EXCEPTION /*@ALR*/ || code == PGM_LSX_TRANSLATION_EXCEPTION /*@ALR*/ || code == PGM_LSTE_SEQUENCE_EXCEPTION /*@ALR*/ || code == PGM_EX_TRANSLATION_EXCEPTION) { STORE_FW(psa->TEA_L, regs->TEA); } #else /*!defined(FEATURE_ESAME)*/ /* Store the translation exception address at PSA+144 */ if ( code == PGM_PAGE_TRANSLATION_EXCEPTION || code == PGM_SEGMENT_TRANSLATION_EXCEPTION || code == PGM_AFX_TRANSLATION_EXCEPTION || code == PGM_ASX_TRANSLATION_EXCEPTION || code == PGM_PRIMARY_AUTHORITY_EXCEPTION || code == PGM_SECONDARY_AUTHORITY_EXCEPTION || code == PGM_SPACE_SWITCH_EVENT || code == PGM_LX_TRANSLATION_EXCEPTION || code == PGM_EX_TRANSLATION_EXCEPTION #ifdef FEATURE_SUPPRESSION_ON_PROTECTION || code == PGM_PROTECTION_EXCEPTION #endif /*FEATURE_SUPPRESSION_ON_PROTECTION*/ ) { STORE_FW(psa->tea, regs->TEA); } #endif /*!defined(FEATURE_ESAME)*/ realregs->TEA = 0; /* Store Data exception code in PSA */ if (code == PGM_DATA_EXCEPTION) { STORE_FW(psa->DXC, regs->dxc); #ifdef FEATURE_BASIC_FP_EXTENSIONS /* Load data exception code into FPC register byte 2 */ if(regs->CR(0) & CR0_AFP) { regs->fpc &= ~(FPC_DXC); regs->fpc |= ((regs->dxc << 8)) & FPC_DXC; } #endif /*FEATURE_BASIC_FP_EXTENSIONS*/ } /* Store the monitor class and event code */ if (code == PGM_MONITOR_EVENT) { STORE_HW(psa->monclass, regs->monclass); /* Store the monitor code word at PSA+156 */ /* or doubleword at PSA+176 */ /* ISW20090110-1 ZSIEMCFIX */ /* In the event of a z/Arch guest being */ /* intercepted during a succesful Monitor */ /* call, the monitor code is not stored */ /* at psa->moncode (which is beyond sie2bk->ip */ /* but rather at the same location as an */ /* I/O interrupt would store the SSID */ /* zmoncode points to this location */ /* **** FIXME **** FIXME *** FIXME *** */ /* ---- The determination of the location */ /* of the z/Sie Intercept moncode */ /* should be made more flexible */ /* and should be put somewhere in */ /* esa390.h */ /* **** FIXME **** FIXME *** FIXME *** */ #if defined(FEATURE_ESAME) STORE_DW(zmoncode, regs->MONCODE); #else STORE_W(psa->moncode, regs->MONCODE); #endif } #if defined(FEATURE_PER3) /* Store the breaking event address register in the PSA */ SET_BEAR_REG(regs, regs->bear_ip); STORE_W(psa->bea, regs->bear); #endif /*defined(FEATURE_PER3)*/ } /* end if(ECMODE) */ #if defined(_FEATURE_PROTECTION_INTERCEPTION_CONTROL) realregs->hostint = 0; #endif /*defined(_FEATURE_PROTECTION_INTERCEPTION_CONTROL)*/ #if defined(_FEATURE_SIE) if(nointercept) { #endif /*defined(_FEATURE_SIE)*/ //FIXME: Why are we getting intlock here?? // OBTAIN_INTLOCK(realregs); /* Store current PSW at PSA+X'28' or PSA+X'150' for ESAME */ ARCH_DEP(store_psw) (realregs, psa->pgmold); /* Load new PSW from PSA+X'68' or PSA+X'1D0' for ESAME */ if ( (code = ARCH_DEP(load_psw) (realregs, psa->pgmnew)) ) { #if defined(_FEATURE_SIE) if(SIE_MODE(realregs)) { // RELEASE_INTLOCK(realregs); longjmp(realregs->progjmp, pcode); } else #endif /*defined(_FEATURE_SIE)*/ { logmsg (_("HHCCP016I CPU%4.4X: Program interrupt loop: "), realregs->cpuad); display_psw (realregs); OBTAIN_INTLOCK(realregs); realregs->cpustate = CPUSTATE_STOPPING; ON_IC_INTERRUPT(realregs); RELEASE_INTLOCK(realregs); } } // RELEASE_INTLOCK(realregs); longjmp(realregs->progjmp, SIE_NO_INTERCEPT); #if defined(_FEATURE_SIE) } longjmp (realregs->progjmp, pcode); #endif /*defined(_FEATURE_SIE)*/ } /* end function ARCH_DEP(program_interrupt) */ /*-------------------------------------------------------------------*/ /* Load restart new PSW */ /*-------------------------------------------------------------------*/ static void ARCH_DEP(restart_interrupt) (REGS *regs) { int rc; /* Return code */ PSA *psa; /* -> Prefixed storage area */ PTT(PTT_CL_INF,"*RESTART",regs->cpuad,regs->cpustate,regs->psw.IA_L); /* Set the main storage reference and change bits */ STORAGE_KEY(regs->PX, regs) |= (STORKEY_REF | STORKEY_CHANGE); /* Zeroize the interrupt code in the PSW */ regs->psw.intcode = 0; /* Point to PSA in main storage */ psa = (PSA*)(regs->mainstor + regs->PX); /* Store current PSW at PSA+X'8' or PSA+X'120' for ESAME */ ARCH_DEP(store_psw) (regs, psa->RSTOLD); /* Load new PSW from PSA+X'0' or PSA+X'1A0' for ESAME */ rc = ARCH_DEP(load_psw) (regs, psa->RSTNEW); if ( rc == 0) { regs->opinterv = 0; regs->cpustate = CPUSTATE_STARTED; } RELEASE_INTLOCK(regs); if ( rc ) regs->program_interrupt(regs, rc); longjmp (regs->progjmp, SIE_INTERCEPT_RESTART); } /* end function restart_interrupt */ /*-------------------------------------------------------------------*/ /* Perform I/O interrupt if pending */ /* Note: The caller MUST hold the interrupt lock (sysblk.intlock) */ /*-------------------------------------------------------------------*/ void ARCH_DEP(perform_io_interrupt) (REGS *regs) { int rc; /* Return code */ int icode; /* Intercept code */ PSA *psa; /* -> Prefixed storage area */ U32 ioparm; /* I/O interruption parameter*/ U32 ioid; /* I/O interruption address */ U32 iointid; /* I/O interruption ident */ RADR pfx; /* Prefix */ DBLWRD csw; /* CSW for S/370 channels */ /* Test and clear pending I/O interrupt */ icode = ARCH_DEP(present_io_interrupt) (regs, &ioid, &ioparm, &iointid, csw); /* Exit if no interrupt was presented */ if (icode == 0) return; PTT(PTT_CL_IO,"*IOINT",ioid,ioparm,iointid); #if defined(_FEATURE_IO_ASSIST) if(SIE_MODE(regs) && icode != SIE_NO_INTERCEPT) { /* Point to SIE copy of PSA in state descriptor */ psa = (void*)(regs->hostregs->mainstor + SIE_STATE(regs) + SIE_II_PSA_OFFSET); STORAGE_KEY(SIE_STATE(regs), regs->hostregs) |= (STORKEY_REF | STORKEY_CHANGE); } else #endif { /* Point to PSA in main storage */ pfx = #if defined(_FEATURE_SIE) SIE_MODE(regs) ? regs->sie_px : #endif regs->PX; psa = (void*)(regs->mainstor + pfx); STORAGE_KEY(pfx, regs) |= (STORKEY_REF | STORKEY_CHANGE); } #ifdef FEATURE_S370_CHANNEL /* Store the channel status word at PSA+X'40' */ memcpy (psa->csw, csw, 8); /* Set the interrupt code to the I/O device address */ regs->psw.intcode = ioid; /* For ECMODE, store the I/O device address at PSA+X'B8' */ if (ECMODE(®s->psw)) STORE_FW(psa->ioid, ioid); /* Trace the I/O interrupt */ if (CPU_STEPPING_OR_TRACING(regs, 0)) logmsg (_("HHCCP044I I/O interrupt code=%4.4X " "CSW=%2.2X%2.2X%2.2X%2.2X %2.2X%2.2X%2.2X%2.2X\n"), regs->psw.intcode, csw[0], csw[1], csw[2], csw[3], csw[4], csw[5], csw[6], csw[7]); #endif /*FEATURE_S370_CHANNEL*/ #ifdef FEATURE_CHANNEL_SUBSYSTEM /* Store X'0001' + subchannel number at PSA+X'B8' */ STORE_FW(psa->ioid, ioid); /* Store the I/O interruption parameter at PSA+X'BC' */ STORE_FW(psa->ioparm, ioparm); #if defined(FEATURE_ESAME) || defined(_FEATURE_IO_ASSIST) /* Store the I/O interruption identification word at PSA+X'C0' */ STORE_FW(psa->iointid, iointid); #endif /*defined(FEATURE_ESAME)*/ /* Trace the I/O interrupt */ if (CPU_STEPPING_OR_TRACING(regs, 0)) #if !defined(FEATURE_ESAME) && !defined(_FEATURE_IO_ASSIST) logmsg (_("HHCCP045I I/O interrupt code=%8.8X parm=%8.8X\n"), ioid, ioparm); #else /*defined(FEATURE_ESAME)*/ logmsg (_("HHCCP046I I/O interrupt code=%8.8X parm=%8.8X id=%8.8X\n"), ioid, ioparm, iointid); #endif /*defined(FEATURE_ESAME)*/ #endif /*FEATURE_CHANNEL_SUBSYSTEM*/ #if defined(_FEATURE_IO_ASSIST) if(icode == SIE_NO_INTERCEPT) #endif { /* Store current PSW at PSA+X'38' or PSA+X'170' for ESAME */ ARCH_DEP(store_psw) ( regs, psa->iopold ); /* Load new PSW from PSA+X'78' or PSA+X'1F0' for ESAME */ rc = ARCH_DEP(load_psw) ( regs, psa->iopnew ); if ( rc ) { RELEASE_INTLOCK(regs); regs->program_interrupt (regs, rc); } } RELEASE_INTLOCK(regs); longjmp(regs->progjmp, icode); } /* end function perform_io_interrupt */ /*-------------------------------------------------------------------*/ /* Perform Machine Check interrupt if pending */ /* Note: The caller MUST hold the interrupt lock (sysblk.intlock) */ /*-------------------------------------------------------------------*/ static void ARCH_DEP(perform_mck_interrupt) (REGS *regs) { int rc; /* Return code */ PSA *psa; /* -> Prefixed storage area */ U64 mcic; /* Mach.check interrupt code */ U32 xdmg; /* External damage code */ RADR fsta; /* Failing storage address */ /* Test and clear pending machine check interrupt */ rc = ARCH_DEP(present_mck_interrupt) (regs, &mcic, &xdmg, &fsta); /* Exit if no machine check was presented */ if (rc == 0) return; /* Set the main storage reference and change bits */ STORAGE_KEY(regs->PX, regs) |= (STORKEY_REF | STORKEY_CHANGE); /* Point to the PSA in main storage */ psa = (void*)(regs->mainstor + regs->PX); /* Store registers in machine check save area */ ARCH_DEP(store_status) (regs, regs->PX); #if !defined(FEATURE_ESAME) // ZZ /* Set the extended logout area to zeros */ memset(psa->storepsw, 0, 16); #endif /* Store the machine check interrupt code at PSA+232 */ STORE_DW(psa->mckint, mcic); /* Trace the machine check interrupt */ if (CPU_STEPPING_OR_TRACING(regs, 0)) logmsg (_("HHCCP022I Machine Check code=%16.16" I64_FMT "u\n"), (long long)mcic); /* Store the external damage code at PSA+244 */ STORE_FW(psa->xdmgcode, xdmg); #if defined(FEATURE_ESAME) /* Store the failing storage address at PSA+248 */ STORE_DW(psa->mcstorad, fsta); #else /*!defined(FEATURE_ESAME)*/ /* Store the failing storage address at PSA+248 */ STORE_FW(psa->mcstorad, fsta); #endif /*!defined(FEATURE_ESAME)*/ /* Store current PSW at PSA+X'30' */ ARCH_DEP(store_psw) ( regs, psa->mckold ); /* Load new PSW from PSA+X'70' */ rc = ARCH_DEP(load_psw) ( regs, psa->mcknew ); RELEASE_INTLOCK(regs); if ( rc ) regs->program_interrupt (regs, rc); longjmp (regs->progjmp, SIE_INTERCEPT_MCK); } /* end function perform_mck_interrupt */ #if !defined(_GEN_ARCH) REGS *s370_run_cpu (int cpu, REGS *oldregs); REGS *s390_run_cpu (int cpu, REGS *oldregs); REGS *z900_run_cpu (int cpu, REGS *oldregs); static REGS *(* run_cpu[GEN_MAXARCH]) (int cpu, REGS *oldregs) = { #if defined(_370) s370_run_cpu, #endif #if defined(_390) s390_run_cpu, #endif #if defined(_900) z900_run_cpu #endif }; /*-------------------------------------------------------------------*/ /* CPU instruction execution thread */ /*-------------------------------------------------------------------*/ void *cpu_thread (int *ptr) { REGS *regs = NULL; int cpu = *ptr; OBTAIN_INTLOCK(NULL); /* Signal cpu has started */ signal_condition (&sysblk.cpucond); /* Increment number of CPUs online */ sysblk.cpus++; /* Set hi CPU */ if (cpu >= sysblk.hicpu) sysblk.hicpu = cpu + 1; /* Start the TOD clock and CPU timer thread */ if (!sysblk.todtid) { if ( create_thread (&sysblk.todtid, DETACHED, timer_update_thread, NULL, "timer_update_thread") ) { logmsg (_("HHCCP006S Cannot create timer thread: %s\n"), strerror(errno)); RELEASE_INTLOCK(NULL); return NULL; } } /* Set root mode in order to set priority */ SETMODE(ROOT); /* Set CPU thread priority */ if (setpriority(PRIO_PROCESS, 0, sysblk.cpuprio)) logmsg (_("HHCCP001W CPU%4.4X thread set priority %d failed: %s\n"), cpu, sysblk.cpuprio, strerror(errno)); /* Back to user mode */ SETMODE(USER); /* Display thread started message on control panel */ logmsg (_("HHCCP002I CPU%4.4X thread started: tid="TIDPAT", pid=%d, " "priority=%d\n"), cpu, thread_id(), getpid(), getpriority(PRIO_PROCESS,0)); /* Execute the program in specified mode */ do { regs = run_cpu[sysblk.arch_mode] (cpu, regs); } while (regs); /* Decrement number of CPUs online */ sysblk.cpus--; /* Reset hi cpu */ if (cpu + 1 >= sysblk.hicpu) { int i; for (i = MAX_CPU_ENGINES - 1; i >= 0; i--) if (IS_CPU_ONLINE(i)) break; sysblk.hicpu = i + 1; } /* Signal cpu has terminated */ signal_condition (&sysblk.cpucond); /* Display thread ended message on control panel */ logmsg (_("HHCCP008I CPU%4.4X thread ended: tid="TIDPAT", pid=%d\n"), cpu, thread_id(), getpid()); RELEASE_INTLOCK(NULL); return NULL; } void s370_set_jump_pointers(REGS *regs, int jump); void s390_set_jump_pointers(REGS *regs, int jump); void z900_set_jump_pointers(REGS *regs, int jump); /*-------------------------------------------------------------------*/ /* Initialize a CPU */ /*-------------------------------------------------------------------*/ int cpu_init (int cpu, REGS *regs, REGS *hostregs) { int i; obtain_lock (&sysblk.cpulock[cpu]); regs->cpuad = cpu; regs->cpubit = CPU_BIT(cpu); regs->arch_mode = sysblk.arch_mode; regs->mainstor = sysblk.mainstor; regs->sysblk = &sysblk; /* * ISW20060125 : LINE REMOVED : This is the job of * the INITIAL CPU RESET */ #if 0 regs->psa = (PSA*)regs->mainstor; #endif regs->storkeys = sysblk.storkeys; regs->mainlim = sysblk.mainsize - 1; regs->tod_epoch = get_tod_epoch(); initialize_condition (®s->intcond); regs->cpulock = &sysblk.cpulock[cpu]; #if defined(_FEATURE_VECTOR_FACILITY) regs->vf = &sysblk.vf[cpu]; regs->vf->online = (cpu < sysblk.numvec); #endif /*defined(_FEATURE_VECTOR_FACILITY)*/ initial_cpu_reset(regs); if (hostregs == NULL) { regs->cpustate = CPUSTATE_STOPPING; ON_IC_INTERRUPT(regs); regs->hostregs = regs; regs->host = 1; sysblk.regs[cpu] = regs; sysblk.config_mask |= regs->cpubit; sysblk.started_mask |= regs->cpubit; } else { hostregs->guestregs = regs; regs->hostregs = hostregs; regs->guestregs = regs; regs->guest = 1; regs->sie_mode = 1; regs->opinterv = 0; regs->cpustate = CPUSTATE_STARTED; } /* Initialize accelerated lookup fields */ regs->CR_G(CR_ASD_REAL) = TLB_REAL_ASD; for(i = 0; i < 16; i++) regs->aea_ar[i] = CR_ASD_REAL; regs->aea_ar[USE_INST_SPACE] = CR_ASD_REAL; regs->aea_ar[USE_REAL_ADDR] = CR_ASD_REAL; regs->aea_ar[USE_PRIMARY_SPACE] = 1; regs->aea_ar[USE_SECONDARY_SPACE] = 7; regs->aea_ar[USE_HOME_SPACE] = 13; /* Initialize opcode table pointers */ set_opcode_pointers (regs); /* Set multi-byte jump code pointers */ #if defined(_370) s370_set_jump_pointers(regs, 0); #endif #if defined(_390) s390_set_jump_pointers(regs, 0); #endif #if defined(_900) z900_set_jump_pointers(regs, 0); #endif regs->configured = 1; release_lock (&sysblk.cpulock[cpu]); #if defined(FEATURE_CONFIGURATION_TOPOLOGY_FACILITY) /* Set topology-change-report-pending condition */ sysblk.topchnge = 1; #endif /*defined(FEATURE_CONFIGURATION_TOPOLOGY_FACILITY)*/ return 0; } /*-------------------------------------------------------------------*/ /* Uninitialize a CPU */ /*-------------------------------------------------------------------*/ void *cpu_uninit (int cpu, REGS *regs) { if (regs->host) { obtain_lock (&sysblk.cpulock[cpu]); if (regs->guestregs) { cpu_uninit (cpu, regs->guestregs); free (regs->guestregs); } } destroy_condition(®s->intcond); if (regs->host) { #ifdef FEATURE_VECTOR_FACILITY /* Mark Vector Facility offline */ regs->vf->online = 0; #endif /*FEATURE_VECTOR_FACILITY*/ /* Remove CPU from all CPU bit masks */ sysblk.config_mask &= ~CPU_BIT(cpu); sysblk.started_mask &= ~CPU_BIT(cpu); sysblk.waiting_mask &= ~CPU_BIT(cpu); sysblk.regs[cpu] = NULL; release_lock (&sysblk.cpulock[cpu]); } #if defined(FEATURE_CONFIGURATION_TOPOLOGY_FACILITY) /* Set topology-change-report-pending condition */ sysblk.topchnge = 1; #endif /*defined(FEATURE_CONFIGURATION_TOPOLOGY_FACILITY)*/ return NULL; } #endif /*!defined(_GEN_ARCH)*/ /*-------------------------------------------------------------------*/ /* Process interrupt */ /*-------------------------------------------------------------------*/ void (ATTR_REGPARM(1) ARCH_DEP(process_interrupt))(REGS *regs) { /* Process PER program interrupts */ if( OPEN_IC_PER(regs) ) regs->program_interrupt (regs, PGM_PER_EVENT); /* Obtain the interrupt lock */ OBTAIN_INTLOCK(regs); OFF_IC_INTERRUPT(regs); regs->tracing = (sysblk.inststep || sysblk.insttrace); /* Ensure psw.IA is set and invalidate the aia */ INVALIDATE_AIA(regs); /* Perform invalidation */ if (unlikely(regs->invalidate)) ARCH_DEP(invalidate_tlbe)(regs, regs->invalidate_main); /* Take interrupts if CPU is not stopped */ if (likely(regs->cpustate == CPUSTATE_STARTED)) { /* Process machine check interrupt */ if ( OPEN_IC_MCKPENDING(regs) ) { PERFORM_SERIALIZATION (regs); PERFORM_CHKPT_SYNC (regs); ARCH_DEP (perform_mck_interrupt) (regs); } /* Process external interrupt */ if ( OPEN_IC_EXTPENDING(regs) ) { PERFORM_SERIALIZATION (regs); PERFORM_CHKPT_SYNC (regs); ARCH_DEP (perform_external_interrupt) (regs); } /* Process I/O interrupt */ if (IS_IC_IOPENDING) { if ( OPEN_IC_IOPENDING(regs) ) { PERFORM_SERIALIZATION (regs); PERFORM_CHKPT_SYNC (regs); ARCH_DEP (perform_io_interrupt) (regs); } else WAKEUP_CPU_MASK(sysblk.waiting_mask); } } /*CPU_STARTED*/ /* If CPU is stopping, change status to stopped */ if (unlikely(regs->cpustate == CPUSTATE_STOPPING)) { /* Change CPU status to stopped */ regs->opinterv = 0; regs->cpustate = CPUSTATE_STOPPED; /* Thread exit (note - intlock still held) */ if (!regs->configured) longjmp(regs->exitjmp, SIE_NO_INTERCEPT); /* If initial CPU reset pending then perform reset */ if (regs->sigpireset) { PERFORM_SERIALIZATION (regs); PERFORM_CHKPT_SYNC (regs); ARCH_DEP (initial_cpu_reset) (regs); RELEASE_INTLOCK(regs); longjmp(regs->progjmp, SIE_NO_INTERCEPT); } /* If a CPU reset is pending then perform the reset */ if (regs->sigpreset) { PERFORM_SERIALIZATION (regs); PERFORM_CHKPT_SYNC (regs); ARCH_DEP(cpu_reset) (regs); RELEASE_INTLOCK(regs); longjmp(regs->progjmp, SIE_NO_INTERCEPT); } /* Store status at absolute location 0 if requested */ if (IS_IC_STORSTAT(regs)) { OFF_IC_STORSTAT(regs); ARCH_DEP(store_status) (regs, 0); logmsg (_("HHCCP010I CPU%4.4X store status completed.\n"), regs->cpuad); /* ISW 20071102 : Do not return via longjmp here. */ /* process_interrupt needs to finish putting the */ /* CPU in its manual state */ /* RELEASE_INTLOCK(regs); longjmp(regs->progjmp, SIE_NO_INTERCEPT); */ } } /*CPUSTATE_STOPPING*/ /* Perform restart interrupt if pending */ if ( IS_IC_RESTART(regs) ) { PERFORM_SERIALIZATION (regs); PERFORM_CHKPT_SYNC (regs); OFF_IC_RESTART(regs); ARCH_DEP(restart_interrupt) (regs); } /* end if(restart) */ /* This is where a stopped CPU will wait */ if (unlikely(regs->cpustate == CPUSTATE_STOPPED)) { S64 saved_timer = cpu_timer(regs); regs->ints_state = IC_INITIAL_STATE; sysblk.started_mask ^= regs->cpubit; sysblk.intowner = LOCK_OWNER_NONE; /* Wait while we are STOPPED */ wait_condition (®s->intcond, &sysblk.intlock); /* Wait while SYNCHRONIZE_CPUS is in progress */ while (sysblk.syncing) wait_condition (&sysblk.sync_bc_cond, &sysblk.intlock); sysblk.intowner = regs->cpuad; sysblk.started_mask |= regs->cpubit; regs->ints_state |= sysblk.ints_state; set_cpu_timer(regs,saved_timer); ON_IC_INTERRUPT(regs); /* Purge the lookaside buffers */ ARCH_DEP(purge_tlb) (regs); #if defined(FEATURE_ACCESS_REGISTERS) ARCH_DEP(purge_alb) (regs); #endif /*defined(FEATURE_ACCESS_REGISTERS)*/ /* If the architecture mode has changed we must adapt */ if(sysblk.arch_mode != regs->arch_mode) longjmp(regs->archjmp,SIE_NO_INTERCEPT); RELEASE_INTLOCK(regs); longjmp(regs->progjmp, SIE_NO_INTERCEPT); } /*CPUSTATE_STOPPED*/ /* Test for wait state */ if (WAITSTATE(®s->psw)) { #ifdef OPTION_MIPS_COUNTING regs->waittod = host_tod(); #endif /* Test for disabled wait PSW and issue message */ if( IS_IC_DISABLED_WAIT_PSW(regs) ) { logmsg (_("HHCCP011I CPU%4.4X: Disabled wait state\n" " "), regs->cpuad); display_psw (regs); regs->cpustate = CPUSTATE_STOPPING; RELEASE_INTLOCK(regs); longjmp(regs->progjmp, SIE_NO_INTERCEPT); } /* Indicate we are giving up intlock */ sysblk.intowner = LOCK_OWNER_NONE; sysblk.waiting_mask |= regs->cpubit; /* Wait for interrupt */ wait_condition (®s->intcond, &sysblk.intlock); /* Wait while SYNCHRONIZE_CPUS is in progress */ while (sysblk.syncing) wait_condition (&sysblk.sync_bc_cond, &sysblk.intlock); /* Indicate we now own intlock */ sysblk.waiting_mask ^= regs->cpubit; sysblk.intowner = regs->cpuad; #ifdef OPTION_MIPS_COUNTING /* Calculate the time we waited */ regs->waittime += host_tod() - regs->waittod; regs->waittod = 0; #endif RELEASE_INTLOCK(regs); longjmp(regs->progjmp, SIE_NO_INTERCEPT); } /* end if(wait) */ /* Release the interrupt lock */ RELEASE_INTLOCK(regs); return; } /* process_interrupt */ /*-------------------------------------------------------------------*/ /* Run CPU */ /*-------------------------------------------------------------------*/ REGS *ARCH_DEP(run_cpu) (int cpu, REGS *oldregs) { BYTE *ip; REGS regs; if (oldregs) { memcpy (®s, oldregs, sizeof(REGS)); free (oldregs); regs.hostregs = ®s; if (regs.guestregs) regs.guestregs->hostregs = ®s; sysblk.regs[cpu] = ®s; release_lock(&sysblk.cpulock[cpu]); logmsg (_("HHCCP007I CPU%4.4X architecture mode set to %s\n"), cpu, get_arch_mode_string(®s)); } else { memset (®s, 0, sizeof(REGS)); if (cpu_init (cpu, ®s, NULL)) return NULL; logmsg (_("HHCCP003I CPU%4.4X architecture mode %s\n"), cpu, get_arch_mode_string(®s)); #ifdef FEATURE_VECTOR_FACILITY if (regs->vf->online) logmsg (_("HHCCP004I CPU%4.4X Vector Facility online\n"), cpu); #endif /*FEATURE_VECTOR_FACILITY*/ } regs.program_interrupt = &ARCH_DEP(program_interrupt); #if defined(FEATURE_TRACING) regs.trace_br = (func)&ARCH_DEP(trace_br); #endif regs.tracing = (sysblk.inststep || sysblk.insttrace); regs.ints_state |= sysblk.ints_state; /* Establish longjmp destination for cpu thread exit */ if (setjmp(regs.exitjmp)) return cpu_uninit(cpu, ®s); /* Establish longjmp destination for architecture switch */ setjmp(regs.archjmp); /* Switch architecture mode if appropriate */ if(sysblk.arch_mode != regs.arch_mode) { PTT(PTT_CL_INF,"*SETARCH",regs.arch_mode,sysblk.arch_mode,cpu); regs.arch_mode = sysblk.arch_mode; oldregs = malloc (sizeof(REGS)); if (oldregs) { memcpy(oldregs, ®s, sizeof(REGS)); obtain_lock(&sysblk.cpulock[cpu]); } else { logmsg (_("HHCCP080E CPU%4.4X malloc failed for archjmp regs: %s\n"), cpu, strerror(errno)); cpu_uninit (cpu, ®s); } return oldregs; } RELEASE_INTLOCK(®s); /* Establish longjmp destination for program check */ setjmp(regs.progjmp); /* Set `execflag' to 0 in case EXecuted instruction did a longjmp() */ regs.execflag = 0; do { if (INTERRUPT_PENDING(®s)) ARCH_DEP(process_interrupt)(®s); ip = INSTRUCTION_FETCH(®s, 0); regs.instcount++; EXECUTE_INSTRUCTION(ip, ®s); do { UNROLLED_EXECUTE(®s); UNROLLED_EXECUTE(®s); UNROLLED_EXECUTE(®s); UNROLLED_EXECUTE(®s); UNROLLED_EXECUTE(®s); UNROLLED_EXECUTE(®s); regs.instcount += 12; UNROLLED_EXECUTE(®s); UNROLLED_EXECUTE(®s); UNROLLED_EXECUTE(®s); UNROLLED_EXECUTE(®s); UNROLLED_EXECUTE(®s); UNROLLED_EXECUTE(®s); } while (!INTERRUPT_PENDING(®s)); } while (1); /* Never reached */ return NULL; } /* end function cpu_thread */ /*-------------------------------------------------------------------*/ /* Process Trace */ /*-------------------------------------------------------------------*/ void ARCH_DEP(process_trace)(REGS *regs) { int shouldtrace = 0; /* 1=Trace instruction */ int shouldstep = 0; /* 1=Wait for start command */ /* Test for trace */ if (CPU_TRACING(regs, 0)) shouldtrace = 1; /* Test for step */ if (CPU_STEPPING(regs, 0)) shouldstep = 1; /* Display the instruction */ if (shouldtrace || shouldstep) { BYTE *ip = regs->ip < regs->aip ? regs->inst : regs->ip; ARCH_DEP(display_inst) (regs, ip); } /* Stop the CPU */ if (shouldstep) { REGS *hostregs = regs->hostregs; S64 saved_timer[2]; OBTAIN_INTLOCK(hostregs); #ifdef OPTION_MIPS_COUNTING hostregs->waittod = host_tod(); #endif /* The CPU timer is not decremented for a CPU that is in the manual state (e.g. stopped in single step mode) */ saved_timer[0] = cpu_timer(regs); saved_timer[1] = cpu_timer(hostregs); hostregs->cpustate = CPUSTATE_STOPPED; sysblk.started_mask &= ~hostregs->cpubit; hostregs->stepwait = 1; sysblk.intowner = LOCK_OWNER_NONE; while (hostregs->cpustate == CPUSTATE_STOPPED) { wait_condition (&hostregs->intcond, &sysblk.intlock); } sysblk.intowner = hostregs->cpuad; hostregs->stepwait = 0; sysblk.started_mask |= hostregs->cpubit; set_cpu_timer(regs,saved_timer[0]); set_cpu_timer(hostregs,saved_timer[1]); #ifdef OPTION_MIPS_COUNTING hostregs->waittime += host_tod() - hostregs->waittod; hostregs->waittod = 0; #endif RELEASE_INTLOCK(hostregs); } } /* process_trace */ /*-------------------------------------------------------------------*/ /* Set Jump Pointers */ /* */ /* For supported architectures and certain multi-byte instructions, */ /* EXECUTE_INSTRUCTION and UNROLLED_EXECUTE call a label in this */ /* function which does a jump to the real instruction. */ /* */ /* The reason why we use labels instead of individual pointers is */ /* that if -fomit-frame-pointer is omitted then the backframe */ /* isn't pushed onto the stack. */ /* */ /* The reason why this routine is in cpu.c is an attempt to provide */ /* locality with the corresponding run_cpu function. */ /* */ /* This routine is called from cpu_init */ /* */ /*-------------------------------------------------------------------*/ void ARCH_DEP(set_jump_pointers) (REGS *regs, int jump) { #if defined(MULTI_BYTE_ASSIST) /* Use `switch' to confuse smart-ass optimizing compilers */ switch (jump) { #if defined(MULTI_BYTE_ASSIST_IA32) case 0xa7: jump_a7xx: __asm__ ( "movzbl 1(%%eax),%%ecx\n\t" "jmp *%c0(%%edx,%%ecx,4)" : : "i" (offsetof(REGS,ARCH_DEP(opcode_a7xx))) ); return; case 0xb2: jump_b2xx: __asm__ ( "movzbl 1(%%eax),%%ecx\n\t" "jmp *%c0(%%edx,%%ecx,4)" : : "i" (offsetof(REGS,ARCH_DEP(opcode_b2xx))) ); return; case 0xb9: jump_b9xx: __asm__ ( "movzbl 1(%%eax),%%ecx\n\t" "jmp *%c0(%%edx,%%ecx,4)" : : "i" (offsetof(REGS,ARCH_DEP(opcode_b9xx))) ); return; #if defined(FEATURE_ESAME) || defined(FEATURE_ESAME_N3_ESA390) case 0xc0: jump_c0xx: __asm__ ( "movzbl 1(%%eax),%%ecx\n\t" "jmp *%c0(%%edx,%%ecx,4)" : : "i" (offsetof(REGS,ARCH_DEP(opcode_c0xx))) ); return; case 0xe3: jump_e3xx: __asm__ ( "movzbl 5(%%eax),%%ecx\n\t" "jmp *%c0(%%edx,%%ecx,4)" : : "i" (offsetof(REGS,ARCH_DEP(opcode_e3xx))) ); return; case 0xeb: #endif /* defined(FEATURE_ESAME) || defined(FEATURE_ESAME_N3_ESA390) */ jump_ebxx: __asm__ ( "movzbl 5(%%eax),%%ecx\n\t" "jmp *%c0(%%edx,%%ecx,4)" : : "i" (offsetof(REGS,ARCH_DEP(opcode_ebxx))) ); return; #endif /* defined(MULTI_BYTE_ASSIST_IA32) */ } /* switch(jump) */ regs->ARCH_DEP(opcode_table)[0xa7] = &&jump_a7xx; regs->ARCH_DEP(opcode_table)[0xb2] = &&jump_b2xx; regs->ARCH_DEP(opcode_table)[0xb9] = &&jump_b9xx; #if defined(FEATURE_ESAME) || defined(FEATURE_ESAME_N3_ESA390) regs->ARCH_DEP(opcode_table)[0xc0] = &&jump_c0xx; regs->ARCH_DEP(opcode_table)[0xe3] = &&jump_e3xx; #endif /* defined(FEATURE_ESAME) || defined(FEATURE_ESAME_N3_ESA390) */ regs->ARCH_DEP(opcode_table)[0xeb] = &&jump_ebxx; #else /* !defined(MULTI_BYTE_ASSIST) */ UNREFERENCED(regs); UNREFERENCED(jump); #endif /* !defined(MULTI_BYTE_ASSIST) */ } #if !defined(_GEN_ARCH) #if defined(_ARCHMODE2) #define _GEN_ARCH _ARCHMODE2 #include "cpu.c" #endif #if defined(_ARCHMODE3) #undef _GEN_ARCH #define _GEN_ARCH _ARCHMODE3 #include "cpu.c" #endif /*-------------------------------------------------------------------*/ /* Copy program status word */ /*-------------------------------------------------------------------*/ DLL_EXPORT void copy_psw (REGS *regs, BYTE *addr) { REGS cregs; memcpy(&cregs, regs, sysblk.regs_copy_len); switch(cregs.arch_mode) { #if defined(_370) case ARCH_370: s370_store_psw(&cregs, addr); break; #endif #if defined(_390) case ARCH_390: s390_store_psw(&cregs, addr); break; #endif #if defined(_900) case ARCH_900: z900_store_psw(&cregs, addr); break; #endif } } /* end function copy_psw */ /*-------------------------------------------------------------------*/ /* Display program status word */ /*-------------------------------------------------------------------*/ void display_psw (REGS *regs) { QWORD qword; /* quadword work area */ memset(qword, 0, sizeof(qword)); if( regs->arch_mode != ARCH_900 ) { copy_psw (regs, qword); logmsg (_("PSW=%2.2X%2.2X%2.2X%2.2X %2.2X%2.2X%2.2X%2.2X\n"), qword[0], qword[1], qword[2], qword[3], qword[4], qword[5], qword[6], qword[7]); } else { copy_psw (regs, qword); logmsg (_("PSW=%2.2X%2.2X%2.2X%2.2X %2.2X%2.2X%2.2X%2.2X " "%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X\n"), qword[0], qword[1], qword[2], qword[3], qword[4], qword[5], qword[6], qword[7], qword[8], qword[9], qword[10], qword[11], qword[12], qword[13], qword[14], qword[15]); } } /* end function display_psw */ const char* arch_name[GEN_MAXARCH] = { #if defined(_370) _ARCH_370_NAME, #endif #if defined(_390) _ARCH_390_NAME, #endif #if defined(_900) _ARCH_900_NAME #endif }; const char* get_arch_mode_string(REGS* regs) { if (!regs) return arch_name[sysblk.arch_mode]; else return arch_name[regs->arch_mode]; } #endif /*!defined(_GEN_ARCH)*/ hercules-3.07/cpuint.h000644 000765 000765 00000062633 11321734033 016425 0ustar00jmaynardjmaynard000000 000000 /* CPUINT.H (c) Copyright Jan Jaeger, 2001-2009 */ /* Hercules Interrupt State and Mask Definitions */ // $Id: cpuint.h 5553 2009-12-23 17:34:16Z ivan $ /********************************************************************** Interrupts_State & Interrupts_Mask bits definition (Initial_Mask=800E) Machine check, PER and external interrupt subclass bit positions are fixed by the architecture and cannot be changed Floating interrupts are made pending to all CPUs, and are recorded in the sysblk structure, CPU specific interrupts are recorded in the regs structure. hi0m mmmm pppp p00p xxxx xxxx xxxx h0hs : type U32 || | |||| |||| |--| |||| |||| |||| |-|| h:mask is always '1' || | |||| |||| | | |||| |||| |||| | || s:state is always '1' || | |||| |||| | | |||| |||| |||| | |+--> '1' : PSW_WAIT || | |||| |||| | | |||| |||| |||| | +---> '1' : RESTART || | |||| |||| | | |||| |||| |||| | (available) || | |||| |||| | | |||| |||| |||| +-----> '1' : STORSTAT || | |||| |||| | | |||| |||| |||| || | |||| |||| | | |||| |||| |||+-------> '1' : ETR || | |||| |||| | | |||| |||| ||+--------> '1' : EXTSIG || | |||| |||| | | |||| |||| |+---------> '1' : INTKEY || | |||| |||| | | |||| |||| +----------> '1' : ITIMER || | |||| |||| | | |||| |||| || | |||| |||| | | |||| |||+------------> '1' : ECPS VTIMER || | |||| |||| | | |||| ||+-------------> '1' : SERVSIG || | |||| |||| | | |||| |+--------------> '1' : PTIMER || | |||| |||| | | |||| +---------------> '1' : CLKC || | |||| |||| | | |||| || | |||| |||| | | |||+-----------------> '1' : TODSYNC || | |||| |||| | | ||+------------------> '1' : EXTCALL || | |||| |||| | | |+-------------------> '1' : EMERSIG || | |||| |||| | | +--------------------> '1' : MALFALT || | |||| |||| | | || | |||| |||| | +----------------------> '1' : PER IFNUL || | |||| |||| | || | |||| |||| | || | |||| |||| +-------------------------> '1' : PER STURA || | |||| |||| || | |||| |||+---------------------------> '1' : PER GRA || | |||| ||+----------------------------> '1' : PER SA || | |||| |+-----------------------------> '1' : PER IF || | |||| +------------------------------> '1' : PER SB || | |||| || | |||+--------------------------------> '1' : WARNING || | ||+---------------------------------> '1' : XDMGRPT || | |+----------------------------------> '1' : DGRDRPT || | +-----------------------------------> '1' : RCVYRPT || | || +-------------------------------------> '1' : CHANRPT || |+---------------------------------------> '1' : IO +----------------------------------------> '1' : INTERRUPT possible **********************************************************************/ // Hercules internal bit# macro: bit numbers are referenced counting // from the RIGHT to left (i.e. 31 <-- 0) and thus the numerical value // of a set bit is equal to two raised to the power of the bit position. // While this is the COMPLETE OPPOSITE from the way bit numbers are // numbered in IBM architectural reference manuals, we do it this way // anyway since that's the way Intel numbers their bits, thus allowing // us to easily replace bit referencing statements with corresponding // Intel assembler bit manipulation instructions (since Intel is still // the predominant host architecture platform for Hercules) /* The BIT() macro should only be used for bit numbers strictly less than 32 */ #ifndef BIT #define BIT(nr) ( 1 << (nr) ) // (bit# counting from the right) #endif /* The CPU_BIT macro is solely for manipulating the CPU number as a CPU bit in a CPU_BITMAP */ #ifndef CPU_BIT #define CPU_BIT(nr) ( (( CPU_BITMAP ) ( 1 ) ) << ( nr ) ) #endif /* Interrupt bit numbers */ #define IC_INTERRUPT 31 /* 0x80000000 */ #define IC_IO 30 /* 0x40000000 */ #define IC_UNUSED_29 29 /* 0x20000000 */ #define IC_CHANRPT 28 /* 0x10000000 - Architecture dependent (CR14) */ #define IC_RCVYRPT 27 /* 0x08000000 - Architecture dependent (CR14) */ #define IC_DGRDRPT 26 /* 0x04000000 - Architecture dependent (CR14) */ #define IC_XDMGRPT 25 /* 0x02000000 - Architecture dependent (CR14) */ #define IC_WARNING 24 /* 0x01000000 - Architecture dependent (CR14) */ #define IC_PER_SB 23 /* 0x00800000 - Architecture dependent (CR9 >> 8) */ #define IC_PER_IF 22 /* 0x00400000 - Architecture dependent (CR9 >> 8) */ #define IC_PER_SA 21 /* 0x00200000 - Architecture dependent (CR9 >> 8) */ #define IC_PER_GRA 20 /* 0x00100000 - Architecture dependent (CR9 >> 8) */ #define IC_PER_STURA 19 /* 0x00080000 - Architecture dependent (CR9 >> 8) */ #define IC_UNUSED_18 18 /* 0x00040000 */ #define IC_UNUSED_17 17 /* 0x00020000 */ #define IC_PER_IFNUL 16 /* 0x00010000 - Architecture dependent (CR9 >> 8) */ #define IC_MALFALT 15 /* 0x00008000 - Architecture dependent (CR0) */ #define IC_EMERSIG 14 /* 0x00004000 - Architecture dependent (CR0) */ #define IC_EXTCALL 13 /* 0x00002000 - Architecture dependent (CR0) */ #define IC_TODSYNC 12 /* 0x00001000 - Architecture dependent (CR0) */ #define IC_CLKC 11 /* 0x00000800 - Architecture dependent (CR0) */ #define IC_PTIMER 10 /* 0x00000400 - Architecture dependent (CR0) */ #define IC_SERVSIG 9 /* 0x00000200 - Architecture dependent (CR0) */ #define IC_ECPSVTIMER 8 /* 0x00000100 - Not Architecture dependent */ #define IC_ITIMER 7 /* 0x00000080 - Architecture dependent (CR0) */ #define IC_INTKEY 6 /* 0x00000040 - Architecture dependent (CR0) */ #define IC_EXTSIG 5 /* 0x00000020 - Architecture dependent (CR0) */ #define IC_ETR 4 /* 0x00000010 - Architecture dependent (CR0) */ #define IC_STORSTAT 3 /* 0x00000008 */ #define IC_UNUSED_2 2 /* 0x00000004 */ #define IC_RESTART 1 /* 0x00000002 */ #define IC_PSW_WAIT 0 /* 0x00000001 */ /* Initial values */ #define IC_INITIAL_STATE BIT(IC_PSW_WAIT) #define IC_INITIAL_MASK ( BIT(IC_INTERRUPT) \ | BIT(IC_RESTART) \ | BIT(IC_STORSTAT) \ ) #define SET_IC_INITIAL_MASK(_regs) (_regs)->ints_mask = IC_INITIAL_MASK #define SET_IC_INITIAL_STATE(_regs) (_regs)->ints_state = IC_INITIAL_STATE /* I/O interrupt subclasses */ #define IC_IOPENDING ( BIT(IC_IO) ) /* External interrupt subclasses in CR 0 */ #define IC_EXT_SCM_CR0 ( BIT(IC_MALFALT) \ | BIT(IC_EMERSIG) \ | BIT(IC_EXTCALL) \ | BIT(IC_TODSYNC) \ | BIT(IC_CLKC) \ | BIT(IC_PTIMER) \ | BIT(IC_SERVSIG) \ | BIT(IC_ITIMER) \ | BIT(IC_INTKEY) \ | BIT(IC_EXTSIG) \ | BIT(IC_ETR) \ ) /* External interrupt subclasses */ /* * Adds ECPS:VM Vtimer which has no individual * subclass mask in CR0 */ #define IC_EXTPENDING ( BIT(IC_MALFALT) \ | BIT(IC_EMERSIG) \ | BIT(IC_EXTCALL) \ | BIT(IC_TODSYNC) \ | BIT(IC_CLKC) \ | BIT(IC_PTIMER) \ | BIT(IC_SERVSIG) \ | BIT(IC_ECPSVTIMER) \ | BIT(IC_ITIMER) \ | BIT(IC_INTKEY) \ | BIT(IC_EXTSIG) \ | BIT(IC_ETR) \ ) /* Machine check subclasses */ #define IC_MCKPENDING ( BIT(IC_CHANRPT) \ | BIT(IC_RCVYRPT) \ | BIT(IC_DGRDRPT) \ | BIT(IC_XDMGRPT) \ | BIT(IC_WARNING) \ ) /* Not disabled mask */ #define IC_OPEN_MASK ( IC_MCKPENDING \ | IC_EXTPENDING \ | IC_IOPENDING \ ) #define IC_PER_MASK ( BIT(IC_PER_SB) \ | BIT(IC_PER_IF) \ | BIT(IC_PER_SA) \ | BIT(IC_PER_GRA) \ | BIT(IC_PER_STURA) \ | BIT(IC_PER_IFNUL) \ ) /* SIE & Assist supported events */ #define IC_SIE_INT ( BIT(IC_IO) \ | BIT(IC_CLKC) \ | BIT(IC_PTIMER) \ | BIT(IC_ITIMER) \ ) #define IC_CR9_SHIFT 8 /* Mask bits are ONLY set by the associated cpu thread and * therefore don't have to be serialized. The mask bits * indicate which interrupts the CPU is willing to take at * this time. We set the mask bits below in one fell swoop * to avoid multiple updates to `ints_mask'. */ #undef IC_CR0_TO_INTMASK #if defined(FEATURE_ECPSVM) #define IC_CR0_TO_INTMASK(_regs) \ ( ( (_regs)->CR(0) & IC_EXT_SCM_CR0) \ | (((_regs)->CR(0) & BIT(IC_ITIMER)) ? BIT(IC_ECPSVTIMER) : 0) ) #else #define IC_CR0_TO_INTMASK(_regs) \ ( (_regs)->CR(0) & IC_EXT_SCM_CR0) #endif /* FEATURE_ECPSVM */ #define IC_MASK(_regs) \ ( ( IC_INITIAL_MASK ) \ | ( ECMODE(&(_regs)->psw) \ ? ( ((_regs)->psw.sysmask & PSW_IOMASK) ? BIT(IC_IO) : 0 ) \ : ( ((_regs)->psw.sysmask & 0xFE) ? BIT(IC_IO) : 0 ) \ ) \ | ( MACHMASK(&(_regs)->psw) ? ((_regs)->CR(14) & IC_MCKPENDING) : 0 ) \ | ( PER_MODE((_regs)) ? ((_regs)->ints_mask & IC_PER_MASK) : 0 ) \ | ( ((_regs)->psw.sysmask & PSW_EXTMASK) ? (IC_CR0_TO_INTMASK((_regs))) : 0 ) \ | ( WAITSTATE(&(_regs)->psw) ? BIT(IC_PSW_WAIT) : 0 ) \ ) #define IC_ECMODE_MASK(_regs) \ ( ( IC_INITIAL_MASK ) \ | ( ((_regs)->psw.sysmask & PSW_IOMASK) ? BIT(IC_IO) : 0 ) \ | ( MACHMASK(&(_regs)->psw) ? ((_regs)->CR(14) & IC_MCKPENDING) : 0 ) \ | ( PER_MODE((_regs)) ? ((_regs)->ints_mask & IC_PER_MASK) : 0 ) \ | ( ((_regs)->psw.sysmask & PSW_EXTMASK) ? (IC_CR0_TO_INTMASK((_regs))) : 0 ) \ | ( WAITSTATE(&(_regs)->psw) ? BIT(IC_PSW_WAIT) : 0 ) \ ) #define IC_BCMODE_MASK(_regs) \ ( ( IC_INITIAL_MASK ) \ | ( ((_regs)->psw.sysmask & 0xFE) ? BIT(IC_IO) : 0 ) \ | ( MACHMASK(&(_regs)->psw) ? ((_regs)->CR(14) & IC_MCKPENDING) : 0 ) \ | ( PER_MODE((_regs)) ? ((_regs)->ints_mask & IC_PER_MASK) : 0 ) \ | ( ((_regs)->psw.sysmask & PSW_EXTMASK) ? (IC_CR0_TO_INTMASK((_regs))) : 0 ) \ | ( WAITSTATE(&(_regs)->psw) ? BIT(IC_PSW_WAIT) : 0 ) \ ) /* Note: if PER mode, invalidate the AIA to force instfetch to be called */ #define SET_IC_ECMODE_MASK(_regs) \ do { \ (_regs)->ints_mask = IC_ECMODE_MASK((_regs)); \ if ( ( (_regs)->permode = PER_MODE((_regs)) ) ) \ INVALIDATE_AIA((_regs)); \ } while (0) #define SET_IC_BCMODE_MASK(_regs) \ do { \ (_regs)->ints_mask = IC_BCMODE_MASK((_regs)); \ if ( ( (_regs)->permode = PER_MODE((_regs)) ) ) \ INVALIDATE_AIA((_regs)); \ } while (0) #undef SET_IC_MASK #ifdef FEATURE_BCMODE #define SET_IC_MASK(_regs) \ do { \ (_regs)->ints_mask = IC_MASK((_regs)); \ if ( ( (_regs)->permode = PER_MODE((_regs)) ) ) \ INVALIDATE_AIA((_regs)); \ } while (0) #else #define SET_IC_MASK(_regs) SET_IC_ECMODE_MASK(_regs) #endif /* * State bits indicate what interrupts are possibly pending * for a CPU. These bits can be set by any thread and therefore * are serialized by the `intlock'. * For PER, the state bits are set when CR9 is loaded and the mask * bits are set when a PER event occurs */ #define SET_IC_TRACE \ do { \ int i; \ CPU_BITMAP mask = sysblk.started_mask; \ for (i = 0; mask; i++) { \ if (mask & 1) \ sysblk.regs[i]->ints_state |= BIT(IC_INTERRUPT); \ mask >>= 1; \ } \ } while (0) #define SET_IC_PER(_regs) \ do { \ (_regs)->ints_state &= (~IC_PER_MASK); \ (_regs)->ints_state |= (((_regs)->CR(9) >> IC_CR9_SHIFT) & IC_PER_MASK); \ (_regs)->ints_mask &= (~IC_PER_MASK | (_regs)->ints_state); \ } while (0) /* * * * * * * * * * * * * * * Set state bit to '1' * * * * * * * * * * * * * * */ #define ON_IC_INTERRUPT(_regs) \ do { \ (_regs)->ints_state |= BIT(IC_INTERRUPT); \ } while (0) #define ON_IC_RESTART(_regs) \ do { \ (_regs)->ints_state |= BIT(IC_INTERRUPT) | BIT(IC_RESTART); \ } while (0) #define ON_IC_STORSTAT(_regs) \ do { \ (_regs)->ints_state |= BIT(IC_INTERRUPT) | BIT(IC_STORSTAT); \ } while (0) #define ON_IC_IOPENDING \ do { \ int i; CPU_BITMAP mask; \ if ( !(sysblk.ints_state & BIT(IC_IO)) ) { \ sysblk.ints_state |= BIT(IC_IO); \ mask = sysblk.started_mask; \ for (i = 0; mask; i++) { \ if (mask & 1) { \ if ( sysblk.regs[i]->ints_mask & BIT(IC_IO) ) \ sysblk.regs[i]->ints_state |= BIT(IC_INTERRUPT) | BIT(IC_IO); \ else \ sysblk.regs[i]->ints_state |= BIT(IC_IO); \ } \ mask >>= 1; \ } \ } \ } while (0) #define ON_IC_CHANRPT \ do { \ int i; CPU_BITMAP mask; \ if ( !(sysblk.ints_state & BIT(IC_CHANRPT)) ) { \ sysblk.ints_state |= BIT(IC_CHANRPT); \ mask = sysblk.started_mask; \ for (i = 0; mask; i++) { \ if (mask & 1) { \ if ( sysblk.regs[i]->ints_mask & BIT(IC_CHANRPT) ) \ sysblk.regs[i]->ints_state |= BIT(IC_INTERRUPT) | BIT(IC_CHANRPT); \ else \ sysblk.regs[i]->ints_state |= BIT(IC_CHANRPT); \ } \ mask >>= 1; \ } \ } \ } while (0) #define ON_IC_INTKEY \ do { \ int i; CPU_BITMAP mask; \ if ( !(sysblk.ints_state & BIT(IC_INTKEY)) ) { \ sysblk.ints_state |= BIT(IC_INTKEY); \ mask = sysblk.started_mask; \ for (i = 0; mask; i++) { \ if (mask & 1) { \ if ( sysblk.regs[i]->ints_mask & BIT(IC_INTKEY) ) \ sysblk.regs[i]->ints_state |= BIT(IC_INTERRUPT) | BIT(IC_INTKEY); \ else \ sysblk.regs[i]->ints_state |= BIT(IC_INTKEY); \ } \ mask >>= 1; \ } \ } \ } while (0) #define ON_IC_SERVSIG \ do { \ int i; CPU_BITMAP mask; \ if ( !(sysblk.ints_state & BIT(IC_SERVSIG)) ) { \ sysblk.ints_state |= BIT(IC_SERVSIG); \ mask = sysblk.started_mask; \ for (i = 0; mask; i++) { \ if (mask & 1) { \ if ( sysblk.regs[i]->ints_mask & BIT(IC_SERVSIG) ) \ sysblk.regs[i]->ints_state |= BIT(IC_INTERRUPT) | BIT(IC_SERVSIG); \ else \ sysblk.regs[i]->ints_state |= BIT(IC_SERVSIG); \ } \ mask >>= 1; \ } \ } \ } while (0) #define ON_IC_ITIMER(_regs) \ do { \ if ( (_regs)->ints_mask & BIT(IC_ITIMER) ) \ (_regs)->ints_state |= BIT(IC_INTERRUPT) | BIT(IC_ITIMER); \ else \ (_regs)->ints_state |= BIT(IC_ITIMER); \ } while (0) #define ON_IC_PTIMER(_regs) \ do { \ if ( (_regs)->ints_mask & BIT(IC_PTIMER) ) \ (_regs)->ints_state |= BIT(IC_INTERRUPT) | BIT(IC_PTIMER); \ else \ (_regs)->ints_state |= BIT(IC_PTIMER); \ } while (0) #define ON_IC_ECPSVTIMER(_regs) \ do { \ if ( (_regs)->ints_mask & BIT(IC_ECPSVTIMER) ) \ (_regs)->ints_state |= BIT(IC_INTERRUPT) | BIT(IC_ECPSVTIMER); \ else \ (_regs)->ints_state |= BIT(IC_ECPSVTIMER); \ } while (0) #define ON_IC_CLKC(_regs) \ do { \ if ( (_regs)->ints_mask & BIT(IC_CLKC) ) \ (_regs)->ints_state |= BIT(IC_INTERRUPT) | BIT(IC_CLKC); \ else \ (_regs)->ints_state |= BIT(IC_CLKC); \ } while (0) #define ON_IC_EXTCALL(_regs) \ do { \ if ( (_regs)->ints_mask & BIT(IC_EXTCALL) ) \ (_regs)->ints_state |= BIT(IC_INTERRUPT) | BIT(IC_EXTCALL); \ else \ (_regs)->ints_state |= BIT(IC_EXTCALL); \ } while (0) #define ON_IC_MALFALT(_regs) \ do { \ if ( (_regs)->ints_mask & BIT(IC_MALFALT) ) \ (_regs)->ints_state |= BIT(IC_INTERRUPT) | BIT(IC_MALFALT); \ else \ (_regs)->ints_state |= BIT(IC_MALFALT); \ } while (0) #define ON_IC_EMERSIG(_regs) \ do { \ if ( (_regs)->ints_mask & BIT(IC_EMERSIG) ) \ (_regs)->ints_state |= BIT(IC_INTERRUPT) | BIT(IC_EMERSIG); \ else \ (_regs)->ints_state |= BIT(IC_EMERSIG); \ } while (0) /* * When a PER event occurs we set the bit in ints_mask instead of * ints_state; therefore intlock does not need to be held. * The ints_state bits are set when CR9 is loaded. */ #define ON_IC_PER_SB(_regs) \ do { \ (_regs)->ints_mask |= BIT(IC_PER_SB); \ } while (0) #define ON_IC_PER_IF(_regs) \ do { \ (_regs)->ints_mask |= BIT(IC_PER_IF); \ } while (0) #define ON_IC_PER_SA(_regs) \ do { \ (_regs)->ints_mask |= BIT(IC_PER_SA); \ } while (0) #define ON_IC_PER_GRA(_regs) \ do { \ (_regs)->ints_mask |= BIT(IC_PER_GRA); \ } while (0) #define ON_IC_PER_STURA(_regs) \ do { \ (_regs)->ints_mask |= BIT(IC_PER_STURA); \ } while (0) #define ON_IC_PER_IFNUL(_regs) \ do { \ (_regs)->ints_mask |= BIT(IC_PER_IFNUL); \ } while (0) /* * * * * * * * * * * * * * * Set state bit to '0' * * * * * * * * * * * * * * */ #define OFF_IC_INTERRUPT(_regs) \ do { \ (_regs)->ints_state &= ~BIT(IC_INTERRUPT); \ } while (0) #define OFF_IC_RESTART(_regs) \ do { \ (_regs)->ints_state &= ~BIT(IC_RESTART); \ } while (0) #define OFF_IC_STORSTAT(_regs) \ do { \ (_regs)->ints_state &= ~BIT(IC_STORSTAT); \ } while (0) #define OFF_IC_IOPENDING \ do { \ int i; CPU_BITMAP mask; \ if ( sysblk.ints_state & BIT(IC_IO) ) { \ sysblk.ints_state &= ~BIT(IC_IO); \ mask = sysblk.started_mask; \ for (i = 0; mask; i++) { \ if (mask & 1) \ sysblk.regs[i]->ints_state &= ~BIT(IC_IO); \ mask >>= 1; \ } \ } \ } while (0) #define OFF_IC_CHANRPT \ do { \ int i; CPU_BITMAP mask; \ if ( sysblk.ints_state & BIT(IC_CHANRPT) ) { \ sysblk.ints_state &= ~BIT(IC_CHANRPT); \ mask = sysblk.started_mask; \ for (i = 0; mask; i++) { \ if (mask & 1) \ sysblk.regs[i]->ints_state &= ~BIT(IC_CHANRPT); \ mask >>= 1; \ } \ } \ } while (0) #define OFF_IC_INTKEY \ do { \ int i; CPU_BITMAP mask; \ if ( sysblk.ints_state & BIT(IC_INTKEY) ) { \ sysblk.ints_state &= ~BIT(IC_INTKEY); \ mask = sysblk.started_mask; \ for (i = 0; mask; i++) { \ if (mask & 1) \ sysblk.regs[i]->ints_state &= ~BIT(IC_INTKEY); \ mask >>= 1; \ } \ } \ } while (0) #define OFF_IC_SERVSIG \ do { \ int i; CPU_BITMAP mask; \ if ( sysblk.ints_state & BIT(IC_SERVSIG) ) { \ sysblk.ints_state &= ~BIT(IC_SERVSIG); \ mask = sysblk.started_mask; \ for (i = 0; mask; i++) { \ if (mask & 1) \ sysblk.regs[i]->ints_state &= ~BIT(IC_SERVSIG); \ mask >>= 1; \ } \ } \ } while (0) #define OFF_IC_ITIMER(_regs) \ do { \ (_regs)->ints_state &= ~BIT(IC_ITIMER); \ } while (0) #define OFF_IC_PTIMER(_regs) \ do { \ (_regs)->ints_state &= ~BIT(IC_PTIMER); \ } while (0) #define OFF_IC_ECPSVTIMER(_regs) \ do { \ (_regs)->ints_state &= ~BIT(IC_ECPSVTIMER); \ } while (0) #define OFF_IC_CLKC(_regs) \ do { \ (_regs)->ints_state &= ~BIT(IC_CLKC); \ } while (0) #define OFF_IC_EXTCALL(_regs) \ do { \ (_regs)->ints_state &= ~BIT(IC_EXTCALL); \ } while (0) #define OFF_IC_MALFALT(_regs) \ do { \ (_regs)->ints_state &= ~BIT(IC_MALFALT); \ } while (0) #define OFF_IC_EMERSIG(_regs) \ do { \ (_regs)->ints_state &= ~BIT(IC_EMERSIG); \ } while (0) #define OFF_IC_PER(_regs) \ do { \ (_regs)->ints_mask &= ~IC_PER_MASK; \ } while (0) #define OFF_IC_PER_SB(_regs) \ do { \ (_regs)->ints_mask &= ~BIT(IC_PER_SB); \ } while (0) #define OFF_IC_PER_IF(_regs) \ do { \ (_regs)->ints_mask &= ~BIT(IC_PER_IF); \ } while (0) #define OFF_IC_PER_SA(_regs) \ do { \ (_regs)->ints_mask &= ~BIT(IC_PER_SA); \ } while (0) #define OFF_IC_PER_GRA(_regs) \ do { \ (_regs)->ints_mask &= ~BIT(IC_PER_GRA); \ } while (0) #define OFF_IC_PER_STURA(_regs) \ do { \ (_regs)->ints_mask &= ~BIT(IC_PER_STURA); \ } while (0) #define OFF_IC_PER_IFNUL(_regs) \ do { \ (_regs)->ints_mask &= ~BIT(IC_PER_IFNUL); \ } while (0) /* * * * * * * * * * * * * * * Test interrupt state * * * * * * * * * * * * * * */ #define IS_IC_INTERRUPT(_regs) ( (_regs)->ints_state & BIT(IC_INTERRUPT) ) #define IS_IC_RESTART(_regs) ( (_regs)->ints_state & BIT(IC_RESTART) ) #define IS_IC_STORSTAT(_regs) ( (_regs)->ints_state & BIT(IC_STORSTAT) ) #define IS_IC_IOPENDING ( sysblk.ints_state & BIT(IC_IO) ) #define IS_IC_MCKPENDING(_regs) ( (_regs)->ints_state & IC_MCKPENDING ) #define IS_IC_CHANRPT ( sysblk.ints_state & BIT(IC_CHANRPT) ) #define IS_IC_INTKEY ( sysblk.ints_state & BIT(IC_INTKEY) ) #define IS_IC_SERVSIG ( sysblk.ints_state & BIT(IC_SERVSIG) ) #define IS_IC_ITIMER(_regs) ( (_regs)->ints_state & BIT(IC_ITIMER) ) #define IS_IC_PTIMER(_regs) ( (_regs)->ints_state & BIT(IC_PTIMER) ) #define IS_IC_ECPSVTIMER(_regs) ( (_regs)->ints_state & BIT(IC_ECPSVTIMER)) #define IS_IC_CLKC(_regs) ( (_regs)->ints_state & BIT(IC_CLKC) ) #define IS_IC_EXTCALL(_regs) ( (_regs)->ints_state & BIT(IC_EXTCALL) ) #define IS_IC_MALFALT(_regs) ( (_regs)->ints_state & BIT(IC_MALFALT) ) #define IS_IC_EMERSIG(_regs) ( (_regs)->ints_state & BIT(IC_EMERSIG) ) #define IS_IC_PER(_regs) ( (_regs)->ints_mask & IC_PER_MASK ) #define IS_IC_PER_SB(_regs) ( (_regs)->ints_mask & BIT(IC_PER_SB) ) #define IS_IC_PER_IF(_regs) ( (_regs)->ints_mask & BIT(IC_PER_IF) ) #define IS_IC_PER_SA(_regs) ( (_regs)->ints_mask & BIT(IC_PER_SA) ) #define IS_IC_PER_GRA(_regs) ( (_regs)->ints_mask & BIT(IC_PER_GRA) ) #define IS_IC_PER_STURA(_regs) ( (_regs)->ints_mask & BIT(IC_PER_STURA) ) #define IS_IC_PER_IFNUL(_regs) ( (_regs)->ints_mask & BIT(IC_PER_IFNUL) ) /* * * * * * * * * * * * * * * Disabled wait check * * * * * * * * * * * * * * */ #define IS_IC_DISABLED_WAIT_PSW(_regs) \ ( ((_regs)->ints_mask & IC_OPEN_MASK) == 0 ) /* * * * * * * * * * * * * * * Test PER mask bits * * * * * * * * * * * * * * */ #define EN_IC_PER(_regs) unlikely( (_regs)->permode ) #define EN_IC_PER_SB(_regs) ( EN_IC_PER(_regs) && ((_regs)->ints_state & BIT(IC_PER_SB)) ) #define EN_IC_PER_IF(_regs) ( EN_IC_PER(_regs) && ((_regs)->ints_state & BIT(IC_PER_IF)) ) #define EN_IC_PER_SA(_regs) ( EN_IC_PER(_regs) && ((_regs)->ints_state & BIT(IC_PER_SA)) ) #define EN_IC_PER_GRA(_regs) ( EN_IC_PER(_regs) && ((_regs)->ints_state & BIT(IC_PER_GRA)) ) #define EN_IC_PER_STURA(_regs) ( EN_IC_PER(_regs) && ((_regs)->ints_state & BIT(IC_PER_STURA)) ) #define EN_IC_PER_IFNUL(_regs) ( EN_IC_PER(_regs) && ((_regs)->ints_state & BIT(IC_PER_IFNUL)) ) /* * * * * * * * * * * * * * * * * * * * * * * * * * Check for specific enabled pending interrupt * * * * * * * * * * * * * * * * * * * * * * * * * */ #define OPEN_IC_MCKPENDING(_regs) \ ( (_regs)->ints_state & (_regs)->ints_mask & IC_MCKPENDING ) #define OPEN_IC_IOPENDING(_regs) \ ( (_regs)->ints_state & (_regs)->ints_mask & IC_IOPENDING ) #define OPEN_IC_CHANRPT(_regs) \ ( (_regs)->ints_state & (_regs)->ints_mask & BIT(IC_CHANRPT) ) #define OPEN_IC_EXTPENDING(_regs) \ ( (_regs)->ints_state & (_regs)->ints_mask & IC_EXTPENDING ) #define OPEN_IC_ITIMER(_regs) \ ( (_regs)->ints_state & (_regs)->ints_mask & BIT(IC_ITIMER) ) #define OPEN_IC_PTIMER(_regs) \ ( (_regs)->ints_state & (_regs)->ints_mask & BIT(IC_PTIMER) ) #define OPEN_IC_ECPSVTIMER(_regs) \ ( (_regs)->ints_state & (_regs)->ints_mask & BIT(IC_ECPSVTIMER) ) #define OPEN_IC_CLKC(_regs) \ ( (_regs)->ints_state & (_regs)->ints_mask & BIT(IC_CLKC) ) #define OPEN_IC_INTKEY(_regs) \ ( (_regs)->ints_state & (_regs)->ints_mask & BIT(IC_INTKEY) ) #define OPEN_IC_SERVSIG(_regs) \ ( (_regs)->ints_state & (_regs)->ints_mask & BIT(IC_SERVSIG) ) #define OPEN_IC_EXTCALL(_regs) \ ( (_regs)->ints_state & (_regs)->ints_mask & BIT(IC_EXTCALL) ) #define OPEN_IC_MALFALT(_regs) \ ( (_regs)->ints_state & (_regs)->ints_mask & BIT(IC_MALFALT) ) #define OPEN_IC_EMERSIG(_regs) \ ( (_regs)->ints_state & (_regs)->ints_mask & BIT(IC_EMERSIG) ) #define OPEN_IC_PER(_regs) \ ( (_regs)->ints_state & (_regs)->ints_mask & IC_PER_MASK ) #define OPEN_IC_PER_SB(_regs) \ ( (_regs)->ints_state & (_regs)->ints_mask & BIT(IC_PER_SB) ) #define OPEN_IC_PER_IF(_regs) \ ( (_regs)->ints_state & (_regs)->ints_mask & BIT(IC_PER_IF) ) #define OPEN_IC_PER_SA(_regs) \ ( (_regs)->ints_state & (_regs)->ints_mask & BIT(IC_PER_SA) ) #define OPEN_IC_PER_GRA(_regs) \ ( (_regs)->ints_state & (_regs)->ints_mask & BIT(IC_PER_GRA) ) #define OPEN_IC_PER_STURA(_regs) \ ( (_regs)->ints_state & (_regs)->ints_mask & BIT(IC_PER_STURA) ) #define OPEN_IC_PER_IFNUL(_regs) \ ( (_regs)->ints_state & (_regs)->ints_mask & BIT(IC_PER_IFNUL) ) /* * * * * * * * * * * * * * * * * * * * * * * * * * Check for general enabled pending interrupt * * * * * * * * * * * * * * * * * * * * * * * * * */ #define IC_INTERRUPT_CPU(_regs) \ ( (_regs)->ints_state & (_regs)->ints_mask ) #define INTERRUPT_PENDING(_regs) IC_INTERRUPT_CPU((_regs)) #define SIE_IC_INTERRUPT_CPU(_regs) \ (((_regs)->ints_state|((_regs)->hostregs->ints_state&IC_SIE_INT)) & (_regs)->ints_mask) #define SIE_INTERRUPT_PENDING(_regs) SIE_IC_INTERRUPT_CPU((_regs)) hercules-3.07/crypto/000777 000765 000765 00000000000 11345533276 016300 5ustar00jmaynardjmaynard000000 000000 hercules-3.07/crypto.c000644 000765 000765 00000006231 11321734033 016426 0ustar00jmaynardjmaynard000000 000000 /* CRYPTO.C (c) Copyright Jan Jaeger, 2000-2010 */ /* Cryptographic instructions */ // $Id: crypto.c 5571 2009-12-29 13:13:01Z bernard $ // // $Log$ // Revision 1.14 2007/06/23 00:04:05 ivan // Update copyright notices to include current year (2007) // // Revision 1.13 2006/12/08 09:43:19 jj // Add CVS message log // #include "hstdinc.h" #define _CRYPTO_C_ #define _HENGINE_DLL_ #include "hercules.h" #if defined(FEATURE_MESSAGE_SECURITY_ASSIST) #include "opcode.h" #define CRYPTO_EXTERN #include "crypto.h" /*----------------------------------------------------------------------------*/ /* B92E KM - Cipher Message [RRE] */ /*----------------------------------------------------------------------------*/ DEF_INST(cipher_message_r) { if( ARCH_DEP(cipher_message) ) ARCH_DEP(cipher_message) (inst, regs); else { int r1, r2; /* register values */ RRE(inst, regs, r1, r2); ARCH_DEP(program_interrupt) (regs, PGM_OPERATION_EXCEPTION); } } /*----------------------------------------------------------------------------*/ /* B92F KMC - Cipher Message with Chaining [RRE] */ /*----------------------------------------------------------------------------*/ DEF_INST(cipher_message_with_chaining_r) { if( ARCH_DEP(cipher_message_with_chaining) ) ARCH_DEP(cipher_message_with_chaining) (inst, regs); else { int r1, r2; /* register values */ RRE(inst, regs, r1, r2); ARCH_DEP(program_interrupt) (regs, PGM_OPERATION_EXCEPTION); } } /*----------------------------------------------------------------------------*/ /* B93E/B93F KIMD/KLMD - Compute Intermediate/Last Message Digest [RRE] */ /*----------------------------------------------------------------------------*/ DEF_INST(compute_message_digest_r) { if( ARCH_DEP(compute_message_digest) ) ARCH_DEP(compute_message_digest) (inst, regs); else { int r1, r2; /* register values */ RRE(inst, regs, r1, r2); ARCH_DEP(program_interrupt) (regs, PGM_OPERATION_EXCEPTION); } } /*----------------------------------------------------------------------------*/ /* B91E KMAC - Compute Message Authentication Code [RRE] */ /*----------------------------------------------------------------------------*/ DEF_INST(compute_message_authentication_code_r) { if( ARCH_DEP(compute_message_authentication_code) ) ARCH_DEP(compute_message_authentication_code) (inst, regs); else { int r1, r2; /* register values */ RRE(inst, regs, r1, r2); ARCH_DEP(program_interrupt) (regs, PGM_OPERATION_EXCEPTION); } } #endif /*defined(FEATURE_MESSAGE_SECURITY_ASSIST)*/ #if !defined(_GEN_ARCH) #if defined(_ARCHMODE2) #define _GEN_ARCH _ARCHMODE2 #include "crypto.c" #endif #if defined(_ARCHMODE3) #undef _GEN_ARCH #define _GEN_ARCH _ARCHMODE3 #include "crypto.c" #endif #endif /*!defined(_GEN_ARCH)*/ hercules-3.07/crypto.h000644 000765 000765 00000002137 11321734033 016434 0ustar00jmaynardjmaynard000000 000000 /* CRYPTO.H (c) Copyright Jan Jaeger, 2000-2009 */ /* Cryptographic instructions */ // $Id: crypto.h 5572 2009-12-29 13:13:15Z bernard $ // // $Log$ // Revision 1.11 2007/06/23 00:04:05 ivan // Update copyright notices to include current year (2007) // // Revision 1.10 2006/12/08 09:43:19 jj // Add CVS message log // #if defined(_FEATURE_MESSAGE_SECURITY_ASSIST) #ifndef _CRYPTO_C_ #ifndef _HENGINE_DLL_ #define CRY_DLL_IMPORT DLL_IMPORT #else /* _HDASD_DLL_ */ #define CRY_DLL_IMPORT extern #endif /* _HDASD_DLL_ */ #else #define CRY_DLL_IMPORT DLL_EXPORT #endif CRY_DLL_IMPORT void ( ATTR_REGPARM(2) *ARCH_DEP( cipher_message ) ) ( BYTE*, REGS* ); CRY_DLL_IMPORT void ( ATTR_REGPARM(2) *ARCH_DEP( cipher_message_with_chaining ) ) ( BYTE*, REGS* ); CRY_DLL_IMPORT void ( ATTR_REGPARM(2) *ARCH_DEP( compute_message_digest ) ) ( BYTE*, REGS* ); CRY_DLL_IMPORT void ( ATTR_REGPARM(2) *ARCH_DEP( compute_message_authentication_code ) ) ( BYTE*, REGS* ); #endif /*defined(_FEATURE_MESSAGE_SECURITY_ASSIST)*/ hercules-3.07/ctc_ctci.c000644 000765 000765 00000144747 11143760542 016706 0ustar00jmaynardjmaynard000000 000000 // ==================================================================== // Hercules IP Channel-to-Channel Support (CTCI) // ==================================================================== // // Copyright (C) Copyright James A. Pierson, 2002-2009 // (C) Copyright "Fish" (David B. Trout), 2002-2009 // (C) Copyright Roger Bowler, 2000-2009 // // linux 2.4 modifications (c) Copyright Fritz Elfert, 2001-2009 // // $Id: ctc_ctci.c 5125 2009-01-23 12:01:44Z bernard $ // // $Log$ // Revision 1.77 2008/11/04 05:56:31 fish // Put ensure consistent create_thread ATTR usage change back in // // Revision 1.76 2008/11/03 15:31:57 rbowler // Back out consistent create_thread ATTR modification // // Revision 1.75 2008/10/18 09:32:21 fish // Ensure consistent create_thread ATTR usage // // Revision 1.74 2008/07/17 07:19:12 fish // Fix FCS (Frame Check Sequence) bug in LCS_Write function // and other minor bugs. // // Revision 1.72 2008/07/17 03:30:40 fish // CTC/LCS cosmetic-only changes -- part 1 // (no actual functionality was changed!) // // Revision 1.71 2008/02/07 00:29:04 rbowler // Solaris build support by Jeff Savit // // Revision 1.70 2008/01/11 21:33:21 fish // new 'ctc' command to enable/disable debug option on demand // // Revision 1.69 2007/11/21 22:54:14 fish // Use new BEGIN_DEVICE_CLASS_QUERY macro // // Revision 1.68 2007/07/29 02:02:44 fish // Fix day-1 CTCI/LCS bug found by Vince Weaver [vince@deater.net] // // Revision 1.67 2007/07/29 00:24:43 fish // (comment change only) // // Revision 1.66 2007/06/23 00:04:05 ivan // Update copyright notices to include current year (2007) // // Revision 1.65 2006/12/08 09:43:19 jj // Add CVS message log // #include "hstdinc.h" /* jbs 10/27/2007 added _SOLARIS_ silly typo fixed 01/18/08 when looked at this again */ #if !defined(__SOLARIS__) #include "hercules.h" #include "ctcadpt.h" #include "tuntap.h" #include "hercifc.h" #include "opcode.h" /* getopt dynamic linking kludge */ #include "herc_getopt.h" #if defined(OPTION_W32_CTCI) #include "tt32api.h" #endif /*-------------------------------------------------------------------*/ /* Ivan Warren 20040227 */ /* This table is used by channel.c to determine if a CCW code is an */ /* immediate command or not */ /* The tape is addressed in the DEVHND structure as 'DEVIMM immed' */ /* 0 : Command is NOT an immediate command */ /* 1 : Command is an immediate command */ /* Note : An immediate command is defined as a command which returns */ /* CE (channel end) during initialisation (that is, no data is */ /* actually transfered. In this case, IL is not indicated for a CCW */ /* Format 0 or for a CCW Format 1 when IL Suppression Mode is in */ /* effect */ /*-------------------------------------------------------------------*/ static BYTE CTCI_Immed_Commands[256]= { 0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; // ==================================================================== // Declarations // ==================================================================== static void* CTCI_ReadThread( PCTCBLK pCTCBLK ); static int CTCI_EnqueueIPFrame( DEVBLK* pDEVBLK, BYTE* pData, size_t iSize ); static int ParseArgs( DEVBLK* pDEVBLK, PCTCBLK pCTCBLK, int argc, char** argv ); // -------------------------------------------------------------------- // Device Handler Information Block // -------------------------------------------------------------------- DEVHND ctci_device_hndinfo = { &CTCI_Init, /* Device Initialisation */ &CTCI_ExecuteCCW, /* Device CCW execute */ &CTCI_Close, /* Device Close */ &CTCI_Query, /* Device Query */ NULL, /* Device Start channel pgm */ NULL, /* Device End channel pgm */ NULL, /* Device Resume channel pgm */ NULL, /* Device Suspend channel pgm */ NULL, /* Device Read */ NULL, /* Device Write */ NULL, /* Device Query used */ NULL, /* Device Reserve */ NULL, /* Device Release */ NULL, /* Device Attention */ CTCI_Immed_Commands, /* Immediate CCW Codes */ NULL, /* Signal Adapter Input */ NULL, /* Signal Adapter Output */ NULL, /* Hercules suspend */ NULL /* Hercules resume */ }; // ==================================================================== // // ==================================================================== // // CTCI_Init // #define CTC_DEVICES_IN_GROUP 2 // a read and write device int CTCI_Init( DEVBLK* pDEVBLK, int argc, char *argv[] ) { PCTCBLK pWrkCTCBLK = NULL; // Working CTCBLK PCTCBLK pDevCTCBLK = NULL; // Device CTCBLK int rc = 0; // Return code int nIFType; // Interface type int nIFFlags; // Interface flags char thread_name[32]; // CTCI_ReadThread nIFType = // Interface type 0 | IFF_TUN // ("TUN", not "tap") | IFF_NO_PI // (no packet info) ; nIFFlags = // Interface flags 0 | IFF_UP // (interface is being enabled) | IFF_BROADCAST // (interface broadcast addr is valid) ; #if defined( TUNTAP_IFF_RUNNING_NEEDED ) nIFFlags |= // ADDITIONAL Interface flags 0 | IFF_RUNNING // (interface is ALSO operational) ; #endif /* defined( TUNTAP_IFF_RUNNING_NEEDED ) */ pDEVBLK->devtype = 0x3088; // CTC is a group device if(!group_device(pDEVBLK, CTC_DEVICES_IN_GROUP)) return 0; // Housekeeping pWrkCTCBLK = malloc( sizeof( CTCBLK ) ); if( !pWrkCTCBLK ) { logmsg( _("HHCCT037E %4.4X: Unable to allocate CTCBLK\n"), pDEVBLK->devnum ); return -1; } memset( pWrkCTCBLK, 0, sizeof( CTCBLK ) ); // Parse configuration file statement if( ParseArgs( pDEVBLK, pWrkCTCBLK, argc, (char**)argv ) != 0 ) { free( pWrkCTCBLK ); pWrkCTCBLK = NULL; return -1; } // Allocate the device CTCBLK and copy parsed information. pDevCTCBLK = malloc( sizeof( CTCBLK ) ); if( !pDevCTCBLK ) { logmsg( _("HHCCT038E %4.4X: Unable to allocate CTCBLK\n"), pDEVBLK->devnum ); free( pWrkCTCBLK ); pWrkCTCBLK = NULL; return -1; } memcpy( pDevCTCBLK, pWrkCTCBLK, sizeof( CTCBLK ) ); // New format has only one device statement for both addresses // We need to dynamically allocate the read device block pDevCTCBLK->pDEVBLK[0] = pDEVBLK->group->memdev[0]; pDevCTCBLK->pDEVBLK[1] = pDEVBLK->group->memdev[1]; pDevCTCBLK->pDEVBLK[0]->dev_data = pDevCTCBLK; pDevCTCBLK->pDEVBLK[1]->dev_data = pDevCTCBLK; SetSIDInfo( pDevCTCBLK->pDEVBLK[0], 0x3088, 0x08, 0x3088, 0x01 ); SetSIDInfo( pDevCTCBLK->pDEVBLK[1], 0x3088, 0x08, 0x3088, 0x01 ); pDevCTCBLK->pDEVBLK[0]->ctctype = CTC_CTCI; pDevCTCBLK->pDEVBLK[0]->ctcxmode = 1; pDevCTCBLK->pDEVBLK[1]->ctctype = CTC_CTCI; pDevCTCBLK->pDEVBLK[1]->ctcxmode = 1; pDevCTCBLK->sMTU = atoi( pDevCTCBLK->szMTU ); pDevCTCBLK->iMaxFrameBufferSize = sizeof(pDevCTCBLK->bFrameBuffer); initialize_lock( &pDevCTCBLK->Lock ); initialize_lock( &pDevCTCBLK->EventLock ); initialize_condition( &pDevCTCBLK->Event ); // Give both Herc devices a reasonable name... strlcpy( pDevCTCBLK->pDEVBLK[0]->filename, pDevCTCBLK->szTUNCharName, sizeof( pDevCTCBLK->pDEVBLK[0]->filename ) ); strlcpy( pDevCTCBLK->pDEVBLK[1]->filename, pDevCTCBLK->szTUNCharName, sizeof( pDevCTCBLK->pDEVBLK[1]->filename ) ); rc = TUNTAP_CreateInterface( pDevCTCBLK->szTUNCharName, IFF_TUN | IFF_NO_PI, &pDevCTCBLK->fd, pDevCTCBLK->szTUNDevName ); if( rc < 0 ) { free( pWrkCTCBLK ); pWrkCTCBLK = NULL; return -1; } else { logmsg(_("HHCCT073I %4.4X: TUN device %s opened\n"), pDevCTCBLK->pDEVBLK[0]->devnum, pDevCTCBLK->szTUNDevName); } #if defined(OPTION_W32_CTCI) // Set the specified driver/dll i/o buffer sizes.. { struct tt32ctl tt32ctl; memset( &tt32ctl, 0, sizeof(tt32ctl) ); strlcpy( tt32ctl.tt32ctl_name, pDevCTCBLK->szTUNDevName, sizeof(tt32ctl.tt32ctl_name) ); tt32ctl.tt32ctl_devbuffsize = pDevCTCBLK->iKernBuff; if( TUNTAP_IOCtl( pDevCTCBLK->fd, TT32SDEVBUFF, (char*)&tt32ctl ) != 0 ) { logmsg( _("HHCCT074W TT32SDEVBUFF failed for device %s: %s.\n"), pDevCTCBLK->szTUNDevName, strerror( errno ) ); } tt32ctl.tt32ctl_iobuffsize = pDevCTCBLK->iIOBuff; if( TUNTAP_IOCtl( pDevCTCBLK->fd, TT32SIOBUFF, (char*)&tt32ctl ) != 0 ) { logmsg( _("HHCCT075W TT32SIOBUFF failed for device %s: %s.\n"), pDevCTCBLK->szTUNDevName, strerror( errno ) ); } } #endif #ifdef OPTION_TUNTAP_CLRIPADDR VERIFY( TUNTAP_ClrIPAddr ( pDevCTCBLK->szTUNDevName ) == 0 ); #endif #ifdef OPTION_TUNTAP_SETMACADDR if( !pDevCTCBLK->szMACAddress[0] ) // (if MAC address unspecified) { in_addr_t wrk_guest_ip_addr; MAC wrk_guest_mac_addr; if ((in_addr_t)-1 != (wrk_guest_ip_addr = inet_addr( pDevCTCBLK->szGuestIPAddr ))) { build_herc_iface_mac ( wrk_guest_mac_addr, (const BYTE*) &wrk_guest_ip_addr ); snprintf ( pDevCTCBLK->szMACAddress, sizeof( pDevCTCBLK->szMACAddress ), "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X" ,wrk_guest_mac_addr[0] ,wrk_guest_mac_addr[1] ,wrk_guest_mac_addr[2] ,wrk_guest_mac_addr[3] ,wrk_guest_mac_addr[4] ,wrk_guest_mac_addr[5] ); } } TRACE ( "** CTCI_Init: %4.4X (%s): IP \"%s\" --> default MAC \"%s\"\n" ,pDevCTCBLK->pDEVBLK[0]->devnum ,pDevCTCBLK->szTUNDevName ,pDevCTCBLK->szGuestIPAddr ,pDevCTCBLK->szMACAddress ); VERIFY( TUNTAP_SetMACAddr ( pDevCTCBLK->szTUNDevName, pDevCTCBLK->szMACAddress ) == 0 ); #endif VERIFY( TUNTAP_SetIPAddr ( pDevCTCBLK->szTUNDevName, pDevCTCBLK->szDriveIPAddr ) == 0 ); VERIFY( TUNTAP_SetDestAddr( pDevCTCBLK->szTUNDevName, pDevCTCBLK->szGuestIPAddr ) == 0 ); #ifdef OPTION_TUNTAP_SETNETMASK VERIFY( TUNTAP_SetNetMask ( pDevCTCBLK->szTUNDevName, pDevCTCBLK->szNetMask ) == 0 ); #endif VERIFY( TUNTAP_SetMTU ( pDevCTCBLK->szTUNDevName, pDevCTCBLK->szMTU ) == 0 ); VERIFY( TUNTAP_SetFlags ( pDevCTCBLK->szTUNDevName, nIFFlags ) == 0 ); // Copy the fd to make panel.c happy pDevCTCBLK->pDEVBLK[0]->fd = pDevCTCBLK->pDEVBLK[1]->fd = pDevCTCBLK->fd; snprintf(thread_name,sizeof(thread_name),"CTCI %4.4X ReadThread",pDEVBLK->devnum); thread_name[sizeof(thread_name)-1]=0; create_thread( &pDevCTCBLK->tid, JOINABLE, CTCI_ReadThread, pDevCTCBLK, thread_name ); pDevCTCBLK->pDEVBLK[0]->tid = pDevCTCBLK->tid; pDevCTCBLK->pDEVBLK[1]->tid = pDevCTCBLK->tid; free( pWrkCTCBLK ); pWrkCTCBLK = NULL; return 0; } // // CTCI_ExecuteCCW // void CTCI_ExecuteCCW( DEVBLK* pDEVBLK, BYTE bCode, BYTE bFlags, BYTE bChained, U16 sCount, BYTE bPrevCode, int iCCWSeq, BYTE* pIOBuf, BYTE* pMore, BYTE* pUnitStat, U16* pResidual ) { int iNum; // Number of bytes to move BYTE bOpCode; // CCW opcode with modifier // bits masked off UNREFERENCED( bFlags ); UNREFERENCED( bChained ); UNREFERENCED( bPrevCode ); UNREFERENCED( iCCWSeq ); // Intervention required if the device file is not open if( pDEVBLK->fd < 0 && !IS_CCW_SENSE( bCode ) && !IS_CCW_CONTROL( bCode ) ) { pDEVBLK->sense[0] = SENSE_IR; *pUnitStat = CSW_CE | CSW_DE | CSW_UC; return; } // Mask off the modifier bits in the CCW bOpCode if( ( bCode & 0x07 ) == 0x07 ) bOpCode = 0x07; else if( ( bCode & 0x03 ) == 0x02 ) bOpCode = 0x02; else if( ( bCode & 0x0F ) == 0x0C ) bOpCode = 0x0C; else if( ( bCode & 0x03 ) == 0x01 ) bOpCode = pDEVBLK->ctcxmode ? ( bCode & 0x83 ) : 0x01; else if( ( bCode & 0x1F ) == 0x14 ) bOpCode = 0x14; else if( ( bCode & 0x47 ) == 0x03 ) bOpCode = 0x03; else if( ( bCode & 0xC7 ) == 0x43 ) bOpCode = 0x43; else bOpCode = bCode; // Process depending on CCW bOpCode switch (bOpCode) { case 0x01: // 0MMMMM01 WRITE //------------------------------------------------------------ // WRITE //------------------------------------------------------------ // Return normal status if CCW count is zero if( sCount == 0 ) { *pUnitStat = CSW_CE | CSW_DE; break; } CTCI_Write( pDEVBLK, sCount, pIOBuf, pUnitStat, pResidual ); break; case 0x81: // 1MMMMM01 WEOF //------------------------------------------------------------ // WRITE EOF //------------------------------------------------------------ // Return normal status *pUnitStat = CSW_CE | CSW_DE; break; case 0x02: // MMMMMM10 READ case 0x0C: // MMMM1100 RDBACK // ----------------------------------------------------------- // READ & READ BACKWARDS // ----------------------------------------------------------- // Read data and set unit status and residual byte count CTCI_Read( pDEVBLK, sCount, pIOBuf, pUnitStat, pResidual, pMore ); break; case 0x07: // MMMMM111 CTL // ----------------------------------------------------------- // CONTROL // ----------------------------------------------------------- *pUnitStat = CSW_CE | CSW_DE; break; case 0x03: // M0MMM011 NOP // ----------------------------------------------------------- // CONTROL NO-OPERATON // ----------------------------------------------------------- *pUnitStat = CSW_CE | CSW_DE; break; case 0x43: // 00XXX011 SBM // ----------------------------------------------------------- // SET BASIC MODE // ----------------------------------------------------------- // Command reject if in basic mode if( pDEVBLK->ctcxmode == 0 ) { pDEVBLK->sense[0] = SENSE_CR; *pUnitStat = CSW_CE | CSW_DE | CSW_UC; break; } // Reset extended mode and return normal status pDEVBLK->ctcxmode = 0; *pResidual = 0; *pUnitStat = CSW_CE | CSW_DE; break; case 0xC3: // 11000011 SEM // ----------------------------------------------------------- // SET EXTENDED MODE // ----------------------------------------------------------- pDEVBLK->ctcxmode = 1; *pResidual = 0; *pUnitStat = CSW_CE | CSW_DE; break; case 0xE3: // 11100011 // ----------------------------------------------------------- // PREPARE (PREP) // ----------------------------------------------------------- *pUnitStat = CSW_CE | CSW_DE; break; case 0x14: // XXX10100 SCB // ----------------------------------------------------------- // SENSE COMMAND BYTE // ----------------------------------------------------------- *pUnitStat = CSW_CE | CSW_DE; break; case 0x04: // 00000100 SENSE // ----------------------------------------------------------- // SENSE // ----------------------------------------------------------- // Command reject if in basic mode if( pDEVBLK->ctcxmode == 0 ) { pDEVBLK->sense[0] = SENSE_CR; *pUnitStat = CSW_CE | CSW_DE | CSW_UC; break; } // Calculate residual byte count iNum = ( sCount < pDEVBLK->numsense ) ? sCount : pDEVBLK->numsense; *pResidual = sCount - iNum; if( sCount < pDEVBLK->numsense ) *pMore = 1; // Copy device sense bytes to channel I/O buffer memcpy( pIOBuf, pDEVBLK->sense, iNum ); // Clear the device sense bytes memset( pDEVBLK->sense, 0, sizeof( pDEVBLK->sense ) ); // Return unit status *pUnitStat = CSW_CE | CSW_DE; break; case 0xE4: // 11100100 SID // ----------------------------------------------------------- // SENSE ID // ----------------------------------------------------------- // Calculate residual byte count iNum = ( sCount < pDEVBLK->numdevid ) ? sCount : pDEVBLK->numdevid; *pResidual = sCount - iNum; if( sCount < pDEVBLK->numdevid ) *pMore = 1; // Copy device identifier bytes to channel I/O buffer memcpy( pIOBuf, pDEVBLK->devid, iNum ); // Return unit status *pUnitStat = CSW_CE | CSW_DE; break; default: // ------------------------------------------------------------ // INVALID OPERATION // ------------------------------------------------------------ // Set command reject sense byte, and unit check status pDEVBLK->sense[0] = SENSE_CR; *pUnitStat = CSW_CE | CSW_DE | CSW_UC; } } // ------------------------------------------------------------------- // CTCI_Close // ------------------------------------------------------------------- int CTCI_Close( DEVBLK* pDEVBLK ) { /* DEVBLK* pDEVBLK2; */ PCTCBLK pCTCBLK = (PCTCBLK)pDEVBLK->dev_data; // Close the device file (if not already closed) if( pCTCBLK->fd >= 0 ) { // PROGRAMMING NOTE: there's currently no way to interrupt // the "CTCI_ReadThread"s TUNTAP_Read of the adapter. Thus // we must simply wait for CTCI_ReadThread to eventually // notice that we're doing a close (via our setting of the // fCloseInProgress flag). Its TUNTAP_Read will eventually // timeout after a few seconds (currently 5, which is dif- // ferent than the CTC_READ_TIMEOUT_SECS timeout value the // CTCI_Read function uses) and will then do the close of // the adapter for us (TUNTAP_Close) so we don't have to. // All we need to do is ask it to exit (via our setting of // the fCloseInProgress flag) and then wait for it to exit // (which, as stated, could take up to a max of 5 seconds). // All of this is simply because it's poor form to close a // device from one thread while another thread is reading // from it. Attempting to do so could trip a race condition // wherein the internal i/o buffers used to process the // read request could have been freed (by the close call) // by the time the read request eventually gets serviced. TID tid = pCTCBLK->tid; pCTCBLK->fCloseInProgress = 1; // (ask read thread to exit) signal_thread( tid, SIGUSR2 ); // (for non-Win32 platforms) //FIXME signal_thread not working for non-MSVC platforms #if defined(_MSVC_) join_thread( tid, NULL ); // (wait for thread to end) #endif detach_thread( tid ); // (wait for thread to end) } pDEVBLK->fd = -1; // indicate we're now closed return 0; } // ------------------------------------------------------------------- // CTCI_Query // ------------------------------------------------------------------- void CTCI_Query( DEVBLK* pDEVBLK, char** ppszClass, int iBufLen, char* pBuffer ) { CTCBLK* pCTCBLK; BEGIN_DEVICE_CLASS_QUERY( "CTCA", pDEVBLK, ppszClass, iBufLen, pBuffer ); pCTCBLK = (CTCBLK*) pDEVBLK->dev_data; if(!pCTCBLK) { strlcpy(pBuffer,"*Uninitialized",iBufLen); return; } snprintf( pBuffer, iBufLen, "CTCI %s/%s (%s)%s", pCTCBLK->szGuestIPAddr, pCTCBLK->szDriveIPAddr, pCTCBLK->szTUNDevName, pCTCBLK->fDebug ? " -d" : "" ); } // ------------------------------------------------------------------- // CTCI_Read // ------------------------------------------------------------------- // // Once an IP frame is received by the Read Thread, it is enqueued // on the device frame buffer for presentation to the host program. // The residual byte count is set to indicate the amount of the buffer // which was not filled. // // For details regarding the actual buffer layout, please refer to // the comments preceding the CTCI_ReadThread function. // Input: // pDEVBLK A pointer to the CTC adapter device block // sCount The I/O buffer length from the read CCW // pIOBuf The I/O buffer from the read CCW // // Output: // pUnitStat The CSW status (CE+DE or CE+DE+UC or CE+DE+UC+SM) // pResidual The CSW residual byte count // pMore Set to 1 if packet data exceeds CCW count // void CTCI_Read( DEVBLK* pDEVBLK, U16 sCount, BYTE* pIOBuf, BYTE* pUnitStat, U16* pResidual, BYTE* pMore ) { PCTCBLK pCTCBLK = (PCTCBLK)pDEVBLK->dev_data; PCTCIHDR pFrame = NULL; size_t iLength = 0; int rc = 0; for ( ; ; ) { obtain_lock( &pCTCBLK->Lock ); if( !pCTCBLK->fDataPending ) { struct timespec waittime; struct timeval now; release_lock( &pCTCBLK->Lock ); gettimeofday( &now, NULL ); waittime.tv_sec = now.tv_sec + CTC_READ_TIMEOUT_SECS; waittime.tv_nsec = now.tv_usec * 1000; obtain_lock( &pCTCBLK->EventLock ); rc = timed_wait_condition( &pCTCBLK->Event, &pCTCBLK->EventLock, &waittime ); release_lock( &pCTCBLK->EventLock ); if( rc == ETIMEDOUT || rc == EINTR ) { // check for halt condition if( pDEVBLK->scsw.flag2 & SCSW2_FC_HALT || pDEVBLK->scsw.flag2 & SCSW2_FC_CLEAR ) { if( pDEVBLK->ccwtrace || pDEVBLK->ccwstep ) logmsg( _("HHCCT040I %4.4X: Halt or Clear Recognized\n"), pDEVBLK->devnum ); *pUnitStat = CSW_CE | CSW_DE; *pResidual = sCount; return; } continue; } obtain_lock( &pCTCBLK->Lock ); } // Sanity check if( pCTCBLK->iFrameOffset == 0 ) { release_lock( &pCTCBLK->Lock ); continue; } // Fix-up frame pointer and terminate block pFrame = (PCTCIHDR)( pCTCBLK->bFrameBuffer + sizeof( CTCIHDR ) + pCTCBLK->iFrameOffset ); STORE_HW( pFrame->hwOffset, 0x0000 ); // (fix for day-1 bug offered by Vince Weaver [vince@deater.net]) // iLength = pCTCBLK->iFrameOffset + sizeof( CTCIHDR ) + 2; iLength = pCTCBLK->iFrameOffset + sizeof( CTCIHDR ); if( sCount < iLength ) { *pMore = 1; *pResidual = 0; iLength = sCount; } else { *pMore = 0; *pResidual -= iLength; } *pUnitStat = CSW_CE | CSW_DE; memcpy( pIOBuf, pCTCBLK->bFrameBuffer, iLength ); if( pCTCBLK->fDebug ) { logmsg( _("HHCCT041I %4.4X: CTC Received Frame (%d bytes):\n"), pDEVBLK->devnum, iLength ); packet_trace( pCTCBLK->bFrameBuffer, iLength ); } // Reset frame buffer pCTCBLK->iFrameOffset = 0; pCTCBLK->fDataPending = 0; release_lock( &pCTCBLK->Lock ); return; } } // ------------------------------------------------------------------- // CTCI_Write // ------------------------------------------------------------------- // // For details regarding the actual buffer layout, please refer to // the comments preceding the CTCI_ReadThread function. // void CTCI_Write( DEVBLK* pDEVBLK, U16 sCount, BYTE* pIOBuf, BYTE* pUnitStat, U16* pResidual ) { PCTCBLK pCTCBLK = (PCTCBLK)pDEVBLK->dev_data; PCTCIHDR pFrame; // -> Frame header PCTCISEG pSegment; // -> Segment in buffer U16 sOffset; // Offset of next frame U16 sSegLen; // Current segment length U16 sDataLen; // Length of IP Frame data int iPos; // Offset into buffer U16 i; // Array subscript int rc; // Return code BYTE szStackID[33]; // VSE IP stack identity U32 iStackCmd; // VSE IP stack command // Check that CCW count is sufficient to contain block header if( sCount < sizeof( CTCIHDR ) ) { logmsg( _("HHCCT042E %4.4X: Write CCW count %u is invalid\n"), pDEVBLK->devnum, sCount ); pDEVBLK->sense[0] = SENSE_DC; *pUnitStat = CSW_CE | CSW_DE | CSW_UC; return; } // Fix-up frame pointer pFrame = (PCTCIHDR)pIOBuf; // Extract the frame length from the header FETCH_HW( sOffset, pFrame->hwOffset ); // Check for special VSE TCP/IP stack command packet if( sOffset == 0 && sCount == 40 ) { // Extract the 32-byte stack identity string for( i = 0; i < sizeof( szStackID ) - 1 && i < sCount - 4; i++) szStackID[i] = guest_to_host( pIOBuf[i+4] ); szStackID[i] = '\0'; // Extract the stack command word FETCH_FW( iStackCmd, *((FWORD*)&pIOBuf[36]) ); // Display stack command and discard the packet logmsg( _("HHCCT043I %4.4X: Interface command: %s %8.8X\n"), pDEVBLK->devnum, szStackID, iStackCmd ); *pUnitStat = CSW_CE | CSW_DE; *pResidual = 0; return; } // Check for special L/390 initialization packet if( sOffset == 0 ) { // Return normal status and discard the packet *pUnitStat = CSW_CE | CSW_DE; *pResidual = 0; return; } #if 0 // Notes: It appears that TurboLinux has gotten sloppy in their // ways. They are now giving us buffer sizes that are // greater than the CCW count, but the segment size // is within the count. // Check that the frame offset is valid if( sOffset < sizeof( CTCIHDR ) || sOffset > sCount ) { logmsg( _("CTC101W %4.4X: Write buffer contains invalid " "frame offset %u\n"), pDEVBLK->devnum, sOffset ); pDEVBLK->sense[0] = SENSE_CR; *pUnitStat = CSW_CE | CSW_DE | CSW_UC; return; } #endif // Adjust the residual byte count *pResidual -= sizeof( CTCIHDR ); // Process each segment in the buffer for( iPos = sizeof( CTCIHDR ); iPos < sOffset; iPos += sSegLen ) { // Check that the segment is fully contained within the block if( iPos + sizeof( CTCISEG ) > sOffset ) { logmsg( _("HHCCT044E %4.4X: Write buffer contains incomplete " "segment header at offset %4.4X\n"), pDEVBLK->devnum, iPos ); pDEVBLK->sense[0] = SENSE_DC; *pUnitStat = CSW_CE | CSW_DE | CSW_UC; return; } // Fix-up segment header in the I/O buffer pSegment = (PCTCISEG)(pIOBuf + iPos); // Extract the segment length from the segment header FETCH_HW( sSegLen, pSegment->hwLength ); // Check that the segment length is valid if( ( sSegLen < sizeof( CTCISEG ) ) || ( iPos + sSegLen > sOffset ) || ( iPos + sSegLen > sCount ) ) { logmsg( _("HHCCT045E %4.4X: Write buffer contains invalid " "segment length %u at offset %4.4X\n"), pDEVBLK->devnum, sSegLen, iPos ); pDEVBLK->sense[0] = SENSE_DC; *pUnitStat = CSW_CE | CSW_DE | CSW_UC; return; } // Calculate length of IP frame data sDataLen = sSegLen - sizeof( CTCISEG ); // Trace the IP packet before sending to TUN device if( pCTCBLK->fDebug ) { logmsg( _("HHCCT046I %4.4X: Sending packet to %s:\n"), pDEVBLK->devnum, pCTCBLK->szTUNDevName ); packet_trace( pSegment->bData, sDataLen ); } // Write the IP packet to the TUN/TAP interface rc = TUNTAP_Write( pCTCBLK->fd, pSegment->bData, sDataLen ); if( rc < 0 ) { logmsg( _("HHCCT047E %4.4X: Error writing to %s: %s\n"), pDEVBLK->devnum, pCTCBLK->szTUNDevName, strerror( errno ) ); pDEVBLK->sense[0] = SENSE_EC; *pUnitStat = CSW_CE | CSW_DE | CSW_UC; return; } // Adjust the residual byte count *pResidual -= sSegLen; // We are done if current segment satisfies CCW count if( iPos + sSegLen == sCount ) { *pResidual -= sSegLen; *pUnitStat = CSW_CE | CSW_DE; return; } } // Set unit status and residual byte count *pUnitStat = CSW_CE | CSW_DE; *pResidual = 0; } // -------------------------------------------------------------------- // CTCI_ReadThread // -------------------------------------------------------------------- // // When an IP frame is received from the TUN/TAP interface, the frame // is enqueued on the device frame buffer. // // The device frame buffer is a chain of blocks. The first 2 bytes of // a block (CTCIHDR) specify the offset in the buffer of the next block. // The final block in indicated by a CTCIHDR offset value of 0x0000. // // Within each block, each IP frame is preceeded by a segment header // (CTCISEG). This segment header has a 2 byte length field that // specifies the length of the segment (including the segment header), // a 2 byte frame type field (always 0x0800 = IPv4), and a 2 byte // reserved area (always 0000), followed by the actual frame data. // // The CTCI_ReadThread reads the IP frame, then CTCI_EnqueueIPFrame // function is called to add it to the frame buffer (which precedes // each one with a CTCISEG and adjusts the block header (CTCIHDR) // offset value as appropriate. // // Oddly, it is the CTCI_Read function (called by CCW processing in // response to a guest SIO request) that adds the CTCIHDR with the // 000 offset value marking the end of the buffer's chain of blocks, // and not the CTCI_EnqueueIPFrame nor the CTCI_ReadThread as would // be expected. // // Also note that the iFrameOffset field in the CTCI device's CTCBLK // control block is the offset from the end of the buffer's first // CTCIHDR to where the end-of-chain CTCIHDR is, and is identical to // all of the queued CTCISEG's hwLength fields added together. // static void* CTCI_ReadThread( PCTCBLK pCTCBLK ) { DEVBLK* pDEVBLK = pCTCBLK->pDEVBLK[0]; int iLength; BYTE szBuff[2048]; // ZZ FIXME: Try to avoid race condition at startup with hercifc SLEEP(10); pCTCBLK->pid = getpid(); while( pCTCBLK->fd != -1 && !pCTCBLK->fCloseInProgress ) { // Read frame from the TUN/TAP interface iLength = TUNTAP_Read( pCTCBLK->fd, szBuff, sizeof(szBuff) ); // Check for error condition if( iLength < 0 ) { logmsg( _("HHCCT048E %4.4X: Error reading from %s: %s\n"), pDEVBLK->devnum, pCTCBLK->szTUNDevName, strerror( errno ) ); SLEEP(1); // (purposeful long delay) continue; } if( iLength == 0 ) // (probably EINTR; ignore) continue; if( pCTCBLK->fDebug ) { logmsg( _("HHCCT049I %4.4X: Received packet from %s (%d bytes):\n"), pDEVBLK->devnum, pCTCBLK->szTUNDevName, iLength ); packet_trace( szBuff, iLength ); } // Enqueue frame on buffer, if buffer is full, keep trying while( CTCI_EnqueueIPFrame( pDEVBLK, szBuff, iLength ) < 0 && pCTCBLK->fd != -1 && !pCTCBLK->fCloseInProgress ) { if( EMSGSIZE == errno ) // (if too large for buffer) { if( pCTCBLK->fDebug ) logmsg( _("HHCCT072W %4.4X: Packet too big; dropped.\n"), pDEVBLK->devnum ); break; // (discard it...) } ASSERT( ENOBUFS == errno ); // Don't use sched_yield() here; use an actual non-dispatchable // delay instead so as to allow another [possibly lower priority] // thread to 'read' (remove) some packet(s) from our frame buffer. usleep( CTC_DELAY_USECS ); // (wait a bit before retrying...) } } // We must do the close since we were the one doing the i/o... VERIFY( pCTCBLK->fd == -1 || TUNTAP_Close( pCTCBLK->fd ) == 0 ); pCTCBLK->fd = -1; return NULL; } // -------------------------------------------------------------------- // CTCI_EnqueueIPFrame // -------------------------------------------------------------------- // // Places the provided IP frame in the next available frame slot in // the adapter buffer. For details regarding the actual buffer layout // please refer to the comments preceding the CTCI_ReadThread function. // // Returns: // // 0 == Success // -1 == Failure; errno = ENOBUFS: No buffer space available // EMSGSIZE: Message too long // static int CTCI_EnqueueIPFrame( DEVBLK* pDEVBLK, BYTE* pData, size_t iSize ) { PCTCIHDR pFrame; PCTCISEG pSegment; PCTCBLK pCTCBLK = (PCTCBLK)pDEVBLK->dev_data; // Will frame NEVER fit into buffer?? if( iSize > MAX_CTCI_FRAME_SIZE( pCTCBLK ) ) { errno = EMSGSIZE; // Message too long return -1; // (-1==failure) } obtain_lock( &pCTCBLK->Lock ); // Ensure we dont overflow the buffer if( ( pCTCBLK->iFrameOffset + // Current buffer Offset sizeof( CTCIHDR ) + // Size of Block Header sizeof( CTCISEG ) + // Size of Segment Header iSize + // Size of Ethernet packet sizeof(pFrame->hwOffset) ) // Size of Block terminator > pCTCBLK->iMaxFrameBufferSize ) // Size of Frame buffer { release_lock( &pCTCBLK->Lock ); errno = ENOBUFS; // No buffer space available return -1; // (-1==failure) } // Fix-up Frame pointer pFrame = (PCTCIHDR)pCTCBLK->bFrameBuffer; // Fix-up Segment pointer pSegment = (PCTCISEG)( pCTCBLK->bFrameBuffer + sizeof( CTCIHDR ) + pCTCBLK->iFrameOffset ); // Initialize segment memset( pSegment, 0, iSize + sizeof( CTCISEG ) ); // Increment offset pCTCBLK->iFrameOffset += sizeof( CTCISEG ) + iSize; // Update next frame offset STORE_HW( pFrame->hwOffset, pCTCBLK->iFrameOffset + sizeof( CTCIHDR ) ); // Store segment length STORE_HW( pSegment->hwLength, sizeof( CTCISEG ) + iSize ); // Store Frame type STORE_HW( pSegment->hwType, ETH_TYPE_IP ); // Copy data memcpy( pSegment->bData, pData, iSize ); // Mark data pending pCTCBLK->fDataPending = 1; release_lock( &pCTCBLK->Lock ); obtain_lock( &pCTCBLK->EventLock ); signal_condition( &pCTCBLK->Event ); release_lock( &pCTCBLK->EventLock ); return 0; // (0==success) } // // ParseArgs // static int ParseArgs( DEVBLK* pDEVBLK, PCTCBLK pCTCBLK, int argc, char** argv ) { struct in_addr addr; // Work area for addresses int iMTU; int i; MAC mac; // Work area for MAC address #if defined(OPTION_W32_CTCI) int iKernBuff; int iIOBuff; #endif // Housekeeping memset( &addr, 0, sizeof( struct in_addr ) ); memset( &mac, 0, sizeof( MAC ) ); // Set some initial defaults strcpy( pCTCBLK->szMTU, "1500" ); strcpy( pCTCBLK->szNetMask, "255.255.255.255" ); #if defined( OPTION_W32_CTCI ) strcpy( pCTCBLK->szTUNCharName, tt32_get_default_iface() ); #else strcpy( pCTCBLK->szTUNCharName, HERCTUN_DEV ); #endif #if defined( OPTION_W32_CTCI ) pCTCBLK->iKernBuff = DEF_CAPTURE_BUFFSIZE; pCTCBLK->iIOBuff = DEF_PACKET_BUFFSIZE; #endif // Initialize getopt's counter. This is necessary in the case // that getopt was used previously for another device. OPTRESET(); optind = 0; // Check for correct number of arguments if( argc < 2 ) { logmsg( _("HHCCT056E %4.4X: Incorrect number of parameters\n"), pDEVBLK->devnum ); return -1; } // Compatability with old format configuration files needs to be // maintained. Old format statements have the tun character device // name as the second argument on Linux, or CTCI-W32 as the first // argument on Windows. if( ( strncasecmp( argv[0], "/", 1 ) == 0 ) || ( strncasecmp( pDEVBLK->typname, "CTCI-W32", 8 ) == 0 ) ) { pCTCBLK->fOldFormat = 1; } else { // Build new argv list. // getopt_long used to work on old format configuration statements // because LCS was the first argument passed to the device // initialization routine (and was interpreted by getopt* // as the program name and ignored). Now that argv[0] is a valid // argument, we need to shift the arguments and insert a dummy // argv[0]; // Don't allow us to exceed the allocated storage (sanity check) if( argc > (MAX_ARGS-1) ) argc = (MAX_ARGS-1); for( i = argc; i > 0; i-- ) argv[i] = argv[i - 1]; argc++; argv[0] = pDEVBLK->typname; } // Parse any optional arguments if not old format while( !pCTCBLK->fOldFormat ) { int c; #if defined(HAVE_GETOPT_LONG) int iOpt; static struct option options[] = { { "dev", 1, NULL, 'n' }, #if defined( OPTION_W32_CTCI ) { "kbuff", 1, NULL, 'k' }, { "ibuff", 1, NULL, 'i' }, #endif { "mtu", 1, NULL, 't' }, { "netmask", 1, NULL, 's' }, { "mac", 1, NULL, 'm' }, { "debug", 0, NULL, 'd' }, { NULL, 0, NULL, 0 } }; c = getopt_long( argc, argv, "n" #if defined( OPTION_W32_CTCI ) ":k:i" #endif ":t:s:m:d", options, &iOpt ); #else /* defined(HAVE_GETOPT_LONG) */ c = getopt( argc, argv, "n" #if defined( OPTION_W32_CTCI ) ":k:i" #endif ":t:s:m:d"); #endif /* defined(HAVE_GETOPT_LONG) */ if( c == -1 ) // No more options found break; switch( c ) { case 'n': // Network Device #if defined( OPTION_W32_CTCI ) // This could be the IP or MAC address of the // host ethernet adapter. if( inet_aton( optarg, &addr ) == 0 ) { // Not an IP address, check for valid MAC if( ParseMAC( optarg, mac ) != 0 ) { logmsg( _("HHCCT050E %4.4X: Invalid adapter address %s\n"), pDEVBLK->devnum, optarg ); return -1; } } #endif // defined( OPTION_W32_CTCI ) // This is the file name of the special TUN/TAP character device if( strlen( optarg ) > sizeof( pCTCBLK->szTUNCharName ) - 1 ) { logmsg( _("HHCCT051E %4.4X: Invalid device name %s\n"), pDEVBLK->devnum, optarg ); return -1; } strcpy( pCTCBLK->szTUNCharName, optarg ); break; #if defined( OPTION_W32_CTCI ) case 'k': // Kernel Buffer Size (Windows only) iKernBuff = atoi( optarg ); if( iKernBuff * 1024 < MIN_CAPTURE_BUFFSIZE || iKernBuff * 1024 > MAX_CAPTURE_BUFFSIZE ) { logmsg( _("HHCCT052E %4.4X: Invalid kernel buffer size %s\n"), pDEVBLK->devnum, optarg ); return -1; } pCTCBLK->iKernBuff = iKernBuff * 1024; break; case 'i': // I/O Buffer Size (Windows only) iIOBuff = atoi( optarg ); if( iIOBuff * 1024 < MIN_PACKET_BUFFSIZE || iIOBuff * 1024 > MAX_PACKET_BUFFSIZE ) { logmsg( _("HHCCT053E %4.4X: Invalid DLL I/O buffer size %s\n"), pDEVBLK->devnum, optarg ); return -1; } pCTCBLK->iIOBuff = iIOBuff * 1024; break; #endif // defined( OPTION_W32_CTCI ) case 't': // MTU of point-to-point link (ignored if Windows) iMTU = atoi( optarg ); if( iMTU < 46 || iMTU > 65536 ) { logmsg( _("HHCCT054E %4.4X: Invalid MTU size %s\n"), pDEVBLK->devnum, optarg ); return -1; } strcpy( pCTCBLK->szMTU, optarg ); break; case 's': // Netmask of point-to-point link if( inet_aton( optarg, &addr ) == 0 ) { logmsg( _("HHCCT055E %4.4X: Invalid netmask %s\n"), pDEVBLK->devnum, optarg ); return -1; } strcpy( pCTCBLK->szNetMask, optarg ); break; case 'm': if( ParseMAC( optarg, mac ) != 0 ) { logmsg( _("HHCCT056E %4.4X: Invalid MAC address %s\n"), pDEVBLK->devnum, optarg ); return -1; } strcpy( pCTCBLK->szMACAddress, optarg ); break; case 'd': // Diagnostics pCTCBLK->fDebug = TRUE; break; default: break; } } // Shift past any options argc -= optind; argv += optind; i = 0; // Check for correct number of arguments if( argc == 0 ) { logmsg( _("HHCCT056E %4.4X: Incorrect number of parameters\n"), pDEVBLK->devnum ); return -1; } if( !pCTCBLK->fOldFormat ) { // New format has 2 and only 2 parameters (Though several options). if( argc != 2 ) { logmsg( _("HHCCT057E %4.4X: Incorrect number of parameters\n"), pDEVBLK->devnum ); return -1; } // Guest IP Address if( inet_aton( *argv, &addr ) == 0 ) { logmsg( _("HHCCT058E %4.4X: Invalid IP address %s\n"), pDEVBLK->devnum, *argv ); return -1; } strcpy( pCTCBLK->szGuestIPAddr, *argv ); argc--; argv++; // Driver IP Address if( inet_aton( *argv, &addr ) == 0 ) { logmsg( _("HHCCT059E %4.4X: Invalid IP address %s\n"), pDEVBLK->devnum, *argv ); return -1; } strcpy( pCTCBLK->szDriveIPAddr, *argv ); argc--; argv++; } else // if( pCTCBLK->fOldFormat ) { #if !defined( OPTION_W32_CTCI ) // All arguments are non-optional in linux old-format // Old format has 5 and only 5 arguments if( argc != 5 ) { logmsg( _("HHCCT060E %4.4X: Incorrect number of parameters\n"), pDEVBLK->devnum ); return -1; } // TUN/TAP Device if( **argv != '/' || strlen( *argv ) > sizeof( pCTCBLK->szTUNCharName ) - 1 ) { logmsg( _("HHCCT061E %4.4X: invalid device name %s\n"), pDEVBLK->devnum, *argv ); return -1; } strcpy( pCTCBLK->szTUNCharName, *argv ); argc--; argv++; // MTU Size iMTU = atoi( *argv ); if( iMTU < 46 || iMTU > 65536 ) { logmsg( _("HHCCT062E %4.4X: Invalid MTU size %s\n"), pDEVBLK->devnum, *argv ); return -1; } strcpy( pCTCBLK->szMTU, *argv ); argc--; argv++; // Guest IP Address if( inet_aton( *argv, &addr ) == 0 ) { logmsg( _("HHCCT063E %4.4X: Invalid IP address %s\n"), pDEVBLK->devnum, *argv ); return -1; } strcpy( pCTCBLK->szGuestIPAddr, *argv ); argc--; argv++; // Driver IP Address if( inet_aton( *argv, &addr ) == 0 ) { logmsg( _("HHCCT064E %4.4X: Invalid IP address %s\n"), pDEVBLK->devnum, *argv ); return -1; } strcpy( pCTCBLK->szDriveIPAddr, *argv ); argc--; argv++; // Netmask if( inet_aton( *argv, &addr ) == 0 ) { logmsg( _("HHCCT065E %4.4X: Invalid netmask %s\n"), pDEVBLK->devnum, *argv ); return -1; } strcpy( pCTCBLK->szNetMask, *argv ); argc--; argv++; if( argc > 0 ) { logmsg( _("HHCCT066E %4.4X: Incorrect number of parameters\n"), pDEVBLK->devnum ); return -1; } #else // defined( OPTION_W32_CTCI ) // There are 2 non-optional arguments in the Windows old-format: // Guest IP address and Gateway address. // There are also 2 additional optional arguments: // Kernel buffer size and I/O buffer size. while( argc > 0 ) { switch( i ) { case 0: // Non-optional arguments // Guest IP Address if( inet_aton( *argv, &addr ) == 0 ) { logmsg( _("HHCCT067E %4.4X: Invalid IP address %s\n"), pDEVBLK->devnum, *argv ); return -1; } strcpy( pCTCBLK->szGuestIPAddr, *argv ); argc--; argv++; // Destination (Gateway) Address if( inet_aton( *argv, &addr ) == 0 ) { // Not an IP address, check for valid MAC if( ParseMAC( *argv, mac ) != 0 ) { logmsg( _("HHCCT068E %4.4X: Invalid MAC address %s\n"), pDEVBLK->devnum, *argv ); return -1; } } strcpy( pCTCBLK->szTUNCharName, *argv ); // Kludge: This may look strange at first, but with // TunTap32, only the last 3 bytes of the "driver IP // address" is actually used. It's purpose is to // generate a unique MAC for the virtual interface. // Thus, having the same address for the adapter and // destination is not an issue. This used to be // generated from the guest IP address, I screwed up // TunTap32 V2. (JAP) // This also fixes the confusing error messages from // TunTap.c when a MAC is given for this argument. strcpy( pCTCBLK->szDriveIPAddr, pCTCBLK->szGuestIPAddr ); argc--; argv++; i++; continue; case 1: // Optional arguments from here on: // Kernel Buffer Size iKernBuff = atoi( *argv ); if( iKernBuff * 1024 < MIN_CAPTURE_BUFFSIZE || iKernBuff * 1024 > MAX_CAPTURE_BUFFSIZE ) { logmsg( _("HHCCT069E %4.4X: Invalid kernel buffer size %s\n"), pDEVBLK->devnum, *argv ); return -1; } pCTCBLK->iKernBuff = iKernBuff * 1024; argc--; argv++; i++; continue; case 2: // I/O Buffer Size iIOBuff = atoi( *argv ); if( iIOBuff * 1024 < MIN_PACKET_BUFFSIZE || iIOBuff * 1024 > MAX_PACKET_BUFFSIZE ) { logmsg( _("HHCCT070E %4.4X: Invalid DLL I/O buffer size %s\n"), pDEVBLK->devnum, *argv ); return -1; } pCTCBLK->iIOBuff = iIOBuff * 1024; argc--; argv++; i++; continue; default: logmsg( _("HHCCT071E %4.4X: Incorrect number of parameters\n"), pDEVBLK->devnum ); return -1; } } #endif // !defined( OPTION_W32_CTCI ) } return 0; } #endif /* !defined(__SOLARIS__) jbs */ hercules-3.07/ctc_lcs.c000644 000765 000765 00000272163 11143760543 016540 0ustar00jmaynardjmaynard000000 000000 // ==================================================================== // Hercules LAN Channel Station Support // ==================================================================== // // Copyright (C) 2002-2009 by James A. Pierson (original author) // Copyright (C) 2002-2009 by David B. Trout (current maintainer) // // $Id: ctc_lcs.c 5125 2009-01-23 12:01:44Z bernard $ // // $Log$ // Revision 1.81 2008/12/23 14:01:22 rbowler // Allow symbol substitution in OAT files // // Revision 1.80 2008/12/22 14:14:03 rbowler // Correct typographical error in message HHCLC032E // // Revision 1.79 2008/11/04 05:56:31 fish // Put ensure consistent create_thread ATTR usage change back in // // Revision 1.78 2008/11/03 15:31:57 rbowler // Back out consistent create_thread ATTR modification // // Revision 1.77 2008/10/18 09:32:21 fish // Ensure consistent create_thread ATTR usage // // Revision 1.76 2008/08/19 21:36:37 fish // Init LCS interface ASAP to fix wrong MAC being used // // Revision 1.75 2008/08/15 04:40:49 fish // Trace LCS Command Frame packets as they are received, // ensure iMaxFrameBufferSize greater than minimum allowed. // // Revision 1.74 2008/07/17 07:42:15 fish // (extremely minor comment change only) // // Revision 1.73 2008/07/17 07:19:12 fish // Fix FCS (Frame Check Sequence) bug in LCS_Write function // and other minor bugs. // // Revision 1.71 2008/07/17 03:30:40 fish // CTC/LCS cosmetic-only changes -- part 1 // (no actual functionality was changed!) // // Revision 1.70 2008/05/22 18:27:25 fish // Fix read timeout bug in LCS logic // // Revision 1.69 2008/02/07 00:29:04 rbowler // Solaris build support by Jeff Savit // // Revision 1.68 2008/01/11 21:33:21 fish // new 'ctc' command to enable/disable debug option on demand // // Revision 1.67 2007/11/21 22:54:14 fish // Use new BEGIN_DEVICE_CLASS_QUERY macro // // Revision 1.66 2007/08/17 00:59:40 fish // Backout 28 Jul fix for LCS (fix was only meant for CTCI) // // Revision 1.65 2007/07/29 02:02:44 fish // Fix day-1 CTCI/LCS bug found by Vince Weaver [vince@deater.net] // // Revision 1.64 2007/06/23 00:04:05 ivan // Update copyright notices to include current year (2007) // // Revision 1.63 2007/02/25 15:05:46 fish // Fix crash in LCS close if devinit of incomplete group // // Revision 1.62 2007/01/14 22:17:35 rbowler // Correct compile error introduced by rev 1.61 // // Revision 1.61 2007/01/14 08:03:30 fish // correct minor (benign(?)) bug in LCS_QueryIPAssists, fix HHCLC011I and related deug msgs in LCS_PortThread to display IP address in correct byte-order. // // Revision 1.60 2006/12/08 09:43:19 jj // Add CVS message log // #include "hstdinc.h" /* jbs 10/27/2007 added _SOLARIS_ */ #if !defined(__SOLARIS__) #include "hercules.h" #include "ctcadpt.h" #include "tuntap.h" #include "hercifc.h" #include "opcode.h" #include "herc_getopt.h" #if defined(OPTION_W32_CTCI) #include "tt32api.h" #endif //----------------------------------------------------------------------------- // Debugging... //#define NO_LCS_OPTIMIZE // #undef for Release, #define while testing #if !defined( DEBUG) && !defined( _DEBUG ) // only needed for Release builds #ifdef NO_LCS_OPTIMIZE // for reliable breakpoints and instr stepping #pragma optimize( "", off ) // disable optimizations for reliable breakpoints #pragma warning( push ) // save current settings #pragma warning( disable: 4748 ) // C4748: /GS can not ... because optimizations are disabled... #endif // NO_LCS_OPTIMIZE #endif // !defined( DEBUG) && !defined( _DEBUG ) #ifdef NO_LCS_OPTIMIZE #undef ASSERT #undef VERIFY #ifdef _MSVC_ #define ASSERT(a) \ do \ { \ if (!(a)) \ { \ logmsg("HHCxx999W *** Assertion Failed! *** %s(%d); function: %s\n",__FILE__,__LINE__,__FUNCTION__); \ if (IsDebuggerPresent()) DebugBreak(); /* (break into debugger) */ \ } \ } \ while(0) #else // ! _MSVC_ #define ASSERT(a) \ do \ { \ if (!(a)) \ { \ logmsg("HHCxx999W *** Assertion Failed! *** %s(%d)\n",__FILE__,__LINE__); \ } \ } \ while(0) #endif // _MSVC_ #define VERIFY(a) ASSERT((a)) #endif // NO_LCS_OPTIMIZE //----------------------------------------------------------------------------- /* CCW Codes 0x03 & 0xC3 are immediate commands */ static BYTE CTC_Immed_Commands [256] = { /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ 0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0, /* 00 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 10 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 20 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 30 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 40 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 50 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 60 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 70 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 80 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 90 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* A0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* B0 */ 0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0, /* C0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* D0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* E0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* F0 */ }; // ==================================================================== // Declarations // ==================================================================== static void LCS_Startup ( PLCSDEV pLCSDEV, PLCSCMDHDR pCmdFrame ); static void LCS_Shutdown ( PLCSDEV pLCSDEV, PLCSCMDHDR pCmdFrame ); static void LCS_StartLan ( PLCSDEV pLCSDEV, PLCSCMDHDR pCmdFrame ); static void LCS_StopLan ( PLCSDEV pLCSDEV, PLCSCMDHDR pCmdFrame ); static void LCS_QueryIPAssists( PLCSDEV pLCSDEV, PLCSCMDHDR pCmdFrame ); static void LCS_LanStats ( PLCSDEV pLCSDEV, PLCSCMDHDR pCmdFrame ); static void LCS_DefaultCmdProc( PLCSDEV pLCSDEV, PLCSCMDHDR pCmdFrame ); static void* LCS_PortThread( PLCSPORT pLCSPORT ); static int LCS_EnqueueEthFrame( PLCSDEV pLCSDEV, BYTE bPort, BYTE* pData, size_t iSize ); static void* LCS_InitReplyFrame( PLCSDEV pLCSDEV, size_t iSize, PLCSCMDHDR pCmdFrame ); static int BuildOAT( char* pszOATName, PLCSBLK pLCSBLK ); static char* ReadOAT( char* pszOATName, FILE* fp, char* pszBuff ); static int ParseArgs( DEVBLK* pDEVBLK, PLCSBLK pLCSBLK, int argc, char** argv ); // ==================================================================== // find_group_device // ==================================================================== static DEVBLK * find_group_device(DEVGRP *group, U16 devnum) { int i; for(i = 0; i < group->acount; i++) if( group->memdev[i]->devnum == devnum ) return group->memdev[i]; return NULL; } // ==================================================================== // LCS_Init // ==================================================================== int LCS_Init( DEVBLK* pDEVBLK, int argc, char *argv[] ) { PLCSBLK pLCSBLK; PLCSDEV pLCSDev; int i; struct in_addr addr; // Work area for addresses pDEVBLK->devtype = 0x3088; // Return when an existing group has been joined but is still incomplete if(!group_device(pDEVBLK, 0) && pDEVBLK->group) return 0; // We need to create a group, and as such determine the number of devices if(!pDEVBLK->group) { // Housekeeping pLCSBLK = malloc( sizeof( LCSBLK ) ); if( !pLCSBLK ) { logmsg( _("HHCLC001E %4.4X unable to allocate LCSBLK\n"), pDEVBLK->devnum ); return -1; } memset( pLCSBLK, 0, sizeof( LCSBLK ) ); for( i = 0; i < LCS_MAX_PORTS; i++ ) { memset( &pLCSBLK->Port[i], 0, sizeof ( LCSPORT ) ); pLCSBLK->Port[i].bPort = i; pLCSBLK->Port[i].pLCSBLK = pLCSBLK; // Initialize locking and event mechanisms initialize_lock( &pLCSBLK->Port[i].Lock ); initialize_lock( &pLCSBLK->Port[i].EventLock ); initialize_condition( &pLCSBLK->Port[i].Event ); } // Parse configuration file statement if( ParseArgs( pDEVBLK, pLCSBLK, argc, (char**)argv ) != 0 ) { free( pLCSBLK ); pLCSBLK = NULL; return -1; } if( pLCSBLK->pszOATFilename ) { // If an OAT file was specified, Parse it and build the // OAT table. if( BuildOAT( pLCSBLK->pszOATFilename, pLCSBLK ) != 0 ) { free( pLCSBLK ); pLCSBLK = NULL; return -1; } } else { // Otherwise, build an OAT based on the address specified // in the config file with an assumption of IP mode. pLCSBLK->pDevices = malloc( sizeof( LCSDEV ) ); memset( pLCSBLK->pDevices, 0, sizeof( LCSDEV ) ); if( pLCSBLK->pszIPAddress ) inet_aton( pLCSBLK->pszIPAddress, &addr ); pLCSBLK->pDevices->sAddr = pDEVBLK->devnum; pLCSBLK->pDevices->bMode = LCSDEV_MODE_IP; pLCSBLK->pDevices->bPort = 0; pLCSBLK->pDevices->bType = 0; pLCSBLK->pDevices->lIPAddress = addr.s_addr; // (network byte order) pLCSBLK->pDevices->pszIPAddress = pLCSBLK->pszIPAddress; pLCSBLK->pDevices->pNext = NULL; pLCSBLK->icDevices = 2; } // Now we must create the group if(!group_device(pDEVBLK, pLCSBLK->icDevices)) { pDEVBLK->group->grp_data = pLCSBLK; return 0; } else pDEVBLK->group->grp_data = pLCSBLK; } else pLCSBLK = pDEVBLK->group->grp_data; // When this code is reached the last devblk has been allocated... // // Now build the LCSDEV's. // If an OAT is specified, the addresses that were specified in the // hercules.cnf file must match those that are specified in the OAT. for( pLCSDev = pLCSBLK->pDevices; pLCSDev; pLCSDev = pLCSDev->pNext ) { pLCSDev->pDEVBLK[0] = find_group_device(pDEVBLK->group, pLCSDev->sAddr); if( !pLCSDev->pDEVBLK[0] ) { logmsg(D_("HHCLC040E %4.4X LCSDEV %4.4X not in configuration\n"), pDEVBLK->group->memdev[0]->devnum, pLCSDev->sAddr ); return -1; } // Establish SENSE ID and Command Information Word data. SetSIDInfo( pLCSDev->pDEVBLK[0], 0x3088, 0x60, 0x3088, 0x01 ); // SetCIWInfo( pLCSDev->pDEVBLK[0], 0, 0, 0x72, 0x0080 ); // SetCIWInfo( pLCSDev->pDEVBLK[0], 1, 1, 0x83, 0x0004 ); // SetCIWInfo( pLCSDev->pDEVBLK[0], 2, 2, 0x82, 0x0040 ); pLCSDev->pDEVBLK[0]->ctctype = CTC_LCS; pLCSDev->pDEVBLK[0]->ctcxmode = 1; pLCSDev->pDEVBLK[0]->dev_data = pLCSDev; pLCSDev->pLCSBLK = pLCSBLK; strcpy( pLCSDev->pDEVBLK[0]->filename, pLCSBLK->pszTUNDevice ); // If this is an IP Passthru address, we need a write address if( pLCSDev->bMode == LCSDEV_MODE_IP ) { pLCSDev->pDEVBLK[1] = find_group_device(pDEVBLK->group, pLCSDev->sAddr^1); if( !pLCSDev->pDEVBLK[1] ) { logmsg(D_("HHCLC040E %4.4X LCSDEV %4.4X not in configuration\n"), pDEVBLK->group->memdev[0]->devnum, pLCSDev->sAddr^1 ); return -1; } // Establish SENSE ID and Command Information Word data. SetSIDInfo( pLCSDev->pDEVBLK[1], 0x3088, 0x60, 0x3088, 0x01 ); // SetCIWInfo( pLCSDev->pDEVBLK[1], 0, 0, 0x72, 0x0080 ); // SetCIWInfo( pLCSDev->pDEVBLK[1], 1, 1, 0x83, 0x0004 ); // SetCIWInfo( pLCSDev->pDEVBLK[1], 2, 2, 0x82, 0x0040 ); pLCSDev->pDEVBLK[1]->ctctype = CTC_LCS; pLCSDev->pDEVBLK[1]->ctcxmode = 1; pLCSDev->pDEVBLK[1]->dev_data = pLCSDev; strcpy( pLCSDev->pDEVBLK[1]->filename, pLCSBLK->pszTUNDevice ); } // Indicate that the DEVBLK(s) have been create sucessfully pLCSDev->fCreated = 1; // Initialize locking and event mechanisms initialize_lock( &pLCSDev->Lock ); initialize_lock( &pLCSDev->EventLock ); initialize_condition( &pLCSDev->Event ); // Create the TAP interface (if not already created by a // previous pass. More than one interface can exist on a port. if( !pLCSBLK->Port[pLCSDev->bPort].fCreated ) { int rc; rc = TUNTAP_CreateInterface( pLCSBLK->pszTUNDevice, IFF_TAP | IFF_NO_PI, &pLCSBLK->Port[pLCSDev->bPort].fd, pLCSBLK->Port[pLCSDev->bPort].szNetDevName ); logmsg(_("HHCLC073I %4.4X: TAP device %s opened\n"), pLCSDev->pDEVBLK[0]->devnum, pLCSBLK->Port[pLCSDev->bPort].szNetDevName); #if defined(OPTION_W32_CTCI) // Set the specified driver/dll i/o buffer sizes.. { struct tt32ctl tt32ctl; memset( &tt32ctl, 0, sizeof(tt32ctl) ); strlcpy( tt32ctl.tt32ctl_name, pLCSBLK->Port[pLCSDev->bPort].szNetDevName, sizeof(tt32ctl.tt32ctl_name) ); tt32ctl.tt32ctl_devbuffsize = pLCSBLK->iKernBuff; if( TUNTAP_IOCtl( pLCSBLK->Port[pLCSDev->bPort].fd, TT32SDEVBUFF, (char*)&tt32ctl ) != 0 ) { logmsg( _("HHCLC074W TT32SDEVBUFF failed for device %s: %s.\n"), pLCSBLK->Port[pLCSDev->bPort].szNetDevName, strerror( errno ) ); } tt32ctl.tt32ctl_iobuffsize = pLCSBLK->iIOBuff; if( TUNTAP_IOCtl( pLCSBLK->Port[pLCSDev->bPort].fd, TT32SIOBUFF, (char*)&tt32ctl ) != 0 ) { logmsg( _("HHCLC075W TT32SIOBUFF failed for device %s: %s.\n"), pLCSBLK->Port[pLCSDev->bPort].szNetDevName, strerror( errno ) ); } } #endif // Indicate that the port is used. pLCSBLK->Port[pLCSDev->bPort].fUsed = 1; pLCSBLK->Port[pLCSDev->bPort].fCreated = 1; create_thread( &pLCSBLK->Port[pLCSDev->bPort].tid, JOINABLE, LCS_PortThread, &pLCSBLK->Port[pLCSDev->bPort], "LCS_PortThread" ); /* Identify the thread ID with the devices on which they are active */ pLCSDev->pDEVBLK[0]->tid = pLCSBLK->Port[pLCSDev->bPort].tid; if (pLCSDev->pDEVBLK[1]) pLCSDev->pDEVBLK[1]->tid = pLCSBLK->Port[pLCSDev->bPort].tid; } // Add these devices to the ports device list. pLCSBLK->Port[pLCSDev->bPort].icDevices++; pLCSDev->pDEVBLK[0]->fd = pLCSBLK->Port[pLCSDev->bPort].fd; if( pLCSDev->pDEVBLK[1] ) pLCSDev->pDEVBLK[1]->fd = pLCSBLK->Port[pLCSDev->bPort].fd; } return 0; } // ==================================================================== // LCS_ExecuteCCW // ==================================================================== void LCS_ExecuteCCW( DEVBLK* pDEVBLK, BYTE bCode, BYTE bFlags, BYTE bChained, U16 sCount, BYTE bPrevCode, int iCCWSeq, BYTE* pIOBuf, BYTE* pMore, BYTE* pUnitStat, U16* pResidual ) { int iNum; // Number of bytes to move BYTE bOpCode; // CCW opcode with modifier // bits masked off UNREFERENCED( bFlags ); UNREFERENCED( bChained ); UNREFERENCED( bPrevCode ); UNREFERENCED( iCCWSeq ); // Intervention required if the device file is not open if( pDEVBLK->fd < 0 && !IS_CCW_SENSE( bCode ) && !IS_CCW_CONTROL( bCode ) ) { pDEVBLK->sense[0] = SENSE_IR; *pUnitStat = CSW_CE | CSW_DE | CSW_UC; return; } // Mask off the modifier bits in the CCW bOpCode if( ( bCode & 0x07 ) == 0x07 ) bOpCode = 0x07; else if( ( bCode & 0x03 ) == 0x02 ) bOpCode = 0x02; else if( ( bCode & 0x0F ) == 0x0C ) bOpCode = 0x0C; else if( ( bCode & 0x03 ) == 0x01 ) bOpCode = pDEVBLK->ctcxmode ? ( bCode & 0x83 ) : 0x01; else if( ( bCode & 0x1F ) == 0x14 ) bOpCode = 0x14; else if( ( bCode & 0x47 ) == 0x03 ) bOpCode = 0x03; else if( ( bCode & 0xC7 ) == 0x43 ) bOpCode = 0x43; #if 0 // Special case for LCS CIW's else if( ( bCode == 72 || bCode == 82 || bCode == 83 ) ) bOpCode == bCode; #endif else bOpCode = bCode; // Process depending on CCW bOpCode switch (bOpCode) { case 0x01: // 0MMMMM01 WRITE //------------------------------------------------------------ // WRITE //------------------------------------------------------------ // Return normal status if CCW count is zero if( sCount == 0 ) { *pUnitStat = CSW_CE | CSW_DE; break; } LCS_Write( pDEVBLK, sCount, pIOBuf, pUnitStat, pResidual ); break; case 0x81: // 1MMMMM01 WEOF //------------------------------------------------------------ // WRITE EOF //------------------------------------------------------------ // Return normal status *pUnitStat = CSW_CE | CSW_DE; break; case 0x02: // MMMMMM10 READ case 0x0C: // MMMM1100 RDBACK // ----------------------------------------------------------- // READ & READ BACKWARDS // ----------------------------------------------------------- // Read data and set unit status and residual byte count LCS_Read( pDEVBLK, sCount, pIOBuf, pUnitStat, pResidual, pMore ); break; case 0x07: // MMMMM111 CTL // ----------------------------------------------------------- // CONTROL // ----------------------------------------------------------- *pUnitStat = CSW_CE | CSW_DE; break; case 0x03: // M0MMM011 NOP // ----------------------------------------------------------- // CONTROL NO-OPERATON // ----------------------------------------------------------- *pUnitStat = CSW_CE | CSW_DE; break; case 0x43: // 00XXX011 SBM // ----------------------------------------------------------- // SET BASIC MODE // ----------------------------------------------------------- // Command reject if in basic mode if( pDEVBLK->ctcxmode == 0 ) { pDEVBLK->sense[0] = SENSE_CR; *pUnitStat = CSW_CE | CSW_DE | CSW_UC; break; } // Reset extended mode and return normal status pDEVBLK->ctcxmode = 0; *pResidual = 0; *pUnitStat = CSW_CE | CSW_DE; break; case 0xC3: // 11000011 SEM // ----------------------------------------------------------- // SET EXTENDED MODE // ----------------------------------------------------------- pDEVBLK->ctcxmode = 1; *pResidual = 0; *pUnitStat = CSW_CE | CSW_DE; break; case 0xE3: // 11100011 // ----------------------------------------------------------- // PREPARE (PREP) // ----------------------------------------------------------- *pUnitStat = CSW_CE | CSW_DE; break; case 0x14: // XXX10100 SCB // ----------------------------------------------------------- // SENSE COMMAND BYTE // ----------------------------------------------------------- *pUnitStat = CSW_CE | CSW_DE; break; case 0x04: // 00000100 SENSE // ----------------------------------------------------------- // SENSE // ----------------------------------------------------------- // Command reject if in basic mode if( pDEVBLK->ctcxmode == 0 ) { pDEVBLK->sense[0] = SENSE_CR; *pUnitStat = CSW_CE | CSW_DE | CSW_UC; break; } // Calculate residual byte count iNum = ( sCount < pDEVBLK->numsense ) ? sCount : pDEVBLK->numsense; *pResidual = sCount - iNum; if( sCount < pDEVBLK->numsense ) *pMore = 1; // Copy device sense bytes to channel I/O buffer memcpy( pIOBuf, pDEVBLK->sense, iNum ); // Clear the device sense bytes memset( pDEVBLK->sense, 0, sizeof( pDEVBLK->sense ) ); // Return unit status *pUnitStat = CSW_CE | CSW_DE; break; case 0xE4: // 11100100 SID // ----------------------------------------------------------- // SENSE ID // ----------------------------------------------------------- // Calculate residual byte count iNum = ( sCount < pDEVBLK->numdevid ) ? sCount : pDEVBLK->numdevid; *pResidual = sCount - iNum; if( sCount < pDEVBLK->numdevid ) *pMore = 1; // Copy device identifier bytes to channel I/O buffer memcpy( pIOBuf, pDEVBLK->devid, iNum ); // Return unit status *pUnitStat = CSW_CE | CSW_DE; break; #if 0 case 0x72: // 0111010 RCD // ------------------------------------------------------------ // READ CONFIGURATION DATA // ------------------------------------------------------------ case 0x82: // 10000010 SID // ------------------------------------------------------------ // SET INTERFACE IDENTIFER // ------------------------------------------------------------ case 0x83: // 10000011 RID // ------------------------------------------------------------ // READ NODE IDENTIFER // ------------------------------------------------------------ LCS_SDC( pDEVBLK, bOpCode, sCount, pIOBuf, pUnitStat, pResidual, pMore ); break; #endif default: // ------------------------------------------------------------ // INVALID OPERATION // ------------------------------------------------------------ // Set command reject sense byte, and unit check status pDEVBLK->sense[0] = SENSE_CR; *pUnitStat = CSW_CE | CSW_DE | CSW_UC; } } // ==================================================================== // LCS_Close // ==================================================================== int LCS_Close( DEVBLK* pDEVBLK ) { PLCSDEV pLCSDEV; PLCSBLK pLCSBLK; PLCSPORT pLCSPORT; if (!(pLCSDEV = (PLCSDEV)pDEVBLK->dev_data)) return 0; // (was incomplete group) pLCSBLK = pLCSDEV->pLCSBLK; pLCSPORT = &pLCSBLK->Port[pLCSDEV->bPort]; pLCSPORT->icDevices--; // Is this the last device on the port? if( !pLCSPORT->icDevices ) { // PROGRAMMING NOTE: there's currently no way to interrupt // the "LCS_PortThread"s TUNTAP_Read of the adapter. Thus // we must simply wait for LCS_PortThread to eventually // notice that we're doing a close (via our setting of the // fCloseInProgress flag). Its TUNTAP_Read will eventually // timeout after a few seconds (currently 5, which is dif- // ferent than the CTC_READ_TIMEOUT_SECS timeout value the // CTCI_Read function uses) and will then do the close of // the adapter for us (TUNTAP_Close) so we don't have to. // All we need to do is ask it to exit (via our setting of // the fCloseInProgress flag) and then wait for it to exit // (which, as stated, could take up to a max of 5 seconds). // All of this is simply because it's poor form to close a // device from one thread while another thread is reading // from it. Attempting to do so could trip a race condition // wherein the internal i/o buffers used to process the // read request could have been freed (by the close call) // by the time the read request eventually gets serviced. if( pLCSPORT->fd >= 0 ) { TID tid = pLCSPORT->tid; obtain_lock( &pLCSPORT->EventLock ); { pLCSPORT->fStarted = 0; pLCSPORT->fCloseInProgress = 1; signal_condition( &pLCSPORT->Event ); } release_lock( &pLCSPORT->EventLock ); signal_thread( tid, SIGUSR2 ); join_thread( tid, NULL ); detach_thread( tid ); } if( pLCSDEV->pDEVBLK[0] && pLCSDEV->pDEVBLK[0]->fd >= 0 ) pLCSDEV->pDEVBLK[0]->fd = -1; if( pLCSDEV->pDEVBLK[1] && pLCSDEV->pDEVBLK[1]->fd >= 0 ) pLCSDEV->pDEVBLK[1]->fd = -1; } // Housekeeping if( pLCSDEV->pDEVBLK[0] == pDEVBLK ) pLCSDEV->pDEVBLK[0] = NULL; if( pLCSDEV->pDEVBLK[1] == pDEVBLK ) pLCSDEV->pDEVBLK[1] = NULL; if( !pLCSDEV->pDEVBLK[0] && !pLCSDEV->pDEVBLK[1] ) { // Remove this LCS Device from the chain... PLCSDEV pCurrLCSDev = NULL; PLCSDEV* ppPrevLCSDev = &pLCSBLK->pDevices; for( pCurrLCSDev = pLCSBLK->pDevices; pCurrLCSDev; pCurrLCSDev = pCurrLCSDev->pNext ) { if( pCurrLCSDev == pLCSDEV ) { *ppPrevLCSDev = pCurrLCSDev->pNext; if( pCurrLCSDev->pszIPAddress ) { free( pCurrLCSDev->pszIPAddress ); pCurrLCSDev->pszIPAddress = NULL; } free( pLCSDEV ); pLCSDEV = NULL; break; } ppPrevLCSDev = &pCurrLCSDev->pNext; } } if( !pLCSBLK->pDevices ) { if( pLCSBLK->pszTUNDevice ) { free( pLCSBLK->pszTUNDevice ); pLCSBLK->pszTUNDevice = NULL; } if( pLCSBLK->pszOATFilename ) { free( pLCSBLK->pszOATFilename ); pLCSBLK->pszOATFilename = NULL; } // if( pLCSBLK->pszIPAddress ) { free( pLCSBLK->pszIPAddress ); pLCSBLK->pszIPAddress = NULL; } if( pLCSBLK->pszMACAddress ) { free( pLCSBLK->pszMACAddress ); pLCSBLK->pszMACAddress = NULL; } if( pLCSBLK->pszOATFilename ) { if( pLCSBLK->pszIPAddress ) { free( pLCSBLK->pszIPAddress ); pLCSBLK->pszIPAddress = NULL; } } free( pLCSBLK ); pLCSBLK = NULL; } pDEVBLK->dev_data = NULL; return 0; } // ==================================================================== // LCS_Query // ==================================================================== void LCS_Query( DEVBLK* pDEVBLK, char** ppszClass, int iBufLen, char* pBuffer ) { char *sType[] = { "", " Pri", " Sec" }; LCSDEV* pLCSDEV; BEGIN_DEVICE_CLASS_QUERY( "CTCA", pDEVBLK, ppszClass, iBufLen, pBuffer ); pLCSDEV = (LCSDEV*) pDEVBLK->dev_data; if(!pLCSDEV) { strlcpy(pBuffer,"*Uninitialized",iBufLen); return; } snprintf( pBuffer, iBufLen, "LCS Port %2.2X %s%s (%s)%s", pLCSDEV->bPort, pLCSDEV->bMode == LCSDEV_MODE_IP ? "IP" : "SNA", sType[pLCSDEV->bType], pLCSDEV->pLCSBLK->Port[pLCSDEV->bPort].szNetDevName, pLCSDEV->pLCSBLK->fDebug ? " -d" : "" ); } // ==================================================================== // LCS_Read // ==================================================================== // The guest o/s is issuing a Read CCW for our LCS device. Return to // it all available LCS Frames that we have buffered up in our buffer. // -------------------------------------------------------------------- void LCS_Read( DEVBLK* pDEVBLK, U16 sCount, BYTE* pIOBuf, BYTE* pUnitStat, U16* pResidual, BYTE* pMore ) { PLCSHDR pLCSHdr; PLCSDEV pLCSDEV = (PLCSDEV)pDEVBLK->dev_data; size_t iLength = 0; int rc = 0; // FIXME: we currently don't support data-chaining but // probably should if real LCS devices do (I was unable // to determine whether they do or not). -- Fish for (;;) { // Wait for some LCS Frames to arrive in our buffer... obtain_lock( &pLCSDEV->Lock ); if( !( pLCSDEV->fDataPending || pLCSDEV->fReplyPending ) ) { struct timespec waittime; struct timeval now; release_lock( &pLCSDEV->Lock ); // Wait 5 seconds then check for channel conditions gettimeofday( &now, NULL ); waittime.tv_sec = now.tv_sec + CTC_READ_TIMEOUT_SECS; waittime.tv_nsec = now.tv_usec * 1000; obtain_lock( &pLCSDEV->EventLock ); rc = timed_wait_condition( &pLCSDEV->Event, &pLCSDEV->EventLock, &waittime ); release_lock( &pLCSDEV->EventLock ); // If we didn't receive any, keep waiting... if( rc == ETIMEDOUT || rc == EINTR ) { // check for halt condition if( pDEVBLK->scsw.flag2 & SCSW2_FC_HALT || pDEVBLK->scsw.flag2 & SCSW2_FC_CLEAR ) { if( pDEVBLK->ccwtrace || pDEVBLK->ccwstep ) logmsg( _("HHCLC002I %4.4X: Halt or Clear Recognized\n"), pDEVBLK->devnum ); *pUnitStat = CSW_CE | CSW_DE; *pResidual = sCount; return; } continue; // (keep waiting) } // We received some LCS Frames... obtain_lock( &pLCSDEV->Lock ); } // Point to the end of all buffered LCS Frames... // (where the next Frame *would* go if there was one) pLCSHdr = (PLCSHDR)( pLCSDEV->bFrameBuffer + pLCSDEV->iFrameOffset ); // Mark the end of this batch of LCS Frames by setting // the "offset to NEXT frame" LCS Header field to zero. // (a zero "next Frame offset" is like an "EOF" flag) STORE_HW( pLCSHdr->hwOffset, 0x0000 ); // Calculate how much data we're going to be giving them. // Since 'iFrameOffset' points to the next available LCS // Frame slot in our buffer, the total amount of LCS Frame // data we have is exactly that amount. We give them two // extra bytes however so that they can optionally chase // the "hwOffset" field in each LCS Frame's LCS Header to // eventually reach our zero hwOffset "EOF" flag). iLength = pLCSDEV->iFrameOffset + sizeof(pLCSHdr->hwOffset); // (calculate residual and set memcpy amount) // FIXME: we currently don't support data-chaining but // probably should if real LCS devices do (I was unable // to determine whether they do or not). -- Fish if( sCount < iLength ) { *pMore = 1; *pResidual = 0; iLength = sCount; // PROGRAMMING NOTE: As a result of the caller asking // for less data than we actually have available, the // remainder of their unread data they didn't ask for // will end up being silently discarded. Refer to the // other NOTEs and FIXME's sprinkled throughout this // function... } else { *pMore = 0; *pResidual -= iLength; } *pUnitStat = CSW_CE | CSW_DE; memcpy( pIOBuf, pLCSDEV->bFrameBuffer, iLength ); // Trace the i/o if requested... if( pDEVBLK->ccwtrace || pDEVBLK->ccwstep ) { logmsg( _("HHCLC003I %4.4X: LCS Read:\n"), pDEVBLK->devnum ); packet_trace( pIOBuf, iLength ); } // Reset frame buffer to empty... // PROGRAMMING NOTE: even though not all available data // may have been read by the guest, we don't currently // support data-chaining. Thus any unread data is always // discarded by resetting both of the iFrameOffset and // fDataPending fields to 0 so that the next read always // grabs a new batch of LCS Frames starting at the very // beginning of our frame buffer again. (I was unable // to determine whether real LCS devices support data- // chaining or not, but if they do we should fix this). pLCSDEV->iFrameOffset = 0; pLCSDEV->fReplyPending = 0; pLCSDEV->fDataPending = 0; release_lock( &pLCSDEV->Lock ); return; } } // ==================================================================== // LCS_Write // ==================================================================== void LCS_Write( DEVBLK* pDEVBLK, U16 sCount, BYTE* pIOBuf, BYTE* pUnitStat, U16* pResidual ) { PLCSDEV pLCSDEV = (PLCSDEV)pDEVBLK->dev_data; PLCSHDR pLCSHDR = NULL; PLCSCMDHDR pCmdFrame = NULL; PLCSETHFRM pLCSEthFrame = NULL; PETHFRM pEthFrame = NULL; U16 iOffset = 0; U16 iPrevOffset = 0; U16 iLength = 0; U16 iEthLen = 0; UNREFERENCED( sCount ); // Process each frame in the buffer... while( 1 ) { // Fix-up the LCS header pointer to the current frame pLCSHDR = (PLCSHDR)( pIOBuf + iOffset ); // Save current offset so we can tell how big next frame is iPrevOffset = iOffset; // Get the next frame offset, exit loop if 0 FETCH_HW( iOffset, pLCSHDR->hwOffset ); if( iOffset == 0 ) // ("EOF") break; // Calculate size of this LCS Frame iLength = iOffset - iPrevOffset; switch( pLCSHDR->bType ) { case LCS_FRMTYP_CMD: // LCS Command Frame pCmdFrame = (PLCSCMDHDR)pLCSHDR; // Trace received command frame... if( pDEVBLK->ccwtrace || pDEVBLK->ccwstep ) { logmsg( _("HHCLC051I %4.4X: Cmd Packet...\n"), pDEVBLK->devnum ); packet_trace( (BYTE*)pCmdFrame, iLength ); } // FIXME: what is this all about? I'm not saying it's wrong, // only that we need to document via comments the purpose of // this test. What's it doing? Why ignore "initiator 1"? etc. // PLEASE EXPLAIN! -- Fish if( pCmdFrame->bInitiator == 0x01 ) break; switch( pCmdFrame->bCmdCode ) { case LCS_CMD_STARTUP: // Start Host if( pLCSDEV->pLCSBLK->fDebug ) logmsg( _("HHCLC043I %4.4X: Startup\n"),pDEVBLK->devnum); LCS_Startup( pLCSDEV, pCmdFrame ); break; case LCS_CMD_SHUTDOWN: // Shutdown Host if( pLCSDEV->pLCSBLK->fDebug ) logmsg( _("HHCLC044I %4.4X: Shutdown\n"),pDEVBLK->devnum); LCS_Shutdown( pLCSDEV, pCmdFrame ); break; case LCS_CMD_STRTLAN: // Start LAN if( pLCSDEV->pLCSBLK->fDebug ) logmsg( _("HHCLC045I %4.4X: Start LAN\n"),pDEVBLK->devnum); LCS_StartLan( pLCSDEV, pCmdFrame ); break; case LCS_CMD_STOPLAN: // Stop LAN if( pLCSDEV->pLCSBLK->fDebug ) logmsg( _("HHCLC046I %4.4X: Stop LAN\n"),pDEVBLK->devnum); LCS_StopLan( pLCSDEV, pCmdFrame ); break; case LCS_CMD_QIPASSIST: // Query IP Assists if( pLCSDEV->pLCSBLK->fDebug ) logmsg( _("HHCLC047I %4.4X: Query IP Assists\n"),pDEVBLK->devnum); LCS_QueryIPAssists( pLCSDEV, pCmdFrame ); break; case LCS_CMD_LANSTAT: // LAN Stats if( pLCSDEV->pLCSBLK->fDebug ) logmsg( _("HHCLC048I %4.4X: Statistics\n"),pDEVBLK->devnum); LCS_LanStats( pLCSDEV, pCmdFrame ); break; // ZZ FIXME: Once multicasting support is confirmed in tuntap // and/or TunTap32, we need to add support in Herc by handling // the below LCS_CMD_SETIPM and LCS_CMD_DELIPM frames and then // issuing an ioctl( SIOCADDMULTI ) to tuntap/TunTap32... case LCS_CMD_SETIPM: // Set IP Multicast case LCS_CMD_DELIPM: // Delete IP Multicast case LCS_CMD_GENSTAT: // General Stats case LCS_CMD_LISTLAN: // List LAN case LCS_CMD_LISTLAN2: // List LAN (another version) case LCS_CMD_TIMING: // Timing request default: LCS_DefaultCmdProc( pLCSDEV, pCmdFrame ); break; } // end switch( LCS Command Frame cmd code ) break; // end case LCS_FRMTYP_CMD case LCS_FRMTYP_ENET: // Ethernet Passthru case LCS_FRMTYP_TR: // Token Ring case LCS_FRMTYP_FDDI: // FDDI case LCS_FRMTYP_AUTO: // auto-detect pLCSEthFrame = (PLCSETHFRM)pLCSHDR; pEthFrame = (PETHFRM)pLCSEthFrame->bData; iEthLen = iLength - sizeof(LCSETHFRM); // Trace Ethernet frame before sending to TAP device if( pDEVBLK->ccwtrace || pDEVBLK->ccwstep ) { logmsg( _("HHCLC004I %4.4X: Sending packet to %s:\n"), pDEVBLK->devnum, pDEVBLK->filename ); packet_trace( (BYTE*)pEthFrame, iEthLen ); } // Write the Ethernet frame to the TAP device if( TUNTAP_Write( pDEVBLK->fd, (BYTE*)pEthFrame, iEthLen ) != iEthLen ) { logmsg( _("HHCLC005E %4.4X: Error writing to %s: %s\n"), pDEVBLK->devnum, pDEVBLK->filename, strerror( errno ) ); pDEVBLK->sense[0] = SENSE_EC; *pUnitStat = CSW_CE | CSW_DE | CSW_UC; return; } break; default: logmsg( _("HHCLC050E %4.4X: LCS_Write: Unsupported frame type 0x%2.2X\n"), pDEVBLK->devnum, pDEVBLK->filename ); ASSERT( FALSE ); pDEVBLK->sense[0] = SENSE_EC; *pUnitStat = CSW_CE | CSW_DE | CSW_UC; return; } // end switch( LCS Frame type ) } // end while (1) *pResidual = 0; *pUnitStat = CSW_CE | CSW_DE; if( pLCSDEV->fReplyPending ) { if( pDEVBLK->ccwtrace || pDEVBLK->ccwstep ) logmsg( _("HHCLC006I %4.4X Triggering Event.\n"), pDEVBLK->devnum ); obtain_lock( &pLCSDEV->EventLock ); signal_condition( &pLCSDEV->Event ); release_lock( &pLCSDEV->EventLock ); } } #if 0 // ==================================================================== // LCS_SDC // ==================================================================== void LCS_SDC( DEVBLK* pDEVBLK, BYTE bOpCode, U16 sCount, BYTE* pIOBuf, BYTE* UnitStat, U16* pResidual, BYTE* pMore ) { PLCSDEV pLCSDEV = (PLCSDEV)pDEVBLK->dev_data; PLCSBLK pLCSBLK = pLCSDEV->pLCSBLK; switch( bOpCode ) { case 0x72: // 0111010 RCD // ------------------------------------------------------------ // READ CONFIGURATION DATA // ------------------------------------------------------------ SDC_CreateNED( pIOBuf, 0, NED_EMULATION, NED_TYPE_DEV, NED_CLASS_CTCA, 0, "003088", "001", "", "", "", 0 ); SDC_CreateNED( pIOBuf, 1, NED_SERIAL_VALID, NED_TYPE_DEV, NED_CLASS_UNSPECIFIED, 0, "003172", "000", "HDG", "00", pLCSBLK->szSerialNumber, pLCSDEV->bPort ); SDC_CreateGeneralNEQ( pIOBuf, 2, 0, // Interface ID 60, // Timeout NULL ); // Extended Info SDC_CreateNED( pIOBuf, 3, NED_TOKEN | NED_SERIAL_UNIQUE, NED_TYPE_DEV, NED_CLASS_UNSPECIFIED, 0, "003172", "000", "HDG", "00", pLCSBLK->szSerialNumber, 0 ); break; case 0x82: // 10000010 SID // ------------------------------------------------------------ // SET INTERFACE IDENTIFER // ------------------------------------------------------------ break; case 0x83: // 10000011 RID // ------------------------------------------------------------ // READ NODE IDENTIFER // ------------------------------------------------------------ break; } } #endif // ==================================================================== // LCS_Startup // ==================================================================== static void LCS_Startup( PLCSDEV pLCSDEV, PLCSCMDHDR pCmdFrame ) { PLCSSTDFRM pStdCmdReplyFrame; PLCSSTRTFRM pStartupCmdFrame; PLCSPORT pLCSPORT; pLCSPORT = &pLCSDEV->pLCSBLK->Port[pLCSDEV->bPort]; // Get a pointer to the next available reply frame pStdCmdReplyFrame = (PLCSSTDFRM)LCS_InitReplyFrame( pLCSDEV, sizeof( LCSSTDFRM ), pCmdFrame ); // NOTE: pStdCmdReplyFrame now points to a reply frame // the first part of which is an LCSCMDHDR which, except for // the 'hwOffset' field, is an exact copy of the LCSCMDHDR // that was passed to us... pStdCmdReplyFrame->bLCSCmdHdr.bLanType = LCS_FRMTYP_ENET; pStdCmdReplyFrame->bLCSCmdHdr.bRelAdapterNo = pLCSDEV->bPort; pStartupCmdFrame = (PLCSSTRTFRM)pCmdFrame; // Save the max buffer size parameter FETCH_HW( pLCSDEV->iMaxFrameBufferSize, pStartupCmdFrame->hwBufferSize ); // Make sure it doesn't exceed our compiled maximum if (pLCSDEV->iMaxFrameBufferSize > sizeof(pLCSDEV->bFrameBuffer)) { logmsg( _("HHCLC049W %4.4X: LCS_Startup: Requested frame buffer size of 0x%4.4X " "larger than compiled size of 0x%4.4X; requested size ignored.\n"), pLCSDEV->pDEVBLK[1]->devnum, pLCSDEV->iMaxFrameBufferSize, sizeof( pLCSDEV->bFrameBuffer ) ); pLCSDEV->iMaxFrameBufferSize = sizeof(pLCSDEV->bFrameBuffer); } // Make sure it's not smaller than the compiled minimum size if (pLCSDEV->iMaxFrameBufferSize < CTC_MIN_FRAME_BUFFER_SIZE) { logmsg( _("HHCLC054W %4.4X: LCS_Startup: Requested frame buffer size of 0x%4.4X " "smaller than compiled minimum size of 0x%4.4X; requested size ignored.\n"), pLCSDEV->pDEVBLK[1]->devnum, pLCSDEV->iMaxFrameBufferSize, CTC_MIN_FRAME_BUFFER_SIZE ); pLCSDEV->iMaxFrameBufferSize = sizeof(pLCSDEV->bFrameBuffer); } VERIFY( TUNTAP_SetIPAddr( pLCSPORT->szNetDevName, "0.0.0.0" ) == 0 ); VERIFY( TUNTAP_SetMTU ( pLCSPORT->szNetDevName, "1500" ) == 0 ); #ifdef OPTION_TUNTAP_SETMACADDR if (pLCSPORT->fLocalMAC) { VERIFY( TUNTAP_SetMACAddr( pLCSPORT->szNetDevName, pLCSPORT->szMACAddress ) == 0 ); } #endif // OPTION_TUNTAP_SETMACADDR STORE_HW( pStdCmdReplyFrame->bLCSCmdHdr.hwReturnCode, 0x0000 ); pLCSDEV->fStarted = 1; } // ==================================================================== // LCS_Shutdown // ==================================================================== static void LCS_Shutdown( PLCSDEV pLCSDEV, PLCSCMDHDR pCmdFrame ) { PLCSSTDFRM pStdCmdReplyFrame; // Get a pointer to the next available reply frame pStdCmdReplyFrame = (PLCSSTDFRM)LCS_InitReplyFrame( pLCSDEV, sizeof( LCSSTDFRM ), pCmdFrame ); // NOTE: pStdCmdReplyFrame now points to a reply frame // the first part of which is an LCSCMDHDR which, except for // the 'hwOffset' field, is an exact copy of the LCSCMDHDR // that was passed to us... pStdCmdReplyFrame->bLCSCmdHdr.bLanType = LCS_FRMTYP_ENET; pStdCmdReplyFrame->bLCSCmdHdr.bRelAdapterNo = pLCSDEV->bPort; STORE_HW( pStdCmdReplyFrame->bLCSCmdHdr.hwReturnCode, 0x0000 ); pLCSDEV->fStarted = 0; } // ==================================================================== // LCS_StartLan // ==================================================================== static void LCS_StartLan( PLCSDEV pLCSDEV, PLCSCMDHDR pCmdFrame ) { PLCSPORT pLCSPORT; #ifdef OPTION_TUNTAP_DELADD_ROUTES PLCSRTE pLCSRTE; #endif // OPTION_TUNTAP_DELADD_ROUTES PLCSSTDFRM pStdCmdReplyFrame; int nIFFlags; pLCSPORT = &pLCSDEV->pLCSBLK->Port[pLCSDEV->bPort]; // Serialize access to eliminate ioctl errors obtain_lock( &pLCSPORT->Lock ); // Configure the TAP interface if used if( pLCSPORT->fUsed && pLCSPORT->fCreated && !pLCSPORT->fStarted ) { nIFFlags = // Interface flags 0 | IFF_UP // (interface is being enabled) | IFF_BROADCAST // (interface broadcast addr is valid) ; #if defined( TUNTAP_IFF_RUNNING_NEEDED ) nIFFlags |= // ADDITIONAL Interface flags 0 | IFF_RUNNING // (interface is ALSO operational) ; #endif /* defined( TUNTAP_IFF_RUNNING_NEEDED ) */ // Enable the interface by turning on the IFF_UP flag... VERIFY( TUNTAP_SetFlags( pLCSPORT->szNetDevName, nIFFlags ) == 0 ); #ifdef OPTION_TUNTAP_DELADD_ROUTES // Add any needed extra routing entries the // user may have specified in their OAT file // to the host's routing table... for( pLCSRTE = pLCSPORT->pRoutes; pLCSRTE; pLCSRTE = pLCSRTE->pNext ) { VERIFY( TUNTAP_AddRoute( pLCSPORT->szNetDevName, pLCSRTE->pszNetAddr, pLCSRTE->pszNetMask, NULL, RTF_UP ) == 0 ); } #endif // OPTION_TUNTAP_DELADD_ROUTES obtain_lock( &pLCSPORT->EventLock ); pLCSPORT->fStarted = 1; signal_condition( &pLCSPORT->Event ); release_lock( &pLCSPORT->EventLock ); usleep( 250*1000 ); } release_lock( &pLCSPORT->Lock ); #ifdef OPTION_TUNTAP_DELADD_ROUTES // Add a Point-To-Point routing entry to the // host's routing table for our interface... if( pLCSDEV->pszIPAddress ) { VERIFY( TUNTAP_AddRoute( pLCSPORT->szNetDevName, pLCSDEV->pszIPAddress, "255.255.255.255", NULL, RTF_UP | RTF_HOST ) == 0 ); } #endif // OPTION_TUNTAP_DELADD_ROUTES // Get a pointer to the next available reply frame pStdCmdReplyFrame = (PLCSSTDFRM)LCS_InitReplyFrame( pLCSDEV, sizeof( LCSSTDFRM ), pCmdFrame ); // NOTE: pStdCmdReplyFrame now points to a reply frame // the first part of which is an LCSCMDHDR which, except for // the 'hwOffset' field, is an exact copy of the LCSCMDHDR // that was passed to us... STORE_HW( pStdCmdReplyFrame->bLCSCmdHdr.hwReturnCode, 0 ); } // ==================================================================== // LCS_StopLan // ==================================================================== static void LCS_StopLan( PLCSDEV pLCSDEV, PLCSCMDHDR pCmdFrame ) { PLCSPORT pLCSPORT; PLCSSTDFRM pStdCmdReplyFrame; #ifdef OPTION_TUNTAP_DELADD_ROUTES PLCSRTE pLCSRTE; #endif // OPTION_TUNTAP_DELADD_ROUTES pLCSPORT = &pLCSDEV->pLCSBLK->Port[pLCSDEV->bPort]; // Serialize access to eliminate ioctl errors obtain_lock( &pLCSPORT->Lock ); obtain_lock( &pLCSPORT->EventLock ); pLCSPORT->fStarted = 0; signal_condition( &pLCSPORT->Event ); release_lock( &pLCSPORT->EventLock ); usleep( 250*1000 ); // Disable the interface by turning off the IFF_UP flag... VERIFY( TUNTAP_SetFlags( pLCSPORT->szNetDevName, 0 ) == 0 ); #ifdef OPTION_TUNTAP_DELADD_ROUTES // Remove routing entries from host's routing table... // First, remove the Point-To-Point routing entry // we added when we brought the interface IFF_UP... if( pLCSDEV->pszIPAddress ) { VERIFY( TUNTAP_DelRoute( pLCSPORT->szNetDevName, pLCSDEV->pszIPAddress, "255.255.255.255", NULL, RTF_HOST ) == 0 ); } // Next, remove any extra routing entries // (specified by the user in their OAT file) // that we may have also added... for( pLCSRTE = pLCSPORT->pRoutes; pLCSRTE; pLCSRTE = pLCSRTE->pNext ) { VERIFY( TUNTAP_DelRoute( pLCSPORT->szNetDevName, pLCSRTE->pszNetAddr, pLCSRTE->pszNetMask, NULL, RTF_UP ) == 0 ); } #endif // OPTION_TUNTAP_DELADD_ROUTES release_lock( &pLCSPORT->Lock ); // FIXME: Really need to iterate through the devices and close // the TAP interface if all devices have been stopped. // Get a pointer to the next available reply frame pStdCmdReplyFrame = (PLCSSTDFRM)LCS_InitReplyFrame( pLCSDEV, sizeof( LCSSTDFRM ), pCmdFrame ); // NOTE: pStdCmdReplyFrame now points to a reply frame // the first part of which is an LCSCMDHDR which, except for // the 'hwOffset' field, is an exact copy of the LCSCMDHDR // that was passed to us... STORE_HW( pStdCmdReplyFrame->bLCSCmdHdr.hwReturnCode, 0 ); } // ==================================================================== // LCS_QueryIPAssists // ==================================================================== static void LCS_QueryIPAssists( PLCSDEV pLCSDEV, PLCSCMDHDR pCmdFrame ) { PLCSPORT pLCSPORT; PLCSQIPFRM pStdCmdReplyFrame; pLCSPORT = &pLCSDEV->pLCSBLK->Port[pLCSDEV->bPort]; // Get a pointer to the next available reply frame pStdCmdReplyFrame = (PLCSQIPFRM)LCS_InitReplyFrame( pLCSDEV, sizeof( LCSQIPFRM ), pCmdFrame ); // NOTE: pStdCmdReplyFrame now points to a reply frame // the first part of which is an LCSCMDHDR which, except for // the 'hwOffset' field, is an exact copy of the LCSCMDHDR // that was passed to us... #if defined( WIN32 ) // FIXME: TunTap32 *does* support TCP/IP checksum offloading // (for both inbound and outbound packets), but Microsoft's // latest NDIS 6.0 release has broken it, so until I can get // it straightened out we can't support it. Sorry! -- Fish // The other assists however, TunTap32 does not yet support. pLCSPORT->sIPAssistsSupported = 0 // | LCS_INBOUND_CHECKSUM_SUPPORT // | LCS_OUTBOUND_CHECKSUM_SUPPORT // | LCS_ARP_PROCESSING // | LCS_IP_FRAG_REASSEMBLY // | LCS_IP_FILTERING // | LCS_IP_V6_SUPPORT // | LCS_MULTICAST_SUPPORT ; pLCSPORT->sIPAssistsEnabled = 0 // | LCS_INBOUND_CHECKSUM_SUPPORT // | LCS_OUTBOUND_CHECKSUM_SUPPORT // | LCS_ARP_PROCESSING // | LCS_IP_FRAG_REASSEMBLY // | LCS_IP_FILTERING // | LCS_IP_V6_SUPPORT // | LCS_MULTICAST_SUPPORT ; #else // !WIN32 (Linux, Apple, etc) // Linux/Apple/etc 'tuntap' driver DOES support // certain types of assists?? (task offloading) pLCSPORT->sIPAssistsSupported = 0 // | LCS_INBOUND_CHECKSUM_SUPPORT // | LCS_OUTBOUND_CHECKSUM_SUPPORT // | LCS_ARP_PROCESSING | LCS_IP_FRAG_REASSEMBLY // | LCS_IP_FILTERING // | LCS_IP_V6_SUPPORT | LCS_MULTICAST_SUPPORT ; pLCSPORT->sIPAssistsEnabled = 0 // | LCS_INBOUND_CHECKSUM_SUPPORT // | LCS_OUTBOUND_CHECKSUM_SUPPORT // | LCS_ARP_PROCESSING | LCS_IP_FRAG_REASSEMBLY // | LCS_IP_FILTERING // | LCS_IP_V6_SUPPORT | LCS_MULTICAST_SUPPORT ; #endif // WIN32 STORE_HW( pStdCmdReplyFrame->hwNumIPPairs, 0x0000 ); STORE_HW( pStdCmdReplyFrame->hwIPAssistsSupported, pLCSPORT->sIPAssistsSupported ); STORE_HW( pStdCmdReplyFrame->hwIPAssistsEnabled, pLCSPORT->sIPAssistsEnabled ); STORE_HW( pStdCmdReplyFrame->hwIPVersion, 0x0004 ); } // ==================================================================== // LCS_LanStats // ==================================================================== static void LCS_LanStats( PLCSDEV pLCSDEV, PLCSCMDHDR pCmdFrame ) { PLCSPORT pLCSPORT; PLCSLSTFRM pStdCmdReplyFrame; int fd; struct ifreq ifr; BYTE* pPortMAC; BYTE* pIFaceMAC; pLCSPORT = &pLCSDEV->pLCSBLK->Port[pLCSDEV->bPort]; // Get a pointer to the next available reply frame pStdCmdReplyFrame = (PLCSLSTFRM)LCS_InitReplyFrame( pLCSDEV, sizeof( LCSLSTFRM ), pCmdFrame ); // NOTE: pStdCmdReplyFrame now points to a reply frame // the first part of which is an LCSCMDHDR which, except for // the 'hwOffset' field, is an exact copy of the LCSCMDHDR // that was passed to us... STORE_HW( pStdCmdReplyFrame->bLCSCmdHdr.hwReturnCode, 0x0000 ); fd = socket( AF_INET, SOCK_STREAM, IPPROTO_IP ); if( fd == -1 ) { logmsg( _("HHCLC007E Error in call to socket: %s.\n"), strerror( HSO_errno ) ); // FIXME: we should probably be returning a non-zero hwReturnCode // STORE_HW( pStdCmdReplyFrame->bLCSCmdHdr.hwReturnCode, 0x0001 ); return; } memset( &ifr, 0, sizeof( ifr ) ); strcpy( ifr.ifr_name, pLCSPORT->szNetDevName ); pPortMAC = (BYTE*) &pLCSPORT->MAC_Address; /* Not all systems can return the hardware address of an interface. */ #if defined(SIOCGIFHWADDR) if( TUNTAP_IOCtl( fd, SIOCGIFHWADDR, (char*)&ifr ) != 0 ) { logmsg( _("HHCLC008E ioctl error on device %s: %s.\n"), pLCSPORT->szNetDevName, strerror( errno ) ); // FIXME: we should probably be returning a non-zero hwReturnCode // STORE_HW( pStdCmdReplyFrame->bLCSCmdHdr.hwReturnCode, 0x0002 ); return; } pIFaceMAC = (BYTE*) ifr.ifr_hwaddr.sa_data; #else // !defined(SIOCGIFHWADDR) pIFaceMAC = pPortMAC; #endif // defined(SIOCGIFHWADDR) /* Report what MAC address we will really be using */ logmsg( _("HHCLC055I %s using MAC %2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X\n"), pLCSPORT->szNetDevName, *(pIFaceMAC+0),*(pIFaceMAC+1), *(pIFaceMAC+2),*(pIFaceMAC+3), *(pIFaceMAC+4),*(pIFaceMAC+5)); /* Issue warning if different from specified value */ if (memcmp( pPortMAC, pIFaceMAC, IFHWADDRLEN ) != 0) { logmsg( _("HHCLC056W %s NOT using MAC %2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X\n"), pLCSPORT->szNetDevName, *(pPortMAC+0),*(pPortMAC+1), *(pPortMAC+2),*(pPortMAC+3), *(pPortMAC+4),*(pPortMAC+5)); memcpy( pPortMAC, pIFaceMAC, IFHWADDRLEN ); snprintf(pLCSPORT->szMACAddress, sizeof(pLCSPORT->szMACAddress), "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X", *(pPortMAC+0), *(pPortMAC+1), *(pPortMAC+2), *(pPortMAC+3), *(pPortMAC+4), *(pPortMAC+5)); } memcpy( pStdCmdReplyFrame->MAC_Address, pIFaceMAC, IFHWADDRLEN ); // FIXME: Really should read /proc/net/dev to retrieve actual stats } // ==================================================================== // LCS_DefaultCmdProc // ==================================================================== static void LCS_DefaultCmdProc( PLCSDEV pLCSDEV, PLCSCMDHDR pCmdFrame ) { PLCSSTDFRM pStdCmdReplyFrame; // Get a pointer to the next available reply frame pStdCmdReplyFrame = (PLCSSTDFRM)LCS_InitReplyFrame( pLCSDEV, sizeof( LCSSTDFRM ), pCmdFrame ); // NOTE: pStdCmdReplyFrame now points to a reply frame // the first part of which is an LCSCMDHDR which, except for // the 'hwOffset' field, is an exact copy of the LCSCMDHDR // that was passed to us... pStdCmdReplyFrame->bLCSCmdHdr.bLanType = LCS_FRMTYP_ENET; pStdCmdReplyFrame->bLCSCmdHdr.bRelAdapterNo = pLCSDEV->bPort; STORE_HW( pStdCmdReplyFrame->bLCSCmdHdr.hwReturnCode, 0x0000 ); } // ==================================================================== // LCS_PortThread // ==================================================================== static void* LCS_PortThread( PLCSPORT pLCSPORT ) { PLCSDEV pLCSDev; PLCSDEV pPrimaryLCSDEV; PLCSDEV pSecondaryLCSDEV; PLCSDEV pMatchingLCSDEV; PLCSRTE pLCSRTE; PETHFRM pEthFrame; PIP4FRM pIPFrame = NULL; PARPFRM pARPFrame = NULL; int iLength; U16 hwEthernetType; U32 lIPAddress; // (network byte order) BYTE* pMAC; BYTE szBuff[2048]; char bReported = 0; pLCSPORT->pid = getpid(); for (;;) { obtain_lock( &pLCSPORT->EventLock ); { // Don't read unless/until port is enabled... while (1 && !(pLCSPORT->fd < 0) && !pLCSPORT->fCloseInProgress && !pLCSPORT->fStarted ) { timed_wait_condition_relative_usecs ( &pLCSPORT->Event, // ptr to condition to wait on &pLCSPORT->EventLock, // ptr to controlling lock (must be held!) 250*1000, // max #of microseconds to wait NULL // [OPTIONAL] ptr to tod value (may be NULL) ); } } release_lock( &pLCSPORT->EventLock ); // Exit when told... if ( pLCSPORT->fd < 0 || pLCSPORT->fCloseInProgress ) break; // Read an IP packet from the TAP device iLength = TUNTAP_Read( pLCSPORT->fd, szBuff, sizeof( szBuff ) ); if( iLength == 0 ) // (probably EINTR; ignore) continue; // Check for other error condition if( iLength < 0 ) { if( pLCSPORT->fd < 0 || pLCSPORT->fCloseInProgress ) break; logmsg( _("HHCLC042E Port %2.2X: Read error: %s\n"), pLCSPORT->bPort, strerror( errno ) ); SLEEP(1); // (purposeful long delay) continue; } if( pLCSPORT->pLCSBLK->fDebug ) { // Trace the frame logmsg( _("HHCLC009I Port %2.2X: Read Buffer:\n"), pLCSPORT->bPort ); packet_trace( szBuff, iLength ); bReported = 0; } pEthFrame = (PETHFRM)szBuff; FETCH_HW( hwEthernetType, pEthFrame->hwEthernetType ); // Housekeeping pPrimaryLCSDEV = NULL; pSecondaryLCSDEV = NULL; pMatchingLCSDEV = NULL; // Attempt to find the device that this frame belongs to for( pLCSDev = pLCSPORT->pLCSBLK->pDevices; pLCSDev; pLCSDev = pLCSDev->pNext ) { // Only process devices that are on this port if( pLCSDev->bPort == pLCSPORT->bPort ) { if( hwEthernetType == ETH_TYPE_IP ) { pIPFrame = (PIP4FRM)pEthFrame->bData; lIPAddress = pIPFrame->lDstIP; // (network byte order) if( pLCSPORT->pLCSBLK->fDebug && !bReported ) { logmsg( _("HHCLC010I Port %2.2X: " "IPV4 frame for %8.8X\n"), pLCSPORT->bPort, ntohl(lIPAddress) ); bReported = 1; } // If this is an exact match use it // otherwise look for primary and secondary // default devices if( pLCSDev->lIPAddress == lIPAddress ) { pMatchingLCSDEV = pLCSDev; break; } else if( pLCSDev->bType == LCSDEV_TYPE_PRIMARY ) pPrimaryLCSDEV = pLCSDev; else if( pLCSDev->bType == LCSDEV_TYPE_SECONDARY ) pSecondaryLCSDEV = pLCSDev; } else if( hwEthernetType == ETH_TYPE_ARP ) { pARPFrame = (PARPFRM)pEthFrame->bData; lIPAddress = pARPFrame->lTargIPAddr; // (network byte order) if( pLCSPORT->pLCSBLK->fDebug && !bReported ) { logmsg( _("HHCLC011I Port %2.2X: " "ARP frame for %8.8X\n"), pLCSPORT->bPort, ntohl(lIPAddress) ); bReported = 1; } // If this is an exact match use it // otherwise look for primary and secondary // default devices if( pLCSDev->lIPAddress == lIPAddress ) { pMatchingLCSDEV = pLCSDev; break; } else if( pLCSDev->bType == LCSDEV_TYPE_PRIMARY ) pPrimaryLCSDEV = pLCSDev; else if( pLCSDev->bType == LCSDEV_TYPE_SECONDARY ) pSecondaryLCSDEV = pLCSDev; } else if( hwEthernetType == ETH_TYPE_RARP ) { pARPFrame = (PARPFRM)pEthFrame->bData; pMAC = pARPFrame->bTargEthAddr; if( pLCSPORT->pLCSBLK->fDebug && !bReported ) { logmsg ( _("HHCLC011I Port %2.2X: RARP frame for " "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X\n") ,pLCSPORT->bPort ,*(pMAC+0) ,*(pMAC+1) ,*(pMAC+2) ,*(pMAC+3) ,*(pMAC+4) ,*(pMAC+5) ); bReported = 1; } // If this is an exact match use it // otherwise look for primary and secondary // default devices if( memcmp( pMAC, pLCSPORT->MAC_Address, IFHWADDRLEN ) == 0 ) { pMatchingLCSDEV = pLCSDev; break; } else if( pLCSDev->bType == LCSDEV_TYPE_PRIMARY ) pPrimaryLCSDEV = pLCSDev; else if( pLCSDev->bType == LCSDEV_TYPE_SECONDARY ) pSecondaryLCSDEV = pLCSDev; } else if( hwEthernetType == ETH_TYPE_SNA ) { if( pLCSPORT->pLCSBLK->fDebug && !bReported ) { logmsg( _("HHCLC012I Port %2.2X: SNA frame\n"), pLCSPORT->bPort ); bReported = 1; } if( pLCSDev->bMode == LCSDEV_MODE_SNA ) { pMatchingLCSDEV = pLCSDev; break; } } } } // If the matching device is not started // nullify the pointer and pass frame to one // of the defaults if present if( pMatchingLCSDEV && !pMatchingLCSDEV->fStarted ) pMatchingLCSDEV = NULL; // Match not found, check for default devices // If one is defined and started, use it if( !pMatchingLCSDEV ) { if( pPrimaryLCSDEV && pPrimaryLCSDEV->fStarted ) { pMatchingLCSDEV = pPrimaryLCSDEV; if( pLCSPORT->pLCSBLK->fDebug ) logmsg( _("HHCLC013I Port %2.2X: " "No match found - " "selecting primary %4.4X\n"), pLCSPORT->bPort, pMatchingLCSDEV->sAddr ); } else if( pSecondaryLCSDEV && pSecondaryLCSDEV->fStarted ) { pMatchingLCSDEV = pSecondaryLCSDEV; if( pLCSPORT->pLCSBLK->fDebug ) logmsg( _("HHCLC014I Port %2.2X: " "No match found - " "selecting secondary %4.4X\n"), pLCSPORT->bPort, pMatchingLCSDEV->sAddr ); } } // No match found, discard frame if( !pMatchingLCSDEV ) { if( pLCSPORT->pLCSBLK->fDebug ) logmsg( _("HHCLC015I Port %2.2X: " "No match found - Discarding frame\n"), pLCSPORT->bPort ); continue; } if( pLCSPORT->pLCSBLK->fDebug ) logmsg( _("HHCLC016I Port %2.2X: " "Enqueing frame to device %4.4X (%8.8X)\n"), pLCSPORT->bPort, pMatchingLCSDEV->sAddr, ntohl(pMatchingLCSDEV->lIPAddress) ); // Match was found. // Enqueue frame on buffer, if buffer is full, keep trying while( LCS_EnqueueEthFrame( pMatchingLCSDEV, pLCSPORT->bPort, szBuff, iLength ) < 0 && pLCSPORT->fd != -1 && !pLCSPORT->fCloseInProgress ) { if (EMSGSIZE == errno) { if( pLCSPORT->pLCSBLK->fDebug ) logmsg( _("HHCLC041W Port %2.2X: " "Frame too big; discarded.\n"), pLCSPORT->bPort ); break; } ASSERT( ENOBUFS == errno ); usleep( CTC_DELAY_USECS ); } } // end for(;;) // We must do the close since we were the one doing the i/o... VERIFY( pLCSPORT->fd == -1 || TUNTAP_Close( pLCSPORT->fd ) == 0 ); // Housekeeping - Cleanup Port Block memset( pLCSPORT->MAC_Address, 0, sizeof( MAC ) ); memset( pLCSPORT->szNetDevName, 0, IFNAMSIZ ); memset( pLCSPORT->szMACAddress, 0, 32 ); for( pLCSRTE = pLCSPORT->pRoutes; pLCSRTE; pLCSRTE = pLCSPORT->pRoutes ) { pLCSPORT->pRoutes = pLCSRTE->pNext; free( pLCSRTE ); pLCSRTE = NULL; } pLCSPORT->sIPAssistsSupported = 0; pLCSPORT->sIPAssistsEnabled = 0; pLCSPORT->fUsed = 0; pLCSPORT->fLocalMAC = 0; pLCSPORT->fCreated = 0; pLCSPORT->fStarted = 0; pLCSPORT->fRouteAdded = 0; pLCSPORT->fd = -1; return NULL; } // end of LCS_PortThread // ==================================================================== // LCS_EnqueueEthFrame // ==================================================================== // // Places the provided ethernet frame in the next available frame // slot in the adapter buffer. // // pData points the the Ethernet packet just received // iSize is the size of the Ethernet packet // // Returns: // // 0 == Success // -1 == Failure; errno = ENOBUFS: No buffer space available // EMSGSIZE: Message too long // // -------------------------------------------------------------------- static int LCS_EnqueueEthFrame( PLCSDEV pLCSDEV, BYTE bPort, BYTE* pData, size_t iSize ) { PLCSETHFRM pLCSEthFrame; // Will frame NEVER fit into buffer?? if( iSize > MAX_LCS_ETH_FRAME_SIZE( pLCSDEV ) ) { errno = EMSGSIZE; // Message too long return -1; // (-1==failure) } obtain_lock( &pLCSDEV->Lock ); // Ensure we dont overflow the buffer if( ( pLCSDEV->iFrameOffset + // Current buffer Offset sizeof( LCSETHFRM ) + // Size of Frame Header iSize + // Size of Ethernet packet sizeof(pLCSEthFrame->bLCSHdr.hwOffset) ) // Size of Frame terminator > pLCSDEV->iMaxFrameBufferSize ) // Size of Frame buffer { release_lock( &pLCSDEV->Lock ); errno = ENOBUFS; // No buffer space available return -1; // (-1==failure) } // Point to next available LCS Frame slot in our buffer pLCSEthFrame = (PLCSETHFRM)( pLCSDEV->bFrameBuffer + pLCSDEV->iFrameOffset ); // Increment offset to NEXT available slot (after ours) pLCSDEV->iFrameOffset += sizeof(LCSETHFRM) + iSize; // Plug updated offset to next frame into our frame header STORE_HW( pLCSEthFrame->bLCSHdr.hwOffset, pLCSDEV->iFrameOffset ); // Finish building the LCS Ethernet Passthru frame header pLCSEthFrame->bLCSHdr.bType = LCS_FRMTYP_ENET; pLCSEthFrame->bLCSHdr.bSlot = bPort; // Copy Ethernet packet to LCS Ethernet Passthru frame memcpy( pLCSEthFrame->bData, pData, iSize ); // Tell "LCS_Read" function that data is available for reading pLCSDEV->fDataPending = 1; release_lock( &pLCSDEV->Lock ); // (wake up "LCS_Read" function) obtain_lock( &pLCSDEV->EventLock ); signal_condition( &pLCSDEV->Event ); release_lock( &pLCSDEV->EventLock ); return 0; // (success) } // ==================================================================== // LCS_InitReplyFrame // ==================================================================== // // Returns a pointer to the next available frame slot of iSize bytes // of type LCSCMDHDR (i.e. the partially pre-initialized reply frame) // // As a part of frame setup, initializes the reply frame with basic // information that is provided in the original frame for which this // is a reply frame for. Note that only Command frames have replies. // // -------------------------------------------------------------------- static void* LCS_InitReplyFrame( PLCSDEV pLCSDEV, size_t iSize, PLCSCMDHDR pCmdFrame ) { PLCSCMDHDR pReplyCmdFrame; obtain_lock( &pLCSDEV->Lock ); // Point to next available LCS Frame slot in our buffer... pReplyCmdFrame = (PLCSCMDHDR)( pLCSDEV->bFrameBuffer + pLCSDEV->iFrameOffset ); // Increment buffer offset to NEXT next-available-slot... pLCSDEV->iFrameOffset += iSize; // Initialize our Reply LCS Command Frame... memset( pReplyCmdFrame, 0, iSize ); // Use the LCS Command Frame header that was passed to us // as a template for the Reply LCS Command Frame we're to // build... memcpy( pReplyCmdFrame, pCmdFrame, sizeof( LCSCMDHDR ) ); // Store offset of next frame STORE_HW( pReplyCmdFrame->bLCSHdr.hwOffset, pLCSDEV->iFrameOffset ); // Mark reply pending pLCSDEV->fReplyPending = 1; release_lock( &pLCSDEV->Lock ); return pReplyCmdFrame; } // ==================================================================== // ParseArgs // ==================================================================== int ParseArgs( DEVBLK* pDEVBLK, PLCSBLK pLCSBLK, int argc, char** argv ) { struct in_addr addr; // Work area for addresses MAC mac; int i; #if defined(OPTION_W32_CTCI) int iKernBuff; int iIOBuff; #endif // Housekeeping memset( &addr, 0, sizeof( struct in_addr ) ); // Set some initial defaults #if defined( WIN32 ) pLCSBLK->pszTUNDevice = strdup( tt32_get_default_iface() ); #else pLCSBLK->pszTUNDevice = strdup( HERCTUN_DEV ); #endif pLCSBLK->pszOATFilename = NULL; pLCSBLK->pszIPAddress = NULL; pLCSBLK->pszMACAddress = NULL; #if defined( OPTION_W32_CTCI ) pLCSBLK->iKernBuff = DEF_CAPTURE_BUFFSIZE; pLCSBLK->iIOBuff = DEF_PACKET_BUFFSIZE; #endif // Initialize getopt's counter. This is necessary in the case // that getopt was used previously for another device. optind = 0; // Build new argv list. // getopt_long used to work on old format configuration statements // because LCS was the first argument passed to the device // initialization routine (and was interpreted by getopt* // as the program name and ignored). Now that argv[0] is a valid // argument, we need to shift the arguments and insert a dummy // argv[0]; // Don't allow us to exceed the allocated storage (sanity check) if( argc > (MAX_ARGS-1)) argc = (MAX_ARGS-1); for( i = argc; i > 0; i-- ) argv[i] = argv[i - 1]; argc++; argv[0] = pDEVBLK->typname; // Parse the optional arguments OPTRESET(); optind=0; while( 1 ) { int c; #if defined(HAVE_GETOPT_LONG) int iOpt; static struct option options[] = { { "dev", 1, NULL, 'n' }, #if defined(OPTION_W32_CTCI) { "kbuff", 1, NULL, 'k' }, { "ibuff", 1, NULL, 'i' }, #endif { "oat", 1, NULL, 'o' }, { "mac", 1, NULL, 'm' }, { "debug", 0, NULL, 'd' }, { NULL, 0, NULL, 0 } }; c = getopt_long( argc, argv, "n" #if defined( OPTION_W32_CTCI ) ":k:i" #endif ":o:m:d", options, &iOpt ); #else /* defined(HAVE_GETOPT_LONG) */ c = getopt( argc, argv, "n" #if defined( OPTION_W32_CTCI ) ":k:i" #endif ":o:m:d" ); #endif /* defined(HAVE_GETOPT_LONG) */ if( c == -1 ) break; switch( c ) { case 'n': if( strlen( optarg ) > sizeof( pDEVBLK->filename ) - 1 ) { logmsg( _("HHCLC017E %4.4X invalid device name %s\n"), pDEVBLK->devnum, optarg ); return -1; } pLCSBLK->pszTUNDevice = strdup( optarg ); break; #if defined( OPTION_W32_CTCI ) case 'k': // Kernel Buffer Size (Windows only) iKernBuff = atoi( optarg ); if( iKernBuff * 1024 < MIN_CAPTURE_BUFFSIZE || iKernBuff * 1024 > MAX_CAPTURE_BUFFSIZE ) { logmsg( _("HHCLC052E %4.4X: Invalid kernel buffer size %s\n"), pDEVBLK->devnum, optarg ); return -1; } pLCSBLK->iKernBuff = iKernBuff * 1024; break; case 'i': // I/O Buffer Size (Windows only) iIOBuff = atoi( optarg ); if( iIOBuff * 1024 < MIN_PACKET_BUFFSIZE || iIOBuff * 1024 > MAX_PACKET_BUFFSIZE ) { logmsg( _("HHCLC053E %4.4X: Invalid DLL I/O buffer size %s\n"), pDEVBLK->devnum, optarg ); return -1; } pLCSBLK->iIOBuff = iIOBuff * 1024; break; #endif // defined( OPTION_W32_CTCI ) case 'o': pLCSBLK->pszOATFilename = strdup( optarg ); break; case 'm': if( ParseMAC( optarg, mac ) != 0 ) { logmsg( _("HHCLC018E %4.4X invalid MAC address %s\n"), pDEVBLK->devnum, optarg ); return -1; } strcpy( pLCSBLK->Port[0].szMACAddress, optarg ); pLCSBLK->Port[0].fLocalMAC = TRUE; break; case 'd': pLCSBLK->fDebug = TRUE; break; default: break; } } argc -= optind; argv += optind; if( argc > 1 ) { logmsg( _("HHCLC019E %4.4X too many arguments in statement.\n"), pDEVBLK->devnum ); return -1; } // If an argument is left, it is the optional IP Address if( argc ) { if( inet_aton( *argv, &addr ) == 0 ) { logmsg( _("HHCLC020E %4.4X invalid IP address %s\n"), pDEVBLK->devnum, *argv ); return -1; } if ( pLCSBLK->pszIPAddress ) { free( pLCSBLK->pszIPAddress ); pLCSBLK->pszIPAddress = NULL; } pLCSBLK->pszIPAddress = strdup( *argv ); } return 0; } // ==================================================================== // BuildOAT // ==================================================================== static int BuildOAT( char* pszOATName, PLCSBLK pLCSBLK ) { FILE* fp; char szBuff[255]; int i; char c; // Character work area char* pszStatement = NULL; // -> Resolved statement char* pszKeyword; // -> Statement keyword char* pszOperand; // -> Statement operand int argc; // Number of args char* argv[MAX_ARGS]; // Argument array PLCSPORT pLCSPORT; PLCSDEV pLCSDev; PLCSRTE pLCSRTE; U16 sPort; BYTE bMode; U16 sDevNum; BYTE bType; U32 lIPAddr = 0; // (network byte order) char* pszIPAddress = NULL; char* pszNetAddr = NULL; char* pszNetMask = NULL; struct in_addr addr; // Work area for addresses char pathname[MAX_PATH]; // pszOATName in host path format // Open the configuration file hostpath(pathname, pszOATName, sizeof(pathname)); fp = fopen( pathname, "r" ); if( !fp ) { logmsg( _("HHCLC039E Cannot open file %s: %s\n"), pszOATName, strerror( errno ) ); return -1; } for(;;) { // Read next record from the OAT file if( !ReadOAT( pszOATName, fp, szBuff ) ) { return 0; } if( pszStatement ) { free( pszStatement ); pszStatement = NULL; } #if defined(OPTION_CONFIG_SYMBOLS) // Make a copy of the OAT statement with symbols resolved pszStatement = resolve_symbol_string( szBuff ); #else // Make a copy of the OAT statement pszStatement = strdup( szBuff ); #endif sPort = 0; bMode = 0; sDevNum = 0; bType = 0; pszIPAddress = NULL; pszNetAddr = NULL; pszNetMask = NULL; memset( &addr, 0, sizeof( addr ) ); // Split the statement into keyword and first operand pszKeyword = strtok( pszStatement, " \t" ); pszOperand = strtok( NULL, " \t" ); // Extract any arguments for( argc = 0; argc < MAX_ARGS && ( argv[argc] = strtok( NULL, " \t" ) ) != NULL && argv[argc][0] != '#'; argc++ ); // Clear any unused argument pointers for( i = argc; i < MAX_ARGS; i++ ) argv[i] = NULL; if( strcasecmp( pszKeyword, "HWADD" ) == 0 ) { if( !pszOperand || argc != 1 || sscanf( pszOperand, "%hi%c", &sPort, &c ) != 1 ) { logmsg( _("HHCLC021E Invalid HWADD statement in %s: %s\n"), pszOATName, szBuff ); return -1; } pLCSPORT = &pLCSBLK->Port[sPort]; if( ParseMAC( argv[0], pLCSPORT->MAC_Address ) != 0 ) { logmsg( _("HHCLC022E Invalid MAC in HWADD statement " "in %s: %s (%s)\n "), pszOATName, szBuff, argv[0] ); memset( pLCSPORT->MAC_Address, 0, sizeof(MAC) ); return -1; } strcpy( pLCSPORT->szMACAddress, argv[0] ); pLCSPORT->fLocalMAC = TRUE; } else if( strcasecmp( pszKeyword, "ROUTE" ) == 0 ) { if( !pszOperand || argc != 2 || sscanf( pszOperand, "%hi%c", &sPort, &c ) != 1 ) { logmsg( _("HHCLC023E Invalid ROUTE statement in %s: %s\n"), pszOATName, szBuff ); return -1; } if( inet_aton( argv[0], &addr ) == 0 ) { logmsg( _("HHCLC024E Invalid net address in ROUTE %s: %s (%s)\n"), pszOATName, szBuff, argv[0] ); return -1; } pszNetAddr = strdup( argv[0] ); if( inet_aton( argv[1], &addr ) == 0 ) { free(pszNetAddr); logmsg( _("HHCLC025E Invalid net mask in ROUTE %s: %s (%s)\n"), pszOATName, szBuff, argv[1] ); return -1; } pszNetMask = strdup( argv[1] ); pLCSPORT = &pLCSBLK->Port[sPort]; if( !pLCSPORT->pRoutes ) { pLCSPORT->pRoutes = malloc( sizeof( LCSRTE ) ); pLCSRTE = pLCSPORT->pRoutes; } else { for( pLCSRTE = pLCSPORT->pRoutes; pLCSRTE->pNext; pLCSRTE = pLCSRTE->pNext ); pLCSRTE->pNext = malloc( sizeof( LCSRTE ) ); pLCSRTE = pLCSRTE->pNext; } pLCSRTE->pszNetAddr = pszNetAddr; pLCSRTE->pszNetMask = pszNetMask; pLCSRTE->pNext = NULL; } else // (presumed OAT file device statement) { if( !pszKeyword || !pszOperand ) { logmsg( _("HHCLC026E Error in %s: " "Missing device number or mode\n"), pszOATName ); return -1; } if( strlen( pszKeyword ) > 4 || sscanf( pszKeyword, "%hx%c", &sDevNum, &c ) != 1 ) { logmsg( _("HHCLC027E Error in %s: %s: " "Invalid device number\n"), pszOATName, pszKeyword ); return -1; } if( strcasecmp( pszOperand, "IP" ) == 0 ) { bMode = LCSDEV_MODE_IP; if( argc < 1 ) { logmsg( _("HHCLC028E Error in %s: %s:" "Missing PORT number\n"), pszOATName, szBuff ); return -1; } if( sscanf( argv[0], "%hi%c", &sPort, &c ) != 1 ) { logmsg( _("HHCLC029E Error in %s: %s: " "Invalid PORT number\n"), pszOATName, argv[0] ); return -1; } if( argc > 1 ) { if( strcasecmp( argv[1], "PRI" ) == 0 ) bType = LCSDEV_TYPE_PRIMARY; else if( strcasecmp( argv[1], "SEC" ) == 0 ) bType = LCSDEV_TYPE_SECONDARY; else if( strcasecmp( argv[1], "NO" ) == 0 ) bType = LCSDEV_TYPE_NONE; else { logmsg( _("HHCLC031E Error in %s: %s: " "Invalid entry starting at %s\n"), pszOATName, szBuff, argv[1] ); return -1; } if( argc > 2 ) { pszIPAddress = strdup( argv[2] ); if( inet_aton( pszIPAddress, &addr ) == 0 ) { logmsg( _("HHCLC032E Error in %s: %s: " "Invalid IP address (%s)\n"), pszOATName, szBuff, pszIPAddress ); return -1; } lIPAddr = addr.s_addr; // (network byte order) } } } else if( strcasecmp( pszOperand, "SNA" ) == 0 ) { bMode = LCSDEV_MODE_SNA; if( argc < 1 ) { logmsg( _("HHCLC033E Error in %s: %s: " "Missing PORT number\n"), pszOATName, szBuff ); return -1; } if( sscanf( argv[0], "%hi%c", &sPort, &c ) != 1 ) { logmsg( _("HHCLC034E Error in %s: %s:" "Invalid PORT number\n"), pszOATName, argv[0] ); return -1; } if( argc > 1 ) { logmsg( _("HHCLC035E Error in %s: %s: " "SNA does not accept any arguments\n"), pszOATName, szBuff ); return -1; } } else { logmsg( _("HHCLC036E Error in %s: %s: " "Invalid MODE\n"), pszOATName, pszOperand ); return -1; } // Create new LCS Device... pLCSDev = malloc( sizeof( LCSDEV ) ); memset( pLCSDev, 0, sizeof( LCSDEV ) ); pLCSDev->sAddr = sDevNum; pLCSDev->bMode = bMode; pLCSDev->bPort = sPort; pLCSDev->bType = bType; pLCSDev->lIPAddress = lIPAddr; // (network byte order) pLCSDev->pszIPAddress = pszIPAddress; pLCSDev->pNext = NULL; // Add it to end of chain... if( !pLCSBLK->pDevices ) pLCSBLK->pDevices = pLCSDev; // (first link in chain) else { PLCSDEV pOldLastLCSDEV; // (find last link in chain) for( pOldLastLCSDEV = pLCSBLK->pDevices; pOldLastLCSDEV->pNext; pOldLastLCSDEV = pOldLastLCSDEV->pNext ); // (add new link to end of chain) pOldLastLCSDEV->pNext = pLCSDev; } // Count it... if(pLCSDev->bMode == LCSDEV_MODE_IP) pLCSBLK->icDevices += 2; else pLCSBLK->icDevices += 1; } // end OAT file statement } // end for(;;) return 0; } // ==================================================================== // ReadOAT // ==================================================================== static char* ReadOAT( char* pszOATName, FILE* fp, char* pszBuff ) { int c; // Character work area int iLine = 0; // Statement number int iLen; // Statement length while( 1 ) { // Increment statement number iLine++; // Read next statement from OAT for( iLen = 0; ; ) { // Read character from OAT c = fgetc( fp ); // Check for I/O error if( ferror( fp ) ) { logmsg( _("HHCLC037E Error reading file %s line %d: %s\n"), pszOATName, iLine, strerror( errno ) ); return NULL; } // Check for end of file if( iLen == 0 && ( c == EOF || c == '\x1A' ) ) return NULL; // Check for end of line if( c == '\n' || c == EOF || c == '\x1A' ) break; // Ignore leading blanks and tabs if( iLen == 0 && ( c == ' ' || c == '\t' ) ) continue; // Ignore nulls and carriage returns if( c == '\0' || c == '\r' ) continue; // Check that statement does not overflow bufffer if( iLen >= 255 ) { logmsg( _("HHCLC038E File %s line %d is too long\n"), pszOATName, iLine ); exit(1); } // Append character to buffer pszBuff[iLen++] = c; } // Remove trailing blanks and tabs while( iLen > 0 && ( pszBuff[iLen-1] == ' ' || pszBuff[iLen-1] == '\t' ) ) iLen--; pszBuff[iLen] = '\0'; // Ignore comments and null statements if( iLen == 0 || pszBuff[0] == '*' || pszBuff[0] == '#' ) continue; break; } return pszBuff; } // ==================================================================== // Device Handler Information // ==================================================================== /* NOTE : lcs_device_hndinfo is NEVER static as it is referenced by the CTC meta driver */ DEVHND lcs_device_hndinfo = { &LCS_Init, /* Device Initialisation */ &LCS_ExecuteCCW, /* Device CCW execute */ &LCS_Close, /* Device Close */ &LCS_Query, /* Device Query */ NULL, /* Device Start channel pgm */ NULL, /* Device End channel pgm */ NULL, /* Device Resume channel pgm */ NULL, /* Device Suspend channel pgm */ NULL, /* Device Read */ NULL, /* Device Write */ NULL, /* Device Query used */ NULL, /* Device Reserve */ NULL, /* Device Release */ NULL, /* Device Attention */ CTC_Immed_Commands, /* Immediate CCW Codes */ NULL, /* Signal Adapter Input */ NULL, /* Signal Adapter Output */ NULL, /* Hercules suspend */ NULL /* Hercules resume */ }; /* Libtool static name colision resolution */ /* note : lt_dlopen will look for symbol & modulename_LTX_symbol */ #if !defined(HDL_BUILD_SHARED) && defined(HDL_USE_LIBTOOL) #define hdl_ddev hdt3088_LTX_hdl_ddev #define hdl_depc hdt3088_LTX_hdl_depc #define hdl_reso hdt3088_LTX_hdl_reso #define hdl_init hdt3088_LTX_hdl_init #define hdl_fini hdt3088_LTX_hdl_fini #endif #if defined(OPTION_DYNAMIC_LOAD) HDL_DEPENDENCY_SECTION; { HDL_DEPENDENCY(HERCULES); HDL_DEPENDENCY(DEVBLK); } END_DEPENDENCY_SECTION HDL_REGISTER_SECTION; // ("Register" our entry-points) // Hercules's Our // registered overriding // entry-point entry-point // name value #if defined( WIN32 ) HDL_REGISTER ( debug_tt32_stats, display_tt32_stats ); HDL_REGISTER ( debug_tt32_tracing, enable_tt32_debug_tracing ); #endif END_REGISTER_SECTION HDL_DEVICE_SECTION; { HDL_DEVICE(LCS, lcs_device_hndinfo ); // ZZ the following device types should be moved to // ZZ their own loadable modules HDL_DEVICE(3088, ctcadpt_device_hndinfo ); HDL_DEVICE(CTCI, ctci_device_hndinfo ); HDL_DEVICE(CTCT, ctct_device_hndinfo ); HDL_DEVICE(VMNET,vmnet_device_hndinfo ); #if defined(WIN32) HDL_DEVICE(CTCI-W32,ctci_device_hndinfo ); #endif } END_DEVICE_SECTION #endif //----------------------------------------------------------------------------- // Debugging... #if !defined( DEBUG) && !defined( _DEBUG ) // only needed for Release builds #ifdef NO_LCS_OPTIMIZE // for reliable breakpoints and instr stepping #pragma warning( pop ) // restore previous settings #pragma optimize( "", on ) // restore previous settings #endif // NO_LCS_OPTIMIZE #endif // !defined( DEBUG) && !defined( _DEBUG ) //----------------------------------------------------------------------------- #endif /* !defined(__SOLARIS__) jbs 10/2007 10/2007 */ hercules-3.07/ctcadpt.c000644 000765 000765 00000131532 11202676512 016540 0ustar00jmaynardjmaynard000000 000000 // Hercules Channel-to-Channel Emulation Support // ==================================================================== // // Copyright (C) James A. Pierson, 2002-2009 // Roger Bowler, 2000-2009 // // vmnet (C) Copyright Willem Konynenberg, 2000-2009 // CTCT (C) Copyright Vic Cross, 2001-2009 // // Notes: // This module contains the remaining CTC emulation modes that // have not been moved to seperate modules. There is also logic // to allow old style 3088 device definitions for compatibility // and may be removed in a future release. // // Please read README.NETWORKING for more info. // // $Id: ctcadpt.c 5311 2009-04-05 08:14:17Z rbowler $ #include "hstdinc.h" #define _CTCADPT_C_ #define _HENGINE_DLL_ #include "hercules.h" #include "devtype.h" #include "ctcadpt.h" #include "opcode.h" #include "devtype.h" // ==================================================================== // Declarations // ==================================================================== static int CTCT_Init( DEVBLK *dev, int argc, char *argv[] ); static void CTCT_Read( DEVBLK* pDEVBLK, U16 sCount, BYTE* pIOBuf, BYTE* pUnitStat, U16* pResidual, BYTE* pMore ); static void CTCT_Write( DEVBLK* pDEVBLK, U16 sCount, BYTE* pIOBuf, BYTE* pUnitStat, U16* pResidual ); static void* CTCT_ListenThread( void* argp ); static int VMNET_Init( DEVBLK *dev, int argc, char *argv[] ); static int VMNET_Write( DEVBLK *dev, BYTE *iobuf, U16 count, BYTE *unitstat ); static int VMNET_Read( DEVBLK *dev, BYTE *iobuf, U16 count, BYTE *unitstat ); // -------------------------------------------------------------------- // Definitions for CTC general data blocks // -------------------------------------------------------------------- typedef struct _CTCG_PARMBLK { int listenfd; struct sockaddr_in addr; DEVBLK* dev; } CTCG_PARMBLK; // -------------------------------------------------------------------- // Device Handler Information Block // -------------------------------------------------------------------- DEVHND ctcadpt_device_hndinfo = { &CTCX_Init, /* Device Initialisation */ &CTCX_ExecuteCCW, /* Device CCW execute */ &CTCX_Close, /* Device Close */ &CTCX_Query, /* Device Query */ NULL, /* Device Start channel pgm */ NULL, /* Device End channel pgm */ NULL, /* Device Resume channel pgm */ NULL, /* Device Suspend channel pgm */ NULL, /* Device Read */ NULL, /* Device Write */ NULL, /* Device Query used */ NULL, /* Device Reserve */ NULL, /* Device Release */ NULL, /* Device Attention */ NULL, /* Immediate CCW Codes */ NULL, /* Signal Adapter Input */ NULL, /* Signal Adapter Output */ NULL, /* Hercules suspend */ NULL /* Hercules resume */ }; DEVHND ctct_device_hndinfo = { &CTCT_Init, /* Device Initialisation */ &CTCX_ExecuteCCW, /* Device CCW execute */ &CTCX_Close, /* Device Close */ &CTCX_Query, /* Device Query */ NULL, /* Device Start channel pgm */ NULL, /* Device End channel pgm */ NULL, /* Device Resume channel pgm */ NULL, /* Device Suspend channel pgm */ NULL, /* Device Read */ NULL, /* Device Write */ NULL, /* Device Query used */ NULL, /* Device Reserve */ NULL, /* Device Release */ NULL, /* Device Attention */ NULL, /* Immediate CCW Codes */ NULL, /* Signal Adapter Input */ NULL, /* Signal Adapter Output */ NULL, /* Hercules suspend */ NULL /* Hercules resume */ }; DEVHND vmnet_device_hndinfo = { &VMNET_Init, /* Device Initialisation */ &CTCX_ExecuteCCW, /* Device CCW execute */ &CTCX_Close, /* Device Close */ &CTCX_Query, /* Device Query */ NULL, /* Device Start channel pgm */ NULL, /* Device End channel pgm */ NULL, /* Device Resume channel pgm */ NULL, /* Device Suspend channel pgm */ NULL, /* Device Read */ NULL, /* Device Write */ NULL, /* Device Query used */ NULL, /* Device Reserve */ NULL, /* Device Release */ NULL, /* Device Attention */ NULL, /* Immediate CCW Codes */ NULL, /* Signal Adapter Input */ NULL, /* Signal Adapter Output */ NULL, /* Hercules suspend */ NULL /* Hercules resume */ }; extern DEVHND ctci_device_hndinfo; extern DEVHND lcs_device_hndinfo; // ==================================================================== // Primary Module Entry Points // ==================================================================== // -------------------------------------------------------------------- // Device Initialization Handler (Generic) // -------------------------------------------------------------------- int CTCX_Init( DEVBLK* pDEVBLK, int argc, char *argv[] ) { pDEVBLK->devtype = 0x3088; // The first argument is the device emulation type if( argc < 1 ) { logmsg( _("HHCCT001E %4.4X: Incorrect number of parameters\n"), pDEVBLK->devnum ); return -1; } if((pDEVBLK->hnd = hdl_ghnd(argv[0]))) { if(pDEVBLK->hnd->init == &CTCX_Init) return -1; free(pDEVBLK->typname); pDEVBLK->typname = strdup(argv[0]); return (pDEVBLK->hnd->init)( pDEVBLK, --argc, ++argv ); } logmsg (_("HHCCT034E %s: Unrecognized/unsupported CTC emulation type\n"), argv[0]); return -1; } // ------------------------------------------------------------------- // Query the device definition (Generic) // ------------------------------------------------------------------- void CTCX_Query( DEVBLK* pDEVBLK, char** ppszClass, int iBufLen, char* pBuffer ) { BEGIN_DEVICE_CLASS_QUERY( "CTCA", pDEVBLK, ppszClass, iBufLen, pBuffer ); snprintf( pBuffer, iBufLen, "%s", pDEVBLK->filename ); } // ------------------------------------------------------------------- // Close the device (Generic) // ------------------------------------------------------------------- int CTCX_Close( DEVBLK* pDEVBLK ) { // Close the device file (if not already closed) if( pDEVBLK->fd >= 0 ) { if (socket_is_socket( pDEVBLK->fd )) close_socket( pDEVBLK->fd ); else close( pDEVBLK->fd ); pDEVBLK->fd = -1; // indicate we're now closed } return 0; } // ------------------------------------------------------------------- // Execute a Channel Command Word (Generic) // ------------------------------------------------------------------- void CTCX_ExecuteCCW( DEVBLK* pDEVBLK, BYTE bCode, BYTE bFlags, BYTE bChained, U16 sCount, BYTE bPrevCode, int iCCWSeq, BYTE* pIOBuf, BYTE* pMore, BYTE* pUnitStat, U16* pResidual ) { int iNum; // Number of bytes to move BYTE bOpCode; // CCW opcode with modifier // bits masked off UNREFERENCED( bFlags ); UNREFERENCED( bChained ); UNREFERENCED( bPrevCode ); UNREFERENCED( iCCWSeq ); // Intervention required if the device file is not open if( pDEVBLK->fd < 0 && !IS_CCW_SENSE( bCode ) && !IS_CCW_CONTROL( bCode ) ) { pDEVBLK->sense[0] = SENSE_IR; *pUnitStat = CSW_CE | CSW_DE | CSW_UC; return; } // Mask off the modifier bits in the CCW bOpCode if( ( bCode & 0x07 ) == 0x07 ) bOpCode = 0x07; else if( ( bCode & 0x03 ) == 0x02 ) bOpCode = 0x02; else if( ( bCode & 0x0F ) == 0x0C ) bOpCode = 0x0C; else if( ( bCode & 0x03 ) == 0x01 ) bOpCode = pDEVBLK->ctcxmode ? ( bCode & 0x83 ) : 0x01; else if( ( bCode & 0x1F ) == 0x14 ) bOpCode = 0x14; else if( ( bCode & 0x47 ) == 0x03 ) bOpCode = 0x03; else if( ( bCode & 0xC7 ) == 0x43 ) bOpCode = 0x43; else bOpCode = bCode; // Process depending on CCW bOpCode switch (bOpCode) { case 0x01: // 0MMMMM01 WRITE //------------------------------------------------------------ // WRITE //------------------------------------------------------------ // Return normal status if CCW count is zero if( sCount == 0 ) { *pUnitStat = CSW_CE | CSW_DE; break; } // Write data and set unit status and residual byte count switch( pDEVBLK->ctctype ) { case CTC_CTCT: CTCT_Write( pDEVBLK, sCount, pIOBuf, pUnitStat, pResidual ); break; case CTC_VMNET: *pResidual = sCount - VMNET_Write( pDEVBLK, pIOBuf, sCount, pUnitStat ); break; } break; case 0x81: // 1MMMMM01 WEOF //------------------------------------------------------------ // WRITE EOF //------------------------------------------------------------ // Return normal status *pUnitStat = CSW_CE | CSW_DE; break; case 0x02: // MMMMMM10 READ case 0x0C: // MMMM1100 RDBACK // ----------------------------------------------------------- // READ & READ BACKWARDS // ----------------------------------------------------------- // Read data and set unit status and residual byte count switch( pDEVBLK->ctctype ) { case CTC_CTCT: CTCT_Read( pDEVBLK, sCount, pIOBuf, pUnitStat, pResidual, pMore ); break; case CTC_VMNET: *pResidual = sCount - VMNET_Read( pDEVBLK, pIOBuf, sCount, pUnitStat ); break; } break; case 0x07: // MMMMM111 CTL // ----------------------------------------------------------- // CONTROL // ----------------------------------------------------------- *pUnitStat = CSW_CE | CSW_DE; break; case 0x03: // M0MMM011 NOP // ----------------------------------------------------------- // CONTROL NO-OPERATON // ----------------------------------------------------------- *pUnitStat = CSW_CE | CSW_DE; break; case 0x43: // 00XXX011 SBM // ----------------------------------------------------------- // SET BASIC MODE // ----------------------------------------------------------- // Command reject if in basic mode if( pDEVBLK->ctcxmode == 0 ) { pDEVBLK->sense[0] = SENSE_CR; *pUnitStat = CSW_CE | CSW_DE | CSW_UC; break; } // Reset extended mode and return normal status pDEVBLK->ctcxmode = 0; *pResidual = 0; *pUnitStat = CSW_CE | CSW_DE; break; case 0xC3: // 11000011 SEM // ----------------------------------------------------------- // SET EXTENDED MODE // ----------------------------------------------------------- pDEVBLK->ctcxmode = 1; *pResidual = 0; *pUnitStat = CSW_CE | CSW_DE; break; case 0xE3: // 11100011 // ----------------------------------------------------------- // PREPARE (PREP) // ----------------------------------------------------------- *pUnitStat = CSW_CE | CSW_DE; break; case 0x14: // XXX10100 SCB // ----------------------------------------------------------- // SENSE COMMAND BYTE // ----------------------------------------------------------- *pUnitStat = CSW_CE | CSW_DE; break; case 0x04: // 00000100 SENSE // ----------------------------------------------------------- // SENSE // ----------------------------------------------------------- // Command reject if in basic mode if( pDEVBLK->ctcxmode == 0 ) { pDEVBLK->sense[0] = SENSE_CR; *pUnitStat = CSW_CE | CSW_DE | CSW_UC; break; } // Calculate residual byte count iNum = ( sCount < pDEVBLK->numsense ) ? sCount : pDEVBLK->numsense; *pResidual = sCount - iNum; if( sCount < pDEVBLK->numsense ) *pMore = 1; // Copy device sense bytes to channel I/O buffer memcpy( pIOBuf, pDEVBLK->sense, iNum ); // Clear the device sense bytes memset( pDEVBLK->sense, 0, sizeof( pDEVBLK->sense ) ); // Return unit status *pUnitStat = CSW_CE | CSW_DE; break; case 0xE4: // 11100100 SID // ----------------------------------------------------------- // SENSE ID // ----------------------------------------------------------- // Calculate residual byte count iNum = ( sCount < pDEVBLK->numdevid ) ? sCount : pDEVBLK->numdevid; *pResidual = sCount - iNum; if( sCount < pDEVBLK->numdevid ) *pMore = 1; // Copy device identifier bytes to channel I/O buffer memcpy( pIOBuf, pDEVBLK->devid, iNum ); // Return unit status *pUnitStat = CSW_CE | CSW_DE; break; default: // ------------------------------------------------------------ // INVALID OPERATION // ------------------------------------------------------------ // Set command reject sense byte, and unit check status pDEVBLK->sense[0] = SENSE_CR; *pUnitStat = CSW_CE | CSW_DE | CSW_UC; } } // ==================================================================== // CTCT Support // ==================================================================== // // CTCT_Init // static int CTCT_Init( DEVBLK *dev, int argc, char *argv[] ) { char str[80]; // Thread name int rc; // Return code int mtu; // MTU size (binary) int lport; // Listen port (binary) int rport; // Destination port (binary) char* listenp; // Listening port number char* remotep; // Destination port number char* mtusize; // MTU size (characters) char* remaddr; // Remote IP address struct in_addr ipaddr; // Work area for IP address BYTE c; // Character work area TID tid; // Thread ID for server CTCG_PARMBLK parm; // Parameters for the server char address[20]=""; // temp space for IP address dev->devtype = 0x3088; dev->ctctype = CTC_CTCT; SetSIDInfo( dev, 0x3088, 0x08, 0x3088, 0x01 ); // Check for correct number of arguments if (argc != 4) { logmsg( _("HHCCT002E %4.4X: Incorrect number of parameters\n"), dev->devnum ); return -1; } // The first argument is the listening port number listenp = *argv++; if( strlen( listenp ) > 5 || sscanf( listenp, "%u%c", &lport, &c ) != 1 || lport < 1024 || lport > 65534 ) { logmsg( _("HHCCT003E %4.4X: Invalid port number: %s\n"), dev->devnum, listenp ); return -1; } // The second argument is the IP address or hostname of the // remote side of the point-to-point link remaddr = *argv++; if( inet_aton( remaddr, &ipaddr ) == 0 ) { struct hostent *hp; if( ( hp = gethostbyname( remaddr ) ) != NULL ) { memcpy( &ipaddr, hp->h_addr, hp->h_length ); strcpy( address, inet_ntoa( ipaddr ) ); remaddr = address; } else { logmsg( _("HHCCT004E %4.4X: Invalid IP address %s\n"), dev->devnum, remaddr ); return -1; } } // The third argument is the destination port number remotep = *argv++; if( strlen( remotep ) > 5 || sscanf( remotep, "%u%c", &rport, &c ) != 1 || rport < 1024 || rport > 65534 ) { logmsg( _("HHCCT005E %4.4X: Invalid port number: %s\n"), dev->devnum, remotep ); return -1; } // The fourth argument is the maximum transmission unit (MTU) size mtusize = *argv; if( strlen( mtusize ) > 5 || sscanf( mtusize, "%u%c", &mtu, &c ) != 1 || mtu < 46 || mtu > 65536 ) { logmsg( _("HHCCT006E %4.4X: Invalid MTU size %s\n"), dev->devnum, mtusize ); return -1; } // Set the device buffer size equal to the MTU size dev->bufsize = mtu; // Initialize the file descriptor for the socket connection // It's a little confusing, but we're using a couple of the // members of the server paramter structure to initiate the // outgoing connection. Saves a couple of variable declarations, // though. If we feel strongly about it, we can declare separate // variables... // make a TCP socket parm.listenfd = socket( AF_INET, SOCK_STREAM, 0 ); if( parm.listenfd < 0 ) { logmsg( _("HHCCT007E %4.4X: Error creating socket: %s\n"), dev->devnum, strerror( HSO_errno ) ); CTCX_Close( dev ); return -1; } // bind socket to our local port // (might seem like overkill, and usually isn't done, but doing this // bind() to the local port we configure gives the other end a chance // at validating the connection request) memset( &(parm.addr), 0, sizeof( parm.addr ) ); parm.addr.sin_family = AF_INET; parm.addr.sin_port = htons(lport); parm.addr.sin_addr.s_addr = htonl(INADDR_ANY); rc = bind( parm.listenfd, (struct sockaddr *)&parm.addr, sizeof( parm.addr ) ); if( rc < 0 ) { logmsg( _("HHCCT008E %4.4X: Error binding to socket: %s\n"), dev->devnum, strerror( HSO_errno ) ); CTCX_Close( dev ); return -1; } // initiate a connection to the other end memset( &(parm.addr), 0, sizeof( parm.addr ) ); parm.addr.sin_family = AF_INET; parm.addr.sin_port = htons(rport); parm.addr.sin_addr = ipaddr; rc = connect( parm.listenfd, (struct sockaddr *)&parm.addr, sizeof( parm.addr ) ); // if connection was not successful, start a server if( rc < 0 ) { // used to pass parameters to the server thread CTCG_PARMBLK* arg; logmsg( _("HHCCT009I %4.4X: Connect to %s:%s failed, starting server\n"), dev->devnum, remaddr, remotep ); // probably don't need to do this, not sure... close_socket( parm.listenfd ); parm.listenfd = socket( AF_INET, SOCK_STREAM, 0 ); if( parm.listenfd < 0 ) { logmsg( _("HHCCT010E %4.4X: Error creating socket: %s\n"), dev->devnum, strerror( HSO_errno ) ); CTCX_Close( dev ); return -1; } // set up the listening port memset( &(parm.addr), 0, sizeof( parm.addr ) ); parm.addr.sin_family = AF_INET; parm.addr.sin_port = htons(lport); parm.addr.sin_addr.s_addr = htonl(INADDR_ANY); if( bind( parm.listenfd, (struct sockaddr *)&parm.addr, sizeof( parm.addr ) ) < 0 ) { logmsg( _("HHCCT011E %4.4X: Error binding to socket: %s\n"), dev->devnum, strerror( HSO_errno ) ); CTCX_Close( dev ); return -1; } if( listen( parm.listenfd, 1 ) < 0 ) { logmsg( _("HHCCT012E %4.4X: Error on call to listen: %s\n"), dev->devnum, strerror( HSO_errno ) ); CTCX_Close( dev ); return -1; } // we are listening, so create a thread to accept connection arg = malloc( sizeof( CTCG_PARMBLK ) ); memcpy( arg, &parm, sizeof( parm ) ); arg->dev = dev; snprintf(str,sizeof(str),"CTCT %4.4X ListenThread",dev->devnum); str[sizeof(str)-1]=0; create_thread( &tid, JOINABLE, CTCT_ListenThread, arg, str ); } else // successfully connected (outbound) to the other end { logmsg( _("HHCCT013I %4.4X: Connected to %s:%s\n"), dev->devnum, remaddr, remotep ); dev->fd = parm.listenfd; } // for cosmetics, since we are successfully connected or serving, // fill in some details for the panel. sprintf( dev->filename, "%s:%s", remaddr, remotep ); return 0; } // // CTCT_Write // static void CTCT_Write( DEVBLK* pDEVBLK, U16 sCount, BYTE* pIOBuf, BYTE* pUnitStat, U16* pResidual ) { PCTCIHDR pFrame; // -> Frame header PCTCISEG pSegment; // -> Segment in buffer U16 sOffset; // Offset of next frame U16 sSegLen; // Current segment length U16 sDataLen; // Length of IP Frame data int iPos; // Offset into buffer U16 i; // Array subscript int rc; // Return code BYTE szStackID[33]; // VSE IP stack identity U32 iStackCmd; // VSE IP stack command // Check that CCW count is sufficient to contain block header if( sCount < sizeof( CTCIHDR ) ) { logmsg( _("HHCCT014E %4.4X: Write CCW count %u is invalid\n"), pDEVBLK->devnum, sCount ); pDEVBLK->sense[0] = SENSE_DC; *pUnitStat = CSW_CE | CSW_DE | CSW_UC; return; } // Fix-up frame pointer pFrame = (PCTCIHDR)pIOBuf; // Extract the frame length from the header FETCH_HW( sOffset, pFrame->hwOffset ); // Check for special VSE TCP/IP stack command packet if( sOffset == 0 && sCount == 40 ) { // Extract the 32-byte stack identity string for( i = 0; i < sizeof( szStackID ) - 1 && i < sCount - 4; i++) szStackID[i] = guest_to_host( pIOBuf[i+4] ); szStackID[i] = '\0'; // Extract the stack command word FETCH_FW( iStackCmd, *((FWORD*)&pIOBuf[36]) ); // Display stack command and discard the packet logmsg( _("HHCCT015I %4.4X: Interface command: %s %8.8X\n"), pDEVBLK->devnum, szStackID, iStackCmd ); *pUnitStat = CSW_CE | CSW_DE; *pResidual = 0; return; } // Check for special L/390 initialization packet if( sOffset == 0 ) { // Return normal status and discard the packet *pUnitStat = CSW_CE | CSW_DE; *pResidual = 0; return; } #if 0 // Notes: It appears that TurboLinux has gotten sloppy in their // ways. They are now giving us buffer sizes that are // greater than the CCW count, but the segment size // is within the count. // Check that the frame offset is valid if( sOffset < sizeof( CTCIHDR ) || sOffset > sCount ) { logmsg( _("CTC101W %4.4X: Write buffer contains invalid " "frame offset %u\n"), pDEVBLK->devnum, sOffset ); pDEVBLK->sense[0] = SENSE_CR; *pUnitStat = CSW_CE | CSW_DE | CSW_UC; return; } #endif // Adjust the residual byte count *pResidual -= sizeof( CTCIHDR ); // Process each segment in the buffer for( iPos = sizeof( CTCIHDR ); iPos < sOffset; iPos += sSegLen ) { // Check that the segment is fully contained within the block if( iPos + sizeof( CTCISEG ) > sOffset ) { logmsg( _("HHCCT016E %4.4X: Write buffer contains incomplete " "segment header at offset %4.4X\n"), pDEVBLK->devnum, iPos ); pDEVBLK->sense[0] = SENSE_DC; *pUnitStat = CSW_CE | CSW_DE | CSW_UC; return; } // Fix-up segment header in the I/O buffer pSegment = (PCTCISEG)(pIOBuf + iPos); // Extract the segment length from the segment header FETCH_HW( sSegLen, pSegment->hwLength ); // Check that the segment length is valid if( ( sSegLen < sizeof( CTCISEG ) ) || ( iPos + sSegLen > sOffset ) || ( iPos + sSegLen > sCount ) ) { logmsg( _("HHCCT017E %4.4X: Write buffer contains invalid " "segment length %u at offset %4.4X\n"), pDEVBLK->devnum, sSegLen, iPos ); pDEVBLK->sense[0] = SENSE_DC; *pUnitStat = CSW_CE | CSW_DE | CSW_UC; return; } // Calculate length of IP frame data sDataLen = sSegLen - sizeof( CTCISEG ); // Trace the IP packet before sending if( pDEVBLK->ccwtrace || pDEVBLK->ccwstep ) { logmsg( _("HHCCT018I %4.4X: Sending packet to %s:\n"), pDEVBLK->devnum, pDEVBLK->filename ); if( pDEVBLK->ccwtrace ) packet_trace( pSegment->bData, sDataLen ); } // Write the IP packet rc = write_socket( pDEVBLK->fd, pSegment->bData, sDataLen ); if( rc < 0 ) { logmsg( _("HHCCT019E %4.4X: Error writing to %s: %s\n"), pDEVBLK->devnum, pDEVBLK->filename, strerror( HSO_errno ) ); pDEVBLK->sense[0] = SENSE_EC; *pUnitStat = CSW_CE | CSW_DE | CSW_UC; return; } // Adjust the residual byte count *pResidual -= sSegLen; // We are done if current segment satisfies CCW count if( iPos + sSegLen == sCount ) { *pResidual -= sSegLen; *pUnitStat = CSW_CE | CSW_DE; return; } } // Set unit status and residual byte count *pUnitStat = CSW_CE | CSW_DE; *pResidual = 0; } // // CTCT_Read // static void CTCT_Read( DEVBLK* pDEVBLK, U16 sCount, BYTE* pIOBuf, BYTE* pUnitStat, U16* pResidual, BYTE* pMore ) { PCTCIHDR pFrame = NULL; // -> Frame header PCTCISEG pSegment = NULL; // -> Segment in buffer fd_set rfds; // Read FD_SET int iRetVal; // Return code from 'select' ssize_t iLength = 0; static struct timeval tv; // Timeout time for 'select' // Limit how long we should wait for data to come in FD_ZERO( &rfds ); FD_SET( pDEVBLK->fd, &rfds ); tv.tv_sec = CTC_READ_TIMEOUT_SECS; tv.tv_usec = 0; iRetVal = select( pDEVBLK->fd + 1, &rfds, NULL, NULL, &tv ); switch( iRetVal ) { case 0: *pUnitStat = CSW_CE | CSW_DE | CSW_UC | CSW_SM; pDEVBLK->sense[0] = 0; return; case -1: if( HSO_errno == HSO_EINTR ) return; logmsg( _("HHCCT020E %4.4X: Error reading from %s: %s\n"), pDEVBLK->devnum, pDEVBLK->filename, strerror( HSO_errno ) ); pDEVBLK->sense[0] = SENSE_EC; *pUnitStat = CSW_CE | CSW_DE | CSW_UC; return; default: break; } // Read an IP packet from the TUN device iLength = read_socket( pDEVBLK->fd, pDEVBLK->buf, pDEVBLK->bufsize ); // Check for other error condition if( iLength < 0 ) { logmsg( _("HHCCT021E %4.4X: Error reading from %s: %s\n"), pDEVBLK->devnum, pDEVBLK->filename, strerror( HSO_errno ) ); pDEVBLK->sense[0] = SENSE_EC; *pUnitStat = CSW_CE | CSW_DE | CSW_UC; return; } // Trace the packet received from the TUN device if( pDEVBLK->ccwtrace || pDEVBLK->ccwstep ) { logmsg( _("HHCCT022I %4.4X: Received packet from %s (%d bytes):\n"), pDEVBLK->devnum, pDEVBLK->filename, iLength ); packet_trace( pDEVBLK->buf, iLength ); } // Fix-up Frame pointer pFrame = (PCTCIHDR)pIOBuf; // Fix-up Segment pointer pSegment = (PCTCISEG)( pIOBuf + sizeof( CTCIHDR ) ); // Initialize segment memset( pSegment, 0, iLength + sizeof( CTCISEG ) ); // Update next frame offset STORE_HW( pFrame->hwOffset, iLength + sizeof( CTCIHDR ) + sizeof( CTCISEG ) ); // Store segment length STORE_HW( pSegment->hwLength, iLength + sizeof( CTCISEG ) ); // Store Frame type STORE_HW( pSegment->hwType, ETH_TYPE_IP ); // Copy data memcpy( pSegment->bData, pDEVBLK->buf, iLength ); // Fix-up frame pointer and terminate block pFrame = (PCTCIHDR)( pIOBuf + sizeof( CTCIHDR ) + sizeof( CTCISEG ) + iLength ); STORE_HW( pFrame->hwOffset, 0x0000 ); // Calculate #of bytes returned including two slack bytes iLength += sizeof( CTCIHDR ) + sizeof( CTCISEG ) + 2; if( sCount < iLength ) { *pMore = 1; *pResidual = 0; iLength = sCount; } else { *pMore = 0; *pResidual -= iLength; } // Set unit status *pUnitStat = CSW_CE | CSW_DE; } // // CTCT_ListenThread // static void* CTCT_ListenThread( void* argp ) { int connfd; socklen_t servlen; char str[80]; CTCG_PARMBLK parm; // set up the parameters passed via create_thread parm = *((CTCG_PARMBLK*) argp); free( argp ); for( ; ; ) { servlen = sizeof(parm.addr); // await a connection connfd = accept( parm.listenfd, (struct sockaddr *)&parm.addr, &servlen ); sprintf( str, "%s:%d", inet_ntoa( parm.addr.sin_addr ), ntohs( parm.addr.sin_port ) ); if( strcmp( str, parm.dev->filename ) != 0 ) { logmsg( _("HHCCT023E %4.4X: Incorrect client or config error\n" " Config=%s, connecting client=%s\n"), parm.dev->devnum, parm.dev->filename, str); close_socket( connfd ); } else { parm.dev->fd = connfd; } // Ok, so having done that we're going to loop back to the // accept(). This was meant to handle the connection failing // at the other end; this end will be ready to accept another // connection. Although this will happen, I'm sure you can // see the possibility for bad things to occur (eg if another // Hercules tries to connect). This will also be fixed RSN. } return NULL; // make compiler happy } // ==================================================================== // VMNET Support -- written by Willem Konynenberg // ==================================================================== /*-------------------------------------------------------------------*/ /* Definitions for SLIP encapsulation */ /*-------------------------------------------------------------------*/ #define SLIP_END 0300 #define SLIP_ESC 0333 #define SLIP_ESC_END 0334 #define SLIP_ESC_ESC 0335 /*-------------------------------------------------------------------*/ /* Functions to support vmnet written by Willem Konynenberg */ /*-------------------------------------------------------------------*/ static int start_vmnet(DEVBLK *dev, DEVBLK *xdev, int argc, char *argv[]) { int sockfd[2]; int r, i; char *ipaddress; if (argc < 2) { logmsg (_("HHCCT024E %4.4X: Not enough arguments to start vmnet\n"), dev->devnum); return -1; } ipaddress = argv[0]; argc--; argv++; if (socketpair (AF_UNIX, SOCK_STREAM, 0, sockfd) < 0) { logmsg (_("HHCCT025E %4.4X: Failed: socketpair: %s\n"), dev->devnum, strerror(errno)); return -1; } r = fork (); if (r < 0) { logmsg (_("HHCCT026E %4.4X: Failed: fork: %s\n"), dev->devnum, strerror(errno)); return -1; } else if (r == 0) { /* child */ close (0); close (1); dup (sockfd[1]); dup (sockfd[1]); r = (sockfd[0] > sockfd[1]) ? sockfd[0] : sockfd[1]; for (i = 3; i <= r; i++) { close (i); } /* the ugly cast is to silence a compiler warning due to const */ execv (argv[0], (EXECV_ARG2_ARGV_T)argv); exit (1); } close (sockfd[1]); dev->fd = sockfd[0]; xdev->fd = sockfd[0]; /* We just blindly copy these out in the hope vmnet will pick them * up correctly. I don't feel like implementing a complete login * scripting facility here... */ write(dev->fd, ipaddress, strlen(ipaddress)); write(dev->fd, "\n", 1); return 0; } static int VMNET_Init(DEVBLK *dev, int argc, char *argv[]) { U16 xdevnum; /* Pair device devnum */ DEVBLK *xdev; /* Pair device */ int rc; U16 lcss; dev->devtype = 0x3088; /* parameters for network CTC are: * devnum of the other CTC device of the pair * ipaddress * vmnet command line * * CTC adapters are used in pairs, one for READ, one for WRITE. * The vmnet is only initialised when both are initialised. */ if (argc < 3) { logmsg(_("HHCCT027E %4.4X: Not enough parameters\n"), dev->devnum); return -1; } rc=parse_single_devnum(argv[0],&lcss,&xdevnum); if (rc<0) { logmsg(_("HHCCT028E %d:%4.4X: Bad device number '%s'\n"), SSID_TO_LCSS(dev->ssid), dev->devnum, argv[0]); return -1; } xdev = find_device_by_devnum(lcss,xdevnum); if (xdev != NULL) { if (start_vmnet(dev, xdev, argc - 1, &argv[1])) return -1; } strcpy(dev->filename, "vmnet"); /* Set the control unit type */ /* Linux/390 currently only supports 3088 model 2 CTCA and ESCON */ dev->ctctype = CTC_VMNET; SetSIDInfo( dev, 0x3088, 0x08, 0x3088, 0x01 ); /* Initialize the device dependent fields */ dev->ctcpos = 0; dev->ctcrem = 0; /* Set length of buffer */ /* This size guarantees we can write a full iobuf of 65536 * as a SLIP packet in a single write. Probably overkill... */ dev->bufsize = 65536 * 2 + 1; return 0; } static int VMNET_Write(DEVBLK *dev, BYTE *iobuf, U16 count, BYTE *unitstat) { int blklen = (iobuf[0]<<8) | iobuf[1]; int pktlen; BYTE *p = iobuf + 2; BYTE *buffer = dev->buf; int len = 0, rem; if (count < blklen) { logmsg (_("HHCCT029E %4.4X: bad block length: %d < %d\n"), dev->devnum, count, blklen); blklen = count; } while (p < iobuf + blklen) { pktlen = (p[0]<<8) | p[1]; rem = iobuf + blklen - p; if (rem < pktlen) { logmsg (_("HHCCT030E %4.4X: bad packet length: %d < %d\n"), dev->devnum, rem, pktlen); pktlen = rem; } if (pktlen < 6) { logmsg (_("HHCCT031E %4.4X: bad packet length: %d < 6\n"), dev->devnum, pktlen); pktlen = 6; } pktlen -= 6; p += 6; while (pktlen--) { switch (*p) { case SLIP_END: buffer[len++] = SLIP_ESC; buffer[len++] = SLIP_ESC_END; break; case SLIP_ESC: buffer[len++] = SLIP_ESC; buffer[len++] = SLIP_ESC_ESC; break; default: buffer[len++] = *p; break; } p++; } buffer[len++] = SLIP_END; write(dev->fd, buffer, len); /* should check error conditions? */ len = 0; } *unitstat = CSW_CE | CSW_DE; return count; } static int bufgetc(DEVBLK *dev, int blocking) { BYTE *bufp = dev->buf + dev->ctcpos, *bufend = bufp + dev->ctcrem; int n; if (bufp >= bufend) { if (blocking == 0) return -1; do { n = read(dev->fd, dev->buf, dev->bufsize); if (n <= 0) { if (n == 0) { /* VMnet died on us. */ logmsg (_("HHCCT032E %4.4X: Error: EOF on read, " "CTC network down\n"), dev->devnum); /* -2 will cause an error status to be set */ return -2; } if( n == EINTR ) return -3; logmsg (_("HHCCT033E %4.4X: Error: read: %s\n"), dev->devnum, strerror(errno)); SLEEP(2); } } while (n <= 0); dev->ctcrem = n; bufend = &dev->buf[n]; dev->ctclastpos = dev->ctclastrem = dev->ctcpos = 0; bufp = dev->buf; } dev->ctcpos++; dev->ctcrem--; return *bufp; } static void setblkheader(BYTE *iobuf, int buflen) { iobuf[0] = (buflen >> 8) & 0xFF; iobuf[1] = buflen & 0xFF; } static void setpktheader(BYTE *iobuf, int packetpos, int packetlen) { iobuf[packetpos] = (packetlen >> 8) & 0xFF; iobuf[packetpos+1] = packetlen & 0xFF; iobuf[packetpos+2] = 0x08; iobuf[packetpos+3] = 0; iobuf[packetpos+4] = 0; iobuf[packetpos+5] = 0; } /* read data from the CTC connection. * If a packet overflows the iobuf or the read buffer runs out, there are * 2 possibilities: * - block has single packet: continue reading packet, drop bytes, * then return truncated packet. * - block has multiple packets: back up on last packet and return * what we have. Do this last packet in the next IO. */ static int VMNET_Read(DEVBLK *dev, BYTE *iobuf, U16 count, BYTE *unitstat) { int c; /* next byte to process */ int len = 8; /* length of block */ int lastlen = 2; /* block length at last pckt */ dev->ctclastpos = dev->ctcpos; dev->ctclastrem = dev->ctcrem; while (1) { c = bufgetc(dev, lastlen == 2); if (c < 0) { if(c == -3) return 0; /* End of input buffer. Return what we have. */ setblkheader (iobuf, lastlen); dev->ctcpos = dev->ctclastpos; dev->ctcrem = dev->ctclastrem; *unitstat = CSW_CE | CSW_DE | (c == -2 ? CSW_UX : 0); return lastlen; } switch (c) { case SLIP_END: if (len > 8) { /* End of packet. Set up for next. */ setpktheader (iobuf, lastlen, len-lastlen); dev->ctclastpos = dev->ctcpos; dev->ctclastrem = dev->ctcrem; lastlen = len; len += 6; } break; case SLIP_ESC: c = bufgetc(dev, lastlen == 2); if (c < 0) { if(c == -3) return 0; /* End of input buffer. Return what we have. */ setblkheader (iobuf, lastlen); dev->ctcpos = dev->ctclastpos; dev->ctcrem = dev->ctclastrem; *unitstat = CSW_CE | CSW_DE | (c == -2 ? CSW_UX : 0); return lastlen; } switch (c) { case SLIP_ESC_END: c = SLIP_END; break; case SLIP_ESC_ESC: c = SLIP_ESC; break; } /* FALLTHRU */ default: if (len < count) { iobuf[len++] = c; } else if (lastlen > 2) { /* IO buffer is full and we have data to return */ setblkheader (iobuf, lastlen); dev->ctcpos = dev->ctclastpos; dev->ctcrem = dev->ctclastrem; *unitstat = CSW_CE | CSW_DE | (c == -2 ? CSW_UX : 0); return lastlen; } /* else truncate end of very large single packet... */ } } } /*-------------------------------------------------------------------*/ /* End of VMNET functions written by Willem Konynenberg */ /*-------------------------------------------------------------------*/ // ==================================================================== // Support Functions // ==================================================================== // --------------------------------------------------------------------- // ParseMAC // --------------------------------------------------------------------- // // Parse a string containing a MAC (hardware) address and return the // binary equivalent. // // Input: // pszMACAddr Pointer to string containing a MAC Address in the // format "xx-xx-xx-xx-xx-xx" or "xx:xx:xx:xx:xx:xx". // // Output: // pbMACAddr Pointer to a BYTE array to receive the MAC Address // that MUST be at least sizeof(MAC) bytes long. // // Returns: // 0 on success, -1 otherwise // int ParseMAC( char* pszMACAddr, BYTE* pbMACAddr ) { char work[((sizeof(MAC)*3)-0)]; BYTE sep; int x; unsigned i; if (strlen(pszMACAddr) != ((sizeof(MAC)*3)-1) || (sizeof(MAC) > 1 && *(pszMACAddr+2) != '-' && *(pszMACAddr+2) != ':') ) { errno = EINVAL; return -1; } strncpy(work,pszMACAddr,((sizeof(MAC)*3)-1)); work[((sizeof(MAC)*3)-1)] = sep = *(pszMACAddr+2); for (i=0; i < sizeof(MAC); i++) { if (0 || !isxdigit(work[(i*3)+0]) || !isxdigit(work[(i*3)+1]) || sep != work[(i*3)+2] ) { errno = EINVAL; return -1; } work[(i*3)+2] = 0; sscanf(&work[(i*3)+0],"%x",&x); *(pbMACAddr+i) = x; } return 0; } // --------------------------------------------------------------------- // packet_trace // --------------------------------------------------------------------- // // Subroutine to trace the contents of a buffer // void packet_trace( BYTE* pAddr, int iLen ) { int offset; unsigned int i; unsigned char c = '\0'; unsigned char e = '\0'; unsigned char print_chars[17]; for( offset = 0; offset < iLen; ) { memset( print_chars, 0, sizeof( print_chars ) ); logmsg( "+%4.4X ", offset ); for( i = 0; i < 16; i++ ) { c = *pAddr++; if( offset < iLen ) { logmsg("%2.2X", c); print_chars[i] = '.'; e = guest_to_host( c ); if( isprint( e ) ) print_chars[i] = e; if( isprint( c ) ) print_chars[i] = c; } else { logmsg( " " ); } offset++; if( ( offset & 3 ) == 0 ) { logmsg( " " ); } } logmsg( " %s\n", print_chars ); } } hercules-3.07/ctcadpt.h000644 000765 000765 00000067542 11301535255 016554 0ustar00jmaynardjmaynard000000 000000 // ==================================================================== // Hercules Channel to Channel Emulation Support // ==================================================================== // // Copyright (C) 2002-2009 by James A. Pierson (original author) // Copyright (C) 2002-2009 by David B. Trout (current maintainer) // $Id: ctcadpt.h 5497 2009-10-27 20:17:03Z fish $ // // $Log$ // Revision 1.27 2008/08/19 21:36:37 fish // Init LCS interface ASAP to fix wrong MAC being used // // Revision 1.26 2008/07/17 07:19:12 fish // Fix FCS (Frame Check Sequence) bug in LCS_Write function // and other minor bugs. // // Revision 1.24 2008/07/17 03:30:40 fish // CTC/LCS cosmetic-only changes -- part 1 // (no actual functionality was changed!) // // Revision 1.23 2007/06/23 00:04:07 ivan // Update copyright notices to include current year (2007) // // Revision 1.22 2007/01/14 07:59:58 fish // add some field/struct comments re byte-order (network vs.host) // // Revision 1.21 2006/12/08 09:43:19 jj // Add CVS message log // #ifndef __CTCADPT_H_ #define __CTCADPT_H_ // -------------------------------------------------------------------- // Pack all structures to byte boundary... // -------------------------------------------------------------------- #undef ATTRIBUTE_PACKED #if defined(_MSVC_) #pragma pack(push) #pragma pack(1) #define ATTRIBUTE_PACKED #else #define ATTRIBUTE_PACKED __attribute__((packed)) #endif // -------------------------------------------------------------------- // Definitions for 3088 model numbers // -------------------------------------------------------------------- #define CTC_3088_01 0x308801 // 3172 XCA #define CTC_3088_04 0x308804 // 3088 model 1 CTCA #define CTC_3088_08 0x308808 // 3088 model 2 CTCA #define CTC_3088_1F 0x30881F // 3172 LCS #define CTC_3088_60 0x308860 // OSA or 8232 LCS #define CTC_3088_61 0x308861 // CLAW device // -------------------------------------------------------------------- // Media Access Control address (MAC address) // -------------------------------------------------------------------- #ifndef IFHWADDRLEN // (only predefined on Linux) #define IFHWADDRLEN 6 // Ethernet MAC address length #endif typedef uint8_t MAC[ IFHWADDRLEN ]; // Data Type for MAC Addresses // -------------------------------------------------------------------- // External Declarations // -------------------------------------------------------------------- extern int CTCX_Init( DEVBLK* pDEVBLK, int argc, char *argv[] ); extern int CTCX_Close( DEVBLK* pDEVBLK ); extern void CTCX_Query( DEVBLK* pDEVBLK, char** ppszClass, int iBufLen, char* pBuffer ); extern void CTCX_ExecuteCCW( DEVBLK* pDEVBLK, BYTE bCode, BYTE bFlags, BYTE bChained, U16 sCount, BYTE bPrevCode, int iCCWSeq, BYTE* pIOBuf, BYTE* pMore, BYTE* pUnitStat, U16* pResidual ); extern int CTCI_Init( DEVBLK* pDEVBLK, int argc, char *argv[] ); extern int CTCI_Close( DEVBLK* pDEVBLK ); extern void CTCI_Query( DEVBLK* pDEVBLK, char** ppszClass, int iBufLen, char* pBuffer ); extern void CTCI_ExecuteCCW( DEVBLK* pDEVBLK, BYTE bCode, BYTE bFlags, BYTE bChained, U16 sCount, BYTE bPrevCode, int iCCWSeq, BYTE* pIOBuf, BYTE* pMore, BYTE* pUnitStat, U16* pResidual ); extern void CTCI_Read( DEVBLK* pDEVBLK, U16 sCount, BYTE* pIOBuf, BYTE* UnitStat, U16* pResidual, BYTE* pMore ); extern void CTCI_Write( DEVBLK* pDEVBLK, U16 sCount, BYTE* pIOBuf, BYTE* UnitStat, U16* pResidual ); extern int LCS_Init( DEVBLK* pDEVBLK, int argc, char *argv[] ); extern int LCS_Close( DEVBLK* pDEVBLK ); extern void LCS_Query( DEVBLK* pDEVBLK, char** ppszClass, int iBufLen, char* pBuffer ); extern void LCS_ExecuteCCW( DEVBLK* pDEVBLK, BYTE bCode, BYTE bFlags, BYTE bChained, U16 sCount, BYTE bPrevCode, int iCCWSeq, BYTE* pIOBuf, BYTE* pMore, BYTE* pUnitStat, U16* pResidual ); extern void LCS_Read( DEVBLK* pDEVBLK, U16 sCount, BYTE* pIOBuf, BYTE* UnitStat, U16* pResidual, BYTE* pMore ); extern void LCS_Write( DEVBLK* pDEVBLK, U16 sCount, BYTE* pIOBuf, BYTE* UnitStat, U16* pResidual ); extern void LCS_SDC( DEVBLK* pDEVBLK, BYTE bOpCode, U16 sCount, BYTE* pIOBuf, BYTE* UnitStat, U16* pResidual, BYTE* pMore ); extern int ParseMAC( char* pszMACAddr, BYTE* pbMACAddr ); extern void packet_trace( BYTE *addr, int len ); /**********************************************************************\ ********************************************************************** ** ** ** STANDARD ETHERNET FRAMES LAYOUT ** ** ** ********************************************************************** \**********************************************************************/ // -------------------------------------------------------------------- // Ethernet Frame Header (network byte order) // -------------------------------------------------------------------- struct _ETHFRM { MAC bDestMAC; // 0x00 MAC bSrcMAC; // 0x06 HWORD hwEthernetType; // 0x0C (see below #defines) BYTE bData[FLEXIBLE_ARRAY]; // 0x0E } ATTRIBUTE_PACKED; typedef struct _ETHFRM ETHFRM, *PETHFRM; #define ETH_TYPE_IP 0x0800 #define ETH_TYPE_ARP 0x0806 #define ETH_TYPE_RARP 0x0835 #define ETH_TYPE_SNA 0x80D5 // -------------------------------------------------------------------- // IP Version 4 Frame Header (Type 0x0800) (network byte order) // -------------------------------------------------------------------- struct _IP4FRM { BYTE bVersIHL; // 0x00 Vers:4, IHL:4 BYTE bTOS; // 0x01 HWORD hwTotalLength; // 0x02 HWORD hwIdentification; // 0x04 U16 bFlagsFragOffset; // 0x06 Flags:3, FragOffset:13 BYTE bTTL; // 0x08 BYTE bProtocol; // 0x09 HWORD hwChecksum; // 0x0A U32 lSrcIP; // 0x0C U32 lDstIP; // 0x10 BYTE bData[FLEXIBLE_ARRAY]; // 0x14 } ATTRIBUTE_PACKED; typedef struct _IP4FRM IP4FRM, *PIP4FRM; // -------------------------------------------------------------------- // Address Resolution Protocol Frame (Type 0x0806) (network byte order) // -------------------------------------------------------------------- struct _ARPFRM { HWORD hwHardwareType; // 0x00 HWORD hwProtocolType; // 0x02 BYTE bHardwareSize; // 0x04 BYTE bProtocolSize; // 0x05 HWORD hwOperation; // 0x06 MAC bSendEthAddr; // 0x08 U32 lSendIPAddr; // 0x12 MAC bTargEthAddr; // 0x16 U32 lTargIPAddr; // 0x1C } ATTRIBUTE_PACKED; typedef struct _ARPFRM ARPFRM, *PARPFRM; #define ARP_REQUEST 0x01 #define ARP_REPLY 0x02 #define RARP_REQUEST 0x03 #define RARP_REPLY 0x04 /**********************************************************************\ ********************************************************************** ** ** ** CTCI DEVICE CONTROL BLOCKS ** ** ** ********************************************************************** \**********************************************************************/ #define MAX_CTCI_FRAME_SIZE( pCTCBLK ) \ ( \ pCTCBLK->iMaxFrameBufferSize /* (whatever CTCI_Init defined) */ \ - sizeof( CTCIHDR ) \ - sizeof( CTCISEG ) \ - sizeof_member(CTCIHDR,hwOffset) \ ) #define MAX_LCS_ETH_FRAME_SIZE( pLCSDEV ) \ ( \ pLCSDEV->iMaxFrameBufferSize /* (whatever LCS_Startup defined) */ \ - sizeof( LCSETHFRM ) \ - sizeof_member(LCSHDR,hwOffset) \ ) // PROGRAMMING NOTE: the following frame buffer size should always be // no smaller than the maximum frame buffer size possible for an LCS // device (currently hard-coded in S390 Linux to be 0x5000 via the // #define LCS_IOBUFFERSIZE). Also note that the minimum and maximum // frame buffer size, according to IBM documentation, is 16K to 64K. #define CTC_FRAME_BUFFER_SIZE (0x5000) // 20K CTCI/LCS frame buffer #define CTC_MIN_FRAME_BUFFER_SIZE (0x4000) // Minimum frame buffer size #define CTC_MAX_FRAME_BUFFER_SIZE (0xFFFF) // Maximum frame buffer size #define CTC_READ_TIMEOUT_SECS (5) // five seconds #define CTC_DELAY_USECS (100) // 100 microseconds delay; used // mostly by enqueue frame buffer // full delay loop... struct _CTCBLK; struct _CTCIHDR; struct _CTCISEG; typedef struct _CTCBLK CTCBLK, *PCTCBLK; typedef struct _CTCIHDR CTCIHDR,*PCTCIHDR; typedef struct _CTCISEG CTCISEG,*PCTCISEG; // -------------------------------------------------------------------- // CTCBLK - (host byte order) // -------------------------------------------------------------------- struct _CTCBLK { int fd; // TUN/TAP fd TID tid; // Read Thread ID pid_t pid; // Read Thread pid DEVBLK* pDEVBLK[2]; // 0 - Read subchannel // 1 - Write subchannel U16 iMaxFrameBufferSize; // Device Buffer Size BYTE bFrameBuffer[CTC_FRAME_BUFFER_SIZE]; // (this really SHOULD be dynamically allocated!) U16 iFrameOffset; // Curr Offset into Buffer U16 sMTU; // Max MTU LOCK Lock; // Data LOCK LOCK EventLock; // Condition LOCK COND Event; // Condition signal u_int fDebug:1; // Debugging u_int fOldFormat:1; // Old Config Format u_int fCreated:1; // Interface Created u_int fStarted:1; // Startup Received u_int fDataPending:1; // Data is pending for // read device u_int fCloseInProgress:1; // Close in progress int iKernBuff; // Kernel buffer in K bytes. int iIOBuff; // I/O buffer in K bytes. char szGuestIPAddr[32]; // IP Address (Guest OS) char szDriveIPAddr[32]; // IP Address (Driver) char szNetMask[32]; // Netmask for P2P link char szMTU[32]; char szTUNCharName[256]; // TUN/TAP char filename char szTUNDevName[IFNAMSIZ]; // Network Device Name char szMACAddress[32]; // MAC Address }; /**********************************************************************\ ********************************************************************** ** ** ** CTCI DEVICE FRAMES ** ** ** ********************************************************************** \**********************************************************************/ // -------------------------------------------------------------------- // CTCI Block Header (host byte order) // -------------------------------------------------------------------- struct _CTCIHDR // CTCI Block Header { HWORD hwOffset; // Offset of next block BYTE bData[FLEXIBLE_ARRAY]; // start of data (CTCISEG) } ATTRIBUTE_PACKED; // -------------------------------------------------------------------- // CTCI Segment Header (host byte order) // -------------------------------------------------------------------- struct _CTCISEG // CTCI Segment Header { HWORD hwLength; // Segment length including // this header HWORD hwType; // Ethernet packet type HWORD _reserved; // Unused, set to zeroes BYTE bData[FLEXIBLE_ARRAY]; // Start of data (IP pakcet) } ATTRIBUTE_PACKED; /**********************************************************************\ ********************************************************************** ** ** ** LCS DEVICE CONTROL BLOCKS ** ** ** ********************************************************************** \**********************************************************************/ #define LCS_MAX_PORTS 4 struct _LCSBLK; struct _LCSDEV; struct _LCSPORT; struct _LCSRTE; struct _LCSHDR; struct _LCSCMDHDR; struct _LCSSTDFRM; struct _LCSSTRTFRM; struct _LCSQIPFRM; struct _LCSLSTFRM; struct _LCSIPMPAIR; struct _LCSIPMFRM; struct _LCSETHFRM; typedef struct _LCSBLK LCSBLK, *PLCSBLK; typedef struct _LCSDEV LCSDEV, *PLCSDEV; typedef struct _LCSPORT LCSPORT, *PLCSPORT; typedef struct _LCSRTE LCSRTE, *PLCSRTE; typedef struct _LCSHDR LCSHDR, *PLCSHDR; typedef struct _LCSCMDHDR LCSCMDHDR, *PLCSCMDHDR; typedef struct _LCSSTDFRM LCSSTDFRM, *PLCSSTDFRM; typedef struct _LCSSTRTFRM LCSSTRTFRM, *PLCSSTRTFRM; typedef struct _LCSQIPFRM LCSQIPFRM, *PLCSQIPFRM; typedef struct _LCSLSTFRM LCSLSTFRM, *PLCSLSTFRM; typedef struct _LCSIPMPAIR LCSIPMPAIR, *PLCSIPMPAIR; typedef struct _LCSIPMFRM LCSIPMFRM, *PLCSIPMFRM; typedef struct _LCSETHFRM LCSETHFRM, *PLCSETHFRM; // -------------------------------------------------------------------- // LCS Device (host byte order) // -------------------------------------------------------------------- struct _LCSDEV { U16 sAddr; // Device Base Address BYTE bMode; // (see below #defines) BYTE bPort; // Relative Adapter No. BYTE bType; // (see below #defines) char* pszIPAddress; // IP Address (string) U32 lIPAddress; // IP Address (binary), // (network byte order) PLCSBLK pLCSBLK; // -> LCSBLK DEVBLK* pDEVBLK[2]; // 0 - Read subchannel // 1 - Write cubchannel U16 iMaxFrameBufferSize; // Device Buffer Size BYTE bFrameBuffer[CTC_FRAME_BUFFER_SIZE]; // (this really SHOULD be dynamically allocated!) U16 iFrameOffset; // Curr Offset into Buffer LOCK Lock; // Data LOCK LOCK EventLock; // Condition LOCK COND Event; // Condition signal u_int fCreated:1; // DEVBLK(s) Created u_int fStarted:1; // Device Started u_int fRouteAdded:1; // Routing Added u_int fReplyPending:1; // Cmd Reply is Pending u_int fDataPending:1; // Data is Pending PLCSDEV pNext; // Next device }; #define LCSDEV_MODE_IP 0x01 #define LCSDEV_MODE_SNA 0x02 #define LCSDEV_TYPE_NONE 0x00 #define LCSDEV_TYPE_PRIMARY 0x01 #define LCSDEV_TYPE_SECONDARY 0x02 // -------------------------------------------------------------------- // LCS Port (or Relative Adapter) (host byte order) // -------------------------------------------------------------------- struct _LCSPORT { BYTE bPort; // Relative Adapter No MAC MAC_Address; // MAC Address of Adapter PLCSRTE pRoutes; // -> Routes chain PLCSBLK pLCSBLK; // -> LCSBLK U16 sIPAssistsSupported; // IP Assist Info U16 sIPAssistsEnabled; LOCK Lock; // Data LOCK LOCK EventLock; // Condition LOCK COND Event; // Condition signal u_int fUsed:1; // Port is used u_int fLocalMAC:1; // MAC is specified in OAT u_int fCreated:1; // Interface Created u_int fStarted:1; // Startup Received u_int fRouteAdded:1; // Routing Added u_int fCloseInProgress:1; // Close in progress int fd; // TUN/TAP fd TID tid; // Read Thread ID pid_t pid; // Read Thread pid int icDevices; // Device count char szNetDevName[IFNAMSIZ]; // Network Device Name char szMACAddress[32]; // MAC Address char szGWAddress[32]; // Gateway for W32 }; // -------------------------------------------------------------------- // LCSRTE - Routing Entries (host byte order) // -------------------------------------------------------------------- struct _LCSRTE { char* pszNetAddr; char* pszNetMask; PLCSRTE pNext; }; // -------------------------------------------------------------------- // LCSBLK - Common Storage for LCS Emulation (host byte order) // -------------------------------------------------------------------- struct _LCSBLK { // Config line parameters char* pszTUNDevice; // TUN/TAP char device char* pszOATFilename; // OAT Filename char* pszIPAddress; // IP Address char* pszMACAddress; // MAC Address (string) MAC MAC_Address; // MAC Address (binary) u_int fDebug:1; int icDevices; // Number of devices int iKernBuff; // Kernel buffer in K bytes. int iIOBuff; // I/O buffer in K bytes. PLCSDEV pDevices; // -> Device chain LCSPORT Port[LCS_MAX_PORTS]; // Port Blocks // Self Describing Component Information char szSerialNumber[13]; }; /**********************************************************************\ ********************************************************************** ** ** ** LCS DEVICE FRAMES ** ** ** ********************************************************************** \**********************************************************************/ // -------------------------------------------------------------------- // LCS Frame Header (network byte order) // -------------------------------------------------------------------- struct _LCSHDR // *ALL* LCS Frames start with the following header { HWORD hwOffset; // Offset to next frame or 0 BYTE bType; // (see below #defines) BYTE bSlot; // (i.e. port) } ATTRIBUTE_PACKED; #define LCS_FRMTYP_CMD 0x00 // LCS command mode #define LCS_FRMTYP_ENET 0x01 // Ethernet Passthru #define LCS_FRMTYP_TR 0x02 // Token Ring #define LCS_FRMTYP_FDDI 0x07 // FDDI #define LCS_FRMTYP_AUTO 0xFF // auto-detect // -------------------------------------------------------------------- // LCS Command Frame Header (network byte order) // -------------------------------------------------------------------- struct _LCSCMDHDR // All LCS *COMMAND* Frames start with this header { LCSHDR bLCSHdr; // LCS Frame header BYTE bCmdCode; // (see below #defines) BYTE bInitiator; HWORD hwSequenceNo; HWORD hwReturnCode; BYTE bLanType; // usually LCS_FRMTYP_ENET BYTE bRelAdapterNo; // (i.e. port) } ATTRIBUTE_PACKED; #define LCS_CMD_TIMING 0x00 // Timing request #define LCS_CMD_STRTLAN 0x01 // Start LAN #define LCS_CMD_STOPLAN 0x02 // Stop LAN #define LCS_CMD_GENSTAT 0x03 // Generate Stats #define LCS_CMD_LANSTAT 0x04 // LAN Stats #define LCS_CMD_LISTLAN 0x06 // List LAN #define LCS_CMD_STARTUP 0x07 // Start Host #define LCS_CMD_SHUTDOWN 0x08 // Shutdown Host #define LCS_CMD_LISTLAN2 0x0B // List LAN (another version) #define LCS_CMD_QIPASSIST 0xB2 // Query IP Assists #define LCS_CMD_SETIPM 0xB4 // Set IP Multicast #define LCS_CMD_DELIPM 0xB5 // Delete IP Multicast // -------------------------------------------------------------------- // LCS Standard Command Frame (network byte order) // -------------------------------------------------------------------- struct _LCSSTDFRM { LCSCMDHDR bLCSCmdHdr; // LCS Command Frame header HWORD hwParameterCount; BYTE bOperatorFlags[3]; BYTE _reserved[3]; BYTE bData[FLEXIBLE_ARRAY]; } ATTRIBUTE_PACKED; // -------------------------------------------------------------------- // LCS Startup Command Frame (network byte order) // -------------------------------------------------------------------- struct _LCSSTRTFRM { LCSCMDHDR bLCSCmdHdr; // LCS Command Frame header HWORD hwBufferSize; BYTE _unused2[6]; } ATTRIBUTE_PACKED; // -------------------------------------------------------------------- // LCS Query IP Assists Command Frame (network byte order) // -------------------------------------------------------------------- struct _LCSQIPFRM { LCSCMDHDR bLCSCmdHdr; // LCS Command Frame header HWORD hwNumIPPairs; HWORD hwIPAssistsSupported; HWORD hwIPAssistsEnabled; HWORD hwIPVersion; } ATTRIBUTE_PACKED; #define LCS_ARP_PROCESSING 0x0001 #define LCS_INBOUND_CHECKSUM_SUPPORT 0x0002 #define LCS_OUTBOUND_CHECKSUM_SUPPORT 0x0004 #define LCS_IP_FRAG_REASSEMBLY 0x0008 #define LCS_IP_FILTERING 0x0010 #define LCS_IP_V6_SUPPORT 0x0020 #define LCS_MULTICAST_SUPPORT 0x0040 // -------------------------------------------------------------------- // LCS LAN Statistics Command Frame (network byte order) // -------------------------------------------------------------------- struct _LCSLSTFRM { LCSCMDHDR bLCSCmdHdr; // LCS Command Frame header BYTE _unused1[10]; MAC MAC_Address; // MAC Address of Adapter FWORD fwPacketsDeblocked; FWORD fwPacketsBlocked; FWORD fwTX_Packets; FWORD fwTX_Errors; FWORD fwTX_PacketsDiscarded; FWORD fwRX_Packets; FWORD fwRX_Errors; FWORD fwRX_DiscardedNoBuffs; U32 fwRX_DiscardedTooLarge; } ATTRIBUTE_PACKED; // -------------------------------------------------------------------- // LCS Set IP Multicast Command Frame (network byte order) // -------------------------------------------------------------------- struct _LCSIPMPAIR { U32 IP_Addr; MAC MAC_Address; // MAC Address of Adapter BYTE _reserved[2]; } ATTRIBUTE_PACKED; #define MAX_IP_MAC_PAIRS 32 struct _LCSIPMFRM { LCSCMDHDR bLCSCmdHdr; // LCS Command Frame header HWORD hwNumIPPairs; U16 hwIPAssistsSupported; U16 hwIPAssistsEnabled; U16 hwIPVersion; LCSIPMPAIR IP_MAC_Pair[MAX_IP_MAC_PAIRS]; U32 fwResponseData; } ATTRIBUTE_PACKED; // -------------------------------------------------------------------- // LCS Ethernet Passthru Frame (network byte order) // -------------------------------------------------------------------- struct _LCSETHFRM { LCSHDR bLCSHdr; // LCS Frame header BYTE bData[FLEXIBLE_ARRAY]; // Ethernet Frame } ATTRIBUTE_PACKED; /**********************************************************************\ ********************************************************************** ** ** ** INLINE FUNCTIONS ** ** ** ********************************************************************** \**********************************************************************/ // -------------------------------------------------------------------- // Set SenseID Information // -------------------------------------------------------------------- static inline void SetSIDInfo( DEVBLK* pDEVBLK, U16 wCUType, BYTE bCUMod, U16 wDevType, BYTE bDevMod ) { BYTE* pSIDInfo = pDEVBLK->devid; memset( pSIDInfo, 0, 256 ); *pSIDInfo++ = 0x0FF; *pSIDInfo++ = (BYTE)(( wCUType >> 8 ) & 0x00FF ); *pSIDInfo++ = (BYTE)( wCUType & 0x00FF ); *pSIDInfo++ = bCUMod; *pSIDInfo++ = (BYTE)(( wDevType >> 8 ) & 0x00FF ); *pSIDInfo++ = (BYTE)( wDevType & 0x00FF ); *pSIDInfo++ = bDevMod; *pSIDInfo++ = 0x00; pDEVBLK->numdevid = 7; } // -------------------------------------------------------------------- // Set SenseID CIW Information // -------------------------------------------------------------------- static inline void SetCIWInfo( DEVBLK* pDEVBLK, U16 bOffset, BYTE bCIWType, BYTE bCIWOp, U16 wCIWCount ) { BYTE* pSIDInfo = pDEVBLK->devid; pSIDInfo += 8; pSIDInfo += ( bOffset * 4 ); *pSIDInfo++ = bCIWType | 0x40; *pSIDInfo++ = bCIWOp; *pSIDInfo++ = (BYTE)(( wCIWCount >> 8 ) & 0x00FF ); *pSIDInfo++ = (BYTE)( wCIWCount & 0x00FF ); pDEVBLK->numdevid += pDEVBLK->numdevid == 7 ? 5 : 4; } // -------------------------------------------------------------------- #if defined(_MSVC_) #pragma pack(pop) #endif #endif // __CTCADPT_H_ hercules-3.07/dasdblks.h000644 000765 000765 00000055523 11143760543 016721 0ustar00jmaynardjmaynard000000 000000 /* DASDBLKS.H (c) Copyright Roger Bowler, 1999-2009 */ /* DASD control block structures */ // $Id: dasdblks.h 5125 2009-01-23 12:01:44Z bernard $ /*-------------------------------------------------------------------*/ /* This header file contains definitions of OS Data Management */ /* control block structures for use by the Hercules DASD utilities. */ /* It also contains function prototypes for the DASD utilities. */ /*-------------------------------------------------------------------*/ // $Log$ // Revision 1.21 2007/06/23 00:04:08 ivan // Update copyright notices to include current year (2007) // // Revision 1.20 2006/12/08 09:43:19 jj // Add CVS message log // #include "hercules.h" #ifndef _DASDUTIL_C_ #ifndef _HDASD_DLL_ #define DUT_DLL_IMPORT DLL_IMPORT #else /* _HDASD_DLL_ */ #define DUT_DLL_IMPORT extern #endif /* _HDASD_DLL_ */ #else #define DUT_DLL_IMPORT DLL_EXPORT #endif // Forward references... typedef struct FORMAT1_DSCB FORMAT1_DSCB; // DSCB1: Dataset descriptor typedef struct FORMAT3_DSCB FORMAT3_DSCB; // DSCB3: Additional extents typedef struct FORMAT4_DSCB FORMAT4_DSCB; // DSCB4: VTOC descriptor typedef struct FORMAT5_DSCB FORMAT5_DSCB; // DSCB5: Free space map typedef struct F5AVEXT F5AVEXT; // Available extent in DSCB5 typedef struct DSXTENT DSXTENT; // Dataset extent descriptor typedef struct PDSDIR PDSDIR; // PDS directory entry typedef struct CIFBLK CIFBLK; // CKD image file descriptor typedef struct COPYR1 COPYR1; // IEBCOPY header record 1 typedef struct COPYR2 COPYR2; // IEBCOPY header record 2 typedef struct DATABLK DATABLK; // IEBCOPY unload data rec #define MAX_TRACKS 32767 /*-------------------------------------------------------------------*/ /* Definition of DSCB records in VTOC */ /*-------------------------------------------------------------------*/ struct DSXTENT { /* Dataset extent descriptor */ BYTE xttype; /* Extent type */ BYTE xtseqn; /* Extent sequence number */ HWORD xtbcyl; /* Extent begin cylinder */ HWORD xtbtrk; /* Extent begin track */ HWORD xtecyl; /* Extent end cylinder */ HWORD xtetrk; /* Extent end track */ }; /* Bit definitions for extent type */ #define XTTYPE_UNUSED 0x00 /* Unused extent descriptor */ #define XTTYPE_DATA 0x01 /* Data extent */ #define XTTYPE_OVERFLOW 0x02 /* Overflow extent */ #define XTTYPE_INDEX 0x04 /* Index extent */ #define XTTYPE_USERLBL 0x40 /* User label extent */ #define XTTYPE_SHARCYL 0x80 /* Shared cylinders */ #define XTTYPE_CYLBOUND 0x81 /* Extent on cyl boundary */ struct FORMAT1_DSCB { /* DSCB1: Dataset descriptor */ BYTE ds1dsnam[44]; /* Key (44 byte dataset name)*/ BYTE ds1fmtid; /* Format identifier (0xF1) */ BYTE ds1dssn[6]; /* Volume serial number */ HWORD ds1volsq; /* Volume sequence number */ BYTE ds1credt[3]; /* Dataset creation date... ...byte 0: Binary year-1900 ...bytes 1-2: Binary day */ BYTE ds1expdt[3]; /* Dataset expiry date */ BYTE ds1noepv; /* Number of extents */ BYTE ds1bodbd; /* #bytes used in last dirblk*/ BYTE resv1; /* Reserved */ BYTE ds1syscd[13]; /* System code (IBMOSVS2) */ BYTE resv2[7]; /* Reserved */ BYTE ds1dsorg[2]; /* Dataset organization */ BYTE ds1recfm; /* Record format */ BYTE ds1optcd; /* Option codes */ HWORD ds1blkl; /* Block length */ HWORD ds1lrecl; /* Logical record length */ BYTE ds1keyl; /* Key length */ HWORD ds1rkp; /* Relative key position */ BYTE ds1dsind; /* Dataset indicators */ FWORD ds1scalo; /* Secondary allocation... ...byte 0: Allocation units ...bytes 1-3: Quantity */ BYTE ds1lstar[3]; /* Last used TTR */ HWORD ds1trbal; /* Bytes unused on last trk */ BYTE resv3[2]; /* Reserved */ DSXTENT ds1ext1; /* First extent descriptor */ DSXTENT ds1ext2; /* Second extent descriptor */ DSXTENT ds1ext3; /* Third extent descriptor */ BYTE ds1ptrds[5]; /* CCHHR of F2 or F3 DSCB */ }; /* Bit definitions for ds1dsind */ #define DS1DSIND_LASTVOL 0x80 /* Last volume of dataset */ #define DS1DSIND_RACFIND 0x40 /* RACF indicated */ #define DS1DSIND_BLKSIZ8 0x20 /* Blocksize multiple of 8 */ #define DS1DSIND_PASSWD 0x10 /* Password protected */ #define DS1DSIND_WRTPROT 0x04 /* Write protected */ #define DS1DSIND_UPDATED 0x02 /* Updated since last backup */ #define DS1DSIND_SECCKPT 0x01 /* Secure checkpoint dataset */ /* Bit definitions for ds1optcd */ #define DS1OPTCD_ICFDSET 0x80 /* Dataset in ICF catalog */ #define DS1OPTCD_ICFCTLG 0x40 /* ICF catalog */ /* Bit definitions for ds1scalo byte 0 */ #define DS1SCALO_UNITS 0xC0 /* Allocation units... */ #define DS1SCALO_UNITS_ABSTR 0x00 /* ...absolute tracks */ #define DS1SCALO_UNITS_BLK 0x40 /* ...blocks */ #define DS1SCALO_UNITS_TRK 0x80 /* ...tracks */ #define DS1SCALO_UNITS_CYL 0xC0 /* ...cylinders */ #define DS1SCALO_CONTIG 0x08 /* Contiguous space */ #define DS1SCALO_MXIG 0x04 /* Maximum contiguous extent */ #define DS1SCALO_ALX 0x02 /* Up to 5 largest extents */ #define DS1SCALO_ROUND 0x01 /* Round to cylinders */ struct FORMAT3_DSCB { /* DSCB3: Additional extents */ BYTE ds3keyid[4]; /* Key (4 bytes of 0x03) */ DSXTENT ds3extnt[4]; /* Four extent descriptors */ BYTE ds3fmtid; /* Format identifier (0xF3) */ DSXTENT ds3adext[9]; /* Nine extent descriptors */ BYTE ds3ptrds[5]; /* CCHHR of next F3 DSCB */ }; struct FORMAT4_DSCB { /* DSCB4: VTOC descriptor */ BYTE ds4keyid[44]; /* Key (44 bytes of 0x04) */ BYTE ds4fmtid; /* Format identifier (0xF4) */ BYTE ds4hpchr[5]; /* CCHHR of highest F1 DSCB */ HWORD ds4dsrec; /* Number of format 0 DSCBs */ BYTE ds4hcchh[4]; /* CCHH of next avail alt trk*/ HWORD ds4noatk; /* Number of avail alt tracks*/ BYTE ds4vtoci; /* VTOC indicators */ BYTE ds4noext; /* Number of extents in VTOC */ BYTE resv1[2]; /* Reserved */ FWORD ds4devsz; /* Device size (CCHH) */ HWORD ds4devtk; /* Device track length */ BYTE ds4devi; /* Non-last keyed blk overhd */ BYTE ds4devl; /* Last keyed block overhead */ BYTE ds4devk; /* Non-keyed block difference*/ BYTE ds4devfg; /* Device flags */ HWORD ds4devtl; /* Device tolerance */ BYTE ds4devdt; /* Number of DSCBs per track */ BYTE ds4devdb; /* Number of dirblks/track */ DBLWRD ds4amtim; /* VSAM timestamp */ BYTE ds4vsind; /* VSAM indicators */ HWORD ds4vscra; /* CRA track location */ DBLWRD ds4r2tim; /* VSAM vol/cat timestamp */ BYTE resv2[5]; /* Reserved */ BYTE ds4f6ptr[5]; /* CCHHR of first F6 DSCB */ DSXTENT ds4vtoce; /* VTOC extent descriptor */ BYTE resv3[25]; /* Reserved */ }; /* Bit definitions for ds4vtoci */ #define DS4VTOCI_DOS 0x80 /* Format 5 DSCBs not valid */ #define DS4VTOCI_DOSSTCK 0x10 /* DOS stacked pack */ #define DS4VTOCI_DOSCNVT 0x08 /* DOS converted pack */ #define DS4VTOCI_DIRF 0x40 /* VTOC contains errors */ #define DS4VTOCI_DIRFCVT 0x20 /* DIRF reclaimed */ /* Bit definitions for ds4devfg */ #define DS4DEVFG_TOL 0x01 /* Tolerance factor applies to all but last block of trk */ struct F5AVEXT { /* Available extent in DSCB5 */ HWORD btrk; /* Extent begin track address*/ HWORD ncyl; /* Number of full cylinders */ BYTE ntrk; /* Number of odd tracks */ }; struct FORMAT5_DSCB { /* DSCB5: Free space map */ BYTE ds5keyid[4]; /* Key (4 bytes of 0x05) */ F5AVEXT ds5avext[8]; /* First 8 available extents */ BYTE ds5fmtid; /* Format identifier (0xF5) */ F5AVEXT ds5mavet[18]; /* 18 more available extents */ BYTE ds5ptrds[5]; /* CCHHR of next F5 DSCB */ }; /*-------------------------------------------------------------------*/ /* Definitions of DSORG and RECFM fields */ /*-------------------------------------------------------------------*/ /* Bit settings for dataset organization byte 0 */ #define DSORG_IS 0x80 /* Indexed sequential */ #define DSORG_PS 0x40 /* Physically sequential */ #define DSORG_DA 0x20 /* Direct access */ #define DSORG_PO 0x02 /* Partitioned organization */ #define DSORG_U 0x01 /* Unmovable */ /* Bit settings for dataset organization byte 1 */ #define DSORG_AM 0x08 /* VSAM dataset */ /* Bit settings for record format */ #define RECFM_FORMAT 0xC0 /* Bits 0-1=Record format */ #define RECFM_FORMAT_V 0x40 /* ...variable length */ #define RECFM_FORMAT_F 0x80 /* ...fixed length */ #define RECFM_FORMAT_U 0xC0 /* ...undefined length */ #define RECFM_TRKOFLOW 0x20 /* Bit 2=Track overflow */ #define RECFM_BLOCKED 0x10 /* Bit 3=Blocked */ #define RECFM_SPANNED 0x08 /* Bit 4=Spanned or standard */ #define RECFM_CTLCHAR 0x06 /* Bits 5-6=Carriage control */ #define RECFM_CTLCHAR_A 0x04 /* ...ANSI carriage control */ #define RECFM_CTLCHAR_M 0x02 /* ...Machine carriage ctl. */ /*-------------------------------------------------------------------*/ /* Definition of PDS directory entry */ /*-------------------------------------------------------------------*/ struct PDSDIR { /* PDS directory entry */ BYTE pds2name[8]; /* Member name */ BYTE pds2ttrp[3]; /* TTR of first block */ BYTE pds2indc; /* Indicator byte */ BYTE pds2usrd[62]; /* User data (0-31 halfwords)*/ }; /* Bit definitions for PDS directory indicator byte */ #define PDS2INDC_ALIAS 0x80 /* Bit 0: Name is an alias */ #define PDS2INDC_NTTR 0x60 /* Bits 1-2: User TTR count */ #define PDS2INDC_NTTR_SHIFT 5 /* Shift count for NTTR */ #define PDS2INDC_LUSR 0x1F /* Bits 3-7: User halfwords */ /*-------------------------------------------------------------------*/ /* Text unit keys for transmit/receive */ /*-------------------------------------------------------------------*/ #define INMDDNAM 0x0001 /* DDNAME for the file */ #define INMDSNAM 0x0002 /* Name of the file */ #define INMMEMBR 0x0003 /* Member name list */ #define INMSECND 0x000B /* Secondary space quantity */ #define INMDIR 0x000C /* Directory space quantity */ #define INMEXPDT 0x0022 /* Expiration date */ #define INMTERM 0x0028 /* Data transmitted as msg */ #define INMBLKSZ 0x0030 /* Block size */ #define INMDSORG 0x003C /* File organization */ #define INMLRECL 0x0042 /* Logical record length */ #define INMRECFM 0x0049 /* Record format */ #define INMTNODE 0x1001 /* Target node name/number */ #define INMTUID 0x1002 /* Target user ID */ #define INMFNODE 0x1011 /* Origin node name/number */ #define INMFUID 0x1012 /* Origin user ID */ #define INMLREF 0x1020 /* Date last referenced */ #define INMLCHG 0x1021 /* Date last changed */ #define INMCREAT 0x1022 /* Creation date */ #define INMFVERS 0x1023 /* Origin vers# of data fmt */ #define INMFTIME 0x1024 /* Origin timestamp */ #define INMTTIME 0x1025 /* Destination timestamp */ #define INMFACK 0x1026 /* Originator request notify */ #define INMERRCD 0x1027 /* RECEIVE command error code*/ #define INMUTILN 0x1028 /* Name of utility program */ #define INMUSERP 0x1029 /* User parameter string */ #define INMRECCT 0x102A /* Transmitted record count */ #define INMSIZE 0x102C /* File size in bytes */ #define INMFFM 0x102D /* Filemode number */ #define INMNUMF 0x102F /* #of files transmitted */ #define INMTYPE 0x8012 /* Dataset type */ /*-------------------------------------------------------------------*/ /* Definitions of IEBCOPY header records */ /*-------------------------------------------------------------------*/ struct COPYR1 { /* IEBCOPY header record 1 */ BYTE uldfmt; /* Unload format */ BYTE hdrid[3]; /* Header identifier */ HWORD ds1dsorg; /* Dataset organization */ HWORD ds1blkl; /* Block size */ HWORD ds1lrecl; /* Logical record length */ BYTE ds1recfm; /* Record format */ BYTE ds1keyl; /* Key length */ BYTE ds1optcd; /* Option codes */ BYTE ds1smsfg; /* SMS indicators */ HWORD uldblksz; /* Block size of container */ /* Start of DEVTYPE fields */ FWORD ucbtype; /* Original device type */ FWORD maxblksz; /* Maximum block size */ HWORD cyls; /* Number of cylinders */ HWORD heads; /* Number of tracks/cylinder */ HWORD tracklen; /* Track length */ HWORD overhead; /* Block overhead */ BYTE keyovhead; /* Keyed block overhead */ BYTE devflags; /* Flags */ HWORD tolerance; /* Tolerance factor */ /* End of DEVTYPE fields */ HWORD hdrcount; /* Number of header records (if zero, then 2 headers) */ BYTE resv1; /* Reserved */ BYTE ds1refd[3]; /* Last reference date */ BYTE ds1scext[3]; /* Secondary space extension */ BYTE ds1scalo[4]; /* Secondary allocation */ BYTE ds1lstar[3]; /* Last track used TTR */ HWORD ds1trbal; /* Last track balance */ HWORD resv2; /* Reserved */ }; /* Bit settings for unload format byte */ #define COPYR1_ULD_FORMAT 0xC0 /* Bits 0-1=unload format... */ #define COPYR1_ULD_FORMAT_OLD 0x00 /* ...old format */ #define COPYR1_ULD_FORMAT_PDSE 0x40 /* ...PDSE format */ #define COPYR1_ULD_FORMAT_ERROR 0x80 /* ...error during unload */ #define COPYR1_ULD_FORMAT_XFER 0xC0 /* ...transfer format */ #define COPYR1_ULD_PROGRAM 0x10 /* Bit 3=Contains programs */ #define COPYR1_ULD_PDSE 0x01 /* Bit 7=Contains PDSE */ /* Bit settings for header identifier */ #define COPYR1_HDRID "\xCA\x6D\x0F" /* Constant value for hdrid */ struct COPYR2 { /* IEBCOPY header record 2 */ BYTE debbasic[16]; /* Last 16 bytes of basic section of original DEB */ BYTE debxtent[16][16]; /* First 16 extent descriptors from original DEB */ FWORD resv; /* Reserved */ }; /*-------------------------------------------------------------------*/ /* Definition of data record block in IEBCOPY unload file */ /*-------------------------------------------------------------------*/ struct DATABLK { /* IEBCOPY unload data rec */ FWORD header; /* Reserved */ HWORD cyl; /* Cylinder number */ HWORD head; /* Head number */ BYTE rec; /* Record number */ BYTE klen; /* Key length */ HWORD dlen; /* Data length */ #define MAX_DATALEN 32767 BYTE kdarea[MAX_DATALEN]; /* Key and data area */ }; /*-------------------------------------------------------------------*/ /* Internal structures used by DASD utility functions */ /*-------------------------------------------------------------------*/ struct CIFBLK { /* CKD image file descriptor */ char *fname; /* -> CKD image file name */ int fd; /* CKD image file descriptor */ int trksz; /* CKD image track size */ BYTE *trkbuf; /* -> Track buffer */ int curcyl; /* Cylinder number of track currently in track buffer */ int curhead; /* Head number of track currently in track buffer */ int trkmodif; /* 1=Track has been modified */ int heads; /* Tracks per cylinder */ DEVBLK devblk; /* Device Block */ }; /*-------------------------------------------------------------------*/ /* Macro definitions */ /*-------------------------------------------------------------------*/ #define ROUND_UP(x,y) (((x)+(y)-1)/(y)*(y)) /*-------------------------------------------------------------------*/ /* Function prototypes */ /*-------------------------------------------------------------------*/ /* Functions in module dasdutil.c */ DUT_DLL_IMPORT void string_to_upper (char *source); DUT_DLL_IMPORT void string_to_lower (char *source); DUT_DLL_IMPORT void convert_to_ebcdic (BYTE *dest, int len, char *source); DUT_DLL_IMPORT int make_asciiz (char *dest, int destlen, BYTE *src, int srclen); DUT_DLL_IMPORT void data_dump (void *addr, int len); DUT_DLL_IMPORT int read_track (CIFBLK *cif, int cyl, int head); int rewrite_track (CIFBLK *cif); DUT_DLL_IMPORT int read_block (CIFBLK *cif, int cyl, int head, int rec, BYTE **keyptr, int *keylen, BYTE **dataptr, int *datalen); DUT_DLL_IMPORT int search_key_equal (CIFBLK *cif, BYTE *key, int keylen, int noext, DSXTENT extent[], int *cyl, int *head, int *rec); DUT_DLL_IMPORT int convert_tt (int tt, int noext, DSXTENT extent[], int heads, int *cyl, int *head); DUT_DLL_IMPORT CIFBLK* open_ckd_image (char *fname, char *sfname, int omode, int dasdcopy); DUT_DLL_IMPORT CIFBLK* open_fba_image (char *fname, char *sfname, int omode, int dasdcopy); DUT_DLL_IMPORT int close_ckd_image (CIFBLK *cif); #define close_image_file(cif) close_ckd_image((cif)) DUT_DLL_IMPORT int build_extent_array (CIFBLK *cif, char *dsnama, DSXTENT extent[], int *noext); DUT_DLL_IMPORT int capacity_calc (CIFBLK *cif, int used, int keylen, int datalen, int *newused, int *trkbaln, int *physlen, int *kbconst, int *lbconst, int *nkconst, BYTE*devflag, int *tolfact, int *maxdlen, int *numrecs, int *numhead, int *numcyls); DUT_DLL_IMPORT int create_ckd (char *fname, U16 devtype, U32 heads, U32 maxdlen, U32 volcyls, char *volser, BYTE comp, int lfs, int dasdcopy, int nullfmt, int rawflag); DUT_DLL_IMPORT int create_fba (char *fname, U16 devtype, U32 sectsz, U32 sectors, char *volser, BYTE comp, int lfs, int dasdcopy, int rawflag); int create_compressed_fba (char *fname, U16 devtype, U32 sectsz, U32 sectors, char *volser, BYTE comp, int lfs, int dasdcopy, int rawflag); int get_verbose_util(void); DUT_DLL_IMPORT void set_verbose_util(int v); #define DEFAULT_FBA_TYPE 0x3370 hercules-3.07/dasdcat.c000644 000765 000765 00000016761 11143760544 016532 0ustar00jmaynardjmaynard000000 000000 /* * dasdcat * * Vast swathes copied from dasdpdsu.c (c) Copyright Roger Bowler, 1999-2009 * Changes and additions Copyright 2000-2009 by Malcolm Beattie * * $Id: dasdcat.c 5125 2009-01-23 12:01:44Z bernard $ * * $Log$ * Revision 1.33 2008/11/04 04:50:45 fish * Ensure consistent utility startup * * Revision 1.32 2007/06/23 00:04:08 ivan * Update copyright notices to include current year (2007) * * Revision 1.31 2006/12/08 09:43:19 jj * Add CVS message log * */ #include "hstdinc.h" #include "hercules.h" #include "dasdblks.h" #ifdef WIN32 #include // (setmode) #endif /* Option flags */ #define OPT_ASCIIFY 0x1 #define OPT_CARDS 0x2 #define OPT_PDS_WILDCARD 0x4 #define OPT_PDS_LISTONLY 0x8 #define OPT_SEQNO 0x10 int end_of_track(BYTE *p) { return p[0] == 0xff && p[1] == 0xff && p[2] == 0xff && p[3] == 0xff && p[4] == 0xff && p[5] == 0xff && p[6] == 0xff && p[7] == 0xff; } int do_cat_cards(BYTE *buf, int len, unsigned long optflags) { if (len % 80 != 0) { fprintf(stderr, _("HHCDT002E Can't make 80 column card images from block length %d\n"), len); return -1; } while (len) { char card[81]; make_asciiz(card, sizeof(card), buf, (optflags & OPT_SEQNO) ? 80 : 72); if (optflags & OPT_PDS_WILDCARD) { putchar('|'); putchar(' '); } puts(card); len -= 80; buf += 80; } return 0; } int process_member(CIFBLK *cif, int noext, DSXTENT extent[], BYTE *ttr, unsigned long optflags) { int rc, trk, len, cyl, head, rec; BYTE *buf; set_codepage(NULL); trk = (ttr[0] << 8) | ttr[1]; rec = ttr[2]; while (1) { rc = convert_tt(trk, noext, extent, cif->heads, &cyl, &head); if (rc < 0) return -1; rc = read_block(cif, cyl, head, rec, 0, 0, &buf, &len); if (rc < 0) return -1; if (rc > 0) { trk++; rec = 1; continue; } if (len == 0) break; if (optflags & OPT_CARDS) do_cat_cards(buf, len, optflags); else if (optflags & OPT_ASCIIFY) { BYTE *p; for (p = buf; len--; p++) putchar(guest_to_host(*p)); } else { #if O_BINARY != 0 setmode(fileno(stdout),O_BINARY); #endif fwrite(buf, len, 1, stdout); } rec++; } return 0; } int process_dirblk(CIFBLK *cif, int noext, DSXTENT extent[], BYTE *dirblk, char *pdsmember, unsigned long optflags) { int rc; int dirrem; char memname[9]; /* Load number of bytes in directory block */ dirrem = (dirblk[0] << 8) | dirblk[1]; if (dirrem < 2 || dirrem > 256) { fprintf(stderr, _("HHCDT003E Directory block byte count is invalid\n")); return -1; } if (!strcmp(pdsmember, "*")) optflags |= OPT_PDS_WILDCARD; else if (!strcmp(pdsmember, "?")) optflags |= OPT_PDS_LISTONLY; /* Point to first directory entry */ dirblk += 2; dirrem -= 2; while (dirrem > 0) { PDSDIR *dirent = (PDSDIR*)dirblk; int k, size; if (end_of_track(dirent->pds2name)) return 1; make_asciiz(memname, sizeof(memname), dirent->pds2name, 8); if (optflags & OPT_PDS_LISTONLY) { char memname_lc[9]; memcpy(memname_lc, memname, sizeof(memname)); string_to_lower(memname_lc); puts(memname_lc); } else if ((optflags & OPT_PDS_WILDCARD) || !strcmp(pdsmember, memname)) { if (optflags & OPT_PDS_WILDCARD) printf("> Member %s\n", memname); rc = process_member(cif, noext, extent, dirent->pds2ttrp, optflags); if (rc < 0) return -1; } /* Load the user data halfword count */ k = dirent->pds2indc & PDS2INDC_LUSR; /* Point to next directory entry */ size = 12 + k*2; dirblk += size; dirrem -= size; } return 0; } int do_cat_pdsmember(CIFBLK *cif, DSXTENT *extent, int noext, char *pdsmember, unsigned long optflags) { int rc, trk, rec; /* Point to the start of the directory */ trk = 0; rec = 1; /* Read the directory */ while (1) { BYTE *blkptr; BYTE dirblk[256]; int cyl, head, len; #ifdef EXTERNALGUI if (extgui) fprintf(stderr,"CTRK=%d\n",trk); #endif /*EXTERNALGUI*/ rc = convert_tt(trk, noext, extent, cif->heads, &cyl, &head); if (rc < 0) return -1; rc = read_block(cif, cyl, head, rec, 0, 0, &blkptr, &len); if (rc < 0) return -1; if (rc > 0) { trk++; rec = 1; continue; } if (len == 0) break; memcpy(dirblk, blkptr, sizeof(dirblk)); rc = process_dirblk(cif, noext, extent, dirblk, pdsmember, optflags); if (rc < 0) return -1; if (rc > 0) break; rec++; } return rc; } int do_cat_nonpds(CIFBLK *cif, DSXTENT *extent, int noext, unsigned long optflags) { UNREFERENCED(cif); UNREFERENCED(extent); UNREFERENCED(noext); UNREFERENCED(optflags); fprintf(stderr, _("HHCDT004E non-PDS-members not yet supported\n")); return -1; } int do_cat(CIFBLK *cif, char *file) { int rc; DSXTENT extent[16]; int noext; char buff[100]; /* must fit max length DSNAME/MEMBER..OPTS */ char dsname[45]; unsigned long optflags = 0; char *p; char *pdsmember = 0; if (!cif) return 1; strncpy(buff, file, sizeof(buff)); buff[sizeof(buff)-1] = 0; p = strchr(buff, ':'); if (p) { *p++ = 0; for (; *p; p++) { if (*p == 'a') optflags |= OPT_ASCIIFY; else if (*p == 'c') optflags |= OPT_CARDS; else if (*p == 's') optflags |= OPT_SEQNO; else fprintf(stderr, _("HHCDT005E unknown dataset name option: '%c'\n"), *p); } } p = strchr(buff, '/'); if (p) { *p = 0; pdsmember = p + 1; string_to_upper(pdsmember); } strncpy(dsname, buff, sizeof(dsname)); dsname[sizeof(dsname)-1] = 0; string_to_upper(dsname); rc = build_extent_array(cif, dsname, extent, &noext); if (rc < 0) return -1; #ifdef EXTERNALGUI /* Calculate ending relative track */ if (extgui) { int bcyl; /* Extent begin cylinder */ int btrk; /* Extent begin head */ int ecyl; /* Extent end cylinder */ int etrk; /* Extent end head */ int trks; /* total tracks in dataset */ int i; /* loop control */ for (i = 0, trks = 0; i < noext; i++) { bcyl = (extent[i].xtbcyl[0] << 8) | extent[i].xtbcyl[1]; btrk = (extent[i].xtbtrk[0] << 8) | extent[i].xtbtrk[1]; ecyl = (extent[i].xtecyl[0] << 8) | extent[i].xtecyl[1]; etrk = (extent[i].xtetrk[0] << 8) | extent[i].xtetrk[1]; trks += (((ecyl*cif->heads)+etrk)-((bcyl*cif->heads)+btrk))+1; } fprintf(stderr,"ETRK=%d\n",trks-1); } #endif /*EXTERNALGUI*/ if (pdsmember) rc = do_cat_pdsmember(cif, extent, noext, pdsmember, optflags); else rc = do_cat_nonpds(cif, extent, noext, optflags); return rc; } int main(int argc, char **argv) { int rc = 0; CIFBLK *cif = 0; char *fn, *sfn; INITIALIZE_UTILITY("dasdcat"); /* Display program info message */ display_version (stderr, "Hercules DASD cat program ", FALSE); if (argc < 2) { fprintf(stderr, "Usage: dasdcat [-i dasd_image [sf=shadow-file-name] dsname...]...\n"); fprintf(stderr, " dsname can (currently must) be pdsname/spec\n"); fprintf(stderr, " spec is memname[:flags], * (all) or ? (list)\n"); fprintf(stderr, " flags can include (c)ard images, (a)scii\n"); exit(2); } /* * If your version of Hercules doesn't have support in its * dasdutil.c for turning off verbose messages, then remove * the following line but you'll have to live with chatty * progress output on stdout. */ set_verbose_util(0); while (*++argv) { if (!strcmp(*argv, "-i")) { fn = *++argv; if (*(argv+1) && strlen (*(argv+1)) > 3 && !memcmp(*(argv+1), "sf=", 3)) sfn = *++argv; else sfn = NULL; if (cif) { close_ckd_image(cif); cif = 0; } cif = open_ckd_image(fn, sfn, O_RDONLY | O_BINARY, 0); if (!cif) fprintf(stderr, _("HHCDT001E failed to open image %s\n"), *argv); } else { if (do_cat(cif, *argv)) rc = 1; } } if (cif) close_ckd_image(cif); return rc; } hercules-3.07/dasdconv.c000644 000765 000765 00000110764 11224164171 016720 0ustar00jmaynardjmaynard000000 000000 /* DASDCONV.C (c) Copyright Roger Bowler, 1999-2009 */ /* Hercules DASD Utilities: DASD image converter */ // $Id: dasdconv.c 5378 2009-06-02 21:23:43Z rbowler $ /*-------------------------------------------------------------------*/ /* This program converts a CKD disk image from HDR-30 format */ /* to the AWSCKD format used by Hercules. */ /* */ /* The program is invoked from the shell prompt using the command: */ /* */ /* dasdconv [options] infile outfile */ /* */ /* options -r means overwrite existing outfile */ /* -q means suppress progress messages */ /* -lfs creates one large output file (if supported) */ /* infile is the name of the HDR-30 format CKD image file */ /* ("-" means that the CKD image is read from stdin) */ /* If this module was compiled with HAVE_LIBZ option */ /* activated, then the input file may be compressed */ /* or uncompressed. Otherwise it must be uncompressed. */ /* outfile is the name of the AWSCKD image file to be created. */ /* If the image exceeds 2GB then multiple files will */ /* be created, with names suffixed _1, _2, etc. */ /* (except if the underlying file system supports files */ /* larger than 2GB and the -lfs option is specified). */ /* This program will not overwrite an existing file. */ /*-------------------------------------------------------------------*/ #include "hstdinc.h" #include "hercules.h" #include "dasdblks.h" #include "opcode.h" /*-------------------------------------------------------------------*/ /* Definition of HDR-30 CKD image headers */ /*-------------------------------------------------------------------*/ typedef struct _H30CKD_TRKHDR { /* Track header */ HWORD devcode; /* Device type code */ BYTE resv02[14]; /* Reserved */ HWORD cyl; /* Cylinder number */ HWORD head; /* Head number */ BYTE resv14[28]; /* Reserved */ } H30CKD_TRKHDR; typedef struct _H30CKD_RECHDR { /* Record header */ FWORD resv00; /* Reserved */ HWORD cyl; /* Cylinder number */ HWORD head; /* Head number */ BYTE rec; /* Record number */ BYTE klen; /* Key length */ HWORD dlen; /* Data length */ } H30CKD_RECHDR; #define H30CKD_TRKHDR_SIZE ((ssize_t)sizeof(H30CKD_TRKHDR)) #define H30CKD_RECHDR_SIZE ((ssize_t)sizeof(H30CKD_RECHDR)) /*-------------------------------------------------------------------*/ /* Static data areas */ /*-------------------------------------------------------------------*/ BYTE eighthexFF[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; BYTE twelvehex00[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; BYTE ebcdicvol1[] = {0xE5, 0xD6, 0xD3, 0xF1}; BYTE gz_magic_id[] = {0x1F, 0x8B}; BYTE ckd_ident[] = {0x43, 0x4B, 0x44, 0x5F}; /* CKD_ in ASCII */ /*-------------------------------------------------------------------*/ /* Definition of file descriptor for gzip and non-gzip builds */ /*-------------------------------------------------------------------*/ #if defined(HAVE_LIBZ) #define IFD gzFile #define IFREAD gzread #define IFCLOS gzclose #else /*!defined(HAVE_LIBZ)*/ #define IFD int #define IFREAD read #define IFCLOS close #endif /*!defined(HAVE_LIBZ)*/ /*-------------------------------------------------------------------*/ /* Subroutine to exit the program */ /*-------------------------------------------------------------------*/ void delayed_exit (int exit_code) { /* Delay exiting is to give the system * time to display the error message. */ usleep(100000); exit(exit_code); } #define EXIT(rc) delayed_exit(rc) /* (use this macro to exit) */ /*-------------------------------------------------------------------*/ /* Subroutine to display command syntax and exit */ /*-------------------------------------------------------------------*/ static void argexit ( int code ) { fprintf (stderr, "Syntax:\tdasdconv [options] infile outfile\n" "where:\n\tinfile = name of input HDR-30 CKD image file" " (\"-\" means stdin)\n" #if defined(HAVE_LIBZ) "\t\t (input file may be compressed)\n" #endif /*defined(HAVE_LIBZ)*/ "\toutfile = name of AWSCKD image file to be created\n" "options:\n\t-r = replace existing output file\n" "\t-q = suppress progress messages\n"); if (sizeof(off_t) > 4) fprintf(stderr, "\t-lfs = build one large output file\n"); EXIT(code); } /* end function argexit */ /*-------------------------------------------------------------------*/ /* Subroutine to read data from input file */ /* Input: */ /* ifd Input file descriptor */ /* ifname Input file name */ /* buf Address of input buffer */ /* reqlen Number of bytes requested */ /* offset Current offset in file (for error message only) */ /*-------------------------------------------------------------------*/ static void read_input_data (IFD ifd, char *ifname, BYTE *buf, int reqlen, U32 offset) { int rc; /* Return code */ int len = 0; /* Number of bytes read */ while (len < reqlen) { rc = IFREAD (ifd, buf + len, reqlen - len); if (rc == 0) break; if (rc < 0) { fprintf (stderr, "%s read error: %s\n", ifname, strerror(errno)); EXIT(3); } len += rc; } /* end while */ if (len < reqlen) { fprintf (stderr, "Unexpected end-of-file on %s\n" "Expected %d bytes at offset %8.8X," " found %d bytes\n", ifname, reqlen, offset, len); EXIT(3); } } /* end function read_input_data */ /*-------------------------------------------------------------------*/ /* Subroutine to locate next record in HDR-30 CKD track image */ /* Input: */ /* buf Pointer to start of track image buffer */ /* Input+Output: */ /* ppbuf Pointer to current position in track image buffer */ /* plen Length remaining in track image buffer */ /* Output: */ /* pkl Key length */ /* pkp Address of record key */ /* pdl Data length */ /* pdp Address of record data */ /* pcc Cylinder number */ /* phh Head number */ /* prn Record number */ /* Return value: */ /* 0=OK, 1=End of track, >1=Track format error detected */ /*-------------------------------------------------------------------*/ static int find_input_record (BYTE *buf, BYTE **ppbuf, int *plen, BYTE *pkl, BYTE **pkp, U16 *pdl, BYTE **pdp, U32 *pcc, U32 *phh, BYTE *prn) { H30CKD_RECHDR *hrec; /* Input record header */ U16 dlen; /* Data length */ BYTE klen; /* Key length */ int n; /* Integer work area */ UNREFERENCED(buf); /* End of track if not enough bytes remain in buffer */ if (*plen < H30CKD_RECHDR_SIZE) return 1; /* Point to record header */ hrec = (H30CKD_RECHDR*)(*ppbuf); /* End of track if record header is all zero */ if (memcmp(*ppbuf, twelvehex00, 12) == 0) return 1; /* Extract the key length and data length */ klen = hrec->klen; FETCH_HW (dlen, hrec->dlen); /* Check that the reserved bytes are all zero */ if (memcmp(hrec->resv00, twelvehex00, sizeof(hrec->resv00)) != 0) return 2; /* Check that the key and data do not overflow the buffer */ if (*plen < H30CKD_RECHDR_SIZE + klen + dlen) return 3; /* Return the cylinder, head, and record number */ FETCH_HW (*pcc, hrec->cyl); FETCH_HW (*phh, hrec->head); *prn = hrec->rec; /* Point past the record header to the key */ *plen -= H30CKD_RECHDR_SIZE; *ppbuf += H30CKD_RECHDR_SIZE; /* Return the key length and key pointer */ *pkl = klen; *pkp = *ppbuf; /* Point past the key to the data */ *plen -= klen; *ppbuf += klen; /* Return the data length and data pointer */ *pdl = dlen; *pdp = *ppbuf; /* Point past the data to the next record header */ *plen -= dlen; *ppbuf += dlen; /* Ensure next header starts on a fullword boundary */ if ((klen + dlen) & 3) { n = 4 - ((klen + dlen) % 4); *plen -= n; *ppbuf += n; } /* Issue progress message */ #if 0 fprintf (stderr, "+%4.4X cyl=%4.4X head=%4.4X rec=%2.2X" " kl=%2.2X dl=%4.4X trkbal=%d\n", (BYTE*)hrec-buf, *pcc, *phh, *prn, klen, dlen, *plen); #endif return 0; } /* end function find_input_record */ /*-------------------------------------------------------------------*/ /* Subroutine to open input HDR-30 CKD image file */ /* Input: */ /* ifname Input HDR-30 CKD image file name */ /* Output: */ /* devt Device type */ /* vcyls Number of primary cylinders on volume */ /* itrkl Input HDR-30 CKD image track length */ /* itrkb -> Track image buffer (containing 1st track image) */ /* volser Volume serial number (6 bytes ASCII + X'00') */ /* Return value: */ /* Input file descriptor */ /*-------------------------------------------------------------------*/ static IFD open_input_image (char *ifname, U16 *devt, U32 *vcyls, U32 *itrkl, BYTE **itrkb, BYTE *volser) { int rc; /* Return code */ H30CKD_TRKHDR h30trkhdr; /* Input track header */ IFD ifd; /* Input file descriptor */ int len; /* Length of input */ U16 code; /* Device type code */ U16 dt; /* Device type */ U32 cyls; /* Device size (pri+alt cyls)*/ U32 alts; /* Number of alternate cyls */ BYTE *itrkbuf; /* -> Input track buffer */ U32 itrklen; /* Input track length */ BYTE *pbuf; /* Current byte in input buf */ BYTE klen; /* Key length */ U16 dlen; /* Data length */ BYTE *kptr; /* -> Key in input buffer */ BYTE *dptr; /* -> Data in input buffer */ U32 cyl; /* Cylinder number */ U32 head; /* Head number */ BYTE rec; /* Record number */ char pathname[MAX_PATH]; /* file path in host format */ hostpath(pathname, (char *)ifname, sizeof(pathname)); /* Open the HDR-30 CKD image file */ #if defined(HAVE_LIBZ) if (strcmp(ifname, "-") == 0) ifd = gzdopen (STDIN_FILENO, "rb"); else ifd = gzopen (pathname, "rb"); if (ifd == NULL) { fprintf (stderr, "Cannot open %s: %s\n", ifname, errno == 0 ? "gzopen error" : strerror(errno)); EXIT(3); } #else /*!defined(HAVE_LIBZ)*/ if (strcmp(ifname, "-") == 0) ifd = STDIN_FILENO; else { ifd = open (pathname, O_RDONLY | O_BINARY); if (ifd < 0) { fprintf (stderr, "Cannot open %s: %s\n", ifname, strerror(errno)); EXIT(3); } } #endif /*!defined(HAVE_LIBZ)*/ /* Read the first track header */ read_input_data (ifd, ifname, (BYTE*)&h30trkhdr, H30CKD_TRKHDR_SIZE, 0); #if !defined(HAVE_LIBZ) /* Reject input if compressed and we lack gzip support */ if (memcmp(h30trkhdr.devcode, gz_magic_id, sizeof(gz_magic_id)) == 0) { fprintf (stderr, "Input file %s appears to be a .gz file\n" "but this program was compiled without compression support\n", ifname); EXIT(3); } #endif /*!defined(HAVE_LIBZ)*/ /* Reject input if it is already in CKD or CCKD format */ if (memcmp((BYTE*)&h30trkhdr, ckd_ident, sizeof(ckd_ident)) == 0) { fprintf (stderr, "Input file %s is already in CKD format, use dasdcopy\n", ifname); EXIT(3); } /* Extract the device type code from the track header */ FETCH_HW (code, h30trkhdr.devcode); /* Determine the input device type and size from the device code */ switch (code) { case 0x01: dt=0x3330; cyls=411; alts=7; break; /* 3330 */ case 0x02: dt=0x3330; cyls=815; alts=7; break; /* 3330-11 */ case 0x03: dt=0x3340; cyls=351; alts=1; break; /* 3340-35 */ case 0x04: dt=0x3340; cyls=701; alts=1; break; /* 3340-70 */ case 0x05: dt=0x3350; cyls=562; alts=7; break; /* 3350 */ case 0x06: dt=0x3375; cyls=962; alts=3; break; /* 3375 */ case 0x08: dt=0x3380; cyls=888; alts=3; break; /* 3380-A,D,J*/ case 0x09: dt=0x3380; cyls=1774; alts=4; break; /* 3380-E */ case 0x0A: dt=0x3380; cyls=2660; alts=5; break; /* 3380-K */ case 0x0B: dt=0x3390; cyls=1117; alts=4; break; /* 3390-1 */ case 0x0C: dt=0x3390; cyls=2230; alts=4; break; /* 3390-2 */ case 0x0D: dt=0x3390; cyls=3343; alts=4; break; /* 3390-3 */ case 0x12: dt=0x2314; cyls=203; alts=3; break; /* 2314 */ case 0x13: dt=0x3390; cyls=10038; alts=21; break; /* 3390-9 */ case 0x14: dt=0x9345; cyls=1454; alts=14; break; /* 9345-1 */ case 0x15: dt=0x9345; cyls=2170; alts=14; break; /* 9345-2 */ default: fprintf (stderr, "Unknown device code %4.4X" \ " at offset 00000000 in input file %s\n", code, ifname); EXIT(3); } /* end switch(code) */ /* Use the device type to determine the input image track size */ switch (dt) { case 0x2314: itrklen = 0x2000; break; case 0x3330: itrklen = 0x3400; break; case 0x3340: itrklen = 0x2400; break; case 0x3350: itrklen = 0x4C00; break; case 0x3375: itrklen = 0x9000; break; case 0x3380: itrklen = 0xBC00; break; case 0x3390: itrklen = 0xE400; break; case 0x9345: itrklen = 0xBC00; break; default: fprintf (stderr, "Unknown device type: %4.4X\n", dt); EXIT(3); } /* end switch(dt) */ /* Obtain the input track buffer */ itrkbuf = malloc (itrklen); if (itrkbuf == NULL) { fprintf (stderr, "Cannot obtain storage for input track buffer: %s\n", strerror(errno)); EXIT(3); } /* Copy the first track header to the input track buffer */ memcpy (itrkbuf, &h30trkhdr, H30CKD_TRKHDR_SIZE); /* Read the remainder of the first track into the buffer */ read_input_data (ifd, ifname, itrkbuf + H30CKD_TRKHDR_SIZE, itrklen - H30CKD_TRKHDR_SIZE, H30CKD_TRKHDR_SIZE); /* Initialize the volume serial number */ strcpy ((char *)volser, "(NONE)"); /* Search for volume label in record 3 of first track */ pbuf = itrkbuf + H30CKD_TRKHDR_SIZE; len = itrklen - H30CKD_TRKHDR_SIZE; while (1) { /* Find next input record */ rc = find_input_record (itrkbuf, &pbuf, &len, &klen, &kptr, &dlen, &dptr, &cyl, &head, &rec); /* Give up if error or end of track */ if (rc != 0) break; /* Process when record 3 is found */ if (cyl == 0 && head == 0 && rec == 3) { /* Extract volser if it is a volume label */ if (klen == 4 && memcmp(kptr, ebcdicvol1, 4) == 0 && dlen == 80 && memcmp(dptr, ebcdicvol1, 4) == 0) make_asciiz ((char *)volser, 7, dptr+4, 6); break; } } /* end while */ /* Set output variables and return the input file descriptor */ *devt = dt; *vcyls = cyls - alts; *itrkl = itrklen; *itrkb = itrkbuf; return ifd; } /* end function open_input_image */ /*-------------------------------------------------------------------*/ /* Subroutine to create an AWSCKD DASD image file */ /* Input: */ /* ifd Input HDR-30 image file descriptor */ /* ifname Input file name */ /* itrklen Length of input track buffer */ /* itrkbuf Address of input track buffer */ /* repl 1=replace existing file, 0=do not replace */ /* ofname Output AWSCKD file name */ /* fseqn Sequence number of this file (1=first) */ /* devtype Device type */ /* heads Number of heads per cylinder */ /* trksize AWSCKD image track length */ /* obuf Address of output AWSCKD track image buffer */ /* start Starting cylinder number for this file */ /* end Ending cylinder number for this file */ /* volcyls Total number of cylinders on volume */ /* volser Volume serial number */ /*-------------------------------------------------------------------*/ static void convert_ckd_file (IFD ifd, char *ifname, int itrklen, BYTE *itrkbuf, int repl, int quiet, char *ofname, int fseqn, U16 devtype, U32 heads, U32 trksize, BYTE *obuf, U32 start, U32 end, U32 volcyls, BYTE *volser) { int rc; /* Return code */ int ofd; /* Output file descriptor */ CKDDASD_DEVHDR devhdr; /* Output device header */ CKDDASD_TRKHDR *trkhdr; /* -> Output track header */ CKDDASD_RECHDR *rechdr; /* -> Output record header */ U32 cyl; /* Cylinder number */ U32 head; /* Head number */ int fileseq; /* CKD header sequence number*/ int highcyl; /* CKD header high cyl number*/ BYTE *opos; /* -> Byte in output buffer */ BYTE klen; /* Key length */ U16 dlen; /* Data length */ BYTE rec; /* Record number */ BYTE *iptr; /* -> Byte in input buffer */ BYTE *kptr; /* -> Key in input buffer */ BYTE *dptr; /* -> Data in input buffer */ int ilen; /* Bytes left in input buffer*/ H30CKD_TRKHDR *ith; /* -> Input track header */ U32 ihc, ihh; /* Input trk header cyl,head */ U32 offset; /* Current input file offset */ char pathname[MAX_PATH]; /* file path in host format */ UNREFERENCED(volser); /* Set file sequence number to zero if this is the only file */ if (fseqn == 1 && end + 1 == volcyls) fileseq = 0; else fileseq = fseqn; /* Set high cylinder number to zero if this is the last file */ if (end + 1 == volcyls) highcyl = 0; else highcyl = end; /* Create the AWSCKD image file */ hostpath(pathname, (char *)ofname, sizeof(pathname)); ofd = open (pathname, O_WRONLY | O_CREAT | O_BINARY | (repl ? 0 : O_EXCL), S_IRUSR | S_IWUSR | S_IRGRP); if (ofd < 0) { fprintf (stderr, "%s open error: %s\n", ofname, strerror(errno)); EXIT(8); } /* Create the device header */ memset(&devhdr, 0, CKDDASD_DEVHDR_SIZE); memcpy(devhdr.devid, "CKD_P370", 8); devhdr.heads[3] = (heads >> 24) & 0xFF; devhdr.heads[2] = (heads >> 16) & 0xFF; devhdr.heads[1] = (heads >> 8) & 0xFF; devhdr.heads[0] = heads & 0xFF; devhdr.trksize[3] = (trksize >> 24) & 0xFF; devhdr.trksize[2] = (trksize >> 16) & 0xFF; devhdr.trksize[1] = (trksize >> 8) & 0xFF; devhdr.trksize[0] = trksize & 0xFF; devhdr.devtype = devtype & 0xFF; devhdr.fileseq = fileseq; devhdr.highcyl[1] = (highcyl >> 8) & 0xFF; devhdr.highcyl[0] = highcyl & 0xFF; /* Write the device header */ rc = write (ofd, &devhdr, CKDDASD_DEVHDR_SIZE); if (rc < CKDDASD_DEVHDR_SIZE) { fprintf (stderr, "%s device header write error: %s\n", ofname, errno ? strerror(errno) : "incomplete"); EXIT(1); } /* Write each cylinder */ for (cyl = start; cyl <= end; cyl++) { /* Display progress message every 10 cylinders */ if ((cyl % 10) == 0) { #ifdef EXTERNALGUI if (extgui) fprintf (stderr, "CYL=%u\n", cyl); else #endif /*EXTERNALGUI*/ if (quiet == 0) fprintf (stderr, "Writing cylinder %u\r", cyl); } for (head = 0; head < heads; head++) { /* Calculate the current offset in the file */ offset = ((cyl*heads)+head)*itrklen; /* Read the input track image (except cyl 0 head 0 already read by the open_input_image procedure) */ if (cyl > 0 || head > 0) { read_input_data (ifd, ifname, itrkbuf, itrklen, offset); } /* end if(cyl>0||head>0) */ /* Validate the track header */ ith = (H30CKD_TRKHDR*)itrkbuf; FETCH_HW (ihc, ith->cyl); FETCH_HW (ihh, ith->head); if (ihc != cyl || ihh != head) { fprintf (stderr, "Invalid track header found at offset %8.8X\n" "in input file %s\n" "Expected cyl=%4.4X head=%4.4X\n" " Found cyl=%4.4X head=%4.4X\n", offset, ifname, cyl, head, ihc, ihh); EXIT(8); } /* Clear the output track image to zeroes */ memset (obuf, 0, trksize); /* Build the output track header */ trkhdr = (CKDDASD_TRKHDR*)obuf; trkhdr->bin = 0; STORE_HW (trkhdr->cyl, cyl); STORE_HW (trkhdr->head, head); opos = obuf + CKDDASD_TRKHDR_SIZE; /* Copy each record from the input buffer */ iptr = itrkbuf + H30CKD_TRKHDR_SIZE; ilen = itrklen - H30CKD_TRKHDR_SIZE; while (1) { /* Locate the next input record */ rc = find_input_record (itrkbuf, &iptr, &ilen, &klen, &kptr, &dlen, &dptr, &ihc, &ihh, &rec); /* Exit at end of track */ if (rc == 1) break; /* Error if invalid record header detected */ if (rc > 1) { fprintf (stderr, "Invalid record header (reason %d)\n" "at offset %4.4X" " in track at cyl %4.4X head %4.4X\n" "at offset %8.8X in input file %s\n", rc, (unsigned int)(iptr-itrkbuf), cyl, head, offset, ifname); EXIT(9); } /* Build AWSCKD record header in output buffer */ rechdr = (CKDDASD_RECHDR*)opos; opos += CKDDASD_RECHDR_SIZE; STORE_HW (rechdr->cyl, ihc); STORE_HW (rechdr->head, ihh); rechdr->rec = rec; rechdr->klen = klen; STORE_HW (rechdr->dlen, dlen); /* Copy key and data to output buffer */ if (klen != 0) { memcpy (opos, kptr, klen); opos += klen; } if (dlen != 0) { memcpy (opos, dptr, dlen); opos += dlen; } } /* end while */ /* Build the end of track marker */ memcpy (opos, eighthexFF, 8); /* Write the track to the file */ rc = write (ofd, obuf, trksize); if (rc < 0 || (U32)rc < trksize) { fprintf (stderr, "%s cylinder %u head %u write error: %s\n", ofname, cyl, head, errno ? strerror(errno) : "incomplete"); EXIT(1); } } /* end for(head) */ } /* end for(cyl) */ /* Close the AWSCKD image file */ rc = close (ofd); if (rc < 0) { fprintf (stderr, "%s close error: %s\n", ofname, strerror(errno)); EXIT(10); } /* Display completion message */ fprintf (stderr, "%u cylinders successfully written to file %s\n", cyl - start, ofname); } /* end function convert_ckd_file */ /*-------------------------------------------------------------------*/ /* Subroutine to create an AWSCKD DASD image */ /* Input: */ /* lfs Build one large output file */ /* ifd Input HDR-30 image file descriptor */ /* ifname Input file name */ /* itrklen Length of input track buffer */ /* itrkbuf Address of input track buffer */ /* repl 1=replace existing file, 0=do not replace */ /* ofname Output AWSCKD image file name */ /* devtype Device type */ /* heads Number of heads per cylinder */ /* maxdlen Maximum R1 record data length */ /* volcyls Total number of cylinders on volume */ /* volser Volume serial number */ /* */ /* If the total number of cylinders exceeds the capacity of a 2GB */ /* file, then multiple CKD image files will be created, with the */ /* suffix _1, _2, etc suffixed to the specified file name. */ /* Otherwise a single file is created without a suffix. */ /*-------------------------------------------------------------------*/ static void convert_ckd (int lfs, IFD ifd, char *ifname, int itrklen, BYTE *itrkbuf, int repl, int quiet, char *ofname, U16 devtype, U32 heads, U32 maxdlen, U32 volcyls, BYTE *volser) { int i; /* Array subscript */ char *s; /* String pointer */ int fileseq; /* File sequence number */ char sfname[260]; /* Suffixed name of this file*/ char *suffix; /* -> Suffix character */ U32 endcyl; /* Last cylinder of this file*/ U32 cyl; /* Cylinder number */ U32 cylsize; /* Cylinder size in bytes */ BYTE *obuf; /* -> Output track buffer */ U32 mincyls; /* Minimum cylinder count */ U32 maxcyls; /* Maximum cylinder count */ U32 maxcpif; /* Maximum number of cylinders in each CKD image file */ int rec0len = 8; /* Length of R0 data */ U32 trksize; /* AWSCKD image track length */ /* Compute the AWSCKD image track length */ trksize = sizeof(CKDDASD_TRKHDR) + sizeof(CKDDASD_RECHDR) + rec0len + sizeof(CKDDASD_RECHDR) + maxdlen + sizeof(eighthexFF); trksize = ROUND_UP(trksize,512); /* Compute minimum and maximum number of cylinders */ cylsize = trksize * heads; mincyls = 1; if (!lfs) { maxcpif = 0x80000000 / cylsize; maxcyls = maxcpif * CKD_MAXFILES; } else maxcpif = maxcyls = volcyls; if (maxcyls > 65536) maxcyls = 65536; /* Check for valid number of cylinders */ if (volcyls < mincyls || volcyls > maxcyls) { fprintf (stderr, "Cylinder count %u is outside range %u-%u\n", volcyls, mincyls, maxcyls); EXIT(4); } /* Obtain track data buffer */ obuf = malloc(trksize); if (obuf == NULL) { fprintf (stderr, "Cannot obtain track buffer: %s\n", strerror(errno)); EXIT(6); } /* Display progress message */ fprintf (stderr, "Converting %4.4X volume %s: %u cyls, " "%u trks/cyl, %u bytes/track\n", devtype, volser, volcyls, heads, trksize); #ifdef EXTERNALGUI if (extgui) fprintf (stderr, "CYLS=%u\n", volcyls); #endif /*EXTERNALGUI*/ /* Copy the unsuffixed AWSCKD image file name */ strcpy (sfname, ofname); suffix = NULL; /* Create the suffixed file name if volume will exceed 2GB */ if (volcyls > maxcpif) { /* Look for last slash marking end of directory name */ s = strrchr (ofname, '/'); if (s == NULL) s = ofname; /* Insert suffix before first dot in file name, or append suffix to file name if there is no dot */ s = strchr (s, '.'); if (s != NULL) { i = s - ofname; strcpy (sfname + i, "_1"); strcat (sfname, ofname + i); suffix = sfname + i + 1; } else { strcat (sfname, "_1"); suffix = sfname + strlen(sfname) - 1; } } /* Create the AWSCKD image files */ for (cyl = 0, fileseq = 1; cyl < volcyls; cyl += maxcpif, fileseq++) { /* Insert the file sequence number in the file name */ if (suffix) *suffix = '0' + fileseq; /* Calculate the ending cylinder for this file */ if (cyl + maxcpif < volcyls) endcyl = cyl + maxcpif - 1; else endcyl = volcyls - 1; /* Create an AWSCKD image file */ convert_ckd_file (ifd, ifname, itrklen, itrkbuf, repl, quiet, sfname, fileseq, devtype, heads, trksize, obuf, cyl, endcyl, volcyls, volser); } /* Release the output track buffer */ free (obuf); } /* end function convert_ckd */ /*-------------------------------------------------------------------*/ /* DASDCONV program main entry point */ /*-------------------------------------------------------------------*/ int main ( int argc, char *argv[] ) { IFD ifd; /* Input file descriptor */ int repl = 0; /* 1=replace existing file */ int quiet = 0; /* 1=suppress progress msgs */ BYTE *itrkbuf; /* -> Input track buffer */ U32 itrklen; /* Input track length */ U32 volcyls; /* Total cylinders on volume */ U32 heads = 0; /* Number of tracks/cylinder */ U32 maxdlen = 0; /* Maximum R1 data length */ U16 devtype; /* Device type */ char ifname[256]; /* Input file name */ char ofname[256]; /* Output file name */ BYTE volser[7]; /* Volume serial (ASCIIZ) */ int lfs = 0; /* 1 = Build large file */ INITIALIZE_UTILITY("dasdconv"); /* Display the program identification message */ display_version (stderr, "Hercules DASD CKD image conversion program\n", FALSE); /* Process the options in the argument list */ for (; argc > 1; argc--, argv++) { if (strcmp(argv[1], "-") == 0) break; if (argv[1][0] != '-') break; if (strcmp(argv[1], "-r") == 0) repl = 1; else if (strcmp(argv[1], "-q") == 0) quiet = 1; else if (sizeof(off_t) > 4 && strcmp(argv[1], "-lfs") == 0) lfs = 1; else argexit(5); } if (argc != 3) argexit(5); /* The first argument is the input file name */ if (argv[1] == NULL || strlen(argv[1]) == 0 || strlen(argv[1]) > sizeof(ifname)-1) argexit(1); strcpy (ifname, argv[1]); /* The second argument is the output file name */ if (argv[2] == NULL || strlen(argv[2]) == 0 || strlen(argv[2]) > sizeof(ofname)-1) argexit(2); strcpy (ofname, argv[2]); /* Read the first track of the input file, and determine the device type and size from the track header */ ifd = open_input_image (ifname, &devtype, &volcyls, &itrklen, &itrkbuf, volser); /* Use the device type to determine track characteristics */ switch (devtype) { case 0x2314: heads = 20; maxdlen = 7294; break; case 0x3330: heads = 19; maxdlen = 13030; break; case 0x3340: heads = 12; maxdlen = 8368; break; case 0x3350: heads = 30; maxdlen = 19069; break; case 0x3375: heads = 12; maxdlen = 35616; break; case 0x3380: heads = 15; maxdlen = 47476; break; case 0x3390: heads = 15; maxdlen = 56664; break; case 0x9345: heads = 15; maxdlen = 46456; break; default: fprintf (stderr, "Unknown device type: %4.4X\n", devtype); EXIT(3); } /* end switch(devtype) */ /* Create the device */ convert_ckd (lfs, ifd, ifname, itrklen, itrkbuf, repl, quiet, ofname, devtype, heads, maxdlen, volcyls, volser); /* Release the input buffer and close the input file */ free (itrkbuf); IFCLOS (ifd); /* Display completion message */ fprintf (stderr, "DASD conversion successfully completed.\n"); return 0; } /* end function main */ hercules-3.07/dasdcopy.c000644 000765 000765 00000057527 11321734033 016732 0ustar00jmaynardjmaynard000000 000000 /* DASDCOPY.C (c) Copyright Roger Bowler, 1999-2010 */ /* Copy a dasd file to another dasd file */ // $Id: dasdcopy.c 5589 2010-01-04 09:26:36Z rbowler $ /*-------------------------------------------------------------------*/ /* This program copies a dasd file to another dasd file. */ /* Input file and output file may be compressed or not. */ /* Files may be either ckd (or cckd) or fba (or cfba) but */ /* file types (ckd/cckd or fba/cfba) may not be mixed. */ /* */ /* Usage: */ /* dasdcopy [-options] ifile [sf=sfile] ofile */ /* */ /* Refer to the usage section below for details of options. */ /* */ /* The program may also be invoked by one of the following */ /* aliases which override the default output file format: */ /* */ /* ckd2cckd [-options] ifile ofile */ /* cckd2ckd [-options] ifile [sf=sfile] ofile */ /* fba2cfba [-options] ifile ofile */ /* cfba2fba [-options] ifile [sf=sfile] ofile */ /*-------------------------------------------------------------------*/ #include "hstdinc.h" #include "hercules.h" #include "dasdblks.h" #include "devtype.h" #include "opcode.h" #define FBA_BLKGRP_SIZE (120 * 512) /* Size of block group */ #define FBA_BLKS_PER_GRP 120 /* Blocks per group */ int syntax (char *); void status (int, int); int nulltrk(BYTE *, int, int, int); #define CKD 0x01 #define CCKD 0x02 #define FBA 0x04 #define CFBA 0x08 #define CKDMASK 0x03 #define FBAMASK 0x0c #define COMPMASK 0x0a /*-------------------------------------------------------------------*/ /* Copy a dasd file to another dasd file */ /*-------------------------------------------------------------------*/ int main (int argc, char *argv[]) { char *pgm; /* -> Program name */ int ckddasd=-1; /* 1=CKD 0=FBA */ int rc; /* Return code */ int quiet=0; /* 1=Don't display status */ int comp=255; /* Compression algorithm */ int cyls=-1, blks=-1; /* Size of output file */ int lfs=0; /* 1=Create 1 large file */ int alt=0; /* 1=Create alt cyls */ int r=0; /* 1=Replace output file */ int in=0, out=0; /* Input/Output file types */ int fd; /* Input file descriptor */ char *ifile, *ofile; /* -> Input/Output file names*/ char *sfile=NULL; /* -> Input shadow file name */ CIFBLK *icif, *ocif; /* -> Input/Output CIFBLK */ DEVBLK *idev, *odev; /* -> Input/Output DEVBLK */ CKDDEV *ckd=NULL; /* -> CKD device table entry */ FBADEV *fba=NULL; /* -> FBA device table entry */ int i, n, max; /* Loop index, limits */ BYTE unitstat; /* Device unit status */ char msgbuf[512]; /* Message buffer */ size_t fba_bytes_remaining=0; /* FBA bytes to be copied */ int nullfmt = CKDDASD_NULLTRK_FMT0; /* Null track format */ char pathname[MAX_PATH]; /* file path in host format */ char pgmpath[MAX_PATH]; /* prog path in host format */ INITIALIZE_UTILITY("dasdcopy"); /* Figure out processing based on the program name */ hostpath(pgmpath, argv[0], sizeof(pgmpath)); pgm = strrchr (pgmpath, '/'); if (pgm) pgm++; else pgm = argv[0]; strtok (pgm, "."); if (strcmp(pgm, "ckd2cckd") == 0) { in = CKD; out = CCKD; } else if (strcmp(pgm, "cckd2ckd") == 0) { in = CCKD; out = CKD; } else if (strcmp(pgm, "fba2cfba") == 0) { in = FBA; out = CFBA; } else if (strcmp(pgm, "cfba2fba") == 0) { in = CFBA; out = FBA; } /* Process the arguments */ for (argc--, argv++ ; argc > 0 ; argc--, argv++) { if (argv[0][0] != '-') break; if (strcmp(argv[0], "-v") == 0) { snprintf (msgbuf, 512, _("Hercules %s copy program "), pgm); display_version (stderr, msgbuf, FALSE); return 0; } else if (strcmp(argv[0], "-h") == 0) { syntax(pgm); return 0; } else if (strcmp(argv[0], "-q") == 0 || strcmp(argv[0], "-quiet") == 0) quiet = 1; else if (strcmp(argv[0], "-r") == 0) r = 1; #ifdef CCKD_COMPRESS_ZLIB else if (strcmp(argv[0], "-z") == 0) comp = CCKD_COMPRESS_ZLIB; #endif #ifdef CCKD_COMPRESS_BZIP2 else if (strcmp(argv[0], "-bz2") == 0) comp = CCKD_COMPRESS_BZIP2; #endif else if (strcmp(argv[0], "-0") == 0) comp = CCKD_COMPRESS_NONE; else if ((strcmp(argv[0], "-cyl") == 0 || strcmp(argv[0], "-cyls") == 0) && cyls < 0) { if (argc < 2 || (cyls = atoi(argv[1])) < 0) return syntax(pgm); argc--; argv++; } else if ((strcmp(argv[0], "-blk") == 0 || strcmp(argv[0], "-blks") == 0) && blks < 0) { if (argc < 2 || (blks = atoi(argv[1])) < 0) return syntax(pgm); argc--; argv++; } else if (strcmp(argv[0], "-a") == 0 || strcmp(argv[0], "-alt") == 0 || strcmp(argv[0], "-alts") == 0) alt = 1; else if (strcmp(argv[0], "-lfs") == 0) lfs = 1; else if (out == 0 && strcmp(argv[0], "-o") == 0) { if (argc < 2 || out != 0) return syntax(pgm); if (strcasecmp(argv[1], "ckd") == 0) out = CKD; else if (strcasecmp(argv[1], "cckd") == 0) out = CCKD; else if (strcasecmp(argv[1], "fba") == 0) out = FBA; else if (strcasecmp(argv[1], "cfba") == 0) out = CFBA; else return syntax(pgm); argc--; argv++; } else return syntax(pgm); } /* Get the file names: input-file [sf=shadow-file] output-file */ if (argc < 2 || argc > 3) return syntax(pgm); ifile = argv[0]; if (argc < 3) ofile = argv[1]; else { if (strlen(argv[1]) < 4 || memcmp(argv[1], "sf=", 3)) return syntax(pgm); sfile = argv[1]; ofile = argv[2]; } /* If we don't know what the input file is then find out */ if (in == 0) { BYTE buf[8]; hostpath(pathname, ifile, sizeof(pathname)); fd = open (pathname, O_RDONLY|O_BINARY); if (fd < 0) { fprintf (stderr, _("HHCDC001E %s: %s open error: %s\n"), pgm, ifile, strerror(errno)); return -1; } rc = read (fd, buf, 8); if (rc < 8) { fprintf (stderr, _("HHCDC002E %s: %s read error: %s\n"), pgm, ifile, strerror(errno)); return -1; } if (memcmp(buf, "CKD_P370", 8) == 0) in = CKD; else if (memcmp(buf, "CKD_C370", 8) == 0) in = CCKD; else if (memcmp(buf, "FBA_C370", 8) == 0) in = CFBA; else in = FBA; close (fd); } /* If we don't know what the output file type is then derive it from the input file type */ if (out == 0) { switch (in) { case CKD: if (!lfs) out = CCKD; else out = CKD; break; case CCKD: if (comp == 255) out = CKD; else out = CCKD; break; case FBA: if (!lfs) out = CFBA; else out = FBA; break; case CFBA: if (comp == 255) out = FBA; else out = CFBA; break; } } /* Set default compression if out file is to be compressed */ if (comp == 255 && (out & COMPMASK)) #ifdef CCKD_COMPRESS_ZLIB comp = CCKD_COMPRESS_ZLIB; #else comp = CCKD_COMPRESS_NONE; #endif /* Perform sanity checks on the options */ if ((in & CKDMASK) && !(out & CKDMASK)) return syntax(pgm); if ((in & FBAMASK) && !(out & FBAMASK)) return syntax(pgm); if (sfile && !(in & COMPMASK)) return syntax(pgm); if (comp != 255 && !(out & COMPMASK)) return syntax(pgm); if (lfs && (out & COMPMASK)) return syntax(pgm); if (cyls >= 0 && !(in & CKDMASK)) return syntax(pgm); if (blks >= 0 && !(in & FBAMASK)) return syntax(pgm); if (!(in & CKDMASK) && alt) return syntax(pgm); /* Set the type of processing (ckd or fba) */ ckddasd = (in & CKDMASK); /* Open the input file */ if (ckddasd) icif = open_ckd_image (ifile, sfile, O_RDONLY|O_BINARY, 0); else icif = open_fba_image (ifile, sfile, O_RDONLY|O_BINARY, 0); if (icif == NULL) { fprintf (stderr, _("HHCDC003E %s: %s open failed\n"), pgm, ifile); return -1; } idev = &icif->devblk; if (idev->oslinux) nullfmt = CKDDASD_NULLTRK_FMT2; /* Calculate the number of tracks or blocks to copy */ if (ckddasd) { if (cyls < 0) cyls = idev->ckdcyls; else if (cyls == 0) cyls = (idev->hnd->used)(idev); ckd = dasd_lookup (DASD_CKDDEV, NULL, idev->devtype, cyls); if (ckd == NULL) { fprintf (stderr, _("HHCDC004E %s: ckd lookup failed for %4.4X " "cyls %d\n"), pgm, idev->devtype, cyls); close_image_file (icif); return -1; } if (out == CCKD) cyls = ckd->cyls; if (cyls <= ckd->cyls && alt) cyls = ckd->cyls + ckd->altcyls; n = cyls * idev->ckdheads; max = idev->ckdtrks; if (max < n && out == CCKD) n = max; } else { fba_bytes_remaining = idev->fbanumblk * idev->fbablksiz; if (blks < 0) blks = idev->fbanumblk; else if (blks == 0) blks = (idev->hnd->used)(idev); fba = dasd_lookup (DASD_FBADEV, NULL, idev->devtype, blks); if (fba == NULL) { fprintf (stderr, _("HHCDC005E %s: fba lookup failed, blks %d\n"), pgm, blks); close_image_file (icif); return -1; } n = blks; max = idev->fbanumblk; if (max < n && out == CFBA) n = max; n = (n + FBA_BLKS_PER_GRP - 1) / FBA_BLKS_PER_GRP; max = (max + FBA_BLKS_PER_GRP - 1) / FBA_BLKS_PER_GRP; } /* Create the output file */ if (ckddasd) rc = create_ckd(ofile, idev->devtype, idev->ckdheads, ckd->r1, cyls, "", comp, lfs, 1+r, nullfmt, 0); else rc = create_fba(ofile, idev->devtype, fba->size, blks, "", comp, lfs, 1+r, 0); if (rc < 0) { fprintf (stderr, _("HHCDC006E %s: %s create failed\n"), pgm, ofile); close_image_file (icif); return -1; } /* Open the output file */ if (ckddasd) ocif = open_ckd_image (ofile, NULL, O_RDWR|O_BINARY, 1); else ocif = open_fba_image (ofile, NULL, O_RDWR|O_BINARY, 1); if (ocif == NULL) { fprintf (stderr, _("HHCDC007E %s: %s open failed\n"), pgm, ofile); close_image_file (icif); return -1; } odev = &ocif->devblk; /* Copy the files */ #ifdef EXTERNALGUI if (extgui) /* Notify GUI of total #of tracks or blocks being copied... */ fprintf (stderr, "TRKS=%d\n", n); else #endif /*EXTERNALGUI*/ if (!quiet) printf (" %3d%% %7d of %d", 0, 0, n); for (i = 0; i < n; i++) { /* Read a track or block */ if (ckddasd) { if (i < max) rc = (idev->hnd->read)(idev, i, &unitstat); else { memset (idev->buf, 0, idev->ckdtrksz); rc = nulltrk(idev->buf, i, idev->ckdheads, nullfmt); } } else { if (i < max) rc = (idev->hnd->read)(idev, i, &unitstat); else memset (idev->buf, 0, FBA_BLKGRP_SIZE); rc = 0; } if (rc < 0) { fprintf (stderr, _("HHCDC008E %s: %s read error %s %d " "stat=%2.2X, null %s substituted\n"), pgm, ifile, ckddasd ? "track" : "block", i, unitstat, ckddasd ? "track" : "block"); if (ckddasd) nulltrk(idev->buf, i, idev->ckdheads, nullfmt); else memset (idev->buf, 0, FBA_BLKGRP_SIZE); if (!quiet) { printf (_(" %3d%% %7d of %d"), 0, 0, n); status (i, n); } } /* Write the track or block just read */ if (ckddasd) { rc = (odev->hnd->write)(odev, i, 0, idev->buf, idev->ckdtrksz, &unitstat); } else { if (fba_bytes_remaining >= (size_t)idev->buflen) { rc = (odev->hnd->write)(odev, i, 0, idev->buf, idev->buflen, &unitstat); fba_bytes_remaining -= (size_t)idev->buflen; } else { ASSERT(fba_bytes_remaining > 0 && (i+1) >= n); rc = (odev->hnd->write)(odev, i, 0, idev->buf, (int)fba_bytes_remaining, &unitstat); fba_bytes_remaining = 0; } } if (rc < 0) { fprintf (stderr, _("HHCDC009E %s: %s write error %s %d " "stat=%2.2X\n"), pgm, ofile, ckddasd ? "track" : "block", i, unitstat); close_image_file(icif); close_image_file(ocif); return -1; } /* Update the status indicator */ if (!quiet) status (i+1, n); } close_image_file(icif); close_image_file(ocif); if (!quiet) printf (_("\r")); printf (_("HHCDC010I %s successfully completed.\n"), pgm); return 0; } /*-------------------------------------------------------------------*/ /* Build a null track image */ /*-------------------------------------------------------------------*/ int nulltrk(BYTE *buf, int trk, int heads, int nullfmt) { int i; /* Loop counter */ CKDDASD_TRKHDR *trkhdr; /* -> Track header */ CKDDASD_RECHDR *rechdr; /* -> Record header */ U32 cyl; /* Cylinder number */ U32 head; /* Head number */ BYTE r; /* Record number */ BYTE *pos; /* -> Next position in buffer*/ static BYTE eighthexFF[]={0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}; /* cylinder and head calculations */ cyl = trk / heads; head = trk % heads; /* Build the track header */ trkhdr = (CKDDASD_TRKHDR*)buf; trkhdr->bin = 0; store_hw(&trkhdr->cyl, cyl); store_hw(&trkhdr->head, head); pos = buf + CKDDASD_TRKHDR_SIZE; /* Build record zero */ r = 0; rechdr = (CKDDASD_RECHDR*)pos; pos += CKDDASD_RECHDR_SIZE; store_hw(&rechdr->cyl, cyl); store_hw(&rechdr->head, head); rechdr->rec = r; rechdr->klen = 0; store_hw(&rechdr->dlen, 8); pos += 8; r++; /* Specific null track formatting */ if (nullfmt == CKDDASD_NULLTRK_FMT0) { rechdr = (CKDDASD_RECHDR*)pos; pos += CKDDASD_RECHDR_SIZE; store_hw(&rechdr->cyl, cyl); store_hw(&rechdr->head, head); rechdr->rec = r; rechdr->klen = 0; store_hw(&rechdr->dlen, 0); r++; } else if (nullfmt == CKDDASD_NULLTRK_FMT2) { for (i = 0; i < 12; i++) { rechdr = (CKDDASD_RECHDR*)pos; pos += CKDDASD_RECHDR_SIZE; store_hw(&rechdr->cyl, cyl); store_hw(&rechdr->head, head); rechdr->rec = r; rechdr->klen = 0; store_hw(&rechdr->dlen, 4096); r++; pos += 4096; } } /* Build the end of track marker */ memcpy (pos, eighthexFF, 8); pos += 8; return 0; } /*-------------------------------------------------------------------*/ /* Display command syntax */ /*-------------------------------------------------------------------*/ int syntax (char *pgm) { char usage[8192]; if (strcmp(pgm, "ckd2cckd") == 0) snprintf(usage,8192,_( "usage: ckd2cckd [-options] ifile ofile\n" "\n" " copy a ckd dasd file to a compressed ckd dasd file\n" "\n" " ifile -- input ckd dasd file\n" " ofile -- output compressed ckd dasd file\n" "\n" " options:\n" " -v display program version and quit\n" " -h display this help and quit\n" " -q quiet mode, don't display status\n" " -r replace the output file if it exists\n" "%s" "%s" " -0 don't compress track images\n" " -cyls n size of output file\n" " -a output file will have alt cyls\n" ), #ifdef CCKD_COMPRESS_ZLIB _( " -z compress using zlib [default]\n" ), #else "", #endif #ifdef CCKD_COMPRESS_BZIP2 _( " -bz2 compress using bzip2\n" ) #else "" #endif ); else if (strcmp(pgm, "cckd2ckd") == 0) snprintf(usage,8192,_( "usage: cckd2ckd [-options] ifile [sf=sfile] ofile\n" "\n" " copy a compressed ckd file to a ckd file\n" "\n" " ifile -- input compressed ckd dasd file\n" " sfile -- input compressed ckd shadow file\n" " (optional)\n" " ofile -- output ckd dasd file\n" "\n" " options:\n" " -v display program version and quit\n" " -h display this help and quit\n" " -q quiet mode, don't display status\n" " -r replace the output file if it exists\n" "%s" " -cyls n size of output file\n" " -a output file will have alt cyls\n" ), (sizeof(off_t) > 4) ? _( " -lfs create single large output file\n" ) : ( "" ) ); else if (strcmp(pgm, "fba2cfba") == 0) snprintf(usage,8192,_( "usage: fba2cfba [-options] ifile ofile\n" "\n" " copy a fba dasd file to a compressed fba dasd file\n" "\n" " ifile -- input fba dasd file\n" " ofile -- output compressed fba dasd file\n" "\n" " options:\n" " -v display program version and quit\n" " -h display this help and quit\n" " -q quiet mode, don't display status\n" " -r replace the output file if it exists\n" "%s" "%s" " -0 don't compress track images\n" " -blks n size of output file\n" ), #ifdef CCKD_COMPRESS_ZLIB _( " -z compress using zlib [default]\n" ), #else "", #endif #ifdef CCKD_COMPRESS_BZIP2 _( " -bz2 compress using bzip2\n" ) #else "" #endif ); else if (strcmp(pgm, "cfba2fba") == 0) snprintf(usage,8192,_( "usage: cfba2fba [-options] ifile [sf=sfile] ofile\n" "\n" " copy a compressed fba file to a fba file\n" "\n" " ifile -- input compressed fba dasd file\n" " sfile -- input compressed fba shadow file\n" " (optional)\n" " ofile -- output fba dasd file\n" "\n" " options:\n" " -v display program version and quit\n" " -h display this help and quit\n" " -q quiet mode, don't display status\n" " -r replace the output file if it exists\n" "%s" " -blks n size of output file\n" ), (sizeof(off_t) > 4) ? _( " -lfs create single large output file\n" ) : ( "" ) ); else snprintf(usage,8192,_( "usage: %s [-options] ifile [sf=sfile] ofile\n" "\n" " copy a dasd file to another dasd file\n" "\n" " ifile -- input dasd file\n" " sfile -- input shadow file [optional]\n" " ofile -- output dasd file\n" "\n" " options:\n" " -v display program version and quit\n" " -h display this help and quit\n" " -q quiet mode, don't display status\n" " -r replace the output file if it exists\n" "%s" "%s" " -0 don't compress output\n" " -blks n size of output fba file\n" " -cyls n size of output ckd file\n" " -a output ckd file will have alt cyls\n" "%s" " even if it exceeds 2G in size\n" " -o type output file type (CKD, CCKD, FBA, CFBA)\n" ), pgm, #ifdef CCKD_COMPRESS_ZLIB _( " -z compress using zlib [default]\n" ), #else "", #endif #ifdef CCKD_COMPRESS_BZIP2 _( " -bz2 compress output using bzip2\n" ) #else "" #endif ,(sizeof(off_t) > 4) ? _( " -lfs output ckd file will be a single file\n" ) : ( "" ) ); printf (usage); return -1; } /* end function syntax */ /*-------------------------------------------------------------------*/ /* Display progress status */ /*-------------------------------------------------------------------*/ void status (int i, int n) { static char indic[] = "|/-\\"; #ifdef EXTERNALGUI if (extgui) { if (i % 100) return; fprintf (stderr, "TRK=%d\n", i); return; } #endif /*EXTERNALGUI*/ // if (i % 101 != 1) return; printf ("\r%c %3d%% %7d", indic[i%4], (int)((i*100.0)/n), i); } /* end function status */ hercules-3.07/dasdinit.c000644 000765 000765 00000026170 11143760544 016721 0ustar00jmaynardjmaynard000000 000000 /* DASDINIT.C (c) Copyright Roger Bowler, 1999-2009 */ /* Hercules DASD Utilities: DASD image builder */ // $Id: dasdinit.c 5125 2009-01-23 12:01:44Z bernard $ /*-------------------------------------------------------------------*/ /* This program creates a disk image file and initializes it as */ /* a blank FBA or CKD DASD volume. */ /* */ /* The program is invoked from the shell prompt using the command: */ /* */ /* dasdinit [-options] filename devtype[-model] [volser] [size] */ /* */ /* options options: */ /* -a include alternate cylinders */ /* (ignored if size specified manually) */ /* -z build compressed device using zlib */ /* -bz2 build compressed device using bzip2 */ /* -0 build compressed device with no compression */ /* -r "raw" init (bypass VOL1 & IPL track fmt) */ /* */ /* filename is the name of the disk image file to be created */ /* (this program will not overwrite an existing file) */ /* */ /* devtype is the emulated device type. */ /* CKD: 2305, 2311, 2314, 3330, 3350, 3375, 3380, */ /* 3390, 9345 */ /* FBA: 0671, 3310, 3370, 9313, 9332, 9335, 9336 */ /* */ /* model is the device model number and implies the device */ /* size. If specified, then size shouldn't be specified.*/ /* */ /* volser is the volume serial number (1-6 characters) */ /* (only if '-r' option not used) */ /* */ /* size is the size of the device (in cylinders for CKD */ /* devices, or in 512-byte sectors for FBA devices). */ /* Shouldn't be specified if model is specified. */ /* */ /*-------------------------------------------------------------------*/ // $Log$ // Revision 1.50 2008/11/04 04:50:46 fish // Ensure consistent utility startup // // Revision 1.49 2007/09/30 13:30:08 rbowler // Revert extra blank lines inserted by rev 1.12 // // Revision 1.48 2007/09/30 12:23:22 rbowler // Error message if DASD initialisation unsuccessful // // Revision 1.47 2007/06/23 00:04:08 ivan // Update copyright notices to include current year (2007) // // Revision 1.46 2006/12/08 09:43:19 jj // Add CVS message log // #include "hstdinc.h" #include "hercules.h" #include "dasdblks.h" /*-------------------------------------------------------------------*/ /* Subroutine to display command syntax and exit */ /*-------------------------------------------------------------------*/ static void argexit ( int code, char *m ) { switch (code) { case 0: fprintf (stderr, "Invalid or unsupported option: %s\n", m ? m : "(null)"); break; case 1: fprintf (stderr, "Invalid or missing filename: %s\n", m ? m : "(null)"); break; case 2: fprintf (stderr, "Invalid or missing device type: %s\n", m ? m : "(null)"); break; case 3: fprintf (stderr, "Invalid or missing volser: %s\n", m ? m : "(null)"); break; case 4: fprintf (stderr, "Invalid or missing size: %s\n", m ? m : "(null)"); break; case 5: fprintf (stderr, "Invalid number of arguments\n"); break; case 6: fprintf (stderr, "`-linux' only supported for device type 3390\n"); break; default: display_version (stderr, "Hercules DASD image file creation program\n", FALSE); fprintf (stderr, "Builds an empty dasd image file:\n\n" " dasdinit [-options] filename devtype[-model] [volser] [size]\n\n" "where:\n\n" " -v display version info and help\n" #ifdef HAVE_LIBZ " -z build compressed dasd image file using zlib\n" #endif #ifdef CCKD_BZIP2 " -bz2 build compressed dasd image file using bzip2\n" #endif " -0 build compressed dasd image file with no compression\n" ); if (sizeof(off_t) > 4) fprintf(stderr, " -lfs build a large (uncompressed) dasd file (if supported)\n" ); fprintf(stderr, " -a build dasd image file that includes alternate cylinders\n" " (option ignored if size is manually specified)\n" " -r build 'raw' dasd image file (no VOL1 or IPL track)\n" " -linux null track images will look like linux dasdfmt'ed images\n" " (3390 device type only)\n\n" " filename name of dasd image file to be created\n\n" " devtype CKD: 2305, 2311, 2314, 3330, 3340, 3350, 3375, 3380, 3390, 9345\n" " FBA: 0671, 3310, 3370, 9313, 9332, 9335, 9336\n\n" " model device model (implies size) (opt)\n\n" " volser volume serial number (1-6 characters)\n" " (specified only if '-r' option not used)\n\n" " size number of CKD cylinders or 512-byte FBA sectors\n" " (required if model not specified else optional)\n" ); break; } exit(code); } /* end function argexit */ /*-------------------------------------------------------------------*/ /* DASDINIT program main entry point */ /*-------------------------------------------------------------------*/ int main ( int argc, char *argv[] ) { int altcylflag = 0; /* Alternate cylinders flag */ int rawflag = 0; /* Raw format flag */ int volsize_argnum = 4; /* argc value of size option */ U32 size = 0; /* Volume size */ U32 altsize = 0; /* Alternate cylinders */ U32 heads = 0; /* Number of tracks/cylinder */ U32 maxdlen = 0; /* Maximum R1 data length */ U32 sectsize = 0; /* Sector size */ U16 devtype = 0; /* Device type */ BYTE comp = 0xff; /* Compression algoritm */ BYTE type = 0; /* C=CKD, F=FBA */ char fname[1024]; /* File name */ char volser[7]; /* Volume serial number */ BYTE c; /* Character work area */ CKDDEV *ckd; /* -> CKD device table entry */ FBADEV *fba; /* -> FBA device table entry */ int lfs = 0; /* 1 = Build large file */ int nullfmt = CKDDASD_NULLTRK_FMT1; /* Null track format type */ int rc; /* Return code */ INITIALIZE_UTILITY("dasdinit"); /* Display program identification and help */ if (argc <= 1 || (argc == 2 && !strcmp(argv[1], "-v"))) argexit(-1, NULL); /* Process optional arguments */ for ( ; argc > 1 && argv[1][0] == '-'; argv++, argc--) { if (strcmp("0", &argv[1][1]) == 0) comp = CCKD_COMPRESS_NONE; #ifdef HAVE_LIBZ else if (strcmp("z", &argv[1][1]) == 0) comp = CCKD_COMPRESS_ZLIB; #endif #ifdef CCKD_BZIP2 else if (strcmp("bz2", &argv[1][1]) == 0) comp = CCKD_COMPRESS_BZIP2; #endif else if (strcmp("a", &argv[1][1]) == 0) altcylflag = 1; else if (strcmp("r", &argv[1][1]) == 0) rawflag = 1; else if (strcmp("lfs", &argv[1][1]) == 0 && sizeof(off_t) > 4) lfs = 1; else if (strcmp("linux", &argv[1][1]) == 0) nullfmt = CKDDASD_NULLTRK_FMT2; else argexit(0, argv[1]); } /* Check remaining number of arguments */ if (argc < (rawflag ? 3 : 4) || argc > (rawflag ? 4 : 5)) argexit(5, NULL); /* The first argument is the file name */ if (argv[1] == NULL || strlen(argv[1]) == 0 || strlen(argv[1]) > sizeof(fname)-1) argexit(1, argv[1]); strcpy (fname, argv[1]); /* The second argument is the device type. Model number may also be specified */ if (argv[2] == NULL) argexit(2, argv[2]); ckd = dasd_lookup (DASD_CKDDEV, argv[2], 0, 0); if (ckd != NULL) { type = 'C'; devtype = ckd->devt; size = ckd->cyls; altsize = ckd->altcyls; heads = ckd->heads; maxdlen = ckd->r1; } else { fba = dasd_lookup (DASD_FBADEV, argv[2], 0, 0); if (fba != NULL) { type = 'F'; devtype = fba->devt; size = fba->blks; altsize = 0; sectsize = fba->size; } } if (!type) /* Specified model not found */ argexit(2, argv[2]); /* If -r option specified, then there is not volume serial argument and volume size argument is actually argument number 3 and not argument number 4 as otherwise */ if (rawflag) volsize_argnum = 3; else { volsize_argnum = 4; /* The third argument is the volume serial number */ if (argv[3] == NULL || strlen(argv[3]) == 0 || strlen(argv[3]) > sizeof(volser)-1) argexit(3, argv[3]); strcpy (volser, argv[3]); string_to_upper (volser); } /* The fourth argument (or third for -r) is the volume size */ if (argc > volsize_argnum) { if (argc > (volsize_argnum+1)) argexit(5, NULL); if (!argv[volsize_argnum] || strlen(argv[volsize_argnum]) == 0 || sscanf(argv[volsize_argnum], "%u%c", &size, &c) != 1) argexit(4, argv[volsize_argnum]); altcylflag = 0; } /* `-linux' only supported for 3390 device type */ if (nullfmt == CKDDASD_NULLTRK_FMT2 && devtype != 0x3390) argexit(6, NULL); if (altcylflag) size += altsize; /* Create the device */ if (type == 'C') rc = create_ckd (fname, devtype, heads, maxdlen, size, volser, comp, lfs, 0, nullfmt, rawflag); else rc = create_fba (fname, devtype, sectsize, size, volser, comp, lfs, 0, rawflag); /* Display completion message */ if (rc == 0) { fprintf (stderr, _("HHCDI001I DASD initialization successfully " "completed.\n")); } else { fprintf (stderr, _("HHCDI002I DASD initialization unsuccessful" "\n")); } return rc; } /* end function main */ hercules-3.07/dasdisup.c000644 000765 000765 00000066105 11143760544 016740 0ustar00jmaynardjmaynard000000 000000 /* DASDISUP.C (c) Copyright Roger Bowler, 1999-2009 */ /* Hercules DASD Utilities: IEHIOSUP */ // $Id: dasdisup.c 5125 2009-01-23 12:01:44Z bernard $ /*-------------------------------------------------------------------*/ /* This program performs the IEHIOSUP function of OS/360. */ /* It adjusts the TTRs in the XCTL tables in each of the */ /* Open/Close/EOV modules in SYS1.SVCLIB. */ /* */ /* The command format is: */ /* dasdisup ckdfile */ /* where: ckdfile is the name of the CKD image file */ /*-------------------------------------------------------------------*/ // $Log$ // Revision 1.31 2008/11/04 04:50:46 fish // Ensure consistent utility startup // // Revision 1.30 2007/06/23 00:04:08 ivan // Update copyright notices to include current year (2007) // // Revision 1.29 2006/12/08 09:43:19 jj // Add CVS message log // #include "hstdinc.h" #include "hercules.h" #include "dasdblks.h" /*-------------------------------------------------------------------*/ /* Internal macro definitions */ /*-------------------------------------------------------------------*/ #define HEX00 ((BYTE)'\x00') /* EBCDIC low value */ #define HEX40 ((BYTE)'\x40') /* EBCDIC space */ #define HEXFF ((BYTE)'\xFF') /* EBCDIC high value */ #define OVERPUNCH_ZERO ((BYTE)'\xC0') /* EBCDIC 12-0 card punch */ /*-------------------------------------------------------------------*/ /* Definition of member information array entry */ /*-------------------------------------------------------------------*/ typedef struct _MEMINFO { BYTE memname[8]; /* Member name (EBCDIC) */ BYTE ttrtext[3]; /* TTR of first text record */ BYTE dwdsize; /* Text size in doublewords */ BYTE alias; /* 1=This is an alias */ BYTE notable; /* 1=Member has no XCTL table*/ BYTE multitxt; /* 1=Member has >1 text rcd */ } MEMINFO; #define MAX_MEMBERS 1000 /* Size of member info array */ /*-------------------------------------------------------------------*/ /* Static data areas */ /*-------------------------------------------------------------------*/ /* List of first loads for Open/Close/EOV routines */ static char *firstload[] = { "IGC0001I", /* Open (SVC19) */ "IGC0002{", /* Close (SVC20) */ "IGC0002A", /* Stow (SVC21) */ "IGC0002B", /* OpenJ (SVC22) */ "IGC0002C", /* TClose (SVC23) */ "IGC0002I", /* Scratch (SVC29) */ "IGC0003A", /* FEOV (SVC31) */ "IGC0003B", /* Allocate (SVC32) */ "IGC0005E", /* EOV (SVC55) */ "IGC0008A", /* Setprt (SVC81) */ "IGC0008F", /* Atlas (SVC86) */ "IGC0009C", /* TSO (SVC93) */ "IGC0009D", /* TSO (SVC94) */ NULL }; /* End of list */ /* List of second loads for Open/Close/EOV routines */ static char *secondload[] = { "IFG019", "IGG019", /* Open (SVC19) */ "IFG020", "IGG020", /* Close (SVC20) */ "IGG021", /* Stow (SVC21) */ "IFG023", "IGG023", /* TClose (SVC23) */ "IGG029", /* Scratch (SVC29) */ "IGG032", /* Allocate (SVC32) */ "IFG055", "IGG055", /* EOV (SVC55) */ "IGG081", /* Setprt (SVC81) */ "IGG086", /* Atlas (SVC86) */ "IGG093", /* TSO (SVC93) */ "IGG094", /* TSO (SVC94) */ NULL }; /* End of list */ static BYTE eighthexFF[] = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}; #if 0 /*-------------------------------------------------------------------*/ /* Subroutine to process a member */ /* Input: */ /* cif -> CKD image file descriptor structure */ /* noext Number of extents in dataset */ /* extent Dataset extent array */ /* memname Member name (ASCIIZ) */ /* ttr Member TTR */ /* */ /* Return value is 0 if successful, or -1 if error */ /*-------------------------------------------------------------------*/ static int process_member (CIFBLK *cif, int noext, DSXTENT extent[], BYTE *memname, BYTE *ttr) { int rc; /* Return code */ int len; /* Record length */ int trk; /* Relative track number */ int cyl; /* Cylinder number */ int head; /* Head number */ int rec; /* Record number */ BYTE *buf; /* -> Data block */ FILE *ofp; /* Output file pointer */ BYTE ofname[256]; /* Output file name */ int offset; /* Offset of record in buffer*/ BYTE card[81]; /* Logical record (ASCIIZ) */ char pathname[MAX_PATH]; /* ofname in host path format*/ /* Build the output file name */ memset (ofname, 0, sizeof(ofname)); strncpy (ofname, memname, 8); string_to_lower (ofname); strcat (ofname, ".mac"); /* Open the output file */ hostpath(pathname, ofname, sizeof(pathname)); ofp = fopen (pathname, "w"); if (ofp == NULL) { fprintf (stderr, "Cannot open %s: %s\n", ofname, strerror(errno)); return -1; } /* Point to the start of the member */ trk = (ttr[0] << 8) | ttr[1]; rec = ttr[2]; fprintf (stdout, "Member %s TTR=%4.4X%2.2X\n", memname, trk, rec); /* Read the member */ while (1) { /* Convert relative track to cylinder and head */ rc = convert_tt (trk, noext, extent, cif->heads, &cyl, &head); if (rc < 0) return -1; // fprintf (stdout, // "CCHHR=%4.4X%4.4X%2.2X\n", // cyl, head, rec); /* Read a data block */ rc = read_block (cif, cyl, head, rec, NULL, NULL, &buf, &len); if (rc < 0) return -1; /* Move to next track if record not found */ if (rc > 0) { trk++; rec = 1; continue; } /* Exit at end of member */ if (len == 0) break; /* Check length of data block */ if (len % 80 != 0) { fprintf (stdout, "Bad block length %d at cyl %d head %d rec %d\n", len, cyl, head, rec); return -1; } /* Process each record in the data block */ for (offset = 0; offset < len; offset += 80) { if (asciiflag) { make_asciiz (card, sizeof(card), buf + offset, 72); fprintf (ofp, "%s\n", card); } else { fwrite (buf+offset, 80, 1, ofp); } if (ferror(ofp)) { fprintf (stdout, "Error writing %s: %s\n", ofname, strerror(errno)); return -1; } } /* end for(offset) */ /* Point to the next data block */ rec++; } /* end while */ /* Close the output file and exit */ fclose (ofp); return 0; } /* end function process_member */ #endif /*-------------------------------------------------------------------*/ /* Subroutine to process a directory block */ /* Input: */ /* cif -> CKD image file descriptor structure */ /* noext Number of extents in dataset */ /* extent Dataset extent array */ /* dirblk Pointer to directory block */ /* Input/output: */ /* memtab Member information array */ /* nmem Number of entries in member information array */ /* */ /* Directory information for each member is extracted from the */ /* directory block and saved in the member information array. */ /* */ /* Return value is 0 if OK, +1 if end of directory, or -1 if error */ /*-------------------------------------------------------------------*/ static int process_dirblk (CIFBLK *cif, int noext, DSXTENT extent[], BYTE *dirblk, MEMINFO memtab[], int *nmem) { int n; /* Member array subscript */ int i; /* Array subscript */ int totlen; /* Total module length */ int txtlen; /* Length of 1st text block */ int size; /* Size of directory entry */ int k; /* Userdata halfword count */ BYTE *dirptr; /* -> Next byte within block */ int dirrem; /* Number of bytes remaining */ PDSDIR *dirent; /* -> Directory entry */ char memnama[9]; /* Member name (ASCIIZ) */ UNREFERENCED(cif); UNREFERENCED(noext); UNREFERENCED(extent); /* Load number of bytes in directory block */ dirptr = dirblk; dirrem = (dirptr[0] << 8) | dirptr[1]; if (dirrem < 2 || dirrem > 256) { fprintf (stdout, _("HHCDS003E Directory block byte count is invalid\n")); return -1; } /* Point to first directory entry */ dirptr += 2; dirrem -= 2; /* Process each directory entry */ for (n = *nmem; dirrem > 0; ) { /* Point to next directory entry */ dirent = (PDSDIR*)dirptr; /* Test for end of directory */ if (memcmp(dirent->pds2name, eighthexFF, 8) == 0) return +1; /* Load the user data halfword count */ k = dirent->pds2indc & PDS2INDC_LUSR; /* Point to next directory entry */ size = 12 + k*2; dirptr += size; dirrem -= size; /* Extract the member name */ make_asciiz (memnama, sizeof(memnama), dirent->pds2name, 8); if (dirent->pds2name[7] == OVERPUNCH_ZERO) memnama[7] = '{'; /* Find member in first load table */ for (i = 0; firstload[i] != NULL; i++) if (strcmp(memnama, firstload[i]) == 0) break; /* If not in first table, find in second table */ if (firstload[i] == NULL) { for (i = 0; secondload[i] != NULL; i++) if (memcmp(memnama, secondload[i], 6) == 0) break; /* If not in second table then skip member */ if (secondload[i] == NULL) { fprintf (stdout, _("HHCDS018I %s %s skipped\n"), memnama, ((dirent->pds2indc & PDS2INDC_ALIAS) ? "Alias" : "Member")); continue; } } /* end if(firstload[i]==NULL) */ /* Check that member information array is not full */ if (n >= MAX_MEMBERS) { fprintf (stdout, _("HHCDS004E Number of members exceeds MAX_MEMBERS\n")); return -1; } /* Check that user data contains at least 1 TTR */ if (((dirent->pds2indc & PDS2INDC_NTTR) >> PDS2INDC_NTTR_SHIFT) < 1) { fprintf (stdout, _("HHCDS005E Member %s TTR count is zero\n"), memnama); return -1; } /* Extract the total module length */ totlen = (dirent->pds2usrd[10] << 16) | (dirent->pds2usrd[11] << 8) | dirent->pds2usrd[12]; /* Extract the length of the first text block */ txtlen = (dirent->pds2usrd[13] << 8) | dirent->pds2usrd[14]; /* Save member information in the array */ memcpy (memtab[n].memname, dirent->pds2name, 8); memcpy (memtab[n].ttrtext, dirent->pds2usrd + 0, 3); memtab[n].dwdsize = totlen / 8; /* Flag the member if it is an alias */ memtab[n].alias = (dirent->pds2indc & PDS2INDC_ALIAS) ? 1 : 0; /* Flag member if 7th character of name is non-numeric */ memtab[n].notable = (memnama[6] < '0' || memnama[6] > '9') ? 1 : 0; /* Check that the member has a single text record */ if ((dirent->pds2usrd[8] & 0x01) == 0 || totlen != txtlen) { fprintf (stdout, _("HHCDS006W Member %s is not single text record\n"), memnama); memtab[n].multitxt = 1; } /* Check that the total module length does not exceed X'7F8' */ if (totlen > 255*8) { fprintf (stdout, _("HHCDS007W Member %s size %4.4X " "exceeds X\'7F8\' bytes\n"), memnama, totlen); } /* Check that the total module length is a multiple of 8 */ if (totlen & 0x7) { fprintf (stdout, _("HHCDS008W Member %s size %4.4X " "is not a multiple of 8\n"), memnama, totlen); } /* Increment number of entries in table */ *nmem = ++n; } /* end for */ return 0; } /* end function process_dirblk */ /*-------------------------------------------------------------------*/ /* Subroutine to resolve TTRs embedded within a member */ /* Input: */ /* cif -> CKD image file descriptor structure */ /* noext Number of extents in dataset */ /* extent Dataset extent array */ /* memp Array entry for member whose TTRs are to be resolved */ /* memtab Member information array */ /* nmem Number of entries in member information array */ /* */ /* Return value is 0 if OK, -1 if error */ /*-------------------------------------------------------------------*/ static int resolve_xctltab (CIFBLK *cif, int noext, DSXTENT extent[], MEMINFO *memp, MEMINFO memtab[], int nmem) { int rc; /* Return code */ int i; /* Array subscript */ int len; /* Record length */ int cyl; /* Cylinder number */ int head; /* Head number */ int rec; /* Record number */ int trk; /* Relative track number */ int xctloff; /* Offset to XCTL table */ int warn; /* 1=Flag TTRL difference */ BYTE *blkptr; /* -> Text record data */ char memnama[9]; /* Member name (ASCIIZ) */ BYTE svcnum[3]; /* SVC number (EBCDIC) */ BYTE prefix[3]; /* IGG/IFG prefix (EBCDIC) */ BYTE refname[8]; /* Referred name (EBCDIC) */ char refnama[9]; /* Referred name (ASCIIZ) */ /* Extract the member name */ make_asciiz (memnama, sizeof(memnama), memp->memname, 8); if (memp->memname[7] == OVERPUNCH_ZERO) memnama[7] = '{'; /* Skip the member if it is an alias */ if (memp->alias) { fprintf (stdout, _("HHCDS009I Alias %s skipped\n"), memnama); return 0; } /* Skip the member if it has no XCTL table */ if (memp->notable) { fprintf (stdout, _("HHCDS010I Member %s skipped\n"), memnama); return 0; } /* Error if member is not a single text record */ if (memp->multitxt) { fprintf (stdout, _("HHCDS011E Member %s has multiple text records\n"), memnama); return -1; } /* Convert relative track to cylinder and head */ trk = (memp->ttrtext[0] << 8) | memp->ttrtext[1]; rec = memp->ttrtext[2]; rc = convert_tt (trk, noext, extent, cif->heads, &cyl, &head); if (rc < 0) { fprintf (stdout, _("HHCDS012E Member %s has invalid TTR %4.4X%2.2X\n"), memnama, trk, rec); return -1; } fprintf (stdout, _("HHCDS013I Processing member %s text record TTR=%4.4X%2.2X " "CCHHR=%4.4X%4.4X%2.2X\n"), memnama, trk, rec, cyl, head, rec); /* Read the text record */ rc = read_block (cif, cyl, head, rec, NULL, NULL, &blkptr, &len); if (rc != 0) { fprintf (stdout, _("HHCDS014E Member %s error reading TTR %4.4X%2.2X\n"), memnama, trk, rec); return -1; } /* Check for incorrect length record */ if (len < 8 || len > 1024 || (len & 0x7)) { fprintf (stdout, _("HHCDS015E Member %s TTR %4.4X%2.2X " "text record length %4.4X is not valid\n"), memnama, trk, rec, len); return -1; } /* Check that text record length matches directory entry */ if (len != memp->dwdsize * 8) { fprintf (stdout, _("HHCDS016E Member %s TTR %4.4X%2.2X " "text record length %4.4X does not match " "length %4.4X in directory\n"), memnama, trk, rec, len, memp->dwdsize * 8); return -1; } /* Extract the SVC number and the XCTL table offset from the last 4 bytes of the text record */ memcpy (svcnum, blkptr + len - 4, sizeof(svcnum)); xctloff = blkptr[len-1] * 8; /* For the first load of SVC 19, 20, 23, and 55, and for IFG modules, the table is in two parts. The parts are separated by a X'FFFF' delimiter. The first part refers to IFG modules, the second part refers to IGG modules */ if ((memcmp(memnama, "IGC", 3) == 0 && (memcmp(svcnum, "\xF0\xF1\xF9", 3) == 0 || memcmp(svcnum, "\xF0\xF2\xF0", 3) == 0 || memcmp(svcnum, "\xF0\xF2\xF3", 3) == 0 || memcmp(svcnum, "\xF0\xF5\xF5", 3) == 0)) || memcmp(memnama, "IFG", 3) == 0) convert_to_ebcdic (prefix, sizeof(prefix), "IFG"); else convert_to_ebcdic (prefix, sizeof(prefix), "IGG"); /* Process each entry in the XCTL table */ while (1) { /* Exit at end of XCTL table */ if (blkptr[xctloff] == HEX00 && blkptr[xctloff+1] == HEX00) break; /* Switch prefix at end of first part of table */ if (blkptr[xctloff] == HEXFF && blkptr[xctloff+1] == HEXFF) { xctloff += 2; convert_to_ebcdic (prefix, sizeof(prefix), "IGG"); continue; } /* Error if XCTL table overflows text record */ if (xctloff >= len - 10) { fprintf (stdout, _("HHCDS017E Member %s TTR %4.4X%2.2X " "XCTL table improperly terminated\n"), memnama, trk, rec); return -1; } /* Skip this entry if the suffix is blank */ if (blkptr[xctloff] == HEX40 && blkptr[xctloff+1] == HEX40) { xctloff += 6; continue; } /* Build the name of the member referred to */ memcpy (refname, prefix, 3); memcpy (refname + 3, svcnum, 3); memcpy (refname + 6, blkptr+xctloff, 2); make_asciiz (refnama, sizeof(refnama), refname, 8); /* Display XCTL table entry */ fprintf (stdout, _("HHCDS019I In member %s: %s TTRL=%2.2X%2.2X%2.2X%2.2X"), memnama, refnama, blkptr[xctloff+2], blkptr[xctloff+3], blkptr[xctloff+4], blkptr[xctloff+5]); /* Find the referred member in the member array */ for (i = 0; i < nmem; i++) { if (memcmp(memtab[i].memname, refname, 8) == 0) break; } /* end for(i) */ /* Loop if member not found */ if (i == nmem) { fprintf (stdout, " ** Member %s not found **\n", refnama); xctloff += 6; continue; } /* Loop if TTRL in the XCTL table matches actual TTRL */ if (memcmp(blkptr+xctloff+2, memtab[i].ttrtext, 3) == 0 && blkptr[xctloff+5] == memtab[i].dwdsize) { fprintf (stdout, "\n"); xctloff += 6; continue; } /* Flag entries whose L differs */ if (blkptr[xctloff+5] != memtab[i].dwdsize) warn = 1; else warn = 0; /* Replace TTRL in the XCTL table by the actual TTRL */ memcpy (blkptr+xctloff+2, memtab[i].ttrtext, 3); blkptr[xctloff+5] = memtab[i].dwdsize; fprintf (stdout, " replaced by TTRL=%2.2X%2.2X%2.2X%2.2X %s\n", blkptr[xctloff+2], blkptr[xctloff+3], blkptr[xctloff+4], blkptr[xctloff+5], (warn ? "****" : "")); /* Flag the track as modified to force rewrite */ cif->trkmodif = 1; /* Point to next entry in XCTL table */ xctloff += 6; } /* end while */ return 0; } /* end function resolve_xctltab */ /*-------------------------------------------------------------------*/ /* DASDISUP main entry point */ /*-------------------------------------------------------------------*/ int main (int argc, char *argv[]) { int rc; /* Return code */ int i; /* Array subscript */ int len; /* Record length */ int cyl; /* Cylinder number */ int head; /* Head number */ int rec; /* Record number */ int trk; /* Relative track number */ char *fname; /* -> CKD image file name */ char *sfname; /* -> CKD shadow file name */ int noext; /* Number of extents */ DSXTENT extent[16]; /* Extent descriptor array */ BYTE *blkptr; /* -> PDS directory block */ CIFBLK *cif; /* CKD image file descriptor */ MEMINFO *memtab; /* -> Member info array */ int nmem = 0; /* Number of array entries */ INITIALIZE_UTILITY("dasdisup"); /* Display the program identification message */ display_version (stderr, "Hercules IEHIOSUP program ", FALSE); /* Check the number of arguments */ if (argc < 2 || argc > 3) { fprintf (stdout, "Usage: %s ckdfile [sf=shadow-file-name]\n", argv[0]); return -1; } /* The first argument is the name of the CKD image file */ fname = argv[1]; /* The next argument, if there, is the name of the shadow file */ if (argc > 2) sfname = argv[2]; else sfname = NULL; /* Obtain storage for the member information array */ memtab = (MEMINFO*) malloc (sizeof(MEMINFO) * MAX_MEMBERS); if (memtab == NULL) { fprintf (stdout, _("HHCDS001E Cannot obtain storage for member array: %s\n"), strerror(errno)); return -1; } /* Open the CKD image file */ cif = open_ckd_image (fname, sfname, O_RDWR|O_BINARY, 0); if (cif == NULL) return -1; /* Build the extent array for the SVCLIB dataset */ rc = build_extent_array (cif, "SYS1.SVCLIB", extent, &noext); if (rc < 0) return -1; /* Point to the start of the directory */ trk = 0; rec = 1; /* Read the directory */ while (1) { /* Convert relative track to cylinder and head */ rc = convert_tt (trk, noext, extent, cif->heads, &cyl, &head); if (rc < 0) return -1; /* Read a directory block */ rc = read_block (cif, cyl, head, rec, NULL, NULL, &blkptr, &len); if (rc < 0) return -1; /* Move to next track if block not found */ if (rc > 0) { trk++; rec = 1; continue; } /* Exit at end of directory */ if (len == 0) break; /* Extract information for each member in directory block */ rc = process_dirblk (cif, noext, extent, blkptr, memtab, &nmem); if (rc < 0) return -1; if (rc > 0) break; /* Point to the next directory block */ rec++; } /* end while */ fprintf (stdout, _("HHCDS002I End of directory: %d members selected\n"), nmem); #ifdef EXTERNALGUI if (extgui) fprintf (stderr,"NMEM=%d\n",nmem); #endif /*EXTERNALGUI*/ /* Read each member and resolve the embedded TTRs */ for (i = 0; i < nmem; i++) { #ifdef EXTERNALGUI if (extgui) fprintf (stderr,"MEM=%d\n",i); #endif /*EXTERNALGUI*/ rc = resolve_xctltab (cif, noext, extent, memtab+i, memtab, nmem); } /* end for(i) */ /* Close the CKD image file and exit */ rc = close_ckd_image (cif); free (memtab); return rc; } /* end function main */ hercules-3.07/dasdload.c000644 000765 000765 00000546567 11143760543 016715 0ustar00jmaynardjmaynard000000 000000 /* DASDLOAD.C (c) Copyright Roger Bowler, 1999-2009 */ /* Hercules DASD Utilities: DASD image loader */ // $Id: dasdload.c 5125 2009-01-23 12:01:44Z bernard $ /*-------------------------------------------------------------------*/ /* This program creates a virtual DASD volume from a list of */ /* datasets previously unloaded using the TSO XMIT command. */ /*-------------------------------------------------------------------*/ /*-------------------------------------------------------------------*/ /* Additional credits: */ /* Corrections to CVOL initialization logic by Jay Maynard */ /* IEBCOPY native dataset support by Ronen Tzur */ /*-------------------------------------------------------------------*/ // $Log$ // Revision 1.54 2008/11/04 04:50:46 fish // Ensure consistent utility startup // // Revision 1.53 2007/06/23 00:04:08 ivan // Update copyright notices to include current year (2007) // // Revision 1.52 2007/05/24 21:13:27 rbowler // Circumvent MSVC optimizer bug in cvol_initialize function // // Revision 1.51 2006/12/08 09:43:19 jj // Add CVS message log // #include "hstdinc.h" #include "hercules.h" #include "dasdblks.h" /*-------------------------------------------------------------------*/ /* Internal table sizes */ /*-------------------------------------------------------------------*/ #define MAXDBLK 10000 /* Maximum number of directory blocks per dataset */ #define MAXTTR 50000 /* Maximum number of TTRs per dataset */ #define MAXDSCB 1000 /* Maximum number of DSCBs */ /*-------------------------------------------------------------------*/ /* Internal macro definitions */ /*-------------------------------------------------------------------*/ #define CASERET(s) case s: return (#s) #define XMINF info_msg #define XMINFF info_msg #define XMERR printf #define XMERRF printf #define R0_DATALEN 8 #define IPL1_KEYLEN 4 #define IPL1_DATALEN 24 #define IPL2_KEYLEN 4 #define IPL2_DATALEN 144 #define VOL1_KEYLEN 4 #define VOL1_DATALEN 80 #define EBCDIC_END "\xC5\xD5\xC4" #define EBCDIC_TXT "\xE3\xE7\xE3" /*-------------------------------------------------------------------*/ /* Definition of LOGREC header record */ /*-------------------------------------------------------------------*/ typedef struct _DIPHDR { HWORD recid; /* Record identifier (0xFFFF)*/ HWORD bcyl; /* Extent begin cylinder */ HWORD btrk; /* Extent begin track */ HWORD ecyl; /* Extent end cylinder */ HWORD etrk; /* Extent end track */ BYTE resv; /* Unused */ BYTE restart[7]; /* Restart area BBCCHHR */ HWORD trkbal; /* Bytes remaining on track */ HWORD trklen; /* Total bytes on track */ BYTE reused[7]; /* Last reused BBCCHHR */ HWORD lasthead; /* Last track on cylinder */ HWORD trklen90; /* 90% of track length */ BYTE devcode; /* Device type code */ BYTE cchh90[4]; /* 90% full track CCHH */ BYTE switches; /* Switches */ BYTE endid; /* Check byte (0xFF) */ } DIPHDR; /*-------------------------------------------------------------------*/ /* Definition of internal extent descriptor array entry */ /*-------------------------------------------------------------------*/ typedef struct _EXTDESC { U16 bcyl; /* Begin cylinder */ U16 btrk; /* Begin track */ U16 ecyl; /* End cylinder */ U16 etrk; /* End track */ U16 ntrk; /* Number of tracks */ } EXTDESC; /*-------------------------------------------------------------------*/ /* Definition of internal TTR conversion table array entry */ /*-------------------------------------------------------------------*/ typedef struct _TTRCONV { BYTE origttr[3]; /* TTR in original dataset */ BYTE outpttr[3]; /* TTR in output dataset */ } TTRCONV; /*-------------------------------------------------------------------*/ /* Definitions for dataset initialization methods */ /*-------------------------------------------------------------------*/ #define METHOD_EMPTY 0 #define METHOD_XMIT 1 #define METHOD_DIP 2 #define METHOD_CVOL 3 #define METHOD_VTOC 4 #define METHOD_VS 5 #define METHOD_SEQ 6 /*-------------------------------------------------------------------*/ /* Static data areas */ /*-------------------------------------------------------------------*/ static BYTE eighthexFF[] = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}; BYTE twelvehex00[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; BYTE cvol_low_key[] = {0, 0, 0, 0, 0, 0, 0, 1}; BYTE iplpsw[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; BYTE iplccw1[8] = {0x06, 0x00, 0x3A, 0x98, 0x60, 0x00, 0x00, 0x60}; BYTE iplccw2[8] = {0x08, 0x00, 0x3A, 0x98, 0x00, 0x00, 0x00, 0x00}; BYTE ipl2data[] = {0x07, 0x00, 0x3A, 0xB8, 0x40, 0x00, 0x00, 0x06, 0x31, 0x00, 0x3A, 0xBE, 0x40, 0x00, 0x00, 0x05, 0x08, 0x00, 0x3A, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x19, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*BBCCHH*/ 0x00, 0x00, 0x00, 0x00, 0x04}; /*CCHHR*/ BYTE noiplpsw[8] = {0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F}; BYTE noiplccw1[8] = {0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}; BYTE noiplccw2[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; /* Information message level: 0=None, 1=File name, 2=File information, 3=Member information, 4=Text units, record headers, 5=Dump data */ int infolvl = 1; /*-------------------------------------------------------------------*/ /* Subroutine to display command syntax and exit */ /*-------------------------------------------------------------------*/ static void argexit ( int code ) { fprintf (stderr, "dasdload creates a DASD image file from a list " "of TSO XMIT files\n" "Syntax:\tdasdload [options] ctlfile outfile [msglevel]\n" "where:\tctlfile = name of input control file\n" "\toutfile = name of DASD image file to be created\n" "\tmsglevel = Value 0-5 controls output verbosity\n" "\noptions:\n" "\t-0: no compression (default)\n" "\t-a: output disk will include alternate cylinders\n" #ifdef CCKD_COMPRESS_ZLIB "\t-z: compress using zlib\n" #endif #ifdef CCKD_COMPRESS_BZIP2 "\t-bz2: compress using bzip2\n" #endif ); if (sizeof(off_t) > 4) fprintf (stderr, "\t-lfs: create single large output file\n" ); exit(code); } /* end function argexit */ /*-------------------------------------------------------------------*/ /* Subroutine to display an informational message */ /*-------------------------------------------------------------------*/ static void info_msg (int lvl, char *msg, ...) { va_list vl; if (infolvl >= lvl) { va_start(vl, msg); vprintf (msg, vl); } } /* end function info_msg */ /*-------------------------------------------------------------------*/ /* Subroutine to load a S/390 integer value from a buffer */ /*-------------------------------------------------------------------*/ static int make_int (BYTE *src, int srclen) { int result = 0; /* Result accumulator */ int i; /* Array subscript */ for (i=0; i < srclen; i++) { result <<= 8; result |= src[i]; } return result; } /* end function make_int */ /*-------------------------------------------------------------------*/ /* Subroutine to return the name of a dataset organization */ /*-------------------------------------------------------------------*/ static char * dsorg_name (BYTE *dsorg) { static char name[8]; /* Name of dsorg */ if (dsorg[0] & DSORG_IS) strcpy (name, "IS"); else if (dsorg[0] & DSORG_PS) strcpy (name, "PS"); else if (dsorg[0] & DSORG_DA) strcpy (name, "DA"); else if (dsorg[0] & DSORG_PO) strcpy (name, "PO"); if (dsorg[0] & DSORG_U) strcat (name, "U"); return name; } /* end function dsorg_name */ /*-------------------------------------------------------------------*/ /* Subroutine to return the name of a record format */ /*-------------------------------------------------------------------*/ static char * recfm_name (BYTE *recfm) { static char name[8]; /* Name of record format */ switch (recfm[0] & RECFM_FORMAT) { case RECFM_FORMAT_V: strcpy (name, "V"); break; case RECFM_FORMAT_F: strcpy (name, "F"); break; case RECFM_FORMAT_U: strcpy (name, "U"); break; default: strcpy (name,"??"); } /* end switch */ if (recfm[0] & RECFM_TRKOFLOW) strcat (name, "T"); if (recfm[0] & RECFM_BLOCKED) strcat (name, "B"); if (recfm[0] & RECFM_SPANNED) strcat (name, "S"); switch (recfm[0] & RECFM_CTLCHAR) { case RECFM_CTLCHAR_A: strcpy (name, "A"); break; case RECFM_CTLCHAR_M: strcpy (name, "M"); break; } /* end switch */ return name; } /* end function recfm_name */ /*-------------------------------------------------------------------*/ /* Subroutine to return the name of a DASD device from the UCB type */ /*-------------------------------------------------------------------*/ static char * dasd_name (FWORD ucbtype) { if (ucbtype[2] != 0x20) return "????"; switch (ucbtype[3]) { case 0x01: return "2311"; case 0x02: return "2301"; case 0x03: return "2303"; case 0x04: if (ucbtype[1] == 0x00) return "2302"; else return "9345"; case 0x05: return "2321"; case 0x06: return "2305-1"; case 0x07: return "2305-2"; case 0x08: return "2314"; case 0x09: return "3330"; case 0x0A: return "3340"; case 0x0B: return "3350"; case 0x0C: return "3375"; case 0x0D: return "3330-11"; case 0x0E: return "3380"; case 0x0F: return "3390"; } /* end switch(key) */ return "????"; } /* end function dasd_name */ /*-------------------------------------------------------------------*/ /* Subroutine to return the UCBTYPE of a DASD device */ /*-------------------------------------------------------------------*/ static U32 ucbtype_code (U16 devtype) { switch (devtype) { case 0x2311: return 0x30002001; case 0x2301: return 0x30402002; case 0x2303: return 0x30002003; case 0x2302: return 0x30002004; case 0x2321: return 0x30002005; case 0x2305: return 0x30002006; case 0x2314: return 0x30C02008; case 0x3330: return 0x30502009; case 0x3340: return 0x3050200A; case 0x3350: return 0x3050200B; case 0x3375: return 0x3050200C; case 0x3380: return 0x3050200E; case 0x3390: return 0x3050200F; case 0x9345: return 0x30502004; } /* end switch(key) */ return 0; } /* end function ucbtype_code */ /*-------------------------------------------------------------------*/ /* Subroutine to calculate relative track address */ /* Input: */ /* cyl Cylinder number */ /* head Head number */ /* heads Number of heads per cylinder */ /* numext Number of extents */ /* xarray Array containing 1-16 extent descriptions */ /* Output: */ /* The return value is the relative track number, */ /* or -1 if an error occurred. */ /*-------------------------------------------------------------------*/ static int calculate_ttr (int cyl, int head, int heads, int numext, EXTDESC xarray[]) { int i; /* Array subscript */ int track; /* Relative track number */ /* Search the extent descriptor array */ for (i = 0, track = 0; i < numext; track += xarray[i++].ntrk) { if (cyl < xarray[i].bcyl || cyl > xarray[i].ecyl) continue; if (cyl == xarray[i].bcyl && head < xarray[i].btrk) continue; if (cyl == xarray[i].ecyl && head > xarray[i].etrk) continue; track += (cyl - xarray[i].bcyl) * heads - xarray[i].btrk + head; break; } /* end for(i) */ /* Error if track was not found in extent table */ if (i == numext) { XMERRF ("HHCDL033E CCHH=%4.4X%4.4X not found in extent table\n", cyl, head); return -1; } /* Return relative track number */ return track; } /* end function calculate_ttr */ /*-------------------------------------------------------------------*/ /* Subroutine to read IPL text from an EBCDIC object file */ /* Input: */ /* iplfnm Name of EBCDIC card image object file */ /* iplbuf Address of buffer in which to build IPL text record */ /* buflen Length of buffer */ /* Output: */ /* The return value is the length of the IPL text built */ /* in the buffer if successful, or -1 if error */ /* Note: */ /* Only TXT records are processed; ESD and RLD records are */ /* ignored because the IPL text is non-relocatable and is */ /* assumed to have zero origin. An END card must be present. */ /*-------------------------------------------------------------------*/ static int read_ipl_text (char *iplfnm, BYTE *iplbuf, int buflen) { int rc; /* Return code */ int ipllen = 0; /* Length of IPL text */ int txtlen; /* Byte count from TXT card */ int txtadr; /* Address from TXT card */ int tfd; /* Object file descriptor */ BYTE objrec[80]; /* Object card image */ char pathname[MAX_PATH]; /* iplfnm in host path format*/ /* Open the object file */ hostpath(pathname, iplfnm, sizeof(pathname)); tfd = open (pathname, O_RDONLY|O_BINARY); if (tfd < 0) { XMERRF ("HHCDL034E Cannot open %s: %s\n", iplfnm, strerror(errno)); return -1; } /* Read the object file */ while (1) { /* Read a card image from the object file */ rc = read (tfd, objrec, 80); if (rc < 80) { XMERRF ("HHCDL035E Cannot read %s: %s\n", iplfnm, strerror(errno)); close (tfd); return -1; } /* Column 1 of each object card must contain X'02' */ if (objrec[0] != 0x02) { XMERRF ("HHCDL036E %s is not a valid object file\n", iplfnm); close (tfd); return -1; } /* Exit if END card has been read */ if (memcmp(objrec+1, EBCDIC_END, 3) == 0) break; /* Ignore any cards which are not TXT cards */ if (memcmp(objrec+1, EBCDIC_TXT, 3) != 0) continue; /* Load the address from TXT card columns 6-8 */ txtadr = (objrec[5] << 16) | (objrec[6] << 8) | objrec[7]; /* Load the byte count from TXT card columns 11-12 */ txtlen = (objrec[10] << 8) | objrec[11]; XMINFF (5, "HHCDL037I IPL text address=%6.6X length=%4.4X\n", txtadr, txtlen); /* Check that the byte count is valid */ if (txtlen > 56) { XMERRF ("HHCDL038E TXT record in %s has invalid count %d\n", iplfnm, txtlen); close (tfd); return -1; } /* Check that the text falls within the buffer */ if (txtadr + txtlen > buflen) { XMERRF ("HHCDL039E IPL text in %s exceeds %d bytes\n", iplfnm, buflen); close (tfd); return -1; } /* Copy the IPL text to the buffer */ memcpy (iplbuf + txtadr, objrec+16, txtlen); /* Update the total size of the IPL text */ if (txtadr + txtlen > ipllen) ipllen = txtadr + txtlen; } /* end while */ return ipllen; } /* end function read_ipl_text */ /*-------------------------------------------------------------------*/ /* Subroutine to initialize the output track buffer */ /* Input: */ /* trklen Track length of virtual output device */ /* trkbuf Pointer to track buffer */ /* cyl Cylinder number on output device */ /* head Head number on output device */ /* Output: */ /* usedv Number of bytes written to track of virtual device */ /*-------------------------------------------------------------------*/ static void init_track (int trklen, BYTE *trkbuf, int cyl, int head, int *usedv) { CKDDASD_TRKHDR *trkhdr; /* -> Track header */ CKDDASD_RECHDR *rechdr; /* -> Record header */ /* Clear the track buffer to zeroes */ memset (trkbuf, 0, trklen); /* Build the home address in the track buffer */ trkhdr = (CKDDASD_TRKHDR*)trkbuf; trkhdr->bin = 0; trkhdr->cyl[0] = (cyl >> 8) & 0xFF; trkhdr->cyl[1] = cyl & 0xFF; trkhdr->head[0] = (head >> 8) & 0xFF; trkhdr->head[1] = head & 0xFF; /* Build a standard record zero in the track buffer */ rechdr = (CKDDASD_RECHDR*)(trkbuf + CKDDASD_TRKHDR_SIZE); rechdr->cyl[0] = (cyl >> 8) & 0xFF; rechdr->cyl[1] = cyl & 0xFF; rechdr->head[0] = (head >> 8) & 0xFF; rechdr->head[1] = head & 0xFF; rechdr->rec = 0; rechdr->klen = 0; rechdr->dlen[0] = (R0_DATALEN >> 8) & 0xFF; rechdr->dlen[1] = R0_DATALEN & 0xFF; /* Set number of bytes used in track buffer */ *usedv = CKDDASD_TRKHDR_SIZE + CKDDASD_RECHDR_SIZE + R0_DATALEN; /* Build end of track marker at end of buffer */ memcpy (trkbuf + *usedv, eighthexFF, 8); } /* end function init_track */ /*-------------------------------------------------------------------*/ /* Subroutine to write track buffer to output file */ /* Input: */ /* cif -> CKD image file descriptor */ /* ofname Output file name */ /* heads Number of tracks per cylinder on output device */ /* trklen Track length of virtual output device */ /* Input/output: */ /* usedv Number of bytes written to track of virtual device */ /* reltrk Relative track number on output device */ /* cyl Cylinder number on output device */ /* head Head number on output device */ /* Output: */ /* The return value is 0 if successful, -1 if error occurred. */ /*-------------------------------------------------------------------*/ static int write_track (CIFBLK *cif, char *ofname, int heads, int trklen, int *usedv, int *reltrk, int *cyl, int *head) { int rc; /* Return code */ UNREFERENCED(ofname); UNREFERENCED(trklen); /* Don't overwrite HA */ if (*usedv == 0) *usedv = CKDDASD_TRKHDR_SIZE; /* Build end of track marker at end of buffer */ memcpy (cif->trkbuf + *usedv, eighthexFF, 8); cif->trkmodif = 1; /* Reset values for next track */ (*reltrk)++; (*head)++; if (*head >= heads) { (*cyl)++; *head = 0; } *usedv = 0; /* Read the next track */ if (*cyl < (int)cif->devblk.ckdcyls) { rc = read_track (cif, *cyl, *head); if (rc < 0) return -1; } return 0; } /* end function write_track */ /*-------------------------------------------------------------------*/ /* Subroutine to add a data block to the output track buffer */ /* Input: */ /* cif -> CKD image file descriptor */ /* ofname Output file name */ /* blk Pointer to data block */ /* keylen Key length */ /* datalen Data length */ /* devtype Output device type */ /* heads Number of tracks per cylinder on output device */ /* trklen Track length of virtual output device */ /* maxtrk Maximum number of tracks to be written */ /* Input/output: */ /* usedv Number of bytes written to track of virtual device */ /* usedr Number of bytes written to track, calculated */ /* according to the formula for a real device */ /* trkbal Number of bytes remaining on track, calculated */ /* according to the formula for a real device */ /* reltrk Relative track number on output device */ /* cyl Cylinder number on output device */ /* head Head number on output device */ /* rec Record number on output device */ /* Output: */ /* The return value is 0 if successful, -1 if error occurred. */ /*-------------------------------------------------------------------*/ static int write_block (CIFBLK *cif, char *ofname, DATABLK *blk, int keylen, int datalen, U16 devtype, int heads, int trklen, int maxtrk, int *usedv, int *usedr, int *trkbal, int *reltrk, int *cyl, int *head, int *rec) { int rc; /* Return code */ int cc; /* Capacity calculation code */ CKDDASD_RECHDR *rechdr; /* -> Record header */ UNREFERENCED(devtype); /* Determine whether record will fit on current track */ cc = capacity_calc (cif, *usedr, keylen, datalen, usedr, trkbal, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); if (cc < 0) return -1; /* Move to next track if record will not fit */ if (cc > 0 && *usedr > 0) { /* Write current track to output file */ rc = write_track (cif, ofname, heads, trklen, usedv, reltrk, cyl, head); if (rc < 0) return -1; /* Clear bytes used and record number for new track */ *usedr = 0; *rec = 0; /* Determine whether record will fit on new track */ cc = capacity_calc (cif, *usedr, keylen, datalen, usedr, trkbal, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); if (cc < 0) return -1; } /* end if */ /* Error if record will not even fit on an empty track */ if (cc > 0) { XMERRF ("HHCDL040E Input record CCHHR=%2.2X%2.2X%2.2X%2.2X%2.2X " "exceeds output device track size\n", blk->cyl[0], blk->cyl[1], blk->head[0], blk->head[1], blk->rec); return -1; } /* Determine whether end of extent has been reached */ if (*reltrk >= maxtrk) { XMERRF ("HHCDL041E Dataset exceeds extent size: reltrk=%d, " "maxtrk=%d\n", *reltrk, maxtrk); return -1; } /* Build home address and record 0 if new track */ if (*usedv == 0) { init_track (trklen, cif->trkbuf, *cyl, *head, usedv); } /* Double check that record will not exceed virtual track size */ if (*usedv + CKDDASD_RECHDR_SIZE + keylen + datalen + 8 > trklen) { XMERRF ("HHCDL042E Input record CCHHR=%2.2X%2.2X%2.2X%2.2X%2.2X " "exceeds virtual device track size\n", blk->cyl[0], blk->cyl[1], blk->head[0], blk->head[1], blk->rec); return -1; } /* Add data block to virtual track buffer */ (*rec)++; rechdr = (CKDDASD_RECHDR*)(cif->trkbuf + *usedv); rechdr->cyl[0] = (*cyl >> 8) & 0xFF; rechdr->cyl[1] = *cyl & 0xFF; rechdr->head[0] = (*head >> 8) & 0xFF; rechdr->head[1] = *head & 0xFF; rechdr->rec = *rec; rechdr->klen = keylen; rechdr->dlen[0] = (datalen >> 8) & 0xFF; rechdr->dlen[1] = datalen & 0xFF; *usedv += CKDDASD_RECHDR_SIZE; memcpy (cif->trkbuf + *usedv, blk->kdarea, keylen + datalen); *usedv += keylen + datalen; cif->trkmodif = 1; return 0; } /* end function write_block */ /*-------------------------------------------------------------------*/ /* Subroutine to write track zero */ /* Input: */ /* cif -> CKD image file descriptor */ /* ofname Output file name */ /* volser Volume serial number (ASCIIZ) */ /* devtype Output device type */ /* heads Number of tracks per cylinder on output device */ /* trklen Track length of virtual output device */ /* iplfnm Name of file containing IPL text object deck */ /* Output: */ /* reltrk Next relative track number on output device */ /* outcyl Cylinder number of next track on output device */ /* outhead Head number of next track on output device */ /* The return value is 0 if successful, -1 if error occurred. */ /*-------------------------------------------------------------------*/ static int write_track_zero (CIFBLK *cif, char *ofname, char *volser, U16 devtype, int heads, int trklen, char *iplfnm, int *reltrk, int *outcyl, int *outhead) { int rc; /* Return code */ int outusedv = 0; /* Output bytes used on track of virtual device */ int outusedr = 0; /* Output bytes used on track of real device */ int outtrkbr = 0; /* Output bytes remaining on track of real device */ int outtrk = 0; /* Output relative track */ int outrec = 0; /* Output record number */ int keylen; /* Key length */ int datalen; /* Data length */ int maxtrks = 1; /* Maximum track count */ DATABLK *datablk; /* -> data block */ BYTE buf[4096]; /* Buffer for data block */ /* For 2311 the IPL text will not fit on track 0 record 4, so adjust the IPL2 so that it loads from track 1 record 1 */ if (devtype == 0x2311) { memcpy (ipl2data + 32, "\x00\x00\x00\x00\x00\x01", 6); memcpy (ipl2data + 38, "\x00\x00\x00\x01\x01", 5); maxtrks = 2; } /* Read track 0 */ rc = read_track (cif, 0, 0); if (rc < 0) return -1; /* Initialize the track buffer */ *outcyl = 0; *outhead = 0; init_track (trklen, cif->trkbuf, *outcyl, *outhead, &outusedv); cif->trkmodif = 1; /* Build the IPL1 record */ memset (buf, 0, sizeof(buf)); datablk = (DATABLK*)buf; convert_to_ebcdic (datablk->kdarea, 4, "IPL1"); if (iplfnm != NULL) { memcpy (datablk->kdarea+4, iplpsw, 8); memcpy (datablk->kdarea+12, iplccw1, 8); memcpy (datablk->kdarea+20, iplccw2, 8); } else { memcpy (datablk->kdarea+4, noiplpsw, 8); memcpy (datablk->kdarea+12, noiplccw1, 8); memcpy (datablk->kdarea+20, noiplccw2, 8); } keylen = IPL1_KEYLEN; datalen = IPL1_DATALEN; rc = write_block (cif, ofname, datablk, keylen, datalen, devtype, heads, trklen, maxtrks, &outusedv, &outusedr, &outtrkbr, &outtrk, outcyl, outhead, &outrec); if (rc < 0) return -1; /* Build the IPL2 record */ memset (buf, 0, sizeof(buf)); datablk = (DATABLK*)buf; convert_to_ebcdic (datablk->kdarea, 4, "IPL2"); if (iplfnm != NULL) { memcpy (datablk->kdarea+4, ipl2data, sizeof(ipl2data)); } keylen = IPL2_KEYLEN; datalen = IPL2_DATALEN; rc = write_block (cif, ofname, datablk, keylen, datalen, devtype, heads, trklen, maxtrks, &outusedv, &outusedr, &outtrkbr, &outtrk, outcyl, outhead, &outrec); if (rc < 0) return -1; /* Build the VOL1 record */ memset (buf, 0x40, sizeof(buf)); datablk = (DATABLK*)buf; convert_to_ebcdic (datablk->kdarea, 4, "VOL1"); convert_to_ebcdic (datablk->kdarea+4, 4, "VOL1"); convert_to_ebcdic (datablk->kdarea+8, 6, volser); memset(datablk->kdarea+15, 0, 5); convert_to_ebcdic (datablk->kdarea+45, 8, "HERCULES"); keylen = VOL1_KEYLEN; datalen = VOL1_DATALEN; rc = write_block (cif, ofname, datablk, keylen, datalen, devtype, heads, trklen, maxtrks, &outusedv, &outusedr, &outtrkbr, &outtrk, outcyl, outhead, &outrec); if (rc < 0) return -1; /* Build the IPL text from the object file */ if (iplfnm != NULL) { memset (buf, 0, sizeof(buf)); datalen = read_ipl_text (iplfnm, buf+12, sizeof(buf)-12); if (datalen < 0) return -1; datablk = (DATABLK*)buf; keylen = 0; rc = write_block (cif, ofname, datablk, keylen, datalen, devtype, heads, trklen, maxtrks, &outusedv, &outusedr, &outtrkbr, &outtrk, outcyl, outhead, &outrec); if (rc < 0) return -1; } /* Write track zero to the output file */ rc = write_track (cif, ofname, heads, trklen, &outusedv, reltrk, outcyl, outhead); if (rc < 0) return -1; return 0; } /* end function write_track_zero */ /*-------------------------------------------------------------------*/ /* Subroutine to update a data block in the output file */ /* Input: */ /* cif -> CKD image file descriptor */ /* ofname Output file name */ /* blk Pointer to data block structure */ /* cyl Cylinder number */ /* head Head number */ /* rec Record number */ /* keylen Key length */ /* datalen Data length */ /* heads Number of tracks per cylinder on output device */ /* trklen Track length of virtual output device */ /* Output: */ /* The return value is 0 if successful, -1 if error occurred. */ /*-------------------------------------------------------------------*/ static int update_block (CIFBLK *cif, char *ofname, DATABLK *blk, int cyl, int head, int rec, int keylen, int datalen, int heads, int trklen) { int rc; /* Return code */ int curcyl; /* Original cylinder */ int curhead; /* Original head */ int klen; /* Record key length */ int dlen; /* Record data length */ int skiplen; /* Number of bytes to skip */ int offset; /* Offset into trkbuf */ CKDDASD_TRKHDR trkhdr; /* Track header */ CKDDASD_RECHDR rechdr; /* Record header */ UNREFERENCED(heads); UNREFERENCED(trklen); /* Save the current position in the output file */ curcyl = cif->curcyl; curhead = cif->curhead; /* Read the requested track */ rc = read_track (cif, cyl, head); if (rc < 0) { XMERRF ("HHCDL043E %s cyl %d head %d read error\n", ofname, cyl, head); return -1; } /* Copy the track header */ memcpy (&trkhdr, cif->trkbuf, CKDDASD_TRKHDR_SIZE); offset = CKDDASD_TRKHDR_SIZE; /* Validate the track header */ if (trkhdr.bin != 0 || trkhdr.cyl[0] != (cyl >> 8) || trkhdr.cyl[1] != (cyl & 0xFF) || trkhdr.head[0] != (head >> 8) || trkhdr.head[1] != (head & 0xFF)) { XMERRF ("HHCDL044E %s cyl %d head %d invalid track header " "%2.2X%2.2X%2.2X%2.2X%2.2X\n", ofname, cyl, head, trkhdr.bin, trkhdr.cyl[0], trkhdr.cyl[1], trkhdr.head[0], trkhdr.head[1]); return -1; } /* Search for the record to be updated */ while (1) { /* Copy the next record header */ memcpy (&rechdr, cif->trkbuf + offset, CKDDASD_RECHDR_SIZE); offset += CKDDASD_RECHDR_SIZE; /* Check for end of track */ if (memcmp(&rechdr, eighthexFF, 8) == 0) { XMERRF ("HHCDL045E %s cyl %d head %d rec %d record not found\n", ofname, cyl, head, rec); return -1; } /* Extract record key length and data length */ klen = rechdr.klen; dlen = (rechdr.dlen[0] << 8) | rechdr.dlen[1]; /* Exit loop if matching record number */ if (rechdr.rec == rec) break; /* Skip the key and data areas */ skiplen = klen + dlen; offset += skiplen; } /* end while */ /* Check for attempt to change key length or data length */ if (keylen != klen || datalen != dlen) { XMERRF ("HHCDL046E Cannot update cyl %d head %d rec %d: " "Unmatched KL/DL\n", cyl, head, rec); return -1; } /* Copy the updated block to the trkbuf */ memcpy (cif->trkbuf + offset, blk->kdarea, keylen + datalen); cif->trkmodif = 1; /* Restore original track */ rc = read_track (cif, curcyl, curhead); if (rc < 0) { XMERRF ("HHCDL047E %s cyl %d head %d read error\n", ofname, curcyl, curhead); return -1; } XMINFF (4, "HHCDL048I Updating cyl %u head %u rec %d kl %d dl %d\n", cyl, head, rec, keylen, datalen); return 0; } /* end function update_block */ /*-------------------------------------------------------------------*/ /* Subroutine to build a format 1 DSCB */ /* Input: */ /* dscbtab Array of pointers to DSCB data blocks */ /* dscbnum Number of entries in dscbtab array */ /* dsname Dataset name (ASCIIZ) */ /* volser Volume serial number (ASCIIZ) */ /* dsorg 1st byte of dataset organization bits */ /* recfm 1st byte of record format bits */ /* lrecl Logical record length */ /* blksz Block size */ /* keyln Key length */ /* dirblu Bytes used in last directory block */ /* lasttrk Relative track number of last-used track of dataset */ /* lastrec Record number of last-used block of dataset */ /* trkbal Bytes remaining on last-used track */ /* units Allocation units (C=CYL, T=TRK) */ /* spsec Secondary allocation quantity */ /* bcyl Extent begin cylinder number */ /* bhead Extent begin head number */ /* ecyl Extent end cylinder number */ /* ehead Extent end head number */ /* Output: */ /* The return value is 0 if successful, or -1 if error */ /* */ /* This subroutine allocates a DATABLK structure, builds a DSCB */ /* within the structure, and adds the structure to the DSCB array. */ /*-------------------------------------------------------------------*/ static int build_format1_dscb (DATABLK *dscbtab[], int dscbnum, char *dsname, char *volser, BYTE dsorg, BYTE recfm, int lrecl, int blksz, int keyln, int dirblu, int lasttrk, int lastrec, int trkbal, BYTE units, int spsec, int bcyl, int bhead, int ecyl, int ehead) { DATABLK *datablk; /* -> Data block structure */ FORMAT1_DSCB *f1dscb; /* -> DSCB within data block */ int blklen; /* Size of data block */ struct tm *tmptr; /* -> Date and time structure*/ time_t timeval; /* Current time value */ /* Obtain the current time */ time(&timeval); tmptr = localtime(&timeval); /* Allocate storage for a DATABLK structure */ blklen = 12 + sizeof(FORMAT1_DSCB); datablk = (DATABLK*)malloc(blklen); if (datablk == NULL) { XMERRF ("HHCDL049E Cannot obtain storage for DSCB: %s\n", strerror(errno)); return -1; } /* Check that there is room in the DSCB pointer array */ if (dscbnum >= MAXDSCB) { XMERRF ("HHCDL050E DSCB count exceeds %d, increase MAXDSCB\n", MAXDSCB); return -1; } /* Clear the data block and save its address in the DSCB array */ memset (datablk, 0, blklen); dscbtab[dscbnum] = datablk; /* Point to the DSCB within the data block */ f1dscb = (FORMAT1_DSCB*)(datablk->kdarea); /* Build the format 1 DSCB */ convert_to_ebcdic (f1dscb->ds1dsnam, 44, dsname); f1dscb->ds1fmtid = 0xF1; convert_to_ebcdic (f1dscb->ds1dssn, 6, volser); f1dscb->ds1volsq[0] = 0; f1dscb->ds1volsq[1] = 1; f1dscb->ds1credt[0] = tmptr->tm_year; f1dscb->ds1credt[1] = (tmptr->tm_yday >> 8) & 0xFF; f1dscb->ds1credt[2] = tmptr->tm_yday & 0xFF; f1dscb->ds1expdt[0] = 0; f1dscb->ds1expdt[1] = 0; f1dscb->ds1expdt[2] = 0; f1dscb->ds1noepv = 1; f1dscb->ds1bodbd = dirblu; convert_to_ebcdic (f1dscb->ds1syscd, 13, "HERCULES"); f1dscb->ds1dsorg[0] = dsorg; f1dscb->ds1dsorg[1] = 0; f1dscb->ds1recfm = recfm; f1dscb->ds1optcd = 0; f1dscb->ds1blkl[0] = (blksz >> 8) & 0xFF; f1dscb->ds1blkl[1] = blksz & 0xFF; f1dscb->ds1lrecl[0] = (lrecl >> 8) & 0xFF; f1dscb->ds1lrecl[1] = lrecl & 0xFF; f1dscb->ds1keyl = keyln; f1dscb->ds1rkp[0] = 0; f1dscb->ds1rkp[1] = 0; f1dscb->ds1dsind = DS1DSIND_LASTVOL; if ((blksz & 0x07) == 0) f1dscb->ds1dsind |= DS1DSIND_BLKSIZ8; f1dscb->ds1scalo[0] = (units == 'C' ? DS1SCALO_UNITS_CYL : DS1SCALO_UNITS_TRK); f1dscb->ds1scalo[1] = (spsec >> 16) & 0xFF; f1dscb->ds1scalo[2] = (spsec >> 8) & 0xFF; f1dscb->ds1scalo[3] = spsec & 0xFF; f1dscb->ds1lstar[0] = (lasttrk >> 8) & 0xFF; f1dscb->ds1lstar[1] = lasttrk & 0xFF; f1dscb->ds1lstar[2] = lastrec; f1dscb->ds1trbal[0] = (trkbal >> 8) & 0xFF; f1dscb->ds1trbal[1] = trkbal & 0xFF; f1dscb->ds1ext1.xttype = (units == 'C' ? XTTYPE_CYLBOUND : XTTYPE_DATA); f1dscb->ds1ext1.xtseqn = 0; f1dscb->ds1ext1.xtbcyl[0] = (bcyl >> 8) & 0xFF; f1dscb->ds1ext1.xtbcyl[1] = bcyl & 0xFF; f1dscb->ds1ext1.xtbtrk[0] = (bhead >> 8) & 0xFF; f1dscb->ds1ext1.xtbtrk[1] = bhead & 0xFF; f1dscb->ds1ext1.xtecyl[0] = (ecyl >> 8) & 0xFF; f1dscb->ds1ext1.xtecyl[1] = ecyl & 0xFF; f1dscb->ds1ext1.xtetrk[0] = (ehead >> 8) & 0xFF; f1dscb->ds1ext1.xtetrk[1] = ehead & 0xFF; return 0; } /* end function build_format1_dscb */ /*-------------------------------------------------------------------*/ /* Subroutine to build a format 4 DSCB */ /* Input: */ /* dscbtab Array of pointers to DSCB data blocks */ /* dscbnum Number of entries in dscbtab array */ /* devtype Output device type */ /* Output: */ /* The return value is 0 if successful, or -1 if error */ /* */ /* This subroutine allocates a DATABLK structure, builds a DSCB */ /* within the structure, and adds the structure to the DSCB array. */ /* */ /* Note: The VTOC extent descriptor, the highest F1 DSCB address, */ /* and the number of unused DSCBs, are set to zeroes here and must */ /* be updated later when the VTOC size and location are known. */ /* The device size in cylinders is set to the normal size for the */ /* device type and must be updated when the actual total number of */ /* cylinders written to the volume is known. */ /*-------------------------------------------------------------------*/ static int build_format4_dscb (DATABLK *dscbtab[], int dscbnum, CIFBLK *cif) { DATABLK *datablk; /* -> Data block structure */ FORMAT4_DSCB *f4dscb; /* -> DSCB within data block */ int blklen; /* Size of data block */ int numdscb; /* Number of DSCBs per track */ int numdblk; /* Number of dir blks/track */ int physlen; /* Physical track length */ int numcyls; /* Device size in cylinders */ int numheads; /* Number of heads/cylinder */ int kbconst; /* Keyed block constant */ int lbconst; /* Last keyed block constant */ int nkconst; /* Non-keyed block constant */ BYTE devflag; /* Device flags for VTOC */ int tolfact; /* Device tolerance */ /* Calculate the physical track length, block overheads, device size, and the number of DSCBs and directory blocks per track */ capacity_calc (cif, 0, 44, 96, NULL, NULL, &physlen, &kbconst, &lbconst, &nkconst, &devflag, &tolfact, NULL, &numdscb, &numheads, &numcyls); capacity_calc (cif, 0, 8, 256, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &numdblk, NULL, NULL); /* Allocate storage for a DATABLK structure */ blklen = 12 + sizeof(FORMAT4_DSCB); datablk = (DATABLK*)malloc(blklen); if (datablk == NULL) { XMERRF ("HHCDL051E Cannot obtain storage for DSCB: %s\n", strerror(errno)); return -1; } /* Check that there is room in the DSCB pointer array */ if (dscbnum >= MAXDSCB) { XMERRF ("HHCDL052E DSCB count exceeds %d, increase MAXDSCB\n", MAXDSCB); return -1; } /* Clear the data block and save its address in the DSCB array */ memset (datablk, 0, blklen); dscbtab[dscbnum] = datablk; /* Point to the DSCB within the data block */ f4dscb = (FORMAT4_DSCB*)(datablk->kdarea); /* Build the format 4 DSCB */ memset (f4dscb->ds4keyid, 0x04, 44); f4dscb->ds4fmtid = 0xF4; f4dscb->ds4hcchh[0] = (numcyls >> 8) & 0xFF; f4dscb->ds4hcchh[1] = numcyls & 0xFF; f4dscb->ds4hcchh[2] = 0; f4dscb->ds4hcchh[3] = 0; f4dscb->ds4noatk[0] = 0; f4dscb->ds4noatk[1] = 0; f4dscb->ds4vtoci = DS4VTOCI_DOS; f4dscb->ds4noext = 1; f4dscb->ds4devsz[0] = (numcyls >> 8) & 0xFF; f4dscb->ds4devsz[1] = numcyls & 0xFF; f4dscb->ds4devsz[2] = (numheads >> 8) & 0xFF; f4dscb->ds4devsz[3] = numheads & 0xFF; f4dscb->ds4devtk[0] = (physlen >> 8) & 0xFF; f4dscb->ds4devtk[1] = physlen & 0xFF; f4dscb->ds4devi = kbconst; f4dscb->ds4devl = lbconst; f4dscb->ds4devk = nkconst; f4dscb->ds4devfg = devflag; f4dscb->ds4devtl[0] = (tolfact >> 8) & 0xFF; f4dscb->ds4devtl[1] = tolfact & 0xFF; f4dscb->ds4devdt = numdscb; f4dscb->ds4devdb = numdblk; return 0; } /* end function build_format4_dscb */ /*-------------------------------------------------------------------*/ /* Subroutine to build a format 5 DSCB */ /* Input: */ /* dscbtab Array of pointers to DSCB data blocks */ /* dscbnum Number of entries in dscbtab array */ /* Output: */ /* The return value is 0 if successful, or -1 if error */ /* */ /* This subroutine allocates a DATABLK structure, builds a DSCB */ /* within the structure, and adds the structure to the DSCB array. */ /* */ /* Note: The format 5 DSCB is built with no free space extents. */ /* The DOS bit which is set in ds4vtoci forces the operating system */ /* VTOC conversion routine to calculate the free space and update */ /* the format 5 DSCB the first time the volume is accessed. */ /*-------------------------------------------------------------------*/ static int build_format5_dscb (DATABLK *dscbtab[], int dscbnum) { DATABLK *datablk; /* -> Data block structure */ FORMAT5_DSCB *f5dscb; /* -> DSCB within data block */ int blklen; /* Size of data block */ /* Allocate storage for a DATABLK structure */ blklen = 12 + sizeof(FORMAT5_DSCB); datablk = (DATABLK*)malloc(blklen); if (datablk == NULL) { XMERRF ("HHCDL053E Cannot obtain storage for DSCB: %s\n", strerror(errno)); return -1; } /* Check that there is room in the DSCB pointer array */ if (dscbnum >= MAXDSCB) { XMERRF ("HHCDL054E DSCB count exceeds %d, increase MAXDSCB\n", MAXDSCB); return -1; } /* Clear the data block and save its address in the DSCB array */ memset (datablk, 0, blklen); dscbtab[dscbnum] = datablk; /* Point to the DSCB within the data block */ f5dscb = (FORMAT5_DSCB*)(datablk->kdarea); /* Build the format 5 DSCB */ memset (f5dscb->ds5keyid, 0x05, 4); f5dscb->ds5fmtid = 0xF5; return 0; } /* end function build_format5_dscb */ /*-------------------------------------------------------------------*/ /* Subroutine to write the VTOC */ /* Input: */ /* dscbtab Array of pointers to DSCB data blocks */ /* numdscb Number of DSCBs including format 4 and format 5 */ /* cif -> CKD image file descriptor */ /* ofname Output file name */ /* devtype Output device type */ /* reqcyls Requested device size in cylinders, or zero */ /* heads Number of tracks per cylinder on output device */ /* trklen Track length of virtual output device */ /* vtoctrk Starting relative track number for VTOC, or zero */ /* vtocext Number of tracks in VTOC, or zero */ /* Input/output: */ /* nxtcyl Starting cylinder number for next dataset */ /* nxthead Starting head number for next dataset */ /* Output: */ /* volvtoc VTOC starting CCHHR (5 bytes) */ /* The return value is 0 if successful, or -1 if error */ /* */ /* If vtoctrk and vtocext are non-zero, then the VTOC is written */ /* into the space previously reserved at the indicated location. */ /* Otherwise, the VTOC is written at the next available dataset */ /* location, using as many tracks as are necessary, and nextcyl */ /* and nexthead are updated to point past the end of the VTOC. */ /*-------------------------------------------------------------------*/ static int write_vtoc (DATABLK *dscbtab[], int numdscb, CIFBLK *cif, char *ofname, U16 devtype, int reqcyls, int heads, int trklen, int vtoctrk, int vtocext, int *nxtcyl, int *nxthead, BYTE volvtoc[]) { int rc; /* Return code */ int i; /* Array subscript */ DATABLK *datablk; /* -> Data block structure */ FORMAT1_DSCB *f1dscb; /* -> Format 1 DSCB */ FORMAT4_DSCB *f4dscb; /* -> Format 4 DSCB */ int dscbpertrk; /* Number of DSCBs per track */ int mintrks; /* Minimum VTOC size (tracks)*/ int numtrks; /* Actual VTOC size (tracks) */ int highcyl; /* Last used cylinder number */ int highhead; /* Last used head number */ int highrec; /* Last used record number */ int numf0dscb; /* Number of unused DSCBs */ int abstrk; /* Absolute track number */ int endcyl; /* VTOC end cylinder number */ int endhead; /* VTOC end head number */ int numcyls; /* Volume size in cylinders */ int outusedv = 0; /* Bytes used in track buffer*/ int outusedr = 0; /* Bytes used on real track */ int outtrkbr; /* Bytes left on real track */ int outcyl; /* Output cylinder number */ int outhead; /* Output head number */ int outtrk = 0; /* Relative track number */ int outrec = 0; /* Output record number */ int prealloc = 0; /* 1=VTOC is preallocated */ BYTE blankblk[152]; /* Data block for blank DSCB */ int curcyl; /* Current cylinder in file */ int curhead; /* Current head in file */ char dsnama[45]; /* Dataset name (ASCIIZ) */ /* Determine if the VTOC is preallocated */ prealloc = (vtoctrk != 0 && vtocext != 0); /* Point to the format 4 DSCB within the first data block */ f4dscb = (FORMAT4_DSCB*)(dscbtab[0]->kdarea); /* Calculate the minimum number of tracks required for the VTOC */ dscbpertrk = f4dscb->ds4devdt; mintrks = (numdscb + dscbpertrk - 1) / dscbpertrk; /* Save the current position in the output file */ curcyl = cif->curcyl; curhead = cif->curhead; /* Obtain the VTOC starting location and size */ if (prealloc) { /* Use preallocated VTOC location */ outcyl = vtoctrk / heads; outhead = vtoctrk % heads; numtrks = vtocext; } else { /* Use next available dataset location for VTOC */ outcyl = *nxtcyl; outhead = *nxthead; numtrks = mintrks; } /* Check that VTOC extent size is sufficient */ if (numtrks < mintrks) { XMERRF ("HHCDL055E VTOC too small, %d track%s required\n", mintrks, (mintrks == 1 ? "" : "s")); return -1; } /* Read the first track of the VTOC */ rc = read_track (cif, outcyl, outhead); if (rc < 0) { XMERRF ("HHCDL056E Error reading VTOC cyl %d head %d\n", outcyl, outhead); return -1; } /* Calculate the CCHHR of the last format 1 DSCB */ abstrk = (outcyl * heads) + outhead; abstrk += mintrks - 1; highcyl = abstrk / heads; highhead = abstrk % heads; highrec = ((numdscb - 1) % dscbpertrk) + 1; /* Update the last format 1 CCHHR in the format 4 DSCB */ f4dscb->ds4hpchr[0] = (highcyl >> 8) & 0xFF; f4dscb->ds4hpchr[1] = highcyl & 0xFF; f4dscb->ds4hpchr[2] = (highhead >> 8) & 0xFF; f4dscb->ds4hpchr[3] = highhead & 0xFF; f4dscb->ds4hpchr[4] = highrec; /* Build the VTOC start CCHHR */ volvtoc[0] = (outcyl >> 8) & 0xFF; volvtoc[1] = outcyl & 0xFF; volvtoc[2] = (outhead >> 8) & 0xFF; volvtoc[3] = outhead & 0xFF; volvtoc[4] = 1; XMINFF (1, "HHCDL057I VTOC starts at cyl %d head %d and is %d track%s\n", outcyl, outhead, numtrks, (numtrks == 1 ? "" : "s")); /* Calculate the number of format 0 DSCBs required to fill out the unused space at the end of the VTOC */ numf0dscb = (numtrks * dscbpertrk) - numdscb; /* Update the format 0 DSCB count in the format 4 DSCB */ f4dscb->ds4dsrec[0] = (numf0dscb >> 8) & 0xFF; f4dscb->ds4dsrec[1] = numf0dscb & 0xFF; /* Calculate the CCHH of the last track of the VTOC */ abstrk = (outcyl * heads) + outhead; abstrk += numtrks - 1; endcyl = abstrk / heads; endhead = abstrk % heads; /* Update the VTOC extent descriptor in the format 4 DSCB */ f4dscb->ds4vtoce.xttype = (endhead == heads - 1 ? XTTYPE_CYLBOUND : XTTYPE_DATA); f4dscb->ds4vtoce.xtseqn = 0; f4dscb->ds4vtoce.xtbcyl[0] = (outcyl >> 8) & 0xFF; f4dscb->ds4vtoce.xtbcyl[1] = outcyl & 0xFF; f4dscb->ds4vtoce.xtbtrk[0] = (outhead >> 8) & 0xFF; f4dscb->ds4vtoce.xtbtrk[1] = outhead & 0xFF; f4dscb->ds4vtoce.xtecyl[0] = (endcyl >> 8) & 0xFF; f4dscb->ds4vtoce.xtecyl[1] = endcyl & 0xFF; f4dscb->ds4vtoce.xtetrk[0] = (endhead >> 8) & 0xFF; f4dscb->ds4vtoce.xtetrk[1] = endhead & 0xFF; /* Calculate the mimimum volume size */ if (prealloc) { /* The VTOC was preallocated, so the minimum volume size equals the next available cylinder number */ numcyls = *nxtcyl; if (*nxthead != 0) numcyls++; } else { /* The VTOC will be written into the available space, so the minimum volume size is one more than the ending cylinder number of the VTOC */ numcyls = endcyl + 1; } /* If the minimum volume size is less than the requested size then use the requested size as the actual size */ if (numcyls < reqcyls) numcyls = reqcyls; /* Update the volume size in cylinders in the format 4 DSCB */ f4dscb->ds4devsz[0] = (numcyls >> 8) & 0xFF; f4dscb->ds4devsz[1] = numcyls & 0xFF; /* Format the track buffer */ init_track (trklen, cif->trkbuf, outcyl, outhead, &outusedv); cif->trkmodif = 1; /* Write the format 4, format 5, and format 1 DSCBs to the VTOC */ for (i = 0; i < numdscb; i++) { /* Load the data block pointer from the DSCB table */ datablk = dscbtab[i]; /* Extract the dataset name from the format 1 DSCB */ memset (dsnama, 0, sizeof(dsnama)); f1dscb = (FORMAT1_DSCB*)(datablk->kdarea); if (f1dscb->ds1fmtid == 0xF1) { make_asciiz (dsnama, sizeof(dsnama), f1dscb->ds1dsnam, sizeof(f1dscb->ds1dsnam)); } /* Add next DSCB to the track buffer */ rc = write_block (cif, ofname, datablk, 44, 96, devtype, heads, trklen, numtrks, &outusedv, &outusedr, &outtrkbr, &outtrk, &outcyl, &outhead, &outrec); if (rc < 0) return -1; XMINFF (4, "HHCDL058I Format %d DSCB CCHHR=%4.4X%4.4X%2.2X " "(TTR=%4.4X%2.2X) %s\n", datablk->kdarea[0] == 0x04 ? 4 : datablk->kdarea[0] == 0x05 ? 5 : 1, outcyl, outhead, outrec, outtrk, outrec, dsnama); if (infolvl >= 5) data_dump (datablk, 152); } /* end for(i) */ /* Fill the remainder of the VTOC with format 0 DSCBs */ for (i = 0; i < numf0dscb; i++) { /* Add a format 0 DSCB to the track buffer */ memset (blankblk, 0, sizeof(blankblk)); datablk = (DATABLK*)blankblk; rc = write_block (cif, ofname, datablk, 44, 96, devtype, heads, trklen, numtrks, &outusedv, &outusedr, &outtrkbr, &outtrk, &outcyl, &outhead, &outrec); if (rc < 0) return -1; XMINFF (4, "HHCDL059I Format 0 DSCB CCHHR=%4.4X%4.4X%2.2X " "(TTR=%4.4X%2.2X)\n", outcyl, outhead, outrec, outtrk, outrec); } /* end for(i) */ /* Write data remaining in last track buffer */ rc = write_track (cif, ofname, heads, trklen, &outusedv, &outtrk, &outcyl, &outhead); if (rc < 0) return -1; /* Restore original file position if VTOC was preallocated */ if (prealloc) { /* Read the original track again */ rc = read_track (cif, curcyl, curhead); if (rc < 0) { XMERRF ("HHCDL060E Error reading track cyl %d head %d\n", curcyl, curhead); return -1; } } else { /* Update next cyl and head if VTOC not preallocated */ *nxtcyl = outcyl; *nxthead = outhead; } return 0; } /* end function write_vtoc */ /*-------------------------------------------------------------------*/ /* Subroutine to return the name of a text unit */ /*-------------------------------------------------------------------*/ static char * tu_name (U16 key) { switch (key) { CASERET(INMDDNAM); CASERET(INMDSNAM); CASERET(INMMEMBR); CASERET(INMDIR ); CASERET(INMEXPDT); CASERET(INMTERM ); CASERET(INMBLKSZ); CASERET(INMDSORG); CASERET(INMLRECL); CASERET(INMRECFM); CASERET(INMTNODE); CASERET(INMTUID ); CASERET(INMFNODE); CASERET(INMFUID ); CASERET(INMLREF ); CASERET(INMLCHG ); CASERET(INMCREAT); CASERET(INMFVERS); CASERET(INMFTIME); CASERET(INMTTIME); CASERET(INMFACK ); CASERET(INMERRCD); CASERET(INMUTILN); CASERET(INMUSERP); CASERET(INMRECCT); CASERET(INMSIZE ); CASERET(INMFFM ); CASERET(INMNUMF ); CASERET(INMTYPE ); } /* end switch(key) */ return "????????"; } /* end function tu_name */ /*-------------------------------------------------------------------*/ /* Subroutine to extract next text unit from buffer */ /* Input: */ /* xbuf Pointer to start of buffer */ /* bufpos Position of next text unit within buffer */ /* bufrem Number of bytes remaining in buffer */ /* pkey Pointer to field to receive text unit key */ /* pnum Pointer to field to receive number of data items */ /* maxnum Maximum number of data items expected */ /* plen Pointer to array to receive data item lengths */ /* pdata Pointer to array to receive data item pointers */ /* Output: */ /* The function return value is the total length of the */ /* text unit, or -1 if error. */ /* */ /* Text units are listed if infolvl is 4 or greater. */ /*-------------------------------------------------------------------*/ static int next_tu (BYTE *xbuf, int bufpos, int bufrem, U16 *pkey, U16 *pnum, U16 maxnum, U16 plen[], BYTE *pdata[]) { int i, j; /* Array subscripts */ U16 key, num; /* Text unit header */ int field; /* Field number */ int offset; /* Offset into text unit */ U16 len; /* Field length */ char *name; /* Text unit name */ BYTE c, chars[9]; /* Character work areas */ char hex[17]; /* Character work areas */ set_codepage(NULL); /* Error if remaining length is insufficient for header */ if (bufrem < 4) { XMERR ("HHCDL061E Incomplete text unit\n"); return -1; } /* Load the key and field count from the first 4 bytes */ key = (xbuf[bufpos] << 8) | xbuf[bufpos+1]; num = (xbuf[bufpos+2] << 8) | xbuf[bufpos+3]; /* Obtain the text unit name */ name = tu_name(key); /* Print the text unit name and field count */ XMINFF (4, "HHCDL062I \t+%4.4X %-8.8s %4.4X %4.4X ", bufpos, name, key, num); /* Error if number of fields exceeds maximum */ if (num > maxnum) { XMINF (4, "\n"); XMERR ("HHCDL063E Too many fields in text unit\n"); return -1; } /* Point to first field */ offset = 4; bufrem -= 4; /* Process each field in text unit */ for (field = 0; field < num; field++) { /* Error if remaining length is insufficient for length */ if (bufrem < 2) { XMINF (4, "\n"); XMERR ("HHCDL064E Incomplete text unit\n"); return -1; } /* Load field length from next 2 bytes */ len = (xbuf[bufpos+offset] << 8) | xbuf[bufpos+offset+1]; offset += 2; bufrem -= 2; /* Error if remaining length is insufficient for data */ if (bufrem < len) { XMINF (4, "\n"); XMERR ("HHCDL065E Incomplete text unit\n"); return -1; } /* Print field length and data */ if (field > 0) XMINF (4, "\n\t\t\t\t "); XMINFF (4, "%4.4X ", len); memset (hex, '\0', sizeof(hex)); memset (chars, '\0', sizeof(chars)); for (i = 0, j = 0; i < len; i++, j++) { if (i > 0 && (i & 0x07) == 0) { XMINFF (4, "%-16.16s %-8.8s\n\t\t\t\t ", hex, chars); memset (hex, '\0', sizeof(hex)); memset (chars, '\0', sizeof(chars)); j = 0; } sprintf(hex+2*j, "%2.2X", xbuf[bufpos+offset+i]); c = guest_to_host(xbuf[bufpos+offset+i]); if (!isprint(c)) c = '.'; chars[j] = c; } /* end for(i) */ XMINFF (4, "%-16.16s %-8.8s", hex, chars); /* Save field length and pointer in array */ plen[field] = len; pdata[field] = xbuf + bufpos + offset; /* Get offset of next field in text unit */ offset += len; bufrem -= len; } /* end for */ /* Print newline at end of text unit */ XMINF (4, "\n"); /* Return key, number of fields, and total length */ *pkey = key; *pnum = num; return offset; } /* end function next_tu */ /*-------------------------------------------------------------------*/ /* Subroutine to assemble a logical record from segments */ /* Input: */ /* xfd Input file descriptor */ /* xfname Input file name */ /* xbuf Pointer to buffer to receive logical record */ /* Output: */ /* ctl Zero=data record, non-zero=control record */ /* The return value is the logical record length, */ /* or -1 if an error occurred. */ /*-------------------------------------------------------------------*/ static int read_xmit_rec (int xfd, char *xfname, BYTE *xbuf, BYTE *ctl) { int rc; /* Return code */ int xreclen = 0; /* Cumulative record length */ int segnum; /* Segment counter */ int seglen; /* Segment data length */ BYTE ctlind = 0x00; /* 0x20=Control record */ BYTE seghdr[2]; /* Segment length and flags */ for (segnum = 0; ; segnum++) { /* Read the segment length and flags */ rc = read (xfd, seghdr, 2); if (rc < 2) { XMERRF ("HHCDL066E %s read error: %s\n", xfname, (rc < 0 ? strerror(errno) : "Unexpected end of file")); return -1; } /* Check for valid segment header */ if (seghdr[0] < 2 || (seghdr[1] & 0x1F) != 0) { XMERRF ("HHCDL067E %s invalid segment header: %2.2X%2.2X\n", xfname, seghdr[0], seghdr[1]); return -1; } /* Check flags for first segment */ if (segnum == 0) { /* Check that first segment indicator is set */ if ((seghdr[1] & 0x80) == 0) { XMERRF ("HHCDL068E %s first segment indicator expected\n", xfname); return -1; } /* Save the control record indicator */ ctlind = (seghdr[1] & 0x20); } /* Check flags for subsequent segments */ if (segnum > 0) { /* Check that first segment indicator is not set */ if (seghdr[1] & 0x80) { XMERRF ("HHCDL069E %s first segment indicator not expected\n", xfname); return -1; } /* Check if ctlrec indicator matches first segment */ if ((seghdr[1] & 0x20) != ctlind) { XMERRF ("HHCDL070E %s control record indicator mismatch\n", xfname); return -1; } } /* Read segment data into buffer */ seglen = seghdr[0] - 2; rc = read (xfd, xbuf + xreclen, seglen); if (rc < seglen) { XMERRF ("HHCDL071E %s read error: %s\n", xfname, (rc < 0 ? strerror(errno) : "Unexpected end of file")); return -1; } /* Accumulate total record length */ xreclen += seglen; /* Exit if last segment of record */ if (seghdr[1] & 0x40) break; } /* end for(segnum) */ /* Return record length and control indicator */ *ctl = ctlind; return xreclen; } /* end function read_xmit_rec */ /*-------------------------------------------------------------------*/ /* Subroutine to assemble a logical record from DSORG=VS file */ /* Input: */ /* xfd Input file descriptor */ /* xfname Input file name */ /* xbuf Pointer to buffer to receive logical record */ /* recnum Relative number for the record to be read */ /* Output: */ /* The return value is the logical record length, */ /* or -1 if an error occurred. */ /*-------------------------------------------------------------------*/ static int read_vs_rec (int xfd, char *xfname, BYTE *xbuf, int recnum) { int rc; /* Return code */ int xreclen; /* Cumulative record length */ DATABLK *datablk; /* Data block */ if (recnum == 0) { xreclen = read(xfd, xbuf, 56); /* read COPYR1 plus some extras */ if (xreclen < 56) { XMERRF ("HHCDL072E %s read error: %s\n", xfname, (xreclen < 0 ? strerror(errno) : "Unexpected end of file")); return -1; } } else if (recnum == 1) { xreclen = read(xfd, xbuf, sizeof(COPYR2)); /* read COPYR2 */ if (xreclen < (int)sizeof(COPYR2)) { XMERRF ("HHCDL073E %s read error: %s\n", xfname, (xreclen < 0 ? strerror(errno) : "Unexpected end of file")); return -1; } } else { rc = read(xfd, xbuf, 12); /* read header of DATABLK */ if (rc == 0) /* read nothing? */ return 0; if (rc < 12) { XMERRF ("HHCDL074E %s read error: %s\n", xfname, (rc < 0 ? strerror(errno) : "Unexpected end of file")); return -1; } datablk = (DATABLK *)xbuf; xreclen = ((datablk->dlen[0] << 8) | datablk->dlen[1]) + datablk->klen; rc = read(xfd, xbuf + 12, xreclen); /* read kdarea of DATABLK */ if (rc < xreclen) { XMERRF ("HHCDL075E %s read error: %s\n", xfname, (rc < 0 ? strerror(errno) : "Unexpected end of file")); return -1; } xreclen += 12; /* also count the header */ } /* Return record length */ return xreclen; } /* end function read_vs_rec */ /*-------------------------------------------------------------------*/ /* Subroutine to process an INMR02 control record */ /* Input: */ /* xbuf Pointer to buffer containing control record */ /* xreclen Length of control record */ /* filen Pointer to field to receive file sequence number */ /* dsorg Pointer to byte to receive dataset organization */ /* recfm Pointer to byte to receive record format */ /* lrecl Pointer to integer to receive logical record length */ /* blksz Pointer to integer to receive block size */ /* keyln Pointer to integer to receive key length */ /* dirnm Pointer to integer to number of directory blocks */ /* Output: */ /* If the record contains the text unit INMUTILN=IEBCOPY */ /* then the dataset attributes are returned and the function */ /* return value is 1. Otherwise the return value is 0 */ /* and the dataset attributes remain unchanged. */ /* If an error occurs then the return value is -1. */ /* */ /* File information is listed if infolvl is 2 or greater. */ /*-------------------------------------------------------------------*/ static int process_inmr02 (BYTE *xbuf, int xreclen, int *filen, BYTE *dsorg, BYTE *recfm, U16 *lrecl, U16 *blksz, U16 *keyln, U16 *dirnm) { int rc; /* Return code */ int i; /* Array subscript */ int len; /* String length */ U32 filenum; /* File number */ int bufpos; /* Position of TU in buffer */ int bufrem; /* Bytes remaining in buffer */ char tuutiln[9]; /* Utility name */ BYTE tukeyln; /* Key length */ HWORD tudsorg; /* Data set organization */ HWORD turecfm; /* Record format */ U16 tulrecl; /* Logical record length */ U16 tublksz; /* Block size */ int tudirct; /* Number of directory blocks*/ U16 tukey; /* Text unit key */ U16 tunum; /* Number of text unit fields*/ char tudsnam[45]; /* Data set name */ #define MAXNUM 20 /* Maximum number of fields */ U16 fieldlen[MAXNUM]; /* Array of field lengths */ BYTE *fieldptr[MAXNUM]; /* Array of field pointers */ /* Extract the file number which follows the record name */ filenum = (xbuf[6] << 24) | (xbuf[7] << 16) | (xbuf[8] << 8) | xbuf[9]; XMINFF (4, "HHCDL076I File number: %d\n", filenum); /* Point to the first text unit */ bufpos = 10; bufrem = xreclen-10; /* Clear values to be loaded from text units */ memset (tudsnam, 0, sizeof(tudsnam)); memset (tuutiln, 0, sizeof(tuutiln)); memset (tudsorg, 0, sizeof(tudsorg)); memset (turecfm, 0, sizeof(turecfm)); tulrecl = 0; tublksz = 0; tukeyln = 0; tudirct = 0; /* Process each text unit */ while (bufrem > 0) { /* Extract the next text unit */ rc = next_tu (xbuf, bufpos, bufrem, &tukey, &tunum, MAXNUM, fieldlen, fieldptr); if (rc < 0) { XMERRF ("HHCDL077E Invalid text unit at offset %4.4X\n", bufpos + 2); return -1; } bufpos += rc; bufrem -= rc; /* Save the values from selected text units */ switch (tukey) { case INMUTILN: make_asciiz (tuutiln, sizeof(tuutiln), fieldptr[0], fieldlen[0]); break; case INMDSORG: if (fieldlen[0] > sizeof(tudsorg)) fieldlen[0] = sizeof(tudsorg); memcpy (tudsorg, fieldptr[0], fieldlen[0]); break; case INMRECFM: if (fieldlen[0] > sizeof(turecfm)) fieldlen[0] = sizeof(turecfm); memcpy (turecfm, fieldptr[0], fieldlen[0]); break; case INMLRECL: tulrecl = make_int (fieldptr[0], fieldlen[0]); break; case INMBLKSZ: tublksz = make_int (fieldptr[0], fieldlen[0]); break; case INMTYPE: tukeyln = make_int (fieldptr[0], fieldlen[0]); break; case INMDIR: tudirct = make_int (fieldptr[0], fieldlen[0]); break; case INMDSNAM: memset (tudsnam, 0, sizeof(tudsnam)); for (i = 0; i < tunum; i++) { len = strlen(tudsnam); if (i > 0 && len < (int)(sizeof(tudsnam) - 1)) tudsnam[len++] = '.'; make_asciiz (tudsnam + len, sizeof(tudsnam) - len, fieldptr[i], fieldlen[i]); } /* end for(i) */ } /* end switch(tukey) */ } /* end while(bufrem) */ /* Return the dataset values if this is the IEBCOPY record */ if (strcmp(tuutiln, "IEBCOPY") == 0) { XMINFF (2, "HHCDL078I File %u: DSNAME=%s\n", filenum, tudsnam); XMINFF (2, "HHCDL079I DSORG=%s RECFM=%s " "LRECL=%d BLKSIZE=%d KEYLEN=%d DIRBLKS=%d\n", dsorg_name(tudsorg), recfm_name(turecfm), tulrecl, tublksz, tukeyln, tudirct); *filen = filenum; *dsorg = tudsorg[0]; *recfm = turecfm[0]; *lrecl = tulrecl; *blksz = tublksz; *keyln = tukeyln; *dirnm = tudirct; } return 0; } /* end function process_inmr02 */ /*-------------------------------------------------------------------*/ /* Subroutine to process a control record other than INMR02 */ /* Input: */ /* xbuf Pointer to buffer containing control record */ /* xreclen Length of control record */ /* Output: */ /* The return value is 0 if successful, or -1 if error. */ /*-------------------------------------------------------------------*/ static int process_inmrxx (BYTE *xbuf, int xreclen) { int rc; /* Return code */ int bufpos; /* Position of TU in buffer */ int bufrem; /* Bytes remaining in buffer */ U16 tukey; /* Text unit key */ U16 tunum; /* Number of text unit fields*/ #define MAXNUM 20 /* Maximum number of fields */ U16 fieldlen[MAXNUM]; /* Array of field lengths */ BYTE *fieldptr[MAXNUM]; /* Array of field pointers */ /* Point to the first text unit */ bufpos = 6; bufrem = xreclen-6; /* Process each text unit */ while (bufrem > 0) { /* Extract the next text unit */ rc = next_tu (xbuf, bufpos, bufrem, &tukey, &tunum, MAXNUM, fieldlen, fieldptr); if (rc < 0) { XMERRF ("HHCDL080E Invalid text unit at offset %4.4X\n", bufpos + 2); return -1; } bufpos += rc; bufrem -= rc; } /* end while(bufrem) */ return 0; } /* end function process_inmrxx */ /*-------------------------------------------------------------------*/ /* Subroutine to process a COPYR1 header record */ /* Input: */ /* xbuf Pointer to buffer containing header record */ /* xreclen Length of header record */ /* Output: */ /* The return value is the number of tracks per cylinder, */ /* or -1 if an error occurred. */ /*-------------------------------------------------------------------*/ static int process_copyr1 (BYTE *xbuf, int xreclen) { COPYR1 *copyr1 = (COPYR1*)xbuf; /* -> COPYR1 header record */ U16 blksize; /* Block size */ U16 lrecl; /* Logical record length */ BYTE keylen; /* Key length */ U16 cyls; /* Number of cylinders */ U16 heads; /* Number of tracks/cylinder */ /* Check COPYR1 record for correct length */ if (xreclen != sizeof(COPYR1) && xreclen != sizeof(COPYR1) - 4) { XMERR ("HHCDL081E COPYR1 record length is invalid\n"); return -1; } /* Check that COPYR1 header identifier is correct */ if (memcmp(copyr1->hdrid, COPYR1_HDRID, 3) != 0) { XMERR ("HHCDL082E COPYR1 header identifier not correct\n"); return -1; } /* Check that the dataset is an old format unload */ if ((copyr1->uldfmt & COPYR1_ULD_FORMAT) != COPYR1_ULD_FORMAT_OLD) { XMERR ("HHCDL083E COPYR1 unload format is unsupported\n"); return -1; } blksize = (copyr1->ds1blkl[0] << 8) | copyr1->ds1blkl[1]; lrecl = (copyr1->ds1lrecl[0] << 8) | copyr1->ds1lrecl[1]; keylen = copyr1->ds1keyl; /* Display original dataset information */ XMINFF (2, "HHCDL084I Original dataset: " "DSORG=%s RECFM=%s LRECL=%d BLKSIZE=%d KEYLEN=%d\n", dsorg_name(copyr1->ds1dsorg), recfm_name(©r1->ds1recfm), lrecl, blksize, keylen); XMINFF (2, "HHCDL085I Dataset was unloaded from device type " "%2.2X%2.2X%2.2X%2.2X (%s)\n", copyr1->ucbtype[0], copyr1->ucbtype[1], copyr1->ucbtype[2], copyr1->ucbtype[3], dasd_name(copyr1->ucbtype)); cyls = (copyr1->cyls[0] << 8) | copyr1->cyls[1]; heads = (copyr1->heads[0] << 8) | copyr1->heads[1]; XMINFF (2, "HHCDL086I Original device has %d cyls and %d heads\n", cyls, heads); return heads; } /* end function process_copyr1 */ /*-------------------------------------------------------------------*/ /* Subroutine to process a COPYR2 header record */ /* Input: */ /* xbuf Pointer to buffer containing header record */ /* xreclen Length of header record */ /* xarray Pointer to array to receive 1-16 extent descriptions */ /* Output: */ /* The return value is the number of extents, */ /* or -1 if an error occurred. */ /* */ /* Extent information is listed if infolvl is 4 or greater. */ /*-------------------------------------------------------------------*/ static int process_copyr2 (BYTE *xbuf, int xreclen, EXTDESC xarray[]) { COPYR2 *copyr2 = (COPYR2*)xbuf; /* -> COPYR2 header record */ int numext; /* Number of extents */ int i; /* Array subscript */ /* Check COPYR2 record for correct length */ if (xreclen != sizeof(COPYR2)) { XMERR ("HHCDL087I COPYR2 record length is invalid\n"); return -1; } /* Get number of extents from DEB basic section */ numext = copyr2->debbasic[0]; if (numext < 1 || numext > 16) { XMERRF ("HHCDL088I Invalid number of extents %d\n", numext); return -1; } /* Copy each extent descriptor into the array */ for (i = 0; i < numext; i++) { xarray[i].bcyl = (copyr2->debxtent[i][6] << 8) | copyr2->debxtent[i][7]; xarray[i].btrk = (copyr2->debxtent[i][8] << 8) | copyr2->debxtent[i][9]; xarray[i].ecyl = (copyr2->debxtent[i][10] << 8) | copyr2->debxtent[i][11]; xarray[i].etrk = (copyr2->debxtent[i][12] << 8) | copyr2->debxtent[i][13]; xarray[i].ntrk = (copyr2->debxtent[i][14] << 8) | copyr2->debxtent[i][15]; XMINFF (4, "HHCDL089I Extent %d: Begin CCHH=%4.4X%4.4X " "End CCHH=%4.4X%4.4X Tracks=%4.4X\n", i, xarray[i].bcyl, xarray[i].btrk, xarray[i].ecyl, xarray[i].etrk, xarray[i].ntrk); } /* end for(i) */ /* Return number of extents */ return numext; } /* end function process_copyr2 */ /*-------------------------------------------------------------------*/ /* Subroutine to process a directory block record */ /* Input: */ /* xbuf Pointer to directory block */ /* blklen Length of directory block */ /* cyl Cylinder number of directory block in output file */ /* head Head number of directory block in output file */ /* rec Record number of directory block in output file */ /* dirblka Array of pointers to directory blocks */ /* dirblkn Number of directory blocks in dirblka array */ /* Output: */ /* dirblu Number of bytes used in directory block */ /* The return value is 0 if successful, 1 if end of directory, */ /* or -1 if an error occurred. */ /* */ /* A pointer to the directory block is saved in the dirblka array. */ /* The copy of the data block is updated with the cylinder, head, */ /* and record number of the directory block in the output file. */ /* Directory information is listed if infolvl is 3 or greater. */ /*-------------------------------------------------------------------*/ static int process_dirblk (DATABLK *xbuf, int blklen, int cyl, int head, int rec, DATABLK *dirblka[], int dirblkn, int *dirblu) { int size; /* Size of directory entry */ int i, j; /* Array subscripts */ int k; /* Userdata halfword count */ DATABLK *blkp; /* -> Copy of directory block*/ BYTE *dirptr; /* -> Next byte within block */ int dirrem; /* Number of bytes remaining */ PDSDIR *dirent; /* -> Directory entry */ char memname[9]; /* Member name (ASCIIZ) */ BYTE c, chars[25]; /* Character work areas */ char hex[49]; /* Character work areas */ set_codepage(NULL); /* Check for end of directory */ if (blklen == 12 && memcmp(xbuf, twelvehex00, 12) == 0) { XMINF (3, "HHCDL090I End of directory\n"); return 1; } /* Check directory block record for correct length */ if (blklen != 276) { XMERR ("HHCDL091E Directory block record length is invalid\n"); return -1; } /* Obtain storage for a copy of the directory block */ blkp = (DATABLK*)malloc(blklen); if (blkp == NULL) { XMERRF ("HHCDL092E Cannot obtain storage for directory block: %s\n", strerror(errno)); return -1; } /* Copy the directory block */ memcpy (blkp, xbuf, blklen); /* Check that there is room in the directory block pointer array */ if (dirblkn >= MAXDBLK) { XMERRF ("HHCDL093E Number of directory blocks exceeds %d, " "increase MAXDBLK\n", MAXDBLK); return -1; } /* Add the directory block to the pointer array */ dirblka[dirblkn] = blkp; /* Update the CCHHR in the copy of the directory block */ blkp->cyl[0] = (cyl >> 8) & 0xFF; blkp->cyl[1] = cyl & 0xFF; blkp->head[0] = (head >> 8) & 0xFF; blkp->head[1] = head & 0xFF; blkp->rec = rec; /* Load number of bytes in directory block */ dirptr = xbuf->kdarea + 8; dirrem = (dirptr[0] << 8) | dirptr[1]; if (dirrem < 2 || dirrem > 256) { XMERR ("HHCDL094E Directory block byte count is invalid\n"); return -1; } /* Return number of bytes used in directory block */ *dirblu = dirrem; /* Point to first directory entry */ dirptr += 2; dirrem -= 2; /* Process each directory entry */ while (dirrem > 0) { /* Point to next directory entry */ dirent = (PDSDIR*)dirptr; /* Test for end of directory */ if (memcmp(dirent->pds2name, eighthexFF, 8) == 0) break; /* Extract the member name */ make_asciiz (memname, sizeof(memname), dirent->pds2name, 8); /* Display the directory entry */ XMINFF (3, "HHCDL095I %s %-8.8s TTR=%2.2X%2.2X%2.2X ", (dirent->pds2indc & PDS2INDC_ALIAS) ? " Alias" : "Member", memname, dirent->pds2ttrp[0], dirent->pds2ttrp[1], dirent->pds2ttrp[2]); /* Load the user data halfword count */ k = dirent->pds2indc & PDS2INDC_LUSR; /* Print the user data */ if (k > 0) XMINF (3, "Userdata="); memset (hex, '\0', sizeof(hex)); memset (chars, '\0', sizeof(chars)); for (i = 0, j = 0; i < k*2; i++, j++) { if (i == 8 || i == 32 || i == 56) { if (i == 8) XMINFF (3, "%-16.16s %-8.8s\n ", hex, chars); else XMINFF (3, "%-16.16s %-16.16s %16.16s %-24.24s\n ", hex, hex+16, hex+32, chars); memset (hex, '\0', sizeof(hex)); memset (chars, '\0', sizeof(chars)); j = 0; } sprintf(hex+2*j, "%2.2X", dirent->pds2usrd[i]); c = guest_to_host(dirent->pds2usrd[i]); if (!isprint(c)) c = '.'; chars[j] = c; } /* end for(i) */ if (i <= 8) XMINFF (3, "%-16.16s %-8.8s\n", hex, chars); else XMINFF (3, "%-16.16s %-16.16s %-16.16s %-24.24s\n", hex, hex+16, hex+32, chars); /* Point to next directory entry */ size = 12 + k*2; dirptr += size; dirrem -= size; } return 0; } /* end function process_dirblk */ /*-------------------------------------------------------------------*/ /* Subroutine to replace a TTR in a PDS directory */ /* Input: */ /* memname Member name (ASCIIZ) */ /* ttrptr Pointer to TTR to be replaced */ /* ttrtab Pointer to TTR conversion table */ /* numttr Number of entries in TTR conversion table */ /* Output: */ /* The TTR is replaced using the TTR conversion table. */ /* */ /* Return value is 0 if successful, or -1 if TTR not in table. */ /* Directory information is listed if infolvl is 3 or greater. */ /*-------------------------------------------------------------------*/ static int replace_ttr (char *memname, BYTE *ttrptr, TTRCONV *ttrtab, int numttr) { int i; /* Array subscript */ /* Search for the TTR in the conversion table */ for (i = 0; i < numttr; i++) { if (memcmp(ttrptr, ttrtab[i].origttr, 3) == 0) { XMINFF (4, "HHCDL096I Member %s TTR=%2.2X%2.2X%2.2X " "replaced by TTR=%2.2X%2.2X%2.2X\n", memname, ttrptr[0], ttrptr[1], ttrptr[2], ttrtab[i].outpttr[0], ttrtab[i].outpttr[1], ttrtab[i].outpttr[2]); memcpy (ttrptr, ttrtab[i].outpttr, 3); return 0; } } /* Return error if TTR not found in conversion table */ XMERRF ("HHCDL097E Member %s TTR=%2.2X%2.2X%2.2X not found in dataset\n", memname, ttrptr[0], ttrptr[1], ttrptr[2]); return -1; } /* end function replace_ttr */ /*-------------------------------------------------------------------*/ /* Subroutine to update a note list record */ /* Input: */ /* cif -> CKD image file descriptor */ /* ofname Output file name */ /* heads Number of tracks per cylinder on output device */ /* trklen Track length of virtual output device */ /* dsstart Relative track number of start of dataset */ /* memname Member name (ASCIIZ) */ /* ttrn Pointer to TTRN of note list record */ /* ttrtab Pointer to TTR conversion table */ /* numttr Number of entries in TTR conversion table */ /* Output: */ /* Each original TTR in the note list record is replaced by the */ /* corresponding output TTR from the TTR conversion table. */ /* */ /* Return value is 0 if successful, or -1 if error. */ /*-------------------------------------------------------------------*/ static int update_note_list (CIFBLK *cif, char *ofname, int heads, int trklen, int dsstart, char *memname, BYTE *ttrn, TTRCONV *ttrtab, int numttr) { int rc; /* Return code */ int i; /* Loop counter */ int trk; /* Relative track number */ int cyl; /* Cylinder number */ int head; /* Head number */ int rec; /* Record number */ int klen; /* Record key length */ int dlen; /* Record data length */ int numnl; /* Number of note list TTRs */ int nllen; /* Note list length */ BYTE *ttrptr; /* -> Note list TTR */ int curcyl; /* Current cylinder */ int curhead; /* Current head */ int offset; /* Offset into track buffer */ int skiplen; /* Number of bytes to skip */ CKDDASD_TRKHDR trkhdr; /* Track header */ CKDDASD_RECHDR rechdr; /* Record header */ BYTE notelist[1024]; /* Note list */ UNREFERENCED(trklen); /* Load the TTR of the note list record */ trk = (ttrn[0] << 8) | ttrn[1]; rec = ttrn[2]; /* Load number of note list TTRs and calculate note list length */ numnl = ttrn[3]; nllen = numnl * 4; /* Calculate the CCHHR of the note list record */ cyl = (dsstart + trk) / heads; head = (dsstart + trk) % heads; XMINFF (4, "HHCDL098I Updating note list for member %s " "at TTR=%4.4X%2.2X CCHHR=%4.4X%4.4X%2.2X\n", memname, trk, rec, cyl, head, rec); /* Save the current position in the output file */ curcyl = cif->curcyl; curhead = cif->curhead; /* Seek to start of track header */ rc = read_track (cif, cyl, head); if (rc < 0) { XMERRF ("HHCDL099E %s cyl %d head %d read error\n", ofname, cyl, head); return -1; } /* Copy the track header */ memcpy (&trkhdr, cif->trkbuf, CKDDASD_TRKHDR_SIZE); offset = CKDDASD_TRKHDR_SIZE; /* Validate the track header */ if (trkhdr.bin != 0 || trkhdr.cyl[0] != (cyl >> 8) || trkhdr.cyl[1] != (cyl & 0xFF) || trkhdr.head[0] != (head >> 8) || trkhdr.head[1] != (head & 0xFF)) { XMERRF ("HHCDL100E %s cyl %d head %d invalid track header " "%2.2X%2.2X%2.2X%2.2X%2.2X\n", ofname, cyl, head, trkhdr.bin, trkhdr.cyl[0], trkhdr.cyl[1], trkhdr.head[0], trkhdr.head[1]); return -1; } /* Search for the note list record */ while (1) { /* Copy the next record header */ memcpy (&rechdr, cif->trkbuf + offset, CKDDASD_RECHDR_SIZE); offset += CKDDASD_RECHDR_SIZE; /* Check for end of track */ if (memcmp(&rechdr, eighthexFF, 8) == 0) { XMERRF ("HHCDL101E %s cyl %d head %d rec %d " "note list record not found\n", ofname, cyl, head, rec); return -1; } /* Extract record key length and data length */ klen = rechdr.klen; dlen = (rechdr.dlen[0] << 8) | rechdr.dlen[1]; /* Exit loop if matching record number */ if (rechdr.rec == rec) break; /* Skip the key and data areas */ skiplen = klen + dlen; offset += skiplen; } /* end while */ /* Check that the data length is sufficient */ if (dlen < nllen) { XMERRF ("HHCDL102E Member %s note list at cyl %d head %d rec %d " "dlen %d is too short for %d TTRs", memname, cyl, head, rec, dlen, numnl); return -1; } /* Skip the key area if present */ offset += klen; /* Copy the note list from the data area */ memcpy (¬elist, cif->trkbuf + offset, nllen); /* Replace the TTRs in the note list record */ ttrptr = notelist; for (i = 0; i < numnl; i++) { rc = replace_ttr (memname, ttrptr, ttrtab, numttr); if (rc < 0) return -1; ttrptr += 4; } /* end for(i) */ /* Copy the updated note list to the buffer */ memcpy (cif->trkbuf + offset, ¬elist, nllen); cif->trkmodif = 1; /* Restore original file position */ rc = read_track (cif, curcyl, curhead); if (rc < 0) { XMERRF ("HHCDL103E %s track read error cyl %d head %d\n", ofname, curcyl, curhead); return -1; } XMINFF (4, "HHCDL104I Updating cyl %u head %u rec %d kl %d dl %d\n", cyl, head, rec, klen, dlen); return 0; } /* end function update_note_list */ /*-------------------------------------------------------------------*/ /* Subroutine to update a directory block record */ /* Input: */ /* cif -> CKD image file descriptor */ /* ofname Output file name */ /* heads Number of tracks per cylinder on output device */ /* trklen Track length of virtual output device */ /* dsstart Relative track number of start of dataset */ /* xbuf Pointer to directory block */ /* ttrtab Pointer to TTR conversion table */ /* numttr Number of entries in TTR conversion table */ /* Output: */ /* Each original TTR in the directory block is replaced by the */ /* corresponding output TTR from the TTR conversion table. */ /* For any module which has note list entries, the note list */ /* TTRs in the note list record are also updated. */ /* */ /* Return value is 0 if successful, or -1 if any directory entry */ /* contains a TTR which is not found in the TTR conversion table. */ /*-------------------------------------------------------------------*/ static int update_dirblk (CIFBLK *cif, char *ofname, int heads, int trklen, int dsstart, DATABLK *xbuf, TTRCONV *ttrtab, int numttr) { int rc; /* Return code */ int size; /* Size of directory entry */ int k; /* Userdata halfword count */ BYTE *dirptr; /* -> Next byte within block */ int dirrem; /* Number of bytes remaining */ PDSDIR *dirent; /* -> Directory entry */ BYTE *ttrptr; /* -> User TTR */ int n; /* Number of user TTRs */ int i; /* Loop counter */ char memname[9]; /* Member name (ASCIIZ) */ /* Load number of bytes in directory block */ dirptr = xbuf->kdarea + 8; dirrem = (dirptr[0] << 8) | dirptr[1]; if (dirrem < 2 || dirrem > 256) { XMERR ("HHCDL105E Directory block byte count is invalid\n"); return -1; } /* Point to first directory entry */ dirptr += 2; dirrem -= 2; /* Process each directory entry */ while (dirrem > 0) { /* Point to next directory entry */ dirent = (PDSDIR*)dirptr; /* Test for end of directory */ if (memcmp(dirent->pds2name, eighthexFF, 8) == 0) break; /* Extract the member name */ make_asciiz (memname, sizeof(memname), dirent->pds2name, 8); /* Replace the member TTR */ rc = replace_ttr (memname, dirent->pds2ttrp, ttrtab, numttr); if (rc < 0) return -1; /* Load the number of user TTRs */ n = (dirent->pds2indc & PDS2INDC_NTTR) >> PDS2INDC_NTTR_SHIFT; /* Replace the user TTRs */ ttrptr = dirent->pds2usrd; for (i = 0; i < n; i++) { rc = replace_ttr (memname, ttrptr, ttrtab, numttr); if (rc < 0) return -1; ttrptr += 4; } /* end for(i) */ /* Update the note list record if note list TTRs exist */ if ((dirent->pds2indc & PDS2INDC_ALIAS) == 0 && n >= 2 && dirent->pds2usrd[7] != 0) { rc = update_note_list (cif, ofname, heads, trklen, dsstart, memname, dirent->pds2usrd+4, ttrtab, numttr); if (rc < 0) return -1; } /* Load the user data halfword count */ k = dirent->pds2indc & PDS2INDC_LUSR; /* Point to next directory entry */ size = 12 + k*2; dirptr += size; dirrem -= size; } return 0; } /* end function update_dirblk */ /*-------------------------------------------------------------------*/ /* Subroutine to read an IEBCOPY file and write to DASD image file */ /* Input: */ /* xfname XMIT input file name */ /* ofname DASD image file name */ /* cif -> CKD image file descriptor */ /* devtype Output device type */ /* heads Output device number of tracks per cylinder */ /* trklen Output device virtual track length */ /* outcyl Output starting cylinder number */ /* outhead Output starting head number */ /* maxtrks Maximum extent size in tracks */ /* method METHOD_XMIT or METHOD_VS */ /* Output: */ /* odsorg Dataset organization */ /* orecfm Record format */ /* olrecl Logical record length */ /* oblksz Block size */ /* okeyln Key length */ /* dirblu Bytes used in last directory block */ /* lastrec Record number of last block written */ /* trkbal Number of bytes remaining on last track */ /* numtrks Number of tracks written */ /* nxtcyl Starting cylinder number for next dataset */ /* nxthead Starting head number for next dataset */ /*-------------------------------------------------------------------*/ static int process_iebcopy_file (char *xfname, char *ofname, CIFBLK *cif, U16 devtype, int heads, int trklen, int outcyl, int outhead, int maxtrks, BYTE method, BYTE *odsorg, BYTE *orecfm, int *olrecl, int *oblksz, int *okeyln, int *dirblu, int *lastrec, int *trkbal, int *numtrks, int *nxtcyl, int *nxthead) { int rc = 0; /* Return code */ int i; /* Array subscript */ int xfd; /* XMIT file descriptor */ int dsstart; /* Relative track number of start of output dataset */ BYTE *xbuf; /* -> Logical record buffer */ int xreclen; /* Logical record length */ BYTE xctl; /* 0x20=Control record */ char xrecname[8]; /* XMIT control record name */ int datarecn = 0; /* Data record counter */ int datafiln = 0; /* Data file counter */ int copyfiln = 0; /* Seq num of file to copy */ BYTE dsorg=0; /* Dataset organization */ BYTE recfm=0; /* Dataset record format */ U16 lrecl=0; /* Dataset record length */ U16 blksz=0; /* Dataset block size */ U16 keyln=0; /* Dataset key length */ U16 dirnm; /* Number of directory blocks*/ int enddir = 0; /* 1=End of directory found */ BYTE *blkptr; /* -> Data block in record */ DATABLK *datablk; /* -> Data block */ int blktrk; /* Data block relative track */ int blkcyl; /* Data block cylinder number*/ int blkhead; /* Data block head number */ int blkrec; /* Data block record number */ int keylen; /* Key length of data block */ int datalen; /* Data length of data block */ int blklen; /* Total length of data block*/ int origheads = 0; /* Number of tracks/cylinder on original dataset */ int numext = 0; /* Number of extents */ EXTDESC xarray[16]; /* Extent descriptor array */ DATABLK **dirblka; /* -> Directory block array */ int dirblkn = 0; /* #of directory blocks read */ int outusedv = 0; /* Output bytes used on track of virtual device */ int outusedr = 0; /* Output bytes used on track of real device */ int outtrkbr = 0; /* Output bytes remaining on track of real device */ int outtrk = 0; /* Output relative track */ int outrec = 0; /* Output record number */ TTRCONV *ttrtab; /* -> TTR conversion table */ int numttr = 0; /* TTR table array index */ COPYR1 *copyr1; /* -> header record 1 */ char pathname[MAX_PATH]; /* xfname in host path format*/ /* Open the input file */ hostpath(pathname, xfname, sizeof(pathname)); xfd = open (pathname, O_RDONLY|O_BINARY); if (xfd < 0) { XMERRF ("HHCDL106E Cannot open %s: %s\n", xfname, strerror(errno)); return -1; } /* Obtain the input logical record buffer */ xbuf = malloc (65536); if (xbuf == NULL) { XMERRF ("HHCDL107E Cannot obtain input buffer: %s\n", strerror(errno)); close (xfd); return -1; } /* Obtain storage for the directory block array */ dirblka = (DATABLK**)malloc (sizeof(DATABLK*) * MAXDBLK); if (dirblka == NULL) { XMERRF ("HHCDL108E Cannot obtain storage for directory block array: %s\n", strerror(errno)); free (xbuf); close (xfd); return -1; } /* Obtain storage for the TTR conversion table */ ttrtab = (TTRCONV*)malloc (sizeof(TTRCONV) * MAXTTR); if (ttrtab == NULL) { XMERRF ("HHCDL109E Cannot obtain storage for TTR table: %s\n", strerror(errno)); free (xbuf); free (dirblka); close (xfd); return -1; } /* Calculate the relative track number of the dataset */ dsstart = (outcyl * heads) + outhead; /* Display the file information message */ XMINFF (1, "HHCDL110I Processing file %s\n", xfname); /* Read each logical record */ while (1) { xctl=0; if (method == METHOD_XMIT) rc = read_xmit_rec (xfd, xfname, xbuf, &xctl); else if (method == METHOD_VS) { rc = read_vs_rec (xfd, xfname, xbuf, datarecn); if (rc == 0) /* end-of-file */ break; } else rc = -1; if (rc < 0) return -1; xreclen = rc; /* Process control records */ if (method == METHOD_XMIT && xctl) { /* Extract the control record name */ make_asciiz (xrecname, sizeof(xrecname), xbuf, 6); XMINFF (4, "HHCDL111I Control record: %s length %d\n", xrecname, xreclen); /* Exit if control record is a trailer record */ if (strcmp(xrecname, "INMR06") == 0) break; /* Process control record according to type */ if (strcmp(xrecname, "INMR02") == 0) { rc = process_inmr02 (xbuf, xreclen, ©filn, &dsorg, &recfm, &lrecl, &blksz, &keyln, &dirnm); if (rc < 0) return -1; } else { rc = process_inmrxx (xbuf, xreclen); if (rc < 0) return -1; } /* Reset the data counter if data control record */ if (strcmp(xrecname, "INMR03") == 0) { datafiln++; datarecn = 0; XMINFF (4, "HHCDL112I File number: %d %s\n", datafiln, (datafiln == copyfiln) ? "(selected)" : "(not selected)"); } /* Loop to get next record */ continue; } /* end if(xctl) */ /* Process data records */ datarecn++; XMINFF (4, "HHCDL113I Data record: length %d\n", xreclen); if (infolvl >= 5) data_dump (xbuf, xreclen); /* If this is not the IEBCOPY file then ignore data record */ if (method == METHOD_XMIT && datafiln != copyfiln) { continue; } /* Process IEBCOPY header record 1 */ if (datarecn == 1) { origheads = process_copyr1 (xbuf, xreclen); if (origheads < 0) exit(1); if (method == METHOD_VS) { copyr1 = (COPYR1 *)xbuf; dsorg = copyr1->ds1dsorg[0]; recfm = copyr1->ds1recfm; lrecl = (copyr1->ds1lrecl[0] << 8) | copyr1->ds1lrecl[1]; blksz = (copyr1->ds1blkl[0] << 8) | copyr1->ds1blkl[1]; keyln = copyr1->ds1keyl; } continue; } /* Process IEBCOPY header record 2 */ if (datarecn == 2) { numext = process_copyr2 (xbuf, xreclen, xarray); if (numext < 0) exit(1); continue; } /* Process each data block in data record */ blkptr = xbuf; while (xreclen > 0) { /* Compute the length of the block */ datablk = (DATABLK*)blkptr; blkcyl = (datablk->cyl[0] << 8) | datablk->cyl[1]; blkhead = (datablk->head[0] << 8) | datablk->head[1]; blkrec = datablk->rec; keylen = datablk->klen; datalen = (datablk->dlen[0] << 8) | datablk->dlen[1]; blklen = 12 + keylen + datalen; /* Calculate the TTR in the original dataset */ blktrk = (enddir == 0) ? 0 : calculate_ttr (blkcyl, blkhead, origheads, numext, xarray); /* Write the data block to the output file */ rc = write_block (cif, ofname, datablk, keylen, datalen, devtype, heads, trklen, maxtrks, &outusedv, &outusedr, &outtrkbr, &outtrk, &outcyl, &outhead, &outrec); if (rc < 0) { XMERRF ("HHCDL114E write error: input record " "CCHHR=%4.4X%4.4X%2.2X " "(TTR=%4.4X%2.2X) KL=%d DL=%d\n", blkcyl, blkhead, blkrec, blktrk, blkrec, keylen, datalen); return -1; } XMINFF (4, "HHCDL115I CCHHR=%4.4X%4.4X%2.2X " "(TTR=%4.4X%2.2X) KL=%d DL=%d " "-> CCHHR=%4.4X%4.4X%2.2X " "(TTR=%4.4X%2.2X)\n", blkcyl, blkhead, blkrec, blktrk, blkrec, keylen, datalen, outcyl, outhead, outrec, outtrk, outrec); /* Process directory block or member block */ if (enddir == 0) { rc = process_dirblk (datablk, blklen, outcyl, outhead, outrec, dirblka, dirblkn, dirblu); if (rc < 0) return -1; enddir = rc; /* Count the number of directory blocks read */ if (enddir == 0) dirblkn++; } else /* Not a directory block */ { /* Check that TTR conversion table is not full */ if (numttr >= MAXTTR) { XMERRF ("HHCDL116E TTR count exceeds %d, " "increase MAXTTR\n", MAXTTR); return -1; } /* Add an entry to the TTR conversion table */ ttrtab[numttr].origttr[0] = (blktrk >> 8) & 0xFF; ttrtab[numttr].origttr[1] = blktrk & 0xFF; ttrtab[numttr].origttr[2] = blkrec; ttrtab[numttr].outpttr[0] = (outtrk >> 8) & 0xFF; ttrtab[numttr].outpttr[1] = outtrk & 0xFF; ttrtab[numttr].outpttr[2] = outrec; numttr++; } /* Point to next data block in data record */ xreclen -= blklen; blkptr += blklen; } /* end while(xreclen) */ } /* end while(1) */ /* Check for unsupported xmit utility */ if (method == METHOD_XMIT && copyfiln == 0) { XMERRF ("HHCDL130W WARNING -- XMIT file utility is not IEBCOPY;" " file %s not loaded\n", xfname); } /* Return the last record number and track balance */ *lastrec = outrec; *trkbal = outtrkbr; /* Write any data remaining in track buffer */ rc = write_track (cif, ofname, heads, trklen, &outusedv, &outtrk, &outcyl, &outhead); if (rc < 0) return -1; /* Update the directory and rewrite to output file */ for (i = 0; i < dirblkn; i++) { /* Obtain the directory block pointer from the array */ datablk = dirblka[i]; /* Update TTR pointers in this directory block */ rc = update_dirblk (cif, ofname, heads, trklen, dsstart, datablk, ttrtab, numttr); if (rc < 0) return -1; /* Rewrite the updated directory block */ blkcyl = (datablk->cyl[0] << 8) | datablk->cyl[1]; blkhead = (datablk->head[0] << 8) | datablk->head[1]; blkrec = datablk->rec; keylen = datablk->klen; datalen = (datablk->dlen[0] << 8) | datablk->dlen[1]; rc = update_block (cif, ofname, datablk, blkcyl, blkhead, blkrec, keylen, datalen, heads, trklen); if (rc < 0) return -1; } /* end for(i) */ /* Close input file and release buffers */ close (xfd); for (i = 0; i < dirblkn; i++) free (dirblka[i]); free (dirblka); free (xbuf); free (ttrtab); /* Return the dataset attributes */ *odsorg = dsorg; *orecfm = recfm; *olrecl = lrecl; *oblksz = blksz; *okeyln = keyln; /* Return number of tracks and starting address of next dataset */ *numtrks = outtrk; *nxtcyl = outcyl; *nxthead = outhead; return 0; } /* end function process_iebcopy_file */ /*-------------------------------------------------------------------*/ /* Subroutine to initialize a SYSCTLG dataset as an OS CVOL */ /* Input: */ /* ofname DASD image file name */ /* cif -> CKD image file descriptor */ /* volser Volume serial number */ /* devtype Output device type */ /* heads Output device number of tracks per cylinder */ /* trklen Output device virtual track length */ /* outcyl Output starting cylinder number */ /* outhead Output starting head number */ /* extsize Extent size in tracks */ /* Output: */ /* lastrec Record number of last block written */ /* trkbal Number of bytes remaining on last track */ /* numtrks Number of tracks written */ /* nxtcyl Starting cylinder number for next dataset */ /* nxthead Starting head number for next dataset */ /* Note: */ /* This subroutine builds a minimal SYSCTLG containing only */ /* the entries required on an OS/360 IPL volume. */ /*-------------------------------------------------------------------*/ static int cvol_initialize (char *ofname, CIFBLK *cif, char *volser, U16 devtype, int heads, int trklen, int outcyl, int outhead, int extsize, int *lastrec, int *trkbal, int *numtrks, int *nxtcyl, int *nxthead) { int rc; /* Return code */ int i; /* Array subscript */ int keylen; /* Key length of data block */ int datalen; /* Data length of data block */ int outusedv = 0; /* Output bytes used on track of virtual device */ int outusedr = 0; /* Output bytes used on track of real device */ int outtrkbr = 0; /* Output bytes remaining on track of real device */ int outtrk = 0; /* Output relative track */ int outrec = 0; /* Output record number */ int blkptrk; /* Number of blocks per track*/ int totblks; /* Number of blocks in CVOL */ int bytes; /* Bytes used in this block */ U32 ucbtype; /* UCB device type */ PDSDIR *catent; /* -> Catalog entry */ DATABLK datablk; /* Data block */ #define NUM_SYS1_DATASETS 8 /* Number of SYS1 datasets */ static char *sys1name[NUM_SYS1_DATASETS] = {"DUMP", "IMAGELIB", "LINKLIB", "NUCLEUS", "PARMLIB", "PROCLIB", "SAMPLIB", "SYSJOBQE"}; /* Set the key length and data length for SYSCTLG dataset */ keylen = 8; datalen = 256; /* Obtain the number of blocks which will fit on a track */ capacity_calc (cif, 0, keylen, datalen, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &blkptrk, NULL, NULL); /* Calculate the total number of blocks in the catalog */ totblks = extsize * blkptrk; /* Get the UCB device type */ ucbtype = ucbtype_code (devtype); /*-----------------------------------*/ /* Initialize the volume index block */ /*-----------------------------------*/ memset (datablk.kdarea, 0, keylen + datalen); /* The key field contains all X'FF' */ memcpy (datablk.kdarea, eighthexFF, 8); /* The first entry begins after the 2 byte count field */ bytes = 2; catent = (PDSDIR*)(datablk.kdarea + keylen + bytes); /* Build the volume index control entry (VICE) */ /* The VICE name is X'0000000000000001' */ memcpy (catent->pds2name, cvol_low_key, 8); /* Set TTR to highest block in volume index, i.e. X'000001' */ catent->pds2ttrp[0] = 0; catent->pds2ttrp[1] = 0; catent->pds2ttrp[2] = 1; /* Indicator byte X'05' means 5 user halfwords follow, and uniquely identifies this catalog entry as a VICE */ catent->pds2indc = 5; /* Set the TTR of the last block of the catalog */ catent->pds2usrd[0] = ((extsize - 1) >> 8) & 0xFF; catent->pds2usrd[1] = (extsize - 1) & 0xFF; catent->pds2usrd[2] = blkptrk; catent->pds2usrd[3] = 0; /* Set the TTR of the first unused block (X'000003') */ catent->pds2usrd[4] = 0; catent->pds2usrd[5] = 0; catent->pds2usrd[6] = 3; /* Remainder of user data is 0 */ catent->pds2usrd[7] = 0; catent->pds2usrd[8] = 0; catent->pds2usrd[9] = 0; /* Increment bytes used by the length of the VICE */ bytes += 22; catent = (PDSDIR*)(datablk.kdarea + keylen + bytes); /* Build the index pointer for SYS1 */ convert_to_ebcdic (catent->pds2name, 8, "SYS1"); /* Set TTR of the SYS1 index block, i.e. X'000002' */ catent->pds2ttrp[0] = 0; catent->pds2ttrp[1] = 0; catent->pds2ttrp[2] = 2; /* Indicator byte X'00' means no user halfwords follow, and uniquely identifies this catalog entry as an index pointer */ catent->pds2indc = 0; /* Increment bytes used by the length of the index pointer */ bytes += 12; catent = (PDSDIR*)(datablk.kdarea + keylen + bytes); /* Set the last entry in block marker */ memcpy (catent->pds2name, eighthexFF, 8); /* Increment bytes used by the last entry marker */ bytes += 12; catent = (PDSDIR*)(datablk.kdarea + keylen + bytes); /* Set the number of bytes used in this block */ datablk.kdarea[keylen+0] = (bytes >> 8) & 0xFF; datablk.kdarea[keylen+1] = bytes & 0xFF; /* Write the volume index block to the output file */ rc = write_block (cif, ofname, &datablk, keylen, datalen, devtype, heads, trklen, extsize, &outusedv, &outusedr, &outtrkbr, &outtrk, &outcyl, &outhead, &outrec); if (rc < 0) return -1; XMINFF (4, "HHCDL117I Catalog block at cyl %d head %d rec %d\n", outcyl, outhead, outrec); if (infolvl >= 5) data_dump (datablk.kdarea, keylen + datalen); /* Count number of blocks written */ totblks--; /*---------------------------------*/ /* Initialize the SYS1 index block */ /*---------------------------------*/ memset (datablk.kdarea, 0, keylen + datalen); /* The key field contains all X'FF' */ memcpy (datablk.kdarea, eighthexFF, 8); /* The first entry begins after the 2 byte count field */ bytes = 2; catent = (PDSDIR*)(datablk.kdarea + keylen + bytes); /* Build the index control entry (ICE) */ /* The ICE name is X'0000000000000001' */ memcpy (catent->pds2name, cvol_low_key, 8); /* Set TTR to highest block in this index, i.e. X'000002' */ catent->pds2ttrp[0] = 0; catent->pds2ttrp[1] = 0; catent->pds2ttrp[2] = 2; /* Indicator byte X'03' means 3 user halfwords follow, and uniquely identifies this catalog entry as an ICE */ catent->pds2indc = 3; /* Set the TTR of this block */ catent->pds2usrd[0] = 0; catent->pds2usrd[1] = 0; catent->pds2usrd[2] = 2; /* The next byte contains the alias count */ catent->pds2usrd[3] = 0; /* The remaining 2 bytes of userdata are zeroes */ catent->pds2usrd[4] = 0; catent->pds2usrd[5] = 0; /* Increment bytes used by the length of the ICE */ bytes += 18; /* Build the dataset pointers for SYS1.xxxxxxxx datasets */ for (i = 0; i < NUM_SYS1_DATASETS; i++) { /* Point to next dataset pointer entry */ catent = (PDSDIR*)(datablk.kdarea + keylen + bytes); /* Set the name of the dataset pointer entry */ convert_to_ebcdic (catent->pds2name, 8, sys1name[i]); /* Set the TTR to zero */ catent->pds2ttrp[0] = 0; catent->pds2ttrp[1] = 0; catent->pds2ttrp[2] = 0; /* Indicator byte X'07' means 7 user halfwords follow, and uniquely identifies the entry as a dataset pointer */ catent->pds2indc = 7; /* The next two bytes contain the volume count (X'0001') */ catent->pds2usrd[0] = 0; catent->pds2usrd[1] = 1; /* The next four bytes contain the UCB type */ catent->pds2usrd[2] = (ucbtype >> 24) & 0xFF; catent->pds2usrd[3] = (ucbtype >> 16) & 0xFF; catent->pds2usrd[4] = (ucbtype >> 8) & 0xFF; catent->pds2usrd[5] = ucbtype & 0xFF; /* The next six bytes contain the volume serial number */ convert_to_ebcdic (catent->pds2usrd+6, 6, volser); /* The next two bytes contain the volume seq.no. (X'0000') */ catent->pds2usrd[12] = 0; catent->pds2usrd[13] = 0; /* Increment bytes used by the length of the dataset pointer */ bytes += 26; } /* end for(i) */ /* Point to last entry in block */ catent = (PDSDIR*)(datablk.kdarea + keylen + bytes); /* Set the last entry in block marker */ memcpy (catent->pds2name, eighthexFF, 8); /* Increment bytes used by the last entry marker */ bytes += 12; catent = (PDSDIR*)(datablk.kdarea + keylen + bytes); /* Set the number of bytes used in this block */ datablk.kdarea[keylen+0] = (bytes >> 8) & 0xFF; datablk.kdarea[keylen+1] = bytes & 0xFF; /* Write the index block to the output file */ rc = write_block (cif, ofname, &datablk, keylen, datalen, devtype, heads, trklen, extsize, &outusedv, &outusedr, &outtrkbr, &outtrk, &outcyl, &outhead, &outrec); if (rc < 0) return -1; XMINFF (4, "HHCDL118I Catalog block at cyl %d head %d rec %d\n", outcyl, outhead, outrec); if (infolvl >= 5) data_dump (datablk.kdarea, keylen + datalen); /* Count number of blocks written */ totblks--; /*--------------------------------------------*/ /* Initialize remaining unused catalog blocks */ /*--------------------------------------------*/ while (totblks > 0) { memset (datablk.kdarea, 0, keylen + datalen); /* Write the volume index block to the output file */ rc = write_block (cif, ofname, &datablk, keylen, datalen, devtype, heads, trklen, extsize, &outusedv, &outusedr, &outtrkbr, &outtrk, &outcyl, &outhead, &outrec); if (rc < 0) return -1; XMINFF (4, "HHCDL119I Catalog block at cyl %d head %d rec %d\n", outcyl, outhead, outrec); if (infolvl >= 5) data_dump (datablk.kdarea, keylen + datalen); /* Count number of blocks written */ totblks--; } /* end while(totblks) */ /* Set the last record number to X'FF' so that OS/360 catalog management routines can recognize that the CVOL has been initialized by detecting X'FF' at ds1lstar+2 in the VTOC */ *lastrec = 0xFF; /* Return the track balance */ *trkbal = outtrkbr; /* Write data remaining in track buffer */ rc = write_track (cif, ofname, heads, trklen, &outusedv, &outtrk, &outcyl, &outhead); if (rc < 0) return -1; /* Return number of tracks and starting address of next dataset */ *numtrks = outtrk; *nxtcyl = outcyl; *nxthead = outhead; return 0; } /* end function cvol_initialize */ /*-------------------------------------------------------------------*/ /* Subroutine to initialize a LOGREC dataset with IFCDIP00 header */ /* Input: */ /* ofname DASD image file name */ /* cif -> CKD image file descriptor */ /* devtype Output device type */ /* heads Output device number of tracks per cylinder */ /* trklen Output device virtual track length */ /* outcyl Output starting cylinder number */ /* outhead Output starting head number */ /* extsize Extent size in tracks */ /* Output: */ /* lastrec Record number of last block written */ /* trkbal Number of bytes remaining on last track */ /* numtrks Number of tracks written */ /* nxtcyl Starting cylinder number for next dataset */ /* nxthead Starting head number for next dataset */ /*-------------------------------------------------------------------*/ static int dip_initialize (char *ofname, CIFBLK *cif, U16 devtype, int heads, int trklen, int outcyl, int outhead, int extsize, int *lastrec, int *trkbal, int *numtrks, int *nxtcyl, int *nxthead) { int rc; /* Return code */ int keylen; /* Key length of data block */ int datalen; /* Data length of data block */ int outusedv = 0; /* Output bytes used on track of virtual device */ int outusedr = 0; /* Output bytes used on track of real device */ int outtrkbr = 0; /* Output bytes remaining on track of real device */ int outtrk = 0; /* Output relative track */ int outrec = 0; /* Output record number */ int remlen; /* Bytes remaining on 1st trk*/ int physlen; /* Physical track length */ int lasthead; /* Highest head on cylinder */ int endcyl; /* Extent end cylinder */ int endhead; /* Extent end head */ int trklen90; /* 90% of track length */ int cyl90; /* 90% full cylinder number */ int head90; /* 90% full head number */ int reltrk90; /* 90% full relative track */ DIPHDR *diphdr; /* -> Record in data block */ DATABLK datablk; /* Data block */ /* Set the key length and data length for the header record */ keylen = 0; datalen = sizeof(DIPHDR); /* Obtain the physical track size and the track balance remaining on the first track after the header record */ capacity_calc (cif, 0, keylen, datalen, NULL, &remlen, &physlen, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); /* Calculate the end of extent cylinder and head */ lasthead = heads - 1; endcyl = outcyl; endhead = outhead + extsize - 1; while (endhead >= heads) { endhead -= heads; endcyl++; } /* Calculate the 90% full cylinder and head */ trklen90 = physlen * 9 / 10; reltrk90 = extsize * trklen90 / physlen; if (reltrk90 == 0) reltrk90 = 1; cyl90 = outcyl; head90 = outhead + reltrk90 - 1; while (head90 >= heads) { head90 -= heads; cyl90++; } /* Initialize the DIP header record */ diphdr = (DIPHDR*)(datablk.kdarea); memset (diphdr, 0, sizeof(DIPHDR)); diphdr->recid[0] = 0xFF; diphdr->recid[1] = 0xFF; diphdr->bcyl[0] = (outcyl >> 8) & 0xFF; diphdr->bcyl[1] = outcyl & 0xFF; diphdr->btrk[0] = (outhead >> 8) & 0xFF; diphdr->btrk[1] = outhead & 0xFF; diphdr->ecyl[0] = (endcyl >> 8) & 0xFF; diphdr->ecyl[1] = endcyl & 0xFF; diphdr->etrk[0] = (endhead >> 8) & 0xFF; diphdr->etrk[1] = endhead & 0xFF; diphdr->restart[2] = (outcyl >> 8) & 0xFF; diphdr->restart[3] = outcyl & 0xFF; diphdr->restart[4] = (outhead >> 8) & 0xFF; diphdr->restart[5] = outhead & 0xFF; diphdr->restart[6] = 1; diphdr->trkbal[0] = (remlen >> 8) & 0xFF; diphdr->trkbal[1] = remlen & 0xFF; diphdr->trklen[0] = (physlen >> 8) & 0xFF; diphdr->trklen[1] = physlen & 0xFF; diphdr->reused[2] = (outcyl >> 8) & 0xFF; diphdr->reused[3] = outcyl & 0xFF; diphdr->reused[4] = (outhead >> 8) & 0xFF; diphdr->reused[5] = outhead & 0xFF; diphdr->reused[6] = 1; diphdr->lasthead[0] = (lasthead >> 8) & 0xFF; diphdr->lasthead[1] = lasthead & 0xFF; diphdr->trklen90[0] = (trklen90 >> 8) & 0xFF; diphdr->trklen90[1] = trklen90 & 0xFF; diphdr->devcode = (ucbtype_code(devtype) & 0x0F) | 0xF0; diphdr->cchh90[0] = (cyl90 >> 8) & 0xFF; diphdr->cchh90[1] = cyl90 & 0xFF; diphdr->cchh90[2] = (head90 >> 8) & 0xFF; diphdr->cchh90[3] = head90 & 0xFF; diphdr->endid = 0xFF; /* Write the data block to the output file */ rc = write_block (cif, ofname, &datablk, keylen, datalen, devtype, heads, trklen, extsize, &outusedv, &outusedr, &outtrkbr, &outtrk, &outcyl, &outhead, &outrec); if (rc < 0) return -1; XMINFF (3, "HHCDL120I DIP complete at cyl %d head %d rec %d\n", outcyl, outhead, outrec); if (infolvl >= 5) data_dump (diphdr, sizeof(DIPHDR)); /* Return the last record number and track balance */ *lastrec = outrec; *trkbal = outtrkbr; /* Write data remaining in track buffer */ rc = write_track (cif, ofname, heads, trklen, &outusedv, &outtrk, &outcyl, &outhead); if (rc < 0) return -1; /* Return number of tracks and starting address of next dataset */ *numtrks = outtrk; *nxtcyl = outcyl; *nxthead = outhead; return 0; } /* end function dip_initialize */ /*-------------------------------------------------------------------*/ /* Subroutine to initialize a sequential dataset */ /* Input: */ /* sfname SEQ input file name */ /* ofname DASD image file name */ /* cif -> CKD image file descriptor */ /* devtype Output device type */ /* heads Output device number of tracks per cylinder */ /* trklen Output device virtual track length */ /* outcyl Output starting cylinder number */ /* outhead Output starting head number */ /* extsize Extent size in tracks */ /* dsorg Dataset organization (DA or PS) */ /* recfm Record Format (F or FB) */ /* lrecl Record length */ /* blksz Block size */ /* keyln Key length */ /* Output: */ /* lastrec Record number of last block written */ /* trkbal Number of bytes remaining on last track */ /* numtrks Number of tracks written */ /* nxtcyl Starting cylinder number for next dataset */ /* nxthead Starting head number for next dataset */ /*-------------------------------------------------------------------*/ static int seq_initialize (char *sfname, char *ofname, CIFBLK *cif, U16 devtype, int heads, int trklen, int outcyl, int outhead, int extsize, BYTE dsorg, BYTE recfm, int lrecl, int blksz, int keyln, int *lastrec, int *trkbal, int *numtrks, int *nxtcyl, int *nxthead) { int rc; /* Return code */ int sfd; /* Input seq file descriptor */ int size; /* Size left in input file */ int outusedv = 0; /* Output bytes used on track of virtual device */ int outusedr = 0; /* Output bytes used on track of real device */ int outtrkbr = 0; /* Output bytes remaining on track of real device */ int outtrk = 0; /* Output relative track */ int outrec = 0; /* Output record number */ struct stat st; /* Data area for fstat() */ DATABLK datablk; /* Data block */ char pathname[MAX_PATH]; /* sfname in host path format*/ /* Perform some checks */ if (!(dsorg & DSORG_PS) && !(dsorg & DSORG_DA)) { XMERRF ("HHCDL121E SEQ dsorg must be PS or DA: dsorg=0x%2.2x\n",dsorg); return -1; } if (recfm != RECFM_FORMAT_F && recfm != (RECFM_FORMAT_F|RECFM_BLOCKED)) { XMERRF ("HHCDL122E SEQ recfm must be F or FB: recfm=0x%2.2x\n",recfm); return -1; } if (blksz == 0) blksz = lrecl; if (lrecl == 0) lrecl = blksz; if (lrecl == 0 || blksz % lrecl != 0 || (blksz != lrecl && recfm == RECFM_FORMAT_F)) { XMERRF ("HHCDL123E SEQ invalid lrecl or blksz: lrecl=%d blksz=%d\n", lrecl,blksz); return -1; } if (keyln > 0 && blksz > lrecl) { XMERR ("HHCDL124E SEQ keyln must be 0 for blocked files\n"); return -1; } /* Open the input file */ hostpath(pathname, sfname, sizeof(pathname)); sfd = open (pathname, O_RDONLY|O_BINARY); if (sfd < 0) { XMERRF ("HHCDL125E Cannot open %s: %s\n", sfname, strerror(errno)); return -1; } /* Get input file status */ rc = fstat(sfd, &st); if (rc < 0) { XMERRF ("HHCDL126E Cannot stat %s: %s\n", sfname, strerror(errno)); close (sfd); return -1; } size = st.st_size; /* Read the first track */ rc = read_track (cif, *nxtcyl, *nxthead); if (rc < 0) { XMERRF ("HHCDL127E %s cyl %d head %d read error\n", ofname, *nxtcyl, *nxthead); close (sfd); return -1; } while (size > 0) { /* Read a block of data from the input file */ rc = read (sfd, &datablk.kdarea, blksz < size ? blksz : size); if (rc < (blksz < size ? blksz : size)) { XMERRF ("HHCDL128E %s read error: %s\n", sfname, strerror(errno)); close (sfd); return -1; } size -= rc; /* Pad the block if necessary */ if (rc < blksz) { /* Adjust blksize down to next highest multiple of lrecl */ blksz = (((rc-1) / lrecl) + 1) * lrecl; memset (&datablk.kdarea[rc], 0, blksz - rc); } rc = write_block (cif, ofname, &datablk, keyln, blksz - keyln, devtype, heads, trklen, extsize, &outusedv, &outusedr, &outtrkbr, &outtrk, &outcyl, &outhead, &outrec); if (rc < 0) { close (sfd); return -1; } } /* Close the input file */ close (sfd); /* Create the end of file record */ rc = write_block (cif, ofname, &datablk, 0, 0, devtype, heads, trklen, extsize, &outusedv, &outusedr, &outtrkbr, &outtrk, &outcyl, &outhead, &outrec); if (rc < 0) return -1; /* Return the last record number and track balance */ *lastrec = outrec; *trkbal = outtrkbr; /* Write data remaining in track buffer */ rc = write_track (cif, ofname, heads, trklen, &outusedv, &outtrk, &outcyl, &outhead); if (rc < 0) return -1; /* Return number of tracks and starting address of next dataset */ *numtrks = outtrk; *nxtcyl = outcyl; *nxthead = outhead; return 0; } /* end function seq_initialize */ /*-------------------------------------------------------------------*/ /* Subroutine to initialize an empty dataset */ /* Input: */ /* ofname DASD image file name */ /* cif -> CKD image file descriptor */ /* devtype Output device type */ /* heads Output device number of tracks per cylinder */ /* trklen Output device virtual track length */ /* outcyl Output starting cylinder number */ /* outhead Output starting head number */ /* extsize Extent size in tracks */ /* dsorg Dataset organization */ /* dirblks Number of directory blocks */ /* Output: */ /* dirblu Bytes used in last directory block */ /* lastrec Record number of last block written */ /* trkbal Number of bytes remaining on last track */ /* numtrks Number of tracks written */ /* nxtcyl Starting cylinder number for next dataset */ /* nxthead Starting head number for next dataset */ /*-------------------------------------------------------------------*/ static int empty_initialize (char *ofname, CIFBLK *cif, U16 devtype, int heads, int trklen, int outcyl, int outhead, int extsize, BYTE dsorg, int dirblks, int *dirblu, int *lastrec, int *trkbal, int *numtrks, int *nxtcyl, int *nxthead) { int rc; /* Return code */ int i; /* Loop counter */ int keylen; /* Key length of data block */ int datalen; /* Data length of data block */ int outusedv = 0; /* Output bytes used on track of virtual device */ int outusedr = 0; /* Output bytes used on track of real device */ int outtrkbr = 0; /* Output bytes remaining on track of real device */ int outdblu = 0; /* Output bytes used in last directory block */ int outtrk = 0; /* Output relative track */ int outrec = 0; /* Output record number */ DATABLK datablk; /* Data block */ /* Initialize the directory if dataset is a PDS */ if (dsorg & DSORG_PO) { /* Build the first directory block */ keylen = 8; datalen = 256; outdblu = 14; memset (datablk.kdarea, 0, keylen + datalen); memcpy (datablk.kdarea, eighthexFF, 8); datablk.kdarea[keylen] = (outdblu >> 8); datablk.kdarea[keylen+1] = outdblu & 0xFF; memcpy (datablk.kdarea + keylen + 2, eighthexFF, 8); /* Write directory blocks to output dataset */ for (i = 0; i < dirblks; i++) { /* Write a directory block */ rc = write_block (cif, ofname, &datablk, keylen, datalen, devtype, heads, trklen, extsize, &outusedv, &outusedr, &outtrkbr, &outtrk, &outcyl, &outhead, &outrec); if (rc < 0) return -1; /* Clear subsequent directory blocks to zero */ memset (datablk.kdarea, 0, keylen + datalen); } /* end for(i) */ } /* end if(DSORG_PO) */ /* Create the end of file record */ keylen = 0; datalen = 0; rc = write_block (cif, ofname, &datablk, keylen, datalen, devtype, heads, trklen, extsize, &outusedv, &outusedr, &outtrkbr, &outtrk, &outcyl, &outhead, &outrec); if (rc < 0) return -1; /* Return number of bytes used in last directory block */ *dirblu = outdblu; /* Return the last record number and track balance */ *lastrec = outrec; *trkbal = outtrkbr; /* Write data remaining in track buffer */ rc = write_track (cif, ofname, heads, trklen, &outusedv, &outtrk, &outcyl, &outhead); if (rc < 0) return -1; /* Return number of tracks and starting address of next dataset */ *numtrks = outtrk; *nxtcyl = outcyl; *nxthead = outhead; return 0; } /* end function empty_initialize */ /*-------------------------------------------------------------------*/ /* Subroutine to read a statement from the control file */ /* Input: */ /* cfp Control file pointer */ /* cfname Control file name */ /* stmt Buffer to receive control statement */ /* sbuflen Length of statement buffer */ /* Output: */ /* pstmtno Statement number */ /* The return value is 0 if a statement was successfully read, */ /* +1 if end of file, or -1 if error */ /*-------------------------------------------------------------------*/ static int read_ctrl_stmt (FILE *cfp, char *cfname, char *stmt, int sbuflen, int *pstmtno) { int stmtlen; /* Length of input statement */ static int stmtno = 0; /* Statement number */ while (1) { /* Read next record from control file */ stmtno++; *pstmtno = stmtno; if (fgets (stmt, sbuflen, cfp) == NULL) { /* Return code +1 if end of control file */ if (feof(cfp)) return +1; /* Return code -1 if control file input error */ XMERRF ("HHCDL019E Cannot read %s line %d: %s\n", cfname, stmtno, strerror(errno)); return -1; } #ifdef EXTERNALGUI /* Indicate input file progess */ if (extgui) fprintf (stderr, "IPOS=%" I64_FMT "d\n", (U64)ftell(cfp)); #endif /*EXTERNALGUI*/ /* Check for DOS end of file character */ if (stmt[0] == '\x1A') return +1; /* Check that end of statement has been read */ stmtlen = strlen(stmt); if (stmtlen == 0 || stmt[stmtlen-1] != '\n') { XMERRF ("HHCDL020E Line too long in %s line %d\n", cfname, stmtno); return -1; } /* Remove trailing carriage return and line feed */ stmtlen--; if (stmtlen > 0 && stmt[stmtlen-1] == '\r') stmtlen--; /* Remove trailing spaces and tab characters */ while (stmtlen > 0 && (stmt[stmtlen-1] == SPACE || stmt[stmtlen-1] == '\t')) stmtlen--; stmt[stmtlen] = '\0'; /* Print the input statement */ XMINFF (0, "--------- %s\n", stmt); /* Ignore comment statements */ if (stmtlen == 0 || stmt[0] == '#' || stmt[0] == '*') continue; break; } /* end while */ return 0; } /* end function read_ctrl_stmt */ /*-------------------------------------------------------------------*/ /* Subroutine to parse a dataset statement from the control file */ /* Input: */ /* stmt Control statement */ /* Output: */ /* dsname ASCIIZ dataset name (1-44 bytes + terminator) */ /* method Processing method (see METHOD_xxx defines) */ /* */ /* The following field is returned only for the XMIT method: */ /* ifptr Pointer to XMIT initialization file name */ /* */ /* The following fields are returned for non-XMIT methods: */ /* units Allocation units (C=CYL, T=TRK) */ /* sppri Primary allocation quantity */ /* spsec Secondary allocation quantity */ /* spdir Directory allocation quantity */ /* dsorg 1st byte of dataset organization bits */ /* recfm 1st byte of record format bits */ /* lrecl Logical record length */ /* blksz Block size */ /* keyln Key length */ /* The return value is 0 if successful, or -1 if error. */ /* Control statement format: */ /* dsname method [initfile] [space [dcbattrib]] */ /* The method can be: */ /* XMIT = load PDS from initfile containing an IEBCOPY unload */ /* dataset created using the TSO TRANSMIT command */ /* EMPTY = create empty dataset (do not specify initfile) */ /* DIP = initialize LOGREC dataset with IFCDIP00 header record */ /* CVOL = initialize SYSCTLG dataset as an OS CVOL */ /* VTOC = reserve space for the VTOC (dsname is ignored) */ /* The space allocation can be: */ /* CYL [pri [sec [dir]]] */ /* TRK [pri [sec [dir]]] */ /* If primary quantity is omitted then the dataset will be */ /* allocated the minimum number of tracks or cylinders needed */ /* to contain the data loaded from the initfile. */ /* Default allocation is in tracks. */ /* The dcb attributes can be: */ /* dsorg recfm lrecl blksize keylen */ /* For the XMIT method the dcb attributes are taken from the */ /* initialization file and need not be specified. */ /* Examples: */ /* SYS1.PARMLIB XMIT /cdrom/os360/reslibs/parmlib.xmi */ /* SYS1.NUCLEUS XMIT /cdrom/os360/reslibs/nucleus.xmi CYL */ /* SYS1.SYSJOBQE EMPTY CYL 10 0 0 DA F 176 176 0 */ /* SYS1.DUMP EMPTY CYL 10 2 0 PS FB 4104 4104 0 */ /* SYS1.OBJPDS EMPTY CYL 10 2 50 PO FB 80 3120 0 */ /* SYSVTOC VTOC CYL 1 */ /* SYSCTLG CVOL TRK 10 */ /* SYS1.LOGREC DIP CYL 1 */ /*-------------------------------------------------------------------*/ static int parse_ctrl_stmt (char *stmt, char *dsname, BYTE *method, char **ifptr, BYTE *units, int *sppri, int *spsec, int *spdir, BYTE *dsorg, BYTE *recfm, int *lrecl, int *blksz, int *keyln) { char *pdsnam; /* -> dsname in input stmt */ char *punits; /* -> allocation units */ char *psppri; /* -> primary space quantity */ char *pspsec; /* -> secondary space qty. */ char *pspdir; /* -> directory space qty. */ char *pdsorg; /* -> dataset organization */ char *precfm; /* -> record format */ char *plrecl; /* -> logical record length */ char *pblksz; /* -> block size */ char *pkeyln; /* -> key length */ char *pimeth; /* -> initialization method */ char *pifile; /* -> initialization filename*/ BYTE c; /* Character work area */ /* Parse the input statement */ pdsnam = strtok (stmt, " \t"); pimeth = strtok (NULL, " \t"); /* Check that all mandatory fields are present */ if (pdsnam == NULL || pimeth == NULL) { XMERR ("HHCDL021E DSNAME or initialization method missing\n"); return -1; } /* Return the dataset name in EBCDIC and ASCII */ string_to_upper (pdsnam); memset (dsname, 0, 45); strncpy (dsname, pdsnam, 44); /* Set default dataset attribute values */ *units = 'T'; *sppri = 1; *spsec = 0; *spdir = 0; *dsorg = 0x00; *recfm = 0x00; *lrecl = 0; *blksz = 0; *keyln = 0; *ifptr = NULL; /* Test for valid initialization method */ if (strcasecmp(pimeth, "XMIT") == 0) *method = METHOD_XMIT; else if (strcasecmp(pimeth, "VS") == 0) *method = METHOD_VS; else if (strcasecmp(pimeth, "EMPTY") == 0) *method = METHOD_EMPTY; else if (strcasecmp(pimeth, "DIP") == 0) *method = METHOD_DIP; else if (strcasecmp(pimeth, "CVOL") == 0) *method = METHOD_CVOL; else if (strcasecmp(pimeth, "VTOC") == 0) *method = METHOD_VTOC; else if (strcasecmp(pimeth, "SEQ") == 0) *method = METHOD_SEQ; else { XMERRF ("HHCDL022E Invalid initialization method: %s\n", pimeth); return -1; } /* Locate the initialization file name */ if (*method == METHOD_XMIT || *method == METHOD_VS || *method == METHOD_SEQ) { pifile = strtok (NULL, " \t"); if (pifile == NULL) { XMERR ("HHCDL023E Initialization file name missing\n"); return -1; } *ifptr = pifile; } /* Determine the space allocation units */ punits = strtok (NULL, " \t"); if (punits == NULL) return 0; string_to_upper (punits); if (strcmp(punits, "CYL") == 0) *units = 'C'; else if (strcmp(punits, "TRK") == 0) *units = 'T'; else { XMERRF ("HHCDL024E Invalid allocation units: %s\n", punits); return -1; } /* Determine the primary space allocation quantity */ psppri = strtok (NULL, " \t"); if (psppri == NULL) return 0; if (sscanf(psppri, "%u%c", sppri, &c) != 1) { XMERRF ("HHCDL025E Invalid primary space: %s\n", psppri); return -1; } /* Determine the secondary space allocation quantity */ pspsec = strtok (NULL, " \t"); if (pspsec == NULL) return 0; if (sscanf(pspsec, "%u%c", spsec, &c) != 1) { XMERRF ("HHCDL026E Invalid secondary space: %s\n", pspsec); return -1; } /* Determine the directory space allocation quantity */ pspdir = strtok (NULL, " \t"); if (pspdir == NULL) return 0; if (sscanf(pspdir, "%u%c", spdir, &c) != 1) { XMERRF ("HHCDL027E Invalid directory space: %s\n", pspsec); return -1; } /* Determine the dataset organization */ pdsorg = strtok (NULL, " \t"); if (pdsorg == NULL) return 0; string_to_upper (pdsorg); if (strcmp(pdsorg, "IS") == 0) *dsorg = DSORG_IS; else if (strcmp(pdsorg, "PS") == 0) *dsorg = DSORG_PS; else if (strcmp(pdsorg, "DA") == 0) *dsorg = DSORG_DA; else if (strcmp(pdsorg, "PO") == 0) *dsorg = DSORG_PO; else { XMERRF ("HHCDL028E Invalid dataset organization: %s\n", pdsorg); return -1; } /* Determine the record format */ precfm = strtok (NULL, " \t"); if (precfm == NULL) return 0; string_to_upper (precfm); if (strcmp(precfm, "F") == 0) *recfm = RECFM_FORMAT_F; else if (strcmp(precfm, "FB") == 0) *recfm = RECFM_FORMAT_F | RECFM_BLOCKED; else if (strcmp(precfm, "FBS") == 0) *recfm = RECFM_FORMAT_F | RECFM_BLOCKED | RECFM_SPANNED; else if (strcmp(precfm, "V") == 0) *recfm = RECFM_FORMAT_V; else if (strcmp(precfm, "VB") == 0) *recfm = RECFM_FORMAT_V | RECFM_BLOCKED; else if (strcmp(precfm, "VBS") == 0) *recfm = RECFM_FORMAT_V | RECFM_BLOCKED | RECFM_SPANNED; else if (strcmp(precfm, "U") == 0) *recfm = RECFM_FORMAT_U; else { XMERRF ("HHCDL029E Invalid record format: %s\n", precfm); return -1; } /* Determine the logical record length */ plrecl = strtok (NULL, " \t"); if (plrecl == NULL) return 0; if (sscanf(plrecl, "%u%c", lrecl, &c) != 1 || *lrecl > MAX_DATALEN) { XMERRF ("HHCDL030E Invalid logical record length: %s\n", plrecl); return -1; } /* Determine the block size */ pblksz = strtok (NULL, " \t"); if (pblksz == NULL) return 0; if (sscanf(pblksz, "%u%c", blksz, &c) != 1 || *blksz > MAX_DATALEN) { XMERRF ("HHCDL031E Invalid block size: %s\n", pblksz); return -1; } /* Determine the key length */ pkeyln = strtok (NULL, " \t"); if (pkeyln == NULL) return 0; if (sscanf(pkeyln, "%u%c", keyln, &c) != 1 || *keyln > 255) { XMERRF ("HHCDL032E Invalid key length: %s\n", pkeyln); return -1; } return 0; } /* end function parse_ctrl_stmt */ /*-------------------------------------------------------------------*/ /* Subroutine to process the control file */ /* Input: */ /* cfp Control file pointer */ /* cfname Control file name */ /* ofname DASD image file name */ /* cif -> CKD image file descriptor */ /* volser Output volume serial number (ASCIIZ) */ /* devtype Output device type */ /* reqcyls Requested device size in cylinders, or zero */ /* heads Output device number of tracks per cylinder */ /* trklen Output device virtual track length */ /* outcyl Output starting cylinder number */ /* outhead Output starting head number */ /* Output: */ /* Datasets are written to the DASD image file as indicated */ /* by the control statements. */ /*-------------------------------------------------------------------*/ static int process_control_file (FILE *cfp, char *cfname, char *ofname, CIFBLK *cif, char *volser, U16 devtype, int reqcyls, int heads, int trklen, int outcyl, int outhead) { int rc; /* Return code */ int i; /* Array subscript */ int n; /* Integer work area */ char dsname[45]; /* Dataset name (ASCIIZ) */ BYTE method; /* Initialization method */ char *ifname; /* ->Initialization file name*/ BYTE units; /* C=CYL, T=TRK */ int sppri; /* Primary space quantity */ int spsec; /* Secondary space quantity */ int spdir; /* Directory space quantity */ BYTE dsorg; /* Dataset organization */ BYTE recfm; /* Record format */ int lrecl; /* Logical record length */ int blksz; /* Block size */ int keyln; /* Key length */ char stmt[256]; /* Control file statement */ int stmtno; /* Statement number */ int mintrks; /* Minimum size of dataset */ int maxtrks; /* Maximum size of dataset */ int outusedv; /* Bytes used in track buffer*/ int tracks = 0; /* Tracks used in dataset */ int numdscb = 0; /* Number of DSCBs */ DATABLK **dscbtab; /* -> Array of DSCB pointers */ int dirblu; /* Bytes used in last dirblk */ int lasttrk; /* Relative track number of last used track of dataset*/ int lastrec; /* Record number of last used block of dataset */ int trkbal; /* Bytes unused on last track*/ int bcyl; /* Dataset begin cylinder */ int bhead; /* Dataset begin head */ int ecyl; /* Dataset end cylinder */ int ehead; /* Dataset end head */ int vtoctrk = 0; /* VTOC start relative track */ int vtocext = 0; /* VTOC extent size (tracks) */ BYTE volvtoc[5]; /* VTOC begin CCHHR */ int offset = 0; /* Offset into trkbuf */ int fsflag = 0; /* 1=Free space message sent */ /* Obtain storage for the array of DSCB pointers */ dscbtab = (DATABLK**)malloc (sizeof(DATABLK*) * MAXDSCB); if (dscbtab == NULL) { XMERRF ("HHCDL010E Cannot obtain storage for DSCB pointer array: %s\n", strerror(errno)); return -1; } /* Initialize the DSCB array with format 4 and format 5 DSCBs */ rc = build_format4_dscb (dscbtab, numdscb, cif); if (rc < 0) return -1; numdscb++; rc = build_format5_dscb (dscbtab, numdscb); if (rc < 0) return -1; numdscb++; /* Read dataset statements from control file */ while (1) { /* Read next statement from control file */ rc = read_ctrl_stmt (cfp, cfname, stmt, sizeof(stmt), &stmtno); if (rc < 0) return -1; /* Exit if end of file */ if (rc > 0) break; /* Parse dataset statement from control file */ rc = parse_ctrl_stmt (stmt, dsname, &method, &ifname, &units, &sppri, &spsec, &spdir, &dsorg, &recfm, &lrecl, &blksz, &keyln); /* Exit if error in control file */ if (rc < 0) { XMERRF ("HHCDL011E Invalid statement in %s line %d\n", cfname, stmtno); return -1; } /* Write empty tracks if allocation is in cylinders */ while (units == 'C' && outhead != 0) { /* Initialize track buffer with empty track */ init_track (trklen, cif->trkbuf, outcyl, outhead, &outusedv); /* Write track to output file */ rc = write_track (cif, ofname, heads, trklen, &outusedv, &tracks, &outcyl, &outhead); if (rc < 0) break; } /* end while */ XMINFF (1, "HHCDL012I Creating dataset %s at cyl %d head %d\n", dsname, outcyl, outhead); bcyl = outcyl; bhead = outhead; /* Calculate minimum size of dataset in tracks */ mintrks = (units == 'C' ? sppri * heads : sppri); /* Create dataset according to method specified */ switch (method) { case METHOD_XMIT: /* IEBCOPY wrapped in XMIT */ case METHOD_VS: /* "straight" IEBCOPY */ /* Create dataset using IEBCOPY file as input */ maxtrks = MAX_TRACKS; rc = process_iebcopy_file (ifname, ofname, cif, devtype, heads, trklen, outcyl, outhead, maxtrks, method, &dsorg, &recfm, &lrecl, &blksz, &keyln, &dirblu, &lastrec, &trkbal, &tracks, &outcyl, &outhead); if (rc < 0) return -1; break; case METHOD_DIP: /* Initialize LOGREC dataset */ rc = dip_initialize (ofname, cif, devtype, heads, trklen, outcyl, outhead, mintrks, &lastrec, &trkbal, &tracks, &outcyl, &outhead); if (rc < 0) return -1; break; case METHOD_CVOL: /* Initialize SYSCTLG dataset */ rc = cvol_initialize (ofname, cif, volser, devtype, heads, trklen, outcyl, outhead, mintrks, &lastrec, &trkbal, &tracks, &outcyl, &outhead); if (rc < 0) return -1; break; case METHOD_VTOC: /* Reserve space for VTOC */ vtoctrk = (outcyl * heads) + outhead; vtocext = mintrks; tracks = 0; lastrec = 0; trkbal = 0; break; case METHOD_SEQ: /* Create sequential dataset */ rc = seq_initialize (ifname, ofname, cif, devtype, heads, trklen, outcyl, outhead, mintrks, dsorg, recfm, lrecl, blksz, keyln, &lastrec, &trkbal, &tracks, &outcyl, &outhead); if (rc < 0) return -1; break; default: case METHOD_EMPTY: /* Create empty dataset */ rc = empty_initialize (ofname, cif, devtype, heads, trklen, outcyl, outhead, mintrks, dsorg, spdir, &dirblu, &lastrec, &trkbal, &tracks, &outcyl, &outhead); if (rc < 0) return -1; break; } /* end switch(method) */ /* Calculate the relative track number of last used track */ lasttrk = tracks - 1; /* Round up space allocation if allocated in cylinders */ if (units == 'C') { n = (tracks + heads - 1) / heads * heads; if (mintrks < n) mintrks = n; } /* Fill unused space in dataset with empty tracks */ while (tracks < mintrks) { /* Initialize track buffer with empty track */ init_track (trklen, cif->trkbuf, outcyl, outhead, &outusedv); /* Write track to output file */ rc = write_track (cif, ofname, heads, trklen, &outusedv, &tracks, &outcyl, &outhead); if (rc < 0) return -1; } /* end while(tracks) */ /* Print number of tracks written to dataset */ XMINFF (2, "HHCDL013I Dataset %s contains %d track%s\n", dsname, tracks, (tracks == 1 ? "" : "s")); /* Calculate end of extent cylinder and head */ ecyl = (outhead > 0 ? outcyl : outcyl - 1); ehead = (outhead > 0 ? outhead - 1 : heads - 1); /* Create format 1 DSCB for the dataset */ if (method != METHOD_VTOC) { rc = build_format1_dscb (dscbtab, numdscb, dsname, volser, dsorg, recfm, lrecl, blksz, keyln, dirblu, lasttrk, lastrec, trkbal, units, spsec, bcyl, bhead, ecyl, ehead); if (rc < 0) return -1; numdscb++; } } /* end while */ /* Write the VTOC */ rc = write_vtoc (dscbtab, numdscb, cif, ofname, devtype, reqcyls, heads, trklen, vtoctrk, vtocext, &outcyl, &outhead, volvtoc); if (rc < 0) return -1; /* Write empty tracks up to end of volume */ while (outhead != 0 || outcyl < reqcyls) { /* Issue free space information message */ if (fsflag == 0) { XMINFF (1, "HHCDL014I Free space starts at cyl %d head %d\n", outcyl, outhead); fsflag = 1; } #ifdef EXTERNALGUI /* Indicate output file progess */ if (extgui) if ((outcyl % 10) == 0) fprintf (stderr, "OUTCYL=%d\n", outcyl); #endif /*EXTERNALGUI*/ /* Initialize track buffer with empty track */ init_track (trklen, cif->trkbuf, outcyl, outhead, &outusedv); /* Write track to output file */ rc = write_track (cif, ofname, heads, trklen, &outusedv, &tracks, &outcyl, &outhead); if (rc < 0) return -1; } /* end while */ if (outcyl > reqcyls && reqcyls != 0) { XMINFF (0, "HHCDL015W Volume exceeds %d cylinders\n", reqcyls); } XMINFF (0, "HHCDL016I Total of %d cylinders written to %s\n", outcyl, ofname); /* Update the VTOC pointer in the volume label */ offset = CKDDASD_TRKHDR_SIZE + CKDDASD_RECHDR_SIZE + 8 + CKDDASD_RECHDR_SIZE + IPL1_KEYLEN + IPL1_DATALEN + CKDDASD_RECHDR_SIZE + IPL2_KEYLEN + IPL2_DATALEN + CKDDASD_RECHDR_SIZE + VOL1_KEYLEN + 11; XMINFF (5, "HHCDL017I Updating VTOC pointer %2.2X%2.2X%2.2X%2.2X%2.2X\n", volvtoc[0], volvtoc[1], volvtoc[2], volvtoc[3], volvtoc[4]); rc = read_track (cif, 0, 0); if (rc < 0) { XMERR ("HHCDL018E Cannot read VOL1 record\n"); return -1; } memcpy (cif->trkbuf + offset, volvtoc, sizeof(volvtoc)); cif->trkmodif = 1; /* Release the DSCB buffers */ for (i = 0; i < numdscb; i++) free (dscbtab[i]); /* Release the array of DSCB pointers */ free (dscbtab); return 0; } /* end function process_control_file */ /*-------------------------------------------------------------------*/ /* DASDLOAD main entry point */ /*-------------------------------------------------------------------*/ int main (int argc, char *argv[]) { int rc = 0; /* Return code */ char *cfname; /* -> Control file name */ char *ofname; /* -> Output file name */ FILE *cfp; /* Control file pointer */ CIFBLK *cif; /* -> CKD image block */ CKDDEV *ckd; /* -> CKD table entry */ char *volser; /* -> Volume serial (ASCIIZ) */ char *sdevtp; /* -> Device type (ASCIIZ) */ char *sdevsz; /* -> Device size (ASCIIZ) */ char *iplfnm; /* -> IPL text file or NULL */ BYTE c; /* Character work area */ U16 devtype; /* Output device type */ int devcyls; /* Default device size (cyls)*/ int reqcyls; /* Requested device size (cyls) or 0 = use minimum size */ int outheads; /* Output device trks/cyl */ int outmaxdl; /* Output device maximum size record data length value */ int outtrklv; /* Output device track length of virtual device */ int reltrk; /* Output track number */ int outcyl; /* Output cylinder number */ int outhead; /* Output head number */ char stmt[256]; /* Control file statement */ int stmtno; /* Statement number */ BYTE comp = 0xff; /* Compression algoritm */ int altcylflag = 0; /* Alternate cylinders flag */ int lfs = 0; /* 1 = Large file */ char pathname[MAX_PATH]; /* cfname in host path format*/ INITIALIZE_UTILITY("dasdload"); /* Display the program identification message */ display_version (stderr, "Hercules DASD loader program ", FALSE); /* Process optional arguments */ for ( ; argc > 1 && argv[1][0] == '-'; argv++, argc--) { if (strcmp("0", &argv[1][1]) == 0) comp = CCKD_COMPRESS_NONE; #ifdef CCKD_COMPRESS_ZLIB else if (strcmp("z", &argv[1][1]) == 0) comp = CCKD_COMPRESS_ZLIB; #endif #ifdef CCKD_COMPRESS_BZIP2 else if (strcmp("bz2", &argv[1][1]) == 0) comp = CCKD_COMPRESS_BZIP2; #endif else if (strcmp("a", &argv[1][1]) == 0) altcylflag = 1; else if (strcmp("lfs", &argv[1][1]) == 0 && sizeof(off_t) > 4) lfs = 1; else argexit(0); } /* Check the number of arguments */ if (argc < 3 || argc > 4) argexit(4); /* The first argument is the control file name */ cfname = argv[1]; if (argv[1] == NULL || strlen(argv[1]) == 0) argexit(1); /* The second argument is the DASD image file name */ ofname = argv[2]; if (argv[2] == NULL || strlen(argv[2]) == 0) argexit(2); /* The optional third argument is the message level */ if (argc > 3 && argv[3] != NULL) { if (sscanf(argv[3], "%u%c", &infolvl, &c) != 1 || infolvl > 5) argexit(3); } /* Open the control file */ hostpath(pathname, cfname, sizeof(pathname)); cfp = fopen (pathname, "r"); if (cfp == NULL) { XMERRF ("HHCDL001E Cannot open %s: %s\n", cfname, strerror(errno)); return -1; } /* Read first statement from control file */ rc = read_ctrl_stmt (cfp, cfname, stmt, sizeof(stmt), &stmtno); if (rc < 0) return -1; /* Error if end of file */ if (rc > 0) { XMERRF ("HHCDL002E Volume serial statement missing from %s\n", cfname); return -1; } /* Parse the volume serial statement */ volser = strtok (stmt, " \t"); sdevtp = strtok (NULL, " \t"); sdevsz = strtok (NULL, " \t"); iplfnm = strtok (NULL, " \t"); /* Validate the volume serial number */ if (volser == NULL || strlen(volser) == 0 || strlen(volser) > 6) { XMERRF ("HHCDL003E Volume serial %s in %s line %d is not valid\n", volser, cfname, stmtno); return -1; } string_to_upper (volser); /* Validate the device type */ ckd = dasd_lookup (DASD_CKDDEV, sdevtp, 0, 0); if (ckd == NULL) { XMERRF ("HHCDL004E Device type %s in %s line %d is not recognized\n", sdevtp, cfname, stmtno); return -1; } devtype = ckd->devt; /* Obtain number of heads per cylinder, maximum data length per track, and default number of cylinders per device */ outheads = ckd->heads; devcyls = ckd->cyls; if (altcylflag) devcyls += ckd->altcyls; outmaxdl = ckd->r1; /* Use default device size if requested size is omitted or is zero or is "*" or compression is specified */ reqcyls = 0; if (sdevsz != NULL && strcmp(sdevsz, "*") != 0 && comp == 0xff) { /* Validate the requested device size in cylinders */ if (sscanf(sdevsz, "%u%c", &reqcyls, &c) != 1) { XMERRF ("HHCDL005E %s in %s line %d is not a valid cylinder " "count\n", sdevsz, cfname, stmtno); return -1; } } if (reqcyls == 0) reqcyls = devcyls; /* Calculate the track size of the virtual device */ outtrklv = sizeof(CKDDASD_TRKHDR) + sizeof(CKDDASD_RECHDR) + R0_DATALEN + sizeof(CKDDASD_RECHDR) + outmaxdl + sizeof(eighthexFF); outtrklv = ROUND_UP(outtrklv,512); /* Display progress message */ XMINFF (0, "HHCDL006I Creating %4.4X volume %s: " "%u trks/cyl, %u bytes/track\n", devtype, volser, outheads, outtrklv); /* Create the output file */ #ifdef EXTERNALGUI if (extgui) fprintf (stderr, "REQCYLS=%d\n", reqcyls); #endif /*EXTERNALGUI*/ rc = create_ckd (ofname, devtype, outheads, outmaxdl, reqcyls, volser, comp, lfs, 0, 0, 0); if (rc < 0) { XMERRF ("HHCDL007E Cannot create %s\n", ofname); return -1; } /* Open the output file */ cif = open_ckd_image (ofname, NULL, O_RDWR | O_BINARY, 0); if (!cif) { XMERRF ("HHCDL008E Cannot open %s\n", ofname); return -1; } /* Display progress message */ XMINFF (0, "HHCDL009I Loading %4.4X volume %s\n", devtype, volser); /* Write track zero to the DASD image file */ rc = write_track_zero (cif, ofname, volser, devtype, outheads, outtrklv, iplfnm, &reltrk, &outcyl, &outhead); if (rc < 0) return -1; /* Process the control file to create the datasets */ rc = process_control_file (cfp, cfname, ofname, cif, volser, devtype, reqcyls, outheads, outtrklv, outcyl, outhead); /* Close files and release buffers */ fclose (cfp); close_ckd_image (cif); return rc; } /* end function main */ hercules-3.07/dasdls.c000644 000765 000765 00000010255 11143760542 016367 0ustar00jmaynardjmaynard000000 000000 /* * dasdls * * Copyright 2000-2009 by Malcolm Beattie * Based on code copyright by Roger Bowler, 1999-2009 * * $Id: dasdls.c 5125 2009-01-23 12:01:44Z bernard $ * * $Log$ * Revision 1.27 2008/11/04 04:50:46 fish * Ensure consistent utility startup * * Revision 1.26 2007/06/23 00:04:08 ivan * Update copyright notices to include current year (2007) * * Revision 1.25 2006/12/08 09:43:19 jj * Add CVS message log * */ #include "hstdinc.h" #include "hercules.h" #include "dasdblks.h" static int needsep = 0; /* Write newline separator next time */ int end_of_track(BYTE *p) { return p[0] == 0xff && p[1] == 0xff && p[2] == 0xff && p[3] == 0xff && p[4] == 0xff && p[5] == 0xff && p[6] == 0xff && p[7] == 0xff; } /* list_contents partly based on dasdutil.c:search_key_equal */ int list_contents(CIFBLK *cif, char *volser, DSXTENT *extent) { int cext = 0; int ccyl = (extent[cext].xtbcyl[0] << 8) | extent[cext].xtbcyl[1]; int chead = (extent[cext].xtbtrk[0] << 8) | extent[cext].xtbtrk[1]; int ecyl = (extent[cext].xtecyl[0] << 8) | extent[cext].xtecyl[1]; int ehead = (extent[cext].xtetrk[0] << 8) | extent[cext].xtetrk[1]; #ifdef EXTERNALGUI if (extgui) fprintf(stderr,"ETRK=%d\n",((ecyl*(cif->heads))+ehead)); #endif /*EXTERNALGUI*/ printf("%s%s: VOLSER=%s\n", needsep ? "\n" : "", cif->fname, volser); needsep = 1; do { BYTE *ptr; int rc = read_track(cif, ccyl, chead); #ifdef EXTERNALGUI if (extgui) fprintf(stderr,"CTRK=%d\n",((ccyl*(cif->heads))+chead)); #endif /*EXTERNALGUI*/ if (rc < 0) return -1; ptr = cif->trkbuf + CKDDASD_TRKHDR_SIZE; while (!end_of_track(ptr)) { char dsname[45]; CKDDASD_RECHDR *rechdr = (CKDDASD_RECHDR*)ptr; int kl = rechdr->klen; int dl = (rechdr->dlen[0] << 8) | rechdr->dlen[1]; make_asciiz(dsname, sizeof(dsname), ptr + CKDDASD_RECHDR_SIZE, kl); /* XXXX Is this a suitable sanity check for a legal dsname? */ if (isalnum(*dsname)) printf("%s\n", dsname); ptr += CKDDASD_RECHDR_SIZE + kl + dl; } chead++; if (chead >= cif->heads) { ccyl++; chead = 0; } } while (ccyl < ecyl || (ccyl == ecyl && chead <= ehead)); return 0; } /* do_ls_cif based on dasdutil.c:build_extent_array */ int do_ls_cif(CIFBLK *cif) { int rc, cyl, head, rec, len; unsigned char *vol1data; FORMAT4_DSCB *f4dscb; char volser[7]; rc = read_block(cif, 0, 0, 3, 0, 0, &vol1data, &len); if (rc < 0) return -1; if (rc > 0) { fprintf(stderr, "VOL1 record not found\n"); return -1; } make_asciiz(volser, sizeof(volser), vol1data+4, 6); cyl = (vol1data[11] << 8) | vol1data[12]; head = (vol1data[13] << 8) | vol1data[14]; rec = vol1data[15]; rc = read_block(cif, cyl, head, rec, (void *)&f4dscb, &len, 0, 0); if (rc < 0) return -1; if (rc > 0) { fprintf(stderr, "F4DSCB record not found\n"); return -1; } return list_contents(cif, volser, &f4dscb->ds4vtoce); } int do_ls(char *file, char *sfile) { CIFBLK *cif = open_ckd_image(file, sfile, O_RDONLY|O_BINARY, 0); if (!cif || do_ls_cif(cif) || close_ckd_image(cif)) return -1; return 0; } int main(int argc, char **argv) { int rc = 0; char *fn, *sfn; INITIALIZE_UTILITY("dasdls"); /* Display program info message */ display_version (stderr, "Hercules DASD list program ", FALSE); if (argc < 2) { fprintf(stderr, "Usage: dasdls dasd_image [sf=shadow-file-name]...\n"); exit(2); } /* * If your version of Hercules doesn't have support in its * dasdutil.c for turning off verbose messages, then remove * the following line but you'll have to live with chatty * progress output on stdout. */ set_verbose_util(0); while (*++argv) { fn = *argv; if (*(argv+1) && strlen (*(argv+1)) > 3 && !memcmp(*(argv+1), "sf=", 3)) sfn = *++argv; else sfn = NULL; if (do_ls(fn, sfn)) rc = 1; } return rc; } hercules-3.07/dasdpdsu.c000644 000765 000765 00000032443 11143760543 016730 0ustar00jmaynardjmaynard000000 000000 /* DASDPDSU.C (c) Copyright Roger Bowler, 1999-2009 */ /* Hercules DASD Utilities: PDS unloader */ // $Id: dasdpdsu.c 5125 2009-01-23 12:01:44Z bernard $ /*-------------------------------------------------------------------*/ /* This program unloads members of a partitioned dataset from */ /* a virtual DASD volume and copies each member to a flat file. */ /* */ /* The command format is: */ /* dasdpdsu ckdfile dsname [ascii] */ /* where: ckdfile is the name of the CKD image file */ /* dsname is the name of the PDS to be unloaded */ /* ascii is an optional keyword which will cause the members */ /* to be unloaded as ASCII variable length text files. */ /* Each member is copied to a file memname.mac in the current */ /* working directory. If the ascii keyword is not specified then */ /* the members are unloaded as fixed length binary files. */ /*-------------------------------------------------------------------*/ // $Log$ // Revision 1.28 2008/11/04 04:50:46 fish // Ensure consistent utility startup // // Revision 1.27 2007/06/23 00:04:08 ivan // Update copyright notices to include current year (2007) // // Revision 1.26 2006/12/08 09:43:19 jj // Add CVS message log // #include "hstdinc.h" #include "hercules.h" #include "dasdblks.h" /*-------------------------------------------------------------------*/ /* Static data areas */ /*-------------------------------------------------------------------*/ static BYTE asciiflag = 0; /* 1=Translate to ASCII */ static BYTE eighthexFF[] = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}; /*-------------------------------------------------------------------*/ /* Subroutine to process a member */ /* Input: */ /* cif -> CKD image file descriptor structure */ /* noext Number of extents in dataset */ /* extent Dataset extent array */ /* memname Member name (ASCIIZ) */ /* ttr Member TTR */ /* */ /* Return value is 0 if successful, or -1 if error */ /*-------------------------------------------------------------------*/ static int process_member (CIFBLK *cif, int noext, DSXTENT extent[], char *memname, BYTE *ttr) { int rc; /* Return code */ int len; /* Record length */ int trk; /* Relative track number */ int cyl; /* Cylinder number */ int head; /* Head number */ int rec; /* Record number */ BYTE *buf; /* -> Data block */ FILE *ofp; /* Output file pointer */ char ofname[256]; /* Output file name */ int offset; /* Offset of record in buffer*/ char card[81]; /* Logical record (ASCIIZ) */ char pathname[MAX_PATH]; /* ofname in host format */ /* Build the output file name */ memset (ofname, 0, sizeof(ofname)); strncpy (ofname, memname, 8); string_to_lower (ofname); strcat (ofname, ".mac"); /* Open the output file */ hostpath(pathname, ofname, sizeof(pathname)); ofp = fopen (pathname, (asciiflag? "w" : "wb")); if (ofp == NULL) { fprintf (stderr, "Cannot open %s: %s\n", ofname, strerror(errno)); return -1; } /* Point to the start of the member */ trk = (ttr[0] << 8) | ttr[1]; rec = ttr[2]; fprintf (stderr, "Member %s TTR=%4.4X%2.2X\n", memname, trk, rec); /* Read the member */ while (1) { /* Convert relative track to cylinder and head */ rc = convert_tt (trk, noext, extent, cif->heads, &cyl, &head); if (rc < 0) return -1; // fprintf (stderr, // "CCHHR=%4.4X%4.4X%2.2X\n", // cyl, head, rec); /* Read a data block */ rc = read_block (cif, cyl, head, rec, NULL, NULL, &buf, &len); if (rc < 0) return -1; /* Move to next track if record not found */ if (rc > 0) { trk++; rec = 1; continue; } /* Exit at end of member */ if (len == 0) break; /* Check length of data block */ if (len % 80 != 0) { fprintf (stderr, "Bad block length %d at cyl %d head %d rec %d\n", len, cyl, head, rec); return -1; } /* Process each record in the data block */ for (offset = 0; offset < len; offset += 80) { if (asciiflag) { make_asciiz (card, sizeof(card), buf + offset, 72); fprintf (ofp, "%s\n", card); } else { fwrite (buf+offset, 80, 1, ofp); } if (ferror(ofp)) { fprintf (stderr, "Error writing %s: %s\n", ofname, strerror(errno)); return -1; } } /* end for(offset) */ /* Point to the next data block */ rec++; } /* end while */ /* Close the output file and exit */ fclose (ofp); return 0; } /* end function process_member */ /*-------------------------------------------------------------------*/ /* Subroutine to process a directory block */ /* Input: */ /* cif -> CKD image file descriptor structure */ /* noext Number of extents in dataset */ /* extent Dataset extent array */ /* dirblk Pointer to directory block */ /* */ /* Return value is 0 if OK, +1 if end of directory, or -1 if error */ /*-------------------------------------------------------------------*/ static int process_dirblk (CIFBLK *cif, int noext, DSXTENT extent[], BYTE *dirblk) { int rc; /* Return code */ int size; /* Size of directory entry */ int k; /* Userdata halfword count */ BYTE *dirptr; /* -> Next byte within block */ int dirrem; /* Number of bytes remaining */ PDSDIR *dirent; /* -> Directory entry */ char memname[9]; /* Member name (ASCIIZ) */ /* Load number of bytes in directory block */ dirptr = dirblk; dirrem = (dirptr[0] << 8) | dirptr[1]; if (dirrem < 2 || dirrem > 256) { fprintf (stderr, "Directory block byte count is invalid\n"); return -1; } /* Point to first directory entry */ dirptr += 2; dirrem -= 2; /* Process each directory entry */ while (dirrem > 0) { /* Point to next directory entry */ dirent = (PDSDIR*)dirptr; /* Test for end of directory */ if (memcmp(dirent->pds2name, eighthexFF, 8) == 0) return +1; /* Extract the member name */ make_asciiz (memname, sizeof(memname), dirent->pds2name, 8); /* Process the member */ rc = process_member (cif, noext, extent, memname, dirent->pds2ttrp); if (rc < 0) return -1; /* Load the user data halfword count */ k = dirent->pds2indc & PDS2INDC_LUSR; /* Point to next directory entry */ size = 12 + k*2; dirptr += size; dirrem -= size; } return 0; } /* end function process_dirblk */ /*-------------------------------------------------------------------*/ /* DASDPDSU main entry point */ /*-------------------------------------------------------------------*/ int main (int argc, char *argv[]) { int rc; /* Return code */ int i=0; /* Arument index */ int len; /* Record length */ int cyl; /* Cylinder number */ int head; /* Head number */ int rec; /* Record number */ int trk; /* Relative track number */ char *fname; /* -> CKD image file name */ char *sfname=NULL; /* -> CKD shadow file name */ char dsnama[45]; /* Dataset name (ASCIIZ) */ int noext; /* Number of extents */ DSXTENT extent[16]; /* Extent descriptor array */ BYTE *blkptr; /* -> PDS directory block */ BYTE dirblk[256]; /* Copy of directory block */ CIFBLK *cif; /* CKD image file descriptor */ INITIALIZE_UTILITY("dasdpdsu"); /* Display the program identification message */ display_version (stderr, "Hercules PDS unload program ", FALSE); /* Check the number of arguments */ if (argc < 3 || argc > 5) { fprintf (stderr, "Usage: %s ckdfile [sf=shadow-file-name] pdsname [ascii]\n", argv[0]); return -1; } /* The first argument is the name of the CKD image file */ fname = argv[1]; /* The next argument may be the shadow file name */ if (!memcmp (argv[2], "sf=", 3)) { sfname = argv[2]; i = 1; } /* The second argument is the dataset name */ memset (dsnama, 0, sizeof(dsnama)); strncpy (dsnama, argv[2|+i], sizeof(dsnama)-1); string_to_upper (dsnama); /* The third argument is an optional keyword */ if (argc > 3+i && argv[3+i] != NULL) { if (strcasecmp(argv[3+i], "ascii") == 0) asciiflag = 1; else { fprintf (stderr, "Keyword %s is not recognized\n", argv[3+i]); return -1; } } /* Open the CKD image file */ cif = open_ckd_image (fname, sfname, O_RDONLY|O_BINARY, 0); if (cif == NULL) return -1; /* Build the extent array for the requested dataset */ rc = build_extent_array (cif, dsnama, extent, &noext); if (rc < 0) return -1; #ifdef EXTERNALGUI /* Calculate ending relative track */ if (extgui) { int bcyl; /* Extent begin cylinder */ int btrk; /* Extent begin head */ int ecyl; /* Extent end cylinder */ int etrk; /* Extent end head */ int trks; /* total tracks in dataset */ int i; /* loop control */ for (i = 0, trks = 0; i < noext; i++) { bcyl = (extent[i].xtbcyl[0] << 8) | extent[i].xtbcyl[1]; btrk = (extent[i].xtbtrk[0] << 8) | extent[i].xtbtrk[1]; ecyl = (extent[i].xtecyl[0] << 8) | extent[i].xtecyl[1]; etrk = (extent[i].xtetrk[0] << 8) | extent[i].xtetrk[1]; trks += (((ecyl * cif->heads) + etrk) - ((bcyl * cif->heads) + btrk)) + 1; } fprintf(stderr,"ETRK=%d\n",trks-1); } #endif /*EXTERNALGUI*/ /* Point to the start of the directory */ trk = 0; rec = 1; /* Read the directory */ while (1) { #ifdef EXTERNALGUI if (extgui) fprintf(stderr,"CTRK=%d\n",trk); #endif /*EXTERNALGUI*/ /* Convert relative track to cylinder and head */ rc = convert_tt (trk, noext, extent, cif->heads, &cyl, &head); if (rc < 0) return -1; /* Read a directory block */ fprintf (stderr, "Reading directory block at cyl %d head %d rec %d\n", cyl, head, rec); rc = read_block (cif, cyl, head, rec, NULL, NULL, &blkptr, &len); if (rc < 0) return -1; /* Move to next track if block not found */ if (rc > 0) { trk++; rec = 1; continue; } /* Exit at end of directory */ if (len == 0) break; /* Copy the directory block */ memcpy (dirblk, blkptr, sizeof(dirblk)); /* Process each member in the directory block */ rc = process_dirblk (cif, noext, extent, dirblk); if (rc < 0) return -1; if (rc > 0) break; /* Point to the next directory block */ rec++; } /* end while */ fprintf (stderr, "End of directory\n"); /* Close the CKD image file and exit */ rc = close_ckd_image (cif); return rc; } /* end function main */ hercules-3.07/dasdseq.c000644 000765 000765 00000141356 11335365456 016560 0ustar00jmaynardjmaynard000000 000000 /* Code borrowed from dasdpdsu Copyright 1999-2009 Roger Bowler */ /* Changes and additions Copyright 2001-2009, James M. Morrison */ // $Id: dasdseq.c 5608 2010-02-07 09:36:35Z fish $ /*-------------------------------------------------------------------*/ /* */ /* dasdseq */ /* */ /* This program retrieves a sequential (DSORG=PS) dataset from */ /* a Hercules CKD/CCKD volume. The input file is assumed to be */ /* encoded in the EBCDIC character set. */ /* */ /*-------------------------------------------------------------------*/ // We don't use some of the regular Hercules dasd routines because // we want the DSCB as read from dasd so we can check some of the // file attributes (such as DSORG, RECFM, LRECL). // Dasdseq now uses the same case for the output dataset as the // user specifies on the command line. Prior versions always // used upper case, which seems unnecessarily loud. #include "hstdinc.h" #include "hercules.h" typedef struct _DASD_VOL_LABEL { /* dasd cyl 0 trk 0 record 3 */ /* identifies volser, owner, and VTOC location */ /* recorded in EBCDIC; 80 bytes in length */ BYTE vollabi[3]; // c'VOL' BYTE volno; // volume label sequence # BYTE volserno[6]; // volume serial BYTE security; // security field, set to 0xc0 BYTE volvtoc[5]; // CCHHR of VTOC's F4DSCB BYTE resv1[21]; // reserved; should be left blank BYTE volowner[14]; // volume owner BYTE resv2[29]; // reserved; should be left blank } DASD_VOL_LABEL; #include "dasdblks.h" #ifndef MAX_EXTENTS // see getF3dscb for notes #define MAX_EXTENTS 123 // maximum supported dataset extents #endif typedef struct _DADSM { DASD_VOL_LABEL volrec; // volume label record FORMAT4_DSCB f4buf; // F4 DSCB DSXTENT f4ext; // VTOC extent info FORMAT3_DSCB f3buf; // F3 DSCB FORMAT1_DSCB f1buf; // F1 DSCB int f1numx; // # valid dataset extents DSXTENT f1ext[MAX_EXTENTS]; // dsn extent info } DADSM; //---------------------------------------------------------------------------------- // Globals //---------------------------------------------------------------------------------- int local_verbose = 0; // verbose setting int copy_verbose = 0; // verbose setting for copyfile char *din; // dasd image filename char *sfn; // shadow file parm int absvalid = 0; // 1 = -abs specified, use CCHH not dsn char *argdsn; // MVS dataset name int expert = 0; // enable -abs help int tran_ascii = 0; // 1 = ascii output #ifdef DEBUG int debug = 1; // enable debug code #else int debug = 0; // disable debug code #endif void sayext(int max, DSXTENT *extent) { int i; fprintf(stderr, " EXTENT --begin-- ---end---\n"); fprintf(stderr, "TYPE NUMBER CCCC HHHH CCCC HHHH\n"); for (i = 0; i < max; i++) { int bcyl = (extent[i].xtbcyl[0] << 8) | extent[i].xtbcyl[1]; int btrk = (extent[i].xtbtrk[0] << 8) | extent[i].xtbtrk[1]; int ecyl = (extent[i].xtecyl[0] << 8) | extent[i].xtecyl[1]; int etrk = (extent[i].xtetrk[0] << 8) | extent[i].xtetrk[1]; fprintf(stderr, " %2.2X %2.2X %4.4X %4.4X %4.4X %4.4X\n", extent[i].xttype, extent[i].xtseqn, bcyl, btrk, ecyl, etrk); } } /* sayext */ //---------------------------------------------------------------------------------- // Display selected F1 DSCB information //---------------------------------------------------------------------------------- void showf1( FILE *fmsg, FORMAT1_DSCB *f1dscb, DSXTENT extent[], int verbose) { int i, dsorg, lrecl, blksize, volseq, x, y, num_extents; char volser[sizeof(f1dscb->ds1dssn) + 1]; char dsn[sizeof(f1dscb->ds1dsnam) + 1]; char txtcredt[9]; // creation date char txtexpdt[9] = "(n/a)"; // expiration date char txtscr[20]; char txtsyscd[14]; char txtdsorg[5] = ""; // dsorg text char txtrecfm[5] = ""; // recfm text if (verbose > 2) { fprintf(fmsg, "showf1 F1 DSCB\n"); data_dump(f1dscb, sizeof(FORMAT1_DSCB)); } make_asciiz(dsn, sizeof(dsn), f1dscb->ds1dsnam, sizeof(f1dscb->ds1dsnam)); make_asciiz(volser, sizeof(volser), f1dscb->ds1dssn, sizeof(f1dscb->ds1dssn)); volseq = (f1dscb->ds1volsq[0] << 8) | (f1dscb->ds1volsq[1]); x = f1dscb->ds1credt[0] + 1900; y = (f1dscb->ds1credt[1] << 8) | f1dscb->ds1credt[2]; sprintf(txtcredt, "%4.4d", x); strcat(txtcredt, "."); sprintf(txtscr, "%3.3d", y); strcat(txtcredt, txtscr); if (f1dscb->ds1expdt[0] || f1dscb->ds1expdt[1] || f1dscb->ds1expdt[2]) { x = f1dscb->ds1expdt[0] + 1900; y = (f1dscb->ds1expdt[1] << 8) | f1dscb->ds1expdt[2]; sprintf(txtexpdt, "%4.4d", x); strcat(txtexpdt, "."); sprintf(txtscr, ".%3.3d", y); strcat(txtexpdt, txtscr); } num_extents = f1dscb->ds1noepv; // Field ignored: ds1nobdb (# bytes used in last PDS dir blk) make_asciiz(txtsyscd, sizeof(txtsyscd), f1dscb->ds1syscd, sizeof(f1dscb->ds1syscd)); dsorg = (f1dscb->ds1dsorg[0] << 8) | (f1dscb->ds1dsorg[1]); if (dsorg & (DSORG_IS * 256)) strcpy(txtdsorg, "IS"); if (dsorg & (DSORG_PS * 256)) strcpy(txtdsorg, "PS"); if (dsorg & (DSORG_DA * 256)) strcpy(txtdsorg, "DA"); if (dsorg & (DSORG_PO * 256)) strcpy(txtdsorg, "PO"); if (dsorg & DSORG_AM) strcpy(txtdsorg, "VS"); if (txtdsorg[0] == '\0') strcpy(txtdsorg, "??"); if (dsorg & (DSORG_U * 256)) strcat(txtdsorg, "U"); if (f1dscb->ds1recfm & RECFM_FORMAT_F) strcpy(txtrecfm, "F"); if (f1dscb->ds1recfm & RECFM_FORMAT_V) strcpy(txtrecfm, "V"); if ((f1dscb->ds1recfm & RECFM_FORMAT_U) == RECFM_FORMAT_U) strcpy(txtrecfm, "U"); if (f1dscb->ds1recfm & RECFM_BLOCKED) strcat(txtrecfm, "B"); if (f1dscb->ds1recfm & RECFM_SPANNED) strcat(txtrecfm, "S"); if (f1dscb->ds1recfm & RECFM_CTLCHAR_A) strcat(txtrecfm, "A"); if (f1dscb->ds1recfm & RECFM_CTLCHAR_M) strcat(txtrecfm, "M"); if (f1dscb->ds1recfm & RECFM_TRKOFLOW) strcat(txtrecfm, "T"); // Field ignored: ds1optcd (option codes, same as in DCB) blksize = (f1dscb->ds1blkl[0] << 8) | f1dscb->ds1blkl[1]; lrecl = (f1dscb->ds1lrecl[0] << 8) | f1dscb->ds1lrecl[1]; // Field ignored: ds1keyl (key length) // Field ignored: ds1rkp (relative key position) // Field ignored: ds1dsind (data set indicators) // Field ignored: ds1scalo (secondary allocation) // Field ignored: ds1lstar (pointer to last written block; ttr) // Field ignored: ds1trbal (bytes remaining on last track used) // Extent information was passed to us, so we ignore what's in F1DSCB fprintf(fmsg, "Dataset %s on volume %s sequence %d\n", dsn, volser, volseq); fprintf(fmsg, "Created %s expires %s\n", txtcredt, txtexpdt); fprintf(fmsg, "Dsorg=%s recfm=%s lrecl=%d blksize=%d\n", txtdsorg, txtrecfm, lrecl, blksize); fprintf(fmsg, "System code %s\n", txtsyscd); if (verbose > 1) { fprintf(stderr, "Dataset has %d extent(s)\n", num_extents); if (verbose > 2) data_dump((void *)extent, sizeof(extent) * MAX_EXTENTS); fprintf(stderr, "Extent Information:\n"); fprintf(stderr, " EXTENT --begin-- ---end---\n"); fprintf(stderr, "TYPE NUMBER CCCC HHHH CCCC HHHH\n"); for (i = 0; i < num_extents; i++) { int bcyl = (extent[i].xtbcyl[0] << 8) | extent[i].xtbcyl[1]; int btrk = (extent[i].xtbtrk[0] << 8) | extent[i].xtbtrk[1]; int ecyl = (extent[i].xtecyl[0] << 8) | extent[i].xtecyl[1]; int etrk = (extent[i].xtetrk[0] << 8) | extent[i].xtetrk[1]; fprintf(stderr, " %2.2X %2.2X %4.4X %4.4X %4.4X %4.4X\n", extent[i].xttype, extent[i].xtseqn, bcyl, btrk, ecyl, etrk); } } return; } /* showf1 */ //---------------------------------------------------------------------------------- // Copy DSORG=PS RECFM=F[B] dataset to output file // // Input: // fout FILE * (opened "w" for ascii, "wb" for ebcdic) // cif dasdutil control block // f1dscb F1 DSCB // extent dataset extent array // tran 0 = ebcdic output, 1 = ascii output // ascii output will have trailing blanks removed // verbose 0 = no status messages // 1 = status messages // > 1 debugging messages // > 2 dump read record // > 3 dump written record // > 4 dump read record from input buffer // Output: // File written, messages displayed on stderr // Returns -1 on error, else returns # records written // Notes: // Caller is responsible for opening and closing fout. // // The F1 DSCB's DS1LSTAR field is used to determine EOF (absent a prior // EOF being encountered), since some datasets don't have an EOF marker // present. On my MVSRES, for instance, SYS1.BRODCAST has no EOF marker. // // 2003-01-14 jmm DS1LSTAR may be zero; if so, ignore DS1LSTAR and // hope for valid EOF. //---------------------------------------------------------------------------------- int fbcopy( FILE *fout, CIFBLK *cif, DADSM *dadsm, int tran, int verbose) { FORMAT1_DSCB *f1dscb = &dadsm->f1buf; DSXTENT extent[MAX_EXTENTS]; int rc, trk = 0, trkconv = 999, rec = 1; int cyl = 0, head = 0, rc_rb, len, offset; int rc_copy = 0; int recs_written = 0, lrecl, num_extents; int lstartrack = 0, lstarrec = 0, lstarvalid = 0; BYTE *buffer; char *pascii = NULL; char zdsn[sizeof(f1dscb->ds1dsnam) + 1]; // ascii dsn // Kludge to avoid rewriting this code (for now): memcpy(&extent, (void *)&(dadsm->f1ext), sizeof(extent)); num_extents = f1dscb->ds1noepv; lrecl = (f1dscb->ds1lrecl[0] << 8) | (f1dscb->ds1lrecl[1]); if (absvalid) { strcpy(zdsn, argdsn); if (debug) fprintf(stderr, "fbcopy absvalid\n"); } else { make_asciiz(zdsn, sizeof(zdsn), f1dscb->ds1dsnam, sizeof(f1dscb->ds1dsnam)); if ((f1dscb->ds1lstar[0] !=0) || (f1dscb->ds1lstar[1] != 0) || (f1dscb->ds1lstar[2] != 0)) { lstartrack = (f1dscb->ds1lstar[0] << 8) | (f1dscb->ds1lstar[1]); lstarrec = f1dscb->ds1lstar[2]; lstarvalid = 1; // DS1LSTAR valid } } if (debug) { fprintf(stderr, "fbcopy zdsn %s\n", zdsn); fprintf(stderr, "fbcopy num_extents %d\n", num_extents); fprintf(stderr, "fbcopy lrecl %d\n", lrecl); fprintf(stderr, "fbcopy F1 DSCB\n"); data_dump(f1dscb, sizeof(FORMAT1_DSCB)); sayext(num_extents, (void *)&extent); } if (verbose) // DS1LSTAR = last block written TTR fprintf(stderr, "fbcopy DS1LSTAR %2.2X%2.2X%2.2X lstartrack %d " "lstarrec %d lstarvalid %d\n", f1dscb->ds1lstar[0], f1dscb->ds1lstar[1], f1dscb->ds1lstar[2], lstartrack, lstarrec, lstarvalid); if (tran) { // need ASCII translation buffer? pascii = malloc(lrecl + 1); if (pascii == NULL) { fprintf(stderr, "fbcopy unable to allocate ascii buffer\n"); return -1; } } while (1) { // output records until something stops us // Honor DS1LSTAR when valid if ((lstarvalid) && (trk == lstartrack) && (rec > lstarrec)) { if (verbose) fprintf(stderr, "fbcopy DS1LSTAR indicates EOF\n" "fbcopy DS1LSTAR %2.2X%2.2X%2.2X " "track %d record %d\n", f1dscb->ds1lstar[0], f1dscb->ds1lstar[1], f1dscb->ds1lstar[2], trk, rec); rc_copy = recs_written; break; } // Convert TT to CCHH for upcoming read_block call if (trkconv != trk) { // avoid converting for each block trkconv = trk; // current track converted rc = convert_tt(trk, num_extents, extent, cif->heads, &cyl, &head); if (rc < 0) { fprintf(stderr, "fbcopy convert_tt track %5.5d, rc %d\n", trk, rc); if (absvalid) rc_copy = recs_written; else rc_copy = -1; break; } if (verbose > 1) fprintf(stderr, "fbcopy convert TT %5.5d CCHH %4.4X %4.4X\n", trk, cyl, head); } // Read block from dasd if (verbose > 2) fprintf(stderr, "fbcopy reading track %d " "record %d CCHHR = %4.4X %4.4X %2.2X\n", trk, rec, cyl, head, rec); rc_rb = read_block(cif, cyl, head, rec, NULL, NULL, &buffer, &len); if (rc_rb < 0) { // error fprintf(stderr, "fbcopy error reading %s, rc %d\n", zdsn, rc_rb); rc_copy = -1; break; } // Handle end of track return from read_block if (rc_rb > 0) { // end of track if (verbose > 2) fprintf(stderr, "fbcopy End Of Track %d rec %d\n", trk, rec); trk++; // next track rec = 1; // record 1 on new track continue; } // Check for dataset EOF if (len == 0) { // EOF if (verbose) fprintf(stderr, "fbcopy EOF track %5.5d rec %d\n", trk, rec); if (absvalid) { // capture as much -abs data as possible if (verbose) fprintf(stderr, "fbcopy ignoring -abs EOF\n"); } else { rc_copy = recs_written; break; } } if (verbose > 3) fprintf(stderr, "fbcopy read %d bytes\n", len); if (verbose > 2) { data_dump(buffer, len); fprintf(stderr, "\n"); } // Deblock input dasd block, write records to output dataset for (offset = 0; offset < len; offset += lrecl) { if (verbose > 3) { fprintf(stderr, "fbcopy offset %d length %d rec %d\n", offset, lrecl, recs_written); } if (tran) { // ASCII output memset(pascii, 0, lrecl + 1); make_asciiz(pascii, lrecl + 1, buffer + offset, lrecl); if (verbose > 4) { fprintf(stderr, "fbcopy buffer offset %d rec %d\n", offset, rec); data_dump(buffer + offset, lrecl); } if (verbose > 3) { fprintf(stderr, "->%s<-\n", pascii); data_dump(pascii, lrecl); } fprintf(fout, "%s\n", pascii); } else { // EBCDIC output if (verbose > 3) { fprintf(stderr, "fbcopy EBCDIC buffer\n"); data_dump(buffer + offset, lrecl); } fwrite(buffer + offset, lrecl, 1, fout); } if (ferror(fout)) { fprintf(stderr, "fbcopy error writing %s\n", zdsn); fprintf(stderr, "%s\n", strerror(errno)); rc_copy = -1; } recs_written++; } if (rc_copy != 0) break; else rec++; // next record on track } /* while (1) */ if (pascii) free(pascii); // release ASCII conversion buffer return rc_copy; } /* fbcopy */ //---------------------------------------------------------------------------------- // Given extent information, place it into appropriate extent table entry //---------------------------------------------------------------------------------- void makext( int i, // extent # int heads, // # heads per cylinder on device DSXTENT *extent, // extent table entry int startcyl, // start cylinder int starttrk, // start track int size) { // extent size in tracks int endcyl = ((startcyl * heads) + starttrk + size - 1) / heads; int endtrk = ((startcyl * heads) + starttrk + size - 1) % heads; if (i > (MAX_EXTENTS - 1)) { fprintf(stderr, "makext extent # parm invalid %d, abort\n", i); exit(4); } extent[i].xttype = 1; // extent type extent[i].xtseqn = i; // extent # (relative zero) extent[i].xtbcyl[0] = startcyl >> 8; // begin cyl extent[i].xtbcyl[1] = startcyl - ((startcyl / 256) * 256); extent[i].xtbtrk[0] = starttrk >> 8; extent[i].xtbtrk[1] = starttrk - ((starttrk / 256) * 256); extent[i].xtecyl[0] = endcyl >> 8; // end cyl extent[i].xtecyl[1] = endcyl - ((endcyl / 256) * 256); extent[i].xtetrk[0] = endtrk >> 8; extent[i].xtetrk[1] = endtrk - ((endtrk / 256) * 256); // end track return; } /* makext */ //---------------------------------------------------------------------------------- // showhelp - display syntax help //---------------------------------------------------------------------------------- void showhelp() { fprintf(stderr, (expert) ? "Usage: dasdseq [-debug] [-expert] [-ascii] image [sf=shadow] [attr] filespec\n" " -debug optional - Enables debug mode, additional debug help appears\n" : "Usage: dasdseq [-expert] [-ascii] image [sf=shadow] filespec\n"); fprintf(stderr, " -expert optional - Additional help describes expert operands\n" " -ascii optional - translate output file to ascii, trim trailing blanks\n" " image required - [path/]filename of dasd image file (dasd volume)\n" " shadow optional - [path/]filename of shadow file (note sf=)\n"); if (expert) fprintf(stderr, " ALL EXPERT FACILITIES ARE EXPERIMENTAL\n" " attr optional - dataset attributes (only useful with -abs)\n" " attr syntax: [-recfm fb] [-lrecl aa]\n" " -recfm designates RECFM, reserved for future support\n" " fb - fixed, blocked (only RECFM currently supported)\n" " -lrecl designates dataset LRECL\n" " aa - decimal logical record length (default 80)\n" " Blocksize need not be specified; dasdseq handles whatever\n" " block size comes off the volume.\n" " filespec required (optional sub-operands in the following order):\n" " [-heads xx]\n" " [-abs cc hh tt] [...] [-abs cc hh tt ]\n" " filename\n" " When -abs is -not- specified,\n" " Filename specifies the MVS DSORG=PS dataset on the volume.\n" " The dasd image volume containing the dataset must have a valid VTOC\n" " structure, and a F1 DSCB describing the dataset.\n" " Specifying -debug will (eventually) display extent information.\n" " When -abs is specified, each -abs group specifies one dataset extent.\n" " For multi-extent datasets, -abs groups may be repeated as needed,\n" " in the order in which the dataset's extents occur.\n" " A maximum of %d extents are supported.\n" " No VTOC structure is implied, a F1 DSCB will not be sought.\n" " Dasdseq will frequently report 'track not found in extent table'\n" " (along with a message from fbcopy about rc -1 from convert_tt)\n" " due to potentially missing EOF markers in the extent, and the\n" " fact that the F1 DSCB DS1LSTAR field is not valid.\n" " Check your output file before you panic.\n" " Fbcopy ignores EOF, in case you are attempting to recovery PDS\n" " member(s) from a damaged dasd volume, preferring to wait until\n" " all tracks in the extent have been processed.\n" " Tracks containing PDS members may have more than one EOF per track.\n" " Expect a lot of associated manual effort with -abs.\n" " -heads defines # tracks per cylinder on device;\n" " xx - decimal number of heads per cylinder on device\n" " default xx = 15 (valid for 3380s, 3390s)\n" " -abs indicates the beginning of each extent's location in terms of\n" " absolute dasd image location.\n" " cc - decimal cylinder number (relative zero)\n" " hh - decimal head number (relative zero)\n" " tt - decimal number of tracks in extent\n" " filename will be the filename of the output file in the current directory;\n" " output filename in the same case as the command line filename.\n", MAX_EXTENTS); else fprintf(stderr, " filespec required - MVS dataset name of DSORG=PS dataset, output filename\n"); if (debug) fprintf(stderr, "\n" "Debugging options (at end of dasdseq command)\n" " [verbose [x [y [z]]]]\n\n" " verbose debug output level (default = 0 when not specified)\n" " x main program (default = 1 when verbose specified)\n" " y copyfile + showf1\n" " z dasdutil\n" " Higher numbers produces more output\n"); return; } /* showhelp */ //---------------------------------------------------------------------------------- // parsecmd - parse command line; results stored in program globals //---------------------------------------------------------------------------------- int parsecmd(int argc, char **argv, DADSM *dadsm) { int util_verbose = 0; // Hercules dasdutil.c diagnostic level int heads = 15; // # heads per cylinder on device int extnum = 0; // extent number for makext() int abscyl = 0; // absolute CC (default 0) int abshead = 0; // absolute HH (default 0) int abstrk = 1; // absolute tracks (default 1) int lrecl = 80; // default F1 DSCB lrecl // Usage: dasdseq [-debug] [-expert] [-ascii] image [sf=shadow] [attr] filespec argv++; // skip dasdseq command argv[0] if ((*argv) && (strcasecmp(*argv, "-debug") == 0)) { argv++; debug = 1; fprintf(stderr, "Command line DEBUG specified\n"); } if ((*argv) && (strcasecmp(*argv, "-expert") == 0)) { argv++; expert = 1; if (debug) fprintf(stderr, "EXPERT mode\n"); } if ((*argv) && (strcasecmp(*argv, "-ascii") == 0)) { argv++; tran_ascii = 1; if (debug) fprintf(stderr, "ASCII translation enabled\n"); } if (*argv) din = *argv++; // dasd image filename if (debug) fprintf(stderr, "IMAGE %s\n", din); if (*argv && strlen(*argv) > 3 && !memcmp(*argv, "sf=", 3)) { sfn = *argv++; // shadow file parm } else sfn = NULL; if (debug) fprintf(stderr, "SHADOW %s\n", sfn); dadsm->f1buf.ds1recfm = RECFM_FORMAT_F | RECFM_BLOCKED; // recfm FB for fbcopy if ((*argv) && (strcasecmp(*argv, "-recfm") == 0)) { argv++; // skip -recfm if ((*argv) && (strcasecmp(*argv, "fb") == 0)) { argv++; // skip fb if (debug) fprintf(stderr, "RECFM fb\n"); } else { argv++; // skip bad recfm fprintf(stderr, "Unsupported -recfm value %s\n", *argv); } } if ((*argv) && (strcasecmp(*argv, "-lrecl") == 0)) { argv++; // skip -lrecl if (*argv) lrecl = atoi(*argv++); // lrecl value if (debug) fprintf(stderr, "LRECL %d\n", lrecl); } dadsm->f1buf.ds1lrecl[0] = lrecl >> 8; // for fbcopy dadsm->f1buf.ds1lrecl[1] = lrecl - ((lrecl >> 8) << 8); if ((*argv) && (strcasecmp(*argv, "-heads") == 0)) { argv++; // skip -heads if (*argv) heads = atoi(*argv++); // heads value } if (debug) fprintf(stderr, "HEADS %d\n", heads); if ((*argv) && (strcasecmp(*argv, "-abs") == 0)) { absvalid = 1; // CCHH valid while ((*argv) && (strcasecmp(*argv, "-abs") == 0)) { argv++; // skip -abs abscyl = 0; abshead = 0; abstrk = 1; // defaults if (*argv) abscyl = atoi(*argv++); // abs cc if (*argv) abshead = atoi(*argv++); // abs hh if (*argv) abstrk = atoi(*argv++); // abs tracks // Build extent entry for -abs group makext(extnum, heads, (DSXTENT *) &dadsm->f1ext, abscyl, abshead, abstrk); extnum++; dadsm->f1buf.ds1noepv = extnum; // for fbcopy if (debug) fprintf(stderr, "Absolute CC %d HH %d tracks %d\n", abscyl, abshead, abstrk); if (extnum > MAX_EXTENTS) { fprintf(stderr, "Too many extents, abort\n"); exit(3); } } // if (debug) sayext(MAX_EXTENTS, dadsm->f1ext);// show extent table } if (debug) { fprintf(stderr, "parsecmd completed F1 DSCB\n"); data_dump(&dadsm->f1buf, sizeof(FORMAT1_DSCB)); } if (*argv) argdsn = *argv++; // [MVS dataset name/]output filename if (debug) fprintf(stderr, "DSN %s\n", argdsn); if ((*argv) && ( // support deprecated 'ascii' operand (strcasecmp(*argv, "ascii") == 0) || (strcasecmp(*argv, "-ascii") == 0) ) ) { argv++; tran_ascii = 1; if (debug) fprintf(stderr, "ASCII translation enabled\n"); } set_verbose_util(0); // default util verbosity if ((*argv) && (strcasecmp(*argv, "verbose") == 0)) { local_verbose = 1; argv++; if (*argv) local_verbose = atoi(*argv++); if (*argv) copy_verbose = atoi(*argv++); if (*argv) { util_verbose = atoi(*argv++); set_verbose_util(util_verbose); if (debug) fprintf(stderr, "Utility verbose %d\n", util_verbose); } } // If the user specified expert mode without -abs, give help & exit // Additionally, if the user has "extra" parms, show help & exit // No "extraneous parms" message is issued, since some of the code // above forces *argv to be true when it wants help displayed if ((argc < 3) || (*argv) || ((expert) && (!absvalid))) { showhelp(); // show syntax before bailing exit(2); } return 0; } /* parsecmd */ //---------------------------------------------------------------------------------- // getlabel - retrieve label record from dasd volume image //---------------------------------------------------------------------------------- // // Input: // cif ptr to opened CIFBLK of dasd image // glbuf ptr to 80 byte buffer provided by caller // verbose 0 = no status messages // 1 = status messages // > 1 debugging messages // // Output: // glbuf dasd volume label record // // Returns: 0 OK, else error // // Notes: // The volume label record always resides at CCHHR 0000 0000 03. // The dasd volume label record contains the CCHHR of the VTOC. // The volume label record is copied to the caller's buffer. //---------------------------------------------------------------------------------- int getlabel( CIFBLK *cif, DASD_VOL_LABEL *glbuf, int verbose) { int len, rc; void *plabel; if (verbose) fprintf(stderr, "getlabel reading volume label\n"); rc = read_block(cif, 0, 0, 3, NULL, NULL, (void *) &plabel, &len); if (rc) { fprintf(stderr, "getlabel error reading volume label, rc %d\n", rc); return 1; } if (len != sizeof(DASD_VOL_LABEL)) { fprintf(stderr, "getlabel error: volume label %d, not 80 bytes long\n", len); return 2; } memcpy((void *)glbuf, plabel, sizeof(DASD_VOL_LABEL)); if (verbose > 1) { fprintf(stderr, "getlabel volume label\n"); data_dump(glbuf, len); } return 0; } /* getlabel */ //---------------------------------------------------------------------------------- // getF4dscb - retrieve Format 4 DSCB - VTOC self-descriptor record //---------------------------------------------------------------------------------- // // Input: // cif ptr to opened CIFBLK of dasd image containing dataset // f4dscb ptr to F4 DSCB buffer (key & data) // volrec ptr to buffer containing volume label rec // vtocx ptr to VTOC extent array (one extent only) // verbose 0 = no status messages // 1 = status messages // > 1 debugging messages // // Output: // f4buf F4 DSCB in buffer (44 byte key, 96 bytes of data) // vtocx VTOC extent array updated // // Returns: 0 OK, else error // // Notes: // There should only be one F4 DSCB in the VTOC, and it should always be // the first record in the VTOC. The F4 provides VTOC extent information, // anchors free space DSCBs, and provides information about the device on // which the VTOC resides. //---------------------------------------------------------------------------------- int getF4dscb( CIFBLK *cif, FORMAT4_DSCB *f4dscb, DASD_VOL_LABEL *volrec, DSXTENT *vtocx, int verbose) { char vtockey[sizeof(f4dscb->ds4keyid)]; void *f4key, *f4data; int f4kl, f4dl; int cyl, head, rec, rc; // Extract VTOC's CCHHR from volume label cyl = (volrec->volvtoc[0] << 8) | volrec->volvtoc[1]; head = (volrec->volvtoc[2] << 8) | volrec->volvtoc[3]; rec = volrec->volvtoc[4]; if (verbose > 1) fprintf(stderr, "getF4dscb VTOC F4 at cyl %d head %d rec %d\n", cyl, head, rec); // Read VTOC's Format 4 DSCB (VTOC self-descriptor) if (verbose) fprintf(stderr, "getF4dscb reading VTOC F4 DSCB\n"); rc = read_block(cif, cyl, head, rec, (void *) &f4key, &f4kl, (void *) &f4data, &f4dl); if (rc) { fprintf(stderr, "getF4dscb error reading F4 DSCB, rc %d\n", rc); return 1; } // Verify correct key and data length if ((f4kl != sizeof(f4dscb->ds4keyid)) || (f4dl != (sizeof(FORMAT4_DSCB) - sizeof(f4dscb->ds4keyid)))) { fprintf(stderr, "getF4dscb erroneous key length %d or data length %d\n", f4kl, f4dl); return 2; } // Return data to caller memcpy((void *) &f4dscb->ds4keyid, f4key, f4kl); // copy F4 key into buffer memcpy((void *) &f4dscb->ds4fmtid, f4data, f4dl); // copy F4 data into buffer memcpy((void *) vtocx, (void *)&f4dscb->ds4vtoce, sizeof(f4dscb->ds4vtoce)); // copy VTOC extent entry if (verbose > 1) { fprintf(stderr, "getF4dscb F4 DSCB\n"); data_dump((void *) f4dscb, sizeof(FORMAT4_DSCB)); } // Verify DS4FMTID byte = x'F4', DS4KEYID key = x'04', and DS4NOEXT = x'01' // Do this after copying data to caller's buffer so we can use struct fields // rather than having to calculate offset to verified data; little harm done // if it doesn't verify since we're toast if they're bad. memset(vtockey, 0x04, sizeof(vtockey)); if ((f4dscb->ds4fmtid != 0xf4) || (f4dscb->ds4noext != 0x01) || (memcmp(&f4dscb->ds4keyid, vtockey, sizeof(vtockey)))) { fprintf(stderr, "getF4dscb " "VTOC format id byte invalid (DS4IDFMT) %2.2X, \n" "VTOC key invalid, or multi-extent VTOC\n", f4dscb->ds4fmtid); return 3; } // Display VTOC extent info (always one extent, never more) if (verbose > 1) { fprintf (stderr, "getF4dscb " "VTOC start CCHH=%2.2X%2.2X %2.2X%2.2X " "end CCHH=%2.2X%2.2X %2.2X%2.2X\n", vtocx->xtbcyl[0], vtocx->xtbcyl[1], vtocx->xtbtrk[0], vtocx->xtbtrk[1], vtocx->xtecyl[0], vtocx->xtecyl[1], vtocx->xtetrk[0], vtocx->xtetrk[1]); } return 0; } /* getF4dscb */ //---------------------------------------------------------------------------------- // getF1dscb - retrieve Format 1 DSCB //---------------------------------------------------------------------------------- // // Input: // cif ptr to opened CIFBLK of dasd image containing dataset // zdsn ASCII null-terminated dataset name // f1dscb ptr to F1 DSCB buffer (key & data) // vtocext ptr to VTOC's extent info // verbose 0 = no status messages // 1 = status messages // > 1 debugging messages // // Output: // f1buf F1 DSCB (44 byte key, 96 byte data) // // Returns: 0 OK, else error // // Notes: The F1 DSCB describes the MVS dataset's physical and logical attributes // such as RECFM, LRECL, BLKSIZE, and where on the volume the dataset // resides (the extent information). The first 3 possible extents are // described in the F1 DSCB. If additional extents are allocated, they // are described by F3 DSCBs referred to by the F1 DSCB. //---------------------------------------------------------------------------------- int getF1dscb( CIFBLK *cif, char *pdsn[], FORMAT1_DSCB *f1dscb, DSXTENT *vtocext[], int verbose) { char zdsn[sizeof(f1dscb->ds1dsnam) + 1]; // zASCII dsn BYTE edsn[sizeof(f1dscb->ds1dsnam)]; // EBCDIC dsn void *f1key, *f1data; int f1kl, f1dl; int cyl, head, rec, rc; int vtocextents = 1; // VTOC has only one extent // Locate dataset's F1 DSCB memset(zdsn, 0, sizeof(zdsn)); strncpy(zdsn, *pdsn, sizeof(zdsn) - 1); string_to_upper(zdsn); convert_to_ebcdic(edsn, sizeof(edsn), zdsn); if (verbose) fprintf(stderr, "getF1dscb searching VTOC for %s\n", zdsn); rc = search_key_equal(cif, edsn, sizeof(edsn), vtocextents, (DSXTENT *)vtocext, &cyl, &head, &rec); if (rc) { fprintf(stderr, "getF1dscb search_key_equal rc %d\n", rc); if (verbose) { fprintf(stderr, "getF1dscb key\n"); data_dump(edsn, sizeof(edsn)); } if (rc == 1) fprintf(stderr, "getF1dscb no DSCB found for %s\n", zdsn); return 1; } // Read F1 DSCB describing dataset if (verbose) fprintf(stderr, "getF1dscb reading F1 DSCB\n"); rc = read_block(cif, cyl, head, rec, (void *)&f1key, &f1kl, (void *) &f1data, &f1dl); if (rc) { fprintf(stderr, "getF1dscb error reading F1 DSCB, rc %d\n", rc); return 2; } // Return data to caller if ((f1kl == sizeof(f1dscb->ds1dsnam)) && (f1dl == (sizeof(FORMAT1_DSCB) - sizeof(f1dscb->ds1dsnam)))) { memcpy((void *) &f1dscb->ds1dsnam, f1key, f1kl); // copy F1 key to buffer memcpy((void *) &f1dscb->ds1fmtid, f1data, f1dl); // copy F1 data to buffer } else { fprintf(stderr, "getF1dscb bad key %d or data length %d\n", f1kl, f1dl); return 3; } if (verbose > 1) { fprintf(stderr, "getF1dscb F1 DSCB\n"); data_dump((void *) f1dscb, sizeof(FORMAT1_DSCB)); } // Verify DS1FMTID byte = x'F1' // Do this after copying data to caller's buffer so we can use struct fields // rather than having to calculate offset to verified data; little harm done // if it doesn't verify since we're toast if it's bad. if (f1dscb->ds1fmtid != 0xf1) { fprintf(stderr, "getF1dscb " "F1 DSCB format id byte invalid (DS1IDFMT) %2.2X\n", f1dscb->ds1fmtid); return 4; } return 0; } /* getF1dscb */ //---------------------------------------------------------------------------------- // getF3dscb - Retrieve Format 3 DSCB //---------------------------------------------------------------------------------- // // Input: // cif ptr to opened CIFBLK of dasd image containing dataset // f3cchhr CCHHR of F3 DSCB to be read (key & data) // f3dscb ptr to F3 DSCB buffer // verbose 0 = no status messages // 1 = status messages // > 1 debugging messages // // Output: // f3buf F3 DSCB (44 byte key, 96 byte data) // // Returns: 0 OK, else error // // Notes: The F3 DSCB describes additional dataset extents beyond those // described by the F1 DSCB. Each F3 DSCB describes 13 extents. // Physical sequential datasets are limited to 16 extents on each // volume, extended format datasets are limited to 123 extents on // each volume. Dasdseq doesn't provide explicit support for // multi-volume datasets. // // Note there is extent information embedded in the key. // // If you want support for > 16 extents, you will have to recompile // dasdseq after changing MAX_EXTENTS. // // Warning: I haven't tested the "chase the F3 chain" code, as I have no // reasonable way to do so. The highest level of MVS I can run under // Hercules is MVS38j. //---------------------------------------------------------------------------------- int getF3dscb( CIFBLK *cif, BYTE *f3cchhr, FORMAT3_DSCB *f3dscb, int verbose) { int cyl, head, rec, rc; void *f3key, *f3data; int f3kl, f3dl; cyl = (f3cchhr[0] << 8) | f3cchhr[1]; head = (f3cchhr[2] << 8) | f3cchhr[3]; rec = f3cchhr[4]; if (verbose) fprintf(stderr, "getF3dscb reading F3 DSCB " "cyl %d head %d rec %d\n", cyl, head, rec); rc = read_block (cif, cyl, head, rec, (void *)&f3key, &f3kl, (void *)&f3data, &f3dl); if (rc) { fprintf(stderr, "getF3dscb error reading F3 DSCB, rc %d\n", rc); return 1; } if ((f3kl != 44) || (f3dl != 96)) { fprintf(stderr, "getF3dscb bad key %d or data %d length\n", f3kl, f3dl); return 2; } memcpy((void *) &f3dscb->ds3keyid, f3key, f3kl); // copy F3 key to buffer memcpy((void *) ((BYTE*)f3dscb + f3kl), f3data, f3dl); // copy F3 data to buffer if (verbose > 1) { fprintf(stderr, "getF3dscb F3 DSCB\n"); data_dump((void *) f3dscb, sizeof(FORMAT3_DSCB)); } // Verify DS3FMTID byte = x'F3' // Do this after copying data to caller's buffer so we can use struct fields // rather than having to calculate offset to verified data; little harm done // if it doesn't verify since we're toast if it's bad. if (f3dscb->ds3fmtid != 0xf3) { fprintf(stderr, "getF3dscb " "F3 DSCB format id byte invalid (DS3IDFMT) %2.2X\n", f3dscb->ds3fmtid); return 2; } return 0; } /* getF3dscb */ //---------------------------------------------------------------------------------- // dadsm_setup - retrieve volume label & DSCBs sufficient to describe dataset //---------------------------------------------------------------------------------- // // This routine reads the volume label rec, the VTOC F4 DSCB, the F1 DSCB // for the dataset, and any F3 DSCB(s) associated with the dataset. // Constructs extent array describing space allocated to the dataset. // // Input: // cif ptr to opened CIFBLK of dasd image containing dataset // pdsn ptr to ASCII null-terminated dataset name // dadsm ptr to DADSM workarea // verbose 0 = no status messages // 1 = status messages // > 1 debugging messages // // Output: // dadsm DADSM workarea // // Returns: 0 OK, else error // // Notes: //---------------------------------------------------------------------------------- int dadsm_setup( CIFBLK *cif, char *pdsn[], DADSM *dadsm, int verbose) { DSXTENT *f1x; BYTE *pcchhr; int numx = MAX_EXTENTS; // # extent slots available int rc; // Read dasd volume label record rc = getlabel(cif, &dadsm->volrec, verbose); if (rc) return rc; // Read F4 DSCB, save VTOC extent info rc = getF4dscb(cif, &dadsm->f4buf, &dadsm->volrec, &dadsm->f4ext, verbose); if (rc) return rc; // Read F1 DSCB, save first three extents from F1 DSCB rc = getF1dscb(cif, pdsn, &dadsm->f1buf, (void *)&dadsm->f4ext, verbose); if (rc) return rc; f1x = &dadsm->f1ext[0]; // @ extent # 0 numx -= 3; // will use 3 slots (if available) if (numx < 0) { fprintf(stderr, "dadsm_setup exhausted extent slots\n"); return 1; } memcpy(f1x, &dadsm->f1buf.ds1ext1, sizeof(DSXTENT) * 3); f1x += 3; // @ extent # 3 dadsm->f1numx = dadsm->f1buf.ds1noepv; // # extents alloc'd to dataset if (dadsm->f1numx < 4) { if (verbose > 1) fprintf(stderr, "dadsm_setup " "no F3 DSCB required, only %d extent(s); all in F1\n", dadsm->f1numx); return 0; } // When more than 3 extents, get additional extent info from F3 DSCB(s). // Chase the F3 chain starting with the CCHHR in the F1, accumulating // extent information for the dataset as we progress. pcchhr = (BYTE *)&dadsm->f1buf.ds1ptrds; // @ F1 ptr to F3 while (pcchhr[0] || pcchhr[1] || pcchhr[2] || pcchhr[3] || pcchhr[4]) { rc = getF3dscb(cif, pcchhr, &dadsm->f3buf, verbose); if (rc) return rc; numx -= 4; // use extent slots if (numx < 0) { fprintf(stderr, "dadsm_setup exhausted extent slots\n"); return 2; } memcpy(f1x, &dadsm->f3buf.ds3extnt[0], sizeof(DSXTENT) * 4); f1x += 4; numx -= 9; // use extent slots if (numx < 0) { fprintf(stderr, "dadsm_setup exhausted extent slots\n"); fprintf(stderr, "Maximum supported extents %d\n", MAX_EXTENTS); return 3; } memcpy(f1x, &dadsm->f3buf.ds3adext[0], sizeof(DSXTENT) * 9); f1x += 9; pcchhr = (BYTE *)&dadsm->f3buf.ds3ptrds; // @ next F3 CCHHR } return 0; } /* dadsm_setup */ //---------------------------------------------------------------------------------- // Main //---------------------------------------------------------------------------------- int main(int argc, char **argv) { DADSM dadsm; // DADSM workarea FILE *fout = NULL; // output file CIFBLK *cif; int dsn_recs_written = 0, bail, dsorg, rc; char pathname[MAX_PATH]; fprintf(stderr, "dasdseq %s (C) Copyright 1999-2010 Roger Bowler\n" "Portions (C) Copyright 2001-2010 James M. Morrison\n", VERSION); if (debug) fprintf(stderr, "DEBUG enabled\n"); // Parse command line memset(&dadsm, 0, sizeof(dadsm)); // init DADSM workarea rc = parsecmd(argc, argv, &dadsm); if (rc) exit(rc); // Open CKD image cif = open_ckd_image(din, sfn, O_RDONLY | O_BINARY, 0); if (!cif) { fprintf(stderr, "dasdseq unable to open image file %s\n", din); exit(20); } // Unless -abs specified (in which case trust the expert user): // Retrieve extent information for the dataset // Display dataset attributes // Verify dataset has acceptable attributes if (!absvalid) { rc = dadsm_setup(cif, &argdsn, &dadsm, local_verbose); if (rc) { close_ckd_image(cif); exit(rc); } if (local_verbose) { fprintf(stderr, "\n"); showf1(stderr, &dadsm.f1buf, dadsm.f1ext, copy_verbose); fprintf(stderr, "\n"); } bail = 1; dsorg = (dadsm.f1buf.ds1dsorg[0] << 8) | (dadsm.f1buf.ds1dsorg[1]); if (dsorg & (DSORG_PS * 256)) { if ((dadsm.f1buf.ds1recfm & RECFM_FORMAT) == RECFM_FORMAT_F) bail = 0; if ((dadsm.f1buf.ds1recfm & RECFM_FORMAT) == RECFM_FORMAT_V) { bail = 1; // not yet fprintf(stderr, "dasdseq only supports RECFM=F[B]\n"); } } else fprintf(stderr, "dasdseq only supports DSORG=PS datasets\n"); if (bail) { close_ckd_image(cif); exit(21); } } // Open output dataset (EBCDIC requires binary open) hostpath(pathname, argdsn, sizeof(pathname)); fout = fopen(pathname, (tran_ascii) ? "wb" : "w"); if (fout == NULL) { fprintf(stderr, "dasdseq unable to open output file %s, %s\n", argdsn, strerror(errno)); close_ckd_image(cif); exit(22); } if (local_verbose) fprintf(stderr, "dasdseq writing %s\n", argdsn); // Write dasd data to output dataset dsn_recs_written = fbcopy(fout, cif, &dadsm, tran_ascii, copy_verbose); if (dsn_recs_written == -1) fprintf(stderr, "dasdseq error processing %s\n", argdsn); else fprintf(stderr, "dasdseq wrote %d records to %s\n", dsn_recs_written, argdsn); // Close output dataset, dasd image and return to caller fclose(fout); if (local_verbose > 2) fprintf(stderr, "CLOSED %s\n", argdsn); if (local_verbose > 3) { fprintf(stderr, "CIFBLK\n"); data_dump((void *) cif, sizeof(CIFBLK)); } close_ckd_image(cif); if (local_verbose > 2) fprintf(stderr, "CLOSED image\n"); return rc; } /* main */ hercules-3.07/dasdtab.c000644 000765 000765 00000063665 11301535255 016531 0ustar00jmaynardjmaynard000000 000000 /* DASDTAB.C (c) Copyright Roger Bowler, 1999-2009 */ /* Hercules Supported DASD definitions */ // $Id: dasdtab.c 5444 2009-08-09 16:36:42Z hsg001 $ /*-------------------------------------------------------------------*/ /* This module contains the tables that define the attributes of */ /* each DASD device and control unit supported by Hercules. */ /* Routines are also provided to perform table lookup and build the */ /* device identifier and characteristics areas. */ /* */ /* Note: source for most CKD/FBA device capacities take from SDI's */ /* device capacity page at: http://www.sdisw.com/dasd_capacity.html */ /* (used with permission) */ /*-------------------------------------------------------------------*/ // $Log$ // Revision 1.40 2008/11/02 21:45:07 rbowler // Correction to dasdtab entries for 3375 and 3380 // // Revision 1.39 2008/10/27 15:10:32 rbowler // Revert to 3990 as default control unit for 3390 devices // // Revision 1.38 2008/02/13 00:30:22 gsmith // Fix 3880 SNSID length (thanks De!) // // Revision 1.37 2007/06/23 00:04:08 ivan // Update copyright notices to include current year (2007) // // Revision 1.36 2007/06/20 04:09:54 gsmith // make 3990-6 default control unit for 3390 devices // // Revision 1.35 2007/06/07 19:15:05 kleonard // Document circumvention for DSF X'0A' command reject // // Revision 1.34 2007/05/04 19:28:38 kleonard // Circumvent command reject for DSF X'0A' command // // Revision 1.33 2007/03/06 22:54:19 gsmith // Fix ckd RDC response // // Revision 1.32 2007/02/15 00:10:04 gsmith // Fix ckd RCD, SNSS, SNSID responses // // Revision 1.31 2006/12/08 09:43:20 jj // Add CVS message log // #include "hstdinc.h" #define _DASDTAB_C_ #define _HDASD_DLL_ #include "hercules.h" /*-------------------------------------------------------------------*/ /* CKD device definitions */ /*-------------------------------------------------------------------*/ static CKDDEV ckdtab[] = { /* name type model clas code prime a hd r0 r1 har0 len sec rps f f1 f2 f3 f4 f5 f6 cu */ {"2305", 0x2305,0x00,0x20,0x00, 48,0, 8,14568,14136, 432,14568, 90,0x0000,-1,202,432, 0, 0, 0,0,"2835"}, {"2305-1", 0x2305,0x00,0x20,0x00, 48,0, 8,14568,14136, 432,14568, 90,0x0000,-1,202,432, 0, 0, 0,0,"2835"}, {"2305-2", 0x2305,0x02,0x20,0x00, 96,0, 8,14858,14660, 198,14858, 90,0x0000,-1, 91,198, 0, 0, 0,0,"2835"}, {"2311", 0x2311,0x00,0x20,0x00, 200,3,10, 0, 3625, 0, 3625, 0,0x0000,-2,20, 61, 537, 512, 0,0,"2841"}, {"2311-1", 0x2311,0x00,0x20,0x00, 200,3,10, 0, 3625, 0, 3625, 0,0x0000,-2,20, 61, 537, 512, 0,0,"2841"}, {"2314", 0x2314,0x00,0x20,0x00, 200,3,20, 0, 7294, 0, 7294, 0,0x0000,-2,45,101,2137,2048, 0,0,"2314"}, {"2314-1", 0x2314,0x00,0x20,0x00, 200,3,20, 0, 7294, 0, 7294, 0,0x0000,-2,45,101,2137,2048, 0,0,"2314"}, {"3330", 0x3330,0x01,0x20,0x00, 404,7,19,13165,13030, 135,13165,128,0x0000,-1,56,135, 0, 0, 0,0,"3830"}, {"3330-1", 0x3330,0x01,0x20,0x00, 404,7,19,13165,13030, 135,13165,128,0x0000,-1,56,135, 0, 0, 0,0,"3830"}, {"3330-2", 0x3330,0x11,0x20,0x00, 808,7,19,13165,13030, 135,13165,128,0x0000,-1,56,135, 0, 0, 0,0,"3830"}, {"3330-11", 0x3330,0x11,0x20,0x00, 808,7,19,13165,13030, 135,13165,128,0x0000,-1,56,135, 0, 0, 0,0,"3830"}, {"3340", 0x3340,0x01,0x20,0x00, 348,1,12, 8535, 8368, 167, 8535, 64,0x0000,-1,75,167, 0, 0, 0,0,"3830"}, {"3340-1", 0x3340,0x01,0x20,0x00, 348,1,12, 8535, 8368, 167, 8535, 64,0x0000,-1,75,167, 0, 0, 0,0,"3830"}, {"3340-35", 0x3340,0x01,0x20,0x00, 348,1,12, 8535, 8368, 167, 8535, 64,0x0000,-1,75,167, 0, 0, 0,0,"3830"}, {"3340-2", 0x3340,0x02,0x20,0x00, 696,2,12, 8535, 8368, 167, 8535, 64,0x0000,-1,75,167, 0, 0, 0,0,"3830"}, {"3340-70", 0x3340,0x02,0x20,0x00, 696,2,12, 8535, 8368, 167, 8535, 64,0x0000,-1,75,167, 0, 0, 0,0,"3830"}, {"3350", 0x3350,0x00,0x20,0x00, 555,5,30,19254,19069, 185,19254,128,0x0000,-1,82,185, 0, 0, 0,0,"3830"}, {"3350-1", 0x3350,0x00,0x20,0x00, 555,5,30,19254,19069, 185,19254,128,0x0000,-1,82,185, 0, 0, 0,0,"3830"}, /* name type model clas code prime a hd r0 r1 har0 len sec rps f f1 f2 f3 f4 f5 f6 cu */ {"3375", 0x3375,0x02,0x20,0x0e, 959,3,12,36000,35616, 832,36000,196,0x5007, 1, 32,384,160, 0, 0,0,"3880"}, {"3375-1", 0x3375,0x02,0x20,0x0e, 959,3,12,36000,35616, 832,36000,196,0x5007, 1, 32,384,160, 0, 0,0,"3880"}, {"3380", 0x3380,0x02,0x20,0x0e, 885,1,15,47988,47476,1088,47968,222,0x5007, 1, 32,492,236, 0, 0,0,"3880"}, {"3380-1", 0x3380,0x02,0x20,0x0e, 885,1,15,47988,47476,1088,47968,222,0x5007, 1, 32,492,236, 0, 0,0,"3880"}, {"3380-A", 0x3380,0x02,0x20,0x0e, 885,1,15,47988,47476,1088,47968,222,0x5007, 1, 32,492,236, 0, 0,0,"3880"}, {"3380-B", 0x3380,0x02,0x20,0x0e, 885,1,15,47988,47476,1088,47968,222,0x5007, 1, 32,492,236, 0, 0,0,"3880"}, {"3380-D", 0x3380,0x06,0x20,0x0e, 885,1,15,47988,47476,1088,47968,222,0x5007, 1, 32,492,236, 0, 0,0,"3880"}, {"3380-J", 0x3380,0x16,0x20,0x0e, 885,1,15,47988,47476,1088,47968,222,0x5007, 1, 32,492,236, 0, 0,0,"3880"}, {"3380-2", 0x3380,0x0a,0x20,0x0e, 1770,2,15,47988,47476,1088,47968,222,0x5007, 1, 32,492,236, 0, 0,0,"3880"}, {"3380-E", 0x3380,0x0a,0x20,0x0e, 1770,2,15,47988,47476,1088,47968,222,0x5007, 1, 32,492,236, 0, 0,0,"3880"}, {"3380-3", 0x3380,0x1e,0x20,0x0e, 2655,3,15,47988,47476,1088,47968,222,0x5007, 1, 32,492,236, 0, 0,0,"3880"}, {"3380-K", 0x3380,0x1e,0x20,0x0e, 2655,3,15,47988,47476,1088,47968,222,0x5007, 1, 32,492,236, 0, 0,0,"3880"}, {"EMC3380K+", 0x3380,0x1e,0x20,0x0e, 3339,3,15,47988,47476,1088,47968,222,0x5007, 1, 32,492,236, 0, 0,0,"3880"}, {"EMC3380K++",0x3380,0x1e,0x20,0x0e, 3993,3,15,47988,47476,1088,47968,222,0x5007, 1, 32,492,236, 0, 0,0,"3880"}, /* name type model clas code prime a hd r0 r1 har0 len sec rps f f1 f2 f3 f4 f5 f6 cu */ {"3390", 0x3390,0x02,0x20,0x26, 1113,1,15,57326,56664,1428,58786,224,0x7708, 2, 34,19, 9, 6,116,6,"3990"}, {"3390-1", 0x3390,0x02,0x20,0x26, 1113,1,15,57326,56664,1428,58786,224,0x7708, 2, 34,19, 9, 6,116,6,"3990"}, {"3390-2", 0x3390,0x06,0x20,0x27, 2226,1,15,57326,56664,1428,58786,224,0x7708, 2, 34,19, 9, 6,116,6,"3990"}, {"3390-3", 0x3390,0x0a,0x20,0x24, 3339,1,15,57326,56664,1428,58786,224,0x7708, 2, 34,19, 9, 6,116,6,"3990"}, {"3390-9", 0x3390,0x0c,0x20,0x32,10017,3,15,57326,56664,1428,58786,224,0x7708, 2, 34,19, 9, 6,116,6,"3990"}, {"3390-27", 0x3390,0x0c,0x20,0x32,32760,3,15,57326,56664,1428,58786,224,0x7708, 2, 34,19, 9, 6,116,6,"3990"}, {"3390-J", 0x3390,0x0c,0x20,0x32,32760,3,15,57326,56664,1428,58786,224,0x7708, 2, 34,19, 9, 6,116,6,"3990"}, {"3390-54", 0x3390,0x0c,0x20,0x32,65520,3,15,57326,56664,1428,58786,224,0x7708, 2, 34,19, 9, 6,116,6,"3990"}, {"3390-JJ", 0x3390,0x0c,0x20,0x32,65520,3,15,57326,56664,1428,58786,224,0x7708, 2, 34,19, 9, 6,116,6,"3990"}, {"9345", 0x9345,0x04,0x20,0x04, 1440,0,15,48174,46456,1184,48280,213,0x8b07, 2, 34,18, 7, 6,116,6,"9343"}, {"9345-1", 0x9345,0x04,0x20,0x04, 1440,0,15,48174,46456,1184,48280,213,0x8b07, 2, 34,18, 7, 6,116,6,"9343"}, {"9345-2", 0x9345,0x04,0x20,0x04, 2156,0,15,48174,46456,1184,48280,213,0x8b07, 2, 34,18, 7, 6,116,6,"9343"} /* name type model clas code prime a hd r0 r1 har0 len sec rps f f1 f2 f3 f4 f5 f6 cu */ } ; #define CKDDEV_NUM (sizeof(ckdtab)/CKDDEV_SIZE) /*-------------------------------------------------------------------*/ /* CKD control unit definitions */ /*-------------------------------------------------------------------*/ static CKDCU ckdcutab[] = { /* func/ type */ /* name type model code feat code features ciws --------- */ {"2314", 0x2314,0x00,0x00,0x00,0x00,0x50000103,0,0,0,0,0,0,0,0}, {"2835", 0x2835,0x00,0x00,0x00,0x00,0x50000103,0,0,0,0,0,0,0,0}, {"2841", 0x2841,0x00,0x00,0x00,0x00,0x50000103,0,0,0,0,0,0,0,0}, {"3830", 0x3830,0x02,0x00,0x00,0x00,0x50000103,0,0,0,0,0,0,0,0}, {"3880", 0x3880,0x05,0x09,0x00,0x00,0x80000000,0,0,0,0,0,0,0,0}, {"3990", 0x3990,0xc2,0x10,0x00,0x00,0xd0000002,0x40fa0100,0,0,0,0,0,0,0}, {"3990-3", 0x3990,0xec,0x06,0x00,0x00,0xd000009e,0x40fa0100,0x41270004,0x423e0040,0,0,0,0,0}, {"3990-6", 0x3990,0xe9,0x15,0x48,0x15,0x50003097,0x40fa0100,0x41270004,0x423e0060,0,0,0,0,0}, {"9343", 0x9343,0xe0,0x11,0x00,0x00,0x80000000,0,0,0,0,0,0,0,0} } ; #define CKDCU_NUM (sizeof(ckdcutab)/CKDCU_SIZE) /*-------------------------------------------------------------------*/ /* FBA device definitions - courtesy of Tomas Masek */ /*-------------------------------------------------------------------*/ static FBADEV fbatab[] = { /* name devt class type mdl bpg bpp size blks cu */ {"3310", 0x3310,0x21,0x01,0x01, 32,352,512, 125664,0x4331}, {"3310-1", 0x3310,0x21,0x01,0x01, 32,352,512, 125664,0x4331}, {"3310-x", 0x3310,0x21,0x01,0x01, 32,352,512, 0,0x4331}, {"3370", 0x3370,0x21,0x02,0x00, 62,744,512, 558000,0x3880}, {"3370-1", 0x3370,0x21,0x02,0x00, 62,744,512, 558000,0x3880}, {"3370-A1", 0x3370,0x21,0x02,0x00, 62,744,512, 558000,0x3880}, {"3370-B1", 0x3370,0x21,0x02,0x00, 62,744,512, 558000,0x3880}, {"3370-2", 0x3370,0x21,0x05,0x04, 62,744,512, 712752,0x3880}, {"3370-A2", 0x3370,0x21,0x05,0x04, 62,744,512, 712752,0x3880}, {"3370-B2", 0x3370,0x21,0x05,0x04, 62,744,512, 712752,0x3880}, {"3370-x", 0x3370,0x21,0x05,0x04, 62,744,512, 0,0x3880}, {"9332", 0x9332,0x21,0x07,0x00, 73,292,512, 360036,0x6310}, {"9332-400", 0x9332,0x21,0x07,0x00, 73,292,512, 360036,0x6310}, {"9332-600", 0x9332,0x21,0x07,0x01, 73,292,512, 554800,0x6310}, {"9332-x", 0x9332,0x21,0x07,0x01, 73,292,512, 0,0x6310}, {"9335", 0x9335,0x21,0x06,0x01, 71,426,512, 804714,0x6310}, {"9335-x", 0x9335,0x21,0x06,0x01, 71,426,512, 0,0x6310}, /*"9313", 0x9313,0x21,0x08,0x00, ??,???,512, 246240,0x????}, */ /*"9313-1, 0x9313,0x21,0x08,0x00, ??,???,512, 246240,0x????}, */ /*"9313-14", 0x9313,0x21,0x08,0x14, ??,???,512, 246240,0x????}, */ /* 246240=32*81*5*19 */ {"9313", 0x9313,0x21,0x08,0x00, 96,480,512, 246240,0x6310}, {"9313-x", 0x9313,0x21,0x08,0x00, 96,480,512, 0,0x6310}, /* 9336 Junior models 1,2,3 */ /*"9336-J1", 0x9336,0x21,0x11,0x00, 63,315,512, 920115,0x6310}, */ /*"9336-J2", 0x9336,0x21,0x11,0x04, ??,???,512, ?,0x6310}, */ /*"9336-J3", 0x9336,0x21,0x11,0x08, ??,???,512, ?,0x6310}, */ /* 9336 Senior models 1,2,3 */ /*"9336-S1", 0x9336,0x21,0x11,0x10,111,777,512,1672881,0x6310}, */ /*"9336-S2", 0x9336,0x21,0x11,0x14,???,???,512, ?,0x6310}, */ /*"9336-S3", 0x9336,0x21,0x11,0x18,???,???,512, ?,0x6310}, */ {"9336", 0x9336,0x21,0x11,0x00, 63,315,512, 920115,0x6310}, {"9336-10", 0x9336,0x21,0x11,0x00, 63,315,512, 920115,0x6310}, {"9336-20", 0x9336,0x21,0x11,0x10,111,777,512,1672881,0x6310}, {"9336-25", 0x9336,0x21,0x11,0x10,111,777,512,1672881,0x6310}, {"9336-x", 0x9336,0x21,0x11,0x10,111,777,512, 0,0x6310}, {"0671-08", 0x0671,0x21,0x12,0x08, 63,630,512, 513072,0x6310}, {"0671", 0x0671,0x21,0x12,0x00, 63,630,512, 574560,0x6310}, {"0671-04", 0x0671,0x21,0x12,0x04, 63,630,512, 624456,0x6310}, {"0671-x", 0x0671,0x21,0x12,0x04, 63,630,512, 0,0x6310} } ; #define FBADEV_NUM (sizeof(fbatab)/FBADEV_SIZE) #if defined(FEATURE_VM_BLOCKIO) static BLKTAB blktab[] = { #if 0 /* Remove conditional compilation when CKD devices supported */ CKDIOT("2305",0x2305,15,10,5,3), CKDIOT("2311",0x2311,6,3,1,0), CKDIOT("2314",0x2314,11,6,3,1), CKDIOT("3330",0x3330,20,11,6,3), CKDIOT("3340",0x3340,12,7,3,2), CKDIOT("3350",0x3350,27,15,8,4), CKDIOT("3375",0x3375,40,25,14,8), CKDIOT("3380",0x3380,35,23,14,7), CKDIOT("3390",0x3390,49,33,21,12), CKDIOT("9345",0x9345,41,28,17,9), #endif FBAIOT("0671",0x0671), FBAIOT("3310",0x3310), FBAIOT("3370",0x3370), FBAIOT("9332",0x9332), FBAIOT("9335",0x9335), FBAIOT("9336",0x9336) }; #define BLKTAB_NUM (sizeof(blktab)/BLKTAB_SIZE) #endif /* defined(FEATURE_VM_BLOCKIO) */ /*-------------------------------------------------------------------*/ /* Lookup a table entry either by name or type */ /*-------------------------------------------------------------------*/ DLL_EXPORT void *dasd_lookup (int dtype, char *name, U32 devt, U32 size) { U32 i; /* Loop Index */ switch (dtype) { case DASD_CKDDEV: for (i = 0; i < (int)CKDDEV_NUM; i++) { if ((name && !strcmp(name, ckdtab[i].name)) || (((U32)devt == (U32)ckdtab[i].devt || (U32)devt == (U32)(ckdtab[i].devt & 0xff)) && (U32)size <= (U32)(ckdtab[i].cyls + ckdtab[i].altcyls))) return &ckdtab[i]; } return NULL; case DASD_CKDCU: for (i = 0; i < (int)CKDCU_NUM; i++) { if ((name != NULL && strcmp(name, ckdcutab[i].name) == 0) || devt == ckdcutab[i].devt) return &ckdcutab[i]; } return NULL; case DASD_FBADEV: for (i = 0; i < (int)FBADEV_NUM; i++) { if ((name && !strcmp(name, fbatab[i].name)) || (((U32)devt == (U32)fbatab[i].devt || (U32)devt == (U32)(fbatab[i].devt & 0xff)) && ((size <= fbatab[i].blks) || (fbatab[i].blks == 0)))) return &fbatab[i]; } return NULL; #if defined(FEATURE_VM_BLOCKIO) case DASD_STDBLK: for (i = 0; i < (int)BLKTAB_NUM; i++) { if ((name && !strcmp(name, blktab[i].name)) || (U32)devt == (U32)blktab[i].devt || (U32)devt == (U32)(blktab[i].devt & 0xff)) return &blktab[i]; } return NULL; #endif /* defined(FEATURE_VM_BLOCKIO) */ default: return NULL; } return NULL; } /*-------------------------------------------------------------------*/ /* Build CKD devid field */ /*-------------------------------------------------------------------*/ int dasd_build_ckd_devid (CKDDEV *ckd, CKDCU *cu, BYTE *devid) { int len; memset (devid, 0, 256); store_fw (devid + 0, 0xFF000000 | (cu->devt << 8) | cu->model); store_fw (devid + 4, (ckd->devt << 16) | (ckd->model << 8) | 0x00); store_fw (devid + 8, cu->ciw1); store_fw (devid +12, cu->ciw2); store_fw (devid +16, cu->ciw3); store_fw (devid +20, cu->ciw4); store_fw (devid +24, cu->ciw5); store_fw (devid +28, cu->ciw6); store_fw (devid +32, cu->ciw7); store_fw (devid +36, cu->ciw8); /* Set length */ if (cu->ciw8 != 0) len = 40; else if (cu->ciw7 != 0) len = 36; else if (cu->ciw6 != 0) len = 32; else if (cu->ciw5 != 0) len = 28; else if (cu->ciw4 != 0) len = 24; else if (cu->ciw3 != 0) len = 20; else if (cu->ciw2 != 0) len = 16; else if (cu->ciw1 != 0) len = 12; else len = 7; /* If LEGACYSENSEID ENABLE is not set and device is a 2311 or 2314, set devid length to zero to force command reject response to 0xE4 Sense ID command */ if (1 && !sysblk.legacysenseid && (0 || 0x2311 == ckd->devt || 0x2314 == ckd->devt ) ) { len = 0; } return len; } /*-------------------------------------------------------------------*/ /* Build CKD devchar field */ /*-------------------------------------------------------------------*/ int dasd_build_ckd_devchar (CKDDEV *ckd, CKDCU *cu, BYTE *devchar, int cyls) { int altcyls; /* Number alternate cyls */ if (cyls > ckd->cyls) altcyls = cyls - ckd->cyls; else altcyls = 0; memset (devchar, 0, 64); store_hw(devchar+0, cu->devt); // Storage control type devchar[2] = cu->model; // CU model store_hw(devchar+3, ckd->devt); // Device type devchar[5] = ckd->model; // Device model store_fw(devchar+6, cu->sctlfeat); // Device and SD facilities devchar[10] = ckd->class; // Device class code devchar[11] = ckd->code; // Device type code store_hw(devchar+12, cyls - altcyls); // Primary cylinders store_hw(devchar+14, ckd->heads); // Tracks per cylinder devchar[16] = (BYTE)(ckd->sectors); // Number of sectors store_hw(devchar+18, ckd->len); // Track length store_hw(devchar+20, ckd->har0); // Length of HA and R0 if (ckd->formula == 1) { devchar[22] = (BYTE)(ckd->formula); // Track capacity formula devchar[23] = (BYTE)(ckd->f1); // Factor F1 store_hw(devchar+24, ckd->f2); // Factor F2 store_hw(devchar+26, ckd->f3); // Factor F3 } else if (ckd->formula == 2) { devchar[22] = (BYTE)(ckd->formula); // Track capacity formula devchar[23] = (BYTE)(ckd->f1); // Factor F1 devchar[24] = (BYTE)(ckd->f2); // Factor F2 devchar[25] = (BYTE)(ckd->f3); // Factor F3 devchar[26] = (BYTE)(ckd->f4); // Factor F4 devchar[27] = (BYTE)(ckd->f5); // Factor F5 } if (altcyls > 0) { store_hw(devchar+28, cyls - altcyls); // Alternate cylinder & tracks store_hw(devchar+30, altcyls * ckd->heads); } devchar[40] = ckd->code; // MDR record ID devchar[41] = ckd->code; // OBR record ID devchar[42] = cu->code; // CU Type Code devchar[43] = 0x02; // Parameter length store_hw(devchar+44, ckd->r0); // Record 0 length devchar[47] = 0x01; // Track set devchar[48] = (BYTE)(ckd->f6); // F6 store_hw(devchar+49, ckd->rpscalc); // RPS factor devchar[51] = MODEL6(cu) ? 0x0f : 0x00; // reserved byte 51 devchar[54] = cu->funcfeat; // device/CU functions/features devchar[56] = cu->typecode; // Real CU type code /*---------------------------------------------------------------*/ /* 2007/05/04 @kl */ /* The following line to set devchar[57] to 0xff was restored */ /* to circumvent a command reject when ICKDSF issues a Read */ /* Special Home Address (0x0a) to an alternate track. */ /* According to the IBM 3880 Storage Control Reference, */ /* GA16-1661-09, and the 3990/9330 Reference, GA32-0274-05, */ /* it should be 0x00 for real 3380 and 3390 devices. Setting */ /* it to 0xff makes the underlying real DASD look like a */ /* disk array (whose virtual 3380/3390 disks have no alternate */ /* tracks). This causes DSF to skip issuing the 0x0a channel */ /* command, which Hercules does not currently support, for */ /* alternate tracks. */ /*---------------------------------------------------------------*/ devchar[57] = 0xff; // real device type code return 64; } /*-------------------------------------------------------------------*/ /* Build CKD configuration data */ /*-------------------------------------------------------------------*/ DLL_EXPORT int dasd_build_ckd_config_data (DEVBLK *dev, BYTE *iobuf, int count) { int i; BYTE buf[256]; /* Clear the configuration data area */ memset (buf, 0, 256); /* Bytes 0-31: NED 1 Node element descriptor for the device */ store_fw (buf, 0xc4010100); sprintf ((char *)&buf[4], " %4.4X0%2.2XHRCZZ000000000001", dev->ckdtab->devt, dev->ckdtab->model); for (i = 4; i < 30; i++) buf[i] = host_to_guest(buf[i]); store_hw(buf + 30, 0x0300); /* Bytes 32-63: NED 2 Node element descriptor for the string */ store_fw (buf + 32, 0xc4000000); sprintf ((char *)&buf[36], " %4.4X0%2.2XHRCZZ000000000001", dev->ckdtab->devt, dev->ckdtab->model); for (i = 36; i < 62; i++) buf[i] = host_to_guest(buf[i]); store_hw (buf + 62, 0x0300); /* Bytes 64-95: NED 3 Node element descriptor for the storage director */ store_fw (buf + 64, 0xd4020000); sprintf ((char *)&buf[68], " %4.4X0%2.2XHRCZZ000000000001", dev->ckdcu->devt, dev->ckdcu->model); for (i = 68; i < 94; i++) buf[i] = host_to_guest(buf[i]); store_hw (buf + 94, 0x0300); /* Bytes 96-127: NED 4 Node element descriptor for the subsystem */ store_fw (buf + 96, 0xF0000001); sprintf ((char *)&buf[100], " %4.4X HRCZZ000000000001", dev->ckdcu->devt); for (i = 100; i < 126; i++) buf[i] = host_to_guest(buf[i]); store_hw (buf + 126, 0x0300); /* Bytes 128-223: zeroes */ /* Bytes 224-255: NEQ Node Element Qualifier */ buf[224] = 0x80; // flags (general NEQ) buf[225] = 0; // record selector store_hw (buf + 226, IFID(dev)); // interface id store_hw (buf + 228, 0); // must be zero buf[230] = 0x1E; // primary missing interrupt timer interval buf[231] = 0x00; // secondary missing interrupt timer interval store_hw (buf + 232, SSID(dev)); // subsystem id buf[234] = 0x80; // path/cluster id buf[235] = (dev->devnum & 0xFF); // unit address buf[236] = (dev->devnum & 0xFF); // physical device id buf[237] = (dev->devnum & 0xFF); // physical device address buf[238] = buf[227]; // SA ID (same as interface ID, byte 227) store_hw (buf + 239, 0); // escon link address buf[241] = 0x80; // interface protocol type (parallel) // buf[241] = 0x40; // interface protocol type (escon) buf[242] = 0x80; // NEQ format flags buf[243] = (dev->devnum & 0xFF); // logical device address (LDA) // bytes 244-255 must be zero /* Copy data characteristics to the I/O buf */ count = count > 256 ? 256 : count; memcpy (iobuf, buf, count); return 256; } /*-------------------------------------------------------------------*/ /* Build CKD subsystem status */ /*-------------------------------------------------------------------*/ DLL_EXPORT int dasd_build_ckd_subsys_status (DEVBLK *dev, BYTE *iobuf, int count) { int num; BYTE buf[44]; /* Build the basic subsystem status data in the I/O area */ memset (buf, 0, 44); buf[1] = dev->devnum & 0xFF; buf[2] = DEVICES_PER_SUBSYS - 1; store_hw (buf + 38, SSID(dev)); num = 40; /* Build an additional 4 bytes of data for the 3990-6 */ if (MODEL6(dev->ckdcu)) { buf[0] = 0x01; /* Set 3990-6 enhanced flag */ num = 44; } /* end if(3990-6) */ /* Copy subsystem status to the I/O buf */ count = count > num ? num : count; memcpy (iobuf, buf, count); return num; } /*-------------------------------------------------------------------*/ /* Build FBA devid field */ /*-------------------------------------------------------------------*/ int dasd_build_fba_devid (FBADEV *fba, BYTE *devid) { memset (devid, 0, 256); devid[0] = 0xff; devid[1] = (fba->cu >> 8) & 0xff; devid[2] = fba->cu & 0xff; devid[3] = 0x01; /* assume model is 1 */ devid[4] = (fba->devt >> 8) & 0xff; devid[5] = fba->devt & 0xff; devid[6] = fba->model; return 7; } /*-------------------------------------------------------------------*/ /* Build FBA devchar field */ /*-------------------------------------------------------------------*/ int dasd_build_fba_devchar (FBADEV *fba, BYTE *devchar, int blks) { memset (devchar, 0, 64); devchar[0] = 0x30; // operation modes devchar[1] = 0x08; // features devchar[2] = fba->class; // device class devchar[3] = fba->type; // unit type devchar[4] = (fba->size >> 8) & 0xff; // block size devchar[5] = fba->size & 0xff; devchar[6] = (fba->bpg >> 24) & 0xff; // blks per cyclical group devchar[7] = (fba->bpg >> 16) & 0xff; devchar[8] = (fba->bpg >> 8) & 0xff; devchar[9] = fba->bpg & 0xff; devchar[10] = (fba->bpp >> 24) & 0xff; // blks per access position devchar[11] = (fba->bpp >> 16) & 0xff; devchar[12] = (fba->bpp >> 8) & 0xff; devchar[13] = fba->bpp & 0xff; devchar[14] = (blks >> 24) & 0xff; // blks under movable heads devchar[15] = (blks >> 16) & 0xff; devchar[16] = (blks >> 8) & 0xff; devchar[17] = blks & 0xff; devchar[18] = 0; // blks under fixed heads devchar[19] = 0; devchar[20] = 0; devchar[21] = 0; devchar[22] = 0; // blks in alternate area devchar[23] = 0; devchar[24] = 0; // blks in CE+SA areas devchar[25] = 0; devchar[26] = 0; // cyclic period in ms devchar[27] = 0; devchar[28] = 0; // min time to change access devchar[29] = 0; // position in ms devchar[30] = 0; // max to change access devchar[31] = 0; // position in ms return 32; } hercules-3.07/dasdtab.h000644 000765 000765 00000020211 11301535255 016512 0ustar00jmaynardjmaynard000000 000000 /* DASDTAB.H (c) Copyright Roger Bowler, 1999-2009 */ /* DASD table structures */ // $Id: dasdtab.h 5444 2009-08-09 16:36:42Z hsg001 $ /*-------------------------------------------------------------------*/ /* This header file contains defines the table entries that */ /* describe all DASD devices supported by Hercules. */ /* It also contains function prototypes for the DASD table utilities.*/ /*-------------------------------------------------------------------*/ // $Log$ // Revision 1.14 2007/06/23 00:04:08 ivan // Update copyright notices to include current year (2007) // // Revision 1.13 2007/03/06 22:54:19 gsmith // Fix ckd RDC response // // Revision 1.12 2007/02/15 00:10:04 gsmith // Fix ckd RCD, SNSS, SNSID responses // // Revision 1.11 2006/12/08 09:43:20 jj // Add CVS message log // #if !defined(_DASDTAB_H) #define _DASDTAB_H #include "hercules.h" #ifndef _DASDTAB_C_ #ifndef _HDASD_DLL_ #define DTB_DLL_IMPORT DLL_IMPORT #else /* _HDASD_DLL_ */ #define DTB_DLL_IMPORT extern #endif /* _HDASD_DLL_ */ #else #define DTB_DLL_IMPORT DLL_EXPORT #endif #define CKD_CONFIG_DATA_SIZE 256 #if 0 #define myssid (dev->devnum & 0xffe0) /* Storage subsystem identifier 32 devices per subsystem */ #else #define myssid SSID(dev) #endif /* 32 devices per subsystem */ #define DEVICES_PER_SUBSYS_SHIFT 5 #define DEVICES_PER_SUBSYS (1 << DEVICES_PER_SUBSYS_SHIFT) #define SSID(_dev) ((_dev)->devnum & ~(DEVICES_PER_SUBSYS-1)) #define IFID(_dev) ((SSID((_dev)) >> DEVICES_PER_SUBSYS_SHIFT) & 0x7) /* Test for 3990-6 control unit with extended function */ #define MODEL6(_cu) ((_cu)->devt == 0x3990 && (_cu)->model == 0xe9) /*-------------------------------------------------------------------*/ /* Definition of a CKD DASD device entry */ /*-------------------------------------------------------------------*/ typedef struct _CKDDEV { /* CKD Device table entry */ char *name; /* Device name */ U16 devt; /* Device type */ BYTE model; /* Device model */ BYTE class; /* Device class */ BYTE code; /* Device code */ U16 cyls; /* Number primary cylinders */ U16 altcyls; /* Number alternate cylinders*/ U16 heads; /* Number heads (trks/cyl) */ U16 r0; /* R0 max size */ U16 r1; /* R1 max size */ U16 har0; /* HA/R0 overhead size */ U16 len; /* Max length */ U16 sectors; /* Number sectors */ U16 rpscalc; /* RPS calculation factor */ S16 formula; /* Space calculation formula */ U16 f1,f2,f3,f4,f5,f6; /* Space calculation factors */ char *cu; /* Default control unit name */ } CKDDEV; #define CKDDEV_SIZE sizeof(CKDDEV) /*-------------------------------------------------------------------*/ /* Definition of a CKD DASD control unit entry */ /*-------------------------------------------------------------------*/ typedef struct _CKDCU { /* CKD Control Unit entry */ char *name; /* Control Unit name */ U16 devt; /* Control Unit type */ BYTE model; /* Control Unit model */ BYTE code; /* Control Unit code */ BYTE funcfeat; /* Functions/Features */ BYTE typecode; /* CU Type Code */ U32 sctlfeat; /* Control Unit features */ U32 ciw1; /* CIW 1 */ U32 ciw2; /* CIW 2 */ U32 ciw3; /* CIW 3 */ U32 ciw4; /* CIW 4 */ U32 ciw5; /* CIW 5 */ U32 ciw6; /* CIW 6 */ U32 ciw7; /* CIW 7 */ U32 ciw8; /* CIW 8 */ } CKDCU; #define CKDCU_SIZE sizeof(CKDCU) /*-------------------------------------------------------------------*/ /* Definition of a FBA DASD device entry */ /*-------------------------------------------------------------------*/ typedef struct _FBADEV { /* FBA Device entry */ char *name; /* Device name */ U16 devt; /* Device type */ BYTE class; /* Device class */ BYTE type; /* Type */ BYTE model; /* Model */ U32 bpg; /* Blocks per cyclical group */ U32 bpp; /* Blocks per access position*/ U32 size; /* Block size */ U32 blks; /* Number of blocks */ U16 cu; /* Default control unit type */ } FBADEV; #define FBADEV_SIZE sizeof(FBADEV) #if defined(FEATURE_VM_BLOCKIO) /*-------------------------------------------------------------------*/ /* Device Standard Block Size Information Table */ /*-------------------------------------------------------------------*/ typedef struct _BLKTAB { char *name; /* Device name */ U16 devt; /* Hercules supported device Type */ int darch; /* FBA (0) or CKD (1) device */ #define VMDEVFBA 0 /* Fixed-Block Architecture device */ #define VMDEVCKD 1 /* (Extended-)Count-Key-Data device */ /* sectors per block or blocks per track for standardblock sizes */ int phys512; /* Block size 512 */ int phys1024; /* Block size 1024 */ int phys2048; /* Block size 2048 */ int phys4096; /* Block size 4096 */ } BLKTAB; #define BLKTAB_SIZE sizeof(BLKTAB) /* Macros that define a table entry */ #define CKDIOT(_name,_type,_bs512,_bs1024,_bs2048,_bs4096) \ { _name, _type, 1, _bs512, _bs1024, _bs2048, _bs4906 } #define FBAIOT(_name,_type) \ { _name, _type, 0, 1, 2, 4, 8 } #endif /* defined(FEATURE_VM_BLOCKIO) */ /*-------------------------------------------------------------------*/ /* Request types for dasd_lookup */ /*-------------------------------------------------------------------*/ #define DASD_CKDDEV 1 /* Lookup CKD device */ #define DASD_CKDCU 2 /* Lookup CKD control unit */ #define DASD_FBADEV 3 /* Lookup FBA device */ #if defined(FEATURE_VM_BLOCKIO) #define DASD_STDBLK 4 /* Lookup device standard block/physical */ #endif /* defined(FEATURE_VM_BLOCKIO) */ /*-------------------------------------------------------------------*/ /* Dasd table function prototypes */ /*-------------------------------------------------------------------*/ DTB_DLL_IMPORT void *dasd_lookup (int, char *, U32 , U32 ); int dasd_build_ckd_devid (CKDDEV *, CKDCU *, BYTE *); int dasd_build_ckd_devchar (CKDDEV *, CKDCU *, BYTE *, int); DTB_DLL_IMPORT int dasd_build_ckd_config_data (DEVBLK *, BYTE *, int); DTB_DLL_IMPORT int dasd_build_ckd_subsys_status (DEVBLK *, BYTE *, int); int dasd_build_fba_devid (FBADEV *, BYTE *); int dasd_build_fba_devchar (FBADEV *, BYTE *, int); #endif /*!defined(_DASDTAB_H)*/ hercules-3.07/dasdutil.c000644 000765 000765 00000250073 11335530473 016733 0ustar00jmaynardjmaynard000000 000000 /* DASDUTIL.C (c) Copyright Roger Bowler, 1999-2009 */ /* Hercules DASD Utilities: Common subroutines */ // $Id: dasdutil.c 5628 2010-02-13 14:03:36Z jmaynard $ /*-------------------------------------------------------------------*/ /* This module contains common subroutines used by DASD utilities */ /*-------------------------------------------------------------------*/ // $Log$ // Revision 1.60 2007/06/23 00:04:08 ivan // Update copyright notices to include current year (2007) // // Revision 1.59 2006/12/08 09:43:20 jj // Add CVS message log // #include "hstdinc.h" #define _DASDUTIL_C_ #define _HDASD_DLL_ #include "hercules.h" #include "dasdblks.h" #include "devtype.h" #include "opcode.h" /*-------------------------------------------------------------------*/ /* External references (defined in ckddasd.c) */ /*-------------------------------------------------------------------*/ extern DEVHND ckddasd_device_hndinfo; /*-------------------------------------------------------------------*/ /* Internal macro definitions */ /*-------------------------------------------------------------------*/ /*-------------------------------------------------------------------*/ /* Static data areas */ /*-------------------------------------------------------------------*/ static int verbose = 0; /* Be chatty about reads etc. */ static BYTE eighthexFF[] = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}; static BYTE iplpsw[8] = {0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x0F}; static BYTE iplccw1[8] = {0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x01}; static BYTE iplccw2[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; static int nextnum = 0; #if 0 SYSBLK sysblk; /* Currently required for shared.c */ #endif /*-------------------------------------------------------------------*/ /* Subroutine to convert a null-terminated string to upper case */ /*-------------------------------------------------------------------*/ DLL_EXPORT void string_to_upper (char *source) { int i; /* Array subscript */ for (i = 0; source[i] != '\0'; i++) source[i] = toupper(source[i]); } /* end function string_to_upper */ /*-------------------------------------------------------------------*/ /* Subroutine to convert a null-terminated string to lower case */ /*-------------------------------------------------------------------*/ DLL_EXPORT void string_to_lower (char *source) { int i; /* Array subscript */ for (i = 0; source[i] != '\0'; i++) source[i] = tolower(source[i]); } /* end function string_to_lower */ /*-------------------------------------------------------------------*/ /* Subroutine to convert a string to EBCDIC and pad with blanks */ /*-------------------------------------------------------------------*/ DLL_EXPORT void convert_to_ebcdic (BYTE *dest, int len, char *source) { int i; /* Array subscript */ set_codepage(NULL); for (i = 0; i < len && source[i] != '\0'; i++) dest[i] = host_to_guest(source[i]); while (i < len) dest[i++] = 0x40; } /* end function convert_to_ebcdic */ /*-------------------------------------------------------------------*/ /* Subroutine to convert an EBCDIC string to an ASCIIZ string. */ /* Removes trailing blanks and adds a terminating null. */ /* Returns the length of the ASCII string excluding terminating null */ /*-------------------------------------------------------------------*/ DLL_EXPORT int make_asciiz (char *dest, int destlen, BYTE *src, int srclen) { int len; /* Result length */ set_codepage(NULL); for (len=0; len < srclen && len < destlen-1; len++) dest[len] = guest_to_host(src[len]); while (len > 0 && dest[len-1] == SPACE) len--; dest[len] = '\0'; return len; } /* end function make_asciiz */ /*-------------------------------------------------------------------*/ /* Subroutine to print a data block in hex and character format. */ /*-------------------------------------------------------------------*/ DLL_EXPORT void data_dump ( void *addr, int len ) { unsigned int maxlen = 2048; unsigned int i, xi, offset, startoff = 0; BYTE c; BYTE *pchar; char print_chars[17]; char hex_chars[64]; char prev_hex[64] = ""; int firstsame = 0; int lastsame = 0; set_codepage(NULL); pchar = (BYTE *)addr; for (offset=0; ; ) { if (offset >= maxlen && offset <= len - maxlen) { offset += 16; pchar += 16; prev_hex[0] = '\0'; continue; } if ( offset > 0 ) { if ( strcmp ( hex_chars, prev_hex ) == 0 ) { if ( firstsame == 0 ) firstsame = startoff; lastsame = startoff; } else { if ( firstsame != 0 ) { if ( lastsame == firstsame ) printf ("Line %4.4X same as above\n", firstsame ); else printf ("Lines %4.4X to %4.4X same as above\n", firstsame, lastsame ); firstsame = lastsame = 0; } printf ("+%4.4X %s %s\n", startoff, hex_chars, print_chars); strcpy ( prev_hex, hex_chars ); } } if ( offset >= (U32)len ) break; memset ( print_chars, 0, sizeof(print_chars) ); memset ( hex_chars, SPACE, sizeof(hex_chars) ); startoff = offset; for (xi=0, i=0; i < 16; i++) { c = *pchar++; if (offset < (U32)len) { sprintf(hex_chars+xi, "%2.2X", c); print_chars[i] = '.'; if (isprint(c)) print_chars[i] = c; c = guest_to_host(c); if (isprint(c)) print_chars[i] = c; } offset++; xi += 2; hex_chars[xi] = SPACE; if ((offset & 3) == 0) xi++; } /* end for(i) */ hex_chars[xi] = '\0'; } /* end for(offset) */ } /* end function data_dump */ /*-------------------------------------------------------------------*/ /* Subroutine to read a track from the CKD DASD image */ /* Input: */ /* cif -> CKD image file descriptor structure */ /* cyl Cylinder number */ /* head Head number */ /* Output: */ /* The track is read into trkbuf, and curcyl and curhead */ /* are set to the cylinder and head number. */ /* */ /* Return value is 0 if successful, -1 if error */ /*-------------------------------------------------------------------*/ DLL_EXPORT int read_track (CIFBLK *cif, int cyl, int head) { int rc; /* Return code */ int trk; /* Track number */ DEVBLK *dev; /* -> CKD device block */ BYTE unitstat; /* Unit status */ /* Exit if required track is already in buffer */ if (cif->curcyl == cyl && cif->curhead == head) return 0; dev = &cif->devblk; if (cif->trkmodif) { cif->trkmodif = 0; if (verbose) /* Issue progress message */ fprintf (stdout, _("HHCDU001I Updating cyl %d head %d\n"), cif->curcyl, cif->curhead); trk = (cif->curcyl * cif->heads) + cif->curhead; rc = (dev->hnd->write)(dev, trk, 0, NULL, cif->trksz, &unitstat); if (rc < 0) { fprintf (stderr, _("HHCDU002E %s write track error: stat=%2.2X\n"), cif->fname, unitstat); return -1; } } if (verbose) /* Issue progress message */ fprintf (stdout, _("HHCDU003I Reading cyl %d head %d\n"), cyl, head); trk = (cyl * cif->heads) + head; rc = (dev->hnd->read)(dev, trk, &unitstat); if (rc < 0) { fprintf (stderr, _("HHCDU004E %s read track error: stat=%2.2X\n"), cif->fname, unitstat); return -1; } /* Set current buf, cylinder and head */ cif->trkbuf = dev->buf; cif->curcyl = cyl; cif->curhead = head; return 0; } /* end function read_track */ /*-------------------------------------------------------------------*/ /* Subroutine to read a block from the CKD DASD image */ /* Input: */ /* cif -> CKD image file descriptor structure */ /* cyl Cylinder number of requested block */ /* head Head number of requested block */ /* rec Record number of requested block */ /* Output: */ /* keyptr Pointer to record key */ /* keylen Actual key length */ /* dataptr Pointer to record data */ /* datalen Actual data length */ /* */ /* Return value is 0 if successful, +1 if end of track, -1 if error */ /*-------------------------------------------------------------------*/ DLL_EXPORT int read_block (CIFBLK *cif, int cyl, int head, int rec, BYTE **keyptr, int *keylen, BYTE **dataptr, int *datalen) { int rc; /* Return code */ BYTE *ptr; /* -> byte in track buffer */ CKDDASD_RECHDR *rechdr; /* -> Record header */ int kl; /* Key length */ int dl; /* Data length */ /* Read the required track into the track buffer if necessary */ rc = read_track (cif, cyl, head); if (rc < 0) return -1; /* Search for the requested record in the track buffer */ ptr = cif->trkbuf; ptr += CKDDASD_TRKHDR_SIZE; while (1) { /* Exit with record not found if end of track */ if (memcmp(ptr, eighthexFF, 8) == 0) return +1; /* Extract key length and data length from count field */ rechdr = (CKDDASD_RECHDR*)ptr; kl = rechdr->klen; dl = (rechdr->dlen[0] << 8) | rechdr->dlen[1]; /* Exit if requested record number found */ if (rechdr->rec == rec) break; /* Issue progress message */ // fprintf (stdout, // "Skipping CCHHR=%2.2X%2.2X%2.2X%2.2X" // "%2.2X KL=%2.2X DL=%2.2X%2.2X\n", // rechdr->cyl[0], rechdr->cyl[1], // rechdr->head[0], rechdr->head[1], // rechdr->rec, rechdr->klen, // rechdr->dlen[0], rechdr->dlen[1]); /* Point past count key and data to next block */ ptr += CKDDASD_RECHDR_SIZE + kl + dl; } /* Return key and data pointers and lengths */ if (keyptr != NULL) *keyptr = ptr + CKDDASD_RECHDR_SIZE; if (keylen != NULL) *keylen = kl; if (dataptr != NULL) *dataptr = ptr + CKDDASD_RECHDR_SIZE + kl; if (datalen != NULL) *datalen = dl; return 0; } /* end function read_block */ /*-------------------------------------------------------------------*/ /* Subroutine to search a dataset for a specified key */ /* Input: */ /* cif -> CKD image file descriptor structure */ /* key Key value */ /* keylen Key length */ /* noext Number of extents */ /* extent Dataset extent array */ /* Output: */ /* cyl Cylinder number of requested block */ /* head Head number of requested block */ /* rec Record number of requested block */ /* */ /* Return value is 0 if successful, +1 if key not found, -1 if error */ /*-------------------------------------------------------------------*/ DLL_EXPORT int search_key_equal (CIFBLK *cif, BYTE *key, int keylen, int noext, DSXTENT extent[], int *cyl, int *head, int *rec) { int rc; /* Return code */ int ccyl; /* Cylinder number */ int chead; /* Head number */ int cext; /* Extent sequence number */ int ecyl; /* Extent end cylinder */ int ehead; /* Extent end head */ BYTE *ptr; /* -> byte in track buffer */ CKDDASD_RECHDR *rechdr; /* -> Record header */ int kl; /* Key length */ int dl; /* Data length */ /* Start at first track of first extent */ cext = 0; ccyl = (extent[cext].xtbcyl[0] << 8) | extent[cext].xtbcyl[1]; chead = (extent[cext].xtbtrk[0] << 8) | extent[cext].xtbtrk[1]; ecyl = (extent[cext].xtecyl[0] << 8) | extent[cext].xtecyl[1]; ehead = (extent[cext].xtetrk[0] << 8) | extent[cext].xtetrk[1]; if (verbose) { fprintf (stdout, _("HHCDU005I Searching extent %d begin (%d,%d) end (%d,%d)\n"), cext, ccyl, chead, ecyl, ehead); } while (1) { /* Read the required track into the track buffer */ rc = read_track (cif, ccyl, chead); if (rc < 0) return -1; /* Search for the requested record in the track buffer */ ptr = cif->trkbuf; ptr += CKDDASD_TRKHDR_SIZE; while (1) { /* Exit loop at end of track */ if (memcmp(ptr, eighthexFF, 8) == 0) break; /* Extract key length and data length from count field */ rechdr = (CKDDASD_RECHDR*)ptr; kl = rechdr->klen; dl = (rechdr->dlen[0] << 8) | rechdr->dlen[1]; /* Return if requested record key found */ if (kl == keylen && memcmp(ptr + CKDDASD_RECHDR_SIZE, key, 44) == 0) { *cyl = ccyl; *head = chead; *rec = rechdr->rec; return 0; } /* Issue progress message */ // fprintf (stdout, // "Skipping CCHHR=%2.2X%2.2X%2.2X%2.2X" // "%2.2X KL=%2.2X DL=%2.2X%2.2X\n", // rechdr->cyl[0], rechdr->cyl[1], // rechdr->head[0], rechdr->head[1], // rechdr->rec, rechdr->klen, // rechdr->dlen[0], rechdr->dlen[1]); /* Point past count key and data to next block */ ptr += CKDDASD_RECHDR_SIZE + kl + dl; } /* end while */ /* Point to the next track */ chead++; if (chead >= cif->heads) { ccyl++; chead = 0; } /* Loop if next track is within current extent */ if (ccyl < ecyl || (ccyl == ecyl && chead <= ehead)) continue; /* Move to next extent */ cext++; if (cext >= noext) break; ccyl = (extent[cext].xtbcyl[0] << 8) | extent[cext].xtbcyl[1]; chead = (extent[cext].xtbtrk[0] << 8) | extent[cext].xtbtrk[1]; ecyl = (extent[cext].xtecyl[0] << 8) | extent[cext].xtecyl[1]; ehead = (extent[cext].xtetrk[0] << 8) | extent[cext].xtetrk[1]; if (verbose) { fprintf (stdout, _("HHCDU006I Searching extent %d begin (%d,%d) end (%d,%d)\n"), cext, ccyl, chead, ecyl, ehead); } } /* end while */ /* Return record not found at end of extents */ return +1; } /* end function search_key_equal */ /*-------------------------------------------------------------------*/ /* Subroutine to convert relative track to cylinder and head */ /* Input: */ /* tt Relative track number */ /* noext Number of extents in dataset */ /* extent Dataset extent array */ /* heads Number of tracks per cylinder */ /* Output: */ /* cyl Cylinder number */ /* head Head number */ /* */ /* Return value is 0 if successful, or -1 if error */ /*-------------------------------------------------------------------*/ DLL_EXPORT int convert_tt (int tt, int noext, DSXTENT extent[], int heads, int *cyl, int *head) { int i; /* Extent sequence number */ int trk; /* Relative track number */ int bcyl; /* Extent begin cylinder */ int btrk; /* Extent begin head */ int ecyl; /* Extent end cylinder */ int etrk; /* Extent end head */ int start; /* Extent begin track */ int end; /* Extent end track */ int extsize; /* Extent size in tracks */ for (i = 0, trk = tt; i < noext; i++) { bcyl = (extent[i].xtbcyl[0] << 8) | extent[i].xtbcyl[1]; btrk = (extent[i].xtbtrk[0] << 8) | extent[i].xtbtrk[1]; ecyl = (extent[i].xtecyl[0] << 8) | extent[i].xtecyl[1]; etrk = (extent[i].xtetrk[0] << 8) | extent[i].xtetrk[1]; start = (bcyl * heads) + btrk; end = (ecyl * heads) + etrk; extsize = end - start + 1; if (trk < extsize) { trk += start; *cyl = trk / heads; *head = trk % heads; return 0; } trk -= extsize; } /* end for(i) */ fprintf (stderr, _("HHCDU007E Track %d not found in extent table\n"), tt); return -1; } /* end function convert_tt */ /*-------------------------------------------------------------------*/ /* Subroutine to open a CKD image file */ /* Input: */ /* fname CKD image file name */ /* sfname xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx */ /* omode Open mode: O_RDONLY or O_RDWR */ /* dasdcopy xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx */ /* */ /* The CKD image file is opened, a track buffer is obtained, */ /* and a CKD image file descriptor structure is built. */ /* Return value is a pointer to the CKD image file descriptor */ /* structure if successful, or NULL if unsuccessful. */ /*-------------------------------------------------------------------*/ DLL_EXPORT CIFBLK* open_ckd_image (char *fname, char *sfname, int omode, int dasdcopy) { int fd; /* File descriptor */ int rc; /* Return code */ int len; /* Record length */ CKDDASD_DEVHDR devhdr; /* CKD device header */ CIFBLK *cif; /* CKD image file descriptor */ DEVBLK *dev; /* CKD device block */ CKDDEV *ckd; /* CKD DASD table entry */ char *rmtdev; /* Possible remote device */ char *argv[2]; /* Arguments to */ int argc=0; /* */ char sfxname[1024]; /* Suffixed file name */ char typname[64]; char pathname[MAX_PATH]; /* file path in host format */ /* Obtain storage for the file descriptor structure */ cif = (CIFBLK*) calloc (sizeof(CIFBLK), 1); if (cif == NULL) { fprintf (stderr, _("HHCDU008E Cannot obtain storage for device descriptor " "buffer: %s\n"), strerror(errno)); return NULL; } /* Initialize the devblk */ dev = &cif->devblk; if ((omode & O_RDWR) == 0) dev->ckdrdonly = 1; dev->batch = 1; dev->dasdcopy = dasdcopy; /* If the filename has a `:' then it may be a remote device */ rmtdev = strchr(fname, ':'); /* Read the device header so we can determine the device type */ strcpy (sfxname, fname); hostpath(pathname, sfxname, sizeof(pathname)); fd = open (pathname, omode); if (fd < 0) { /* If no shadow file name was specified, then try opening the file with the file sequence number in the name */ if (sfname == NULL) { int i; char *s,*suffix; /* Look for last slash marking end of directory name */ s = strrchr (fname, '/'); if (s == NULL) s = fname; /* Insert suffix before first dot in file name, or append suffix to file name if there is no dot. If the filename already has a place for the suffix then use that. */ s = strchr (s, '.'); if (s != NULL) { i = s - fname; if (i > 2 && fname[i-2] == '_') suffix = sfxname + i - 1; else { strcpy (sfxname + i, "_1"); strcat (sfxname, fname + i); suffix = sfxname + i + 1; } } else { if (strlen(sfxname) < 2 || sfxname[strlen(sfxname)-2] != '_') strcat (sfxname, "_1"); suffix = sfxname + strlen(sfxname) - 1; } *suffix = '1'; hostpath(pathname, sfxname, sizeof(pathname)); fd = open (pathname, omode); } if (fd < 0 && rmtdev == NULL) { fprintf (stderr, _("HHCDU009E Cannot open %s: %s\n"), fname, strerror(errno)); free (cif); return NULL; } else if (fd < 0) strcpy (sfxname, fname); } /* If not a possible remote devic, check the dasd header and set the device type */ if (fd >= 0) { len = read (fd, &devhdr, CKDDASD_DEVHDR_SIZE); if (len < 0) { fprintf (stderr, _("HHCDU010E %s read error: %s\n"), fname, strerror(errno)); close (fd); free (cif); return NULL; } close (fd); if (len < (int)CKDDASD_DEVHDR_SIZE || (memcmp(devhdr.devid, "CKD_P370", 8) && memcmp(devhdr.devid, "CKD_C370", 8))) { fprintf (stderr, _("HHCDU011E %s CKD header invalid\n"), fname); free (cif); return NULL; } /* Set the device type */ ckd = dasd_lookup (DASD_CKDDEV, NULL, devhdr.devtype, 0); if (ckd == NULL) { fprintf(stderr, _("HHCDU012E DASD table entry not found for " "devtype 0x%2.2X\n"), devhdr.devtype); free (cif); return NULL; } dev->devtype = ckd->devt; snprintf(typname,64,"%4.4X",dev->devtype); dev->typname=typname; /* Makes HDL Happy */ } /* Set the device handlers */ dev->hnd = &ckddasd_device_hndinfo; /* Set the device number */ dev->devnum = ++nextnum; /* Build arguments for ckddasd_init_handler */ argv[0] = sfxname; argc++; if (sfname != NULL) { argv[1] = sfname; argc++; } /* Call the device handler initialization function */ rc = (dev->hnd->init)(dev, argc, argv); if (rc < 0) { fprintf (stderr, _("HHCDU013E CKD initialization failed for %s\n"), fname); free (cif); return NULL; } /* Call the device start exit */ if (dev->hnd->start) (dev->hnd->start) (dev); /* Set CIF fields */ cif->fname = fname; cif->fd = dev->fd; /* Extract the number of heads and the track size */ cif->heads = dev->ckdheads; cif->trksz = ((U32)(devhdr.trksize[3]) << 24) | ((U32)(devhdr.trksize[2]) << 16) | ((U32)(devhdr.trksize[1]) << 8) | (U32)(devhdr.trksize[0]); if (verbose) { fprintf (stderr, _("HHCDU014I %s heads=%d trklen=%d\n"), cif->fname, cif->heads, cif->trksz); } /* Indicate that the track buffer is empty */ cif->curcyl = -1; cif->curhead = -1; cif->trkmodif = 0; return cif; } /* end function open_ckd_image */ /*-------------------------------------------------------------------*/ /* Subroutine to close a CKD image file */ /* Input: */ /* cif -> CKD image file descriptor structure */ /* */ /* The track buffer is flushed and released, the CKD image file */ /* is closed, and the file descriptor structure is released. */ /* Return value is 0 if successful, -1 if error */ /*-------------------------------------------------------------------*/ DLL_EXPORT int close_ckd_image (CIFBLK *cif) { int rc; /* Return code */ int trk; /* Track number */ DEVBLK *dev; /* -> CKD device block */ BYTE unitstat; /* Unit status */ dev = &cif->devblk; /* Write the last track if modified */ if (cif->trkmodif) { if (verbose) /* Issue progress message */ fprintf (stdout, _("HHCDU015I Updating cyl %d head %d\n"), cif->curcyl, cif->curhead); trk = (cif->curcyl * cif->heads) + cif->curhead; rc = (dev->hnd->write)(dev, trk, 0, NULL, cif->trksz, &unitstat); if (rc < 0) { fprintf (stderr, _("HHCDU016E %s write track error: stat=%2.2X\n"), cif->fname, unitstat); } } /* Call the END exit */ if (dev->hnd->end) (dev->hnd->end) (dev); /* Close the CKD image file */ (dev->hnd->close)(dev); /* Release the file descriptor structure */ free (cif); return 0; } /* end function close_ckd_image */ /*-------------------------------------------------------------------*/ /* Subroutine to open a FBA image file */ /* Input: */ /* fname FBA image file name */ /* sfname xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx */ /* omode Open mode: O_RDONLY or O_RDWR */ /* dasdcopy xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx */ /* */ /* The FBA image file is opened, a track buffer is obtained, */ /* and a FBA image file descriptor structure is built. */ /* Return value is a pointer to the FBA image file descriptor */ /* structure if successful, or NULL if unsuccessful. */ /*-------------------------------------------------------------------*/ DLL_EXPORT CIFBLK* open_fba_image (char *fname, char *sfname, int omode, int dasdcopy) { int rc; /* Return code */ CIFBLK *cif; /* FBA image file descriptor */ DEVBLK *dev; /* FBA device block */ FBADEV *fba; /* FBA DASD table entry */ char *argv[2]; /* Arguments to */ int argc=0; /* device open */ /* Obtain storage for the file descriptor structure */ cif = (CIFBLK*) calloc (sizeof(CIFBLK), 1); if (cif == NULL) { fprintf (stderr, _("HHCDU017E Cannot obtain storage for device descriptor " "buffer: %s\n"), strerror(errno)); return NULL; } /* Initialize the devblk */ dev = &cif->devblk; if ((omode & O_RDWR) == 0) dev->ckdrdonly = 1; dev->batch = 1; dev->dasdcopy = dasdcopy; /* Set the device type */ fba = dasd_lookup (DASD_FBADEV, NULL, DEFAULT_FBA_TYPE, 0); if (fba == NULL) { fprintf(stderr, _("HHCDU018E DASD table entry not found for " "devtype 0x%2.2X\n"), DEFAULT_FBA_TYPE); free (cif); return NULL; } dev->devtype = fba->devt; /* Set the device handlers */ dev->hnd = &fbadasd_device_hndinfo; /* Set the device number */ dev->devnum = ++nextnum; /* Build arguments for fbadasd_init_handler */ argv[0] = fname; argc++; if (sfname != NULL) { argv[1] = sfname; argc++; } /* Call the device handler initialization function */ rc = (dev->hnd->init)(dev, argc, argv); if (rc < 0) { fprintf (stderr, _("HHCDU019E FBA initialization failed for %s\n"), fname); free (cif); return NULL; } /* Set CIF fields */ cif->fname = fname; cif->fd = dev->fd; /* Extract the number of sectors and the sector size */ cif->heads = dev->fbanumblk; cif->trksz = dev->fbablksiz; if (verbose) { fprintf (stderr, _("HHCDU020I %s sectors=%d size=%d\n"), cif->fname, cif->heads, cif->trksz); } /* Indicate that the track buffer is empty */ cif->curcyl = -1; cif->curhead = -1; cif->trkmodif = 0; return cif; } /* end function open_fba_image */ /*-------------------------------------------------------------------*/ /* Subroutine to build extent array for specified dataset */ /* Input: */ /* cif -> CKD image file descriptor structure */ /* dsnama -> Dataset name (ASCIIZ) */ /* Output: */ /* extent Extent array (up to 16 entries) */ /* noext Number of extents */ /* */ /* Return value is 0 if successful, or -1 if error */ /*-------------------------------------------------------------------*/ DLL_EXPORT int build_extent_array (CIFBLK *cif, char *dsnama, DSXTENT extent[], int *noext) { int rc; /* Return code */ int len; /* Record length */ int cyl; /* Cylinder number */ int head; /* Head number */ int rec; /* Record number */ BYTE *vol1data; /* -> Volume label */ FORMAT1_DSCB *f1dscb; /* -> Format 1 DSCB */ FORMAT3_DSCB *f3dscb; /* -> Format 3 DSCB */ FORMAT4_DSCB *f4dscb; /* -> Format 4 DSCB */ BYTE dsname[44]; /* Dataset name (EBCDIC) */ char volser[7]; /* Volume serial (ASCIIZ) */ /* Convert the dataset name to EBCDIC */ convert_to_ebcdic (dsname, sizeof(dsname), dsnama); /* Read the volume label */ rc = read_block (cif, 0, 0, 3, NULL, NULL, &vol1data, &len); if (rc < 0) return -1; if (rc > 0) { fprintf (stderr, _("HHCDU021E VOL1 record not found\n")); return -1; } /* Extract the volume serial and the CCHHR of the format 4 DSCB */ make_asciiz (volser, sizeof(volser), vol1data+4, 6); cyl = (vol1data[11] << 8) | vol1data[12]; head = (vol1data[13] << 8) | vol1data[14]; rec = vol1data[15]; if (verbose) { fprintf (stdout, _("HHCDU022I VOLSER=%s VTOC=%4.4X%4.4X%2.2X\n"), volser, cyl, head, rec); } /* Read the format 4 DSCB */ rc = read_block (cif, cyl, head, rec, (void *)&f4dscb, &len, NULL, NULL); if (rc < 0) return -1; if (rc > 0) { fprintf (stderr, _("HHCDU023E F4DSCB record not found\n")); return -1; } if (verbose) { fprintf (stdout, _("HHCDU023I VTOC start %2.2X%2.2X%2.2X%2.2X " "end %2.2X%2.2X%2.2X%2.2X\n"), f4dscb->ds4vtoce.xtbcyl[0], f4dscb->ds4vtoce.xtbcyl[1], f4dscb->ds4vtoce.xtbtrk[0], f4dscb->ds4vtoce.xtbtrk[1], f4dscb->ds4vtoce.xtecyl[0], f4dscb->ds4vtoce.xtecyl[1], f4dscb->ds4vtoce.xtetrk[0], f4dscb->ds4vtoce.xtetrk[1]); } /* Search for the requested dataset in the VTOC */ rc = search_key_equal (cif, dsname, sizeof(dsname), 1, &(f4dscb->ds4vtoce), &cyl, &head, &rec); if (rc < 0) return -1; if (rc > 0) { fprintf (stderr, _("HHCDU024E Dataset %s not found in VTOC\n"), dsnama); return -1; } if (verbose) { fprintf (stdout, _("HHCDU025I DSNAME=%s F1DSCB CCHHR=%4.4X%4.4X%2.2X\n"), dsnama, cyl, head, rec); } /* Read the format 1 DSCB */ rc = read_block (cif, cyl, head, rec, (void *)&f1dscb, &len, NULL, NULL); if (rc < 0) return -1; if (rc > 0) { fprintf (stderr, _("HHCDU026E F1DSCB record not found\n")); return -1; } /* Extract number of extents and first 3 extent descriptors */ *noext = f1dscb->ds1noepv; extent[0] = f1dscb->ds1ext1; extent[1] = f1dscb->ds1ext2; extent[2] = f1dscb->ds1ext3; /* Obtain additional extent descriptors */ if (f1dscb->ds1noepv > 3) { /* Read the format 3 DSCB */ cyl = (f1dscb->ds1ptrds[0] << 8) | f1dscb->ds1ptrds[1]; head = (f1dscb->ds1ptrds[2] << 8) | f1dscb->ds1ptrds[3]; rec = f1dscb->ds1ptrds[4]; rc = read_block (cif, cyl, head, rec, (void *)&f3dscb, &len, NULL, NULL); if (rc < 0) return -1; if (rc > 0) { fprintf (stderr, _("HHCDU027E F3DSCB record not found\n")); return -1; } /* Extract the next 13 extent descriptors */ extent[3] = f3dscb->ds3extnt[0]; extent[4] = f3dscb->ds3extnt[1]; extent[5] = f3dscb->ds3extnt[2]; extent[6] = f3dscb->ds3extnt[3]; extent[7] = f3dscb->ds3adext[0]; extent[8] = f3dscb->ds3adext[1]; extent[9] = f3dscb->ds3adext[2]; extent[10] = f3dscb->ds3adext[3]; extent[11] = f3dscb->ds3adext[4]; extent[12] = f3dscb->ds3adext[5]; extent[13] = f3dscb->ds3adext[6]; extent[14] = f3dscb->ds3adext[7]; extent[15] = f3dscb->ds3adext[8]; } return 0; } /* end function build_extent_array */ /*-------------------------------------------------------------------*/ /* Subroutine to calculate physical device track capacities */ /* Input: */ /* cif -> CKD image file descriptor structure */ /* used Number of bytes used so far on track, */ /* excluding home address and record 0 */ /* keylen Key length of proposed new record */ /* datalen Data length of proposed new record */ /* Output: */ /* newused Number of bytes used including proposed new record */ /* trkbaln Number of bytes remaining on track */ /* physlen Number of bytes on physical track (=ds4devtk) */ /* kbconst Overhead for non-last keyed block (=ds4devi) */ /* lbconst Overhead for last keyed block (=ds4devl) */ /* nkconst Overhead difference for non-keyed block (=ds4devk) */ /* devflag Device flag byte for VTOC (=ds4devfg) */ /* tolfact Device tolerance factor (=ds4devtl) */ /* maxdlen Maximum data length for non-keyed record 1 */ /* numrecs Number of records of specified length per track */ /* numhead Number of tracks per cylinder */ /* numcyls Number of cylinders per volume */ /* Note: */ /* A NULL address may be specified for any of the output */ /* fields if the output value is not required. */ /* The return value is 0 if the record will fit on the track, */ /* +1 if record will not fit on track, or -1 if unknown devtype */ /* Note: */ /* Although the virtual DASD image file contains no interrecord */ /* gaps, this subroutine performs its calculations taking into */ /* account the gaps that would exist on a real device, so that */ /* the track capacities of the real device are not exceeded. */ /*-------------------------------------------------------------------*/ DLL_EXPORT int capacity_calc (CIFBLK *cif, int used, int keylen, int datalen, int *newused, int *trkbaln, int *physlen, int *kbconst, int *lbconst, int *nkconst, BYTE*devflag, int *tolfact, int *maxdlen, int *numrecs, int *numhead, int *numcyls) { CKDDEV *ckd; /* -> CKD device table entry */ int heads; /* Number of tracks/cylinder */ int cyls; /* Number of cyls/volume */ int trklen; /* Physical track length */ int maxlen; /* Maximum data length */ int devi, devl, devk; /* Overhead fields for VTOC */ BYTE devfg; /* Flag field for VTOC */ int devtl; /* Tolerance field for VTOC */ int b1; /* Bytes used by new record when last record on track */ int b2; /* Bytes used by new record when not last on track */ int nrecs; /* Number of record/track */ int c, d1, d2, x; /* 23xx/3330/3350 factors */ int f1, f2, f3, f4, f5, f6; /* 3380/3390/9345 factors */ int fl1, fl2, int1, int2; /* 3380/3390/9345 calculation*/ ckd = cif->devblk.ckdtab; trklen = ckd->len; maxlen = ckd->r1; heads = ckd->heads; cyls = ckd->cyls; switch (ckd->formula) { case -2: /* 2311, 2314 */ c = ckd->f1; x = ckd->f2; d1 = ckd->f3; d2 = ckd->f4; b1 = keylen + datalen + (keylen == 0 ? 0 : c); b2 = ((keylen + datalen) * d1 / d2) + (keylen == 0 ? 0 : c) + x; nrecs = (trklen - b1)/b2 + 1; devi = c + x; devl = c; devk = c; devtl = d1 / (d2/512); devfg = 0x01; break; case -1: /* 3330, 3340, 3350 */ c = ckd->f1; x = ckd->f2; b1 = b2 = keylen + datalen + (keylen == 0 ? 0 : c) + x; nrecs = trklen / b2; devi = c + x; devl = c + x; devk = c; devtl = 512; devfg = 0x01; break; case 1: /* 3375, 3380 */ f1 = ckd->f1; f2 = ckd->f2; f3 = ckd->f3; fl1 = datalen + f2; fl2 = (keylen == 0 ? 0 : keylen + f3); fl1 = ((fl1 + f1 - 1) / f1) * f1; fl2 = ((fl2 + f1 - 1) / f1) * f1; b1 = b2 = fl1 + fl2; nrecs = trklen / b2; devi = 0; devl = 0; devk = 0; devtl = 0; devfg = 0x30; break; case 2: /* 3390, 9345 */ f1 = ckd->f1; f2 = ckd->f2; f3 = ckd->f3; f4 = ckd->f4; f5 = ckd->f5; f6 = ckd->f6; int1 = ((datalen + f6) + (f5*2-1)) / (f5*2); int2 = ((keylen + f6) + (f5*2-1)) / (f5*2); fl1 = (f1 * f2) + datalen + f6 + f4*int1; fl2 = (keylen == 0 ? 0 : (f1 * f3) + keylen + f6 + f4*int2); fl1 = ((fl1 + f1 - 1) / f1) * f1; fl2 = ((fl2 + f1 - 1) / f1) * f1; b1 = b2 = fl1 + fl2; nrecs = trklen / b2; devi = 0; devl = 0; devk = 0; devtl = 0; devfg = 0x30; break; default: return -1; } /* end switch(ckd->formula) */ /* Return VTOC fields and maximum data length */ if (physlen != NULL) *physlen = trklen; if (kbconst != NULL) *kbconst = devi; if (lbconst != NULL) *lbconst = devl; if (nkconst != NULL) *nkconst = devk; if (devflag != NULL) *devflag = devfg; if (tolfact != NULL) *tolfact = devtl; if (maxdlen != NULL) *maxdlen = maxlen; /* Return number of records per track */ if (numrecs != NULL) *numrecs = nrecs; /* Return number of tracks per cylinder and usual number of cylinders per volume */ if (numhead != NULL) *numhead = heads; if (numcyls != NULL) *numcyls = cyls; /* Return if record will not fit on the track */ if (used + b1 > trklen) return +1; /* Calculate number of bytes used and track balance */ if (newused != NULL) *newused = used + b2; if (trkbaln != NULL) *trkbaln = (used + b2 > trklen) ? 0 : trklen - used - b2; return 0; } /* end function capacity_calc */ /*-------------------------------------------------------------------*/ /* Subroutine to create a CKD DASD image file */ /* Input: */ /* fname DASD image file name */ /* fseqn Sequence number of this file (1=first) */ /* devtype Device type */ /* heads Number of heads per cylinder */ /* trksize DADS image track length */ /* buf -> Track image buffer */ /* start Starting cylinder number for this file */ /* end Ending cylinder number for this file */ /* volcyls Total number of cylinders on volume */ /* volser Volume serial number */ /* comp Compression algorithm for a compressed device. */ /* Will be 0xff if device is not to be compressed. */ /* dasdcopy xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx */ /* nullfmt xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx */ /* rawflag create raw image (skip special track 0 handling) */ /*-------------------------------------------------------------------*/ static int create_ckd_file (char *fname, int fseqn, U16 devtype, U32 heads, U32 trksize, BYTE *buf, U32 start, U32 end, U32 volcyls, char *volser, BYTE comp, int dasdcopy, int nullfmt, int rawflag) { int rc; /* Return code */ off_t rcoff; /* Return value from lseek() */ int fd; /* File descriptor */ int i; /* Loop counter */ int n; /* Loop delimiter */ CKDDASD_DEVHDR devhdr; /* Device header */ CCKDDASD_DEVHDR cdevhdr; /* Compressed device header */ CCKD_L1ENT *l1=NULL; /* -> Primary lookup table */ CCKD_L2ENT l2[256]; /* Secondary lookup table */ CKDDASD_TRKHDR *trkhdr; /* -> Track header */ CKDDASD_RECHDR *rechdr; /* -> Record header */ U32 cyl; /* Cylinder number */ U32 head; /* Head number */ int trk = 0; /* Track number */ int trks; /* Total number tracks */ BYTE r; /* Record number */ BYTE *pos; /* -> Next position in buffer*/ U32 cpos = 0; /* Offset into cckd file */ int len = 0; /* Length used in track */ int keylen = 4; /* Length of keys */ int ipl1len = 24; /* Length of IPL1 data */ int ipl2len = 144; /* Length of IPL2 data */ int vol1len = 80; /* Length of VOL1 data */ int rec0len = 8; /* Length of R0 data */ int fileseq; /* CKD header sequence number*/ int highcyl; /* CKD header high cyl number*/ int x=O_EXCL; /* Open option */ CKDDEV *ckdtab; /* -> CKD table entry */ char pathname[MAX_PATH]; /* file path in host format */ /* Locate the CKD dasd table entry */ ckdtab = dasd_lookup (DASD_CKDDEV, NULL, devtype, volcyls); if (ckdtab == NULL) { fprintf (stderr, _("HHCDU028E device type %4.4X not found in dasd table\n"), devtype); return -1; } /* Set file sequence number to zero if this is the only file */ if (fseqn == 1 && end + 1 == volcyls) fileseq = 0; else fileseq = fseqn; /* Set high cylinder number to zero if this is the last file */ if (end + 1 == volcyls) highcyl = 0; else highcyl = end; cyl = end - start + 1; /* Special processing for ckd and dasdcopy */ if (comp == 0xFF && dasdcopy) { highcyl = end; if (end + 1 == volcyls) fileseq = 0xff; } trks = volcyls * heads; /* if `dasdcopy' > 1 then we can replace the existing file */ if (dasdcopy > 1) x = 0; /* Create the DASD image file */ hostpath(pathname, fname, sizeof(pathname)); fd = open (pathname, O_WRONLY | O_CREAT | x | O_BINARY, S_IRUSR | S_IWUSR | S_IRGRP); if (fd < 0) { fprintf (stderr, _("HHCDU028E %s open error: %s\n"), fname, strerror(errno)); return -1; } /* Create the device header */ memset(&devhdr, 0, CKDDASD_DEVHDR_SIZE); if (comp == 0xff) memcpy(devhdr.devid, "CKD_P370", 8); else memcpy(devhdr.devid, "CKD_C370", 8); devhdr.heads[3] = (heads >> 24) & 0xFF; devhdr.heads[2] = (heads >> 16) & 0xFF; devhdr.heads[1] = (heads >> 8) & 0xFF; devhdr.heads[0] = heads & 0xFF; devhdr.trksize[3] = (trksize >> 24) & 0xFF; devhdr.trksize[2] = (trksize >> 16) & 0xFF; devhdr.trksize[1] = (trksize >> 8) & 0xFF; devhdr.trksize[0] = trksize & 0xFF; devhdr.devtype = devtype & 0xFF; devhdr.fileseq = fileseq; devhdr.highcyl[1] = (highcyl >> 8) & 0xFF; devhdr.highcyl[0] = highcyl & 0xFF; /* Write the device header */ rc = write (fd, &devhdr, CKDDASD_DEVHDR_SIZE); if (rc < (int)CKDDASD_DEVHDR_SIZE) { fprintf (stderr, _("HHCDU029E %s device header write error: %s\n"), fname, errno ? strerror(errno) : "incomplete"); return -1; } /* Build a compressed CKD file */ if (comp != 0xff) { /* Create the compressed device header */ memset(&cdevhdr, 0, CCKDDASD_DEVHDR_SIZE); cdevhdr.vrm[0] = CCKD_VERSION; cdevhdr.vrm[1] = CCKD_RELEASE; cdevhdr.vrm[2] = CCKD_MODLVL; if (cckd_endian()) cdevhdr.options |= CCKD_BIGENDIAN; cdevhdr.options |= (CCKD_ORDWR | CCKD_NOFUDGE); cdevhdr.numl1tab = (volcyls * heads + 255) / 256; cdevhdr.numl2tab = 256; cdevhdr.cyls[3] = (volcyls >> 24) & 0xFF; cdevhdr.cyls[2] = (volcyls >> 16) & 0xFF; cdevhdr.cyls[1] = (volcyls >> 8) & 0xFF; cdevhdr.cyls[0] = volcyls & 0xFF; cdevhdr.compress = comp; cdevhdr.compress_parm = -1; cdevhdr.nullfmt = nullfmt; /* Write the compressed device header */ rc = write (fd, &cdevhdr, CCKDDASD_DEVHDR_SIZE); if (rc < (int)CCKDDASD_DEVHDR_SIZE) { fprintf (stderr, _("HHCDU030E %s compressed device header " "write error: %s\n"), fname, errno ? strerror(errno) : "incomplete"); return -1; } /* Create the primary lookup table */ l1 = calloc (cdevhdr.numl1tab, CCKD_L1ENT_SIZE); if (l1 == NULL) { fprintf (stderr, _("HHCDU031E Cannot obtain l1tab buffer: %s\n"), strerror(errno)); return -1; } l1[0] = CCKD_L1TAB_POS + cdevhdr.numl1tab * CCKD_L1ENT_SIZE; /* Write the primary lookup table */ rc = write (fd, l1, cdevhdr.numl1tab * CCKD_L1ENT_SIZE); if (rc < (int)(cdevhdr.numl1tab * CCKD_L1ENT_SIZE)) { fprintf (stderr, _("HHCDU032E %s primary lookup table " "write error: %s\n"), fname, errno ? strerror(errno) : "incomplete"); return -1; } /* Create the secondary lookup table */ memset (&l2, 0, CCKD_L2TAB_SIZE); /* Write the seondary lookup table */ rc = write (fd, &l2, CCKD_L2TAB_SIZE); if (rc < (int)CCKD_L2TAB_SIZE) { fprintf (stderr, _("HHCDU033E %s secondary lookup table " "write error: %s\n"), fname, errno ? strerror(errno) : "incomplete"); return -1; } cpos = l1[0] + CCKD_L2TAB_SIZE; } if (!dasdcopy) { /* Write each cylinder */ for (cyl = start; cyl <= end; cyl++) { /* Display progress message every 10 cylinders */ if (cyl && !(cyl % 10)) { #ifdef EXTERNALGUI if (extgui) fprintf (stderr, "CYL=%u\n", cyl); else #endif /*EXTERNALGUI*/ fprintf (stderr, "Writing cylinder %u\r", cyl); } for (head = 0; head < heads; head++) { /* Clear the track to zeroes */ memset (buf, 0, trksize); /* Build the track header */ trkhdr = (CKDDASD_TRKHDR*)buf; trkhdr->bin = 0; store_hw(&trkhdr->cyl, cyl); store_hw(&trkhdr->head, head); pos = buf + CKDDASD_TRKHDR_SIZE; /* Build record zero */ r = 0; rechdr = (CKDDASD_RECHDR*)pos; pos += CKDDASD_RECHDR_SIZE; store_hw(&rechdr->cyl, cyl); store_hw(&rechdr->head, head); rechdr->rec = r; rechdr->klen = 0; store_hw(&rechdr->dlen, rec0len); pos += rec0len; r++; /* Track 0 contains IPL records and volume label */ if (!rawflag && trk == 0) { /* Build the IPL1 record */ rechdr = (CKDDASD_RECHDR*)pos; pos += CKDDASD_RECHDR_SIZE; store_hw(&rechdr->cyl, cyl); store_hw(&rechdr->head, head); rechdr->rec = r; rechdr->klen = keylen; store_hw(&rechdr->dlen, ipl1len); r++; convert_to_ebcdic (pos, keylen, "IPL1"); pos += keylen; memcpy (pos, iplpsw, 8); memcpy (pos+8, iplccw1, 8); memcpy (pos+16, iplccw2, 8); pos += ipl1len; /* Build the IPL2 record */ rechdr = (CKDDASD_RECHDR*)pos; pos += CKDDASD_RECHDR_SIZE; store_hw(&rechdr->cyl, cyl); store_hw(&rechdr->head, head); rechdr->rec = r; rechdr->klen = keylen; store_hw(&rechdr->dlen, ipl2len); r++; convert_to_ebcdic (pos, keylen, "IPL2"); pos += keylen; pos += ipl2len; /* Build the VOL1 record */ rechdr = (CKDDASD_RECHDR*)pos; pos += CKDDASD_RECHDR_SIZE; store_hw(&rechdr->cyl, cyl); store_hw(&rechdr->head, head); rechdr->rec = r; rechdr->klen = keylen; store_hw(&rechdr->dlen, vol1len); r++; convert_to_ebcdic (pos, keylen, "VOL1"); pos += keylen; convert_to_ebcdic (pos, 4, "VOL1"); //VOL1 convert_to_ebcdic (pos+4, 6, volser); //volser pos[10] = 0x40; //security store_hw(pos+11,0); //vtoc CC store_hw(pos+13,1); //vtoc HH pos[15] = 0x01; //vtoc R memset(pos+16, 0x40, 21); //reserved convert_to_ebcdic (pos+37, 14, " HERCULES"); //ownerid memset(pos+51, 0x40, 29); //reserved pos += vol1len; /* 9 4096 data blocks for linux volume */ if (nullfmt == CKDDASD_NULLTRK_FMT2) { for (i = 0; i < 9; i++) { rechdr = (CKDDASD_RECHDR*)pos; pos += CKDDASD_RECHDR_SIZE; store_hw(&rechdr->cyl, cyl); store_hw(&rechdr->head, head); rechdr->rec = r; rechdr->klen = 0; store_hw(&rechdr->dlen, 4096); pos += 4096; r++; } } } /* end if(trk == 0) */ /* Track 1 for linux contains an empty VTOC */ else if (trk == 1 && nullfmt == CKDDASD_NULLTRK_FMT2) { /* build format 4 dscb */ rechdr = (CKDDASD_RECHDR*)pos; pos += CKDDASD_RECHDR_SIZE; /* track 1 record 1 count */ store_hw(&rechdr->cyl, cyl); store_hw(&rechdr->head, head); rechdr->rec = r; rechdr->klen = 44; store_hw(&rechdr->dlen, 96); r++; /* track 1 record 1 key */ memset (pos, 0x04, 44); pos += 44; /* track 1 record 1 data */ memset (pos, 0, 96); pos[0] = 0xf4; // DS4IDFMT store_hw(pos + 6, 10); // DS4DSREC pos[14] = trks > 65535 ? 0xa0 : 0; // DS4VTOCI pos[15] = 1; // DS4NOEXT store_hw(pos+18, volcyls); // DS4DSCYL store_hw(pos+20, heads); // DS4DSTRK store_hw(pos+22, ckdtab->len); // DS4DEVTK pos[27] = 0x30; // DS4DEVFG pos[30] = 0x0c; // DS4DEVDT pos[61] = 0x01; // DS4VTOCE + 00 pos[66] = 0x01; // DS4VTOCE + 05 pos[70] = 0x01; // DS4VTOCE + 09 pos[81] = trks > 65535 ? 7 : 0; // DS4EFLVL pos[85] = trks > 65535 ? 1 : 0; // DS4EFPTR + 03 pos[86] = trks > 65535 ? 3 : 0; // DS4EFPTR + 04 pos += 96; /* build format 5 dscb */ rechdr = (CKDDASD_RECHDR*)pos; pos += CKDDASD_RECHDR_SIZE; /* track 1 record 1 count */ store_hw(&rechdr->cyl, cyl); store_hw(&rechdr->head, head); rechdr->rec = r; rechdr->klen = 44; store_hw(&rechdr->dlen, 96); r++; /* track 1 record 2 key */ memset (pos, 0x05, 4); // DS5KEYID memset (pos+4, 0, 40); if (trks <= 65535) { store_hw(pos+4, 2); // DS5AVEXT + 00 store_hw(pos+6, volcyls - 1); // DS5AVEXT + 02 pos[8] = heads - 2; // DS5AVEXT + 04 } pos += 44; /* track 1 record 2 data */ memset (pos, 0, 96); pos[0] = 0xf5; // DS5FMTID pos += 96; /* build format 7 dscb */ if (trks > 65535) { rechdr = (CKDDASD_RECHDR*)pos; pos += CKDDASD_RECHDR_SIZE; /* track 1 record 3 count */ store_hw(&rechdr->cyl, cyl); store_hw(&rechdr->head, head); rechdr->rec = r; rechdr->klen = 44; store_hw(&rechdr->dlen, 96); r++; /* track 1 record 2 key */ memset (pos, 0x07, 4); // DS7KEYID memset (pos+4, 0, 40); store_fw(pos+4, 2); // DS7EXTNT + 00 store_fw(pos+8, trks - 1); // DS7EXTNT + 04 pos += 44; /* track 1 record 2 data */ memset (pos, 0, 96); pos[0] = 0xf7; // DS7FMTID pos += 96; } n = 12 - r + 1; for (i = 0; i < n; i++) { rechdr = (CKDDASD_RECHDR*)pos; pos += CKDDASD_RECHDR_SIZE; store_hw(&rechdr->cyl, cyl); store_hw(&rechdr->head, head); rechdr->rec = r; rechdr->klen = 44; store_hw(&rechdr->dlen, 96); pos += 140; r++; } } /* Specific null track formatting */ else if (nullfmt == CKDDASD_NULLTRK_FMT0) { rechdr = (CKDDASD_RECHDR*)pos; pos += CKDDASD_RECHDR_SIZE; store_hw(&rechdr->cyl, cyl); store_hw(&rechdr->head, head); rechdr->rec = r; rechdr->klen = 0; store_hw(&rechdr->dlen, 0); r++; } else if (nullfmt == CKDDASD_NULLTRK_FMT2) { /* Other linux tracks have 12 4096 data records */ for (i = 0; i < 12; i++) { rechdr = (CKDDASD_RECHDR*)pos; pos += CKDDASD_RECHDR_SIZE; store_hw(&rechdr->cyl, cyl); store_hw(&rechdr->head, head); rechdr->rec = r; rechdr->klen = 0; store_hw(&rechdr->dlen, 4096); pos += 4096; r++; } } /* End-of-track marker */ memcpy (pos, eighthexFF, 8); pos += 8; /* Calculate length to write */ if (comp == 0xff) len = (int)trksize; else { len = (int)(pos - buf); l2[trk].pos = cpos; l2[trk].len = l2[trk].size = len; cpos += len; } /* Write the track to the file */ rc = write (fd, buf, len); if (rc != len) { fprintf (stderr, _("HHCDU035E %s cylinder %u head %u " "write error: %s\n"), fname, cyl, head, errno ? strerror(errno) : "incomplete"); return -1; } /* Exit if compressed disk and current track is 1 */ if (comp != 0xff && trk == 1) break; trk++; } /* end for(head) */ /* Exit if compressed disk */ if (comp != 0xff) break; } /* end for(cyl) */ } /* `dasdcopy' bit is off */ else cyl = end + 1; /* Complete building the compressed file */ if (comp != 0xff) { cdevhdr.size = cdevhdr.used = cpos; /* Rewrite the compressed device header */ rcoff = lseek (fd, CKDDASD_DEVHDR_SIZE, SEEK_SET); if (rcoff == -1) { fprintf (stderr, _("HHCDU036E %s compressed device header " "lseek error: %s\n"), fname, strerror(errno)); return -1; } rc = write (fd, &cdevhdr, CCKDDASD_DEVHDR_SIZE); if (rc < (int)CCKDDASD_DEVHDR_SIZE) { fprintf (stderr, _("HHCDU037E %s compressed device header " "write error: %s\n"), fname, errno ? strerror(errno) : "incomplete"); return -1; } /* Rewrite the secondary lookup table */ rcoff = lseek (fd, (off_t)l1[0], SEEK_SET); if (rcoff == -1) { fprintf (stderr, _("HHCDU038E %s secondary lookup table " "lseek error: %s\n"), fname, strerror(errno)); return -1; } rc = write (fd, &l2, CCKD_L2TAB_SIZE); if (rc < (int)CCKD_L2TAB_SIZE) { fprintf (stderr, _("HHCDU039E %s secondary lookup table " "write error: %s\n"), fname, errno ? strerror(errno) : "incomplete"); return -1; } rc = ftruncate(fd, (off_t)cdevhdr.size); free (l1); cyl = volcyls; } /* Close the DASD image file */ rc = close (fd); if (rc < 0) { fprintf (stderr, _("HHCDU040E %s close error: %s\n"), fname, strerror(errno)); return -1; } /* Display completion message */ fprintf (stderr, _("HHCDU041I %u cylinders successfully written to file %s\n"), cyl - start, fname); return 0; } /* end function create_ckd_file */ /*-------------------------------------------------------------------*/ /* Subroutine to create a CKD DASD image */ /* Input: */ /* fname DASD image file name */ /* devtype Device type */ /* heads Number of heads per cylinder */ /* maxdlen Maximum R1 record data length */ /* volcyls Total number of cylinders on volume */ /* volser Volume serial number */ /* comp Compression algorithm for a compressed device. */ /* Will be 0xff if device is not to be compressed. */ /* lfs build large (uncompressed) file (if supported) */ /* dasdcopy xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx */ /* nullfmt xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx */ /* rawflag create raw image (skip special track 0 handling) */ /* */ /* If the total number of cylinders exceeds the capacity of a 2GB */ /* file, then multiple CKD image files will be created, with the */ /* suffix _1, _2, etc suffixed to the specified file name. */ /* Otherwise a single file is created without a suffix. */ /*-------------------------------------------------------------------*/ DLL_EXPORT int create_ckd (char *fname, U16 devtype, U32 heads, U32 maxdlen, U32 volcyls, char *volser, BYTE comp, int lfs, int dasdcopy, int nullfmt, int rawflag) { int i; /* Array subscript */ int rc; /* Return code */ char *s; /* String pointer */ int fileseq; /* File sequence number */ char sfname[260]; /* Suffixed name of this file*/ char *suffix; /* -> Suffix character */ U32 endcyl; /* Last cylinder of this file*/ U32 cyl; /* Cylinder number */ U32 cylsize; /* Cylinder size in bytes */ BYTE *buf; /* -> Track data buffer */ U32 mincyls; /* Minimum cylinder count */ U32 maxcyls; /* Maximum cylinder count */ U32 maxcpif; /* Maximum number of cylinders in each CKD image file */ int rec0len = 8; /* Length of R0 data */ U32 trksize; /* DASD image track length */ /* Compute the DASD image track length */ trksize = sizeof(CKDDASD_TRKHDR) + sizeof(CKDDASD_RECHDR) + rec0len + sizeof(CKDDASD_RECHDR) + maxdlen + sizeof(eighthexFF); trksize = ROUND_UP(trksize,512); /* Compute minimum and maximum number of cylinders */ cylsize = trksize * heads; mincyls = 1; if (comp == 0xff && !lfs) { maxcpif = (0x7fffffff - CKDDASD_DEVHDR_SIZE + 1) / cylsize; maxcyls = maxcpif * CKD_MAXFILES; } else maxcpif = maxcyls = volcyls; if (maxcyls > 65536) maxcyls = 65536; /* Check for valid number of cylinders */ if (volcyls < mincyls || volcyls > maxcyls) { fprintf (stderr, _("HHCDU042E Cylinder count %u is outside range %u-%u\n"), volcyls, mincyls, maxcyls); return -1; } /* Obtain track data buffer */ buf = malloc(trksize); if (buf == NULL) { fprintf (stderr, _("HHCDU043E Cannot obtain track buffer: %s\n"), strerror(errno)); return -1; } /* Display progress message */ fprintf (stderr, _("HHCDU044I Creating %4.4X volume %s: %u cyls, " "%u trks/cyl, %u bytes/track\n"), devtype, rawflag ? "" : volser, volcyls, heads, trksize); /* Copy the unsuffixed DASD image file name */ strcpy (sfname, fname); suffix = NULL; /* Create the suffixed file name if volume will exceed 2GB */ if (volcyls > maxcpif) { /* Look for last slash marking end of directory name */ s = strrchr (fname, '/'); if (s == NULL) s = fname; /* Insert suffix before first dot in file name, or append suffix to file name if there is no dot. If the filename already has a place for the suffix then use that. */ s = strchr (s, '.'); if (s != NULL) { i = s - fname; if (i > 2 && fname[i-2] == '_') suffix = sfname + i - 1; else { strcpy (sfname + i, "_1"); strcat (sfname, fname + i); suffix = sfname + i + 1; } } else { if (strlen(sfname) < 2 || sfname[strlen(sfname)-2] == '_') strcat (sfname, "_1"); suffix = sfname + strlen(sfname) - 1; } } /* Create the DASD image files */ for (cyl = 0, fileseq = 1; cyl < volcyls; cyl += maxcpif, fileseq++) { /* Insert the file sequence number in the file name */ if (suffix) *suffix = '0' + fileseq; /* Calculate the ending cylinder for this file */ if (cyl + maxcpif < volcyls) endcyl = cyl + maxcpif - 1; else endcyl = volcyls - 1; /* Create a CKD DASD image file */ rc = create_ckd_file (sfname, fileseq, devtype, heads, trksize, buf, cyl, endcyl, volcyls, volser, comp, dasdcopy, nullfmt, rawflag); if (rc < 0) return -1; } /* Release data buffer */ free (buf); return 0; } /* end function create_ckd */ /*-------------------------------------------------------------------*/ /* Subroutine to create an FBA DASD image file */ /* Input: */ /* fname DASD image file name */ /* devtype Device type */ /* sectsz Sector size */ /* sectors Number of sectors */ /* volser Volume serial number */ /* comp Compression algorithm for a compressed device. */ /* Will be 0xff if device is not to be compressed. */ /* lfs build large (uncompressed) file (if supported) */ /* dasdcopy xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx */ /* rawflag create raw image (skip sector 1 VOL1 processing) */ /*-------------------------------------------------------------------*/ DLL_EXPORT int create_fba (char *fname, U16 devtype, U32 sectsz, U32 sectors, char *volser, BYTE comp, int lfs, int dasdcopy, int rawflag) { int rc; /* Return code */ int fd; /* File descriptor */ U32 sectnum; /* Sector number */ BYTE *buf; /* -> Sector data buffer */ U32 minsect; /* Minimum sector count */ U32 maxsect; /* Maximum sector count */ int x=O_EXCL; /* Open option */ char pathname[MAX_PATH]; /* file path in host format */ /* Special processing for compressed fba */ if (comp != 0xff) { rc = create_compressed_fba (fname, devtype, sectsz, sectors, volser, comp, lfs, dasdcopy, rawflag); return rc; } /* Compute minimum and maximum number of sectors */ minsect = 64; maxsect = 0x80000000 / sectsz; /* Check for valid number of sectors */ if (sectors < minsect || (!lfs && sectors > maxsect)) { fprintf (stderr, _("HHCDU045E Sector count %u is outside range %u-%u\n"), sectors, minsect, maxsect); return -1; } /* Obtain sector data buffer */ buf = malloc(sectsz); if (buf == NULL) { fprintf (stderr, _("HHCDU046E Cannot obtain sector buffer: %s\n"), strerror(errno)); return -1; } /* Display progress message */ fprintf (stderr, _("HHCDU047I Creating %4.4X volume %s: " "%u sectors, %u bytes/sector\n"), devtype, rawflag ? "" : volser, sectors, sectsz); /* if `dasdcopy' > 1 then we can replace the existing file */ if (dasdcopy > 1) x = 0; /* Create the DASD image file */ hostpath(pathname, fname, sizeof(pathname)); fd = open (pathname, O_WRONLY | O_CREAT | x | O_BINARY, S_IRUSR | S_IWUSR | S_IRGRP); if (fd < 0) { fprintf (stderr, _("HHCDU048I %s open error: %s\n"), fname, strerror(errno)); return -1; } /* If the `dasdcopy' bit is on then simply allocate the space */ if (dasdcopy) { off_t sz = sectors * sectsz; rc = ftruncate (fd, sz); if (rc < 0) { fprintf (stderr, _("HHCDU049E %s dasdcopy ftruncate error: %s\n"), fname, strerror(errno)); return -1; } } /* Write each sector */ else { for (sectnum = 0; sectnum < sectors; sectnum++) { /* Clear the sector to zeroes */ memset (buf, 0, sectsz); /* Sector 1 contains the volume label */ if (!rawflag && sectnum == 1) { convert_to_ebcdic (buf, 4, "VOL1"); convert_to_ebcdic (buf+4, 6, volser); } /* end if(sectnum==1) */ /* Display progress message every 100 sectors */ if ((sectnum % 100) == 0) #ifdef EXTERNALGUI { if (extgui) fprintf (stderr, "BLK=%u\n", sectnum); else fprintf (stderr, "Writing sector %u\r", sectnum); } #else /*!EXTERNALGUI*/ fprintf (stderr, "Writing sector %u\r", sectnum); #endif /*EXTERNALGUI*/ /* Write the sector to the file */ rc = write (fd, buf, sectsz); if (rc < (int)sectsz) { fprintf (stderr, _("HHCDU050E %s sector %u write error: %s\n"), fname, sectnum, errno ? strerror(errno) : "incomplete"); return -1; } } /* end for(sectnum) */ } /* `dasdcopy' bit is off */ /* Close the DASD image file */ rc = close (fd); if (rc < 0) { fprintf (stderr, _("HHCDU051E %s close error: %s\n"), fname, strerror(errno)); return -1; } /* Release data buffer */ free (buf); /* Display completion message */ fprintf (stderr, _("HHCDU052I %u sectors successfully written to file %s\n"), sectors, fname); return 0; } /* end function create_fba */ /*-------------------------------------------------------------------*/ /* Subroutine to create a compressed FBA DASD image file */ /* Input: */ /* fname DASD image file name */ /* devtype Device type */ /* sectsz Sector size */ /* sectors Number of sectors */ /* volser Volume serial number */ /* comp Compression algorithm for a compressed device. */ /* lfs build large (uncompressed) file (if supported) */ /* dasdcopy xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx */ /* rawflag create raw image (skip sector 1 VOL1 processing) */ /*-------------------------------------------------------------------*/ int create_compressed_fba (char *fname, U16 devtype, U32 sectsz, U32 sectors, char *volser, BYTE comp, int lfs, int dasdcopy, int rawflag) { int rc; /* Return code */ off_t rcoff; /* Return value from lseek() */ int fd; /* File descriptor */ CKDDASD_DEVHDR devhdr; /* Device header */ CCKDDASD_DEVHDR cdevhdr; /* Compressed device header */ int blkgrps; /* Number block groups */ int numl1tab, l1tabsz; /* Level 1 entries, size */ CCKD_L1ENT *l1; /* Level 1 table pointer */ CCKD_L2ENT l2[256]; /* Level 2 table */ unsigned long len2; /* Compressed buffer length */ BYTE buf2[256]; /* Compressed buffer */ BYTE buf[65536]; /* Buffer */ int x=O_EXCL; /* Open option */ char pathname[MAX_PATH]; /* file path in host format */ UNREFERENCED(lfs); /* Calculate the size of the level 1 table */ blkgrps = (sectors / CFBA_BLOCK_NUM) + 1; numl1tab = (blkgrps + 255) / 256; l1tabsz = numl1tab * CCKD_L1ENT_SIZE; if (l1tabsz > 65536) { fprintf (stderr, _("HHCDU053E File size too large: %" I64_FMT "ud [%d]\n"), (U64)(sectors * sectsz), numl1tab); return -1; } /* if `dasdcopy' > 1 then we can replace the existing file */ if (dasdcopy > 1) x = 0; /* Create the DASD image file */ hostpath(pathname, fname, sizeof(pathname)); fd = open (pathname, O_WRONLY | O_CREAT | x | O_BINARY, S_IRUSR | S_IWUSR | S_IRGRP); if (fd < 0) { fprintf (stderr, _("HHCDU054E %s open error: %s\n"), fname, strerror(errno)); return -1; } /* Display progress message */ fprintf (stderr, _("HHCDU055I Creating %4.4X compressed volume %s: " "%u sectors, %u bytes/sector\n"), devtype, rawflag ? "" : volser, sectors, sectsz); /* Write the device header */ memset (&devhdr, 0, CKDDASD_DEVHDR_SIZE); memcpy (&devhdr.devid, "FBA_C370", 8); rc = write (fd, &devhdr, CKDDASD_DEVHDR_SIZE); if (rc < (int)CKDDASD_DEVHDR_SIZE) { fprintf (stderr, _("HHCDU056E %s devhdr write error: %s\n"), fname, errno ? strerror(errno) : "incomplete"); return -1; } /* Write the compressed device header */ memset (&cdevhdr, 0, CCKDDASD_DEVHDR_SIZE); cdevhdr.vrm[0] = CCKD_VERSION; cdevhdr.vrm[1] = CCKD_RELEASE; cdevhdr.vrm[2] = CCKD_MODLVL; if (cckd_endian()) cdevhdr.options |= CCKD_BIGENDIAN; cdevhdr.options |= (CCKD_ORDWR | CCKD_NOFUDGE); cdevhdr.numl1tab = numl1tab; cdevhdr.numl2tab = 256; cdevhdr.cyls[3] = (sectors >> 24) & 0xFF; cdevhdr.cyls[2] = (sectors >> 16) & 0xFF; cdevhdr.cyls[1] = (sectors >> 8) & 0xFF; cdevhdr.cyls[0] = sectors & 0xFF; cdevhdr.compress = comp; cdevhdr.compress_parm = -1; rc = write (fd, &cdevhdr, CCKDDASD_DEVHDR_SIZE); if (rc < (int)CCKDDASD_DEVHDR_SIZE) { fprintf (stderr, _("HHCDU057E %s cdevhdr write error: %s\n"), fname, errno ? strerror(errno) : "incomplete"); return -1; } /* Write the level 1 table */ l1 = (CCKD_L1ENT *)&buf; memset (l1, 0, l1tabsz); l1[0] = CKDDASD_DEVHDR_SIZE + CCKDDASD_DEVHDR_SIZE + l1tabsz; rc = write (fd, l1, l1tabsz); if (rc < l1tabsz) { fprintf (stderr, _("HHCDU058E %s l1tab write error: %s\n"), fname, errno ? strerror(errno) : "incomplete"); return -1; } /* Write the 1st level 2 table */ memset (&l2, 0, CCKD_L2TAB_SIZE); l2[0].pos = CKDDASD_DEVHDR_SIZE + CCKDDASD_DEVHDR_SIZE + l1tabsz + CCKD_L2TAB_SIZE; rc = write (fd, &l2, CCKD_L2TAB_SIZE); if (rc < (int)CCKD_L2TAB_SIZE) { fprintf (stderr, _("HHCDU059E %s l2tab write error: %s\n"), fname, errno ? strerror(errno) : "incomplete"); return -1; } /* Write the 1st block group */ memset (&buf, 0, CKDDASD_DEVHDR_SIZE + CFBA_BLOCK_SIZE); if (!rawflag) { convert_to_ebcdic (&buf[CKDDASD_TRKHDR_SIZE+sectsz], 4, "VOL1"); convert_to_ebcdic (&buf[CKDDASD_TRKHDR_SIZE+sectsz+4], 6, volser); } len2 = sizeof(buf2); #ifdef HAVE_LIBZ rc = compress2 (&buf2[0], &len2, &buf[CKDDASD_TRKHDR_SIZE], CFBA_BLOCK_SIZE, -1); if (comp && rc == Z_OK) { buf[0] = CCKD_COMPRESS_ZLIB; rc = write (fd, &buf, CKDDASD_TRKHDR_SIZE); if (rc < (int)CKDDASD_TRKHDR_SIZE) { fprintf (stderr, _("HHCDU060E %s block header write error: %s\n"), fname, errno ? strerror(errno) : "incomplete"); return -1; } rc = write (fd, &buf2, len2); if (rc < (int)len2) { fprintf (stderr, _("HHCDU061E %s block write error: %s\n"), fname, errno ? strerror(errno) : "incomplete"); return -1; } l2[0].len = l2[0].size = CKDDASD_TRKHDR_SIZE + len2; cdevhdr.size = cdevhdr.used = CKDDASD_DEVHDR_SIZE + CCKDDASD_DEVHDR_SIZE + l1tabsz + CCKD_L2TAB_SIZE + CKDDASD_TRKHDR_SIZE + len2; } else #endif // defined(HAVE_LIBZ) { rc = write (fd, &buf, CKDDASD_TRKHDR_SIZE + CFBA_BLOCK_SIZE); if (rc < (int)(CKDDASD_TRKHDR_SIZE + CFBA_BLOCK_SIZE)) { fprintf (stderr, _("HHCDU062E %s block write error: %s\n"), fname, errno ? strerror(errno) : "incomplete"); return -1; } l2[0].len = l2[0].size = CKDDASD_TRKHDR_SIZE + CFBA_BLOCK_SIZE; cdevhdr.size = cdevhdr.used = CKDDASD_DEVHDR_SIZE + CCKDDASD_DEVHDR_SIZE + l1tabsz + CCKD_L2TAB_SIZE + CKDDASD_TRKHDR_SIZE + CFBA_BLOCK_SIZE; } /* Re-write the compressed device header */ rcoff = lseek (fd, CKDDASD_DEVHDR_SIZE, SEEK_SET); if (rcoff < 0) { fprintf (stderr, _("HHCDU063E %s cdevhdr lseek error: %s\n"), fname, strerror(errno)); return -1; } rc = write (fd, &cdevhdr, CCKDDASD_DEVHDR_SIZE); if (rc < (int)CCKDDASD_DEVHDR_SIZE) { fprintf (stderr, _("HHCDU064E %s cdevhdr rewrite error: %s\n"), fname, errno ? strerror(errno) : "incomplete"); return -1; } /* Re-write the 1st level 2 table */ rcoff = lseek (fd, CKDDASD_DEVHDR_SIZE + CCKDDASD_DEVHDR_SIZE + l1tabsz, SEEK_SET); if (rcoff < 0) { fprintf (stderr, _("HHCDU065E %s l2tab lseek error: %s\n"), fname, strerror(errno)); return -1; } rc = write (fd, &l2, CCKD_L2TAB_SIZE); if (rc < (int)CCKD_L2TAB_SIZE) { fprintf (stderr, _("HHCDU066E %s l2tab rewrite error: %s\n"), fname, errno ? strerror(errno) : "incomplete"); return -1; } /* Close the DASD image file */ rc = close (fd); if (rc < 0) { fprintf (stderr, _("HHCDU067E %s close error: %s\n"), fname, strerror(errno)); return -1; } /* Display completion message */ fprintf (stderr, _("HHCDU068I %u sectors successfully written to file %s\n"), sectors, fname); return 0; } /* end function create_compressed_fba */ int get_verbose_util(void) { return verbose; } DLL_EXPORT void set_verbose_util(int v) { verbose = v; } hercules-3.07/dat.c000644 000765 000765 00000001457 11143760543 015672 0ustar00jmaynardjmaynard000000 000000 /* DAT.C */ /* z/Architecture support - (c) Copyright Jan Jaeger, 1999-2009 */ // $Id: dat.c 5125 2009-01-23 12:01:44Z bernard $ // // $Log$ // Revision 1.11 2007/06/23 00:04:08 ivan // Update copyright notices to include current year (2007) // // Revision 1.10 2006/12/08 09:43:20 jj // Add CVS message log // #include "hstdinc.h" #include "hercules.h" #if defined(OPTION_NO_INLINE_DAT) || defined(OPTION_NO_INLINE_LOGICAL) #define _DAT_C #include "opcode.h" #include "inline.h" #if !defined(_GEN_ARCH) #if defined(_ARCHMODE2) #define _GEN_ARCH _ARCHMODE2 #include "dat.c" #endif #if defined(_ARCHMODE3) #undef _GEN_ARCH #define _GEN_ARCH _ARCHMODE3 #include "dat.c" #endif #endif /*!defined(_GEN_ARCH)*/ #endif /*!defined(OPTION_NO_INLINE_DAT) || defined(OPTION_NO_INLINE_LOGICAL)*/ hercules-3.07/dat.h000644 000765 000765 00000274317 11321734033 015677 0ustar00jmaynardjmaynard000000 000000 /* DAT.H (c) Copyright Roger Bowler, 1999-2009 */ /* ESA/390 Dynamic Address Translation */ /* Interpretive Execution - (c) Copyright Jan Jaeger, 1999-2009 */ /* z/Architecture support - (c) Copyright Jan Jaeger, 1999-2009 */ // $Id: dat.h 5549 2009-12-16 16:50:50Z ivan $ /*-------------------------------------------------------------------*/ /* This module implements the DAT, ALET, and ASN translation */ /* functions of the ESA/390 architecture, described in the manual */ /* SA22-7201-04 ESA/390 Principles of Operation. The numbers in */ /* square brackets in the comments refer to sections in the manual. */ /*-------------------------------------------------------------------*/ /*-------------------------------------------------------------------*/ /* Additional credits: */ /* S/370 DAT support by Jay Maynard (as described in */ /* GA22-7000 System/370 Principles of Operation) */ /* Clear remainder of ASTE when ASF=0 - Jan Jaeger */ /* S/370 DAT support when running under SIE - Jan Jaeger */ /* ESAME DAT support by Roger Bowler (SA22-7832) */ /* ESAME ASN authorization and ALET translation - Roger Bowler */ /*-------------------------------------------------------------------*/ // $Log$ // Revision 1.112 2008/12/08 20:38:20 ivan // Fix SIE DAT Issue with ESA/390 Guest on z/Arch host with >2GB of storage // // Revision 1.111 2008/03/16 00:04:37 rbowler // Replace ACC_ARMODE by USE_ARMODE for LPTEA // // Revision 1.110 2008/03/15 23:41:16 rbowler // Correct end function comment for logical_to_main // // Revision 1.109 2008/01/25 00:50:18 gsmith // Fix invalidate_tlbe processing - Paul Leisy // // Revision 1.108 2007/08/31 10:01:01 ivan // Throw an addressing exception when a SIE host->guest DAT points beyond // addressable storage // // Revision 1.107 2007/06/23 00:04:08 ivan // Update copyright notices to include current year (2007) // // Revision 1.106 2007/06/06 22:14:57 gsmith // Fix SYNCHRONIZE_CPUS when numcpu > number of host processors - Greg // // Revision 1.105 2007/03/21 01:28:20 gsmith // Fix missed (acctype != ACC...) compares // // Revision 1.104 2007/03/20 23:46:15 gsmith // Don't update TLB if ACC_NOTLB // // Revision 1.103 2007/03/20 22:27:25 gsmith // Simplify some code in logical_to_main // // Revision 1.102 2007/03/20 22:23:32 gsmith // Redefine ACC_ and ACCTYPE_ macros // // Revision 1.101 2007/03/20 02:06:02 gsmith // Rename IS_MCDS macro to MULTIPLE_CONTROLLED_DATA_SPACE // // Revision 1.100 2007/03/18 18:47:43 gsmith // Simplify MULTIPLE_CONTROLLED_DATA_SPACE tests // // Revision 1.99 2007/03/18 00:41:53 gsmith // Clarify load_address_space_designator code // // Revision 1.98 2007/01/04 23:12:03 gsmith // remove thunk calls for program_interrupt // // Revision 1.97 2006/12/08 09:43:20 jj // Add CVS message log // #if !defined(OPTION_NO_INLINE_DAT) || defined(_DAT_C) #if defined(FEATURE_DUAL_ADDRESS_SPACE) /*-------------------------------------------------------------------*/ /* Translate ASN to produce address-space control parameters */ /* */ /* Input: */ /* asn Address space number to be translated */ /* regs Pointer to the CPU register context */ /* asteo Pointer to a word to receive real address of ASTE */ /* aste Pointer to 16-word area to receive a copy of the */ /* ASN second table entry associated with the ASN */ /* */ /* Output: */ /* If successful, the ASTE corresponding to the ASN value will */ /* be stored into the 16-word area pointed to by aste, and the */ /* return value is zero. Either 4 or 16 words will be stored */ /* depending on the value of the ASF control bit (CR0 bit 15). */ /* The real address of the ASTE will be stored into the word */ /* pointed to by asteo. */ /* */ /* If unsuccessful, the return value is a non-zero exception */ /* code indicating AFX-translation or ASX-translation error */ /* (this is to allow the LASP instruction to handle these */ /* exceptions by setting the condition code). */ /* */ /* A program check may be generated for addressing and ASN */ /* translation specification exceptions, in which case the */ /* function does not return. */ /*-------------------------------------------------------------------*/ _DAT_C_STATIC U16 ARCH_DEP(translate_asn) (U16 asn, REGS *regs, U32 *asteo, U32 aste[]) { U32 afte_addr; /* Address of AFTE */ U32 afte; /* ASN first table entry */ U32 aste_addr; /* Address of ASTE */ BYTE *aste_main; /* ASTE mainstor address */ int code; /* Exception code */ int numwords; /* ASTE size (4 or 16 words) */ int i; /* Array subscript */ /* [3.9.3.1] Use the AFX to obtain the real address of the AFTE */ afte_addr = (regs->CR(14) & CR14_AFTO) << 12; afte_addr += (asn & ASN_AFX) >> 4; /* Addressing exception if AFTE is outside main storage */ if (afte_addr > regs->mainlim) goto asn_addr_excp; /* Load the AFTE from main storage. All four bytes must be fetched concurrently as observed by other CPUs */ afte_addr = APPLY_PREFIXING (afte_addr, regs->PX); afte = ARCH_DEP(fetch_fullword_absolute) (afte_addr, regs); /* AFX translation exception if AFTE invalid bit is set */ if (afte & AFTE_INVALID) goto asn_afx_tran_excp; #if !defined(FEATURE_ESAME) /* ASN translation specification exception if reserved bits set */ if (!ASF_ENABLED(regs)) { if (afte & AFTE_RESV_0) goto asn_asn_tran_spec_excp; } else { if (afte & AFTE_RESV_1) goto asn_asn_tran_spec_excp; } #endif /*!defined(FEATURE_ESAME)*/ /* [3.9.3.2] Use AFTE and ASX to obtain real address of ASTE */ if (!ASF_ENABLED(regs)) { aste_addr = afte & AFTE_ASTO_0; aste_addr += (asn & ASN_ASX) << 4; numwords = 4; } else { aste_addr = afte & AFTE_ASTO_1; aste_addr += (asn & ASN_ASX) << 6; numwords = 16; } /* Ignore carry into bit position 0 of ASTO */ aste_addr &= 0x7FFFFFFF; /* Addressing exception if ASTE is outside main storage */ if (aste_addr > regs->mainlim) goto asn_addr_excp; /* Return the real address of the ASTE */ *asteo = aste_addr; /* Fetch the 16- or 64-byte ASN second table entry from real storage. Each fullword of the ASTE must be fetched concurrently as observed by other CPUs */ aste_addr = APPLY_PREFIXING (aste_addr, regs->PX); aste_main = FETCH_MAIN_ABSOLUTE(aste_addr, regs, numwords * 4); for (i = 0; i < numwords; i++) { aste[i] = fetch_fw(aste_main); aste_main += 4; } /* Clear remaining words if fewer than 16 words were loaded */ while (i < 16) aste[i++] = 0; /* Check the ASX invalid bit in the ASTE */ if (aste[0] & ASTE0_INVALID) goto asn_asx_tran_excp; #if !defined(FEATURE_ESAME) /* Check the reserved bits in first two words of ASTE */ if ((aste[0] & ASTE0_RESV) || (aste[1] & ASTE1_RESV) || ((aste[0] & ASTE0_BASE) #ifdef FEATURE_SUBSPACE_GROUP && !ASF_ENABLED(regs) #endif /*FEATURE_SUBSPACE_GROUP*/ )) goto asn_asn_tran_spec_excp; #endif /*!defined(FEATURE_ESAME)*/ return 0; /* Conditions which always cause program check */ asn_addr_excp: code = PGM_ADDRESSING_EXCEPTION; goto asn_prog_check; #if !defined(FEATURE_ESAME) asn_asn_tran_spec_excp: code = PGM_ASN_TRANSLATION_SPECIFICATION_EXCEPTION; goto asn_prog_check; #endif /*!defined(FEATURE_ESAME)*/ asn_prog_check: regs->program_interrupt (regs, code); /* Conditions which the caller may or may not program check */ asn_afx_tran_excp: regs->TEA = asn; code = PGM_AFX_TRANSLATION_EXCEPTION; return code; asn_asx_tran_excp: regs->TEA = asn; code = PGM_ASX_TRANSLATION_EXCEPTION; return code; } /* end function translate_asn */ #endif /*defined(FEATURE_DUAL_ADDRESS_SPACE)*/ #if defined(FEATURE_DUAL_ADDRESS_SPACE) /*-------------------------------------------------------------------*/ /* Perform ASN authorization process */ /* */ /* Input: */ /* ax Authorization index */ /* aste Pointer to 16-word area containing a copy of the */ /* ASN second table entry associated with the ASN */ /* atemask Specifies which authority bit to test in the ATE: */ /* ATE_PRIMARY (for PT instruction) */ /* ATE_SECONDARY (for PR, SSAR, and LASP instructions, */ /* and all access register translations) */ /* regs Pointer to the CPU register context */ /* */ /* Operation: */ /* The AX is used to select an entry in the authority table */ /* pointed to by the ASTE, and an authorization bit in the ATE */ /* is tested. For ATE_PRIMARY (X'80'), the P bit is tested. */ /* For ATE_SECONDARY (X'40'), the S bit is tested. */ /* Authorization is successful if the ATE falls within the */ /* authority table limit and the tested bit value is 1. */ /* */ /* Output: */ /* If authorization is successful, the return value is zero. */ /* If authorization is unsuccessful, the return value is 1. */ /* */ /* A program check may be generated for addressing exception */ /* if the authority table entry address is invalid, and in */ /* this case the function does not return. */ /*-------------------------------------------------------------------*/ _DAT_C_STATIC int ARCH_DEP(authorize_asn) (U16 ax, U32 aste[], int atemask, REGS *regs) { U32 ato; /* Authority table origin */ int atl; /* Authority table length */ BYTE ate; /* Authority table entry */ /* [3.10.3.1] Authority table lookup */ /* Isolate the authority table origin and length */ ato = aste[0] & ASTE0_ATO; atl = aste[1] & ASTE1_ATL; /* Authorization fails if AX is outside table */ if ((ax & 0xFFF0) > atl) return 1; /* Calculate the address of the byte in the authority table which contains the 2 bit entry for this AX */ ato += (ax >> 2); /* Ignore carry into bit position 0 */ ato &= 0x7FFFFFFF; /* Addressing exception if ATE is outside main storage */ if (ato > regs->mainlim) goto auth_addr_excp; /* Load the byte containing the authority table entry and shift the entry into the leftmost 2 bits */ ato = APPLY_PREFIXING (ato, regs->PX); SIE_TRANSLATE(&ato, ACCTYPE_SIE, regs); ate = regs->mainstor[ato]; ate <<= ((ax & 0x03)*2); /* Set the main storage reference bit */ STORAGE_KEY(ato, regs) |= STORKEY_REF; /* Authorization fails if the specified bit (either X'80' or X'40' of the 2 bit authority table entry) is zero */ if ((ate & atemask) == 0) return 1; /* Exit with successful return code */ return 0; /* Conditions which always cause program check */ auth_addr_excp: regs->program_interrupt (regs, PGM_ADDRESSING_EXCEPTION); return 1; } /* end function authorize_asn */ #endif /*defined(FEATURE_DUAL_ADDRESS_SPACE)*/ #if defined(FEATURE_ACCESS_REGISTERS) /*-------------------------------------------------------------------*/ /* Translate an ALET to produce the corresponding ASTE */ /* */ /* This routine performs both ordinary ART (as used by DAT when */ /* operating in access register mode, and by the TAR instruction), */ /* and special ART (as used by the BSG instruction). The caller */ /* is assumed to have already eliminated the special cases of ALET */ /* values 0 and 1 (which have different meanings depending on */ /* whether the caller is DAT, TAR, or BSG). */ /* */ /* Input: */ /* alet ALET value */ /* eax The authorization index (normally obtained from */ /* CR8; obtained from R2 for TAR; not used for BSG) */ /* acctype Type of access requested: READ, WRITE, instfetch, */ /* TAR, LRA, TPROT, or BSG */ /* regs Pointer to the CPU register context */ /* asteo Pointer to word to receive ASTE origin address */ /* aste Pointer to 16-word area to receive a copy of the */ /* ASN second table entry associated with the ALET */ /* */ /* Output: */ /* If successful, the ASTE is copied into the 16-word area, */ /* the real address of the ASTE is stored into the word pointed */ /* word pointed to by asteop, and the return value is zero; */ /* regs->dat.protect is set to 2 if the fetch-only bit */ /* in the ALE is set, otherwise it is set to zero. */ /* */ /* If unsuccessful, the return value is a non-zero exception */ /* code in the range X'0028' through X'002D' (this is to allow */ /* the TAR, LRA, and TPROT instructions to handle these */ /* exceptions by setting the condition code). */ /* regs->dat.xcode is also set to the exception code. */ /* */ /* A program check may be generated for addressing and ASN */ /* translation specification exceptions, in which case the */ /* function does not return. */ /*-------------------------------------------------------------------*/ _DAT_C_STATIC U16 ARCH_DEP(translate_alet) (U32 alet, U16 eax, int acctype, REGS *regs, U32 *asteo, U32 aste[]) { U32 cb; /* DUCT or PASTE address */ U32 ald; /* Access-list designation */ U32 alo; /* Access-list origin */ U32 all; /* Access-list length */ U32 ale[4]; /* Access-list entry */ U32 aste_addr; /* Real address of ASTE */ U32 abs; /* Absolute address */ BYTE *mn; /* Mainstor address */ int i; /* Array subscript */ regs->dat.protect = 0; /* [5.8.4.3] Check the reserved bits in the ALET */ if ( alet & ALET_RESV ) goto alet_spec_excp; /* [5.8.4.4] Obtain the effective access-list designation */ /* Obtain the real address of the control block containing the effective access-list designation. This is either the Primary ASTE or the DUCT */ cb = (alet & ALET_PRI_LIST) ? regs->CR(5) & CR5_PASTEO : regs->CR(2) & CR2_DUCTO; /* Addressing exception if outside main storage */ if (cb > regs->mainlim) goto alet_addr_excp; /* Load the effective access-list designation (ALD) from offset 16 in the control block. All four bytes must be fetched concurrently as observed by other CPUs. Note that the DUCT and the PASTE cannot cross a page boundary */ cb = APPLY_PREFIXING (cb, regs->PX); ald = ARCH_DEP(fetch_fullword_absolute) (cb+16, regs); /* [5.8.4.5] Access-list lookup */ /* Isolate the access-list origin and access-list length */ alo = ald & ALD_ALO; all = ald & ALD_ALL; /* Check that the ALEN does not exceed the ALL */ if (((alet & ALET_ALEN) >> ALD_ALL_SHIFT) > all) goto alen_tran_excp; /* Add the ALEN x 16 to the access list origin */ alo += (alet & ALET_ALEN) << 4; /* Addressing exception if outside main storage */ if (alo > regs->mainlim) goto alet_addr_excp; /* Fetch the 16-byte access list entry from absolute storage. Each fullword of the ALE must be fetched concurrently as observed by other CPUs */ alo = APPLY_PREFIXING (alo, regs->PX); mn = FETCH_MAIN_ABSOLUTE(alo, regs, 16); for (i = 0; i < 4; i++) { ale[i] = fetch_fw (mn); mn += 4; } /* Check the ALEN invalid bit in the ALE */ if (ale[0] & ALE0_INVALID) goto alen_tran_excp; /* For ordinary ART (but not for special ART), compare the ALE sequence number with the ALET */ if (!(acctype & ACC_SPECIAL_ART) && (ale[0] & ALE0_ALESN) != (alet & ALET_ALESN)) goto ale_seq_excp; /* [5.8.4.6] Locate the ASN-second-table entry */ aste_addr = ale[2] & ALE2_ASTE; /* Addressing exception if ASTE is outside main storage */ abs = APPLY_PREFIXING (aste_addr, regs->PX); if (abs > regs->mainlim) goto alet_addr_excp; mn = FETCH_MAIN_ABSOLUTE(abs, regs, 64); /* Fetch the 64-byte ASN second table entry from real storage. Each fullword of the ASTE must be fetched concurrently as observed by other CPUs. ASTE cannot cross a page boundary */ for (i = 0; i < 16; i++) { aste[i] = fetch_fw(mn); mn += 4; } /* Check the ASX invalid bit in the ASTE */ if (aste[0] & ASTE0_INVALID) goto aste_vald_excp; /* Compare the ASTE sequence number with the ALE */ if ((aste[5] & ASTE5_ASTESN) != (ale[3] & ALE3_ASTESN)) goto aste_seq_excp; /* [5.8.4.7] For ordinary ART (but not for special ART), authorize the use of the access-list entry */ if (!(acctype & ACC_SPECIAL_ART)) { /* If ALE private bit is zero, or the ALE AX equals the EAX, then authorization succeeds. Otherwise perform the extended authorization process. */ if ((ale[0] & ALE0_PRIVATE) && (ale[0] & ALE0_ALEAX) != eax) { #if !defined(FEATURE_ESAME) /* Check the reserved bits in first two words of ASTE */ if ((aste[0] & ASTE0_RESV) || (aste[1] & ASTE1_RESV) || ((aste[0] & ASTE0_BASE) #ifdef FEATURE_SUBSPACE_GROUP && !ASF_ENABLED(regs) #endif /*FEATURE_SUBSPACE_GROUP*/ )) goto alet_asn_tran_spec_excp; #endif /*!defined(FEATURE_ESAME)*/ /* Perform extended authorization */ if (ARCH_DEP(authorize_asn)(eax, aste, ATE_SECONDARY, regs) != 0) goto ext_auth_excp; } } /* end if(!ACCTYPE_BSG) */ /* [5.8.4.8] Check for access-list controlled protection */ if (ale[0] & ALE0_FETCHONLY) regs->dat.protect = 2; /* Return the ASTE origin address */ *asteo = aste_addr; return 0; /* Conditions which always cause program check, except when performing translation for the control panel */ alet_addr_excp: regs->dat.xcode = PGM_ADDRESSING_EXCEPTION; goto alet_prog_check; #if !defined(FEATURE_ESAME) alet_asn_tran_spec_excp: regs->dat.xcode = PGM_ASN_TRANSLATION_SPECIFICATION_EXCEPTION; goto alet_prog_check; #endif /*!defined(FEATURE_ESAME)*/ alet_prog_check: regs->program_interrupt (regs, regs->dat.xcode); /* Conditions which the caller may or may not program check */ alet_spec_excp: regs->dat.xcode = PGM_ALET_SPECIFICATION_EXCEPTION; return regs->dat.xcode; alen_tran_excp: regs->dat.xcode = PGM_ALEN_TRANSLATION_EXCEPTION; return regs->dat.xcode; ale_seq_excp: regs->dat.xcode = PGM_ALE_SEQUENCE_EXCEPTION; return regs->dat.xcode; aste_vald_excp: regs->dat.xcode = PGM_ASTE_VALIDITY_EXCEPTION; return regs->dat.xcode; aste_seq_excp: regs->dat.xcode = PGM_ASTE_SEQUENCE_EXCEPTION; return regs->dat.xcode; ext_auth_excp: regs->dat.xcode = PGM_EXTENDED_AUTHORITY_EXCEPTION; return regs->dat.xcode; } /* end function translate_alet */ #endif /*defined(FEATURE_ACCESS_REGISTERS)*/ #if defined(FEATURE_ACCESS_REGISTERS) /*-------------------------------------------------------------------*/ /* Purge the ART lookaside buffer */ /*-------------------------------------------------------------------*/ _DAT_C_STATIC void ARCH_DEP(purge_alb) (REGS *regs) { int i; for(i = 1; i < 16; i++) if(regs->aea_ar[i] >= CR_ALB_OFFSET && regs->aea_ar[i] != CR_ASD_REAL) regs->aea_ar[i] = 0; if(regs->host && regs->guestregs) for(i = 1; i < 16; i++) if(regs->guestregs->aea_ar[i] >= CR_ALB_OFFSET && regs->guestregs->aea_ar[i] != CR_ASD_REAL) regs->guestregs->aea_ar[i] = 0; } /* end function purge_alb */ /*-------------------------------------------------------------------*/ /* Purge the ART lookaside buffer for all CPUs */ /*-------------------------------------------------------------------*/ _DAT_C_STATIC void ARCH_DEP(purge_alb_all) () { int i; for (i = 0; i < MAX_CPU; i++) if (IS_CPU_ONLINE(i) && (sysblk.regs[i]->cpubit & sysblk.started_mask)) ARCH_DEP(purge_alb) (sysblk.regs[i]); } /* end function purge_alb_all */ #endif /*defined(FEATURE_ACCESS_REGISTERS)*/ /*-------------------------------------------------------------------*/ /* Determine effective ASCE or STD */ /* */ /* This routine returns either an address-space control element */ /* (for ESAME) or a segment table descriptor (for S/370 and ESA/390) */ /* loaded from control register 1, 7, or 13, or computed from the */ /* contents of an address register, together with an indication of */ /* the addressing mode (home, primary, secondary, or AR mode) */ /* which was used to determine the source of the ASCE or STD. */ /* */ /* Input: */ /* arn Access register number (0-15) to be used if the */ /* address-space control (PSW bits 16-17) indicates */ /* that ARMODE is the current translation mode. */ /* An access register number ORed with the special */ /* value USE_ARMODE forces this routine to use ARMODE */ /* regardless of the PSW address-space control setting. */ /* Access register 0 is treated as if it contained 0 */ /* and its actual contents are not examined. */ /* Alternatively the arn parameter may contain one */ /* of these special values (defined in hconsts.h): */ /* USE_PRIMARY_SPACE, USE_SECONDARY_SPACE, */ /* USE_HOME_SPACE, USE_REAL_ADDR to force the use of */ /* a specific translation mode instead of the mode */ /* indicated by the address-space control in the PSW. */ /* regs Pointer to the CPU register context */ /* acctype Type of access requested: READ, WRITE, INSTFETCH, */ /* LRA, IVSK, TPROT, STACK, PTE, LPTEA */ /* */ /* Output: */ /* regs->dat.asd = the selected ASCE or STD */ /* regs->dat.stid = TEA_ST_PRIMARY, TEA_ST_SECNDRY, */ /* TEA_ST_HOME, or TEA_ST_ARMODE indicates which */ /* address space was used to select the ASCE or STD. */ /* regs->dat.protect = 2 if in AR mode and access-list */ /* controlled protection is indicated by the ALE */ /* fetch-only bit; otherwise it remains unchanged. */ /* */ /* If an ALET translation error occurs, the return value */ /* is the exception code; otherwise the return value is zero, */ /* regs->dat.asd field contains the ASCE or STD, and */ /* regs->dat.stid is set to TEA_ST_PRIMARY, TEA_ST_SECNDRY, */ /* TEA_ST_HOME, or TEA_ST_ARMODE. */ /*-------------------------------------------------------------------*/ _DAT_C_STATIC U16 ARCH_DEP(load_address_space_designator) (int arn, REGS *regs, int acctype) { #if defined(FEATURE_ACCESS_REGISTERS) U32 alet; /* Access list entry token */ U32 asteo; /* Real address of ASTE */ U32 aste[16]; /* ASN second table entry */ U16 eax; /* Authorization index */ #else UNREFERENCED(acctype); #endif /*defined(FEATURE_ACCESS_REGISTERS)*/ switch(arn) { case USE_PRIMARY_SPACE: regs->dat.stid = TEA_ST_PRIMARY; regs->dat.asd = regs->CR(1); break; case USE_SECONDARY_SPACE: regs->dat.stid = TEA_ST_SECNDRY; regs->dat.asd = regs->CR(7); break; case USE_HOME_SPACE: regs->dat.stid = TEA_ST_HOME; regs->dat.asd = regs->CR(13); break; case USE_REAL_ADDR: regs->dat.stid = 0; regs->dat.asd = TLB_REAL_ASD; break; case USE_INST_SPACE: switch(regs->aea_ar[USE_INST_SPACE]) { case 1: regs->dat.stid = TEA_ST_PRIMARY; break; #if defined(FEATURE_LINKAGE_STACK) case 13: regs->dat.stid = TEA_ST_HOME; break; #endif default: regs->dat.stid = 0; } /* end switch(regs->aea_ar[USE_INST_SPACE]) */ regs->dat.asd = regs->CR(regs->aea_ar[USE_INST_SPACE]); break; default: #if defined(FEATURE_ACCESS_REGISTERS) if (ACCESS_REGISTER_MODE(®s->psw) || (SIE_ACTIVE(regs) && MULTIPLE_CONTROLLED_DATA_SPACE(regs->guestregs)) || (arn & USE_ARMODE) ) { /* Remove flags giving access register number 0-15 */ arn &= 0xF; /* [5.8.4.1] Select the access-list-entry token */ alet = (arn == 0) ? 0 : /* Guest ALET if XC guest in AR mode */ (SIE_ACTIVE(regs) && MULTIPLE_CONTROLLED_DATA_SPACE(regs->guestregs)) ? regs->guestregs->AR(arn) : /* If SIE host but not XC guest in AR mode then alet is 0 */ SIE_ACTIVE(regs) ? 0 : /* Otherwise alet is in the access register */ regs->AR(arn); /* Use the ALET to determine the segment table origin */ switch (alet) { case ALET_PRIMARY: /* [5.8.4.2] Obtain primary segment table designation */ regs->dat.stid = TEA_ST_PRIMARY; regs->dat.asd = regs->CR(1); break; case ALET_SECONDARY: /* [5.8.4.2] Obtain secondary segment table designation */ regs->dat.stid = TEA_ST_SECNDRY; regs->dat.asd = regs->CR(7); break; default: /* ALB Lookup */ if(regs->aea_ar[arn] >= CR_ALB_OFFSET && regs->aea_ar[arn] != CR_ASD_REAL) { regs->dat.asd = regs->CR(regs->aea_ar[arn]); regs->dat.protect = regs->aea_aleprot[arn]; regs->dat.stid = TEA_ST_ARMODE; } else { /* Extract the extended AX from CR8 bits 0-15 (32-47) */ eax = regs->CR_LHH(8); /* [5.8.4.3] Perform ALET translation to obtain ASTE */ if (ARCH_DEP(translate_alet) (alet, eax, acctype, regs, &asteo, aste)) /* Exit if ALET translation error */ return regs->dat.xcode; /* [5.8.4.9] Obtain the STD or ASCE from the ASTE */ regs->dat.asd = ASTE_AS_DESIGNATOR(aste); regs->dat.stid = TEA_ST_ARMODE; if(regs->dat.protect & 2) { #if defined(FEATURE_ESAME) regs->dat.asd ^= ASCE_RESV; regs->dat.asd |= ASCE_P; #else regs->dat.asd ^= STD_RESV; regs->dat.asd |= STD_PRIVATE; #endif } /* Update ALB */ regs->CR(CR_ALB_OFFSET + arn) = regs->dat.asd; regs->aea_ar[arn] = CR_ALB_OFFSET + arn; regs->aea_common[CR_ALB_OFFSET + arn] = (regs->dat.asd & ASD_PRIVATE) == 0; regs->aea_aleprot[arn] = regs->dat.protect & 2; } } /* end switch(alet) */ break; } /* end if(ACCESS_REGISTER_MODE) */ #endif /*defined(FEATURE_ACCESS_REGISTERS)*/ #if defined(FEATURE_DUAL_ADDRESS_SPACE) if (SECONDARY_SPACE_MODE(®s->psw)) { regs->dat.stid = TEA_ST_SECNDRY; regs->dat.asd = regs->CR(7); break; } #endif /* defined(FEATURE_DUAL_ADDRESS_SPACE) */ #if defined(FEATURE_LINKAGE_STACK) if (HOME_SPACE_MODE(®s->psw)) { regs->dat.stid = TEA_ST_HOME; regs->dat.asd = regs->CR(13); break; } #endif /* defined(FEATURE_LINKAGE_STACK) */ /* Primary space mode */ regs->dat.stid = TEA_ST_PRIMARY; regs->dat.asd = regs->CR(1); break; } /* switch(arn) */ return 0; } /* end function load_address_space_designator */ /*-------------------------------------------------------------------*/ /* Translate a virtual address to a real address */ /* */ /* Input: */ /* vaddr virtual address to be translated */ /* arn Access register number or special value (see */ /* load_address_space_designator function for a */ /* complete description of this parameter) */ /* regs Pointer to the CPU register context */ /* acctype Type of access requested: READ, WRITE, INSTFETCH, */ /* LRA, IVSK, TPROT, STACK, PTE, LPTEA */ /* */ /* Output: */ /* The return value is set to facilitate the setting of the */ /* condition code by the LRA instruction: */ /* 0 = Translation successful; real address field contains */ /* the real address corresponding to the virtual address */ /* supplied by the caller; exception code set to zero. */ /* 1 = Segment table entry invalid; real address field */ /* contains real address of segment table entry; */ /* exception code is set to X'0010'. */ /* 2 = Page table entry invalid; real address field contains */ /* real address of page table entry; exception code */ /* is set to X'0011'. */ /* 3 = Segment or page table length exceeded; real address */ /* field contains the real address of the entry that */ /* would have been fetched if length violation had not */ /* occurred; exception code is set to X'0010' or X'0011'. */ /* 4 = ALET translation error: real address field is not */ /* set; exception code is set to X'0028' through X'002D'. */ /* ASCE-type or region-translation error: real address */ /* is not set; exception code is X'0038' through X'003B'. */ /* The LRA instruction converts this to condition code 3. */ /* */ /* For ACCTYPE_LPTEA, the return value is set to facilitate */ /* setting the condition code by the LPTEA instruction: */ /* 0 = Page table entry found, and page protection bit in the */ /* segment table entry is zero; the real address field */ /* contains the real address of the page table entry; */ /* exception code is set to zero. */ /* 1 = Page table entry found, and page protection bit in the */ /* segment table entry is one; the real address field */ /* contains the real address of the page table entry; */ /* exception code is set to zero. */ /* 2 = Region table or segment table entry invalid bit is set; */ /* the real address field contains the real address of the */ /* region table entry or segment table entry, with the */ /* entry type in the low-order two bits of the address. */ /* 3 = Region table or segment table length exceeded; real */ /* address field is not set; exception code is set to */ /* X'0010' or X'0039' through X'003B'. */ /* ALET translation error: real address field is not */ /* set; exception code is set to X'0028' through X'002D'. */ /* ASCE-type error: real address is not set; exception */ /* exception code is X'0038'. */ /* */ /* regs->dat.raddr is set to the real address if translation */ /* was successful; otherwise it may contain the address of */ /* a page or segment table entry as described above. */ /* For ACCTYPE_PTE or ACCTYPE_LPTEA it contains the address of */ /* the page table entry if translation was successful. */ /* */ /* regs->dat.xcode is set to the exception code if translation */ /* was unsuccessful; otherwise it is set to zero. */ /* */ /* regs->dat.private is set to 1 if translation was */ /* successful and the STD indicates a private address space; */ /* otherwise it is set to zero. */ /* */ /* regs->dat.protect is set to 1 if translation was */ /* successful and page protection, segment protection, or */ /* segment controlled page protection is in effect; it is */ /* set to 2 if translation was successful and ALE controlled */ /* protection (but not page protection) is in effect; */ /* otherwise it is set to zero. */ /* */ /* regs->dat.stid is set to one of the following */ /* values TEA_ST_PRIMARY, TEA_ST_SECNDRY, TEA_ST_HOME, or */ /* TEA_ST_ARMODE if the translation was successful. This */ /* indication is used to set bits 30-31 of the translation */ /* exception address in the event of a protection exception */ /* when the suppression on protection facility is used. */ /* */ /* A program check may be generated for addressing and */ /* translation specification exceptions, in which case the */ /* function does not return. */ /*-------------------------------------------------------------------*/ _DAT_C_STATIC int ARCH_DEP(translate_addr) (VADR vaddr, int arn, REGS *regs, int acctype) { RADR sto = 0; /* Segment table origin */ RADR pto = 0; /* Page table origin */ int cc; /* Condition code */ int tlbix = TLBIX(vaddr); /* TLB entry index */ #if !defined(FEATURE_S390_DAT) && !defined(FEATURE_ESAME) /*-----------------------------------*/ /* S/370 Dynamic Address Translation */ /*-----------------------------------*/ U32 stl; /* Segment table length */ RADR ste; /* Segment table entry */ U16 pte; /* Page table entry */ U32 ptl; /* Page table length */ regs->dat.private = regs->dat.protect = 0; /* Load the effective segment table descriptor */ if (ARCH_DEP(load_address_space_designator) (arn, regs, acctype)) goto tran_alet_excp; /* Check the translation format bits in CR0 */ if ((((regs->CR(0) & CR0_PAGE_SIZE) != CR0_PAGE_SZ_2K) && ((regs->CR(0) & CR0_PAGE_SIZE) != CR0_PAGE_SZ_4K)) || (((regs->CR(0) & CR0_SEG_SIZE) != CR0_SEG_SZ_64K) && ((regs->CR(0) & CR0_SEG_SIZE) != CR0_SEG_SZ_1M))) goto tran_spec_excp; /* Look up the address in the TLB */ if ( !(acctype & ACC_NOTLB) && ((vaddr & TLBID_PAGEMASK) | regs->tlbID) == regs->tlb.TLB_VADDR(tlbix) && (regs->tlb.common[tlbix] || regs->dat.asd == regs->tlb.TLB_ASD(tlbix)) && !(regs->tlb.common[tlbix] && regs->dat.private) ) { pte = regs->tlb.TLB_PTE(tlbix); #ifdef FEATURE_SEGMENT_PROTECTION /* Set the protection indicator if segment is protected */ if (regs->tlb.protect[tlbix]) regs->dat.protect = regs->tlb.protect[tlbix]; #endif /*FEATURE_SEGMENT_PROTECTION*/ } else { /* S/370 segment table lookup */ /* Calculate the real address of the segment table entry */ sto = regs->dat.asd & STD_370_STO; stl = regs->dat.asd & STD_370_STL; sto += ((regs->CR(0) & CR0_SEG_SIZE) == CR0_SEG_SZ_1M) ? ((vaddr & 0x00F00000) >> 18) : ((vaddr & 0x00FF0000) >> 14); /* Check that virtual address is within the segment table */ if (((regs->CR(0) & CR0_SEG_SIZE) == CR0_SEG_SZ_64K) && ((vaddr << 4) & STD_370_STL) > stl) goto seg_tran_length; /* Generate addressing exception if outside real storage */ if (sto > regs->mainlim) goto address_excp; /* Fetch segment table entry from real storage. All bytes must be fetched concurrently as observed by other CPUs */ sto = APPLY_PREFIXING (sto, regs->PX); ste = ARCH_DEP(fetch_fullword_absolute) (sto, regs); /* Generate segment translation exception if segment invalid */ if (ste & SEGTAB_370_INVL) goto seg_tran_invalid; /* Check that all the reserved bits in the STE are zero */ if (ste & SEGTAB_370_RSV) goto tran_spec_excp; /* Isolate page table origin and length */ pto = ste & SEGTAB_370_PTO; ptl = ste & SEGTAB_370_PTL; /* S/370 page table lookup */ /* Calculate the real address of the page table entry */ pto += ((regs->CR(0) & CR0_SEG_SIZE) == CR0_SEG_SZ_1M) ? (((regs->CR(0) & CR0_PAGE_SIZE) == CR0_PAGE_SZ_4K) ? ((vaddr & 0x000FF000) >> 11) : ((vaddr & 0x000FF800) >> 10)) : (((regs->CR(0) & CR0_PAGE_SIZE) == CR0_PAGE_SZ_4K) ? ((vaddr & 0x0000F000) >> 11) : ((vaddr & 0x0000F800) >> 10)); /* Generate addressing exception if outside real storage */ if (pto > regs->mainlim) goto address_excp; /* Check that the virtual address is within the page table */ if ((((regs->CR(0) & CR0_SEG_SIZE) == CR0_SEG_SZ_1M) && (((vaddr & 0x000F0000) >> 16) > ptl)) || (((regs->CR(0) & CR0_SEG_SIZE) == CR0_SEG_SZ_64K) && (((vaddr & 0x0000F000) >> 12) > ptl))) goto page_tran_length; /* Fetch the page table entry from real storage. All bytes must be fetched concurrently as observed by other CPUs */ pto = APPLY_PREFIXING (pto, regs->PX); pte = ARCH_DEP(fetch_halfword_absolute) (pto, regs); /* Generate page translation exception if page invalid */ if ((((regs->CR(0) & CR0_PAGE_SIZE) == CR0_PAGE_SZ_4K) && (pte & PAGETAB_INV_4K)) || (((regs->CR(0) & CR0_PAGE_SIZE) == CR0_PAGE_SZ_2K) && (pte & PAGETAB_INV_2K))) goto page_tran_invalid; /* Check that all the reserved bits in the PTE are zero */ if (((regs->CR(0) & CR0_PAGE_SIZE) == CR0_PAGE_SZ_2K) && (pte & PAGETAB_RSV_2K)) goto tran_spec_excp; #ifdef FEATURE_SEGMENT_PROTECTION /* Set the protection indicator if segment is protected */ if (ste & SEGTAB_370_PROT) regs->dat.protect |= 1; #endif /*FEATURE_SEGMENT_PROTECTION*/ /* Place the translated address in the TLB */ if (!(acctype & ACC_NOTLB)) { regs->tlb.TLB_ASD(tlbix) = regs->dat.asd; regs->tlb.TLB_VADDR(tlbix) = (vaddr & TLBID_PAGEMASK) | regs->tlbID; regs->tlb.TLB_PTE(tlbix) = pte; regs->tlb.common[tlbix] = (ste & SEGTAB_370_CMN) ? 1 : 0; regs->tlb.protect[tlbix] = regs->dat.protect; regs->tlb.acc[tlbix] = 0; regs->tlb.main[tlbix] = NULL; /* Set adjacent TLB entry if 4K page sizes */ if ((regs->CR(0) & CR0_PAGE_SIZE) == CR0_PAGE_SZ_4K) { regs->tlb.TLB_ASD(tlbix^1) = regs->tlb.TLB_ASD(tlbix); regs->tlb.TLB_VADDR(tlbix^1) = (vaddr & TLBID_PAGEMASK) | regs->tlbID; regs->tlb.TLB_PTE(tlbix^1) = regs->tlb.TLB_PTE(tlbix); regs->tlb.common[tlbix^1] = regs->tlb.common[tlbix]; regs->tlb.protect[tlbix^1] = regs->tlb.protect[tlbix]; regs->tlb.acc[tlbix^1] = 0; regs->tlb.main[tlbix^1] = NULL; } } } /* end if(!TLB) */ /* Combine the page frame real address with the byte index of the virtual address to form the real address */ regs->dat.raddr = ((regs->CR(0) & CR0_PAGE_SIZE) == CR0_PAGE_SZ_4K) ? #if defined(FEATURE_S370E_EXTENDED_ADDRESSING) (((U32)pte & PAGETAB_EA_4K) << 23) | #endif (((U32)pte & PAGETAB_PFRA_4K) << 8) | (vaddr & 0xFFF) : (((U32)pte & PAGETAB_PFRA_2K) << 8) | (vaddr & 0x7FF); regs->dat.rpfra = regs->dat.raddr & PAGEFRAME_PAGEMASK; #endif /*!defined(FEATURE_S390_DAT) && !defined(FEATURE_ESAME)*/ #if defined(FEATURE_S390_DAT) /*-----------------------------------*/ /* S/390 Dynamic Address Translation */ /*-----------------------------------*/ U32 stl; /* Segment table length */ RADR ste; /* Segment table entry */ RADR pte; /* Page table entry */ U32 ptl; /* Page table length */ regs->dat.private = regs->dat.protect = 0; /* [3.11.3.1] Load the effective segment table descriptor */ if (ARCH_DEP(load_address_space_designator) (arn, regs, acctype)) goto tran_alet_excp; /* [3.11.3.2] Check the translation format bits in CR0 */ if ((regs->CR(0) & CR0_TRAN_FMT) != CR0_TRAN_ESA390) goto tran_spec_excp; /* Extract the private space bit from segment table descriptor */ regs->dat.private = ((regs->dat.asd & STD_PRIVATE) != 0); /* [3.11.4] Look up the address in the TLB */ if ( !(acctype & ACC_NOTLB) && ((vaddr & TLBID_PAGEMASK) | regs->tlbID) == regs->tlb.TLB_VADDR(tlbix) && (regs->tlb.common[tlbix] || regs->dat.asd == regs->tlb.TLB_ASD(tlbix)) && !(regs->tlb.common[tlbix] && regs->dat.private) ) { pte = regs->tlb.TLB_PTE(tlbix); if (regs->tlb.protect[tlbix]) regs->dat.protect = regs->tlb.protect[tlbix]; } else { /* [3.11.3.3] Segment table lookup */ /* Calculate the real address of the segment table entry */ sto = regs->dat.asd & STD_STO; stl = regs->dat.asd & STD_STL; sto += (vaddr & 0x7FF00000) >> 18; /* Check that virtual address is within the segment table */ if ((vaddr >> 24) > stl) goto seg_tran_length; /* Generate addressing exception if outside real storage */ if (sto > regs->mainlim) goto address_excp; /* Fetch segment table entry from real storage. All bytes must be fetched concurrently as observed by other CPUs */ sto = APPLY_PREFIXING (sto, regs->PX); ste = ARCH_DEP(fetch_fullword_absolute) (sto, regs); /* Generate segment translation exception if segment invalid */ if (ste & SEGTAB_INVALID) goto seg_tran_invalid; /* Check that all the reserved bits in the STE are zero */ if (ste & SEGTAB_RESV) goto tran_spec_excp; /* If the segment table origin register indicates a private address space then STE must not indicate a common segment */ if (regs->dat.private && (ste & (SEGTAB_COMMON))) goto tran_spec_excp; /* Isolate page table origin and length */ pto = ste & SEGTAB_PTO; ptl = ste & SEGTAB_PTL; /* [3.11.3.4] Page table lookup */ /* Calculate the real address of the page table entry */ pto += (vaddr & 0x000FF000) >> 10; /* Check that the virtual address is within the page table */ if (((vaddr & 0x000FF000) >> 16) > ptl) goto page_tran_length; /* Generate addressing exception if outside real storage */ if (pto > regs->mainlim) goto address_excp; /* Fetch the page table entry from real storage. All bytes must be fetched concurrently as observed by other CPUs */ pto = APPLY_PREFIXING (pto, regs->PX); pte = ARCH_DEP(fetch_fullword_absolute) (pto, regs); /* Generate page translation exception if page invalid */ if (pte & PAGETAB_INVALID) goto page_tran_invalid; /* Check that all the reserved bits in the PTE are zero */ if (pte & PAGETAB_RESV) goto tran_spec_excp; /* Set the protection indicator if page protection is active */ if (pte & PAGETAB_PROT) regs->dat.protect |= 1; /* [3.11.4.2] Place the translated address in the TLB */ if (!(acctype & ACC_NOTLB)) { regs->tlb.TLB_ASD(tlbix) = regs->dat.asd; regs->tlb.TLB_VADDR(tlbix) = (vaddr & TLBID_PAGEMASK) | regs->tlbID; regs->tlb.TLB_PTE(tlbix) = pte; regs->tlb.common[tlbix] = (ste & SEGTAB_COMMON) ? 1 : 0; regs->tlb.acc[tlbix] = 0; regs->tlb.protect[tlbix] = regs->dat.protect; regs->tlb.main[tlbix] = NULL; } } /* end if(!TLB) */ if(!(acctype & ACC_PTE)) { /* [3.11.3.5] Combine the page frame real address with the byte index of the virtual address to form the real address */ regs->dat.raddr = (pte & PAGETAB_PFRA) | (vaddr & 0xFFF); regs->dat.rpfra = (pte & PAGETAB_PFRA); } else /* In the case of lock page, return the address of the pagetable entry */ regs->dat.raddr = pto; #endif /*defined(FEATURE_S390_DAT)*/ #if defined(FEATURE_ESAME) /*-----------------------------------*/ /* ESAME Dynamic Address Translation */ /*-----------------------------------*/ RADR rte; /* Region table entry */ #define rto sto /* Region/seg table origin */ RADR ste = 0; /* Segment table entry */ RADR pte = 0; /* Page table entry */ BYTE tt; /* Table type */ BYTE tl; /* Table length */ BYTE tf; /* Table offset */ U16 rfx, rsx, rtx; /* Region first/second/third index + 3 low-order zeros */ U16 sx, px; /* Segment and page index, + 3 low-order zero bits */ regs->dat.private = regs->dat.protect = 0; /* Load the address space control element */ if (ARCH_DEP(load_address_space_designator) (arn, regs, acctype)) goto tran_alet_excp; /* Extract the private space bit from the ASCE */ regs->dat.private = ((regs->dat.asd & (ASCE_P|ASCE_R)) != 0); // logmsg("asce=%16.16" I64_FMT "X\n",regs->dat.asd); /* [3.11.4] Look up the address in the TLB */ if ( !(acctype & ACC_NOTLB) && ((vaddr & TLBID_PAGEMASK) | regs->tlbID) == regs->tlb.TLB_VADDR(tlbix) && (regs->tlb.common[tlbix] || regs->dat.asd == regs->tlb.TLB_ASD(tlbix)) && !(regs->tlb.common[tlbix] && regs->dat.private) ) { pte = regs->tlb.TLB_PTE(tlbix); if (regs->tlb.protect[tlbix]) regs->dat.protect = regs->tlb.protect[tlbix]; } else { /* If ASCE indicates a real-space then real addr = virtual addr */ if (regs->dat.asd & ASCE_R) { // logmsg("asce type = real\n"); /* Translation specification exception if LKPG for a real-space */ if(acctype & ACC_PTE) goto tran_spec_excp; /* Special operation exception if LPTEA for a real-space */ if(acctype & ACC_LPTEA) goto spec_oper_excp; /* Construct a fake page table entry for real = virtual */ pte = vaddr & 0xFFFFFFFFFFFFF000ULL; } else { /* Extract the table origin, type, and length from the ASCE, and set the table offset to zero */ rto = regs->dat.asd & ASCE_TO; tf = 0; tt = regs->dat.asd & ASCE_DT; tl = regs->dat.asd & ASCE_TL; /* Extract the 11-bit region first index, region second index, and region third index from the virtual address, and shift each index into bits 2-12 of a 16-bit integer, ready for addition to the appropriate region table origin */ rfx = (vaddr >> 50) & 0x3FF8; rsx = (vaddr >> 39) & 0x3FF8; rtx = (vaddr >> 28) & 0x3FF8; /* Extract the 11-bit segment index from the virtual address, and shift it into bits 2-12 of a 16-bit integer, ready for addition to the segment table origin */ sx = (vaddr >> 17) & 0x3FF8; /* Extract the 8-bit page index from the virtual address, and shift it into bits 2-12 of a 16-bit integer, ready for addition to the page table origin */ px = (vaddr >> 9) & 0x07F8; /* ASCE-type exception if the virtual address is too large for the table type designated by the ASCE */ if ((rfx != 0 && tt < TT_R1TABL) || (rsx != 0 && tt < TT_R2TABL) || (rtx != 0 && tt < TT_R3TABL)) goto asce_type_excp; /* Perform region translation */ switch (tt) { /* Perform region-first translation */ case TT_R1TABL: /* Region-first translation exception if table length is less than high-order 2 bits of region-first index */ if (tl < (rfx >> 12)) goto reg_first_excp; /* Add the region-first index (with three low-order zeroes) to the region-first table origin, giving the address of the region-first table entry */ rto += rfx; /* Addressing exception if outside main storage */ if (rto > regs->mainlim) goto address_excp; /* Fetch region-first table entry from absolute storage. All bytes must be fetched concurrently as observed by other CPUs */ rte = ARCH_DEP(fetch_doubleword_absolute) (rto, regs); // logmsg("r1te:%16.16" I64_FMT "X=>%16.16" I64_FMT "X\n",rto,rte); /* Region-first translation exception if the bit 58 of the region-first table entry is set (region invalid) */ if (rte & REGTAB_I) goto reg_first_invalid; /* Translation specification exception if bits 60-61 of the region-first table entry do not indicate the correct type of region table */ if ((rte & REGTAB_TT) != TT_R1TABL) goto tran_spec_excp; /* Extract the region-second table origin, offset, and length from the region-first table entry */ rto = rte & REGTAB_TO; tf = (rte & REGTAB_TF) >> 6; tl = rte & REGTAB_TL; /* Fall through to perform region-second translation */ /* Perform region-second translation */ case TT_R2TABL: /* Region-second translation exception if table offset is greater than high-order 2 bits of region-second index */ if (tf > (rsx >> 12)) goto reg_second_excp; /* Region-second translation exception if table length is less than high-order 2 bits of region-second index */ if (tl < (rsx >> 12)) goto reg_second_excp; /* Add the region-second index (with three low-order zeroes) to the region-second table origin, giving the address of the region-second table entry */ rto += rsx; /* Addressing exception if outside main storage */ if (rto > regs->mainlim) goto address_excp; /* Fetch region-second table entry from absolute storage. All bytes must be fetched concurrently as observed by other CPUs */ rte = ARCH_DEP(fetch_doubleword_absolute) (rto, regs); // logmsg("r2te:%16.16" I64_FMT "X=>%16.16" I64_FMT "X\n",rto,rte); /* Region-second translation exception if the bit 58 of the region-second table entry is set (region invalid) */ if (rte & REGTAB_I) goto reg_second_invalid; /* Translation specification exception if bits 60-61 of the region-second table entry do not indicate the correct type of region table */ if ((rte & REGTAB_TT) != TT_R2TABL) goto tran_spec_excp; /* Extract the region-third table origin, offset, and length from the region-second table entry */ rto = rte & REGTAB_TO; tf = (rte & REGTAB_TF) >> 6; tl = rte & REGTAB_TL; /* Fall through to perform region-third translation */ /* Perform region-third translation */ case TT_R3TABL: /* Region-third translation exception if table offset is greater than high-order 2 bits of region-third index */ if (tf > (rtx >> 12)) goto reg_third_excp; /* Region-third translation exception if table length is less than high-order 2 bits of region-third index */ if (tl < (rtx >> 12)) goto reg_third_excp; /* Add the region-third index (with three low-order zeroes) to the region-third table origin, giving the address of the region-third table entry */ rto += rtx; /* Addressing exception if outside main storage */ if (rto > regs->mainlim) goto address_excp; /* Fetch region-third table entry from absolute storage. All bytes must be fetched concurrently as observed by other CPUs */ rte = ARCH_DEP(fetch_doubleword_absolute) (rto, regs); // logmsg("r3te:%16.16" I64_FMT "X=>%16.16" I64_FMT "X\n",rto,rte); /* Region-third translation exception if the bit 58 of the region-third table entry is set (region invalid) */ if (rte & REGTAB_I) goto reg_third_invalid; /* Translation specification exception if bits 60-61 of the region-third table entry do not indicate the correct type of region table */ if ((rte & REGTAB_TT) != TT_R3TABL) goto tran_spec_excp; /* Extract the segment table origin, offset, and length from the region-third table entry */ sto = rte & REGTAB_TO; tf = (rte & REGTAB_TF) >> 6; tl = rte & REGTAB_TL; /* Fall through to perform segment translation */ } /* end switch(tt) */ /* Perform ESAME segment translation */ /* Add the segment index (with three low-order zeroes) to the segment table origin, giving the address of the segment table entry */ sto += sx; /* Segment translation exception if table offset is greater than high-order 2 bits of segment index */ if (tf > (sx >> 12)) goto seg_tran_length; /* Segment translation exception if table length is less than high-order 2 bits of segment index */ if (tl < (sx >> 12)) goto seg_tran_length; /* Addressing exception if outside real storage */ if (sto > regs->mainlim) goto address_excp; /* Fetch segment table entry from absolute storage. All bytes must be fetched concurrently as observed by other CPUs */ ste = ARCH_DEP(fetch_doubleword_absolute) (sto, regs); // logmsg("ste:%16.16" I64_FMT "X=>%16.16" I64_FMT "X\n",sto,ste); /* Segment translation exception if segment invalid */ if (ste & ZSEGTAB_I) goto seg_tran_invalid; /* Translation specification exception if bits 60-61 of the segment table entry do not indicate segment table */ if ((ste & ZSEGTAB_TT) != TT_SEGTAB) goto tran_spec_excp; /* Translation specification exception if the ASCE indicates a private space, and the segment table entry indicates a common segment */ if (regs->dat.private && (ste & ZSEGTAB_C)) goto tran_spec_excp; /* Extract the page table origin from segment table entry */ pto = ste & ZSEGTAB_PTO; /* Perform ESAME page translation */ /* Add the page index (with three low-order zeroes) to the page table origin, giving address of page table entry */ pto += px; /* For LPTEA instruction, return the address of the PTE */ if (acctype & ACC_LPTEA) { regs->dat.raddr = pto; regs->dat.xcode = 0; cc = (ste & ZSEGTAB_P) ? 1 : 0; return cc; } /* end if(ACCTYPE_LPTEA) */ /* Addressing exception if outside real storage */ if (pto > regs->mainlim) goto address_excp; /* Fetch the page table entry from absolute storage. All bytes must be fetched concurrently as observed by other CPUs */ pte = ARCH_DEP(fetch_doubleword_absolute) (pto, regs); // logmsg("pte:%16.16" I64_FMT "X=>%16.16" I64_FMT "X\n",pto,pte); /* Page translation exception if page invalid */ if (pte & ZPGETAB_I) goto page_tran_invalid; /* Check that all the reserved bits in the PTE are zero */ if (pte & ZPGETAB_RESV) goto tran_spec_excp; } /* end else(ASCE_R) */ /* Set protection indicator if page protection is indicated in either the segment table or the page table */ if ((ste & ZSEGTAB_P) || (pte & ZPGETAB_P)) regs->dat.protect |= 1; /* [3.11.4.2] Place the translated address in the TLB */ if (!(acctype & ACC_NOTLB)) { regs->tlb.TLB_ASD(tlbix) = regs->dat.asd; regs->tlb.TLB_VADDR(tlbix) = (vaddr & TLBID_PAGEMASK) | regs->tlbID; regs->tlb.TLB_PTE(tlbix) = pte; regs->tlb.common[tlbix] = (ste & SEGTAB_COMMON) ? 1 : 0; regs->tlb.protect[tlbix] = regs->dat.protect; regs->tlb.acc[tlbix] = 0; regs->tlb.main[tlbix] = NULL; } } if(!(acctype & ACC_PTE)) { /* Combine the page frame real address with the byte index of the virtual address to form the real address */ regs->dat.raddr = (pte & ZPGETAB_PFRA) | (vaddr & 0xFFF); regs->dat.rpfra = (pte & ZPGETAB_PFRA); } else regs->dat.raddr = pto; #endif /*defined(FEATURE_ESAME)*/ /* The following code is common to S/370, ESA/390, and ESAME */ /* Clear exception code and return with zero return code */ regs->dat.xcode = 0; return 0; /* Conditions which always cause program check, except when performing translation for the control panel */ address_excp: // logmsg("dat.c: addressing exception: %8.8X %8.8X %4.4X %8.8X\n", // regs->CR(0),regs->dat.asd,pte,vaddr); regs->dat.xcode = PGM_ADDRESSING_EXCEPTION; goto tran_prog_check; tran_spec_excp: #if defined(FEATURE_ESAME) // logmsg("dat.c: translation specification exception...\n"); // logmsg(" pte = %16.16" I64_FMT "X, ste = %16.16" I64_FMT "X, rte=%16.16" I64_FMT "X\n", // pte, ste, rte); #else // logmsg("dat.c: translation specification exception...\n"); // logmsg(" cr0=%8.8X ste=%8.8X pte=%4.4X vaddr=%8.8X\n", // regs->CR(0),ste,pte,vaddr); #endif regs->dat.xcode = PGM_TRANSLATION_SPECIFICATION_EXCEPTION; goto tran_prog_check; #if defined(FEATURE_ESAME) spec_oper_excp: regs->dat.xcode = PGM_SPECIAL_OPERATION_EXCEPTION; goto tran_prog_check; #endif /*defined(FEATURE_ESAME)*/ tran_prog_check: regs->program_interrupt (regs, regs->dat.xcode); /* Conditions which the caller may or may not program check */ seg_tran_invalid: /* For LPTEA, return segment table entry address with cc 2 */ if (acctype & ACC_LPTEA) { regs->dat.raddr = sto; cc = 2; return cc; } /* end if(ACCTYPE_LPTEA) */ /* Otherwise set translation exception code */ regs->dat.xcode = PGM_SEGMENT_TRANSLATION_EXCEPTION; regs->dat.raddr = sto; cc = 1; goto tran_excp_addr; page_tran_invalid: regs->dat.xcode = PGM_PAGE_TRANSLATION_EXCEPTION; regs->dat.raddr = pto; if(acctype & ACC_PTE) return 0; cc = 2; goto tran_excp_addr; #if !defined(FEATURE_ESAME) page_tran_length: regs->dat.xcode = PGM_PAGE_TRANSLATION_EXCEPTION; regs->dat.raddr = pto; cc = 3; goto tran_excp_addr; #endif /*!defined(FEATURE_ESAME)*/ seg_tran_length: // logmsg("dat.c: segment translation exception due to segment length\n"); // logmsg(" cr0=" F_RADR " sto=" F_RADR "\n",regs->CR(0),sto); regs->dat.xcode = PGM_SEGMENT_TRANSLATION_EXCEPTION; regs->dat.raddr = sto; cc = 3; goto tran_excp_addr; tran_alet_excp: regs->excarid = arn; cc = (acctype & ACC_LPTEA) ? 3 : 4; return cc; #if defined(FEATURE_ESAME) reg_first_invalid: /* For LPTEA, return region table entry address with cc 2 */ if (acctype & ACC_LPTEA) { regs->dat.raddr = rto | (TT_R1TABL >> 2); cc = 2; return cc; } /* end if(ACCTYPE_LPTEA) */ /* Otherwise set translation exception code */ goto reg_first_excp; reg_second_invalid: /* For LPTEA, return region table entry address with cc 2 */ if (acctype & ACC_LPTEA) { regs->dat.raddr = rto | (TT_R2TABL >> 2); cc = 2; return cc; } /* end if(ACCTYPE_LPTEA) */ /* Otherwise set translation exception code */ goto reg_second_excp; reg_third_invalid: /* For LPTEA, return region table entry address with cc 2 */ if (acctype & ACC_LPTEA) { regs->dat.raddr = rto | (TT_R3TABL >> 2); cc = 2; return cc; } /* end if(ACCTYPE_LPTEA) */ /* Otherwise set translation exception code */ goto reg_third_excp; asce_type_excp: // logmsg("rfx = %4.4X, rsx %4.4X, rtx = %4.4X, tt = %1.1X\n", // rfx, rsx, rtx, tt); regs->dat.xcode = PGM_ASCE_TYPE_EXCEPTION; cc = 4; goto tran_excp_addr; reg_first_excp: regs->dat.xcode = PGM_REGION_FIRST_TRANSLATION_EXCEPTION; cc = 4; goto tran_excp_addr; reg_second_excp: regs->dat.xcode = PGM_REGION_SECOND_TRANSLATION_EXCEPTION; cc = 4; goto tran_excp_addr; reg_third_excp: regs->dat.xcode = PGM_REGION_THIRD_TRANSLATION_EXCEPTION; cc = 4; goto tran_excp_addr; #endif /*defined(FEATURE_ESAME)*/ tran_excp_addr: /* For LPTEA instruction, return xcode with cc = 3 */ if (acctype & ACC_LPTEA) return 3; /* Set the translation exception address */ regs->TEA = vaddr & PAGEFRAME_PAGEMASK; /* Set the address space indication in the exception address */ #if defined(FEATURE_ESAME) if(regs->dat.stid == TEA_ST_ARMODE) { if ((regs->dat.asd & ASCE_TO) == (regs->CR(1) & ASCE_TO)) regs->TEA |= TEA_ST_PRIMARY; else if ((regs->dat.asd & ASCE_TO) == (regs->CR(7) & ASCE_TO)) regs->TEA |= TEA_ST_SECNDRY; else if ((regs->dat.asd & ASCE_TO) == (regs->CR(13) & ASCE_TO)) regs->TEA |= TEA_ST_HOME; else regs->TEA |= TEA_ST_ARMODE; } else regs->TEA |= regs->dat.stid; #else /*!defined(FEATURE_ESAME)*/ if(regs->dat.stid == TEA_ST_ARMODE) { if ((regs->dat.asd & STD_STO) == (regs->CR(1) & STD_STO)) regs->TEA |= TEA_ST_PRIMARY; else if ((regs->dat.asd & STD_STO) == (regs->CR(7) & STD_STO)) regs->TEA |= TEA_ST_SECNDRY; else if ((regs->dat.asd & STD_STO) == (regs->CR(13) & STD_STO)) regs->TEA |= TEA_ST_HOME; else regs->TEA |= TEA_ST_ARMODE; } else if((regs->dat.stid == TEA_ST_SECNDRY) && (PRIMARY_SPACE_MODE(®s->psw) || SECONDARY_SPACE_MODE(®s->psw))) regs->TEA |= TEA_ST_SECNDRY | TEA_SECADDR; else regs->TEA |= regs->dat.stid; #endif /*!defined(FEATURE_ESAME)*/ /* Set the exception access identification */ if (ACCESS_REGISTER_MODE(®s->psw) || (SIE_ACTIVE(regs) && MULTIPLE_CONTROLLED_DATA_SPACE(regs->guestregs)) ) regs->excarid = arn > 15 ? 0 : arn; /* Return condition code */ return cc; } /* end function translate_addr */ /*-------------------------------------------------------------------*/ /* Purge the translation lookaside buffer */ /*-------------------------------------------------------------------*/ _DAT_C_STATIC void ARCH_DEP(purge_tlb) (REGS *regs) { INVALIDATE_AIA(regs); if (((++regs->tlbID) & TLBID_BYTEMASK) == 0) { memset (®s->tlb.vaddr, 0, TLBN * sizeof(DW)); regs->tlbID = 1; } #if defined(_FEATURE_SIE) /* Also clear the guest registers in the SIE copy */ if(regs->host && regs->guestregs) { INVALIDATE_AIA(regs->guestregs); if (((++regs->guestregs->tlbID) & TLBID_BYTEMASK) == 0) { memset (®s->guestregs->tlb.vaddr, 0, TLBN * sizeof(DW)); regs->guestregs->tlbID = 1; } } #endif /*defined(_FEATURE_SIE)*/ } /* end function purge_tlb */ /*-------------------------------------------------------------------*/ /* Purge the translation lookaside buffer for all CPUs */ /*-------------------------------------------------------------------*/ _DAT_C_STATIC void ARCH_DEP(purge_tlb_all) () { int i; for (i = 0; i < MAX_CPU; i++) if (IS_CPU_ONLINE(i) && (sysblk.regs[i]->cpubit & sysblk.started_mask)) ARCH_DEP(purge_tlb) (sysblk.regs[i]); } /* end function purge_tlb_all */ /*-------------------------------------------------------------------*/ /* Purge translation lookaside buffer entries */ /*-------------------------------------------------------------------*/ _DAT_C_STATIC void ARCH_DEP(purge_tlbe) (REGS *regs, RADR pfra) { int i; RADR pte; RADR ptemask; #if !defined(FEATURE_S390_DAT) && !defined(FEATURE_ESAME) ptemask = ((regs->CR(0) & CR0_PAGE_SIZE) == CR0_PAGE_SZ_4K) ? PAGETAB_PFRA_4K : PAGETAB_PFRA_2K; pte = ((pfra & 0xFFFFFF) >> 8) & ptemask; #endif #if defined(FEATURE_S390_DAT) ptemask = PAGETAB_PFRA; pte = pfra & ptemask; #endif /* defined(FEATURE_S390_DAT) */ #if defined(FEATURE_ESAME) ptemask = (RADR)ZPGETAB_PFRA; pte = pfra & ptemask; #endif /* defined(FEATURE_ESAME) */ INVALIDATE_AIA(regs); for (i = 0; i < TLBN; i++) if ((regs->tlb.TLB_PTE(i) & ptemask) == pte) regs->tlb.TLB_VADDR(i) &= TLBID_PAGEMASK; #if defined(_FEATURE_SIE) /* Also clear the guest registers in the SIE copy */ if (regs->host && regs->guestregs) { INVALIDATE_AIA(regs->guestregs); for (i = 0; i < TLBN; i++) if ((regs->guestregs->tlb.TLB_PTE(i) & ptemask) == pte) regs->guestregs->tlb.TLB_VADDR(i) &= TLBID_PAGEMASK; } else /* For guests, clear any host entries */ if (regs->guest) { INVALIDATE_AIA(regs->hostregs); for (i = 0; i < TLBN; i++) if ((regs->hostregs->tlb.TLB_PTE(i) & ptemask) == pte) regs->hostregs->tlb.TLB_VADDR(i) &= TLBID_PAGEMASK; } #endif /*defined(_FEATURE_SIE)*/ } /* end function purge_tlbe */ /*-------------------------------------------------------------------*/ /* Purge translation lookaside buffer entries for all CPUs */ /*-------------------------------------------------------------------*/ _DAT_C_STATIC void ARCH_DEP(purge_tlbe_all) (RADR pfra) { int i; for (i = 0; i < MAX_CPU; i++) if (IS_CPU_ONLINE(i) && (sysblk.regs[i]->cpubit & sysblk.started_mask)) ARCH_DEP(purge_tlbe) (sysblk.regs[i], pfra); } /* end function purge_tlbe_all */ /*-------------------------------------------------------------------*/ /* Invalidate all translation lookaside buffer entries */ /*-------------------------------------------------------------------*/ _DAT_C_STATIC void ARCH_DEP(invalidate_tlb) (REGS *regs, BYTE mask) { int i; INVALIDATE_AIA(regs); if (mask == 0) memset(®s->tlb.acc, 0, TLBN); else for (i = 0; i < TLBN; i++) if ((regs->tlb.TLB_VADDR(i) & TLBID_BYTEMASK) == regs->tlbID) regs->tlb.acc[i] &= mask; #if defined(_FEATURE_SIE) /* Also invalidate the guest registers in the SIE copy */ if(regs->host && regs->guestregs) { INVALIDATE_AIA(regs->guestregs); if (mask == 0) memset(®s->guestregs->tlb.acc, 0, TLBN); else for (i = 0; i < TLBN; i++) if ((regs->guestregs->tlb.TLB_VADDR(i) & TLBID_BYTEMASK) == regs->guestregs->tlbID) regs->guestregs->tlb.acc[i] &= mask; } else /* Also invalidate the guest registers in the SIE copy */ if(regs->guest) { INVALIDATE_AIA(regs->hostregs); if (mask == 0) memset(®s->hostregs->tlb.acc, 0, TLBN); else for (i = 0; i < TLBN; i++) if ((regs->hostregs->tlb.TLB_VADDR(i) & TLBID_BYTEMASK) == regs->hostregs->tlbID) regs->hostregs->tlb.acc[i] &= mask; } #endif /*defined(_FEATURE_SIE)*/ } /* end function invalidate_tlb */ /*-------------------------------------------------------------------*/ /* Invalidate matching translation lookaside buffer entries */ /* */ /* Input: */ /* main mainstore address to match on. This is mainstore */ /* base plus absolute address (regs->mainstor+aaddr) */ /* */ /* This function is called by the SSK(E) instructions to purge */ /* TLB entries that match the mainstore address. The "main" */ /* field in the TLB contains the mainstore address plus an */ /* XOR hash with effective address (regs->mainstor+aaddr^addr). */ /* Before the compare can happen, the effective address from */ /* the tlb (TLB_VADDR) must be XORed with the "main" field from */ /* the tlb (removing hash). This is done using MAINADDR() macro. */ /* NOTES: */ /* TLB_VADDR does not contain all the effective address bits and */ /* must be created on-the-fly using the tlb index (i << shift). */ /* TLB_VADDR also contains the tlbid, so the regs->tlbid is merged */ /* with the main input variable before the search is begun. */ /*-------------------------------------------------------------------*/ _DAT_C_STATIC void ARCH_DEP(invalidate_tlbe) (REGS *regs, BYTE *main) { int i; /* index into TLB */ int shift; /* Number of bits to shift */ BYTE *mainwid; /* mainstore with tlbid */ if (main == NULL) { ARCH_DEP(invalidate_tlb)(regs, 0); return; } mainwid = main + regs->tlbID; INVALIDATE_AIA_MAIN(regs, main); shift = regs->arch_mode == ARCH_370 ? 11 : 12; for (i = 0; i < TLBN; i++) if (MAINADDR(regs->tlb.main[i], (regs->tlb.TLB_VADDR(i) | (i << shift))) == mainwid) { regs->tlb.acc[i] = 0; #if !defined(FEATURE_S390_DAT) && !defined(FEATURE_ESAME) if ((regs->CR(0) & CR0_PAGE_SIZE) == CR0_PAGE_SZ_4K) regs->tlb.acc[i^1] = 0; #endif } #if defined(_FEATURE_SIE) /* Also clear the guest registers in the SIE copy */ if (regs->host && regs->guestregs) { INVALIDATE_AIA_MAIN(regs->guestregs, main); shift = regs->guestregs->arch_mode == ARCH_370 ? 11 : 12; for (i = 0; i < TLBN; i++) if (MAINADDR(regs->guestregs->tlb.main[i], (regs->guestregs->tlb.TLB_VADDR(i) | (i << shift))) == mainwid) { regs->guestregs->tlb.acc[i] = 0; #if !defined(FEATURE_S390_DAT) && !defined(FEATURE_ESAME) if ((regs->guestregs->CR(0) & CR0_PAGE_SIZE) == CR0_PAGE_SZ_4K) regs->guestregs->tlb.acc[i^1] = 0; #endif } } /* Also clear the host registers in the SIE copy */ if (regs->guest) { INVALIDATE_AIA_MAIN(regs->hostregs, main); shift = regs->hostregs->arch_mode == ARCH_370 ? 11 : 12; for (i = 0; i < TLBN; i++) if (MAINADDR(regs->hostregs->tlb.main[i], (regs->hostregs->tlb.TLB_VADDR(i) | (i << shift))) == mainwid) { regs->hostregs->tlb.acc[i] = 0; #if !defined(FEATURE_S390_DAT) && !defined(FEATURE_ESAME) if ((regs->hostregs->CR(0) & CR0_PAGE_SIZE) == CR0_PAGE_SZ_4K) regs->hostregs->tlb.acc[i^1] = 0; #endif } } #endif /*defined(_FEATURE_SIE)*/ } /* end function invalidate_tlbe */ /*-------------------------------------------------------------------*/ /* Invalidate page table entry */ /* */ /* Input: */ /* ibyte 0x21=IPTE instruction, 0x59=IESBE instruction */ /* r1 First operand register number */ /* r2 Second operand register number */ /* regs CPU register context */ /* */ /* This function is called by the IPTE and IESBE instructions. */ /* It sets the PAGETAB_INVALID bit (for IPTE) or resets the */ /* PAGETAB_ESVALID bit (for IESBE) in the page table entry */ /* addressed by the page table origin in the R1 register and */ /* the page index in the R2 register. It clears the TLB of */ /* all entries whose PFRA matches the page table entry. */ /* */ /* invalidate_pte should be called with the intlock held and */ /* SYNCHRONIZE_CPUS issued while intlock is held. */ /* */ /*-------------------------------------------------------------------*/ _DAT_C_STATIC void ARCH_DEP(invalidate_pte) (BYTE ibyte, int r1, int r2, REGS *regs) { RADR raddr; /* Addr of page table entry */ RADR pte; RADR pfra; UNREFERENCED_370(ibyte); #if !defined(FEATURE_S390_DAT) && !defined(FEATURE_ESAME) { /* Program check if translation format is invalid */ if ((((regs->CR(0) & CR0_PAGE_SIZE) != CR0_PAGE_SZ_2K) && ((regs->CR(0) & CR0_PAGE_SIZE) != CR0_PAGE_SZ_4K)) || (((regs->CR(0) & CR0_SEG_SIZE) != CR0_SEG_SZ_64K) && ((regs->CR(0) & CR0_SEG_SIZE) != CR0_SEG_SZ_1M))) regs->program_interrupt (regs, PGM_TRANSLATION_SPECIFICATION_EXCEPTION); /* Combine the page table origin in the R1 register with the page index in the R2 register, ignoring carry, to form the 31-bit real address of the page table entry */ raddr = (regs->GR_L(r1) & SEGTAB_370_PTO) + (((regs->CR(0) & CR0_SEG_SIZE) == CR0_SEG_SZ_1M) ? (((regs->CR(0) & CR0_PAGE_SIZE) == CR0_PAGE_SZ_4K) ? ((regs->GR_L(r2) & 0x000FF000) >> 11) : ((regs->GR_L(r2) & 0x000FF800) >> 10)) : (((regs->CR(0) & CR0_PAGE_SIZE) == CR0_PAGE_SZ_4K) ? ((regs->GR_L(r2) & 0x0000F000) >> 11) : ((regs->GR_L(r2) & 0x0000F800) >> 10))); raddr &= 0x00FFFFFF; /* Fetch the page table entry from real storage, subject to normal storage protection mechanisms */ pte = ARCH_DEP(vfetch2) ( raddr, USE_REAL_ADDR, regs ); /* Set the page invalid bit in the page table entry, again subject to storage protection mechansims */ // /*debug*/ logmsg("dat.c: IPTE issued for entry %4.4X at %8.8X...\n" // " page table %8.8X, page index %8.8X, cr0 %8.8X\n", // pte, raddr, regs->GR_L(r1), regs->GR_L(r2), regs->CR(0)); if ((regs->CR(0) & CR0_PAGE_SIZE) == CR0_PAGE_SZ_2K) pte |= PAGETAB_INV_2K; else pte |= PAGETAB_INV_4K; ARCH_DEP(vstore2) ( pte, raddr, USE_REAL_ADDR, regs ); pfra = ((regs->CR(0) & CR0_PAGE_SIZE) == CR0_PAGE_SZ_4K) ? #if defined(FEATURE_S370E_EXTENDED_ADDRESSING) (((U32)pte & PAGETAB_EA_4K) << 23) | #endif (((U32)pte & PAGETAB_PFRA_4K) << 8) : (((U32)pte & PAGETAB_PFRA_2K) << 8); } #elif defined(FEATURE_S390_DAT) { /* Program check if translation format is invalid */ if ((regs->CR(0) & CR0_TRAN_FMT) != CR0_TRAN_ESA390) regs->program_interrupt (regs, PGM_TRANSLATION_SPECIFICATION_EXCEPTION); /* Combine the page table origin in the R1 register with the page index in the R2 register, ignoring carry, to form the 31-bit real address of the page table entry */ raddr = (regs->GR_L(r1) & SEGTAB_PTO) + ((regs->GR_L(r2) & 0x000FF000) >> 10); raddr &= 0x7FFFFFFF; /* Fetch the page table entry from real storage, subject to normal storage protection mechanisms */ pte = ARCH_DEP(vfetch4) ( raddr, USE_REAL_ADDR, regs ); /* Set the page invalid bit in the page table entry, again subject to storage protection mechansims */ #if defined(FEATURE_MOVE_PAGE_FACILITY_2) && defined(FEATURE_EXPANDED_STORAGE) if(ibyte == 0x59) pte &= ~PAGETAB_ESVALID; else #endif /*defined(FEATURE_MOVE_PAGE_FACILITY_2)*/ pte |= PAGETAB_INVALID; ARCH_DEP(vstore4) ( pte, raddr, USE_REAL_ADDR, regs ); pfra = pte & PAGETAB_PFRA; } #else /*defined(FEATURE_ESAME)*/ { /* Combine the page table origin in the R1 register with the page index in the R2 register, ignoring carry, to form the 64-bit real address of the page table entry */ raddr = (regs->GR_G(r1) & ZSEGTAB_PTO) + ((regs->GR_G(r2) & 0x000FF000) >> 9); #if defined(MODEL_DEPENDENT) raddr = APPLY_PREFIXING (raddr, regs->PX); #endif /*defined(MODEL_DEPENDENT)*/ /* Fetch the page table entry from real storage, subject to normal storage protection mechanisms */ pte = ARCH_DEP(vfetch8) ( raddr, USE_REAL_ADDR, regs ); /* Set the page invalid bit in the page table entry, again subject to storage protection mechansims */ #if defined(FEATURE_MOVE_PAGE_FACILITY_2) && defined(FEATURE_EXPANDED_STORAGE) if(ibyte == 0x59) pte &= ~ZPGETAB_ESVALID; else #endif /*defined(FEATURE_MOVE_PAGE_FACILITY_2)*/ pte |= ZPGETAB_I; ARCH_DEP(vstore8) ( pte, raddr, USE_REAL_ADDR, regs ); pfra = pte & ZPGETAB_PFRA; } #endif /*defined(FEATURE_ESAME)*/ /* Invalidate TLB entries */ ARCH_DEP(purge_tlbe_all) (pfra); } /* end function invalidate_pte */ #endif /*!defined(OPTION_NO_INLINE_DAT) || defined(_DAT_C) */ #if defined(FEATURE_PER2) /*-------------------------------------------------------------------*/ /* Check for a storage alteration PER2 event */ /* Returns 1 if true, 0 if false */ /*-------------------------------------------------------------------*/ static inline int ARCH_DEP(check_sa_per2) (int arn, int acctype, REGS *regs) { UNREFERENCED(acctype); if((regs->dat.asd & SAEVENT_BIT) || !(regs->CR(9) & CR9_SAC)) { regs->peraid = arn > 0 && arn < 16 ? arn : 0; regs->perc |= regs->dat.stid; return 1; } return 0; } /* end function check_sa_per2 */ #endif /*defined(FEATURE_PER2)*/ #if !defined(OPTION_NO_INLINE_LOGICAL) || defined(_DAT_C) /*-------------------------------------------------------------------*/ /* Convert logical address to absolute address and check protection */ /* */ /* Input: */ /* addr Logical address to be translated */ /* arn Access register number (or USE_REAL_ADDR, */ /* USE_PRIMARY_SPACE, USE_SECONDARY_SPACE) */ /* regs CPU register context */ /* acctype Type of access requested: READ, WRITE, or instfetch */ /* akey Bits 0-3=access key, 4-7=zeroes */ /* Returns: */ /* Absolute storage address. */ /* */ /* If the PSW indicates DAT-off, or if the access register */ /* number parameter is the special value USE_REAL_ADDR, */ /* then the addr parameter is treated as a real address. */ /* Otherwise addr is a virtual address, so dynamic address */ /* translation is called to convert it to a real address. */ /* Prefixing is then applied to convert the real address to */ /* an absolute address, and then low-address protection, */ /* access-list controlled protection, page protection, and */ /* key controlled protection checks are applied to the address. */ /* If successful, the reference and change bits of the storage */ /* key are updated, and the absolute address is returned. */ /* */ /* If the logical address causes an addressing, protection, */ /* or translation exception then a program check is generated */ /* and the function does not return. */ /*-------------------------------------------------------------------*/ _LOGICAL_C_STATIC BYTE *ARCH_DEP(logical_to_main) (VADR addr, int arn, REGS *regs, int acctype, BYTE akey) { RADR aaddr; /* Absolute address */ RADR apfra; /* Abs page frame address */ int ix = TLBIX(addr); /* TLB index */ /* Convert logical address to real address */ if ( (REAL_MODE(®s->psw) || arn == USE_REAL_ADDR) #if defined(FEATURE_INTERPRETIVE_EXECUTION) /* Under SIE guest real is always host primary, regardless of the DAT mode */ && !(regs->sie_active #if !defined(_FEATURE_MULTIPLE_CONTROLLED_DATA_SPACE) && arn == USE_PRIMARY_SPACE #else // && ( (arn == USE_PRIMARY_SPACE) // || SIE_STATB(regs->guestregs, MX, XC) ) #endif /*defined(_FEATURE_MULTIPLE_CONTROLLED_DATA_SPACE)*/ ) #endif /*defined(FEATURE_INTERPRETIVE_EXECUTION)*/ ) { regs->dat.private = regs->dat.protect = 0; regs->dat.raddr = addr; regs->dat.rpfra = addr & PAGEFRAME_PAGEMASK; /* Setup `real' TLB entry (for MADDR) */ regs->tlb.TLB_ASD(ix) = TLB_REAL_ASD; regs->tlb.TLB_VADDR(ix) = (addr & TLBID_PAGEMASK) | regs->tlbID; regs->tlb.TLB_PTE(ix) = addr & TLBID_PAGEMASK; regs->tlb.acc[ix] = regs->tlb.common[ix] = regs->tlb.protect[ix] = 0; } else { if (ARCH_DEP(translate_addr) (addr, arn, regs, acctype)) goto vabs_prog_check; } if (regs->dat.protect && (acctype & (ACC_WRITE|ACC_CHECK))) goto vabs_prot_excp; /* Convert real address to absolute address */ regs->dat.aaddr = aaddr = APPLY_PREFIXING (regs->dat.raddr, regs->PX); apfra=APPLY_PREFIXING(regs->dat.rpfra,regs->PX); /* Program check if absolute address is outside main storage */ if (regs->dat.aaddr > regs->mainlim) goto vabs_addr_excp; #if defined(_FEATURE_SIE) if(SIE_MODE(regs)) regs->hostregs->dat.protect = 0; if(SIE_MODE(regs) && !regs->sie_pref) { if (SIE_TRANSLATE_ADDR (regs->sie_mso + regs->dat.aaddr, (arn > 0 && arn < 16 && MULTIPLE_CONTROLLED_DATA_SPACE(regs)) ? arn : USE_PRIMARY_SPACE, regs->hostregs, ACCTYPE_SIE)) (regs->hostregs->program_interrupt) (regs->hostregs, regs->hostregs->dat.xcode); regs->dat.protect |= regs->hostregs->dat.protect; regs->tlb.protect[ix] |= regs->hostregs->dat.protect; if ( REAL_MODE(®s->psw) || (arn == USE_REAL_ADDR) ) regs->tlb.TLB_PTE(ix) = addr & TLBID_PAGEMASK; /* Indicate a host real space entry for a XC dataspace */ if (arn > 0 && arn < 16 && MULTIPLE_CONTROLLED_DATA_SPACE(regs)) { regs->tlb.TLB_ASD(ix) = regs->dat.asd; /* Ensure that the private bit is percolated to the guest such that LAP is applied correctly */ regs->dat.private = regs->hostregs->dat.private; /* Build tlb entry of XC dataspace */ regs->dat.asd = regs->hostregs->dat.asd ^ TLB_HOST_ASD; regs->CR(CR_ALB_OFFSET + arn) = regs->dat.asd; regs->aea_ar[arn] = CR_ALB_OFFSET + arn; regs->aea_common[CR_ALB_OFFSET + arn] = (regs->dat.asd & ASD_PRIVATE) == 0; regs->aea_aleprot[arn] = regs->hostregs->dat.protect & 2; } /* Convert host real address to host absolute address */ regs->hostregs->dat.aaddr = aaddr = APPLY_PREFIXING (regs->hostregs->dat.raddr, regs->hostregs->PX); apfra = APPLY_PREFIXING(regs->hostregs->dat.rpfra, regs->hostregs->PX); if(regs->hostregs->dat.aaddr > regs->hostregs->mainlim) goto vabs_addr_excp; /* Take into account SIE guests with a 2K page scheme because the SIE host may be operating with a 4K page system */ #if defined(FEATURE_2K_STORAGE_KEYS) if((addr & PAGEFRAME_PAGEMASK) & 0x800) { apfra|=0x800; } #endif } /* Do not apply host key access when SIE fetches/stores data */ if(SIE_ACTIVE(regs)) akey = 0; #endif /*defined(_FEATURE_SIE)*/ /* Check protection and set reference and change bits */ regs->dat.storkey = &(STORAGE_KEY(aaddr, regs)); if (acctype & ACC_READ) { /* Program check if fetch protected location */ if (unlikely(ARCH_DEP(is_fetch_protected) (addr, *regs->dat.storkey, akey, regs))) { if (SIE_MODE(regs)) regs->hostregs->dat.protect = 0; goto vabs_prot_excp; } /* Set the reference bit in the storage key */ *regs->dat.storkey |= STORKEY_REF; /* Update accelerated lookup TLB fields */ regs->tlb.storkey[ix] = regs->dat.storkey; regs->tlb.skey[ix] = *regs->dat.storkey & STORKEY_KEY; regs->tlb.acc[ix] = ACC_READ; regs->tlb.main[ix] = NEW_MAINADDR (regs, addr, apfra); } else if (acctype & (ACC_WRITE|ACC_CHECK)) { /* Program check if store protected location */ if (unlikely(ARCH_DEP(is_store_protected) (addr, *regs->dat.storkey, akey, regs))) { if (SIE_MODE(regs)) regs->hostregs->dat.protect = 0; goto vabs_prot_excp; } if (SIE_MODE(regs) && regs->hostregs->dat.protect) goto vabs_prot_excp; /* Set the reference and change bits in the storage key */ if (acctype & ACC_WRITE) *regs->dat.storkey |= (STORKEY_REF | STORKEY_CHANGE); /* Update accelerated lookup TLB fields */ regs->tlb.storkey[ix] = regs->dat.storkey; regs->tlb.skey[ix] = *regs->dat.storkey & STORKEY_KEY; regs->tlb.acc[ix] = (addr >= PSA_SIZE || regs->dat.private) ? (ACC_READ|ACC_CHECK|acctype) : ACC_READ; regs->tlb.main[ix] = NEW_MAINADDR (regs, addr, apfra); #if defined(FEATURE_PER) if (EN_IC_PER_SA(regs)) { regs->tlb.acc[ix] = ACC_READ; if (arn != USE_REAL_ADDR #if defined(FEATURE_PER2) && ( REAL_MODE(®s->psw) || ARCH_DEP(check_sa_per2) (arn, acctype, regs) ) #endif /*defined(FEATURE_PER2)*/ && PER_RANGE_CHECK(addr,regs->CR(10),regs->CR(11)) ) ON_IC_PER_SA(regs); } #endif /*defined(FEATURE_PER)*/ } /* acctype & ACC_WRITE|CHECK */ /* Return mainstor address */ return regs->mainstor + aaddr; vabs_addr_excp: regs->program_interrupt (regs, PGM_ADDRESSING_EXCEPTION); vabs_prot_excp: #ifdef FEATURE_SUPPRESSION_ON_PROTECTION regs->TEA = addr & STORAGE_KEY_PAGEMASK; if (regs->dat.protect && (acctype & (ACC_WRITE|ACC_CHECK)) ) { regs->TEA |= TEA_PROT_AP; #if defined(FEATURE_ESAME) if (regs->dat.protect & 2) regs->TEA |= TEA_PROT_A; #endif /*defined(FEATURE_ESAME)*/ } regs->TEA |= regs->dat.stid; regs->excarid = (arn > 0 && arn < 16 ? arn : 0); #endif /*FEATURE_SUPPRESSION_ON_PROTECTION*/ #if defined(_FEATURE_PROTECTION_INTERCEPTION_CONTROL) if(SIE_MODE(regs) && regs->hostregs->dat.protect) { #ifdef FEATURE_SUPPRESSION_ON_PROTECTION regs->hostregs->TEA = regs->TEA; regs->hostregs->excarid = regs->excarid; #endif /*FEATURE_SUPPRESSION_ON_PROTECTION*/ (regs->hostregs->program_interrupt) (regs->hostregs, PGM_PROTECTION_EXCEPTION); } else #endif /*defined(_FEATURE_PROTECTION_INTERCEPTION_CONTROL)*/ regs->program_interrupt (regs, PGM_PROTECTION_EXCEPTION); vabs_prog_check: regs->program_interrupt (regs, regs->dat.xcode); return NULL; /* prevent warning from compiler */ } /* end function ARCH_DEP(logical_to_main) */ #endif /*!defined(OPTION_NO_INLINE_LOGICAL) || defined(_DAT_C) */ /* end of DAT.H */ hercules-3.07/decimal.c000644 000765 000765 00000154100 11143760543 016512 0ustar00jmaynardjmaynard000000 000000 /* DECIMAL.C (c) Copyright Roger Bowler, 1991-2009 */ /* ESA/390 Packed Decimal Routines */ // $Id: decimal.c 5125 2009-01-23 12:01:44Z bernard $ /*-------------------------------------------------------------------*/ /* This module contains packed decimal subroutines for ESA/390. */ /* */ /* Acknowledgements: */ /* The lowest level string-math functions are modelled on */ /* algorithms in D.E.Knuth's 'The Art of Computer Programming */ /* Vol.2', and on C.E.Burton's algorithms in DDJ #89. */ /*-------------------------------------------------------------------*/ /*-------------------------------------------------------------------*/ /* Complete rework for reworked instruction decode/execution code */ /* Jan Jaeger 01/07/00 */ /* Add trialrun to ED and EDMK Jan Jaeger 19/07/00 */ /* Fix random MP bug - Mario Bezzi */ /* Clear DXC on data exception - Peter Kuschnerus V209*/ /* z/Architecture support - (c) Copyright Jan Jaeger, 1999-2009 */ /* TP instruction - Roger Bowler 08/02/01 */ /* packed_to_binary subroutine - Roger Bowler 29/06/03 */ /* binary_to_packed subroutine - Roger Bowler 02jul2003 */ /*-------------------------------------------------------------------*/ // $Log$ // Revision 1.24 2007/06/23 00:04:08 ivan // Update copyright notices to include current year (2007) // // Revision 1.23 2007/01/13 07:15:12 bernard // backout ccmask // // Revision 1.22 2007/01/12 15:21:52 bernard // ccmask phase 1 // // Revision 1.21 2006/12/08 09:43:20 jj // Add CVS message log // #include "hstdinc.h" #if !defined(_HENGINE_DLL_) #define _HENGINE_DLL_ #endif #if !defined(_DECIMAL_C_) #define _DECIMAL_C_ #endif #include "hercules.h" #include "opcode.h" #include "inline.h" #if !defined(_DECIMAL_C) #define _DECIMAL_C /*-------------------------------------------------------------------*/ /* Internal macro definitions */ /*-------------------------------------------------------------------*/ #define MAX_DECIMAL_LENGTH 16 #define MAX_DECIMAL_DIGITS (((MAX_DECIMAL_LENGTH)*2)-1) /*-------------------------------------------------------------------*/ /* Convert packed decimal number to binary */ /* */ /* This subroutine is called by the CVB/CVBY/CVBG instructions. */ /* It performs the conversion of a 8-byte or 16-byte packed */ /* decimal number into a 64-bit SIGNED binary result. */ /* This routine is not architecture-dependent; all of its operands */ /* are contained in work areas passed by the architecture-dependent */ /* instruction routines which handle all main-storage accesses and */ /* possible program checks. */ /* */ /* Input: */ /* dec An 8 or 16 byte area containing a copy of the */ /* packed decimal storage operand. */ /* len Length-1 (in bytes) of the packed decimal input */ /* (7 for CVB/CVBY or 15 for CVBG). */ /* Output: */ /* result Points to an U64 field which will receive the */ /* result as a 64-bit SIGNED binary number. */ /* ovf Points to an int field which will be set to 1 if */ /* the result overflows 63 bits plus sign, else 0. */ /* If overflow occurs, the result field will contain */ /* the rightmost 64 bits of the result. */ /* dxf Points to an int field which will be set to 1 if */ /* invalid digits or sign were detected, else 0. */ /* The result field is not set if the dxf is set to 1. */ /*-------------------------------------------------------------------*/ void packed_to_binary (BYTE *dec, int len, U64 *result, int *ovf, int *dxf) { U64 dreg; /* 64-bit result accumulator */ int i; /* Loop counter */ int h, d=0; /* Decimal digits */ U64 inter_u64max_div10; int inter_u64max_rem10; U64 pos_u64max = 9223372036854775807ULL; // (LLONG_MAX) U64 neg_u64max = 9223372036854775808ULL; // (LLONG_MIN) /* Initialize result flags */ *ovf = 0; *dxf = 0; /* Initialize 64-bit result accumulator */ dreg = 0; /* Initialize max unsigned intermediate value for overflow check */ if ((dec[len] & 0x0F) == 0x0B || (dec[len] & 0x0F) == 0x0D) { inter_u64max_div10 = (neg_u64max / 10); inter_u64max_rem10 = (int) (neg_u64max % 10); } else if ((dec[len] & 0x0F) < 0x0A) { *dxf = 1; return; } else { inter_u64max_div10 = (pos_u64max / 10); inter_u64max_rem10 = (int) (pos_u64max % 10); } /* Convert decimal digits to binary */ for (i = 0; i <= len; i++) { /* Isolate high-order and low-order digits */ h = (dec[i] & 0xF0) >> 4; d = dec[i] & 0x0F; /* Data exception if high-order digit is invalid */ if (h > 9) { *dxf = 1; return; } /* Check for overflow before accumulating */ if ( dreg > inter_u64max_div10 || (dreg == inter_u64max_div10 && h > inter_u64max_rem10)) // (NOTE: 'h', not 'd') { *ovf = 1; } /* Accumulate high-order digit into result */ dreg *= 10; dreg += h; /* Check for valid low-order digit or sign */ if (i < len) { /* Data exception if low-order digit is invalid */ if (d > 9) { *dxf = 1; return; } /* Check for overflow before accumulating */ if ( dreg > inter_u64max_div10 || (dreg == inter_u64max_div10 && d > inter_u64max_rem10)) // (NOTE: 'd', not 'h') { *ovf = 1; } /* Accumulate low-order digit into result */ dreg *= 10; dreg += d; } else { /* Data exception if sign is invalid */ if (d < 10) { *dxf = 1; return; } } } /* end for(i) */ /* Result is negative if sign is X'B' or X'D' */ if (d == 0x0B || d == 0x0D) { /* Check for UNDERflow (less than min negative) */ if ( dreg > neg_u64max ) *ovf = 1; else dreg = -((S64)dreg); } else { /* Check for OVERflow (greater than max positive) */ if ( dreg > pos_u64max ) *ovf = 1; } /* Set result field and return */ *result = dreg; } /* end function packed_to_binary */ /*-------------------------------------------------------------------*/ /* Convert binary number to packed decimal */ /* */ /* This subroutine is called by the CVD/CVDY/CVDG instructions. */ /* It performs the conversion of a 64-bit signed binary number */ /* to a 16-byte packed decimal result. Since the maximum 63 bit */ /* number is less than 31 decimal digits, overflow cannot occur. */ /* Similarly, the maximum 31 bit number is less than 15 decimal */ /* digits, therefore CVD/CVDY can safely use the rightmost eight */ /* bytes of the packed decimal result without risk of overflow. */ /* */ /* This routine is not architecture-dependent; all of its operands */ /* are contained in work areas passed by the architecture-dependent */ /* instruction routines which handle all main-storage accesses and */ /* possible program checks. */ /* */ /* Input: */ /* bin Binary number (63 bits plus sign) */ /* Output: */ /* result Points to a 16-byte field which will receive the */ /* result as a packed decimal number (31 digits + sign) */ /*-------------------------------------------------------------------*/ void binary_to_packed (S64 bin, BYTE *result) { int i; /* Array subscript */ int d; /* Decimal digit or sign */ /* Special case when input is maximum negative value */ if ((U64)bin == 0x8000000000000000ULL) { memcpy (result, "\x00\x00\x00\x00\x00\x00\x92\x23" "\x37\x20\x36\x85\x47\x75\x80\x8D", 16); } else { /* Load absolute value and generate sign */ if ((U64)bin < 0x8000000000000000ULL) { /* Value is positive */ d = 0x0C; } else { /* Value is negative */ bin = -bin; d = 0x0D; } /* Store sign and decimal digits from right to left */ memset (result, 0, 16); for (i = 16 - 1; d != 0 || bin != 0; i--) { result[i] = d; d = bin % 10; bin /= 10; result[i] |= (d << 4); d = bin % 10; bin /= 10; } } } /* end function(binary_to_packed) */ /*-------------------------------------------------------------------*/ /* Add two decimal byte strings as unsigned decimal numbers */ /* */ /* Input: */ /* dec1 A 31-byte area containing the decimal digits of */ /* the first operand. Each byte contains one decimal */ /* digit in the low-order 4 bits of the byte. */ /* dec2 A 31-byte area containing the decimal digits of */ /* the second operand. Each byte contains one decimal */ /* digit in the low-order 4 bits of the byte. */ /* Output: */ /* result Points to a 31-byte area to contain the result */ /* digits. One decimal digit is placed in the low-order */ /* 4 bits of each byte. */ /* count Points to an integer to receive the number of */ /* digits in the result excluding leading zeroes. */ /* This field is set to zero if the result is all zero, */ /* or to MAX_DECIMAL_DIGITS+1 if overflow occurred. */ /*-------------------------------------------------------------------*/ static void add_decimal (BYTE *dec1, BYTE *dec2, BYTE *result, int *count) { int d; /* Decimal digit */ int i; /* Array subscript */ int n = 0; /* Significant digit counter */ int carry = 0; /* Carry indicator */ /* Add digits from right to left */ for (i = MAX_DECIMAL_DIGITS - 1; i >= 0; i--) { /* Add digits from first and second operands */ d = dec1[i] + dec2[i] + carry; /* Check for carry into next digit */ if (d > 9) { d -= 10; carry = 1; } else { carry = 0; } /* Check for significant digit */ if (d != 0) n = MAX_DECIMAL_DIGITS - i; /* Store digit in result */ result[i] = d; } /* end for */ /* Check for carry out of leftmost digit */ if (carry) n = MAX_DECIMAL_DIGITS + 1; /* Return significant digit counter */ *count = n; } /* end function add_decimal */ /*-------------------------------------------------------------------*/ /* Subtract two decimal byte strings as unsigned decimal numbers */ /* */ /* Input: */ /* dec1 A 31-byte area containing the decimal digits of */ /* the first operand. Each byte contains one decimal */ /* digit in the low-order 4 bits of the byte. */ /* dec2 A 31-byte area containing the decimal digits of */ /* the second operand. Each byte contains one decimal */ /* digit in the low-order 4 bits of the byte. */ /* Output: */ /* result Points to a 31-byte area to contain the result */ /* digits. One decimal digit is placed in the low-order */ /* 4 bits of each byte. */ /* count Points to an integer to receive the number of */ /* digits in the result excluding leading zeroes. */ /* This field is set to zero if the result is all zero. */ /* sign -1 if the result is negative (operand2 > operand1) */ /* +1 if the result is positive (operand2 <= operand1) */ /*-------------------------------------------------------------------*/ static void subtract_decimal (BYTE *dec1, BYTE *dec2, BYTE *result, int *count, int *sign) { int d; /* Decimal digit */ int i; /* Array subscript */ int n = 0; /* Significant digit counter */ int borrow = 0; /* Borrow indicator */ int rc; /* Return code */ BYTE *higher; /* -> Higher value operand */ BYTE *lower; /* -> Lower value operand */ /* Compare digits to find which operand has higher numeric value */ rc = memcmp (dec1, dec2, MAX_DECIMAL_DIGITS); /* Return positive zero result if both operands are equal */ if (rc == 0) { memset (result, 0, MAX_DECIMAL_DIGITS); *count = 0; *sign = +1; return; } /* Point to higher and lower value operands and set sign */ if (rc > 0) { higher = dec1; lower = dec2; *sign = +1; } else { lower = dec1; higher = dec2; *sign = -1; } /* Subtract digits from right to left */ for (i = MAX_DECIMAL_DIGITS - 1; i >= 0; i--) { /* Subtract lower operand digit from higher operand digit */ d = higher[i] - lower[i] - borrow; /* Check for borrow from next digit */ if (d < 0) { d += 10; borrow = 1; } else { borrow = 0; } /* Check for significant digit */ if (d != 0) n = MAX_DECIMAL_DIGITS - i; /* Store digit in result */ result[i] = d; } /* end for */ /* Return significant digit counter */ *count = n; } /* end function subtract_decimal */ /*-------------------------------------------------------------------*/ /* Divide two decimal byte strings as unsigned decimal numbers */ /* */ /* Input: */ /* dec1 A 31-byte area containing the decimal digits of */ /* the dividend. Each byte contains one decimal */ /* digit in the low-order 4 bits of the byte. */ /* count1 The number of significant digits in the dividend. */ /* dec2 A 31-byte area containing the decimal digits of */ /* the divisor. Each byte contains one decimal */ /* digit in the low-order 4 bits of the byte. */ /* count2 The number of significant digits in the divisor. */ /* Output: */ /* quot Points to a 31-byte area to contain the quotient */ /* digits. One decimal digit is placed in the low-order */ /* 4 bits of each byte. */ /* rem Points to a 31-byte area to contain the remainder */ /* digits. One decimal digit is placed in the low-order */ /* 4 bits of each byte. */ /* Restrictions: */ /* It is assumed that the caller has already verified that */ /* divide overflow cannot occur, that the divisor is not zero, */ /* and that the dividend has at least one high order zero. */ /*-------------------------------------------------------------------*/ static void divide_decimal (BYTE *dec1, int count1, BYTE *dec2, int count2, BYTE *quot, BYTE *rem) { BYTE *num1; /* -> dividend digits */ BYTE *num2; /* -> divisor digits */ int div, flag, scale; /* Work areas for algorithm */ int index, index1, index2; /* Work areas for algorithm */ int indexq, indexr, temp1, temp2; /* Work areas for algorithm */ int temp3, temp4, temp5, qtest; /* Work areas for algorithm */ /* Clear the result fields */ memset (quot, 0, MAX_DECIMAL_DIGITS); memset (rem, 0, MAX_DECIMAL_DIGITS); /* If dividend is zero then return zero quotient and remainder */ if (count1 == 0) return; /* If dividend is less than divisor then return zero quotient and set remainder equal to dividend */ if (memcmp (dec1, dec2, MAX_DECIMAL_DIGITS) < 0) { memcpy (rem, dec1, MAX_DECIMAL_DIGITS); return; } /* Adjust dividend digit count to give one leading zero */ count1++; /* Point to significant digits of dividend with leading zero */ num1 = dec1 + MAX_DECIMAL_DIGITS - count1; /* Point to significant digits of divisor */ num2 = dec2 + MAX_DECIMAL_DIGITS - count2; scale = 10 / (num2[0] + 1); if (scale > 1) { for (index1 = count1-1, flag = 0; index1 >= 0; index1--) { div = flag + scale*num1[index1]; num1[index1] = div % 10; flag = div / 10; } /* end for(index1) */ for (index2 = count2-1, flag = 0; index2 >= 0; index2--) { div = flag + scale*num2[index2]; num2[index2] = div % 10; flag = div / 10; } /* end for(index2) */ } /* end if(scale>1) */ for (index1 = 0; index1 < count1-count2; index1++) { if (num2[0] == num1[index1]) qtest = 9; else { temp2 = (index1+1 < count1) ? num1[index1+1] : 0; qtest = (10*num1[index1] + temp2) / num2[0]; } temp2 = num1[index1]; temp4 = num2[0]; temp1 = (count2 >= 2) ? num2[1] : 0; if (index1+1 < count1) { temp3 = num1[index1+1]; temp5 = (index1+2 < count1) ? num1[index1+2] : 0; } else { temp3 = 0; temp5 = 0; } while (qtest*temp1 > (10*(10*temp2 + temp3 - qtest*temp4) + temp5)) --qtest; for (index = index1+count2, index2 = count2-1, flag = 0; index >= index1; index--, index2--) { if (index2 >= 0) flag -= qtest*num2[index2]; div = flag + num1[index]; if (div < 0) { flag = div / 10; div %= 10; if (div < 0) { div += 10; --flag; } } else flag = 0; num1[index] = div; } /* end for(index) */ indexq = MAX_DECIMAL_DIGITS - (count1-count2) + index1; if (flag != 0) { quot[indexq] = qtest - 1; for (index = index1+count2, index2 = count2-1, flag = 0; index >= index1; index--, index2--) { if (index2 >= 0) flag += num2[index2]; div = flag + num1[index]; if (div > 9) { div -= 10; flag = 1; } else flag = 0; num1[index] = div; } /* end for(index) */ } else quot[indexq] = qtest; } /* end for(index1) */ for (index1 = count1-count2, indexr = MAX_DECIMAL_DIGITS-count2, flag = 0; index1 < count1; index1++, indexr++) { div = num1[index1] + 10*flag; rem[indexr] = div / scale; flag = div % scale; } /* end for(index1) */ for (index2 = 0, flag = 0; index2 < count2; index2++) { div = num2[index2] + 10*flag; num2[index2] = div / scale; flag = div % scale; } /* end for(index2) */ } /* end function divide_decimal */ #endif /*!defined(_DECIMAL_C)*/ /*-------------------------------------------------------------------*/ /* Load a packed decimal storage operand into a decimal byte string */ /* */ /* Input: */ /* addr Logical address of packed decimal storage operand */ /* len Length minus one of storage operand (range 0-15) */ /* arn Access register number associated with operand */ /* regs CPU register context */ /* Output: */ /* result Points to a 31-byte area into which the decimal */ /* digits are loaded. One decimal digit is loaded */ /* into the low-order 4 bits of each byte, and the */ /* result is padded to the left with high-order zeroes */ /* if the storage operand contains less than 31 digits. */ /* count Points to an integer to receive the number of */ /* digits in the result excluding leading zeroes. */ /* This field is set to zero if the result is all zero. */ /* sign Points to an integer which will be set to -1 if a */ /* negative sign was loaded from the operand, or +1 if */ /* a positive sign was loaded from the operand. */ /* */ /* A program check may be generated if the logical address */ /* causes an addressing, translation, or fetch protection */ /* exception, or if the operand causes a data exception */ /* because of invalid decimal digits or sign. */ /*-------------------------------------------------------------------*/ static void ARCH_DEP(load_decimal) (VADR addr, int len, int arn, REGS *regs, BYTE *result, int *count, int *sign) { int h; /* Hexadecimal digit */ int i, j; /* Array subscripts */ int n; /* Significant digit counter */ BYTE pack[MAX_DECIMAL_LENGTH]; /* Packed decimal work area */ /* Fetch the packed decimal operand into work area */ memset (pack, 0, sizeof(pack)); ARCH_DEP(vfetchc) (pack+sizeof(pack)-len-1, len, addr, arn, regs); /* Unpack digits into result */ for (i=0, j=0, n=0; i < MAX_DECIMAL_DIGITS; i++) { /* Load source digit */ if (i & 1) h = pack[j++] & 0x0F; else h = pack[j] >> 4; /* Check for valid numeric */ if (h > 9) { regs->dxc = DXC_DECIMAL; ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION); return; } /* Count significant digits */ if (n > 0 || h != 0) n++; /* Store decimal digit in result */ result[i] = h; } /* end for */ /* Check for valid sign */ h = pack[MAX_DECIMAL_LENGTH-1] & 0x0F; if (h < 0x0A) { regs->dxc = DXC_DECIMAL; ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION); return; } /* Set number of significant digits */ *count = n; /* Set sign of operand */ *sign = (h == 0x0B || h == 0x0D) ? -1 : 1; } /* end function ARCH_DEP(load_decimal) */ /*-------------------------------------------------------------------*/ /* Store decimal byte string into packed decimal storage operand */ /* */ /* Input: */ /* addr Logical address of packed decimal storage operand */ /* len Length minus one of storage operand (range 0-15) */ /* arn Access register number associated with operand */ /* regs CPU register context */ /* dec A 31-byte area containing the decimal digits to be */ /* stored. Each byte contains one decimal digit in */ /* the low-order 4 bits of the byte. */ /* sign -1 if a negative sign is to be stored, or +1 if a */ /* positive sign is to be stored. */ /* */ /* A program check may be generated if the logical address */ /* causes an addressing, translation, or protection exception. */ /*-------------------------------------------------------------------*/ static void ARCH_DEP(store_decimal) (VADR addr, int len, int arn, REGS *regs, BYTE *dec, int sign) { int i, j; /* Array subscripts */ BYTE pack[MAX_DECIMAL_LENGTH]; /* Packed decimal work area */ /* if operand crosses page, make sure both pages are accessable */ if((addr & PAGEFRAME_PAGEMASK) != ((addr + len) & PAGEFRAME_PAGEMASK)) ARCH_DEP(validate_operand) (addr, arn, len, ACCTYPE_WRITE_SKP, regs); /* Pack digits into packed decimal work area */ for (i=0, j=0; i < MAX_DECIMAL_DIGITS; i++) { if (i & 1) pack[j++] |= dec[i]; else pack[j] = dec[i] << 4; } /* end for */ /* Pack the sign into low-order digit of work area */ pack[MAX_DECIMAL_LENGTH-1] |= (sign < 0 ? 0x0D : 0x0C); /* Store the result at the operand location */ ARCH_DEP(vstorec) (pack+sizeof(pack)-len-1, len, addr, arn, regs); } /* end function ARCH_DEP(store_decimal) */ /*-------------------------------------------------------------------*/ /* FA AP - Add Decimal [SS] */ /*-------------------------------------------------------------------*/ DEF_INST(add_decimal) { int l1, l2; /* Length values */ int b1, b2; /* Base register numbers */ VADR effective_addr1, effective_addr2; /* Effective addresses */ int cc; /* Condition code */ BYTE dec1[MAX_DECIMAL_DIGITS]; /* Work area for operand 1 */ BYTE dec2[MAX_DECIMAL_DIGITS]; /* Work area for operand 2 */ BYTE dec3[MAX_DECIMAL_DIGITS]; /* Work area for result */ int count1, count2, count3; /* Significant digit counters*/ int sign1, sign2, sign3; /* Sign of operands & result */ SS(inst, regs, l1, l2, b1, effective_addr1, b2, effective_addr2); /* Load operands into work areas */ ARCH_DEP(load_decimal) (effective_addr1, l1, b1, regs, dec1, &count1, &sign1); ARCH_DEP(load_decimal) (effective_addr2, l2, b2, regs, dec2, &count2, &sign2); /* Add or subtract operand values */ if (count2 == 0) { /* If second operand is zero then result is first operand */ memcpy (dec3, dec1, MAX_DECIMAL_DIGITS); count3 = count1; sign3 = sign1; } else if (count1 == 0) { /* If first operand is zero then result is second operand */ memcpy (dec3, dec2, MAX_DECIMAL_DIGITS); count3 = count2; sign3 = sign2; } else if (sign1 == sign2) { /* If signs are equal then add operands */ add_decimal (dec1, dec2, dec3, &count3); sign3 = sign1; } else { /* If signs are opposite then subtract operands */ subtract_decimal (dec1, dec2, dec3, &count3, &sign3); if (sign1 < 0) sign3 = -sign3; } /* Set condition code */ cc = (count3 == 0) ? 0 : (sign3 < 1) ? 1 : 2; /* Overflow if result exceeds first operand length */ if (count3 > (l1+1) * 2 - 1) cc = 3; /* Set positive sign if result is zero */ if (count3 == 0) sign3 = 1; /* Store result into first operand location */ ARCH_DEP(store_decimal) (effective_addr1, l1, b1, regs, dec3, sign3); /* Set condition code */ regs->psw.cc = cc; /* Program check if overflow and PSW program mask is set */ if (cc == 3 && DOMASK(®s->psw)) ARCH_DEP(program_interrupt) (regs, PGM_DECIMAL_OVERFLOW_EXCEPTION); } /* end DEF_INST(add_decimal) */ /*-------------------------------------------------------------------*/ /* F9 CP - Compare Decimal [SS] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_decimal) { int l1, l2; /* Length values */ int b1, b2; /* Base register numbers */ VADR effective_addr1, effective_addr2; /* Effective addresses */ BYTE dec1[MAX_DECIMAL_DIGITS]; /* Work area for operand 1 */ BYTE dec2[MAX_DECIMAL_DIGITS]; /* Work area for operand 2 */ int count1, count2; /* Significant digit counters*/ int sign1, sign2; /* Sign of each operand */ int rc; /* Return code */ SS(inst, regs, l1, l2, b1, effective_addr1, b2, effective_addr2); /* Load operands into work areas */ ARCH_DEP(load_decimal) (effective_addr1, l1, b1, regs, dec1, &count1, &sign1); ARCH_DEP(load_decimal) (effective_addr2, l2, b2, regs, dec2, &count2, &sign2); /* Result is equal if both operands are zero */ if (count1 == 0 && count2 == 0) { regs->psw.cc = 0; return; } /* Result is low if operand 1 is -ve and operand 2 is +ve */ if (sign1 < 0 && sign2 > 0) { regs->psw.cc = 1; return; } /* Result is high if operand 1 is +ve and operand 2 is -ve */ if (sign1 > 0 && sign2 < 0) { regs->psw.cc = 2; return; } /* If signs are equal then compare the digits */ rc = memcmp (dec1, dec2, MAX_DECIMAL_DIGITS); /* Return low or high (depending on sign) if digits are unequal */ if (rc < 0) regs->psw.cc = (sign1 > 0) ? 1 : 2; else if (rc > 0) regs->psw.cc = (sign1 > 0) ? 2 : 1; else regs->psw.cc = 0; } /* end DEF_INST(compare_decimal) */ /*-------------------------------------------------------------------*/ /* FD DP - Divide Decimal [SS] */ /*-------------------------------------------------------------------*/ DEF_INST(divide_decimal) { int l1, l2; /* Length values */ int b1, b2; /* Base register numbers */ VADR effective_addr1, effective_addr2; /* Effective addresses */ BYTE dec1[MAX_DECIMAL_DIGITS]; /* Operand 1 (dividend) */ BYTE dec2[MAX_DECIMAL_DIGITS]; /* Operand 2 (divisor) */ BYTE quot[MAX_DECIMAL_DIGITS]; /* Quotient */ BYTE rem[MAX_DECIMAL_DIGITS]; /* Remainder */ int count1, count2; /* Significant digit counters*/ int sign1, sign2; /* Sign of operands */ int signq, signr; /* Sign of quotient/remainder*/ SS(inst, regs, l1, l2, b1, effective_addr1, b2, effective_addr2); /* Program check if the second operand length exceeds 15 digits or is equal to or greater than the first operand length */ if (l2 > 7 || l2 >= l1) ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION); /* Load operands into work areas */ ARCH_DEP(load_decimal) (effective_addr1, l1, b1, regs, dec1, &count1, &sign1); ARCH_DEP(load_decimal) (effective_addr2, l2, b2, regs, dec2, &count2, &sign2); /* Program check if second operand value is zero */ if (count2 == 0) ARCH_DEP(program_interrupt) (regs, PGM_DECIMAL_DIVIDE_EXCEPTION); /* Perform trial comparison to determine potential overflow. The leftmost digit of the divisor is aligned one digit to the right of the leftmost dividend digit. When the divisor, so aligned, is less than or equal to the dividend, ignoring signs, a divide exception is indicated. As a result of this comparison, it is also certain that the leftmost digit of the dividend must be zero, and that the divisor cannot be zero */ if (memcmp(dec2 + (MAX_DECIMAL_DIGITS - l2*2 - 2), dec1 + (MAX_DECIMAL_DIGITS - l1*2 - 1), l2*2 + 2) <= 0) ARCH_DEP(program_interrupt) (regs, PGM_DECIMAL_DIVIDE_EXCEPTION); /* Perform decimal division */ divide_decimal (dec1, count1, dec2, count2, quot, rem); /* Quotient is positive if operand signs are equal, and negative if operand signs are opposite, even if quotient is zero */ signq = (sign1 == sign2) ? 1 : -1; /* Remainder sign is same as dividend, even if remainder is zero */ signr = sign1; /* Store remainder into entire first operand location. The entire field will be filled in order to check for store protection. Subsequently the quotient will be stored in the leftmost bytes of the first operand location, overwriting high order zeroes */ ARCH_DEP(store_decimal) (effective_addr1, l1, b1, regs, rem, signr); /* Store quotient in leftmost bytes of first operand location */ ARCH_DEP(store_decimal) (effective_addr1, l1-l2-1, b1, regs, quot, signq); } /* end DEF_INST(divide_decimal) */ /*-------------------------------------------------------------------*/ /* DE ED - Edit [SS] */ /* DF EDMK - Edit and Mark [SS] */ /*-------------------------------------------------------------------*/ DEF_INST(edit_x_edit_and_mark) { int l; /* Length value */ int b1, b2; /* Base register numbers */ VADR effective_addr1, effective_addr2, /* Effective addresses */ addr1, addr2; int cc = 0; /* Condition code */ int sig = 0; /* Significance indicator */ int trial_run; /* 1=trial run */ int i; /* Loop counter */ int d; /* 1=Use right source digit */ int h; /* Hexadecimal digit */ BYTE sbyte; /* Source operand byte */ BYTE fbyte; /* Fill byte */ BYTE pbyte; /* Pattern byte */ BYTE rbyte; /* Result byte */ SS_L(inst, regs, l, b1, effective_addr1, b2, effective_addr2); /* If addr1 crosses page, make sure both pages are accessable */ if((effective_addr1 & PAGEFRAME_PAGEMASK) != ((effective_addr1 + l) & PAGEFRAME_PAGEMASK)) ARCH_DEP(validate_operand) (effective_addr1, b1, l, ACCTYPE_WRITE_SKP, regs); /* If addr2 might cross page, do a trial run to catch possible access rupts */ if((effective_addr2 & PAGEFRAME_PAGEMASK) != ((effective_addr2 + l) & PAGEFRAME_PAGEMASK)) trial_run = 1; else trial_run = 0; for(;trial_run >= 0; trial_run--) { /* Initialize variables */ addr1 = effective_addr1; addr2 = effective_addr2; cc = 0; sig = 0; sbyte = 0; fbyte = 0; /* Process first operand from left to right */ for (i = 0, d = 0; i < l+1; i++) { /* Fetch pattern byte from first operand */ pbyte = ARCH_DEP(vfetchb) ( addr1, b1, regs ); /* The first pattern byte is also the fill byte */ if (i == 0) fbyte = pbyte; /* If pattern byte is digit selector (X'20') or significance starter (X'21') then fetch next hexadecimal digit from the second operand */ if (pbyte == 0x20 || pbyte == 0x21) { if (d == 0) { /* Fetch source byte and extract left digit */ sbyte = ARCH_DEP(vfetchb) ( addr2, b2, regs ); h = sbyte >> 4; sbyte &= 0x0F; d = 1; /* Increment second operand address */ addr2++; addr2 &= ADDRESS_MAXWRAP(regs); /* Program check if left digit is not numeric */ if (h > 9) { regs->dxc = DXC_DECIMAL; ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION); } } else { /* Use right digit of source byte */ h = sbyte; d = 0; } /* For the EDMK instruction only, insert address of result byte into general register 1 if the digit is non-zero and significance indicator was off */ if (!trial_run && (inst[0] == 0xDF) && h > 0 && sig == 0) { #if defined(FEATURE_ESAME) if (regs->psw.amode64) regs->GR_G(1) = addr1; else #endif if ( regs->psw.amode ) regs->GR_L(1) = addr1; else regs->GR_LA24(1) = addr1; } /* Replace the pattern byte by the fill character or by a zoned decimal digit */ rbyte = (sig == 0 && h == 0) ? fbyte : (0xF0 | h); if(!trial_run) ARCH_DEP(vstoreb) ( rbyte, addr1, b1, regs ); else ARCH_DEP(validate_operand) (addr1, b1, 0, ACCTYPE_WRITE_SKP, regs); /* Set condition code 2 if digit is non-zero */ if (h > 0) cc = 2; /* Turn on significance indicator if pattern byte is significance starter or if source digit is non-zero */ if (pbyte == 0x21 || h > 0) sig = 1; /* Examine right digit for sign code */ if (d == 1 && sbyte > 9) { /* Turn off the significance indicator if the right digit is a plus sign code */ if (sbyte != 0x0B && sbyte != 0x0D) sig = 0; /* Take next digit from next source byte */ d = 0; } } /* If pattern byte is field separator (X'22') then replace it by the fill character, turn off the significance indicator, and zeroize conditon code */ else if (pbyte == 0x22) { if(!trial_run) ARCH_DEP(vstoreb) ( fbyte, addr1, b1, regs ); else ARCH_DEP(validate_operand) (addr1, b1, 0, ACCTYPE_WRITE_SKP, regs); sig = 0; cc = 0; } /* If pattern byte is a message byte (anything other than X'20', X'21', or X'22') then replace it by the fill byte if the significance indicator is off */ else { if (sig == 0) { if (!trial_run) ARCH_DEP(vstoreb) ( fbyte, addr1, b1, regs ); else ARCH_DEP(validate_operand) (addr1, b1, 0, ACCTYPE_WRITE_SKP, regs); } else /* store message byte */ { if (!trial_run) ARCH_DEP(vstoreb) ( pbyte, addr1, b1, regs ); else ARCH_DEP(validate_operand) (addr1, b1, 0, ACCTYPE_WRITE_SKP, regs); } } /* Increment first operand address */ addr1++; addr1 &= ADDRESS_MAXWRAP(regs); } /* end for(i) */ } /* end for(trial_run) */ /* Replace condition code 2 by condition code 1 if the significance indicator is on at the end of editing */ if (sig && cc == 2) cc = 1; /* Set condition code */ regs->psw.cc = cc; } /* end DEF_INST(edit_x_edit_and_mark) */ /*-------------------------------------------------------------------*/ /* FC MP - Multiply Decimal [SS] */ /*-------------------------------------------------------------------*/ DEF_INST(multiply_decimal) { int l1, l2; /* Length values */ int b1, b2; /* Base register numbers */ VADR effective_addr1, effective_addr2; /* Effective addresses */ BYTE dec1[MAX_DECIMAL_DIGITS]; /* Work area for operand 1 */ BYTE dec2[MAX_DECIMAL_DIGITS]; /* Work area for operand 2 */ BYTE dec3[MAX_DECIMAL_DIGITS]; /* Work area for result */ int count1, count2; /* Significant digit counters*/ int sign1, sign2, sign3; /* Sign of operands & result */ int d; /* Decimal digit */ int i1, i2, i3; /* Array subscripts */ int carry; /* Carry indicator */ SS(inst, regs, l1, l2, b1, effective_addr1, b2, effective_addr2); /* Program check if the second operand length exceeds 15 digits or is equal to or greater than the first operand length */ if (l2 > 7 || l2 >= l1) ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION); /* Load operands into work areas */ ARCH_DEP(load_decimal) (effective_addr1, l1, b1, regs, dec1, &count1, &sign1); ARCH_DEP(load_decimal) (effective_addr2, l2, b2, regs, dec2, &count2, &sign2); /* Program check if the number of bytes in the second operand is less than the number of bytes of high-order zeroes in the first operand; this ensures that overflow cannot occur */ if (l2 > l1 - (count1/2 + 1)) { regs->dxc = DXC_DECIMAL; ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION); } /* Clear the result field */ memset (dec3, 0, MAX_DECIMAL_DIGITS); /* Perform decimal multiplication */ for (i2 = MAX_DECIMAL_DIGITS-1; i2 >= 0; i2--) { if (dec2[i2] != 0) { for (i1 = MAX_DECIMAL_DIGITS - 1, i3 = i2, carry = 0; i3 >= 0; i1--, i3--) { d = carry + dec1[i1]*dec2[i2] + dec3[i3]; dec3[i3] = d % 10; carry = d / 10; } } } /* end for(i2) */ /* Result is positive if operand signs are equal, and negative if operand signs are opposite, even if result is zero */ sign3 = (sign1 == sign2) ? 1 : -1; /* Store result into first operand location */ ARCH_DEP(store_decimal) (effective_addr1, l1, b1, regs, dec3, sign3); } /* end DEF_INST(multiply_decimal) */ /*-------------------------------------------------------------------*/ /* F0 SRP - Shift and Round Decimal [SS] */ /*-------------------------------------------------------------------*/ DEF_INST(shift_and_round_decimal) { int l1, i3; /* Length and rounding */ int b1, b2; /* Base register numbers */ VADR effective_addr1, effective_addr2; /* Effective addresses */ int cc; /* Condition code */ BYTE dec[MAX_DECIMAL_DIGITS]; /* Work area for operand */ int count; /* Significant digit counter */ int sign; /* Sign of operand/result */ int i, j; /* Array subscripts */ int d; /* Decimal digit */ int carry; /* Carry indicator */ SS(inst, regs, l1, i3, b1, effective_addr1, b2, effective_addr2); /* Load operand into work area */ ARCH_DEP(load_decimal) (effective_addr1, l1, b1, regs, dec, &count, &sign); /* Program check if rounding digit is invalid */ if (i3 > 9) { regs->dxc = DXC_DECIMAL; ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION); } /* Isolate low-order six bits of shift count */ effective_addr2 &= 0x3F; /* Shift count 0-31 means shift left, 32-63 means shift right */ if (effective_addr2 < 32) { /* Set condition code according to operand sign */ cc = (count == 0) ? 0 : (sign < 0) ? 1 : 2; /* Set cc=3 if non-zero digits will be lost on left shift */ if (count > 0 && effective_addr2 > (VADR)((l1+1)*2 - 1 - count)) cc = 3; /* Shift operand left */ for (i=0, j=effective_addr2; i < MAX_DECIMAL_DIGITS; i++, j++) dec[i] = (j < MAX_DECIMAL_DIGITS) ? dec[j] : 0; } else { /* Calculate number of digits (1-32) to shift right */ effective_addr2 = 64 - effective_addr2; /* Add the rounding digit to the leftmost of the digits to be shifted out and propagate the carry to the left */ carry = (effective_addr2 > MAX_DECIMAL_DIGITS) ? 0 : (dec[MAX_DECIMAL_DIGITS - effective_addr2] + i3) / 10; count = 0; /* Shift operand right */ for (i=MAX_DECIMAL_DIGITS-1, j=MAX_DECIMAL_DIGITS-1-effective_addr2; i >= 0; i--, j--) { d = (j >= 0) ? dec[j] : 0; d += carry; carry = d / 10; d %= 10; dec[i] = d; if (d != 0) count = MAX_DECIMAL_DIGITS - i; } /* Set condition code according to operand sign */ cc = (count == 0) ? 0 : (sign < 0) ? 1 : 2; } /* Make sign positive if result is zero */ if (cc == 0) sign = +1; /* Store result into operand location */ ARCH_DEP(store_decimal) (effective_addr1, l1, b1, regs, dec, sign); /* Set condition code */ regs->psw.cc = cc; /* Program check if overflow and PSW program mask is set */ if (cc == 3 && DOMASK(®s->psw)) ARCH_DEP(program_interrupt) (regs, PGM_DECIMAL_OVERFLOW_EXCEPTION); } /* end DEF_INST(shift_and_round_decimal) */ /*-------------------------------------------------------------------*/ /* FB SP - Subtract Decimal [SS] */ /*-------------------------------------------------------------------*/ DEF_INST(subtract_decimal) { int l1, l2; /* Length values */ int b1, b2; /* Base register numbers */ VADR effective_addr1, effective_addr2; /* Effective addresses */ int cc; /* Condition code */ BYTE dec1[MAX_DECIMAL_DIGITS]; /* Work area for operand 1 */ BYTE dec2[MAX_DECIMAL_DIGITS]; /* Work area for operand 2 */ BYTE dec3[MAX_DECIMAL_DIGITS]; /* Work area for result */ int count1, count2, count3; /* Significant digit counters*/ int sign1, sign2, sign3; /* Sign of operands & result */ SS(inst, regs, l1, l2, b1, effective_addr1, b2, effective_addr2); /* Load operands into work areas */ ARCH_DEP(load_decimal) (effective_addr1, l1, b1, regs, dec1, &count1, &sign1); ARCH_DEP(load_decimal) (effective_addr2, l2, b2, regs, dec2, &count2, &sign2); /* Add or subtract operand values */ if (count2 == 0) { /* If second operand is zero then result is first operand */ memcpy (dec3, dec1, MAX_DECIMAL_DIGITS); count3 = count1; sign3 = sign1; } else if (count1 == 0) { /* If first operand is zero then result is -second operand */ memcpy (dec3, dec2, MAX_DECIMAL_DIGITS); count3 = count2; sign3 = -sign2; } else if (sign1 != sign2) { /* If signs are opposite then add operands */ add_decimal (dec1, dec2, dec3, &count3); sign3 = sign1; } else { /* If signs are equal then subtract operands */ subtract_decimal (dec1, dec2, dec3, &count3, &sign3); if (sign1 < 0) sign3 = -sign3; } /* Set condition code */ cc = (count3 == 0) ? 0 : (sign3 < 1) ? 1 : 2; /* Overflow if result exceeds first operand length */ if (count3 > (l1+1) * 2 - 1) cc = 3; /* Set positive sign if result is zero */ if (count3 == 0) sign3 = 1; /* Store result into first operand location */ ARCH_DEP(store_decimal) (effective_addr1, l1, b1, regs, dec3, sign3); /* Return condition code */ regs->psw.cc = cc; /* Program check if overflow and PSW program mask is set */ if (cc == 3 && DOMASK(®s->psw)) ARCH_DEP(program_interrupt) (regs, PGM_DECIMAL_OVERFLOW_EXCEPTION); } /* end DEF_INST(subtract_decimal) */ /*-------------------------------------------------------------------*/ /* F8 ZAP - Zero and Add [SS] */ /*-------------------------------------------------------------------*/ DEF_INST(zero_and_add) { int l1, l2; /* Length values */ int b1, b2; /* Base register numbers */ VADR effective_addr1, effective_addr2; /* Effective addresses */ int cc; /* Condition code */ BYTE dec[MAX_DECIMAL_DIGITS]; /* Work area for operand */ int count; /* Significant digit counter */ int sign; /* Sign */ SS(inst, regs, l1, l2, b1, effective_addr1, b2, effective_addr2); /* Load second operand into work area */ ARCH_DEP(load_decimal) (effective_addr2, l2, b2, regs, dec, &count, &sign); /* Set condition code */ cc = (count == 0) ? 0 : (sign < 1) ? 1 : 2; /* Overflow if result exceeds first operand length */ if (count > (l1+1) * 2 - 1) cc = 3; /* Set positive sign if result is zero */ if (count == 0) sign = +1; /* Store result into first operand location */ ARCH_DEP(store_decimal) (effective_addr1, l1, b1, regs, dec, sign); /* Return condition code */ regs->psw.cc = cc; /* Program check if overflow and PSW program mask is set */ if (cc == 3 && DOMASK(®s->psw)) ARCH_DEP(program_interrupt) (regs, PGM_DECIMAL_OVERFLOW_EXCEPTION); } /* end DEF_INST(zero_and_add) */ #if defined(FEATURE_EXTENDED_TRANSLATION_FACILITY_2) /*-------------------------------------------------------------------*/ /* EBC0 TP - Test Decimal [RSL] */ /*-------------------------------------------------------------------*/ DEF_INST(test_decimal) { int l1; /* Length value */ int b1; /* Base register number */ VADR effective_addr1; /* Effective address */ int i; /* Array subscript */ int cc = 0; /* Condition code */ BYTE pack[MAX_DECIMAL_LENGTH]; /* Packed decimal work area */ RSL(inst, regs, l1, b1, effective_addr1); /* Fetch the packed decimal operand into the work area */ ARCH_DEP(vfetchc) (pack, l1, effective_addr1, b1, regs); /* Test each byte of the operand */ for (i=0; ; i++) { /* Test the high-order digit of the byte */ if ((pack[i] & 0xF0) > 0x90) cc = 2; /* Exit if this is the last byte */ if (i == l1) break; /* Test the low-order digit of the byte */ if ((pack[i] & 0x0F) > 0x09) cc = 2; } /* Test the sign in the last byte */ if ((pack[i] & 0x0F) < 0x0A) cc |= 1; /* Return condition code */ regs->psw.cc = cc; } /* end DEF_INST(test_decimal) */ #endif /*defined(FEATURE_EXTENDED_TRANSLATION_FACILITY_2)*/ #if !defined(_GEN_ARCH) #if defined(_ARCHMODE2) #define _GEN_ARCH _ARCHMODE2 #include "decimal.c" #endif #if defined(_ARCHMODE3) #undef _GEN_ARCH #define _GEN_ARCH _ARCHMODE3 #include "decimal.c" #endif #endif /*!defined(_GEN_ARCH)*/ hercules-3.07/decNumber/000777 000765 000765 00000000000 11345533274 016662 5ustar00jmaynardjmaynard000000 000000 hercules-3.07/devtype.h000644 000765 000765 00000006103 11143760543 016600 0ustar00jmaynardjmaynard000000 000000 /* DEVTYPE.H (c) Copyright Jan Jaeger, 1999-2009 */ /* Hercules Device Definitions */ // $Id: devtype.h 5125 2009-01-23 12:01:44Z bernard $ // // $Log$ // Revision 1.21 2007/11/21 22:48:45 fish // New BEGIN_DEVICE_CLASS_QUERY macro // // Revision 1.20 2007/06/23 00:04:08 ivan // Update copyright notices to include current year (2007) // // Revision 1.19 2006/12/08 09:43:20 jj // Add CVS message log // #if !defined(_DEVICES_H) #define _DEVICES_H #ifndef _FBADASD_C_ #ifndef _HDASD_DLL_ #define FBA_DLL_IMPORT DLL_IMPORT #else /* _HDASD_DLL_ */ #define FBA_DLL_IMPORT extern #endif /* _HDASD_DLL_ */ #else #define FBA_DLL_IMPORT DLL_EXPORT #endif #ifndef _CKDDASD_C_ #ifndef _HDASD_DLL_ #define CKD_DLL_IMPORT DLL_IMPORT #else /* _HDASD_DLL_ */ #define CKD_DLL_IMPORT extern #endif /* _HDASD_DLL_ */ #else #define CKD_DLL_IMPORT DLL_EXPORT #endif struct DEVHND { DEVIF *init; /* Device Initialisation */ DEVXF *exec; /* Device CCW execute */ DEVCF *close; /* Device Close */ DEVQF *query; /* Device Query */ DEVSF *start; /* Device Start channel pgm */ DEVSF *end; /* Device End channel pgm */ DEVSF *resume; /* Device Resume channel pgm */ DEVSF *suspend; /* Device Suspend channel pgm */ DEVRF *read; /* Device Read */ DEVWF *write; /* Device Write */ DEVUF *used; /* Device Query used */ DEVRR *reserve; /* Device Reserve */ DEVRR *release; /* Device Release */ DEVRR *attention; /* Device Attention */ DEVIM immed; /* Immediate CCW Codes */ DEVSA *siga_r; /* Signal Adapter Input */ DEVSA *siga_w; /* Signal Adapter Output */ DEVSR *hsuspend; /* Hercules suspend */ DEVSR *hresume; /* Hercules resume */ }; #define BEGIN_DEVICE_CLASS_QUERY( _classname, _dev, _class, _buflen, _buffer ) \ if (_class) *_class = _classname; \ if (!_dev || !_class || !_buflen || !_buffer) return #if !defined(OPTION_DYNAMIC_LOAD) extern DEVHND constty_device_hndinfo; extern DEVHND loc3270_device_hndinfo; extern DEVHND comadpt_device_hndinfo; extern DEVHND cardrdr_device_hndinfo; extern DEVHND cardpch_device_hndinfo; extern DEVHND printer_device_hndinfo; extern DEVHND tapedev_device_hndinfo; #endif /*!defined(OPTION_DYNAMIC_LOAD)*/ CKD_DLL_IMPORT DEVHND ckddasd_device_hndinfo; FBA_DLL_IMPORT DEVHND fbadasd_device_hndinfo; extern DEVHND ctcadpt_device_hndinfo; extern DEVHND ctci_device_hndinfo; extern DEVHND ctct_device_hndinfo; extern DEVHND lcs_device_hndinfo; extern DEVHND vmnet_device_hndinfo; #endif /*!defined(_DEVICES_H)*/ hercules-3.07/dfp.c000644 000765 000765 00000433636 11143760544 015704 0ustar00jmaynardjmaynard000000 000000 /* DFP.C (c) Copyright Roger Bowler, 2007-2009 */ /* Decimal Floating Point instructions */ // $Id: dfp.c 5125 2009-01-23 12:01:44Z bernard $ /*-------------------------------------------------------------------*/ /* This module implements the Decimal Floating Point instructions */ /* and the Floating Point Support Enhancement Facility instructions */ /* described in the z/Architecture Principles of Operation manual. */ /*-------------------------------------------------------------------*/ // $Log$ // Revision 1.70 2008/11/23 11:18:50 rbowler // Fix signed/unsigned mismatch caused by previous fix // // Revision 1.69 2008/11/23 11:11:54 rbowler // Fix warning C4267 conversion from 'size_t' to 'int' in win64 // // Revision 1.68 2008/11/23 11:06:04 rbowler // Cosmetic: remove extraneous trailing blanks from dfp.c // // Revision 1.67 2007/11/23 12:28:07 rbowler // Correct CPSDR when R1 and R3 are same register (2nd attempt) // // Revision 1.66 2007/11/15 22:11:26 rbowler // Correct CPSDR when R1 and R3 are same register // // Revision 1.65 2007/06/23 00:04:08 ivan // Update copyright notices to include current year (2007) // // Revision 1.64 2007/04/25 12:33:20 rbowler // Move SRNMT to Floating-point-support-enhancement facility // // Revision 1.63 2007/04/25 12:10:27 rbowler // Move LFAS,SFASR to IEEE-exception-simulation facility // // Revision 1.62 2007/03/13 01:52:42 gsmith // Fix unsigned char (BYTE) vs char warnings for decNumberFromString // // Revision 1.61 2007/01/30 16:43:28 rbowler // Activate Decimal Floating Point Facility // // Revision 1.10 2006/12/08 09:43:20 jj // Add CVS message log // #include "hstdinc.h" #if !defined(_HENGINE_DLL_) #define _HENGINE_DLL_ #endif #if !defined(_DFP_C_) #define _DFP_C_ #endif #include "hercules.h" #include "opcode.h" #include "inline.h" #if defined(FEATURE_DECIMAL_FLOATING_POINT) #include "decimal128.h" #include "decimal64.h" #include "decimal32.h" #include "decPacked.h" #endif /*defined(FEATURE_DECIMAL_FLOATING_POINT)*/ #if defined(FEATURE_FPS_ENHANCEMENT) /*===================================================================*/ /* FLOATING POINT SUPPORT INSTRUCTIONS */ /*===================================================================*/ /* Note: the Floating Point Support instructions use the HFPREG_CHECK and HFPREG2_CHECK macros to enforce an AFP-register data exception if an FPS instruction attempts to use one of the 12 additional FPR registers when the AFP-register-control bit in CR0 is zero. */ /*-------------------------------------------------------------------*/ /* B370 LPDFR - Load Positive FPR Long Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(load_positive_fpr_long_reg) { int r1, r2; /* Values of R fields */ int i1, i2; /* FP register subscripts */ RRE(inst, regs, r1, r2); HFPREG2_CHECK(r1, r2, regs); i1 = FPR2I(r1); i2 = FPR2I(r2); /* Copy register contents, clear the sign bit */ regs->fpr[i1] = regs->fpr[i2] & 0x7FFFFFFF; regs->fpr[i1+1] = regs->fpr[i2+1]; } /* end DEF_INST(load_positive_fpr_long_reg) */ /*-------------------------------------------------------------------*/ /* B371 LNDFR - Load Negative FPR Long Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(load_negative_fpr_long_reg) { int r1, r2; /* Values of R fields */ int i1, i2; /* FP register subscripts */ RRE(inst, regs, r1, r2); HFPREG2_CHECK(r1, r2, regs); i1 = FPR2I(r1); i2 = FPR2I(r2); /* Copy register contents, set the sign bit */ regs->fpr[i1] = regs->fpr[i2] | 0x80000000; regs->fpr[i1+1] = regs->fpr[i2+1]; } /* end DEF_INST(load_negative_fpr_long_reg) */ /*-------------------------------------------------------------------*/ /* B372 CPSDR - Copy Sign FPR Long Register [RRF] */ /*-------------------------------------------------------------------*/ DEF_INST(copy_sign_fpr_long_reg) { int r1, r2, r3; /* Values of R fields */ int i1, i2, i3; /* FP register subscripts */ U32 sign; /* Work area for sign bit */ RRF_M(inst, regs, r1, r2, r3); HFPREG2_CHECK(r1, r2, regs); HFPREG_CHECK(r3, regs); i1 = FPR2I(r1); i2 = FPR2I(r2); i3 = FPR2I(r3); /* Copy the sign bit from r3 register */ sign = regs->fpr[i3] & 0x80000000; /* Copy r2 register contents to r1 register */ regs->fpr[i1] = regs->fpr[i2]; regs->fpr[i1+1] = regs->fpr[i2+1]; /* Insert the sign bit into r1 register */ regs->fpr[i1] &= 0x7FFFFFFF; regs->fpr[i1] |= sign; } /* end DEF_INST(copy_sign_fpr_long_reg) */ /*-------------------------------------------------------------------*/ /* B373 LCDFR - Load Complement FPR Long Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(load_complement_fpr_long_reg) { int r1, r2; /* Values of R fields */ int i1, i2; /* FP register subscripts */ RRE(inst, regs, r1, r2); HFPREG2_CHECK(r1, r2, regs); i1 = FPR2I(r1); i2 = FPR2I(r2); /* Copy register contents, invert sign bit */ regs->fpr[i1] = regs->fpr[i2] ^ 0x80000000; regs->fpr[i1+1] = regs->fpr[i2+1]; } /* end DEF_INST(load_complement_fpr_long_reg) */ /*-------------------------------------------------------------------*/ /* B3C1 LDGR - Load FPR from GR Long Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(load_fpr_from_gr_long_reg) { int r1, r2; /* Values of R fields */ int i1; /* FP register subscript */ RRE(inst, regs, r1, r2); HFPREG_CHECK(r1, regs); i1 = FPR2I(r1); /* Load FP register contents from general register */ regs->fpr[i1] = regs->GR_H(r2); regs->fpr[i1+1] = regs->GR_L(r2); } /* end DEF_INST(load_fpr_from_gr_long_reg) */ /*-------------------------------------------------------------------*/ /* B3CD LGDR - Load GR from FPR Long Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(load_gr_from_fpr_long_reg) { int r1, r2; /* Values of R fields */ int i2; /* FP register subscript */ RRE(inst, regs, r1, r2); HFPREG_CHECK(r2, regs); i2 = FPR2I(r2); /* Load general register contents from FP register */ regs->GR_H(r1) = regs->fpr[i2]; regs->GR_L(r1) = regs->fpr[i2+1]; } /* end DEF_INST(load_gr_from_fpr_long_reg) */ /*-------------------------------------------------------------------*/ /* B2B9 SRNMT - Set DFP Rounding Mode [S] */ /*-------------------------------------------------------------------*/ DEF_INST(set_dfp_rounding_mode) { int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ S(inst, regs, b2, effective_addr2); DFPINST_CHECK(regs); /* Set DFP rounding mode in FPC register from address bits 61-63 */ regs->fpc &= ~(FPC_DRM); regs->fpc |= ((effective_addr2 << FPC_DRM_SHIFT) & FPC_DRM); } /* end DEF_INST(set_dfp_rounding_mode) */ #endif /*defined(FEATURE_FPS_ENHANCEMENT)*/ #if defined(FEATURE_IEEE_EXCEPTION_SIMULATION) /*===================================================================*/ /* IEEE-EXCEPTION-SIMULATION FACILITY INSTRUCTIONS */ /*===================================================================*/ #if !defined(_IXS_ARCH_INDEPENDENT_) /*-------------------------------------------------------------------*/ /* Check if a simulated-IEEE-exception event is to be recognized */ /* */ /* This subroutine is called by the LFAS and SFASR instructions to */ /* determine whether the instruction should raise a data exception */ /* at the end of the instruction and, if so, the DXC code to be set. */ /* */ /* Input: */ /* cur_fpc Current value of the FPC register */ /* src_fpc Value of instruction source operand */ /* Output: */ /* The return value is the data exception code (DXC), or */ /* zero if no simulated-IEEE-exception event is recognized */ /*-------------------------------------------------------------------*/ static BYTE fpc_signal_check(U32 cur_fpc, U32 src_fpc) { U32 ff, sm, enabled_flags; /* Mask and flag work areas */ BYTE dxc; /* Data exception code or 0 */ /* AND the current FPC flags with the source FPC mask */ ff = (cur_fpc & FPC_FLAG) >> FPC_FLAG_SHIFT; sm = (src_fpc & FPC_MASK) >> FPC_MASK_SHIFT; enabled_flags = (ff & sm) << FPC_FLAG_SHIFT; /* A simulated-IEEE-exception event is recognized if any current flag corresponds to the source mask */ if (enabled_flags & FPC_FLAG_SFI) { dxc = DXC_IEEE_INV_OP_IISE; } else if (enabled_flags & FPC_FLAG_SFZ) { dxc = DXC_IEEE_DIV_ZERO_IISE; } else if (enabled_flags & FPC_FLAG_SFO) { dxc = (cur_fpc & FPC_FLAG_SFX) ? DXC_IEEE_OF_INEX_IISE : DXC_IEEE_OF_EXACT_IISE; } else if (enabled_flags & FPC_FLAG_SFU) { dxc = (cur_fpc & FPC_FLAG_SFX) ? DXC_IEEE_UF_INEX_IISE : DXC_IEEE_UF_EXACT_IISE; } else if (enabled_flags & FPC_FLAG_SFX) { dxc = DXC_IEEE_INEXACT_IISE; } else { dxc = 0; } /* Return data exception code or zero */ return dxc; } /* end function fpc_signal_check */ #define _IXS_ARCH_INDEPENDENT_ #endif /*!defined(_IXS_ARCH_INDEPENDENT_)*/ /*-------------------------------------------------------------------*/ /* B2BD LFAS - Load FPC and Signal [S] */ /*-------------------------------------------------------------------*/ DEF_INST(load_fpc_and_signal) { int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ U32 src_fpc, new_fpc; /* New value for FPC */ BYTE dxc; /* Data exception code */ S(inst, regs, b2, effective_addr2); DFPINST_CHECK(regs); /* Load new FPC register contents from operand location */ src_fpc = ARCH_DEP(vfetch4) (effective_addr2, b2, regs); /* Program check if reserved bits are non-zero */ FPC_CHECK(src_fpc, regs); /* OR the flags from the current FPC register */ new_fpc = src_fpc | (regs->fpc & FPC_FLAG); /* Determine whether an event is to be signaled */ dxc = fpc_signal_check(regs->fpc, src_fpc); /* Update the FPC register */ regs->fpc = new_fpc; /* Signal a simulated-IEEE-exception event if needed */ if (dxc != 0) { regs->dxc = dxc; ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION); } } /* end DEF_INST(load_fpc_and_signal) */ /*-------------------------------------------------------------------*/ /* B385 SFASR - Set FPC and Signal [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(set_fpc_and_signal) { int r1, unused; /* Values of R fields */ U32 src_fpc, new_fpc; /* New value for FPC */ BYTE dxc; /* Data exception code */ RRE(inst, regs, r1, unused); DFPINST_CHECK(regs); /* Load new FPC register contents from R1 register bits 32-63 */ src_fpc = regs->GR_L(r1); /* Program check if reserved bits are non-zero */ FPC_CHECK(src_fpc, regs); /* OR the flags from the current FPC register */ new_fpc = src_fpc | (regs->fpc & FPC_FLAG); /* Determine whether an event is to be signaled */ dxc = fpc_signal_check(regs->fpc, src_fpc); /* Update the FPC register */ regs->fpc = new_fpc; /* Signal a simulated-IEEE-exception event if needed */ if (dxc != 0) { regs->dxc = dxc; ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION); } } /* end DEF_INST(set_fpc_and_signal) */ #endif /*defined(FEATURE_IEEE_EXCEPTION_SIMULATION)*/ #if defined(FEATURE_DECIMAL_FLOATING_POINT) /*===================================================================*/ /* DECIMAL FLOATING POINT INSTRUCTIONS */ /*===================================================================*/ /* Note: the DFP instructions use the DFPINST_CHECK macro to check the setting of the AFP-register-control bit in CR0. If this bit is zero then the macro generates a DFP-instruction data exception. */ #if !defined(_DFP_ARCH_INDEPENDENT_) /*-------------------------------------------------------------------*/ /* Extract the leftmost digit from a decimal32/64/128 structure */ /*-------------------------------------------------------------------*/ static const int dfp_lmdtable[32] = {0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 9, 8, 9, 0, 0}; static inline int dfp32_extract_lmd(decimal32 *xp) { unsigned int cf = (((FW*)xp)->F & 0x7C000000) >> 26; return dfp_lmdtable[cf]; } /* end function dfp32_extract_lmd */ static inline int dfp64_extract_lmd(decimal64 *xp) { unsigned int cf = (((DW*)xp)->F.H.F & 0x7C000000) >> 26; return dfp_lmdtable[cf]; } /* end function dfp64_extract_lmd */ static inline int dfp128_extract_lmd(decimal128 *xp) { unsigned int cf = (((QW*)xp)->F.HH.F & 0x7C000000) >> 26; return dfp_lmdtable[cf]; } /* end function dfp128_extract_lmd */ /*-------------------------------------------------------------------*/ /* Clear the CF and BXCF fields of a decimal32/64/128 structure */ /*-------------------------------------------------------------------*/ static inline void dfp32_clear_cf_and_bxcf(decimal32 *xp) { ((FW*)xp)->F &= 0x800FFFFF; /* Clear CF and BXCF fields */ } /* end function dfp32_clear_cf_and_bxcf */ static inline void dfp64_clear_cf_and_bxcf(decimal64 *xp) { ((DW*)xp)->F.H.F &= 0x8003FFFF; /* Clear CF and BXCF fields */ } /* end function dfp64_clear_cf_and_bxcf */ static inline void dfp128_clear_cf_and_bxcf(decimal128 *xp) { ((QW*)xp)->F.HH.F &= 0x80003FFF; /* Clear CF and BXCF fields */ } /* end function dfp128_clear_cf_and_bxcf */ /*-------------------------------------------------------------------*/ /* Set the CF and BXCF fields of a decimal32/64/128 structure */ /* Input: */ /* xp Pointer to a decimal32/64/128 structure */ /* cfs A 32-bit value, of which bits 0-25 are ignored, */ /* bits 26-30 contain the new CF field value (5-bits), */ /* bit 31 is the new BXCF signaling indicator (1-bit). */ /* Output: */ /* The CF field and the high-order bit of the BXCF field in */ /* the decimal32/64/128 structure are set to the indicated */ /* values and the remaining bits of the BXCF field are cleared. */ /*-------------------------------------------------------------------*/ #define DFP_CFS_INF ((30<<1)|0) /* CF and BXCF-S for Inf */ #define DFP_CFS_QNAN ((31<<1)|0) /* CF and BXCF-S for QNaN */ #define DFP_CFS_SNAN ((31<<1)|1) /* CF and BXCF-S for SNaN */ static inline void dfp32_set_cf_and_bxcf(decimal32 *xp, U32 cfs) { ((FW*)xp)->F &= 0x800FFFFF; /* Clear CF and BXCF fields */ ((FW*)xp)->F |= (cfs & 0x3F) << 25; /* Set CF and BXCF S-bit */ } /* end function dfp32_set_cf_and_bxcf */ static inline void dfp64_set_cf_and_bxcf(decimal64 *xp, U32 cfs) { ((DW*)xp)->F.H.F &= 0x8003FFFF; /* Clear CF and BXCF fields */ ((DW*)xp)->F.H.F |= (cfs & 0x3F) << 25; /* Set CF and BXCF S-bit */ } /* end function dfp64_set_cf_and_bxcf */ static inline void dfp128_set_cf_and_bxcf(decimal128 *xp, U32 cfs) { ((QW*)xp)->F.HH.F &= 0x80003FFF; /* Clear CF and BXCF fields */ ((QW*)xp)->F.HH.F |= (cfs & 0x3F) << 25; /* Set CF and BXCF S-bit */ } /* end function dfp128_set_cf_and_bxcf */ /*-------------------------------------------------------------------*/ /* Compare exponent and return condition code */ /* */ /* This subroutine is called by the CEETR, CEDTR, and CEXTR */ /* instructions. It compares the exponents of two decimal */ /* numbers and returns a condition code. */ /* */ /* Input: */ /* d1,d2 Pointers to decimal number structures */ /* Output: */ /* The return value is the condition code */ /*-------------------------------------------------------------------*/ static inline int dfp_compare_exponent(decNumber *d1, decNumber *d2) { int cc; /* Condition code */ if (decNumberIsNaN(d1) && decNumberIsNaN(d2)) cc = 0; else if (decNumberIsNaN(d1) || decNumberIsNaN(d2)) cc = 3; else if (decNumberIsInfinite(d1) && decNumberIsInfinite(d2)) cc = 0; else if (decNumberIsInfinite(d1) || decNumberIsInfinite(d2)) cc = 3; else cc = (d1->exponent == d2->exponent) ? 0 : (d1->exponent < d2->exponent) ? 1 : 2 ; return cc; } /* end function dfp_compare_exponent */ /*-------------------------------------------------------------------*/ /* Convert 64-bit signed binary integer to decimal number */ /* */ /* This subroutine is called by the CDGTR and CXGTR instructions. */ /* It converts a 64-bit signed binary integer value into a */ /* decimal number structure. The inexact condition will be set */ /* in the decimal context structure if the number is rounded to */ /* fit the maximum number of digits specified in the context. */ /* */ /* Input: */ /* dn Pointer to decimal number structure */ /* n 64-bit signed binary integer value */ /* pset Pointer to decimal number context structure */ /* Output: */ /* The decimal number structure is updated. */ /*-------------------------------------------------------------------*/ static void dfp_number_from_fix64(decNumber *dn, S64 n, decContext *pset) { int sign = 0; /* Sign of binary integer */ int i; /* Counter */ char zoned[32]; /* Zoned decimal work area */ static char maxnegzd[]="-9223372036854775808"; static U64 maxneg64 = 0x8000000000000000ULL; /* Handle maximum negative number as special case */ if (n == (S64)maxneg64) { decNumberFromString(dn, maxnegzd, pset); return; } /* Convert binary value to zoned decimal */ if (n < 0) { n = -n; sign = 1; } i = sizeof(zoned) - 1; zoned[i] = '\0'; do { zoned[--i] = (n % 10) + '0'; n /= 10; } while(i > 1 && n > 0); if (sign) zoned[--i] = '-'; /* Convert zoned decimal value to decimal number structure */ decNumberFromString(dn, zoned+i, pset); } /* end function dfp_number_from_fix64 */ /*-------------------------------------------------------------------*/ /* Convert decimal number to 64-bit signed binary integer */ /* */ /* This subroutine is called by the CGDTR and CGXTR instructions. */ /* It converts a decimal number structure to a 64-bit signed */ /* binary integer value. The inexact condition will be set in */ /* the decimal context structure if the number is rounded to */ /* an integer. The invalid operation condition will be set if */ /* the decimal value is outside the range of a 64-bit integer. */ /* */ /* Input: */ /* b Pointer to decimal number structure */ /* pset Pointer to decimal number context structure */ /* Output: */ /* The return value is the 64-bit signed binary integer result */ /*-------------------------------------------------------------------*/ static S64 dfp_number_to_fix64(decNumber *b, decContext *pset) { S64 n; /* 64-bit signed result */ int32_t scale; /* Scaling factor */ unsigned i; /* Array subscript */ BYTE packed[17]; /* 33-digit packed work area */ decNumber p, c; /* Working decimal numbers */ static U64 mp64 = 0x7FFFFFFFFFFFFFFFULL; /* Max pos fixed 64 */ static U64 mn64 = 0x8000000000000000ULL; /* Max neg fixed 64 */ static char mpzd[]="9223372036854775807"; /* Max pos zoned dec */ static char mnzd[]="-9223372036854775808"; /* Max neg zoned dec */ static BYTE mpflag = 0; /* 1=mp,mn are initialized */ static decNumber mp, mn; /* Decimal maximum pos,neg */ decContext setmax; /* Working context for mp,mn */ /* Prime the decimal number structures representing the maximum positive and negative numbers representable in 64 bits. Use a 128-bit DFP working context because these numbers are too big to be represented in the 32-bit and 64-bit DFP formats */ if (mpflag == 0) { decContextDefault(&setmax, DEC_INIT_DECIMAL128); decNumberFromString(&mp, mpzd, &setmax); decNumberFromString(&mn, mnzd, &setmax); mpflag = 1; } /* If operand is a NaN then set invalid operation and return maximum negative result */ if (decNumberIsNaN(b)) { pset->status |= DEC_IEEE_854_Invalid_operation; return (S64)mn64; } /* Remove fractional part of decimal number */ decNumberToIntegralValue(&p, b, pset); /* Special case if operand is less than maximum negative number (including where operand is negative infinity) */ decNumberCompare(&c, b, &mn, pset); if (decNumberIsNegative(&c)) { /* If rounded value is less than maximum negative number then set invalid operation otherwise set inexact */ decNumberCompare(&c, &p, &mn, pset); if (decNumberIsNegative(&c)) pset->status |= DEC_IEEE_854_Invalid_operation; else pset->status |= DEC_IEEE_854_Inexact; /* Return maximum negative result */ return (S64)mn64; } /* Special case if operand is greater than maximum positive number (including where operand is positive infinity) */ decNumberCompare(&c, b, &mp, pset); if (decNumberIsNegative(&c) == 0 && decNumberIsZero(&c) == 0) { /* If rounded value is greater than maximum positive number then set invalid operation otherwise set inexact */ decNumberCompare(&c, &p, &mp, pset); if (decNumberIsNegative(&c) == 0 && decNumberIsZero(&c) == 0) pset->status |= DEC_IEEE_854_Invalid_operation; else pset->status |= DEC_IEEE_854_Inexact; /* Return maximum positive result */ return (S64)mp64; } /* Raise inexact condition if result was rounded */ decNumberCompare(&c, &p, b, pset); if (decNumberIsZero(&c) == 0) { pset->status |= DEC_IEEE_854_Inexact; if (decNumberIsNegative(&c) == decNumberIsNegative(b)) pset->status |= DEC_Rounded; } /* Convert decimal number structure to packed decimal */ decPackedFromNumber(packed, sizeof(packed), &scale, &p); /* Convert packed decimal to binary value */ for (i = 0, n = 0; i < sizeof(packed)-1; i++) { n = n * 10 + ((packed[i] & 0xF0) >> 4); n = n * 10 + (packed[i] & 0x0F); } n = n * 10 + ((packed[i] & 0xF0) >> 4); while (scale++) n *= 10; if ((packed[i] & 0x0F) == 0x0D) n = -n; /* Return 64-bit signed result */ return n; } /* end function dfp_number_to_fix64 */ #define MAXDECSTRLEN DECIMAL128_String /* Maximum string length */ /*-------------------------------------------------------------------*/ /* Shift decimal coefficient left or right */ /* */ /* This subroutine is called by the SLDT, SLXT, SRDT and SRXT */ /* instructions. It shifts the coefficient digits of a decimal */ /* number left or right. For a left shift, zeroes are appended */ /* to the coefficient. For a right shift, digits are dropped */ /* from the end of the coefficient. No rounding is performed. */ /* The sign and exponent of the number remain unchanged. */ /* */ /* Input: */ /* pset Pointer to decimal number context structure */ /* dn Pointer to decimal number structure to be shifted */ /* count Number of digits to shift (+ve=left, -ve=right) */ /* Output: */ /* The decimal number structure is updated. */ /*-------------------------------------------------------------------*/ static inline void dfp_shift_coeff(decContext *pset, decNumber *dn, int count) { size_t len; /* String length */ size_t maxlen; /* Maximum coefficient length*/ int32_t exp; /* Original exponent */ uint8_t bits; /* Original flag bits */ char zd[MAXDECSTRLEN+64]; /* Zoned decimal work area */ /* Save original exponent and sign/Inf/NaN bits */ exp = dn->exponent; bits = dn->bits; /* Clear exponent and sign/Inf/NaN bits */ dn->exponent = 0; dn->bits &= ~(DECNEG | DECSPECIAL); /* Convert coefficient digits to zoned decimal */ decNumberToString(dn, zd); len = strlen(zd); /* Shift zoned digits left or right */ if (count > 0) memset(zd + len, '0', count); len += count; maxlen = (bits & DECSPECIAL) ? pset->digits - 1 : pset->digits; if (len > maxlen) { memmove(zd, zd + len - maxlen, maxlen); len = maxlen; } else if (len < 1) { zd[0] = '0'; len = 1; } zd[len] = '\0'; /* Convert shifted coefficient to decimal number structure */ decNumberFromString(dn, zd, pset); /* Restore original exponent and sign/Inf/NaN bits */ dn->exponent = exp; dn->bits |= bits & (DECNEG | DECSPECIAL); } /* end function dfp_shift_coeff */ /* Bit numbers for Test Data Class instructions */ #define DFP_TDC_ZERO 52 #define DFP_TDC_SUBNORMAL 54 #define DFP_TDC_NORMAL 56 #define DFP_TDC_INFINITY 58 #define DFP_TDC_QUIET_NAN 60 #define DFP_TDC_SIGNALING_NAN 62 /*-------------------------------------------------------------------*/ /* Test data class and return condition code */ /* */ /* This subroutine is called by the TDCET, TDCDT, and TDCXT */ /* instructions. It tests the data class and sign of a decimal */ /* number. Each combination of data class and sign corresponds */ /* to one of 12 possible bits in a bitmask. The value (0 or 1) */ /* of the corresponding bit is returned. */ /* */ /* Input: */ /* pset Pointer to decimal number context structure */ /* dn Pointer to decimal number structure to be tested */ /* bits Bitmask in rightmost 12 bits */ /* Output: */ /* The return value is 0 or 1. */ /*-------------------------------------------------------------------*/ static inline int dfp_test_data_class(decContext *pset, decNumber *dn, U32 bits) { int bitn; /* Bit number */ decNumber dm; /* Normalized value of dn */ if (decNumberIsZero(dn)) bitn = DFP_TDC_ZERO; else if (decNumberIsInfinite(dn)) bitn = DFP_TDC_INFINITY; else if (decNumberIsQNaN(dn)) bitn = DFP_TDC_QUIET_NAN; else if (decNumberIsSNaN(dn)) bitn = DFP_TDC_SIGNALING_NAN; else { decNumberNormalize(&dm, dn, pset); bitn = (dm.exponent < pset->emin) ? DFP_TDC_SUBNORMAL : DFP_TDC_NORMAL ; } if (decNumberIsNegative(dn)) bitn++; return (bits >> (63 - bitn)) & 0x01; } /* end function dfp_test_data_class */ /* Bit numbers for Test Data Group instructions */ #define DFP_TDG_SAFE_ZERO 52 #define DFP_TDG_EXTREME_ZERO 54 #define DFP_TDG_EXTREME_NONZERO 56 #define DFP_TDG_SAFE_NZ_LMD_Z 58 #define DFP_TDG_SAFE_NZ_LMD_NZ 60 #define DFP_TDG_SPECIAL 62 /*-------------------------------------------------------------------*/ /* Test data group and return condition code */ /* */ /* This subroutine is called by the TDGET, TDGDT, and TDGXT */ /* instructions. It tests the exponent and leftmost coefficient */ /* digit of a decimal number to determine which of 12 possible */ /* groups the number corresponds to. Each group corresponds to */ /* one of 12 possible bits in a bitmask. The value (0 or 1) of */ /* the corresponding bit is returned. */ /* */ /* Input: */ /* pset Pointer to decimal number context structure */ /* dn Pointer to decimal number structure to be tested */ /* lmd Leftmost digit of decimal FP number */ /* bits Bitmask in rightmost 12 bits */ /* Output: */ /* The return value is 0 or 1. */ /*-------------------------------------------------------------------*/ static inline int dfp_test_data_group(decContext *pset, decNumber *dn, int lmd, U32 bits) { int bitn; /* Bit number */ int extreme; /* 1=exponent is min or max */ int exp; /* Adjusted exponent */ exp = dn->exponent + pset->digits - 1; extreme = (exp == pset->emin) || (exp == pset->emax); if (decNumberIsZero(dn)) bitn = extreme ? DFP_TDG_EXTREME_ZERO : DFP_TDG_SAFE_ZERO ; else if (decNumberIsInfinite(dn) || decNumberIsNaN(dn)) bitn = DFP_TDG_SPECIAL; else if (extreme) bitn = DFP_TDG_EXTREME_NONZERO; else { bitn = (lmd == 0) ? DFP_TDG_SAFE_NZ_LMD_Z : DFP_TDG_SAFE_NZ_LMD_NZ ; } if (decNumberIsNegative(dn)) bitn++; return (bits >> (63 - bitn)) & 0x01; } /* end function dfp_test_data_group */ #define _DFP_ARCH_INDEPENDENT_ #endif /*!defined(_DFP_ARCH_INDEPENDENT_)*/ /*-------------------------------------------------------------------*/ /* Set rounding mode in decimal context structure */ /* */ /* Input: */ /* pset Pointer to decimal number context structure */ /* mask 4-bit mask value */ /* regs CPU register context */ /* Output: */ /* If mask bit X'08' is one then the rounding mode in the */ /* context structure is set according to the value (0 to 7) */ /* indicated by the low-order three bits of the mask. */ /* If mask bit X'08' is zero then the rounding mode in the */ /* context structure is set according to the value (0 to 7) */ /* of the DRM field in the FPC register. */ /*-------------------------------------------------------------------*/ static inline void ARCH_DEP(dfp_rounding_mode) (decContext *pset, int mask, REGS *regs) { BYTE drm; /* Decimal rounding mode */ /* Load DRM from mask or from FPC register */ if (mask & 0x08) drm = mask & 0x07; else drm = (regs->fpc & FPC_DRM) >> FPC_DRM_SHIFT; /* Set rounding mode according to DRM value */ switch (drm) { case DRM_RNE: pset->round = DEC_ROUND_HALF_EVEN; break; case DRM_RTZ: pset->round = DEC_ROUND_DOWN; break; case DRM_RTPI: pset->round = DEC_ROUND_CEILING; break; case DRM_RTMI: pset->round = DEC_ROUND_FLOOR; break; case DRM_RNAZ: pset->round = DEC_ROUND_HALF_UP; break; case DRM_RNTZ: pset->round = DEC_ROUND_HALF_DOWN; break; case DRM_RAFZ: pset->round = DEC_ROUND_UP; break; case DRM_RFSP: /* Rounding mode DRM_RFSP is not supported by the decNumber library, so we arbitrarily convert it to another mode instead... */ pset->round = DEC_ROUND_DOWN; break; } /* end switch(drm) */ } /* end function dfp_rounding_mode */ /*-------------------------------------------------------------------*/ /* Copy a DFP short register into a decimal32 structure */ /* */ /* Input: */ /* rn FP register number */ /* xp Pointer to decimal32 structure */ /* regs CPU register context */ /*-------------------------------------------------------------------*/ static inline void ARCH_DEP(dfp_reg_to_decimal32) (int rn, decimal32 *xp, REGS *regs) { int i; /* FP register subscript */ FW *fwp; /* Fullword pointer */ i = FPR2I(rn); /* Register index */ fwp = (FW*)xp; /* Convert to FW pointer */ fwp->F = regs->fpr[i]; /* Copy FPR bits 0-31 */ } /* end function dfp_reg_to_decimal32 */ /*-------------------------------------------------------------------*/ /* Load a DFP short register from a decimal32 structure */ /* */ /* Input: */ /* rn FP register number (left register of pair) */ /* xp Pointer to decimal32 structure */ /* regs CPU register context */ /*-------------------------------------------------------------------*/ static inline void ARCH_DEP(dfp_reg_from_decimal32) (int rn, decimal32 *xp, REGS *regs) { int i; /* FP register subscript */ FW *fwp; /* Fullword pointer */ i = FPR2I(rn); /* Register index */ fwp = (FW*)xp; /* Convert to FW pointer */ regs->fpr[i] = fwp->F; /* Load FPR bits 0-31 */ } /* end function dfp_reg_from_decimal32 */ /*-------------------------------------------------------------------*/ /* Copy a DFP long register into a decimal64 structure */ /* */ /* Input: */ /* rn FP register number */ /* xp Pointer to decimal64 structure */ /* regs CPU register context */ /*-------------------------------------------------------------------*/ static inline void ARCH_DEP(dfp_reg_to_decimal64) (int rn, decimal64 *xp, REGS *regs) { int i; /* FP register subscript */ DW *dwp; /* Doubleword pointer */ i = FPR2I(rn); /* Register index */ dwp = (DW*)xp; /* Convert to DW pointer */ dwp->F.H.F = regs->fpr[i]; /* Copy FPR bits 0-31 */ dwp->F.L.F = regs->fpr[i+1]; /* Copy FPR bits 32-63 */ } /* end function dfp_reg_to_decimal64 */ /*-------------------------------------------------------------------*/ /* Load a DFP long register from a decimal64 structure */ /* */ /* Input: */ /* rn FP register number (left register of pair) */ /* xp Pointer to decimal64 structure */ /* regs CPU register context */ /*-------------------------------------------------------------------*/ static inline void ARCH_DEP(dfp_reg_from_decimal64) (int rn, decimal64 *xp, REGS *regs) { int i; /* FP register subscript */ DW *dwp; /* Doubleword pointer */ i = FPR2I(rn); /* Register index */ dwp = (DW*)xp; /* Convert to DW pointer */ regs->fpr[i] = dwp->F.H.F; /* Load FPR bits 0-31 */ regs->fpr[i+1] = dwp->F.L.F; /* Load FPR bits 32-63 */ } /* end function dfp_reg_from_decimal64 */ /*-------------------------------------------------------------------*/ /* Copy a DFP extended register into a decimal128 structure */ /* */ /* Input: */ /* rn FP register number (left register of pair) */ /* xp Pointer to decimal128 structure */ /* regs CPU register context */ /*-------------------------------------------------------------------*/ static inline void ARCH_DEP(dfp_reg_to_decimal128) (int rn, decimal128 *xp, REGS *regs) { int i, j; /* FP register subscripts */ QW *qwp; /* Quadword pointer */ i = FPR2I(rn); /* Left register index */ j = i + FPREX; /* Right register index */ qwp = (QW*)xp; /* Convert to QW pointer */ qwp->F.HH.F = regs->fpr[i]; /* Copy FPR bits 0-31 */ qwp->F.HL.F = regs->fpr[i+1]; /* Copy FPR bits 32-63 */ qwp->F.LH.F = regs->fpr[j]; /* Copy FPR bits 64-95 */ qwp->F.LL.F = regs->fpr[j+1]; /* Copy FPR bits 96-127 */ } /* end function dfp_reg_to_decimal128 */ /*-------------------------------------------------------------------*/ /* Load a DFP extended register from a decimal128 structure */ /* */ /* Input: */ /* rn FP register number (left register of pair) */ /* xp Pointer to decimal128 structure */ /* regs CPU register context */ /*-------------------------------------------------------------------*/ static inline void ARCH_DEP(dfp_reg_from_decimal128) (int rn, decimal128 *xp, REGS *regs) { int i, j; /* FP register subscripts */ QW *qwp; /* Quadword pointer */ i = FPR2I(rn); /* Left register index */ j = i + FPREX; /* Right register index */ qwp = (QW*)xp; /* Convert to QW pointer */ regs->fpr[i] = qwp->F.HH.F; /* Load FPR bits 0-31 */ regs->fpr[i+1] = qwp->F.HL.F; /* Load FPR bits 32-63 */ regs->fpr[j] = qwp->F.LH.F; /* Load FPR bits 64-95 */ regs->fpr[j+1] = qwp->F.LL.F; /* Load FPR bits 96-127 */ } /* end function dfp_reg_from_decimal128 */ /*-------------------------------------------------------------------*/ /* Check for DFP exception conditions */ /* */ /* This subroutine is called by the DFP instruction processing */ /* routines after the calculation has been performed but before */ /* the result is loaded into the result register (or before any */ /* storage location is updated, as the case may be). */ /* */ /* The purpose of this subroutine is to check whether any DFP */ /* exception conditions are indicated by the decimal context */ /* structure, and to initiate the appropriate action if so. */ /* */ /* Input: */ /* set Decimal number context */ /* regs CPU register context */ /* */ /* Output: */ /* Return value is DXC (data exception code) or zero. */ /* */ /* When no exception conditions are indicated, the return value */ /* is zero indicating that the instruction may proceed normally. */ /* */ /* When an exception condition exists and the corresponding mask */ /* bit in the FPC register is zero, then the corresponding flag */ /* bit is set in the FPC register. The return value is zero to */ /* indicate that the instruction may proceed normally. */ /* */ /* When an exception condition exists and the corresponding mask */ /* bit in the FPC register is one, then the DXC is set according */ /* to the type of exception, and one of two actions is taken: */ /* - if the exception is of a type which causes the instruction */ /* to be suppressed, then this subroutine raises a program */ /* exception and does not return to the calling instruction */ /* - if the exception is of a type which causes the instruction */ /* to be completed, then this subroutine returns with the */ /* DXC code as its return value. The calling instruction will */ /* then raise a program exception after storing its results. */ /*-------------------------------------------------------------------*/ static BYTE ARCH_DEP(dfp_status_check) (decContext *pset, REGS *regs) { BYTE dxc = 0; /* Data exception code */ int suppress = 0; /* 1=suppress, 0=complete */ if (pset->status & DEC_IEEE_854_Invalid_operation) { /* An IEEE-invalid-operation condition was recognized */ if ((regs->fpc & FPC_MASK_IMI) == 0) { regs->fpc |= FPC_FLAG_SFI; } else { dxc = DXC_IEEE_INVALID_OP; suppress = 1; } } else if (pset->status & DEC_IEEE_854_Division_by_zero) { /* An IEEE-division-by-zero condition was recognized */ if ((regs->fpc & FPC_MASK_IMZ) == 0) { /* Division-by-zero mask is zero */ regs->fpc |= FPC_FLAG_SFZ; } else { /* Division-by-zero mask is one */ dxc = DXC_IEEE_DIV_ZERO; suppress = 1; } } else if (pset->status & DEC_IEEE_854_Overflow) { /* An IEEE-overflow condition was recognized */ if ((regs->fpc & FPC_MASK_IMO) == 0) { /* Overflow mask is zero */ regs->fpc |= FPC_FLAG_SFO; } else { /* Overflow mask is one */ dxc = (pset->status & DEC_IEEE_854_Inexact) ? ((pset->status & DEC_Rounded) ? DXC_IEEE_OF_INEX_INCR : DXC_IEEE_OF_INEX_TRUNC ) : DXC_IEEE_OF_EXACT ; } } else if (pset->status & DEC_IEEE_854_Underflow) { /* An IEEE-underflow condition was recognized */ if ((regs->fpc & FPC_MASK_IMU) == 0) { /* Underflow mask is zero */ if (pset->status & DEC_IEEE_854_Inexact) { if ((regs->fpc & FPC_MASK_IMX) == 0) { /* Inexact result with inexact mask zero */ regs->fpc |= (FPC_FLAG_SFU | FPC_FLAG_SFX); } else { /* Inexact result with inexact mask one */ regs->fpc |= FPC_FLAG_SFU; dxc = (pset->status & DEC_Rounded) ? DXC_IEEE_INEXACT_INCR : DXC_IEEE_INEXACT_TRUNC ; } } } else { /* Underflow mask is one */ if (pset->status & DEC_IEEE_854_Inexact) { /* Underflow with inexact result */ dxc = (pset->status & DEC_Rounded) ? DXC_IEEE_UF_INEX_INCR : DXC_IEEE_UF_INEX_TRUNC ; } else { /* Underflow with exact result */ dxc = DXC_IEEE_UF_EXACT; } } } else if (pset->status & DEC_IEEE_854_Inexact) { /* An IEEE-inexact condition was recognized */ if ((regs->fpc & FPC_MASK_IMX) == 0) { /* Inexact mask is zero */ regs->fpc |= FPC_FLAG_SFX; } else { /* Inexact mask is one */ dxc = (pset->status & DEC_Rounded) ? DXC_IEEE_INEXACT_INCR : DXC_IEEE_INEXACT_TRUNC ; } } /* If suppression is indicated, raise a data exception */ if (suppress) { regs->dxc = dxc; ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION); } /* Otherwise return to complete the instruction */ return dxc; } /* end function dfp_status_check */ /*-------------------------------------------------------------------*/ /* B3DA AXTR - Add DFP Extended Register [RRR] */ /*-------------------------------------------------------------------*/ DEF_INST(add_dfp_ext_reg) { int r1, r2, r3; /* Values of R fields */ decimal128 x1, x2, x3; /* Extended DFP values */ decNumber d1, d2, d3; /* Working decimal numbers */ decContext set; /* Working context */ BYTE dxc; /* Data exception code */ RRR(inst, regs, r1, r2, r3); DFPINST_CHECK(regs); DFPREGPAIR3_CHECK(r1, r2, r3, regs); /* Initialise the context for extended DFP */ decContextDefault(&set, DEC_INIT_DECIMAL128); ARCH_DEP(dfp_rounding_mode)(&set, 0, regs); /* Add FP register r3 to FP register r2 */ ARCH_DEP(dfp_reg_to_decimal128)(r2, &x2, regs); ARCH_DEP(dfp_reg_to_decimal128)(r3, &x3, regs); decimal128ToNumber(&x2, &d2); decimal128ToNumber(&x3, &d3); decNumberAdd(&d1, &d2, &d3, &set); decimal128FromNumber(&x1, &d1, &set); /* Check for exception condition */ dxc = ARCH_DEP(dfp_status_check)(&set, regs); /* Load result into FP register r1 */ ARCH_DEP(dfp_reg_from_decimal128)(r1, &x1, regs); /* Set condition code */ regs->psw.cc = decNumberIsNaN(&d1) ? 3 : decNumberIsZero(&d1) ? 0 : decNumberIsNegative(&d1) ? 1 : 2; /* Raise data exception if error occurred */ if (dxc != 0) { regs->dxc = dxc; ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION); } } /* end DEF_INST(add_dfp_ext_reg) */ /*-------------------------------------------------------------------*/ /* B3D2 ADTR - Add DFP Long Register [RRR] */ /*-------------------------------------------------------------------*/ DEF_INST(add_dfp_long_reg) { int r1, r2, r3; /* Values of R fields */ decimal64 x1, x2, x3; /* Long DFP values */ decNumber d1, d2, d3; /* Working decimal numbers */ decContext set; /* Working context */ BYTE dxc; /* Data exception code */ RRR(inst, regs, r1, r2, r3); DFPINST_CHECK(regs); /* Initialise the context for long DFP */ decContextDefault(&set, DEC_INIT_DECIMAL64); ARCH_DEP(dfp_rounding_mode)(&set, 0, regs); /* Add FP register r3 to FP register r2 */ ARCH_DEP(dfp_reg_to_decimal64)(r2, &x2, regs); ARCH_DEP(dfp_reg_to_decimal64)(r3, &x3, regs); decimal64ToNumber(&x2, &d2); decimal64ToNumber(&x3, &d3); decNumberAdd(&d1, &d2, &d3, &set); decimal64FromNumber(&x1, &d1, &set); /* Check for exception condition */ dxc = ARCH_DEP(dfp_status_check)(&set, regs); /* Load result into FP register r1 */ ARCH_DEP(dfp_reg_from_decimal64)(r1, &x1, regs); /* Set condition code */ regs->psw.cc = decNumberIsNaN(&d1) ? 3 : decNumberIsZero(&d1) ? 0 : decNumberIsNegative(&d1) ? 1 : 2; /* Raise data exception if error occurred */ if (dxc != 0) { regs->dxc = dxc; ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION); } } /* end DEF_INST(add_dfp_long_reg) */ /*-------------------------------------------------------------------*/ /* B3EC CXTR - Compare DFP Extended Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_dfp_ext_reg) { int r1, r2; /* Values of R fields */ decimal128 x1, x2; /* Extended DFP values */ decNumber d1, d2, dr; /* Working decimal numbers */ decContext set; /* Working context */ BYTE dxc; /* Data exception code */ RRE(inst, regs, r1, r2); DFPINST_CHECK(regs); DFPREGPAIR2_CHECK(r1, r2, regs); /* Initialise the context for extended DFP */ decContextDefault(&set, DEC_INIT_DECIMAL128); /* Compare FP register r1 with FP register r2 */ ARCH_DEP(dfp_reg_to_decimal128)(r1, &x1, regs); ARCH_DEP(dfp_reg_to_decimal128)(r2, &x2, regs); decimal128ToNumber(&x1, &d1); decimal128ToNumber(&x2, &d2); decNumberCompare(&dr, &d1, &d2, &set); /* Check for exception condition */ dxc = ARCH_DEP(dfp_status_check)(&set, regs); /* Set condition code */ regs->psw.cc = decNumberIsNaN(&dr) ? 3 : decNumberIsZero(&dr) ? 0 : decNumberIsNegative(&dr) ? 1 : 2; /* Raise data exception if error occurred */ if (dxc != 0) { regs->dxc = dxc; ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION); } } /* end DEF_INST(compare_dfp_ext_reg) */ /*-------------------------------------------------------------------*/ /* B3E4 CDTR - Compare DFP Long Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_dfp_long_reg) { int r1, r2; /* Values of R fields */ decimal64 x1, x2; /* Long DFP values */ decNumber d1, d2, dr; /* Working decimal numbers */ decContext set; /* Working context */ BYTE dxc; /* Data exception code */ RRE(inst, regs, r1, r2); DFPINST_CHECK(regs); /* Initialise the context for long DFP */ decContextDefault(&set, DEC_INIT_DECIMAL64); /* Compare FP register r1 with FP register r2 */ ARCH_DEP(dfp_reg_to_decimal64)(r1, &x1, regs); ARCH_DEP(dfp_reg_to_decimal64)(r2, &x2, regs); decimal64ToNumber(&x1, &d1); decimal64ToNumber(&x2, &d2); decNumberCompare(&dr, &d1, &d2, &set); /* Check for exception condition */ dxc = ARCH_DEP(dfp_status_check)(&set, regs); /* Set condition code */ regs->psw.cc = decNumberIsNaN(&dr) ? 3 : decNumberIsZero(&dr) ? 0 : decNumberIsNegative(&dr) ? 1 : 2; /* Raise data exception if error occurred */ if (dxc != 0) { regs->dxc = dxc; ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION); } } /* end DEF_INST(compare_dfp_long_reg) */ /*-------------------------------------------------------------------*/ /* B3E8 KXTR - Compare and Signal DFP Extended Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_and_signal_dfp_ext_reg) { int r1, r2; /* Values of R fields */ decimal128 x1, x2; /* Extended DFP values */ decNumber d1, d2, dr; /* Working decimal numbers */ decContext set; /* Working context */ BYTE dxc; /* Data exception code */ RRE(inst, regs, r1, r2); DFPINST_CHECK(regs); DFPREGPAIR2_CHECK(r1, r2, regs); /* Initialise the context for extended DFP */ decContextDefault(&set, DEC_INIT_DECIMAL128); /* Compare FP register r1 with FP register r2 */ ARCH_DEP(dfp_reg_to_decimal128)(r1, &x1, regs); ARCH_DEP(dfp_reg_to_decimal128)(r2, &x2, regs); decimal128ToNumber(&x1, &d1); decimal128ToNumber(&x2, &d2); decNumberCompare(&dr, &d1, &d2, &set); /* Force signaling condition if result is a NaN */ if (decNumberIsNaN(&dr)) set.status |= DEC_IEEE_854_Invalid_operation; /* Check for exception condition */ dxc = ARCH_DEP(dfp_status_check)(&set, regs); /* Set condition code */ regs->psw.cc = decNumberIsNaN(&dr) ? 3 : decNumberIsZero(&dr) ? 0 : decNumberIsNegative(&dr) ? 1 : 2; /* Raise data exception if error occurred */ if (dxc != 0) { regs->dxc = dxc; ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION); } } /* end DEF_INST(compare_and_signal_dfp_ext_reg) */ /*-------------------------------------------------------------------*/ /* B3E0 KDTR - Compare and Signal DFP Long Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_and_signal_dfp_long_reg) { int r1, r2; /* Values of R fields */ decimal64 x1, x2; /* Long DFP values */ decNumber d1, d2, dr; /* Working decimal numbers */ decContext set; /* Working context */ BYTE dxc; /* Data exception code */ RRE(inst, regs, r1, r2); DFPINST_CHECK(regs); /* Initialise the context for long DFP */ decContextDefault(&set, DEC_INIT_DECIMAL64); /* Compare FP register r1 with FP register r2 */ ARCH_DEP(dfp_reg_to_decimal64)(r1, &x1, regs); ARCH_DEP(dfp_reg_to_decimal64)(r2, &x2, regs); decimal64ToNumber(&x1, &d1); decimal64ToNumber(&x2, &d2); decNumberCompare(&dr, &d1, &d2, &set); /* Force signaling condition if result is a NaN */ if (decNumberIsNaN(&dr)) set.status |= DEC_IEEE_854_Invalid_operation; /* Check for exception condition */ dxc = ARCH_DEP(dfp_status_check)(&set, regs); /* Set condition code */ regs->psw.cc = decNumberIsNaN(&dr) ? 3 : decNumberIsZero(&dr) ? 0 : decNumberIsNegative(&dr) ? 1 : 2; /* Raise data exception if error occurred */ if (dxc != 0) { regs->dxc = dxc; ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION); } } /* end DEF_INST(compare_and_signal_dfp_long_reg) */ /*-------------------------------------------------------------------*/ /* B3FC CEXTR - Compare Exponent DFP Extended Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_exponent_dfp_ext_reg) { int r1, r2; /* Values of R fields */ decimal128 x1, x2; /* Extended DFP values */ decNumber d1, d2; /* Working decimal numbers */ decContext set; /* Working context */ RRE(inst, regs, r1, r2); DFPINST_CHECK(regs); DFPREGPAIR2_CHECK(r1, r2, regs); /* Initialise the context for extended DFP */ decContextDefault(&set, DEC_INIT_DECIMAL128); /* Convert FP register values to numbers */ ARCH_DEP(dfp_reg_to_decimal128)(r1, &x1, regs); ARCH_DEP(dfp_reg_to_decimal128)(r2, &x2, regs); decimal128ToNumber(&x1, &d1); decimal128ToNumber(&x2, &d2); /* Compare exponents and set condition code */ regs->psw.cc = dfp_compare_exponent(&d1, &d2); } /* end DEF_INST(compare_exponent_dfp_ext_reg) */ /*-------------------------------------------------------------------*/ /* B3F4 CEDTR - Compare Exponent DFP Long Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_exponent_dfp_long_reg) { int r1, r2; /* Values of R fields */ decimal64 x1, x2; /* Long DFP values */ decNumber d1, d2; /* Working decimal numbers */ decContext set; /* Working context */ RRE(inst, regs, r1, r2); DFPINST_CHECK(regs); /* Initialise the context for long DFP */ decContextDefault(&set, DEC_INIT_DECIMAL64); /* Convert FP register values to numbers */ ARCH_DEP(dfp_reg_to_decimal64)(r1, &x1, regs); ARCH_DEP(dfp_reg_to_decimal64)(r2, &x2, regs); decimal64ToNumber(&x1, &d1); decimal64ToNumber(&x2, &d2); /* Compare exponents and set condition code */ regs->psw.cc = dfp_compare_exponent(&d1, &d2); } /* end DEF_INST(compare_exponent_dfp_long_reg) */ /*-------------------------------------------------------------------*/ /* B3F9 CXGTR - Convert from fixed 64 to DFP Extended Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(convert_fix64_to_dfp_ext_reg) { int r1, r2; /* Values of R fields */ S64 n2; /* Value of R2 register */ decimal128 x1; /* Extended DFP value */ decNumber d1; /* Working decimal number */ decContext set; /* Working context */ RRE(inst, regs, r1, r2); DFPINST_CHECK(regs); DFPREGPAIR_CHECK(r1, regs); /* Initialise the context for extended DFP */ decContextDefault(&set, DEC_INIT_DECIMAL128); ARCH_DEP(dfp_rounding_mode)(&set, 0, regs); /* Load 64-bit binary integer value from r2 register */ n2 = (S64)(regs->GR_G(r2)); /* Convert binary integer to extended DFP format */ dfp_number_from_fix64(&d1, n2, &set); decimal128FromNumber(&x1, &d1, &set); /* Load result into FP register r1 */ ARCH_DEP(dfp_reg_from_decimal128)(r1, &x1, regs); } /* end DEF_INST(convert_fix64_to_dfp_ext_reg) */ /*-------------------------------------------------------------------*/ /* B3F1 CDGTR - Convert from fixed 64 to DFP Long Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(convert_fix64_to_dfp_long_reg) { int r1, r2; /* Values of R fields */ S64 n2; /* Value of R2 register */ decimal64 x1; /* Long DFP value */ decNumber d1; /* Working decimal number */ decContext set; /* Working context */ BYTE dxc; /* Data exception code */ RRE(inst, regs, r1, r2); DFPINST_CHECK(regs); /* Initialise the context for long DFP */ decContextDefault(&set, DEC_INIT_DECIMAL64); ARCH_DEP(dfp_rounding_mode)(&set, 0, regs); /* Load 64-bit binary integer value from r2 register */ n2 = (S64)(regs->GR_G(r2)); /* Convert binary integer to long DFP format */ dfp_number_from_fix64(&d1, n2, &set); decimal64FromNumber(&x1, &d1, &set); /* Check for exception condition */ dxc = ARCH_DEP(dfp_status_check)(&set, regs); /* Load result into FP register r1 */ ARCH_DEP(dfp_reg_from_decimal64)(r1, &x1, regs); /* Raise data exception if error occurred */ if (dxc != 0) { regs->dxc = dxc; ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION); } } /* end DEF_INST(convert_fix64_to_dfp_long_reg) */ /*-------------------------------------------------------------------*/ /* B3FB CXSTR - Convert from signed BCD (128-bit to DFP ext) [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(convert_sbcd128_to_dfp_ext_reg) { int r1, r2; /* Values of R fields */ decimal128 x1; /* Extended DFP values */ decNumber dwork, *dp; /* Working decimal numbers */ decContext set; /* Working context */ BYTE pwork[16]; /* 31-digit packed work area */ int32_t scale = 0; /* Scaling factor */ RRE(inst, regs, r1, r2); DFPINST_CHECK(regs); DFPREGPAIR_CHECK(r1, regs); ODD_CHECK(r2, regs); /* Initialise the context for extended DFP */ decContextDefault(&set, DEC_INIT_DECIMAL128); /* Store general register pair in work area */ STORE_DW(pwork, regs->GR_G(r2)); STORE_DW(pwork+8, regs->GR_G(r2+1)); /* Convert signed BCD to internal number format */ dp = decPackedToNumber(pwork, sizeof(pwork), &scale, &dwork); /* Data exception if digits or sign was invalid */ if (dp == NULL) { regs->dxc = DXC_DECIMAL; ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION); } /* Convert internal number to DFP extended format */ decimal128FromNumber(&x1, &dwork, &set); /* Load result into FP register r1 */ ARCH_DEP(dfp_reg_from_decimal128)(r1, &x1, regs); } /* end DEF_INST(convert_sbcd128_to_dfp_ext_reg) */ /*-------------------------------------------------------------------*/ /* B3F3 CDSTR - Convert from signed BCD (64-bit to DFP long) [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(convert_sbcd64_to_dfp_long_reg) { int r1, r2; /* Values of R fields */ decimal64 x1; /* Long DFP values */ decNumber dwork, *dp; /* Working decimal numbers */ decContext set; /* Working context */ BYTE pwork[8]; /* 15-digit packed work area */ int32_t scale = 0; /* Scaling factor */ RRE(inst, regs, r1, r2); DFPINST_CHECK(regs); /* Initialise the context for long DFP */ decContextDefault(&set, DEC_INIT_DECIMAL64); /* Store general register in work area */ STORE_DW(pwork, regs->GR_G(r2)); /* Convert signed BCD to internal number format */ dp = decPackedToNumber(pwork, sizeof(pwork), &scale, &dwork); /* Data exception if digits or sign was invalid */ if (dp == NULL) { regs->dxc = DXC_DECIMAL; ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION); } /* Convert internal number to DFP long format */ decimal64FromNumber(&x1, &dwork, &set); /* Load result into FP register r1 */ ARCH_DEP(dfp_reg_from_decimal64)(r1, &x1, regs); } /* end DEF_INST(convert_sbcd64_to_dfp_long_reg) */ /*-------------------------------------------------------------------*/ /* B3FA CXUTR - Convert from unsigned BCD (128-bit to DFP ext) [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(convert_ubcd128_to_dfp_ext_reg) { unsigned i; /* Array subscript */ int r1, r2; /* Values of R fields */ decimal128 x1; /* Extended DFP values */ decNumber dwork, *dp; /* Working decimal numbers */ decContext set; /* Working context */ BYTE pwork[17]; /* 33-digit packed work area */ int32_t scale = 0; /* Scaling factor */ RRE(inst, regs, r1, r2); DFPINST_CHECK(regs); DFPREGPAIR_CHECK(r1, regs); ODD_CHECK(r2, regs); /* Initialise the context for extended DFP */ decContextDefault(&set, DEC_INIT_DECIMAL128); /* Store general register pair in work area */ pwork[0] = 0; STORE_DW(pwork+1, regs->GR_G(r2)); STORE_DW(pwork+9, regs->GR_G(r2+1)); /* Convert unsigned BCD to signed BCD */ for (i = 0; i < sizeof(pwork)-1; i++) pwork[i] = ((pwork[i] & 0x0F) << 4) | (pwork[i+1] >> 4); pwork[i] = ((pwork[i] & 0x0F) << 4) | 0x0F; /* Convert signed BCD to internal number format */ dp = decPackedToNumber(pwork, sizeof(pwork), &scale, &dwork); /* Data exception if digits invalid */ if (dp == NULL) { regs->dxc = DXC_DECIMAL; ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION); } /* Convert internal number to DFP extended format */ decimal128FromNumber(&x1, &dwork, &set); /* Load result into FP register r1 */ ARCH_DEP(dfp_reg_from_decimal128)(r1, &x1, regs); } /* end DEF_INST(convert_ubcd128_to_dfp_ext_reg) */ /*-------------------------------------------------------------------*/ /* B3F2 CDUTR - Convert from unsigned BCD (64-bit to DFP long) [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(convert_ubcd64_to_dfp_long_reg) { unsigned i; /* Array subscript */ int r1, r2; /* Values of R fields */ decimal64 x1; /* Long DFP values */ decNumber dwork, *dp; /* Working decimal numbers */ decContext set; /* Working context */ BYTE pwork[9]; /* 17-digit packed work area */ int32_t scale = 0; /* Scaling factor */ RRE(inst, regs, r1, r2); DFPINST_CHECK(regs); /* Initialise the context for long DFP */ decContextDefault(&set, DEC_INIT_DECIMAL64); /* Store general register in work area */ pwork[0] = 0; STORE_DW(pwork+1, regs->GR_G(r2)); /* Convert unsigned BCD to signed BCD */ for (i = 0; i < sizeof(pwork)-1; i++) pwork[i] = ((pwork[i] & 0x0F) << 4) | (pwork[i+1] >> 4); pwork[i] = ((pwork[i] & 0x0F) << 4) | 0x0F; /* Convert signed BCD to internal number format */ dp = decPackedToNumber(pwork, sizeof(pwork), &scale, &dwork); /* Data exception if digits or sign was invalid */ if (dp == NULL) { regs->dxc = DXC_DECIMAL; ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION); } /* Convert internal number to DFP long format */ decimal64FromNumber(&x1, &dwork, &set); /* Load result into FP register r1 */ ARCH_DEP(dfp_reg_from_decimal64)(r1, &x1, regs); } /* end DEF_INST(convert_ubcd64_to_dfp_long_reg) */ /*-------------------------------------------------------------------*/ /* B3E9 CGXTR - Convert from DFP Extended Register to fixed 64 [RRF] */ /*-------------------------------------------------------------------*/ DEF_INST(convert_dfp_ext_to_fix64_reg) { int r1, r2; /* Values of R fields */ int m3; /* Values of M fields */ S64 n1; /* Result value */ decimal128 x2; /* Extended DFP value */ decNumber d2; /* Working decimal number */ decContext set; /* Working context */ BYTE dxc; /* Data exception code */ RRF_M(inst, regs, r1, r2, m3); DFPINST_CHECK(regs); DFPREGPAIR_CHECK(r2, regs); /* Initialise the context for extended DFP */ decContextDefault(&set, DEC_INIT_DECIMAL128); ARCH_DEP(dfp_rounding_mode)(&set, m3, regs); /* Load extended DFP value from FP register r2 */ ARCH_DEP(dfp_reg_to_decimal128)(r2, &x2, regs); decimal128ToNumber(&x2, &d2); /* Convert decimal number to 64-bit binary integer */ n1 = dfp_number_to_fix64(&d2, &set); /* Check for exception condition */ dxc = ARCH_DEP(dfp_status_check)(&set, regs); /* Load result into general register r1 */ regs->GR_G(r1) = n1; /* Set condition code */ regs->psw.cc = (set.status & DEC_IEEE_854_Invalid_operation) ? 3 : decNumberIsZero(&d2) ? 0 : decNumberIsNegative(&d2) ? 1 : 2; /* Raise data exception if error occurred */ if (dxc != 0) { regs->dxc = dxc; ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION); } } /* end DEF_INST(convert_dfp_ext_to_fix64_reg) */ /*-------------------------------------------------------------------*/ /* B3E1 CGDTR - Convert from DFP Long Register to fixed 64 [RRF] */ /*-------------------------------------------------------------------*/ DEF_INST(convert_dfp_long_to_fix64_reg) { int r1, r2; /* Values of R fields */ int m3; /* Values of M fields */ S64 n1; /* Result value */ decimal64 x2; /* Long DFP value */ decNumber d2; /* Working decimal number */ decContext set; /* Working context */ BYTE dxc; /* Data exception code */ RRF_M(inst, regs, r1, r2, m3); DFPINST_CHECK(regs); /* Initialise the context for long DFP */ decContextDefault(&set, DEC_INIT_DECIMAL64); ARCH_DEP(dfp_rounding_mode)(&set, m3, regs); /* Load long DFP value from FP register r2 */ ARCH_DEP(dfp_reg_to_decimal64)(r2, &x2, regs); decimal64ToNumber(&x2, &d2); /* Convert decimal number to 64-bit binary integer */ n1 = dfp_number_to_fix64(&d2, &set); /* Check for exception condition */ dxc = ARCH_DEP(dfp_status_check)(&set, regs); /* Load result into general register r1 */ regs->GR_G(r1) = n1; /* Set condition code */ regs->psw.cc = (set.status & DEC_IEEE_854_Invalid_operation) ? 3 : decNumberIsZero(&d2) ? 0 : decNumberIsNegative(&d2) ? 1 : 2; /* Raise data exception if error occurred */ if (dxc != 0) { regs->dxc = dxc; ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION); } } /* end DEF_INST(convert_dfp_long_to_fix64_reg) */ /*-------------------------------------------------------------------*/ /* B3EB CSXTR - Convert to signed BCD (DFP ext to 128-bit) [RRF] */ /*-------------------------------------------------------------------*/ DEF_INST(convert_dfp_ext_to_sbcd128_reg) { int r1, r2; /* Values of R fields */ int m4; /* Values of M fields */ decimal128 x2; /* Extended DFP values */ decNumber dwork; /* Working decimal number */ decContext set; /* Working context */ int32_t scale; /* Scaling factor */ BYTE pwork[17]; /* 33-digit packed work area */ RRF_M4(inst, regs, r1, r2, m4); DFPINST_CHECK(regs); DFPREGPAIR_CHECK(r2, regs); ODD_CHECK(r1, regs); /* Initialise the context for extended DFP */ decContextDefault(&set, DEC_INIT_DECIMAL128); /* Load DFP extended number from FP register r2 */ ARCH_DEP(dfp_reg_to_decimal128)(r2, &x2, regs); decimal128ToNumber(&x2, &dwork); /* If NaN or Inf then use coefficient only */ if (decNumberIsNaN(&dwork) || (decNumberIsInfinite(&dwork))) { dfp128_clear_cf_and_bxcf(&x2); decimal128ToNumber(&x2, &dwork); } /* Convert number to signed BCD in work area */ decPackedFromNumber(pwork, sizeof(pwork), &scale, &dwork); /* Make the plus-sign X'F' if m4 bit 3 is one */ if ((m4 & 0x01) && !decNumberIsNegative(&dwork)) pwork[sizeof(pwork)-1] |= 0x0F; /* Load general register pair r1 and r1+1 from rightmost 31 packed decimal digits of work area */ FETCH_DW(regs->GR_G(r1), pwork+sizeof(pwork)-16); FETCH_DW(regs->GR_G(r1+1), pwork+sizeof(pwork)-8); } /* end DEF_INST(convert_dfp_ext_to_sbcd128_reg) */ /*-------------------------------------------------------------------*/ /* B3E3 CSDTR - Convert to signed BCD (DFP long to 64-bit) [RRF] */ /*-------------------------------------------------------------------*/ DEF_INST(convert_dfp_long_to_sbcd64_reg) { int r1, r2; /* Values of R fields */ int m4; /* Values of M fields */ decimal64 x2; /* Long DFP values */ decNumber dwork; /* Working decimal number */ decContext set; /* Working context */ int32_t scale; /* Scaling factor */ BYTE pwork[9]; /* 17-digit packed work area */ RRF_M4(inst, regs, r1, r2, m4); DFPINST_CHECK(regs); /* Initialise the context for long DFP */ decContextDefault(&set, DEC_INIT_DECIMAL64); /* Load DFP long number from FP register r2 */ ARCH_DEP(dfp_reg_to_decimal64)(r2, &x2, regs); decimal64ToNumber(&x2, &dwork); /* If NaN or Inf then use coefficient only */ if (decNumberIsNaN(&dwork) || (decNumberIsInfinite(&dwork))) { dfp64_clear_cf_and_bxcf(&x2); decimal64ToNumber(&x2, &dwork); } /* Convert number to signed BCD in work area */ decPackedFromNumber(pwork, sizeof(pwork), &scale, &dwork); /* Make the plus-sign X'F' if m4 bit 3 is one */ if ((m4 & 0x01) && !decNumberIsNegative(&dwork)) pwork[sizeof(pwork)-1] |= 0x0F; /* Load general register r1 from rightmost 15 packed decimal digits of work area */ FETCH_DW(regs->GR_G(r1), pwork+sizeof(pwork)-8); } /* end DEF_INST(convert_dfp_long_to_sbcd64_reg) */ /*-------------------------------------------------------------------*/ /* B3EA CUXTR - Convert to unsigned BCD (DFP ext to 128-bit) [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(convert_dfp_ext_to_ubcd128_reg) { int i; /* Array subscript */ int r1, r2; /* Values of R fields */ decimal128 x2; /* Extended DFP values */ decNumber dwork; /* Working decimal number */ decContext set; /* Working context */ int32_t scale; /* Scaling factor */ BYTE pwork[17]; /* 33-digit packed work area */ RRE(inst, regs, r1, r2); DFPINST_CHECK(regs); DFPREGPAIR_CHECK(r2, regs); ODD_CHECK(r1, regs); /* Initialise the context for extended DFP */ decContextDefault(&set, DEC_INIT_DECIMAL128); /* Load DFP extended number from FP register r2 */ ARCH_DEP(dfp_reg_to_decimal128)(r2, &x2, regs); decimal128ToNumber(&x2, &dwork); /* If NaN or Inf then use coefficient only */ if (decNumberIsNaN(&dwork) || (decNumberIsInfinite(&dwork))) { dfp128_clear_cf_and_bxcf(&x2); decimal128ToNumber(&x2, &dwork); } /* Convert number to signed BCD in work area */ decPackedFromNumber(pwork, sizeof(pwork), &scale, &dwork); /* Convert signed BCD to unsigned BCD */ for (i = sizeof(pwork)-1; i > 0; i--) pwork[i] = (pwork[i] >> 4) | ((pwork[i-1] & 0x0F) << 4); /* Load general register pair r1 and r1+1 from rightmost 32 packed decimal digits of work area */ FETCH_DW(regs->GR_G(r1), pwork+sizeof(pwork)-16); FETCH_DW(regs->GR_G(r1+1), pwork+sizeof(pwork)-8); } /* end DEF_INST(convert_dfp_ext_to_ubcd128_reg) */ /*-------------------------------------------------------------------*/ /* B3E2 CUDTR - Convert to unsigned BCD (DFP long to 64-bit) [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(convert_dfp_long_to_ubcd64_reg) { int i; /* Array subscript */ int r1, r2; /* Values of R fields */ decimal64 x2; /* Long DFP values */ decNumber dwork; /* Working decimal number */ decContext set; /* Working context */ int32_t scale; /* Scaling factor */ BYTE pwork[9]; /* 17-digit packed work area */ RRE(inst, regs, r1, r2); DFPINST_CHECK(regs); /* Initialise the context for long DFP */ decContextDefault(&set, DEC_INIT_DECIMAL64); /* Load DFP long number from FP register r2 */ ARCH_DEP(dfp_reg_to_decimal64)(r2, &x2, regs); decimal64ToNumber(&x2, &dwork); /* If NaN or Inf then use coefficient only */ if (decNumberIsNaN(&dwork) || (decNumberIsInfinite(&dwork))) { dfp64_clear_cf_and_bxcf(&x2); decimal64ToNumber(&x2, &dwork); } /* Convert number to signed BCD in work area */ decPackedFromNumber(pwork, sizeof(pwork), &scale, &dwork); /* Convert signed BCD to unsigned BCD */ for (i = sizeof(pwork)-1; i > 0; i--) pwork[i] = (pwork[i] >> 4) | ((pwork[i-1] & 0x0F) << 4); /* Load general register r1 from rightmost 16 packed decimal digits of work area */ FETCH_DW(regs->GR_G(r1), pwork+sizeof(pwork)-8); } /* end DEF_INST(convert_dfp_long_to_ubcd64_reg) */ /*-------------------------------------------------------------------*/ /* B3D9 DXTR - Divide DFP Extended Register [RRR] */ /*-------------------------------------------------------------------*/ DEF_INST(divide_dfp_ext_reg) { int r1, r2, r3; /* Values of R fields */ decimal128 x1, x2, x3; /* Extended DFP values */ decNumber d1, d2, d3; /* Working decimal numbers */ decContext set; /* Working context */ BYTE dxc; /* Data exception code */ RRR(inst, regs, r1, r2, r3); DFPINST_CHECK(regs); DFPREGPAIR3_CHECK(r1, r2, r3, regs); /* Initialise the context for extended DFP */ decContextDefault(&set, DEC_INIT_DECIMAL128); ARCH_DEP(dfp_rounding_mode)(&set, 0, regs); /* Divide FP register r2 by FP register r3 */ ARCH_DEP(dfp_reg_to_decimal128)(r2, &x2, regs); ARCH_DEP(dfp_reg_to_decimal128)(r3, &x3, regs); decimal128ToNumber(&x2, &d2); decimal128ToNumber(&x3, &d3); decNumberDivide(&d1, &d2, &d3, &set); decimal128FromNumber(&x1, &d1, &set); /* Check for exception condition */ dxc = ARCH_DEP(dfp_status_check)(&set, regs); /* Load result into FP register r1 */ ARCH_DEP(dfp_reg_from_decimal128)(r1, &x1, regs); /* Raise data exception if error occurred */ if (dxc != 0) { regs->dxc = dxc; ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION); } } /* end DEF_INST(divide_dfp_ext_reg) */ /*-------------------------------------------------------------------*/ /* B3D1 DDTR - Divide DFP Long Register [RRR] */ /*-------------------------------------------------------------------*/ DEF_INST(divide_dfp_long_reg) { int r1, r2, r3; /* Values of R fields */ decimal64 x1, x2, x3; /* Long DFP values */ decNumber d1, d2, d3; /* Working decimal numbers */ decContext set; /* Working context */ BYTE dxc; /* Data exception code */ RRR(inst, regs, r1, r2, r3); DFPINST_CHECK(regs); /* Initialise the context for long DFP */ decContextDefault(&set, DEC_INIT_DECIMAL64); ARCH_DEP(dfp_rounding_mode)(&set, 0, regs); /* Divide FP register r2 by FP register r3 */ ARCH_DEP(dfp_reg_to_decimal64)(r2, &x2, regs); ARCH_DEP(dfp_reg_to_decimal64)(r3, &x3, regs); decimal64ToNumber(&x2, &d2); decimal64ToNumber(&x3, &d3); decNumberDivide(&d1, &d2, &d3, &set); decimal64FromNumber(&x1, &d1, &set); /* Check for exception condition */ dxc = ARCH_DEP(dfp_status_check)(&set, regs); /* Load result into FP register r1 */ ARCH_DEP(dfp_reg_from_decimal64)(r1, &x1, regs); /* Raise data exception if error occurred */ if (dxc != 0) { regs->dxc = dxc; ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION); } } /* end DEF_INST(divide_dfp_long_reg) */ /*-------------------------------------------------------------------*/ /* B3ED EEXTR - Extract Biased Exponent DFP Extended Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(extract_biased_exponent_dfp_ext_to_fix64_reg) { int r1, r2; /* Values of R fields */ decimal128 x2; /* Extended DFP value */ decNumber d2; /* Working decimal number */ decContext set; /* Working context */ S64 exponent; /* Biased exponent */ RRE(inst, regs, r1, r2); DFPINST_CHECK(regs); DFPREGPAIR_CHECK(r2, regs); /* Initialise the context for extended DFP */ decContextDefault(&set, DEC_INIT_DECIMAL128); /* Load DFP extended number from FP register r2 */ ARCH_DEP(dfp_reg_to_decimal128)(r2, &x2, regs); /* Convert to internal decimal number format */ decimal128ToNumber(&x2, &d2); /* Calculate the biased exponent */ if (decNumberIsInfinite(&d2)) exponent = -1; else if (decNumberIsQNaN(&d2)) exponent = -2; else if (decNumberIsSNaN(&d2)) exponent = -3; else exponent = d2.exponent + DECIMAL128_Bias; /* Load result into general register r1 */ regs->GR(r1) = exponent; } /* end DEF_INST(extract_biased_exponent_dfp_ext_to_fix64_reg) */ /*-------------------------------------------------------------------*/ /* B3E5 EEDTR - Extract Biased Exponent DFP Long Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(extract_biased_exponent_dfp_long_to_fix64_reg) { int r1, r2; /* Values of R fields */ decimal64 x2; /* Long DFP value */ decNumber d2; /* Working decimal number */ decContext set; /* Working context */ S64 exponent; /* Biased exponent */ RRE(inst, regs, r1, r2); DFPINST_CHECK(regs); /* Initialise the context for long DFP */ decContextDefault(&set, DEC_INIT_DECIMAL64); /* Load DFP long number from FP register r2 */ ARCH_DEP(dfp_reg_to_decimal64)(r2, &x2, regs); /* Convert to internal decimal number format */ decimal64ToNumber(&x2, &d2); /* Calculate the biased exponent */ if (decNumberIsInfinite(&d2)) exponent = -1; else if (decNumberIsQNaN(&d2)) exponent = -2; else if (decNumberIsSNaN(&d2)) exponent = -3; else exponent = d2.exponent + DECIMAL64_Bias; /* Load result into general register r1 */ regs->GR(r1) = exponent; } /* end DEF_INST(extract_biased_exponent_dfp_long_to_fix64_reg) */ /*-------------------------------------------------------------------*/ /* B3EF ESXTR - Extract Significance DFP Extended Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(extract_significance_dfp_ext_reg) { int r1, r2; /* Values of R fields */ decimal128 x2; /* Extended DFP value */ decNumber d2; /* Working decimal number */ decContext set; /* Working context */ S64 digits; /* Number of decimal digits */ RRE(inst, regs, r1, r2); DFPINST_CHECK(regs); DFPREGPAIR_CHECK(r2, regs); /* Initialise the context for extended DFP */ decContextDefault(&set, DEC_INIT_DECIMAL128); /* Load DFP extended number from FP register r2 */ ARCH_DEP(dfp_reg_to_decimal128)(r2, &x2, regs); /* Convert to internal decimal number format */ decimal128ToNumber(&x2, &d2); /* Calculate number of significant digits */ if (decNumberIsZero(&d2)) digits = 0; else if (decNumberIsInfinite(&d2)) digits = -1; else if (decNumberIsQNaN(&d2)) digits = -2; else if (decNumberIsSNaN(&d2)) digits = -3; else digits = d2.digits; /* Load result into general register r1 */ regs->GR(r1) = digits; } /* end DEF_INST(extract_significance_dfp_ext_reg) */ /*-------------------------------------------------------------------*/ /* B3E7 ESDTR - Extract Significance DFP Long Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(extract_significance_dfp_long_reg) { int r1, r2; /* Values of R fields */ decimal64 x2; /* Long DFP value */ decNumber d2; /* Working decimal number */ decContext set; /* Working context */ S64 digits; /* Number of decimal digits */ RRE(inst, regs, r1, r2); DFPINST_CHECK(regs); /* Initialise the context for long DFP */ decContextDefault(&set, DEC_INIT_DECIMAL64); /* Load DFP long number from FP register r2 */ ARCH_DEP(dfp_reg_to_decimal64)(r2, &x2, regs); /* Convert to internal decimal number format */ decimal64ToNumber(&x2, &d2); /* Calculate number of significant digits */ if (decNumberIsZero(&d2)) digits = 0; else if (decNumberIsInfinite(&d2)) digits = -1; else if (decNumberIsQNaN(&d2)) digits = -2; else if (decNumberIsSNaN(&d2)) digits = -3; else digits = d2.digits; /* Load result into general register r1 */ regs->GR(r1) = digits; } /* end DEF_INST(extract_significance_dfp_long_reg) */ /*-------------------------------------------------------------------*/ /* B3FE IEXTR - Insert Biased Exponent DFP Extended Register [RRF] */ /*-------------------------------------------------------------------*/ DEF_INST(insert_biased_exponent_fix64_to_dfp_ext_reg) { int r1, r2, r3; /* Values of R fields */ decimal128 x1, x3; /* Extended DFP values */ decNumber d; /* Working decimal number */ decContext set; /* Working context */ S64 bexp; /* Biased exponent */ RRF_M(inst, regs, r1, r2, r3); DFPINST_CHECK(regs); DFPREGPAIR2_CHECK(r1, r3, regs); /* Initialise the context for extended DFP */ decContextDefault(&set, DEC_INIT_DECIMAL128); /* Load biased exponent from general register r2 */ bexp = (S64)(regs->GR(r2)); /* Load DFP extended number from FP register r3 */ ARCH_DEP(dfp_reg_to_decimal128)(r3, &x3, regs); /* Insert biased exponent into number */ if (bexp > DECIMAL128_Ehigh || bexp == -2 || bexp <= -4) { /* Result is a QNaN with re-encoded coefficient-continuation */ dfp128_clear_cf_and_bxcf(&x3); decimal128ToNumber(&x3, &d); decimal128FromNumber(&x1, &d, &set); dfp128_set_cf_and_bxcf(&x1, DFP_CFS_QNAN); } else if (bexp == -3) { /* Result is a SNaN with re-encoded coefficient-continuation */ dfp128_clear_cf_and_bxcf(&x3); decimal128ToNumber(&x3, &d); decimal128FromNumber(&x1, &d, &set); dfp128_set_cf_and_bxcf(&x1, DFP_CFS_SNAN); } else if (bexp == -1) /* Infinity */ { /* Result is Infinity with re-encoded coefficient-continuation */ dfp128_clear_cf_and_bxcf(&x3); decimal128ToNumber(&x3, &d); decimal128FromNumber(&x1, &d, &set); dfp128_set_cf_and_bxcf(&x1, DFP_CFS_INF); } else { decimal128ToNumber(&x3, &d); /* Clear CF and BXCF if source is Infinity or NaN */ if (decNumberIsInfinite(&d) || decNumberIsNaN(&d)) { dfp128_clear_cf_and_bxcf(&x3); decimal128ToNumber(&x3, &d); } /* Update exponent and re-encode coefficient-continuation */ d.exponent = bexp - DECIMAL128_Bias; decimal128FromNumber(&x1, &d, &set); } /* Load result into FP register r1 */ ARCH_DEP(dfp_reg_from_decimal128)(r1, &x1, regs); } /* end DEF_INST(insert_biased_exponent_fix64_to_dfp_ext_reg) */ /*-------------------------------------------------------------------*/ /* B3F6 IEDTR - Insert Biased Exponent DFP Long Register [RRF] */ /*-------------------------------------------------------------------*/ DEF_INST(insert_biased_exponent_fix64_to_dfp_long_reg) { int r1, r2, r3; /* Values of R fields */ decimal64 x1, x3; /* Long DFP values */ decNumber d; /* Working decimal number */ decContext set; /* Working context */ S64 bexp; /* Biased exponent */ RRF_M(inst, regs, r1, r2, r3); DFPINST_CHECK(regs); /* Initialise the context for long DFP */ decContextDefault(&set, DEC_INIT_DECIMAL64); /* Load biased exponent from general register r2 */ bexp = (S64)(regs->GR(r2)); /* Load DFP long number from FP register r3 */ ARCH_DEP(dfp_reg_to_decimal64)(r3, &x3, regs); /* Insert biased exponent into number */ if (bexp > DECIMAL64_Ehigh || bexp == -2 || bexp <= -4) { /* Result is a QNaN with re-encoded coefficient-continuation */ dfp64_clear_cf_and_bxcf(&x3); decimal64ToNumber(&x3, &d); decimal64FromNumber(&x1, &d, &set); dfp64_set_cf_and_bxcf(&x1, DFP_CFS_QNAN); } else if (bexp == -3) { /* Result is a SNaN with re-encoded coefficient-continuation */ dfp64_clear_cf_and_bxcf(&x3); decimal64ToNumber(&x3, &d); decimal64FromNumber(&x1, &d, &set); dfp64_set_cf_and_bxcf(&x1, DFP_CFS_SNAN); } else if (bexp == -1) /* Infinity */ { /* Result is Infinity with re-encoded coefficient-continuation */ dfp64_clear_cf_and_bxcf(&x3); decimal64ToNumber(&x3, &d); decimal64FromNumber(&x1, &d, &set); dfp64_set_cf_and_bxcf(&x1, DFP_CFS_INF); } else { decimal64ToNumber(&x3, &d); /* Clear CF and BXCF if source is Infinity or NaN */ if (decNumberIsInfinite(&d) || decNumberIsNaN(&d)) { dfp64_clear_cf_and_bxcf(&x3); decimal64ToNumber(&x3, &d); } /* Update exponent and re-encode coefficient-continuation */ d.exponent = bexp - DECIMAL64_Bias; decimal64FromNumber(&x1, &d, &set); } /* Load result into FP register r1 */ ARCH_DEP(dfp_reg_from_decimal64)(r1, &x1, regs); } /* end DEF_INST(insert_biased_exponent_fix64_to_dfp_long_reg) */ /*-------------------------------------------------------------------*/ /* B3DE LTXTR - Load and Test DFP Extended Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(load_and_test_dfp_ext_reg) { int r1, r2; /* Values of R fields */ decimal128 x1, x2; /* Extended DFP values */ decNumber d; /* Working decimal number */ decContext set; /* Working context */ BYTE dxc; /* Data exception code */ RRE(inst, regs, r1, r2); DFPINST_CHECK(regs); DFPREGPAIR2_CHECK(r1, r2, regs); /* Initialise the context for extended DFP */ decContextDefault(&set, DEC_INIT_DECIMAL128); /* Load value from FP register r2 */ ARCH_DEP(dfp_reg_to_decimal128)(r2, &x2, regs); decimal128ToNumber(&x2, &d); /* For SNaN, force signaling condition and convert to QNaN */ if (decNumberIsSNaN(&d)) { set.status |= DEC_IEEE_854_Invalid_operation; d.bits &= ~DECSNAN; d.bits |= DECNAN; } /* Check for exception condition */ dxc = ARCH_DEP(dfp_status_check)(&set, regs); /* Reencode value and load into FP register r1 */ decimal128FromNumber(&x1, &d, &set); ARCH_DEP(dfp_reg_from_decimal128)(r1, &x1, regs); /* Set condition code */ regs->psw.cc = decNumberIsNaN(&d) ? 3 : decNumberIsZero(&d) ? 0 : decNumberIsNegative(&d) ? 1 : 2; /* Raise data exception if error occurred */ if (dxc != 0) { regs->dxc = dxc; ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION); } } /* end DEF_INST(load_and_test_dfp_ext_reg) */ /*-------------------------------------------------------------------*/ /* B3D6 LTDTR - Load and Test DFP Long Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(load_and_test_dfp_long_reg) { int r1, r2; /* Values of R fields */ decimal64 x1, x2; /* Long DFP values */ decNumber d; /* Working decimal number */ decContext set; /* Working context */ BYTE dxc; /* Data exception code */ RRE(inst, regs, r1, r2); DFPINST_CHECK(regs); /* Initialise the context for long DFP */ decContextDefault(&set, DEC_INIT_DECIMAL64); /* Load value from FP register r2 */ ARCH_DEP(dfp_reg_to_decimal64)(r2, &x2, regs); decimal64ToNumber(&x2, &d); /* For SNaN, force signaling condition and convert to QNaN */ if (decNumberIsSNaN(&d)) { set.status |= DEC_IEEE_854_Invalid_operation; d.bits &= ~DECSNAN; d.bits |= DECNAN; } /* Check for exception condition */ dxc = ARCH_DEP(dfp_status_check)(&set, regs); /* Reencode value and load into FP register r1 */ decimal64FromNumber(&x1, &d, &set); ARCH_DEP(dfp_reg_from_decimal64)(r1, &x1, regs); /* Set condition code */ regs->psw.cc = decNumberIsNaN(&d) ? 3 : decNumberIsZero(&d) ? 0 : decNumberIsNegative(&d) ? 1 : 2; /* Raise data exception if error occurred */ if (dxc != 0) { regs->dxc = dxc; ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION); } } /* end DEF_INST(load_and_test_dfp_long_reg) */ /*-------------------------------------------------------------------*/ /* B3DF FIXTR - Load FP Integer DFP Extended Register [RRF] */ /*-------------------------------------------------------------------*/ DEF_INST(load_fp_int_dfp_ext_reg) { int r1, r2, m3, m4; /* Values of R and M fields */ decimal128 x1, x2; /* Extended DFP values */ decNumber d1, d2, dc; /* Working decimal numbers */ decContext set; /* Working context */ BYTE dxc; /* Data exception code */ RRF_MM(inst, regs, r1, r2, m3, m4); DFPINST_CHECK(regs); DFPREGPAIR2_CHECK(r1, r2, regs); /* Initialise the context for extended DFP */ decContextDefault(&set, DEC_INIT_DECIMAL128); ARCH_DEP(dfp_rounding_mode)(&set, m3, regs); /* Load decimal number from FP register r2 */ ARCH_DEP(dfp_reg_to_decimal128)(r2, &x2, regs); decimal128ToNumber(&x2, &d2); if (decNumberIsInfinite(&d2) == 0 && decNumberIsNaN(&d2) == 0) { /* Remove fractional part of decimal number */ decNumberToIntegralValue(&d1, &d2, &set); /* Raise inexact condition if M4 bit 1 is zero and result differs in value from original value */ if ((m4 & 0x04) == 0) { decNumberCompare(&dc, &d1, &d2, &set); if (decNumberIsZero(&dc) == 0) { set.status |= DEC_IEEE_854_Inexact; if (decNumberIsNegative(&dc) == decNumberIsNegative(&d2)) set.status |= DEC_Rounded; } } } else { /* Propagate NaN or default infinity */ decNumberCopy(&d1, &d2); /* For SNaN, force signaling condition and convert to QNaN */ if (decNumberIsSNaN(&d2)) { set.status |= DEC_IEEE_854_Invalid_operation; d1.bits &= ~DECSNAN; d1.bits |= DECNAN; } } /* Convert result to extended DFP format */ decimal128FromNumber(&x1, &d1, &set); /* Check for exception condition */ dxc = ARCH_DEP(dfp_status_check)(&set, regs); /* Load result into FP register r1 */ ARCH_DEP(dfp_reg_from_decimal128)(r1, &x1, regs); /* Raise data exception if error occurred */ if (dxc != 0) { regs->dxc = dxc; ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION); } } /* end DEF_INST(load_fp_int_dfp_ext_reg) */ /*-------------------------------------------------------------------*/ /* B3D7 FIDTR - Load FP Integer DFP Long Register [RRF] */ /*-------------------------------------------------------------------*/ DEF_INST(load_fp_int_dfp_long_reg) { int r1, r2, m3, m4; /* Values of R and M fields */ decimal64 x1, x2; /* Long DFP values */ decNumber d1, d2, dc; /* Working decimal numbers */ decContext set; /* Working context */ BYTE dxc; /* Data exception code */ RRF_MM(inst, regs, r1, r2, m3, m4); DFPINST_CHECK(regs); /* Initialise the context for long DFP */ decContextDefault(&set, DEC_INIT_DECIMAL64); ARCH_DEP(dfp_rounding_mode)(&set, m3, regs); /* Load decimal number from FP register r2 */ ARCH_DEP(dfp_reg_to_decimal64)(r2, &x2, regs); decimal64ToNumber(&x2, &d2); if (decNumberIsInfinite(&d2) == 0 && decNumberIsNaN(&d2) == 0) { /* Remove fractional part of decimal number */ decNumberToIntegralValue(&d1, &d2, &set); /* Raise inexact condition if M4 bit 1 is zero and result differs in value from original value */ if ((m4 & 0x04) == 0) { decNumberCompare(&dc, &d1, &d2, &set); if (decNumberIsZero(&dc) == 0) { set.status |= DEC_IEEE_854_Inexact; if (decNumberIsNegative(&dc) == decNumberIsNegative(&d2)) set.status |= DEC_Rounded; } } } else { /* Propagate NaN or default infinity */ decNumberCopy(&d1, &d2); /* For SNaN, force signaling condition and convert to QNaN */ if (decNumberIsSNaN(&d2)) { set.status |= DEC_IEEE_854_Invalid_operation; d1.bits &= ~DECSNAN; d1.bits |= DECNAN; } } /* Convert result to long DFP format */ decimal64FromNumber(&x1, &d1, &set); /* Check for exception condition */ dxc = ARCH_DEP(dfp_status_check)(&set, regs); /* Load result into FP register r1 */ ARCH_DEP(dfp_reg_from_decimal64)(r1, &x1, regs); /* Raise data exception if error occurred */ if (dxc != 0) { regs->dxc = dxc; ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION); } } /* end DEF_INST(load_fp_int_dfp_long_reg) */ /*-------------------------------------------------------------------*/ /* B3DC LXDTR - Load Lengthened DFP Long to Extended Register [RRF] */ /*-------------------------------------------------------------------*/ DEF_INST(load_lengthened_dfp_long_to_ext_reg) { int r1, r2, m4; /* Values of R and M fields */ decimal128 x1; /* Extended DFP value */ decimal64 x2; /* Long DFP value */ decNumber d1, d2; /* Working decimal numbers */ decContext set; /* Working context */ BYTE dxc; /* Data exception code */ RRF_M4(inst, regs, r1, r2, m4); DFPINST_CHECK(regs); DFPREGPAIR_CHECK(r1, regs); /* Initialise the context for extended DFP */ decContextDefault(&set, DEC_INIT_DECIMAL128); /* Load DFP long number from FP register r2 */ ARCH_DEP(dfp_reg_to_decimal64)(r2, &x2, regs); decimal64ToNumber(&x2, &d2); /* Convert number to DFP extended format */ if (decNumberIsInfinite(&d2) && (m4 & 0x08)) { /* For Inf with mask bit 0 set, propagate the digits */ dfp64_clear_cf_and_bxcf(&x2); decimal64ToNumber(&x2, &d1); decimal128FromNumber(&x1, &d1, &set); dfp128_set_cf_and_bxcf(&x1, DFP_CFS_INF); } else if (decNumberIsNaN(&d2)) { decimal64ToNumber(&x2, &d1); /* For SNaN with mask bit 0 off, convert to a QNaN and raise signaling condition */ if (decNumberIsSNaN(&d2) && (m4 & 0x08) == 0) { set.status |= DEC_IEEE_854_Invalid_operation; d1.bits &= ~DECSNAN; d1.bits |= DECNAN; } decimal128FromNumber(&x1, &d1, &set); } else { decNumberCopy(&d1, &d2); decimal128FromNumber(&x1, &d1, &set); } /* Check for exception condition */ dxc = ARCH_DEP(dfp_status_check)(&set, regs); /* Load result into FP register r1 */ ARCH_DEP(dfp_reg_from_decimal128)(r1, &x1, regs); /* Raise data exception if error occurred */ if (dxc != 0) { regs->dxc = dxc; ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION); } } /* end DEF_INST(load_lengthened_dfp_long_to_ext_reg) */ /*-------------------------------------------------------------------*/ /* B3D4 LDETR - Load Lengthened DFP Short to Long Register [RRF] */ /*-------------------------------------------------------------------*/ DEF_INST(load_lengthened_dfp_short_to_long_reg) { int r1, r2, m4; /* Values of R and M fields */ decimal64 x1; /* Long DFP value */ decimal32 x2; /* Short DFP value */ decNumber d1, d2; /* Working decimal numbers */ decContext set; /* Working context */ BYTE dxc; /* Data exception code */ RRF_M4(inst, regs, r1, r2, m4); DFPINST_CHECK(regs); /* Initialise the context for long DFP */ decContextDefault(&set, DEC_INIT_DECIMAL64); /* Load DFP short number from FP register r2 */ ARCH_DEP(dfp_reg_to_decimal32)(r2, &x2, regs); decimal32ToNumber(&x2, &d2); /* Convert number to DFP long format */ if (decNumberIsInfinite(&d2) && (m4 & 0x08)) { /* For Inf with mask bit 0 set, propagate the digits */ dfp32_clear_cf_and_bxcf(&x2); decimal32ToNumber(&x2, &d1); decimal64FromNumber(&x1, &d1, &set); dfp64_set_cf_and_bxcf(&x1, DFP_CFS_INF); } else if (decNumberIsNaN(&d2)) { decimal32ToNumber(&x2, &d1); /* For SNaN with mask bit 0 off, convert to a QNaN and raise signaling condition */ if (decNumberIsSNaN(&d2) && (m4 & 0x08) == 0) { set.status |= DEC_IEEE_854_Invalid_operation; d1.bits &= ~DECSNAN; d1.bits |= DECNAN; } decimal64FromNumber(&x1, &d1, &set); } else { decNumberCopy(&d1, &d2); decimal64FromNumber(&x1, &d1, &set); } /* Check for exception condition */ dxc = ARCH_DEP(dfp_status_check)(&set, regs); /* Load result into FP register r1 */ ARCH_DEP(dfp_reg_from_decimal64)(r1, &x1, regs); /* Raise data exception if error occurred */ if (dxc != 0) { regs->dxc = dxc; ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION); } } /* end DEF_INST(load_lengthened_dfp_short_to_long_reg) */ /*-------------------------------------------------------------------*/ /* B3DD LDXTR - Load Rounded DFP Extended to Long Register [RRF] */ /*-------------------------------------------------------------------*/ DEF_INST(load_rounded_dfp_ext_to_long_reg) { int r1, r2, m3, m4; /* Values of R and M fields */ decimal64 x1; /* Long DFP value */ decimal128 x2; /* Extended DFP value */ decNumber d1, d2; /* Working decimal numbers */ decContext set; /* Working context */ int32_t scale; /* Scaling factor */ BYTE pwork[17]; /* 33-digit packed work area */ BYTE dxc; /* Data exception code */ RRF_MM(inst, regs, r1, r2, m3, m4); DFPINST_CHECK(regs); DFPREGPAIR_CHECK(r2, regs); /* Initialise the context for extended DFP */ decContextDefault(&set, DEC_INIT_DECIMAL128); ARCH_DEP(dfp_rounding_mode)(&set, m3, regs); /* Load DFP extended number from FP register r2 */ ARCH_DEP(dfp_reg_to_decimal128)(r2, &x2, regs); decimal128ToNumber(&x2, &d2); /* Convert number to DFP long format */ if ((decNumberIsInfinite(&d2) && (m4 & 0x08)) || decNumberIsNaN(&d2)) { /* For Inf with mask bit 0 set, or for QNan or SNan, propagate the low 15 digits */ dfp128_clear_cf_and_bxcf(&x2); decimal128ToNumber(&x2, &d1); decPackedFromNumber(pwork, sizeof(pwork), &scale, &d1); scale = 0; decPackedToNumber(pwork+sizeof(pwork)-8, 8, &scale, &d1); decimal64FromNumber(&x1, &d1, &set); if (decNumberIsInfinite(&d2)) { dfp64_set_cf_and_bxcf(&x1, DFP_CFS_INF); } else if (decNumberIsQNaN(&d2)) { dfp64_set_cf_and_bxcf(&x1, DFP_CFS_QNAN); } else /* it is an SNaN */ { /* For SNaN with mask bit 0 off, convert to a QNaN and raise signaling condition */ if (decNumberIsSNaN(&d2) && (m4 & 0x08) == 0) { dfp64_set_cf_and_bxcf(&x1, DFP_CFS_QNAN); set.status |= DEC_IEEE_854_Invalid_operation; } else { dfp64_set_cf_and_bxcf(&x1, DFP_CFS_SNAN); } } } else { /* For finite number, load value rounded to long DFP format, or for Inf with mask bit 0 not set, load default infinity */ decNumberCopy(&d1, &d2); decimal64FromNumber(&x1, &d1, &set); } /* Check for exception condition */ dxc = ARCH_DEP(dfp_status_check)(&set, regs); /* Load result into FP register r1 */ ARCH_DEP(dfp_reg_from_decimal64)(r1, &x1, regs); /* Raise data exception if error occurred */ if (dxc != 0) { regs->dxc = dxc; ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION); } } /* end DEF_INST(load_rounded_dfp_ext_to_long_reg) */ /*-------------------------------------------------------------------*/ /* B3D5 LEDTR - Load Rounded DFP Long to Short Register [RRF] */ /*-------------------------------------------------------------------*/ DEF_INST(load_rounded_dfp_long_to_short_reg) { int r1, r2, m3, m4; /* Values of R and M fields */ decimal32 x1; /* Short DFP value */ decimal64 x2; /* Long DFP value */ decNumber d1, d2; /* Working decimal numbers */ decContext set; /* Working context */ int32_t scale; /* Scaling factor */ BYTE pwork[9]; /* 17-digit packed work area */ BYTE dxc; /* Data exception code */ RRF_MM(inst, regs, r1, r2, m3, m4); DFPINST_CHECK(regs); /* Initialise the context for long DFP */ decContextDefault(&set, DEC_INIT_DECIMAL64); ARCH_DEP(dfp_rounding_mode)(&set, m3, regs); /* Load DFP long number from FP register r2 */ ARCH_DEP(dfp_reg_to_decimal64)(r2, &x2, regs); decimal64ToNumber(&x2, &d2); /* Convert number to DFP short format */ if ((decNumberIsInfinite(&d2) && (m4 & 0x08)) || decNumberIsNaN(&d2)) { /* For Inf with mask bit 0 set, or for QNan or SNan, propagate the low 6 digits */ dfp64_clear_cf_and_bxcf(&x2); decimal64ToNumber(&x2, &d1); decPackedFromNumber(pwork, sizeof(pwork), &scale, &d1); scale = 0; decPackedToNumber(pwork+sizeof(pwork)-4, 4, &scale, &d1); decimal32FromNumber(&x1, &d1, &set); if (decNumberIsInfinite(&d2)) { dfp32_set_cf_and_bxcf(&x1, DFP_CFS_INF); } else if (decNumberIsQNaN(&d2)) { dfp32_set_cf_and_bxcf(&x1, DFP_CFS_QNAN); } else /* it is an SNaN */ { /* For SNaN with mask bit 0 off, convert to a QNaN and raise signaling condition */ if (decNumberIsSNaN(&d2) && (m4 & 0x08) == 0) { dfp32_set_cf_and_bxcf(&x1, DFP_CFS_QNAN); set.status |= DEC_IEEE_854_Invalid_operation; } else { dfp32_set_cf_and_bxcf(&x1, DFP_CFS_SNAN); } } } else { /* For finite number, load value rounded to short DFP format, or for Inf with mask bit 0 not set, load default infinity */ decNumberCopy(&d1, &d2); decimal32FromNumber(&x1, &d1, &set); } /* Check for exception condition */ dxc = ARCH_DEP(dfp_status_check)(&set, regs); /* Load result into FP register r1 */ ARCH_DEP(dfp_reg_from_decimal32)(r1, &x1, regs); /* Raise data exception if error occurred */ if (dxc != 0) { regs->dxc = dxc; ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION); } } /* end DEF_INST(load_rounded_dfp_long_to_short_reg) */ /*-------------------------------------------------------------------*/ /* B3D8 MXTR - Multiply DFP Extended Register [RRR] */ /*-------------------------------------------------------------------*/ DEF_INST(multiply_dfp_ext_reg) { int r1, r2, r3; /* Values of R fields */ decimal128 x1, x2, x3; /* Extended DFP values */ decNumber d1, d2, d3; /* Working decimal numbers */ decContext set; /* Working context */ BYTE dxc; /* Data exception code */ RRR(inst, regs, r1, r2, r3); DFPINST_CHECK(regs); DFPREGPAIR3_CHECK(r1, r2, r3, regs); /* Initialise the context for extended DFP */ decContextDefault(&set, DEC_INIT_DECIMAL128); ARCH_DEP(dfp_rounding_mode)(&set, 0, regs); /* Multiply FP register r2 by FP register r3 */ ARCH_DEP(dfp_reg_to_decimal128)(r2, &x2, regs); ARCH_DEP(dfp_reg_to_decimal128)(r3, &x3, regs); decimal128ToNumber(&x2, &d2); decimal128ToNumber(&x3, &d3); decNumberMultiply(&d1, &d2, &d3, &set); decimal128FromNumber(&x1, &d1, &set); /* Check for exception condition */ dxc = ARCH_DEP(dfp_status_check)(&set, regs); /* Load result into FP register r1 */ ARCH_DEP(dfp_reg_from_decimal128)(r1, &x1, regs); /* Raise data exception if error occurred */ if (dxc != 0) { regs->dxc = dxc; ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION); } } /* end DEF_INST(multiply_dfp_ext_reg) */ /*-------------------------------------------------------------------*/ /* B3D0 MDTR - Multiply DFP Long Register [RRR] */ /*-------------------------------------------------------------------*/ DEF_INST(multiply_dfp_long_reg) { int r1, r2, r3; /* Values of R fields */ decimal64 x1, x2, x3; /* Long DFP values */ decNumber d1, d2, d3; /* Working decimal numbers */ decContext set; /* Working context */ BYTE dxc; /* Data exception code */ RRR(inst, regs, r1, r2, r3); DFPINST_CHECK(regs); /* Initialise the context for long DFP */ decContextDefault(&set, DEC_INIT_DECIMAL64); ARCH_DEP(dfp_rounding_mode)(&set, 0, regs); /* Multiply FP register r2 by FP register r3 */ ARCH_DEP(dfp_reg_to_decimal64)(r2, &x2, regs); ARCH_DEP(dfp_reg_to_decimal64)(r3, &x3, regs); decimal64ToNumber(&x2, &d2); decimal64ToNumber(&x3, &d3); decNumberMultiply(&d1, &d2, &d3, &set); decimal64FromNumber(&x1, &d1, &set); /* Check for exception condition */ dxc = ARCH_DEP(dfp_status_check)(&set, regs); /* Load result into FP register r1 */ ARCH_DEP(dfp_reg_from_decimal64)(r1, &x1, regs); /* Raise data exception if error occurred */ if (dxc != 0) { regs->dxc = dxc; ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION); } } /* end DEF_INST(multiply_dfp_long_reg) */ /*-------------------------------------------------------------------*/ /* B3FD QAXTR - Quantize DFP Extended Register [RRF] */ /*-------------------------------------------------------------------*/ DEF_INST(quantize_dfp_ext_reg) { int r1, r2, r3, m4; /* Values of R and M fields */ decimal128 x1, x2, x3; /* Extended DFP values */ decNumber d1, d2, d3; /* Working decimal numbers */ decContext set; /* Working context */ BYTE dxc; /* Data exception code */ RRF_RM(inst, regs, r1, r2, r3, m4); DFPINST_CHECK(regs); DFPREGPAIR3_CHECK(r1, r2, r3, regs); /* Initialise the context for extended DFP */ decContextDefault(&set, DEC_INIT_DECIMAL128); ARCH_DEP(dfp_rounding_mode)(&set, m4, regs); /* Quantize FP register r3 using FP register r2 */ ARCH_DEP(dfp_reg_to_decimal128)(r2, &x2, regs); ARCH_DEP(dfp_reg_to_decimal128)(r3, &x3, regs); decimal128ToNumber(&x2, &d2); decimal128ToNumber(&x3, &d3); decNumberQuantize(&d1, &d2, &d3, &set); decimal128FromNumber(&x1, &d1, &set); /* Check for exception condition */ dxc = ARCH_DEP(dfp_status_check)(&set, regs); /* Load result into FP register r1 */ ARCH_DEP(dfp_reg_from_decimal128)(r1, &x1, regs); /* Raise data exception if error occurred */ if (dxc != 0) { regs->dxc = dxc; ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION); } } /* end DEF_INST(quantize_dfp_ext_reg) */ /*-------------------------------------------------------------------*/ /* B3F5 QADTR - Quantize DFP Long Register [RRF] */ /*-------------------------------------------------------------------*/ DEF_INST(quantize_dfp_long_reg) { int r1, r2, r3, m4; /* Values of R and M fields */ decimal64 x1, x2, x3; /* Long DFP values */ decNumber d1, d2, d3; /* Working decimal numbers */ decContext set; /* Working context */ BYTE dxc; /* Data exception code */ RRF_RM(inst, regs, r1, r2, r3, m4); DFPINST_CHECK(regs); /* Initialise the context for long DFP */ decContextDefault(&set, DEC_INIT_DECIMAL64); ARCH_DEP(dfp_rounding_mode)(&set, m4, regs); /* Quantize FP register r3 using FP register r2 */ ARCH_DEP(dfp_reg_to_decimal64)(r2, &x2, regs); ARCH_DEP(dfp_reg_to_decimal64)(r3, &x3, regs); decimal64ToNumber(&x2, &d2); decimal64ToNumber(&x3, &d3); decNumberQuantize(&d1, &d2, &d3, &set); decimal64FromNumber(&x1, &d1, &set); /* Check for exception condition */ dxc = ARCH_DEP(dfp_status_check)(&set, regs); /* Load result into FP register r1 */ ARCH_DEP(dfp_reg_from_decimal64)(r1, &x1, regs); /* Raise data exception if error occurred */ if (dxc != 0) { regs->dxc = dxc; ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION); } } /* end DEF_INST(quantize_dfp_long_reg) */ /*-------------------------------------------------------------------*/ /* B3FF RRXTR - Reround DFP Extended Register [RRF] */ /*-------------------------------------------------------------------*/ DEF_INST(reround_dfp_ext_reg) { int signif; /* Requested significance */ int r1, r2, r3, m4; /* Values of R and M fields */ decimal128 x1, x3; /* Extended DFP values */ decNumber d1, d3; /* Working decimal numbers */ decContext set; /* Working context */ BYTE dxc; /* Data exception code */ RRF_RM(inst, regs, r1, r2, r3, m4); DFPINST_CHECK(regs); DFPREGPAIR2_CHECK(r1, r3, regs); /* Initialise the context for extended DFP */ decContextDefault(&set, DEC_INIT_DECIMAL128); ARCH_DEP(dfp_rounding_mode)(&set, m4, regs); /* Load significance from bits 58-63 of general register r2 */ signif = regs->GR_L(r2) & 0x3F; /* Reround FP register r3 */ ARCH_DEP(dfp_reg_to_decimal128)(r3, &x3, regs); decimal128ToNumber(&x3, &d3); if (decNumberIsInfinite(&d3) || decNumberIsNaN(&d3) || decNumberIsZero(&d3) || signif == 0 || d3.digits <= signif) { decNumberCopy(&d1, &d3); } else { set.digits = signif; decNumberPlus(&d1, &d3, &set); } decimal128FromNumber(&x1, &d1, &set); /* Check for exception condition */ dxc = ARCH_DEP(dfp_status_check)(&set, regs); /* Load result into FP register r1 */ ARCH_DEP(dfp_reg_from_decimal128)(r1, &x1, regs); /* Raise data exception if error occurred */ if (dxc != 0) { regs->dxc = dxc; ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION); } } /* end DEF_INST(reround_dfp_ext_reg) */ /*-------------------------------------------------------------------*/ /* B3F7 RRDTR - Reround DFP Long Register [RRF] */ /*-------------------------------------------------------------------*/ DEF_INST(reround_dfp_long_reg) { int signif; /* Requested significance */ int r1, r2, r3, m4; /* Values of R and M fields */ decimal64 x1, x3; /* Long DFP values */ decNumber d1, d3; /* Working decimal numbers */ decContext set; /* Working context */ BYTE dxc; /* Data exception code */ RRF_RM(inst, regs, r1, r2, r3, m4); DFPINST_CHECK(regs); /* Initialise the context for long DFP */ decContextDefault(&set, DEC_INIT_DECIMAL64); ARCH_DEP(dfp_rounding_mode)(&set, m4, regs); /* Load significance from bits 58-63 of general register r2 */ signif = regs->GR_L(r2) & 0x3F; /* Reround FP register r3 */ ARCH_DEP(dfp_reg_to_decimal64)(r3, &x3, regs); decimal64ToNumber(&x3, &d3); if (decNumberIsInfinite(&d3) || decNumberIsNaN(&d3) || decNumberIsZero(&d3) || signif == 0 || d3.digits <= signif) { decNumberCopy(&d1, &d3); } else { set.digits = signif; decNumberPlus(&d1, &d3, &set); } decimal64FromNumber(&x1, &d1, &set); /* Check for exception condition */ dxc = ARCH_DEP(dfp_status_check)(&set, regs); /* Load result into FP register r1 */ ARCH_DEP(dfp_reg_from_decimal64)(r1, &x1, regs); /* Raise data exception if error occurred */ if (dxc != 0) { regs->dxc = dxc; ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION); } } /* end DEF_INST(reround_dfp_long_reg) */ /*-------------------------------------------------------------------*/ /* ED48 SLXT - Shift Coefficient Left DFP Extended [RXF] */ /*-------------------------------------------------------------------*/ DEF_INST(shift_coefficient_left_dfp_ext) { int r1, r3; /* Values of R fields */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ decimal128 x1, x3; /* Extended DFP values */ decNumber d1, d3; /* Working decimal numbers */ decContext set; /* Working context */ int n; /* Number of bits to shift */ RXF(inst, regs, r1, r3, b2, effective_addr2); DFPINST_CHECK(regs); DFPREGPAIR2_CHECK(r1, r3, regs); /* Isolate rightmost 6 bits of second operand address */ n = effective_addr2 & 0x3F; /* Initialise the context for extended DFP */ decContextDefault(&set, DEC_INIT_DECIMAL128); /* Load DFP extended number from FP register r3 */ ARCH_DEP(dfp_reg_to_decimal128)(r3, &x3, regs); /* Convert to internal decimal number format */ decimal128ToNumber(&x3, &d3); /* For NaN and Inf use coefficient continuation digits only */ if (decNumberIsNaN(&d3) || decNumberIsInfinite(&d3)) { dfp128_clear_cf_and_bxcf(&x3); decimal128ToNumber(&x3, &d1); } else { decNumberCopy(&d1, &d3); } /* Shift coefficient left n digit positions */ dfp_shift_coeff(&set, &d1, n); /* Convert result to DFP extended format */ decimal128FromNumber(&x1, &d1, &set); /* Restore Nan or Inf indicators in the result */ if (decNumberIsQNaN(&d3)) dfp128_set_cf_and_bxcf(&x1, DFP_CFS_QNAN); else if (decNumberIsSNaN(&d3)) dfp128_set_cf_and_bxcf(&x1, DFP_CFS_SNAN); else if (decNumberIsInfinite(&d3)) dfp128_set_cf_and_bxcf(&x1, DFP_CFS_INF); /* Load result into FP register r1 */ ARCH_DEP(dfp_reg_from_decimal128)(r1, &x1, regs); } /* end DEF_INST(shift_coefficient_left_dfp_ext) */ /*-------------------------------------------------------------------*/ /* ED40 SLDT - Shift Coefficient Left DFP Long [RXF] */ /*-------------------------------------------------------------------*/ DEF_INST(shift_coefficient_left_dfp_long) { int r1, r3; /* Values of R fields */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ decimal64 x1, x3; /* Long DFP values */ decNumber d1, d3; /* Working decimal numbers */ decContext set; /* Working context */ int n; /* Number of bits to shift */ RXF(inst, regs, r1, r3, b2, effective_addr2); DFPINST_CHECK(regs); /* Isolate rightmost 6 bits of second operand address */ n = effective_addr2 & 0x3F; /* Initialise the context for long DFP */ decContextDefault(&set, DEC_INIT_DECIMAL64); /* Load DFP long number from FP register r3 */ ARCH_DEP(dfp_reg_to_decimal64)(r3, &x3, regs); /* Convert to internal decimal number format */ decimal64ToNumber(&x3, &d3); /* For NaN and Inf use coefficient continuation digits only */ if (decNumberIsNaN(&d3) || decNumberIsInfinite(&d3)) { dfp64_clear_cf_and_bxcf(&x3); decimal64ToNumber(&x3, &d1); } else { decNumberCopy(&d1, &d3); } /* Shift coefficient left n digit positions */ dfp_shift_coeff(&set, &d1, n); /* Convert result to DFP long format */ decimal64FromNumber(&x1, &d1, &set); /* Restore Nan or Inf indicators in the result */ if (decNumberIsQNaN(&d3)) dfp64_set_cf_and_bxcf(&x1, DFP_CFS_QNAN); else if (decNumberIsSNaN(&d3)) dfp64_set_cf_and_bxcf(&x1, DFP_CFS_SNAN); else if (decNumberIsInfinite(&d3)) dfp64_set_cf_and_bxcf(&x1, DFP_CFS_INF); /* Load result into FP register r1 */ ARCH_DEP(dfp_reg_from_decimal64)(r1, &x1, regs); } /* end DEF_INST(shift_coefficient_left_dfp_long) */ /*-------------------------------------------------------------------*/ /* ED49 SRXT - Shift Coefficient Right DFP Extended [RXF] */ /*-------------------------------------------------------------------*/ DEF_INST(shift_coefficient_right_dfp_ext) { int r1, r3; /* Values of R fields */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ decimal128 x1, x3; /* Extended DFP values */ decNumber d1, d3; /* Working decimal numbers */ decContext set; /* Working context */ int n; /* Number of bits to shift */ RXF(inst, regs, r1, r3, b2, effective_addr2); DFPINST_CHECK(regs); DFPREGPAIR2_CHECK(r1, r3, regs); /* Isolate rightmost 6 bits of second operand address */ n = effective_addr2 & 0x3F; /* Initialise the context for extended DFP */ decContextDefault(&set, DEC_INIT_DECIMAL128); /* Load DFP extended number from FP register r3 */ ARCH_DEP(dfp_reg_to_decimal128)(r3, &x3, regs); /* Convert to internal decimal number format */ decimal128ToNumber(&x3, &d3); /* For NaN and Inf use coefficient continuation digits only */ if (decNumberIsNaN(&d3) || decNumberIsInfinite(&d3)) { dfp128_clear_cf_and_bxcf(&x3); decimal128ToNumber(&x3, &d1); } else { decNumberCopy(&d1, &d3); } /* Shift coefficient right n digit positions */ dfp_shift_coeff(&set, &d1, -n); /* Convert result to DFP extended format */ decimal128FromNumber(&x1, &d1, &set); /* Restore Nan or Inf indicators in the result */ if (decNumberIsQNaN(&d3)) dfp128_set_cf_and_bxcf(&x1, DFP_CFS_QNAN); else if (decNumberIsSNaN(&d3)) dfp128_set_cf_and_bxcf(&x1, DFP_CFS_SNAN); else if (decNumberIsInfinite(&d3)) dfp128_set_cf_and_bxcf(&x1, DFP_CFS_INF); /* Load result into FP register r1 */ ARCH_DEP(dfp_reg_from_decimal128)(r1, &x1, regs); } /* end DEF_INST(shift_coefficient_right_dfp_ext) */ /*-------------------------------------------------------------------*/ /* ED41 SRDT - Shift Coefficient Right DFP Long [RXF] */ /*-------------------------------------------------------------------*/ DEF_INST(shift_coefficient_right_dfp_long) { int r1, r3; /* Values of R fields */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ decimal64 x1, x3; /* Long DFP values */ decNumber d1, d3; /* Working decimal numbers */ decContext set; /* Working context */ int n; /* Number of bits to shift */ RXF(inst, regs, r1, r3, b2, effective_addr2); DFPINST_CHECK(regs); /* Isolate rightmost 6 bits of second operand address */ n = effective_addr2 & 0x3F; /* Initialise the context for long DFP */ decContextDefault(&set, DEC_INIT_DECIMAL64); /* Load DFP long number from FP register r3 */ ARCH_DEP(dfp_reg_to_decimal64)(r3, &x3, regs); /* Convert to internal decimal number format */ decimal64ToNumber(&x3, &d3); /* For NaN and Inf use coefficient continuation digits only */ if (decNumberIsNaN(&d3) || decNumberIsInfinite(&d3)) { dfp64_clear_cf_and_bxcf(&x3); decimal64ToNumber(&x3, &d1); } else { decNumberCopy(&d1, &d3); } /* Shift coefficient right n digit positions */ dfp_shift_coeff(&set, &d1, -n); /* Convert result to DFP long format */ decimal64FromNumber(&x1, &d1, &set); /* Restore Nan or Inf indicators in the result */ if (decNumberIsQNaN(&d3)) dfp64_set_cf_and_bxcf(&x1, DFP_CFS_QNAN); else if (decNumberIsSNaN(&d3)) dfp64_set_cf_and_bxcf(&x1, DFP_CFS_SNAN); else if (decNumberIsInfinite(&d3)) dfp64_set_cf_and_bxcf(&x1, DFP_CFS_INF); /* Load result into FP register r1 */ ARCH_DEP(dfp_reg_from_decimal64)(r1, &x1, regs); } /* end DEF_INST(shift_coefficient_right_dfp_long) */ /*-------------------------------------------------------------------*/ /* B3DB SXTR - Subtract DFP Extended Register [RRR] */ /*-------------------------------------------------------------------*/ DEF_INST(subtract_dfp_ext_reg) { int r1, r2, r3; /* Values of R fields */ decimal128 x1, x2, x3; /* Extended DFP values */ decNumber d1, d2, d3; /* Working decimal numbers */ decContext set; /* Working context */ BYTE dxc; /* Data exception code */ RRR(inst, regs, r1, r2, r3); DFPINST_CHECK(regs); DFPREGPAIR3_CHECK(r1, r2, r3, regs); /* Initialise the context for extended DFP */ decContextDefault(&set, DEC_INIT_DECIMAL128); ARCH_DEP(dfp_rounding_mode)(&set, 0, regs); /* Subtract FP register r3 from FP register r2 */ ARCH_DEP(dfp_reg_to_decimal128)(r2, &x2, regs); ARCH_DEP(dfp_reg_to_decimal128)(r3, &x3, regs); decimal128ToNumber(&x2, &d2); decimal128ToNumber(&x3, &d3); decNumberSubtract(&d1, &d2, &d3, &set); decimal128FromNumber(&x1, &d1, &set); /* Check for exception condition */ dxc = ARCH_DEP(dfp_status_check)(&set, regs); /* Load result into FP register r1 */ ARCH_DEP(dfp_reg_from_decimal128)(r1, &x1, regs); /* Set condition code */ regs->psw.cc = decNumberIsNaN(&d1) ? 3 : decNumberIsZero(&d1) ? 0 : decNumberIsNegative(&d1) ? 1 : 2; /* Raise data exception if error occurred */ if (dxc != 0) { regs->dxc = dxc; ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION); } } /* end DEF_INST(subtract_dfp_ext_reg) */ /*-------------------------------------------------------------------*/ /* B3D3 SDTR - Subtract DFP Long Register [RRR] */ /*-------------------------------------------------------------------*/ DEF_INST(subtract_dfp_long_reg) { int r1, r2, r3; /* Values of R fields */ decimal64 x1, x2, x3; /* Long DFP values */ decNumber d1, d2, d3; /* Working decimal numbers */ decContext set; /* Working context */ BYTE dxc; /* Data exception code */ RRR(inst, regs, r1, r2, r3); DFPINST_CHECK(regs); /* Initialise the context for long DFP */ decContextDefault(&set, DEC_INIT_DECIMAL64); ARCH_DEP(dfp_rounding_mode)(&set, 0, regs); /* Subtract FP register r3 from FP register r2 */ ARCH_DEP(dfp_reg_to_decimal64)(r2, &x2, regs); ARCH_DEP(dfp_reg_to_decimal64)(r3, &x3, regs); decimal64ToNumber(&x2, &d2); decimal64ToNumber(&x3, &d3); decNumberSubtract(&d1, &d2, &d3, &set); decimal64FromNumber(&x1, &d1, &set); /* Check for exception condition */ dxc = ARCH_DEP(dfp_status_check)(&set, regs); /* Load result into FP register r1 */ ARCH_DEP(dfp_reg_from_decimal64)(r1, &x1, regs); /* Set condition code */ regs->psw.cc = decNumberIsNaN(&d1) ? 3 : decNumberIsZero(&d1) ? 0 : decNumberIsNegative(&d1) ? 1 : 2; /* Raise data exception if error occurred */ if (dxc != 0) { regs->dxc = dxc; ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION); } } /* end DEF_INST(subtract_dfp_long_reg) */ /*-------------------------------------------------------------------*/ /* ED58 TDCXT - Test Data Class DFP Extended [RXE] */ /*-------------------------------------------------------------------*/ DEF_INST(test_data_class_dfp_ext) { int r1; /* Value of R field */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ decimal128 x1; /* Extended DFP value */ decNumber d1; /* Working decimal number */ decContext set; /* Working context */ U32 bits; /* Low 12 bits of address */ RXE(inst, regs, r1, b2, effective_addr2); DFPINST_CHECK(regs); DFPREGPAIR_CHECK(r1, regs); /* Initialise the context for extended DFP */ decContextDefault(&set, DEC_INIT_DECIMAL128); /* Convert FP register r1 to decimal number format */ ARCH_DEP(dfp_reg_to_decimal128)(r1, &x1, regs); decimal128ToNumber(&x1, &d1); /* Isolate rightmost 12 bits of second operand address */ bits = effective_addr2 & 0xFFF; /* Test data class and set condition code */ regs->psw.cc = dfp_test_data_class(&set, &d1, bits); } /* end DEF_INST(test_data_class_dfp_ext) */ /*-------------------------------------------------------------------*/ /* ED54 TDCDT - Test Data Class DFP Long [RXE] */ /*-------------------------------------------------------------------*/ DEF_INST(test_data_class_dfp_long) { int r1; /* Value of R field */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ decimal64 x1; /* Long DFP value */ decNumber d1; /* Working decimal number */ decContext set; /* Working context */ U32 bits; /* Low 12 bits of address */ RXE(inst, regs, r1, b2, effective_addr2); DFPINST_CHECK(regs); /* Initialise the context for long DFP */ decContextDefault(&set, DEC_INIT_DECIMAL64); /* Convert FP register r1 to decimal number format */ ARCH_DEP(dfp_reg_to_decimal64)(r1, &x1, regs); decimal64ToNumber(&x1, &d1); /* Isolate rightmost 12 bits of second operand address */ bits = effective_addr2 & 0xFFF; /* Test data class and set condition code */ regs->psw.cc = dfp_test_data_class(&set, &d1, bits); } /* end DEF_INST(test_data_class_dfp_long) */ /*-------------------------------------------------------------------*/ /* ED50 TDCET - Test Data Class DFP Short [RXE] */ /*-------------------------------------------------------------------*/ DEF_INST(test_data_class_dfp_short) { int r1; /* Value of R field */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ decimal32 x1; /* Short DFP value */ decNumber d1; /* Working decimal number */ decContext set; /* Working context */ U32 bits; /* Low 12 bits of address */ RXE(inst, regs, r1, b2, effective_addr2); DFPINST_CHECK(regs); /* Initialise the context for short DFP */ decContextDefault(&set, DEC_INIT_DECIMAL32); /* Convert FP register r1 to decimal number format */ ARCH_DEP(dfp_reg_to_decimal32)(r1, &x1, regs); decimal32ToNumber(&x1, &d1); /* Isolate rightmost 12 bits of second operand address */ bits = effective_addr2 & 0xFFF; /* Test data class and set condition code */ regs->psw.cc = dfp_test_data_class(&set, &d1, bits); } /* end DEF_INST(test_data_class_dfp_short) */ /*-------------------------------------------------------------------*/ /* ED59 TDGXT - Test Data Group DFP Extended [RXE] */ /*-------------------------------------------------------------------*/ DEF_INST(test_data_group_dfp_ext) { int r1; /* Value of R field */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ decimal128 x1; /* Extended DFP value */ decNumber d1; /* Working decimal number */ decContext set; /* Working context */ U32 bits; /* Low 12 bits of address */ int lmd; /* Leftmost digit */ RXE(inst, regs, r1, b2, effective_addr2); DFPINST_CHECK(regs); DFPREGPAIR_CHECK(r1, regs); /* Initialise the context for extended DFP */ decContextDefault(&set, DEC_INIT_DECIMAL128); /* Load DFP extended number from FP register r1 */ ARCH_DEP(dfp_reg_to_decimal128)(r1, &x1, regs); /* Extract the leftmost digit from FP register r1 */ lmd = dfp128_extract_lmd(&x1); /* Convert to internal decimal number format */ decimal128ToNumber(&x1, &d1); /* Isolate rightmost 12 bits of second operand address */ bits = effective_addr2 & 0xFFF; /* Test data group and set condition code */ regs->psw.cc = dfp_test_data_group(&set, &d1, lmd, bits); } /* end DEF_INST(test_data_group_dfp_ext) */ /*-------------------------------------------------------------------*/ /* ED55 TDGDT - Test Data Group DFP Long [RXE] */ /*-------------------------------------------------------------------*/ DEF_INST(test_data_group_dfp_long) { int r1; /* Value of R field */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ decimal64 x1; /* Long DFP value */ decNumber d1; /* Working decimal number */ decContext set; /* Working context */ U32 bits; /* Low 12 bits of address */ int lmd; /* Leftmost digit */ RXE(inst, regs, r1, b2, effective_addr2); DFPINST_CHECK(regs); /* Initialise the context for long DFP */ decContextDefault(&set, DEC_INIT_DECIMAL64); /* Load DFP long number from FP register r1 */ ARCH_DEP(dfp_reg_to_decimal64)(r1, &x1, regs); /* Extract the leftmost digit from FP register r1 */ lmd = dfp64_extract_lmd(&x1); /* Convert to internal decimal number format */ decimal64ToNumber(&x1, &d1); /* Isolate rightmost 12 bits of second operand address */ bits = effective_addr2 & 0xFFF; /* Test data group and set condition code */ regs->psw.cc = dfp_test_data_group(&set, &d1, lmd, bits); } /* end DEF_INST(test_data_group_dfp_long) */ /*-------------------------------------------------------------------*/ /* ED51 TDGET - Test Data Group DFP Short [RXE] */ /*-------------------------------------------------------------------*/ DEF_INST(test_data_group_dfp_short) { int r1; /* Value of R field */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ decimal32 x1; /* Short DFP value */ decNumber d1; /* Working decimal number */ decContext set; /* Working context */ U32 bits; /* Low 12 bits of address */ int lmd; /* Leftmost digit */ RXE(inst, regs, r1, b2, effective_addr2); DFPINST_CHECK(regs); /* Initialise the context for short DFP */ decContextDefault(&set, DEC_INIT_DECIMAL32); /* Load DFP short number from FP register r1 */ ARCH_DEP(dfp_reg_to_decimal32)(r1, &x1, regs); /* Extract the leftmost digit from FP register r1 */ lmd = dfp32_extract_lmd(&x1); /* Convert to internal decimal number format */ decimal32ToNumber(&x1, &d1); /* Isolate rightmost 12 bits of second operand address */ bits = effective_addr2 & 0xFFF; /* Test data group and set condition code */ regs->psw.cc = dfp_test_data_group(&set, &d1, lmd, bits); } /* end DEF_INST(test_data_group_dfp_short) */ #endif /*defined(FEATURE_DECIMAL_FLOATING_POINT)*/ #if !defined(_GEN_ARCH) #if defined(_ARCHMODE2) #define _GEN_ARCH _ARCHMODE2 #include "dfp.c" #endif #if defined(_ARCHMODE3) #undef _GEN_ARCH #define _GEN_ARCH _ARCHMODE3 #include "dfp.c" #endif #endif /*!defined(_GEN_ARCH)*/ /* end of dfp.c */ hercules-3.07/diagmssf.c000644 000765 000765 00000077375 11301535255 016727 0ustar00jmaynardjmaynard000000 000000 /* DIAGMSSF.C (c) Copyright Jan Jaeger, 1999-2009 */ /* ESA/390 Diagnose Functions */ // $Id: diagmssf.c 5427 2009-07-11 11:26:54Z ivan $ /*-------------------------------------------------------------------*/ /* This module implements various diagnose functions */ /* MSSF call as described in SA22-7098-0 */ /* SCPEND as described in GC19-6215-0 which is also used with PR/SM */ /* LPAR RMF interface call */ /* */ /* 04/12/1999 Jan Jaeger */ /* z/Architecture support - (c) Copyright Jan Jaeger, 1999-2009 */ /*-------------------------------------------------------------------*/ // $Log$ // Revision 1.47 2008/12/23 11:07:43 ivan // Indicate CPU engine types in DIAG 204 CPU part structure array // // Revision 1.46 2008/12/21 21:25:59 ivan // Fix spelling // // Revision 1.45 2008/12/21 05:46:47 ivan // Fill diag 224 table with all the engine names // // Revision 1.44 2008/11/24 14:52:21 jj // Add PTYP=IFL // Change SCPINFO processing to check on ptyp for IFL specifics // // Revision 1.43 2007/06/23 00:04:08 ivan // Update copyright notices to include current year (2007) // // Revision 1.42 2007/01/14 23:14:12 rbowler // Fix signed/unsigned mismatch in 370-only build // // Revision 1.41 2006/12/08 09:43:20 jj // Add CVS message log // #include "hstdinc.h" #if !defined(_HENGINE_DLL_) #define _HENGINE_DLL_ #endif #if !defined(_DIAGMSSF_C_) #define _DIAGMSSF_C_ #endif #include "hercules.h" #include "opcode.h" #include "inline.h" #include "service.h" #if !defined(_DIAGMSSF_C) #define _DIAGMSSF_C /*-------------------------------------------------------------------*/ /* MSSF Call service processor commands */ /*-------------------------------------------------------------------*/ #define MSSF_READ_CONFIG_INFO 0x00020001 #define MSSF_READ_CHP_STATUS 0x00030001 /*-------------------------------------------------------------------*/ /* Service Processor Command Control Block */ /*-------------------------------------------------------------------*/ typedef struct _SPCCB_HEADER { HWORD length; /* Total length of SPCCB */ BYTE resv1[4]; /* Reserved */ HWORD resp; /* Response code */ } SPCCB_HEADER; #define SPCCB_REAS_COMPLETE 0x00 #define SPCCB_RESP_COMPLETE 0x10 #define SPCCB_REAS_CHECK 0x00 #define SPCCB_RESP_CHECK 0x40 #define SPCCB_REAS_BADLENGTH 0x01 #define SPCCB_RESP_BADLENGTH 0xF0 #define SPCCB_REAS_NOT2KALIGN 0x01 #define SPCCB_RESP_NOT2KALIGN 0x00 #define SPCCB_REAS_UNASSIGNED 0x06 #define SPCCB_RESP_UNASSIGNED 0xF0 /*-------------------------------------------------------------------*/ /* Service Processor Command Control Block */ /*-------------------------------------------------------------------*/ typedef struct _SPCCB_CONFIG_INFO { BYTE totstori; /* Total number of installed storage increments. */ BYTE storisiz; /* Storage increment size in units of one megabyte. */ BYTE hex04; /* This field contains the value of 04 hex. */ BYTE hex01; /* This field contains the value of either 01 hex or 02 hex. */ FWORD reserved; /* Reserved. */ HWORD toticpu; /* Total number of installed CPUs. This number also specifies the total number of entries in the CPU- description list. */ HWORD officpu; /* Offset in the SPCCB to the first entry in the CPU- description list. */ HWORD tothsa; /* Total number of machine- storage areas reserved for the requesting configuration. This number also specifies the total number of entries in the machine-storage-area- description list. */ HWORD offhsa; /* Offset in the SPCCB to the first entry in the machine-storage-area- description list. */ BYTE loadparm[8]; /* Load parameter. This field conains eight bytes of EBCDIC information specified by the operator for the manually initiated load function. If the operator specifies fewer then eight characters, they are left- justified and padded on the right with 40 hex (preferred), or F0 hex, or 00 hex to form an eight byte load parameter. If the operator does not specify a load parameter, a default load parameter is formed, consisting of F1 hex (preferred), or 40 hex, or 00 hex, padded on the right with 40 hex (preferred), or F0 hex, of 00 hex. The load parameter is set to this default value by the activation of the system-reset-clear key or by performing certain operator functions. */ } SPCCB_CONFIG_INFO; typedef struct _SPCCB_CPU_INFO { BYTE cpuaddr; /* Rightmost eight bits of the CPU address */ BYTE todid; /* Identity of the TOD clock accessed by this CPU */ } SPCCB_CPU_INFO; typedef struct _SPCCB_HSA_INFO { BYTE hsasize; /* Bits 1-15 of this field specify the size of the area in units of 4K bytes or 32K bytes. When bit 0 of byte 0 is zero, the size is in units of 32K bytes; otherwise, the size is in units of 4K bytes. */ BYTE hsaaddr; /* Absolute address of the start of the machine- storage area. */ } SPCCB_HSA_INFO; typedef struct _SPCCB_CHP_STATUS { BYTE installed[32]; /* Installed-channel-path bit map. */ BYTE assigned[32]; /* Assigned-channel-path bit map. */ BYTE configured[32]; /* Configured-channel-path bit map. */ BYTE reserved[152]; /* Reserved. */ } SPCCB_CHP_STATUS; typedef struct _DIAG204_HDR { BYTE numpart; /* Number of partitions */ BYTE flags; /* Flag Byte */ #define DIAG204_PHYSICAL_PRESENT 0x80 HWORD resv; /* Unknown , 0 on 2003, 0x0005 under VM */ HWORD physcpu; /* Number of phys CP's */ HWORD offown; /* Offset to own partition */ DBLWRD diagstck; /* TOD of last diag204 */ } DIAG204_HDR; typedef struct _DIAG204_PART { BYTE partnum; /* Logical partition number starts with 1 */ BYTE virtcpu; /* Number of virt CP's */ HWORD resv1[3]; BYTE partname[8]; /* Partition name */ } DIAG204_PART; typedef struct _DIAG204_PART_CPU { HWORD cpaddr; /* CP address */ BYTE resv1[2]; BYTE index; /* Index into diag224 area */ BYTE cflag; /* ??? */ HWORD weight; /* Weight */ DBLWRD totdispatch; /* Total dispatch time */ DBLWRD effdispatch; /* Effective dispatch time */ } DIAG204_PART_CPU; typedef struct _DIAG204_X_HDR { BYTE numpart; /* Number of partitions */ BYTE flags; /* Flag Byte */ #define DIAG204_X_PHYSICAL_PRESENT 0x80 HWORD resv1; /* Unknown , 0 on 2003, 0x0005 under VM */ HWORD physcpu; /* Number of phys CP's */ HWORD offown; /* Offset to own partition */ DBLWRD diagstck1; /* TOD of last diag204 */ DBLWRD diagstck2; /* in STCKE format */ BYTE resv2[40]; } DIAG204_X_HDR; typedef struct _DIAG204_X_PART { BYTE partnum; /* Logical partition number starts with 1 */ BYTE virtcpu; /* Number of virt CP's */ BYTE realcpu; /* Number of real CP's */ BYTE pflag; FWORD mlu; BYTE partname[8]; /* Partition name */ BYTE cpcname[8]; /* CPC name */ BYTE osname[8]; /* Operating system type */ DBLWRD cssize; /* Central storage size */ DBLWRD essize; /* Expanded Storage size */ BYTE upid; BYTE resv1[3]; FWORD gr_mlu; BYTE gr_name[8]; /* Sysplex name? */ BYTE resv2[32]; } DIAG204_X_PART; typedef struct _DIAG204_X_PART_CPU { HWORD cpaddr; /* CP address */ BYTE resv1[2]; BYTE index; /* Index into diag224 area */ BYTE cflag; /* ??? */ HWORD weight; /* Weight */ DBLWRD totdispatch; /* Total dispatch time */ DBLWRD effdispatch; /* Effective dispatch time */ HWORD minweight; HWORD curweight; HWORD maxweight; BYTE resv2[2]; DBLWRD onlinetime; DBLWRD waittime; FWORD pmaweight; FWORD polarweight; BYTE resv3[40]; } DIAG204_X_PART_CPU; static const char diag224_cputable[]= { "CP " "ICF " "ZAAP " "IFL " "*UNKNOWN* " "ZIIP " }; #endif /*!defined(_DIAGMSSF_C)*/ /*-------------------------------------------------------------------*/ /* Process SCPEND call (Function code 0x044) */ /*-------------------------------------------------------------------*/ void ARCH_DEP(scpend_call) (void) { sched_yield(); /* Just go to the dispatcher for a minimum delay */ } /* end function scpend_call */ #ifdef FEATURE_MSSF_CALL /*-------------------------------------------------------------------*/ /* Process MSSF call (Function code 0x080) */ /*-------------------------------------------------------------------*/ int ARCH_DEP(mssf_call) (int r1, int r2, REGS *regs) { U32 spccb_absolute_addr; /* Absolute addr of SPCCB */ U32 mssf_command; /* MSSF command word */ U32 spccblen; /* Length of SPCCB */ SPCCB_HEADER *spccb; /* -> SPCCB header */ SPCCB_CONFIG_INFO *spccbconfig; /* -> SPCCB CONFIG info */ SPCCB_CPU_INFO *spccbcpu; /* -> SPCCB CPU information */ SPCCB_CHP_STATUS *spccbchp; /* -> SPCCB channel path info */ U16 offset; /* Offset from start of SPCCB */ int i; /* loop counter */ DEVBLK *dev; /* Device block pointer */ /* R1 contains the real address of the SPCCB */ spccb_absolute_addr = APPLY_PREFIXING (regs->GR_L(r1), regs->PX); /* R2 contains the service-processor-command word */ mssf_command = regs->GR_L(r2); /* Program check if SPCCB is not on a doubleword boundary */ if ( spccb_absolute_addr & 0x00000007 ) ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION); /* Program check if SPCCB is outside main storage */ if ( spccb_absolute_addr > regs->mainlim ) ARCH_DEP(program_interrupt) (regs, PGM_ADDRESSING_EXCEPTION); // /*debug*/logmsg("MSSF call %8.8X SPCCB=%8.8X\n", // /*debug*/ mssf_command, spccb_absolute_addr); /* Point to Service Processor Command Control Block */ spccb = (SPCCB_HEADER*)(regs->mainstor + spccb_absolute_addr); /* Load SPCCB length from header */ FETCH_HW(spccblen,spccb->length); /* Mark page referenced */ STORAGE_KEY(spccb_absolute_addr, regs) |= STORKEY_REF; /* Program check if end of SPCCB falls outside main storage */ if ( sysblk.mainsize - spccblen < spccb_absolute_addr ) ARCH_DEP(program_interrupt) (regs, PGM_ADDRESSING_EXCEPTION); /* Obtain the interrupt lock */ OBTAIN_INTLOCK(regs); /* If a service signal is pending then we cannot process the request */ if( IS_IC_SERVSIG && (sysblk.servparm & SERVSIG_ADDR)) { RELEASE_INTLOCK(regs); return 2; /* Service Processor Busy */ } if( spccb_absolute_addr & 0x7ffff800 ) { spccb->resp[0] = SPCCB_REAS_NOT2KALIGN; spccb->resp[1] = SPCCB_RESP_NOT2KALIGN; } else /* Test MSSF command word */ switch (mssf_command) { case MSSF_READ_CONFIG_INFO: /* Set response code X'01F0' if SPCCB length is insufficient to contain CONFIG info */ if ( spccblen < 64 ) { spccb->resp[0] = SPCCB_REAS_BADLENGTH; spccb->resp[1] = SPCCB_RESP_BADLENGTH; break; } /* Point to SPCCB data area following SPCCB header */ spccbconfig = (SPCCB_CONFIG_INFO*)(spccb+1); memset (spccbconfig, 0, sizeof(SPCCB_CONFIG_INFO)); /* Set main storage size in SPCCB */ spccbconfig->totstori = sysblk.mainsize >> 20; spccbconfig->storisiz = 1; spccbconfig->hex04 = 0x04; spccbconfig->hex01 = 0x01; /* Set CPU array count and offset in SPCCB */ STORE_HW(spccbconfig->toticpu,MAX_CPU); offset = sizeof(SPCCB_HEADER) + sizeof(SPCCB_CONFIG_INFO); STORE_HW(spccbconfig->officpu,offset); /* Set HSA array count and offset in SPCCB */ STORE_HW(spccbconfig->tothsa,0); offset += sizeof(SPCCB_CPU_INFO) * MAX_CPU; STORE_HW(spccbconfig->offhsa,offset); /* Move IPL load parameter to SPCCB */ get_loadparm (spccbconfig->loadparm); /* Build the CPU information array after the SCP info */ spccbcpu = (SPCCB_CPU_INFO*)(spccbconfig+1); for (i = 0; i < MAX_CPU; i++, spccbcpu++) { memset (spccbcpu, 0, sizeof(SPCCB_CPU_INFO)); spccbcpu->cpuaddr = i; spccbcpu->todid = 0; } /* Set response code X'0010' in SPCCB header */ spccb->resp[0] = SPCCB_REAS_COMPLETE; spccb->resp[1] = SPCCB_RESP_COMPLETE; break; case MSSF_READ_CHP_STATUS: /* Set response code X'0300' if SPCCB length is insufficient to contain channel path info */ if ( spccblen < sizeof(SPCCB_HEADER) + sizeof(SPCCB_CHP_STATUS)) { spccb->resp[0] = SPCCB_REAS_BADLENGTH; spccb->resp[1] = SPCCB_RESP_BADLENGTH; break; } /* Point to SPCCB data area following SPCCB header */ spccbchp = (SPCCB_CHP_STATUS*)(spccb+1); memset (spccbchp, 0, sizeof(SPCCB_CHP_STATUS)); /* Identify CHPIDs used */ for (dev = sysblk.firstdev; dev != NULL; dev = dev->nextdev) { spccbchp->installed[dev->devnum >> 11] |= 0x80 >> ((dev->devnum >> 8) & 7); spccbchp->assigned[dev->devnum >> 11] |= 0x80 >> ((dev->devnum >> 8) & 7); spccbchp->configured[dev->devnum >> 11] |= 0x80 >> ((dev->devnum >> 8) & 7); } /* Set response code X'0010' in SPCCB header */ spccb->resp[0] = SPCCB_REAS_COMPLETE; spccb->resp[1] = SPCCB_RESP_COMPLETE; break; default: PTT(PTT_CL_ERR,"*DIAG080",regs->GR_L(r1),regs->GR_L(r2),regs->psw.IA_L); /* Set response code X'06F0' for invalid MSSF command */ spccb->resp[0] = SPCCB_REAS_UNASSIGNED; spccb->resp[1] = SPCCB_RESP_UNASSIGNED; break; } /* end switch(mssf_command) */ /* Mark page changed */ STORAGE_KEY(spccb_absolute_addr, regs) |= STORKEY_CHANGE; /* Set service signal external interrupt pending */ sysblk.servparm &= ~SERVSIG_ADDR; sysblk.servparm |= spccb_absolute_addr; ON_IC_SERVSIG; /* Release the interrupt lock */ RELEASE_INTLOCK(regs); /* Return condition code 0: Command initiated */ return 0; } /* end function mssf_call */ #endif /* FEATURE_MSSF_CALL */ /*-------------------------------------------------------------------*/ /* Process LPAR DIAG 204 call */ /*-------------------------------------------------------------------*/ void ARCH_DEP(diag204_call) (int r1, int r2, REGS *regs) { DIAG204_HDR *hdrinfo; /* Header */ DIAG204_PART *partinfo; /* Partition info */ DIAG204_PART_CPU *cpuinfo; /* CPU info */ #if defined(FEATURE_EXTENDED_DIAG204) DIAG204_X_HDR *hdrxinfo; /* Header */ DIAG204_X_PART *partxinfo; /* Partition info */ DIAG204_X_PART_CPU *cpuxinfo; /* CPU info */ U64 tdis; #endif /*defined(FEATURE_EXTENDED_DIAG204)*/ RADR abs; /* abs addr of data area */ U64 dreg; /* work doubleword */ int i; /* loop counter */ struct rusage usage; /* RMF type data */ static U64 diag204tod; /* last diag204 tod */ #if defined(FEATURE_PHYSICAL_DIAG204) static BYTE physical[8] = {0xD7,0xC8,0xE8,0xE2,0xC9,0xC3,0xC1,0xD3}; /* PHYSICAL */ #endif /*defined(FEATURE_PHYSICAL_DIAG204)*/ /* Test DIAG204 command word */ switch (regs->GR_L(r2)) { case 0x04: abs = APPLY_PREFIXING (GR_A(r1,regs), regs->PX); /* Program check if RMF data is not on a page boundary */ if ( (abs & PAGEFRAME_BYTEMASK) != 0x000) ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION); /* Program check if RMF data area is outside main storage */ if ( abs > regs->mainlim ) ARCH_DEP(program_interrupt) (regs, PGM_ADDRESSING_EXCEPTION); /* Point to DIAG 204 data area */ hdrinfo = (DIAG204_HDR*)(regs->mainstor + abs); /* Mark page referenced */ STORAGE_KEY(abs, regs) |= STORKEY_REF | STORKEY_CHANGE; /* save last diag204 tod */ dreg = diag204tod; /* Retrieve the TOD clock value and shift out the epoch */ diag204tod = tod_clock(regs) << 8; memset(hdrinfo, 0, sizeof(DIAG204_HDR)); hdrinfo->numpart = 1; #if defined(FEATURE_PHYSICAL_DIAG204) hdrinfo->flags = DIAG204_PHYSICAL_PRESENT; #endif /*defined(FEATURE_PHYSICAL_DIAG204)*/ STORE_HW(hdrinfo->physcpu,sysblk.cpus); STORE_HW(hdrinfo->offown,sizeof(DIAG204_HDR)); STORE_DW(hdrinfo->diagstck,dreg); /* hercules partition */ partinfo = (DIAG204_PART*)(hdrinfo + 1); memset(partinfo, 0, sizeof(DIAG204_PART)); partinfo->partnum = 1; /* Hercules partition */ partinfo->virtcpu = sysblk.cpus; get_lparname(partinfo->partname); /* hercules cpu's */ getrusage(RUSAGE_SELF,&usage); cpuinfo = (DIAG204_PART_CPU*)(partinfo + 1); for(i = 0; i < MAX_CPU; i++) if (IS_CPU_ONLINE(i)) { memset(cpuinfo, 0, sizeof(DIAG204_PART_CPU)); STORE_HW(cpuinfo->cpaddr,sysblk.regs[i]->cpuad); cpuinfo->index=sysblk.ptyp[i]; STORE_HW(cpuinfo->weight,100); dreg = (U64)(usage.ru_utime.tv_sec + usage.ru_stime.tv_sec) * 1000000; dreg = (dreg + (usage.ru_utime.tv_usec + usage.ru_stime.tv_usec)) / sysblk.cpus; dreg <<= 12; STORE_DW(cpuinfo->totdispatch,dreg); dreg = (U64)(usage.ru_utime.tv_sec)* 1000000; dreg = (dreg + (usage.ru_utime.tv_usec)) / sysblk.cpus; dreg <<= 12; STORE_DW(cpuinfo->effdispatch,dreg); cpuinfo += 1; } #if defined(FEATURE_PHYSICAL_DIAG204) /* lpar management */ getrusage(RUSAGE_CHILDREN,&usage); partinfo = (DIAG204_PART*)cpuinfo; memset(partinfo, 0, sizeof(DIAG204_PART)); partinfo->partnum = 0; /* Physical machine */ partinfo->virtcpu = sysblk.cpus; memcpy(partinfo->partname,physical,sizeof(physical)); /* report all emulated physical cpu's */ getrusage(RUSAGE_SELF,&usage); cpuinfo = (DIAG204_PART_CPU*)(partinfo + 1); for(i = 0; i < MAX_CPU; i++) if (IS_CPU_ONLINE(i)) { memset(cpuinfo, 0, sizeof(DIAG204_PART_CPU)); STORE_HW(cpuinfo->cpaddr,sysblk.regs[i]->cpuad); cpuinfo->index = sysblk.ptyp[i]; STORE_HW(cpuinfo->weight,100); dreg = (U64)(usage.ru_utime.tv_sec + usage.ru_stime.tv_sec) * 1000000; dreg = (dreg + (usage.ru_utime.tv_usec + usage.ru_stime.tv_usec)) / sysblk.cpus; dreg <<= 12; STORE_DW(cpuinfo->totdispatch,dreg); dreg = (U64)(usage.ru_utime.tv_sec) * 1000000; dreg = (dreg + (usage.ru_utime.tv_usec)) / sysblk.cpus; dreg <<= 12; STORE_DW(cpuinfo->effdispatch,dreg); cpuinfo += 1; } #endif /*defined(FEATURE_PHYSICAL_DIAG204)*/ regs->GR_L(r2) = 0; break; #if defined(FEATURE_EXTENDED_DIAG204) /* Extended subcode 5 returns the size of the data areas provided by extended subcodes 6 and 7 */ case 0x00010005: i = sizeof(DIAG204_X_HDR) + ((sizeof(DIAG204_X_PART) + (MAX_CPU * sizeof(DIAG204_X_PART_CPU))) * 2); regs->GR_L(r2+1) = (i + PAGEFRAME_BYTEMASK) / PAGEFRAME_PAGESIZE; regs->GR_L(r2) = 0; break; /* Provide extended information */ case 0x00010006: /* We fall through as we do not have any secondary cpus (that we know of) */ /* Provide extended information, including information about secondary CPUs */ case 0x00010007: /* Program check if RMF data is not on a page boundary */ if ( (regs->GR_L(r1) & PAGEFRAME_BYTEMASK) != 0x000) ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION); /* Obtain absolute address of main storage block, check protection, and set reference and change bits */ hdrxinfo = (DIAG204_X_HDR*)MADDR (GR_A(r1,regs), r1, regs, ACCTYPE_WRITE, regs->psw.pkey); /* save last diag204 tod */ dreg = diag204tod; /* Retrieve the TOD clock value and shift out the epoch */ diag204tod = tod_clock(regs) << 8; memset(hdrxinfo, 0, sizeof(DIAG204_X_HDR)); hdrxinfo->numpart = 1; #if defined(FEATURE_PHYSICAL_DIAG204) hdrxinfo->flags = DIAG204_X_PHYSICAL_PRESENT; #endif /*defined(FEATURE_PHYSICAL_DIAG204)*/ STORE_HW(hdrxinfo->physcpu,sysblk.cpus); STORE_HW(hdrxinfo->offown,sizeof(DIAG204_X_HDR)); STORE_DW(hdrxinfo->diagstck1,(dreg >> 8)); STORE_DW(hdrxinfo->diagstck2,( 0x0000000001000000ULL | (regs->cpuad << 16) | regs->todpr)); /* hercules partition */ partxinfo = (DIAG204_X_PART*)(hdrxinfo + 1); memset(partxinfo, 0, sizeof(DIAG204_PART)); partxinfo->partnum = 1; /* Hercules partition */ partxinfo->virtcpu = sysblk.cpus; get_lparname(partxinfo->partname); get_sysname(partxinfo->cpcname); get_systype(partxinfo->osname); STORE_DW(partxinfo->cssize,sysblk.mainsize); STORE_DW(partxinfo->essize,sysblk.xpndsize); get_sysplex(partxinfo->gr_name); /* hercules cpu's */ getrusage(RUSAGE_SELF,&usage); cpuxinfo = (DIAG204_X_PART_CPU*)(partxinfo + 1); for(i = 0; i < MAX_CPU; i++) if (IS_CPU_ONLINE(i)) { memset(cpuxinfo, 0, sizeof(DIAG204_X_PART_CPU)); STORE_HW(cpuxinfo->cpaddr,sysblk.regs[i]->cpuad); cpuxinfo->index = sysblk.ptyp[i]; STORE_HW(cpuxinfo->weight,100); tdis = (U64)(usage.ru_utime.tv_sec + usage.ru_stime.tv_sec) * 1000000; tdis = (tdis + (usage.ru_utime.tv_usec + usage.ru_stime.tv_usec)) / sysblk.cpus; tdis <<= 12; STORE_DW(cpuxinfo->totdispatch,tdis); dreg = (U64)(usage.ru_utime.tv_sec)* 1000000; dreg = (dreg + (usage.ru_utime.tv_usec)) / sysblk.cpus; dreg <<= 12; STORE_DW(cpuxinfo->effdispatch,dreg); STORE_HW(cpuxinfo->minweight,1000); STORE_HW(cpuxinfo->curweight,1000); STORE_HW(cpuxinfo->maxweight,1000); STORE_DW(cpuxinfo->onlinetime, diag204tod - sysblk.todstart); STORE_DW(cpuxinfo->waittime, (diag204tod - sysblk.todstart) - tdis); STORE_HW(cpuxinfo->pmaweight,1000); STORE_HW(cpuxinfo->polarweight,1000); cpuxinfo += 1; } #if defined(FEATURE_PHYSICAL_DIAG204) /* lpar management */ partxinfo = (DIAG204_X_PART*)cpuxinfo; memset(partxinfo, 0, sizeof(DIAG204_X_PART)); partxinfo->partnum = 0; /* Physical machine */ partxinfo->virtcpu = sysblk.cpus; memcpy(partxinfo->partname,physical,sizeof(physical)); /* report all emulated physical cpu's */ getrusage(RUSAGE_CHILDREN,&usage); cpuxinfo = (DIAG204_PART_CPU*)(partinfo + 1); for(i = 0; i < MAX_CPU; i++) if (IS_CPU_ONLINE(i)) { memset(cpuxinfo, 0, sizeof(DIAG204_X_PART_CPU)); STORE_HW(cpuxinfo->cpaddr,sysblk.regs[i]->cpuad); cpuxinfo->index = sysblk.ptyp[i]; STORE_HW(cpuxinfo->weight,100); tdis = (U64)(usage.ru_utime.tv_sec + usage.ru_stime.tv_sec) * 1000000; tdis = (tdis + (usage.ru_utime.tv_usec + usage.ru_stime.tv_usec)) / sysblk.cpus; tdis <<= 12; STORE_DW(cpuxinfo->totdispatch,tdis); dreg = (U64)(usage.ru_utime.tv_sec)* 1000000; dreg = (dreg + (usage.ru_utime.tv_usec)) / sysblk.cpus; dreg <<= 12; STORE_DW(cpuxinfo->effdispatch,dreg); STORE_HW(cpuxinfo->minweight,1000); STORE_HW(cpuxinfo->curweight,1000); STORE_HW(cpuxinfo->maxweight,1000); STORE_DW(cpuxinfo->onlinetime, diag204tod - sysblk.todstart); STORE_DW(cpuxinfo->waittime, (diag204tod - sysblk.todstart) - tdis); STORE_HW(cpuxinfo->pmaweight,1000); STORE_HW(cpuxinfo->polarweight,1000); cpuxinfo += 1; } #endif /*defined(FEATURE_PHYSICAL_DIAG204)*/ regs->GR_L(r2) = 0; break; #endif /*defined(FEATURE_EXTENDED_DIAG204)*/ default: PTT(PTT_CL_ERR,"*DIAG204",regs->GR_L(r1),regs->GR_L(r2),regs->psw.IA_L); regs->GR_L(r2) = 4; } /*switch(regs->GR_L(r2))*/ } /* end function diag204_call */ /*-------------------------------------------------------------------*/ /* Process LPAR DIAG 224 call */ /*-------------------------------------------------------------------*/ void ARCH_DEP(diag224_call) (int r1, int r2, REGS *regs) { RADR abs; /* abs addr of data area */ BYTE *p; /* pointer to the data area */ unsigned int i; /* loop index */ //FIXME : this is probably incomplete. // see linux/arch/s390/hypfs/hypfs_diag.c UNREFERENCED(r1); abs = APPLY_PREFIXING (regs->GR_L(r2), regs->PX); /* Program check if data area is not on a page boundary */ if ( (abs & PAGEFRAME_BYTEMASK) != 0x000) ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION); /* Program check if data area is outside main storage */ if ( abs > regs->mainlim ) ARCH_DEP(program_interrupt) (regs, PGM_ADDRESSING_EXCEPTION); /* Point to DIAG 224 data area */ p = regs->mainstor + abs; /* Mark page referenced */ STORAGE_KEY(abs, regs) |= STORKEY_REF | STORKEY_CHANGE; /* First byte contains the number of entries - 1 */ *p = 5; /* Clear the next 15 bytes */ memset (p + 1, 0, 15); /* Set the 6 possible entries */ p += 16; memcpy(p,diag224_cputable,sizeof(diag224_cputable)-1); /* Convert to EBCDIC */ for (i = 0; i < sizeof(diag224_cputable); i++) p[i] = host_to_guest(p[i]); } /* end function diag224_call */ #if !defined(_GEN_ARCH) #if defined(_ARCHMODE2) #define _GEN_ARCH _ARCHMODE2 #include "diagmssf.c" #endif #if defined(_ARCHMODE3) #undef _GEN_ARCH #define _GEN_ARCH _ARCHMODE3 #include "diagmssf.c" #endif #endif /*!defined(_GEN_ARCH)*/ hercules-3.07/diagnose.c000644 000765 000765 00000060531 11321734033 016702 0ustar00jmaynardjmaynard000000 000000 /* DIAGNOSE.C (c) Copyright Roger Bowler, 2000-2009 */ /* ESA/390 Diagnose Functions */ // $Id: diagnose.c 5548 2009-12-15 15:50:44Z rbowler $ /*-------------------------------------------------------------------*/ /* This module implements miscellaneous diagnose functions */ /*-------------------------------------------------------------------*/ /*-------------------------------------------------------------------*/ /* Additional credits: */ /* Hercules-specific diagnose calls by Jay Maynard. */ /* Set/reset bad frame indicator call by Jan Jaeger. */ /* z/Architecture support - (c) Copyright Jan Jaeger, 1999-2009 */ /*-------------------------------------------------------------------*/ #include "hstdinc.h" #if !defined(_HENGINE_DLL_) #define _HENGINE_DLL_ #endif #if !defined(_DIAGNOSE_C_) #define _DIAGNOSE_C_ #endif #include "hercules.h" #include "opcode.h" #include "inline.h" #if !defined(_DIAGNOSE_H) #define _DIAGNOSE_H /*-------------------------------------------------------------------*/ /* Internal macro definitions */ /*-------------------------------------------------------------------*/ /* Diagnose 308 function subcodes */ #define DIAG308_IPL_CLEAR 3 /* IPL clear */ #define DIAG308_IPL_NORMAL 4 /* IPL normal/dump */ #define DIAG308_SET_PARAM 5 /* Set IPL parameters */ #define DIAG308_STORE_PARAM 6 /* Store IPL parameters */ /* Diagnose 308 return codes */ #define DIAG308_RC_OK 1 #endif /*!defined(_DIAGNOSE_H)*/ #if defined(OPTION_DYNAMIC_LOAD) && defined(FEATURE_HERCULES_DIAGCALLS) void ARCH_DEP(diagf14_call)(int r1, int r3, REGS *regs) { char name[32+1]; char entry[64]; unsigned int i; void (*dllcall)(int, int, REGS *); static char *prefix[] = { #if defined(_370) "s370_diagf14_", #endif #if defined(_390) "s390_diagf14_", #endif #if defined(_900) "z900_diagf14_" #endif }; ARCH_DEP(vfetchc) (name,sizeof(name)-2, regs->GR(r1), USE_REAL_ADDR, regs); for(i = 0; i < sizeof(name)-1; i++) { name[i] = guest_to_host(name[i]); if(!isprint(name[i]) || isspace(name[i])) { name[i] = '\0'; break; } } /* Ensure string terminator */ name[i] = '\0'; strcpy(entry,prefix[regs->arch_mode]); strcat(entry,name); if( (dllcall = HDL_FINDSYM(entry)) ) dllcall(r1, r3, regs); else ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION); } #endif /*defined(OPTION_DYNAMIC_LOAD)*/ #if defined(FEATURE_PROGRAM_DIRECTED_REIPL) && !defined(STOP_CPUS_AND_IPL) #define STOP_CPUS_AND_IPL /*---------------------------------------------------------------------------*/ /* Within diagnose 0x308 (re-ipl) a thread is started with the next code. */ /*---------------------------------------------------------------------------*/ void *stop_cpus_and_ipl(int *ipltype) { int i; char iplcmd[256]; int cpustates; CPU_BITMAP mask; panel_command("stopall"); logmsg("HHCDN001I Diagnose 0x308 called: System is re-ipled\n"); sprintf(iplcmd, "%s %03X", ipltype, sysblk.ipldev); do { OBTAIN_INTLOCK(NULL); cpustates = CPUSTATE_STOPPED; mask = sysblk.started_mask; for(i = 0; mask; i++) { if(mask & 1) { logmsg("HHCDN002I Checking cpu %d\n", i); if(IS_CPU_ONLINE(i) && sysblk.regs[i]->cpustate != CPUSTATE_STOPPED) cpustates = sysblk.regs[i]->cpustate; } mask >>= 1; } RELEASE_INTLOCK(NULL); if(cpustates != CPUSTATE_STOPPED) { logmsg("HHCDN003I Waiting 1 second for cpu's to stop...\n"); SLEEP(1); } } while(cpustates != CPUSTATE_STOPPED); panel_command(iplcmd); return NULL; } #endif /*defined(FEATURE_PROGRAM_DIRECTED_REIPL) && !defined(STOP_CPUS_AND_IPL)*/ /*-------------------------------------------------------------------*/ /* Diagnose instruction */ /*-------------------------------------------------------------------*/ void ARCH_DEP(diagnose_call) (VADR effective_addr2, int b2, int r1, int r2, REGS *regs) { #ifdef FEATURE_HERCULES_DIAGCALLS U32 n; /* 32-bit operand value */ #endif /*FEATURE_HERCULES_DIAGCALLS*/ U32 code; code = effective_addr2; switch(code) { #if defined(FEATURE_IO_ASSIST) case 0x002: /*---------------------------------------------------------------*/ /* Diagnose 002: Update Interrupt Interlock Control Bit in PMCW */ /*---------------------------------------------------------------*/ ARCH_DEP(diagnose_002) (regs, r1, r2); break; #endif case 0x01F: /*---------------------------------------------------------------*/ /* Diagnose 01F: Power Off */ /*---------------------------------------------------------------*/ /* If diag8cmd is not enabled then we are not allowed * to manipulate the real machine i.e. hercules itself */ if(!(sysblk.diag8cmd & DIAG8CMD_ENABLE)) ARCH_DEP(program_interrupt)(regs, PGM_SPECIFICATION_EXCEPTION); /* The poweroff diagnose is only valid on the 9221 */ if(((sysblk.cpuid >> 16 & 0xFFFF) != 0x9221 ) /* and r1/r2 must contain C'POWEROFF' in EBCDIC */ || regs->GR_L(r1) != 0xD7D6E6C5 || regs->GR_L(r2) != 0xD9D6C6C6) ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION); regs->cpustate = CPUSTATE_STOPPING; ON_IC_INTERRUPT(regs); /* Release the configuration */ do_shutdown(); /* Power Off: exit hercules */ exit(0); break; #if defined(FEATURE_HYPERVISOR) || defined(FEATURE_EMULATE_VM) case 0x044: /*---------------------------------------------------------------*/ /* Diagnose 044: Voluntary Time Slice End */ /*---------------------------------------------------------------*/ ARCH_DEP(scpend_call) (); break; #endif #ifdef FEATURE_MSSF_CALL case 0x080: /*---------------------------------------------------------------*/ /* Diagnose 080: MSSF Call */ /*---------------------------------------------------------------*/ regs->psw.cc = ARCH_DEP(mssf_call) (r1, r2, regs); break; #endif /*FEATURE_MSSF_CALL*/ #if defined(FEATURE_HYPERVISOR) || defined(FEATURE_EMULATE_VM) case 0x09C: /*---------------------------------------------------------------*/ /* Diagnose 09C: Voluntary Time Slice End With Target CPU */ /*---------------------------------------------------------------*/ ARCH_DEP(scpend_call) (); // (treat same as DIAG X'44') break; #endif #if defined(FEATURE_HYPERVISOR) case 0x204: /*---------------------------------------------------------------*/ /* Diagnose 204: LPAR RMF Interface */ /*---------------------------------------------------------------*/ ARCH_DEP(diag204_call) (r1, r2, regs); regs->psw.cc = 0; break; case 0x224: /*---------------------------------------------------------------*/ /* Diagnose 224: CPU Names */ /*---------------------------------------------------------------*/ ARCH_DEP(diag224_call) (r1, r2, regs); regs->psw.cc = 0; break; #endif /*defined(FEATURE_HYPERVISOR)*/ #if 0 case 0x21C: /*---------------------------------------------------------------*/ /* Diagnose 21C: ???? */ /*---------------------------------------------------------------*/ /*INCOMPLETE*/ regs->psw.cc = 0; break; #endif #ifdef FEATURE_EMULATE_VM case 0x000: /*---------------------------------------------------------------*/ /* Diagnose 000: Store Extended Identification Code */ /*---------------------------------------------------------------*/ ARCH_DEP(extid_call) (r1, r2, regs); break; case 0x008: /*---------------------------------------------------------------*/ /* Diagnose 008: Virtual Console Function */ /*---------------------------------------------------------------*/ /* If diag8cmd is not enabled then we are not allowed * to manipulate the real machine i.e. hercules itself */ if(!(sysblk.diag8cmd & DIAG8CMD_ENABLE)) ARCH_DEP(program_interrupt)(regs, PGM_SPECIFICATION_EXCEPTION); /* Process CP command and set condition code */ regs->psw.cc = ARCH_DEP(cpcmd_call) (r1, r2, regs); break; case 0x00C: /*---------------------------------------------------------------*/ /* Diagnose 00C: Pseudo Timer */ /*---------------------------------------------------------------*/ ARCH_DEP(pseudo_timer) (code, r1, r2, regs); break; case 0x024: /*---------------------------------------------------------------*/ /* Diagnose 024: Device Type and Features */ /*---------------------------------------------------------------*/ regs->psw.cc = ARCH_DEP(diag_devtype) (r1, r2, regs); break; case 0x05C: /*---------------------------------------------------------------*/ /* Diagnose 05C: Error Message Editing */ /*---------------------------------------------------------------*/ /* This function is implemented as a no-operation */ regs->psw.cc = 0; break; case 0x060: /*---------------------------------------------------------------*/ /* Diagnose 060: Virtual Machine Storage Size */ /*---------------------------------------------------------------*/ /* Load main storage size in bytes into R1 register */ regs->GR_L(r1) = sysblk.mainsize; break; case 0x064: /*---------------------------------------------------------------*/ /* Diagnose 064: Named Saved Segment Manipulation */ /*---------------------------------------------------------------*/ /* Return code 44 cond code 2 means segment does not exist */ regs->GR_L(r2) = 44; regs->psw.cc = 2; break; case 0x0A4: /*---------------------------------------------------------------*/ /* Diagnose 0A4: Synchronous I/O (Standard CMS Blocksize) */ /*---------------------------------------------------------------*/ regs->psw.cc = ARCH_DEP(syncblk_io) (r1, r2, regs); // logmsg ("Diagnose X\'0A4\': CC=%d, R15=%8.8X\n", /*debug*/ // regs->psw.cc, regs->GR_L(15)); /*debug*/ break; case 0x0A8: /*---------------------------------------------------------------*/ /* Diagnose 0A8: Synchronous General I/O */ /*---------------------------------------------------------------*/ regs->psw.cc = ARCH_DEP(syncgen_io) (r1, r2, regs); // logmsg ("Diagnose X\'0A8\': CC=%d, R15=%8.8X\n", /*debug*/ // regs->psw.cc, regs->GR_L(15)); /*debug*/ break; case 0x0B0: /*---------------------------------------------------------------*/ /* Diagnose 0B0: Access Re-IPL Data */ /*---------------------------------------------------------------*/ ARCH_DEP(access_reipl_data) (r1, r2, regs); break; case 0x0DC: /*---------------------------------------------------------------*/ /* Diagnose 0DC: Control Application Monitor Record Collection */ /*---------------------------------------------------------------*/ /* This function is implemented as a no-operation */ regs->GR_L(r2) = 0; regs->psw.cc = 0; break; case 0x210: /*---------------------------------------------------------------*/ /* Diagnose 210: Retrieve Device Information */ /*---------------------------------------------------------------*/ regs->psw.cc = ARCH_DEP(device_info) (r1, r2, regs); break; case 0x214: /*---------------------------------------------------------------*/ /* Diagnose 214: Pending Page Release */ /*---------------------------------------------------------------*/ regs->psw.cc = ARCH_DEP(diag_ppagerel) (r1, r2, regs); break; case 0x220: /*---------------------------------------------------------------*/ /* Diagnose 220: TOD Epoch */ /*---------------------------------------------------------------*/ ODD_CHECK(r2, regs); switch(regs->GR_L(r1)) { case 0: /* Obtain TOD features */ regs->GR_L(r2) =0xc0000000; regs->GR_L(r2+1)=0x00000000; break; case 1: /* Obtain TOD offset to real TOD in R2, R2+1 */ regs->GR_L(r2) = (regs->tod_epoch >> 24) & 0xFFFFFFFF; regs->GR_L(r2+1)= (regs->tod_epoch << 8) & 0xFFFFFFFF; break; default: ARCH_DEP(program_interrupt)(regs, PGM_SPECIFICATION_EXCEPTION); } break; case 0x23C: /*---------------------------------------------------------------*/ /* Diagnose 23C: Address Space Services */ /*---------------------------------------------------------------*/ /* This function is implemented as a no-operation */ regs->GR_L(r2) = 0; break; #if defined(FEATURE_VM_BLOCKIO) case 0x250: /*---------------------------------------------------------------*/ /* Diagnose 250: Standardized Block I/O */ /*---------------------------------------------------------------*/ regs->psw.cc = ARCH_DEP(vm_blockio) (r1, r2, regs); break; #endif /*defined(FEATURE_VM_BLOCKIO)*/ case 0x260: /*---------------------------------------------------------------*/ /* Diagnose 260: Access Certain Virtual Machine Information */ /*---------------------------------------------------------------*/ ARCH_DEP(vm_info) (r1, r2, regs); break; case 0x264: /*---------------------------------------------------------------*/ /* Diagnose 264: CP Communication */ /*---------------------------------------------------------------*/ /* This function is implemented as a no-operation */ PTT(PTT_CL_ERR,"*DIAG264",regs->GR_L(r1),regs->GR_L(r2),regs->psw.IA_L); regs->psw.cc = 0; break; case 0x270: /*---------------------------------------------------------------*/ /* Diagnose 270: Pseudo Timer Extended */ /*---------------------------------------------------------------*/ ARCH_DEP(pseudo_timer) (code, r1, r2, regs); break; case 0x274: /*---------------------------------------------------------------*/ /* Diagnose 274: Set Timezone Interrupt Flag */ /*---------------------------------------------------------------*/ /* This function is implemented as a no-operation */ PTT(PTT_CL_ERR,"*DIAG274",regs->GR_L(r1),regs->GR_L(r2),regs->psw.IA_L); regs->psw.cc = 0; break; #endif /*FEATURE_EMULATE_VM*/ #ifdef FEATURE_HERCULES_DIAGCALLS case 0xF00: /*---------------------------------------------------------------*/ /* Diagnose F00: Hercules normal mode */ /*---------------------------------------------------------------*/ /* If diag8cmd is not enabled then we are not allowed * to manipulate the real machine i.e. hercules itself */ if(!(sysblk.diag8cmd & DIAG8CMD_ENABLE)) ARCH_DEP(program_interrupt)(regs, PGM_SPECIFICATION_EXCEPTION); sysblk.inststep = 0; SET_IC_TRACE; break; case 0xF04: /*---------------------------------------------------------------*/ /* Diagnose F04: Hercules single step mode */ /*---------------------------------------------------------------*/ /* If diag8cmd is not enabled then we are not allowed * to manipulate the real machine i.e. hercules itself */ if(!(sysblk.diag8cmd & DIAG8CMD_ENABLE)) ARCH_DEP(program_interrupt)(regs, PGM_SPECIFICATION_EXCEPTION); sysblk.inststep = 1; SET_IC_TRACE; break; case 0xF08: /*---------------------------------------------------------------*/ /* Diagnose F08: Hercules get instruction counter */ /*---------------------------------------------------------------*/ regs->GR_L(r1) = (U32)INSTCOUNT(regs); break; case 0xF0C: /*---------------------------------------------------------------*/ /* Diagnose F0C: Set/reset bad frame indicator */ /*---------------------------------------------------------------*/ /* If diag8cmd is not enabled then we are not allowed * to manipulate the real machine i.e. hercules itself */ if(!(sysblk.diag8cmd & DIAG8CMD_ENABLE)) ARCH_DEP(program_interrupt)(regs, PGM_SPECIFICATION_EXCEPTION); /* Load 4K block address from R2 register */ n = regs->GR_L(r2) & ADDRESS_MAXWRAP(regs); /* Convert real address to absolute address */ n = APPLY_PREFIXING (n, regs->PX); /* Addressing exception if block is outside main storage */ if ( n > regs->mainlim ) { ARCH_DEP(program_interrupt) (regs, PGM_ADDRESSING_EXCEPTION); break; } /* Update the storage key from R1 register bit 31 */ STORAGE_KEY(n, regs) &= ~(STORKEY_BADFRM); STORAGE_KEY(n, regs) |= regs->GR_L(r1) & STORKEY_BADFRM; break; case 0xF10: /*---------------------------------------------------------------*/ /* Diagnose F10: Hercules CPU stop */ /*---------------------------------------------------------------*/ /* If diag8cmd is not enabled then we are not allowed * to manipulate the real machine i.e. hercules itself */ if(!(sysblk.diag8cmd & DIAG8CMD_ENABLE)) ARCH_DEP(program_interrupt)(regs, PGM_SPECIFICATION_EXCEPTION); regs->cpustate = CPUSTATE_STOPPING; ON_IC_INTERRUPT(regs); break; #if defined(OPTION_DYNAMIC_LOAD) case 0xF14: /*---------------------------------------------------------------*/ /* Diagnose F14: Hercules DLL interface */ /*---------------------------------------------------------------*/ ARCH_DEP(diagf14_call) (r1, r2, regs); break; #endif /*defined(OPTION_DYNAMIC_LOAD)*/ #if !defined(NO_SIGABEND_HANDLER) /* The following diagnose calls cause a exigent (non-repressible) machine check, and are used for test purposes only *JJ */ case 0xFE8: /*---------------------------------------------------------------*/ /* Diagnose FE8: Simulate Illegal Instruction */ /*---------------------------------------------------------------*/ raise(SIGILL); break; case 0xFEC: /*---------------------------------------------------------------*/ /* Diagnose FEC: Simulate Floating Point Exception */ /*---------------------------------------------------------------*/ raise(SIGFPE); break; case 0xFF0: /*---------------------------------------------------------------*/ /* Diagnose FF0: Simulate Segment Violation */ /*---------------------------------------------------------------*/ raise(SIGSEGV); break; case 0xFF4: /*---------------------------------------------------------------*/ /* Diagnose FF4: Simulate BUS Error */ /*---------------------------------------------------------------*/ raise(SIGBUS); break; case 0xFF8: /*---------------------------------------------------------------*/ /* Diagnose FF8: Simulate Loop */ /*---------------------------------------------------------------*/ while(1); break; case 0xFFC: /*---------------------------------------------------------------*/ /* Diagnose FFC: Simulate Wait */ /*---------------------------------------------------------------*/ SLEEP(300); break; #endif /*!defined(NO_SIGABEND_HANDLER)*/ #endif /*FEATURE_HERCULES_DIAGCALLS*/ case 0x308: /*---------------------------------------------------------------*/ /* Diagnose 308: IPL functions */ /*---------------------------------------------------------------*/ switch(r2) { #ifdef FEATURE_PROGRAM_DIRECTED_REIPL TID tid; /* Thread identifier */ char *ipltype; /* "ipl" or "iplc" */ case DIAG308_IPL_CLEAR: ipltype = "iplc"; goto diag308_cthread; case DIAG308_IPL_NORMAL: ipltype = "ipl"; diag308_cthread: if(create_thread(&tid, DETACHED, stop_cpus_and_ipl, ipltype, "Stop cpus and ipl")) logmsg("HHCDN004E Error starting thread in diagnose 0x308: %s\n", strerror(errno)); regs->cpustate = CPUSTATE_STOPPING; ON_IC_INTERRUPT(regs); break; case DIAG308_SET_PARAM: /* INCOMPLETE */ regs->GR(1) = DIAG308_RC_OK; break; case DIAG308_STORE_PARAM: /* INCOMPLETE */ regs->GR(1) = DIAG308_RC_OK; break; #endif /*FEATURE_PROGRAM_DIRECTED_REIPL*/ default: ARCH_DEP(program_interrupt)(regs, PGM_SPECIFICATION_EXCEPTION); } /* end switch(r2) */ break; default: /*---------------------------------------------------------------*/ /* Diagnose xxx: Invalid function code */ /*---------------------------------------------------------------*/ if( HDC4(debug_diagnose, code, r1, r2, regs) ) return; /* Power Off diagnose on 4361, 9371, 9373, 9375, 9377, 9221: */ /* */ /* DS 0H */ /* DC X'8302',S(SHUTDATA) MUST BE R0 AND R2 */ /* ... */ /* DS 0H */ /* SHUTDATA DC X'0000FFFF' MUST BE X'0000FFFF' */ if (0 == r1 && 2 == r2 && (sysblk.cpuid >> 56 & 0xFF) != 0xFF && ((sysblk.cpuid >> 16 & 0xFFFF) == 0x4361 || (sysblk.cpuid >> 16 & 0xFFF9) == 0x9371 /* (937X) */ || (sysblk.cpuid >> 16 & 0xFFFF) == 0x9221) ) { if (0x0000FFFF == ARCH_DEP(vfetch4)(effective_addr2, b2, regs)) { /* If diag8cmd is not enabled then we are not allowed * to manipulate the real machine i.e. hercules itself */ if(!(sysblk.diag8cmd & DIAG8CMD_ENABLE)) ARCH_DEP(program_interrupt)(regs, PGM_SPECIFICATION_EXCEPTION); regs->cpustate = CPUSTATE_STOPPING; ON_IC_INTERRUPT(regs); /* Release the configuration */ do_shutdown(); /* Power Off: exit hercules */ exit(0); } } #if defined(FEATURE_S370_CHANNEL) && defined(OPTION_NOP_MODEL158_DIAGNOSE) if((sysblk.cpuid >> 16 & 0xFFFF) != 0x0158) #endif ARCH_DEP(program_interrupt)(regs, PGM_SPECIFICATION_EXCEPTION); return; } /* end switch(code) */ return; } /* end function diagnose_call */ #if !defined(_GEN_ARCH) #if defined(_ARCHMODE2) #define _GEN_ARCH _ARCHMODE2 #include "diagnose.c" #endif #if defined(_ARCHMODE3) #undef _GEN_ARCH #define _GEN_ARCH _ARCHMODE3 #include "diagnose.c" #endif #endif /*!defined(_GEN_ARCH)*/ hercules-3.07/dmap2hrc.c000644 000765 000765 00000017641 11143760543 016624 0ustar00jmaynardjmaynard000000 000000 /* DMAP2HRC.C (c) Copyright Jay Maynard, 2001-2009 */ /* Convert P/390 DEVMAP to Hercules config file */ // $Id: dmap2hrc.c 5125 2009-01-23 12:01:44Z bernard $ /*-------------------------------------------------------------------*/ /* This program reads a P/390 DEVMAP file and extracts the device */ /* definitions from it, then writes them to the standard output in */ /* the format Hercules uses for its .cnf file. */ /*-------------------------------------------------------------------*/ // $Log$ // Revision 1.21 2008/11/04 04:50:46 fish // Ensure consistent utility startup // // Revision 1.20 2007/06/23 00:04:08 ivan // Update copyright notices to include current year (2007) // // Revision 1.19 2006/12/08 09:43:20 jj // Add CVS message log // #include "hstdinc.h" #include "hercules.h" /*-------------------------------------------------------------------*/ /* Structure definition for DEVMAP controller record */ /*-------------------------------------------------------------------*/ typedef struct _DEVMAP_CTLR { BYTE channel; /* High order dev addr byte */ BYTE name[8]; /* Name of controller program*/ BYTE lowdev; /* Low addr byte first dev */ BYTE highdev; /* Low addr byte last dev */ BYTE filler1; /* Fill byte */ BYTE type[4]; /* Type of controller */ BYTE flags; /* Flag byte */ BYTE filler2[47]; /* More filler bytes */ } DEVMAP_CTLR; /*-------------------------------------------------------------------*/ /* Structure definition for DEVMAP device record */ /*-------------------------------------------------------------------*/ typedef struct _DEVMAP_DEV { BYTE highaddr; /* High order dev addr byte */ BYTE lowaddr; /* Low order dev addr byte */ char type[4]; /* Type of device */ union { struct { /* Disk devices: */ BYTE filler1[4]; /* filler */ BYTE volser[6]; /* Volume serial */ BYTE filler2[2]; /* more filler */ char filename[45]; /* name of file on disk */ BYTE flags; /* flag byte */ } disk; struct { /* Other devices: */ BYTE filler1[7]; /* fill bytes */ char filename[50]; /* device filename */ BYTE flags; /* flag byte */ } other; } parms; } DEVMAP_DEV; /*-------------------------------------------------------------------*/ /* DEVMAP2CNF main entry point */ /*-------------------------------------------------------------------*/ int main (int argc, char *argv[]) { int i; /* Array subscript */ int len; /* Length of actual read */ char *filename; /* -> Input file name */ int infd = -1; /* Input file descriptor */ DEVMAP_CTLR controller; /* Controller record */ DEVMAP_DEV device; /* Device record */ char output_type[5]; /* Device type to print */ char *output_filename; /* -> filename to print */ int more_devices; /* More devices this ctlr? */ char pathname[MAX_PATH]; /* file path in host format */ INITIALIZE_UTILITY("dmap2hrc"); /* Display the program identification message */ display_version (stderr, "P/390 DEVMAP to Hercules conversion program\n", FALSE); /* The only argument is the DEVMAP file name */ if (argc == 2 && argv[1] != NULL) { filename = argv[1]; } else { fprintf (stderr,"Usage: dmap2hrc filename\n"); exit (1); } /* Open the devmap file */ hostpath(pathname, filename, sizeof(pathname)); infd = open (pathname, O_RDONLY | O_BINARY); if (infd < 0) { fprintf (stderr,"dmap2hrc: Error opening %s: %s\n", filename, strerror(errno)); exit (2); } /* Skip the file header */ for (i = 0; i < 9; i++) { len = read (infd, (void *)&controller, sizeof(DEVMAP_CTLR)); if (len < 0) { fprintf (stderr, "dmap2hrc: error reading header records from %s: %s\n", filename, strerror(errno)); exit (3); } } /* Read records from the input file and convert them */ while (1) { /* Read a controller record. */ len = read (infd, (void *)&controller, sizeof(DEVMAP_CTLR)); if (len < 0) { fprintf (stderr, "dmap2hrc: error reading controller record from %s:" " %s\n", filename, strerror(errno)); exit (4); } /* Did we finish too soon? */ if ((len > 0) && (len < (int)sizeof(DEVMAP_CTLR))) { fprintf (stderr, "dmap2hrc: incomplete controller record on %s\n", filename); exit(5); } /* Check for end of file. */ if (len == 0) { fprintf(stderr, "End of input file.\n"); break; } /* Read devices on this controller. */ more_devices = 1; while (more_devices) { /* Read a device record. */ len = read (infd, (void *)&device, sizeof(DEVMAP_DEV)); if (len < 0) { fprintf (stderr, "dmap2hrc: error reading device record from %s:" " %s\n", filename, strerror(errno)); exit (6); } /* Did we finish too soon? */ if ((len > 0) && (len < (int)sizeof(DEVMAP_DEV))) { fprintf (stderr, "dmap2hrc: incomplete device record on %s\n", filename); exit(7); } /* Check for end of file. */ if (len == 0) { fprintf (stderr,"dmap2hrc: premature end of input file\n"); exit(8); } /* Is this the dummy device record at the end of the controller's set of devices? */ if (strncmp(device.type," ",4) == 0) { more_devices = 0; break; } /* It's a real device. Fix the type so Hercules can use it and locate the output filename. */ strncpy(output_type, device.type, 4); output_type[4] = '\0'; if (isprint(device.parms.disk.volser[0])) output_filename = device.parms.disk.filename; else output_filename = device.parms.other.filename; if (strncmp(device.type, "3278", 4) == 0) { strcpy(output_type, "3270"); output_filename = ""; } if (strncmp(device.type, "2540", 4) == 0) strcpy(output_type, "3505"); /* Emit the Hercules config file entry. */ printf("%02X%02X %s", device.highaddr, device.lowaddr, output_type); if (strlen(output_filename) > 0) printf(" %s", output_filename); puts(""); /* newline */ } /* end while more_devices) */ } /* end while (1) */ /* Close files and exit */ close (infd); return 0; } /* end function main */ hercules-3.07/dyngui.c000644 000765 000765 00000177576 11344073445 016442 0ustar00jmaynardjmaynard000000 000000 /*********************************************************************/ /* DYNGUI.C Hercules External GUI Interface DLL */ /* (c) Copyright "Fish" (David B. Trout), 2003-2009 */ /* */ /* Primary contact: Fish [fish@infidels.com] */ /* */ /*********************************************************************/ // $Id: dyngui.c 5643 2010-02-24 00:47:55Z fish $ #include "hstdinc.h" #include "hercules.h" // (#includes "config." w/#define for VERSION) #ifdef EXTERNALGUI #if defined(OPTION_DYNAMIC_LOAD) #include "devtype.h" #include "opcode.h" /////////////////////////////////////////////////////////////////////////////// // Some handy macros... (feel free to add these to hercules.h) #ifndef BOOL #define BOOL BYTE #endif #ifndef FALSE #define FALSE 0 #endif #ifndef TRUE #define TRUE 1 #endif /////////////////////////////////////////////////////////////////////////////// // Our global variables... (initialized by our "Initialize" function) #define INPUT_STREAM_FILE_PTR ( stdin ) #define OUTPUT_STREAM_FILE_PTR ( stdout ) #define STATUS_STREAM_FILE_PTR ( stderr ) #define MAX_COMMAND_LEN ( 1024 ) #define DEF_MAXRATES_RPT_INTVL ( 1440 ) #if defined( WIN32 ) && !defined( HDL_USE_LIBTOOL ) #if !defined( _MSVC_ ) SYSBLK *psysblk; // (ptr to Herc's SYSBLK structure) #define sysblk (*psysblk) #endif #endif static FILE* fOutputStream = NULL; // (stdout stream) static FILE* fStatusStream = NULL; // (stderr stream) static int nInputStreamFileNum = -1; // (file descriptor for stdin stream) static int gui_nounload = 1; // (nounload indicator) // The device query buffer SHOULD be the maximum device filename length // plus the maximum descriptive length of any/all options for the device, // but there is no #define for either so we have no choice but to impose // our own maximum. #define MAX_DEVICEQUERY_LEN ( 1024 + 256 ) /////////////////////////////////////////////////////////////////////////////// // Some forward references... (our own functions that we call) void Initialize (); void ProcessingLoop (); void Cleanup (); void UpdateTargetCPU (); void ReadInputData (int nTimeoutMillsecs); void ProcessInputData (); void* gui_panel_command (char* pszCommand); void UpdateStatus (); void HandleForcedRefresh(); void UpdateCPUStatus (); void UpdateRegisters (); void UpdateDeviceStatus (); void NewUpdateDevStats (); void gui_fprintf( FILE* stream, const char* pszFormat, ... ); /////////////////////////////////////////////////////////////////////////////// // Our main processing loop... BOOL bDoneProcessing = FALSE; // (set to TRUE to exit) void ProcessingLoop() { // Notify logger_thread we're in control sysblk.panel_init = 1; // Our main purpose in life: read input stream and process // any commands that may be entered, and send periodic status // information back to the external gui via its status stream. // Note we only exit whenever our bDoneProcessing flag is set // which is normally not done until just before Herc unloads // us which is normally not done until immediately before it // terminates. // Also note we re-retrieve sysblk.panrate each iteration // since it could change from one iteration to the next as a result // of the Hercules "panrate" command being entered and processed. while (!bDoneProcessing) { UpdateTargetCPU(); // ("cpu" command could have changed it) UpdateStatus(); // (keep sending status back to gui...) ReadInputData( sysblk.panrate ); ProcessInputData(); // (if there even is any of course...) } } /////////////////////////////////////////////////////////////////////////////// int pcpu = INT_MAX; // target cpu# for commands and displays REGS* pTargetCPU_REGS = NULL; // pointer to target cpu REGS int prev_pcpu = INT_MAX; // (previous value) REGS* pPrevTargetCPU_REGS = NULL; // (previous value) REGS copyregs; // (copy of active cpu's REGS) REGS copysieregs; // (same but when in SIE mode) REGS* CopyREGS( int cpu ); // (fwd ref) /////////////////////////////////////////////////////////////////////////////// void UpdateTargetCPU () { if (!sysblk.shutdown) pTargetCPU_REGS = CopyREGS( pcpu = sysblk.pcpu ); } /////////////////////////////////////////////////////////////////////////////// // (get non-moving/non-dynamic working copy of active cpu's register context) REGS* CopyREGS( int cpu ) // (same logic as in panel.c) { REGS* regs; if (cpu < 0 || cpu >= MAX_CPU_ENGINES) cpu = 0; obtain_lock( &sysblk.cpulock[cpu] ); if (!(regs = sysblk.regs[cpu])) { release_lock( &sysblk.cpulock[cpu] ); return &sysblk.dummyregs; } memcpy( ©regs, regs, sysblk.regs_copy_len ); if (!copyregs.hostregs) { release_lock(&sysblk.cpulock[cpu]); return &sysblk.dummyregs; } #if defined(_FEATURE_SIE) if (regs->sie_active) { memcpy( ©sieregs, regs->guestregs, sysblk.regs_copy_len ); copyregs.guestregs = ©sieregs; copysieregs.hostregs = ©regs; regs = ©sieregs; } else #endif regs = ©regs; SET_PSW_IA( regs ); release_lock( &sysblk.cpulock[cpu] ); return regs; } /////////////////////////////////////////////////////////////////////////////// char* pszInputBuff = NULL; // ptr to buffer int nInputBuffSize = (MAX_COMMAND_LEN+1); // how big the buffer is int nInputLen = 0; // amount of data it's holding /////////////////////////////////////////////////////////////////////////////// void ReadInputData ( int nTimeoutMillsecs ) { size_t nMaxBytesToRead; int nBytesRead; char* pReadBuffer; // Wait for keyboard input data to arrive... #if !defined( _MSVC_ ) fd_set input_fd_set; struct timeval wait_interval_timeval; int rc; FD_ZERO ( &input_fd_set ); FD_SET ( nInputStreamFileNum, &input_fd_set ); wait_interval_timeval.tv_sec = nTimeoutMillsecs / 1000; wait_interval_timeval.tv_usec = (nTimeoutMillsecs % 1000) * 1000; if ((rc = select( nInputStreamFileNum+1, &input_fd_set, NULL, NULL, &wait_interval_timeval )) < 0) { if (HSO_EINTR == HSO_errno) return; // (we were interrupted by a signal) // A bona fide error occurred; abort... logmsg ( _("HHCDG003S select failed on input stream: %s\n") ,strerror(HSO_errno) ); bDoneProcessing = TRUE; // (force main loop to exit) return; } // Has keyboard input data indeed arrived yet? if (!FD_ISSET( nInputStreamFileNum, &input_fd_set )) return; // (nothing for us to do...) #endif // !defined( _MSVC_ ) // Ensure our buffer never overflows... (-2 because // we need room for at least 1 byte + NULL terminator) MINMAX(nInputLen,0,(nInputBuffSize-2)); // Read input data into next available buffer location... // (nMaxBytesToRead-1 == room for NULL terminator) pReadBuffer = (pszInputBuff + nInputLen); nMaxBytesToRead = (nInputBuffSize - nInputLen) - 1; #if !defined( _MSVC_ ) if ((nBytesRead = read( nInputStreamFileNum, pReadBuffer, nMaxBytesToRead )) < 0) { if (EINTR == errno) return; // (we were interrupted by a signal) // A bona fide error occurred; abort... logmsg ( _("HHCDG004S read failed on input stream: %s\n") ,strerror(errno) ); bDoneProcessing = TRUE; // (force main loop to exit) return; } #else // defined( _MSVC_ ) if ( ( nBytesRead = w32_get_stdin_char( pReadBuffer, nTimeoutMillsecs ) ) <= 0 ) return; #endif // !defined( _MSVC_ ) // Update amount of input data we have and // ensure that it's always NULL terminated... MINMAX(nBytesRead,0,nInputBuffSize); nInputLen += nBytesRead; MINMAX(nInputLen,0,(nInputBuffSize-1)); *(pszInputBuff + nInputLen) = 0; } /////////////////////////////////////////////////////////////////////////////// char* pszCommandBuff = NULL; // ptr to buffer int nCommandBuffSize = (MAX_COMMAND_LEN+1); // how big the buffer is int nCommandLen = 0; // amount of data it's holding /////////////////////////////////////////////////////////////////////////////// // Process the data we just read from the input stream... void ProcessInputData () { char* pNewLineChar; // Ensure our buffer is NULL terminated... MINMAX(nInputLen,0,(nInputBuffSize-1)); *(pszInputBuff + nInputLen) = 0; // Input commands are delimited by newline characters... while (nInputLen && (pNewLineChar = strchr(pszInputBuff,'\n')) != NULL) { // Extract command from input buffer // into our command processing buffer... nCommandLen = (pNewLineChar - pszInputBuff); MINMAX(nCommandLen,0,(nCommandBuffSize-1)); memcpy(pszCommandBuff, pszInputBuff, nCommandLen); *(pszCommandBuff + nCommandLen) = 0; // Process the extracted command... // Note that we always call the registered "panel_command" function // rather than call our "gui_panel_command" function directly. This // is in case some other DLL has overridden OUR command handler... panel_command ( pszCommandBuff ); // (call registered handler) // Shift remaining data back to beginning of input buffer... nInputLen = ((pszInputBuff + nInputLen) - (pNewLineChar+1)); MINMAX(nInputLen,0,(nInputBuffSize-1)); memmove(pszInputBuff,pNewLineChar+1,nInputLen); *(pszInputBuff + nInputLen) = 0; } } /////////////////////////////////////////////////////////////////////////////// // (These are actually boolean flags..) double gui_version = 0.0; // (version of HercGUI we're talking to) BYTE gui_forced_refresh = 1; // (force initial update refresh) BYTE gui_wants_gregs = 0; BYTE gui_wants_gregs64 = 0; BYTE gui_wants_cregs = 0; BYTE gui_wants_cregs64 = 0; BYTE gui_wants_aregs = 0; BYTE gui_wants_fregs = 0; BYTE gui_wants_fregs64 = 0; BYTE gui_wants_devlist = 0; BYTE gui_wants_new_devlist = 1; // (should always be initially on) #if defined(OPTION_MIPS_COUNTING) BYTE gui_wants_cpupct = 0; #endif #ifdef OPTION_MIPS_COUNTING U32 prev_mips_rate = 0; U32 prev_sios_rate = 0; #endif /////////////////////////////////////////////////////////////////////////////// // Our Hercules "panel_command" override... void* gui_panel_command (char* pszCommand) { void* (*next_panel_command_handler)(char* pszCommand); // Special GUI commands start with ']'. At the moment, all these special // gui commands tell us is what status information it's interested in... if ( ']' != *pszCommand ) goto NotSpecialGUICommand; gui_forced_refresh = 1; // (forced update refresh) pszCommand++; // (bump past ']') if (strncasecmp(pszCommand,"VERS=",5) == 0) { gui_version = atof(pszCommand+5); return NULL; } if (strncasecmp(pszCommand,"SCD=",4) == 0) { chdir(pszCommand+4); return NULL; } if (strncasecmp(pszCommand,"GREGS=",6) == 0) { gui_wants_gregs = atoi(pszCommand+6); return NULL; } if (strncasecmp(pszCommand,"GREGS64=",8) == 0) { gui_wants_gregs64 = atoi(pszCommand+8); return NULL; } if (strncasecmp(pszCommand,"CREGS=",6) == 0) { gui_wants_cregs = atoi(pszCommand+6); return NULL; } if (strncasecmp(pszCommand,"CREGS64=",8) == 0) { gui_wants_cregs64 = atoi(pszCommand+8); return NULL; } if (strncasecmp(pszCommand,"AREGS=",6) == 0) { gui_wants_aregs = atoi(pszCommand+6); return NULL; } if (strncasecmp(pszCommand,"FREGS=",6) == 0) { gui_wants_fregs = atoi(pszCommand+6); return NULL; } if (strncasecmp(pszCommand,"FREGS64=",8) == 0) { gui_wants_fregs64 = atoi(pszCommand+8); return NULL; } if (strncasecmp(pszCommand,"DEVLIST=",8) == 0) { gui_wants_devlist = atoi(pszCommand+8); if ( gui_wants_devlist ) gui_wants_new_devlist = 0; return NULL; } if (strncasecmp(pszCommand,"NEWDEVLIST=",11) == 0) { gui_wants_new_devlist = atoi(pszCommand+11); if ( gui_wants_new_devlist ) gui_wants_devlist = 0; return NULL; } if (strncasecmp(pszCommand,"MAINSTOR=",9) == 0) { gui_fprintf(fStatusStream,"MAINSTOR=%"UINT_PTR_FMT"d\n",(uintptr_t)pTargetCPU_REGS->mainstor); // Here's a trick! Hercules reports its version number to the GUI // by means of the MAINSIZE value! Later releases of HercGUI know // to interpret mainsizes less than 1000 as Hercule's version number. // Earlier versions of HercGUI will simply try to interpret it as // the actual mainsize, but no real harm is done since we immediately // send it the CORRECT mainsize immediately afterwards. This allows // future versions of HercGUI to know whether the version of Hercules // that it's talking to supports a given feature or not. Slick, eh? :) gui_fprintf(fStatusStream,"MAINSIZE=%s\n",VERSION); gui_fprintf(fStatusStream,"MAINSIZE=%d\n",(U32)sysblk.mainsize); return NULL; } #if defined(OPTION_MIPS_COUNTING) if (strncasecmp(pszCommand,"CPUPCT=",7) == 0) { gui_wants_cpupct = atoi(pszCommand+7); return NULL; } #endif // Silently ignore any unrecognized special GUI commands... return NULL; // (silently ignore it) NotSpecialGUICommand: // Ignore "commands" that are actually just comments (start with '*' or '#') if ('*' == pszCommand[0] || '#' == pszCommand[0]) { logmsg("%s\n",pszCommand); // (log comment to console) return NULL; // (and otherwise ignore it) } // Otherwise it's not a command that we handle. Call the next higher // level command handler which, under normal circumstances SHOULD be // Hercules's "panel_command" function, but which MAY have been over- // ridden by yet some OTHER dynamically loaded command handler... next_panel_command_handler = HDL_FINDNXT( gui_panel_command ); if (!next_panel_command_handler) // (extremely unlikely!) return NULL; // (extremely unlikely!) return next_panel_command_handler( pszCommand ); } /////////////////////////////////////////////////////////////////////////////// // Status updating control fields... QWORD psw, prev_psw; BYTE wait_bit; BYTE prev_cpustate = 0xFF; U64 prev_instcount = 0; U32 prev_gr [16]; U64 prev_gr64 [16]; U32 prev_cr [16]; U64 prev_cr64 [16]; U32 prev_ar [16]; U32 prev_fpr [8*2]; U32 prev_fpr64[16*2]; /////////////////////////////////////////////////////////////////////////////// // Send status information messages back to the gui... void UpdateStatus () { BOOL bStatusChanged = FALSE; // (whether or not anything has changed) if (sysblk.shutdown) return; copy_psw(pTargetCPU_REGS, psw); wait_bit = (psw[1] & 0x02); // The SYS light and %CPU-Utilization // information we send *ALL* the time... if (!(0 || CPUSTATE_STOPPING == pTargetCPU_REGS->cpustate || CPUSTATE_STOPPED == pTargetCPU_REGS->cpustate )) { gui_fprintf(fStatusStream, "SYS=%c\n" ,wait_bit ? '0' : '1' ); } #if defined(OPTION_MIPS_COUNTING) if (gui_wants_cpupct) { gui_fprintf(fStatusStream, "CPUPCT=%d\n" ,pTargetCPU_REGS->cpupct ); } #endif // Determine if we need to inform the GUI of anything... bStatusChanged = FALSE; // (whether or not anything has changed) if (0 || gui_forced_refresh || pTargetCPU_REGS != pPrevTargetCPU_REGS || pcpu != prev_pcpu || memcmp(prev_psw, psw, sizeof(prev_psw)) != 0 || prev_cpustate != pTargetCPU_REGS->cpustate || prev_instcount != INSTCOUNT(pTargetCPU_REGS) ) { bStatusChanged = TRUE; // (something has indeed changed...) if (gui_forced_refresh) // (forced refresh?) HandleForcedRefresh(); // (reset all prev values) // Save new values for next time... pPrevTargetCPU_REGS = pTargetCPU_REGS; prev_pcpu = pcpu; memcpy(prev_psw, psw, sizeof(prev_psw)); prev_cpustate = pTargetCPU_REGS->cpustate; prev_instcount = INSTCOUNT(pTargetCPU_REGS); } // If anything has changed, inform the GUI... if (bStatusChanged) { UpdateCPUStatus(); // (update the status line info...) UpdateRegisters(); // (update the registers display...) } // PROGRAMMING NOTE: my original [rather poorly designed I admit] logic // sent device status messages to the GUI *continuously* (i.e. all the // time), even when both Herc and the channel subsystem was idle. This // proved to be terribly inefficient, causing the GUI to consume *FAR* // too much valuable CPU cycles parsing all of those messages. // Thus, starting with this version of dyngui, we now only send device // status messages to the GUI only whenever the device's status actually // changes, but only if it (the GUI) specifically requests such notifi- // cations of course (via the new "]NEWDEVLIST=" special message). // The new(er) version of HercGUI understands (and thus requests) these // newer format device status messages, but older versions of HercGUI // of course do not. Thus in order to remain compatible with the current // (older) version of the GUI, we still need to support the inefficient // technique of constantly sending a constant stream of device status // messages. // Eventually at some point this existing original inefficient technique // logic will be removed (once everyone has had time to upgrade to the // newer version of HercGUI), but for now, at least for the next couple // of HercGUI release cycles, we need to keep it. if (gui_wants_devlist) // (if the device list is visible) UpdateDeviceStatus(); // (update the list of devices...) else // (the two options are mutually exclusive from one another) if (gui_wants_new_devlist) // (if the device list is visible) NewUpdateDevStats(); // (update the list of devices...) gui_forced_refresh = 0; // (reset switch; must follow devlist update) } /////////////////////////////////////////////////////////////////////////////// // Forced GUI Refresh: reset all "previous" values to force update... void HandleForcedRefresh() { #ifdef OPTION_MIPS_COUNTING prev_mips_rate = INT_MAX; prev_sios_rate = INT_MAX; #endif prev_instcount = ULLONG_MAX; prev_pcpu = INT_MAX; pPrevTargetCPU_REGS = NULL; prev_cpustate = 0xFF; memset( prev_psw, 0xFF, sizeof(prev_psw) ); memset( &prev_gr [0], 0xFF, sizeof(prev_gr) ); memset( &prev_cr [0], 0xFF, sizeof(prev_cr) ); memset( &prev_ar [0], 0xFF, sizeof(prev_ar) ); memset( &prev_fpr [0], 0xFF, sizeof(prev_fpr) ); memset( &prev_gr64 [0], 0xFF, sizeof(prev_gr64) ); memset( &prev_cr64 [0], 0xFF, sizeof(prev_cr64) ); memset( &prev_fpr64[0], 0xFF, sizeof(prev_fpr64) ); } /////////////////////////////////////////////////////////////////////////////// // Send status information messages back to the gui... void UpdateCPUStatus () { if (sysblk.shutdown) return; if (pTargetCPU_REGS == &sysblk.dummyregs) { // pTargetCPU_REGS == &sysblk.dummyregs; cpu is offline gui_fprintf(fStatusStream, "STATUS=" "CPU%4.4X (((((((((((((((((((((((( OFFLINE ))))))))))))))))))))))))\n" ,pcpu); } else // pTargetCPU_REGS != &sysblk.dummyregs; cpu is online { // CPU status line... (PSW, status indicators, and instruction count) gui_fprintf(fStatusStream, "STATUS=" "CPU%4.4X " "PSW=%2.2X%2.2X%2.2X%2.2X " "%2.2X%2.2X%2.2X%2.2X " "%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X " "%c%c%c%c%c%c%c%c " "instcount=%" I64_FMT "u\n" ,pTargetCPU_REGS->cpuad ,psw[0], psw[1], psw[2], psw[3] ,psw[4], psw[5], psw[6], psw[7] ,psw[8], psw[9], psw[10], psw[11], psw[12], psw[13], psw[14], psw[15] ,CPUSTATE_STOPPED == pTargetCPU_REGS->cpustate ? 'M' : '.' ,sysblk.inststep ? 'T' : '.' ,wait_bit ? 'W' : '.' ,pTargetCPU_REGS->loadstate ? 'L' : '.' ,pTargetCPU_REGS->checkstop ? 'C' : '.' ,PROBSTATE(&pTargetCPU_REGS->psw) ? 'P' : '.' , #if defined(_FEATURE_SIE) SIE_MODE(pTargetCPU_REGS) ? 'S' : '.' #else // !defined(_FEATURE_SIE) '.' #endif // defined(_FEATURE_SIE) , #if defined(_900) ARCH_900 == pTargetCPU_REGS->arch_mode ? 'Z' : '.' #else // !defined(_900) '.' #endif // defined(_900) ,(long long)INSTCOUNT(pTargetCPU_REGS) ); } // endif cpu is online/offline // MIPS rate and SIOS rate... #if defined(OPTION_MIPS_COUNTING) // MIPS rate... if (sysblk.mipsrate != prev_mips_rate) { gui_fprintf(fStatusStream, "MIPS=%2.1d.%2.2d\n" , sysblk.mipsrate / 1000000 ,(sysblk.mipsrate % 1000000) / 10000 ); prev_mips_rate = sysblk.mipsrate; } // SIOS rate... if (sysblk.siosrate != prev_sios_rate) { gui_fprintf(fStatusStream, "SIOS=%5d\n" ,sysblk.siosrate ); prev_sios_rate = sysblk.siosrate; } update_maxrates_hwm(); // (update high-water-mark values) #endif // defined(OPTION_MIPS_COUNTING) } /////////////////////////////////////////////////////////////////////////////// // Send status information messages back to the gui... #define REG32FMT "%8.8"I32_FMT"X" #define REG64FMT "%16.16"I64_FMT"X" void UpdateRegisters () { if (sysblk.shutdown) return; if (gui_wants_gregs) { if (0 || prev_gr[0] != pTargetCPU_REGS->GR_L(0) || prev_gr[1] != pTargetCPU_REGS->GR_L(1) || prev_gr[2] != pTargetCPU_REGS->GR_L(2) || prev_gr[3] != pTargetCPU_REGS->GR_L(3) ) { prev_gr[0] = pTargetCPU_REGS->GR_L(0); prev_gr[1] = pTargetCPU_REGS->GR_L(1); prev_gr[2] = pTargetCPU_REGS->GR_L(2); prev_gr[3] = pTargetCPU_REGS->GR_L(3); gui_fprintf(fStatusStream, "GR0-3="REG32FMT" "REG32FMT" "REG32FMT" "REG32FMT"\n" ,pTargetCPU_REGS->GR_L(0) ,pTargetCPU_REGS->GR_L(1) ,pTargetCPU_REGS->GR_L(2) ,pTargetCPU_REGS->GR_L(3) ); } if (0 || prev_gr[4] != pTargetCPU_REGS->GR_L(4) || prev_gr[5] != pTargetCPU_REGS->GR_L(5) || prev_gr[6] != pTargetCPU_REGS->GR_L(6) || prev_gr[7] != pTargetCPU_REGS->GR_L(7) ) { prev_gr[4] = pTargetCPU_REGS->GR_L(4); prev_gr[5] = pTargetCPU_REGS->GR_L(5); prev_gr[6] = pTargetCPU_REGS->GR_L(6); prev_gr[7] = pTargetCPU_REGS->GR_L(7); gui_fprintf(fStatusStream, "GR4-7="REG32FMT" "REG32FMT" "REG32FMT" "REG32FMT"\n" ,pTargetCPU_REGS->GR_L(4) ,pTargetCPU_REGS->GR_L(5) ,pTargetCPU_REGS->GR_L(6) ,pTargetCPU_REGS->GR_L(7) ); } if (0 || prev_gr[8] != pTargetCPU_REGS->GR_L(8) || prev_gr[9] != pTargetCPU_REGS->GR_L(9) || prev_gr[10] != pTargetCPU_REGS->GR_L(10) || prev_gr[11] != pTargetCPU_REGS->GR_L(11) ) { prev_gr[8] = pTargetCPU_REGS->GR_L(8); prev_gr[9] = pTargetCPU_REGS->GR_L(9); prev_gr[10] = pTargetCPU_REGS->GR_L(10); prev_gr[11] = pTargetCPU_REGS->GR_L(11); gui_fprintf(fStatusStream, "GR8-B="REG32FMT" "REG32FMT" "REG32FMT" "REG32FMT"\n" ,pTargetCPU_REGS->GR_L(8) ,pTargetCPU_REGS->GR_L(9) ,pTargetCPU_REGS->GR_L(10) ,pTargetCPU_REGS->GR_L(11) ); } if (0 || prev_gr[12] != pTargetCPU_REGS->GR_L(12) || prev_gr[13] != pTargetCPU_REGS->GR_L(13) || prev_gr[14] != pTargetCPU_REGS->GR_L(14) || prev_gr[15] != pTargetCPU_REGS->GR_L(15) ) { prev_gr[12] = pTargetCPU_REGS->GR_L(12); prev_gr[13] = pTargetCPU_REGS->GR_L(13); prev_gr[14] = pTargetCPU_REGS->GR_L(14); prev_gr[15] = pTargetCPU_REGS->GR_L(15); gui_fprintf(fStatusStream, "GRC-F="REG32FMT" "REG32FMT" "REG32FMT" "REG32FMT"\n" ,pTargetCPU_REGS->GR_L(12) ,pTargetCPU_REGS->GR_L(13) ,pTargetCPU_REGS->GR_L(14) ,pTargetCPU_REGS->GR_L(15) ); } } if (gui_wants_gregs64) { if (0 || prev_gr64[0] != pTargetCPU_REGS->GR_G(0) || prev_gr64[1] != pTargetCPU_REGS->GR_G(1) ) { prev_gr64[0] = pTargetCPU_REGS->GR_G(0); prev_gr64[1] = pTargetCPU_REGS->GR_G(1); gui_fprintf(fStatusStream, "64_GR0-1="REG64FMT" "REG64FMT"\n" ,pTargetCPU_REGS->GR_G(0) ,pTargetCPU_REGS->GR_G(1) ); } if (0 || prev_gr64[2] != pTargetCPU_REGS->GR_G(2) || prev_gr64[3] != pTargetCPU_REGS->GR_G(3) ) { prev_gr64[2] = pTargetCPU_REGS->GR_G(2); prev_gr64[3] = pTargetCPU_REGS->GR_G(3); gui_fprintf(fStatusStream, "64_GR2-3="REG64FMT" "REG64FMT"\n" ,pTargetCPU_REGS->GR_G(2) ,pTargetCPU_REGS->GR_G(3) ); } if (0 || prev_gr64[4] != pTargetCPU_REGS->GR_G(4) || prev_gr64[5] != pTargetCPU_REGS->GR_G(5) ) { prev_gr64[4] = pTargetCPU_REGS->GR_G(4); prev_gr64[5] = pTargetCPU_REGS->GR_G(5); gui_fprintf(fStatusStream, "64_GR4-5="REG64FMT" "REG64FMT"\n" ,pTargetCPU_REGS->GR_G(4) ,pTargetCPU_REGS->GR_G(5) ); } if (0 || prev_gr64[6] != pTargetCPU_REGS->GR_G(6) || prev_gr64[7] != pTargetCPU_REGS->GR_G(7) ) { prev_gr64[6] = pTargetCPU_REGS->GR_G(6); prev_gr64[7] = pTargetCPU_REGS->GR_G(7); gui_fprintf(fStatusStream, "64_GR6-7="REG64FMT" "REG64FMT"\n" ,pTargetCPU_REGS->GR_G(6) ,pTargetCPU_REGS->GR_G(7) ); } if (0 || prev_gr64[8] != pTargetCPU_REGS->GR_G(8) || prev_gr64[9] != pTargetCPU_REGS->GR_G(9) ) { prev_gr64[8] = pTargetCPU_REGS->GR_G(8); prev_gr64[9] = pTargetCPU_REGS->GR_G(9); gui_fprintf(fStatusStream, "64_GR8-9="REG64FMT" "REG64FMT"\n" ,pTargetCPU_REGS->GR_G(8) ,pTargetCPU_REGS->GR_G(9) ); } if (0 || prev_gr64[10] != pTargetCPU_REGS->GR_G(10) || prev_gr64[11] != pTargetCPU_REGS->GR_G(11) ) { prev_gr64[10] = pTargetCPU_REGS->GR_G(10); prev_gr64[11] = pTargetCPU_REGS->GR_G(11); gui_fprintf(fStatusStream, "64_GRA-B="REG64FMT" "REG64FMT"\n" ,pTargetCPU_REGS->GR_G(10) ,pTargetCPU_REGS->GR_G(11) ); } if (0 || prev_gr64[12] != pTargetCPU_REGS->GR_G(12) || prev_gr64[13] != pTargetCPU_REGS->GR_G(13) ) { prev_gr64[12] = pTargetCPU_REGS->GR_G(12); prev_gr64[13] = pTargetCPU_REGS->GR_G(13); gui_fprintf(fStatusStream, "64_GRC-D="REG64FMT" "REG64FMT"\n" ,pTargetCPU_REGS->GR_G(12) ,pTargetCPU_REGS->GR_G(13) ); } if (0 || prev_gr64[14] != pTargetCPU_REGS->GR_G(14) || prev_gr64[15] != pTargetCPU_REGS->GR_G(15) ) { prev_gr64[14] = pTargetCPU_REGS->GR_G(14); prev_gr64[15] = pTargetCPU_REGS->GR_G(15); gui_fprintf(fStatusStream, "64_GRE-F="REG64FMT" "REG64FMT"\n" ,pTargetCPU_REGS->GR_G(14) ,pTargetCPU_REGS->GR_G(15) ); } } if (gui_wants_cregs) { if (0 || prev_cr[0] != pTargetCPU_REGS->CR_L(0) || prev_cr[1] != pTargetCPU_REGS->CR_L(1) || prev_cr[2] != pTargetCPU_REGS->CR_L(2) || prev_cr[3] != pTargetCPU_REGS->CR_L(3) ) { prev_cr[0] = pTargetCPU_REGS->CR_L(0); prev_cr[1] = pTargetCPU_REGS->CR_L(1); prev_cr[2] = pTargetCPU_REGS->CR_L(2); prev_cr[3] = pTargetCPU_REGS->CR_L(3); gui_fprintf(fStatusStream, "CR0-3="REG32FMT" "REG32FMT" "REG32FMT" "REG32FMT"\n" ,pTargetCPU_REGS->CR_L(0) ,pTargetCPU_REGS->CR_L(1) ,pTargetCPU_REGS->CR_L(2) ,pTargetCPU_REGS->CR_L(3) ); } if (0 || prev_cr[4] != pTargetCPU_REGS->CR_L(4) || prev_cr[5] != pTargetCPU_REGS->CR_L(5) || prev_cr[6] != pTargetCPU_REGS->CR_L(6) || prev_cr[7] != pTargetCPU_REGS->CR_L(7) ) { prev_cr[4] = pTargetCPU_REGS->CR_L(4); prev_cr[5] = pTargetCPU_REGS->CR_L(5); prev_cr[6] = pTargetCPU_REGS->CR_L(6); prev_cr[7] = pTargetCPU_REGS->CR_L(7); gui_fprintf(fStatusStream, "CR4-7="REG32FMT" "REG32FMT" "REG32FMT" "REG32FMT"\n" ,pTargetCPU_REGS->CR_L(4) ,pTargetCPU_REGS->CR_L(5) ,pTargetCPU_REGS->CR_L(6) ,pTargetCPU_REGS->CR_L(7) ); } if (0 || prev_cr[8] != pTargetCPU_REGS->CR_L(8) || prev_cr[9] != pTargetCPU_REGS->CR_L(9) || prev_cr[10] != pTargetCPU_REGS->CR_L(10) || prev_cr[11] != pTargetCPU_REGS->CR_L(11) ) { prev_cr[8] = pTargetCPU_REGS->CR_L(8); prev_cr[9] = pTargetCPU_REGS->CR_L(9); prev_cr[10] = pTargetCPU_REGS->CR_L(10); prev_cr[10] = pTargetCPU_REGS->CR_L(10); gui_fprintf(fStatusStream, "CR8-B="REG32FMT" "REG32FMT" "REG32FMT" "REG32FMT"\n" ,pTargetCPU_REGS->CR_L(8) ,pTargetCPU_REGS->CR_L(9) ,pTargetCPU_REGS->CR_L(10) ,pTargetCPU_REGS->CR_L(11) ); } if (0 || prev_cr[12] != pTargetCPU_REGS->CR_L(12) || prev_cr[13] != pTargetCPU_REGS->CR_L(13) || prev_cr[14] != pTargetCPU_REGS->CR_L(14) || prev_cr[15] != pTargetCPU_REGS->CR_L(15) ) { prev_cr[12] = pTargetCPU_REGS->CR_L(12); prev_cr[13] = pTargetCPU_REGS->CR_L(13); prev_cr[14] = pTargetCPU_REGS->CR_L(14); prev_cr[15] = pTargetCPU_REGS->CR_L(15); gui_fprintf(fStatusStream, "CRC-F="REG32FMT" "REG32FMT" "REG32FMT" "REG32FMT"\n" ,pTargetCPU_REGS->CR_L(12) ,pTargetCPU_REGS->CR_L(13) ,pTargetCPU_REGS->CR_L(14) ,pTargetCPU_REGS->CR_L(15) ); } } if (gui_wants_cregs64) { if (0 || prev_cr64[0] != pTargetCPU_REGS->CR_G(0) || prev_cr64[1] != pTargetCPU_REGS->CR_G(1) ) { prev_cr64[0] = pTargetCPU_REGS->CR_G(0); prev_cr64[1] = pTargetCPU_REGS->CR_G(1); gui_fprintf(fStatusStream, "64_CR0-1="REG64FMT" "REG64FMT"\n" ,pTargetCPU_REGS->CR_G(0) ,pTargetCPU_REGS->CR_G(1) ); } if (0 || prev_cr64[2] != pTargetCPU_REGS->CR_G(2) || prev_cr64[3] != pTargetCPU_REGS->CR_G(3) ) { prev_cr64[2] = pTargetCPU_REGS->CR_G(2); prev_cr64[3] = pTargetCPU_REGS->CR_G(3); gui_fprintf(fStatusStream, "64_CR2-3="REG64FMT" "REG64FMT"\n" ,pTargetCPU_REGS->CR_G(2) ,pTargetCPU_REGS->CR_G(3) ); } if (0 || prev_cr64[4] != pTargetCPU_REGS->CR_G(4) || prev_cr64[5] != pTargetCPU_REGS->CR_G(5) ) { prev_cr64[4] = pTargetCPU_REGS->CR_G(4); prev_cr64[5] = pTargetCPU_REGS->CR_G(5); gui_fprintf(fStatusStream, "64_CR4-5="REG64FMT" "REG64FMT"\n" ,pTargetCPU_REGS->CR_G(4) ,pTargetCPU_REGS->CR_G(5) ); } if (0 || prev_cr64[6] != pTargetCPU_REGS->CR_G(6) || prev_cr64[7] != pTargetCPU_REGS->CR_G(7) ) { prev_cr64[6] = pTargetCPU_REGS->CR_G(6); prev_cr64[7] = pTargetCPU_REGS->CR_G(7); gui_fprintf(fStatusStream, "64_CR6-7="REG64FMT" "REG64FMT"\n" ,pTargetCPU_REGS->CR_G(6) ,pTargetCPU_REGS->CR_G(7) ); } if (0 || prev_cr64[8] != pTargetCPU_REGS->CR_G(8) || prev_cr64[9] != pTargetCPU_REGS->CR_G(9) ) { prev_cr64[8] = pTargetCPU_REGS->CR_G(8); prev_cr64[9] = pTargetCPU_REGS->CR_G(9); gui_fprintf(fStatusStream, "64_CR8-9="REG64FMT" "REG64FMT"\n" ,pTargetCPU_REGS->CR_G(8) ,pTargetCPU_REGS->CR_G(9) ); } if (0 || prev_cr64[10] != pTargetCPU_REGS->CR_G(10) || prev_cr64[11] != pTargetCPU_REGS->CR_G(11) ) { prev_cr64[10] = pTargetCPU_REGS->CR_G(10); prev_cr64[11] = pTargetCPU_REGS->CR_G(11); gui_fprintf(fStatusStream, "64_CRA-B="REG64FMT" "REG64FMT"\n" ,pTargetCPU_REGS->CR_G(10) ,pTargetCPU_REGS->CR_G(11) ); } if (0 || prev_cr64[12] != pTargetCPU_REGS->CR_G(12) || prev_cr64[13] != pTargetCPU_REGS->CR_G(13) ) { prev_cr64[12] = pTargetCPU_REGS->CR_G(12); prev_cr64[13] = pTargetCPU_REGS->CR_G(13); gui_fprintf(fStatusStream, "64_CRC-D="REG64FMT" "REG64FMT"\n" ,pTargetCPU_REGS->CR_G(12) ,pTargetCPU_REGS->CR_G(13) ); } if (0 || prev_cr64[14] != pTargetCPU_REGS->CR_G(14) || prev_cr64[15] != pTargetCPU_REGS->CR_G(15) ) { prev_cr64[14] = pTargetCPU_REGS->CR_G(14); prev_cr64[15] = pTargetCPU_REGS->CR_G(15); gui_fprintf(fStatusStream, "64_CRE-F="REG64FMT" "REG64FMT"\n" ,pTargetCPU_REGS->CR_G(14) ,pTargetCPU_REGS->CR_G(15) ); } } if (gui_wants_aregs) { if (0 || prev_ar[0] != pTargetCPU_REGS->AR(0) || prev_ar[1] != pTargetCPU_REGS->AR(1) || prev_ar[2] != pTargetCPU_REGS->AR(2) || prev_ar[3] != pTargetCPU_REGS->AR(3) ) { prev_ar[0] = pTargetCPU_REGS->AR(0); prev_ar[1] = pTargetCPU_REGS->AR(1); prev_ar[2] = pTargetCPU_REGS->AR(2); prev_ar[3] = pTargetCPU_REGS->AR(3); gui_fprintf(fStatusStream, "AR0-3="REG32FMT" "REG32FMT" "REG32FMT" "REG32FMT"\n" ,pTargetCPU_REGS->AR(0) ,pTargetCPU_REGS->AR(1) ,pTargetCPU_REGS->AR(2) ,pTargetCPU_REGS->AR(3) ); } if (0 || prev_ar[4] != pTargetCPU_REGS->AR(4) || prev_ar[5] != pTargetCPU_REGS->AR(5) || prev_ar[6] != pTargetCPU_REGS->AR(6) || prev_ar[7] != pTargetCPU_REGS->AR(7) ) { prev_ar[4] = pTargetCPU_REGS->AR(4); prev_ar[5] = pTargetCPU_REGS->AR(5); prev_ar[6] = pTargetCPU_REGS->AR(6); prev_ar[7] = pTargetCPU_REGS->AR(7); gui_fprintf(fStatusStream, "AR4-7="REG32FMT" "REG32FMT" "REG32FMT" "REG32FMT"\n" ,pTargetCPU_REGS->AR(4) ,pTargetCPU_REGS->AR(5) ,pTargetCPU_REGS->AR(6) ,pTargetCPU_REGS->AR(7) ); } if (0 || prev_ar[8] != pTargetCPU_REGS->AR(8) || prev_ar[9] != pTargetCPU_REGS->AR(9) || prev_ar[10] != pTargetCPU_REGS->AR(10) || prev_ar[11] != pTargetCPU_REGS->AR(11) ) { prev_ar[8] = pTargetCPU_REGS->AR(8); prev_ar[9] = pTargetCPU_REGS->AR(9); prev_ar[10] = pTargetCPU_REGS->AR(10); prev_ar[11] = pTargetCPU_REGS->AR(11); gui_fprintf(fStatusStream, "AR8-B="REG32FMT" "REG32FMT" "REG32FMT" "REG32FMT"\n" ,pTargetCPU_REGS->AR(8) ,pTargetCPU_REGS->AR(9) ,pTargetCPU_REGS->AR(10) ,pTargetCPU_REGS->AR(11) ); } if (0 || prev_ar[12] != pTargetCPU_REGS->AR(12) || prev_ar[13] != pTargetCPU_REGS->AR(13) || prev_ar[14] != pTargetCPU_REGS->AR(14) || prev_ar[15] != pTargetCPU_REGS->AR(15) ) { prev_ar[12] = pTargetCPU_REGS->AR(12); prev_ar[13] = pTargetCPU_REGS->AR(13); prev_ar[14] = pTargetCPU_REGS->AR(14); prev_ar[15] = pTargetCPU_REGS->AR(15); gui_fprintf(fStatusStream, "ARC-F="REG32FMT" "REG32FMT" "REG32FMT" "REG32FMT"\n" ,pTargetCPU_REGS->AR(12) ,pTargetCPU_REGS->AR(13) ,pTargetCPU_REGS->AR(14) ,pTargetCPU_REGS->AR(15) ); } } if (gui_wants_fregs) { if (0 || prev_fpr[0] != pTargetCPU_REGS->fpr[0] || prev_fpr[1] != pTargetCPU_REGS->fpr[1] || prev_fpr[2] != pTargetCPU_REGS->fpr[2] || prev_fpr[3] != pTargetCPU_REGS->fpr[3] ) { prev_fpr[0] = pTargetCPU_REGS->fpr[0]; prev_fpr[1] = pTargetCPU_REGS->fpr[1]; prev_fpr[2] = pTargetCPU_REGS->fpr[2]; prev_fpr[3] = pTargetCPU_REGS->fpr[3]; gui_fprintf(fStatusStream, "FR0-2="REG32FMT" "REG32FMT" "REG32FMT" "REG32FMT"\n" ,pTargetCPU_REGS->fpr[0] ,pTargetCPU_REGS->fpr[1] ,pTargetCPU_REGS->fpr[2] ,pTargetCPU_REGS->fpr[3] ); } if (0 || prev_fpr[4] != pTargetCPU_REGS->fpr[4] || prev_fpr[5] != pTargetCPU_REGS->fpr[5] || prev_fpr[6] != pTargetCPU_REGS->fpr[6] || prev_fpr[7] != pTargetCPU_REGS->fpr[7] ) { prev_fpr[4] = pTargetCPU_REGS->fpr[4]; prev_fpr[5] = pTargetCPU_REGS->fpr[5]; prev_fpr[6] = pTargetCPU_REGS->fpr[6]; prev_fpr[7] = pTargetCPU_REGS->fpr[7]; gui_fprintf(fStatusStream, "FR4-6="REG32FMT" "REG32FMT" "REG32FMT" "REG32FMT"\n" ,pTargetCPU_REGS->fpr[4] ,pTargetCPU_REGS->fpr[5] ,pTargetCPU_REGS->fpr[6] ,pTargetCPU_REGS->fpr[7] ); } } if (gui_wants_fregs64) { if (0 || prev_fpr64[0] != pTargetCPU_REGS->fpr[0] || prev_fpr64[1] != pTargetCPU_REGS->fpr[1] || prev_fpr64[2] != pTargetCPU_REGS->fpr[2] || prev_fpr64[3] != pTargetCPU_REGS->fpr[3] ) { prev_fpr64[0] = pTargetCPU_REGS->fpr[0]; prev_fpr64[1] = pTargetCPU_REGS->fpr[1]; prev_fpr64[2] = pTargetCPU_REGS->fpr[2]; prev_fpr64[3] = pTargetCPU_REGS->fpr[3]; gui_fprintf(fStatusStream, "64_FR0-1="REG32FMT""REG32FMT" "REG32FMT""REG32FMT"\n" ,pTargetCPU_REGS->fpr[0] ,pTargetCPU_REGS->fpr[1] ,pTargetCPU_REGS->fpr[2] ,pTargetCPU_REGS->fpr[3] ); } if (0 || prev_fpr64[4] != pTargetCPU_REGS->fpr[4] || prev_fpr64[5] != pTargetCPU_REGS->fpr[5] || prev_fpr64[6] != pTargetCPU_REGS->fpr[6] || prev_fpr64[7] != pTargetCPU_REGS->fpr[7] ) { prev_fpr64[4] = pTargetCPU_REGS->fpr[4]; prev_fpr64[5] = pTargetCPU_REGS->fpr[5]; prev_fpr64[6] = pTargetCPU_REGS->fpr[6]; prev_fpr64[7] = pTargetCPU_REGS->fpr[7]; gui_fprintf(fStatusStream, "64_FR2-3="REG32FMT""REG32FMT" "REG32FMT""REG32FMT"\n" ,pTargetCPU_REGS->fpr[4] ,pTargetCPU_REGS->fpr[5] ,pTargetCPU_REGS->fpr[6] ,pTargetCPU_REGS->fpr[7] ); } if (0 || prev_fpr64[8] != pTargetCPU_REGS->fpr[8] || prev_fpr64[9] != pTargetCPU_REGS->fpr[9] || prev_fpr64[10] != pTargetCPU_REGS->fpr[10] || prev_fpr64[11] != pTargetCPU_REGS->fpr[11] ) { prev_fpr64[8] = pTargetCPU_REGS->fpr[8]; prev_fpr64[9] = pTargetCPU_REGS->fpr[9]; prev_fpr64[10] = pTargetCPU_REGS->fpr[10]; prev_fpr64[11] = pTargetCPU_REGS->fpr[11]; gui_fprintf(fStatusStream, "64_FR4-5="REG32FMT""REG32FMT" "REG32FMT""REG32FMT"\n" ,pTargetCPU_REGS->fpr[8] ,pTargetCPU_REGS->fpr[9] ,pTargetCPU_REGS->fpr[10] ,pTargetCPU_REGS->fpr[11] ); } if (0 || prev_fpr64[12] != pTargetCPU_REGS->fpr[12] || prev_fpr64[13] != pTargetCPU_REGS->fpr[13] || prev_fpr64[14] != pTargetCPU_REGS->fpr[14] || prev_fpr64[15] != pTargetCPU_REGS->fpr[15] ) { prev_fpr64[12] = pTargetCPU_REGS->fpr[12]; prev_fpr64[13] = pTargetCPU_REGS->fpr[13]; prev_fpr64[14] = pTargetCPU_REGS->fpr[14]; prev_fpr64[15] = pTargetCPU_REGS->fpr[15]; gui_fprintf(fStatusStream, "64_FR6-7="REG32FMT""REG32FMT" "REG32FMT""REG32FMT"\n" ,pTargetCPU_REGS->fpr[12] ,pTargetCPU_REGS->fpr[13] ,pTargetCPU_REGS->fpr[14] ,pTargetCPU_REGS->fpr[15] ); } if (0 || prev_fpr64[16] != pTargetCPU_REGS->fpr[16] || prev_fpr64[17] != pTargetCPU_REGS->fpr[17] || prev_fpr64[18] != pTargetCPU_REGS->fpr[18] || prev_fpr64[19] != pTargetCPU_REGS->fpr[19] ) { prev_fpr64[16] = pTargetCPU_REGS->fpr[16]; prev_fpr64[17] = pTargetCPU_REGS->fpr[17]; prev_fpr64[18] = pTargetCPU_REGS->fpr[18]; prev_fpr64[19] = pTargetCPU_REGS->fpr[19]; gui_fprintf(fStatusStream, "64_FR8-9="REG32FMT""REG32FMT" "REG32FMT""REG32FMT"\n" ,pTargetCPU_REGS->fpr[16] ,pTargetCPU_REGS->fpr[17] ,pTargetCPU_REGS->fpr[18] ,pTargetCPU_REGS->fpr[19] ); } if (0 || prev_fpr64[20] != pTargetCPU_REGS->fpr[20] || prev_fpr64[21] != pTargetCPU_REGS->fpr[21] || prev_fpr64[22] != pTargetCPU_REGS->fpr[22] || prev_fpr64[23] != pTargetCPU_REGS->fpr[23] ) { prev_fpr64[20] = pTargetCPU_REGS->fpr[20]; prev_fpr64[21] = pTargetCPU_REGS->fpr[21]; prev_fpr64[22] = pTargetCPU_REGS->fpr[22]; prev_fpr64[23] = pTargetCPU_REGS->fpr[23]; gui_fprintf(fStatusStream, "64_FRA-B="REG32FMT""REG32FMT" "REG32FMT""REG32FMT"\n" ,pTargetCPU_REGS->fpr[20] ,pTargetCPU_REGS->fpr[21] ,pTargetCPU_REGS->fpr[22] ,pTargetCPU_REGS->fpr[23] ); } if (0 || prev_fpr64[24] != pTargetCPU_REGS->fpr[24] || prev_fpr64[25] != pTargetCPU_REGS->fpr[25] || prev_fpr64[26] != pTargetCPU_REGS->fpr[26] || prev_fpr64[27] != pTargetCPU_REGS->fpr[27] ) { prev_fpr64[24] = pTargetCPU_REGS->fpr[24]; prev_fpr64[25] = pTargetCPU_REGS->fpr[25]; prev_fpr64[26] = pTargetCPU_REGS->fpr[26]; prev_fpr64[27] = pTargetCPU_REGS->fpr[27]; gui_fprintf(fStatusStream, "64_FRC-D="REG32FMT""REG32FMT" "REG32FMT""REG32FMT"\n" ,pTargetCPU_REGS->fpr[24] ,pTargetCPU_REGS->fpr[25] ,pTargetCPU_REGS->fpr[26] ,pTargetCPU_REGS->fpr[27] ); } if (0 || prev_fpr64[28] != pTargetCPU_REGS->fpr[28] || prev_fpr64[29] != pTargetCPU_REGS->fpr[29] || prev_fpr64[30] != pTargetCPU_REGS->fpr[30] || prev_fpr64[31] != pTargetCPU_REGS->fpr[31] ) { prev_fpr64[28] = pTargetCPU_REGS->fpr[28]; prev_fpr64[29] = pTargetCPU_REGS->fpr[29]; prev_fpr64[30] = pTargetCPU_REGS->fpr[30]; prev_fpr64[31] = pTargetCPU_REGS->fpr[31]; gui_fprintf(fStatusStream, "64_FRE-F="REG32FMT""REG32FMT" "REG32FMT""REG32FMT"\n" ,pTargetCPU_REGS->fpr[28] ,pTargetCPU_REGS->fpr[29] ,pTargetCPU_REGS->fpr[30] ,pTargetCPU_REGS->fpr[31] ); } } } /////////////////////////////////////////////////////////////////////////////// char szQueryDeviceBuff[ MAX_DEVICEQUERY_LEN + 1 ]; // (always +1 for safety!) /////////////////////////////////////////////////////////////////////////////// // Send status information messages back to the gui... (VERY inefficient!) void UpdateDeviceStatus () { DEVBLK* pDEVBLK; char* pDEVClass; BYTE chOnlineStat, chBusyStat, chPendingStat, chOpenStat; if (sysblk.shutdown) return; // Process ALL the devices in the entire configuration each time... for (pDEVBLK = sysblk.firstdev; pDEVBLK != NULL; pDEVBLK = pDEVBLK->nextdev) { // Does this device actually exist in the configuration? if (!pDEVBLK->allocated || !(pDEVBLK->pmcw.flag5 & PMCW5_V)) continue; // (no, skip) // Retrieve this device's filename and optional settings parameter values... szQueryDeviceBuff[MAX_DEVICEQUERY_LEN] = 0; // (buffer allows room for 1 extra) (pDEVBLK->hnd->query)(pDEVBLK, &pDEVClass, MAX_DEVICEQUERY_LEN, szQueryDeviceBuff); if (0 != szQueryDeviceBuff[MAX_DEVICEQUERY_LEN]) // (buffer overflow?) { logmsg ( _("HHCDG005E Device query buffer overflow! (device=%4.4X)\n") ,pDEVBLK->devnum ); } szQueryDeviceBuff[MAX_DEVICEQUERY_LEN] = 0; // (enforce NULL termination) // Device status flags... chOnlineStat = chBusyStat = chPendingStat = chOpenStat = '0'; if ((!pDEVBLK->console && pDEVBLK->fd >= 0) || ( pDEVBLK->console && pDEVBLK->connected)) chOnlineStat = '1'; if (pDEVBLK->busy) chBusyStat = '1'; if (IOPENDING(pDEVBLK)) chPendingStat = '1'; if (pDEVBLK->fd > MAX(STDIN_FILENO,MAX(STDOUT_FILENO,STDERR_FILENO))) chOpenStat = '1'; // Send status message back to gui... gui_fprintf(fStatusStream, "DEV=%4.4X %4.4X %-4.4s %c%c%c%c %s\n" ,pDEVBLK->devnum ,pDEVBLK->devtype ,pDEVClass ,chOnlineStat ,chBusyStat ,chPendingStat ,chOpenStat ,szQueryDeviceBuff ); } // Since the device list can be in any order and devices can be added // and/or removed at any time, the GUI needs to know "That's all the // devices there are" so that it can detect when devices are removed... gui_fprintf(fStatusStream, "DEV=X\n"); // (indicates end of list) } /////////////////////////////////////////////////////////////////////////////// // Send device status msgs to the gui IF NEEDED... (slightly more efficient) void NewUpdateDevStats () { DEVBLK* pDEVBLK; GUISTAT* pGUIStat; char* pDEVClass; BYTE chOnlineStat, chBusyStat, chPendingStat, chOpenStat; BOOL bUpdatesSent = FALSE; if (sysblk.shutdown) return; // Process ALL the devices in the entire configuration each time... // (But only send device status messages to the GUI only when the // device's status actually changes and not continuously like before) for (pDEVBLK = sysblk.firstdev; pDEVBLK != NULL; pDEVBLK = pDEVBLK->nextdev) { pGUIStat = pDEVBLK->pGUIStat; // Does this device exist in the configuration? if (!pDEVBLK->allocated || !(pDEVBLK->pmcw.flag5 & PMCW5_V)) { // This device no longer exists in the configuration... // If we haven't yet notified the GUI about this device // being deleted from the configuration, then do so at // this time... if (*pGUIStat->pszNewStatStr) { // Send "device deleted" message... gui_fprintf ( fStatusStream, "DEVD=%4.4X\n", pDEVBLK->devnum ); bUpdatesSent = TRUE; *pGUIStat->pszNewStatStr = 0; // (prevent re-reporting it) *pGUIStat->pszOldStatStr = 0; // (prevent re-reporting it) } continue; // (go on to next device) } // Retrieve this device's filename and optional settings parameter values... szQueryDeviceBuff[MAX_DEVICEQUERY_LEN] = 0; // (buffer allows room for 1 extra) (pDEVBLK->hnd->query)(pDEVBLK, &pDEVClass, MAX_DEVICEQUERY_LEN, szQueryDeviceBuff); if (0 != szQueryDeviceBuff[MAX_DEVICEQUERY_LEN]) // (buffer overflow?) { logmsg ( _("HHCDG005E Device query buffer overflow! (device=%4.4X)\n") ,pDEVBLK->devnum ); } szQueryDeviceBuff[MAX_DEVICEQUERY_LEN] = 0; // (enforce NULL termination) // Device status flags... chOnlineStat = chBusyStat = chPendingStat = chOpenStat = '0'; if ((!pDEVBLK->console && pDEVBLK->fd >= 0) || ( pDEVBLK->console && pDEVBLK->connected)) chOnlineStat = '1'; if (pDEVBLK->busy) chBusyStat = '1'; if (IOPENDING(pDEVBLK)) chPendingStat = '1'; if (pDEVBLK->fd > MAX(STDIN_FILENO,MAX(STDOUT_FILENO,STDERR_FILENO))) chOpenStat = '1'; // Build a new "device added" or "device changed" // status string for this device... snprintf( pGUIStat->pszNewStatStr, GUI_STATSTR_BUFSIZ, "DEV%c=%4.4X %4.4X %-4.4s %c%c%c%c %s" ,*pGUIStat->pszOldStatStr ? 'C' : 'A' ,pDEVBLK->devnum ,pDEVBLK->devtype ,pDEVClass ,chOnlineStat ,chBusyStat ,chPendingStat ,chOpenStat ,szQueryDeviceBuff ); *(pGUIStat->pszNewStatStr + GUI_STATSTR_BUFSIZ - 1) = 0; // If the new status string is different from the old one, // then send the new one to the GUI and swap buffer ptrs // for next time. In this way we only send device status // msgs to the GUI only when the status actually changes... if (strcmp( pGUIStat->pszNewStatStr, pGUIStat->pszOldStatStr )) { gui_fprintf ( fStatusStream, "%s\n", pGUIStat->pszNewStatStr ); bUpdatesSent = TRUE; { register char* pszSavStatStr = pGUIStat->pszNewStatStr; pGUIStat->pszNewStatStr = pGUIStat->pszOldStatStr; pGUIStat->pszOldStatStr = pszSavStatStr; } } } if ( bUpdatesSent ) gui_fprintf(fStatusStream, "DEVX=\n"); // (send end-of-batch indicator) } /////////////////////////////////////////////////////////////////////////////// // Our Hercules "debug_cpu_state" override... // // Hercules calls the following function from several different places to fix // an unintentional problem caused by the new logger mechanism (wherein stdout // and stderr now point to the same stream) due to a oversight (bug) on my part // wherein the 'LOAD' and 'MAN' messages are being [mistakenly] written to stdout // instead of stderr (where they normally should be). The current version of // the gui expects both messages to come in on the stdout stream, but due to the // recent logger changes, they now come in on the stderr stream instead (because // stdout was duped to stderr by the new logger logic) thus causing the gui to // miss seeing them without the below fix. The below fix simply corrects for the // problem by simply writing the two messages to the stdout stream where older // versions of the gui expect to see them. void* gui_debug_cpu_state ( REGS* pREGS ) { void *(*next_debug_call)(REGS *); static BOOL bLoading = FALSE; static BOOL bStopped = FALSE; if (sysblk.shutdown) return NULL; if (pTargetCPU_REGS && pREGS != pTargetCPU_REGS) return NULL; if (bLoading != (pREGS->loadstate ? TRUE : FALSE)) { bLoading = (pREGS->loadstate ? TRUE : FALSE); gui_fprintf(stdout,"LOAD=%c\n", bLoading ? '1' : '0'); } if (bStopped != ((CPUSTATE_STOPPED == pREGS->cpustate) ? TRUE : FALSE)) { bStopped = ((CPUSTATE_STOPPED == pREGS->cpustate) ? TRUE : FALSE); gui_fprintf(stdout,"MAN=%c\n", bStopped ? '1' : '0'); } if((next_debug_call = HDL_FINDNXT( gui_debug_cpu_state ))) return next_debug_call( pREGS ); return NULL; // (I have no idea why this is a void* func) } /////////////////////////////////////////////////////////////////////////////// // Our Hercules "debug_cd_cmd" hook... // // The following function is called by the 'cd_cmd' panel command to notify // the GUI of what the new current directory was just changed to... void* gui_debug_cd_cmd( char* pszCWD ) { ASSERT( pszCWD ); if (gui_version >= 1.12) gui_fprintf( fStatusStream, "]CWD=%s\n", pszCWD ); return NULL; } /////////////////////////////////////////////////////////////////////////////// // Streams 'fprintf' function to prevent interleaving collision problem... LOCK gui_fprintf_lock; void gui_fprintf( FILE* stream, const char* pszFormat, ... ) { va_list vl; va_start( vl, pszFormat ); obtain_lock ( &gui_fprintf_lock ); vfprintf( stream, pszFormat, vl ); fflush( stream ); release_lock( &gui_fprintf_lock ); } /////////////////////////////////////////////////////////////////////////////// // Acquire any resources we need in order to operate... // (called by 'gui_panel_display' before main loop initiates...) void Initialize () { initialize_lock( &gui_fprintf_lock ); // reject any unload attempt gui_nounload = 1; // Initialize streams... fOutputStream = OUTPUT_STREAM_FILE_PTR; fStatusStream = STATUS_STREAM_FILE_PTR; nInputStreamFileNum = fileno( INPUT_STREAM_FILE_PTR ); // Allocate input stream buffer... if (!(pszInputBuff = (char *) malloc( nInputBuffSize ))) { fprintf(stderr, _("HHCDG006S malloc pszInputBuff failed: %s\n") ,strerror(errno)); exit(0); } memset(pszInputBuff,0,nInputBuffSize); nInputLen = 0; // Allocate command processing buffer... if (!(pszCommandBuff = (char *) malloc( nCommandBuffSize ))) { fprintf(stderr, _("HHCDG007S malloc pszCommandBuff failed: %s\n") ,strerror(errno)); exit(0); } memset(pszCommandBuff,0,nCommandBuffSize); nCommandLen = 0; // Initialize some variables... HandleForcedRefresh(); } /////////////////////////////////////////////////////////////////////////////// // Release any resources we acquired in order to operate... // (called by 'gui_panel_display' when main loop terminates...) void Cleanup() { if (pszInputBuff) free(pszInputBuff); if (pszCommandBuff) free(pszCommandBuff); } /////////////////////////////////////////////////////////////////////////////// // Hercules "daemon_task" -or- "panel_display" override... void gui_panel_display () { static char *DisQuietCmd[] = { "$zapcmd", "quiet", "NoCmd" }; SET_THREAD_NAME("dyngui"); ProcessConfigCommand(3,DisQuietCmd,NULL); // Disable the quiet command if ( !bDoneProcessing ) { logmsg(_("HHCDG001I dyngui.dll initiated\n")); Initialize(); // (allocate buffers, etc) ProcessingLoop(); // (primary processing loop) logmsg(_("HHCDG002I dyngui.dll terminated\n")); Cleanup(); // (de-allocate resources) } } /*****************************************************************************\ Hercules Dynamic Loader control sections... \*****************************************************************************/ /* Note that ALL of the below "sections" are actually just simple functions that Hercules's dynamic loader logic calls, thus allowing you to insert whatever 'C' code you may need directly into any of the below sections. */ /////////////////////////////////////////////////////////////////////////////// // HDL_DEPENDENCY_SECTION // The following are the various Hercules structures whose layout this module // depends on. The layout of the following structures (size and version) MUST // match the layout that was used to build Hercules with. If the size/version // of any of the following structures changes (and a new version of Hercules // is built using the new layout), then THIS module must also be built with // the new layout as well. The layout (size/version) of the structure as it // was when Hercules was built MUST MATCH the layout as it was when THIS DLL // was built) /* Libtool static name colision resolution */ /* note : lt_dlopen will look for symbol & modulename_LTX_symbol */ #if !defined(HDL_BUILD_SHARED) && defined(HDL_USE_LIBTOOL) #define hdl_ddev dyngui_LTX_hdl_ddev #define hdl_depc dyngui_LTX_hdl_depc #define hdl_reso dyngui_LTX_hdl_reso #define hdl_init dyngui_LTX_hdl_init #define hdl_fini dyngui_LTX_hdl_fini #endif HDL_DEPENDENCY_SECTION; HDL_DEPENDENCY ( HERCULES ); // hercules itself HDL_DEPENDENCY ( SYSBLK ); // master control block HDL_DEPENDENCY ( REGS ); // cpu regs and such HDL_DEPENDENCY ( DEVBLK ); // device info block END_DEPENDENCY_SECTION /////////////////////////////////////////////////////////////////////////////// // HDL_REGISTER_SECTION // The following section defines the entry points within Hercules that THIS // module is overriding (replacing). That is to say, THIS module's functions // will be called by Hercules instead of the normal Hercules function (if any). // The functions defined below thus provide additional/different functionality // above/beyond the functionality normally provided by Hercules. (Of course, // yet OTHER dlls may have further overridden whatever overrides we register // here, such as would likely be the case for panel command overrides). HDL_REGISTER_SECTION; // ("Register" our entry-points) // Hercules's Our // registered overriding // entry-point entry-point // name value HDL_REGISTER ( panel_display, gui_panel_display );// (Yep! We override EITHER!) HDL_REGISTER ( daemon_task, gui_panel_display );// (Yep! We override EITHER!) HDL_REGISTER ( debug_cpu_state, gui_debug_cpu_state ); HDL_REGISTER ( debug_cd_cmd, gui_debug_cd_cmd ); HDL_REGISTER ( panel_command, gui_panel_command ); END_REGISTER_SECTION #if defined( WIN32 ) && !defined( HDL_USE_LIBTOOL ) #if !defined( _MSVC_ ) #undef sysblk #endif /////////////////////////////////////////////////////////////////////////////// // HDL_RESOLVER_SECTION // The following section "resolves" entry-points that this module needs. The // below HDL_RESOLVE entries define the names of Hercules's registered entry- // points that we need "imported" to us (so that we may call those functions // directly ourselves). The HDL_RESOLVE_PTRVAR entries set the named pointer // variable value (i.e. the name of OUR pointer variable) to the registered // entry-point value that was registered by Hercules or some other DLL. HDL_RESOLVER_SECTION; // ("Resolve" needed entry-points) // Registered // entry-points // that we call HDL_RESOLVE ( panel_command ); #if !defined( _MSVC_ ) // Our pointer- Registered entry- // variable name point value name HDL_RESOLVE_PTRVAR ( psysblk, sysblk ); #endif END_RESOLVER_SECTION #endif /////////////////////////////////////////////////////////////////////////////// // HDL_FINAL_SECTION // The following section defines what should be done immediately before this // module is unloaded. It is nothing more than a function that is called by // Hercules just before your module is unloaded. You can do anything you want // but the normal thing to do is release any resources that were acquired when // your module was loaded (e.g. release memory that was malloc'ed, etc). HDL_FINAL_SECTION; { bDoneProcessing = TRUE; // (tell main loop to stop processing) usleep(100000); // (brief delay to give GUI time // to display ALL shutdown msgs) return gui_nounload; // (reject unloads when activated) } END_FINAL_SECTION /////////////////////////////////////////////////////////////////////////////// #endif /*defined(OPTION_DYNAMIC_LOAD)*/ #endif // EXTERNALGUI hercules-3.07/dyninst.c000644 000765 000765 00000034734 11143760543 016616 0ustar00jmaynardjmaynard000000 000000 /* DYNINST.C (c) Copyright Jan Jaeger, 2003-2009 */ /* Hercules Dynamic Loader */ // $Id: dyninst.c 5125 2009-01-23 12:01:44Z bernard $ /* This module dynamically loads instructions. Instruction routine */ /* names must be registered under the name of s370_opcode_B220 for */ /* example, where s370 may also be s390 or z900 for ESA/390 or ESAME */ /* mode respectively. B220 is the opcode, and is depending on the */ /* instruction 2 3 or 4 digits. */ // $Log$ // Revision 1.24 2008/02/29 15:53:10 rbowler // Instruction decoder for C4xx and C6xx instructions // // Revision 1.23 2008/02/29 12:05:06 rbowler // dyninst.c incorrect restore of C8xx opcodes // // Revision 1.22 2007/06/23 00:04:09 ivan // Update copyright notices to include current year (2007) // // Revision 1.21 2006/12/08 09:43:20 jj // Add CVS message log // #include "hstdinc.h" #include "hercules.h" #if defined(OPTION_DYNAMIC_LOAD) #if defined(WIN32) && !defined(HDL_USE_LIBTOOL) && !defined(_MSVC_) /* We need to do some special tricks for windows here, since windows */ /* does not support backlink and we need to resolve symbols during */ /* dll initialisation (REGISTER/RESOLVER). Opcode tables are renamed */ /* such that no naming conflicts occur. */ #define copy_opcode_tables copy_opcode_tables_r #define opcode_table opcode_table_r #define opcode_01xx opcode_01xx_r #define opcode_a5xx opcode_a5xx_r #define opcode_a4xx opcode_a4xx_r #define opcode_a7xx opcode_a1xx_r #define opcode_b2xx opcode_b2xx_r #define opcode_b3xx opcode_b3xx_r #define opcode_b9xx opcode_b9xx_r #define opcode_c0xx opcode_c0xx_r #define opcode_c2xx opcode_c2xx_r #define opcode_c4xx opcode_c4xx_r /*208*/ #define opcode_c6xx opcode_c6xx_r /*208*/ #define opcode_c8xx opcode_c8xx_r #define opcode_e3xx opcode_e3xx_r #define opcode_e5xx opcode_e5xx_r #define opcode_e6xx opcode_e6xx_r #define opcode_ebxx opcode_ebxx_r #define opcode_ecxx opcode_ecxx_r #define opcode_edxx opcode_edxx_r #endif #include "opcode.h" #if defined(WIN32) && !defined(HDL_USE_LIBTOOL) && !defined(_MSVC_) #undef copy_opcode_tables #undef opcode_table #undef opcode_01xx #undef opcode_a5xx #undef opcode_a4xx #undef opcode_a7xx #undef opcode_b2xx #undef opcode_b3xx #undef opcode_b9xx #undef opcode_c0xx #undef opcode_c2xx #undef opcode_c4xx /*208*/ #undef opcode_c6xx /*208*/ #undef opcode_c8xx #undef opcode_e3xx #undef opcode_e5xx #undef opcode_e6xx #undef opcode_ebxx #undef opcode_ecxx #undef opcode_edxx #endif #include "inline.h" #if !defined(_GEN_ARCH) #if defined(_ARCHMODE2) #define _GEN_ARCH _ARCHMODE2 #include "dyninst.c" #endif #if defined(_ARCHMODE3) #undef _GEN_ARCH #define _GEN_ARCH _ARCHMODE3 #include "dyninst.c" #endif static zz_func save_table[256][GEN_MAXARCH]; static zz_func save_01xx[256][GEN_MAXARCH]; #if defined (FEATURE_VECTOR_FACILITY) static zz_func save_a4xx[256][GEN_MAXARCH]; #endif static zz_func save_a5xx[16][GEN_MAXARCH]; static zz_func save_a7xx[16][GEN_MAXARCH]; static zz_func save_b2xx[256][GEN_MAXARCH]; static zz_func save_b3xx[256][GEN_MAXARCH]; static zz_func save_b9xx[256][GEN_MAXARCH]; static zz_func save_c0xx[16][GEN_MAXARCH]; static zz_func save_c2xx[16][GEN_MAXARCH]; /*@Z9*/ static zz_func save_c4xx[16][GEN_MAXARCH]; /*208*/ static zz_func save_c6xx[16][GEN_MAXARCH]; /*208*/ static zz_func save_c8xx[16][GEN_MAXARCH]; static zz_func save_e3xx[256][GEN_MAXARCH]; static zz_func save_e5xx[256][GEN_MAXARCH]; static zz_func save_e6xx[256][GEN_MAXARCH]; static zz_func save_ebxx[256][GEN_MAXARCH]; static zz_func save_ecxx[256][GEN_MAXARCH]; static zz_func save_edxx[256][GEN_MAXARCH]; #if defined(WIN32) && !defined(HDL_USE_LIBTOOL) && !defined(_MSVC_) static int opcodes_saved; static void copy_opcode_tables (); static void * opcode_table; static void * opcode_01xx; #if defined (FEATURE_VECTOR_FACILITY) static void * opcode_a4xx; #endif static void * opcode_a5xx; static void * opcode_a7xx; static void * opcode_b2xx; static void * opcode_b3xx; static void * opcode_b9xx; static void * opcode_c0xx; static void * opcode_c2xx; /*@Z9*/ static void * opcode_c4xx; /*208*/ static void * opcode_c6xx; /*208*/ static void * opcode_c8xx; static void * opcode_e3xx; static void * opcode_e5xx; static void * opcode_e6xx; static void * opcode_ebxx; static void * opcode_ecxx; static void * opcode_edxx; #endif static char *prefix[] = { #if defined(_370) "s370_dyninst_opcode_", #endif #if defined(_390) "s390_dyninst_opcode_", #endif #if defined(_900) "z900_dyninst_opcode_" #endif }; static void opcode_save() { memcpy(save_table,opcode_table,sizeof(save_table)); memcpy(save_01xx,opcode_01xx,sizeof(save_01xx)); #if defined (FEATURE_VECTOR_FACILITY) memcpy(save_a4xx,opcode_a4xx,sizeof(save_a4xx)); #endif memcpy(save_a5xx,opcode_a5xx,sizeof(save_a5xx)); memcpy(save_a7xx,opcode_a7xx,sizeof(save_a7xx)); memcpy(save_b2xx,opcode_b2xx,sizeof(save_b2xx)); memcpy(save_b3xx,opcode_b3xx,sizeof(save_b3xx)); memcpy(save_b9xx,opcode_b9xx,sizeof(save_b9xx)); memcpy(save_c0xx,opcode_c0xx,sizeof(save_c0xx)); memcpy(save_c2xx,opcode_c2xx,sizeof(save_c2xx)); /*@Z9*/ memcpy(save_c4xx,opcode_c4xx,sizeof(save_c4xx)); /*208*/ memcpy(save_c6xx,opcode_c6xx,sizeof(save_c6xx)); /*208*/ memcpy(save_c8xx,opcode_c8xx,sizeof(save_c8xx)); memcpy(save_e3xx,opcode_e3xx,sizeof(save_e3xx)); memcpy(save_e5xx,opcode_e5xx,sizeof(save_e5xx)); memcpy(save_e6xx,opcode_e6xx,sizeof(save_e6xx)); memcpy(save_ebxx,opcode_ebxx,sizeof(save_ebxx)); memcpy(save_ecxx,opcode_ecxx,sizeof(save_ecxx)); memcpy(save_edxx,opcode_edxx,sizeof(save_edxx)); } static void opcode_restore() { memcpy(opcode_table,save_table,sizeof(save_table)); memcpy(opcode_01xx,save_01xx,sizeof(save_01xx)); #if defined (FEATURE_VECTOR_FACILITY) memcpy(opcode_a4xx,save_a4xx,sizeof(save_a4xx)); #endif memcpy(opcode_a5xx,save_a5xx,sizeof(save_a5xx)); memcpy(opcode_a7xx,save_a7xx,sizeof(save_a7xx)); memcpy(opcode_b2xx,save_b2xx,sizeof(save_b2xx)); memcpy(opcode_b3xx,save_b3xx,sizeof(save_b3xx)); memcpy(opcode_b9xx,save_b9xx,sizeof(save_b9xx)); memcpy(opcode_c0xx,save_c0xx,sizeof(save_c0xx)); memcpy(opcode_c2xx,save_c2xx,sizeof(save_c2xx)); /*@Z9*/ memcpy(opcode_c4xx,save_c4xx,sizeof(save_c4xx)); /*208*/ memcpy(opcode_c6xx,save_c6xx,sizeof(save_c6xx)); /*208*/ memcpy(opcode_c8xx,save_c8xx,sizeof(save_c8xx)); memcpy(opcode_e3xx,save_e3xx,sizeof(save_e3xx)); memcpy(opcode_e5xx,save_e5xx,sizeof(save_e5xx)); memcpy(opcode_e6xx,save_e6xx,sizeof(save_e6xx)); memcpy(opcode_ebxx,save_ebxx,sizeof(save_ebxx)); memcpy(opcode_ecxx,save_ecxx,sizeof(save_ecxx)); memcpy(opcode_edxx,save_edxx,sizeof(save_edxx)); } static void assign_extop1(int opcode, int extop, zz_func table[256][GEN_MAXARCH], zz_func saved[256][GEN_MAXARCH]) { int arch; void *tmp; for(arch = 0; arch < GEN_MAXARCH - 2; arch++) { char name[32]; sprintf(name,"%s%02X%1X",prefix[arch],opcode,extop); if((tmp = HDL_FINDSYM(name))) table[extop][arch] = tmp; else table[extop][arch] = saved[extop][arch]; } } static void assign_extop(int opcode, int extop, zz_func table[256][GEN_MAXARCH], zz_func saved[256][GEN_MAXARCH]) { int arch; void *tmp; for(arch = 0; arch < GEN_MAXARCH - 2; arch++) { char name[32]; sprintf(name,"%s%02X%02X",prefix[arch],opcode,extop); if((tmp = HDL_FINDSYM(name))) table[extop][arch] = tmp; else table[extop][arch] = saved[extop][arch]; } } static void assign_opcode(int opcode, zz_func table[256][GEN_MAXARCH], zz_func saved[256][GEN_MAXARCH]) { int arch; void *tmp; for(arch = 0; arch < GEN_MAXARCH - 2; arch++) { char name[32]; sprintf(name,"%s%02X",prefix[arch],opcode); if((tmp = HDL_FINDSYM(name))) table[opcode][arch] = tmp; else table[opcode][arch] = saved[opcode][arch]; } } static inline void copy_opcode(zz_func to_table[256], zz_func from_table[256][GEN_MAXARCH], int opcode, int arch_mode) { to_table[opcode] = from_table[opcode][arch_mode]; } /* Libtool static name colision resolution */ /* note : lt_dlopen will look for symbol & modulename_LTX_symbol */ #if !defined(HDL_BUILD_SHARED) && defined(HDL_USE_LIBTOOL) #define hdl_ddev dyninst_LTX_hdl_ddev #define hdl_depc dyninst_LTX_hdl_depc #define hdl_reso dyninst_LTX_hdl_reso #define hdl_init dyninst_LTX_hdl_init #define hdl_fini dyninst_LTX_hdl_fini #endif HDL_DEPENDENCY_SECTION; { HDL_DEPENDENCY (HERCULES); HDL_DEPENDENCY (REGS); HDL_DEPENDENCY (DEVBLK); HDL_DEPENDENCY (SYSBLK); } END_DEPENDENCY_SECTION HDL_REGISTER_SECTION; { #if defined(WIN32) && !defined(HDL_USE_LIBTOOL) && !defined(_MSVC_) opcodes_saved = 0; #else opcode_save(); #endif } END_REGISTER_SECTION HDL_RESOLVER_SECTION; { int opcode, extop; #if 0 #if defined(WIN32) && !defined(HDL_USE_LIBTOOL) && !defined(_MSVC_) if(!opcodes_saved) { HDL_RESOLVE(copy_opcode_tables); HDL_RESOLVE(opcode_table); HDL_RESOLVE(opcode_01xx); #if defined(FEATURE_VECTOR_FACILITY) HDL_RESOLVE(opcode_a4xx); #endif HDL_RESOLVE(opcode_a5xx); HDL_RESOLVE(opcode_a7xx); HDL_RESOLVE(opcode_b2xx); HDL_RESOLVE(opcode_b3xx); HDL_RESOLVE(opcode_b9xx); HDL_RESOLVE(opcode_c0xx); HDL_RESOLVE(opcode_c2xx); /*@Z9*/ HDL_RESOLVE(opcode_c4xx); /*208*/ HDL_RESOLVE(opcode_c6xx); /*208*/ HDL_RESOLVE(opcode_c8xx); HDL_RESOLVE(opcode_e3xx); HDL_RESOLVE(opcode_e5xx); HDL_RESOLVE(opcode_e6xx); HDL_RESOLVE(opcode_ebxx); HDL_RESOLVE(opcode_ecxx); HDL_RESOLVE(opcode_edxx); opcode_save(); opcodes_saved = 1; } #endif #endif for(opcode = 0; opcode < 256; opcode++) { switch(opcode) { case 0x01: for(extop = 0; extop < 256; extop++) assign_extop(opcode, extop, opcode_01xx, save_01xx); break; #if defined (FEATURE_VECTOR_FACILITY) case 0xA4: for(extop = 0; extop < 256; extop++) assign_extop(opcode, extop, v_opcode_a4xx, save_a4xx); break; #endif case 0xA5: for(extop = 0; extop < 16; extop++) assign_extop1(opcode, extop, opcode_a5xx, save_a5xx); break; case 0xA7: for(extop = 0; extop < 16; extop++) assign_extop1(opcode, extop, opcode_a7xx, save_a7xx); break; case 0xB2: for(extop = 0; extop < 256; extop++) assign_extop(opcode, extop, opcode_b2xx, save_b2xx); break; case 0xB3: for(extop = 0; extop < 256; extop++) assign_extop(opcode, extop, opcode_b3xx, save_b3xx); break; case 0xB9: for(extop = 0; extop < 256; extop++) assign_extop(opcode, extop, opcode_b9xx, save_b9xx); break; case 0xC0: for(extop = 0; extop < 16; extop++) assign_extop1(opcode, extop, opcode_c0xx, save_c0xx); break; case 0xC2: /*@Z9*/ for(extop = 0; extop < 16; extop++) /*@Z9*/ assign_extop1(opcode, extop, opcode_c2xx, save_c2xx); /*@Z9*/ break; /*@Z9*/ case 0xC4: /*208*/ for(extop = 0; extop < 16; extop++) /*208*/ assign_extop1(opcode, extop, opcode_c4xx, save_c4xx); /*208*/ break; /*208*/ case 0xC6: /*208*/ for(extop = 0; extop < 16; extop++) /*208*/ assign_extop1(opcode, extop, opcode_c6xx, save_c6xx); /*208*/ break; /*208*/ case 0xC8: for(extop = 0; extop < 16; extop++) assign_extop1(opcode, extop, opcode_c8xx, save_c8xx); break; case 0xE3: for(extop = 0; extop < 256; extop++) assign_extop(opcode, extop, opcode_e3xx, save_e3xx); break; case 0xE5: for(extop = 0; extop < 256; extop++) assign_extop(opcode, extop, opcode_e5xx, save_e5xx); break; case 0xE6: for(extop = 0; extop < 256; extop++) assign_extop(opcode, extop, opcode_e6xx, save_e6xx); break; case 0xEB: for(extop = 0; extop < 256; extop++) assign_extop(opcode, extop, opcode_ebxx, save_ebxx); break; case 0xEC: for(extop = 0; extop < 256; extop++) assign_extop(opcode, extop, opcode_ecxx, save_ecxx); break; case 0xED: for(extop = 0; extop < 256; extop++) assign_extop(opcode, extop, opcode_edxx, save_edxx); break; default: assign_opcode(opcode, opcode_table, save_table); } } /* Copy opcodes to performance shadow tables */ copy_opcode_tables(); } END_RESOLVER_SECTION HDL_FINAL_SECTION; { opcode_restore(); } END_FINAL_SECTION #endif /*!defined(_GEN_ARCH)*/ #endif /*defined(OPTION_DYNAMIC_LOAD)*/ hercules-3.07/dynmake.bat000644 000765 000765 00000031257 11340774747 017111 0ustar00jmaynardjmaynard000000 000000 @REM $Id: dynmake.bat 5642 2010-02-20 02:35:17Z fish $ @if defined TRACEON (@echo on) else (@echo off) REM If this batch file works okay then it was written by Fish. REM If it doesn't work then I don't know who the heck wrote it. ::***************************************************************************** ::***************************************************************************** ::***************************************************************************** ::*** *** ::*** DYNMAKE.BAT *** ::*** *** ::***************************************************************************** ::***************************************************************************** ::***************************************************************************** ::* * ::* Designed to be called either from the command line or by a * ::* Visual Studio makefile project with the "Build command line" * ::* set to: "dynmake.bat ". See 'HELP' section * ::* further below for details regarding use. * ::* * ::***************************************************************************** ::* * ::* PROGRAMMING NOTE * ::* * ::* All error messages *MUST* be issued in the following strict format: * ::* * ::* echo %~nx0^(1^) : error C9999 : error-message-text... * ::* * ::* in order for the Visual Studio IDE to detect it as a build error since * ::* exiting with a non-zero return code doesn't do the trick. Visual Studio * ::* apparently examines the message-text looking for error/warning strings. * ::* * ::***************************************************************************** setlocal pushd . set rc=0 set "TRACE=if defined TRACEON echo" if "%~1" == "" goto :help if "%~1" == "?" goto :help if "%~1" == "/?" goto :help if "%~1" == "-?" goto :help if "%~1" == "--help" goto :help set hercdir=%~dp0 set projdir=%~1 set modname=%~2 set build_type=%~3 set num_cpus=%~4 set extra_nmake_args=%~5 :extra_args if "%~6" == "" goto :begin set extra_nmake_args=%extra_nmake_args% %~6 shift /1 goto :extra_args ::--------------------------------------------------------------------- :: HELP ::--------------------------------------------------------------------- :help set rc=1 echo. echo %~nx0^(1^) : error C9999 : Help information is as follows: echo. echo. echo. echo %~nx0 echo. echo. echo Build script for building a dynamically loadable Hercules plugin echo module. This script performs some necessary pre-processing before echo eventually invoking the main Hercules build script to build your echo dynamic module. echo. echo. echo Format: echo. echo. echo %~nx0 {projdir} {modname} {build_type} {num_cpus} [-a^|clean] echo. echo. echo Where: echo. echo {projdir} The fully qualified path of your dynamic module echo project directory. If the path contains spaces echo enclose it within double quotes. echo. echo {modname} The root filename of your dynamic module (e.g. echo "dyn75"). One word without any spaces in it. echo. echo {build_type} Desired build configuration. Valid values are echo DEBUG or RETAIL for building a 32-bit module, echo DEBUG-X64 or RETAIL-X64 for a 64-bit module echo targeting AMD64 processors, or DEBUG-IA64 or echo RETAIL-IA64 for a 64-bit module targeting the echo Intel Itanium-64 processor. The same value is echo passed back to your optional prebuild.bat and echo or postbld.bat scripts as the 2nd argument. echo. echo {num_cpus} The maximum number of emulated CPUs (NUMCPU=) echo your module supports: 1 to 64. Must be the same echo value that was used to build Hercules with. echo The same value is passed back to you as the echo 3rd parameter to your optional prebuild.bat echo and/or postbld.bat scripts. echo. echo [-a^|clean] Either '-a' to perform a full rebuild of your echo module, or 'clean' to clean the output directory echo of all previously built binaries and work files. echo If not specified then your module is only built echo if it actually needs rebuilding (i.e. only if echo any of your source files changed for example). echo It is HIGHLY RECOMMENDED that you ALWAYS use echo '-a' for any/all "retail" type builds. These echo value(s) you specify here are passed back to echo your optional prebuild.bat and/or postbld.bat echo scripts as the last set of arguments (4 - n). echo. goto :exit ::--------------------------------------------------------------------- :begin echo %~nx0^(1^) : Building dynamic module "%modname%" from "%projdir%"... ::--------------------------------------------------------------------- :: Validate parameters... call :parseargs if %rc% NEQ 0 goto :exit ::--------------------------------------------------------------------- :: Switch immediately to our primary directory... cd /d "%hercdir%" set xcopy_opts=/v /c /r /k /o /x /y ::--------------------------------------------------------------------- :: Create our o/p module building sub-directory... call :isdir %DYNDIR% if not defined # mkdir %DYNDIR% ::--------------------------------------------------------------------- :: Add the dynamic module's sub-directory to the list of directories :: that the compiler uses to resolve #include statements with (which :: 'nmake' also uses to resolve its own !INCLUDE statements with)... set INCLUDE=%INCLUDE%;%hercdir%;%hercdir%%DYNDIR% ::--------------------------------------------------------------------- :: Perform pre-build processing... call :do_callback "prebuild.bat" "pre-build" if %rc% NEQ 0 goto :exit ::--------------------------------------------------------------------- :: Copy the dynamic module's source files from their directory :: over into our module building sub-directory... cd /d %DYNDIR% if exist "%projdir%*.c" xcopy "%projdir%*.c" . %xcopy_opts% > NUL if exist "%projdir%*.h" xcopy "%projdir%*.h" . %xcopy_opts% > NUL if exist "%projdir%*.rc" xcopy "%projdir%*.rc" . %xcopy_opts% > NUL if exist "%projdir%*.rc2" xcopy "%projdir%*.rc2" . %xcopy_opts% > NUL if exist "%projdir%%DYNMOD%.msvc" xcopy "%projdir%%DYNMOD%.msvc" . %xcopy_opts% > NUL cd .. ::--------------------------------------------------------------------- :: Now switch back to the main Hercules source-code directory :: to do the actual build, by calling its main "makefile.bat" cd /d "%hercdir%" call "%hercdir%makefile.bat" "%build_type%" "%hercdir%makefile.msvc" "%num_cpus%" %extra_nmake_args% set rc=%errorlevel% if %rc% NEQ 0 goto :exit ::--------------------------------------------------------------------- :: Perform post-build processing... call :do_callback "postbld.bat" "post-build" if %rc% NEQ 0 goto :exit ::--------------------------------------------------------------------- :: Done! echo %~nx0^(1^) : Build complete. goto :exit ::--------------------------------------------------------------------- :: Restore original directory and environment before exiting... :exit popd endlocal & set rc=%rc% exit /b %rc% ::--------------------------------------------------------------------- :: CALLED SUBROUTINES ::--------------------------------------------------------------------- :parseargs :: Validate hercules directory... call :isdir "%hercdir%" if not defined # ( echo %~nx0^(1^) : error C9999 : hercdir "%hercdir%" not found?! set rc=1 goto :EOF ) :: Validate module name... call :hasblank "%modname%" if defined # goto :bad_modname call :goodfn "%modname%" if not defined # ( :bad_modname echo %~nx0^(1^) : error C9999 : Invalid module name "%modname%" set rc=1 goto :EOF ) :: Specified dynamic module name becomes our work sub-directory. set DYNMOD=%modname% set DYNDIR=%modname%\ :: Validate i/p project directory... call :isdir "%projdir%" if not defined # ( echo %~nx0^(1^) : error C9999 : projdir "%projdir%" not found. set rc=1 goto :EOF ) :: Verify their makefile include exists... call :isfile "%projdir%%DYNMOD%.msvc" if not defined # ( :bad_projdir echo %~nx0^(1^) : error C9999 : makefile include "%projdir%%DYNMOD%.msvc" not found. set rc=1 goto :EOF ) :: Make sure the project directory they specified :: was a fully qualified directory path... set @=%cd% cd /d "%projdir%" call :fullpath "%projdir%%DYNMOD%.msvc" cd /d "%@%" if not defined # goto :bad_projdir if /i not "%#%" == "%projdir%%DYNMOD%.msvc" if /i not "%#%" == "%projdir%\%DYNMOD%.msvc" ( echo %~nx0^(1^) : error C9999 : projdir "%projdir%" not fully qualified. set rc=1 goto :EOF ) :: Everything looks okay... goto :EOF ::--------------------------------------------------------------------- :do_callback set batfile=%~1 set msgtxt=%~2 call :isfile "%projdir%%batfile%" if not defined # goto :EOF echo %~nx0^(1^) : Invoking %msgtxt% processing... cd /d "%projdir%" call "%projdir%%batfile%" "%hercdir%" "%modname%" "%build_type%" "%num_cpus%" %extra_nmake_args% set rc=%errorlevel% cd /d "%hercdir%" if %rc% NEQ 0 echo %~nx0^(1^) : error C9999 : %msgtxt% processing failed. if %rc% EQU 0 echo %~nx0^(1^) : continuing... goto :EOF ::--------------------------------------------------------------------- :hasblank REM %1 = string to check REM # = return code: 1 if contains blank, undefined if not setlocal set @=%~1 set #= for /f "tokens=1*" %%a in ("@%@%@") do if not "%%b" == "" set #=1 endlocal & set #=%#% goto :EOF ::--------------------------------------------------------------------- :goodfn REM %1 = string to check REM # = return code: 1 if good filename, undefined if not setlocal set @=%~1 set #=1 for /f "delims=\/:*?<>|" %%i in ("@%@%@") do if not "%%i" == "@%@%@" set #= endlocal & set #=%#% goto :EOF ::--------------------------------------------------------------------- :isfile REM %1 = file to check REM # = return code: defined if file exists, else undefined set "#=%~a1" if not defined # goto :EOF if "%#:~0,1%" == "-" goto :EOF set "#=" goto :EOF ::--------------------------------------------------------------------- :isdir REM %1 = directory to check REM # = return code: defined if directory exists, else undefined set #=%~a1 if not defined # goto :EOF if "%#:~0,1%" == "d" goto :EOF set "#=" goto :EOF ::--------------------------------------------------------------------- :fullpath REM %1 = filename to check (with or without directory) REM # = returned full path or undefined if not found :: Search the Windows PATH for the file in question and return :: its fully qualified path if found. Otherwise return an empty :: string. Note: the below does not work for directories, only :: files... setlocal set path=.;%path% set #=%~dpnx$PATH:1 endlocal & set #=%#% goto :EOF ::--------------------------------------------------------------------- hercules-3.07/ecpsvm.c000644 000765 000765 00000274576 11143760543 016435 0ustar00jmaynardjmaynard000000 000000 /***********************************************************/ /* HERCULES ECPS:VM Support */ /* (c) Copyright 2003-2009 Roger Bowler and Others */ /* Use of this program is governed by the QPL License */ /* Original Author : Ivan Warren */ /* Prime Maintainer : Ivan Warren */ /***********************************************************/ // $Id: ecpsvm.c 5125 2009-01-23 12:01:44Z bernard $ /***********************************************************/ /* */ /* General guidelines about E6XX instruction class */ /* this is an implementation of ECPS:VM Level 20 */ /* */ /* General rule is : Only do what is safe to do. In doubt, */ /* give control to CP back (and act as */ /* a NO-OP). All instructions have this */ /* behaviour, therefore allowing only */ /* partial implementation, or bypassing */ /* tricky cases */ /* */ /* NOTE : ECPS:VM is only available for S/370 architecture */ /* */ /* In order for CP ASSIST to be active, a CONFIGURATION */ /* statement is added : ECPS:VM lvl|no */ /* lvl is the ASSIST level (20 is recommended) */ /* no means CP ASSIST is disabled (default) */ /* */ /* Currently supported CP ASSIST instructions : */ /* +-----+-------+----------------------------------------+*/ /* |opc | Mnemo | Function |*/ /* +-----+-------+----------------------------------------+*/ /* |E602 | LCKPG | Lock Page in core table |*/ /* |E603 | ULKPG | Unlock page in core table |*/ /* |E608 | TRBRG | LRA + Basic checks on VPAGE |*/ /* |E609 | TRLOK | Same as TRBRG + Lock page in core |*/ /* |E60E | SCNRU | Scan Real Unit control blocks |*/ /* |E612 | STLVL | Store ECPS:VM Level |*/ /* |E614 | FREEX | Allocate CP FREE Storage from subpool |*/ /* |E615 | FRETX | Release CP FREE Storage to subpool |*/ /* +-----+-------+----------------------------------------+*/ /* */ /* Currently supported VM ASSIST instructions : */ /* +-----+-------+----------------------------------------+*/ /* |opc | Mnemo | Function |*/ /* +-----+-------+----------------------------------------+*/ /* |0A | SVC | Virtual SVC Assist |*/ /* |80 | SSM | Virtual SSM Assist |*/ /* |82 | LPSW | Virtual LPSW Assist |*/ /* +-----+-------+----------------------------------------+*/ /* */ /***********************************************************/ // $Log$ // Revision 1.68 2007/06/23 00:04:09 ivan // Update copyright notices to include current year (2007) // // Revision 1.67 2007/01/13 07:18:14 bernard // backout ccmask // // Revision 1.66 2007/01/12 15:22:37 bernard // ccmask phase 1 // // Revision 1.65 2006/12/31 17:53:48 gsmith // 2006 Dec 31 Update ecpsvm.c for new psw IA scheme // // Revision 1.64 2006/12/08 09:43:20 jj // Add CVS message log // #include "hstdinc.h" #if !defined(_HENGINE_DLL_) #define _HENGINE_DLL_ #endif #if !defined(_ECPSVM_C_) #define _ECPSVM_C_ #endif #include "hercules.h" #include "opcode.h" #include "inline.h" #include "ecpsvm.h" #ifdef FEATURE_ECPSVM ECPSVM_CMDENT *ecpsvm_getcmdent(char *cmd); struct _ECPSVM_CPSTATS { ECPSVM_STAT_DCL(SVC); ECPSVM_STAT_DCL(SSM); ECPSVM_STAT_DCL(LPSW); ECPSVM_STAT_DCL(STNSM); ECPSVM_STAT_DCL(STOSM); ECPSVM_STAT_DCL(SIO); ECPSVM_STAT_DCL(VTIMER); ECPSVM_STAT_DCL(STCTL); ECPSVM_STAT_DCL(LCTL); ECPSVM_STAT_DCL(DIAG); ECPSVM_STAT_DCL(IUCV); } ecpsvm_sastats={ ECPSVM_STAT_DEF(SVC), ECPSVM_STAT_DEF(SSM), ECPSVM_STAT_DEF(LPSW), ECPSVM_STAT_DEFU(STNSM), ECPSVM_STAT_DEFU(STOSM), ECPSVM_STAT_DEFU(SIO), ECPSVM_STAT_DEF(VTIMER), ECPSVM_STAT_DEFU(STCTL), ECPSVM_STAT_DEF(LCTL), ECPSVM_STAT_DEFU(DIAG), ECPSVM_STAT_DEFU(IUCV), }; struct _ECPSVM_SASTATS { ECPSVM_STAT_DCL(FREE); ECPSVM_STAT_DCL(FRET); ECPSVM_STAT_DCL(LCKPG); ECPSVM_STAT_DCL(ULKPG); ECPSVM_STAT_DCL(SCNRU); ECPSVM_STAT_DCL(SCNVU); ECPSVM_STAT_DCL(DISP0); ECPSVM_STAT_DCL(DISP1); ECPSVM_STAT_DCL(DISP2); ECPSVM_STAT_DCL(DNCCW); ECPSVM_STAT_DCL(DFCCW); ECPSVM_STAT_DCL(FCCWS); ECPSVM_STAT_DCL(CCWGN); ECPSVM_STAT_DCL(UXCCW); ECPSVM_STAT_DCL(TRBRG); ECPSVM_STAT_DCL(TRLOK); ECPSVM_STAT_DCL(VIST); ECPSVM_STAT_DCL(VIPT); ECPSVM_STAT_DCL(STEVL); ECPSVM_STAT_DCL(FREEX); ECPSVM_STAT_DCL(FRETX); ECPSVM_STAT_DCL(PMASS); ECPSVM_STAT_DCL(LCSPG); } ecpsvm_cpstats={ ECPSVM_STAT_DEFU(FREE), ECPSVM_STAT_DEFU(FRET), ECPSVM_STAT_DEF(LCKPG), ECPSVM_STAT_DEF(ULKPG), ECPSVM_STAT_DEF(SCNRU), ECPSVM_STAT_DEF(SCNVU), ECPSVM_STAT_DEF(DISP0), ECPSVM_STAT_DEF(DISP1), ECPSVM_STAT_DEF(DISP2), ECPSVM_STAT_DEFU(DNCCW), ECPSVM_STAT_DEFU(DFCCW), ECPSVM_STAT_DEFU(FCCWS), ECPSVM_STAT_DEFU(CCWGN), ECPSVM_STAT_DEFU(UXCCW), ECPSVM_STAT_DEF(TRBRG), ECPSVM_STAT_DEF(TRLOK), ECPSVM_STAT_DEFU(VIST), ECPSVM_STAT_DEFU(VIPT), ECPSVM_STAT_DEF(STEVL), ECPSVM_STAT_DEF(FREEX), ECPSVM_STAT_DEF(FRETX), ECPSVM_STAT_DEFU(PMASS), ECPSVM_STAT_DEFU(LCSPG), }; #define DEBUG_CPASSIST #define DEBUG_SASSIST #define DODEBUG_ASSIST(_cond,x) \ { \ if((_cond)) \ { \ x; \ }\ } #if defined(DEBUG_SASSIST) #define DEBUG_SASSISTX(_inst,x) \ { \ DODEBUG_ASSIST(ecpsvm_sastats._inst.debug,x) \ } #else #define DEBUG_SASSISTX(_cond,x) #endif #if defined(DEBUG_CPASSIST) #define DEBUG_CPASSISTX(_inst,x) \ { \ DODEBUG_ASSIST(ecpsvm_cpstats._inst.debug,x) \ } #else #define DEBUG_CPASSISTX(_cond,x) #endif /* Utility macros because I am very lazy */ #define EVM_IC( x ) ARCH_DEP(vfetchb) ( ( ( x ) & ADDRESS_MAXWRAP(regs) ) , USE_REAL_ADDR , regs ) #define EVM_LH( x ) ARCH_DEP(vfetch2) ( ( ( x ) & ADDRESS_MAXWRAP(regs) ) , USE_REAL_ADDR , regs ) #define EVM_L( x ) ARCH_DEP(vfetch4) ( ( ( x ) & ADDRESS_MAXWRAP(regs) ) , USE_REAL_ADDR , regs ) #define EVM_LD( x ) ARCH_DEP(vfetch8) ( ( ( x ) & ADDRESS_MAXWRAP(regs) ) , USE_REAL_ADDR , regs ) #define EVM_STD( x , y ) ARCH_DEP(vstore8) ( ( x ) , ( ( y ) & ADDRESS_MAXWRAP(regs) ) , USE_REAL_ADDR , regs ) #define EVM_ST( x , y ) ARCH_DEP(vstore4) ( ( x ) , ( ( y ) & ADDRESS_MAXWRAP(regs) ) , USE_REAL_ADDR , regs ) #define EVM_STH( x , y ) ARCH_DEP(vstore2) ( ( x ) , ( ( y ) & ADDRESS_MAXWRAP(regs) ) , USE_REAL_ADDR , regs ) #define EVM_STC( x , y ) ARCH_DEP(vstoreb) ( ( x ) , ( ( y ) & ADDRESS_MAXWRAP(regs) ) , USE_REAL_ADDR , regs ) #define EVM_MVC( x , y , z ) ARCH_DEP(vfetchc) ( ( x ) , ( z ) , ( y ) , USE_REAL_ADDR , regs ) #define BR14 UPD_PSW_IA(regs, regs->GR_L(14)) #define INITPSEUDOIP(_regs) \ do { \ (_regs).ip=(BYTE*)"\0\0"; \ } while(0) #define INITPSEUDOREGS(_regs) \ do { \ memset(&(_regs),0,sysblk.regs_copy_len); \ INITPSEUDOIP((_regs)); \ } while(0) #define CPASSIST_HIT(_stat) ecpsvm_cpstats._stat.hit++ #define SASSIST_HIT(_stat) ecpsvm_sastats._stat.hit++ #define SASSIST_LPSW(_regs) \ do { \ SET_PSW_IA(&(_regs)); \ UPD_PSW_IA(regs, _regs.psw.IA); \ regs->psw.cc=_regs.psw.cc; \ regs->psw.pkey=_regs.psw.pkey; \ regs->psw.progmask=_regs.psw.progmask; \ } \ while(0) #define SASSIST_PROLOG( _instname) \ VADR amicblok; \ VADR vpswa; \ BYTE *vpswa_p; \ REGS vpregs; \ BYTE micpend; \ U32 CR6; \ ECPSVM_MICBLOK micblok; \ BYTE micevma; \ BYTE micevma2; \ BYTE micevma3; \ BYTE micevma4; \ if(SIE_STATE(regs)) \ return(1); \ if(!PROBSTATE(®s->psw)) \ { \ return(1); \ } \ if(!sysblk.ecpsvm.available) \ { \ DEBUG_SASSISTX(_instname,logmsg(_("HHCEV300D : SASSIST "#_instname" ECPS:VM Disabled in configuration\n"))); \ return(1); \ } \ if(!ecpsvm_sastats._instname.enabled) \ { \ DEBUG_SASSISTX(_instname,logmsg(_("HHCEV300D : SASSIST "#_instname" ECPS:VM Disabled by command\n"))); \ return(1); \ } \ CR6=regs->CR_L(6); \ regs->ecps_vtmrpt = NULL; /* Assume vtimer off until validated */ \ if(!(CR6 & ECPSVM_CR6_VMASSIST)) \ { \ DEBUG_SASSISTX(_instname,logmsg(_("HHCEV300D : EVMA Disabled by guest\n"))); \ return(1); \ } \ /* Increment call now (don't count early misses) */ \ ecpsvm_sastats._instname.call++; \ amicblok=CR6 & ECPSVM_CR6_MICBLOK; \ /* Ensure MICBLOK resides on a single 2K page */ \ /* Then set ref bit by calling LOG_TO_ABS */ \ if((amicblok & 0x007ff) > 0x7e0) \ { \ DEBUG_SASSISTX(_instname,logmsg(_("HHCEV300D : SASSIST "#_instname" Micblok @ %6.6X crosses page frame\n"),amicblok)); \ return(1); \ } \ /* Load the micblok copy */ \ micblok.MICRSEG=EVM_L(amicblok); \ micblok.MICCREG=EVM_L(amicblok+4); \ micblok.MICVPSW=EVM_L(amicblok+8); \ micblok.MICWORK=EVM_L(amicblok+12); \ micblok.MICVTMR=EVM_L(amicblok+16); \ micblok.MICACF=EVM_L(amicblok+20); \ micpend=(micblok.MICVPSW >> 24); \ vpswa=micblok.MICVPSW & ADDRESS_MAXWRAP(regs); \ micevma=(micblok.MICACF >> 24); \ micevma2=((micblok.MICACF & 0x00ff0000) >> 16); \ micevma3=((micblok.MICACF & 0x0000ff00) >> 8); \ micevma4=(micblok.MICACF & 0x000000ff); \ if((CR6 & ECPSVM_CR6_VIRTTIMR)) \ { \ regs->ecps_vtmrpt = MADDR(micblok.MICVTMR,USE_REAL_ADDR,regs,ACCTYPE_READ,0); \ } \ /* Set ref bit on page where Virtual PSW is stored */ \ vpswa_p=MADDR(vpswa,USE_REAL_ADDR,regs,ACCTYPE_READ,0); \ DEBUG_SASSISTX(_instname,logmsg(_("HHCEV300D : SASSIST "#_instname" VPSWA= %8.8X Virtual "),vpswa)); \ DEBUG_SASSISTX(_instname,logmsg(_("HHCEV300D : SASSIST "#_instname" CR6= %8.8X\n"),CR6)); \ DEBUG_SASSISTX(_instname,logmsg(_("HHCEV300D : SASSIST "#_instname" MICVTMR= %8.8X\n"),micblok.MICVTMR)); \ DEBUG_SASSISTX(_instname,logmsg(_("HHCEV300D : SASSIST "#_instname" Real "))); \ DEBUG_SASSISTX(_instname,display_psw(regs)); \ /* Load the Virtual PSW in a temporary REGS structure */ \ INITPSEUDOREGS(vpregs); \ ARCH_DEP(load_psw) (&vpregs,vpswa_p); \ DEBUG_SASSISTX(_instname,display_psw(&vpregs)); \ #define ECPSVM_PROLOG(_inst) \ int b1, b2; \ VADR effective_addr1, \ effective_addr2; \ SSE(inst, regs, b1, effective_addr1, b2, effective_addr2); \ PRIV_CHECK(regs); \ SIE_INTERCEPT(regs); \ if(!sysblk.ecpsvm.available) \ { \ DEBUG_CPASSISTX(_inst,logmsg(_("HHCEV300D : CPASSTS "#_inst" ECPS:VM Disabled in configuration "))); \ ARCH_DEP(program_interrupt) (regs, PGM_OPERATION_EXCEPTION); \ } \ PRIV_CHECK(regs); /* No problem state please */ \ if(!ecpsvm_cpstats._inst.enabled) \ { \ DEBUG_CPASSISTX(_inst,logmsg(_("HHCEV300D : CPASSTS "#_inst" Disabled by command"))); \ return; \ } \ if(!(regs->CR_L(6) & 0x02000000)) \ { \ return; \ } \ ecpsvm_cpstats._inst.call++; \ DEBUG_CPASSISTX(_inst,logmsg(_("HHCEV300D : "#_inst" called\n"))); /* DISPx Utility macros */ #define STPT(_x) \ { \ EVM_STD(cpu_timer(regs),_x); \ } #define SPT(_x) \ { \ set_cpu_timer(regs,EVM_LD(_x)); \ OBTAIN_INTLOCK(regs); \ if(CPU_TIMER(regs) < 0) \ { \ ON_IC_PTIMER(regs); \ } \ else \ { \ OFF_IC_PTIMER(regs); \ } \ RELEASE_INTLOCK(regs); \ } #define CHARGE_STOP(_x) \ { \ STPT(_x+VMTTIME); \ } #define CHARGE_START(_x) \ { \ SPT(_x+VMTTIME); \ } #define CHARGE_SWITCH(_x,_y) \ { \ CHARGE_STOP(_x); \ CHARGE_START(_y); \ (_x)=(_y); \ } int ecpsvm_do_fretx(REGS *regs,VADR block,U16 numdw,VADR maxsztbl,VADR fretl); /* CPASSIST FREE (Basic) Not supported */ /* This is part of ECPS:VM Level 18 and 19 */ /* ECPS:VM Level 20 use FREEX */ DEF_INST(ecpsvm_basic_freex) { ECPSVM_PROLOG(FREE); } /* CPASSIST FRET (Basic) Not supported */ /* This is part of ECPS:VM Level 18 and 19 */ /* ECPS:VM Level 20 use FRETX */ DEF_INST(ecpsvm_basic_fretx) { ECPSVM_PROLOG(FRET); } /* Lockpage common code (LCKPG/TRLOK) */ static void ecpsvm_lockpage1(REGS *regs,RADR cortab,RADR pg) { BYTE corcode; VADR corte; U32 lockcount; RADR cortbl; DEBUG_CPASSISTX(LCKPG,logmsg(_("HHCEV300D : LKPG coreptr = "F_RADR" Frame = "F_RADR"\n"),cortab,pg)); cortbl=EVM_L(cortab); corte=cortbl+((pg & 0xfff000)>>8); DEBUG_CPASSISTX(LCKPG,logmsg(_("HHCEV300D : LKPG corete = %6.6X\n"),corte)); corcode=EVM_IC(corte+8); if(corcode & 0x80) { lockcount=EVM_L(corte+4); lockcount++; } else { lockcount=1; corcode|=0x80; EVM_STC(corcode,corte+8); } EVM_ST(lockcount,corte+4); DEBUG_CPASSISTX(LCKPG,logmsg(_("HHCEV300D : LKPG Page locked. Count = %6.6X\n"),lockcount)); return; } /* E602 LCKPG Instruction */ /* LCKPG D1(R1,B1),D2(R2,B2) */ /* 1st operand : PTR_PL -> Address of coretable */ /* 2nd Operand : Page address to be locked */ DEF_INST(ecpsvm_lock_page) { VADR ptr_pl; VADR pg; ECPSVM_PROLOG(LCKPG); ptr_pl=effective_addr1; pg=effective_addr2; DEBUG_CPASSISTX(LCKPG,logmsg(_("HHCEV300D : LKPG PAGE=%6.6X, PTRPL=%6.6X\n"),pg,ptr_pl)); ecpsvm_lockpage1(regs,ptr_pl,pg); regs->psw.cc=0; BR14; CPASSIST_HIT(LCKPG); return; } /* E603 ULKPG Instruction */ /* ULKPG D1(R1,B1),D2(R2,B2) */ /* 1st operand : PTR_PL -> +0 - Maxsize, +4 Coretable */ /* 2nd Operand : Page address to be unlocked */ DEF_INST(ecpsvm_unlock_page) { VADR ptr_pl; VADR pg; VADR corsz; VADR cortbl; VADR corte; BYTE corcode; U32 lockcount; ECPSVM_PROLOG(ULKPG); ptr_pl=effective_addr1; pg=effective_addr2; DEBUG_CPASSISTX(ULKPG,logmsg(_("HHCEV300D : ULKPG PAGE=%6.6X, PTRPL=%6.6X\n"),pg,ptr_pl)); corsz=EVM_L(ptr_pl); cortbl=EVM_L(ptr_pl+4); if((pg+4095)>corsz) { DEBUG_CPASSISTX(ULKPG,logmsg(_("HHCEV300D : ULKPG Page beyond core size of %6.6X\n"),corsz)); return; } corte=cortbl+((pg & 0xfff000)>>8); corcode=EVM_IC(corte+8); if(corcode & 0x80) { lockcount=EVM_L(corte+4); lockcount--; } else { DEBUG_CPASSISTX(ULKPG,logmsg(_("HHCEV300D : ULKPG Attempting to unlock page that is not locked\n"))); return; } if(lockcount==0) { corcode &= ~(0x80|0x02); EVM_STC(corcode,corte+8); DEBUG_CPASSISTX(ULKPG,logmsg(_("HHCEV300D : ULKPG now unlocked\n"))); } else { DEBUG_CPASSISTX(ULKPG,logmsg(_("HHCEV300D : ULKPG Page still locked. Count = %6.6X\n"),lockcount)); } EVM_ST(lockcount,corte+4); CPASSIST_HIT(ULKPG); BR14; return; } /* DNCCW : Not supported */ DEF_INST(ecpsvm_decode_next_ccw) { ECPSVM_PROLOG(DNCCW); } /* FCCWS : Not supported */ DEF_INST(ecpsvm_free_ccwstor) { ECPSVM_PROLOG(FCCWS); } /* SCNVU : Scan for Virtual Device blocks */ DEF_INST(ecpsvm_locate_vblock) { U32 vdev; U32 vchix; U32 vcuix; U32 vdvix; VADR vchtbl; VADR vch; VADR vcu; VADR vdv; ECPSVM_PROLOG(SCNVU); vdev=regs->GR_L(1); vchtbl=effective_addr1; vchix=EVM_LH(vchtbl+((vdev & 0xf00)>>7)); /* Get Index */ if(vchix & 0x8000) { DEBUG_CPASSISTX(SCNVU,logmsg(_("HHCEV300D SCNVU Virtual Device %4.4X has no VCHAN block\n"),vdev)); return; } vch=EVM_L(effective_addr2)+vchix; vcuix=EVM_LH(vch+8+((vdev & 0xf0)>>3)); if(vcuix & 0x8000) { DEBUG_CPASSISTX(SCNVU,logmsg(_("HHCEV300D SCNVU Virtual Device %4.4X has no VCU block\n"),vdev)); return; } vcu=EVM_L(effective_addr2+4)+vcuix; vdvix=EVM_LH(vcu+8+((vdev & 0xf)<<1)); if(vdvix & 0x8000) { DEBUG_CPASSISTX(SCNVU,logmsg(_("HHCEV300D SCNVU Virtual Device %4.4X has no VDEV block\n"),vdev)); return; } vdv=EVM_L(effective_addr2+8)+vdvix; DEBUG_CPASSISTX(SCNVU,logmsg(_("HHCEV300D SCNVU %4.4X : VCH = %8.8X, VCU = %8.8X, VDEV = %8.8X\n"), vdev, vch, vcu, vdv)); regs->GR_L(6)=vch; regs->GR_L(7)=vcu; regs->GR_L(8)=vdv; regs->psw.cc=0; CPASSIST_HIT(SCNVU); BR14; return; } /* DISP1 Core */ /* rc : 0 - Done */ /* rc : 1 - No-op */ /* rc : 2 - Invoke DISP2 */ int ecpsvm_do_disp1(REGS *regs,VADR dl,VADR el) { VADR vmb; U32 F_VMFLGS; /* Aggregate for quick test */ U32 F_SCHMASK; /* Flags to test */ U32 F_SCHMON; /* Flags allowed on for quick dispatch */ VADR F_ASYSVM; /* System VMBLOK */ VADR SCHDL; /* SCHDL Exit */ BYTE B_VMOSTAT; BYTE B_VMQSTAT; BYTE B_VMRSTAT; vmb=regs->GR_L(11); DEBUG_CPASSISTX(DISP1,logmsg("DISP1 Data list = %6.6X VM=%6.6X\n",dl,vmb)); F_VMFLGS=EVM_L(vmb+VMRSTAT); F_SCHMASK=EVM_L(dl+64); F_SCHMON=EVM_L(dl+68); if((F_VMFLGS & F_SCHMASK) == F_SCHMON) { DEBUG_CPASSISTX(DISP1,logmsg("DISP1 Quick Check complete\n")); return(2); } else { DEBUG_CPASSISTX(DISP1,logmsg("DISP1 Quick Check failed : %8.8X != %8.8X\n",(F_VMFLGS & F_SCHMASK),F_SCHMON)); } F_ASYSVM=EVM_L(ASYSVM); if(vmb==F_ASYSVM) { DEBUG_CPASSISTX(DISP1,logmsg("DISP1 VMB is SYSTEM VMBLOCK\n")); return(2); } SCHDL=EVM_L(el+4); B_VMOSTAT=EVM_IC(vmb+VMOSTAT); if(!(B_VMOSTAT & VMKILL)) { DEBUG_CPASSISTX(DISP1,logmsg("DISP1 Call SCHEDULE because VMKILL not set\n")); UPD_PSW_IA(regs, SCHDL); return(0); } B_VMQSTAT=EVM_IC(vmb+VMQSTAT); if(!(B_VMQSTAT & VMCFREAD)) { if(B_VMOSTAT & VMCF) { DEBUG_CPASSISTX(DISP1,logmsg("DISP1 Call SCHEDULE because VMKILL & VMCF & !VMCFREAD set\n")); UPD_PSW_IA(regs, SCHDL); return(0); } } /* At DSP - OFF */ B_VMQSTAT &= ~VMCFREAD; B_VMOSTAT &= ~VMKILL; EVM_STC(B_VMQSTAT,vmb+VMQSTAT); EVM_STC(B_VMOSTAT,vmb+VMOSTAT); B_VMRSTAT=EVM_IC(vmb+VMRSTAT); if(B_VMRSTAT & VMLOGOFF) { DEBUG_CPASSISTX(DISP1,logmsg("DISP1 Continue because already logging off\n")); return(2); } B_VMRSTAT |= VMLOGOFF; EVM_STC(B_VMRSTAT,vmb+VMRSTAT); UPD_PSW_IA(regs, EVM_L(el+0)); DEBUG_CPASSISTX(DISP1,logmsg("DISP1 : Call USOFF\n")); return(0); } /* DISP2 Core */ int ecpsvm_do_disp2(REGS *regs,VADR dl,VADR el) { VADR vmb; /* Current VMBLOK */ VADR svmb; /* ASYSVM */ VADR runu; /* RUNUSER */ VADR lastu; /* LASTUSER */ VADR F_TRQB; VADR F_CPEXB; VADR F,B; U16 HW1; U32 FW1; U64 DW1; U32 CPEXBKUP[15]; /* CPEXBLOK Regs backup except GPR15 which is useless */ VADR F_ECBLOK; /* Pointer to user's EC block for extended VM */ VADR F_CPEXADD; U32 F_QUANTUM; REGS wregs; /* Work REGS structure of PSW manipulation for Virtual PSW */ REGS rregs; /* Work REGS structure of PSW manipulation for Real PSW */ int i; BYTE B_VMDSTAT,B_VMRSTAT,B_VMESTAT,B_VMPSTAT,B_VMMCR6,B_MICVIP; BYTE B_VMOSTAT,B_VMPEND; VADR F_MICBLOK; U32 F_VMIOINT,F_VMPXINT; U32 F_VMVCR0; U32 NCR0,NCR1; BYTE *work_p; vmb=regs->GR_L(11); DEBUG_CPASSISTX(DISP2,logmsg("DISP2 Data list=%6.6X VM=%6.6X\n",dl,vmb)); CHARGE_STOP(vmb); if(EVM_IC(XTENDLOCK) == XTENDLOCKSET) { DEBUG_CPASSISTX(DISP2,logmsg("DISP2 Exit 8 : System extending\n")); /* System in Extend process */ UPD_PSW_IA(regs, EVM_L(el+8)); return(0); } if(EVM_IC(APSTAT2) & CPMCHLK) { DEBUG_CPASSISTX(DISP2,logmsg("DISP2 Exit 8 : MCH Recovery\n")); /* Machine Check recovery in progress */ UPD_PSW_IA(regs, EVM_L(el+8)); return(0); } svmb=EVM_L(ASYSVM); /* Check IOB/TRQ for dispatch */ F_TRQB=EVM_L(dl+8); if(F_TRQB!=dl) { DEBUG_CPASSISTX(DISP2,logmsg("DISP2 TRQ/IOB @ %6.6X Exit being routed\n",F_TRQB)); /* We have a TRQ/IOB */ /* Update stack */ F=EVM_L(F_TRQB+8); B=EVM_L(F_TRQB+12); EVM_ST(F,B+8); EVM_ST(B,F+12); /* Get VMBLOK Responsible for this block */ vmb=EVM_L(F_TRQB+0x18); /* Update stack count for the VMBLOK */ HW1=EVM_LH(vmb+VMSTKCNT); HW1--; EVM_STH(HW1,vmb+VMSTKCNT); /* Start charging user for processor time */ CHARGE_START(vmb); EVM_ST(vmb,STACKVM); /* Update registers for TRQ/IOB exit */ regs->GR_L(10)=F_TRQB; regs->GR_L(11)=vmb; regs->GR_L(12)=EVM_L(F_TRQB+0x1C); UPD_PSW_IA(regs, regs->GR_L(12)); DEBUG_CPASSISTX(DISP2,logmsg("DISP2 TRQ/IOB @ %6.6X IA = %6.6X\n",F_TRQB,regs->GR_L(12))); return(0); } /* Check CPEX BLOCK for dispatch */ F_CPEXB=EVM_L(dl+0); if(F_CPEXB!=dl) { DEBUG_CPASSISTX(DISP2,logmsg("DISP2 CPEXBLOK Exit being routed CPEX=%6.6X\n",F_CPEXB)); /* We have a CPEXBLOCK */ /* Update stack */ F=EVM_L(F_CPEXB+0); B=EVM_L(F_CPEXB+4); EVM_ST(F,B+0); EVM_ST(B,F+4); vmb=EVM_L(F_CPEXB+0x10+(11*4)); HW1=EVM_LH(vmb+VMSTKCNT); HW1--; EVM_STH(HW1,vmb+VMSTKCNT); CHARGE_START(vmb); /* Copy CPEXBLOCK Contents, and attempt FRET */ /* If fret fails, use exit #12 */ for(i=0;i<15;i++) { CPEXBKUP[i]=EVM_L(F_CPEXB+0x10+(i*4)); } F_CPEXADD=EVM_L(F_CPEXB+0x0C); if(ecpsvm_do_fretx(regs,F_CPEXB,10,EVM_L(dl+28),EVM_L(dl+32))!=0) { DEBUG_CPASSISTX(DISP2,logmsg("DISP2 CPEXBLOK CPEX=%6.6X Fret Failed\n",F_CPEXB)); regs->GR_L(0)=10; regs->GR_L(1)=F_CPEXB; for(i=2;i<12;i++) { regs->GR_L(i)=CPEXBKUP[i]; } /* Save GPRS 12-1 (wraping) in DSPSAVE (datalist +40) */ /* So that LM 12,1,DSPSAVE in DMKDSP works after call to DMKFRET */ EVM_ST(dl+40,CPEXBKUP[12]); EVM_ST(dl+44,CPEXBKUP[13]); EVM_ST(dl+48,CPEXBKUP[14]); EVM_ST(dl+52,EVM_L(F_CPEXB+12)); /* DSPSAVE + 12 = CPEXADD */ EVM_ST(dl+56,CPEXBKUP[0]); EVM_ST(dl+60,CPEXBKUP[1]); /* Note : DMKDSP Is wrong - SCHMASK is at +64 (not +60) */ /* Upon taking this exit, GPRS 12-15 are same as entry */ UPD_PSW_IA(regs, EVM_L(el+12)); return(0); } for(i=0;i<15;i++) { regs->GR_L(i)=CPEXBKUP[i]; } regs->GR_L(15)=F_CPEXADD; UPD_PSW_IA(regs, F_CPEXADD); DEBUG_CPASSISTX(DISP2,logmsg("DISP2 CPEXBLOK CPEX=%6.6X IA=%6.6X\n",F_CPEXB,F_CPEXADD)); return(0); /* CPEXBLOCK Branch taken */ } /* Check for a USER run */ /* AT DMKDSP - DONE */ if(EVM_IC(CPSTAT2) & CPSHRLK) { DEBUG_CPASSISTX(DISP2,logmsg("DISP2 Exit 24 : CPSHRLK Set in CPSTAT2\n")); UPD_PSW_IA(regs, EVM_L(el+24)); /* IDLEECPS */ return(0); } /* Scan Scheduler IN-Q */ DEBUG_CPASSISTX(DISP2,logmsg("DISP2 : Scanning Scheduler IN-Queue\n")); FW1=EVM_L(dl+24); for(vmb=EVM_L(FW1);vmb!=FW1;vmb=EVM_L(vmb)) { if(!(EVM_IC(vmb+VMDSTAT) & VMRUN)) { DEBUG_CPASSISTX(DISP2,logmsg("DISP2 : VMB @ %6.6X Not eligible : VMRUN not set\n",vmb)); continue; } if(EVM_IC(vmb+VMRSTAT) & VMCPWAIT) { DEBUG_CPASSISTX(DISP2,logmsg("DISP2 : VMB @ %6.6X Not eligible : VMCPWAIT set\n",vmb)); continue; } if(EVM_IC(vmb+VMNOECPS)) { DEBUG_CPASSISTX(DISP2,logmsg("DISP2 : Exit 20 : VMB @ %6.6X Has VMNOECPS Set to %2.2X\n",vmb,EVM_IC(vmb+VMNOECPS))); regs->GR_L(1)=vmb; regs->GR_L(11)=EVM_L(ASYSVM); UPD_PSW_IA(regs, EVM_L(el+20)); /* FREELOCK */ return(0); } DEBUG_CPASSISTX(DISP2,logmsg("DISP2 : VMB @ %6.6X Will now be dispatched\n",vmb)); runu=EVM_L(RUNUSER); F_QUANTUM=EVM_L(QUANTUM); if(vmb!=runu) { /* User switching */ /* DMKDSP - FNDUSRD */ DEBUG_CPASSISTX(DISP2,logmsg("DISP2 : User switch from %6.6X to %6.6X\n",runu,vmb)); runu=EVM_L(RUNUSER); EVM_STC(EVM_IC(runu+VMDSTAT) & ~VMDSP,runu+VMDSTAT); lastu=EVM_L(LASTUSER); DEBUG_CPASSISTX(DISP2,logmsg("DISP2 : RUNU=%6.6X, LASTU=%6.6X\n",runu,lastu)); if(lastu!=svmb && lastu!=vmb) { if(EVM_IC(lastu+VMOSTAT) & VMSHR) /* Running shared sys */ { DEBUG_CPASSISTX(DISP2,logmsg("DISP2 : Exit 16 : LASTU=%6.6X has shared sys & LCSHPG not impl\n",lastu)); CHARGE_START(lastu); /* LCSHRPG not implemented yet */ regs->GR_L(10)=vmb; regs->GR_L(11)=lastu; UPD_PSW_IA(regs, EVM_L(el+16)); return(0); /* A CHARGE_STOP(runu) is due when LCSHRPG is implemented */ } } } if(vmb!=runu || (vmb==runu && (F_QUANTUM & 0x80000000))) { DEBUG_CPASSISTX(DISP2,logmsg("DISP2 : Restarting Time Slice\n")); F_QUANTUM=EVM_L(dl+16); if(EVM_IC(vmb+VMQLEVEL) & VMCOMP) { F_QUANTUM <<= 2; } } EVM_ST(F_QUANTUM,INTTIMER); CHARGE_START(vmb); EVM_ST(vmb,LASTUSER); EVM_ST(vmb,RUNUSER); /*** Prepare to run a user ***/ /* Cache some important VMBLOK flag bytes */ B_VMDSTAT=EVM_IC(vmb+VMDSTAT); B_VMRSTAT=EVM_IC(vmb+VMRSTAT); B_VMPSTAT=EVM_IC(vmb+VMPSTAT); B_VMESTAT=EVM_IC(vmb+VMESTAT); B_VMOSTAT=EVM_IC(vmb+VMOSTAT); B_VMPEND =EVM_IC(vmb+VMPEND); B_VMMCR6=EVM_IC(vmb+VMMCR6); F_MICBLOK=EVM_L(vmb+VMMCR6) & ADDRESS_MAXWRAP(regs); /* LOAD FPRS */ for(i=0;i<8;i+=2) { FW1=EVM_L(vmb+VMFPRS+(i*16)); regs->fpr[i*4]=FW1; FW1=EVM_L(vmb+VMFPRS+(i*16)+4); regs->fpr[i*4+1]=FW1; FW1=EVM_L(vmb+VMFPRS+(i*16)+8); regs->fpr[i*4+2]=FW1; FW1=EVM_L(vmb+VMFPRS+(i*16)+12); regs->fpr[i*4+3]=FW1; } INITPSEUDOREGS(wregs); work_p=MADDR(vmb+VMPSW,0,regs,USE_REAL_ADDR,0); ARCH_DEP(load_psw) (&wregs,work_p); /* Load user's Virtual PSW in work structure */ SET_PSW_IA(&wregs); /* Build REAL PSW */ INITPSEUDOREGS(rregs); /* Copy IAR */ UPD_PSW_IA(&rregs, wregs.psw.IA); /* Copy CC, PSW KEYs and PGM Mask */ rregs.psw.cc=wregs.psw.cc; rregs.psw.pkey=wregs.psw.pkey; /* Indicate Translation + I/O + Ext + Ecmode + Problem + MC */ rregs.psw.sysmask=0x07; /* I/O + EXT + Trans */ rregs.psw.states = BIT(PSW_EC_BIT) /* ECMODE */ | BIT(PSW_PROB_BIT) /* Problem state */ | BIT(PSW_MACH_BIT); /* MC Enabled */ rregs.psw.intcode=0; /* Clear intcode */ rregs.psw.progmask=wregs.psw.progmask; NCR0=EVM_L(CPCREG0); /* Assume for now */ NCR1=EVM_L(vmb+VMSEG); /* Ditto */ /* Disable ECPS:VM in VM-REAL CR6 For now */ B_VMMCR6&=~(VMMSHADT|VMMPROB|VMMNOSK|VMMFE); /* We load VMECEXT Even if it's not a ECMODE VM */ /* in which case F_ECBLOK is also Virtual CR0 */ F_ECBLOK=EVM_L(vmb+VMECEXT); /* ECMODE VM ? */ if(B_VMPSTAT & VMV370R) { DEBUG_CPASSISTX(DISP2,logmsg("DISP2 : VMB @ %6.6X has ECMODE ON\n",vmb)); /* Is this an ECMODE PSW Machine ? */ if(B_VMESTAT & VMEXTCM) { if((B_VMESTAT & (VMINVSEG|VMNEWCR0)) == (VMINVSEG|VMNEWCR0)) { /* CP Say this is NOT good */ /* Take exit 28 */ logmsg(_("HHCEV004W : Abend condition detected in DISP2 instr\n")); UPD_PSW_IA(regs, EVM_L(el+28)); return(0); } /* Check 3rd level translation */ if(wregs.psw.sysmask & 0x04) { NCR0=EVM_L(F_ECBLOK+EXTSHCR0); NCR1=EVM_L(F_ECBLOK+EXTSHCR1); B_VMMCR6|=VMMSHADT; /* re-enable Shadow Table management in CR6 */ } } } /* Invalidate Shadow Tables if necessary */ if(B_VMESTAT & (VMINVPAG | VMSHADT)) { DEBUG_CPASSISTX(DISP2,logmsg("DISP2 : VMB @ %6.6X Refusing to simulate DMKVATAB\n",vmb)); /* Really looks like DMKVATAB is a huge thing to simulate */ /* My belief is that the assist can't handle this one */ /* Return to caller as a NO-OP on this one */ return(1); /* ecpsvm_inv_shadtab_pages(regs,vmb); */ } B_VMESTAT&=~VMINVPAG; B_VMDSTAT|=VMDSP; /* Test for CPMICON in DMKDSP useless here */ /* if CPMICON was off, we would have never */ /* been called anyway */ if(F_MICBLOK!=0) /* That is SET ASSIST ON */ { B_MICVIP=0; /* Check tracing (incompatible with assist) */ if(!(EVM_IC(vmb+VMTRCTL) & (VMTRSVC|VMTRPRV|VMTRBRIN))) { B_VMMCR6|=VMMFE; if(B_VMOSTAT & VMSHR) { /* Cannot allow ISK/SSK in shared sys VM */ B_VMMCR6|=VMMNOSK; } if(PROBSTATE(&wregs.psw)) { B_VMMCR6|=VMMPROB; } /* Set MICPEND if necessary */ /* (assist stuff to ensure LPSW/SSM/SVC sim */ /* does not re-enable VPSW when an interrupt */ /* is pending) */ while(1) { B_MICVIP=0; F_VMIOINT=EVM_LH(vmb+VMIOINT); if(EVM_LH(vmb+VMIOINT)!=0) { F_VMIOINT<<=16; if(B_VMESTAT & VMEXTCM) { if(F_VMIOINT&=EVM_L(F_ECBLOK)) { B_MICVIP|=0x80; break; } } else { B_MICVIP|=0x80; break; } } if(B_VMESTAT & VMEXTCM) { if(B_VMPEND & VMPGPND) { B_MICVIP|=0x80; } } if(B_VMPSTAT & VMV370R) { F_VMVCR0=EVM_L(F_ECBLOK+0); } else { F_VMVCR0=F_ECBLOK; } for(F_VMPXINT=EVM_L(vmb+VMPXINT);F_VMPXINT;F_VMPXINT=EVM_L(F_VMPXINT)) /* XINTNEXT at +0 */ { if(F_VMVCR0 & EVM_LH(F_VMPXINT+10)) { B_MICVIP|=0x80; break; } } break; /* Terminate dummy while loop */ } /* While dummy loop for MICPEND */ } /* if(Not tracing) */ EVM_STC(B_MICVIP,F_MICBLOK+8); /* Save new MICVIP */ } /* if(F_MICBLOCK!=0) */ /* If an Extended VM, Load CRs 3-13 */ /* CR6 Will be overwritten in a second */ if(B_VMESTAT & VMV370R) { for(i=4;i<14;i++) { regs->CR_L(i)=EVM_L(F_ECBLOK+(3*4)+(i*4)); } } /* Update VMMICRO */ EVM_STC(B_VMMCR6,vmb+VMMCR6); /* Update PER Control */ if(EVM_IC(vmb+VMTRCTL) & VMTRPER) { DEBUG_CPASSISTX(DISP2,logmsg("DISP2 : PER ON\n")); FW1=EVM_L(vmb+VMTREXT); regs->CR_L( 9)=EVM_L(FW1+0x1C); regs->CR_L(10)=EVM_L(FW1+0x20); regs->CR_L(11)=EVM_L(FW1+0x24); rregs.psw.sysmask |= 0x40; /* PER Mask in PSW */ } /* Update CR6 */ regs->CR_L(6)=EVM_L(vmb+VMMCR6); /* Insure proper re-entry */ EVM_ST(0,STACKVM); /* Update PROBLEM Start time */ DW1=EVM_LD(vmb+VMTMOUTQ); EVM_STD(DW1,PROBSTRT); /* Checkpoint Interval Timer */ FW1=EVM_L(INTTIMER); EVM_ST(FW1,QUANTUM); /* Update REAL CR0/CR1 */ regs->CR_L(0)=NCR0; regs->CR_L(1)=NCR1; /* Indicate RUNNING a user */ EVM_STC(CPRUN,CPSTATUS); /* Update real PSW with working PSW */ /* Update regs */ for(i=0;i<16;i++) { regs->GR_L(i)=EVM_L(vmb+VMGPRS+(i*4)); } /* Clear I/O Old PSW Byte 0 */ EVM_STC(0,IOOPSW); /* Issue PTLB if necessary */ if(EVM_IC(APSTAT2) & CPPTLBR) { DEBUG_CPASSISTX(DISP2,logmsg("DISP2 : Purging TLB\n")); ARCH_DEP(purge_tlb)(regs); EVM_STC(EVM_IC(APSTAT2) & ~CPPTLBR,APSTAT2); } /* Update cached VMBLOK flags */ EVM_STC(B_VMDSTAT,vmb+VMDSTAT); EVM_STC(B_VMRSTAT,vmb+VMRSTAT); EVM_STC(B_VMESTAT,vmb+VMESTAT); EVM_STC(B_VMPSTAT,vmb+VMPSTAT); EVM_STC(B_VMOSTAT,vmb+VMOSTAT); work_p=MADDR(vmb+VMPSW,USE_REAL_ADDR,regs,ACCTYPE_WRITE,0); \ ARCH_DEP(store_psw) (&wregs,work_p); /* Stop charging current VM Block for Supervisor time */ CHARGE_STOP(vmb); /* Rest goes for problem state */ SPT(vmb+VMTMOUTQ); /* Save RUNCR0, RUNCR1 & RUNPSW */ /* Might be used by later CP Modules (including DMKPRV) */ EVM_ST(NCR0,RUNCR0); EVM_ST(NCR1,RUNCR1); work_p=MADDR(RUNPSW,USE_REAL_ADDR,regs,ACCTYPE_WRITE,0); \ ARCH_DEP(store_psw) (&rregs,work_p); DEBUG_CPASSISTX(DISP2,logmsg("DISP2 : Entry Real ")); DEBUG_CPASSISTX(DISP2,display_psw(regs)); ARCH_DEP(load_psw) (regs,work_p); DEBUG_CPASSISTX(DISP2,logmsg("DISP2 : VMB @ %6.6X Now being dispatched\n",vmb)); DEBUG_CPASSISTX(DISP2,logmsg("DISP2 : Real ")); DEBUG_CPASSISTX(DISP2,display_psw(regs)); DEBUG_CPASSISTX(DISP2,logmsg("DISP2 : Virtual ")); DEBUG_CPASSISTX(DISP2,display_psw(&wregs)); /* TEST */ ARCH_DEP(purge_tlb)(regs); SET_IC_MASK(regs); SET_AEA_MODE(regs); SET_AEA_COMMON(regs); SET_PSW_IA(regs); /* Dispatch..... */ DEBUG_CPASSISTX(DISP2,logmsg(_("HHCPEV300D : DISP2 - Next Instruction : %2.2X\n"),ARCH_DEP(vfetchb)(regs->psw.IA,USE_PRIMARY_SPACE,regs))); DEBUG_CPASSISTX(DISP2,display_regs(regs)); DEBUG_CPASSISTX(DISP2,display_cregs(regs)); return(2); /* OK - Perform INTCHECK */ } /* Nothing else to do - wait state */ DEBUG_CPASSISTX(DISP2,logmsg("DISP2 : Nothing to dispatch - IDLEECPS\n")); UPD_PSW_IA(regs, EVM_L(el+24)); /* IDLEECPS */ return(0); } /* DISP1 : Early tests part 2 */ /* DISP1 Checks if the user is OK to run */ /* early tests part 1 already done by DISP0 */ DEF_INST(ecpsvm_disp1) { ECPSVM_PROLOG(DISP1); switch(ecpsvm_do_disp1(regs,effective_addr1,effective_addr2)) { case 0: /* Done */ CPASSIST_HIT(DISP1); return; case 1: /* No-op */ break; case 2: /* Call DISP2 - INTCHECK NOT needed */ switch(ecpsvm_do_disp2(regs,effective_addr1,effective_addr2)) { case 0: CPASSIST_HIT(DISP1); return; case 1: return; case 2: CPASSIST_HIT(DISP1); RETURN_INTCHECK(regs); default: break; } return; default: return; } } static int ecpsvm_int_lra(REGS *regs,VADR pgadd,RADR *raddr) { int cc; cc = ARCH_DEP(translate_addr) (pgadd , USE_PRIMARY_SPACE, regs, ACCTYPE_LRA); *raddr = regs->dat.raddr; return cc; } /* TRANBRNG/TRANLOCK Common code */ static int ecpsvm_tranbrng(REGS *regs,VADR cortabad,VADR pgadd,RADR *raddr) { int cc; int corcode; #if defined(FEATURE_2K_STORAGE_KEYS) RADR pg1,pg2; #endif VADR cortab; cc=ecpsvm_int_lra(regs,pgadd,raddr); if(cc!=0) { DEBUG_CPASSISTX(TRBRG,logmsg(_("HHCEV300D : Tranbring : LRA cc = %d\n"),cc)); return(1); } /* Get the core table entry from the Real address */ cortab=EVM_L( cortabad ); cortab+=((*raddr) & 0xfff000) >> 8; corcode=EVM_IC(cortab+8); if(!(corcode & 0x08)) { DEBUG_CPASSISTX(TRBRG,logmsg(_("HHCEV300D : Page not shared - OK %d\n"),cc)); return(0); /* Page is NOT shared.. All OK */ } #if defined(FEATURE_2K_STORAGE_KEYS) pg1=(*raddr & 0xfff000); pg2=pg1+0x800; DEBUG_CPASSISTX(TRBRG,logmsg(_("HHCEV300D : Checking 2K Storage keys @"F_RADR" & "F_RADR"\n"),pg1,pg2)); if((STORAGE_KEY(pg1,regs) & STORKEY_CHANGE) || (STORAGE_KEY(pg2,regs) & STORKEY_CHANGE)) { #else DEBUG_CPASSISTX(TRBRG,logmsg(_("HHCEV300D : Checking 4K Storage keys @"F_RADR"\n"),*raddr)); if(STORAGE_KEY(*raddr,regs) & STORKEY_CHANGE) { #endif DEBUG_CPASSISTX(TRBRG,logmsg(_("HHCEV300D : Page shared and changed\n"))); return(1); /* Page shared AND changed */ } DEBUG_CPASSISTX(TRBRG,logmsg(_("HHCEV300D : Page shared but not changed\n"))); return(0); /* All done */ } /* TRBRG : Translate a page address */ /* TRBRG D1(R1,B1),D2(R2,B2) */ /* 1st operand : Coretable address */ /* 2nd operand : Virtual address */ /* Note : CR1 Contains the relevant segment table */ /* pointers */ /* The REAL address is resolved. If the page is flagged */ /* as shared in the core table, the page is checked for */ /* the change bit */ /* If no unusual condition is detected, control is returned */ /* to the address in GPR 14. Otherwise, TRBRG is a no-op */ DEF_INST(ecpsvm_tpage) { int rc; RADR raddr; ECPSVM_PROLOG(TRBRG); DEBUG_CPASSISTX(TRBRG,logmsg(_("HHCEV300D : TRANBRNG\n"))); rc=ecpsvm_tranbrng(regs,effective_addr1,regs->GR_L(1),&raddr); if(rc) { DEBUG_CPASSISTX(TRBRG,logmsg(_("HHCEV300D : TRANBRNG - Back to CP\n"))); return; /* Something not right : NO OP */ } regs->psw.cc=0; regs->GR_L(2)=raddr; UPD_PSW_IA(regs, effective_addr2); CPASSIST_HIT(TRBRG); return; } /* TRLOK : Translate a page address and lock */ /* TRLOK D1(R1,B1),D2(R2,B2) */ /* See TRBRG. */ /* If sucessfull, the page is also locked in the core table */ DEF_INST(ecpsvm_tpage_lock) { int rc; RADR raddr; ECPSVM_PROLOG(TRLOK); DEBUG_CPASSISTX(TRLOK,logmsg(_("HHCEV300D : TRANLOCK\n"))); rc=ecpsvm_tranbrng(regs,effective_addr1,regs->GR_L(1),&raddr); if(rc) { DEBUG_CPASSISTX(TRLOK,logmsg(_("HHCEV300D : TRANLOCK - Back to CP\n"))); return; /* Something not right : NO OP */ } /* * Lock the page in Core Table */ ecpsvm_lockpage1(regs,effective_addr1,raddr); regs->psw.cc=0; regs->GR_L(2)=raddr; UPD_PSW_IA(regs, effective_addr2); CPASSIST_HIT(TRLOK); return; } /* VIST : Not supported */ DEF_INST(ecpsvm_inval_segtab) { ECPSVM_PROLOG(VIST); } /* VIPT : Not supported */ DEF_INST(ecpsvm_inval_ptable) { ECPSVM_PROLOG(VIPT); } /* DFCCW : Not Supported */ DEF_INST(ecpsvm_decode_first_ccw) { ECPSVM_PROLOG(DFCCW); } /* DISP0 Utility functions */ /* DMKDSP - INCPROBT */ static int ecpsvm_disp_incprobt(REGS *regs,VADR vmb) { U64 tspent; U64 DW_VMTMOUTQ; U64 DW_PROBSTRT; U64 DW_PROBTIME; DEBUG_CPASSISTX(DISP0,logmsg("INCPROBT Entry : VMBLOK @ %8.8X\n",vmb)); DW_VMTMOUTQ=EVM_LD(vmb+VMTMOUTQ); DW_PROBSTRT=EVM_LD(PROBSTRT); DEBUG_CPASSISTX(DISP0,logmsg("INCPROBT Entry : VMTMOUTQ = %16.16" I64_FMT "x\n",DW_VMTMOUTQ)); DEBUG_CPASSISTX(DISP0,logmsg("INCPROBT Entry : PROBSTRT = %16.16" I64_FMT "x\n",DW_PROBSTRT)); if(DW_VMTMOUTQ==DW_PROBSTRT) { DEBUG_CPASSISTX(DISP0,logmsg("INCPROBT Already performed")); return(2); /* continue */ } tspent=DW_PROBSTRT-DW_VMTMOUTQ; DEBUG_CPASSISTX(DISP0,logmsg("INCPROBT TSPENT = %16.16" I64_FMT "x\n",tspent)); DW_PROBTIME=EVM_LD(PROBTIME); DW_PROBTIME-=tspent; EVM_STD(DW_PROBTIME,PROBTIME); DEBUG_CPASSISTX(DISP0,logmsg("INCPROBT NEW PROBTIME = %16.16" I64_FMT "x\n",DW_PROBTIME)); return(2); } /* DMKDSP RUNTIME */ static int ecpsvm_disp_runtime(REGS *regs,VADR *vmb_p,VADR dlist,VADR exitlist) { U64 DW_VMTTIME; U64 DW_VMTMINQ; BYTE B_VMDSTAT; BYTE B_VMTLEVEL; BYTE B_VMMCR6; U32 F_QUANTUM; U32 F_QUANTUMR; U32 F_ITIMER; int cc; RADR raddr; VADR tmraddr; U32 oldtimer,newtimer; VADR vmb; VADR runu; vmb=*vmb_p; DEBUG_CPASSISTX(DISP0,logmsg("RUNTIME Entry : VMBLOK @ %8.8X\n",vmb)); runu=EVM_L(RUNUSER); /* BAL RUNTIME Processing */ EVM_STC(CPEX+CPSUPER,CPSTATUS); CHARGE_STOP(vmb); if(vmb!=runu) { DEBUG_CPASSISTX(DISP0,logmsg("RUNTIME Switching to RUNUSER VMBLOK @ %8.8X\n",runu)); CHARGE_SWITCH(vmb,runu); /* Charge RUNUSER */ F_ITIMER=EVM_L(QUANTUMR); *vmb_p=vmb; } else { F_ITIMER=EVM_L(INTTIMER); } DEBUG_CPASSISTX(DISP0,logmsg("RUNTIME : VMBLOK @ %8.8X\n",vmb)); /* vmb is now RUNUSER */ /* Check if time slice is over */ if(F_ITIMER & 0x80000000) { B_VMDSTAT=EVM_IC(vmb+VMDSTAT); B_VMDSTAT&=~VMDSP; B_VMDSTAT|=VMTSEND; EVM_STC(B_VMDSTAT,vmb+VMDSTAT); } /* Check if still eligible for current run Q */ DW_VMTTIME=EVM_LD(vmb+VMTTIME); DW_VMTMINQ=EVM_LD(vmb+VMTMINQ); /* Check 1st 5 bytes */ if((DW_VMTTIME & 0xffffffffff000000ULL) < (DW_VMTMINQ & 0xffffffffff000000ULL)) { B_VMDSTAT=EVM_IC(vmb+VMDSTAT); B_VMDSTAT&=~VMDSP; B_VMDSTAT|=VMQSEND; EVM_STC(B_VMDSTAT,vmb+VMDSTAT); } ecpsvm_disp_incprobt(regs,vmb); F_QUANTUM=EVM_L(QUANTUM); EVM_ST(F_ITIMER,QUANTUM); /* Check if Virtual Timer assist is active */ B_VMMCR6=EVM_IC(vmb+VMMCR6); if(B_VMMCR6 & 0x01) /* Virtual Timer Flag */ { DEBUG_CPASSISTX(DISP0,logmsg("RUNTIME : Complete - VTIMER Assist active\n")); return(2); /* End of "RUNTIME" here */ } /* Check SET TIMER ON or SET TIMER REAL */ B_VMTLEVEL=EVM_IC(vmb+VMTLEVEL); if(!(B_VMTLEVEL & (VMTON | VMRON))) { DEBUG_CPASSISTX(DISP0,logmsg("RUNTIME : Complete - SET TIMER OFF\n")); return(2); } /* Update virtual interval timer */ F_QUANTUMR=EVM_L(QUANTUMR); F_QUANTUM-=F_QUANTUMR; if(F_QUANTUM & 0x80000000) { /* Abend condition detected during virtual time update - exit at +32 */ DEBUG_CPASSISTX(DISP0,logmsg("RUNTIME : Bad ITIMER - Taking Exist #32\n")); UPD_PSW_IA(regs, EVM_L(exitlist+32)); return(0); } /* Load CR1 with the vmblock's VMSEG */ regs->CR_L(1)=EVM_L(vmb+VMSEG); /* Do LRA - Don't access the page directly yet - Could yield a Paging fault */ cc = ecpsvm_int_lra(regs,INTTIMER,&raddr); if(cc!=0) { /* Update VMTIMER instead */ tmraddr=vmb+VMTIMER; } else { tmraddr=(VADR)raddr; } oldtimer=EVM_L(tmraddr); newtimer=oldtimer-F_QUANTUM; EVM_ST(newtimer,tmraddr); if((newtimer & 0x80000000) != (oldtimer & 0x80000000)) { /* Indicate XINT to be generated (exit + 8) */ /* Setup a few regs 1st */ regs->GR_L(3)=0; regs->GR_L(4)=0x00800080; regs->GR_L(9)=EVM_L(dlist+4); regs->GR_L(11)=vmb; UPD_PSW_IA(regs, EVM_L(exitlist+8)); DEBUG_CPASSISTX(DISP0,logmsg("RUNTIME : Complete - Taking exit #8\n")); return(0); } /* Return - Continue DISP0 Processing */ DEBUG_CPASSISTX(DISP0,logmsg("RUNTIME : Complete - ITIMER Updated\n")); return(2); } /* DISP0 : Operand 1 : DISP0 Data list, Operand 2 : DISP0 Exit list */ /* R11 : User to dispatch */ DEF_INST(ecpsvm_dispatch_main) { VADR dlist; VADR elist; VADR vmb; /* PSA Fetched Values */ BYTE B_CPSTATUS; BYTE B_VMDSTAT; BYTE B_VMPSTAT; BYTE B_VMRSTAT; BYTE B_VMPEND; BYTE B_VMESTAT; VADR F_VMPXINT; VADR OXINT; /* Back chain ptr for exit 20 */ U32 F_VMPSWHI; U32 F_VMVCR0; U32 F_VMIOINT; U32 F_VMVCR2; U32 DISPCNT; U16 H_XINTMASK; U32 iomask; BYTE extendmsk; /* Extended I/O mask */ ECPSVM_PROLOG(DISP0); dlist=effective_addr1; elist=effective_addr2; vmb=regs->GR_L(11); DISPCNT=EVM_L(dlist); DISPCNT++; /* Question #1 : Are we currently running a user */ B_CPSTATUS=EVM_IC(CPSTATUS); if((B_CPSTATUS & CPRUN)) { DEBUG_CPASSISTX(DISP0,logmsg("DISP0 : CPRUN On\n")); switch(ecpsvm_disp_runtime(regs,&vmb,dlist,elist)) { case 0: /* Exit taken - success */ EVM_ST(DISPCNT,dlist); CPASSIST_HIT(DISP0); return; case 1: /* no-op DISP0 */ return; default: /* Continue processing */ break; } /* Load VMDSTAT */ B_VMDSTAT=EVM_IC(vmb+VMDSTAT); /* Check if I/O Old PSW has tranlation on */ if(regs->mainstor[0x38] & 0x04) { DEBUG_CPASSISTX(DISP0,logmsg("DISP0 : I/O Old as XLATE on\n")); /* Yes - I/O Interrupt while running a USER */ if(B_VMDSTAT & VMDSP) { DEBUG_CPASSISTX(DISP0,logmsg("DISP0 : VMDSP on in VMBLOK - Clean status (Exit #36)\n")); /* Clean status - Do exit 36 */ regs->GR_L(11)=vmb; UPD_PSW_IA(regs, EVM_L(elist+36)); EVM_ST(DISPCNT,dlist); CPASSIST_HIT(DISP0); return; } } } else { DEBUG_CPASSISTX(DISP0,logmsg("DISP0 : CPRUN Off\n")); /* Check if was in Wait State */ if(B_CPSTATUS & CPWAIT) { DEBUG_CPASSISTX(DISP0,logmsg("DISP0 : CPWAIT On : Exit #4\n")); /* Take exit #4 : Coming out of wait state */ /* DMKDSPC3 */ /* No need to update R11 */ CPASSIST_HIT(DISP0); UPD_PSW_IA(regs, EVM_L(elist+4)); EVM_ST(DISPCNT,dlist); return; } } /* VMB is now either original GPR11 or RUNUSER */ /* DMKDSP - UNSTACK */ DEBUG_CPASSISTX(DISP0,logmsg("DISP0 : At UNSTACK : VMBLOK = %8.8X\n",vmb)); B_VMRSTAT=EVM_IC(vmb+VMRSTAT); if(B_VMRSTAT & VMCPWAIT) { DEBUG_CPASSISTX(DISP0,logmsg("DISP0 : VMRSTAT VMCPWAIT On (%2.2X) - Taking exit #12\n",B_VMRSTAT)); /* Take Exit 12 */ regs->GR_L(11)=vmb; UPD_PSW_IA(regs, EVM_L(elist+12)); CPASSIST_HIT(DISP0); EVM_ST(DISPCNT,dlist); return; } /* Check for PER/PPF (CKPEND) */ B_VMPEND=EVM_IC(vmb+VMPEND); if(B_VMPEND & (VMPERPND | VMPGPND)) { DEBUG_CPASSISTX(DISP0,logmsg("DISP0 : PER/PPF Pending - Taking exit #16\n")); /* Take Exit 16 */ regs->GR_L(11)=vmb; UPD_PSW_IA(regs, EVM_L(elist+16)); CPASSIST_HIT(DISP0); EVM_ST(DISPCNT,dlist); return; } /* Now, check if we should unstack an external int */ /* 1st check if VMPXINT is NULL */ F_VMPSWHI=EVM_L(vmb+VMPSW); /* Load top of virt PSW - Will need it */ B_VMPSTAT=EVM_IC(vmb+VMPSTAT); /* Will need VMPSTAT for I/O ints too */ F_VMPXINT=EVM_L(vmb+VMPXINT); DEBUG_CPASSISTX(DISP0,logmsg("DISP0 : Checking for EXT; Base VMPXINT=%8.8X\n",F_VMPXINT)); /* This is DMKDSP - CKEXT */ if(F_VMPXINT!=0) { DEBUG_CPASSISTX(DISP0,logmsg("DISP0 : VPSW HI = %8.8X\n",F_VMPSWHI)); OXINT=vmb+VMPXINT; /* Check if Virtual PSW enabled for Externals */ /* (works in both BC & EC modes) */ if(F_VMPSWHI & 0x01000000) { DEBUG_CPASSISTX(DISP0,logmsg("DISP0 : PSW Enabled for EXT\n")); /* Use VMVCR0 or CR0 in ECBLOK */ F_VMVCR0=EVM_L(vmb+VMVCR0); /* CR0 or ECBLOK Address */ if(B_VMPSTAT & VMV370R) /* SET ECMODE ON ?? */ { F_VMVCR0=EVM_L(F_VMVCR0+0); /* EXTCR0 at disp +0 in ECBLOK */ } DEBUG_CPASSISTX(DISP0,logmsg("DISP0 : CR0 = %8.8X\n",F_VMVCR0)); /* scan the XINTBLOKS for a mask match */ /* Save OXINT in the loop for exit 20 */ for(;F_VMPXINT;OXINT=F_VMPXINT,F_VMPXINT=EVM_L(F_VMPXINT)) /* XINTNEXT @ +0 in XINTBLOK */ { H_XINTMASK=EVM_LH(F_VMPXINT+10); /* Get interrupt subclass in XINTBLOK */ DEBUG_CPASSISTX(DISP0,logmsg("DISP0 : XINTMASK = %4.4X\n",H_XINTMASK)); H_XINTMASK &= F_VMVCR0; if(H_XINTMASK) /* Check against CR0 (External subclass mask) */ { DEBUG_CPASSISTX(DISP0,logmsg("DISP0 : EXT Hit - Taking exit #20\n")); /* Enabled for this external */ /* Take exit 20 */ regs->GR_L(4)=H_XINTMASK; /* Enabled subclass bits */ regs->GR_L(5)=OXINT; /* XINTBLOK Back pointer (or VMPXINT) */ regs->GR_L(6)=F_VMPXINT; /* Current XINTBLOK */ regs->GR_L(11)=vmb; /* RUNUSER */ UPD_PSW_IA(regs, EVM_L(elist+20)); /* Exit +20 */ EVM_ST(DISPCNT,dlist); CPASSIST_HIT(DISP0); return; } } } } /* After CKEXT : No external pending/reflectable */ /* This is DMKDSP UNSTIO */ /* Check for pending I/O Interrupt */ /* Load PIM */ F_VMIOINT=EVM_LH(vmb+VMIOINT); DEBUG_CPASSISTX(DISP0,logmsg("DISP0 : Checking for I/O; VMIOINT=%8.8X\n",F_VMIOINT)); if(F_VMIOINT!=0) /* If anything in the pipe */ { F_VMIOINT <<=16; /* Put IOINT mask in bits 0-15 */ /* Is V-PSW in EC Mode ? */ iomask=0; extendmsk=0; B_VMESTAT=EVM_L(VMESTAT); if(B_VMESTAT & VMEXTCM) /* Implies VMV370R on */ { /* Check I/O bit */ if(F_VMPSWHI & 0x02000000) { iomask=0; extendmsk=1; } } else { /* BC Mode PSW */ /* Isolate channel masks for channels 0-5 */ iomask=F_VMPSWHI & 0xfc000000; if(B_VMPSTAT & VMV370R) /* SET ECMODE ON ? */ { if(F_VMPSWHI & 0x02000000) { extendmsk=1; } } } if(extendmsk) { F_VMVCR2=EVM_L(vmb+VMECEXT); F_VMVCR2=EVM_L(F_VMVCR2+8); iomask |= F_VMVCR2; } if(iomask & 0xffff0000) { F_VMIOINT&=iomask; if(F_VMIOINT) { DEBUG_CPASSISTX(DISP0,logmsg("DISP0 : I/O Hit - Taking exit #24\n")); /* Take Exit 24 */ regs->GR_L(7)=F_VMIOINT; regs->GR_L(11)=vmb; UPD_PSW_IA(regs, EVM_L(elist+24)); /* Exit +24 */ EVM_ST(DISPCNT,dlist); CPASSIST_HIT(DISP0); return; } } } /* DMKDSP - CKWAIT */ /* Clear Wait / Idle bits in VMRSTAT */ B_VMRSTAT=EVM_IC(vmb+VMRSTAT); B_VMRSTAT &= ~(VMPSWAIT | VMIDLE); EVM_STC(B_VMRSTAT,vmb+VMRSTAT); if(F_VMPSWHI & 0x00020000) { DEBUG_CPASSISTX(DISP0,logmsg("DISP0 : VWAIT - Taking exit #28\n")); /* Take exit 28 */ regs->GR_L(11)=vmb; UPD_PSW_IA(regs, EVM_L(elist+28)); /* Exit +28 */ CPASSIST_HIT(DISP0); EVM_ST(DISPCNT,dlist); return; } /* Take exit 0 (DISPATCH) */ DEBUG_CPASSISTX(DISP0,logmsg("DISP0 : DISPATCH - Taking exit #0\n")); regs->GR_L(11)=vmb; UPD_PSW_IA(regs, EVM_L(elist+0)); /* Exit +0 */ CPASSIST_HIT(DISP0); EVM_ST(DISPCNT,dlist); return; } /******************************************************/ /* SCNRU Instruction : Scan Real Unit */ /* Invoked by DMKSCN */ /* E60D */ /* SCNRU D1(R1,B1),D2(R2,B2) */ /* */ /* Operations */ /* The Device Address specified in operand 1 is */ /* the real device address for which control block */ /* addresses are to be returned. The storage area */ /* designated as the 2nd operand is a list of 4 */ /* consecutive fullword (note : the 2nd operand is */ /* treated as a Real Address, regardless of any */ /* translation mode that may be in effect) */ /* +--------------------+-------------------+ */ /* | CHNLINDEX | RCHTABLE | */ /* +--------------------+-------------------+ */ /* | RCUTABLE | RDVTABLE | */ /* +--------------------+-------------------+ */ /* CHNLINDEX is an array of 16 halfwords, each */ /* representing the offset of the target's device */ /* channel's RCHBLOCK. If the channel is not defined */ /* in the RIO table, the index has bit 0, byte 0 set */ /* to 1 */ /* */ /* The RCHBLOK has at offset +X'20' a table of */ /* 32 possible control unit indices */ /* the device's address bit 8 to 12 are used to fetch */ /* the index specified at the table. If it has */ /* bit 0 byte 0 set, then the same operation is */ /* attempted with bits 8 to 11 */ /* The RCUBLOK then fetched from RCUTABLE + the index */ /* fetched from the RCHBLOK has a DEVICE index table */ /* at offset +X'28' which can be fetched by using */ /* bits 5-7 */ /* If the RCUBLOK designates an alternate control */ /* unit block, (Offset +X'5' bit 1 set), then */ /* the primary RCUBLOK is fetched from offset X'10' */ /* */ /* If no RCHBLOK is found, R6,R7 and R8 contain -1 */ /* and Condition Code 3 is set */ /* */ /* if no RCUBLOK is found, R6 contains the RCHBLOK, */ /* R7 and R8 contain -1, and Condition Code 2 is set */ /* */ /* if no RDVBLOK is found, R6 contains the RCHBLOK, */ /* R7 contains the RCUBLOK and R8 contains -1, and */ /* condition code 1 is set */ /* */ /* If all 3 control blocks are found, R6 contains the */ /* the RCHBLOK, R7 Contains the RCUBLOK and R8 cont- */ /* ains the RDVBLOK. Condition code 0 is set */ /* */ /* If the instruction is sucesfull, control is */ /* returned at the address specified by GPR14. */ /* Otherwise, the next sequential instruction is */ /* executed, and no GPR or condition code is changed. */ /* */ /* Exceptions : */ /* Operation Exception : ECPS:VM Disabled */ /* Priviledged Exception : PSW in problem state */ /* */ /* Note : no access exception is generated for */ /* the second operand. */ /* */ /* Note : as of yet, for any other situation than */ /* finding all 3 control blocks, SCNRU acts */ /* as a NO-OP */ /******************************************************/ DEF_INST(ecpsvm_locate_rblock) { U32 chix; /* offset of RCH in RCH Array */ U32 cuix; /* Offset of RCU in RCU Array */ U32 dvix; /* Offset of RDV in RDV Array */ VADR rchixtbl; /* RCH Index Table */ VADR rchtbl; /* RCH Array */ VADR rcutbl; /* RCU Array */ VADR rdvtbl; /* RDV Array */ VADR arioct; /* Data list for SCNRU */ VADR rchblk; /* Effective RCHBLOK Address */ VADR rcublk; /* Effective RCUBLOK Address */ VADR rdvblk; /* Effective RDVBLOK Address */ U16 rdev; ECPSVM_PROLOG(SCNRU); /* Obtain the Device address */ rdev=(effective_addr1 & 0xfff); /* And the DMKRIO tables addresses */ arioct=effective_addr2; DEBUG_CPASSISTX(SCNRU,logmsg(_("HHCEV300D : ECPS:VM SCNRU called; RDEV=%4.4X ARIOCT=%6.6X\n"),effective_addr1,arioct)); /* Get the Channel Index Table */ rchixtbl= EVM_L(effective_addr2); /* Obtain the RCH offset */ chix=EVM_LH(rchixtbl+((rdev & 0xf00) >> 7)); DEBUG_CPASSISTX(SCNRU,logmsg(_("HHCEV300D : ECPS:VM SCNRU : RCH IX = %x\n"),chix)); /* Check if Bit 0 set (no RCH) */ if(chix & 0x8000) { // logmsg(_("HHCEV300D : ECPS:VM SCNRU : NO CHANNEL\n")); /* regs->GR_L(6)=~0; regs->GR_L(7)=~0; regs->GR_L(8)=~0; UPD_PSW_IA(regs, regs->GR_L(14)); regs->psw.cc=1; */ /* Right now, let CP handle the case */ return; } /* Obtain the RCH Table pointer */ rchtbl=EVM_L(arioct+4); /* Add the RCH Index offset */ rchblk=rchtbl+chix; /* Try to obtain RCU index with bits 8-12 of the device */ cuix=EVM_LH(rchblk+0x20+((rdev & 0xf8)>>2)); if(cuix & 0x8000) { /* Try with bits 8-11 */ cuix=EVM_LH(rchblk+0x20+((rdev & 0xf0)>>2)); if(cuix & 0x8000) { // logmsg(_("HHCEV300D : ECPS:VM SCNRU : NO CONTROL UNIT\n")); /* regs->GR_L(6)=rchblk; regs->GR_L(7)=~0; regs->GR_L(8)=~0; UPD_PSW_IA(regs, regs->GR_L(14)); regs->psw.cc=2; */ return; } } DEBUG_CPASSISTX(SCNRU,logmsg(_("HHCEV300D : ECPS:VM SCNRU : RCU IX = %x\n"),cuix)); rcutbl=EVM_L(arioct+8); rcublk=rcutbl+cuix; dvix=EVM_LH(rcublk+0x28+((rdev & 0x00f)<<1)); if(EVM_IC(rcublk+5)&0x40) { rcublk=EVM_L(rcublk+0x10); } if(dvix & 0x8000) { // logmsg(_("HHCEV300D : ECPS:VM SCNRU : NO RDEVBLOK\n")); /* regs->GR_L(6)=rchblk; regs->GR_L(7)=rcublk; regs->GR_L(8)=~0; UPD_PSW_IA(regs, regs->GR_L(14)); regs->psw.cc=3; */ return; } DEBUG_CPASSISTX(SCNRU,logmsg(_("HHCEV300D : ECPS:VM SCNRU : RDV IX = %x\n"),dvix)); dvix<<=3; rdvtbl=EVM_L(arioct+12); rdvblk=rdvtbl+dvix; DEBUG_CPASSISTX(SCNRU,logmsg(_("HHCEV300D : ECPS:VM SCNRU : RCH = %6.6X, RCU = %6.6X, RDV = %6.6X\n"),rchblk,rcublk,rdvblk)); regs->GR_L(6)=rchblk; regs->GR_L(7)=rcublk; regs->GR_L(8)=rdvblk; regs->psw.cc=0; regs->GR_L(15)=0; BR14; CPASSIST_HIT(SCNRU); } /* CCWGN : Not supported */ DEF_INST(ecpsvm_comm_ccwproc) { ECPSVM_PROLOG(CCWGN); } /* UXCCW : Not supported */ DEF_INST(ecpsvm_unxlate_ccw) { ECPSVM_PROLOG(UXCCW); } /* DISP2 : Not supported */ DEF_INST(ecpsvm_disp2) { ECPSVM_PROLOG(DISP2); switch(ecpsvm_do_disp2(regs,effective_addr1,effective_addr2)) { case 0: /* Done */ CPASSIST_HIT(DISP2); return; case 1: /* No-op */ return; case 2: /* Done */ CPASSIST_HIT(DISP2); RETURN_INTCHECK(regs); } return; } /* STEVL : Store ECPS:VM support level */ /* STEVL D1(R1,B1),D2(R2,B2) */ /* 1st operand : Fullword address in which to store ECPS:VM Support level */ /* 2nd operand : ignored */ DEF_INST(ecpsvm_store_level) { ECPSVM_PROLOG(STEVL); EVM_ST(sysblk.ecpsvm.level,effective_addr1); DEBUG_CPASSISTX(STEVL,logmsg(_("HHCEV300D : ECPS:VM STORE LEVEL %d called\n"),sysblk.ecpsvm.level)); CPASSIST_HIT(STEVL); } /* LCSPG : Locate Changed Shared Page */ /* LCSPG : Not supported */ DEF_INST(ecpsvm_loc_chgshrpg) { ECPSVM_PROLOG(LCSPG); } /*************************************************************/ /* FREEX : Allocate CP Storage Extended */ /* FREEX B1(R1,B1),D2(R2,B2) */ /* 1st operand : Address of FREEX Parameter list */ /* +0 : Maxsize = Max number of DW allocatable */ /* with FREEX */ /* +4- : Subpool index table */ /* 2nd operand : Subpool table (indexed) */ /* GPR 0 : Number of DWs to allocate */ /* */ /* Each allocatable block is forward chained */ /* if the subpool is empty, return to caller */ /* if the subpool has an entry, allocate from the subpool */ /* and save the next block address as the subpool chain head */ /* return allocated block in GPR1. return at address in GPR14*/ /* if allocation succeeded */ /* if allocate fails, return at next sequential instruction */ /*************************************************************/ DEF_INST(ecpsvm_extended_freex) { U32 maxdw; U32 numdw; U32 maxsztbl; U32 spixtbl; BYTE spix; U32 freeblock; U32 nextblk; ECPSVM_PROLOG(FREEX); numdw=regs->GR_L(0); spixtbl=effective_addr2; maxsztbl=effective_addr1; DEBUG_CPASSISTX(FREEX,logmsg(_("HHCEV300D : ECPS:VM FREEX DW = %4.4X\n"),numdw)); if(numdw==0) { return; } DEBUG_CPASSISTX(FREEX,logmsg(_("HHCEV300D : MAXSIZE ADDR = %6.6X, SUBPOOL INDEX TABLE = %6.6X\n"),maxsztbl,spixtbl)); /* E1 = @ of MAXSIZE (maximum # of DW allocatable by FREEX from subpools) */ /* followed by subpool pointers */ /* E2 = @ of subpool indices */ maxdw=EVM_L(maxsztbl); if(regs->GR_L(0)>maxdw) { DEBUG_CPASSISTX(FREEX,logmsg(_("HHCEV300D : FREEX request beyond subpool capacity\n"))); return; } /* Fetch subpool index */ spix=EVM_IC(spixtbl+numdw); DEBUG_CPASSISTX(FREEX,logmsg(_("HHCEV300D : Subpool index = %X\n"),spix)); /* Fetch value */ freeblock=EVM_L(maxsztbl+4+spix); DEBUG_CPASSISTX(FREEX,logmsg(_("HHCEV300D : Value in subpool table = %6.6X\n"),freeblock)); if(freeblock==0) { /* Can't fullfill request here */ return; } nextblk=EVM_L(freeblock); EVM_ST(nextblk,maxsztbl+4+spix); DEBUG_CPASSISTX(FREEX,logmsg(_("HHCEV300D : New Value in subpool table = %6.6X\n"),nextblk)); regs->GR_L(1)=freeblock; regs->psw.cc=0; BR14; CPASSIST_HIT(FREEX); return; } /*************************************************************/ /* FRETX : Return CP Free storage */ /* FRETX D1(R1,B1),R2(D2,B2) */ /* 1st operand : Max DW for subpool free/fret */ /* 2nd Operand : FRET PLIST */ /* +0 Coretable address */ /* +4 CL4'FREE' */ /* +8 Maxsize (same as operand 1) */ /* +12 Subpool Table Index */ /* The block is checked VS the core table to check if it */ /* is eligible to be returned to the subpool chains */ /* If it is, then it is returned. Control is returned at */ /* the address in GPR 14. Otherwise, if anything cannot */ /* be resolved, control is returned at the next sequential */ /* Instruction */ /*************************************************************/ int ecpsvm_do_fretx(REGS *regs,VADR block,U16 numdw,VADR maxsztbl,VADR fretl) { U32 cortbl; U32 maxdw; U32 cortbe; /* Core table Page entry for fretted block */ U32 prevblk; BYTE spix; DEBUG_CPASSISTX(FRETX,logmsg(_("HHCEV300D : X fretx called AREA=%6.6X, DW=%4.4X\n"),regs->GR_L(1),regs->GR_L(0))); if(numdw==0) { DEBUG_CPASSISTX(FRETX,logmsg(_("HHCEV300D : ECPS:VM Cannot FRETX : DWORDS = 0\n"))); return(1); } maxdw=EVM_L(maxsztbl); if(numdw>maxdw) { DEBUG_CPASSISTX(FRETX,logmsg(_("HHCEV300D : ECPS:VM Cannot FRETX : DWORDS = %d > MAXDW %d\n"),numdw,maxdw)); return(1); } cortbl=EVM_L(fretl); cortbe=cortbl+((block & 0xfff000)>>8); if(EVM_L(cortbe)!=EVM_L(fretl+4)) { DEBUG_CPASSISTX(FRETX,logmsg(_("HHCEV300D : ECPS:VM Cannot FRETX : Area not in Core Free area\n"))); return(1); } if(EVM_IC(cortbe+8)!=0x02) { DEBUG_CPASSISTX(FRETX,logmsg(_("HHCEV300D : ECPS:VM Cannot FRETX : Area flag != 0x02\n"))); return(1); } spix=EVM_IC(fretl+11+numdw); prevblk=EVM_L(maxsztbl+4+spix); if(prevblk==block) { DEBUG_CPASSISTX(FRETX,logmsg(_("HHCEV300D : ECPS:VM Cannot FRETX : fretted block already on subpool chain\n"))); return(1); } EVM_ST(block,maxsztbl+4+spix); EVM_ST(prevblk,block); return(0); } DEF_INST(ecpsvm_extended_fretx) { U32 fretl; U32 maxsztbl; U32 numdw; U32 block; ECPSVM_PROLOG(FRETX); numdw=regs->GR_L(0); block=regs->GR_L(1) & ADDRESS_MAXWRAP(regs); maxsztbl=effective_addr1 & ADDRESS_MAXWRAP(regs); fretl=effective_addr2 & ADDRESS_MAXWRAP(regs); if(ecpsvm_do_fretx(regs,block,numdw,maxsztbl,fretl)==0) { BR14; CPASSIST_HIT(FRETX); } return; } DEF_INST(ecpsvm_prefmach_assist) { ECPSVM_PROLOG(PMASS); } /**********************************/ /* VM ASSISTS */ /**********************************/ /******************************************************************/ /* LPSW/SSM/STxSM : */ /* Not sure about the current processing .. */ /* *MAYBE* we need to invoke DMKDSPCH when the newly loaded PSW */ /* does not need further checking. Now.. I wonder what the point */ /* is to return to CP anyway, as we have entirelly validated the */ /* new PSW (i.e. for most of it, this is essentially a BRANCH */ /* However... */ /* Maybe we should call DMKDSPCH (from the DMKPRVMA list) */ /* only if re-enabling bits (and no Int pending) */ /* */ /* For the time being, we do THIS : */ /* If the new PSW 'disables' bits or enables bit but MICPEND=0 */ /* we just update the VPSW and continue */ /* Same for LPSW.. But we also update the IA */ /* If we encounter ANY issue, we just return to caller (which will*/ /* generate a PRIVOP) thus invoking CP like for non-EVMA */ /******************************************************************/ /******************************************************************/ /* Check psw Transition validity */ /******************************************************************/ /* NOTE : oldr/newr Only have the PSW field valid (the rest is not initialised) */ int ecpsvm_check_pswtrans(REGS *regs,ECPSVM_MICBLOK *micblok, BYTE micpend, REGS *oldr, REGS *newr) { UNREFERENCED(micblok); UNREFERENCED(regs); SET_PSW_IA(newr); SET_PSW_IA(oldr); /* Check for a switch from BC->EC or EC->BC */ if(ECMODE(&oldr->psw)!=ECMODE(&newr->psw)) { DEBUG_SASSISTX(LPSW,logmsg(_("HHCEV300D : New and Old PSW have a EC/BC transition\n"))); return(1); } /* Check if PER or DAT is being changed */ if(ECMODE(&newr->psw)) { if((newr->psw.sysmask & 0x44) != (oldr->psw.sysmask & 0x44)) { DEBUG_SASSISTX(LPSW,logmsg(_("HHCEV300D : New PSW Enables DAT or PER\n"))); return(1); } } /* Check if a Virtual interrupt is pending and new interrupts are being enabled */ if(micpend & 0x80) { if(ECMODE(&newr->psw)) { if(((~oldr->psw.sysmask) & 0x03) & newr->psw.sysmask) { DEBUG_SASSISTX(LPSW,logmsg(_("HHCEV300D : New PSW Enables interrupts and MICPEND (EC)\n"))); return(1); } } else { if(~oldr->psw.sysmask & newr->psw.sysmask) { DEBUG_SASSISTX(LPSW,logmsg(_("HHCEV300D : New PSW Enables interrupts and MICPEND (BC)\n"))); return(1); } } } if(WAITSTATE(&newr->psw)) { DEBUG_SASSISTX(LPSW,logmsg(_("HHCEV300D : New PSW is a WAIT PSW\n"))); return(1); } if(ECMODE(&newr->psw)) { if(newr->psw.sysmask & 0xb8) { DEBUG_SASSISTX(LPSW,logmsg(_("HHCEV300D : New PSW sysmask incorrect\n"))); return(1); } } if(newr->psw.IA & 0x01) { DEBUG_SASSISTX(LPSW,logmsg(_("HHCEV300D : New PSW has ODD IA\n"))); return(1); } return(0); } int ecpsvm_dossm(REGS *regs,int b2,VADR effective_addr2) { BYTE reqmask; BYTE *cregs; U32 creg0; REGS npregs; SASSIST_PROLOG(SSM); /* Reject if V PSW is in problem state */ if(CR6 & ECPSVM_CR6_VIRTPROB) { DEBUG_SASSISTX(SSM,logmsg("HHCEV300D : SASSIST SSM reject : V PB State\n")); return(1); } /* if(!(micevma & MICSTSM)) { DEBUG_SASSISTX(SSM,logmsg("HHCEV300D : SASSIST SSM reject : SSM Disabled in MICEVMA; EVMA=%2.2X\n",micevma)); return(1); } */ /* Get CR0 - set ref bit on fetched CR0 (already done in prolog for MICBLOK) */ cregs=MADDR(micblok.MICCREG,USE_REAL_ADDR,regs,ACCTYPE_READ,0); FETCH_FW(creg0,cregs); /* Reject if V CR0 specifies SSM Suppression */ if(creg0 & 0x40000000) { DEBUG_SASSISTX(SSM,logmsg("HHCEV300D : SASSIST SSM reject : V SSM Suppr\n")); return(1); } /* Load the requested SSM Mask */ /* USE Normal vfetchb here ! not only do we want tranlsation */ /* but also fetch protection control, ref bit, etc.. */ reqmask=ARCH_DEP(vfetchb) (effective_addr2,b2,regs); INITPSEUDOREGS(npregs); /* Load the virtual PSW AGAIN in a new structure */ ARCH_DEP(load_psw) (&npregs,vpswa_p); npregs.psw.sysmask=reqmask; if(ecpsvm_check_pswtrans(regs,&micblok,micpend,&vpregs,&npregs)) /* Check PSW transition capability */ { DEBUG_SASSISTX(SSM,logmsg("HHCEV300D : SASSIST SSM Reject : New PSW too complex\n")); return(1); /* Something in the NEW PSW we can't handle.. let CP do it */ } /* While we are at it, set the IA in the V PSW */ SET_PSW_IA(regs); UPD_PSW_IA(&npregs, regs->psw.IA); /* Set the change bit */ MADDR(vpswa,USE_REAL_ADDR,regs,ACCTYPE_WRITE,0); /* store the new PSW */ ARCH_DEP(store_psw) (&npregs,vpswa_p); DEBUG_SASSISTX(SSM,logmsg("HHCEV300D : SASSIST SSM Complete : new SM = %2.2X\n",reqmask)); DEBUG_SASSISTX(LPSW,logmsg("HHCEV300D : SASSIST SSM New VIRT ")); DEBUG_SASSISTX(LPSW,display_psw(&npregs)); DEBUG_SASSISTX(LPSW,logmsg("HHCEV300D : SASSIST SSM New REAL ")); DEBUG_SASSISTX(LPSW,display_psw(regs)); SASSIST_HIT(SSM); return(0); } int ecpsvm_dosvc(REGS *regs,int svccode) { PSA_3XX *psa; REGS newr; SASSIST_PROLOG(SVC); if(svccode==76) /* NEVER trap SVC 76 */ { DEBUG_SASSISTX(SVC,logmsg("HHCEV300D : SASSIST SVC Reject : SVC 76\n")); return(1); } if(CR6 & ECPSVM_CR6_SVCINHIB) { DEBUG_SASSISTX(SVC,logmsg("HHCEV300D : SASSIST SVC Reject : SVC Assist Inhibit\n")); return(1); /* SVC SASSIST INHIBIT ON */ } /* Get what the NEW PSW should be */ psa=(PSA_3XX *)MADDR((VADR)0 , USE_PRIMARY_SPACE, regs, ACCTYPE_READ, 0); /* Use all around access key 0 */ /* Also sets reference bit */ INITPSEUDOREGS(newr); ARCH_DEP(load_psw) (&newr, (BYTE *)&psa->svcnew); /* Ref bit set above */ DEBUG_SASSISTX(SVC,logmsg("HHCEV300D : SASSIST SVC NEW VIRT ")); DEBUG_SASSISTX(SVC,display_psw(&newr)); /* Get some stuff from the REAL Running PSW to put in OLD SVC PSW */ SET_PSW_IA(regs); UPD_PSW_IA(&vpregs, regs->psw.IA); /* Instruction Address */ vpregs.psw.cc=regs->psw.cc; /* Condition Code */ vpregs.psw.pkey=regs->psw.pkey; /* Protection Key */ vpregs.psw.progmask=regs->psw.progmask; /* Program Mask */ vpregs.psw.intcode=svccode; /* SVC Interrupt code */ DEBUG_SASSISTX(SVC,logmsg("HHCEV300D : SASSIST SVC OLD VIRT ")); DEBUG_SASSISTX(SVC,display_psw(&vpregs)); if(ecpsvm_check_pswtrans(regs,&micblok,micpend,&vpregs,&newr)) /* Check PSW transition capability */ { DEBUG_SASSISTX(SVC,logmsg("HHCEV300D : SASSIST SVC Reject : Cannot make transition to new PSW\n")); return(1); /* Something in the NEW PSW we can't handle.. let CP do it */ } /* Store the OLD SVC PSW */ // ZZ psa=(PSA_3XX *)MADDR((VADR)0, USE_PRIMARY_SPACE, regs, ACCTYPE_WRITE, 0); /* Use all around access key 0 */ /* Also sets change bit */ /* Set intcode in PSW (for BC mode) */ ARCH_DEP(store_psw) (&vpregs, (BYTE *)&psa->svcold); if(ECMODE(&vpregs.psw)) { /* Also set SVC interrupt code */ /* and ILC */ STORE_FW((BYTE *)&psa->svcint,0x00020000 | svccode); } /* * Now, update some stuff in the REAL PSW */ SASSIST_LPSW(newr); /* * Now store the new PSW in the area pointed by the MICBLOK */ ARCH_DEP(store_psw) (&newr,vpswa_p); DEBUG_SASSISTX(SVC,logmsg("HHCEV300D : SASSIST SVC Done\n")); SASSIST_HIT(SVC); return(0); } /* LPSW Assist */ int ecpsvm_dolpsw(REGS *regs,int b2,VADR e2) { BYTE * nlpsw; REGS nregs; SASSIST_PROLOG(LPSW); /* Reject if V PSW is in problem state */ if(CR6 & ECPSVM_CR6_VIRTPROB) { DEBUG_SASSISTX(LPSW,logmsg("HHCEV300D : SASSIST LPSW reject : V PB State\n")); return(1); } /* Reject if MICEVMA says not to do LPSW sim */ if(!(micevma & MICLPSW)) { DEBUG_SASSISTX(LPSW,logmsg("HHCEV300D : SASSIST LPSW reject : LPSW disabled in MICEVMA\n")); return(1); } if(e2&0x03) { DEBUG_SASSISTX(LPSW,logmsg("HHCEV300D : SASSIST LPSW %6.6X - Alignement error\n",e2)); return(1); } nlpsw=MADDR(e2,b2,regs,ACCTYPE_READ,regs->psw.pkey); INITPSEUDOREGS(nregs); ARCH_DEP(load_psw) (&nregs,nlpsw); if(ecpsvm_check_pswtrans(regs,&micblok,micpend,&vpregs,&nregs)) { DEBUG_SASSISTX(LPSW,logmsg("HHCEV300D : SASSIST LPSW Rejected - Cannot make PSW transition\n")); return(1); } SASSIST_LPSW(nregs); MADDR(vpswa,USE_REAL_ADDR,regs,ACCTYPE_WRITE,0); /* Set ref bit in address pointed by MICBLOK */ ARCH_DEP(store_psw) (&nregs,vpswa_p); DEBUG_SASSISTX(LPSW,logmsg("HHCEV300D : SASSIST LPSW New VIRT ")); DEBUG_SASSISTX(LPSW,display_psw(&nregs)); DEBUG_SASSISTX(LPSW,logmsg("HHCEV300D : SASSIST LPSW New REAL ")); DEBUG_SASSISTX(LPSW,display_psw(regs)); SASSIST_HIT(LPSW); return(0); } int ecpsvm_virttmr_ext(REGS *regs) { DEBUG_SASSISTX(VTIMER,logmsg("HHCEV300D : SASSIST VTIMER Checking if we can IRPT\n")); DEBUG_SASSISTX(VTIMER,logmsg("HHCEV300D : SASSIST VTIMER Virtual")); DEBUG_SASSISTX(VTIMER,display_psw(regs)); if(IS_IC_ECPSVTIMER(regs)) { DEBUG_SASSISTX(VTIMER,logmsg("HHCEV300D : SASSIST VTIMER Not pending\n")); return(1); } if(!PROBSTATE(®s->psw)) { DEBUG_SASSISTX(VTIMER,logmsg("HHCEV300D : SASSIST VTIMER Not dispatching a VM\n")); return(1); } if(!(regs->psw.sysmask & PSW_EXTMASK)) { DEBUG_SASSISTX(VTIMER,logmsg("HHCEV300D : SASSIST VTIMER Test int : Not enabled for EXT\n")); return(1); } if(!(regs->CR_L(6) & ECPSVM_CR6_VIRTTIMR)) { DEBUG_SASSISTX(VTIMER,logmsg("HHCEV300D : SASSIST VTIMER Test int : Not enabled for VTIMER\n")); return(1); } DEBUG_SASSISTX(VTIMER,logmsg("HHCEV300D : SASSIST VTIMER Please, do\n")); return(0); } /* SIO/SIOF Assist */ int ecpsvm_dosio(REGS *regs,int b2,VADR e2) { SASSIST_PROLOG(SIO); UNREFERENCED(b2); UNREFERENCED(e2); return(1); } int ecpsvm_dostnsm(REGS *regs,int b1,VADR effective_addr1,int imm2) { SASSIST_PROLOG(STNSM); UNREFERENCED(b1); UNREFERENCED(effective_addr1); UNREFERENCED(imm2); return(1); } int ecpsvm_dostosm(REGS *regs,int b1,VADR effective_addr1,int imm2) { SASSIST_PROLOG(STOSM); UNREFERENCED(b1); UNREFERENCED(effective_addr1); UNREFERENCED(imm2); return(1); } int ecpsvm_dostctl(REGS *regs,int r1,int r3,int b2,VADR effective_addr2) { SASSIST_PROLOG(STCTL); UNREFERENCED(r1); UNREFERENCED(r3); UNREFERENCED(b2); UNREFERENCED(effective_addr2); return(1); } int ecpsvm_dolctl(REGS *regs,int r1,int r3,int b2,VADR effective_addr2) { U32 crs[16]; /* New CRs */ U32 rcrs[16]; /* REAL CRs */ U32 ocrs[16]; /* Old CRs */ BYTE *ecb_p; VADR F_ECBLOK,vmb; BYTE B_VMPSTAT; int i,j,numcrs; SASSIST_PROLOG(LCTL); if(effective_addr2 & 0x03) { DEBUG_SASSISTX(LCTL,logmsg("HHCEV300D : SASSIST LCTL Reject : Not aligned\n")); return(1); } vmb=vpswa-0xA8; B_VMPSTAT=EVM_IC(vmb+VMPSTAT); if((!(B_VMPSTAT & VMV370R)) && ((r1!=r3) || (r1!=0))) { DEBUG_SASSISTX(LCTL,logmsg("HHCEV300D : SASSIST LCTL Reject : BC Mode VM & LCTL != 0,0\n")); return(1); } /* Determine the range of CRs to be loaded */ if(r1>r3) { numcrs=(r3+16)-r1; } else { numcrs=r3-r1; } numcrs++; for(j=r1,i=0;i15) { j-=16; } crs[j]=ARCH_DEP(vfetch4)((effective_addr2+(i*4)) & ADDRESS_MAXWRAP(regs),b2,regs); } if(B_VMPSTAT & VMV370R) { F_ECBLOK=fetch_fw(regs->mainstor+vmb+VMECEXT); for(i=0;i<16;i++) { ecb_p=MADDR(F_ECBLOK+(i*4),USE_REAL_ADDR,regs,ACCTYPE_READ,0); ocrs[i]=fetch_fw(ecb_p); } } else { F_ECBLOK=vmb+VMECEXT; /* Update ECBLOK ADDRESS for VCR0 Update */ ecb_p=MADDR(F_ECBLOK,USE_REAL_ADDR,regs,ACCTYPE_READ,0); /* Load OLD CR0 From VMBLOK */ ocrs[0]=fetch_fw(ecb_p); } for(i=0;i<16;i++) { rcrs[i]=regs->CR_L(i); } /* Source safely loaded into "crs" array */ /* Load the CRS - exit from loop if it's not possible */ DEBUG_SASSISTX(LCTL,logmsg("HHCEV300D : SASSIST LCTL %d,%d : Modifying %d cregs\n",r1,r3,numcrs)); for(j=r1,i=0;i15) { j-=16; } switch(j) { case 0: /* CR0 Case */ /* Check 1st 2 bytes of CR0 - No change allowed */ if((ocrs[0] & 0xffff0000) != (crs[0] & 0xffff0000)) { DEBUG_SASSISTX(LCTL,logmsg("HHCEV300D : SASSIST LCTL Reject : CR0 High changed\n")); return 1; } /* Not allowed if : NEW mask is being enabled AND MICPEND AND PSW has EXT enabled */ if(vpregs.psw.sysmask & 0x01) { if(micpend & 0x80) { if((~(ocrs[0] & 0xffff)) & (crs[0] & 0xffff)) { DEBUG_SASSISTX(LCTL,logmsg("HHCEV300D : SASSIST LCTL Reject : CR0 EXTSM Enables new EXTS\n")); return 1; } } } ocrs[0]=crs[0]; break; case 1: if(ocrs[1] != crs[1]) { DEBUG_SASSISTX(LCTL,logmsg("HHCEV300D : SASSIST LCTL Reject : CR1 Updates shadow table\n")); return 1; } break; case 2: /* Not allowed if : NEW Channel mask is turned on AND micpend AND PSW Extended I/O Mask is on */ if(vpregs.psw.sysmask & 0x02) { if((~ocrs[2]) & crs[2]) { if(micpend & 0x80) { DEBUG_SASSISTX(LCTL,logmsg("HHCEV300D : SASSIST LCTL Reject : CR2 IOCSM Enables I/O Ints\n")); return(1); } } } ocrs[2]=crs[2]; break; case 3: /* DAS Control regs (not used under VM/370) */ case 4: case 5: case 7: ocrs[j]=crs[j]; rcrs[j]=crs[j]; break; case 6: /* VCR6 Ignored on real machine */ ocrs[j]=crs[j]; break; case 8: /* Monitor Calls */ DEBUG_SASSISTX(LCTL,logmsg("HHCEV300D : SASSIST LCTL Reject : MC CR8 Update\n")); return(1); case 9: /* PER Control Regs */ case 10: case 11: DEBUG_SASSISTX(LCTL,logmsg("HHCEV300D : SASSIST LCTL Reject : PER CR%d Update\n",j)); return(1); case 12: case 13: /* 12-13 : Unused */ ocrs[j]=crs[j]; rcrs[j]=crs[j]; break; case 14: case 15: /* 14-15 Machine Check & I/O Logout control (plus DAS) */ ocrs[j]=crs[j]; break; default: break; } } /* Update REAL Control regs */ for(i=0;i<16;i++) { regs->CR_L(i)=rcrs[i]; } /* Update ECBLOK/VMBLOK Control regs */ /* Note : if F_ECBLOK addresses VMVCR0 in the VMBLOCK */ /* check has already been done to make sure */ /* r1=0 and numcrs=1 */ for(j=r1,i=0;i15) { j-=16; } ecb_p=MADDR(F_ECBLOK+(j*4),USE_REAL_ADDR,regs,ACCTYPE_WRITE,0); store_fw(ecb_p,ocrs[j]); } DEBUG_SASSISTX(LCTL,logmsg("HHCEV300D : SASSIST LCTL %d,%d Done\n",r1,r3)); SASSIST_HIT(LCTL); return 0; } int ecpsvm_doiucv(REGS *regs,int b2,VADR effective_addr2) { SASSIST_PROLOG(IUCV); UNREFERENCED(b2); UNREFERENCED(effective_addr2); return(1); } int ecpsvm_dodiag(REGS *regs,int r1,int r3,int b2,VADR effective_addr2) { SASSIST_PROLOG(DIAG); UNREFERENCED(r1); UNREFERENCED(r3); UNREFERENCED(b2); UNREFERENCED(effective_addr2); return(1); } static char *ecpsvm_stat_sep="HHCEV003I +-----------+----------+----------+-------+\n"; static int ecpsvm_sortstats(const void *a,const void *b) { ECPSVM_STAT *ea,*eb; ea=(ECPSVM_STAT *)a; eb=(ECPSVM_STAT *)b; return(eb->call-ea->call); } static void ecpsvm_showstats2(ECPSVM_STAT *ar,size_t count) { char *sep=ecpsvm_stat_sep; char nname[32]; int havedisp=0; int notshown=0; size_t unsupcc=0; int haveunsup=0; int callt=0; int hitt=0; size_t i; for(i=0;iname)==0) { *fclass="VM ASSIST"; return(es); } } esl=(ECPSVM_STAT *)&ecpsvm_cpstats; fcount=sizeof(ecpsvm_cpstats)/sizeof(ECPSVM_STAT); for(i=0;iname)==0) { *fclass="CP ASSIST"; return(es); } } return(NULL); } void ecpsvm_enadisaall(char *fclass,ECPSVM_STAT *tbl,size_t count,int onoff,int debug) { ECPSVM_STAT *es; size_t i; char *enadisa,*debugonoff; enadisa=onoff?"Enabled":"Disabled"; debugonoff=debug?"On":"Off"; for(i=0;i=0) { es->enabled=onoff; logmsg(_("HHCEV015I ECPS:VM %s feature %s %s\n"),fclass,es->name,enadisa); } if(debug>=0) { es->debug=debug; logmsg(_("HHCEV015I ECPS:VM %s feature %s Debug %s\n"),fclass,es->name,debugonoff); } } if(onoff>=0) { logmsg(_("HHCEV016I All ECPS:VM %s features %s\n"),fclass,enadisa); } if(debug>=0) { logmsg(_("HHCEV016I All ECPS:VM %s features Debug %s\n"),fclass,debugonoff); } } void ecpsvm_enable_disable(int ac,char **av,int onoff,int debug) { char *fclass; char *enadisa,*debugonoff; int i; size_t sacount,cpcount; ECPSVM_STAT *es; ECPSVM_STAT *sal,*cpl; sal=(ECPSVM_STAT *)&ecpsvm_sastats; cpl=(ECPSVM_STAT *)&ecpsvm_cpstats; sacount=sizeof(ecpsvm_sastats)/sizeof(ECPSVM_STAT); cpcount=sizeof(ecpsvm_cpstats)/sizeof(ECPSVM_STAT); enadisa=onoff?"Enabled":"Disabled"; debugonoff=debug?"On":"Off"; if(ac==1) { ecpsvm_enadisaall("VM ASSIST",sal,sacount,onoff,debug); ecpsvm_enadisaall("CP ASSIST",cpl,cpcount,onoff,debug); if(debug>=0) { sysblk.ecpsvm.debug=debug; logmsg(_("HHCEV013I ECPS:VM Global Debug %s\n"),debugonoff); } return; } for(i=1;i=0) { es->enabled=onoff; logmsg(_("HHCEV014I ECPS:VM %s feature %s %s\n"),fclass,es->name,enadisa); } if(debug>=0) { es->debug=onoff; logmsg(_("HHCEV014I ECPS:VM %s feature %s Debug %s\n"),fclass,es->name,debugonoff); } } else { logmsg(_("HHCEV014I Unknown ECPS:VM feature %s; Ignored\n"),av[i]); } } } void ecpsvm_disable(int ac,char **av) { ecpsvm_enable_disable(ac,av,0,-1); } void ecpsvm_enable(int ac,char **av) { ecpsvm_enable_disable(ac,av,1,-1); } void ecpsvm_debug(int ac,char **av) { ecpsvm_enable_disable(ac,av,-1,1); } void ecpsvm_nodebug(int ac,char **av) { ecpsvm_enable_disable(ac,av,-1,0); } void ecpsvm_level(int ac,char **av) { int lvl; if(sysblk.ecpsvm.available) { logmsg(_("HHCEV016I Current reported ECPS:VM Level is %d\n"),sysblk.ecpsvm.level); } else { logmsg(_("HHCEV016I Current reported ECPS:VM Level is %d\n"),sysblk.ecpsvm.level); logmsg(_("HHCEV017I But ECPS:VM is currently disabled\n")); } if(ac>1) { lvl=atoi(av[1]); logmsg(_("HHCEV016I Level reported to guest program is now %d\n"),lvl); sysblk.ecpsvm.level=lvl; } if(sysblk.ecpsvm.level!=20) { logmsg(_("HHCEV017W WARNING ! current level (%d) is not supported\n"),sysblk.ecpsvm.level); logmsg(_("HHCEV018W WARNING ! Unpredictable results may occur\n")); logmsg(_("HHCEV019I The microcode support level is 20\n")); } } static void ecpsvm_helpcmd(int,char **); static ECPSVM_CMDENT ecpsvm_cmdtab[]={ {"Help",1,ecpsvm_helpcmd,"Show help","format : \"evm help [cmd]\" Shows help on the specified\n" " ECPSVM subcommand\n"}, {"STats",2,ecpsvm_showstats,"Show statistical counters","format : evm stats : Shows various ECPS:VM Counters\n"}, {"DIsable",2,ecpsvm_disable,"Disable ECPS:VM Features","format : evm disable [ALL|feat1[ feat2|...]\n"}, {"ENable",2,ecpsvm_enable,"Enable ECPS:VM Features","format : evm enable [ALL|feat1[ feat2|...]\n"}, #if defined(DEBUG_SASSIST) || defined(DEBUG_CPASSIST) {"DEBUG",5,ecpsvm_debug,"Debug ECPS:VM Features","format : evm debug [ALL|feat1[ feat2|...]\n"}, {"NODebug",3,ecpsvm_nodebug,"Turn Debug off for ECPS:VM Features","format : evm NODebug [ALL|feat1[ feat2|...]\n"}, #endif {"Level",1,ecpsvm_level,"Set/Show ECPS:VM level","format : evm Level [nn]\n"}, {NULL,0,NULL,NULL,NULL}}; static void ecpsvm_helpcmdlist(void) { int i; ECPSVM_CMDENT *ce; for(i=0;ecpsvm_cmdtab[i].name;i++) { ce=&ecpsvm_cmdtab[i]; logmsg(_("HHCEV010I : %s : %s\n"),ce->name,ce->expl); } return; } void ecpsvm_helpcmd(int ac,char **av) { ECPSVM_CMDENT *ce; if(ac==1) { ecpsvm_helpcmdlist(); return; } ce=ecpsvm_getcmdent(av[1]); if(ce==NULL) { logmsg(_("HHCEV011E Unknown subcommand %s - valid subcommands are :\n"),av[1]); ecpsvm_helpcmdlist(); return; } logmsg(_("HHCEV012I : %s : %s"),ce->name,ce->help); return; } ECPSVM_CMDENT *ecpsvm_getcmdent(char *cmd) { ECPSVM_CMDENT *ce; int i; int clen; for(i=0;ecpsvm_cmdtab[i].name;i++) { ce=&ecpsvm_cmdtab[i]; if(strlen(cmd)<=strlen(ce->name) && strlen(cmd)>=(size_t)ce->abbrev) { clen=strlen(cmd); if(strncasecmp(cmd,ce->name,clen)==0) { return(ce); } } } return(NULL); } void ecpsvm_command(int ac,char **av) { ECPSVM_CMDENT *ce; logmsg(_("HHCEV011I ECPS:VM Command processor invoked\n")); if(ac==1) { logmsg(_("HHCEV008E NO EVM subcommand. Type \"evm help\" for a list of valid subcommands\n")); return; } ce=ecpsvm_getcmdent(av[1]); if(ce==NULL) { logmsg(_("HHCEV008E Unknown EVM subcommand %s\n"),av[1]); return; } ce->fun(ac-1,av+1); logmsg(_("HHCEV011I ECPS:VM Command processor complete\n")); } #endif /* ifdef FEATURE_ECPSVM */ /* Note : The following forces inclusion for S/390 & z/ARCH */ /* This is necessary just in order to properly define */ /* S/390 auxialiary routines invoked by S/370 routines */ /* because of SIE */ #if !defined(_GEN_ARCH) #if defined(_ARCHMODE2) #define _GEN_ARCH _ARCHMODE2 #include "ecpsvm.c" #endif #if defined(_ARCHMODE3) #undef _GEN_ARCH #define _GEN_ARCH _ARCHMODE3 #include "ecpsvm.c" #endif #endif /*!defined(_GEN_ARCH)*/ hercules-3.07/ecpsvm.h000644 000765 000765 00000025300 11143760543 016415 0ustar00jmaynardjmaynard000000 000000 // $Id: ecpsvm.h 4102 2006-12-08 09:43:35Z jj $ // // $Log$ #ifndef __ECPSVM_H__ #define __ECPSVM_H__ /* CR6 Definitions */ #define ECPSVM_CR6_VMASSIST 0x80000000 /* DO Privop Sim */ #define ECPSVM_CR6_VIRTPROB 0x40000000 /* Running user in Problem State */ #define ECPSVM_CR6_ISKINHIB 0x20000000 /* Inhibit ISK/SSK Sim */ #define ECPSVM_CR6_S360ONLY 0x10000000 /* Only S/360 Operations */ #define ECPSVM_CR6_SVCINHIB 0x08000000 /* No SVC sim */ #define ECPSVM_CR6_STVINHIB 0x04000000 /* No Shadow Table Validation */ #define ECPSVM_CR6_ECPSVM 0x02000000 /* ECPS:VM Enable */ #define ECPSVM_CR6_VIRTTIMR 0x01000000 /* Virtual Interval Timer update */ #define ECPSVM_CR6_MICBLOK 0x00FFFFF8 /* MICBLOK Address mask */ #define ECPSVM_CR6_VMMVSAS 0x00000004 /* VM Assists for MVS Enable (370E) */ /* CR6 Definitions (VMBLOK style) */ #define VMMFE 0x80 #define VMMPROB 0x40 #define VMMNOSK 0x20 #define VMM360 0x10 #define VMMSVC 0x08 #define VMMSHADT 0x04 #define VMMCPAST 0x02 #define VMMVTMR 0x01 /* MICBLOK */ typedef struct _ECPSVM_MICBLOK { U32 MICRSEG; U32 MICCREG; U32 MICVPSW; #define MICVIP MICVPSW #define MICPEND 0x80 U32 MICWORK; U32 MICVTMR; U32 MICACF; U32 RESERVED1; U32 RESERVED2; U32 MICCREG0; U32 RESERVED3; /* Bits defined in MICEVMA */ #define MICLPSW 0x80 /* LPSW SIM */ #define MICPTLB 0x40 /* PTLB SIM */ #define MICSCSP 0x20 /* SCKC, SPT SIM */ #define MICSIO 0x10 /* SIO, SIOF SIM */ #define MICSTSM 0x08 /* SSM, STNSM, STOSM SIM */ #define MICSTPT 0x04 /* STPT SIM */ #define MICTCH 0x02 /* TCH SIM */ #define MICDIAG 0x01 /* DIAG SIM */ /* Hint : The following bits may be irrelevant for ECPS:VM Level 20 */ /* Bits defined in MICEVMA2 */ /* V=R Shadow Table Bypass assists */ #define MICSTBVR 0x80 /* V=R STBYPASS Assist active */ #define MICPTLB2 0x40 /* VRSTBYPASS PTLB Simulation */ #define MICIPTP2 0x20 /* VRSTBYPASS IPTE/TPRT Simulation */ #define MICVPFR2 0x10 /* Virtual Page Fault reflection Assists */ #define MICLRA2 0x08 /* VRSTBYPASS LRA Simulation */ #define MICSTSM2 0x02 /* VRSTBYPASS SSM/STxSM Sim */ #define MICLCTL2 0x01 /* VRSTBYPASS LCTL Sim */ /* Bits define in MICEVMA3 */ #define MICSKYMD 0x20 /* Unknown */ #define MICISKE 0x10 /* PTLB Sim */ #define MICRRBE 0x08 /* IPTE/TPRT Sim */ #define MICSSKE 0x04 /* V Page Fault Sim */ /* Bits defined in MICEVMA4 */ #define MICSVC4 0x40 /* SVC/LPSW/LCTL Assists Extentions */ #define MICSPT4 0x20 /* SPT Assist Extension */ #define MICIUCV 0x10 /* IUCV ASSIST */ } ECPSVM_MICBLOK; /* PSA Usefull Values */ #define IOOPSW 0x038 #define QUANTUMR 0x04C /* Usefull little unused space for MVCing NEW ITIMER */ #define INTTIMER 0x050 #define QUANTUM 0x054 /* Usefull little unused space for MVCing OLD ITIMER */ /* PSA Displacements used by ECPS:VM */ /* PSA Entries used by DISPx Instructions */ #define CPSTATUS 0x348 /* PSA + 348 : CPSTATUS */ #define CPWAIT 0x80 /* CP IN WAIT STATE */ #define CPRUN 0x40 /* RUNUSER is use running */ #define CPEX 0x20 /* CPEXBLOK RUNNING */ #define CPSUPER 0x08 /* Supervisor State */ /* PSA + 349 : SYSTEM EXTENDING FREE STORAGE BYTE */ /* Note : PSA+0X349 = 0xFF if storage extending */ #define XTENDLOCK 0x349 #define XTENDLOCKSET 0xff /* PSA + 34A : CPSTAT2 */ #define CPSTAT2 0x34A #define CPMICAVL 0x80 #define CPMICON 0x40 #define CPSHRLK 0x20 #define CPASTAVL 0x08 #define CPASTON 0x04 /* RUNPSW */ /* PSW used during dispatch */ #define RUNPSW 0x330 /* RUNUSER PSA+338 */ #define RUNUSER 0x338 /* RUNCR0, RUNCR1 */ /* CR0 & CR1 used during dispatch */ #define RUNCR0 0x340 #define RUNCR1 0x344 /* ASYSVM : PSA+37C */ #define ASYSVM 0x37C /* PSA + X'3D4' - ASSISTS STUFF */ #define CPCREG0 0x3D4 #define CPCREG6 0x3D8 #define CPCREG8 0x3DC #define TIMEDISP 0x3E0 #define ASVCLIST 0x3E4 #define AVMALIST 0x3E8 #define LASTUSER 0x3EC /* PSA + 328 : PROBTIME */ /* Total time spent in problem state (2's complement) */ #define PROBTIME 0x328 /* PSA + 69D : APSTAT2 - Machine check recov & PTLB Required */ #define APSTAT2 0x69D #define CPMCHLK 0x10 #define CPPTLBR 0x02 /* PSA + 6A8 : PROBSTRT */ /* TOD Clock at Proble state entry */ #define PROBSTRT 0x6A8 /* PSA + 6D0 : STACKVM - GPR11 Backup for dispatcher */ #define STACKVM 0x6D0 /* CP ASSIST SVC (Not VM Assist SVC) LIST */ /* ASSISTS FOR CP LINK/RETURN SVCs */ /* DMKSVCNS */ /* Address found @ PSA+3E4 */ typedef struct _ECPSVM_SVCLIST { DW NEXTSAVE; /* Pointer to next Save Area + 8 */ DW SLCADDR; /* V=R Start */ DW DMKSVCHI; /* DMKFREHI */ DW DMKSVCLO; /* DMKFRELO + SAVEAREA LENGTH */ } ECPSVM_SVCLIST; /* VM ASSIST LISTS */ /* ENTRYPOINT TO VARIOUS PRIVOP SIM FASTPATH */ /* (DMKPRVMA) */ /* Address found @ PSA+3E8 */ typedef struct _ECPSVM_VMALIST { DW VSIVS; /* EP To DMKVSIVS (Fastpath SIO/SIOF) */ DW VSIEX; /* Base addr for VSIVS */ DW DSPCH; /* Scheduler - Fast path for LPSW/SSM/STNSM/STOSM */ DW TMRCC; /* SCKC EP */ DW TMR; /* Timer ops base */ DW TMRSP; /* SPT EP */ DW VATAT; /* ARCHITECT */ DW DSPB; /* Slow Path Dispatcher - PSW Revalidate required */ DW PRVVS; /* VSIVS COUNT */ DW PRVVL; /* LPSW Count */ DW PRVVM; /* SSM/STxSM COUNT */ DW PRVVC; /* SCKC COUNT */ DW RESERVED; DW PRVVP; /* SPT COUNT */ } ECPSVM_VMALIST; /* VMBLOK Displacements */ #define VMQFPNT 0x000 #define VMQBPNT 0x004 #define VMPNT 0x008 #define VMECEXT 0x00C #define VMVCR0 VMECEXT #define VMSEG 0x010 #define VMSIZE 0x014 #define VMCHSTRT 0x018 #define VMCUSTRT 0x01C #define VMDVSTRT 0x020 #define VMTERM 0x024 #define VMVTERM 0x028 #define VMTRMID 0x02A #define VMTLEND 0x02C #define VMTLDEL 0x02D #define VMTCDEL 0x02E #define VMTESCP 0x02F #define VMCHCNT 0x030 #define VMCUCNT 0x032 #define VMDVCNT 0x034 #define VMIOACTV 0x036 #define VMCHTBL 0x038 #define VMRSTAT 0x058 /* Flags defined in VMRSTAT */ #define VMCFWAIT 0x80 #define VMPGWAIT 0x40 #define VMIOWAIT 0x20 #define VMPSWAIT 0x10 #define VMEXWAIT 0x08 #define VMLOGON 0x04 #define VMLOGOFF 0x02 #define VMIDLE 0x01 #define VMCPWAIT (VMCFWAIT|VMPGWAIT|VMIOWAIT|VMEXWAIT|VMLOGOFF|VMLOGON) #define VMNORUN (VMCPWAIT|VMPSWAIT) #define VMLONGWT (VMCFWAIT|VMLOGON|VMLOGOFF|VMIDLE) #define VMDSTAT 0x059 /* Flags defined in VMDSTAT */ #define VMDSP 0x80 #define VMTSEND 0x40 #define VMQSEND 0x20 #define VMTIO 0x10 #define VMRUN 0x08 #define VMINQ 0x04 #define VMELIG 0x02 #define VMDSPCH 0x01 #define VMOSTAT 0x05A /* Flags defined in VMOSTAT */ #define VMSYSOP 0x80 #define VMSHR 0x40 #define VMSLEEP 0x20 #define VMDISC 0x10 #define VMCFRUN 0x08 #define VMVIRCF 0x04 #define VMCF 0x02 #define VMKILL 0x01 #define VMQSTAT 0x05B /* Flags defined in VMQSTAT */ #define VMPRIDSP 0x80 #define VMAUTOLOG 0x40 #define VMWSERNG 0x20 #define VMDLDRP 0x10 #define VMWSCHG 0x08 #define VMINHMIG 0x04 #define VMCFREAD 0x02 #define VMPA2APL 0x01 #define VMPSTAT 0x05C /* Flags defined in VMPSTAT */ #define VMISAM 0x80 #define VMV370R 0x40 #define VMRPAGE 0x20 #define VMREAL 0x10 #define VMNOTRAN 0x08 #define VMNSHR 0x04 #define VMACCOUN 0x02 #define VMPAGEX 0x01 #define VMESTAT 0x05D /* Flags defined in VMESTAT */ #define VMSHADT 0x80 #define VMPERCM 0x40 #define VMBADCR0 0x20 #define VMMICSVC 0x10 #define VMEXTCM 0x08 #define VMNEWCR0 0x04 #define VMINVSEG 0x02 #define VMINVPAG 0x01 #define VMECZAP ~VMMICSVC #define VMTRCTL 0x05E /* Bits defined in VMTRCTL */ #define VMTRPER 0x80 #define VMTRSVC 0x40 #define VMTRPRG 0x20 #define VMTRIO 0x10 #define VMTREX 0x08 #define VMTRPRV 0x04 #define VMTRSIO 0x02 #define VMTRBRIN 0x01 #define VMTRINT (VMTRSVC|VMTRPRG|VMTRIO|VMTREX) #define VMMLEVEL 0x05F #define VMQLEVEL 0x060 /* Bits defined in VMQLEVEL */ #define VMQ1 0x80 #define VMCOMP 0x40 #define VMHIPRI 0x20 #define VMLOPRI 0x10 #define VMAEX 0x08 #define VMAEXP 0x04 #define VMAQ3 0x02 #define VMDROP1 0x02 #define VMFS 0x01 #define VM_RESERVED1 0x061 #define VMTLEVEL 0x062 /* Flags defined for VMTLEVEL */ #define VMTON 0x80 #define VMRON 0x40 #define VMCPUTMR 0x20 #define VMSTMPI 0x08 #define VMSTMPT 0x04 #define VMTMRINT 0x01 #define VMPEND 0x063 /* Flags defined in VMPEND */ #define VMDEFSTK 0x80 #define VMPERPND 0x40 #define VMPRGPND 0x20 #define VMSVCPND 0x10 #define VMPGPND 0x08 #define VMIOPND 0x02 #define VMEXTPND 0x01 #define VMLOCKER 0x064 #define VMFSTAT 0x068 #define VMMLVL2 0x069 #define VMIOINT 0x06A #define VMTIMER 0x06C #define VMVTIME 0x070 #define VMTMOUTQ 0x078 #define VMTTIME 0x080 #define VMTMINQ 0x088 #define VMTSOUTQ VMTMINQ #define VMTODINQ 0x090 #define VMINST 0x098 #define VMUPRIOR 0x09E #define VMPSWCT 0x09F #define VMTREXT 0x0A0 #define VMADSTOP 0x0A4 #define VMPSW 0x0A8 #define VMGPRS 0x0B0 #define VMFPRS 0x0F0 #define VMUSER 0x110 #define VMACCNT 0x118 #define VMDIST 0x120 #define VMMICRO 0x17C #define VMMCR6 VMMICRO #define VMMADDR VMMICRO+1 #define VMPXINT 0x184 #define VMNOECPS 0x1A7 #define VMSTKCNT 0x1CC /* ECBLOK Specifics */ #define EXTSHCR0 0x40 #define EXTSHCR1 0x44 typedef struct _ECPSVM_STAT { char *name; U32 call; U32 hit; u_int support:1; u_int enabled:1; u_int debug:1; u_int total:1; } ECPSVM_STAT; /* THE FOLLOWING ARE C99 INITIALISATION OF THE ECPSVM INSTRUCTION STATE STRUCTURES */ /* SINCE MSVC SEEMS TO NOT LIKE THOSE, THEY ARE REPLACED FOR THE TIME BEING */ #if 0 #define ECPSVM_STAT_DCL(_name) ECPSVM_STAT _name #define ECPSVM_STAT_DEF(_name) ._name = { .name = ""#_name"" ,.call=0,.hit=0,.support=1,.total=0,.enabled=1,.debug=0} #define ECPSVM_STAT_DEFU(_name) ._name = { .name = ""#_name"" ,.call=0,.hit=0,.support=0,.total=0,.enabled=1,.debug=0} #define ECPSVM_STAT_DEFM(_name) ._name = { .name = ""#_name"" ,.call=0,.hit=0,.support=1,.total=1,.enabled=1,.debug=0} #endif /* BELOW ARE NON C99 STRUCTURE INITIALIZERS KEEP THE ABOVE IN SYNC PLEASE */ #define ECPSVM_STAT_DCL(_name) ECPSVM_STAT _name #define ECPSVM_STAT_DEF(_name) { ""#_name"" ,0,0,1,1,0,0} #define ECPSVM_STAT_DEFU(_name) {""#_name"" ,0,0,0,1,0,0} #define ECPSVM_STAT_DEFM(_name) {""#_name"" ,0,0,1,1,0,1} typedef struct _ECPSVM_CMDENT { char *name; int abbrev; void (*fun)(int argc,char **av); char *expl; char *help; } ECPSVM_CMDENT; #endif hercules-3.07/esa390.h000644 000765 000765 00000365470 11337307610 016140 0ustar00jmaynardjmaynard000000 000000 /* ESA390.H (c) Copyright Roger Bowler, 1994-2010 */ /* ESA/390 Data Areas */ /* Interpretive Execution - (c) Copyright Jan Jaeger, 1999-2009 */ /* z/Architecture support - (c) Copyright Jan Jaeger, 1999-2009 */ // $Id: esa390.h 5631 2010-02-14 22:26:40Z rbowler $ #ifndef _ESA390_H #define _ESA390_H /* Platform-independent storage operand definitions */ #include "htypes.h" // (need Hercules fixed-size data types) #if defined(WORDS_BIGENDIAN) typedef union { U16 H; struct { BYTE H; BYTE L; } B; } HW; typedef union { U32 F; struct { HW H; HW L; } H; struct { BYTE B; U32 A:24; } A; } FW; typedef union { U64 D; struct { FW H; FW L; } F; } DW; typedef union { struct { DW H; DW L; } D; struct { FW HH; FW HL; FW LH; FW LL; } F; } QW; #else // !defined(WORDS_BIGENDIAN) typedef union { U16 H; struct { BYTE L; BYTE H; } B; } HW; typedef union { U32 F; struct { HW L; HW H; } H; struct { U32 A:24, B:8; } A; } FW; typedef union { U64 D; struct { FW L; FW H; } F; } DW; typedef union { struct { DW L; DW H; } D; struct { FW LL; FW LH; FW HL; FW HH; } F; } QW; #endif // defined(WORDS_BIGENDIAN) typedef union { HWORD H; struct { BYTE H; BYTE L; } B; } HWORD_U; typedef union { FWORD F; struct { HWORD_U H; HWORD_U L; } H; } FWORD_U; typedef union { DBLWRD D; struct { FWORD_U H; FWORD_U L; } F; } DWORD_U; /* Internal-format PSW structure definition */ typedef struct _PSW { BYTE sysmask; /* System mask (0 - 7) */ BYTE pkey; /* PSW Key (8 - 11) */ BYTE states; /* EC,M,W,P bits (12 - 15) */ BYTE asc; /* Address space control */ /* (16 - 17) */ BYTE cc; /* Condition code (18 - 19) */ BYTE progmask; /* Program mask (20 - 23) */ BYTE zerobyte; /* Zeroes (24 - 31) */ /* or (esame) (24 - 30) */ u_int /* Addressing mode (31 - 32) */ amode64:1, /* 64-bit addressing (31) */ amode:1, /* 31-bit addressing (32) */ zeroilc:1; /* 1=Zero ILC */ U32 zeroword; /* esame only (33 - 63) */ DW ia; /* Instruction addrress */ /* (33 - 63) */ /* or (esame) (64 -127) */ DW amask; /* Address wraparound mask */ U16 intcode; /* Interruption code */ BYTE ilc; /* Instruction length count */ BYTE unused; } PSW; #define IA_G ia.D #define IA_H ia.F.H.F #define IA_L ia.F.L.F #define IA_LA24 ia.F.L.A.A #define AMASK_G amask.D #define AMASK_L amask.F.L.F #define AMASK_H amask.F.H.F #define AMASK24 0x00FFFFFF #define AMASK31 0x7FFFFFFF #define AMASK64 0xFFFFFFFFFFFFFFFFULL /* System mask (0 - 7) */ #define PSW_PERMODE 0x40 /* Program event recording */ #define PSW_DATMODE 0x04 /* Dynamic addr translation */ #define PSW_IOMASK 0x02 /* I/O interrupt mask */ #define PSW_EXTMASK 0x01 /* External interrupt mask */ /* PSW key mask (8 - 11) */ #define PSW_KEYMASK 0xF0 /* PSW key mask */ /* (12 - 15) */ #define PSW_EC_BIT 3 /* 0x08 ECMODE */ #define PSW_MACH_BIT 2 /* 0x04 Machine check mask */ #define PSW_WAIT_BIT 1 /* 0x02 Wait state */ #define PSW_PROB_BIT 0 /* 0x01 Problem state */ #define PSW_NOTESAME_BIT PSW_EC_BIT /* Address space control (16 - 17) */ #define PSW_ASCMASK 0xC0 /* Address space control mask*/ #define PSW_SPACE_BIT 7 /* 0x80 Space mode bit */ #define PSW_AR_BIT 6 /* 0x40 Access register mode bit */ #define PSW_PRIMARY_SPACE_MODE 0x00 /* Primary-space mode */ #define PSW_SECONDARY_SPACE_MODE 0x80 /* Secondary-space mode */ #define PSW_ACCESS_REGISTER_MODE 0x40 /* Access-register mode */ #define PSW_HOME_SPACE_MODE 0xC0 /* Home-space mode */ /* Condition code (18 - 19) */ #define PSW_CCMASK 0x30 /* Condition code mask */ /* Program mask (20 - 23) */ #define PSW_PROGMASK 0x0F /* Program-mask bits */ #define PSW_FOBIT 3 /* 0x08 Fixed-point overflow bit */ #define PSW_DOBIT 2 /* 0x04 Decimal overflow bit */ #define PSW_EUBIT 1 /* 0x02 Exponent underflow bit */ #define PSW_SGBIT 0 /* 0x01 Significance bit */ /* Address mode (31 - 32) */ #define PSW_AMODE64_BIT 0 /* Extended addressing (31) */ #define PSW_AMODE31_BIT 7 /* Basic addressing (32) */ /* Macros for testing states (EC, M, W, P bits) */ #define ECMODE(p) (((p)->states & BIT(PSW_EC_BIT)) != 0) #define NOTESAME(p) (((p)->states & BIT(PSW_NOTESAME_BIT)) != 0) #define MACHMASK(p) (((p)->states & BIT(PSW_MACH_BIT)) != 0) #define WAITSTATE(p) (((p)->states & BIT(PSW_WAIT_BIT)) != 0) #define PROBSTATE(p) (((p)->states & BIT(PSW_PROB_BIT)) != 0) /* Macros for testing program mask */ #define FOMASK(p) ( (p)->progmask & BIT(PSW_FOBIT) ) #define DOMASK(p) ( (p)->progmask & BIT(PSW_DOBIT) ) #define EUMASK(p) ( (p)->progmask & BIT(PSW_EUBIT) ) #define SGMASK(p) ( (p)->progmask & BIT(PSW_SGBIT) ) /* Structure definition for translation-lookaside buffer entry */ #define TLBN 1024 /* Number TLB entries */ #define TLB_MASK 0x3FF /* Mask for 1024 entries */ #define TLB_REAL_ASD_L 0xFFFFFFFF /* ASD values for real mode */ #define TLB_REAL_ASD_G 0xFFFFFFFFFFFFFFFFULL #define TLB_HOST_ASD 0x800 /* Host entry for XC guest */ typedef struct _TLB { DW asd[TLBN]; /* Address space designator */ #define TLB_ASD_G(_n) asd[(_n)].D #define TLB_ASD_L(_n) asd[(_n)].F.L.F DW vaddr[TLBN]; /* Virtual page address */ #define TLB_VADDR_G(_n) vaddr[(_n)].D #define TLB_VADDR_L(_n) vaddr[(_n)].F.L.F DW pte[TLBN]; /* Copy of page table entry */ #define TLB_PTE_G(_n) pte[(_n)].D #define TLB_PTE_L(_n) pte[(_n)].F.L.F BYTE *main[TLBN]; /* Mainstor address */ BYTE *storkey[TLBN]; /* -> Storage key */ BYTE skey[TLBN]; /* Storage key key-value */ BYTE common[TLBN]; /* 1=Page in common segment */ BYTE protect[TLBN]; /* 1=Page in protected segmnt*/ BYTE acc[TLBN]; /* Access type flags */ } TLB; /* TLB Notes - * Fields set by translate_addr() are asd, vaddr, pte, id, common and * protect. * Fields set by logical_to_main() are main, storkey, skey, read and * write and are used for accelerated address lookup (formerly AEA). */ /* Structure for Dynamic Address Translation */ typedef struct _DAT { RADR raddr; /* Real address */ RADR aaddr; /* Absolute address */ RADR rpfra; /* Real page frame address */ RADR asd; /* Address space designator: */ /* STD or ASCE */ int stid; /* Address space indicator */ BYTE *storkey; /* ->Storage key */ U16 xcode; /* Translation exception code*/ u_int private:1, /* 1=Private address space */ protect:2; /* 1=Page prot, 2=ALE prot */ } DAT; /* Bit definitions for control register 0 */ #define CR0_BMPX 0x80000000 /* Block multiplex ctl S/370*/ #define CR0_SSM_SUPP 0x40000000 /* SSM suppression control */ #define CR0_TOD_SYNC 0x20000000 /* TOD clock sync control */ #define CR0_LOW_PROT 0x10000000 /* Low-address protection */ #define CR0_EXT_AUTH 0x08000000 /* Extraction auth control */ #define CR0_SEC_SPACE 0x04000000 /* Secondary space control */ #define CR0_FETCH_OVRD 0x02000000 /* Fetch protection override */ #define CR0_STORE_OVRD 0x01000000 /* Store protection override */ #define CR0_STORKEY_4K 0x01000000 /* Storkey exception control */ #define CR0_TRAN_FMT 0x00F80000 /* Translation format bits...*/ #define CR0_TRAN_ESA390 0x00B00000 /* ...1M/4K ESA/390 format */ #define CR0_PAGE_SIZE 0x00C00000 /* Page size for S/370... */ #define CR0_PAGE_SZ_2K 0x00400000 /* ...2K pages */ #define CR0_PAGE_SZ_4K 0x00800000 /* ...4K pages */ #define CR0_ZPAG_SZ_1M 0x00800000 /* ...1M pages EDAT*/ #define CR0_SEG_SIZE 0x00380000 /* Segment size for S/370... */ #define CR0_SEG_SZ_64K 0x00000000 /* ...64K segments */ #define CR0_SEG_SZ_1M 0x00100000 /* ...1M segments */ #define CR0_ASN_LX_REUS 0x00080000 /* ASN-and-LX-reuse control */ #define CR0_AFP 0x00040000 /* AFP register control */ #define CR0_VOP 0x00020000 /* Vector control 390*/ #define CR0_ASF 0x00010000 /* AS function control 390*/ #define CR0_XM_MALFALT 0x00008000 /* Malfunction alert mask */ #define CR0_XM_EMERSIG 0x00004000 /* Emergency signal mask */ #define CR0_XM_EXTCALL 0x00002000 /* External call mask */ #define CR0_XM_TODSYNC 0x00001000 /* TOD clock sync mask */ #define CR0_XM_CLKC 0x00000800 /* Clock comparator mask */ #define CR0_XM_PTIMER 0x00000400 /* CPU timer mask */ #define CR0_XM_SERVSIG 0x00000200 /* Service signal mask */ #define CR0_XM_ITIMER 0x00000080 /* Interval timer mask S/370*/ #define CR0_XM_INTKEY 0x00000040 /* Interrupt key mask */ #define CR0_XM_EXTSIG 0x00000020 /* External signal mask S/370*/ #define CR0_XM_ETR 0x00000010 /* External timer mask */ #define CR0_PC_FAST 0x00000008 /* PC fast control 390*/ #define CR0_CRYPTO 0x00000004 /* Crypto control ESAME*/ #define CR0_IUCV 0x00000002 /* IUCV interrupt mask */ #define SERVSIG_PEND 0x00000001 /* Event buffer pending */ #define SERVSIG_ADDR 0xFFFFFFF8 /* Parameter address */ /* Bit definitions for control register 1 */ /* CR1 is the primary segment table descriptor or primary ASCE */ /* Bit definitions for control register 2 */ #define CR2_DUCTO 0x7FFFFFC0 /* DUCT origin */ /* For S/370, CR2 contains channel masks for channels 0-31 */ /* Bit definitions for control register 3 */ #define CR3_SASTEIN 0xFFFFFFFF00000000ULL /* SASN STE instance# */ #define CR3_KEYMASK 0xFFFF0000 /* PSW key mask */ #define CR3_SASN 0x0000FFFF /* Secondary ASN */ /* Bit definitions for control register 4 */ #define CR4_PASTEIN 0xFFFFFFFF00000000ULL /* PASN STE instance# */ #define CR4_AX 0xFFFF0000 /* Authorization index */ #define CR4_PASN 0x0000FFFF /* Primary ASN */ /* Bit definitions for control register 5 */ /* When CR0_ASF=0 (ESA/390): */ #define CR5_SSLINK 0x80000000 /* Subsystem-Linkage control */ #define CR5_LTO 0x7FFFFF80 /* Linkage-Table origin */ #define CR5_LTL 0x0000007F /* Linkage-Table length */ /* When CR0_ASF=1 or ESAME: */ #define CR5_PASTEO 0x7FFFFFC0 /* Primary-ASTE origin */ /* Bit definitions for control register 6 */ /* CR6 is the I/O interruption subclass mask */ /* Bit definitions for control register 7 */ /* CR7 is the secondary segment table descriptor or secondary ASCE */ /* Bit definitions for control register 8 */ #define CR8_EAX 0xFFFF0000 /* Extended auth index */ #define CR8_MCMASK 0x0000FFFF /* Monitor masks */ /* Bit definitions for PER */ #define CR9_SB 0x80000000 /* Successful Branching */ #define CR9_IF 0x40000000 /* Instruction Fetch */ #define CR9_SA 0x20000000 /* Storage Alteration */ #define CR9_GRA 0x10000000 /* General Register Alt. */ #define CR9_STURA 0x08000000 /* Store using real addr */ #define CR9_IFNUL 0x01000000 /* IF nullification @PER3*/ #define CR9_GRMASK 0x0000FFFF /* GR mask bits */ #define CR9_BAC 0x00800000 /* Br addr control PER2 only */ #define CR9_SAC 0x00200000 /* Stor. alter. c. PER2 only */ /* Bit definitions for control register 12 */ #define S_CR12_BRTRACE 0x80000000 /* Branch trace control */ #define Z_CR12_BRTRACE 0x8000000000000000ULL /* Branch trace control*/ #define CR12_MTRACE 0x4000000000000000ULL /* Mode trace control */ #define S_CR12_TRACEEA 0x7FFFFFFC /* Trace entry address */ #define Z_CR12_TRACEEA 0x3FFFFFFFFFFFFFFCULL /* Trace entry address */ #define CR12_ASNTRACE 0x00000002 /* ASN trace control */ #define CR12_EXTRACE 0x00000001 /* Explicit trace control */ /* Bit definitions for control register 13 */ /* CR13 is the home segment table descriptor or home ASCE */ /* Bit definitions for control register 14 */ #define CR14_CHKSTOP 0x80000000 /* Check-stop control S/370*/ #define CR14_SYNCMCEL 0x40000000 /* Synchronous MCEL S/370*/ #define CR14_IOEXTLOG 0x20000000 /* I/O extended logout S/370*/ #define CR14_CHANRPT 0x10000000 /* Channel report mask */ #define CR14_RCVYRPT 0x08000000 /* Recovery report mask */ #define CR14_DGRDRPT 0x04000000 /* Degradation report mask */ #define CR14_XDMGRPT 0x02000000 /* External damage mask */ #define CR14_WARNING 0x01000000 /* Warning mask */ #define CR14_ASYNMCEL 0x00800000 /* Asynchronous MCEL S/370*/ #define CR14_ASYNFIXL 0x00400000 /* Asynch fixed log S/370*/ #define CR14_TODCTLOV 0x00200000 /* TOD clock control override*/ #define CR14_ASN_TRAN 0x00080000 /* ASN translation control */ #define CR14_AFTO 0x0007FFFF /* ASN first table origin */ /* Bit definitions for control register 15 */ #define CR15_LSEA_390 0x7FFFFFF8 /* Linkage stack address 390*/ #define CR15_LSEA_900 0xFFFFFFFFFFFFFFF8ULL /* Linkage stack ESAME*/ #define CR15_MCEL 0x00FFFFF8 /* MCEL address S/370*/ /* Linkage table designation bit definitions */ #define LTD_SSLINK 0x80000000 /* Subsystem-Linkage control */ #define LTD_LTO 0x7FFFFF80 /* Linkage-Table origin */ #define LTD_LTL 0x0000007F /* Linkage-Table length */ /* Linkage first table designation bit definitions (ASN-and-LX-reuse)*/ #define LFTD_SSLINK 0x80000000 /* Subsystem-Linkage control */ #define LFTD_LFTO 0x7FFFFF00 /* Linkage-First-Table origin*/ #define LFTD_LFTL 0x000000FF /* Linkage-First-Table length*/ /* Values for designation type and table type (ESAME mode) */ #define TT_R1TABL 0xC /* Region first table */ #define TT_R2TABL 0x8 /* Region second table */ #define TT_R3TABL 0x4 /* Region third table */ #define TT_SEGTAB 0x0 /* Segment table */ /* Address space control element bit definitions (ESAME mode) */ #define ASCE_TO 0xFFFFFFFFFFFFF000ULL /* Table origin */ #define ASCE_G 0x200 /* Subspace group indicator */ #define ASCE_P 0x100 /* Private space indicator */ #define ASCE_S 0x080 /* Storage alteration event */ #define ASCE_X 0x040 /* Space switch event */ #define ASCE_R 0x020 /* Real space */ #define ASCE_DT 0x00C /* Designation type */ #define ASCE_TL 0x003 /* Table length */ #define ASCE_RESV 0xC10 /* Reserved bits - ignored */ /* Region table entry bit definitions (ESAME mode) */ #define REGTAB_TO 0xFFFFFFFFFFFFF000ULL /* Table origin */ #define REGTAB_P 0x200 /* DAT Protection bit EDAT*/ #define REGTAB_TF 0x0C0 /* Table offset */ #define REGTAB_I 0x020 /* Region invalid */ #define REGTAB_TT 0x00C /* Table type */ #define REGTAB_TL 0x003 /* Table length */ #define REGTAB_RESV 0xD10 /* Reserved bits - ignored */ /* Segment table entry bit definitions (ESAME mode) */ #define ZSEGTAB_PTO 0xFFFFFFFFFFFFF800ULL /* Page table origin */ #define ZSEGTAB_SFAA 0xFFFFFFFFFFF00000ULL /* Seg Fr Abs Addr EDAT*/ #define ZSEGTAB_AV 0x10000 /* ACCF Validity Control EDAT*/ #define ZSEGTAB_ACC 0x0F000 /* Access Control Bits EDAT*/ #define ZSEGTAB_F 0x800 /* Fetch Protection EDAT*/ #define ZSEGTAB_FC 0x400 /* Format control EDAT*/ #define ZSEGTAB_P 0x200 /* Page protection bit */ #define ZSEGTAB_CO 0x100 /* Change-rec override EDAT*/ #define ZSEGTAB_I 0x020 /* Invalid segment */ #define ZSEGTAB_C 0x010 /* Common segment */ #define ZSEGTAB_TT 0x00C /* Table type */ #define ZSEGTAB_RESV 0x0C3 /* Reserved bits - ignored */ /* Page table entry bit definitions (ESAME mode) */ #define ZPGETAB_PFRA 0xFFFFFFFFFFFFF000ULL /* Page frame real addr*/ #define ZPGETAB_I 0x400 /* Invalid page */ #define ZPGETAB_P 0x200 /* Protected page */ #define ZPGETAB_ESVALID 0x100 /* Valid in expanded storage */ #define ZPGETAB_CO 0x100 /* Change-rec override EDAT*/ #define ZPGETAB_ESREF 0x080 /* ES Referenced */ #define ZPGETAB_ESCHA 0x040 /* ES Changed */ #define ZPGETAB_ESLCK 0x020 /* ES Locked */ #define ZPGETAB_RESV 0x800 /* Reserved bits - must be 0 */ /* Segment table designation bit definitions (ESA/390 mode) */ #define STD_SSEVENT 0x80000000 /* Space switch event */ #define STD_STO 0x7FFFF000 /* Segment table origin */ #define STD_RESV 0x00000C00 /* Reserved bits - must be 0 */ #define STD_GROUP 0x00000200 /* Subspace group indicator */ #define STD_PRIVATE 0x00000100 /* Private space indicator */ #define STD_SAEVENT 0x00000080 /* Storage alteration event */ #define STD_STL 0x0000007F /* Segment table length */ /* Segment table entry bit definitions (ESA/390 mode) */ #define SEGTAB_PTO 0x7FFFFFC0 /* Page table origin */ #define SEGTAB_INVALID 0x00000020 /* Invalid segment */ #define SEGTAB_COMMON 0x00000010 /* Common segment */ #define SEGTAB_PTL 0x0000000F /* Page table length */ #define SEGTAB_RESV 0x80000000 /* Reserved bits - must be 0 */ /* Page table entry bit definitions (ESA/390 mode) */ #define PAGETAB_PFRA 0x7FFFF000 /* Page frame real address */ #define PAGETAB_ESNK 0x00000800 /* ES NK bit */ #define PAGETAB_INVALID 0x00000400 /* Invalid page */ #define PAGETAB_PROT 0x00000200 /* Protected page */ #define PAGETAB_ESVALID 0x00000100 /* Valid in expanded storage */ #define PAGETAB_ESREF 0x00000004 /* ES Referenced */ #define PAGETAB_ESCHA 0x00000002 /* ES Changed */ #define PAGETAB_PGLOCK 0x00000001 /* Page lock (LKPG) */ #define PAGETAB_RESV 0x80000900 /* Reserved bits - must be 0 */ /* Segment table designation bit definitions (S/370 mode) */ #define STD_370_STL 0xFF000000 /* 370 segment table length */ #define STD_370_STO 0x00FFFFC0 /* 370 segment table origin */ #define STD_370_SSEVENT 0x00000001 /* 370 space switch event */ /* Segment table entry bit definitions (S/370 mode) */ #define SEGTAB_370_PTL 0xF0000000 /* Page table length */ #define SEGTAB_370_PTO 0x00FFFFF8 /* Page table origin */ #define SEGTAB_370_PROT 0x00000004 /* Protected segment */ #define SEGTAB_370_CMN 0x00000002 /* Common segment */ #define SEGTAB_370_INVL 0x00000001 /* Invalid segment */ #define SEGTAB_370_RSV 0x0F000000 /* Reserved bits - must be 0 */ /* Page table entry bit definitions (S/370 mode) */ #define PAGETAB_PFRA_4K 0xFFF0 /* Page frame real address */ #define PAGETAB_INV_4K 0x0008 /* Invalid page */ #define PAGETAB_EA_4K 0x0006 /* Extended physical address */ #define PAGETAB_PFRA_2K 0xFFF8 /* Page frame real address */ #define PAGETAB_INV_2K 0x0004 /* Invalid page */ #define PAGETAB_RSV_2K 0x0002 /* Reserved bit - must be 0 */ /* Access-list entry token special value definitions */ #define ALET_PRIMARY 0 /* Primary address-space */ #define ALET_SECONDARY 1 /* Secondary address-space */ #define ALET_HOME 2 /* Home address-space */ /* Access-list entry token bit definitions */ #define ALET_RESV 0xFE000000 /* Reserved bits - must be 0 */ #define ALET_PRI_LIST 0x01000000 /* Primary space access-list */ #define ALET_ALESN 0x00FF0000 /* ALE sequence number */ #define ALET_ALEN 0x0000FFFF /* Access-list entry number */ /* Access-list designation bit definitions */ #if FEATURE_ALD_FORMAT == 0 || defined(_900) #define ALD_ALO 0x7FFFFF80 /* Access-list origin (fmt0) */ #define ALD_ALL 0x0000007F /* Access-list length (fmt0) */ #define ALD_ALL_SHIFT 3 /* Length units are 2**3 */ #else #define ALD_ALO 0x7FFFFF00 /* Access-list origin (fmt1) */ #define ALD_ALL 0x000000FF /* Access-list length (fmt1) */ #define ALD_ALL_SHIFT 4 /* Length units are 2**4 */ #endif /* Access-list entry bit definitions */ #define ALE0_INVALID 0x80000000 /* ALEN invalid */ #define ALE0_FETCHONLY 0x02000000 /* Fetch only address space */ #define ALE0_PRIVATE 0x01000000 /* Private address space */ #define ALE0_ALESN 0x00FF0000 /* ALE sequence number */ #define ALE0_ALEAX 0x0000FFFF /* ALE authorization index */ #define ALE2_ASTE 0x7FFFFFC0 /* ASTE address */ #define ALE3_ASTESN 0xFFFFFFFF /* ASTE sequence number */ /* Address-space number (ASN) bit definitions */ #define ASN_AFX 0xFFC0 /* ASN first table index */ #define ASN_ASX 0x003F /* ASN second table index */ /* ASN first table entry bit definitions */ #define AFTE_INVALID 0x80000000 /* ASN invalid */ #define AFTE_ASTO_0 0x7FFFFFF0 /* ASTE origin (CR0_ASF=0) */ #define AFTE_RESV_0 0x0000000F /* Reserved bits (CR0_ASF=0) */ #define AFTE_ASTO_1 0x7FFFFFC0 /* ASTE origin (CR0_ASF=1) */ #define AFTE_RESV_1 0x0000003F /* Reserved bits (CR0_ASF=1) */ /* ASN second table entry bit definitions */ #define ASTE0_INVALID 0x80000000 /* ASX invalid */ #define ASTE0_ATO 0x7FFFFFFC /* Authority-table origin */ #define ASTE0_RESV 0x00000002 /* Must be 0 for ESA/390 */ #define ASTE0_BASE 0x00000001 /* Base space of group */ #define ASTE1_AX 0xFFFF0000 /* Authorization index */ #define ASTE1_ATL 0x0000FFF0 /* Authority-table length */ #define ASTE1_RESV 0x0000000F /* Must be 0 for ESA/390 */ #define ASTE1_CA 0x00000002 /* Controlled ASN */ #define ASTE1_RA 0x00000001 /* Reusable ASN */ /* ASTE word 2 is the segment table designation for ESA/390 */ /* ASTE word 3 is the linkage-table designation for ESA/390 */ /* ASTE words 2 and 3 are the ASCE (RTD, STD, or RSD) for ESAME */ /* ASTE word 4 is the access-list designation */ #define ASTE5_ASTESN 0xFFFFFFFF /* ASTE sequence number */ #define ASTE6_RESV 0xFFFFFFFF /* Must be zero for ESA/390 */ /* ASTE word 6 is the LTD or LFTD for ESAME */ /* ASTE words 7-9 are reserved for control program use */ /* ASTE word 10 is unused */ #define ASTE11_ASTEIN 0xFFFFFFFF /* ASTE instance number */ /* ASTE words 12-15 are unused */ /* Authority table entry bit definitions */ #define ATE_PRIMARY 0x80 /* Primary authority bit */ #define ATE_SECONDARY 0x40 /* Secondary authority bit */ /* Dispatchable unit control table bit definitions */ #define DUCT0_BASTEO 0x7FFFFFC0 /* Base ASTE origin */ #define DUCT1_SA 0x80000000 /* Subspace active */ #define DUCT1_SSASTEO 0x7FFFFFC0 /* Subspace ASTE origin */ /* DUCT word 2 is unused */ #define DUCT3_SSASTESN 0xFFFFFFFF /* Subspace ASTE seq number */ /* DUCT word 4 is the access-list designation */ /* DUCT word 5 is unused for ESA/390 */ /* DUCT word 5 contains PKM/KEY/RA/PROB for ESAME */ /* DUCT word 6 is unused */ /* DUCT word 7 is for control program use */ /* DUCT words 8 and 9 are the return address for ESAME. In 24-bit and 31-bit mode, word 8 contains zero and word 9 contains AM31/IA31 */ /* DUCT word 8 contains AM31/IA31 for ESA/390 */ /* DUCT word 9 contains PKM/KEY/RA/PROB for ESA/390 */ /* DUCT word 10 is unused */ #define DUCT11_TCBA 0x7FFFFFF8 /* Trap control block address*/ #define DUCT11_TE 0x00000001 /* Trap enabled */ /* DUCT word 12 is unused */ /* DUCT word 13 is unused */ /* DUCT word 14 is unused */ /* DUCT word 15 is unused */ /* Bit definitions for DUCT word 5 (ESAME) or word 9 (ESA/390) */ #define DUCT_PKM 0xFFFF0000 /* PSW key mask */ #define DUCT_KEY 0x000000F0 /* PSW key */ #define DUCT_RA 0x00000008 /* Reduced authority state */ #define DUCT_PROB 0x00000001 /* Problem state */ /* Bit definitions for DUCT word 9 (ESAME) or word 8 (ESA/390) */ #define DUCT_AM31 0x80000000 /* 1=31-bit, 0=24-bit address*/ #define DUCT_IA31 0x7FFFFFFF /* 24/31 return address */ #define TCB0_P 0x00040000 /* Bit 13 PSW Control (P) */ #define TCB0_R 0x00020000 /* Bit 14 GR Control (R) */ #define TRAP0_EXECUTE 0x80000000 /* TRAP is target of execute */ #define TRAP0_TRAP4 0x40000000 /* TRAP is TRAP4 */ /* Linkage stack entry descriptor structure definition */ typedef struct _LSED { BYTE uet; /* U-bit and entry type */ BYTE si; /* Section identification */ HWORD rfs; /* Remaining free space */ HWORD nes; /* Next entry size */ HWORD resv; /* Reserved bits - must be 0 */ } LSED; /* Stack type definitions */ #define LSED_UET_U 0x80 /* Unstack suppression bit */ #define LSED_UET_ET 0x7F /* Entry type... */ #define S_LSED_UET_HDR 0x01 /* ...header entry */ #define S_LSED_UET_TLR 0x02 /* ...trailer entry */ #define S_LSED_UET_BAKR 0x04 /* ...branch state entry */ #define S_LSED_UET_PC 0x05 /* ...call state entry */ #define Z_LSED_UET_HDR 0x09 /* ...header entry */ #define Z_LSED_UET_TLR 0x0A /* ...trailer entry */ #define Z_LSED_UET_BAKR 0x0C /* ...branch state entry */ #define Z_LSED_UET_PC 0x0D /* ...call state entry */ /* Program call number bit definitions */ #define PC_LFX1 0xFFF00000 /* Linkage first index (high)*/ #define PC_BIT44 0x00080000 /* 1=LFX1 is significant */ #define PC_LFX2 0x0007E000 /* Linkage first index (low) */ #define PC_LSX 0x00001F00 /* Linkage second index */ #define PC_LX 0x000FFF00 /* Linkage index */ #define PC_EX 0x000000FF /* Entry index */ /* Linkage table entry bit definitions */ #define LTE_INVALID 0x80000000 /* LX invalid */ #define LTE_ETO 0x7FFFFFC0 /* Entry table origin */ #define LTE_ETL 0x0000003F /* Entry table length */ /* Linkage first table entry bit definitions (ASN-and-LX-reuse) */ #define LFTE_INVALID 0x80000000 /* LFX invalid */ #define LFTE_LSTO 0x7FFFFF00 /* Linkage second table orig */ /* Linkage second table entry bit definitions (ASN-and-LX-reuse) */ #define LSTE0_INVALID 0x80000000 /* LSX invalid */ #define LSTE0_ETO 0x7FFFFFC0 /* Entry table origin */ #define LSTE0_ETL 0x0000003F /* Entry table length */ #define LSTE1_LSTESN 0xFFFFFFFF /* LSTE sequence number */ /* Entry table bit entry definitions */ /* ETE word 0 is the left half of the EIA for ESAME if ETE4_G is set */ #define ETE0_AKM 0xFFFF0000 /* Authorization key mask 390*/ #define ETE0_ASN 0x0000FFFF /* Address space number 390*/ #define ETE1_AMODE 0x80000000 /* Addressing mode */ #define ETE1_EIA 0x7FFFFFFE /* Instruction address */ #define ETE1_PROB 0x00000001 /* Problem state bit */ /* ETE word 2 is the entry parameter for ESA/390 */ #define ETE2_AKM 0xFFFF0000 /* Auth.key mask ESAME*/ #define ETE2_ASN 0x0000FFFF /* Address space number ESAME*/ #define ETE3_EKM 0xFFFF0000 /* Entry key mask */ #define ETE4_T 0x80000000 /* 0=Basic PC, 1=Stacking PC */ #define ETE4_G 0x40000000 /* 1=64-bit EIA/EPARM ESAME*/ #define ETE4_K 0x10000000 /* 1=Replace PSW key by EK */ #define ETE4_M 0x08000000 /* 1=Replace PKM by EKM, 0=or*/ #define ETE4_E 0x04000000 /* 1=Replace EAX by EEAX */ #define ETE4_C 0x02000000 /* 0=Primary mode, 1=AR mode */ #define ETE4_S 0x01000000 /* SASN:0=old PASN,1=new PASN*/ #define ETE4_EK 0x00F00000 /* Entry key */ #define ETE4_EEAX 0x0000FFFF /* Entry extended AX */ #define ETE5_ASTE 0x7FFFFFC0 /* ASTE address */ /* ETE words 6 and 7 are unused for ESA/390 */ /* ETE words 6 and 7 are the entry parameter for ESAME */ /* Clock states */ #define CC_CLOCK_SET 0 /* Clock in set state */ #define CC_CLOCK_NOTSET 1 /* Clock in not-set state */ #define CC_CLOCK_ERROR 2 /* Clock in error state */ #define CC_CLOCK_STOP 3 /* Clock in stopped state or not-operational state */ /* SIGP order codes */ #define SIGP_SENSE 0x01 /* Sense */ #define SIGP_EXTCALL 0x02 /* External call */ #define SIGP_EMERGENCY 0x03 /* Emergency signal */ #define SIGP_START 0x04 /* Start */ #define SIGP_STOP 0x05 /* Stop */ #define SIGP_RESTART 0x06 /* Restart */ #define SIGP_IPR 0x07 /* Initial program reset 370*/ #define SIGP_PR 0x08 /* Program reset 370*/ #define SIGP_STOPSTORE 0x09 /* Stop and store status */ #define SIGP_IMPL 0x0A /* Initial uprogram load 370*/ #define SIGP_INITRESET 0x0B /* Initial CPU reset */ #define SIGP_RESET 0x0C /* CPU reset */ #define SIGP_SETPREFIX 0x0D /* Set prefix */ #define SIGP_STORE 0x0E /* Store status at address */ #define SIGP_STOREX 0x11 /* Store ext stat at addr 390*/ #define SIGP_SETARCH 0x12 /* Set architecture mode */ #define SIGP_COND_EMERGENCY 0x13 /* Conditional Emergency */ #define SIGP_SENSE_RUNNING_STATE 0x15 /* Sense Running State */ #define MAX_SIGPORDER 0x15 /* Maximum SIGP order value */ #define LOG_SIGPORDER 0x03 /* Log any SIGP > this value */ /* SIGP status codes */ #define SIGP_STATUS_EQUIPMENT_CHECK 0x80000000 #define SIGP_STATUS_NOT_RUNNING 0x00000400 #define SIGP_STATUS_INCORRECT_STATE 0x00000200 #define SIGP_STATUS_INVALID_PARAMETER 0x00000100 #define SIGP_STATUS_EXTERNAL_CALL_PENDING 0x00000080 #define SIGP_STATUS_STOPPED 0x00000040 #define SIGP_STATUS_OPERATOR_INTERVENING 0x00000020 #define SIGP_STATUS_CHECK_STOP 0x00000010 #define SIGP_STATUS_INOPERATIVE 0x00000004 #define SIGP_STATUS_INVALID_ORDER 0x00000002 #define SIGP_STATUS_RECEIVER_CHECK 0x00000001 /* Storage key bit definitions */ #define STORKEY_KEY 0xF0 /* Storage key */ #define STORKEY_FETCH 0x08 /* Fetch protect bit */ #define STORKEY_REF 0x04 /* Reference bit */ #define STORKEY_CHANGE 0x02 /* Change bit */ #define STORKEY_BADFRM 0x01 /* Unusable frame */ /* Prefixed storage area structure definition */ typedef struct _PSA_3XX { /* Prefixed storage area */ /*000*/ DBLWRD iplpsw; /* IPL PSW, Restart new PSW */ /*008*/ DBLWRD iplccw1; /* IPL CCW1, Restart old PSW */ /*010*/ DBLWRD iplccw2; /* IPL CCW2 */ /*018*/ DBLWRD extold; /* External old PSW */ /*020*/ DBLWRD svcold; /* SVC old PSW */ /*028*/ DBLWRD pgmold; /* Program check old PSW */ /*030*/ DBLWRD mckold; /* Machine check old PSW */ /*038*/ DBLWRD iopold; /* I/O old PSW */ /*040*/ DBLWRD csw; /* Channel status word (S370)*/ /*048*/ FWORD caw; /* Channel address word(S370)*/ /*04C*/ FWORD resv04C; /* Reserved */ /*050*/ FWORD inttimer; /* Interval timer */ /*054*/ FWORD resv054; /* Reserved */ /*058*/ DBLWRD extnew; /* External new PSW */ /*060*/ DBLWRD svcnew; /* SVC new PSW */ /*068*/ DBLWRD pgmnew; /* Program check new PSW */ /*070*/ DBLWRD mcknew; /* Machine check new PSW */ /*078*/ DBLWRD iopnew; /* I/O new PSW */ /*080*/ FWORD extparm; /* External interrupt param */ /*084*/ HWORD extcpad; /* External interrupt CPU# */ /*086*/ HWORD extint; /* External interrupt code */ /*088*/ FWORD svcint; /* SVC interrupt code */ /*08C*/ FWORD pgmint; /* Program interrupt code */ /*090*/ FWORD tea; /* Translation exception addr*/ /*094*/ HWORD monclass; /* Monitor class */ /*096*/ HWORD perint; /* PER interrupt code */ /*098*/ FWORD peradr; /* PER address */ /*09C*/ FWORD moncode; /* Monitor code */ /*0A0*/ BYTE excarid; /* Exception access id */ /*0A1*/ BYTE perarid; /* PER access id */ /*0A2*/ BYTE opndrid; /* Operand access id */ /*0A3*/ BYTE arch; /* Architecture mode ID */ /*0A4*/ FWORD resv0A4; /* Reserved */ /*0A8*/ FWORD chanid; /* Channel id (S370) */ /*0AC*/ FWORD ioelptr; /* I/O extended logout (S370)*/ /*0B0*/ FWORD lcl; /* Limited chan logout (S370)*/ /*0B4*/ FWORD resv0B0; /* Reserved */ /*0B8*/ FWORD ioid; /* I/O interrupt device id */ /*0BC*/ FWORD ioparm; /* I/O interrupt parameter */ /*0C0*/ FWORD iointid; /* I/O interrupt ID */ /*0C4*/ FWORD resv0C4; /* Reserved */ /*0C8*/ FWORD stfl; /* Facilities list (STFL) */ /*0CC*/ FWORD resv0CC; /* Reserved */ /*0D0*/ DBLWRD resv0D0; /* Reserved */ /*0D8*/ DBLWRD storeptmr; /* CPU timer save area */ /*0E0*/ DBLWRD storeclkc; /* Clock comparator save area*/ /*0E8*/ DBLWRD mckint; /* Machine check int code */ /*0F0*/ FWORD resv0F0; /* Reserved */ /*0F4*/ FWORD xdmgcode; /* External damage code */ /*0F8*/ FWORD mcstorad; /* Failing storage address */ /*0FC*/ FWORD resv0FC; /* Reserved */ /*100*/ DBLWRD storepsw; /* Store status PSW save area*/ /*108*/ FWORD storepfx; /* Prefix register save area */ /*10C*/ FWORD resv10C; /* Reserved */ /*110*/ DBLWRD resv110; /* Reserved */ /*118*/ DBLWRD resv118; /* Reserved */ /*120*/ FWORD storear[16]; /* Access register save area */ /*160*/ FWORD storefpr[8]; /* FP register save area */ /*180*/ FWORD storegpr[16]; /* General register save area*/ /*1C0*/ FWORD storecr[16]; /* Control register save area*/ } PSA_3XX; /* ESAME Prefixed storage area structure definition */ typedef struct _PSA_900 { /* Prefixed storage area */ /*0000*/ DBLWRD iplpsw; /* IPL PSW */ /*0008*/ DBLWRD iplccw1; /* IPL CCW1 */ /*0010*/ DBLWRD iplccw2; /* IPL CCW2 */ /*0018*/ BYTE resv0018[104]; /* Reserved */ /*0080*/ FWORD extparm; /* External interrupt param */ /*0084*/ HWORD extcpad; /* External interrupt CPU# */ /*0086*/ HWORD extint; /* External interrupt code */ /*0088*/ FWORD svcint; /* SVC interrupt code */ /*008C*/ FWORD pgmint; /* Program interrupt code */ /*0090*/ FWORD dataexc; /* Data exception code */ /*0094*/ HWORD monclass; /* Monitor class */ /*0096*/ HWORD perint; /* PER interrupt code */ /*0098*/ DBLWRD peradr; /* PER address */ /*00A0*/ BYTE excarid; /* Exception access id */ /*00A1*/ BYTE perarid; /* PER access id */ /*00A2*/ BYTE opndrid; /* Operand access id */ /*00A3*/ BYTE arch; /* Architecture mode ID */ /*00A4*/ FWORD mpladdr; /* MPL addr */ /*00A8*/ DWORD_U tea; /* Translation exception addr*/ #define TEA_G tea.D #define TEA_L tea.F.L.F #define TEA_H tea.F.H.F /*00B0*/ DBLWRD moncode; /* Monitor code */ /*00B8*/ FWORD ioid; /* I/O interrupt subsys id */ /*00BC*/ FWORD ioparm; /* I/O interrupt parameter */ /*00C0*/ FWORD iointid; /* I/O interrupt ID */ /*00C4*/ FWORD resv00C0; /* Reserved */ /*00C8*/ FWORD stfl; /* Facilities list (STFL) */ /*00CC*/ FWORD resv00CC; /* Reserved */ /*00D0*/ DBLWRD resv00D0; /* Reserved */ /*00D8*/ DBLWRD resv00D8; /* Reserved */ /*00E0*/ DBLWRD resv00E0; /* Reserved */ /*00E8*/ DBLWRD mckint; /* Machine check int code */ /*00F0*/ FWORD mckext; /* Machine check int code ext*/ /*00F4*/ FWORD xdmgcode; /* External damage code */ /*00F8*/ DBLWRD mcstorad; /* Failing storage address */ /*0100*/ DBLWRD resv0100; /* Reserved */ /*0108*/ DBLWRD resv0108; /* Reserved */ /*0110*/ DBLWRD bea; /* Breaking event address @Z9*/ /*0118*/ DBLWRD resv0118; /* Reserved */ /*0120*/ QWORD rstold; /* Restart old PSW */ /*0130*/ QWORD extold; /* External old PSW */ /*0140*/ QWORD svcold; /* SVC old PSW */ /*0150*/ QWORD pgmold; /* Program check old PSW */ /*0160*/ QWORD mckold; /* Machine check old PSW */ /*0170*/ QWORD iopold; /* I/O old PSW */ /*0180*/ BYTE resv0180[32]; /* Reserved */ /*01A0*/ QWORD rstnew; /* Restart new PSW */ /*01B0*/ QWORD extnew; /* External new PSW */ /*01C0*/ QWORD svcnew; /* SVC new PSW */ /*01D0*/ QWORD pgmnew; /* Program check new PSW */ /*01E0*/ QWORD mcknew; /* Machine check new PSW */ /*01F0*/ QWORD iopnew; /* I/O new PSW */ /*0200*/ BYTE resv0200[4096]; /* Reserved */ /*1200*/ FWORD storefpr[32]; /* FP register save area */ /*1280*/ DBLWRD storegpr[16]; /* General register save area*/ /*1300*/ QWORD storepsw; /* Store status PSW save area*/ /*1310*/ DBLWRD resv1310; /* Reserved */ /*1318*/ FWORD storepfx; /* Prefix register save area */ /*131C*/ FWORD storefpc; /* FP control save area */ /*1320*/ FWORD resv1320; /* Reserved */ /*1324*/ FWORD storetpr; /* TOD prog reg save area */ /*1328*/ DBLWRD storeptmr; /* CPU timer save area */ /*1330*/ DBLWRD storeclkc; /* Clock comparator save area*/ /*1338*/ DBLWRD resv1338; /* Reserved */ /*1340*/ FWORD storear[16]; /* Access register save area */ /*1380*/ DBLWRD storecr[16]; /* Control register save area*/ } PSA_900; /* Bit settings for translation exception address */ #define TEA_SECADDR 0x80000000 /* Secondary addr (370,390) */ #define TEA_PROT_A 0x008 /* Access-list prot (ESAME) */ #define TEA_PROT_AP 0x004 /* Access-list/page protected*/ #define TEA_MVPG 0x004 /* MVPG exception (ESAME) */ #define TEA_ST 0x003 /* Address space indication..*/ #define TEA_ST_PRIMARY 0x000 /* ..primary STO/ASCE used */ #define TEA_ST_ARMODE 0x001 /* ..access register mode */ #define TEA_ST_SECNDRY 0x002 /* ..secondary STO/ASCE used */ #define TEA_ST_HOME 0x003 /* ..home STO/ASCE used */ #define TEA_SSEVENT 0x80000000 /* Space switch event bit */ #define TEA_ASN 0x0000FFFF /* Address space number */ #define TEA_PCN 0x000FFFFF /* Program call number */ /* Bit settings for machine check interruption code */ #define MCIC_SD 0x8000000000000000ULL /* System damage */ #define MCIC_P 0x4000000000000000ULL /* Instruction proc damage */ #define MCIC_SR 0x2000000000000000ULL /* System recovery */ #define MCIC_CD 0x0800000000000000ULL /* Timing facility damage */ #define MCIC_ED 0x0400000000000000ULL /* External damage */ #define MCIC_VF 0x0200000000000000ULL /* Vector facility failure */ #define MCIC_DG 0x0100000000000000ULL /* Degradation */ #define MCIC_W 0x0080000000000000ULL /* Warning */ #define MCIC_CP 0x0040000000000000ULL /* Channel report pending */ #define MCIC_SP 0x0020000000000000ULL /* Service processor damage */ #define MCIC_CK 0x0010000000000000ULL /* Channel subsystem damage */ #define MCIC_VS 0x0004000000000000ULL /* Vector facility source */ #define MCIC_B 0x0002000000000000ULL /* Backed up */ #define MCIC_SE 0x0000800000000000ULL /* Storage error uncorrected */ #define MCIC_SC 0x0000400000000000ULL /* Storage error corrected */ #define MCIC_KE 0x0000200000000000ULL /* Storkey error uncorrected */ #define MCIC_DS 0x0000100000000000ULL /* Storage degradation */ #define MCIC_WP 0x0000080000000000ULL /* PSW-MWP validity */ #define MCIC_MS 0x0000040000000000ULL /* PSW mask and key validity */ #define MCIC_PM 0x0000020000000000ULL /* PSW pm and cc validity */ #define MCIC_IA 0x0000010000000000ULL /* PSW ia validity */ #define MCIC_FA 0x0000008000000000ULL /* Failing stor addr validity*/ #define MCIC_EC 0x0000002000000000ULL /* External damage code val. */ #define MCIC_FP 0x0000001000000000ULL /* Floating point reg val. */ #define MCIC_GR 0x0000000800000000ULL /* General register validity */ #define MCIC_CR 0x0000000400000000ULL /* Control register validity */ #define MCIC_ST 0x0000000100000000ULL /* Storage logical validity */ #define MCIC_IE 0x0000000080000000ULL /* Indirect storage error */ #define MCIC_AR 0x0000000040000000ULL /* Access register validity */ #define MCIC_DA 0x0000000020000000ULL /* Delayed access exeption */ #define MCIC_PR 0x0000000000200000ULL /* TOD prog. reg. validity */ #define MCIC_XF 0x0000000000100000ULL /* Extended float reg val. */ #define MCIC_AP 0x0000000000080000ULL /* Ancillary report */ #define MCIC_CT 0x0000000000020000ULL /* CPU timer validity */ #define MCIC_CC 0x0000000000010000ULL /* Clock comparator validity */ /* Channel Report Word definitions */ #define CRW_SOL 0x40000000 /* Solicited CRW */ #define CRW_OVER 0x20000000 /* Overflow, CRW's lost */ #define CRW_CHAIN 0x10000000 /* More CRW's describe event */ #define CRW_RSC 0x0F000000 /* Reporting resource mask */ #define CRW_MONIT 0x02000000 /* Channel monitor is source */ #define CRW_SUBCH 0x03000000 /* Subchannel is source */ #define CRW_CHPID 0x04000000 /* Channel path is source */ #define CRW_CAF 0x09000000 /* Configuration alert */ #define CRW_CSS 0x0B000000 /* Channel subsys is source */ #define CRW_AR 0x00800000 /* Ancillary report indicator*/ #define CRW_ERC 0x003F0000 /* Error recovery code */ #define CRW_AVAIL 0x00010000 /* Available */ #define CRW_INIT 0x00020000 /* Initialized no parm. chg. */ #define CRW_TEMP 0x00030000 /* Temporary error */ #define CRW_ALERT 0x00040000 /* Installed, subch changed */ #define CRW_TERM 0x00050000 /* Terminal */ #define CRW_PERM 0x00060000 /* Permanent error / not init*/ #define CRW_PERMI 0x00070000 /* Permanent, initialized */ #define CRW_IPM 0x00080000 /* PIM / PAM / CHPIDs changed*/ #define CRW_RSID 0x0000FFFF /* Resource identifier */ /* Bit settings for channel id */ #define CHANNEL_TYPE 0xF0000000 /* Bits 0-3=Channel type... */ #define CHANNEL_SEL 0x00000000 /* ...selector channel */ #define CHANNEL_MPX 0x10000000 /* ...byte multiplexor */ #define CHANNEL_BMX 0x20000000 /* ...block multiplexor */ #define CHANNEL_MODEL 0x0FFF0000 /* Bits 4-15=Channel model */ #define CHANNEL_MAXIOEL 0x0000FFFF /* Bits 16-31=Max.IOEL length*/ /* Program interruption codes */ #define PGM_OPERATION_EXCEPTION 0x0001 #define PGM_PRIVILEGED_OPERATION_EXCEPTION 0x0002 #define PGM_EXECUTE_EXCEPTION 0x0003 #define PGM_PROTECTION_EXCEPTION 0x0004 #define PGM_ADDRESSING_EXCEPTION 0x0005 #define PGM_SPECIFICATION_EXCEPTION 0x0006 #define PGM_DATA_EXCEPTION 0x0007 #define PGM_FIXED_POINT_OVERFLOW_EXCEPTION 0x0008 #define PGM_FIXED_POINT_DIVIDE_EXCEPTION 0x0009 #define PGM_DECIMAL_OVERFLOW_EXCEPTION 0x000A #define PGM_DECIMAL_DIVIDE_EXCEPTION 0x000B #define PGM_EXPONENT_OVERFLOW_EXCEPTION 0x000C #define PGM_EXPONENT_UNDERFLOW_EXCEPTION 0x000D #define PGM_SIGNIFICANCE_EXCEPTION 0x000E #define PGM_FLOATING_POINT_DIVIDE_EXCEPTION 0x000F #define PGM_SEGMENT_TRANSLATION_EXCEPTION 0x0010 #define PGM_PAGE_TRANSLATION_EXCEPTION 0x0011 #define PGM_TRANSLATION_SPECIFICATION_EXCEPTION 0x0012 #define PGM_SPECIAL_OPERATION_EXCEPTION 0x0013 #define PGM_OPERAND_EXCEPTION 0x0015 #define PGM_TRACE_TABLE_EXCEPTION 0x0016 #define PGM_ASN_TRANSLATION_SPECIFICATION_EXCEPTION 0x0017 #define PGM_VECTOR_OPERATION_EXCEPTION 0x0019 #define PGM_SPACE_SWITCH_EVENT 0x001C #define PGM_SQUARE_ROOT_EXCEPTION 0x001D #define PGM_UNNORMALIZED_OPERAND_EXCEPTION 0x001E #define PGM_PC_TRANSLATION_SPECIFICATION_EXCEPTION 0x001F #define PGM_AFX_TRANSLATION_EXCEPTION 0x0020 #define PGM_ASX_TRANSLATION_EXCEPTION 0x0021 #define PGM_LX_TRANSLATION_EXCEPTION 0x0022 #define PGM_EX_TRANSLATION_EXCEPTION 0x0023 #define PGM_PRIMARY_AUTHORITY_EXCEPTION 0x0024 #define PGM_SECONDARY_AUTHORITY_EXCEPTION 0x0025 #define PGM_LFX_TRANSLATION_EXCEPTION 0x0026 #define PGM_LSX_TRANSLATION_EXCEPTION 0x0027 #define PGM_ALET_SPECIFICATION_EXCEPTION 0x0028 #define PGM_ALEN_TRANSLATION_EXCEPTION 0x0029 #define PGM_ALE_SEQUENCE_EXCEPTION 0x002A #define PGM_ASTE_VALIDITY_EXCEPTION 0x002B #define PGM_ASTE_SEQUENCE_EXCEPTION 0x002C #define PGM_EXTENDED_AUTHORITY_EXCEPTION 0x002D #define PGM_LSTE_SEQUENCE_EXCEPTION 0x002E #define PGM_ASTE_INSTANCE_EXCEPTION 0x002F #define PGM_STACK_FULL_EXCEPTION 0x0030 #define PGM_STACK_EMPTY_EXCEPTION 0x0031 #define PGM_STACK_SPECIFICATION_EXCEPTION 0x0032 #define PGM_STACK_TYPE_EXCEPTION 0x0033 #define PGM_STACK_OPERATION_EXCEPTION 0x0034 #define PGM_ASCE_TYPE_EXCEPTION 0x0038 #define PGM_REGION_FIRST_TRANSLATION_EXCEPTION 0x0039 #define PGM_REGION_SECOND_TRANSLATION_EXCEPTION 0x003A #define PGM_REGION_THIRD_TRANSLATION_EXCEPTION 0x003B #define PGM_MONITOR_EVENT 0x0040 #define PGM_PER_EVENT 0x0080 #define PGM_CRYPTO_OPERATION_EXCEPTION 0x0119 /* External interrupt codes */ #define EXT_INTERRUPT_KEY_INTERRUPT 0x0040 #define EXT_INTERVAL_TIMER_INTERRUPT 0x0080 #define EXT_TOD_CLOCK_SYNC_CHECK_INTERRUPT 0x1003 #define EXT_CLOCK_COMPARATOR_INTERRUPT 0x1004 #define EXT_CPU_TIMER_INTERRUPT 0x1005 #define EXT_MALFUNCTION_ALERT_INTERRUPT 0x1200 #define EXT_EMERGENCY_SIGNAL_INTERRUPT 0x1201 #define EXT_EXTERNAL_CALL_INTERRUPT 0x1202 #define EXT_ETR_INTERRUPT 0x1406 #define EXT_SERVICE_SIGNAL_INTERRUPT 0x2401 #define EXT_IUCV_INTERRUPT 0x4000 #if defined(FEATURE_ECPSVM) #define EXT_VINTERVAL_TIMER_INTERRUPT 0x0100 #endif #if defined(FEATURE_VM_BLOCKIO) #define EXT_BLOCKIO_INTERRUPT 0x2603 #endif /* Macros for classifying CCW operation codes */ #define IS_CCW_WRITE(c) (((c)&0x03)==0x01) #define IS_CCW_READ(c) (((c)&0x03)==0x02) #define IS_CCW_CONTROL(c) (((c)&0x03)==0x03) #define IS_CCW_NOP(c) ((c)==0x03) #define IS_CCW_SET_EXTENDED(c) ((c)==0xC3) #define IS_CCW_SENSE(c) (((c)&0x0F)==0x04) #define IS_CCW_TIC(c) (((c)&0x0F)==0x08) #define IS_CCW_RDBACK(c) (((c)&0x0F)==0x0C) /* Operation request block structure definition */ typedef struct _ORB { FWORD intparm; /* Interruption parameter */ BYTE flag4; /* Flag byte 4 */ BYTE flag5; /* Flag byte 5 */ BYTE lpm; /* Logical path mask */ BYTE flag7; /* Flag byte 7 */ FWORD ccwaddr; /* CCW address */ } ORB; /* Bit definitions for ORB flag byte 4 */ #define ORB4_KEY 0xF0 /* Subchannel protection key */ #define ORB4_S 0x08 /* Suspend control */ #define ORB4_C 0x04 /* Streaming mode (FICON) */ #define ORB4_M 0x02 /* Modification (FICON) */ #define ORB4_Y 0x01 /* Synchronization (FICON) */ /* Bit definitions for ORB flag byte 5 */ #define ORB5_F 0x80 /* CCW format */ #define ORB5_P 0x40 /* Prefetch */ #define ORB5_I 0x20 /* Initial status interrupt */ #define ORB5_A 0x10 /* Address limit checking */ #define ORB5_U 0x08 /* Suppress susp interrupt */ #define ORB5_RESV 0x04 /* Reserved bit - must be 0 */ #define ORB5_H 0x02 /* Format-2 IDAW control */ #define ORB5_T 0x01 /* 2K format-2 IDAW control */ /* Bit definitions for ORB flag byte 7 */ #define ORB7_L 0x80 /* Suppress incorrect length */ #define ORB7_D 0x40 /* MIDAW control @MW*/ #define ORB7_RESV 0x3E /* Reserved - must be 0 @MW*/ #define ORB7_X 0x01 /* ORB extension control */ /* Path management control word structure definition */ typedef struct _PMCW { FWORD intparm; /* Interruption parameter */ BYTE flag4; /* Flag byte 4 */ BYTE flag5; /* Flag byte 5 */ HWORD devnum; /* Device number */ BYTE lpm; /* Logical path mask */ BYTE pnom; /* Path not operational mask */ BYTE lpum; /* Last path used mask */ BYTE pim; /* Path installed mask */ HWORD mbi; /* Measurement block index */ BYTE pom; /* Path operational mask */ BYTE pam; /* Path available mask */ BYTE chpid[8]; /* Channel path identifiers */ BYTE zone; /* SIE zone */ BYTE flag25; /* Flag byte 25 */ BYTE flag26; /* Reserved byte - must be 0 */ BYTE flag27; /* Flag byte 27 */ } PMCW; /* Bit definitions for PMCW flag byte 4 */ #define PMCW4_Q 0x80 /* QDIO available */ #define PMCW4_ISC 0x38 /* Interruption subclass */ #define PMCW4_A 0x01 /* Alternate Block Control */ #define PMCW4_RESV 0x46 /* Reserved bits - must be 0 */ /* Bit definitions for PMCW flag byte 5 */ #define PMCW5_E 0x80 /* Subchannel enabled */ #define PMCW5_LM 0x60 /* Limit mode... */ #define PMCW5_LM_NONE 0x00 /* ...no limit checking */ #define PMCW5_LM_LOW 0x20 /* ...lower limit specified */ #define PMCW5_LM_HIGH 0x40 /* ...upper limit specified */ #define PMCW5_LM_RESV 0x60 /* ...reserved value */ #define PMCW5_MM 0x18 /* Measurement mode enable...*/ #define PMCW5_MM_MBU 0x10 /* ...meas.block.upd enabled */ #define PMCW5_MM_DCTM 0x08 /* Dev.conn.time.meas enabled*/ #define PMCW5_D 0x04 /* Multipath mode enabled */ #define PMCW5_T 0x02 /* Timing facility available */ #define PMCW5_V 0x01 /* Subchannel valid */ /* Bit definitions for PMCW flag byte 25 */ #define PMCW25_VISC 0x1F /* Guest ISC */ #define PMCW25_TYPE 0xE0 /* Subchannel Type */ #define PMCW25_TYPE_0 0x00 /* I/O Subchannel */ #define PMCW25_TYPE_1 0x20 /* CHSC subchannel */ #define PMCW25_TYPE_2 0x40 /* Message subchannel */ #define PMCW25_TYPE_3 0x60 /* ADM subchannel */ /* Bit definitions for PMCW flag byte 27 */ #define PMCW27_I 0x80 /* Interrupt Interlock Cntl */ #define PMCW27_S 0x01 /* Concurrent sense mode */ #define PMCW27_RESV 0x7E /* Reserved bits - must be 0 */ /* Extended status word structure definition */ typedef struct _ESW { BYTE scl0; /* Subchannel logout byte 0 */ BYTE lpum; /* Last path used mask */ BYTE scl2; /* Subchannel logout byte 2 */ BYTE scl3; /* Subchannel logout byte 3 */ BYTE erw0; /* Extended report word byte0*/ BYTE erw1; /* Extended report word byte1*/ BYTE erw2; /* Extended report word byte2*/ BYTE erw3; /* Extended report word byte3*/ FWORD failaddr; /* Failing storage address */ FWORD resv2; /* Reserved word - must be 0 */ FWORD resv3; /* Reserved word - must be 0 */ } ESW; /* Bit definitions for subchannel logout byte 0 */ #define SCL0_ESF 0x7F /* Extended status flags... */ #define SCL0_ESF_KEY 0x40 /* ...key check */ #define SCL0_ESF_MBPGK 0x20 /* ...meas.block prog.check */ #define SCL0_ESF_MBDCK 0x10 /* ...meas.block data check */ #define SCL0_ESF_MBPTK 0x08 /* ...meas.block prot.check */ #define SCL0_ESF_CCWCK 0x04 /* ...CCW check */ #define SCL0_ESF_IDACK 0x02 /* ...IDAW check */ /* Bit definitions for subchannel logout byte 2 */ #define SCL2_R 0x80 /* Ancillary report bit */ #define SCL2_FVF 0x7C /* Field validity flags... */ #define SCL2_FVF_LPUM 0x40 /* ...LPUM valid */ #define SCL2_FVF_TC 0x20 /* ...termination code valid */ #define SCL2_FVF_SC 0x10 /* ...sequence code valid */ #define SCL2_FVF_USTAT 0x08 /* ...device status valid */ #define SCL2_FVF_CCWAD 0x04 /* ...CCW address valid */ #define SCL2_SA 0x03 /* Storage access code... */ #define SCL2_SA_UNK 0x00 /* ...access type unknown */ #define SCL2_SA_RD 0x01 /* ...read */ #define SCL2_SA_WRT 0x02 /* ...write */ #define SCL2_SA_RDBK 0x03 /* ...read backward */ /* Bit definitions for subchannel logout byte 3 */ #define SCL3_TC 0xC0 /* Termination code... */ #define SCL3_TC_HALT 0x00 /* ...halt signal issued */ #define SCL3_TC_NORM 0x40 /* ...stop, stack, or normal */ #define SCL3_TC_CLEAR 0x80 /* ...clear signal issued */ #define SCL3_TC_RESV 0xC0 /* ...reserved */ #define SCL3_D 0x20 /* Device status check */ #define SCL3_E 0x10 /* Secondary error */ #define SCL3_A 0x08 /* I/O error alert */ #define SCL3_SC 0x07 /* Sequence code */ /* Bit definitions for extended report word byte 0 */ #define ERW0_A 0x10 /* Authorization check */ #define ERW0_P 0x08 /* Path verification required*/ #define ERW0_T 0x04 /* Channel path timeout */ #define ERW0_F 0x02 /* Failing storage addr valid*/ #define ERW0_S 0x01 /* Concurrent sense */ /* Bit definitions for extended report word byte 1 */ #define ERW1_SCNT 0x3F /* Concurrent sense count */ /* Subchannel status word structure definition */ typedef struct _SCSW { BYTE flag0; /* Flag byte 0 */ BYTE flag1; /* Flag byte 1 */ BYTE flag2; /* Flag byte 2 */ BYTE flag3; /* Flag byte 3 */ FWORD ccwaddr; /* CCW address */ BYTE unitstat; /* Device status */ BYTE chanstat; /* Subchannel status */ HWORD count; /* Residual byte count */ } SCSW; /* Bit definitions for SCSW flag byte 0 */ #define SCSW0_KEY 0xF0 /* Subchannel protection key */ #define SCSW0_S 0x08 /* Suspend control */ #define SCSW0_L 0x04 /* ESW format (logout stored)*/ #define SCSW0_CC 0x03 /* Deferred condition code...*/ #define SCSW0_CC_0 0x00 /* ...condition code 0 */ #define SCSW0_CC_1 0x01 /* ...condition code 1 */ #define SCSW0_CC_3 0x03 /* ...condition code 3 */ /* Bit definitions for SCSW flag byte 1 */ #define SCSW1_F 0x80 /* CCW format */ #define SCSW1_P 0x40 /* Prefetch */ #define SCSW1_I 0x20 /* Initial status interrupt */ #define SCSW1_A 0x10 /* Address limit checking */ #define SCSW1_U 0x08 /* Suppress susp interrupt */ #define SCSW1_Z 0x04 /* Zero condition code */ #define SCSW1_E 0x02 /* Extended control */ #define SCSW1_N 0x01 /* Path not operational */ /* Bit definitions for SCSW flag byte 2 */ #define SCSW2_Q 0x80 /* QDIO active */ #define SCSW2_FC 0x70 /* Function control bits... */ #define SCSW2_FC_START 0x40 /* ...start function */ #define SCSW2_FC_HALT 0x20 /* ...halt function */ #define SCSW2_FC_CLEAR 0x10 /* ...clear function */ #define SCSW2_AC 0x0F /* Activity control bits... */ #define SCSW2_AC_RESUM 0x08 /* ...resume pending */ #define SCSW2_AC_START 0x04 /* ...start pending */ #define SCSW2_AC_HALT 0x02 /* ...halt pending */ #define SCSW2_AC_CLEAR 0x01 /* ...clear pending */ /* Bit definitions for SCSW flag byte 3 */ #define SCSW3_AC 0xE0 /* Activity control bits... */ #define SCSW3_AC_SCHAC 0x80 /* ...subchannel active */ #define SCSW3_AC_DEVAC 0x40 /* ...device active */ #define SCSW3_AC_SUSP 0x20 /* ...suspended */ #define SCSW3_SC 0x1F /* Status control bits... */ #define SCSW3_SC_ALERT 0x10 /* ...alert status */ #define SCSW3_SC_INTER 0x08 /* ...intermediate status */ #define SCSW3_SC_PRI 0x04 /* ...primary status */ #define SCSW3_SC_SEC 0x02 /* ...secondary status */ #define SCSW3_SC_PEND 0x01 /* ...status pending */ /* CSW unit status flags */ #define CSW_ATTN 0x80 /* Attention */ #define CSW_SM 0x40 /* Status modifier */ #define CSW_CUE 0x20 /* Control unit end */ #define CSW_BUSY 0x10 /* Busy */ #define CSW_CE 0x08 /* Channel end */ #define CSW_DE 0x04 /* Device end */ #define CSW_UC 0x02 /* Unit check */ #define CSW_UX 0x01 /* Unit exception */ /* CSW channel status flags */ #define CSW_PCI 0x80 /* Program control interrupt */ #define CSW_IL 0x40 /* Incorrect length */ #define CSW_PROGC 0x20 /* Program check */ #define CSW_PROTC 0x10 /* Protection check */ #define CSW_CDC 0x08 /* Channel data check */ #define CSW_CCC 0x04 /* Channel control check */ #define CSW_ICC 0x02 /* Interface control check */ #define CSW_CHC 0x01 /* Chaining check */ /* CCW flags */ #define CCW_FLAGS_CD 0x80 /* Chain data flag */ #define CCW_FLAGS_CC 0x40 /* Chain command flag */ #define CCW_FLAGS_SLI 0x20 /* Suppress incorrect length indication flag */ #define CCW_FLAGS_SKIP 0x10 /* Skip flag */ #define CCW_FLAGS_PCI 0x08 /* Program controlled interrupt flag */ #define CCW_FLAGS_IDA 0x04 /* Indirect data address flag*/ #define CCW_FLAGS_SUSP 0x02 /* Suspend flag */ #define CCW_FLAGS_MIDAW 0x01 /* Modified IDAW flag @MW*/ /* MIDAW flags (bits 40-47) @MW*/ #define MIDAW_LAST 0x80 /* Last MIDAW flag @MW*/ #define MIDAW_SKIP 0x40 /* Skip flag @MW*/ #define MIDAW_DTI 0x20 /* Data transfer interrupt@MW*/ #define MIDAW_RESV 0x1F /* Reserved bits @MW*/ /* Device independent bit settings for sense byte 0 */ #define SENSE_CR 0x80 /* Command reject */ #define SENSE_IR 0x40 /* Intervention required */ #define SENSE_BOC 0x20 /* Bus-out check */ #define SENSE_EC 0x10 /* Equipment check */ #define SENSE_DC 0x08 /* Data check */ #define SENSE_OR 0x04 /* Overrun */ #define SENSE_US 0x04 /* Unit specify */ #define SENSE_CC 0x02 /* Control check */ #define SENSE_OC 0x01 /* Operation check */ /* Device dependent bit settings for sense byte 1 */ #define SENSE1_PER 0x80 /* Permanent Error */ #define SENSE1_ITF 0x40 /* Invalid Track Format */ #define SENSE1_EOC 0x20 /* End of Cylinder */ #define SENSE1_MTO 0x10 /* Message to Operator */ #define SENSE1_NRF 0x08 /* No Record Found */ #define SENSE1_FP 0x04 /* File Protected */ #define SENSE1_WRI 0x02 /* Write Inhibited */ #define SENSE1_IE 0x01 /* Imprecise Ending */ /* Subchannel information block structure definition */ typedef struct _SCHIB { PMCW pmcw; /* Path management ctl word */ SCSW scsw; /* Subchannel status word */ BYTE moddep[12]; /* Model dependent area */ } SCHIB; /* Interruption response block structure definition */ typedef struct _IRB { SCSW scsw; /* Subchannel status word */ ESW esw; /* Extended status word */ BYTE ecw[32]; /* Extended control word */ } IRB; /* Measurement Block */ typedef struct _MBK { HWORD srcount; /* SSCH + RSCH count */ HWORD samplecnt; /* Sample count */ FWORD dct; /* Device connect time */ FWORD fpt; /* Function pending time */ FWORD ddt; /* Device disconnect time */ FWORD cuqt; /* Control unit queueing time*/ FWORD resv[3]; /* Reserved */ } MBK; /* Bit definitions for SCHM instruction */ #define CHM_GPR1_MBK 0xF0000000 /* Measurement Block Key */ #define CHM_GPR1_M 0x00000002 /* Measurement mode control */ #define CHM_GPR1_D 0x00000001 /* Block update Mode */ #define CHM_GPR1_A 0x01000000 /* Alternate mode */ #define CHM_GPR1_ZONE 0x00FF0000 /* Zone */ #define CHM_GPR1_RESV 0x0E00FFFC /* Reserved, must be zero */ /* Measurement Block Origin */ #define S_CHM_GPR2_RESV 0x8000001F /* Reserved, must be zero */ #define Z_CHM_GPR2_RESV 0x0000001F /* Reserved, must be zero */ /* Definitions for PLO instruction */ #define PLO_GPR0_FC 0x000000FF /* Function code mask */ #define PLO_GPR0_T 0x00000100 /* Function test mask */ #define PLO_GPR0_RESV 0xFFFFFE00 /* Reserved bits */ #define PLO_CL 0 /* Compare and load */ #define PLO_CLG 1 /* Compare and load */ #define PLO_CLGR 2 /* Compare and load ESAME */ #define PLO_CLX 3 /* Compare and load ESAME */ #define PLO_CS 4 /* Compare and swap */ #define PLO_CSG 5 /* Compare and swap */ #define PLO_CSGR 6 /* Compare and swap ESAME */ #define PLO_CSX 7 /* Compare and swap ESAME */ #define PLO_DCS 8 /* Double compare and swap */ #define PLO_DCSG 9 /* Double compare and swap */ #define PLO_DCSGR 10 /* Double c and s ESAME */ #define PLO_DCSX 11 /* Double c and s ESAME */ #define PLO_CSST 12 /* Compare and swap and store*/ #define PLO_CSSTG 13 /* Compare and swap and store*/ #define PLO_CSSTGR 14 /* C/S/S ESAME */ #define PLO_CSSTX 15 /* C/S/S ESAME */ #define PLO_CSDST 16 /* C/S and double store */ #define PLO_CSDSTG 17 /* C/S and double store */ #define PLO_CSDSTGR 18 /* C/S/DS ESAME */ #define PLO_CSDSTX 19 /* C/S/DS ESAME */ #define PLO_CSTST 20 /* C/S and triple store */ #define PLO_CSTSTG 21 /* C/S and triple store */ #define PLO_CSTSTGR 22 /* C/S/TS ESAME */ #define PLO_CSTSTX 23 /* C/S/TS ESAME */ /* Bit definitions for Store Facilities List instruction */ /* Byte STFL_0: STFL/STFLE bits 0-7 */ #define STFL_0_N3 0x80 /* Instructions marked N3 in the reference summary are available in ESA/390 mode */ #define STFL_0_ESAME_INSTALLED 0x40 /* ESAME mode is available on this processor */ #define STFL_0_ESAME_ACTIVE 0x20 /* ESAME mode is active on this processor */ #define STFL_0_IDTE_INSTALLED 0x10 /* IDTE installed ESAME mode */ #define STFL_0_IDTE_SC_SEGTAB 0x08 /* IDTE selective clearing when segtab invalidated */ #define STFL_0_IDTE_SC_REGTAB 0x04 /* IDTE selective clearing when regtab invalidated */ #define STFL_0_ASN_LX_REUSE 0x02 /* ASN-and-LX-reuse facility is installed */ #define STFL_0_STFL_EXTENDED 0x01 /* Store facility list @Z9 extended is installed @Z9*/ /* Byte STFL_1: STFL/STFLE bits 8-15 */ #define STFL_1_ENHANCED_DAT 0x80 /* Enhanced-DAT facility 208 is installed 208*/ #define STFL_1_SENSE_RUN_STATUS 0x40 /* Sense running status @Z9 facility is installed @Z9*/ #define STFL_1_CONDITIONAL_SSKE 0x20 /* Conditional SSKE facility is installed 407*/ #define STFL_1_CONFIG_TOPOLOGY 0x10 /* STSI-enhancement for configuration topology */ /* Byte STFL_2: STFL/STFLE bits 16-23 */ #define STFL_2_TRAN_FAC2 0x80 /* Extended translation facility 2 is installed */ #define STFL_2_MSG_SECURITY 0x40 /* Message security assist feature is installed */ #define STFL_2_LONG_DISPL_INST 0x20 /* Long displacement facility is installed */ #define STFL_2_LONG_DISPL_HPERF 0x10 /* Long displacement facility has high performance */ #define STFL_2_HFP_MULT_ADD_SUB 0x08 /* HFP multiply-add/subtract facility is installed */ #define STFL_2_EXTENDED_IMMED 0x04 /* Extended immediate @Z9 facility is installed @Z9*/ #define STFL_2_TRAN_FAC3 0x02 /* Extended translation facility 3 is installed */ #define STFL_2_HFP_UNNORM_EXT 0x01 /* HFP unnormalized extension facility is installed @Z9*/ /* Byte STFL_3: STFL/STFLE bits 24-31 */ #define STFL_3_ETF2_ENHANCEMENT 0x80 /* Extended translation @Z9 facility 2 enhancement @Z9*/ #define STFL_3_STORE_CLOCK_FAST 0x40 /* Store clock fast @Z9 enhancement installed @Z9*/ #define STFL_3_PARSING_ENHANCE 0x20 /* Parsing-Enhancement 208 facility is installed 208*/ #define STFL_3_MVCOS 0x10 /* MVCOS instruction is installed 407*/ #define STFL_3_TOD_CLOCK_STEER 0x08 /* TOD clock steering @Z9 facility is installed @Z9*/ #define STFL_3_ETF3_ENHANCEMENT 0x02 /* Extended translation @Z9 facility 3 enhancement @Z9*/ #define STFL_3_EXTRACT_CPU_TIME 0x01 /* Extract CPU time facility is installed 407*/ /* Byte STFL_4: STFLE bits 32-39 */ #define STFL_4_CSSF 0x80 /* Compare-and-Swap-and-Store facility is installed */ #define STFL_4_CSSF2 0x40 /* Compare-and-Swap-and-Store facility 2 is installed */ #define STFL_4_GEN_INST_EXTN 0x20 /* General-Instr-Extn 208 facility is installed 208*/ #define STFL_4_EXECUTE_EXTN 0x10 /* Execute-Extensions 208 facility is installed 208*/ /* Byte STFL_5: STFLE bits 40-47 */ #define STFL_5_SET_PROG_PARAM 0x80 /* 40:Set-Program-Parameter facility installed (ESAME)*/ #define STFL_5_FPS_ENHANCEMENT 0x40 /* Floating point support enhancements (FPR-GR-loading FPS-sign-handling, and DFP-rounding) installed */ #define STFL_5_DECIMAL_FLOAT 0x20 /* Decimal floating point (DFP) facility */ #define STFL_5_DFP_HPERF 0x10 /* DFP has high performance */ #define STFL_5_PFPO 0x08 /* PFPO instruction installed*/ /* Byte STFL_6: STFLE bits 48-55 */ /* Byte STFL_7: STFLE bits 56-63 */ /* Byte STFL_8: STFLE bits 64-71 */ #define STFL_8_CPU_MEAS_COUNTER 0x10 /* 67:CPU-measurement counter facility installed (ESAME)*/ #define STFL_8_CPU_MEAS_SAMPLNG 0x08 /* 68:CPU-measurement sampling facility installed (ESAME)*/ /* Bit definitions for the Vector Facility */ #define VSR_M 0x0001000000000000ULL /* Vector mask mode bit */ #define VSR_VCT 0x0000FFFF00000000ULL /* Vector count */ #define VSR_VIX 0x00000000FFFF0000ULL /* Vector interruption index */ #define VSR_VIU 0x000000000000FF00ULL /* Vector in-use bits */ #define VSR_VIU0 0x0000000000008000ULL /* Vector in-use bit vr0 */ #define VSR_VCH 0x00000000000000FFULL /* Vector change bits */ #define VSR_VCH0 0x0000000000000080ULL /* Vector change bit vr0 */ #define VSR_RESV 0xFFFE000000000000ULL /* Reserved bits */ #define VAC_MASK 0x00FFFFFFFFFFFFFFULL /* Vector Activity Count mask*/ /* SIE Format 1 State Descriptor Block */ typedef struct _SIE1BK { /* SIE State Descriptor */ /*000*/ BYTE v; /* Intervention requests */ #define SIE_V v #define SIE_V_WAIT 0x10 /* Wait/Run bit */ #define SIE_V_EXTCALL 0x08 /* External call pending */ #define SIE_V_STOP 0x04 /* SIE Stop control */ #define SIE_V_IO 0x02 /* I/O Interrupt pending */ #define SIE_V_EXT 0x01 /* EXT Interrupt pending */ /*001*/ BYTE s; /* State controls */ #define SIE_S s #define SIE_S_T 0x80 /* Interval timer irpt pend */ #define SIE_S_RETENTION 0x40 /* SIE State retained */ #define SIE_S_EXP_TIMER 0x02 /* Expedite timer enabled */ #define SIE_S_EXP_RUN 0x01 /* Expedite run enabled */ /*002*/ BYTE mx; /* Machine mode control */ #define SIE_MX mx #define SIE_MX_RRF 0x80 /* Region Relocate Installed */ #define SIE_MX_XC 0x01 /* XC mode guest */ /*003*/ BYTE m; /* Mode controls */ #define SIE_M m #define SIE_M_VCC 0x40 /* Vector change control */ #define SIE_M_XA 0x20 /* XA mode guest */ #define SIE_M_370 0x10 /* 370 mode guest */ #define SIE_M_VR 0x08 /* V=R mode guest */ #define SIE_M_ITMOF 0x04 /* Guest ival timer disabled */ #define SIE_M_GPE 0x01 /* Guest per enhancement */ /*004*/ FWORD prefix; /* Guest prefix register */ /*008*/ HWORD mso; /* Main Storage Origin */ /*00A*/ HWORD mse; /* Main Storage Extent */ /*00C*/ FWORD resv0cf; /*010*/ FWORD gr14; /* Guest gr 14 */ /*014*/ FWORD gr15; /* Guest gr 15 */ /*018*/ DBLWRD psw; /* Guest PSW */ /*020*/ FWORD resv20f; /*024*/ FWORD residue; /* Residue counter */ /*028*/ DBLWRD cputimer; /* CPU timer */ /*030*/ DBLWRD clockcomp; /* Clock comparator */ /*038*/ DBLWRD epoch; /* Guest/Host epoch diff. */ /*040*/ FWORD svc_ctl; /* SVC Controls */ #define SIE_SVC0 svc_ctl[0] #define SIE_SVC0_ALL 0x80 /* Intercept all SVCs */ #define SIE_SVC0_1N 0x40 /* Intercept SVC 1n */ #define SIE_SVC0_2N 0x20 /* Intercept SVC 2n */ #define SIE_SVC0_3N 0x10 /* Intercept SVC 3n */ /*044*/ HWORD lctl_ctl; /* LCTL Control */ #define SIE_LCTL0 lctl_ctl[0] #define SIE_LCTL0_CR0 0x80 /* Intercept LCTL 0 */ #define SIE_LCTL0_CR1 0x40 /* Intercept LCTL 1 */ #define SIE_LCTL0_CR2 0x20 /* Intercept LCTL 2 */ #define SIE_LCTL0_CR3 0x10 /* Intercept LCTL 3 */ #define SIE_LCTL0_CR4 0x08 /* Intercept LCTL 4 */ #define SIE_LCTL0_CR5 0x04 /* Intercept LCTL 5 */ #define SIE_LCTL0_CR6 0x02 /* Intercept LCTL 6 */ #define SIE_LCTL0_CR7 0x01 /* Intercept LCTL 7 */ #define SIE_LCTL1 lctl_ctl[1] #define SIE_LCTL1_CR8 0x80 /* Intercept LCTL 8 */ #define SIE_LCTL1_CR9 0x40 /* Intercept LCTL 9 */ #define SIE_LCTL1_CR10 0x20 /* Intercept LCTL 10 */ #define SIE_LCTL1_CR11 0x10 /* Intercept LCTL 11 */ #define SIE_LCTL1_CR12 0x08 /* Intercept LCTL 12 */ #define SIE_LCTL1_CR13 0x04 /* Intercept LCTL 13 */ #define SIE_LCTL1_CR14 0x02 /* Intercept LCTL 14 */ #define SIE_LCTL1_CR15 0x01 /* Intercept LCTL 15 */ /*046*/ HWORD cpuad; /* Virtual CPU address */ /*048*/ FWORD ic; /* Interception Controls */ #define SIE_IC0 ic[0] #define SIE_IC0_OPEREX 0x80 /* Intercept operation exc. */ #define SIE_IC0_PRIVOP 0x40 /* Intercept priv. op. exc. */ #define SIE_IC0_PGMALL 0x20 /* Intercept program ints */ #define SIE_IC0_TS1 0x08 /* Intercept TS cc1 */ #define SIE_IC0_CS1 0x04 /* Intercept CS cc1 */ #define SIE_IC0_CDS1 0x02 /* Intercept CDS cc1 */ #define SIE_IC0_IPTECSP 0x01 /* Intercept IPTE or CSP */ #define SIE_IC1 ic[1] #define SIE_IC1_LPSW 0x40 /* Intercept LPSW */ #define SIE_IC1_PXLB 0x20 /* Intercept PTLB or PALB */ #define SIE_IC1_SSM 0x10 /* Intercept SSM */ #define SIE_IC1_BSA 0x08 /* Intercept BSA */ #define SIE_IC1_STCTL 0x04 /* Intercept STCTL */ #define SIE_IC1_STNSM 0x02 /* Intercept STNSM */ #define SIE_IC1_STOSM 0x01 /* Intercept STOSM */ #define SIE_IC2 ic[2] #define SIE_IC2_STCK 0x80 /* Intercept STCK */ #define SIE_IC2_ISKE 0x40 /* Intercept ISK/ISKE */ #define SIE_IC2_SSKE 0x20 /* Intercept SSK/SSKE */ #define SIE_IC2_RRBE 0x10 /* Intercept RRB/RRBE */ #define SIE_IC2_PC 0x08 /* Intercept PC */ #define SIE_IC2_PT 0x04 /* Intercept PT */ #define SIE_IC2_TPROT 0x02 /* Intercept TPROT */ #define SIE_IC2_LASP 0x01 /* Intercept LASP */ #define SIE_IC3 ic[3] #define SIE_IC3_VACSV 0x80 /* Intercept VACSV */ #define SIE_IC3_SPT 0x40 /* Intercept SPT and STPT */ #define SIE_IC3_SCKC 0x20 /* Intercept SCKC and STCKC */ #define SIE_IC3_VACRS 0x10 /* Intercept VACRS */ #define SIE_IC3_PR 0x08 /* Intercept PR */ #define SIE_IC3_BAKR 0x04 /* Intercept BAKR */ #define SIE_IC3_PGX 0x02 /* Intercept PGIN/PGOUT */ /*04C*/ FWORD ec; /* Execution Controls */ #define SIE_EC0 ec[0] #define SIE_EC0_EXTA 0x80 /* External Interrupt Assist */ #define SIE_EC0_INTA 0x40 /* Intervention Bypass Assist*/ #define SIE_EC0_WAIA 0x20 /* Wait State Assist */ #define SIE_EC0_SIGPA 0x10 /* SIGP Assist */ #define SIE_EC0_ALERT 0x08 /* Alert Monitoring */ #define SIE_EC0_IOA 0x04 /* I/O Assist */ #define SIE_EC0_MVPG 0x01 /* Interpret MVPG and IESBE */ #define SIE_EC1 ec[1] #define SIE_EC1_EC370 0x20 /* 370 I/O Assist */ #define SIE_EC1_VFONL 0x04 /* Virtual VF online */ #define SIE_EC2 ec[2] #define SIE_EC2_PROTEX 0x20 /* Intercept prot exception */ #define SIE_EC3 ec[3] #define SIE_EC3_SIGAA 0x04 /* SIGA Assist */ /*050*/ BYTE c; /* Interception Code */ #define SIE_C_INST 4 /* Instruction interception */ #define SIE_C_PGMINT 8 /* Program interruption */ #define SIE_C_PGMINST 12 /* Program/instruction int */ #define SIE_C_EXTREQ 16 /* External request */ #define SIE_C_EXTINT 20 /* External interruption */ #define SIE_C_IOREQ 24 /* I/O request */ #define SIE_C_WAIT 28 /* Wait state */ #define SIE_C_VALIDITY 32 /* Validity */ #define SIE_C_STOPREQ 40 /* Stop request */ #define SIE_C_OPEREXC 44 /* Operation Exception */ #define SIE_C_IOINT 60 /* I/O Interruption */ #define SIE_C_IOINST 64 /* I/O Instruction */ #define SIE_C_EXP_RUN 68 /* Expedited Run Intercept */ #define SIE_C_EXP_TIMER 72 /* Expedited Timer Intercept */ /*051*/ BYTE f; /* Interception Status */ #define SIE_F f #define SIE_F_IN 0x80 /* Intercept format 2 */ #define SIE_F_IF 0x02 /* Instruction fetch PER */ #define SIE_F_EX 0x01 /* Icept for target of EX */ /*052*/ HWORD lhcpu; /* Last Host CPU addr */ /*054*/ HWORD todpf; /* TOD programmable field */ /*056*/ HWORD ipa; /* Instruction parameter A */ /*058*/ FWORD ipb; /* Instruction parameter B */ /*05C*/ FWORD ipc; /* Instruction parameter C */ /*060*/ FWORD rcpo; /* RCP area origin */ #define SIE_RCPO0 rcpo[0] #define SIE_RCPO0_SKA 0x80 /* Storage Key Assist */ #define SIE_RCPO0_SKAIP 0x40 /* SKA in progress */ #define SIE_RCPO2 rcpo[2] #define SIE_RCPO2_RCPBY 0x10 /* RCP Bypass */ /*064*/ FWORD scao; /* SCA area origin */ /*068*/ FWORD subchtabo; /* Subchannel table origin */ /*06C*/ FWORD resv6Cf; /*070*/ HWORD tch_ctl; /* Test Channel control */ /*072*/ HWORD resv72h; /*074*/ BYTE zone; /* Zone Number */ /*075*/ BYTE resv075; /*076*/ BYTE tschds; /* TSCH device status */ /*077*/ BYTE tschsc; /* TSCH subchannel status */ /*078*/ BYTE xslim[3]; /* Extended stor upper lim */ /*07B*/ BYTE resv7Bb; /*07C*/ FWORD resv7Cf; /*080*/ FWORD cr[16]; /* Guest Control registers */ /*0C0*/ BYTE ip[34]; /* Interruption parameters */ #define SIE_IP_PSA_OFFSET 0x40 /* Offset of the IP field relative to the ipfields in the PSA */ #define SIE_II_PSA_OFFSET 0x30 /* Offset of the IP field relative to the I/O fields in the PSA for ESAME guest*/ /*0E2*/ BYTE xso[3]; /* Expanded storage origin */ /*0E5*/ BYTE xsl[3]; /* Expanded storage limit */ /*0E8*/ BYTE resvE8b[24]; } SIE1BK; /* SIE Format 2 State Descriptor Block */ typedef struct _SIE2BK { /* SIE State Descriptor */ /*000*/ BYTE v; /* Intervention requests */ #define SIE_V v #define SIE_V_WAIT 0x10 /* Wait/Run bit */ #define SIE_V_EXTCALL 0x08 /* External call pending */ #define SIE_V_STOP 0x04 /* SIE Stop control */ #define SIE_V_IO 0x02 /* I/O Interrupt pending */ #define SIE_V_EXT 0x01 /* EXT Interrupt pending */ /*001*/ BYTE s; /* State controls */ #define SIE_S s #define SIE_S_T 0x80 /* Interval timer irpt pend */ #define SIE_S_RETENTION 0x40 /* SIE State retained */ #define SIE_S_EXP_TIMER 0x02 /* Expedite timer enabled */ #define SIE_S_EXP_RUN 0x01 /* Expedite run enabled */ /*002*/ BYTE mx; /* Machine mode control */ #define SIE_MX mx #define SIE_MX_RRF 0x80 /* Region Relocate Installed */ #define SIE_MX_XC 0x01 /* XC mode guest */ #define SIE_MX_ESAME 0x08 /* ESAME mode guest */ /*003*/ BYTE m; /* Mode controls */ #define SIE_M m #define SIE_M_VCC 0x40 /* Vector change control */ #define SIE_M_XA 0x20 /* XA mode guest */ #define SIE_M_370 0x10 /* 370 mode guest */ #define SIE_M_VR 0x08 /* V=R mode guest */ #define SIE_M_ITMOF 0x04 /* Guest ival timer disabled */ #define SIE_M_GPE 0x01 /* Guest per enhancement */ /*004*/ FWORD prefix; /* Guest prefix register */ /*008*/ FWORD resv008f; /*00C*/ FWORD resv00cf; /*010*/ DBLWRD resv010d; /*018*/ DBLWRD resv018d; /*020*/ DBLWRD resv020d; /*028*/ DBLWRD cputimer; /* CPU timer */ /*030*/ DBLWRD clockcomp; /* Clock comparator */ /*038*/ DBLWRD epoch; /* Guest/Host epoch diff. */ /*040*/ FWORD svc_ctl; /* SVC Controls */ #define SIE_SVC0 svc_ctl[0] #define SIE_SVC0_ALL 0x80 /* Intercept all SVCs */ #define SIE_SVC0_1N 0x40 /* Intercept SVC 1n */ #define SIE_SVC0_2N 0x20 /* Intercept SVC 2n */ #define SIE_SVC0_3N 0x10 /* Intercept SVC 3n */ /*044*/ HWORD lctl_ctl; /* LCTL Control */ #define SIE_LCTL0 lctl_ctl[0] #define SIE_LCTL0_CR0 0x80 /* Intercept LCTL 0 */ #define SIE_LCTL0_CR1 0x40 /* Intercept LCTL 1 */ #define SIE_LCTL0_CR2 0x20 /* Intercept LCTL 2 */ #define SIE_LCTL0_CR3 0x10 /* Intercept LCTL 3 */ #define SIE_LCTL0_CR4 0x08 /* Intercept LCTL 4 */ #define SIE_LCTL0_CR5 0x04 /* Intercept LCTL 5 */ #define SIE_LCTL0_CR6 0x02 /* Intercept LCTL 6 */ #define SIE_LCTL0_CR7 0x01 /* Intercept LCTL 7 */ #define SIE_LCTL1 lctl_ctl[1] #define SIE_LCTL1_CR8 0x80 /* Intercept LCTL 8 */ #define SIE_LCTL1_CR9 0x40 /* Intercept LCTL 9 */ #define SIE_LCTL1_CR10 0x20 /* Intercept LCTL 10 */ #define SIE_LCTL1_CR11 0x10 /* Intercept LCTL 11 */ #define SIE_LCTL1_CR12 0x08 /* Intercept LCTL 12 */ #define SIE_LCTL1_CR13 0x04 /* Intercept LCTL 13 */ #define SIE_LCTL1_CR14 0x02 /* Intercept LCTL 14 */ #define SIE_LCTL1_CR15 0x01 /* Intercept LCTL 15 */ /*046*/ HWORD cpuad; /* Virtual CPU address */ /*048*/ FWORD ic; /* Interception Controls */ #define SIE_IC0 ic[0] #define SIE_IC0_OPEREX 0x80 /* Intercept operation exc. */ #define SIE_IC0_PRIVOP 0x40 /* Intercept priv. op. exc. */ #define SIE_IC0_PGMALL 0x20 /* Intercept program ints */ #define SIE_IC0_TS1 0x08 /* Intercept TS cc1 */ #define SIE_IC0_CS1 0x04 /* Intercept CS cc1 */ #define SIE_IC0_CDS1 0x02 /* Intercept CDS cc1 */ #define SIE_IC0_IPTECSP 0x01 /* Intercept IPTE or CSP */ #define SIE_IC1 ic[1] #define SIE_IC1_LPSW 0x40 /* Intercept LPSW/LPSWE */ #define SIE_IC1_PXLB 0x20 /* Intercept PTLB or PALB */ #define SIE_IC1_SSM 0x10 /* Intercept SSM */ #define SIE_IC1_BSA 0x08 /* Intercept BSA */ #define SIE_IC1_STCTL 0x04 /* Intercept STCTL */ #define SIE_IC1_STNSM 0x02 /* Intercept STNSM */ #define SIE_IC1_STOSM 0x01 /* Intercept STOSM */ #define SIE_IC2 ic[2] #define SIE_IC2_STCK 0x80 /* Intercept STCK */ #define SIE_IC2_ISKE 0x40 /* Intercept ISK/ISKE */ #define SIE_IC2_SSKE 0x20 /* Intercept SSK/SSKE */ #define SIE_IC2_RRBE 0x10 /* Intercept RRB/RRBE */ #define SIE_IC2_PC 0x08 /* Intercept PC */ #define SIE_IC2_PT 0x04 /* Intercept PT */ #define SIE_IC2_TPROT 0x02 /* Intercept TPROT */ #define SIE_IC2_LASP 0x01 /* Intercept LASP */ #define SIE_IC3 ic[3] #define SIE_IC3_VACSV 0x80 /* Intercept VACSV */ #define SIE_IC3_SPT 0x40 /* Intercept SPT and STPT */ #define SIE_IC3_SCKC 0x20 /* Intercept SCKC and STCKC */ #define SIE_IC3_VACRS 0x10 /* Intercept VACRS */ #define SIE_IC3_PR 0x08 /* Intercept PR */ #define SIE_IC3_BAKR 0x04 /* Intercept BAKR */ #define SIE_IC3_PGX 0x02 /* Intercept PGIN/PGOUT */ /*04C*/ FWORD ec; /* Execution Controls */ #define SIE_EC0 ec[0] #define SIE_EC0_EXTA 0x80 /* External Interrupt Assist */ #define SIE_EC0_INTA 0x40 /* Intervention Bypass Assist*/ #define SIE_EC0_WAIA 0x20 /* Wait State Assist */ #define SIE_EC0_SIGPA 0x10 /* SIGP Assist */ #define SIE_EC0_ALERT 0x08 /* Alert Monitoring */ #define SIE_EC0_IOA 0x04 /* I/O Assist */ #define SIE_EC0_MVPG 0x01 /* Interpret MVPG and IESBE */ #define SIE_EC1 ec[1] #define SIE_EC1_EC370 0x20 /* 370 I/O Assist */ #define SIE_EC1_VFONL 0x04 /* Virtual VF online */ #define SIE_EC2 ec[2] #define SIE_EC2_PROTEX 0x20 /* Intercept prot exception */ #define SIE_EC3 ec[3] #define SIE_EC3_SIGAA 0x04 /* SIGA Assist */ /*050*/ BYTE c; /* Interception Code */ #define SIE_C_INST 4 /* Instruction interception */ #define SIE_C_PGMINT 8 /* Program interruption */ #define SIE_C_PGMINST 12 /* Program/instruction int */ #define SIE_C_EXTREQ 16 /* External request */ #define SIE_C_EXTINT 20 /* External interruption */ #define SIE_C_IOREQ 24 /* I/O request */ #define SIE_C_WAIT 28 /* Wait state */ #define SIE_C_VALIDITY 32 /* Validity */ #define SIE_C_STOPREQ 40 /* Stop request */ #define SIE_C_OPEREXC 44 /* Operation Exception */ #define SIE_C_EXP_RUN 68 /* Expedited Run Intercept */ #define SIE_C_EXP_TIMER 72 /* Expedited Timer Intercept */ /*051*/ BYTE f; /* Interception Status */ #define SIE_F f #define SIE_F_IN 0x80 /* Intercept format 2 */ #define SIE_F_IF 0x02 /* Instruction fetch PER */ #define SIE_F_EX 0x01 /* Icept for target of EX */ /*052*/ HWORD lhcpu; /* Last Host CPU addr */ /*054*/ HWORD resv054h; /*056*/ HWORD ipa; /* Instruction parameter A */ #define vi_who ipa[0] #define vi_when ipa[1] #define vi_why ipb #define vi_zero ipb+2 /*058*/ FWORD ipb; /* Instruction parameter B */ /*05C*/ FWORD ipc; /* Instruction parameter C */ /*060*/ FWORD rcpo; /* RCP area origin */ #define SIE_RCPO0 rcpo[0] #define SIE_RCPO0_SKA 0x80 /* Storage Key Assist */ #define SIE_RCPO0_SKAIP 0x40 /* SKA in progress */ #define SIE_RCPO2 rcpo[2] #define SIE_RCPO2_RCPBY 0x10 /* RCP Bypass */ /*064*/ FWORD scao; /* SCA area origin */ /*068*/ FWORD resv068f; /*06C*/ HWORD todpfh; /* TOD pf high half */ /*06E*/ HWORD todpf; /* TOD programmable field */ /*070*/ FWORD resv070f; /*074*/ BYTE zone; /* Zone Number */ /*075*/ BYTE resv075; /*076*/ BYTE tschds; /* TSCH device status */ /*077*/ BYTE tschsc; /* TSCH subchannel status */ /*078*/ FWORD resv078f; /*07C*/ FWORD resv07cf; /*080*/ DBLWRD mso; /* Main Storage Origin */ /*088*/ DBLWRD mse; /* Main Storage Extend The actual guest machine size is (mse+1)-mso */ #define SIE2_MS_MASK 0xFFFFFFFFFFF00000ULL /*090*/ QWORD psw; /* Guest PSW */ /*0A0*/ DBLWRD gr14; /* Guest gr 14 */ /*0A8*/ DBLWRD gr15; /* Guest gr 15 */ /*0B0*/ DBLWRD recv0b0d; /*0B8*/ HWORD recv0b8d; /*0BA*/ BYTE xso[3]; /* Expanded storage origin */ /*0BD*/ BYTE xsl[3]; /* Expanded storage limit */ /*0C0*/ BYTE ip[52]; /* Interruption parameters */ #define SIE_IP_PSA_OFFSET 0x40 /* Offset of the IP field relative to the ipfields in the PSA for ESAME guest*/ #define SIE_II_PSA_OFFSET 0x30 /* Offset of the IP field relative to the I/O fields in the PSA for ESAME guest*/ /*0F4*/ BYTE resv0f4b[6]; /*0FA*/ HWORD ief; /* Migration Emulation cnlt */ /*0FC*/ FWORD resv0fcf; /*100*/ DBLWRD cr[16]; /* Control registers */ /*180*/ BYTE resv180b[128]; } SIE2BK; #define SIE_VI_WHO_LVLM 0xF0 /* Mask for "source level" field: If non-zero, this is the inter- pretive-execution depth at which the problem was originally detected. It is set to 1 (or 2 for Interpreted SIE) by the entity (hardware or vSIE software) that reports the problem, and is incremented (to a max of 15) by every level of vSIE that passes the interception along. */ #define SIE_VI_WHO_LVL1 0x10 /* Condition recognized one level down in interpretive execution */ #define SIE_VI_WHO_LVLMX 0xF0 /* Maximum source level reported */ #define SIE_VI_WHO_INITM 0x0F /* Mask for "initiator" field, identifying the type of entity that detected the problem. */ #define SIE_VI_WHO_CPU 0x01 /* Initiator was a CPU */ #define SIE_VI_WHO_VSIE 0x08 /* Initiator was vSIE software */ #define SIE_VI_WHEN_RECPM 0xF0 /* Mask for "recognition point" field the normal processing that recognized the condition necessitating the validity interception. */ #define SIE_VI_WHEN_SIENT 0x10 /* Condition recognized during SIE entry */ #define SIE_VI_WHEN_INST 0x20 /* Condition recognized during instruction interpretation */ #define SIE_VI_WHEN_IRPT 0x30 /* Condition recognized during interruption interpretation */ #define SIE_VI_WHEN_SIEXT 0x40 /* Condition recognized during SIE exit */ #define SIE_VI_WHY_MODE 0x0001 /* Invalid guest mode or invalid combination of modes */ #define SIE_VI_WHY_ARCHM 0x0002 /* Invalid architecture mode specified (neither or both S/370 and ESA/390) */ #define SIE_VI_WHY_370NI 0x0003 /* S/370 interpretation requested but not installed */ #define SIE_VI_WHY_PRMCS 0x0004 /* Preferred and MCDS modes specified together */ #define SIE_VI_WHY_MCS37 0x0005 /* MCDS and S/370 modes specified together */ #define SIE_VI_WHY_RRFNI 0x0006 /* RRF requested but not installed */ #define SIE_VI_WHY_ISINI 0x0007 /* iSIE requested but not installed */ #define SIE_VI_WHY_PFOUT 0x0010 /* Guest prefix outside guest extent */ #define SIE_VI_WHY_SCHPF 0x0011 /* SCA origin nonzero and its frame address matches host prefix reg */ #define SIE_VI_WHY_SDOVL 0x0030 /* State description overlaps guest storage */ #define SIE_VI_WHY_SCOVL 0x0031 /* SCA overlaps guest storage */ #define SIE_VI_WHY_APOVL 0x0032 /* APCB overlaps guest storage */ #define SIE_VI_WHY_SCADR 0x0034 /* SCA at invalid host address */ #define SIE_VI_WHY_APADR 0x0035 /* APCB at invalid host address */ #define SIE_VI_WHY_PFACC 0x0037 /* Access exception on guest prefix area */ #define SIE_VI_WHY_SCZER 0x0038 /* SCA origin nonzero but under 4K (8K for ESAME host) */ #define SIE_VI_WHY_APZER 0x0039 /* APCB origin is zero when an APCB is needed */ #define SIE_VI_WHY_PSADR 0x003A /* PGSTE at invalid host address */ #define SIE_VI_WHY_SCBDY 0x003B /* SCA crosses 4KB boundary */ #define SIE_VI_WHY_APBDY 0x003C /* APCB crosses 4KB boundary */ #define SIE_VI_WHY_MSLEX 0x003D /* MSL exceeds maximum host address supported for guest storage (ESAME SIE only) */ #define SIE_VI_WHY_MSDEF 0x0041 /* MSO exceeds MSL (ESAME SIE only) */ #define SIE_VI_WHY_MSDF2 0x0042 /* Alternate for MSDEF detected during guest prefix access */ #define SIE_VI_WHY_RRHPF 0x0046 /* RRF guest extent (zone) includes host prefix area */ #define SIE_VI_WHY_PRHPF 0x0050 /* Preferred guest extent includes host prefix area */ #define SIE_VI_WHY_MSONZ 0x0051 /* MSO not zero for preferred guest */ #define SIE_VI_WHY_CDXNI 0x0070 /* Crypto Domain Index not installed */ #define SIE_VI_WHY_DRFNI 0x1001 /* DRF requested but not installed */ #define SIE_VI_WHY_PRALE 0x1002 /* Alerting enabled for preferred non-DRF guest */ #define SIE_VI_WHY_AZNNI 0x1005 /* Zone identified by AZN is not installed */ #define SIE_VI_WHY_AZNNZ 0x1006 /* Nonzero AZN for non-RRF/DRF guest (or level-1 DSC nonzero for pageable guest) */ /* The following occur only under ESA/390 SIE: */ #define SIE_VI_WHY_MSSTL 0x0043 /* Guest extent exceeds host STL */ #define SIE_VI_WHY_HOSTF 0x0060 /* Invalid host translation format (CR0.8-12) */ #define SIE_VI_WHY_MSOFL 0x0061 /* Pageable guest extent exceeds 2G-1 */ #define SIE_VI_WHY_RCOFL 0x0062 /* RCP area extends beyond 2G-1 in host virtual */ #define SIE_VI_WHY_RCSTL 0x0063 /* RCP area exceeds host STL */ #define SIE_VI_WHY_SCOFL 0x0064 /* SCA extends beyond 2G-1 */ #define SIE_VI_WHY_APOFL 0x0065 /* APCB extends beyond 2G-1 */ #define SIE_VI_WHY_RCZER 0x0067 /* RCP area origin is zero */ #define SIE_VI_WHY_PFSTL 0x0068 /* Guest prefix exceeds host STL */ #define SIE_VI_WHY_PTBDY 0x0069 /* PTO/PGST not on 2K boundary */ #define SIE_VI_WHY_MSODS 0x006A /* MSO nonzero for MCDS guest */ #define SIE_VI_WHY_SNOVL 0x1009 /* SNT overlaps guest storage */ #define SIE_VI_WHY_SNHPF 0x100C /* SNT overlaps host prefix area */ /* The following occur only in virtual machines under VM/ESA: */ #define SIE_VI_WHY_PFRDO 0xF000 /* Guest prefix maps to read-only storage (e.g. in a DCSS) */ #define SIE_VI_WHY_SCRDO 0xF001 /* SCA in read-only storage */ #define SIE_VI_WHY_OBMSB 0xF003 /* MSO/MSE not multiple of 1Meg... ..not supported in ESAME gen */ /* Zone Parameter Block */ typedef struct _ZPB1 { FWORD mso; /* Main Storage Origin bits 0-15 must be 0 */ FWORD msl; /* Main Storage Limit bits 0-15 must be 0 */ FWORD eso; /* Expanded Storage Origin bits 0-7 must be 0 */ FWORD esl; /* Expanded Storage Limit bits 0-7 must be 0 */ FWORD res[4]; /* Reserved bits - must be 0 */ } ZPB1; typedef struct _ZPB2 { DBLWRD mso; /* Main Storage Origin bits 0-19 must be 0 */ DBLWRD msl; /* Main Storage Limit bits 0-19 must be 0 */ #define ZPB2_MS_VALID 0x00000FFFFFFFFFFFULL DBLWRD eso; /* Expanded Storage Origin bits 0-7 must be 0 */ DBLWRD esl; /* Expanded Storage Limit bits 0-7 must be 0 */ #define ZPB2_ES_VALID 0x00FFFFFFFFFFFFFFULL } ZPB2; #define LKPG_GPR0_LOCKBIT 0x00000200 #define LKPG_GPR0_RESV 0x0000FD00 #define STSI_GPR0_FC_MASK 0xF0000000 #define STSI_GPR0_FC_CURRNUM 0x00000000 #define STSI_GPR0_FC_BASIC 0x10000000 #define STSI_GPR0_FC_LPAR 0x20000000 #define STSI_GPR0_FC_VM 0x30000000 #define STSI_GPR0_FC_CURRINFO 0xF0000000 #define STSI_GPR0_SEL1_MASK 0x000000FF #define STSI_GPR0_RESERVED 0x0FFFFF00 #define STSI_GPR1_SEL2_MASK 0x0000FFFF #define STSI_GPR1_RESERVED 0xFFFF0000 typedef struct _SYSIB111 { /* Basic Machine Config */ BYTE flag1; /* 1.1.1 SYSIB Flag */ #define SYSIB111_PFLAG 0x80 /* Type percentage present */ BYTE resv1[3]; /* Reserved */ FWORD resv2[7]; /* Reserved */ BYTE manufact[16]; /* Manufacturer */ BYTE type[4]; /* Type */ FWORD resv3[3]; /* Reserved */ BYTE modcapaid[16]; /* Model capacity identifier */ BYTE seqc[16]; /* Sequence Code */ BYTE plant[4]; /* Plant of manufacture */ BYTE model[16]; /* System Model */ BYTE mpci[16]; /* Model Perm Capacity ID */ BYTE mtci[16]; /* Model Temp Capacity ID */ FWORD mcaprating; /* Model Capacity Rating */ FWORD mpcaprating; /* Model Perm Capacity Rating*/ FWORD mtcaprating; /* Model temp Capacity Rating*/ BYTE typepct[5]; /* Secondary CPU types pct */ } SYSIB111; typedef struct _SYSIB121 { /* Basic Machine CPU */ FWORD resv1[20]; /* Reserved */ BYTE seqc[16]; /* Sequence Code */ BYTE plant[4]; /* Plant of manufacture */ HWORD resv2; /* Reserved */ HWORD cpuad; /* CPU address */ } SYSIB121; typedef struct _SYSIB122 { /* Basic Machine CPUs */ BYTE format; /* Format 0 or 1 */ BYTE resv1; /* Reserved */ HWORD accoff; /* Offset to accap field */ FWORD resv2[6]; /* Reserved */ FWORD sccap; /* Secondary CPU Capability */ FWORD cap; /* CPU capability */ HWORD totcpu; /* Total CPU count */ HWORD confcpu; /* Configured CPU count */ HWORD sbcpu; /* Standby CPU count */ HWORD resvcpu; /* Reserved CPU count */ HWORD mpfact[MAX_CPU_ENGINES-1]; /* MP factors */ #if ((MAX_CPU_ENGINES-1) % 2) /* if prev is odd #of HWORDs */ HWORD resv3; /* then need some alignment */ #endif FWORD accap; /* Alternate CPU Capability */ HWORD ampfact[MAX_CPU_ENGINES-1]; /* Alternate MP factors */ #if ((MAX_CPU_ENGINES-1) % 2) /* if prev is odd #of HWORDs */ HWORD resv4; /* then need some alignment */ #endif } SYSIB122; typedef struct _SYSIB221 { /* Logical partition CPU */ FWORD resv1[20]; /* Reserved */ BYTE seqc[16]; /* Logical CPU Sequence Code */ BYTE plant[4]; /* Plant of manufacture */ HWORD lcpuid; /* Logical CPU ID */ HWORD cpuad; /* CPU address */ } SYSIB221; typedef struct _SYSIB222 { /* Logical partition CPUs */ FWORD resv1[8]; /* Reserved */ HWORD lparnum; /* LPAR number */ BYTE resv2; /* Reserved */ BYTE lcpuc; /* Logical CPU characteristic*/ #define SYSIB222_LCPUC_DEDICATED 0x80 #define SYSIB222_LCPUC_SHARED 0x40 #define SYSIB222_LCPUC_CAPPED 0x20 HWORD totcpu; /* Total CPU count */ HWORD confcpu; /* Configured CPU count */ HWORD sbcpu; /* Standby CPU count */ HWORD resvcpu; /* Reserved CPU count */ BYTE lparname[8]; /* LPAR name */ FWORD lparcaf; /* LPAR capability adjustment*/ FWORD mdep[2]; /* Model Dependent */ FWORD resv3[2]; /* Reserved */ HWORD dedcpu; /* Dedicated CPU count */ HWORD shrcpu; /* Shared CPU count */ } SYSIB222; typedef struct _SYSIB322 { /* Virtual Machines CPUs */ BYTE resv1[4*7]; /* Reserved */ BYTE resv2[3*1]; /* Reserved */ BYTE dbct; /* Four bit desc block count */ BYTE vmdb[4*16]; /* Virtual Machine desc block*/ } SYSIB322; typedef struct _SYSIB1512 { /* Configuration Topology */ HWORD resv1; /* Reserved */ HWORD len; /* Length */ BYTE mag[6]; /* Magnitudes 6, 5, ... 1 */ BYTE resv2; /* Reserved */ BYTE mnest; /* Nesting Level */ FWORD resv3; /* Reserved */ BYTE tles[FLEXIBLE_ARRAY]; /* Topology List Entries */ } SYSIB1512; typedef struct _TLECNTNR { /* Container TLE */ BYTE nl; /* Nesting Level */ BYTE resv1[3]; /* Reserved */ BYTE resv2; /* Reserved */ BYTE resv3[2]; /* Reserved */ BYTE cntnrid; /* Container Id */ } TLECNTNR; typedef struct _TLECPU { /* CPU TLE */ BYTE nl; /* Nesting Level */ BYTE resv1[3]; /* Reserved */ BYTE flags; /* Flags */ BYTE cputype; /* CPU Type */ U16 cpuadorg; /* CPU Address Origin */ DW cpumask; /* CPU Mask */ } TLECPU; #define CPUTLE_FLAG_RESERVED 0xF8 #define CPUTLE_FLAG_DEDICATED 0x04 #define CPUTLE_FLAG_VPOLARMASK 0x03 typedef struct _SYSIBVMDB { /* Virtual Machine Desc Block*/ BYTE resv1[4*1]; /* Reserved */ HWORD totcpu; /* Total CPU count */ HWORD confcpu; /* Configured CPU count */ HWORD sbcpu; /* Standby CPU count */ HWORD resvcpu; /* Reserved CPU count */ BYTE vmname[8]; /* VM userid */ FWORD vmcaf; /* VM capability adjustment */ BYTE cpid[4*4]; /* Control Program ID */ } SYSIBVMDB; #define PTFF_GPR0_RESV 0x00000080 #define PTFF_GPR0_FC_MASK 0x0000007F #define PTFF_GPR0_FC_QAF 0x00 #define PTFF_GPR0_FC_QTO 0x01 #define PTFF_GPR0_FC_QSI 0x02 #define PTFF_GPR0_FC_QPT 0x03 #define PTFF_GPR0_FC_ATO 0x40 #define PTFF_GPR0_FC_STO 0x41 #define PTFF_GPR0_FC_SFS 0x42 #define PTFF_GPR0_FC_SGS 0x43 typedef struct _PTFFQAF { /* Query Available Functions */ FWORD sb[4]; /* Status Bits words */ } PTFFQAF; typedef struct _PTFFQTO { /* Query TOD Offset */ DBLWRD physclk; /* Physical Clock */ DBLWRD todoff; /* TOD Offset */ DBLWRD ltodoff; /* Logical TOD Offset */ DBLWRD todepoch; /* TOD Epoch Difference */ } PTFFQTO; typedef struct _PTFFQSI { /* Query Steering Information*/ DBLWRD physclk; /* Physical Clock */ DBLWRD oldestart; /* Old Episode Start Time */ DBLWRD oldebase; /* Old Episode Base Offset */ FWORD oldfsr; /* Old Episode Fine St. Rate */ FWORD oldgsr; /* Old Episode Gross St. Rate*/ DBLWRD newestart; /* New Episode Start Time */ DBLWRD newebase; /* New Episode Base Offset */ FWORD newfsr; /* New Episode Fine St. Rate */ FWORD newgsr; /* New Episode Gross St. Rate*/ } PTFFQSI; #define SIGA_FC_W 0 /* Initiate Output */ #define SIGA_FC_R 1 /* Initiate Input */ #define SIGA_FC_S 2 /* Synchronize */ #define SIGA_FC_MAX SIGA_FC_S /* Bit definitions for floating-point-control register */ #define FPC_MASK 0xF8000000 #define FPC_MASK_IMI 0x80000000 #define FPC_MASK_IMZ 0x40000000 #define FPC_MASK_IMO 0x20000000 #define FPC_MASK_IMU 0x10000000 #define FPC_MASK_IMX 0x08000000 #define FPC_FLAG 0x00F80000 #define FPC_FLAG_SFI 0x00800000 #define FPC_FLAG_SFZ 0x00400000 #define FPC_FLAG_SFO 0x00200000 #define FPC_FLAG_SFU 0x00100000 #define FPC_FLAG_SFX 0x00080000 #define FPC_DXC 0x0000FF00 #define FPC_DXC_I 0x00008000 #define FPC_DXC_Z 0x00004000 #define FPC_DXC_O 0x00002000 #define FPC_DXC_U 0x00001000 #define FPC_DXC_X 0x00000800 #define FPC_DXC_Y 0x00000400 #define FPC_DRM 0x00000070 #define FPC_BRM 0x00000003 #define FPC_RESERVED 0x0707008C /* Shift counts to allow alignment of each field in the FPC register */ #define FPC_MASK_SHIFT 27 #define FPC_FLAG_SHIFT 19 #define FPC_DXC_SHIFT 8 #define FPC_DRM_SHIFT 4 #define FPC_BRM_SHIFT 0 /* Data exception codes */ #define DXC_DECIMAL 0x00 /* Decimal operand exception */ #define DXC_AFP_REGISTER 0x01 /* AFP register exception */ #define DXC_BFP_INSTRUCTION 0x02 /* BFP instruction exception */ #define DXC_DFP_INSTRUCTION 0x03 /* DFP instruction exception */ #define DXC_IEEE_INEXACT_TRUNC 0x08 /* IEEE inexact, truncated */ #define DXC_IEEE_INEXACT_IISE 0x0B /* IEEE inexact (IISE) DFP*/ #define DXC_IEEE_INEXACT_INCR 0x0C /* IEEE inexact, incremented */ #define DXC_IEEE_UF_EXACT 0x10 /* IEEE underflow. exact */ #define DXC_IEEE_UF_EXACT_IISE 0x13 /* IEEE u/flow,exact(IISE)DFP*/ #define DXC_IEEE_UF_INEX_TRUNC 0x18 /* IEEE u/flow,inexact,trunc */ #define DXC_IEEE_UF_INEX_IISE 0x1B /* IEEE u/flow,inex(IISE) DFP*/ #define DXC_IEEE_UF_INEX_INCR 0x1C /* IEEE u/flow,inexact,incr */ #define DXC_IEEE_OF_EXACT 0x20 /* IEEE overflow. exact */ #define DXC_IEEE_OF_EXACT_IISE 0x23 /* IEEE o/flow,exact(IISE)DFP*/ #define DXC_IEEE_OF_INEX_TRUNC 0x28 /* IEEE o/flow,inexact,trunc */ #define DXC_IEEE_OF_INEX_IISE 0x2B /* IEEE o/flow,inex(IISE) DFP*/ #define DXC_IEEE_OF_INEX_INCR 0x2C /* IEEE o/flow,inexact,incr */ #define DXC_IEEE_DIV_ZERO 0x40 /* IEEE division by zero */ #define DXC_IEEE_DIV_ZERO_IISE 0x43 /* IEEE div by zero(IISE) DFP*/ #define DXC_IEEE_INVALID_OP 0x80 /* IEEE invalid operation */ #define DXC_IEEE_INV_OP_IISE 0x83 /* IEEE invalid op (IISE) DFP*/ #define DXC_COMPARE_AND_TRAP 0xFF /* Compare-and-trap exception*/ /* Note: IISE = IEEE-interruption-simulation event */ /* Decimal rounding modes */ #define DRM_RNE 0 /* Round to nearest tie even */ #define DRM_RTZ 1 /* Round toward zero */ #define DRM_RTPI 2 /* Round toward +infinity */ #define DRM_RTMI 3 /* Round toward -infinity */ #define DRM_RNAZ 4 /* Round nearest tie away 0 */ #define DRM_RNTZ 5 /* Round nearest tie toward 0*/ #define DRM_RAFZ 6 /* Round away from zero */ #define DRM_RFSP 7 /* Prepare shorter precision */ /* Binary rounding modes */ #define BRM_RNE 0 /* Round to nearest tie even */ #define BRM_RTZ 1 /* Round toward zero */ #define BRM_RTPI 2 /* Round toward +infinity */ #define BRM_RTMI 3 /* Round toward -infinity */ /* Mask bits for conditional SSKE facility */ #define SSKE_MASK_MR 0x04 /* Reference bit update mask */ #define SSKE_MASK_MC 0x02 /* Change bit update mask */ #endif // _ESA390_H hercules-3.07/esame.c000644 000765 000765 00001103327 11337307610 016211 0ustar00jmaynardjmaynard000000 000000 /* ESAME.C (c) Copyright Jan Jaeger, 2000-2010 */ /* ESAME (z/Architecture) instructions */ // $Id: esame.c 5633 2010-02-15 13:37:55Z jmaynard $ /*-------------------------------------------------------------------*/ /* This module implements the instructions which exist in ESAME */ /* mode but not in ESA/390 mode, as described in the manual */ /* SA22-7832-00 z/Architecture Principles of Operation */ /*-------------------------------------------------------------------*/ /*-------------------------------------------------------------------*/ /* Additional credits: */ /* EPSW/EREGG/LMD instructions - Roger Bowler */ /* PKA/PKU/UNPKA/UNPKU instructions - Roger Bowler */ /* Multiply/Divide Logical instructions - Vic Cross Feb2001*/ /* Long displacement facility - Roger Bowler June2003*/ /* DAT enhancement facility - Roger Bowler July2004*/ /* Extended immediate facility - Roger Bowler Aug2005*/ /*-------------------------------------------------------------------*/ // $Log$ // Revision 1.204 2009/01/23 11:53:18 bernard // copyright notice // // Revision 1.203 2009/01/15 17:27:02 rbowler // STFLE bit settings for CPU Measurement Facility // // Revision 1.202 2008/05/06 22:15:42 rbowler // Fix warning: operation on `p1' may be undefined // // Revision 1.201 2008/04/11 14:28:29 bernard // Integrate regs->exrl into base Hercules code. // // Revision 1.200 2008/04/09 07:36:51 bernard // Allign to Rogers terminal ;-) // // Revision 1.199 2008/04/08 23:57:15 rbowler // Fix '#' : invalid character : possibly the result of a macro expansion // // Revision 1.198 2008/04/08 17:12:47 bernard // Added execute relative long instruction // // Revision 1.197 2008/03/16 00:04:37 rbowler // Replace ACC_ARMODE by USE_ARMODE for LPTEA // // Revision 1.196 2008/03/06 16:10:35 rbowler // Remove extraneous trailing blanks (cosmetic change only) // // Revision 1.195 2008/03/01 12:19:04 rbowler // Rename new features to include the word facility // // Revision 1.194 2008/02/28 22:05:10 ptl00 // Fix RP for z/arch and mode switch trace // // Revision 1.193 2008/02/28 10:11:50 rbowler // STFL bit settings for new features in zPOP-06 // // Revision 1.192 2008/02/15 21:17:55 ptl00 // Add pic13 check to RP // // Revision 1.191 2007/11/17 21:57:52 rbowler // Correct comments on two #endif statements // // Revision 1.190 2007/11/15 21:34:01 rbowler // EPSW correction in accord with ESA/390 POP ninth edition // // Revision 1.189 2007/06/23 00:04:09 ivan // Update copyright notices to include current year (2007) // // Revision 1.188 2007/04/27 10:50:40 rbowler // STFL bit 27 for MVCOS // // Revision 1.187 2007/04/25 15:23:49 rbowler // Standardize comment format in ECTG // // Revision 1.186 2007/04/25 14:46:35 rbowler // Rename RSS instruction format as SSF // // Revision 1.185 2007/04/24 16:34:41 rbowler // Define feature macros and STFL bit settings for new features in zPOP-05 // // Revision 1.184 2007/03/21 21:35:11 gsmith // Fix LPTEA to use variable acctype for translate_addr() call // // Revision 1.183 2007/03/20 22:23:33 gsmith // Redefine ACC_ and ACCTYPE_ macros // // Revision 1.182 2007/03/10 06:27:43 gsmith // machdep.h updates // // Revision 1.181 2007/01/13 07:18:59 bernard // backout ccmask // // Revision 1.180 2007/01/12 15:23:13 bernard // ccmask phase 1 // // Revision 1.179 2007/01/09 05:10:19 gsmith // Tweaks to lm/stm // // Revision 1.178 2007/01/04 23:12:04 gsmith // remove thunk calls for program_interrupt // // Revision 1.177 2006/12/31 21:16:32 gsmith // 2006 Dec 31 really back out mainlockx.pat // // Revision 1.176 2006/12/20 09:09:40 jj // Fix bogus log entries // // Revision 1.175 2006/12/20 04:26:19 gsmith // 19 Dec 2006 ip_all.pat - performance patch - Greg Smith // // Revision 1.174 2006/12/20 04:22:00 gsmith // 2006 Dec 19 Backout mainlockx.pat - possible SMP problems - Greg Smith // // Revision 1.173 2006/12/08 09:43:20 jj // Add CVS message log // #include "hstdinc.h" #if !defined(_HENGINE_DLL_) #define _HENGINE_DLL_ #endif #if !defined(_ESAME_C_) #define _ESAME_C_ BYTE * get_stfl_data(int, int *); #endif #include "hercules.h" #include "opcode.h" #include "inline.h" #define CRYPTO_EXTERN extern #include "crypto.h" #include "clock.h" #if defined(FEATURE_BINARY_FLOATING_POINT) /*-------------------------------------------------------------------*/ /* B29C STFPC - Store FPC [S] */ /*-------------------------------------------------------------------*/ DEF_INST(store_fpc) { int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ S(inst, regs, b2, effective_addr2); BFPINST_CHECK(regs); /* Store register contents at operand address */ ARCH_DEP(vstore4) ( regs->fpc, effective_addr2, b2, regs ); } /* end DEF_INST(store_fpc) */ #endif /*defined(FEATURE_BINARY_FLOATING_POINT)*/ #if defined(FEATURE_BINARY_FLOATING_POINT) /*-------------------------------------------------------------------*/ /* B29D LFPC - Load FPC [S] */ /*-------------------------------------------------------------------*/ DEF_INST(load_fpc) { int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ U32 tmp_fpc; S(inst, regs, b2, effective_addr2); BFPINST_CHECK(regs); /* Load FPC register from operand address */ tmp_fpc = ARCH_DEP(vfetch4) (effective_addr2, b2, regs); /* Program check if reserved bits are non-zero */ FPC_CHECK(tmp_fpc, regs); /* Update FPC register */ regs->fpc = tmp_fpc; } /* end DEF_INST(load_fpc) */ #endif /*defined(FEATURE_BINARY_FLOATING_POINT)*/ #if defined(FEATURE_BINARY_FLOATING_POINT) /*-------------------------------------------------------------------*/ /* B384 SFPC - Set FPC [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(set_fpc) { int r1, unused; /* Values of R fields */ RRE(inst, regs, r1, unused); BFPINST_CHECK(regs); /* Program check if reserved bits are non-zero */ FPC_CHECK(regs->GR_L(r1), regs); /* Load FPC register from R1 register bits 32-63 */ regs->fpc = regs->GR_L(r1); } /* end DEF_INST(set_fpc) */ #endif /*defined(FEATURE_BINARY_FLOATING_POINT)*/ #if defined(FEATURE_BINARY_FLOATING_POINT) /*-------------------------------------------------------------------*/ /* B38C EFPC - Extract FPC [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(extract_fpc) { int r1, unused; /* Values of R fields */ RRE(inst, regs, r1, unused); BFPINST_CHECK(regs); /* Load R1 register bits 32-63 from FPC register */ regs->GR_L(r1) = regs->fpc; } /* end DEF_INST(extract_fpc) */ #endif /*defined(FEATURE_BINARY_FLOATING_POINT)*/ #if defined(FEATURE_BINARY_FLOATING_POINT) /*-------------------------------------------------------------------*/ /* B299 SRNM - Set BFP Rounding Mode [S] */ /*-------------------------------------------------------------------*/ DEF_INST(set_bfp_rounding_mode) { int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ S(inst, regs, b2, effective_addr2); BFPINST_CHECK(regs); /* Set FPC register BFP rounding mode bits from operand address */ regs->fpc &= ~(FPC_BRM); regs->fpc |= (effective_addr2 & FPC_BRM); } /* end DEF_INST(set_bfp_rounding_mode) */ #endif /*defined(FEATURE_BINARY_FLOATING_POINT)*/ #if defined(FEATURE_LINKAGE_STACK) /*-------------------------------------------------------------------*/ /* 01FF TRAP2 - Trap [E] */ /*-------------------------------------------------------------------*/ DEF_INST(trap2) { E(inst, regs); UNREFERENCED(inst); ARCH_DEP(trap_x) (0, regs, 0); } /* end DEF_INST(trap2) */ #endif /*defined(FEATURE_LINKAGE_STACK)*/ #if defined(FEATURE_LINKAGE_STACK) /*-------------------------------------------------------------------*/ /* B2FF TRAP4 - Trap [S] */ /*-------------------------------------------------------------------*/ DEF_INST(trap4) { int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ S(inst, regs, b2, effective_addr2); ARCH_DEP(trap_x) (1, regs, effective_addr2); } /* end DEF_INST(trap4) */ #endif /*defined(FEATURE_LINKAGE_STACK)*/ #if defined(FEATURE_RESUME_PROGRAM) /*-------------------------------------------------------------------*/ /* B277 RP - Resume Program [S] */ /*-------------------------------------------------------------------*/ DEF_INST(resume_program) { int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ VADR pl_addr; /* Address of parmlist */ U16 flags; /* Flags in parmfield */ U16 psw_offset; /* Offset to new PSW */ U16 ar_offset; /* Offset to new AR */ U16 gr_offset; /* Offset to new GR */ U32 ar; /* Copy of new AR */ U32 gr = 0; /* Copy of new GR */ #if defined(FEATURE_ESAME) U16 grd_offset = 0; /* Offset of disjoint GR_H */ BYTE psw[16]; /* Copy of new PSW */ U64 gr8 = 0; /* Copy of new GR - 8 bytes */ U32 grd = 0; /* Copy of new GR - disjoint */ U64 ia; /* ia for trace */ BYTE amode64; /* save for amod64 */ #else /*!defined(FEATURE_ESAME)*/ BYTE psw[8]; /* Copy of new PSW */ U32 ia; /* ia for trace */ #endif /*!defined(FEATURE_ESAME)*/ BYTE amode; /* amode for trace */ PSW save_psw; /* Saved copy of current PSW */ BYTE *mn; /* Mainstor address of parm */ #ifdef FEATURE_TRACING CREG newcr12 = 0; /* CR12 upon completion */ #endif /*FEATURE_TRACING*/ S(inst, regs, b2, effective_addr2); /* Determine the address of the parameter list */ pl_addr = !regs->execflag ? PSW_IA(regs, 0) : regs->exrl ? (regs->ET + 6) : (regs->ET + 4); /* Fetch flags from the instruction address space */ mn = MADDR (pl_addr, USE_INST_SPACE, regs, ACCTYPE_INSTFETCH, regs->psw.pkey); FETCH_HW(flags, mn); #if defined(FEATURE_ESAME) /* Bits 0-12 must be zero */ if(flags & 0xFFF8) #else /*!defined(FEATURE_ESAME)*/ /* All flag bits must be zero in ESA/390 mode */ if(flags) #endif /*!defined(FEATURE_ESAME)*/ regs->program_interrupt (regs, PGM_SPECIFICATION_EXCEPTION); /* Fetch the offset to the new psw */ mn = MADDR (pl_addr + 2, USE_INST_SPACE, regs, ACCTYPE_INSTFETCH, regs->psw.pkey); FETCH_HW(psw_offset, mn); /* Fetch the offset to the new ar */ mn = MADDR (pl_addr + 4, USE_INST_SPACE, regs, ACCTYPE_INSTFETCH, regs->psw.pkey); FETCH_HW(ar_offset, mn); /* Fetch the offset to the new gr */ mn = MADDR (pl_addr + 6, USE_INST_SPACE, regs, ACCTYPE_INSTFETCH, regs->psw.pkey); FETCH_HW(gr_offset, mn); #if defined(FEATURE_ESAME) /* Fetch the offset to the new disjoint gr_h */ if((flags & 0x0003) == 0x0003) { mn = MADDR (pl_addr + 8, USE_INST_SPACE, regs, ACCTYPE_INSTFETCH, regs->psw.pkey); FETCH_HW(grd_offset, mn); } #endif /*defined(FEATURE_ESAME)*/ /* Fetch the PSW from the operand address + psw offset */ #if defined(FEATURE_ESAME) if(flags & 0x0004) ARCH_DEP(vfetchc) (psw, 15, (effective_addr2 + psw_offset) & ADDRESS_MAXWRAP(regs), b2, regs); else #endif /*defined(FEATURE_ESAME)*/ ARCH_DEP(vfetchc) (psw, 7, (effective_addr2 + psw_offset) & ADDRESS_MAXWRAP(regs), b2, regs); /* Fetch new AR (B2) from operand address + AR offset */ ar = ARCH_DEP(vfetch4) ((effective_addr2 + ar_offset) & ADDRESS_MAXWRAP(regs), b2, regs); /* Fetch the new gr from operand address + GPR offset */ #if defined(FEATURE_ESAME) /* General Register Field 1 is eight bytes */ if((flags & 0x0003) == 0x0002) { gr8 = ARCH_DEP(vfetch8) ((effective_addr2 + gr_offset) & ADDRESS_MAXWRAP(regs), b2, regs); } /* General Register Field 1 and 2 are four bytes - disjoint */ else if((flags & 0x0003) == 0x0003) { gr = ARCH_DEP(vfetch4) ((effective_addr2 + gr_offset) & ADDRESS_MAXWRAP(regs), b2, regs); grd = ARCH_DEP(vfetch4) ((effective_addr2 + grd_offset) & ADDRESS_MAXWRAP(regs), b2, regs); } else #endif /*defined(FEATURE_ESAME)*/ gr = ARCH_DEP(vfetch4) ((effective_addr2 + gr_offset) & ADDRESS_MAXWRAP(regs), b2, regs); #if defined(FEATURE_TRACING) #if defined(FEATURE_ESAME) /* fetch 8 or 4 byte IA depending on psw operand size */ if (flags & 0x0004) FETCH_DW(ia, psw + 8); else FETCH_FW(ia, psw + 4); amode64 = psw[3] & 0x01; #else /*!defined(FEATURE_ESAME)*/ FETCH_FW(ia, psw + 4); ia &= 0x7FFFFFFF; #endif /*!defined(FEATURE_ESAME)*/ amode = psw[4] & 0x80; #if defined(FEATURE_ESAME) /* Add a mode trace entry when switching in/out of 64 bit mode */ if((regs->CR(12) & CR12_MTRACE) && (regs->psw.amode64 != amode64)) newcr12 = ARCH_DEP(trace_ms) (regs->CR(12) & CR12_BRTRACE ? 1 : 0, ia, regs); else #endif /*defined(FEATURE_ESAME)*/ if (regs->CR(12) & CR12_BRTRACE) newcr12 = ARCH_DEP(trace_br) (amode, ia, regs); #endif /*defined(FEATURE_TRACING)*/ INVALIDATE_AIA(regs); /* Save current PSW */ save_psw = regs->psw; /* Use bytes 0 and 1 of old psw and byte 2 from operand */ psw[0] = save_psw.sysmask; psw[1] = save_psw.pkey | save_psw.states; /* ignore bits 24-30 */ psw[3] = 0x01 & psw[3]; #if defined(FEATURE_MULTIPLE_CONTROLLED_DATA_SPACE) if(SIE_STATB(regs, MX, XC) && (psw[2] & 0x80)) regs->program_interrupt (regs, PGM_SPECIAL_OPERATION_EXCEPTION); #endif /*defined(FEATURE_MULTIPLE_CONTROLLED_DATA_SPACE)*/ /* Special operation exception when setting AR space mode and ASF is off */ if(!REAL_MODE(®s->psw) && ((psw[2] & 0xC0) == 0x40) && !ASF_ENABLED(regs) ) regs->program_interrupt (regs, PGM_SPECIAL_OPERATION_EXCEPTION); /* Privileged Operation exception when setting home space mode in problem state */ if(!REAL_MODE(®s->psw) && PROBSTATE(®s->psw) && ((psw[2] & 0xC0) == 0xC0) ) regs->program_interrupt (regs, PGM_PRIVILEGED_OPERATION_EXCEPTION); #if defined(FEATURE_ESAME) /* Handle 16 byte psw operand */ if(flags & 0x0004) { psw[1] &= ~0x08; /* force bit 12 off */ if( ARCH_DEP(load_psw) (regs, psw) )/* only check invalid IA not odd */ { /* restore the psw */ regs->psw = save_psw; /* And generate a program interrupt */ regs->program_interrupt (regs, PGM_SPECIFICATION_EXCEPTION); } } /* Handle 8 byte psw operand */ else { /* Save amode64, do not check amode64 bit (force to zero) */ /* This is so s390_load_psw will work. */ /* Checks for amode64 will be done a few lines later */ amode64 = psw[3] & 01; psw[3] &= ~0x01; #endif /*defined(FEATURE_ESAME)*/ psw[1] |= 0x08; /* force bit 12 on */ if( s390_load_psw(regs, psw) ) { /* restore the psw */ regs->psw = save_psw; /* And generate a program interrupt */ regs->program_interrupt (regs, PGM_SPECIFICATION_EXCEPTION); } #if defined(FEATURE_ESAME) regs->psw.states &= ~BIT(PSW_NOTESAME_BIT); /* clear high word of IA since operand was 8-byte psw */ regs->psw.IA_H = 0; /* Check original amode64 and restore and do checks */ if (amode64) { /* if amode64 (31) on, then amode (32) must be on too */ if (!regs->psw.amode) { /* restore the psw */ regs->psw = save_psw; /* And generate a program interrupt */ regs->program_interrupt (regs, PGM_SPECIFICATION_EXCEPTION); } regs->psw.amode64 = 1; regs->psw.AMASK = AMASK64; } else { regs->psw.amode64 = 0; regs->psw.AMASK_H = 0; } } #endif /*defined(FEATURE_ESAME)*/ /* Check for odd IA in psw */ if(regs->psw.IA & 0x01) { /* restore the psw */ regs->psw = save_psw; /* And generate a program interrupt */ regs->program_interrupt (regs, PGM_SPECIFICATION_EXCEPTION); } /* Update access register b2 */ regs->AR(b2) = ar; /* Update general register b2 */ #if defined(FEATURE_ESAME) if((flags & 0x0003) == 0x0002) regs->GR_G(b2) = gr8; else if((flags & 0x0003) == 0x0003) { regs->GR_L(b2) = gr; regs->GR_H(b2) = grd; } else #endif /*defined(FEATURE_ESAME)*/ regs->GR_L(b2) = gr; #ifdef FEATURE_TRACING /* Update trace table address if branch tracing is on */ if (newcr12) regs->CR(12) = newcr12; #endif /*FEATURE_TRACING*/ SET_BEAR_REG(regs, regs->ip - 4); SET_IC_ECMODE_MASK(regs); SET_AEA_MODE(regs); PER_SB(regs, regs->psw.IA); /* Space switch event when switching into or out of home space mode AND space-switch-event on in CR1 or CR13 */ if((HOME_SPACE_MODE(&(regs->psw)) ^ HOME_SPACE_MODE(&save_psw)) && (!REAL_MODE(®s->psw)) && ((regs->CR(1) & SSEVENT_BIT) || (regs->CR(13) & SSEVENT_BIT) || OPEN_IC_PER(regs) )) { if (HOME_SPACE_MODE(&(regs->psw))) { /* When switching into home-space mode, set the translation exception address equal to the primary ASN, with the high-order bit set equal to the value of the primary space-switch-event control bit */ regs->TEA = regs->CR_LHL(4); if (regs->CR(1) & SSEVENT_BIT) regs->TEA |= TEA_SSEVENT; } else { /* When switching out of home-space mode, set the translation exception address equal to zero, with the high-order bit set equal to the value of the home space-switch-event control bit */ regs->TEA = 0; if (regs->CR(13) & SSEVENT_BIT) regs->TEA |= TEA_SSEVENT; } regs->program_interrupt (regs, PGM_SPACE_SWITCH_EVENT); } RETURN_INTCHECK(regs); } /* end DEF_INST(resume_program) */ #endif /*defined(FEATURE_RESUME_PROGRAM)*/ #if defined(FEATURE_ESAME) && defined(FEATURE_TRACING) /*-------------------------------------------------------------------*/ /* EB0F TRACG - Trace Long [RSY] */ /*-------------------------------------------------------------------*/ DEF_INST(trace_long) { int r1, r3; /* Register numbers */ int b2; /* effective address base */ VADR effective_addr2; /* effective address */ #if defined(FEATURE_TRACING) U32 op; /* Operand */ #endif /*defined(FEATURE_TRACING)*/ RSY(inst, regs, r1, r3, b2, effective_addr2); PRIV_CHECK(regs); FW_CHECK(effective_addr2, regs); /* Exit if explicit tracing (control reg 12 bit 31) is off */ if ( (regs->CR(12) & CR12_EXTRACE) == 0 ) return; /* Fetch the trace operand */ op = ARCH_DEP(vfetch4) ( effective_addr2, b2, regs ); /* Exit if bit zero of the trace operand is one */ if ( (op & 0x80000000) ) return; /* Perform serialization and checkpoint-synchronization */ PERFORM_SERIALIZATION (regs); PERFORM_CHKPT_SYNC (regs); regs->CR(12) = ARCH_DEP(trace_tg) (r1, r3, op, regs); /* Perform serialization and checkpoint-synchronization */ PERFORM_SERIALIZATION (regs); PERFORM_CHKPT_SYNC (regs); } /* end DEF_INST(trace_long) */ #endif /*defined(FEATURE_ESAME) && defined(FEATURE_TRACING)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* E30E CVBG - Convert to Binary Long [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(convert_to_binary_long) { U64 dreg; /* 64-bit result accumulator */ int r1; /* Value of R1 field */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ int ovf; /* 1=overflow */ int dxf; /* 1=data exception */ BYTE dec[16]; /* Packed decimal operand */ RXY(inst, regs, r1, b2, effective_addr2); /* Fetch 16-byte packed decimal operand */ ARCH_DEP(vfetchc) ( dec, 16-1, effective_addr2, b2, regs ); /* Convert 16-byte packed decimal to 64-bit signed binary */ packed_to_binary (dec, 16-1, &dreg, &ovf, &dxf); /* Data exception if invalid digits or sign */ if (dxf) { regs->dxc = DXC_DECIMAL; regs->program_interrupt (regs, PGM_DATA_EXCEPTION); } /* Exception if overflow (operation suppressed, R1 unchanged) */ if (ovf) regs->program_interrupt (regs, PGM_FIXED_POINT_DIVIDE_EXCEPTION); /* Store 64-bit result into R1 register */ regs->GR_G(r1) = dreg; } /* end DEF_INST(convert_to_binary_long) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* E32E CVDG - Convert to Decimal Long [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(convert_to_decimal_long) { S64 bin; /* Signed value to convert */ int r1; /* Value of R1 field */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ BYTE dec[16]; /* Packed decimal result */ RXY(inst, regs, r1, b2, effective_addr2); /* Load signed value of register */ bin = (S64)(regs->GR_G(r1)); /* Convert to 16-byte packed decimal number */ binary_to_packed (bin, dec); /* Store 16-byte packed decimal result at operand address */ ARCH_DEP(vstorec) ( dec, 16-1, effective_addr2, b2, regs ); } /* end DEF_INST(convert_to_decimal_long) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* E396 ML - Multiply Logical [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(multiply_logical) { int r1; /* Values of R fields */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective Address */ U32 m; U64 p; RXY(inst, regs, r1, b2, effective_addr2); ODD_CHECK(r1, regs); /* Load second operand from operand address */ m = ARCH_DEP(vfetch4) (effective_addr2, b2, regs); /* Multiply unsigned values */ p = (U64)regs->GR_L(r1 + 1) * m; /* Store the result */ regs->GR_L(r1) = (p >> 32); regs->GR_L(r1 + 1) = (p & 0xFFFFFFFF); } /* end DEF_INST(multiply_logical) */ #endif /*defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* E386 MLG - Multiply Logical Long [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(multiply_logical_long) { int r1; /* Values of R fields */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective Address */ U64 m, ph, pl; RXY(inst, regs, r1, b2, effective_addr2); ODD_CHECK(r1, regs); /* Load second operand from operand address */ m = ARCH_DEP(vfetch8) (effective_addr2, b2, regs); /* Multiply unsigned values */ mult_logical_long(&ph, &pl, regs->GR_G(r1 + 1), m); /* Store the result */ regs->GR_G(r1) = ph; regs->GR_G(r1 + 1) = pl; } /* end DEF_INST(multiply_logical_long) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* B996 MLR - Multiply Logical Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(multiply_logical_register) { int r1, r2; /* Values of R fields */ U64 p; RRE(inst, regs, r1, r2); ODD_CHECK(r1, regs); /* Multiply unsigned values */ p = (U64)regs->GR_L(r1 + 1) * (U64)regs->GR_L(r2); /* Store the result */ regs->GR_L(r1) = (p >> 32); regs->GR_L(r1 + 1) = (p & 0xFFFFFFFF); } /* end DEF_INST(multiply_logical_register) */ #endif /*defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* B986 MLGR - Multiply Logical Long Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(multiply_logical_long_register) { int r1, r2; /* Values of R fields */ U64 ph, pl; RRE(inst, regs, r1, r2); ODD_CHECK(r1, regs); /* Multiply unsigned values */ mult_logical_long(&ph, &pl, regs->GR_G(r1 + 1), regs->GR_G(r2)); /* Store the result */ regs->GR_G(r1) = ph; regs->GR_G(r1 + 1) = pl; } /* end DEF_INST(multiply_logical_long_register) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* E397 DL - Divide Logical [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(divide_logical) { int r1; /* Values of R fields */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective Address */ U32 d; U64 n; RXY(inst, regs, r1, b2, effective_addr2); ODD_CHECK(r1, regs); n = ((U64)regs->GR_L(r1) << 32) | (U32)regs->GR_L(r1 + 1); /* Load second operand from operand address */ d = ARCH_DEP(vfetch4) (effective_addr2, b2, regs); if (d == 0 || (n / d) > 0xFFFFFFFF) regs->program_interrupt (regs, PGM_FIXED_POINT_DIVIDE_EXCEPTION); /* Divide unsigned registers */ regs->GR_L(r1) = n % d; regs->GR_L(r1 + 1) = n / d; } /* end DEF_INST(divide_logical) */ #endif /*defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* E387 DLG - Divide Logical Long [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(divide_logical_long) { int r1; /* Values of R fields */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective Address */ U64 d, r, q; RXY(inst, regs, r1, b2, effective_addr2); ODD_CHECK(r1, regs); /* Load second operand from operand address */ d = ARCH_DEP(vfetch8) (effective_addr2, b2, regs); if (regs->GR_G(r1) == 0) /* check for the simple case */ { if (d == 0) regs->program_interrupt (regs, PGM_FIXED_POINT_DIVIDE_EXCEPTION); /* Divide signed registers */ regs->GR_G(r1) = regs->GR_G(r1 + 1) % d; regs->GR_G(r1 + 1) = regs->GR_G(r1 + 1) / d; } else { if (div_logical_long(&r, &q, regs->GR_G(r1), regs->GR_G(r1 + 1), d) ) regs->program_interrupt (regs, PGM_FIXED_POINT_DIVIDE_EXCEPTION); else { regs->GR_G(r1) = r; regs->GR_G(r1 + 1) = q; } } } /* end DEF_INST(divide_logical_long) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* B997 DLR - Divide Logical Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(divide_logical_register) { int r1, r2; /* Values of R fields */ U64 n; U32 d; RRE(inst, regs, r1, r2); ODD_CHECK(r1, regs); n = ((U64)regs->GR_L(r1) << 32) | regs->GR_L(r1 + 1); d = regs->GR_L(r2); if(d == 0 || (n / d) > 0xFFFFFFFF) regs->program_interrupt (regs, PGM_FIXED_POINT_DIVIDE_EXCEPTION); /* Divide signed registers */ regs->GR_L(r1) = n % d; regs->GR_L(r1 + 1) = n / d; } /* end DEF_INST(divide_logical_register) */ #endif /*defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* B987 DLGR - Divide Logical Long Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(divide_logical_long_register) { int r1, r2; /* Values of R fields */ U64 r, q, d; RRE(inst, regs, r1, r2); ODD_CHECK(r1, regs); d = regs->GR_G(r2); if (regs->GR_G(r1) == 0) /* check for the simple case */ { if(d == 0) regs->program_interrupt (regs, PGM_FIXED_POINT_DIVIDE_EXCEPTION); /* Divide signed registers */ regs->GR_G(r1) = regs->GR_G(r1 + 1) % d; regs->GR_G(r1 + 1) = regs->GR_G(r1 + 1) / d; } else { if (div_logical_long(&r, &q, regs->GR_G(r1), regs->GR_G(r1 + 1), d) ) regs->program_interrupt (regs, PGM_FIXED_POINT_DIVIDE_EXCEPTION); else { regs->GR_G(r1) = r; regs->GR_G(r1 + 1) = q; } } } /* end DEF_INST(divide_logical_long_register) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* B988 ALCGR - Add Logical with Carry Long Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(add_logical_carry_long_register) { int r1, r2; /* Values of R fields */ int carry = 0; U64 n; RRE0(inst, regs, r1, r2); n = regs->GR_G(r2); /* Add the carry to operand */ if(regs->psw.cc & 2) carry = add_logical_long(&(regs->GR_G(r1)), regs->GR_G(r1), 1) & 2; /* Add unsigned operands and set condition code */ regs->psw.cc = add_logical_long(&(regs->GR_G(r1)), regs->GR_G(r1), n) | carry; } /* end DEF_INST(add_logical_carry_long_register) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* B989 SLBGR - Subtract Logical with Borrow Long Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(subtract_logical_borrow_long_register) { int r1, r2; /* Values of R fields */ int borrow = 2; U64 n; RRE0(inst, regs, r1, r2); n = regs->GR_G(r2); /* Subtract the borrow from operand */ if(!(regs->psw.cc & 2)) borrow = sub_logical_long(&(regs->GR_G(r1)), regs->GR_G(r1), 1); /* Subtract unsigned operands and set condition code */ regs->psw.cc = sub_logical_long(&(regs->GR_G(r1)), regs->GR_G(r1), n) & (borrow|1); } /* end DEF_INST(subtract_logical_borrow_long_register) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_DAT_ENHANCEMENT) /*-------------------------------------------------------------------*/ /* B98A CSPG - Compare and Swap and Purge Long [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_and_swap_and_purge_long) { int r1, r2; /* Values of R fields */ U64 n2; /* Virtual address of op2 */ BYTE *main2; /* Mainstor address of op2 */ U64 old; /* Old value */ RRE(inst, regs, r1, r2); PRIV_CHECK(regs); ODD_CHECK(r1, regs); #if defined(_FEATURE_SIE) if(SIE_STATB(regs,IC0, IPTECSP)) longjmp(regs->progjmp, SIE_INTERCEPT_INST); #endif /*defined(_FEATURE_SIE)*/ #if defined(_FEATURE_SIE) if(SIE_MODE(regs) && regs->sie_scao) { STORAGE_KEY(regs->sie_scao, regs) |= STORKEY_REF; if(regs->mainstor[regs->sie_scao] & 0x80) longjmp(regs->progjmp, SIE_INTERCEPT_INST); } #endif /*defined(_FEATURE_SIE)*/ /* Perform serialization before starting operation */ PERFORM_SERIALIZATION (regs); /* Obtain 2nd operand address from r2 */ n2 = regs->GR(r2) & 0xFFFFFFFFFFFFFFF8ULL & ADDRESS_MAXWRAP(regs); main2 = MADDR (n2, r2, regs, ACCTYPE_WRITE, regs->psw.pkey); old = CSWAP64 (regs->GR_G(r1)); /* Obtain main-storage access lock */ OBTAIN_MAINLOCK(regs); /* Attempt to exchange the values */ regs->psw.cc = cmpxchg8 (&old, CSWAP64(regs->GR_G(r1+1)), main2); /* Release main-storage access lock */ RELEASE_MAINLOCK(regs); if (regs->psw.cc == 0) { /* Perform requested funtion specified as per request code in r2 */ if (regs->GR_L(r2) & 3) { OBTAIN_INTLOCK(regs); SYNCHRONIZE_CPUS(regs); if (regs->GR_L(r2) & 1) ARCH_DEP(purge_tlb_all)(); if (regs->GR_L(r2) & 2) ARCH_DEP(purge_alb_all)(); RELEASE_INTLOCK(regs); } } else { PTT(PTT_CL_CSF,"*CSPG",regs->GR_L(r1),regs->GR_L(r2),regs->psw.IA_L); /* Otherwise yield */ regs->GR_G(r1) = CSWAP64(old); if (sysblk.cpus > 1) sched_yield(); } /* Perform serialization after completing operation */ PERFORM_SERIALIZATION (regs); } /* end DEF_INST(compare_and_swap_and_purge_long) */ #endif /*defined(FEATURE_DAT_ENHANCEMENT)*/ #if defined(FEATURE_DAT_ENHANCEMENT) /*-------------------------------------------------------------------*/ /* B98E IDTE - Invalidate DAT Table Entry [RRF] */ /*-------------------------------------------------------------------*/ DEF_INST(invalidate_dat_table_entry) { int r1, r2, r3; /* Values of R fields */ int m4; /* Unused mask field */ U64 asceto; /* ASCE table origin */ int ascedt; /* ASCE designation type */ int count; /* Invalidation counter */ int eiindx; /* Eff. invalidation index */ U64 asce; /* Contents of ASCE */ BYTE *mn; /* Mainstor address of ASCE */ RRF_RM(inst, regs, r1, r2, r3, m4); SIE_XC_INTERCEPT(regs); PRIV_CHECK(regs); /* Program check if bits 44-51 of r2 register are non-zero */ if (regs->GR_L(r2) & 0x000FF000) regs->program_interrupt (regs, PGM_SPECIFICATION_EXCEPTION); #if defined(_FEATURE_SIE) if(SIE_STATB(regs,IC0, IPTECSP)) longjmp(regs->progjmp, SIE_INTERCEPT_INST); #endif /*defined(_FEATURE_SIE)*/ #if defined(_FEATURE_SIE) if(SIE_MODE(regs) && regs->sie_scao) { STORAGE_KEY(regs->sie_scao, regs) |= STORKEY_REF; if(regs->mainstor[regs->sie_scao] & 0x80) longjmp(regs->progjmp, SIE_INTERCEPT_INST); } #endif /*defined(_FEATURE_SIE)*/ /* Perform serialization before starting operation */ PERFORM_SERIALIZATION (regs); /* Bit 52 of the r2 register determines the operation performed */ if ((regs->GR_L(r2) & 0x00000800) == 0) { /* Perform invalidation-and-clearing operation */ /* Extract the invalidation table origin and type from r1 */ asceto = regs->GR_G(r1) & ASCE_TO; ascedt = regs->GR_L(r1) & ASCE_DT; /* Extract the effective invalidation index from r2 */ switch(ascedt) { case TT_R1TABL: /* Region first table */ eiindx = (regs->GR_H(r2) & 0xFF700000) >> 18; break; case TT_R2TABL: /* Region second table */ eiindx = (regs->GR_H(r2) & 0x001FFC00) >> 7; break; case TT_R3TABL: /* Region third table */ eiindx = (regs->GR_G(r2) & 0x000003FF80000000ULL) >> 28; break; case TT_SEGTAB: /* Segment table */ default: eiindx = (regs->GR_L(r2) & 0x7FF00000) >> 17; break; } /* end switch(ascedt) */ /* Calculate the address of table for invalidation, noting that it is always a 64-bit address regardless of the current addressing mode, and that overflow is ignored */ asceto += eiindx; /* Extract the additional entry count from r2 */ count = (regs->GR_L(r2) & 0x7FF) + 1; /* Perform invalidation of one or more table entries */ while (count-- > 0) { /* Fetch the table entry, set the invalid bit, then store only the byte containing the invalid bit */ mn = MADDR (asceto, USE_REAL_ADDR, regs, ACCTYPE_WRITE, regs->psw.pkey); FETCH_DW(asce, mn); asce |= ZSEGTAB_I; mn[7] = asce & 0xFF; /* Calculate the address of the next table entry, noting that it is always a 64-bit address regardless of the current addressing mode, and that overflow is ignored */ asceto += 8; } /* end while */ /* Clear the TLB and signal all other CPUs to clear their TLB */ /* Note: Currently we clear all entries regardless of whether a clearing ASCE is passed in the r3 register. This conforms to the POP which only specifies the minimum set of entries which must be cleared from the TLB. */ OBTAIN_INTLOCK(regs); SYNCHRONIZE_CPUS(regs); ARCH_DEP(purge_tlb_all)(); RELEASE_INTLOCK(regs); } /* end if(invalidation-and-clearing) */ else { /* Perform clearing-by-ASCE operation */ /* Clear the TLB and signal all other CPUs to clear their TLB */ /* Note: Currently we clear all entries regardless of the clearing ASCE passed in the r3 register. This conforms to the POP which only specifies the minimum set of entries which must be cleared from the TLB. */ OBTAIN_INTLOCK(regs); SYNCHRONIZE_CPUS(regs); ARCH_DEP(purge_tlb_all)(); RELEASE_INTLOCK(regs); } /* end else(clearing-by-ASCE) */ /* Perform serialization after completing operation */ PERFORM_SERIALIZATION (regs); } /* end DEF_INST(invalidate_dat_table_entry) */ #endif /*defined(FEATURE_DAT_ENHANCEMENT)*/ #if defined(FEATURE_DAT_ENHANCEMENT_FACILITY_2) /*-------------------------------------------------------------------*/ /* B9AA LPTEA - Load Page-Table-Entry Address [RRF] */ /*-------------------------------------------------------------------*/ DEF_INST(load_page_table_entry_address) { VADR vaddr; /* Virtual address */ int r1, r2, r3; /* Register numbers */ int m4; /* Mask field */ int n; /* Address space indication */ int cc; /* Condition code */ int acctype = ACCTYPE_LPTEA; /* Storage access type */ RRF_RM(inst, regs, r1, r2, r3, m4); SIE_XC_INTERCEPT(regs); PRIV_CHECK(regs); /* The m4 field determines which address space to use */ switch (m4) { case 0: /* Use ASCE in control register 1 */ n = USE_PRIMARY_SPACE; break; case 1: /* Use ALET in access register r2 */ n = USE_ARMODE | r2; break; case 2: /* Use ASCE in control register 7 */ n = USE_SECONDARY_SPACE; break; case 3: /* Use ASCE in control register 13 */ n = USE_HOME_SPACE; break; case 4: /* Use current addressing mode (PSW bits 16-17) */ n = r2; /* r2 is the access register number if ARMODE */ break; default: /* Specification exception if invalid value for m4 */ n = -1; /* makes compiler happy */ regs->program_interrupt (regs, PGM_SPECIFICATION_EXCEPTION); } /* end switch(m4) */ /* Load the virtual address from the r2 register */ vaddr = regs->GR(r2) & ADDRESS_MAXWRAP(regs); /* Find the page table address and condition code */ cc = ARCH_DEP(translate_addr) (vaddr, n, regs, acctype); /* Set R1 to real address or exception code depending on cc */ regs->GR_G(r1) = (cc < 3) ? regs->dat.raddr : regs->dat.xcode; /* Set condition code */ regs->psw.cc = cc; } /* end DEF_INST(load_page_table_entry_address) */ #endif /*defined(FEATURE_DAT_ENHANCEMENT_FACILITY_2)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* E388 ALCG - Add Logical with Carry Long [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(add_logical_carry_long) { int r1; /* Values of R fields */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ U64 n; /* 64-bit operand values */ int carry = 0; RXY(inst, regs, r1, b2, effective_addr2); /* Load second operand from operand address */ n = ARCH_DEP(vfetch8) ( effective_addr2, b2, regs ); /* Add the carry to operand */ if(regs->psw.cc & 2) carry = add_logical_long(&(regs->GR_G(r1)), regs->GR_G(r1), 1) & 2; /* Add unsigned operands and set condition code */ regs->psw.cc = add_logical_long(&(regs->GR_G(r1)), regs->GR_G(r1), n) | carry; } /* end DEF_INST(add_logical_carry_long) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* E389 SLBG - Subtract Logical with Borrow Long [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(subtract_logical_borrow_long) { int r1; /* Values of R fields */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ U64 n; /* 64-bit operand values */ int borrow = 2; RXY(inst, regs, r1, b2, effective_addr2); /* Load second operand from operand address */ n = ARCH_DEP(vfetch8) ( effective_addr2, b2, regs ); /* Subtract the borrow from operand */ if(!(regs->psw.cc & 2)) borrow = sub_logical_long(&(regs->GR_G(r1)), regs->GR_G(r1), 1); /* Subtract unsigned operands and set condition code */ regs->psw.cc = sub_logical_long(&(regs->GR_G(r1)), regs->GR_G(r1), n) & (borrow|1); } /* end DEF_INST(subtract_logical_borrow_long) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* B998 ALCR - Add Logical with Carry Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(add_logical_carry_register) { int r1, r2; /* Values of R fields */ int carry = 0; U32 n; RRE0(inst, regs, r1, r2); n = regs->GR_L(r2); /* Add the carry to operand */ if(regs->psw.cc & 2) carry = add_logical(&(regs->GR_L(r1)), regs->GR_L(r1), 1) & 2; /* Add unsigned operands and set condition code */ regs->psw.cc = add_logical(&(regs->GR_L(r1)), regs->GR_L(r1), n) | carry; } /* end DEF_INST(add_logical_carry_register) */ #endif /*defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* B999 SLBR - Subtract Logical with Borrow Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(subtract_logical_borrow_register) { int r1, r2; /* Values of R fields */ int borrow = 2; U32 n; RRE0(inst, regs, r1, r2); n = regs->GR_L(r2); /* Subtract the borrow from operand */ if(!(regs->psw.cc & 2)) borrow = sub_logical(&(regs->GR_L(r1)), regs->GR_L(r1), 1); /* Subtract unsigned operands and set condition code */ regs->psw.cc = sub_logical(&(regs->GR_L(r1)), regs->GR_L(r1), n) & (borrow|1); } /* end DEF_INST(subtract_logical_borrow_register) */ #endif /*defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* E398 ALC - Add Logical with Carry [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(add_logical_carry) { int r1; /* Values of R fields */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ U32 n; /* 32-bit operand values */ int carry = 0; RXY(inst, regs, r1, b2, effective_addr2); /* Load second operand from operand address */ n = ARCH_DEP(vfetch4) ( effective_addr2, b2, regs ); /* Add the carry to operand */ if(regs->psw.cc & 2) carry = add_logical(&(regs->GR_L(r1)), regs->GR_L(r1), 1) & 2; /* Add unsigned operands and set condition code */ regs->psw.cc = add_logical(&(regs->GR_L(r1)), regs->GR_L(r1), n) | carry; } /* end DEF_INST(add_logical_carry) */ #endif /*defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* E399 SLB - Subtract Logical with Borrow [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(subtract_logical_borrow) { int r1; /* Values of R fields */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ U32 n; /* 32-bit operand values */ int borrow = 2; RXY(inst, regs, r1, b2, effective_addr2); /* Load second operand from operand address */ n = ARCH_DEP(vfetch4) ( effective_addr2, b2, regs ); /* Subtract the borrow from operand */ if(!(regs->psw.cc & 2)) borrow = sub_logical(&(regs->GR_L(r1)), regs->GR_L(r1), 1); /* Subtract unsigned operands and set condition code */ regs->psw.cc = sub_logical(&(regs->GR_L(r1)), regs->GR_L(r1), n) & (borrow|1); } /* end DEF_INST(subtract_logical_borrow) */ #endif /*defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* E30D DSG - Divide Single Long [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(divide_single_long) { int r1; /* Values of R fields */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ U64 n; /* 64-bit operand values */ RXY(inst, regs, r1, b2, effective_addr2); ODD_CHECK(r1, regs); /* Load second operand from operand address */ n = ARCH_DEP(vfetch8) ( effective_addr2, b2, regs ); if(n == 0 || ((S64)n == -1LL && regs->GR_G(r1 + 1) == 0x8000000000000000ULL)) regs->program_interrupt (regs, PGM_FIXED_POINT_DIVIDE_EXCEPTION); regs->GR_G(r1) = (S64)regs->GR_G(r1 + 1) % (S64)n; regs->GR_G(r1 + 1) = (S64)regs->GR_G(r1 + 1) / (S64)n; } /* end DEF_INST(divide_single_long) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* E31D DSGF - Divide Single Long Fullword [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(divide_single_long_fullword) { int r1; /* Values of R fields */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ U32 n; /* 64-bit operand values */ RXY(inst, regs, r1, b2, effective_addr2); ODD_CHECK(r1, regs); /* Load second operand from operand address */ n = ARCH_DEP(vfetch4) ( effective_addr2, b2, regs ); if(n == 0 || ((S32)n == -1 && regs->GR_G(r1 + 1) == 0x8000000000000000ULL)) regs->program_interrupt (regs, PGM_FIXED_POINT_DIVIDE_EXCEPTION); regs->GR_G(r1) = (S64)regs->GR_G(r1 + 1) % (S32)n; regs->GR_G(r1 + 1) = (S64)regs->GR_G(r1 + 1) / (S32)n; } /* end DEF_INST(divide_single_long_fullword) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* B90D DSGR - Divide Single Long Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(divide_single_long_register) { int r1, r2; /* Values of R fields */ U64 n; RRE(inst, regs, r1, r2); ODD_CHECK(r1, regs); if(regs->GR_G(r2) == 0 || ((S64)regs->GR_G(r2) == -1LL && regs->GR_G(r1 + 1) == 0x8000000000000000ULL)) regs->program_interrupt (regs, PGM_FIXED_POINT_DIVIDE_EXCEPTION); n = regs->GR_G(r2); /* Divide signed registers */ regs->GR_G(r1) = (S64)regs->GR_G(r1 + 1) % (S64)n; regs->GR_G(r1 + 1) = (S64)regs->GR_G(r1 + 1) / (S64)n; } /* end DEF_INST(divide_single_long_register) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* B91D DSGFR - Divide Single Long Fullword Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(divide_single_long_fullword_register) { int r1, r2; /* Values of R fields */ U32 n; RRE(inst, regs, r1, r2); ODD_CHECK(r1, regs); if(regs->GR_L(r2) == 0 || ((S32)regs->GR_L(r2) == -1 && regs->GR_G(r1 + 1) == 0x8000000000000000ULL)) regs->program_interrupt (regs, PGM_FIXED_POINT_DIVIDE_EXCEPTION); n = regs->GR_L(r2); /* Divide signed registers */ regs->GR_G(r1) = (S64)regs->GR_G(r1 + 1) % (S32)n; regs->GR_G(r1 + 1) = (S64)regs->GR_G(r1 + 1) / (S32)n; } /* end DEF_INST(divide_single_long_fullword_register) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* E390 LLGC - Load Logical Long Character [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(load_logical_long_character) { int r1; /* Value of R field */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ RXY(inst, regs, r1, b2, effective_addr2); regs->GR_G(r1) = ARCH_DEP(vfetchb) ( effective_addr2, b2, regs ); } /* end DEF_INST(load_logical_long_character) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* E391 LLGH - Load Logical Long Halfword [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(load_logical_long_halfword) { int r1; /* Value of R field */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ RXY(inst, regs, r1, b2, effective_addr2); regs->GR_G(r1) = ARCH_DEP(vfetch2) ( effective_addr2, b2, regs ); } /* end DEF_INST(load_logical_long_halfword) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* E38E STPQ - Store Pair to Quadword [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(store_pair_to_quadword) { int r1; /* Value of R field */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ QWORD qwork; /* Quadword work area */ RXY(inst, regs, r1, b2, effective_addr2); ODD_CHECK(r1, regs); QW_CHECK(effective_addr2, regs); /* Store regs in workarea */ STORE_DW(qwork, regs->GR_G(r1)); STORE_DW(qwork+8, regs->GR_G(r1+1)); /* Store R1 and R1+1 registers to second operand Provide storage consistancy by means of obtaining the main storage access lock */ OBTAIN_MAINLOCK(regs); ARCH_DEP(vstorec) ( qwork, 16-1, effective_addr2, b2, regs ); RELEASE_MAINLOCK(regs); } /* end DEF_INST(store_pair_to_quadword) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* E38F LPQ - Load Pair from Quadword [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(load_pair_from_quadword) { int r1; /* Value of R field */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ QWORD qwork; /* Quadword work area */ RXY(inst, regs, r1, b2, effective_addr2); ODD_CHECK(r1, regs); QW_CHECK(effective_addr2, regs); /* Load R1 and R1+1 registers contents from second operand Provide storage consistancy by means of obtaining the main storage access lock */ OBTAIN_MAINLOCK(regs); ARCH_DEP(vfetchc) ( qwork, 16-1, effective_addr2, b2, regs ); RELEASE_MAINLOCK(regs); /* Load regs from workarea */ FETCH_DW(regs->GR_G(r1), qwork); FETCH_DW(regs->GR_G(r1+1), qwork+8); } /* end DEF_INST(load_pair_from_quadword) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* B90E EREGG - Extract Stacked Registers Long [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(extract_stacked_registers_long) { int r1, r2; /* Values of R fields */ LSED lsed; /* Linkage stack entry desc. */ VADR lsea; /* Linkage stack entry addr */ RRE(inst, regs, r1, r2); SIE_XC_INTERCEPT(regs); /* Find the virtual address of the entry descriptor of the current state entry in the linkage stack */ lsea = ARCH_DEP(locate_stack_entry) (0, &lsed, regs); /* Load registers from the stack entry */ ARCH_DEP(unstack_registers) (1, lsea, r1, r2, regs); } /* end DEF_INST(extract_stacked_registers_long) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* B98D EPSW - Extract PSW [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(extract_psw) { int r1, r2; /* Values of R fields */ QWORD currpsw; /* Work area for PSW */ RRE(inst, regs, r1, r2); #if defined(_FEATURE_ZSIE) if(SIE_STATB(regs, IC1, LPSW)) longjmp(regs->progjmp, SIE_INTERCEPT_INST); #endif /*defined(_FEATURE_ZSIE)*/ /* Store the current PSW in work area */ ARCH_DEP(store_psw) (regs, currpsw); /* Load PSW bits 0-31 into bits 32-63 of the R1 register */ FETCH_FW(regs->GR_L(r1), currpsw); /* If R2 specifies a register other than register zero, load PSW bits 32-63 into bits 32-63 of the R2 register */ if(r2 != 0) { FETCH_FW(regs->GR_L(r2), currpsw+4); #if !defined(FEATURE_ESAME) /* The Ninth Edition of ESA/390 POP (SA22-7201-08) requires the low 31 bits to be set to zeroes in ESA/390 mode */ regs->GR_L(r2) &= 0x80000000; #endif /*!defined(FEATURE_ESAME)*/ } } /* end DEF_INST(extract_psw) */ #endif /*defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* B99D ESEA - Extract and Set Extended Authority [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(extract_and_set_extended_authority) { int r1, unused; /* Value of R field */ RRE(inst, regs, r1, unused); PRIV_CHECK(regs); #if 0 #if defined(_FEATURE_ZSIE) if(SIE_STATB(regs, LCTL1, CR8)) longjmp(regs->progjmp, SIE_INTERCEPT_INST); #endif /*defined(_FEATURE_ZSIE)*/ #endif regs->GR_LHH(r1) = regs->CR_LHH(8); regs->CR_LHH(8) = regs->GR_LHL(r1); } /* end DEF_INST(extract_and_set_extended_authority) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* C0x0 LARL - Load Address Relative Long [RIL] */ /*-------------------------------------------------------------------*/ DEF_INST(load_address_relative_long) { int r1; /* Register number */ int opcd; /* Opcode */ U32 i2; /* 32-bit operand values */ RIL0(inst, regs, r1, opcd, i2); SET_GR_A(r1, regs, likely(!regs->execflag) ? PSW_IA(regs, -6 + 2LL*(S32)i2) : (regs->ET + 2LL*(S32)i2) & ADDRESS_MAXWRAP(regs)); } /* end DEF_INST(load_address_relative_long) */ #endif /*defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* A5x0 IIHH - Insert Immediate High High [RI] */ /*-------------------------------------------------------------------*/ DEF_INST(insert_immediate_high_high) { int r1; /* Register number */ int opcd; /* Opcode */ U16 i2; /* 16-bit operand values */ RI0(inst, regs, r1, opcd, i2); regs->GR_HHH(r1) = i2; } /* end DEF_INST(insert_immediate_high_high) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* A5x1 IIHL - Insert Immediate High Low [RI] */ /*-------------------------------------------------------------------*/ DEF_INST(insert_immediate_high_low) { int r1; /* Register number */ int opcd; /* Opcode */ U16 i2; /* 16-bit operand values */ RI0(inst, regs, r1, opcd, i2); regs->GR_HHL(r1) = i2; } /* end DEF_INST(insert_immediate_high_low) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* A5x2 IILH - Insert Immediate Low High [RI] */ /*-------------------------------------------------------------------*/ DEF_INST(insert_immediate_low_high) { int r1; /* Register number */ int opcd; /* Opcode */ U16 i2; /* 16-bit operand values */ RI0(inst, regs, r1, opcd, i2); regs->GR_LHH(r1) = i2; } /* end DEF_INST(insert_immediate_low_high) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* A5x3 IILL - Insert Immediate Low Low [RI] */ /*-------------------------------------------------------------------*/ DEF_INST(insert_immediate_low_low) { int r1; /* Register number */ int opcd; /* Opcode */ U16 i2; /* 16-bit operand values */ RI0(inst, regs, r1, opcd, i2); regs->GR_LHL(r1) = i2; } /* end DEF_INST(insert_immediate_low_low) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* A5x4 NIHH - And Immediate High High [RI] */ /*-------------------------------------------------------------------*/ DEF_INST(and_immediate_high_high) { int r1; /* Register number */ int opcd; /* Opcode */ U16 i2; /* 16-bit operand values */ RI0(inst, regs, r1, opcd, i2); regs->GR_HHH(r1) &= i2; /* Set condition code according to result */ regs->psw.cc = regs->GR_HHH(r1) ? 1 : 0; } /* end DEF_INST(and_immediate_high_high) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* A5x5 NIHL - And Immediate High Low [RI] */ /*-------------------------------------------------------------------*/ DEF_INST(and_immediate_high_low) { int r1; /* Register number */ int opcd; /* Opcode */ U16 i2; /* 16-bit operand values */ RI0(inst, regs, r1, opcd, i2); regs->GR_HHL(r1) &= i2; /* Set condition code according to result */ regs->psw.cc = regs->GR_HHL(r1) ? 1 : 0; } /* end DEF_INST(and_immediate_high_low) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* A5x6 NILH - And Immediate Low High [RI] */ /*-------------------------------------------------------------------*/ DEF_INST(and_immediate_low_high) { int r1; /* Register number */ int opcd; /* Opcode */ U16 i2; /* 16-bit operand values */ RI0(inst, regs, r1, opcd, i2); regs->GR_LHH(r1) &= i2; /* Set condition code according to result */ regs->psw.cc = regs->GR_LHH(r1) ? 1 : 0; } /* end DEF_INST(and_immediate_low_high) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* A5x7 NILL - And Immediate Low Low [RI] */ /*-------------------------------------------------------------------*/ DEF_INST(and_immediate_low_low) { int r1; /* Register number */ int opcd; /* Opcode */ U16 i2; /* 16-bit operand values */ RI0(inst, regs, r1, opcd, i2); regs->GR_LHL(r1) &= i2; /* Set condition code according to result */ regs->psw.cc = regs->GR_LHL(r1) ? 1 : 0; } /* end DEF_INST(and_immediate_low_low) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* A5x8 OIHH - Or Immediate High High [RI] */ /*-------------------------------------------------------------------*/ DEF_INST(or_immediate_high_high) { int r1; /* Register number */ int opcd; /* Opcode */ U16 i2; /* 16-bit operand values */ RI0(inst, regs, r1, opcd, i2); regs->GR_HHH(r1) |= i2; /* Set condition code according to result */ regs->psw.cc = regs->GR_HHH(r1) ? 1 : 0; } /* end DEF_INST(or_immediate_high_high) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* A5x9 OIHL - Or Immediate High Low [RI] */ /*-------------------------------------------------------------------*/ DEF_INST(or_immediate_high_low) { int r1; /* Register number */ int opcd; /* Opcode */ U16 i2; /* 16-bit operand values */ RI0(inst, regs, r1, opcd, i2); regs->GR_HHL(r1) |= i2; /* Set condition code according to result */ regs->psw.cc = regs->GR_HHL(r1) ? 1 : 0; } /* end DEF_INST(or_immediate_high_low) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* A5xA OILH - Or Immediate Low High [RI] */ /*-------------------------------------------------------------------*/ DEF_INST(or_immediate_low_high) { int r1; /* Register number */ int opcd; /* Opcode */ U16 i2; /* 16-bit operand values */ RI0(inst, regs, r1, opcd, i2); regs->GR_LHH(r1) |= i2; /* Set condition code according to result */ regs->psw.cc = regs->GR_LHH(r1) ? 1 : 0; } /* end DEF_INST(or_immediate_low_high) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* A5xB OILL - Or Immediate Low Low [RI] */ /*-------------------------------------------------------------------*/ DEF_INST(or_immediate_low_low) { int r1; /* Register number */ int opcd; /* Opcode */ U16 i2; /* 16-bit operand values */ RI0(inst, regs, r1, opcd, i2); regs->GR_LHL(r1) |= i2; /* Set condition code according to result */ regs->psw.cc = regs->GR_LHL(r1) ? 1 : 0; } /* end DEF_INST(or_immediate_low_low) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* A5xC LLIHH - Load Logical Immediate High High [RI] */ /*-------------------------------------------------------------------*/ DEF_INST(load_logical_immediate_high_high) { int r1; /* Register number */ int opcd; /* Opcode */ U16 i2; /* 16-bit operand values */ RI0(inst, regs, r1, opcd, i2); regs->GR_G(r1) = (U64)i2 << 48; } /* end DEF_INST(load_logical_immediate_high_high) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* A5xD LLIHL - Load Logical Immediate High Low [RI] */ /*-------------------------------------------------------------------*/ DEF_INST(load_logical_immediate_high_low) { int r1; /* Register number */ int opcd; /* Opcode */ U16 i2; /* 16-bit operand values */ RI0(inst, regs, r1, opcd, i2); regs->GR_G(r1) = (U64)i2 << 32; } /* end DEF_INST(load_logical_immediate_high_low) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* A5xE LLILH - Load Logical Immediate Low High [RI] */ /*-------------------------------------------------------------------*/ DEF_INST(load_logical_immediate_low_high) { int r1; /* Register number */ int opcd; /* Opcode */ U16 i2; /* 16-bit operand values */ RI0(inst, regs, r1, opcd, i2); regs->GR_G(r1) = (U64)i2 << 16; } /* end DEF_INST(load_logical_immediate_low_high) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* A5xF LLILL - Load Logical Immediate Low Low [RI] */ /*-------------------------------------------------------------------*/ DEF_INST(load_logical_immediate_low_low) { int r1; /* Register number */ int opcd; /* Opcode */ U16 i2; /* 16-bit operand values */ RI0(inst, regs, r1, opcd, i2); regs->GR_G(r1) = (U64)i2; } /* end DEF_INST(load_logical_immediate_low_low) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* C0x4 BRCL - Branch Relative on Condition Long [RIL] */ /*-------------------------------------------------------------------*/ DEF_INST(branch_relative_on_condition_long) { //int r1; /* Register number */ //int opcd; /* Opcode */ //U32 i2; /* 32-bit operand values */ // RIL(inst, regs, r1, opcd, i2); /* Branch if R1 mask bit is set */ if (inst[1] & (0x80 >> regs->psw.cc)) SUCCESSFUL_RELATIVE_BRANCH_LONG(regs, 2LL*(S32)fetch_fw(inst+2)); else INST_UPDATE_PSW(regs, 6, 0); } /* end DEF_INST(branch_relative_on_condition_long) */ #endif /*defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* C0x5 BRASL - Branch Relative And Save Long [RIL] */ /*-------------------------------------------------------------------*/ DEF_INST(branch_relative_and_save_long) { int r1; /* Register number */ int opcd; /* Opcode */ U32 i2; /* 32-bit operand values */ RIL_B(inst, regs, r1, opcd, i2); #if defined(FEATURE_ESAME) if(regs->psw.amode64) regs->GR_G(r1) = PSW_IA64(regs, 6); else #endif /*defined(FEATURE_ESAME)*/ if ( regs->psw.amode ) regs->GR_L(r1) = 0x80000000 | PSW_IA31(regs, 6); else regs->GR_L(r1) = PSW_IA24(regs, 6); SUCCESSFUL_RELATIVE_BRANCH_LONG(regs, 2LL*(S32)fetch_fw(inst+2)); } /* end DEF_INST(branch_relative_and_save_long) */ #endif /*defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* EB20 CLMH - Compare Logical Characters under Mask High [RSY] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_logical_characters_under_mask_high) { int r1, r3; /* Register numbers */ int b2; /* effective address base */ VADR effective_addr2; /* effective address */ int i, j; /* Integer work areas */ int cc = 0; /* Condition code */ BYTE rbyte[4], /* Register bytes */ vbyte; /* Virtual storage byte */ RSY(inst, regs, r1, r3, b2, effective_addr2); /* Set register bytes by mask */ i = 0; if (r3 & 0x8) rbyte[i++] = (regs->GR_H(r1) >> 24) & 0xFF; if (r3 & 0x4) rbyte[i++] = (regs->GR_H(r1) >> 16) & 0xFF; if (r3 & 0x2) rbyte[i++] = (regs->GR_H(r1) >> 8) & 0xFF; if (r3 & 0x1) rbyte[i++] = (regs->GR_H(r1) ) & 0xFF; /* Perform access check if mask is 0 */ if (!r3) ARCH_DEP(vfetchb) (effective_addr2, b2, regs); /* Compare byte by byte */ for (j = 0; j < i && !cc; j++) { effective_addr2 &= ADDRESS_MAXWRAP(regs); vbyte = ARCH_DEP(vfetchb) (effective_addr2++, b2, regs); if (rbyte[j] != vbyte) cc = rbyte[j] < vbyte ? 1 : 2; } regs->psw.cc = cc; } /* end DEF_INST(compare_logical_characters_under_mask_high) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* EB2C STCMH - Store Characters under Mask High [RSY] */ /*-------------------------------------------------------------------*/ DEF_INST(store_characters_under_mask_high) { int r1, r3; /* Register numbers */ int b2; /* effective address base */ VADR effective_addr2; /* effective address */ int i; /* Integer work area */ BYTE rbyte[4]; /* Register bytes from mask */ RSY(inst, regs, r1, r3, b2, effective_addr2); switch (r3) { case 15: /* Optimized case */ ARCH_DEP(vstore4) (regs->GR_H(r1), effective_addr2, b2, regs); break; default: /* Extract value from register by mask */ i = 0; if (r3 & 0x8) rbyte[i++] = (regs->GR_H(r1) >> 24) & 0xFF; if (r3 & 0x4) rbyte[i++] = (regs->GR_H(r1) >> 16) & 0xFF; if (r3 & 0x2) rbyte[i++] = (regs->GR_H(r1) >> 8) & 0xFF; if (r3 & 0x1) rbyte[i++] = (regs->GR_H(r1) ) & 0xFF; if (i) ARCH_DEP(vstorec) (rbyte, i-1, effective_addr2, b2, regs); #if defined(MODEL_DEPENDENT_STCM) /* If the mask is all zero, we nevertheless access one byte from the storage operand, because POP states that an access exception may be recognized on the first byte */ else ARCH_DEP(validate_operand) (effective_addr2, b2, 0, ACCTYPE_WRITE, regs); #endif break; } /* switch (r3) */ } /* end DEF_INST(store_characters_under_mask_high) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_EXTRACT_CPU_TIME) /*-------------------------------------------------------------------*/ /* C8x1 ECTG - Extract CPU Time [SSF] */ /*-------------------------------------------------------------------*/ DEF_INST(extract_cpu_time) { int b1, b2; /* Base of effective addr */ VADR effective_addr1; /* Effective address */ VADR effective_addr2; /* Effective address */ int r3; /* R3 register number */ S64 dreg; /* Double word workarea */ U64 gr0, gr1; /* Result register workareas */ SSF(inst, regs, b1, effective_addr1, b2, effective_addr2, r3); #if defined(_FEATURE_SIE) if(SIE_STATB(regs, IC3, SPT)) longjmp(regs->progjmp, SIE_INTERCEPT_INST); #endif /*defined(_FEATURE_SIE)*/ OBTAIN_INTLOCK(regs); /* Save the CPU timer value */ dreg = cpu_timer(regs); /* Reset the cpu timer pending flag according to its value */ if( CPU_TIMER(regs) < 0 ) { ON_IC_PTIMER(regs); /* Roll back the instruction and take the timer interrupt if we have a pending CPU timer and we are enabled for such interrupts *JJ */ if( OPEN_IC_PTIMER(regs) ) { RELEASE_INTLOCK(regs); UPD_PSW_IA(regs, PSW_IA(regs, !regs->execflag ? -6 : regs->exrl ? -6 : -4)); RETURN_INTCHECK(regs); } } else OFF_IC_PTIMER(regs); RELEASE_INTLOCK(regs); /* The value of the current CPU timer is subtracted from the first operand and the result is placed in general register 0 */ gr0 = ARCH_DEP(vfetch8) (effective_addr1, b1, regs) - dreg; /* The second operand is placed in general register 1 */ gr1 = ARCH_DEP(vfetch8) (effective_addr2, b2, regs); /* The eight bytes at the third operand location replace the contents of general register R3. The operands are treated as unsigned 64-bit integers. The contents of R3 is treated according to current addressing mode. In AR mode, access register R3 is used. */ regs->GR_G(r3) = ARCH_DEP(wfetch8) (regs->GR_G(r3), r3, regs); regs->GR_G(0) = gr0; regs->GR_G(1) = gr1; RETURN_INTCHECK(regs); } /* end DEF_INST(extract_cpu_time) */ #endif /*defined(FEATURE_EXTRACT_CPU_TIME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* EB80 ICMH - Insert Characters under Mask High [RSY] */ /*-------------------------------------------------------------------*/ DEF_INST(insert_characters_under_mask_high) { int r1, r3; /* Register numbers */ int b2; /* effective address base */ VADR effective_addr2; /* effective address */ int i; /* Integer work area */ BYTE vbyte[4]; /* Fetched storage bytes */ U32 n; /* Fetched value */ static const int /* Length-1 to fetch by mask */ icmhlen[16] = {0, 0, 0, 1, 0, 1, 1, 2, 0, 1, 1, 2, 1, 2, 2, 3}; static const unsigned int /* Turn reg bytes off by mask*/ icmhmask[16] = {0xFFFFFFFF, 0xFFFFFF00, 0xFFFF00FF, 0xFFFF0000, 0xFF00FFFF, 0xFF00FF00, 0xFF0000FF, 0xFF000000, 0x00FFFFFF, 0x00FFFF00, 0x00FF00FF, 0x00FF0000, 0x0000FFFF, 0x0000FF00, 0x000000FF, 0x00000000}; RSY(inst, regs, r1, r3, b2, effective_addr2); switch (r3) { case 15: /* Optimized case */ regs->GR_H(r1) = ARCH_DEP(vfetch4) (effective_addr2, b2, regs); regs->psw.cc = regs->GR_H(r1) ? regs->GR_H(r1) & 0x80000000 ? 1 : 2 : 0; break; default: memset (vbyte, 0, 4); ARCH_DEP(vfetchc)(vbyte, icmhlen[r3], effective_addr2, b2, regs); /* If mask was 0 then we still had to fetch, according to POP. If so, set the fetched byte to 0 to force zero cc */ if (!r3) vbyte[0] = 0; n = fetch_fw (vbyte); regs->psw.cc = n ? n & 0x80000000 ? 1 : 2 : 0; /* Turn off the reg bytes we are going to set */ regs->GR_H(r1) &= icmhmask[r3]; /* Set bytes one at a time according to the mask */ i = 0; if (r3 & 0x8) regs->GR_H(r1) |= vbyte[i++] << 24; if (r3 & 0x4) regs->GR_H(r1) |= vbyte[i++] << 16; if (r3 & 0x2) regs->GR_H(r1) |= vbyte[i++] << 8; if (r3 & 0x1) regs->GR_H(r1) |= vbyte[i]; break; } /* switch (r3) */ } /* end DEF_INST(insert_characters_under_mask_high) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* EC44 BRXHG - Branch Relative on Index High Long [RIE] */ /*-------------------------------------------------------------------*/ DEF_INST(branch_relative_on_index_high_long) { int r1, r3; /* Register numbers */ S16 i2; /* 16-bit immediate offset */ S64 i,j; /* Integer workareas */ RIE_B(inst, regs, r1, r3, i2); /* Load the increment value from the R3 register */ i = (S64)regs->GR_G(r3); /* Load compare value from R3 (if R3 odd), or R3+1 (if even) */ j = (r3 & 1) ? (S64)regs->GR_G(r3) : (S64)regs->GR_G(r3+1); /* Add the increment value to the R1 register */ regs->GR_G(r1) = (S64)regs->GR_G(r1) + i; /* Branch if result compares high */ if ( (S64)regs->GR_G(r1) > j ) SUCCESSFUL_RELATIVE_BRANCH(regs, 2*i2, 6); else INST_UPDATE_PSW(regs, 6, 0); } /* end DEF_INST(branch_relative_on_index_high_long) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* EC45 BRXLG - Branch Relative on Index Low or Equal Long [RIE] */ /*-------------------------------------------------------------------*/ DEF_INST(branch_relative_on_index_low_or_equal_long) { int r1, r3; /* Register numbers */ S16 i2; /* 16-bit immediate offset */ S64 i,j; /* Integer workareas */ RIE_B(inst, regs, r1, r3, i2); /* Load the increment value from the R3 register */ i = (S64)regs->GR_G(r3); /* Load compare value from R3 (if R3 odd), or R3+1 (if even) */ j = (r3 & 1) ? (S64)regs->GR_G(r3) : (S64)regs->GR_G(r3+1); /* Add the increment value to the R1 register */ regs->GR_G(r1) = (S64)regs->GR_G(r1) + i; /* Branch if result compares low or equal */ if ( (S64)regs->GR_G(r1) <= j ) SUCCESSFUL_RELATIVE_BRANCH(regs, 2*i2, 6); else INST_UPDATE_PSW(regs, 6, 0); } /* end DEF_INST(branch_relative_on_index_low_or_equal_long) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* EB44 BXHG - Branch on Index High Long [RSY] */ /*-------------------------------------------------------------------*/ DEF_INST(branch_on_index_high_long) { int r1, r3; /* Register numbers */ int b2; /* effective address base */ VADR effective_addr2; /* effective address */ S64 i, j; /* Integer work areas */ RSY_B(inst, regs, r1, r3, b2, effective_addr2); /* Load the increment value from the R3 register */ i = (S64)regs->GR_G(r3); /* Load compare value from R3 (if R3 odd), or R3+1 (if even) */ j = (r3 & 1) ? (S64)regs->GR_G(r3) : (S64)regs->GR_G(r3+1); /* Add the increment value to the R1 register */ regs->GR_G(r1) = (S64)regs->GR_G(r1) + i; /* Branch if result compares high */ if ( (S64)regs->GR_G(r1) > j ) SUCCESSFUL_BRANCH(regs, effective_addr2, 6); else INST_UPDATE_PSW(regs, 6, 0); } /* end DEF_INST(branch_on_index_high_long) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* EB45 BXLEG - Branch on Index Low or Equal Long [RSY] */ /*-------------------------------------------------------------------*/ DEF_INST(branch_on_index_low_or_equal_long) { int r1, r3; /* Register numbers */ int b2; /* effective address base */ VADR effective_addr2; /* effective address */ S64 i, j; /* Integer work areas */ RSY_B(inst, regs, r1, r3, b2, effective_addr2); /* Load the increment value from the R3 register */ i = regs->GR_G(r3); /* Load compare value from R3 (if R3 odd), or R3+1 (if even) */ j = (r3 & 1) ? (S64)regs->GR_G(r3) : (S64)regs->GR_G(r3+1); /* Add the increment value to the R1 register */ regs->GR_G(r1) = (S64)regs->GR_G(r1) + i; /* Branch if result compares low or equal */ if ( (S64)regs->GR_G(r1) <= j ) SUCCESSFUL_BRANCH(regs, effective_addr2, 6); else INST_UPDATE_PSW(regs, 6, 0); } /* end DEF_INST(branch_on_index_low_or_equal_long) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* EB30 CSG - Compare and Swap Long [RSY] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_and_swap_long) { int r1, r3; /* Register numbers */ int b2; /* effective address base */ VADR effective_addr2; /* effective address */ BYTE *main2; /* mainstor address */ U64 old; /* old value */ RSY(inst, regs, r1, r3, b2, effective_addr2); DW_CHECK(effective_addr2, regs); /* Perform serialization before starting operation */ PERFORM_SERIALIZATION (regs); /* Get operand absolute address */ main2 = MADDR (effective_addr2, b2, regs, ACCTYPE_WRITE, regs->psw.pkey); /* Get old value */ old = CSWAP64(regs->GR_G(r1)); /* Obtain main-storage access lock */ OBTAIN_MAINLOCK(regs); /* Attempt to exchange the values */ regs->psw.cc = cmpxchg8 (&old, CSWAP64(regs->GR_G(r3)), main2); /* Release main-storage access lock */ RELEASE_MAINLOCK(regs); /* Perform serialization after completing operation */ PERFORM_SERIALIZATION (regs); if (regs->psw.cc == 1) { regs->GR_G(r1) = CSWAP64(old); #if defined(_FEATURE_ZSIE) if(SIE_STATB(regs, IC0, CS1)) { if( !OPEN_IC_PER(regs) ) longjmp(regs->progjmp, SIE_INTERCEPT_INST); else longjmp(regs->progjmp, SIE_INTERCEPT_INSTCOMP); } else #endif /*defined(_FEATURE_ZSIE)*/ if (sysblk.cpus > 1) sched_yield(); } } /* end DEF_INST(compare_and_swap_long) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* EB3E CDSG - Compare Double and Swap Long [RSY] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_double_and_swap_long) { int r1, r3; /* Register numbers */ int b2; /* effective address base */ VADR effective_addr2; /* effective address */ BYTE *main2; /* mainstor address */ U64 old1, old2; /* old value */ RSY(inst, regs, r1, r3, b2, effective_addr2); ODD2_CHECK(r1, r3, regs); QW_CHECK(effective_addr2, regs); /* Perform serialization before starting operation */ PERFORM_SERIALIZATION (regs); /* Get operand mainstor address */ main2 = MADDR (effective_addr2, b2, regs, ACCTYPE_WRITE, regs->psw.pkey); /* Get old values */ old1 = CSWAP64(regs->GR_G(r1)); old2 = CSWAP64(regs->GR_G(r1+1)); /* Obtain main-storage access lock */ OBTAIN_MAINLOCK(regs); /* Attempt to exchange the values */ regs->psw.cc = cmpxchg16 (&old1, &old2, CSWAP64(regs->GR_G(r3)), CSWAP64(regs->GR_G(r3+1)), main2); /* Release main-storage access lock */ RELEASE_MAINLOCK(regs); /* Perform serialization after completing operation */ PERFORM_SERIALIZATION (regs); if (regs->psw.cc == 1) { regs->GR_G(r1) = CSWAP64(old1); regs->GR_G(r1+1) = CSWAP64(old2); #if defined(_FEATURE_ZSIE) if(SIE_STATB(regs, IC0, CS1)) { if( !OPEN_IC_PER(regs) ) longjmp(regs->progjmp, SIE_INTERCEPT_INST); else longjmp(regs->progjmp, SIE_INTERCEPT_INSTCOMP); } else #endif /*defined(_FEATURE_ZSIE)*/ if (sysblk.cpus > 1) sched_yield(); } } /* end DEF_INST(compare_double_and_swap_long) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* E346 BCTG - Branch on Count Long [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(branch_on_count_long) { int r1; /* Value of R field */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ RXY_B(inst, regs, r1, b2, effective_addr2); /* Subtract 1 from the R1 operand and branch if non-zero */ if ( --(regs->GR_G(r1)) ) SUCCESSFUL_BRANCH(regs, effective_addr2, 6); else INST_UPDATE_PSW(regs, 6, 0); } /* end DEF_INST(branch_on_count_long) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* B946 BCTGR - Branch on Count Long Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(branch_on_count_long_register) { int r1, r2; /* Values of R fields */ VADR newia; /* New instruction address */ RRE_B(inst, regs, r1, r2); /* Compute the branch address from the R2 operand */ newia = regs->GR_G(r2); /* Subtract 1 from the R1 operand and branch if result is non-zero and R2 operand is not register zero */ if ( --(regs->GR_G(r1)) && r2 != 0 ) SUCCESSFUL_BRANCH(regs, newia, 2); else INST_UPDATE_PSW(regs, 4, 0); } /* end DEF_INST(branch_on_count_long_register) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* B920 CGR - Compare Long Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_long_register) { int r1, r2; /* Values of R fields */ RRE0(inst, regs, r1, r2); /* Compare signed operands and set condition code */ regs->psw.cc = (S64)regs->GR_G(r1) < (S64)regs->GR_G(r2) ? 1 : (S64)regs->GR_G(r1) > (S64)regs->GR_G(r2) ? 2 : 0; } /* end DEF_INST(compare_long_register) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* B930 CGFR - Compare Long Fullword Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_long_fullword_register) { int r1, r2; /* Values of R fields */ RRE0(inst, regs, r1, r2); /* Compare signed operands and set condition code */ regs->psw.cc = (S64)regs->GR_G(r1) < (S32)regs->GR_L(r2) ? 1 : (S64)regs->GR_G(r1) > (S32)regs->GR_L(r2) ? 2 : 0; } /* end DEF_INST(compare_long_fullword_register) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* E320 CG - Compare Long [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_long) { int r1; /* Values of R fields */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ U64 n; /* 64-bit operand values */ RXY(inst, regs, r1, b2, effective_addr2); /* Load second operand from operand address */ n = ARCH_DEP(vfetch8) ( effective_addr2, b2, regs ); /* Compare signed operands and set condition code */ regs->psw.cc = (S64)regs->GR_G(r1) < (S64)n ? 1 : (S64)regs->GR_G(r1) > (S64)n ? 2 : 0; } /* end DEF_INST(compare_long) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* E330 CGF - Compare Long Fullword [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_long_fullword) { int r1; /* Values of R fields */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ U32 n; /* 32-bit operand values */ RXY(inst, regs, r1, b2, effective_addr2); /* Load second operand from operand address */ n = ARCH_DEP(vfetch4) ( effective_addr2, b2, regs ); /* Compare signed operands and set condition code */ regs->psw.cc = (S64)regs->GR_G(r1) < (S32)n ? 1 : (S64)regs->GR_G(r1) > (S32)n ? 2 : 0; } /* end DEF_INST(compare_long_fullword) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* E30A ALG - Add Logical Long [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(add_logical_long) { int r1; /* Values of R fields */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ U64 n; /* 64-bit operand values */ RXY(inst, regs, r1, b2, effective_addr2); /* Load second operand from operand address */ n = ARCH_DEP(vfetch8) ( effective_addr2, b2, regs ); /* Add unsigned operands and set condition code */ regs->psw.cc = add_logical_long(&(regs->GR_G(r1)), regs->GR_G(r1), n); } /* end DEF_INST(add_logical_long) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* E31A ALGF - Add Logical Long Fullword [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(add_logical_long_fullword) { int r1; /* Values of R fields */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ U32 n; /* 32-bit operand values */ RXY(inst, regs, r1, b2, effective_addr2); /* Load second operand from operand address */ n = ARCH_DEP(vfetch4) ( effective_addr2, b2, regs ); /* Add unsigned operands and set condition code */ regs->psw.cc = add_logical_long(&(regs->GR_G(r1)), regs->GR_G(r1), n); } /* end DEF_INST(add_logical_long_fullword) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* E318 AGF - Add Long Fullword [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(add_long_fullword) { int r1; /* Values of R fields */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ U32 n; /* 32-bit operand values */ RXY(inst, regs, r1, b2, effective_addr2); /* Load second operand from operand address */ n = ARCH_DEP(vfetch4) ( effective_addr2, b2, regs ); /* Add signed operands and set condition code */ regs->psw.cc = add_signed_long (&(regs->GR_G(r1)), regs->GR_G(r1), (S32)n); /* Program check if fixed-point overflow */ if ( regs->psw.cc == 3 && FOMASK(®s->psw) ) regs->program_interrupt (regs, PGM_FIXED_POINT_OVERFLOW_EXCEPTION); } /* end DEF_INST(add_long_fullword) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* E308 AG - Add Long [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(add_long) { int r1; /* Values of R fields */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ U64 n; /* 64-bit operand values */ RXY(inst, regs, r1, b2, effective_addr2); /* Load second operand from operand address */ n = ARCH_DEP(vfetch8) ( effective_addr2, b2, regs ); /* Add signed operands and set condition code */ regs->psw.cc = add_signed_long (&(regs->GR_G(r1)), regs->GR_G(r1), n); /* Program check if fixed-point overflow */ if ( regs->psw.cc == 3 && FOMASK(®s->psw) ) regs->program_interrupt (regs, PGM_FIXED_POINT_OVERFLOW_EXCEPTION); } /* end DEF_INST(add_long) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* E30B SLG - Subtract Logical Long [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(subtract_logical_long) { int r1; /* Values of R fields */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ U64 n; /* 64-bit operand values */ RXY(inst, regs, r1, b2, effective_addr2); /* Load second operand from operand address */ n = ARCH_DEP(vfetch8) ( effective_addr2, b2, regs ); /* Subtract unsigned operands and set condition code */ regs->psw.cc = sub_logical_long(&(regs->GR_G(r1)), regs->GR_G(r1), n); } /* end DEF_INST(subtract_logical_long) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* E31B SLGF - Subtract Logical Long Fullword [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(subtract_logical_long_fullword) { int r1; /* Values of R fields */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ U32 n; /* 32-bit operand values */ RXY(inst, regs, r1, b2, effective_addr2); /* Load second operand from operand address */ n = ARCH_DEP(vfetch4) ( effective_addr2, b2, regs ); /* Subtract unsigned operands and set condition code */ regs->psw.cc = sub_logical_long(&(regs->GR_G(r1)), regs->GR_G(r1), n); } /* end DEF_INST(subtract_logical_long_fullword) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* E319 SGF - Subtract Long Fullword [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(subtract_long_fullword) { int r1; /* Values of R fields */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ U32 n; /* 32-bit operand values */ RXY(inst, regs, r1, b2, effective_addr2); /* Load second operand from operand address */ n = ARCH_DEP(vfetch4) ( effective_addr2, b2, regs ); /* Subtract signed operands and set condition code */ regs->psw.cc = sub_signed_long(&(regs->GR_G(r1)), regs->GR_G(r1), (S32)n); /* Program check if fixed-point overflow */ if ( regs->psw.cc == 3 && FOMASK(®s->psw) ) regs->program_interrupt (regs, PGM_FIXED_POINT_OVERFLOW_EXCEPTION); } /* end DEF_INST(subtract_long_fullword) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* E309 SG - Subtract Long [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(subtract_long) { int r1; /* Values of R fields */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ U64 n; /* 64-bit operand values */ RXY(inst, regs, r1, b2, effective_addr2); /* Load second operand from operand address */ n = ARCH_DEP(vfetch8) ( effective_addr2, b2, regs ); /* Subtract signed operands and set condition code */ regs->psw.cc = sub_signed_long(&(regs->GR_G(r1)), regs->GR_G(r1), n); /* Program check if fixed-point overflow */ if ( regs->psw.cc == 3 && FOMASK(®s->psw) ) regs->program_interrupt (regs, PGM_FIXED_POINT_OVERFLOW_EXCEPTION); } /* end DEF_INST(subtract_long) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* B909 SGR - Subtract Long Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(subtract_long_register) { int r1, r2; /* Values of R fields */ RRE(inst, regs, r1, r2); /* Subtract signed operands and set condition code */ regs->psw.cc = sub_signed_long(&(regs->GR_G(r1)), regs->GR_G(r1), regs->GR_G(r2)); /* Program check if fixed-point overflow */ if ( regs->psw.cc == 3 && FOMASK(®s->psw) ) regs->program_interrupt (regs, PGM_FIXED_POINT_OVERFLOW_EXCEPTION); } /* end DEF_INST(subtract_long_register) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* B919 SGFR - Subtract Long Fullword Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(subtract_long_fullword_register) { int r1, r2; /* Values of R fields */ RRE(inst, regs, r1, r2); /* Subtract signed operands and set condition code */ regs->psw.cc = sub_signed_long(&(regs->GR_G(r1)), regs->GR_G(r1), (S32)regs->GR_L(r2)); /* Program check if fixed-point overflow */ if ( regs->psw.cc == 3 && FOMASK(®s->psw) ) regs->program_interrupt (regs, PGM_FIXED_POINT_OVERFLOW_EXCEPTION); } /* end DEF_INST(subtract_long_fullword_register) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* B908 AGR - Add Long Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(add_long_register) { int r1, r2; /* Values of R fields */ RRE(inst, regs, r1, r2); /* Add signed operands and set condition code */ regs->psw.cc = add_signed_long(&(regs->GR_G(r1)), regs->GR_G(r1), regs->GR_G(r2)); /* Program check if fixed-point overflow */ if ( regs->psw.cc == 3 && FOMASK(®s->psw) ) regs->program_interrupt (regs, PGM_FIXED_POINT_OVERFLOW_EXCEPTION); } /* end DEF_INST(add_long_register) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* B918 AGFR - Add Long Fullword Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(add_long_fullword_register) { int r1, r2; /* Values of R fields */ RRE(inst, regs, r1, r2); /* Add signed operands and set condition code */ regs->psw.cc = add_signed_long(&(regs->GR_G(r1)), regs->GR_G(r1), (S32)regs->GR_L(r2)); /* Program check if fixed-point overflow */ if ( regs->psw.cc == 3 && FOMASK(®s->psw) ) regs->program_interrupt (regs, PGM_FIXED_POINT_OVERFLOW_EXCEPTION); } /* end DEF_INST(add_long_fullword_register) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* B900 LPGR - Load Positive Long Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(load_positive_long_register) { int r1, r2; /* Values of R fields */ RRE(inst, regs, r1, r2); /* Condition code 3 and program check if overflow */ if ( regs->GR_G(r2) == 0x8000000000000000ULL ) { regs->GR_G(r1) = regs->GR_G(r2); regs->psw.cc = 3; if ( FOMASK(®s->psw) ) regs->program_interrupt (regs, PGM_FIXED_POINT_OVERFLOW_EXCEPTION); return; } /* Load positive value of second operand and set cc */ regs->GR_G(r1) = (S64)regs->GR_G(r2) < 0 ? -((S64)regs->GR_G(r2)) : (S64)regs->GR_G(r2); regs->psw.cc = (S64)regs->GR_G(r1) == 0 ? 0 : 2; } /* end DEF_INST(load_positive_long_register) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* B910 LPGFR - Load Positive Long Fullword Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(load_positive_long_fullword_register) { int r1, r2; /* Values of R fields */ S64 gpr2l; RRE0(inst, regs, r1, r2); gpr2l = (S32)regs->GR_L(r2); /* Load positive value of second operand and set cc */ regs->GR_G(r1) = gpr2l < 0 ? -gpr2l : gpr2l; regs->psw.cc = (S64)regs->GR_G(r1) == 0 ? 0 : 2; } /* end DEF_INST(load_positive_long_fullword_register) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* B901 LNGR - Load Negative Long Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(load_negative_long_register) { int r1, r2; /* Values of R fields */ RRE0(inst, regs, r1, r2); /* Load negative value of second operand and set cc */ regs->GR_G(r1) = (S64)regs->GR_G(r2) > 0 ? -((S64)regs->GR_G(r2)) : (S64)regs->GR_G(r2); regs->psw.cc = (S64)regs->GR_G(r1) == 0 ? 0 : 1; } /* end DEF_INST(load_negative_long_register) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* B911 LNGFR - Load Negative Long Fullword Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(load_negative_long_fullword_register) { int r1, r2; /* Values of R fields */ S64 gpr2l; RRE0(inst, regs, r1, r2); gpr2l = (S32)regs->GR_L(r2); /* Load negative value of second operand and set cc */ regs->GR_G(r1) = gpr2l > 0 ? -gpr2l : gpr2l; regs->psw.cc = (S64)regs->GR_G(r1) == 0 ? 0 : 1; } /* end DEF_INST(load_negative_long_fullword_register) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* B902 LTGR - Load and Test Long Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(load_and_test_long_register) { int r1, r2; /* Values of R fields */ RRE0(inst, regs, r1, r2); /* Copy second operand and set condition code */ regs->GR_G(r1) = regs->GR_G(r2); regs->psw.cc = (S64)regs->GR_G(r1) < 0 ? 1 : (S64)regs->GR_G(r1) > 0 ? 2 : 0; } /* end DEF_INST(load_and_test_long_register) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* B912 LTGFR - Load and Test Long Fullword Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(load_and_test_long_fullword_register) { int r1, r2; /* Values of R fields */ RRE0(inst, regs, r1, r2); /* Copy second operand and set condition code */ regs->GR_G(r1) = (S32)regs->GR_L(r2); regs->psw.cc = (S64)regs->GR_G(r1) < 0 ? 1 : (S64)regs->GR_G(r1) > 0 ? 2 : 0; } /* end DEF_INST(load_and_test_long_fullword_register) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* B903 LCGR - Load Complement Long Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(load_complement_long_register) { int r1, r2; /* Values of R fields */ RRE(inst, regs, r1, r2); /* Condition code 3 and program check if overflow */ if ( regs->GR_G(r2) == 0x8000000000000000ULL ) { regs->GR_G(r1) = regs->GR_G(r2); regs->psw.cc = 3; if ( FOMASK(®s->psw) ) regs->program_interrupt (regs, PGM_FIXED_POINT_OVERFLOW_EXCEPTION); return; } /* Load complement of second operand and set condition code */ regs->GR_G(r1) = -((S64)regs->GR_G(r2)); regs->psw.cc = (S64)regs->GR_G(r1) < 0 ? 1 : (S64)regs->GR_G(r1) > 0 ? 2 : 0; } /* end DEF_INST(load_complement_long_register) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* B913 LCGFR - Load Complement Long Fullword Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(load_complement_long_fullword_register) { int r1, r2; /* Values of R fields */ S64 gpr2l; RRE0(inst, regs, r1, r2); gpr2l = (S32)regs->GR_L(r2); /* Load complement of second operand and set condition code */ regs->GR_G(r1) = -gpr2l; regs->psw.cc = (S64)regs->GR_G(r1) < 0 ? 1 : (S64)regs->GR_G(r1) > 0 ? 2 : 0; } /* end DEF_INST(load_complement_long_fullword_register) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* A7x2 TMHH - Test under Mask High High [RI] */ /*-------------------------------------------------------------------*/ DEF_INST(test_under_mask_high_high) { int r1; /* Register number */ int opcd; /* Opcode */ U16 i2; /* 16-bit operand values */ U16 h1; /* 16-bit operand values */ U16 h2; /* 16-bit operand values */ RI0(inst, regs, r1, opcd, i2); /* AND register bits 0-15 with immediate operand */ h1 = i2 & regs->GR_HHH(r1); /* Isolate leftmost bit of immediate operand */ for ( h2 = 0x8000; h2 != 0 && (h2 & i2) == 0; h2 >>= 1 ); /* Set condition code according to result */ regs->psw.cc = ( h1 == 0 ) ? 0 : /* result all zeroes */ ( h1 == i2) ? 3 : /* result all ones */ ((h1 & h2) == 0) ? 1 : /* leftmost bit zero */ 2; /* leftmost bit one */ } /* end DEF_INST(test_under_mask_high_high) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* A7x3 TMHL - Test under Mask High Low [RI] */ /*-------------------------------------------------------------------*/ DEF_INST(test_under_mask_high_low) { int r1; /* Register number */ int opcd; /* Opcode */ U16 i2; /* 16-bit operand values */ U16 h1; /* 16-bit operand values */ U16 h2; /* 16-bit operand values */ RI0(inst, regs, r1, opcd, i2); /* AND register bits 16-31 with immediate operand */ h1 = i2 & regs->GR_HHL(r1); /* Isolate leftmost bit of immediate operand */ for ( h2 = 0x8000; h2 != 0 && (h2 & i2) == 0; h2 >>= 1 ); /* Set condition code according to result */ regs->psw.cc = ( h1 == 0 ) ? 0 : /* result all zeroes */ ( h1 == i2) ? 3 : /* result all ones */ ((h1 & h2) == 0) ? 1 : /* leftmost bit zero */ 2; /* leftmost bit one */ } /* end DEF_INST(test_under_mask_high_low) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* A7x7 BRCTG - Branch Relative on Count Long [RI] */ /*-------------------------------------------------------------------*/ DEF_INST(branch_relative_on_count_long) { int r1; /* Register number */ int opcd; /* Opcode */ U16 i2; /* 16-bit operand values */ RI_B(inst, regs, r1, opcd, i2); /* Subtract 1 from the R1 operand and branch if non-zero */ if ( --(regs->GR_G(r1)) ) SUCCESSFUL_RELATIVE_BRANCH(regs, 2*(S16)i2, 4); else INST_UPDATE_PSW(regs, 4, 0); } /* end DEF_INST(branch_relative_on_count_long) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* E321 CLG - Compare Logical long [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_logical_long) { int r1; /* Values of R fields */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ U64 n; /* 64-bit operand values */ RXY(inst, regs, r1, b2, effective_addr2); /* Load second operand from operand address */ n = ARCH_DEP(vfetch8) ( effective_addr2, b2, regs ); /* Compare unsigned operands and set condition code */ regs->psw.cc = regs->GR_G(r1) < n ? 1 : regs->GR_G(r1) > n ? 2 : 0; } /* end DEF_INST(compare_logical_long) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* E331 CLGF - Compare Logical long fullword [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_logical_long_fullword) { int r1; /* Values of R fields */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ U32 n; /* 32-bit operand values */ RXY(inst, regs, r1, b2, effective_addr2); /* Load second operand from operand address */ n = ARCH_DEP(vfetch4) ( effective_addr2, b2, regs ); /* Compare unsigned operands and set condition code */ regs->psw.cc = regs->GR_G(r1) < n ? 1 : regs->GR_G(r1) > n ? 2 : 0; } /* end DEF_INST(compare_logical_long_fullword) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* B931 CLGFR - Compare Logical Long Fullword Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_logical_long_fullword_register) { int r1, r2; /* Values of R fields */ RRE0(inst, regs, r1, r2); /* Compare unsigned operands and set condition code */ regs->psw.cc = regs->GR_G(r1) < regs->GR_L(r2) ? 1 : regs->GR_G(r1) > regs->GR_L(r2) ? 2 : 0; } /* end DEF_INST(compare_logical_long_fullword_register) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* B917 LLGTR - Load Logical Long Thirtyone Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(load_logical_long_thirtyone_register) { int r1, r2; /* Values of R fields */ RRE0(inst, regs, r1, r2); regs->GR_G(r1) = regs->GR_L(r2) & 0x7FFFFFFF; } /* end DEF_INST(load_logical_long_thirtyone_register) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* B921 CLGR - Compare Logical Long Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_logical_long_register) { int r1, r2; /* Values of R fields */ RRE0(inst, regs, r1, r2); /* Compare unsigned operands and set condition code */ regs->psw.cc = regs->GR_G(r1) < regs->GR_G(r2) ? 1 : regs->GR_G(r1) > regs->GR_G(r2) ? 2 : 0; } /* end DEF_INST(compare_logical_long_register) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* EB1C RLLG - Rotate Left Single Logical Long [RSY] */ /*-------------------------------------------------------------------*/ DEF_INST(rotate_left_single_logical_long) { int r1, r3; /* Register numbers */ int b2; /* effective address base */ VADR effective_addr2; /* effective address */ U64 n; /* Integer work areas */ RSY0(inst, regs, r1, r3, b2, effective_addr2); /* Use rightmost six bits of operand address as shift count */ n = effective_addr2 & 0x3F; /* Rotate and copy contents of r3 to r1 */ regs->GR_G(r1) = (regs->GR_G(r3) << n) | ((n == 0) ? 0 : (regs->GR_G(r3) >> (64 - n))); } /* end DEF_INST(rotate_left_single_logical_long) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* EB1D RLL - Rotate Left Single Logical [RSY] */ /*-------------------------------------------------------------------*/ DEF_INST(rotate_left_single_logical) { int r1, r3; /* Register numbers */ int b2; /* effective address base */ VADR effective_addr2; /* effective address */ U64 n; /* Integer work areas */ RSY0(inst, regs, r1, r3, b2, effective_addr2); /* Use rightmost five bits of operand address as shift count */ n = effective_addr2 & 0x1F; /* Rotate and copy contents of r3 to r1 */ regs->GR_L(r1) = (regs->GR_L(r3) << n) | ((n == 0) ? 0 : (regs->GR_L(r3) >> (32 - n))); } /* end DEF_INST(rotate_left_single_logical) */ #endif /*defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* EB0D SLLG - Shift Left Single Logical Long [RSY] */ /*-------------------------------------------------------------------*/ DEF_INST(shift_left_single_logical_long) { int r1, r3; /* Register numbers */ int b2; /* effective address base */ VADR effective_addr2; /* effective address */ U64 n; /* Integer work areas */ RSY0(inst, regs, r1, r3, b2, effective_addr2); /* Use rightmost six bits of operand address as shift count */ n = effective_addr2 & 0x3F; /* Copy contents of r3 to r1 and perform shift */ regs->GR_G(r1) = regs->GR_G(r3) << n; } /* end DEF_INST(shift_left_single_logical_long) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* EB0C SRLG - Shift Right Single Logical Long [RSY] */ /*-------------------------------------------------------------------*/ DEF_INST(shift_right_single_logical_long) { int r1, r3; /* Register numbers */ int b2; /* effective address base */ VADR effective_addr2; /* effective address */ U64 n; /* Integer work areas */ RSY0(inst, regs, r1, r3, b2, effective_addr2); /* Use rightmost six bits of operand address as shift count */ n = effective_addr2 & 0x3F; /* Copy contents of r3 to r1 and perform shift */ regs->GR_G(r1) = regs->GR_G(r3) >> n; } /* end DEF_INST(shift_right_single_logical_long) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* EB0B SLAG - Shift Left Single Long [RSY] */ /*-------------------------------------------------------------------*/ DEF_INST(shift_left_single_long) { U32 r1, r3; /* Register numbers */ U32 b2; /* effective address base */ VADR effective_addr2; /* effective address */ U64 n, n1, n2; /* 64-bit operand values */ U32 i, j; /* Integer work areas */ RSY(inst, regs, r1, r3, b2, effective_addr2); /* Use rightmost six bits of operand address as shift count */ n = effective_addr2 & 0x3F; /* Load the numeric and sign portions from the R3 register */ n1 = regs->GR_G(r3) & 0x7FFFFFFFFFFFFFFFULL; n2 = regs->GR_G(r3) & 0x8000000000000000ULL; /* Shift the numeric portion left n positions */ for (i = 0, j = 0; i < n; i++) { /* Shift bits 1-63 left one bit position */ n1 <<= 1; /* Overflow if bit shifted out is unlike the sign bit */ if ((n1 & 0x8000000000000000ULL) != n2) j = 1; } /* Load the updated value into the R1 register */ regs->GR_G(r1) = (n1 & 0x7FFFFFFFFFFFFFFFULL) | n2; /* Condition code 3 and program check if overflow occurred */ if (j) { regs->psw.cc = 3; if ( FOMASK(®s->psw) ) regs->program_interrupt (regs, PGM_FIXED_POINT_OVERFLOW_EXCEPTION); return; } /* Set the condition code */ regs->psw.cc = (S64)regs->GR_G(r1) > 0 ? 2 : (S64)regs->GR_G(r1) < 0 ? 1 : 0; } /* end DEF_INST(shift_left_single_long) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* EB0A SRAG - Shift Right Single Long [RSY] */ /*-------------------------------------------------------------------*/ DEF_INST(shift_right_single_long) { int r1, r3; /* Register numbers */ int b2; /* effective address base */ VADR effective_addr2; /* effective address */ U64 n; /* Integer work areas */ RSY0(inst, regs, r1, r3, b2, effective_addr2); /* Use rightmost six bits of operand address as shift count */ n = effective_addr2 & 0x3F; /* Copy and shift the signed value of the R3 register */ regs->GR_G(r1) = (n > 62) ? ((S64)regs->GR_G(r3) < 0 ? -1LL : 0) : (S64)regs->GR_G(r3) >> n; /* Set the condition code */ regs->psw.cc = (S64)regs->GR_G(r1) > 0 ? 2 : (S64)regs->GR_G(r1) < 0 ? 1 : 0; } /* end DEF_INST(shift_right_single_long) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* E31C MSGF - Multiply Single Long Fullword [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(multiply_single_long_fullword) { int r1; /* Value of R field */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ U32 n; /* 32-bit operand values */ RXY(inst, regs, r1, b2, effective_addr2); /* Load second operand from operand address */ n = ARCH_DEP(vfetch4) ( effective_addr2, b2, regs ); /* Multiply signed operands ignoring overflow */ regs->GR_G(r1) = (S64)regs->GR_G(r1) * (S32)n; } /* end DEF_INST(multiply_single_long_fullword) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* E30C MSG - Multiply Single Long [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(multiply_single_long) { int r1; /* Value of R field */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ U64 n; /* 64-bit operand values */ RXY(inst, regs, r1, b2, effective_addr2); /* Load second operand from operand address */ n = ARCH_DEP(vfetch8) ( effective_addr2, b2, regs ); /* Multiply signed operands ignoring overflow */ regs->GR_G(r1) = (S64)regs->GR_G(r1) * (S64)n; } /* end DEF_INST(multiply_single_long) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* B91C MSGFR - Multiply Single Long Fullword Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(multiply_single_long_fullword_register) { int r1, r2; /* Values of R fields */ RRE0(inst, regs, r1, r2); /* Multiply signed registers ignoring overflow */ regs->GR_G(r1) = (S64)regs->GR_G(r1) * (S32)regs->GR_L(r2); } /* end DEF_INST(multiply_single_long_fullword_register) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* B90C MSGR - Multiply Single Long Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(multiply_single_long_register) { int r1, r2; /* Values of R fields */ RRE0(inst, regs, r1, r2); /* Multiply signed registers ignoring overflow */ regs->GR_G(r1) = (S64)regs->GR_G(r1) * (S64)regs->GR_G(r2); } /* end DEF_INST(multiply_single_long_register) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* A7x9 LGHI - Load Long Halfword Immediate [RI] */ /*-------------------------------------------------------------------*/ DEF_INST(load_long_halfword_immediate) { int r1; /* Register number */ int opcd; /* Opcode */ U16 i2; /* 16-bit operand values */ RI0(inst, regs, r1, opcd, i2); /* Load operand into register */ regs->GR_G(r1) = (S16)i2; } /* end DEF_INST(load_long_halfword_immediate) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* A7xB AGHI - Add Long Halfword Immediate [RI] */ /*-------------------------------------------------------------------*/ DEF_INST(add_long_halfword_immediate) { int r1; /* Register number */ int opcd; /* Opcode */ U16 i2; /* 16-bit immediate op */ RI(inst, regs, r1, opcd, i2); /* Add signed operands and set condition code */ regs->psw.cc = add_signed_long(&(regs->GR_G(r1)), regs->GR_G(r1), (S16)i2); /* Program check if fixed-point overflow */ if ( regs->psw.cc == 3 && FOMASK(®s->psw) ) regs->program_interrupt (regs, PGM_FIXED_POINT_OVERFLOW_EXCEPTION); } /* end DEF_INST(add_long_halfword_immediate) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* A7xD MGHI - Multiply Long Halfword Immediate [RI] */ /*-------------------------------------------------------------------*/ DEF_INST(multiply_long_halfword_immediate) { int r1; /* Register number */ int opcd; /* Opcode */ U16 i2; /* 16-bit operand */ RI0(inst, regs, r1, opcd, i2); /* Multiply register by operand ignoring overflow */ regs->GR_G(r1) = (S64)regs->GR_G(r1) * (S16)i2; } /* end DEF_INST(multiply_long_halfword_immediate) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* A7xF CGHI - Compare Long Halfword Immediate [RI] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_long_halfword_immediate) { int r1; /* Register number */ int opcd; /* Opcode */ U16 i2; /* 16-bit operand */ RI0(inst, regs, r1, opcd, i2); /* Compare signed operands and set condition code */ regs->psw.cc = (S64)regs->GR_G(r1) < (S16)i2 ? 1 : (S64)regs->GR_G(r1) > (S16)i2 ? 2 : 0; } /* end DEF_INST(compare_long_halfword_immediate) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* B980 NGR - And Register Long [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(and_long_register) { int r1, r2; /* Values of R fields */ RRE0(inst, regs, r1, r2); /* AND second operand with first and set condition code */ regs->psw.cc = ( regs->GR_G(r1) &= regs->GR_G(r2) ) ? 1 : 0; } /* end DEF_INST(and_long_register) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* B981 OGR - Or Register Long [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(or_long_register) { int r1, r2; /* Values of R fields */ RRE0(inst, regs, r1, r2); /* OR second operand with first and set condition code */ regs->psw.cc = ( regs->GR_G(r1) |= regs->GR_G(r2) ) ? 1 : 0; } /* end DEF_INST(or_long_register) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* B982 XGR - Exclusive Or Register Long [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(exclusive_or_long_register) { int r1, r2; /* Values of R fields */ RRE0(inst, regs, r1, r2); /* XOR second operand with first and set condition code */ regs->psw.cc = ( regs->GR_G(r1) ^= regs->GR_G(r2) ) ? 1 : 0; } /* end DEF_INST(exclusive_or_long_register) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* E380 NG - And Long [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(and_long) { int r1; /* Value of R field */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ U64 n; /* 64-bit operand values */ RXY(inst, regs, r1, b2, effective_addr2); /* Load second operand from operand address */ n = ARCH_DEP(vfetch8) ( effective_addr2, b2, regs ); /* AND second operand with first and set condition code */ regs->psw.cc = ( regs->GR_G(r1) &= n ) ? 1 : 0; } /* end DEF_INST(and_long) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* E381 OG - Or Long [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(or_long) { int r1; /* Value of R field */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ U64 n; /* 64-bit operand values */ RXY(inst, regs, r1, b2, effective_addr2); /* Load second operand from operand address */ n = ARCH_DEP(vfetch8) ( effective_addr2, b2, regs ); /* OR second operand with first and set condition code */ regs->psw.cc = ( regs->GR_G(r1) |= n ) ? 1 : 0; } /* end DEF_INST(or_long) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* E382 XG - Exclusive Or Long [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(exclusive_or_long) { int r1; /* Values of R fields */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ U64 n; /* 64-bit operand values */ RXY(inst, regs, r1, b2, effective_addr2); /* Load second operand from operand address */ n = ARCH_DEP(vfetch8) ( effective_addr2, b2, regs ); /* XOR second operand with first and set condition code */ regs->psw.cc = ( regs->GR_G(r1) ^= n ) ? 1 : 0; } /* end DEF_INST(exclusive_or_long) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* B904 LGR - Load Long Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(load_long_register) { int r1, r2; /* Values of R fields */ RRE0(inst, regs, r1, r2); /* Copy second operand to first operand */ regs->GR_G(r1) = regs->GR_G(r2); } /* end DEF_INST(load_long_register) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* B916 LLGFR - Load Logical Long Fullword Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(load_logical_long_fullword_register) { int r1, r2; /* Values of R fields */ RRE0(inst, regs, r1, r2); /* Copy second operand to first operand */ regs->GR_G(r1) = regs->GR_L(r2); } /* end DEF_INST(load_logical_long_fullword_register) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* B914 LGFR - Load Long Fullword Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(load_long_fullword_register) { int r1, r2; /* Values of R fields */ RRE0(inst, regs, r1, r2); /* Copy second operand to first operand */ regs->GR_G(r1) = (S32)regs->GR_L(r2); } /* end DEF_INST(load_long_fullword_register) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* B90A ALGR - Add Logical Register Long [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(add_logical_long_register) { int r1, r2; /* Values of R fields */ RRE0(inst, regs, r1, r2); /* Add unsigned operands and set condition code */ regs->psw.cc = add_logical_long(&(regs->GR_G(r1)), regs->GR_G(r1), regs->GR_G(r2)); } /* end DEF_INST(add_logical_long_register) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* B91A ALGFR - Add Logical Long Fullword Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(add_logical_long_fullword_register) { int r1, r2; /* Values of R fields */ RRE0(inst, regs, r1, r2); /* Add unsigned operands and set condition code */ regs->psw.cc = add_logical_long(&(regs->GR_G(r1)), regs->GR_G(r1), regs->GR_L(r2)); } /* end DEF_INST(add_logical_long_fullword_register) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* B91B SLGFR - Subtract Logical Long Fullword Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(subtract_logical_long_fullword_register) { int r1, r2; /* Values of R fields */ RRE0(inst, regs, r1, r2); /* Subtract unsigned operands and set condition code */ regs->psw.cc = sub_logical_long(&(regs->GR_G(r1)), regs->GR_G(r1), regs->GR_L(r2)); } /* end DEF_INST(subtract_logical_long_fullword_register) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* B90B SLGR - Subtract Logical Register Long [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(subtract_logical_long_register) { int r1, r2; /* Values of R fields */ RRE0(inst, regs, r1, r2); /* Subtract unsigned operands and set condition code */ regs->psw.cc = sub_logical_long(&(regs->GR_G(r1)), regs->GR_G(r1), regs->GR_G(r2)); } /* end DEF_INST(subtract_logical_long_register) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* EF LMD - Load Multiple Disjoint [SS] */ /*-------------------------------------------------------------------*/ DEF_INST(load_multiple_disjoint) { int r1, r3; /* Register numbers */ int b2, b4; /* Base register numbers */ VADR effective_addr2; /* Operand2 address */ VADR effective_addr4; /* Operand4 address */ int i, n; /* Integer work areas */ U32 rwork1[16], rwork2[16]; /* Intermediate work areas */ SS(inst, regs, r1, r3, b2, effective_addr2, b4, effective_addr4); n = ((r3 - r1) & 0xF) + 1; ARCH_DEP(vfetchc) (rwork1, (n * 4) - 1, effective_addr2, b2, regs); ARCH_DEP(vfetchc) (rwork2, (n * 4) - 1, effective_addr4, b4, regs); /* Load a register at a time */ for (i = 0; i < n; i++) { regs->GR_H((r1 + i) & 0xF) = fetch_fw(&rwork1[i]); regs->GR_L((r1 + i) & 0xF) = fetch_fw(&rwork2[i]); } } /* end DEF_INST(load_multiple_disjoint) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* EB96 LMH - Load Multiple High [RSY] */ /*-------------------------------------------------------------------*/ DEF_INST(load_multiple_high) { int r1, r3; /* Register numbers */ int b2; /* effective address base */ VADR effective_addr2; /* effective address */ int i, m, n; /* Integer work areas */ U32 *p1, *p2; /* Mainstor pointers */ RSY(inst, regs, r1, r3, b2, effective_addr2); /* Calculate number of bytes to load */ n = (((r3 - r1) & 0xF) + 1) << 2; /* Calculate number of bytes to next boundary */ m = 0x800 - ((VADR_L)effective_addr2 & 0x7ff); /* Address of operand beginning */ p1 = (U32*)MADDR(effective_addr2, b2, regs, ACCTYPE_READ, regs->psw.pkey); if (likely(n <= m)) { /* Boundary not crossed */ n >>= 2; for (i = 0; i < n; i++, p1++) regs->GR_H((r1 + i) & 0xF) = fetch_fw (p1); } else { /* Boundary crossed, get 2nd page address */ effective_addr2 += m; effective_addr2 &= ADDRESS_MAXWRAP(regs); p2 = (U32*)MADDR(effective_addr2, b2, regs, ACCTYPE_READ, regs->psw.pkey); if (likely((m & 0x3) == 0)) { /* Addresses are word aligned */ m >>= 2; for (i = 0; i < m; i++, p1++) regs->GR_H((r1 + i) & 0xF) = fetch_fw (p1); n >>= 2; for ( ; i < n; i++, p2++) regs->GR_H((r1 + i) & 0xF) = fetch_fw (p2); } else { /* Worst case */ U32 rwork[16]; BYTE *b1, *b2; b1 = (BYTE *)&rwork[0]; b2 = (BYTE *)p1; for (i = 0; i < m; i++) *b1++ = *b2++; b2 = (BYTE *)p2; for ( ; i < n; i++) *b1++ = *b2++; n >>= 2; for (i = 0; i < n; i++) regs->GR_H((r1 + i) & 0xF) = CSWAP32(rwork[i]); } } } /* end DEF_INST(load_multiple_high) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* EB04 LMG - Load Multiple Long [RSY] */ /*-------------------------------------------------------------------*/ DEF_INST(load_multiple_long) { int r1, r3; /* Register numbers */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ int i, m, n; /* Integer work areas */ U64 *p1, *p2; /* Mainstor pointers */ BYTE *bp1; /* Unaligned Mainstor ptr */ RSY(inst, regs, r1, r3, b2, effective_addr2); /* Calculate number of bytes to load */ n = (((r3 - r1) & 0xF) + 1) << 3; /* Calculate number of bytes to next boundary */ m = 0x800 - ((VADR_L)effective_addr2 & 0x7ff); /* Address of operand beginning */ bp1 = (BYTE*)MADDR(effective_addr2, b2, regs, ACCTYPE_READ, regs->psw.pkey); p1=(U64*)bp1; if (likely(n <= m)) { /* Boundary not crossed */ n >>= 3; #if defined(OPTION_STRICT_ALIGNMENT) if(likely(!(((uintptr_t)effective_addr2)&0x07))) { #endif #if defined(OPTION_SINGLE_CPU_DW) && defined(ASSIST_STORE_DW) if (regs->cpubit == regs->sysblk->started_mask) for (i = 0; i < n; i++, p1++) regs->GR_G((r1 + i) & 0xF) = CSWAP64(*p1); else #endif for (i = 0; i < n; i++, p1++) regs->GR_G((r1 + i) & 0xF) = fetch_dw (p1); #if defined(OPTION_STRICT_ALIGNMENT) } else { for (i = 0; i < n; i++, bp1+=8) regs->GR_G((r1 + i) & 0xF) = fetch_dw (bp1); } #endif } else { /* Boundary crossed, get 2nd page address */ effective_addr2 += m; effective_addr2 &= ADDRESS_MAXWRAP(regs); p2 = (U64*)MADDR(effective_addr2, b2, regs, ACCTYPE_READ, regs->psw.pkey); if (likely((m & 0x7) == 0)) { /* FIXME: This code blows up on at least Mac OS X Snow Leopard (10.6) when compiled for a 32-bit Intel host using gcc 4.2.1 unless the PTT call below is present. The problem appears to be in the gcc 4.2.1 optimizer, as the code works when compiled with -O0. DO NOT REMOVE this until it's been found and fixed. -- JRM, 11 Feb 2010 */ // PTT(PTT_CL_INF,"LMG2KIN",p2,0,0); /* Addresses are double-word aligned */ m >>= 3; for (i = 0; i < m; i++, p1++) regs->GR_G((r1 + i) & 0xF) = fetch_dw (p1); n >>= 3; for ( ; i < n; i++, p2++) regs->GR_G((r1 + i) & 0xF) = fetch_dw (p2); } else { /* Worst case */ U64 rwork[16]; BYTE *b1, *b2; b1 = (BYTE *)&rwork[0]; b2 = (BYTE *)p1; for (i = 0; i < m; i++) *b1++ = *b2++; b2 = (BYTE *)p2; for ( ; i < n; i++) *b1++ = *b2++; n >>= 3; for (i = 0; i < n; i++) regs->GR_G((r1 + i) & 0xF) = CSWAP64(rwork[i]); } } } /* end DEF_INST(load_multiple_long) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* EB25 STCTG - Store Control Long [RSY] */ /*-------------------------------------------------------------------*/ DEF_INST(store_control_long) { int r1, r3; /* Register numbers */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ int i, m, n; /* Integer work areas */ U64 *p1, *p2 = NULL; /* Mainstor pointers */ RSY(inst, regs, r1, r3, b2, effective_addr2); PRIV_CHECK(regs); DW_CHECK(effective_addr2, regs); #if defined(_FEATURE_ZSIE) if(SIE_STATB(regs, IC1, STCTL)) longjmp(regs->progjmp, SIE_INTERCEPT_INST); #endif /*defined(_FEATURE_ZSIE)*/ /* Calculate number of regs to store */ n = ((r3 - r1) & 0xF) + 1; /* Calculate number of double words to next boundary */ m = (0x800 - (effective_addr2 & 0x7ff)) >> 3; /* Address of operand beginning */ p1 = (U64*)MADDR(effective_addr2, b2, regs, ACCTYPE_WRITE, regs->psw.pkey); /* Get address of next page if boundary crossed */ if (unlikely (m < n)) p2 = (U64*)MADDR(effective_addr2 + (m*8), b2, regs, ACCTYPE_WRITE, regs->psw.pkey); else m = n; /* Store to first page */ for (i = 0; i < m; i++) store_dw(p1++, regs->CR_G((r1 + i) & 0xF)); /* Store to next page */ for ( ; i < n; i++) store_dw(p2++, regs->CR_G((r1 + i) & 0xF)); } /* end DEF_INST(store_control_long) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* EB2F LCTLG - Load Control Long [RSY] */ /*-------------------------------------------------------------------*/ DEF_INST(load_control_long) { int r1, r3; /* Register numbers */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ int i, m, n; /* Integer work areas */ U64 *p1, *p2 = NULL; /* Mainstor pointers */ U16 updated = 0; /* Updated control regs */ RSY(inst, regs, r1, r3, b2, effective_addr2); PRIV_CHECK(regs); DW_CHECK(effective_addr2, regs); /* Calculate number of regs to load */ n = ((r3 - r1) & 0xF) + 1; #if defined(_FEATURE_ZSIE) if ( SIE_MODE(regs) ) { U16 cr_mask = fetch_hw (regs->siebk->lctl_ctl); for (i = 0; i < n; i++) if (cr_mask & BIT(15 - ((r1 + i) & 0xF))) longjmp(regs->progjmp, SIE_INTERCEPT_INST); } #endif /* Calculate number of double words to next boundary */ m = (0x800 - (effective_addr2 & 0x7ff)) >> 3; /* Address of operand beginning */ p1 = (U64*)MADDR(effective_addr2, b2, regs, ACCTYPE_READ, regs->psw.pkey); /* Get address of next page if boundary crossed */ if (unlikely (m < n)) p2 = (U64*)MADDR(effective_addr2 + (m*8), b2, regs, ACCTYPE_READ, regs->psw.pkey); else m = n; /* Load from first page */ for (i = 0; i < m; i++, p1++) { regs->CR_G((r1 + i) & 0xF) = fetch_dw(p1); updated |= BIT((r1 + i) & 0xF); } /* Load from next page */ for ( ; i < n; i++, p2++) { regs->CR_G((r1 + i) & 0xF) = fetch_dw(p2); updated |= BIT((r1 + i) & 0xF); } /* Actions based on updated control regs */ SET_IC_MASK(regs); if (updated & (BIT(1) | BIT(7) | BIT(13))) SET_AEA_COMMON(regs); if (updated & BIT(regs->aea_ar[USE_INST_SPACE])) INVALIDATE_AIA(regs); if (updated & BIT(9)) { OBTAIN_INTLOCK(regs); SET_IC_PER(regs); RELEASE_INTLOCK(regs); if (EN_IC_PER_SA(regs)) ARCH_DEP(invalidate_tlb)(regs,~(ACC_WRITE|ACC_CHECK)); } RETURN_INTCHECK(regs); } /* end DEF_INST(load_control_long) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* EB24 STMG - Store Multiple Long [RSY] */ /*-------------------------------------------------------------------*/ DEF_INST(store_multiple_long) { int r1, r3; /* Register numbers */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ int i, m, n; /* Integer work areas */ U64 *p1, *p2; /* Mainstor pointers */ BYTE *bp1; /* Unaligned Mainstor ptr */ RSY(inst, regs, r1, r3, b2, effective_addr2); /* Calculate number of bytes to store */ n = (((r3 - r1) & 0xF) + 1) << 3; /* Calculate number of bytes to next boundary */ m = 0x800 - ((VADR_L)effective_addr2 & 0x7ff); /* Get address of first page */ bp1 = (BYTE*)MADDR(effective_addr2, b2, regs, ACCTYPE_WRITE, regs->psw.pkey); p1=(U64*)bp1; if (likely(n <= m)) { /* Boundary not crossed */ n >>= 3; #if defined(OPTION_STRICT_ALIGNMENT) if(likely(!(((uintptr_t)effective_addr2)&0x07))) { #endif #if defined(OPTION_SINGLE_CPU_DW) && defined(ASSIST_STORE_DW) if (regs->cpubit == regs->sysblk->started_mask) for (i = 0; i < n; i++) *p1++ = CSWAP64(regs->GR_G((r1 + i) & 0xF)); else #endif for (i = 0; i < n; i++) store_dw (p1++, regs->GR_G((r1 + i) & 0xF)); #if defined(OPTION_STRICT_ALIGNMENT) } else { for (i = 0; i < n; i++,bp1+=8) store_dw (bp1, regs->GR_G((r1 + i) & 0xF)); } #endif } if (likely(n <= m)) { /* boundary not crossed */ n >>= 3; } else { /* boundary crossed, get address of the 2nd page */ effective_addr2 += m; effective_addr2 &= ADDRESS_MAXWRAP(regs); p2 = (U64*)MADDR(effective_addr2, b2, regs, ACCTYPE_WRITE, regs->psw.pkey); if (likely((m & 0x7) == 0)) { /* double word aligned */ m >>= 3; for (i = 0; i < m; i++) store_dw (p1++, regs->GR_G((r1 + i) & 0xF)); n >>= 3; for ( ; i < n; i++) store_dw (p2++, regs->GR_G((r1 + i) & 0xF)); } else { /* worst case */ U64 rwork[16]; BYTE *b1, *b2; for (i = 0; i < (n >> 3); i++) rwork[i] = CSWAP64(regs->GR_G((r1 + i) & 0xF)); b1 = (BYTE *)&rwork[0]; b2 = (BYTE *)p1; for (i = 0; i < m; i++) *b2++ = *b1++; b2 = (BYTE *)p2; for ( ; i < n; i++) *b2++ = *b1++; } } } /* end DEF_INST(store_multiple_long) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* EB26 STMH - Store Multiple High [RSY] */ /*-------------------------------------------------------------------*/ DEF_INST(store_multiple_high) { int r1, r3; /* Register numbers */ int b2; /* effective address base */ VADR effective_addr2; /* effective address */ int i, m, n; /* Integer work areas */ U32 *p1, *p2; /* Mainstor pointers */ RSY(inst, regs, r1, r3, b2, effective_addr2); /* Calculate number of bytes to store */ n = (((r3 - r1) & 0xF) + 1) << 2; /* Calculate number of bytes to next boundary */ m = 0x800 - ((VADR_L)effective_addr2 & 0x7ff); /* Get address of first page */ p1 = (U32*)MADDR(effective_addr2, b2, regs, ACCTYPE_WRITE, regs->psw.pkey); if (likely(n <= m)) { /* boundary not crossed */ n >>= 2; for (i = 0; i < n; i++) store_fw (p1++, regs->GR_H((r1 + i) & 0xF)); } else { /* boundary crossed, get address of the 2nd page */ effective_addr2 += m; effective_addr2 &= ADDRESS_MAXWRAP(regs); p2 = (U32*)MADDR(effective_addr2, b2, regs, ACCTYPE_WRITE, regs->psw.pkey); if (likely((m & 0x3) == 0)) { /* word aligned */ m >>= 2; for (i = 0; i < m; i++) store_fw (p1++, regs->GR_H((r1 + i) & 0xF)); n >>= 2; for ( ; i < n; i++) store_fw (p2++, regs->GR_H((r1 + i) & 0xF)); } else { /* worst case */ U32 rwork[16]; BYTE *b1, *b2; for (i = 0; i < (n >> 2); i++) rwork[i] = CSWAP32(regs->GR_H((r1 + i) & 0xF)); b1 = (BYTE *)&rwork[0]; b2 = (BYTE *)p1; for (i = 0; i < m; i++) *b2++ = *b1++; b2 = (BYTE *)p2; for ( ; i < n; i++) *b2++ = *b1++; } } } /* end DEF_INST(store_multiple_high) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* B905 LURAG - Load Using Real Address Long [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(load_using_real_address_long) { int r1, r2; /* Values of R fields */ RADR n; /* Unsigned work */ RRE(inst, regs, r1, r2); PRIV_CHECK(regs); /* R2 register contains operand real storage address */ n = regs->GR_G(r2) & ADDRESS_MAXWRAP(regs); /* Program check if operand not on doubleword boundary */ DW_CHECK(n, regs); /* Load R1 register from second operand */ regs->GR_G(r1) = ARCH_DEP(vfetch8) ( n, USE_REAL_ADDR, regs ); } /* end DEF_INST(load_using_real_address_long) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* B925 STURG - Store Using Real Address Long [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(store_using_real_address_long) { int r1, r2; /* Values of R fields */ RADR n; /* Unsigned work */ RRE(inst, regs, r1, r2); PRIV_CHECK(regs); /* R2 register contains operand real storage address */ n = regs->GR_G(r2) & ADDRESS_MAXWRAP(regs); /* Program check if operand not on doubleword boundary */ DW_CHECK(n, regs); /* Store R1 register at second operand location */ ARCH_DEP(vstore8) (regs->GR_G(r1), n, USE_REAL_ADDR, regs ); #if defined(FEATURE_PER2) /* Storage alteration must be enabled for STURA to be recognised */ if( EN_IC_PER_SA(regs) && EN_IC_PER_STURA(regs) ) { ON_IC_PER_SA(regs) ; ON_IC_PER_STURA(regs) ; } #endif /*defined(FEATURE_PER2)*/ } /* end DEF_INST(store_using_real_address_long) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* 010B TAM - Test Addressing Mode [E] */ /*-------------------------------------------------------------------*/ DEF_INST(test_addressing_mode) { E(inst, regs); UNREFERENCED(inst); regs->psw.cc = #if defined(FEATURE_ESAME) (regs->psw.amode64 << 1) | #endif /*defined(FEATURE_ESAME)*/ regs->psw.amode; } /* end DEF_INST(test_addressing_mode) */ #endif /*defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* 010C SAM24 - Set Addressing Mode 24 [E] */ /*-------------------------------------------------------------------*/ DEF_INST(set_addressing_mode_24) { VADR ia = PSW_IA(regs, 0); /* Unupdated instruction addr*/ E(inst, regs); UNREFERENCED(inst); /* Set the bear register */ SET_BEAR_REG(regs, regs->bear_ip); /* Program check if instruction is located above 16MB */ if (ia > 0xFFFFFFULL) regs->program_interrupt (regs, PGM_SPECIFICATION_EXCEPTION); #if defined(FEATURE_ESAME) /* Add a mode trace entry when switching in/out of 64 bit mode */ if((regs->CR(12) & CR12_MTRACE) && regs->psw.amode64) regs->CR(12) = ARCH_DEP(trace_ms) (0, 0, regs); #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) regs->psw.amode64 = #endif /*defined(FEATURE_ESAME)*/ regs->psw.amode = 0; regs->psw.AMASK = AMASK24; } /* end DEF_INST(set_addressing_mode_24) */ #endif /*defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* 010D SAM31 - Set Addressing Mode 31 [E] */ /*-------------------------------------------------------------------*/ DEF_INST(set_addressing_mode_31) { VADR ia = PSW_IA(regs, 0); /* Unupdated instruction addr*/ E(inst, regs); UNREFERENCED(inst); /* Set the bear register */ SET_BEAR_REG(regs, regs->bear_ip); /* Program check if instruction is located above 2GB */ if (ia > 0x7FFFFFFFULL) regs->program_interrupt (regs, PGM_SPECIFICATION_EXCEPTION); #if defined(FEATURE_ESAME) /* Add a mode trace entry when switching in/out of 64 bit mode */ if((regs->CR(12) & CR12_MTRACE) && regs->psw.amode64) regs->CR(12) = ARCH_DEP(trace_ms) (0, 0, regs); #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) regs->psw.amode64 = 0; #endif /*defined(FEATURE_ESAME)*/ regs->psw.amode = 1; regs->psw.AMASK = AMASK31; } /* end DEF_INST(set_addressing_mode_31) */ #endif /*defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* 010E SAM64 - Set Addressing Mode 64 [E] */ /*-------------------------------------------------------------------*/ DEF_INST(set_addressing_mode_64) { E(inst, regs); UNREFERENCED(inst); /* Set the bear register */ SET_BEAR_REG(regs, regs->bear_ip); #if defined(FEATURE_ESAME) /* Add a mode trace entry when switching in/out of 64 bit mode */ if((regs->CR(12) & CR12_MTRACE) && !regs->psw.amode64) regs->CR(12) = ARCH_DEP(trace_ms) (0, 0, regs); #endif /*defined(FEATURE_ESAME)*/ regs->psw.amode = regs->psw.amode64 = 1; regs->psw.AMASK = AMASK64; } /* end DEF_INST(set_addressing_mode_64) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* E324 STG - Store Long [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(store_long) { int r1; /* Values of R fields */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ RXY(inst, regs, r1, b2, effective_addr2); /* Store register contents at operand address */ ARCH_DEP(vstore8) ( regs->GR_G(r1), effective_addr2, b2, regs ); } /* end DEF_INST(store_long) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* E502 STRAG - Store Real Address [SSE] */ /*-------------------------------------------------------------------*/ DEF_INST(store_real_address) { int b1, b2; /* Values of base registers */ VADR effective_addr1, effective_addr2; /* Effective addresses */ SSE(inst, regs, b1, effective_addr1, b2, effective_addr2); PRIV_CHECK(regs); DW_CHECK(effective_addr1, regs); /* Translate virtual address to real address */ if (ARCH_DEP(translate_addr) (effective_addr2, b2, regs, ACCTYPE_STRAG)) regs->program_interrupt (regs, regs->dat.xcode); /* Store register contents at operand address */ ARCH_DEP(vstore8) (regs->dat.raddr, effective_addr1, b1, regs ); } /* end DEF_INST(store_real_address) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* E304 LG - Load Long [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(load_long) { int r1; /* Value of R field */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ RXY(inst, regs, r1, b2, effective_addr2); /* Load R1 register from second operand */ regs->GR_G(r1) = ARCH_DEP(vfetch8) ( effective_addr2, b2, regs ); } /* end DEF_INST(load_long) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* E314 LGF - Load Long Fullword [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(load_long_fullword) { int r1; /* Value of R field */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ RXY(inst, regs, r1, b2, effective_addr2); /* Load R1 register from second operand */ regs->GR_G(r1) = (S32)ARCH_DEP(vfetch4) ( effective_addr2, b2, regs ); } /* end DEF_INST(load_long_fullword) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* E315 LGH - Load Long Halfword [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(load_long_halfword) { int r1; /* Value of R field */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ RXY(inst, regs, r1, b2, effective_addr2); /* Load R1 register from second operand */ regs->GR_G(r1) = (S16)ARCH_DEP(vfetch2) ( effective_addr2, b2, regs ); } /* end DEF_INST(load_long_halfword) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* E316 LLGF - Load Logical Long Fullword [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(load_logical_long_fullword) { int r1; /* Value of R field */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ RXY(inst, regs, r1, b2, effective_addr2); /* Load R1 register from second operand */ regs->GR_G(r1) = ARCH_DEP(vfetch4) ( effective_addr2, b2, regs ); } /* end DEF_INST(load_logical_long_fullword) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* E317 LLGT - Load Logical Long Thirtyone [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(load_logical_long_thirtyone) { int r1; /* Value of R field */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ RXY(inst, regs, r1, b2, effective_addr2); /* Load R1 register from second operand */ regs->GR_G(r1) = ARCH_DEP(vfetch4) ( effective_addr2, b2, regs ) & 0x7FFFFFFF; } /* end DEF_INST(load_logical_long_thirtyone) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* B2B2 LPSWE - Load PSW Extended [S] */ /*-------------------------------------------------------------------*/ DEF_INST(load_program_status_word_extended) { int b2; /* Base of effective addr */ U64 effective_addr2; /* Effective address */ QWORD qword; int rc; S(inst, regs, b2, effective_addr2); PRIV_CHECK(regs); DW_CHECK(effective_addr2, regs); #if defined(_FEATURE_ZSIE) if(SIE_STATB(regs, IC1, LPSW)) longjmp(regs->progjmp, SIE_INTERCEPT_INST); #endif /*defined(_FEATURE_ZSIE)*/ /* Perform serialization and checkpoint synchronization */ PERFORM_SERIALIZATION (regs); PERFORM_CHKPT_SYNC (regs); /* Fetch new PSW from operand address */ ARCH_DEP(vfetchc) ( qword, 16-1, effective_addr2, b2, regs ); /* Set the breaking event address register */ SET_BEAR_REG(regs, regs->ip - 4); /* Load updated PSW */ if ( ( rc = ARCH_DEP(load_psw) ( regs, qword ) ) ) regs->program_interrupt (regs, rc); /* Perform serialization and checkpoint synchronization */ PERFORM_SERIALIZATION (regs); PERFORM_CHKPT_SYNC (regs); RETURN_INTCHECK(regs); } /* end DEF_INST(load_program_status_word_extended) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* E303 LRAG - Load Real Address Long [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(load_real_address_long) { int r1; /* Register number */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ int cc; /* Condition code */ RXY(inst, regs, r1, b2, effective_addr2); SIE_XC_INTERCEPT(regs); PRIV_CHECK(regs); /* Translate the effective address to a real address */ cc = ARCH_DEP(translate_addr) (effective_addr2, b2, regs, ACCTYPE_LRA); /* If ALET exception or ASCE-type or region translation exception, or if the segment table entry is outside the table and the entry address exceeds 2GB, set exception code in R1 bits 48-63, set bit 32 of R1, and set cc 3 */ if (cc > 3 || (cc == 3 && regs->dat.raddr > 0x7FFFFFFF)) { regs->GR_L(r1) = 0x80000000 | regs->dat.xcode; cc = 3; } else if (cc == 3) /* && regs->dat.raddr <= 0x7FFFFFFF */ { /* If segment table entry is outside table and entry address does not exceed 2GB, return bits 32-63 of the entry address and leave bits 0-31 unchanged */ regs->GR_L(r1) = regs->dat.raddr; } else { /* Set R1 and condition code as returned by translate_addr */ regs->GR_G(r1) = regs->dat.raddr; } /* Set condition code */ regs->psw.cc = cc; } /* end DEF_INST(load_real_address_long) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_TOD_CLOCK_STEERING) /*-------------------------------------------------------------------*/ /* 0104 PTFF - Perform Timing Facility Function [E] */ /*-------------------------------------------------------------------*/ DEF_INST(perform_timing_facility_function) { E(inst, regs); UNREFERENCED(inst); SIE_INTERCEPT(regs); if(regs->GR_L(0) & PTFF_GPR0_RESV) regs->program_interrupt (regs, PGM_SPECIFICATION_EXCEPTION); switch(regs->GR_L(0) & PTFF_GPR0_FC_MASK) { case PTFF_GPR0_FC_QAF: ARCH_DEP(query_available_functions) (regs); regs->psw.cc = 0; break; case PTFF_GPR0_FC_QTO: ARCH_DEP(query_tod_offset) (regs); regs->psw.cc = 0; break; case PTFF_GPR0_FC_QSI: ARCH_DEP(query_steering_information) (regs); regs->psw.cc = 0; break; case PTFF_GPR0_FC_QPT: ARCH_DEP(query_physical_clock) (regs); regs->psw.cc = 0; break; case PTFF_GPR0_FC_ATO: PRIV_CHECK(regs); ARCH_DEP(adjust_tod_offset) (regs); regs->psw.cc = 0; break; case PTFF_GPR0_FC_STO: PRIV_CHECK(regs); ARCH_DEP(set_tod_offset) (regs); regs->psw.cc = 0; break; case PTFF_GPR0_FC_SFS: PRIV_CHECK(regs); ARCH_DEP(set_fine_s_rate) (regs); regs->psw.cc = 0; break; case PTFF_GPR0_FC_SGS: PRIV_CHECK(regs); ARCH_DEP(set_gross_s_rate) (regs); regs->psw.cc = 0; break; default: PTT(PTT_CL_ERR,"*PTFF",regs->GR_L(0),regs->GR_L(1),regs->psw.IA_L); regs->psw.cc = 3; } } #endif /*defined(FEATURE_TOD_CLOCK_STEERING)*/ #if defined(FEATURE_CONFIGURATION_TOPOLOGY_FACILITY) /*-------------------------------------------------------------------*/ /* B9A2 PTF - Perform Topology Function [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(perform_topology_function) { int r1, unused; /* Values of R fields */ int fc, rc = 0; /* Function / Reason Code */ RRE(inst, regs, r1, unused); PTT(PTT_CL_INF,"PTF",regs->GR_G(r1),0,regs->psw.IA_L); PRIV_CHECK(regs); SIE_INTERCEPT(regs); /* Specification Exception if bits 0-55 of general register R1 are not zeros */ if (regs->GR_G(r1) & 0xFFFFFFFFFFFFFF00ULL) { PTT(PTT_CL_ERR,"*PTF",regs->GR_G(r1),rc,regs->psw.IA_L); regs->program_interrupt (regs, PGM_SPECIFICATION_EXCEPTION); } /* Extract function code */ fc = (int)(regs->GR_G(r1) & 0x00000000000000FFULL); /* Perform requested function */ switch (fc) { case 0: /* Request horizontal polarization */ regs->psw.cc = 2; /* Request rejected */ rc = 1; /* Already polarized as specified */ break; case 1: /* Request vertical polarization */ regs->psw.cc = 2; /* Request rejected */ rc = 0; /* No reason specified */ break; case 2: /* Check topology-change status */ OBTAIN_INTLOCK(NULL); regs->psw.cc = sysblk.topchnge ? 1 /* (report was pending) */ : 0; /* (report not pending) */ sysblk.topchnge = 0; /* (clear pending flag) */ RELEASE_INTLOCK(NULL); break; default: /* Undefined function code */ PTT(PTT_CL_ERR,"*PTF",regs->GR_G(r1),rc,regs->psw.IA_L); regs->program_interrupt (regs, PGM_SPECIFICATION_EXCEPTION); } /* Set reason code in bits 48-55 when condition code is 2 */ if (regs->psw.cc == 2) regs->GR_G(r1) |= rc << 8; if (regs->psw.cc != 0) PTT(PTT_CL_ERR,"*PTF",regs->GR_G(r1),rc,regs->psw.IA_L); } #endif /*defined(FEATURE_CONFIGURATION_TOPOLOGY_FACILITY)*/ #if defined(FEATURE_ESAME) || defined(FEATURE_ESAME_N3_ESA390) BYTE ARCH_DEP(stfl_data)[] = { 0 #if defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_ESAME) | STFL_0_N3 #endif /*defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) | STFL_0_ESAME_ACTIVE #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) | STFL_0_ESAME_INSTALLED #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_DAT_ENHANCEMENT) | STFL_0_IDTE_INSTALLED #endif /*defined(FEATURE_DAT_ENHANCEMENT)*/ #if defined(FEATURE_ASN_AND_LX_REUSE) | STFL_0_ASN_LX_REUSE #endif /*defined(FEATURE_ASN_AND_LX_REUSE)*/ #if defined(FEATURE_STORE_FACILITY_LIST_EXTENDED) | STFL_0_STFL_EXTENDED #endif /*defined(FEATURE_STORE_FACILITY_LIST_EXTENDED)*/ , 0 #if defined(FEATURE_ENHANCED_DAT_FACILITY) /*208*/ | STFL_1_ENHANCED_DAT /*208*/ #endif /*defined(FEATURE_ENHANCED_DAT_FACILITY)*/ /*208*/ #if defined(FEATURE_SENSE_RUNNING_STATUS) | STFL_1_SENSE_RUN_STATUS #endif /*defined(FEATURE_SENSE_RUNNING_STATUS)*/ #if defined(FEATURE_CONDITIONAL_SSKE) | STFL_1_CONDITIONAL_SSKE #endif /*defined(FEATURE_CONDITIONAL_SSKE)*/ #if defined(FEATURE_CONFIGURATION_TOPOLOGY_FACILITY) /*208*/ | STFL_1_CONFIG_TOPOLOGY /*208*/ #endif /*defined(FEATURE_CONFIGURATION_TOPOLOGY_FACILITY)*/ /*208*/ , 0 #if defined(FEATURE_EXTENDED_TRANSLATION_FACILITY_2) | STFL_2_TRAN_FAC2 #endif /*defined(FEATURE_EXTENDED_TRANSLATION_FACILITY_2)*/ #if defined(FEATURE_MESSAGE_SECURITY_ASSIST) | STFL_2_MSG_SECURITY #endif /*defined(FEATURE_MESSAGE_SECURITY_ASSIST)*/ #if defined(FEATURE_LONG_DISPLACEMENT) | STFL_2_LONG_DISPL_INST | STFL_2_LONG_DISPL_HPERF #endif /*defined(FEATURE_LONG_DISPLACEMENT)*/ #if defined(FEATURE_HFP_MULTIPLY_ADD_SUBTRACT) | STFL_2_HFP_MULT_ADD_SUB #endif /*defined(FEATURE_HFP_MULTIPLY_ADD_SUBTRACT)*/ #if defined(FEATURE_EXTENDED_IMMEDIATE) | STFL_2_EXTENDED_IMMED #endif /*defined(FEATURE_EXTENDED_IMMEDIATE)*/ #if defined(FEATURE_EXTENDED_TRANSLATION_FACILITY_3) | STFL_2_TRAN_FAC3 #endif /*defined(FEATURE_EXTENDED_TRANSLATION_FACILITY_3)*/ #if defined(FEATURE_HFP_UNNORMALIZED_EXTENSION) | STFL_2_HFP_UNNORM_EXT #endif /*defined(FEATURE_HFP_UNNORMALIZED_EXTENSION)*/ , 0 #if defined(FEATURE_ETF2_ENHANCEMENT) | STFL_3_ETF2_ENHANCEMENT #endif /*defined(FEATURE_ETF2_ENHANCEMENT)*/ #if defined(FEATURE_STORE_CLOCK_FAST) | STFL_3_STORE_CLOCK_FAST #endif /*defined(FEATURE_STORE_CLOCK_FAST)*/ #if defined(FEATURE_PARSING_ENHANCEMENT_FACILITY) /*208*/ | STFL_3_PARSING_ENHANCE /*208*/ #endif /*defined(FEATURE_PARSING_ENHANCEMENT_FACILITY)*/ /*208*/ #if defined(FEATURE_MOVE_WITH_OPTIONAL_SPECIFICATIONS) /*208*/ | STFL_3_MVCOS /*208*/ #endif /*defined(FEATURE_MOVE_WITH_OPTIONAL_SPECIFICATIONS)*/ /*208*/ #if defined(FEATURE_TOD_CLOCK_STEERING) | STFL_3_TOD_CLOCK_STEER #endif /*defined(FEATURE_TOD_CLOCK_STEERING)*/ #if defined(FEATURE_ETF3_ENHANCEMENT) | STFL_3_ETF3_ENHANCEMENT #endif /*defined(FEATURE_ETF3_ENHANCEMENT)*/ #if defined(FEATURE_EXTRACT_CPU_TIME) | STFL_3_EXTRACT_CPU_TIME #endif /*defined(FEATURE_EXTRACT_CPU_TIME)*/ , 0 #if defined(FEATURE_COMPARE_AND_SWAP_AND_STORE) | STFL_4_CSSF #endif /*defined(FEATURE_COMPARE_AND_SWAP_AND_STORE)*/ #if defined(FEATURE_COMPARE_AND_SWAP_AND_STORE_FACILITY_2) /*208*/ | STFL_4_CSSF2 /*208*/ #endif /*FEATURE_COMPARE_AND_SWAP_AND_STORE_FACILITY_2*/ /*208*/ #if defined(FEATURE_GENERAL_INSTRUCTIONS_EXTENSION_FACILITY) /*208*/ | STFL_4_GEN_INST_EXTN /*208*/ #endif /*FEATURE_GENERAL_INSTRUCTIONS_EXTENSION_FACILITY*/ /*208*/ #if defined(FEATURE_EXECUTE_EXTENSIONS_FACILITY) /*208*/ | STFL_4_EXECUTE_EXTN /*208*/ #endif /*defined(FEATURE_EXECUTE_EXTENSIONS_FACILITY)*/ /*208*/ , 0 #if defined(FEATURE_SET_PROGRAM_PARAMETER_FACILITY) | STFL_5_SET_PROG_PARAM #endif /*defined(FEATURE_SET_PROGRAM_PARAMETER_FACILITY)*/ #if defined(FEATURE_FPS_ENHANCEMENT) | STFL_5_FPS_ENHANCEMENT #endif /*defined(FEATURE_FPS_ENHANCEMENT)*/ #if defined(FEATURE_DECIMAL_FLOATING_POINT) | STFL_5_DECIMAL_FLOAT | STFL_5_DFP_HPERF #endif /*defined(FEATURE_DECIMAL_FLOATING_POINT)*/ #if defined(FEATURE_PFPO) | STFL_5_PFPO #endif /*defined(FEATURE_PFPO)*/ , 0 , 0 , 0 #if defined(FEATURE_CPU_MEASUREMENT_COUNTER_FACILITY) | STFL_8_CPU_MEAS_COUNTER #endif /*defined(FEATURE_CPU_MEASUREMENT_COUNTER_FACILITY)*/ #if defined(FEATURE_CPU_MEASUREMENT_SAMPLING_FACILITY) | STFL_8_CPU_MEAS_SAMPLNG #endif /*defined(FEATURE_CPU_MEASUREMENT_SAMPLING_FACILITY)*/ , 0 , 0 , 0 , 0 , 0 , 0 , 0 }; /*-------------------------------------------------------------------*/ /* Adjust the facility list to account for runtime options */ /*-------------------------------------------------------------------*/ BYTE * ARCH_DEP(adjust_stfl_data) (int *data_len, REGS *regs) { int stfl_len; /* Length of STFL data */ BYTE *stfl_data; /* -> STFL data being modified. Depends upon */ /* installed architecture, but not the current */ /* architecture mode being executed. */ /* ARCH_DEP is unreliable choice for STFL data */ /* post IPL of a z/Architecture machine but */ /* before the CPU has been placed in */ /* in z/Architecture mode. In this case, */ /* ARCH_DEP selects ESA/390 STFL data which is */ /* incomplete when z/Architecture is installed. */ /* This creates problems for OS's that expect to */ /* detect z/Architecture features before */ /* entering z/Architecture mode and only find */ /* ESA/390 features. */ if (sysblk.arch_z900) { /* 'ARCHMODE z/Arch' in configuration (or console configured) */ /* Locate the STFL data for a z/Architecture system */ stfl_data=get_stfl_data(ARCH_900, &stfl_len); /* A little overkill, but deals with the possible corner case */ if (!stfl_data) { stfl_len=sizeof(ARCH_DEP(stfl_data)); stfl_data=&ARCH_DEP(stfl_data)[0]; } stfl_data[0] |= STFL_0_ESAME_INSTALLED; /* Set whether z/Arch is active based upon CPU mode */ if (regs->arch_mode == ARCH_900) stfl_data[0] |= STFL_0_ESAME_ACTIVE; else stfl_data[0] &= ~STFL_0_ESAME_ACTIVE; } else { /* 'ARCHMODE ESA/390' in configuration (or console configured) */ /* Locate the STFL data for an ESA/390 system */ stfl_data=get_stfl_data(ARCH_390, &stfl_len); /* Same overkill, but just in case */ if (!stfl_data) { stfl_len=sizeof(ARCH_DEP(stfl_data)); stfl_data=&ARCH_DEP(stfl_data)[0]; } stfl_data[0] &= ~STFL_0_ESAME_INSTALLED; stfl_data[0] &= ~STFL_0_ESAME_ACTIVE; } #if defined(FEATURE_MESSAGE_SECURITY_ASSIST) /* MSA is enabled only if the dyncrypt DLL module is loaded */ if(ARCH_DEP(cipher_message)) stfl_data[2] |= STFL_2_MSG_SECURITY; else stfl_data[2] &= ~STFL_2_MSG_SECURITY; #endif /*defined(FEATURE_MESSAGE_SECURITY_ASSIST)*/ #if defined(_FEATURE_ASN_AND_LX_REUSE) /* ALRF enablement is an option in the configuration file */ if(sysblk.asnandlxreuse) stfl_data[0] |= STFL_0_ASN_LX_REUSE; else stfl_data[0] &= ~STFL_0_ASN_LX_REUSE; #endif /*defined(FEATURE_ASN_AND_LX_REUSE)*/ *data_len=stfl_len; return stfl_data; } /* end ARCH_DEP(adjust_stfl_data) */ /*-------------------------------------------------------------------*/ /* B2B1 STFL - Store Facility List [S] */ /*-------------------------------------------------------------------*/ DEF_INST(store_facility_list) { int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ int data_len; /* Size of STFL data */ /* Note: data_len not used here, but STFLE needs it */ PSA *psa; /* -> Prefixed storage area */ BYTE *stfl_data; /* -> STFL data */ S(inst, regs, b2, effective_addr2); PRIV_CHECK(regs); SIE_INTERCEPT(regs); PTT(PTT_CL_INF,"STFL",b2,(U32)(effective_addr2 & 0xffffffff),regs->psw.IA_L); /* Adjust the facility list to account for runtime options */ stfl_data = ARCH_DEP(adjust_stfl_data)(&data_len, regs); #if 0 logmsg ("store_facility_list STFL data length %i\n",data_len); logmsg ("STFL=%2.2X %2.2X %2.2X %2.2X\n", *stfl_data,*(stfl_data+1),*(stfl_data+2),*(stfl_data+3)); #endif /* Set the main storage reference and change bits */ STORAGE_KEY(regs->PX, regs) |= (STORKEY_REF | STORKEY_CHANGE); /* Point to PSA in main storage */ psa = (void*)(regs->mainstor + regs->PX); memcpy(psa->stfl, stfl_data, sizeof(psa->stfl)); } /* end DEF_INST(store_facility_list) */ #if defined(FEATURE_STORE_FACILITY_LIST_EXTENDED) /*-------------------------------------------------------------------*/ /* B2B0 STFLE - Store Facility List Extended [S] */ /*-------------------------------------------------------------------*/ DEF_INST(store_facility_list_extended) { int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ int data_len; /* Size of STFL data */ int nmax; /* #of doublewords defined */ int ndbl; /* #of doublewords to store */ int cc; /* Condition code */ BYTE *stfl_data; /* -> STFL data */ S(inst, regs, b2, effective_addr2); SIE_INTERCEPT(regs); PTT(PTT_CL_INF,"STFLE",regs->GR_L(0),(U32)(effective_addr2 & 0xffffffff),regs->psw.IA_L); /* Note: STFLE is NOT a privileged instruction (unlike STFL) */ DW_CHECK(effective_addr2, regs); /* Adjust the facility list to account for runtime options */ stfl_data = ARCH_DEP(adjust_stfl_data)(&data_len, regs); /* Calculate number of doublewords of facilities defined */ nmax = (data_len+7) / 8; /* Obtain operand length from register 0 bits 56-63 */ ndbl = regs->GR_LHLCL(0) + 1; /* Check if operand length is sufficient */ if (ndbl >= nmax) { ndbl = nmax; cc = 0; } else { PTT(PTT_CL_ERR,"*STFLE", ndbl, nmax, regs->psw.IA_L); cc = 3; } /* Store facility list at operand location */ ARCH_DEP(vstorec) ( stfl_data, ndbl*8-1, effective_addr2, b2, regs ); /* Save number of doublewords minus 1 into register 0 bits 56-63 */ regs->GR_LHLCL(0) = (BYTE)(nmax - 1); /* Set condition code */ regs->psw.cc = cc; } /* end DEF_INST(store_facility_list_extended) */ #endif /*defined(FEATURE_STORE_FACILITY_LIST_EXTENDED)*/ #endif /*defined(FEATURE_ESAME) || defined(FEATURE_ESAME_N3_ESA390)*/ #if defined(FEATURE_LOAD_REVERSED) && defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* B90F LRVGR - Load Reversed Long Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(load_reversed_long_register) { int r1, r2; /* Values of R fields */ RRE0(inst, regs, r1, r2); /* Copy second operand to first operand */ regs->GR_G(r1) = bswap_64(regs->GR_G(r2)); } /* end DEF_INST(load_reversed_long_register) */ #endif /*defined(FEATURE_LOAD_REVERSED) && defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_LOAD_REVERSED) /*-------------------------------------------------------------------*/ /* B91F LRVR - Load Reversed Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(load_reversed_register) { int r1, r2; /* Values of R fields */ RRE0(inst, regs, r1, r2); /* Copy second operand to first operand */ regs->GR_L(r1) = bswap_32(regs->GR_L(r2)); } /* end DEF_INST(load_reversed_register) */ #endif /*defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_LOAD_REVERSED)*/ #if defined(FEATURE_LOAD_REVERSED) && defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* E30F LRVG - Load Reversed Long [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(load_reversed_long) { int r1; /* Value of R field */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ RXY(inst, regs, r1, b2, effective_addr2); /* Load R1 register from second operand */ regs->GR_G(r1) = bswap_64(ARCH_DEP(vfetch8) ( effective_addr2, b2, regs )); } /* end DEF_INST(load_reversed_long) */ #endif /*defined(FEATURE_LOAD_REVERSED) && defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_LOAD_REVERSED) /*-------------------------------------------------------------------*/ /* E31E LRV - Load Reversed [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(load_reversed) { int r1; /* Value of R field */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ RXY(inst, regs, r1, b2, effective_addr2); /* Load R1 register from second operand */ regs->GR_L(r1) = bswap_32(ARCH_DEP(vfetch4) ( effective_addr2, b2, regs )); } /* end DEF_INST(load_reversed) */ #endif /*defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_LOAD_REVERSED)*/ #if defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_LOAD_REVERSED) /*-------------------------------------------------------------------*/ /* E31F LRVH - Load Reversed Half [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(load_reversed_half) { int r1; /* Value of R field */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ RXY(inst, regs, r1, b2, effective_addr2); /* Load R1 register from second operand */ regs->GR_LHL(r1) = bswap_16(ARCH_DEP(vfetch2) ( effective_addr2, b2, regs )); } /* end DEF_INST(load_reversed_half) */ #endif /*defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_LOAD_REVERSED)*/ #if defined(FEATURE_LOAD_REVERSED) && defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* E32F STRVG - Store Reversed Long [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(store_reversed_long) { int r1; /* Values of R fields */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ RXY(inst, regs, r1, b2, effective_addr2); /* Store register contents at operand address */ ARCH_DEP(vstore8) ( bswap_64(regs->GR_G(r1)), effective_addr2, b2, regs ); } /* end DEF_INST(store_reversed_long) */ #endif /*defined(FEATURE_LOAD_REVERSED) && defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_LOAD_REVERSED) /*-------------------------------------------------------------------*/ /* E33E STRV - Store Reversed [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(store_reversed) { int r1; /* Values of R fields */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ RXY(inst, regs, r1, b2, effective_addr2); /* Store register contents at operand address */ ARCH_DEP(vstore4) ( bswap_32(regs->GR_L(r1)), effective_addr2, b2, regs ); } /* end DEF_INST(store_reversed) */ #endif /*defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_LOAD_REVERSED)*/ #if defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_LOAD_REVERSED) /*-------------------------------------------------------------------*/ /* E33F STRVH - Store Reversed Half [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(store_reversed_half) { int r1; /* Values of R fields */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ RXY(inst, regs, r1, b2, effective_addr2); /* Store register contents at operand address */ ARCH_DEP(vstore2) ( bswap_16(regs->GR_LHL(r1)), effective_addr2, b2, regs ); } /* end DEF_INST(store_reversed_half) */ #endif /*defined(FEATURE_ESAME_N3_ESA390) || defined(FEATURE_LOAD_REVERSED)*/ #if defined(FEATURE_EXTENDED_TRANSLATION_FACILITY_2) /*-------------------------------------------------------------------*/ /* E9 PKA - Pack ASCII [SS] */ /*-------------------------------------------------------------------*/ DEF_INST(pack_ascii) { int len; /* Second operand length */ int b1, b2; /* Base registers */ VADR addr1, addr2; /* Effective addresses */ BYTE source[33]; /* 32 digits + implied sign */ BYTE result[16]; /* 31-digit packed result */ int i, j; /* Array subscripts */ SS_L(inst, regs, len, b1, addr1, b2, addr2); /* Program check if operand length (len+1) exceeds 32 bytes */ if (len > 31) regs->program_interrupt (regs, PGM_SPECIFICATION_EXCEPTION); /* Fetch the second operand and right justify */ memset (source, 0, sizeof(source)); ARCH_DEP(vfetchc) ( source+31-len, len, addr2, b2, regs ); /* Append an implied plus sign */ source[32] = 0x0C; /* Pack the rightmost 31 digits and sign into the result */ for (i = 1, j = 0; j < 16; i += 2, j++) { result[j] = (source[i] << 4) | (source[i+1] & 0x0F); } /* Store 16-byte packed decimal result at operand address */ ARCH_DEP(vstorec) ( result, 16-1, addr1, b1, regs ); } /* end DEF_INST(pack_ascii) */ #endif /*defined(FEATURE_EXTENDED_TRANSLATION_FACILITY_2)*/ #if defined(FEATURE_EXTENDED_TRANSLATION_FACILITY_2) /*-------------------------------------------------------------------*/ /* E1 PKU - Pack Unicode [SS] */ /*-------------------------------------------------------------------*/ DEF_INST(pack_unicode) { int len; /* Second operand length */ int b1, b2; /* Base registers */ VADR addr1, addr2; /* Effective addresses */ BYTE source[66]; /* 32 digits + implied sign */ BYTE result[16]; /* 31-digit packed result */ int i, j; /* Array subscripts */ SS_L(inst, regs, len, b1, addr1, b2, addr2); /* Program check if byte count (len+1) exceeds 64 or is odd */ if (len > 63 || (len & 1) == 0) regs->program_interrupt (regs, PGM_SPECIFICATION_EXCEPTION); /* Fetch the second operand and right justify */ memset (source, 0, sizeof(source)); ARCH_DEP(vfetchc) ( source+63-len, len, addr2, b2, regs ); /* Append an implied plus sign */ source[64] = 0x00; source[65] = 0x0C; /* Pack the rightmost 31 digits and sign into the result */ for (i = 2, j = 0; j < 16; i += 4, j++) { result[j] = (source[i+1] << 4) | (source[i+3] & 0x0F); } /* Store 16-byte packed decimal result at operand address */ ARCH_DEP(vstorec) ( result, 16-1, addr1, b1, regs ); } /* end DEF_INST(pack_unicode) */ #endif /*defined(FEATURE_EXTENDED_TRANSLATION_FACILITY_2)*/ #if defined(FEATURE_EXTENDED_TRANSLATION_FACILITY_2) /*-------------------------------------------------------------------*/ /* EA UNPKA - Unpack ASCII [SS] */ /*-------------------------------------------------------------------*/ DEF_INST(unpack_ascii) { int len; /* First operand length */ int b1, b2; /* Base registers */ VADR addr1, addr2; /* Effective addresses */ BYTE result[32]; /* 32-digit result */ BYTE source[16]; /* 31-digit packed operand */ int i, j; /* Array subscripts */ int cc; /* Condition code */ SS_L(inst, regs, len, b1, addr1, b2, addr2); /* Program check if operand length (len+1) exceeds 32 bytes */ if (len > 31) regs->program_interrupt (regs, PGM_SPECIFICATION_EXCEPTION); /* Fetch the 16-byte second operand */ ARCH_DEP(vfetchc) ( source, 15, addr2, b2, regs ); /* Set high-order result byte to ASCII zero */ result[0] = 0x30; /* Unpack remaining 31 digits into the result */ for (j = 1, i = 0; ; i++) { result[j++] = (source[i] >> 4) | 0x30; if (i == 15) break; result[j++] = (source[i] & 0x0F) | 0x30; } /* Store rightmost digits of result at first operand address */ ARCH_DEP(vstorec) ( result+31-len, len, addr1, b1, regs ); /* Set the condition code according to the sign */ switch (source[15] & 0x0F) { case 0x0A: case 0x0C: case 0x0E: case 0x0F: cc = 0; break; case 0x0B: case 0x0D: cc = 1; break; default: cc = 3; } /* end switch */ regs->psw.cc = cc; } /* end DEF_INST(unpack_ascii) */ #endif /*defined(FEATURE_EXTENDED_TRANSLATION_FACILITY_2)*/ #if defined(FEATURE_EXTENDED_TRANSLATION_FACILITY_2) /*-------------------------------------------------------------------*/ /* E2 UNPKU - Unpack Unicode [SS] */ /*-------------------------------------------------------------------*/ DEF_INST(unpack_unicode) { int len; /* First operand length */ int b1, b2; /* Base registers */ VADR addr1, addr2; /* Effective addresses */ BYTE result[64]; /* 32-digit result */ BYTE source[16]; /* 31-digit packed operand */ int i, j; /* Array subscripts */ int cc; /* Condition code */ SS_L(inst, regs, len, b1, addr1, b2, addr2); /* Program check if byte count (len+1) exceeds 64 or is odd */ if (len > 63 || (len & 1) == 0) regs->program_interrupt (regs, PGM_SPECIFICATION_EXCEPTION); /* Fetch the 16-byte second operand */ ARCH_DEP(vfetchc) ( source, 15, addr2, b2, regs ); /* Set high-order result pair to Unicode zero */ result[0] = 0x00; result[1] = 0x30; /* Unpack remaining 31 digits into the result */ for (j = 2, i = 0; ; i++) { result[j++] = 0x00; result[j++] = (source[i] >> 4) | 0x30; if (i == 15) break; result[j++] = 0x00; result[j++] = (source[i] & 0x0F) | 0x30; } /* Store rightmost digits of result at first operand address */ ARCH_DEP(vstorec) ( result+63-len, len, addr1, b1, regs ); /* Set the condition code according to the sign */ switch (source[15] & 0x0F) { case 0x0A: case 0x0C: case 0x0E: case 0x0F: cc = 0; break; case 0x0B: case 0x0D: cc = 1; break; default: cc = 3; } /* end switch */ regs->psw.cc = cc; } /* end DEF_INST(unpack_unicode) */ #endif /*defined(FEATURE_EXTENDED_TRANSLATION_FACILITY_2)*/ #if defined(FEATURE_EXTENDED_TRANSLATION_FACILITY_2) /*-------------------------------------------------------------------*/ /* B993 TROO - Translate One to One [RRF] */ /*-------------------------------------------------------------------*/ DEF_INST(translate_one_to_one) { int r1, r2; /* Values of R fields */ VADR addr1, addr2, trtab; /* Effective addresses */ GREG len; BYTE svalue, dvalue, tvalue; #ifdef FEATURE_ETF2_ENHANCEMENT int tccc; /* Test-Character-Comparison Control */ #endif // NOTE: it's faster to decode with RRE format // and then to handle the 'tccc' flag separately... // RRF_M(inst, regs, r1, r2, tccc); RRE(inst, regs, r1, r2); ODD_CHECK(r1, regs); #ifdef FEATURE_ETF2_ENHANCEMENT /* Set Test-Character-Comparison Control */ if(inst[2] & 0x10) tccc = 1; else tccc = 0; #endif /* Determine length */ len = GR_A(r1 + 1,regs); /* Determine destination, source and translate table address */ addr1 = regs->GR(r1) & ADDRESS_MAXWRAP(regs); addr2 = regs->GR(r2) & ADDRESS_MAXWRAP(regs); trtab = regs->GR(1) & ADDRESS_MAXWRAP(regs) & ~7; /* Determine test value */ tvalue = regs->GR_LHLCL(0); /* Preset condition code to zero in case of zero length */ if(!len) regs->psw.cc = 0; while(len) { svalue = ARCH_DEP(vfetchb) (addr2, r2, regs); /* Fetch value from translation table */ dvalue = ARCH_DEP(vfetchb) (((trtab + svalue) & ADDRESS_MAXWRAP(regs) ), 1, regs); #ifdef FEATURE_ETF2_ENHANCEMENT /* Test-Character-Comparison Control */ if(!tccc) { #endif /* If the testvalue was found then exit with cc1 */ if(dvalue == tvalue) { regs->psw.cc = 1; break; } #ifdef FEATURE_ETF2_ENHANCEMENT } #endif /* Store destination value */ ARCH_DEP(vstoreb) (dvalue, addr1, r1, regs); /* Adjust source addr, destination addr and length */ addr1++; addr1 &= ADDRESS_MAXWRAP(regs); addr2++; addr2 &= ADDRESS_MAXWRAP(regs); len--; /* Update the registers */ SET_GR_A(r1, regs, addr1); SET_GR_A(r1 + 1, regs, len); SET_GR_A(r2, regs, addr2); /* Set cc0 when all values have been processed */ regs->psw.cc = len ? 3 : 0; /* exit on the cpu determined number of bytes */ if((len != 0) && (!(addr1 & 0xfff) || !(addr2 & 0xfff))) break; } /* end while */ } /* end DEF_INST(translate_one_to_one) */ #endif /*defined(FEATURE_EXTENDED_TRANSLATION_FACILITY_2)*/ #if defined(FEATURE_EXTENDED_TRANSLATION_FACILITY_2) /*-------------------------------------------------------------------*/ /* B992 TROT - Translate One to Two [RRF] */ /*-------------------------------------------------------------------*/ DEF_INST(translate_one_to_two) { int r1, r2; /* Values of R fields */ VADR addr1, addr2, trtab; /* Effective addresses */ GREG len; BYTE svalue; U16 dvalue, tvalue; #ifdef FEATURE_ETF2_ENHANCEMENT int tccc; /* Test-Character-Comparison Control */ #endif // NOTE: it's faster to decode with RRE format // and then to handle the 'tccc' flag separately... // RRF_M(inst, regs, r1, r2, tccc); RRE(inst, regs, r1, r2); ODD_CHECK(r1, regs); #ifdef FEATURE_ETF2_ENHANCEMENT /* Set Test-Character-Comparison Control */ if(inst[2] & 0x10) tccc = 1; else tccc = 0; #endif /* Determine length */ len = GR_A(r1 + 1,regs); /* Determine destination, source and translate table address */ addr1 = regs->GR(r1) & ADDRESS_MAXWRAP(regs); addr2 = regs->GR(r2) & ADDRESS_MAXWRAP(regs); trtab = regs->GR(1) & ADDRESS_MAXWRAP(regs) & ~7; /* Determine test value */ tvalue = regs->GR_LHL(0); /* Preset condition code to zero in case of zero length */ if(!len) regs->psw.cc = 0; while(len) { svalue = ARCH_DEP(vfetchb) (addr2, r2, regs); /* Fetch value from translation table */ dvalue = ARCH_DEP(vfetch2) (((trtab + (svalue << 1)) & ADDRESS_MAXWRAP(regs) ), 1, regs); #ifdef FEATURE_ETF2_ENHANCEMENT /* Test-Character-Comparison Control */ if(!tccc) { #endif /* If the testvalue was found then exit with cc1 */ if(dvalue == tvalue) { regs->psw.cc = 1; break; } #ifdef FEATURE_ETF2_ENHANCEMENT } #endif /* Store destination value */ ARCH_DEP(vstore2) (dvalue, addr1, r1, regs); /* Adjust source addr, destination addr and length */ addr1 += 2; addr1 &= ADDRESS_MAXWRAP(regs); addr2++; addr2 &= ADDRESS_MAXWRAP(regs); len--; /* Update the registers */ SET_GR_A(r1, regs, addr1); SET_GR_A(r1 + 1, regs, len); SET_GR_A(r2, regs, addr2); /* Set cc0 when all values have been processed */ regs->psw.cc = len ? 3 : 0; /* exit on the cpu determined number of bytes */ if((len != 0) && (!(addr1 & 0xfff) || !(addr2 & 0xfff))) break; } /* end while */ } /* end DEF_INST(translate_one_to_two) */ #endif /*defined(FEATURE_EXTENDED_TRANSLATION_FACILITY_2)*/ #if defined(FEATURE_EXTENDED_TRANSLATION_FACILITY_2) /*-------------------------------------------------------------------*/ /* B991 TRTO - Translate Two to One [RRF] */ /*-------------------------------------------------------------------*/ DEF_INST(translate_two_to_one) { int r1, r2; /* Values of R fields */ VADR addr1, addr2, trtab; /* Effective addresses */ GREG len; U16 svalue; BYTE dvalue, tvalue; #ifdef FEATURE_ETF2_ENHANCEMENT int tccc; /* Test-Character-Comparison Control */ #endif // NOTE: it's faster to decode with RRE format // and then to handle the 'tccc' flag separately... // RRF_M(inst, regs, r1, r2, tccc); RRE(inst, regs, r1, r2); ODD_CHECK(r1, regs); #ifdef FEATURE_ETF2_ENHANCEMENT /* Set Test-Character-Comparison Control */ if(inst[2] & 0x10) tccc = 1; else tccc = 0; #endif /* Determine length */ len = GR_A(r1 + 1,regs); ODD_CHECK(len, regs); /* Determine destination, source and translate table address */ addr1 = regs->GR(r1) & ADDRESS_MAXWRAP(regs); addr2 = regs->GR(r2) & ADDRESS_MAXWRAP(regs); #ifdef FEATURE_ETF2_ENHANCEMENT trtab = regs->GR(1) & ADDRESS_MAXWRAP(regs) & ~7; #else trtab = regs->GR(1) & ADDRESS_MAXWRAP(regs) & ~0xfff; #endif /* Determine test value */ tvalue = regs->GR_LHLCL(0); /* Preset condition code to zero in case of zero length */ if(!len) regs->psw.cc = 0; while(len) { svalue = ARCH_DEP(vfetch2) (addr2, r2, regs); /* Fetch value from translation table */ dvalue = ARCH_DEP(vfetchb) (((trtab + svalue) & ADDRESS_MAXWRAP(regs) ), 1, regs); #ifdef FEATURE_ETF2_ENHANCEMENT /* Test-Character-Comparison Control */ if(!tccc) { #endif /* If the testvalue was found then exit with cc1 */ if(dvalue == tvalue) { regs->psw.cc = 1; break; } #ifdef FEATURE_ETF2_ENHANCEMENT } #endif /* Store destination value */ ARCH_DEP(vstoreb) (dvalue, addr1, r1, regs); /* Adjust source addr, destination addr and length */ addr1++; addr1 &= ADDRESS_MAXWRAP(regs); addr2 += 2; addr2 &= ADDRESS_MAXWRAP(regs); len -= 2; /* Update the registers */ SET_GR_A(r1, regs, addr1); SET_GR_A(r1 + 1, regs, len); SET_GR_A(r2, regs, addr2); /* Set cc0 when all values have been processed */ regs->psw.cc = len ? 3 : 0; /* exit on the cpu determined number of bytes */ if((len != 0) && (!(addr1 & 0xfff) || !(addr2 & 0xfff))) break; } /* end while */ } /* end DEF_INST(translate_two_to_one) */ #endif /*defined(FEATURE_EXTENDED_TRANSLATION_FACILITY_2)*/ #if defined(FEATURE_EXTENDED_TRANSLATION_FACILITY_2) /*-------------------------------------------------------------------*/ /* B990 TRTT - Translate Two to Two [RRF] */ /*-------------------------------------------------------------------*/ DEF_INST(translate_two_to_two) { int r1, r2; /* Values of R fields */ VADR addr1, addr2, trtab; /* Effective addresses */ GREG len; U16 svalue, dvalue, tvalue; #ifdef FEATURE_ETF2_ENHANCEMENT int tccc; /* Test-Character-Comparison Control */ #endif // NOTE: it's faster to decode with RRE format // and then to handle the 'tccc' flag separately... // RRF_M(inst, regs, r1, r2, tccc); RRE(inst, regs, r1, r2); ODD_CHECK(r1, regs); #ifdef FEATURE_ETF2_ENHANCEMENT /* Set Test-Character-Comparison Control */ if(inst[2] & 0x10) tccc = 1; else tccc = 0; #endif /* Determine length */ len = GR_A(r1 + 1,regs); ODD_CHECK(len, regs); /* Determine destination, source and translate table address */ addr1 = regs->GR(r1) & ADDRESS_MAXWRAP(regs); addr2 = regs->GR(r2) & ADDRESS_MAXWRAP(regs); #ifdef FEATURE_ETF2_ENHANCEMENT trtab = regs->GR(1) & ADDRESS_MAXWRAP(regs) & ~7; #else trtab = regs->GR(1) & ADDRESS_MAXWRAP(regs) & ~0xfff; #endif /* Determine test value */ tvalue = regs->GR_LHL(0); /* Preset condition code to zero in case of zero length */ if(!len) regs->psw.cc = 0; while(len) { svalue = ARCH_DEP(vfetch2) (addr2, r2, regs); /* Fetch value from translation table */ dvalue = ARCH_DEP(vfetch2) (((trtab + (svalue << 1)) & ADDRESS_MAXWRAP(regs) ), 1, regs); #ifdef FEATURE_ETF2_ENHANCEMENT /* Test-Character-Comparison Control */ if(!tccc) { #endif /* If the testvalue was found then exit with cc1 */ if(dvalue == tvalue) { regs->psw.cc = 1; break; } #ifdef FEATURE_ETF2_ENHANCEMENT } #endif /* Store destination value */ ARCH_DEP(vstore2) (dvalue, addr1, r1, regs); /* Adjust source addr, destination addr and length */ addr1 += 2; addr1 &= ADDRESS_MAXWRAP(regs); addr2 += 2; addr2 &= ADDRESS_MAXWRAP(regs); len -= 2; /* Update the registers */ SET_GR_A(r1, regs, addr1); SET_GR_A(r1 + 1, regs, len); SET_GR_A(r2, regs, addr2); /* Set cc0 when all values have been processed */ regs->psw.cc = len ? 3 : 0; /* exit on the cpu determined number of bytes */ if((len != 0) && (!(addr1 & 0xfff) || !(addr2 & 0xfff))) break; } /* end while */ } /* end DEF_INST(translate_two_to_two) */ #endif /*defined(FEATURE_EXTENDED_TRANSLATION_FACILITY_2)*/ #if defined(FEATURE_EXTENDED_TRANSLATION_FACILITY_2) /*-------------------------------------------------------------------*/ /* EB8E MVCLU - Move Long Unicode [RSY] */ /*-------------------------------------------------------------------*/ DEF_INST(move_long_unicode) { int r1, r3; /* Register numbers */ int b2; /* effective address base */ VADR effective_addr2; /* effective address */ int i; /* Loop counter */ int cc; /* Condition code */ VADR addr1, addr3; /* Operand addresses */ GREG len1, len3; /* Operand lengths */ U16 odbyte; /* Operand double byte */ U16 pad; /* Padding double byte */ int cpu_length; /* cpu determined length */ RSY(inst, regs, r1, r3, b2, effective_addr2); ODD2_CHECK(r1, r3, regs); /* Load operand lengths from bits 0-31 of R1+1 and R3+1 */ len1 = GR_A(r1 + 1, regs); len3 = GR_A(r3 + 1, regs); ODD2_CHECK(len1, len3, regs); /* Load padding doublebyte from bits 48-63 of effective address */ pad = effective_addr2 & 0xFFFF; /* Determine the destination and source addresses */ addr1 = regs->GR(r1) & ADDRESS_MAXWRAP(regs); addr3 = regs->GR(r3) & ADDRESS_MAXWRAP(regs); /* set cpu_length as shortest distance to new page */ if ((addr1 & 0xFFF) > (addr3 & 0xFFF)) cpu_length = 0x1000 - (addr1 & 0xFFF); else cpu_length = 0x1000 - (addr3 & 0xFFF); /* Set the condition code according to the lengths */ cc = (len1 < len3) ? 1 : (len1 > len3) ? 2 : 0; /* Process operands from left to right */ for (i = 0; len1 > 0; i += 2) { /* If cpu determined length has been moved, exit with cc=3 */ if (i >= cpu_length) { cc = 3; break; } /* Fetch byte from source operand, or use padding double byte */ if (len3 > 0) { odbyte = ARCH_DEP(vfetch2) ( addr3, r3, regs ); addr3 += 2; addr3 &= ADDRESS_MAXWRAP(regs); len3 -= 2; } else odbyte = pad; /* Store the double byte in the destination operand */ ARCH_DEP(vstore2) ( odbyte, addr1, r1, regs ); addr1 +=2; addr1 &= ADDRESS_MAXWRAP(regs); len1 -= 2; /* Update the registers */ SET_GR_A(r1, regs, addr1); SET_GR_A(r1 + 1, regs, len1); SET_GR_A(r3, regs, addr3); SET_GR_A(r3 + 1, regs, len3); } /* end for(i) */ regs->psw.cc = cc; } /* end DEF_INST(move_long_unicode) */ #endif /*defined(FEATURE_EXTENDED_TRANSLATION_FACILITY_2)*/ #if defined(FEATURE_EXTENDED_TRANSLATION_FACILITY_2) /*-------------------------------------------------------------------*/ /* EB8F CLCLU - Compare Logical Long Unicode [RSY] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_logical_long_unicode) { int r1, r3; /* Register numbers */ int b2; /* effective address base */ VADR effective_addr2; /* effective address */ int i; /* Loop counter */ int cc = 0; /* Condition code */ VADR addr1, addr3; /* Operand addresses */ GREG len1, len3; /* Operand lengths */ U16 dbyte1, dbyte3; /* Operand double bytes */ U16 pad; /* Padding double byte */ int cpu_length; /* cpu determined length */ RSY(inst, regs, r1, r3, b2, effective_addr2); ODD2_CHECK(r1, r3, regs); /* Load operand lengths from bits 0-31 of R1+1 and R3+1 */ len1 = GR_A(r1 + 1, regs); len3 = GR_A(r3 + 1, regs); ODD2_CHECK(len1, len3, regs); /* Load padding doublebyte from bits 48-64 of effective address */ pad = effective_addr2 & 0xFFFF; /* Determine the destination and source addresses */ addr1 = regs->GR(r1) & ADDRESS_MAXWRAP(regs); addr3 = regs->GR(r3) & ADDRESS_MAXWRAP(regs); /* set cpu_length as shortest distance to new page */ if ((addr1 & 0xFFF) > (addr3 & 0xFFF)) cpu_length = 0x1000 - (addr1 & 0xFFF); else cpu_length = 0x1000 - (addr3 & 0xFFF); /* Process operands from left to right */ for (i = 0; len1 > 0 || len3 > 0 ; i += 2) { /* If max 4096 bytes have been compared, exit with cc=3 */ if (i >= cpu_length) { cc = 3; break; } /* Fetch a byte from each operand, or use padding double byte */ dbyte1 = (len1 > 0) ? ARCH_DEP(vfetch2) (addr1, r1, regs) : pad; dbyte3 = (len3 > 0) ? ARCH_DEP(vfetch2) (addr3, r3, regs) : pad; /* Compare operand bytes, set condition code if unequal */ if (dbyte1 != dbyte3) { cc = (dbyte1 < dbyte3) ? 1 : 2; break; } /* end if */ /* Update the first operand address and length */ if (len1 > 0) { addr1 += 2; addr1 &= ADDRESS_MAXWRAP(regs); len1 -= 2; } /* Update the second operand address and length */ if (len3 > 0) { addr3 += 2; addr3 &= ADDRESS_MAXWRAP(regs); len3 -= 2; } } /* end for(i) */ /* Update the registers */ SET_GR_A(r1, regs, addr1); SET_GR_A(r1 + 1, regs, len1); SET_GR_A(r3, regs, addr3); SET_GR_A(r3 + 1, regs, len3); regs->psw.cc = cc; } /* end DEF_INST(compare_logical_long_unicode) */ #endif /*defined(FEATURE_EXTENDED_TRANSLATION_FACILITY_2)*/ #if defined(FEATURE_LONG_DISPLACEMENT) /*-------------------------------------------------------------------*/ /* E376 LB - Load Byte [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(load_byte) { int r1; /* Value of R field */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ RXY(inst, regs, r1, b2, effective_addr2); /* Load sign-extended byte from operand address */ regs->GR_L(r1) = (S8)ARCH_DEP(vfetchb) ( effective_addr2, b2, regs ); } /* end DEF_INST(load_byte) */ #endif /*defined(FEATURE_LONG_DISPLACEMENT)*/ #if defined(FEATURE_LONG_DISPLACEMENT) /*-------------------------------------------------------------------*/ /* E377 LGB - Load Byte Long [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(load_byte_long) { int r1; /* Value of R field */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ RXY(inst, regs, r1, b2, effective_addr2); /* Load sign-extended byte from operand address */ regs->GR_G(r1) = (S8)ARCH_DEP(vfetchb) ( effective_addr2, b2, regs ); } /* end DEF_INST(load_byte_long) */ #endif /*defined(FEATURE_LONG_DISPLACEMENT)*/ #if defined(FEATURE_LONG_DISPLACEMENT) /*-------------------------------------------------------------------*/ /* E35A AY - Add (Long Displacement) [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(add_y) { int r1; /* Values of R fields */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ U32 n; /* 32-bit operand values */ RXY(inst, regs, r1, b2, effective_addr2); /* Load second operand from operand address */ n = ARCH_DEP(vfetch4) ( effective_addr2, b2, regs ); /* Add signed operands and set condition code */ regs->psw.cc = add_signed (&(regs->GR_L(r1)), regs->GR_L(r1), n); /* Program check if fixed-point overflow */ if ( regs->psw.cc == 3 && FOMASK(®s->psw) ) regs->program_interrupt (regs, PGM_FIXED_POINT_OVERFLOW_EXCEPTION); } /* end DEF_INST(add_y) */ #endif /*defined(FEATURE_LONG_DISPLACEMENT)*/ #if defined(FEATURE_LONG_DISPLACEMENT) /*-------------------------------------------------------------------*/ /* E37A AHY - Add Halfword (Long Displacement) [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(add_halfword_y) { int r1; /* Value of R field */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ S32 n; /* 32-bit operand values */ RXY(inst, regs, r1, b2, effective_addr2); /* Load 2 bytes from operand address */ n = (S16)ARCH_DEP(vfetch2) ( effective_addr2, b2, regs ); /* Add signed operands and set condition code */ regs->psw.cc = add_signed (&(regs->GR_L(r1)), regs->GR_L(r1), (U32)n); /* Program check if fixed-point overflow */ if ( regs->psw.cc == 3 && FOMASK(®s->psw) ) regs->program_interrupt (regs, PGM_FIXED_POINT_OVERFLOW_EXCEPTION); } /* end DEF_INST(add_halfword_y) */ #endif /*defined(FEATURE_LONG_DISPLACEMENT)*/ #if defined(FEATURE_LONG_DISPLACEMENT) /*-------------------------------------------------------------------*/ /* E35E ALY - Add Logical (Long Displacement) [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(add_logical_y) { int r1; /* Value of R field */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ U32 n; /* 32-bit operand values */ RXY(inst, regs, r1, b2, effective_addr2); /* Load second operand from operand address */ n = ARCH_DEP(vfetch4) ( effective_addr2, b2, regs ); /* Add signed operands and set condition code */ regs->psw.cc = add_logical (&(regs->GR_L(r1)), regs->GR_L(r1), n); } /* end DEF_INST(add_logical_y) */ #endif /*defined(FEATURE_LONG_DISPLACEMENT)*/ #if defined(FEATURE_LONG_DISPLACEMENT) /*-------------------------------------------------------------------*/ /* EB54 NIY - And Immediate (Long Displacement) [SIY] */ /*-------------------------------------------------------------------*/ DEF_INST(and_immediate_y) { BYTE i2; /* Immediate byte of opcode */ int b1; /* Base of effective addr */ VADR effective_addr1; /* Effective address */ BYTE rbyte; /* Result byte */ SIY(inst, regs, i2, b1, effective_addr1); /* Fetch byte from operand address */ rbyte = ARCH_DEP(vfetchb) ( effective_addr1, b1, regs ); /* AND with immediate operand */ rbyte &= i2; /* Store result at operand address */ ARCH_DEP(vstoreb) ( rbyte, effective_addr1, b1, regs ); /* Set condition code */ regs->psw.cc = rbyte ? 1 : 0; } /* end DEF_INST(and_immediate_y) */ #endif /*defined(FEATURE_LONG_DISPLACEMENT)*/ #if defined(FEATURE_LONG_DISPLACEMENT) /*-------------------------------------------------------------------*/ /* E354 NY - And (Long Displacement) [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(and_y) { int r1; /* Value of R field */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ U32 n; /* 32-bit operand values */ RXY(inst, regs, r1, b2, effective_addr2); /* Load second operand from operand address */ n = ARCH_DEP(vfetch4) ( effective_addr2, b2, regs ); /* AND second operand with first and set condition code */ regs->psw.cc = ( regs->GR_L(r1) &= n ) ? 1 : 0; } /* end DEF_INST(and_y) */ #endif /*defined(FEATURE_LONG_DISPLACEMENT)*/ #if defined(FEATURE_LONG_DISPLACEMENT) /*-------------------------------------------------------------------*/ /* E359 CY - Compare (Long Displacement) [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_y) { int r1; /* Values of R fields */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ U32 n; /* 32-bit operand values */ RXY(inst, regs, r1, b2, effective_addr2); /* Load second operand from operand address */ n = ARCH_DEP(vfetch4) ( effective_addr2, b2, regs ); /* Compare signed operands and set condition code */ regs->psw.cc = (S32)regs->GR_L(r1) < (S32)n ? 1 : (S32)regs->GR_L(r1) > (S32)n ? 2 : 0; } /* end DEF_INST(compare_y) */ #endif /*defined(FEATURE_LONG_DISPLACEMENT)*/ #if defined(FEATURE_LONG_DISPLACEMENT) /*-------------------------------------------------------------------*/ /* E379 CHY - Compare Halfword (Long Displacement) [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_halfword_y) { int r1; /* Values of R fields */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ S32 n; /* 32-bit operand values */ RXY(inst, regs, r1, b2, effective_addr2); /* Load rightmost 2 bytes of comparand from operand address */ n = (S16)ARCH_DEP(vfetch2) ( effective_addr2, b2, regs ); /* Compare signed operands and set condition code */ regs->psw.cc = (S32)regs->GR_L(r1) < n ? 1 : (S32)regs->GR_L(r1) > n ? 2 : 0; } /* end DEF_INST(compare_halfword_y) */ #endif /*defined(FEATURE_LONG_DISPLACEMENT)*/ #if defined(FEATURE_LONG_DISPLACEMENT) /*-------------------------------------------------------------------*/ /* E355 CLY - Compare Logical (Long Displacement) [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_logical_y) { int r1; /* Values of R fields */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ U32 n; /* 32-bit operand values */ RXY(inst, regs, r1, b2, effective_addr2); /* Load second operand from operand address */ n = ARCH_DEP(vfetch4) ( effective_addr2, b2, regs ); /* Compare unsigned operands and set condition code */ regs->psw.cc = regs->GR_L(r1) < n ? 1 : regs->GR_L(r1) > n ? 2 : 0; } /* end DEF_INST(compare_logical_y) */ #endif /*defined(FEATURE_LONG_DISPLACEMENT)*/ #if defined(FEATURE_LONG_DISPLACEMENT) /*-------------------------------------------------------------------*/ /* EB55 CLIY - Compare Logical Immediate (Long Displacement) [SIY] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_logical_immediate_y) { BYTE i2; /* Immediate byte */ int b1; /* Base of effective addr */ VADR effective_addr1; /* Effective address */ BYTE cbyte; /* Compare byte */ SIY(inst, regs, i2, b1, effective_addr1); /* Fetch byte from operand address */ cbyte = ARCH_DEP(vfetchb) ( effective_addr1, b1, regs ); /* Compare with immediate operand and set condition code */ regs->psw.cc = (cbyte < i2) ? 1 : (cbyte > i2) ? 2 : 0; } /* end DEF_INST(compare_logical_immediate_y) */ #endif /*defined(FEATURE_LONG_DISPLACEMENT)*/ #if defined(FEATURE_LONG_DISPLACEMENT) /*-------------------------------------------------------------------*/ /* EB21 CLMY - Compare Logical Characters under Mask Long Disp[RSY] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_logical_characters_under_mask_y) { int r1, r3; /* Register numbers */ int b2; /* effective address base */ VADR effective_addr2; /* effective address */ int i, j; /* Integer work areas */ int cc = 0; /* Condition code */ BYTE rbyte[4], /* Register bytes */ vbyte; /* Virtual storage byte */ RSY(inst, regs, r1, r3, b2, effective_addr2); /* Set register bytes by mask */ i = 0; if (r3 & 0x8) rbyte[i++] = (regs->GR_L(r1) >> 24) & 0xFF; if (r3 & 0x4) rbyte[i++] = (regs->GR_L(r1) >> 16) & 0xFF; if (r3 & 0x2) rbyte[i++] = (regs->GR_L(r1) >> 8) & 0xFF; if (r3 & 0x1) rbyte[i++] = (regs->GR_L(r1) ) & 0xFF; /* Perform access check if mask is 0 */ if (!r3) ARCH_DEP(vfetchb) (effective_addr2, b2, regs); /* Compare byte by byte */ for (j = 0; j < i && !cc; j++) { effective_addr2 &= ADDRESS_MAXWRAP(regs); vbyte = ARCH_DEP(vfetchb) (effective_addr2++, b2, regs); if (rbyte[j] != vbyte) cc = rbyte[j] < vbyte ? 1 : 2; } regs->psw.cc = cc; } /* end DEF_INST(compare_logical_characters_under_mask_y) */ #endif /*defined(FEATURE_LONG_DISPLACEMENT)*/ #if defined(FEATURE_LONG_DISPLACEMENT) /*-------------------------------------------------------------------*/ /* EB14 CSY - Compare and Swap (Long Displacement) [RSY] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_and_swap_y) { int r1, r3; /* Register numbers */ int b2; /* effective address base */ VADR effective_addr2; /* effective address */ BYTE *main2; /* mainstor address */ U32 old; /* old value */ RSY(inst, regs, r1, r3, b2, effective_addr2); FW_CHECK(effective_addr2, regs); /* Perform serialization before starting operation */ PERFORM_SERIALIZATION (regs); /* Get operand mainstor address */ main2 = MADDR (effective_addr2, b2, regs, ACCTYPE_WRITE, regs->psw.pkey); /* Get old value */ old = CSWAP32(regs->GR_L(r1)); /* Obtain main-storage access lock */ OBTAIN_MAINLOCK(regs); /* Attempt to exchange the values */ regs->psw.cc = cmpxchg4 (&old, CSWAP32(regs->GR_L(r3)), main2); /* Release main-storage access lock */ RELEASE_MAINLOCK(regs); /* Perform serialization after completing operation */ PERFORM_SERIALIZATION (regs); if (regs->psw.cc == 1) { regs->GR_L(r1) = CSWAP32(old); #if defined(_FEATURE_SIE) if(SIE_STATB(regs, IC0, CS1)) { if( !OPEN_IC_PER(regs) ) longjmp(regs->progjmp, SIE_INTERCEPT_INST); else longjmp(regs->progjmp, SIE_INTERCEPT_INSTCOMP); } else #endif /*defined(_FEATURE_SIE)*/ if (sysblk.cpus > 1) sched_yield(); } } /* end DEF_INST(compare_and_swap_y) */ #endif /*defined(FEATURE_LONG_DISPLACEMENT)*/ #if defined(FEATURE_LONG_DISPLACEMENT) /*-------------------------------------------------------------------*/ /* EB31 CDSY - Compare Double and Swap (Long Displacement) [RSY] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_double_and_swap_y) { int r1, r3; /* Register numbers */ int b2; /* effective address base */ VADR effective_addr2; /* effective address */ BYTE *main2; /* mainstor address */ U64 old, new; /* old, new values */ RSY(inst, regs, r1, r3, b2, effective_addr2); ODD2_CHECK(r1, r3, regs); DW_CHECK(effective_addr2, regs); /* Perform serialization before starting operation */ PERFORM_SERIALIZATION (regs); /* Get operand mainstor address */ main2 = MADDR (effective_addr2, b2, regs, ACCTYPE_WRITE, regs->psw.pkey); /* Get old, new values */ old = CSWAP64(((U64)(regs->GR_L(r1)) << 32) | regs->GR_L(r1+1)); new = CSWAP64(((U64)(regs->GR_L(r3)) << 32) | regs->GR_L(r3+1)); /* Obtain main-storage access lock */ OBTAIN_MAINLOCK(regs); /* Attempt to exchange the values */ regs->psw.cc = cmpxchg8 (&old, new, main2); /* Release main-storage access lock */ RELEASE_MAINLOCK(regs); /* Perform serialization after completing operation */ PERFORM_SERIALIZATION (regs); if (regs->psw.cc == 1) { regs->GR_L(r1) = CSWAP64(old) >> 32; regs->GR_L(r1+1) = CSWAP64(old) & 0xffffffff; #if defined(_FEATURE_SIE) if(SIE_STATB(regs, IC0, CS1)) { if( !OPEN_IC_PER(regs) ) longjmp(regs->progjmp, SIE_INTERCEPT_INST); else longjmp(regs->progjmp, SIE_INTERCEPT_INSTCOMP); } else #endif /*defined(_FEATURE_SIE)*/ if (sysblk.cpus > 1) sched_yield(); } } /* end DEF_INST(compare_double_and_swap_y) */ #endif /*defined(FEATURE_LONG_DISPLACEMENT)*/ #if defined(FEATURE_LONG_DISPLACEMENT) /*-------------------------------------------------------------------*/ /* E306 CVBY - Convert to Binary (Long Displacement) [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(convert_to_binary_y) { U64 dreg; /* 64-bit result accumulator */ int r1; /* Value of R1 field */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ int ovf; /* 1=overflow */ int dxf; /* 1=data exception */ BYTE dec[8]; /* Packed decimal operand */ RXY(inst, regs, r1, b2, effective_addr2); /* Fetch 8-byte packed decimal operand */ ARCH_DEP(vfetchc) (dec, 8-1, effective_addr2, b2, regs); /* Convert 8-byte packed decimal to 64-bit signed binary */ packed_to_binary (dec, 8-1, &dreg, &ovf, &dxf); /* Data exception if invalid digits or sign */ if (dxf) { regs->dxc = DXC_DECIMAL; regs->program_interrupt (regs, PGM_DATA_EXCEPTION); } /* Overflow if result exceeds 31 bits plus sign */ if ((S64)dreg < -2147483648LL || (S64)dreg > 2147483647LL) ovf = 1; /* Store low-order 32 bits of result into R1 register */ regs->GR_L(r1) = dreg & 0xFFFFFFFF; /* Program check if overflow (R1 contains rightmost 32 bits) */ if (ovf) regs->program_interrupt (regs, PGM_FIXED_POINT_DIVIDE_EXCEPTION); } #endif /*defined(FEATURE_LONG_DISPLACEMENT)*/ #if defined(FEATURE_LONG_DISPLACEMENT) /*-------------------------------------------------------------------*/ /* E326 CVDY - Convert to Decimal (Long Displacement) [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(convert_to_decimal_y) { S64 bin; /* 64-bit signed binary value*/ int r1; /* Value of R1 field */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ BYTE dec[16]; /* Packed decimal result */ RXY(inst, regs, r1, b2, effective_addr2); /* Load value of register and sign-extend to 64 bits */ bin = (S64)((S32)(regs->GR_L(r1))); /* Convert to 16-byte packed decimal number */ binary_to_packed (bin, dec); /* Store low 8 bytes of result at operand address */ ARCH_DEP(vstorec) ( dec+8, 8-1, effective_addr2, b2, regs ); } /* end DEF_INST(convert_to_decimal_y) */ #endif /*defined(FEATURE_LONG_DISPLACEMENT)*/ #if defined(FEATURE_LONG_DISPLACEMENT) /*-------------------------------------------------------------------*/ /* EB57 XIY - Exclusive Or Immediate (Long Displacement) [SIY] */ /*-------------------------------------------------------------------*/ DEF_INST(exclusive_or_immediate_y) { BYTE i2; /* Immediate operand */ int b1; /* Base of effective addr */ VADR effective_addr1; /* Effective address */ BYTE rbyte; /* Result byte */ SIY(inst, regs, i2, b1, effective_addr1); /* Fetch byte from operand address */ rbyte = ARCH_DEP(vfetchb) ( effective_addr1, b1, regs ); /* XOR with immediate operand */ rbyte ^= i2; /* Store result at operand address */ ARCH_DEP(vstoreb) ( rbyte, effective_addr1, b1, regs ); /* Set condition code */ regs->psw.cc = rbyte ? 1 : 0; } /* end DEF_INST(exclusive_or_immediate_y) */ #endif /*defined(FEATURE_LONG_DISPLACEMENT)*/ #if defined(FEATURE_LONG_DISPLACEMENT) /*-------------------------------------------------------------------*/ /* E357 XY - Exclusive Or (Long Displacement) [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(exclusive_or_y) { int r1; /* Values of R fields */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ U32 n; /* 32-bit operand values */ RXY(inst, regs, r1, b2, effective_addr2); /* Load second operand from operand address */ n = ARCH_DEP(vfetch4) ( effective_addr2, b2, regs ); /* XOR second operand with first and set condition code */ regs->psw.cc = ( regs->GR_L(r1) ^= n ) ? 1 : 0; } /* end DEF_INST(exclusive_or_y) */ #endif /*defined(FEATURE_LONG_DISPLACEMENT)*/ #if defined(FEATURE_LONG_DISPLACEMENT) /*-------------------------------------------------------------------*/ /* E373 ICY - Insert Character (Long Displacement) [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(insert_character_y) { int r1; /* Value of R field */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ RXY(inst, regs, r1, b2, effective_addr2); /* Insert character in r1 register */ regs->GR_LHLCL(r1) = ARCH_DEP(vfetchb) ( effective_addr2, b2, regs ); } /* end DEF_INST(insert_character_y) */ #endif /*defined(FEATURE_LONG_DISPLACEMENT)*/ #if defined(FEATURE_LONG_DISPLACEMENT) /*-------------------------------------------------------------------*/ /* EB81 ICMY - Insert Characters under Mask Long Displacement [RSY] */ /*-------------------------------------------------------------------*/ DEF_INST(insert_characters_under_mask_y) { int r1, r3; /* Register numbers */ int b2; /* effective address base */ VADR effective_addr2; /* effective address */ int i; /* Integer work area */ BYTE vbyte[4]; /* Fetched storage bytes */ U32 n; /* Fetched value */ static const int /* Length-1 to fetch by mask */ icmylen[16] = {0, 0, 0, 1, 0, 1, 1, 2, 0, 1, 1, 2, 1, 2, 2, 3}; static const unsigned int /* Turn reg bytes off by mask*/ icmymask[16] = {0xFFFFFFFF, 0xFFFFFF00, 0xFFFF00FF, 0xFFFF0000, 0xFF00FFFF, 0xFF00FF00, 0xFF0000FF, 0xFF000000, 0x00FFFFFF, 0x00FFFF00, 0x00FF00FF, 0x00FF0000, 0x0000FFFF, 0x0000FF00, 0x000000FF, 0x00000000}; RSY(inst, regs, r1, r3, b2, effective_addr2); switch (r3) { case 15: /* Optimized case */ regs->GR_L(r1) = ARCH_DEP(vfetch4) (effective_addr2, b2, regs); regs->psw.cc = regs->GR_L(r1) ? regs->GR_L(r1) & 0x80000000 ? 1 : 2 : 0; break; default: memset (vbyte, 0, 4); ARCH_DEP(vfetchc)(vbyte, icmylen[r3], effective_addr2, b2, regs); /* If mask was 0 then we still had to fetch, according to POP. If so, set the fetched byte to 0 to force zero cc */ if (!r3) vbyte[0] = 0; n = fetch_fw (vbyte); regs->psw.cc = n ? n & 0x80000000 ? 1 : 2 : 0; /* Turn off the reg bytes we are going to set */ regs->GR_L(r1) &= icmymask[r3]; /* Set bytes one at a time according to the mask */ i = 0; if (r3 & 0x8) regs->GR_L(r1) |= vbyte[i++] << 24; if (r3 & 0x4) regs->GR_L(r1) |= vbyte[i++] << 16; if (r3 & 0x2) regs->GR_L(r1) |= vbyte[i++] << 8; if (r3 & 0x1) regs->GR_L(r1) |= vbyte[i]; break; } /* switch (r3) */ } /* end DEF_INST(insert_characters_under_mask_y) */ #endif /*defined(FEATURE_LONG_DISPLACEMENT)*/ #if defined(FEATURE_LONG_DISPLACEMENT) /*-------------------------------------------------------------------*/ /* E358 LY - Load (Long Displacement) [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(load_y) { int r1; /* Value of R field */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ RXY(inst, regs, r1, b2, effective_addr2); /* Load R1 register from second operand */ regs->GR_L(r1) = ARCH_DEP(vfetch4) ( effective_addr2, b2, regs ); } /* end DEF_INST(load_y) */ #endif /*defined(FEATURE_LONG_DISPLACEMENT)*/ #if defined(FEATURE_LONG_DISPLACEMENT) #if defined(FEATURE_ACCESS_REGISTERS) /*-------------------------------------------------------------------*/ /* EB9A LAMY - Load Access Multiple (Long Displacement) [RSY] */ /*-------------------------------------------------------------------*/ DEF_INST(load_access_multiple_y) { int r1, r3; /* Register numbers */ int b2; /* effective address base */ VADR effective_addr2; /* effective address */ int i, m, n; /* Integer work areas */ U32 *p1, *p2 = NULL; /* Mainstor pointers */ RSY(inst, regs, r1, r3, b2, effective_addr2); FW_CHECK(effective_addr2, regs); /* Calculate number of regs to load */ n = ((r3 - r1) & 0xF) + 1; /* Calculate number of words to next boundary */ m = (0x800 - (effective_addr2 & 0x7ff)) >> 2; /* Address of operand beginning */ p1 = (U32*)MADDR(effective_addr2, b2, regs, ACCTYPE_READ, regs->psw.pkey); /* Get address of next page if boundary crossed */ if (unlikely (m < n)) p2 = (U32*)MADDR(effective_addr2 + (m*4), b2, regs, ACCTYPE_READ, regs->psw.pkey); else m = n; /* Load from first page */ for (i = 0; i < m; i++, p1++) { regs->AR((r1 + i) & 0xF) = fetch_fw (p1); SET_AEA_AR(regs, (r1 + i) & 0xF); } /* Load from next page */ for ( ; i < n; i++, p2++) { regs->AR((r1 + i) & 0xF) = fetch_fw (p2); SET_AEA_AR(regs, (r1 + i) & 0xF); } } /* end DEF_INST(load_access_multiple_y) */ #endif /*defined(FEATURE_ACCESS_REGISTERS)*/ #endif /*defined(FEATURE_LONG_DISPLACEMENT)*/ #if defined(FEATURE_LONG_DISPLACEMENT) /*-------------------------------------------------------------------*/ /* E371 LAY - Load Address (Long Displacement) [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(load_address_y) { int r1; /* Value of R field */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ RXY0(inst, regs, r1, b2, effective_addr2); /* Load operand address into register */ SET_GR_A(r1, regs, effective_addr2); } /* end DEF_INST(load_address_y) */ #endif /*defined(FEATURE_LONG_DISPLACEMENT)*/ #if defined(FEATURE_LONG_DISPLACEMENT) /*-------------------------------------------------------------------*/ /* E378 LHY - Load Halfword (Long Displacement) [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(load_halfword_y) { int r1; /* Value of R field */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ RXY(inst, regs, r1, b2, effective_addr2); /* Load rightmost 2 bytes of register from operand address */ regs->GR_L(r1) = (S16)ARCH_DEP(vfetch2) ( effective_addr2, b2, regs ); } /* end DEF_INST(load_halfword_y) */ #endif /*defined(FEATURE_LONG_DISPLACEMENT)*/ #if defined(FEATURE_LONG_DISPLACEMENT) /*-------------------------------------------------------------------*/ /* EB98 LMY - Load Multiple (Long Displacement) [RSY] */ /*-------------------------------------------------------------------*/ DEF_INST(load_multiple_y) { int r1, r3; /* Register numbers */ int b2; /* effective address base */ VADR effective_addr2; /* effective address */ int i, m, n; /* Integer work areas */ U32 *p1, *p2; /* Mainstor pointers */ RSY(inst, regs, r1, r3, b2, effective_addr2); /* Calculate number of bytes to load */ n = (((r3 - r1) & 0xF) + 1) << 2; /* Calculate number of bytes to next boundary */ m = 0x800 - ((VADR_L)effective_addr2 & 0x7ff); /* Address of operand beginning */ p1 = (U32*)MADDR(effective_addr2, b2, regs, ACCTYPE_READ, regs->psw.pkey); if (likely(n <= m)) { /* Boundary not crossed */ n >>= 2; for (i = 0; i < n; i++, p1++) regs->GR_L((r1 + i) & 0xF) = fetch_fw (p1); } else { /* Boundary crossed, get 2nd page address */ effective_addr2 += m; effective_addr2 &= ADDRESS_MAXWRAP(regs); p2 = (U32*)MADDR(effective_addr2, b2, regs, ACCTYPE_READ, regs->psw.pkey); if (likely((m & 0x3) == 0)) { /* Addresses are word aligned */ m >>= 2; for (i = 0; i < m; i++, p1++) regs->GR_L((r1 + i) & 0xF) = fetch_fw (p1); n >>= 2; for ( ; i < n; i++, p2++) regs->GR_L((r1 + i) & 0xF) = fetch_fw (p2); } else { /* Worst case */ U32 rwork[16]; BYTE *b1, *b2; b1 = (BYTE *)&rwork[0]; b2 = (BYTE *)p1; for (i = 0; i < m; i++) *b1++ = *b2++; b2 = (BYTE *)p2; for ( ; i < n; i++) *b1++ = *b2++; n >>= 2; for (i = 0; i < n; i++) regs->GR_L((r1 + i) & 0xF) = CSWAP32(rwork[i]); } } } /* end DEF_INST(load_multiple_y) */ #endif /*defined(FEATURE_LONG_DISPLACEMENT)*/ #if defined(FEATURE_LONG_DISPLACEMENT) /*-------------------------------------------------------------------*/ /* E313 LRAY - Load Real Address (Long Displacement) [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(load_real_address_y) { int r1; /* Register number */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ RXY(inst, regs, r1, b2, effective_addr2); ARCH_DEP(load_real_address_proc) (regs, r1, b2, effective_addr2); } /* end DEF_INST(load_real_address_y) */ #endif /*defined(FEATURE_LONG_DISPLACEMENT)*/ #if defined(FEATURE_LONG_DISPLACEMENT) /*-------------------------------------------------------------------*/ /* EB52 MVIY - Move Immediate (Long Displacement) [SIY] */ /*-------------------------------------------------------------------*/ DEF_INST(move_immediate_y) { BYTE i2; /* Immediate operand */ int b1; /* Base of effective addr */ VADR effective_addr1; /* Effective address */ SIY(inst, regs, i2, b1, effective_addr1); /* Store immediate operand at operand address */ ARCH_DEP(vstoreb) ( i2, effective_addr1, b1, regs ); } /* end DEF_INST(move_immediate_y) */ #endif /*defined(FEATURE_LONG_DISPLACEMENT)*/ #if defined(FEATURE_LONG_DISPLACEMENT) /*-------------------------------------------------------------------*/ /* E351 MSY - Multiply Single (Long Displacement) [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(multiply_single_y) { int r1; /* Value of R field */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ S32 n; /* 32-bit operand values */ RXY(inst, regs, r1, b2, effective_addr2); /* Load second operand from operand address */ n = (S32)ARCH_DEP(vfetch4) ( effective_addr2, b2, regs ); /* Multiply signed operands ignoring overflow */ regs->GR_L(r1) = (S32)regs->GR_L(r1) * n; } /* end DEF_INST(multiply_single) */ #endif /*defined(FEATURE_LONG_DISPLACEMENT)*/ #if defined(FEATURE_LONG_DISPLACEMENT) /*-------------------------------------------------------------------*/ /* EB56 OIY - Or Immediate (Long Displacement) [SIY] */ /*-------------------------------------------------------------------*/ DEF_INST(or_immediate_y) { BYTE i2; /* Immediate operand byte */ int b1; /* Base of effective addr */ VADR effective_addr1; /* Effective address */ BYTE rbyte; /* Result byte */ SIY(inst, regs, i2, b1, effective_addr1); /* Fetch byte from operand address */ rbyte = ARCH_DEP(vfetchb) ( effective_addr1, b1, regs ); /* OR with immediate operand */ rbyte |= i2; /* Store result at operand address */ ARCH_DEP(vstoreb) ( rbyte, effective_addr1, b1, regs ); /* Set condition code */ regs->psw.cc = rbyte ? 1 : 0; } /* end DEF_INST(or_immediate_y) */ #endif /*defined(FEATURE_LONG_DISPLACEMENT)*/ #if defined(FEATURE_LONG_DISPLACEMENT) /*-------------------------------------------------------------------*/ /* E356 OY - Or (Long Displacement) [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(or_y) { int r1; /* Value of R field */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ U32 n; /* 32-bit operand values */ RXY(inst, regs, r1, b2, effective_addr2); /* Load second operand from operand address */ n = ARCH_DEP(vfetch4) ( effective_addr2, b2, regs ); /* OR second operand with first and set condition code */ regs->psw.cc = ( regs->GR_L(r1) |= n ) ? 1 : 0; } /* end DEF_INST(or_y) */ #endif /*defined(FEATURE_LONG_DISPLACEMENT)*/ #if defined(FEATURE_LONG_DISPLACEMENT) /*-------------------------------------------------------------------*/ /* E350 STY - Store (Long Displacement) [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(store_y) { int r1; /* Values of R fields */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ RXY(inst, regs, r1, b2, effective_addr2); /* Store register contents at operand address */ ARCH_DEP(vstore4) ( regs->GR_L(r1), effective_addr2, b2, regs ); } /* end DEF_INST(store_y) */ #endif /*defined(FEATURE_LONG_DISPLACEMENT)*/ #if defined(FEATURE_LONG_DISPLACEMENT) #if defined(FEATURE_ACCESS_REGISTERS) /*-------------------------------------------------------------------*/ /* EB9B STAMY - Store Access Multiple (Long Displacement) [RSY] */ /*-------------------------------------------------------------------*/ DEF_INST(store_access_multiple_y) { int r1, r3; /* Register numbers */ int b2; /* effective address base */ VADR effective_addr2; /* effective address */ int i, m, n; /* Integer work area */ U32 *p1, *p2 = NULL; /* Mainstor pointers */ RSY(inst, regs, r1, r3, b2, effective_addr2); FW_CHECK(effective_addr2, regs); /* Calculate number of regs to store */ n = ((r3 - r1) & 0xF) + 1; /* Store 4 bytes at a time */ ARCH_DEP(validate_operand)(effective_addr2, b2, (n*4) - 1, ACCTYPE_WRITE, regs); for (i = 0; i < n; i++) ARCH_DEP(vstore4)(regs->AR((r1 + i) & 0xF), effective_addr2 + (i*4), b2, regs); /* Calculate number of words to next boundary */ m = (0x800 - (effective_addr2 & 0x7ff)) >> 2; /* Address of operand beginning */ p1 = (U32*)MADDR(effective_addr2, b2, regs, ACCTYPE_WRITE, regs->psw.pkey); /* Get address of next page if boundary crossed */ if (unlikely(m < n)) p2 = (U32*)MADDR(effective_addr2 + (m*4), b2, regs, ACCTYPE_WRITE, regs->psw.pkey); else m = n; /* Store at operand beginning */ for (i = 0; i < m; i++) store_fw (p1++, regs->AR((r1 + i) & 0xF)); /* Store on next page */ for ( ; i < n; i++) store_fw (p2++, regs->AR((r1 + i) & 0xF)); } /* end DEF_INST(store_access_multiple_y) */ #endif /*defined(FEATURE_ACCESS_REGISTERS)*/ #endif /*defined(FEATURE_LONG_DISPLACEMENT)*/ #if defined(FEATURE_LONG_DISPLACEMENT) /*-------------------------------------------------------------------*/ /* E372 STCY - Store Character (Long Displacement) [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(store_character_y) { int r1; /* Value of R field */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ RXY(inst, regs, r1, b2, effective_addr2); /* Store rightmost byte of R1 register at operand address */ ARCH_DEP(vstoreb) ( regs->GR_LHLCL(r1), effective_addr2, b2, regs ); } /* end DEF_INST(store_character_y) */ #endif /*defined(FEATURE_LONG_DISPLACEMENT)*/ #if defined(FEATURE_LONG_DISPLACEMENT) /*-------------------------------------------------------------------*/ /* EB2D STCMY - Store Characters under Mask (Long Displacement)[RSY] */ /*-------------------------------------------------------------------*/ DEF_INST(store_characters_under_mask_y) { int r1, r3; /* Register numbers */ int b2; /* effective address base */ VADR effective_addr2; /* effective address */ int i; /* Integer work area */ BYTE rbyte[4]; /* Byte work area */ RSY(inst, regs, r1, r3, b2, effective_addr2); switch (r3) { case 15: /* Optimized case */ ARCH_DEP(vstore4) (regs->GR_L(r1), effective_addr2, b2, regs); break; default: /* Extract value from register by mask */ i = 0; if (r3 & 0x8) rbyte[i++] = (regs->GR_L(r1) >> 24) & 0xFF; if (r3 & 0x4) rbyte[i++] = (regs->GR_L(r1) >> 16) & 0xFF; if (r3 & 0x2) rbyte[i++] = (regs->GR_L(r1) >> 8) & 0xFF; if (r3 & 0x1) rbyte[i++] = (regs->GR_L(r1) ) & 0xFF; if (i) ARCH_DEP(vstorec) (rbyte, i-1, effective_addr2, b2, regs); #if defined(MODEL_DEPENDENT_STCM) /* If the mask is all zero, we nevertheless access one byte from the storage operand, because POP states that an access exception may be recognized on the first byte */ else ARCH_DEP(validate_operand) (effective_addr2, b2, 0, ACCTYPE_WRITE, regs); #endif break; } /* switch (r3) */ } /* end DEF_INST(store_characters_under_mask_y) */ #endif /*defined(FEATURE_LONG_DISPLACEMENT)*/ #if defined(FEATURE_LONG_DISPLACEMENT) /*-------------------------------------------------------------------*/ /* E370 STHY - Store Halfword (Long Displacement) [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(store_halfword_y) { int r1; /* Value of R field */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ RXY(inst, regs, r1, b2, effective_addr2); /* Store rightmost 2 bytes of R1 register at operand address */ ARCH_DEP(vstore2) ( regs->GR_LHL(r1), effective_addr2, b2, regs ); } /* end DEF_INST(store_halfword_y) */ #endif /*defined(FEATURE_LONG_DISPLACEMENT)*/ #if defined(FEATURE_LONG_DISPLACEMENT) /*-------------------------------------------------------------------*/ /* EB90 STMY - Store Multiple (Long Displacement) [RSY] */ /*-------------------------------------------------------------------*/ DEF_INST(store_multiple_y) { int r1, r3; /* Register numbers */ int b2; /* effective address base */ VADR effective_addr2; /* effective address */ int i, m, n; /* Integer work areas */ U32 *p1, *p2; /* Mainstor pointers */ RSY(inst, regs, r1, r3, b2, effective_addr2); /* Calculate number of bytes to store */ n = (((r3 - r1) & 0xF) + 1) << 2; /* Calculate number of bytes to next boundary */ m = 0x800 - ((VADR_L)effective_addr2 & 0x7ff); /* Get address of first page */ p1 = (U32*)MADDR(effective_addr2, b2, regs, ACCTYPE_WRITE, regs->psw.pkey); if (likely(n <= m)) { /* boundary not crossed */ n >>= 2; for (i = 0; i < n; i++) store_fw (p1++, regs->GR_L((r1 + i) & 0xF)); } else { /* boundary crossed, get address of the 2nd page */ effective_addr2 += m; effective_addr2 &= ADDRESS_MAXWRAP(regs); p2 = (U32*)MADDR(effective_addr2, b2, regs, ACCTYPE_WRITE, regs->psw.pkey); if (likely((m & 0x3) == 0)) { /* word aligned */ m >>= 2; for (i = 0; i < m; i++) store_fw (p1++, regs->GR_L((r1 + i) & 0xF)); n >>= 2; for ( ; i < n; i++) store_fw (p2++, regs->GR_L((r1 + i) & 0xF)); } else { /* worst case */ U32 rwork[16]; BYTE *b1, *b2; for (i = 0; i < (n >> 2); i++) rwork[i] = CSWAP32(regs->GR_L((r1 + i) & 0xF)); b1 = (BYTE *)&rwork[0]; b2 = (BYTE *)p1; for (i = 0; i < m; i++) *b2++ = *b1++; b2 = (BYTE *)p2; for ( ; i < n; i++) *b2++ = *b1++; } } } /* end DEF_INST(store_multiple_y) */ #endif /*defined(FEATURE_LONG_DISPLACEMENT)*/ #if defined(FEATURE_LONG_DISPLACEMENT) /*-------------------------------------------------------------------*/ /* E35B SY - Subtract (Long Displacement) [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(subtract_y) { int r1; /* Value of R field */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ U32 n; /* 32-bit operand values */ RXY(inst, regs, r1, b2, effective_addr2); /* Load second operand from operand address */ n = ARCH_DEP(vfetch4) ( effective_addr2, b2, regs ); /* Subtract signed operands and set condition code */ regs->psw.cc = sub_signed (&(regs->GR_L(r1)), regs->GR_L(r1), n); /* Program check if fixed-point overflow */ if ( regs->psw.cc == 3 && FOMASK(®s->psw) ) regs->program_interrupt (regs, PGM_FIXED_POINT_OVERFLOW_EXCEPTION); } /* end DEF_INST(subtract_y) */ #endif /*defined(FEATURE_LONG_DISPLACEMENT)*/ #if defined(FEATURE_LONG_DISPLACEMENT) /*-------------------------------------------------------------------*/ /* E37B SHY - Subtract Halfword (Long Displacement) [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(subtract_halfword_y) { int r1; /* Value of R field */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ S32 n; /* 32-bit operand values */ RXY(inst, regs, r1, b2, effective_addr2); /* Load 2 bytes from operand address */ n = (S16)ARCH_DEP(vfetch2) ( effective_addr2, b2, regs ); /* Subtract signed operands and set condition code */ regs->psw.cc = sub_signed (&(regs->GR_L(r1)), regs->GR_L(r1), (U32)n); /* Program check if fixed-point overflow */ if ( regs->psw.cc == 3 && FOMASK(®s->psw) ) regs->program_interrupt (regs, PGM_FIXED_POINT_OVERFLOW_EXCEPTION); } /* end DEF_INST(subtract_halfword_y) */ #endif /*defined(FEATURE_LONG_DISPLACEMENT)*/ #if defined(FEATURE_LONG_DISPLACEMENT) /*-------------------------------------------------------------------*/ /* E35F SLY - Subtract Logical (Long Displacement) [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(subtract_logical_y) { int r1; /* Value of R field */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ U32 n; /* 32-bit operand values */ RXY(inst, regs, r1, b2, effective_addr2); /* Load second operand from operand address */ n = ARCH_DEP(vfetch4) ( effective_addr2, b2, regs ); /* Subtract unsigned operands and set condition code */ regs->psw.cc = sub_logical (&(regs->GR_L(r1)), regs->GR_L(r1), n); } /* end DEF_INST(subtract_logical_y) */ #endif /*defined(FEATURE_LONG_DISPLACEMENT)*/ #if defined(FEATURE_LONG_DISPLACEMENT) /*-------------------------------------------------------------------*/ /* EB51 TMY - Test under Mask (Long Displacement) [SIY] */ /*-------------------------------------------------------------------*/ DEF_INST(test_under_mask_y) { BYTE i2; /* Immediate operand */ int b1; /* Base of effective addr */ VADR effective_addr1; /* Effective address */ BYTE tbyte; /* Work byte */ SIY(inst, regs, i2, b1, effective_addr1); /* Fetch byte from operand address */ tbyte = ARCH_DEP(vfetchb) ( effective_addr1, b1, regs ); /* AND with immediate operand mask */ tbyte &= i2; /* Set condition code according to result */ regs->psw.cc = ( tbyte == 0 ) ? 0 : /* result all zeroes */ ( tbyte == i2) ? 3 : /* result all ones */ 1 ; /* result mixed */ } /* end DEF_INST(test_under_mask_y) */ #endif /*defined(FEATURE_LONG_DISPLACEMENT)*/ #if defined(FEATURE_EXTENDED_IMMEDIATE) /*@Z9*/ /*-------------------------------------------------------------------*/ /* C2x9 AFI - Add Fullword Immediate [RIL] */ /*-------------------------------------------------------------------*/ DEF_INST(add_fullword_immediate) { int r1; /* Register number */ int opcd; /* Opcode */ U32 i2; /* 32-bit operand value */ RIL(inst, regs, r1, opcd, i2); /* Add signed operands and set condition code */ regs->psw.cc = add_signed (&(regs->GR_L(r1)), regs->GR_L(r1), (S32)i2); /* Program check if fixed-point overflow */ if ( regs->psw.cc == 3 && FOMASK(®s->psw) ) regs->program_interrupt (regs, PGM_FIXED_POINT_OVERFLOW_EXCEPTION); } /* end DEF_INST(add_fullword_immediate) */ /*-------------------------------------------------------------------*/ /* C2x8 AGFI - Add Long Fullword Immediate [RIL] */ /*-------------------------------------------------------------------*/ DEF_INST(add_long_fullword_immediate) { int r1; /* Register number */ int opcd; /* Opcode */ U32 i2; /* 32-bit operand value */ RIL(inst, regs, r1, opcd, i2); /* Add signed operands and set condition code */ regs->psw.cc = add_signed_long (&(regs->GR_G(r1)), regs->GR_G(r1), (S32)i2); /* Program check if fixed-point overflow */ if ( regs->psw.cc == 3 && FOMASK(®s->psw) ) regs->program_interrupt (regs, PGM_FIXED_POINT_OVERFLOW_EXCEPTION); } /* end DEF_INST(add_long_fullword_immediate) */ /*-------------------------------------------------------------------*/ /* C2xB ALFI - Add Logical Fullword Immediate [RIL] */ /*-------------------------------------------------------------------*/ DEF_INST(add_logical_fullword_immediate) { int r1; /* Register number */ int opcd; /* Opcode */ U32 i2; /* 32-bit operand value */ RIL0(inst, regs, r1, opcd, i2); /* Add signed operands and set condition code */ regs->psw.cc = add_logical (&(regs->GR_L(r1)), regs->GR_L(r1), i2); } /* end DEF_INST(add_logical_fullword_immediate) */ /*-------------------------------------------------------------------*/ /* C2xA ALGFI - Add Logical Long Fullword Immediate [RIL] */ /*-------------------------------------------------------------------*/ DEF_INST(add_logical_long_fullword_immediate) { int r1; /* Register number */ int opcd; /* Opcode */ U32 i2; /* 32-bit operand value */ RIL0(inst, regs, r1, opcd, i2); /* Add unsigned operands and set condition code */ regs->psw.cc = add_logical_long(&(regs->GR_G(r1)), regs->GR_G(r1), i2); } /* end DEF_INST(add_logical_long_fullword_immediate) */ /*-------------------------------------------------------------------*/ /* C0xA NIHF - And Immediate High Fullword [RIL] */ /*-------------------------------------------------------------------*/ DEF_INST(and_immediate_high_fullword) { int r1; /* Register number */ int opcd; /* Opcode */ U32 i2; /* 32-bit operand value */ RIL0(inst, regs, r1, opcd, i2); /* And fullword operand with high 32 bits of register */ regs->GR_H(r1) &= i2; /* Set condition code according to result */ regs->psw.cc = regs->GR_H(r1) ? 1 : 0; } /* end DEF_INST(and_immediate_high_fullword) */ /*-------------------------------------------------------------------*/ /* C0xB NILF - And Immediate Low Fullword [RIL] */ /*-------------------------------------------------------------------*/ DEF_INST(and_immediate_low_fullword) { int r1; /* Register number */ int opcd; /* Opcode */ U32 i2; /* 32-bit operand value */ RIL0(inst, regs, r1, opcd, i2); /* And fullword operand with low 32 bits of register */ regs->GR_L(r1) &= i2; /* Set condition code according to result */ regs->psw.cc = regs->GR_L(r1) ? 1 : 0; } /* end DEF_INST(and_immediate_low_fullword) */ /*-------------------------------------------------------------------*/ /* C2xD CFI - Compare Fullword Immediate [RIL] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_fullword_immediate) { int r1; /* Register number */ int opcd; /* Opcode */ U32 i2; /* 32-bit operand value */ RIL0(inst, regs, r1, opcd, i2); /* Compare signed operands and set condition code */ regs->psw.cc = (S32)regs->GR_L(r1) < (S32)i2 ? 1 : (S32)regs->GR_L(r1) > (S32)i2 ? 2 : 0; } /* end DEF_INST(compare_fullword_immediate) */ /*-------------------------------------------------------------------*/ /* C2xC CGFI - Compare Long Fullword Immediate [RIL] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_long_fullword_immediate) { int r1; /* Register number */ int opcd; /* Opcode */ U32 i2; /* 32-bit operand value */ RIL0(inst, regs, r1, opcd, i2); /* Compare signed operands and set condition code */ regs->psw.cc = (S64)regs->GR_G(r1) < (S32)i2 ? 1 : (S64)regs->GR_G(r1) > (S32)i2 ? 2 : 0; } /* end DEF_INST(compare_long_fullword_immediate) */ /*-------------------------------------------------------------------*/ /* C2xF CLFI - Compare Logical Fullword Immediate [RIL] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_logical_fullword_immediate) { int r1; /* Register number */ int opcd; /* Opcode */ U32 i2; /* 32-bit operand value */ RIL0(inst, regs, r1, opcd, i2); /* Compare unsigned operands and set condition code */ regs->psw.cc = regs->GR_L(r1) < i2 ? 1 : regs->GR_L(r1) > i2 ? 2 : 0; } /* end DEF_INST(compare_logical_fullword_immediate) */ /*-------------------------------------------------------------------*/ /* C2xE CLGFI - Compare Logical Long Fullword Immediate [RIL] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_logical_long_fullword_immediate) { int r1; /* Register number */ int opcd; /* Opcode */ U32 i2; /* 32-bit operand value */ RIL0(inst, regs, r1, opcd, i2); /* Compare unsigned operands and set condition code */ regs->psw.cc = regs->GR_G(r1) < i2 ? 1 : regs->GR_G(r1) > i2 ? 2 : 0; } /* end DEF_INST(compare_logical_long_fullword_immediate) */ /*-------------------------------------------------------------------*/ /* C0x6 XIHF - Exclusive Or Immediate High Fullword [RIL] */ /*-------------------------------------------------------------------*/ DEF_INST(exclusive_or_immediate_high_fullword) { int r1; /* Register number */ int opcd; /* Opcode */ U32 i2; /* 32-bit operand value */ RIL0(inst, regs, r1, opcd, i2); /* XOR fullword operand with high 32 bits of register */ regs->GR_H(r1) ^= i2; /* Set condition code according to result */ regs->psw.cc = regs->GR_H(r1) ? 1 : 0; } /* end DEF_INST(exclusive_or_immediate_high_fullword) */ /*-------------------------------------------------------------------*/ /* C0x7 XILF - Exclusive Or Immediate Low Fullword [RIL] */ /*-------------------------------------------------------------------*/ DEF_INST(exclusive_or_immediate_low_fullword) { int r1; /* Register number */ int opcd; /* Opcode */ U32 i2; /* 32-bit operand value */ RIL0(inst, regs, r1, opcd, i2); /* XOR fullword operand with low 32 bits of register */ regs->GR_L(r1) ^= i2; /* Set condition code according to result */ regs->psw.cc = regs->GR_L(r1) ? 1 : 0; } /* end DEF_INST(exclusive_or_immediate_low_fullword) */ /*-------------------------------------------------------------------*/ /* C0x8 IIHF - Insert Immediate High Fullword [RIL] */ /*-------------------------------------------------------------------*/ DEF_INST(insert_immediate_high_fullword) { int r1; /* Register number */ int opcd; /* Opcode */ U32 i2; /* 32-bit operand value */ RIL0(inst, regs, r1, opcd, i2); /* Insert fullword operand into high 32 bits of register */ regs->GR_H(r1) = i2; } /* end DEF_INST(insert_immediate_high_fullword) */ /*-------------------------------------------------------------------*/ /* C0x9 IILF - Insert Immediate Low Fullword [RIL] */ /*-------------------------------------------------------------------*/ DEF_INST(insert_immediate_low_fullword) { int r1; /* Register number */ int opcd; /* Opcode */ U32 i2; /* 32-bit operand value */ RIL0(inst, regs, r1, opcd, i2); /* Insert fullword operand into low 32 bits of register */ regs->GR_L(r1) = i2; } /* end DEF_INST(insert_immediate_low_fullword) */ /*-------------------------------------------------------------------*/ /* C0xE LLIHF - Load Logical Immediate High Fullword [RIL] */ /*-------------------------------------------------------------------*/ DEF_INST(load_logical_immediate_high_fullword) { int r1; /* Register number */ int opcd; /* Opcode */ U32 i2; /* 32-bit operand value */ RIL0(inst, regs, r1, opcd, i2); /* Load fullword operand into high 32 bits of register and set remaining bits to zero */ regs->GR_H(r1) = i2; regs->GR_L(r1) = 0; } /* end DEF_INST(load_logical_immediate_high_fullword) */ /*-------------------------------------------------------------------*/ /* C0xF LLILF - Load Logical Immediate Low Fullword [RIL] */ /*-------------------------------------------------------------------*/ DEF_INST(load_logical_immediate_low_fullword) { int r1; /* Register number */ int opcd; /* Opcode */ U32 i2; /* 32-bit operand value */ RIL0(inst, regs, r1, opcd, i2); /* Load fullword operand into low 32 bits of register and set remaining bits to zero */ regs->GR_G(r1) = i2; } /* end DEF_INST(load_logical_immediate_low_fullword) */ /*-------------------------------------------------------------------*/ /* C0x1 LGFI - Load Long Fullword Immediate [RIL] */ /*-------------------------------------------------------------------*/ DEF_INST(load_long_fullword_immediate) { int r1; /* Register number */ int opcd; /* Opcode */ U32 i2; /* 32-bit operand value */ RIL0(inst, regs, r1, opcd, i2); /* Load operand into register */ regs->GR_G(r1) = (S32)i2; } /* end DEF_INST(load_long_fullword_immediate) */ /*-------------------------------------------------------------------*/ /* C0xC OIHF - Or Immediate High Fullword [RIL] */ /*-------------------------------------------------------------------*/ DEF_INST(or_immediate_high_fullword) { int r1; /* Register number */ int opcd; /* Opcode */ U32 i2; /* 32-bit operand value */ RIL0(inst, regs, r1, opcd, i2); /* Or fullword operand with high 32 bits of register */ regs->GR_H(r1) |= i2; /* Set condition code according to result */ regs->psw.cc = regs->GR_H(r1) ? 1 : 0; } /* end DEF_INST(or_immediate_high_fullword) */ /*-------------------------------------------------------------------*/ /* C0xD OILF - Or Immediate Low Fullword [RIL] */ /*-------------------------------------------------------------------*/ DEF_INST(or_immediate_low_fullword) { int r1; /* Register number */ int opcd; /* Opcode */ U32 i2; /* 32-bit operand value */ RIL0(inst, regs, r1, opcd, i2); /* Or fullword operand with low 32 bits of register */ regs->GR_L(r1) |= i2; /* Set condition code according to result */ regs->psw.cc = regs->GR_L(r1) ? 1 : 0; } /* end DEF_INST(or_immediate_low_fullword) */ /*-------------------------------------------------------------------*/ /* C2x5 SLFI - Subtract Logical Fullword Immediate [RIL] */ /*-------------------------------------------------------------------*/ DEF_INST(subtract_logical_fullword_immediate) { int r1; /* Register number */ int opcd; /* Opcode */ U32 i2; /* 32-bit operand value */ RIL0(inst, regs, r1, opcd, i2); /* Subtract unsigned operands and set condition code */ regs->psw.cc = sub_logical (&(regs->GR_L(r1)), regs->GR_L(r1), i2); } /* end DEF_INST(subtract_logical_fullword_immediate) */ /*-------------------------------------------------------------------*/ /* C2x4 SLGFI - Subtract Logical Long Fullword Immediate [RIL] */ /*-------------------------------------------------------------------*/ DEF_INST(subtract_logical_long_fullword_immediate) { int r1; /* Register number */ int opcd; /* Opcode */ U32 i2; /* 32-bit operand value */ RIL0(inst, regs, r1, opcd, i2); /* Subtract unsigned operands and set condition code */ regs->psw.cc = sub_logical_long(&(regs->GR_G(r1)), regs->GR_G(r1), i2); } /* end DEF_INST(subtract_logical_long_fullword_immediate) */ #endif /*defined(FEATURE_EXTENDED_IMMEDIATE)*/ /*@Z9*/ #if defined(FEATURE_EXTENDED_IMMEDIATE) /*@Z9*/ /*-------------------------------------------------------------------*/ /* E312 LT - Load and Test [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(load_and_test) { int r1; /* Value of R field */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ RXY(inst, regs, r1, b2, effective_addr2); /* Load R1 register from second operand */ regs->GR_L(r1) = ARCH_DEP(vfetch4) ( effective_addr2, b2, regs ); /* Set condition code according to value loaded */ regs->psw.cc = (S32)regs->GR_L(r1) < 0 ? 1 : (S32)regs->GR_L(r1) > 0 ? 2 : 0; } /* end DEF_INST(load_and_test) */ /*-------------------------------------------------------------------*/ /* E302 LTG - Load and Test Long [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(load_and_test_long) { int r1; /* Value of R field */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ RXY(inst, regs, r1, b2, effective_addr2); /* Load R1 register from second operand */ regs->GR_G(r1) = ARCH_DEP(vfetch8) ( effective_addr2, b2, regs ); /* Set condition code according to value loaded */ regs->psw.cc = (S64)regs->GR_G(r1) < 0 ? 1 : (S64)regs->GR_G(r1) > 0 ? 2 : 0; } /* end DEF_INST(load_and_test_long) */ /*-------------------------------------------------------------------*/ /* B926 LBR - Load Byte Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(load_byte_register) { int r1, r2; /* Values of R fields */ RRE0(inst, regs, r1, r2); /* Load sign-extended byte from second register */ regs->GR_L(r1) = (S32)(S8)(regs->GR_LHLCL(r2)); } /* end DEF_INST(load_byte_register) */ /*-------------------------------------------------------------------*/ /* B906 LGBR - Load Long Byte Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(load_long_byte_register) { int r1, r2; /* Values of R fields */ RRE0(inst, regs, r1, r2); /* Load sign-extended byte from second register */ regs->GR_G(r1) = (S64)(S8)(regs->GR_LHLCL(r2)); } /* end DEF_INST(load_long_byte_register) */ /*-------------------------------------------------------------------*/ /* B927 LHR - Load Halfword Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(load_halfword_register) { int r1, r2; /* Values of R fields */ RRE0(inst, regs, r1, r2); /* Load sign-extended halfword from second register */ regs->GR_L(r1) = (S32)(S16)(regs->GR_LHL(r2)); } /* end DEF_INST(load_halfword_register) */ /*-------------------------------------------------------------------*/ /* B907 LGHR - Load Long Halfword Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(load_long_halfword_register) { int r1, r2; /* Values of R fields */ RRE0(inst, regs, r1, r2); /* Load sign-extended halfword from second register */ regs->GR_G(r1) = (S64)(S16)(regs->GR_LHL(r2)); } /* end DEF_INST(load_long_halfword_register) */ /*-------------------------------------------------------------------*/ /* E394 LLC - Load Logical Character [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(load_logical_character) { int r1; /* Value of R field */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ RXY(inst, regs, r1, b2, effective_addr2); regs->GR_L(r1) = ARCH_DEP(vfetchb) ( effective_addr2, b2, regs ); } /* end DEF_INST(load_logical_character) */ /*-------------------------------------------------------------------*/ /* B994 LLCR - Load Logical Character Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(load_logical_character_register) { int r1, r2; /* Values of R fields */ RRE0(inst, regs, r1, r2); /* Load bits 56-63 from second register and clear bits 32-55 */ regs->GR_L(r1) = regs->GR_LHLCL(r2); } /* end DEF_INST(load_logical_character_register) */ /*-------------------------------------------------------------------*/ /* B984 LLGCR - Load Logical Long Character Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(load_logical_long_character_register) { int r1, r2; /* Values of R fields */ RRE0(inst, regs, r1, r2); /* Load bits 56-63 from second register and clear bits 0-55 */ regs->GR_G(r1) = regs->GR_LHLCL(r2); } /* end DEF_INST(load_logical_long_character_register) */ /*-------------------------------------------------------------------*/ /* E395 LLH - Load Logical Halfword [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(load_logical_halfword) { int r1; /* Value of R field */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ RXY(inst, regs, r1, b2, effective_addr2); regs->GR_L(r1) = ARCH_DEP(vfetch2) ( effective_addr2, b2, regs ); } /* end DEF_INST(load_logical_halfword) */ /*-------------------------------------------------------------------*/ /* B995 LLHR - Load Logical Halfword Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(load_logical_halfword_register) { int r1, r2; /* Values of R fields */ RRE0(inst, regs, r1, r2); /* Load bits 48-63 from second register and clear bits 32-47 */ regs->GR_L(r1) = regs->GR_LHL(r2); } /* end DEF_INST(load_logical_halfword_register) */ /*-------------------------------------------------------------------*/ /* B985 LLGHR - Load Logical Long Halfword Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(load_logical_long_halfword_register) { int r1, r2; /* Values of R fields */ RRE0(inst, regs, r1, r2); /* Load bits 48-63 from second register and clear bits 0-47 */ regs->GR_G(r1) = regs->GR_LHL(r2); } /* end DEF_INST(load_logical_long_halfword_register) */ /*-------------------------------------------------------------------*/ /* B983 FLOGR - Find Leftmost One Long Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(find_leftmost_one_long_register) { int r1, r2; /* Values of R fields */ U64 op; /* R2 contents */ U64 mask; /* Bit mask for leftmost one */ int n; /* Position of leftmost one */ RRE(inst, regs, r1, r2); ODD_CHECK(r1, regs); /* Load contents of second register */ op = regs->GR_G(r2); /* If R2 contents is all zero, set R1 register to 64, set R1+1 register to zero, and return cond code 0 */ if (op == 0) { regs->GR_G(r1) = 64; regs->GR_G(r1+1) = 0; regs->psw.cc = 0; } else { /* Find leftmost one */ for (mask = 0x8000000000000000ULL, n=0; n < 64 && (op & mask) == 0; n++, mask >>= 1); /* Load leftmost one position into R1 register */ regs->GR_G(r1) = n; /* Copy original R2 to R1+1 and clear leftmost one */ regs->GR_G(r1+1) = op & (~mask); /* Return with condition code 2 */ regs->psw.cc = 2; } } /* end DEF_INST(find_leftmost_one_long_register) */ #endif /*defined(FEATURE_EXTENDED_IMMEDIATE)*/ /*@Z9*/ #if !defined(_GEN_ARCH) #if defined(_ARCHMODE2) #define _GEN_ARCH _ARCHMODE2 #include "esame.c" #endif #if defined(_ARCHMODE3) #undef _GEN_ARCH #define _GEN_ARCH _ARCHMODE3 #include "esame.c" #endif /*-------------------------------------------------------------------*/ /* Locate STFL data independent of current architecture mode setting */ /*-------------------------------------------------------------------*/ /* Note: this function must be here so that all ARCH_DEP(stlf_data) */ /* with correct architecture settings have been defined with */ /* architecture sensitive features */ BYTE* get_stfl_data(int mode, int *data_len) { switch(mode) { #if defined(_390) case ARCH_390: *data_len=sizeof(s390_stfl_data); return &s390_stfl_data[0]; #endif #if defined(_900) case ARCH_900: *data_len=sizeof(z900_stfl_data); return &z900_stfl_data[0]; #endif } *data_len=0; return NULL; } #endif /*!defined(_GEN_ARCH)*/ hercules-3.07/external.c000644 000765 000765 00000051565 11301535254 016744 0ustar00jmaynardjmaynard000000 000000 /* EXTERNAL.C (c) Copyright Roger Bowler, 1999-2009 */ /* ESA/390 External Interrupt and Timer */ // $Id: external.c 5469 2009-10-03 19:11:05Z hsg001 $ /* Interpretive Execution - (c) Copyright Jan Jaeger, 1999-2009 */ /* z/Architecture support - (c) Copyright Jan Jaeger, 1999-2009 */ /*-------------------------------------------------------------------*/ /* This module implements external interrupt, timer, and signalling */ /* functions for the Hercules ESA/390 emulator. */ /*-------------------------------------------------------------------*/ /*-------------------------------------------------------------------*/ /* Additional credits: */ /* TOD clock offset contributed by Jay Maynard */ /* Correction to timer interrupt by Valery Pogonchenko */ /* TOD clock drag factor contributed by Jan Jaeger */ /* CPU timer and clock comparator interrupt improvements by */ /* Jan Jaeger, after a suggestion by Willem Koynenberg */ /* Prevent TOD clock and CPU timer from going back - Jan Jaeger */ /* Use longjmp on all interrupt types - Jan Jaeger */ /* Fix todclock - Jay Maynard */ /* Modifications for Interpretive Execution (SIE) by Jan Jaeger */ /*-------------------------------------------------------------------*/ // $Log$ // Revision 1.72 2008/12/28 22:00:57 rbowler // Issue message if service signal interrupt occurs while stepping or tracing // // Revision 1.71 2007/06/23 00:04:09 ivan // Update copyright notices to include current year (2007) // // Revision 1.70 2007/02/26 00:54:22 gsmith // Display timer interrupts only if tracing/stepping all // // Revision 1.69 2007/01/16 01:45:33 gsmith // Tweaks to instruction stepping/tracing // // Revision 1.68 2006/12/08 09:43:20 jj // Add CVS message log // #include "hstdinc.h" #if !defined(_HENGINE_DLL_) #define _HENGINE_DLL_ #endif #if !defined(_EXTERNAL_C_) #define _EXTERNAL_C_ #endif #include "hercules.h" #include "opcode.h" #include "inline.h" /*-------------------------------------------------------------------*/ /* Load external interrupt new PSW */ /*-------------------------------------------------------------------*/ static void ARCH_DEP(external_interrupt) (int code, REGS *regs) { RADR pfx; PSA *psa; int rc; PTT(PTT_CL_SIG,"*EXTINT",code,regs->cpuad,regs->psw.IA_L); #if defined(_FEATURE_SIE) /* Set the main storage reference and change bits */ if(SIE_MODE(regs) #if defined(_FEATURE_EXPEDITED_SIE_SUBSET) && !SIE_FEATB(regs, S, EXP_TIMER) #endif /*defined(_FEATURE_EXPEDITED_SIE_SUBSET)*/ #if defined(_FEATURE_EXTERNAL_INTERRUPT_ASSIST) && !SIE_FEATB(regs, EC0, EXTA) #endif ) { /* Point to SIE copy of PSA in state descriptor */ psa = (void*)(regs->hostregs->mainstor + SIE_STATE(regs) + SIE_IP_PSA_OFFSET); STORAGE_KEY(SIE_STATE(regs), regs->hostregs) |= (STORKEY_REF | STORKEY_CHANGE); } else #endif /*defined(_FEATURE_SIE)*/ { /* Point to PSA in main storage */ pfx = regs->PX; #if defined(_FEATURE_EXPEDITED_SIE_SUBSET) SIE_TRANSLATE(&pfx, ACCTYPE_SIE, regs); #endif /*defined(_FEATURE_EXPEDITED_SIE_SUBSET)*/ psa = (void*)(regs->mainstor + pfx); STORAGE_KEY(pfx, regs) |= (STORKEY_REF | STORKEY_CHANGE); } /* Store the interrupt code in the PSW */ regs->psw.intcode = code; /* Zero extcpuad field unless extcall or ems signal or blockio */ if(code != EXT_EXTERNAL_CALL_INTERRUPT #if defined(FEATURE_VM_BLOCKIO) && code != EXT_BLOCKIO_INTERRUPT #endif /* defined(FEATURE_VM_BLOCKIO) */ && code != EXT_EMERGENCY_SIGNAL_INTERRUPT) STORE_HW(psa->extcpad,0); #if defined(FEATURE_BCMODE) /* For ECMODE, store external interrupt code at PSA+X'86' */ if ( ECMODE(®s->psw) ) #endif /*defined(FEATURE_BCMODE)*/ STORE_HW(psa->extint,code); if ( !SIE_MODE(regs) #if defined(_FEATURE_EXPEDITED_SIE_SUBSET) || SIE_FEATB(regs, S, EXP_TIMER) #endif /*defined(_FEATURE_EXPEDITED_SIE_SUBSET)*/ #if defined(_FEATURE_EXTERNAL_INTERRUPT_ASSIST) || SIE_FEATB(regs, EC0, EXTA) #endif ) { /* Store current PSW at PSA+X'18' */ ARCH_DEP(store_psw) (regs, psa->extold); /* Load new PSW from PSA+X'58' */ rc = ARCH_DEP(load_psw) (regs, psa->extnew); if ( rc ) { RELEASE_INTLOCK(regs); ARCH_DEP(program_interrupt)(regs, rc); } } #if defined(FEATURE_INTERVAL_TIMER) /* Ensure the interval timer is uptodate */ ARCH_DEP(store_int_timer_nolock) (regs); #endif RELEASE_INTLOCK(regs); if ( SIE_MODE(regs) #if defined(_FEATURE_EXPEDITED_SIE_SUBSET) && !SIE_FEATB(regs, S, EXP_TIMER) #endif /*defined(_FEATURE_EXPEDITED_SIE_SUBSET)*/ #if defined(_FEATURE_EXTERNAL_INTERRUPT_ASSIST) && !SIE_FEATB(regs, EC0, EXTA) #endif ) longjmp (regs->progjmp, SIE_INTERCEPT_EXT); else longjmp (regs->progjmp, SIE_NO_INTERCEPT); } /* end function external_interrupt */ /*-------------------------------------------------------------------*/ /* Perform external interrupt if pending */ /* */ /* This function is called by the CPU to check whether any */ /* external interrupt conditions are pending, and to perform */ /* an external interrupt if so. If multiple external interrupts */ /* are pending, then only the highest priority interrupt is taken, */ /* and any other interrupts remain pending. Remaining interrupts */ /* will be processed one-by-one during subsequent calls. */ /* */ /* Important notes: */ /* (i) This function must NOT be called if the CPU is disabled */ /* for external interrupts (PSW bit 7 is zero). */ /* (ii) The caller MUST hold the interrupt lock (sysblk.intlock) */ /* to ensure correct serialization of interrupt pending bits. */ /*-------------------------------------------------------------------*/ void ARCH_DEP(perform_external_interrupt) (REGS *regs) { PSA *psa; /* -> Prefixed storage area */ U16 cpuad; /* Originating CPU address */ #if defined(FEATURE_VM_BLOCKIO) #if defined(FEATURE_ESAME) RADR servpadr; /* Address of 64-bit block I/O interrupt */ #endif U16 servcode; /* Service Signal or Block I/O Interrupt code */ #endif /* defined(FEATURE_VM_BLOCKIO) */ /* External interrupt if console interrupt key was depressed */ if ( OPEN_IC_INTKEY(regs) && !SIE_MODE(regs) ) { logmsg (_("HHCCP023I External interrupt: Interrupt key\n")); /* Reset interrupt key pending */ OFF_IC_INTKEY; /* Generate interrupt key interrupt */ ARCH_DEP(external_interrupt) (EXT_INTERRUPT_KEY_INTERRUPT, regs); } /* External interrupt if malfunction alert is pending */ if (OPEN_IC_MALFALT(regs)) { /* Find first CPU which generated a malfunction alert */ for (cpuad = 0; regs->malfcpu[cpuad] == 0; cpuad++) { if (cpuad >= MAX_CPU) { OFF_IC_MALFALT(regs); return; } } /* end for(cpuad) */ // /*debug*/ logmsg (_("External interrupt: Malfuction Alert from CPU %d\n"), // /*debug*/ cpuad); /* Reset the indicator for the CPU which was found */ regs->malfcpu[cpuad] = 0; /* Store originating CPU address at PSA+X'84' */ psa = (void*)(regs->mainstor + regs->PX); STORE_HW(psa->extcpad,cpuad); /* Reset emergency signal pending flag if there are no other CPUs which generated emergency signal */ OFF_IC_MALFALT(regs); while (++cpuad < MAX_CPU) { if (regs->malfcpu[cpuad]) { ON_IC_MALFALT(regs); break; } } /* end while */ /* Generate emergency signal interrupt */ ARCH_DEP(external_interrupt) (EXT_MALFUNCTION_ALERT_INTERRUPT, regs); } /* External interrupt if emergency signal is pending */ if (OPEN_IC_EMERSIG(regs)) { /* Find first CPU which generated an emergency signal */ for (cpuad = 0; regs->emercpu[cpuad] == 0; cpuad++) { if (cpuad >= MAX_CPU) { OFF_IC_EMERSIG(regs); return; } } /* end for(cpuad) */ // /*debug*/ logmsg (_("External interrupt: Emergency Signal from CPU %d\n"), // /*debug*/ cpuad); /* Reset the indicator for the CPU which was found */ regs->emercpu[cpuad] = 0; /* Store originating CPU address at PSA+X'84' */ psa = (void*)(regs->mainstor + regs->PX); STORE_HW(psa->extcpad,cpuad); /* Reset emergency signal pending flag if there are no other CPUs which generated emergency signal */ OFF_IC_EMERSIG(regs); while (++cpuad < MAX_CPU) { if (regs->emercpu[cpuad]) { ON_IC_EMERSIG(regs); break; } } /* end while */ /* Generate emergency signal interrupt */ ARCH_DEP(external_interrupt) (EXT_EMERGENCY_SIGNAL_INTERRUPT, regs); } /* External interrupt if external call is pending */ if (OPEN_IC_EXTCALL(regs)) { // /*debug*/logmsg (_("External interrupt: External Call from CPU %d\n"), // /*debug*/ regs->extccpu); /* Reset external call pending */ OFF_IC_EXTCALL(regs); /* Store originating CPU address at PSA+X'84' */ psa = (void*)(regs->mainstor + regs->PX); STORE_HW(psa->extcpad,regs->extccpu); /* Generate external call interrupt */ ARCH_DEP(external_interrupt) (EXT_EXTERNAL_CALL_INTERRUPT, regs); } /* External interrupt if TOD clock exceeds clock comparator */ if ( tod_clock(regs) > regs->clkc && OPEN_IC_CLKC(regs) ) { if (CPU_STEPPING_OR_TRACING_ALL) { logmsg (_("HHCCP024I External interrupt: Clock comparator\n")); } ARCH_DEP(external_interrupt) (EXT_CLOCK_COMPARATOR_INTERRUPT, regs); } /* External interrupt if CPU timer is negative */ if ( CPU_TIMER(regs) < 0 && OPEN_IC_PTIMER(regs) ) { if (CPU_STEPPING_OR_TRACING_ALL) { logmsg (_("HHCCP025I External interrupt: CPU timer=%16.16" I64_FMT "X\n"), (long long)CPU_TIMER(regs) << 8); } ARCH_DEP(external_interrupt) (EXT_CPU_TIMER_INTERRUPT, regs); } /* External interrupt if interval timer interrupt is pending */ #if defined(FEATURE_INTERVAL_TIMER) if (OPEN_IC_ITIMER(regs) #if defined(_FEATURE_SIE) && !(SIE_STATB(regs, M, ITMOF)) #endif /*defined(_FEATURE_SIE)*/ ) { if (CPU_STEPPING_OR_TRACING_ALL) { logmsg (_("HHCCP026I External interrupt: Interval timer\n")); } OFF_IC_ITIMER(regs); ARCH_DEP(external_interrupt) (EXT_INTERVAL_TIMER_INTERRUPT, regs); } #if defined(FEATURE_ECPSVM) if ( OPEN_IC_ECPSVTIMER(regs) ) { OFF_IC_ECPSVTIMER(regs); ARCH_DEP(external_interrupt) (EXT_VINTERVAL_TIMER_INTERRUPT,regs); } #endif /*FEATURE_ECPSVM*/ #endif /*FEATURE_INTERVAL_TIMER*/ /* External interrupt if service signal is pending */ if ( OPEN_IC_SERVSIG(regs) && !SIE_MODE(regs) ) { #if defined(FEATURE_VM_BLOCKIO) /* Note: Both Block I/O and Service Signal are enabled by the */ /* the same CR0 bit. Hence they are handled in the same code */ switch(sysblk.servcode) { case EXT_BLOCKIO_INTERRUPT: /* VM Block I/O Interrupt */ if (sysblk.biodev->ccwtrace) { logmsg (_("%4.4X:HHCCP031I Processing Block I/O interrupt: " "code=%4.4X parm=%16.16X status=%2.2X subcode=%2.2X\n"), sysblk.biodev->devnum, sysblk.servcode, sysblk.bioparm, sysblk.biostat, sysblk.biosubcd ); } servcode = EXT_BLOCKIO_INTERRUPT; #if defined(FEATURE_ESAME) /* Real address used to store the 64-bit interrupt parameter */ #define VM_BLOCKIO_INT_PARM 0x11B8 if (sysblk.biosubcd == 0x07) { /* 8-byte interrupt parm */ if (CPU_STEPPING_OR_TRACING_ALL) { logmsg (_("HHCCP028I External interrupt: Block I/O %16.16X\n"), sysblk.bioparm); } /* Set the main storage reference and change bits */ /* for 64-bit interruption parameter. */ /* Note: This is handled for the first 4K page in */ /* ARCH_DEP(external_interrupt), but not for the */ /* the second 4K page used for the 64-bit interrupt */ /* parameter. */ /* Point to 2nd page of PSA in main storage */ servpadr=APPLY_PREFIXING(VM_BLOCKIO_INT_PARM,regs->PX); STORAGE_KEY(servpadr, regs) |= (STORKEY_REF | STORKEY_CHANGE); #if 0 /* Store the 64-bit interrupt parameter */ logmsg (_("Saving 64-bit Block I/O interrupt parm at " "%16.16X: %16.16X\n"), servpadr, sysblk.bioparm ); #endif STORE_DW(regs->mainstor + servpadr,sysblk.bioparm); psa = (void*)(regs->mainstor + regs->PX); } else { #endif /* defined(FEATURE_ESAME) */ /* 4-byte interrupt parm */ if (CPU_STEPPING_OR_TRACING_ALL) { logmsg (_("HHCCP028I External interrupt: Block I/O %8.8X\n"), (U32)sysblk.bioparm); } /* Store Block I/O parameter at PSA+X'80' */ psa = (void*)(regs->mainstor + regs->PX); STORE_FW(psa->extparm,(U32)sysblk.bioparm); #if defined(FEATURE_ESAME) } #endif /* Store sub-interruption code and status at PSA+X'84' */ STORE_HW(psa->extcpad,(sysblk.biosubcd<<8)|sysblk.biostat); /* Reset interruption data */ sysblk.bioparm = 0; sysblk.biosubcd = 0; sysblk.biostat = 0; break; case EXT_SERVICE_SIGNAL_INTERRUPT: /* Service Signal */ default: servcode = EXT_SERVICE_SIGNAL_INTERRUPT; /* Apply prefixing if the parameter is a storage address */ if ( (sysblk.servparm & SERVSIG_ADDR) ) sysblk.servparm = APPLY_PREFIXING (sysblk.servparm, regs->PX); if (CPU_STEPPING_OR_TRACING_ALL) { logmsg (_("HHCCP027I External interrupt: Service signal %8.8X\n"), sysblk.servparm); } /* Store service signal parameter at PSA+X'80' */ psa = (void*)(regs->mainstor + regs->PX); STORE_FW(psa->extparm,sysblk.servparm); } /* end switch(sysblk.servcode) */ /* Reset service parameter */ sysblk.servparm = 0; /* Reset service code */ sysblk.servcode = 0; /* Reset service signal pending */ OFF_IC_SERVSIG; /* Generate service signal interrupt */ ARCH_DEP(external_interrupt) (servcode, regs); #else /* defined(FEATURE_VM_BLOCKIO) */ /* Apply prefixing if the parameter is a storage address */ if ( (sysblk.servparm & SERVSIG_ADDR) ) sysblk.servparm = APPLY_PREFIXING (sysblk.servparm, regs->PX); if (CPU_STEPPING_OR_TRACING_ALL) { logmsg (_("HHCCP027I External interrupt: Service signal %8.8X\n"), sysblk.servparm); } /* Store service signal parameter at PSA+X'80' */ psa = (void*)(regs->mainstor + regs->PX); STORE_FW(psa->extparm,sysblk.servparm); /* Reset service parameter */ sysblk.servparm = 0; /* Reset service signal pending */ OFF_IC_SERVSIG; /* Generate service signal interrupt */ ARCH_DEP(external_interrupt) (EXT_SERVICE_SIGNAL_INTERRUPT, regs); #endif /* defined(FEATURE_VM_BLOCKIO) */ } /* end OPEN_IC_SERVSIG(regs) */ } /* end function perform_external_interrupt */ /*-------------------------------------------------------------------*/ /* Store Status */ /* Input: */ /* sregs Register context of CPU whose status is to be stored */ /* aaddr A valid absolute address of a 512-byte block into */ /* which status is to be stored */ /* For an implicit store status, or an operator */ /* initiated store status the absolute address will be */ /* zero, for a store status at address order the */ /* supplied address will be nonzero */ /*-------------------------------------------------------------------*/ void ARCH_DEP(store_status) (REGS *ssreg, RADR aaddr) { int i; /* Array subscript */ PSA *sspsa; /* -> Store status area */ /* Set reference and change bits */ STORAGE_KEY(aaddr, ssreg) |= (STORKEY_REF | STORKEY_CHANGE); #if defined(FEATURE_ESAME) /* The ESAME PSA is two pages in size */ if(!aaddr) STORAGE_KEY(aaddr + 4096, ssreg) |= (STORKEY_REF | STORKEY_CHANGE); #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /* For store status at address, we must adjust the PSA offset */ /* ZZ THIS TEST IS NOT CONCLUSIVE */ if(aaddr != 0 && aaddr != ssreg->PX) aaddr -= 512 + 4096 ; #endif aaddr &= 0x7FFFFE00; /* Point to the PSA into which status is to be stored */ sspsa = (void*)(ssreg->mainstor + aaddr); /* Store CPU timer in bytes 216-223 */ STORE_DW(sspsa->storeptmr, cpu_timer(ssreg)); /* Store clock comparator in bytes 224-231 */ #if defined(FEATURE_ESAME) STORE_DW(sspsa->storeclkc, ssreg->clkc); #else /*defined(FEATURE_ESAME)*/ STORE_DW(sspsa->storeclkc, ssreg->clkc << 8); #endif /*defined(FEATURE_ESAME)*/ /* Store PSW in bytes 256-263 */ ARCH_DEP(store_psw) (ssreg, sspsa->storepsw); /* Store prefix register in bytes 264-267 */ STORE_FW(sspsa->storepfx,ssreg->PX); #if defined(FEATURE_ESAME) /* Store Floating Point Control Register */ STORE_FW(sspsa->storefpc,ssreg->fpc); /* Store TOD Programable register */ STORE_FW(sspsa->storetpr,ssreg->todpr); #endif /*defined(FEATURE_ESAME)*/ #if defined(_900) /* Only store the arch mode indicator for a PSA type store status */ if(!aaddr) #if defined(FEATURE_ESAME) sspsa->arch = 1; #else /*defined(FEATURE_ESAME)*/ sspsa->arch = 0; #endif /*defined(FEATURE_ESAME)*/ #endif /*defined(_900)*/ /* Store access registers in bytes 288-351 */ for (i = 0; i < 16; i++) STORE_FW(sspsa->storear[i],ssreg->AR(i)); /* Store floating-point registers in bytes 352-383 */ #if defined(FEATURE_ESAME) for (i = 0; i < 32; i++) #else /*!defined(FEATURE_ESAME)*/ for (i = 0; i < 8; i++) #endif /*!defined(FEATURE_ESAME)*/ STORE_FW(sspsa->storefpr[i],ssreg->fpr[i]); /* Store general-purpose registers in bytes 384-447 */ for (i = 0; i < 16; i++) STORE_W(sspsa->storegpr[i],ssreg->GR(i)); /* Store control registers in bytes 448-511 */ for (i = 0; i < 16; i++) STORE_W(sspsa->storecr[i],ssreg->CR(i)); } /* end function store_status */ #if !defined(_GEN_ARCH) #if defined(_ARCHMODE2) #define _GEN_ARCH _ARCHMODE2 #include "external.c" #endif #if defined(_ARCHMODE3) #undef _GEN_ARCH #define _GEN_ARCH _ARCHMODE3 #include "external.c" #endif void store_status (REGS *ssreg, U64 aaddr) { switch(ssreg->arch_mode) { #if defined(_370) case ARCH_370: aaddr &= 0x7FFFFFFF; s370_store_status (ssreg, aaddr); break; #endif #if defined(_390) case ARCH_390: aaddr &= 0x7FFFFFFF; s390_store_status (ssreg, aaddr); break; #endif #if defined(_900) case ARCH_900: z900_store_status (ssreg, aaddr); break; #endif } } #endif /*!defined(_GEN_ARCH)*/ hercules-3.07/faketape.c000644 000765 000765 00000073337 11321734033 016701 0ustar00jmaynardjmaynard000000 000000 /* FAKETAPE.C (c) Copyright Roger Bowler, 1999-2009 */ /* Hercules Tape Device Handler for FAKETAPE */ /* Original Author: "Fish" (David B. Trout) */ /* Prime Maintainer: "Fish" (David B. Trout) */ /* Secondary Maintainer: Ivan Warren */ // $Id: faketape.c 5587 2009-12-31 15:05:57Z rbowler $ /*-------------------------------------------------------------------*/ /* This module contains the FAKETAPE emulated tape format support. */ /* */ /* The subroutines in this module are called by the general tape */ /* device handler (tapedev.c) when the tape format is FAKETAPE. */ /* */ /* Messages issued by this module are prefixed HHCTA5nn */ /*-------------------------------------------------------------------*/ /*-------------------------------------------------------------------*/ /* Reference information: */ /* FSIMS100 Faketape manual */ /*-------------------------------------------------------------------*/ #include "hstdinc.h" #include "hercules.h" /* need Hercules control blocks */ #include "tapedev.h" /* Main tape handler header file */ //#define ENABLE_TRACING_STMTS // (Fish: DEBUGGING) #ifdef ENABLE_TRACING_STMTS #if !defined(DEBUG) #warning DEBUG required for ENABLE_TRACING_STMTS #endif // (TRACE, ASSERT, and VERIFY macros are #defined in hmacros.h) #else #undef TRACE #undef ASSERT #undef VERIFY #define TRACE 1 ? ((void)0) : logmsg #define ASSERT(a) #define VERIFY(a) ((void)(a)) #endif /*********************************************************************/ /* START OF ORIGINAL AWS FUNCTIONS (ISW Additions) */ /*********************************************************************/ /*-------------------------------------------------------------------*/ /* Close a FAKETAPE format file */ /* New Function added by ISW for consistency with other medias */ /*-------------------------------------------------------------------*/ void close_faketape (DEVBLK *dev) { if(dev->fd>=0) { logmsg (_("HHCTA501I %4.4X: FakeTape %s closed\n"), dev->devnum, dev->filename); close(dev->fd); } strcpy(dev->filename, TAPE_UNLOADED); dev->fd=-1; dev->blockid = 0; dev->fenced = 0; return; } /*-------------------------------------------------------------------*/ /* Rewinds a FAKETAPE format file */ /* New Function added by ISW for consistency with other medias */ /*-------------------------------------------------------------------*/ int rewind_faketape (DEVBLK *dev,BYTE *unitstat,BYTE code) { off_t rcoff; rcoff=lseek(dev->fd,0,SEEK_SET); if(rcoff<0) { build_senseX(TAPE_BSENSE_REWINDFAILED,dev,unitstat,code); return -1; } dev->nxtblkpos=0; dev->prvblkpos=-1; dev->curfilen=1; dev->blockid=0; dev->fenced = 0; return 0; } /*-------------------------------------------------------------------*/ /* Determines if a FAKETAPE has passed a virtual EOT marker */ /* New Function added by ISW for consistency with other medias */ /*-------------------------------------------------------------------*/ int passedeot_faketape (DEVBLK *dev) { if(dev->nxtblkpos==0) { dev->eotwarning = 0; return 0; } if(dev->tdparms.maxsize==0) { dev->eotwarning = 0; return 0; } if(dev->nxtblkpos+dev->eotmargin > dev->tdparms.maxsize) { dev->eotwarning = 1; return 1; } dev->eotwarning = 0; return 0; } /*********************************************************************/ /* START OF ORIGINAL RB AWS FUNCTIONS */ /*********************************************************************/ /*-------------------------------------------------------------------*/ /* Open a FAKETAPE format file */ /* */ /* If successful, the file descriptor is stored in the device block */ /* and the return value is zero. Otherwise the return value is -1. */ /*-------------------------------------------------------------------*/ int open_faketape (DEVBLK *dev, BYTE *unitstat,BYTE code) { int rc = -1; /* Return code */ char pathname[MAX_PATH]; /* file path in host format */ /* Check for no tape in drive */ if (!strcmp (dev->filename, TAPE_UNLOADED)) { build_senseX(TAPE_BSENSE_TAPEUNLOADED,dev,unitstat,code); return -1; } /* Open the FAKETAPE file */ hostpath(pathname, dev->filename, sizeof(pathname)); if(!dev->tdparms.logical_readonly) { rc = open (pathname, O_RDWR | O_BINARY); } /* If file is read-only, attempt to open again */ if (dev->tdparms.logical_readonly || (rc < 0 && (EROFS == errno || EACCES == errno))) { dev->readonly = 1; rc = open (pathname, O_RDONLY | O_BINARY); } /* Check for successful open */ if (rc < 0) { logmsg (_("HHCTA502E %4.4X: Error opening %s: %s\n"), dev->devnum, dev->filename, strerror(errno)); strcpy(dev->filename, TAPE_UNLOADED); build_senseX(TAPE_BSENSE_TAPELOADFAIL,dev,unitstat,code); return -1; } /* Store the file descriptor in the device block */ dev->fd = rc; rc=rewind_faketape(dev,unitstat,code); return rc; } /* end function open_faketape */ /*-------------------------------------------------------------------*/ /* Read a FAKETAPE block header */ /* */ /* If successful, return value is zero, and prvblkl and curblkl are */ /* set to the previous and current block lengths respectively. */ /* If error, return value is -1 and unitstat is set to CE+DE+UC */ /* and prvblkl and curblkl are undefined. Either or both of prvblkl */ /* and/or curblkl may be NULL. */ /*-------------------------------------------------------------------*/ int readhdr_faketape (DEVBLK *dev, off_t blkpos, U16* pprvblkl, U16* pcurblkl, BYTE *unitstat,BYTE code) { int rc; /* Return code */ off_t rcoff; /* Return code from lseek() */ FAKETAPE_BLKHDR fakehdr; /* FakeTape block header */ char sblklen[5]; /* work for converting hdr */ int prvblkl; /* Previous block length */ int curblkl; /* Current block length */ int xorblkl; /* XOR check of block lens */ /* Reposition file to the requested block header */ rcoff = lseek (dev->fd, blkpos, SEEK_SET); if (rcoff < 0) { /* Handle seek error condition */ logmsg (_("HHCTA503E %4.4X: Error seeking to offset "I64_FMTX" " "in file %s: %s\n"), dev->devnum, blkpos, dev->filename, strerror(errno)); /* Set unit check with equipment check */ build_senseX(TAPE_BSENSE_LOCATEERR,dev,unitstat,code); return -1; } /* Read the 12-ASCII-hex-character block header */ rc = read (dev->fd, &fakehdr, sizeof(FAKETAPE_BLKHDR)); /* Handle read error condition */ if (rc < 0) { logmsg (_("HHCTA504E %4.4X: Error reading block header " "at offset "I64_FMTX" in file %s: %s\n"), dev->devnum, blkpos, dev->filename, strerror(errno)); /* Set unit check with equipment check */ build_senseX(TAPE_BSENSE_READFAIL,dev,unitstat,code); return -1; } /* Handle end of file (uninitialized tape) condition */ if (rc == 0) { logmsg (_("HHCTA505E %4.4X: End of file (end of tape) " "at offset "I64_FMTX" in file %s\n"), dev->devnum, blkpos, dev->filename); /* Set unit exception with tape indicate (end of tape) */ build_senseX(TAPE_BSENSE_EMPTYTAPE,dev,unitstat,code); return -1; } /* Handle end of file within block header */ if (rc < (int)sizeof(FAKETAPE_BLKHDR)) { logmsg (_("HHCTA506E %4.4X: Unexpected end of file in block header " "at offset "I64_FMTX" in file %s\n"), dev->devnum, blkpos, dev->filename); build_senseX(TAPE_BSENSE_BLOCKSHORT,dev,unitstat,code); return -1; } /* Convert the ASCII-hex-character block lengths to binary */ strncpy( sblklen, fakehdr.sprvblkl, 4 ); sblklen[4] = 0; sscanf( sblklen, "%x", &prvblkl ); strncpy( sblklen, fakehdr.scurblkl, 4 ); sblklen[4] = 0; sscanf( sblklen, "%x", &curblkl ); strncpy( sblklen, fakehdr.sxorblkl, 4 ); sblklen[4] = 0; sscanf( sblklen, "%x", &xorblkl ); /* Verify header integrity using the XOR header field */ if ( (prvblkl ^ curblkl) != xorblkl ) { logmsg (_("HHCTA507E %4.4X: Block header damage " "at offset "I64_FMTX" in file %s\n"), dev->devnum, blkpos, dev->filename); /* Set unit check with equipment check */ build_senseX(TAPE_BSENSE_READFAIL,dev,unitstat,code); return -1; } /* Return the converted value(s) to the caller */ if (pprvblkl) *pprvblkl = prvblkl; if (pcurblkl) *pcurblkl = curblkl; /* Successful return */ return 0; } /* end function readhdr_faketape */ /*-------------------------------------------------------------------*/ /* Read a block from a FAKETAPE format file */ /* */ /* If successful, return value is block length read. */ /* If a tapemark was read, the return value is zero, and the */ /* current file number in the device block is incremented. */ /* If error, return value is -1 and unitstat is set to CE+DE+UC */ /*-------------------------------------------------------------------*/ int read_faketape (DEVBLK *dev, BYTE *buf, BYTE *unitstat,BYTE code) { int rc; /* Return code */ off_t blkpos; /* Offset of block header */ U16 curblkl; /* Current block length */ /* Initialize current block position */ blkpos = dev->nxtblkpos; /* Read the block header to obtain the current block length */ rc = readhdr_faketape (dev, blkpos, NULL, &curblkl, unitstat,code); if (rc < 0) return -1; /* (error message already issued) */ ASSERT( curblkl >= 0 ); /* Calculate the offset of the next block header */ blkpos += sizeof(FAKETAPE_BLKHDR) + curblkl; #if 0 /*BHE following code will never be true!!*/ /* Check that block length will not exceed buffer size */ if (curblkl > MAX_BLKLEN) { logmsg (_("HHCTA508E %4.4X: Block length exceeds %d " "at offset "I64_FMTX" in file %s\n"), dev->devnum, (int)MAX_BLKLEN, blkpos, dev->filename); /* Set unit check with data check */ build_senseX(TAPE_BSENSE_READFAIL,dev,unitstat,code); return -1; } #endif /* If not a tapemark, read the data block */ if (curblkl > 0) { rc = read (dev->fd, buf, curblkl); /* Handle read error condition */ if (rc < 0) { logmsg (_("HHCTA510E %4.4X: Error reading data block " "at offset "I64_FMTX" in file %s: %s\n"), dev->devnum, blkpos, dev->filename, strerror(errno)); /* Set unit check with equipment check */ build_senseX(TAPE_BSENSE_READFAIL,dev,unitstat,code); return -1; } /* Handle end of file within data block */ if (rc < curblkl) { logmsg (_("HHCTA511E %4.4X: Unexpected end of file in data block " "at offset "I64_FMTX" in file %s\n"), dev->devnum, blkpos, dev->filename); /* Set unit check with data check and partial record */ build_senseX(TAPE_BSENSE_BLOCKSHORT,dev,unitstat,code); return -1; } } /* Calculate the offsets of the next and previous blocks */ dev->prvblkpos = dev->nxtblkpos; dev->nxtblkpos = blkpos; /* Increment the block number */ dev->blockid++; /* Increment file number and return zero if tapemark was read */ if (curblkl == 0) { dev->curfilen++; return 0; /* UX will be set by caller */ } /* Return block length */ return curblkl; } /* end function read_faketape */ /*-------------------------------------------------------------------*/ /* Write a FAKETAPE block header */ /* */ /* If successful, return value is zero. */ /* If error, return value is -1 and unitstat is set to CE+DE+UC. */ /*-------------------------------------------------------------------*/ int writehdr_faketape (DEVBLK *dev, off_t blkpos, U16 prvblkl, U16 curblkl, BYTE *unitstat, BYTE code) { int rc; /* Return code */ off_t rcoff; /* Return code from lseek() */ FAKETAPE_BLKHDR fakehdr; /* FAKETAPE block header */ char sblklen[5]; /* work buffer */ /* Position file to where block header is to go */ rcoff = lseek (dev->fd, blkpos, SEEK_SET); if (rcoff < 0) { /* Handle seek error condition */ logmsg (_("HHCTA512E %4.4X: Error seeking to offset "I64_FMTX" " "in file %s: %s\n"), dev->devnum, blkpos, dev->filename, strerror(errno)); /* Set unit check with equipment check */ build_senseX(TAPE_BSENSE_LOCATEERR,dev,unitstat,code); return -1; } /* Build the 12-ASCII-hex-character block header */ snprintf( sblklen, sizeof(sblklen), "%4.4X", prvblkl ); strncpy( fakehdr.sprvblkl, sblklen, sizeof(fakehdr.sprvblkl) ); snprintf( sblklen, sizeof(sblklen), "%4.4X", curblkl ); strncpy( fakehdr.scurblkl, sblklen, sizeof(fakehdr.scurblkl) ); snprintf( sblklen, sizeof(sblklen), "%4.4X", prvblkl ^ curblkl ); strncpy( fakehdr.sxorblkl, sblklen, sizeof(fakehdr.sxorblkl) ); /* Write the block header */ rc = write (dev->fd, &fakehdr, sizeof(FAKETAPE_BLKHDR)); if (rc < (int)sizeof(FAKETAPE_BLKHDR)) { if(errno==ENOSPC) { /* Disk FULL */ build_senseX(TAPE_BSENSE_ENDOFTAPE,dev,unitstat,code); logmsg (_("HHCTA513E %4.4X: Media full condition reached " "at offset "I64_FMTX" in file %s\n"), dev->devnum, blkpos, dev->filename); return -1; } /* Handle write error condition */ logmsg (_("HHCTA514E %4.4X: Error writing block header " "at offset "I64_FMTX" in file %s: %s\n"), dev->devnum, blkpos, dev->filename, strerror(errno)); /* Set unit check with equipment check */ build_senseX(TAPE_BSENSE_WRITEFAIL,dev,unitstat,code); return -1; } return 0; } /* end function writehdr_faketape */ /*-------------------------------------------------------------------*/ /* Write a block to a FAKETAPE format file */ /* */ /* If successful, return value is zero. */ /* If error, return value is -1 and unitstat is set to CE+DE+UC */ /*-------------------------------------------------------------------*/ int write_faketape (DEVBLK *dev, BYTE *buf, U16 blklen, BYTE *unitstat,BYTE code) { int rc; /* Return code */ off_t rcoff; /* Return code from lseek() */ off_t blkpos; /* Offset of block header */ U16 prvblkl; /* Length of previous block */ /* Initialize current block position and previous block length */ blkpos = dev->nxtblkpos; prvblkl = 0; /* Determine previous block length if not at start of tape */ if (dev->nxtblkpos > 0) { /* Retrieve the previous block length */ rc = readhdr_faketape (dev, dev->prvblkpos, NULL, &prvblkl, unitstat,code); if (rc < 0) return -1; /* Recalculate the offset of the next block */ blkpos = dev->prvblkpos + sizeof(FAKETAPE_BLKHDR) + prvblkl; } /* Reposition file to the new block header */ rcoff = lseek (dev->fd, blkpos, SEEK_SET); if (rcoff < 0) { /* Handle seek error condition */ logmsg (_("HHCTA515E %4.4X: Error seeking to offset "I64_FMTX" " "in file %s: %s\n"), dev->devnum, blkpos, dev->filename, strerror(errno)); /* Set unit check with equipment check */ build_senseX(TAPE_BSENSE_LOCATEERR,dev,unitstat,code); return -1; } /* ISW: Determine if we are passed maxsize */ if(dev->tdparms.maxsize>0) { if((off_t)(dev->nxtblkpos+blklen+sizeof(FAKETAPE_BLKHDR)) > dev->tdparms.maxsize) { build_senseX(TAPE_BSENSE_ENDOFTAPE,dev,unitstat,code); return -1; } } /* ISW: End of virtual physical EOT determination */ /* Write the block header */ rc = writehdr_faketape (dev, rcoff, prvblkl, blklen, unitstat, code); if (rc < 0) return -1; /* (error message already issued) */ /* Calculate the offsets of the next and previous blocks */ dev->nxtblkpos = blkpos + sizeof(FAKETAPE_BLKHDR) + blklen; dev->prvblkpos = blkpos; /* Write the data block */ rc = write (dev->fd, buf, blklen); if (rc < blklen) { if(errno==ENOSPC) { /* Disk FULL */ build_senseX(TAPE_BSENSE_ENDOFTAPE,dev,unitstat,code); logmsg (_("HHCTA516E %4.4X: Media full condition reached " "at offset "I64_FMTX" in file %s\n"), dev->devnum, blkpos, dev->filename); return -1; } /* Handle write error condition */ logmsg (_("HHCTA517E %4.4X: Error writing data block " "at offset "I64_FMTX" in file %s: %s\n"), dev->devnum, blkpos, dev->filename, strerror(errno)); /* Set unit check with equipment check */ build_senseX(TAPE_BSENSE_WRITEFAIL,dev,unitstat,code); return -1; } /* Increment the block number */ dev->blockid++; /* Set new physical EOF */ do rc = ftruncate( dev->fd, dev->nxtblkpos ); while (EINTR == rc); if (rc != 0) { /* Handle write error condition */ logmsg (_("HHCTA518E %4.4X: Error writing data block " "at offset "I64_FMTX" in file %s: %s\n"), dev->devnum, blkpos, dev->filename, strerror(errno)); /* Set unit check with equipment check */ build_senseX(TAPE_BSENSE_WRITEFAIL,dev,unitstat,code); return -1; } /* Return normal status */ return 0; } /* end function write_faketape */ /*-------------------------------------------------------------------*/ /* Write a tapemark to a FAKETAPE format file */ /* */ /* If successful, return value is zero. */ /* If error, return value is -1 and unitstat is set to CE+DE+UC */ /*-------------------------------------------------------------------*/ int write_fakemark (DEVBLK *dev, BYTE *unitstat,BYTE code) { int rc; /* Return code */ off_t rcoff; /* Return code from lseek() */ off_t blkpos; /* Offset of block header */ U16 prvblkl; /* Length of previous block */ /* Initialize current block position and previous block length */ blkpos = dev->nxtblkpos; prvblkl = 0; /* Determine previous block length if not at start of tape */ if (dev->nxtblkpos > 0) { /* Retrieve the previous block length */ rc = readhdr_faketape (dev, dev->prvblkpos, NULL, &prvblkl, unitstat,code); if (rc < 0) return -1; /* Recalculate the offset of the next block */ blkpos = dev->prvblkpos + sizeof(FAKETAPE_BLKHDR) + prvblkl; } /* Reposition file to the new block header */ rcoff = lseek (dev->fd, blkpos, SEEK_SET); if (rcoff < 0) { /* Handle seek error condition */ logmsg (_("HHCTA519E %4.4X: Error seeking to offset "I64_FMTX" " "in file %s: %s\n"), dev->devnum, blkpos, dev->filename, strerror(errno)); build_senseX(TAPE_BSENSE_LOCATEERR,dev,unitstat,code); return -1; } /* ISW: Determine if we are passed maxsize */ if(dev->tdparms.maxsize>0) { if((off_t)(dev->nxtblkpos+sizeof(FAKETAPE_BLKHDR)) > dev->tdparms.maxsize) { build_senseX(TAPE_BSENSE_ENDOFTAPE,dev,unitstat,code); return -1; } } /* ISW: End of virtual physical EOT determination */ /* Write the block header */ rc = writehdr_faketape (dev, rcoff, prvblkl, 0, unitstat, code); if (rc < 0) return -1; /* (error message already issued) */ /* Increment the block number */ dev->blockid++; /* Calculate the offsets of the next and previous blocks */ dev->nxtblkpos = blkpos + sizeof(FAKETAPE_BLKHDR); dev->prvblkpos = blkpos; /* Set new physical EOF */ do rc = ftruncate( dev->fd, dev->nxtblkpos ); while (EINTR == rc); if (rc != 0) { /* Handle write error condition */ logmsg (_("HHCTA520E %4.4X: Error writing tape mark " "at offset "I64_FMTX" in file %s: %s\n"), dev->devnum, blkpos, dev->filename, strerror(errno)); /* Set unit check with equipment check */ build_senseX(TAPE_BSENSE_WRITEFAIL,dev,unitstat,code); return -1; } /* Return normal status */ return 0; } /* end function write_fakemark */ /*-------------------------------------------------------------------*/ /* Synchronize a FAKETAPE format file (i.e. flush buffers to disk) */ /* */ /* If successful, return value is zero. */ /* If error, return value is -1 and unitstat is set to CE+DE+UC */ /*-------------------------------------------------------------------*/ int sync_faketape (DEVBLK *dev, BYTE *unitstat,BYTE code) { /* Unit check if tape is write-protected */ if (dev->readonly) { build_senseX(TAPE_BSENSE_WRITEPROTECT,dev,unitstat,code); return -1; } /* Perform sync. Return error on failure. */ if (fdatasync( dev->fd ) < 0) { /* Log the error */ logmsg (_("HHCTA521E %4.4X: Sync error on file %s: %s\n"), dev->devnum, dev->filename, strerror(errno)); /* Set unit check with equipment check */ build_senseX(TAPE_BSENSE_WRITEFAIL,dev,unitstat,code); return -1; } /* Return normal status */ return 0; } /* end function sync_faketape */ /*-------------------------------------------------------------------*/ /* Forward space over next block of a FAKETAPE format file */ /* */ /* If successful, return value is the length of the block skipped. */ /* If the block skipped was a tapemark, the return value is zero, */ /* and the current file number in the device block is incremented. */ /* If error, return value is -1 and unitstat is set to CE+DE+UC */ /*-------------------------------------------------------------------*/ int fsb_faketape (DEVBLK *dev, BYTE *unitstat,BYTE code) { int rc; /* Return code */ off_t blkpos; /* Offset of block header */ U16 blklen; /* Block length */ /* Initialize current block position */ blkpos = dev->nxtblkpos; /* Read the block header to obtain the current block length */ rc = readhdr_faketape (dev, blkpos, NULL, &blklen, unitstat,code); if (rc < 0) return -1; /* (error message already issued) */ /* Calculate the offset of the next block */ blkpos += sizeof(FAKETAPE_BLKHDR) + blklen; /* Calculate the offsets of the next and previous blocks */ dev->prvblkpos = dev->nxtblkpos; dev->nxtblkpos = blkpos; /* Increment current file number if tapemark was skipped */ if (blklen == 0) dev->curfilen++; /* Increment the block number */ dev->blockid++; /* Return block length or zero if tapemark */ return blklen; } /* end function fsb_faketape */ /*-------------------------------------------------------------------*/ /* Backspace to previous block of a FAKETAPE format file */ /* */ /* If successful, return value is the length of the block. */ /* If the block is a tapemark, the return value is zero, */ /* and the current file number in the device block is decremented. */ /* If error, return value is -1 and unitstat is set to CE+DE+UC */ /*-------------------------------------------------------------------*/ int bsb_faketape (DEVBLK *dev, BYTE *unitstat,BYTE code) { int rc; /* Return code */ U16 curblkl; /* Length of current block */ U16 prvblkl; /* Length of previous block */ off_t blkpos; /* Offset of block header */ /* Unit check if already at start of tape */ if (dev->nxtblkpos == 0) { build_senseX(TAPE_BSENSE_LOADPTERR,dev,unitstat,code); return -1; } /* Backspace to previous block position */ blkpos = dev->prvblkpos; /* Read the block header to obtain the block lengths */ rc = readhdr_faketape (dev, blkpos, &prvblkl, &curblkl, unitstat,code); if (rc < 0) return -1; /* (error message already issued) */ /* Calculate the offset of the previous block */ dev->prvblkpos = blkpos - sizeof(FAKETAPE_BLKHDR) - prvblkl; dev->nxtblkpos = blkpos; /* Decrement current file number if backspaced over tapemark */ if (curblkl == 0) dev->curfilen--; /* Decrement the block number */ dev->blockid--; /* Return block length or zero if tapemark */ return curblkl; } /* end function bsb_faketape */ /*-------------------------------------------------------------------*/ /* Forward space to next logical file of a FAKETAPE format file */ /* */ /* For FAKETAPE files, the forward space file operation is achieved */ /* by forward spacing blocks until positioned just after a tapemark. */ /* */ /* If successful, return value is zero, and the current file number */ /* in the device block is incremented by fsb_faketape. */ /* If error, return value is -1 and unitstat is set to CE+DE+UC */ /*-------------------------------------------------------------------*/ int fsf_faketape (DEVBLK *dev, BYTE *unitstat,BYTE code) { int rc; /* Return code */ while (1) { /* Forward space over next block */ rc = fsb_faketape (dev, unitstat,code); if (rc < 0) return -1; /* (error message already issued) */ /* Exit loop if spaced over a tapemark */ if (rc == 0) break; } /* end while */ /* Return normal status */ return 0; } /* end function fsf_faketape */ /*-------------------------------------------------------------------*/ /* Backspace to previous logical file of a FAKETAPE format file */ /* */ /* For FAKETAPE files, the backspace file operation is achieved */ /* by backspacing blocks until positioned just before a tapemark */ /* or until positioned at start of tape. */ /* */ /* If successful, return value is zero, and the current file number */ /* in the device block is decremented by bsb_faketape. */ /* If error, return value is -1 and unitstat is set to CE+DE+UC */ /*-------------------------------------------------------------------*/ int bsf_faketape (DEVBLK *dev, BYTE *unitstat,BYTE code) { int rc; /* Return code */ while (1) { /* Exit if now at start of tape */ if (dev->nxtblkpos == 0) { build_senseX(TAPE_BSENSE_LOADPTERR,dev,unitstat,code); return -1; } /* Backspace to previous block position */ rc = bsb_faketape (dev, unitstat,code); if (rc < 0) return -1; /* (error message already issued) */ /* Exit loop if backspaced over a tapemark */ if (rc == 0) break; } /* end while */ /* Return normal status */ return 0; } /* end function bsf_faketape */ /*********************************************************************/ /* END OF ORIGINAL RB AWS FUNCTIONS */ /*********************************************************************/ hercules-3.07/fbadasd.c000644 000765 000765 00000160346 11301535255 016505 0ustar00jmaynardjmaynard000000 000000 /* FBADASD.C (c) Copyright Roger Bowler, 1999-2009 */ /* ESA/390 FBA Direct Access Storage Device Handler */ // $Id: fbadasd.c 5460 2009-09-15 07:47:32Z hsg001 $ /*-------------------------------------------------------------------*/ /* This module contains device handling functions for emulated */ /* fixed block architecture direct access storage devices. */ /*-------------------------------------------------------------------*/ /*-------------------------------------------------------------------*/ /* Additional credits: */ /* 0671 device support by Jay Maynard */ /*-------------------------------------------------------------------*/ // $Log$ // Revision 1.49 2009/01/23 11:53:48 bernard // copyright notice // // Revision 1.48 2007/11/21 22:54:14 fish // Use new BEGIN_DEVICE_CLASS_QUERY macro // // Revision 1.47 2007/06/23 00:04:09 ivan // Update copyright notices to include current year (2007) // // Revision 1.46 2007/06/06 02:55:39 ivan // Allow Byte 0 Bit 3 of FBA Locate CCW to be non-zero // // Revision 1.45 2007/03/15 20:57:55 gsmith // Fix fba when the fba device is > 4G // // Revision 1.44 2006/12/08 09:43:20 jj // Add CVS message log // #include "hstdinc.h" #define _FBADASD_C_ #define _HDASD_DLL_ #include "hercules.h" #include "dasdblks.h" // (need #define DEFAULT_FBA_TYPE) #include "sr.h" /*-------------------------------------------------------------------*/ /* Bit definitions for Define Extent file mask */ /*-------------------------------------------------------------------*/ #define FBAMASK_CTL 0xC0 /* Operation control bits... */ #define FBAMASK_CTL_INHFMT 0x00 /* ...inhibit format writes */ #define FBAMASK_CTL_INHWRT 0x40 /* ...inhibit all writes */ #define FBAMASK_CTL_ALLWRT 0xC0 /* ...allow all writes */ #define FBAMASK_CTL_RESV 0x80 /* ...reserved bit setting */ #define FBAMASK_CE 0x08 /* CE field extent */ #define FBAMASK_DIAG 0x04 /* Permit diagnostic command */ #define FBAMASK_RESV 0x33 /* Reserved bits - must be 0 */ /*-------------------------------------------------------------------*/ /* Bit definitions for Locate operation byte */ /*-------------------------------------------------------------------*/ #define FBAOPER_RESV 0xE0 /* Reserved bits - must be 0 */ /* Note : Bit 3 seems to be */ /* The "suppress" bit but is */ /* apparently ignored */ /* It is therefore valid but */ /* not used. */ #define FBAOPER_CODE 0x0F /* Operation code bits... */ #define FBAOPER_WRITE 0x01 /* ...write data */ #define FBAOPER_READREP 0x02 /* ...read replicated data */ #define FBAOPER_FMTDEFC 0x04 /* ...format defective block */ #define FBAOPER_WRTVRFY 0x05 /* ...write data and verify */ #define FBAOPER_READ 0x06 /* ...read data */ #define FBA_BLKGRP_SIZE (120 * 512) /* Size of block group */ /*-------------------------------------------------------------------*/ /* Initialize the device handler */ /*-------------------------------------------------------------------*/ int fbadasd_init_handler ( DEVBLK *dev, int argc, char *argv[] ) { int rc; /* Return code */ struct stat statbuf; /* File information */ int startblk; /* Device origin block number*/ int numblks; /* Device block count */ BYTE c; /* Character work area */ int cfba = 0; /* 1 = Compressed fba */ int i; /* Loop index */ CKDDASD_DEVHDR devhdr; /* Device header */ CCKDDASD_DEVHDR cdevhdr; /* Compressed device header */ char pathname[MAX_PATH]; /* file path in host format */ if (!dev->typname || !sscanf(dev->typname,"%hx",&(dev->devtype))) dev->devtype = DEFAULT_FBA_TYPE; /* The first argument is the file name */ if (argc == 0 || strlen(argv[0]) > sizeof(dev->filename)-1) { logmsg (_("HHCDA056E File name missing or invalid\n")); return -1; } /* Save the file name in the device block */ strcpy (dev->filename, argv[0]); /* Device is shareable */ dev->shared = 1; /* Check for possible remote device */ hostpath(pathname, dev->filename, sizeof(pathname)); if (stat(pathname, &statbuf) < 0) { rc = shared_fba_init ( dev, argc, argv); if (rc < 0) { logmsg (_("HHCDA057E %4.4X:File not found or invalid\n"), dev->devnum); return -1; } else return rc; } /* Open the device file */ hostpath(pathname, dev->filename, sizeof(pathname)); dev->fd = open (pathname, O_RDWR|O_BINARY); if (dev->fd < 0) { dev->fd = open (pathname, O_RDONLY|O_BINARY); if (dev->fd < 0) { logmsg (_("HHCDA058E File %s open error: %s\n"), dev->filename, strerror(errno)); return -1; } } /* Read the first block to see if it's compressed */ rc = read (dev->fd, &devhdr, CKDDASD_DEVHDR_SIZE); if (rc < (int)CKDDASD_DEVHDR_SIZE) { /* Handle read error condition */ if (rc < 0) logmsg (_("HHCDA059E Read error in file %s: %s\n"), dev->filename, strerror(errno)); else logmsg (_("HHCDA060E Unexpected end of file in %s\n"), dev->filename); close (dev->fd); dev->fd = -1; return -1; } /* Processing for compressed fba dasd */ if (memcmp (&devhdr.devid, "FBA_C370", 8) == 0) { cfba = 1; /* Read the compressed device header */ rc = read (dev->fd, &cdevhdr, CCKDDASD_DEVHDR_SIZE); if (rc < (int)CKDDASD_DEVHDR_SIZE) { /* Handle read error condition */ if (rc < 0) logmsg (_("HHCDA061E Read error in file %s: %s\n"), dev->filename, strerror(errno)); else logmsg (_("HHCDA062E Unexpected end of file in %s\n"), dev->filename); close (dev->fd); dev->fd = -1; return -1; } /* Set block size, device origin, and device size in blocks */ dev->fbablksiz = 512; dev->fbaorigin = 0; dev->fbanumblk = ((U32)(cdevhdr.cyls[3]) << 24) | ((U32)(cdevhdr.cyls[2]) << 16) | ((U32)(cdevhdr.cyls[1]) << 8) | (U32)(cdevhdr.cyls[0]); /* Default to synchronous I/O */ //FIXME: syncio is reported to be broken for fba // dev->syncio = 1; /* process the remaining arguments */ for (i = 1; i < argc; i++) { if (strlen (argv[i]) > 3 && memcmp ("sf=", argv[i], 3) == 0) { if (strlen(argv[i]+3) < 256) dev->dasdsfn=strdup (argv[i]+3); if (dev->dasdsfn) { /* Set the pointer to the suffix character */ dev->dasdsfx = strrchr (dev->dasdsfn, '/'); if (dev->dasdsfx == NULL) dev->dasdsfx = dev->dasdsfn + 1; dev->dasdsfx = strchr (dev->dasdsfx, '.'); if (dev->dasdsfx == NULL) dev->dasdsfx = dev->dasdsfn + strlen(dev->dasdsfn); dev->dasdsfx--; } continue; } if (strcasecmp ("nosyncio", argv[i]) == 0 || strcasecmp ("nosyio", argv[i]) == 0) { dev->syncio = 0; continue; } if (strcasecmp ("syncio", argv[i]) == 0 || strcasecmp ("syio", argv[i]) == 0) { dev->syncio = 1; continue; } logmsg (_("HHCDA063E parameter %d is invalid: %s\n"), i + 1, argv[i]); return -1; } } /* Processing for regular fba dasd */ else { /* Determine the device size */ rc = fstat (dev->fd, &statbuf); if (rc < 0) { logmsg (_("HHCDA064E File %s fstat error: %s\n"), dev->filename, strerror(errno)); close (dev->fd); dev->fd = -1; return -1; } #if defined(OPTION_FBA_BLKDEVICE) && defined(BLKGETSIZE) if(S_ISBLK(statbuf.st_mode)) { rc=ioctl(dev->fd,BLKGETSIZE,&statbuf.st_size); if(rc<0) { logmsg (_("HHCDA082E File %s IOCTL BLKGETSIZE error: %s\n"), dev->filename, strerror(errno)); close (dev->fd); dev->fd = -1; return -1; } dev->fbablksiz = 512; dev->fbaorigin = 0; dev->fbanumblk = statbuf.st_size; logmsg("REAL FBA Opened\n"); } else #endif // defined(OPTION_FBA_BLKDEVICE) && defined(BLKGETSIZE) { /* Set block size, device origin, and device size in blocks */ dev->fbablksiz = 512; dev->fbaorigin = 0; dev->fbanumblk = statbuf.st_size / dev->fbablksiz; } /* The second argument is the device origin block number */ if (argc >= 2) { if (sscanf(argv[1], "%u%c", &startblk, &c) != 1 || startblk >= dev->fbanumblk) { logmsg (_("HHCDA065E Invalid device origin block number %s\n"), argv[1]); close (dev->fd); dev->fd = -1; return -1; } dev->fbaorigin = (off_t)startblk; dev->fbanumblk -= startblk; } /* The third argument is the device block count */ if (argc >= 3 && strcmp(argv[2],"*") != 0) { if (sscanf(argv[2], "%u%c", &numblks, &c) != 1 || numblks > dev->fbanumblk) { logmsg (_("HHCDA066E Invalid device block count %s\n"), argv[2]); close (dev->fd); dev->fd = -1; return -1; } dev->fbanumblk = numblks; } } dev->fbaend = (dev->fbaorigin + dev->fbanumblk) * dev->fbablksiz; logmsg (_("HHCDA067I %s origin=%lld blks=%d\n"), dev->filename, (long long)dev->fbaorigin, dev->fbanumblk); /* Set number of sense bytes */ dev->numsense = 24; /* Locate the FBA dasd table entry */ dev->fbatab = dasd_lookup (DASD_FBADEV, NULL, dev->devtype, dev->fbanumblk); if (dev->fbatab == NULL) { logmsg (_("HHCDA068E %4.4X device type %4.4X not found in dasd table\n"), dev->devnum, dev->devtype); close (dev->fd); dev->fd = -1; return -1; } /* Build the devid area */ dev->numdevid = dasd_build_fba_devid (dev->fbatab,(BYTE *)&dev->devid); /* Build the devchar area */ dev->numdevchar = dasd_build_fba_devchar (dev->fbatab, (BYTE *)&dev->devchar,dev->fbanumblk); /* Initialize current blkgrp and cache entry */ dev->bufcur = dev->cache = -1; /* Activate I/O tracing */ // dev->ccwtrace = 1; /* Call the compressed init handler if compressed fba */ if (cfba) return cckddasd_init_handler (dev, argc, argv); return 0; } /* end function fbadasd_init_handler */ /*-------------------------------------------------------------------*/ /* Query the device definition */ /*-------------------------------------------------------------------*/ void fbadasd_query_device (DEVBLK *dev, char **class, int buflen, char *buffer) { BEGIN_DEVICE_CLASS_QUERY( "DASD", dev, class, buflen, buffer ); snprintf (buffer, buflen, "%s [%lld,%d]", dev->filename, (long long)dev->fbaorigin, dev->fbanumblk); } /* end function fbadasd_query_device */ /*-------------------------------------------------------------------*/ /* Calculate length of an FBA block group */ /*-------------------------------------------------------------------*/ static int fba_blkgrp_len (DEVBLK *dev, int blkgrp) { off_t offset; /* Offset of block group */ offset = blkgrp * FBA_BLKGRP_SIZE; if (dev->fbaend - offset < FBA_BLKGRP_SIZE) return (int)(dev->fbaend - offset); else return FBA_BLKGRP_SIZE; } /*-------------------------------------------------------------------*/ /* Read fba block(s) */ /*-------------------------------------------------------------------*/ static int fba_read (DEVBLK *dev, BYTE *buf, int len, BYTE *unitstat) { int rc; /* Return code */ int blkgrp; /* Block group number */ int blklen; /* Length left in block group*/ int off; /* Device buffer offset */ int bufoff; /* Buffer offset */ int copylen; /* Length left to copy */ /* Command reject if referencing outside the volume */ if (dev->fbarba < dev->fbaorigin * dev->fbablksiz || dev->fbarba + len > dev->fbaend) { dev->sense[0] = SENSE_CR; *unitstat = CSW_CE | CSW_DE | CSW_UC; return -1; } /* Read the block group */ blkgrp = dev->fbarba / FBA_BLKGRP_SIZE; rc = (dev->hnd->read) (dev, blkgrp, unitstat); if (rc < 0) return -1; off = dev->fbarba % FBA_BLKGRP_SIZE; blklen = dev->buflen - off; /* Initialize target buffer offset and length to copy */ bufoff = 0; copylen = len; /* Access multiple block groups asynchronously */ if (dev->syncio_active && copylen > blklen) { dev->syncio_retry = 1; return -1; } /* Copy from the device buffer to the target buffer */ while (copylen > 0) { int len = copylen < blklen ? copylen : blklen; /* Copy to the target buffer */ if (buf) memcpy (buf + bufoff, dev->buf + off, len); /* Update offsets and lengths */ bufoff += len; copylen -= blklen; /* Read the next block group if still more to copy */ if (copylen > 0) { blkgrp++; off = 0; rc = (dev->hnd->read) (dev, blkgrp, unitstat); if (rc < 0) return -1; blklen = fba_blkgrp_len (dev, blkgrp); } } /* Update the rba */ dev->fbarba += len; return len; } /* end function fba_read */ /*-------------------------------------------------------------------*/ /* Write fba block(s) */ /*-------------------------------------------------------------------*/ static int fba_write (DEVBLK *dev, BYTE *buf, int len, BYTE *unitstat) { int rc; /* Return code */ int blkgrp; /* Block group number */ int blklen; /* Length left in block group*/ int off; /* Target buffer offset */ int bufoff; /* Source buffer offset */ int copylen; /* Length left to copy */ /* Command reject if referencing outside the volume */ if (dev->fbarba < dev->fbaorigin * dev->fbablksiz || dev->fbarba + len > dev->fbaend) { dev->sense[0] = SENSE_CR; *unitstat = CSW_CE | CSW_DE | CSW_UC; return -1; } /* Read the block group */ blkgrp = dev->fbarba / FBA_BLKGRP_SIZE; rc = (dev->hnd->read) (dev, blkgrp, unitstat); if (rc < 0) return -1; off = dev->fbarba % FBA_BLKGRP_SIZE; blklen = dev->buflen - off; /* Initialize source buffer offset and length to copy */ bufoff = 0; copylen = len; /* Access multiple block groups asynchronously */ if (dev->syncio_active && copylen > blklen) { dev->syncio_retry = 1; return -1; } /* Copy to the device buffer from the target buffer */ while (copylen > 0) { int len = copylen < blklen ? copylen : blklen; /* Write to the block group */ rc = (dev->hnd->write) (dev, blkgrp, off, buf + bufoff, len, unitstat); if (rc < 0) return -1; /* Update offsets and lengths */ bufoff += len; copylen -= len; blkgrp++; off = 0; blklen = fba_blkgrp_len (dev, blkgrp); } /* Update the rba */ dev->fbarba += len; return len; } /* end function fba_write */ /*-------------------------------------------------------------------*/ /* FBA read block group exit */ /*-------------------------------------------------------------------*/ static int fbadasd_read_blkgrp (DEVBLK *dev, int blkgrp, BYTE *unitstat) { int rc; /* Return code */ int i, o; /* Cache indexes */ int len; /* Length to read */ off_t offset; /* File offsets */ /* Return if reading the same block group */ if (blkgrp >= 0 && blkgrp == dev->bufcur) return 0; /* Write the previous block group if modified */ if (dev->bufupd) { /* Retry if synchronous I/O */ if (dev->syncio_active) { dev->syncio_retry = 1; return -1; } dev->bufupd = 0; /* Seek to the old block group offset */ offset = (off_t)(((S64)dev->bufcur * FBA_BLKGRP_SIZE) + dev->bufupdlo); offset = lseek (dev->fd, offset, SEEK_SET); if (offset < 0) { /* Handle seek error condition */ logmsg (_("HHCDA069E error writing blkgrp %d: lseek error: %s\n"), dev->bufcur, strerror(errno)); dev->sense[0] = SENSE_EC; *unitstat = CSW_CE | CSW_DE | CSW_UC; cache_lock(CACHE_DEVBUF); cache_setflag(CACHE_DEVBUF, dev->cache, ~FBA_CACHE_ACTIVE, 0); cache_unlock(CACHE_DEVBUF); dev->bufupdlo = dev->bufupdhi = 0; dev->bufcur = dev->cache = -1; return -1; } /* Write the portion of the block group that was modified */ rc = write (dev->fd, dev->buf + dev->bufupdlo, dev->bufupdhi - dev->bufupdlo); if (rc < dev->bufupdhi - dev->bufupdlo) { /* Handle write error condition */ logmsg (_("HHCDA070E error writing blkgrp %d: write error: %s\n"), dev->bufcur, strerror(errno)); dev->sense[0] = SENSE_EC; *unitstat = CSW_CE | CSW_DE | CSW_UC; cache_lock(CACHE_DEVBUF); cache_setflag(CACHE_DEVBUF, dev->cache, ~FBA_CACHE_ACTIVE, 0); cache_unlock(CACHE_DEVBUF); dev->bufupdlo = dev->bufupdhi = 0; dev->bufcur = dev->cache = -1; return -1; } dev->bufupdlo = dev->bufupdhi = 0; } cache_lock (CACHE_DEVBUF); /* Make the previous cache entry inactive */ if (dev->cache >= 0) cache_setflag(CACHE_DEVBUF, dev->cache, ~FBA_CACHE_ACTIVE, 0); dev->bufcur = dev->cache = -1; /* Return on special case when called by the close handler */ if (blkgrp < 0) { cache_unlock (CACHE_DEVBUF); return 0; } fba_read_blkgrp_retry: /* Search the cache */ i = cache_lookup (CACHE_DEVBUF, FBA_CACHE_SETKEY(dev->devnum, blkgrp), &o); /* Cache hit */ if (i >= 0) { cache_setflag(CACHE_DEVBUF, i, ~0, FBA_CACHE_ACTIVE); cache_setage(CACHE_DEVBUF, i); cache_unlock(CACHE_DEVBUF); logdevtr (dev, _("HHCDA071I read blkgrp %d cache hit, using cache[%d]\n"), blkgrp, i); dev->cachehits++; dev->cache = i; dev->buf = cache_getbuf(CACHE_DEVBUF, dev->cache, 0); dev->bufcur = blkgrp; dev->bufoff = 0; dev->bufoffhi = fba_blkgrp_len (dev, blkgrp); dev->buflen = fba_blkgrp_len (dev, blkgrp); dev->bufsize = cache_getlen(CACHE_DEVBUF, dev->cache); return 0; } /* Retry if synchronous I/O */ if (dev->syncio_active) { cache_unlock(CACHE_DEVBUF); dev->syncio_retry = 1; return -1; } /* Wait if no available cache entry */ if (o < 0) { logdevtr (dev, _("HHCDA072I read blkgrp %d no available cache entry, waiting\n"), blkgrp); dev->cachewaits++; cache_wait(CACHE_DEVBUF); goto fba_read_blkgrp_retry; } /* Cache miss */ logdevtr (dev, _("HHCDA073I read blkgrp %d cache miss, using cache[%d]\n"), blkgrp, o); dev->cachemisses++; /* Make this cache entry active */ cache_setkey (CACHE_DEVBUF, o, FBA_CACHE_SETKEY(dev->devnum, blkgrp)); cache_setflag(CACHE_DEVBUF, o, 0, FBA_CACHE_ACTIVE|DEVBUF_TYPE_FBA); cache_setage (CACHE_DEVBUF, o); dev->buf = cache_getbuf(CACHE_DEVBUF, o, FBA_BLKGRP_SIZE); cache_unlock (CACHE_DEVBUF); /* Get offset and length */ offset = (off_t)((S64)blkgrp * FBA_BLKGRP_SIZE); len = fba_blkgrp_len (dev, blkgrp); logdevtr (dev, _("HHCDA074I read blkgrp %d offset %" I64_FMT "d len %d\n"), blkgrp, (long long)offset, fba_blkgrp_len(dev, blkgrp)); /* Seek to the block group offset */ offset = lseek (dev->fd, offset, SEEK_SET); if (offset < 0) { /* Handle seek error condition */ logmsg (_("HHCDA075E error reading blkgrp %d: lseek error: %s\n"), blkgrp, strerror(errno)); dev->sense[0] = SENSE_EC; *unitstat = CSW_CE | CSW_DE | CSW_UC; cache_lock(CACHE_DEVBUF); cache_release(CACHE_DEVBUF, o, 0); cache_unlock(CACHE_DEVBUF); return -1; } /* Read the block group */ rc = read (dev->fd, dev->buf, len); if (rc < len) { /* Handle read error condition */ logmsg (_("HHCDA076E error reading blkgrp %d: read error: %s\n"), blkgrp, rc < 0 ? strerror(errno) : "end of file"); dev->sense[0] = SENSE_EC; *unitstat = CSW_CE | CSW_DE | CSW_UC; cache_lock(CACHE_DEVBUF); cache_release(CACHE_DEVBUF, o, 0); cache_unlock(CACHE_DEVBUF); return -1; } dev->cache = o; dev->buf = cache_getbuf(CACHE_DEVBUF, dev->cache, 0); dev->bufcur = blkgrp; dev->bufoff = 0; dev->bufoffhi = fba_blkgrp_len (dev, blkgrp); dev->buflen = fba_blkgrp_len (dev, blkgrp); dev->bufsize = cache_getlen(CACHE_DEVBUF, dev->cache); return 0; } /* end function fbadasd_read_blkgrp */ /*-------------------------------------------------------------------*/ /* FBA update block group exit */ /*-------------------------------------------------------------------*/ static int fbadasd_update_blkgrp (DEVBLK *dev, int blkgrp, int off, BYTE *buf, int len, BYTE *unitstat) { int rc; /* Return code */ /* Read the block group */ if (blkgrp != dev->bufcur) { rc = (dev->hnd->read) (dev, blkgrp, unitstat); if (rc < 0) { dev->bufcur = dev->cache = -1; return -1; } } /* Copy to the device buffer */ if (buf) memcpy (dev->buf + off, buf, len); /* Update high/low offsets */ if (!dev->bufupd || off < dev->bufupdlo) dev->bufupdlo = off; if (off + len > dev-> bufupdhi) dev->bufupdhi = off + len; /* Indicate block group has been modified */ if (!dev->bufupd) { dev->bufupd = 1; shared_update_notify (dev, blkgrp); } return len; } /* end function fbadasd_update_blkgrp */ /*-------------------------------------------------------------------*/ /* Channel program end exit */ /*-------------------------------------------------------------------*/ static void fbadasd_end (DEVBLK *dev) { BYTE unitstat; /* Forces updated buffer to be written */ fbadasd_read_blkgrp (dev, -1, &unitstat); } /*-------------------------------------------------------------------*/ /* Release cache entries */ /*-------------------------------------------------------------------*/ int fbadasd_purge_cache (int *answer, int ix, int i, void *data) { U16 devnum; /* Cached device number */ int blkgrp; /* Cached block group */ DEVBLK *dev = data; /* -> device block */ UNREFERENCED(answer); FBA_CACHE_GETKEY(i, devnum, blkgrp); if (dev->devnum == devnum) cache_release (ix, i, CACHE_FREEBUF); return 0; } /*-------------------------------------------------------------------*/ /* Close the device */ /*-------------------------------------------------------------------*/ int fbadasd_close_device ( DEVBLK *dev ) { BYTE unitstat; /* Forces updated buffer to be written */ fbadasd_read_blkgrp (dev, -1, &unitstat); /* Free the cache */ cache_lock(CACHE_DEVBUF); cache_scan(CACHE_DEVBUF, fbadasd_purge_cache, dev); cache_unlock(CACHE_DEVBUF); /* Close the device file */ close (dev->fd); dev->fd = -1; return 0; } /* end function fbadasd_close_device */ /*-------------------------------------------------------------------*/ /* Return used blocks */ /*-------------------------------------------------------------------*/ static int fbadasd_used (DEVBLK *dev) { return dev->fbanumblk; } /*-------------------------------------------------------------------*/ /* Execute a Channel Command Word */ /*-------------------------------------------------------------------*/ void fbadasd_execute_ccw ( DEVBLK *dev, BYTE code, BYTE flags, BYTE chained, U16 count, BYTE prevcode, int ccwseq, BYTE *iobuf, BYTE *more, BYTE *unitstat, U16 *residual ) { int rc; /* Return code */ int num; /* Number of bytes to move */ BYTE hexzeroes[512]; /* Bytes for zero fill */ int rem; /* Byte count for zero fill */ int repcnt; /* Replication count */ /* Reset extent flag at start of CCW chain */ if (chained == 0) dev->fbaxtdef = 0; /* Process depending on CCW opcode */ switch (code) { case 0x02: /*---------------------------------------------------------------*/ /* READ IPL */ /*---------------------------------------------------------------*/ /* Must be first CCW or chained from a previous READ IPL CCW */ if (chained && prevcode != 0x02) { dev->sense[0] = SENSE_CR; *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Zeroize the file mask and set extent for entire device */ dev->fbamask = 0; dev->fbaxblkn = 0; dev->fbaxfirst = 0; dev->fbaxlast = dev->fbanumblk - 1; /* Seek to start of block zero */ dev->fbarba = dev->fbaorigin * dev->fbablksiz; /* Overrun if data chaining */ if ((flags & CCW_FLAGS_CD)) { dev->sense[0] = SENSE_OR; *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Calculate number of bytes to read and set residual count */ num = (count < dev->fbablksiz) ? count : dev->fbablksiz; *residual = count - num; if (count < dev->fbablksiz) *more = 1; /* Read physical block into channel buffer */ rc = fba_read (dev, iobuf, num, unitstat); if (rc < num) break; /* Set extent defined flag */ dev->fbaxtdef = 1; /* Set normal status */ *unitstat = CSW_CE | CSW_DE; break; case 0x03: /*---------------------------------------------------------------*/ /* CONTROL NO-OPERATION */ /*---------------------------------------------------------------*/ *unitstat = CSW_CE | CSW_DE; break; case 0x41: /*---------------------------------------------------------------*/ /* WRITE */ /*---------------------------------------------------------------*/ /* Reject if previous command was not LOCATE */ if (prevcode != 0x43) { dev->sense[0] = SENSE_CR; *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Reject if locate command did not specify write operation */ if ((dev->fbaoper & FBAOPER_CODE) != FBAOPER_WRITE && (dev->fbaoper & FBAOPER_CODE) != FBAOPER_WRTVRFY) { dev->sense[0] = SENSE_CR; *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Prepare a block of zeroes for write padding */ memset (hexzeroes, 0, sizeof(hexzeroes)); /* Write physical blocks of data to the device */ while (dev->fbalcnum > 0) { /* Exit if data chaining and this CCW is exhausted */ if ((flags & CCW_FLAGS_CD) && count == 0) break; /* Overrun if data chaining within a physical block */ if ((flags & CCW_FLAGS_CD) && count < dev->fbablksiz) { dev->sense[0] = SENSE_OR; *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Calculate number of bytes to write */ num = (count < dev->fbablksiz) ? count : dev->fbablksiz; if (num < dev->fbablksiz) *more = 1; /* Write physical block from channel buffer */ if (num > 0) { rc = fba_write (dev, iobuf, num, unitstat); if (rc < num) break; } /* Fill remainder of block with zeroes */ if (num < dev->fbablksiz) { rem = dev->fbablksiz - num; rc = fba_write (dev, hexzeroes, rem, unitstat); if (rc < rem) break; } /* Prepare to write next block */ count -= num; iobuf += num; dev->fbalcnum--; } /* end while */ /* Set residual byte count */ *residual = count; if (dev->fbalcnum > 0) *more = 1; /* Set ending status */ *unitstat |= CSW_CE | CSW_DE; break; case 0x42: /*---------------------------------------------------------------*/ /* READ */ /*---------------------------------------------------------------*/ /* Reject if previous command was not LOCATE or READ IPL */ if (prevcode != 0x43 && prevcode != 0x02) { dev->sense[0] = SENSE_CR; *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Reject if locate command did not specify read operation */ if (prevcode != 0x02 && (dev->fbaoper & FBAOPER_CODE) != FBAOPER_READ && (dev->fbaoper & FBAOPER_CODE) != FBAOPER_READREP) { dev->sense[0] = SENSE_CR; *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Read physical blocks of data from device */ while (dev->fbalcnum > 0 && count > 0) { /* Overrun if data chaining within a physical block */ if ((flags & CCW_FLAGS_CD) && count < dev->fbablksiz) { dev->sense[0] = SENSE_OR; *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Calculate number of bytes to read */ num = (count < dev->fbablksiz) ? count : dev->fbablksiz; if (num < dev->fbablksiz) *more = 1; /* Read physical block into channel buffer */ rc = fba_read (dev, iobuf, num, unitstat); if (rc < num) break; /* Prepare to read next block */ count -= num; iobuf += num; dev->fbalcnum--; } /* end while */ /* Set residual byte count */ *residual = count; if (dev->fbalcnum > 0) *more = 1; /* Set ending status */ *unitstat |= CSW_CE | CSW_DE; break; case 0x43: /*---------------------------------------------------------------*/ /* LOCATE */ /*---------------------------------------------------------------*/ /* Calculate residual byte count */ num = (count < 8) ? count : 8; *residual = count - num; /* Control information length must be at least 8 bytes */ if (count < 8) { dev->sense[0] = SENSE_CR; *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* LOCATE must be preceded by DEFINE EXTENT or READ IPL */ if (dev->fbaxtdef == 0) { dev->sense[0] = SENSE_CR; *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Save and validate the operation byte */ dev->fbaoper = iobuf[0]; if (dev->fbaoper & FBAOPER_RESV) { dev->sense[0] = SENSE_CR; *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Validate and process operation code */ if ((dev->fbaoper & FBAOPER_CODE) == FBAOPER_WRITE || (dev->fbaoper & FBAOPER_CODE) == FBAOPER_WRTVRFY) { /* Reject command if file mask inhibits all writes */ if ((dev->fbamask & FBAMASK_CTL) == FBAMASK_CTL_INHWRT) { dev->sense[0] = SENSE_CR; *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } } else if ((dev->fbaoper & FBAOPER_CODE) == FBAOPER_READ || (dev->fbaoper & FBAOPER_CODE) == FBAOPER_READREP) { } else if ((dev->fbaoper & FBAOPER_CODE) == FBAOPER_FMTDEFC) { /* Reject command if file mask inhibits format writes */ if ((dev->fbamask & FBAMASK_CTL) == FBAMASK_CTL_INHFMT) { dev->sense[0] = SENSE_CR; *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } } else /* Operation code is invalid */ { dev->sense[0] = SENSE_CR; *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Byte 1 contains the replication count */ repcnt = iobuf[1]; /* Bytes 2-3 contain the block count */ dev->fbalcnum = fetch_hw(iobuf + 2); /* Bytes 4-7 contain the displacement of the first block relative to the start of the dataset */ dev->fbalcblk = fetch_fw(iobuf + 4); /* Verify that the block count is non-zero, and that the starting and ending blocks fall within the extent */ if ( dev->fbalcnum == 0 || dev->fbalcnum > dev->fbaxlast + 1 || dev->fbalcblk < dev->fbaxfirst || dev->fbalcblk > dev->fbaxlast + 1 - dev->fbalcnum) { dev->sense[0] = SENSE_CR; *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* For replicated data, verify that the replication count is non-zero and is a multiple of the block count */ if ((dev->fbaoper & FBAOPER_CODE) == FBAOPER_READREP) { if (repcnt == 0 || repcnt % dev->fbalcnum != 0) { dev->sense[0] = SENSE_CR; *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } } /* Position device to start of block */ dev->fbarba = (dev->fbaorigin + dev->fbaxblkn + dev->fbalcblk - dev->fbaxfirst ) * dev->fbablksiz; logdevtr (dev, _("HHCDA077I Positioning to %8.8" I64_FMT "X (%" I64_FMT "u)\n"), (long long unsigned int)dev->fbarba, (long long unsigned int)dev->fbarba); /* Return normal status */ *unitstat = CSW_CE | CSW_DE; break; case 0x63: /*---------------------------------------------------------------*/ /* DEFINE EXTENT */ /*---------------------------------------------------------------*/ /* Calculate residual byte count */ num = (count < 16) ? count : 16; *residual = count - num; /* Control information length must be at least 16 bytes */ if (count < 16) { logmsg(_("HHCDA078E define extent data too short: %d bytes\n"), count); dev->sense[0] = SENSE_CR; *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Reject if extent previously defined in this CCW chain */ if (dev->fbaxtdef) { logmsg(_("HHCDA079E second define extent in chain\n")); dev->sense[0] = SENSE_CR; *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Save and validate the file mask */ dev->fbamask = iobuf[0]; if ((dev->fbamask & (FBAMASK_RESV | FBAMASK_CE)) || (dev->fbamask & FBAMASK_CTL) == FBAMASK_CTL_RESV) { logmsg(_("HHCDA080E invalid file mask %2.2X\n"), dev->fbamask); dev->sense[0] = SENSE_CR; *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } // VM/ESA sends 0x00000200 0x00000000 0x00000000 0x0001404F // /* Verify that bytes 1-3 are zeroes */ // if (iobuf[1] != 0 || iobuf[2] != 0 || iobuf[3] != 0) // { // logmsg(_("fbadasd: invalid reserved bytes %2.2X %2.2X %2.2X\n"), // iobuf[1], iobuf[2], iobuf[3]); // dev->sense[0] = SENSE_CR; // *unitstat = CSW_CE | CSW_DE | CSW_UC; // break; // } /* Bytes 4-7 contain the block number of the first block of the extent relative to the start of the device */ dev->fbaxblkn = fetch_fw(iobuf + 4); /* Bytes 8-11 contain the block number of the first block of the extent relative to the start of the dataset */ dev->fbaxfirst = fetch_fw(iobuf + 8); /* Bytes 12-15 contain the block number of the last block of the extent relative to the start of the dataset */ dev->fbaxlast = fetch_fw(iobuf + 12); /* Validate the extent description by checking that the ending block is not less than the starting block and that the ending block does not exceed the device size */ if (dev->fbaxlast < dev->fbaxfirst || dev->fbaxblkn > (U32)dev->fbanumblk || dev->fbaxlast - dev->fbaxfirst >= dev->fbanumblk - dev->fbaxblkn) { logmsg(_("HHCDA081E invalid extent: first block %d, last block %d,\n"), dev->fbaxfirst, dev->fbaxlast); logmsg(_(" numblks %d, device size %d\n"), dev->fbaxblkn, dev->fbanumblk); dev->sense[0] = SENSE_CR; *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Set extent defined flag and return normal status */ dev->fbaxtdef = 1; *unitstat = CSW_CE | CSW_DE; break; case 0x64: /*---------------------------------------------------------------*/ /* READ DEVICE CHARACTERISTICS */ /*---------------------------------------------------------------*/ /* Calculate residual byte count */ num = (count < dev->numdevchar) ? count : dev->numdevchar; *residual = count - num; if (count < dev->numdevchar) *more = 1; /* Copy device characteristics bytes to channel buffer */ memcpy (iobuf, dev->devchar, num); *unitstat = CSW_CE | CSW_DE; break; case 0x94: /*---------------------------------------------------------------*/ /* DEVICE RELEASE */ /*---------------------------------------------------------------*/ /* Reject if extent previously defined in this CCW chain */ if (dev->fbaxtdef) { dev->sense[0] = SENSE_CR; *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } if (dev->hnd->release) (dev->hnd->release) (dev); obtain_lock (&dev->lock); dev->reserved = 0; release_lock (&dev->lock); /* Return sense information */ goto sense; case 0xB4: /*---------------------------------------------------------------*/ /* DEVICE RESERVE */ /*---------------------------------------------------------------*/ /* Reject if extent previously defined in this CCW chain */ if (dev->fbaxtdef) { dev->sense[0] = SENSE_CR; *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Reserve device to the ID of the active channel program */ obtain_lock (&dev->lock); dev->reserved = 1; release_lock (&dev->lock); if (dev->hnd->reserve) (dev->hnd->reserve) (dev); /* Return sense information */ goto sense; case 0x14: /*---------------------------------------------------------------*/ /* UNCONDITIONAL RESERVE */ /*---------------------------------------------------------------*/ /* Reject if this is not the first CCW in the chain */ if (ccwseq > 0) { dev->sense[0] = SENSE_CR; *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Reserve device to the ID of the active channel program */ obtain_lock (&dev->lock); dev->reserved = 1; release_lock (&dev->lock); if (dev->hnd->reserve) (dev->hnd->reserve) (dev); /* Return sense information */ goto sense; case 0x04: /*---------------------------------------------------------------*/ /* SENSE */ /*---------------------------------------------------------------*/ sense: /* Calculate residual byte count */ num = (count < dev->numsense) ? count : dev->numsense; *residual = count - num; if (count < dev->numsense) *more = 1; /* Copy device sense bytes to channel I/O buffer */ memcpy (iobuf, dev->sense, num); /* Clear the device sense bytes */ memset (dev->sense, 0, sizeof(dev->sense)); /* Return unit status */ *unitstat = CSW_CE | CSW_DE; break; case 0xE4: /*---------------------------------------------------------------*/ /* SENSE ID */ /*---------------------------------------------------------------*/ /* Calculate residual byte count */ num = (count < dev->numdevid) ? count : dev->numdevid; *residual = count - num; if (count < dev->numdevid) *more = 1; /* Copy device identifier bytes to channel I/O buffer */ memcpy (iobuf, dev->devid, num); /* Return unit status */ *unitstat = CSW_CE | CSW_DE; break; case 0xA4: /*---------------------------------------------------------------*/ /* READ AND RESET BUFFERED LOG */ /*---------------------------------------------------------------*/ /* Calculate residual byte count */ num = (count < 24) ? count : 24; *residual = count - num; if (count < 24) *more = 1; /* Copy device identifier bytes to channel I/O buffer */ memset (iobuf, 0, num); /* Return unit status */ *unitstat = CSW_CE | CSW_DE; break; default: /*---------------------------------------------------------------*/ /* INVALID OPERATION */ /*---------------------------------------------------------------*/ /* Set command reject sense byte, and unit check status */ dev->sense[0] = SENSE_CR; *unitstat = CSW_CE | CSW_DE | CSW_UC; } /* end switch(code) */ } /* end function fbadasd_execute_ccw */ /*-------------------------------------------------------------------*/ /* Read Standard Block (used by Diagnose instructions) */ /*-------------------------------------------------------------------*/ DLL_EXPORT void fbadasd_read_block ( DEVBLK *dev, int blknum, int blksize, int blkfactor, BYTE *iobuf, BYTE *unitstat, U16 *residual ) { int rc; /* Return code */ int sector; /* First sector being read */ /* Unit check if block number is invalid */ sector = blknum * blkfactor; if (sector >= dev->fbanumblk) { dev->sense[0] = SENSE_CR; *unitstat = CSW_CE | CSW_DE | CSW_UC; return; } /* Seek to start of desired block */ dev->fbarba = ( dev->fbaorigin + sector ) * dev->fbablksiz; /* Read block into I/O buffer */ rc = fba_read (dev, iobuf, blksize, unitstat); if (rc < blksize) { dev->sense[0] = SENSE_CR; *unitstat = CSW_CE | CSW_DE | CSW_UC; return; } /* Return unit status and residual byte count */ *unitstat = CSW_CE | CSW_DE; *residual = 0; } /* end function fbadasd_read_block */ /*-------------------------------------------------------------------*/ /* Write Standard Block (used by Diagnose instructions) */ /*-------------------------------------------------------------------*/ DLL_EXPORT void fbadasd_write_block ( DEVBLK *dev, int blknum, int blksize, int blkfactor, BYTE *iobuf, BYTE *unitstat, U16 *residual ) { int rc; /* Return code from write function */ int sector; /* First sector being read */ #if 0 U64 rba; /* Large file size offset */ #endif /* Unit check if block number is invalid */ sector = blknum * blkfactor; if (sector >= dev->fbanumblk || sector < 0 ) { dev->sense[0] = SENSE_CR; *unitstat = CSW_CE | CSW_DE | CSW_UC; return; } /* Seek to start of desired block */ dev->fbarba = (off_t)(( dev->fbaorigin + sector ) * dev->fbablksiz); /* Read block into I/O buffer */ rc = fba_write (dev, iobuf, blksize, unitstat); if (rc < blksize) { dev->sense[0] = SENSE_CR; *unitstat = CSW_CE | CSW_DE | CSW_UC; return; } /* Return unit status and residual byte count */ *unitstat = CSW_CE | CSW_DE; *residual = 0; } /* end function fbadasd_write_block */ /* Deprecated: Will be replaced by fbadasd_read/write_block functions */ /*-------------------------------------------------------------------*/ /* Synchronous Fixed Block I/O (used by Diagnose instruction) */ /*-------------------------------------------------------------------*/ DLL_EXPORT void fbadasd_syncblk_io ( DEVBLK *dev, BYTE type, int blknum, int blksize, BYTE *iobuf, BYTE *unitstat, U16 *residual ) { int rc; /* Return code */ int blkfactor; /* Number of device blocks per logical block */ /* Calculate the blocking factor */ blkfactor = blksize / dev->fbablksiz; /* Unit check if block number is invalid */ if (blknum * blkfactor >= dev->fbanumblk) { dev->sense[0] = SENSE_CR; *unitstat = CSW_CE | CSW_DE | CSW_UC; return; } /* Seek to start of desired block */ dev->fbarba = dev->fbaorigin * dev->fbablksiz; /* Process depending on operation type */ switch (type) { case 0x01: /* Write block from I/O buffer */ rc = fba_write (dev, iobuf, blksize, unitstat); if (rc < blksize) return; break; case 0x02: /* Read block into I/O buffer */ rc = fba_read (dev, iobuf, blksize, unitstat); if (rc < blksize) return; break; } /* end switch(type) */ /* Return unit status and residual byte count */ *unitstat = CSW_CE | CSW_DE; *residual = 0; } /* end function fbadasd_syncblk_io */ /*-------------------------------------------------------------------*/ /* Hercules suspend/resume text unit key values */ /*-------------------------------------------------------------------*/ #define SR_DEV_FBA_BUFCUR ( SR_DEV_FBA | 0x001 ) #define SR_DEV_FBA_BUFOFF ( SR_DEV_FBA | 0x002 ) #define SR_DEV_FBA_ORIGIN ( SR_DEV_FBA | 0x003 ) #define SR_DEV_FBA_NUMBLK ( SR_DEV_FBA | 0x004 ) #define SR_DEV_FBA_RBA ( SR_DEV_FBA | 0x005 ) #define SR_DEV_FBA_END ( SR_DEV_FBA | 0x006 ) #define SR_DEV_FBA_DXBLKN ( SR_DEV_FBA | 0x007 ) #define SR_DEV_FBA_DXFIRST ( SR_DEV_FBA | 0x008 ) #define SR_DEV_FBA_DXLAST ( SR_DEV_FBA | 0x009 ) #define SR_DEV_FBA_LCBLK ( SR_DEV_FBA | 0x00a ) #define SR_DEV_FBA_LCNUM ( SR_DEV_FBA | 0x00b ) #define SR_DEV_FBA_BLKSIZ ( SR_DEV_FBA | 0x00c ) #define SR_DEV_FBA_XTDEF ( SR_DEV_FBA | 0x00d ) #define SR_DEV_FBA_OPER ( SR_DEV_FBA | 0x00e ) #define SR_DEV_FBA_MASK ( SR_DEV_FBA | 0x00f ) /*-------------------------------------------------------------------*/ /* Hercules suspend */ /*-------------------------------------------------------------------*/ int fbadasd_hsuspend(DEVBLK *dev, void *file) { if (dev->bufcur >= 0) { SR_WRITE_VALUE(file, SR_DEV_FBA_BUFCUR, dev->bufcur, sizeof(dev->bufcur)); SR_WRITE_VALUE(file, SR_DEV_FBA_BUFOFF, dev->bufoff, sizeof(dev->bufoff)); } SR_WRITE_VALUE(file, SR_DEV_FBA_ORIGIN, dev->fbaorigin, sizeof(dev->fbaorigin)); SR_WRITE_VALUE(file, SR_DEV_FBA_NUMBLK, dev->fbanumblk, sizeof(dev->fbanumblk)); SR_WRITE_VALUE(file, SR_DEV_FBA_RBA, dev->fbarba, sizeof(dev->fbarba)); SR_WRITE_VALUE(file, SR_DEV_FBA_END, dev->fbaend, sizeof(dev->fbaend)); SR_WRITE_VALUE(file, SR_DEV_FBA_DXBLKN, dev->fbaxblkn, sizeof(dev->fbaxblkn)); SR_WRITE_VALUE(file, SR_DEV_FBA_DXFIRST, dev->fbaxfirst, sizeof(dev->fbaxfirst)); SR_WRITE_VALUE(file, SR_DEV_FBA_DXLAST, dev->fbaxlast, sizeof(dev->fbaxlast)); SR_WRITE_VALUE(file, SR_DEV_FBA_LCBLK, dev->fbalcblk, sizeof(dev->fbalcblk)); SR_WRITE_VALUE(file, SR_DEV_FBA_LCNUM, dev->fbalcnum, sizeof(dev->fbalcnum)); SR_WRITE_VALUE(file, SR_DEV_FBA_BLKSIZ, dev->fbablksiz, sizeof(dev->fbablksiz)); SR_WRITE_VALUE(file, SR_DEV_FBA_XTDEF, dev->fbaxtdef, 1); SR_WRITE_VALUE(file, SR_DEV_FBA_OPER, dev->fbaoper, sizeof(dev->fbaoper)); SR_WRITE_VALUE(file, SR_DEV_FBA_MASK, dev->fbamask, sizeof(dev->fbamask)); return 0; } /*-------------------------------------------------------------------*/ /* Hercules resume */ /*-------------------------------------------------------------------*/ int fbadasd_hresume(DEVBLK *dev, void *file) { int rc; size_t key, len; BYTE byte; do { SR_READ_HDR(file, key, len); switch (key) { case SR_DEV_FBA_BUFCUR: SR_READ_VALUE(file, len, &rc, sizeof(rc)); rc = (dev->hnd->read) ? (dev->hnd->read)(dev, rc, &byte) : -1; if ((int)rc < 0) return -1; break; case SR_DEV_FBA_BUFOFF: SR_READ_VALUE(file, len, &dev->bufoff, sizeof(dev->bufoff)); break; case SR_DEV_FBA_ORIGIN: SR_READ_VALUE(file, len, &rc, sizeof(rc)); if ((off_t)rc != dev->fbaorigin) { logmsg(_("HHCDA901E %4.4x FBA origin mismatch: %d, expected %d,\n"), rc, dev->fbaorigin); return -1; } break; case SR_DEV_FBA_NUMBLK: SR_READ_VALUE(file, len, &rc, sizeof(rc)); if ((int)rc != dev->fbanumblk) { logmsg(_("HHCDA902E %4.4x FBA numblk mismatch: %d, expected %d,\n"), rc, dev->fbanumblk); return -1; } break; case SR_DEV_FBA_RBA: SR_READ_VALUE(file, len, &dev->fbarba, sizeof(dev->fbarba)); break; case SR_DEV_FBA_END: SR_READ_VALUE(file, len, &dev->fbaend, sizeof(dev->fbaend)); break; case SR_DEV_FBA_DXBLKN: SR_READ_VALUE(file, len, &dev->fbaxblkn, sizeof(dev->fbaxblkn)); break; case SR_DEV_FBA_DXFIRST: SR_READ_VALUE(file, len, &dev->fbaxfirst, sizeof(dev->fbaxfirst)); break; case SR_DEV_FBA_DXLAST: SR_READ_VALUE(file, len, &dev->fbaxlast, sizeof(dev->fbaxlast)); break; case SR_DEV_FBA_LCBLK: SR_READ_VALUE(file, len, &dev->fbalcblk, sizeof(dev->fbalcblk)); break; case SR_DEV_FBA_LCNUM: SR_READ_VALUE(file, len, &dev->fbalcnum, sizeof(dev->fbalcnum)); break; case SR_DEV_FBA_BLKSIZ: SR_READ_VALUE(file, len, &rc, sizeof(rc)); if ((int)rc != dev->fbablksiz) { logmsg(_("HHCDA903E %4.4x FBA blksiz mismatch: %d, expected %d,\n"), rc, dev->fbablksiz); return -1; } break; case SR_DEV_FBA_XTDEF: SR_READ_VALUE(file, len, &rc, sizeof(rc)); dev->fbaxtdef = rc; break; case SR_DEV_FBA_OPER: SR_READ_VALUE(file, len, &dev->fbaoper, sizeof(dev->fbaoper)); break; case SR_DEV_FBA_MASK: SR_READ_VALUE(file, len, &dev->fbamask, sizeof(dev->fbamask)); break; default: SR_READ_SKIP(file, len); break; } /* switch (key) */ } while ((key & SR_DEV_MASK) == SR_DEV_FBA); return 0; } DLL_EXPORT DEVHND fbadasd_device_hndinfo = { &fbadasd_init_handler, /* Device Initialisation */ &fbadasd_execute_ccw, /* Device CCW execute */ &fbadasd_close_device, /* Device Close */ &fbadasd_query_device, /* Device Query */ NULL, /* Device Start channel pgm */ &fbadasd_end, /* Device End channel pgm */ NULL, /* Device Resume channel pgm */ &fbadasd_end, /* Device Suspend channel pgm */ &fbadasd_read_blkgrp, /* Device Read */ &fbadasd_update_blkgrp, /* Device Write */ &fbadasd_used, /* Device Query used */ NULL, /* Device Reserve */ NULL, /* Device Release */ NULL, /* Device Attention */ NULL, /* Immediate CCW Codes */ NULL, /* Signal Adapter Input */ NULL, /* Signal Adapter Ouput */ &fbadasd_hsuspend, /* Hercules suspend */ &fbadasd_hresume /* Hercules resume */ }; hercules-3.07/feat370.h000644 000765 000765 00000005074 11321734033 016270 0ustar00jmaynardjmaynard000000 000000 /* FEAT370.H (c) Copyright Jan Jaeger, 2000-2009 */ /* S/370 feature definitions */ // $Id: feat370.h 5569 2009-12-27 14:01:09Z hsg001 $ /*-------------------------------------------------------------------*/ /* This file defines the architectural features which are included */ /* at compilation time for S/370 mode */ /*-------------------------------------------------------------------*/ #if defined(OPTION_370_MODE) #define _ARCH_370_NAME "S/370" /* This file MUST NOT contain #undef statements */ #define FEATURE_2K_STORAGE_KEYS #define FEATURE_BASIC_STORAGE_KEYS #define FEATURE_EXTENDED_STORAGE_KEYS #define FEATURE_BCMODE #define FEATURE_DUAL_ADDRESS_SPACE #define FEATURE_EMULATE_VM #define FEATURE_HERCULES_DIAGCALLS #define FEATURE_HEXADECIMAL_FLOATING_POINT #define FEATURE_PER #define FEATURE_INTERVAL_TIMER #define FEATURE_SEGMENT_PROTECTION #define FEATURE_S370_CHANNEL #define FEATURE_CHANNEL_SWITCHING #define FEATURE_S370E_EXTENDED_ADDRESSING #define FEATURE_TEST_BLOCK #define FEATURE_ECPSVM #define FEATURE_VM_BLOCKIO /* The following ESA/390 features can be retrofitted to S/370 and may be activated if desired by uncommenting the appropriate define statements below and performing a complete rebuild */ //#define FEATURE_BASIC_FP_EXTENSIONS //#define FEATURE_BINARY_FLOATING_POINT //#define FEATURE_CHECKSUM_INSTRUCTION //#define FEATURE_COMPARE_AND_MOVE_EXTENDED //#define FEATURE_COMPRESSION //#define FEATURE_EXTENDED_TRANSLATION //#define FEATURE_EXTENDED_TRANSLATION_FACILITY_2 //#define FEATURE_HFP_EXTENSIONS //#define FEATURE_HFP_MULTIPLY_ADD_SUBTRACT //#define FEATURE_HFP_UNNORMALIZED_EXTENSION //#define FEATURE_IMMEDIATE_AND_RELATIVE //#define FEATURE_SQUARE_ROOT //#define FEATURE_STRING_INSTRUCTION /* The following ESAME features can be retrofitted to S/370 and may be activated if desired by uncommenting the appropriate define statements below and performing a complete rebuild */ //#define FEATURE_ESAME_N3_ESA390 //#define FEATURE_ETF2_ENHANCEMENT //#define FEATURE_ETF3_ENHANCEMENT //#define FEATURE_EXECUTE_EXTENSIONS_FACILITY //#define FEATURE_EXTENDED_IMMEDIATE //#define FEATURE_EXTENDED_TRANSLATION_FACILITY_3 //#define FEATURE_GENERAL_INSTRUCTIONS_EXTENSION_FACILITY //#define FEATURE_LONG_DISPLACEMENT //#define FEATURE_MESSAGE_SECURITY_ASSIST //#define FEATURE_MESSAGE_SECURITY_ASSIST_EXTENSION_1 //#define FEATURE_MESSAGE_SECURITY_ASSIST_EXTENSION_2 //#define FEATURE_PARSING_ENHANCEMENT_FACILITY #endif /*defined(OPTION_370_MODE)*/ /* end of FEAT370.H */ hercules-3.07/feat390.h000644 000765 000765 00000007060 11301535255 016272 0ustar00jmaynardjmaynard000000 000000 /* FEAT390.H (c) Copyright Jan Jaeger, 2000-2009 */ /* ESA/390 feature definitions */ // $Id: feat390.h 5454 2009-08-14 14:25:06Z rbowler $ /*-------------------------------------------------------------------*/ /* This file defines the architectural features which are included */ /* at compilation time for ESA/390 mode */ /*-------------------------------------------------------------------*/ /* This file MUST NOT contain #undef statements */ #if defined(OPTION_390_MODE) #define _ARCH_390_NAME "ESA/390" #define FEATURE_4K_STORAGE_KEYS #define FEATURE_ACCESS_REGISTERS #define FEATURE_ADDRESS_LIMIT_CHECKING #define FEATURE_BASIC_FP_EXTENSIONS #define FEATURE_BIMODAL_ADDRESSING #define FEATURE_BINARY_FLOATING_POINT #define FEATURE_BRANCH_AND_SET_AUTHORITY #define FEATURE_BROADCASTED_PURGING #define FEATURE_CANCEL_IO_FACILITY #define FEATURE_CALLED_SPACE_IDENTIFICATION #define FEATURE_CHANNEL_SUBSYSTEM #define FEATURE_CHECKSUM_INSTRUCTION #define FEATURE_CHSC #define FEATURE_COMPARE_AND_MOVE_EXTENDED #define FEATURE_COMPRESSION #define FEATURE_CPU_RECONFIG #define FEATURE_DUAL_ADDRESS_SPACE #define FEATURE_EMULATE_VM #define FEATURE_ETF2_ENHANCEMENT /*@ZA*/ #define FEATURE_ETF3_ENHANCEMENT /*@ZA*/ #define FEATURE_EXPANDED_STORAGE #define FEATURE_EXPEDITED_SIE_SUBSET #define FEATURE_EXTENDED_STORAGE_KEYS #define FEATURE_EXTENDED_TOD_CLOCK #define FEATURE_EXTENDED_TRANSLATION #define FEATURE_EXTENDED_TRANSLATION_FACILITY_2 #define FEATURE_EXTENDED_TRANSLATION_FACILITY_3 /*@ZA*/ #define FEATURE_EXTERNAL_INTERRUPT_ASSIST #define FEATURE_FAST_SYNC_DATA_MOVER #define FEATURE_FETCH_PROTECTION_OVERRIDE #define FEATURE_FPS_ENHANCEMENT /*DFP*/ #define FEATURE_FPS_EXTENSIONS #define FEATURE_HERCULES_DIAGCALLS #define FEATURE_HEXADECIMAL_FLOATING_POINT #define FEATURE_HFP_EXTENSIONS #define FEATURE_HFP_MULTIPLY_ADD_SUBTRACT #define FEATURE_HYPERVISOR #define FEATURE_IMMEDIATE_AND_RELATIVE #define FEATURE_INCORRECT_LENGTH_INDICATION_SUPPRESSION #define FEATURE_INTEGRATED_3270_CONSOLE //#define FEATURE_INTEGRATED_ASCII_CONSOLE #define FEATURE_INTERPRETIVE_EXECUTION #define FEATURE_IO_ASSIST #define FEATURE_LOCK_PAGE #define FEATURE_LINKAGE_STACK #define FEATURE_MESSAGE_SECURITY_ASSIST #define FEATURE_MESSAGE_SECURITY_ASSIST_EXTENSION_1 #define FEATURE_MESSAGE_SECURITY_ASSIST_EXTENSION_2 #define FEATURE_MOVE_PAGE_FACILITY_2 #define FEATURE_MPF_INFO #define FEATURE_MSSF_CALL #define FEATURE_MULTIPLE_CONTROLLED_DATA_SPACE #define FEATURE_MVS_ASSIST #define FEATURE_PAGE_PROTECTION #define FEATURE_PERFORM_LOCKED_OPERATION #define FEATURE_PER #define FEATURE_PER2 #define FEATURE_PRIVATE_SPACE #define FEATURE_PROTECTION_INTERCEPTION_CONTROL #define FEATURE_QUEUED_DIRECT_IO #define FEATURE_REGION_RELOCATE #define FEATURE_RESUME_PROGRAM #define FEATURE_S390_DAT #define FEATURE_SCEDIO #define FEATURE_SERVICE_PROCESSOR #define FEATURE_SET_ADDRESS_SPACE_CONTROL_FAST #define FEATURE_SQUARE_ROOT #define FEATURE_STORAGE_KEY_ASSIST #define FEATURE_STORAGE_PROTECTION_OVERRIDE #define FEATURE_STORE_SYSTEM_INFORMATION #define FEATURE_STRING_INSTRUCTION #define FEATURE_SUBSPACE_GROUP #define FEATURE_SUPPRESSION_ON_PROTECTION #define FEATURE_SYSTEM_CONSOLE #define FEATURE_TEST_BLOCK #define FEATURE_TRACING #define FEATURE_WAITSTATE_ASSIST #define FEATURE_STORE_FACILITY_LIST_EXTENDED #define FEATURE_VM_BLOCKIO // #define FEATURE_VECTOR_FACILITY #endif /*defined(OPTION_390_MODE)*/ /* end of FEAT390.H */ hercules-3.07/feat900.h000644 000765 000765 00000012527 11321734033 016270 0ustar00jmaynardjmaynard000000 000000 /* FEAT900.H (c) Copyright Jan Jaeger, 2000-2009 */ /* ESAME feature definitions */ // $Id: feat900.h 5569 2009-12-27 14:01:09Z hsg001 $ /*-------------------------------------------------------------------*/ /* This file defines the architectural features which are included */ /* at compilation time for ESAME (z/Architecture) mode */ /*-------------------------------------------------------------------*/ #if defined(OPTION_900_MODE) #define _ARCH_900_NAME "z/Arch" /* also: "ESAME" */ /* This file MUST NOT contain #undef statements */ #define FEATURE_4K_STORAGE_KEYS #define FEATURE_ACCESS_REGISTERS #define FEATURE_ADDRESS_LIMIT_CHECKING #define FEATURE_ASN_AND_LX_REUSE #define FEATURE_BASIC_FP_EXTENSIONS #define FEATURE_BIMODAL_ADDRESSING #define FEATURE_BINARY_FLOATING_POINT #define FEATURE_BRANCH_AND_SET_AUTHORITY #define FEATURE_BROADCASTED_PURGING #define FEATURE_CANCEL_IO_FACILITY #define FEATURE_CALLED_SPACE_IDENTIFICATION #define FEATURE_CHANNEL_SUBSYSTEM #define FEATURE_CHECKSUM_INSTRUCTION #define FEATURE_CHSC #define FEATURE_COMPARE_AND_MOVE_EXTENDED #define FEATURE_COMPARE_AND_SWAP_AND_STORE /*407*/ #define FEATURE_COMPARE_AND_SWAP_AND_STORE_FACILITY_2 /*ISW*/ #define FEATURE_COMPRESSION #define FEATURE_CONDITIONAL_SSKE /*407*/ #define FEATURE_CONFIGURATION_TOPOLOGY_FACILITY /*208*/ //#define FEATURE_CPU_MEASUREMENT_COUNTER_FACILITY //#define FEATURE_CPU_MEASUREMENT_SAMPLING_FACILITY #define FEATURE_CPU_RECONFIG #define FEATURE_DAT_ENHANCEMENT #define FEATURE_DAT_ENHANCEMENT_FACILITY_2 /*@Z9*/ #define FEATURE_DECIMAL_FLOATING_POINT /*DFP*/ #define FEATURE_DUAL_ADDRESS_SPACE #define FEATURE_EMULATE_VM //#define FEATURE_ENHANCED_DAT_FACILITY /*208*/ #define FEATURE_ESAME #define FEATURE_ETF2_ENHANCEMENT /*@Z9*/ #define FEATURE_ETF3_ENHANCEMENT /*@Z9*/ #define FEATURE_EXECUTE_EXTENSIONS_FACILITY /*208*/ #define FEATURE_EXPANDED_STORAGE #define FEATURE_EXPEDITED_SIE_SUBSET #define FEATURE_EXTENDED_DIAG204 #define FEATURE_EXTENDED_IMMEDIATE /*@Z9*/ #define FEATURE_EXTENDED_STORAGE_KEYS #define FEATURE_EXTENDED_TOD_CLOCK #define FEATURE_EXTENDED_TRANSLATION #define FEATURE_EXTENDED_TRANSLATION_FACILITY_2 #define FEATURE_EXTENDED_TRANSLATION_FACILITY_3 #define FEATURE_EXTERNAL_INTERRUPT_ASSIST #define FEATURE_EXTRACT_CPU_TIME /*407*/ #define FEATURE_FETCH_PROTECTION_OVERRIDE #define FEATURE_FPS_ENHANCEMENT /*DFP*/ #define FEATURE_FPS_EXTENSIONS #define FEATURE_GENERAL_INSTRUCTIONS_EXTENSION_FACILITY /*208*/ #define FEATURE_HERCULES_DIAGCALLS #define FEATURE_HEXADECIMAL_FLOATING_POINT #define FEATURE_HFP_EXTENSIONS #define FEATURE_HFP_MULTIPLY_ADD_SUBTRACT #define FEATURE_HFP_UNNORMALIZED_EXTENSION /*@Z9*/ #define FEATURE_HYPERVISOR #define FEATURE_IEEE_EXCEPTION_SIMULATION /*407*/ #define FEATURE_IMMEDIATE_AND_RELATIVE #define FEATURE_INCORRECT_LENGTH_INDICATION_SUPPRESSION #define FEATURE_INTEGRATED_3270_CONSOLE //#define FEATURE_INTEGRATED_ASCII_CONSOLE #define FEATURE_INTERPRETIVE_EXECUTION #define FEATURE_IO_ASSIST #define FEATURE_LINKAGE_STACK #define FEATURE_LOAD_REVERSED #define FEATURE_LOCK_PAGE #define FEATURE_LONG_DISPLACEMENT #define FEATURE_MESSAGE_SECURITY_ASSIST #define FEATURE_MESSAGE_SECURITY_ASSIST_EXTENSION_1 /*@Z9*/ #define FEATURE_MESSAGE_SECURITY_ASSIST_EXTENSION_2 #define FEATURE_MIDAW /*@Z9*/ #define FEATURE_MOVE_PAGE_FACILITY_2 #define FEATURE_MOVE_WITH_OPTIONAL_SPECIFICATIONS /*208*/ #define FEATURE_MPF_INFO #define FEATURE_MVS_ASSIST #define FEATURE_PAGE_PROTECTION #define FEATURE_PARSING_ENHANCEMENT_FACILITY /*208*/ #define FEATURE_PERFORM_LOCKED_OPERATION #define FEATURE_PER #define FEATURE_PER2 #define FEATURE_PER3 /*@Z9*/ //#define FEATURE_PFPO /*407*/ #define FEATURE_PRIVATE_SPACE //#define FEATURE_PROGRAM_DIRECTED_REIPL /*DIAG308 incomplete*/ /*@Z9*/ #define FEATURE_PROTECTION_INTERCEPTION_CONTROL #define FEATURE_QUEUED_DIRECT_IO //#define FEATURE_RESTORE_SUBCHANNEL_FACILITY /*208*/ #define FEATURE_RESUME_PROGRAM #define FEATURE_REGION_RELOCATE #define FEATURE_SCEDIO #define FEATURE_SENSE_RUNNING_STATUS /*@Z9*/ #define FEATURE_SERVICE_PROCESSOR #define FEATURE_SET_ADDRESS_SPACE_CONTROL_FAST //#define FEATURE_SET_PROGRAM_PARAMETER_FACILITY #define FEATURE_SQUARE_ROOT #define FEATURE_STORAGE_KEY_ASSIST #define FEATURE_STORAGE_PROTECTION_OVERRIDE #define FEATURE_STORE_CLOCK_FAST #define FEATURE_STORE_FACILITY_LIST_EXTENDED /*@Z9*/ #define FEATURE_STORE_SYSTEM_INFORMATION #define FEATURE_STRING_INSTRUCTION #define FEATURE_SUBSPACE_GROUP #define FEATURE_SUPPRESSION_ON_PROTECTION #define FEATURE_SYSTEM_CONSOLE #define FEATURE_TEST_BLOCK #define FEATURE_TOD_CLOCK_STEERING /*@Z9*/ #define FEATURE_TRACING #define FEATURE_WAITSTATE_ASSIST #define FEATURE_VM_BLOCKIO #endif /*defined(OPTION_900_MODE)*/ /* end of FEAT900.H */ hercules-3.07/featall.h000644 000765 000765 00000024267 11301535255 016537 0ustar00jmaynardjmaynard000000 000000 /* FEATALL.H (c) Copyright Jan Jaeger, 2000-2009 */ /* Architecture-dependent macro definitions */ // $Id: featall.h 5454 2009-08-14 14:25:06Z rbowler $ /*-------------------------------------------------------------------*/ /* Default features */ /* All existing features MUST be #undef-ed here. */ /*-------------------------------------------------------------------*/ #define OPTION_370_MODE /* Generate S/370 support */ #define OPTION_390_MODE /* Generate ESA/390 support */ #define OPTION_900_MODE /* Generate ESAME support */ #define OPTION_LPP_RESTRICT /* Disable Licensed Software */ #define OPTION_SMP /* Enable SMP support */ #define VECTOR_SECTION_SIZE 128 /* Vector section size */ #define VECTOR_PARTIAL_SUM_NUMBER 1 /* Vector partial sum number */ #define CKD_MAXFILES 4 /* Max files per CKD volume */ #define OPTION_MIPS_COUNTING /* Display MIPS on ctl panel */ #define PANEL_REFRESH_RATE /* Enable panrate feature */ #define PANEL_REFRESH_RATE_FAST 50 /* Fast refresh rate */ #define PANEL_REFRESH_RATE_SLOW 500 /* Slow refresh rate */ #define DEFAULT_TIMER_REFRESH_USECS 50 /* Default timer refresh int */ #define MAX_DEVICE_THREAD_IDLE_SECS 300 /* 5 Minute thread timeout */ #undef OPTION_NO_INLINE_DAT /* Performance option */ #undef OPTION_NO_INLINE_LOGICAL /* Performance option */ #undef OPTION_NO_INLINE_VSTORE /* Performance option */ #undef OPTION_NO_INLINE_IFETCH /* Performance option */ #define OPTION_MULTI_BYTE_ASSIST /* Performance option */ #define OPTION_SINGLE_CPU_DW /* Performance option (ia32) */ #define OPTION_FAST_DEVLOOKUP /* Fast devnum/subchan lookup*/ #define OPTION_IODELAY_KLUDGE /* IODELAY kludge for linux */ #undef OPTION_FOOTPRINT_BUFFER /* 2048 ** Size must be a power of 2 */ #undef OPTION_INSTRUCTION_COUNTING /* First use trace and count */ #define OPTION_CKD_KEY_TRACING /* Trace CKD search keys */ #undef OPTION_CMPSC_DEBUGLVL /* 3 ** 1=Exp 2=Comp 3=Both debug */ #undef MODEL_DEPENDENT_STCM /* STCM, STCMH always store */ #define OPTION_NOP_MODEL158_DIAGNOSE /* NOP mod 158 specific diags*/ #define FEATURE_ALD_FORMAT 0 /* Use fmt0 Access-lists */ #define FEATURE_SIE_MAXZONES 8 /* Maximum SIE Zones */ #define FEATURE_LCSS_MAX 4 /* Number of supported lcss's*/ // #define SIE_DEBUG_PERFMON /* SIE performance monitor */ #define OPTION_LPARNAME /* DIAG 204 lparname */ #define OPTION_HTTP_SERVER /* HTTP server support */ #define OPTION_WAKEUP_SELECT_VIA_PIPE /* Use communication pipes to interrupt selects instead of inter-thread signaling */ #define OPTION_TIMESTAMP_LOGFILE /* Hardcopy logfile HH:MM:SS */ #define OPTION_IPLPARM /* IPL PARM a la VM */ #ifndef FISH_HANG #define OPTION_PTTRACE /* Pthreads tracing */ #endif //#define OPTION_DEBUG_MESSAGES /* Prefix msgs with filename // and line# if DEBUG build */ #define OPTION_SET_STSI_INFO /* Set STSI info in cfg file */ #define OPTION_TAPE_AUTOMOUNT /* "Automount" CCWs support */ #define OPTION_CMDTGT /* the cmdtgt command */ #define OPTION_MSGCLR /* Colored messages */ #define OPTION_MSGHLD /* Sticky messages */ #if defined(OPTION_MSGHLD) && !defined(OPTION_MSGCLR) #error OPTION_MSGHLD requires OPTION_MSGCLR #endif // defined(OPTION_MSGHLD) && !defined(OPTION_MSGCLR) /*********************************************************************\ ********************************************************************* ** ** ** *** NOTE! *** ** ** ** ** All HOST-operating-system-specific FEATUREs and OPTIONs ** ** should be #defined in the below header (and ONLY in the ** ** below header!) Please read the comments there! ** ** ** ********************************************************************* \*********************************************************************/ #include "hostopts.h" // (HOST-specific options/feature settings) // (allow for compiler command-line overrides...) #if defined(OPTION_370_MODE) && defined(NO_370_MODE) #undef OPTION_370_MODE #endif #if defined(OPTION_390_MODE) && defined(NO_390_MODE) #undef OPTION_390_MODE #endif #if defined(OPTION_900_MODE) && defined(NO_900_MODE) #undef OPTION_900_MODE #endif #undef FEATURE_4K_STORAGE_KEYS #undef FEATURE_2K_STORAGE_KEYS #undef FEATURE_ACCESS_REGISTERS #undef FEATURE_ADDRESS_LIMIT_CHECKING #undef FEATURE_ASN_AND_LX_REUSE #undef FEATURE_BASIC_FP_EXTENSIONS #undef FEATURE_BASIC_STORAGE_KEYS #undef FEATURE_BCMODE #undef FEATURE_BIMODAL_ADDRESSING #undef FEATURE_BINARY_FLOATING_POINT #undef FEATURE_BRANCH_AND_SET_AUTHORITY #undef FEATURE_BROADCASTED_PURGING #undef FEATURE_CALLED_SPACE_IDENTIFICATION #undef FEATURE_CANCEL_IO_FACILITY #undef FEATURE_CHANNEL_SUBSYSTEM #undef FEATURE_CHANNEL_SWITCHING #undef FEATURE_CHECKSUM_INSTRUCTION #undef FEATURE_CHSC #undef FEATURE_COMPARE_AND_MOVE_EXTENDED #undef FEATURE_COMPARE_AND_SWAP_AND_STORE /*407*/ #undef FEATURE_COMPARE_AND_SWAP_AND_STORE_FACILITY_2 /*208*/ #undef FEATURE_COMPRESSION #undef FEATURE_CONDITIONAL_SSKE /*407*/ #undef FEATURE_CONFIGURATION_TOPOLOGY_FACILITY /*208*/ #undef FEATURE_CPU_MEASUREMENT_COUNTER_FACILITY #undef FEATURE_CPU_MEASUREMENT_SAMPLING_FACILITY #undef FEATURE_CPU_RECONFIG #undef FEATURE_DAT_ENHANCEMENT #undef FEATURE_DAT_ENHANCEMENT_FACILITY_2 /*@Z9*/ #undef FEATURE_DECIMAL_FLOATING_POINT /*DFP*/ #undef FEATURE_DUAL_ADDRESS_SPACE #undef FEATURE_ECPSVM #undef FEATURE_EMULATE_VM #undef FEATURE_ENHANCED_DAT_FACILITY /*208*/ #undef FEATURE_ESAME #undef FEATURE_ESAME_N3_ESA390 #undef FEATURE_ETF2_ENHANCEMENT /*@Z9*/ #undef FEATURE_ETF3_ENHANCEMENT /*@Z9*/ #undef FEATURE_EXECUTE_EXTENSIONS_FACILITY /*208*/ #undef FEATURE_EXPANDED_STORAGE #undef FEATURE_EXPEDITED_SIE_SUBSET #undef FEATURE_EXTENDED_DIAG204 #undef FEATURE_EXTENDED_IMMEDIATE /*@Z9*/ #undef FEATURE_EXTENDED_STORAGE_KEYS #undef FEATURE_EXTENDED_TOD_CLOCK #undef FEATURE_EXTENDED_TRANSLATION #undef FEATURE_EXTENDED_TRANSLATION_FACILITY_2 #undef FEATURE_EXTENDED_TRANSLATION_FACILITY_3 #undef FEATURE_EXTERNAL_INTERRUPT_ASSIST #undef FEATURE_EXTRACT_CPU_TIME /*407*/ #undef FEATURE_FAST_SYNC_DATA_MOVER #undef FEATURE_FETCH_PROTECTION_OVERRIDE #undef FEATURE_FPS_ENHANCEMENT /*DFP*/ #undef FEATURE_FPS_EXTENSIONS #undef FEATURE_GENERAL_INSTRUCTIONS_EXTENSION_FACILITY #undef FEATURE_HERCULES_DIAGCALLS #undef FEATURE_HEXADECIMAL_FLOATING_POINT #undef FEATURE_HFP_EXTENSIONS #undef FEATURE_HFP_MULTIPLY_ADD_SUBTRACT #undef FEATURE_HFP_UNNORMALIZED_EXTENSION /*@Z9*/ #undef FEATURE_HYPERVISOR #undef FEATURE_IEEE_EXCEPTION_SIMULATION /*407*/ #undef FEATURE_IMMEDIATE_AND_RELATIVE #undef FEATURE_INCORRECT_LENGTH_INDICATION_SUPPRESSION #undef FEATURE_INTEGRATED_3270_CONSOLE #undef FEATURE_INTEGRATED_ASCII_CONSOLE #undef FEATURE_INTERPRETIVE_EXECUTION #undef FEATURE_INTERVAL_TIMER #undef FEATURE_IO_ASSIST #undef FEATURE_LINKAGE_STACK #undef FEATURE_LOAD_REVERSED #undef FEATURE_LOCK_PAGE #undef FEATURE_LONG_DISPLACEMENT #undef FEATURE_MESSAGE_SECURITY_ASSIST #undef FEATURE_MESSAGE_SECURITY_ASSIST_EXTENSION_1 /*@Z9*/ #undef FEATURE_MESSAGE_SECURITY_ASSIST_EXTENSION_2 #undef FEATURE_MIDAW /*@Z9*/ #undef FEATURE_MOVE_PAGE_FACILITY_2 #undef FEATURE_MOVE_WITH_OPTIONAL_SPECIFICATIONS /*208*/ #undef FEATURE_MPF_INFO #undef FEATURE_MSSF_CALL #undef FEATURE_MULTIPLE_CONTROLLED_DATA_SPACE #undef FEATURE_MVS_ASSIST #undef FEATURE_PAGE_PROTECTION #undef FEATURE_PARSING_ENHANCEMENT_FACILITY /*208*/ #undef FEATURE_PERFORM_LOCKED_OPERATION #undef FEATURE_PER #undef FEATURE_PER2 #undef FEATURE_PER3 /*@Z9*/ #undef FEATURE_PFPO /*407*/ #undef FEATURE_PRIVATE_SPACE #undef FEATURE_PROGRAM_DIRECTED_REIPL /*@Z9*/ #undef FEATURE_PROTECTION_INTERCEPTION_CONTROL #undef FEATURE_QUEUED_DIRECT_IO #undef FEATURE_REGION_RELOCATE #undef FEATURE_RESTORE_SUBCHANNEL_FACILITY /*208*/ #undef FEATURE_RESUME_PROGRAM #undef FEATURE_SCEDIO #undef FEATURE_S370_CHANNEL #undef FEATURE_S390_DAT #undef FEATURE_S370E_EXTENDED_ADDRESSING #undef FEATURE_SEGMENT_PROTECTION #undef FEATURE_SENSE_RUNNING_STATUS /*@Z9*/ #undef FEATURE_SERVICE_PROCESSOR #undef FEATURE_SET_ADDRESS_SPACE_CONTROL_FAST #undef FEATURE_SET_PROGRAM_PARAMETER_FACILITY #undef FEATURE_SQUARE_ROOT #undef FEATURE_STORAGE_KEY_ASSIST #undef FEATURE_STORAGE_PROTECTION_OVERRIDE #undef FEATURE_STORE_CLOCK_FAST /*@Z9*/ #undef FEATURE_STORE_FACILITY_LIST_EXTENDED /*@Z9*/ #undef FEATURE_STORE_SYSTEM_INFORMATION #undef FEATURE_STRING_INSTRUCTION #undef FEATURE_SUBSPACE_GROUP #undef FEATURE_SUPPRESSION_ON_PROTECTION #undef FEATURE_SYSTEM_CONSOLE #undef FEATURE_TEST_BLOCK #undef FEATURE_TOD_CLOCK_STEERING /*@Z9*/ #undef FEATURE_TRACING #undef FEATURE_VECTOR_FACILITY #undef FEATURE_VM_BLOCKIO #undef FEATURE_WAITSTATE_ASSIST /* end of FEATALL.H */ hercules-3.07/featchk.h000644 000765 000765 00000025445 11301535254 016532 0ustar00jmaynardjmaynard000000 000000 /* FEATCHK.H (c) Copyright Jan Jaeger, 2000-2009 */ /* Feature definition consistency checks */ // $Id: featchk.h 5454 2009-08-14 14:25:06Z rbowler $ /*-------------------------------------------------------------------*/ /* Perform various checks on feature combinations, and set */ /* additional flags to percolate certain features such as */ /* SIE down to lower architecture levels such that these */ /* can include emulation support */ /*-------------------------------------------------------------------*/ #if defined(FEATCHK_CHECK_ALL) /* FEATURE_INTERPRETIVE_EXECUTION is related to host related issues _FEATURE_SIE is related to guest (emulation) related issues. This because if FEATURE_INTERPRETIVE_EXECUTION is defined for say 390 mode, then _FEATURE_SIE will also need to be in 370 in order to support 370 mode SIE emulation */ #if defined(FEATURE_INTERPRETIVE_EXECUTION) #define _FEATURE_SIE #if defined(FEATURE_ESAME) #define _FEATURE_ZSIE #endif #if defined(FEATURE_PROTECTION_INTERCEPTION_CONTROL) #define _FEATURE_PROTECTION_INTERCEPTION_CONTROL #endif #endif /* _FEATURE_MULTIPLE_CONTROLLED_DATA_SPACE is used for host related processing issues, FEATURE_MULTIPLE_CONTROLLED_DATA_SPACE is defined only in ESA/390 mode. MCDS is an ESA/390 feature that is supported under z/Architecture SIE */ #if defined(FEATURE_MULTIPLE_CONTROLLED_DATA_SPACE) #define _FEATURE_MULTIPLE_CONTROLLED_DATA_SPACE #endif #if defined(FEATURE_2K_STORAGE_KEYS) #define _FEATURE_2K_STORAGE_KEYS #endif #if defined(FEATURE_INTERVAL_TIMER) #define _FEATURE_INTERVAL_TIMER #endif #if defined(FEATURE_ECPSVM) #define _FEATURE_ECPSVM #endif #if defined(FEATURE_VECTOR_FACILITY) #define _FEATURE_VECTOR_FACILITY #endif #if defined(FEATURE_CHANNEL_SUBSYSTEM) #define _FEATURE_CHANNEL_SUBSYSTEM #endif #if defined(FEATURE_SYSTEM_CONSOLE) #define _FEATURE_SYSTEM_CONSOLE #endif #if defined(FEATURE_EXPANDED_STORAGE) #define _FEATURE_EXPANDED_STORAGE #endif #if defined(FEATURE_ECPSVM) #define _FEATURE_ECPSVM #endif #if defined(_FEATURE_SIE) && defined(FEATURE_STORAGE_KEY_ASSIST) #define _FEATURE_STORAGE_KEY_ASSIST #endif #if defined(FEATURE_CPU_RECONFIG) #define _FEATURE_CPU_RECONFIG #endif #if defined(FEATURE_PER) #define _FEATURE_PER #endif #if defined(FEATURE_PER2) #define _FEATURE_PER2 #endif #if defined(FEATURE_EXPEDITED_SIE_SUBSET) #define _FEATURE_EXPEDITED_SIE_SUBSET #endif #if defined(FEATURE_REGION_RELOCATE) #define _FEATURE_REGION_RELOCATE #endif #if defined(FEATURE_IO_ASSIST) #define _FEATURE_IO_ASSIST #endif #if defined(FEATURE_WAITSTATE_ASSIST) #define _FEATURE_WAITSTATE_ASSIST #endif #if defined(FEATURE_EXTERNAL_INTERRUPT_ASSIST) #define _FEATURE_EXTERNAL_INTERRUPT_ASSIST #endif #if defined(FEATURE_MESSAGE_SECURITY_ASSIST) #define _FEATURE_MESSAGE_SECURITY_ASSIST #endif #if defined(FEATURE_ASN_AND_LX_REUSE) #define _FEATURE_ASN_AND_LX_REUSE #endif #if defined(FEATURE_INTEGRATED_3270_CONSOLE) #define _FEATURE_INTEGRATED_3270_CONSOLE #endif #if defined(FEATURE_INTEGRATED_ASCII_CONSOLE) #define _FEATURE_INTEGRATED_ASCII_CONSOLE #endif #undef _VSTORE_C_STATIC #if !defined(OPTION_NO_INLINE_VSTORE) #define _VSTORE_C_STATIC static inline #define _VSTORE_FULL_C_STATIC static #else #define _VSTORE_C_STATIC #define _VSTORE_FULL_C_STATIC #endif #undef _VFETCH_C_STATIC #if !defined(OPTION_NO_INLINE_IFETCH) #define _VFETCH_C_STATIC static inline #else #define _VFETCH_C_STATIC #endif #undef _DAT_C_STATIC #if !defined(OPTION_NO_INLINE_DAT) #define _DAT_C_STATIC static inline #else #define _DAT_C_STATIC #endif #undef _LOGICAL_C_STATIC #if !defined(OPTION_NO_INLINE_LOGICAL) #define _LOGICAL_C_STATIC static inline #else #define _LOGICAL_C_STATIC #endif #if !defined(OPTION_370_MODE) \ && !defined(OPTION_390_MODE) \ && !defined(OPTION_900_MODE) #error No Architecture mode #endif #if defined(OPTION_370_MODE) #define _370 #define _ARCHMODE1 370 #define ARCH_370 0 #endif #if defined(OPTION_390_MODE) #define _390 #if !defined(_ARCHMODE1) #define _ARCHMODE1 390 #define ARCH_390 0 #else #define _ARCHMODE2 390 #define ARCH_390 1 #endif #endif #if defined(OPTION_900_MODE) #define _900 #if !defined(_ARCHMODE2) #define _ARCHMODE2 900 #define ARCH_900 1 #else #define _ARCHMODE3 900 #define ARCH_900 2 #endif #endif #if !defined(ARCH_370) #define ARCH_370 -1 #endif #if !defined(ARCH_390) #define ARCH_390 -1 #endif #if !defined(ARCH_900) #define ARCH_900 -1 #endif #if defined(_ARCHMODE3) #define GEN_MAXARCH 3+2 #elif defined(_ARCHMODE2) #define GEN_MAXARCH 2+2 #else #define GEN_MAXARCH 1+2 #endif #if defined(_900) && !defined(_390) #error OPTION_390_MODE must be enabled for OPTION_900_MODE #endif #else /*!defined(FEATCHK_CHECK_ALL)*/ /* When ESAME is installed then all instructions marked N3 in the reference are also available in ESA/390 mode */ #if defined(_900) && (__GEN_ARCH == 390) #define FEATURE_ESAME_N3_ESA390 #endif #if !defined(FEATURE_2K_STORAGE_KEYS) \ && !defined(FEATURE_4K_STORAGE_KEYS) #error Storage keys must be 2K or 4K #endif #if defined(FEATURE_EXTENDED_STORAGE_KEYS) #if !defined(FEATURE_S370E_EXTENDED_ADDRESSING) #define FEATURE_S370E_EXTENDED_ADDRESSING #endif #endif #if defined(FEATURE_EXPANDED_STORAGE) \ && !defined(FEATURE_4K_STORAGE_KEYS) #error Expanded storage cannot be defined with 2K storage keys #endif #if defined(_900) && defined(FEATURE_VECTOR_FACILITY) #error Vector Facility not supported on ESAME capable processors #endif #if !defined(FEATURE_S370_CHANNEL) && !defined(FEATURE_CHANNEL_SUBSYSTEM) #error Either S/370 Channel or Channel Subsystem must be defined #endif #if defined(FEATURE_S370_CHANNEL) && defined(FEATURE_CHANNEL_SUBSYSTEM) #error S/370 Channel and Channel Subsystem cannot both be defined #endif #if defined(FEATURE_CANCEL_IO_FACILITY) \ && !defined(FEATURE_CHANNEL_SUBSYSTEM) #error Cancel I/O facility requires Channel Subsystem #endif #if defined(FEATURE_MOVE_PAGE_FACILITY_2) \ && !defined(FEATURE_4K_STORAGE_KEYS) #error Move page facility cannot be defined with 2K storage keys #endif #if defined(FEATURE_FAST_SYNC_DATA_MOVER) \ && !defined(FEATURE_MOVE_PAGE_FACILITY_2) #error Fast sync data mover facility requires Move page facility #endif #if defined(FEATURE_ESAME) \ && defined(FEATURE_INTERPRETIVE_EXECUTION) \ && !defined(_FEATURE_SIE) #error ESA/390 SIE must be defined when defining ESAME SIE #endif #if defined(FEATURE_MULTIPLE_CONTROLLED_DATA_SPACE) \ && !defined(FEATURE_INTERPRETIVE_EXECUTION) #error MCDS only supported with SIE #endif #if defined(FEATURE_PROTECTION_INTERCEPTION_CONTROL) \ && !defined(FEATURE_INTERPRETIVE_EXECUTION) #error Protection Interception Control only supported with SIE #endif #if defined(FEATURE_MULTIPLE_CONTROLLED_DATA_SPACE) \ && !defined(FEATURE_STORAGE_KEY_ASSIST) #error MCDS requires storage key assist #endif #if defined(FEATURE_SIE) && defined(FEATURE_ESAME) \ && !defined(FEATURE_STORAGE_KEY_ASSIST) #error ESAME SIE requires storage key assist #endif #if defined(FEATURE_STORAGE_KEY_ASSIST) \ && !defined(FEATURE_INTERPRETIVE_EXECUTION) #error Storage Key assist only supported with SIE #endif #if defined(FEATURE_REGION_RELOCATE) \ && !defined(FEATURE_INTERPRETIVE_EXECUTION) #error Region Relocate Facility only supported with SIE #endif #if defined(FEATURE_IO_ASSIST) \ && !defined(_FEATURE_SIE) #error I/O Assist Feature only supported with SIE #endif #if defined(FEATURE_IO_ASSIST) \ && !defined(_FEATURE_REGION_RELOCATE) #error Region Relocate Facility required for IO Assist #endif #if defined(FEATURE_EXTERNAL_INTERRUPT_ASSIST) \ && !defined(_FEATURE_SIE) #error External Interruption assist only supported with SIE #endif #if defined(FEATURE_EXPEDITED_SIE_SUBSET) \ && !defined(_FEATURE_SIE) #error Expedited SIE Subset only supported with SIE #endif #if defined(FEATURE_ASN_AND_LX_REUSE) #if !defined(FEATURE_DUAL_ADDRESS_SPACE) #error ASN-and-LX-Reuse requires Dual Address-Space feature #endif #if !defined(FEATURE_ESAME) #error ASN-and-LX-Reuse is only supported with ESAME #endif #endif #if defined(FEATURE_ESAME) \ && defined(FEATURE_VECTOR_FACILITY) #error Vector Facility not supported in ESAME mode #endif #if defined(FEATURE_BINARY_FLOATING_POINT) \ && defined(NO_IEEE_SUPPORT) #undef FEATURE_BINARY_FLOATING_POINT #undef FEATURE_FPS_EXTENSIONS #endif #if defined(FEATURE_BINARY_FLOATING_POINT) \ && !defined(FEATURE_BASIC_FP_EXTENSIONS) #error Binary floating point requires basic FP extensions #endif #if defined(FEATURE_DECIMAL_FLOATING_POINT) \ && !defined(FEATURE_BASIC_FP_EXTENSIONS) #error Decimal floating point requires basic FP extensions #endif #if defined(FEATURE_BASIC_FP_EXTENSIONS) \ && !defined(FEATURE_HEXADECIMAL_FLOATING_POINT) #error Basic FP extensions requires hexadecimal floating point #endif #if !defined(FEATURE_BASIC_FP_EXTENSIONS) #if defined(FEATURE_HFP_EXTENSIONS) \ || defined(FEATURE_FPS_EXTENSIONS) #error Floating point extensions require basic FP extensions #endif #endif #if defined(FEATURE_FPS_EXTENSIONS) \ && !defined(FEATURE_BINARY_FLOATING_POINT) #error FP support extensions requires binary floating point #endif #if defined(FEATURE_HFP_MULTIPLY_ADD_SUBTRACT) \ && !defined(FEATURE_HEXADECIMAL_FLOATING_POINT) #error HFP multiply add/subtract requires hexadecimal floating point #endif #if defined(FEATURE_HFP_UNNORMALIZED_EXTENSION) \ && !defined(FEATURE_HEXADECIMAL_FLOATING_POINT) #error HFP unnormalized extension requires hexadecimal floating point #endif #if defined(FEATURE_PER2) && !defined(FEATURE_PER) #error FEATURE_PER must be defined when using FEATURE_PER2 #endif #if defined(FEATURE_PER3) && !defined(FEATURE_PER) #error FEATURE_PER must be defined when using FEATURE_PER3 #endif #if defined(FEATURE_COMPARE_AND_SWAP_AND_STORE_FACILITY_2) && !defined(FEATURE_COMPARE_AND_SWAP_AND_STORE) #error FEATURE_COMPARE_AND_SWAP_AND_STORE must be defined when using FEATURE_COMPARE_AND_SWAP_AND_STORE_FACILITY_2 #endif #if defined(FEATURE_INTEGRATED_3270_CONSOLE) && !defined(FEATURE_SYSTEM_CONSOLE) #error Integrated 3270 console requires FEATURE_SYSTEM_CONSOLE #endif #if defined(FEATURE_INTEGRATED_ASCII_CONSOLE) && !defined(FEATURE_SYSTEM_CONSOLE) #error Integrated ASCII console requires FEATURE_SYSTEM_CONSOLE #endif #if defined(FEATURE_VM_BLOCKIO) && !defined(FEATURE_EMULATE_VM) #error VM Standard Block I/O DIAGNOSE 0x250 requires FEATURE_EMULATE_VM #endif #if defined(FEATURE_MESSAGE_SECURITY_ASSIST) #if defined(_370) #define _370_FEATURE_MESSAGE_SECURITY_ASSIST #endif #if defined(_390) #define _390_FEATURE_MESSAGE_SECURITY_ASSIST #endif #if defined(_900) #define _900_FEATURE_MESSAGE_SECURITY_ASSIST #endif #endif /*defined(FEATURE_MESSAGE_SECURITY_ASSIST)*/ #endif /*!defined(FEATALL_CHECKALL)*/ /* end of FEATCHK.H */ hercules-3.07/feature.h000644 000765 000765 00000053567 11321734033 016564 0ustar00jmaynardjmaynard000000 000000 /* FEATURE.H (c) Copyright Jan Jaeger, 2000-2009 */ /* Architecture-dependent macro definitions */ // $Id: feature.h 5531 2009-12-11 18:23:29Z bernard $ #ifdef HAVE_CONFIG_H #include // Hercules build configuration options/settings #endif #if !defined(FEATCHK_CHECK_DONE) #include "featall.h" #include "feat370.h" #include "feat390.h" #include "feat900.h" #define FEATCHK_CHECK_ALL #include "featchk.h" #undef FEATCHK_CHECK_ALL #define FEATCHK_CHECK_DONE #endif /*!defined(FEATCHK_CHECK_DONE)*/ #undef __GEN_ARCH #if defined(_GEN_ARCH) #define __GEN_ARCH _GEN_ARCH #else #define __GEN_ARCH _ARCHMODE1 #endif #include "featall.h" #if __GEN_ARCH == 370 #include "feat370.h" #elif __GEN_ARCH == 390 #include "feat390.h" #elif __GEN_ARCH == 900 #include "feat900.h" #else #error Unable to determine Architecture Mode #endif #include "featchk.h" #undef ARCH_MODE #undef APPLY_PREFIXING #undef AMASK #undef ADDRESS_MAXWRAP #undef ADDRESS_MAXWRAP_E #undef REAL_MODE #undef PER_MODE #undef ASF_ENABLED #undef ASN_AND_LX_REUSE_ENABLED #undef ASTE_AS_DESIGNATOR #undef ASTE_LT_DESIGNATOR #undef SAEVENT_BIT #undef SSEVENT_BIT #undef SSGROUP_BIT #undef LSED_UET_HDR #undef LSED_UET_TLR #undef LSED_UET_BAKR #undef LSED_UET_PC #undef CR12_BRTRACE #undef CR12_TRACEEA #undef CHM_GPR2_RESV #undef DEF_INST #undef ARCH_DEP #undef PSA #undef PSA_SIZE #undef IA #undef PX #undef CR #undef GR #undef GR_A #undef SET_GR_A #undef MONCODE #undef TEA #undef DXC #undef ET #undef PX_MASK #undef RSTOLD #undef RSTNEW #undef RADR #undef F_RADR #undef VADR #undef VADR_L #undef F_VADR #undef GREG #undef F_GREG #undef CREG #undef F_CREG #undef AREG #undef F_AREG #undef STORE_W #undef FETCH_W #undef AIV #undef AIE #undef VIE #undef SIEBK #undef ZPB #undef TLB_REAL_ASD #undef TLB_ASD #undef TLB_VADDR #undef TLB_PTE #undef TLB_PAGEMASK #undef TLB_BYTEMASK #undef TLB_PAGESHIFT #undef TLBID_PAGEMASK #undef TLBID_BYTEMASK #undef ASD_PRIVATE #undef PER_SB #if __GEN_ARCH == 370 #define ARCH_MODE ARCH_370 #define DEF_INST(_name) \ void (ATTR_REGPARM(2) s370_ ## _name) (BYTE inst[], REGS *regs) #define ARCH_DEP(_name) \ s370_ ## _name #define APPLY_PREFIXING(addr,pfx) \ ( ((U32)(addr) & 0x7FFFF000) == 0 || ((U32)(addr) & 0x7FFFF000) == (pfx) \ ? (U32)(addr) ^ (pfx) \ : (addr) \ ) #define AMASK AMASK_L #define ADDRESS_MAXWRAP(_register_context) \ (AMASK24) #define ADDRESS_MAXWRAP_E(_register_context) \ (AMASK31) #define REAL_MODE(p) \ (!ECMODE(p) || ((p)->sysmask & PSW_DATMODE)==0) #if defined(_FEATURE_SIE) #define PER_MODE(_regs) \ ( (ECMODE(&(_regs)->psw) && ((_regs)->psw.sysmask & PSW_PERMODE)) \ || (SIE_MODE((_regs)) && ((_regs)->siebk->m & SIE_M_GPE)) ) #else #define PER_MODE(_regs) \ (ECMODE(&(_regs)->psw) && ((_regs)->psw.sysmask & PSW_PERMODE)) #endif #define ASF_ENABLED(_regs) 0 /* ASF is never enabled for S/370 */ #define ASN_AND_LX_REUSE_ENABLED(_regs) 0 /* never enabled for S/370 */ #define ASTE_AS_DESIGNATOR(_aste) \ ((_aste)[2]) #define ASTE_LT_DESIGNATOR(_aste) \ ((_aste)[3]) #define SAEVENT_BIT STD_SAEVENT #define SSEVENT_BIT STD_SSEVENT #define SSGROUP_BIT STD_GROUP #define PSA PSA_3XX #define PSA_SIZE 4096 #define IA IA_L #define PX PX_L #define CR(_r) CR_L(_r) #define GR(_r) GR_L(_r) #define GR_A(_r, _regs) ((_regs)->GR_L((_r))) #define SET_GR_A(_r, _regs,_v) ((_regs)->GR_L((_r))=(_v)) #define MONCODE MC_L #define TEA EA_L #define DXC tea #define ET ET_L #define PX_MASK 0x7FFFF000 #define RSTOLD iplccw1 #define RSTNEW iplpsw #if !defined(_FEATURE_ZSIE) #define RADR U32 #define F_RADR "%8.8"I32_FMT"X" #else #define RADR U64 #define F_RADR "%8.8"I64_FMT"X" #endif #define VADR U32 #define VADR_L VADR #define F_VADR "%8.8"I32_FMT"X" #define GREG U32 #define F_GREG "%8.8"I32_FMT"X" #define CREG U32 #define F_CREG "%8.8"I32_FMT"X" #define AREG U32 #define F_AREG "%8.8"I32_FMT"X" #define STORE_W STORE_FW #define FETCH_W FETCH_FW #define AIV AIV_L #define AIE AIE_L #define SIEBK SIE1BK #define ZPB ZPB1 #define TLB_REAL_ASD TLB_REAL_ASD_L #define TLB_ASD(_n) TLB_ASD_L(_n) #define TLB_VADDR(_n) TLB_VADDR_L(_n) #define TLB_PTE(_n) TLB_PTE_L(_n) #define TLB_PAGEMASK 0x00FFF800 #define TLB_BYTEMASK 0x000007FF #define TLB_PAGESHIFT 11 #define TLBID_PAGEMASK 0x00E00000 #define TLBID_BYTEMASK 0x001FFFFF #define ASD_PRIVATE SEGTAB_370_CMN #elif __GEN_ARCH == 390 #define ARCH_MODE ARCH_390 #define DEF_INST(_name) \ void (ATTR_REGPARM(2) s390_ ## _name) (BYTE inst[], REGS *regs) #define ARCH_DEP(_name) \ s390_ ## _name #define APPLY_PREFIXING(addr,pfx) \ ( ((U32)(addr) & 0x7FFFF000) == 0 || ((U32)(addr) & 0x7FFFF000) == (pfx) \ ? (U32)(addr) ^ (pfx) \ : (addr) \ ) #define AMASK AMASK_L #define ADDRESS_MAXWRAP(_register_context) \ ((_register_context)->psw.AMASK) #define ADDRESS_MAXWRAP_E(_register_context) \ ((_register_context)->psw.AMASK) #define REAL_MODE(p) \ (((p)->sysmask & PSW_DATMODE)==0) #if defined(_FEATURE_SIE) #define PER_MODE(_regs) \ ( ((_regs)->psw.sysmask & PSW_PERMODE) \ || (SIE_MODE((_regs)) && ((_regs)->siebk->m & SIE_M_GPE)) ) #else #define PER_MODE(_regs) \ ((_regs)->psw.sysmask & PSW_PERMODE) #endif #define ASF_ENABLED(_regs) ((_regs)->CR(0) & CR0_ASF) #define ASN_AND_LX_REUSE_ENABLED(_regs) 0 /* never enabled in ESA/390 */ #define ASTE_AS_DESIGNATOR(_aste) \ ((_aste)[2]) #define ASTE_LT_DESIGNATOR(_aste) \ ((_aste)[3]) #define SAEVENT_BIT STD_SAEVENT #define SSEVENT_BIT STD_SSEVENT #define SSGROUP_BIT STD_GROUP #define LSED_UET_HDR S_LSED_UET_HDR #define LSED_UET_TLR S_LSED_UET_TLR #define LSED_UET_BAKR S_LSED_UET_BAKR #define LSED_UET_PC S_LSED_UET_PC #define CR12_BRTRACE S_CR12_BRTRACE #define CR12_TRACEEA S_CR12_TRACEEA #define CHM_GPR2_RESV S_CHM_GPR2_RESV #define PSA PSA_3XX #define PSA_SIZE 4096 #define IA IA_L #define PX PX_L #define CR(_r) CR_L(_r) #define GR(_r) GR_L(_r) #define GR_A(_r, _regs) ((_regs)->GR_L((_r))) #define SET_GR_A(_r, _regs,_v) ((_regs)->GR_L((_r))=(_v)) #define MONCODE MC_L #define TEA EA_L #define DXC tea #define ET ET_L #define PX_MASK 0x7FFFF000 #define RSTNEW iplpsw #define RSTOLD iplccw1 #if !defined(_FEATURE_ZSIE) #define RADR U32 #define F_RADR "%8.8"I32_FMT"X" #else #define RADR U64 #define F_RADR "%8.8"I64_FMT"X" #endif #define VADR U32 #define VADR_L VADR #define F_VADR "%8.8"I32_FMT"X" #define GREG U32 #define F_GREG "%8.8"I32_FMT"X" #define CREG U32 #define F_CREG "%8.8"I32_FMT"X" #define AREG U32 #define F_AREG "%8.8"I32_FMT"X" #define STORE_W STORE_FW #define FETCH_W FETCH_FW #define AIV AIV_L #define AIE AIE_L #define SIEBK SIE1BK #define ZPB ZPB1 #define TLB_REAL_ASD TLB_REAL_ASD_L #define TLB_ASD(_n) TLB_ASD_L(_n) #define TLB_VADDR(_n) TLB_VADDR_L(_n) #define TLB_PTE(_n) TLB_PTE_L(_n) #define TLB_PAGEMASK 0x7FFFF000 #define TLB_BYTEMASK 0x00000FFF #define TLB_PAGESHIFT 12 #define TLBID_PAGEMASK 0x7FC00000 #define TLBID_BYTEMASK 0x003FFFFF #define ASD_PRIVATE STD_PRIVATE #elif __GEN_ARCH == 900 #define ARCH_MODE ARCH_900 #define APPLY_PREFIXING(addr,pfx) \ ( (U64)((addr) & 0xFFFFFFFFFFFFE000ULL) == (U64)0 || (U64)((addr) & 0xFFFFFFFFFFFFE000ULL) == (pfx) \ ? (addr) ^ (pfx) \ : (addr) \ ) #define AMASK AMASK_G #define ADDRESS_MAXWRAP(_register_context) \ ((_register_context)->psw.AMASK) #define ADDRESS_MAXWRAP_E(_register_context) \ ((_register_context)->psw.AMASK) #define REAL_MODE(p) \ (((p)->sysmask & PSW_DATMODE)==0) #if defined(_FEATURE_SIE) #define PER_MODE(_regs) \ ( ((_regs)->psw.sysmask & PSW_PERMODE) \ || (SIE_MODE((_regs)) && ((_regs)->siebk->m & SIE_M_GPE)) ) #else #define PER_MODE(_regs) \ ((_regs)->psw.sysmask & PSW_PERMODE) #endif #define ASF_ENABLED(_regs) 1 /* ASF is always enabled for ESAME */ /* ASN-and-LX-reuse is enabled if the ASN-and-LX-reuse facility is installed and CR0 bit 44 is 1 */ #if defined(FEATURE_ASN_AND_LX_REUSE) #define ASN_AND_LX_REUSE_ENABLED(_regs) \ (sysblk.asnandlxreuse && ((_regs)->CR_L(0) & CR0_ASN_LX_REUS)) #else /* !defined(FEATURE_ASN_AND_LX_REUSE) */ #define ASN_AND_LX_REUSE_ENABLED(_regs) 0 #endif /* !defined(FEATURE_ASN_AND_LX_REUSE) */ #define ASTE_AS_DESIGNATOR(_aste) \ (((U64)((_aste)[2])<<32)|(U64)((_aste)[3])) #define ASTE_LT_DESIGNATOR(_aste) \ ((_aste)[6]) #define SAEVENT_BIT ASCE_S #define SSEVENT_BIT ASCE_X #define SSGROUP_BIT ASCE_G #define LSED_UET_HDR Z_LSED_UET_HDR #define LSED_UET_TLR Z_LSED_UET_TLR #define LSED_UET_BAKR Z_LSED_UET_BAKR #define LSED_UET_PC Z_LSED_UET_PC #define CR12_BRTRACE Z_CR12_BRTRACE #define CR12_TRACEEA Z_CR12_TRACEEA #define CHM_GPR2_RESV Z_CHM_GPR2_RESV #define DEF_INST(_name) \ void (ATTR_REGPARM(2) z900_ ## _name) (BYTE inst[], REGS *regs) #define ARCH_DEP(_name) \ z900_ ## _name #define PSA PSA_900 #define PSA_SIZE 8192 #define IA IA_G #define PX PX_L #define CR(_r) CR_G(_r) #define GR(_r) GR_G(_r) #define GR_A(_r, _regs) ((_regs)->psw.amode64 ? (_regs)->GR_G((_r)) : (_regs)->GR_L((_r))) #define SET_GR_A(_r, _regs,_v) \ do { \ if((_regs)->psw.amode64) { \ ((_regs)->GR_G((_r))=(_v)); \ } else { \ ((_regs)->GR_L((_r))=(_v)); \ } \ } while(0) #define MONCODE MC_G #define TEA EA_G #define DXC dataexc #define ET ET_G #define PX_MASK 0x7FFFE000 #define RSTOLD rstold #define RSTNEW rstnew #if 0 #define RADR U32 #else #define RADR U64 #endif #define F_RADR "%16.16"I64_FMT"X" #define VADR U64 #if SIZEOF_INT == 4 #define VADR_L U32 #else #define VADR_L VADR #endif #define F_VADR "%16.16"I64_FMT"X" #define GREG U64 #define F_GREG "%16.16"I64_FMT"X" #define CREG U64 #define F_CREG "%16.16"I64_FMT"X" #define AREG U32 #define F_AREG "%8.8"I32_FMT"X" #define STORE_W STORE_DW #define FETCH_W FETCH_DW #define AIV AIV_G #define AIE AIE_G #define SIEBK SIE2BK #define ZPB ZPB2 #define TLB_REAL_ASD TLB_REAL_ASD_G #define TLB_ASD(_n) TLB_ASD_G(_n) #define TLB_VADDR(_n) TLB_VADDR_G(_n) #define TLB_PTE(_n) TLB_PTE_G(_n) #define TLB_PAGEMASK 0xFFFFFFFFFFFFF000ULL #define TLB_BYTEMASK 0x0000000000000FFFULL #define TLB_PAGESHIFT 12 #define TLBID_PAGEMASK 0xFFFFFFFFFFC00000ULL #define TLBID_BYTEMASK 0x00000000003FFFFFULL #define ASD_PRIVATE (ASCE_P|ASCE_R) #else #warning __GEN_ARCH must be 370, 390, 900 or undefined #endif #undef PAGEFRAME_PAGESIZE #undef PAGEFRAME_PAGESHIFT #undef PAGEFRAME_BYTEMASK #undef PAGEFRAME_PAGEMASK #undef MAXADDRESS #if defined(FEATURE_ESAME) #define PAGEFRAME_PAGESIZE 4096 #define PAGEFRAME_PAGESHIFT 12 #define PAGEFRAME_BYTEMASK 0x00000FFF #define PAGEFRAME_PAGEMASK 0xFFFFFFFFFFFFF000ULL #define MAXADDRESS 0xFFFFFFFFFFFFFFFFULL #elif defined(FEATURE_S390_DAT) #define PAGEFRAME_PAGESIZE 4096 #define PAGEFRAME_PAGESHIFT 12 #define PAGEFRAME_BYTEMASK 0x00000FFF #define PAGEFRAME_PAGEMASK 0x7FFFF000 #define MAXADDRESS 0x7FFFFFFF #else /* S/370 */ #define PAGEFRAME_PAGESIZE 2048 #define PAGEFRAME_PAGESHIFT 11 #define PAGEFRAME_BYTEMASK 0x000007FF #define PAGEFRAME_PAGEMASK 0x7FFFF800 #if defined(FEATURE_370E_EXTENDED_ADDRESSING) #define MAXADDRESS 0x03FFFFFF #else #define MAXADDRESS 0x00FFFFFF #endif #endif #undef ITIMER_UPDATE #undef ITIMER_SYNC #if defined(FEATURE_INTERVAL_TIMER) #define ITIMER_UPDATE(_addr, _len, _regs) \ do { \ if( ITIMER_ACCESS((_addr), (_len)) ) \ ARCH_DEP(fetch_int_timer) ((_regs)); \ } while(0) #define ITIMER_SYNC(_addr, _len, _regs) \ do { \ if( ITIMER_ACCESS((_addr), (_len)) ) \ ARCH_DEP(store_int_timer) ((_regs)); \ } while (0) #else #define ITIMER_UPDATE(_addr, _len, _regs) #define ITIMER_SYNC(_addr, _len, _regs) #endif #if !defined(_FEATURE_2K_STORAGE_KEYS) #define STORAGE_KEY_UNITSIZE 4096 #else #define STORAGE_KEY_UNITSIZE 2048 #endif #undef STORAGE_KEY #undef STORAGE_KEY_PAGESHIFT #undef STORAGE_KEY_PAGESIZE #undef STORAGE_KEY_PAGEMASK #undef STORAGE_KEY_BYTEMASK #ifdef FEATURE_4K_STORAGE_KEYS #if defined(_FEATURE_2K_STORAGE_KEYS) #define STORAGE_KEY_PAGESHIFT 11 #else #define STORAGE_KEY_PAGESHIFT 12 #endif #define STORAGE_KEY_PAGESIZE 4096 #if defined(FEATURE_ESAME) #define STORAGE_KEY_PAGEMASK 0xFFFFFFFFFFFFF000ULL #else #define STORAGE_KEY_PAGEMASK 0x7FFFF000 #endif #define STORAGE_KEY_BYTEMASK 0x00000FFF #else #define STORAGE_KEY_PAGESHIFT 11 #define STORAGE_KEY_PAGESIZE 2048 #define STORAGE_KEY_PAGEMASK 0x7FFFF800 #define STORAGE_KEY_BYTEMASK 0x000007FF #endif #define STORAGE_KEY(_addr, _pointer) \ (_pointer)->storkeys[(_addr)>>STORAGE_KEY_PAGESHIFT] #if defined(_FEATURE_2K_STORAGE_KEYS) #define STORAGE_KEY1(_addr, _pointer) \ (_pointer)->storkeys[((_addr)>>STORAGE_KEY_PAGESHIFT)&~1] #define STORAGE_KEY2(_addr, _pointer) \ (_pointer)->storkeys[((_addr)>>STORAGE_KEY_PAGESHIFT)|1] #endif #define XSTORE_INCREMENT_SIZE 0x00100000 #define XSTORE_PAGESHIFT 12 #define XSTORE_PAGESIZE 4096 #undef XSTORE_PAGEMASK #if defined(FEATURE_ESAME) || defined(_FEATURE_ZSIE) #define XSTORE_PAGEMASK 0xFFFFFFFFFFFFF000ULL #else #define XSTORE_PAGEMASK 0x7FFFF000 #endif /*-------------------------------------------------------------------*/ /* Macros use by Compare and Form Codeword (CFC (B21A)) instruction */ /*-------------------------------------------------------------------*/ #undef CFC_A64_OPSIZE #undef CFC_DEF_OPSIZE #undef CFC_MAX_OPSIZE #undef CFC_OPSIZE #undef CFC_GR2_SHIFT #undef CFC_HIGH_BIT #undef AR1 #define AR1 ( 1 ) /* Access Register 1 */ #define CFC_A64_OPSIZE ( 6 ) /* amode-64 operand size */ #define CFC_DEF_OPSIZE ( 2 ) /* non-amode-64 operand size */ #define CFC_MAX_OPSIZE ( CFC_A64_OPSIZE > CFC_DEF_OPSIZE ? CFC_A64_OPSIZE : CFC_DEF_OPSIZE ) #if defined(FEATURE_ESAME) #define CFC_OPSIZE ( a64 ? CFC_A64_OPSIZE : CFC_DEF_OPSIZE ) #define CFC_GR2_SHIFT ( a64 ? ( CFC_A64_OPSIZE * 8 ) : ( CFC_DEF_OPSIZE * 8 ) ) #define CFC_HIGH_BIT ( a64 ? 0x8000000000000000ULL : 0x0000000080000000ULL ) #else #define CFC_OPSIZE ( CFC_DEF_OPSIZE ) #define CFC_GR2_SHIFT ( CFC_DEF_OPSIZE * 8 ) #define CFC_HIGH_BIT ( 0x80000000UL ) #endif /*-------------------------------------------------------------------*/ /* Macros use by Update Tree (CFC (0102)) instruction */ /*-------------------------------------------------------------------*/ #undef UPT_ALIGN_MASK #undef UPT_SHIFT_MASK #undef UPT_HIGH_BIT #undef AR4 #define AR4 (4) /* Access Register 4 */ #if defined(FEATURE_ESAME) #define UPT_ALIGN_MASK ( a64 ? 0x000000000000000FULL : 0x0000000000000007ULL ) #define UPT_SHIFT_MASK ( a64 ? 0xFFFFFFFFFFFFFFF0ULL : 0xFFFFFFFFFFFFFFF8ULL ) #define UPT_HIGH_BIT ( a64 ? 0x8000000000000000ULL : 0x0000000080000000ULL ) #else #define UPT_ALIGN_MASK ( 0x00000007 ) #define UPT_SHIFT_MASK ( 0xFFFFFFF8 ) #define UPT_HIGH_BIT ( 0x80000000 ) #endif /* Macros for accelerated lookup */ #undef SPACE_BIT #undef AR_BIT #undef PRIMARY_SPACE_MODE #undef SECONDARY_SPACE_MODE #undef ACCESS_REGISTER_MODE #undef HOME_SPACE_MODE #undef AEA_MODE #undef SET_AEA_COMMON #undef SET_AEA_MODE #undef _CASE_AR_SET_AEA_MODE #undef _CASE_DAS_SET_AEA_MODE #undef _CASE_HOME_SET_AEA_MODE #undef TEST_SET_AEA_MODE #undef SET_AEA_AR #undef MADDR #if defined(FEATURE_DUAL_ADDRESS_SPACE) && defined(FEATURE_LINKAGE_STACK) #define SET_AEA_COMMON(_regs) \ do { \ (_regs)->aea_common[1] = ((_regs)->CR(1) & ASD_PRIVATE) == 0; \ (_regs)->aea_common[7] = ((_regs)->CR(7) & ASD_PRIVATE) == 0; \ (_regs)->aea_common[13] = ((_regs)->CR(13) & ASD_PRIVATE) == 0; \ } while (0) #elif defined(FEATURE_DUAL_ADDRESS_SPACE) #define SET_AEA_COMMON(_regs) \ do { \ (_regs)->aea_common[1] = ((_regs)->CR(1) & ASD_PRIVATE) == 0; \ (_regs)->aea_common[7] = ((_regs)->CR(7) & ASD_PRIVATE) == 0; \ } while (0) #else #define SET_AEA_COMMON(_regs) \ do { \ (_regs)->aea_common[1] = ((_regs)->CR(1) & ASD_PRIVATE) == 0; \ } while (0) #endif #if defined(FEATURE_DUAL_ADDRESS_SPACE) || defined(FEATURE_LINKAGE_STACK) #define SPACE_BIT(p) \ (((p)->asc & BIT(PSW_SPACE_BIT)) != 0) #define AR_BIT(p) \ (((p)->asc & BIT(PSW_AR_BIT)) != 0) #define PRIMARY_SPACE_MODE(p) \ ((p)->asc == PSW_PRIMARY_SPACE_MODE) #define SECONDARY_SPACE_MODE(p) \ ((p)->asc == PSW_SECONDARY_SPACE_MODE) #define ACCESS_REGISTER_MODE(p) \ ((p)->asc == PSW_ACCESS_REGISTER_MODE) #define HOME_SPACE_MODE(p) \ ((p)->asc == PSW_HOME_SPACE_MODE) #define AEA_MODE(_regs) \ ( ( REAL_MODE(&(_regs)->psw) ? (SIE_STATB((_regs), MX, XC) && AR_BIT(&(_regs)->psw) ? 2 : 0) : (((_regs)->psw.asc >> 6) + 1) ) \ | ( PER_MODE((_regs)) ? 0x40 : 0 ) \ ) #else #define SPACE_BIT(p) (0) #define AR_BIT(p) (0) #define PRIMARY_SPACE_MODE(p) (1) #define SECONDARY_SPACE_MODE(p) (0) #define ACCESS_REGISTER_MODE(p) (0) #define HOME_SPACE_MODE(p) (0) #define AEA_MODE(_regs) \ ( (REAL_MODE(&(_regs)->psw) ? 0 : 1 ) | (PER_MODE((_regs)) ? 0x40 : 0 ) ) #endif #if defined(FEATURE_ACCESS_REGISTERS) /* * Update the aea_ar vector whenever an access register * is changed and in armode */ #define SET_AEA_AR(_regs, _arn) \ do \ { \ if (ACCESS_REGISTER_MODE(&(_regs)->psw) && (_arn) > 0 && (_arn) < 16) { \ if ((_regs)->AR((_arn)) == ALET_PRIMARY) \ (_regs)->aea_ar[(_arn)] = 1; \ else if ((_regs)->AR((_arn)) == ALET_SECONDARY) \ (_regs)->aea_ar[(_arn)] = 7; \ else \ (_regs)->aea_ar[(_arn)] = 0; \ } \ } while (0) #else #define SET_AEA_AR(_regs, _arn) #endif /* * Conditionally reset the aea_ar vector */ #define TEST_SET_AEA_MODE(_regs) \ do \ { \ if ((_regs)->aea_mode != AEA_MODE((_regs))) { \ SET_AEA_MODE((_regs)); \ } \ } while (0) /* * Reset aea_ar vector to indicate the appropriate * control register: * 0 - unresolvable (armode and alet is not 0 or 1) * 1 - primary space * 7 - secondary space * 13 - home space * 16 - real */ #if defined(FEATURE_ACCESS_REGISTERS) #define _CASE_AR_SET_AEA_MODE(_regs) \ case 2: /* AR */ \ (_regs)->aea_ar[USE_INST_SPACE] = 1; \ for(i = 0; i < 16; i++) \ (_regs)->aea_ar[i] = 1; \ for (i = 1; i < 16; i++) { \ if ((_regs)->AR(i) == ALET_SECONDARY) (_regs)->aea_ar[i] = 7; \ else if ((_regs)->AR(i) != ALET_PRIMARY) (_regs)->aea_ar[i] = 0; \ } \ break; #else #define _CASE_AR_SET_AEA_MODE(_regs) #endif #if defined(FEATURE_DUAL_ADDRESS_SPACE) #define _CASE_DAS_SET_AEA_MODE(_regs) \ case 3: /* SEC */ \ (_regs)->aea_ar[USE_INST_SPACE] = 1; \ for(i = 0; i < 16; i++) \ (_regs)->aea_ar[i] = 7; \ break; #else #define _CASE_DAS_SET_AEA_MODE(_regs) #endif #if defined(FEATURE_LINKAGE_STACK) #define _CASE_HOME_SET_AEA_MODE(_regs) \ case 4: /* HOME */ \ (_regs)->aea_ar[USE_INST_SPACE] = 13; \ for(i = 0; i < 16; i++) \ (_regs)->aea_ar[i] = 13; \ break; #else #define _CASE_HOME_SET_AEA_MODE(_regs) #endif #define SET_AEA_MODE(_regs) \ do { \ int i; \ int inst_cr = (_regs)->aea_ar[USE_INST_SPACE]; \ BYTE oldmode = (_regs)->aea_mode; \ (_regs)->aea_mode = AEA_MODE((_regs)); \ switch ((_regs)->aea_mode & 0x0F) { \ case 1: /* PRIM */ \ (_regs)->aea_ar[USE_INST_SPACE] = 1; \ for(i = 0; i < 16; i++) \ (_regs)->aea_ar[i] = 1; \ break; \ _CASE_AR_SET_AEA_MODE((_regs)) \ _CASE_DAS_SET_AEA_MODE((_regs)) \ _CASE_HOME_SET_AEA_MODE((_regs)) \ default: /* case 0: REAL */ \ (_regs)->aea_ar[USE_INST_SPACE] = CR_ASD_REAL; \ for(i = 0; i < 16; i++) \ (_regs)->aea_ar[i] = CR_ASD_REAL; \ } \ if (inst_cr != (_regs)->aea_ar[USE_INST_SPACE]) \ INVALIDATE_AIA((_regs)); \ if ((oldmode & PSW_PERMODE) == 0 && ((_regs)->aea_mode & PSW_PERMODE) != 0) { \ INVALIDATE_AIA((_regs)); \ if (EN_IC_PER_SA((_regs))) \ ARCH_DEP(invalidate_tlb)((_regs),~(ACC_WRITE|ACC_CHECK)); \ } \ } while (0) /* * Accelerated lookup */ #define MADDR(_addr, _arn, _regs, _acctype, _akey) \ ( \ likely((_regs)->aea_ar[(_arn)]) \ && likely( \ ((_regs)->CR((_regs)->aea_ar[(_arn)]) == (_regs)->tlb.TLB_ASD(TLBIX(_addr))) \ || ((_regs)->aea_common[(_regs)->aea_ar[(_arn)]] & (_regs)->tlb.common[TLBIX(_addr)]) \ ) \ && likely((_akey) == 0 || (_akey) == (_regs)->tlb.skey[TLBIX(_addr)]) \ && likely((((_addr) & TLBID_PAGEMASK) | (_regs)->tlbID) == (_regs)->tlb.TLB_VADDR(TLBIX(_addr))) \ && likely((_acctype) & (_regs)->tlb.acc[TLBIX(_addr)]) \ ? ( \ ((_acctype) & ACC_CHECK) ? \ (_regs)->dat.storkey = (_regs)->tlb.storkey[TLBIX(_addr)], \ MAINADDR((_regs)->tlb.main[TLBIX(_addr)], (_addr)) : \ MAINADDR((_regs)->tlb.main[TLBIX(_addr)], (_addr)) \ ) \ : ( \ ARCH_DEP(logical_to_main) ((_addr), (_arn), (_regs), (_acctype), (_akey)) \ ) \ ) /* * PER Successful Branch */ #if defined(FEATURE_PER) #if defined(FEATURE_PER2) #define PER_SB(_regs, _addr) \ do { \ if (unlikely(EN_IC_PER_SB((_regs))) \ && (!((_regs)->CR(9) & CR9_BAC) \ || PER_RANGE_CHECK((_addr) & ADDRESS_MAXWRAP((_regs)), \ (_regs)->CR(10), (_regs)->CR(11)) \ ) \ ) \ ON_IC_PER_SB((_regs)); \ } while (0) #else /*!defined(FEATURE_PER2)*/ #define PER_SB(_regs, _addr) \ do { \ if (unlikely(EN_IC_PER_SB((_regs)))) \ ON_IC_PER_SB((_regs)); \ } while (0) #endif /*!defined(FEATURE_PER2)*/ #else /*!defined(FEATURE_PER)*/ #define PER_SB(_regs,_addr) #endif /*!defined(FEATURE_PER)*/ /* end of FEATURES.H */ hercules-3.07/fillfnam.c000644 000765 000765 00000015151 11143760543 016706 0ustar00jmaynardjmaynard000000 000000 // $Id: fillfnam.c 4857 2008-08-29 07:07:08Z fish $ // // $Log$ // Revision 1.11 2008/02/18 22:57:08 rbowler // Disable filename completion for Solaris 2.9 due to missing scandir function // // Revision 1.10 2006/12/31 17:52:50 gsmith // 31 Dec 2006 Fix typo in line 1 of fillfnam.c // // Revision 1.9 2006/12/31 11:31:21 fish // Fix cmdline tabbed filename-completion for MSVC // // Revision 1.8 2006/12/08 09:43:21 jj // Add CVS message log // #include "hstdinc.h" #include "hercules.h" #include "fillfnam.h" /* On Solaris 2.9 (SunOS 5.9) and earlier, there is no scandir and alphasort function. In this case fillfnam does nothing and the tab command is effectively a no-operation */ #if !(defined(HAVE_SCANDIR) && defined(HAVE_ALPHASORT)) && !defined(_MSVC_) int tab_pressed(char *cmdlinefull, int *cmdoffset) { UNREFERENCED(cmdlinefull); UNREFERENCED(cmdoffset); return 0; } #else char *filterarray; int filter(const struct dirent *ent) { if (filterarray == NULL) return(1); if (strncmp(ent->d_name, filterarray, strlen(filterarray)) == 0) return(1); return(0); } /* tab can be pressed anywhere in the command line, so I have to split command line for example: attach 0a00 3390 volu_ sf=volume1.shadow will be divided part1 = "attach 0a00 " part2 = "volu" part3 = " sf=volume1.shadow" only part2 can be changed and it must be divided into path and filename */ int tab_pressed(char *cmdlinefull, int *cmdoffset) { struct dirent **namelist; int n, i, j, len, len1, len2; int cmdoff = *(cmdoffset); /* for easy reading of source code */ char *part1, *part2, *part3; char *buff; char *filename, *path, *tmp; char result[1024]; char pathname[MAX_PATH]; #ifdef _MSVC_ int within_quoted_string = 0; int quote_pos; #endif /* part3 goes from cursor position to the end of line */ part3 = cmdlinefull + cmdoff; /* looking for ' ','@' or '=' backward, starting from cursor offset I am not aware of any other delimiters which can be used in hercules */ /* (except for '"' (double quote) for the MSVC version of herc - Fish) */ #ifdef _MSVC_ /* determine if tab was pressed within a quoted string */ for (i=0; i < cmdoff; i++) if ('\"' == cmdlinefull[i]) { within_quoted_string = !within_quoted_string; quote_pos = i; /* (save position of quote immediately preceding cmdoff) */ } if (within_quoted_string) i = quote_pos; /* (the quote is our delimiter) */ else #endif for (i = cmdoff-1; i>=0; i--) if (cmdlinefull[i] == ' ' || cmdlinefull[i] == '@' || cmdlinefull[i] == '=') break; /* part1 is from beginning to found delimiter (including delimiter itself) */ part1 = (char*) malloc(i+2); strncpy(part1, cmdlinefull, i+1); part1[i+1]= '\0'; /* part2 is the interesting one */ part2 = (char*)malloc(cmdoff - i); strncpy(part2, cmdlinefull + i + 1, cmdoff - i - 1); part2[cmdoff - i - 1] = '\0'; len = strlen(part2); /* 3 characters minimum needed, for ./\0 in path. */ /* (or 4 chars for MSVC if within quoted string, for \"./\0 - Fish) */ #ifdef _MSVC_ if (within_quoted_string) { if (len < 3) len = 3; } else #endif if (len < 2) len = 2; path = (char*)malloc(len + 1); *path = '\0'; filename = part2; /* is it pure filename or is there whole path ? */ tmp = strrchr(part2, '/'); #ifdef _MSVC_ if (!tmp) tmp = strrchr(part2, '\\'); #endif if (tmp != NULL) { filename = tmp + 1; strncpy(path, part2, strlen(part2)-strlen(filename)); path[strlen(part2)-strlen(filename)] = '\0'; tmp[0] = '\0'; } else { #ifdef _MSVC_ if (within_quoted_string) strcpy(path,"\"./"); else #endif strcpy(path,"./"); } /* this is used in filter function to include only relevant filenames */ filterarray = filename; n = scandir(path, &namelist, filter, alphasort); if (n > 0) { for (i=0; id_name contains filtered filenames, check if they are directories with stat(), before that create whole path */ if (tmp != NULL) sprintf(fullfilename, "%s%s", path, namelist[i]->d_name); else sprintf(fullfilename, "%s", namelist[i]->d_name); #ifdef _MSVC_ if (within_quoted_string) strlcat(fullfilename,"\"",sizeof(fullfilename)); #endif /* if it is a directory, add '/' to the end so it can be seen on screen*/ hostpath(pathname, fullfilename, sizeof(pathname)); if (stat(pathname,&buf) == 0) if (buf.st_mode & S_IFDIR) { // strcat(namelist[i]->d_name,"/"); // Don't write past end of d_name // Problem debugged by bb5ch39t namelist[i] = realloc(namelist[i], sizeof(struct dirent) + strlen(namelist[i]->d_name) + 2); if (namelist[i]) strcat(namelist[i]->d_name,"/"); } } /* now check, if filenames have something in common, after a cycle buff contains maximal intersection of names */ buff = (char*)malloc(strlen(namelist[0]->d_name) + 1); /* first one */ strcpy(buff, namelist[0]->d_name); for (i = 1; i < n; i++) { len1 = strlen(buff); len2 = strlen(namelist[i]->d_name); /* check number of characters in shorter one */ len = len1 > len2 ? len2 : len1; for (j = 0; j < len; j++) if (buff[j] != namelist[i]->d_name[j]) { buff[j] = '\0'; /* end the string where characters are not equal */ break; } } /* if maximal intersection of filenames is longer then original filename */ if (strlen(buff) > strlen(filename)) { char *fullfilename; fullfilename = (char*)malloc(strlen(path) + strlen(buff) + 1); /* this test is not useless as path contains './' if there was no path in original filename. it is because of scandir function, which needs path portion */ if (tmp != NULL) sprintf(fullfilename, "%s%s", path, buff); else sprintf(fullfilename, "%s", buff); /* construct command line */ sprintf(result, "%s%s%s", part1, fullfilename, part3); /* move cursor */ *(cmdoffset) = strlen(part1) + strlen(fullfilename); strcpy(cmdlinefull, result); free(fullfilename); } else { /* display all alternatives */ for (i = 0; i< n; i++) logmsg("%s\n", namelist[i]->d_name); } /* free everything */ free(buff); for (i = 0; i< n; i++) free(namelist[i]); free(namelist); } free(part1); free(part2); free(path); return(0); } #endif /*(HAVE_SCANDIR && HAVE_ALPHASORT) || _MSVC_*/ hercules-3.07/fillfnam.h000644 000765 000765 00000000252 11143760543 016707 0ustar00jmaynardjmaynard000000 000000 // $Id: fillfnam.h 4102 2006-12-08 09:43:35Z jj $ // // $Log$ #ifndef __FILLFNAM_H__ #define __FILLFNAM_H__ int tab_pressed(char *cmdlinefull, int *cmdoffset); #endif hercules-3.07/fishhang.c000644 000765 000765 00000141114 11321734033 016675 0ustar00jmaynardjmaynard000000 000000 //////////////////////////////////////////////////////////////////////////////////// // fishhang.c verify/debug proper Hercules LOCK handling... //////////////////////////////////////////////////////////////////////////////////// // (c) Copyright "Fish" (David B. Trout), 2002-2009. Released under the Q Public License // (http://www.hercules-390.org/herclic.html) as modifications to Hercules. //////////////////////////////////////////////////////////////////////////////////// // $Id: fishhang.c 5586 2009-12-31 10:29:11Z rbowler $ // // $Log$ // Revision 1.19 2007/11/30 14:54:32 jmaynard // Changed conmicro.cx to hercules-390.org or conmicro.com, as needed. // // Revision 1.18 2007/06/23 00:04:09 ivan // Update copyright notices to include current year (2007) // // Revision 1.17 2006/12/31 12:25:26 fish // Fix "undefined reference to _beginthreadex" issue for non-MSVC (i.e. Cygwin) builds. // // Revision 1.16 2006/12/28 15:49:34 fish // Use _beginthreadex/_endthreadex instead of CreateThread/ExitThread in continuing effort to try and resolve our still existing long-standing 'errno' issue... // // Revision 1.15 2006/12/08 09:43:21 jj // Add CVS message log // #include "hstdinc.h" #define _FISHHANG_C_ #define _HUTIL_DLL_ #include "hercules.h" #include "fishhang.h" // (prototypes for this module) #if defined(FISH_HANG) //////////////////////////////////////////////////////////////////////////////////// // Global variables... LIST_ENTRY ThreadsListHead; // head list entry of list of threads LIST_ENTRY LocksListHead; // head list entry of list of locks LIST_ENTRY EventsListHead; // head list entry of list of events // Controlled access to above lists... CRITICAL_SECTION ListsLock; #define LockFishHang() (EnterCriticalSection(&ListsLock)) #define UnlockFishHang() (LeaveCriticalSection(&ListsLock)) // bFishHangAtExit is set before exiting to disable some error checking... DLL_EXPORT BOOL bFishHangAtExit = FALSE; ////////////////////////////////////////////////////////////////////////////////// // We need to use our own private report o/p stream since // the logger thread uses fthreads and thus fishhang too! FILE* fh_report_stream = NULL; #define logmsg FishHang_Printf DLL_EXPORT void FishHang_Printf( const char* pszFormat, ... ) { va_list vl; va_start( vl, pszFormat ); vfprintf( fh_report_stream, pszFormat, vl ); fflush( fh_report_stream ); } ////////////////////////////////////////////////////////////////////////////////// // Thread information... (locks it owns, which lock/event it's waiting on, etc) typedef struct _tagFishThread { DWORD dwCreatingThreadID; // threadid that created it SYSTEMTIME timeCreated; // time created const char* pszFileCreated; // source file that created it int nLineCreated; // line number of source file ////////////////////////////////////////////////////////////////// DWORD dwThreadID; // threadid of this entry LIST_ENTRY ThreadListLink; // chaining list entry of list of threads LIST_ENTRY ThreadLockListHead; // head list entry of list of locks // obtained by this thread BOOL bWaitingForLock; // stuck in EnterCriticalSection // waiting to obtain a lock BOOL bTryingForLock; // TRUE = TryEnterCriticalSection, // FALSE = EnterCriticalSection BOOL bWaitingForEvent; // stuck in WaitForSingleObject // waiting for event to be signalled void* pWhatWaiting; // ptr to FISH_LOCK last attempted to be signalled // -or- to FISH_EVENT last waited to be posted // (NOTE: must manually cast to whichever type) const char* pszFileWaiting; // source file where attempt/wait occured int nLineWaiting; // line number of source file SYSTEMTIME timeWaiting; // time when attempt/wait occured } FISH_THREAD; ////////////////////////////////////////////////////////////////////////////////// // Lock information... (which thread has it locked, etc) typedef struct _tagFishLock { DWORD dwCreatingThreadID; // threadid that created it SYSTEMTIME timeCreated; // time created const char* pszFileCreated; // source file that created it int nLineCreated; // line number of source file ////////////////////////////////////////////////////////////////// void* pLock; // ptr to actual lock (CRITICAL_SECTION) LIST_ENTRY LockListLink; // chaining list entry of list of locks LIST_ENTRY ThreadLockListLink; // chaining list entry of list of locks // obtained by a given thread FISH_THREAD* pOwningThread; // ptr to FISH_THREAD that has it locked // (i.e. who owns it; NULL if nobody) int nLockedDepth; // counts recursive obtains } FISH_LOCK; ////////////////////////////////////////////////////////////////////////////////// // Event information... (who set/reset it, when it was set/reset, etc) typedef struct _tagFishEvent { DWORD dwCreatingThreadID; // threadid that created it SYSTEMTIME timeCreated; // time created const char* pszFileCreated; // source file that created it int nLineCreated; // line number of source file ////////////////////////////////////////////////////////////////// HANDLE hEvent; // handle of actual event LIST_ENTRY EventsListLink; // chaining list entry of list of events FISH_THREAD* pWhoSet; // ptr to FISH_THREAD that set it SYSTEMTIME timeSet; // time set const char* pszFileSet; // source file that set it int nLineSet; // line number of source file FISH_THREAD* pWhoReset; // ptr to FISH_THREAD that reset it SYSTEMTIME timeReset; // time reset const char* pszFileReset; // source file that reset it int nLineReset; // line number of source file } FISH_EVENT; ///////////////////////////////////////////////////////////////////////////// // Macro to remove Microsoft's standard fullpath from __FILE__ name... #define FIXFILENAME( filename ) \ do { if ( filename ) { \ char* p = strrchr( filename, '\\' ); \ if (!p) p = strrchr( filename, '/' ); \ if (p) filename = p+1; } } while (0) ///////////////////////////////////////////////////////////////////////////// // (forward references...) FISH_THREAD* CreateFISH_THREAD( const char* pszFileCreated, const int nLineCreated ); ///////////////////////////////////////////////////////////////////////////// // Initialize global variables... DLL_EXPORT void FishHangInit( const char* pszFileCreated, const int nLineCreated ) { FISH_THREAD* pFISH_THREAD; FIXFILENAME(pszFileCreated); if ( !( fh_report_stream = fopen( "FishHangReport.txt", "w" ) ) ) { perror( "FishHang report o/p file open failure" ); abort(); } InitializeListHead(&ThreadsListHead); InitializeListHead(&LocksListHead); InitializeListHead(&EventsListHead); InitializeCriticalSection(&ListsLock); if (!(pFISH_THREAD = CreateFISH_THREAD(pszFileCreated,nLineCreated))) { logmsg("** FishHangInit: CreateFISH_THREAD failed\n"); exit(-1); } pFISH_THREAD->dwThreadID = GetCurrentThreadId(); InsertListTail(&ThreadsListHead,&pFISH_THREAD->ThreadListLink); } ///////////////////////////////////////////////////////////////////////////// // Indicate we're about to exit... (disables some error checking) DLL_EXPORT void FishHangAtExit() { bFishHangAtExit = TRUE; } ///////////////////////////////////////////////////////////////////////////// // Internal abort function... #define FishHangAbort(file,line) \ { \ FishHangAtExit(); /* (disable further error checking) */ \ UnlockFishHang(); /* (prevent deadlocking ourselves!) */ \ logmsg("** FishHangAbort called from %s(%d)\n",(file),(line)); \ Sleep(100); /* (give system time to display messages) */ \ exit(-1); /* (immediately terminate entire process) */ \ } ///////////////////////////////////////////////////////////////////////////// FISH_THREAD* CreateFISH_THREAD ( const char* pszFileCreated, // source file that created it; const int nLineCreated // line number of source file; ) { FISH_THREAD* pFISH_THREAD = malloc(sizeof(FISH_THREAD)); if (!pFISH_THREAD) return NULL; GetSystemTime(&pFISH_THREAD->timeCreated); FIXFILENAME(pszFileCreated); pFISH_THREAD->dwCreatingThreadID = GetCurrentThreadId(); pFISH_THREAD->pszFileCreated = pszFileCreated; pFISH_THREAD->nLineCreated = nLineCreated; GetSystemTime(&pFISH_THREAD->timeWaiting); InitializeListLink(&pFISH_THREAD->ThreadListLink); InitializeListHead(&pFISH_THREAD->ThreadLockListHead); pFISH_THREAD->dwThreadID = 0; pFISH_THREAD->bWaitingForLock = FALSE; pFISH_THREAD->bTryingForLock = FALSE; pFISH_THREAD->bWaitingForEvent = FALSE; pFISH_THREAD->pWhatWaiting = NULL; pFISH_THREAD->pszFileWaiting = NULL; pFISH_THREAD->nLineWaiting = 0; return pFISH_THREAD; } ///////////////////////////////////////////////////////////////////////////// FISH_LOCK* CreateFISH_LOCK ( const char* pszFileCreated, // source file that created it; const int nLineCreated // line number of source file; ) { FISH_LOCK* pFISH_LOCK = malloc(sizeof(FISH_LOCK)); if (!pFISH_LOCK) return NULL; GetSystemTime(&pFISH_LOCK->timeCreated); FIXFILENAME(pszFileCreated); pFISH_LOCK->dwCreatingThreadID = GetCurrentThreadId(); pFISH_LOCK->pszFileCreated = pszFileCreated; pFISH_LOCK->nLineCreated = nLineCreated; InitializeListLink(&pFISH_LOCK->LockListLink); InitializeListLink(&pFISH_LOCK->ThreadLockListLink); pFISH_LOCK->pLock = NULL; pFISH_LOCK->pOwningThread = NULL; pFISH_LOCK->nLockedDepth = 0; return pFISH_LOCK; } ///////////////////////////////////////////////////////////////////////////// FISH_EVENT* CreateFISH_EVENT ( const char* pszFileCreated, // source file that created it; const int nLineCreated // line number of source file; ) { FISH_EVENT* pFISH_EVENT = malloc(sizeof(FISH_EVENT)); if (!pFISH_EVENT) return NULL; GetSystemTime(&pFISH_EVENT->timeCreated); FIXFILENAME(pszFileCreated); pFISH_EVENT->dwCreatingThreadID = GetCurrentThreadId(); pFISH_EVENT->pszFileCreated = pszFileCreated; pFISH_EVENT->nLineCreated = nLineCreated; GetSystemTime(&pFISH_EVENT->timeSet); GetSystemTime(&pFISH_EVENT->timeReset); pFISH_EVENT->hEvent = NULL; pFISH_EVENT->pWhoSet = NULL; pFISH_EVENT->pszFileSet = NULL; pFISH_EVENT->nLineSet = 0; pFISH_EVENT->pWhoReset = NULL; pFISH_EVENT->pszFileReset = NULL; pFISH_EVENT->nLineReset = 0; InitializeListLink(&pFISH_EVENT->EventsListLink); return pFISH_EVENT; } ///////////////////////////////////////////////////////////////////////////// // NOTE! Global lock must be held before calling this function! FISH_THREAD* FindFISH_THREAD ( DWORD dwThreadID // thread id ) { FISH_THREAD* pFISH_THREAD; LIST_ENTRY* pListEntry = ThreadsListHead.Flink; while (pListEntry != &ThreadsListHead) { pFISH_THREAD = CONTAINING_RECORD(pListEntry,FISH_THREAD,ThreadListLink); pListEntry = pListEntry->Flink; if (pFISH_THREAD->dwThreadID != dwThreadID) continue; return pFISH_THREAD; } return NULL; } ///////////////////////////////////////////////////////////////////////////// // NOTE! Global lock must be held before calling this function! FISH_LOCK* FindFISH_LOCK ( LPCRITICAL_SECTION lpCriticalSection // ptr to actual lock (CRITICAL_SECTION) ) { FISH_LOCK* pFISH_LOCK; LIST_ENTRY* pListEntry = LocksListHead.Flink; while (pListEntry != &LocksListHead) { pFISH_LOCK = CONTAINING_RECORD(pListEntry,FISH_LOCK,LockListLink); pListEntry = pListEntry->Flink; if (pFISH_LOCK->pLock != lpCriticalSection) continue; return pFISH_LOCK; } return NULL; } ///////////////////////////////////////////////////////////////////////////// // NOTE! Global lock must be held before calling this function! FISH_EVENT* FindFISH_EVENT ( HANDLE hEvent // handle of actual event ) { FISH_EVENT* pFISH_EVENT; LIST_ENTRY* pListEntry = EventsListHead.Flink; while (pListEntry != &EventsListHead) { pFISH_EVENT = CONTAINING_RECORD(pListEntry,FISH_EVENT,EventsListLink); pListEntry = pListEntry->Flink; if (pFISH_EVENT->hEvent != hEvent) continue; return pFISH_EVENT; } return NULL; } ///////////////////////////////////////////////////////////////////////////// // NOTE! Global lock must be held before calling this function! char PrintFISH_THREADBuffer[4096]; char* PrintFISH_THREAD ( FISH_THREAD* pFISH_THREAD // ptr to thread to be printed ) { LIST_ENTRY* pListEntry; FISH_THREAD* ThreadListLink; FISH_LOCK* ThreadLockListLink; pListEntry = pFISH_THREAD->ThreadListLink.Flink; if (pListEntry != &ThreadsListHead) { ThreadListLink = CONTAINING_RECORD(pListEntry,FISH_THREAD,ThreadListLink); } else ThreadListLink = (FISH_THREAD*) &ThreadsListHead; pListEntry = pFISH_THREAD->ThreadLockListHead.Flink; if (pListEntry != &pFISH_THREAD->ThreadLockListHead) { ThreadLockListLink = CONTAINING_RECORD(pListEntry,FISH_LOCK,ThreadLockListLink); } else { ThreadLockListLink = NULL; } snprintf(PrintFISH_THREADBuffer,sizeof(PrintFISH_THREADBuffer), "THREAD @ %8.8X\n" " bWaitingForLock = %s\n" " bTryingForLock = %s\n" " bWaitingForEvent = %s\n" " pWhatWaiting = %8.8X\n" " pszFileWaiting = %s\n" " nLineWaiting = %d\n" " timeWaiting = %2.2d:%2.2d:%2.2d.%3.3d\n" " dwThreadID = %8.8X\n" " ThreadLockListLink = %8.8X\n" " dwCreatingThreadID = %8.8X\n" " timeCreated = %2.2d:%2.2d:%2.2d.%3.3d\n" " pszFileCreated = %s\n" " nLineCreated = %d\n" " ThreadListLink = %8.8X\n", (int)pFISH_THREAD, pFISH_THREAD->bWaitingForLock ? "TRUE" : "FALSE", pFISH_THREAD->bTryingForLock ? "TRUE" : "FALSE", pFISH_THREAD->bWaitingForEvent ? "TRUE" : "FALSE", (int)pFISH_THREAD->pWhatWaiting, pFISH_THREAD->pszFileWaiting, (int)pFISH_THREAD->nLineWaiting, (int)pFISH_THREAD->timeWaiting.wHour, (int)pFISH_THREAD->timeWaiting.wMinute, (int)pFISH_THREAD->timeWaiting.wSecond, (int)pFISH_THREAD->timeWaiting.wMilliseconds, (int)pFISH_THREAD->dwThreadID, (int)ThreadLockListLink, (int)pFISH_THREAD->dwCreatingThreadID, (int)pFISH_THREAD->timeCreated.wHour, (int)pFISH_THREAD->timeCreated.wMinute, (int)pFISH_THREAD->timeCreated.wSecond, (int)pFISH_THREAD->timeCreated.wMilliseconds, pFISH_THREAD->pszFileCreated, (int)pFISH_THREAD->nLineCreated, (int)ThreadListLink ); PrintFISH_THREADBuffer[ sizeof(PrintFISH_THREADBuffer) - 1 ] = 0; return PrintFISH_THREADBuffer; } ///////////////////////////////////////////////////////////////////////////// // NOTE! Global lock must be held before calling this function! char PrintFISH_LOCKBuffer[4096]; char* PrintFISH_LOCK ( FISH_LOCK* pFISH_LOCK // ptr to lock to be printed ) { LIST_ENTRY* pListEntry; FISH_LOCK* LockListLink; FISH_LOCK* ThreadLockListLink; FISH_THREAD* pOwningThread; pListEntry = pFISH_LOCK->LockListLink.Flink; if (pListEntry != &LocksListHead) { LockListLink = CONTAINING_RECORD(pListEntry,FISH_LOCK,LockListLink); } else LockListLink = (FISH_LOCK*) &LocksListHead; pOwningThread = pFISH_LOCK->pOwningThread; ThreadLockListLink = (FISH_LOCK*) pFISH_LOCK->ThreadLockListLink.Flink; if (pOwningThread) { if ((LIST_ENTRY*)ThreadLockListLink == &pOwningThread->ThreadLockListHead) { ThreadLockListLink = (FISH_LOCK*) pOwningThread->ThreadLockListHead.Flink; } pListEntry = (LIST_ENTRY*) ThreadLockListLink; ThreadLockListLink = CONTAINING_RECORD(pListEntry,FISH_LOCK,ThreadLockListLink); } else { if (ThreadLockListLink) { logmsg("** PrintFISH_LOCK: **OOPS!** " "Lock %8.8X not owned, " "but ThreadLockListLink not NULL!\n", (int)pFISH_LOCK ); } } snprintf(PrintFISH_LOCKBuffer,sizeof(PrintFISH_LOCKBuffer), "LOCK @ %8.8X\n" " pOwningThread = %8.8X\n" " nLockedDepth = %d\n" " ThreadLockListLink = %8.8X\n" " dwCreatingThreadID = %8.8X\n" " timeCreated = %2.2d:%2.2d:%2.2d.%3.3d\n" " pszFileCreated = %s\n" " nLineCreated = %d\n" " pLock = %8.8X\n" " LockListLink = %8.8X\n", (int)pFISH_LOCK, (int)pOwningThread, (int)pFISH_LOCK->nLockedDepth, (int)ThreadLockListLink, (int)pFISH_LOCK->dwCreatingThreadID, (int)pFISH_LOCK->timeCreated.wHour, (int)pFISH_LOCK->timeCreated.wMinute, (int)pFISH_LOCK->timeCreated.wSecond, (int)pFISH_LOCK->timeCreated.wMilliseconds, pFISH_LOCK->pszFileCreated, (int)pFISH_LOCK->nLineCreated, (int)pFISH_LOCK->pLock, (int)LockListLink ); PrintFISH_LOCKBuffer[ sizeof(PrintFISH_LOCKBuffer) - 1 ] = 0; return PrintFISH_LOCKBuffer; } ///////////////////////////////////////////////////////////////////////////// // NOTE! Global lock must be held before calling this function! char PrintFISH_EVENTBuffer[4096]; char* PrintFISH_EVENT ( FISH_EVENT* pFISH_EVENT // ptr to event to be printed ) { LIST_ENTRY* pListEntry; FISH_EVENT* EventsListLink; pListEntry = pFISH_EVENT->EventsListLink.Flink; if (pListEntry != &EventsListHead) { EventsListLink = CONTAINING_RECORD(pListEntry,FISH_EVENT,EventsListLink); } else EventsListLink = (FISH_EVENT*) &EventsListHead; snprintf(PrintFISH_EVENTBuffer,sizeof(PrintFISH_EVENTBuffer), "EVENT @ %8.8X\n" " timeSet = %2.2d:%2.2d:%2.2d.%3.3d\n" " pszFileSet = %s\n" " nLineSet = %d\n" " pWhoSet = %8.8X\n" " timeReset = %2.2d:%2.2d:%2.2d.%3.3d\n" " pszFileReset = %s\n" " nLineReset = %d\n" " pWhoReset = %8.8X\n" " timeCreated = %2.2d:%2.2d:%2.2d.%3.3d\n" " pszFileCreated = %s\n" " nLineCreated = %d\n" " dwCreatingThreadID = %8.8X\n" " hEvent = %8.8X\n" " EventsListLink = %8.8X\n", (int)pFISH_EVENT, (int)pFISH_EVENT->timeSet.wHour, (int)pFISH_EVENT->timeSet.wMinute, (int)pFISH_EVENT->timeSet.wSecond, (int)pFISH_EVENT->timeSet.wMilliseconds, pFISH_EVENT->pszFileSet, (int)pFISH_EVENT->nLineSet, (int)pFISH_EVENT->pWhoSet, (int)pFISH_EVENT->timeReset.wHour, (int)pFISH_EVENT->timeReset.wMinute, (int)pFISH_EVENT->timeReset.wSecond, (int)pFISH_EVENT->timeReset.wMilliseconds, pFISH_EVENT->pszFileReset, (int)pFISH_EVENT->nLineReset, (int)pFISH_EVENT->pWhoReset, (int)pFISH_EVENT->timeCreated.wHour, (int)pFISH_EVENT->timeCreated.wMinute, (int)pFISH_EVENT->timeCreated.wSecond, (int)pFISH_EVENT->timeCreated.wMilliseconds, pFISH_EVENT->pszFileCreated, (int)pFISH_EVENT->nLineCreated, (int)pFISH_EVENT->dwCreatingThreadID, (int)pFISH_EVENT->hEvent, (int)EventsListLink ); PrintFISH_EVENTBuffer[ sizeof(PrintFISH_EVENTBuffer) - 1 ] = 0; return PrintFISH_EVENTBuffer; } ///////////////////////////////////////////////////////////////////////////// // NOTE! Global lock must be held before calling this function! void PrintAllFISH_THREADs() { LIST_ENTRY* pListEntry; FISH_THREAD* pFISH_THREAD; pListEntry = ThreadsListHead.Flink; if (pListEntry != &ThreadsListHead) { pFISH_THREAD = CONTAINING_RECORD(pListEntry,FISH_THREAD,ThreadListLink); } else pFISH_THREAD = (FISH_THREAD*) &ThreadsListHead; logmsg("\nTHREAD LIST ANCHOR @ %8.8X --> %8.8X\n\n", (int)&ThreadsListHead,(int)pFISH_THREAD); while (pListEntry != &ThreadsListHead) { pFISH_THREAD = CONTAINING_RECORD(pListEntry,FISH_THREAD,ThreadListLink); pListEntry = pListEntry->Flink; logmsg("%s\n",PrintFISH_THREAD(pFISH_THREAD)); } } ///////////////////////////////////////////////////////////////////////////// // NOTE! Global lock must be held before calling this function! void PrintAllFISH_LOCKs() { LIST_ENTRY* pListEntry; FISH_LOCK* pFISH_LOCK; pListEntry = LocksListHead.Flink; if (pListEntry != &LocksListHead) { pFISH_LOCK = CONTAINING_RECORD(pListEntry,FISH_LOCK,LockListLink); } else pFISH_LOCK = (FISH_LOCK*) &LocksListHead; logmsg("\nLOCK LIST ANCHOR @ %8.8X --> %8.8X\n\n", (int)&LocksListHead,(int)pFISH_LOCK); while (pListEntry != &LocksListHead) { pFISH_LOCK = CONTAINING_RECORD(pListEntry,FISH_LOCK,LockListLink); pListEntry = pListEntry->Flink; logmsg("%s\n",PrintFISH_LOCK(pFISH_LOCK)); } } ///////////////////////////////////////////////////////////////////////////// // NOTE! Global lock must be held before calling this function! void PrintAllFISH_EVENTs() { LIST_ENTRY* pListEntry; FISH_EVENT* pFISH_EVENT; pListEntry = EventsListHead.Flink; if (pListEntry != &EventsListHead) { pFISH_EVENT = CONTAINING_RECORD(pListEntry,FISH_EVENT,EventsListLink); } else pFISH_EVENT = (FISH_EVENT*) &EventsListHead; logmsg("\nEVENT LIST ANCHOR @ %8.8X --> %8.8X\n\n", (int)&EventsListHead,(int)pFISH_EVENT); while (pListEntry != &EventsListHead) { pFISH_EVENT = CONTAINING_RECORD(pListEntry,FISH_EVENT,EventsListLink); pListEntry = pListEntry->Flink; logmsg("%s\n",PrintFISH_EVENT(pFISH_EVENT)); } } ///////////////////////////////////////////////////////////////////////////// DLL_EXPORT HANDLE FishHang_CreateThread ( const char* pszFileCreated, // source file that created it const int nLineCreated, // line number of source file LPSECURITY_ATTRIBUTES lpThreadAttributes, // pointer to security attributes DWORD dwStackSize, // initial thread stack size LPTHREAD_START_ROUTINE lpStartAddress, // pointer to thread function LPVOID lpParameter, // argument for new thread DWORD dwCreationFlags, // creation flags LPDWORD lpThreadId // pointer to receive thread ID ) { FISH_THREAD* pFISH_THREAD; HANDLE hThread; FIXFILENAME(pszFileCreated); if (!(pFISH_THREAD = CreateFISH_THREAD(pszFileCreated,nLineCreated))) return NULL; #ifdef _MSVC_ hThread = (HANDLE) _beginthreadex #else // (Cygwin) hThread = CreateThread #endif ( lpThreadAttributes, // pointer to security attributes dwStackSize, // initial thread stack size lpStartAddress, // pointer to thread function lpParameter, // argument for new thread dwCreationFlags, // creation flags lpThreadId // pointer to receive thread ID ); if (hThread) { pFISH_THREAD->dwThreadID = *lpThreadId; LockFishHang(); InsertListTail(&ThreadsListHead,&pFISH_THREAD->ThreadListLink); UnlockFishHang(); } else { free(pFISH_THREAD); } return hThread; } ///////////////////////////////////////////////////////////////////////////// DLL_EXPORT void FishHang_InitializeCriticalSection ( const char* pszFileCreated, // source file that created it const int nLineCreated, // line number of source file LPCRITICAL_SECTION lpCriticalSection // address of critical section object ) { FISH_LOCK* pFISH_LOCK; FIXFILENAME(pszFileCreated); LockFishHang(); pFISH_LOCK = FindFISH_LOCK(lpCriticalSection); if (pFISH_LOCK) { logmsg( "** ERROR ** FISH_LOCK %8.8X already initialized!\n", (int)pFISH_LOCK); logmsg("%s(%d)\n",pszFileCreated,nLineCreated); logmsg("%s\n",PrintFISH_LOCK(pFISH_LOCK)); FishHangAbort(pszFileCreated,nLineCreated); } if (!(pFISH_LOCK = CreateFISH_LOCK(pszFileCreated,nLineCreated))) { logmsg("** FishHang_InitializeCriticalSection: CreateFISH_LOCK failed!\n"); FishHangAbort(pszFileCreated,nLineCreated); } InitializeCriticalSection(lpCriticalSection); pFISH_LOCK->pLock = lpCriticalSection; InsertListTail(&LocksListHead,&pFISH_LOCK->LockListLink); UnlockFishHang(); } ///////////////////////////////////////////////////////////////////////////// // NOTE! Global lock must be held before calling this function! BOOL GetThreadAndLockPtrs ( FISH_THREAD** ppFISH_THREAD, FISH_LOCK** ppFISH_LOCK, LPCRITICAL_SECTION lpCriticalSection // address of critical section object ) { *ppFISH_THREAD = FindFISH_THREAD(GetCurrentThreadId()); *ppFISH_LOCK = FindFISH_LOCK(lpCriticalSection); if (*ppFISH_THREAD && *ppFISH_LOCK) return TRUE; if (!*ppFISH_THREAD) { logmsg( "** GetThreadAndLockPtrs: FindFISH_THREAD(%8.8X) failed!\n", (int)GetCurrentThreadId()); PrintAllFISH_THREADs(); // (caller will abort) } if (!*ppFISH_LOCK) { logmsg( "** GetThreadAndLockPtrs: FindFISH_LOCK(%8.8X) failed!\n", (int)lpCriticalSection); PrintAllFISH_LOCKs(); // (caller will abort) } return FALSE; } ///////////////////////////////////////////////////////////////////////////// // NOTE! Global lock must be held before calling this function! BOOL GetThreadAndEventPtrs ( FISH_THREAD** ppFISH_THREAD, FISH_EVENT** ppFISH_EVENT, HANDLE hEvent // handle to event object ) { *ppFISH_THREAD = FindFISH_THREAD(GetCurrentThreadId()); *ppFISH_EVENT = FindFISH_EVENT(hEvent); if (*ppFISH_THREAD && *ppFISH_EVENT) return TRUE; if (!*ppFISH_THREAD) { logmsg( "** GetThreadAndEventPtrs: FindFISH_THREAD(%8.8X) failed!\n", (int)GetCurrentThreadId()); PrintAllFISH_THREADs(); // (caller will abort) } if (!*ppFISH_EVENT) { logmsg( "** GetThreadAndEventPtrs: FindFISH_EVENT(%8.8X) failed!\n", (int)hEvent); PrintAllFISH_EVENTs(); // (caller will abort) } return FALSE; } ///////////////////////////////////////////////////////////////////////////// // NOTE! Global lock must be held before calling this function! BOOL PrintDeadlock ( FISH_THREAD* pForThisFISH_THREAD, // thread to check const char* pszFile, // source file (may be NULL) const int nLine // line number of source file ) { LIST_ENTRY* pListEntry; FISH_THREAD* pFISH_THREAD; FISH_LOCK* pWhatWaiting; FISH_THREAD* pOwningThread; FIXFILENAME(pszFile); // Technique: for each thread that is waiting for a lock, chase the lock owner // chain to see if it leads back to the thread we started with... pListEntry = ThreadsListHead.Flink; while (pListEntry != &ThreadsListHead) { pFISH_THREAD = CONTAINING_RECORD(pListEntry,FISH_THREAD,ThreadListLink); pListEntry = pListEntry->Flink; // (go on to next entry ahead of time) // If we're only interested in checking if a *specific* thread is deadlocked // (instead of *any* thread), then skip past this thread if it isn't the one // we're interested in... if (pForThisFISH_THREAD && pFISH_THREAD != pForThisFISH_THREAD) continue; // If the thread isn't waiting for a lock, then no deadlock possible; skip it. if (!pFISH_THREAD->bWaitingForLock) { // If the caller was only interested in checking this one thread // then since it's not waiting for any locks, we're done... if (pForThisFISH_THREAD) return FALSE; // (that was easy!) continue; } // This thread (pFISH_THREAD) is waiting for a lock. Chase the lock owner // chain to see if it eventually leads back to the current thread. If so, // then we've found a deadlock... // (I.e. If this thread A is waiting for lock X and lock X is owned by thread // B and thread B is itself waiting for lock Y and lock Y is owned by thread C // and thread C is itself waiting for lock Z and lock Z is owned by thread A // (the thread we started with), then we have found a deadlock situation. If // any of the threads in the chain are not waiting for a lock. then of course // no deadlock is possible so we simply move on to the next thread). // Get a pointer to the lock that this thread is waiting for... pWhatWaiting = (FISH_LOCK*) pFISH_THREAD->pWhatWaiting; for (;;) { // (Note: if the pOwningThread variable is NULL (i.e. lock not currently // owned by anyone), then the thread isn't actually waiting for a lock at // all. All a NULL pOwningThread variable means is the thread was simply // interrupted in the middle of its FishHang_EnterCriticalSection call, // and if had NOT been interrupted, it WOULD have grabbed that lock.) // Grab the owner of the lock the current thread is trying to acquire... pOwningThread = pWhatWaiting->pOwningThread; // (next owner in chain) if (!pOwningThread || // (if there is no lock owner, or) !pOwningThread->bWaitingForLock) // (owner not waiting for any locks) break; // (then go on to next thread) // Grab which lock the current lock-owner is trying to acquire... pWhatWaiting = (FISH_LOCK*) pOwningThread->pWhatWaiting; // If we've circled around such that the current lock-owner is the very // same thread we began with, then we've detected a deadlock situation... if (pOwningThread != pFISH_THREAD) // (back to where we started?) continue; // (nope, go on to next owner) logmsg(">>>>>>> Deadlock detected! <<<<<<<\n"); if (pszFile) logmsg("%s(%d)\n",pszFile,nLine); logmsg("\n"); // Now do the same thing we already just did, but THIS time print // each thread that's participating in the deadlock and the lock // they're each waiting on... pWhatWaiting = (FISH_LOCK*) pFISH_THREAD->pWhatWaiting; logmsg("%s",PrintFISH_THREAD(pFISH_THREAD)); logmsg("%s",PrintFISH_LOCK(pWhatWaiting)); do { logmsg("\n"); pOwningThread = pWhatWaiting->pOwningThread; pWhatWaiting = (FISH_LOCK*) pOwningThread->pWhatWaiting; logmsg("%s",PrintFISH_THREAD(pOwningThread)); logmsg("%s",PrintFISH_LOCK(pWhatWaiting)); } while (pWhatWaiting->pOwningThread != pFISH_THREAD); logmsg("\n"); return TRUE; // (deadlock detected!) } } return FALSE; // (no deadlock detected) } ///////////////////////////////////////////////////////////////////////////// DLL_EXPORT void FishHang_EnterCriticalSection ( const char* pszFileWaiting, // source file that attempted it const int nLineWaiting, // line number of source file LPCRITICAL_SECTION lpCriticalSection // address of critical section object ) { FISH_THREAD* pFISH_THREAD; FISH_LOCK* pFISH_LOCK; FIXFILENAME(pszFileWaiting); LockFishHang(); if (!GetThreadAndLockPtrs(&pFISH_THREAD,&pFISH_LOCK,lpCriticalSection)) FishHangAbort(pszFileWaiting,nLineWaiting); pFISH_THREAD->bWaitingForLock = TRUE; pFISH_THREAD->bTryingForLock = FALSE; pFISH_THREAD->pWhatWaiting = pFISH_LOCK; pFISH_THREAD->pszFileWaiting = pszFileWaiting; pFISH_THREAD->nLineWaiting = nLineWaiting; GetSystemTime(&pFISH_THREAD->timeWaiting); if (PrintDeadlock(pFISH_THREAD,pszFileWaiting,nLineWaiting)) FishHangAbort(pszFileWaiting,nLineWaiting); UnlockFishHang(); EnterCriticalSection(lpCriticalSection); LockFishHang(); pFISH_THREAD->bWaitingForLock = FALSE; pFISH_THREAD->bTryingForLock = FALSE; if (pFISH_LOCK->pOwningThread != pFISH_THREAD) { pFISH_LOCK->pOwningThread = pFISH_THREAD; pFISH_LOCK->nLockedDepth = 1; InsertListTail(&pFISH_THREAD->ThreadLockListHead,&pFISH_LOCK->ThreadLockListLink); } else { pFISH_LOCK->nLockedDepth++; } UnlockFishHang(); } ///////////////////////////////////////////////////////////////////////////// DLL_EXPORT BOOL FishHang_TryEnterCriticalSection ( const char* pszFileWaiting, // source file that attempted it const int nLineWaiting, // line number of source file LPCRITICAL_SECTION lpCriticalSection // address of critical section object ) { FISH_THREAD* pFISH_THREAD; FISH_LOCK* pFISH_LOCK; BOOL bSuccess; FIXFILENAME(pszFileWaiting); LockFishHang(); if (!GetThreadAndLockPtrs(&pFISH_THREAD,&pFISH_LOCK,lpCriticalSection)) FishHangAbort(pszFileWaiting,nLineWaiting); pFISH_THREAD->bWaitingForLock = FALSE; pFISH_THREAD->bTryingForLock = TRUE; pFISH_THREAD->pWhatWaiting = pFISH_LOCK; pFISH_THREAD->pszFileWaiting = pszFileWaiting; pFISH_THREAD->nLineWaiting = nLineWaiting; GetSystemTime(&pFISH_THREAD->timeWaiting); if (PrintDeadlock(pFISH_THREAD,pszFileWaiting,nLineWaiting)) FishHangAbort(pszFileWaiting,nLineWaiting); UnlockFishHang(); bSuccess = TryEnterCriticalSection(lpCriticalSection); LockFishHang(); pFISH_THREAD->bTryingForLock = FALSE; if (bSuccess) { pFISH_THREAD->bWaitingForLock = FALSE; if (pFISH_LOCK->pOwningThread != pFISH_THREAD) { pFISH_LOCK->pOwningThread = pFISH_THREAD; pFISH_LOCK->nLockedDepth = 1; InsertListTail(&pFISH_THREAD->ThreadLockListHead,&pFISH_LOCK->ThreadLockListLink); } else { pFISH_LOCK->nLockedDepth++; } } UnlockFishHang(); return bSuccess; } ///////////////////////////////////////////////////////////////////////////// DLL_EXPORT void FishHang_LeaveCriticalSection ( const char* pszFileReleasing, // source file that attempted it const int nLineReleasing, // line number of source file LPCRITICAL_SECTION lpCriticalSection // address of critical section object ) { FISH_THREAD* pFISH_THREAD; FISH_LOCK* pFISH_LOCK; FIXFILENAME(pszFileReleasing); LockFishHang(); if (!GetThreadAndLockPtrs(&pFISH_THREAD,&pFISH_LOCK,lpCriticalSection)) FishHangAbort(pszFileReleasing,nLineReleasing); if (!bFishHangAtExit && pFISH_LOCK->pOwningThread != pFISH_THREAD) { logmsg( "\n** ERROR ** FISH_THREAD %8.8X " "releasing FISH_LOCK %8.8X " "owned by FISH_THREAD %8.8X!\n" "** Here's the culprit! --> %s(%d)\n", (int)pFISH_THREAD, (int)pFISH_LOCK, (int)pFISH_LOCK->pOwningThread, pszFileReleasing,nLineReleasing ); RemoveListEntry(&pFISH_THREAD->ThreadListLink); InsertListHead(&ThreadsListHead,&pFISH_THREAD->ThreadListLink); PrintAllFISH_THREADs(); if (pFISH_LOCK->pOwningThread) { RemoveListEntry(&pFISH_LOCK->ThreadLockListLink); InsertListHead(&pFISH_LOCK->pOwningThread->ThreadLockListHead,&pFISH_LOCK->ThreadLockListLink); } PrintAllFISH_LOCKs(); FishHangAbort(pszFileReleasing,nLineReleasing); } else { pFISH_LOCK->nLockedDepth--; } if (pFISH_LOCK->nLockedDepth <= 0) { if (pFISH_LOCK->nLockedDepth < 0) { logmsg( "\n** ERROR ** FISH_THREAD %8.8X " "attempted to release FISH_LOCK %8.8X " "one too many times!?!\n" "** Here's the culprit! --> %s(%d)\n", (int)pFISH_THREAD, (int)pFISH_LOCK, pszFileReleasing,nLineReleasing ); RemoveListEntry(&pFISH_THREAD->ThreadListLink); InsertListHead(&ThreadsListHead,&pFISH_THREAD->ThreadListLink); PrintAllFISH_THREADs(); if (pFISH_LOCK->pOwningThread) { RemoveListEntry(&pFISH_LOCK->ThreadLockListLink); InsertListHead(&pFISH_LOCK->pOwningThread->ThreadLockListHead,&pFISH_LOCK->ThreadLockListLink); } PrintAllFISH_LOCKs(); FishHangAbort(pszFileReleasing,nLineReleasing); } pFISH_LOCK->pOwningThread = NULL; RemoveListEntry(&pFISH_LOCK->ThreadLockListLink); InitializeListLink(&pFISH_LOCK->ThreadLockListLink); } UnlockFishHang(); LeaveCriticalSection(lpCriticalSection); } ///////////////////////////////////////////////////////////////////////////// DLL_EXPORT HANDLE FishHang_CreateEvent ( const char* pszFileCreated, // source file that created it const int nLineCreated, // line number of source file LPSECURITY_ATTRIBUTES lpEventAttributes, // pointer to security attributes BOOL bManualReset, // flag for manual-reset event BOOL bInitialState, // flag for initial state LPCTSTR lpName // pointer to event-object name ) { FISH_EVENT* pFISH_EVENT; HANDLE hEvent; FIXFILENAME(pszFileCreated); if (!(pFISH_EVENT = CreateFISH_EVENT(pszFileCreated,nLineCreated))) { logmsg("** FishHang_CreateEvent: CreateFISH_EVENT failed\n"); exit(-1); } if (!(hEvent = CreateEvent(lpEventAttributes,bManualReset,bInitialState,lpName))) { free(pFISH_EVENT); } else { pFISH_EVENT->hEvent = hEvent; LockFishHang(); InsertListTail(&EventsListHead,&pFISH_EVENT->EventsListLink); UnlockFishHang(); } return hEvent; } ///////////////////////////////////////////////////////////////////////////// DLL_EXPORT BOOL FishHang_SetEvent ( const char* pszFileSet, // source file that set it const int nLineSet, // line number of source file HANDLE hEvent // handle to event object ) { FISH_THREAD* pFISH_THREAD; FISH_EVENT* pFISH_EVENT; FIXFILENAME(pszFileSet); LockFishHang(); if (!GetThreadAndEventPtrs(&pFISH_THREAD,&pFISH_EVENT,hEvent)) FishHangAbort(pszFileSet,nLineSet); GetSystemTime(&pFISH_EVENT->timeSet); pFISH_EVENT->pWhoSet = pFISH_THREAD; pFISH_EVENT->pszFileSet = pszFileSet; pFISH_EVENT->nLineSet = nLineSet; UnlockFishHang(); return SetEvent(hEvent); } ///////////////////////////////////////////////////////////////////////////// DLL_EXPORT BOOL FishHang_ResetEvent ( const char* pszFileReset, // source file that reset it const int nLineReset, // line number of source file HANDLE hEvent // handle to event object ) { FISH_THREAD* pFISH_THREAD; FISH_EVENT* pFISH_EVENT; FIXFILENAME(pszFileReset); LockFishHang(); if (!GetThreadAndEventPtrs(&pFISH_THREAD,&pFISH_EVENT,hEvent)) FishHangAbort(pszFileReset,nLineReset); GetSystemTime(&pFISH_EVENT->timeReset); pFISH_EVENT->pWhoReset = pFISH_THREAD; pFISH_EVENT->pszFileReset = pszFileReset; pFISH_EVENT->nLineReset = nLineReset; UnlockFishHang(); return ResetEvent(hEvent); } ///////////////////////////////////////////////////////////////////////////// DLL_EXPORT BOOL FishHang_PulseEvent ( const char* pszFilePosted, // source file that signalled it const int nLinePosted, // line number of source file HANDLE hEvent // handle to event object ) { FISH_THREAD* pFISH_THREAD; FISH_EVENT* pFISH_EVENT; FIXFILENAME(pszFilePosted); LockFishHang(); if (!GetThreadAndEventPtrs(&pFISH_THREAD,&pFISH_EVENT,hEvent)) FishHangAbort(pszFilePosted,nLinePosted); GetSystemTime(&pFISH_EVENT->timeSet); GetSystemTime(&pFISH_EVENT->timeReset); pFISH_EVENT->pWhoSet = pFISH_THREAD; pFISH_EVENT->pWhoReset = pFISH_THREAD; pFISH_EVENT->pszFileSet = pszFilePosted; pFISH_EVENT->pszFileReset = pszFilePosted; pFISH_EVENT->nLineSet = nLinePosted; pFISH_EVENT->nLineReset = nLinePosted; UnlockFishHang(); return PulseEvent(hEvent); } ///////////////////////////////////////////////////////////////////////////// DLL_EXPORT BOOL FishHang_CloseHandle // ** NOTE: only events for right now ** ( const char* pszFileClosed, // source file that closed it const int nLineClosed, // line number of source file HANDLE hEvent // handle to event object ) { FISH_THREAD* pThisFISH_THREAD; FISH_EVENT* pFISH_EVENT; LIST_ENTRY* pListEntry; FISH_THREAD* pWaitingFISH_THREAD; FIXFILENAME(pszFileClosed); LockFishHang(); if (!GetThreadAndEventPtrs(&pThisFISH_THREAD,&pFISH_EVENT,hEvent)) FishHangAbort(pszFileClosed,nLineClosed); pListEntry = ThreadsListHead.Flink; while (pListEntry != &ThreadsListHead) { pWaitingFISH_THREAD = CONTAINING_RECORD(pListEntry,FISH_THREAD,ThreadListLink); pListEntry = pListEntry->Flink; if (!pWaitingFISH_THREAD->bWaitingForEvent || pWaitingFISH_THREAD->pWhatWaiting != pFISH_EVENT) continue; logmsg( "\n** ERROR ** %s(%d); FISH_THREAD %8.8X " "is closing FISH_EVENT %8.8X " "that FISH_THREAD %8.8X is still waiting on!\n", pszFileClosed,nLineClosed,(int)pThisFISH_THREAD, (int)pFISH_EVENT, (int)pWaitingFISH_THREAD ); logmsg("\n%s\n%s\n%s\n", PrintFISH_THREAD(pThisFISH_THREAD), PrintFISH_EVENT(pFISH_EVENT), PrintFISH_THREAD(pWaitingFISH_THREAD) ); FishHangAbort(pszFileClosed,nLineClosed); } RemoveListEntry(&pFISH_EVENT->EventsListLink); free(pFISH_EVENT); UnlockFishHang(); return CloseHandle(hEvent); } ///////////////////////////////////////////////////////////////////////////// DLL_EXPORT DWORD FishHang_WaitForSingleObject // ** NOTE: only events for right now ** ( const char* pszFileWaiting, // source file that attempted it const int nLineWaiting, // line number of source file HANDLE hEvent, // handle to event to wait for DWORD dwMilliseconds // time-out interval in milliseconds ) { FISH_THREAD* pFISH_THREAD; FISH_EVENT* pFISH_EVENT; DWORD dwWaitRetCode; FIXFILENAME(pszFileWaiting); LockFishHang(); if (!GetThreadAndEventPtrs(&pFISH_THREAD,&pFISH_EVENT,hEvent)) FishHangAbort(pszFileWaiting,nLineWaiting); pFISH_THREAD->bWaitingForEvent = TRUE; pFISH_THREAD->pWhatWaiting = pFISH_EVENT; pFISH_THREAD->pszFileWaiting = pszFileWaiting; pFISH_THREAD->nLineWaiting = nLineWaiting; GetSystemTime(&pFISH_THREAD->timeWaiting); UnlockFishHang(); dwWaitRetCode = WaitForSingleObject(hEvent,dwMilliseconds); LockFishHang(); pFISH_THREAD->bWaitingForEvent = FALSE; UnlockFishHang(); return dwWaitRetCode; } ///////////////////////////////////////////////////////////////////////////// DLL_EXPORT void FishHangReport() { LockFishHang(); logmsg("\n--------------- BEGIN FishHangReport ---------------\n\n"); PrintDeadlock(NULL,NULL,0); PrintAllFISH_THREADs(); PrintAllFISH_LOCKs(); PrintAllFISH_EVENTs(); logmsg("\n---------------- END FishHangReport ----------------\n\n"); UnlockFishHang(); } ///////////////////////////////////////////////////////////////////////////// DLL_EXPORT void FishHang_DeleteCriticalSection ( const char* pszFileDeleting, // source file that's deleting it const int nLineDeleting, // line number of source file LPCRITICAL_SECTION lpCriticalSection // address of critical section object ) { FISH_THREAD* pFISH_THREAD; FISH_LOCK* pFISH_LOCK; FIXFILENAME(pszFileDeleting); LockFishHang(); if (!GetThreadAndLockPtrs(&pFISH_THREAD,&pFISH_LOCK,lpCriticalSection)) FishHangAbort(pszFileDeleting,nLineDeleting); if (!bFishHangAtExit && pFISH_LOCK->nLockedDepth) { logmsg( "\n** ERROR ** FISH_THREAD %8.8X " "deleting still-locked FISH_LOCK %8.8X!\n", (int)pFISH_THREAD, (int)pFISH_LOCK ); if (pFISH_LOCK->pOwningThread != pFISH_THREAD) { logmsg( "** ERROR ** FISH_LOCK %8.8X " "owned by FISH_THREAD %8.8X!\n", (int)pFISH_LOCK, (int)pFISH_LOCK->pOwningThread ); } logmsg("%s(%d)\n\n",pszFileDeleting,nLineDeleting); logmsg("%s\n",PrintFISH_THREAD(pFISH_THREAD)); logmsg("%s\n",PrintFISH_LOCK(pFISH_LOCK)); } RemoveListEntry(&pFISH_LOCK->LockListLink); if (pFISH_LOCK->ThreadLockListLink.Flink) { RemoveListEntry(&pFISH_LOCK->ThreadLockListLink); } free(pFISH_LOCK); UnlockFishHang(); DeleteCriticalSection(lpCriticalSection); } ///////////////////////////////////////////////////////////////////////////// DLL_EXPORT void FishHang_ExitThread ( DWORD dwExitCode // exit code for this thread ) { FISH_THREAD* pFISH_THREAD; LIST_ENTRY* pListEntry; FISH_LOCK* pFISH_LOCK; LockFishHang(); if (!(pFISH_THREAD = FindFISH_THREAD(GetCurrentThreadId()))) { UnlockFishHang(); logmsg("** FishHang_ExitThread: FindFISH_THREAD failed!\n"); if (bFishHangAtExit) _endthreadex(dwExitCode); exit(-1); } // "If a thread terminates while it has ownership of a critical // section, the state of the critical section is undefined." if (!bFishHangAtExit && !IsListEmpty(&pFISH_THREAD->ThreadLockListHead)) { logmsg( "\n** ERROR ** FISH_THREAD %8.8X " "exiting with locks still owned!\n\n", (int)pFISH_THREAD); RemoveListEntry(&pFISH_THREAD->ThreadListLink); InsertListHead(&ThreadsListHead,&pFISH_THREAD->ThreadListLink); logmsg("%s\n",PrintFISH_THREAD(pFISH_THREAD)); pListEntry = pFISH_THREAD->ThreadLockListHead.Flink; while (pListEntry != &pFISH_THREAD->ThreadLockListHead) { pFISH_LOCK = CONTAINING_RECORD(pListEntry,FISH_LOCK,ThreadLockListLink); pListEntry = pListEntry->Flink; logmsg("%s\n",PrintFISH_LOCK(pFISH_LOCK)); } } UnlockFishHang(); _endthreadex(dwExitCode); } ///////////////////////////////////////////////////////////////////////////// #endif // !defined(FISH_HANG) hercules-3.07/fishhang.h000644 000765 000765 00000031725 11143760543 016717 0ustar00jmaynardjmaynard000000 000000 //////////////////////////////////////////////////////////////////////////////////// // fishhang.h verify/debug proper Hercules LOCK handling... //////////////////////////////////////////////////////////////////////////////////// // (c) Copyright "Fish" (David B. Trout), 2002-2009. Released under the Q Public License // (http://www.hercules-390.org/herclic.html) as modifications to Hercules. //////////////////////////////////////////////////////////////////////////////////// // $Id: fishhang.h 5125 2009-01-23 12:01:44Z bernard $ // // $Log$ // Revision 1.16 2008/11/29 21:22:09 rbowler // Fix win64 warning C4267 conversion from size_t to unsigned int in fthreads.c // // Revision 1.15 2007/11/30 14:54:32 jmaynard // Changed conmicro.cx to hercules-390.org or conmicro.com, as needed. // // Revision 1.14 2007/06/23 00:04:09 ivan // Update copyright notices to include current year (2007) // // Revision 1.13 2006/12/31 12:25:26 fish // Fix "undefined reference to _beginthreadex" issue for non-MSVC (i.e. Cygwin) builds. // // Revision 1.12 2006/12/28 15:49:35 fish // Use _beginthreadex/_endthreadex instead of CreateThread/ExitThread in continuing effort to try and resolve our still existing long-standing 'errno' issue... // // Revision 1.11 2006/12/08 09:43:21 jj // Add CVS message log // #ifndef _FISHHANG_H_ #define _FISHHANG_H_ #ifndef _FISHHANG_C_ #ifndef _HUTIL_DLL_ #define FH_DLL_IMPORT DLL_IMPORT #else /* _HUTIL_DLL_ */ #define FH_DLL_IMPORT extern #endif /* _HUTIL_DLL_ */ #else #define FH_DLL_IMPORT DLL_EXPORT #endif #include ///////////////////////////////////////////////////////////////////////////// // The pttrace facility cannot be used if FISH_HANG is enabled... #if (defined(DEBUG) || defined(_DEBUG)) && !defined(FISH_HANG) #define FT_ENABLE_DEBUG_VIA_PTTRACE #endif #ifdef FT_ENABLE_DEBUG_VIA_PTTRACE #ifdef FISH_HANG #error OPTION_PTTRACE incompatible with (mutually exclusive to) FISH_HANG #endif #endif ///////////////////////////////////////////////////////////////////////////// #if defined(FISH_HANG) #ifdef FT_ENABLE_DEBUG_VIA_PTTRACE #error FISH_HANG incompatible with (mutually exclusive to) OPTION_PTTRACE #endif // fthreads makes Win32 calls on behalf of the caller and thus passes // the CALLER'S file and line# value to FishHang, whereas other Win32 // modules (such as 'w32chan.c' for example) call Win32 function on // behalf of themselves. // Thus we need two different sets of macros: one for 'fthreads.c' to // use, and another for all other Win32 modules to use, thus allowing // FishHang to accurately report the responsible party... #if defined( _FTHREADS_C_ ) #define MyInitializeCriticalSection(pCS) (FishHang_InitializeCriticalSection(pszFile,nLine,(CRITICAL_SECTION*)(pCS))) #define MyEnterCriticalSection(pCS) (FishHang_EnterCriticalSection(pszFile,nLine,(CRITICAL_SECTION*)(pCS))) #define MyTryEnterCriticalSection(pCS) (FishHang_TryEnterCriticalSection(pszFile,nLine,(CRITICAL_SECTION*)(pCS))) #define MyLeaveCriticalSection(pCS) (FishHang_LeaveCriticalSection(pszFile,nLine,(CRITICAL_SECTION*)(pCS))) #define MyDeleteCriticalSection(pCS) (FishHang_DeleteCriticalSection(pszFile,nLine,(CRITICAL_SECTION*)(pCS))) #define MyCreateThread(sec,stack,start,parm,flags,tid) (FishHang_CreateThread(pszFile,nLine,(sec),(stack),(start),(parm),(flags),(tid))) #define MyExitThread(code) (FishHang_ExitThread((code))) #define MyCreateEvent(sec,man,set,name) (FishHang_CreateEvent(pszFile,nLine,(sec),(man),(set),(name))) #define MySetEvent(h) (FishHang_SetEvent(pszFile,nLine,(h))) #define MyResetEvent(h) (FishHang_ResetEvent(pszFile,nLine,(h))) #define MyDeleteEvent(h) (FishHang_CloseHandle(pszFile,nLine,(h))) #define MyCloseHandle(h) (FishHang_CloseHandle(pszFile,nLine,(h))) #define MyWaitForSingleObject(h,millsecs) (FishHang_WaitForSingleObject(pszFile,nLine,(h),(millsecs))) #else #define MyInitializeCriticalSection(pCS) (FishHang_InitializeCriticalSection(__FILE__,__LINE__,(CRITICAL_SECTION*)(pCS))) #define MyEnterCriticalSection(pCS) (FishHang_EnterCriticalSection(__FILE__,__LINE__,(CRITICAL_SECTION*)(pCS))) #define MyTryEnterCriticalSection(pCS) (FishHang_TryEnterCriticalSection(__FILE__,__LINE__,(CRITICAL_SECTION*)(pCS))) #define MyLeaveCriticalSection(pCS) (FishHang_LeaveCriticalSection(__FILE__,__LINE__,(CRITICAL_SECTION*)(pCS))) #define MyDeleteCriticalSection(pCS) (FishHang_DeleteCriticalSection(__FILE__,__LINE__,(CRITICAL_SECTION*)(pCS))) #define MyCreateThread(sec,stack,start,parm,flags,tid) (FishHang_CreateThread(__FILE__,__LINE__,(sec),(stack),(start),(parm),(flags),(tid))) #define MyExitThread(code) (FishHang_ExitThread((code))) #define MyCreateEvent(sec,man,set,name) (FishHang_CreateEvent(__FILE__,__LINE__,(sec),(man),(set),(name))) #define MySetEvent(h) (FishHang_SetEvent(__FILE__,__LINE__,(h))) #define MyResetEvent(h) (FishHang_ResetEvent(__FILE__,__LINE__,(h))) #define MyDeleteEvent(h) (FishHang_CloseHandle(__FILE__,__LINE__,(h))) #define MyCloseHandle(h) (FishHang_CloseHandle(__FILE__,__LINE__,(h))) #define MyWaitForSingleObject(h,millsecs) (FishHang_WaitForSingleObject(__FILE__,__LINE__,(h),(millsecs))) #endif #else // !defined(FISH_HANG) #define MyInitializeCriticalSection(pCS) (InitializeCriticalSectionAndSpinCount((CRITICAL_SECTION*)(pCS),3000)) #define MyEnterCriticalSection(pCS) (EnterCriticalSection((CRITICAL_SECTION*)(pCS))) #define MyTryEnterCriticalSection(pCS) (TryEnterCriticalSection((CRITICAL_SECTION*)(pCS))) #define MyLeaveCriticalSection(pCS) (LeaveCriticalSection((CRITICAL_SECTION*)(pCS))) #define MyDeleteCriticalSection(pCS) (DeleteCriticalSection((CRITICAL_SECTION*)(pCS))) #ifdef _MSVC_ #define MyCreateThread(sec,stack,start,parm,flags,tid) ((HANDLE) _beginthreadex((sec),(unsigned)(stack),(start),(parm),(flags),(tid))) #define MyExitThread(code) (_endthreadex((code))) #else // (Cygwin) #define MyCreateThread(sec,stack,start,parm,flags,tid) (CreateThread((sec),(stack),(start),(parm),(flags),(tid))) #define MyExitThread(code) (ExitThread((code))) #endif #define MyCreateEvent(sec,man,set,name) (CreateEvent((sec),(man),(set),(name))) #define MySetEvent(h) (SetEvent((h))) #define MyResetEvent(h) (ResetEvent((h))) #define MyDeleteEvent(h) (CloseHandle((h))) #define MyCloseHandle(h) (CloseHandle((h))) #define MyWaitForSingleObject(h,millisecs) (WaitForSingleObject((h),(millisecs))) #endif // defined(FISH_HANG) ///////////////////////////////////////////////////////////////////////////// FH_DLL_IMPORT HANDLE FishHang_CreateThread ( const char* pszFileCreated, // source file that created it const int nLineCreated, // line number of source file LPSECURITY_ATTRIBUTES lpThreadAttributes, // pointer to security attributes DWORD dwStackSize, // initial thread stack size LPTHREAD_START_ROUTINE lpStartAddress, // pointer to thread function LPVOID lpParameter, // argument for new thread DWORD dwCreationFlags, // creation flags LPDWORD lpThreadId // pointer to receive thread ID ); ///////////////////////////////////////////////////////////////////////////// FH_DLL_IMPORT void FishHang_ExitThread ( DWORD dwExitCode // exit code for this thread ); ///////////////////////////////////////////////////////////////////////////// FH_DLL_IMPORT void FishHang_InitializeCriticalSection ( const char* pszFileCreated, // source file that created it const int nLineCreated, // line number of source file LPCRITICAL_SECTION lpCriticalSection // address of critical section object ); ///////////////////////////////////////////////////////////////////////////// FH_DLL_IMPORT void FishHang_DeleteCriticalSection ( const char* pszFileDeleting, // source file that's deleting it const int nLineDeleting, // line number of source file LPCRITICAL_SECTION lpCriticalSection // address of critical section object ); ///////////////////////////////////////////////////////////////////////////// FH_DLL_IMPORT void FishHang_EnterCriticalSection ( const char* pszFileWaiting, // source file that attempted it const int nLineWaiting, // line number of source file LPCRITICAL_SECTION lpCriticalSection // address of critical section object ); ///////////////////////////////////////////////////////////////////////////// FH_DLL_IMPORT BOOL FishHang_TryEnterCriticalSection ( const char* pszFileWaiting, // source file that attempted it const int nLineWaiting, // line number of source file LPCRITICAL_SECTION lpCriticalSection // address of critical section object ); ///////////////////////////////////////////////////////////////////////////// FH_DLL_IMPORT void FishHang_LeaveCriticalSection ( const char* pszFileReleasing, // source file that attempted it const int nLineReleasing, // line number of source file LPCRITICAL_SECTION lpCriticalSection // address of critical section object ); ///////////////////////////////////////////////////////////////////////////// FH_DLL_IMPORT HANDLE FishHang_CreateEvent ( const char* pszFileCreated, // source file that created it const int nLineCreated, // line number of source file LPSECURITY_ATTRIBUTES lpEventAttributes, // pointer to security attributes BOOL bManualReset, // flag for manual-reset event BOOL bInitialState, // flag for initial state LPCTSTR lpName // pointer to event-object name ); ///////////////////////////////////////////////////////////////////////////// FH_DLL_IMPORT BOOL FishHang_SetEvent ( const char* pszFileSet, // source file that set it const int nLineSet, // line number of source file HANDLE hEvent // handle to event object ); ///////////////////////////////////////////////////////////////////////////// FH_DLL_IMPORT BOOL FishHang_ResetEvent ( const char* pszFileReset, // source file that reset it const int nLineReset, // line number of source file HANDLE hEvent // handle to event object ); ///////////////////////////////////////////////////////////////////////////// FH_DLL_IMPORT BOOL FishHang_PulseEvent ( const char* pszFilePosted, // source file that signalled it const int nLinePosted, // line number of source file HANDLE hEvent // handle to event object ); ///////////////////////////////////////////////////////////////////////////// FH_DLL_IMPORT BOOL FishHang_CloseHandle // ** NOTE: only events for right now ** ( const char* pszFileClosed, // source file that closed it const int nLineClosed, // line number of source file HANDLE hEvent // handle to event object ); ///////////////////////////////////////////////////////////////////////////// FH_DLL_IMPORT DWORD FishHang_WaitForSingleObject // ** NOTE: only events for right now ** ( const char* pszFileWaiting, // source file that's waiting on it const int nLineWaiting, // line number of source file HANDLE hEvent, // handle to event to wait for DWORD dwMilliseconds // time-out interval in milliseconds ); ///////////////////////////////////////////////////////////////////////////// FH_DLL_IMPORT int bFishHangAtExit; // (set to true when shutting down) FH_DLL_IMPORT void FishHangInit( const char* pszFileCreated, const int nLineCreated ); FH_DLL_IMPORT void FishHangReport(); FH_DLL_IMPORT void FishHangAtExit(); FH_DLL_IMPORT void FishHang_Printf( const char* pszFormat, ... ); ///////////////////////////////////////////////////////////////////////////// #endif // _FISHHANG_H_ hercules-3.07/float.c000644 000765 000765 00001007136 11321734033 016221 0ustar00jmaynardjmaynard000000 000000 /* FLOAT.C (c) Copyright Peter Kuschnerus, 2000-2009 */ /* ESA/390 Hex Floatingpoint Instructions */ // $Id: float.c 5569 2009-12-27 14:01:09Z hsg001 $ /*-------------------------------------------------------------------*/ /* This module implements the ESA/390 Hex Floatingpoint Instructions */ /* described in the manual ESA/390 Principles of Operation. */ /*-------------------------------------------------------------------*/ /*-------------------------------------------------------------------*/ /* Incorporated all floating point instructions from cpu.c in order */ /* to implement revised instruction decoding. */ /* Jan Jaeger 01/07/00 */ /* z/Architecture support - (c) Copyright Jan Jaeger, 1999-2009 */ /*-------------------------------------------------------------------*/ /*-------------------------------------------------------------------*/ /* Added the square-root-facility (instructions SQDR, SQER). */ /* Peter Kuschnerus 01/09/00 */ /*-------------------------------------------------------------------*/ /*-------------------------------------------------------------------*/ /* Added the HFP-extension-facility (26 additional instructions). */ /* Added the AFP-Registers-facility (additional float registers). */ /* Peter Kuschnerus 13/12/00 */ /* Long Displacement Facility: LDY,LEY,STDY,STEY R.Bowler 29/06/03 */ /* FPS Extensions Facility: LXR,LZER,LZDR,LZXR R.Bowler 06juil03 */ /* HFP Multiply and Add/Subtract Facility R.Bowler 10juil03 */ /* Convert 64fixed to float family CEGR,CDGR,CXGR BvdHelm 28/01/06 */ /* Completed the family CGER, CGDR and CGXR BvdHelm 04/11/06 */ /*-------------------------------------------------------------------*/ // $Log$ // Revision 1.56 2008/05/04 14:14:03 rbowler // Fix CGXR to handle values exceeding 2G // // Revision 1.55 2008/05/04 10:01:48 rbowler // Fix CGDR to handle values exceeding 2G // // Revision 1.54 2008/04/27 22:34:23 rbowler // CGER result incorrect when expo=70 // // Revision 1.53 2008/04/25 21:35:02 rbowler // CGER result incorrect for values over 2G // // Revision 1.52 2008/04/22 17:41:21 rbowler // Correction to CXGR instruction // // Revision 1.51 2008/04/21 20:26:27 rbowler // CEGR result incorrect if source exceeds 6 digits // // Revision 1.50 2008/04/20 21:53:50 rbowler // CDGR result incorrect if source exceeds 14 digits // // Revision 1.49 2007/06/23 00:04:09 ivan // Update copyright notices to include current year (2007) // // Revision 1.48 2007/01/13 07:19:55 bernard // backout ccmask // // Revision 1.47 2007/01/12 15:23:26 bernard // ccmask phase 1 // // Revision 1.46 2006/12/08 09:43:21 jj // Add CVS message log // #include "hstdinc.h" #if !defined(_HENGINE_DLL_) #define _HENGINE_DLL_ #endif #if !defined(_FLOAT_C_) #define _FLOAT_C_ #endif #include "hercules.h" #include "opcode.h" #include "inline.h" #if defined(FEATURE_HEXADECIMAL_FLOATING_POINT) /* Rename all inline functions for multi architectural support *JJ */ #undef get_sf #undef store_sf #undef get_lf #undef store_lf #undef get_ef #undef store_ef #undef vfetch_sf #undef vfetch_lf #undef normal_sf #undef normal_lf #undef normal_ef #undef overflow_sf #undef overflow_lf #undef overflow_ef #undef underflow_sf #undef underflow_lf #undef underflow_ef #undef over_under_flow_sf #undef over_under_flow_lf #undef over_under_flow_ef #undef significance_sf #undef significance_lf #undef significance_ef #undef add_ef #undef add_lf #undef add_sf #undef cmp_lf #undef cmp_sf #undef div_U128 #undef div_U256 #undef div_ef #undef div_lf #undef div_sf #undef mul_ef #undef mul_sf #undef mul_lf #undef mul_lf_to_ef #undef mul_sf_to_lf #undef square_root_fraction #undef sq_sf #undef sq_lf #if __GEN_ARCH == 370 #define get_ef s370_get_ef #define get_lf s370_get_lf #define get_sf s370_get_sf #define normal_ef s370_normal_ef #define normal_lf s370_normal_lf #define normal_sf s370_normal_sf #define over_under_flow_ef s370_over_under_flow_ef #define over_under_flow_lf s370_over_under_flow_lf #define over_under_flow_sf s370_over_under_flow_sf #define overflow_ef s370_overflow_ef #define overflow_lf s370_overflow_lf #define overflow_sf s370_overflow_sf #define significance_ef s370_significance_ef #define significance_lf s370_significance_lf #define significance_sf s370_significance_sf #define store_ef s370_store_ef #define store_lf s370_store_lf #define store_sf s370_store_sf #define underflow_ef s370_underflow_ef #define underflow_lf s370_underflow_lf #define underflow_sf s370_underflow_sf #define vfetch_lf s370_vfetch_lf #define vfetch_sf s370_vfetch_sf #define add_ef s370_add_ef #define add_lf s370_add_lf #define add_sf s370_add_sf #define cmp_lf s370_cmp_lf #define cmp_sf s370_cmp_sf #define div_U128 s370_div_U128 #define div_U256 s370_div_U256 #define div_ef s370_div_ef #define div_lf s370_div_lf #define div_sf s370_div_sf #define mul_ef s370_mul_ef #define mul_sf s370_mul_sf #define mul_lf s370_mul_lf #define mul_lf_to_ef s370_mul_lf_to_ef #define mul_sf_to_lf s370_mul_sf_to_lf #define square_root_fraction s370_square_root_fraction #define sq_sf s370_sq_sf #define sq_lf s370_sq_lf #elif __GEN_ARCH == 390 #define get_ef s390_get_ef #define get_lf s390_get_lf #define get_sf s390_get_sf #define normal_ef s390_normal_ef #define normal_lf s390_normal_lf #define normal_sf s390_normal_sf #define over_under_flow_ef s390_over_under_flow_ef #define over_under_flow_lf s390_over_under_flow_lf #define over_under_flow_sf s390_over_under_flow_sf #define overflow_ef s390_overflow_ef #define overflow_lf s390_overflow_lf #define overflow_sf s390_overflow_sf #define significance_ef s390_significance_ef #define significance_lf s390_significance_lf #define significance_sf s390_significance_sf #define store_ef s390_store_ef #define store_lf s390_store_lf #define store_sf s390_store_sf #define underflow_ef s390_underflow_ef #define underflow_lf s390_underflow_lf #define underflow_sf s390_underflow_sf #define vfetch_lf s390_vfetch_lf #define vfetch_sf s390_vfetch_sf #define add_ef s390_add_ef #define add_lf s390_add_lf #define add_sf s390_add_sf #define cmp_lf s390_cmp_lf #define cmp_sf s390_cmp_sf #define div_U128 s390_div_U128 #define div_U256 s390_div_U256 #define div_ef s390_div_ef #define div_lf s390_div_lf #define div_sf s390_div_sf #define mul_ef s390_mul_ef #define mul_sf s390_mul_sf #define mul_lf s390_mul_lf #define mul_lf_to_ef s390_mul_lf_to_ef #define mul_sf_to_lf s390_mul_sf_to_lf #define square_root_fraction s390_square_root_fraction #define sq_sf s390_sq_sf #define sq_lf s390_sq_lf #elif __GEN_ARCH == 900 #define get_ef z900_get_ef #define get_lf z900_get_lf #define get_sf z900_get_sf #define normal_ef z900_normal_ef #define normal_lf z900_normal_lf #define normal_sf z900_normal_sf #define over_under_flow_ef z900_over_under_flow_ef #define over_under_flow_lf z900_over_under_flow_lf #define over_under_flow_sf z900_over_under_flow_sf #define overflow_ef z900_overflow_ef #define overflow_lf z900_overflow_lf #define overflow_sf z900_overflow_sf #define significance_ef z900_significance_ef #define significance_lf z900_significance_lf #define significance_sf z900_significance_sf #define store_ef z900_store_ef #define store_lf z900_store_lf #define store_sf z900_store_sf #define underflow_ef z900_underflow_ef #define underflow_lf z900_underflow_lf #define underflow_sf z900_underflow_sf #define vfetch_lf z900_vfetch_lf #define vfetch_sf z900_vfetch_sf #define add_ef z900_add_ef #define add_lf z900_add_lf #define add_sf z900_add_sf #define cmp_lf z900_cmp_lf #define cmp_sf z900_cmp_sf #define div_U128 z900_div_U128 #define div_U256 z900_div_U256 #define div_ef z900_div_ef #define div_lf z900_div_lf #define div_sf z900_div_sf #define mul_ef z900_mul_ef #define mul_sf z900_mul_sf #define mul_lf z900_mul_lf #define mul_lf_to_ef z900_mul_lf_to_ef #define mul_sf_to_lf z900_mul_sf_to_lf #define square_root_fraction z900_square_root_fraction #define sq_sf z900_sq_sf #define sq_lf z900_sq_lf #else #error Unable to determine GEN_ARCH #endif #if !defined(_FLOAT_C) #define _FLOAT_C /*-------------------------------------------------------------------*/ /* Definitions */ /*-------------------------------------------------------------------*/ #define POS 0 /* Positive value of sign */ #define NEG 1 /* Negative value of sign */ #define UNNORMAL 0 /* Without normalisation */ #define NORMAL 1 /* With normalisation */ #define OVUNF 1 /* Check for over/underflow */ #define NOOVUNF 0 /* Leave exponent as is (for multiply-add/subtrace) */ #define SIGEX 1 /* Significance exception if result fraction is zero */ #define NOSIGEX 0 /* Do not raise significance exception, use true zero */ #define FLOAT_DEBUG 0 /* Change to 1 to enable debug messages */ /*-------------------------------------------------------------------*/ /* Add 128 bit unsigned integer */ /* The result is placed in operand a */ /* */ /* msa most significant 64 bit of operand a */ /* lsa least significant 64 bit of operand a */ /* msb most significant 64 bit of operand b */ /* lsb least significant 64 bit of operand b */ /* */ /* all operands are expected to be defined as U64 */ /*-------------------------------------------------------------------*/ #define add_U128(msa, lsa, msb, lsb) \ (lsa) += (lsb); \ (msa) += (msb); \ if ((lsa) < (lsb)) \ (msa)++ /*-------------------------------------------------------------------*/ /* Subtract 128 bit unsigned integer */ /* The operand b is subtracted from operand a */ /* The result is placed in operand a */ /* */ /* msa most significant 64 bit of operand a */ /* lsa least significant 64 bit of operand a */ /* msb most significant 64 bit of operand b */ /* lsb least significant 64 bit of operand b */ /* */ /* all operands are expected to be defined as U64 */ /*-------------------------------------------------------------------*/ #define sub_U128(msa, lsa, msb, lsb) \ (msa) -= (msb); \ if ((lsa) < (lsb)) \ (msa)--; \ (lsa) -= (lsb) /*-------------------------------------------------------------------*/ /* Subtract 128 bit unsigned integer reverse */ /* The operand a is subtracted from operand b */ /* The result is placed in operand a */ /* */ /* msa most significant 64 bit of operand a */ /* lsa least significant 64 bit of operand a */ /* msb most significant 64 bit of operand b */ /* lsb least significant 64 bit of operand b */ /* */ /* all operands are expected to be defined as U64 */ /*-------------------------------------------------------------------*/ #define sub_reverse_U128(msa, lsa, msb, lsb) \ (msa) = (msb) - (msa); \ if ((lsb) < (lsa)) \ (msa)--; \ (lsa) = (lsb) - (lsa) /*-------------------------------------------------------------------*/ /* Shift 128 bit one bit right */ /* */ /* ms most significant 64 bit of operand */ /* ls least significant 64 bit of operand */ /* */ /* all operands are expected to be defined as U64 */ /*-------------------------------------------------------------------*/ #define shift_right_U128(ms, ls) \ (ls) = ((ls) >> 1) | ((ms) << 63); \ (ms) >>= 1 /*-------------------------------------------------------------------*/ /* Shift 128 bit one bit left */ /* */ /* ms most significant 64 bit of operand */ /* ls least significant 64 bit of operand */ /* */ /* all operands are expected to be defined as U64 */ /*-------------------------------------------------------------------*/ #define shift_left_U128(ms, ls) \ (ms) = ((ms) << 1) | ((ls) >> 63); \ (ls) <<= 1 /*-------------------------------------------------------------------*/ /* Shift 128 bit 4 bits right with shifted digit */ /* */ /* ms most significant 64 bit of operand */ /* ls least significant 64 bit of operand */ /* dig lesast significant 4 bits removed by right shift */ /* */ /* all operands are expected to be defined as U64 */ /*-------------------------------------------------------------------*/ #define shift_right4_U128(ms, ls, dig) \ (dig) = (ls) & 0xF; \ (ls) = ((ls) >> 4) | ((ms) << 60); \ (ms) >>= 4 /*-------------------------------------------------------------------*/ /* Shift 128 bit 4 bits left with shifted digit */ /* */ /* ms most significant 64 bit of operand */ /* ls least significant 64 bit of operand */ /* dig most significant 4 bits removed by left shift */ /* */ /* all operands are expected to be defined as U64 */ /*-------------------------------------------------------------------*/ #define shift_left4_U128(ms, ls, dig) \ (dig) = (ms) >> 60; \ (ms) = ((ms) << 4) | ((ls) >> 60); \ (ls) <<= 1 /*-------------------------------------------------------------------*/ /* Shift 256 bit one bit left */ /* */ /* mms most significant 64 bit of operand */ /* ms more significant 64 bit of operand */ /* ls less significant 64 bit of operand */ /* lls least significant 64 bit of operand */ /* */ /* all operands are expected to be defined as U64 */ /*-------------------------------------------------------------------*/ #define shift_left_U256(mms, ms, ls, lls) \ (mms) = ((mms) << 1) | ((ms) >> 63); \ (ms) = ((ms) << 1) | ((ls) >> 63); \ (ls) = ((ls) << 1) | ((lls) >> 63); \ (lls) <<= 1 /*-------------------------------------------------------------------*/ /* Structure definition for internal short floatingpoint format */ /*-------------------------------------------------------------------*/ typedef struct _SHORT_FLOAT { U32 short_fract; /* Fraction */ short expo; /* Exponent + 64 */ BYTE sign; /* Sign */ } SHORT_FLOAT; /*-------------------------------------------------------------------*/ /* Structure definition for internal long floatingpoint format */ /*-------------------------------------------------------------------*/ typedef struct _LONG_FLOAT { U64 long_fract; /* Fraction */ short expo; /* Exponent + 64 */ BYTE sign; /* Sign */ } LONG_FLOAT; /*-------------------------------------------------------------------*/ /* Structure definition for internal extended floatingpoint format */ /*-------------------------------------------------------------------*/ typedef struct _EXTENDED_FLOAT { U64 ms_fract, ls_fract; /* Fraction */ short expo; /* Exponent + 64 */ BYTE sign; /* Sign */ } EXTENDED_FLOAT; #endif /*!defined(_FLOAT_C)*/ /*-------------------------------------------------------------------*/ /* Static inline functions */ /*-------------------------------------------------------------------*/ /*-------------------------------------------------------------------*/ /* Get short float from register */ /* */ /* Input: */ /* fl Internal float format to be converted to */ /* fpr Pointer to register to be converted from */ /*-------------------------------------------------------------------*/ static inline void get_sf( SHORT_FLOAT *fl, U32 *fpr ) { fl->sign = *fpr >> 31; fl->expo = (*fpr >> 24) & 0x007F; fl->short_fract = *fpr & 0x00FFFFFF; } /* end function get_sf */ /*-------------------------------------------------------------------*/ /* Store short float to register */ /* */ /* Input: */ /* fl Internal float format to be converted from */ /* fpr Pointer to register to be converted to */ /*-------------------------------------------------------------------*/ static inline void store_sf( SHORT_FLOAT *fl, U32 *fpr ) { *fpr = ((U32)fl->sign << 31) | ((U32)fl->expo << 24) | (fl->short_fract); } /* end function store_sf */ /*-------------------------------------------------------------------*/ /* Get long float from register */ /* */ /* Input: */ /* fl Internal float format to be converted to */ /* fpr Pointer to register to be converted from */ /*-------------------------------------------------------------------*/ static inline void get_lf( LONG_FLOAT *fl, U32 *fpr ) { fl->sign = *fpr >> 31; fl->expo = (*fpr >> 24) & 0x007F; fl->long_fract = ((U64)(fpr[0] & 0x00FFFFFF) << 32) | fpr[1]; } /* end function get_lf */ /*-------------------------------------------------------------------*/ /* Store long float to register */ /* */ /* Input: */ /* fl Internal float format to be converted from */ /* fpr Pointer to register to be converted to */ /*-------------------------------------------------------------------*/ static inline void store_lf( LONG_FLOAT *fl, U32 *fpr ) { fpr[0] = ((U32)fl->sign << 31) | ((U32)fl->expo << 24) | (fl->long_fract >> 32); fpr[1] = fl->long_fract; } /* end function store_lf */ /*-------------------------------------------------------------------*/ /* Get extended float from register */ /* */ /* Input: */ /* fl Internal float format to be converted to */ /* fpr Pointer to register to be converted from */ /*-------------------------------------------------------------------*/ static inline void get_ef( EXTENDED_FLOAT *fl, U32 *fpr ) { fl->sign = *fpr >> 31; fl->expo = (*fpr >> 24) & 0x007F; fl->ms_fract = ((U64)(fpr[0] & 0x00FFFFFF) << 24) | (fpr[1] >> 8); fl->ls_fract = (((U64)fpr[1]) << 56) | (((U64)(fpr[FPREX] & 0x00FFFFFF)) << 32) | fpr[FPREX+1]; } /* end function get_ef */ /*-------------------------------------------------------------------*/ /* Store extended float to register */ /* */ /* Input: */ /* fl Internal float format to be converted from */ /* fpr Pointer to register to be converted from */ /*-------------------------------------------------------------------*/ static inline void store_ef( EXTENDED_FLOAT *fl, U32 *fpr ) { fpr[0] = ((U32)fl->sign << 31) | ((U32)fl->expo << 24) | (fl->ms_fract >> 24); fpr[1] = (fl->ms_fract << 8) | (fl->ls_fract >> 56); fpr[FPREX] = ((U32)fl->sign << 31) | ((fl->ls_fract >> 32) & 0x00FFFFFF); fpr[FPREX+1] = fl->ls_fract; if ( fpr[0] || fpr[1] || fpr[FPREX] || fpr[FPREX+1] ) { fpr[FPREX] |= ((((U32)fl->expo - 14) << 24) & 0x7f000000); } } /* end function store_ef */ #if defined(FEATURE_HFP_UNNORMALIZED_EXTENSION) /*-------------------------------------------------------------------*/ /* Store extended float to register pair unnormalized */ /* */ /* Input: */ /* fl Internal float format to be converted from */ /* fpr Pointer to register to be converted to */ /*-------------------------------------------------------------------*/ static inline void ARCH_DEP(store_ef_unnorm)( EXTENDED_FLOAT *fl, U32 *fpr ) { fpr[0] = ((U32)fl->sign << 31) | (((U32)fl->expo & 0x7f) << 24) | (fl->ms_fract >> 24); fpr[1] = (fl->ms_fract << 8) | (fl->ls_fract >> 56); fpr[FPREX] = ((U32)fl->sign << 31) | ((fl->ls_fract >> 32) & 0x00FFFFFF); fpr[FPREX+1] = fl->ls_fract; fpr[FPREX] |= ((((U32)fl->expo - 14) << 24) & 0x7f000000); } /* end ARCH_DEP(store_ef_unnorm) */ /*-------------------------------------------------------------------*/ /* Store extended float high-order part to register unnormalized */ /* */ /* Input: */ /* fl Internal float format to be converted from */ /* fpr Pointer to register to be converted to */ /*-------------------------------------------------------------------*/ static inline void ARCH_DEP(store_ef_unnorm_hi)( EXTENDED_FLOAT *fl, U32 *fpr ) { fpr[0] = ((U32)fl->sign << 31) | (((U32)fl->expo & 0x7f) << 24) | (fl->ms_fract >> 24); fpr[1] = (fl->ms_fract << 8) | (fl->ls_fract >> 56); } /* end ARCH_DEP(store_ef_unnorm_hi) */ /*-------------------------------------------------------------------*/ /* Store extended float low-order part to register unnormalized */ /* */ /* Input: */ /* fl Internal float format to be converted from */ /* fpr Pointer to register to be converted to */ /*-------------------------------------------------------------------*/ static inline void ARCH_DEP(store_ef_unnorm_lo)( EXTENDED_FLOAT *fl, U32 *fpr ) { fpr[0] = ((U32)fl->sign << 31) | ((((U32)fl->expo - 14 ) & 0x7f) << 24) | ((fl->ls_fract >> 32) & 0x00FFFFFF); fpr[1] = fl->ls_fract; } /* end ARCH_DEP(store_ef_unnorm_lo) */ /*-------------------------------------------------------------------*/ /* Convert long to extended format unnormalized */ /* */ /* Input: */ /* fl Internal float format to be converted from */ /* fpr Pointer to register to be converted to */ /*-------------------------------------------------------------------*/ static inline void ARCH_DEP(lf_to_ef_unnorm) ( EXTENDED_FLOAT *fx, LONG_FLOAT *fl ) { fx->sign = fl->sign; fx->expo = fl->expo; fx->ms_fract = fl->long_fract >> 8; fx->ls_fract = (fl->long_fract & 0xff) << 56; } /* end ARCH_DEP(lf_to_ef_unnorm) */ #endif /* defined(FEATURE_HFP_UNNORMALIZED_EXTENSION) */ /*-------------------------------------------------------------------*/ /* Fetch a short floatingpoint operand from virtual storage */ /* */ /* Input: */ /* fl Internal float format */ /* addr Logical address of leftmost byte of operand */ /* arn Access register number */ /* regs CPU register context */ /* */ /* A program check may be generated if the logical address */ /* causes an addressing, translation, or fetch protection */ /* exception, and in this case the function does not return. */ /*-------------------------------------------------------------------*/ static inline void vfetch_sf( SHORT_FLOAT *fl, VADR addr, int arn, REGS *regs ) { U32 value; /* Operand value */ /* Fetch 4 bytes from operand address */ value = ARCH_DEP(vfetch4) (addr, arn, regs); /* Extract sign and exponent from high-order byte */ fl->sign = value >> 31; fl->expo = (value >> 24) & 0x007F; /* Extract fraction from low-order 3 bytes */ fl->short_fract = value & 0x00FFFFFF; } /* end function vfetch_sf */ /*-------------------------------------------------------------------*/ /* Fetch a long floatingpoint operand from virtual storage */ /* */ /* Input: */ /* fl Internal float format */ /* addr Logical address of leftmost byte of operand */ /* arn Access register number */ /* regs CPU register context */ /* */ /* A program check may be generated if the logical address */ /* causes an addressing, translation, or fetch protection */ /* exception, and in this case the function does not return. */ /*-------------------------------------------------------------------*/ static inline void vfetch_lf( LONG_FLOAT *fl, VADR addr, int arn, REGS *regs ) { U64 value; /* Operand value */ /* Fetch 8 bytes from operand address */ value = ARCH_DEP(vfetch8) (addr, arn, regs); /* Extract sign and exponent from high-order byte */ fl->sign = value >> 63; fl->expo = (value >> 56) & 0x007F; /* Extract fraction from low-order 7 bytes */ fl->long_fract = value & 0x00FFFFFFFFFFFFFFULL; } /* end function vfetch_lf */ /*-------------------------------------------------------------------*/ /* Normalize short float */ /* */ /* Input: */ /* fl Internal float */ /*-------------------------------------------------------------------*/ static inline void normal_sf( SHORT_FLOAT *fl ) { if (fl->short_fract) { if ((fl->short_fract & 0x00FFFF00) == 0) { fl->short_fract <<= 16; fl->expo -= 4; } if ((fl->short_fract & 0x00FF0000) == 0) { fl->short_fract <<= 8; fl->expo -= 2; } if ((fl->short_fract & 0x00F00000) == 0) { fl->short_fract <<= 4; (fl->expo)--; } } else { fl->sign = POS; fl->expo = 0; } } /* end function normal_sf */ /*-------------------------------------------------------------------*/ /* Normalize long float */ /* */ /* Input: */ /* fl Internal float */ /*-------------------------------------------------------------------*/ static inline void normal_lf( LONG_FLOAT *fl ) { if (fl->long_fract) { if ((fl->long_fract & 0x00FFFFFFFF000000ULL) == 0) { fl->long_fract <<= 32; fl->expo -= 8; } if ((fl->long_fract & 0x00FFFF0000000000ULL) == 0) { fl->long_fract <<= 16; fl->expo -= 4; } if ((fl->long_fract & 0x00FF000000000000ULL) == 0) { fl->long_fract <<= 8; fl->expo -= 2; } if ((fl->long_fract & 0x00F0000000000000ULL) == 0) { fl->long_fract <<= 4; (fl->expo)--; } } else { fl->sign = POS; fl->expo = 0; } } /* end function normal_lf */ /*-------------------------------------------------------------------*/ /* Normalize extended float */ /* */ /* Input: */ /* fl Internal float */ /*-------------------------------------------------------------------*/ static inline void normal_ef( EXTENDED_FLOAT *fl ) { if (fl->ms_fract || fl->ls_fract) { if (fl->ms_fract == 0) { fl->ms_fract = fl->ls_fract >> 16; fl->ls_fract <<= 48; fl->expo -= 12; } if ((fl->ms_fract & 0x0000FFFFFFFF0000ULL) == 0) { if (fl->ls_fract) { fl->ms_fract = (fl->ms_fract << 32) | (fl->ls_fract >> 32); fl->ls_fract <<= 32; } else { fl->ms_fract <<= 32; } fl->expo -= 8; } if ((fl->ms_fract & 0x0000FFFF00000000ULL) == 0) { if (fl->ls_fract) { fl->ms_fract = (fl->ms_fract << 16) | (fl->ls_fract >> 48); fl->ls_fract <<= 16; } else { fl->ms_fract <<= 16; } fl->expo -= 4; } if ((fl->ms_fract & 0x0000FF0000000000ULL) == 0) { if (fl->ls_fract) { fl->ms_fract = (fl->ms_fract << 8) | (fl->ls_fract >> 56); fl->ls_fract <<= 8; } else { fl->ms_fract <<= 8; } fl->expo -= 2; } if ((fl->ms_fract & 0x0000F00000000000ULL) == 0) { if (fl->ls_fract) { fl->ms_fract = (fl->ms_fract << 4) | (fl->ls_fract >> 60); fl->ls_fract <<= 4; } else { fl->ms_fract <<= 4; } (fl->expo)--; } } else { fl->sign = POS; fl->expo = 0; } } /* end function normal_ef */ /*-------------------------------------------------------------------*/ /* Overflow of short float */ /* */ /* Input: */ /* fl Internal float */ /* regs CPU register context */ /* Value: */ /* exeption */ /*-------------------------------------------------------------------*/ static inline int overflow_sf( SHORT_FLOAT *fl, REGS *regs ) { UNREFERENCED(regs); if (fl->expo > 127) { fl->expo &= 0x007F; return(PGM_EXPONENT_OVERFLOW_EXCEPTION); } return(0); } /* end function overflow_sf */ /*-------------------------------------------------------------------*/ /* Overflow of long float */ /* */ /* Input: */ /* fl Internal float */ /* regs CPU register context */ /* Value: */ /* exeption */ /*-------------------------------------------------------------------*/ static inline int overflow_lf( LONG_FLOAT *fl, REGS *regs ) { UNREFERENCED(regs); if (fl->expo > 127) { fl->expo &= 0x007F; return(PGM_EXPONENT_OVERFLOW_EXCEPTION); } return(0); } /* end function overflow_lf */ /*-------------------------------------------------------------------*/ /* Overflow of extended float */ /* */ /* Input: */ /* fl Internal float */ /* regs CPU register context */ /* Value: */ /* exeption */ /*-------------------------------------------------------------------*/ static inline int overflow_ef( EXTENDED_FLOAT *fl, REGS *regs ) { UNREFERENCED(regs); if (fl->expo > 127) { fl->expo &= 0x007F; return(PGM_EXPONENT_OVERFLOW_EXCEPTION); } return(0); } /* end function overflow_ef */ /*-------------------------------------------------------------------*/ /* Underflow of short float */ /* */ /* Input: */ /* fl Internal float */ /* regs CPU register context */ /* Value: */ /* exeption */ /*-------------------------------------------------------------------*/ static inline int underflow_sf( SHORT_FLOAT *fl, REGS *regs ) { if (fl->expo < 0) { if (EUMASK(®s->psw)) { fl->expo &= 0x007F; return(PGM_EXPONENT_UNDERFLOW_EXCEPTION); } else { /* set true 0 */ fl->short_fract = 0; fl->expo = 0; fl->sign = POS; } } return(0); } /* end function underflow_sf */ /*-------------------------------------------------------------------*/ /* Underflow of long float */ /* */ /* Input: */ /* fl Internal float */ /* regs CPU register context */ /* Value: */ /* exeption */ /*-------------------------------------------------------------------*/ static inline int underflow_lf( LONG_FLOAT *fl, REGS *regs ) { if (fl->expo < 0) { if (EUMASK(®s->psw)) { fl->expo &= 0x007F; return(PGM_EXPONENT_UNDERFLOW_EXCEPTION); } else { /* set true 0 */ fl->long_fract = 0; fl->expo = 0; fl->sign = POS; } } return(0); } /* end function underflow_lf */ /*-------------------------------------------------------------------*/ /* Underflow of extended float */ /* */ /* Input: */ /* fl Internal float */ /* fpr Pointer to register to be stored to */ /* regs CPU register context */ /* Value: */ /* exeption */ /*-------------------------------------------------------------------*/ static inline int underflow_ef( EXTENDED_FLOAT *fl, U32 *fpr, REGS *regs ) { if (fl->expo < 0) { if (EUMASK(®s->psw)) { fl->expo &= 0x007F; store_ef( fl, fpr ); return(PGM_EXPONENT_UNDERFLOW_EXCEPTION); } else { /* set true 0 */ fpr[0] = 0; fpr[1] = 0; fpr[FPREX] = 0; fpr[FPREX+1] = 0; fl->ms_fract = 0; fl->ls_fract = 0; return(0); } } store_ef( fl, fpr ); return(0); } /* end function underflow_ef */ /*-------------------------------------------------------------------*/ /* Overflow and underflow of short float */ /* */ /* Input: */ /* fl Internal float */ /* regs CPU register context */ /* Value: */ /* exeption */ /*-------------------------------------------------------------------*/ static inline int over_under_flow_sf( SHORT_FLOAT *fl, REGS *regs ) { if (fl->expo > 127) { fl->expo &= 0x007F; return(PGM_EXPONENT_OVERFLOW_EXCEPTION); } else { if (fl->expo < 0) { if (EUMASK(®s->psw)) { fl->expo &= 0x007F; return(PGM_EXPONENT_UNDERFLOW_EXCEPTION); } else { /* set true 0 */ fl->short_fract = 0; fl->expo = 0; fl->sign = POS; } } } return(0); } /* end function over_under_flow_sf */ /*-------------------------------------------------------------------*/ /* Overflow and underflow of long float */ /* */ /* Input: */ /* fl Internal float */ /* regs CPU register context */ /* Value: */ /* exeption */ /*-------------------------------------------------------------------*/ static inline int over_under_flow_lf( LONG_FLOAT *fl, REGS *regs ) { if (fl->expo > 127) { fl->expo &= 0x007F; return(PGM_EXPONENT_OVERFLOW_EXCEPTION); } else { if (fl->expo < 0) { if (EUMASK(®s->psw)) { fl->expo &= 0x007F; return(PGM_EXPONENT_UNDERFLOW_EXCEPTION); } else { /* set true 0 */ fl->long_fract = 0; fl->expo = 0; fl->sign = POS; } } } return(0); } /* end function over_under_flow_lf */ /*-------------------------------------------------------------------*/ /* Overflow and underflow of extended float */ /* */ /* Input: */ /* fl Internal float */ /* regs CPU register context */ /* Value: */ /* exeption */ /*-------------------------------------------------------------------*/ static inline int over_under_flow_ef( EXTENDED_FLOAT *fl, REGS *regs ) { if (fl->expo > 127) { fl->expo &= 0x007F; return(PGM_EXPONENT_OVERFLOW_EXCEPTION); } else { if (fl->expo < 0) { if (EUMASK(®s->psw)) { fl->expo &= 0x007F; return(PGM_EXPONENT_UNDERFLOW_EXCEPTION); } else { /* set true 0 */ fl->ms_fract = 0; fl->ls_fract = 0; fl->expo = 0; fl->sign = POS; } } } return(0); } /* end function over_under_flow_ef */ /*-------------------------------------------------------------------*/ /* Significance of short float */ /* The fraction is expected to be zero */ /* */ /* Input: */ /* fl Internal float */ /* sigex Allow significance exception if true */ /* regs CPU register context */ /* Value: */ /* exeption */ /*-------------------------------------------------------------------*/ static inline int significance_sf( SHORT_FLOAT *fl, BYTE sigex, REGS *regs ) { fl->sign = POS; if (sigex && SGMASK(®s->psw)) { return(PGM_SIGNIFICANCE_EXCEPTION); } /* set true 0 */ fl->expo = 0; return(0); } /* end function significance_sf */ /*-------------------------------------------------------------------*/ /* Significance of long float */ /* The fraction is expected to be zero */ /* */ /* Input: */ /* fl Internal float */ /* sigex Allow significance exception if true */ /* regs CPU register context */ /* Value: */ /* exeption */ /*-------------------------------------------------------------------*/ static inline int significance_lf( LONG_FLOAT *fl, BYTE sigex, REGS *regs ) { fl->sign = POS; if (sigex && SGMASK(®s->psw)) { return(PGM_SIGNIFICANCE_EXCEPTION); } /* set true 0 */ fl->expo = 0; return(0); } /* end function significance_lf */ /*-------------------------------------------------------------------*/ /* Significance of extended float */ /* The fraction is expected to be zero */ /* */ /* Input: */ /* fl Internal float */ /* fpr Pointer to register to be stored to */ /* regs CPU register context */ /* Value: */ /* exeption */ /*-------------------------------------------------------------------*/ static inline int significance_ef( EXTENDED_FLOAT *fl, U32 *fpr, REGS *regs ) { fpr[1] = 0; fpr[FPREX+1] = 0; if (SGMASK(®s->psw)) { fpr[0] = (U32)fl->expo << 24; fpr[FPREX] = (((U32)fl->expo - 14) << 24) & 0x7f000000; return(PGM_SIGNIFICANCE_EXCEPTION); } /* set true 0 */ fpr[0] = 0; fpr[FPREX] = 0; return(0); } /* end function significance_ef */ /*-------------------------------------------------------------------*/ /* Static functions */ /*-------------------------------------------------------------------*/ /*-------------------------------------------------------------------*/ /* Add short float */ /* */ /* Input: */ /* fl Float */ /* add_fl Float to be added */ /* normal Normalize if true */ /* sigex Allow significance exception if true */ /* regs CPU register context */ /* Value: */ /* exeption */ /*-------------------------------------------------------------------*/ static int add_sf( SHORT_FLOAT *fl, SHORT_FLOAT *add_fl, BYTE normal, BYTE sigex, REGS *regs ) { int pgm_check; BYTE shift; pgm_check = 0; if (add_fl->short_fract || add_fl->expo) { /* add_fl not 0 */ if (fl->short_fract || fl->expo) { /* fl not 0 */ /* both not 0 */ if (fl->expo == add_fl->expo) { /* expo equal */ /* both guard digits */ fl->short_fract <<= 4; add_fl->short_fract <<= 4; } else { /* expo not equal, denormalize */ if (fl->expo < add_fl->expo) { /* shift minus guard digit */ shift = add_fl->expo - fl->expo - 1; fl->expo = add_fl->expo; if (shift) { if (shift >= 6 || ((fl->short_fract >>= (shift * 4)) == 0)) { /* 0, copy summand */ fl->sign = add_fl->sign; fl->short_fract = add_fl->short_fract; if (fl->short_fract == 0) { pgm_check = significance_sf(fl, sigex, regs); } else { if (normal == NORMAL) { normal_sf(fl); pgm_check = underflow_sf(fl, regs); } } return(pgm_check); } } /* guard digit */ add_fl->short_fract <<= 4; } else { /* shift minus guard digit */ shift = fl->expo - add_fl->expo - 1; if (shift) { if (shift >= 6 || ((add_fl->short_fract >>= (shift * 4)) == 0)) { /* 0, nothing to add */ if (fl->short_fract == 0) { pgm_check = significance_sf(fl, sigex, regs); } else { if (normal == NORMAL) { normal_sf(fl); pgm_check = underflow_sf(fl, regs); } } return(pgm_check); } } /* guard digit */ fl->short_fract <<= 4; } } /* compute with guard digit */ if (fl->sign == add_fl->sign) { fl->short_fract += add_fl->short_fract; } else { if (fl->short_fract == add_fl->short_fract) { /* true 0 */ fl->short_fract = 0; return( significance_sf(fl, sigex, regs) ); } else if (fl->short_fract > add_fl->short_fract) { fl->short_fract -= add_fl->short_fract; } else { fl->short_fract = add_fl->short_fract - fl->short_fract; fl->sign = add_fl->sign; } } /* handle overflow with guard digit */ if (fl->short_fract & 0xF0000000) { fl->short_fract >>= 8; (fl->expo)++; pgm_check = overflow_sf(fl, regs); } else { if (normal == NORMAL) { /* normalize with guard digit */ if (fl->short_fract) { /* not 0 */ if (fl->short_fract & 0x0F000000) { /* not normalize, just guard digit */ fl->short_fract >>= 4; } else { (fl->expo)--; normal_sf(fl); pgm_check = underflow_sf(fl, regs); } } else { /* true 0 */ pgm_check = significance_sf(fl, sigex, regs); } } else { /* not normalize, just guard digit */ fl->short_fract >>= 4; if (fl->short_fract == 0) { pgm_check = significance_sf(fl, sigex, regs); } } } return(pgm_check); } else { /* fl 0, add_fl not 0 */ /* copy summand */ fl->expo = add_fl->expo; fl->sign = add_fl->sign; fl->short_fract = add_fl->short_fract; if (fl->short_fract == 0) { return( significance_sf(fl, sigex, regs) ); } } } else { /* add_fl 0 */ if (fl->short_fract == 0) { /* fl 0 */ /* both 0 */ return( significance_sf(fl, sigex, regs) ); } } if (normal == NORMAL) { normal_sf(fl); pgm_check = underflow_sf(fl, regs); } return(pgm_check); } /* end function add_sf */ /*-------------------------------------------------------------------*/ /* Add long float */ /* */ /* Input: */ /* fl Float */ /* add_fl Float to be added */ /* normal Normalize if true */ /* sigex Allow significance exception if true */ /* regs CPU register context */ /* Value: */ /* exeption */ /*-------------------------------------------------------------------*/ static int add_lf( LONG_FLOAT *fl, LONG_FLOAT *add_fl, BYTE normal, BYTE sigex, REGS *regs ) { int pgm_check; BYTE shift; pgm_check = 0; if (add_fl->long_fract || add_fl->expo) { /* add_fl not 0 */ if (fl->long_fract || fl->expo) { /* fl not 0 */ /* both not 0 */ if (fl->expo == add_fl->expo) { /* expo equal */ /* both guard digits */ fl->long_fract <<= 4; add_fl->long_fract <<= 4; } else { /* expo not equal, denormalize */ if (fl->expo < add_fl->expo) { /* shift minus guard digit */ shift = add_fl->expo - fl->expo - 1; fl->expo = add_fl->expo; if (shift) { if (shift >= 14 || ((fl->long_fract >>= (shift * 4)) == 0)) { /* 0, copy summand */ fl->sign = add_fl->sign; fl->long_fract = add_fl->long_fract; if (fl->long_fract == 0) { pgm_check = significance_lf(fl, sigex, regs); } else { if (normal == NORMAL) { normal_lf(fl); pgm_check = underflow_lf(fl, regs); } } return(pgm_check); } } /* guard digit */ add_fl->long_fract <<= 4; } else { /* shift minus guard digit */ shift = fl->expo - add_fl->expo - 1; if (shift) { if (shift >= 14 || ((add_fl->long_fract >>= (shift * 4)) == 0)) { /* 0, nothing to add */ if (fl->long_fract == 0) { pgm_check = significance_lf(fl, sigex, regs); } else { if (normal == NORMAL) { normal_lf(fl); pgm_check = underflow_lf(fl, regs); } } return(pgm_check); } } /* guard digit */ fl->long_fract <<= 4; } } /* compute with guard digit */ if (fl->sign == add_fl->sign) { fl->long_fract += add_fl->long_fract; } else { if (fl->long_fract == add_fl->long_fract) { /* true 0 */ fl->long_fract = 0; return( significance_lf(fl, sigex, regs) ); } else if (fl->long_fract > add_fl->long_fract) { fl->long_fract -= add_fl->long_fract; } else { fl->long_fract = add_fl->long_fract - fl->long_fract; fl->sign = add_fl->sign; } } /* handle overflow with guard digit */ if (fl->long_fract & 0xF000000000000000ULL) { fl->long_fract >>= 8; (fl->expo)++; pgm_check = overflow_lf(fl, regs); } else { if (normal == NORMAL) { /* normalize with guard digit */ if (fl->long_fract) { /* not 0 */ if (fl->long_fract & 0x0F00000000000000ULL) { /* not normalize, just guard digit */ fl->long_fract >>= 4; } else { (fl->expo)--; normal_lf(fl); pgm_check = underflow_lf(fl, regs); } } else { /* true 0 */ pgm_check = significance_lf(fl, sigex, regs); } } else { /* not normalize, just guard digit */ fl->long_fract >>= 4; if (fl->long_fract == 0) { pgm_check = significance_lf(fl, sigex, regs); } } } return(pgm_check); } else { /* fl 0, add_fl not 0 */ /* copy summand */ fl->expo = add_fl->expo; fl->sign = add_fl->sign; fl->long_fract = add_fl->long_fract; if (fl->long_fract == 0) { return( significance_lf(fl, sigex, regs) ); } } } else { /* add_fl 0 */ if (fl->long_fract == 0) { /* fl 0 */ /* both 0 */ return( significance_lf(fl, sigex, regs) ); } } if (normal == NORMAL) { normal_lf(fl); pgm_check = underflow_lf(fl, regs); } return(pgm_check); } /* end function add_lf */ /*-------------------------------------------------------------------*/ /* Add extended float normalized */ /* */ /* Input: */ /* fl Float */ /* add_fl Float to be added */ /* fpr Pointer to register */ /* regs CPU register context */ /* Value: */ /* exeption */ /*-------------------------------------------------------------------*/ static int add_ef( EXTENDED_FLOAT *fl, EXTENDED_FLOAT *add_fl, U32 *fpr, REGS *regs ) { int pgm_check; BYTE shift; pgm_check = 0; if (add_fl->ms_fract || add_fl->ls_fract || add_fl->expo) { /* add_fl not 0 */ if (fl->ms_fract || fl->ls_fract || fl->expo) { /* fl not 0 */ /* both not 0 */ if (fl->expo == add_fl->expo) { /* expo equal */ /* both guard digits */ fl->ms_fract = (fl->ms_fract << 4) | (fl->ls_fract >> 60); fl->ls_fract <<= 4; add_fl->ms_fract = (add_fl->ms_fract << 4) | (add_fl->ls_fract >> 60); add_fl->ls_fract <<= 4; } else { /* expo not equal, denormalize */ if (fl->expo < add_fl->expo) { /* shift minus guard digit */ shift = add_fl->expo - fl->expo - 1; fl->expo = add_fl->expo; if (shift) { if (shift >= 28) { /* 0, copy summand */ fl->sign = add_fl->sign; fl->ms_fract = add_fl->ms_fract; fl->ls_fract = add_fl->ls_fract; if ((fl->ms_fract == 0) && (fl->ls_fract == 0)) { pgm_check = significance_ef(fl, fpr, regs); } else { normal_ef(fl); pgm_check = underflow_ef(fl, fpr, regs); } return(pgm_check); } else if (shift >= 16) { fl->ls_fract = fl->ms_fract; if (shift > 16) { fl->ls_fract >>= (shift - 16) * 4; } fl->ms_fract = 0; } else { shift *= 4; fl->ls_fract = fl->ms_fract << (64 - shift) | fl->ls_fract >> shift; fl->ms_fract >>= shift; } if ((fl->ms_fract == 0) && (fl->ls_fract == 0)) { /* 0, copy summand */ fl->sign = add_fl->sign; fl->ms_fract = add_fl->ms_fract; fl->ls_fract = add_fl->ls_fract; if ((fl->ms_fract == 0) && (fl->ls_fract == 0)) { pgm_check = significance_ef(fl, fpr, regs); } else { normal_ef(fl); pgm_check = underflow_ef(fl, fpr, regs); } return(pgm_check); } } /* guard digit */ add_fl->ms_fract = (add_fl->ms_fract << 4) | (add_fl->ls_fract >> 60); add_fl->ls_fract <<= 4; } else { /* shift minus guard digit */ shift = fl->expo - add_fl->expo - 1; if (shift) { if (shift >= 28) { /* 0, nothing to add */ if ((fl->ms_fract == 0) && (fl->ls_fract == 0)) { pgm_check = significance_ef(fl, fpr, regs); } else { normal_ef(fl); pgm_check = underflow_ef(fl, fpr, regs); } return(pgm_check); } else if (shift >= 16) { add_fl->ls_fract = add_fl->ms_fract; if (shift > 16) { add_fl->ls_fract >>= (shift - 16) * 4; } add_fl->ms_fract = 0; } else { shift *= 4; add_fl->ls_fract = add_fl->ms_fract << (64 - shift) | add_fl->ls_fract >> shift; add_fl->ms_fract >>= shift; } if ((add_fl->ms_fract == 0) && (add_fl->ls_fract == 0)) { /* 0, nothing to add */ if ((fl->ms_fract == 0) && (fl->ls_fract == 0)) { pgm_check = significance_ef(fl, fpr, regs); } else { normal_ef(fl); pgm_check = underflow_ef(fl, fpr, regs); } return(pgm_check); } } /* guard digit */ fl->ms_fract = (fl->ms_fract << 4) | (fl->ls_fract >> 60); fl->ls_fract <<= 4; } } /* compute with guard digit */ if (fl->sign == add_fl->sign) { add_U128(fl->ms_fract, fl->ls_fract, add_fl->ms_fract, add_fl->ls_fract); } else { if ((fl->ms_fract == add_fl->ms_fract) && (fl->ls_fract == add_fl->ls_fract)) { /* true 0 */ fl->ms_fract = 0; fl->ls_fract = 0; return( significance_ef(fl, fpr, regs) ); } else if ( (fl->ms_fract > add_fl->ms_fract) || ( (fl->ms_fract == add_fl->ms_fract) && (fl->ls_fract > add_fl->ls_fract))) { sub_U128(fl->ms_fract, fl->ls_fract, add_fl->ms_fract, add_fl->ls_fract); } else { sub_reverse_U128(fl->ms_fract, fl->ls_fract, add_fl->ms_fract, add_fl->ls_fract); fl->sign = add_fl->sign; } } /* handle overflow with guard digit */ if (fl->ms_fract & 0x00F0000000000000ULL) { fl->ls_fract = (fl->ms_fract << 56) | (fl->ls_fract >> 8); fl->ms_fract >>= 8; (fl->expo)++; pgm_check = overflow_ef(fl, regs); store_ef( fl, fpr ); } else { /* normalize with guard digit */ if (fl->ms_fract || fl->ls_fract) { /* not 0 */ if (fl->ms_fract & 0x000F000000000000ULL) { /* not normalize, just guard digit */ fl->ls_fract = (fl->ms_fract << 60) | (fl->ls_fract >> 4); fl->ms_fract >>= 4; store_ef( fl, fpr ); } else { (fl->expo)--; normal_ef(fl); pgm_check = underflow_ef(fl, fpr, regs); } } else { /* true 0 */ pgm_check = significance_ef(fl, fpr, regs); } } return(pgm_check); } else { /* fl 0, add_fl not 0 */ /* copy summand */ fl->expo = add_fl->expo; fl->sign = add_fl->sign; fl->ms_fract = add_fl->ms_fract; fl->ls_fract = add_fl->ls_fract; if ((fl->ms_fract == 0) && (fl->ls_fract == 0)) { return( significance_ef(fl, fpr, regs) ); } } } else { /* add_fl 0*/ if ((fl->ms_fract == 0) && (fl->ls_fract == 0)) { /* fl 0 */ /* both 0 */ return( significance_ef(fl, fpr, regs) ); } } normal_ef(fl); return( underflow_ef(fl, fpr, regs) ); } /* end function add_ef */ /*-------------------------------------------------------------------*/ /* Compare short float */ /* */ /* Input: */ /* fl Float */ /* cmp_fl Float to be compared */ /* regs CPU register context */ /*-------------------------------------------------------------------*/ static void cmp_sf( SHORT_FLOAT *fl, SHORT_FLOAT *cmp_fl, REGS *regs ) { BYTE shift; if (cmp_fl->short_fract || cmp_fl->expo) { /* cmp_fl not 0 */ if (fl->short_fract || fl->expo) { /* fl not 0 */ /* both not 0 */ if (fl->expo == cmp_fl->expo) { /* expo equal */ /* both guard digits */ fl->short_fract <<= 4; cmp_fl->short_fract <<= 4; } else { /* expo not equal, denormalize */ if (fl->expo < cmp_fl->expo) { /* shift minus guard digit */ shift = cmp_fl->expo - fl->expo - 1; if (shift) { if (shift >= 6 || ((fl->short_fract >>= (shift * 4)) == 0)) { /* Set condition code */ if (cmp_fl->short_fract) { regs->psw.cc = cmp_fl->sign ? 2 : 1; } else { regs->psw.cc = 0; } return; } } /* guard digit */ cmp_fl->short_fract <<= 4; } else { /* shift minus guard digit */ shift = fl->expo - cmp_fl->expo - 1; if (shift) { if (shift >= 6 || ((cmp_fl->short_fract >>= (shift * 4)) == 0)) { /* Set condition code */ if (fl->short_fract) { regs->psw.cc = fl->sign ? 1 : 2; } else { regs->psw.cc = 0; } return; } } /* guard digit */ fl->short_fract <<= 4; } } /* compute with guard digit */ if (fl->sign != cmp_fl->sign) { fl->short_fract += cmp_fl->short_fract; } else if (fl->short_fract >= cmp_fl->short_fract) { fl->short_fract -= cmp_fl->short_fract; } else { fl->short_fract = cmp_fl->short_fract - fl->short_fract; fl->sign = ! (cmp_fl->sign); } /* handle overflow with guard digit */ if (fl->short_fract & 0xF0000000) { fl->short_fract >>= 4; } /* Set condition code */ if (fl->short_fract) { regs->psw.cc = fl->sign ? 1 : 2; } else { regs->psw.cc = 0; } return; } else { /* fl 0, cmp_fl not 0 */ /* Set condition code */ if (cmp_fl->short_fract) { regs->psw.cc = cmp_fl->sign ? 2 : 1; } else { regs->psw.cc = 0; } return; } } else { /* cmp_fl 0 */ /* Set condition code */ if (fl->short_fract) { regs->psw.cc = fl->sign ? 1 : 2; } else { regs->psw.cc = 0; } return; } } /* end function cmp_sf */ /*-------------------------------------------------------------------*/ /* Compare long float */ /* */ /* Input: */ /* fl Float */ /* cmp_fl Float to be compared */ /* regs CPU register context */ /*-------------------------------------------------------------------*/ static void cmp_lf( LONG_FLOAT *fl, LONG_FLOAT *cmp_fl, REGS *regs ) { BYTE shift; if (cmp_fl->long_fract || cmp_fl->expo) { /* cmp_fl not 0 */ if (fl->long_fract || fl->expo) { /* fl not 0 */ /* both not 0 */ if (fl->expo == cmp_fl->expo) { /* expo equal */ /* both guard digits */ fl->long_fract <<= 4; cmp_fl->long_fract <<= 4; } else { /* expo not equal, denormalize */ if (fl->expo < cmp_fl->expo) { /* shift minus guard digit */ shift = cmp_fl->expo - fl->expo - 1; if (shift) { if (shift >= 14 || ((fl->long_fract >>= (shift * 4)) == 0)) { /* Set condition code */ if (cmp_fl->long_fract) { regs->psw.cc = cmp_fl->sign ? 2 : 1; } else { regs->psw.cc = 0; } return; } } /* guard digit */ cmp_fl->long_fract <<= 4; } else { /* shift minus guard digit */ shift = fl->expo - cmp_fl->expo - 1; if (shift) { if (shift >= 14 || ((cmp_fl->long_fract >>= (shift * 4)) == 0)) { /* Set condition code */ if (fl->long_fract) { regs->psw.cc = fl->sign ? 1 : 2; } else { regs->psw.cc = 0; } return; } } /* guard digit */ fl->long_fract <<= 4; } } /* compute with guard digit */ if (fl->sign != cmp_fl->sign) { fl->long_fract += cmp_fl->long_fract; } else if (fl->long_fract >= cmp_fl->long_fract) { fl->long_fract -= cmp_fl->long_fract; } else { fl->long_fract = cmp_fl->long_fract - fl->long_fract; fl->sign = ! (cmp_fl->sign); } /* handle overflow with guard digit */ if (fl->long_fract & 0xF0000000) { fl->long_fract >>= 4; } /* Set condition code */ if (fl->long_fract) { regs->psw.cc = fl->sign ? 1 : 2; } else { regs->psw.cc = 0; } return; } else { /* fl 0, cmp_fl not 0 */ /* Set condition code */ if (cmp_fl->long_fract) { regs->psw.cc = cmp_fl->sign ? 2 : 1; } else { regs->psw.cc = 0; } return; } } else { /* cmp_fl 0 */ /* Set condition code */ if (fl->long_fract) { regs->psw.cc = fl->sign ? 1 : 2; } else { regs->psw.cc = 0; } return; } } /* end function cmp_lf */ /*-------------------------------------------------------------------*/ /* Multiply short float to long float */ /* */ /* Input: */ /* fl Multiplicand short float */ /* mul_fl Multiplicator short float */ /* result_fl Result long float */ /* regs CPU register context */ /* Value: */ /* exeption */ /*-------------------------------------------------------------------*/ static int mul_sf_to_lf( SHORT_FLOAT *fl, SHORT_FLOAT *mul_fl, LONG_FLOAT *result_fl, REGS *regs ) { if (fl->short_fract && mul_fl->short_fract) { /* normalize operands */ normal_sf( fl ); normal_sf( mul_fl ); /* multiply fracts */ result_fl->long_fract = (U64) fl->short_fract * mul_fl->short_fract; /* normalize result and compute expo */ if (result_fl->long_fract & 0x0000F00000000000ULL) { result_fl->long_fract <<= 8; result_fl->expo = fl->expo + mul_fl->expo - 64; } else { result_fl->long_fract <<= 12; result_fl->expo = fl->expo + mul_fl->expo - 65; } /* determine sign */ result_fl->sign = (fl->sign == mul_fl->sign) ? POS : NEG; /* handle overflow and underflow */ return( over_under_flow_lf(result_fl, regs) ); } else { /* set true 0 */ result_fl->long_fract = 0; result_fl->expo = 0; result_fl->sign = POS; return(0); } } /* end function mul_sf_to_lf */ /*-------------------------------------------------------------------*/ /* Multiply long float to extended float */ /* */ /* Input: */ /* fl Multiplicand long float */ /* mul_fl Multiplicator long float */ /* result_fl Result extended float */ /* regs CPU register context */ /* Value: */ /* exeption */ /*-------------------------------------------------------------------*/ static int mul_lf_to_ef( LONG_FLOAT *fl, LONG_FLOAT *mul_fl, EXTENDED_FLOAT *result_fl, REGS *regs ) { U64 wk; if (fl->long_fract && mul_fl->long_fract) { /* normalize operands */ normal_lf( fl ); normal_lf( mul_fl ); /* multiply fracts by sum of partial multiplications */ wk = (fl->long_fract & 0x00000000FFFFFFFFULL) * (mul_fl->long_fract & 0x00000000FFFFFFFFULL); result_fl->ls_fract = wk & 0x00000000FFFFFFFFULL; wk >>= 32; wk += ((fl->long_fract & 0x00000000FFFFFFFFULL) * (mul_fl->long_fract >> 32)); wk += ((fl->long_fract >> 32) * (mul_fl->long_fract & 0x00000000FFFFFFFFULL)); result_fl->ls_fract |= wk << 32; result_fl->ms_fract = (wk >> 32) + ((fl->long_fract >> 32) * (mul_fl->long_fract >> 32)); /* normalize result and compute expo */ if (result_fl->ms_fract & 0x0000F00000000000ULL) { result_fl->expo = fl->expo + mul_fl->expo - 64; } else { result_fl->ms_fract = (result_fl->ms_fract << 4) | (result_fl->ls_fract >> 60); result_fl->ls_fract <<= 4; result_fl->expo = fl->expo + mul_fl->expo - 65; } /* determine sign */ result_fl->sign = (fl->sign == mul_fl->sign) ? POS : NEG; /* handle overflow and underflow */ return( over_under_flow_ef(result_fl, regs) ); } else { /* set true 0 */ result_fl->ms_fract = 0; result_fl->ls_fract = 0; result_fl->expo = 0; result_fl->sign = POS; return(0); } } /* end function mul_lf_to_ef */ #if defined(FEATURE_HFP_EXTENSIONS) \ || defined(FEATURE_HFP_MULTIPLY_ADD_SUBTRACT) /*-------------------------------------------------------------------*/ /* Multiply short float */ /* */ /* Input: */ /* fl Multiplicand short float */ /* mul_fl Multiplicator short float */ /* ovunf Handle overflow/underflow if true */ /* regs CPU register context */ /* Value: */ /* exeption */ /*-------------------------------------------------------------------*/ static int mul_sf( SHORT_FLOAT *fl, SHORT_FLOAT *mul_fl, BYTE ovunf, REGS *regs ) { U64 wk; if (fl->short_fract && mul_fl->short_fract) { /* normalize operands */ normal_sf( fl ); normal_sf( mul_fl ); /* multiply fracts */ wk = (U64) fl->short_fract * mul_fl->short_fract; /* normalize result and compute expo */ if (wk & 0x0000F00000000000ULL) { fl->short_fract = wk >> 24; fl->expo = fl->expo + mul_fl->expo - 64; } else { fl->short_fract = wk >> 20; fl->expo = fl->expo + mul_fl->expo - 65; } /* determine sign */ fl->sign = (fl->sign == mul_fl->sign) ? POS : NEG; /* handle overflow and underflow if required */ if (ovunf == OVUNF) return( over_under_flow_sf(fl, regs) ); /* otherwise leave exponent as is */ return(0); } else { /* set true 0 */ fl->short_fract = 0; fl->expo = 0; fl->sign = POS; return(0); } } /* end function mul_sf */ #endif /*FEATURE_HFP_EXTENSIONS || FEATURE_HFP_MULTIPLY_ADD_SUBTRACT*/ /*-------------------------------------------------------------------*/ /* Multiply long float */ /* */ /* Input: */ /* fl Multiplicand long float */ /* mul_fl Multiplicator long float */ /* ovunf Handle overflow/underflow if true */ /* regs CPU register context */ /* Value: */ /* exeption */ /*-------------------------------------------------------------------*/ static int mul_lf( LONG_FLOAT *fl, LONG_FLOAT *mul_fl, BYTE ovunf, REGS *regs ) { U64 wk; U32 v; if (fl->long_fract && mul_fl->long_fract) { /* normalize operands */ normal_lf( fl ); normal_lf( mul_fl ); /* multiply fracts by sum of partial multiplications */ wk = ((fl->long_fract & 0x00000000FFFFFFFFULL) * (mul_fl->long_fract & 0x00000000FFFFFFFFULL)) >> 32; wk += ((fl->long_fract & 0x00000000FFFFFFFFULL) * (mul_fl->long_fract >> 32)); wk += ((fl->long_fract >> 32) * (mul_fl->long_fract & 0x00000000FFFFFFFFULL)); v = wk; fl->long_fract = (wk >> 32) + ((fl->long_fract >> 32) * (mul_fl->long_fract >> 32)); /* normalize result and compute expo */ if (fl->long_fract & 0x0000F00000000000ULL) { fl->long_fract = (fl->long_fract << 8) | (v >> 24); fl->expo = fl->expo + mul_fl->expo - 64; } else { fl->long_fract = (fl->long_fract << 12) | (v >> 20); fl->expo = fl->expo + mul_fl->expo - 65; } /* determine sign */ fl->sign = (fl->sign == mul_fl->sign) ? POS : NEG; /* handle overflow and underflow if required */ if (ovunf == OVUNF) return( over_under_flow_lf(fl, regs) ); /* otherwise leave exponent as is */ return(0); } else { /* set true 0 */ fl->long_fract = 0; fl->expo = 0; fl->sign = POS; return(0); } } /* end function mul_lf */ /*-------------------------------------------------------------------*/ /* Multiply extended float */ /* */ /* Input: */ /* fl Multiplicand extended float */ /* mul_fl Multiplicator extended float */ /* regs CPU register context */ /* Value: */ /* exeption */ /*-------------------------------------------------------------------*/ static int mul_ef( EXTENDED_FLOAT *fl, EXTENDED_FLOAT *mul_fl, REGS *regs ) { U64 wk1; U64 wk2; U64 wk3; U64 wk4; U64 wk; U32 wk0; U32 v; if ((fl->ms_fract || fl->ls_fract) && (mul_fl->ms_fract || mul_fl->ls_fract)) { /* normalize operands */ normal_ef ( fl ); normal_ef ( mul_fl ); /* multiply fracts by sum of partial multiplications */ wk0 = ((fl->ls_fract & 0x00000000FFFFFFFFULL) * (mul_fl->ls_fract & 0x00000000FFFFFFFFULL)) >> 32; wk1 = (fl->ls_fract & 0x00000000FFFFFFFFULL) * (mul_fl->ls_fract >> 32); wk2 = (fl->ls_fract >> 32) * (mul_fl->ls_fract & 0x00000000FFFFFFFFULL); wk = wk0 + (wk1 & 0x00000000FFFFFFFFULL) + (wk2 & 0x00000000FFFFFFFFULL); wk = (wk >> 32) + (wk1 >> 32) + (wk2 >> 32); wk1 = (fl->ls_fract & 0x00000000FFFFFFFFULL) * (mul_fl->ms_fract & 0x00000000FFFFFFFFULL); wk2 = (fl->ls_fract >> 32) * (mul_fl->ls_fract >> 32); wk3 = (fl->ms_fract & 0x00000000FFFFFFFFULL) * (mul_fl->ls_fract & 0x00000000FFFFFFFFULL); wk += ((wk1 & 0x00000000FFFFFFFFULL) + (wk2 & 0x00000000FFFFFFFFULL) + (wk3 & 0x00000000FFFFFFFFULL)); wk = (wk >> 32) + (wk1 >> 32) + (wk2 >> 32) + (wk3 >> 32); wk1 = (fl->ls_fract & 0x00000000FFFFFFFFULL) * (mul_fl->ms_fract >> 32); wk2 = (fl->ls_fract >> 32) * (mul_fl->ms_fract & 0x00000000FFFFFFFFULL); wk3 = (fl->ms_fract & 0x00000000FFFFFFFFULL) * (mul_fl->ls_fract >> 32); wk4 = (fl->ms_fract >> 32) * (mul_fl->ls_fract & 0x00000000FFFFFFFFULL); wk += ((wk1 & 0x00000000FFFFFFFFULL) + (wk2 & 0x00000000FFFFFFFFULL) + (wk3 & 0x00000000FFFFFFFFULL) + (wk4 & 0x00000000FFFFFFFFULL)); v = wk; wk = (wk >> 32) + (wk1 >> 32) + (wk2 >> 32) + (wk3 >> 32) + (wk4 >> 32); wk1 = (fl->ls_fract >> 32) * (mul_fl->ms_fract >> 32); wk2 = (fl->ms_fract & 0x00000000FFFFFFFFULL) * (mul_fl->ms_fract & 0x00000000FFFFFFFFULL); wk3 = (fl->ms_fract >> 32) * (mul_fl->ls_fract >> 32); wk += ((wk1 & 0x00000000FFFFFFFFULL) + (wk2 & 0x00000000FFFFFFFFULL) + (wk3 & 0x00000000FFFFFFFFULL)); fl->ls_fract = wk & 0x00000000FFFFFFFFULL; wk = (wk >> 32) + (wk1 >> 32) + (wk2 >> 32) + (wk3 >> 32); wk1 = (fl->ms_fract & 0x00000000FFFFFFFFULL) * (mul_fl->ms_fract >> 32); wk2 = (fl->ms_fract >> 32) * (mul_fl->ms_fract & 0x00000000FFFFFFFFULL); wk += ((wk1 & 0x00000000FFFFFFFFULL) + (wk2 & 0x00000000FFFFFFFFULL)); fl->ls_fract |= wk << 32; wk0 = (wk >> 32) + (wk1 >> 32) + (wk2 >> 32); wk0 += ((fl->ms_fract >> 32) * (mul_fl->ms_fract >> 32)); fl->ms_fract = wk0; /* normalize result and compute expo */ if (wk0 & 0xF0000000UL) { fl->ms_fract = (fl->ms_fract << 16) | (fl->ls_fract >> 48); fl->ls_fract = (fl->ls_fract << 16) | (v >> 16); fl->expo = fl->expo + mul_fl->expo - 64; } else { fl->ms_fract = (fl->ms_fract << 20) | (fl->ls_fract >> 44); fl->ls_fract = (fl->ls_fract << 20) | (v >> 12); fl->expo = fl->expo + mul_fl->expo - 65; } /* determine sign */ fl->sign = (fl->sign == mul_fl->sign) ? POS : NEG; /* handle overflow and underflow */ return ( over_under_flow_ef (fl, regs) ); } else { /* set true 0 */ fl->ms_fract = 0; fl->ls_fract = 0; fl->expo = 0; fl->sign = POS; return (0); } } /* end function mul_ef */ /*-------------------------------------------------------------------*/ /* Divide short float */ /* */ /* Input: */ /* fl Dividend short float */ /* div_fl Divisor short float */ /* regs CPU register context */ /* Value: */ /* exeption */ /*-------------------------------------------------------------------*/ static int div_sf( SHORT_FLOAT *fl, SHORT_FLOAT *div_fl, REGS *regs ) { U64 wk; if (div_fl->short_fract) { if (fl->short_fract) { /* normalize operands */ normal_sf( fl ); normal_sf( div_fl ); /* position fracts and compute expo */ if (fl->short_fract < div_fl->short_fract) { wk = (U64) fl->short_fract << 24; fl->expo = fl->expo - div_fl->expo + 64; } else { wk = (U64) fl->short_fract << 20; fl->expo = fl->expo - div_fl->expo + 65; } /* divide fractions */ fl->short_fract = wk / div_fl->short_fract; /* determine sign */ fl->sign = (fl->sign == div_fl->sign) ? POS : NEG; /* handle overflow and underflow */ return( over_under_flow_sf(fl, regs) ); } else { /* fraction of dividend 0, set true 0 */ fl->short_fract = 0; fl->expo = 0; fl->sign = POS; } } else { /* divisor 0 */ ARCH_DEP(program_interrupt) (regs, PGM_FLOATING_POINT_DIVIDE_EXCEPTION); } return(0); } /* end function div_sf */ /*-------------------------------------------------------------------*/ /* Divide long float */ /* */ /* Input: */ /* fl Dividend long float */ /* div_fl Divisor long float */ /* regs CPU register context */ /* Value: */ /* exeption */ /*-------------------------------------------------------------------*/ static int div_lf( LONG_FLOAT *fl, LONG_FLOAT *div_fl, REGS *regs ) { U64 wk; U64 wk2; int i; if (div_fl->long_fract) { if (fl->long_fract) { /* normalize operands */ normal_lf( fl ); normal_lf( div_fl ); /* position fracts and compute expo */ if (fl->long_fract < div_fl->long_fract) { fl->expo = fl->expo - div_fl->expo + 64; } else { fl->expo = fl->expo - div_fl->expo + 65; div_fl->long_fract <<= 4; } /* partial divide first hex digit */ wk2 = fl->long_fract / div_fl->long_fract; wk = (fl->long_fract % div_fl->long_fract) << 4; /* partial divide middle hex digits */ i = 13; while (i--) { wk2 = (wk2 << 4) | (wk / div_fl->long_fract); wk = (wk % div_fl->long_fract) << 4; } /* partial divide last hex digit */ fl->long_fract = (wk2 << 4) | (wk / div_fl->long_fract); /* determine sign */ fl->sign = (fl->sign == div_fl->sign) ? POS : NEG; /* handle overflow and underflow */ return( over_under_flow_lf(fl, regs) ); } else { /* fraction of dividend 0, set true 0 */ fl->long_fract = 0; fl->expo = 0; fl->sign = POS; } } else { /* divisor 0 */ ARCH_DEP(program_interrupt) (regs, PGM_FLOATING_POINT_DIVIDE_EXCEPTION); } return(0); } /* end function div_lf */ /*-------------------------------------------------------------------*/ /* Divide extended float */ /* */ /* Input: */ /* fl Dividend extended float */ /* div_fl Divisor extended float */ /* regs CPU register context */ /* Value: */ /* exeption */ /*-------------------------------------------------------------------*/ static int div_ef( EXTENDED_FLOAT *fl, EXTENDED_FLOAT *div_fl, REGS *regs ) { U64 wkm; U64 wkl; int i; if (div_fl->ms_fract || div_fl->ls_fract) { if (fl->ms_fract || fl->ls_fract) { /* normalize operands */ normal_ef( fl ); normal_ef( div_fl ); /* position fracts and compute expo */ if ((fl->ms_fract < div_fl->ms_fract) || ((fl->ms_fract == div_fl->ms_fract) && (fl->ls_fract < div_fl->ls_fract))) { fl->expo = fl->expo - div_fl->expo + 64; } else { fl->expo = fl->expo - div_fl->expo + 65; div_fl->ms_fract = (div_fl->ms_fract << 4) | (div_fl->ls_fract >> 60); div_fl->ls_fract <<= 4; } /* divide fractions */ /* the first binary digit */ wkm = fl->ms_fract; wkl = fl->ls_fract; sub_U128(wkm, wkl, div_fl->ms_fract, div_fl->ls_fract); wkm = (wkm << 1) | (wkl >> 63); wkl <<= 1; fl->ms_fract = 0; if (((S64)wkm) >= 0) { fl->ls_fract = 1; sub_U128(wkm, wkl, div_fl->ms_fract, div_fl->ls_fract); } else { fl->ls_fract = 0; add_U128(wkm, wkl, div_fl->ms_fract, div_fl->ls_fract); } /* the middle binary digits */ i = 111; while (i--) { wkm = (wkm << 1) | (wkl >> 63); wkl <<= 1; fl->ms_fract = (fl->ms_fract << 1) | (fl->ls_fract >> 63); fl->ls_fract <<= 1; if (((S64)wkm) >= 0) { fl->ls_fract |= 1; sub_U128(wkm, wkl, div_fl->ms_fract, div_fl->ls_fract); } else { add_U128(wkm, wkl, div_fl->ms_fract, div_fl->ls_fract); } } /* the last binary digit */ fl->ms_fract = (fl->ms_fract << 1) | (fl->ls_fract >> 63); fl->ls_fract <<= 1; if (((S64)wkm) >= 0) { fl->ls_fract |= 1; } /* determine sign */ fl->sign = (fl->sign == div_fl->sign) ? POS : NEG; /* handle overflow and underflow */ return( over_under_flow_ef(fl, regs) ); } else { /* fraction of dividend 0, set true 0 */ fl->ms_fract = 0; fl->ls_fract = 0; fl->expo = 0; fl->sign = POS; } } else { /* divisor 0 */ ARCH_DEP(program_interrupt) (regs, PGM_FLOATING_POINT_DIVIDE_EXCEPTION); } return(0); } /* end function div_ef */ #if defined (FEATURE_SQUARE_ROOT) /*-------------------------------------------------------------------*/ /* Square root of fraction */ /* This routine uses the Newton-Iteration-Method */ /* The iteration is startet with a table look up */ /* */ /* Input: */ /* a short fraction expanded to U64 */ /* Value: */ /* square root as U32 */ /*-------------------------------------------------------------------*/ static U32 square_root_fraction( U64 a ) { U32 xi; U32 xj; static const unsigned short sqtab[] = { /* 0 */ 0, /* 1 */ 304, /* 2 */ 401, /* 3 */ 476, /* 4 */ 541, /* 5 */ 599, /* 6 */ 652, /* 7 */ 700, /* 8 */ 746, /* 9 */ 788, /* 10 */ 829, /* 11 */ 868, /* 12 */ 905, /* 13 */ 940, /* 14 */ 975, /* 15 */ 1008, /* 16 */ 1040, /* 17 */ 1071, /* 18 */ 1101, /* 19 */ 1130, /* 20 */ 1159, /* 21 */ 1187, /* 22 */ 1214, /* 23 */ 1241, /* 24 */ 1267, /* 25 */ 1293, /* 26 */ 1318, /* 27 */ 1342, /* 28 */ 1367, /* 29 */ 1390, /* 30 */ 1414, /* 31 */ 1437, /* 32 */ 1459, /* 33 */ 1482, /* 34 */ 1504, /* 35 */ 1525, /* 36 */ 1547, /* 37 */ 1568, /* 38 */ 1588, /* 39 */ 1609, /* 40 */ 1629, /* 41 */ 1649, /* 42 */ 1669, /* 43 */ 1688, /* 44 */ 1708, /* 45 */ 1727, /* 46 */ 1746, /* 47 */ 1764, /* 48 */ 1783, /* 49 */ 1801, /* 50 */ 1819, /* 51 */ 1837, /* 52 */ 1855, /* 53 */ 1872, /* 54 */ 1890, /* 55 */ 1907, /* 56 */ 1924, /* 57 */ 1941, /* 58 */ 1958, /* 59 */ 1975, /* 60 */ 1991, /* 61 */ 2008, /* 62 */ 2024, /* 63 */ 2040, /* 64 */ 2056, /* 65 */ 2072, /* 66 */ 2088, /* 67 */ 2103, /* 68 */ 2119, /* 69 */ 2134, /* 70 */ 2149, /* 71 */ 2165, /* 72 */ 2180, /* 73 */ 2195, /* 74 */ 2210, /* 75 */ 2224, /* 76 */ 2239, /* 77 */ 2254, /* 78 */ 2268, /* 79 */ 2283, /* 80 */ 2297, /* 81 */ 2311, /* 82 */ 2325, /* 83 */ 2339, /* 84 */ 2353, /* 85 */ 2367, /* 86 */ 2381, /* 87 */ 2395, /* 88 */ 2408, /* 89 */ 2422, /* 90 */ 2435, /* 91 */ 2449, /* 92 */ 2462, /* 93 */ 2475, /* 94 */ 2489, /* 95 */ 2502, /* 96 */ 2515, /* 97 */ 2528, /* 98 */ 2541, /* 99 */ 2554, /* 100 */ 2566, /* 101 */ 2579, /* 102 */ 2592, /* 103 */ 2604, /* 104 */ 2617, /* 105 */ 2629, /* 106 */ 2642, /* 107 */ 2654, /* 108 */ 2667, /* 109 */ 2679, /* 110 */ 2691, /* 111 */ 2703, /* 112 */ 2715, /* 113 */ 2727, /* 114 */ 2739, /* 115 */ 2751, /* 116 */ 2763, /* 117 */ 2775, /* 118 */ 2787, /* 119 */ 2798, /* 120 */ 2810, /* 121 */ 2822, /* 122 */ 2833, /* 123 */ 2845, /* 124 */ 2856, /* 125 */ 2868, /* 126 */ 2879, /* 127 */ 2891, /* 128 */ 2902, /* 129 */ 2913, /* 130 */ 2924, /* 131 */ 2936, /* 132 */ 2947, /* 133 */ 2958, /* 134 */ 2969, /* 135 */ 2980, /* 136 */ 2991, /* 137 */ 3002, /* 138 */ 3013, /* 139 */ 3024, /* 140 */ 3034, /* 141 */ 3045, /* 142 */ 3056, /* 143 */ 3067, /* 144 */ 3077, /* 145 */ 3088, /* 146 */ 3099, /* 147 */ 3109, /* 148 */ 3120, /* 149 */ 3130, /* 150 */ 3141, /* 151 */ 3151, /* 152 */ 3161, /* 153 */ 3172, /* 154 */ 3182, /* 155 */ 3192, /* 156 */ 3203, /* 157 */ 3213, /* 158 */ 3223, /* 159 */ 3233, /* 160 */ 3243, /* 161 */ 3253, /* 162 */ 3263, /* 163 */ 3273, /* 164 */ 3283, /* 165 */ 3293, /* 166 */ 3303, /* 167 */ 3313, /* 168 */ 3323, /* 169 */ 3333, /* 170 */ 3343, /* 171 */ 3353, /* 172 */ 3362, /* 173 */ 3372, /* 174 */ 3382, /* 175 */ 3391, /* 176 */ 3401, /* 177 */ 3411, /* 178 */ 3420, /* 179 */ 3430, /* 180 */ 3439, /* 181 */ 3449, /* 182 */ 3458, /* 183 */ 3468, /* 184 */ 3477, /* 185 */ 3487, /* 186 */ 3496, /* 187 */ 3505, /* 188 */ 3515, /* 189 */ 3524, /* 190 */ 3533, /* 191 */ 3543, /* 192 */ 3552, /* 193 */ 3561, /* 194 */ 3570, /* 195 */ 3579, /* 196 */ 3589, /* 197 */ 3598, /* 198 */ 3607, /* 199 */ 3616, /* 200 */ 3625, /* 201 */ 3634, /* 202 */ 3643, /* 203 */ 3652, /* 204 */ 3661, /* 205 */ 3670, /* 206 */ 3679, /* 207 */ 3688, /* 208 */ 3697, /* 209 */ 3705, /* 210 */ 3714, /* 211 */ 3723, /* 212 */ 3732, /* 213 */ 3741, /* 214 */ 3749, /* 215 */ 3758, /* 216 */ 3767, /* 217 */ 3775, /* 218 */ 3784, /* 219 */ 3793, /* 220 */ 3801, /* 221 */ 3810, /* 222 */ 3819, /* 223 */ 3827, /* 224 */ 3836, /* 225 */ 3844, /* 226 */ 3853, /* 227 */ 3861, /* 228 */ 3870, /* 229 */ 3878, /* 230 */ 3887, /* 231 */ 3895, /* 232 */ 3903, /* 233 */ 3912, /* 234 */ 3920, /* 235 */ 3929, /* 236 */ 3937, /* 237 */ 3945, /* 238 */ 3954, /* 239 */ 3962, /* 240 */ 3970, /* 241 */ 3978, /* 242 */ 3987, /* 243 */ 3995, /* 244 */ 4003, /* 245 */ 4011, /* 246 */ 4019, /* 247 */ 4027, /* 248 */ 4036, /* 249 */ 4044, /* 250 */ 4052, /* 251 */ 4060, /* 252 */ 4068, /* 253 */ 4076, /* 254 */ 4084, /* 255 */ 4092 }; /* initial table look up */ xi = ((U32) sqtab[a >> 48]) << 16; if (xi == 0) return(xi); /* iterate */ /* exit iteration when xi, xj equal or differ by 1 */ for (;;) { xj = (((U32)(a / xi)) + xi) >> 1; if ((xj == xi) || (abs(xj - xi) == 1)) { break; } xi = xj; } return(xj); } /* end function square_root_fraction */ /*-------------------------------------------------------------------*/ /* Divide 128 bit integer by 64 bit integer */ /* The result is returned as 64 bit integer */ /* */ /* Input: */ /* msa most significant 64 bit of dividend */ /* lsa least significant 64 bit of dividend */ /* div divisor */ /* Value: */ /* quotient */ /*-------------------------------------------------------------------*/ static U64 div_U128( U64 msa, U64 lsa, U64 div ) { U64 q; int i; /* the first binary digit */ msa -= div; shift_left_U128(msa, lsa); if (((S64)msa) >= 0) { q = 1; msa -= div; } else { q = 0; msa += div; } /* the middle binary digits */ i = 63; while (i--) { shift_left_U128(msa, lsa); q <<= 1; if (((S64)msa) >= 0) { q |= 1; msa -= div; } else { msa += div; } } /* the last binary digit */ q <<= 1; if (((S64)msa) >= 0) { q |= 1; } return(q); } /* end function div_U128 */ /*-------------------------------------------------------------------*/ /* Square root short float */ /* */ /* Input: */ /* sq_fl Result short float */ /* fl Input short float */ /* regs CPU register context */ /*-------------------------------------------------------------------*/ static void sq_sf( SHORT_FLOAT *sq_fl, SHORT_FLOAT *fl, REGS *regs ) { U64 a; U32 x; if (fl->short_fract) { if (fl->sign) { /* less than zero */ sq_fl->short_fract = 0; sq_fl->expo = 0; ARCH_DEP(program_interrupt) (regs, PGM_SQUARE_ROOT_EXCEPTION); } else { /* normalize operand */ normal_sf(fl); if (fl->expo & 1) { /* odd */ /* compute characteristic */ sq_fl->expo = (fl->expo + 65) >> 1; /* with guard digit */ a = (U64) fl->short_fract << 28; } else { /* even */ /* compute characteristic */ sq_fl->expo = (fl->expo + 64) >> 1; /* without guard digit */ a = (U64) fl->short_fract << 32; } /* square root of fraction */ /* common subroutine of all square root */ x = square_root_fraction(a); /* round with guard digit */ sq_fl->short_fract = (x + 8) >> 4; } } else { /* true zero */ sq_fl->short_fract = 0; sq_fl->expo = 0; } /* all results positive */ sq_fl->sign = POS; } /* end function sq_sf */ /*-------------------------------------------------------------------*/ /* Square root long float */ /* */ /* Input: */ /* sq_fl Result long float */ /* fl Input long float */ /* regs CPU register context */ /*-------------------------------------------------------------------*/ static void sq_lf( LONG_FLOAT *sq_fl, LONG_FLOAT *fl, REGS *regs ) { U64 msa, lsa; U64 xi; U64 xj; if (fl->long_fract) { if (fl->sign) { /* less than zero */ ARCH_DEP(program_interrupt) (regs, PGM_SQUARE_ROOT_EXCEPTION); } else { /* normalize operand */ normal_lf(fl); if (fl->expo & 1) { /* odd */ /* compute characteristic */ sq_fl->expo = (fl->expo + 65) >> 1; /* with guard digit */ msa = fl->long_fract >> 4; lsa = fl->long_fract << 60; } else { /* even */ /* compute characteristic */ sq_fl->expo = (fl->expo + 64) >> 1; /* without guard digit */ msa = fl->long_fract; lsa = 0; } /* square root of fraction low precision */ /* common subroutine of all square root */ xi = ((U64) (square_root_fraction(msa & 0xFFFFFFFFFFFFFFFEULL)) << 32) | 0x80000000UL; /* continue iteration for high precision */ for (;;) { xj = (div_U128(msa, lsa, xi) + xi) >> 1; if (xj == xi) { break; } xi = xj; } /* round with guard digit */ sq_fl->long_fract = (xi + 8) >> 4; } } else { /* true zero */ sq_fl->long_fract = 0; sq_fl->expo = 0; } /* all results positive */ sq_fl->sign = POS; } /* end function sq_lf */ #endif /* FEATURE_SQUARE_ROOT */ #if defined (FEATURE_HFP_EXTENSIONS) /*-------------------------------------------------------------------*/ /* Divide 256 bit integer by 128 bit integer */ /* The result is returned as 128 bit integer */ /* */ /* Input: */ /* mmsa most significant 64 bit of dividend */ /* msa more significant 64 bit of dividend */ /* lsa less significant 64 bit of dividend */ /* llsa least significant 64 bit of dividend */ /* msd most significant 64 bit of divisor */ /* lsd least significant 64 bit of divisor */ /* msq most significant 64 bit of quotient */ /* lsq least significant 64 bit of quotient */ /*-------------------------------------------------------------------*/ static void div_U256( U64 mmsa, U64 msa, U64 lsa, U64 llsa, U64 msd, U64 lsd, U64 *msq, U64 *lsq ) { int i; /* the first binary digit */ sub_U128(mmsa, msa, msd, lsd); shift_left_U256(mmsa, msa, lsa, llsa); *msq = 0; if (((S64)mmsa) >= 0) { *lsq = 1; sub_U128(mmsa, msa, msd, lsd); } else { *lsq = 0; add_U128(mmsa, msa, msd, lsd); } /* the middle binary digits */ i = 127; while (i--) { shift_left_U256(mmsa, msa, lsa, llsa); shift_left_U128(*msq, *lsq); if (((S64)mmsa) >= 0) { *lsq |= 1; sub_U128(mmsa, msa, msd, lsd); } else { add_U128(mmsa, msa, msd, lsd); } } /* the last binary digit */ shift_left_U128(*msq, *lsq); if (((S64)mmsa) >= 0) { *lsq |= 1; } } /* end function div_U256 */ #endif /* FEATURE_HFP_EXTENSIONS */ #if defined(FEATURE_HFP_UNNORMALIZED_EXTENSION) /*-------------------------------------------------------------------*/ /* Multiply long float to extended float unnormalized */ /* */ /* Input: */ /* fl Multiplicand long float */ /* mul_fl Multiplicator long float */ /* result_fl Intermediate extended float result */ /* regs CPU register context */ /* Value: */ /* none */ /*-------------------------------------------------------------------*/ static void ARCH_DEP(mul_lf_to_ef_unnorm)( LONG_FLOAT *fl, LONG_FLOAT *mul_fl, EXTENDED_FLOAT *result_fl ) { U64 wk; /* multiply fracts by sum of partial multiplications */ wk = (fl->long_fract & 0x00000000FFFFFFFFULL) * (mul_fl->long_fract & 0x00000000FFFFFFFFULL); result_fl->ls_fract = wk & 0x00000000FFFFFFFFULL; wk >>= 32; wk += ((fl->long_fract & 0x00000000FFFFFFFFULL) * (mul_fl->long_fract >> 32)); wk += ((fl->long_fract >> 32) * (mul_fl->long_fract & 0x00000000FFFFFFFFULL)); result_fl->ls_fract |= wk << 32; result_fl->ms_fract = (wk >> 32) + ((fl->long_fract >> 32) * (mul_fl->long_fract >> 32)); /* compute expo */ result_fl->expo = fl->expo + mul_fl->expo - 64; /* determine sign */ result_fl->sign = (fl->sign == mul_fl->sign) ? POS : NEG; } /* end function mul_lf_to_ef_unnorm */ /*-------------------------------------------------------------------*/ /* Add extended float unnormalized */ /* Note: This addition is specific to MULTIPLY AND ADD UNNORMALIZED */ /* set of instructions */ /* */ /* Input: */ /* prod_fl Extended Intermediate product */ /* add_fl Extended Addend */ /* result_fl Extended Intermediate result */ /* Value: */ /* none */ /*-------------------------------------------------------------------*/ static void ARCH_DEP(add_ef_unnorm)( EXTENDED_FLOAT *prod_fl, EXTENDED_FLOAT *add_fl, EXTENDED_FLOAT *result_fl ) { int ldigits = 0; /* or'd left digits shifted */ int rdigits = 0; /* or'd right digits shifted */ int xdigit; /* digit lost by addend shifting */ /* Note: In EXTENDED_FLOAT, ms_fract and ls_fract taken together*/ /* constitute a U128 value. */ /* Convert separate high/low fractions to contiguous U128 */ #if FLOAT_DEBUG logmsg (_("Prod Frac: %16.16llX %16.16llX\n"), prod_fl->ms_fract, prod_fl->ls_fract); logmsg (_("Adnd Frac: %16.16llX %16.16llX\n"), add_fl->ms_fract, add_fl->ls_fract); #endif result_fl->ms_fract = 0; result_fl->ls_fract = 0; /* Default result to product sign in case addend expo == prod expo */ result_fl->sign = prod_fl->sign; /* Step one - shift addend to match product's characteristic */ if (add_fl->expo < prod_fl->expo) { while(add_fl->expo != prod_fl->expo) { if ((!add_fl->ms_fract) && (!add_fl->ls_fract)) { /* If both the high and low parts of the fraction are zero */ /* we don't need to shift any more digits. */ /* Just force the exponents equal and quit */ add_fl->expo = prod_fl->expo; break; } /* shift addend fraction right until characteristics are equal */ shift_right4_U128(add_fl->ms_fract, add_fl->ls_fract, xdigit); rdigits |= xdigit; add_fl->expo += 1; } } else if(add_fl->expo > prod_fl->expo) { while(add_fl->expo != prod_fl->expo) { if ((!add_fl->ms_fract) && (!add_fl->ls_fract)) { /* If both the high and low parts of the fraction are zero */ /* we don't need to shift any more digits. */ /* Just force the exponents equal and quit */ add_fl->expo = prod_fl->expo; break; } /* shift addend fraction right until characteristics are equal */ shift_left4_U128(add_fl->ms_fract, add_fl->ls_fract, xdigit); ldigits |= xdigit; add_fl->expo -= 1; } } #if FLOAT_DEBUG logmsg (_("Shft Frac: %16.16llX %16.16llX\n"), add_fl->ms_fract, add_fl->ls_fract); #endif /* Step 2 - Do algebraic addition of aligned fractions */ if (add_fl->sign == prod_fl->sign) { /* signs equal, so just add fractions */ result_fl->sign = prod_fl->sign; result_fl->ms_fract = prod_fl->ms_fract; result_fl->ls_fract = prod_fl->ls_fract; add_U128(result_fl->ms_fract, result_fl->ls_fract, add_fl->ms_fract, add_fl->ls_fract); /* Recognize any overflow of left hand digits */ ldigits |= result_fl->ms_fract >> 48; /* Remove them from the result */ result_fl->ms_fract &= 0x0000FFFFFFFFFFFFULL; /* result sign already set to product sign */ } else { /* signs unequal, subtract the larger fraction from the smaller */ /* result has sign of the larger fraction */ if ( (prod_fl->ms_fract > add_fl->ms_fract) || ((prod_fl->ms_fract == add_fl->ms_fract) && (prod_fl->ls_fract >= add_fl->ls_fract)) ) /* product fraction larger than or equal to addend fraction */ { /* subtract addend fraction from product fraction */ /* result has sign of product */ result_fl->ms_fract = prod_fl->ms_fract; result_fl->ls_fract = prod_fl->ls_fract; if (rdigits) { /* If any right shifted addend digits, then we need to */ /* borrow from the product fraction to reflect the shifted*/ /* digits participation in the result */ sub_U128(result_fl->ms_fract, result_fl->ls_fract, (U64)0, (U64)1); #if FLOAT_DEBUG logmsg (_("Barw Frac: %16.16llX %16.16llX\n"), result_fl->ms_fract, result_fl->ls_fract); #endif /* Due to participation of right shifted digits */ /* result fraction NOT zero, so true zero will not result */ /* hence, force sign will not to change */ ldigits = 1; } sub_U128(result_fl->ms_fract, result_fl->ls_fract, add_fl->ms_fract, add_fl->ls_fract); #if FLOAT_DEBUG logmsg (_("P-A Frac: %16.16llX %16.16llX\n"), result_fl->ms_fract, result_fl->ls_fract); #endif /* result sign already set to product sign above as default */ } else /* addend fraction larger than product fraction */ { /* subtract product fraction from addend fraction */ /* result has sign of addend */ result_fl->ms_fract = add_fl->ms_fract; result_fl->ls_fract = add_fl->ls_fract; sub_U128(result_fl->ms_fract, result_fl->ls_fract, prod_fl->ms_fract, prod_fl->ls_fract); #if FLOAT_DEBUG logmsg (_("A-P Frac: %16.16llX %16.16llX\n"), result_fl->ms_fract, result_fl->ls_fract); #endif result_fl->sign = add_fl->sign; } } #if FLOAT_DEBUG logmsg (_("Resl Frac: %16.16llX %16.16llX\n"), result_fl->ms_fract, result_fl->ls_fract); #endif /* result exponent always the same as the product */ result_fl->expo = prod_fl->expo; /* Step 3 - If fraction is TRULY zero, sign is set to positive */ if ( (!result_fl->ms_fract) && (!result_fl->ls_fract) && (!ldigits) && (!rdigits) ) { result_fl->sign = POS; } } /* end ARCH_DEP(add_ef_unnorm) */ #endif /* defined(FEATURE_HFP_UNNORMALIZED_EXTENSION) */ /*-------------------------------------------------------------------*/ /* Extern functions */ /*-------------------------------------------------------------------*/ /*-------------------------------------------------------------------*/ /* 20 LPDR - Load Positive Floating Point Long Register [RR] */ /*-------------------------------------------------------------------*/ DEF_INST(load_positive_float_long_reg) { int r1, r2; /* Values of R fields */ int i1, i2; RR(inst, regs, r1, r2); HFPREG2_CHECK(r1, r2, regs); i1 = FPR2I(r1); i2 = FPR2I(r2); /* Copy register contents, clear the sign bit */ regs->fpr[i1] = regs->fpr[i2] & 0x7FFFFFFF; regs->fpr[i1+1] = regs->fpr[i2+1]; /* Set condition code */ regs->psw.cc = ((regs->fpr[i1] & 0x00FFFFFF) || regs->fpr[i1+1]) ? 2 : 0; } /*-------------------------------------------------------------------*/ /* 21 LNDR - Load Negative Floating Point Long Register [RR] */ /*-------------------------------------------------------------------*/ DEF_INST(load_negative_float_long_reg) { int r1, r2; /* Values of R fields */ int i1, i2; RR(inst, regs, r1, r2); HFPREG2_CHECK(r1, r2, regs); i1 = FPR2I(r1); i2 = FPR2I(r2); /* Copy register contents, set the sign bit */ regs->fpr[i1] = regs->fpr[i2] | 0x80000000; regs->fpr[i1+1] = regs->fpr[i2+1]; /* Set condition code */ regs->psw.cc = ((regs->fpr[i1] & 0x00FFFFFF) || regs->fpr[i1+1]) ? 1 : 0; } /*-------------------------------------------------------------------*/ /* 22 LTDR - Load and Test Floating Point Long Register [RR] */ /*-------------------------------------------------------------------*/ DEF_INST(load_and_test_float_long_reg) { int r1, r2; /* Values of R fields */ int i1, i2; RR(inst, regs, r1, r2); HFPREG2_CHECK(r1, r2, regs); i1 = FPR2I(r1); i2 = FPR2I(r2); /* Copy register contents */ regs->fpr[i1] = regs->fpr[i2]; regs->fpr[i1+1] = regs->fpr[i2+1]; /* Set condition code */ if ((regs->fpr[i1] & 0x00FFFFFF) || regs->fpr[i1+1]) { regs->psw.cc = (regs->fpr[i1] & 0x80000000) ? 1 : 2; } else { regs->psw.cc = 0; } } /*-------------------------------------------------------------------*/ /* 23 LCDR - Load Complement Floating Point Long Register [RR] */ /*-------------------------------------------------------------------*/ DEF_INST(load_complement_float_long_reg) { int r1, r2; /* Values of R fields */ int i1, i2; RR(inst, regs, r1, r2); HFPREG2_CHECK(r1, r2, regs); i1 = FPR2I(r1); i2 = FPR2I(r2); /* Copy register contents, invert sign bit */ regs->fpr[i1] = regs->fpr[i2] ^ 0x80000000; regs->fpr[i1+1] = regs->fpr[i2+1]; /* Set condition code */ if ((regs->fpr[i1] & 0x00FFFFFF) || regs->fpr[i1+1]) { regs->psw.cc = (regs->fpr[i1] & 0x80000000) ? 1 : 2; } else { regs->psw.cc = 0; } } /*-------------------------------------------------------------------*/ /* 24 HDR - Halve Floating Point Long Register [RR] */ /*-------------------------------------------------------------------*/ DEF_INST(halve_float_long_reg) { int r1, r2; /* Values of R fields */ LONG_FLOAT fl; int pgm_check; RR(inst, regs, r1, r2); HFPREG2_CHECK(r1, r2, regs); /* Get register content */ get_lf(&fl, regs->fpr + FPR2I(r2)); /* Halve the value */ if (fl.long_fract & 0x00E0000000000000ULL) { fl.long_fract >>= 1; pgm_check = 0; } else { fl.long_fract <<= 3; (fl.expo)--; normal_lf(&fl); pgm_check = underflow_lf(&fl, regs); } /* Back to register */ store_lf(&fl, regs->fpr + FPR2I(r1)); /* Program check ? */ if (pgm_check) { ARCH_DEP(program_interrupt) (regs, pgm_check); } } /*-------------------------------------------------------------------*/ /* 25 LDXR - Load Rounded Floating Point Long Register [RR] */ /* Older mnemonic of this instruction is LRDR */ /*-------------------------------------------------------------------*/ DEF_INST(load_rounded_float_long_reg) { int r1, r2; /* Values of R fields */ LONG_FLOAT fl; int pgm_check; RR(inst, regs, r1, r2); HFPREG_CHECK(r1, regs); HFPODD_CHECK(r2, regs); /* Get register content */ get_lf(&fl, regs->fpr + FPR2I(r2)); /* Rounding */ fl.long_fract += ((regs->fpr[FPR2I(r2 + 2)] >> 23) & 1); /* Handle overflow */ if (fl.long_fract & 0x0F00000000000000ULL) { fl.long_fract >>= 4; (fl.expo)++; pgm_check = overflow_lf(&fl, regs); } else { pgm_check = 0; } /* Back to register */ store_lf(&fl, regs->fpr + FPR2I(r1)); /* Program check ? */ if (pgm_check) { ARCH_DEP(program_interrupt) (regs, pgm_check); } } /*-------------------------------------------------------------------*/ /* 26 MXR - Multiply Floating Point Extended Register [RR] */ /*-------------------------------------------------------------------*/ DEF_INST(multiply_float_ext_reg) { int r1, r2; /* Values of R fields */ int i1; EXTENDED_FLOAT fl; EXTENDED_FLOAT mul_fl; int pgm_check; RR(inst, regs, r1, r2); HFPODD2_CHECK(r1, r2, regs); i1 = FPR2I(r1); /* Get the operands */ get_ef(&fl, regs->fpr + i1); get_ef(&mul_fl, regs->fpr + FPR2I(r2)); /* multiply extended */ pgm_check = mul_ef(&fl, &mul_fl, regs); /* Back to register */ store_ef(&fl, regs->fpr + i1); /* Program check ? */ if (pgm_check) { ARCH_DEP(program_interrupt) (regs, pgm_check); } } /*-------------------------------------------------------------------*/ /* 27 MXDR - Multiply Floating Point Long to Extended Reg. [RR] */ /*-------------------------------------------------------------------*/ DEF_INST(multiply_float_long_to_ext_reg) { int r1, r2; /* Values of R fields */ int i1; LONG_FLOAT fl; LONG_FLOAT mul_fl; EXTENDED_FLOAT result_fl; int pgm_check; RR(inst, regs, r1, r2); HFPODD_CHECK(r1, regs); i1 = FPR2I(r1); HFPREG_CHECK(r2, regs); /* Get the operands */ get_lf(&fl, regs->fpr + i1); get_lf(&mul_fl, regs->fpr + FPR2I(r2)); /* multiply long to extended */ pgm_check = mul_lf_to_ef(&fl, &mul_fl, &result_fl, regs); /* Back to register */ store_ef(&result_fl, regs->fpr + i1); /* Program check ? */ if (pgm_check) { ARCH_DEP(program_interrupt) (regs, pgm_check); } } /*-------------------------------------------------------------------*/ /* 28 LDR - Load Floating Point Long Register [RR] */ /*-------------------------------------------------------------------*/ DEF_INST(load_float_long_reg) { int r1, r2; /* Values of R fields */ int i1, i2; RR(inst, regs, r1, r2); HFPREG2_CHECK(r1, r2, regs); i1 = FPR2I(r1); i2 = FPR2I(r2); /* Copy register contents */ regs->fpr[i1] = regs->fpr[i2]; regs->fpr[i1+1] = regs->fpr[i2+1]; } /*-------------------------------------------------------------------*/ /* 29 CDR - Compare Floating Point Long Register [RR] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_float_long_reg) { int r1, r2; /* Values of R fields */ LONG_FLOAT fl; LONG_FLOAT cmp_fl; RR(inst, regs, r1, r2); HFPREG2_CHECK(r1, r2, regs); /* Get the operands */ get_lf(&fl, regs->fpr + FPR2I(r1)); get_lf(&cmp_fl, regs->fpr + FPR2I(r2)); /* Compare long */ cmp_lf(&fl, &cmp_fl, regs); } /*-------------------------------------------------------------------*/ /* 2A ADR - Add Floating Point Long Register [RR] */ /*-------------------------------------------------------------------*/ DEF_INST(add_float_long_reg) { int r1, r2; /* Values of R fields */ int i1; /* Index of R1 in fpr array */ LONG_FLOAT fl; LONG_FLOAT add_fl; int pgm_check; RR(inst, regs, r1, r2); HFPREG2_CHECK(r1, r2, regs); i1 = FPR2I(r1); /* Get the operands */ get_lf(&fl, regs->fpr + i1); get_lf(&add_fl, regs->fpr + FPR2I(r2)); /* Add long with normalization */ pgm_check = add_lf(&fl, &add_fl, NORMAL, SIGEX, regs); /* Set condition code */ if (fl.long_fract) { regs->psw.cc = fl.sign ? 1 : 2; } else { regs->psw.cc = 0; } /* Back to register */ store_lf(&fl, regs->fpr + i1); /* Program check ? */ if (pgm_check) { ARCH_DEP(program_interrupt) (regs, pgm_check); } } /* end DEF_INST(add_float_long_reg) */ /*-------------------------------------------------------------------*/ /* 2B SDR - Subtract Floating Point Long Register [RR] */ /*-------------------------------------------------------------------*/ DEF_INST(subtract_float_long_reg) { int r1, r2; /* Values of R fields */ int i1; /* Index of R1 in fpr array */ LONG_FLOAT fl; LONG_FLOAT sub_fl; int pgm_check; RR(inst, regs, r1, r2); HFPREG2_CHECK(r1, r2, regs); i1 = FPR2I(r1); /* Get the operands */ get_lf(&fl, regs->fpr + i1); get_lf(&sub_fl, regs->fpr + FPR2I(r2)); /* Invert the sign of 2nd operand */ sub_fl.sign = ! (sub_fl.sign); /* Add long with normalization */ pgm_check = add_lf(&fl, &sub_fl, NORMAL, SIGEX, regs); /* Set condition code */ if (fl.long_fract) { regs->psw.cc = fl.sign ? 1 : 2; } else { regs->psw.cc = 0; } /* Back to register */ store_lf(&fl, regs->fpr + i1); /* Program check ? */ if (pgm_check) { ARCH_DEP(program_interrupt) (regs, pgm_check); } } /* end DEF_INST(subtract_float_long_reg) */ /*-------------------------------------------------------------------*/ /* 2C MDR - Multiply Floating Point Long Register [RR] */ /*-------------------------------------------------------------------*/ DEF_INST(multiply_float_long_reg) { int r1, r2; /* Values of R fields */ int i1; /* Index of R1 in fpr array */ LONG_FLOAT fl; LONG_FLOAT mul_fl; int pgm_check; RR(inst, regs, r1, r2); HFPREG2_CHECK(r1, r2, regs); i1 = FPR2I(r1); /* Get the operands */ get_lf(&fl, regs->fpr + i1); get_lf(&mul_fl, regs->fpr + FPR2I(r2)); /* multiply long */ pgm_check = mul_lf(&fl, &mul_fl, OVUNF, regs); /* Back to register */ store_lf(&fl, regs->fpr + i1); /* Program check ? */ if (pgm_check) { ARCH_DEP(program_interrupt) (regs, pgm_check); } } /* end DEF_INST(multiply_float_long_reg) */ /*-------------------------------------------------------------------*/ /* 2D DDR - Divide Floating Point Long Register [RR] */ /*-------------------------------------------------------------------*/ DEF_INST(divide_float_long_reg) { int r1, r2; /* Values of R fields */ int i1; LONG_FLOAT fl; LONG_FLOAT div_fl; int pgm_check; RR(inst, regs, r1, r2); HFPREG2_CHECK(r1, r2, regs); i1 = FPR2I(r1); /* Get the operands */ get_lf(&fl, regs->fpr + i1); get_lf(&div_fl, regs->fpr + FPR2I(r2)); /* divide long */ pgm_check = div_lf(&fl, &div_fl, regs); /* Back to register */ store_lf(&fl, regs->fpr + i1); /* Program check ? */ if (pgm_check) { ARCH_DEP(program_interrupt) (regs, pgm_check); } } /*-------------------------------------------------------------------*/ /* 2E AWR - Add Unnormalized Floating Point Long Register [RR] */ /*-------------------------------------------------------------------*/ DEF_INST(add_unnormal_float_long_reg) { int r1, r2; /* Values of R fields */ int i1; /* Index of R1 in fpr array */ LONG_FLOAT fl; LONG_FLOAT add_fl; int pgm_check; RR(inst, regs, r1, r2); HFPREG2_CHECK(r1, r2, regs); i1 = FPR2I(r1); /* Get the operands */ get_lf(&fl, regs->fpr + i1); get_lf(&add_fl, regs->fpr + FPR2I(r2)); /* Add long without normalization */ pgm_check = add_lf(&fl, &add_fl, UNNORMAL, SIGEX, regs); /* Set condition code */ if (fl.long_fract) { regs->psw.cc = fl.sign ? 1 : 2; } else { regs->psw.cc = 0; } /* Back to register */ store_lf(&fl, regs->fpr + i1); /* Program check ? */ if (pgm_check) { ARCH_DEP(program_interrupt) (regs, pgm_check); } } /* end DEF_INST(add_unnormal_float_long_reg) */ /*-------------------------------------------------------------------*/ /* 2F SWR - Subtract Unnormalized Floating Point Long Reg. [RR] */ /*-------------------------------------------------------------------*/ DEF_INST(subtract_unnormal_float_long_reg) { int r1, r2; /* Values of R fields */ int i1; /* Index of R1 in fpr array */ LONG_FLOAT fl; LONG_FLOAT sub_fl; int pgm_check; RR(inst, regs, r1, r2); HFPREG2_CHECK(r1, r2, regs); i1 = FPR2I(r1); /* Get the operands */ get_lf(&fl, regs->fpr + i1); get_lf(&sub_fl, regs->fpr + FPR2I(r2)); /* Invert the sign of 2nd operand */ sub_fl.sign = ! (sub_fl.sign); /* Add long without normalization */ pgm_check = add_lf(&fl, &sub_fl, UNNORMAL, SIGEX, regs); /* Set condition code */ if (fl.long_fract) { regs->psw.cc = fl.sign ? 1 : 2; } else { regs->psw.cc = 0; } /* Back to register */ store_lf(&fl, regs->fpr + i1); /* Program check ? */ if (pgm_check) { ARCH_DEP(program_interrupt) (regs, pgm_check); } } /* end DEF_INST(subtract_unnormal_float_long_reg) */ /*-------------------------------------------------------------------*/ /* 30 LPER - Load Positive Floating Point Short Register [RR] */ /*-------------------------------------------------------------------*/ DEF_INST(load_positive_float_short_reg) { int r1, r2; /* Values of R fields */ int i1; RR(inst, regs, r1, r2); HFPREG2_CHECK(r1, r2, regs); i1 = FPR2I(r1); /* Copy register contents, clear sign bit */ regs->fpr[i1] = regs->fpr[FPR2I(r2)] & 0x7FFFFFFF; /* Set condition code */ regs->psw.cc = (regs->fpr[i1] & 0x00FFFFFF) ? 2 : 0; } /*-------------------------------------------------------------------*/ /* 31 LNER - Load Negative Floating Point Short Register [RR] */ /*-------------------------------------------------------------------*/ DEF_INST(load_negative_float_short_reg) { int r1, r2; /* Values of R fields */ int i1; RR(inst, regs, r1, r2); HFPREG2_CHECK(r1, r2, regs); i1 = FPR2I(r1); /* Copy register contents, set sign bit */ regs->fpr[i1] = regs->fpr[FPR2I(r2)] | 0x80000000; /* Set condition code */ regs->psw.cc = (regs->fpr[i1] & 0x00FFFFFF) ? 1 : 0; } /*-------------------------------------------------------------------*/ /* 32 LTER - Load and Test Floating Point Short Register [RR] */ /*-------------------------------------------------------------------*/ DEF_INST(load_and_test_float_short_reg) { int r1, r2; /* Values of R fields */ int i1; RR(inst, regs, r1, r2); HFPREG2_CHECK(r1, r2, regs); i1 = FPR2I(r1); /* Copy register contents */ regs->fpr[i1] = regs->fpr[FPR2I(r2)]; /* Set condition code */ if (regs->fpr[i1] & 0x00FFFFFF) { regs->psw.cc = (regs->fpr[i1] & 0x80000000) ? 1 : 2; } else { regs->psw.cc = 0; } } /*-------------------------------------------------------------------*/ /* 33 LCER - Load Complement Floating Point Short Register [RR] */ /*-------------------------------------------------------------------*/ DEF_INST(load_complement_float_short_reg) { int r1, r2; /* Values of R fields */ int i1; RR(inst, regs, r1, r2); HFPREG2_CHECK(r1, r2, regs); i1 = FPR2I(r1); /* Copy register contents, invert sign bit */ regs->fpr[i1] = regs->fpr[FPR2I(r2)] ^ 0x80000000; /* Set condition code */ if (regs->fpr[i1] & 0x00FFFFFF) { regs->psw.cc = (regs->fpr[i1] & 0x80000000) ? 1 : 2; } else { regs->psw.cc = 0; } } /*-------------------------------------------------------------------*/ /* 34 HER - Halve Floating Point Short Register [RR] */ /*-------------------------------------------------------------------*/ DEF_INST(halve_float_short_reg) { int r1, r2; /* Values of R fields */ SHORT_FLOAT fl; int pgm_check; RR(inst, regs, r1, r2); HFPREG2_CHECK(r1, r2, regs); /* Get register content */ get_sf(&fl, regs->fpr + FPR2I(r2)); /* Halve the value */ if (fl.short_fract & 0x00E00000) { fl.short_fract >>= 1; pgm_check = 0; } else { fl.short_fract <<= 3; (fl.expo)--; normal_sf(&fl); pgm_check = underflow_sf(&fl, regs); } /* Back to register */ store_sf(&fl, regs->fpr + FPR2I(r1)); /* Program check ? */ if (pgm_check) { ARCH_DEP(program_interrupt) (regs, pgm_check); } } /*-------------------------------------------------------------------*/ /* 35 LEDR - Load Rounded Floating Point Short Register [RR] */ /* Older mnemonic of this instruction is LRER */ /*-------------------------------------------------------------------*/ DEF_INST(load_rounded_float_short_reg) { int r1, r2; /* Values of R fields */ LONG_FLOAT from_fl; SHORT_FLOAT to_fl; int pgm_check; RR(inst, regs, r1, r2); HFPREG2_CHECK(r1, r2, regs); /* Get register content */ get_lf(&from_fl, regs->fpr + FPR2I(r2)); /* Rounding */ to_fl.short_fract = (from_fl.long_fract + 0x0000000080000000ULL) >> 32; to_fl.sign = from_fl.sign; to_fl.expo = from_fl.expo; /* Handle overflow */ if (to_fl.short_fract & 0x0F000000) { to_fl.short_fract >>= 4; (to_fl.expo)++; pgm_check = overflow_sf(&to_fl, regs); } else { pgm_check = 0; } /* To register */ store_sf(&to_fl, regs->fpr + FPR2I(r1)); /* Program check ? */ if (pgm_check) { ARCH_DEP(program_interrupt) (regs, pgm_check); } } /*-------------------------------------------------------------------*/ /* 36 AXR - Add Floating Point Extended Register [RR] */ /*-------------------------------------------------------------------*/ DEF_INST(add_float_ext_reg) { int r1, r2; /* Values of R fields */ int i1; EXTENDED_FLOAT fl; EXTENDED_FLOAT add_fl; int pgm_check; RR(inst, regs, r1, r2); HFPODD2_CHECK(r1, r2, regs); i1 = FPR2I(r1); /* Get the operands */ get_ef(&fl, regs->fpr + i1); get_ef(&add_fl, regs->fpr + FPR2I(r2)); /* Add extended */ pgm_check = add_ef(&fl, &add_fl, regs->fpr + i1, regs); /* Set condition code */ if (fl.ms_fract || fl.ls_fract) { regs->psw.cc = fl.sign ? 1 : 2; } else { regs->psw.cc = 0; } /* Program check ? */ if (pgm_check) { ARCH_DEP(program_interrupt) (regs, pgm_check); } } /*-------------------------------------------------------------------*/ /* 37 SXR - Subtract Floating Point Extended Register [RR] */ /*-------------------------------------------------------------------*/ DEF_INST(subtract_float_ext_reg) { int r1, r2; /* Values of R fields */ int i1; EXTENDED_FLOAT fl; EXTENDED_FLOAT sub_fl; int pgm_check; RR(inst, regs, r1, r2); HFPODD2_CHECK(r1, r2, regs); i1 = FPR2I(r1); /* Get the operands */ get_ef(&fl, regs->fpr + i1); get_ef(&sub_fl, regs->fpr + FPR2I(r2)); /* Invert the sign of 2nd operand */ sub_fl.sign = ! (sub_fl.sign); /* Add extended */ pgm_check = add_ef(&fl, &sub_fl, regs->fpr + i1, regs); /* Set condition code */ if (fl.ms_fract || fl.ls_fract) { regs->psw.cc = fl.sign ? 1 : 2; } else { regs->psw.cc = 0; } /* Program check ? */ if (pgm_check) { ARCH_DEP(program_interrupt) (regs, pgm_check); } } /*-------------------------------------------------------------------*/ /* 38 LER - Load Floating Point Short Register [RR] */ /*-------------------------------------------------------------------*/ DEF_INST(load_float_short_reg) { int r1, r2; /* Values of R fields */ RR(inst, regs, r1, r2); HFPREG2_CHECK(r1, r2, regs); /* Copy register content */ regs->fpr[FPR2I(r1)] = regs->fpr[FPR2I(r2)]; } /*-------------------------------------------------------------------*/ /* 39 CER - Compare Floating Point Short Register [RR] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_float_short_reg) { int r1, r2; /* Values of R fields */ SHORT_FLOAT fl; SHORT_FLOAT cmp_fl; RR(inst, regs, r1, r2); HFPREG2_CHECK(r1, r2, regs); /* Get the operands */ get_sf(&fl, regs->fpr + FPR2I(r1)); get_sf(&cmp_fl, regs->fpr + FPR2I(r2)); /* Compare short */ cmp_sf(&fl, &cmp_fl, regs); } /*-------------------------------------------------------------------*/ /* 3A AER - Add Floating Point Short Register [RR] */ /*-------------------------------------------------------------------*/ DEF_INST(add_float_short_reg) { int r1, r2; /* Values of R fields */ int i1; /* Index of R1 in fpr array */ SHORT_FLOAT fl; SHORT_FLOAT add_fl; int pgm_check; RR(inst, regs, r1, r2); HFPREG2_CHECK(r1, r2, regs); i1 = FPR2I(r1); /* Get the operands */ get_sf(&fl, regs->fpr + i1); get_sf(&add_fl, regs->fpr + FPR2I(r2)); /* Add short with normalization */ pgm_check = add_sf(&fl, &add_fl, NORMAL, SIGEX, regs); /* Set condition code */ if (fl.short_fract) { regs->psw.cc = fl.sign ? 1 : 2; } else { regs->psw.cc = 0; } /* Back to register */ store_sf(&fl, regs->fpr + i1); /* Program check ? */ if (pgm_check) { ARCH_DEP(program_interrupt) (regs, pgm_check); } } /* end DEF_INST(add_float_short_reg) */ /*-------------------------------------------------------------------*/ /* 3B SER - Subtract Floating Point Short Register [RR] */ /*-------------------------------------------------------------------*/ DEF_INST(subtract_float_short_reg) { int r1, r2; /* Values of R fields */ int i1; /* Index of R1 in fpr array */ SHORT_FLOAT fl; SHORT_FLOAT sub_fl; int pgm_check; RR(inst, regs, r1, r2); HFPREG2_CHECK(r1, r2, regs); i1 = FPR2I(r1); /* Get the operands */ get_sf(&fl, regs->fpr + i1); get_sf(&sub_fl, regs->fpr + FPR2I(r2)); /* Invert the sign of 2nd operand */ sub_fl.sign = ! (sub_fl.sign); /* Subtract short with normalization */ pgm_check = add_sf(&fl, &sub_fl, NORMAL, SIGEX, regs); /* Set condition code */ if (fl.short_fract) { regs->psw.cc = fl.sign ? 1 : 2; } else { regs->psw.cc = 0; } /* Back to register */ store_sf(&fl, regs->fpr + i1); /* Program check ? */ if (pgm_check) { ARCH_DEP(program_interrupt) (regs, pgm_check); } } /* end DEF_INST(subtract_float_short_reg) */ /*-------------------------------------------------------------------*/ /* 3C MDER - Multiply Short to Long Floating Point Register [RR] */ /* Older mnemonic of this instruction is MER */ /*-------------------------------------------------------------------*/ DEF_INST(multiply_float_short_to_long_reg) { int r1, r2; /* Values of R fields */ int i1; SHORT_FLOAT fl; SHORT_FLOAT mul_fl; LONG_FLOAT result_fl; int pgm_check; RR(inst, regs, r1, r2); HFPREG2_CHECK(r1, r2, regs); i1 = FPR2I(r1); /* Get the operands */ get_sf(&fl, regs->fpr + i1); get_sf(&mul_fl, regs->fpr + FPR2I(r2)); /* multiply short to long */ pgm_check = mul_sf_to_lf(&fl, &mul_fl, &result_fl, regs); /* Back to register */ store_lf(&result_fl, regs->fpr + i1); /* Program check ? */ if (pgm_check) { ARCH_DEP(program_interrupt) (regs, pgm_check); } } /*-------------------------------------------------------------------*/ /* 3D DER - Divide Floating Point Short Register [RR] */ /*-------------------------------------------------------------------*/ DEF_INST(divide_float_short_reg) { int r1, r2; /* Values of R fields */ int i1; SHORT_FLOAT fl; SHORT_FLOAT div_fl; int pgm_check; RR(inst, regs, r1, r2); HFPREG2_CHECK(r1, r2, regs); i1 = FPR2I(r1); /* Get the operands */ get_sf(&fl, regs->fpr + i1); get_sf(&div_fl, regs->fpr + FPR2I(r2)); /* divide short */ pgm_check = div_sf(&fl, &div_fl, regs); /* Back to register */ store_sf(&fl, regs->fpr + i1); /* Program check ? */ if (pgm_check) { ARCH_DEP(program_interrupt) (regs, pgm_check); } } /*-------------------------------------------------------------------*/ /* 3E AUR - Add Unnormalized Floating Point Short Register [RR] */ /*-------------------------------------------------------------------*/ DEF_INST(add_unnormal_float_short_reg) { int r1, r2; /* Values of R fields */ int i1; /* Index of R1 in fpr array */ SHORT_FLOAT fl; SHORT_FLOAT add_fl; int pgm_check; RR(inst, regs, r1, r2); HFPREG2_CHECK(r1, r2, regs); i1 = FPR2I(r1); /* Get the operands */ get_sf(&fl, regs->fpr + i1); get_sf(&add_fl, regs->fpr + FPR2I(r2)); /* Add short without normalization */ pgm_check = add_sf(&fl, &add_fl, UNNORMAL, SIGEX, regs); /* Set condition code */ if (fl.short_fract) { regs->psw.cc = fl.sign ? 1 : 2; } else { regs->psw.cc = 0; } /* Back to register */ store_sf(&fl, regs->fpr + i1); /* Program check ? */ if (pgm_check) { ARCH_DEP(program_interrupt) (regs, pgm_check); } } /* end DEF_INST(add_unnormal_float_short_reg) */ /*-------------------------------------------------------------------*/ /* 3F SUR - Subtract Unnormalized Floating Point Short Reg. [RR] */ /*-------------------------------------------------------------------*/ DEF_INST(subtract_unnormal_float_short_reg) { int r1, r2; /* Values of R fields */ int i1; /* Index of R1 in fpr array */ SHORT_FLOAT fl; SHORT_FLOAT sub_fl; int pgm_check; RR(inst, regs, r1, r2); HFPREG2_CHECK(r1, r2, regs); i1 = FPR2I(r1); /* Get the operands */ get_sf(&fl, regs->fpr + i1); get_sf(&sub_fl, regs->fpr + FPR2I(r2)); /* Invert the sign of 2nd operand */ sub_fl.sign = ! (sub_fl.sign); /* Add short without normalization */ pgm_check = add_sf(&fl, &sub_fl, UNNORMAL, SIGEX, regs); /* Set condition code */ if (fl.short_fract) { regs->psw.cc = fl.sign ? 1 : 2; } else { regs->psw.cc = 0; } /* Back to register */ store_sf(&fl, regs->fpr + i1); /* Program check ? */ if (pgm_check) { ARCH_DEP(program_interrupt) (regs, pgm_check); } } /* end DEF_INST(subtract_unnormal_float_short_reg) */ /*-------------------------------------------------------------------*/ /* 60 STD - Store Floating Point Long [RX] */ /*-------------------------------------------------------------------*/ DEF_INST(store_float_long) { int r1; /* Value of R field */ int i1; int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ U64 dreg; /* Double word workarea */ RX(inst, regs, r1, b2, effective_addr2); HFPREG_CHECK(r1, regs); i1 = FPR2I(r1); /* Store register contents at operand address */ dreg = ((U64)regs->fpr[i1] << 32) | regs->fpr[i1+1]; ARCH_DEP(vstore8) (dreg, effective_addr2, b2, regs); } /*-------------------------------------------------------------------*/ /* 67 MXD - Multiply Floating Point Long to Extended [RX] */ /*-------------------------------------------------------------------*/ DEF_INST(multiply_float_long_to_ext) { int r1; /* Value of R field */ int i1; int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ LONG_FLOAT fl; LONG_FLOAT mul_fl; EXTENDED_FLOAT result_fl; int pgm_check; RX(inst, regs, r1, b2, effective_addr2); HFPODD_CHECK(r1, regs); i1 = FPR2I(r1); /* Get the operands */ get_lf(&fl, regs->fpr + i1); vfetch_lf(&mul_fl, effective_addr2, b2, regs ); /* multiply long to extended */ pgm_check = mul_lf_to_ef(&fl, &mul_fl, &result_fl, regs); /* Back to register */ store_ef(&result_fl, regs->fpr + i1); /* Program check ? */ if (pgm_check) { ARCH_DEP(program_interrupt) (regs, pgm_check); } } /*-------------------------------------------------------------------*/ /* 68 LD - Load Floating Point Long [RX] */ /*-------------------------------------------------------------------*/ DEF_INST(load_float_long) { int r1; /* Value of R field */ int i1; int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ U64 dreg; /* Double word workarea */ RX(inst, regs, r1, b2, effective_addr2); HFPREG_CHECK(r1, regs); i1 = FPR2I(r1); /* Fetch value from operand address */ dreg = ARCH_DEP(vfetch8) (effective_addr2, b2, regs); /* Update register contents */ regs->fpr[i1] = dreg >> 32; regs->fpr[i1+1] = dreg; } /*-------------------------------------------------------------------*/ /* 69 CD - Compare Floating Point Long [RX] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_float_long) { int r1; /* Value of R field */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ LONG_FLOAT fl; LONG_FLOAT cmp_fl; RX(inst, regs, r1, b2, effective_addr2); HFPREG_CHECK(r1, regs); /* Get the operands */ get_lf(&fl, regs->fpr + FPR2I(r1)); vfetch_lf(&cmp_fl, effective_addr2, b2, regs ); /* Compare long */ cmp_lf(&fl, &cmp_fl, regs); } /*-------------------------------------------------------------------*/ /* 6A AD - Add Floating Point Long [RX] */ /*-------------------------------------------------------------------*/ DEF_INST(add_float_long) { int r1; /* Value of R field */ int i1; /* Index of R1 in fpr array */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ LONG_FLOAT fl; LONG_FLOAT add_fl; int pgm_check; RX(inst, regs, r1, b2, effective_addr2); HFPREG_CHECK(r1, regs); i1 = FPR2I(r1); /* Get the operands */ get_lf(&fl, regs->fpr + i1); vfetch_lf(&add_fl, effective_addr2, b2, regs ); /* Add long with normalization */ pgm_check = add_lf(&fl, &add_fl, NORMAL, SIGEX, regs); /* Set condition code */ if (fl.long_fract) { regs->psw.cc = fl.sign ? 1 : 2; } else { regs->psw.cc = 0; } /* Back to register */ store_lf(&fl, regs->fpr + i1); /* Program check ? */ if (pgm_check) { ARCH_DEP(program_interrupt) (regs, pgm_check); } } /* end DEF_INST(add_float_long) */ /*-------------------------------------------------------------------*/ /* 6B SD - Subtract Floating Point Long [RX] */ /*-------------------------------------------------------------------*/ DEF_INST(subtract_float_long) { int r1; /* Value of R field */ int i1; /* Index of R1 in fpr array */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ LONG_FLOAT fl; LONG_FLOAT sub_fl; int pgm_check; RX(inst, regs, r1, b2, effective_addr2); HFPREG_CHECK(r1, regs); i1 = FPR2I(r1); /* Get the operands */ get_lf(&fl, regs->fpr + i1); vfetch_lf(&sub_fl, effective_addr2, b2, regs ); /* Invert the sign of 2nd operand */ sub_fl.sign = ! (sub_fl.sign); /* Add long with normalization */ pgm_check = add_lf(&fl, &sub_fl, NORMAL, SIGEX, regs); /* Set condition code */ if (fl.long_fract) { regs->psw.cc = fl.sign ? 1 : 2; } else { regs->psw.cc = 0; } /* Back to register */ store_lf(&fl, regs->fpr + i1); /* Program check ? */ if (pgm_check) { ARCH_DEP(program_interrupt) (regs, pgm_check); } } /* end DEF_INST(subtract_float_long) */ /*-------------------------------------------------------------------*/ /* 6C MD - Multiply Floating Point Long [RX] */ /*-------------------------------------------------------------------*/ DEF_INST(multiply_float_long) { int r1; /* Value of R field */ int i1; /* Index of R1 in fpr array */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ LONG_FLOAT fl; LONG_FLOAT mul_fl; int pgm_check; RX(inst, regs, r1, b2, effective_addr2); HFPREG_CHECK(r1, regs); i1 = FPR2I(r1); /* Get the operands */ get_lf(&fl, regs->fpr + i1); vfetch_lf(&mul_fl, effective_addr2, b2, regs ); /* multiply long */ pgm_check = mul_lf(&fl, &mul_fl, OVUNF, regs); /* Back to register */ store_lf(&fl, regs->fpr + i1); /* Program check ? */ if (pgm_check) { ARCH_DEP(program_interrupt) (regs, pgm_check); } } /* end DEF_INST(multiply_float_long) */ /*-------------------------------------------------------------------*/ /* 6D DD - Divide Floating Point Long [RX] */ /*-------------------------------------------------------------------*/ DEF_INST(divide_float_long) { int r1; /* Value of R field */ int i1; int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ LONG_FLOAT fl; LONG_FLOAT div_fl; int pgm_check; RX(inst, regs, r1, b2, effective_addr2); HFPREG_CHECK(r1, regs); i1 = FPR2I(r1); /* Get the operands */ get_lf(&fl, regs->fpr + i1); vfetch_lf(&div_fl, effective_addr2, b2, regs ); /* divide long */ pgm_check = div_lf(&fl, &div_fl, regs); /* Back to register */ store_lf(&fl, regs->fpr + i1); /* Program check ? */ if (pgm_check) { ARCH_DEP(program_interrupt) (regs, pgm_check); } } /*-------------------------------------------------------------------*/ /* 6E AW - Add Unnormalized Floating Point Long [RX] */ /*-------------------------------------------------------------------*/ DEF_INST(add_unnormal_float_long) { int r1; /* Value of R field */ int i1; /* Index of R1 in fpr array */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ LONG_FLOAT fl; LONG_FLOAT add_fl; int pgm_check; RX(inst, regs, r1, b2, effective_addr2); HFPREG_CHECK(r1, regs); i1 = FPR2I(r1); /* Get the operands */ get_lf(&fl, regs->fpr + i1); vfetch_lf(&add_fl, effective_addr2, b2, regs ); /* Add long without normalization */ pgm_check = add_lf(&fl, &add_fl, UNNORMAL, SIGEX, regs); /* Set condition code */ if (fl.long_fract) { regs->psw.cc = fl.sign ? 1 : 2; } else { regs->psw.cc = 0; } /* Back to register */ store_lf(&fl, regs->fpr + i1); /* Program check ? */ if (pgm_check) { ARCH_DEP(program_interrupt) (regs, pgm_check); } } /* end DEF_INST(add_unnormal_float_long) */ /*-------------------------------------------------------------------*/ /* 6F SW - Subtract Unnormalized Floating Point Long [RX] */ /*-------------------------------------------------------------------*/ DEF_INST(subtract_unnormal_float_long) { int r1; /* Value of R field */ int i1; /* Index of R1 in fpr array */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ LONG_FLOAT fl; LONG_FLOAT sub_fl; int pgm_check; RX(inst, regs, r1, b2, effective_addr2); HFPREG_CHECK(r1, regs); i1 = FPR2I(r1); /* Get the operands */ get_lf(&fl, regs->fpr + i1); vfetch_lf(&sub_fl, effective_addr2, b2, regs ); /* Invert the sign of 2nd operand */ sub_fl.sign = ! (sub_fl.sign); /* Add long without normalization */ pgm_check = add_lf(&fl, &sub_fl, UNNORMAL, SIGEX, regs); /* Set condition code */ if (fl.long_fract) { regs->psw.cc = fl.sign ? 1 : 2; } else { regs->psw.cc = 0; } /* Back to register */ store_lf(&fl, regs->fpr + i1); /* Program check ? */ if (pgm_check) { ARCH_DEP(program_interrupt) (regs, pgm_check); } } /* end DEF_INST(subtract_unnormal_float_long) */ /*-------------------------------------------------------------------*/ /* 70 STE - Store Floating Point Short [RX] */ /*-------------------------------------------------------------------*/ DEF_INST(store_float_short) { int r1; /* Value of R field */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ RX(inst, regs, r1, b2, effective_addr2); HFPREG_CHECK(r1, regs); /* Store register contents at operand address */ ARCH_DEP(vstore4) (regs->fpr[FPR2I(r1)], effective_addr2, b2, regs); } /*-------------------------------------------------------------------*/ /* 78 LE - Load Floating Point Short [RX] */ /*-------------------------------------------------------------------*/ DEF_INST(load_float_short) { int r1; /* Value of R field */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ RX(inst, regs, r1, b2, effective_addr2); HFPREG_CHECK(r1, regs); /* Update first 32 bits of register from operand address */ regs->fpr[FPR2I(r1)] = ARCH_DEP(vfetch4) (effective_addr2, b2, regs); } /*-------------------------------------------------------------------*/ /* 79 CE - Compare Floating Point Short [RX] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_float_short) { int r1; /* Value of R field */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ SHORT_FLOAT fl; SHORT_FLOAT cmp_fl; RX(inst, regs, r1, b2, effective_addr2); HFPREG_CHECK(r1, regs); /* Get the operands */ get_sf(&fl, regs->fpr + FPR2I(r1)); vfetch_sf(&cmp_fl, effective_addr2, b2, regs ); /* Compare long */ cmp_sf(&fl, &cmp_fl, regs); } /*-------------------------------------------------------------------*/ /* 7A AE - Add Floating Point Short [RX] */ /*-------------------------------------------------------------------*/ DEF_INST(add_float_short) { int r1; /* Value of R field */ int i1; /* Index of R1 in fpr array */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ SHORT_FLOAT fl; SHORT_FLOAT add_fl; int pgm_check; RX(inst, regs, r1, b2, effective_addr2); HFPREG_CHECK(r1, regs); i1 = FPR2I(r1); /* Get the operands */ get_sf(&fl, regs->fpr + i1); vfetch_sf(&add_fl, effective_addr2, b2, regs ); /* Add short with normalization */ pgm_check = add_sf(&fl, &add_fl, NORMAL, SIGEX, regs); /* Set condition code */ if (fl.short_fract) { regs->psw.cc = fl.sign ? 1 : 2; } else { regs->psw.cc = 0; } /* Back to register */ store_sf(&fl, regs->fpr + i1); /* Program check ? */ if (pgm_check) { ARCH_DEP(program_interrupt) (regs, pgm_check); } } /* end DEF_INST(add_float_short) */ /*-------------------------------------------------------------------*/ /* 7B SE - Subtract Floating Point Short [RX] */ /*-------------------------------------------------------------------*/ DEF_INST(subtract_float_short) { int r1; /* Value of R field */ int i1; /* Index of R1 in fpr array */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ SHORT_FLOAT fl; SHORT_FLOAT sub_fl; int pgm_check; RX(inst, regs, r1, b2, effective_addr2); HFPREG_CHECK(r1, regs); i1 = FPR2I(r1); /* Get the operands */ get_sf(&fl, regs->fpr + i1); vfetch_sf(&sub_fl, effective_addr2, b2, regs ); /* Invert the sign of 2nd operand */ sub_fl.sign = ! (sub_fl.sign); /* Add short with normalization */ pgm_check = add_sf(&fl, &sub_fl, NORMAL, SIGEX, regs); /* Set condition code */ if (fl.short_fract) { regs->psw.cc = fl.sign ? 1 : 2; } else { regs->psw.cc = 0; } /* Back to register */ store_sf(&fl, regs->fpr + i1); /* Program check ? */ if (pgm_check) { ARCH_DEP(program_interrupt) (regs, pgm_check); } } /* end DEF_INST(subtract_float_short) */ /*-------------------------------------------------------------------*/ /* 7C MDE - Multiply Floating Point Short to Long [RX] */ /* Older mnemonic of this instruction is ME */ /*-------------------------------------------------------------------*/ DEF_INST(multiply_float_short_to_long) { int r1; /* Value of R field */ int i1; int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ SHORT_FLOAT fl; SHORT_FLOAT mul_fl; LONG_FLOAT result_fl; int pgm_check; RX(inst, regs, r1, b2, effective_addr2); HFPREG_CHECK(r1, regs); i1 = FPR2I(r1); /* Get the operands */ get_sf(&fl, regs->fpr + i1); vfetch_sf(&mul_fl, effective_addr2, b2, regs ); /* multiply short to long */ pgm_check = mul_sf_to_lf(&fl, &mul_fl, &result_fl, regs); /* Back to register */ store_lf(&result_fl, regs->fpr + i1); /* Program check ? */ if (pgm_check) { ARCH_DEP(program_interrupt) (regs, pgm_check); } } /*-------------------------------------------------------------------*/ /* 7D DE - Divide Floating Point Short [RX] */ /*-------------------------------------------------------------------*/ DEF_INST(divide_float_short) { int r1; /* Value of R field */ int i1; int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ SHORT_FLOAT fl; SHORT_FLOAT div_fl; int pgm_check; RX(inst, regs, r1, b2, effective_addr2); HFPREG_CHECK(r1, regs); i1 = FPR2I(r1); /* Get the operands */ get_sf(&fl, regs->fpr + i1); vfetch_sf(&div_fl, effective_addr2, b2, regs ); /* divide short */ pgm_check = div_sf(&fl, &div_fl, regs); /* Back to register */ store_sf(&fl, regs->fpr + i1); /* Program check ? */ if (pgm_check) { ARCH_DEP(program_interrupt) (regs, pgm_check); } } /*-------------------------------------------------------------------*/ /* 7E AU - Add Unnormalized Floating Point Short [RX] */ /*-------------------------------------------------------------------*/ DEF_INST(add_unnormal_float_short) { int r1; /* Value of R field */ int i1; /* Index of R1 in fpr array */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ SHORT_FLOAT fl; SHORT_FLOAT add_fl; int pgm_check; RX(inst, regs, r1, b2, effective_addr2); HFPREG_CHECK(r1, regs); i1 = FPR2I(r1); /* Get the operands */ get_sf(&fl, regs->fpr + i1); vfetch_sf(&add_fl, effective_addr2, b2, regs ); /* Add short without normalization */ pgm_check = add_sf(&fl, &add_fl, UNNORMAL, SIGEX, regs); /* Set condition code */ if (fl.short_fract) { regs->psw.cc = fl.sign ? 1 : 2; } else { regs->psw.cc = 0; } /* Back to register */ store_sf(&fl, regs->fpr + i1); /* Program check ? */ if (pgm_check) { ARCH_DEP(program_interrupt) (regs, pgm_check); } } /* end DEF_INST(add_unnormal_float_short) */ /*-------------------------------------------------------------------*/ /* 7F SU - Subtract Unnormalized Floating Point Short [RX] */ /*-------------------------------------------------------------------*/ DEF_INST(subtract_unnormal_float_short) { int r1; /* Value of R field */ int i1; /* Index of R1 in fpr array */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ SHORT_FLOAT fl; SHORT_FLOAT sub_fl; int pgm_check; RX(inst, regs, r1, b2, effective_addr2); HFPREG_CHECK(r1, regs); i1 = FPR2I(r1); /* Get the operands */ get_sf(&fl, regs->fpr + i1); vfetch_sf(&sub_fl, effective_addr2, b2, regs ); /* Invert the sign of 2nd operand */ sub_fl.sign = ! (sub_fl.sign); /* Add short without normalization */ pgm_check = add_sf(&fl, &sub_fl, UNNORMAL, SIGEX, regs); /* Set condition code */ if (fl.short_fract) { regs->psw.cc = fl.sign ? 1 : 2; } else { regs->psw.cc = 0; } /* Back to register */ store_sf(&fl, regs->fpr + i1); /* Program check ? */ if (pgm_check) { ARCH_DEP(program_interrupt) (regs, pgm_check); } } /* end DEF_INST(subtract_unnormal_float_short) */ /*-------------------------------------------------------------------*/ /* B22D DXR - Divide Floating Point Extended Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(divide_float_ext_reg) { int r1, r2; /* Values of R fields */ int i1; EXTENDED_FLOAT fl; EXTENDED_FLOAT div_fl; int pgm_check; RRE(inst, regs, r1, r2); HFPODD2_CHECK(r1, r2, regs); i1 = FPR2I(r1); /* Get the operands */ get_ef(&fl, regs->fpr + i1); get_ef(&div_fl, regs->fpr + FPR2I(r2)); /* divide extended */ pgm_check = div_ef(&fl, &div_fl, regs); /* Back to register */ store_ef(&fl, regs->fpr + i1); /* Program check ? */ if (pgm_check) { ARCH_DEP(program_interrupt) (regs, pgm_check); } } #if defined (FEATURE_SQUARE_ROOT) /*-------------------------------------------------------------------*/ /* B244 SQDR - Square Root Floating Point Long Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(squareroot_float_long_reg) { int r1, r2; /* Values of R fields */ LONG_FLOAT sq_fl; LONG_FLOAT fl; RRE(inst, regs, r1, r2); HFPREG2_CHECK(r1, r2, regs); /* Get the 2nd operand */ get_lf(&fl, regs->fpr + FPR2I(r2)); /* square root long */ sq_lf(&sq_fl, &fl, regs); /* Back to register */ store_lf(&sq_fl, regs->fpr + FPR2I(r1)); } /*-------------------------------------------------------------------*/ /* B245 SQER - Square Root Floating Point Short Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(squareroot_float_short_reg) { int r1, r2; /* Values of R fields */ SHORT_FLOAT sq_fl; SHORT_FLOAT fl; RRE(inst, regs, r1, r2); HFPREG2_CHECK(r1, r2, regs); /* Get the 2nd operand */ get_sf(&fl, regs->fpr + FPR2I(r2)); /* square root short */ sq_sf(&sq_fl, &fl, regs); /* Back to register */ store_sf(&sq_fl, regs->fpr + FPR2I(r1)); } #endif /* FEATURE_SQUARE_ROOT */ #if defined (FEATURE_HFP_EXTENSIONS) /*-------------------------------------------------------------------*/ /* B324 LDER - Load Length. Float. Short to Long Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(load_lengthened_float_short_to_long_reg) { int r1, r2; /* Values of R fields */ int i1; RRE(inst, regs, r1, r2); HFPREG2_CHECK(r1, r2, regs); i1 = FPR2I(r1); /* Copy register content */ regs->fpr[i1] = regs->fpr[FPR2I(r2)]; /* Clear register */ regs->fpr[i1+1] = 0; } /*-------------------------------------------------------------------*/ /* B325 LXDR - Load Length. Float. Long to Extended Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(load_lengthened_float_long_to_ext_reg) { int r1, r2; /* Values of R fields */ int i1, i2; RRE(inst, regs, r1, r2); HFPODD_CHECK(r1, regs); i1 = FPR2I(r1); HFPREG_CHECK(r2, regs); i2 = FPR2I(r2); if ((regs->fpr[i2] & 0x00FFFFFF) || regs->fpr[i2+1]) { /* Copy register contents */ regs->fpr[i1] = regs->fpr[i2]; regs->fpr[i1+1] = regs->fpr[i2+1]; /* Low order register */ regs->fpr[i1+FPREX] = (regs->fpr[i2] & 0x80000000) | ((regs->fpr[i2] - (14 << 24)) & 0x7F000000); } else { /* true zero with sign */ regs->fpr[i1] = regs->fpr[i2] & 0x80000000; regs->fpr[i1+1] = 0; regs->fpr[i1+FPREX] = regs->fpr[i1]; } /* Clear register */ regs->fpr[i1+FPREX+1] = 0; } /*-------------------------------------------------------------------*/ /* B326 LXER - Load Length. Float. Short to Extended Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(load_lengthened_float_short_to_ext_reg) { int r1, r2; /* Values of R fields */ int i1, i2; RRE(inst, regs, r1, r2); HFPODD_CHECK(r1, regs); i1 = FPR2I(r1); HFPREG_CHECK(r2, regs); i2 = FPR2I(r2); if (regs->fpr[i2] & 0x00FFFFFF) { /* Copy register content */ regs->fpr[i1] = regs->fpr[i2]; /* Low order register */ regs->fpr[i1+FPREX] = (regs->fpr[i2] & 0x80000000) | ((regs->fpr[i2] - (14 << 24)) & 0x7F000000); } else { /* true zero with sign */ regs->fpr[i1] = regs->fpr[i2] & 0x80000000; regs->fpr[i1+FPREX] = regs->fpr[i1]; } /* Clear register */ regs->fpr[i1+1] = 0; regs->fpr[i1+FPREX+1] = 0; } /*-------------------------------------------------------------------*/ /* B336 SQXR - Square Root Floating Point Extended Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(squareroot_float_ext_reg) { int r1, r2; /* Values of R fields */ EXTENDED_FLOAT sq_fl; EXTENDED_FLOAT fl; U64 mmsa, msa, lsa, llsa; U64 xi; U64 xj; U64 msi, lsi; U64 msj, lsj; RRE(inst, regs, r1, r2); HFPODD2_CHECK(r1, r2, regs); /* Get the 2nd operand */ get_ef(&fl, regs->fpr + FPR2I(r2)); if ((fl.ms_fract) || (fl.ls_fract)) { if (fl.sign) { /* less than zero */ ARCH_DEP(program_interrupt) (regs, PGM_SQUARE_ROOT_EXCEPTION); return; /* Never reached */ } else { /* normalize operand */ normal_ef(&fl); if (fl.expo & 1) { /* odd */ /* compute characteristic */ sq_fl.expo = (fl.expo + 65) >> 1; /* with guard digit */ mmsa = fl.ms_fract >> 4; msa = (fl.ms_fract << 60) | (fl.ls_fract >> 4); lsa = fl.ls_fract << 60; llsa = 0; } else { /* even */ /* compute characteristic */ sq_fl.expo = (fl.expo + 64) >> 1; /* without guard digit */ mmsa = fl.ms_fract; msa = fl.ls_fract; lsa = 0; llsa = 0; } /* square root of fraction low precision */ /* common subroutine of all square root */ xi = ((U64) (square_root_fraction(mmsa & 0xFFFFFFFFFFFFFFFEULL)) << 32) | 0x80000000UL; /* continue iteration for high precision */ /* done iteration when xi, xj equal or differ by 1 */ for (;;) { xj = (div_U128(mmsa, msa, xi) + xi) >> 1; if ((xj == xi) || (abs(xj - xi) == 1)) { break; } xi = xj; } msi = xi; lsi = 0x8000000000000000ULL; /* continue iteration for extended precision */ for (;;) { div_U256(mmsa, msa, lsa, llsa, msi, lsi, &msj, &lsj); add_U128(msj, lsj, msi, lsi); shift_right_U128(msj, lsj); if ((msj == msi) && (lsj == lsi)) { break; } msi = msj; lsi = lsj; } /* round with guard digit */ add_U128(msi, lsi, 0, 0x80); sq_fl.ls_fract = (lsi >> 8) | (msi << 56); sq_fl.ms_fract = msi >> 8; } } else { /* true zero */ sq_fl.ms_fract = 0; sq_fl.ls_fract = 0; sq_fl.expo = 0; } /* all results positive */ sq_fl.sign = POS; /* Back to register */ store_ef(&sq_fl, regs->fpr + FPR2I(r1)); } /*-------------------------------------------------------------------*/ /* B337 MEER - Multiply Floating Point Short Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(multiply_float_short_reg) { int r1, r2; /* Values of R fields */ int i1; /* Index of R1 in fpr array */ SHORT_FLOAT fl; SHORT_FLOAT mul_fl; int pgm_check; RRE(inst, regs, r1, r2); HFPREG2_CHECK(r1, r2, regs); i1 = FPR2I(r1); /* Get the operands */ get_sf(&fl, regs->fpr + i1); get_sf(&mul_fl, regs->fpr + FPR2I(r2)); /* multiply short to long */ pgm_check = mul_sf(&fl, &mul_fl, OVUNF, regs); /* Back to register */ store_sf(&fl, regs->fpr + i1); /* Program check ? */ if (pgm_check) { ARCH_DEP(program_interrupt) (regs, pgm_check); } } /* end DEF_INST(multiply_float_short_reg) */ /*-------------------------------------------------------------------*/ /* B360 LPXR - Load Positive Floating Point Extended Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(load_positive_float_ext_reg) { int r1, r2; /* Values of R fields */ int i1, i2; RRE(inst, regs, r1, r2); HFPODD2_CHECK(r1, r2, regs); i1 = FPR2I(r1); i2 = FPR2I(r2); if ((regs->fpr[i2] & 0x00FFFFFF) || regs->fpr[i2+1] || (regs->fpr[i2+FPREX] & 0x00FFFFFF) || regs->fpr[i2+FPREX+1]) { /* Copy register contents, clear the sign bit */ regs->fpr[i1] = regs->fpr[i2] & 0x7FFFFFFF; regs->fpr[i1+1] = regs->fpr[i2+1]; /* Low order register */ regs->fpr[i1+FPREX] = (((regs->fpr[i2] - (14 << 24)) & 0x7F000000)) | (regs->fpr[i2+FPREX] & 0x00FFFFFF); regs->fpr[i1+FPREX+1] = regs->fpr[i2+FPREX+1]; /* Set condition code */ regs->psw.cc = 2; } else { /* true zero */ regs->fpr[i1] = 0; regs->fpr[i1+1] = 0; regs->fpr[i1+FPREX] = 0; regs->fpr[i1+FPREX+1] = 0; /* Set condition code */ regs->psw.cc = 0; } } /*-------------------------------------------------------------------*/ /* B361 LNXR - Load Negative Floating Point Extended Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(load_negative_float_ext_reg) { int r1, r2; /* Values of R fields */ int i1, i2; RRE(inst, regs, r1, r2); HFPODD2_CHECK(r1, r2, regs); i1 = FPR2I(r1); i2 = FPR2I(r2); if ((regs->fpr[i2] & 0x00FFFFFF) || regs->fpr[i2+1] || (regs->fpr[i2+FPREX] & 0x00FFFFFF) || regs->fpr[i2+FPREX+1]) { /* Copy register contents, set the sign bit */ regs->fpr[i1] = 0x80000000 | regs->fpr[i2]; regs->fpr[i1+1] = regs->fpr[i2+1]; /* Low order register */ regs->fpr[i1+FPREX] = 0x80000000 | (((regs->fpr[i2] - (14 << 24)) & 0x7F000000)) | (regs->fpr[i2+FPREX] & 0x00FFFFFF); regs->fpr[i1+FPREX+1] = regs->fpr[i2+FPREX+1]; /* Set condition code */ regs->psw.cc = 1; } else { /* true zero with sign */ regs->fpr[i1] = 0x80000000; regs->fpr[i1+FPREX] = 0x80000000; regs->fpr[i1+1] = 0; regs->fpr[i1+FPREX+1] = 0; /* Set condition code */ regs->psw.cc = 0; } } /*-------------------------------------------------------------------*/ /* B362 LTXR - Load and Test Floating Point Extended Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(load_and_test_float_ext_reg) { int r1, r2; /* Values of R fields */ int i1, i2; RRE(inst, regs, r1, r2); HFPODD2_CHECK(r1, r2, regs); i1 = FPR2I(r1); i2 = FPR2I(r2); if ((regs->fpr[i2] & 0x00FFFFFF) || regs->fpr[i2+1] || (regs->fpr[i2+FPREX] & 0x00FFFFFF) || regs->fpr[i2+FPREX+1]) { /* Copy register contents */ regs->fpr[i1] = regs->fpr[i2]; regs->fpr[i1+1] = regs->fpr[i2+1]; /* Low order register */ regs->fpr[i1+FPREX] = (regs->fpr[i2] & 0x80000000) | ((regs->fpr[i2] - (14 << 24)) & 0x7F000000) | (regs->fpr[i2+FPREX] & 0x00FFFFFF); regs->fpr[i1+FPREX+1] = regs->fpr[i2+FPREX+1]; /* Set condition code */ regs->psw.cc = (regs->fpr[i2] & 0x80000000) ? 1 : 2; } else { /* true zero with sign */ regs->fpr[i1] = regs->fpr[i2] & 0x80000000; regs->fpr[i1+FPREX] = regs->fpr[i1]; regs->fpr[i1+1] = 0; regs->fpr[i1+FPREX+1] = 0; /* Set condition code */ regs->psw.cc = 0; } } /*-------------------------------------------------------------------*/ /* B363 LCXR - Load Complement Float. Extended Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(load_complement_float_ext_reg) { int r1, r2; /* Values of R fields */ int i1, i2; RRE(inst, regs, r1, r2); HFPODD2_CHECK(r1, r2, regs); i1 = FPR2I(r1); i2 = FPR2I(r2); if ((regs->fpr[i2] & 0x00FFFFFF) || regs->fpr[i2+1] || (regs->fpr[i2+FPREX] & 0x00FFFFFF) || regs->fpr[i2+FPREX+1]) { /* Copy register contents, invert sign bit */ regs->fpr[i1] = regs->fpr[i2] ^ 0x80000000; regs->fpr[i1+1] = regs->fpr[i2+1]; /* Low order register */ regs->fpr[i1+FPREX] = (regs->fpr[i1] & 0x80000000) |(((regs->fpr[i1] & 0x7F000000) - 0x0E000000) & 0x7F000000) | (regs->fpr[i2+FPREX] & 0x00FFFFFF); regs->fpr[i1+FPREX+1] = regs->fpr[i2+FPREX+1]; /* Set condition code */ regs->psw.cc = (regs->fpr[i1] & 0x80000000) ? 1 : 2; } else { /* true zero with sign */ regs->fpr[i1] = (regs->fpr[i2] ^ 0x80000000) & 0x80000000; regs->fpr[i1+FPREX] = regs->fpr[i1]; regs->fpr[i1+1] = 0; regs->fpr[i1+FPREX+1] = 0; /* Set condition code */ regs->psw.cc = 0; } } /*-------------------------------------------------------------------*/ /* B366 LEXR - Load Rounded Float. Extended to Short Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(load_rounded_float_ext_to_short_reg) { int r1, r2; /* Values of R fields */ EXTENDED_FLOAT from_fl; SHORT_FLOAT to_fl; int pgm_check; RRE(inst, regs, r1, r2); HFPREG_CHECK(r1, regs); HFPODD_CHECK(r2, regs); /* Get register content */ get_ef(&from_fl, regs->fpr + FPR2I(r2)); /* Rounding (herc ms fract is 12 digits) */ to_fl.short_fract = (from_fl.ms_fract + 0x0000000000800000ULL) >> 24; to_fl.sign = from_fl.sign; to_fl.expo = from_fl.expo; /* Handle overflow */ if (to_fl.short_fract & 0x0F000000) { to_fl.short_fract >>= 4; (to_fl.expo)++; pgm_check = overflow_sf(&to_fl, regs); } else { pgm_check = 0; } /* To register */ store_sf(&to_fl, regs->fpr + FPR2I(r1)); /* Program check ? */ if (pgm_check) { ARCH_DEP(program_interrupt) (regs, pgm_check); } } /*-------------------------------------------------------------------*/ /* B367 FIXR - Load FP Integer Float. Extended Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(load_fp_int_float_ext_reg) { int r1, r2; /* Values of R fields */ int i1; EXTENDED_FLOAT fl; BYTE shift; RRE(inst, regs, r1, r2); HFPODD2_CHECK(r1, r2, regs); i1 = FPR2I(r1); /* Get register content */ get_ef(&fl, regs->fpr + FPR2I(r2)); if (fl.expo > 64) { if (fl.expo < 92) { /* Denormalize */ shift = (92 - fl.expo) * 4; if (shift > 64) { fl.ls_fract = fl.ms_fract >> (shift - 64); fl.ms_fract = 0; } else if (shift == 64) { fl.ls_fract = fl.ms_fract; fl.ms_fract = 0; } else { fl.ls_fract = (fl.ls_fract >> shift) | (fl.ms_fract << (64 - shift)); fl.ms_fract >>= shift; } fl.expo = 92; } /* Normalize result */ normal_ef(&fl); /* To register */ store_ef(&fl, regs->fpr + i1); } else { /* True zero */ regs->fpr[i1] = 0; regs->fpr[i1+1] = 0; regs->fpr[i1+FPREX] = 0; regs->fpr[i1+FPREX+1] = 0; } } /*-------------------------------------------------------------------*/ /* B369 CXR - Compare Floating Point Extended Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_float_ext_reg) { int r1, r2; /* Values of R fields */ EXTENDED_FLOAT fl; EXTENDED_FLOAT cmp_fl; BYTE shift; RRE(inst, regs, r1, r2); HFPODD2_CHECK(r1, r2, regs); /* Get the operands */ get_ef(&fl, regs->fpr + FPR2I(r1)); get_ef(&cmp_fl, regs->fpr + FPR2I(r2));; if (cmp_fl.ms_fract || cmp_fl.ls_fract || cmp_fl.expo) { /* cmp_fl not 0 */ if (fl.ms_fract || fl.ls_fract || fl.expo) { /* fl not 0 */ /* both not 0 */ if (fl.expo == cmp_fl.expo) { /* expo equal */ /* both guard digits */ fl.ms_fract = (fl.ms_fract << 4) | (fl.ls_fract >> 60); fl.ls_fract <<= 4; cmp_fl.ms_fract = (cmp_fl.ms_fract << 4) | (cmp_fl.ls_fract >> 60); cmp_fl.ls_fract <<= 4; } else { /* expo not equal, denormalize */ if (fl.expo < cmp_fl.expo) { /* shift minus guard digit */ shift = cmp_fl.expo - fl.expo - 1; if (shift) { if (shift >= 28) { /* Set condition code */ if (cmp_fl.ms_fract || cmp_fl.ls_fract) { regs->psw.cc = cmp_fl.sign ? 2 : 1; } else { regs->psw.cc = 0; } return; } else if (shift >= 16) { fl.ls_fract = fl.ms_fract; if (shift > 16) { fl.ls_fract >>= (shift - 16) * 4; } fl.ms_fract = 0; } else { shift *= 4; fl.ls_fract = fl.ms_fract << (64 - shift) | fl.ls_fract >> shift; fl.ms_fract >>= shift; } if ((fl.ms_fract == 0) && (fl.ls_fract == 0)) { /* Set condition code */ if (cmp_fl.ms_fract || cmp_fl.ls_fract) { regs->psw.cc = cmp_fl.sign ? 2 : 1; } else { regs->psw.cc = 0; } return; } } /* guard digit */ cmp_fl.ms_fract = (cmp_fl.ms_fract << 4) | (cmp_fl.ls_fract >> 60); cmp_fl.ls_fract <<= 4; } else { /* shift minus guard digit */ shift = fl.expo - cmp_fl.expo - 1; if (shift) { if (shift >= 28) { /* Set condition code */ if (fl.ms_fract || fl.ls_fract) { regs->psw.cc = fl.sign ? 1 : 2; } else { regs->psw.cc = 0; } return; } else if (shift >= 16) { cmp_fl.ls_fract = cmp_fl.ms_fract; if (shift > 16) { cmp_fl.ls_fract >>= (shift - 16) * 4; } cmp_fl.ms_fract = 0; } else { shift *= 4; cmp_fl.ls_fract = cmp_fl.ms_fract << (64 - shift) | cmp_fl.ls_fract >> shift; cmp_fl.ms_fract >>= shift; } if ((cmp_fl.ms_fract == 0) && (cmp_fl.ls_fract == 0)) { /* Set condition code */ if (fl.ms_fract || fl.ls_fract) { regs->psw.cc = fl.sign ? 1 : 2; } else { regs->psw.cc = 0; } return; } } /* guard digit */ fl.ms_fract = (fl.ms_fract << 4) | (fl.ls_fract >> 60); fl.ls_fract <<= 4; } } /* compute with guard digit */ if (fl.sign != cmp_fl.sign) { add_U128(fl.ms_fract, fl.ls_fract, cmp_fl.ms_fract, cmp_fl.ls_fract); } else if ((fl.ms_fract > cmp_fl.ms_fract) || ((fl.ms_fract == cmp_fl.ms_fract) && (fl.ls_fract >= cmp_fl.ls_fract))) { sub_U128(fl.ms_fract, fl.ls_fract, cmp_fl.ms_fract, cmp_fl.ls_fract); } else { sub_reverse_U128(fl.ms_fract, fl.ls_fract, cmp_fl.ms_fract, cmp_fl.ls_fract); fl.sign = ! (cmp_fl.sign); } /* handle overflow with guard digit */ if (fl.ms_fract & 0x00F0000000000000ULL) { fl.ls_fract = (fl.ms_fract << 60) | (fl.ls_fract >> 4); fl.ms_fract >>= 4; } /* Set condition code */ if (fl.ms_fract || fl.ls_fract) { regs->psw.cc = fl.sign ? 1 : 2; } else { regs->psw.cc = 0; } return; } else { /* fl 0, cmp_fl not 0 */ /* Set condition code */ if (cmp_fl.ms_fract || cmp_fl.ls_fract) { regs->psw.cc = cmp_fl.sign ? 2 : 1; } else { regs->psw.cc = 0; } return; } } else { /* cmp_fl 0 */ /* Set condition code */ if (fl.ms_fract || fl.ls_fract) { regs->psw.cc = fl.sign ? 1 : 2; } else { regs->psw.cc = 0; } return; } } /*-------------------------------------------------------------------*/ /* B377 FIER - Load FP Integer Floating Point Short Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(load_fp_int_float_short_reg) { int r1, r2; /* Values of R fields */ int i1; SHORT_FLOAT fl; RRE(inst, regs, r1, r2); HFPREG2_CHECK(r1, r2, regs); i1 = FPR2I(r1); /* Get register content */ get_sf(&fl, regs->fpr + FPR2I(r2)); if (fl.expo > 64) { if (fl.expo < 70) { /* Denormalize */ fl.short_fract >>= ((70 - fl.expo) * 4); fl.expo = 70; } /* Normalize result */ normal_sf(&fl); /* To register */ store_sf(&fl, regs->fpr + i1); } else { /* True zero */ regs->fpr[i1] = 0; } } /*-------------------------------------------------------------------*/ /* B37F FIDR - Load FP Integer Floating Point Long Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(load_fp_int_float_long_reg) { int r1, r2; /* Values of R fields */ int i1; LONG_FLOAT fl; RRE(inst, regs, r1, r2); HFPREG2_CHECK(r1, r2, regs); i1 = FPR2I(r1); /* Get register content */ get_lf(&fl, regs->fpr + FPR2I(r2)); if (fl.expo > 64) { if (fl.expo < 78) { /* Denormalize */ fl.long_fract >>= ((78 - fl.expo) * 4); fl.expo = 78; } /* Normalize result */ normal_lf(&fl); /* To register */ store_lf(&fl, regs->fpr + i1); } else { /* True zero */ regs->fpr[i1] = 0; regs->fpr[i1+1] = 0; } } /*-------------------------------------------------------------------*/ /* B3B4 CEFR - Convert from Fixed to Float. Short Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(convert_fixed_to_float_short_reg) { int r1, r2; /* Values of R fields */ int i1; LONG_FLOAT fl; S64 fix; RRE(inst, regs, r1, r2); HFPREG_CHECK(r1, regs); i1 = FPR2I(r1); /* get fixed value */ fix = regs->GR_L(r2); if (fix & 0x0000000080000000) fix |= 0xFFFFFFFF00000000ULL; if (fix) { if (fix < 0) { fl.sign = NEG; fl.long_fract = (-fix); } else { fl.sign = POS; fl.long_fract = fix; } fl.expo = 78; /* Normalize result */ normal_lf(&fl); /* To register (converting to short float) */ regs->fpr[i1] = ((U32)fl.sign << 31) | ((U32)fl.expo << 24) | (fl.long_fract >> 32); } else { /* true zero */ regs->fpr[i1] = 0; } } /*-------------------------------------------------------------------*/ /* B3B5 CDFR - Convert from Fixed to Float. Long Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(convert_fixed_to_float_long_reg) { int r1, r2; /* Values of R fields */ int i1; LONG_FLOAT fl; S64 fix; RRE(inst, regs, r1, r2); HFPREG_CHECK(r1, regs); i1 = FPR2I(r1); /* get fixed value */ fix = regs->GR_L(r2); if (fix & 0x0000000080000000) fix |= 0xFFFFFFFF00000000ULL; if (fix) { if (fix < 0) { fl.sign = NEG; fl.long_fract = (-fix); } else { fl.sign = POS; fl.long_fract = fix; } fl.expo = 78; /* Normalize result */ normal_lf(&fl); /* To register */ store_lf(&fl, regs->fpr + i1); } else { /* true zero */ regs->fpr[i1] = 0; regs->fpr[i1+1] = 0; } } /*-------------------------------------------------------------------*/ /* B3B6 CXFR - Convert from Fixed to Float. Extended Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(convert_fixed_to_float_ext_reg) { int r1, r2; /* Values of R fields */ int i1; EXTENDED_FLOAT fl; S64 fix; RRE(inst, regs, r1, r2); HFPODD_CHECK(r1, regs); i1 = FPR2I(r1); /* get fixed value */ fix = regs->GR_L(r2); if (fix & 0x0000000080000000) fix |= 0xFFFFFFFF00000000ULL; if (fix) { if (fix < 0) { fl.sign = NEG; fl.ms_fract = (-fix); } else { fl.sign = POS; fl.ms_fract = fix; } fl.ls_fract = 0; fl.expo = 76; /* 64 + 12 (Herc ms fract is 12 digits) */ /* Normalize result */ normal_ef(&fl); /* To register */ store_ef(&fl, regs->fpr + i1); } else { /* true zero */ regs->fpr[i1] = 0; regs->fpr[i1+1] = 0; regs->fpr[i1+FPREX] = 0; regs->fpr[i1+FPREX+1] = 0; } } /*-------------------------------------------------------------------*/ /* B3C4 CEGR - Convert from Fix64 to Float. Short Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(convert_fix64_to_float_short_reg) { int r1, r2; /* Values of R fields */ int i1; SHORT_FLOAT fl; U64 fix; RRE(inst, regs, r1, r2); HFPREG_CHECK(r1, regs); i1 = FPR2I(r1); fix = regs->GR_G(r2); /* Test for negative value */ if (fix & 0x8000000000000000ULL) { fix = ~fix + 1; /* fix = abs(fix); */ fl.sign = NEG; } else fl.sign = POS; if (fix) { fl.expo = 70; /* Truncate fraction to 6 hexadecimal digits */ while (fix & 0xFFFFFFFFFF000000ULL) { fix >>= 4; fl.expo += 1; } fl.short_fract = (U32)fix; /* Normalize result */ normal_sf(&fl); /* To register */ store_sf(&fl, regs->fpr + i1); } else { /* true zero */ regs->fpr[i1] = 0; } } /*-------------------------------------------------------------------*/ /* B3C5 CDGR - Convert from Fix64 to Float. Long Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(convert_fix64_to_float_long_reg) { int r1, r2; /* Values of R fields */ int i1; LONG_FLOAT fl; U64 fix; RRE(inst, regs, r1, r2); HFPREG_CHECK(r1, regs); i1 = FPR2I(r1); fix = regs->GR_G(r2); /* Test for negative value */ if (fix & 0x8000000000000000ULL) { fix = ~fix + 1; /* fix = abs(fix); */ fl.sign = NEG; } else fl.sign = POS; if (fix) { fl.long_fract = fix; fl.expo = 78; /* Truncate fraction to 14 hexadecimal digits */ while (fl.long_fract & 0xFF00000000000000ULL) { fl.long_fract >>= 4; fl.expo += 1; } /* Normalize result */ normal_lf(&fl); /* To register */ store_lf(&fl, regs->fpr + i1); } else { /* true zero */ regs->fpr[i1] = 0; regs->fpr[i1+1] = 0; } } /*-------------------------------------------------------------------*/ /* B3C6 CXGR - Convert from Fix64 to Float. Extended Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(convert_fix64_to_float_ext_reg) { int r1, r2; /* Values of R fields */ int i1; EXTENDED_FLOAT fl; U64 fix; RRE(inst, regs, r1, r2); HFPODD_CHECK(r1, regs); i1 = FPR2I(r1); fix = regs->GR_G(r2); /* Test for negative value */ if (fix & 0x8000000000000000ULL) { fix = ~fix + 1; /* fix = abs(fix); */ fl.sign = NEG; } else fl.sign = POS; if (fix) { fl.ms_fract = fix >> 16; /* Fraction high (12 digits) */ fl.ls_fract = fix << 48; /* Fraction low (16 digits) */ fl.expo = 80; /* Normalize result */ normal_ef(&fl); /* To register */ store_ef(&fl, regs->fpr + i1); } else { /* true zero */ regs->fpr[i1] = 0; regs->fpr[i1+1] = 0; regs->fpr[i1+FPREX] = 0; regs->fpr[i1+FPREX+1] = 0; } } /*-------------------------------------------------------------------*/ /* B3B8 CFER - Convert from Float. Short to Fixed Register [RRF] */ /*-------------------------------------------------------------------*/ DEF_INST(convert_float_short_to_fixed_reg) { int r1, r2; /* Values of R fields */ int m3; SHORT_FLOAT fl; BYTE shift; U32 lsfract; RRF_M(inst, regs, r1, r2, m3); HFPM_CHECK(m3, regs); HFPREG_CHECK(r2, regs); /* Get register content */ get_sf(&fl, regs->fpr + FPR2I(r2)); if (fl.short_fract) { /* not zero */ normal_sf(&fl); if (fl.expo > 72) { /* exeeds range by exponent */ regs->GR_L(r1) = fl.sign ? 0x80000000UL : 0x7FFFFFFFUL; regs->psw.cc = 3; return; } if (fl.expo > 70) { /* to be left shifted */ fl.short_fract <<= ((fl.expo - 70) * 4); if (fl.sign) { /* negative */ if (fl.short_fract > 0x80000000UL) { /* exeeds range by value */ regs->GR_L(r1) = 0x80000000UL; regs->psw.cc = 3; return; } } else { /* positive */ if (fl.short_fract > 0x7FFFFFFFUL) { /* exeeds range by value */ regs->GR_L(r1) = 0x7FFFFFFFUL; regs->psw.cc = 3; return; } } } else if ((fl.expo > 64) && (fl.expo < 70)) { /* to be right shifted and to be rounded */ shift = ((70 - fl.expo) * 4); lsfract = fl.short_fract << (32 - shift); fl.short_fract >>= shift; if (m3 == 1) { /* biased round to nearest */ if (lsfract & 0x80000000UL) { fl.short_fract++; } } else if (m3 == 4) { /* round to nearest */ if ((lsfract > 0x80000000UL) || ((fl.short_fract & 0x00000001UL) && (lsfract == 0x80000000UL))) { fl.short_fract++; } } else if (m3 == 6) { /* round toward + */ if ((fl.sign == POS) && lsfract) { fl.short_fract++; } } else if (m3 == 7) { /* round toward - */ if ((fl.sign == NEG) && lsfract) { fl.short_fract++; } } } else if (fl.expo == 64) { /* to be rounded */ lsfract = fl.short_fract << 8; fl.short_fract = 0; if (m3 == 1) { /* biased round to nearest */ if (lsfract & 0x80000000UL) { fl.short_fract++; } } else if (m3 == 4) { /* round to nearest */ if (lsfract > 0x80000000UL) { fl.short_fract++; } } else if (m3 == 6) { /* round toward + */ if ((fl.sign == POS) && lsfract) { fl.short_fract++; } } else if (m3 == 7) { /* round toward - */ if ((fl.sign == NEG) && lsfract) { fl.short_fract++; } } } else if (fl.expo < 64) { fl.short_fract = 0; if (((m3 == 6) && (fl.sign == POS)) || ((m3 == 7) && (fl.sign == NEG))) { fl.short_fract++; } } if (fl.sign) { /* negative */ regs->GR_L(r1) = -((S32) fl.short_fract); regs->psw.cc = 1; } else { /* positive */ regs->GR_L(r1) = fl.short_fract; regs->psw.cc = 2; } } else { /* zero */ regs->GR_L(r1) = 0; regs->psw.cc = 0; } } /*-------------------------------------------------------------------*/ /* B3B9 CFDR - Convert from Float. Long to Fixed Register [RRF] */ /*-------------------------------------------------------------------*/ DEF_INST(convert_float_long_to_fixed_reg) { int r1, r2; /* Values of R fields */ int m3; LONG_FLOAT fl; BYTE shift; U64 lsfract; RRF_M(inst, regs, r1, r2, m3); HFPM_CHECK(m3, regs); HFPREG_CHECK(r2, regs); /* Get register content */ get_lf(&fl, regs->fpr + FPR2I(r2)); if (fl.long_fract) { /* not zero */ normal_lf(&fl); if (fl.expo > 72) { /* exeeds range by exponent */ regs->GR_L(r1) = fl.sign ? 0x80000000UL : 0x7FFFFFFFUL; regs->psw.cc = 3; return; } if (fl.expo > 64) { /* to be right shifted and to be rounded */ shift = ((78 - fl.expo) * 4); lsfract = fl.long_fract << (64 - shift); fl.long_fract >>= shift; if (m3 == 1) { /* biased round to nearest */ if (lsfract & 0x8000000000000000ULL) { fl.long_fract++; } } else if (m3 == 4) { /* round to nearest */ if ((lsfract > 0x8000000000000000ULL) || ((fl.long_fract & 0x0000000000000001ULL) && (lsfract == 0x8000000000000000ULL))) { fl.long_fract++; } } else if (m3 == 6) { /* round toward + */ if ((fl.sign == POS) && lsfract) { fl.long_fract++; } } else if (m3 == 7) { /* round toward - */ if ((fl.sign == NEG) && lsfract) { fl.long_fract++; } } if (fl.expo == 72) { if (fl.sign) { /* negative */ if (fl.long_fract > 0x80000000UL) { /* exeeds range by value */ regs->GR_L(r1) = 0x80000000UL; regs->psw.cc = 3; return; } } else { /* positive */ if (fl.long_fract > 0x7FFFFFFFUL) { /* exeeds range by value */ regs->GR_L(r1) = 0x7FFFFFFFUL; regs->psw.cc = 3; return; } } } } else if (fl.expo == 64) { /* to be rounded */ lsfract = fl.long_fract << 8; fl.long_fract = 0; if (m3 == 1) { /* biased round to nearest */ if (lsfract & 0x8000000000000000ULL) { fl.long_fract++; } } else if (m3 == 4) { /* round to nearest */ if (lsfract > 0x8000000000000000ULL) { fl.long_fract++; } } else if (m3 == 6) { /* round toward + */ if ((fl.sign == POS) && lsfract) { fl.long_fract++; } } else if (m3 == 7) { /* round toward - */ if ((fl.sign == NEG) && lsfract) { fl.long_fract++; } } } else { /* fl.expo < 64 */ fl.long_fract = 0; if (((m3 == 6) && (fl.sign == POS)) || ((m3 == 7) && (fl.sign == NEG))) { fl.long_fract++; } } if (fl.sign) { /* negative */ regs->GR_L(r1) = -((S32) fl.long_fract); regs->psw.cc = 1; } else { /* positive */ regs->GR_L(r1) = fl.long_fract; regs->psw.cc = 2; } } else { /* zero */ regs->GR_L(r1) = 0; regs->psw.cc = 0; } } /*-------------------------------------------------------------------*/ /* B3BA CFXR - Convert from Float. Extended to Fixed Register [RRF] */ /*-------------------------------------------------------------------*/ DEF_INST(convert_float_ext_to_fixed_reg) { int r1, r2; /* Values of R fields */ int m3; EXTENDED_FLOAT fl; BYTE shift; U64 lsfract; RRF_M(inst, regs, r1, r2, m3); HFPM_CHECK(m3, regs); HFPODD_CHECK(r2, regs); /* Get register content */ get_ef(&fl, regs->fpr + FPR2I(r2)); if (fl.ms_fract || fl.ls_fract) { /* not zero */ normal_ef(&fl); if (fl.expo > 72) { /* exeeds range by exponent */ regs->GR_L(r1) = fl.sign ? 0x80000000UL : 0x7FFFFFFFUL; regs->psw.cc = 3; return; } if (fl.expo > 64) { /* to be right shifted and to be rounded */ shift = ((92 - fl.expo - 16) * 4); lsfract = fl.ms_fract << (64 - shift); fl.ms_fract >>= shift; if (m3 == 1) { /* biased round to nearest */ if (lsfract & 0x8000000000000000ULL) { fl.ms_fract++; } } else if (m3 == 4) { /* round to nearest */ if (((lsfract & 0x8000000000000000ULL) && ((lsfract & 0x7FFFFFFFFFFFFFFFULL) || fl.ls_fract)) || ( (fl.ms_fract & 0x0000000000000001ULL) && (lsfract == 0x8000000000000000ULL) && (fl.ls_fract == 0))) { fl.ms_fract++; } } else if (m3 == 6) { /* round toward + */ if ((fl.sign == POS) && (lsfract || fl.ls_fract)) { fl.ms_fract++; } } else if (m3 == 7) { /* round toward - */ if ((fl.sign == NEG) && (lsfract || fl.ls_fract)) { fl.ms_fract++; } } } else if (fl.expo == 64) { /* to be rounded */ lsfract = fl.ms_fract << 16; fl.ms_fract = 0; if (m3 == 1) { /* biased round to nearest */ if (lsfract & 0x8000000000000000ULL) { fl.ms_fract++; } } else if (m3 == 4) { /* round to nearest */ if ((lsfract & 0x8000000000000000ULL) && ((lsfract & 0x7FFFFFFFFFFFFFFFULL) || fl.ls_fract)) { fl.ms_fract++; } } else if (m3 == 6) { /* round toward + */ if ((fl.sign == POS) && (lsfract || fl.ls_fract)) { fl.ms_fract++; } } else if (m3 == 7) { /* round toward - */ if ((fl.sign == NEG) && (lsfract || fl.ls_fract)) { fl.ms_fract++; } } } else { /* fl.expo < 64 */ fl.ms_fract = 0; if (((m3 == 6) && (fl.sign == POS)) || ((m3 == 7) && (fl.sign == NEG))) { fl.ms_fract++; } } if (fl.sign) { /* negative */ if (fl.ms_fract > 0x80000000UL) { /* exeeds range by value */ regs->GR_L(r1) = 0x80000000UL; regs->psw.cc = 3; return; } regs->GR_L(r1) = -((S32) fl.ms_fract); regs->psw.cc = 1; } else { /* positive */ if (fl.ms_fract > 0x7FFFFFFFUL) { /* exeeds range by value */ regs->GR_L(r1) = 0x7FFFFFFFUL; regs->psw.cc = 3; return; } regs->GR_L(r1) = fl.ms_fract; regs->psw.cc = 2; } } else { /* zero */ regs->GR_L(r1) = 0; regs->psw.cc = 0; } } /*-------------------------------------------------------------------*/ /* B3C8 CGER - Convert from Float. Short to Fix64 Register [RRF] */ /*-------------------------------------------------------------------*/ DEF_INST(convert_float_short_to_fix64_reg) { int r1, r2; /* Values of R fields */ int m3; SHORT_FLOAT fl; BYTE shift; U64 intpart; U32 lsfract; RRF_M(inst, regs, r1, r2, m3); HFPM_CHECK(m3, regs); HFPREG_CHECK(r2, regs); /* Get register content */ get_sf(&fl, regs->fpr + FPR2I(r2)); if (fl.short_fract) { /* not zero */ normal_sf(&fl); if (fl.expo > 80) { /* exeeds range by exponent */ regs->GR_G(r1) = fl.sign ? 0x8000000000000000ULL : 0x7FFFFFFFFFFFFFFFULL; regs->psw.cc = 3; return; } if (fl.expo > 70) { /* to be left shifted */ intpart = (U64)fl.short_fract << ((fl.expo - 70) * 4); if (fl.sign) { /* negative */ if (intpart > 0x8000000000000000ULL) { /* exeeds range by value */ regs->GR_G(r1) = 0x8000000000000000ULL; regs->psw.cc = 3; return; } } else { /* positive */ if (intpart > 0x7FFFFFFFFFFFFFFFULL) { /* exeeds range by value */ regs->GR_G(r1) = 0x7FFFFFFFFFFFFFFFULL; regs->psw.cc = 3; return; } } } else if ((fl.expo > 64) && (fl.expo < 70)) { /* to be right shifted and to be rounded */ shift = ((70 - fl.expo) * 4); lsfract = fl.short_fract << (32 - shift); intpart = fl.short_fract >> shift; if (m3 == 1) { /* biased round to nearest */ if (lsfract & 0x80000000UL) { intpart++; } } else if (m3 == 4) { /* round to nearest */ if ((lsfract > 0x80000000UL) || ((intpart & 0x0000000000000001ULL) && (lsfract == 0x80000000UL))) { intpart++; } } else if (m3 == 6) { /* round toward + */ if ((fl.sign == POS) && lsfract) { intpart++; } } else if (m3 == 7) { /* round toward - */ if ((fl.sign == NEG) && lsfract) { intpart++; } } } else if (fl.expo == 64) { /* to be rounded */ lsfract = fl.short_fract << 8; intpart = 0; if (m3 == 1) { /* biased round to nearest */ if (lsfract & 0x80000000UL) { intpart++; } } else if (m3 == 4) { /* round to nearest */ if (lsfract > 0x80000000UL) { intpart++; } } else if (m3 == 6) { /* round toward + */ if ((fl.sign == POS) && lsfract) { intpart++; } } else if (m3 == 7) { /* round toward - */ if ((fl.sign == NEG) && lsfract) { intpart++; } } } else if (fl.expo < 64) { intpart = 0; if (((m3 == 6) && (fl.sign == POS)) || ((m3 == 7) && (fl.sign == NEG))) { intpart++; } } else /* fl.expo == 70 */ { /* no shift or round required */ intpart = (U64)fl.short_fract; } if (fl.sign) { /* negative */ if (intpart == 0x8000000000000000ULL) regs->GR_G(r1) = 0x8000000000000000ULL; else regs->GR_G(r1) = -((S64)intpart); regs->psw.cc = 1; } else { /* positive */ regs->GR_G(r1) = intpart; regs->psw.cc = 2; } } else { /* zero */ regs->GR_G(r1) = 0; regs->psw.cc = 0; } } /*-------------------------------------------------------------------*/ /* B3C9 CGDR - Convert from Float. Long to Fix64 Register [RRF] */ /*-------------------------------------------------------------------*/ DEF_INST(convert_float_long_to_fix64_reg) { int r1, r2; /* Values of R fields */ int m3; LONG_FLOAT fl; BYTE shift; U64 lsfract; RRF_M(inst, regs, r1, r2, m3); HFPM_CHECK(m3, regs); HFPREG_CHECK(r2, regs); /* Get register content */ get_lf(&fl, regs->fpr + FPR2I(r2)); if (fl.long_fract) { /* not zero */ normal_lf(&fl); if (fl.expo > 80) { /* exeeds range by exponent */ regs->GR_G(r1) = fl.sign ? 0x8000000000000000ULL : 0x7FFFFFFFFFFFFFFFULL; regs->psw.cc = 3; return; } if (fl.expo > 78) { /* to be left shifted */ fl.long_fract <<= ((fl.expo - 78) * 4); if (fl.sign) { /* negative */ if (fl.long_fract > 0x8000000000000000ULL) { /* exeeds range by value */ regs->GR_G(r1) = 0x8000000000000000ULL; regs->psw.cc = 3; return; } } else { /* positive */ if (fl.long_fract > 0x7FFFFFFFFFFFFFFFULL) { /* exeeds range by value */ regs->GR_G(r1) = 0x7FFFFFFFFFFFFFFFULL; regs->psw.cc = 3; return; } } } else if ((fl.expo > 64) && (fl.expo < 78)) { /* to be right shifted and to be rounded */ shift = ((78 - fl.expo) * 4); lsfract = fl.long_fract << (64 - shift); fl.long_fract >>= shift; if (m3 == 1) { /* biased round to nearest */ if (lsfract & 0x8000000000000000ULL) { fl.long_fract++; } } else if (m3 == 4) { /* round to nearest */ if ((lsfract > 0x8000000000000000ULL) || ((fl.long_fract & 0x0000000000000001ULL) && (lsfract == 0x8000000000000000ULL))) { fl.long_fract++; } } else if (m3 == 6) { /* round toward + */ if ((fl.sign == POS) && lsfract) { fl.long_fract++; } } else if (m3 == 7) { /* round toward - */ if ((fl.sign == NEG) && lsfract) { fl.long_fract++; } } } else if (fl.expo == 64) { /* to be rounded */ lsfract = fl.long_fract << 8; fl.long_fract = 0; if (m3 == 1) { /* biased round to nearest */ if (lsfract & 0x8000000000000000ULL) { fl.long_fract++; } } else if (m3 == 4) { /* round to nearest */ if (lsfract > 0x8000000000000000ULL) { fl.long_fract++; } } else if (m3 == 6) { /* round toward + */ if ((fl.sign == POS) && lsfract) { fl.long_fract++; } } else if (m3 == 7) { /* round toward - */ if ((fl.sign == NEG) && lsfract) { fl.long_fract++; } } } else if (fl.expo < 64) { fl.long_fract = 0; if (((m3 == 6) && (fl.sign == POS)) || ((m3 == 7) && (fl.sign == NEG))) { fl.long_fract++; } } if (fl.sign) { /* negative */ if (fl.long_fract == 0x8000000000000000ULL) regs->GR_G(r1) = 0x8000000000000000ULL; else regs->GR_G(r1) = -((S64)fl.long_fract); regs->psw.cc = 1; } else { /* positive */ regs->GR_G(r1) = fl.long_fract; regs->psw.cc = 2; } } else { /* zero */ regs->GR_G(r1) = 0; regs->psw.cc = 0; } } /*-------------------------------------------------------------------*/ /* B3CA CGXR - Convert from Float. Extended to Fix64 Register [RRF] */ /*-------------------------------------------------------------------*/ DEF_INST(convert_float_ext_to_fix64_reg) { int r1, r2; /* Values of R fields */ int m3; EXTENDED_FLOAT fl; BYTE shift; U64 intpart; U64 lsfract; RRF_M(inst, regs, r1, r2, m3); HFPM_CHECK(m3, regs); HFPODD_CHECK(r2, regs); /* Get register content */ get_ef(&fl, regs->fpr + FPR2I(r2)); if (fl.ms_fract || fl.ls_fract) { /* not zero */ normal_ef(&fl); if (fl.expo > 80) { /* exeeds range by exponent */ regs->GR_G(r1) = fl.sign ? 0x8000000000000000ULL : 0x7FFFFFFFFFFFFFFFULL; regs->psw.cc = 3; return; } if (fl.expo > 64) { /* to be right shifted and to be rounded */ shift = ((92 - fl.expo) * 4); if (shift > 64) { intpart = fl.ms_fract >> (shift - 64); lsfract = (fl.ls_fract >> (128 - shift)) | (fl.ms_fract << (128 - shift)); } else if (shift < 64) { intpart = (fl.ls_fract >> shift) | (fl.ms_fract << (64 - shift)); lsfract = fl.ls_fract << (64 - shift); } else /* shift == 64 */ { intpart = fl.ms_fract; lsfract = fl.ls_fract; } if (m3 == 1) { /* biased round to nearest */ if (lsfract & 0x8000000000000000ULL) { intpart++; } } else if (m3 == 4) { /* round to nearest */ if ((lsfract > 0x8000000000000000ULL) || ((intpart & 0x0000000000000001ULL) && (lsfract == 0x8000000000000000ULL))) { intpart++; } } else if (m3 == 6) { /* round toward + */ if ((fl.sign == POS) && lsfract) { intpart++; } } else if (m3 == 7) { /* round toward - */ if ((fl.sign == NEG) && lsfract) { intpart++; } } } else if (fl.expo == 64) { /* to be rounded */ lsfract = (fl.ms_fract << 16) | (fl.ls_fract >> 48); intpart = 0; if (m3 == 1) { /* biased round to nearest */ if (lsfract & 0x8000000000000000ULL) { intpart++; } } else if (m3 == 4) { /* round to nearest */ if (lsfract > 0x8000000000000000ULL) { intpart++; } } else if (m3 == 6) { /* round toward + */ if ((fl.sign == POS) && lsfract) { intpart++; } } else if (m3 == 7) { /* round toward - */ if ((fl.sign == NEG) && lsfract) { intpart++; } } } else { /* fl.expo < 64 */ intpart = 0; if (((m3 == 6) && (fl.sign == POS)) || ((m3 == 7) && (fl.sign == NEG))) { intpart++; } } if (fl.sign) { /* negative */ if (intpart > 0x8000000000000000ULL) { /* exeeds range by value */ regs->GR_G(r1) = 0x8000000000000000ULL; regs->psw.cc = 3; return; } if (intpart == 0x8000000000000000ULL) regs->GR_G(r1) = 0x8000000000000000ULL; else regs->GR_G(r1) = -((S64)intpart); regs->psw.cc = 1; } else { /* positive */ if (intpart > 0x7FFFFFFFFFFFFFFFULL) { /* exeeds range by value */ regs->GR_G(r1) = 0x7FFFFFFFFFFFFFFFULL; regs->psw.cc = 3; return; } regs->GR_G(r1) = intpart; regs->psw.cc = 2; } } else { /* zero */ regs->GR_G(r1) = 0; regs->psw.cc = 0; } } /*-------------------------------------------------------------------*/ /* ED24 LDE - Load Lengthened Floating Point Short to Long [RXE] */ /*-------------------------------------------------------------------*/ DEF_INST(load_lengthened_float_short_to_long) { int r1; /* Value of R field */ int i1; int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ RXE(inst, regs, r1, b2, effective_addr2); HFPREG_CHECK(r1, regs); i1 = FPR2I(r1); /* Update first 32 bits of register from operand address */ regs->fpr[i1] = ARCH_DEP(vfetch4) (effective_addr2, b2, regs); /* Zero register content */ regs->fpr[i1+1] = 0; } /*-------------------------------------------------------------------*/ /* ED25 LXD - Load Lengthened Floating Point Long to Extended [RXE] */ /*-------------------------------------------------------------------*/ DEF_INST(load_lengthened_float_long_to_ext) { int r1; /* Value of R field */ int i1; int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ U32 wk; U64 wkd; RXE(inst, regs, r1, b2, effective_addr2); HFPODD_CHECK(r1, regs); i1 = FPR2I(r1); /* Get the 2nd operand */ wkd = ARCH_DEP(vfetch8) (effective_addr2, b2, regs); wk = wkd >> 32; if (wkd & 0x00FFFFFFFFFFFFFFULL) { /* Back to register */ regs->fpr[i1] = wk; regs->fpr[i1+1] = wkd; /* Low order register */ regs->fpr[i1+FPREX] = (wk & 0x80000000) | ((wk - (14 << 24)) & 0x7F000000); } else { /* true zero with sign */ regs->fpr[i1] = (wk & 0x80000000); regs->fpr[i1+FPREX] = regs->fpr[i1]; regs->fpr[i1+1] = 0; } regs->fpr[i1+FPREX+1] = 0; } /*-------------------------------------------------------------------*/ /* ED26 LXE - Load Lengthened Float. Short to Extended [RXE] */ /*-------------------------------------------------------------------*/ DEF_INST(load_lengthened_float_short_to_ext) { int r1; /* Value of R field */ int i1; int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ U32 wk; RXE(inst, regs, r1, b2, effective_addr2); HFPODD_CHECK(r1, regs); i1 = FPR2I(r1); /* Get the 2nd operand */ wk = ARCH_DEP(vfetch4) (effective_addr2, b2, regs); if (wk & 0x00FFFFFF) { /* Back to register */ regs->fpr[i1] = wk; /* Zero register content */ regs->fpr[i1+1] = 0; /* Low order register */ regs->fpr[i1+FPREX] = (wk & 0x80000000) | ((wk - (14 << 24)) & 0x7F000000); regs->fpr[i1+FPREX+1] = 0; } else { /* true zero with sign */ regs->fpr[i1] = (wk & 0x80000000); regs->fpr[i1+FPREX] = regs->fpr[i1]; regs->fpr[i1+1] = 0; regs->fpr[i1+FPREX+1] = 0; } } /*-------------------------------------------------------------------*/ /* ED34 SQE - Square Root Floating Point Short [RXE] */ /*-------------------------------------------------------------------*/ DEF_INST(squareroot_float_short) { int r1; /* Value of R field */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ SHORT_FLOAT sq_fl; SHORT_FLOAT fl; RXE(inst, regs, r1, b2, effective_addr2); HFPREG_CHECK(r1, regs); /* Get the 2nd operand */ vfetch_sf(&fl, effective_addr2, b2, regs ); /* short square root subroutine */ sq_sf(&sq_fl, &fl, regs); /* Back to register */ store_sf(&sq_fl, regs->fpr + FPR2I(r1)); } /*-------------------------------------------------------------------*/ /* ED35 SQD - Square Root Floating Point Long [RXE] */ /*-------------------------------------------------------------------*/ DEF_INST(squareroot_float_long) { int r1; /* Value of R field */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ LONG_FLOAT sq_fl; LONG_FLOAT fl; RXE(inst, regs, r1, b2, effective_addr2); HFPREG_CHECK(r1, regs); /* Get the 2nd operand */ vfetch_lf(&fl, effective_addr2, b2, regs ); /* long square root subroutine */ sq_lf(&sq_fl, &fl, regs); /* Back to register */ store_lf(&sq_fl, regs->fpr + FPR2I(r1)); } /*-------------------------------------------------------------------*/ /* ED37 MEE - Multiply Floating Point Short [RXE] */ /*-------------------------------------------------------------------*/ DEF_INST(multiply_float_short) { int r1; /* Value of R field */ int i1; int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ SHORT_FLOAT fl; SHORT_FLOAT mul_fl; int pgm_check; RXE(inst, regs, r1, b2, effective_addr2); HFPREG_CHECK(r1, regs); i1 = FPR2I(r1); /* Get the operands */ get_sf(&fl, regs->fpr + i1); vfetch_sf(&mul_fl, effective_addr2, b2, regs ); /* multiply short to long */ pgm_check = mul_sf(&fl, &mul_fl, OVUNF, regs); /* Back to register */ store_sf(&fl, regs->fpr + i1); /* Program check ? */ if (pgm_check) { ARCH_DEP(program_interrupt) (regs, pgm_check); } } #endif /* FEATURE_HFP_EXTENSIONS */ #if defined(FEATURE_FPS_EXTENSIONS) /*-------------------------------------------------------------------*/ /* B365 LXR - Load Floating Point Extended Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(load_float_ext_reg) { int r1, r2; /* Values of R fields */ int i1, i2; /* Index into fpr array */ RRE(inst, regs, r1, r2); HFPODD2_CHECK(r1, r2, regs); i1 = FPR2I(r1); i2 = FPR2I(r2); /* Copy register R2 contents to register R1 */ regs->fpr[i1] = regs->fpr[i2]; regs->fpr[i1+1] = regs->fpr[i2+1]; regs->fpr[i1+FPREX] = regs->fpr[i2+FPREX]; regs->fpr[i1+FPREX+1] = regs->fpr[i2+FPREX+1]; } /* end DEF_INST(load_float_ext_reg) */ /*-------------------------------------------------------------------*/ /* B374 LZER - Load Zero Floating Point Short Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(load_zero_float_short_reg) { int r1, r2; /* Values of R fields */ int i1; /* Index of R1 in fpr array */ RRE(inst, regs, r1, r2); HFPREG_CHECK(r1, regs); i1 = FPR2I(r1); /* Set all bits of register R1 to zeros */ regs->fpr[i1] = 0; } /* end DEF_INST(load_zero_float_short_reg) */ /*-------------------------------------------------------------------*/ /* B375 LZDR - Load Zero Floating Point Long Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(load_zero_float_long_reg) { int r1, r2; /* Values of R fields */ int i1; /* Index of R1 in fpr array */ RRE(inst, regs, r1, r2); HFPREG_CHECK(r1, regs); i1 = FPR2I(r1); /* Set all bits of register R1 to zeros */ regs->fpr[i1] = 0; regs->fpr[i1+1] = 0; } /* end DEF_INST(load_zero_float_long_reg) */ /*-------------------------------------------------------------------*/ /* B376 LZXR - Load Zero Floating Point Extended Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(load_zero_float_ext_reg) { int r1, r2; /* Values of R fields */ int i1; /* Index of R1 in fpr array */ RRE(inst, regs, r1, r2); HFPODD_CHECK(r1, regs); i1 = FPR2I(r1); /* Set all bits of register R1 to zeros */ regs->fpr[i1] = 0; regs->fpr[i1+1] = 0; regs->fpr[i1+FPREX] = 0; regs->fpr[i1+FPREX+1] = 0; } /* end DEF_INST(load_zero_float_ext_reg) */ #endif /*defined(FEATURE_FPS_EXTENSIONS)*/ #if defined(FEATURE_HFP_MULTIPLY_ADD_SUBTRACT) /*-------------------------------------------------------------------*/ /* B32E MAER - Multiply and Add Floating Point Short Register [RRF] */ /*-------------------------------------------------------------------*/ DEF_INST(multiply_add_float_short_reg) { int r1, r2, r3; /* Values of R fields */ int i1; /* Index of R1 in fpr array */ SHORT_FLOAT fl1, fl2, fl3; int pgm_check; RRF_R(inst, regs, r1, r2, r3); HFPREG2_CHECK(r1, r2, regs); HFPREG_CHECK(r3, regs); i1 = FPR2I(r1); /* Get the operands */ get_sf(&fl1, regs->fpr + i1); get_sf(&fl2, regs->fpr + FPR2I(r2)); get_sf(&fl3, regs->fpr + FPR2I(r3)); /* Multiply third and second operands */ mul_sf(&fl2, &fl3, NOOVUNF, regs); /* Add the first operand with normalization */ pgm_check = add_sf(&fl1, &fl2, NORMAL, NOSIGEX, regs); /* Store result back to first operand register */ store_sf(&fl1, regs->fpr + i1); /* Program check ? */ if (pgm_check) { ARCH_DEP(program_interrupt) (regs, pgm_check); } } /* end DEF_INST(multiply_add_float_short_reg) */ /*-------------------------------------------------------------------*/ /* B32F MSER - Multiply and Subtract Floating Point Short Reg [RRF] */ /*-------------------------------------------------------------------*/ DEF_INST(multiply_subtract_float_short_reg) { int r1, r2, r3; /* Values of R fields */ int i1; /* Index of R1 in fpr array */ SHORT_FLOAT fl1, fl2, fl3; int pgm_check; RRF_R(inst, regs, r1, r2, r3); HFPREG2_CHECK(r1, r2, regs); HFPREG_CHECK(r3, regs); i1 = FPR2I(r1); /* Get the operands */ get_sf(&fl1, regs->fpr + i1); get_sf(&fl2, regs->fpr + FPR2I(r2)); get_sf(&fl3, regs->fpr + FPR2I(r3)); /* Multiply third and second operands */ mul_sf(&fl2, &fl3, NOOVUNF, regs); /* Invert the sign of the first operand */ fl1.sign = ! (fl1.sign); /* Subtract the first operand with normalization */ pgm_check = add_sf(&fl1, &fl2, NORMAL, NOSIGEX, regs); /* Store result back to first operand register */ store_sf(&fl1, regs->fpr + i1); /* Program check ? */ if (pgm_check) { ARCH_DEP(program_interrupt) (regs, pgm_check); } } /* end DEF_INST(multiply_subtract_float_short_reg) */ /*-------------------------------------------------------------------*/ /* B33E MADR - Multiply and Add Floating Point Long Register [RRF] */ /*-------------------------------------------------------------------*/ DEF_INST(multiply_add_float_long_reg) { int r1, r2, r3; /* Values of R fields */ int i1; /* Index of R1 in fpr array */ LONG_FLOAT fl1, fl2, fl3; int pgm_check; RRF_R(inst, regs, r1, r2, r3); HFPREG2_CHECK(r1, r2, regs); HFPREG_CHECK(r3, regs); i1 = FPR2I(r1); /* Get the operands */ get_lf(&fl1, regs->fpr + i1); get_lf(&fl2, regs->fpr + FPR2I(r2)); get_lf(&fl3, regs->fpr + FPR2I(r3)); /* Multiply long third and second operands */ mul_lf(&fl2, &fl3, NOOVUNF, regs); /* Add the first operand with normalization */ pgm_check = add_lf(&fl1, &fl2, NORMAL, NOSIGEX, regs); /* Store result back to first operand register */ store_lf(&fl1, regs->fpr + i1); /* Program check ? */ if (pgm_check) { ARCH_DEP(program_interrupt) (regs, pgm_check); } } /* end DEF_INST(multiply_add_float_long_reg) */ /*-------------------------------------------------------------------*/ /* B33F MSDR - Multiply and Subtract Floating Point Long Reg [RRF] */ /*-------------------------------------------------------------------*/ DEF_INST(multiply_subtract_float_long_reg) { int r1, r2, r3; /* Values of R fields */ int i1; /* Index of R1 in fpr array */ LONG_FLOAT fl1, fl2, fl3; int pgm_check; RRF_R(inst, regs, r1, r2, r3); HFPREG2_CHECK(r1, r2, regs); HFPREG_CHECK(r3, regs); i1 = FPR2I(r1); /* Get the operands */ get_lf(&fl1, regs->fpr + i1); get_lf(&fl2, regs->fpr + FPR2I(r2)); get_lf(&fl3, regs->fpr + FPR2I(r3)); /* Multiply long third and second operands */ mul_lf(&fl2, &fl3, NOOVUNF, regs); /* Invert the sign of the first operand */ fl1.sign = ! (fl1.sign); /* Subtract the first operand with normalization */ pgm_check = add_lf(&fl1, &fl2, NORMAL, NOSIGEX, regs); /* Store result back to first operand register */ store_lf(&fl1, regs->fpr + i1); /* Program check ? */ if (pgm_check) { ARCH_DEP(program_interrupt) (regs, pgm_check); } } /* end DEF_INST(multiply_subtract_float_long_reg) */ /*-------------------------------------------------------------------*/ /* ED2E MAE - Multiply and Add Floating Point Short [RXF] */ /*-------------------------------------------------------------------*/ DEF_INST(multiply_add_float_short) { int r1, r3; /* Values of R fields */ int i1; /* Index of R1 in fpr array */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ SHORT_FLOAT fl1, fl2, fl3; int pgm_check; RXF(inst, regs, r1, r3, b2, effective_addr2); HFPREG2_CHECK(r1, r3, regs); i1 = FPR2I(r1); /* Get the operands */ get_sf(&fl1, regs->fpr + i1); vfetch_sf(&fl2, effective_addr2, b2, regs ); get_sf(&fl3, regs->fpr + FPR2I(r3)); /* Multiply third and second operands */ mul_sf(&fl2, &fl3, NOOVUNF, regs); /* Add the first operand with normalization */ pgm_check = add_sf(&fl1, &fl2, NORMAL, NOSIGEX, regs); /* Back to register */ store_sf(&fl1, regs->fpr + i1); /* Program check ? */ if (pgm_check) { ARCH_DEP(program_interrupt) (regs, pgm_check); } } /* end DEF_INST(multiply_add_float_short) */ /*-------------------------------------------------------------------*/ /* ED2F MSE - Multiply and Subtract Floating Point Short [RXF] */ /*-------------------------------------------------------------------*/ DEF_INST(multiply_subtract_float_short) { int r1, r3; /* Values of R fields */ int i1; /* Index of R1 in fpr array */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ SHORT_FLOAT fl1, fl2, fl3; int pgm_check; RXF(inst, regs, r1, r3, b2, effective_addr2); HFPREG2_CHECK(r1, r3, regs); i1 = FPR2I(r1); /* Get the operands */ get_sf(&fl1, regs->fpr + i1); vfetch_sf(&fl2, effective_addr2, b2, regs ); get_sf(&fl3, regs->fpr + FPR2I(r3)); /* Multiply third and second operands */ mul_sf(&fl2, &fl3, NOOVUNF, regs); /* Invert the sign of the first operand */ fl1.sign = ! (fl1.sign); /* Subtract the first operand with normalization */ pgm_check = add_sf(&fl1, &fl2, NORMAL, NOSIGEX, regs); /* Back to register */ store_sf(&fl1, regs->fpr + i1); /* Program check ? */ if (pgm_check) { ARCH_DEP(program_interrupt) (regs, pgm_check); } } /* end DEF_INST(multiply_subtract_float_short) */ /*-------------------------------------------------------------------*/ /* ED3E MAD - Multiply and Add Floating Point Long [RXF] */ /*-------------------------------------------------------------------*/ DEF_INST(multiply_add_float_long) { int r1, r3; /* Values of R fields */ int i1; /* Index of R1 in fpr array */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ LONG_FLOAT fl1, fl2, fl3; int pgm_check; RXF(inst, regs, r1, r3, b2, effective_addr2); HFPREG2_CHECK(r1, r3, regs); i1 = FPR2I(r1); /* Get the operands */ get_lf(&fl1, regs->fpr + i1); vfetch_lf(&fl2, effective_addr2, b2, regs ); get_lf(&fl3, regs->fpr + FPR2I(r3)); /* Multiply long third and second operands */ mul_lf(&fl2, &fl3, NOOVUNF, regs); /* Add long first operand with normalization */ pgm_check = add_lf(&fl1, &fl2, NORMAL, NOSIGEX, regs); /* Back to register */ store_lf(&fl1, regs->fpr + i1); /* Program check ? */ if (pgm_check) { ARCH_DEP(program_interrupt) (regs, pgm_check); } } /* end DEF_INST(multiply_add_float_long) */ /*-------------------------------------------------------------------*/ /* ED3F MSD - Multiply and Subtract Floating Point Long [RXF] */ /*-------------------------------------------------------------------*/ DEF_INST(multiply_subtract_float_long) { int r1, r3; /* Values of R fields */ int i1; /* Index of R1 in fpr array */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ LONG_FLOAT fl1, fl2, fl3; int pgm_check; RXF(inst, regs, r1, r3, b2, effective_addr2); HFPREG2_CHECK(r1, r3, regs); i1 = FPR2I(r1); /* Get the operands */ get_lf(&fl1, regs->fpr + i1); vfetch_lf(&fl2, effective_addr2, b2, regs ); get_lf(&fl3, regs->fpr + FPR2I(r3)); /* Multiply long third and second operands */ mul_lf(&fl2, &fl3, NOOVUNF, regs); /* Invert the sign of the first operand */ fl1.sign = ! (fl1.sign); /* Subtract long with normalization */ pgm_check = add_lf(&fl1, &fl2, NORMAL, NOSIGEX, regs); /* Back to register */ store_lf(&fl1, regs->fpr + i1); /* Program check ? */ if (pgm_check) { ARCH_DEP(program_interrupt) (regs, pgm_check); } } /* end DEF_INST(multiply_subtract_float_long) */ #endif /*defined(FEATURE_HFP_MULTIPLY_ADD_SUBTRACT)*/ #if defined(FEATURE_HFP_UNNORMALIZED_EXTENSION) /*-------------------------------------------------------------------*/ /* B338 MAYLR - Multiply and Add Unnorm. Long to Ext. Low Reg. [RRF] */ /*-------------------------------------------------------------------*/ DEF_INST(multiply_add_unnormal_float_long_to_ext_low_reg) { int r1, r2, r3; /* Values of R fields */ int i1; /* Index of FP register */ LONG_FLOAT fl2, fl3; /* Multiplier/Multiplicand */ LONG_FLOAT fl1; /* Addend */ EXTENDED_FLOAT fxp1; /* Intermediate product */ EXTENDED_FLOAT fxadd; /* Addend in extended format */ EXTENDED_FLOAT fxres; /* Extended result */ RRF_R(inst, regs, r1, r2, r3) HFPREG2_CHECK(r2, r3, regs); HFPREG_CHECK(r1, regs); i1 = FPR2I(r1); /* Get the operands */ get_lf(&fl1, regs->fpr + i1); get_lf(&fl2, regs->fpr + FPR2I(r2)); get_lf(&fl3, regs->fpr + FPR2I(r3)); /* Calculate intermediate product */ ARCH_DEP(mul_lf_to_ef_unnorm)(&fl2, &fl3, &fxp1); /* Convert Addend to extended format */ ARCH_DEP(lf_to_ef_unnorm)(&fxadd, &fl1); /* Add the addend to the intermediate product */ ARCH_DEP(add_ef_unnorm)(&fxp1, &fxadd, &fxres); /* Place low-order part of result in register */ ARCH_DEP(store_ef_unnorm_lo)(&fxres, regs->fpr + FPR2I(r1)); } /* end DEF_INST(multiply_add_unnormal_float_long_to_ext_low_reg) */ /*-------------------------------------------------------------------*/ /* B339 MYLR - Multiply Unnormalized Long to Ext. Low FP Reg. [RRF] */ /*-------------------------------------------------------------------*/ DEF_INST(multiply_unnormal_float_long_to_ext_low_reg) { int r1, r2, r3; /* Values of R fields */ LONG_FLOAT fl2, fl3; /* Multiplier/Multiplicand */ EXTENDED_FLOAT fx1; /* Intermediate result */ RRF_R(inst, regs, r1, r2, r3); HFPREG2_CHECK(r2, r3, regs); HFPREG_CHECK(r1, regs); /* Get the operands */ get_lf(&fl2, regs->fpr + FPR2I(r2)); get_lf(&fl3, regs->fpr + FPR2I(r3)); /* Calculate intermediate result */ ARCH_DEP(mul_lf_to_ef_unnorm)(&fl2, &fl3, &fx1); /* Place low-order part of result in register */ ARCH_DEP(store_ef_unnorm_lo)(&fx1, regs->fpr + FPR2I(r1)); } /* end DEF_INST(multiply_unnormal_float_long_to_ext_low_reg) */ /*-------------------------------------------------------------------*/ /* B33A MAYR - Multiply and Add Unnorm. Long to Ext. Reg. [RRF] */ /*-------------------------------------------------------------------*/ DEF_INST(multiply_add_unnormal_float_long_to_ext_reg) { int r1, r2, r3; /* Values of R fields */ int i1; /* Index of FP register */ LONG_FLOAT fl2, fl3; /* Multiplier/Multiplicand */ LONG_FLOAT fl1; /* Addend */ EXTENDED_FLOAT fxp1; /* Intermediate product */ EXTENDED_FLOAT fxadd; /* Addend in extended format */ EXTENDED_FLOAT fxres; /* Extended result */ RRF_R(inst, regs, r1, r2, r3); HFPREG2_CHECK(r2, r3, regs); HFPREG_CHECK(r1, regs); /* Either the low- or high-numbered register of a pair is valid */ r1 &= 13; /* Convert to the low numbered register */ i1 = FPR2I(r1); /* Get the operands */ get_lf(&fl1, regs->fpr + i1); get_lf(&fl2, regs->fpr + FPR2I(r2)); get_lf(&fl3, regs->fpr + FPR2I(r3)); /* Calculate intermediate product */ ARCH_DEP(mul_lf_to_ef_unnorm)(&fl2, &fl3, &fxp1); /* Convert Addend to extended format */ ARCH_DEP(lf_to_ef_unnorm)(&fxadd, &fl1); /* Add the addend to the intermediate product */ ARCH_DEP(add_ef_unnorm)(&fxp1, &fxadd, &fxres); /* Place result in register */ ARCH_DEP(store_ef_unnorm)(&fxres, regs->fpr + FPR2I(r1)); } /* end DEF_INST(multiply_add_unnormal_float_long_to_ext_reg) */ /*-------------------------------------------------------------------*/ /* B33B MYR - Multiply Unnormalized Long to Extended Reg [RRF] */ /*-------------------------------------------------------------------*/ DEF_INST(multiply_unnormal_float_long_to_ext_reg) { int r1, r2, r3; /* Values of R fields */ LONG_FLOAT fl2, fl3; /* Multiplier/Multiplicand */ EXTENDED_FLOAT fx1; /* Intermediate result */ RRF_R(inst, regs, r1, r2, r3); HFPODD_CHECK(r1, regs); HFPREG2_CHECK(r2, r3, regs); /* Get the operands */ get_lf(&fl2, regs->fpr + FPR2I(r2)); get_lf(&fl3, regs->fpr + FPR2I(r3)); /* Calculate intermediate result */ ARCH_DEP(mul_lf_to_ef_unnorm)(&fl2, &fl3, &fx1); /* Place result in register */ ARCH_DEP(store_ef_unnorm)(&fx1, regs->fpr + FPR2I(r1)); } /* DEF_INST(multiply_unnormal_float_long_to_ext_reg) */ /*-------------------------------------------------------------------*/ /* B33C MAYHR - Multiply and Add Unnorm. Long to Ext. High Reg [RRF] */ /*-------------------------------------------------------------------*/ DEF_INST(multiply_add_unnormal_float_long_to_ext_high_reg) { int r1, r2, r3; /* Values of R fields */ int i1; /* Index of FP register */ LONG_FLOAT fl2, fl3; /* Multiplier/Multiplicand */ LONG_FLOAT fl1; /* Addend */ EXTENDED_FLOAT fxp1; /* Intermediate product */ EXTENDED_FLOAT fxadd; /* Addend in extended format */ EXTENDED_FLOAT fxres; /* Extended result */ RRF_R(inst, regs, r1, r2, r3); HFPREG2_CHECK(r2, r3, regs); HFPREG_CHECK(r1, regs); i1 = FPR2I(r1); /* Get the operands */ get_lf(&fl1, regs->fpr + i1); get_lf(&fl2, regs->fpr + FPR2I(r2)); get_lf(&fl3, regs->fpr + FPR2I(r3)); /* Calculate intermediate product */ ARCH_DEP(mul_lf_to_ef_unnorm)(&fl2, &fl3, &fxp1); /* Convert Addend to extended format */ ARCH_DEP(lf_to_ef_unnorm)(&fxadd, &fl1); /* Add the addend to the intermediate product */ ARCH_DEP(add_ef_unnorm)(&fxp1, &fxadd, &fxres); /* Place high-order part of result in register */ ARCH_DEP(store_ef_unnorm_hi)(&fxres, regs->fpr + FPR2I(r1)); } /* end DEF_INST(multiply_add_unnormal_float_long_to_ext_high_reg) */ /*-------------------------------------------------------------------*/ /* B33D MYHR - Multiply Unnormalized Long to Ext. High FP Reg[RRF] */ /*-------------------------------------------------------------------*/ DEF_INST(multiply_unnormal_float_long_to_ext_high_reg) { int r1, r2, r3; /* Values of R fields */ LONG_FLOAT fl2, fl3; /* Multiplier/Multiplicand */ EXTENDED_FLOAT fx1; /* Intermediate result */ RRF_R(inst, regs, r1, r2, r3); HFPODD_CHECK(r1, regs); HFPREG2_CHECK(r2, r3, regs); /* Get the operands */ get_lf(&fl2, regs->fpr + FPR2I(r2)); get_lf(&fl3, regs->fpr + FPR2I(r3)); /* Calculate intermediate result */ ARCH_DEP(mul_lf_to_ef_unnorm)(&fl2, &fl3, &fx1); /* Place high-order part of result in register */ ARCH_DEP(store_ef_unnorm_hi)(&fx1, regs->fpr + FPR2I(r1)); } /* end DEF_INST(multiply_unnormal_float_long_to_ext_high_reg) */ /*-------------------------------------------------------------------*/ /* ED38 MAYL - Multiply and Add Unnorm. Long to Ext. Low FP [RXF] */ /*-------------------------------------------------------------------*/ DEF_INST(multiply_add_unnormal_float_long_to_ext_low) { int r1, r3; /* Values of R fields */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ int i1; /* Index of FP register */ LONG_FLOAT fl2,fl3; /* Multiplier/Multiplicand */ LONG_FLOAT fl1; /* Addend */ EXTENDED_FLOAT fxp1; /* Intermediate product */ EXTENDED_FLOAT fxadd; /* Addend in extended format */ EXTENDED_FLOAT fxres; /* Extended result */ RXF(inst, regs, r1, r3, b2, effective_addr2); HFPREG2_CHECK(r1, r3, regs); i1 = FPR2I(r1); /* Get the operands */ get_lf(&fl1, regs->fpr + i1); vfetch_lf(&fl2, effective_addr2, b2, regs ); get_lf(&fl3, regs->fpr + FPR2I(r3)); /* Calculate intermediate product */ ARCH_DEP(mul_lf_to_ef_unnorm)(&fl2, &fl3, &fxp1); /* Convert Addend to extended format */ ARCH_DEP(lf_to_ef_unnorm)(&fxadd, &fl1); /* Add the addend to the intermediate product */ ARCH_DEP(add_ef_unnorm)(&fxp1, &fxadd, &fxres); /* Place low-order part of result in register */ ARCH_DEP(store_ef_unnorm_lo)(&fxres, regs->fpr + FPR2I(r1)); } /* end DEF_INST(multiply_add_unnormal_float_long_to_ext_low) */ /*-------------------------------------------------------------------*/ /* ED39 MYL - Multiply Unnormalized Long to Extended Low FP [RXF] */ /*-------------------------------------------------------------------*/ DEF_INST(multiply_unnormal_float_long_to_ext_low) { int r1, r3; /* Values of R fields */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ LONG_FLOAT fl2, fl3; /* Multiplier/Multiplicand */ EXTENDED_FLOAT fx1; /* Intermediate result */ RXF(inst, regs, r1, r3, b2, effective_addr2); HFPREG2_CHECK(r1, r3, regs); /* Get the operands */ vfetch_lf(&fl2, effective_addr2, b2, regs ); get_lf(&fl3, regs->fpr + FPR2I(r3)); /* Calculate intermediate result */ ARCH_DEP(mul_lf_to_ef_unnorm)(&fl2, &fl3, &fx1); /* Place low-order part of result in register */ ARCH_DEP(store_ef_unnorm_lo)(&fx1, regs->fpr + FPR2I(r1)); } /* end DEF_INST(multiply_unnormal_float_long_to_ext_low) */ /*-------------------------------------------------------------------*/ /* ED3A MAY - Multiply and Add Unnorm. Long to Extended FP [RXF] */ /*-------------------------------------------------------------------*/ DEF_INST(multiply_add_unnormal_float_long_to_ext) { int r1, r3; /* Values of R fields */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ int i1; /* Index of FP register */ LONG_FLOAT fl2, fl3; /* Multiplier/Multiplicand */ LONG_FLOAT fl1; /* Addend */ EXTENDED_FLOAT fxp1; /* Intermediate product */ EXTENDED_FLOAT fxadd; /* Addend in extended format */ EXTENDED_FLOAT fxres; /* Extended result */ RXF(inst, regs, r1, r3, b2, effective_addr2); HFPREG2_CHECK(r1, r3, regs); /* Either the low- or high-numbered register of a pair is valid */ r1 &= 13; /* Convert to the low numbered register */ i1 = FPR2I(r1); /* Get the operands */ get_lf(&fl1, regs->fpr + i1); vfetch_lf(&fl2, effective_addr2, b2, regs ); get_lf(&fl3, regs->fpr + FPR2I(r3)); /* Calculate intermediate product */ ARCH_DEP(mul_lf_to_ef_unnorm)(&fl2, &fl3, &fxp1); /* Convert Addend to extended format */ ARCH_DEP(lf_to_ef_unnorm)(&fxadd, &fl1); /* Add the addend to the intermediate product */ ARCH_DEP(add_ef_unnorm)(&fxp1, &fxadd, &fxres); /* Place result in register */ ARCH_DEP(store_ef_unnorm)(&fxres, regs->fpr + FPR2I(r1)); } /* end DEF_INST(multiply_add_unnormal_float_long_to_ext) */ /*-------------------------------------------------------------------*/ /* ED3B MY - Multiply Unnormalized Long to Extended FP [RXF] */ /*-------------------------------------------------------------------*/ DEF_INST(multiply_unnormal_float_long_to_ext) { int r1, r3; /* Values of R fields */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ LONG_FLOAT fl2, fl3; /* Multiplier/Multiplicand */ EXTENDED_FLOAT fx1; /* Intermediate result */ RXF(inst, regs, r1, r3, b2, effective_addr2); HFPODD_CHECK(r1, regs); HFPREG_CHECK(r3, regs); /* Get the operands */ vfetch_lf(&fl2, effective_addr2, b2, regs ); get_lf(&fl3, regs->fpr + FPR2I(r3)); /* Calculate intermediate result */ ARCH_DEP(mul_lf_to_ef_unnorm)(&fl2, &fl3, &fx1); /* Place result in register */ ARCH_DEP(store_ef_unnorm)(&fx1, regs->fpr + FPR2I(r1)); } /* end DEF_INST(multiply_unnormal_float_long_to_ext) */ /*-------------------------------------------------------------------*/ /* ED3C MAYH - Multiply and Add Unnorm. Long to Extended High [RXF] */ /*-------------------------------------------------------------------*/ DEF_INST(multiply_add_unnormal_float_long_to_ext_high) { int r1, r3; /* Values of R fields */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ int i1; /* Index of FP register */ LONG_FLOAT fl2, fl3; /* Multiplier/Multiplicand */ LONG_FLOAT fl1; /* Addend */ EXTENDED_FLOAT fxp1; /* Intermediate product */ EXTENDED_FLOAT fxadd; /* Addend in extended format */ EXTENDED_FLOAT fxres; /* Extended result */ RXF(inst, regs, r1, r3, b2, effective_addr2); HFPREG2_CHECK(r1, r3, regs); i1 = FPR2I(r1); /* Get the operands */ get_lf(&fl1, regs->fpr + i1); vfetch_lf(&fl2, effective_addr2, b2, regs ); get_lf(&fl3, regs->fpr + FPR2I(r3)); /* Calculate intermediate product */ ARCH_DEP(mul_lf_to_ef_unnorm)(&fl2, &fl3, &fxp1); /* Convert Addend to extended format */ ARCH_DEP(lf_to_ef_unnorm)(&fxadd, &fl1); /* Add the addend to the intermediate product */ ARCH_DEP(add_ef_unnorm)(&fxp1, &fxadd, &fxres); /* Place high-order part of result in register */ ARCH_DEP(store_ef_unnorm_hi)(&fxres, regs->fpr + FPR2I(r1)); } /* end DEF_INST(multiply_add_unnormal_float_long_to_ext_high) */ /*-------------------------------------------------------------------*/ /* ED3D MYH - Multiply Unnormalized Long to Extended High FP [RXF] */ /*-------------------------------------------------------------------*/ DEF_INST(multiply_unnormal_float_long_to_ext_high) { int r1, r3; /* Values of R fields */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ LONG_FLOAT fl2, fl3; /* Multiplier/Multiplicand */ EXTENDED_FLOAT fx1; /* Intermediate result */ RXF(inst, regs, r1, r3, b2, effective_addr2); HFPREG2_CHECK(r1, r3, regs); /* Get the operands */ vfetch_lf(&fl2, effective_addr2, b2, regs ); get_lf(&fl3, regs->fpr + FPR2I(r3)); /* Calculate intermediate result */ ARCH_DEP(mul_lf_to_ef_unnorm)(&fl2, &fl3, &fx1); /* Place high-order part of result in register */ ARCH_DEP(store_ef_unnorm_hi)(&fx1, regs->fpr + FPR2I(r1)); } /* end DEF_INST(multiply_unnormal_float_long_to_ext_high) */ #endif /*defined(FEATURE_HFP_UNNORMALIZED_EXTENSION)*/ #if defined(FEATURE_LONG_DISPLACEMENT) /*-------------------------------------------------------------------*/ /* ED64 LEY - Load Floating Point Short (Long Displacement) [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(load_float_short_y) { int r1; /* Value of R field */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ RXY(inst, regs, r1, b2, effective_addr2); HFPREG_CHECK(r1, regs); /* Update first 32 bits of register from operand address */ regs->fpr[FPR2I(r1)] = ARCH_DEP(vfetch4) (effective_addr2, b2, regs); } /*-------------------------------------------------------------------*/ /* ED65 LDY - Load Floating Point Long (Long Displacement) [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(load_float_long_y) { int r1; /* Value of R field */ int i1; /* Index of r1 in fpr array */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ U64 dreg; /* Double word workarea */ RXY(inst, regs, r1, b2, effective_addr2); HFPREG_CHECK(r1, regs); i1 = FPR2I(r1); /* Fetch value from operand address */ dreg = ARCH_DEP(vfetch8) (effective_addr2, b2, regs); /* Update register contents */ regs->fpr[i1] = dreg >> 32; regs->fpr[i1+1] = dreg; } /*-------------------------------------------------------------------*/ /* ED66 STEY - Store Floating Point Short (Long Displacement) [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(store_float_short_y) { int r1; /* Value of R field */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ RXY(inst, regs, r1, b2, effective_addr2); HFPREG_CHECK(r1, regs); /* Store register contents at operand address */ ARCH_DEP(vstore4) (regs->fpr[FPR2I(r1)], effective_addr2, b2, regs); } /*-------------------------------------------------------------------*/ /* ED67 STDY - Store Floating Point Long (Long Displacement) [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(store_float_long_y) { int r1; /* Value of R field */ int i1; /* Index of r1 in fpr array */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ U64 dreg; /* Double word workarea */ RXY(inst, regs, r1, b2, effective_addr2); HFPREG_CHECK(r1, regs); i1 = FPR2I(r1); /* Store register contents at operand address */ dreg = ((U64)regs->fpr[i1] << 32) | regs->fpr[i1+1]; ARCH_DEP(vstore8) (dreg, effective_addr2, b2, regs); } #endif /*defined(FEATURE_LONG_DISPLACEMENT)*/ #endif /* FEATURE_HEXADECIMAL_FLOATING_POINT */ #if !defined(_GEN_ARCH) #if defined(_ARCHMODE2) #define _GEN_ARCH _ARCHMODE2 #include "float.c" #endif #if defined(_ARCHMODE3) #undef _GEN_ARCH #define _GEN_ARCH _ARCHMODE3 #include "float.c" #endif #endif /*!defined(_GEN_ARCH)*/ /* end of float.c */ hercules-3.07/fthreads.c000644 000765 000765 00000176623 11335365456 016741 0ustar00jmaynardjmaynard000000 000000 //////////////////////////////////////////////////////////////////////////////////// // fthreads.c Fish's WIN32 version of pthreads //////////////////////////////////////////////////////////////////////////////////// // (c) Copyright "Fish" (David B. Trout), 2001-2009. Released under the Q Public License // (http://www.hercules-390.org/herclic.html) as modifications to Hercules. //////////////////////////////////////////////////////////////////////////////////// // $Id: fthreads.c 5620 2010-02-09 00:24:03Z fish $ // // $Log$ // Revision 1.30 2007/11/30 14:54:32 jmaynard // Changed conmicro.cx to hercules-390.org or conmicro.com, as needed. // // Revision 1.29 2007/06/23 00:04:10 ivan // Update copyright notices to include current year (2007) // // Revision 1.28 2007/01/10 09:29:45 fish // Fix thread naming that was inadvertently broken by my 12/28 fishhang change that introduced use of _beginthreadex // // Revision 1.27 2006/12/08 09:43:21 jj // Add CVS message log // #include "hstdinc.h" #define _FTHREADS_C_ #define _HUTIL_DLL_ #include "hercules.h" #include "fthreads.h" #if defined(OPTION_FTHREADS) //////////////////////////////////////////////////////////////////////////////////// // Private internal fthreads structures... typedef struct _tagFT_MUTEX // fthread "mutex" structure { CRITICAL_SECTION MutexLock; // (lock for accessing this data) DWORD dwMutexMagic; // (magic number) HANDLE hUnlockedEvent; // (signalled while NOT locked) DWORD dwMutexType; // (type of mutex (normal, etc)) DWORD dwLockOwner; // (thread-id of who owns it) int nLockedCount; // (#of times lock acquired) } FT_MUTEX, *PFT_MUTEX; typedef struct _tagFT_COND_VAR // fthread "condition variable" structure { CRITICAL_SECTION CondVarLock; // (lock for accessing this data) DWORD dwCondMagic; // (magic number) HANDLE hSigXmitEvent; // set during signal transmission HANDLE hSigRecvdEvent; // set once signal received by every- // one that's supposed to receive it. BOOL bBroadcastSig; // TRUE = "broadcast", FALSE = "signal" int nNumWaiting; // #of threads waiting to receive signal } FT_COND_VAR, *PFT_COND_VAR; //////////////////////////////////////////////////////////////////////////////////// // So we can tell whether our structures have been properly initialized or not... #define FT_MUTEX_MAGIC 0x4D767478 // "Mutx" in ASCII #define FT_COND_MAGIC 0x436F6E64 // "Cond" in ASCII #define FT_ATTR_MAGIC 0x41747472 // "Attr" in ASCII //////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////// // Private internal fthreads functions... static BOOL IsValidMutexType ( DWORD dwMutexType ) { return (0 // || FTHREAD_MUTEX_DEFAULT == dwMutexType // (FTHREAD_MUTEX_RECURSIVE) || FTHREAD_MUTEX_RECURSIVE == dwMutexType || FTHREAD_MUTEX_ERRORCHECK == dwMutexType // || FTHREAD_MUTEX_NORMAL == dwMutexType // (not currently supported) ); } //////////////////////////////////////////////////////////////////////////////////// static FT_MUTEX* MallocFT_MUTEX ( ) { FT_MUTEX* pFT_MUTEX = (FT_MUTEX*) malloc ( sizeof ( FT_MUTEX ) ); if ( !pFT_MUTEX ) return NULL; memset ( pFT_MUTEX, 0xCD, sizeof ( FT_MUTEX ) ); return pFT_MUTEX; } //////////////////////////////////////////////////////////////////////////////////// static BOOL InitializeFT_MUTEX ( #ifdef FISH_HANG const char* pszFile, const int nLine, #endif FT_MUTEX* pFT_MUTEX, DWORD dwMutexType ) { // Note: UnlockedEvent created initially signalled if ( !(pFT_MUTEX->hUnlockedEvent = MyCreateEvent ( NULL, TRUE, TRUE, NULL )) ) { memset ( pFT_MUTEX, 0xCD, sizeof ( FT_MUTEX ) ); return FALSE; } MyInitializeCriticalSection ( &pFT_MUTEX->MutexLock ); pFT_MUTEX->dwMutexMagic = FT_MUTEX_MAGIC; pFT_MUTEX->dwMutexType = dwMutexType; pFT_MUTEX->dwLockOwner = 0; pFT_MUTEX->nLockedCount = 0; return TRUE; } //////////////////////////////////////////////////////////////////////////////////// static BOOL UninitializeFT_MUTEX ( #ifdef FISH_HANG const char* pszFile, const int nLine, #endif FT_MUTEX* pFT_MUTEX ) { if ( pFT_MUTEX->nLockedCount > 0 ) return FALSE; // (still in use) ASSERT( IsEventSet ( pFT_MUTEX->hUnlockedEvent ) ); MyDeleteEvent ( pFT_MUTEX->hUnlockedEvent ); MyDeleteCriticalSection ( &pFT_MUTEX->MutexLock ); memset ( pFT_MUTEX, 0xCD, sizeof ( FT_MUTEX ) ); return TRUE; } //////////////////////////////////////////////////////////////////////////////////// static FT_COND_VAR* MallocFT_COND_VAR ( ) { FT_COND_VAR* pFT_COND_VAR = (FT_COND_VAR*) malloc ( sizeof ( FT_COND_VAR ) ); if ( !pFT_COND_VAR ) return NULL; memset ( pFT_COND_VAR, 0xCD, sizeof ( FT_COND_VAR ) ); return pFT_COND_VAR; } //////////////////////////////////////////////////////////////////////////////////// static BOOL InitializeFT_COND_VAR ( #ifdef FISH_HANG const char* pszFile, const int nLine, #endif FT_COND_VAR* pFT_COND_VAR ) { if ( ( pFT_COND_VAR->hSigXmitEvent = MyCreateEvent ( NULL, TRUE, FALSE, NULL ) ) ) { // Note: hSigRecvdEvent created initially signaled if ( ( pFT_COND_VAR->hSigRecvdEvent = MyCreateEvent ( NULL, TRUE, TRUE, NULL ) ) ) { MyInitializeCriticalSection ( &pFT_COND_VAR->CondVarLock ); pFT_COND_VAR->dwCondMagic = FT_COND_MAGIC; pFT_COND_VAR->bBroadcastSig = FALSE; pFT_COND_VAR->nNumWaiting = 0; return TRUE; } MyDeleteEvent ( pFT_COND_VAR->hSigXmitEvent ); } memset ( pFT_COND_VAR, 0xCD, sizeof ( FT_COND_VAR ) ); return FALSE; } //////////////////////////////////////////////////////////////////////////////////// static BOOL UninitializeFT_COND_VAR ( #ifdef FISH_HANG const char* pszFile, const int nLine, #endif FT_COND_VAR* pFT_COND_VAR ) { if (0 || pFT_COND_VAR->nNumWaiting || IsEventSet ( pFT_COND_VAR->hSigXmitEvent ) || !IsEventSet ( pFT_COND_VAR->hSigRecvdEvent ) ) return FALSE; MyDeleteEvent ( pFT_COND_VAR->hSigXmitEvent ); MyDeleteEvent ( pFT_COND_VAR->hSigRecvdEvent ); MyDeleteCriticalSection ( &pFT_COND_VAR->CondVarLock ); memset ( pFT_COND_VAR, 0xCD, sizeof ( FT_COND_VAR ) ); return TRUE; } //////////////////////////////////////////////////////////////////////////////////// static BOOL TryEnterFT_MUTEX ( #ifdef FISH_HANG const char* pszFile, const int nLine, #endif FT_MUTEX* pFT_MUTEX ) { BOOL bSuccess; DWORD dwThreadId = GetCurrentThreadId(); if ( hostinfo.trycritsec_avail ) { bSuccess = MyTryEnterCriticalSection ( &pFT_MUTEX->MutexLock ); if ( bSuccess ) { pFT_MUTEX->nLockedCount++; ASSERT( pFT_MUTEX->nLockedCount > 0 ); pFT_MUTEX->dwLockOwner = dwThreadId; } } else { MyEnterCriticalSection ( &pFT_MUTEX->MutexLock ); ASSERT ( pFT_MUTEX->nLockedCount >= 0 ); bSuccess = ( pFT_MUTEX->nLockedCount <= 0 || pFT_MUTEX->dwLockOwner == dwThreadId ); if ( bSuccess ) { pFT_MUTEX->nLockedCount++; ASSERT ( pFT_MUTEX->nLockedCount > 0 ); pFT_MUTEX->dwLockOwner = dwThreadId; MyResetEvent ( pFT_MUTEX->hUnlockedEvent ); } MyLeaveCriticalSection ( &pFT_MUTEX->MutexLock ); } return bSuccess; } //////////////////////////////////////////////////////////////////////////////////// static void EnterFT_MUTEX ( #ifdef FISH_HANG const char* pszFile, const int nLine, #endif FT_MUTEX* pFT_MUTEX ) { DWORD dwThreadId = GetCurrentThreadId(); if ( hostinfo.trycritsec_avail ) { MyEnterCriticalSection ( &pFT_MUTEX->MutexLock ); pFT_MUTEX->dwLockOwner = dwThreadId; pFT_MUTEX->nLockedCount++; ASSERT ( pFT_MUTEX->nLockedCount > 0 ); } else { for (;;) { MyEnterCriticalSection ( &pFT_MUTEX->MutexLock ); ASSERT ( pFT_MUTEX->nLockedCount >= 0 ); if ( pFT_MUTEX->nLockedCount <= 0 || pFT_MUTEX->dwLockOwner == dwThreadId ) break; MyLeaveCriticalSection ( &pFT_MUTEX->MutexLock ); MyWaitForSingleObject ( pFT_MUTEX->hUnlockedEvent, INFINITE ); } MyResetEvent ( pFT_MUTEX->hUnlockedEvent ); pFT_MUTEX->dwLockOwner = dwThreadId; pFT_MUTEX->nLockedCount++; ASSERT ( pFT_MUTEX->nLockedCount > 0 ); MyLeaveCriticalSection ( &pFT_MUTEX->MutexLock ); } } //////////////////////////////////////////////////////////////////////////////////// static void LeaveFT_MUTEX ( #ifdef FISH_HANG const char* pszFile, const int nLine, #endif FT_MUTEX* pFT_MUTEX ) { if ( hostinfo.trycritsec_avail ) { ASSERT ( pFT_MUTEX->nLockedCount > 0 ); pFT_MUTEX->nLockedCount--; if ( pFT_MUTEX->nLockedCount <= 0 ) pFT_MUTEX->dwLockOwner = 0; MyLeaveCriticalSection ( &pFT_MUTEX->MutexLock ); } else { MyEnterCriticalSection ( &pFT_MUTEX->MutexLock ); ASSERT ( pFT_MUTEX->nLockedCount > 0 ); pFT_MUTEX->nLockedCount--; if ( pFT_MUTEX->nLockedCount <= 0 ) { pFT_MUTEX->dwLockOwner = 0; MySetEvent ( pFT_MUTEX->hUnlockedEvent ); } MyLeaveCriticalSection ( &pFT_MUTEX->MutexLock ); } } //////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////// // Now we get to the "meat" of fthreads... // // The below function atomically releases the caller's mutex and registers the fact // that the caller wishes to wait on their condition variable (or rather the other // way around: it first registers the fact that the caller wishes to wait on the // condition by first acquiring the condition variable lock and then registering // the wait and THEN afterwards (once the wait has been registered and condition // variable lock acquired) releases the original mutex). This ensures that no one // can "sneak a signal past us" from the time this function is called until we can // manage to register the wait request since no signals can ever be sent while the // condition variable is locked. static int BeginWait ( #ifdef FISH_HANG const char* pszFile, const int nLine, #endif FT_COND_VAR* pFT_COND_VAR, fthread_mutex_t* pFTUSER_MUTEX ) { int rc; FT_MUTEX* pFT_MUTEX; if (0 || !pFT_COND_VAR // (invalid ptr) || pFT_COND_VAR -> dwCondMagic != FT_COND_MAGIC // (not initialized) || !pFTUSER_MUTEX // (invalid ptr) || pFTUSER_MUTEX-> dwMutexMagic != FT_MUTEX_MAGIC // (not initialized) || !(pFT_MUTEX = pFTUSER_MUTEX->hMutex) // (invalid ptr) // || !pFT_MUTEX // (invalid ptr) || pFT_MUTEX -> dwMutexMagic != FT_MUTEX_MAGIC // (not initialized) ) return RC(EINVAL); if (0 || pFT_MUTEX -> dwLockOwner != GetCurrentThreadId() // (mutex not owned) || pFT_MUTEX -> nLockedCount <= 0 // (mutex not locked) ) return RC(EPERM); // First, acquire the fthreads condition variable lock... for (;;) { MyEnterCriticalSection ( &pFT_COND_VAR->CondVarLock ); // It is always safe to proceed if the prior signal was completely // processed (received by everyone who was supposed to receive it) if ( IsEventSet ( pFT_COND_VAR->hSigRecvdEvent ) ) break; // Prior signal not completely received yet... Verify that it is // still being transmitted... ASSERT ( IsEventSet ( pFT_COND_VAR->hSigXmitEvent ) ); // If no one is currently waiting to receive [this signal not yet // completely received and still being transmitted], then we can // go ahead and receive it right now *regardless* of what type of // signal it is ("signal" or "broadcast") since we're *obviously* // the one who is supposed to receive it (since we ARE trying to // wait on it after all and it IS being transmitted. The 'xmit' // event is *always* turned off once everyone [who is *supposed* // to receive the signal] *has* received the signal. Thus, since // it's still being transmitted, that means *not* everyone who // *should* receive it *has* received it yet, and thus we can be // absolutely certain that we indeed *should* therefore receive it // since we *are* after all waiting for it). // Otherwise (prior signal not completely processed AND there are // still others waiting to receive it too (as well as us)), then if // it's a "broadcast" type signal, we can go ahead and receive that // type of signal too as well (along with the others); we just came // to the party a little bit late (but nevertheless in the nick of // time!), that's all... if ( !pFT_COND_VAR->nNumWaiting || pFT_COND_VAR->bBroadcastSig ) break; // Otherwise it's a "signal" type signal (and not a broadcast type) // that hasn't been completely received yet, meaning only ONE thread // should be released. Thus, since there's already a thread (or more // than one thread) already waiting/trying to receive it, we need to // let [one of] THEM receive it and NOT US. Thus we go back to sleep // and wait for the signal processing currently in progress to finish // releasing the proper number of threads first. Only once that has // happened can we then be allowed to try and catch whatever signal // happens to come along next... MyLeaveCriticalSection ( &pFT_COND_VAR->CondVarLock ); // (Programming Note: technically we should really be checking our // return code from the below wait call too) MyWaitForSingleObject ( pFT_COND_VAR->hSigRecvdEvent, INFINITE ); } // Register the caller's wait request while we still have control // over this condition variable... pFT_COND_VAR->nNumWaiting++; // (register wait request) // Now release the original mutex and thus any potential signalers... // (but note that no signal can actually ever be sent per se until // the condition variable which we currently have locked is first // released, which gets done in the WaitForTransmission function). if ( ( rc = fthread_mutex_unlock ( #ifdef FISH_HANG pszFile, nLine, #endif pFTUSER_MUTEX ) ) != 0 ) { // Oops! Something went wrong. We couldn't release the original // caller's original mutex. Since we've already registered their // wait and already have the condition variable locked, we need // to first de-register their wait and release the condition var- // iable lock before returning our error (i.e. we essentially // need to back out what we previously did just above). #ifdef FISH_HANG logmsg("fthreads: BeginWait: fthread_mutex_unlock failed at %s(%d)! rc=%d\n" ,pszFile ,nLine ,rc ); #else logmsg("fthreads: BeginWait: fthread_mutex_unlock failed! rc=%d\n" ,rc ); #endif pFT_COND_VAR->nNumWaiting--; // (de-register wait request) MyLeaveCriticalSection ( &pFT_COND_VAR->CondVarLock ); return RC(rc); } // Our "begin-to-wait-on-condition-variable" task has been successfully // completed. We have essentially atomically released the originally mutex // and "begun our wait" on it (by registering the fact that there's someone // wanting to wait on it). Return to OUR caller with the condition variable // still locked (so no signals can be sent nor any threads released until // our caller calls the below WaitForTransmission function)... return RC(0); // (success) } //////////////////////////////////////////////////////////////////////////////////// // Wait for the condition variable in question to receive a transmission... static int WaitForTransmission ( #ifdef FISH_HANG const char* pszFile, const int nLine, #endif FT_COND_VAR* pFT_COND_VAR, struct timespec* pTimeTimeout // (NULL == INFINITE wait) ) { DWORD dwWaitRetCode, dwWaitMilliSecs; // If the signal has already arrived (i.e. is still being transmitted) // then there's no need to wait for it. Simply return success with the // condition variable still locked... if ( IsEventSet ( pFT_COND_VAR->hSigXmitEvent ) ) { // There's no need to wait for the signal (transmission) // to arrive because it's already been sent! Just return. return 0; // (transmission received!) } // Our loop to wait for our transmission to arrive... do { // Release condition var lock (so signal (transmission) can // be sent) and then wait for the signal (transmission)... MyLeaveCriticalSection ( &pFT_COND_VAR->CondVarLock ); // Need to calculate a timeout value if this is a // timed condition wait as opposed to a normal wait... // Note that we unfortunately need to do this on each iteration // because Window's wait API requires a relative timeout value // rather than an absolute TOD timeout value like pthreads... if ( !pTimeTimeout ) { dwWaitMilliSecs = INFINITE; } else { struct timeval TimeNow; gettimeofday ( &TimeNow, NULL ); if (TimeNow.tv_sec > pTimeTimeout->tv_sec || ( TimeNow.tv_sec == pTimeTimeout->tv_sec && (TimeNow.tv_usec * 1000) > pTimeTimeout->tv_nsec ) ) { dwWaitMilliSecs = 0; } else { dwWaitMilliSecs = ((pTimeTimeout->tv_sec - TimeNow.tv_sec) * 1000) + ((pTimeTimeout->tv_nsec - (TimeNow.tv_usec * 1000)) / 1000000); } } // Finally we get to do the actual wait... dwWaitRetCode = MyWaitForSingleObject ( pFT_COND_VAR->hSigXmitEvent, dwWaitMilliSecs ); // A signal (transmission) has been sent; reacquire our condition var lock // and receive the transmission (if it's still being transmitted that is)... MyEnterCriticalSection ( &pFT_COND_VAR->CondVarLock ); // The "WAIT_OBJECT_0 == dwWaitRetCode && ..." clause in the below 'while' // statement ensures that we will always break out of our wait loop whenever // either a timeout occurs or our actual MyWaitForSingleObject call fails // for any reason. As long as dwWaitRetCode is WAIT_OBJECT_0 though *AND* // our event has still not been signaled yet, then we'll continue looping // to wait for a signal (transmission) that we're supposed to receive... // Also note that one might at first think/ask: "Gee, Fish, why do we need // to check to see if the condition variable's "hSigXmitEvent" event has // been set each time (via the 'IsEventSet' macro)? Shouldn't it *always* // be set if the above MyWaitForSingleObject call returns??" The answer is // of course no, it might NOT [still] be signaled. This is because whenever // someone *does* happen to signal it, we will of course be released from // our wait (the above MyWaitForSingleObject call) BUT... someone else who // was also waiting for it may have managed to grab our condition variable // lock before we could and they could have reset it. Thus we need to check // it again each time. } while ( WAIT_OBJECT_0 == dwWaitRetCode && !IsEventSet( pFT_COND_VAR->hSigXmitEvent ) ); // Our signal (transmission) has either [finally] arrived or else we got // tired of waiting for it (i.e. we timed out) or else there was an error... if ( WAIT_OBJECT_0 == dwWaitRetCode ) return RC(0); if ( WAIT_TIMEOUT == dwWaitRetCode ) return RC(ETIMEDOUT); // Our wait failed! Something is VERY wrong! Maybe the condition variable // was prematurely destroyed by someone? In any case there's not // much we can do about it other than log the fact that it occurred and // return the error back to the caller. Their wait request has, believe // it or not, actually been completed (although not as they expected it // would in all likelihood!)... #ifdef FISH_HANG logmsg ( "fthreads: WaitForTransmission: MyWaitForSingleObject failed at %s(%d)! dwWaitRetCode=%d (0x%8.8X)\n" ,pszFile ,nLine ,dwWaitRetCode ,dwWaitRetCode ); #else logmsg ( "fthreads: WaitForTransmission: MyWaitForSingleObject failed! dwWaitRetCode=%d (0x%8.8X)\n" ,dwWaitRetCode ,dwWaitRetCode ); #endif return RC(EFAULT); } //////////////////////////////////////////////////////////////////////////////////// // Send a "signal" or "broadcast" to a condition variable... static int QueueTransmission ( #ifdef FISH_HANG const char* pszFile, const int nLine, #endif FT_COND_VAR* pFT_COND_VAR, BOOL bXmitType ) { if (0 || !pFT_COND_VAR // (invalid ptr) || pFT_COND_VAR->dwCondMagic != FT_COND_MAGIC // (not initialized) ) { return RC(EINVAL); // (invalid parameters were passed) } // Wait for the condition variable to become free so we can begin transmitting // our signal... If the condition variable is still "busy" (in use), then that // means threads are still in the process of being released as a result of some // prior signal (transmission). Thus we must wait until that work is completed // first before we can send our new signal (transmission)... for (;;) { MyEnterCriticalSection ( &pFT_COND_VAR->CondVarLock ); if ( IsEventSet ( pFT_COND_VAR->hSigRecvdEvent ) ) break; MyLeaveCriticalSection ( &pFT_COND_VAR->CondVarLock ); MyWaitForSingleObject ( pFT_COND_VAR->hSigRecvdEvent, INFINITE ); } // Turn on our transmitter... (i.e. start transmitting our "signal" to // all threads who might be waiting to receive it (if there are any)... // If no one has registered their interest in receiving any transmissions // associated with this particular condition variable, then they are unfor- // tunately a little too late in doing so because we're ready to start our // transmission right now! If there's no one to receive our transmission, // then it simply gets lost (i.e. a "missed signal" situation has essenti- // ally occurred), but then that's not our concern here; our only concern // here is to transmit the signal (transmission) and nothing more. Tough // beans if there's no one listening to receive it... if ( pFT_COND_VAR->nNumWaiting ) // (anyone interested?) { pFT_COND_VAR->bBroadcastSig = bXmitType; // (yep! set xmit type) MySetEvent ( pFT_COND_VAR->hSigXmitEvent ); // (turn on transmitter) MyResetEvent ( pFT_COND_VAR->hSigRecvdEvent ); // (serialize reception) } MyLeaveCriticalSection ( &pFT_COND_VAR->CondVarLock ); return RC(0); } //////////////////////////////////////////////////////////////////////////////////// // A thread has been released as a result of someone's signal or broadcast... static void ReceiveXmission ( #ifdef FISH_HANG const char* pszFile, const int nLine, #endif FT_COND_VAR* pFT_COND_VAR ) { // If we were the only ones supposed to receive the transmission, (or // if no one remains to receive any transmissions), then turn off the // transmitter (i.e. stop sending the signal) and indicate that it has // been completely received all interested parties (i.e. by everyone // who was supposed to receive it)... pFT_COND_VAR->nNumWaiting--; // (de-register wait since transmission // has been successfully received now) // Determine whether any more waiters (threads) should also receive // this transmission (i.e. also be released) or whether we should // reset (turn off) our transmitter so as to not release any other // thread(s) besides ourselves... if (0 || !pFT_COND_VAR->bBroadcastSig // ("signal" == only us) || pFT_COND_VAR->nNumWaiting <= 0 // (no one else == only us) ) { MyResetEvent ( pFT_COND_VAR->hSigXmitEvent ); // (turn off transmitter) MySetEvent ( pFT_COND_VAR->hSigRecvdEvent ); // (transmission complete) } } //////////////////////////////////////////////////////////////////////////////////// // The following function is called just before returning back to the caller. It // first releases the condition variable lock (since we're now done with it) and // then reacquires the caller's original mutex before returning [back to the caller]. // We MUST do things in that order! 1) release our condition variable lock, and THEN // 2) try to reacquire the caller's original mutex. Otherwise a deadlock could occur! // If we still had the condition variable locked before trying to acquire the caller's // original mutex, we could easily become blocked if some other thread still already // owned (had locked) the caller's mutex. We would then be unable to ever release our // condition variable lock until whoever had the mutex locked first released it, but // they would never be able to release it because we still had the condition variable // still locked! Recall that upon entry to a wait call (see previous BeginWait function) // we acquire the condition variable lock *first* (in order to register the caller's // wait) before releasing their mutex. Thus, we MUST therefore release our condition // variable lock FIRST and THEN try reacquiring their original mutex before returning. static int ReturnFromWait ( #ifdef FISH_HANG const char* pszFile, const int nLine, #endif FT_COND_VAR* pFT_COND_VAR, fthread_mutex_t* pFTUSER_MUTEX, int nRetCode ) { int rc; FT_MUTEX* pFT_MUTEX; if (0 || !pFT_COND_VAR // (invalid ptr) || pFT_COND_VAR -> dwCondMagic != FT_COND_MAGIC // (not initialized) || !pFTUSER_MUTEX // (invalid ptr) || pFTUSER_MUTEX-> dwMutexMagic != FT_MUTEX_MAGIC // (not initialized) || !(pFT_MUTEX = pFTUSER_MUTEX->hMutex) // (invalid ptr) // || !pFT_MUTEX // (invalid ptr) || pFT_MUTEX -> dwMutexMagic != FT_MUTEX_MAGIC // (not initialized) ) return RC(EINVAL); // (let other threads access this condition variable now...) MyLeaveCriticalSection ( &pFT_COND_VAR->CondVarLock ); // (reacquire original mutex before returning back to the original caller...) if ( ( rc = fthread_mutex_lock ( #ifdef FISH_HANG pszFile, nLine, #endif pFTUSER_MUTEX ) ) != 0 ) { // Oops! We were unable to reacquire the caller's original mutex! This // is actually a catastrophic type of error! The caller expects their // mutex to still be owned (locked) by themselves upon return, but we // were unable to reacquire it for them! Unfortunately there's nothing // we can do about this; the system is essentially hosed at this point. // Just log the fact that something went wrong and return. #ifdef FISH_HANG logmsg("fthreads: ReturnFromWait: fthread_mutex_lock failed at %s(%d)! rc=%d\n" ,pszFile ,nLine ,rc ); #else logmsg("fthreads: ReturnFromWait: fthread_mutex_lock failed! rc=%d\n" ,rc ); #endif return RC(rc); // (what went wrong) } // Return to caller with the requested return code. (The caller passes to us // the return code they wish to pass back to the original caller, so we just // return that same return code back to OUR caller (so they can then pass it // back to the original fthreads caller)). return RC(nRetCode); // (as requested) } //////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////// // Threading functions... LIST_ENTRY ThreadListHead; // head list entry of list of joinable threads CRITICAL_SECTION ThreadListLock; // lock for accessing list of joinable threads #define LockThreadsList() EnterCriticalSection ( &ThreadListLock ) #define UnlockThreadsList() LeaveCriticalSection ( &ThreadListLock ) //////////////////////////////////////////////////////////////////////////////////// // internal joinable thread information typedef struct _tagFTHREAD { LIST_ENTRY ThreadListLink; // (links entries together in a chain) DWORD dwThreadID; // (thread-id) HANDLE hThreadHandle; // (Win32 thread handle) BOOL bJoinable; // (whether thread is joinable or detached) int nJoinedCount; // (#of threads that did join on this one) void* ExitVal; // (saved thread exit value) jmp_buf JumpBuf; // (jump buffer for fthread_exit) } FTHREAD, *PFTHREAD; //////////////////////////////////////////////////////////////////////////////////// // (Note: returns with thread list lock still held if found; not held if not found) static FTHREAD* FindFTHREAD ( DWORD dwThreadID ) { FTHREAD* pFTHREAD; LIST_ENTRY* pListEntry; LockThreadsList(); // (acquire thread list lock) pListEntry = ThreadListHead.Flink; while ( pListEntry != &ThreadListHead ) { pFTHREAD = CONTAINING_RECORD ( pListEntry, FTHREAD, ThreadListLink ); pListEntry = pListEntry->Flink; if ( pFTHREAD->dwThreadID != dwThreadID ) continue; return pFTHREAD; // (return with thread list lock still held) } UnlockThreadsList(); // (release thread list lock) return NULL; // (not found) } //////////////////////////////////////////////////////////////////////////////////// typedef struct _ftCallThreadParms { PFT_THREAD_FUNC pfnTheirThreadFunc; void* pvTheirThreadArgs; char* pszTheirThreadName; FTHREAD* pFTHREAD; } FT_CALL_THREAD_PARMS; //---------------------------------------------------------------------------------- static DWORD __stdcall FTWin32ThreadFunc ( void* pMyArgs ) { FT_CALL_THREAD_PARMS* pCallTheirThreadParms; PFT_THREAD_FUNC pfnTheirThreadFunc; void* pvTheirThreadArgs; FTHREAD* pFTHREAD; pCallTheirThreadParms = (FT_CALL_THREAD_PARMS*) pMyArgs; pfnTheirThreadFunc = pCallTheirThreadParms->pfnTheirThreadFunc; pvTheirThreadArgs = pCallTheirThreadParms->pvTheirThreadArgs; pFTHREAD = pCallTheirThreadParms->pFTHREAD; // PROGRAMMING NOTE: -1 == "current calling thread" SET_THREAD_NAME_ID ( -1, pCallTheirThreadParms->pszTheirThreadName ); free ( pCallTheirThreadParms ); if ( setjmp ( pFTHREAD->JumpBuf ) == 0 ) pFTHREAD->ExitVal = pfnTheirThreadFunc ( pvTheirThreadArgs ); LockThreadsList(); if ( !pFTHREAD->bJoinable ) { // If we are not a joinable thread, we must free our // own resources ourselves, but ONLY IF the 'joined' // count is zero. If the 'joined' count is NOT zero, // then, however it occurred, there is still someone // waiting in the join function for us to exit, and // thus, we cannot free our resources at this time // (since the thread that did the join and which is // waiting for us to exit still needs access to our // resources). In such a situation the actual freeing // of resources is deferred and will be done by the // join function itself whenever it's done with them. if ( pFTHREAD->nJoinedCount <= 0 ) { CloseHandle ( pFTHREAD->hThreadHandle ); RemoveListEntry ( &pFTHREAD->ThreadListLink ); free ( pFTHREAD ); } } UnlockThreadsList(); MyExitThread ( 0 ); return 0; // (make compiler happy) } //////////////////////////////////////////////////////////////////////////////////// // Create a new thread... DLL_EXPORT int fthread_create ( #ifdef FISH_HANG const char* pszFile, const int nLine, #endif fthread_t* pdwThreadID, fthread_attr_t* pThreadAttr, PFT_THREAD_FUNC pfnThreadFunc, void* pvThreadArgs, char* pszThreadName ) { static BOOL bDidInit = FALSE; FT_CALL_THREAD_PARMS* pCallTheirThreadParms; size_t nStackSize; int nDetachState; FTHREAD* pFTHREAD; HANDLE hThread; DWORD dwThreadID; if ( !bDidInit ) { bDidInit = TRUE; InitializeListHead ( &ThreadListHead ); InitializeCriticalSection ( &ThreadListLock ); } if (0 || !pdwThreadID || !pfnThreadFunc ) return RC(EINVAL); if ( pThreadAttr ) { if ( pThreadAttr->dwAttrMagic != FT_ATTR_MAGIC || ( pThreadAttr->nDetachState != FTHREAD_CREATE_DETACHED && pThreadAttr->nDetachState != FTHREAD_CREATE_JOINABLE ) ) return RC(EINVAL); nStackSize = pThreadAttr->nStackSize; nDetachState = pThreadAttr->nDetachState; } else { nStackSize = 0; nDetachState = FTHREAD_CREATE_DEFAULT; } pCallTheirThreadParms = (FT_CALL_THREAD_PARMS*) malloc ( sizeof ( FT_CALL_THREAD_PARMS ) ); if ( !pCallTheirThreadParms ) { #ifdef FISH_HANG logmsg("fthread_create: malloc(FT_CALL_THREAD_PARMS) failed; %s(%d)\n",pszFile,nLine); #else logmsg("fthread_create: malloc(FT_CALL_THREAD_PARMS) failed\n"); #endif return RC(ENOMEM); // (out of memory) } pFTHREAD = (FTHREAD*) malloc ( sizeof( FTHREAD ) ); if ( !pFTHREAD ) { #ifdef FISH_HANG logmsg("fthread_create: malloc(FTHREAD) failed; %s(%d)\n",pszFile,nLine); #else logmsg("fthread_create: malloc(FTHREAD) failed\n"); #endif free ( pCallTheirThreadParms ); return RC(ENOMEM); // (out of memory) } pCallTheirThreadParms->pfnTheirThreadFunc = pfnThreadFunc; pCallTheirThreadParms->pvTheirThreadArgs = pvThreadArgs; pCallTheirThreadParms->pszTheirThreadName = pszThreadName; pCallTheirThreadParms->pFTHREAD = pFTHREAD; InitializeListLink(&pFTHREAD->ThreadListLink); pFTHREAD->dwThreadID = 0; pFTHREAD->hThreadHandle = NULL; pFTHREAD->bJoinable = ((FTHREAD_CREATE_JOINABLE == nDetachState) ? (TRUE) : (FALSE)); pFTHREAD->nJoinedCount = 0; pFTHREAD->ExitVal = NULL; LockThreadsList(); hThread = MyCreateThread ( NULL, nStackSize, FTWin32ThreadFunc, pCallTheirThreadParms, 0, &dwThreadID ); if ( !hThread ) { UnlockThreadsList(); #ifdef FISH_HANG logmsg("fthread_create: MyCreateThread failed; %s(%d)\n",pszFile,nLine); #else logmsg("fthread_create: MyCreateThread failed\n"); #endif free ( pCallTheirThreadParms ); free ( pFTHREAD ); return RC(EAGAIN); // (unable to obtain required resources) } pFTHREAD->hThreadHandle = hThread; pFTHREAD->dwThreadID = dwThreadID; *pdwThreadID = dwThreadID; InsertListHead ( &ThreadListHead, &pFTHREAD->ThreadListLink ); UnlockThreadsList(); return RC(0); } //////////////////////////////////////////////////////////////////////////////////// // Exit from a thread... DLL_EXPORT void fthread_exit ( void* ExitVal ) { FTHREAD* pFTHREAD; VERIFY ( pFTHREAD = FindFTHREAD ( GetCurrentThreadId() ) ); pFTHREAD->ExitVal = ExitVal; UnlockThreadsList(); longjmp ( pFTHREAD->JumpBuf, 1 ); } //////////////////////////////////////////////////////////////////////////////////// // Join a thread (i.e. wait for a thread's termination)... DLL_EXPORT int fthread_join ( #ifdef FISH_HANG const char* pszFile, const int nLine, #endif fthread_t dwThreadID, void** pExitVal ) { HANDLE hThread; FTHREAD* pFTHREAD; if ( GetCurrentThreadId() == dwThreadID ) return RC(EDEADLK); // (can't join self!) if ( !(pFTHREAD = FindFTHREAD ( dwThreadID ) ) ) return RC(ESRCH); // (thread not found) // (Note: threads list lock still held at this point // since thread was found...) if ( !pFTHREAD->bJoinable ) { UnlockThreadsList(); return RC(EINVAL); // (not a joinable thread) } ASSERT ( pFTHREAD->nJoinedCount >= 0 ); pFTHREAD->nJoinedCount++; hThread = pFTHREAD->hThreadHandle; UnlockThreadsList(); // FishHang doesn't support waiting on thread objects, // only event objects. Thus we do a normal Win32 call here... WaitForSingleObject ( hThread, INFINITE ); // (wait for thread exit) LockThreadsList(); if ( pExitVal ) *pExitVal = pFTHREAD->ExitVal; // (pass back thread's exit value) ASSERT ( pFTHREAD->nJoinedCount > 0 ); pFTHREAD->nJoinedCount--; // If this is the last thread to be resumed after having been suspended // (as a result of doing the join), then we need to do the detach (i.e. // to free resources), BUT ONLY IF the detach for the thread in question // has already been done by someone (which can be determined by virtue of // the "joinable" flag having already been changed back to non-joinable). // The idea here is that the 'detach' function purposely does not free // the resources unless the 'joined' count is zero. If the joined count // is NOT zero whenever the detach function is called, then the resources // cannot be freed since there's still a thread waiting to be resumed // from its join (perhaps us!), and it obviously still needs access to // the resources in question. Thus, in such a situation (i.e. there still // being a thread remaining to be woken up from its join when the detach // is done), the freeing of resources normally done by the detach function // is deferred so that WE can do the resource freeing ourselves once we // are done with them. if ( !pFTHREAD->bJoinable && pFTHREAD->nJoinedCount <= 0 ) { CloseHandle ( pFTHREAD->hThreadHandle ); RemoveListEntry ( &pFTHREAD->ThreadListLink ); free ( pFTHREAD ); } UnlockThreadsList(); return RC(0); } //////////////////////////////////////////////////////////////////////////////////// // Detach a thread (i.e. ignore a thread's termination)... DLL_EXPORT int fthread_detach ( fthread_t dwThreadID ) { FTHREAD* pFTHREAD; if ( !( pFTHREAD = FindFTHREAD ( dwThreadID ) ) ) return RC(ESRCH); // (thread not found) // (Note: threads list lock still held at this point // since thread was found...) if ( !pFTHREAD->bJoinable ) { UnlockThreadsList(); return RC(EINVAL); // (not a joinable thread) } // If the thread has not yet exited, then IT will free its // own resources itself whenever it eventually does exit by // virtue of our changing it to a non-joinable thread type. pFTHREAD->bJoinable = FALSE; // (indicate detach was done) // Otherwise we need to free its resources ourselves since // it obviously can't (since it has already exited). // Note that we cannot free the resources ourselves even if the // thread has already exited if there are still other threads // waiting to be woken up from their own join (since they will // still need to have access to the resources). In other words, // even if the thread has already exited (and thus it would seem // that our freeing the resources would be the proper thing to // do), we CANNOT do so if the 'join' count is non-zero. // In such a situation (the join count being non-zero indicating // there is still another thread waiting to be resumed from its // own join), we simply defer the actual freeing of resources to // the thread still waiting to be woken up from its join. Whenever // it does eventually wake up from its join, it will free the // resources for us, as long as we remember to reset the 'joinable' // flag back to non-joinable (which we've already done just above). if ( IsEventSet ( pFTHREAD->hThreadHandle ) && pFTHREAD->nJoinedCount <= 0 ) { CloseHandle ( pFTHREAD->hThreadHandle ); RemoveListEntry ( &pFTHREAD->ThreadListLink ); free ( pFTHREAD ); } UnlockThreadsList(); return RC(0); } //////////////////////////////////////////////////////////////////////////////////// // Initialize a "thread attribute"... DLL_EXPORT int fthread_attr_init ( fthread_attr_t* pThreadAttr ) { if ( !pThreadAttr ) return RC(EINVAL); // (invalid ptr) if ( FT_ATTR_MAGIC == pThreadAttr->dwAttrMagic ) return RC(EBUSY); // (already initialized) pThreadAttr->dwAttrMagic = FT_ATTR_MAGIC; pThreadAttr->nDetachState = FTHREAD_CREATE_DEFAULT; pThreadAttr->nStackSize = 0; return RC(0); } //////////////////////////////////////////////////////////////////////////////////// // Destroy a "thread attribute"... DLL_EXPORT int fthread_attr_destroy ( fthread_attr_t* pThreadAttr ) { if ( !pThreadAttr ) return RC(EINVAL); // (invalid ptr) if ( FT_ATTR_MAGIC != pThreadAttr->dwAttrMagic ) return RC(EINVAL); // (not initialized) pThreadAttr->dwAttrMagic = 0; pThreadAttr->nDetachState = 0; pThreadAttr->nStackSize = 0; return RC(0); } //////////////////////////////////////////////////////////////////////////////////// // Set a thread's "detachstate" attribute... DLL_EXPORT int fthread_attr_setdetachstate ( fthread_attr_t* pThreadAttr, int nDetachState ) { if ( !pThreadAttr ) return RC(EINVAL); // (invalid ptr) if ( FT_ATTR_MAGIC != pThreadAttr->dwAttrMagic ) return RC(EINVAL); // (not initialized) if ( FTHREAD_CREATE_DETACHED != nDetachState && FTHREAD_CREATE_JOINABLE != nDetachState ) return RC(EINVAL); // (invalid detach state) pThreadAttr->nDetachState = nDetachState; return RC(0); } //////////////////////////////////////////////////////////////////////////////////// // Retrieve a thread's "detachstate" attribute... DLL_EXPORT int fthread_attr_getdetachstate ( const fthread_attr_t* pThreadAttr, int* pnDetachState ) { if ( !pThreadAttr || !pnDetachState ) return RC(EINVAL); // (invalid ptr) if ( FT_ATTR_MAGIC != pThreadAttr->dwAttrMagic ) return RC(EINVAL); // (not initialized) if ( FTHREAD_CREATE_DETACHED != pThreadAttr->nDetachState && FTHREAD_CREATE_JOINABLE != pThreadAttr->nDetachState ) return RC(EINVAL); // (invalid detach state) *pnDetachState = pThreadAttr->nDetachState; return RC(0); } //////////////////////////////////////////////////////////////////////////////////// // Set a thread's initial stack size... DLL_EXPORT int fthread_attr_setstacksize ( fthread_attr_t* pThreadAttr, size_t nStackSize ) { if ( !pThreadAttr ) return RC(EINVAL); // (invalid ptr) if ( FT_ATTR_MAGIC != pThreadAttr->dwAttrMagic ) return RC(EINVAL); // (not initialized) pThreadAttr->nStackSize = nStackSize; return RC(0); } //////////////////////////////////////////////////////////////////////////////////// // Retrieve a thread's initial stack size... DLL_EXPORT int fthread_attr_getstacksize ( const fthread_attr_t* pThreadAttr, size_t* pnStackSize ) { if ( !pThreadAttr || !pnStackSize ) return RC(EINVAL); // (invalid ptr) if ( FT_ATTR_MAGIC != pThreadAttr->dwAttrMagic ) return RC(EINVAL); // (not initialized) *pnStackSize = pThreadAttr->nStackSize; return RC(0); } //////////////////////////////////////////////////////////////////////////////////// // (thread signalling not [currently] supported (yet); always returns ENOTSUP...) DLL_EXPORT int fthread_kill // FIXME: TODO: ( int dummy1, int dummy2 ) { UNREFERENCED ( dummy1 ); UNREFERENCED ( dummy2 ); return RC(ENOTSUP); } //////////////////////////////////////////////////////////////////////////////////// // Return thread-id... DLL_EXPORT fthread_t fthread_self () { return GetCurrentThreadId(); } //////////////////////////////////////////////////////////////////////////////////// // Compare thread-ids... DLL_EXPORT int fthread_equal ( fthread_t pdwThreadID_1, fthread_t pdwThreadID_2 ) { return ( pdwThreadID_1 == pdwThreadID_2 ); } //////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////// // Initialize a lock... DLL_EXPORT int fthread_mutex_init ( #ifdef FISH_HANG const char* pszFile, const int nLine, #endif fthread_mutex_t* pFTUSER_MUTEX, const fthread_mutexattr_t* pFT_MUTEX_ATTR ) { DWORD dwMutexType = 0; if ( !pFTUSER_MUTEX ) return RC(EINVAL); // (invalid mutex ptr) if ( FT_MUTEX_MAGIC == pFTUSER_MUTEX->dwMutexMagic ) return RC(EBUSY); // (mutex already initialized) if ( pFT_MUTEX_ATTR && !IsValidMutexType ( dwMutexType = *pFT_MUTEX_ATTR ) ) return RC(EINVAL); // (invalid mutex attr ptr or mutex attr type) if ( !(pFTUSER_MUTEX->hMutex = MallocFT_MUTEX()) ) return RC(ENOMEM); // (out of memory) if ( !InitializeFT_MUTEX ( #ifdef FISH_HANG pszFile, nLine, #endif pFTUSER_MUTEX->hMutex, pFT_MUTEX_ATTR ? dwMutexType : FTHREAD_MUTEX_DEFAULT )) { free ( pFTUSER_MUTEX->hMutex ); pFTUSER_MUTEX->dwMutexMagic = 0; pFTUSER_MUTEX->hMutex = NULL; return RC(EAGAIN); // (unable to obtain required resources) } pFTUSER_MUTEX->dwMutexMagic = FT_MUTEX_MAGIC; return RC(0); } //////////////////////////////////////////////////////////////////////////////////// // Destroy a lock... DLL_EXPORT int fthread_mutex_destroy ( #ifdef FISH_HANG const char* pszFile, const int nLine, #endif fthread_mutex_t* pFTUSER_MUTEX ) { if ( !pFTUSER_MUTEX ) return RC(EINVAL); // (invalid ptr) if ( FT_MUTEX_MAGIC != pFTUSER_MUTEX->dwMutexMagic ) return RC(EINVAL); // (not initialized) if ( !UninitializeFT_MUTEX ( #ifdef FISH_HANG pszFile, nLine, #endif pFTUSER_MUTEX->hMutex )) return RC(EBUSY); // (still in use) free ( pFTUSER_MUTEX->hMutex ); pFTUSER_MUTEX->dwMutexMagic = 0; pFTUSER_MUTEX->hMutex = NULL; return RC(0); } //////////////////////////////////////////////////////////////////////////////////// // Try to lock a "mutex"... DLL_EXPORT int fthread_mutex_trylock ( #ifdef FISH_HANG const char* pszFile, const int nLine, #endif fthread_mutex_t* pFTUSER_MUTEX ) { if ( !pFTUSER_MUTEX ) return RC(EINVAL); // (invalid ptr) if ( FT_MUTEX_MAGIC != pFTUSER_MUTEX->dwMutexMagic ) return RC(EINVAL); // (not initialized) // Try to acquire the requested mutex... if ( !TryEnterFT_MUTEX ( #ifdef FISH_HANG pszFile, nLine, #endif pFTUSER_MUTEX->hMutex ) ) // We could not acquire the mutex; return 'busy'... return RC(EBUSY); // We successfully acquired the mutex... If the mutex type is recursive, // or, if not recursive (i.e. error-check), if this was the first/initial // lock on the mutex, then return success... if (0 || FTHREAD_MUTEX_RECURSIVE == ((FT_MUTEX*)pFTUSER_MUTEX->hMutex)->dwMutexType || ((FT_MUTEX*)pFTUSER_MUTEX->hMutex)->nLockedCount <= 1 ) return RC(0); ASSERT ( FTHREAD_MUTEX_ERRORCHECK == ((FT_MUTEX*)pFTUSER_MUTEX->hMutex)->dwMutexType && ((FT_MUTEX*)pFTUSER_MUTEX->hMutex)->nLockedCount > 1 ); // The mutex type is error-check and we already previously had the mutex locked // before (i.e. this was the *second* time we acquired this same mutex). Return // 'busy' after first releasing the mutex once (to decrement the locked count // back down to what it was (i.e. 1 (one))). LeaveFT_MUTEX ( #ifdef FISH_HANG pszFile, nLine, #endif pFTUSER_MUTEX->hMutex ); return RC(EBUSY); } //////////////////////////////////////////////////////////////////////////////////// // Lock a "mutex"... DLL_EXPORT int fthread_mutex_lock ( #ifdef FISH_HANG const char* pszFile, const int nLine, #endif fthread_mutex_t* pFTUSER_MUTEX ) { if ( !pFTUSER_MUTEX ) return RC(EINVAL); // (invalid ptr) if ( FT_MUTEX_MAGIC != pFTUSER_MUTEX->dwMutexMagic ) return RC(EINVAL); // (not initialized) // Try to acquire the requested mutex... if ( !TryEnterFT_MUTEX ( #ifdef FISH_HANG pszFile, nLine, #endif pFTUSER_MUTEX->hMutex ) ) { // We could not acquire the mutex. This means someone already owns the mutex, // so just do a normal acquire on the mutex. Both recursive and error-check // types will block until such time as the mutex is successfully acquired... EnterFT_MUTEX ( #ifdef FISH_HANG pszFile, nLine, #endif pFTUSER_MUTEX->hMutex ); return RC(0); } // We successfully acquired the mutex... If the mutex type is recursive, // or, if not recursive (i.e. error-check), if this was the first/initial // lock on the mutex, then return success... if (0 || FTHREAD_MUTEX_RECURSIVE == ((FT_MUTEX*)pFTUSER_MUTEX->hMutex)->dwMutexType || ((FT_MUTEX*)pFTUSER_MUTEX->hMutex)->nLockedCount <= 1 ) return RC(0); ASSERT ( FTHREAD_MUTEX_ERRORCHECK == ((FT_MUTEX*)pFTUSER_MUTEX->hMutex)->dwMutexType && ((FT_MUTEX*)pFTUSER_MUTEX->hMutex)->nLockedCount > 1 ); // The mutex type is error-check and we already previously had the mutex locked // before (i.e. this was the *second* time we acquired this same mutex). Return // 'deadlock' after first releasing the mutex once (to decrement the locked count // back down to what it was (i.e. 1 (one))). LeaveFT_MUTEX ( #ifdef FISH_HANG pszFile, nLine, #endif pFTUSER_MUTEX->hMutex ); return RC(EDEADLK); } //////////////////////////////////////////////////////////////////////////////////// // Unlock a "mutex"... DLL_EXPORT int fthread_mutex_unlock ( #ifdef FISH_HANG const char* pszFile, const int nLine, #endif fthread_mutex_t* pFTUSER_MUTEX ) { if (0 || !pFTUSER_MUTEX // (invalid ptr) || FT_MUTEX_MAGIC != pFTUSER_MUTEX->dwMutexMagic // (not initialized) ) return RC(EINVAL); if (0 || GetCurrentThreadId() != ((PFT_MUTEX)pFTUSER_MUTEX->hMutex)->dwLockOwner // (not owned) || ((PFT_MUTEX)pFTUSER_MUTEX->hMutex)->nLockedCount <= 0 // (not locked) ) return RC(EPERM); ASSERT ( ((FT_MUTEX*)pFTUSER_MUTEX->hMutex)->nLockedCount <= 1 || FTHREAD_MUTEX_RECURSIVE == ((FT_MUTEX*)pFTUSER_MUTEX->hMutex)->dwMutexType ); LeaveFT_MUTEX ( #ifdef FISH_HANG pszFile, nLine, #endif pFTUSER_MUTEX->hMutex ); return RC(0); } //////////////////////////////////////////////////////////////////////////////////// // Initialize a "condition"... DLL_EXPORT int fthread_cond_init ( #ifdef FISH_HANG const char* pszFile, const int nLine, #endif fthread_cond_t* pFT_COND_VAR ) { if ( !pFT_COND_VAR ) return RC(EINVAL); // (invalid ptr) if ( FT_COND_MAGIC == pFT_COND_VAR->dwCondMagic ) return RC(EBUSY); // (already initialized) if ( !(pFT_COND_VAR->hCondVar = MallocFT_COND_VAR()) ) return RC(ENOMEM); // (out of memory) if ( !InitializeFT_COND_VAR ( #ifdef FISH_HANG pszFile, nLine, #endif pFT_COND_VAR->hCondVar )) { free ( pFT_COND_VAR->hCondVar ); pFT_COND_VAR->dwCondMagic = 0; pFT_COND_VAR->hCondVar = NULL; return RC(EAGAIN); // (unable to obtain required resources) } pFT_COND_VAR->dwCondMagic = FT_COND_MAGIC; return RC(0); } //////////////////////////////////////////////////////////////////////////////////// // Destroy a "condition"... DLL_EXPORT int fthread_cond_destroy ( #ifdef FISH_HANG const char* pszFile, const int nLine, #endif fthread_cond_t* pFT_COND_VAR ) { if ( !pFT_COND_VAR ) return RC(EINVAL); // (invalid ptr) if ( FT_COND_MAGIC != pFT_COND_VAR->dwCondMagic ) return RC(EINVAL); // (not initialized) if ( !UninitializeFT_COND_VAR ( #ifdef FISH_HANG pszFile, nLine, #endif pFT_COND_VAR->hCondVar )) return RC(EBUSY); // (still in use) free ( pFT_COND_VAR->hCondVar ); pFT_COND_VAR->dwCondMagic = 0; pFT_COND_VAR->hCondVar = NULL; return RC(0); } //////////////////////////////////////////////////////////////////////////////////// // 'Signal' a "condition"... (causes ONE waiting thread to be released) DLL_EXPORT int fthread_cond_signal ( #ifdef FISH_HANG const char* pszFile, const int nLine, #endif fthread_cond_t* pFT_COND_VAR ) { if ( !pFT_COND_VAR ) return RC(EINVAL); // (invalid ptr) if ( FT_COND_MAGIC != pFT_COND_VAR->dwCondMagic ) return RC(EINVAL); // (not initialized) return QueueTransmission ( #ifdef FISH_HANG pszFile, nLine, #endif pFT_COND_VAR->hCondVar, FALSE // (FALSE == not "broadcast") ); } //////////////////////////////////////////////////////////////////////////////////// // 'Broadcast' a "condition"... (causes ALL waiting threads to be released) DLL_EXPORT int fthread_cond_broadcast ( #ifdef FISH_HANG const char* pszFile, const int nLine, #endif fthread_cond_t* pFT_COND_VAR ) { if ( !pFT_COND_VAR ) return RC(EINVAL); // (invalid ptr) if ( FT_COND_MAGIC != pFT_COND_VAR->dwCondMagic ) return RC(EINVAL); // (not initialized) return QueueTransmission ( #ifdef FISH_HANG pszFile, nLine, #endif pFT_COND_VAR->hCondVar, TRUE // (TRUE == "broadcast" type) ); } //////////////////////////////////////////////////////////////////////////////////// // Wait for a "condition" to occur... DLL_EXPORT int fthread_cond_wait ( #ifdef FISH_HANG const char* pszFile, const int nLine, #endif fthread_cond_t* pFT_COND_VAR, fthread_mutex_t* pFTUSER_MUTEX ) { int rc; if (0 || !pFT_COND_VAR // (invalid ptr) || FT_COND_MAGIC != pFT_COND_VAR -> dwCondMagic // (not initialized) || !pFTUSER_MUTEX // (invalid ptr) || FT_MUTEX_MAGIC != pFTUSER_MUTEX -> dwMutexMagic // (not initialized) ) return RC(EINVAL); // The following call essentially atomically releases the caller's mutex // and does a wait. Of course, it doesn't really do the wait though; that's // actually done further below. BUT, it does atomically register the fact // that this thread *wishes* to do a wait by acquiring the condition variable // lock and then incrementing the #of waiters counter before it releases the // original mutex. Thus, whenever the below function call returns back to us, // we can be assured that: 1) our request to wait on this condition variable // has been registered AND 2) we have control of the condition variable in // question (i.e. we still hold the condition variable lock thus preventing // anyone from trying to send a signal just yet)... if ( ( rc = BeginWait ( #ifdef FISH_HANG pszFile, nLine, #endif pFT_COND_VAR -> hCondVar, pFTUSER_MUTEX ) ) != 0 ) { // OOPS! Something went wrong. The original mutex has NOT been released // and we did NOT acquire our condition variable lock (and thus our wait // was not registered). Thus we can safely return back to the caller with // the original mutex still owned (held) by the caller. return RC(rc); // (return error code to caller; their wait failed) } // We only reach here if the condition var was successfully acquired AND our // wait was registered AND the original mutex was released so the signal can // be sent (but the signal (transmission) of course cannot ever be sent until // we first release our lock on our condition variable, which is of course is // what the below WaitForTransmission function call does within its wait loop)... rc = WaitForTransmission // (wait for "signal" or "broadcast"...) ( #ifdef FISH_HANG pszFile, nLine, #endif pFT_COND_VAR->hCondVar, NULL ); // A signal (transmission) was sent and we're one of the ones (or the // only one) that's supposed to receive it... // If we're the only one that's supposed to receive this transmission, // then we need to turn off the transmitter (stop "sending" the signal) // so that no other threads get "woken up" (released) as a result of // this particular "signal" (transmission)... // (Note that the below call also de-registers our wait too) ReceiveXmission // (reset transmitter) ( #ifdef FISH_HANG pszFile, nLine, #endif pFT_COND_VAR->hCondVar ); // Release the condition var lock (since we're done with it) and then // reacquire the caller's original mutex (if possible) and then return // back to the original caller with their original mutex held with what- // ever return code got set by the above wait call... return ReturnFromWait ( #ifdef FISH_HANG pszFile, nLine, #endif pFT_COND_VAR -> hCondVar, pFTUSER_MUTEX, rc ); } //////////////////////////////////////////////////////////////////////////////////// // Wait (but not forever) for a "condition" to occur... // Refer to the comments in the above 'fthread_cond_wait' function (as well as all // of our other internal functions too of course (BeginWait, WaitForTransmission, // ReceiveXmission and ReturnFromWait)) for details regarding what's going on here // (i.e. what we're doing below and why). The below function is essentially identical // to the above 'fthread_cond_wait' function except that we don't wait forever; we // only wait for a limited amount of time. Other than that they're exactly identical // so there's no sense in repeating myself here... DLL_EXPORT int fthread_cond_timedwait ( #ifdef FISH_HANG const char* pszFile, const int nLine, #endif fthread_cond_t* pFT_COND_VAR, fthread_mutex_t* pFTUSER_MUTEX, struct timespec* pTimeTimeout ) { int rc; if (0 || !pFT_COND_VAR || FT_COND_MAGIC != pFT_COND_VAR -> dwCondMagic || !pFTUSER_MUTEX || FT_MUTEX_MAGIC != pFTUSER_MUTEX -> dwMutexMagic || !pTimeTimeout ) return RC(EINVAL); if ( ( rc = BeginWait ( #ifdef FISH_HANG pszFile, nLine, #endif pFT_COND_VAR -> hCondVar, pFTUSER_MUTEX ) ) != 0 ) return rc; rc = WaitForTransmission ( #ifdef FISH_HANG pszFile, nLine, #endif pFT_COND_VAR->hCondVar, pTimeTimeout ); ReceiveXmission ( #ifdef FISH_HANG pszFile, nLine, #endif pFT_COND_VAR->hCondVar ); return ReturnFromWait ( #ifdef FISH_HANG pszFile, nLine, #endif pFT_COND_VAR -> hCondVar, pFTUSER_MUTEX, rc ); } //////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////// // Initialize a "mutex" attribute... DLL_EXPORT int fthread_mutexattr_init ( fthread_mutexattr_t* pFT_MUTEX_ATTR ) { if ( !pFT_MUTEX_ATTR ) return RC(EINVAL); *pFT_MUTEX_ATTR = FTHREAD_MUTEX_DEFAULT; return RC(0); } //////////////////////////////////////////////////////////////////////////////////// // Destroy a "mutex" attribute... DLL_EXPORT int fthread_mutexattr_destroy ( fthread_mutexattr_t* pFT_MUTEX_ATTR ) { if ( !pFT_MUTEX_ATTR ) return RC(EINVAL); *pFT_MUTEX_ATTR = 0xCDCDCDCD; return RC(0); } //////////////////////////////////////////////////////////////////////////////////// // Retrieve "mutex" attribute type... DLL_EXPORT int fthread_mutexattr_gettype ( const fthread_mutexattr_t* pFT_MUTEX_ATTR, int* pnMutexType ) { DWORD dwMutexType; if ( !pFT_MUTEX_ATTR || !pnMutexType || !IsValidMutexType ( dwMutexType = *pFT_MUTEX_ATTR ) ) return RC(EINVAL); *pnMutexType = (int) dwMutexType; return RC(0); } //////////////////////////////////////////////////////////////////////////////////// // Set "mutex" attribute type... DLL_EXPORT int fthread_mutexattr_settype ( fthread_mutexattr_t* pFT_MUTEX_ATTR, int nMutexType ) { if ( !pFT_MUTEX_ATTR || !IsValidMutexType ( (DWORD) nMutexType ) ) return RC(EINVAL); *pFT_MUTEX_ATTR = (DWORD) nMutexType; return RC(0); } //////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////// #endif // !defined(OPTION_FTHREADS) hercules-3.07/fthreads.h000644 000765 000765 00000033410 11143760543 016721 0ustar00jmaynardjmaynard000000 000000 //////////////////////////////////////////////////////////////////////////////////// // fthreads.h Fish's WIN32 version of pthreads //////////////////////////////////////////////////////////////////////////////////// // (c) Copyright "Fish" (David B. Trout), 2001-2009. Released under the Q Public License // (http://www.hercules-390.org/herclic.html) as modifications to Hercules. //////////////////////////////////////////////////////////////////////////////////// // $Id: fthreads.h 5125 2009-01-23 12:01:44Z bernard $ // // $Log$ // Revision 1.24 2008/03/25 11:41:31 fish // SCSI TAPE MODS part 1: groundwork: non-functional changes: // rename some functions, comments, general restructuring, etc. // New source modules awstape.c, omatape.c, hettape.c and // tapeccws.c added, but not yet used (all will be used in a future // commit though when tapedev.c code is eventually split) // // Revision 1.23 2007/11/30 14:54:32 jmaynard // Changed conmicro.cx to hercules-390.org or conmicro.com, as needed. // // Revision 1.22 2007/06/23 00:04:10 ivan // Update copyright notices to include current year (2007) // // Revision 1.21 2007/01/10 09:29:45 fish // Fix thread naming that was inadvertently broken by my 12/28 fishhang change that introduced use of _beginthreadex // // Revision 1.20 2006/12/08 09:43:21 jj // Add CVS message log // #ifndef _FTHREADS_H_ #define _FTHREADS_H_ #include "hercules.h" #include "fishhang.h" #ifndef _FTHREADS_C_ #ifndef _HUTIL_DLL_ #define FT_DLL_IMPORT DLL_IMPORT #else /* _HUTIL_DLL_ */ #define FT_DLL_IMPORT extern #endif /* _HUTIL_DLL_ */ #else #define FT_DLL_IMPORT DLL_EXPORT #endif //////////////////////////////////////////////////////////////////////////////////// // Just a handy macro to have around... #define RC(rc) (errno = rc) //////////////////////////////////////////////////////////////////////////////////// // (need struct timespec for fthread_cond_timedwait) #if !defined(TIMESPEC_IN_SYS_TYPES_H) && !defined(TIMESPEC_IN_TIME_H) // (need to define it ourselves) struct timespec { time_t tv_sec; // (seconds) long tv_nsec; // (nanoseconds) }; #endif //////////////////////////////////////////////////////////////////////////////////// // fthread typedefs... typedef void* FT_W32_HANDLE; // HANDLE typedef unsigned long FT_W32_DWORD; // DWORD typedef FT_W32_DWORD fthread_t; // thread id typedef FT_W32_DWORD fthread_mutexattr_t; // mutex attribute typedef void* (FT_THREAD_FUNC)(void*); // thread function typedef FT_THREAD_FUNC* PFT_THREAD_FUNC; // thread function ptr typedef struct _tagFTU_MUTEX // fthread "mutex" structure { FT_W32_DWORD dwMutexMagic; // (magic number) FT_W32_HANDLE hMutex; // (ptr to actual mutex structure) } fthread_mutex_t; typedef struct _tagFTU_COND // fthread "condition variable" structure { FT_W32_DWORD dwCondMagic; // (magic number) FT_W32_HANDLE hCondVar; // (ptr to actual condition variable structure) } fthread_cond_t; typedef struct _tagFTU_ATTR // fthread "thread attribute" structure { FT_W32_DWORD dwAttrMagic; // (magic number) size_t nStackSize; // (initial stack size in bytes) int nDetachState; // (requested detach state: detached/joinable) } fthread_attr_t; //////////////////////////////////////////////////////////////////////////////////// // fthread thread attribute types... #define FTHREAD_CREATE_JOINABLE 0x4A6F696E // "Join" in ASCII #define FTHREAD_CREATE_DETACHED 0x44697363 // "Disc" in ASCII #define FTHREAD_CREATE_DEFAULT FTHREAD_CREATE_JOINABLE //////////////////////////////////////////////////////////////////////////////////// // Initialize a "thread attribute"... FT_DLL_IMPORT int fthread_attr_init ( fthread_attr_t* pThreadAttr ); //////////////////////////////////////////////////////////////////////////////////// // Destroy a "thread attribute"... FT_DLL_IMPORT int fthread_attr_destroy ( fthread_attr_t* pThreadAttr ); //////////////////////////////////////////////////////////////////////////////////// // Set a thread's "detachstate" attribute... FT_DLL_IMPORT int fthread_attr_setdetachstate ( fthread_attr_t* pThreadAttr, int nDetachState ); //////////////////////////////////////////////////////////////////////////////////// // Retrieve a thread's "detachstate" attribute... FT_DLL_IMPORT int fthread_attr_getdetachstate ( const fthread_attr_t* pThreadAttr, int* pnDetachState ); //////////////////////////////////////////////////////////////////////////////////// // Set a thread's initial stack size... FT_DLL_IMPORT int fthread_attr_setstacksize ( fthread_attr_t* pThreadAttr, size_t nStackSize ); //////////////////////////////////////////////////////////////////////////////////// // Retrieve a thread's initial stack size... FT_DLL_IMPORT int fthread_attr_getstacksize ( const fthread_attr_t* pThreadAttr, size_t* pnStackSize ); //////////////////////////////////////////////////////////////////////////////////// // Join a thread (i.e. wait for a thread's termination)... FT_DLL_IMPORT int fthread_join ( #ifdef FISH_HANG const char* pszFile, const int nLine, #endif fthread_t dwThreadID, void** pExitVal ); //////////////////////////////////////////////////////////////////////////////////// // Detach a thread (i.e. ignore a thread's termination)... FT_DLL_IMPORT int fthread_detach ( fthread_t dwThreadID ); //////////////////////////////////////////////////////////////////////////////////// // Create a new thread... FT_DLL_IMPORT int fthread_create ( #ifdef FISH_HANG const char* pszFile, const int nLine, #endif fthread_t* pdwThreadID, fthread_attr_t* pThreadAttr, PFT_THREAD_FUNC pfnThreadFunc, void* pvThreadArgs, char* pszThreadName ); //////////////////////////////////////////////////////////////////////////////////// // Exit from a thread... FT_DLL_IMPORT void fthread_exit ( void* ExitVal ); //////////////////////////////////////////////////////////////////////////////////// // Return thread-id... FT_DLL_IMPORT fthread_t fthread_self ( ); //////////////////////////////////////////////////////////////////////////////////// // Compare thread-ids... FT_DLL_IMPORT int fthread_equal ( fthread_t pdwThreadID_1, fthread_t pdwThreadID_2 ); //////////////////////////////////////////////////////////////////////////////////// // (thread signalling not [currently] supported (yet); always returns ENOTSUP...) FT_DLL_IMPORT int fthread_kill // FIXME: TODO: ( int dummy1, int dummy2 ); //////////////////////////////////////////////////////////////////////////////////// // Initialize a "mutex"... FT_DLL_IMPORT int fthread_mutex_init ( #ifdef FISH_HANG const char* pszFile, const int nLine, #endif fthread_mutex_t* pFT_MUTEX, const fthread_mutexattr_t* pFT_MUTEX_ATTR ); //////////////////////////////////////////////////////////////////////////////////// // Destroy a "mutex"... FT_DLL_IMPORT int fthread_mutex_destroy ( #ifdef FISH_HANG const char* pszFile, const int nLine, #endif fthread_mutex_t* pFT_MUTEX ); //////////////////////////////////////////////////////////////////////////////////// // Lock a "mutex"... FT_DLL_IMPORT int fthread_mutex_lock ( #ifdef FISH_HANG const char* pszFile, const int nLine, #endif fthread_mutex_t* pFT_MUTEX ); //////////////////////////////////////////////////////////////////////////////////// // Try to lock a "mutex"... FT_DLL_IMPORT int fthread_mutex_trylock ( #ifdef FISH_HANG const char* pszFile, const int nLine, #endif fthread_mutex_t* pFT_MUTEX ); //////////////////////////////////////////////////////////////////////////////////// // Unlock a "mutex"... FT_DLL_IMPORT int fthread_mutex_unlock ( #ifdef FISH_HANG const char* pszFile, const int nLine, #endif fthread_mutex_t* pFT_MUTEX ); //////////////////////////////////////////////////////////////////////////////////// // Initialize a "condition"... FT_DLL_IMPORT int fthread_cond_init ( #ifdef FISH_HANG const char* pszFile, const int nLine, #endif fthread_cond_t* pFT_COND_VAR ); //////////////////////////////////////////////////////////////////////////////////// // Destroy a "condition"... FT_DLL_IMPORT int fthread_cond_destroy ( #ifdef FISH_HANG const char* pszFile, const int nLine, #endif fthread_cond_t* pFT_COND_VAR ); //////////////////////////////////////////////////////////////////////////////////// // 'Signal' a "condition"... (causes ONE waiting thread to be released) FT_DLL_IMPORT int fthread_cond_signal ( #ifdef FISH_HANG const char* pszFile, const int nLine, #endif fthread_cond_t* pFT_COND_VAR ); //////////////////////////////////////////////////////////////////////////////////// // 'Broadcast' a "condition"... (causes ALL waiting threads to be released) FT_DLL_IMPORT int fthread_cond_broadcast ( #ifdef FISH_HANG const char* pszFile, const int nLine, #endif fthread_cond_t* pFT_COND_VAR ); //////////////////////////////////////////////////////////////////////////////////// // Wait for a "condition" to occur... FT_DLL_IMPORT int fthread_cond_wait ( #ifdef FISH_HANG const char* pszFile, const int nLine, #endif fthread_cond_t* pFT_COND_VAR, fthread_mutex_t* pFT_MUTEX ); //////////////////////////////////////////////////////////////////////////////////// // Wait (but not forever) for a "condition" to occur... FT_DLL_IMPORT int fthread_cond_timedwait ( #ifdef FISH_HANG const char* pszFile, const int nLine, #endif fthread_cond_t* pFT_COND_VAR, fthread_mutex_t* pFT_MUTEX, struct timespec* pTimeTimeout ); //////////////////////////////////////////////////////////////////////////////////// // fthread mutex attribute types... // // FTHREAD_MUTEX_NORMAL This type of mutex does not detect deadlock. A thread // attempting to relock this mutex without first unlocking // it shall deadlock. Attempting to unlock a mutex locked // by a different thread results in undefined behavior. // Attempting to unlock an unlocked mutex results in // undefined behavior. The FTHREAD_MUTEX_NORMAL mutex type // is not currently supported by fthreads. // // FTHREAD_MUTEX_ERRORCHECK This type of mutex provides error checking. A thread // attempting to relock this mutex without first unlocking // it shall return with an error. A thread attempting to // unlock a mutex which another thread has locked shall // return with an error. A thread attempting to unlock an // unlocked mutex shall return with an error. // // FTHREAD_MUTEX_RECURSIVE A thread attempting to relock this mutex without first // unlocking it shall succeed in locking the mutex. The // relocking deadlock which can occur with mutexes of type // FTHREAD_MUTEX_NORMAL cannot occur with this type of mutex. // Multiple locks of this mutex shall require the same number // of unlocks to release the mutex before another thread // can acquire the mutex. A thread attempting to unlock a // mutex which another thread has locked shall return with // an error. A thread attempting to unlock an unlocked mutex // shall return with an error. // // FTHREAD_MUTEX_DEFAULT Attempting to recursively lock a mutex of this type results // in undefined behavior. Attempting to unlock a mutex of this // type which was not locked by the calling thread results // in undefined behavior. Attempting to unlock a mutex of this // type which is not locked results in undefined behavior. // An implementation may map this mutex to one of the other // mutex types. #define FTHREAD_MUTEX_ERRORCHECK 0x4F6E6365 // "Once" in ASCII #define FTHREAD_MUTEX_RECURSIVE 0x4D616E79 // "Many" in ASCII #define FTHREAD_MUTEX_DEFAULT FTHREAD_MUTEX_ERRORCHECK //////////////////////////////////////////////////////////////////////////////////// // Initialize a "mutex" attribute... FT_DLL_IMPORT int fthread_mutexattr_init ( fthread_mutexattr_t* pFT_MUTEX_ATTR ); //////////////////////////////////////////////////////////////////////////////////// // Destroy a "mutex" attribute... FT_DLL_IMPORT int fthread_mutexattr_destroy ( fthread_mutexattr_t* pFT_MUTEX_ATTR ); //////////////////////////////////////////////////////////////////////////////////// // Retrieve "mutex" attribute type... FT_DLL_IMPORT int fthread_mutexattr_gettype ( const fthread_mutexattr_t* pFT_MUTEX_ATTR, int* pnMutexType ); //////////////////////////////////////////////////////////////////////////////////// // Set "mutex" attribute type... FT_DLL_IMPORT int fthread_mutexattr_settype ( fthread_mutexattr_t* pFT_MUTEX_ATTR, int nMutexType ); //////////////////////////////////////////////////////////////////////////////////// #endif // _FTHREADS_H_ hercules-3.07/general1.c000644 000765 000765 00000503132 11157241226 016612 0ustar00jmaynardjmaynard000000 000000 /* GENERAL1.C (c) Copyright Roger Bowler, 1994-2009 */ /* ESA/390 CPU Emulator */ /* Instructions A-M */ /* (c) Copyright Peter Kuschnerus, 1999-2009 (UPT & CFC)*/ /* Interpretive Execution - (c) Copyright Jan Jaeger, 1999-2009 */ /* z/Architecture support - (c) Copyright Jan Jaeger, 1999-2009 */ // $Id: general1.c 5220 2009-03-01 09:46:32Z jj $ /*-------------------------------------------------------------------*/ /* This module implements all general instructions of the */ /* S/370 and ESA/390 architectures, as described in the manuals */ /* GA22-7000-03 System/370 Principles of Operation */ /* SA22-7201-06 ESA/390 Principles of Operation */ /*-------------------------------------------------------------------*/ /*-------------------------------------------------------------------*/ /* Additional credits: */ /* Corrections to shift instructions by Jay Maynard, Jan Jaeger */ /* Branch tracing by Jan Jaeger */ /* Instruction decode by macros - Jan Jaeger */ /* Prevent TOD from going backwards in time - Jan Jaeger */ /* Fix STCKE instruction - Bernard van der Helm */ /* Instruction decode rework - Jan Jaeger */ /* Make STCK update the TOD clock - Jay Maynard */ /* Fix address wraparound in MVO - Jan Jaeger */ /* PLO instruction - Jan Jaeger */ /* Modifications for Interpretive Execution (SIE) by Jan Jaeger */ /* Clear TEA on data exception - Peter Kuschnerus v209*/ /*-------------------------------------------------------------------*/ // $Log$ // Revision 1.178 2009/02/07 22:54:06 ivan // Define MIN() macro for MVCLE use in case it isn't defined // // Revision 1.177 2009/02/07 22:49:38 ivan // Use concpy in MVCL to maintain Concurrent Block Update Consistency // Use concpy in MVCLE to maintain Concurrent Block Update Consistency // Enhance performances for MVCLE // // Revision 1.176 2009/02/04 18:09:39 ivan // Temporary fixes for 'potentially uninitialized variables' by GCC. // To me, it's bogus. Look for MVCL in general1.c & zmoncode in cpu.c // and read FIXME. // // Revision 1.175 2009/02/04 12:22:37 ivan // Fix issue with unaligned LM/STM when running on a host architecture that // enforces alignment // // Revision 1.174 2009/01/31 21:37:50 rbowler // Adopt general coding style - No functional changes // // Revision 1.173 2009/01/31 17:49:17 ivan // Ensure proper nullification of MVCL if an access exception occurs during the 1st unit of operation // // Revision 1.172 2009/01/23 11:55:54 bernard // copyright notice // // Revision 1.171 2009/01/11 20:28:33 ivan // Remove dead code // // Revision 1.170 2008/12/24 07:50:16 ivan // CSST Fix - Parm 2 alignement check error // // Revision 1.169 2008/12/23 13:44:57 ivan // CSST Facility 2 fix // // Revision 1.168 2008/12/22 00:29:10 ivan // Implement February 2008 z/Arch Compare And Swap And Store Facility 2 // Update FAQ to reflect change // update FAQ to also indicate z/Arch DAT Enhancement is implemented // // Revision 1.167 2008/10/07 22:24:35 gsmith // Fix zero ilc problem after branch trace // // Revision 1.166 2008/05/06 22:15:42 rbowler // Fix warning: operation on `p1' may be undefined // // Revision 1.165 2008/04/11 14:28:44 bernard // Integrate regs->exrl into base Hercules code. // // Revision 1.164 2008/04/09 12:01:35 rbowler // Correct target instruction address for EXRL // // Revision 1.163 2008/04/09 07:38:09 bernard // Allign to Rogers terminal ;-) // // Revision 1.162 2008/04/09 07:15:14 bernard // Comment Roger // // Revision 1.161 2008/04/09 07:05:19 bernard // EXRL has format C6x0, not C6. Thanks Roger! // // Revision 1.160 2008/04/09 05:38:57 bernard // Instruction fetching error, now fetched with PSW_IA macro. // // Revision 1.159 2008/04/08 18:33:41 bernard // Error in EXRL // // Revision 1.158 2008/04/08 17:13:26 bernard // Added execute relative long instruction // // Revision 1.157 2008/03/05 00:34:44 ptl00 // Fix CFC operand size fetch // // Revision 1.156 2008/03/04 00:52:32 ptl00 // Fix BSM/BASSM mode switch trace // // Revision 1.155 2008/02/28 22:07:09 ptl00 // Fix mode switch trace // // Revision 1.154 2008/02/15 21:20:00 ptl00 // Fix EX to SS ops so that ILC is 4 on PER rupts // // Revision 1.153 2007/11/30 15:14:14 rbowler // Permit String-Instruction facility to be activated in S/370 mode // // Revision 1.152 2007/08/07 19:47:59 ivan // Fix a couple of gcc-4.2 warnings // // Revision 1.151 2007/06/23 00:04:10 ivan // Update copyright notices to include current year (2007) // // Revision 1.150 2007/05/26 21:23:19 rbowler // Eliminate uninitialised variable warnings in CSST // // Revision 1.149 2007/05/26 14:23:55 rbowler // CSST instruction // // Revision 1.148 2007/01/13 07:21:11 bernard // backout ccmask // // Revision 1.147 2007/01/12 15:23:41 bernard // ccmaks phase 1 // // Revision 1.146 2007/01/09 05:10:19 gsmith // Tweaks to lm/stm // // Revision 1.145 2007/01/04 23:12:04 gsmith // remove thunk calls for program_interrupt // // Revision 1.144 2006/12/31 21:16:32 gsmith // 2006 Dec 31 really back out mainlockx.pat // // Revision 1.143 2006/12/20 09:09:40 jj // Fix bogus log entries // // Revision 1.142 2006/12/20 04:26:19 gsmith // 19 Dec 2006 ip_all.pat - performance patch - Greg Smith // // Revision 1.141 2006/12/20 04:22:00 gsmith // 2006 Dec 19 Backout mainlockx.pat - possible SMP problems - Greg Smith // // Revision 1.140 2006/12/08 09:43:21 jj // Add CVS message log // #include "hstdinc.h" #if !defined(_HENGINE_DLL_) #define _HENGINE_DLL_ #endif #if !defined(_GENERAL1_C_) #define _GENERAL1_C_ #endif #include "hercules.h" #include "opcode.h" #include "inline.h" #include "clock.h" /*-------------------------------------------------------------------*/ /* 1A AR - Add Register [RR] */ /*-------------------------------------------------------------------*/ DEF_INST(add_register) { int r1, r2; /* Values of R fields */ RR(inst, regs, r1, r2); /* Add signed operands and set condition code */ regs->psw.cc = add_signed (&(regs->GR_L(r1)), regs->GR_L(r1), regs->GR_L(r2)); /* Program check if fixed-point overflow */ if ( regs->psw.cc == 3 && FOMASK(®s->psw) ) regs->program_interrupt (regs, PGM_FIXED_POINT_OVERFLOW_EXCEPTION); } /*-------------------------------------------------------------------*/ /* 5A A - Add [RX] */ /*-------------------------------------------------------------------*/ DEF_INST(add) { int r1; /* Values of R fields */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ U32 n; /* 32-bit operand values */ RX(inst, regs, r1, b2, effective_addr2); /* Load second operand from operand address */ n = ARCH_DEP(vfetch4) ( effective_addr2, b2, regs ); /* Add signed operands and set condition code */ regs->psw.cc = add_signed (&(regs->GR_L(r1)), regs->GR_L(r1), n); /* Program check if fixed-point overflow */ if ( regs->psw.cc == 3 && FOMASK(®s->psw) ) regs->program_interrupt (regs, PGM_FIXED_POINT_OVERFLOW_EXCEPTION); } /*-------------------------------------------------------------------*/ /* 4A AH - Add Halfword [RX] */ /*-------------------------------------------------------------------*/ DEF_INST(add_halfword) { int r1; /* Value of R field */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ S32 n; /* 32-bit operand values */ RX(inst, regs, r1, b2, effective_addr2); /* Load 2 bytes from operand address */ n = (S16)ARCH_DEP(vfetch2) ( effective_addr2, b2, regs ); /* Add signed operands and set condition code */ regs->psw.cc = add_signed (&(regs->GR_L(r1)), regs->GR_L(r1), (U32)n); /* Program check if fixed-point overflow */ if ( regs->psw.cc == 3 && FOMASK(®s->psw) ) regs->program_interrupt (regs, PGM_FIXED_POINT_OVERFLOW_EXCEPTION); } #if defined(FEATURE_IMMEDIATE_AND_RELATIVE) /*-------------------------------------------------------------------*/ /* A7xA AHI - Add Halfword Immediate [RI] */ /*-------------------------------------------------------------------*/ DEF_INST(add_halfword_immediate) { int r1; /* Register number */ int opcd; /* Opcode */ U16 i2; /* 16-bit immediate op */ RI(inst, regs, r1, opcd, i2); /* Add signed operands and set condition code */ regs->psw.cc = add_signed (&(regs->GR_L(r1)), regs->GR_L(r1), (S16)i2); /* Program check if fixed-point overflow */ if ( regs->psw.cc == 3 && FOMASK(®s->psw) ) regs->program_interrupt (regs, PGM_FIXED_POINT_OVERFLOW_EXCEPTION); } #endif /*defined(FEATURE_IMMEDIATE_AND_RELATIVE)*/ /*-------------------------------------------------------------------*/ /* 1E ALR - Add Logical Register [RR] */ /*-------------------------------------------------------------------*/ DEF_INST(add_logical_register) { int r1, r2; /* Values of R fields */ RR0(inst, regs, r1, r2); /* Add signed operands and set condition code */ regs->psw.cc = add_logical (&(regs->GR_L(r1)), regs->GR_L(r1), regs->GR_L(r2)); } /*-------------------------------------------------------------------*/ /* 5E AL - Add Logical [RX] */ /*-------------------------------------------------------------------*/ DEF_INST(add_logical) { int r1; /* Value of R field */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ U32 n; /* 32-bit operand values */ RX(inst, regs, r1, b2, effective_addr2); /* Load second operand from operand address */ n = ARCH_DEP(vfetch4) ( effective_addr2, b2, regs ); /* Add signed operands and set condition code */ regs->psw.cc = add_logical (&(regs->GR_L(r1)), regs->GR_L(r1), n); } /*-------------------------------------------------------------------*/ /* 14 NR - And Register [RR] */ /*-------------------------------------------------------------------*/ DEF_INST(and_register) { int r1, r2; /* Values of R fields */ RR0(inst, regs, r1, r2); /* AND second operand with first and set condition code */ regs->psw.cc = ( regs->GR_L(r1) &= regs->GR_L(r2) ) ? 1 : 0; } /*-------------------------------------------------------------------*/ /* 54 N - And [RX] */ /*-------------------------------------------------------------------*/ DEF_INST(and) { int r1; /* Value of R field */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ U32 n; /* 32-bit operand values */ RX(inst, regs, r1, b2, effective_addr2); /* Load second operand from operand address */ n = ARCH_DEP(vfetch4) ( effective_addr2, b2, regs ); /* AND second operand with first and set condition code */ regs->psw.cc = ( regs->GR_L(r1) &= n ) ? 1 : 0; } /*-------------------------------------------------------------------*/ /* 94 NI - And Immediate [SI] */ /*-------------------------------------------------------------------*/ DEF_INST(and_immediate) { BYTE i2; /* Immediate byte of opcode */ int b1; /* Base of effective addr */ VADR effective_addr1; /* Effective address */ BYTE *dest; /* Pointer to target byte */ SI(inst, regs, i2, b1, effective_addr1); /* Get byte mainstor address */ dest = MADDR (effective_addr1, b1, regs, ACCTYPE_WRITE, regs->psw.pkey ); /* AND byte with immediate operand, setting condition code */ regs->psw.cc = ((*dest &= i2) != 0); /* Update interval timer if necessary */ ITIMER_UPDATE(effective_addr1,4-1,regs); } /*-------------------------------------------------------------------*/ /* D4 NC - And Character [SS] */ /*-------------------------------------------------------------------*/ DEF_INST(and_character) { int len, len2, len3; /* Lengths to copy */ int b1, b2; /* Base register numbers */ VADR addr1, addr2; /* Virtual addresses */ BYTE *dest1, *dest2; /* Destination addresses */ BYTE *source1, *source2; /* Source addresses */ BYTE *sk1, *sk2; /* Storage key addresses */ int i; /* Loop counter */ int cc = 0; /* Condition code */ SS_L(inst, regs, len, b1, addr1, b2, addr2); ITIMER_SYNC(addr2,len,regs); ITIMER_SYNC(addr1,len,regs); /* Quick out for 1 byte (no boundary crossed) */ if (unlikely(len == 0)) { source1 = MADDR (addr2, b2, regs, ACCTYPE_READ, regs->psw.pkey); dest1 = MADDR (addr1, b1, regs, ACCTYPE_WRITE, regs->psw.pkey); *dest1 &= *source1; regs->psw.cc = (*dest1 != 0); ITIMER_UPDATE(addr1,0,regs); return; } /* There are several scenarios (in optimal order): * (1) dest boundary and source boundary not crossed * (2) dest boundary not crossed and source boundary crossed * (3) dest boundary crossed and source boundary not crossed * (4) dest boundary and source boundary are crossed * (a) dest and source boundary cross at the same time * (b) dest boundary crossed first * (c) source boundary crossed first */ /* Translate addresses of leftmost operand bytes */ dest1 = MADDR (addr1, b1, regs, ACCTYPE_WRITE_SKP, regs->psw.pkey); sk1 = regs->dat.storkey; source1 = MADDR (addr2, b2, regs, ACCTYPE_READ, regs->psw.pkey); if ( NOCROSS2K(addr1,len ) ) { if ( NOCROSS2K(addr2,len) ) { /* (1) - No boundaries are crossed */ for (i = 0; i <= len; i++) if (*dest1++ &= *source1++) cc = 1; } else { /* (2) - Second operand crosses a boundary */ len2 = 0x800 - (addr2 & 0x7FF); source2 = MADDR ((addr2 + len2) & ADDRESS_MAXWRAP(regs), b2, regs, ACCTYPE_READ, regs->psw.pkey); for ( i = 0; i < len2; i++) if (*dest1++ &= *source1++) cc = 1; len2 = len - len2; for ( i = 0; i <= len2; i++) if (*dest1++ &= *source2++) cc = 1; } *sk1 |= (STORKEY_REF | STORKEY_CHANGE); } else { /* First operand crosses a boundary */ len2 = 0x800 - (addr1 & 0x7FF); dest2 = MADDR ((addr1 + len2) & ADDRESS_MAXWRAP(regs), b1, regs, ACCTYPE_WRITE_SKP, regs->psw.pkey); sk2 = regs->dat.storkey; if ( NOCROSS2K(addr2,len )) { /* (3) - First operand crosses a boundary */ for ( i = 0; i < len2; i++) if (*dest1++ &= *source1++) cc = 1; len2 = len - len2; for ( i = 0; i <= len2; i++) if (*dest2++ &= *source1++) cc = 1; } else { /* (4) - Both operands cross a boundary */ len3 = 0x800 - (addr2 & 0x7FF); source2 = MADDR ((addr2 + len3) & ADDRESS_MAXWRAP(regs), b2, regs, ACCTYPE_READ, regs->psw.pkey); if (len2 == len3) { /* (4a) - Both operands cross at the same time */ for ( i = 0; i < len2; i++) if (*dest1++ &= *source1++) cc = 1; len2 = len - len2; for ( i = 0; i <= len2; i++) if (*dest2++ &= *source2++) cc = 1; } else if (len2 < len3) { /* (4b) - First operand crosses first */ for ( i = 0; i < len2; i++) if (*dest1++ &= *source1++) cc = 1; len2 = len3 - len2; for ( i = 0; i < len2; i++) if (*dest2++ &= *source1++) cc = 1; len2 = len - len3; for ( i = 0; i <= len2; i++) if (*dest2++ &= *source2++) cc = 1; } else { /* (4c) - Second operand crosses first */ for ( i = 0; i < len3; i++) if (*dest1++ &= *source1++) cc = 1; len3 = len2 - len3; for ( i = 0; i < len3; i++) if (*dest1++ &= *source2++) cc = 1; len3 = len - len2; for ( i = 0; i <= len3; i++) if (*dest2++ &= *source2++) cc = 1; } } *sk1 |= (STORKEY_REF | STORKEY_CHANGE); *sk2 |= (STORKEY_REF | STORKEY_CHANGE); } ITIMER_UPDATE(addr1,len,regs); regs->psw.cc = cc; } /*-------------------------------------------------------------------*/ /* 05 BALR - Branch and Link Register [RR] */ /*-------------------------------------------------------------------*/ DEF_INST(branch_and_link_register) { int r1, r2; /* Values of R fields */ VADR newia; /* New instruction address */ RR_B(inst, regs, r1, r2); #if defined(FEATURE_TRACING) /* Add a branch trace entry to the trace table */ if ((regs->CR(12) & CR12_BRTRACE) && (r2 != 0)) { regs->psw.ilc = 0; // indicates regs->ip not updated regs->CR(12) = ((ARCH_DEP(trace_br_func))regs->trace_br) (regs->psw.amode, regs->GR_L(r2), regs); regs->psw.ilc = 2; // reset if trace didn't pgm check } #endif /*defined(FEATURE_TRACING)*/ /* Compute the branch address from the R2 operand */ newia = regs->GR(r2); /* Save the link information in the R1 operand */ #if defined(FEATURE_ESAME) if( regs->psw.amode64 ) regs->GR_G(r1) = PSW_IA64(regs, 2); else #endif regs->GR_L(r1) = ( regs->psw.amode ) ? (0x80000000 | PSW_IA31(regs, 2)) : (((!regs->execflag ? 2 : regs->exrl ? 6 : 4) << 29) | (regs->psw.cc << 28) | (regs->psw.progmask << 24) | PSW_IA24(regs, 2)); /* Execute the branch unless R2 specifies register 0 */ if ( r2 != 0 ) SUCCESSFUL_BRANCH(regs, newia, 2); else INST_UPDATE_PSW(regs, 2, 0); } /* end DEF_INST(branch_and_link_register) */ /*-------------------------------------------------------------------*/ /* 45 BAL - Branch and Link [RX] */ /*-------------------------------------------------------------------*/ DEF_INST(branch_and_link) { int r1; /* Value of R field */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ RX_B(inst, regs, r1, b2, effective_addr2); /* Save the link information in the R1 operand */ #if defined(FEATURE_ESAME) if( regs->psw.amode64 ) regs->GR_G(r1) = PSW_IA64(regs, 4); else #endif regs->GR_L(r1) = ( regs->psw.amode ) ? (0x80000000 | PSW_IA31(regs, 4)) : ((4 << 29) | (regs->psw.cc << 28) | (regs->psw.progmask << 24) | PSW_IA24(regs, 4)); SUCCESSFUL_BRANCH(regs, effective_addr2, 4); } /* end DEF_INST(branch_and_link) */ /*-------------------------------------------------------------------*/ /* 0D BASR - Branch and Save Register [RR] */ /*-------------------------------------------------------------------*/ DEF_INST(branch_and_save_register) { int r1, r2; /* Values of R fields */ VADR newia; /* New instruction address */ RR_B(inst, regs, r1, r2); #if defined(FEATURE_TRACING) /* Add a branch trace entry to the trace table */ if ((regs->CR(12) & CR12_BRTRACE) && (r2 != 0)) { regs->psw.ilc = 0; // indcates regs->ip not updated regs->CR(12) = ((ARCH_DEP(trace_br_func))regs->trace_br) (regs->psw.amode, regs->GR_L(r2), regs); regs->psw.ilc = 2; // reset if trace didn't pgm check } #endif /*defined(FEATURE_TRACING)*/ /* Compute the branch address from the R2 operand */ newia = regs->GR(r2); /* Save the link information in the R1 operand */ #if defined(FEATURE_ESAME) if ( regs->psw.amode64 ) regs->GR_G(r1) = PSW_IA64(regs, 2); else #endif if ( regs->psw.amode ) regs->GR_L(r1) = 0x80000000 | PSW_IA31(regs, 2); else regs->GR_L(r1) = PSW_IA24(regs, 2); /* Execute the branch unless R2 specifies register 0 */ if ( r2 != 0 ) SUCCESSFUL_BRANCH(regs, newia, 2); else INST_UPDATE_PSW(regs, 2, 0); } /* end DEF_INST(branch_and_save_register) */ /*-------------------------------------------------------------------*/ /* 4D BAS - Branch and Save [RX] */ /*-------------------------------------------------------------------*/ DEF_INST(branch_and_save) { int r1; /* Value of R field */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ RX_B(inst, regs, r1, b2, effective_addr2); /* Save the link information in the R1 register */ #if defined(FEATURE_ESAME) if ( regs->psw.amode64 ) regs->GR_G(r1) = PSW_IA64(regs, 4); else #endif if ( regs->psw.amode ) regs->GR_L(r1) = 0x80000000 | PSW_IA31(regs, 4); else regs->GR_L(r1) = PSW_IA24(regs, 4); SUCCESSFUL_BRANCH(regs, effective_addr2, 4); } /* end DEF_INST(branch_and_save) */ #if defined(FEATURE_BIMODAL_ADDRESSING) /*-------------------------------------------------------------------*/ /* 0C BASSM - Branch and Save and Set Mode [RR] */ /*-------------------------------------------------------------------*/ DEF_INST(branch_and_save_and_set_mode) { int r1, r2; /* Values of R fields */ VADR newia; /* New instruction address */ int xmode; /* 64 or 31 mode of target */ #if defined(FEATURE_ESAME) BYTE *ipsav; /* save for ip */ #endif /*defined(FEATURE_ESAME)*/ RR_B(inst, regs, r1, r2); /* Compute the branch address from the R2 operand */ newia = regs->GR(r2); #if defined(FEATURE_TRACING) #if defined(FEATURE_ESAME) /* Add a mode trace entry when switching in/out of 64 bit mode */ if((regs->CR(12) & CR12_MTRACE) && (r2 != 0) && (regs->psw.amode64 != (newia & 1))) { /* save ip and update it for mode switch trace */ ipsav = regs->ip; INST_UPDATE_PSW(regs, 2, 0); regs->psw.ilc = 2; regs->CR(12) = ARCH_DEP(trace_ms) (regs->CR(12) & CR12_BRTRACE ? 1 : 0, newia & ~0x01, regs); regs->ip = ipsav; } else #endif /*defined(FEATURE_ESAME)*/ /* Add a branch trace entry to the trace table */ if ((regs->CR(12) & CR12_BRTRACE) && (r2 != 0)) { regs->psw.ilc = 0; // indicates regs->ip not updated #if defined(FEATURE_ESAME) if (newia & 0x01) xmode = 1; else #endif /*defined(FEATURE_ESAME)*/ xmode = newia & 0x80000000 ? 1 : 0; regs->CR(12) = ARCH_DEP(trace_br) (xmode, newia & ~0x01, regs); regs->psw.ilc = 2; // reset if trace didn't pgm check } #endif /*defined(FEATURE_TRACING)*/ /* Save the link information in the R1 operand */ #if defined(FEATURE_ESAME) if ( regs->psw.amode64 ) regs->GR_G(r1) = PSW_IA64(regs, 3); // low bit on else #endif /*defined(FEATURE_ESAME)*/ if ( regs->psw.amode ) regs->GR_L(r1) = 0x80000000 | PSW_IA31(regs, 2); else regs->GR_L(r1) = PSW_IA24(regs, 2); /* Set mode and branch to address specified by R2 operand */ if ( r2 != 0 ) { SET_ADDRESSING_MODE(regs, newia); SUCCESSFUL_BRANCH(regs, newia, 2); } else INST_UPDATE_PSW(regs, 2, 0); } /* end DEF_INST(branch_and_save_and_set_mode) */ #endif /*defined(FEATURE_BIMODAL_ADDRESSING)*/ #if defined(FEATURE_BIMODAL_ADDRESSING) /*-------------------------------------------------------------------*/ /* 0B BSM - Branch and Set Mode [RR] */ /*-------------------------------------------------------------------*/ DEF_INST(branch_and_set_mode) { int r1, r2; /* Values of R fields */ VADR newia; /* New instruction address */ RR_B(inst, regs, r1, r2); /* Compute the branch address from the R2 operand */ newia = regs->GR(r2); #if defined(FEATURE_TRACING) #if defined(FEATURE_ESAME) /* Add a mode trace entry when switching in/out of 64 bit mode */ if((regs->CR(12) & CR12_MTRACE) && (r2 != 0) && (regs->psw.amode64 != (newia & 1))) { INST_UPDATE_PSW(regs, 2, 0); regs->psw.ilc = 2; regs->CR(12) = ARCH_DEP(trace_ms) (0, 0, regs); } #endif /*defined(FEATURE_ESAME)*/ #endif /*defined(FEATURE_TRACING)*/ /* Insert addressing mode into bit 0 of R1 operand */ if ( r1 != 0 ) { #if defined(FEATURE_ESAME) /* Z/Pops seems to be in error about this */ // regs->GR_LHLCL(r1) &= 0xFE; if ( regs->psw.amode64 ) regs->GR_LHLCL(r1) |= 0x01; else #endif { if ( regs->psw.amode ) regs->GR_L(r1) |= 0x80000000; else regs->GR_L(r1) &= 0x7FFFFFFF; } } /* Set mode and branch to address specified by R2 operand */ if ( r2 != 0 ) { SET_ADDRESSING_MODE(regs, newia); SUCCESSFUL_BRANCH(regs, newia, 2); } else INST_UPDATE_PSW(regs, 2, 0); } /* end DEF_INST(branch_and_set_mode) */ #endif /*defined(FEATURE_BIMODAL_ADDRESSING)*/ /*-------------------------------------------------------------------*/ /* 07 BCR - Branch on Condition Register [RR] */ /*-------------------------------------------------------------------*/ DEF_INST(branch_on_condition_register) { //int r1, r2; /* Values of R fields */ // RR(inst, regs, r1, r2); /* Branch if R1 mask bit is set and R2 is not register 0 */ if ((inst[1] & 0x0F) != 0 && (inst[1] & (0x80 >> regs->psw.cc))) SUCCESSFUL_BRANCH(regs, regs->GR(inst[1] & 0x0F), 2); else { INST_UPDATE_PSW(regs, 2, 0); /* Perform serialization and checkpoint synchronization if the mask is all ones and the register is all zeroes */ if ( inst[1] == 0xF0 ) { PERFORM_SERIALIZATION (regs); PERFORM_CHKPT_SYNC (regs); } } } /* end DEF_INST(branch_on_condition_register) */ /*-------------------------------------------------------------------*/ /* 47 BC - Branch on Condition [RX] */ /*-------------------------------------------------------------------*/ DEF_INST(branch_on_condition) { int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ /* Branch to operand address if r1 mask bit is set */ if ((0x80 >> regs->psw.cc) & inst[1]) { RX_BC(inst, regs, b2, effective_addr2); SUCCESSFUL_BRANCH(regs, effective_addr2, 4); } else INST_UPDATE_PSW(regs, 4, 0); } /* end DEF_INST(branch_on_condition) */ /*-------------------------------------------------------------------*/ /* 06 BCTR - Branch on Count Register [RR] */ /*-------------------------------------------------------------------*/ DEF_INST(branch_on_count_register) { int r1, r2; /* Values of R fields */ VADR newia; /* New instruction address */ RR_B(inst, regs, r1, r2); /* Compute the branch address from the R2 operand */ newia = regs->GR(r2); /* Subtract 1 from the R1 operand and branch if result is non-zero and R2 operand is not register zero */ if ( --(regs->GR_L(r1)) && r2 != 0 ) SUCCESSFUL_BRANCH(regs, newia, 2); else INST_UPDATE_PSW(regs, 2, 0); } /* end DEF_INST(branch_on_count_register) */ /*-------------------------------------------------------------------*/ /* 46 BCT - Branch on Count [RX] */ /*-------------------------------------------------------------------*/ DEF_INST(branch_on_count) { int r1; /* Value of R field */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ RX_B(inst, regs, r1, b2, effective_addr2); /* Subtract 1 from the R1 operand and branch if non-zero */ if ( --(regs->GR_L(r1)) ) SUCCESSFUL_BRANCH(regs, effective_addr2, 4); else INST_UPDATE_PSW(regs, 4, 0); } /* end DEF_INST(branch_on_count) */ /*-------------------------------------------------------------------*/ /* 86 BXH - Branch on Index High [RS] */ /*-------------------------------------------------------------------*/ DEF_INST(branch_on_index_high) { int r1, r3; /* Register numbers */ int b2; /* effective address base */ VADR effective_addr2; /* effective address */ S32 i, j; /* Integer work areas */ RS_B(inst, regs, r1, r3, b2, effective_addr2); /* Load the increment value from the R3 register */ i = (S32)regs->GR_L(r3); /* Load compare value from R3 (if R3 odd), or R3+1 (if even) */ j = (r3 & 1) ? (S32)regs->GR_L(r3) : (S32)regs->GR_L(r3+1); /* Add the increment value to the R1 register */ regs->GR_L(r1) = (S32)regs->GR_L(r1) + i; /* Branch if result compares high */ if ( (S32)regs->GR_L(r1) > j ) SUCCESSFUL_BRANCH(regs, effective_addr2, 4); else INST_UPDATE_PSW(regs, 4, 0); } /* end DEF_INST(branch_on_index_high) */ /*-------------------------------------------------------------------*/ /* 87 BXLE - Branch on Index Low or Equal [RS] */ /*-------------------------------------------------------------------*/ DEF_INST(branch_on_index_low_or_equal) { int r1, r3; /* Register numbers */ int b2; /* effective address base */ VADR effective_addr2; /* effective address */ S32 i, j; /* Integer work areas */ RS_B(inst, regs, r1, r3, b2, effective_addr2); /* Load the increment value from the R3 register */ i = regs->GR_L(r3); /* Load compare value from R3 (if R3 odd), or R3+1 (if even) */ j = (r3 & 1) ? (S32)regs->GR_L(r3) : (S32)regs->GR_L(r3+1); /* Add the increment value to the R1 register */ regs->GR_L(r1) = (S32)regs->GR_L(r1) + i; /* Branch if result compares low or equal */ if ( (S32)regs->GR_L(r1) <= j ) SUCCESSFUL_BRANCH(regs, effective_addr2, 4); else INST_UPDATE_PSW(regs, 4, 0); } /* end DEF_INST(branch_on_index_low_or_equal) */ #if defined(FEATURE_IMMEDIATE_AND_RELATIVE) /*-------------------------------------------------------------------*/ /* A7x4 BRC - Branch Relative on Condition [RI] */ /*-------------------------------------------------------------------*/ DEF_INST(branch_relative_on_condition) { //int r1; /* Register number */ //int opcd; /* Opcode */ U16 i2; /* 16-bit operand values */ // RI(inst, regs, r1, opcd, i2); /* Branch if R1 mask bit is set */ if (inst[1] & (0x80 >> regs->psw.cc)) { i2 = fetch_fw(inst) & 0xFFFF; SUCCESSFUL_RELATIVE_BRANCH(regs, 2*(S16)i2, 4); } else INST_UPDATE_PSW(regs, 4, 0); } /* end DEF_INST(branch_relative_on_condition) */ #endif /*defined(FEATURE_IMMEDIATE_AND_RELATIVE)*/ #if defined(FEATURE_IMMEDIATE_AND_RELATIVE) /*-------------------------------------------------------------------*/ /* A7x5 BRAS - Branch Relative And Save [RI] */ /*-------------------------------------------------------------------*/ DEF_INST(branch_relative_and_save) { int r1; /* Register number */ int opcd; /* Opcode */ U16 i2; /* 16-bit operand values */ RI_B(inst, regs, r1, opcd, i2); /* Save the link information in the R1 operand */ #if defined(FEATURE_ESAME) if ( regs->psw.amode64 ) regs->GR_G(r1) = PSW_IA64(regs, 4); else #endif if ( regs->psw.amode ) regs->GR_L(r1) = 0x80000000 | PSW_IA31(regs, 4); else regs->GR_L(r1) = PSW_IA24(regs, 4); SUCCESSFUL_RELATIVE_BRANCH(regs, 2*(S16)i2, 4); } /* end DEF_INST(branch_relative_and_save) */ #endif /*defined(FEATURE_IMMEDIATE_AND_RELATIVE)*/ #if defined(FEATURE_IMMEDIATE_AND_RELATIVE) /*-------------------------------------------------------------------*/ /* A7x6 BRCT - Branch Relative on Count [RI] */ /*-------------------------------------------------------------------*/ DEF_INST(branch_relative_on_count) { int r1; /* Register number */ int opcd; /* Opcode */ U16 i2; /* 16-bit operand values */ RI_B(inst, regs, r1, opcd, i2); /* Subtract 1 from the R1 operand and branch if non-zero */ if ( --(regs->GR_L(r1)) ) SUCCESSFUL_RELATIVE_BRANCH(regs, 2*(S16)i2, 4); else INST_UPDATE_PSW(regs, 4, 0); } /* end DEF_INST(branch_relative_on_count) */ #endif /*defined(FEATURE_IMMEDIATE_AND_RELATIVE)*/ #if defined(FEATURE_IMMEDIATE_AND_RELATIVE) /*-------------------------------------------------------------------*/ /* 84 BRXH - Branch Relative on Index High [RSI] */ /*-------------------------------------------------------------------*/ DEF_INST(branch_relative_on_index_high) { int r1, r3; /* Register numbers */ U16 i2; /* 16-bit operand */ S32 i,j; /* Integer workareas */ RI_B(inst, regs, r1, r3, i2); /* Load the increment value from the R3 register */ i = (S32)regs->GR_L(r3); /* Load compare value from R3 (if R3 odd), or R3+1 (if even) */ j = (r3 & 1) ? (S32)regs->GR_L(r3) : (S32)regs->GR_L(r3+1); /* Add the increment value to the R1 register */ regs->GR_L(r1) = (S32)regs->GR_L(r1) + i; /* Branch if result compares high */ if ( (S32)regs->GR_L(r1) > j ) SUCCESSFUL_RELATIVE_BRANCH(regs, 2*(S16)i2, 4); else INST_UPDATE_PSW(regs, 4, 0); } /* end DEF_INST(branch_relative_on_index_high) */ #endif /*defined(FEATURE_IMMEDIATE_AND_RELATIVE)*/ #if defined(FEATURE_IMMEDIATE_AND_RELATIVE) /*-------------------------------------------------------------------*/ /* 85 BRXLE - Branch Relative on Index Low or Equal [RSI] */ /*-------------------------------------------------------------------*/ DEF_INST(branch_relative_on_index_low_or_equal) { int r1, r3; /* Register numbers */ U16 i2; /* 16-bit operand */ S32 i,j; /* Integer workareas */ RI_B(inst, regs, r1, r3, i2); /* Load the increment value from the R3 register */ i = (S32)regs->GR_L(r3); /* Load compare value from R3 (if R3 odd), or R3+1 (if even) */ j = (r3 & 1) ? (S32)regs->GR_L(r3) : (S32)regs->GR_L(r3+1); /* Add the increment value to the R1 register */ regs->GR_L(r1) = (S32)regs->GR_L(r1) + i; /* Branch if result compares low or equal */ if ( (S32)regs->GR_L(r1) <= j ) SUCCESSFUL_RELATIVE_BRANCH(regs, 2*(S16)i2, 4); else INST_UPDATE_PSW(regs, 4, 0); } /* end DEF_INST(branch_relative_on_index_low_or_equal) */ #endif /*defined(FEATURE_IMMEDIATE_AND_RELATIVE)*/ #if defined(FEATURE_CHECKSUM_INSTRUCTION) /*-------------------------------------------------------------------*/ /* B241 CKSM - Checksum [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(checksum) { int r1, r2; /* Values of R fields */ VADR addr2; /* Address of second operand */ GREG len; /* Operand length */ int i, j; /* Loop counters */ int cc = 0; /* Condition code */ U32 n; /* Word loaded from operand */ U64 dreg; /* Checksum accumulator */ RRE(inst, regs, r1, r2); ODD_CHECK(r2, regs); /* Obtain the second operand address and length from R2, R2+1 */ addr2 = regs->GR(r2) & ADDRESS_MAXWRAP(regs); len = GR_A(r2+1, regs); /* Initialize the checksum from the first operand register */ dreg = regs->GR_L(r1); /* Process each fullword of second operand */ for ( i = 0; len > 0 ; i++ ) { /* If 1024 words have been processed, exit with cc=3 */ if ( i >= 1024 ) { cc = 3; break; } /* Fetch fullword from second operand */ if (len >= 4) { n = ARCH_DEP(vfetch4) ( addr2, r2, regs ); addr2 += 4; addr2 &= ADDRESS_MAXWRAP(regs); len -= 4; } else { /* Fetch final 1, 2, or 3 bytes and pad with zeroes */ for (j = 0, n = 0; j < 4; j++) { n <<= 8; if (len > 0) { n |= ARCH_DEP(vfetchb) ( addr2, r2, regs ); addr2++; addr2 &= ADDRESS_MAXWRAP(regs); len--; } } /* end for(j) */ } /* Accumulate the fullword into the checksum */ dreg += n; /* Carry 32 bit overflow into bit 31 */ if (dreg > 0xFFFFFFFFULL) { dreg &= 0xFFFFFFFFULL; dreg++; } } /* end for(i) */ /* Load the updated checksum into the R1 register */ regs->GR_L(r1) = dreg; /* Update the operand address and length registers */ SET_GR_A(r2, regs,addr2); SET_GR_A(r2+1, regs,len); /* Set condition code 0 or 3 */ regs->psw.cc = cc; } #endif /*defined(FEATURE_CHECKSUM_INSTRUCTION)*/ /*-------------------------------------------------------------------*/ /* 19 CR - Compare Register [RR] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_register) { int r1, r2; /* Values of R fields */ RR0(inst, regs, r1, r2); /* Compare signed operands and set condition code */ regs->psw.cc = (S32)regs->GR_L(r1) < (S32)regs->GR_L(r2) ? 1 : (S32)regs->GR_L(r1) > (S32)regs->GR_L(r2) ? 2 : 0; } /*-------------------------------------------------------------------*/ /* 59 C - Compare [RX] */ /*-------------------------------------------------------------------*/ DEF_INST(compare) { int r1; /* Values of R fields */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ U32 n; /* 32-bit operand values */ RX(inst, regs, r1, b2, effective_addr2); /* Load second operand from operand address */ n = ARCH_DEP(vfetch4) ( effective_addr2, b2, regs ); /* Compare signed operands and set condition code */ regs->psw.cc = (S32)regs->GR_L(r1) < (S32)n ? 1 : (S32)regs->GR_L(r1) > (S32)n ? 2 : 0; } /*-------------------------------------------------------------------*/ /* B21A CFC - Compare and Form Codeword [S] */ /* (c) Copyright Peter Kuschnerus, 1999-2009 */ /* (c) Copyright "Fish" (David B. Trout), 2005-2009 */ /*-------------------------------------------------------------------*/ DEF_INST(compare_and_form_codeword) { int b2; /* Base of effective addr */ int rc; /* memcmp() return code */ int i; /* (work var) */ VADR op2_effective_addr; /* (op2 effective address) */ VADR op1_addr, op3_addr; /* (op1 & op3 fetch addr) */ GREG work_reg; /* (register work area) */ U16 index, max_index; /* (operand index values) */ BYTE op1[CFC_MAX_OPSIZE]; /* (work field) */ BYTE op3[CFC_MAX_OPSIZE]; /* (work field) */ BYTE tmp[CFC_MAX_OPSIZE]; /* (work field) */ BYTE descending; /* (sort-order control bit) */ #if defined(FEATURE_ESAME) BYTE a64 = regs->psw.amode64; /* ("64-bit mode" flag) */ #endif BYTE op_size = CFC_OPSIZE; /* (work constant; uses a64) */ BYTE gr2_shift = CFC_GR2_SHIFT; /* (work constant; uses a64) */ GREG gr2_high_bit = CFC_HIGH_BIT; /* (work constant; uses a64) */ S(inst, regs, b2, op2_effective_addr); /* All operands must be halfword aligned */ if (0 || GR_A(1,regs) & 1 || GR_A(2,regs) & 1 || GR_A(3,regs) & 1 ) regs->program_interrupt (regs, PGM_SPECIFICATION_EXCEPTION); /* Initialize "end-of-operand-data" index value... */ max_index = op2_effective_addr & 0x7FFE; /* Loop until we either locate where the two operands differ from one another or until we reach the end of the operand data... */ do { /* Exit w/cc0 (op1==op3) when end of operands are reached */ index = GR_A(2,regs) & 0xFFFF; if ( index > max_index ) { regs->psw.cc = 0; // (operands are equal to each other) SET_GR_A( 2, regs, GR_A(3,regs) | gr2_high_bit ); return; } /* Fetch next chunk of operand data... */ op1_addr = ( regs->GR(1) + index ) & ADDRESS_MAXWRAP(regs); op3_addr = ( regs->GR(3) + index ) & ADDRESS_MAXWRAP(regs); ARCH_DEP( vfetchc )( op1, op_size - 1, op1_addr, AR1, regs ); ARCH_DEP( vfetchc )( op3, op_size - 1, op3_addr, AR1, regs ); /* Update GR2 operand index value... (Note: we must do this AFTER we fetch the operand data in case of storage access exceptions) */ SET_GR_A( 2, regs, GR_A(2,regs) + op_size ); /* Compare operands; continue while still equal... */ } while ( !( rc = memcmp( op1, op3, op_size ) ) ); /* Operands are NOT equal (we found an inequality). Set the condition code, form our codeword, and then exit */ ASSERT( rc != 0 ); // (we shouldn't be here unless this is true!) /* Check to see which sequence the operands should be sorted into so we can know whether or not we need to form our codeword using either the inverse of the higher operand's data (if doing an ascending sort), or the lower operand's data AS-IS (if doing a descending sort). This thus causes either the lower (or higher) operand values (depending on which type of sort we're doing, ascending or descending) to bubble to the top (beginning) of the tree that the UPT (Update Tree) instruction ultimately/eventually updates (which gets built from our codewords). */ descending = op2_effective_addr & 1; // (0==ascending, 1==descending) if ( rc < 0 ) // (operand-1 < operand-3) { if ( !descending ) // (ascending; in sequence) { regs->psw.cc = 1; // (cc1 == in sequence) /* Ascending sort: use inverse of higher operand's data */ for ( i=0; i < op_size; i++ ) tmp[i] = ~op3[i]; } else // (descending; out-of-sequence) { regs->psw.cc = 2; // (cc2 == out-of-sequence) /* Descending sort: use lower operand's data as-is */ memcpy( tmp, op1, op_size ); /* Swap GR1 & GR3 because out-of-sequence */ work_reg = GR_A(1,regs); SET_GR_A( 1, regs, GR_A(3,regs) ); SET_GR_A( 3, regs, work_reg ); } } else // (operand-1 > operand-3) { if ( !descending ) // (ascending; out-of-sequence) { regs->psw.cc = 2; // (cc2 == out-of-sequence) /* Ascending sort: use inverse of higher operand's data */ for ( i=0; i < op_size; i++ ) tmp[i] = ~op1[i]; /* Swap GR1 & GR3 because out-of-sequence */ work_reg = GR_A(1,regs); SET_GR_A( 1, regs, GR_A(3,regs) ); SET_GR_A( 3, regs, work_reg ); } else // (descending; in sequence) { regs->psw.cc = 1; // (cc1 == in sequence) /* Descending sort: use lower operand's data as-is */ memcpy( tmp, op3, op_size ); } } /* Form a sort/merge codeword to be used to sort the two operands into their proper sequence consisting of a combination of both the index position where the inequality was found (current GR2 value) and either the one's complement inverse of the higher operand's data (if doing an ascending sort) or the lower oper- and's data as-is (if doing a descending sort)... */ for ( work_reg=0, i=0; i < op_size; i++ ) work_reg = ( work_reg << 8 ) | tmp[i]; SET_GR_A( 2, regs, ( GR_A(2,regs) << gr2_shift ) | work_reg ); } /*-------------------------------------------------------------------*/ /* BA CS - Compare and Swap [RS] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_and_swap) { int r1, r3; /* Register numbers */ int b2; /* effective address base */ VADR addr2; /* effective address */ BYTE *main2; /* mainstor address */ U32 old; /* old value */ RS(inst, regs, r1, r3, b2, addr2); FW_CHECK(addr2, regs); ITIMER_SYNC(addr2,4-1,regs); /* Perform serialization before starting operation */ PERFORM_SERIALIZATION (regs); /* Get mainstor address */ main2 = MADDR (addr2, b2, regs, ACCTYPE_WRITE, regs->psw.pkey); old = CSWAP32(regs->GR_L(r1)); /* Obtain main-storage access lock */ OBTAIN_MAINLOCK(regs); /* Attempt to exchange the values */ regs->psw.cc = cmpxchg4 (&old, CSWAP32(regs->GR_L(r3)), main2); /* Release main-storage access lock */ RELEASE_MAINLOCK(regs); /* Perform serialization after completing operation */ PERFORM_SERIALIZATION (regs); if (regs->psw.cc == 1) { PTT(PTT_CL_CSF,"*CS",regs->GR_L(r1),regs->GR_L(r3),(U32)(addr2 & 0xffffffff)); regs->GR_L(r1) = CSWAP32(old); #if defined(_FEATURE_SIE) if(SIE_STATB(regs, IC0, CS1)) { if( !OPEN_IC_PER(regs) ) longjmp(regs->progjmp, SIE_INTERCEPT_INST); else longjmp(regs->progjmp, SIE_INTERCEPT_INSTCOMP); } else #endif /*defined(_FEATURE_SIE)*/ if (sysblk.cpus > 1) sched_yield(); } else { ITIMER_UPDATE(addr2,4-1,regs); } } /*-------------------------------------------------------------------*/ /* BB CDS - Compare Double and Swap [RS] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_double_and_swap) { int r1, r3; /* Register numbers */ int b2; /* effective address base */ VADR addr2; /* effective address */ BYTE *main2; /* mainstor address */ U64 old, new; /* old, new values */ RS(inst, regs, r1, r3, b2, addr2); ODD2_CHECK(r1, r3, regs); DW_CHECK(addr2, regs); ITIMER_SYNC(addr2,8-1,regs); /* Perform serialization before starting operation */ PERFORM_SERIALIZATION (regs); /* Get operand absolute address */ main2 = MADDR (addr2, b2, regs, ACCTYPE_WRITE, regs->psw.pkey); /* Get old, new values */ old = CSWAP64(((U64)(regs->GR_L(r1)) << 32) | regs->GR_L(r1+1)); new = CSWAP64(((U64)(regs->GR_L(r3)) << 32) | regs->GR_L(r3+1)); /* Obtain main-storage access lock */ OBTAIN_MAINLOCK(regs); /* Attempt to exchange the values */ regs->psw.cc = cmpxchg8 (&old, new, main2); /* Release main-storage access lock */ RELEASE_MAINLOCK(regs); /* Perform serialization after completing operation */ PERFORM_SERIALIZATION (regs); if (regs->psw.cc == 1) { PTT(PTT_CL_CSF,"*CDS",regs->GR_L(r1),regs->GR_L(r3),(U32)(addr2 & 0xffffffff)); regs->GR_L(r1) = CSWAP64(old) >> 32; regs->GR_L(r1+1) = CSWAP64(old) & 0xffffffff; #if defined(_FEATURE_SIE) if(SIE_STATB(regs, IC0, CS1)) { if( !OPEN_IC_PER(regs) ) longjmp(regs->progjmp, SIE_INTERCEPT_INST); else longjmp(regs->progjmp, SIE_INTERCEPT_INSTCOMP); } else #endif /*defined(_FEATURE_SIE)*/ if (sysblk.cpus > 1) sched_yield(); } else { ITIMER_UPDATE(addr2,8-1,regs); } } #if defined(FEATURE_COMPARE_AND_SWAP_AND_STORE) #if defined(FEATURE_COMPARE_AND_SWAP_AND_STORE_FACILITY_2) #define MAX_CSST_FC 2 #define MAX_CSST_SC 4 #else #define MAX_CSST_FC 1 #define MAX_CSST_SC 3 #endif /*-------------------------------------------------------------------*/ /* C8x2 CSST - Compare and Swap and Store [SSF] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_and_swap_and_store) { int r3; /* Value of R3 field */ int b1, b2; /* Base registers */ const int rp=1; /* Parameter list register */ VADR addr1, addr2; /* Effective addresses */ VADR addrp; /* Parameter list address */ BYTE *main1; /* Mainstor address of op1 */ int ln2; /* Second operand length - 1 */ U64 old16l=0, old16h=0, new16l=0, new16h=0; /* swap values for cmpxchg16 */ U64 old8=0, new8=0; /* Swap values for cmpxchg8 */ U32 old4=0, new4=0; /* Swap values for cmpxchg4 */ U64 stv16h=0,stv16l=0; /* 16-byte store value pair */ U64 stv8=0; /* 8-byte store value */ U32 stv4=0; /* 4-byte store value */ U16 stv2=0; /* 2-byte store value */ BYTE stv1=0; /* 1-byte store value */ BYTE fc; /* Function code */ BYTE sc; /* Store characteristic */ SSF(inst, regs, b1, addr1, b2, addr2, r3); /* Extract function code from register 0 bits 56-63 */ fc = regs->GR_LHLCL(0); /* Extract store characteristic from register 0 bits 48-55 */ sc = regs->GR_LHLCH(0); /* Program check if function code is not 0 or 1 */ if (fc > MAX_CSST_FC) regs->program_interrupt (regs, PGM_SPECIFICATION_EXCEPTION); /* Program check if store characteristic is not 0, 1, 2, or 3 */ if (sc > MAX_CSST_SC) regs->program_interrupt (regs, PGM_SPECIFICATION_EXCEPTION); /* Calculate length minus 1 of second operand */ ln2 = (1 << sc) - 1; /* Program check if first operand is not on correct boundary */ switch(fc) { case 0: FW_CHECK(addr1, regs); break; case 1: DW_CHECK(addr1, regs); break; #if defined(FEATURE_COMPARE_AND_SWAP_AND_STORE_FACILITY_2) case 2: QW_CHECK(addr1, regs); break; #endif } #if defined(FEATURE_COMPARE_AND_SWAP_AND_STORE_FACILITY_2) if(r3 & 1) { regs->program_interrupt (regs, PGM_SPECIFICATION_EXCEPTION); } #endif /* Program check if second operand is not on correct boundary */ switch(sc) { case 1: HW_CHECK(addr2, regs); break; case 2: FW_CHECK(addr2, regs); break; case 3: DW_CHECK(addr2, regs); break; #if defined(FEATURE_COMPARE_AND_SWAP_AND_STORE_FACILITY_2) case 4: QW_CHECK(addr2, regs); break; #endif } /* Perform serialization before starting operation */ PERFORM_SERIALIZATION (regs); /* Obtain parameter list address from register 1 bits 0-59 */ addrp = regs->GR(rp) & 0xFFFFFFFFFFFFFFF0ULL & ADDRESS_MAXWRAP(regs); /* Obtain main storage address of first operand */ main1 = MADDR (addr1, b1, regs, ACCTYPE_WRITE, regs->psw.pkey); /* Ensure second operand storage is writable */ ARCH_DEP(validate_operand) (addr2, b2, ln2, ACCTYPE_WRITE_SKP, regs); /* Obtain main-storage access lock */ OBTAIN_MAINLOCK(regs); /* Load the compare value from the r3 register and also */ /* load replacement value from bytes 0-3, 0-7 or 0-15 of parameter list */ switch(fc) { case 0: old4 = CSWAP32(regs->GR_L(r3)); new4 = ARCH_DEP(vfetch4) (addrp, rp, regs); new4 = CSWAP32(new4); break; case 1: old8 = CSWAP64(regs->GR_G(r3)); new8 = ARCH_DEP(vfetch8) (addrp, rp, regs); new8 = CSWAP64(new8); break; #if defined(FEATURE_COMPARE_AND_SWAP_AND_STORE_FACILITY_2) case 2: old16h = CSWAP64(regs->GR_G(r3)); old16l = CSWAP64(regs->GR_G(r3+1)); new16h = ARCH_DEP(vfetch8) (addrp, rp, regs); new16l = ARCH_DEP(vfetch8) (addrp+8, rp, regs); new16h = CSWAP64(new16h); new16l = CSWAP64(new16l); break; #endif } /* Load the store value from bytes 16-23 of parameter list */ addrp += 16; addrp = addrp & ADDRESS_MAXWRAP(regs); switch(sc) { case 0: stv1 = ARCH_DEP(vfetchb) (addrp, rp, regs); break; case 1: stv2 = ARCH_DEP(vfetch2) (addrp, rp, regs); break; case 2: stv4 = ARCH_DEP(vfetch4) (addrp, rp, regs); break; case 3: stv8 = ARCH_DEP(vfetch8) (addrp, rp, regs); break; #if defined(FEATURE_COMPARE_AND_SWAP_AND_STORE_FACILITY_2) case 4: stv16h = ARCH_DEP(vfetch8) (addrp, rp, regs); stv16l = ARCH_DEP(vfetch8) (addrp+8, rp, regs); break; #endif } switch(fc) { case 0: regs->psw.cc = cmpxchg4 (&old4, new4, main1); break; case 1: regs->psw.cc = cmpxchg8 (&old8, new8, main1); break; #if defined(FEATURE_COMPARE_AND_SWAP_AND_STORE_FACILITY_2) case 2: regs->psw.cc = cmpxchg16 (&old16h, &old16l, new16h, new16l, main1); break; #endif } if (regs->psw.cc == 0) { /* Store the store value into the second operand location */ switch(sc) { case 0: ARCH_DEP(vstoreb) (stv1, addr2, b2, regs); break; case 1: ARCH_DEP(vstore2) (stv2, addr2, b2, regs); break; case 2: ARCH_DEP(vstore4) (stv4, addr2, b2, regs); break; case 3: ARCH_DEP(vstore8) (stv8, addr2, b2, regs); break; #if defined(FEATURE_COMPARE_AND_SWAP_AND_STORE_FACILITY_2) case 4: ARCH_DEP(vstore8) (stv16h, addr2, b2, regs); ARCH_DEP(vstore8) (stv16l, addr2+8, b2, regs); break; #endif } } else { switch(fc) { case 0: regs->GR_L(r3) = CSWAP32(old4); break; case 1: regs->GR_G(r3) = CSWAP64(old8); break; #if defined(FEATURE_COMPARE_AND_SWAP_AND_STORE_FACILITY_2) case 2: regs->GR_G(r3) = CSWAP64(old16h); regs->GR_G(r3+1) = CSWAP64(old16l); break; #endif } } /* Release main-storage access lock */ RELEASE_MAINLOCK(regs); /* Perform serialization after completing operation */ PERFORM_SERIALIZATION (regs); } /* end DEF_INST(compare_and_swap_and_store) */ #endif /*defined(FEATURE_COMPARE_AND_SWAP_AND_STORE)*/ /*-------------------------------------------------------------------*/ /* 49 CH - Compare Halfword [RX] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_halfword) { int r1; /* Values of R fields */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ S32 n; /* 32-bit operand values */ RX(inst, regs, r1, b2, effective_addr2); /* Load rightmost 2 bytes of comparand from operand address */ n = (S16)ARCH_DEP(vfetch2) ( effective_addr2, b2, regs ); /* Compare signed operands and set condition code */ regs->psw.cc = (S32)regs->GR_L(r1) < n ? 1 : (S32)regs->GR_L(r1) > n ? 2 : 0; } #if defined(FEATURE_IMMEDIATE_AND_RELATIVE) /*-------------------------------------------------------------------*/ /* A7xE CHI - Compare Halfword Immediate [RI] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_halfword_immediate) { int r1; /* Register number */ int opcd; /* Opcode */ U16 i2; /* 16-bit operand */ RI0(inst, regs, r1, opcd, i2); /* Compare signed operands and set condition code */ regs->psw.cc = (S32)regs->GR_L(r1) < (S16)i2 ? 1 : (S32)regs->GR_L(r1) > (S16)i2 ? 2 : 0; } #endif /*defined(FEATURE_IMMEDIATE_AND_RELATIVE)*/ /*-------------------------------------------------------------------*/ /* 15 CLR - Compare Logical Register [RR] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_logical_register) { int r1, r2; /* Values of R fields */ RR0(inst, regs, r1, r2); /* Compare unsigned operands and set condition code */ regs->psw.cc = regs->GR_L(r1) < regs->GR_L(r2) ? 1 : regs->GR_L(r1) > regs->GR_L(r2) ? 2 : 0; } /*-------------------------------------------------------------------*/ /* 55 CL - Compare Logical [RX] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_logical) { int r1; /* Values of R fields */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ U32 n; /* 32-bit operand values */ RX(inst, regs, r1, b2, effective_addr2); /* Load second operand from operand address */ n = ARCH_DEP(vfetch4) ( effective_addr2, b2, regs ); /* Compare unsigned operands and set condition code */ regs->psw.cc = regs->GR_L(r1) < n ? 1 : regs->GR_L(r1) > n ? 2 : 0; } /*-------------------------------------------------------------------*/ /* 95 CLI - Compare Logical Immediate [SI] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_logical_immediate) { BYTE i2; /* Immediate byte */ int b1; /* Base of effective addr */ VADR effective_addr1; /* Effective address */ BYTE cbyte; /* Compare byte */ SI(inst, regs, i2, b1, effective_addr1); /* Fetch byte from operand address */ cbyte = ARCH_DEP(vfetchb) ( effective_addr1, b1, regs ); /* Compare with immediate operand and set condition code */ regs->psw.cc = (cbyte < i2) ? 1 : (cbyte > i2) ? 2 : 0; } /*-------------------------------------------------------------------*/ /* D5 CLC - Compare Logical Character [SS] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_logical_character) { unsigned int len, len1, len2; /* Lengths */ int rc; /* memcmp() return code */ int b1, b2; /* Base registers */ VADR ea1, ea2; /* Effective addresses */ BYTE *m1, *m2; /* Mainstor addresses */ SS_L(inst, regs, len, b1, ea1, b2, ea2); ITIMER_SYNC(ea1,len,regs); ITIMER_SYNC(ea2,len,regs); /* Translate addresses of leftmost operand bytes */ m1 = MADDR (ea1, b1, regs, ACCTYPE_READ, regs->psw.pkey); m2 = MADDR (ea2, b2, regs, ACCTYPE_READ, regs->psw.pkey); /* Quick out if comparing just 1 byte */ if (unlikely(len == 0)) { rc = *m1 - *m2; regs->psw.cc = ( rc == 0 ? 0 : ( rc < 0 ? 1 : 2 ) ); return; } /* There are several scenarios (in optimal order): * (1) dest boundary and source boundary not crossed * (a) halfword compare * (b) fullword compare * (c) doubleword compare (64-bit machines) * (d) other * (2) dest boundary not crossed and source boundary crossed * (3) dest boundary crossed and source boundary not crossed * (4) dest boundary and source boundary are crossed * (a) dest and source boundary cross at the same time * (b) dest boundary crossed first * (c) source boundary crossed first */ if ( (ea1 & 0x7FF) <= 0x7FF - len ) { if ( (ea2 & 0x7FF) <= 0x7FF - len ) { /* (1) - No boundaries are crossed */ switch(len) { case 1: /* (1a) - halfword compare */ { U16 v1, v2; v1 = fetch_hw(m1); v2 = fetch_hw(m2); regs->psw.cc = ( v1 == v2 ? 0 : ( v1 < v2 ? 1 : 2 ) ); return; } break; case 3: /* (1b) - fullword compare */ { U32 v1, v2; v1 = fetch_fw(m1); v2 = fetch_fw(m2); regs->psw.cc = ( v1 == v2 ? 0 : ( v1 < v2 ? 1 : 2 ) ); return; } break; case 7: /* (1c) - doubleword compare (64-bit machines) */ if (sizeof(unsigned int) >= 8) { U64 v1, v2; v1 = fetch_dw(m1); v2 = fetch_dw(m2); regs->psw.cc = ( v1 == v2 ? 0 : ( v1 < v2 ? 1 : 2 ) ); return; } default: /* (1d) - other compare */ rc = memcmp(m1, m2, len + 1); break; } } else { /* (2) - Second operand crosses a boundary */ len2 = 0x800 - (ea2 & 0x7FF); rc = memcmp(m1, m2, len2); if (rc == 0) { m2 = MADDR ((ea2 + len2) & ADDRESS_MAXWRAP(regs), b2, regs, ACCTYPE_READ, regs->psw.pkey); rc = memcmp(m1 + len2, m2, len - len2 + 1); } } } else { /* First operand crosses a boundary */ len1 = 0x800 - (ea1 & 0x7FF); if ( (ea2 & 0x7FF) <= 0x7FF - len ) { /* (3) - First operand crosses a boundary */ rc = memcmp(m1, m2, len1); if (rc == 0) { m1 = MADDR ((ea1 + len1) & ADDRESS_MAXWRAP(regs), b1, regs, ACCTYPE_READ, regs->psw.pkey); rc = memcmp(m1, m2 + len1, len - len1 + 1); } } else { /* (4) - Both operands cross a boundary */ len2 = 0x800 - (ea2 & 0x7FF); if (len1 == len2) { /* (4a) - Both operands cross at the same time */ rc = memcmp(m1, m2, len1); if (rc == 0) { m1 = MADDR ((ea1 + len1) & ADDRESS_MAXWRAP(regs), b1, regs, ACCTYPE_READ, regs->psw.pkey); m2 = MADDR ((ea2 + len1) & ADDRESS_MAXWRAP(regs), b2, regs, ACCTYPE_READ, regs->psw.pkey); rc = memcmp(m1, m2, len - len1 +1); } } else if (len1 < len2) { /* (4b) - First operand crosses first */ rc = memcmp(m1, m2, len1); if (rc == 0) { m1 = MADDR ((ea1 + len1) & ADDRESS_MAXWRAP(regs), b1, regs, ACCTYPE_READ, regs->psw.pkey); rc = memcmp (m1, m2 + len1, len2 - len1); } if (rc == 0) { m2 = MADDR ((ea2 + len2) & ADDRESS_MAXWRAP(regs), b2, regs, ACCTYPE_READ, regs->psw.pkey); rc = memcmp (m1 + len2 - len1, m2, len - len2 + 1); } } else { /* (4c) - Second operand crosses first */ rc = memcmp(m1, m2, len2); if (rc == 0) { m2 = MADDR ((ea2 + len2) & ADDRESS_MAXWRAP(regs), b2, regs, ACCTYPE_READ, regs->psw.pkey); rc = memcmp (m1 + len2, m2, len1 - len2); } if (rc == 0) { m1 = MADDR ((ea1 + len1) & ADDRESS_MAXWRAP(regs), b1, regs, ACCTYPE_READ, regs->psw.pkey); rc = memcmp (m1, m2 + len1 - len2, len - len1 + 1); } } } } regs->psw.cc = ( rc == 0 ? 0 : ( rc < 0 ? 1 : 2 ) ); } /*-------------------------------------------------------------------*/ /* BD CLM - Compare Logical Characters under Mask [RS] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_logical_characters_under_mask) { int r1, r3; /* Register numbers */ int b2; /* effective address base */ VADR effective_addr2; /* effective address */ int i, j; /* Integer work areas */ int cc = 0; /* Condition code */ BYTE rbyte[4], /* Register bytes */ vbyte; /* Virtual storage byte */ RS(inst, regs, r1, r3, b2, effective_addr2); /* Set register bytes by mask */ i = 0; if (r3 & 0x8) rbyte[i++] = (regs->GR_L(r1) >> 24) & 0xFF; if (r3 & 0x4) rbyte[i++] = (regs->GR_L(r1) >> 16) & 0xFF; if (r3 & 0x2) rbyte[i++] = (regs->GR_L(r1) >> 8) & 0xFF; if (r3 & 0x1) rbyte[i++] = (regs->GR_L(r1) ) & 0xFF; /* Perform access check if mask is 0 */ if (!r3) ARCH_DEP(vfetchb) (effective_addr2, b2, regs); /* Compare byte by byte */ for (j = 0; j < i && !cc; j++) { effective_addr2 &= ADDRESS_MAXWRAP(regs); vbyte = ARCH_DEP(vfetchb) (effective_addr2++, b2, regs); if (rbyte[j] != vbyte) cc = rbyte[j] < vbyte ? 1 : 2; } regs->psw.cc = cc; } /*-------------------------------------------------------------------*/ /* 0F CLCL - Compare Logical Long [RR] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_logical_character_long) { int r1, r2; /* Values of R fields */ int cc = 0; /* Condition code */ VADR addr1, addr2; /* Operand addresses */ U32 len1, len2; /* Operand lengths */ BYTE byte1, byte2; /* Operand bytes */ BYTE pad; /* Padding byte */ RR(inst, regs, r1, r2); ODD2_CHECK(r1, r2, regs); /* Determine the destination and source addresses */ addr1 = regs->GR(r1) & ADDRESS_MAXWRAP(regs); addr2 = regs->GR(r2) & ADDRESS_MAXWRAP(regs); /* Load padding byte from bits 0-7 of R2+1 register */ pad = regs->GR_LHHCH(r2+1); /* Load operand lengths from bits 8-31 of R1+1 and R2+1 */ len1 = regs->GR_LA24(r1+1); len2 = regs->GR_LA24(r2+1); /* Process operands from left to right */ while (len1 > 0 || len2 > 0) { /* Fetch a byte from each operand, or use padding byte */ byte1 = (len1 > 0) ? ARCH_DEP(vfetchb) (addr1, r1, regs) : pad; byte2 = (len2 > 0) ? ARCH_DEP(vfetchb) (addr2, r2, regs) : pad; /* Compare operand bytes, set condition code if unequal */ if (byte1 != byte2) { cc = (byte1 < byte2) ? 1 : 2; break; } /* end if */ /* Update the first operand address and length */ if (len1 > 0) { addr1++; addr1 &= ADDRESS_MAXWRAP(regs); len1--; } /* Update the second operand address and length */ if (len2 > 0) { addr2++; addr2 &= ADDRESS_MAXWRAP(regs); len2--; } /* Update Regs if cross half page - may get access rupt */ if ((addr1 & 0x7ff) == 0 || (addr2 & 0x7ff) == 0) { SET_GR_A(r1, regs, addr1); SET_GR_A(r2, regs, addr2); regs->GR_LA24(r1+1) = len1; regs->GR_LA24(r2+1) = len2; } /* The instruction can be interrupted when a CPU determined number of bytes have been processed. The instruction address will be backed up, and the instruction will be re-executed. This is consistent with operation under a hypervisor such as LPAR or VM. *JJ */ if ((len1 + len2 > 255) && !((addr1 - len2) & 0xFFF)) { UPD_PSW_IA (regs, PSW_IA(regs, -REAL_ILC(regs))); break; } } /* end while(len1||len2) */ /* Update the registers */ SET_GR_A(r1, regs,addr1); SET_GR_A(r2, regs,addr2); regs->GR_LA24(r1+1) = len1; regs->GR_LA24(r2+1) = len2; regs->psw.cc = cc; } #if defined(FEATURE_COMPARE_AND_MOVE_EXTENDED) /*-------------------------------------------------------------------*/ /* A9 CLCLE - Compare Logical Long Extended [RS] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_logical_long_extended) { int r1, r3; /* Register numbers */ int b2; /* effective address base */ VADR effective_addr2; /* effective address */ int i; /* Loop counter */ int cc = 0; /* Condition code */ VADR addr1, addr2; /* Operand addresses */ GREG len1, len2; /* Operand lengths */ BYTE byte1, byte2; /* Operand bytes */ BYTE pad; /* Padding byte */ RS(inst, regs, r1, r3, b2, effective_addr2); ODD2_CHECK(r1, r3, regs); /* Load padding byte from bits 24-31 of effective address */ pad = effective_addr2 & 0xFF; /* Determine the destination and source addresses */ addr1 = regs->GR(r1) & ADDRESS_MAXWRAP(regs); addr2 = regs->GR(r3) & ADDRESS_MAXWRAP(regs); /* Load operand lengths from bits 0-31 of R1+1 and R3+1 */ len1 = GR_A(r1+1, regs); len2 = GR_A(r3+1, regs); /* Process operands from left to right */ for (i = 0; len1 > 0 || len2 > 0 ; i++) { /* If 4096 bytes have been compared, exit with cc=3 */ if (i >= 4096) { cc = 3; break; } /* Fetch a byte from each operand, or use padding byte */ byte1 = (len1 > 0) ? ARCH_DEP(vfetchb) (addr1, r1, regs) : pad; byte2 = (len2 > 0) ? ARCH_DEP(vfetchb) (addr2, r3, regs) : pad; /* Compare operand bytes, set condition code if unequal */ if (byte1 != byte2) { cc = (byte1 < byte2) ? 1 : 2; break; } /* end if */ /* Update the first operand address and length */ if (len1 > 0) { addr1++; addr1 &= ADDRESS_MAXWRAP(regs); len1--; } /* Update the second operand address and length */ if (len2 > 0) { addr2++; addr2 &= ADDRESS_MAXWRAP(regs); len2--; } } /* end for(i) */ /* Update the registers */ SET_GR_A(r1, regs,addr1); SET_GR_A(r1+1, regs,len1); SET_GR_A(r3, regs,addr2); SET_GR_A(r3+1, regs,len2); regs->psw.cc = cc; } #endif /*defined(FEATURE_COMPARE_AND_MOVE_EXTENDED)*/ #if defined(FEATURE_STRING_INSTRUCTION) /*-------------------------------------------------------------------*/ /* B25D CLST - Compare Logical String [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_logical_string) { int r1, r2; /* Values of R fields */ int i; /* Loop counter */ int cc; /* Condition code */ VADR addr1, addr2; /* Operand addresses */ BYTE byte1, byte2; /* Operand bytes */ BYTE termchar; /* Terminating character */ RRE(inst, regs, r1, r2); /* Program check if bits 0-23 of register 0 not zero */ if ((regs->GR_L(0) & 0xFFFFFF00) != 0) regs->program_interrupt (regs, PGM_SPECIFICATION_EXCEPTION); /* Load string terminating character from register 0 bits 24-31 */ termchar = regs->GR_LHLCL(0); /* Determine the operand addresses */ addr1 = regs->GR(r1) & ADDRESS_MAXWRAP(regs); addr2 = regs->GR(r2) & ADDRESS_MAXWRAP(regs); /* Initialize the condition code to 3 */ cc = 3; /* Compare up to 4096 bytes until terminating character */ for (i = 0; i < 4096; i++) { /* Fetch a byte from each operand */ byte1 = ARCH_DEP(vfetchb) ( addr1, r1, regs ); byte2 = ARCH_DEP(vfetchb) ( addr2, r2, regs ); /* If both bytes are the terminating character then the strings are equal so return condition code 0 and leave the R1 and R2 registers unchanged */ if (byte1 == termchar && byte2 == termchar) { regs->psw.cc = 0; return; } /* If first operand byte is the terminating character, or if the first operand byte is lower than the second operand byte, then return condition code 1 */ if (byte1 == termchar || ((byte1 < byte2) && (byte2 != termchar))) { cc = 1; break; } /* If second operand byte is the terminating character, or if the first operand byte is higher than the second operand byte, then return condition code 2 */ if (byte2 == termchar || byte1 > byte2) { cc = 2; break; } /* Increment operand addresses */ addr1++; addr1 &= ADDRESS_MAXWRAP(regs); addr2++; addr2 &= ADDRESS_MAXWRAP(regs); } /* end for(i) */ /* Set R1 and R2 to point to current character of each operand */ SET_GR_A(r1, regs,addr1); SET_GR_A(r2, regs,addr2); /* Set condition code */ regs->psw.cc = cc; } /* end DEF_INST(compare_logical_string) */ #endif /*defined(FEATURE_STRING_INSTRUCTION)*/ #if defined(FEATURE_STRING_INSTRUCTION) /*-------------------------------------------------------------------*/ /* B257 CUSE - Compare Until Substring Equal [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_until_substring_equal) { int r1, r2; /* Values of R fields */ int i; /* Loop counter */ int cc = 0; /* Condition code */ VADR addr1, addr2; /* Operand addresses */ BYTE byte1, byte2; /* Operand bytes */ BYTE pad; /* Padding byte */ BYTE sublen; /* Substring length */ BYTE equlen = 0; /* Equal byte counter */ VADR eqaddr1, eqaddr2; /* Address of equal substring*/ #if defined(FEATURE_ESAME) S64 len1, len2; /* Operand lengths */ S64 remlen1, remlen2; /* Lengths remaining */ #else /*!defined(FEATURE_ESAME)*/ S32 len1, len2; /* Operand lengths */ S32 remlen1, remlen2; /* Lengths remaining */ #endif /*!defined(FEATURE_ESAME)*/ RRE(inst, regs, r1, r2); ODD2_CHECK(r1, r2, regs); /* Load substring length from bits 24-31 of register 0 */ sublen = regs->GR_LHLCL(0); /* Load padding byte from bits 24-31 of register 1 */ pad = regs->GR_LHLCL(1); /* Determine the destination and source addresses */ addr1 = regs->GR(r1) & ADDRESS_MAXWRAP(regs); addr2 = regs->GR(r2) & ADDRESS_MAXWRAP(regs); /* update regs so unused bits zeroed */ SET_GR_A(r1, regs,addr1); SET_GR_A(r2, regs,addr2); /* Load signed operand lengths from R1+1 and R2+1 */ len1 = #if defined(FEATURE_ESAME) regs->psw.amode64 ? (S64)(regs->GR_G(r1+1)) : #endif /*defined(FEATURE_ESAME)*/ (S32)(regs->GR_L(r1+1)); len2 = #if defined(FEATURE_ESAME) regs->psw.amode64 ? (S64)(regs->GR_G(r2+1)) : #endif /*defined(FEATURE_ESAME)*/ (S32)(regs->GR_L(r2+1)); /* Initialize equal string addresses and lengths */ eqaddr1 = addr1; eqaddr2 = addr2; remlen1 = len1; remlen2 = len2; /* If substring length is zero, exit with condition code 0 */ if (sublen == 0) { regs->psw.cc = 0; return; } /* If both operand lengths are zero, exit with condition code 2 */ if (len1 <= 0 && len2 <= 0) { regs->psw.cc = 2; return; } /* If r1=r2, exit with condition code 0 or 1*/ if (r1 == r2) { regs->psw.cc = (len1 < sublen) ? 1 : 0; return; } /* Process operands from left to right */ for (i = 0; len1 > 0 || len2 > 0 ; i++) { /* If 4096 bytes have been compared, and the last bytes compared were unequal, exit with condition code 3 */ if (equlen == 0 && i >= 4096) { cc = 3; break; } /* Fetch byte from first operand, or use padding byte */ if (len1 > 0) byte1 = ARCH_DEP(vfetchb) ( addr1, r1, regs ); else byte1 = pad; /* Fetch byte from second operand, or use padding byte */ if (len2 > 0) byte2 = ARCH_DEP(vfetchb) ( addr2, r2, regs ); else byte2 = pad; /* Test if bytes compare equal */ if (byte1 == byte2) { /* If this is the first equal byte, save the start of substring addresses and remaining lengths */ if (equlen == 0) { eqaddr1 = addr1; eqaddr2 = addr2; remlen1 = len1; remlen2 = len2; } /* Count the number of equal bytes */ equlen++; /* Set condition code 1 */ cc = 1; } else { /* Reset equal byte count and set condition code 2 */ equlen = 0; cc = 2; } /* Update the first operand address and length */ if (len1 > 0) { addr1++; addr1 &= ADDRESS_MAXWRAP(regs); len1--; } /* Update the second operand address and length */ if (len2 > 0) { addr2++; addr2 &= ADDRESS_MAXWRAP(regs); len2--; } /* update GPRs if we just crossed half page - could get rupt */ if ((addr1 & 0x7FF) == 0 || (addr2 & 0x7FF) == 0) { /* Update R1 and R2 to point to next bytes to compare */ SET_GR_A(r1, regs,addr1); SET_GR_A(r2, regs,addr2); /* Set R1+1 and R2+1 to remaining operand lengths */ SET_GR_A(r1+1, regs,len1); SET_GR_A(r2+1, regs,len2); } /* If equal byte count has reached substring length exit with condition code zero */ if (equlen == sublen) { cc = 0; break; } } /* end for(i) */ /* Update the registers */ if (cc < 2) { /* Update R1 and R2 to point to the equal substring */ SET_GR_A(r1, regs,eqaddr1); SET_GR_A(r2, regs,eqaddr2); /* Set R1+1 and R2+1 to length remaining in each operand after the start of the substring */ SET_GR_A(r1+1, regs,remlen1); SET_GR_A(r2+1, regs,remlen2); } else { /* Update R1 and R2 to point to next bytes to compare */ SET_GR_A(r1, regs,addr1); SET_GR_A(r2, regs,addr2); /* Set R1+1 and R2+1 to remaining operand lengths */ SET_GR_A(r1+1, regs,len1); SET_GR_A(r2+1, regs,len2); } /* Set condition code */ regs->psw.cc = cc; } /* end DEF_INST(compare_until_substring_equal) */ #endif /*defined(FEATURE_STRING_INSTRUCTION)*/ #ifdef FEATURE_EXTENDED_TRANSLATION /*-------------------------------------------------------------------*/ /* B2A6 CU21 (CUUTF) - Convert Unicode to UTF-8 [RRF] */ /*-------------------------------------------------------------------*/ DEF_INST(convert_utf16_to_utf8) { int r1, r2; /* Register numbers */ int i; /* Loop counter */ int cc = 0; /* Condition code */ VADR addr1, addr2; /* Operand addresses */ GREG len1, len2; /* Operand lengths */ VADR naddr2; /* Next operand 2 addr */ GREG nlen2; /* Next operand 2 length */ U16 uvwxy; /* Unicode work area */ U16 unicode1; /* Unicode character */ U16 unicode2; /* Unicode low surrogate */ GREG n; /* Number of UTF-8 bytes - 1 */ BYTE utf[4]; /* UTF-8 bytes */ #if defined(FEATURE_ETF3_ENHANCEMENT) int wfc; /* Well-Formedness-Checking */ #endif /*defined(FEATURE_ETF3_ENHANCEMENT)*/ // NOTE: it's faster to decode with RRE format // and then to handle the 'wfc' flag separately... // RRF_M(inst, regs, r1, r2, wfc); RRE(inst, regs, r1, r2); ODD2_CHECK(r1, r2, regs); #if defined(FEATURE_ETF3_ENHANCEMENT) /* Set WellFormednessChecking */ if(inst[2] & 0x10) wfc = 1; else wfc = 0; #endif /*defined(FEATURE_ETF3_ENHANCEMENT)*/ /* Determine the destination and source addresses */ addr1 = regs->GR(r1) & ADDRESS_MAXWRAP(regs); addr2 = regs->GR(r2) & ADDRESS_MAXWRAP(regs); /* Load operand lengths from bits 0-31 of R1+1 and R2+1 */ len1 = GR_A(r1+1, regs); len2 = GR_A(r2+1, regs); if (len1 == 0 && len2 > 1) cc = 1; /* Process operands from left to right */ for (i = 0; len1 > 0 && len2 > 0; i++) { /* If 4096 characters have been converted, exit with cc=3 */ if (i >= 4096) { cc = 3; break; } /* Exit if fewer than 2 bytes remain in source operand */ if (len2 < 2) break; /* Fetch two bytes from source operand */ unicode1 = ARCH_DEP(vfetch2) ( addr2, r2, regs ); naddr2 = addr2 + 2; naddr2 &= ADDRESS_MAXWRAP(regs); nlen2 = len2 - 2; /* Convert Unicode to UTF-8 */ if (unicode1 < 0x0080) { /* Convert Unicode 0000-007F to one UTF-8 byte */ utf[0] = (BYTE)unicode1; n = 0; } else if (unicode1 < 0x0800) { /* Convert Unicode 0080-07FF to two UTF-8 bytes */ utf[0] = (BYTE)0xC0 | (BYTE)(unicode1 >> 6); utf[1] = (BYTE)0x80 | (BYTE)(unicode1 & 0x003F); n = 1; } else if (unicode1 < 0xD800 || unicode1 >= 0xDC00) { /* Convert Unicode 0800-D7FF or DC00-FFFF to three UTF-8 bytes */ utf[0] = (BYTE)0xE0 | (BYTE)(unicode1 >> 12); utf[1] = (BYTE)0x80 | (BYTE)((unicode1 & 0x0FC0) >> 6); utf[2] = (BYTE)0x80 | (BYTE)(unicode1 & 0x003F); n = 2; } else { /* Exit if fewer than 2 bytes remain in source operand */ if (nlen2 < 2) break; /* Fetch the Unicode low surrogate */ unicode2 = ARCH_DEP(vfetch2) ( naddr2, r2, regs ); naddr2 += 2; naddr2 &= ADDRESS_MAXWRAP(regs); nlen2 -= 2; #if defined(FEATURE_ETF3_ENHANCEMENT) /* WellFormdnessChecking */ if(wfc) { if(unicode2 < 0xdc00 || unicode2 > 0xdf00) { regs->psw.cc = 2; return; } } #endif /*defined(FEATURE_ETF3_ENHANCEMENT)*/ /* Convert Unicode surrogate pair to four UTF-8 bytes */ uvwxy = ((unicode1 & 0x03C0) >> 6) + 1; utf[0] = (BYTE)0xF0 | (BYTE)(uvwxy >> 2); utf[1] = (BYTE)0x80 | (BYTE)((uvwxy & 0x0003) << 4) | (BYTE)((unicode1 & 0x003C) >> 2); utf[2] = (BYTE)0x80 | (BYTE)((unicode1 & 0x0003) << 4) | (BYTE)((unicode2 & 0x03C0) >> 6); utf[3] = (BYTE)0x80 | (BYTE)(unicode2 & 0x003F); n = 3; } /* Exit cc=1 if too few bytes remain in destination operand */ if (len1 <= n) { cc = 1; break; } /* Store the result bytes in the destination operand */ ARCH_DEP(vstorec) ( utf, n, addr1, r1, regs ); addr1 += n + 1; addr1 &= ADDRESS_MAXWRAP(regs); len1 -= n + 1; /* Update operand 2 address and length */ addr2 = naddr2; len2 = nlen2; /* Update the registers */ SET_GR_A(r1, regs,addr1); SET_GR_A(r1+1, regs,len1); SET_GR_A(r2, regs,addr2); SET_GR_A(r2+1, regs,len2); if (len1 == 0 && len2 != 0) cc = 1; } /* end for(i) */ regs->psw.cc = cc; } /* end convert_utf16_to_utf8 */ /*-------------------------------------------------------------------*/ /* B2A7 CU12 (CUTFU) - Convert UTF-8 to Unicode [RRF] */ /*-------------------------------------------------------------------*/ DEF_INST(convert_utf8_to_utf16) { int r1, r2; /* Register numbers */ int i; /* Loop counter */ int cc = 0; /* Condition code */ VADR addr1, addr2; /* Operand addresses */ GREG len1, len2; /* Operand lengths */ int pair; /* 1=Store Unicode pair */ U16 uvwxy; /* Unicode work area */ U16 unicode1; /* Unicode character */ U16 unicode2 = 0; /* Unicode low surrogate */ GREG n; /* Number of UTF-8 bytes - 1 */ BYTE utf[4]; /* UTF-8 bytes */ #if defined(FEATURE_ETF3_ENHANCEMENT) int wfc; /* WellFormednessChecking */ #endif /*defined(FEATURE_ETF3_ENHANCEMENT)*/ // NOTE: it's faster to decode with RRE format // and then to handle the 'wfc' flag separately... // RRF_M(inst, regs, r1, r2, wfc); RRE(inst, regs, r1, r2); ODD2_CHECK(r1, r2, regs); #if defined(FEATURE_ETF3_ENHANCEMENT) /* Set WellFormednessChecking */ if(inst[2] & 0x10) wfc = 1; else wfc = 0; #endif /*defined(FEATURE_ETF3_ENHANCEMENT)*/ /* Determine the destination and source addresses */ addr1 = regs->GR(r1) & ADDRESS_MAXWRAP(regs); addr2 = regs->GR(r2) & ADDRESS_MAXWRAP(regs); /* Load operand lengths from bits 0-31 of R1+1 and R2+1 */ len1 = GR_A(r1+1, regs); len2 = GR_A(r2+1, regs); if (len1 == 0 && len2 > 0) cc = 1; /* Process operands from left to right */ for (i = 0; len1 > 0 && len2 > 0; i++) { /* If 4096 characters have been converted, exit with cc=3 */ if (i >= 4096) { cc = 3; break; } /* Fetch first UTF-8 byte from source operand */ utf[0] = ARCH_DEP(vfetchb) ( addr2, r2, regs ); /* Convert UTF-8 to Unicode */ if (utf[0] < (BYTE)0x80) { /* Convert 00-7F to Unicode 0000-007F */ n = 0; unicode1 = utf[0]; pair = 0; } else if ((utf[0] & 0xE0) == 0xC0) { #if defined(FEATURE_ETF3_ENHANCEMENT) /* WellFormdnessChecking */ if(wfc) { if(utf[0] <= 0xc1) { regs->psw.cc = 2; return; } } #endif /*defined(FEATURE_ETF3_ENHANCEMENT)*/ /* Exit if fewer than 2 bytes remain in source operand */ n = 1; if (len2 <= n) break; /* Fetch two UTF-8 bytes from source operand */ ARCH_DEP(vfetchc) ( utf, n, addr2, r2, regs ); #if defined(FEATURE_ETF3_ENHANCEMENT) /* WellFormednessChecking */ if(wfc) { if(utf[1] < 0x80 || utf[1] > 0xbf) { regs->psw.cc = 2; return; } } #endif /*defined(FEATURE_ETF3_ENHANCEMENT)*/ /* Convert C0xx-DFxx to Unicode */ unicode1 = ((U16)(utf[0] & 0x1F) << 6) | ((U16)(utf[1] & 0x3F)); pair = 0; } else if ((utf[0] & 0xF0) == 0xE0) { /* Exit if fewer than 3 bytes remain in source operand */ n = 2; if (len2 <= n) break; /* Fetch three UTF-8 bytes from source operand */ ARCH_DEP(vfetchc) ( utf, n, addr2, r2, regs ); #if defined(FEATURE_ETF3_ENHANCEMENT) /* WellFormdnessChecking */ if(wfc) { if(utf[0] == 0xe0) { if(utf[1] < 0xa0 || utf[1] > 0xbf || utf[2] < 0x80 || utf[2] > 0xbf) { regs->psw.cc = 2; return; } } if((utf[0] >= 0xe1 && utf[0] <= 0xec) || (utf[0] >= 0xee && utf[0] < 0xef)) { if(utf[1] < 0x80 || utf[1] > 0xbf || utf[2] < 0x80 || utf[2] > 0xbf) { regs->psw.cc = 2; return; } } if(utf[0] == 0xed) { if(utf[1] < 0x80 || utf[1] > 0x9f || utf[2] < 0x80 || utf[2] > 0xbf) { regs->psw.cc = 2; return; } } } #endif /*defined(FEATURE_ETF3_ENHANCEMENT)*/ /* Convert E0xxxx-EFxxxx to Unicode */ unicode1 = ((U16)(utf[0]) << 12) | ((U16)(utf[1] & 0x3F) << 6) | ((U16)(utf[2] & 0x3F)); pair = 0; } else if ((utf[0] & 0xF8) == 0xF0) { /* Exit if fewer than 4 bytes remain in source operand */ n = 3; if (len2 <= n) break; /* Fetch four UTF-8 bytes from source operand */ ARCH_DEP(vfetchc) ( utf, n, addr2, r2, regs ); #if defined(FEATURE_ETF3_ENHANCEMENT) /* WellFormdnessChecking */ if(wfc) { if(utf[0] == 0xf0) { if(utf[1] < 0x90 || utf[1] > 0xbf || utf[2] < 0x80 || utf[2] > 0xbf || utf[3] < 0x80 || utf[3] > 0xbf) { regs->psw.cc = 2; return; } } if(utf[0] >= 0xf1 && utf[0] <= 0xf3) { if(utf[1] < 0x80 || utf[1] > 0xbf || utf[2] < 0x80 || utf[2] > 0xbf || utf[3] < 0x80 || utf[3] > 0xbf) { regs->psw.cc = 2; return; } } if(utf[0] == 0xf4) { if(utf[1] < 0x80 || utf[1] > 0x8f || utf[2] < 0x80 || utf[2] > 0xbf || utf[3] < 0x80 || utf[3] > 0xbf) { regs->psw.cc = 2; return; } } } #endif /*defined(FEATURE_ETF3_ENHANCEMENT)*/ /* Convert F0xxxxxx-F7xxxxxx to Unicode surrogate pair */ uvwxy = ((((U16)(utf[0] & 0x07) << 2) | ((U16)(utf[1] & 0x30) >> 4)) - 1) & 0x0F; unicode1 = 0xD800 | (uvwxy << 6) | ((U16)(utf[1] & 0x0F) << 2) | ((U16)(utf[2] & 0x30) >> 4); unicode2 = 0xDC00 | ((U16)(utf[2] & 0x0F) << 6) | ((U16)(utf[3] & 0x3F)); pair = 1; } else { /* Invalid UTF-8 byte 80-BF or F8-FF, exit with cc=2 */ cc = 2; break; } /* Store the result bytes in the destination operand */ if (pair) { /* Exit if fewer than 4 bytes remain in destination */ if (len1 < 4) { cc = 1; break; } /* Store Unicode surrogate pair in destination */ ARCH_DEP(vstore4) ( ((U32)unicode1 << 16) | (U32)unicode2, addr1, r1, regs ); addr1 += 4; addr1 &= ADDRESS_MAXWRAP(regs); len1 -= 4; } else { /* Exit if fewer than 2 bytes remain in destination */ if (len1 < 2) { cc = 1; break; } /* Store Unicode character in destination */ ARCH_DEP(vstore2) ( unicode1, addr1, r1, regs ); addr1 += 2; addr1 &= ADDRESS_MAXWRAP(regs); len1 -= 2; } /* Update operand 2 address and length */ addr2 += n + 1; addr2 &= ADDRESS_MAXWRAP(regs); len2 -= n + 1; /* Update the registers */ SET_GR_A(r1, regs,addr1); SET_GR_A(r1+1, regs,len1); SET_GR_A(r2, regs,addr2); SET_GR_A(r2+1, regs,len2); if (len1 == 0 && len2 != 0) cc = 1; } /* end for(i) */ regs->psw.cc = cc; } /* end convert_utf8_to_utf16 */ #endif /*FEATURE_EXTENDED_TRANSLATION*/ /*-------------------------------------------------------------------*/ /* 4F CVB - Convert to Binary [RX] */ /*-------------------------------------------------------------------*/ DEF_INST(convert_to_binary) { U64 dreg; /* 64-bit result accumulator */ int r1; /* Value of R1 field */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ int ovf; /* 1=overflow */ int dxf; /* 1=data exception */ BYTE dec[8]; /* Packed decimal operand */ RX(inst, regs, r1, b2, effective_addr2); /* Fetch 8-byte packed decimal operand */ ARCH_DEP(vfetchc) (dec, 8-1, effective_addr2, b2, regs); /* Convert 8-byte packed decimal to 64-bit signed binary */ packed_to_binary (dec, 8-1, &dreg, &ovf, &dxf); /* Data exception if invalid digits or sign */ if (dxf) { regs->dxc = DXC_DECIMAL; regs->program_interrupt (regs, PGM_DATA_EXCEPTION); } /* Overflow if result exceeds 31 bits plus sign */ if ((S64)dreg < -2147483648LL || (S64)dreg > 2147483647LL) ovf = 1; /* Store low-order 32 bits of result into R1 register */ regs->GR_L(r1) = dreg & 0xFFFFFFFF; /* Program check if overflow (R1 contains rightmost 32 bits) */ if (ovf) regs->program_interrupt (regs, PGM_FIXED_POINT_DIVIDE_EXCEPTION); } /* end DEF_INST(convert_to_binary) */ /*-------------------------------------------------------------------*/ /* 4E CVD - Convert to Decimal [RX] */ /*-------------------------------------------------------------------*/ DEF_INST(convert_to_decimal) { S64 bin; /* 64-bit signed binary value*/ int r1; /* Value of R1 field */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ BYTE dec[16]; /* Packed decimal result */ RX(inst, regs, r1, b2, effective_addr2); /* Load value of register and sign-extend to 64 bits */ bin = (S64)((S32)(regs->GR_L(r1))); /* Convert to 16-byte packed decimal number */ binary_to_packed (bin, dec); /* Store low 8 bytes of result at operand address */ ARCH_DEP(vstorec) ( dec+8, 8-1, effective_addr2, b2, regs ); } /* end DEF_INST(convert_to_decimal) */ #if defined(FEATURE_ACCESS_REGISTERS) /*-------------------------------------------------------------------*/ /* B24D CPYA - Copy Access [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(copy_access) { int r1, r2; /* Values of R fields */ RRE0(inst, regs, r1, r2); /* Copy R2 access register to R1 access register */ regs->AR(r1) = regs->AR(r2); SET_AEA_AR(regs, r1); } #endif /*defined(FEATURE_ACCESS_REGISTERS)*/ /*-------------------------------------------------------------------*/ /* 1D DR - Divide Register [RR] */ /*-------------------------------------------------------------------*/ DEF_INST(divide_register) { int r1; /* Values of R fields */ int r2; /* Values of R fields */ int divide_overflow; /* 1=divide overflow */ RR(inst, regs, r1, r2); ODD_CHECK(r1, regs); /* Divide r1::r1+1 by r2, remainder in r1, quotient in r1+1 */ divide_overflow = div_signed (&(regs->GR_L(r1)),&(regs->GR_L(r1+1)), regs->GR_L(r1), regs->GR_L(r1+1), regs->GR_L(r2)); /* Program check if overflow */ if ( divide_overflow ) regs->program_interrupt (regs, PGM_FIXED_POINT_DIVIDE_EXCEPTION); } /*-------------------------------------------------------------------*/ /* 5D D - Divide [RX] */ /*-------------------------------------------------------------------*/ DEF_INST(divide) { int r1; /* Values of R fields */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ U32 n; /* 32-bit operand values */ int divide_overflow; /* 1=divide overflow */ RX(inst, regs, r1, b2, effective_addr2); ODD_CHECK(r1, regs); /* Load second operand from operand address */ n = ARCH_DEP(vfetch4) ( effective_addr2, b2, regs ); /* Divide r1::r1+1 by n, remainder in r1, quotient in r1+1 */ divide_overflow = div_signed (&(regs->GR_L(r1)), &(regs->GR_L(r1+1)), regs->GR_L(r1), regs->GR_L(r1+1), n); /* Program check if overflow */ if ( divide_overflow ) regs->program_interrupt (regs, PGM_FIXED_POINT_DIVIDE_EXCEPTION); } /*-------------------------------------------------------------------*/ /* 17 XR - Exclusive Or Register [RR] */ /*-------------------------------------------------------------------*/ DEF_INST(exclusive_or_register) { int r1, r2; /* Values of R fields */ RR0(inst, regs, r1, r2); /* XOR second operand with first and set condition code */ regs->psw.cc = ( regs->GR_L(r1) ^= regs->GR_L(r2) ) ? 1 : 0; } /*-------------------------------------------------------------------*/ /* 57 X - Exclusive Or [RX] */ /*-------------------------------------------------------------------*/ DEF_INST(exclusive_or) { int r1; /* Values of R fields */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ U32 n; /* 32-bit operand values */ RX(inst, regs, r1, b2, effective_addr2); /* Load second operand from operand address */ n = ARCH_DEP(vfetch4) ( effective_addr2, b2, regs ); /* XOR second operand with first and set condition code */ regs->psw.cc = ( regs->GR_L(r1) ^= n ) ? 1 : 0; } /*-------------------------------------------------------------------*/ /* 97 XI - Exclusive Or Immediate [SI] */ /*-------------------------------------------------------------------*/ DEF_INST(exclusive_or_immediate) { BYTE i2; /* Immediate operand */ int b1; /* Base of effective addr */ VADR effective_addr1; /* Effective address */ BYTE *dest; /* Pointer to target byte */ SI(inst, regs, i2, b1, effective_addr1); ITIMER_SYNC(effective_addr1,1,regs); /* Get byte mainstor address */ dest = MADDR (effective_addr1, b1, regs, ACCTYPE_WRITE, regs->psw.pkey ); /* XOR byte with immediate operand, setting condition code */ regs->psw.cc = ((*dest ^= i2) != 0); ITIMER_UPDATE(effective_addr1,0,regs); } /*-------------------------------------------------------------------*/ /* D7 XC - Exclusive Or Character [SS] */ /*-------------------------------------------------------------------*/ DEF_INST(exclusive_or_character) { int len, len2, len3; /* Lengths to copy */ int b1, b2; /* Base register numbers */ VADR addr1, addr2; /* Virtual addresses */ BYTE *dest1, *dest2; /* Destination addresses */ BYTE *source1, *source2; /* Source addresses */ BYTE *sk1, *sk2; /* Storage key addresses */ int i; /* Loop counter */ int cc = 0; /* Condition code */ SS_L(inst, regs, len, b1, addr1, b2, addr2); ITIMER_SYNC(addr1,len,regs); ITIMER_SYNC(addr2,len,regs); /* Quick out for 1 byte (no boundary crossed) */ if (unlikely(len == 0)) { source1 = MADDR (addr2, b2, regs, ACCTYPE_READ, regs->psw.pkey); dest1 = MADDR (addr1, b1, regs, ACCTYPE_WRITE, regs->psw.pkey); if (*dest1 ^= *source1) cc = 1; regs->psw.cc = cc; return; } /* There are several scenarios (in optimal order): * (1) dest boundary and source boundary not crossed * (a) dest and source are the same, set dest to zeroes * (b) dest and source are not the same * (2) dest boundary not crossed and source boundary crossed * (3) dest boundary crossed and source boundary not crossed * (4) dest boundary and source boundary are crossed * (a) dest and source boundary cross at the same time * (b) dest boundary crossed first * (c) source boundary crossed first */ /* Translate addresses of leftmost operand bytes */ dest1 = MADDR (addr1, b1, regs, ACCTYPE_WRITE_SKP, regs->psw.pkey); sk1 = regs->dat.storkey; source1 = MADDR (addr2, b2, regs, ACCTYPE_READ, regs->psw.pkey); if ( NOCROSS2K(addr1,len)) { if ( NOCROSS2K(addr2,len)) { /* (1) - No boundaries are crossed */ if (dest1 == source1) { /* (1a) - Dest and source are the same */ memset(dest1, 0, len + 1); } else { /* (1b) - Dest and source are not the sam */ for (i = 0; i <= len; i++) if (*dest1++ ^= *source1++) cc = 1; } } else { /* (2) - Second operand crosses a boundary */ len2 = 0x800 - (addr2 & 0x7FF); source2 = MADDR ((addr2 + len2) & ADDRESS_MAXWRAP(regs), b2, regs, ACCTYPE_READ, regs->psw.pkey); for ( i = 0; i < len2; i++) if (*dest1++ ^= *source1++) cc = 1; len2 = len - len2; for ( i = 0; i <= len2; i++) if (*dest1++ ^= *source2++) cc = 1; } *sk1 |= (STORKEY_REF | STORKEY_CHANGE); } else { /* First operand crosses a boundary */ len2 = 0x800 - (addr1 & 0x7FF); dest2 = MADDR ((addr1 + len2) & ADDRESS_MAXWRAP(regs), b1, regs, ACCTYPE_WRITE_SKP, regs->psw.pkey); sk2 = regs->dat.storkey; if ( NOCROSS2K(addr2,len)) { /* (3) - First operand crosses a boundary */ for ( i = 0; i < len2; i++) if (*dest1++ ^= *source1++) cc = 1; len2 = len - len2; for ( i = 0; i <= len2; i++) if (*dest2++ ^= *source1++) cc = 1; } else { /* (4) - Both operands cross a boundary */ len3 = 0x800 - (addr2 & 0x7FF); source2 = MADDR ((addr2 + len3) & ADDRESS_MAXWRAP(regs), b2, regs, ACCTYPE_READ, regs->psw.pkey); if (len2 == len3) { /* (4a) - Both operands cross at the same time */ for ( i = 0; i < len2; i++) if (*dest1++ ^= *source1++) cc = 1; len2 = len - len2; for ( i = 0; i <= len2; i++) if (*dest2++ ^= *source2++) cc = 1; } else if (len2 < len3) { /* (4b) - First operand crosses first */ for ( i = 0; i < len2; i++) if (*dest1++ ^= *source1++) cc = 1; len2 = len3 - len2; for ( i = 0; i < len2; i++) if (*dest2++ ^= *source1++) cc = 1; len2 = len - len3; for ( i = 0; i <= len2; i++) if (*dest2++ ^= *source2++) cc = 1; } else { /* (4c) - Second operand crosses first */ for ( i = 0; i < len3; i++) if (*dest1++ ^= *source1++) cc = 1; len3 = len2 - len3; for ( i = 0; i < len3; i++) if (*dest1++ ^= *source2++) cc = 1; len3 = len - len2; for ( i = 0; i <= len3; i++) if (*dest2++ ^= *source2++) cc = 1; } } *sk1 |= (STORKEY_REF | STORKEY_CHANGE); *sk2 |= (STORKEY_REF | STORKEY_CHANGE); } regs->psw.cc = cc; ITIMER_UPDATE(addr1,len,regs); } /*-------------------------------------------------------------------*/ /* 44 EX - Execute [RX] */ /*-------------------------------------------------------------------*/ DEF_INST(execute) { int r1; /* Value of R field */ int b2; /* Base of effective addr */ BYTE *ip; /* -> executed instruction */ RX(inst, regs, r1, b2, regs->ET); ODD_CHECK(regs->ET, regs); #if defined(_FEATURE_SIE) /* Ensure that the instruction field is zero, such that zeros are stored in the interception parm field, if the interrupt is intercepted */ memset(regs->exinst, 0, 8); #endif /*defined(_FEATURE_SIE)*/ /* Fetch target instruction from operand address */ ip = INSTRUCTION_FETCH(regs, 1); if (ip != regs->exinst) memcpy (regs->exinst, ip, 8); /* Program check if recursive execute */ if ( regs->exinst[0] == 0x44 #if defined(FEATURE_EXECUTE_EXTENSIONS_FACILITY) || (regs->exinst[0] == 0xc6 && !(regs->exinst[1] & 0x0f)) #endif /*defined(FEATURE_EXECUTE_EXTENSIONS_FACILITY)*/ ) regs->program_interrupt (regs, PGM_EXECUTE_EXCEPTION); /* Or 2nd byte of instruction with low-order byte of R1 */ regs->exinst[1] |= r1 ? regs->GR_LHLCL(r1) : 0; /* * Turn execflag on indicating this instruction is EXecuted. * psw.ip is backed up by the EXecuted instruction length to * be incremented back by the instruction decoder. */ regs->execflag = 1; regs->exrl = 0; regs->ip -= ILC(regs->exinst[0]); EXECUTE_INSTRUCTION (regs->exinst, regs); /* Leave execflag on if pending PER so ILC will reflect EX */ if (!OPEN_IC_PER(regs)) regs->execflag = 0; } #if defined(FEATURE_EXECUTE_EXTENSIONS_FACILITY) /*-------------------------------------------------------------------*/ /* C6x0 EXRL - Execute Relative Long [RIL] */ /*-------------------------------------------------------------------*/ DEF_INST(execute_relative_long) { int r1; /* Register number */ BYTE *ip; /* -> executed instruction */ RIL_A(inst, regs, r1, regs->ET); #if defined(_FEATURE_SIE) /* Ensure that the instruction field is zero, such that zeros are stored in the interception parm field, if the interrupt is intercepted */ memset(regs->exinst, 0, 8); #endif /*defined(_FEATURE_SIE)*/ /* Fetch target instruction from operand address */ ip = INSTRUCTION_FETCH(regs, 1); if (ip != regs->exinst) memcpy (regs->exinst, ip, 8); #if 1 /* Display target instruction if stepping or tracing */ if (CPU_STEPPING_OR_TRACING(regs, 6)) { int n, ilc; char buf[256]; #if defined(FEATURE_ESAME) n = sprintf (buf, "EXRL target ADDR="F_VADR" ", regs->ET); #else n = sprintf (buf, "EXRL ADDR="F_VADR" ", regs->ET); #endif ilc = ILC(ip[0]); n += sprintf (buf+n, " INST=%2.2X%2.2X", ip[0], ip[1]); if (ilc > 2) n += sprintf (buf+n, "%2.2X%2.2X", ip[2], ip[3]); if (ilc > 4) n += sprintf (buf+n, "%2.2X%2.2X", ip[4], ip[5]); logmsg ("%s %s", buf,(ilc<4) ? " " : (ilc<6) ? " " : ""); DISASM_INSTRUCTION(ip); logmsg ("\n"); } #endif /* Program check if recursive execute */ if ( regs->exinst[0] == 0x44 || (regs->exinst[0] == 0xc6 && !(regs->exinst[1] & 0x0f)) ) regs->program_interrupt (regs, PGM_EXECUTE_EXCEPTION); /* Or 2nd byte of instruction with low-order byte of R1 */ regs->exinst[1] |= r1 ? regs->GR_LHLCL(r1) : 0; /* * Turn execflag on indicating this instruction is EXecuted. * psw.ip is backed up by the EXecuted instruction length to * be incremented back by the instruction decoder. */ regs->execflag = 1; regs->exrl = 1; regs->ip -= ILC(regs->exinst[0]); EXECUTE_INSTRUCTION (regs->exinst, regs); /* Leave execflag on if pending PER so ILC will reflect EXRL */ if (!OPEN_IC_PER(regs)) regs->execflag = 0; } #endif /* defined(FEATURE_EXECUTE_EXTENSION_FACILITY) */ #if defined(FEATURE_ACCESS_REGISTERS) /*-------------------------------------------------------------------*/ /* B24F EAR - Extract Access Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(extract_access_register) { int r1, r2; /* Values of R fields */ RRE0(inst, regs, r1, r2); /* Copy R2 access register to R1 general register */ regs->GR_L(r1) = regs->AR(r2); } #endif /*defined(FEATURE_ACCESS_REGISTERS)*/ /*-------------------------------------------------------------------*/ /* 43 IC - Insert Character [RX] */ /*-------------------------------------------------------------------*/ DEF_INST(insert_character) { int r1; /* Value of R field */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ RX(inst, regs, r1, b2, effective_addr2); /* Insert character in r1 register */ regs->GR_LHLCL(r1) = ARCH_DEP(vfetchb) ( effective_addr2, b2, regs ); } /*-------------------------------------------------------------------*/ /* BF ICM - Insert Characters under Mask [RS] */ /*-------------------------------------------------------------------*/ DEF_INST(insert_characters_under_mask) { int r1, r3; /* Register numbers */ int b2; /* effective address base */ VADR effective_addr2; /* effective address */ int i; /* Integer work area */ BYTE vbyte[4]; /* Fetched storage bytes */ U32 n; /* Fetched value */ static const int /* Length-1 to fetch by mask */ icmlen[16] = {0, 0, 0, 1, 0, 1, 1, 2, 0, 1, 1, 2, 1, 2, 2, 3}; static const unsigned int /* Turn reg bytes off by mask*/ icmmask[16] = {0xFFFFFFFF, 0xFFFFFF00, 0xFFFF00FF, 0xFFFF0000, 0xFF00FFFF, 0xFF00FF00, 0xFF0000FF, 0xFF000000, 0x00FFFFFF, 0x00FFFF00, 0x00FF00FF, 0x00FF0000, 0x0000FFFF, 0x0000FF00, 0x000000FF, 0x00000000}; RS(inst, regs, r1, r3, b2, effective_addr2); switch (r3) { case 7: /* Optimized case */ vbyte[0] = 0; ARCH_DEP(vfetchc) (vbyte + 1, 2, effective_addr2, b2, regs); n = fetch_fw (vbyte); regs->GR_L(r1) = (regs->GR_L(r1) & 0xFF000000) | n; regs->psw.cc = n ? n & 0x00800000 ? 1 : 2 : 0; break; case 15: /* Optimized case */ regs->GR_L(r1) = ARCH_DEP(vfetch4) (effective_addr2, b2, regs); regs->psw.cc = regs->GR_L(r1) ? regs->GR_L(r1) & 0x80000000 ? 1 : 2 : 0; break; default: memset (vbyte, 0, 4); ARCH_DEP(vfetchc)(vbyte, icmlen[r3], effective_addr2, b2, regs); /* If mask was 0 then we still had to fetch, according to POP. If so, set the fetched byte to 0 to force zero cc */ if (!r3) vbyte[0] = 0; n = fetch_fw (vbyte); regs->psw.cc = n ? n & 0x80000000 ? 1 : 2 : 0; /* Turn off the reg bytes we are going to set */ regs->GR_L(r1) &= icmmask[r3]; /* Set bytes one at a time according to the mask */ i = 0; if (r3 & 0x8) regs->GR_L(r1) |= vbyte[i++] << 24; if (r3 & 0x4) regs->GR_L(r1) |= vbyte[i++] << 16; if (r3 & 0x2) regs->GR_L(r1) |= vbyte[i++] << 8; if (r3 & 0x1) regs->GR_L(r1) |= vbyte[i]; break; } /* switch (r3) */ } /*-------------------------------------------------------------------*/ /* B222 IPM - Insert Program Mask [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(insert_program_mask) { int r1, unused; /* Value of R field */ RRE0(inst, regs, r1, unused); /* Insert condition code in R1 bits 2-3, program mask in R1 bits 4-7, and set R1 bits 0-1 to zero */ regs->GR_LHHCH(r1) = (regs->psw.cc << 4) | regs->psw.progmask; } /*-------------------------------------------------------------------*/ /* 58 L - Load [RX] */ /*-------------------------------------------------------------------*/ DEF_INST(load) { int r1; /* Value of R field */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ #if 0 U32 *p; /* Mainstor pointer */ #endif RX(inst, regs, r1, b2, effective_addr2); /* Load R1 register from second operand */ regs->GR_L(r1) = ARCH_DEP(vfetch4) ( effective_addr2, b2, regs ); } /* end DEF_INST(load) */ /*-------------------------------------------------------------------*/ /* 18 LR - Load Register [RR] */ /*-------------------------------------------------------------------*/ DEF_INST(load_register) { int r1, r2; /* Values of R fields */ RR0(inst, regs, r1, r2); /* Copy second operand to first operand */ regs->GR_L(r1) = regs->GR_L(r2); } #if defined(FEATURE_ACCESS_REGISTERS) /*-------------------------------------------------------------------*/ /* 9A LAM - Load Access Multiple [RS] */ /*-------------------------------------------------------------------*/ DEF_INST(load_access_multiple) { int r1, r3; /* Register numbers */ int b2; /* effective address base */ VADR effective_addr2; /* effective address */ int i, m, n; /* Integer work areas */ U32 *p1, *p2 = NULL; /* Mainstor pointers */ RS(inst, regs, r1, r3, b2, effective_addr2); FW_CHECK(effective_addr2, regs); /* Calculate number of regs to fetch */ n = ((r3 - r1) & 0xF) + 1; /* Calculate number of words to next boundary */ m = (0x800 - (effective_addr2 & 0x7ff)) >> 2; /* Address of operand beginning */ p1 = (U32*)MADDR(effective_addr2, b2, regs, ACCTYPE_READ, regs->psw.pkey); /* Get address of next page if boundary crossed */ if (unlikely (m < n)) p2 = (U32*)MADDR(effective_addr2 + (m*4), b2, regs, ACCTYPE_READ, regs->psw.pkey); else m = n; /* Copy from operand beginning */ for (i = 0; i < m; i++, p1++) { regs->AR((r1 + i) & 0xF) = fetch_fw (p1); SET_AEA_AR (regs, (r1 + i) & 0xF); } /* Copy from next page */ for ( ; i < n; i++, p2++) { regs->AR((r1 + i) & 0xF) = fetch_fw (p2); SET_AEA_AR (regs, (r1 + i) & 0xF); } } #endif /*defined(FEATURE_ACCESS_REGISTERS)*/ /*-------------------------------------------------------------------*/ /* 41 LA - Load Address [RX] */ /*-------------------------------------------------------------------*/ DEF_INST(load_address) { int r1; /* Value of R field */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ RX0(inst, regs, r1, b2, effective_addr2); /* Load operand address into register */ SET_GR_A(r1, regs, effective_addr2); } #if defined(FEATURE_ACCESS_REGISTERS) /*-------------------------------------------------------------------*/ /* 51 LAE - Load Address Extended [RX] */ /*-------------------------------------------------------------------*/ DEF_INST(load_address_extended) { int r1; /* Value of R field */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ RX0(inst, regs, r1, b2, effective_addr2); /* Load operand address into register */ SET_GR_A(r1, regs,effective_addr2); /* Load corresponding value into access register */ if ( PRIMARY_SPACE_MODE(&(regs->psw)) ) regs->AR(r1) = ALET_PRIMARY; else if ( SECONDARY_SPACE_MODE(&(regs->psw)) ) regs->AR(r1) = ALET_SECONDARY; else if ( HOME_SPACE_MODE(&(regs->psw)) ) regs->AR(r1) = ALET_HOME; else /* ACCESS_REGISTER_MODE(&(regs->psw)) */ regs->AR(r1) = (b2 == 0) ? 0 : regs->AR(b2); SET_AEA_AR(regs, r1); } #endif /*defined(FEATURE_ACCESS_REGISTERS)*/ /*-------------------------------------------------------------------*/ /* 12 LTR - Load and Test Register [RR] */ /*-------------------------------------------------------------------*/ DEF_INST(load_and_test_register) { int r1, r2; /* Values of R fields */ RR0(inst, regs, r1, r2); /* Copy second operand and set condition code */ regs->GR_L(r1) = regs->GR_L(r2); regs->psw.cc = (S32)regs->GR_L(r1) < 0 ? 1 : (S32)regs->GR_L(r1) > 0 ? 2 : 0; } /*-------------------------------------------------------------------*/ /* 13 LCR - Load Complement Register [RR] */ /*-------------------------------------------------------------------*/ DEF_INST(load_complement_register) { int r1, r2; /* Values of R fields */ RR(inst, regs, r1, r2); /* Condition code 3 and program check if overflow */ if ( regs->GR_L(r2) == 0x80000000 ) { regs->GR_L(r1) = regs->GR_L(r2); regs->psw.cc = 3; if ( FOMASK(®s->psw) ) regs->program_interrupt (regs, PGM_FIXED_POINT_OVERFLOW_EXCEPTION); return; } /* Load complement of second operand and set condition code */ regs->GR_L(r1) = -((S32)regs->GR_L(r2)); regs->psw.cc = (S32)regs->GR_L(r1) < 0 ? 1 : (S32)regs->GR_L(r1) > 0 ? 2 : 0; } /*-------------------------------------------------------------------*/ /* 48 LH - Load Halfword [RX] */ /*-------------------------------------------------------------------*/ DEF_INST(load_halfword) { int r1; /* Value of R field */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ RX(inst, regs, r1, b2, effective_addr2); /* Load rightmost 2 bytes of register from operand address */ regs->GR_L(r1) = (S16)ARCH_DEP(vfetch2) ( effective_addr2, b2, regs ); } #if defined(FEATURE_IMMEDIATE_AND_RELATIVE) /*-------------------------------------------------------------------*/ /* A7x8 LHI - Load Halfword Immediate [RI] */ /*-------------------------------------------------------------------*/ DEF_INST(load_halfword_immediate) { int r1; /* Register number */ int opcd; /* Opcode */ U16 i2; /* 16-bit operand values */ RI0(inst, regs, r1, opcd, i2); /* Load operand into register */ regs->GR_L(r1) = (S16)i2; } #endif /*defined(FEATURE_IMMEDIATE_AND_RELATIVE)*/ /*-------------------------------------------------------------------*/ /* 98 LM - Load Multiple [RS] */ /*-------------------------------------------------------------------*/ DEF_INST(load_multiple) { int r1, r3; /* Register numbers */ int b2; /* effective address base */ VADR effective_addr2; /* effective address */ int i, m, n; /* Integer work areas */ U32 *p1, *p2; /* Mainstor pointers */ BYTE *bp1; /* Unaligned maintstor ptr */ RS(inst, regs, r1, r3, b2, effective_addr2); /* Calculate number of bytes to load */ n = (((r3 - r1) & 0xF) + 1) << 2; /* Calculate number of bytes to next boundary */ m = 0x800 - ((VADR_L)effective_addr2 & 0x7ff); /* Address of operand beginning */ bp1 = (BYTE*)MADDR(effective_addr2, b2, regs, ACCTYPE_READ, regs->psw.pkey); p1=(U32*)bp1; if (likely(n <= m)) { /* Boundary not crossed */ n >>= 2; #if defined(OPTION_STRICT_ALIGNMENT) if(likely(!(((uintptr_t)effective_addr2)&0x03))) { #endif for (i = 0; i < n; i++, p1++) regs->GR_L((r1 + i) & 0xF) = fetch_fw (p1); #if defined(OPTION_STRICT_ALIGNMENT) } else { for (i = 0; i < n; i++, bp1+=4) regs->GR_L((r1 + i) & 0xF) = fetch_fw (bp1); } #endif } else { /* Boundary crossed, get 2nd page address */ effective_addr2 += m; effective_addr2 &= ADDRESS_MAXWRAP(regs); p2 = (U32*)MADDR(effective_addr2, b2, regs, ACCTYPE_READ, regs->psw.pkey); if (likely((m & 0x3) == 0)) { /* Addresses are word aligned */ m >>= 2; for (i = 0; i < m; i++, p1++) regs->GR_L((r1 + i) & 0xF) = fetch_fw (p1); n >>= 2; for ( ; i < n; i++, p2++) regs->GR_L((r1 + i) & 0xF) = fetch_fw (p2); } else { /* Worst case */ U32 rwork[16]; BYTE *b1, *b2; b1 = (BYTE *)&rwork[0]; b2 = (BYTE *)p1; for (i = 0; i < m; i++) *b1++ = *b2++; b2 = (BYTE *)p2; for ( ; i < n; i++) *b1++ = *b2++; n >>= 2; for (i = 0; i < n; i++) regs->GR_L((r1 + i) & 0xF) = CSWAP32(rwork[i]); } } } /* end DEF_INST(load_multiple) */ /*-------------------------------------------------------------------*/ /* 11 LNR - Load Negative Register [RR] */ /*-------------------------------------------------------------------*/ DEF_INST(load_negative_register) { int r1, r2; /* Values of R fields */ RR0(inst, regs, r1, r2); /* Load negative value of second operand and set cc */ regs->GR_L(r1) = (S32)regs->GR_L(r2) > 0 ? -((S32)regs->GR_L(r2)) : (S32)regs->GR_L(r2); regs->psw.cc = (S32)regs->GR_L(r1) == 0 ? 0 : 1; } /*-------------------------------------------------------------------*/ /* 10 LPR - Load Positive Register [RR] */ /*-------------------------------------------------------------------*/ DEF_INST(load_positive_register) { int r1, r2; /* Values of R fields */ RR(inst, regs, r1, r2); /* Condition code 3 and program check if overflow */ if ( regs->GR_L(r2) == 0x80000000 ) { regs->GR_L(r1) = regs->GR_L(r2); regs->psw.cc = 3; if ( FOMASK(®s->psw) ) regs->program_interrupt (regs, PGM_FIXED_POINT_OVERFLOW_EXCEPTION); return; } /* Load positive value of second operand and set cc */ regs->GR_L(r1) = (S32)regs->GR_L(r2) < 0 ? -((S32)regs->GR_L(r2)) : (S32)regs->GR_L(r2); regs->psw.cc = (S32)regs->GR_L(r1) == 0 ? 0 : 2; } /*-------------------------------------------------------------------*/ /* AF MC - Monitor Call [SI] */ /*-------------------------------------------------------------------*/ DEF_INST(monitor_call) { BYTE i2; /* Monitor class */ int b1; /* Base of effective addr */ VADR effective_addr1; /* Effective address */ CREG n; /* Work */ SI(inst, regs, i2, b1, effective_addr1); /* Program check if monitor class exceeds 15 */ if ( i2 > 0x0F ) regs->program_interrupt (regs, PGM_SPECIFICATION_EXCEPTION); /* Ignore if monitor mask in control register 8 is zero */ n = (regs->CR(8) & CR8_MCMASK) << i2; if ((n & 0x00008000) == 0) return; regs->monclass = i2; regs->MONCODE = effective_addr1; /* Generate a monitor event program interruption */ regs->program_interrupt (regs, PGM_MONITOR_EVENT); } /*-------------------------------------------------------------------*/ /* 92 MVI - Move Immediate [SI] */ /*-------------------------------------------------------------------*/ DEF_INST(move_immediate) { BYTE i2; /* Immediate operand */ int b1; /* Base of effective addr */ VADR effective_addr1; /* Effective address */ SI(inst, regs, i2, b1, effective_addr1); /* Store immediate operand at operand address */ ARCH_DEP(vstoreb) ( i2, effective_addr1, b1, regs ); } /*-------------------------------------------------------------------*/ /* D2 MVC - Move Character [SS] */ /*-------------------------------------------------------------------*/ DEF_INST(move_character) { BYTE l; /* Length byte */ int b1, b2; /* Values of base fields */ VADR effective_addr1, effective_addr2; /* Effective addresses */ SS_L(inst, regs, l, b1, effective_addr1, b2, effective_addr2); /* Move characters using current addressing mode and key */ ARCH_DEP(move_chars) (effective_addr1, b1, regs->psw.pkey, effective_addr2, b2, regs->psw.pkey, l, regs); } /*-------------------------------------------------------------------*/ /* E8 MVCIN - Move Inverse [SS] */ /*-------------------------------------------------------------------*/ DEF_INST(move_inverse) { BYTE l; /* Lenght byte */ int b1, b2; /* Base registers */ VADR effective_addr1, effective_addr2; /* Effective addresses */ VADR n; /* 32-bit operand values */ BYTE tbyte; /* Byte work areas */ int i; /* Integer work areas */ SS_L(inst, regs, l, b1, effective_addr1, b2, effective_addr2); /* If operand 1 crosses a page, make sure both pages are accessable */ if((effective_addr1 & PAGEFRAME_PAGEMASK) != ((effective_addr1 + l) & PAGEFRAME_PAGEMASK)) ARCH_DEP(validate_operand) (effective_addr1, b1, l, ACCTYPE_WRITE_SKP, regs); /* If operand 2 crosses a page, make sure both pages are accessable */ n = (effective_addr2 - l) & ADDRESS_MAXWRAP(regs); if((n & PAGEFRAME_PAGEMASK) != ((n + l) & PAGEFRAME_PAGEMASK)) ARCH_DEP(validate_operand) (n, b2, l, ACCTYPE_READ, regs); /* Process the destination operand from left to right, and the source operand from right to left */ for ( i = 0; i <= l; i++ ) { /* Fetch a byte from the source operand */ tbyte = ARCH_DEP(vfetchb) ( effective_addr2, b2, regs ); /* Store the byte in the destination operand */ ARCH_DEP(vstoreb) ( tbyte, effective_addr1, b1, regs ); /* Increment destination operand address */ effective_addr1++; effective_addr1 &= ADDRESS_MAXWRAP(regs); /* Decrement source operand address */ effective_addr2--; effective_addr2 &= ADDRESS_MAXWRAP(regs); } /* end for(i) */ } /*-------------------------------------------------------------------*/ /* 0E MVCL - Move Long [RR] */ /*-------------------------------------------------------------------*/ DEF_INST(move_long) { int r1, r2; /* Values of R fields */ VADR addr1, addr2; /* Operand addresses */ int len1, len2; /* Operand lengths */ int len, len3, len4; /* Work lengths */ VADR n; /* Work area */ BYTE *dest, *source; /* Mainstor addresses */ BYTE pad; /* Padding byte */ #if defined(FEATURE_INTERVAL_TIMER) int orglen1; /* Original dest length */ #endif RR(inst, regs, r1, r2); ODD2_CHECK(r1, r2, regs); /* Determine the destination and source addresses */ addr1 = regs->GR(r1) & ADDRESS_MAXWRAP(regs); addr2 = regs->GR(r2) & ADDRESS_MAXWRAP(regs); /* Load padding byte from bits 0-7 of R2+1 register */ pad = regs->GR_LHHCH(r2+1); /* Load operand lengths from bits 8-31 of R1+1 and R2+1 */ len1 = regs->GR_LA24(r1+1); len2 = regs->GR_LA24(r2+1); #if defined(FEATURE_INTERVAL_TIMER) orglen1=len1; #endif ITIMER_SYNC(addr2,len2,regs); /* Test for destructive overlap */ if ( len2 > 1 && len1 > 1 && (!ACCESS_REGISTER_MODE(&(regs->psw)) || (r1 == 0 ? 0 : regs->AR(r1)) == (r2 == 0 ? 0 : regs->AR(r2)))) { n = addr2 + ((len2 < len1) ? len2 : len1) - 1; n &= ADDRESS_MAXWRAP(regs); if ((n > addr2 && (addr1 > addr2 && addr1 <= n)) || (n <= addr2 && (addr1 > addr2 || addr1 <= n))) { SET_GR_A(r1, regs,addr1); SET_GR_A(r2, regs,addr2); regs->psw.cc = 3; #if 0 logmsg (_("MVCL destructive overlap: ")); ARCH_DEP(display_inst) (regs, inst); #endif return; } } /* Initialize source and dest addresses */ if (len1) { if (len2) { source = MADDR (addr2, r2, regs, ACCTYPE_READ, regs->psw.pkey); } else { source=NULL; } dest = MADDR (addr1, r1, regs, ACCTYPE_WRITE, regs->psw.pkey); } else { /* FIXME : We shouldn't have to do that - just to prevent potentially uninitialized variable warning in GCC.. Can't see where it is getting this diagnostic from. ISW 2009/02/04 */ source=NULL; dest=NULL; } /* Set the condition code according to the lengths */ regs->psw.cc = (len1 < len2) ? 1 : (len1 > len2) ? 2 : 0; /* Set the registers *after* translating - so that the instruction is properly nullified when there is an access exception on the 1st unit of operation */ SET_GR_A(r1, regs,addr1); SET_GR_A(r2, regs,addr2); while (len1) { /* Clear or copy memory */ if (len2 == 0) { len = NOCROSS2KL(addr1,len1) ? len1 : (int)(0x800 - (addr1 & 0x7FF)); memset (dest, pad, len); } else { len3 = NOCROSS2KL(addr1,len1) ? len1 : (int)(0x800 - (addr1 & 0x7FF)); len4 = NOCROSS2KL(addr2,len2) ? len2 : (int)(0x800 - (addr2 & 0x7FF)); len = len3 < len4 ? len3 : len4; /* Use concpy to ensure Concurrent block update consistency */ concpy (regs, dest, source, len); } /* Check for storage alteration PER event */ #if defined(FEATURE_PER) if ( EN_IC_PER_SA(regs) #if defined(FEATURE_PER2) && ( REAL_MODE(®s->psw) || ARCH_DEP(check_sa_per2) (r1, ACCTYPE_WRITE, regs) ) #endif /*defined(FEATURE_PER2)*/ && PER_RANGE_CHECK2(addr1, addr1+len, regs->CR(10), regs->CR(11)) ) ON_IC_PER_SA(regs); #endif /*defined(FEATURE_PER)*/ /* Adjust lengths and virtual addresses */ len1 -= len; addr1 = (addr1 + len) & ADDRESS_MAXWRAP(regs); if (len2) { len2 -= len; addr2 = (addr2 + len) & ADDRESS_MAXWRAP(regs); } /* Update regs (since interrupt may occur) */ SET_GR_A(r1, regs,addr1); SET_GR_A(r2, regs,addr2); regs->GR_LA24(r1+1) = len1; regs->GR_LA24(r2+1) = len2; /* Check for pending interrupt */ if ( len1 > 256 && (OPEN_IC_EXTPENDING(regs) || OPEN_IC_IOPENDING(regs)) ) { UPD_PSW_IA (regs, PSW_IA(regs, -REAL_ILC(regs))); break; } /* Translate next source and dest addresses */ if (len1) { if (len2) { if (addr2 & 0x7FF) source += len; else source = MADDR (addr2, r2, regs, ACCTYPE_READ, regs->psw.pkey); } if (addr1 & 0x7FF) dest += len; else dest = MADDR (addr1, r1, regs, ACCTYPE_WRITE, regs->psw.pkey); } } /* while (len1) */ ITIMER_UPDATE(addr1,orglen1,regs); /* If len1 is non-zero then we were interrupted */ if (len1) RETURN_INTCHECK(regs); } #if defined(FEATURE_COMPARE_AND_MOVE_EXTENDED) /*-------------------------------------------------------------------*/ /* A8 MVCLE - Move Long Extended [RS] */ /*-------------------------------------------------------------------*/ DEF_INST(move_long_extended) { int r1, r3; /* Register numbers */ int b2; /* effective address base */ VADR effective_addr2; /* effective address */ int cc; /* Condition code */ VADR addr1, addr2; /* Operand addresses */ GREG len1, len2; /* Operand lengths */ BYTE pad; /* Padding byte */ size_t cpu_length; /* cpu determined length */ size_t copylen; /* Length to copy */ BYTE *dest; /* Maint storage pointers */ size_t dstlen,srclen; /* Page wide src/dst lengths */ RS(inst, regs, r1, r3, b2, effective_addr2); ODD2_CHECK(r1, r3, regs); /* Load padding byte from bits 24-31 of effective address */ pad = effective_addr2 & 0xFF; /* Determine the destination and source addresses */ addr1 = regs->GR(r1) & ADDRESS_MAXWRAP(regs); addr2 = regs->GR(r3) & ADDRESS_MAXWRAP(regs); /* Load operand lengths from bits 0-31 of R1+1 and R3+1 */ len1 = GR_A(r1+1, regs); len2 = GR_A(r3+1, regs); /* set cpu_length as shortest distance to new page */ if ((addr1 & 0xFFF) > (addr2 & 0xFFF)) cpu_length = 0x1000 - (addr1 & 0xFFF); else cpu_length = 0x1000 - (addr2 & 0xFFF); dstlen=MIN(cpu_length,len1); srclen=MIN(cpu_length,len2); copylen=MIN(dstlen,srclen); /* Set the condition code according to the lengths */ cc = (len1 < len2) ? 1 : (len1 > len2) ? 2 : 0; /* Obtain destination pointer */ if(len1==0) { /* bail out if nothing to do */ regs->psw.cc = cc; return; } dest = MADDR (addr1, r1, regs, ACCTYPE_WRITE, regs->psw.pkey); if(copylen!=0) { /* here if we need to copy data */ BYTE *source; /* get source frame and copy concurrently */ source = MADDR (addr2, r3, regs, ACCTYPE_READ, regs->psw.pkey); concpy(regs,dest,source,copylen); /* Adjust operands */ addr2+=copylen; len2-=copylen; addr1+=copylen; len1-=copylen; /* Adjust length & pointers for this cycle */ dest+=copylen; dstlen-=copylen; srclen-=copylen; } if(srclen==0 && dstlen!=0) { /* here if we need to pad the destination */ memset(dest,pad,dstlen); /* Adjust destination operands */ addr1+=dstlen; len1-=dstlen; } /* Update the registers */ SET_GR_A(r1, regs,addr1); SET_GR_A(r1+1, regs,len1); SET_GR_A(r3, regs,addr2); SET_GR_A(r3+1, regs,len2); /* if len1 != 0 then set CC to 3 to indicate we have reached end of CPU dependent length */ if(len1>0) cc=3; regs->psw.cc = cc; } #endif /*defined(FEATURE_COMPARE_AND_MOVE_EXTENDED)*/ #define MOVE_NUMERIC_BUMP(_d,_s) \ do { \ *(_d)=( *(_d) & 0xF0) | ( *(_s) & 0x0F); \ _d++; \ _s++; \ } while(0) /*-------------------------------------------------------------------*/ /* D1 MVN - Move Numerics [SS] */ /*-------------------------------------------------------------------*/ DEF_INST(move_numerics) { VADR addr1, addr2; /* Operand virtual addresses */ int len, arn1, arn2; /* Operand values */ BYTE *dest1, *dest2; /* Destination addresses */ BYTE *source1, *source2; /* Source addresses */ BYTE *sk1, *sk2; /* Storage key addresses */ int len2, len3; /* Lengths to copy */ int i; /* Loop counter */ SS_L(inst, regs, len, arn1, addr1, arn2, addr2); ITIMER_SYNC(addr2,len,regs); /* Translate addresses of leftmost operand bytes */ dest1 = MADDR (addr1, arn1, regs, ACCTYPE_WRITE_SKP, regs->psw.pkey); sk1 = regs->dat.storkey; source1 = MADDR (addr2, arn2, regs, ACCTYPE_READ, regs->psw.pkey); /* There are several scenarios (in optimal order): * (1) dest boundary and source boundary not crossed * (2) dest boundary not crossed and source boundary crossed * (3) dest boundary crossed and source boundary not crossed * (4) dest boundary and source boundary are crossed * (a) dest and source boundary cross at the same time * (b) dest boundary crossed first * (c) source boundary crossed first */ if ( NOCROSS2K(addr1,len)) { if ( NOCROSS2K(addr2,len)) { /* (1) - No boundaries are crossed */ for ( i = 0; i <= len; i++) MOVE_NUMERIC_BUMP(dest1,source1); } else { /* (2) - Second operand crosses a boundary */ len2 = 0x800 - (addr2 & 0x7FF); source2 = MADDR ((addr2 + len2) & ADDRESS_MAXWRAP(regs), arn2, regs, ACCTYPE_READ, regs->psw.pkey); for ( i = 0; i < len2; i++) MOVE_NUMERIC_BUMP(dest1,source1); len2 = len - len2; for ( i = 0; i <= len2; i++) MOVE_NUMERIC_BUMP(dest1,source2); } *sk1 |= (STORKEY_REF | STORKEY_CHANGE); } else { /* First operand crosses a boundary */ len2 = 0x800 - (addr1 & 0x7FF); dest2 = MADDR ((addr1 + len2) & ADDRESS_MAXWRAP(regs), arn1, regs, ACCTYPE_WRITE_SKP, regs->psw.pkey); sk2 = regs->dat.storkey; if ( NOCROSS2K(addr2,len) ) { /* (3) - First operand crosses a boundary */ for ( i = 0; i < len2; i++) MOVE_NUMERIC_BUMP(dest1,source1); len2 = len - len2; for ( i = 0; i <= len2; i++) MOVE_NUMERIC_BUMP(dest2,source1); } else { /* (4) - Both operands cross a boundary */ len3 = 0x800 - (addr2 & 0x7FF); source2 = MADDR ((addr2 + len3) & ADDRESS_MAXWRAP(regs), arn2, regs, ACCTYPE_READ, regs->psw.pkey); if (len2 == len3) { /* (4a) - Both operands cross at the same time */ for ( i = 0; i < len2; i++) MOVE_NUMERIC_BUMP(dest1,source1); len2 = len - len2; for ( i = 0; i <= len2; i++) MOVE_NUMERIC_BUMP(dest2,source2); } else if (len2 < len3) { /* (4b) - First operand crosses first */ for ( i = 0; i < len2; i++) MOVE_NUMERIC_BUMP(dest1,source1); len2 = len3 - len2; for ( i = 0; i < len2; i++) MOVE_NUMERIC_BUMP(dest2,source1); len2 = len - len3; for ( i = 0; i <= len2; i++) MOVE_NUMERIC_BUMP(dest2,source2); } else { /* (4c) - Second operand crosses first */ for ( i = 0; i < len3; i++) MOVE_NUMERIC_BUMP(dest1,source1); len3 = len2 - len3; for ( i = 0; i < len3; i++) MOVE_NUMERIC_BUMP(dest1,source2); len3 = len - len2; for ( i = 0; i <= len3; i++) MOVE_NUMERIC_BUMP(dest2,source2); } } *sk1 |= (STORKEY_REF | STORKEY_CHANGE); *sk2 |= (STORKEY_REF | STORKEY_CHANGE); } ITIMER_UPDATE(addr1,len,regs); } #if defined(FEATURE_STRING_INSTRUCTION) /*-------------------------------------------------------------------*/ /* B255 MVST - Move String [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(move_string) { int r1, r2; /* Values of R fields */ int i; /* Loop counter */ VADR addr1, addr2; /* Operand addresses */ BYTE sbyte; /* String character */ BYTE termchar; /* Terminating character */ int cpu_length; /* length to next page */ RRE(inst, regs, r1, r2); /* Program check if bits 0-23 of register 0 not zero */ if ((regs->GR_L(0) & 0xFFFFFF00) != 0) regs->program_interrupt (regs, PGM_SPECIFICATION_EXCEPTION); /* Load string terminating character from register 0 bits 24-31 */ termchar = regs->GR_LHLCL(0); /* Determine the destination and source addresses */ addr1 = regs->GR(r1) & ADDRESS_MAXWRAP(regs); addr2 = regs->GR(r2) & ADDRESS_MAXWRAP(regs); /* set cpu_length as shortest distance to new page */ if ((addr1 & 0xFFF) > (addr2 & 0xFFF)) cpu_length = 0x1000 - (addr1 & 0xFFF); else cpu_length = 0x1000 - (addr2 & 0xFFF); /* Move up to 4096 bytes until terminating character */ for (i = 0; i < cpu_length; i++) { /* Fetch a byte from the source operand */ sbyte = ARCH_DEP(vfetchb) ( addr2, r2, regs ); /* Store the byte in the destination operand */ ARCH_DEP(vstoreb) ( sbyte, addr1, r1, regs ); /* Check if string terminating character was moved */ if (sbyte == termchar) { /* Set r1 to point to terminating character */ SET_GR_A(r1, regs,addr1); /* Set condition code 1 */ regs->psw.cc = 1; return; } /* Increment operand addresses */ addr1++; addr1 &= ADDRESS_MAXWRAP(regs); addr2++; addr2 &= ADDRESS_MAXWRAP(regs); } /* end for(i) */ /* Set R1 and R2 to point to next character of each operand */ SET_GR_A(r1, regs,addr1); SET_GR_A(r2, regs,addr2); /* Set condition code 3 */ regs->psw.cc = 3; } /* end DEF_INST(move_string) */ #endif /*defined(FEATURE_STRING_INSTRUCTION)*/ /*-------------------------------------------------------------------*/ /* F1 MVO - Move with Offset [SS] */ /*-------------------------------------------------------------------*/ DEF_INST(move_with_offset) { int l1, l2; /* Lenght values */ int b1, b2; /* Values of base registers */ VADR effective_addr1, effective_addr2; /* Effective addresses */ int i, j; /* Loop counters */ BYTE sbyte; /* Source operand byte */ BYTE dbyte; /* Destination operand byte */ SS(inst, regs, l1, l2, b1, effective_addr1, b2, effective_addr2); /* If operand 1 crosses a page, make sure both pages are accessable */ if((effective_addr1 & PAGEFRAME_PAGEMASK) != ((effective_addr1 + l1) & PAGEFRAME_PAGEMASK)) ARCH_DEP(validate_operand) (effective_addr1, b1, l1, ACCTYPE_WRITE_SKP, regs); /* If operand 2 crosses a page, make sure both pages are accessable */ if((effective_addr2 & PAGEFRAME_PAGEMASK) != ((effective_addr2 + l2) & PAGEFRAME_PAGEMASK)) ARCH_DEP(validate_operand) (effective_addr2, b2, l2, ACCTYPE_READ, regs); /* Fetch the rightmost byte from the source operand */ effective_addr2 += l2; effective_addr2 &= ADDRESS_MAXWRAP(regs); sbyte = ARCH_DEP(vfetchb) ( effective_addr2--, b2, regs ); /* Fetch the rightmost byte from the destination operand */ effective_addr1 += l1; effective_addr1 &= ADDRESS_MAXWRAP(regs); dbyte = ARCH_DEP(vfetchb) ( effective_addr1, b1, regs ); /* Move low digit of source byte to high digit of destination */ dbyte &= 0x0F; dbyte |= sbyte << 4; ARCH_DEP(vstoreb) ( dbyte, effective_addr1--, b1, regs ); /* Process remaining bytes from right to left */ for (i = l1, j = l2; i > 0; i--) { /* Move previous high digit to destination low digit */ dbyte = sbyte >> 4; /* Fetch next byte from second operand */ if ( j-- > 0 ) { effective_addr2 &= ADDRESS_MAXWRAP(regs); sbyte = ARCH_DEP(vfetchb) ( effective_addr2--, b2, regs ); } else sbyte = 0x00; /* Move low digit to destination high digit */ dbyte |= sbyte << 4; effective_addr1 &= ADDRESS_MAXWRAP(regs); ARCH_DEP(vstoreb) ( dbyte, effective_addr1--, b1, regs ); } /* end for(i) */ } #define MOVE_ZONE_BUMP(_d,_s) \ do { \ *(_d)=( *(_d) & 0x0F) | ( *(_s) & 0xF0); \ _d++; \ _s++; \ } while(0) /*-------------------------------------------------------------------*/ /* D3 MVZ - Move Zones [SS] */ /*-------------------------------------------------------------------*/ DEF_INST(move_zones) { VADR addr1, addr2; /* Operand virtual addresses */ int len, arn1, arn2; /* Operand values */ BYTE *dest1, *dest2; /* Destination addresses */ BYTE *source1, *source2; /* Source addresses */ BYTE *sk1, *sk2; /* Storage key addresses */ int len2, len3; /* Lengths to copy */ int i; /* Loop counter */ SS_L(inst, regs, len, arn1, addr1, arn2, addr2); ITIMER_SYNC(addr2,len,regs); /* Translate addresses of leftmost operand bytes */ dest1 = MADDR (addr1, arn1, regs, ACCTYPE_WRITE_SKP, regs->psw.pkey); sk1 = regs->dat.storkey; source1 = MADDR (addr2, arn2, regs, ACCTYPE_READ, regs->psw.pkey); /* There are several scenarios (in optimal order): * (1) dest boundary and source boundary not crossed * (2) dest boundary not crossed and source boundary crossed * (3) dest boundary crossed and source boundary not crossed * (4) dest boundary and source boundary are crossed * (a) dest and source boundary cross at the same time * (b) dest boundary crossed first * (c) source boundary crossed first */ if ( NOCROSS2K(addr1,len) ) { if ( NOCROSS2K(addr2,len) ) { /* (1) - No boundaries are crossed */ for ( i = 0; i <= len; i++) MOVE_ZONE_BUMP(dest1,source1); } else { /* (2) - Second operand crosses a boundary */ len2 = 0x800 - (addr2 & 0x7FF); source2 = MADDR ((addr2 + len2) & ADDRESS_MAXWRAP(regs), arn2, regs, ACCTYPE_READ, regs->psw.pkey); for ( i = 0; i < len2; i++) MOVE_ZONE_BUMP(dest1,source1); len2 = len - len2; for ( i = 0; i <= len2; i++) MOVE_ZONE_BUMP(dest1,source2); } *sk1 |= (STORKEY_REF | STORKEY_CHANGE); } else { /* First operand crosses a boundary */ len2 = 0x800 - (addr1 & 0x7FF); dest2 = MADDR ((addr1 + len2) & ADDRESS_MAXWRAP(regs), arn1, regs, ACCTYPE_WRITE_SKP, regs->psw.pkey); sk2 = regs->dat.storkey; if ( NOCROSS2K(addr2,len) ) { /* (3) - First operand crosses a boundary */ for ( i = 0; i < len2; i++) MOVE_ZONE_BUMP(dest1,source1); len2 = len - len2; for ( i = 0; i <= len2; i++) MOVE_ZONE_BUMP(dest2,source1); } else { /* (4) - Both operands cross a boundary */ len3 = 0x800 - (addr2 & 0x7FF); source2 = MADDR ((addr2 + len3) & ADDRESS_MAXWRAP(regs), arn2, regs, ACCTYPE_READ, regs->psw.pkey); if (len2 == len3) { /* (4a) - Both operands cross at the same time */ for ( i = 0; i < len2; i++) MOVE_ZONE_BUMP(dest1,source1); len2 = len - len2; for ( i = 0; i <= len2; i++) MOVE_ZONE_BUMP(dest2,source2); } else if (len2 < len3) { /* (4b) - First operand crosses first */ for ( i = 0; i < len2; i++) MOVE_ZONE_BUMP(dest1,source1); len2 = len3 - len2; for ( i = 0; i < len2; i++) MOVE_ZONE_BUMP(dest2,source1); len2 = len - len3; for ( i = 0; i <= len2; i++) MOVE_ZONE_BUMP(dest2,source2); } else { /* (4c) - Second operand crosses first */ for ( i = 0; i < len3; i++) MOVE_ZONE_BUMP(dest1,source1); len3 = len2 - len3; for ( i = 0; i < len3; i++) MOVE_ZONE_BUMP(dest1,source2); len3 = len - len2; for ( i = 0; i <= len3; i++) MOVE_ZONE_BUMP(dest2,source2); } } *sk1 |= (STORKEY_REF | STORKEY_CHANGE); *sk2 |= (STORKEY_REF | STORKEY_CHANGE); } ITIMER_UPDATE(addr1,len,regs); } /*-------------------------------------------------------------------*/ /* 1C MR - Multiply Register [RR] */ /*-------------------------------------------------------------------*/ DEF_INST(multiply_register) { int r1, r2; /* Values of R fields */ RR(inst, regs, r1, r2); ODD_CHECK(r1, regs); /* Multiply r1+1 by r2 and place result in r1 and r1+1 */ mul_signed (&(regs->GR_L(r1)),&(regs->GR_L(r1+1)), regs->GR_L(r1+1), regs->GR_L(r2)); } /*-------------------------------------------------------------------*/ /* 5C M - Multiply [RX] */ /*-------------------------------------------------------------------*/ DEF_INST(multiply) { int r1; /* Value of R field */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ U32 n; /* 32-bit operand values */ RX(inst, regs, r1, b2, effective_addr2); ODD_CHECK(r1, regs); /* Load second operand from operand address */ n = ARCH_DEP(vfetch4) ( effective_addr2, b2, regs ); /* Multiply r1+1 by n and place result in r1 and r1+1 */ mul_signed (&(regs->GR_L(r1)), &(regs->GR_L(r1+1)), regs->GR_L(r1+1), n); } /*-------------------------------------------------------------------*/ /* 4C MH - Multiply Halfword [RX] */ /*-------------------------------------------------------------------*/ DEF_INST(multiply_halfword) { int r1; /* Value of R field */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ S32 n; /* 32-bit operand values */ RX(inst, regs, r1, b2, effective_addr2); /* Load 2 bytes from operand address */ n = (S16)ARCH_DEP(vfetch2) ( effective_addr2, b2, regs ); /* Multiply R1 register by n, ignore leftmost 32 bits of result, and place rightmost 32 bits in R1 register */ mul_signed ((U32 *)&n, &(regs->GR_L(r1)), regs->GR_L(r1), n); } #if defined(FEATURE_IMMEDIATE_AND_RELATIVE) /*-------------------------------------------------------------------*/ /* A7xC MHI - Multiply Halfword Immediate [RI] */ /*-------------------------------------------------------------------*/ DEF_INST(multiply_halfword_immediate) { int r1; /* Register number */ int opcd; /* Opcode */ U16 i2; /* 16-bit operand */ RI0(inst, regs, r1, opcd, i2); /* Multiply register by operand ignoring overflow */ regs->GR_L(r1) = (S32)regs->GR_L(r1) * (S16)i2; } /* end DEF_INST(multiply_halfword_immediate) */ /*-------------------------------------------------------------------*/ /* B252 MSR - Multiply Single Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(multiply_single_register) { int r1, r2; /* Values of R fields */ RRE0(inst, regs, r1, r2); /* Multiply signed registers ignoring overflow */ regs->GR_L(r1) = (S32)regs->GR_L(r1) * (S32)regs->GR_L(r2); } /* end DEF_INST(multiply_single_register) */ /*-------------------------------------------------------------------*/ /* 71 MS - Multiply Single [RX] */ /*-------------------------------------------------------------------*/ DEF_INST(multiply_single) { int r1; /* Value of R field */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ U32 n; /* 32-bit operand values */ RX(inst, regs, r1, b2, effective_addr2); /* Load second operand from operand address */ n = ARCH_DEP(vfetch4) ( effective_addr2, b2, regs ); /* Multiply signed operands ignoring overflow */ regs->GR_L(r1) = (S32)regs->GR_L(r1) * (S32)n; } /* end DEF_INST(multiply_single) */ #endif /*defined(FEATURE_IMMEDIATE_AND_RELATIVE)*/ #if !defined(_GEN_ARCH) #if defined(_ARCHMODE2) #define _GEN_ARCH _ARCHMODE2 #include "general1.c" #endif #if defined(_ARCHMODE3) #undef _GEN_ARCH #define _GEN_ARCH _ARCHMODE3 #include "general1.c" #endif #endif /*!defined(_GEN_ARCH)*/ hercules-3.07/general2.c000644 000765 000765 00000304145 11157241226 016616 0ustar00jmaynardjmaynard000000 000000 /* GENERAL2.C (c) Copyright Roger Bowler, 1994-2009 */ /* ESA/390 CPU Emulator */ /* Instructions N-Z */ // $Id: general2.c 5222 2009-03-01 12:28:49Z jj $ /* (c) Copyright Peter Kuschnerus, 1999-2009 (UPT & CFC)*/ /* Interpretive Execution - (c) Copyright Jan Jaeger, 1999-2009 */ /* z/Architecture support - (c) Copyright Jan Jaeger, 1999-2009 */ /*-------------------------------------------------------------------*/ /* This module implements all general instructions of the */ /* S/370 and ESA/390 architectures, as described in the manuals */ /* GA22-7000-03 System/370 Principles of Operation */ /* SA22-7201-06 ESA/390 Principles of Operation */ /*-------------------------------------------------------------------*/ /*-------------------------------------------------------------------*/ /* Additional credits: */ /* Corrections to shift instructions by Jay Maynard, Jan Jaeger */ /* Branch tracing by Jan Jaeger */ /* Instruction decode by macros - Jan Jaeger */ /* Prevent TOD from going backwards in time - Jan Jaeger */ /* Fix STCKE instruction - Bernard van der Helm */ /* Instruction decode rework - Jan Jaeger */ /* Make STCK update the TOD clock - Jay Maynard */ /* Fix address wraparound in MVO - Jan Jaeger */ /* PLO instruction - Jan Jaeger */ /* Modifications for Interpretive Execution (SIE) by Jan Jaeger */ /* Clear TEA on data exception - Peter Kuschnerus v209*/ /*-------------------------------------------------------------------*/ // $Log$ // Revision 1.127 2009/01/23 11:56:02 bernard // copyright notice // // Revision 1.126 2008/03/28 13:36:25 rbowler // Fix incorrect registers when cc=1 for TRTE,TRTRE // // Revision 1.125 2008/03/27 16:45:17 rbowler // TRTE and TRTRE incorrectly return cc=3 // // Revision 1.124 2008/03/06 16:10:35 rbowler // Remove extraneous trailing blanks (cosmetic change only) // // Revision 1.123 2008/03/01 15:15:41 bernard // Removed the silly control-M characters // // Revision 1.122 2008/03/01 12:19:04 rbowler // Rename new features to include the word facility // // Revision 1.121 2008/03/01 07:51:00 bernard // TRTE, TRTRE: Checking for a_bit and ch>255 is double. Removed the a_bit. // // Revision 1.120 2008/02/29 16:25:13 bernard // Added Parsing Enhancement Facility // // Revision 1.119 2008/02/15 21:21:18 ptl00 // Fix STCKE so that byte 0 is cleared // // Revision 1.118 2008/01/24 00:59:03 gsmith // Fix and optimize TR instruction // // Revision 1.117 2007/12/30 17:48:21 bernard // Anoter UTF xlate error // // Revision 1.116 2007/12/30 09:09:51 bernard // Some errors in UTF translation // // Revision 1.115 2007/11/30 15:14:14 rbowler // Permit String-Instruction facility to be activated in S/370 mode // // Revision 1.114 2007/06/23 00:04:10 ivan // Update copyright notices to include current year (2007) // // Revision 1.113 2007/01/13 07:21:48 bernard // backout ccmask // // Revision 1.112 2007/01/12 15:23:51 bernard // ccmask phase 1 // // Revision 1.111 2007/01/09 05:10:19 gsmith // Tweaks to lm/stm // // Revision 1.110 2007/01/04 23:12:04 gsmith // remove thunk calls for program_interrupt // // Revision 1.109 2006/12/31 21:16:32 gsmith // 2006 Dec 31 really back out mainlockx.pat // // Revision 1.108 2006/12/20 09:09:40 jj // Fix bogus log entries // // Revision 1.107 2006/12/20 04:26:20 gsmith // 19 Dec 2006 ip_all.pat - performance patch - Greg Smith // // Revision 1.106 2006/12/20 04:22:00 gsmith // 2006 Dec 19 Backout mainlockx.pat - possible SMP problems - Greg Smith // // Revision 1.105 2006/12/08 09:43:21 jj // Add CVS message log // #include "hstdinc.h" #if !defined(_HENGINE_DLL_) #define _HENGINE_DLL_ #endif #if !defined(_GENERAL2_C_) #define _GENERAL2_C_ #endif #include "hercules.h" #include "opcode.h" #include "inline.h" #include "clock.h" /*-------------------------------------------------------------------*/ /* 16 OR - Or Register [RR] */ /*-------------------------------------------------------------------*/ DEF_INST(or_register) { int r1, r2; /* Values of R fields */ RR0(inst, regs, r1, r2); /* OR second operand with first and set condition code */ regs->psw.cc = ( regs->GR_L(r1) |= regs->GR_L(r2) ) ? 1 : 0; } /*-------------------------------------------------------------------*/ /* 56 O - Or [RX] */ /*-------------------------------------------------------------------*/ DEF_INST(or) { int r1; /* Value of R field */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ U32 n; /* 32-bit operand values */ RX(inst, regs, r1, b2, effective_addr2); /* Load second operand from operand address */ n = ARCH_DEP(vfetch4) ( effective_addr2, b2, regs ); /* OR second operand with first and set condition code */ regs->psw.cc = ( regs->GR_L(r1) |= n ) ? 1 : 0; } /*-------------------------------------------------------------------*/ /* 96 OI - Or Immediate [SI] */ /*-------------------------------------------------------------------*/ DEF_INST(or_immediate) { BYTE i2; /* Immediate operand byte */ int b1; /* Base of effective addr */ VADR effective_addr1; /* Effective address */ BYTE *dest; /* Pointer to target byte */ SI(inst, regs, i2, b1, effective_addr1); ITIMER_SYNC(effective_addr1,1,regs); /* Get byte mainstor address */ dest = MADDR (effective_addr1, b1, regs, ACCTYPE_WRITE, regs->psw.pkey ); /* OR byte with immediate operand, setting condition code */ regs->psw.cc = ((*dest |= i2) != 0); ITIMER_UPDATE(effective_addr1,1,regs); } /*-------------------------------------------------------------------*/ /* D6 OC - Or Characters [SS] */ /*-------------------------------------------------------------------*/ DEF_INST(or_character) { int len, len2, len3; /* Lengths to copy */ int b1, b2; /* Base register numbers */ VADR addr1, addr2; /* Virtual addresses */ BYTE *dest1, *dest2; /* Destination addresses */ BYTE *source1, *source2; /* Source addresses */ BYTE *sk1, *sk2; /* Storage key addresses */ int i; /* Loop counter */ int cc = 0; /* Condition code */ SS_L(inst, regs, len, b1, addr1, b2, addr2); ITIMER_SYNC(addr1,len,regs); ITIMER_SYNC(addr2,len,regs); /* Quick out for 1 byte (no boundary crossed) */ if (unlikely(len == 0)) { source1 = MADDR (addr2, b2, regs, ACCTYPE_READ, regs->psw.pkey); dest1 = MADDR (addr1, b1, regs, ACCTYPE_WRITE, regs->psw.pkey); *dest1 |= *source1; regs->psw.cc = (*dest1 != 0); ITIMER_UPDATE(addr1,len,regs); return; } /* There are several scenarios (in optimal order): * (1) dest boundary and source boundary not crossed * (2) dest boundary not crossed and source boundary crossed * (3) dest boundary crossed and source boundary not crossed * (4) dest boundary and source boundary are crossed * (a) dest and source boundary cross at the same time * (b) dest boundary crossed first * (c) source boundary crossed first */ /* Translate addresses of leftmost operand bytes */ dest1 = MADDR (addr1, b1, regs, ACCTYPE_WRITE_SKP, regs->psw.pkey); sk1 = regs->dat.storkey; source1 = MADDR (addr2, b2, regs, ACCTYPE_READ, regs->psw.pkey); if ( NOCROSS2K(addr1,len) ) { if ( NOCROSS2K(addr2,len) ) { /* (1) - No boundaries are crossed */ for (i = 0; i <= len; i++) if (*dest1++ |= *source1++) cc = 1; } else { /* (2) - Second operand crosses a boundary */ len2 = 0x800 - (addr2 & 0x7FF); source2 = MADDR ((addr2 + len2) & ADDRESS_MAXWRAP(regs), b2, regs, ACCTYPE_READ, regs->psw.pkey); for ( i = 0; i < len2; i++) if (*dest1++ |= *source1++) cc = 1; len2 = len - len2; for ( i = 0; i <= len2; i++) if (*dest1++ |= *source2++) cc = 1; } *sk1 |= (STORKEY_REF | STORKEY_CHANGE); } else { /* First operand crosses a boundary */ len2 = 0x800 - (addr1 & 0x7FF); dest2 = MADDR ((addr1 + len2) & ADDRESS_MAXWRAP(regs), b1, regs, ACCTYPE_WRITE_SKP, regs->psw.pkey); sk2 = regs->dat.storkey; if ( NOCROSS2K(addr2,len) ) { /* (3) - First operand crosses a boundary */ for ( i = 0; i < len2; i++) if (*dest1++ |= *source1++) cc = 1; len2 = len - len2; for ( i = 0; i <= len2; i++) if (*dest2++ |= *source1++) cc = 1; } else { /* (4) - Both operands cross a boundary */ len3 = 0x800 - (addr2 & 0x7FF); source2 = MADDR ((addr2 + len3) & ADDRESS_MAXWRAP(regs), b2, regs, ACCTYPE_READ, regs->psw.pkey); if (len2 == len3) { /* (4a) - Both operands cross at the same time */ for ( i = 0; i < len2; i++) if (*dest1++ |= *source1++) cc = 1; len2 = len - len2; for ( i = 0; i <= len2; i++) if (*dest2++ |= *source2++) cc = 1; } else if (len2 < len3) { /* (4b) - First operand crosses first */ for ( i = 0; i < len2; i++) if (*dest1++ |= *source1++) cc = 1; len2 = len3 - len2; for ( i = 0; i < len2; i++) if (*dest2++ |= *source1++) cc = 1; len2 = len - len3; for ( i = 0; i <= len2; i++) if (*dest2++ |= *source2++) cc = 1; } else { /* (4c) - Second operand crosses first */ for ( i = 0; i < len3; i++) if (*dest1++ |= *source1++) cc = 1; len3 = len2 - len3; for ( i = 0; i < len3; i++) if (*dest1++ |= *source2++) cc = 1; len3 = len - len2; for ( i = 0; i <= len3; i++) if (*dest2++ |= *source2++) cc = 1; } } *sk1 |= (STORKEY_REF | STORKEY_CHANGE); *sk2 |= (STORKEY_REF | STORKEY_CHANGE); } regs->psw.cc = cc; ITIMER_UPDATE(addr1,len,regs); } /*-------------------------------------------------------------------*/ /* F2 PACK - Pack [SS] */ /*-------------------------------------------------------------------*/ DEF_INST(pack) { int l1, l2; /* Lenght values */ int b1, b2; /* Values of base registers */ VADR effective_addr1, effective_addr2; /* Effective addresses */ int i, j; /* Loop counters */ BYTE sbyte; /* Source operand byte */ BYTE dbyte; /* Destination operand byte */ SS(inst, regs, l1, l2, b1, effective_addr1, b2, effective_addr2); /* If operand 1 crosses a page, make sure both pages are accessable */ if((effective_addr1 & PAGEFRAME_PAGEMASK) != ((effective_addr1 + l1) & PAGEFRAME_PAGEMASK)) ARCH_DEP(validate_operand) (effective_addr1, b1, l1, ACCTYPE_WRITE_SKP, regs); /* If operand 2 crosses a page, make sure both pages are accessable */ if((effective_addr2 & PAGEFRAME_PAGEMASK) != ((effective_addr2 + l2) & PAGEFRAME_PAGEMASK)) ARCH_DEP(validate_operand) (effective_addr2, b2, l2, ACCTYPE_READ, regs); /* Exchange the digits in the rightmost byte */ effective_addr1 += l1; effective_addr2 += l2; sbyte = ARCH_DEP(vfetchb) ( effective_addr2, b2, regs ); dbyte = (sbyte << 4) | (sbyte >> 4); ARCH_DEP(vstoreb) ( dbyte, effective_addr1, b1, regs ); /* Process remaining bytes from right to left */ for (i = l1, j = l2; i > 0; i--) { /* Fetch source bytes from second operand */ if (j-- > 0) { sbyte = ARCH_DEP(vfetchb) ( --effective_addr2, b2, regs ); dbyte = sbyte & 0x0F; if (j-- > 0) { effective_addr2 &= ADDRESS_MAXWRAP(regs); sbyte = ARCH_DEP(vfetchb) ( --effective_addr2, b2, regs ); dbyte |= sbyte << 4; } } else { dbyte = 0; } /* Store packed digits at first operand address */ ARCH_DEP(vstoreb) ( dbyte, --effective_addr1, b1, regs ); /* Wraparound according to addressing mode */ effective_addr1 &= ADDRESS_MAXWRAP(regs); effective_addr2 &= ADDRESS_MAXWRAP(regs); } /* end for(i) */ } #if defined(FEATURE_PERFORM_LOCKED_OPERATION) /*-------------------------------------------------------------------*/ /* EE PLO - Perform Locked Operation [SS] */ /*-------------------------------------------------------------------*/ DEF_INST(perform_locked_operation) { int r1, r3; /* Lenght values */ int b2, b4; /* Values of base registers */ VADR effective_addr2, effective_addr4; /* Effective addresses */ SS(inst, regs, r1, r3, b2, effective_addr2, b4, effective_addr4); if(regs->GR_L(0) & PLO_GPR0_RESV) regs->program_interrupt(regs, PGM_SPECIFICATION_EXCEPTION); if(regs->GR_L(0) & PLO_GPR0_T) switch(regs->GR_L(0) & PLO_GPR0_FC) { case PLO_CL: case PLO_CLG: case PLO_CS: case PLO_CSG: case PLO_DCS: case PLO_DCSG: case PLO_CSST: case PLO_CSSTG: case PLO_CSDST: case PLO_CSDSTG: case PLO_CSTST: case PLO_CSTSTG: #if defined(FEATURE_ESAME) case PLO_CLGR: case PLO_CLX: case PLO_CSGR: case PLO_CSX: case PLO_DCSGR: case PLO_DCSX: case PLO_CSSTGR: case PLO_CSSTX: case PLO_CSDSTGR: case PLO_CSDSTX: case PLO_CSTSTGR: case PLO_CSTSTX: #endif /*defined(FEATURE_ESAME)*/ /* Indicate function supported */ regs->psw.cc = 0; break; default: PTT(PTT_CL_ERR,"*PLO",regs->GR_L(0),regs->GR_L(r1),regs->psw.IA_L); /* indicate function not supported */ regs->psw.cc = 3; break; } else { /* gpr1/ar1 indentify the program lock token, which is used to select a lock from the model dependent number of locks in the configuration. We simply use 1 lock which is the main storage access lock which is also used by CS, CDS and TS. *JJ */ OBTAIN_MAINLOCK(regs); switch(regs->GR_L(0) & PLO_GPR0_FC) { case PLO_CL: regs->psw.cc = ARCH_DEP(plo_cl) (r1, r3, effective_addr2, b2, effective_addr4, b4, regs); break; case PLO_CLG: regs->psw.cc = ARCH_DEP(plo_clg) (r1, r3, effective_addr2, b2, effective_addr4, b4, regs); break; case PLO_CS: regs->psw.cc = ARCH_DEP(plo_cs) (r1, r3, effective_addr2, b2, effective_addr4, b4, regs); break; case PLO_CSG: regs->psw.cc = ARCH_DEP(plo_csg) (r1, r3, effective_addr2, b2, effective_addr4, b4, regs); break; case PLO_DCS: regs->psw.cc = ARCH_DEP(plo_dcs) (r1, r3, effective_addr2, b2, effective_addr4, b4, regs); break; case PLO_DCSG: regs->psw.cc = ARCH_DEP(plo_dcsg) (r1, r3, effective_addr2, b2, effective_addr4, b4, regs); break; case PLO_CSST: regs->psw.cc = ARCH_DEP(plo_csst) (r1, r3, effective_addr2, b2, effective_addr4, b4, regs); break; case PLO_CSSTG: regs->psw.cc = ARCH_DEP(plo_csstg) (r1, r3, effective_addr2, b2, effective_addr4, b4, regs); break; case PLO_CSDST: regs->psw.cc = ARCH_DEP(plo_csdst) (r1, r3, effective_addr2, b2, effective_addr4, b4, regs); break; case PLO_CSDSTG: regs->psw.cc = ARCH_DEP(plo_csdstg) (r1, r3, effective_addr2, b2, effective_addr4, b4, regs); break; case PLO_CSTST: regs->psw.cc = ARCH_DEP(plo_cstst) (r1, r3, effective_addr2, b2, effective_addr4, b4, regs); break; case PLO_CSTSTG: regs->psw.cc = ARCH_DEP(plo_cststg) (r1, r3, effective_addr2, b2, effective_addr4, b4, regs); break; #if defined(FEATURE_ESAME) case PLO_CLGR: regs->psw.cc = ARCH_DEP(plo_clgr) (r1, r3, effective_addr2, b2, effective_addr4, b4, regs); break; case PLO_CLX: regs->psw.cc = ARCH_DEP(plo_clx) (r1, r3, effective_addr2, b2, effective_addr4, b4, regs); break; case PLO_CSGR: regs->psw.cc = ARCH_DEP(plo_csgr) (r1, r3, effective_addr2, b2, effective_addr4, b4, regs); break; case PLO_CSX: regs->psw.cc = ARCH_DEP(plo_csx) (r1, r3, effective_addr2, b2, effective_addr4, b4, regs); break; case PLO_DCSGR: regs->psw.cc = ARCH_DEP(plo_dcsgr) (r1, r3, effective_addr2, b2, effective_addr4, b4, regs); break; case PLO_DCSX: regs->psw.cc = ARCH_DEP(plo_dcsx) (r1, r3, effective_addr2, b2, effective_addr4, b4, regs); break; case PLO_CSSTGR: regs->psw.cc = ARCH_DEP(plo_csstgr) (r1, r3, effective_addr2, b2, effective_addr4, b4, regs); break; case PLO_CSSTX: regs->psw.cc = ARCH_DEP(plo_csstx) (r1, r3, effective_addr2, b2, effective_addr4, b4, regs); break; case PLO_CSDSTGR: regs->psw.cc = ARCH_DEP(plo_csdstgr) (r1, r3, effective_addr2, b2, effective_addr4, b4, regs); break; case PLO_CSDSTX: regs->psw.cc = ARCH_DEP(plo_csdstx) (r1, r3, effective_addr2, b2, effective_addr4, b4, regs); break; case PLO_CSTSTGR: regs->psw.cc = ARCH_DEP(plo_cststgr) (r1, r3, effective_addr2, b2, effective_addr4, b4, regs); break; case PLO_CSTSTX: regs->psw.cc = ARCH_DEP(plo_cststx) (r1, r3, effective_addr2, b2, effective_addr4, b4, regs); break; #endif /*defined(FEATURE_ESAME)*/ default: regs->program_interrupt(regs, PGM_SPECIFICATION_EXCEPTION); } /* Release main-storage access lock */ RELEASE_MAINLOCK(regs); if(regs->psw.cc && sysblk.cpus > 1) { PTT(PTT_CL_CSF,"*PLO",regs->GR_L(0),regs->GR_L(r1),regs->psw.IA_L); sched_yield(); } } } #endif /*defined(FEATURE_PERFORM_LOCKED_OPERATION)*/ #if defined(FEATURE_STRING_INSTRUCTION) /*-------------------------------------------------------------------*/ /* B25E SRST - Search String [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(search_string) { int r1, r2; /* Values of R fields */ int i; /* Loop counter */ VADR addr1, addr2; /* End/start addresses */ BYTE sbyte; /* String character */ BYTE termchar; /* Terminating character */ RRE(inst, regs, r1, r2); /* Program check if bits 0-23 of register 0 not zero */ if ((regs->GR_L(0) & 0xFFFFFF00) != 0) regs->program_interrupt (regs, PGM_SPECIFICATION_EXCEPTION); /* Load string terminating character from register 0 bits 24-31 */ termchar = regs->GR_LHLCL(0); /* Determine the operand end and start addresses */ addr1 = regs->GR(r1) & ADDRESS_MAXWRAP(regs); addr2 = regs->GR(r2) & ADDRESS_MAXWRAP(regs); /* Search up to 256 bytes or until end of operand */ for (i = 0; i < 0x100; i++) { /* If operand end address has been reached, return condition code 2 and leave the R1 and R2 registers unchanged */ if (addr2 == addr1) { regs->psw.cc = 2; return; } /* Fetch a byte from the operand */ sbyte = ARCH_DEP(vfetchb) ( addr2, r2, regs ); /* If the terminating character was found, return condition code 1 and load the address of the character into R1 */ if (sbyte == termchar) { SET_GR_A(r1, regs, addr2); regs->psw.cc = 1; return; } /* Increment operand address */ addr2++; addr2 &= ADDRESS_MAXWRAP(regs); } /* end for(i) */ /* Set R2 to point to next character of operand */ SET_GR_A(r2, regs, addr2); /* Return condition code 3 */ regs->psw.cc = 3; } /* end DEF_INST(search_string) */ #endif /*defined(FEATURE_STRING_INSTRUCTION)*/ #if defined(FEATURE_ACCESS_REGISTERS) /*-------------------------------------------------------------------*/ /* B24E SAR - Set Access Register [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(set_access_register) { int r1, r2; /* Values of R fields */ RRE0(inst, regs, r1, r2); /* Copy R2 general register to R1 access register */ regs->AR(r1) = regs->GR_L(r2); SET_AEA_AR(regs, r1); } #endif /*defined(FEATURE_ACCESS_REGISTERS)*/ /*-------------------------------------------------------------------*/ /* 04 SPM - Set Program Mask [RR] */ /*-------------------------------------------------------------------*/ DEF_INST(set_program_mask) { int r1, r2; /* Values of R fields */ RR0(inst, regs, r1, r2); /* Set condition code from bits 2-3 of R1 register */ regs->psw.cc = ( regs->GR_L(r1) & 0x30000000 ) >> 28; /* Set program mask from bits 4-7 of R1 register */ regs->psw.progmask = ( regs->GR_L(r1) >> 24) & PSW_PROGMASK; } /*-------------------------------------------------------------------*/ /* 8F SLDA - Shift Left Double [RS] */ /*-------------------------------------------------------------------*/ DEF_INST(shift_left_double) { int r1, r3; /* Register numbers */ int b2; /* effective address base */ VADR effective_addr2; /* effective address */ U32 n; /* 32-bit operand values */ U64 dreg; /* Double register work area */ U32 h, i, j, m; /* Integer work areas */ RS(inst, regs, r1, r3, b2, effective_addr2); ODD_CHECK(r1, regs); /* Use rightmost six bits of operand address as shift count */ n = effective_addr2 & 0x3F; /* Load the signed value from the R1 and R1+1 registers */ dreg = (U64)regs->GR_L(r1) << 32 | regs->GR_L(r1+1); m = ((S64)dreg < 0) ? 1 : 0; /* Shift the numeric portion of the value */ for (i = 0, j = 0; i < n; i++) { /* Shift bits 1-63 left one bit position */ dreg <<= 1; /* Overflow if bit shifted out is unlike the sign bit */ h = ((S64)dreg < 0) ? 1 : 0; if (h != m) j = 1; } /* Load updated value into the R1 and R1+1 registers */ regs->GR_L(r1) = (dreg >> 32) & 0x7FFFFFFF; if (m) regs->GR_L(r1) |= 0x80000000; regs->GR_L(r1+1) = dreg & 0xFFFFFFFF; /* Condition code 3 and program check if overflow occurred */ if (j) { regs->psw.cc = 3; if ( FOMASK(®s->psw) ) regs->program_interrupt (regs, PGM_FIXED_POINT_OVERFLOW_EXCEPTION); return; } /* Set the condition code */ regs->psw.cc = (S64)dreg > 0 ? 2 : (S64)dreg < 0 ? 1 : 0; } /*-------------------------------------------------------------------*/ /* 8D SLDL - Shift Left Double Logical [RS] */ /*-------------------------------------------------------------------*/ DEF_INST(shift_left_double_logical) { int r1, r3; /* Register numbers */ int b2; /* effective address base */ VADR effective_addr2; /* effective address */ U32 n; /* 32-bit operand values */ U64 dreg; /* Double register work area */ RS(inst, regs, r1, r3, b2, effective_addr2); ODD_CHECK(r1, regs); /* Use rightmost six bits of operand address as shift count */ n = effective_addr2 & 0x3F; /* Shift the R1 and R1+1 registers */ dreg = (U64)regs->GR_L(r1) << 32 | regs->GR_L(r1+1); dreg <<= n; regs->GR_L(r1) = dreg >> 32; regs->GR_L(r1+1) = dreg & 0xFFFFFFFF; } /*-------------------------------------------------------------------*/ /* 8B SLA - Shift Left Single [RS] */ /*-------------------------------------------------------------------*/ DEF_INST(shift_left_single) { int r1, r3; /* Register numbers */ int b2; /* effective address base */ VADR effective_addr2; /* effective address */ U32 n, n1, n2; /* 32-bit operand values */ U32 i, j; /* Integer work areas */ RS(inst, regs, r1, r3, b2, effective_addr2); /* Use rightmost six bits of operand address as shift count */ n = effective_addr2 & 0x3F; /* Fast path if no possible overflow */ if (regs->GR_L(r1) < 0x10000 && n < 16) { regs->GR_L(r1) <<= n; regs->psw.cc = regs->GR_L(r1) ? 2 : 0; return; } /* Load the numeric and sign portions from the R1 register */ n1 = regs->GR_L(r1) & 0x7FFFFFFF; n2 = regs->GR_L(r1) & 0x80000000; /* Shift the numeric portion left n positions */ for (i = 0, j = 0; i < n; i++) { /* Shift bits 1-31 left one bit position */ n1 <<= 1; /* Overflow if bit shifted out is unlike the sign bit */ if ((n1 & 0x80000000) != n2) j = 1; } /* Load the updated value into the R1 register */ regs->GR_L(r1) = (n1 & 0x7FFFFFFF) | n2; /* Condition code 3 and program check if overflow occurred */ if (j) { regs->psw.cc = 3; if ( FOMASK(®s->psw) ) regs->program_interrupt (regs, PGM_FIXED_POINT_OVERFLOW_EXCEPTION); return; } /* Set the condition code */ regs->psw.cc = (S32)regs->GR_L(r1) > 0 ? 2 : (S32)regs->GR_L(r1) < 0 ? 1 : 0; } /*-------------------------------------------------------------------*/ /* 89 SLL - Shift Left Single Logical [RS] */ /*-------------------------------------------------------------------*/ DEF_INST(shift_left_single_logical) { int r1, r3; /* Register numbers */ int b2; /* effective address base */ VADR effective_addr2; /* effective address */ U32 n; /* Integer work areas */ RS0(inst, regs, r1, r3, b2, effective_addr2); /* Use rightmost six bits of operand address as shift count */ n = effective_addr2 & 0x3F; /* Shift the R1 register */ regs->GR_L(r1) = n > 31 ? 0 : regs->GR_L(r1) << n; } /*-------------------------------------------------------------------*/ /* 8E SRDA - Shift Right Double [RS] */ /*-------------------------------------------------------------------*/ DEF_INST(shift_right_double) { int r1, r3; /* Register numbers */ int b2; /* effective address base */ VADR effective_addr2; /* effective address */ U32 n; /* 32-bit operand values */ U64 dreg; /* Double register work area */ RS(inst, regs, r1, r3, b2, effective_addr2); ODD_CHECK(r1, regs); /* Use rightmost six bits of operand address as shift count */ n = effective_addr2 & 0x3F; /* Shift the R1 and R1+1 registers */ dreg = (U64)regs->GR_L(r1) << 32 | regs->GR_L(r1+1); dreg = (U64)((S64)dreg >> n); regs->GR_L(r1) = dreg >> 32; regs->GR_L(r1+1) = dreg & 0xFFFFFFFF; /* Set the condition code */ regs->psw.cc = (S64)dreg > 0 ? 2 : (S64)dreg < 0 ? 1 : 0; } /*-------------------------------------------------------------------*/ /* 8C SRDL - Shift Right Double Logical [RS] */ /*-------------------------------------------------------------------*/ DEF_INST(shift_right_double_logical) { int r1, r3; /* Register numbers */ int b2; /* effective address base */ VADR effective_addr2; /* effective address */ U32 n; /* 32-bit operand values */ U64 dreg; /* Double register work area */ RS(inst, regs, r1, r3, b2, effective_addr2); ODD_CHECK(r1, regs); /* Use rightmost six bits of operand address as shift count */ n = effective_addr2 & 0x3F; /* Shift the R1 and R1+1 registers */ dreg = (U64)regs->GR_L(r1) << 32 | regs->GR_L(r1+1); dreg >>= n; regs->GR_L(r1) = dreg >> 32; regs->GR_L(r1+1) = dreg & 0xFFFFFFFF; } /*-------------------------------------------------------------------*/ /* 8A SRA - Shift Right Single [RS] */ /*-------------------------------------------------------------------*/ DEF_INST(shift_right_single) { int r1, r3; /* Register numbers */ int b2; /* effective address base */ VADR effective_addr2; /* effective address */ U32 n; /* Integer work areas */ RS0(inst, regs, r1, r3, b2, effective_addr2); /* Use rightmost six bits of operand address as shift count */ n = effective_addr2 & 0x3F; /* Shift the signed value of the R1 register */ regs->GR_L(r1) = n > 30 ? ((S32)regs->GR_L(r1) < 0 ? -1 : 0) : (S32)regs->GR_L(r1) >> n; /* Set the condition code */ regs->psw.cc = ((S32)regs->GR_L(r1) > 0) ? 2 : (((S32)regs->GR_L(r1) < 0) ? 1 : 0); } /*-------------------------------------------------------------------*/ /* 88 SRL - Shift Right Single Logical [RS] */ /*-------------------------------------------------------------------*/ DEF_INST(shift_right_single_logical) { int r1, r3; /* Register numbers */ int b2; /* effective address base */ VADR effective_addr2; /* effective address */ U32 n; /* Integer work areas */ RS0(inst, regs, r1, r3, b2, effective_addr2); /* Use rightmost six bits of operand address as shift count */ n = effective_addr2 & 0x3F; /* Shift the R1 register */ regs->GR_L(r1) = n > 31 ? 0 : regs->GR_L(r1) >> n; } /*-------------------------------------------------------------------*/ /* 50 ST - Store [RX] */ /*-------------------------------------------------------------------*/ DEF_INST(store) { int r1; /* Values of R fields */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ #if 0 U32 *p; /* Mainstor pointer */ #endif RX(inst, regs, r1, b2, effective_addr2); /* Store register contents at operand address */ /* FOLLOWING BLOCK COMMENTED OUT ISW 20060119 */ #if 0 if ((effective_addr2 & 3) == 0) { p = (U32*)MADDR(effective_addr2, b2, regs, ACCTYPE_WRITE, regs->psw.pkey); STORE_FW (p, regs->GR_L(r1)); ITIMER_UPDATE(effective_addr2, 4-1, regs); } else #endif ARCH_DEP(vstore4) ( regs->GR_L(r1), effective_addr2, b2, regs ); } /* end DEF_INST(store) */ #if defined(FEATURE_ACCESS_REGISTERS) /*-------------------------------------------------------------------*/ /* 9B STAM - Store Access Multiple [RS] */ /*-------------------------------------------------------------------*/ DEF_INST(store_access_multiple) { int r1, r3; /* Register numbers */ int b2; /* effective address base */ VADR effective_addr2; /* effective address */ int i, m, n; /* Integer work area */ U32 *p1, *p2 = NULL; /* Mainstor pointers */ RS(inst, regs, r1, r3, b2, effective_addr2); FW_CHECK(effective_addr2, regs); /* Calculate number of regs to store */ n = ((r3 - r1) & 0xF) + 1; /* Calculate number of words to next boundary */ m = (0x800 - (effective_addr2 & 0x7ff)) >> 2; /* Address of operand beginning */ p1 = (U32*)MADDR(effective_addr2, b2, regs, ACCTYPE_WRITE, regs->psw.pkey); /* Get address of next page if boundary crossed */ if (unlikely (m < n)) p2 = (U32*)MADDR(effective_addr2 + (m*4), b2, regs, ACCTYPE_WRITE, regs->psw.pkey); else m = n; /* Store to first page */ for (i = 0; i < m; i++) store_fw (p1++, regs->AR((r1 + i) & 0xF)); /* Store to next page */ for ( ; i < n; i++) store_fw (p2++, regs->AR((r1 + i) & 0xF)); } #endif /*defined(FEATURE_ACCESS_REGISTERS)*/ /*-------------------------------------------------------------------*/ /* 42 STC - Store Character [RX] */ /*-------------------------------------------------------------------*/ DEF_INST(store_character) { int r1; /* Value of R field */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ RX(inst, regs, r1, b2, effective_addr2); /* Store rightmost byte of R1 register at operand address */ ARCH_DEP(vstoreb) ( regs->GR_LHLCL(r1), effective_addr2, b2, regs ); } /*-------------------------------------------------------------------*/ /* BE STCM - Store Characters under Mask [RS] */ /*-------------------------------------------------------------------*/ DEF_INST(store_characters_under_mask) { int r1, r3; /* Register numbers */ int b2; /* effective address base */ VADR effective_addr2; /* effective address */ int i; /* Integer work area */ BYTE rbyte[4]; /* Byte work area */ RS(inst, regs, r1, r3, b2, effective_addr2); switch (r3) { case 7: /* Optimized case */ store_fw(rbyte, regs->GR_L(r1)); ARCH_DEP(vstorec) (rbyte+1, 2, effective_addr2, b2, regs); break; case 15: /* Optimized case */ ARCH_DEP(vstore4) (regs->GR_L(r1), effective_addr2, b2, regs); break; default: /* Extract value from register by mask */ i = 0; if (r3 & 0x8) rbyte[i++] = (regs->GR_L(r1) >> 24) & 0xFF; if (r3 & 0x4) rbyte[i++] = (regs->GR_L(r1) >> 16) & 0xFF; if (r3 & 0x2) rbyte[i++] = (regs->GR_L(r1) >> 8) & 0xFF; if (r3 & 0x1) rbyte[i++] = (regs->GR_L(r1) ) & 0xFF; if (i) ARCH_DEP(vstorec) (rbyte, i-1, effective_addr2, b2, regs); #if defined(MODEL_DEPENDENT_STCM) /* If the mask is all zero, we nevertheless access one byte from the storage operand, because POP states that an access exception may be recognized on the first byte */ else ARCH_DEP(validate_operand) (effective_addr2, b2, 0, ACCTYPE_WRITE, regs); #endif break; } /* switch (r3) */ } /*-------------------------------------------------------------------*/ /* B205 STCK - Store Clock [S] */ /* B27C STCKF - Store Clock Fast [S] */ /*-------------------------------------------------------------------*/ DEF_INST(store_clock) { int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ U64 dreg; /* Double word work area */ S(inst, regs, b2, effective_addr2); #if defined(_FEATURE_SIE) if(SIE_STATB(regs, IC2, STCK)) longjmp(regs->progjmp, SIE_INTERCEPT_INST); #endif /*defined(_FEATURE_SIE)*/ #if defined(FEATURE_STORE_CLOCK_FAST) if(inst[1] == 0x05) // STCK only #endif /*defined(FEATURE_STORE_CLOCK_FAST)*/ /* Perform serialization before fetching clock */ PERFORM_SERIALIZATION (regs); /* Retrieve the TOD clock value and shift out the epoch */ dreg = tod_clock(regs) << 8; #if defined(FEATURE_STORE_CLOCK_FAST) if(inst[1] == 0x05) // STCK only #endif /*defined(FEATURE_STORE_CLOCK_FAST)*/ /* Insert the cpu address to ensure a unique value */ dreg |= regs->cpuad; // /*debug*/logmsg("Store TOD clock=%16.16" I64_FMT "X\n", dreg); /* Store TOD clock value at operand address */ ARCH_DEP(vstore8) ( dreg, effective_addr2, b2, regs ); #if defined(FEATURE_STORE_CLOCK_FAST) if(inst[1] == 0x05) // STCK only #endif /*defined(FEATURE_STORE_CLOCK_FAST)*/ /* Perform serialization after storing clock */ PERFORM_SERIALIZATION (regs); /* Set condition code zero */ regs->psw.cc = 0; } #if defined(FEATURE_EXTENDED_TOD_CLOCK) /*-------------------------------------------------------------------*/ /* B278 STCKE - Store Clock Extended [S] */ /*-------------------------------------------------------------------*/ DEF_INST(store_clock_extended) { int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ U64 dreg; /* Double word work area */ S(inst, regs, b2, effective_addr2); #if defined(_FEATURE_SIE) if(SIE_STATB(regs, IC2, STCK)) longjmp(regs->progjmp, SIE_INTERCEPT_INST); #endif /*defined(_FEATURE_SIE)*/ /* Perform serialization before fetching clock */ PERFORM_SERIALIZATION (regs); /* Retrieve the TOD epoch, clock bits 0-51, and 4 zeroes */ dreg = 0x00ffffffffffffffULL & tod_clock(regs); /* Check that all 16 bytes of the operand are accessible */ ARCH_DEP(validate_operand) (effective_addr2, b2, 15, ACCTYPE_WRITE, regs); // /*debug*/logmsg("Store TOD clock extended: +0=%16.16" I64_FMT "X\n", // /*debug*/ dreg); /* Store the 8 bit TOD epoch, clock bits 0-51, and bits 20-23 of the TOD uniqueness value at operand address */ ARCH_DEP(vstore8) ( dreg, effective_addr2, b2, regs ); // /*debug*/logmsg("Store TOD clock extended: +8=%16.16" I64_FMT "X\n", // /*debug*/ dreg); /* Store second doubleword value at operand+8 */ effective_addr2 += 8; effective_addr2 &= ADDRESS_MAXWRAP(regs); /* Store nonzero value in pos 72 to 111 */ dreg = 0x0000000001000000ULL | (regs->cpuad << 16) | regs->todpr; ARCH_DEP(vstore8) ( dreg, effective_addr2, b2, regs ); /* Perform serialization after storing clock */ PERFORM_SERIALIZATION (regs); /* Set condition code zero */ regs->psw.cc = 0; } #endif /*defined(FEATURE_EXTENDED_TOD_CLOCK)*/ /*-------------------------------------------------------------------*/ /* 40 STH - Store Halfword [RX] */ /*-------------------------------------------------------------------*/ DEF_INST(store_halfword) { int r1; /* Value of R field */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ RX(inst, regs, r1, b2, effective_addr2); /* Store rightmost 2 bytes of R1 register at operand address */ ARCH_DEP(vstore2) ( regs->GR_LHL(r1), effective_addr2, b2, regs ); } /*-------------------------------------------------------------------*/ /* 90 STM - Store Multiple [RS] */ /*-------------------------------------------------------------------*/ DEF_INST(store_multiple) { int r1, r3; /* Register numbers */ int b2; /* effective address base */ VADR effective_addr2; /* effective address */ int i, m, n; /* Integer work areas */ U32 *p1, *p2; /* Mainstor pointers */ BYTE *bp1; /* Unaligned mainstor ptr */ RS(inst, regs, r1, r3, b2, effective_addr2); /* Calculate number of bytes to store */ n = (((r3 - r1) & 0xF) + 1) << 2; /* Calculate number of bytes to next boundary */ m = 0x800 - ((VADR_L)effective_addr2 & 0x7ff); /* Get address of first page */ bp1 = (BYTE*)MADDR(effective_addr2, b2, regs, ACCTYPE_WRITE, regs->psw.pkey); p1 = (U32*)bp1; if (likely(n <= m)) { /* boundary not crossed */ n >>= 2; #if defined(OPTION_STRICT_ALIGNMENT) if(likely(!(((uintptr_t)effective_addr2)&0x03))) { #endif for (i = 0; i < n; i++) store_fw (p1++, regs->GR_L((r1 + i) & 0xF)); #if defined(OPTION_STRICT_ALIGNMENT) } else { for (i = 0; i < n; i++,bp1+=4) store_fw (bp1, regs->GR_L((r1 + i) & 0xF)); } #endif ITIMER_UPDATE(effective_addr2,(n*4)-1,regs); } else { /* boundary crossed, get address of the 2nd page */ effective_addr2 += m; effective_addr2 &= ADDRESS_MAXWRAP(regs); p2 = (U32*)MADDR(effective_addr2, b2, regs, ACCTYPE_WRITE, regs->psw.pkey); if (likely((m & 0x3) == 0)) { /* word aligned */ m >>= 2; for (i = 0; i < m; i++) store_fw (p1++, regs->GR_L((r1 + i) & 0xF)); n >>= 2; for ( ; i < n; i++) store_fw (p2++, regs->GR_L((r1 + i) & 0xF)); } else { /* worst case */ U32 rwork[16]; BYTE *b1, *b2; for (i = 0; i < (n >> 2); i++) rwork[i] = CSWAP32(regs->GR_L((r1 + i) & 0xF)); b1 = (BYTE *)&rwork[0]; b2 = (BYTE *)p1; for (i = 0; i < m; i++) *b2++ = *b1++; b2 = (BYTE *)p2; for ( ; i < n; i++) *b2++ = *b1++; } } } /* end DEF_INST(store_multiple) */ /*-------------------------------------------------------------------*/ /* 1B SR - Subtract Register [RR] */ /*-------------------------------------------------------------------*/ DEF_INST(subtract_register) { int r1, r2; /* Values of R fields */ RR(inst, regs, r1, r2); /* Subtract signed operands and set condition code */ regs->psw.cc = sub_signed (&(regs->GR_L(r1)), regs->GR_L(r1), regs->GR_L(r2)); /* Program check if fixed-point overflow */ if ( regs->psw.cc == 3 && FOMASK(®s->psw) ) regs->program_interrupt (regs, PGM_FIXED_POINT_OVERFLOW_EXCEPTION); } /*-------------------------------------------------------------------*/ /* 5B S - Subtract [RX] */ /*-------------------------------------------------------------------*/ DEF_INST(subtract) { int r1; /* Value of R field */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ U32 n; /* 32-bit operand values */ RX(inst, regs, r1, b2, effective_addr2); /* Load second operand from operand address */ n = ARCH_DEP(vfetch4) ( effective_addr2, b2, regs ); /* Subtract signed operands and set condition code */ regs->psw.cc = sub_signed (&(regs->GR_L(r1)), regs->GR_L(r1), n); /* Program check if fixed-point overflow */ if ( regs->psw.cc == 3 && FOMASK(®s->psw) ) regs->program_interrupt (regs, PGM_FIXED_POINT_OVERFLOW_EXCEPTION); } /*-------------------------------------------------------------------*/ /* 4B SH - Subtract Halfword [RX] */ /*-------------------------------------------------------------------*/ DEF_INST(subtract_halfword) { int r1; /* Value of R field */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ U32 n; /* 32-bit operand values */ RX(inst, regs, r1, b2, effective_addr2); /* Load 2 bytes from operand address */ n = (S16)ARCH_DEP(vfetch2) ( effective_addr2, b2, regs ); /* Subtract signed operands and set condition code */ regs->psw.cc = sub_signed (&(regs->GR_L(r1)), regs->GR_L(r1), n); /* Program check if fixed-point overflow */ if ( regs->psw.cc == 3 && FOMASK(®s->psw) ) regs->program_interrupt (regs, PGM_FIXED_POINT_OVERFLOW_EXCEPTION); } /*-------------------------------------------------------------------*/ /* 1F SLR - Subtract Logical Register [RR] */ /*-------------------------------------------------------------------*/ DEF_INST(subtract_logical_register) { int r1, r2; /* Values of R fields */ RR0(inst, regs, r1, r2); /* Subtract unsigned operands and set condition code */ if (likely(r1 == r2)) { regs->psw.cc = 2; regs->GR_L(r1) = 0; } else regs->psw.cc = sub_logical (&(regs->GR_L(r1)), regs->GR_L(r1), regs->GR_L(r2)); } /*-------------------------------------------------------------------*/ /* 5F SL - Subtract Logical [RX] */ /*-------------------------------------------------------------------*/ DEF_INST(subtract_logical) { int r1; /* Value of R field */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ U32 n; /* 32-bit operand values */ RX(inst, regs, r1, b2, effective_addr2); /* Load second operand from operand address */ n = ARCH_DEP(vfetch4) ( effective_addr2, b2, regs ); /* Subtract unsigned operands and set condition code */ regs->psw.cc = sub_logical (&(regs->GR_L(r1)), regs->GR_L(r1), n); } /*-------------------------------------------------------------------*/ /* 0A SVC - Supervisor Call [RR] */ /*-------------------------------------------------------------------*/ DEF_INST(supervisor_call) { BYTE i; /* Instruction byte 1 */ PSA *psa; /* -> prefixed storage area */ RADR px; /* prefix */ int rc; /* Return code */ RR_SVC(inst, regs, i); #if defined(FEATURE_ECPSVM) if(ecpsvm_dosvc(regs,i)==0) { return; } #endif #if defined(_FEATURE_SIE) if(SIE_MODE(regs) && ( (regs->siebk->svc_ctl[0] & SIE_SVC0_ALL) || ( (regs->siebk->svc_ctl[0] & SIE_SVC0_1N) && regs->siebk->svc_ctl[1] == i) || ( (regs->siebk->svc_ctl[0] & SIE_SVC0_2N) && regs->siebk->svc_ctl[2] == i) || ( (regs->siebk->svc_ctl[0] & SIE_SVC0_3N) && regs->siebk->svc_ctl[3] == i) )) longjmp(regs->progjmp, SIE_INTERCEPT_INST); #endif /*defined(_FEATURE_SIE)*/ px = regs->PX; SIE_TRANSLATE(&px, ACCTYPE_WRITE, regs); /* Set the main storage reference and change bits */ STORAGE_KEY(px, regs) |= (STORKEY_REF | STORKEY_CHANGE); /* Use the I-byte to set the SVC interruption code */ regs->psw.intcode = i; /* OS/390 2.10 debugging for negative length GETMAIN */ #if 0 if ( (i == 0x78) || (i == 0x0a) ) { ARCH_DEP(display_inst) (regs, regs->ip); } #endif /* Point to PSA in main storage */ psa = (void*)(regs->mainstor + px); #if defined(FEATURE_BCMODE) /* For ECMODE, store SVC interrupt code at PSA+X'88' */ if ( ECMODE(®s->psw) ) #endif /*defined(FEATURE_BCMODE)*/ { psa->svcint[0] = 0; psa->svcint[1] = REAL_ILC(regs); psa->svcint[2] = 0; psa->svcint[3] = i; } /* Store current PSW at PSA+X'20' */ ARCH_DEP(store_psw) ( regs, psa->svcold ); /* Load new PSW from PSA+X'60' */ if ( (rc = ARCH_DEP(load_psw) ( regs, psa->svcnew ) ) ) regs->program_interrupt (regs, rc); /* Perform serialization and checkpoint synchronization */ PERFORM_SERIALIZATION (regs); PERFORM_CHKPT_SYNC (regs); RETURN_INTCHECK(regs); } /*-------------------------------------------------------------------*/ /* 93 TS - Test and Set [S] */ /*-------------------------------------------------------------------*/ DEF_INST(test_and_set) { int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ BYTE *main2; /* Mainstor address */ BYTE old; /* Old value */ S(inst, regs, b2, effective_addr2); ITIMER_SYNC(effective_addr2,0,regs); /* Perform serialization before starting operation */ PERFORM_SERIALIZATION (regs); /* Get operand absolute address */ main2 = MADDR (effective_addr2, b2, regs, ACCTYPE_WRITE, regs->psw.pkey); /* Obtain main-storage access lock */ OBTAIN_MAINLOCK(regs); /* Get old value */ old = *main2; /* Attempt to exchange the values */ while (cmpxchg1(&old, 255, main2)); regs->psw.cc = old >> 7; /* Release main-storage access lock */ RELEASE_MAINLOCK(regs); /* Perform serialization after completing operation */ PERFORM_SERIALIZATION (regs); if (regs->psw.cc == 1) { #if defined(_FEATURE_SIE) if(SIE_STATB(regs, IC0, TS1)) { if( !OPEN_IC_PER(regs) ) longjmp(regs->progjmp, SIE_INTERCEPT_INST); else longjmp(regs->progjmp, SIE_INTERCEPT_INSTCOMP); } else #endif /*defined(_FEATURE_SIE)*/ if (sysblk.cpus > 1) sched_yield(); } else { ITIMER_UPDATE(effective_addr2,0,regs); } } /*-------------------------------------------------------------------*/ /* 91 TM - Test under Mask [SI] */ /*-------------------------------------------------------------------*/ DEF_INST(test_under_mask) { BYTE i2; /* Immediate operand */ int b1; /* Base of effective addr */ VADR effective_addr1; /* Effective address */ BYTE tbyte; /* Work byte */ SI(inst, regs, i2, b1, effective_addr1); /* Fetch byte from operand address */ tbyte = ARCH_DEP(vfetchb) ( effective_addr1, b1, regs ); /* AND with immediate operand mask */ tbyte &= i2; /* Set condition code according to result */ regs->psw.cc = ( tbyte == 0 ) ? 0 : /* result all zeroes */ ( tbyte == i2) ? 3 : /* result all ones */ 1 ; /* result mixed */ } #if defined(FEATURE_IMMEDIATE_AND_RELATIVE) /*-------------------------------------------------------------------*/ /* A7x0 TMH - Test under Mask High [RI] */ /*-------------------------------------------------------------------*/ DEF_INST(test_under_mask_high) { int r1; /* Register number */ int opcd; /* Opcode */ U16 i2; /* 16-bit operand values */ U16 h1; /* 16-bit operand values */ U16 h2; /* 16-bit operand values */ RI0(inst, regs, r1, opcd, i2); /* AND register bits 0-15 with immediate operand */ h1 = i2 & regs->GR_LHH(r1); /* Isolate leftmost bit of immediate operand */ for ( h2 = 0x8000; h2 != 0 && (h2 & i2) == 0; h2 >>= 1 ); /* Set condition code according to result */ regs->psw.cc = ( h1 == 0 ) ? 0 : /* result all zeroes */ ( h1 == i2) ? 3 : /* result all ones */ ((h1 & h2) == 0) ? 1 : /* leftmost bit zero */ 2; /* leftmost bit one */ } #endif /*defined(FEATURE_IMMEDIATE_AND_RELATIVE)*/ #if defined(FEATURE_IMMEDIATE_AND_RELATIVE) /*-------------------------------------------------------------------*/ /* A7x1 TML - Test under Mask Low [RI] */ /*-------------------------------------------------------------------*/ DEF_INST(test_under_mask_low) { int r1; /* Register number */ int opcd; /* Opcode */ U16 i2; /* 16-bit operand values */ U16 h1; /* 16-bit operand values */ U16 h2; /* 16-bit operand values */ RI0(inst, regs, r1, opcd, i2); /* AND register bits 16-31 with immediate operand */ h1 = i2 & regs->GR_LHL(r1); /* Isolate leftmost bit of immediate operand */ for ( h2 = 0x8000; h2 != 0 && (h2 & i2) == 0; h2 >>= 1 ); /* Set condition code according to result */ regs->psw.cc = ( h1 == 0 ) ? 0 : /* result all zeroes */ ( h1 == i2) ? 3 : /* result all ones */ ((h1 & h2) == 0) ? 1 : /* leftmost bit zero */ 2; /* leftmost bit one */ } #endif /*defined(FEATURE_IMMEDIATE_AND_RELATIVE)*/ /*-------------------------------------------------------------------*/ /* DC TR - Translate [SS] */ /*-------------------------------------------------------------------*/ DEF_INST(translate) { int len, len2 = -1; /* Lengths */ int b1, b2; /* Values of base field */ int i, b, n; /* Work variables */ VADR addr1, addr2; /* Effective addresses */ BYTE *dest, *dest2 = NULL, *tab, *tab2; /* Mainstor pointers */ SS_L(inst, regs, len, b1, addr1, b2, addr2); /* Get destination pointer */ dest = MADDR (addr1, b1, regs, ACCTYPE_WRITE, regs->psw.pkey); /* Get pointer to next page if destination crosses a boundary */ if (CROSS2K (addr1, len)) { len2 = len; len = 0x7FF - (addr1 & 0x7FF); len2 -= (len + 1); dest2 = MADDR ((addr1+len+1) & ADDRESS_MAXWRAP(regs), b1, regs, ACCTYPE_WRITE, regs->psw.pkey); } /* Fast path if table does not cross a boundary */ if (NOCROSS2K (addr2, 255)) { tab = MADDR (addr2, b2, regs, ACCTYPE_READ, regs->psw.pkey); /* Perform translate function */ for (i = 0; i <= len; i++) dest[i] = tab[dest[i]]; for (i = 0; i <= len2; i++) dest2[i] = tab[dest2[i]]; } else { n = 0x800 - (addr2 & 0x7FF); b = dest[0]; /* Referenced part of the table may or may not span boundary */ if (b < n) { tab = MADDR (addr2, b2, regs, ACCTYPE_READ, regs->psw.pkey); for (i = 1; i <= len && b < n; i++) b = dest[i]; for (i = 0; i <= len2 && b < n; i++) b = dest2[i]; tab2 = b < n ? NULL : MADDR ((addr2+n) & ADDRESS_MAXWRAP(regs), b2, regs, ACCTYPE_READ, regs->psw.pkey); } else { tab2 = MADDR ((addr2+n) & ADDRESS_MAXWRAP(regs), b2, regs, ACCTYPE_READ, regs->psw.pkey); for (i = 1; i <= len && b >= n; i++) b = dest[i]; for (i = 0; i <= len2 && b >= n; i++) b = dest2[i]; tab = b >= n ? NULL : MADDR (addr2, b2, regs, ACCTYPE_READ, regs->psw.pkey); } /* Perform translate function */ for (i = 0; i <= len; i++) dest[i] = dest[i] < n ? tab[dest[i]] : tab2[dest[i]-n]; for (i = 0; i <= len2; i++) dest2[i] = dest2[i] < n ? tab[dest2[i]] : tab2[dest2[i]-n]; } /* Translate table spans a boundary */ } /*-------------------------------------------------------------------*/ /* DD TRT - Translate and Test [SS] */ /*-------------------------------------------------------------------*/ DEF_INST(translate_and_test) { int l; /* Lenght byte */ int b1, b2; /* Values of base field */ VADR effective_addr1, effective_addr2; /* Effective addresses */ int cc = 0; /* Condition code */ BYTE sbyte; /* Byte work areas */ BYTE dbyte; /* Byte work areas */ int i; /* Integer work areas */ SS_L(inst, regs, l, b1, effective_addr1, b2, effective_addr2); /* Process first operand from left to right */ for ( i = 0; i <= l; i++ ) { /* Fetch argument byte from first operand */ dbyte = ARCH_DEP(vfetchb) ( effective_addr1, b1, regs ); /* Fetch function byte from second operand */ sbyte = ARCH_DEP(vfetchb) ( (effective_addr2 + dbyte) & ADDRESS_MAXWRAP(regs), b2, regs ); /* Test for non-zero function byte */ if (sbyte != 0) { /* Store address of argument byte in register 1 */ #if defined(FEATURE_ESAME) if(regs->psw.amode64) regs->GR_G(1) = effective_addr1; else #endif if ( regs->psw.amode ) regs->GR_L(1) = effective_addr1; else regs->GR_LA24(1) = effective_addr1; /* Store function byte in low-order byte of reg.2 */ regs->GR_LHLCL(2) = sbyte; /* Set condition code 2 if argument byte was last byte of first operand, otherwise set condition code 1 */ cc = (i == l) ? 2 : 1; /* Terminate the operation at this point */ break; } /* end if(sbyte) */ /* Increment first operand address */ effective_addr1++; effective_addr1 &= ADDRESS_MAXWRAP(regs); } /* end for(i) */ /* Update the condition code */ regs->psw.cc = cc; } #ifdef FEATURE_EXTENDED_TRANSLATION /*-------------------------------------------------------------------*/ /* B2A5 TRE - Translate Extended [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(translate_extended) { int r1, r2; /* Values of R fields */ int i; /* Loop counter */ int cc = 0; /* Condition code */ VADR addr1, addr2; /* Operand addresses */ GREG len1; /* Operand length */ BYTE byte1, byte2; /* Operand bytes */ BYTE tbyte; /* Test byte */ BYTE trtab[256]; /* Translate table */ RRE(inst, regs, r1, r2); ODD_CHECK(r1, regs); /* Load the test byte from bits 24-31 of register 0 */ tbyte = regs->GR_LHLCL(0); /* Load the operand addresses */ addr1 = regs->GR(r1) & ADDRESS_MAXWRAP(regs); addr2 = regs->GR(r2) & ADDRESS_MAXWRAP(regs); /* Load first operand length from R1+1 */ len1 = GR_A(r1+1, regs); /* Fetch second operand into work area. [7.5.101] Access exceptions for all 256 bytes of the second operand may be recognized, even if not all bytes are used */ ARCH_DEP(vfetchc) ( trtab, 255, addr2, r2, regs ); /* Process first operand from left to right */ for (i = 0; len1 > 0; i++) { /* If 4096 bytes have been compared, exit with condition code 3 */ if (i >= 4096) { cc = 3; break; } /* Fetch byte from first operand */ byte1 = ARCH_DEP(vfetchb) ( addr1, r1, regs ); /* If equal to test byte, exit with condition code 1 */ if (byte1 == tbyte) { cc = 1; break; } /* Load indicated byte from translate table */ byte2 = trtab[byte1]; /* Store result at first operand address */ ARCH_DEP(vstoreb) ( byte2, addr1, r1, regs ); addr1++; addr1 &= ADDRESS_MAXWRAP(regs); len1--; /* Update the registers */ SET_GR_A(r1, regs, addr1); SET_GR_A(r1+1, regs, len1); } /* end for(i) */ /* Set condition code */ regs->psw.cc = cc; } /* end translate_extended */ #endif /*FEATURE_EXTENDED_TRANSLATION*/ /*-------------------------------------------------------------------*/ /* F3 UNPK - Unpack [SS] */ /*-------------------------------------------------------------------*/ DEF_INST(unpack) { int l1, l2; /* Register numbers */ int b1, b2; /* Base registers */ VADR effective_addr1, effective_addr2; /* Effective addressES */ int i, j; /* Loop counters */ BYTE sbyte; /* Source operand byte */ BYTE rbyte; /* Right result byte of pair */ BYTE lbyte; /* Left result byte of pair */ SS(inst, regs, l1, l2, b1, effective_addr1, b2, effective_addr2); /* If operand 1 crosses a page, make sure both pages are accessable */ if((effective_addr1 & PAGEFRAME_PAGEMASK) != ((effective_addr1 + l1) & PAGEFRAME_PAGEMASK)) ARCH_DEP(validate_operand) (effective_addr1, b1, l1, ACCTYPE_WRITE_SKP, regs); /* If operand 2 crosses a page, make sure both pages are accessable */ if((effective_addr2 & PAGEFRAME_PAGEMASK) != ((effective_addr2 + l2) & PAGEFRAME_PAGEMASK)) ARCH_DEP(validate_operand) (effective_addr2, b2, l2, ACCTYPE_READ, regs); /* Exchange the digits in the rightmost byte */ effective_addr1 += l1; effective_addr2 += l2; sbyte = ARCH_DEP(vfetchb) ( effective_addr2, b2, regs ); rbyte = (sbyte << 4) | (sbyte >> 4); ARCH_DEP(vstoreb) ( rbyte, effective_addr1, b1, regs ); /* Process remaining bytes from right to left */ for (i = l1, j = l2; i > 0; i--) { /* Fetch source byte from second operand */ if (j-- > 0) { sbyte = ARCH_DEP(vfetchb) ( --effective_addr2, b2, regs ); rbyte = (sbyte & 0x0F) | 0xF0; lbyte = (sbyte >> 4) | 0xF0; } else { rbyte = 0xF0; lbyte = 0xF0; } /* Store unpacked bytes at first operand address */ ARCH_DEP(vstoreb) ( rbyte, --effective_addr1, b1, regs ); if (--i > 0) { effective_addr1 &= ADDRESS_MAXWRAP(regs); ARCH_DEP(vstoreb) ( lbyte, --effective_addr1, b1, regs ); } /* Wraparound according to addressing mode */ effective_addr1 &= ADDRESS_MAXWRAP(regs); effective_addr2 &= ADDRESS_MAXWRAP(regs); } /* end for(i) */ } /*-------------------------------------------------------------------*/ /* 0102 UPT - Update Tree [E] */ /* (c) Copyright Peter Kuschnerus, 1999-2009 */ /* (c) Copyright "Fish" (David B. Trout), 2005-2009 */ /*-------------------------------------------------------------------*/ DEF_INST(update_tree) { GREG index; /* tree index */ GREG nodecode; /* current node's codeword */ GREG nodedata; /* current node's other data */ VADR nodeaddr; /* work addr of current node */ #if defined(FEATURE_ESAME) BYTE a64 = regs->psw.amode64; /* 64-bit mode flag */ #endif E(inst, regs); UNREFERENCED(inst); /* ** GR0, GR1 node values (codeword and other data) of node ** with "highest encountered codeword value" ** GR2, GR3 node values (codeword and other data) from whichever ** node we happened to have encountered that had a code- ** word value equal to our current "highest encountered ** codeword value" (e.g. GR0) (cc0 only) ** GR4 pointer to one node BEFORE the beginning of the tree ** GR5 current node index (tree displacement to current node) */ /* Check GR4, GR5 for proper alignment */ if (0 || ( GR_A(4,regs) & UPT_ALIGN_MASK ) || ( GR_A(5,regs) & UPT_ALIGN_MASK ) ) regs->program_interrupt (regs, PGM_SPECIFICATION_EXCEPTION); /* Bubble the tree by moving successively higher nodes towards the front (beginning) of the tree, only stopping whenever we either: 1. reach the beginning of the tree, -OR- 2. encounter a node with a negative codeword value, -OR- 3. encounter a node whose codeword is equal to our current "highest encountered codeword". Thus, when we're done, GR0 & GR1 will then contain the node values of the node with the highest encountered codeword value, and all other traversed nodes will have been reordered into descending code- word sequence (i.e. from highest codeword value to lowest codeword value; this is after all an instruction used for sorting/merging). */ for (;;) { /* Calculate index value of next node to be examined (half as far from beginning of tree to where we currently are) */ index = (GR_A(5,regs) >> 1) & UPT_SHIFT_MASK; /* Exit with cc1 when we've gone as far as we can go */ if ( !index ) { regs->psw.cc = 1; break; } /* Exit with cc3 when we encounter a negative codeword value (i.e. any codeword value with its highest-order bit on) */ if ( GR_A(0,regs) & UPT_HIGH_BIT ) { regs->psw.cc = 3; break; } /* Retrieve this node's values for closer examination... */ nodeaddr = regs->GR(4) + index; #if defined(FEATURE_ESAME) if ( a64 ) { nodecode = ARCH_DEP(vfetch8) ( (nodeaddr+0) & ADDRESS_MAXWRAP(regs), AR4, regs ); nodedata = ARCH_DEP(vfetch8) ( (nodeaddr+8) & ADDRESS_MAXWRAP(regs), AR4, regs ); } else #endif { nodecode = ARCH_DEP(vfetch4) ( (nodeaddr+0) & ADDRESS_MAXWRAP(regs), AR4, regs ); nodedata = ARCH_DEP(vfetch4) ( (nodeaddr+4) & ADDRESS_MAXWRAP(regs), AR4, regs ); } /* GR5 must remain UNCHANGED if the execution of a unit of operation is nullified or suppressed! Thus it must ONLY be updated/committed AFTER we've successfully retrieved the node data (since the storage access could cause a program-check thereby nullifying/suppressing the instruction's "current unit of operation") */ SET_GR_A(5,regs,index); // (do AFTER node data is accessed!) /* Exit with cc0 whenever we reach a node whose codeword is equal to our current "highest encountered" codeword value (i.e. any node whose codeword matches our current "highest" (GR0) value) */ if ( nodecode == GR_A(0,regs) ) { /* Load GR2 and GR3 with the equal codeword node's values */ SET_GR_A(2,regs,nodecode); SET_GR_A(3,regs,nodedata); regs->psw.cc = 0; return; } /* Keep resequencing the tree's nodes, moving successively higher nodes to the front (beginning of tree)... */ if ( nodecode < GR_A(0,regs) ) continue; /* This node has a codeword value higher than our currently saved highest encountered codeword value (GR0). Swap our GR0/1 values with this node's values, such that GR0/1 always hold the values from the node with the highest encountered codeword value... */ /* Store obsolete GR0 and GR1 values into this node's entry */ #if defined(FEATURE_ESAME) if ( a64 ) { ARCH_DEP(vstore8) ( GR_A(0,regs), (nodeaddr+0) & ADDRESS_MAXWRAP(regs), AR4, regs ); ARCH_DEP(vstore8) ( GR_A(1,regs), (nodeaddr+8) & ADDRESS_MAXWRAP(regs), AR4, regs ); } else #endif { ARCH_DEP(vstore4) ( GR_A(0,regs), (nodeaddr+0) & ADDRESS_MAXWRAP(regs), AR4, regs ); ARCH_DEP(vstore4) ( GR_A(1,regs), (nodeaddr+4) & ADDRESS_MAXWRAP(regs), AR4, regs ); } /* Update GR0 and GR1 with the new "highest encountered" values */ SET_GR_A(0,regs,nodecode); SET_GR_A(1,regs,nodedata); } /* Commit GR5 with the actual index value we stopped on */ SET_GR_A(5,regs,index); } #if defined(FEATURE_EXTENDED_TRANSLATION_FACILITY_3) /*-------------------------------------------------------------------*/ /* B9B0 CU14 - Convert UTF-8 to UTF-32 [RRF] */ /*-------------------------------------------------------------------*/ DEF_INST(convert_utf8_to_utf32) { VADR dest; /* Destination address */ GREG destlen; /* Destination length */ int r1; int r2; int read; /* Bytes read */ VADR srce; /* Source address */ GREG srcelen; /* Source length */ BYTE utf32[4]; /* utf32 character(s) */ BYTE utf8[4]; /* utf8 character(s) */ #if defined(FEATURE_ETF3_ENHANCEMENT) int wfc; /* Well-Formedness-Checking (W) */ #endif /*defined(FEATURE_ETF3_ENHANCEMENT)*/ int xlated; /* characters translated */ // NOTE: it's faster to decode with RRE format // and then to handle the 'wfc' flag separately... //RRF_M(inst, regs, r1, r2, wfc); RRE(inst, regs, r1, r2); ODD2_CHECK(r1, r2, regs); /* Get paramaters */ dest = regs->GR(r1) & ADDRESS_MAXWRAP(regs); destlen = GR_A(r1 + 1, regs); srce = regs->GR(r2) & ADDRESS_MAXWRAP(regs); srcelen = GR_A(r2 + 1, regs); #if defined(FEATURE_ETF3_ENHANCEMENT) if(inst[2] & 0x10) wfc = 1; else wfc = 0; #endif /*defined(FEATURE_ETF3_ENHANCEMENT)*/ /* Every valid utf-32 starts with 0x00 */ utf32[0] = 0x00; /* Initialize number of translated charachters */ xlated = 0; while(xlated < 4096) { /* Check end of source or destination */ if(srcelen < 1) { regs->psw.cc = 0; return; } if(destlen < 4) { regs->psw.cc = 1; return; } /* Fetch a byte */ utf8[0] = ARCH_DEP(vfetchb)(srce, r2, regs); if(utf8[0] < 0x80) { /* xlate range 00-7f */ /* 0jklmnop -> 00000000 00000000 00000000 0jklmnop */ utf32[1] = 0x00; utf32[2] = 0x00; utf32[3] = utf8[0]; read = 1; } else if(utf8[0] >= 0xc0 && utf8[0] <= 0xdf) { #if defined(FEATURE_ETF3_ENHANCEMENT) /* WellFormednessChecking */ if(wfc) { if(utf8[0] <= 0xc1) { regs->psw.cc = 2; return; } } #endif /*defined(FEATURE_ETF3_ENHANCEMENT)*/ /* Check end of source */ if(srcelen < 2) { regs->psw.cc = 0; /* Strange but stated in POP */ return; } /* Get the next byte */ utf8[1] = ARCH_DEP(vfetchb)(srce + 1, r2, regs); #if defined(FEATURE_ETF3_ENHANCEMENT) /* WellFormednessChecking */ if(wfc) { if(utf8[1] < 0x80 || utf8[1] > 0xbf) { regs->psw.cc = 2; return; } } #endif /*defined(FEATURE_ETF3_ENHANCEMENT)*/ /* xlate range c000-dfff */ /* 110fghij 10klmnop -> 00000000 00000000 00000fgh ijklmnop */ utf32[1] = 0x00; utf32[2] = (utf8[0] & 0x1c) >> 2; utf32[3] = (utf8[0] << 6) | (utf8[1] & 0x3f); read = 2; } else if(utf8[0] >= 0xe0 && utf8[0] <= 0xef) { /* Check end of source */ if(srcelen < 3) { regs->psw.cc = 0; /* Strange but stated in POP */ return; } /* Get the next 2 bytes */ ARCH_DEP(vfetchc)(&utf8[1], 1, srce + 1, r2, regs); #if defined(FEATURE_ETF3_ENHANCEMENT) /* WellformednessChecking */ if(wfc) { if(utf8[0] == 0xe0) { if(utf8[1] < 0xa0 || utf8[1] > 0xbf || utf8[2] < 0x80 || utf8[2] > 0xbf) { regs->psw.cc = 2; return; } } if((utf8[0] >= 0xe1 && utf8[0] <= 0xec) || (utf8[0] >= 0xee && utf8[0] <= 0xef)) { if(utf8[1] < 0x80 || utf8[1] > 0xbf || utf8[2] < 0x80 || utf8[2] > 0xbf) { regs->psw.cc = 2; return; } } if(utf8[0] == 0xed) { if(utf8[1] < 0x80 || utf8[1] > 0x9f || utf8[2] < 0x80 || utf8[2] > 0xbf) { regs->psw.cc = 2; return; } } } #endif /*defined(FEATURE_ETF3_ENHANCEMENT)*/ /* xlate range e00000-efffff */ /* 1110abcd 10efghij 10klmnop -> 00000000 00000000 abcdefgh ijklmnop */ utf32[1] = 0x00; utf32[2] = (utf8[0] << 4) | ((utf8[1] & 0x3c) >> 2); utf32[3] = (utf8[1] << 6) | (utf8[2] & 0x3f); read = 3; } else if(utf8[0] >= 0xf0 && utf8[0] <= 0xf7) { #if defined(FEATURE_ETF3_ENHANCEMENT) /* WellFormednessChecking */ if(wfc) { if(utf8[0] > 0xf4) { regs->psw.cc = 2; return; } } #endif /*defined(FEATURE_ETF3_ENHANCEMENT)*/ /* Check end of source */ if(srcelen < 4) { regs->psw.cc = 0; /* Strange but stated in POP */ return; } /* Get the next 3 bytes */ ARCH_DEP(vfetchc)(&utf8[1], 2, srce + 1, r2, regs); #if defined(FEATURE_ETF3_ENHANCEMENT) /* WellFormdnessChecking */ if(wfc) { if(utf8[0] == 0xf0) { if(utf8[1] < 0x90 || utf8[1] > 0xbf || utf8[2] < 0x80 || utf8[2] > 0xbf || utf8[3] < 0x80 || utf8[3] > 0xbf) { regs->psw.cc = 2; return; } } if(utf8[0] >= 0xf1 && utf8[0] <= 0xf3) { if(utf8[1] < 0x80 || utf8[1] > 0xbf || utf8[2] < 0x80 || utf8[2] > 0xbf || utf8[3] < 0x80 || utf8[3] > 0xbf) { regs->psw.cc = 2; return; } } if(utf8[0] == 0xf4) { if(utf8[1] < 0x80 || utf8[1] > 0x8f || utf8[2] < 0x80 || utf8[2] > 0xbf || utf8[3] < 0x80 || utf8[3] > 0xbf) { regs->psw.cc = 2; return; } } } #endif /*defined(FEATURE_ETF3_ENHANCEMENT)*/ /* xlate range f0000000-f7000000 */ /* 1110uvw 10xyefgh 10ijklmn 10opqrst -> 00000000 000uvwxy efghijkl mnopqrst */ utf32[1] = ((utf8[0] & 0x07) << 2) | ((utf8[1] & 0x30) >> 4); utf32[2] = (utf8[1] << 4) | ((utf8[2] & 0x3c) >> 2); utf32[3] = (utf8[2] << 6) | (utf8[3] & 0x3f); read = 4; } else { regs->psw.cc = 2; return; } /* Write and commit registers */ ARCH_DEP(vstorec)(utf32, 3, dest, r1, regs); SET_GR_A(r1, regs, (dest + 4) & ADDRESS_MAXWRAP(regs)); SET_GR_A(r1 + 1, regs, destlen - 4); SET_GR_A(r2, regs, (srce + read) & ADDRESS_MAXWRAP(regs)); SET_GR_A(r2 + 1, regs, srcelen - read); xlated += read; } /* CPU determined number of characters reached */ regs->psw.cc = 3; } /*-------------------------------------------------------------------*/ /* B9B1 CU24 - Convert UTF-16 to UTF-32 [RRF] */ /*-------------------------------------------------------------------*/ DEF_INST(convert_utf16_to_utf32) { VADR dest; /* Destination address */ GREG destlen; /* Destination length */ int r1; int r2; int read; /* Bytes read */ VADR srce; /* Source address */ GREG srcelen; /* Source length */ BYTE utf16[4]; /* utf16 character(s) */ BYTE utf32[4]; /* utf328 character(s) */ BYTE uvwxy; /* Work value */ #if defined(FEATURE_ETF3_ENHANCEMENT) int wfc; /* Well-Formedness-Checking (W) */ #endif /*defined(FEATURE_ETF3_ENHANCEMENT)*/ int xlated; /* characters translated */ // NOTE: it's faster to decode with RRE format // and then to handle the 'wfc' flag separately... //RRF_M(inst, regs, r1, r2, wfc); RRE(inst, regs, r1, r2); ODD2_CHECK(r1, r2, regs); /* Get paramaters */ dest = regs->GR(r1) & ADDRESS_MAXWRAP(regs); destlen = GR_A(r1 + 1, regs); srce = regs->GR(r2) & ADDRESS_MAXWRAP(regs); srcelen = GR_A(r2 + 1, regs); #if defined(FEATURE_ETF3_ENHANCEMENT) if(inst[2] & 0x10) wfc = 1; else wfc = 0; #endif /*defined(FEATURE_ETF3_ENHANCEMENT)*/ /* Every valid utf-32 starts with 0x00 */ utf32[0] = 0x00; /* Initialize number of translated charachters */ xlated = 0; while(xlated < 4096) { /* Check end of source or destination */ if(srcelen < 2) { regs->psw.cc = 0; return; } if(destlen < 4) { regs->psw.cc = 1; return; } /* Fetch 2 bytes */ ARCH_DEP(vfetchc)(utf16, 1, srce, r2, regs); if(utf16[0] <= 0xd7 || utf16[0] >= 0xdc) { /* xlate range 0000-d7fff and dc00-ffff */ /* abcdefgh ijklmnop -> 00000000 00000000 abcdefgh ijklmnop */ utf32[1] = 0x00; utf32[2] = utf16[0]; utf32[3] = utf16[1]; read = 2; } else { /* Check end of source */ if(srcelen < 4) { regs->psw.cc = 0; /* Strange but stated in POP */ return; } /* Fetch another 2 bytes */ ARCH_DEP(vfetchc)(&utf16[2], 1, srce, r2, regs); #if defined(FEATURE_ETF3_ENHANCEMENT) /* WellFormednessChecking */ if(wfc) { if(utf16[2] < 0xdc && utf16[2] > 0xdf) { regs->psw.cc = 2; return; } } #endif /*defined(FEATURE_ETF3_ENHANCEMENT)*/ /* xlate range d800-dbff */ /* 110110ab cdefghij 110111kl mnopqrst -> 00000000 000uvwxy efghijkl mnopqrst */ /* 000uvwxy = 0000abcde + 1 */ uvwxy = (((utf16[0] & 0x03) << 2) | (utf16[1] >> 6)) + 1; utf32[1] = uvwxy; utf32[2] = (utf16[1] << 2) | (utf16[2] & 0x03); utf32[3] = utf16[3]; read = 4; } /* Write and commit registers */ ARCH_DEP(vstorec)(utf32, 3, dest, r1, regs); SET_GR_A(r1, regs, (dest + 4) & ADDRESS_MAXWRAP(regs)); SET_GR_A(r1 + 1, regs, destlen - 4); SET_GR_A(r2, regs, (srce + read) & ADDRESS_MAXWRAP(regs)); SET_GR_A(r2 + 1, regs, srcelen - read); xlated += read; } /* CPU determined number of characters reached */ regs->psw.cc = 3; } /*-------------------------------------------------------------------*/ /* B9B2 CU41 - Convert UTF-32 to UTF-8 [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(convert_utf32_to_utf8) { VADR dest; /* Destination address */ GREG destlen; /* Destination length */ int r1; int r2; VADR srce; /* Source address */ GREG srcelen; /* Source length */ BYTE utf32[4]; /* utf32 character(s) */ BYTE utf8[4]; /* utf8 character(s) */ int write; /* Bytes written */ int xlated; /* characters translated */ RRE(inst, regs, r1, r2); ODD2_CHECK(r1, r2, regs); /* Get paramaters */ dest = regs->GR(r1) & ADDRESS_MAXWRAP(regs); destlen = GR_A(r1 + 1, regs); srce = regs->GR(r2) & ADDRESS_MAXWRAP(regs); srcelen = GR_A(r2 + 1, regs); /* Initialize number of translated charachters */ xlated = 0; write = 0; while(xlated < 4096) { /* Check end of source or destination */ if(srcelen < 4) { regs->psw.cc = 0; return; } if(destlen < 1) { regs->psw.cc = 1; return; } /* Get 4 bytes */ ARCH_DEP(vfetchc)(utf32, 3, srce, r2, regs); if(utf32[0] != 0x00) { regs->psw.cc = 2; return; } else if(utf32[1] == 0x00) { if(utf32[2] == 0x00) { if(utf32[3] <= 0x7f) { /* xlate range 00000000-0000007f */ /* 00000000 00000000 00000000 0jklmnop -> 0jklmnop */ utf8[0] = utf32[3]; write = 1; } } else if(utf32[2] <= 0x07) { /* Check destination length */ if(destlen < 2) { regs->psw.cc = 1; return; } /* xlate range 00000080-000007ff */ /* 00000000 00000000 00000fgh ijklmnop -> 110fghij 10klmnop */ utf8[0] = 0xc0 | (utf32[2] << 2) | (utf32[2] >> 6); utf8[1] = 0x80 | (utf32[2] & 0x3f); write = 2; } else if(utf32[2] <= 0xd7 || utf32[2] > 0xdc) { /* Check destination length */ if(destlen < 3) { regs->psw.cc = 1; return; } /* xlate range 00000800-0000d7ff and 0000dc00-0000ffff */ /* 00000000 00000000 abcdefgh ijklnmop -> 1110abcd 10efghij 10klmnop */ utf8[0] = 0xe0 | (utf32[2] >> 4); utf8[1] = 0x80 | ((utf32[2] & 0x0f) << 2) | (utf32[3] >> 6); utf8[2] = 0x80 | (utf32[3] & 0x3f); write = 3; } else { regs->psw.cc = 2; return; } } else if(utf32[1] >= 0x01 && utf32[1] <= 0x10) { /* Check destination length */ if(destlen < 4) { regs->psw.cc = 1; return; } /* xlate range 00010000-0010ffff */ /* 00000000 000uvwxy efghijkl mnopqrst -> 11110uvw 10xyefgh 10ijklmn 10opqrst */ utf8[0] = 0xf0 | (utf32[1] >> 2); utf8[1] = 0x80 | ((utf32[1] & 0x03) << 4) | (utf32[2] >> 4); utf8[2] = 0x80 | ((utf32[2] & 0x0f) << 2) | (utf32[3] >> 6); utf8[3] = 0x80 | (utf32[3] & 0x3f); write = 4; } else { regs->psw.cc = 2; return; } /* Write and commit registers */ ARCH_DEP(vstorec)(utf8, write - 1, dest, r1, regs); SET_GR_A(r1, regs, (dest + write) & ADDRESS_MAXWRAP(regs)); SET_GR_A(r1 + 1, regs, destlen - write); SET_GR_A(r2, regs, (srce + 4) & ADDRESS_MAXWRAP(regs)); SET_GR_A(r2 + 1, regs, srcelen - 4); xlated += 4; } /* CPU determined number of characters reached */ regs->psw.cc = 3; } /*-------------------------------------------------------------------*/ /* B9B3 CU42 - Convert UTF-32 to UTF-16 [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(convert_utf32_to_utf16) { VADR dest; /* Destination address */ GREG destlen; /* Destination length */ int r1; int r2; VADR srce; /* Source address */ GREG srcelen; /* Source length */ BYTE utf16[4]; /* utf16 character(s) */ BYTE utf32[4]; /* utf32 character(s) */ int write; /* Bytes written */ int xlated; /* characters translated */ BYTE zabcd; /* Work value */ RRE(inst, regs, r1, r2); ODD2_CHECK(r1, r2, regs); /* Get paramaters */ dest = regs->GR(r1) & ADDRESS_MAXWRAP(regs); destlen = GR_A(r1 + 1, regs); srce = regs->GR(r2) & ADDRESS_MAXWRAP(regs); srcelen = GR_A(r2 + 1, regs); /* Initialize number of translated charachters */ xlated = 0; while(xlated < 4096) { /* Check end of source or destination */ if(srcelen < 4) { regs->psw.cc = 0; return; } if(destlen < 2) { regs->psw.cc = 1; return; } /* Get 4 bytes */ ARCH_DEP(vfetchc)(utf32, 3, srce, r2, regs); if(utf32[0] != 0x00) { regs->psw.cc = 2; return; } else if(utf32[1] == 0x00 && (utf32[2] <= 0xd7 || utf32[2] >= 0xdc)) { /* xlate range 00000000-0000d7ff and 0000dc00-0000ffff */ /* 00000000 00000000 abcdefgh ijklmnop -> abcdefgh ijklmnop */ utf16[0] = utf32[2]; utf16[1] = utf32[3]; write = 2; } else if(utf32[1] >= 0x01 && utf32[1] <= 0x10) { /* Check end of destination */ if(destlen < 4) { regs->psw.cc = 1; return; } /* xlate range 00010000-0010ffff */ /* 00000000 000uvwxy efghijkl mnopqrst -> 110110ab cdefghij 110111kl mnopqrst */ /* 000zabcd = 000uvwxy - 1 */ zabcd = (utf32[1] - 1) & 0x0f; utf16[0] = 0xd8 | (zabcd >> 2); utf16[1] = (zabcd << 6) | (utf32[2] >> 2); utf16[2] = 0xdc | (utf32[2] & 0x03); utf16[3] = utf32[3]; write = 4; } else { regs->psw.cc = 2; return; } /* Write and commit registers */ ARCH_DEP(vstorec)(utf16, write - 1, dest, r1, regs); SET_GR_A(r1, regs, (dest + write) & ADDRESS_MAXWRAP(regs)); SET_GR_A(r1 + 1, regs, destlen - write); SET_GR_A(r2, regs, (srce + 4) & ADDRESS_MAXWRAP(regs)); SET_GR_A(r2 + 1, regs, srcelen - 4); xlated += 4; } /* CPU determined number of characters reached */ regs->psw.cc = 3; } /*-------------------------------------------------------------------*/ /* B9BE SRSTU - Search String Unicode [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(search_string_unicode) { VADR addr1, addr2; /* End/start addresses */ int i; /* Loop counter */ int r1, r2; /* Values of R fields */ U16 sbyte; /* String character */ U16 termchar; /* Terminating character */ RRE(inst, regs, r1, r2); /* Program check if bits 0-15 of register 0 not zero */ if(regs->GR_L(0) & 0xFFFF0000) regs->program_interrupt (regs, PGM_SPECIFICATION_EXCEPTION); /* Load string terminating character from register 0 bits 16-31 */ termchar = (U16) regs->GR(0); /* Determine the operand end and start addresses */ addr1 = regs->GR(r1) & ADDRESS_MAXWRAP(regs); addr2 = regs->GR(r2) & ADDRESS_MAXWRAP(regs); /* Search up to 256 bytes or until end of operand */ for(i = 0; i < 0x100; i++) { /* If operand end address has been reached, return condition code 2 and leave the R1 and R2 registers unchanged */ if(addr2 == addr1) { regs->psw.cc = 2; return; } /* Fetch 2 bytes from the operand */ sbyte = ARCH_DEP(vfetch2)(addr2, r2, regs ); /* If the terminating character was found, return condition code 1 and load the address of the character into R1 */ if(sbyte == termchar) { SET_GR_A(r1, regs, addr2); regs->psw.cc = 1; return; } /* Increment operand address */ addr2 += 2; addr2 &= ADDRESS_MAXWRAP(regs); } /* end for(i) */ /* Set R2 to point to next character of operand */ SET_GR_A(r2, regs, addr2); /* Return condition code 3 */ regs->psw.cc = 3; } /*-------------------------------------------------------------------*/ /* D0 TRTR - Translate and Test Reverse [SS] */ /*-------------------------------------------------------------------*/ DEF_INST(translate_and_test_reverse) { int b1, b2; /* Values of base field */ int cc = 0; /* Condition code */ BYTE dbyte; /* Byte work areas */ VADR effective_addr1; VADR effective_addr2; /* Effective addresses */ int i; /* Integer work areas */ int l; /* Lenght byte */ BYTE sbyte; /* Byte work areas */ SS_L(inst, regs, l, b1, effective_addr1, b2, effective_addr2); /* Process first operand from right to left*/ for(i = 0; i <= l; i++) { /* Fetch argument byte from first operand */ dbyte = ARCH_DEP(vfetchb)(effective_addr1, b1, regs); /* Fetch function byte from second operand */ sbyte = ARCH_DEP(vfetchb)((effective_addr2 + dbyte) & ADDRESS_MAXWRAP(regs), b2, regs); /* Test for non-zero function byte */ if(sbyte != 0) { /* Store address of argument byte in register 1 */ #if defined(FEATURE_ESAME) if(regs->psw.amode64) regs->GR_G(1) = effective_addr1; else #endif if(regs->psw.amode) { /* Note: TRTR differs from TRT in 31 bit mode. TRTR leaves bit 32 unchanged, TRT clears bit 32 */ regs->GR_L(1) &= 0x80000000; regs->GR_L(1) |= effective_addr1; } else regs->GR_LA24(1) = effective_addr1; /* Store function byte in low-order byte of reg.2 */ regs->GR_LHLCL(2) = sbyte; /* Set condition code 2 if argument byte was last byte of first operand, otherwise set condition code 1 */ cc = (i == l) ? 2 : 1; /* Terminate the operation at this point */ break; } /* end if(sbyte) */ /* Decrement first operand address */ effective_addr1--; /* Another difference with TRT */ effective_addr1 &= ADDRESS_MAXWRAP(regs); } /* end for(i) */ /* Update the condition code */ regs->psw.cc = cc; } #endif /*defined(FEATURE_EXTENDED_TRANSLATION_FACILITY_3)*/ #ifdef FEATURE_PARSING_ENHANCEMENT_FACILITY /*-------------------------------------------------------------------*/ /* B9BF TRTE - Translate and Test Extended [RRF] */ /*-------------------------------------------------------------------*/ DEF_INST(translate_and_test_extended) { int a_bit; /* Argument-Character Control (A) */ U32 arg_ch; /* Argument character */ VADR buf_addr; /* first argument address */ GREG buf_len; /* First argument length */ int f_bit; /* Function-Code Control (F) */ U32 fc; /* Function-Code */ VADR fct_addr; /* Function-code table address */ int l_bit; /* Argument-Character Limit (L) */ int m3; int processed; /* # bytes processed */ int r1; int r2; RRF_M(inst, regs, r1, r2, m3); a_bit = ((m3 & 0x08) ? 1 : 0); f_bit = ((m3 & 0x04) ? 1 : 0); l_bit = ((m3 & 0x02) ? 1 : 0); buf_addr = regs->GR(r1) & ADDRESS_MAXWRAP(regs); buf_len = GR_A(r1 + 1, regs); fct_addr = regs->GR(1) & ADDRESS_MAXWRAP(regs); if(unlikely((a_bit && (buf_len % 1)) || r1 & 0x01)) regs->program_interrupt(regs, PGM_SPECIFICATION_EXCEPTION); fc = 0; processed = 0; while(buf_len && !fc && processed < 16384) { if(a_bit) { arg_ch = ARCH_DEP(vfetch2)(buf_addr, r1, regs); } else { arg_ch = ARCH_DEP(vfetchb)(buf_addr, r1, regs); } if(l_bit && arg_ch > 255) fc = 0; else { if(f_bit) fc = ARCH_DEP(vfetch2)((fct_addr + (arg_ch * 2)) & ADDRESS_MAXWRAP(regs), 1, regs); else fc = ARCH_DEP(vfetchb)((fct_addr + arg_ch) & ADDRESS_MAXWRAP(regs), 1, regs); } if(!fc) { if(a_bit) { buf_len -= 2; processed += 2; buf_addr = (buf_addr + 2) & ADDRESS_MAXWRAP(regs); } else { buf_len--; processed++; buf_addr = (buf_addr + 1) & ADDRESS_MAXWRAP(regs); } } } /* Commit registers */ SET_GR_A(r1, regs, buf_addr); SET_GR_A(r1 + 1, regs, buf_len); /* Check if CPU determined number of bytes have been processed */ if(buf_len && !fc) { regs->psw.cc = 3; return; } /* Set function code */ if(likely(r2 != r1 && r2 != r1 + 1)) SET_GR_A(r2, regs, fc); /* Set condition code */ if(fc) regs->psw.cc = 1; else regs->psw.cc = 0; } /*-------------------------------------------------------------------*/ /* B9BD TRTRE - Translate and Test Reverse Extended [RRF] */ /*-------------------------------------------------------------------*/ DEF_INST(translate_and_test_reverse_extended) { int a_bit; /* Argument-Character Control (A) */ U32 arg_ch; /* Argument character */ VADR buf_addr; /* first argument address */ GREG buf_len; /* First argument length */ int f_bit; /* Function-Code Control (F) */ U32 fc; /* Function-Code */ VADR fct_addr; /* Function-code table address */ int l_bit; /* Argument-Character Limit (L) */ int m3; int processed; /* # bytes processed */ int r1; int r2; RRF_M(inst, regs, r1, r2, m3); a_bit = ((m3 & 0x08) ? 1 : 0); f_bit = ((m3 & 0x04) ? 1 : 0); l_bit = ((m3 & 0x02) ? 1 : 0); buf_addr = regs->GR(r1) & ADDRESS_MAXWRAP(regs); buf_len = GR_A(r1 + 1, regs); fct_addr = regs->GR(1) & ADDRESS_MAXWRAP(regs); if(unlikely((a_bit && (buf_len % 1)) || r1 & 0x01)) regs->program_interrupt(regs, PGM_SPECIFICATION_EXCEPTION); fc = 0; processed = 0; while(buf_len && !fc && processed < 16384) { if(a_bit) { arg_ch = ARCH_DEP(vfetch2)(buf_addr, r1, regs); } else { arg_ch = ARCH_DEP(vfetchb)(buf_addr, r1, regs); } if(l_bit && arg_ch > 255) fc = 0; else { if(f_bit) fc = ARCH_DEP(vfetch2)((fct_addr + (arg_ch * 2)) & ADDRESS_MAXWRAP(regs), 1, regs); else fc = ARCH_DEP(vfetchb)((fct_addr + arg_ch) & ADDRESS_MAXWRAP(regs), 1, regs); } if(!fc) { if(a_bit) { buf_len -= 2; processed += 2; buf_addr = (buf_addr - 2) & ADDRESS_MAXWRAP(regs); } else { buf_len--; processed++; buf_addr = (buf_addr - 1) & ADDRESS_MAXWRAP(regs); } } } /* Commit registers */ SET_GR_A(r1, regs, buf_addr); SET_GR_A(r1 + 1, regs, buf_len); /* Check if CPU determined number of bytes have been processed */ if(buf_len && !fc) { regs->psw.cc = 3; return; } /* Set function code */ if(likely(r2 != r1 && r2 != r1 + 1)) SET_GR_A(r2, regs, fc); /* Set condition code */ if(fc) regs->psw.cc = 1; else regs->psw.cc = 0; } #endif /* FEATURE_PARSING_ENHANCEMENT_FACILITY */ #if !defined(_GEN_ARCH) #if defined(_ARCHMODE2) #define _GEN_ARCH _ARCHMODE2 #include "general2.c" #endif #if defined(_ARCHMODE3) #undef _GEN_ARCH #define _GEN_ARCH _ARCHMODE3 #include "general2.c" #endif #endif /*!defined(_GEN_ARCH)*/ hercules-3.07/general3.c000644 000765 000765 00000221704 11143760543 016621 0ustar00jmaynardjmaynard000000 000000 /* GENERAL3.C (c) Copyright Roger Bowler, 2009 */ /* Additional General Instructions */ // $Id: general3.c 5125 2009-01-23 12:01:44Z bernard $ /*-------------------------------------------------------------------*/ /* This module implements additional general instructions introduced */ /* as later extensions to z/Architecture and described in the manual */ /* SA22-7832-06 z/Architecture Principles of Operation */ /*-------------------------------------------------------------------*/ // $Log$ // Revision 1.22 2008/05/12 16:08:29 rbowler // ECAG correction // // Revision 1.21 2008/03/30 00:07:58 rbowler // Incorrect bit selection again for RNSBG,RISBG,ROSBG,RXSBG // // Revision 1.20 2008/03/28 23:03:54 rbowler // Correct relative address calculation for RIL-format instructions // // Revision 1.19 2008/03/23 08:00:40 rbowler // Fix incorrect bit selection for RNSBG,RISBG,ROSBG,RXSBG // // Revision 1.18 2008/03/12 18:23:55 jj // Fix store operation of ASI, AGSI, ALSI and AGLSI // // Revision 1.17 2008/03/08 23:08:32 rbowler // Add STHRL,STRL,STGRL instructions // // Revision 1.16 2008/03/08 22:54:25 rbowler // Add LHRL,LGHRL,LLHRL,LLGHRL,LLGFRL,LRL,LGRL,LGFRL instructions // // Revision 1.15 2008/03/08 22:28:04 rbowler // Add CHRL,CGHRL,CLRL,CLGRL,CLGFRL,CLHRL,CLGHRL, // CRL,CGRL,CGFRL instructions // // Revision 1.14 2008/03/05 16:36:51 rbowler // Add RNSBG,RISBG,ROSBG,RXSBG instructions // // Revision 1.13 2008/03/05 12:04:23 rbowler // Add CRJ,CGRJ,CIJ,CGIJ,CLRJ,CLGRJ,CLIJ,CLGIJ instructions // // Revision 1.12 2008/03/04 17:09:14 rbowler // Add CRT,CGRT,CIT,CGIT,CLRT,CLGRT,CLFIT,CLGIT instructions // // Revision 1.11 2008/03/04 15:42:50 rbowler // Add CRB,CGRB,CIB,CGIB,CLRB,CLGRB,CLIB,CLGIB instructions // // Revision 1.10 2008/03/04 14:40:28 rbowler // Add CLFHSI,CLHHSI,CLGHSI instructions // // Revision 1.9 2008/03/04 14:23:00 rbowler // Add CHHSI,CGHSI,CHSI,CGH instructions // // Revision 1.8 2008/03/03 23:22:43 rbowler // Add LTGF instruction // // Revision 1.7 2008/03/03 22:43:43 rbowler // Add MVHI,MVHHI,MVGHI instructions // // Revision 1.6 2008/03/03 00:21:45 rbowler // Add ECAG,LAEY,PFD,PFDRL instructions // // Revision 1.5 2008/03/02 23:29:49 rbowler // Add MFY,MHY,MSFI,MSGFI instructions // // Revision 1.4 2008/03/01 23:07:06 rbowler // Add ALSI,ALGSI instructions // // Revision 1.3 2008/03/01 22:49:31 rbowler // ASI,AGSI treat I2 operand as 8-bit signed integer // // Revision 1.2 2008/03/01 22:41:51 rbowler // Add ASI,AGSI instructions // // Revision 1.1 2008/03/01 14:19:29 rbowler // Add new module general3.c for general-instructions-extension facility // #include "hstdinc.h" #if !defined(_HENGINE_DLL_) #define _HENGINE_DLL_ #endif #if !defined(_GENERAL3_C_) #define _GENERAL3_C_ #endif #include "hercules.h" #include "opcode.h" #include "inline.h" #if defined(FEATURE_GENERAL_INSTRUCTIONS_EXTENSION_FACILITY) /*-------------------------------------------------------------------*/ /* EB6A ASI - Add Immediate Storage [SIY] */ /*-------------------------------------------------------------------*/ DEF_INST(add_immediate_storage) { BYTE i2; /* Immediate byte */ int b1; /* Base of effective addr */ VADR effective_addr1; /* Effective address */ U32 n; /* 32-bit operand value */ int cc; /* Condition Code */ SIY(inst, regs, i2, b1, effective_addr1); /* Load 32-bit operand from operand address */ n = ARCH_DEP(vfetch4) ( effective_addr1, b1, regs ); /* Add signed operands and set condition code */ cc = add_signed (&n, n, (S32)(S8)i2); /* Store 32-bit operand at operand address */ ARCH_DEP(vstore4) ( n, effective_addr1, b1, regs ); /* Update Condition Code */ regs->psw.cc = cc; /* Program check if fixed-point overflow */ if ( regs->psw.cc == 3 && FOMASK(®s->psw) ) regs->program_interrupt (regs, PGM_FIXED_POINT_OVERFLOW_EXCEPTION); } /* end DEF_INST(add_immediate_storage) */ /*-------------------------------------------------------------------*/ /* EB7A AGSI - Add Immediate Long Storage [SIY] */ /*-------------------------------------------------------------------*/ DEF_INST(add_immediate_long_storage) { BYTE i2; /* Immediate byte */ int b1; /* Base of effective addr */ VADR effective_addr1; /* Effective address */ U64 n; /* 64-bit operand value */ int cc; /* Condition Code */ SIY(inst, regs, i2, b1, effective_addr1); /* Load 64-bit operand from operand address */ n = ARCH_DEP(vfetch8) ( effective_addr1, b1, regs ); /* Add signed operands and set condition code */ cc = add_signed_long (&n, n, (S64)(S8)i2); /* Store 64-bit value at operand address */ ARCH_DEP(vstore8) ( n, effective_addr1, b1, regs ); /* Update Condition Code */ regs->psw.cc = cc; /* Program check if fixed-point overflow */ if ( regs->psw.cc == 3 && FOMASK(®s->psw) ) regs->program_interrupt (regs, PGM_FIXED_POINT_OVERFLOW_EXCEPTION); } /* end DEF_INST(add_immediate_long_storage) */ /*-------------------------------------------------------------------*/ /* EB6E ALSI - Add Logical with Signed Immediate [SIY] */ /*-------------------------------------------------------------------*/ DEF_INST(add_logical_with_signed_immediate) { BYTE i2; /* Immediate byte */ int b1; /* Base of effective addr */ VADR effective_addr1; /* Effective address */ U32 n; /* 32-bit operand value */ int cc; /* Condition Code */ SIY(inst, regs, i2, b1, effective_addr1); /* Load 32-bit operand from operand address */ n = ARCH_DEP(vfetch4) ( effective_addr1, b1, regs ); /* Add operands and set condition code */ cc = (S8)i2 < 0 ? sub_logical (&n, n, (S32)(-(S8)i2)) : add_logical (&n, n, (S32)(S8)i2); /* Store 32-bit operand at operand address */ ARCH_DEP(vstore4) ( n, effective_addr1, b1, regs ); /* Update Condition Code */ regs->psw.cc = cc; } /* end DEF_INST(add_logical_with_signed_immediate) */ /*-------------------------------------------------------------------*/ /* EB7E ALGSI - Add Logical with Signed Immediate Long [SIY] */ /*-------------------------------------------------------------------*/ DEF_INST(add_logical_with_signed_immediate_long) { BYTE i2; /* Immediate byte */ int b1; /* Base of effective addr */ VADR effective_addr1; /* Effective address */ U64 n; /* 64-bit operand value */ int cc; /* Condition Code */ SIY(inst, regs, i2, b1, effective_addr1); /* Load 64-bit operand from operand address */ n = ARCH_DEP(vfetch8) ( effective_addr1, b1, regs ); /* Add operands and set condition code */ cc = (S8)i2 < 0 ? sub_logical_long (&n, n, (S64)(-(S8)i2)) : add_logical_long (&n, n, (S64)(S8)i2); /* Store 64-bit value at operand address */ ARCH_DEP(vstore8) ( n, effective_addr1, b1, regs ); /* Update Condition Code */ regs->psw.cc = cc; } /* end DEF_INST(add_logical_with_signed_immediate_long) */ /*-------------------------------------------------------------------*/ /* ECF6 CRB - Compare and Branch Register [RRS] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_and_branch_register) { int r1, r2; /* Register numbers */ int m3; /* Mask bits */ int b4; /* Base of effective addr */ VADR effective_addr4; /* Effective address */ int cc; /* Comparison result */ RRS_B(inst, regs, r1, r2, m3, b4, effective_addr4); /* Compare signed operands and set comparison result */ cc = (S32)regs->GR_L(r1) < (S32)regs->GR_L(r2) ? 1 : (S32)regs->GR_L(r1) > (S32)regs->GR_L(r2) ? 2 : 0; /* Branch to operand address if m3 mask bit is set */ if ((0x8 >> cc) & m3) SUCCESSFUL_BRANCH(regs, effective_addr4, 6); else INST_UPDATE_PSW(regs, 6, 0); } /* end DEF_INST(compare_and_branch_register) */ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* ECE4 CGRB - Compare and Branch Long Register [RRS] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_and_branch_long_register) { int r1, r2; /* Register numbers */ int m3; /* Mask bits */ int b4; /* Base of effective addr */ VADR effective_addr4; /* Effective address */ int cc; /* Comparison result */ RRS_B(inst, regs, r1, r2, m3, b4, effective_addr4); /* Compare signed operands and set comparison result */ cc = (S64)regs->GR_G(r1) < (S64)regs->GR_G(r2) ? 1 : (S64)regs->GR_G(r1) > (S64)regs->GR_G(r2) ? 2 : 0; /* Branch to operand address if m3 mask bit is set */ if ((0x8 >> cc) & m3) SUCCESSFUL_BRANCH(regs, effective_addr4, 6); else INST_UPDATE_PSW(regs, 6, 0); } /* end DEF_INST(compare_and_branch_long_register) */ #endif /*defined(FEATURE_ESAME)*/ /*-------------------------------------------------------------------*/ /* EC76 CRJ - Compare and Branch Relative Register [RIE] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_and_branch_relative_register) { int r1, r2; /* Register numbers */ int m3; /* Mask bits */ S16 i4; /* 16-bit immediate offset */ int cc; /* Comparison result */ RIE_RRIM_B(inst, regs, r1, r2, i4, m3); /* Compare signed operands and set comparison result */ cc = (S32)regs->GR_L(r1) < (S32)regs->GR_L(r2) ? 1 : (S32)regs->GR_L(r1) > (S32)regs->GR_L(r2) ? 2 : 0; /* Branch to immediate offset if m3 mask bit is set */ if ((0x8 >> cc) & m3) SUCCESSFUL_RELATIVE_BRANCH(regs, 2*i4, 6); else INST_UPDATE_PSW(regs, 6, 0); } /* end DEF_INST(compare_and_branch_relative_register) */ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* EC64 CGRJ - Compare and Branch Relative Long Register [RIE] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_and_branch_relative_long_register) { int r1, r2; /* Register numbers */ int m3; /* Mask bits */ S16 i4; /* 16-bit immediate offset */ int cc; /* Comparison result */ RIE_RRIM_B(inst, regs, r1, r2, i4, m3); /* Compare signed operands and set comparison result */ cc = (S64)regs->GR_G(r1) < (S64)regs->GR_G(r2) ? 1 : (S64)regs->GR_G(r1) > (S64)regs->GR_G(r2) ? 2 : 0; /* Branch to immediate offset if m3 mask bit is set */ if ((0x8 >> cc) & m3) SUCCESSFUL_RELATIVE_BRANCH(regs, 2*i4, 6); else INST_UPDATE_PSW(regs, 6, 0); } /* end DEF_INST(compare_and_branch_relative_long_register) */ #endif /*defined(FEATURE_ESAME)*/ /*-------------------------------------------------------------------*/ /* B972 CRT - Compare and Trap Register [RRF] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_and_trap_register) { int r1, r2; /* Register numbers */ int m3; /* Mask bits */ int cc; /* Comparison result */ RRF_M(inst, regs, r1, r2, m3); /* Compare signed operands and set comparison result */ cc = (S32)regs->GR_L(r1) < (S32)regs->GR_L(r2) ? 1 : (S32)regs->GR_L(r1) > (S32)regs->GR_L(r2) ? 2 : 0; /* Raise data exception if m3 mask bit is set */ if ((0x8 >> cc) & m3) { regs->dxc = DXC_COMPARE_AND_TRAP; ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION); } } /* end DEF_INST(compare_and_trap_register) */ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* B960 CGRT - Compare and Trap Long Register [RRF] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_and_trap_long_register) { int r1, r2; /* Register numbers */ int m3; /* Mask bits */ int cc; /* Comparison result */ RRF_M(inst, regs, r1, r2, m3); /* Compare signed operands and set comparison result */ cc = (S64)regs->GR_G(r1) < (S64)regs->GR_G(r2) ? 1 : (S64)regs->GR_G(r1) > (S64)regs->GR_G(r2) ? 2 : 0; /* Raise data exception if m3 mask bit is set */ if ((0x8 >> cc) & m3) { regs->dxc = DXC_COMPARE_AND_TRAP; ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION); } } /* end DEF_INST(compare_and_trap_long_register) */ #endif /*defined(FEATURE_ESAME)*/ /*-------------------------------------------------------------------*/ /* E554 CHHSI - Compare Halfword Immediate Halfword Storage [SIL] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_halfword_immediate_halfword_storage) { int b1; /* Base of effective addr */ VADR effective_addr1; /* Effective address */ S16 i2; /* 16-bit immediate value */ S16 n; /* 16-bit storage value */ SIL(inst, regs, i2, b1, effective_addr1); /* Load 16-bit value from first operand address */ n = (S16)ARCH_DEP(vfetch2) ( effective_addr1, b1, regs ); /* Compare signed operands and set condition code */ regs->psw.cc = n < i2 ? 1 : n > i2 ? 2 : 0; } /* end DEF_INST(compare_halfword_immediate_halfword_storage) */ /*-------------------------------------------------------------------*/ /* E558 CGHSI - Compare Halfword Immediate Long Storage [SIL] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_halfword_immediate_long_storage) { int b1; /* Base of effective addr */ VADR effective_addr1; /* Effective address */ S16 i2; /* 16-bit immediate value */ S64 n; /* 64-bit storage value */ SIL(inst, regs, i2, b1, effective_addr1); /* Load 64-bit value from first operand address */ n = (S64)ARCH_DEP(vfetch8) ( effective_addr1, b1, regs ); /* Compare signed operands and set condition code */ regs->psw.cc = n < i2 ? 1 : n > i2 ? 2 : 0; } /* end DEF_INST(compare_halfword_immediate_long_storage) */ /*-------------------------------------------------------------------*/ /* E55C CHSI - Compare Halfword Immediate Storage [SIL] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_halfword_immediate_storage) { int b1; /* Base of effective addr */ VADR effective_addr1; /* Effective address */ S16 i2; /* 16-bit immediate value */ S32 n; /* 32-bit storage value */ SIL(inst, regs, i2, b1, effective_addr1); /* Load 32-bit value from first operand address */ n = (S32)ARCH_DEP(vfetch4) ( effective_addr1, b1, regs ); /* Compare signed operands and set condition code */ regs->psw.cc = n < i2 ? 1 : n > i2 ? 2 : 0; } /* end DEF_INST(compare_halfword_immediate_storage) */ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* E334 CGH - Compare Halfword Long [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_halfword_long) { int r1; /* Values of R fields */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ S64 n; /* 64-bit operand value */ RXY(inst, regs, r1, b2, effective_addr2); /* Load rightmost 2 bytes of comparand from operand address */ n = (S16)ARCH_DEP(vfetch2) ( effective_addr2, b2, regs ); /* Compare signed operands and set condition code */ regs->psw.cc = (S64)regs->GR_G(r1) < n ? 1 : (S64)regs->GR_G(r1) > n ? 2 : 0; } /* end DEF_INST(compare_halfword_long) */ #endif /*defined(FEATURE_ESAME)*/ /*-------------------------------------------------------------------*/ /* C6x5 CHRL - Compare Halfword Relative Long [RIL] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_halfword_relative_long) { int r1; /* Register number */ VADR addr2; /* Relative operand address */ U16 n; /* Relative operand value */ RIL_A(inst, regs, r1, addr2); /* Load relative operand from instruction address space */ n = ARCH_DEP(vfetch2) ( addr2, USE_INST_SPACE, regs ); /* Compare signed operands and set condition code */ regs->psw.cc = (S32)regs->GR_L(r1) < (S16)n ? 1 : (S32)regs->GR_L(r1) > (S16)n ? 2 : 0; } /* end DEF_INST(compare_halfword_relative_long) */ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* C6x4 CGHRL - Compare Halfword Relative Long Long [RIL] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_halfword_relative_long_long) { int r1; /* Register number */ VADR addr2; /* Relative operand address */ U16 n; /* Relative operand value */ RIL_A(inst, regs, r1, addr2); /* Load relative operand from instruction address space */ n = ARCH_DEP(vfetch2) ( addr2, USE_INST_SPACE, regs ); /* Compare signed operands and set condition code */ regs->psw.cc = (S64)regs->GR_G(r1) < (S16)n ? 1 : (S64)regs->GR_G(r1) > (S16)n ? 2 : 0; } /* end DEF_INST(compare_halfword_relative_long_long) */ #endif /*defined(FEATURE_ESAME)*/ /*-------------------------------------------------------------------*/ /* ECFE CIB - Compare Immediate and Branch [RIS] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_immediate_and_branch) { int r1; /* Register number */ int m3; /* Mask bits */ int b4; /* Base of effective addr */ VADR effective_addr4; /* Effective address */ int cc; /* Comparison result */ BYTE i2; /* Immediate value */ RIS_B(inst, regs, r1, i2, m3, b4, effective_addr4); /* Compare signed operands and set comparison result */ cc = (S32)regs->GR_L(r1) < (S32)(S8)i2 ? 1 : (S32)regs->GR_L(r1) > (S32)(S8)i2 ? 2 : 0; /* Branch to operand address if m3 mask bit is set */ if ((0x8 >> cc) & m3) SUCCESSFUL_BRANCH(regs, effective_addr4, 6); else INST_UPDATE_PSW(regs, 6, 0); } /* end DEF_INST(compare_immediate_and_branch) */ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* ECFC CGIB - Compare Immediate and Branch Long [RIS] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_immediate_and_branch_long) { int r1; /* Register number */ int m3; /* Mask bits */ int b4; /* Base of effective addr */ VADR effective_addr4; /* Effective address */ int cc; /* Comparison result */ BYTE i2; /* Immediate value */ RIS_B(inst, regs, r1, i2, m3, b4, effective_addr4); /* Compare signed operands and set comparison result */ cc = (S64)regs->GR_G(r1) < (S64)(S8)i2 ? 1 : (S64)regs->GR_G(r1) > (S64)(S8)i2 ? 2 : 0; /* Branch to operand address if m3 mask bit is set */ if ((0x8 >> cc) & m3) SUCCESSFUL_BRANCH(regs, effective_addr4, 6); else INST_UPDATE_PSW(regs, 6, 0); } /* end DEF_INST(compare_immediate_and_branch_long) */ #endif /*defined(FEATURE_ESAME)*/ /*-------------------------------------------------------------------*/ /* EC7E CIJ - Compare Immediate and Branch Relative [RIE] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_immediate_and_branch_relative) { int r1; /* Register numbers */ int m3; /* Mask bits */ BYTE i2; /* Immediate operand value */ S16 i4; /* 16-bit immediate offset */ int cc; /* Comparison result */ RIE_RMII_B(inst, regs, r1, i2, m3, i4); /* Compare signed operands and set comparison result */ cc = (S32)regs->GR_L(r1) < (S32)(S8)i2 ? 1 : (S32)regs->GR_L(r1) > (S32)(S8)i2 ? 2 : 0; /* Branch to immediate offset if m3 mask bit is set */ if ((0x8 >> cc) & m3) SUCCESSFUL_RELATIVE_BRANCH(regs, 2*i4, 6); else INST_UPDATE_PSW(regs, 6, 0); } /* end DEF_INST(compare_immediate_and_branch_relative) */ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* EC7C CGIJ - Compare Immediate and Branch Relative Long [RIE] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_immediate_and_branch_relative_long) { int r1; /* Register numbers */ int m3; /* Mask bits */ BYTE i2; /* Immediate operand value */ S16 i4; /* 16-bit immediate offset */ int cc; /* Comparison result */ RIE_RMII_B(inst, regs, r1, i2, m3, i4); /* Compare signed operands and set comparison result */ cc = (S64)regs->GR_G(r1) < (S64)(S8)i2 ? 1 : (S64)regs->GR_G(r1) > (S64)(S8)i2 ? 2 : 0; /* Branch to immediate offset if m3 mask bit is set */ if ((0x8 >> cc) & m3) SUCCESSFUL_RELATIVE_BRANCH(regs, 2*i4, 6); else INST_UPDATE_PSW(regs, 6, 0); } /* end DEF_INST(compare_immediate_and_branch_relative_long) */ #endif /*defined(FEATURE_ESAME)*/ /*-------------------------------------------------------------------*/ /* EC72 CIT - Compare Immediate and Trap [RIE] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_immediate_and_trap) { int r1; /* Register number */ int m3; /* Mask bits */ int cc; /* Comparison result */ U16 i2; /* 16-bit immediate value */ RIE_RIM(inst, regs, r1, i2, m3); /* Compare signed operands and set comparison result */ cc = (S32)regs->GR_L(r1) < (S32)(S16)i2 ? 1 : (S32)regs->GR_L(r1) > (S32)(S16)i2 ? 2 : 0; /* Raise data exception if m3 mask bit is set */ if ((0x8 >> cc) & m3) { regs->dxc = DXC_COMPARE_AND_TRAP; ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION); } } /* end DEF_INST(compare_immediate_and_trap) */ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* EC70 CGIT - Compare Immediate and Trap Long [RIE] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_immediate_and_trap_long) { int r1; /* Register number */ int m3; /* Mask bits */ int cc; /* Comparison result */ U16 i2; /* 16-bit immediate value */ RIE_RIM(inst, regs, r1, i2, m3); /* Compare signed operands and set comparison result */ cc = (S64)regs->GR_G(r1) < (S64)(S16)i2 ? 1 : (S64)regs->GR_G(r1) > (S64)(S16)i2 ? 2 : 0; /* Raise data exception if m3 mask bit is set */ if ((0x8 >> cc) & m3) { regs->dxc = DXC_COMPARE_AND_TRAP; ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION); } } /* end DEF_INST(compare_immediate_and_trap_long) */ #endif /*defined(FEATURE_ESAME)*/ /*-------------------------------------------------------------------*/ /* ECF7 CLRB - Compare Logical and Branch Register [RRS] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_logical_and_branch_register) { int r1, r2; /* Register numbers */ int m3; /* Mask bits */ int b4; /* Base of effective addr */ VADR effective_addr4; /* Effective address */ int cc; /* Comparison result */ RRS_B(inst, regs, r1, r2, m3, b4, effective_addr4); /* Compare unsigned operands and set comparison result */ cc = regs->GR_L(r1) < regs->GR_L(r2) ? 1 : regs->GR_L(r1) > regs->GR_L(r2) ? 2 : 0; /* Branch to operand address if m3 mask bit is set */ if ((0x8 >> cc) & m3) SUCCESSFUL_BRANCH(regs, effective_addr4, 6); else INST_UPDATE_PSW(regs, 6, 0); } /* end DEF_INST(compare_logical_and_branch_register) */ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* ECE5 CLGRB - Compare Logical and Branch Long Register [RRS] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_logical_and_branch_long_register) { int r1, r2; /* Register numbers */ int m3; /* Mask bits */ int b4; /* Base of effective addr */ VADR effective_addr4; /* Effective address */ int cc; /* Comparison result */ RRS_B(inst, regs, r1, r2, m3, b4, effective_addr4); /* Compare unsigned operands and set comparison result */ cc = regs->GR_G(r1) < regs->GR_G(r2) ? 1 : regs->GR_G(r1) > regs->GR_G(r2) ? 2 : 0; /* Branch to operand address if m3 mask bit is set */ if ((0x8 >> cc) & m3) SUCCESSFUL_BRANCH(regs, effective_addr4, 6); else INST_UPDATE_PSW(regs, 6, 0); } /* end DEF_INST(compare_logical_and_branch_long_register) */ #endif /*defined(FEATURE_ESAME)*/ /*-------------------------------------------------------------------*/ /* EC77 CLRJ - Compare Logical and Branch Relative Register [RIE] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_logical_and_branch_relative_register) { int r1, r2; /* Register numbers */ int m3; /* Mask bits */ S16 i4; /* 16-bit immediate offset */ int cc; /* Comparison result */ RIE_RRIM_B(inst, regs, r1, r2, i4, m3); /* Compare unsigned operands and set comparison result */ cc = regs->GR_L(r1) < regs->GR_L(r2) ? 1 : regs->GR_L(r1) > regs->GR_L(r2) ? 2 : 0; /* Branch to immediate offset if m3 mask bit is set */ if ((0x8 >> cc) & m3) SUCCESSFUL_RELATIVE_BRANCH(regs, 2*i4, 6); else INST_UPDATE_PSW(regs, 6, 0); } /* end DEF_INST(compare_logical_and_branch_relative_register) */ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* EC65 CLGRJ - Compare Logical and Branch Relative Long Reg [RIE] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_logical_and_branch_relative_long_register) { int r1, r2; /* Register numbers */ int m3; /* Mask bits */ S16 i4; /* 16-bit immediate offset */ int cc; /* Comparison result */ RIE_RRIM_B(inst, regs, r1, r2, i4, m3); /* Compare unsigned operands and set comparison result */ cc = regs->GR_G(r1) < regs->GR_G(r2) ? 1 : regs->GR_G(r1) > regs->GR_G(r2) ? 2 : 0; /* Branch to immediate offset if m3 mask bit is set */ if ((0x8 >> cc) & m3) SUCCESSFUL_RELATIVE_BRANCH(regs, 2*i4, 6); else INST_UPDATE_PSW(regs, 6, 0); } /* end DEF_INST(compare_logical_and_branch_relative_long_register) */ #endif /*defined(FEATURE_ESAME)*/ /*-------------------------------------------------------------------*/ /* B973 CLRT - Compare Logical and Trap Register [RRF] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_logical_and_trap_register) { int r1, r2; /* Register numbers */ int m3; /* Mask bits */ int cc; /* Comparison result */ RRF_M(inst, regs, r1, r2, m3); /* Compare unsigned operands and set comparison result */ cc = regs->GR_L(r1) < regs->GR_L(r2) ? 1 : regs->GR_L(r1) > regs->GR_L(r2) ? 2 : 0; /* Raise data exception if m3 mask bit is set */ if ((0x8 >> cc) & m3) { regs->dxc = DXC_COMPARE_AND_TRAP; ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION); } } /* end DEF_INST(compare_logical_and_trap_register) */ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* B961 CLGRT - Compare Logical and Trap Long Register [RRF] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_logical_and_trap_long_register) { int r1, r2; /* Register numbers */ int m3; /* Mask bits */ int cc; /* Comparison result */ RRF_M(inst, regs, r1, r2, m3); /* Compare unsigned operands and set comparison result */ cc = regs->GR_G(r1) < regs->GR_G(r2) ? 1 : regs->GR_G(r1) > regs->GR_G(r2) ? 2 : 0; /* Raise data exception if m3 mask bit is set */ if ((0x8 >> cc) & m3) { regs->dxc = DXC_COMPARE_AND_TRAP; ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION); } } /* end DEF_INST(compare_logical_and_trap_long_register) */ #endif /*defined(FEATURE_ESAME)*/ /*-------------------------------------------------------------------*/ /* ECFF CLIB - Compare Logical Immediate and Branch [RIS] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_logical_immediate_and_branch) { int r1; /* Register number */ int m3; /* Mask bits */ int b4; /* Base of effective addr */ VADR effective_addr4; /* Effective address */ int cc; /* Comparison result */ BYTE i2; /* Immediate value */ RIS_B(inst, regs, r1, i2, m3, b4, effective_addr4); /* Compare unsigned operands and set comparison result */ cc = regs->GR_L(r1) < i2 ? 1 : regs->GR_L(r1) > i2 ? 2 : 0; /* Branch to operand address if m3 mask bit is set */ if ((0x8 >> cc) & m3) SUCCESSFUL_BRANCH(regs, effective_addr4, 6); else INST_UPDATE_PSW(regs, 6, 0); } /* end DEF_INST(compare_logical_immediate_and_branch) */ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* ECFD CLGIB - Compare Logical Immediate and Branch Long [RIS] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_logical_immediate_and_branch_long) { int r1; /* Register number */ int m3; /* Mask bits */ int b4; /* Base of effective addr */ VADR effective_addr4; /* Effective address */ int cc; /* Comparison result */ BYTE i2; /* Immediate value */ RIS_B(inst, regs, r1, i2, m3, b4, effective_addr4); /* Compare unsigned operands and set comparison result */ cc = regs->GR_G(r1) < i2 ? 1 : regs->GR_G(r1) > i2 ? 2 : 0; /* Branch to operand address if m3 mask bit is set */ if ((0x8 >> cc) & m3) SUCCESSFUL_BRANCH(regs, effective_addr4, 6); else INST_UPDATE_PSW(regs, 6, 0); } /* end DEF_INST(compare_logical_immediate_and_branch_long) */ #endif /*defined(FEATURE_ESAME)*/ /*-------------------------------------------------------------------*/ /* EC7F CLIJ - Compare Logical Immediate and Branch Relative [RIE] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_logical_immediate_and_branch_relative) { int r1; /* Register number */ int m3; /* Mask bits */ BYTE i2; /* Immediate operand value */ S16 i4; /* 16-bit immediate offset */ int cc; /* Comparison result */ RIE_RMII_B(inst, regs, r1, i2, m3, i4); /* Compare unsigned operands and set comparison result */ cc = regs->GR_L(r1) < i2 ? 1 : regs->GR_L(r1) > i2 ? 2 : 0; /* Branch to immediate offset if m3 mask bit is set */ if ((0x8 >> cc) & m3) SUCCESSFUL_RELATIVE_BRANCH(regs, 2*i4, 6); else INST_UPDATE_PSW(regs, 6, 0); } /* end DEF_INST(compare_logical_immediate_and_branch_relative) */ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* EC7D CLGIJ - Compare Logical Immed and Branch Relative Long [RIE] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_logical_immediate_and_branch_relative_long) { int r1; /* Register number */ int m3; /* Mask bits */ BYTE i2; /* Immediate operand value */ S16 i4; /* 16-bit immediate offset */ int cc; /* Comparison result */ RIE_RMII_B(inst, regs, r1, i2, m3, i4); /* Compare unsigned operands and set comparison result */ cc = regs->GR_G(r1) < i2 ? 1 : regs->GR_G(r1) > i2 ? 2 : 0; /* Branch to immediate offset if m3 mask bit is set */ if ((0x8 >> cc) & m3) SUCCESSFUL_RELATIVE_BRANCH(regs, 2*i4, 6); else INST_UPDATE_PSW(regs, 6, 0); } /* end DEF_INST(compare_logical_immediate_and_branch_relative_long) */ #endif /*defined(FEATURE_ESAME)*/ /*-------------------------------------------------------------------*/ /* EC73 CLFIT - Compare Logical Immediate and Trap Fullword [RIE] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_logical_immediate_and_trap_fullword) { int r1; /* Register number */ int m3; /* Mask bits */ int cc; /* Comparison result */ U16 i2; /* 16-bit immediate value */ RIE_RIM(inst, regs, r1, i2, m3); /* Compare unsigned operands and set comparison result */ cc = regs->GR_L(r1) < i2 ? 1 : regs->GR_L(r1) > i2 ? 2 : 0; /* Raise data exception if m3 mask bit is set */ if ((0x8 >> cc) & m3) { regs->dxc = DXC_COMPARE_AND_TRAP; ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION); } } /* end DEF_INST(compare_logical_immediate_and_trap_fullword) */ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* EC71 CLGIT - Compare Logical Immediate and Trap Long [RIE] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_logical_immediate_and_trap_long) { int r1; /* Register number */ int m3; /* Mask bits */ int cc; /* Comparison result */ U16 i2; /* 16-bit immediate value */ RIE_RIM(inst, regs, r1, i2, m3); /* Compare unsigned operands and set comparison result */ cc = regs->GR_G(r1) < i2 ? 1 : regs->GR_G(r1) > i2 ? 2 : 0; /* Raise data exception if m3 mask bit is set */ if ((0x8 >> cc) & m3) { regs->dxc = DXC_COMPARE_AND_TRAP; ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION); } } /* end DEF_INST(compare_logical_immediate_and_trap_long) */ #endif /*defined(FEATURE_ESAME)*/ /*-------------------------------------------------------------------*/ /* E55D CLFHSI - Compare Logical Immediate Fullword Storage [SIL] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_logical_immediate_fullword_storage) { int b1; /* Base of effective addr */ VADR effective_addr1; /* Effective address */ U16 i2; /* 16-bit immediate value */ U32 n; /* 32-bit storage value */ SIL(inst, regs, i2, b1, effective_addr1); /* Load 32-bit value from first operand address */ n = ARCH_DEP(vfetch4) ( effective_addr1, b1, regs ); /* Compare unsigned operands and set condition code */ regs->psw.cc = n < i2 ? 1 : n > i2 ? 2 : 0; } /* end DEF_INST(compare_logical_immediate_fullword_storage) */ /*-------------------------------------------------------------------*/ /* E555 CLHHSI - Compare Logical Immediate Halfword Storage [SIL] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_logical_immediate_halfword_storage) { int b1; /* Base of effective addr */ VADR effective_addr1; /* Effective address */ U16 i2; /* 16-bit immediate value */ U16 n; /* 16-bit storage value */ SIL(inst, regs, i2, b1, effective_addr1); /* Load 16-bit value from first operand address */ n = ARCH_DEP(vfetch2) ( effective_addr1, b1, regs ); /* Compare unsigned operands and set condition code */ regs->psw.cc = n < i2 ? 1 : n > i2 ? 2 : 0; } /* end DEF_INST(compare_logical_immediate_halfword_storage) */ /*-------------------------------------------------------------------*/ /* E559 CLGHSI - Compare Logical Immediate Long Storage [SIL] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_logical_immediate_long_storage) { int b1; /* Base of effective addr */ VADR effective_addr1; /* Effective address */ U16 i2; /* 16-bit immediate value */ U64 n; /* 64-bit storage value */ SIL(inst, regs, i2, b1, effective_addr1); /* Load 64-bit value from first operand address */ n = ARCH_DEP(vfetch8) ( effective_addr1, b1, regs ); /* Compare unsigned operands and set condition code */ regs->psw.cc = n < i2 ? 1 : n > i2 ? 2 : 0; } /* end DEF_INST(compare_logical_immediate_long_storage) */ /*-------------------------------------------------------------------*/ /* C6xF CLRL - Compare Logical Relative Long [RIL] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_logical_relative_long) { int r1; /* Register number */ VADR addr2; /* Relative operand address */ U32 n; /* Relative operand value */ RIL_A(inst, regs, r1, addr2); /* Program check if operand not on fullword boundary */ FW_CHECK(addr2, regs); /* Load relative operand from instruction address space */ n = ARCH_DEP(vfetch4) ( addr2, USE_INST_SPACE, regs ); /* Compare signed operands and set condition code */ regs->psw.cc = regs->GR_L(r1) < n ? 1 : regs->GR_L(r1) > n ? 2 : 0; } /* end DEF_INST(compare_logical_relative_long) */ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* C6xA CLGRL - Compare Logical Relative Long Long [RIL] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_logical_relative_long_long) { int r1; /* Register number */ VADR addr2; /* Relative operand address */ U64 n; /* Relative operand value */ RIL_A(inst, regs, r1, addr2); /* Program check if operand not on doubleword boundary */ DW_CHECK(addr2, regs); /* Load relative operand from instruction address space */ n = ARCH_DEP(vfetch8) ( addr2, USE_INST_SPACE, regs ); /* Compare signed operands and set condition code */ regs->psw.cc = regs->GR_G(r1) < n ? 1 : regs->GR_G(r1) > n ? 2 : 0; } /* end DEF_INST(compare_logical_relative_long_long) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* C6xE CLGFRL - Compare Logical Relative Long Long Fullword [RIL] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_logical_relative_long_long_fullword) { int r1; /* Register number */ VADR addr2; /* Relative operand address */ U32 n; /* Relative operand value */ RIL_A(inst, regs, r1, addr2); /* Program check if operand not on fullword boundary */ FW_CHECK(addr2, regs); /* Load relative operand from instruction address space */ n = ARCH_DEP(vfetch4) ( addr2, USE_INST_SPACE, regs ); /* Compare signed operands and set condition code */ regs->psw.cc = regs->GR_G(r1) < n ? 1 : regs->GR_G(r1) > n ? 2 : 0; } /* end DEF_INST(compare_logical_relative_long_long_fullword) */ #endif /*defined(FEATURE_ESAME)*/ /*-------------------------------------------------------------------*/ /* C6x7 CLHRL - Compare Logical Halfword Relative Long [RIL] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_logical_relative_long_halfword) { int r1; /* Register number */ VADR addr2; /* Relative operand address */ U16 n; /* Relative operand value */ RIL_A(inst, regs, r1, addr2); /* Load relative operand from instruction address space */ n = ARCH_DEP(vfetch2) ( addr2, USE_INST_SPACE, regs ); /* Compare signed operands and set condition code */ regs->psw.cc = regs->GR_L(r1) < n ? 1 : regs->GR_L(r1) > n ? 2 : 0; } /* end DEF_INST(compare_logical_relative_long_halfword) */ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* C6x6 CLGHRL - Compare Logical Halfword Relative Long Long [RIL] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_logical_relative_long_long_halfword) { int r1; /* Register number */ VADR addr2; /* Relative operand address */ U16 n; /* Relative operand value */ RIL_A(inst, regs, r1, addr2); /* Load relative operand from instruction address space */ n = ARCH_DEP(vfetch2) ( addr2, USE_INST_SPACE, regs ); /* Compare signed operands and set condition code */ regs->psw.cc = regs->GR_G(r1) < n ? 1 : regs->GR_G(r1) > n ? 2 : 0; } /* end DEF_INST(compare_logical_relative_long_long_halfword) */ #endif /*defined(FEATURE_ESAME)*/ /*-------------------------------------------------------------------*/ /* C6xD CRL - Compare Relative Long [RIL] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_relative_long) { int r1; /* Register number */ VADR addr2; /* Relative operand address */ U32 n; /* Relative operand value */ RIL_A(inst, regs, r1, addr2); /* Program check if operand not on fullword boundary */ FW_CHECK(addr2, regs); /* Load relative operand from instruction address space */ n = ARCH_DEP(vfetch4) ( addr2, USE_INST_SPACE, regs ); /* Compare signed operands and set condition code */ regs->psw.cc = (S32)regs->GR_L(r1) < (S32)n ? 1 : (S32)regs->GR_L(r1) > (S32)n ? 2 : 0; } /* end DEF_INST(compare_relative_long) */ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* C6x8 CGRL - Compare Relative Long Long [RIL] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_relative_long_long) { int r1; /* Register number */ VADR addr2; /* Relative operand address */ U64 n; /* Relative operand value */ RIL_A(inst, regs, r1, addr2); /* Program check if operand not on doubleword boundary */ DW_CHECK(addr2, regs); /* Load relative operand from instruction address space */ n = ARCH_DEP(vfetch8) ( addr2, USE_INST_SPACE, regs ); /* Compare signed operands and set condition code */ regs->psw.cc = (S64)regs->GR_G(r1) < (S64)n ? 1 : (S64)regs->GR_G(r1) > (S64)n ? 2 : 0; } /* end DEF_INST(compare_relative_long_long) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* C6xC CGFRL - Compare Relative Long Long Fullword [RIL] */ /*-------------------------------------------------------------------*/ DEF_INST(compare_relative_long_long_fullword) { int r1; /* Register number */ VADR addr2; /* Relative operand address */ U32 n; /* Relative operand value */ RIL_A(inst, regs, r1, addr2); /* Program check if operand not on fullword boundary */ FW_CHECK(addr2, regs); /* Load relative operand from instruction address space */ n = ARCH_DEP(vfetch4) ( addr2, USE_INST_SPACE, regs ); /* Compare signed operands and set condition code */ regs->psw.cc = (S64)regs->GR_G(r1) < (S32)n ? 1 : (S64)regs->GR_G(r1) > (S32)n ? 2 : 0; } /* end DEF_INST(compare_relative_long_long_fullword) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* EB4C ECAG - Extract Cache Attribute [RSY] */ /*-------------------------------------------------------------------*/ DEF_INST(extract_cache_attribute) { int r1, r3; /* Register numbers */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ int ai, li, ti; /* Operand address subfields */ RSY(inst, regs, r1, r3, b2, effective_addr2); /* Address bit 63 contains the Type Indication (TI) */ ti = effective_addr2 & 0x1; /* Address bits 60-62 contain the Level Indication (LI) */ li = (effective_addr2 >> 1) & 0x7; /* Address bits 56-59 contain the Attribute Indication (AI) */ ai = (effective_addr2 >> 4) & 0xF; //logmsg ("ECAG ai=%d li=%d ti=%d\n", ai, li, ti); /* If reserved bits 40-55 are not zero then set r1 to all ones */ if ((effective_addr2 & 0xFFFF00) != 0) { regs->GR(r1) = 0xFFFFFFFFFFFFFFFFULL; return; } /* If AI=0 (topology summary) is requested, set register r1 to indicate that cache level 0 is private to this CPU and that cache levels 1-7 are not implemented */ if (ai == 0) { regs->GR_H(r1) = 0x04000000; regs->GR_L(r1) = 0x00000000; return; } /* If cache level is not 0, set register r1 to all ones which indicates that the requested cache level is not implemented */ if (li > 0) { regs->GR(r1) = 0xFFFFFFFFFFFFFFFFULL; return; } /* If AI=1 (cache line size) is requested for cache level 0 set register r1 to indicate a fictitious cache line size */ if (ai == 1 && li == 0) { regs->GR(r1) = 256; return; } /* If AI=2 (total cache size) is requested for cache level 0 set register r1 to indicate a fictitious total cache size */ if (ai == 2 && li == 0) { regs->GR(r1) = 256 * 2048; return; } /* Set register r1 to all ones indicating that the requested attribute indication is reserved */ regs->GR(r1) = 0xFFFFFFFFFFFFFFFFULL; } /* end DEF_INST(extract_cache_attribute) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ACCESS_REGISTERS) /*-------------------------------------------------------------------*/ /* E375 LAEY - Load Address Extended (Long Displacement) [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(load_address_extended_y) { int r1; /* Value of R field */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ RXY0(inst, regs, r1, b2, effective_addr2); /* Load operand address into register */ SET_GR_A(r1, regs,effective_addr2); /* Load corresponding value into access register */ if ( PRIMARY_SPACE_MODE(&(regs->psw)) ) regs->AR(r1) = ALET_PRIMARY; else if ( SECONDARY_SPACE_MODE(&(regs->psw)) ) regs->AR(r1) = ALET_SECONDARY; else if ( HOME_SPACE_MODE(&(regs->psw)) ) regs->AR(r1) = ALET_HOME; else /* ACCESS_REGISTER_MODE(&(regs->psw)) */ regs->AR(r1) = (b2 == 0) ? 0 : regs->AR(b2); SET_AEA_AR(regs, r1); } /* end DEF_INST(load_address_extended_y) */ #endif /*defined(FEATURE_ACCESS_REGISTERS)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* E332 LTGF - Load and Test Long Fullword [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(load_and_test_long_fullword) { int r1; /* Value of R field */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ U32 n; /* Second operand value */ RXY(inst, regs, r1, b2, effective_addr2); /* Load R1 register from sign-extended second operand */ n = ARCH_DEP(vfetch4) ( effective_addr2, b2, regs ); regs->GR_G(r1) = (S64)(S32)n; /* Set condition code according to value loaded */ regs->psw.cc = (S64)regs->GR_G(r1) < 0 ? 1 : (S64)regs->GR_G(r1) > 0 ? 2 : 0; } /* end DEF_INST(load_and_test_long_fullword) */ #endif /*defined(FEATURE_ESAME)*/ /*-------------------------------------------------------------------*/ /* C4x5 LHRL - Load Halfword Relative Long [RIL] */ /*-------------------------------------------------------------------*/ DEF_INST(load_halfword_relative_long) { int r1; /* Register number */ VADR addr2; /* Relative operand address */ U16 n; /* Relative operand value */ RIL_A(inst, regs, r1, addr2); /* Load relative operand from instruction address space */ n = ARCH_DEP(vfetch2) ( addr2, USE_INST_SPACE, regs ); /* Sign-extend operand value and load into R1 register */ regs->GR_L(r1) = (S32)(S16)n; } /* end DEF_INST(load_halfword_relative_long) */ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* C4x4 LGHRL - Load Halfword Relative Long Long [RIL] */ /*-------------------------------------------------------------------*/ DEF_INST(load_halfword_relative_long_long) { int r1; /* Register number */ VADR addr2; /* Relative operand address */ U16 n; /* Relative operand value */ RIL_A(inst, regs, r1, addr2); /* Load relative operand from instruction address space */ n = ARCH_DEP(vfetch2) ( addr2, USE_INST_SPACE, regs ); /* Sign-extend operand value and load into R1 register */ regs->GR_G(r1) = (S64)(S16)n; } /* end DEF_INST(load_halfword_relative_long_long) */ #endif /*defined(FEATURE_ESAME)*/ /*-------------------------------------------------------------------*/ /* C4x2 LLHRL - Load Logical Halfword Relative Long [RIL] */ /*-------------------------------------------------------------------*/ DEF_INST(load_logical_halfword_relative_long) { int r1; /* Register number */ VADR addr2; /* Relative operand address */ U16 n; /* Relative operand value */ RIL_A(inst, regs, r1, addr2); /* Load relative operand from instruction address space */ n = ARCH_DEP(vfetch2) ( addr2, USE_INST_SPACE, regs ); /* Zero-extend operand value and load into R1 register */ regs->GR_L(r1) = n; } /* end DEF_INST(load_logical_halfword_relative_long) */ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* C4x6 LLGHRL - Load Logical Halfword Relative Long Long [RIL] */ /*-------------------------------------------------------------------*/ DEF_INST(load_logical_halfword_relative_long_long) { int r1; /* Register number */ VADR addr2; /* Relative operand address */ U16 n; /* Relative operand value */ RIL_A(inst, regs, r1, addr2); /* Load relative operand from instruction address space */ n = ARCH_DEP(vfetch2) ( addr2, USE_INST_SPACE, regs ); /* Zero-extend operand value and load into R1 register */ regs->GR_G(r1) = n; } /* end DEF_INST(load_logical_halfword_relative_long_long) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* C4xE LLGFRL - Load Logical Relative Long Long Fullword [RIL] */ /*-------------------------------------------------------------------*/ DEF_INST(load_logical_relative_long_long_fullword) { int r1; /* Register number */ VADR addr2; /* Relative operand address */ U32 n; /* Relative operand value */ RIL_A(inst, regs, r1, addr2); /* Program check if operand not on fullword boundary */ FW_CHECK(addr2, regs); /* Load relative operand from instruction address space */ n = ARCH_DEP(vfetch4) ( addr2, USE_INST_SPACE, regs ); /* Zero-extend operand value and load into R1 register */ regs->GR_G(r1) = n; } /* end DEF_INST(load_logical_relative_long_long_fullword) */ #endif /*defined(FEATURE_ESAME)*/ /*-------------------------------------------------------------------*/ /* C4xD LRL - Load Relative Long [RIL] */ /*-------------------------------------------------------------------*/ DEF_INST(load_relative_long) { int r1; /* Register number */ VADR addr2; /* Relative operand address */ U32 n; /* Relative operand value */ RIL_A(inst, regs, r1, addr2); /* Program check if operand not on fullword boundary */ FW_CHECK(addr2, regs); /* Load relative operand from instruction address space */ n = ARCH_DEP(vfetch4) ( addr2, USE_INST_SPACE, regs ); /* Load operand value into R1 register */ regs->GR_L(r1) = n; } /* end DEF_INST(load_relative_long) */ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* C4x8 LGRL - Load Relative Long Long [RIL] */ /*-------------------------------------------------------------------*/ DEF_INST(load_relative_long_long) { int r1; /* Register number */ VADR addr2; /* Relative operand address */ U64 n; /* Relative operand value */ RIL_A(inst, regs, r1, addr2); /* Program check if operand not on doubleword boundary */ DW_CHECK(addr2, regs); /* Load relative operand from instruction address space */ n = ARCH_DEP(vfetch8) ( addr2, USE_INST_SPACE, regs ); /* Load operand value into R1 register */ regs->GR_G(r1) = n; } /* end DEF_INST(load_relative_long_long) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* C4xC LGFRL - Load Relative Long Long Fullword [RIL] */ /*-------------------------------------------------------------------*/ DEF_INST(load_relative_long_long_fullword) { int r1; /* Register number */ VADR addr2; /* Relative operand address */ U32 n; /* Relative operand value */ RIL_A(inst, regs, r1, addr2); /* Program check if operand not on fullword boundary */ FW_CHECK(addr2, regs); /* Load relative operand from instruction address space */ n = ARCH_DEP(vfetch4) ( addr2, USE_INST_SPACE, regs ); /* Sign-extend operand value and load into R1 register */ regs->GR_G(r1) = (S64)(S32)n; } /* end DEF_INST(load_relative_long_long_fullword) */ #endif /*defined(FEATURE_ESAME)*/ /*-------------------------------------------------------------------*/ /* E54C MVHI - Move Fullword from Halfword Immediate [SIL] */ /*-------------------------------------------------------------------*/ DEF_INST(move_fullword_from_halfword_immediate) { int b1; /* Base of effective addr */ VADR effective_addr1; /* Effective address */ S16 i2; /* 16-bit immediate value */ S32 n; /* Sign-extended value of i2 */ SIL(inst, regs, i2, b1, effective_addr1); /* Sign-extend 16-bit immediate value to 32 bits */ n = i2; /* Store 4-byte value at operand address */ ARCH_DEP(vstore4) ( n, effective_addr1, b1, regs ); } /* end DEF_INST(move_fullword_from_halfword_immediate) */ /*-------------------------------------------------------------------*/ /* E544 MVHHI - Move Halfword from Halfword Immediate [SIL] */ /*-------------------------------------------------------------------*/ DEF_INST(move_halfword_from_halfword_immediate) { int b1; /* Base of effective addr */ VADR effective_addr1; /* Effective address */ S16 i2; /* 16-bit immediate value */ SIL(inst, regs, i2, b1, effective_addr1); /* Store 16-bit immediate value at operand address */ ARCH_DEP(vstore2) ( i2, effective_addr1, b1, regs ); } /* end DEF_INST(move_halfword_from_halfword_immediate) */ /*-------------------------------------------------------------------*/ /* E548 MVGHI - Move Long from Halfword Immediate [SIL] */ /*-------------------------------------------------------------------*/ DEF_INST(move_long_from_halfword_immediate) { int b1; /* Base of effective addr */ VADR effective_addr1; /* Effective address */ S16 i2; /* 16-bit immediate value */ S64 n; /* Sign-extended value of i2 */ SIL(inst, regs, i2, b1, effective_addr1); /* Sign-extend 16-bit immediate value to 64 bits */ n = i2; /* Store 8-byte value at operand address */ ARCH_DEP(vstore8) ( n, effective_addr1, b1, regs ); } /* end DEF_INST(move_long_from_halfword_immediate) */ /*-------------------------------------------------------------------*/ /* E37C MHY - Multiply Halfword (Long Displacement) [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(multiply_halfword_y) { int r1; /* Value of R field */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ S32 n; /* 32-bit operand values */ RXY(inst, regs, r1, b2, effective_addr2); /* Load 2 bytes from operand address */ n = (S16)ARCH_DEP(vfetch2) ( effective_addr2, b2, regs ); /* Multiply R1 register by n, ignore leftmost 32 bits of result, and place rightmost 32 bits in R1 register */ mul_signed ((U32 *)&n, &(regs->GR_L(r1)), regs->GR_L(r1), n); } /* end DEF_INST(multiply_halfword_y) */ /*-------------------------------------------------------------------*/ /* C2x1 MSFI - Multiply Single Immediate Fullword [RIL] */ /*-------------------------------------------------------------------*/ DEF_INST(multiply_single_immediate_fullword) { int r1; /* Register number */ int opcd; /* Opcode */ U32 i2; /* 32-bit operand value */ RIL(inst, regs, r1, opcd, i2); /* Multiply signed operands ignoring overflow */ regs->GR_L(r1) = (S32)regs->GR_L(r1) * (S32)i2; } /* end DEF_INST(multiply_single_immediate_fullword) */ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* C2x0 MSGFI - Multiply Single Immediate Long Fullword [RIL] */ /*-------------------------------------------------------------------*/ DEF_INST(multiply_single_immediate_long_fullword) { int r1; /* Register number */ int opcd; /* Opcode */ U32 i2; /* 32-bit operand value */ RIL(inst, regs, r1, opcd, i2); /* Multiply signed operands ignoring overflow */ regs->GR_G(r1) = (S64)regs->GR_G(r1) * (S32)i2; } /* end DEF_INST(multiply_single_immediate_long_fullword) */ #endif /*defined(FEATURE_ESAME)*/ /*-------------------------------------------------------------------*/ /* E35C MFY - Multiply (Long Displacement) [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(multiply_y) { int r1; /* Value of R field */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ U32 n; /* 32-bit operand values */ RXY(inst, regs, r1, b2, effective_addr2); ODD_CHECK(r1, regs); /* Load second operand from operand address */ n = ARCH_DEP(vfetch4) ( effective_addr2, b2, regs ); /* Multiply r1+1 by n and place result in r1 and r1+1 */ mul_signed (&(regs->GR_L(r1)), &(regs->GR_L(r1+1)), regs->GR_L(r1+1), n); } /* end DEF_INST(multiply_y) */ /*-------------------------------------------------------------------*/ /* E336 PFD - Prefetch Data [RXY] */ /*-------------------------------------------------------------------*/ DEF_INST(prefetch_data) { int m1; /* Mask value */ int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ RXY(inst, regs, m1, b2, effective_addr2); /* The Prefetch Data instruction acts as a no-op */ } /* end DEF_INST(prefetch_data) */ /*-------------------------------------------------------------------*/ /* C6x2 PFDRL - Prefetch Data Relative Long [RIL] */ /*-------------------------------------------------------------------*/ DEF_INST(prefetch_data_relative_long) { int m1; /* Mask value */ VADR addr2; /* Relative operand address */ RIL_A(inst, regs, m1, addr2); /* The Prefetch Data instruction acts as a no-op */ } /* end DEF_INST(prefetch_data_relative_long) */ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* Rotate Then Perform Operation On Selected Bits Long Register */ /* Subroutine is called by RNSBG,RISBG,ROSBG,RXSBG instructions */ /*-------------------------------------------------------------------*/ DEF_INST(rotate_then_xxx_selected_bits_long_reg) { int r1, r2; /* Register numbers */ int start, end; /* Start and end bit number */ U64 mask, rota, resu; /* 64-bit work areas */ int n; /* Number of bits to shift */ int t_bit = 0; /* Test-results indicator */ int z_bit = 0; /* Zero-remaining indicator */ int i; /* Loop counter */ BYTE i3, i4, i5; /* Immediate values */ BYTE opcode; /* 2nd byte of opcode */ RIE_RRIII(inst, regs, r1, r2, i3, i4, i5); /* Extract second byte of instruction opcode */ opcode = inst[5]; /* Extract parameters from immediate fields */ start = i3 & 0x3F; end = i4 & 0x3F; n = i5 & 0x3F; if (opcode == 0x55) z_bit = i4 >> 7; else t_bit = i3 >> 7; /* Copy value from R2 register and rotate left n bits */ rota = (regs->GR_G(r2) << n) | ((n == 0) ? 0 : (regs->GR_G(r2) >> (64 - n))); /* Construct mask for selected bits */ for (i=0, mask=0; i < 64; i++) { mask <<= 1; if (start <= end) { if (i >= start && i <= end) mask |= 1; } else { if (i <= end || i >= start) mask |= 1; } } /* end for(i) */ /* Isolate selected bits of rotated second operand */ rota &= mask; /* Isolate selected bits of first operand */ resu = regs->GR_G(r1) & mask; /* Perform operation on selected bits */ switch (opcode) { case 0x54: /* And */ resu &= rota; break; case 0x55: /* Insert */ resu = rota; break; case 0x56: /* Or */ resu |= rota; break; case 0x57: /* Exclusive Or */ resu ^= rota; break; } /* end switch(opcode) */ /* Except RISBG set condition code according to result bits */ if (opcode != 0x55) regs->psw.cc = (resu == 0) ? 0 : 1; /* Insert result bits into R1 register */ if (t_bit == 0) { if (z_bit == 0) regs->GR_G(r1) = (regs->GR_G(r1) & ~mask) | resu; else regs->GR_G(r1) = resu; } /* end if(t_bit==0) */ /* For RISBG set condition code according to signed result */ if (opcode == 0x55) regs->psw.cc = (S64)regs->GR_G(r1) < 0 ? 1 : (S64)regs->GR_G(r1) > 0 ? 2 : 0; } /* end DEF_INST(rotate_then_xxx_selected_bits_long_reg) */ /*-------------------------------------------------------------------*/ /* EC54 RNSBG - Rotate Then And Selected Bits [RIE] */ /*-------------------------------------------------------------------*/ DEF_INST(rotate_then_and_selected_bits_long_reg) { ARCH_DEP(rotate_then_xxx_selected_bits_long_reg) (inst, regs); } /* end DEF_INST(rotate_then_and_selected_bits_long_reg) */ /*-------------------------------------------------------------------*/ /* EC55 RISBG - Rotate Then Insert Selected Bits [RIE] */ /*-------------------------------------------------------------------*/ DEF_INST(rotate_then_insert_selected_bits_long_reg) { ARCH_DEP(rotate_then_xxx_selected_bits_long_reg) (inst, regs); } /* end DEF_INST(rotate_then_insert_selected_bits_long_reg) */ /*-------------------------------------------------------------------*/ /* EC56 ROSBG - Rotate Then Or Selected Bits [RIE] */ /*-------------------------------------------------------------------*/ DEF_INST(rotate_then_or_selected_bits_long_reg) { ARCH_DEP(rotate_then_xxx_selected_bits_long_reg) (inst, regs); } /* end DEF_INST(rotate_then_or_selected_bits_long_reg) */ /*-------------------------------------------------------------------*/ /* EC57 RXSBG - Rotate Then Exclusive Or Selected Bits [RIE] */ /*-------------------------------------------------------------------*/ DEF_INST(rotate_then_exclusive_or_selected_bits_long_reg) { ARCH_DEP(rotate_then_xxx_selected_bits_long_reg) (inst, regs); } /* end DEF_INST(rotate_then_exclusive_or_selected_bits_long_reg) */ #endif /*defined(FEATURE_ESAME)*/ /*-------------------------------------------------------------------*/ /* C4x7 STHRL - Store Halfword Relative Long [RIL] */ /*-------------------------------------------------------------------*/ DEF_INST(store_halfword_relative_long) { int r1; /* Register number */ VADR addr2; /* Relative operand address */ RIL_A(inst, regs, r1, addr2); /* Store low 2 bytes of R1 register in instruction address space */ ARCH_DEP(vstore2) ( regs->GR_LHL(r1), addr2, USE_INST_SPACE, regs ); } /* end DEF_INST(store_halfword_relative_long) */ /*-------------------------------------------------------------------*/ /* C4xF STRL - Store Relative Long [RIL] */ /*-------------------------------------------------------------------*/ DEF_INST(store_relative_long) { int r1; /* Register number */ VADR addr2; /* Relative operand address */ RIL_A(inst, regs, r1, addr2); /* Program check if operand not on fullword boundary */ FW_CHECK(addr2, regs); /* Store low 4 bytes of R1 register in instruction address space */ ARCH_DEP(vstore4) ( regs->GR_L(r1), addr2, USE_INST_SPACE, regs ); } /* end DEF_INST(store_relative_long) */ /*-------------------------------------------------------------------*/ /* C4xB STGRL - Store Relative Long Long [RIL] */ /*-------------------------------------------------------------------*/ DEF_INST(store_relative_long_long) { int r1; /* Register number */ VADR addr2; /* Relative operand address */ RIL_A(inst, regs, r1, addr2); /* Program check if operand not on doubleword boundary */ DW_CHECK(addr2, regs); /* Store R1 register in instruction address space */ ARCH_DEP(vstore8) ( regs->GR_G(r1), addr2, USE_INST_SPACE, regs ); } /* end DEF_INST(store_relative_long_long) */ #endif /*defined(FEATURE_GENERAL_INSTRUCTIONS_EXTENSION_FACILITY)*/ #if !defined(_GEN_ARCH) #if defined(_ARCHMODE2) #define _GEN_ARCH _ARCHMODE2 #include "general3.c" #endif #if defined(_ARCHMODE3) #undef _GEN_ARCH #define _GEN_ARCH _ARCHMODE3 #include "general3.c" #endif #endif /*!defined(_GEN_ARCH)*/ hercules-3.07/getopt.c000644 000765 000765 00000046167 11143760544 016434 0ustar00jmaynardjmaynard000000 000000 /* $NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $ */ // $Id: getopt.c 5013 2009-01-02 19:21:52Z jj $ /*- * Copyright (c) 2000 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Dieter Baron and Thomas Klausner. * * 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. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the NetBSD * Foundation, Inc. and its contributors. * 4. Neither the name of The NetBSD Foundation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. */ // $Log$ // Revision 1.3 2006/12/08 09:43:21 jj // Add CVS message log // #define _GETOPT_C_ #define _HUTIL_DLL_ #include "hstdinc.h" #include "hercules.h" /* #include #include #include */ #include "getopt.h" /* #include #include */ #define REPLACE_GETOPT #define _DIAGASSERT(x) do {} while (0) #ifdef REPLACE_GETOPT #ifdef __weak_alias __weak_alias(getopt,_getopt) #endif DLL_EXPORT int opterr = 1; /* if error message should be printed */ DLL_EXPORT int optind = 1; /* index into parent argv vector */ DLL_EXPORT int optopt = '?'; /* character checked for validity */ DLL_EXPORT int optreset; /* reset getopt */ DLL_EXPORT char *optarg; /* argument associated with option */ #endif #ifdef __weak_alias __weak_alias(getopt_long,_getopt_long) #endif #ifndef __CYGWIN__ #define __progname __argv[0] #else extern char __declspec(dllimport) *__progname; #endif #define IGNORE_FIRST (*options == '-' || *options == '+') #define PRINT_ERROR ((opterr) && ((*options != ':') \ || (IGNORE_FIRST && options[1] != ':'))) /* This differs from the cygwin implementation, which effectively defaults to PC, but is consistent with the NetBSD implementation and doc's. */ #ifndef IS_POSIXLY_CORRECT #define IS_POSIXLY_CORRECT (getenv("POSIXLY_CORRECT") != NULL) #endif #define PERMUTE (!IS_POSIXLY_CORRECT && !IGNORE_FIRST) /* XXX: GNU ignores PC if *options == '-' */ #define IN_ORDER (!IS_POSIXLY_CORRECT && *options == '-') /* return values */ #define BADCH (int)'?' #define BADARG ((IGNORE_FIRST && options[1] == ':') \ || (*options == ':') ? (int)':' : (int)'?') #define INORDER (int)1 static char EMSG[1]; static int getopt_internal (int, char * const *, const char *); static int gcd (int, int); static void permute_args (int, int, int, char * const *); static char *place = EMSG; /* option letter processing */ /* XXX: set optreset to 1 rather than these two */ static int nonopt_start = -1; /* first non option argument (for permute) */ static int nonopt_end = -1; /* first option after non options (for permute) */ /* Error messages */ static const char recargchar[] = "option requires an argument -- %c"; static const char recargstring[] = "option requires an argument -- %s"; static const char ambig[] = "ambiguous option -- %.*s"; static const char noarg[] = "option doesn't take an argument -- %.*s"; static const char illoptchar[] = "unknown option -- %c"; static const char illoptstring[] = "unknown option -- %s"; static void _vwarnx(const char *fmt, va_list ap) { (void)fprintf(stderr, "%s: ", __progname); if (fmt != NULL) (void)vfprintf(stderr, fmt, ap); (void)fprintf(stderr, "\n"); } static void warnx(const char *fmt, ...) { va_list ap; va_start(ap, fmt); _vwarnx(fmt, ap); va_end(ap); } /* * Compute the greatest common divisor of a and b. */ static int gcd(a, b) int a; int b; { int c; c = a % b; while (c != 0) { a = b; b = c; c = a % b; } return b; } /* * Exchange the block from nonopt_start to nonopt_end with the block * from nonopt_end to opt_end (keeping the same order of arguments * in each block). */ static void permute_args(panonopt_start, panonopt_end, opt_end, nargv) int panonopt_start; int panonopt_end; int opt_end; char * const *nargv; { int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos; char *swap; _DIAGASSERT(nargv != NULL); /* * compute lengths of blocks and number and size of cycles */ nnonopts = panonopt_end - panonopt_start; nopts = opt_end - panonopt_end; ncycle = gcd(nnonopts, nopts); cyclelen = (opt_end - panonopt_start) / ncycle; for (i = 0; i < ncycle; i++) { cstart = panonopt_end+i; pos = cstart; for (j = 0; j < cyclelen; j++) { if (pos >= panonopt_end) pos -= nnonopts; else pos += nopts; swap = nargv[pos]; /* LINTED const cast */ ((char **) nargv)[pos] = nargv[cstart]; /* LINTED const cast */ ((char **)nargv)[cstart] = swap; } } } /* * getopt_internal -- * Parse argc/argv argument vector. Called by user level routines. * Returns -2 if -- is found (can be long option or end of options marker). */ static int getopt_internal(nargc, nargv, options) int nargc; char * const *nargv; const char *options; { char *oli; /* option letter list index */ int optchar; _DIAGASSERT(nargv != NULL); _DIAGASSERT(options != NULL); optarg = NULL; /* * XXX Some programs (like rsyncd) expect to be able to * XXX re-initialize optind to 0 and have getopt_long(3) * XXX properly function again. Work around this braindamage. */ if (optind == 0) optind = 1; if (optreset) nonopt_start = nonopt_end = -1; start: if (optreset || !*place) { /* update scanning pointer */ optreset = 0; if (optind >= nargc) { /* end of argument vector */ place = EMSG; if (nonopt_end != -1) { /* do permutation, if we have to */ permute_args(nonopt_start, nonopt_end, optind, nargv); optind -= nonopt_end - nonopt_start; } else if (nonopt_start != -1) { /* * If we skipped non-options, set optind * to the first of them. */ optind = nonopt_start; } nonopt_start = nonopt_end = -1; return -1; } if ((*(place = nargv[optind]) != '-') || (place[1] == '\0')) { /* found non-option */ place = EMSG; if (IN_ORDER) { /* * GNU extension: * return non-option as argument to option 1 */ optarg = nargv[optind++]; return INORDER; } if (!PERMUTE) { /* * if no permutation wanted, stop parsing * at first non-option */ return -1; } /* do permutation */ if (nonopt_start == -1) nonopt_start = optind; else if (nonopt_end != -1) { permute_args(nonopt_start, nonopt_end, optind, nargv); nonopt_start = optind - (nonopt_end - nonopt_start); nonopt_end = -1; } optind++; /* process next argument */ goto start; } if (nonopt_start != -1 && nonopt_end == -1) nonopt_end = optind; if (place[1] && *++place == '-') { /* found "--" */ place++; return -2; } } if ((optchar = (int)*place++) == (int)':' || (oli = strchr(options + (IGNORE_FIRST ? 1 : 0), optchar)) == NULL) { /* option letter unknown or ':' */ if (!*place) ++optind; if (PRINT_ERROR) warnx(illoptchar, optchar); optopt = optchar; return BADCH; } if (optchar == 'W' && oli[1] == ';') { /* -W long-option */ /* XXX: what if no long options provided (called by getopt)? */ if (*place) return -2; if (++optind >= nargc) { /* no arg */ place = EMSG; if (PRINT_ERROR) warnx(recargchar, optchar); optopt = optchar; return BADARG; } else /* white space */ place = nargv[optind]; /* * Handle -W arg the same as --arg (which causes getopt to * stop parsing). */ return -2; } if (*++oli != ':') { /* doesn't take argument */ if (!*place) ++optind; } else { /* takes (optional) argument */ optarg = NULL; if (*place) /* no white space */ optarg = place; /* XXX: disable test for :: if PC? (GNU doesn't) */ else if (oli[1] != ':') { /* arg not optional */ if (++optind >= nargc) { /* no arg */ place = EMSG; if (PRINT_ERROR) warnx(recargchar, optchar); optopt = optchar; return BADARG; } else optarg = nargv[optind]; } place = EMSG; ++optind; } /* dump back option letter */ return optchar; } #ifdef REPLACE_GETOPT /* * getopt -- * Parse argc/argv argument vector. * * [eventually this will replace the real getopt] */ DLL_EXPORT int getopt(nargc, nargv, options) int nargc; char * const *nargv; const char *options; { int retval; _DIAGASSERT(nargv != NULL); _DIAGASSERT(options != NULL); if ((retval = getopt_internal(nargc, nargv, options)) == -2) { ++optind; /* * We found an option (--), so if we skipped non-options, * we have to permute. */ if (nonopt_end != -1) { permute_args(nonopt_start, nonopt_end, optind, nargv); optind -= nonopt_end - nonopt_start; } nonopt_start = nonopt_end = -1; retval = -1; } return retval; } #endif /* * getopt_long -- * Parse argc/argv argument vector. */ DLL_EXPORT int getopt_long(nargc, nargv, options, long_options, idx) int nargc; char * const *nargv; const char *options; const struct option *long_options; int *idx; { int retval; _DIAGASSERT(nargv != NULL); _DIAGASSERT(options != NULL); _DIAGASSERT(long_options != NULL); /* idx may be NULL */ if ((retval = getopt_internal(nargc, nargv, options)) == -2) { char *current_argv, *has_equal; size_t current_argv_len; int i, match; current_argv = place; match = -1; optind++; place = EMSG; if (*current_argv == '\0') { /* found "--" */ /* * We found an option (--), so if we skipped * non-options, we have to permute. */ if (nonopt_end != -1) { permute_args(nonopt_start, nonopt_end, optind, nargv); optind -= nonopt_end - nonopt_start; } nonopt_start = nonopt_end = -1; return -1; } if ((has_equal = strchr(current_argv, '=')) != NULL) { /* argument found (--option=arg) */ current_argv_len = has_equal - current_argv; has_equal++; } else current_argv_len = strlen(current_argv); for (i = 0; long_options[i].name; i++) { /* find matching long option */ if (strncmp(current_argv, long_options[i].name, current_argv_len)) continue; if (strlen(long_options[i].name) == (unsigned)current_argv_len) { /* exact match */ match = i; break; } if (match == -1) /* partial match */ match = i; else { /* ambiguous abbreviation */ if (PRINT_ERROR) warnx(ambig, (int)current_argv_len, current_argv); optopt = 0; return BADCH; } } if (match != -1) { /* option found */ if (long_options[match].has_arg == no_argument && has_equal) { if (PRINT_ERROR) warnx(noarg, (int)current_argv_len, current_argv); /* * XXX: GNU sets optopt to val regardless of * flag */ if (long_options[match].flag == NULL) optopt = long_options[match].val; else optopt = 0; return BADARG; } if (long_options[match].has_arg == required_argument || long_options[match].has_arg == optional_argument) { if (has_equal) optarg = has_equal; else if (long_options[match].has_arg == required_argument) { /* * optional argument doesn't use * next nargv */ optarg = nargv[optind++]; } } if ((long_options[match].has_arg == required_argument) && (optarg == NULL)) { /* * Missing argument; leading ':' * indicates no error should be generated */ if (PRINT_ERROR) warnx(recargstring, current_argv); /* * XXX: GNU sets optopt to val regardless * of flag */ if (long_options[match].flag == NULL) optopt = long_options[match].val; else optopt = 0; --optind; return BADARG; } } else { /* unknown option */ if (PRINT_ERROR) warnx(illoptstring, current_argv); optopt = 0; return BADCH; } if (long_options[match].flag) { *long_options[match].flag = long_options[match].val; retval = 0; } else retval = long_options[match].val; if (idx) *idx = match; } return retval; } hercules-3.07/getopt.h000644 000765 000765 00000006366 11143760544 016436 0ustar00jmaynardjmaynard000000 000000 /* * Copyright (c) 1987, 1993, 1994, 1996 * The Regents of the University of California. 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. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. */ #ifndef __GETOPT_H__ #define __GETOPT_H__ #ifdef _MSVC_ #include "hostopts.h" #ifdef HDL_BUILD_SHARED #ifndef _GETOPT_C_ #ifndef _HUTIL_DLL_ #define GOP_DLL_IMPORT DLL_IMPORT #else /* _HUTIL_DLL_ */ #define GOP_DLL_IMPORT extern #endif /* _HUTIL_DLL_ */ #else #define GOP_DLL_IMPORT DLL_EXPORT #endif #else #define GOP_DLL_IMPORT extern #endif #endif #ifndef _MSVC_ #define GOP_DLL_IMPORT extern #endif #ifdef __cplusplus extern "C" { #endif GOP_DLL_IMPORT int opterr; /* if error message should be printed */ GOP_DLL_IMPORT int optind; /* index into parent argv vector */ GOP_DLL_IMPORT int optopt; /* character checked for validity */ GOP_DLL_IMPORT int optreset; /* reset getopt */ GOP_DLL_IMPORT char *optarg; /* argument associated with option */ GOP_DLL_IMPORT int getopt (int, char * const *, const char *); #ifdef __cplusplus } #endif #endif /* __GETOPT_H__ */ #ifndef __UNISTD_GETOPT__ #ifndef __GETOPT_LONG_H__ #define __GETOPT_LONG_H__ #ifdef __cplusplus extern "C" { #endif struct option { const char *name; int has_arg; int *flag; int val; }; GOP_DLL_IMPORT int getopt_long (int, char *const *, const char *, const struct option *, int *); #ifndef HAVE_DECL_GETOPT #define HAVE_DECL_GETOPT 1 #endif #define no_argument 0 #define required_argument 1 #define optional_argument 2 #ifdef __cplusplus } #endif #endif /* __GETOPT_LONG_H__ */ #endif /* __UNISTD_GETOPT__ */ hercules-3.07/hao.c000644 000765 000765 00000052351 11143760544 015671 0ustar00jmaynardjmaynard000000 000000 /*---------------------------------------------------------------------------*/ /* file: hao.c */ /* */ /* Implementation of the automatic operator withing the Hercules z/Series */ /* emulator. This implementation couldn't be done without the advise of */ /* Jan Jaeger, who always has an answer to any question. Thanks for the */ /* regex advice! */ /* */ /* (c) Copyright Bernard van der Helm, 2002-2009 */ /* Noordwijkerhout, The Netherlands. */ /* */ /*---------------------------------------------------------------------------*/ // $Id: hao.c 5125 2009-01-23 12:01:44Z bernard $ // // $Log$ // Revision 1.15 2008/11/30 09:12:41 bernard // End the licensed OS experiment // // Revision 1.14 2008/11/29 12:26:19 bernard // PGMPRDOS implementation within hoa. Not perfect! please provide command // hoa clear if you want to violate the PGMPRDOS warning. // // Revision 1.13 2008/11/04 05:56:31 fish // Put ensure consistent create_thread ATTR usage change back in // // Revision 1.12 2008/11/03 15:31:57 rbowler // Back out consistent create_thread ATTR modification // // Revision 1.11 2008/10/18 09:32:21 fish // Ensure consistent create_thread ATTR usage // // Revision 1.10 2008/08/23 11:55:23 fish // Increase max #of rules from 10 to 64 // // Revision 1.9 2008/07/30 15:29:04 bernard // Strip herc prefix before checking the message. // // Revision 1.8 2008/07/30 06:25:27 fish // use 'if' statement instead of 'min' macro to fix Linux build error, // and remove redundant buffer initialization already done by hao_initialize. // // Revision 1.7 2008/07/29 05:55:41 fish // Fix buffer mgmt bug in hao_thread causing garbage // // Revision 1.6 2008/07/26 14:39:42 bernard // Foutje, bedankt! // // Revision 1.5 2008/07/26 14:30:17 bernard // Reject hao automatic commands. This causes deadlocks. // // Revision 1.4 2007/06/23 00:04:10 ivan // Update copyright notices to include current year (2007) // // Revision 1.3 2006/12/08 09:43:21 jj // Add CVS message log // #include "hstdinc.h" #define _HAO_C_ #define _HENGINE_DLL_ #include "hercules.h" #if defined(OPTION_HAO) /*---------------------------------------------------------------------------*/ /* constants */ /*---------------------------------------------------------------------------*/ #define HHCAO001I "HHCAO001I Hercules Automatic Operator thread started;\n" \ " tid="TIDPAT", pri=%d, pid=%d\n" #define HHCAO002I "HHCAO002I Hercules Automatic Operator thread ended\n" #define HHCAO003I "HHCAO003I Firing command: '%s'\n" #define HHCAO004I "HHCAO004I The defined Automatic Operator rule(s) are:\n" #define HHCAO005I "HHCAO005I %02d: '%s' -> '%s'\n" #define HHCAO006I "HHCAO006I %d rule(s) displayed\n" #define HHCAO007E "HHCAO007E Unknown hao command, valid commands are:\n" \ " hao tgt : define target rule (pattern) to react on\n" \ " hao cmd : define command for previously defined rule\n" \ " hao list : list all rules/commands or only at index \n" \ " hao del : delete the rule at index \n" \ " hao clear : delete all rules (stops automatic operator)\n" #define HHCAO008E "HHCAO008E No rule defined at index %d\n" #define HHCAO009E "HHCAO009E Invalid index, index must be between 0 and %d\n" #define HHCAO010E "HHCAO010E Target not added, table full\n" #define HHCAO011E "HHCAO011E Tgt command given, but cmd command expected\n" #define HHCAO012E "HHCAO012E Empty target specified\n" #define HHCAO013E "HHCAO013E Target not added, duplicate found in table\n" #define HHCAO014E "HHCAO014E %s\n" #define HHCAO015E "HHCAO015E %s\n" #define HHCAO016I "HHCAO016I Target placed at index %d\n" #define HHCAO017E "HHCAO017E Cmd command given, but tgt command expected\n" #define HHCAO018E "HHCAO018E Empty command specified\n" #define HHCAO019E "HHCAO019E Command not added; causes loop with target at index %d\n" #define HHCAO020I "HHCAO020I Command placed at index %d\n" #define HHCAO021E "HHCAO021E Target not added, causes loop with command at index %d\n" #define HHCAO022I "HHCAO022I All automatic operation rules cleared\n" #define HHCAO023E "HHCAO023E hao del command given without a valid index\n" #define HHCAO024E "HHCAO024E Rule at index %d not deleted, already empty\n" #define HHCAO025I "HHCAO025I Rule at index %d succesfully deleted\n" #define HHCA0026E "HHCA0026E Command not added, may cause dead locks\n" #define HAO_WKLEN 256 /* (maximum message length able to tolerate) */ #define HAO_MAXRULE 64 /* (purely arbitrary and easily increasable) */ /*---------------------------------------------------------------------------*/ /* local variables */ /*---------------------------------------------------------------------------*/ static LOCK ao_lock; static regex_t ao_preg[HAO_MAXRULE]; static char *ao_cmd[HAO_MAXRULE]; static char *ao_tgt[HAO_MAXRULE]; static char ao_msgbuf[LOG_DEFSIZE+1]; /* (plus+1 for NULL termination) */ /*---------------------------------------------------------------------------*/ /* function prototypes */ /*---------------------------------------------------------------------------*/ DLL_EXPORT void hao_initialize(void); DLL_EXPORT void hao_command(char *cmd); DLL_EXPORT void hao_message(char *buf); static void hao_clear(void); static void hao_cmd(char *arg); static void hao_cpstrp(char *dest, char *src); static void hao_del(char *arg); static void hao_list(char *arg); static void hao_tgt(char *arg); static void* hao_thread(void* dummy); /*---------------------------------------------------------------------------*/ /* void hao_initialize(void) */ /* */ /* This function is called at system startup by impl.c 'process_rc_file' */ /* It initializes all global variables. */ /*---------------------------------------------------------------------------*/ DLL_EXPORT void hao_initialize(void) { int i = 0; initialize_lock(&ao_lock); /* serialize */ obtain_lock(&ao_lock); /* initialize variables */ for(i = 0; i < HAO_MAXRULE; i++) { ao_cmd[i] = NULL; ao_tgt[i] = NULL; } /* initialize message buffer */ memset(ao_msgbuf, 0, sizeof(ao_msgbuf)); /* Start message monitoring thread */ if ( create_thread (&sysblk.haotid, JOINABLE, hao_thread, NULL, "hao_thread") ) { logmsg(_("HHCIN004S Cannot create HAO thread: %s\n"), strerror(errno)); } release_lock(&ao_lock); } /*---------------------------------------------------------------------------*/ /* void hao_command(char *cmd) */ /* */ /* Within panel this function is called when a command is given that starts */ /* with the string hao. Here we check if a correct hao command is requested, */ /* otherwise a help is printed. */ /*---------------------------------------------------------------------------*/ DLL_EXPORT void hao_command(char *cmd) { char work[HAO_WKLEN]; char work2[HAO_WKLEN]; /* copy and strip spaces */ hao_cpstrp(work, cmd); /* again without starting hao */ hao_cpstrp(work2, &work[3]); if(!strncasecmp(work2, "tgt", 3)) { /* again without starting tgt */ hao_cpstrp(work, &work2[3]); hao_tgt(work); return; } if(!strncasecmp(work2, "cmd", 3)) { /* again without starting cmd */ hao_cpstrp(work, &work2[3]); hao_cmd(work); return; } if(!strncasecmp(work2, "del", 3)) { /* again without starting del */ hao_cpstrp(work, &work2[3]); hao_del(work); return; } if(!strncasecmp(work2, "list", 4)) { /* again without starting list */ hao_cpstrp(work, &work2[4]); hao_list(work); return; } if(!strncasecmp(work2, "clear", 4)) { hao_clear(); return; } logmsg(HHCAO007E); } /*---------------------------------------------------------------------------*/ /* hao_cpstrp(char *dest, char *src) */ /* */ /* This function copies the string from src to dest, without the trailing */ /* and ending spaces. */ /*---------------------------------------------------------------------------*/ static void hao_cpstrp(char *dest, char *src) { int i; for(i = 0; src[i] == ' '; i++); strncpy(dest, &src[i], HAO_WKLEN); dest[HAO_WKLEN-1] = 0; for(i = strlen(dest); i && dest[i - 1] == ' '; i--); dest[i] = 0; } /*---------------------------------------------------------------------------*/ /* void hao_tgt(char *arg) */ /* */ /* This function is given when the hao tgt command is given. A free slot is */ /* to be found and filled with the rule. There will be loop checking. */ /*---------------------------------------------------------------------------*/ static void hao_tgt(char *arg) { int i; int j; int rc; char work[HAO_WKLEN]; /* serialize */ obtain_lock(&ao_lock); /* find a free slot */ for(i = 0; ao_tgt[i] && i < HAO_MAXRULE; i++) /* check for table full */ if(i == HAO_MAXRULE) { release_lock(&ao_lock); logmsg(HHCAO010E); return; } /* check if not command is expected */ for(j = 0; j < HAO_MAXRULE; j++) { if(ao_tgt[j] && !ao_cmd[j]) { release_lock(&ao_lock); logmsg(HHCAO011E); return; } } /* check for empty target */ if(!strlen(arg)) { release_lock(&ao_lock); logmsg(HHCAO012E); return; } /* check for duplicate targets */ for(j = 0; j < HAO_MAXRULE; j++) { if(ao_tgt[j] && !strcmp(arg, ao_tgt[j])) { release_lock(&ao_lock); logmsg(HHCAO013E); return; } } /* compile the target string */ rc = regcomp(&ao_preg[i], arg, 0); /* check for error */ if(rc) { release_lock(&ao_lock); /* place error in work */ regerror(rc, (const regex_t *) &ao_preg[i], work, HAO_WKLEN); logmsg(HHCAO014E, work); return; } /* check for possible loop */ for(j = 0; j < HAO_MAXRULE; j++) { if(ao_cmd[j] && !regexec(&ao_preg[i], ao_cmd[j], 0, NULL, 0)) { release_lock(&ao_lock); regfree(&ao_preg[i]); logmsg(HHCAO021E, i); return; } } /* duplicate the target */ ao_tgt[i] = strdup(arg); /* check duplication */ if(!ao_tgt[i]) { release_lock(&ao_lock); regfree(&ao_preg[i]); logmsg(HHCAO015E, strerror(ENOMEM)); return; } release_lock(&ao_lock); logmsg(HHCAO016I, i); } /*---------------------------------------------------------------------------*/ /* void hao_cmd(char *arg) */ /* */ /* This function is called when the hao cmd command is given. It searches */ /* the index of the last given hao tgt command. Does some checking and fills */ /* the entry with the given command. There will be loop checking */ /*---------------------------------------------------------------------------*/ static void hao_cmd(char *arg) { int i; int j; /* serialize */ obtain_lock(&ao_lock); /* find the free slot */ for(i = 0; ao_cmd[i] && i < HAO_MAXRULE; i++); /* check for table full -> so tgt cmd expected */ if(i == HAO_MAXRULE) { release_lock(&ao_lock); logmsg(HHCAO017E); return; } /* check if target is given */ if(!ao_tgt[i]) { release_lock(&ao_lock); logmsg(HHCAO017E); return; } /* check for empty cmd string */ if(!strlen(arg)) { release_lock(&ao_lock); logmsg(HHCAO018E); return; } /* check for hao command, prevent deadlock */ for(j = 0; !strncasecmp(&arg[j], "herc ", 4); j += 5); if(!strcasecmp(&arg[j], "hao") || !strncasecmp(&arg[j], "hao ", 4)) { release_lock(&ao_lock); logmsg(HHCA0026E); return; } /* check for possible loop */ for(j = 0; j < HAO_MAXRULE; j++) { if(ao_tgt[j] && !regexec(&ao_preg[j], arg, 0, NULL, 0)) { release_lock(&ao_lock); logmsg(HHCAO019E, j); return; } } /* duplicate the string */ ao_cmd[i] = strdup(arg); /* check duplication */ if(!ao_cmd[i]) { release_lock(&ao_lock); logmsg(HHCAO015E, strerror(ENOMEM)); return; } release_lock(&ao_lock); logmsg(HHCAO020I, i); } /*---------------------------------------------------------------------------*/ /* void hao_del(char *arg) */ /* */ /* This function is called when the command hao del is given. the rule in */ /* the given index is cleared. */ /*---------------------------------------------------------------------------*/ static void hao_del(char *arg) { int i; int rc; /* read the index number to delete */ rc = sscanf(arg, "%d", &i); if(!rc || rc == -1) { logmsg(HHCAO023E); return; } /* check if index is valid */ if(i < 0 || i >= HAO_MAXRULE) { logmsg(HHCAO009E, HAO_MAXRULE - 1); return; } /* serialize */ obtain_lock(&ao_lock); /* check if entry exists */ if(!ao_tgt[i]) { release_lock(&ao_lock); logmsg(HHCAO024E, i); return; } /* delete the entry */ free(ao_tgt[i]); ao_tgt[i] = NULL; regfree(&ao_preg[i]); if(ao_cmd[i]) { free(ao_cmd[i]); ao_cmd[i] = NULL; } release_lock(&ao_lock); logmsg(HHCAO025I, i); } /*---------------------------------------------------------------------------*/ /* void hao_list(char *arg) */ /* */ /* this function is called when the hao list command is given. It lists all */ /* rules. When given an index, only that index will be showed. */ /*---------------------------------------------------------------------------*/ static void hao_list(char *arg) { int i; int rc; int size; rc = sscanf(arg, "%d", &i); if(!rc || rc == -1) { /* list all rules */ logmsg(HHCAO004I); size = 0; /* serialize */ obtain_lock(&ao_lock); for(i = 0; i < HAO_MAXRULE; i++) { if(ao_tgt[i]) { logmsg(HHCAO005I, i, ao_tgt[i], (ao_cmd[i] ? ao_cmd[i] : "")); size++; } } release_lock(&ao_lock); logmsg(HHCAO006I, size); } else { /* list specific index */ if(i < 0 || i >= HAO_MAXRULE) logmsg(HHCAO009E, HAO_MAXRULE - 1); else { /* serialize */ obtain_lock(&ao_lock); if(!ao_tgt[i]) logmsg(HHCAO008E, i); else logmsg(HHCAO005I, i, ao_tgt[i], (ao_cmd[i] ? ao_cmd[i] : "not specified")); release_lock(&ao_lock); } } } /*---------------------------------------------------------------------------*/ /* void hao_clear(void) */ /* */ /* This function is called when the hao clear command is given. This */ /* function just clears all defined rules. Handy command for panic */ /* situations. */ /*---------------------------------------------------------------------------*/ static void hao_clear(void) { int i; /* serialize */ obtain_lock(&ao_lock); /* clear all defined rules */ for(i = 0; i < HAO_MAXRULE; i++) { if(ao_tgt[i]) { free(ao_tgt[i]); ao_tgt[i] = NULL; regfree(&ao_preg[i]); } if(ao_cmd[i]) { free(ao_cmd[i]); ao_cmd[i] = NULL; } } release_lock(&ao_lock); logmsg(HHCAO022I); } /*---------------------------------------------------------------------------*/ /* void* hao_thread(void* dummy) */ /* */ /* This thread is created by hao_initialize. It examines every message */ /* printed. Here we check if a rule applies to the message. If so we fire */ /* the command within the rule. */ /*---------------------------------------------------------------------------*/ static void* hao_thread(void* dummy) { char* msgbuf = NULL; int msgidx = -1; int msgamt = 0; char* msgend = NULL; char svchar = 0; int bufamt = 0; UNREFERENCED(dummy); logmsg(HHCAO001I, thread_id(), getpriority(PRIO_PROCESS,0), getpid()); /* Wait for panel thread to engage */ while (!sysblk.panel_init && !sysblk.shutdown) usleep( 10 * 1000 ); /* Do until shutdown */ while (!sysblk.shutdown && msgamt >= 0) { /* wait for message data */ if ((msgamt = log_read(&msgbuf, &msgidx, LOG_BLOCK)) > 0 ) { /* append to existing data */ if (msgamt > (int)((sizeof(ao_msgbuf) - 1) - bufamt) ) msgamt = (int)((sizeof(ao_msgbuf) - 1) - bufamt); strncpy( &ao_msgbuf[bufamt], msgbuf, msgamt ); ao_msgbuf[bufamt += msgamt] = 0; msgbuf = ao_msgbuf; /* process only complete messages */ while (NULL != (msgend = strchr(msgbuf,'\n'))) { /* null terminate message */ svchar = *(msgend+1); *(msgend+1) = 0; /* process message */ hao_message(msgbuf); /* restore destroyed byte */ *(msgend+1) = svchar; msgbuf = msgend+1; } /* shift message buffer */ memmove( ao_msgbuf, msgbuf, bufamt -= (msgbuf - ao_msgbuf) ); } } logmsg(HHCAO002I); return NULL; } /*---------------------------------------------------------------------------*/ /* void hao_message(char *buf) */ /* */ /* This function is called by hao_thread whenever a message is about to be */ /* printed. Here we check if a rule applies to the message. If so we fire */ /* the command within the rule. */ /*---------------------------------------------------------------------------*/ DLL_EXPORT void hao_message(char *buf) { char work[HAO_WKLEN]; regmatch_t rm; int i; /* copy and strip spaces */ hao_cpstrp(work, buf); /* strip the herc prefix */ while(!strncmp(work, "herc", 4)) hao_cpstrp(work, &work[4]); /* don't react on own messages */ if(!strncmp(work, "HHCAO", 5)) return; /* don't react on own commands */ if(!strncasecmp(work, "hao", 3)) return; /* also from the .rc file */ if(!strncasecmp(work, "> hao", 5)) return; /* serialize */ obtain_lock(&ao_lock); /* check all defined rules */ for(i = 0; i < HAO_MAXRULE; i++) { if(ao_tgt[i] && ao_cmd[i]) /* complete rule defined in this slot? */ { /* does this rule match our message? */ if (regexec(&ao_preg[i], work, 1, &rm, 0) == 0) { /* issue command for this rule */ logmsg(HHCAO003I, ao_cmd[i]); panel_command(ao_cmd[i]); } } } release_lock(&ao_lock); } #endif /* defined(OPTION_HAO) */ /////////////////////////////////////////////////////////////////////////////// // Fish notes for possible future enhancement: I was thinking we should // probably at some point support command rules that allow a custom // command to be constructed based on the string(s) that was/were found. #if 0 /* The following demonstrates how the REG_NOTBOL flag could be used with regexec() to find all substrings in a line that match a pattern supplied by a user. (For simplicity of the example, very little error checking is done.) */ regex_t re; /* regular expression */ regmatch_t pm; /* match info */ int error; /* rc from regexec */ char buffer[] = "The quick brown dog jumps over the lazy fox"; char pattern[] = "lazy"; /* Compile the search pattern */ (void)regcomp( &re, pattern, 0 ); /* This call to regexec() finds the first match on the line */ error = regexec( &re, &buffer[0], 1, &pm, 0 ); while (error == 0) /* while matches found */ { /* Substring found between 'pm.rm_so' and 'pm.rm_eo' */ /* This call to regexec() finds the next match */ error = regexec( &re, buffer + pm.rm_eo, 1, &pm, REG_NOTBOL ); } #endif /////////////////////////////////////////////////////////////////////////////// hercules-3.07/hbyteswp.h000644 000765 000765 00000007736 11143760543 017002 0ustar00jmaynardjmaynard000000 000000 /* BYTESWAP.H Little <> Big Endian conversion - Jan Jaeger */ /* These definitions are only nessesary when running on older */ /* versions of linux that do not have /usr/include/byteswap.h */ /* compile option -DNO_ASM_BYTESWAP will expand 'C' code */ /* otherwise Intel (486+) assember will be generated */ // $Id: hbyteswp.h 5039 2009-01-08 01:59:20Z jmaynard $ // // $Log$ // Revision 1.11 2009/01/07 18:00:13 jmaynard // Added x86_64 assembler swap assists for those systems that don't have // byteswap.h in the library. // // Revision 1.10 2006/12/08 09:43:21 jj // Add CVS message log // #ifndef _BYTESWAP_H #define _BYTESWAP_H #if !defined(NO_ASM_BYTESWAP) #include "htypes.h" // (need Hercules fixed-size data types) #if defined( _MSVC_ ) static __inline uint16_t __fastcall bswap_16 ( uint16_t x ) { return _byteswap_ushort((x)); } static __inline uint32_t __fastcall bswap_32 ( uint32_t x ) { return _byteswap_ulong((x)); } #else // !defined( _MSVC_ ) static __inline__ uint16_t (ATTR_REGPARM(1) bswap_16)(uint16_t x) { #if defined(__x86_64__) __asm__("xchgb %b0,%h0" : "=Q" (x) : "0" (x)); #else __asm__("xchgb %b0,%h0" : "=q" (x) : "0" (x)); #endif return x; } static __inline__ uint32_t (ATTR_REGPARM(1) bswap_32)(uint32_t x) { #if defined(__x86_64__) __asm__("bswapl %0" : "=r" (x) : "0" (x)); #else __asm__("bswap %0" : "=r" (x) : "0" (x)); #endif return x; } #endif // defined( _MSVC_ ) #else // defined(NO_ASM_BYTESWAP) #define bswap_16(_x) \ ( (((_x) & 0xFF00) >> 8) \ | (((_x) & 0x00FF) << 8) ) #define bswap_32(_x) \ ( (((_x) & 0xFF000000) >> 24) \ | (((_x) & 0x00FF0000) >> 8) \ | (((_x) & 0x0000FF00) << 8) \ | (((_x) & 0x000000FF) << 24) ) #endif // !defined(NO_ASM_BYTESWAP) #if defined( _MSVC_ ) // Microsoft's Toolkit 2003 compiler (version 1300) has a known bug // that causes the _byteswap_uint64 intrinsic to screw up if global // otimizations are enabled. The new VStudio 8.0 compiler (version // 14.00) doesn't have this problem that I am aware of. NOTE that // the #pragma must be outside the function (at global scope) to // prevent compiler error C2156 "pragma must be outside function". #if ( _MSC_VER < 1400 ) #pragma optimize("g",off) // (disable global optimizations) #endif static __inline uint64_t __fastcall bswap_64(uint64_t x) { return _byteswap_uint64((x)); } #if ( _MSC_VER < 1400 ) #pragma optimize ( "", on ) #endif #else // !defined( _MSVC_ ) #if defined(NO_ASM_BYTESWAP) #define bswap_64(_x) \ ( ((U64)((_x) & 0xFF00000000000000ULL) >> 56) \ | ((U64)((_x) & 0x00FF000000000000ULL) >> 40) \ | ((U64)((_x) & 0x0000FF0000000000ULL) >> 24) \ | ((U64)((_x) & 0x000000FF00000000ULL) >> 8) \ | ((U64)((_x) & 0x00000000FF000000ULL) << 8) \ | ((U64)((_x) & 0x0000000000FF0000ULL) << 24) \ | ((U64)((_x) & 0x000000000000FF00ULL) << 40) \ | ((U64)((_x) & 0x00000000000000FFULL) << 56) ) #else static __inline__ uint64_t (ATTR_REGPARM(1) bswap_64)(uint64_t x) { #if defined(__x86_64__) __asm__("bswapq %0" : "=r" (x) : "0" (x)); return x; #else // swap the two words after byteswapping them union { struct { uint32_t high,low; } words; uint64_t quad; } value; value.quad=x; __asm__("bswap %0" : "=r" (value.words.high) : "0" (value.words.high)); __asm__("bswap %0" : "=r" (value.words.low) : "0" (value.words.low)); __asm__("xchgl %0,%1" : "=r" (value.words.high), "=r" (value.words.low) : "0" (value.words.high), "1" (value.words.low)); return value.quad; #endif // defined(__x86_64__) } #endif // defined(NO_ASM_BYTESWAP) #endif // defined( _MSVC_ ) #endif // _BYTESWAP_H hercules-3.07/hchan.c000644 000765 000765 00000017556 11143760542 016211 0ustar00jmaynardjmaynard000000 000000 /* GCHAN.C (c) Copyright Ivan Warren, 2005-2009 */ /* Based on work (c)Roger Bowler, Jan Jaeger & Others 1999-2009 */ /* Generic channel device handler */ // $Id: hchan.c 5125 2009-01-23 12:01:44Z bernard $ /* This code is covered by the QPL Licence */ /**CAUTION*CAUTION*CAUTION*CAUTION*CAUTION*CAUTION*CAUTION*CAUTION****/ /* THIS CODE IS CURRENTLY IN A DEVELOPMENT STAGE AND IS NOT */ /* OPERATIONAL */ /* THIS FONCTIONALITY IS NOT YET SUPPORTED */ /**CAUTION*CAUTION*CAUTION*CAUTION*CAUTION*CAUTION*CAUTION*CAUTION****/ /*-------------------------------------------------------------------*/ /* This module contains code to handle a generic protocol to */ /* communicate with external device handlers. */ /*-------------------------------------------------------------------*/ // $Log$ // Revision 1.11 2007/11/21 22:54:14 fish // Use new BEGIN_DEVICE_CLASS_QUERY macro // // Revision 1.10 2007/06/23 00:04:10 ivan // Update copyright notices to include current year (2007) // // Revision 1.9 2006/12/08 09:43:21 jj // Add CVS message log // #include "hercules.h" #include "devtype.h" #include "hchan.h" #if defined(OPTION_DYNAMIC_LOAD) && defined(WIN32) && !defined(HDL_USE_LIBTOOL) && !defined(_MSVC_) SYSBLK *psysblk; #define sysblk (*psysblk) #endif /* * Initialisation string for a Generic Subchannel * * Format : * parms * The 'EXEC' method will attempt to fork/exec the specified * program. If the program dies during device initialisation, the * subchannel will be invalidated (initialisation error). If it fails * afterwards, the subchannel will be put offline and the offload * thread will attempt to restart it at periodic intervals. * The 'CONNECT' method will attempt to establish a TCP connection * to the IP/PORT specified. If the connection fails, the connection * will be attempted at periodic intervals. * The 'ITHREAD' method will spawn a thread using a dynamically loaded module */ static int hchan_init_handler ( DEVBLK *dev, int argc, char *argv[] ) { int rc; dev->devtype=0x2880; /* Temporary until the device is actually initialised */ while(1) { if(argc<1) { logmsg("HHCGCH003E %4.4X : Missing Generic Channel method\n",dev->devnum); rc=-1; break; } if(strcasecmp(argv[0],"EXEC")==0) { rc=hchan_init_exec(dev,argc,argv); break; } if(strcasecmp(argv[0],"CONNECT")==0) { rc=hchan_init_connect(dev,argc,argv); break; } if(strcasecmp(argv[0],"ITHREAD")==0) { rc=hchan_init_int(dev,argc,argv); break; } logmsg("HHCGCH001E %4.4X : Incorrect Generic Channel method %s\n",dev->devnum,argv[0]); rc=-1; break; } if(rc) { logmsg("HHCGCH002T %4.4X : Generic channel initialisation failed\n",dev->devnum); } logmsg("HHCGCH999W %4.4X : Generic channel is currently in development\n",dev->devnum); return(rc); } static int hchan_init_exec(DEVBLK *dev,int ac,char **av) { UNREFERENCED(dev); UNREFERENCED(ac); UNREFERENCED(av); return(0); } static int hchan_init_connect(DEVBLK *dev,int ac,char **av) { UNREFERENCED(dev); UNREFERENCED(ac); UNREFERENCED(av); return(0); } static int hchan_init_int(DEVBLK *dev,int ac,char **av) { UNREFERENCED(dev); UNREFERENCED(ac); UNREFERENCED(av); return(0); } /*-------------------------------------------------------------------*/ /* Query the device definition */ /*-------------------------------------------------------------------*/ static void hchan_query_device (DEVBLK *dev, char **class, int buflen, char *buffer) { BEGIN_DEVICE_CLASS_QUERY( "CHAN", dev, class, buflen, buffer ); snprintf(buffer,buflen,"** CONTROL UNIT OFFLINE **"); } /*-------------------------------------------------------------------*/ /* Close the device */ /*-------------------------------------------------------------------*/ static int hchan_close_device ( DEVBLK *dev ) { UNREFERENCED(dev); return 0; } /*-------------------------------------------------------------------*/ /* Execute a Channel Command Word */ /*-------------------------------------------------------------------*/ static void hchan_execute_ccw ( DEVBLK *dev, BYTE code, BYTE flags, BYTE chained, U16 count, BYTE prevcode, int ccwseq, BYTE *iobuf, BYTE *more, BYTE *unitstat, U16 *residual ) { UNREFERENCED(flags); UNREFERENCED(prevcode); UNREFERENCED(ccwseq); UNREFERENCED(chained); UNREFERENCED(count); UNREFERENCED(iobuf); UNREFERENCED(more); UNREFERENCED(residual); /* Process depending on CCW opcode */ switch (code) { default: /*---------------------------------------------------------------*/ /* INVALID OPERATION */ /*---------------------------------------------------------------*/ /* Set command reject sense byte, and unit check status */ dev->sense[0] = SENSE_CR; *unitstat = CSW_CE | CSW_DE | CSW_UC; } } #if defined(OPTION_DYNAMIC_LOAD) static #endif DEVHND hchan_device_hndinfo = { &hchan_init_handler, /* Device Initialisation */ &hchan_execute_ccw, /* Device CCW execute */ &hchan_close_device, /* Device Close */ &hchan_query_device, /* Device Query */ NULL, /* Device Start channel pgm */ NULL, /* Device End channel pgm */ NULL, /* Device Resume channel pgm */ NULL, /* Device Suspend channel pgm */ NULL, /* Device Read */ NULL, /* Device Write */ NULL, /* Device Query used */ NULL, /* Device Reserve */ NULL, /* Device Release */ NULL, /* Device Attention */ NULL, /* Immediate CCW Codes */ NULL, /* Signal Adapter Input */ NULL, /* Signal Adapter Output */ NULL, /* Hercules suspend */ NULL /* Hercules resume */ }; /* Libtool static name colision resolution */ /* note : lt_dlopen will look for symbol & modulename_LTX_symbol */ #if !defined(HDL_BUILD_SHARED) && defined(HDL_USE_LIBTOOL) #define hdl_ddev hdt0000_LTX_hdl_ddev #define hdl_depc hdt0000_LTX_hdl_depc #define hdl_reso hdt0000_LTX_hdl_reso #define hdl_init hdt0000_LTX_hdl_init #define hdl_fini hdt0000_LTX_hdl_fini #endif #if defined(OPTION_DYNAMIC_LOAD) HDL_DEPENDENCY_SECTION; { HDL_DEPENDENCY(HERCULES); HDL_DEPENDENCY(DEVBLK); HDL_DEPENDENCY(SYSBLK); } END_DEPENDENCY_SECTION #if defined(WIN32) && !defined(HDL_USE_LIBTOOL) && !defined(_MSVC_) #undef sysblk HDL_RESOLVER_SECTION; { HDL_RESOLVE_PTRVAR( psysblk, sysblk ); } END_RESOLVER_SECTION #endif HDL_DEVICE_SECTION; { HDL_DEVICE(HCHAN, hchan_device_hndinfo ); HDL_DEVICE(2860, hchan_device_hndinfo ); HDL_DEVICE(2870, hchan_device_hndinfo ); HDL_DEVICE(2880, hchan_device_hndinfo ); HDL_DEVICE(9032, hchan_device_hndinfo ); } END_DEVICE_SECTION #endif hercules-3.07/hchan.h000644 000765 000765 00000000744 11143760542 016205 0ustar00jmaynardjmaynard000000 000000 // $Id: hchan.h 4102 2006-12-08 09:43:35Z jj $ // // $Log$ #ifndef __HCHAN_H__ #define __HCHAN_H__ /* * Hercules Generic Channel internal definitions * (c) Ivan Scott Warren 2004-2006 * based on work * (c) Roger Bowler, Jan Jaeger and Others 1999-2006 * This code is covered by the QPL Licence */ static int hchan_init_exec(DEVBLK *,int,char **); static int hchan_init_connect(DEVBLK *,int,char **); static int hchan_init_int(DEVBLK *,int,char **); #endif hercules-3.07/hconsole.c000644 000765 000765 00000106617 11143760542 016737 0ustar00jmaynardjmaynard000000 000000 ////////////////////////////////////////////////////////////////////////////////////////// // hconsole.c Hercules hardware console (panel) support functions ////////////////////////////////////////////////////////////////////////////////////////// // (c) Copyright "Fish" (David B. Trout), 2005-2009. Released under the Q Public License // (http://www.hercules-390.org/herclic.html) as modifications to Hercules. ////////////////////////////////////////////////////////////////////////////////////////// // $Id: hconsole.c 5125 2009-01-23 12:01:44Z bernard $ // // $Log$ // Revision 1.16 2008/09/02 06:08:09 fish // ALT_RIGHTARROW and ALT_LEFTARROW // // Revision 1.15 2008/08/29 10:22:08 fish // Lay groundwork for eventual extended cursor handling // // Revision 1.14 2008/08/23 11:57:19 fish // Also set console OUTPUT buffer mode for // MSVC builds in order to fix line-wrap issue. // // Revision 1.13 2008/07/10 18:31:33 fish // 1) Add support for Ctrl+Home and Ctrl+End extended control sequences, and // 2) ignore other unsupported extended control sequences. // // Revision 1.12 2008/07/08 13:48:40 fish // Ctrl + uparrow / downarrow ==> scroll up/down one line // // Revision 1.11 2007/11/30 14:54:32 jmaynard // Changed conmicro.cx to hercules-390.org or conmicro.com, as needed. // // Revision 1.10 2007/06/23 00:04:10 ivan // Update copyright notices to include current year (2007) // // Revision 1.9 2006/12/08 09:43:21 jj // Add CVS message log // #include "hstdinc.h" #include "hercules.h" #include "hconsole.h" ////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// #if defined( _MSVC_ ) ////////////////////////////////////////////////////////////////////////////////////////// // 'save_and_set' = 1 --> just what it says; 0 --> restore from saved value. static DWORD g_dwConsoleInputMode = 0; // (saved value so we can later restore it) static DWORD g_dwConsoleOutputMode = 0; // (saved value so we can later restore it) static WORD g_wDefaultAttrib = 0; // (saved value so we can later restore it) static WORD default_FG_color() { return g_wDefaultAttrib & 0x0F; } static WORD default_BG_color() { return (g_wDefaultAttrib >> 4) & 0x0F; } int set_or_reset_console_mode( int keybrd_fd, short save_and_set ) { CONSOLE_SCREEN_BUFFER_INFO csbi; HANDLE hStdIn, hStdErr; DWORD dwNewInputMode; DWORD dwNewOutputMode; if ( ! _isatty( keybrd_fd ) ) { errno = EBADF; return -1; } hStdIn = (HANDLE) _get_osfhandle( keybrd_fd ); ASSERT( hStdIn && INVALID_HANDLE_VALUE != hStdIn ); hStdErr = GetStdHandle( STD_ERROR_HANDLE ); ASSERT( hStdErr && INVALID_HANDLE_VALUE != hStdErr ); if ( save_and_set ) { VERIFY( GetConsoleMode( hStdIn, &g_dwConsoleInputMode ) ); VERIFY( GetConsoleMode( hStdErr, &g_dwConsoleOutputMode ) ); VERIFY( GetConsoleScreenBufferInfo( hStdErr, &csbi ) ); g_wDefaultAttrib = csbi.wAttributes; dwNewInputMode = 0; dwNewOutputMode = 0; } else // (restore/reset) { VERIFY( SetConsoleTextAttribute( hStdErr, g_wDefaultAttrib ) ); dwNewInputMode = g_dwConsoleInputMode; dwNewOutputMode = g_dwConsoleOutputMode; } VERIFY( SetConsoleMode( hStdIn, dwNewInputMode ) ); VERIFY( SetConsoleMode( hStdErr, dwNewOutputMode ) ); return 0; } ////////////////////////////////////////////////////////////////////////////////////////// // Translate Herc color to Win32 color... #define W32_FOREGROUND_COLOR( w32_color ) ( ( w32_color ) ) #define W32_BACKGROUND_COLOR( w32_color ) ( ( w32_color ) << 4 ) #define W32_COLOR_BLACK ( 0 ) #define W32_COLOR_RED ( FOREGROUND_RED ) #define W32_COLOR_GREEN ( FOREGROUND_GREEN ) #define W32_COLOR_BLUE ( FOREGROUND_BLUE ) #define W32_COLOR_CYAN ( FOREGROUND_GREEN | FOREGROUND_BLUE ) #define W32_COLOR_MAGENTA ( FOREGROUND_RED | FOREGROUND_BLUE ) #define W32_COLOR_YELLOW ( FOREGROUND_RED | FOREGROUND_GREEN ) #define W32_COLOR_LIGHT_GREY ( FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE ) #define W32_COLOR_DARK_GREY ( FOREGROUND_INTENSITY | W32_COLOR_BLACK ) #define W32_COLOR_LIGHT_RED ( FOREGROUND_INTENSITY | W32_COLOR_RED ) #define W32_COLOR_LIGHT_GREEN ( FOREGROUND_INTENSITY | W32_COLOR_GREEN ) #define W32_COLOR_LIGHT_BLUE ( FOREGROUND_INTENSITY | W32_COLOR_BLUE ) #define W32_COLOR_LIGHT_CYAN ( FOREGROUND_INTENSITY | W32_COLOR_CYAN ) #define W32_COLOR_LIGHT_MAGENTA ( FOREGROUND_INTENSITY | W32_COLOR_MAGENTA ) #define W32_COLOR_LIGHT_YELLOW ( FOREGROUND_INTENSITY | W32_COLOR_YELLOW ) #define W32_COLOR_WHITE ( FOREGROUND_INTENSITY | W32_COLOR_LIGHT_GREY ) static WORD W32_COLOR( short herc_color ) { switch ( herc_color ) { case COLOR_BLACK: return W32_COLOR_BLACK; case COLOR_RED: return W32_COLOR_RED; case COLOR_GREEN: return W32_COLOR_GREEN; case COLOR_BLUE: return W32_COLOR_BLUE; case COLOR_CYAN: return W32_COLOR_CYAN; case COLOR_MAGENTA: return W32_COLOR_MAGENTA; case COLOR_YELLOW: return W32_COLOR_YELLOW; case COLOR_DARK_GREY: return W32_COLOR_DARK_GREY; case COLOR_LIGHT_GREY: return W32_COLOR_LIGHT_GREY; case COLOR_LIGHT_RED: return W32_COLOR_LIGHT_RED; case COLOR_LIGHT_GREEN: return W32_COLOR_LIGHT_GREEN; case COLOR_LIGHT_BLUE: return W32_COLOR_LIGHT_BLUE; case COLOR_LIGHT_CYAN: return W32_COLOR_LIGHT_CYAN; case COLOR_LIGHT_MAGENTA: return W32_COLOR_LIGHT_MAGENTA; case COLOR_LIGHT_YELLOW: return W32_COLOR_LIGHT_YELLOW; case COLOR_WHITE: return W32_COLOR_WHITE; case COLOR_DEFAULT_BG: return default_BG_color(); case COLOR_DEFAULT_FG: return default_FG_color(); case COLOR_DEFAULT_LIGHT: return default_FG_color() | FOREGROUND_INTENSITY; default: return default_FG_color(); } } ////////////////////////////////////////////////////////////////////////////////////////// int set_screen_color ( FILE* confp, short herc_fore, short herc_back ) { HANDLE hStdErr; WORD wColor; int cons_fd; if ( !confp ) { errno = EINVAL; return -1; } if ( ! _isatty( cons_fd = fileno( confp ) ) ) { errno = EBADF; return -1; } hStdErr = (HANDLE) _get_osfhandle( cons_fd ); ASSERT( hStdErr && INVALID_HANDLE_VALUE != hStdErr ); wColor = 0 | W32_FOREGROUND_COLOR( W32_COLOR( herc_fore ) ) | W32_BACKGROUND_COLOR( W32_COLOR( herc_back ) ) ; VERIFY( SetConsoleTextAttribute( hStdErr, wColor ) ); return 0; } ////////////////////////////////////////////////////////////////////////////////////////// // screen positions are 1-based; row 1 == top line; col 1 == leftmost column int set_screen_pos( FILE* confp, short rowY1, short colX1 ) { CONSOLE_SCREEN_BUFFER_INFO csbi; HANDLE hStdErr; COORD ptConsole; int cons_fd; if ( !confp ) { errno = EINVAL; return -1; } if ( ! _isatty( cons_fd = fileno( confp ) ) ) { errno = EBADF; return -1; } hStdErr = (HANDLE) _get_osfhandle( cons_fd ); ASSERT( hStdErr && INVALID_HANDLE_VALUE != hStdErr ); VERIFY( GetConsoleScreenBufferInfo( hStdErr, &csbi ) ); // Note: ANSI escape codes are 1-based, whereas // SetConsoleCursorPosition values are 0-based... if (0 || colX1 < 1 || colX1 > csbi.dwSize.X || rowY1 < 1 || rowY1 > csbi.dwSize.Y ) { errno = EINVAL; return -1; } ptConsole.X = colX1 - 1; ptConsole.Y = rowY1 - 1; VERIFY( SetConsoleCursorPosition( hStdErr, ptConsole ) ); return 0; } ////////////////////////////////////////////////////////////////////////////////////////// // (From KB article 99261) int clear_screen( FILE* confp ) { CONSOLE_SCREEN_BUFFER_INFO csbi; HANDLE hStdErr; DWORD dwNumCells, dwCellsWritten; COORD ptConsole = { 0, 0 }; int cons_fd; if ( !confp ) { errno = EINVAL; return -1; } if ( ! _isatty( cons_fd = fileno( confp ) ) ) { errno = EBADF; return -1; } hStdErr = (HANDLE) _get_osfhandle( cons_fd ); ASSERT( hStdErr && INVALID_HANDLE_VALUE != hStdErr ); VERIFY( GetConsoleScreenBufferInfo( hStdErr, &csbi ) ); dwNumCells = csbi.dwSize.X * csbi.dwSize.Y; VERIFY( FillConsoleOutputCharacter( hStdErr, ' ', dwNumCells, ptConsole, &dwCellsWritten ) ); VERIFY( GetConsoleScreenBufferInfo( hStdErr, &csbi ) ); VERIFY( FillConsoleOutputAttribute( hStdErr, csbi.wAttributes, dwNumCells, ptConsole, &dwCellsWritten ) ); VERIFY( SetConsoleCursorPosition ( hStdErr, ptConsole ) ); return 0; } ////////////////////////////////////////////////////////////////////////////////////////// int erase_to_eol( FILE* confp ) { CONSOLE_SCREEN_BUFFER_INFO csbi; HANDLE hStdErr; DWORD dwCellsWritten; COORD ptConsole; int cons_fd; if ( !confp ) { errno = EINVAL; return -1; } if ( ! _isatty( cons_fd = fileno( confp ) ) ) { errno = EBADF; return -1; } hStdErr = (HANDLE) _get_osfhandle( cons_fd ); ASSERT( hStdErr && INVALID_HANDLE_VALUE != hStdErr ); VERIFY( GetConsoleScreenBufferInfo( hStdErr, &csbi ) ); ptConsole = csbi.dwCursorPosition; VERIFY( FillConsoleOutputAttribute( hStdErr, csbi.wAttributes, csbi.dwSize.X - ptConsole.X, ptConsole, &dwCellsWritten ) ); VERIFY( FillConsoleOutputCharacter( hStdErr, ' ', csbi.dwSize.X - ptConsole.X, ptConsole, &dwCellsWritten ) ); return 0; } ////////////////////////////////////////////////////////////////////////////////////////// // Handles key presses that result in TWO characters being generated... void translate_keystroke( char kbbuf[], int* pkblen ) { BYTE ch = kbbuf[0]; // (move char to work var) switch ( ch ) // Check if special key pressed... { case 0x0D: // enter key kbbuf[0] = '\n'; // change to newline character // fall thru to default case default: // no further translation needed break; // accept the keystroke as-is // translate special key (escape sequence)... case 0x00: // 1st char of special key press case 0xE0: // 1st char of special key press { BYTE orig_ch, ch2; if ( !kbhit() ) // if not two chars generated, break; // then not special key press orig_ch = ch; // save original keystroke ch = '\x1B'; // change it to an escape char ch2 = getch(); // get second keystroke of pair switch ( ch2 ) // generate ANSI escape sequence { case 0x47: strcpy( kbbuf, KBD_HOME ); break; case 0x52: strcpy( kbbuf, KBD_INSERT ); break; case 0x53: strcpy( kbbuf, KBD_DELETE ); break; case 0x4F: strcpy( kbbuf, KBD_END ); break; case 0x49: strcpy( kbbuf, KBD_PAGE_UP ); break; case 0x51: strcpy( kbbuf, KBD_PAGE_DOWN ); break; case 0x48: strcpy( kbbuf, KBD_UP_ARROW ); break; case 0x50: strcpy( kbbuf, KBD_DOWN_ARROW ); break; case 0x4D: strcpy( kbbuf, KBD_RIGHT_ARROW ); break; case 0x4B: strcpy( kbbuf, KBD_LEFT_ARROW ); break; case 0x77: strcpy( kbbuf, KBD_CTRL_HOME ); break; case 0x75: strcpy( kbbuf, KBD_CTRL_END ); break; case 0x8D: strcpy( kbbuf, KBD_CTRL_UP_ARROW ); break; case 0x91: strcpy( kbbuf, KBD_CTRL_DOWN_ARROW ); break; case 0x98: strcpy( kbbuf, KBD_ALT_UP_ARROW ); break; case 0xA0: strcpy( kbbuf, KBD_ALT_DOWN_ARROW ); break; case 0x9D: strcpy( kbbuf, KBD_ALT_RIGHT_ARROW ); break; case 0x9B: strcpy( kbbuf, KBD_ALT_LEFT_ARROW ); break; default: { #if 0 kbbuf[0] = '\x1B'; kbbuf[1] = ch2; kbbuf[2] = 0; #else /* EAT IT */ kbbuf[0] = 0; kbbuf[1] = 0; kbbuf[2] = 0; #endif break; } // end default } // end switch( ch2 ) *pkblen = strlen( kbbuf ); // inform caller #of chars break; } // end case: 0x00, 0xE0 } // end switch( ch ) } ////////////////////////////////////////////////////////////////////////////////////////// int console_beep( FILE* confp ) { int cons_fd; if ( !confp ) { errno = EINVAL; return -1; } if ( ! _isatty( cons_fd = fileno( confp ) ) ) { errno = EBADF; return -1; } MessageBeep(-1); return 0; } ////////////////////////////////////////////////////////////////////////////////////////// #ifdef OPTION_EXTCURS int get_cursor_pos( int keybrd_fd, FILE* confp, short* row, short* col ) { CONSOLE_SCREEN_BUFFER_INFO csbi; HANDLE hStdErr; int cons_fd; UNREFERENCED( keybrd_fd ); if ( !confp || !row || !col ) { errno = EINVAL; return -1; } if ( ! _isatty( cons_fd = fileno( confp ) ) ) { errno = EBADF; return -1; } hStdErr = (HANDLE) _get_osfhandle( cons_fd ); ASSERT( hStdErr && INVALID_HANDLE_VALUE != hStdErr ); if ( !GetConsoleScreenBufferInfo( hStdErr, &csbi ) ) { errno = EIO; return -1; } *row = 1 + csbi.dwCursorPosition.Y; *col = 1 + csbi.dwCursorPosition.X; return 0; } #endif // OPTION_EXTCURS ////////////////////////////////////////////////////////////////////////////////////////// int get_console_dim( FILE* confp, int* rows, int* cols ) { CONSOLE_SCREEN_BUFFER_INFO csbi; HANDLE hStdErr; int cons_fd; if ( !confp || !rows || !cols ) { errno = EINVAL; return -1; } *rows = *cols = 0; if ( ! _isatty( cons_fd = fileno( confp ) ) ) { errno = EBADF; return -1; } hStdErr = (HANDLE) _get_osfhandle( cons_fd ); ASSERT( hStdErr && INVALID_HANDLE_VALUE != hStdErr ); if ( !GetConsoleScreenBufferInfo( hStdErr, &csbi ) ) { errno = EIO; return -1; } *rows = 1 + csbi.srWindow.Bottom - csbi.srWindow.Top; *cols = 1 + csbi.srWindow.Right - csbi.srWindow.Left; return 0; } ////////////////////////////////////////////////////////////////////////////////////////// int set_console_cursor_shape( FILE* confp, int ins ) { CONSOLE_CURSOR_INFO ci; HANDLE hStdErr; int cons_fd; if ( !confp ) { errno = EINVAL; return -1; } if ( ! _isatty( cons_fd = fileno( confp ) ) ) { errno = EBADF; return -1; } hStdErr = (HANDLE) _get_osfhandle( cons_fd ); ASSERT( hStdErr && INVALID_HANDLE_VALUE != hStdErr ); ci.bVisible = TRUE; ci.dwSize = ins ? 20 : 100; // (note: values are percent of cell height) if ( !SetConsoleCursorInfo( hStdErr, &ci ) ) { errno = EIO; return -1; } return 0; } ////////////////////////////////////////////////////////////////////////////////////////// // From KB article 124103: "How To Obtain a Console Window Handle (HWND)" // http://support.microsoft.com/?kbid=124103 #define MAX_WINDOW_TITLE_LEN (256) // (purely arbitrary) static TCHAR g_szOriginalTitle[ MAX_WINDOW_TITLE_LEN ] = {0}; int w32_set_console_title( char* pszTitle ) { TCHAR szNewTitleBuff [ MAX_WINDOW_TITLE_LEN ]; LPCTSTR pszNewTitle = NULL; if (!g_szOriginalTitle[0]) VERIFY(GetConsoleTitle( g_szOriginalTitle, MAX_WINDOW_TITLE_LEN )); if (pszTitle) { _sntprintf( szNewTitleBuff, MAX_WINDOW_TITLE_LEN-1, _T("%hs"), pszTitle ); szNewTitleBuff[MAX_WINDOW_TITLE_LEN-1]=0; pszNewTitle = szNewTitleBuff; } else pszNewTitle = g_szOriginalTitle; if (!SetConsoleTitle( pszNewTitle )) { errno = GetLastError(); return -1; } return 0; } ////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// #else // !defined( WIN32 ) #ifdef HAVE_TERMIOS_H static struct termios saved_kbattr; // (saved value so we can later restore it) #endif // 'save_and_set' = 1 --> just what it says; 0 --> restore from saved value. int set_or_reset_console_mode( int keybrd_fd, short save_and_set ) { #ifdef HAVE_TERMIOS_H struct termios kbattr; if ( save_and_set ) { // Put the terminal into cbreak mode tcgetattr( keybrd_fd, &saved_kbattr ); // (save for later restore) kbattr = saved_kbattr; // (make copy) kbattr.c_lflag &= ~(ECHO | ICANON); // (set desired values...) kbattr.c_cc[VMIN] = 0; kbattr.c_cc[VTIME] = 0; tcsetattr( keybrd_fd, TCSANOW, &kbattr ); } else { // Restore the terminal mode tcsetattr( STDIN_FILENO, TCSANOW, &saved_kbattr ); // (restore prev value) } #else UNREFERENCED( keybrd_fd ); UNREFERENCED( save_and_set ); #endif return 0; } ////////////////////////////////////////////////////////////////////////////////////////// // screen positions are 1-based; row 1 == top line; col 1 == leftmost column int set_screen_pos( FILE* confp, short rowY1, short colX1 ) { #define ANSI_POSITION_CURSOR "\x1B[%d;%dH" return ( fprintf( confp, ANSI_POSITION_CURSOR, rowY1, colX1 ) ? 0 : -1 ); } ////////////////////////////////////////////////////////////////////////////////////////// int erase_to_eol( FILE* confp ) { #define ANSI_ERASE_EOL "\x1B[K" return ( fprintf( confp, ANSI_ERASE_EOL ) ? 0 : -1 ); } ////////////////////////////////////////////////////////////////////////////////////////// int clear_screen( FILE* confp ) { #define ANSI_ERASE_SCREEN "\x1B[2J" return ( fprintf( confp, ANSI_ERASE_SCREEN ) ? 0 : -1 ); } ////////////////////////////////////////////////////////////////////////////////////////// /* From: (http://www.vtt.fi/tte/EuroBridge/Xew/iso6429.html) CSI (Control Sequence Introducer) = "\033[" or "\233" SGR (Select Graphic Rendition) = CSI Ps1;Ps2;... m SGR (Select Graphic Rendition): CSI Ps ... 0x6d (Note: 0x6d = ASCII 'm') SGR is used to establish one or more graphic rendition aspects for subsequent text. The established aspects remain in effect until the next occurrence of SGR in the data stream, depending on the setting of the GRAPHIC RENDITION COMBINATION MODE (GRCM). The implementation assumes the GRCM = CUMULATIVE (that is, each aspect will be in effect until explicitly cancelled by another SGR). -------------------------------------------------------------------------- Ps Description -------------------------------------------------------------------------- 0 default rendition; cancel all preceding occurrences of SGR; invoke primary font. 1 bold or increased intensity 2 faint <------<<< Fish: non-standard, but apparently anyway (based on other documents I've seen) 3 italicized 4 underlined 7 negative image 9 crossed out 10 primary (default) font 11-19 first to ninth alternative fonts (see also fonts) 21 doubly underlined 22 normal intensity (neither bold nor faint) 23 not italicized 24 not underlined (neither singly or doubly) 27 positive image 29 not crossed out 30-37 foreground color of the text; 30=black, 31=red, 32=green, 33=yellow, 34=blue, 35=magenta, 36=cyan, 37=white. 39 default foreground text color (foreground color of the widget) 40-47 background color of the text; 40=black, 41=red, 42=green, 43=yellow, 44=blue, 45=magenta, 46=cyan, 47=white. 49 default background text color (background color of the widget) 51 framed (see FrameRendition) 53 overlined [not implemented yet] 54 not framed, not encircled 55 not overlined [not implemented yet] -------------------------------------------------------------------------- "\033[m" Reset "\033[0m" Reset "\033[1m" Bold "\033[2m" Faint <------<<< Fish: non-standard, but apparently anyway (based on other documents I've seen) "\033[3m" Italic "\033[4m" Underline "\033[7m" Inverse "\033[9m" Crossed out "\033[10m" primary font "\033[11m" 1st alternate font "\033[12m" 2nd alternate font "\033[13m" 3rd alternate font "\033[14m" 4th alternate font "\033[15m" 5th alternate font "\033[16m" 6th alternate font "\033[17m" 7th alternate font "\033[18m" 8th alternate font "\033[19m" 9th alternate font "\033[21m" Double underline "\033[22m" Bold off "\033[23m" Italic off "\033[24m" Underline off (double or single) "\033[27m" Inverse off "\033[29m" Crossed out off "\033[30m" Black foreground "\033[31m" Red foreground "\033[32m" Green foreground "\033[33m" Yellow foreground "\033[34m" Blue foreground "\033[35m" Magenta foreground "\033[36m" Cyan foreground "\033[37m" White foreground "\033[39m" Default foreground "\033[40m" Black background "\033[41m" Red background "\033[42m" Green background "\033[43m" Yellow background "\033[44m" Blue background "\033[45m" Magenta background "\033[46m" Cyan background "\033[47m" White background "\033[49m" Default background "\033[51m" Framed on "\033[54m" Framed off */ ////////////////////////////////////////////////////////////////////////////////////////// // Translate Herc color to ANSI/ISO-6429 (ECMA-48) color... // High-order byte is attribute (0=normal, 1=bold), low-order byte is color. #define ISO_COLOR_BLACK ( 30 ) #define ISO_COLOR_RED ( 31 ) #define ISO_COLOR_GREEN ( 32 ) #define ISO_COLOR_YELLOW ( 33 ) #define ISO_COLOR_BLUE ( 34 ) #define ISO_COLOR_MAGENTA ( 35 ) #define ISO_COLOR_CYAN ( 36 ) #define ISO_COLOR_WHITE ( 37 ) #define ISO_COLOR_DEFAULT ( 39 ) #define ISO_NORMAL( iso_color ) ( ( 0x0000 ) | ( (uint16_t)( iso_color ) ) ) #define ISO_BRIGHT( iso_color ) ( ( 0x0100 ) | ( (uint16_t)( iso_color ) ) ) #define ISO_IS_ISO_BRIGHT( iso_color ) ( ( ( iso_color ) >> 8 ) & 0x01 ) // PROGRAMMING NOTE: the '2' (faint/dim) and '22' (bold-off) // attribute codes are UNRELIABLE. They are apparently rarely // implemented properly on many platforms (Cygwin included). // Thus we prefer to use the more reliable (but programmatically // bothersome) '0' (reset) attribute instead [whenever we wish // to paint a 'dim/faint' (non-bold) color]. As a result however, // we need to be careful to paint the foregoround/background // colors in the proper sequence/order and in the proper manner. // See the below 'set_screen_color' function for details. (Fish) //#define ISO_NORMAL_OR_BRIGHT( iso_color ) ISO_IS_ISO_BRIGHT( iso_color ) ? 1 : 22 //#define ISO_NORMAL_OR_BRIGHT( iso_color ) ISO_IS_ISO_BRIGHT( iso_color ) ? 1 : 2 #define ISO_NORMAL_OR_BRIGHT( iso_color ) ISO_IS_ISO_BRIGHT( iso_color ) ? 1 : 0 #define ISO_FOREGROUND_COLOR( iso_color ) ( ( ( iso_color ) & 0x00FF ) ) #define ISO_BACKGROUND_COLOR( iso_color ) ( ( ( iso_color ) & 0x00FF ) + 10 ) static uint16_t ISO_COLOR( short herc_color ) { switch ( herc_color ) { case COLOR_BLACK: return ISO_NORMAL( ISO_COLOR_BLACK ); case COLOR_RED: return ISO_NORMAL( ISO_COLOR_RED ); case COLOR_GREEN: return ISO_NORMAL( ISO_COLOR_GREEN ); case COLOR_BLUE: return ISO_NORMAL( ISO_COLOR_BLUE ); case COLOR_CYAN: return ISO_NORMAL( ISO_COLOR_CYAN ); case COLOR_MAGENTA: return ISO_NORMAL( ISO_COLOR_MAGENTA ); case COLOR_YELLOW: return ISO_NORMAL( ISO_COLOR_YELLOW ); case COLOR_DARK_GREY: return ISO_BRIGHT( ISO_COLOR_BLACK ); case COLOR_LIGHT_GREY: return ISO_NORMAL( ISO_COLOR_WHITE ); case COLOR_LIGHT_RED: return ISO_BRIGHT( ISO_COLOR_RED ); case COLOR_LIGHT_GREEN: return ISO_BRIGHT( ISO_COLOR_GREEN ); case COLOR_LIGHT_BLUE: return ISO_BRIGHT( ISO_COLOR_BLUE ); case COLOR_LIGHT_CYAN: return ISO_BRIGHT( ISO_COLOR_CYAN ); case COLOR_LIGHT_MAGENTA: return ISO_BRIGHT( ISO_COLOR_MAGENTA ); case COLOR_LIGHT_YELLOW: return ISO_BRIGHT( ISO_COLOR_YELLOW ); case COLOR_WHITE: return ISO_BRIGHT( ISO_COLOR_WHITE ); case COLOR_DEFAULT_FG: return ISO_NORMAL( ISO_COLOR_DEFAULT ); case COLOR_DEFAULT_BG: return ISO_NORMAL( ISO_COLOR_DEFAULT ); case COLOR_DEFAULT_LIGHT: return ISO_BRIGHT( ISO_COLOR_DEFAULT ); default: return ISO_NORMAL( ISO_COLOR_DEFAULT ); } } ////////////////////////////////////////////////////////////////////////////////////////// // Translate Herc color to ANSI/ISO-6429 (ECMA-48) SGR terminal escape sequence... int set_screen_color( FILE* confp, short herc_fore, short herc_back ) { uint16_t iso_fore, iso_back; uint16_t iso_bold_color, iso_dim_color; int rc; // Translate Herc color to ANSI (ISO) color... iso_fore = ISO_COLOR( herc_fore ); iso_back = ISO_COLOR( herc_back ); // PROGRAMMING NOTE: Because the only means we have to RELIABLY // set non-bold (faint/dim) color attributes across ALL platforms // is to use the '0' (reset) escape code (which of course has the // unfortunate(?) side-effect of resetting BOTH the background // AND foreground colors to dim/faint instead of just one or the // other), we need to be careful to always set the dim (NON-bold) // color attribute FIRST (which will of course reset both the fore- // ground AND the backgound colors to non-bold/faint/dim as well), // and then to, AFTERWARDS, set the BOLD color attribute. This is // the ONLY way I've been able to discover (empirically via trial // and error) how to RELIABLY set bold/faint foreground/background // color attributes across all(?) supported platforms. (Fish) if ( ISO_IS_ISO_BRIGHT(iso_fore) == ISO_IS_ISO_BRIGHT(iso_back) ) { // BOTH the foreground color AND the background colors // are either BOTH bold or BOTH dim/faint (normal)... rc = fprintf ( confp, // Set the bold/dim attribute FIRST and then // BOTH foreground/background colors afterwards... "\x1B[%d;%d;%dm" ,ISO_NORMAL_OR_BRIGHT( iso_back ) ,ISO_BACKGROUND_COLOR( iso_back ) ,ISO_FOREGROUND_COLOR( iso_fore ) ); } else // ( ISO_IS_ISO_BRIGHT(iso_fore) != ISO_IS_ISO_BRIGHT(iso_back) ) { // ONE of either the foreground OR background colors // is bold, but the OTHER one is dim/faint (normal)... if ( ISO_IS_ISO_BRIGHT(iso_fore) ) { // The foregound color is the bright/bold one... iso_bold_color = ISO_FOREGROUND_COLOR( iso_fore ); iso_dim_color = ISO_BACKGROUND_COLOR( iso_back ); } else // ( !ISO_IS_ISO_BRIGHT(iso_fore) ) { // The background color is the bright/bold one... iso_bold_color = ISO_BACKGROUND_COLOR( iso_back ); iso_dim_color = ISO_FOREGROUND_COLOR( iso_fore ); } // Set whichever is the DIM color attribute FIRST // and then AFTERWARDS whichever one is the BOLD... rc = fprintf ( confp, "\x1B[0;%d;1;%dm" // (reset, dim-color, bold, bold-color) ,iso_dim_color ,iso_bold_color ); } return rc < 0 ? -1 : 0; } ////////////////////////////////////////////////////////////////////////////////////////// void translate_keystroke( char kbbuf[], int* pkblen ) { UNREFERENCED( kbbuf ); UNREFERENCED( pkblen ); return; } ////////////////////////////////////////////////////////////////////////////////////////// int console_beep( FILE* confp ) { return fprintf( confp, "\a" ) < 0 ? -1 : 0; } ////////////////////////////////////////////////////////////////////////////////////////// int get_console_dim( FILE* confp, int* rows, int* cols ) { char* env; #if defined(TIOCGWINSZ) struct winsize winsize; #else UNREFERENCED( confp ); #endif if ( !rows || !cols ) { errno = EINVAL; return -1; } #if defined(TIOCGWINSZ) if (ioctl(fileno(confp), TIOCGWINSZ, &winsize) >= 0) { *rows = winsize.ws_row; *cols = winsize.ws_col; } else #endif { if (!(env = getenv( "LINES" ))) *rows = 24; else *rows = atoi(env); if (!(env = getenv( "COLUMNS" ))) *cols = 80; else *cols = atoi(env); } if (!*rows || !*cols) { errno = EIO; return -1; } return 0; } ////////////////////////////////////////////////////////////////////////////////////////// #ifdef OPTION_EXTCURS int get_cursor_pos( int keybrd_fd, FILE* confp, short* row, short* col ) { struct timeval tv; /* Select timeout structure */ fd_set readset; /* Select file descriptors */ char kbbuf[16]; /* Keyboard i/p buffer */ char* semi; /* Index of semicolon */ int kblen; /* Number of chars in kbbuf */ int maxfd; /* Highest file descriptor */ int rc; /* Return code */ char c; /* Work for scanf */ /* Request the CPR (Cursor Position Report) */ if ( fprintf( confp, KBD_ASK_CURSOR_POS ) < 0 ) return -1; /* Read the CPR from the keyboard i/p buffer */ while (1) { FD_ZERO (&readset); FD_SET (keybrd_fd, &readset); maxfd = keybrd_fd; tv.tv_sec = 0; tv.tv_usec = 50 * 1000; // (PLENTY long enough!) /* Wait for CPR to arrive in our i/p buffer */ rc = select (maxfd + 1, &readset, NULL, NULL, &tv); if (rc < 0 ) { if (errno == EINTR) continue; errno = EIO; break; } /* If keyboard input has arrived then process it */ if (!FD_ISSET(keybrd_fd, &readset)) continue; /* Read character(s) from the keyboard */ kblen = read (keybrd_fd, kbbuf, sizeof(kbbuf)-1); if (kblen < 0) { errno = EIO; break; } kbbuf[kblen] = 0; // The returned CPR is the string "\x1B[n;mR" // where n = decimal row, m = decimal column. // Note: we expect the entire the CPR to have // been read on our first i/o (i.e. for it to // have arrived all at once in one piece) and // not piecemeal requiring several i/o's... if (0 || kblen < 6 || kbbuf[ 0 ] != '\x1B' || kbbuf[ 1 ] != '[' || kbbuf[kblen-1] != 'R' || (semi = memchr( kbbuf, ';', kblen )) == NULL || (semi - kbbuf) < 3 || sscanf( &kbbuf[2], "%hu%c", row, &c ) != 2 || c != ';' || sscanf( semi+1, "%hu%c", col, &c ) != 2 || c != 'R' ) { errno = EIO; rc = -1; break; } /* Success! */ rc = 0; break } return rc; } #endif // OPTION_EXTCURS ////////////////////////////////////////////////////////////////////////////////////////// /* From: (http://groups-beta.google.com/group/comp.protocols.kermit.misc/msg/1cc3ec6f0bfc0084) VGA-softcursor.txt, from the 2.2 kernel Software cursor for VGA by Pavel Machek ======================= and Martin Mares Linux now has some ability to manipulate cursor appearance. Normally, you can set the size of hardware cursor (and also work around some ugly bugs in those miserable Trident cards--see #define TRIDENT_GLITCH in drivers/video/ vgacon.c). You can now play a few new tricks: you can make your cursor look like a non-blinking red block, make it inverse background of the character it's over or to highlight that character and still choose whether the original hardware cursor should remain visible or not. There may be other things I have never thought of. The cursor appearance is controlled by a "[?1;2;3c" escape sequence where 1, 2 and 3 are parameters described below. If you omit any of them, they will default to zeroes. Parameter 1 specifies cursor size (0=default, 1=invisible, 2=underline, ..., 8=full block) + 16 if you want the software cursor to be applied + 32 if you want to always change the background color + 64 if you dislike having the background the same as the foreground. Highlights are ignored for the last two flags. The second parameter selects character attribute bits you want to change (by simply XORing them with the value of this parameter). On standard VGA, the high four bits specify background and the low four the foreground. In both groups, low three bits set color (as in normal color codes used by the console) and the most significant one turns on highlight (or sometimes blinking--it depends on the configuration of your VGA). The third parameter consists of character attribute bits you want to set. Bit setting takes place before bit toggling, so you can simply clear a bit by including it in both the set mask and the toggle mask. Examples: ========= To get normal blinking underline, use: echo -e '\033[?2c' To get blinking block, use: echo -e '\033[?6c' To get red non-blinking block, use: echo -e '\033[?17;0;64c' */ int set_console_cursor_shape( FILE* confp, int ins ) { #if SET_CONSOLE_CURSOR_SHAPE_METHOD == CURSOR_SHAPE_NOT_SUPPORTED UNREFERENCED( confp ); UNREFERENCED( ins ); return 0; #elif SET_CONSOLE_CURSOR_SHAPE_METHOD == CURSOR_SHAPE_VIA_SPECIAL_LINUX_ESCAPE #define LINUX_UNDER_BLINK_CURSOR "\x1B[?2c" #define LINUX_BLINK_BLOCK_CURSOR "\x1B[?6c" return fprintf( confp, ins ? LINUX_UNDER_BLINK_CURSOR : LINUX_BLINK_BLOCK_CURSOR ); #else #error Invalid #defined SET_CONSOLE_CURSOR_SHAPE_METHOD value return -1; #endif } ////////////////////////////////////////////////////////////////////////////////////////// #endif // defined( WIN32 ) ////////////////////////////////////////////////////////////////////////////////////////// hercules-3.07/hconsole.h000644 000765 000765 00000012521 11143760542 016732 0ustar00jmaynardjmaynard000000 000000 ////////////////////////////////////////////////////////////////////////////////////////// // hconsole.h Hercules hardware console (panel) support functions ////////////////////////////////////////////////////////////////////////////////////////// // (c) Copyright "Fish" (David B. Trout), 2009. Released under the Q Public License // (http://www.hercules-390.org/herclic.html) as modifications to Hercules. ////////////////////////////////////////////////////////////////////////////////////////// // $Id: hconsole.h 5125 2009-01-23 12:01:44Z bernard $ // // $Log$ // Revision 1.13 2008/09/02 06:08:09 fish // ALT_RIGHTARROW and ALT_LEFTARROW // // Revision 1.12 2008/08/29 10:22:08 fish // Lay groundwork for eventual extended cursor handling // // Revision 1.11 2008/07/10 18:31:33 fish // 1) Add support for Ctrl+Home and Ctrl+End extended control sequences, and // 2) ignore other unsupported extended control sequences. // // Revision 1.10 2008/07/08 13:48:40 fish // Ctrl + uparrow / downarrow ==> scroll up/down one line // // Revision 1.9 2007/11/30 14:54:32 jmaynard // Changed conmicro.cx to hercules-390.org or conmicro.com, as needed. // // Revision 1.8 2007/06/23 00:04:10 ivan // Update copyright notices to include current year (2007) // // Revision 1.7 2006/12/08 09:43:25 jj // Add CVS message log // #ifndef _HCONSOLE_H #define _HCONSOLE_H //----------------------------------------------------------------------------- // // VT100 User Guide // // Table 3-6 Cursor Control Key Codes // // Cursor Key VT52 ANSI and Cursor Key Mode ANSI and Cursor Key Mode // (Arrow) Mode Reset (Normal mode) Set (Application mode) // // Up ESC A ESC [ A ESC O A // Down ESC B ESC [ B ESC O B // Right ESC C ESC [ C ESC O C // Left ESC D ESC [ D ESC O D // //----------------------------------------------------------------------------- #define ANSI_RESET_ALL_ATTRIBUTES "\x1B[0m" #define KBD_HOME "\x1B[1~" #define KBD_INSERT "\x1B[2~" #define KBD_DELETE "\x1B[3~" #define KBD_END "\x1B[4~" #define KBD_PAGE_UP "\x1B[5~" #define KBD_PAGE_DOWN "\x1B[6~" #define KBD_UP_ARROW "\x1B[A" #define KBD_DOWN_ARROW "\x1B[B" #define KBD_RIGHT_ARROW "\x1B[C" #define KBD_LEFT_ARROW "\x1B[D" #define KBD_UP_ARROW2 "\x1BOA" #define KBD_DOWN_ARROW2 "\x1BOB" #define KBD_RIGHT_ARROW2 "\x1BOC" #define KBD_LEFT_ARROW2 "\x1BOD" // Does anyone know what the actual escape sequence that // gets generated actually is on Linux for "Alt+UpArrow" // and "Alt+DownArrow", etc?? Thanks! -- Fish #define KBD_ALT_UP_ARROW KBD_UP_ARROW2 #define KBD_ALT_DOWN_ARROW KBD_DOWN_ARROW2 #define KBD_ALT_RIGHT_ARROW KBD_RIGHT_ARROW2 #define KBD_ALT_LEFT_ARROW KBD_LEFT_ARROW2 #define KBD_CTRL_HOME "\x1B""w" // (is this right??) #define KBD_CTRL_END "\x1B""u" // (is this right??) #define KBD_CTRL_UP_ARROW "\x1B""D" // (is this right??) #define KBD_CTRL_DOWN_ARROW "\x1B""M" // (is this right??) //efine KBD_CTRL_RIGHT_ARROW "???????" // (luckily we don't need it right now) //efine KBD_CTRL_LEFT_ARROW "???????" // (luckily we don't need it right now) #define KBD_ASK_CURSOR_POS "\x1B[6n" // Return value is the string "\x1B[n;mR" // returned in the keyboard buffer where // n = decimal row, m = decimal column. // Hercules console color codes... #define COLOR_BLACK 0 #define COLOR_RED 1 #define COLOR_GREEN 2 #define COLOR_BLUE 3 #define COLOR_CYAN 4 #define COLOR_MAGENTA 5 #define COLOR_YELLOW 6 #define COLOR_DARK_GREY 7 #define COLOR_LIGHT_GREY 8 #define COLOR_LIGHT_RED 9 #define COLOR_LIGHT_GREEN 10 #define COLOR_LIGHT_BLUE 11 #define COLOR_LIGHT_CYAN 12 #define COLOR_LIGHT_MAGENTA 13 #define COLOR_LIGHT_YELLOW 14 #define COLOR_WHITE 15 #define COLOR_DEFAULT_FG 16 #define COLOR_DEFAULT_BG 17 #define COLOR_DEFAULT_LIGHT 18 extern int set_screen_color ( FILE* confp, short herc_fore, short herc_back ); // screen positions are 1-based; row 1 == top line; col 1 == leftmost column extern int set_screen_pos ( FILE* confp, short rowY1, short colX1 ); extern int clear_screen ( FILE* confp ); extern int erase_to_eol ( FILE* confp ); // 'save_and_set' = 1 --> just what it says; 0 --> restore from saved value. extern int set_or_reset_console_mode ( int keybrd_fd, short save_and_set ); extern void translate_keystroke( char kbbuf[], int* pkblen ); extern int console_beep( FILE* confp ); extern int get_console_dim( FILE* confp, int* rows, int* cols ); #ifdef OPTION_EXTCURS extern int get_cursor_pos( int keybrd_fd, FILE* confp, short* row, short* col ); #endif // OPTION_EXTCURS extern int set_console_cursor_shape( FILE* confp, int ins ); #if defined( _MSVC_ ) extern int w32_set_console_title( char* pszTitle ); #endif #endif // _HCONSOLE_H hercules-3.07/hconsts.h000644 000765 000765 00000026546 11321734033 016607 0ustar00jmaynardjmaynard000000 000000 /*-------------------------------------------------------------------*/ /* HCONSTS.H Hercules #define constants... */ /*-------------------------------------------------------------------*/ // This header auto-#included by 'hercules.h'... // // The header and other required headers are // presumed to have already been #included ahead of it... // $Id: hconsts.h 5522 2009-12-11 15:25:15Z bernard $ #ifndef _HCONSTS_H #define _HCONSTS_H #include "hercules.h" /*-------------------------------------------------------------------*/ /* Miscellaneous system related constants we could be missing... */ /*-------------------------------------------------------------------*/ #ifndef MAX_PATH #ifdef PATH_MAX #define MAX_PATH PATH_MAX #else #define MAX_PATH 4096 #endif #endif #ifndef PATH_SEP #ifdef _MSVC_ #define PATH_SEP "\\" #else #define PATH_SEP "/" #endif #endif #if defined( _MSVC_ ) // The following are missing from MINGW32/MSVC... #ifndef S_IRGRP #define S_IRGRP 0 #endif #ifndef S_IWGRP #define S_IWGRP 0 #endif #ifndef SIGUSR2 // (needs defined for OPTION_WAKEUP_SELECT_VIA_PIPE) #define SIGUSR2 31 // (the value's unimportant, but we'll be accurate) #endif #ifndef IFNAMSIZ #define IFNAMSIZ 16 #endif #ifndef IFHWADDRLEN #define IFHWADDRLEN 6 #endif #ifndef EFAULT #if defined (WSAEFAULT) #define EFAULT WSAEFAULT #else #define EFAULT 14 #endif #endif #ifndef ENOSYS #if defined (WSASYSCALLFAILURE) #define ENOSYS WSASYSCALLFAILURE #else #define ENOSYS 88 #endif #endif #ifndef EOPNOTSUPP #if defined (WSAEOPNOTSUPP) #define EOPNOTSUPP WSAEOPNOTSUPP #else #define EOPNOTSUPP 95 #endif #endif #ifndef ECONNRESET #if defined (WSAECONNRESET) #define ECONNRESET WSAECONNRESET #else #define ECONNRESET 104 #endif #endif #ifndef ENOBUFS #if defined (ENOMEM) #define ENOBUFS ENOMEM #else #define ENOBUFS 105 #endif #endif #ifndef EAFNOSUPPORT #if defined (WSAEAFNOSUPPORT) #define EAFNOSUPPORT WSAEAFNOSUPPORT #else #define EAFNOSUPPORT 106 #endif #endif #ifndef EPROTOTYPE #if defined (WSAEPROTOTYPE) #define EPROTOTYPE WSAEPROTOTYPE #else #define EPROTOTYPE 107 #endif #endif #ifndef ENOTSOCK #if defined (WSAENOTSOCK) #define ENOTSOCK WSAENOTSOCK #else #define ENOTSOCK 108 #endif #endif #ifndef EADDRINUSE #if defined (WSAEADDRINUSE) #define EADDRINUSE WSAEADDRINUSE #else #define EADDRINUSE 112 #endif #endif #ifndef ENETDOWN #if defined (WSAENETDOWN) #define ENETDOWN WSAENETDOWN #else #define ENETDOWN 115 #endif #endif #ifndef ETIMEDOUT #if defined (WSAETIMEDOUT) #define ETIMEDOUT WSAETIMEDOUT #else #define ETIMEDOUT 116 #endif #endif #ifndef EINPROGRESS #if defined (WSAEINPROGRESS) #define EINPROGRESS WSAEINPROGRESS #else #define EINPROGRESS 119 #endif #endif #ifndef EMSGSIZE #if defined (E2BIG) #define EMSGSIZE E2BIG #else #define EMSGSIZE 122 #endif #endif #ifndef EPROTONOSUPPORT #if defined (WSAEPROTONOSUPPORT) #define EPROTONOSUPPORT WSAEPROTONOSUPPORT #else #define EPROTONOSUPPORT 123 #endif #endif #ifndef ENOTCONN #if defined (WSAENOTCONN) #define ENOTCONN WSAENOTCONN #else #define ENOTCONN 128 #endif #endif #ifndef ENOTSUP #if defined (ENOSYS) #define ENOTSUP ENOSYS #else #define ENOTSUP 134 #endif #endif #ifndef ENOMEDIUM #if defined (ENOENT) #define ENOMEDIUM ENOENT #else #define ENOMEDIUM 135 #endif #endif #ifndef EOVERFLOW #if defined (ERANGE) #define EOVERFLOW ERANGE #else #define EOVERFLOW 139 #endif #endif #endif // defined(_MSVC_) // CLK_TCK not part of SUSE 7.2 specs; added. (VB) #ifndef CLK_TCK #define CLK_TCK CLOCKS_PER_SEC #endif /*-------------------------------------------------------------------*/ /* Console tn3270/telnet session TCP "Keep-Alive" values... */ /*-------------------------------------------------------------------*/ #define KEEPALIVE_IDLE_TIME 3 /* Idle time to first probe */ #define KEEPALIVE_PROBE_INTERVAL 1 /* Probe timeout value */ #define KEEPALIVE_PROBE_COUNT 10 /* Max probe timeouts */ /*-------------------------------------------------------------------*/ /* Miscellaneous Hercules-related constants... */ /*-------------------------------------------------------------------*/ #define SPACE ' ' /* <---<<< Look close! There's a space there! */ /* Definitions for OS tailoring - msb eq mon event, lsb eq oper exc. */ #define OS_NONE 0x7FFFFFFFF7DE7FFFULL /* No spec OS tail. */ #define OS_OS390 0x7FF673FFF7DE7FFDULL /* OS/390 */ #define OS_ZOS 0x7B7673FFF7DE7FB7ULL /* z/OS */ #define OS_VSE 0x7FF673FFF7DE7FFFULL /* VSE */ #define OS_VM 0x7FFFFFFFF7DE7FFCULL /* VM */ #define OS_OPENSOLARIS 0xF8FFFFFFFFDE7FF7ULL /* OpenSolaris */ #if !defined(NO_IEEE_SUPPORT) #define OS_LINUX 0x78FFFFFFF7DE7FF7ULL /* Linux */ #else #define OS_LINUX 0x78FFFFFFF7DE7FD6ULL /* Linux */ #endif /* Definitions for program product OS restriction flag. This flag is ORed with the SCLP READ CPU INFO response code. A 4 here makes the CPU look like an IFL (Integrated Facility for Linux) engine, which cannot run licensed ESA/390 or z/Architecture OSes. */ #define PGM_PRD_OS_RESTRICTED 4 /* Restricted */ #define PGM_PRD_OS_LICENSED 0 /* Licensed */ /* Storage access bits used by logical_to_main */ #define ACC_CHECK 0x0001 /* Possible storage update*/ #define ACC_WRITE 0x0002 /* Storage update */ #define ACC_READ 0x0004 /* Storage read */ /* Storage access bits used by other dat.h routines */ #define ACC_NOTLB 0x0100 /* Don't do TLB lookup */ #define ACC_PTE 0x0200 /* Return page table entry*/ #define ACC_LPTEA 0x0400 /* Esame page table entry */ #define ACC_SPECIAL_ART 0x0800 /* Used by BSG */ #define ACCTYPE_HW 0 /* Hardware access */ #define ACCTYPE_INSTFETCH ACC_READ /* Instruction fetch */ #define ACCTYPE_READ ACC_READ /* Read storage */ #define ACCTYPE_WRITE_SKP ACC_CHECK /* Write, skip change bit */ #define ACCTYPE_WRITE ACC_WRITE /* Write storage */ #define ACCTYPE_TAR 0 /* TAR instruction */ #define ACCTYPE_LRA ACC_NOTLB /* LRA instruction */ #define ACCTYPE_TPROT 0 /* TPROT instruction */ #define ACCTYPE_IVSK 0 /* ISVK instruction */ #define ACCTYPE_BSG ACC_SPECIAL_ART /* BSG instruction */ #define ACCTYPE_PTE (ACC_PTE|ACC_NOTLB) /* page table entry */ #define ACCTYPE_SIE 0 /* SIE host access */ #define ACCTYPE_STRAG 0 /* STRAG instruction */ #define ACCTYPE_LPTEA (ACC_LPTEA|ACC_NOTLB) /* LPTEA instruction */ /* Special value for arn parameter for translate functions in dat.c */ /* _USE_... values for killing the "array subscript" warnings */ #define USE_INST_SPACE 20 /* Instruction space virtual */ #define USE_REAL_ADDR 19 /* Real address */ #define USE_PRIMARY_SPACE 18 /* Primary space virtual */ #define USE_SECONDARY_SPACE 17 /* Secondary space virtual */ #define USE_HOME_SPACE 16 /* Home space virtual */ #define USE_ARMODE 16 /* OR with access register number to force AR mode */ /* Interception codes used by longjmp/SIE */ #define SIE_NO_INTERCEPT (-1) /* Continue (after pgmint) */ #define SIE_HOST_INTERRUPT (-2) /* Host interrupt pending */ #define SIE_HOST_PGMINT (-3) /* Host program interrupt */ #define SIE_INTERCEPT_INST (-4) /* Instruction interception */ #define SIE_INTERCEPT_INSTCOMP (-5) /* Instr. int TS/CS/CDS */ #define SIE_INTERCEPT_EXTREQ (-6) /* External interrupt */ #define SIE_INTERCEPT_IOREQ (-7) /* I/O interrupt */ #define SIE_INTERCEPT_WAIT (-8) /* Wait state loaded */ #define SIE_INTERCEPT_STOPREQ (-9) /* STOP reqeust */ #define SIE_INTERCEPT_RESTART (-10) /* Restart interrupt */ #define SIE_INTERCEPT_MCK (-11) /* Machine Check interrupt */ #define SIE_INTERCEPT_EXT (-12) /* External interrupt pending*/ #define SIE_INTERCEPT_VALIDITY (-13) /* SIE validity check */ #define SIE_INTERCEPT_PER (-14) /* SIE guest per event */ #define SIE_INTERCEPT_IOINT (-15) /* I/O Interruption */ #define SIE_INTERCEPT_IOINTP (-16) /* I/O Interruption pending */ #define SIE_INTERCEPT_IOINST (-17) /* I/O Instruction */ #if defined(SIE_DEBUG_PERFMON) #define SIE_PERF_ENTER 0 /* SIE performance monitor */ #define SIE_PERF_ENTER_F -31 /* Enter Fast (retain state) */ #define SIE_PERF_EXIT -30 /* SIE exit */ #define SIE_PERF_RUNSIE -29 /* run_sie entered */ #define SIE_PERF_RUNLOOP_1 -28 /* run_sie runloop 1 */ #define SIE_PERF_RUNLOOP_2 -27 /* run_sue runloop 2 */ #define SIE_PERF_INTCHECK -26 /* run_sie intcheck */ #define SIE_PERF_EXEC -25 /* run_sie execute inst */ #define SIE_PERF_EXEC_U -24 /* run_sie unrolled exec */ #endif /*defined(SIE_DEBUG_PERFMON)*/ /*-------------------------------------------------------------------*/ /* Definitions for CTC protocol types */ /*-------------------------------------------------------------------*/ #define CTC_XCA 1 /* XCA device */ #define CTC_LCS 2 /* LCS device */ #define CTC_CETI 3 /* CETI device */ #define CTC_CLAW 4 /* CLAW device */ #define CTC_CTCN 5 /* CTC link via NETBIOS */ #define CTC_CTCT 6 /* CTC link via TCP */ #define CTC_CTCI 7 /* CTC link to TCP/IP stack */ #define CTC_VMNET 8 /* CTC link via wfk's vmnet */ #define CTC_CFC 9 /* Coupling facility channel */ #endif // _HCONSTS_H hercules-3.07/hdl.c000644 000765 000765 00000056241 11143760542 015671 0ustar00jmaynardjmaynard000000 000000 /* HDL.C (c) Copyright Jan Jaeger, 2003-2009 */ /* Hercules Dynamic Loader */ // $Id: hdl.c 5125 2009-01-23 12:01:44Z bernard $ // // $Log$ // Revision 1.55 2009/01/14 15:23:20 jj // Move modpath logic to hsccmd.c // // Revision 1.54 2008/11/23 23:29:44 rbowler // Fix win64 type conversion warnings in hdl.c // // Revision 1.53 2007/06/23 00:04:10 ivan // Update copyright notices to include current year (2007) // // Revision 1.52 2006/12/08 09:43:25 jj // Add CVS message log // #include "hstdinc.h" #define _HDL_C_ #define _HUTIL_DLL_ #include "hercules.h" /* extern HDLPRE hdl_preload[]; */ #if defined(OPTION_DYNAMIC_LOAD) HDLPRE hdl_preload[] = { { "hdteq", HDL_LOAD_NOMSG }, { "dyncrypt", HDL_LOAD_NOMSG }, #if 0 { "dyn_test1", HDL_LOAD_DEFAULT }, { "dyn_test2", HDL_LOAD_NOMSG }, { "dyn_test3", HDL_LOAD_NOMSG | HDL_LOAD_NOUNLOAD }, #endif { NULL, 0 } }; #if 0 /* Forward definitions from hdlmain.c stuff */ /* needed because we cannot depend on dlopen(self) */ extern void *HDL_DEPC; extern void *HDL_INIT; extern void *HDL_RESO; extern void *HDL_DDEV; extern void *HDL_FINI; #endif static DLLENT *hdl_dll; /* dll chain */ static LOCK hdl_lock; /* loader lock */ static DLLENT *hdl_cdll; /* current dll (hdl_lock) */ static HDLDEP *hdl_depend; /* Version codes in hdlmain */ static char *hdl_modpath = NULL; #endif static LOCK hdl_sdlock; /* shutdown lock */ static HDLSHD *hdl_shdlist; /* Shutdown call list */ /* Global hdl_device_type_equates */ DLL_EXPORT char *(*hdl_device_type_equates)(const char *); /* hdl_adsc - add shutdown call */ DLL_EXPORT void hdl_adsc (char* shdname, void * shdcall, void * shdarg) { HDLSHD *newcall; newcall = malloc(sizeof(HDLSHD)); newcall->shdname = shdname; newcall->shdcall = shdcall; newcall->shdarg = shdarg; newcall->next = hdl_shdlist; hdl_shdlist = newcall; } /* hdl_rmsc - remove shutdown call */ DLL_EXPORT int hdl_rmsc (void *shdcall, void *shdarg) { HDLSHD **tmpcall; for(tmpcall = &(hdl_shdlist); *tmpcall; tmpcall = &((*tmpcall)->next) ) { if( (*tmpcall)->shdcall == shdcall && (*tmpcall)->shdarg == shdarg ) { HDLSHD *frecall; frecall = *tmpcall; *tmpcall = (*tmpcall)->next; free(frecall); return 0; } } return -1; } /* hdl_shut - call all shutdown call entries in LIFO order */ DLL_EXPORT void hdl_shut (void) { HDLSHD *shdent; logmsg("HHCHD900I Begin shutdown sequence\n"); obtain_lock (&hdl_sdlock); for(shdent = hdl_shdlist; shdent; shdent = hdl_shdlist) { logmsg("HHCHD901I Calling %s\n",shdent->shdname); { (shdent->shdcall) (shdent->shdarg); } logmsg("HHCHD902I %s complete\n",shdent->shdname); /* Remove shutdown call entry to ensure it is called once */ hdl_shdlist = shdent->next; free(shdent); } release_lock (&hdl_sdlock); logmsg("HHCHD909I Shutdown sequence complete\n"); } #if defined(OPTION_DYNAMIC_LOAD) /* hdl_setpath - set path for module load */ DLL_EXPORT void hdl_setpath(char *path) { if(hdl_modpath) free(hdl_modpath); hdl_modpath = strdup(path); logmsg(_("HHCHD018I Loadable module directory is %s\n"),hdl_modpath); } static void * hdl_dlopen(char *filename, int flag _HDL_UNUSED) { char *fullname; void *ret; size_t fulllen = 0; if(filename && *filename != '/' && *filename != '.') { if(hdl_modpath && *hdl_modpath) { fulllen = strlen(filename) + strlen(hdl_modpath) + 2 + HDL_SUFFIX_LENGTH; fullname = malloc(fulllen); strlcpy(fullname,hdl_modpath,fulllen); strlcat(fullname,"/",fulllen); strlcat(fullname,filename,fulllen); #if defined(HDL_MODULE_SUFFIX) strlcat(fullname,HDL_MODULE_SUFFIX,fulllen); #endif } else fullname = filename; if((ret = dlopen(fullname,flag))) { if(fulllen) free(fullname); return ret; } #if defined(HDL_MODULE_SUFFIX) fullname[strlen(fullname) - HDL_SUFFIX_LENGTH] = '\0'; if((ret = dlopen(fullname,flag))) { if(fulllen) free(fullname); return ret; } #endif if(fulllen) free(fullname); fulllen=0; } if(filename && *filename != '/' && *filename != '.') { fulllen = strlen(filename) + 1 + HDL_SUFFIX_LENGTH; fullname = malloc(fulllen); strlcpy(fullname,filename,fulllen); #if defined(HDL_MODULE_SUFFIX) strlcat(fullname,HDL_MODULE_SUFFIX,fulllen); #endif if((ret = dlopen(fullname,flag))) { if(fulllen) free(fullname); return ret; } #if defined(HDL_MODULE_SUFFIX) fullname[strlen(fullname) - HDL_SUFFIX_LENGTH] = '\0'; if((ret = dlopen(fullname,flag))) { if(fulllen) free(fullname); return ret; } #endif if(fulllen) free(fullname); fulllen=0; } return dlopen(filename,flag); } /* hdl_dvad - register device type */ DLL_EXPORT void hdl_dvad (char *devname, DEVHND *devhnd) { HDLDEV *newhnd; newhnd = malloc(sizeof(HDLDEV)); newhnd->name = strdup(devname); newhnd->hnd = devhnd; newhnd->next = hdl_cdll->hndent; hdl_cdll->hndent = newhnd; } /* hdl_fhnd - find registered device handler */ static DEVHND * hdl_fhnd (const char *devname) { DLLENT *dllent; HDLDEV *hndent; for(dllent = hdl_dll; dllent; dllent = dllent->dllnext) { for(hndent = dllent->hndent; hndent; hndent = hndent->next) { if(!strcasecmp(devname,hndent->name)) { return hndent->hnd; } } } return NULL; } /* hdl_bdnm - build device module name */ static char * hdl_bdnm (const char *ltype) { char *dtname; unsigned int n; dtname = malloc(strlen(ltype) + sizeof(HDL_HDTP_Q)); strcpy(dtname,HDL_HDTP_Q); strcat(dtname,ltype); for(n = 0; n < strlen(dtname); n++) if(isupper(dtname[n])) dtname[n] = tolower(dtname[n]); return dtname; } /* hdl_ghnd - obtain device handler */ DLL_EXPORT DEVHND * hdl_ghnd (const char *devtype) { DEVHND *hnd; char *hdtname; char *ltype; if((hnd = hdl_fhnd(devtype))) return hnd; hdtname = hdl_bdnm(devtype); if(hdl_load(hdtname,HDL_LOAD_NOMSG) || !hdl_fhnd(devtype)) { if(hdl_device_type_equates) { if((ltype = hdl_device_type_equates(devtype))) { free(hdtname); hdtname = hdl_bdnm(ltype); hdl_load(hdtname,HDL_LOAD_NOMSG); } } } free(hdtname); return hdl_fhnd(devtype); } /* hdl_list - list all entry points */ DLL_EXPORT void hdl_list (int flags) { DLLENT *dllent; MODENT *modent; for(dllent = hdl_dll; dllent; dllent = dllent->dllnext) { logmsg("dll type = %s",(dllent->flags & HDL_LOAD_MAIN) ? "main" : "load"); logmsg(", name = %s",dllent->name); if (dllent->flags & (HDL_LOAD_NOUNLOAD | HDL_LOAD_WAS_FORCED)) { logmsg(", flags = (%s%s%s)" ,(dllent->flags & HDL_LOAD_NOUNLOAD) ? "nounload" : "" ,(dllent->flags & HDL_LOAD_NOUNLOAD) && (dllent->flags & HDL_LOAD_WAS_FORCED) ? ", " : "" ,(dllent->flags & HDL_LOAD_WAS_FORCED) ? "forced" : "" ); } logmsg("\n"); for(modent = dllent->modent; modent; modent = modent->modnext) if((flags & HDL_LIST_ALL) || !((dllent->flags & HDL_LOAD_MAIN) && !modent->fep)) { logmsg(" symbol = %s",modent->name); // logmsg(", ep = %p",modent->fep); if(modent->fep) logmsg(", loadcount = %d",modent->count); else logmsg(", unresolved"); logmsg(", owner = %s\n",dllent->name); } if(dllent->hndent) { HDLDEV *hndent; logmsg(" devtype ="); for(hndent = dllent->hndent; hndent; hndent = hndent->next) logmsg(" %s",hndent->name); logmsg("\n"); } } } /* hdl_dlst - list all dependencies */ DLL_EXPORT void hdl_dlst (void) { HDLDEP *depent; for(depent = hdl_depend; depent; depent = depent->next) logmsg("dependency(%s) version(%s) size(%d)\n", depent->name,depent->version,depent->size); } /* hdl_dadd - add dependency */ static int hdl_dadd (char *name, char *version, int size) { HDLDEP **newdep; for (newdep = &(hdl_depend); *newdep; newdep = &((*newdep)->next)); (*newdep) = malloc(sizeof(HDLDEP)); (*newdep)->next = NULL; (*newdep)->name = strdup(name); (*newdep)->version = strdup(version); (*newdep)->size = size; return 0; } /* hdl_dchk - dependency check */ static int hdl_dchk (char *name, char *version, int size) { HDLDEP *depent; for(depent = hdl_depend; depent && strcmp(name,depent->name); depent = depent->next); if(depent) { if(strcmp(version,depent->version)) { logmsg(_("HHCHD010I Dependency check failed for %s, version(%s) expected(%s)\n"), name,version,depent->version); return -1; } if(size != depent->size) { logmsg(_("HHCHD011I Dependency check failed for %s, size(%d) expected(%d)\n"), name,size,depent->size); return -1; } } else { hdl_dadd(name,version,size); } return 0; } /* hdl_fent - find entry point */ DLL_EXPORT void * hdl_fent (char *name) { DLLENT *dllent; MODENT *modent; void *fep; /* Find entry point and increase loadcount */ for(dllent = hdl_dll; dllent; dllent = dllent->dllnext) { for(modent = dllent->modent; modent; modent = modent->modnext) { if(!strcmp(name,modent->name)) { modent->count++; return modent->fep; } } } /* If not found then lookup as regular symbol */ for(dllent = hdl_dll; dllent; dllent = dllent->dllnext) { if((fep = dlsym(dllent->dll,name))) { if(!(modent = malloc(sizeof(MODENT)))) { logmsg(_("HHCHD001E registration malloc failed for %s\n"), name); return NULL; } modent->fep = fep; modent->name = strdup(name); modent->count = 1; /* Insert current entry as first in chain */ modent->modnext = dllent->modent; dllent->modent = modent; return fep; } } /* No entry point found */ return NULL; } /* hdl_nent - find next entry point in chain */ DLL_EXPORT void * hdl_nent (void *fep) { DLLENT *dllent; MODENT *modent = NULL; char *name; for(dllent = hdl_dll; dllent; dllent = dllent->dllnext) { for(modent = dllent->modent; modent; modent = modent->modnext) { if(modent->fep == fep) break; } if(modent && modent->fep == fep) break; } if(!modent) return NULL; name = modent->name; if(!(modent = modent->modnext)) { if((dllent = dllent->dllnext)) modent = dllent->modent; else return NULL; } /* Find entry point */ for(; dllent; dllent = dllent->dllnext, modent = dllent->modent) { for(; modent; modent = modent->modnext) { if(!strcmp(name,modent->name)) { return modent->fep; } } } return NULL; } /* hdl_regi - register entry point */ static void hdl_regi (char *name, void *fep) { MODENT *modent; modent = malloc(sizeof(MODENT)); modent->fep = fep; modent->name = strdup(name); modent->count = 0; modent->modnext = hdl_cdll->modent; hdl_cdll->modent = modent; } /* hdl_term - process all "HDL_FINAL_SECTION"s */ static void hdl_term (void *unused _HDL_UNUSED) { DLLENT *dllent; logmsg("HHCHD950I Begin HDL termination sequence\n"); /* Call all final routines, in reverse load order */ for(dllent = hdl_dll; dllent; dllent = dllent->dllnext) { if(dllent->hdlfini) { logmsg("HHCHD951I Calling module %s cleanup routine\n",dllent->name); { (dllent->hdlfini)(); } logmsg("HHCHD952I Module %s cleanup complete\n",dllent->name); } } logmsg("HHCHD959I HDL Termination sequence complete\n"); } #if defined(_MSVC_) /* hdl_lexe - load exe */ static int hdl_lexe () { DLLENT *dllent; MODENT *modent; for(dllent = hdl_dll; dllent; dllent = dllent->dllnext); dllent->name = strdup("*Main"); if(!(dllent->dll = (void*)GetModuleHandle( NULL ) )); { logmsg(_("HHCHD007E unable to open DLL %s: %s\n"), dllent->name,dlerror()); free(dllent); return -1; } dllent->flags = HDL_LOAD_MAIN; if(!(dllent->hdldepc = dlsym(dllent->dll,HDL_DEPC_Q))) { logmsg(_("HHCHD013E No dependency section in %s: %s\n"), dllent->name, dlerror()); free(dllent); return -1; } dllent->hdlinit = dlsym(dllent->dll,HDL_INIT_Q); dllent->hdlreso = dlsym(dllent->dll,HDL_RESO_Q); dllent->hdlddev = dlsym(dllent->dll,HDL_DDEV_Q); dllent->hdlfini = dlsym(dllent->dll,HDL_FINI_Q); /* No modules or device types registered yet */ dllent->modent = NULL; dllent->hndent = NULL; obtain_lock(&hdl_lock); if(dllent->hdldepc) { if((dllent->hdldepc)(&hdl_dchk)) { logmsg(_("HHCHD014E Dependency check failed for module %s\n"), dllent->name); } } hdl_cdll = dllent; /* Call initializer */ if(hdl_cdll->hdlinit) (dllent->hdlinit)(&hdl_regi); /* Insert current entry as first in chain */ dllent->dllnext = hdl_dll; hdl_dll = dllent; /* Reset the loadcounts */ for(dllent = hdl_dll; dllent; dllent = dllent->dllnext) for(modent = dllent->modent; modent; modent = modent->modnext) modent->count = 0; /* Call all resolvers */ for(dllent = hdl_dll; dllent; dllent = dllent->dllnext) { if(dllent->hdlreso) (dllent->hdlreso)(&hdl_fent); } /* register any device types */ if(hdl_cdll->hdlddev) (hdl_cdll->hdlddev)(&hdl_dvad); hdl_cdll = NULL; release_lock(&hdl_lock); return 0; } #endif /* hdl_main - initialize hercules dynamic loader */ DLL_EXPORT void hdl_main (void) { HDLPRE *preload; initialize_lock(&hdl_lock); initialize_lock(&hdl_sdlock); hdl_setpath(HDL_DEFAULT_PATH); dlinit(); if(!(hdl_cdll = hdl_dll = malloc(sizeof(DLLENT)))) { fprintf(stderr, _("HHCHD002E cannot allocate memory for DLL descriptor: %s\n"), strerror(errno)); exit(1); } hdl_cdll->name = strdup("*Hercules"); /* This was a nice trick. Unfortunately, on some platforms */ /* it becomes impossible. Some platforms need fully defined */ /* DLLs, some other platforms do not allow dlopen(self) */ #if 1 if(!(hdl_cdll->dll = hdl_dlopen(NULL, RTLD_NOW ))) { fprintf(stderr, _("HHCHD003E unable to open hercules as DLL: %s\n"), dlerror()); exit(1); } hdl_cdll->flags = HDL_LOAD_MAIN | HDL_LOAD_NOUNLOAD; if(!(hdl_cdll->hdldepc = dlsym(hdl_cdll->dll,HDL_DEPC_Q))) { fprintf(stderr, _("HHCHD012E No dependency section in %s: %s\n"), hdl_cdll->name, dlerror()); exit(1); } hdl_cdll->hdlinit = dlsym(hdl_cdll->dll,HDL_INIT_Q); hdl_cdll->hdlreso = dlsym(hdl_cdll->dll,HDL_RESO_Q); hdl_cdll->hdlddev = dlsym(hdl_cdll->dll,HDL_DDEV_Q); hdl_cdll->hdlfini = dlsym(hdl_cdll->dll,HDL_FINI_Q); #else hdl_cdll->flags = HDL_LOAD_MAIN | HDL_LOAD_NOUNLOAD; hdl_cdll->hdldepc = &HDL_DEPC; hdl_cdll->hdlinit = &HDL_INIT; hdl_cdll->hdlreso = &HDL_RESO; hdl_cdll->hdlddev = &HDL_DDEV; hdl_cdll->hdlfini = &HDL_FINI; #endif /* No modules or device types registered yet */ hdl_cdll->modent = NULL; hdl_cdll->hndent = NULL; /* No dll's loaded yet */ hdl_cdll->dllnext = NULL; obtain_lock(&hdl_lock); if(hdl_cdll->hdldepc) (hdl_cdll->hdldepc)(&hdl_dadd); if(hdl_cdll->hdlinit) (hdl_cdll->hdlinit)(&hdl_regi); if(hdl_cdll->hdlreso) (hdl_cdll->hdlreso)(&hdl_fent); if(hdl_cdll->hdlddev) (hdl_cdll->hdlddev)(&hdl_dvad); release_lock(&hdl_lock); /* Register termination exit */ hdl_adsc( "hdl_term", hdl_term, NULL); for(preload = hdl_preload; preload->name; preload++) hdl_load(preload->name, preload->flag); #if defined(_MSVC_) && 0 hdl_lexe(); #endif } /* hdl_load - load a dll */ DLL_EXPORT int hdl_load (char *name,int flags) { DLLENT *dllent, *tmpdll; MODENT *modent; char *modname; modname = (modname = strrchr(name,'/')) ? modname+1 : name; for(dllent = hdl_dll; dllent; dllent = dllent->dllnext) { if(strfilenamecmp(modname,dllent->name) == 0) { logmsg(_("HHCHD005E %s already loaded\n"),dllent->name); return -1; } } if(!(dllent = malloc(sizeof(DLLENT)))) { logmsg(_("HHCHD006S cannot allocate memory for DLL descriptor: %s\n"), strerror(errno)); return -1; } dllent->name = strdup(modname); if(!(dllent->dll = hdl_dlopen(name, RTLD_NOW))) { if(!(flags & HDL_LOAD_NOMSG)) logmsg(_("HHCHD007E unable to open DLL %s: %s\n"), name,dlerror()); free(dllent); return -1; } dllent->flags = (flags & (~HDL_LOAD_WAS_FORCED)); if(!(dllent->hdldepc = dlsym(dllent->dll,HDL_DEPC_Q))) { logmsg(_("HHCHD013E No dependency section in %s: %s\n"), dllent->name, dlerror()); dlclose(dllent->dll); free(dllent); return -1; } for(tmpdll = hdl_dll; tmpdll; tmpdll = tmpdll->dllnext) { if(tmpdll->hdldepc == dllent->hdldepc) { logmsg(_("HHCHD016E DLL %s is duplicate of %s\n"), dllent->name, tmpdll->name); dlclose(dllent->dll); free(dllent); return -1; } } dllent->hdlinit = dlsym(dllent->dll,HDL_INIT_Q); dllent->hdlreso = dlsym(dllent->dll,HDL_RESO_Q); dllent->hdlddev = dlsym(dllent->dll,HDL_DDEV_Q); dllent->hdlfini = dlsym(dllent->dll,HDL_FINI_Q); /* No modules or device types registered yet */ dllent->modent = NULL; dllent->hndent = NULL; obtain_lock(&hdl_lock); if(dllent->hdldepc) { if((dllent->hdldepc)(&hdl_dchk)) { logmsg(_("HHCHD014E Dependency check failed for module %s\n"), dllent->name); if(!(flags & HDL_LOAD_FORCE)) { dlclose(dllent->dll); free(dllent); release_lock(&hdl_lock); return -1; } dllent->flags |= HDL_LOAD_WAS_FORCED; } } hdl_cdll = dllent; /* Call initializer */ if(hdl_cdll->hdlinit) (dllent->hdlinit)(&hdl_regi); /* Insert current entry as first in chain */ dllent->dllnext = hdl_dll; hdl_dll = dllent; /* Reset the loadcounts */ for(dllent = hdl_dll; dllent; dllent = dllent->dllnext) for(modent = dllent->modent; modent; modent = modent->modnext) modent->count = 0; /* Call all resolvers */ for(dllent = hdl_dll; dllent; dllent = dllent->dllnext) { if(dllent->hdlreso) (dllent->hdlreso)(&hdl_fent); } /* register any device types */ if(hdl_cdll->hdlddev) (hdl_cdll->hdlddev)(&hdl_dvad); hdl_cdll = NULL; release_lock(&hdl_lock); return 0; } /* hdl_dele - unload a dll */ DLL_EXPORT int hdl_dele (char *name) { DLLENT **dllent, *tmpdll; MODENT *modent, *tmpmod; DEVBLK *dev; HDLDEV *hnd; char *modname; modname = (modname = strrchr(name,'/')) ? modname+1 : name; obtain_lock(&hdl_lock); for(dllent = &(hdl_dll); *dllent; dllent = &((*dllent)->dllnext)) { if(strfilenamecmp(modname,(*dllent)->name) == 0) { if((*dllent)->flags & (HDL_LOAD_MAIN | HDL_LOAD_NOUNLOAD)) { logmsg(_("HHCHD015E Unloading of %s not allowed\n"),(*dllent)->name); release_lock(&hdl_lock); return -1; } for(dev = sysblk.firstdev; dev; dev = dev->nextdev) if(dev->pmcw.flag5 & PMCW5_V) for(hnd = (*dllent)->hndent; hnd; hnd = hnd->next) if(hnd->hnd == dev->hnd) { logmsg(_("HHCHD008E Device %4.4X bound to %s\n"),dev->devnum,(*dllent)->name); release_lock(&hdl_lock); return -1; } /* Call dll close routine */ if((*dllent)->hdlfini) { int rc; if((rc = ((*dllent)->hdlfini)())) { logmsg(_("HHCHD017E Unload of %s rejected by final section\n"),(*dllent)->name); release_lock(&hdl_lock); return rc; } } modent = (*dllent)->modent; while(modent) { tmpmod = modent; /* remove current entry from chain */ modent = modent->modnext; /* free module resources */ free(tmpmod->name); free(tmpmod); } tmpdll = *dllent; /* remove current entry from chain */ *dllent = (*dllent)->dllnext; for(hnd = tmpdll->hndent; hnd;) { HDLDEV *nexthnd; free(hnd->name); nexthnd = hnd->next; free(hnd); hnd = nexthnd; } // dlclose(tmpdll->dll); /* free dll resources */ free(tmpdll->name); free(tmpdll); /* Reset the loadcounts */ for(tmpdll = hdl_dll; tmpdll; tmpdll = tmpdll->dllnext) for(tmpmod = tmpdll->modent; tmpmod; tmpmod = tmpmod->modnext) tmpmod->count = 0; /* Call all resolvers */ for(tmpdll = hdl_dll; tmpdll; tmpdll = tmpdll->dllnext) { if(tmpdll->hdlreso) (tmpdll->hdlreso)(&hdl_fent); } release_lock(&hdl_lock); return 0; } } release_lock(&hdl_lock); logmsg(_("HHCHD009E %s not found\n"),modname); return -1; } #endif /*defined(OPTION_DYNAMIC_LOAD)*/ hercules-3.07/hdl.h000644 000765 000765 00000022362 11143760542 015673 0ustar00jmaynardjmaynard000000 000000 /*********************************************************************/ /* HDL.H (c) Copyright Jan Jaeger, 2003-2009 */ /* Hercules Dynamic Loader */ /*********************************************************************/ // $Id: hdl.h 5125 2009-01-23 12:01:44Z bernard $ // // $Log$ // Revision 1.34 2007/06/23 00:04:10 ivan // Update copyright notices to include current year (2007) // // Revision 1.33 2006/12/08 09:43:25 jj // Add CVS message log // #ifndef _HDL_H #define _HDL_H #include "hercules.h" #if !defined(_MSVC_) #define _HDL_UNUSED __attribute__ ((unused)) #else #define _HDL_UNUSED #endif #ifndef _HDL_C_ #ifndef _HUTIL_DLL_ #define HDL_DLL_IMPORT DLL_IMPORT #else /* _HUTIL_DLL_ */ #define HDL_DLL_IMPORT extern #endif /* _HUTIL_DLL_ */ #else #define HDL_DLL_IMPORT DLL_EXPORT #endif #ifndef _HDLMAIN_C_ #ifndef _HENGINE_DLL_ #define HDM_DLL_IMPORT DLL_IMPORT #else /* _HENGINE_DLL_ */ #define HDM_DLL_IMPORT extern #endif /* _HENGINE_DLL_ */ #else #define HDM_DLL_IMPORT DLL_EXPORT #endif /*********************************************************************/ #define STRING_M( _string ) #_string #define STRING_Q( _string ) STRING_M( _string ) struct _HDLSHD; typedef struct _HDLSHD { struct _HDLSHD *next; char* shdname; /* identifying name */ void (*shdcall) (void *); /* Entry to be called */ void *shdarg; /* Optional argument */ } HDLSHD; HDL_DLL_IMPORT void hdl_adsc(char*, void *, void *);/* Add shutdown routine */ HDL_DLL_IMPORT int hdl_rmsc(void *, void *); /* Remove shutdown routine */ HDL_DLL_IMPORT void hdl_shut(void); /* Call all shutdown routines*/ DLL_EXPORT DEVHND *hdl_ghnd(const char *devname); /* Get device handler */ /*********************************************************************/ #if !defined(OPTION_DYNAMIC_LOAD) #define HDL_DEVICE_SECTION \ DLL_EXPORT DEVHND *hdl_ghnd(const char *devtype) \ { #define HDL_DEVICE( _devname, _devhnd ) \ if(!strcasecmp( STRING_Q(_devname), devtype )) \ return &(_devhnd); #define END_DEVICE_SECTION \ return NULL; \ } #else /* defined(OPTION_DYNAMIC_LOAD) */ /*********************************************************************/ #if !defined(HDL_USE_LIBTOOL) #define dlinit() #else #define dlinit() lt_dlinit() #define dlopen(_name, _flags) lt_dlopen(_name) #define dlsym(_handle, _symbol) lt_dlsym(_handle, _symbol) #define dlclose(_handle) lt_dlclose(_handle) #define dlerror() lt_dlerror() #define RTLD_NOW 0 #endif // extern char *(*hdl_device_type_equates)(char *); typedef struct _HDLDEV { /* Device entry */ char *name; /* Device type name */ DEVHND *hnd; /* Device handlers */ struct _HDLDEV *next; /* Next entry */ } HDLDEV; struct _HDLDEP; typedef struct _HDLDEP { /* Dependency entry */ char *name; /* Dependency name */ char *version; /* Version */ int size; /* Structure/module size */ struct _HDLDEP *next; /* Next entry */ } HDLDEP; typedef struct _HDLPRE { /* Preload list entry */ char *name; /* Module name */ int flag; /* Load flags */ } HDLPRE; struct _MODENT; typedef struct _MODENT { /* External Symbol entry */ void (*fep)(); /* Function entry point */ char *name; /* Function symbol name */ int count; /* Symbol load count */ struct _MODENT *modnext; /* Next entry in chain */ } MODENT; struct _DLLENT; typedef struct _DLLENT { /* DLL entry */ char *name; /* load module name */ void *dll; /* DLL handle (dlopen) */ int flags; /* load flags */ int (*hdldepc)(void *); /* hdl_depc */ int (*hdlreso)(void *); /* hdl_reso */ int (*hdlinit)(void *); /* hdl_init */ int (*hdlddev)(void *); /* hdl_ddev */ int (*hdlfini)(); /* hdl_fini */ struct _MODENT *modent; /* First symbol entry */ struct _HDLDEV *hndent; /* First device entry */ struct _DLLENT *dllnext; /* Next entry in chain */ } DLLENT; #if defined(MODULESDIR) #define HDL_DEFAULT_PATH MODULESDIR #else #define HDL_DEFAULT_PATH "hercules" #endif /* SHLIBEXT defined by ISW in configure.ac/config.h */ #if defined( HDL_BUILD_SHARED ) && defined( LTDL_SHLIB_EXT ) #define HDL_MODULE_SUFFIX LTDL_SHLIB_EXT #else #if defined(_MSVC_) #define HDL_MODULE_SUFFIX ".dll" #else #define HDL_MODULE_SUFFIX ".la" #endif #endif #if defined( HDL_MODULE_SUFFIX ) #define HDL_SUFFIX_LENGTH (sizeof(HDL_MODULE_SUFFIX) - 1) #else #define HDL_SUFFIX_LENGTH 0 #endif DLL_EXPORT int hdl_load(char *, int); /* load dll */ #define HDL_LOAD_DEFAULT 0x00000000 #define HDL_LOAD_MAIN 0x00000001 /* Hercules MAIN module flag */ #define HDL_LOAD_NOUNLOAD 0x00000002 /* Module cannot be unloaded */ #define HDL_LOAD_FORCE 0x00000004 /* Override dependency check */ #define HDL_LOAD_NOMSG 0x00000008 /* Do not issue not found msg*/ #define HDL_LOAD_WAS_FORCED 0x00000010 /* Module load was forced */ DLL_EXPORT int hdl_dele(char *); /* Unload dll */ DLL_EXPORT void hdl_list(int); /* list all loaded modules */ #define HDL_LIST_DEFAULT 0x00000000 #define HDL_LIST_ALL 0x00000001 /* list all references */ DLL_EXPORT void hdl_dlst(); /* list all dependencies */ DLL_EXPORT void hdl_main(); /* Main initialization rtn */ DLL_EXPORT void hdl_setpath(char *); /* Set module path */ DLL_EXPORT void * hdl_fent(char *); /* Find entry name */ DLL_EXPORT void * hdl_nent(void *); /* Find next in chain */ /* The following statement should be void *(*unresolved)(void) = NULL*/ static void **unresolved _HDL_UNUSED = NULL; #define UNRESOLVED *unresolved #define HDL_DEPC hdl_depc #define HDL_RESO hdl_reso #define HDL_INIT hdl_init #define HDL_FINI hdl_fini #define HDL_DDEV hdl_ddev #define HDL_HDTP hdt #define HDL_DEPC_Q STRING_Q(HDL_DEPC) #define HDL_RESO_Q STRING_Q(HDL_RESO) #define HDL_INIT_Q STRING_Q(HDL_INIT) #define HDL_FINI_Q STRING_Q(HDL_FINI) #define HDL_DDEV_Q STRING_Q(HDL_DDEV) #define HDL_HDTP_Q STRING_Q(HDL_HDTP) #define HDL_FINDSYM(_name) \ hdl_fent( (_name) ) #define HDL_FINDNXT(_ep) \ hdl_nent( &(_ep) ) #define HDL_DEPENDENCY_SECTION \ DLL_EXPORT int HDL_DEPC(int (*hdl_depc_vers)(char *, char *, int) _HDL_UNUSED ) \ { \ int hdl_depc_rc = 0 #define HDL_DEPENDENCY(_comp) \ if (hdl_depc_vers( STRING_Q(_comp), HDL_VERS_ ## _comp, HDL_SIZE_ ## _comp)) \ hdl_depc_rc = 1 #define END_DEPENDENCY_SECTION \ return hdl_depc_rc; } #define HDL_REGISTER_SECTION \ DLL_EXPORT void HDL_INIT(int (*hdl_init_regi)(char *, void *) _HDL_UNUSED ) \ { /* register this epname, as ep = addr of this var or func... */ #define HDL_REGISTER( _epname, _varname ) \ (hdl_init_regi)( STRING_Q(_epname), &(_varname) ) #define END_REGISTER_SECTION \ } #define HDL_DEVICE_SECTION \ DLL_EXPORT void HDL_DDEV(int (*hdl_init_ddev)(char *, void *) _HDL_UNUSED ) \ { #define HDL_DEVICE( _devname, _devhnd ) \ (hdl_init_ddev)( STRING_Q(_devname), &(_devhnd) ) #define END_DEVICE_SECTION \ } #define HDL_RESOLVER_SECTION \ DLL_EXPORT void HDL_RESO(void *(*hdl_reso_fent)(char *) _HDL_UNUSED ) \ { #define HDL_RESOLVE(_name) \ (_name) = (hdl_reso_fent)(STRING_Q(_name)) /* set this ptrvar, to this ep value... */ #define HDL_RESOLVE_PTRVAR( _ptrvar, _epname ) \ (_ptrvar) = (hdl_reso_fent)( STRING_Q(_epname) ) #define END_RESOLVER_SECTION \ } #define HDL_FINAL_SECTION \ DLL_EXPORT int HDL_FINI() \ { #define END_FINAL_SECTION \ return 0; } #endif /* defined(OPTION_DYNAMIC_LOAD) */ /*********************************************************************/ #endif /* _HDL_H */ hercules-3.07/hdlmain.c000644 000765 000765 00000020243 11321734033 016521 0ustar00jmaynardjmaynard000000 000000 /* HDLMAIN.C (c) Copyright Jan Jaeger, 2003-2010 */ /* Hercules Dynamic Loader */ // $Id: hdlmain.c 5576 2009-12-29 13:17:11Z bernard $ // // $Log$ // Revision 1.51 2008/12/24 15:42:13 jj // Add debug entry point for sclp event masks // // Revision 1.50 2008/12/22 13:10:21 jj // Add sclp debug entry points // // Revision 1.49 2008/02/12 08:42:15 fish // dyngui tweaks: new def devlist fmt, new debug_cd_cmd hook // // Revision 1.48 2007/06/23 00:04:10 ivan // Update copyright notices to include current year (2007) // // Revision 1.47 2006/12/08 09:43:25 jj // Add CVS message log // #include "hstdinc.h" #define _HDLMAIN_C_ #define _HERCULES_EXE_ #include "hercules.h" #include "httpmisc.h" #define CRYPTO_EXTERN extern #include "crypto.h" #if !defined(_GEN_ARCH) #if defined(_ARCHMODE2) #define _GEN_ARCH _ARCHMODE2 #include "hdlmain.c" #endif #if defined(_ARCHMODE3) #undef _GEN_ARCH #define _GEN_ARCH _ARCHMODE3 #include "hdlmain.c" #endif #if defined(OPTION_DYNAMIC_LOAD) /* Following block moved to 'hdl.c' */ /* this is so that */ /* hdlmain.c can be moved to the executable portion */ /* hdl_main can find hdl_preload */ /* HDLPRE hdl_preload[] = { { "hdteq", HDL_LOAD_NOMSG }, { "dyncrypt", HDL_LOAD_NOMSG }, #if 0 { "dyn_test1", HDL_LOAD_DEFAULT }, { "dyn_test2", HDL_LOAD_NOMSG }, { "dyn_test3", HDL_LOAD_NOMSG | HDL_LOAD_NOUNLOAD }, #endif { NULL, 0 } }; */ HDL_DEPENDENCY_SECTION; { HDL_DEPENDENCY(HERCULES); HDL_DEPENDENCY(REGS); HDL_DEPENDENCY(DEVBLK); HDL_DEPENDENCY(SYSBLK); HDL_DEPENDENCY(WEBBLK); } END_DEPENDENCY_SECTION HDL_REGISTER_SECTION; { HDL_REGISTER( parse_args, parse_args ); HDL_REGISTER( panel_command, panel_command_r ); HDL_REGISTER( panel_display, panel_display_r ); HDL_REGISTER( config_command, UNRESOLVED ); HDL_REGISTER( system_command, UNRESOLVED ); HDL_REGISTER( daemon_task, UNRESOLVED ); HDL_REGISTER( debug_cpu_state, UNRESOLVED ); HDL_REGISTER( debug_cd_cmd, UNRESOLVED ); HDL_REGISTER( debug_device_state, UNRESOLVED ); HDL_REGISTER( debug_program_interrupt, UNRESOLVED ); HDL_REGISTER( debug_diagnose, UNRESOLVED ); HDL_REGISTER( debug_iucv, UNRESOLVED ); HDL_REGISTER( debug_sclp_unknown_command, UNRESOLVED ); HDL_REGISTER( debug_sclp_unknown_event, UNRESOLVED ); HDL_REGISTER( debug_sclp_unknown_event_mask, UNRESOLVED ); HDL_REGISTER( debug_sclp_event_data, UNRESOLVED ); HDL_REGISTER( debug_chsc_unknown_request, UNRESOLVED ); HDL_REGISTER( debug_watchdog_signal, UNRESOLVED ); #if defined(OPTION_W32_CTCI) HDL_REGISTER( debug_tt32_stats, UNRESOLVED ); HDL_REGISTER( debug_tt32_tracing, UNRESOLVED ); #endif HDL_REGISTER( hdl_device_type_equates, UNRESOLVED ); #if defined(_390_FEATURE_MESSAGE_SECURITY_ASSIST) HDL_REGISTER( s390_cipher_message, UNRESOLVED ); HDL_REGISTER( s390_cipher_message_with_chaining, UNRESOLVED ); HDL_REGISTER( s390_compute_message_digest, UNRESOLVED ); HDL_REGISTER( s390_compute_message_authentication_code, UNRESOLVED ); #endif /*defined(_390_FEATURE_MESSAGE_SECURITY_ASSIST)*/ #if defined(_900_FEATURE_MESSAGE_SECURITY_ASSIST) HDL_REGISTER( z900_cipher_message, UNRESOLVED ); HDL_REGISTER( z900_cipher_message_with_chaining, UNRESOLVED ); HDL_REGISTER( z900_compute_message_digest, UNRESOLVED ); HDL_REGISTER( z900_compute_message_authentication_code, UNRESOLVED ); #endif /*defined(_900_FEATURE_MESSAGE_SECURITY_ASSIST)*/ } END_REGISTER_SECTION HDL_RESOLVER_SECTION; { HDL_RESOLVE( panel_command ); HDL_RESOLVE( panel_display ); HDL_RESOLVE( config_command ); HDL_RESOLVE( system_command ); HDL_RESOLVE( daemon_task ); HDL_RESOLVE( debug_cpu_state ); HDL_RESOLVE( debug_cd_cmd ); HDL_RESOLVE( debug_device_state ); HDL_RESOLVE( debug_program_interrupt ); HDL_RESOLVE( debug_diagnose ); HDL_RESOLVE( debug_sclp_unknown_command ); HDL_RESOLVE( debug_sclp_unknown_event ); HDL_RESOLVE( debug_sclp_unknown_event_mask ); HDL_RESOLVE( debug_sclp_event_data ); HDL_RESOLVE( debug_chsc_unknown_request ); #if defined(OPTION_W32_CTCI) HDL_RESOLVE( debug_tt32_stats ); HDL_RESOLVE( debug_tt32_tracing ); #endif HDL_RESOLVE( hdl_device_type_equates ); #if defined(_390_FEATURE_MESSAGE_SECURITY_ASSIST) HDL_RESOLVE( s390_cipher_message ); HDL_RESOLVE( s390_cipher_message_with_chaining ); HDL_RESOLVE( s390_compute_message_digest ); HDL_RESOLVE( s390_compute_message_authentication_code ); #endif /*defined(_390_FEATURE_MESSAGE_SECURITY_ASSIST)*/ #if defined(_900_FEATURE_MESSAGE_SECURITY_ASSIST) HDL_RESOLVE( z900_cipher_message ); HDL_RESOLVE( z900_cipher_message_with_chaining ); HDL_RESOLVE( z900_compute_message_digest ); HDL_RESOLVE( z900_compute_message_authentication_code ); #endif /*defined(_900_FEATURE_MESSAGE_SECURITY_ASSIST)*/ } END_RESOLVER_SECTION HDL_FINAL_SECTION; { system_cleanup(); } END_FINAL_SECTION #endif /*defined(OPTION_DYNAMIC_LOAD)*/ HDL_DEVICE_SECTION; { #if !defined(OPTION_DYNAMIC_LOAD) /* TTY consoles */ HDL_DEVICE(1052, constty_device_hndinfo ); HDL_DEVICE(3215, constty_device_hndinfo ); /* 3270 consoles */ HDL_DEVICE(3270, loc3270_device_hndinfo ); HDL_DEVICE(3287, loc3270_device_hndinfo ); /* Communication line devices */ HDL_DEVICE(2703, comadpt_device_hndinfo ); /* Card readers */ HDL_DEVICE(1442, cardrdr_device_hndinfo ); HDL_DEVICE(2501, cardrdr_device_hndinfo ); HDL_DEVICE(3505, cardrdr_device_hndinfo ); /* Card punches */ HDL_DEVICE(3525, cardpch_device_hndinfo ); /* Printers */ HDL_DEVICE(1403, printer_device_hndinfo ); HDL_DEVICE(3211, printer_device_hndinfo ); /* Tape drives */ HDL_DEVICE(3410, tapedev_device_hndinfo ); HDL_DEVICE(3411, tapedev_device_hndinfo ); HDL_DEVICE(3420, tapedev_device_hndinfo ); HDL_DEVICE(3480, tapedev_device_hndinfo ); HDL_DEVICE(3490, tapedev_device_hndinfo ); HDL_DEVICE(9347, tapedev_device_hndinfo ); HDL_DEVICE(9348, tapedev_device_hndinfo ); HDL_DEVICE(8809, tapedev_device_hndinfo ); HDL_DEVICE(3422, tapedev_device_hndinfo ); HDL_DEVICE(3430, tapedev_device_hndinfo ); /* Communications devices */ HDL_DEVICE(3088, ctcadpt_device_hndinfo ); HDL_DEVICE(CTCI, ctci_device_hndinfo ); HDL_DEVICE(CTCT, ctct_device_hndinfo ); HDL_DEVICE(LCS, lcs_device_hndinfo ); HDL_DEVICE(VMNET,vmnet_device_hndinfo ); #if defined(WIN32) HDL_DEVICE(CTCI-W32, ctci_device_hndinfo); #endif /*defined(WIN32)*/ #endif /*!defined(OPTION_DYNAMIC_LOAD)*/ /* Count Key Data Direct Access Storage Devices */ HDL_DEVICE(2305, ckddasd_device_hndinfo ); HDL_DEVICE(2311, ckddasd_device_hndinfo ); HDL_DEVICE(2314, ckddasd_device_hndinfo ); HDL_DEVICE(3330, ckddasd_device_hndinfo ); HDL_DEVICE(3340, ckddasd_device_hndinfo ); HDL_DEVICE(3350, ckddasd_device_hndinfo ); HDL_DEVICE(3375, ckddasd_device_hndinfo ); HDL_DEVICE(3380, ckddasd_device_hndinfo ); HDL_DEVICE(3390, ckddasd_device_hndinfo ); HDL_DEVICE(9345, ckddasd_device_hndinfo ); /* Fixed Block Architecture Direct Access Storage Devices */ HDL_DEVICE(0671, fbadasd_device_hndinfo ); HDL_DEVICE(3310, fbadasd_device_hndinfo ); HDL_DEVICE(3370, fbadasd_device_hndinfo ); HDL_DEVICE(9313, fbadasd_device_hndinfo ); HDL_DEVICE(9332, fbadasd_device_hndinfo ); HDL_DEVICE(9335, fbadasd_device_hndinfo ); HDL_DEVICE(9336, fbadasd_device_hndinfo ); } END_DEVICE_SECTION #endif /*!defined(_GEN_ARCH)*/ hercules-3.07/hdteq.c000644 000765 000765 00000005751 11143760543 016230 0ustar00jmaynardjmaynard000000 000000 /* HDTEQ.C (c) Copyright Jan Jaeger, 2003-2009 */ /* Hercules Dynamic Loader */ // $Id: hdteq.c 5125 2009-01-23 12:01:44Z bernard $ // // $Log$ // Revision 1.16 2008/12/28 15:30:09 jj // SYSG and SYSA mods // // Revision 1.15 2007/06/23 00:04:10 ivan // Update copyright notices to include current year (2007) // // Revision 1.14 2006/12/08 09:43:25 jj // Add CVS message log // #include "hstdinc.h" #include "hercules.h" typedef struct _DTEQ { char *alias; char *name; } DTEQ; static DTEQ dteq[] = { /* This table provides aliases for device types, such that various device types may be mapped to a common loadable module. The only purpose of this table is to associate the right loadable module with a specific device type, before the device type in question has been registered. This table will not be searched for registered device types or if the specific loadable module exists. device type requested | | base device support | | V V */ // { "3390", "3990" }, // { "3380", "3990" }, { "1052", "3270" }, { "3215", "3270" }, { "3287", "3270" }, { "SYSG", "3270" }, { "1052-C", "1052c" }, { "3215-C", "1052c" }, { "1442", "3505" }, { "2501", "3505" }, { "3211", "1403" }, { "3410", "3420" }, { "3411", "3420" }, // { "3420", "3420" }, { "3480", "3420" }, { "3490", "3420" }, { "3590", "3420" }, { "9347", "3420" }, { "9348", "3420" }, { "8809", "3420" }, { "3422", "3420" }, { "3430", "3420" }, { "LCS", "3088" }, { "CTCI", "3088" }, { "CTCT", "3088" }, { "VMNET", "3088" }, { "HCHAN", "2880" }, // { "2880", "2880" }, { "2870", "2880" }, { "2860", "2880" }, { "9032", "2880" }, { NULL, NULL } }; #if defined(OPTION_DYNAMIC_LOAD) static char *hdt_device_type_equates(char *typname) { DTEQ *device_type; char *(*nextcall)(char *); for(device_type = dteq; device_type->name; device_type++) if(!strcasecmp(device_type->alias, typname)) return device_type->name; if((nextcall = HDL_FINDNXT(hdt_device_type_equates))) return nextcall(typname); return NULL; } /* Libtool static name colision resolution */ /* note : lt_dlopen will look for symbol & modulename_LTX_symbol */ /* for use in DLREOPEN case only */ #if !defined(HDL_BUILD_SHARED) && defined(HDL_USE_LIBTOOL) #define hdl_ddev hdteq_LTX_hdl_ddev #define hdl_depc hdteq_LTX_hdl_depc #define hdl_reso hdteq_LTX_hdl_reso #define hdl_init hdteq_LTX_hdl_init #define hdl_fini hdteq_LTX_hdl_fini #endif HDL_DEPENDENCY_SECTION; { HDL_DEPENDENCY(HERCULES); } END_DEPENDENCY_SECTION HDL_REGISTER_SECTION; { HDL_REGISTER(hdl_device_type_equates,hdt_device_type_equates); } END_REGISTER_SECTION #endif hercules-3.07/herc_getopt.h000644 000765 000765 00000002230 11143760543 017420 0ustar00jmaynardjmaynard000000 000000 // $Id: herc_getopt.h 4102 2006-12-08 09:43:35Z jj $ // // $Log$ #if !defined(__HERC_GETOPT_H__) # define __HERC_GETOPT_H__ #include "hercules.h" #include "getopt.h" #if defined(NEED_GETOPT_OPTRESET) #define OPTRESET() optreset=1 #else #define OPTRESET() #endif #if defined(NEED_GETOPT_WRAPPER) // The following series of defines end up causing the source file // that happens to include "herc_getopt.h" to end up calling HERC's // version of getopt instead of the normal system getopt. #define getopt herc_getopt #define optarg herc_optarg #define optind herc_optind #define optopt herc_optopt #define optreset herc_optreset int herc_getopt(int,char * const *,const char *); #if defined(HAVE_GETOPT_LONG) #define getopt_long herc_getopt_long struct option; // (fwd ref) int herc_getopt_long(int,char * const *,const char *,const struct option *,int *); #endif extern char *herc_optarg; extern int herc_optind; extern int herc_opterr; extern int herc_optopt; extern int herc_optreset; #endif /* defined(NEED_GETOPT_WRAPPER) */ #endif /* __HERC_GETOPT_H__ */ hercules-3.07/hercifc.c000644 000765 000765 00000016727 11321734033 016524 0ustar00jmaynardjmaynard000000 000000 // ==================================================================== // Hercules Interface Configuration Program // ==================================================================== // // Copyright (C) Copyright Roger Bowler, 2000-2009 // (C) Copyright James A. Pierson, 2002-2009 // // Based on code originally written by Roger Bowler // Modified to communicate via unix sockets. // // This module configures the TUN/TAP interface for Hercules. // It is invoked as a setuid root program by tuntap.c // // The are no command line arguments anymore. // // Error messages are written to stderr, which is redirected to // the Hercules message log by ctcadpt.c // // The exit status is zero if successful, non-zero if error. // // $Id: hercifc.c 5585 2009-12-30 22:40:19Z rbowler $ #include "hercules.h" #if defined(BUILD_HERCIFC) #include "hercifc.h" // -------------------------------------------------------------------- // HERCIFC program entry point // -------------------------------------------------------------------- int main( int argc, char **argv ) { char* pszProgName = NULL; // Name of this program char* pOp = NULL; // Operation text char* pIF = NULL; // -> interface name void* pArg = NULL; // -> ifreq or rtentry CTLREQ ctlreq; // Request Buffer int sockfd; // Socket descriptor int fd; // FD for ioctl int rc; // Return code pid_t ppid; // Parent's PID int answer; // 1 = write answer to stdout char szMsgBuffer[255]; UNREFERENCED( argc ); DROP_PRIVILEGES(CAP_NET_ADMIN); pszProgName = strdup( argv[0] ); // Must not be run from the commandline if( isatty( STDIN_FILENO ) ) { fprintf( stderr, _("HHCIF001E %s: Must be called from within Hercules.\n"), pszProgName ); exit( 1 ); } // Obtain a socket for ioctl operations sockfd = socket( AF_INET, SOCK_DGRAM, 0 ); if( sockfd < 0 ) { fprintf( stderr, _("HHCIF002E %s: Cannot obtain socket: %s\n"), pszProgName, strerror( errno ) ); exit( 2 ); } ppid = getppid(); // Process ioctl messages from Hercules while( 1 ) { rc = read( STDIN_FILENO, &ctlreq, CTLREQ_SIZE ); if( rc == -1 ) { fprintf( stderr, _("HHCIF003E %s: I/O error on read: %s.\n"), pszProgName, strerror( errno ) ); exit( 3 ); } if( ppid != getppid() ) { sleep( 1 ); // Let other messages go first fprintf( stderr, _("HHCIF007E %s: Hercules disappeared!! .. exiting\n"), pszProgName); exit( 4 ); } fd = sockfd; answer = 0; switch( ctlreq.iCtlOp ) { case TUNSETIFF: pOp = "TUNSETIFF"; pArg = &ctlreq.iru.ifreq; pIF = "?"; fd = ctlreq.iProcID; answer = 1; break; case SIOCSIFADDR: pOp = "SIOCSIFADDR"; pArg = &ctlreq.iru.ifreq; pIF = ctlreq.iru.ifreq.ifr_name; break; case SIOCSIFDSTADDR: pOp = "SIOCSIFDSTADDR"; pArg = &ctlreq.iru.ifreq; pIF = ctlreq.iru.ifreq.ifr_name; break; case SIOCSIFFLAGS: pOp = "SIOCSIFFLAGS"; pArg = &ctlreq.iru.ifreq; pIF = ctlreq.iru.ifreq.ifr_name; break; #if 0 /* (hercifc can't "get" information, only "set" it) */ case SIOCGIFFLAGS: pOp = "SIOCGIFFLAGS"; pArg = &ctlreq.iru.ifreq; pIF = ctlreq.iru.ifreq.ifr_name; answer = 1; break; #endif /* (caller should do 'ioctl' directly themselves instead) */ case SIOCSIFMTU: pOp = "SIOCSIFMTU"; pArg = &ctlreq.iru.ifreq; pIF = ctlreq.iru.ifreq.ifr_name; break; case SIOCADDMULTI: pOp = "SIOCADDMULTI"; pArg = &ctlreq.iru.ifreq; pIF = ctlreq.iru.ifreq.ifr_name; break; case SIOCDELMULTI: pOp = "SIOCDELMULTI"; pArg = &ctlreq.iru.ifreq; pIF = ctlreq.iru.ifreq.ifr_name; break; #ifdef OPTION_TUNTAP_SETNETMASK case SIOCSIFNETMASK: pOp = "SIOCSIFNETMASK"; pArg = &ctlreq.iru.ifreq; pIF = ctlreq.iru.ifreq.ifr_name; break; #endif #ifdef OPTION_TUNTAP_SETMACADDR case SIOCSIFHWADDR: pOp = "SIOCSIFHWADDR"; pArg = &ctlreq.iru.ifreq; pIF = ctlreq.iru.ifreq.ifr_name; break; #endif #ifdef OPTION_TUNTAP_DELADD_ROUTES case SIOCADDRT: pOp = "SIOCADDRT"; pArg = &ctlreq.iru.rtentry; pIF = ctlreq.szIFName; ctlreq.iru.rtentry.rt_dev = ctlreq.szIFName; break; case SIOCDELRT: pOp = "SIOCDELRT"; pArg = &ctlreq.iru.rtentry; pIF = ctlreq.szIFName; ctlreq.iru.rtentry.rt_dev = ctlreq.szIFName; break; #endif #ifdef OPTION_TUNTAP_CLRIPADDR case SIOCDIFADDR: pOp = "SIOCDIFADDR"; pArg = &ctlreq.iru.ifreq; pIF = ctlreq.iru.ifreq.ifr_name; break; #endif case CTLREQ_OP_DONE: close( STDIN_FILENO ); close( STDOUT_FILENO ); close( STDERR_FILENO ); exit( 0 ); default: snprintf( szMsgBuffer,sizeof(szMsgBuffer), _("HHCIF004W %s: Unknown request: %lX\n"), pszProgName, ctlreq.iCtlOp ); write( STDERR_FILENO, szMsgBuffer, strlen( szMsgBuffer ) ); continue; } #if defined(DEBUG) || defined(_DEBUG) snprintf( szMsgBuffer,sizeof(szMsgBuffer), _("HHCIF006I %s: Doing %s on %s\n"), pszProgName, pOp, pIF); write( STDERR_FILENO, szMsgBuffer, strlen( szMsgBuffer ) ); #endif /*defined(DEBUG) || defined(_DEBUG)*/ rc = ioctl( fd, ctlreq.iCtlOp, pArg ); if( rc < 0 ) { if (1 #if defined(SIOCSIFHWADDR) && defined(ENOTSUP) /* Suppress spurious error message */ && !(ctlreq.iCtlOp == SIOCSIFHWADDR && errno == ENOTSUP) #endif #if defined(SIOCDIFADDR) && defined(EINVAL) /* Suppress spurious error message */ && !(ctlreq.iCtlOp == SIOCDIFADDR && errno == EINVAL) #endif #if defined(TUNSETIFF) && defined(EINVAL) /* Suppress spurious error message */ && !(ctlreq.iCtlOp == TUNSETIFF && errno == EINVAL) #endif ) { snprintf( szMsgBuffer,sizeof(szMsgBuffer), _("HHCIF005E %s: ioctl error doing %s on %s: %d %s\n"), pszProgName, pOp, pIF, errno, strerror( errno ) ); write( STDERR_FILENO, szMsgBuffer, strlen( szMsgBuffer ) ); } } else if (answer) { write( STDOUT_FILENO, &ctlreq, CTLREQ_SIZE ); } } // Never reached. return 0; } #endif // defined(BUILD_HERCIFC) hercules-3.07/hercifc.h000644 000765 000765 00000006726 11143760542 016535 0ustar00jmaynardjmaynard000000 000000 // ==================================================================== // Hercules Interface Control Program // ==================================================================== // // Copyright (C) Copyright Roger Bowler, 2000-2009 // (C) Copyright James A. Pierson, 2002-2009 // // $Id: hercifc.h 5125 2009-01-23 12:01:44Z bernard $ // // $Log$ // Revision 1.14 2008/02/07 00:29:04 rbowler // Solaris build support by Jeff Savit // // Revision 1.13 2007/06/23 00:04:10 ivan // Update copyright notices to include current year (2007) // // Revision 1.12 2006/12/08 09:43:25 jj // Add CVS message log // #if defined(NEED_HERCIFC_H) #ifndef __HERCIFC_H_ #define __HERCIFC_H_ #if ( (!defined(WIN32) && \ !(defined(HAVE_LINUX_IF_TUN_H) || defined(HAVE_NET_IF_H)) ) || \ (defined(WIN32) && !defined(HAVE_NET_IF_H)) ) struct ifreq { union { char ifrn_name[IFNAMSIZ]; // (interface name) } ifr_ifrn; union { struct sockaddr ifru_addr; // (IP address) struct sockaddr ifru_netmask; // (network mask) struct sockaddr ifru_hwaddr; // (MAC address) short int ifru_flags; // (flags) int ifru_mtu; // (maximum transmission unit) } ifr_ifru; }; #define ifr_name ifr_ifrn.ifrn_name #define ifr_hwaddr ifr_ifru.ifru_hwaddr #define ifr_addr ifr_ifru.ifru_addr #define ifr_netmask ifr_ifru.ifru_netmask #define ifr_flags ifr_ifru.ifru_flags #define ifr_mtu ifr_ifru.ifru_mtu #endif #if ( !defined(WIN32) && !defined(HAVE_LINUX_IF_TUN_H) ) || \ ( defined(OPTION_W32_CTCI) ) /* Ioctl defines */ #define TUNSETNOCSUM _IOW('T', 200, int) #define TUNSETDEBUG _IOW('T', 201, int) #define TUNSETIFF _IOW('T', 202, int) #define TUNSETPERSIST _IOW('T', 203, int) #define TUNSETOWNER _IOW('T', 204, int) /* TUNSETIFF ifr flags */ #define IFF_TUN 0x0001 #define IFF_TAP 0x0002 #define IFF_NO_PI 0x1000 #define IFF_ONE_QUEUE 0x2000 #endif #if !defined(HAVE_NET_IF_H) /* Standard interface flags. */ #define IFF_UP 0x1 /* interface is up */ #define IFF_BROADCAST 0x2 /* broadcast address valid */ #define IFF_LOOPBACK 0x8 /* is a loopback net */ #define IFF_NOTRAILERS 0x20 /* avoid use of trailers */ #define IFF_RUNNING 0x40 /* resources allocated */ #define IFF_PROMISC 0x100 /* receive all packets */ #define IFF_MULTICAST 0x1000 /* Supports multicast */ #endif // -------------------------------------------------------------------- // Definition of the control request structure // -------------------------------------------------------------------- #define HERCIFC_CMD "hercifc" // Interface config command #define HERCTUN_DEV "/dev/net/tun" // Default TUN/TAP char dev typedef struct _CTLREQ { long iType; int iProcID; unsigned long int iCtlOp; char szIFName[IFNAMSIZ]; union { struct ifreq ifreq; #if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__SOLARIS__) struct rtentry rtentry; #endif } iru; } CTLREQ, *PCTLREQ; #define CTLREQ_SIZE sizeof( CTLREQ ) #define CTLREQ_OP_DONE 0 #endif // __HERCIFC_H_ #endif // #if defined(NEED_HERCIFC_H) hercules-3.07/herclin.c000644 000765 000765 00000007041 11143760544 016542 0ustar00jmaynardjmaynard000000 000000 /************************************************/ /* (C) Copyright 2005-2009 Roger Bowler & Others*/ /* Initial author : Ivan Warren */ /* */ /* HERCLIN.C */ /* */ /* THIS IS SAMPLE CODE DEMONSTRATING */ /* THE USE OF THE INITIAL HARDWARE PANEL */ /* INTERFACE FEATURE. */ /************************************************/ // $Id: herclin.c 5125 2009-01-23 12:01:44Z bernard $ // // $Log$ // Revision 1.5 2007/06/23 00:04:10 ivan // Update copyright notices to include current year (2007) // // Revision 1.4 2006/12/08 09:43:25 jj // Add CVS message log // #ifdef _MSVC_ #include #include #endif #include #include #include #include "hextapi.h" #if defined(HDL_USE_LIBTOOL) /* This must be included if HDL uses the */ /* libtool ltdl convenience library */ #include "ltdl.h" #endif /**********************************************/ /* The following function is the LOG callback */ /* function. It gets called by the engine */ /* whenever a log message needs to be */ /* displayed. This function may therefore be */ /* invoked from a separate thread */ /* */ /* This simple version simply writes to STDOUT*/ /**********************************************/ #ifdef _MSVC_ static HANDLE hLogCallbackThread = NULL; #endif void mywrite(const char *a,size_t b) { #ifdef _MSVC_ if (!hLogCallbackThread) hLogCallbackThread = OpenThread( SYNCHRONIZE, FALSE, GetCurrentThreadId()); #endif fflush(stdout); fwrite(a,b,1,stdout); fflush(stdout); } int main(int ac,char **av) { /*****************************************/ /* COMMANDHANDLER is the function type */ /* of the engine's panel command handler */ /* this MUST be resolved at run time */ /* since some HDL module might have */ /* redirected the initial engine function*/ /*****************************************/ COMMANDHANDLER ch; char *str,*bfr; #if defined( OPTION_DYNAMIC_LOAD ) && defined( HDL_USE_LIBTOOL ) /* LTDL Preloaded symbols for HDL using libtool */ LTDL_SET_PRELOADED_SYMBOLS(); #endif /******************************************/ /* Register the 'mywrite' function as the */ /* log callback routine */ /******************************************/ registerLogCallback(mywrite); /******************************************/ /* Initialize the HERCULE Engine */ /******************************************/ impl(ac,av); /******************************************/ /* Get the command handler function */ /* This MUST be done after IML */ /******************************************/ ch=getCommandHandler(); /******************************************/ /* Read STDIN and pass to Command Handler */ /******************************************/ bfr=(char *)malloc(1024); while ( #ifdef _MSVC_ !hLogCallbackThread || WaitForSingleObject(hLogCallbackThread,0) != WAIT_OBJECT_0 #else 1 #endif ) { #ifdef _MSVC_ if (!kbhit()) Sleep(50); else #endif if ((str=fgets(bfr,1024,stdin))) { str[strlen(str)-1]=0; ch(str); } } #ifdef _MSVC_ CloseHandle(hLogCallbackThread); #endif return 0; } hercules-3.07/herclogo.txt000644 000765 000765 00000002114 11143760542 017307 0ustar00jmaynardjmaynard000000 000000 @ALIGN NONE @SBA 0,0 @SF P Hercules Version : @SF HP $(VERSION) @NL @SF P Host name : @SF HP $(HOSTNAME) @NL @SF P Host OS : @SF HP $(HOSTOS)-$(HOSTOSREL) $(HOSTOSVER) @NL @SF P Host Architecture : @SF HP $(HOSTARCH) @NL @SF P Processors : @SF HP $(HOSTNUMCPUS) @NL @SF P Chanl Subsys : @SF HP $(CSS) @NL @SF P Device number : @SF HP $(CCUU) @NL @SF P Subchannel : @SF HP $(SUBCHAN) @SF P @ALIGN LEFT HHH HHH The S/370, ESA/390 and z/Architecture HHH HHH Emulator HHH HHH HHH HHH EEEE RRR CCC U U L EEEE SSS HHHHHHHHHHHHHHHH E R R C U U L E S HHHHHHHHHHHHHHHH EEE RRR C U U L EEE SS HHHHHHHHHHHHHHHH E R R C U U L E S HHH HHH EEEE R R CCC UU LLLL EEEE SSS HHH HHH HHH HHH HHH HHH My PC thinks it's a MAINFRAME Copyright (c) 1999-2009 Roger Bowler, Jan Jaeger, and others hercules-3.07/hercules.cnf000644 000765 000765 00000013107 11202676511 017250 0ustar00jmaynardjmaynard000000 000000 # # Sample configuration file for Hercules ESA/390 emulator # # $Id: hercules.cnf 5334 2009-04-19 20:37:29Z rbowler $ # # $Log$ # Revision 1.26 2009/01/14 14:45:20 jj # hercules command table now also used for config commands # # Revision 1.25 2008/12/01 16:19:49 jj # Check for licensed operating systems without impairing architectural # compliance of IFL's # # Revision 1.24 2006/12/08 09:43:25 jj # Add CVS message log # #------------------------------------------------------------------------------ # CPU Configuration #------------------------------------------------------------------------------ CPUSERIAL 002623 # CPU serial number CPUMODEL 3090 # CPU model number MODEL EMULATOR # STSI returned model PLANT ZZ # STSI returned plant MANUFACTURER HRC # STSI returned manufacturer LPARNAME HERCULES # DIAG 204 returned lparname CPUVERID FD # CPU Version Identification MAINSIZE 64 # Main storage size in megabytes XPNDSIZE 0 # Expanded storage size in megabytes NUMCPU 1 # Number of CPUs # NUMVEC 1 # Number of Vector Processors MAXCPU 8 # Maximum number of CPUs ARCHMODE ESA/390 # Architecture mode S/370, ESA/390 or z/Arch ALRF DISABLE # ASN-and-LX-Reuse facility ECPSVM NO # VM Assist : NO or Level (20 recommended) #------------------------------------------------------------------------------ # OS Tailoring #------------------------------------------------------------------------------ LOADPARM 0120.... # IPL parameter OSTAILOR LINUX # OS tailoring SYSEPOCH 1900 # Base year for initial TOD clock # TZOFFSET 0 # Using UTC (GMT) #------------------------------------------------------------------------------ # Hercules Service Processor and Hercules Application Window #------------------------------------------------------------------------------ # MODPATH /usr/local/lib/hercules # Where to search for modules # LDMOD dyninst tcpip # Modules to be loaded #------------------------------------------------------------------------------ # Hercules Service Processor and Hercules Application Window #------------------------------------------------------------------------------ CODEPAGE default # CodePage conversion table DIAG8CMD disable # OS may not issue commands via DIAG 8 HTTPPORT 8081 noauth userid password # HTTP server port # HTTPROOT /usr/local/share/hercules/ # HTTP root directory PANRATE FAST # Panel refresh rate #------------------------------------------------------------------------------- # Advanced Hercules Performance Tailoring # # +----------------------------------------------------------------+ # | Caution: Modification of these parameters may adversely | # | affect the performance of the host system | # | and/or Hercules. | # +----------------------------------------------------------------+ #------------------------------------------------------------------------------- # HERCPRIO 0 # Hercules process runs at Normal priority # CPUPRIO 15 # CPU thread(s) run at Low priority # DEVPRIO 8 # Device thread(s) run at Below Normal priority # TODPRIO -20 # TOD Clock and timer thread are Time Critical #------------------------------------------------------------------------------- # Integrated Hercules I/O Controller # # DEVTMAX 0 # Device threads, 8 on Windows, else unlimited CNSLPORT 3270 # TCP port number to which consoles connect # SHRDPORT 3990 # TCP port number for sharing DASD images on # this instance of Hercules (inactive) # .-----------------------Device number # | .-----------------Device type # | | .---------File name and parameters # | | | # V V V # ---- ---- -------------------- 0009 3215-C / noprompt 000C 3505 ./util/zzsacard.bin 000D 3525 punch00d.txt ascii 000E 1403 print00e.txt crlf 001F 3270 # The following statements are examples. Some of them require # user tailoring before being used. # 0580 3420 ickdsf.ipl # 0120 3380 mvsv5r.120 # 0121 3380 mvsv5d.121 # 0122 3380 mvswk1.122 # 0140 9336 dosres.140 # 0141 9336 syswk1.141 # # The following statement defines 3 3270 devices starting # at address 0200 # 0200.3 3270 # # The following statement defines 3480 devices # at addresses 0280 to 028F # 280-28F 3480 # # The following statement defines 3420 devices # at addresses 02C0 & 02C2 # 2C0,2C2 3420 # 0300 3370 sysres.300 # # The following statements define 3380 Devices # with the CUU substituted in the device file name # device file names will be # 400.3380, 401.3380, 402.3380 and 403.3380 # 400-403 3380 $(CUU).3380 # # CCUU may also be used to define a 4 digit device address # in the name # device file names will be # 0480.3380, 0481.3380, 0482.3380 and 0483.3380 # 480-483 3380 $(CCUU).3380 # # 0700 3270 hercules-3.07/Hercules.dsp000644 000765 000765 00000046035 11143760544 017242 0ustar00jmaynardjmaynard000000 000000 # Microsoft Developer Studio Project File - Name="Hercules" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) External Target" 0x0106 CFG=Hercules - Win32 Debug_DLL_Modules !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "Hercules.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "Hercules.mak" CFG="Hercules - Win32 Debug_DLL_Modules" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "Hercules - Win32 Retail_Static" (based on "Win32 (x86) External Target") !MESSAGE "Hercules - Win32 Debug_Static" (based on "Win32 (x86) External Target") !MESSAGE "Hercules - Win32 Retail_DLL" (based on "Win32 (x86) External Target") !MESSAGE "Hercules - Win32 Debug_DLL" (based on "Win32 (x86) External Target") !MESSAGE "Hercules - Win32 Retail_DLL_Modules" (based on "Win32 (x86) External Target") !MESSAGE "Hercules - Win32 Debug_DLL_Modules" (based on "Win32 (x86) External Target") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" !IF "$(CFG)" == "Hercules - Win32 Retail_Static" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "msvc.bin" # PROP BASE Intermediate_Dir "msvc.obj" # PROP BASE Cmd_Line "makefile.bat RETAIL makefile.msvc 8" # PROP BASE Rebuild_Opt "-a" # PROP BASE Target_File "Hercules.exe" # PROP BASE Bsc_Name "" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "msvc.bin" # PROP Intermediate_Dir "msvc.obj" # PROP Cmd_Line "makefile.bat RETAIL makefile.msvc 8" # PROP Rebuild_Opt "-a" # PROP Target_File "Hercules.exe" # PROP Bsc_Name "" # PROP Target_Dir "" !ELSEIF "$(CFG)" == "Hercules - Win32 Debug_Static" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "msvc.debug.bin" # PROP BASE Intermediate_Dir "msvc.debug.obj" # PROP BASE Cmd_Line "makefile.bat DEBUG makefile.msvc 8" # PROP BASE Rebuild_Opt "-a" # PROP BASE Target_File "Hercules.exe" # PROP BASE Bsc_Name "" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "msvc.debug.bin" # PROP Intermediate_Dir "msvc.debug.obj" # PROP Cmd_Line "makefile.bat DEBUG makefile.msvc 8" # PROP Rebuild_Opt "-a" # PROP Target_File "Hercules.exe" # PROP Bsc_Name "" # PROP Target_Dir "" !ELSEIF "$(CFG)" == "Hercules - Win32 Retail_DLL" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "msvc.dll.bin" # PROP BASE Intermediate_Dir "msvc.dll.obj" # PROP BASE Cmd_Line "makefile.bat RETAIL makefile-dll.msvc 8" # PROP BASE Rebuild_Opt "-a" # PROP BASE Target_File "Hercules.exe" # PROP BASE Bsc_Name "" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "msvc.dll.bin" # PROP Intermediate_Dir "msvc.dll.obj" # PROP Cmd_Line "makefile.bat RETAIL makefile-dll.msvc 8" # PROP Rebuild_Opt "-a" # PROP Target_File "Hercules.exe" # PROP Bsc_Name "" # PROP Target_Dir "" !ELSEIF "$(CFG)" == "Hercules - Win32 Debug_DLL" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "msvc.debug.dll.bin" # PROP BASE Intermediate_Dir "msvc.debug.dll.obj" # PROP BASE Cmd_Line "makefile.bat DEBUG makefile-dll.msvc 8" # PROP BASE Rebuild_Opt "-a" # PROP BASE Target_File "Hercules.exe" # PROP BASE Bsc_Name "" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "msvc.debug.dll.bin" # PROP Intermediate_Dir "msvc.debug.dll.obj" # PROP Cmd_Line "makefile.bat DEBUG makefile-dll.msvc 8" # PROP Rebuild_Opt "-a" # PROP Target_File "Hercules.exe" # PROP Bsc_Name "" # PROP Target_Dir "" !ELSEIF "$(CFG)" == "Hercules - Win32 Retail_DLL_Modules" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "msvc.dllmod.bin" # PROP BASE Intermediate_Dir "msvc.dllmod.obj" # PROP BASE Cmd_Line "makefile.bat RETAIL makefile-dllmod.msvc 8" # PROP BASE Rebuild_Opt "-a" # PROP BASE Target_File "Hercules.exe" # PROP BASE Bsc_Name "" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "msvc.dllmod.bin" # PROP Intermediate_Dir "msvc.dllmod.obj" # PROP Cmd_Line "makefile.bat RETAIL makefile-dllmod.msvc 8" # PROP Rebuild_Opt "-a" # PROP Target_File "Hercules.exe" # PROP Bsc_Name "" # PROP Target_Dir "" !ELSEIF "$(CFG)" == "Hercules - Win32 Debug_DLL_Modules" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "msvc.debug.dllmod.bin" # PROP BASE Intermediate_Dir "msvc.debug.dllmod.obj" # PROP BASE Cmd_Line "makefile.bat DEBUG makefile-dllmod.msvc 8" # PROP BASE Rebuild_Opt "-a" # PROP BASE Target_File "Hercules.exe" # PROP BASE Bsc_Name "" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "msvc.debug.dllmod.bin" # PROP Intermediate_Dir "msvc.debug.dllmod.obj" # PROP Cmd_Line "makefile.bat DEBUG makefile-dllmod.msvc 8" # PROP Rebuild_Opt "-a" # PROP Target_File "Hercules.exe" # PROP Bsc_Name "" # PROP Target_Dir "" !ENDIF # Begin Target # Name "Hercules - Win32 Retail_Static" # Name "Hercules - Win32 Debug_Static" # Name "Hercules - Win32 Retail_DLL" # Name "Hercules - Win32 Debug_DLL" # Name "Hercules - Win32 Retail_DLL_Modules" # Name "Hercules - Win32 Debug_DLL_Modules" !IF "$(CFG)" == "Hercules - Win32 Retail_Static" !ELSEIF "$(CFG)" == "Hercules - Win32 Debug_Static" !ELSEIF "$(CFG)" == "Hercules - Win32 Retail_DLL" !ELSEIF "$(CFG)" == "Hercules - Win32 Debug_DLL" !ELSEIF "$(CFG)" == "Hercules - Win32 Retail_DLL_Modules" !ELSEIF "$(CFG)" == "Hercules - Win32 Debug_DLL_Modules" !ENDIF # Begin Group "Resource Files" # PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" # Begin Source File SOURCE=.\dyngui.rc # End Source File # End Group # Begin Group "Other Files" # PROP Default_Filter "" # Begin Source File SOURCE=.\_build # End Source File # Begin Source File SOURCE=.\_build.bat # End Source File # Begin Source File SOURCE=.\_build.tail # End Source File # Begin Source File SOURCE=".\ABOUT-NLS" # End Source File # Begin Source File SOURCE=.\autogen.sh # End Source File # Begin Source File SOURCE=.\CHANGES # End Source File # Begin Source File SOURCE=.\configure.ac # End Source File # Begin Source File SOURCE=.\COPYRIGHT # End Source File # Begin Source File SOURCE=.\hercules.cnf # End Source File # Begin Source File SOURCE=.\INSTALL # End Source File # Begin Source File SOURCE=".\makefile-dll.msvc" # End Source File # Begin Source File SOURCE=".\makefile-dllmod.msvc" # End Source File # Begin Source File SOURCE=.\Makefile.am # End Source File # Begin Source File SOURCE=.\makefile.bat # End Source File # Begin Source File SOURCE=.\makefile.generic # End Source File # Begin Source File SOURCE=.\makefile.msvc # End Source File # Begin Source File SOURCE=.\makefile.w32 # End Source File # Begin Source File SOURCE=.\README.COMMADPT # End Source File # Begin Source File SOURCE=.\README.CVS # End Source File # Begin Source File SOURCE=.\README.ECPSVM # End Source File # Begin Source File SOURCE=.\README.HDL # End Source File # Begin Source File SOURCE=.\README.ISSUES # End Source File # Begin Source File SOURCE=.\README.MINGW # End Source File # Begin Source File SOURCE=.\README.MSVC # End Source File # Begin Source File SOURCE=.\README.NETWORKING # End Source File # Begin Source File SOURCE=.\README.OSX # End Source File # Begin Source File SOURCE=.\README.TAPE # End Source File # Begin Source File SOURCE=.\RELEASE.NOTES # End Source File # Begin Source File SOURCE=".\stamp-h.in" # End Source File # End Group # Begin Source File SOURCE=.\assist.c # End Source File # Begin Source File SOURCE=.\AutoBuildCount.h # End Source File # Begin Source File SOURCE=.\bldcfg.c # End Source File # Begin Source File SOURCE=.\bootstrap.c # End Source File # Begin Source File SOURCE=.\build_pch.c # End Source File # Begin Source File SOURCE=.\cache.c # End Source File # Begin Source File SOURCE=.\cache.h # End Source File # Begin Source File SOURCE=.\cardpch.c # End Source File # Begin Source File SOURCE=.\cardrdr.c # End Source File # Begin Source File SOURCE=.\cckdcdsk.c # End Source File # Begin Source File SOURCE=.\cckdcomp.c # End Source File # Begin Source File SOURCE=.\cckddasd.c # End Source File # Begin Source File SOURCE=.\cckddiag.c # End Source File # Begin Source File SOURCE=.\cckdfix.c # End Source File # Begin Source File SOURCE=.\cckdswap.c # End Source File # Begin Source File SOURCE=.\cckdutil.c # End Source File # Begin Source File SOURCE=.\cgibin.c # End Source File # Begin Source File SOURCE=.\channel.c # End Source File # Begin Source File SOURCE=.\chsc.c # End Source File # Begin Source File SOURCE=.\chsc.h # End Source File # Begin Source File SOURCE=.\ckddasd.c # End Source File # Begin Source File SOURCE=.\cmpsc.c # End Source File # Begin Source File SOURCE=.\codepage.c # End Source File # Begin Source File SOURCE=.\codepage.h # End Source File # Begin Source File SOURCE=.\commadpt.c # End Source File # Begin Source File SOURCE=.\commadpt.h # End Source File # Begin Source File SOURCE=.\con1052c.c # End Source File # Begin Source File SOURCE=.\config.c # End Source File # Begin Source File SOURCE=.\console.c # End Source File # Begin Source File SOURCE=.\control.c # End Source File # Begin Source File SOURCE=.\cpu.c # End Source File # Begin Source File SOURCE=.\cpuint.h # End Source File # Begin Source File SOURCE=.\crypto.c # End Source File # Begin Source File SOURCE=.\crypto.h # End Source File # Begin Source File SOURCE=.\ctc_ctci.c # End Source File # Begin Source File SOURCE=.\ctc_lcs.c # End Source File # Begin Source File SOURCE=.\ctcadpt.c # End Source File # Begin Source File SOURCE=.\ctcadpt.h # End Source File # Begin Source File SOURCE=.\dasdblks.h # End Source File # Begin Source File SOURCE=.\dasdcat.c # End Source File # Begin Source File SOURCE=.\dasdconv.c # End Source File # Begin Source File SOURCE=.\dasdcopy.c # End Source File # Begin Source File SOURCE=.\dasdinit.c # End Source File # Begin Source File SOURCE=.\dasdisup.c # End Source File # Begin Source File SOURCE=.\dasdload.c # End Source File # Begin Source File SOURCE=.\dasdls.c # End Source File # Begin Source File SOURCE=.\dasdpdsu.c # End Source File # Begin Source File SOURCE=.\dasdseq.c # End Source File # Begin Source File SOURCE=.\dasdtab.c # End Source File # Begin Source File SOURCE=.\dasdtab.h # End Source File # Begin Source File SOURCE=.\dasdutil.c # End Source File # Begin Source File SOURCE=.\dat.c # End Source File # Begin Source File SOURCE=.\dat.h # End Source File # Begin Source File SOURCE=.\decimal.c # End Source File # Begin Source File SOURCE=.\devtype.h # End Source File # Begin Source File SOURCE=.\dfp.c # End Source File # Begin Source File SOURCE=.\diagmssf.c # End Source File # Begin Source File SOURCE=.\diagnose.c # End Source File # Begin Source File SOURCE=.\dmap2hrc.c # End Source File # Begin Source File SOURCE=.\dyngui.c # End Source File # Begin Source File SOURCE=.\dynguib.h # End Source File # Begin Source File SOURCE=.\dynguip.h # End Source File # Begin Source File SOURCE=.\dynguiv.h # End Source File # Begin Source File SOURCE=.\dyninst.c # End Source File # Begin Source File SOURCE=.\ecpsvm.c # End Source File # Begin Source File SOURCE=.\ecpsvm.h # End Source File # Begin Source File SOURCE=.\esa390.h # End Source File # Begin Source File SOURCE=.\esame.c # End Source File # Begin Source File SOURCE=.\external.c # End Source File # Begin Source File SOURCE=.\fbadasd.c # End Source File # Begin Source File SOURCE=.\feat370.h # End Source File # Begin Source File SOURCE=.\feat390.h # End Source File # Begin Source File SOURCE=.\feat900.h # End Source File # Begin Source File SOURCE=.\featall.h # End Source File # Begin Source File SOURCE=.\featchk.h # End Source File # Begin Source File SOURCE=.\feature.h # End Source File # Begin Source File SOURCE=.\fillfnam.c # End Source File # Begin Source File SOURCE=.\fillfnam.h # End Source File # Begin Source File SOURCE=.\fishhang.c # End Source File # Begin Source File SOURCE=.\fishhang.h # End Source File # Begin Source File SOURCE=.\float.c # End Source File # Begin Source File SOURCE=.\fthreads.c # End Source File # Begin Source File SOURCE=.\fthreads.h # End Source File # Begin Source File SOURCE=.\general1.c # End Source File # Begin Source File SOURCE=.\general2.c # End Source File # Begin Source File SOURCE=.\general3.c # End Source File # Begin Source File SOURCE=.\getopt.c # End Source File # Begin Source File SOURCE=.\getopt.h # End Source File # Begin Source File SOURCE=.\hbyteswp.h # End Source File # Begin Source File SOURCE=.\hchan.c # End Source File # Begin Source File SOURCE=.\hchan.h # End Source File # Begin Source File SOURCE=.\hconsole.c # End Source File # Begin Source File SOURCE=.\hconsole.h # End Source File # Begin Source File SOURCE=.\hconsts.h # End Source File # Begin Source File SOURCE=.\hdl.c # End Source File # Begin Source File SOURCE=.\hdl.h # End Source File # Begin Source File SOURCE=.\hdlmain.c # End Source File # Begin Source File SOURCE=.\hdteq.c # End Source File # Begin Source File SOURCE=.\herc_getopt.h # End Source File # Begin Source File SOURCE=.\hercifc.c # End Source File # Begin Source File SOURCE=.\hercifc.h # End Source File # Begin Source File SOURCE=.\herclin.c # End Source File # Begin Source File SOURCE=.\hercnls.h # End Source File # Begin Source File SOURCE=.\hercules.h # End Source File # Begin Source File SOURCE=.\hercwind.h # End Source File # Begin Source File SOURCE=.\hetget.c # End Source File # Begin Source File SOURCE=.\hetinit.c # End Source File # Begin Source File SOURCE=.\hetlib.c # End Source File # Begin Source File SOURCE=.\hetlib.h # End Source File # Begin Source File SOURCE=.\hetmap.c # End Source File # Begin Source File SOURCE=.\hetupd.c # End Source File # Begin Source File SOURCE=.\hextapi.h # End Source File # Begin Source File SOURCE=.\hexterns.h # End Source File # Begin Source File SOURCE=.\history.c # End Source File # Begin Source File SOURCE=.\history.h # End Source File # Begin Source File SOURCE=.\hmacros.h # End Source File # Begin Source File SOURCE=.\hostinfo.c # End Source File # Begin Source File SOURCE=.\hostinfo.h # End Source File # Begin Source File SOURCE=.\hostopts.h # End Source File # Begin Source File SOURCE=.\hsccmd.c # End Source File # Begin Source File SOURCE=.\hscmisc.c # End Source File # Begin Source File SOURCE=.\hscutl.c # End Source File # Begin Source File SOURCE=.\hscutl.h # End Source File # Begin Source File SOURCE=.\hscutl2.c # End Source File # Begin Source File SOURCE=.\hsocket.h # End Source File # Begin Source File SOURCE=.\hstdinc.h # End Source File # Begin Source File SOURCE=.\hstructs.h # End Source File # Begin Source File SOURCE=.\hsys.c # End Source File # Begin Source File SOURCE=.\hthreads.h # End Source File # Begin Source File SOURCE=.\httpmisc.h # End Source File # Begin Source File SOURCE=.\httpserv.c # End Source File # Begin Source File SOURCE=.\htypes.h # End Source File # Begin Source File SOURCE=".\ieee-w32.h" # End Source File # Begin Source File SOURCE=.\ieee.c # End Source File # Begin Source File SOURCE=.\impl.c # End Source File # Begin Source File SOURCE=.\inline.h # End Source File # Begin Source File SOURCE=.\io.c # End Source File # Begin Source File SOURCE=.\ipl.c # End Source File # Begin Source File SOURCE=.\linklist.h # End Source File # Begin Source File SOURCE=.\loadparm.c # End Source File # Begin Source File SOURCE=.\logger.c # End Source File # Begin Source File SOURCE=.\logger.h # End Source File # Begin Source File SOURCE=.\logmsg.c # End Source File # Begin Source File SOURCE=.\losc.c # End Source File # Begin Source File SOURCE=.\ltdl.c # End Source File # Begin Source File SOURCE=.\ltdl.h # End Source File # Begin Source File SOURCE=.\machchk.c # End Source File # Begin Source File SOURCE=.\machdep.h # End Source File # Begin Source File SOURCE=.\memrchr.c # End Source File # Begin Source File SOURCE=.\memrchr.h # End Source File # Begin Source File SOURCE=.\opcode.c # End Source File # Begin Source File SOURCE=.\opcode.h # End Source File # Begin Source File SOURCE=.\panel.c # End Source File # Begin Source File SOURCE=.\parser.c # End Source File # Begin Source File SOURCE=.\parser.h # End Source File # Begin Source File SOURCE=.\pfpo.c # End Source File # Begin Source File SOURCE=.\plo.c # End Source File # Begin Source File SOURCE=.\printer.c # End Source File # Begin Source File SOURCE=.\pttrace.c # End Source File # Begin Source File SOURCE=.\pttrace.h # End Source File # Begin Source File SOURCE=.\qdio.c # End Source File # Begin Source File SOURCE=.\qeth.c # End Source File # Begin Source File SOURCE=.\scsitape.h # End Source File # Begin Source File SOURCE=.\service.c # End Source File # Begin Source File SOURCE=.\service.h # End Source File # Begin Source File SOURCE=.\shared.c # End Source File # Begin Source File SOURCE=.\shared.h # End Source File # Begin Source File SOURCE=.\sie.c # End Source File # Begin Source File SOURCE=.\sllib.c # End Source File # Begin Source File SOURCE=.\sllib.h # End Source File # Begin Source File SOURCE=.\sockdev.c # End Source File # Begin Source File SOURCE=.\sockdev.h # End Source File # Begin Source File SOURCE=.\sr.c # End Source File # Begin Source File SOURCE=.\sr.h # End Source File # Begin Source File SOURCE=.\stack.c # End Source File # Begin Source File SOURCE=.\strsignal.c # End Source File # Begin Source File SOURCE=.\tapecopy.c # End Source File # Begin Source File SOURCE=.\tapedev.c # End Source File # Begin Source File SOURCE=.\tapedev.h # End Source File # Begin Source File SOURCE=.\tapemap.c # End Source File # Begin Source File SOURCE=.\tapesplt.c # End Source File # Begin Source File SOURCE=.\timer.c # End Source File # Begin Source File SOURCE=.\trace.c # End Source File # Begin Source File SOURCE=.\tt32api.h # End Source File # Begin Source File SOURCE=.\tuntap.c # End Source File # Begin Source File SOURCE=.\tuntap.h # End Source File # Begin Source File SOURCE=.\vector.c # End Source File # Begin Source File SOURCE=.\version.c # End Source File # Begin Source File SOURCE=.\version.h # End Source File # Begin Source File SOURCE=.\vm.c # End Source File # Begin Source File SOURCE=.\vstore.c # End Source File # Begin Source File SOURCE=.\vstore.h # End Source File # Begin Source File SOURCE=.\w32chan.c # End Source File # Begin Source File SOURCE=.\w32chan.h # End Source File # Begin Source File SOURCE=.\w32ctca.c # End Source File # Begin Source File SOURCE=.\w32ctca.h # End Source File # Begin Source File SOURCE=.\w32dl.h # End Source File # Begin Source File SOURCE=.\w32ftol2.c # End Source File # Begin Source File SOURCE=.\w32util.c # End Source File # Begin Source File SOURCE=.\w32util.h # End Source File # Begin Source File SOURCE=.\xstore.c # End Source File # End Target # End Project hercules-3.07/Hercules.dsw000644 000765 000765 00000000777 11143760544 017254 0ustar00jmaynardjmaynard000000 000000 Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "Hercules"=".\Hercules.dsp" - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### hercules-3.07/hercules.h000644 000765 000765 00000011332 11143760543 016732 0ustar00jmaynardjmaynard000000 000000 /* HERCULES.H (c) Copyright Roger Bowler, 1999-2009 */ /* Hercules Header Files */ /* Interpretive Execution - (c) Copyright Jan Jaeger, 1999-2009 */ /* z/Architecture support - (c) Copyright Jan Jaeger, 1999-2009 */ // $Id: hercules.h 5125 2009-01-23 12:01:44Z bernard $ // // $Log$ // Revision 1.303 2009/01/02 19:21:51 jj // DVD-RAM IPL // RAMSAVE // SYSG Integrated 3270 console fixes // // Revision 1.302 2008/05/22 21:34:22 fish // Attempt to fix my *nix SCSI tape BSR over tapemark bug identified by Bob Schneider [bschneider@pingdata.net] // // Revision 1.301 2007/12/11 15:01:06 rbowler // Fix undefined gettimeofday in clock.h rev 1.27 (MSVC) // // Revision 1.300 2007/06/23 00:04:10 ivan // Update copyright notices to include current year (2007) // // Revision 1.299 2006/12/08 09:43:25 jj // Add CVS message log // #ifdef HAVE_CONFIG_H #include // Hercules build configuration options/settings #endif /*-------------------------------------------------------------------*/ /* Performance attribute: use registers to pass function parameters */ /* (must be #defined BEFORE "feature,h" since it uses it) */ /*-------------------------------------------------------------------*/ #if defined(HAVE_ATTR_REGPARM) #ifdef _MSVC_ #define ATTR_REGPARM(n) __fastcall #else /* GCC presumed */ #define ATTR_REGPARM(n) __attribute__ (( regparm(n) )) #endif #else #define ATTR_REGPARM(n) /* nothing */ #endif // ------------------------------------------------------------------- // // PROGRAMMING NOTE // // The "feature.h" header MUST be #included AFTER *AND* // BEFORE the _HERCULES_H pre-processor variable gets #defined. This // is to enure that it is ALWAYS #included regardless of whether the // "hercules.h" header has already been #included or not. This is so // the various architecture dependent source modules compile properly // since they #include themselves several times so as to cause them // to be compiled multiple times, each time with a new architecture // mode #defined (e.g. 370/390/900). See the very end of the source // member "general2.c" for a typical example of this very technique. // // ------------------------------------------------------------------- // // // Include standard system headers (if not already done) // #include "feature.h" // Hercules [manually maintained] features; // auto-includes featall.h and hostopts.h // ALWAYS include cpuint.h after feature.h // and also assure it is re-included for // each archs. #include "cpuint.h" #ifndef _HERCULES_H // MUST come AFTER "feature.h" is #included #define _HERCULES_H // MUST come AFTER "feature.h" is #included #include "hstdinc.h" // Precompilation-eligible header files #ifdef _MSVC_ #include "getopt.h" #else #if defined(HAVE_GETOPT_LONG) && !defined(__GETOPT_H__) #include #endif #endif #ifdef OPTION_DYNAMIC_LOAD #ifdef HDL_USE_LIBTOOL #include #else #if defined(__MINGW__) || defined(_MSVC_) #include "w32dl.h" #else #include #endif #endif #endif /////////////////////////////////////////////////////////////////////// // Private Hercules-specific headers..... /////////////////////////////////////////////////////////////////////// #include "linklist.h" // (Hercules-wide linked-list macros) #include "hconsts.h" // (Hercules-wide #define constants) #include "hthreads.h" // (Hercules-wide threading macros) #include "hmacros.h" // (Hercules-wide #define macros) #if !defined(HAVE_BYTESWAP_H) || defined(NO_ASM_BYTESWAP) #include "hbyteswp.h" // (Hercules equivalent of ) #endif #if !defined(HAVE_MEMRCHR) #include "memrchr.h" #endif #if defined(HAVE_ASSERT_H) #include #endif #include "hostinfo.h" #include "version.h" #include "esa390.h" // (ESA/390 structure definitions) #include "hscutl.h" // (utility functions) #include "w32util.h" // (win32 porting functions) #include "clock.h" // (TOD definitions) #include "codepage.h" #include "logger.h" // (logmsg, etc) #include "hdl.h" // (Hercules Dynamic Loader) #include "cache.h" #include "devtype.h" #include "dasdtab.h" #include "shared.h" #include "hetlib.h" #include "sockdev.h" #include "w32ctca.h" #include "service.h" #include "hsocket.h" #ifdef _MSVC_ #include "w32mtio.h" // 'mtio.h' needed by hstructs.h #endif // _MSVC_ #include "hstructs.h" // (Hercules-wide structures) #include "hexterns.h" // (Hercules-wide extern function prototypes) #endif // _HERCULES_H hercules-3.07/hercules.ico000644 000765 000765 00000005256 11143760543 017265 0ustar00jmaynardjmaynard000000 000000 (6 è^00hF( €€€€€€€€€€€€€ÀÀÀ˙˙˙˙˙˙˙˙˙˙˙˙"" (‚€"" (‚€"" (ˆˆˆ‚€""""" (ˆˆˆ‚€"" (‚€"" (‚€"" ˙˙ÇÇÇÇÇ€€€ÇÇÇÇÇ˙˙˙˙( @€€€€€€€€€€€€ÀÀÀ˙˙˙˙˙˙˙˙˙˙˙˙"" """""""" "" """" "" """""""" "" """" "" """""""" "" """" """""""""""""""""""""""" """""""""""""" "" """""""" "" """" "" """""""" "" """" "" """""""" "" ""˙˙˙˙˙˙˙˙˙˙˙˙ŝà?üŝĝ˙˙ŝà?üŝĝ˙˙ŝà?üŝĝ˙˙àĝ˙˙ŝà?üŝĝ˙˙ŝà?üŝĝ˙˙ŝà?üŝ˙˙˙˙˙˙˙˙(0`€€€€€€€€€€ÀÀÀ€€€˙˙˙˙˙˙˙˙˙˙˙˙"""" """ """"""""""" """""""" """""""" """ """" """" """"""""""" """""""" """""""" """ """" """" """"""""""" """""""" """""""" """ """"""" """""""""""""""""""""""""""""""""" """"""""""""""""" """"""""""""""""" """""""""""""""""""""""""""""""" """ """"""""""" """""""" """""""" """ """" """" """"""""""" """""""" """""""" """ """" """" """"""""""" """""""" """""""" """ """"""" ˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙ĝ?˙˙˙˙ŝ˙à˙ü˙à˙ü˙à˙ü˙˙ŝ˙ü˙˙˙˙ŝ˙à˙ü˙à˙ü˙à˙ü˙˙ŝ˙ü˙˙˙˙ŝ˙à˙ü˙à˙ü˙à˙ü˙˙ŝ˙ĝ?˙˙˙˙à˙à˙à˙˙ĝ˙˙ŝ˙à˙ü˙à˙ü˙à˙ü˙˙ŝ˙ü˙˙˙˙ŝ˙à˙ü˙à˙ü˙à˙ü˙˙ŝ˙ü˙˙˙˙ŝ˙à˙ü˙à˙ü˙à˙ü˙˙ŝ˙ĝ?˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙hercules-3.07/Hercules.sln000644 000765 000765 00000006561 11224164171 017242 0ustar00jmaynardjmaynard000000 000000 ïğż Microsoft Visual Studio Solution File, Format Version 10.00 # Visual Studio 2008 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Hercules", "Hercules.vcproj", "{A0F495FF-9C35-4DFB-A51A-0427D8420779}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Itanium = Debug|Itanium Debug|Win32 = Debug|Win32 Debug|x64 = Debug|x64 Release|Itanium = Release|Itanium Release|Win32 = Release|Win32 Release|x64 = Release|x64 Debug-All|Itanium = Debug-All|Itanium Debug-All|Win32 = Debug-All|Win32 Debug-All|x64 = Debug-All|x64 Release-All|Itanium = Release-All|Itanium Release-All|Win32 = Release-All|Win32 Release-All|x64 = Release-All|x64 All-All|Itanium = All-All|Itanium All-All|Win32 = All-All|Win32 All-All|x64 = All-All|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {A0F495FF-9C35-4DFB-A51A-0427D8420779}.Debug|Itanium.ActiveCfg = Debug|Itanium {A0F495FF-9C35-4DFB-A51A-0427D8420779}.Debug|Itanium.Build.0 = Debug|Itanium {A0F495FF-9C35-4DFB-A51A-0427D8420779}.Debug|Win32.ActiveCfg = Debug|Win32 {A0F495FF-9C35-4DFB-A51A-0427D8420779}.Debug|Win32.Build.0 = Debug|Win32 {A0F495FF-9C35-4DFB-A51A-0427D8420779}.Debug|x64.ActiveCfg = Debug|x64 {A0F495FF-9C35-4DFB-A51A-0427D8420779}.Debug|x64.Build.0 = Debug|x64 {A0F495FF-9C35-4DFB-A51A-0427D8420779}.Release|Itanium.ActiveCfg = Release|Itanium {A0F495FF-9C35-4DFB-A51A-0427D8420779}.Release|Itanium.Build.0 = Release|Itanium {A0F495FF-9C35-4DFB-A51A-0427D8420779}.Release|Win32.ActiveCfg = Release|Win32 {A0F495FF-9C35-4DFB-A51A-0427D8420779}.Release|Win32.Build.0 = Release|Win32 {A0F495FF-9C35-4DFB-A51A-0427D8420779}.Release|x64.ActiveCfg = Release|x64 {A0F495FF-9C35-4DFB-A51A-0427D8420779}.Release|x64.Build.0 = Release|x64 {A0F495FF-9C35-4DFB-A51A-0427D8420779}.Debug-All|Itanium.ActiveCfg = Debug-All|Itanium {A0F495FF-9C35-4DFB-A51A-0427D8420779}.Debug-All|Itanium.Build.0 = Debug-All|Itanium {A0F495FF-9C35-4DFB-A51A-0427D8420779}.Debug-All|Win32.ActiveCfg = Debug-All|Win32 {A0F495FF-9C35-4DFB-A51A-0427D8420779}.Debug-All|Win32.Build.0 = Debug-All|Win32 {A0F495FF-9C35-4DFB-A51A-0427D8420779}.Debug-All|x64.ActiveCfg = Debug-All|x64 {A0F495FF-9C35-4DFB-A51A-0427D8420779}.Debug-All|x64.Build.0 = Debug-All|x64 {A0F495FF-9C35-4DFB-A51A-0427D8420779}.Release-All|Itanium.ActiveCfg = Release-All|Itanium {A0F495FF-9C35-4DFB-A51A-0427D8420779}.Release-All|Itanium.Build.0 = Release-All|Itanium {A0F495FF-9C35-4DFB-A51A-0427D8420779}.Release-All|Win32.ActiveCfg = Release-All|Win32 {A0F495FF-9C35-4DFB-A51A-0427D8420779}.Release-All|Win32.Build.0 = Release-All|Win32 {A0F495FF-9C35-4DFB-A51A-0427D8420779}.Release-All|x64.ActiveCfg = Release-All|x64 {A0F495FF-9C35-4DFB-A51A-0427D8420779}.Release-All|x64.Build.0 = Release-All|x64 {A0F495FF-9C35-4DFB-A51A-0427D8420779}.All-All|Itanium.ActiveCfg = All-All|Itanium {A0F495FF-9C35-4DFB-A51A-0427D8420779}.All-All|Itanium.Build.0 = All-All|Itanium {A0F495FF-9C35-4DFB-A51A-0427D8420779}.All-All|Win32.ActiveCfg = All-All|Win32 {A0F495FF-9C35-4DFB-A51A-0427D8420779}.All-All|Win32.Build.0 = All-All|Win32 {A0F495FF-9C35-4DFB-A51A-0427D8420779}.All-All|x64.ActiveCfg = All-All|x64 {A0F495FF-9C35-4DFB-A51A-0427D8420779}.All-All|x64.Build.0 = All-All|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal hercules-3.07/Hercules.vcproj000644 000765 000765 00000135243 11335365456 017765 0ustar00jmaynardjmaynard000000 000000 ïğż hercules-3.07/hercver.rc000644 000765 000765 00000007036 11333023063 016727 0ustar00jmaynardjmaynard000000 000000 ///////////////////////////////////////////////////////////////////////////////////////// // HercVer.rc -- defines the Windows resources to be linked into the product // (c) Copyright "Fish" (David B. Trout), 2009 // Released under the Q Public License as modifications to Hercules. // (http://www.hercules-390.org/herclic.html) ///////////////////////////////////////////////////////////////////////////////////////// // $Id: hercver.rc 5604 2010-02-05 14:07:42Z jmaynard $ // // $Log$ // Revision 1.7 2008/05/17 13:45:07 ivan // Update (c) info in hercver.rc // // Revision 1.6 2007/11/30 14:54:32 jmaynard // Changed conmicro.cx to hercules-390.org or conmicro.com, as needed. // // Revision 1.5 2006/12/08 09:55:11 jj // Add CVS message log // #ifdef APSTUDIO_INVOKED #error This file is not editable by Microsoft Visual C++ #endif ///////////////////////////////////////////////////////////////////////////////////////// // Icon with lowest ID value placed first to ensure application icon // remains consistent on all systems. 001 ICON DISCARDABLE "hercules.ico" ///////////////////////////////////////////////////////////////////////////////////////// #include #ifndef NONE #define NONE 0x0L #endif #define HERCULES_PRODUCT "The Hercules System/370, ESA/390, and z/Architecture Emulator" #define HERCULES_COPYRIGHT "(c)Copyright 1999-2010" #define HERCULES_COMPANY "by Roger Bowler, Jan Jaeger, and others" #define HERCULES_PRODUCT_URL "http://www.hercules-390.org" #define HERCULES_PRODUCT_EMAIL "hercules-390@yahoogroups.com" #if defined(PRERELEASE) #define ISPRERELEASE VS_FF_PRERELEASE #else #define ISPRERELEASE NONE #endif #if !defined(VERSION) || !defined(V1) || !defined(V2) || !defined(V3) || !defined(V4) #error VERSION not defined properly #endif ///////////////////////////////////////////////////////////////////////////////////////// 1 VERSIONINFO FILEVERSION V1, V2, V3, V4 PRODUCTVERSION V1, V2, V3, V4 FILEOS VOS_NT_WINDOWS32 FILETYPE VFT_UNKNOWN #if defined(DEBUG) || defined(_DEBUG) FILEFLAGS ISPRERELEASE | VS_FF_SPECIALBUILD | VS_FF_DEBUG #else FILEFLAGS ISPRERELEASE | VS_FF_SPECIALBUILD #endif FILEFLAGSMASK VS_FFI_FILEFLAGSMASK { BLOCK "StringFileInfo" { BLOCK "040904B0" // 0x0409 (1033) == U.S. English, 0x04B0 (1200) == UNICODE { // Standard/Required Attributes... VALUE "ProductName", HERCULES_PRODUCT "\0" VALUE "ProductVersion", VERSION "\0" VALUE "FileDescription", HERCULES_PRODUCT "\0" VALUE "FileVersion", VERSION "\0" VALUE "CompanyName", HERCULES_COMPANY "\0" VALUE "LegalCopyright", HERCULES_COPYRIGHT " " HERCULES_COMPANY "\0" // Custom Attributes... VALUE "Hercules URL", HERCULES_PRODUCT_URL "\0" VALUE "Hercules Email", HERCULES_PRODUCT_EMAIL "\0" VALUE "Hercules Version", VERSION "\0" #if defined(PRERELEASE) #define PRE "PRERELEASE " #else #define PRE #endif #if defined(_WIN64) #define ARCH "64-bit " #else #define ARCH "32-bit " #endif #if defined(_DEBUG) || defined(DEBUG) #define CFG "DEBUG " #else #define CFG "RETAIL " #endif VALUE "SpecialBuild", PRE ARCH CFG "version" "\0" } } BLOCK "VarFileInfo" { VALUE "Translation", 0x409, 1200 // 0x409 (1033) == U.S. English, 1200 (0x4B0) == UNICODE } } ///////////////////////////////////////////////////////////////////////////////////////// hercules-3.07/hercwind.h000644 000765 000765 00000017177 11224164171 016733 0ustar00jmaynardjmaynard000000 000000 /* HERCWIND.H (c) Copyright Roger Bowler, 2005-2009 */ /* MSVC Environment Specific Definitions */ /*-------------------------------------------------------------------*/ /* Header file containing additional data structures and function */ /* prototypes required by Hercules in the MSVC environment */ /*-------------------------------------------------------------------*/ // $Id: hercwind.h 5373 2009-06-02 06:03:58Z fish $ // // $Log$ // Revision 1.19 2008/06/22 05:54:30 fish // Fix print-formatting issue (mostly in tape modules) // that can sometimes, in certain circumstances, // cause herc to crash. (%8.8lx --> I32_FMTX, etc) // // Revision 1.18 2008/05/28 16:37:48 fish // #define PATH_MAX from _MAX_PATH if available // // Revision 1.17 2008/03/25 11:41:31 fish // SCSI TAPE MODS part 1: groundwork: non-functional changes: // rename some functions, comments, general restructuring, etc. // New source modules awstape.c, omatape.c, hettape.c and // tapeccws.c added, but not yet used (all will be used in a future // commit though when tapedev.c code is eventually split) // // Revision 1.16 2008/02/19 17:18:36 rbowler // Missing u_int8_t causes crypto compile errors on Solaris // // Revision 1.15 2007/06/23 00:04:10 ivan // Update copyright notices to include current year (2007) // // Revision 1.14 2006/12/08 09:43:26 jj // Add CVS message log // #if !defined(_HERCWIND_H) #define _HERCWIND_H // PROGRAMMING NOTE: Cygwin has a bug in setvbuf requiring us // to do an 'fflush()' after each stdout/err write, and it doesn't // hurt doing it for the MSVC build either... #define NEED_LOGMSG_FFLUSH #if !defined( _MSVC_ ) #error This file is only for building Hercules with MSVC #endif #if defined( _MSC_VER ) && (_MSC_VER < 1300) #error MSVC compiler versions less than 13.0 not supported. #endif /////////////////////////////////////////////////////////////////////// // The following is mostly for issuing "warning" messages since MS's // compiler doesn't support #warning. Instead, we must use #pragma // message as follows: // // #pragma message( MSVC_MESSAGE_LINENUM "blah, blah..." ) // // which results in: // // foobar.c(123) : blah, blah... // // which is really handy when using their Visual Studio IDE since // it allows us to quickly jump to that specific source statement // with just the press of a function key... #if !defined( MSVC_MESSAGE_LINENUM ) #define MSVC_STRINGIZE( L ) #L #define MSVC_MAKESTRING( M, L ) M( L ) #define MSVC_QUOTED_LINENUM MSVC_MAKESTRING( MSVC_STRINGIZE, __LINE__ ) #define MSVC_MESSAGE_LINENUM __FILE__ "(" MSVC_QUOTED_LINENUM ") : " #endif /////////////////////////////////////////////////////////////////////// // Disable some warnings that tend to get in the way... // // FIXME: purposely disabling warning C4244 is dangerous IMO and might // come back to haunt us in the future when we DO happen to introduce // an unintentional coding error that results in unexpected data loss. // // We should instead take the time to fix all places where it's issued // (being sure to add comments when we do) so that we can then rely on // C4244 to warn us of real/actual coding errors. - Fish, April 2006 #pragma warning( disable: 4142 ) // C4142: benign redefinition of type #pragma warning( disable: 4244 ) // C4244: conversion from 'type' to 'type', possible loss of data /////////////////////////////////////////////////////////////////////// #ifdef _MAX_PATH #define PATH_MAX _MAX_PATH #else #ifdef FILENAME_MAX #define PATH_MAX FILENAME_MAX #else #define PATH_MAX 260 #endif #endif struct dirent { long d_ino; char d_name[FILENAME_MAX + 1]; }; typedef unsigned __int32 in_addr_t; typedef unsigned char u_char; typedef unsigned int u_int; typedef unsigned long u_long; typedef unsigned __int8 u_int8_t; typedef unsigned __int16 u_int16_t; typedef unsigned __int32 u_int32_t; typedef unsigned __int64 u_int64_t; typedef signed __int8 int8_t; typedef signed __int16 int16_t; typedef signed __int32 int32_t; typedef signed __int64 int64_t; typedef int ssize_t; typedef int pid_t; typedef int mode_t; #include #include #include #include #define STDIN_FILENO fileno(stdin) #define STDOUT_FILENO fileno(stdout) #define STDERR_FILENO fileno(stderr) /* Bit settings for open() and stat() functions */ #define S_IRUSR _S_IREAD #define S_IWUSR _S_IWRITE #define S_IRGRP _S_IREAD #define S_ISREG(m) (((m) & _S_IFMT) == _S_IFREG) #define S_ISDIR(m) (((m) & _S_IFMT) == _S_IFDIR) #define S_ISCHR(m) (((m) & _S_IFMT) == _S_IFCHR) #define S_ISFIFO(m) (((m) & _S_IFMT) == _S_IFIFO) /* Bit settings for access() function */ #define F_OK 0 #define W_OK 2 #define R_OK 4 #define strcasecmp stricmp #define strncasecmp strnicmp #define snprintf _snprintf #define vsnprintf _vsnprintf #define strerror w32_strerror #define strerror_r w32_strerror_r #define inline __inline #define __inline__ __inline #define HAVE_STRUCT_IN_ADDR_S_ADDR #define HAVE_U_INT #define HAVE_U_INT8_T #define HAVE_LIBMSVCRT #define HAVE_SYS_MTIO_H // (ours is called 'w32mtio.h') #ifndef MAX_CPU_ENGINES #define MAX_CPU_ENGINES 8 #endif #define OPTION_CONFIG_SYMBOLS #define OPTION_ENHANCED_CONFIG_SYMBOLS #define OPTION_ENHANCED_CONFIG_INCLUDE #define OPTION_FTHREADS #define HAVE_STRSIGNAL #define EXTERNALGUI #define NO_SETUID #define NO_SIGABEND_HANDLER #undef NO_ATTR_REGPARM // ( ATTR_REGPARM(x) == __fastcall ) #define HAVE_ATTR_REGPARM // ( ATTR_REGPARM(x) == __fastcall ) #define C99_FLEXIBLE_ARRAYS // ("DEVBLK *memdev[];" supported) //#include "getopt.h" #define HAVE_GETOPT_LONG #include #define HAVE_SQRTL #define HAVE_LDEXPL #define HAVE_FABSL #define HAVE_FMODL #define HAVE_FREXPL // The following are needed by hostopts.h... #define HAVE_DECL_SIOCSIFNETMASK 1 // (manually defined in tuntap.h) #define HAVE_DECL_SIOCSIFHWADDR 1 // (manually defined in tuntap.h) #define HAVE_DECL_SIOCADDRT 0 // (unsupported by CTCI-W32) #define HAVE_DECL_SIOCDELRT 0 // (unsupported by CTCI-W32) #define HAVE_DECL_SIOCDIFADDR 0 // (unsupported by CTCI-W32) // SCSI tape handling transparency/portability #define HAVE_DECL_MTEOTWARN 1 // (always true since I made it up!) #define HAVE_DECL_MTEWARN 1 // (same as HAVE_DECL_MTEOTWARN) // GNUWin32 PCRE (Perl-Compatible Regular Expressions) support... #if defined(HAVE_PCRE) // (earlier packages failed to define this so we must do so ourselves) #define PCRE_DATA_SCOPE extern __declspec(dllimport) #include PCRE_INCNAME // (passed by makefile) #define OPTION_HAO // Hercules Automatic Operator #endif #if defined( _WIN64 ) #define SIZEOF_INT_P 8 #define SIZEOF_SIZE_T 8 #else #define SIZEOF_INT_P 4 #define SIZEOF_SIZE_T 4 #endif #define DBGTRACE DebugTrace inline void DebugTrace(char* fmt, ...) { const int chunksize = 512; int buffsize = 0; char* buffer = NULL; int rc = -1; va_list args; va_start( args, fmt ); do { if (buffer) free( buffer ); buffsize += chunksize; buffer = malloc( buffsize ); if (!buffer) __debugbreak(); rc = vsnprintf( buffer, buffsize, fmt, args); } while (rc < 0 || rc >= buffsize); OutputDebugStringA( buffer ); free( buffer ); va_end( args ); } #endif /*!defined(_HERCWIND_H)*/ hercules-3.07/hetget.c000644 000765 000765 00000042532 11224164170 016373 0ustar00jmaynardjmaynard000000 000000 /* || ---------------------------------------------------------------------------- || || HETGET.C (c) Copyright Leland Lucius, 2000-2009 || Released under terms of the Q Public License. || || Extract files from an HET file || || ---------------------------------------------------------------------------- */ // $Id: hetget.c 5374 2009-06-02 06:19:00Z fish $ // // $Log$ // Revision 1.26 2008/11/04 04:50:46 fish // Ensure consistent utility startup // // Revision 1.25 2007/06/23 00:04:10 ivan // Update copyright notices to include current year (2007) // // Revision 1.24 2006/12/08 09:43:26 jj // Add CVS message log // #include "hstdinc.h" #include "hercules.h" #include "hetlib.h" #include "sllib.h" #include "herc_getopt.h" /* || Local volatile data */ #define O_NL 0x80 #define O_ASCII 0x40 #define O_STRIP 0x20 #define O_UNBLOCK 0x10 struct { char *ifile; char *ofile; int fileno; int lrecl; int blksize; unsigned char flags; unsigned char recfm; } opts = { NULL, NULL, 0, 0, 0, 0, 0, }; /* || Local constant data */ static const char help[] = "%s - Extract files from an HET file\n\n" "Usage: %s [options] hetfile outfile fileno [recfm lrecl blksize]\n\n" "Options:\n" " -a convert to ASCII (implies -u)\n" " -h display usage summary\n" " -n file is an NL (or BLP like) tape\n" " -u unblock (removes BDWs and RDWs if RECFM=V)\n" " -s strip trailing blanks (requires -a)\n"; /* || Valid record formats */ #define O_UNDEFINED 0x80 #define O_FIXED 0x40 #define O_VARIABLE 0x20 #define O_BLOCKED 0x08 #define O_SPANNED 0x04 static const struct { char *recfm; int fmt; } valfm[] = { { "U", O_UNDEFINED | 0 | 0 }, { "UA", O_UNDEFINED | 0 | 0 }, { "UM", O_UNDEFINED | 0 | 0 }, { "F", O_FIXED | 0 | 0 }, { "FA", O_FIXED | 0 | 0 }, { "FM", O_FIXED | 0 | 0 }, { "FB", O_FIXED | O_BLOCKED | 0 }, { "FBA", O_FIXED | O_BLOCKED | 0 }, { "FBM", O_FIXED | O_BLOCKED | 0 }, { "FS", O_FIXED | O_BLOCKED | 0 }, { "FSA", O_FIXED | O_BLOCKED | 0 }, { "FSM", O_FIXED | O_BLOCKED | 0 }, { "FBS", O_FIXED | O_BLOCKED | 0 }, { "FBSA", O_FIXED | O_BLOCKED | 0 }, { "FBSM", O_FIXED | O_BLOCKED | 0 }, { "V", O_VARIABLE | 0 | 0 }, { "VA", O_VARIABLE | 0 | 0 }, { "VM", O_VARIABLE | 0 | 0 }, { "VB", O_VARIABLE | O_BLOCKED | 0 }, { "VBA", O_VARIABLE | O_BLOCKED | 0 }, { "VBM", O_VARIABLE | O_BLOCKED | 0 }, { "VS", O_VARIABLE | 0 | O_SPANNED }, { "VSA", O_VARIABLE | 0 | O_SPANNED }, { "VSM", O_VARIABLE | 0 | O_SPANNED }, { "VBS", O_VARIABLE | O_BLOCKED | O_SPANNED }, { "VBSA", O_VARIABLE | O_BLOCKED | O_SPANNED }, { "VBSM", O_VARIABLE | O_BLOCKED | O_SPANNED }, }; #define VALFMCNT ( sizeof( valfm ) / sizeof( valfm[ 0 ] ) ) /* || Block and record management */ unsigned char *blkptr = NULL; int blkidx = 0; int blklen = 0; unsigned char *recptr = NULL; int recidx = 0; int reclen = 0; #ifdef EXTERNALGUI /* || Previously reported file position */ static off_t prevpos = 0; /* || Report progress every this many bytes */ #define PROGRESS_MASK (~0x3FFFF /* 256K */) #endif /*EXTERNALGUI*/ /* || Merge DCB information from HDR2 label */ void merge( SLLABEL *lab ) { SLFMT fmt; int i; /* || Make the label more managable */ sl_fmtlab( &fmt, lab ); /* || Merge the record format; */ if( opts.recfm == 0 ) { opts.recfm = O_UNDEFINED; for( i = 0 ; i < (int)VALFMCNT ; i++ ) { if( strcasecmp( fmt.slds2.recfm, valfm[ i ].recfm ) == 0 ) { opts.recfm = valfm[ i ].fmt; break; } } } /* || Merge in the record length */ if( opts.lrecl == 0 ) { opts.lrecl = atoi( fmt.slds2.lrecl ); } /* || Merge in the block size */ if( opts.blksize == 0 ) { /* || Try the blksize field first */ opts.blksize = atoi( fmt.slds2.blksize ); if( opts.blksize == 0 ) { /* || Still zero, so try the lblkln field */ opts.blksize = atoi( fmt.slds2.lblkln ); } } /* || Locate final RECFM string */ for( i = 0 ; i < (int)VALFMCNT ; i++ ) { if( strcasecmp( fmt.slds2.recfm, valfm[ i ].recfm ) == 0 ) { break; } } /* || Print DCB attributes */ printf( "DCB Attributes used:\n" ); printf( " RECFM=%-4.4s LRECL=%-5.5d BLKSIZE=%d\n", valfm[ i ].recfm, opts.lrecl, opts.blksize ); return; } /* || Return block length from BDW */ int bdw_length( const unsigned char *ptr ) { unsigned int len; /* || Extended format BDW? */ if( ptr[ 0 ] & 0x80 ) { /* || Length is 31 bits */ len = ptr[ 0 ] << 24; len += ptr[ 1 ] << 16; len += ptr[ 2 ] << 8; len += ptr[ 3 ]; len &= 0x7fffffff; } else { /* || Length is 15 bits */ len = ptr[ 0 ] << 8; len += ptr[ 1 ]; } return( len ); } /* || Return record length from RDW */ int rdw_length( const unsigned char *ptr ) { unsigned int len; /* || Get the record length */ len = ptr[ 0 ] << 8; len += ptr[ 1 ]; return( len ); } /* || Retrieves a block from the tape file and resets variables */ int getblock( HETB *hetb ) { int rc; /* || Read a block from the tape */ rc = het_read( hetb, blkptr ); if( rc < 0 ) { return( rc ); } /* || Save the block length (should we use BDW for RECFM=V files???) */ blklen = rc; return( rc ); } /* || Retrieve logical records from the tape - doesn't handle SPANNED records */ int getrecord( HETB *hetb ) { int rc; /* || Won't be null if we've been here before */ if( recptr != NULL ) { recidx += reclen; } /* || Need a new block first time through or we've exhausted current block */ if( ( recptr == NULL ) || ( recidx >= blklen ) ) { /* || Go get another block */ rc = getblock( hetb ); if( rc < 0 ) { return( rc ); } /* || For RECFM=V, bump index past BDW */ recidx = 0; if( opts.recfm & O_VARIABLE ) { /* protect against a corrupt (short) block */ if ( rc < 8 ) { return ( -1 ); } recidx = 4; } } /* || Set the new record pointer */ recptr = &blkptr[ recidx ]; /* || Set the record length depending on record type */ if( opts.recfm & O_FIXED ) { reclen = opts.lrecl; } else if( opts.recfm & O_VARIABLE ) { reclen = rdw_length( recptr ); /* protect against corrupt (short) block */ if ( reclen + recidx > blklen ) { return (-1); } /* protect against a corrupt (less than 4) RDW */ if ( reclen < 4 ) { return (-1); } } else { reclen = blklen; } return( reclen ); } /* || Retrieve and validate a standard label */ int get_sl( HETB *hetb, SLLABEL *lab ) { int rc; /* || Read a block */ rc = het_read( hetb, blkptr ); if( rc >= 0 ) { /* || Does is look like a standard label? */ if( sl_islabel( lab, blkptr, rc ) == TRUE ) { return( 0 ); } } else { printf( "%s while reading block\n", het_error( rc ) ); } return( -1 ); } /* || Extract the file from the tape */ int getfile( HETB *hetb, FILE *outf ) { SLFMT fmt; SLLABEL lab; unsigned char *ptr; int fileno; int rc; /* || Skip to the desired file */ if( opts.flags & O_NL ) { /* || For NL tapes, just use the specified file number */ fileno = opts.fileno; /* || Start skipping */ while( --fileno ) { /* || Forward space to beginning of next file */ rc = het_fsf( hetb ); if( rc < 0 ) { printf( "%s while positioning to file #%d\n", het_error( rc ), opts.fileno ); return( rc ); } } } else { /* || First block should be a VOL1 record */ rc = get_sl( hetb, &lab ); if( rc < 0 || !sl_isvol( &lab, 1 ) ) { printf( "Expected VOL1 label\n" ); return( -1 ); } /* || For SL, adjust the file # so we end up on the label before the data */ fileno = ( opts.fileno * 3 ) - 2; /* || Start skipping */ while( --fileno ) { /* || Forward space to beginning of next file */ rc = het_fsf( hetb ); if( rc < 0 ) { printf( "%s while positioning to file #%d\n", het_error( rc ), opts.fileno ); return( rc ); } } /* || Get the HDR1 label. */ rc = get_sl( hetb, &lab ); if( rc < 0 || !sl_ishdr( &lab, 1 ) ) { printf( "Expected HDR1 label\n" ); return( -1 ); } /* || Make the label more managable */ sl_fmtlab( &fmt, &lab ); printf("File Info:\n DSN=%-17.17s\n", fmt.slds1.dsid ); /* || Get the HDR2 label. */ rc = get_sl( hetb, &lab ); if( rc < 0 || !sl_ishdr( &lab, 2 ) ) { printf( "Expected HDR2 label\n" ); return( -1 ); } /* || Merge the DCB information */ merge( &lab ); /* || Hop over the tapemark */ rc = het_fsf( hetb ); if( rc < 0 ) { printf( "%s while spacing to start of data\n", het_error( rc ) ); return( rc ); } } /* || Different processing when converting to ASCII */ if( opts.flags & ( O_ASCII | O_UNBLOCK ) ) { /* || Get a record */ while( ( rc = getrecord( hetb ) ) >= 0 ) { #ifdef EXTERNALGUI if( extgui ) { /* Report progress every nnnK */ off_t curpos = ftell( hetb->fd ); if( ( curpos & PROGRESS_MASK ) != ( prevpos & PROGRESS_MASK ) ) { prevpos = curpos; fprintf( stderr, "IPOS=%" I64_FMT "d\n", (U64)curpos ); } } #endif /*EXTERNALGUI*/ /* || Get working copy of record ptr */ ptr = recptr; /* || Only want data portion for RECFM=V records */ if( opts.recfm & O_VARIABLE ) { ptr += 4; rc -= 4; } /* || Convert record to ASCII */ if( opts.flags & O_ASCII ) { sl_etoa( NULL, ptr, rc ); } /* || Strip trailing blanks */ if( opts.flags & O_STRIP ) { while( rc > 0 && ptr[ rc - 1 ] == ' ' ) { rc--; } } /* || Write the record out */ fwrite( ptr, rc, 1, outf ); /* || Put out a linefeed when converting */ if( opts.flags & O_ASCII ) { fwrite( "\n", 1, 1, outf ); } } } else { /* || Get a record */ while( ( rc = getblock( hetb ) ) >= 0 ) { #ifdef EXTERNALGUI if( extgui ) { /* Report progress every nnnK */ off_t curpos = ftell( hetb->fd ); if( ( curpos & PROGRESS_MASK ) != ( prevpos & PROGRESS_MASK ) ) { prevpos = curpos; fprintf( stderr, "IPOS=%" I64_FMT "d\n", (U64)curpos ); } } #endif /*EXTERNALGUI*/ /* || Write the record out */ fwrite( blkptr, blklen, 1, outf ); } } return( rc ); } /* || Prints usage information */ void usage( char *name ) { printf( help, name, name ); } /* || Standard main */ int main( int argc, char *argv[] ) { HETB *hetb; FILE *outf; int rc; int i; INITIALIZE_UTILITY("hetget"); /* Display the program identification message */ display_version (stderr, "Hercules HET extract files program ", FALSE); /* || Process option switches */ while( TRUE ) { rc = getopt( argc, argv, "abhnsu" ); if( rc == -1 ) { break; } switch( rc ) { case 'a': opts.flags |= O_ASCII; break; case 'h': usage( argv[ 0 ] ); exit( 1 ); break; case 'n': opts.flags |= O_NL; break; case 's': opts.flags |= O_STRIP; break; case 'u': opts.flags |= O_UNBLOCK; break; default: usage( argv[ 0 ] ); exit( 1 ); break; } } /* || Calc number of non-switch arguments */ argc -= optind; /* || We must have at least the first 3 parms */ if( argc < 3 ) { printf( "Must specify input tape, output file, and file #\n" ); printf( "Use -h option for more help\n" ); exit( 1 ); } opts.ifile = argv[ optind ]; opts.ofile = argv[ optind + 1 ]; opts.fileno = atoi( argv[ optind + 2 ] ); if( opts.fileno == 0 || opts.fileno > 9999 ) { printf( "File number must be within 1-9999\n" ); exit( 1 ); } /* || If NL tape, then we require the DCB attributes */ if( opts.flags & O_NL ) { if( argc != 6 ) { printf( "DCB attributes required for NL tapes\n" ); exit( 1 ); } } /* || If specified, get the DCB attributes */ if( argc > 3 ) { /* || Must have only three */ if( argc != 6 ) { usage( argv[ 0 ] ); exit( 1 ); } /* || Lookup the specified RECFM in our table */ opts.recfm = 0; for( i = 0 ; i < (int)VALFMCNT ; i++ ) { if( strcasecmp( argv[ optind + 3 ], valfm[ i ].recfm ) == 0 ) { opts.recfm = valfm[ i ].fmt; break; } } /* || If we didn't find a match, show the user what the valid ones are */ if( opts.recfm == 0) { /* || Dump out the valid RECFMs */ printf( "Valid record formats are:\n" ); for( i = 0 ; i < (int)VALFMCNT ; i++ ) { printf( " %-4.4s", valfm[ i ].recfm ); if( ( ( i + 1 ) % 3 ) == 0 ) { printf( "\n" ); } } exit( 1 ); } /* || Get the record length */ opts.lrecl = atoi( argv[ optind + 4 ] ); /* || Get and validate the blksize */ opts.blksize = atoi( argv[ optind + 5 ] ); if( opts.blksize == 0 ) { printf( "Block size can't be zero\n" ); exit( 1 ); } } /* || Open the tape file */ rc = het_open( &hetb, opts.ifile, 0 ); if( rc >= 0 ) { /* || Get memory for the tape buffer */ blkptr = malloc( HETMAX_BLOCKSIZE ); if( blkptr != NULL ) { /* || Open the output file */ char pathname[MAX_PATH]; hostpath(pathname, opts.ofile, sizeof(pathname)); outf = fopen( pathname, "wb" ); if( outf != NULL ) { /* || Go extract the file from the tape */ rc = getfile( hetb, outf ); /* || Close the output file */ fclose( outf ); } /* || Free the buffer memory */ free( blkptr ); } } else { printf( "het_open() returned %s\n", het_error( rc ) ); } /* || Close the tape file */ het_close( &hetb ); return 0; } hercules-3.07/hetinit.c000644 000765 000765 00000011267 11143760544 016567 0ustar00jmaynardjmaynard000000 000000 /* || ---------------------------------------------------------------------------- || || HETINIT.C (c) Copyright Leland Lucius, 2000-2009 || Released under terms of the Q Public License. || || Creates IEHINITT or NL format Hercules Emulated Tapes. || || ---------------------------------------------------------------------------- */ // $Id: hetinit.c 5125 2009-01-23 12:01:44Z bernard $ // // $Log$ // Revision 1.25 2008/11/04 04:50:46 fish // Ensure consistent utility startup // // Revision 1.24 2007/06/23 00:04:10 ivan // Update copyright notices to include current year (2007) // // Revision 1.23 2006/12/08 09:43:26 jj // Add CVS message log // #include "hstdinc.h" #include "hercules.h" #include "hetlib.h" #include "sllib.h" #include "herc_getopt.h" /* || Local constant data */ static const char help[] = "%s - Initialize a tape\n\n" "Usage: %s [options] filename [volser] [owner]\n\n" "Options:\n" " -d disable compression\n" " -h display usage summary\n" " -i create an IEHINITT formatted tape (default: on)\n" " -n create an NL tape\n"; /* || Prints usage information */ static void usage( char *name ) { printf( help, name, name ); } /* || Subroutine to convert a null-terminated string to upper case */ void het_string_to_upper (char *source) { int i; for (i = 0; source[i] != '\0'; i++) source[i] = toupper(source[i]); } /* || Standard main() function */ int main( int argc, char *argv[] ) { int rc; SLLABEL lab; HETB *hetb; int o_iehinitt; int o_nl; int o_compress; char *o_filename; char *o_owner; char *o_volser; INITIALIZE_UTILITY("hetinit"); hetb = NULL; o_filename = NULL; o_iehinitt = TRUE; o_nl = FALSE; o_compress = TRUE; o_owner = NULL; o_volser = NULL; /* Display the program identification message */ display_version (stderr, "Hercules HET IEHINITT program ", FALSE); while( TRUE ) { rc = getopt( argc, argv, "dhin" ); if( rc == -1 ) { break; } switch( rc ) { case 'd': o_compress = FALSE; break; case 'h': usage( argv[ 0 ] ); goto exit; break; case 'i': o_iehinitt = TRUE; o_nl = FALSE; break; case 'n': o_iehinitt = FALSE; o_nl = TRUE; break; default: usage( argv[ 0 ] ); goto exit; break; } } argc -= optind; if( argc < 1 ) { usage( argv[ 0 ] ); goto exit; } o_filename = argv[ optind ]; if( o_iehinitt ) { if( argc == 2 ) { o_volser = argv[ optind + 1 ]; } else if( argc == 3 ) { o_volser = argv[ optind + 1 ]; o_owner = argv[ optind + 2 ]; } else { usage( argv[ 0 ] ); goto exit; } } if( o_nl ) { if( argc != 1 ) { usage( argv[ 0 ] ); goto exit; } } if( o_volser ) het_string_to_upper( o_volser ); if( o_owner ) het_string_to_upper( o_owner ); rc = het_open( &hetb, o_filename, HETOPEN_CREATE ); if( rc < 0 ) { printf( "het_open() returned %d\n", rc ); goto exit; } rc = het_cntl( hetb, HETCNTL_SET | HETCNTL_COMPRESS, o_compress ); if( rc < 0 ) { printf( "het_cntl() returned %d\n", rc ); goto exit; } if( o_iehinitt ) { rc = sl_vol1( &lab, o_volser, o_owner ); if( rc < 0 ) { printf( "%s\n", sl_error(rc) ); goto exit; } rc = het_write( hetb, &lab, sizeof( lab ) ); if( rc < 0 ) { printf( "het_write() for VOL1 returned %d\n", rc ); goto exit; } rc = sl_hdr1( &lab, SL_INITDSN, NULL, 0, 0, NULL, 0 ); if( rc < 0 ) { printf( "%s\n", sl_error(rc) ); goto exit; } rc = het_write( hetb, &lab, sizeof( lab ) ); if( rc < 0 ) { printf( "het_write() for HDR1 returned %d\n", rc ); goto exit; } } else if( o_nl ) { rc = het_tapemark( hetb ); if( rc < 0 ) { printf( "het_tapemark() returned %d\n", rc ); goto exit; } } rc = het_tapemark( hetb ); if( rc < 0 ) { printf( "het_tapemark() returned %d\n", rc ); goto exit; } exit: het_close( &hetb ); return( rc < 0 ); } hercules-3.07/hetlib.c000644 000765 000765 00000153733 11143760544 016377 0ustar00jmaynardjmaynard000000 000000 /* || ---------------------------------------------------------------------------- || || HETLIB.C (c) Copyright Leland Lucius, 2000-2009 || Released under terms of the Q Public License. || || Library for managing Hercules Emulated Tapes. || || ---------------------------------------------------------------------------- */ // $Id: hetlib.c 5125 2009-01-23 12:01:44Z bernard $ // // $Log$ // Revision 1.34 2007/11/21 23:30:41 fish // (comment change only) // // Revision 1.33 2007/07/24 22:36:32 fish // Fix tape Synchronize CCW (x'43') to do actual commit // // Revision 1.32 2007/06/23 00:04:10 ivan // Update copyright notices to include current year (2007) // // Revision 1.31 2007/02/25 21:10:44 fish // Fix het_locate to continue on tapemark // // Revision 1.30 2006/12/08 09:43:26 jj // Add CVS message log // #include "hstdinc.h" #define _HETLIB_C_ #define _HTAPE_DLL_ #include "hercules.h" #include "hetlib.h" #undef HETDEBUGR #undef HETDEBUGW /* || Local constant data */ static const char *het_errstr[] = { "No error", "File error", "Tapemark read", "Beginning of tape", "End of tape", "BOR not found", "EOR not found", "Unexpected tapemark", "Buffer not big enough", "Premature EOF", "Decompression error", "Unknown compression method", "Compression error", "Specified length to big", "Write protected", "Bad function code passed", "Bad compression method", "Bad compression level", "Bad write chunk size", "Invalid direction specified", "Insufficient memory", "Couldn't read block header", "Inconsistent compression flags", "Invalid error code", }; #define HET_ERRSTR_MAX ( sizeof( het_errstr) / sizeof( het_errstr[ 0 ] ) ) /*==DOC== NAME het_open - Open an HET format file SYNOPSIS #include "hetlib.h" int het_open( HETB **hetb, char *filename, int flags ) DESCRIPTION The het_open() function opens the file indicated by the "filename" parameter and, if successful, places the address of an HETB at the location pointed to by the "hetb" parameter. Currently, "HETOPEN_CREATE" is the only flag available and has the same function as the O_CREAT flag of the open(3) function. @ISW@ Added flag HETOPEN_READONLY HETOPEN_CREATE and HETOPEN_READONLY are mutually exclusive. When HETOPEN_READONLY is set, the het file must exist. It is opened read only. Any attempt to write will fail. RETURN VALUE If no errors are detected then the return value will be >= 0 and the address of the newly allocated HETB will be place at the "hetb" location. If an error occurs, then the return value will be < 0 and will be one of the following: HETE_NOMEM Insufficient memory to allocate an HETB HETE_ERROR File system error - check errno(3) For other possible errors, see: het_read_header() het_tapemark() het_rewind() NOTES Even if het_open() fails, you should still call het_close(). EXAMPLE // // Create an NL tape // #include "hetlib.h" int main( int argc, char *argv[] ) { HETB *hetb; int rc; rc = het_open( &hetb, argv[ 1 ], HETOPEN_CREATE ); if( rc < 0 ) { printf( "het_open() returned: %d\n", rc ); } else { printf( "%s successfully created\n", argv[ 1 ] ); } het_close( &hetb ); return( 0 ); } SEE ALSO het_read_header(), het_tapemark(), het_rewind(), het_close() ==DOC==*/ DLL_EXPORT int het_open( HETB **hetb, char *filename, int flags ) { HETB *thetb; char *omode; int rc; int fd; int oflags; char pathname[MAX_PATH]; /* || Initialize */ *hetb = NULL; hostpath(pathname, filename, sizeof(pathname)); /* || Allocate a new HETB */ thetb = calloc( 1, sizeof( HETB ) ); if( thetb == NULL ) { return( HETE_NOMEM ); } /* || Set defaults */ thetb->compress = HETDFLT_COMPRESS; thetb->decompress = HETDFLT_DECOMPRESS; thetb->method = HETDFLT_METHOD; thetb->level = HETDFLT_LEVEL; thetb->chksize = HETDFLT_CHKSIZE; /* || clear HETOPEN_CREATE if HETOPEN_READONLY is specified */ if(flags & HETOPEN_READONLY) { flags&=~HETOPEN_CREATE; } /* || Translate HET create flag to filesystem flag */ oflags = ( ( flags & HETOPEN_CREATE ) ? O_CREAT : 0 ); /* || Open the tape file */ omode = "r+b"; if(!(flags & HETOPEN_READONLY)) { fd = open( pathname, O_RDWR | O_BINARY | oflags, S_IRUSR | S_IWUSR | S_IRGRP ); } if( (flags & HETOPEN_READONLY) || (fd == -1 && (errno == EROFS || errno == EACCES) ) ) { /* || Retry open if file resides on readonly file system */ omode = "rb"; thetb->writeprotect = TRUE; fd = open( pathname, O_RDONLY | O_BINARY, S_IRUSR | S_IWUSR | S_IRGRP ); } /* || Error out if both opens failed */ if( fd == -1 ) { free( thetb ); return( HETE_ERROR ); } /* || Associate stream with file descriptor */ thetb->fd = fdopen( fd, omode ); if( thetb->fd == NULL ) { rc = errno; close( fd ); errno = rc; free( thetb ); return( HETE_ERROR ); } /* || If uninitialized tape, write 2 tapemarks to make it a valid NL tape */ rc = het_read_header( thetb ); if( rc < 0 && rc != HETE_TAPEMARK ) { if( rc != HETE_EOT ) { return( rc ); } rc = het_tapemark( thetb ); if( rc < 0 ) { return( rc ); } rc = het_tapemark( thetb ); if( rc < 0 ) { return( rc ); } } /* || Reposition tape to load point */ rc = het_rewind( thetb ); if( rc < 0 ) { return( rc ); } /* || Give the caller the new HETB */ *hetb = thetb; return( 0 ); } /*==DOC== NAME het_close - Close an HET file SYNOPSIS #include "hetlib.h" int het_close( HETB **hetb ) DESCRIPTION The het_close() function closes an HET file and releases the HETB. RETURN VALUE If no errors are detected then the return value will be >= 0 and the location specified by the "hetb" parameter will be set to NULL. If an error occurs, then the return value will be < 0. At this time, no errors will be returned. EXAMPLE // // Create an NL tape // #include "hetlib.h" int main( int argc, char *argv[] ) { HETB *hetb; int rc; rc = het_open( &hetb, argv[ 1 ], HETOPEN_CREATE ); if( rc < 0 ) { printf( "het_open() returned: %d\n", rc ); } else { printf( "%s successfully created\n", argv[ 1 ] ); } het_close( &hetb ); return( 0 ); } SEE ALSO het_open() ==DOC==*/ DLL_EXPORT int het_close( HETB **hetb ) { /* || Only free the HETB if we have one */ if( *(hetb) != NULL ) { /* || Only close the file if opened */ if( (*hetb)->fd != NULL ) { fclose( (*hetb)->fd ); } free( *(hetb) ); } /* || Reinitialize pointer */ *hetb = NULL; return( 0 ); } /*==DOC== NAME het_cntl - Control HET file behavior SYNOPSIS #include "hetlib.h" int het_cntl( HETB *hetb, int func, unsigned long val ) DESCRIPTION The het_cntl() function allows you to get/set several values that control how an HET file behaves. The value of the "val" parameter depends on the function code. The possible modes are: HETCNTL_GET Should be ORed (|) with the function codes to retrieve the current setting. (Default) HETCNTL_SET Should be ORed (|) with the function codes to set a new value. The possible function codes are: HETCNTL_COMPRESS val=TRUE to enable write compression (see notes) Values: FALSE (disable) TRUE (enable) Default: HETDFLT_COMPRESS (TRUE) HETCNTL_DECOMPRESS val=TRUE to enable read decompression Values: FALSE (disable) TRUE (enable) Default: HETDFLT_DECOMPRESS (TRUE) HETCNTL_METHOD val=Compression method to use Values: HETMETH_ZLIB (1) HETMETH_BZLIB (2) Default: HETDFLT_METHOD (HETMETH_ZLIB) HETCNTL_LEVEL val=Level of compression Min: HETMIN_LEVEL (1) Max: HETMAX_LEVEL (9) Default: HETDFLT_LEVEL (4) HETCNTL_CHUNKSIZE val=Size of output chunks (see notes) Min: HETMIN_CHUNKSIZE (4096) Max: HETMAX_CHUNKSIZE (65535) Default: HETDFLT_CHUNKSIZE (65535) RETURN VALUE If no errors are detected then the return value will be either the current setting for a "get" request or >= 0 for a "set" request. If an error occurs, then the return value will be < 0 and can be one of the following: HETE_BADMETHOD Specified method out of range HETE_BADLEVEL Specified level out of range HETE_BADCHUNKSIZE Specified chunk size out of range HETE_BADFUNC Unrecognized function code NOTES Each block on an HET file is made up of "HETCNTL_CHUNKSIZE" sized chunks. There can be 1 or many chunks per block. If you wish to create an AWSTAPE compatible file, specify a chunk size of 4096 and disable write compression. EXAMPLE // // Create an NL tape and write an uncompressed string to it // #include "hetlib.h" char data[] = "This is a test"; int main( int argc, char *argv[] ) { HETB *hetb; int rc; rc = het_open( &hetb, argv[ 1 ], HETOPEN_CREATE ); if( rc >= 0 ) { rc = het_cntl( hetb, HETCNTL_SET | HETCNTL_COMPRESS, FALSE ); if( rc >= 0 ) { rc = het_write( hetb, data, sizeof( data ) ); if( rc >= 0 ) { printf( "Data successfully written\n" ); } } } if( rc < 0 ) { printf( "HETLIB error: %d\n", rc ); } het_close( &hetb ); return( 0 ); } SEE ALSO het_open(), het_cntl(), het_write(), het_close() ==DOC==*/ DLL_EXPORT int het_cntl( HETB *hetb, int func, unsigned long val ) { int mode; /* || Isolate the mode */ mode = func & HETCNTL_SET; /* || Process the requested function */ switch( func & ( ~( HETCNTL_GET | HETCNTL_SET ) ) ) { case HETCNTL_COMPRESS: if( mode == HETCNTL_GET ) { return( hetb->compress ); } hetb->compress = ( val ? TRUE : FALSE ); break; case HETCNTL_DECOMPRESS: if( mode == HETCNTL_GET ) { return( hetb->decompress ); } hetb->decompress = ( val ? TRUE : FALSE ); break; case HETCNTL_METHOD: if( mode == HETCNTL_GET ) { return( hetb->method ); } if( val < HETMIN_METHOD || val > HETMAX_METHOD ) { return( HETE_BADMETHOD ); } hetb->method = val; break; case HETCNTL_LEVEL: if( mode == HETCNTL_GET ) { return( hetb->level ); } if( val < HETMIN_LEVEL || val > HETMAX_LEVEL ) { return( HETE_BADLEVEL ); } hetb->level = val; break; case HETCNTL_CHUNKSIZE: if( mode == HETCNTL_GET ) { return( hetb->chksize ); } if( val < HETMIN_CHUNKSIZE || val > HETMAX_CHUNKSIZE ) { return( HETE_BADSIZE ); } hetb->chksize = val; break; default: return( HETE_BADFUNC ); break; } /* || Success */ return( 0 ); } /*==DOC== NAME het_read_header - Retrieve the next chunk header from an HET file SYNOPSIS #include "hetlib.h" int het_read_header( HETB *hetb ) DESCRIPTION Retrieves the next chunk header and stores it in the HETB. RETURN VALUE If no errors are detected then the return value will be >= 0 and the current block count will be incremented. If an error occurs, then the return value will be < 0 and can be one of the following: HETE_EOT End of tape encountered HETE_ERROR File system error - check errno(3) HETE_TAPEMARK Tape mark encountered NOTES This function is not normally called from user programs and its behavior may change. EXAMPLE // // Read a chunk header from an HET file. // #include "hetlib.h" int main( int argc, char *argv[] ) { HETB *hetb; int rc; rc = het_open( &hetb, argv[ 1 ], 0 ); if( rc >= 0 ) { rc = het_read_header( hetb ); if( rc >= 0 ) { printf( "Header read:\n" ); printf( " Current length: %d\n", HETHDR_CLEN( hetb ) ); printf( " Previous length: %d\n", HETHDR_PLEN( hetb ) ); printf( " Flags1: %x\n", hetb->flags1 ); printf( " Flags2: %x\n", hetb->flags2 ); } } if( rc < 0 ) { printf( "HETLIB error: %d\n", rc ); } het_close( &hetb ); return( 0 ); } SEE ALSO het_open(), het_close() ==DOC==*/ DLL_EXPORT int het_read_header( HETB *hetb ) { int rc; /* || Read in a headers worth of data */ rc = fread( &hetb->chdr, sizeof( HETHDR ), 1, hetb->fd ); if( rc != 1 ) { /* || Return EOT if at end of physical file */ if( feof( hetb->fd ) ) { return( HETE_EOT ); } /* || Something else must've happened */ return( HETE_ERROR ); } #if defined( HETDEBUGR ) printf("read hdr: pl=%d, cl=%d, f1=%02x, f2=%02x\n", HETHDR_PLEN( hetb ), HETHDR_CLEN( hetb ), hetb->chdr.flags1, hetb->chdr.flags2); #endif /* || Bump block number if done with entire block */ if( hetb->chdr.flags1 & ( HETHDR_FLAGS1_EOR | HETHDR_FLAGS1_TAPEMARK ) ) { hetb->cblk++; } /* || Check for tape marks */ if( hetb->chdr.flags1 & HETHDR_FLAGS1_TAPEMARK ) { return( HETE_TAPEMARK ); } /* || Success */ return( 0 ); } /*==DOC== NAME het_read - Retrieve the next block from an HET file SYNOPSIS #include "hetlib.h" int het_read( HETB *hetb, void *sbuf ) DESCRIPTION Read the next block of data into the "sbuf" memory location. The length of "sbuf" should be at least HETMAX_BLOCKSIZE bytes. RETURN VALUE If no errors are detected then the return value will be the size of the block read. This will be either the compressed or uncompressed length depending on the current AWSCNTL_DECOMPRESS setting. If an error occurs, then the return value will be < 0 and can be one of the following: HETE_ERROR File system error - check errno(3) HETE_BADBOR Beginning of record expected but not found HETE_BADCOMPRESS Compression mismatch between related chunks HETE_OVERFLOW Record too large for buffer HETE_PREMEOF Premature EOF on file HETE_DECERR Decompression error (stored in errno(3)) HETE_UNKMETH Unknown compression method encountered For other possible errors, see: het_read_header() EXAMPLE // // Read a block from an HET file. // #include "hetlib.h" char buffer[ HETMAX_BLOCKSIZE ]; int main( int argc, char *argv[] ) { HETB *hetb; int rc; rc = het_open( &hetb, argv[ 1 ], 0 ); if( rc >= 0 ) { rc = het_read( hetb, buffer ); if( rc >= 0 ) { printf( "Block read - length: %d\n", rc ); } } if( rc < 0 ) { printf( "HETLIB error: %d\n", rc ); } het_close( &hetb ); return( 0 ); } SEE ALSO het_open(), het_read_header(), het_close() ==DOC==*/ DLL_EXPORT int het_read( HETB *hetb, void *sbuf ) { char *tptr; int rc; unsigned long slen; int flags1, flags2; unsigned long tlen; char tbuf[ HETMAX_BLOCKSIZE ]; /* || Initialize */ flags1 = flags2 = 0; tlen = 0; tptr = sbuf; /* || Read chunks until entire block has been read */ do { /* || Get a header */ rc = het_read_header( hetb ); if( rc < 0 ) { return( rc ); } /* || Have we seen a BOR chunk yet? */ if( !( flags1 & HETHDR_FLAGS1_BOR ) ) { /* || Nope, so this chunk MUST have the BOR set */ if( !( hetb->chdr.flags1 & HETHDR_FLAGS1_BOR ) ) { return( HETE_BADBOR ); } /* || If block is compressed (and decompression is desired), set || destination pointer. */ if( hetb->decompress ) { if( hetb->chdr.flags1 & HETHDR_FLAGS1_COMPRESS || hetb->chdr.flags2 & HETHDR_FLAGS2_COMPRESS ) { if( ( hetb->chdr.flags1 & HETHDR_FLAGS1_COMPRESS ) && ( hetb->chdr.flags2 & HETHDR_FLAGS2_COMPRESS ) ) { return( HETE_BADCOMPRESS ); } tptr = tbuf; } } /* || Save flags for later validation */ flags1 = hetb->chdr.flags1; flags2 = hetb->chdr.flags2; } else { /* || Yep, so this chunk MUST NOT have the BOR flag set */ if( hetb->chdr.flags1 & HETHDR_FLAGS1_BOR ) { return( HETE_BADBOR ); } } /* || Compression flags from related chunks must match */ if( ( flags1 & HETHDR_FLAGS1_COMPRESS ) != ( hetb->chdr.flags1 & HETHDR_FLAGS1_COMPRESS ) ) { return( HETE_BADCOMPRESS ); } if( ( flags2 & HETHDR_FLAGS2_COMPRESS ) != ( hetb->chdr.flags2 & HETHDR_FLAGS2_COMPRESS ) ) { return( HETE_BADCOMPRESS ); } /* || Calculate running length */ slen = HETHDR_CLEN( hetb ); tlen += slen; /* || Can't be bigger than HETMAX_BLOCKSIZE */ if( tlen > HETMAX_BLOCKSIZE ) { return( HETE_OVERFLOW ); } /* || Finally read in the chunk data */ rc = fread( tptr, 1, slen, hetb->fd ); if( rc != (int)slen ) { if( feof( hetb->fd ) ) { return( HETE_PREMEOF ); } return( HETE_ERROR ); } /* || Bump destination pointer to next possible location */ tptr += slen; } while( !( hetb->chdr.flags1 & HETHDR_FLAGS1_EOR ) ); /* || Save compressed length (means cblksize size and ublksize will be the || same for uncompressed data) */ hetb->cblksize = tlen; /* || Decompress data if requested */ if( hetb->decompress ) { switch( hetb->chdr.flags1 & HETHDR_FLAGS1_COMPRESS ) { case 0: switch( hetb->chdr.flags2 & HETHDR_FLAGS2_COMPRESS ) { case 0: break; #if defined( HAVE_LIBZ ) case HETHDR_FLAGS2_ZLIB_BUSTECH: slen = HETMAX_BLOCKSIZE; rc = uncompress( sbuf, &slen, (unsigned char *)tbuf, tlen ); if( rc != Z_OK ) { errno = rc; return( HETE_DECERR ); } tlen = slen; break; #endif /* defined( HAVE_LIBZ ) */ default: return( HETE_UNKMETH ); break; } break; #if defined( HAVE_LIBZ ) case HETHDR_FLAGS1_ZLIB: slen = HETMAX_BLOCKSIZE; rc = uncompress( sbuf, &slen, (unsigned char *)tbuf, tlen ); if( rc != Z_OK ) { errno = rc; return( HETE_DECERR ); } tlen = slen; break; #endif /* defined( HAVE_LIBZ ) */ #if defined( HET_BZIP2 ) case HETHDR_FLAGS1_BZLIB: slen = HETMAX_BLOCKSIZE; rc = BZ2_bzBuffToBuffDecompress( sbuf, (void *) &slen, tbuf, tlen, 0, 0 ); if (rc != BZ_OK) { errno = rc; return( HETE_DECERR ); } tlen = slen; break; #endif /* defined( HET_BZIP2 ) */ default: return( HETE_UNKMETH ); break; } } /* || Save uncompressed length */ hetb->ublksize = tlen; /* || Success */ return( tlen ); } /*==DOC== NAME het_write_header - Write a chunk header to an HET file SYNOPSIS #include "hetlib.h" int het_write_header( HETB *hetb, int len, int flags1, int flags2 ) DESCRIPTION Constructs and writes a chunk header to an HET file. RETURN VALUE If no errors are detected then the return value will be >= 0 and the current block count will be incremented. If an error occurs, then the return value will be < 0 and can be one of the following: HETE_BADLEN "len" parameter out of range HETE_PROTECTED File is write protected HETE_ERROR File system error - check errno(3) NOTES This function is not normally called from user programs and its behavior may change. If this function is called and the tape is not positioned at the end, then the file will be truncated to the current position. This means that rewriting blocks is not currently possible. EXAMPLE // // Write a chunk header to an HET file. // #include "hetlib.h" int main( int argc, char *argv[] ) { HETB *hetb; int rc; rc = het_open( &hetb, argv[ 1 ], 0 ); if( rc >= 0 ) { rc = het_write_header( hetb, 0, HETHDR_TAPEMARK, 0 ); if( rc >= 0 ) { printf( "Header written\n" ); } } if( rc < 0 ) { printf( "HETLIB error: %d\n", rc ); } het_close( &hetb ); return( 0 ); } SEE ALSO het_open(), het_close() ==DOC==*/ int het_write_header( HETB *hetb, int len, int flags1, int flags2 ) { int rc; off_t rcoff; #if defined( HETDEBUGW ) printf("write hdr: pl=%d, cl=%d, f1=%02x, f2=%02x\n", HETHDR_PLEN( hetb ), HETHDR_CLEN( hetb ), hetb->chdr.flags1, hetb->chdr.flags2); #endif /* || Validate length */ if( len > HETMAX_CHUNKSIZE ) { return( HETE_BADLEN ); } /* || Can't write anything on readonly media */ if( hetb->writeprotect ) { return( HETE_PROTECTED ); } /* || For tapemarks, length must be zero. */ if( flags1 & HETHDR_FLAGS1_TAPEMARK ) { len = 0; } /* || According to Linux fopen() man page, a positioning function is required || between reads and writes. Is this REALLY necessary??? */ if( !hetb->readlast ) { fseek( hetb->fd, 0, SEEK_CUR ); hetb->readlast = FALSE; } /* || If this is the first write, truncate the file */ if( !hetb->truncated ) { rcoff = ftell( hetb->fd ); if( rcoff == -1 ) { return( HETE_ERROR ); } rc = ftruncate( fileno( hetb->fd ), rcoff ); if( rc == -1 ) { return( HETE_ERROR ); } hetb->truncated = TRUE; } /* || Construct the header */ hetb->chdr.plen[ 0 ] = hetb->chdr.clen[ 0 ]; hetb->chdr.plen[ 1 ] = hetb->chdr.clen[ 1 ]; hetb->chdr.clen[ 0 ] = len & 0xFF; hetb->chdr.clen[ 1 ] = ( len >> 8 ) & 0xFF; hetb->chdr.flags1 = flags1; hetb->chdr.flags2 = flags2; /* || Write it out */ rc = fwrite( &hetb->chdr, sizeof( HETHDR ), 1, hetb->fd ); if( rc != 1 ) { return( HETE_ERROR ); } /* || Bump block count if done with entire block */ if( hetb->chdr.flags1 & ( HETHDR_FLAGS1_EOR | HETHDR_FLAGS1_TAPEMARK ) ) { hetb->cblk++; } /* || Success */ return 0; } /*==DOC== NAME het_write - Write a block to an HET file SYNOPSIS #include "hetlib.h" int het_write( HETB *hetb, void *sbuf, int slen ) DESCRIPTION Writes a block of data specified by "sbuf" with a length of "slen" to an HET file. Depending on the current HETCNTL_COMPRESS setting, the data may be compressed prior to writing. RETURN VALUE If no errors are detected then the return value will be the size of the block written. This will be either the compressed or uncompressed length depending on the current AWSCNTL_COMPRESS setting. If an error occurs, then the return value will be < 0 and can be one of the following: HETE_ERROR File system error - check errno(3) HETE_BADLEN "slen" parameter out of range HETE_BADCOMPRESS Compression mismatch between related chunks For other possible errors, see: het_write_header() EXAMPLE // // Create an NL tape and write a string to it // #include "hetlib.h" char data[] = "This is a test"; int main( int argc, char *argv[] ) { HETB *hetb; int rc; rc = het_open( &hetb, argv[ 1 ], HETOPEN_CREATE ); if( rc >= 0 ) { rc = het_write( hetb, data, sizeof( data ) ); if( rc >= 0 ) { printf( "Block written - length: %d\n", rc ); } } if( rc < 0 ) { printf( "HETLIB error: %d\n", rc ); } het_close( &hetb ); return( 0 ); } SEE ALSO het_open(), het_write_header(), het_close() ==DOC==*/ DLL_EXPORT int het_write( HETB *hetb, void *sbuf, int slen ) { int rc; int flags; unsigned long tlen; #if defined(HAVE_LIBZ) || defined( HET_BZIP2 ) char tbuf[ ((((HETMAX_BLOCKSIZE * 1001) + 999) / 1000) + 12) ]; #endif /* || Validate */ if( slen > HETMAX_BLOCKSIZE ) { return( HETE_BADLEN ); } /* || Initialize */ flags = HETHDR_FLAGS1_BOR; /* || Save uncompressed length */ hetb->ublksize = slen; /* || Compress data if requested */ if( hetb->compress ) { switch( hetb->method ) { #if defined(HAVE_LIBZ) case HETHDR_FLAGS1_ZLIB: tlen = sizeof( tbuf ); rc = compress2( (unsigned char *)tbuf, &tlen, sbuf, slen, hetb->level ); if( rc != Z_OK ) { errno = rc; return( HETE_COMPERR ); } if( (int)tlen < slen ) { sbuf = tbuf; slen = tlen; flags |= HETHDR_FLAGS1_ZLIB; } break; #endif #if defined( HET_BZIP2 ) case HETHDR_FLAGS1_BZLIB: tlen = sizeof( tbuf ); rc = BZ2_bzBuffToBuffCompress( tbuf, (void *) &tlen, sbuf, slen, hetb->level, 0, 0 ); if( rc != BZ_OK ) { errno = rc; return( HETE_COMPERR ); } if( (int)tlen < slen ) { sbuf = tbuf; slen = tlen; flags |= HETHDR_FLAGS1_BZLIB; } break; #endif /* defined( HET_BZIP2 ) */ } } /* || Save compressed length */ hetb->cblksize = slen; /* || Write block, breaking it into "chksize" chunks */ do { /* || Last chunk for this block? */ if( slen <= (int)hetb->chksize ) { flags |= HETHDR_FLAGS1_EOR; tlen = slen; } else { tlen = hetb->chksize; } /* || Write the header */ rc = het_write_header( hetb, tlen, flags, 0 ); if( rc < 0 ) { return( rc ); } /* || Write the block */ rc = fwrite( sbuf, 1, tlen, hetb->fd ); if( rc != (int)tlen ) { return( HETE_ERROR ); } /* || Bump pointers and turn off BOR flag */ { char *csbuf; csbuf=(char *)sbuf; csbuf+=tlen; sbuf=(void *)csbuf; } slen -= tlen; flags &= (~HETHDR_FLAGS1_BOR); } while( slen > 0 ); /* || Set new physical EOF */ do rc = ftruncate( fileno( hetb->fd ), ftell( hetb->fd ) ); while (EINTR == rc); if (rc != 0) { return( HETE_ERROR ); } /* || Success */ return( hetb->cblksize ); } /*==DOC== NAME het_tapemark - Write a tape mark to an HET file SYNOPSIS #include "hetlib.h" int het_tapemark( HETB *hetb ) DESCRIPTION Writes a special chunk header to an HET file to simulate a tape mark. RETURN VALUE If no errors are detected then the return value will be >= 0. If an error occurs, then the return value will be < 0 and will be the same as those returned by het_write_header(). EXAMPLE // // Write a tapemark to an HET file // #include "hetlib.h" int main( int argc, char *argv[] ) { HETB *hetb; int rc; rc = het_open( &hetb, argv[ 1 ], HETOPEN_CREATE ); if( rc >= 0 ) { rc = het_tapemark( hetb ); if( rc >= 0 ) { printf( "Tape mark written\n" ); } } if( rc < 0 ) { printf( "HETLIB error: %d\n", rc ); } het_close( &hetb ); return( 0 ); } SEE ALSO het_open(), het_write_header(), het_close() ==DOC==*/ DLL_EXPORT int het_tapemark( HETB *hetb ) { int rc; /* || Just write a tapemark header */ rc = het_write_header( hetb, 0, HETHDR_FLAGS1_TAPEMARK, 0 ); if( rc < 0 ) { return( rc ); } /* || Set new physical EOF */ do rc = ftruncate( fileno( hetb->fd ), ftell( hetb->fd ) ); while (EINTR == rc); if (rc != 0) { return( HETE_ERROR ); } /* || Success */ return( 0 ); } /*==DOC== NAME het_sync - commit/flush a HET file's buffers to disk SYNOPSIS #include "hetlib.h" int het_sync( HETB *hetb ) DESCRIPTION Calls the file system's "fdatasync" (or fsync) function to cause all data for the HET file to be transferred to disk by forcing a physical write of all data from the file's buffers or the file- system's cache, to the disk, thereby assuring that after a system crash or other failure, that all data up to the time of the call is thus recorded on the disk. RETURN VALUE If no errors are detected then the return value will be >= 0. If an error occurs, then the return value will be < 0 and will be one of the following: HETE_PROTECTED File is write protected HETE_ERROR File system error - check errno(3) EXAMPLE // // Flush a HET file's buffers to disk // #include "hetlib.h" char data[] = "This is a test"; int main( int argc, char *argv[] ) { HETB *hetb; int rc; rc = het_open( &hetb, argv[ 1 ], HETOPEN_CREATE ); if( rc >= 0 ) { rc = het_write( hetb, data, sizeof( data ) ); if( rc >= 0 ) { printf( "Block successfully written\n" ); rc = het_sync( &hetb ); if( rc >= 0 ) { printf( "Block successfully committed\n" ); } } } if( rc < 0 ) { printf( "HETLIB error: %d\n", rc ); } het_close( &hetb ); return( 0 ); } SEE ALSO het_open(), het_write(), het_close() ==DOC==*/ DLL_EXPORT int het_sync( HETB *hetb ) { int rc; /* || Can't sync to readonly media */ if( hetb->writeprotect ) { return( HETE_PROTECTED ); } /* || Perform the sync */ do rc = fdatasync( fileno( hetb->fd ) ); while (EINTR == rc); if (rc != 0) { return( HETE_ERROR ); } /* || Success */ return( 0 ); } /*==DOC== NAME het_locate - Locate a block within an HET file SYNOPSIS #include "hetlib.h" int het_locate( HETB *hetb, int block ) DESCRIPTION Repositions the HET file to the start of the block specified by the "block" parameter. RETURN VALUE If no errors are detected then the return value will be >= 0 and represents the new current block number. If an error occurs, then the return value will be < 0 and will the same as those returned by: het_rewind() het_fsb() NOTES Block numbers start at 0. EXAMPLE // // Seek to block #4 in HET file // #include "hetlib.h" int main( int argc, char *argv[] ) { HETB *hetb; int rc; rc = het_open( &hetb, argv[ 1 ], 0 ); if( rc >= 0 ) { rc = het_locate( hetb, 4 ); if( rc >= 0 ) { printf( "New tape position: %d\n", rc ); } } if( rc < 0 ) { printf( "HETLIB error: %d\n", rc ); } het_close( &hetb ); return( 0 ); } SEE ALSO het_open(), het_rewind(), het_fsb(), het_close() ==DOC==*/ DLL_EXPORT int het_locate( HETB *hetb, int block ) { int rc; /* || Start the search from the beginning */ rc = het_rewind( hetb ); if( rc < 0 ) { return( rc ); } /* || Forward space until we reach the desired block */ while( (int)hetb->cblk < block ) { rc = het_fsb( hetb ); if( rc < 0 && HETE_TAPEMARK != rc ) { return( rc ); } } return( hetb->cblk ); } /*==DOC== NAME het_bsb - Backspace a block in an HET file SYNOPSIS #include "hetlib.h" int het_bsb( HETB *hetb ) DESCRIPTION Repositions the current block pointer in an HET file to the previous block. RETURN VALUE If no errors are detected then the return value will be >= 0 and will be the new block number. If an error occurs, then the return value will be < 0 and can be one of the following: HETE_ERROR File system error - check errno(3) HETE_BOT Beginning of tape HETE_TAPEMARK Tape mark encountered For other possible errors, see: het_rewind() het_read_header() EXAMPLE // // Backspace a block in an HET file // #include "hetlib.h" int main( int argc, char *argv[] ) { HETB *hetb; int rc; rc = het_open( &hetb, argv[ 1 ], 0 ); if( rc >= 0 ) { rc = het_fsb( hetb ); if( rc >= 0 ) { rc = het_bsb( hetb ); if( rc >= 0 ) { printf( "New block number = %d\n", rc ); } } } if( rc < 0 ) { printf( "HETLIB error: %d\n", rc ); } het_close( &hetb ); return( 0 ); } SEE ALSO het_open(), het_rewind(), het_read_header(), het_fsb(), het_close() ==DOC==*/ DLL_EXPORT int het_bsb( HETB *hetb ) { int rc; int newblk; int offset; // (note: safe to use 'int' as offset here // since we only ever seek from SEEK_CUR) int tapemark = FALSE; /* || Error if at BOT */ if( hetb->cblk == 0 ) { return( HETE_BOT ); } /* || Get new block number */ newblk = hetb->cblk - 1; /* || If new block is first on, then just rewind */ if( newblk == 0 ) { return( het_rewind( hetb ) ); } /* || Calculate offset to get back to beginning of current block */ offset = -((int)( HETHDR_CLEN( hetb ) + sizeof( HETHDR ) )); /* || Search backwards an entire block. If the block is a tapemark, we can't || just return to caller since we must load the chunk header preceding it || to maintain the chdr in the HET. */ do { /* || Reposition to start of chunk */ rc = fseek( hetb->fd, offset, SEEK_CUR ); if( rc == -1 ) { return( HETE_ERROR ); } /* || Read header, ignoring tapemarks */ rc = het_read_header( hetb ); if( rc < 0 && rc != HETE_TAPEMARK ) { return( rc ); } /* || Recalculate offset */ offset = -((int)( HETHDR_PLEN( hetb ) + ( sizeof( HETHDR ) * 2 ) )); } while( hetb->chdr.flags1 & !( HETHDR_FLAGS1_BOR | HETHDR_FLAGS1_TAPEMARK ) ); /* || Remember whether it's a tapemark or not */ tapemark = ( hetb->chdr.flags1 & HETHDR_FLAGS1_TAPEMARK ); /* || Reposition to chunk header preceding this one so we can load keep the || chdr in the HET current. */ rc = fseek( hetb->fd, offset, SEEK_CUR ); if( rc == -1 ) { return( HETE_ERROR ); } /* || Read header (ignore tapemarks) */ rc = het_read_header( hetb ); if( rc < 0 && ( rc != HETE_TAPEMARK ) ) { return( rc ); } /* || Finally reposition back to the where we should be */ rc = fseek( hetb->fd, HETHDR_CLEN( hetb ), SEEK_CUR ); if( rc == -1 ) { return( HETE_ERROR ); } /* || Store new block number */ hetb->cblk = newblk; /* || Was it a tapemark? */ if( tapemark ) { return( HETE_TAPEMARK ); } /* || Reset flag to force truncation if a write occurs */ hetb->truncated = FALSE; /* || Return block number */ return( hetb->cblk ); } /*==DOC== NAME het_fsb - Foward space a block in an HET file SYNOPSIS #include "hetlib.h" int het_fsb( HETB *hetb ) DESCRIPTION Repositions the current block pointer in an HET file to the next block. RETURN VALUE If no errors are detected then the return value will be >= 0 and will be the new block number. If an error occurs, then the return value will be < 0 and can be one of the following: HETE_ERROR File system error - check errno(3) For other possible errors, see: het_read_header() EXAMPLE // // Forward space a block in an HET file // #include "hetlib.h" int main( int argc, char *argv[] ) { HETB *hetb; int rc; rc = het_open( &hetb, argv[ 1 ], 0 ); if( rc >= 0 ) { rc = het_fsb( hetb ); if( rc >= 0 ) { printf( "New block number = %d\n", rc ); } } if( rc < 0 ) { printf( "HETLIB error: %d\n", rc ); } het_close( &hetb ); return( 0 ); } SEE ALSO het_open(), het_read_header(), het_close() ==DOC==*/ DLL_EXPORT int het_fsb( HETB *hetb ) { int rc; /* || Loop until we've processed an entire block */ do { /* || Read header to get length of next chunk */ rc = het_read_header( hetb ); if( rc < 0 ) { return( rc ); } /* || Seek to next chunk */ rc = fseek( hetb->fd, HETHDR_CLEN( hetb ), SEEK_CUR ); if( rc == -1 ) { return( HETE_ERROR ); } } while( !( hetb->chdr.flags1 & HETHDR_FLAGS1_EOR ) ); /* || Reset flag to force truncation if a write occurs */ hetb->truncated = FALSE; /* || Return block number */ return( hetb->cblk ); } /*==DOC== NAME het_bsf - Backspace a file in an HET file SYNOPSIS #include "hetlib.h" int het_bsf( HETB *hetb ) DESCRIPTION Repositions the current block pointer in an HET file to the previous tapemark. RETURN VALUE If no errors are detected then the return value will be >= 0 and will be the new block number. If an error occurs, then the return value will be < 0 and will be the same as those returned by het_bsb() with the exception that HETE_TAPEMARK and HETE_BOT will not occur. EXAMPLE // // Backspace a file in an HET file // #include "hetlib.h" int main( int argc, char *argv[] ) { HETB *hetb; int rc; rc = het_open( &hetb, argv[ 1 ], 0 ); if( rc >= 0 ) { rc = het_fsf( hetb ); if( rc >= 0 ) { rc = het_bsf( hetb ); if( rc >= 0 ) { printf( "Backspaced (sort of :-))\n" ); } } } if( rc < 0 ) { printf( "HETLIB error: %d\n", rc ); } het_close( &hetb ); return( 0 ); } SEE ALSO het_open(), het_bsb(), het_fsf(), het_close() ==DOC==*/ DLL_EXPORT int het_bsf( HETB *hetb ) { int rc; /* || Backspace until we hit a tapemark */ do { rc = het_bsb( hetb ); } while( rc >= 0 ); /* || Success */ if( ( rc == HETE_BOT ) || ( rc == HETE_TAPEMARK ) ) { return( hetb->cblk ); } /* || Failure */ return( rc ); } /*==DOC== NAME het_fsf - Forward space a file in an HET file SYNOPSIS #include "hetlib.h" int het_fsf( HETB *hetb ) DESCRIPTION Repositions the current block pointer in an HET file to the next tapemark. RETURN VALUE If no errors are detected then the return value will be >= 0 and will be the new block number. If an error occurs, then the return value will be < 0 and will be the same as those returned by het_fsb() with the exception that HETE_TAPEMARK will not occur. EXAMPLE // // Forward space a file in an HET file // #include "hetlib.h" int main( int argc, char *argv[] ) { HETB *hetb; int rc; rc = het_open( &hetb, argv[ 1 ], 0 ); if( rc >= 0 ) { rc = het_fsf( hetb ); if( rc >= 0 ) { printf( "Forward spaced\n" ); } } if( rc < 0 ) { printf( "HETLIB error: %d\n", rc ); } het_close( &hetb ); return( 0 ); } SEE ALSO het_open(), het_fsb(), het_close() ==DOC==*/ DLL_EXPORT int het_fsf( HETB *hetb ) { int rc; /* || Forward space until we hit a tapemark */ do { rc = het_fsb( hetb ); } while( rc >= 0 ); /* || Success */ if( rc == HETE_TAPEMARK ) { return( hetb->cblk ); } /* || Failure */ return( rc ); } /*==DOC== NAME het_rewind - Rewind an HET file SYNOPSIS #include "hetlib.h" int het_rewind( HETB *hetb ) DESCRIPTION Repositions the current block pointer in an HET file to the load point. RETURN VALUE If no errors are detected then the return value will be >= 0 and represents the new block number (always 0). If an error occurs, then the return value will be < 0 and will be one of the following: HETE_ERROR File system error - check errno(3) EXAMPLE // // Rewind an HET file to the load point. // #include "hetlib.h" int main( int argc, char *argv[] ) { HETB *hetb; int rc; rc = het_open( &hetb, argv[ 1 ], 0 ); if( rc >= 0 ) { rc = het_rewind( hetb ); if( rc >= 0 ) { printf( "Tape rewound\n" ); } } if( rc < 0 ) { printf( "HETLIB error: %d\n", rc ); } het_close( &hetb ); return( 0 ); } SEE ALSO het_open(), het_close() ==DOC==*/ DLL_EXPORT int het_rewind( HETB *hetb ) { int rc; /* || Just seek to the beginning of the file */ rc = fseek( hetb->fd, 0, SEEK_SET ); if( rc == -1 ) { return( HETE_ERROR ); } /* || Reset current block */ hetb->cblk = 0; /* || Clear header for the heck of it */ memset( &hetb->chdr, 0, sizeof( hetb->chdr ) ); /* || Reset flag to force truncation if a write occurs */ hetb->truncated = FALSE; /* || Return block number */ return( hetb->cblk ); } /*==DOC== NAME het_error - Returns a text message for an HET error code SYNOPSIS #include "hetlib.h" char *het_error( int rc ) DESCRIPTION Simply returns a pointer to a string that describes the error code passed in the "rc" parameter. RETURN VALUE The return value is always valid and no errors are returned. EXAMPLE // // Print text of HETE_BADLEN. // #include "hetlib.h" int main( int argc, char *argv[] ) { printf( "HETLIB error: %d = %s\n", HETE_BADLEN, het_error( HETE_BADLEN ) ); return( 0 ); } SEE ALSO ==DOC==*/ DLL_EXPORT const char * het_error( int rc ) { /* || If not an error just return the "OK" string */ if( rc >= 0 ) { rc = 0; } /* || Turn it into an index */ rc = -rc; /* || Within range? */ if( rc >= (int)HET_ERRSTR_MAX ) { rc = HET_ERRSTR_MAX - 1; } /* || Return string */ return( het_errstr[ rc ] ); } /*==DOC== NAME het_tell - Returns the current read/write pointer offset SYNOPSIS #include "hetlib.h" off_t het_tell( HETB *hetb ) DESCRIPTION Returns a off_t describing the actual read/write cursor within the HET file RETURN VALUE >=0 The actual cursor offset <0 An error occured. Possible errors are : HETE_ERROR - File system error occured EXAMPLE // // Get the current HET pointer // #include "hetlib.h" int main( int argc, char *argv[] ) { HETB *hetb; int rc; off_t rwptr; rc = het_open( &hetb, argv[ 1 ], 0 ); if( rc >= 0 ) { rwptr = het_tell( hetb ); if( rwptr >= 0 ) { printf( "Current offset is %" I64_FMT "d\n" , (U64)rwptr); } } if( rc < 0 ) { printf( "HETLIB error: %d\n", rc ); } het_close( &hetb ); return( 0 ); } SEE ALSO ==DOC==*/ DLL_EXPORT off_t het_tell( HETB *hetb ) { off_t rwptr = ftell( hetb->fd ); if ( rwptr < 0 ) { return HETE_ERROR; } return rwptr; } hercules-3.07/hetlib.h000644 000765 000765 00000020772 11143760544 016400 0ustar00jmaynardjmaynard000000 000000 #if !defined( _HETLIB_H_ ) #define _HETLIB_H_ /* || ---------------------------------------------------------------------------- || || HETLIB.H (c) Copyright Leland Lucius, 2000-2009 || Released under terms of the Q Public License. || || Header for the Hercules Emulated Tape library. || || ---------------------------------------------------------------------------- */ // $Id: hetlib.h 5125 2009-01-23 12:01:44Z bernard $ // // $Log$ // Revision 1.18 2007/07/24 22:36:33 fish // Fix tape Synchronize CCW (x'43') to do actual commit // // Revision 1.17 2007/06/23 00:04:11 ivan // Update copyright notices to include current year (2007) // // Revision 1.16 2006/12/08 09:43:26 jj // Add CVS message log // #include "hercules.h" #ifndef _HETLIB_C_ #ifndef _HTAPE_DLL_ #define HET_DLL_IMPORT DLL_IMPORT #else /* _HUTIL_DLL_ */ #define HET_DLL_IMPORT extern #endif /* _HUTIL_DLL_ */ #else #define HET_DLL_IMPORT DLL_EXPORT #endif #if !defined( TRUE ) #define TRUE (1L) #endif #if !defined( FALSE ) #define FALSE (0L) #endif /* || Chunk header for an HET. Physically compatable with AWSTAPE format. */ typedef struct _hethdr { uint8_t clen[ 2 ]; /* Length of current block */ uint8_t plen[ 2 ]; /* Length of previous block */ uint8_t flags1; /* Flags byte 1 */ uint8_t flags2; /* Flags byte 2 */ } HETHDR; /* || Macros for accessing current and previous sizes - accept ptr to HETHDR */ #define HETHDR_CLEN( h ) ( ( (h)->chdr.clen[ 1 ] << 8 ) + (h)->chdr.clen[ 0 ] ) #define HETHDR_PLEN( h ) ( ( (h)->chdr.plen[ 1 ] << 8 ) + (h)->chdr.plen[ 0 ] ) /* || Definitions for HETHDR flags byte 1 (compression incompatable with AWSTAPE) */ #define HETHDR_FLAGS1_BOR 0x80 /* Start of new record */ #define HETHDR_FLAGS1_TAPEMARK 0x40 /* Tape mark */ #define HETHDR_FLAGS1_EOR 0x20 /* End of record */ #define HETHDR_FLAGS1_COMPRESS 0x03 /* Compression method mask */ #define HETHDR_FLAGS1_BZLIB 0x02 /* BZLIB compression */ #define HETHDR_FLAGS1_ZLIB 0x01 /* ZLIB compression */ /* || Definitions for HETHDR flags byte 2 (incompatable with AWSTAPE and HET) */ #define HETHDR_FLAGS2_COMPRESS 0x80 /* Compression method mask */ #define HETHDR_FLAGS2_ZLIB_BUSTECH 0x80 /* Bus-Tech ZLIB compression */ /* || Control block for Hercules Emulated Tape files */ typedef struct _hetb { FILE *fd; /* Tape file descriptor */ uint32_t chksize; /* Size of output chunks */ uint32_t ublksize; /* Current block compressed size */ uint32_t cblksize; /* Current block uncompressed size */ uint32_t cblk; /* Current block number */ HETHDR chdr; /* Current block header */ u_int writeprotect:1; /* TRUE=write protected */ u_int readlast:1; /* TRUE=last i/o was read */ u_int truncated:1; /* TRUE=file truncated */ u_int compress:1; /* TRUE=compress written data */ u_int decompress:1; /* TRUE=decompress read data */ u_int method:2; /* 1=ZLIB, 2=BZLIB compresion */ u_int level:4; /* 1=fd ); if( ( curpos & PROGRESS_MASK ) != ( prevpos & PROGRESS_MASK ) ) { prevpos = curpos; fprintf( stderr, "IPOS=%" I64_FMT "d\n", (U64)curpos ); } } #endif /*EXTERNALGUI*/ rc = het_read( hetb, buf ); if( rc == HETE_EOT ) { if( opts & O_TAPEMAP_OUTPUT ) { printf ("End of tape.\n"); } break; } if( rc == HETE_TAPEMARK ) { fileno += 1; if( opts & O_TAPEMAP_OUTPUT ) { printf ("File %u: Blocks=%u, block size min=%u, max=%u\n", fileno, blocks, uminsz, umaxsz ); } if( opts & O_FILES ) { printf( sep ); printf( "%-20.20s: %d\n", "File #", fileno ); printf( "%-20.20s: %d\n", "Blocks", blocks ); printf( "%-20.20s: %d\n", "Min Blocksize", uminsz ); printf( "%-20.20s: %d\n", "Max Blocksize", umaxsz ); printf( "%-20.20s: %d\n", "Uncompressed bytes", ubytes ); printf( "%-20.20s: %d\n", "Min Blocksize-Comp", cminsz ); printf( "%-20.20s: %d\n", "Max Blocksize-Comp", cmaxsz ); printf( "%-20.20s: %d\n", "Compressed bytes", cbytes ); } totblocks += blocks; totubytes += ubytes; totcbytes += cbytes; blocks = 0; uminsz = 0; umaxsz = 0; ubytes = 0; cminsz = 0; cmaxsz = 0; cbytes = 0; continue; } if( rc < 0 ) { printf( "het_read() returned %d\n", rc ); break; } blocks += 1; ubytes += hetb->ublksize; cbytes += hetb->cblksize; if( uminsz == 0 || hetb->ublksize < uminsz ) uminsz = hetb->ublksize; if( hetb->ublksize > umaxsz ) umaxsz = hetb->ublksize; if( cminsz == 0 || hetb->cblksize < cminsz ) cminsz = hetb->cblksize; if( hetb->cblksize > cmaxsz ) cmaxsz = hetb->cblksize; if( opts & O_LABELS ) { printlabel( buf, rc ); } if( opts & O_TAPEMAP_OUTPUT ) { printlabeltapemap( buf, rc ); } if( opts & O_DATASETS ) { printdataset( buf, rc, fileno ); } } if( opts & O_FILES ) { printf( sep ); printf( "%-20.20s:\n", "Summary" ); printf( "%-20.20s: %d\n", "Files", fileno ); printf( "%-20.20s: %d\n", "Blocks", totblocks ); printf( "%-20.20s: %d\n", "Uncompressed bytes", totubytes ); printf( "%-20.20s: %d\n", "Compressed bytes", totcbytes ); printf( "%-20.20s: %d\n", "Reduction", totubytes - totcbytes ); } het_close( &hetb ); return 0; } hercules-3.07/hettape.c000644 000765 000765 00000044131 11321734033 016541 0ustar00jmaynardjmaynard000000 000000 /* HETTAPE.C (c) Copyright Roger Bowler, 1999-2009 */ /* Hercules Tape Device Handler for HETTAPE */ /* Original Author: Leland Lucius */ /* Prime Maintainer: Ivan Warren */ /* Secondary Maintainer: "Fish" (David B. Trout) */ // $Id: hettape.c 5587 2009-12-31 15:05:57Z rbowler $ /*-------------------------------------------------------------------*/ /* This module contains the HET emulated tape format support. */ /* */ /* The subroutines in this module are called by the general tape */ /* device handler (tapedev.c) when the tape format is HETTAPE. */ /* */ /* Messages issued by this module are prefixed HHCTA4nn */ /*-------------------------------------------------------------------*/ #include "hstdinc.h" #include "hercules.h" /* need Hercules control blocks */ #include "tapedev.h" /* Main tape handler header file */ //#define ENABLE_TRACING_STMTS // (Fish: DEBUGGING) #ifdef ENABLE_TRACING_STMTS #if !defined(DEBUG) #warning DEBUG required for ENABLE_TRACING_STMTS #endif // (TRACE, ASSERT, and VERIFY macros are #defined in hmacros.h) #else #undef TRACE #undef ASSERT #undef VERIFY #define TRACE 1 ? ((void)0) : logmsg #define ASSERT(a) #define VERIFY(a) ((void)(a)) #endif /*-------------------------------------------------------------------*/ /* Open an HET format file */ /* */ /* If successful, the het control blk is stored in the device block */ /* and the return value is zero. Otherwise the return value is -1. */ /*-------------------------------------------------------------------*/ int open_het (DEVBLK *dev, BYTE *unitstat,BYTE code) { int rc; /* Return code */ /* Check for no tape in drive */ if (!strcmp (dev->filename, TAPE_UNLOADED)) { build_senseX(TAPE_BSENSE_TAPEUNLOADED,dev,unitstat,code); return -1; } /* Open the HET file */ rc = het_open (&dev->hetb, dev->filename, dev->tdparms.logical_readonly ? HETOPEN_READONLY : HETOPEN_CREATE ); if (rc >= 0) { if(dev->hetb->writeprotect) { dev->readonly=1; } rc = het_cntl (dev->hetb, HETCNTL_SET | HETCNTL_COMPRESS, dev->tdparms.compress); if (rc >= 0) { rc = het_cntl (dev->hetb, HETCNTL_SET | HETCNTL_METHOD, dev->tdparms.method); if (rc >= 0) { rc = het_cntl (dev->hetb, HETCNTL_SET | HETCNTL_LEVEL, dev->tdparms.level); if (rc >= 0) { rc = het_cntl (dev->hetb, HETCNTL_SET | HETCNTL_CHUNKSIZE, dev->tdparms.chksize); } } } } /* Check for successful open */ if (rc < 0) { int save_errno = errno; het_close (&dev->hetb); errno = save_errno; logmsg (_("HHCTA401E %4.4X: Error opening %s: %s(%s)\n"), dev->devnum, dev->filename, het_error(rc), strerror(errno)); strcpy(dev->filename, TAPE_UNLOADED); build_senseX(TAPE_BSENSE_TAPELOADFAIL,dev,unitstat,code); return -1; } /* Indicate file opened */ dev->fd = 1; return 0; } /* end function open_het */ /*-------------------------------------------------------------------*/ /* Close an HET format file */ /* */ /* The HET file is close and all device block fields reinitialized. */ /*-------------------------------------------------------------------*/ void close_het (DEVBLK *dev) { /* Close the HET file */ het_close (&dev->hetb); /* Reinitialize the DEV fields */ dev->fd = -1; strcpy (dev->filename, TAPE_UNLOADED); dev->blockid = 0; dev->fenced = 0; return; } /* end function close_het */ /*-------------------------------------------------------------------*/ /* Rewind HET format file */ /* */ /* The HET file is close and all device block fields reinitialized. */ /*-------------------------------------------------------------------*/ int rewind_het(DEVBLK *dev,BYTE *unitstat,BYTE code) { int rc; rc = het_rewind (dev->hetb); if (rc < 0) { /* Handle seek error condition */ logmsg (_("HHCTA402E %4.4X: Error seeking to start of %s: %s(%s)\n"), dev->devnum, dev->filename, het_error(rc), strerror(errno)); build_senseX(TAPE_BSENSE_REWINDFAILED,dev,unitstat,code); return -1; } dev->nxtblkpos=0; dev->prvblkpos=-1; dev->curfilen=1; dev->blockid=0; dev->fenced = 0; return 0; } /*-------------------------------------------------------------------*/ /* Read a block from an HET format file */ /* */ /* If successful, return value is block length read. */ /* If a tapemark was read, the return value is zero, and the */ /* current file number in the device block is incremented. */ /* If error, return value is -1 and unitstat is set to CE+DE+UC */ /*-------------------------------------------------------------------*/ int read_het (DEVBLK *dev, BYTE *buf, BYTE *unitstat,BYTE code) { int rc; /* Return code */ rc = het_read (dev->hetb, buf); if (rc < 0) { /* Increment file number and return zero if tapemark was read */ if (rc == HETE_TAPEMARK) { dev->curfilen++; dev->blockid++; return 0; } /* Handle end of file (uninitialized tape) condition */ if (rc == HETE_EOT) { logmsg (_("HHCTA414E %4.4X: End of file (end of tape) " "at block %8.8X in file %s\n"), dev->devnum, dev->hetb->cblk, dev->filename); /* Set unit exception with tape indicate (end of tape) */ build_senseX(TAPE_BSENSE_ENDOFTAPE,dev,unitstat,code); return -1; } logmsg (_("HHCTA415E %4.4X: Error reading data block " "at block %8.8X in file %s: %s(%s)\n"), dev->devnum, dev->hetb->cblk, dev->filename, het_error(rc), strerror(errno)); /* Set unit check with equipment check */ build_senseX(TAPE_BSENSE_READFAIL,dev,unitstat,code); return -1; } dev->blockid++; /* Return block length */ return rc; } /* end function read_het */ /*-------------------------------------------------------------------*/ /* Write a block to an HET format file */ /* */ /* If successful, return value is zero. */ /* If error, return value is -1 and unitstat is set to CE+DE+UC */ /*-------------------------------------------------------------------*/ int write_het (DEVBLK *dev, BYTE *buf, U16 blklen, BYTE *unitstat,BYTE code) { int rc; /* Return code */ off_t cursize; /* Current size for size chk */ /* Check if we have already violated the size limit */ if(dev->tdparms.maxsize>0) { cursize=het_tell(dev->hetb); if(cursize>=dev->tdparms.maxsize) { build_senseX(TAPE_BSENSE_ENDOFTAPE,dev,unitstat,code); return -1; } } /* Write the data block */ rc = het_write (dev->hetb, buf, blklen); if (rc < 0) { /* Handle write error condition */ logmsg (_("HHCTA416E %4.4X: Error writing data block " "at block %8.8X in file %s: %s(%s)\n"), dev->devnum, dev->hetb->cblk, dev->filename, het_error(rc), strerror(errno)); /* Set unit check with equipment check */ build_senseX(TAPE_BSENSE_WRITEFAIL,dev,unitstat,code); return -1; } /* Check if we have violated the maxsize limit */ /* Also check if we are passed EOT marker */ if(dev->tdparms.maxsize>0) { cursize=het_tell(dev->hetb); if(cursize>dev->tdparms.maxsize) { logmsg (_("HHCTA430I %4.4X: max tape capacity exceeded\n"), dev->devnum); if(dev->tdparms.strictsize) { logmsg (_("HHCTA431I %4.4X: max tape capacity enforced\n"), dev->devnum); het_bsb(dev->hetb); cursize=het_tell(dev->hetb); ftruncate( fileno(dev->hetb->fd),cursize); dev->hetb->truncated=TRUE; /* SHOULD BE IN HETLIB */ } build_senseX(TAPE_BSENSE_ENDOFTAPE,dev,unitstat,code); return -1; } } /* Return normal status */ dev->blockid++; return 0; } /* end function write_het */ /*-------------------------------------------------------------------*/ /* Write a tapemark to an HET format file */ /* */ /* If successful, return value is zero. */ /* If error, return value is -1 and unitstat is set to CE+DE+UC */ /*-------------------------------------------------------------------*/ int write_hetmark (DEVBLK *dev, BYTE *unitstat,BYTE code) { int rc; /* Return code */ /* Write the tape mark */ rc = het_tapemark (dev->hetb); if (rc < 0) { /* Handle error condition */ logmsg (_("HHCTA417E %4.4X: Error writing tape mark " "at block %8.8X in file %s: %s(%s)\n"), dev->devnum, dev->hetb->cblk, dev->filename, het_error(rc), strerror(errno)); /* Set unit check with equipment check */ build_senseX(TAPE_BSENSE_WRITEFAIL,dev,unitstat,code); return -1; } /* Return normal status */ dev->blockid++; return 0; } /* end function write_hetmark */ /*-------------------------------------------------------------------*/ /* Synchronize a HET format file (i.e. flush its buffers to disk) */ /* */ /* If successful, return value is zero. */ /* If error, return value is -1 and unitstat is set to CE+DE+UC */ /*-------------------------------------------------------------------*/ int sync_het(DEVBLK *dev, BYTE *unitstat,BYTE code) { int rc; /* Return code */ /* Perform the flush */ rc = het_sync (dev->hetb); if (rc < 0) { /* Handle error condition */ if (HETE_PROTECTED == rc) build_senseX(TAPE_BSENSE_WRITEPROTECT,dev,unitstat,code); else { logmsg (_("HHCTA488E %4.4X: Sync error on file %s: %s\n"), dev->devnum, dev->filename, strerror(errno)); build_senseX(TAPE_BSENSE_WRITEFAIL,dev,unitstat,code); } return -1; } /* Return normal status */ return 0; } /* end function sync_het */ /*-------------------------------------------------------------------*/ /* Forward space over next block of an HET format file */ /* */ /* If successful, return value +1. */ /* If the block skipped was a tapemark, the return value is zero, */ /* and the current file number in the device block is incremented. */ /* If error, return value is -1 and unitstat is set to CE+DE+UC */ /*-------------------------------------------------------------------*/ int fsb_het (DEVBLK *dev, BYTE *unitstat,BYTE code) { int rc; /* Return code */ /* Forward space one block */ rc = het_fsb (dev->hetb); if (rc < 0) { /* Increment file number and return zero if tapemark was read */ if (rc == HETE_TAPEMARK) { dev->blockid++; dev->curfilen++; return 0; } logmsg (_("HHCTA418E %4.4X: Error forward spacing " "at block %8.8X in file %s: %s(%s)\n"), dev->devnum, dev->hetb->cblk, dev->filename, het_error(rc), strerror(errno)); /* Set unit check with equipment check */ if(rc==HETE_EOT) { build_senseX(TAPE_BSENSE_ENDOFTAPE,dev,unitstat,code); } else { build_senseX(TAPE_BSENSE_READFAIL,dev,unitstat,code); } return -1; } dev->blockid++; /* Return +1 to indicate forward space successful */ return +1; } /* end function fsb_het */ /*-------------------------------------------------------------------*/ /* Backspace to previous block of an HET format file */ /* */ /* If successful, return value will be +1. */ /* If the block is a tapemark, the return value is zero, */ /* and the current file number in the device block is decremented. */ /* If error, return value is -1 and unitstat is set to CE+DE+UC */ /*-------------------------------------------------------------------*/ int bsb_het (DEVBLK *dev, BYTE *unitstat,BYTE code) { int rc; /* Return code */ /* Back space one block */ rc = het_bsb (dev->hetb); if (rc < 0) { /* Increment file number and return zero if tapemark was read */ if (rc == HETE_TAPEMARK) { dev->blockid--; dev->curfilen--; return 0; } /* Unit check if already at start of tape */ if (rc == HETE_BOT) { build_senseX(TAPE_BSENSE_LOADPTERR,dev,unitstat,code); return -1; } logmsg (_("HHCTA419E %4.4X: Error reading data block " "at block %8.8X in file %s: %s(%s)\n"), dev->devnum, dev->hetb->cblk, dev->filename, het_error(rc), strerror(errno)); /* Set unit check with equipment check */ build_senseX(TAPE_BSENSE_READFAIL,dev,unitstat,code); return -1; } dev->blockid--; /* Return +1 to indicate back space successful */ return +1; } /* end function bsb_het */ /*-------------------------------------------------------------------*/ /* Forward space to next logical file of HET format file */ /* */ /* If successful, return value is zero, and the current file number */ /* in the device block is incremented. */ /* If error, return value is -1 and unitstat is set to CE+DE+UC */ /*-------------------------------------------------------------------*/ int fsf_het (DEVBLK *dev, BYTE *unitstat,BYTE code) { int rc; /* Return code */ /* Forward space to start of next file */ rc = het_fsf (dev->hetb); if (rc < 0) { logmsg (_("HHCTA420E %4.4X: Error forward spacing to next file " "at block %8.8X in file %s: %s(%s)\n"), dev->devnum, dev->hetb->cblk, dev->filename, het_error(rc), strerror(errno)); if(rc==HETE_EOT) { build_senseX(TAPE_BSENSE_ENDOFTAPE,dev,unitstat,code); } else { build_senseX(TAPE_BSENSE_READFAIL,dev,unitstat,code); } return -1; } /* Maintain position */ dev->blockid = rc; dev->curfilen++; /* Return success */ return 0; } /* end function fsf_het */ /*-------------------------------------------------------------------*/ /* Check HET file is passed the allowed EOT margin */ /*-------------------------------------------------------------------*/ int passedeot_het (DEVBLK *dev) { off_t cursize; if(dev->fd>0) { if(dev->tdparms.maxsize>0) { cursize=het_tell(dev->hetb); if(cursize+dev->eotmargin>dev->tdparms.maxsize) { dev->eotwarning = 1; return 1; } } } dev->eotwarning = 0; return 0; } /*-------------------------------------------------------------------*/ /* Backspace to previous logical file of HET format file */ /* */ /* If successful, return value is zero, and the current file number */ /* in the device block is decremented. */ /* If error, return value is -1 and unitstat is set to CE+DE+UC */ /*-------------------------------------------------------------------*/ int bsf_het (DEVBLK *dev, BYTE *unitstat,BYTE code) { int rc; /* Return code */ /* Exit if already at BOT */ if (dev->curfilen==1 && dev->nxtblkpos == 0) { build_senseX(TAPE_BSENSE_LOADPTERR,dev,unitstat,code); return -1; } rc = het_bsf (dev->hetb); if (rc < 0) { logmsg (_("HHCTA421E %4.4X: Error back spacing to previous file " "at block %8.8X in file %s:\n %s(%s)\n"), dev->devnum, dev->hetb->cblk, dev->filename, het_error(rc), strerror(errno)); build_senseX(TAPE_BSENSE_LOCATEERR,dev,unitstat,code); return -1; } /* Maintain position */ dev->blockid = rc; dev->curfilen--; /* Return success */ return 0; } /* end function bsf_het */ hercules-3.07/hetupd.c000644 000765 000765 00000021362 11143760543 016410 0ustar00jmaynardjmaynard000000 000000 /* || ---------------------------------------------------------------------------- || || HETUPD.C (c) Copyright Leland Lucius, 2000-2009 || Released under terms of the Q Public License. || || Copy/update Hercules Emulated Tapes while allowing various modifications || like enabling/disabling compression, changing compression method/level, and || internal chunk size. || || ---------------------------------------------------------------------------- */ // $Id: hetupd.c 5125 2009-01-23 12:01:44Z bernard $ // // $Log$ // Revision 1.27 2008/11/04 04:50:46 fish // Ensure consistent utility startup // // Revision 1.26 2007/06/23 00:04:11 ivan // Update copyright notices to include current year (2007) // // Revision 1.25 2006/12/08 09:43:26 jj // Add CVS message log // #include "hstdinc.h" #include "hercules.h" #include "hetlib.h" #include "sllib.h" #include "herc_getopt.h" /* || Local volatile data */ static int o_chunksize = HETDFLT_CHKSIZE; static int o_decompress = HETDFLT_DECOMPRESS; static int o_compress = HETDFLT_COMPRESS; static int o_level = HETDFLT_LEVEL; static int o_method = HETDFLT_METHOD; static int o_verbose = FALSE; static char *o_sname = NULL; static char *o_dname = NULL; static int dorename = FALSE; static HETB *s_hetb = NULL; static HETB *d_hetb = NULL; #ifdef EXTERNALGUI /* Previous reported file position */ static off_t prevpos = 0; /* Report progress every this many bytes */ #define PROGRESS_MASK (~0x3FFFF /* 256K */) #endif /*EXTERNALGUI*/ /* || Local constant data */ static const char help[] = "%s - Updates the compression of a Hercules Emulated Tape file.\n\n" "Usage: %s [options] source [dest]\n\n" "Options:\n" " -1 compress fast\n" " ...\n" " -9 compress best\n" #if defined( HET_BZIP2 ) " -b use BZLIB compression\n" #endif /* defined( HET_BZIP2 ) */ " -c n set chunk size to \"n\"\n" " -d decompress source tape\n" " -h display usage summary\n" " -r rechucnk\n" " -s strict AWSTAPE specification (chunksize=4096,no compression)\n" " -v verbose information\n" " -z use ZLIB compression\n"; /* || Prints usage information */ static void usage( char *name ) { printf( help, name, name ); } /* || Supply "Yes" or "No" */ static const char * yesno( int val ) { return( ( val ? "Yes" : "No" ) ); } /* || Close tapes and cleanup */ static void closetapes( int rc ) { het_close( &d_hetb ); het_close( &s_hetb ); if( dorename ) { if( rc >= 0 ) { rc = rename( o_dname, o_sname ); } else { rc = remove( o_dname ); } if( rc == -1 ) { printf( "Error renaming files - manual checks required\n"); } } return; } /* || Copy source to dest */ static int copytape( void ) { int rc; char buf[ HETMAX_BLOCKSIZE ]; while( TRUE ) { #ifdef EXTERNALGUI if( extgui ) { /* Report progress every nnnK */ off_t curpos = ftell( s_hetb->fd ); if( ( curpos & PROGRESS_MASK ) != ( prevpos & PROGRESS_MASK ) ) { prevpos = curpos; fprintf( stderr, "IPOS=%" I64_FMT "d\n", (U64)curpos ); } } #endif /*EXTERNALGUI*/ rc = het_read( s_hetb, buf ); if( rc == HETE_EOT ) { rc = 0; break; } if( rc == HETE_TAPEMARK ) { rc = het_tapemark( d_hetb ); if( rc < 0 ) { printf( "Error writing tapemark - rc: %d\n", rc ); break; } continue; } if( rc < 0 ) { printf( "het_read() returned %d\n", rc ); break; } rc = het_write( d_hetb, buf, rc ); if( rc < 0 ) { printf( "het_write() returned %d\n", rc ); break; } } return( rc ); } /* || Open HET tapes and set options */ static int opentapes( void ) { int rc; rc = het_open( &s_hetb, o_sname, 0 ); if( rc < 0 ) { goto exit; } rc = het_open( &d_hetb, o_dname, HETOPEN_CREATE ); if( rc < 0 ) { goto exit; } rc = het_cntl( s_hetb, HETCNTL_SET | HETCNTL_DECOMPRESS, o_decompress ); if( rc < 0 ) { goto exit; } rc = het_cntl( d_hetb, HETCNTL_SET | HETCNTL_COMPRESS, o_compress ); if( rc < 0 ) { goto exit; } rc = het_cntl( d_hetb, HETCNTL_SET | HETCNTL_METHOD, o_method ); if( rc < 0 ) { goto exit; } rc = het_cntl( d_hetb, HETCNTL_SET | HETCNTL_LEVEL, o_level ); if( rc < 0 ) { goto exit; } rc = het_cntl( d_hetb, HETCNTL_SET | HETCNTL_CHUNKSIZE, o_chunksize ); if( rc < 0 ) { goto exit; } if( o_verbose ) { printf( "Source : %s\n", o_sname ); printf( "Destination : %s\n", o_dname ); printf( "Decompress source : %s\n", yesno( het_cntl( s_hetb, HETCNTL_DECOMPRESS, 0 ) ) ); printf( "Compress dest : %s\n", yesno( het_cntl( d_hetb, HETCNTL_COMPRESS, 0 ) ) ); printf( "Compression method : %d\n", het_cntl( d_hetb, HETCNTL_METHOD, 0 ) ); printf( "Compression level : %d\n", het_cntl( d_hetb, HETCNTL_LEVEL, 0 ) ); } exit: if( rc < 0 ) { het_close( &d_hetb ); het_close( &s_hetb ); } return( rc ); } /* || Standard main */ int main( int argc, char *argv[] ) { char toname[ PATH_MAX ]; HETB *s_hetb; HETB *d_hetb; int rc; INITIALIZE_UTILITY("hetupd"); s_hetb = NULL; d_hetb = NULL; /* Display the program identification message */ display_version (stderr, "Hercules HET copy/update program ", FALSE); while( TRUE ) { #if defined( HET_BZIP2 ) rc = getopt( argc, argv, "bc:dhrsvz0123456789" ); #else rc = getopt( argc, argv, "c:dhrsvz0123456789" ); #endif /* defined( HET_BZIP2 ) */ if( rc == -1 ) { break; } switch( rc ) { case '1': case '2': case '3': case '4': /* Compression level */ case '5': case '6': case '7': case '8': case '9': o_level = ( rc - '0' ); break; #if defined( HET_BZIP2 ) case 'b': /* Use BZLIB compression */ o_method = HETMETH_BZLIB; o_compress = TRUE; o_decompress = TRUE; break; #endif /* defined( HET_BZIP2 ) */ case 'c': /* Chunk size */ o_chunksize = atoi( optarg ); break; case 'd': /* Decompress */ o_compress = FALSE; o_decompress = TRUE; break; case 'h': /* Print usage */ usage( argv[ 0 ] ); exit( 1 ); break; case 'r': /* Rechunk */ o_compress = FALSE; o_decompress = FALSE; break; case 's': /* Strict HET spec */ o_chunksize = 4096; o_compress = FALSE; o_decompress = TRUE; break; case 'v': /* Be chatty */ o_verbose = TRUE; break; case 'z': /* Use ZLIB compression */ o_method = HETMETH_ZLIB; o_compress = TRUE; o_decompress = TRUE; break; default: /* Print usage */ usage( argv[ 0 ] ); exit( 1 ); break; } } argc -= optind; switch( argc ) { case 1: sprintf( toname, "%s.%010d", argv[ optind ], rand() ); o_dname = toname; dorename = TRUE; break; case 2: o_dname = argv[ optind + 1 ]; break; default: usage( argv[ 0 ] ); exit( 1 ); break; } o_sname = argv[ optind ] ; rc = opentapes(); if( rc < 0 ) { printf( "Error opening files - HETLIB rc: %d\n%s\n", rc, het_error( rc ) ); exit( 1 ); } rc = copytape(); if( rc < 0 ) { printf( "Error copying files - HETLIB rc: %d\n%s\n", rc, het_error( rc ) ); exit( 1 ); } closetapes( rc ); return 0; } hercules-3.07/hextapi.h000644 000765 000765 00000002357 11143760543 016571 0ustar00jmaynardjmaynard000000 000000 /********************************************************/ /* HEXTAPI.H : Definition of Hercules External (public) */ /* APIs */ /* (c) Copyright 2005-2009 Roger Bowler & Others */ /* This file originally written by Ivan Warren */ /* THE STATE OF THIS API IS NOT YET FINALIZED */ /* AND THEREFORE, THE INTERFACE MAY CHANGE */ /********************************************************/ // $Id: hextapi.h 5125 2009-01-23 12:01:44Z bernard $ // // $Log$ // Revision 1.5 2007/06/23 00:04:11 ivan // Update copyright notices to include current year (2007) // // Revision 1.4 2006/12/08 09:43:26 jj // Add CVS message log // #ifndef _HEXTAPI_H_ #define _HEXTAPI_H_ #if defined(_MSVC_) && defined(HERC_DLL_BUILD) #define DLL_IMPORT __declspec(dllimport) #else #define DLL_IMPORT extern #endif typedef void (*LOGCALLBACK)(const char *,size_t); typedef void (*COMMANDHANDLER)(void *); #ifdef __cplusplus extern "C" { #endif /* LOG Callback */ DLL_IMPORT void registerLogCallback(LOGCALLBACK); /* Panel Commands */ DLL_IMPORT COMMANDHANDLER getCommandHandler(void); /* IMPL */ DLL_IMPORT int impl(int ac,char **av); #ifdef __cplusplus } #endif #endif hercules-3.07/hexterns.h000644 000765 000765 00000036475 11344707123 016775 0ustar00jmaynardjmaynard000000 000000 /*-------------------------------------------------------------------*/ /* HEXTERNS.H Hercules function prototypes... */ /*-------------------------------------------------------------------*/ // This header auto-#included by 'hercules.h'... // // The header and other required headers are // presumed to have already been #included ahead of it... // $Id: hexterns.h 5654 2010-03-07 03:15:17Z fish $ #ifndef _HEXTERNS_H #define _HEXTERNS_H #include "hercules.h" // Define all DLL Imports depending on current file #ifndef _HSYS_C_ #define HSYS_DLL_IMPORT DLL_IMPORT #else /* _HSYS_C_ */ #define HSYS_DLL_IMPORT DLL_EXPORT #endif /* _HSYS_C_ */ #ifndef _CCKDDASD_C_ #ifndef _HDASD_DLL_ #define CCKD_DLL_IMPORT DLL_IMPORT #else /* _HDASD_DLL_ */ #define CCKD_DLL_IMPORT extern #endif /* _HDASD_DLL_ */ #else #define CCKD_DLL_IMPORT DLL_EXPORT #endif #ifndef _HDL_C_ #ifndef _HUTIL_DLL_ #define HHDL_DLL_IMPORT DLL_IMPORT #else /* _HDASD_DLL_ */ #define HHDL_DLL_IMPORT extern #endif /* _HDASD_DLL_ */ #else #define HHDL_DLL_IMPORT DLL_EXPORT #endif #ifndef _HSCCMD_C_ #ifndef _HENGINE_DLL_ #define HCMD_DLL_IMPORT DLL_IMPORT #else /* _HENGINE_DLL_ */ #define HCMD_DLL_IMPORT extern #endif /* _HENGINE_DLL_ */ #else #define HCMD_DLL_IMPORT DLL_EXPORT #endif #ifndef _CMDTAB_C_ #ifndef _HENGINE_DLL_ #define CMDT_DLL_IMPORT DLL_IMPORT #else /* _HENGINE_DLL_ */ #define CMDT_DLL_IMPORT extern #endif /* _HENGINE_DLL_ */ #else #define CMDT_DLL_IMPORT DLL_EXPORT #endif #ifndef _HAO_C_ #ifndef _HENGINE_DLL_ #define HAO_DLL_IMPORT DLL_IMPORT #else /* _HENGINE_DLL_ */ #define HAO_DLL_IMPORT extern #endif /* _HENGINE_DLL_ */ #else #define HAO_DLL_IMPORT DLL_EXPORT #endif #ifndef _PANEL_C_ #ifndef _HENGINE_DLL_ #define HPAN_DLL_IMPORT DLL_IMPORT #else /* _HENGINE_DLL_ */ #define HPAN_DLL_IMPORT extern #endif /* _HENGINE_DLL_ */ #else #define HPAN_DLL_IMPORT DLL_EXPORT #endif #ifndef _IMPL_C_ #ifndef _HENGINE_DLL_ #define IMPL_DLL_IMPORT DLL_IMPORT #else /* _HENGINE_DLL_ */ #define IMPL_DLL_IMPORT extern #endif /* _HENGINE_DLL_ */ #else #define IMPL_DLL_IMPORT DLL_EXPORT #endif #ifndef _CCKDUTIL_C_ #ifndef _HDASD_DLL_ #define CCDU_DLL_IMPORT DLL_IMPORT #else /* _HDASD_DLL_ */ #define CCDU_DLL_IMPORT extern #endif /* _HDASD_DLL_ */ #else #define CCDU_DLL_IMPORT DLL_EXPORT #endif #ifndef _CONFIG_C_ #ifndef _HENGINE_DLL_ #define CONF_DLL_IMPORT DLL_IMPORT #else /* _HDASD_DLL_ */ #define CONF_DLL_IMPORT extern #endif /* _HDASD_DLL_ */ #else #define CONF_DLL_IMPORT DLL_EXPORT #endif #ifndef _BLDCFG_C_ #ifndef _HENGINE_DLL_ #define BLDC_DLL_IMPORT DLL_IMPORT #else /* _HDASD_DLL_ */ #define BLDC_DLL_IMPORT extern #endif /* _HDASD_DLL_ */ #else #define BLDC_DLL_IMPORT DLL_EXPORT #endif #ifndef _SERVICE_C_ #ifndef _HENGINE_DLL_ #define SERV_DLL_IMPORT DLL_IMPORT #else /* _HENGINE_DLL_ */ #define SERV_DLL_IMPORT extern #endif /* _HENGINE_DLL_ */ #else #define SERV_DLL_IMPORT DLL_EXPORT #endif #ifndef _LOADPARM_C_ #ifndef _HENGINE_DLL_ #define LOADPARM_DLL_IMPORT DLL_IMPORT #else /* _HENGINE_DLL_ */ #define LOADPARM_DLL_IMPORT extern #endif /* _HENGINE_DLL_ */ #else #define LOADPARM_DLL_IMPORT DLL_EXPORT #endif #if defined( _MSC_VER ) && (_MSC_VER >= 1300) && (_MSC_VER < 1400) // '_ftol' is defined in MSVCRT.DLL // '_ftol2' we define ourselves in "w32ftol2.c" extern long _ftol ( double dblSource ); extern long _ftol2( double dblSource ); #endif #if !defined(HAVE_STRSIGNAL) const char* strsignal(int signo); // (ours is in 'strsignal.c') #endif #if defined(HAVE_SETRESUID) /* (the following missing from SUSE 7.1) */ int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid); int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid); int setresuid(uid_t ruid, uid_t euid, uid_t suid); int setresgid(gid_t rgid, gid_t egid, gid_t sgid); #endif /* Function used to compare filenames */ #if defined(MIXEDCASE_FILENAMES_ARE_UNIQUE) #define strfilenamecmp strcmp #define strnfilenamecmp strncmp #else #define strfilenamecmp strcasecmp #define strnfilenamecmp strncasecmp #endif /* Global data areas in module config.c */ HSYS_DLL_IMPORT SYSBLK sysblk; /* System control block */ CCKD_DLL_IMPORT CCKDBLK cckdblk; /* CCKD global block */ #ifdef EXTERNALGUI HSYS_DLL_IMPORT int extgui; // __attribute__ ((deprecated)); /* The external gui interface is now external and now uses the HDC(debug_cpu_state, regs) interface */ #endif /*EXTERNALGUI*/ /* Functions in module config.c or bldcfg.c */ void build_config (char *fname); void release_config (); CONF_DLL_IMPORT DEVBLK *find_device_by_devnum (U16 lcss, U16 devnum); DEVBLK *find_device_by_subchan (U32 ioid); REGS *devregs(DEVBLK *dev); DEVBLK *get_devblk (U16 lcss, U16 devnum); void ret_devblk (DEVBLK *dev); int attach_device (U16 lcss, U16 devnum, const char *devtype, int addargc, char *addargv[]); int detach_subchan (U16 lcss, U16 subchan); int detach_device (U16 lcss, U16 devnum); int define_device (U16 lcss, U16 olddev, U16 newdev); CONF_DLL_IMPORT int group_device(DEVBLK *dev, int members); int configure_cpu (int cpu); int deconfigure_cpu (int cpu); BLDC_DLL_IMPORT int parse_args (char* p, int maxargc, char** pargv, int* pargc); #define MAX_ARGS 12 /* Max argv[] array size */ int parse_and_attach_devices(const char *devnums,const char *devtype,int ac,char **av); CONF_DLL_IMPORT int parse_single_devnum(const char *spec, U16 *lcss, U16 *devnum); int parse_single_devnum_silent(const char *spec, U16 *lcss, U16 *devnum); int readlogo(char *fn); void clearlogo(void); CONF_DLL_IMPORT int parse_conkpalv(char* s, int* idle, int* intv, int* cnt ); #if defined( OPTION_TAPE_AUTOMOUNT ) BLDC_DLL_IMPORT int add_tamdir( char *tamdir, TAMDIR **ppTAMDIR ); #endif /* OPTION_TAPE_AUTOMOUNT */ /* Global data areas and functions in module cpu.c */ extern const char* arch_name[]; extern const char* get_arch_mode_string(REGS* regs); /* Functions in module panel.c */ void expire_kept_msgs(int unconditional); #ifdef OPTION_MIPS_COUNTING HPAN_DLL_IMPORT U32 maxrates_rpt_intvl; // (reporting interval) HPAN_DLL_IMPORT U32 curr_high_mips_rate; // (high water mark for current interval) HPAN_DLL_IMPORT U32 curr_high_sios_rate; // (high water mark for current interval) HPAN_DLL_IMPORT U32 prev_high_mips_rate; // (saved high water mark for previous interval) HPAN_DLL_IMPORT U32 prev_high_sios_rate; // (saved high water mark for previous interval) HPAN_DLL_IMPORT time_t curr_int_start_time; // (start time of current interval) HPAN_DLL_IMPORT time_t prev_int_start_time; // (start time of previous interval) HPAN_DLL_IMPORT void update_maxrates_hwm(); // (update high-water-mark values) #endif // OPTION_MIPS_COUNTING /* Functions in module hao.c (Hercules Automatic Operator) */ #if defined(OPTION_HAO) HAO_DLL_IMPORT void hao_initialize(void); /* initialize hao */ HAO_DLL_IMPORT void hao_command(char *command); /* process hao command */ HAO_DLL_IMPORT void hao_message(char *message); /* process message */ #endif /* defined(OPTION_HAO) */ /* Functions in module hsccmd.c (so PTT debugging patches can access them) */ HCMD_DLL_IMPORT int aia_cmd (int argc, char *argv[], char *cmdline); HCMD_DLL_IMPORT int stopall_cmd (int argc, char *argv[], char *cmdline); /* Functions in module cmdtab.c */ CMDT_DLL_IMPORT int ProcessConfigCommand (int argc, char **argv, char *cmdline); /* Functions in losc.c */ void losc_set (int license_status); void losc_check(char *ostype); #if defined(OPTION_DYNAMIC_LOAD) HHDL_DLL_IMPORT char *(*hdl_device_type_equates) (const char *); CMDT_DLL_IMPORT void *(panel_command_r) (void *cmdline); HPAN_DLL_IMPORT void (panel_display_r) (void); HSYS_DLL_IMPORT int (*config_command) (int argc, char *argv[], char *cmdline); HSYS_DLL_IMPORT int (*system_command) (int argc, char *argv[], char *cmdline); HSYS_DLL_IMPORT void (*daemon_task) (void); HSYS_DLL_IMPORT void (*panel_display) (void); HSYS_DLL_IMPORT void *(*panel_command) (void *); HSYS_DLL_IMPORT void *(*debug_device_state) (DEVBLK *); HSYS_DLL_IMPORT void *(*debug_cpu_state) (REGS *); HSYS_DLL_IMPORT void *(*debug_cd_cmd) (char *); HSYS_DLL_IMPORT void *(*debug_watchdog_signal) (REGS *); HSYS_DLL_IMPORT void *(*debug_program_interrupt) (REGS *, int); HSYS_DLL_IMPORT void *(*debug_diagnose) (U32, int, int, REGS *); HSYS_DLL_IMPORT void *(*debug_iucv) (int, VADR, REGS *); HSYS_DLL_IMPORT void *(*debug_sclp_unknown_command) (U32, void *, REGS *); HSYS_DLL_IMPORT void *(*debug_sclp_unknown_event) (void *, void *, REGS *); HSYS_DLL_IMPORT void *(*debug_sclp_unknown_event_mask) (void *, void *, REGS *); HSYS_DLL_IMPORT void *(*debug_chsc_unknown_request) (void *, void *, REGS *); HSYS_DLL_IMPORT void *(*debug_sclp_event_data) (void *, void *, REGS *); #else void *panel_command (void *cmdline); void panel_display (void); #define debug_cpu_state NULL #define debug_cd_cmd NULL #define debug_device_state NULL #define debug_program_interrupt NULL #define debug_diagnose NULL #define debug_iucv NULL #define debug_sclp_unknown_command NULL #define debug_sclp_unknown_event NULL #define debug_sclp_event_data NULL #define debug_chsc_unknown_request NULL #define debug_watchdog_signal NULL #endif /* Functions in module loadparm.c */ void set_loadparm(char *name); void get_loadparm(BYTE *dest); char *str_loadparm(); void set_lparname(char *name); void get_lparname(BYTE *dest); LOADPARM_DLL_IMPORT char *str_lparname(); void set_manufacturer(char *name); void set_plant(char *name); void set_model(int argc, char *m1, char* m2, char* m3, char* m4); void get_manufacturer(BYTE *name); void get_plant(BYTE *name); void get_model(BYTE *name); void get_modelcapa(BYTE *name); void get_modelperm(BYTE *name); void get_modeltemp(BYTE *name); void get_sysname(BYTE *name); void get_systype(BYTE *name); void get_sysplex(BYTE *name); void set_sysname(BYTE *name); void set_systype(BYTE *name); void set_sysplex(BYTE *name); void get_mpfactors(BYTE *dest); /* Functions in module impl.c */ IMPL_DLL_IMPORT void system_cleanup(void); typedef void (*LOGCALLBACK)(const char *,size_t); typedef void *(*COMMANDHANDLER)(void *); IMPL_DLL_IMPORT int impl(int,char **); IMPL_DLL_IMPORT void regiserLogCallback(LOGCALLBACK); IMPL_DLL_IMPORT COMMANDHANDLER getCommandHandler(void); /* Functions in module timer.c */ void update_TOD_clock (void); void *timer_update_thread (void *argp); /* Functions in module service.c */ void scp_command (char *command, int priomsg); int can_signal_quiesce (); int signal_quiesce (U16 count, BYTE unit); void sclp_attention(U16 type); void sclp_reset(); SERV_DLL_IMPORT void sclp_sysg_attention(); int servc_hsuspend(void *file); int servc_hresume(void *file); /* Functions in module ckddasd.c */ void ckd_build_sense ( DEVBLK *, BYTE, BYTE, BYTE, BYTE, BYTE); int ckddasd_init_handler ( DEVBLK *dev, int argc, char *argv[]); void ckddasd_execute_ccw ( DEVBLK *dev, BYTE code, BYTE flags, BYTE chained, U16 count, BYTE prevcode, int ccwseq, BYTE *iobuf, BYTE *more, BYTE *unitstat, U16 *residual ); int ckddasd_close_device ( DEVBLK *dev ); void ckddasd_query_device (DEVBLK *dev, char **class, int buflen, char *buffer); int ckddasd_hsuspend ( DEVBLK *dev, void *file ); int ckddasd_hresume ( DEVBLK *dev, void *file ); /* Functions in module fbadasd.c */ FBA_DLL_IMPORT void fbadasd_syncblk_io (DEVBLK *dev, BYTE type, int blknum, int blksize, BYTE *iobuf, BYTE *unitstat, U16 *residual); FBA_DLL_IMPORT void fbadasd_read_block ( DEVBLK *dev, int blknum, int blksize, int blkfactor, BYTE *iobuf, BYTE *unitstat, U16 *residual ); FBA_DLL_IMPORT void fbadasd_write_block ( DEVBLK *dev, int blknum, int blksize, int blkfactor, BYTE *iobuf, BYTE *unitstat, U16 *residual ); int fbadasd_init_handler ( DEVBLK *dev, int argc, char *argv[]); void fbadasd_execute_ccw ( DEVBLK *dev, BYTE code, BYTE flags, BYTE chained, U16 count, BYTE prevcode, int ccwseq, BYTE *iobuf, BYTE *more, BYTE *unitstat, U16 *residual ); int fbadasd_close_device ( DEVBLK *dev ); void fbadasd_query_device (DEVBLK *dev, char **class, int buflen, char *buffer); int fbadasd_hsuspend ( DEVBLK *dev, void *file ); int fbadasd_hresume ( DEVBLK *dev, void *file ); /* Functions in module cckddasd.c */ DEVIF cckddasd_init_handler; int cckddasd_close_device (DEVBLK *); int cckd_read_track (DEVBLK *, int, BYTE *); int cckd_update_track (DEVBLK *, int, int, BYTE *, int, BYTE *); int cfba_read_block (DEVBLK *, int, BYTE *); int cfba_write_block (DEVBLK *, int, int, BYTE *, int, BYTE *); CCKD_DLL_IMPORT void *cckd_sf_add (void *); CCKD_DLL_IMPORT void *cckd_sf_remove (void *); CCKD_DLL_IMPORT void *cckd_sf_stats (void *); CCKD_DLL_IMPORT void *cckd_sf_comp (void *); CCKD_DLL_IMPORT void *cckd_sf_chk (void *); CCKD_DLL_IMPORT int cckd_command(char *, int); CCKD_DLL_IMPORT void cckd_print_itrace (); /* Functions in module cckdutil.c */ CCDU_DLL_IMPORT int cckd_swapend (DEVBLK *); CCDU_DLL_IMPORT void cckd_swapend_chdr (CCKD_DEVHDR *); CCDU_DLL_IMPORT void cckd_swapend_l1 (CCKD_L1ENT *, int); CCDU_DLL_IMPORT void cckd_swapend_l2 (CCKD_L2ENT *); CCDU_DLL_IMPORT void cckd_swapend_free (CCKD_FREEBLK *); CCDU_DLL_IMPORT void cckd_swapend4 (char *); CCDU_DLL_IMPORT void cckd_swapend2 (char *); CCDU_DLL_IMPORT int cckd_endian (); CCDU_DLL_IMPORT int cckd_comp (DEVBLK *); CCDU_DLL_IMPORT int cckd_chkdsk (DEVBLK *, int); CCDU_DLL_IMPORT void cckdumsg (DEVBLK *, int, char *, ...); /* Functions in module hscmisc.c */ int herc_system (char* command); void do_shutdown(); void display_regs (REGS *regs); void display_fregs (REGS *regs); void display_cregs (REGS *regs); void display_aregs (REGS *regs); void display_subchannel (DEVBLK *dev); void get_connected_client (DEVBLK* dev, char** pclientip, char** pclientname); void alter_display_real (char *opnd, REGS *regs); void alter_display_virt (char *opnd, REGS *regs); void disasm_stor(REGS *regs, char *opnd); int drop_privileges(int capa); /* Functions in module sr.c */ int suspend_cmd(int argc, char *argv[],char *cmdline); int resume_cmd(int argc, char *argv[],char *cmdline); /* Functions in ecpsvm.c that are not *direct* instructions */ /* but support functions either used by other instruction */ /* functions or from somewhere else */ #ifdef FEATURE_ECPSVM int ecpsvm_dosvc(REGS *regs, int svccode); int ecpsvm_dossm(REGS *regs,int b,VADR ea); int ecpsvm_dolpsw(REGS *regs,int b,VADR ea); int ecpsvm_dostnsm(REGS *regs,int b,VADR ea,int imm); int ecpsvm_dostosm(REGS *regs,int b,VADR ea,int imm); int ecpsvm_dosio(REGS *regs,int b,VADR ea); int ecpsvm_dodiag(REGS *regs,int r1,int r3,int b2,VADR effective_addr2); int ecpsvm_dolctl(REGS *regs,int r1,int r3,int b2,VADR effective_addr2); int ecpsvm_dostctl(REGS *regs,int r1,int r3,int b2,VADR effective_addr2); int ecpsvm_doiucv(REGS *regs,int b2,VADR effective_addr2); int ecpsvm_virttmr_ext(REGS *regs); #endif /* Functions in module w32ctca.c */ #if defined(OPTION_W32_CTCI) HSYS_DLL_IMPORT int (*debug_tt32_stats) (int); HSYS_DLL_IMPORT void (*debug_tt32_tracing) (int); #endif // defined(OPTION_W32_CTCI) #endif // _HEXTERNS_H hercules-3.07/history.c000644 000765 000765 00000011733 11143760543 016621 0ustar00jmaynardjmaynard000000 000000 // $Id: history.c 4102 2006-12-08 09:43:35Z jj $ // // $Log$ #include "hstdinc.h" #include "hercules.h" #include "history.h" #define HISTORY_MAX 10 #define CMD_SIZE 256 /* 32767 is way toooooo much */ typedef struct history { int number; char *cmdline; struct history *prev; struct history *next; } HISTORY; BYTE history_count; /* for line numbering */ HISTORY *history_lines; /* points to the beginning of history list (oldest command) */ HISTORY *history_lines_end; /* points to the end of history list (most recent command) */ HISTORY *history_ptr; /* points to last command retrieved by key press */ HISTORY *backup; /* used for backuping last removed command */ /* these 2 are used in panel.c to see if there was history command requested and returns that command */ char *historyCmdLine; int history_requested = 0; void copy_to_historyCmdLine(char* cmdline) { if (historyCmdLine) free(historyCmdLine); historyCmdLine = malloc(strlen(cmdline)+1); strcpy(historyCmdLine, cmdline); } /* initialize environment */ int history_init() { history_lines = NULL; history_lines_end = NULL; historyCmdLine = (char *) malloc(255); history_requested = 0; backup = NULL; history_count = 0; history_ptr = NULL; return(0); } /* add commandline to history list */ int history_add(char *cmdline) { HISTORY *tmp; /* if there is some backup line remaining, remove it */ if (backup != NULL) { free(backup->cmdline); free(backup); backup = NULL; } /* allocate space and copy string */ tmp = (HISTORY*) malloc(sizeof(HISTORY)); tmp->cmdline = (char*) malloc(strlen(cmdline) + 1); strcpy(tmp->cmdline, cmdline); tmp->next = NULL; tmp->prev = NULL; tmp->number = ++history_count; if (history_lines == NULL) { /* first in list */ history_lines = tmp; history_lines_end = tmp; } else { tmp->prev = history_lines_end; history_lines_end->next = tmp; history_lines_end = tmp; } history_ptr = NULL; if (history_count > HISTORY_MAX) { /* if we are over maximum number of lines in history list, oldest one should be deleted but we don't know whether history_remove will not be called, so oldest line is backuped and not removed */ backup = history_lines; history_lines = history_lines->next; backup->next = NULL; history_lines->prev = NULL; } return(0); } /* show list of lines in history */ int history_show() { HISTORY *tmp; tmp = history_lines; while (tmp != NULL) { logmsg("%4d %s\n", tmp->number, tmp->cmdline); tmp = tmp->next; } return(0); } /* remove last line from history list (called only when history command was invoked) */ int history_remove() { HISTORY *tmp; if (history_lines == NULL) return(0); if (history_lines == history_lines_end) { ASSERT(history_lines->next == NULL); ASSERT(history_count == 1); free(history_lines->cmdline); free(history_lines); history_lines = NULL; history_lines_end = NULL; history_count--; return(0); } tmp = history_lines_end->prev; tmp->next = NULL; free(history_lines_end->cmdline); free(history_lines_end); history_count--; history_lines_end = tmp; if (backup != NULL) { backup->next = history_lines; history_lines->prev = backup; history_lines = backup; backup = NULL; } return(0); } int history_relative_line(int x) { HISTORY *tmp = history_lines_end; if (-x > HISTORY_MAX) { logmsg("History limited to last %d commands\n", HISTORY_MAX); return (-1); } if (-x > history_count) { logmsg("only %d commands in history\n", history_count); return (-1); } while (x<-1) { tmp = tmp->prev; x++; } copy_to_historyCmdLine(tmp->cmdline); history_ptr = NULL; return(0); } int history_absolute_line(int x) { HISTORY *tmp = history_lines_end; int lowlimit; if (history_count == 0) { logmsg("history empty\n"); return -1; } lowlimit = history_count - HISTORY_MAX; if (x > history_count || x <= lowlimit) { logmsg("only commands %d-%d are in history\n", lowlimit<0? 1 : lowlimit + 1, history_count); return (-1); } while (tmp->number != x) tmp = tmp->prev; copy_to_historyCmdLine(tmp->cmdline); history_ptr = NULL; return(0); } int history_next() { if (history_ptr == NULL) { history_ptr = history_lines_end; if (history_ptr == NULL) return(-1); copy_to_historyCmdLine(history_ptr->cmdline); return(0); } if (history_ptr->next == NULL) history_ptr = history_lines; else history_ptr = history_ptr->next; copy_to_historyCmdLine(history_ptr->cmdline); return(0); } int history_prev() { if (history_ptr == NULL) { history_ptr = history_lines_end; if (history_ptr == NULL) return(-1); copy_to_historyCmdLine(history_ptr->cmdline); return(0); } if (history_ptr->prev == NULL) history_ptr = history_lines_end; else history_ptr = history_ptr->prev; copy_to_historyCmdLine(history_ptr->cmdline); return(0); } hercules-3.07/history.h000644 000765 000765 00000000574 11143760543 016627 0ustar00jmaynardjmaynard000000 000000 // $Id: history.h 4102 2006-12-08 09:43:35Z jj $ // // $Log$ #ifndef HISTORY_H #define HISTORY_H extern int history_requested; extern char *historyCmdLine; int history_init(); int history_add(char *cmdline); int history_show(); int history_absolute_line(int x); int history_relative_line(int x); int history_next(void); int history_prev(void); int history_remove(void); #endif hercules-3.07/hmacros.h000644 000765 000765 00000057306 11332367225 016567 0ustar00jmaynardjmaynard000000 000000 /*-------------------------------------------------------------------*/ /* HMACROS.H Hercules macros... */ /*-------------------------------------------------------------------*/ // This header auto-#included by 'hercules.h'... // // The header and other required headers are // presumed to have already been #included ahead of it... // $Id: hmacros.h 5602 2010-01-16 12:15:16Z fish $ #ifndef _HMACROS_H #define _HMACROS_H #include "hercules.h" /*-------------------------------------------------------------------*/ /* "Portability" macros for handling _MSVC_ port... */ /*-------------------------------------------------------------------*/ /* PROGRAMMING NOTE: the following 'tape' portability macros are only for physical (SCSI) tape devices, not emulated aws files */ #ifdef _MSVC_ #define open_tape w32_open_tape #define read_tape w32_read_tape #define write_tape w32_write_tape #define ioctl_tape w32_ioctl_tape #define close_tape w32_close_tape #else #define open_tape open #define read_tape read #define write_tape write #define ioctl_tape ioctl #define close_tape close #endif #ifdef _MSVC_ #define create_pipe(a) socketpair(AF_INET,SOCK_STREAM,IPPROTO_IP,a) #define read_pipe(f,b,n) recv(f,b,n,0) #define write_pipe(f,b,n) send(f,b,(int)n,0) #define close_pipe(f) closesocket(f) #else #define create_pipe(f) pipe(f) #define read_pipe(f,b,n) read(f,b,n) #define write_pipe(f,b,n) write(f,b,n) #define close_pipe(f) close(f) #endif #ifdef _MSVC_ #define socket w32_socket /* Now defined in hsocket.h int read_socket(int fd, char *ptr, int nbytes); int write_socket(int fd, const char *ptr, int nbytes); */ #define close_socket(f) closesocket(f) #else /* Now defined in hsocket.h int read_socket(int fd, char *ptr, int nbytes); int write_socket(int fd, const char *ptr, int nbytes); */ #define close_socket(f) close(f) #endif #ifdef _MSVC_ #undef FD_SET #undef FD_ISSET #define FD_SET w32_FD_SET #define FD_ISSET w32_FD_ISSET #define select(n,r,w,e,t) w32_select((n),(r),(w),(e),(t),__FILE__,__LINE__) #define fdopen w32_fdopen #define fwrite w32_fwrite #define fprintf w32_fprintf #define fclose w32_fclose #endif #ifdef _MSVC_ #define fdatasync _commit #define atoll _atoi64 #else #if !defined(HAVE_FDATASYNC_SUPPORTED) #ifdef HAVE_FSYNC #define fdatasync fsync #else #error Required 'fdatasync' function is missing and alternate 'fsync' function also missing #endif #endif #define atoll(s) strtoll(s,NULL,0) #endif /*-------------------------------------------------------------------*/ /* Portable macro for copying 'va_list' variable arguments variable */ /*-------------------------------------------------------------------*/ // ZZ FIXME: this should probably be handled in configure.ac... #if !defined( va_copy ) #if defined( __va_copy ) #define va_copy __va_copy #elif defined( _MSVC_ ) #define va_copy(to,from) (to) = (from) #else #define va_copy(to,from) memcpy((to),(from),sizeof(va_list)) #endif #endif /*-------------------------------------------------------------------*/ /* some handy array/struct macros... */ /*-------------------------------------------------------------------*/ #ifndef _countof #define _countof(x) ( sizeof(x) / sizeof(x[0]) ) #endif #ifndef arraysize #define arraysize(x) _countof(x) #endif #ifndef sizeof_member #define sizeof_member(_struct,_member) sizeof(((_struct*)0)->_member) #endif #ifndef offsetof #define offsetof(_struct,_member) (size_t)&(((_struct*)0)->_member) #endif /*-------------------------------------------------------------------*/ /* Large File Support portability... */ /*-------------------------------------------------------------------*/ #ifdef _MSVC_ /* "Native" 64-bit Large File Support */ #define off_t __int64 #if (_MSC_VER >= 1400) #define ftruncate _chsize_s #define ftell _ftelli64 #define fseek _fseeki64 #else // (_MSC_VER < 1400) #define ftruncate w32_ftrunc64 #define ftell w32_ftelli64 #define fseek w32_fseeki64 #endif #define lseek _lseeki64 #define fstat _fstati64 #define stat _stati64 #elif defined(_LFS_LARGEFILE) || ( defined(SIZEOF_OFF_T) && SIZEOF_OFF_T > 4 ) /* Native 64-bit Large File Support */ #if defined(HAVE_FSEEKO) #define ftell ftello #define fseek fseeko #else #if defined(SIZEOF_LONG) && SIZEOF_LONG <= 4 #warning fseek/ftell use offset arguments of insufficient size #endif #endif #elif defined(_LFS64_LARGEFILE) /* Transitional 64-bit Large File Support */ #define off_t off64_t #define ftruncate ftruncate64 #define ftell ftello64 #define fseek fseeko64 #define lseek lseek64 #define fstat fstat64 #define stat stat64 #else // !defined(_LFS_LARGEFILE) && !defined(_LFS64_LARGEFILE) && (!defined(SIZEOF_OFF_T) || SIZEOF_OFF_T <= 4) /* No 64-bit Large File Support at all */ #warning Large File Support missing #endif /*-------------------------------------------------------------------*/ /* Macro definitions for version number */ /*-------------------------------------------------------------------*/ #define STRINGMAC(x) #x #define MSTRING(x) STRINGMAC(x) /*-------------------------------------------------------------------*/ /* Use these to suppress unreferenced variable warnings... */ /*-------------------------------------------------------------------*/ #define UNREFERENCED(x) ((x)=(x)) #define UNREFERENCED_370(x) ((x)=(x)) #define UNREFERENCED_390(x) ((x)=(x)) #define UNREFERENCED_900(x) ((x)=(x)) /*-------------------------------------------------------------------*/ /* Macro for Debugging / Tracing... */ /*-------------------------------------------------------------------*/ /* Add message prefix filename:linenumber: to messages when compiled with debug enabled - JJ 30/12/99 */ /* But only if OPTION_DEBUG_MESSAGES defined in featall.h - Fish */ #define DEBUG_MSG_Q( _string ) #_string #define DEBUG_MSG_M( _string ) DEBUG_MSG_Q( _string ) #define DEBUG_MSG( _string ) __FILE__ ":" DEBUG_MSG_M( __LINE__ ) ":" _string #define D_( _string ) DEBUG_MSG( _string ) #if defined(OPTION_DEBUG_MESSAGES) && defined(DEBUG) #define DEBUG_( _string ) D_( _string ) #else #define DEBUG_( _string ) _string #endif #if defined(ENABLE_NLS) #define _(_string) gettext(DEBUG_(_string)) #else #define _(_string) (DEBUG_(_string)) #define N_(_string) (DEBUG_(_string)) #define textdomain(_domain) #define bindtextdomain(_package, _directory) #endif #if defined(DEBUG) || defined(_DEBUG) #ifdef _MSVC_ #define TRACE(...) \ do \ { \ IsDebuggerPresent() ? DebugTrace (__VA_ARGS__): \ logmsg (__VA_ARGS__); \ } \ while (0) #undef ASSERT /* For VS9 2008 */ #define ASSERT(a) \ do \ { \ if (!(a)) \ { \ TRACE("HHCxx999W *** Assertion Failed! *** %s(%d); function: %s\n",__FILE__,__LINE__,__FUNCTION__); \ if (IsDebuggerPresent()) DebugBreak(); /* (break into debugger) */ \ } \ } \ while(0) #else // ! _MSVC_ #define TRACE logmsg #define ASSERT(a) \ do \ { \ if (!(a)) \ { \ TRACE("HHCxx999W *** Assertion Failed! *** %s(%d)\n",__FILE__,__LINE__); \ } \ } \ while(0) #endif // _MSVC_ #define VERIFY ASSERT #else // non-debug build... #ifdef _MSVC_ #define TRACE __noop #undef ASSERT /* For VS9 2008 */ #define ASSERT(a) __noop #define VERIFY(a) ((void)(a)) #else // ! _MSVC_ #define TRACE 1 ? ((void)0) : logmsg #define ASSERT(a) #define VERIFY(a) ((void)(a)) #endif // _MSVC_ #endif /* Opcode routing table function pointer */ typedef void (ATTR_REGPARM(2)*FUNC)(); /* Program Interrupt function pointer */ typedef void (ATTR_REGPARM(2) *pi_func) (REGS *regs, int pcode); /* trace_br function */ typedef U32 (*s390_trace_br_func) (int amode, U32 ia, REGS *regs); typedef U64 (*z900_trace_br_func) (int amode, U64 ia, REGS *regs); /*-------------------------------------------------------------------*/ /* compiler optimization hints (for performance) */ /*-------------------------------------------------------------------*/ #undef likely #undef unlikely #ifdef _MSVC_ #define likely(_c) ( (_c) ? ( __assume((_c)), 1 ) : 0 ) #define unlikely(_c) ( (_c) ? 1 : ( __assume(!(_c)), 0 ) ) #else // !_MSVC_ #if __GNUC__ >= 3 #define likely(_c) __builtin_expect((_c),1) #define unlikely(_c) __builtin_expect((_c),0) #else #define likely(_c) (_c) #define unlikely(_c) (_c) #endif #endif // _MSVC_ /*-------------------------------------------------------------------*/ /* CPU state related macros and constants... */ /*-------------------------------------------------------------------*/ /* Definitions for CPU state */ #define CPUSTATE_STARTED 1 /* CPU is started */ #define CPUSTATE_STOPPING 2 /* CPU is stopping */ #define CPUSTATE_STOPPED 3 /* CPU is stopped */ #define IS_CPU_ONLINE(_cpu) \ (sysblk.regs[(_cpu)] != NULL) #if defined(_FEATURE_CPU_RECONFIG) #define MAX_CPU sysblk.maxcpu #else #define MAX_CPU sysblk.numcpu #endif #define HI_CPU sysblk.hicpu #define MAX_REPORTED_MIPSRATE (250000000) /* instructions / second */ #define MAX_REPORTED_SIOSRATE (10000) /* SIOs per second */ /* Instruction count for a CPU */ #define INSTCOUNT(_regs) \ ((_regs)->hostregs->prevcount + (_regs)->hostregs->instcount) /*-------------------------------------------------------------------*/ /* Obtain/Release mainlock. */ /* mainlock is only obtained by a CPU thread */ /*-------------------------------------------------------------------*/ #define OBTAIN_MAINLOCK(_regs) \ do { \ if ((_regs)->hostregs->cpubit != (_regs)->sysblk->started_mask) { \ obtain_lock(&(_regs)->sysblk->mainlock); \ (_regs)->sysblk->mainowner = regs->hostregs->cpuad; \ } \ } while (0) #define RELEASE_MAINLOCK(_regs) \ do { \ if ((_regs)->sysblk->mainowner == (_regs)->hostregs->cpuad) { \ (_regs)->sysblk->mainowner = LOCK_OWNER_NONE; \ release_lock(&(_regs)->sysblk->mainlock); \ } \ } while (0) /*-------------------------------------------------------------------*/ /* Obtain/Release intlock. */ /* intlock can be obtained by any thread */ /* if obtained by a cpu thread, check to see if synchronize_cpus */ /* is in progress. */ /*-------------------------------------------------------------------*/ #define OBTAIN_INTLOCK(_iregs) \ do { \ REGS *_regs = (_iregs); \ if ((_regs)) \ (_regs)->hostregs->intwait = 1; \ obtain_lock (&sysblk.intlock); \ if ((_regs)) { \ while (sysblk.syncing) { \ sysblk.sync_mask &= ~(_regs)->hostregs->cpubit; \ if (!sysblk.sync_mask) \ signal_condition(&sysblk.sync_cond); \ wait_condition(&sysblk.sync_bc_cond, &sysblk.intlock); \ } \ (_regs)->hostregs->intwait = 0; \ sysblk.intowner = (_regs)->hostregs->cpuad; \ } else \ sysblk.intowner = LOCK_OWNER_OTHER; \ } while (0) #define RELEASE_INTLOCK(_regs) \ do { \ sysblk.intowner = LOCK_OWNER_NONE; \ release_lock(&sysblk.intlock); \ } while (0) /*-------------------------------------------------------------------*/ /* Returns when all other CPU threads are blocked on intlock */ /*-------------------------------------------------------------------*/ #define SYNCHRONIZE_CPUS(_regs) \ do { \ int _i, _n = 0; \ CPU_BITMAP _mask = sysblk.started_mask \ ^ (sysblk.waiting_mask | (_regs)->hostregs->cpubit); \ for (_i = 0; _mask && _i < sysblk.hicpu; _i++) { \ if ((_mask & CPU_BIT(_i))) { \ if (sysblk.regs[_i]->intwait || sysblk.regs[_i]->syncio) \ _mask ^= CPU_BIT(_i); \ else { \ ON_IC_INTERRUPT(sysblk.regs[_i]); \ if (SIE_MODE(sysblk.regs[_i])) \ ON_IC_INTERRUPT(sysblk.regs[_i]->guestregs); \ _n++; \ } \ } \ } \ if (_n) { \ if (_n < hostinfo.num_procs) { \ for (_n = 1; _mask; _n++) { \ if (_n & 0xff) \ sched_yield(); \ else \ usleep(1); \ for (_i = 0; _i < sysblk.hicpu; _i++) \ if ((_mask & CPU_BIT(_i)) && sysblk.regs[_i]->intwait) \ _mask ^= CPU_BIT(_i); \ } \ } else { \ sysblk.sync_mask = sysblk.started_mask \ ^ (sysblk.waiting_mask | (_regs)->hostregs->cpubit); \ sysblk.syncing = 1; \ sysblk.intowner = LOCK_OWNER_NONE; \ wait_condition(&sysblk.sync_cond, &sysblk.intlock); \ sysblk.intowner = (_regs)->hostregs->cpuad; \ sysblk.syncing = 0; \ broadcast_condition(&sysblk.sync_bc_cond); \ } \ } \ } while (0) /*-------------------------------------------------------------------*/ /* Macros to signal interrupt condition to a CPU[s]... */ /*-------------------------------------------------------------------*/ #define WAKEUP_CPU(_regs) \ do { \ signal_condition(&(_regs)->intcond); \ } while (0) #define WAKEUP_CPU_MASK(_mask) \ do { \ int i; \ CPU_BITMAP mask = (_mask); \ for (i = 0; mask; i++) { \ if (mask & 1) \ { \ signal_condition(&sysblk.regs[i]->intcond); \ break; \ } \ mask >>= 1; \ } \ } while (0) #define WAKEUP_CPUS_MASK(_mask) \ do { \ int i; \ CPU_BITMAP mask = (_mask); \ for (i = 0; mask; i++) { \ if (mask & 1) \ signal_condition(&sysblk.regs[i]->intcond); \ mask >>= 1; \ } \ } while (0) /*-------------------------------------------------------------------*/ /* Macros to queue/dequeue a device on the I/O interrupt queue... */ /*-------------------------------------------------------------------*/ /* NOTE: sysblk.iointqlk ALWAYS needed to examine sysblk.iointq */ #define QUEUE_IO_INTERRUPT(_io) \ do { \ obtain_lock(&sysblk.iointqlk); \ QUEUE_IO_INTERRUPT_QLOCKED((_io)); \ release_lock(&sysblk.iointqlk); \ } while (0) #define QUEUE_IO_INTERRUPT_QLOCKED(_io) \ do { \ IOINT *prev; \ for (prev = (IOINT *)&sysblk.iointq; prev->next != NULL; prev = prev->next) \ if (prev->next == (_io) || prev->next->priority > (_io)->dev->priority) \ break; \ if (prev->next != (_io)) { \ (_io)->next = prev->next; \ prev->next = (_io); \ (_io)->priority = (_io)->dev->priority; \ } \ if ((_io)->pending) (_io)->dev->pending = 1; \ else if ((_io)->pcipending) (_io)->dev->pcipending = 1; \ else if ((_io)->attnpending) (_io)->dev->attnpending = 1; \ } while (0) #define DEQUEUE_IO_INTERRUPT(_io) \ do { \ obtain_lock(&sysblk.iointqlk); \ DEQUEUE_IO_INTERRUPT_QLOCKED((_io)); \ release_lock(&sysblk.iointqlk); \ } while (0) #define DEQUEUE_IO_INTERRUPT_QLOCKED(_io) \ do { \ IOINT *prev; \ for (prev = (IOINT *)&sysblk.iointq; prev->next != NULL; prev = prev->next) \ if (prev->next == (_io)) { \ prev->next = (_io)->next; \ if ((_io)->pending) (_io)->dev->pending = 0; \ else if ((_io)->pcipending) (_io)->dev->pcipending = 0; \ else if ((_io)->attnpending) (_io)->dev->attnpending = 0; \ break; \ } \ } while (0) /* NOTE: sysblk.iointqlk needed to examine sysblk.iointq, sysblk.intlock (which MUST be held before calling these macros) needed in order to set/reset IC_IOPENDING flag */ #define UPDATE_IC_IOPENDING() \ do { \ obtain_lock(&sysblk.iointqlk); \ UPDATE_IC_IOPENDING_QLOCKED(); \ release_lock(&sysblk.iointqlk); \ } while (0) #define UPDATE_IC_IOPENDING_QLOCKED() \ do { \ if (sysblk.iointq == NULL) \ OFF_IC_IOPENDING; \ else { \ ON_IC_IOPENDING; \ WAKEUP_CPU_MASK (sysblk.waiting_mask); \ } \ } while (0) /*-------------------------------------------------------------------*/ /* Handy utility macro for channel.c */ /*-------------------------------------------------------------------*/ #define IS_CCW_IMMEDIATE(_dev) \ ( \ ( (_dev)->hnd->immed && (_dev)->hnd->immed[(_dev)->code]) \ || ( (_dev)->immed && (_dev)->immed[(_dev)->code]) \ || IS_CCW_NOP((_dev)->code) \ || IS_CCW_SET_EXTENDED((_dev)->code) \ ) /*-------------------------------------------------------------------*/ /* Hercules Dynamic Loader macro to call optional function override */ /*-------------------------------------------------------------------*/ #if defined(OPTION_DYNAMIC_LOAD) #define HDC1(_func, _arg1) \ ((_func) ? (_func) ((_arg1)) : (NULL)) #define HDC2(_func, _arg1,_arg2) \ ((_func) ? (_func) ((_arg1),(_arg2)) : (NULL)) #define HDC3(_func, _arg1,_arg2,_arg3) \ ((_func) ? (_func) ((_arg1),(_arg2),(_arg3)) : (NULL)) #define HDC4(_func, _arg1,_arg2,_arg3,_arg4) \ ((_func) ? (_func) ((_arg1),(_arg2),(_arg3),(_arg4)) : (NULL)) #define HDC5(_func, _arg1,_arg2,_arg3,_arg4,_arg5) \ ((_func) ? (_func) ((_arg1),(_arg2),(_arg3),(_arg4),(_arg5)) : (NULL)) #define HDC6(_func, _arg1,_arg2,_arg3,_arg4,_arg5,_arg6) \ ((_func) ? (_func) ((_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6)) : (NULL)) #else #define HDC1(_func, _arg1) \ (NULL) #define HDC2(_func, _arg1,_arg2) \ (NULL) #define HDC3(_func, _arg1,_arg2,_arg3) \ (NULL) #define HDC4(_func, _arg1,_arg2,arg3,arg4) \ (NULL) #define HDC5(_func, _arg1,_arg2,_arg3,_arg4,_arg5) \ (NULL) #define HDC6(_func, _arg1,_arg2,_arg3,_arg4,_arg5,_arg6) \ (NULL) #endif /*-------------------------------------------------------------------*/ /* sleep for as long as we like */ /*-------------------------------------------------------------------*/ #define SLEEP(_n) \ do { \ unsigned int rc = (_n); \ while (rc) \ if ((rc = sleep (rc))) \ sched_yield(); \ } while (0) /*-------------------------------------------------------------------*/ /* Perform standard utility initialization */ /*-------------------------------------------------------------------*/ #if !defined(ENABLE_NLS) #define INITIALIZE_NLS() #else #define INITIALIZE_NLS() \ do { \ setlocale(LC_ALL, ""); \ bindtextdomain(PACKAGE, HERC_LOCALEDIR); \ textdomain(PACKAGE); \ } while (0) #endif #if !defined(EXTERNALGUI) #define INITIALIZE_EXTERNAL_GUI() #else #define INITIALIZE_EXTERNAL_GUI() \ do { \ if (argc >= 1 && strncmp(argv[argc-1],"EXTERNALGUI",11) == 0) { \ extgui = 1; \ argv[argc-1] = NULL; \ argc--; \ setvbuf(stderr, NULL, _IONBF, 0); \ setvbuf(stdout, NULL, _IONBF, 0); \ } \ } while (0) #endif #define INITIALIZE_UTILITY(name) \ do { \ SET_THREAD_NAME(name); \ INITIALIZE_NLS(); \ INITIALIZE_EXTERNAL_GUI(); \ memset (&sysblk, 0, sizeof(SYSBLK)); \ initialize_detach_attr (DETACHED); \ initialize_join_attr (JOINABLE); \ set_codepage(NULL); \ init_hostinfo( &hostinfo ); \ } while (0) /*-------------------------------------------------------------------*/ /* Macro for Setting a Thread Name (mostly for debugging purposes) */ /*-------------------------------------------------------------------*/ #ifdef _MSVC_ #define SET_THREAD_NAME_ID(t,n) w32_set_thread_name((t),(n)) #define SET_THREAD_NAME(n) SET_THREAD_NAME_ID(GetCurrentThreadId(),(n)) #else #define SET_THREAD_NAME_ID(t,n) #define SET_THREAD_NAME(n) #endif #if !defined(NO_SETUID) /* SETMODE(INIT) * sets the saved uid to the effective uid, and * sets the effective uid to the real uid, such * that the program is running with normal user * attributes, other then that it may switch to * the saved uid by SETMODE(ROOT). This call is * usually made upon entry to the setuid program. * * SETMODE(ROOT) * sets the saved uid to the real uid, and * sets the real and effective uid to the saved uid. * A setuid root program will enter 'root mode' and * will have all the appropriate access. * * SETMODE(USER) * sets the real and effective uid to the uid of the * caller. The saved uid will be the effective uid * upon entry to the program (as before SETMODE(INIT)) * * SETMODE(TERM) * sets real, effective and saved uid to the real uid * upon entry to the program. This call will revoke * any setuid access that the thread/process has. It * is important to issue this call before an exec to a * shell or other program that could introduce integrity * exposures when running with root access. */ #if defined(HAVE_SYS_CAPABILITY_H) && defined(HAVE_SYS_PRCTL_H) && defined(OPTION_CAPABILITIES) #define SETMODE(_x) #define DROP_PRIVILEGES(_capa) drop_privileges(_capa) #define DROP_ALL_CAPS() drop_all_caps() #else #define DROP_PRIVILEGES(_capa) #define DROP_ALL_CAPS() #if defined(HAVE_SETRESUID) #define _SETMODE_INIT \ do { \ getresuid(&sysblk.ruid,&sysblk.euid,&sysblk.suid); \ getresgid(&sysblk.rgid,&sysblk.egid,&sysblk.sgid); \ setresuid(sysblk.ruid,sysblk.ruid,sysblk.euid); \ setresgid(sysblk.rgid,sysblk.rgid,sysblk.egid); \ } while(0) #define _SETMODE_ROOT \ do { \ setresuid(sysblk.suid,sysblk.suid,sysblk.ruid); \ } while(0) #define _SETMODE_USER \ do { \ setresuid(sysblk.ruid,sysblk.ruid,sysblk.suid); \ } while(0) #define _SETMODE_TERM \ do { \ setresuid(sysblk.ruid,sysblk.ruid,sysblk.ruid); \ setresgid(sysblk.rgid,sysblk.rgid,sysblk.rgid); \ } while(0) #elif defined(HAVE_SETREUID) #define _SETMODE_INIT \ do { \ sysblk.ruid = getuid(); \ sysblk.euid = geteuid(); \ sysblk.rgid = getgid(); \ sysblk.egid = getegid(); \ setreuid(sysblk.euid, sysblk.ruid); \ setregid(sysblk.egid, sysblk.rgid); \ } while (0) #define _SETMODE_ROOT \ do { \ setreuid(sysblk.ruid, sysblk.euid); \ setregid(sysblk.rgid, sysblk.egid); \ } while (0) #define _SETMODE_USER \ do { \ setregid(sysblk.egid, sysblk.rgid); \ setreuid(sysblk.euid, sysblk.ruid); \ } while (0) #define _SETMODE_TERM \ do { \ setuid(sysblk.ruid); \ setgid(sysblk.rgid); \ } while (0) #else /* defined(HAVE_SETRESUID) || defined(HAVE_SETEREUID) */ #error Cannot figure out how to swap effective UID/GID, maybe you should define NO_SETUID? #endif /* defined(HAVE_SETREUID) || defined(HAVE_SETRESUID) */ #define SETMODE(_func) _SETMODE_ ## _func #endif /* !defined(HAVE_SYS_CAPABILITY_H) */ #else /* !defined(NO_SETUID) */ #define SETMODE(_func) #define DROP_PRIVILEGES(_capa) #define DROP_ALL_CAPS() #endif /* !defined(NO_SETUID) */ /* min/max macros */ #if !defined(MIN) #define MIN(_x,_y) ( ( ( _x ) < ( _y ) ) ? ( _x ) : ( _y ) ) #endif /*!defined(MIN)*/ #if !defined(MAX) #define MAX(_x,_y) ( ( ( _x ) > ( _y ) ) ? ( _x ) : ( _y ) ) #endif /*!defined(MAX)*/ #if !defined(MINMAX) #define MINMAX(_x,_y,_z) ((_x) = MIN(MAX((_x),(_y)),(_z))) #endif /*!defined(MINMAX)*/ #endif // _HMACROS_H hercules-3.07/hostinfo.c000644 000765 000765 00000011542 11143760544 016750 0ustar00jmaynardjmaynard000000 000000 /* HOSTINFO.C (c) Copyright "Fish" (David B. Trout), 2002-2009 */ // $Id: hostinfo.c 5125 2009-01-23 12:01:44Z bernard $ /* Released under the Q Public License */ /* (http://www.hercules-390.org/herclic.html) */ /* as modifications to Hercules. */ /*-------------------------------------------------------------------*/ /* functions to set/query host system information */ /*-------------------------------------------------------------------*/ // $Log$ // Revision 1.17 2007/11/30 14:54:32 jmaynard // Changed conmicro.cx to hercules-390.org or conmicro.com, as needed. // // Revision 1.16 2007/06/23 00:04:11 ivan // Update copyright notices to include current year (2007) // // Revision 1.15 2006/12/08 09:43:26 jj // Add CVS message log // #include "hstdinc.h" #define _HOSTINFO_C_ #define _HUTIL_DLL_ #include "hercules.h" DLL_EXPORT HOST_INFO hostinfo; /* Host system information */ /*-------------------------------------------------------------------*/ /* Initialize host system information */ /*-------------------------------------------------------------------*/ DLL_EXPORT void init_hostinfo ( HOST_INFO* pHostInfo ) { #if defined(_MSVC_) if ( !pHostInfo ) pHostInfo = &hostinfo; w32_init_hostinfo( pHostInfo ); #elif defined( HAVE_SYS_UTSNAME_H ) struct utsname uname_info; if ( !pHostInfo ) pHostInfo = &hostinfo; uname( &uname_info ); strlcpy( pHostInfo->sysname, uname_info.sysname, sizeof(pHostInfo->sysname) ); strlcpy( pHostInfo->nodename, uname_info.nodename, sizeof(pHostInfo->nodename) ); strlcpy( pHostInfo->release, uname_info.release, sizeof(pHostInfo->release) ); strlcpy( pHostInfo->version, uname_info.version, sizeof(pHostInfo->version) ); strlcpy( pHostInfo->machine, uname_info.machine, sizeof(pHostInfo->machine) ); pHostInfo->trycritsec_avail = 0; #if defined(HAVE_SYSCONF) && defined(HAVE_DECL__SC_NPROCESSORS_CONF) && HAVE_DECL__SC_NPROCESSORS_CONF pHostInfo->num_procs = sysconf(_SC_NPROCESSORS_CONF); #else pHostInfo->num_procs = 0; // (unknown) #endif #else if ( !pHostInfo ) pHostInfo = &hostinfo; strlcpy( pHostInfo->sysname, "(unknown)", sizeof(pHostInfo->sysname) ); strlcpy( pHostInfo->nodename, "(unknown)", sizeof(pHostInfo->nodename) ); strlcpy( pHostInfo->release, "(unknown)", sizeof(pHostInfo->release) ); strlcpy( pHostInfo->version, "(unknown)", sizeof(pHostInfo->version) ); strlcpy( pHostInfo->machine, "(unknown)", sizeof(pHostInfo->machine) ); pHostInfo->trycritsec_avail = 0; #if defined(HAVE_SYSCONF) && defined(HAVE_DECL__SC_NPROCESSORS_CONF) && HAVE_DECL__SC_NPROCESSORS_CONF pHostInfo->num_procs = sysconf(_SC_NPROCESSORS_CONF); #else pHostInfo->num_procs = 0; // (unknown) #endif #endif } /*-------------------------------------------------------------------*/ /* Build a host system information string for displaying purposes */ /* (the returned string does NOT end with a newline) */ /*-------------------------------------------------------------------*/ DLL_EXPORT char* get_hostinfo_str ( HOST_INFO* pHostInfo, char* pszHostInfoStrBuff, size_t nHostInfoStrBuffSiz ) { if ( pszHostInfoStrBuff && nHostInfoStrBuffSiz ) { char num_procs[16]; if ( !pHostInfo ) pHostInfo = &hostinfo; if ( pHostInfo->num_procs > 1 ) snprintf( num_procs, sizeof(num_procs), " MP=%d", pHostInfo->num_procs ); else if ( pHostInfo->num_procs == 1 ) strlcpy( num_procs, " UP", sizeof(num_procs) ); else strlcpy( num_procs, "", sizeof(num_procs) ); snprintf( pszHostInfoStrBuff, nHostInfoStrBuffSiz, _("Running on %s %s-%s.%s %s%s"), pHostInfo->nodename, pHostInfo->sysname, pHostInfo->release, pHostInfo->version, pHostInfo->machine, num_procs ); *(pszHostInfoStrBuff + nHostInfoStrBuffSiz - 1) = 0; } return pszHostInfoStrBuff; } /*-------------------------------------------------------------------*/ /* Display host system information on the indicated stream */ /*-------------------------------------------------------------------*/ DLL_EXPORT void display_hostinfo ( HOST_INFO* pHostInfo, FILE *f, int httpfd ) { char host_info_str[256]; init_hostinfo( pHostInfo ); get_hostinfo_str(pHostInfo, host_info_str, sizeof(host_info_str)); if(httpfd<0) { if (!f) f = stdout; if (f != stdout) fprintf(f, "%s\n", host_info_str); else logmsg( "%s\n", host_info_str); } else { hprintf(httpfd,"%s\n",host_info_str); } } hercules-3.07/hostinfo.h000644 000765 000765 00000003604 11143760542 016753 0ustar00jmaynardjmaynard000000 000000 /* HOSTINFO.H (c) Copyright "Fish" (David B. Trout), 2002-2009 */ /* Released under the Q Public License */ /* (http://www.hercules-390.org/herclic.html) */ /* as modifications to Hercules. */ // $Id: hostinfo.h 5125 2009-01-23 12:01:44Z bernard $ /*-------------------------------------------------------------------*/ /* Header file contains host system information */ /*-------------------------------------------------------------------*/ // $Log$ // Revision 1.13 2007/11/30 14:54:32 jmaynard // Changed conmicro.cx to hercules-390.org or conmicro.com, as needed. // // Revision 1.12 2007/06/23 00:04:11 ivan // Update copyright notices to include current year (2007) // // Revision 1.11 2006/12/08 09:43:26 jj // Add CVS message log // #ifndef _HOSTINFO_H_ #define _HOSTINFO_H_ #include "hercules.h" #ifndef _HOSTINFO_C_ #ifndef _HUTIL_DLL_ #define HI_DLL_IMPORT DLL_IMPORT #else /* _HUTIL_DLL_ */ #define HI_DLL_IMPORT extern #endif /* _HUTIL_DLL_ */ #else #define HI_DLL_IMPORT DLL_EXPORT #endif typedef struct HOST_INFO { char sysname[20]; char nodename[20]; char release[20]; char version[50]; char machine[20]; int trycritsec_avail; /* 1=TryEnterCriticalSection */ int num_procs; /* #of processors */ } HOST_INFO; HI_DLL_IMPORT HOST_INFO hostinfo; HI_DLL_IMPORT void init_hostinfo ( HOST_INFO* pHostInfo ); HI_DLL_IMPORT void display_hostinfo ( HOST_INFO* pHostInfo, FILE *f,int httpfd ); HI_DLL_IMPORT char* get_hostinfo_str ( HOST_INFO* pHostInfo, char* pszHostInfoStrBuff, size_t nHostInfoStrBuffSiz ); /* Hercules Host Information structure (similar to utsname struct) */ #endif // _HOSTINFO_H_ hercules-3.07/hostopts.h000644 000765 000765 00000034411 11321734033 016777 0ustar00jmaynardjmaynard000000 000000 /* HOSTOPTS.H (c) Copyright "Fish" (David B. Trout), 2005-2009 */ /* Host-specific features and options for Hercules */ // $Id: hostopts.h 5586 2009-12-31 10:29:11Z rbowler $ // This header file #included by 'featall.h' and 'hercules.h' /* All HOST-operating-specific (Win32, Apple. Linux, etc) FEATures and OPTIONs that cannot be otherwise determined via configure.ac tests should be #defined here, and ONLY here! ----------------------------------------------------------------- REMINDER: please do NOT use host-specific tests anywhere else in Hercules source code if you can help it! (e.g. #ifdef WIN32, etc) Instead, add a test to configure.ac which tests for the availability of the specific feature in question and then #defines a OPTION_XXX which can then be used in Hercules source code. ----------------------------------------------------------------- The ONLY allowed exception is in the Hercules.h and htypes.h header files where different header files need to be #included (e.g. sockets) and/or typedef/#defines need to be made depending on the host build system type. ONLY IF such a configure.ac test is impractical or otherwise not possible should you then hard-code the OPTION_XXX setting here in this member (and ONLY in this member!) depending on the host o/s. Thus, all of the below hard-coded options are candidates for some future configure.ac test. Feel free to design one. Please. :) */ #ifndef _HOSTOPTS_H #define _HOSTOPTS_H #if defined(_MSVC_) #include "hercwind.h" // (need HAVE_DECL_SIOCSIFHWADDR, etc) #endif /*-------------------------------------------------------------------*/ /* ZZ FIXME 'OPTION_SCSI_ERASE_TAPE' 'OPTION_SCSI_ERASE_GAP' NOTE: The following SHOULD in reality be some sort of test within configure.ac, but until we can devise some sort of simple configure test, we must hard-code them for now. According to the only docs I could find: MTERASE Erase the media from current position. If the field mt_count is nonzero, a full erase is done (from current position to end of media). If mt_count is zero, only an erase gap is written. It is hard to say which drives support only one but not the other option HOWEVER, since it's hard to say which drivers support short erase-gaps and which support erase-tape (and HOW they support them if they do! For example, Cygwin is currently coded to perform whichever type of erase the drive happens to support; e.g. if you try to do an erase-gap but the drive doesn't support short erases, it will end up doing a LONG erase [of the entire tape]!! (and vice-versa: doing a long erase-tape on a drive that doesn't support it will cause [Cygwin] to do an erase- gap instead)). THUS, the SAFEST thing to do is to simply treat all "erases", whether short or long, as 'nop's for now (in order to prevent the accidental erasure of an entire tape!) Once we happen to know for DAMN SURE that a particular host o/s ALWAYS does what we want it to should we then change the below #defines. (and like I said, they really SHOULD be in some type of configure test/setting and not here). */ /*-------------------------------------------------------------------*\ File name comparisons ('strcmp' vs. 'strcasecmp') On Windows, file names are not case sensitive. While the case of the file name may be preserved by the file system (and thus show file names in both upper/lower case in directory listings for example), the file system itself is NOT case-sensitive. File names "Foo", "foo", "fOo", "FoO", etc, all refer to the same file. On other platforms however (e.g. *nix), the file system IS case sensitive. File names "Foo", "foo", "fOo", "FoO", etc, all refer to different files on such systems. Thus we define a 'strfilecmp' macro to be used for filename comparisons and define it to be strcasecmp on Win32 platforms and strcmp for other platforms. \*-------------------------------------------------------------------*/ /*-------------------------------------------------------------------*/ /* Constants used in "#if OPTION_NAME == OPTION_VALUE" statements */ /*-------------------------------------------------------------------*/ // HOW_TO_IMPLEMENT_SH_COMMAND #define USE_FORK_API_FOR_SH_COMMAND 4 #define USE_W32_POOR_MANS_FORK 5 #define USE_ANSI_SYSTEM_API_FOR_SH_COMMAND 9 // SET_CONSOLE_CURSOR_SHAPE_METHOD #define CURSOR_SHAPE_NOT_SUPPORTED 0 #define CURSOR_SHAPE_VIA_SPECIAL_LINUX_ESCAPE 1 #define CURSOR_SHAPE_WINDOWS_NATIVE 2 /*-------------------------------------------------------------------*/ /* The following is now handled automatically for ALL host platforms */ /*-------------------------------------------------------------------*/ #undef OPTION_TUNTAP_SETNETMASK /* (default initial setting) */ #undef OPTION_TUNTAP_SETMACADDR /* (default initial setting) */ #undef OPTION_TUNTAP_DELADD_ROUTES /* (default initial setting) */ #undef OPTION_TUNTAP_CLRIPADDR /* (default initial setting) */ #if defined(HAVE_DECL_SIOCSIFNETMASK) && \ HAVE_DECL_SIOCSIFNETMASK #define OPTION_TUNTAP_SETNETMASK /* TUNTAP_SetNetMask works */ #endif #if defined(HAVE_DECL_SIOCSIFHWADDR) && \ HAVE_DECL_SIOCSIFHWADDR #define OPTION_TUNTAP_SETMACADDR /* TUNTAP_SetMACAddr works */ #endif #if defined(HAVE_DECL_SIOCADDRT) && defined(HAVE_DECL_SIOCDELRT) && \ HAVE_DECL_SIOCADDRT && HAVE_DECL_SIOCDELRT #define OPTION_TUNTAP_DELADD_ROUTES /* Del/Add Routes works */ #endif #if defined(HAVE_DECL_SIOCDIFADDR) && \ HAVE_DECL_SIOCDIFADDR #define OPTION_TUNTAP_CLRIPADDR /* TUNTAP_ClrIPAddr works */ #endif /*-------------------------------------------------------------------*/ /* Hard-coded Win32-specific features and options... */ /*-------------------------------------------------------------------*/ #if defined(WIN32) /* "Windows" options */ #if defined(HDL_BUILD_SHARED) && defined(_MSVC_) #define DLL_IMPORT __declspec ( dllimport ) #define DLL_EXPORT __declspec ( dllexport ) #else #define DLL_IMPORT extern #define DLL_EXPORT #endif #define HTTP_SERVER_CONNECT_KLUDGE /* Note: OPTION_FISHIO only possible with OPTION_FTHREADS */ #if defined(OPTION_FTHREADS) #define OPTION_FISHIO /* Use Fish's I/O scheduler */ #else #undef OPTION_FISHIO /* Use Herc's I/O scheduler */ #endif #define OPTION_W32_CTCI /* Fish's TunTap for CTCA's */ #undef TUNTAP_IFF_RUNNING_NEEDED /* TunTap32 doesn't allow it */ #define OPTION_SCSI_TAPE /* SCSI tape support */ #ifdef _MSVC_ #define OPTION_SCSI_ERASE_TAPE /* SUPPORTED! */ #define OPTION_SCSI_ERASE_GAP /* SUPPORTED! */ #else // (mingw or cygwin?) #undef OPTION_SCSI_ERASE_TAPE /* (NOT supported!) */ #undef OPTION_SCSI_ERASE_GAP /* (NOT supported!) */ #endif #undef OPTION_FBA_BLKDEVICE /* (no FBA BLKDEVICE support)*/ #define MAX_DEVICE_THREADS 0 /* (0 == unlimited) */ #undef MIXEDCASE_FILENAMES_ARE_UNIQUE /* ("Foo" same as "fOo"!!) */ #define DEFAULT_HERCPRIO 0 #define DEFAULT_TOD_PRIO -20 #define DEFAULT_CPU_PRIO 15 #define DEFAULT_DEV_PRIO 8 #ifdef _MSVC_ #define HOW_TO_IMPLEMENT_SH_COMMAND USE_W32_POOR_MANS_FORK #define SET_CONSOLE_CURSOR_SHAPE_METHOD CURSOR_SHAPE_WINDOWS_NATIVE #define OPTION_EXTCURS /* Extended cursor handling */ #else #define HOW_TO_IMPLEMENT_SH_COMMAND USE_FORK_API_FOR_SH_COMMAND #define SET_CONSOLE_CURSOR_SHAPE_METHOD CURSOR_SHAPE_VIA_SPECIAL_LINUX_ESCAPE #undef OPTION_EXTCURS /* Normal cursor handling */ #endif #define IsEventSet(h) (WaitForSingleObject(h,0) == WAIT_OBJECT_0) /*-------------------------------------------------------------------*/ /* Hard-coded Solaris-specific features and options... */ /*-------------------------------------------------------------------*/ #elif defined(__sun__) && defined(__svr4__) #define __SOLARIS__ 1 /* jbs 10/15/2003 need to define INADDR_NONE if using Solaris 10 and not Solaris Nevada aka OpenSolaris */ #if !defined(INADDR_NONE) #define INADDR_NONE 0xffffffffU #endif #undef OPTION_SCSI_TAPE /* No SCSI tape support */ #undef OPTION_SCSI_ERASE_TAPE /* (NOT supported) */ #undef OPTION_SCSI_ERASE_GAP /* (NOT supported) */ #define DLL_IMPORT extern #define DLL_EXPORT /* #undef OPTION_PTTRACE maybe not, after all */ #define MAX_DEVICE_THREADS 0 /* (0 == unlimited) */ #define MIXEDCASE_FILENAMES_ARE_UNIQUE /* ("Foo" and "fOo" unique) */ #define DEFAULT_HERCPRIO 0 #define DEFAULT_TOD_PRIO -20 #define DEFAULT_CPU_PRIO 15 #define DEFAULT_DEV_PRIO 8 #define HOW_TO_IMPLEMENT_SH_COMMAND USE_ANSI_SYSTEM_API_FOR_SH_COMMAND #define SET_CONSOLE_CURSOR_SHAPE_METHOD CURSOR_SHAPE_NOT_SUPPORTED #undef OPTION_EXTCURS /* Normal cursor handling */ /*-------------------------------------------------------------------*/ /* Hard-coded Apple-specific features and options... */ /*-------------------------------------------------------------------*/ #elif defined(__APPLE__) /* "Apple" options */ #define DLL_IMPORT extern #define DLL_EXPORT #define TUNTAP_IFF_RUNNING_NEEDED /* Needed by tuntap driver?? */ #undef OPTION_SCSI_TAPE /* No SCSI tape support */ #undef OPTION_SCSI_ERASE_TAPE /* (NOT supported) */ #undef OPTION_SCSI_ERASE_GAP /* (NOT supported) */ #undef OPTION_FBA_BLKDEVICE /* (no FBA BLKDEVICE support)*/ #define MAX_DEVICE_THREADS 0 /* (0 == unlimited) */ #define MIXEDCASE_FILENAMES_ARE_UNIQUE /* ("Foo" and "fOo" unique) */ #define DEFAULT_HERCPRIO 0 #define DEFAULT_TOD_PRIO -20 #define DEFAULT_CPU_PRIO 15 #define DEFAULT_DEV_PRIO 8 #define HOW_TO_IMPLEMENT_SH_COMMAND USE_ANSI_SYSTEM_API_FOR_SH_COMMAND #define SET_CONSOLE_CURSOR_SHAPE_METHOD CURSOR_SHAPE_NOT_SUPPORTED #undef OPTION_EXTCURS /* Normal cursor handling */ /*-------------------------------------------------------------------*/ /* Hard-coded FreeBSD-specific features and options... */ /*-------------------------------------------------------------------*/ #elif defined(__FreeBSD__) /* "FreeBSD" options */ #define DLL_IMPORT extern #define DLL_EXPORT #define TUNTAP_IFF_RUNNING_NEEDED /* Needed by tuntap driver?? */ #undef OPTION_SCSI_ERASE_TAPE /* (NOT supported) */ #undef OPTION_SCSI_ERASE_GAP /* (NOT supported) */ #define MAX_DEVICE_THREADS 0 /* (0 == unlimited) */ #define MIXEDCASE_FILENAMES_ARE_UNIQUE /* ("Foo" and "fOo" unique) */ #define DEFAULT_HERCPRIO 0 #define DEFAULT_TOD_PRIO -20 #define DEFAULT_CPU_PRIO 15 #define DEFAULT_DEV_PRIO 8 #define HOW_TO_IMPLEMENT_SH_COMMAND USE_ANSI_SYSTEM_API_FOR_SH_COMMAND #define SET_CONSOLE_CURSOR_SHAPE_METHOD CURSOR_SHAPE_NOT_SUPPORTED #undef OPTION_EXTCURS /* Normal cursor handling */ /*-------------------------------------------------------------------*/ /* GNU Linux options... */ /*-------------------------------------------------------------------*/ #elif defined(__gnu_linux__) /* GNU Linux options */ #define DLL_IMPORT extern #define DLL_EXPORT #define TUNTAP_IFF_RUNNING_NEEDED /* Needed by tuntap driver?? */ #define OPTION_SCSI_TAPE /* SCSI tape support */ #undef OPTION_SCSI_ERASE_TAPE /* (NOT supported) */ #undef OPTION_SCSI_ERASE_GAP /* (NOT supported) */ #define OPTION_FBA_BLKDEVICE /* FBA block device support */ #define MAX_DEVICE_THREADS 0 /* (0 == unlimited) */ #define MIXEDCASE_FILENAMES_ARE_UNIQUE /* ("Foo" and "fOo" unique) */ #define DEFAULT_HERCPRIO 0 #define DEFAULT_TOD_PRIO -20 #define DEFAULT_CPU_PRIO 15 #define DEFAULT_DEV_PRIO 8 #if defined( HAVE_FORK ) #define HOW_TO_IMPLEMENT_SH_COMMAND USE_FORK_API_FOR_SH_COMMAND #else #define HOW_TO_IMPLEMENT_SH_COMMAND USE_ANSI_SYSTEM_API_FOR_SH_COMMAND #endif #define SET_CONSOLE_CURSOR_SHAPE_METHOD CURSOR_SHAPE_VIA_SPECIAL_LINUX_ESCAPE #undef OPTION_EXTCURS /* Normal cursor handling */ /*-------------------------------------------------------------------*/ /* Hard-coded OTHER (DEFAULT) host-specific features and options... */ /*-------------------------------------------------------------------*/ #else /* "Other platform" options */ #warning hostopts.h: unknown target platform: defaulting to generic platform settings. #define DLL_IMPORT extern /* (a safe default) */ #define DLL_EXPORT #undef TUNTAP_IFF_RUNNING_NEEDED /* (tuntap support unknown) */ #undef OPTION_SCSI_TAPE /* (NO SCSI tape support) */ #undef OPTION_SCSI_ERASE_TAPE /* (NOT supported) */ #undef OPTION_SCSI_ERASE_GAP /* (NOT supported) */ #undef OPTION_FBA_BLKDEVICE /* (no FBA BLKDEVICE support)*/ #define MAX_DEVICE_THREADS 0 /* (0 == unlimited) */ #define MIXEDCASE_FILENAMES_ARE_UNIQUE /* ("Foo" and "fOo" unique) */ #define DEFAULT_HERCPRIO 0 #define DEFAULT_TOD_PRIO -20 #define DEFAULT_CPU_PRIO 15 #define DEFAULT_DEV_PRIO 8 #if defined( HAVE_FORK ) #define HOW_TO_IMPLEMENT_SH_COMMAND USE_FORK_API_FOR_SH_COMMAND #else #define HOW_TO_IMPLEMENT_SH_COMMAND USE_ANSI_SYSTEM_API_FOR_SH_COMMAND #endif #define SET_CONSOLE_CURSOR_SHAPE_METHOD CURSOR_SHAPE_NOT_SUPPORTED #undef OPTION_EXTCURS /* Normal cursor handling */ #endif // (host-specific tests) #endif // _HOSTOPTS_H hercules-3.07/hsccmd.c000644 000765 000765 00000653456 11335530473 016377 0ustar00jmaynardjmaynard000000 000000 /* HSCCMD.C (c) Copyright Roger Bowler, 1999-2009 */ /* (c) Copyright "Fish" (David B. Trout), 2002-2009 */ /* Execute Hercules System Commands */ /* */ /* Released under the Q Public License */ /* (http://www.hercules-390.org/herclic.html) as modifications to */ /* Hercules. */ // $Id: hsccmd.c 5628 2010-02-13 14:03:36Z jmaynard $ /*-------------------------------------------------------------------*/ /* This module implements the various Hercules System Console */ /* (i.e. hardware console) commands that the emulator supports. */ /* To define a new commmand, add an entry to the "Commands" CMDTAB */ /* table pointing to the command processing function, and optionally */ /* add additional help text to the HelpTab HELPTAB. Both tables are */ /* near the end of this module. */ /*-------------------------------------------------------------------*/ #include "hstdinc.h" #define _HSCCMD_C_ #define _HENGINE_DLL_ #include "hercules.h" #include "devtype.h" #include "opcode.h" #include "history.h" #include "httpmisc.h" #if defined(OPTION_FISHIO) #include "w32chan.h" #endif /* defined(OPTION_FISHIO) */ #include "tapedev.h" #include "dasdtab.h" #include "ctcadpt.h" // (forward references, etc) #define MAX_DEVLIST_DEVICES 1024 #if defined(FEATURE_ECPSVM) extern void ecpsvm_command(int argc,char **argv); #endif int ProcessPanelCommand (char*); int process_script_file(char *,int); /* $test_cmd - do something or other */ #ifdef _MSVC_ #pragma optimize( "", off ) #endif int test_p = 0; int test_n = 0; int test_t = 0; TID test_tid = 0; int test_msg_num = 0; char* test_p_msg = "Test protected message %d...\n"; char* test_n_msg = "Test normal message %d...\n"; void do_test_msgs() { int i; for (i=0; i < test_n; i++) logmsg( test_n_msg, test_msg_num++ ); if ( !test_p) return; for (i=0; i < test_p; i++) logmsg( test_p_msg, test_msg_num++ ); if ( !test_n) return; for (i=0; i < test_n; i++) logmsg( test_n_msg, test_msg_num++ ); } void* test_thread(void* parg) { UNREFERENCED(parg); logmsg("test thread: STARTING\n"); SLEEP( 5 ); do_test_msgs(); logmsg("test thread: EXITING\n"); test_tid = 0; return NULL; } /*-------------------------------------------------------------------*/ /* test command */ /*-------------------------------------------------------------------*/ int test_cmd(int argc, char *argv[],char *cmdline) { // UNREFERENCED(argc); // UNREFERENCED(argv); UNREFERENCED(cmdline); // cause_crash(); if (test_tid) { logmsg("ERROR: test thread still running!\n"); return 0; } if (argc < 2 || argc > 4) { logmsg("Format: \"$test p=#msgs n=#msgs &\" (args can be in any order)\n"); return 0; } test_p = 0; test_n = 0; test_t = 0; if (argc > 1) { if (strncasecmp(argv[1], "p=",2) == 0) test_p = atoi( &argv[1][2] ); if (strncasecmp(argv[1], "n=",2) == 0) test_n = atoi( &argv[1][2] ); if (argv[1][0] == '&') test_t = 1; } if (argc > 2) { if (strncasecmp(argv[2], "p=",2) == 0) test_p = atoi( &argv[2][2] ); if (strncasecmp(argv[2], "n=",2) == 0) test_n = atoi( &argv[2][2] ); if (argv[2][0] == '&') test_t = 1; } if (argc > 3) { if (strncasecmp(argv[3], "p=",2) == 0) test_p = atoi( &argv[3][2] ); if (strncasecmp(argv[3], "n=",2) == 0) test_n = atoi( &argv[3][2] ); if (argv[3][0] == '&') test_t = 1; } if (test_t) create_thread( &test_tid, DETACHED, test_thread, NULL, "test thread" ); else do_test_msgs(); return 0; } #ifdef _MSVC_ #pragma optimize( "", on ) #endif /* Issue generic Device not found error message */ static inline int devnotfound_msg(U16 lcss,U16 devnum) { logmsg(_("HHCPN181E Device number %d:%4.4X not found\n"),lcss,devnum); return -1; } /* Issue generic Missing device number message */ static inline void missing_devnum() { logmsg( _("HHCPN031E Missing device number\n") ); } /* maxrates command - report maximum seen mips/sios rates */ #ifdef OPTION_MIPS_COUNTING /*-------------------------------------------------------------------*/ /* maxrates command */ /*-------------------------------------------------------------------*/ int maxrates_cmd(int argc, char *argv[],char *cmdline) { UNREFERENCED(cmdline); if (argc > 1) { int bError = FALSE; if (argc > 2) { logmsg( _("Improper command format") ); bError = TRUE; } else { int interval = 0; BYTE c; if ( sscanf( argv[1], "%d%c", &interval, &c ) != 1 || interval < 1 ) { logmsg( _("\"%s\": invalid maxrates interval"), argv[1] ); bError = TRUE; } else { maxrates_rpt_intvl = interval; logmsg( _("Maxrates interval set to %d minutes.\n"), maxrates_rpt_intvl ); } } if (bError) logmsg( _("; enter \"help maxrates\" for help.\n") ); } else { char* pszPrevIntervalStartDateTime; char* pszCurrIntervalStartDateTime; char* pszCurrentDateTime; time_t current_time; current_time = time( NULL ); pszPrevIntervalStartDateTime = strdup( ctime( &prev_int_start_time ) ); pszCurrIntervalStartDateTime = strdup( ctime( &curr_int_start_time ) ); pszCurrentDateTime = strdup( ctime( ¤t_time ) ); logmsg ( "Highest observed MIPS/SIOS rates:\n\n" " From: %s" " To: %s\n" ,pszPrevIntervalStartDateTime ,pszCurrIntervalStartDateTime ); logmsg ( " MIPS: %2.1d.%2.2d\n" " SIOS: %d\n\n" ,prev_high_mips_rate / 1000000 ,prev_high_mips_rate % 1000000 ,prev_high_sios_rate ); logmsg ( " From: %s" " To: %s\n" ,pszCurrIntervalStartDateTime ,pszCurrentDateTime ); logmsg ( " MIPS: %2.1d.%2.2d\n" " SIOS: %d\n\n" ,curr_high_mips_rate / 1000000 ,curr_high_mips_rate % 1000000 ,curr_high_sios_rate ); logmsg ( "Current interval = %d minutes.\n" ,maxrates_rpt_intvl ); free( pszPrevIntervalStartDateTime ); free( pszCurrIntervalStartDateTime ); free( pszCurrentDateTime ); } return 0; // (make compiler happy) } #endif // OPTION_MIPS_COUNTING /*-------------------------------------------------------------------*/ /* message command - Display a line of text at the console */ /*-------------------------------------------------------------------*/ int message_cmd(int argc,char *argv[], char *cmdline,int withhdr) { char *msgtxt; time_t mytime; struct tm *mytm; int toskip,state,i; msgtxt=NULL; toskip=3; if(argc>2) { if(strcasecmp(argv[2],"AT")==0) { toskip=5; } } for(state=0,i=0;cmdline[i];i++) { if(!state) { if(cmdline[i]!=' ') { state=1; toskip--; if(!toskip) break; } } else { if(cmdline[i]==' ') { state=0; if(toskip==1) { i++; toskip=0; break; } } } } if(!toskip) { msgtxt=&cmdline[i]; } if(msgtxt && strlen(msgtxt)>0) { if(withhdr) { time(&mytime); mytm=localtime(&mytime); logmsg( #if defined(OPTION_MSGCLR) "" #endif " %2.2u:%2.2u:%2.2u * MSG FROM HERCULES: %s\n", mytm->tm_hour, mytm->tm_min, mytm->tm_sec, msgtxt); } else { logmsg( #if defined(OPTION_MSGCLR) "" #endif "%s\n",msgtxt); } } return 0; } /*-------------------------------------------------------------------*/ /* msg command - Display a line of text at the console */ /*-------------------------------------------------------------------*/ int msg_cmd(int argc,char *argv[], char *cmdline) { return(message_cmd(argc,argv,cmdline,1)); } /*-------------------------------------------------------------------*/ /* msgnoh command - Display a line of text at the console */ /*-------------------------------------------------------------------*/ int msgnoh_cmd(int argc,char *argv[], char *cmdline) { return(message_cmd(argc,argv,cmdline,0)); } /*-------------------------------------------------------------------*/ /* comment command - do absolutely nothing */ /*-------------------------------------------------------------------*/ int comment_cmd(int argc, char *argv[],char *cmdline) { UNREFERENCED(argc); UNREFERENCED(argv); UNREFERENCED(cmdline); // Do nothing; command has already been echo'ed to console... return 0; // (make compiler happy) } /*-------------------------------------------------------------------*/ /* quit or exit command - terminate the emulator */ /*-------------------------------------------------------------------*/ int quit_cmd(int argc, char *argv[],char *cmdline) { UNREFERENCED(argc); UNREFERENCED(argv); UNREFERENCED(cmdline); do_shutdown(); return 0; /* (make compiler happy) */ } /*-------------------------------------------------------------------*/ /* history command */ /*-------------------------------------------------------------------*/ int History(int argc, char *argv[], char *cmdline) { UNREFERENCED(cmdline); /* last stored command is for sure command 'hst' so remove it this is the only place where history_remove is called */ history_remove(); history_requested = 1; /* only 'hst' called */ if (argc == 1) { if (history_relative_line(-1) == -1) history_requested = 0; return 0; } /* hst with argument called */ if (argc == 2) { int x; switch (argv[1][0]) { case 'l': history_show(); history_requested = 0; break; default: x = atoi(argv[1]); if (x>0) { if (history_absolute_line(x) == -1) history_requested = 0; } else { if (x<0) { if (history_relative_line(x) == -1) history_requested = 0; } else { /* x == 0 */ history_show(); history_requested = 0; } } } } return 0; } /*-------------------------------------------------------------------*/ /* log command - direct log output */ /*-------------------------------------------------------------------*/ int log_cmd(int argc, char *argv[],char *cmdline) { UNREFERENCED(cmdline); if(argc > 1) { if(strcasecmp("off",argv[1])) log_sethrdcpy(argv[1]); else log_sethrdcpy(NULL); } else logmsg(_("HHCPN160E no argument\n")); return 0; } /*-------------------------------------------------------------------*/ /* logopt command - change log options */ /*-------------------------------------------------------------------*/ int logopt_cmd(int argc, char *argv[],char *cmdline) { UNREFERENCED(cmdline); if(argc < 2) { logmsg(_("HHCPN195I Log options:%s\n"), sysblk.logoptnotime ? " NOTIMESTAMP" : " TIMESTAMP" ); } else { while (argc > 1) { argv++; argc--; if (strcasecmp(argv[0],"timestamp") == 0 || strcasecmp(argv[0],"time" ) == 0) { sysblk.logoptnotime = 0; logmsg(_("HHCPN197I Log option set: TIMESTAMP\n")); continue; } if (strcasecmp(argv[0],"notimestamp") == 0 || strcasecmp(argv[0],"notime" ) == 0) { sysblk.logoptnotime = 1; logmsg(_("HHCPN197I Log option set: NOTIMESTAMP\n")); continue; } logmsg(_("HHCPN196E Invalid logopt value %s\n"), argv[0]); } /* while (argc > 1) */ } return 0; } /*-------------------------------------------------------------------*/ /* uptime command - display how long Hercules has been running */ /*-------------------------------------------------------------------*/ int uptime_cmd(int argc, char *argv[],char *cmdline) { time_t now; unsigned uptime, weeks, days, hours, mins, secs; UNREFERENCED( cmdline ); UNREFERENCED( argc ); UNREFERENCED( argv ); time( &now ); uptime = (unsigned) difftime( now, sysblk.impltime ); #define SECS_PER_MIN ( 60 ) #define SECS_PER_HOUR ( 60 * SECS_PER_MIN ) #define SECS_PER_DAY ( 24 * SECS_PER_HOUR ) #define SECS_PER_WEEK ( 7 * SECS_PER_DAY ) weeks = uptime / SECS_PER_WEEK; uptime %= SECS_PER_WEEK; days = uptime / SECS_PER_DAY; uptime %= SECS_PER_DAY; hours = uptime / SECS_PER_HOUR; uptime %= SECS_PER_HOUR; mins = uptime / SECS_PER_MIN; uptime %= SECS_PER_MIN; secs = uptime; if (weeks) { logmsg(_("Hercules has been up for %u week%s, %u day%s, %02u:%02u:%02u.\n"), weeks, weeks > 1 ? "s" : "", days, days != 1 ? "s" : "", hours, mins, secs); } else if (days) { logmsg(_("Hercules has been up for %u day%s, %02u:%02u:%02u.\n"), days, days != 1 ? "s" : "", hours, mins, secs); } else { logmsg(_("Hercules has been up for %02u:%02u:%02u.\n"), hours, mins, secs); } return 0; } /*-------------------------------------------------------------------*/ /* version command - display version information */ /*-------------------------------------------------------------------*/ int version_cmd(int argc, char *argv[],char *cmdline) { UNREFERENCED(cmdline); UNREFERENCED(argc); UNREFERENCED(argv); display_version (stdout, "Hercules ", TRUE); return 0; } /*-------------------------------------------------------------------*/ /* start command - start CPU (or printer device if argument given) */ /*-------------------------------------------------------------------*/ int start_cmd(int argc, char *argv[], char *cmdline) { UNREFERENCED(cmdline); if (argc < 2) { OBTAIN_INTLOCK(NULL); if (IS_CPU_ONLINE(sysblk.pcpu)) { REGS *regs = sysblk.regs[sysblk.pcpu]; regs->opinterv = 0; regs->cpustate = CPUSTATE_STARTED; regs->checkstop = 0; WAKEUP_CPU(regs); } RELEASE_INTLOCK(NULL); } else { /* start specified printer device */ U16 devnum; U16 lcss; int stopprt; DEVBLK* dev; char* devclass; int rc; rc=parse_single_devnum(argv[1],&lcss,&devnum); if (rc<0) { return -1; } if (!(dev = find_device_by_devnum (lcss,devnum))) { devnotfound_msg(lcss,devnum); return -1; } (dev->hnd->query)(dev, &devclass, 0, NULL); if (strcasecmp(devclass,"PRT")) { logmsg( _("HHCPN017E Device %d:%4.4X is not a printer device\n"), lcss, devnum ); return -1; } /* un-stop the printer and raise attention interrupt */ stopprt = dev->stopprt; dev->stopprt = 0; rc = device_attention (dev, CSW_ATTN); if (rc) dev->stopprt = stopprt; switch (rc) { case 0: logmsg(_("HHCPN018I Printer %d:%4.4X started\n"), lcss,devnum); break; case 1: logmsg(_("HHCPN019E Printer %d:%4.4X not started: " "busy or interrupt pending\n"), lcss, devnum); break; case 2: logmsg(_("HHCPN020E Printer %d:%4.4X not started: " "attention request rejected\n"), lcss, devnum); break; case 3: logmsg(_("HHCPN021E Printer %d:%4.4X not started: " "subchannel not enabled\n"), lcss, devnum); break; } } return 0; } /*-------------------------------------------------------------------*/ /* g command - turn off single stepping and start CPU */ /*-------------------------------------------------------------------*/ int g_cmd(int argc, char *argv[], char *cmdline) { int i; UNREFERENCED(cmdline); UNREFERENCED(argc); UNREFERENCED(argv); OBTAIN_INTLOCK(NULL); sysblk.inststep = 0; SET_IC_TRACE; for (i = 0; i < HI_CPU; i++) if (IS_CPU_ONLINE(i) && sysblk.regs[i]->stepwait) { sysblk.regs[i]->cpustate = CPUSTATE_STARTED; WAKEUP_CPU(sysblk.regs[i]); } RELEASE_INTLOCK(NULL); return 0; } /*-------------------------------------------------------------------*/ /* stop command - stop CPU (or printer device if argument given) */ /*-------------------------------------------------------------------*/ int stop_cmd(int argc, char *argv[], char *cmdline) { UNREFERENCED(cmdline); if (argc < 2) { OBTAIN_INTLOCK(NULL); if (IS_CPU_ONLINE(sysblk.pcpu)) { REGS *regs = sysblk.regs[sysblk.pcpu]; regs->opinterv = 1; regs->cpustate = CPUSTATE_STOPPING; ON_IC_INTERRUPT(regs); WAKEUP_CPU (regs); } RELEASE_INTLOCK(NULL); } else { /* stop specified printer device */ U16 devnum; U16 lcss; DEVBLK* dev; char* devclass; int rc; rc=parse_single_devnum(argv[1],&lcss,&devnum); if (rc<0) { return -1; } if (!(dev = find_device_by_devnum (lcss, devnum))) { devnotfound_msg(lcss,devnum); return -1; } (dev->hnd->query)(dev, &devclass, 0, NULL); if (strcasecmp(devclass,"PRT")) { logmsg( _("HHCPN024E Device %d:%4.4X is not a printer device\n"), lcss, devnum ); return -1; } dev->stopprt = 1; logmsg( _("HHCPN025I Printer %d:%4.4X stopped\n"), lcss, devnum ); } return 0; } /*-------------------------------------------------------------------*/ /* startall command - start all CPU's */ /*-------------------------------------------------------------------*/ int startall_cmd(int argc, char *argv[], char *cmdline) { int i; CPU_BITMAP mask; UNREFERENCED(cmdline); UNREFERENCED(argc); UNREFERENCED(argv); OBTAIN_INTLOCK(NULL); mask = (~sysblk.started_mask) & sysblk.config_mask; for (i = 0; mask; i++) { if (mask & 1) { REGS *regs = sysblk.regs[i]; regs->opinterv = 0; regs->cpustate = CPUSTATE_STARTED; signal_condition(®s->intcond); } mask >>= 1; } RELEASE_INTLOCK(NULL); return 0; } /*-------------------------------------------------------------------*/ /* stopall command - stop all CPU's */ /*-------------------------------------------------------------------*/ DLL_EXPORT int stopall_cmd(int argc, char *argv[], char *cmdline) { int i; CPU_BITMAP mask; UNREFERENCED(cmdline); UNREFERENCED(argc); UNREFERENCED(argv); OBTAIN_INTLOCK(NULL); mask = sysblk.started_mask; for (i = 0; mask; i++) { if (mask & 1) { REGS *regs = sysblk.regs[i]; regs->opinterv = 1; regs->cpustate = CPUSTATE_STOPPING; ON_IC_INTERRUPT(regs); signal_condition(®s->intcond); } mask >>= 1; } RELEASE_INTLOCK(NULL); return 0; } #ifdef _FEATURE_CPU_RECONFIG /*-------------------------------------------------------------------*/ /* cf command - configure/deconfigure a CPU */ /*-------------------------------------------------------------------*/ int cf_cmd(int argc, char *argv[], char *cmdline) { int on = -1; UNREFERENCED(cmdline); if (argc == 2) { if (!strcasecmp(argv[1],"on")) on = 1; else if (!strcasecmp(argv[1], "off")) on = 0; } OBTAIN_INTLOCK(NULL); if (IS_CPU_ONLINE(sysblk.pcpu)) { if (on < 0) logmsg(_("HHCPN152I CPU%4.4X online\n"), sysblk.pcpu); else if (on == 0) deconfigure_cpu(sysblk.pcpu); } else { if (on < 0) logmsg(_("HHCPN153I CPU%4.4X offline\n"), sysblk.pcpu); else if (on > 0) configure_cpu(sysblk.pcpu); } RELEASE_INTLOCK(NULL); if (on >= 0) cf_cmd (0, NULL, NULL); return 0; } /*-------------------------------------------------------------------*/ /* cfall command - configure/deconfigure all CPU's */ /*-------------------------------------------------------------------*/ int cfall_cmd(int argc, char *argv[], char *cmdline) { int i; int on = -1; UNREFERENCED(cmdline); if (argc == 2) { if (!strcasecmp(argv[1],"on")) on = 1; else if (!strcasecmp(argv[1], "off")) on = 0; } OBTAIN_INTLOCK(NULL); for (i = 0; i < MAX_CPU_ENGINES; i++) if (IS_CPU_ONLINE(i)) { if (on < 0) logmsg(_("HHCPN154I CPU%4.4X online\n"), i); else if (on == 0) deconfigure_cpu(i); } else { if (on < 0) logmsg(_("HHCPN155I CPU%4.4X offline\n"), i); else if (on > 0 && i < MAX_CPU) configure_cpu(i); } RELEASE_INTLOCK(NULL); if (on >= 0) cfall_cmd (0, NULL, NULL); return 0; } #endif /*_FEATURE_CPU_RECONFIG*/ /*-------------------------------------------------------------------*/ /* quiet command - quiet PANEL */ /*-------------------------------------------------------------------*/ int quiet_cmd(int argc, char *argv[], char *cmdline) { UNREFERENCED(cmdline); UNREFERENCED(argc); UNREFERENCED(argv); #ifdef EXTERNALGUI if (extgui) { logmsg( _("HHCPN026W Ignored. (external GUI active)\n") ); return 0; } #endif /*EXTERNALGUI*/ sysblk.npquiet = !sysblk.npquiet; logmsg( _("HHCPN027I Automatic refresh %s.\n"), sysblk.npquiet ? _("disabled") : _("enabled") ); return 0; } /* format_tod - generate displayable date from TOD value */ /* always uses epoch of 1900 */ char * format_tod(char *buf, U64 tod, int flagdate) { int leapyear, years, days, hours, minutes, seconds, microseconds; if(tod >= TOD_YEAR) { tod -= TOD_YEAR; years = (tod / TOD_4YEARS * 4) + 1; tod %= TOD_4YEARS; if((leapyear = tod / TOD_YEAR) == 4) { tod %= TOD_YEAR; years--; tod += TOD_YEAR; } else tod %= TOD_YEAR; years += leapyear; } else years = 0; days = tod / TOD_DAY; tod %= TOD_DAY; hours = tod / TOD_HOUR; tod %= TOD_HOUR; minutes = tod / TOD_MIN; tod %= TOD_MIN; seconds = tod / TOD_SEC; microseconds = (tod % TOD_SEC) / TOD_USEC; if (flagdate) { years += 1900; days += 1; } sprintf(buf,"%4d.%03d %02d:%02d:%02d.%06d", years,days,hours,minutes,seconds,microseconds); return buf; } /*-------------------------------------------------------------------*/ /* timerint - display or set the timer interval */ /*-------------------------------------------------------------------*/ int timerint_cmd(int argc, char *argv[], char *cmdline) { UNREFERENCED(cmdline); if (argc > 1) { if (!strcasecmp(argv[1],"default")) sysblk.timerint = DEFAULT_TIMER_REFRESH_USECS; else if (!strcasecmp(argv[1],"reset")) sysblk.timerint = DEFAULT_TIMER_REFRESH_USECS; else { int timerint = 0; BYTE c; if (1 && sscanf(argv[1], "%d%c", &timerint, &c) == 1 && timerint >= 1 && timerint <= 1000000 ) { sysblk.timerint = timerint; } } } else logmsg( _("HHCPN037I Timer update interval = %d microsecond(s)\n"), sysblk.timerint ); return 0; } /*-------------------------------------------------------------------*/ /* clocks command - display tod clkc and cpu timer */ /*-------------------------------------------------------------------*/ int clocks_cmd(int argc, char *argv[], char *cmdline) { REGS *regs; char clock_buf[30]; U64 tod_now; U64 hw_now; S64 epoch_now; U64 epoch_now_abs; char epoch_sign; U64 clkc_now; S64 cpt_now; #if defined(_FEATURE_SIE) U64 vtod_now = 0; S64 vepoch_now = 0; U64 vepoch_now_abs = 0; char vepoch_sign = ' '; U64 vclkc_now = 0; S64 vcpt_now = 0; char sie_flag = 0; #endif U32 itimer = 0; char itimer_formatted[20]; char arch370_flag = 0; UNREFERENCED(cmdline); UNREFERENCED(argc); UNREFERENCED(argv); obtain_lock(&sysblk.cpulock[sysblk.pcpu]); if (!IS_CPU_ONLINE(sysblk.pcpu)) { release_lock(&sysblk.cpulock[sysblk.pcpu]); logmsg( _("HHCPN160W CPU%4.4X not configured\n"), sysblk.pcpu); return 0; } regs = sysblk.regs[sysblk.pcpu]; /* Get the clock values all at once for consistency and so we can release the CPU lock more quickly. */ tod_now = (tod_clock(regs) << 8) >> 8; hw_now = hw_tod; epoch_now = regs->tod_epoch; clkc_now = regs->clkc; cpt_now = CPU_TIMER(regs); #if defined(_FEATURE_SIE) if(regs->sie_active) { vtod_now = (TOD_CLOCK(regs->guestregs) << 8) >> 8; vepoch_now = regs->guestregs->tod_epoch; vclkc_now = regs->guestregs->clkc; vcpt_now = CPU_TIMER(regs->guestregs); sie_flag = 1; } #endif if (regs->arch_mode == ARCH_370) { itimer = INT_TIMER(regs); /* The interval timer counts 76800 per second, or one every 13.0208 microseconds. */ sprintf(itimer_formatted,"%02u:%02u:%02u.%06u", (itimer/(76800*60*60)),((itimer%(76800*60*60))/(76800*60)), ((itimer%(76800*60))/76800),((itimer%76800)*13)); arch370_flag = 1; } release_lock(&sysblk.cpulock[sysblk.pcpu]); logmsg( _("HHCPN028I tod = %16.16" I64_FMT "X %s\n"), (tod_now << 8),format_tod(clock_buf,tod_now,TRUE)); logmsg( _(" h/w = %16.16" I64_FMT "X %s\n"), (hw_now << 8),format_tod(clock_buf,hw_now,TRUE)); if (epoch_now < 0) { epoch_now_abs = -(epoch_now); epoch_sign = '-'; } else { epoch_now_abs = epoch_now; epoch_sign = ' '; } logmsg( _(" off = %16.16" I64_FMT "X %c%s\n"), (epoch_now << 8),epoch_sign, format_tod(clock_buf,epoch_now_abs,FALSE)); logmsg( _(" ckc = %16.16" I64_FMT "X %s\n"), (clkc_now << 8),format_tod(clock_buf,clkc_now,TRUE)); if (regs->cpustate != CPUSTATE_STOPPED) logmsg( _(" cpt = %16.16" I64_FMT "X\n"), cpt_now << 8); else logmsg( _(" cpt = not decrementing\n")); #if defined(_FEATURE_SIE) if(sie_flag) { logmsg( _(" vtod = %16.16" I64_FMT "X %s\n"), (vtod_now << 8),format_tod(clock_buf,vtod_now,TRUE)); if (epoch_now < 0) { epoch_now_abs = -(epoch_now); epoch_sign = '-'; } else { epoch_now_abs = epoch_now; epoch_sign = ' '; } logmsg( _(" voff = %16.16" I64_FMT "X %c%s\n"), (vepoch_now << 8),vepoch_sign, format_tod(clock_buf,vepoch_now_abs,FALSE)); logmsg( _(" vckc = %16.16" I64_FMT "X %s\n"), (vclkc_now << 8),format_tod(clock_buf,vclkc_now,TRUE)); logmsg( _(" vcpt = %16.16" I64_FMT "X\n"),vcpt_now << 8); } #endif if (arch370_flag) { logmsg( _(" itm = %8.8" I32_FMT "X %s\n"), itimer, itimer_formatted ); } return 0; } #ifdef OPTION_IODELAY_KLUDGE /*-------------------------------------------------------------------*/ /* iodelay command - display or set I/O delay value */ /*-------------------------------------------------------------------*/ int iodelay_cmd(int argc, char *argv[], char *cmdline) { UNREFERENCED(cmdline); if (argc > 1) { int iodelay = 0; BYTE c; /* Character work area */ if (sscanf(argv[1], "%d%c", &iodelay, &c) != 1) logmsg( _("HHCPN029E Invalid I/O delay value: %s\n"), argv[1] ); else sysblk.iodelay = iodelay; } else logmsg( _("HHCPN030I I/O delay = %d\n"), sysblk.iodelay ); return 0; } #endif /*OPTION_IODELAY_KLUDGE*/ #if defined( OPTION_TAPE_AUTOMOUNT ) /*-------------------------------------------------------------------*/ /* automount_cmd - show or update AUTOMOUNT directories list */ /*-------------------------------------------------------------------*/ int automount_cmd(int argc, char *argv[], char *cmdline) { int rc; UNREFERENCED(cmdline); if (argc < 2) { logmsg(_("HHCPN200E Missing operand; enter 'HELP AUTOMOUNT' for syntax.\n")); return -1; } if (strcasecmp(argv[1],"list") == 0) { TAMDIR* pTAMDIR = sysblk.tamdir; if (argc != 2) { logmsg(_("HHCPN201E Invalid syntax; enter 'HELP AUTOMOUNT' for help.\n")); return -1; } if (!pTAMDIR) { logmsg(_("HHCPN202E Empty list.\n")); return -1; } // List all entries... for (; pTAMDIR; pTAMDIR = pTAMDIR->next) logmsg(_("HHCPN203I \"%c%s\"\n") ,pTAMDIR->rej ? '-' : '+' ,pTAMDIR->dir ); return 0; } if (strcasecmp(argv[1],"add") == 0 || *argv[1] == '+') { char *argv2; char tamdir[MAX_PATH+1]; /* +1 for optional '+' or '-' prefix */ TAMDIR* pTAMDIR = NULL; // int was_empty = (sysblk.tamdir == NULL); if(*argv[1] == '+') { argv2 = argv[1] + 1; if (argc != 2 ) { logmsg(_("HHCPN204E Invalid syntax; enter 'HELP AUTOMOUNT' for help.\n")); return -1; } } else { argv2 = argv[2]; if (argc != 3 ) { logmsg(_("HHCPN204E Invalid syntax; enter 'HELP AUTOMOUNT' for help.\n")); return -1; } } // Add the requested entry... strlcpy (tamdir, argv2, sizeof(tamdir)); rc = add_tamdir( tamdir, &pTAMDIR ); // Did that work? switch (rc) { default: /* (oops!) */ { logmsg( _("HHCPN205E **LOGIC ERROR** file \"%s\", line %d\n"), __FILE__, __LINE__); return -1; } case 5: /* ("out of memory") */ { logmsg( _("HHCPN206E Out of memory!\n")); return -1; } case 1: /* ("unresolvable path") */ case 2: /* ("path inaccessible") */ { logmsg( _("HHCPN207E Invalid AUTOMOUNT directory: \"%s\": %s\n"), tamdir, strerror(errno)); return -1; } case 3: /* ("conflict w/previous") */ { logmsg( _("HHCPN208E AUTOMOUNT directory \"%s\"" " conflicts with previous specification\n"), tamdir); return -1; } case 4: /* ("duplicates previous") */ { logmsg( _("HHCPN209E AUTOMOUNT directory \"%s\"" " duplicates previous specification\n"), tamdir); return -1; } case 0: /* ("success") */ { logmsg(_("HHCPN210I %s%s AUTOMOUNT directory = \"%s\"\n"), pTAMDIR->dir == sysblk.defdir ? "Default " : "", pTAMDIR->rej ? "Disallowed" : "Allowed", pTAMDIR->dir); /* Define default AUTOMOUNT directory if needed */ if (sysblk.defdir == NULL) { static char cwd[ MAX_PATH ]; VERIFY( getcwd( cwd, sizeof(cwd) ) != NULL ); rc = strlen( cwd ); if (cwd[rc-1] != *PATH_SEP) strlcat (cwd, PATH_SEP, sizeof(cwd)); if (!(pTAMDIR = malloc( sizeof(TAMDIR) ))) { logmsg( _("HHCPN211E Out of memory!\n")); sysblk.defdir = cwd; /* EMERGENCY! */ } else { pTAMDIR->dir = strdup (cwd); pTAMDIR->len = strlen (cwd); pTAMDIR->rej = 0; pTAMDIR->next = sysblk.tamdir; sysblk.tamdir = pTAMDIR; sysblk.defdir = pTAMDIR->dir; } logmsg(_("HHCPN212I Default Allowed AUTOMOUNT directory = \"%s\"\n"), sysblk.defdir); } return 0; } } } if (strcasecmp(argv[1],"del") == 0 || *argv[1] == '-') { char *argv2; char tamdir1[MAX_PATH+1] = {0}; // (resolved path) char tamdir2[MAX_PATH+1] = {0}; // (expanded but unresolved path) char workdir[MAX_PATH+1] = {0}; // (work) char *tamdir = tamdir1; // (-> tamdir2 on retry) TAMDIR* pPrevTAMDIR = NULL; TAMDIR* pCurrTAMDIR = sysblk.tamdir; // int was_empty = (sysblk.tamdir == NULL); if(*argv[1] == '-') { argv2 = argv[1] + 1; if (argc != 2 ) { logmsg(_("HHCPN213E Invalid syntax; enter 'HELP AUTOMOUNT' for help.\n")); return -1; } } else { argv2 = argv[2]; if (argc != 3 ) { logmsg(_("HHCPN213E Invalid syntax; enter 'HELP AUTOMOUNT' for help.\n")); return -1; } } // Convert argument to absolute path ending with a slash strlcpy( tamdir2, argv2, sizeof(tamdir2) ); if (tamdir2[0] == '-') memmove (&tamdir2[0], &tamdir2[1], MAX_PATH); else if (tamdir2[0] == '+') memmove (&tamdir2[0], &tamdir2[1], MAX_PATH); #if defined(_MSVC_) // (expand any embedded %var% environment variables) rc = expand_environ_vars( tamdir2, workdir, MAX_PATH ); if (rc == 0) strlcpy (tamdir2, workdir, MAX_PATH); #endif // _MSVC_ if (sysblk.defdir == NULL #if defined(_MSVC_) || tamdir2[1] == ':' // (fullpath given?) #else // !_MSVC_ || tamdir2[0] == '/' // (fullpath given?) #endif // _MSVC_ || tamdir2[0] == '.' // (relative path given?) ) tamdir1[0] = 0; // (then use just given spec) else // (else prepend with default) strlcpy( tamdir1, sysblk.defdir, sizeof(tamdir1) ); // (finish building path to be resolved) strlcat( tamdir1, tamdir2, sizeof(tamdir1) ); // (try resolving it to an absolute path and // append trailing path separator if needed) if (realpath(tamdir1, workdir) != NULL) { strlcpy (tamdir1, workdir, MAX_PATH); rc = strlen( tamdir1 ); if (tamdir1[rc-1] != *PATH_SEP) strlcat (tamdir1, PATH_SEP, MAX_PATH); tamdir = tamdir1; // (try tamdir1 first) } else tamdir = tamdir2; // (try only tamdir2) rc = strlen( tamdir2 ); if (tamdir2[rc-1] != *PATH_SEP) strlcat (tamdir2, PATH_SEP, MAX_PATH); // Find entry to be deleted... for (;;) { for (pCurrTAMDIR = sysblk.tamdir, pPrevTAMDIR = NULL; pCurrTAMDIR; pPrevTAMDIR = pCurrTAMDIR, pCurrTAMDIR = pCurrTAMDIR->next) { if (strfilenamecmp( pCurrTAMDIR->dir, tamdir ) == 0) { int def = (sysblk.defdir == pCurrTAMDIR->dir); // Delete the found entry... if (pPrevTAMDIR) pPrevTAMDIR->next = pCurrTAMDIR->next; else sysblk.tamdir = pCurrTAMDIR->next; free( pCurrTAMDIR->dir ); free( pCurrTAMDIR ); // (point back to list begin) pCurrTAMDIR = sysblk.tamdir; logmsg(_("HHCPN214I Ok.%s\n"), pCurrTAMDIR ? "" : " (list now empty)"); // Default entry just deleted? if (def) { if (!pCurrTAMDIR) sysblk.defdir = NULL; // (no default) else { // Set new default entry... for (; pCurrTAMDIR; pCurrTAMDIR = pCurrTAMDIR->next) { if (pCurrTAMDIR->rej == 0) { sysblk.defdir = pCurrTAMDIR->dir; break; } } // If we couldn't find an existing allowable // directory entry to use as the new default, // then add the current directory and use it. if (!pCurrTAMDIR) { static char cwd[ MAX_PATH ] = {0}; VERIFY( getcwd( cwd, sizeof(cwd) ) != NULL ); rc = strlen( cwd ); if (cwd[rc-1] != *PATH_SEP) strlcat (cwd, PATH_SEP, sizeof(cwd)); if (!(pCurrTAMDIR = malloc( sizeof(TAMDIR) ))) { logmsg( _("HHCPN215E Out of memory!\n")); sysblk.defdir = cwd; /* EMERGENCY! */ } else { pCurrTAMDIR->dir = strdup (cwd); pCurrTAMDIR->len = strlen (cwd); pCurrTAMDIR->rej = 0; pCurrTAMDIR->next = sysblk.tamdir; sysblk.tamdir = pCurrTAMDIR; sysblk.defdir = pCurrTAMDIR->dir; } } logmsg(_("HHCPN216I Default Allowed AUTOMOUNT directory = \"%s\"\n"), sysblk.defdir); } } return 0; // (success) } } // (not found; try tamdir2 if we haven't yet) if (tamdir == tamdir2) break; tamdir = tamdir2; } if (sysblk.tamdir == NULL) logmsg(_("HHCPN217E Empty list.\n")); else logmsg(_("HHCPN218E Entry not found.\n")); return -1; } logmsg(_("HHCPN219E Unsupported function; enter 'HELP AUTOMOUNT' for syntax.\n")); return 0; } #endif /* OPTION_TAPE_AUTOMOUNT */ #if defined( OPTION_SCSI_TAPE ) // (helper function for 'scsimount' and 'devlist' commands) static void try_scsi_refresh( DEVBLK* dev ) { // PROGRAMMING NOTE: we can only ever cause the auto-scsi-mount // thread to startup or shutdown [according to the current user // setting] if the current drive status is "not mounted". // What we unfortunately CANNOT do (indeed MUST NOT do!) however // is actually "force" a refresh of a current [presumably bogus] // "mounted" status (to presumably detect that a tape that was // once mounted has now been manually unmounted for example). // The reasons for why this is not possible is clearly explained // in the 'update_status_scsitape' function in 'scsitape.c'. All // we can ever hope to do here is either cause an already-running // auto-mount thread to exit (if the user has just now disabled // auto-mounts) or else cause one to automatically start (if they // just enabled auto-mounts and there's no tape already mounted). // If the user manually unloaded a mounted tape (such that there // is now no longer a tape mounted even though the drive status // says there is), then they unfortunately have no choice but to // manually issue the 'devinit' command themselves, because, as // explained, we unfortunately cannot refresh a mounted status // for them (due to the inherent danger of doing so as explained // by comments in 'update_status_scsitape' in member scsitape.c). GENTMH_PARMS gen_parms; gen_parms.action = GENTMH_SCSI_ACTION_UPDATE_STATUS; gen_parms.dev = dev; broadcast_condition( &dev->stape_exit_cond ); // (force exit if needed) VERIFY( dev->tmh->generic( &gen_parms ) == 0 ); // (maybe update status) usleep(10*1000); // (let thread start/end) } /*-------------------------------------------------------------------*/ /* scsimount command - display or adjust the SCSI auto-mount option */ /*-------------------------------------------------------------------*/ int scsimount_cmd(int argc, char *argv[], char *cmdline) { char* eyecatcher = "*************************************************************************************************"; DEVBLK* dev; int tapeloaded; char* tapemsg=""; char volname[7]; BYTE mountreq, unmountreq; char* label_type; // Unused.. // int old_auto_scsi_mount_secs = sysblk.auto_scsi_mount_secs; UNREFERENCED(cmdline); if (argc > 1) { if ( strcasecmp( argv[1], "no" ) == 0 ) { sysblk.auto_scsi_mount_secs = 0; } else if ( strcasecmp( argv[1], "yes" ) == 0 ) { sysblk.auto_scsi_mount_secs = DEFAULT_AUTO_SCSI_MOUNT_SECS; } else { int auto_scsi_mount_secs; BYTE c; if ( sscanf( argv[1], "%d%c", &auto_scsi_mount_secs, &c ) != 1 || auto_scsi_mount_secs < 0 || auto_scsi_mount_secs > 99 ) { logmsg ( _( "HHCCF068E Invalid value: %s; Enter \"help scsimount\" for help.\n" ) ,argv[1] ); return 0; } sysblk.auto_scsi_mount_secs = auto_scsi_mount_secs; } } if ( sysblk.auto_scsi_mount_secs ) logmsg( _("SCSI auto-mount queries = every %d seconds (when needed)\n"), sysblk.auto_scsi_mount_secs ); else logmsg( _("SCSI auto-mount queries are disabled.\n") ); // Scan the device list looking for all SCSI tape devices // with either an active scsi mount thread and/or an out- // standing tape mount request... for ( dev = sysblk.firstdev; dev; dev = dev->nextdev ) { if ( !dev->allocated || TAPEDEVT_SCSITAPE != dev->tapedevt ) continue; // (not an active SCSI tape device; skip) try_scsi_refresh( dev ); // (see comments in function) logmsg ( _("SCSI auto-mount thread %s active for drive %u:%4.4X = %s.\n") ,dev->stape_mountmon_tid ? "IS" : "is NOT" ,SSID_TO_LCSS(dev->ssid) ,dev->devnum ,dev->filename ); if (!dev->tdparms.displayfeat) continue; mountreq = FALSE; // (default) unmountreq = FALSE; // (default) if (0 || TAPEDISPTYP_MOUNT == dev->tapedisptype || TAPEDISPTYP_UNMOUNT == dev->tapedisptype || TAPEDISPTYP_UMOUNTMOUNT == dev->tapedisptype ) { tapeloaded = dev->tmh->tapeloaded( dev, NULL, 0 ); if ( TAPEDISPTYP_MOUNT == dev->tapedisptype && !tapeloaded ) { mountreq = TRUE; unmountreq = FALSE; tapemsg = dev->tapemsg1; } else if ( TAPEDISPTYP_UNMOUNT == dev->tapedisptype && tapeloaded ) { unmountreq = TRUE; mountreq = FALSE; tapemsg = dev->tapemsg1; } else // ( TAPEDISPTYP_UMOUNTMOUNT == dev->tapedisptype ) { if (tapeloaded) { if ( !(dev->tapedispflags & TAPEDISPFLG_MESSAGE2) ) { unmountreq = TRUE; mountreq = FALSE; tapemsg = dev->tapemsg1; } } else // (!tapeloaded) { mountreq = TRUE; unmountreq = FALSE; tapemsg = dev->tapemsg2; } } } if ((mountreq || unmountreq) && ' ' != *tapemsg) { switch (*(tapemsg+7)) { case 'A': label_type = "ascii-standard"; break; case 'S': label_type = "standard"; break; case 'N': label_type = "non"; break; case 'U': label_type = "un"; break; default : label_type = "??"; break; } volname[0]=0; if (*(tapemsg+1)) { strncpy( volname, tapemsg+1, 6 ); volname[6]=0; } logmsg ( _("\n%s\nHHCCF069I %s of %s-labeled volume \"%s\" pending for drive %u:%4.4X = %s\n%s\n\n") ,eyecatcher ,mountreq ? "Mount" : "Dismount" ,label_type ,volname ,SSID_TO_LCSS(dev->ssid) ,dev->devnum ,dev->filename ,eyecatcher ); } else { logmsg( _("No mount/dismount requests pending for drive %u:%4.4X = %s.\n"), SSID_TO_LCSS(dev->ssid),dev->devnum, dev->filename ); } } return 0; } #endif /* defined( OPTION_SCSI_TAPE ) */ /*-------------------------------------------------------------------*/ /* cckd command */ /*-------------------------------------------------------------------*/ int cckd_cmd(int argc, char *argv[], char *cmdline) { char* p = strtok(cmdline+4," \t"); UNREFERENCED(argc); UNREFERENCED(argv); return cckd_command(p,1); } /*-------------------------------------------------------------------*/ /* ctc command - enable/disable CTC debugging */ /*-------------------------------------------------------------------*/ int ctc_cmd( int argc, char *argv[], char *cmdline ) { DEVBLK* dev; CTCBLK* pCTCBLK; LCSDEV* pLCSDEV; LCSBLK* pLCSBLK; U16 lcss; U16 devnum; BYTE onoff; UNREFERENCED( cmdline ); // Format: "ctc debug { on | off } [ | ALL ]" if (0 || argc < 3 || strcasecmp( argv[1], "debug" ) != 0 || (1 && strcasecmp( argv[2], "on" ) != 0 && strcasecmp( argv[2], "off" ) != 0 ) || argc > 4 || (1 && argc == 4 && strcasecmp( argv[3], "ALL" ) != 0 && parse_single_devnum( argv[3], &lcss, &devnum) < 0 ) ) { panel_command ("help ctc"); return -1; } onoff = (strcasecmp( argv[2], "on" ) == 0); if (argc < 4 || strcasecmp( argv[3], "ALL" ) == 0) { for ( dev = sysblk.firstdev; dev; dev = dev->nextdev ) { if (0 || !dev->allocated || 0x3088 != dev->devtype || (CTC_CTCI != dev->ctctype && CTC_LCS != dev->ctctype) ) continue; if (CTC_CTCI == dev->ctctype) { pCTCBLK = dev->dev_data; pCTCBLK->fDebug = onoff; } else // (CTC_LCS == dev->ctctype) { pLCSDEV = dev->dev_data; pLCSBLK = pLCSDEV->pLCSBLK; pLCSBLK->fDebug = onoff; } } logmsg( _("HHCPNXXXI CTC debugging now %s for all CTCI/LCS device groups.\n"), onoff ? _("ON") : _("OFF") ); } else { int i; DEVGRP* pDEVGRP; DEVBLK* pDEVBLK; if (!(dev = find_device_by_devnum ( lcss, devnum ))) { devnotfound_msg( lcss, devnum ); return -1; } pDEVGRP = dev->group; if (CTC_CTCI == dev->ctctype) { for (i=0; i < pDEVGRP->acount; i++) { pDEVBLK = pDEVGRP->memdev[i]; pCTCBLK = pDEVBLK->dev_data; pCTCBLK->fDebug = onoff; } } else if (CTC_LCS == dev->ctctype) { for (i=0; i < pDEVGRP->acount; i++) { pDEVBLK = pDEVGRP->memdev[i]; pLCSDEV = pDEVBLK->dev_data; pLCSBLK = pLCSDEV->pLCSBLK; pLCSBLK->fDebug = onoff; } } else { logmsg( _("HHCPN034E Device %d:%4.4X is not a CTCI or LCS device\n"), lcss, devnum ); return -1; } logmsg( _("HHCPNXXXI CTC debugging now %s for %s device %d:%4.4X group.\n"), onoff ? _("ON") : _("OFF"), CTC_LCS == dev->ctctype ? "LCS" : "CTCI", lcss, devnum ); } return 0; } #if defined(OPTION_W32_CTCI) /*-------------------------------------------------------------------*/ /* tt32 command - control/query CTCI-W32 functionality */ /*-------------------------------------------------------------------*/ int tt32_cmd( int argc, char *argv[], char *cmdline ) { int rc = 0; U16 devnum; U16 lcss; DEVBLK* dev; UNREFERENCED(cmdline); if (argc < 2) { logmsg( _("HHCPN188E Missing arguments; enter 'help tt32' for help.\n") ); rc = -1; } else if (strcasecmp(argv[1],"stats") == 0) { if (argc < 3) { missing_devnum(); return -1; } if ((rc = parse_single_devnum(argv[2], &lcss, &devnum)) < 0) return -1; if (!(dev = find_device_by_devnum (lcss, devnum)) && !(dev = find_device_by_devnum (lcss, devnum ^ 0x01))) { devnotfound_msg(lcss,devnum); return -1; } if (CTC_CTCI != dev->ctctype && CTC_LCS != dev->ctctype) { logmsg( _("HHCPN034E Device %d:%4.4X is not a CTCI or LCS device\n"), lcss, devnum ); return -1; } if (debug_tt32_stats) rc = debug_tt32_stats (dev->fd); else { logmsg( _("(error)\n") ); rc = -1; } } else if (strcasecmp(argv[1],"debug") == 0) { if (debug_tt32_tracing) { debug_tt32_tracing(1); // 1=ON rc = 0; logmsg( _("HHCPN189I TT32 debug tracing messages enabled\n") ); } else { logmsg( _("(error)\n") ); rc = -1; } } else if (strcasecmp(argv[1],"nodebug") == 0) { if (debug_tt32_tracing) { debug_tt32_tracing(0); // 0=OFF rc = 0; logmsg( _("HHCPN189I TT32 debug tracing messages disabled\n") ); } else { logmsg( _("(error)\n") ); rc = -1; } } else { logmsg( _("HHCPN187E Invalid argument\n") ); rc = -1; } return rc; } #endif /* defined(OPTION_W32_CTCI) */ /*-------------------------------------------------------------------*/ /* store command - store CPU status at absolute zero */ /*-------------------------------------------------------------------*/ int store_cmd(int argc, char *argv[], char *cmdline) { REGS *regs; UNREFERENCED(cmdline); UNREFERENCED(argc); UNREFERENCED(argv); obtain_lock(&sysblk.cpulock[sysblk.pcpu]); if (!IS_CPU_ONLINE(sysblk.pcpu)) { release_lock(&sysblk.cpulock[sysblk.pcpu]); logmsg( _("HHCPN160W CPU%4.4X not configured\n"), sysblk.pcpu); return 0; } regs = sysblk.regs[sysblk.pcpu]; /* Command is valid only when CPU is stopped */ if (regs->cpustate != CPUSTATE_STOPPED) { logmsg( _("HHCPN035E store status rejected: CPU not stopped\n") ); return -1; } /* Store status in 512 byte block at absolute location 0 */ store_status (regs, 0); release_lock(&sysblk.cpulock[sysblk.pcpu]); logmsg (_("HHCCP010I CPU%4.4X store status completed.\n"), regs->cpuad); return 0; } /*-------------------------------------------------------------------*/ /* sclproot command - set SCLP base directory */ /*-------------------------------------------------------------------*/ int sclproot_cmd(int argc, char *argv[], char *cmdline) { char *basedir; UNREFERENCED(cmdline); if (argc > 1) if (!strcasecmp(argv[1],"none")) set_sce_dir(NULL); else set_sce_dir(argv[1]); else if((basedir = get_sce_dir())) logmsg(_("SCLPROOT %s\n"),basedir); else logmsg(_("SCLP DISK I/O Disabled\n")); return 0; } #if defined(OPTION_HTTP_SERVER) /*-------------------------------------------------------------------*/ /* httproot command - set HTTP server base directory */ /*-------------------------------------------------------------------*/ int httproot_cmd(int argc, char *argv[], char *cmdline) { UNREFERENCED(cmdline); if (argc > 1) { if (sysblk.httproot) free(sysblk.httproot); sysblk.httproot = strdup(argv[1]); } else if(sysblk.httproot) logmsg(_("HHCnnxxxI HTTPROOT %s\n"),sysblk.httproot); else logmsg(_("HHCnnxxxI HTTPROOT not specified\n")); return 0; } /*-------------------------------------------------------------------*/ /* httpport command - set HTTP server port */ /*-------------------------------------------------------------------*/ int httpport_cmd(int argc, char *argv[], char *cmdline) { char c; UNREFERENCED(cmdline); if (argc > 1) { if (!strcasecmp(argv[1],"none")) { if(sysblk.httpport) { sysblk.httpport = 0; signal_thread(sysblk.httptid, SIGUSR2); } } else if(sysblk.httpport) { logmsg(_("HHCxxnnnS HTTP server already active\n")); return -1; } else { if (sscanf(argv[1], "%hu%c", &sysblk.httpport, &c) != 1 || sysblk.httpport == 0 || (sysblk.httpport < 1024 && sysblk.httpport != 80) ) { logmsg(_("HHCCF029S Invalid HTTP port number %s\n"), argv[1]); return -1; } if (argc > 2) { if (!strcasecmp(argv[2],"auth")) sysblk.httpauth = 1; else if (strcasecmp(argv[2],"noauth")) { logmsg(_("HHCCF005S Unrecognized argument %s\n"),argv[2]); return -1; } } if (argc > 3) { if (sysblk.httpuser) free(sysblk.httpuser); sysblk.httpuser = strdup(argv[3]); } if (argc > 4) { if (sysblk.httppass) free(sysblk.httppass); sysblk.httppass = strdup(argv[4]); } /* Start the http server connection thread */ if ( create_thread (&sysblk.httptid, DETACHED, http_server, NULL, "http_server") ) { logmsg(_("HHCIN005S Cannot create http_server thread: %s\n"), strerror(errno)); return -1; } } } else logmsg(_("HHCxxnnnI HTTPPORT %d\n"),sysblk.httpport); return 0; } #if defined( HTTP_SERVER_CONNECT_KLUDGE ) /*-------------------------------------------------------------------*/ /* http_server_kludge_msecs */ /*-------------------------------------------------------------------*/ int httpskm_cmd(int argc, char *argv[], char *cmdline) { char c; UNREFERENCED(cmdline); if (argc > 1) { int http_server_kludge_msecs; if ( sscanf( argv[1], "%d%c", &http_server_kludge_msecs, &c ) != 1 || http_server_kludge_msecs <= 0 || http_server_kludge_msecs > 50 ) { logmsg(_("HHCCF066S Invalid HTTP_SERVER_CONNECT_KLUDGE value: %s\n" ),argv[1]); return -1; } sysblk.http_server_kludge_msecs = http_server_kludge_msecs; } else logmsg(_("HHCxxnnnS HTTP_SERVER_CONNECT_KLUDGE value: %s\n" ) ,sysblk.http_server_kludge_msecs); return 0; } #endif // defined( HTTP_SERVER_CONNECT_KLUDGE ) #endif /*defined(OPTION_HTTP_SERVER)*/ #if defined(_FEATURE_ASN_AND_LX_REUSE) /*-------------------------------------------------------------------*/ /* alrf command - display or set asn_and_lx_reuse */ /*-------------------------------------------------------------------*/ int alrf_cmd(int argc, char *argv[], char *cmdline) { UNREFERENCED(cmdline); if (argc > 1) { if(strcasecmp(argv[1],"enable")==0) sysblk.asnandlxreuse=1; else { if(strcasecmp(argv[1],"disable")==0) sysblk.asnandlxreuse=0; else { logmsg(_("HHCCF067S Incorrect keyword %s for the ASN_AND_LX_REUSE statement.\n"), argv[1]); return -1; } } } else logmsg(_("HHCCF0028I ASN and LX reuse is %s\n"),sysblk.asnandlxreuse ? "Enabled" : "Disabled"); return 0; } #endif /*defined(_FEATURE_ASN_AND_LX_REUSE)*/ /*-------------------------------------------------------------------*/ /* toddrag command - display or set TOD clock drag factor */ /*-------------------------------------------------------------------*/ int toddrag_cmd(int argc, char *argv[], char *cmdline) { UNREFERENCED(cmdline); if (argc > 1) { double toddrag = -1.0; sscanf(argv[1], "%lf", &toddrag); if (toddrag >= 0.0001 && toddrag <= 10000.0) { /* Set clock steering based on drag factor */ set_tod_steering(-(1.0-(1.0/toddrag))); } } else logmsg( _("HHCPN036I TOD clock drag factor = %lf\n"), (1.0/(1.0+get_tod_steering()))); return 0; } #ifdef PANEL_REFRESH_RATE /*-------------------------------------------------------------------*/ /* panrate command - display or set rate at which console refreshes */ /*-------------------------------------------------------------------*/ int panrate_cmd(int argc, char *argv[], char *cmdline) { UNREFERENCED(cmdline); if (argc > 1) { if (!strcasecmp(argv[1],"fast")) sysblk.panrate = PANEL_REFRESH_RATE_FAST; else if (!strcasecmp(argv[1],"slow")) sysblk.panrate = PANEL_REFRESH_RATE_SLOW; else { int trate = 0; sscanf(argv[1],"%d", &trate); if (trate >= (1000 / CLK_TCK) && trate < 5001) sysblk.panrate = trate; } } else logmsg( _("HHCPN037I Panel refresh rate = %d millisecond(s)\n"), sysblk.panrate ); return 0; } #endif /*PANEL_REFRESH_RATE */ /*-------------------------------------------------------------------*/ /* pantitle xxxxxxxx command - set console title */ /*-------------------------------------------------------------------*/ int pantitle_cmd(int argc, char *argv[], char *cmdline) { UNREFERENCED(cmdline); /* Update pantitle if operand is specified */ if (argc > 1) { if (sysblk.pantitle) free(sysblk.pantitle); sysblk.pantitle = strdup(argv[1]); } else logmsg( _("HHCxxnnnI pantitle = %s\n"),sysblk.pantitle); return 0; } #ifdef OPTION_MSGHLD /*-------------------------------------------------------------------*/ /* msghld command - display or set rate at which console refreshes */ /*-------------------------------------------------------------------*/ int msghld_cmd(int argc, char *argv[], char *cmdline) { UNREFERENCED(cmdline); if(argc == 2) { if(!strcasecmp(argv[1], "info")) { logmsg("Current message held time is %d seconds.\n", sysblk.keep_timeout_secs); return(0); } else if(!strcasecmp(argv[1], "clear")) { expire_kept_msgs(1); logmsg("Held messages cleared.\n"); return(0); } else { int new_timeout; if(sscanf(argv[1], "%d", &new_timeout) && new_timeout >= 0) { sysblk.keep_timeout_secs = new_timeout; logmsg("The message held time is set to %d seconds.\n", sysblk.keep_timeout_secs); return(0); } } } logmsg("msghld: Invalid usage\n"); return(0); } #endif // OPTION_MSGHLD /*-------------------------------------------------------------------*/ /* shell command */ /*-------------------------------------------------------------------*/ int sh_cmd(int argc, char *argv[], char *cmdline) { char* cmd; UNREFERENCED(argc); UNREFERENCED(argv); if (sysblk.shcmdopt & SHCMDOPT_DISABLE) { logmsg( _("HHCPN180E shell commands are disabled\n")); return -1; } cmd = cmdline + 2; while (isspace(*cmd)) cmd++; if (*cmd) return herc_system (cmd); return -1; } /*-------------------------------------------------------------------*/ /* change directory command */ /*-------------------------------------------------------------------*/ int cd_cmd(int argc, char *argv[], char *cmdline) { char* path; char cwd [ MAX_PATH ]; UNREFERENCED(argc); UNREFERENCED(argv); if (sysblk.shcmdopt & SHCMDOPT_DISABLE) { logmsg( _("HHCPN180E shell commands are disabled\n")); return -1; } path = cmdline + 2; while (isspace(*path)) path++; chdir(path); getcwd( cwd, sizeof(cwd) ); logmsg("%s\n",cwd); HDC1( debug_cd_cmd, cwd ); return 0; } /*-------------------------------------------------------------------*/ /* print working directory command */ /*-------------------------------------------------------------------*/ int pwd_cmd(int argc, char *argv[], char *cmdline) { char cwd [ MAX_PATH ]; UNREFERENCED(argv); UNREFERENCED(cmdline); if (sysblk.shcmdopt & SHCMDOPT_DISABLE) { logmsg( _("HHCPN180E shell commands are disabled\n")); return -1; } if (argc > 1) { logmsg( _("HHCPN163E Invalid format. Command does not support any arguments.\n")); return -1; } getcwd( cwd, sizeof(cwd) ); logmsg("%s\n",cwd); return 0; } /*-------------------------------------------------------------------*/ /* gpr command - display or alter general purpose registers */ /*-------------------------------------------------------------------*/ int gpr_cmd(int argc, char *argv[], char *cmdline) { REGS *regs; UNREFERENCED(cmdline); obtain_lock(&sysblk.cpulock[sysblk.pcpu]); if (!IS_CPU_ONLINE(sysblk.pcpu)) { release_lock(&sysblk.cpulock[sysblk.pcpu]); logmsg( _("HHCPN160W CPU%4.4X not configured\n"), sysblk.pcpu); return 0; } regs = sysblk.regs[sysblk.pcpu]; if (argc > 1) { int reg_num; BYTE equal_sign, c; U64 reg_value; if (argc > 2) { release_lock(&sysblk.cpulock[sysblk.pcpu]); logmsg( _("HHCPN162E Invalid format. Enter \"help gpr\" for help.\n")); return 0; } if (0 || sscanf( argv[1], "%d%c%"I64_FMT"x%c", ®_num, &equal_sign, ®_value, &c ) != 3 || 0 > reg_num || 15 < reg_num || '=' != equal_sign ) { release_lock(&sysblk.cpulock[sysblk.pcpu]); logmsg( _("HHCPN162E Invalid format. .Enter \"help gpr\" for help.\n")); return 0; } if ( ARCH_900 == regs->arch_mode ) regs->GR_G(reg_num) = (U64) reg_value; else regs->GR_L(reg_num) = (U32) reg_value; } display_regs (regs); release_lock(&sysblk.cpulock[sysblk.pcpu]); return 0; } /*-------------------------------------------------------------------*/ /* fpr command - display floating point registers */ /*-------------------------------------------------------------------*/ int fpr_cmd(int argc, char *argv[], char *cmdline) { REGS *regs; UNREFERENCED(cmdline); UNREFERENCED(argc); UNREFERENCED(argv); obtain_lock(&sysblk.cpulock[sysblk.pcpu]); if (!IS_CPU_ONLINE(sysblk.pcpu)) { release_lock(&sysblk.cpulock[sysblk.pcpu]); logmsg( _("HHCPN160W CPU%4.4X not configured\n"), sysblk.pcpu); return 0; } regs = sysblk.regs[sysblk.pcpu]; display_fregs (regs); release_lock(&sysblk.cpulock[sysblk.pcpu]); return 0; } /*-------------------------------------------------------------------*/ /* fpc command - display floating point control register */ /*-------------------------------------------------------------------*/ int fpc_cmd(int argc, char *argv[], char *cmdline) { REGS *regs; UNREFERENCED(cmdline); UNREFERENCED(argc); UNREFERENCED(argv); obtain_lock(&sysblk.cpulock[sysblk.pcpu]); if (!IS_CPU_ONLINE(sysblk.pcpu)) { release_lock(&sysblk.cpulock[sysblk.pcpu]); logmsg( _("HHCPN160W CPU%4.4X not configured\n"), sysblk.pcpu); return 0; } regs = sysblk.regs[sysblk.pcpu]; logmsg( "FPC=%8.8"I32_FMT"X\n", regs->fpc ); release_lock(&sysblk.cpulock[sysblk.pcpu]); return 0; } /*-------------------------------------------------------------------*/ /* cr command - display or alter control registers */ /*-------------------------------------------------------------------*/ int cr_cmd(int argc, char *argv[], char *cmdline) { REGS *regs; int cr_num; BYTE equal_sign, c; U64 cr_value; UNREFERENCED(cmdline); obtain_lock(&sysblk.cpulock[sysblk.pcpu]); if (!IS_CPU_ONLINE(sysblk.pcpu)) { release_lock(&sysblk.cpulock[sysblk.pcpu]); logmsg( _("HHCPN160W CPU%4.4X not configured\n"), sysblk.pcpu); return 0; } regs = sysblk.regs[sysblk.pcpu]; if (argc > 1) { if (argc > 2 || sscanf( argv[1], "%d%c%"I64_FMT"x%c", &cr_num, &equal_sign, &cr_value, &c ) != 3 || '=' != equal_sign || cr_num < 0 || cr_num > 15) { release_lock(&sysblk.cpulock[sysblk.pcpu]); logmsg( _("HHCPN164E Invalid format. .Enter \"help cr\" for help.\n")); return 0; } if ( ARCH_900 == regs->arch_mode ) regs->CR_G(cr_num) = (U64)cr_value; else regs->CR_G(cr_num) = (U32)cr_value; } display_cregs (regs); release_lock(&sysblk.cpulock[sysblk.pcpu]); return 0; } /*-------------------------------------------------------------------*/ /* ar command - display access registers */ /*-------------------------------------------------------------------*/ int ar_cmd(int argc, char *argv[], char *cmdline) { REGS *regs; UNREFERENCED(cmdline); UNREFERENCED(argc); UNREFERENCED(argv); obtain_lock(&sysblk.cpulock[sysblk.pcpu]); if (!IS_CPU_ONLINE(sysblk.pcpu)) { release_lock(&sysblk.cpulock[sysblk.pcpu]); logmsg( _("HHCPN160W CPU%4.4X not configured\n"), sysblk.pcpu); return 0; } regs = sysblk.regs[sysblk.pcpu]; display_aregs (regs); release_lock(&sysblk.cpulock[sysblk.pcpu]); return 0; } /*-------------------------------------------------------------------*/ /* pr command - display prefix register */ /*-------------------------------------------------------------------*/ int pr_cmd(int argc, char *argv[], char *cmdline) { REGS *regs; UNREFERENCED(cmdline); UNREFERENCED(argc); UNREFERENCED(argv); obtain_lock(&sysblk.cpulock[sysblk.pcpu]); if (!IS_CPU_ONLINE(sysblk.pcpu)) { release_lock(&sysblk.cpulock[sysblk.pcpu]); logmsg( _("HHCPN160W CPU%4.4X not configured\n"), sysblk.pcpu); return 0; } regs = sysblk.regs[sysblk.pcpu]; if(regs->arch_mode == ARCH_900) logmsg( "Prefix=%16.16" I64_FMT "X\n", (long long)regs->PX_G ); else logmsg( "Prefix=%8.8X\n", regs->PX_L ); release_lock(&sysblk.cpulock[sysblk.pcpu]); return 0; } /*-------------------------------------------------------------------*/ /* psw command - display or alter program status word */ /*-------------------------------------------------------------------*/ int psw_cmd(int argc, char *argv[], char *cmdline) { REGS *regs; BYTE c; U64 newia=0; int newam=0, newas=0, newcc=0, newcmwp=0, newpk=0, newpm=0, newsm=0; int updia=0, updas=0, updcc=0, updcmwp=0, updpk=0, updpm=0, updsm=0; int n, errflag, stopflag=0, modflag=0; UNREFERENCED(cmdline); obtain_lock(&sysblk.cpulock[sysblk.pcpu]); if (!IS_CPU_ONLINE(sysblk.pcpu)) { release_lock(&sysblk.cpulock[sysblk.pcpu]); logmsg( _("HHCPN160W CPU%4.4X not configured\n"), sysblk.pcpu); return 0; } regs = sysblk.regs[sysblk.pcpu]; /* Process optional operands */ for (n = 1; n < argc; n++) { modflag = 1; errflag = 0; if (strncasecmp(argv[n],"sm=",3) == 0) { /* PSW system mask operand */ if (sscanf(argv[n]+3, "%x%c", &newsm, &c) == 1 && newsm >= 0 && newsm <= 255) updsm = 1; else errflag = 1; } else if (strncasecmp(argv[n],"pk=",3) == 0) { /* PSW protection key operand */ if (sscanf(argv[n]+3, "%d%c", &newpk, &c) == 1 && newpk >= 0 && newpk <= 15) updpk = 1; else errflag = 1; } else if (strncasecmp(argv[n],"cmwp=",5) == 0) { /* PSW CMWP bits operand */ if (sscanf(argv[n]+5, "%x%c", &newcmwp, &c) == 1 && newcmwp >= 0 && newcmwp <= 15) updcmwp = 1; else errflag = 1; } else if (strncasecmp(argv[n],"as=",3) == 0) { /* PSW address-space control operand */ if (strcasecmp(argv[n]+3,"pri") == 0) newas = PSW_PRIMARY_SPACE_MODE; else if (strcmp(argv[n]+3,"ar") == 0) newas = PSW_ACCESS_REGISTER_MODE; else if (strcmp(argv[n]+3,"sec") == 0) newas = PSW_SECONDARY_SPACE_MODE; else if (strcmp(argv[n]+3,"home") == 0) newas = PSW_HOME_SPACE_MODE; else errflag = 1; if (errflag == 0) updas = 1; } else if (strncasecmp(argv[n],"cc=",3) == 0) { /* PSW condition code operand */ if (sscanf(argv[n]+3, "%d%c", &newcc, &c) == 1 && newcc >= 0 && newcc <= 3) updcc = 1; else errflag = 1; } else if (strncasecmp(argv[n],"pm=",3) == 0) { /* PSW program mask operand */ if (sscanf(argv[n]+3, "%x%c", &newpm, &c) == 1 && newpm >= 0 && newpm <= 15) updpm = 1; else errflag = 1; } else if (strncasecmp(argv[n],"am=",3) == 0) { /* PSW addressing mode operand */ if (strcmp(argv[n]+3,"24") == 0) newam = 24; else if (strcmp(argv[n]+3,"31") == 0 && (sysblk.arch_mode == ARCH_390 || sysblk.arch_mode == ARCH_900)) newam = 31; else if (strcmp(argv[n]+3,"64") == 0 && sysblk.arch_mode == ARCH_900) newam = 64; else errflag = 1; } else if (strncasecmp(argv[n],"ia=",3) == 0) { /* PSW instruction address operand */ if (sscanf(argv[n]+3, "%"I64_FMT"x%c", &newia, &c) == 1) updia = 1; else errflag = 1; } else /* unknown operand keyword */ errflag = 1; /* Error message if this operand was invalid */ if (errflag) { logmsg( _("HHCPN165E Invalid operand %s\n"), argv[n]); stopflag = 1; } } /* end for(n) */ /* Finish now if any errors occurred */ if (stopflag) { release_lock(&sysblk.cpulock[sysblk.pcpu]); return 0; } /* Update the PSW system mask, if specified */ if (updsm) { regs->psw.sysmask = newsm; } /* Update the PSW protection key, if specified */ if (updpk) { regs->psw.pkey = newpk << 4; } /* Update the PSW CMWP bits, if specified */ if (updcmwp) { regs->psw.states = newcmwp; } /* Update the PSW address-space control mode, if specified */ if (updas && (ECMODE(®s->psw) || sysblk.arch_mode == ARCH_390 || sysblk.arch_mode == ARCH_900)) { regs->psw.asc = newas; } /* Update the PSW condition code, if specified */ if (updcc) { regs->psw.cc = newcc; } /* Update the PSW program mask, if specified */ if (updpm) { regs->psw.progmask = newpm; } /* Update the PSW addressing mode, if specified */ switch(newam) { case 64: regs->psw.amode = regs->psw.amode64 = 1; regs->psw.AMASK_G = AMASK64; break; case 31: regs->psw.amode = 1; regs->psw.amode64 = 0; regs->psw.AMASK_G = AMASK31; break; case 24: regs->psw.amode = regs->psw.amode64 = 0; regs->psw.AMASK_G = AMASK24; break; } /* end switch(newam) */ /* Update the PSW instruction address, if specified */ if (updia) { regs->psw.IA_G = newia; } /* If any modifications were made, reapply the addressing mode mask to the instruction address and invalidate the instruction pointer */ if (modflag) { regs->psw.IA_G &= regs->psw.AMASK_G; regs->aie = NULL; } /* Display the PSW field by field */ logmsg("psw sm=%2.2X pk=%d cmwp=%X as=%s cc=%d pm=%X am=%s ia=%"I64_FMT"X\n", regs->psw.sysmask, regs->psw.pkey >> 4, regs->psw.states, (regs->psw.asc == PSW_PRIMARY_SPACE_MODE ? "pri" : regs->psw.asc == PSW_ACCESS_REGISTER_MODE ? "ar" : regs->psw.asc == PSW_SECONDARY_SPACE_MODE ? "sec" : regs->psw.asc == PSW_HOME_SPACE_MODE ? "home" : "???"), regs->psw.cc, regs->psw.progmask, (regs->psw.amode == 0 && regs->psw.amode64 == 0 ? "24" : regs->psw.amode == 1 && regs->psw.amode64 == 0 ? "31" : regs->psw.amode == 1 && regs->psw.amode64 == 1 ? "64" : "???"), regs->psw.IA_G); /* Display the PSW */ display_psw (regs); release_lock(&sysblk.cpulock[sysblk.pcpu]); return 0; } /*-------------------------------------------------------------------*/ /* restart command - generate restart interrupt */ /*-------------------------------------------------------------------*/ int restart_cmd(int argc, char *argv[], char *cmdline) { UNREFERENCED(cmdline); UNREFERENCED(argc); UNREFERENCED(argv); /* Check that target processor type allows IPL */ if (sysblk.ptyp[sysblk.pcpu] == SCCB_PTYP_IFA || sysblk.ptyp[sysblk.pcpu] == SCCB_PTYP_SUP) { logmsg(_("HHCPN052E Target CPU %d type %d" " does not allow ipl nor restart\n"), sysblk.pcpu, sysblk.ptyp[sysblk.pcpu]); return -1; } logmsg( _("HHCPN038I Restart key depressed\n") ); /* Obtain the interrupt lock */ OBTAIN_INTLOCK(NULL); if (!IS_CPU_ONLINE(sysblk.pcpu)) { RELEASE_INTLOCK(NULL); logmsg( _("HHCPN160W CPU%4.4X not configured\n"), sysblk.pcpu ); return 0; } /* Indicate that a restart interrupt is pending */ ON_IC_RESTART(sysblk.regs[sysblk.pcpu]); /* Ensure that a stopped CPU will recognize the restart */ if (sysblk.regs[sysblk.pcpu]->cpustate == CPUSTATE_STOPPED) sysblk.regs[sysblk.pcpu]->cpustate = CPUSTATE_STOPPING; sysblk.regs[sysblk.pcpu]->checkstop = 0; /* Signal CPU that an interrupt is pending */ WAKEUP_CPU (sysblk.regs[sysblk.pcpu]); /* Release the interrupt lock */ RELEASE_INTLOCK(NULL); return 0; } /*-------------------------------------------------------------------*/ /* r command - display or alter real storage */ /*-------------------------------------------------------------------*/ int r_cmd(int argc, char *argv[], char *cmdline) { REGS *regs; UNREFERENCED(argc); UNREFERENCED(argv); obtain_lock(&sysblk.cpulock[sysblk.pcpu]); if (!IS_CPU_ONLINE(sysblk.pcpu)) { release_lock(&sysblk.cpulock[sysblk.pcpu]); logmsg( _("HHCPN160W CPU%4.4X not configured\n"), sysblk.pcpu); return 0; } regs = sysblk.regs[sysblk.pcpu]; alter_display_real (cmdline+1, regs); release_lock(&sysblk.cpulock[sysblk.pcpu]); return 0; } /*-------------------------------------------------------------------*/ /* u command - disassemble */ /*-------------------------------------------------------------------*/ int u_cmd(int argc, char *argv[], char *cmdline) { REGS *regs; UNREFERENCED(argc); UNREFERENCED(argv); obtain_lock(&sysblk.cpulock[sysblk.pcpu]); if (!IS_CPU_ONLINE(sysblk.pcpu)) { release_lock(&sysblk.cpulock[sysblk.pcpu]); logmsg( _("HHCPN160W CPU%4.4X not configured\n"), sysblk.pcpu); return 0; } regs = sysblk.regs[sysblk.pcpu]; disasm_stor (regs, cmdline+2); release_lock(&sysblk.cpulock[sysblk.pcpu]); return 0; } /*-------------------------------------------------------------------*/ /* v command - display or alter virtual storage */ /*-------------------------------------------------------------------*/ int v_cmd(int argc, char *argv[], char *cmdline) { REGS *regs; UNREFERENCED(argc); UNREFERENCED(argv); obtain_lock(&sysblk.cpulock[sysblk.pcpu]); if (!IS_CPU_ONLINE(sysblk.pcpu)) { release_lock(&sysblk.cpulock[sysblk.pcpu]); logmsg( _("HHCPN160W CPU%4.4X not configured\n"), sysblk.pcpu); return 0; } regs = sysblk.regs[sysblk.pcpu]; alter_display_virt (cmdline+1, regs); release_lock(&sysblk.cpulock[sysblk.pcpu]); return 0; } /*-------------------------------------------------------------------*/ /* tracing commands: t, t+, t-, t?, s, s+, s-, s?, b */ /*-------------------------------------------------------------------*/ int trace_cmd(int argc, char *argv[], char *cmdline) { int on = 0, off = 0, query = 0; int trace = 0; int rc; BYTE c[2]; U64 addr[2]; char range[256]; trace = cmdline[0] == 't'; if (strlen(cmdline) > 1) { on = cmdline[1] == '+' || (cmdline[0] == 'b' && cmdline[1] == ' '); off = cmdline[1] == '-'; query = cmdline[1] == '?'; } if (argc > 2 || (off && argc > 1) || (query && argc > 1)) { logmsg( _("HHCPN039E Invalid arguments\n") ); return -1; } /* Get address range */ if (argc == 2) { rc = sscanf(argv[1], "%"I64_FMT"x%c%"I64_FMT"x%c", &addr[0], &c[0], &addr[1], &c[1]); if (rc == 1) { c[0] = '-'; addr[1] = addr[0]; } else if (rc != 3 || (c[0] != '-' && c[0] != ':' && c[0] != '.')) { logmsg( _("HHCPN039E Invalid arguments\n") ); return -1; } if (c[0] == '.') addr[1] += addr[0]; if (trace) { sysblk.traceaddr[0] = addr[0]; sysblk.traceaddr[1] = addr[1]; } else { sysblk.stepaddr[0] = addr[0]; sysblk.stepaddr[1] = addr[1]; } } else c[0] = '-'; /* Set tracing/stepping bit on or off */ if (on || off) { OBTAIN_INTLOCK(NULL); if (trace) sysblk.insttrace = on; else sysblk.inststep = on; SET_IC_TRACE; RELEASE_INTLOCK(NULL); } /* Build range for message */ range[0] = '\0'; if (trace && (sysblk.traceaddr[0] != 0 || sysblk.traceaddr[1] != 0)) sprintf(range, "range %" I64_FMT "x%c%" I64_FMT "x", sysblk.traceaddr[0], c[0], c[0] != '.' ? sysblk.traceaddr[1] : sysblk.traceaddr[1] - sysblk.traceaddr[0]); else if (!trace && (sysblk.stepaddr[0] != 0 || sysblk.stepaddr[1] != 0)) sprintf(range, "range %" I64_FMT "x%c%" I64_FMT "x", sysblk.stepaddr[0], c[0], c[0] != '.' ? sysblk.stepaddr[1] : sysblk.stepaddr[1] - sysblk.stepaddr[0]); /* Determine if this trace is on or off for message */ on = (trace && sysblk.insttrace) || (!trace && sysblk.inststep); /* Display message */ logmsg(_("HHCPN040I Instruction %s %s %s\n"), cmdline[0] == 't' ? _("tracing") : cmdline[0] == 's' ? _("stepping") : _("break"), on ? _("on") : _("off"), range); return 0; } /*-------------------------------------------------------------------*/ /* i command - generate I/O attention interrupt for device */ /*-------------------------------------------------------------------*/ int i_cmd(int argc, char *argv[], char *cmdline) { REGS *regs; int rc = 0; U16 devnum; U16 lcss; DEVBLK* dev; UNREFERENCED(cmdline); if (argc < 2) { missing_devnum(); return -1; } rc=parse_single_devnum(argv[1],&lcss,&devnum); if (rc<0) { return -1; } if (!(dev = find_device_by_devnum (lcss, devnum))) { devnotfound_msg(lcss,devnum); return -1; } rc = device_attention (dev, CSW_ATTN); switch (rc) { case 0: logmsg(_("HHCPN045I Device %4.4X attention request raised\n"), devnum); break; case 1: logmsg(_("HHCPN046E Device %4.4X busy or interrupt pending\n"), devnum); break; case 2: logmsg(_("HHCPN047E Device %4.4X attention request rejected\n"), devnum); break; case 3: logmsg(_("HHCPN048E Device %4.4X subchannel not enabled\n"), devnum); break; } regs = sysblk.regs[sysblk.pcpu]; if (rc == 3 && IS_CPU_ONLINE(sysblk.pcpu) && CPUSTATE_STOPPED == regs->cpustate) logmsg( _("HHCPN049W Are you sure you didn't mean 'ipl %4.4X' " "instead?\n"), devnum ); return rc; } /*-------------------------------------------------------------------*/ /* ext command - generate external interrupt */ /*-------------------------------------------------------------------*/ int ext_cmd(int argc, char *argv[], char *cmdline) { UNREFERENCED(cmdline); UNREFERENCED(argc); UNREFERENCED(argv); OBTAIN_INTLOCK(NULL); ON_IC_INTKEY; logmsg( _("HHCPN050I Interrupt key depressed\n") ); /* Signal waiting CPUs that an interrupt is pending */ WAKEUP_CPUS_MASK (sysblk.waiting_mask); RELEASE_INTLOCK(NULL); return 0; } /*-------------------------------------------------------------------*/ /* pgmprdos config command */ /*-------------------------------------------------------------------*/ int pgmprdos_cmd(int argc, char *argv[], char *cmdline) { UNREFERENCED(cmdline); /* Parse program product OS allowed */ if (argc > 1) { if (strcasecmp (argv[1], "LICENSED") == 0) { losc_set(PGM_PRD_OS_LICENSED); } /* Handle silly British spelling. */ else if (strcasecmp (argv[1], "LICENCED") == 0) { losc_set(PGM_PRD_OS_LICENSED); } else if (strcasecmp (argv[1], "RESTRICTED") == 0) { losc_set(PGM_PRD_OS_RESTRICTED); } else { logmsg( _("HHCCF028S Invalid program product OS license setting %s\n"), argv[1]); } } else return -1; return 0; } /*-------------------------------------------------------------------*/ /* diag8cmd command */ /*-------------------------------------------------------------------*/ int diag8_cmd(int argc, char *argv[], char *cmdline) { int i; UNREFERENCED(cmdline); /* Parse diag8cmd operand */ if(argc > 1) for(i = 1; i < argc; i++) { if(strcasecmp(argv[i],"echo")==0) sysblk.diag8cmd |= DIAG8CMD_ECHO; else if(strcasecmp(argv[i],"noecho")==0) sysblk.diag8cmd &= ~DIAG8CMD_ECHO; else if(strcasecmp(argv[i],"enable")==0) sysblk.diag8cmd |= DIAG8CMD_ENABLE; else if(strcasecmp(argv[i],"disable")==0) // disable implies no echo sysblk.diag8cmd &= ~(DIAG8CMD_ENABLE | DIAG8CMD_ECHO); else { logmsg(_("HHCCF052S DIAG8CMD invalid option: %s\n"),argv[i]); return -1; } } else logmsg(_("HHCCF054S DIAG8CMD: %sable, %secho\n"), (sysblk.diag8cmd & DIAG8CMD_ENABLE) ? "en" : "dis", (sysblk.diag8cmd & DIAG8CMD_ECHO) ? "" : "no"); return 0; } /*-------------------------------------------------------------------*/ /* shcmdopt command */ /*-------------------------------------------------------------------*/ int shcmdopt_cmd(int argc, char *argv[], char *cmdline) { int i; UNREFERENCED(cmdline); /* Parse SHCMDOPT operand */ if (argc > 1) for(i = 1; i < argc; i++) { if (strcasecmp (argv[i], "enable") == 0) sysblk.shcmdopt &= ~SHCMDOPT_DISABLE; else if (strcasecmp (argv[i], "diag8") == 0) sysblk.shcmdopt &= ~SHCMDOPT_NODIAG8; else if (strcasecmp (argv[i], "disable") == 0) sysblk.shcmdopt |= SHCMDOPT_DISABLE; else if (strcasecmp (argv[i], "nodiag8") == 0) sysblk.shcmdopt |= SHCMDOPT_NODIAG8; else { logmsg(_("HHCCF053I SHCMDOPT invalid option: %s\n"), argv[i]); return -1; } } else logmsg(_("HHCCF053I SCHMDOPT %sabled%s\n"), (sysblk.shcmdopt&SHCMDOPT_DISABLE)?"Dis":"En", (sysblk.shcmdopt&SHCMDOPT_NODIAG8)?" NoDiag8":""); return 0; } /*-------------------------------------------------------------------*/ /* legacysenseid command */ /*-------------------------------------------------------------------*/ int lsid_cmd(int argc, char *argv[], char *cmdline) { UNREFERENCED(cmdline); /* Parse Legacy SenseID option */ if (argc > 1) { if(strcasecmp(argv[1],"enable") == 0) sysblk.legacysenseid = 1; else if(strcasecmp(argv[1],"on") == 0) sysblk.legacysenseid = 1; else if(strcasecmp(argv[1],"disable") == 0) sysblk.legacysenseid = 0; else if(strcasecmp(argv[1],"off") == 0) sysblk.legacysenseid = 0; else { logmsg(_("HHCxxnnnE Legacysenseid invalid option: %s\n"), argv[1]); return -1; } } else logmsg(_("HHCxxnnnE Legacysenseid %sabled\n"), sysblk.legacysenseid?"En":"Dis"); return 0; } /*-------------------------------------------------------------------*/ /* codepage xxxxxxxx command */ /*-------------------------------------------------------------------*/ int codepage_cmd(int argc, char *argv[], char *cmdline) { UNREFERENCED(cmdline); /* Update LPAR name if operand is specified */ if (argc > 1) set_codepage(argv[1]); else { logmsg( _("Usage %s \n"),argv[0]); return -1; } return 0; } #if defined(OPTION_SET_STSI_INFO) /*-------------------------------------------------------------------*/ /* model config statement */ /* operands: hardware_model [capacity_model [perm_model temp_model]] */ /*-------------------------------------------------------------------*/ int stsi_model_cmd(int argc, char *argv[], char *cmdline) { UNREFERENCED(cmdline); /* Update model name if operand is specified */ if (argc > 1) set_model(argc, argv[1], argv[2], argv[3], argv[4]); else { logmsg( _("HHCxxnnnE MODEL: no model code\n")); return -1; } return 0; } /*-------------------------------------------------------------------*/ /* plant config statement */ /*-------------------------------------------------------------------*/ int stsi_plant_cmd(int argc, char *argv[], char *cmdline) { UNREFERENCED(cmdline); /* Update model name if operand is specified */ if (argc > 1) set_plant(argv[1]); else { logmsg( _("HHCxxnnnE PLANT: no plant code\n")); return -1; } return 0; } /*-------------------------------------------------------------------*/ /* manufacturer config statement */ /*-------------------------------------------------------------------*/ int stsi_mfct_cmd(int argc, char *argv[], char *cmdline) { UNREFERENCED(cmdline); /* Update model name if operand is specified */ if (argc > 1) set_manufacturer(argv[1]); else { logmsg( _("HHCxxnnnE MANUFACTURER: no manufacturer code\n")); return -1; } return 0; } #endif /* defined(OPTION_SET_STSI_INFO) */ /*-------------------------------------------------------------------*/ /* lparname - set or display LPAR name */ /*-------------------------------------------------------------------*/ int lparname_cmd(int argc, char *argv[], char *cmdline) { UNREFERENCED(cmdline); /* Update LPAR name if operand is specified */ if (argc > 1) set_lparname(argv[1]); else logmsg( _("HHCPN056I LPAR name = %s\n"),str_lparname()); return 0; } /*-------------------------------------------------------------------*/ /* lparnum command - set or display LPAR identification number */ /*-------------------------------------------------------------------*/ int lparnum_cmd(int argc, char *argv[], char *cmdline) { U16 id; BYTE c; UNREFERENCED(cmdline); /* Update LPAR identification number if operand is specified */ if (argc > 1) { if (argv[1] != NULL && strlen(argv[1]) >= 1 && strlen(argv[1]) <= 2 && sscanf(argv[1], "%hx%c", &id, &c) == 1) { sysblk.lparnum = id; sysblk.lparnuml = strlen(argv[1]); } else { logmsg( _("HHCPN058E LPARNUM must be one or two hex digits\n")); return -1; } } else logmsg( _("HHCPN060I LPAR number = %"I16_FMT"X\n"), sysblk.lparnum); return 0; } /*-------------------------------------------------------------------*/ /* loadparm - set or display IPL parameter */ /*-------------------------------------------------------------------*/ int loadparm_cmd(int argc, char *argv[], char *cmdline) { UNREFERENCED(cmdline); /* Update IPL parameter if operand is specified */ if (argc > 1) set_loadparm(argv[1]); else logmsg( _("HHCPN051I LOADPARM=%s\n"),str_loadparm()); return 0; } /*-------------------------------------------------------------------*/ /* system reset/system reset clear function */ /*-------------------------------------------------------------------*/ static int reset_cmd(int ac,char *av[],char *cmdline,int clear) { int i; UNREFERENCED(ac); UNREFERENCED(av); UNREFERENCED(cmdline); OBTAIN_INTLOCK(NULL); for (i = 0; i < MAX_CPU; i++) if (IS_CPU_ONLINE(i) && sysblk.regs[i]->cpustate != CPUSTATE_STOPPED) { RELEASE_INTLOCK(NULL); logmsg( _("HHCPN053E System reset/clear rejected: All CPU's must be stopped\n") ); return -1; } system_reset (sysblk.pcpu, clear); RELEASE_INTLOCK(NULL); return 0; } /*-------------------------------------------------------------------*/ /* system reset command */ /*-------------------------------------------------------------------*/ int sysr_cmd(int ac,char *av[],char *cmdline) { return(reset_cmd(ac,av,cmdline,0)); } /*-------------------------------------------------------------------*/ /* system reset clear command */ /*-------------------------------------------------------------------*/ int sysc_cmd(int ac,char *av[],char *cmdline) { return(reset_cmd(ac,av,cmdline,1)); } /*-------------------------------------------------------------------*/ /* ipl function */ /*-------------------------------------------------------------------*/ int ipl_cmd2(int argc, char *argv[], char *cmdline, int clear) { BYTE c; /* Character work area */ int rc; /* Return code */ int i; #if defined(OPTION_IPLPARM) int j; size_t maxb; #endif U16 lcss; U16 devnum; char *cdev, *clcss; /* Check that target processor type allows IPL */ if (sysblk.ptyp[sysblk.pcpu] == SCCB_PTYP_IFA || sysblk.ptyp[sysblk.pcpu] == SCCB_PTYP_SUP) { logmsg(_("HHCPN052E Target CPU %d type %d" " does not allow ipl nor restart\n"), sysblk.pcpu, sysblk.ptyp[sysblk.pcpu]); return -1; } /* Check the parameters of the IPL command */ if (argc < 2) { missing_devnum(); return -1; } #if defined(OPTION_IPLPARM) #define MAXPARMSTRING sizeof(sysblk.iplparmstring) sysblk.haveiplparm=0; maxb=0; if(argc>2) { if(strcasecmp(argv[2],"parm")==0) { memset(sysblk.iplparmstring,0,MAXPARMSTRING); sysblk.haveiplparm=1; for(i=3;icpustate != CPUSTATE_STOPPED) { RELEASE_INTLOCK(NULL); logmsg( _("HHCPN053E ipl rejected: All CPU's must be stopped\n") ); return -1; } /* The ipl device number might be in format lcss:devnum */ if((cdev = strchr(argv[1],':'))) { clcss = argv[1]; cdev++; } else { clcss = NULL; cdev = argv[1]; } /* If the ipl device is not a valid hex number we assume */ /* This is a load from the service processor */ if (sscanf(cdev, "%hx%c", &devnum, &c) != 1) rc = load_hmc(strtok(cmdline+3+clear," \t"), sysblk.pcpu, clear); else { *--cdev = '\0'; if(clcss) { if (sscanf(clcss, "%hd%c", &lcss, &c) != 1) { logmsg( _("HHCPN059E LCSS id %s is invalid\n"), clcss ); return -1; } } else lcss = 0; rc = load_ipl (lcss, devnum, sysblk.pcpu, clear); } RELEASE_INTLOCK(NULL); return rc; } /*-------------------------------------------------------------------*/ /* ipl command */ /*-------------------------------------------------------------------*/ int ipl_cmd(int argc, char *argv[], char *cmdline) { return(ipl_cmd2(argc,argv,cmdline,0)); } /*-------------------------------------------------------------------*/ /* ipl clear command */ /*-------------------------------------------------------------------*/ int iplc_cmd(int argc, char *argv[], char *cmdline) { return(ipl_cmd2(argc,argv,cmdline,1)); } /*-------------------------------------------------------------------*/ /* cpu command - define target cpu for panel display and commands */ /*-------------------------------------------------------------------*/ int cpu_cmd(int argc, char *argv[], char *cmdline) { BYTE c; /* Character work area */ int cpu; UNREFERENCED(cmdline); if (argc < 2) { logmsg( _("HHCPN054E Missing argument\n") ); return -1; } if (sscanf(argv[1], "%x%c", &cpu, &c) != 1 || cpu < 0 || cpu >= MAX_CPU) { logmsg( _("HHCPN055E Target CPU %s is invalid\n"), argv[1] ); return -1; } sysblk.dummyregs.cpuad = cpu; sysblk.pcpu = cpu; return 0; } #if defined(FISH_HANG) /*-------------------------------------------------------------------*/ /* FishHangReport - verify/debug proper Hercules LOCK handling... */ /*-------------------------------------------------------------------*/ int FishHangReport_cmd(int argc, char *argv[], char *cmdline) { UNREFERENCED(cmdline); UNREFERENCED(argc); UNREFERENCED(argv); FishHangReport(); #if defined(OPTION_FISHIO) PrintAllDEVTHREADPARMSs(); #endif return 0; } #endif // defined(FISH_HANG) static int SortDevBlkPtrsAscendingByDevnum(const void* pDevBlkPtr1, const void* pDevBlkPtr2) { return ((int)((*(DEVBLK**)pDevBlkPtr1)->devnum) - (int)((*(DEVBLK**)pDevBlkPtr2)->devnum)); } /*-------------------------------------------------------------------*/ /* devlist command - list devices */ /*-------------------------------------------------------------------*/ int devlist_cmd(int argc, char *argv[], char *cmdline) { DEVBLK* dev; char* devclass; char devnam[1024]; DEVBLK** pDevBlkPtr; DEVBLK** orig_pDevBlkPtrs; size_t nDevCount, i; int bTooMany = 0; U16 lcss; U16 ssid=0; U16 devnum; int single_devnum = 0; UNREFERENCED(cmdline); UNREFERENCED(argc); UNREFERENCED(argv); if (argc >= 2) { single_devnum = 1; if (parse_single_devnum(argv[1], &lcss, &devnum) < 0) { // (error message already issued) return -1; } if (!(dev = find_device_by_devnum (lcss, devnum))) { devnotfound_msg(lcss, devnum); return -1; } ssid = LCSS_TO_SSID(lcss); } // Since we wish to display the list of devices in ascending device // number order, we build our own private a sorted array of DEVBLK // pointers and use that instead to make the devlist command wholly // immune from the actual order/sequence of the actual DEVBLK chain. // Note too that there is no lock to lock access to ALL device blocks // (even though there really SHOULD be), only one to lock an individual // DEVBLK (which doesn't do us much good here). if (!(orig_pDevBlkPtrs = malloc(sizeof(DEVBLK*) * MAX_DEVLIST_DEVICES))) { logmsg( _("HHCPN146E Work buffer malloc failed: %s\n"), strerror(errno) ); return -1; } nDevCount = 0; pDevBlkPtr = orig_pDevBlkPtrs; for (dev = sysblk.firstdev; dev && nDevCount <= MAX_DEVLIST_DEVICES; dev = dev->nextdev) { if (dev->allocated) // (valid device?) { if (single_devnum && (dev->ssid != ssid || dev->devnum != devnum)) continue; if (nDevCount < MAX_DEVLIST_DEVICES) { *pDevBlkPtr = dev; // (save ptr to DEVBLK) nDevCount++; // (count array entries) pDevBlkPtr++; // (bump to next entry) if (single_devnum) break; } else { bTooMany = 1; // (no more room) break; // (no more room) } } } ASSERT(nDevCount <= MAX_DEVLIST_DEVICES); // (sanity check) // Sort the DEVBLK pointers into ascending sequence by device number. qsort(orig_pDevBlkPtrs, nDevCount, sizeof(DEVBLK*), SortDevBlkPtrsAscendingByDevnum); // Now use our sorted array of DEVBLK pointers // to display our sorted list of devices... for (i = nDevCount, pDevBlkPtr = orig_pDevBlkPtrs; i; --i, pDevBlkPtr++) { dev = *pDevBlkPtr; // --> DEVBLK /* Call device handler's query definition function */ #if defined(OPTION_SCSI_TAPE) if (TAPEDEVT_SCSITAPE == dev->tapedevt) try_scsi_refresh( dev ); // (see comments in function) #endif dev->hnd->query( dev, &devclass, sizeof(devnam), devnam ); /* Display the device definition and status */ logmsg( "%d:%4.4X %4.4X %s %s%s%s\n", SSID_TO_LCSS(dev->ssid), dev->devnum, dev->devtype, devnam, (dev->fd > 2 ? _("open ") : ""), (dev->busy ? _("busy ") : ""), (IOPENDING(dev) ? _("pending ") : "") ); if (dev->bs) { char *clientip, *clientname; get_connected_client(dev,&clientip,&clientname); if (clientip) { logmsg( _(" (client %s (%s) connected)\n"), clientip, clientname ); } else { logmsg( _(" (no one currently connected)\n") ); } if (clientip) free(clientip); if (clientname) free(clientname); } } free ( orig_pDevBlkPtrs ); if (bTooMany) { logmsg( _("HHCPN147W Warning: not all devices shown (max %d)\n"), MAX_DEVLIST_DEVICES); return -1; // (treat as error) } return 0; } /*-------------------------------------------------------------------*/ /* qd command - query dasd */ /*-------------------------------------------------------------------*/ int qd_cmd(int argc, char *argv[], char *cmdline) { DEVBLK* dev; DEVBLK** pDevBlkPtr; DEVBLK** orig_pDevBlkPtrs; size_t nDevCount, i, j, num; int bTooMany = 0; U16 lcss; U16 ssid=0; U16 devnum; int single_devnum = 0; BYTE iobuf[256]; BYTE cbuf[17]; UNREFERENCED(cmdline); if (argc >= 2) { single_devnum = 1; if (parse_single_devnum(argv[1], &lcss, &devnum) < 0) return -1; if (!(dev = find_device_by_devnum (lcss, devnum))) { devnotfound_msg(lcss, devnum); return -1; } ssid = LCSS_TO_SSID(lcss); } if (!(orig_pDevBlkPtrs = malloc(sizeof(DEVBLK*) * MAX_DEVLIST_DEVICES))) { logmsg( _("HHCPN146E Work buffer malloc failed: %s\n"), strerror(errno) ); return -1; } nDevCount = 0; pDevBlkPtr = orig_pDevBlkPtrs; for (dev = sysblk.firstdev; dev && nDevCount <= MAX_DEVLIST_DEVICES; dev = dev->nextdev) { if (dev->allocated) // (valid device?) { if (single_devnum && (dev->ssid != ssid || dev->devnum != devnum)) continue; if (!dev->ckdcyls) continue; if (nDevCount < MAX_DEVLIST_DEVICES) { *pDevBlkPtr = dev; // (save ptr to DEVBLK) nDevCount++; // (count array entries) pDevBlkPtr++; // (bump to next entry) if (single_devnum) break; } else { bTooMany = 1; // (no more room) break; // (no more room) } } } // Sort the DEVBLK pointers into ascending sequence by device number. qsort(orig_pDevBlkPtrs, nDevCount, sizeof(DEVBLK*), SortDevBlkPtrsAscendingByDevnum); // Now use our sorted array of DEVBLK pointers // to display our sorted list of devices... for (i = nDevCount, pDevBlkPtr = orig_pDevBlkPtrs; i; --i, pDevBlkPtr++) { dev = *pDevBlkPtr; // --> DEVBLK /* Display sense-id */ for (j = 0; j < dev->numdevid; j++) { if (j == 0) logmsg("%4.4x SNSID 00 ",dev->devnum); else if (j%16 == 0) logmsg("\n %2.2x ", j); if (j%4 == 0) logmsg(" "); logmsg("%2.2x", dev->devid[j]); } logmsg("\n"); /* Display device characteristics */ for (j = 0; j < dev->numdevchar; j++) { if (j == 0) logmsg("%4.4x RDC 00 ",dev->devnum); else if (j%16 == 0) logmsg("\n %2.2x ", j); if (j%4 == 0) logmsg(" "); logmsg("%2.2x", dev->devchar[j]); } logmsg("\n"); /* Display configuration data */ dasd_build_ckd_config_data (dev, iobuf, 256); cbuf[16]=0; for (j = 0; j < 256; j++) { if (j == 0) logmsg("%4.4x RCD 00 ",dev->devnum); else if (j%16 == 0) logmsg(" |%s|\n %2.2x ", cbuf, j); if (j%4 == 0) logmsg(" "); logmsg("%2.2x", iobuf[j]); cbuf[j%16] = isprint(guest_to_host(iobuf[j])) ? guest_to_host(iobuf[j]) : '.'; } logmsg(" |%s|\n", cbuf); /* Display subsystem status */ num = dasd_build_ckd_subsys_status(dev, iobuf, 44); for (j = 0; j < num; j++) { if (j == 0) logmsg("%4.4x SNSS 00 ",dev->devnum); else if (j%16 == 0) logmsg("\n %2.2x ", j); if (j%4 == 0) logmsg(" "); logmsg("%2.2x", iobuf[j]); } logmsg("\n"); } free ( orig_pDevBlkPtrs ); if (bTooMany) { logmsg( _("HHCPN147W Warning: not all devices shown (max %d)\n"), MAX_DEVLIST_DEVICES); return -1; // (treat as error) } return 0; #undef myssid #undef CONFIG_DATA_SIZE } /*-------------------------------------------------------------------*/ /* attach command - configure a device */ /*-------------------------------------------------------------------*/ int attach_cmd(int argc, char *argv[], char *cmdline) { UNREFERENCED(cmdline); if (argc < 3) { logmsg( _("HHCPN057E Missing argument(s)\n") ); return -1; } return parse_and_attach_devices(argv[1],argv[2],argc-3,&argv[3]); #if 0 if((cdev = strchr(argv[1],':'))) { clcss = argv[1]; *cdev++ = '\0'; } else { clcss = NULL; cdev = argv[1]; } if (sscanf(cdev, "%hx%c", &devnum, &c) != 1) { logmsg( _("HHCPN059E Device number %s is invalid\n"), cdev ); return -1; } if(clcss) { if (sscanf(clcss, "%hd%c", &lcss, &c) != 1) { logmsg( _("HHCPN059E LCSS id %s is invalid\n"), clcss ); return -1; } } else lcss = 0; #if 0 /* JAP - Breaks the whole idea behind devtype.c */ if (sscanf(argv[2], "%hx%c", &dummy_devtype, &c) != 1) { logmsg( _("Device type %s is invalid\n"), argv[2] ); return -1; } #endif return attach_device (lcss, devnum, argv[2], argc-3, &argv[3]); #endif } /*-------------------------------------------------------------------*/ /* detach command - remove device */ /*-------------------------------------------------------------------*/ int detach_cmd(int argc, char *argv[], char *cmdline) { U16 devnum; U16 lcss; int rc; UNREFERENCED(cmdline); if (argc < 2) { missing_devnum(); return -1; } rc=parse_single_devnum(argv[1],&lcss,&devnum); if (rc<0) { return -1; } return detach_device (lcss, devnum); } /*-------------------------------------------------------------------*/ /* define command - rename a device */ /*-------------------------------------------------------------------*/ int define_cmd(int argc, char *argv[], char *cmdline) { U16 devnum, newdevn; U16 lcss,newlcss; int rc; UNREFERENCED(cmdline); if (argc < 3) { logmsg( _("HHCPN062E Missing argument(s)\n") ); return -1; } rc=parse_single_devnum(argv[1],&lcss,&devnum); if (rc<0) { return -1; } rc=parse_single_devnum(argv[2],&newlcss,&newdevn); if (rc<0) { return -1; } if(lcss!=newlcss) { logmsg(_("HHCPN182E Device numbers can only be redefined within the same Logical channel subsystem\n")); return -1; } return define_device (lcss, devnum, newdevn); } /*-------------------------------------------------------------------*/ /* pgmtrace command - trace program interrupts */ /*-------------------------------------------------------------------*/ int pgmtrace_cmd(int argc, char *argv[], char *cmdline) { int abs_rupt_num, rupt_num; BYTE c; /* Character work area */ UNREFERENCED(cmdline); if (argc < 2) { if (sysblk.pgminttr == 0xFFFFFFFFFFFFFFFFULL) logmsg("pgmtrace == all\n"); else if (sysblk.pgminttr == 0) logmsg("pgmtrace == none\n"); else { char flags[64+1]; int i; for (i=0; i < 64; i++) flags[i] = (sysblk.pgminttr & (1ULL << i)) ? ' ' : '*'; flags[64] = 0; logmsg ( " * = Tracing suppressed; otherwise tracing enabled\n" " 0000000000000001111111111111111222222222222222233333333333333334\n" " 123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0\n" " %s\n" ,flags ); } return 0; } if (sscanf(argv[1], "%x%c", &rupt_num, &c) != 1) { logmsg( _("HHCPN066E Program interrupt number %s is invalid\n"), argv[1] ); return -1; } if ((abs_rupt_num = abs(rupt_num)) < 1 || abs_rupt_num > 0x40) { logmsg( _("HHCPN067E Program interrupt number out of range (%4.4X)\n"), abs_rupt_num ); return -1; } /* Add to, or remove interruption code from mask */ if (rupt_num < 0) sysblk.pgminttr &= ~((U64)1 << (abs_rupt_num - 1)); else sysblk.pgminttr |= ((U64)1 << (abs_rupt_num - 1)); return 0; } /*-------------------------------------------------------------------*/ /* ostailor command - trace program interrupts */ /*-------------------------------------------------------------------*/ int ostailor_cmd(int argc, char *argv[], char *cmdline) { UNREFERENCED(cmdline); if (argc < 2) { char* sostailor = "(custom)"; if (sysblk.pgminttr == OS_OS390 ) sostailor = "OS/390"; if (sysblk.pgminttr == OS_ZOS ) sostailor = "z/OS"; if (sysblk.pgminttr == OS_VSE ) sostailor = "VSE"; if (sysblk.pgminttr == OS_VM ) sostailor = "VM"; if (sysblk.pgminttr == OS_LINUX ) sostailor = "LINUX"; if (sysblk.pgminttr == OS_OPENSOLARIS ) sostailor = "OpenSolaris"; if (sysblk.pgminttr == 0xFFFFFFFFFFFFFFFFULL) sostailor = "NULL"; if (sysblk.pgminttr == 0 ) sostailor = "QUIET"; logmsg( _("OSTAILOR %s\n"),sostailor); return 0; } if (strcasecmp (argv[1], "OS/390") == 0) { sysblk.pgminttr = OS_OS390; return 0; } if (strcasecmp (argv[1], "+OS/390") == 0) { sysblk.pgminttr &= OS_OS390; return 0; } if (strcasecmp (argv[1], "-OS/390") == 0) { sysblk.pgminttr |= ~OS_OS390; return 0; } if (strcasecmp (argv[1], "Z/OS") == 0) { sysblk.pgminttr = OS_ZOS; return 0; } if (strcasecmp (argv[1], "+Z/OS") == 0) { sysblk.pgminttr &= OS_ZOS; return 0; } if (strcasecmp (argv[1], "-Z/OS") == 0) { sysblk.pgminttr |= ~OS_ZOS; return 0; } if (strcasecmp (argv[1], "VSE") == 0) { sysblk.pgminttr = OS_VSE; return 0; } if (strcasecmp (argv[1], "+VSE") == 0) { sysblk.pgminttr &= OS_VSE; return 0; } if (strcasecmp (argv[1], "-VSE") == 0) { sysblk.pgminttr |= ~OS_VSE; return 0; } if (strcasecmp (argv[1], "VM") == 0) { sysblk.pgminttr = OS_VM; return 0; } if (strcasecmp (argv[1], "+VM") == 0) { sysblk.pgminttr &= OS_VM; return 0; } if (strcasecmp (argv[1], "-VM") == 0) { sysblk.pgminttr |= ~OS_VM; return 0; } if (strcasecmp (argv[1], "LINUX") == 0) { sysblk.pgminttr = OS_LINUX; return 0; } if (strcasecmp (argv[1], "+LINUX") == 0) { sysblk.pgminttr &= OS_LINUX; return 0; } if (strcasecmp (argv[1], "-LINUX") == 0) { sysblk.pgminttr |= ~OS_LINUX; return 0; } if (strcasecmp (argv[1], "OpenSolaris") == 0) { sysblk.pgminttr = OS_OPENSOLARIS; return 0; } if (strcasecmp (argv[1], "+OpenSolaris") == 0) { sysblk.pgminttr &= OS_OPENSOLARIS; return 0; } if (strcasecmp (argv[1], "-OpenSolaris") == 0) { sysblk.pgminttr |= ~OS_OPENSOLARIS; return 0; } if (strcasecmp (argv[1], "NULL") == 0) { sysblk.pgminttr = 0xFFFFFFFFFFFFFFFFULL; return 0; } if (strcasecmp (argv[1], "QUIET") == 0) { sysblk.pgminttr = 0; return 0; } logmsg( _("Unknown OS tailor specification %s\n"), argv[1] ); return -1; } /*-------------------------------------------------------------------*/ /* k command - print out cckd internal trace */ /*-------------------------------------------------------------------*/ int k_cmd(int argc, char *argv[], char *cmdline) { UNREFERENCED(cmdline); UNREFERENCED(argc); UNREFERENCED(argv); cckd_print_itrace (); return 0; } /*-------------------------------------------------------------------*/ /* ds - display subchannel */ /*-------------------------------------------------------------------*/ int ds_cmd(int argc, char *argv[], char *cmdline) { DEVBLK* dev; U16 devnum; U16 lcss; int rc; UNREFERENCED(cmdline); if (argc < 2) { missing_devnum(); return -1; } rc=parse_single_devnum(argv[1],&lcss,&devnum); if (rc<0) { return -1; } if (!(dev = find_device_by_devnum (lcss,devnum))) { devnotfound_msg(lcss,devnum); return -1; } display_subchannel (dev); return 0; } /*-------------------------------------------------------------------*/ /* syncio command - list syncio devices statistics */ /*-------------------------------------------------------------------*/ int syncio_cmd(int argc, char *argv[], char *cmdline) { DEVBLK* dev; U64 syncios = 0, asyncios = 0; int found = 0; UNREFERENCED(cmdline); UNREFERENCED(argc); UNREFERENCED(argv); for (dev = sysblk.firstdev; dev != NULL; dev = dev->nextdev) { if (!dev->syncio) continue; found = 1; logmsg( _("HHCPN072I %4.4X synchronous: %12" I64_FMT "d " "asynchronous: %12" I64_FMT "d\n"), dev->devnum, (long long)dev->syncios, (long long)dev->asyncios ); syncios += dev->syncios; asyncios += dev->asyncios; } if (!found) logmsg( _("HHCPN073I No synchronous I/O devices found\n") ); else logmsg( _("HHCPN074I TOTAL synchronous: %12" I64_FMT "d " "asynchronous: %12" I64_FMT "d %3" I64_FMT "d%%\n"), (long long)syncios, (long long)asyncios, (long long)((syncios * 100) / (syncios + asyncios + 1)) ); return 0; } #if !defined(OPTION_FISHIO) void *device_thread(void *arg); #endif /* !defined(OPTION_FISHIO) */ /*-------------------------------------------------------------------*/ /* devtmax command - display or set max device threads */ /*-------------------------------------------------------------------*/ int devtmax_cmd(int argc, char *argv[], char *cmdline) { int devtmax = -2; #if defined(OPTION_FISHIO) UNREFERENCED(cmdline); /* Note: no need to lock scheduler vars since WE are * the only one that updates "ios_devtmax" (the scheduler * just references it) and we only display (but not update) * all the other variables. */ if (argc > 1) { sscanf(argv[1], "%d", &devtmax); if (devtmax >= -1) ios_devtmax = devtmax; else { logmsg( _("HHCPN075E Invalid max device threads value " "(must be -1 to n)\n") ); return -1; } TrimDeviceThreads(); /* (enforce newly defined threshold) */ } else logmsg( _("HHCPN076I Max device threads: %d, current: %d, most: %d, " "waiting: %d, max exceeded: %d\n"), ios_devtmax, ios_devtnbr, ios_devthwm, (int)ios_devtwait, ios_devtunavail ); #else /* !defined(OPTION_FISHIO) */ TID tid; UNREFERENCED(cmdline); if (argc > 1) { sscanf(argv[1], "%d", &devtmax); if (devtmax >= -1) sysblk.devtmax = devtmax; else { logmsg( _("HHCPN077E Invalid max device threads value " "(must be -1 to n)\n") ); return -1; } /* Create a new device thread if the I/O queue is not NULL and more threads can be created */ /* the IOQ lock is obtained in order to write to sysblk.devtwait */ obtain_lock(&sysblk.ioqlock); if (sysblk.ioq && (!sysblk.devtmax || sysblk.devtnbr < sysblk.devtmax)) create_thread(&tid, DETACHED, device_thread, NULL, "idle device thread"); /* Wakeup threads in case they need to terminate */ sysblk.devtwait=0; broadcast_condition (&sysblk.ioqcond); release_lock(&sysblk.ioqlock); } else logmsg( _("HHCPN078E Max device threads %d current %d most %d " "waiting %d total I/Os queued %d\n"), sysblk.devtmax, sysblk.devtnbr, sysblk.devthwm, sysblk.devtwait, sysblk.devtunavail ); #endif /* defined(OPTION_FISHIO) */ return 0; } /*-------------------------------------------------------------------*/ /* sf commands - shadow file add/remove/set/compress/display */ /*-------------------------------------------------------------------*/ int ShadowFile_cmd(int argc, char *argv[], char *cmdline) { char action; /* Action character `+-cd' */ char *devascii; /* -> Device name */ DEVBLK *dev; /* -> Device block */ U16 devnum; /* Device number */ U16 lcss; /* Logical CSS */ int flag = 1; /* sf- flag (default merge) */ int level = 2; /* sfk level (default 2) */ TID tid; /* sf command thread id */ char c; /* work for sscan */ UNREFERENCED(cmdline); if (strlen(argv[0]) < 3 || strchr ("+-cdk", argv[0][2]) == NULL) { logmsg( _("HHCPN091E Command must be 'sf+', 'sf-', " "'sfc', 'sfk' or 'sfd'\n") ); return -1; } action = argv[0][2]; /* * device name either follows the action character or is the * next operand */ if (strlen(argv[0]) > 3) devascii = argv[0] + 3; else { argv++; argc--; if (argc < 0 || (devascii = argv[0]) == NULL) { missing_devnum(); return -1; } } /* device name can be `*' meaning all cckd devices */ if (strcmp (devascii, "*") == 0) { for (dev=sysblk.firstdev; dev && !dev->cckd_ext; dev=dev->nextdev); /* nothing */ if (!dev) { logmsg( _("HHCPN081E No cckd devices found\n") ); return -1; } dev = NULL; } else { if (parse_single_devnum(devascii,&lcss,&devnum) < 0) return -1; if ((dev = find_device_by_devnum (lcss,devnum)) == NULL) return devnotfound_msg(lcss,devnum); if (dev->cckd_ext == NULL) { logmsg( _("HHCPN084E Device number %d:%4.4X " "is not a cckd device\n"), lcss, devnum ); return -1; } } /* For `sf-' the operand can be `nomerge', `merge' or `force' */ if (action == '-' && argc > 1) { if (strcmp(argv[1], "nomerge") == 0) flag = 0; else if (strcmp(argv[1], "merge") == 0) flag = 1; else if (strcmp(argv[1], "force") == 0) flag = 2; else { logmsg( _("HHCPN087E Operand must be " "`merge', `nomerge' or `force'\n") ); return -1; } argv++; argc--; } /* For `sfk' the operand is an integer -1 .. 4 */ if (action == 'k' && argc > 1) { if (sscanf(argv[1], "%d%c", &level, &c) != 1 || level < -1 || level > 4) { logmsg( _("HHCPN087E Operand must be a number -1 .. 4\n")); return -1; } argv++; argc--; } /* No other operands allowed */ if (argc > 1) { logmsg( _("HHCPN089E Unexpected operand: %s\n"), argv[1] ); return -1; } /* Set sf- flags in either cckdblk or the cckd extension */ if (action == '-') { if (dev) { CCKDDASD_EXT *cckd = dev->cckd_ext; cckd->sfmerge = flag == 1; cckd->sfforce = flag == 2; } else { cckdblk.sfmerge = flag == 1; cckdblk.sfforce = flag == 2; } } /* Set sfk level in either cckdblk or the cckd extension */ else if (action == 'k') { if (dev) { CCKDDASD_EXT *cckd = dev->cckd_ext; cckd->sflevel = level; } else cckdblk.sflevel = level; } /* Process the command */ switch (action) { case '+': if (create_thread(&tid, DETACHED, cckd_sf_add, dev, "sf+ command")) cckd_sf_add(dev); break; case '-': if (create_thread(&tid, DETACHED, cckd_sf_remove, dev, "sf- command")) cckd_sf_remove(dev); break; case 'c': if (create_thread(&tid, DETACHED, cckd_sf_comp, dev, "sfc command")) cckd_sf_comp(dev); break; case 'd': if (create_thread(&tid, DETACHED, cckd_sf_stats, dev, "sfd command")) cckd_sf_stats(dev); break; case 'k': if (create_thread(&tid, DETACHED, cckd_sf_chk, dev, "sfk command")) cckd_sf_chk(dev); break; } return 0; } /*-------------------------------------------------------------------*/ /* mounted_tape_reinit statement */ /*-------------------------------------------------------------------*/ int mnttapri_cmd(int argc, char *argv[], char *cmdline) { UNREFERENCED(cmdline); if(argc > 1) { if ( !strcasecmp( argv[1], "disallow" ) ) sysblk.nomountedtapereinit = 1; else if ( !strcasecmp( argv[1], "allow" ) ) sysblk.nomountedtapereinit = 0; else { logmsg( _("HHCCF052S %s: %s invalid argument\n"),argv[0],argv[1]); return -1; } } else logmsg( _("Tape mount reinit %sallowed\n"),sysblk.nomountedtapereinit?"dis":""); return 0; } #if defined( OPTION_SCSI_TAPE ) /*-------------------------------------------------------------------*/ /* auto_scsi_mount statement */ /*-------------------------------------------------------------------*/ int ascsimnt_cmd(int argc, char *argv[], char *cmdline) { UNREFERENCED(cmdline); if(argc > 1) { if ( !strcasecmp( argv[1], "no" ) ) sysblk.auto_scsi_mount_secs = 0; else if ( !strcasecmp( argv[1], "yes" ) ) sysblk.auto_scsi_mount_secs = DEFAULT_AUTO_SCSI_MOUNT_SECS; else { int secs; char c; if ( sscanf( argv[1], "%d%c", &secs, &c ) != 1 || secs <= 0 || secs > 99 ) { logmsg( _("HHCCF052S %s: %s invalid argument\n"),argv[0],argv[1]); return -1; } else sysblk.auto_scsi_mount_secs = secs; } } else logmsg( _("Auto SCSI mount %d seconds\n"),sysblk.auto_scsi_mount_secs); return 0; } #endif /*defined( OPTION_SCSI_TAPE )*/ /*-------------------------------------------------------------------*/ /* devinit command - assign/open a file for a configured device */ /*-------------------------------------------------------------------*/ int devinit_cmd(int argc, char *argv[], char *cmdline) { DEVBLK* dev; U16 devnum; U16 lcss; int i, rc; int nomountedtapereinit = sysblk.nomountedtapereinit; int init_argc; char **init_argv; UNREFERENCED(cmdline); if (argc < 2) { logmsg( _("HHCPN093E Missing argument(s)\n") ); return -1; } rc=parse_single_devnum(argv[1],&lcss,&devnum); if (rc<0) { return -1; } if (!(dev = find_device_by_devnum (lcss, devnum))) { devnotfound_msg(lcss,devnum); return -1; } /* Obtain the device lock */ obtain_lock (&dev->lock); /* Reject if device is busy or interrupt pending */ if (dev->busy || IOPENDING(dev) || (dev->scsw.flag3 & SCSW3_SC_PEND)) { release_lock (&dev->lock); logmsg( _("HHCPN096E Device %d:%4.4X busy or interrupt pending\n"), lcss, devnum ); return -1; } /* Prevent accidental re-init'ing of already loaded tape drives */ if (nomountedtapereinit) { char* devclass; ASSERT( dev->hnd && dev->hnd->query ); dev->hnd->query( dev, &devclass, 0, NULL ); if (1 && strcmp(devclass,"TAPE") == 0 && (0 || TAPEDEVT_SCSITAPE == dev->tapedevt || (argc >= 3 && strcmp(argv[2], TAPE_UNLOADED) != 0) ) ) { ASSERT( dev->tmh && dev->tmh->tapeloaded ); if (dev->tmh->tapeloaded( dev, NULL, 0 )) { release_lock (&dev->lock); logmsg(_("HHCPN183E Reinit rejected for drive %u:%4.4X; drive not empty\n"), SSID_TO_LCSS(dev->ssid), dev->devnum); return -1; } } } /* Close the existing file, if any */ if (dev->fd < 0 || dev->fd > 2) { (dev->hnd->close)(dev); } /* Build the device initialization arguments array */ if (argc > 2) { /* Use the specified new arguments */ init_argc = argc-2; init_argv = &argv[2]; } else { /* Use the same arguments as originally used */ init_argc = dev->argc; if (init_argc) { init_argv = malloc ( init_argc * sizeof(char*) ); for (i = 0; i < init_argc; i++) if (dev->argv[i]) init_argv[i] = strdup(dev->argv[i]); else init_argv[i] = NULL; } else init_argv = NULL; } /* Call the device init routine to do the hard work */ if ((rc = (dev->hnd->init)(dev, init_argc, init_argv)) < 0) { logmsg( _("HHCPN097E Initialization failed for device %d:%4.4X\n"), lcss, devnum ); } else { logmsg( _("HHCPN098I Device %d:%4.4X initialized\n"), lcss, devnum ); } /* Save arguments for next time */ if (rc == 0) { for (i = 0; i < dev->argc; i++) if (dev->argv[i]) free(dev->argv[i]); if (dev->argv) free(dev->argv); dev->argc = init_argc; if (init_argc) { dev->argv = malloc ( init_argc * sizeof(char*) ); for (i = 0; i < init_argc; i++) if (init_argv[i]) dev->argv[i] = strdup(init_argv[i]); else dev->argv[i] = NULL; } else dev->argv = NULL; } /* Release the device lock */ release_lock (&dev->lock); /* Raise unsolicited device end interrupt for the device */ if (rc == 0) rc = device_attention (dev, CSW_DE); return rc; } /*-------------------------------------------------------------------*/ /* savecore filename command - save a core image to file */ /*-------------------------------------------------------------------*/ int savecore_cmd(int argc, char *argv[], char *cmdline) { REGS *regs; char *fname; /* -> File name (ASCIIZ) */ char *loadaddr; /* loadcore memory address */ U32 aaddr; /* Absolute storage address */ U32 aaddr2; /* Absolute storage address */ int fd; /* File descriptor */ int len; /* Number of bytes read */ BYTE c; /* (dummy sscanf work area) */ char pathname[MAX_PATH]; /* fname in host path format */ UNREFERENCED(cmdline); if (argc < 2) { logmsg( _("HHCPN099E savecore rejected: filename missing\n") ); return -1; } fname = argv[1]; obtain_lock(&sysblk.cpulock[sysblk.pcpu]); if (!IS_CPU_ONLINE(sysblk.pcpu)) { release_lock(&sysblk.cpulock[sysblk.pcpu]); logmsg( _("HHCPN160W CPU%4.4X not configured\n"), sysblk.pcpu); return 0; } regs = sysblk.regs[sysblk.pcpu]; if (argc < 3 || '*' == *(loadaddr = argv[2])) { for (aaddr = 0; aaddr < sysblk.mainsize && !(STORAGE_KEY(aaddr, regs) & STORKEY_CHANGE); aaddr += 4096) { ; /* (nop) */ } if (aaddr >= sysblk.mainsize) aaddr = 0; else aaddr &= ~0xFFF; } else if (sscanf(loadaddr, "%x%c", &aaddr, &c) !=1 || aaddr >= sysblk.mainsize ) { release_lock(&sysblk.cpulock[sysblk.pcpu]); logmsg( _("HHCPN100E savecore: invalid starting address: %s \n"), loadaddr ); return -1; } if (argc < 4 || '*' == *(loadaddr = argv[3])) { for (aaddr2 = sysblk.mainsize - 4096; aaddr2 > 0 && !(STORAGE_KEY(aaddr2, regs) & STORKEY_CHANGE); aaddr2 -= 4096) { ; /* (nop) */ } if ( STORAGE_KEY(aaddr2, regs) & STORKEY_CHANGE ) aaddr2 |= 0xFFF; else { release_lock(&sysblk.cpulock[sysblk.pcpu]); logmsg( _("HHCPN148E savecore: no modified storage found\n") ); return -1; } } else if (sscanf(loadaddr, "%x%c", &aaddr2, &c) !=1 || aaddr2 >= sysblk.mainsize ) { release_lock(&sysblk.cpulock[sysblk.pcpu]); logmsg( _("HHCPN101E savecore: invalid ending address: %s \n"), loadaddr ); return -1; } /* Command is valid only when CPU is stopped */ if (CPUSTATE_STOPPED != regs->cpustate) { release_lock(&sysblk.cpulock[sysblk.pcpu]); logmsg( _("HHCPN102E savecore rejected: CPU not stopped\n") ); return -1; } if (aaddr > aaddr2) { release_lock(&sysblk.cpulock[sysblk.pcpu]); logmsg( _("HHCPN103E invalid range: %8.8X-%8.8X\n"), aaddr, aaddr2 ); return -1; } /* Save the file from absolute storage */ logmsg( _("HHCPN104I Saving locations %8.8X-%8.8X to %s\n"), aaddr, aaddr2, fname ); hostpath(pathname, fname, sizeof(pathname)); if ((fd = open(pathname, O_CREAT|O_WRONLY|O_EXCL|O_BINARY, S_IREAD|S_IWRITE|S_IRGRP)) < 0) { int saved_errno = errno; release_lock(&sysblk.cpulock[sysblk.pcpu]); logmsg( _("HHCPN105E savecore error creating %s: %s\n"), fname, strerror(saved_errno) ); return -1; } if ((len = write(fd, regs->mainstor + aaddr, (aaddr2 - aaddr) + 1)) < 0) logmsg( _("HHCPN106E savecore error writing to %s: %s\n"), fname, strerror(errno) ); else if((U32)len < (aaddr2 - aaddr) + 1) logmsg( _("HHCPN107E savecore: unable to save %d bytes\n"), ((aaddr2 - aaddr) + 1) - len ); close(fd); release_lock(&sysblk.cpulock[sysblk.pcpu]); logmsg( _("HHCPN170I savecore command complete.\n")); return 0; } /*-------------------------------------------------------------------*/ /* loadcore filename command - load a core image file */ /*-------------------------------------------------------------------*/ int loadcore_cmd(int argc, char *argv[], char *cmdline) { REGS *regs; char *fname; /* -> File name (ASCIIZ) */ struct stat statbuff; /* Buffer for file status */ char *loadaddr; /* loadcore memory address */ U32 aaddr; /* Absolute storage address */ int len; /* Number of bytes read */ char pathname[MAX_PATH]; /* file in host path format */ UNREFERENCED(cmdline); if (argc < 2) { logmsg( _("HHCPN108E loadcore rejected: filename missing\n") ); return -1; } fname = argv[1]; hostpath(pathname, fname, sizeof(pathname)); if (stat(pathname, &statbuff) < 0) { logmsg( _("HHCPN109E Cannot open %s: %s\n"), fname, strerror(errno)); return -1; } if (argc < 3) aaddr = 0; else { loadaddr = argv[2]; if (sscanf(loadaddr, "%x", &aaddr) !=1) { logmsg( _("HHCPN110E invalid address: %s \n"), loadaddr ); return -1; } } obtain_lock(&sysblk.cpulock[sysblk.pcpu]); if (!IS_CPU_ONLINE(sysblk.pcpu)) { release_lock(&sysblk.cpulock[sysblk.pcpu]); logmsg( _("HHCPN160W CPU%4.4X not configured\n"), sysblk.pcpu); return 0; } regs = sysblk.regs[sysblk.pcpu]; /* Command is valid only when CPU is stopped */ if (CPUSTATE_STOPPED != regs->cpustate) { release_lock(&sysblk.cpulock[sysblk.pcpu]); logmsg( _("HHCPN111E loadcore rejected: CPU not stopped\n") ); return -1; } /* Read the file into absolute storage */ logmsg( _("HHCPN112I Loading %s to location %x \n"), fname, aaddr ); len = load_main(fname, aaddr); release_lock(&sysblk.cpulock[sysblk.pcpu]); logmsg( _("HHCPN113I %d bytes read from %s\n"), len, fname ); return 0; } /*-------------------------------------------------------------------*/ /* loadtext filename command - load a text deck file */ /*-------------------------------------------------------------------*/ int loadtext_cmd(int argc, char *argv[], char *cmdline) { char *fname; /* -> File name (ASCIIZ) */ char *loadaddr; /* loadcore memory address */ U32 aaddr; /* Absolute storage address */ int fd; /* File descriptor */ BYTE buf[80]; /* Read buffer */ int len; /* Number of bytes read */ int n; REGS *regs; char pathname[MAX_PATH]; UNREFERENCED(cmdline); if (argc < 2) { logmsg( _("HHCPN114E loadtext rejected: filename missing\n") ); return -1; } fname = argv[1]; if (argc < 3) aaddr = 0; else { loadaddr = argv[2]; if (sscanf(loadaddr, "%x", &aaddr) !=1) { logmsg( _("HHCPN115E invalid address: %s \n"), loadaddr ); return -1; } } obtain_lock(&sysblk.cpulock[sysblk.pcpu]); if (!IS_CPU_ONLINE(sysblk.pcpu)) { release_lock(&sysblk.cpulock[sysblk.pcpu]); logmsg( _("HHCPN160W CPU%4.4X not configured\n"), sysblk.pcpu); return 0; } regs = sysblk.regs[sysblk.pcpu]; if (aaddr > regs->mainlim) { release_lock(&sysblk.cpulock[sysblk.pcpu]); logmsg( _("HHCPN116E Address greater than mainstore size\n") ); return -1; } /* Command is valid only when CPU is stopped */ if (CPUSTATE_STOPPED != regs->cpustate) { release_lock(&sysblk.cpulock[sysblk.pcpu]); logmsg( _("HHCPN117E loadtext rejected: CPU not stopped\n") ); return -1; } /* Open the specified file name */ hostpath(pathname, fname, sizeof(pathname)); if ((fd = open (pathname, O_RDONLY | O_BINARY)) < 0) { release_lock(&sysblk.cpulock[sysblk.pcpu]); logmsg( _("HHCPN118E Cannot open %s: %s\n"), fname, strerror(errno)); return -1; } for ( n = 0; ; ) { /* Read 80 bytes into buffer */ if ((len = read (fd, buf, 80)) < 0) { release_lock(&sysblk.cpulock[sysblk.pcpu]); logmsg( _("HHCPN119E Cannot read %s: %s\n"), fname, strerror(errno)); close (fd); return -1; } /* if record is "END" then break out of loop */ if (0xC5 == buf[1] && 0xD5 == buf[2] && 0xC4 == buf[3]) break; /* if record is "TXT" then copy bytes to mainstore */ if (0xE3 == buf[1] && 0xE7 == buf[2] && 0xE3 == buf[3]) { n = buf[5]*65536 + buf[6]*256 + buf[7]; len = buf[11]; memcpy(regs->mainstor + aaddr + n, &buf[16], len); STORAGE_KEY(aaddr + n, regs) |= (STORKEY_REF | STORKEY_CHANGE); STORAGE_KEY(aaddr + n + len - 1, regs) |= (STORKEY_REF | STORKEY_CHANGE); } } /* Close file and issue status message */ close (fd); logmsg( _("HHCPN120I Finished loading TEXT deck file\n") ); logmsg( _(" Last 'TXT' record had address: %3.3X\n"), n ); release_lock(&sysblk.cpulock[sysblk.pcpu]); return 0; } /*-------------------------------------------------------------------*/ /* ipending command - display pending interrupts */ /*-------------------------------------------------------------------*/ int ipending_cmd(int argc, char *argv[], char *cmdline) { DEVBLK *dev; /* -> Device block */ IOINT *io; /* -> I/O interrupt entry */ unsigned i; char sysid[12]; BYTE curpsw[16]; char *states[] = { "?(0)", "STARTED", "STOPPING", "STOPPED" }; UNREFERENCED(argc); UNREFERENCED(argv); UNREFERENCED(cmdline); for (i = 0; i < MAX_CPU_ENGINES; i++) { if (!IS_CPU_ONLINE(i)) { logmsg(_("HHCPN123I CPU%4.4X: offline\n"), i); continue; } // /*DEBUG*/logmsg( _("CPU%4.4X: Any cpu interrupt %spending\n"), // /*DEBUG*/ sysblk.regs[i]->cpuad, sysblk.regs[i]->cpuint ? "" : _("not ") ); logmsg( _("HHCPN123I CPU%4.4X: CPUint=%8.8X " "(State:%8.8X)&(Mask:%8.8X)\n"), sysblk.regs[i]->cpuad, IC_INTERRUPT_CPU(sysblk.regs[i]), sysblk.regs[i]->ints_state, sysblk.regs[i]->ints_mask ); logmsg( _(" CPU%4.4X: Interrupt %spending\n"), sysblk.regs[i]->cpuad, IS_IC_INTERRUPT(sysblk.regs[i]) ? "" : _("not ") ); logmsg( _(" CPU%4.4X: I/O interrupt %spending\n"), sysblk.regs[i]->cpuad, IS_IC_IOPENDING ? "" : _("not ") ); logmsg( _(" CPU%4.4X: Clock comparator %spending\n"), sysblk.regs[i]->cpuad, IS_IC_CLKC(sysblk.regs[i]) ? "" : _("not ") ); logmsg( _(" CPU%4.4X: CPU timer %spending\n"), sysblk.regs[i]->cpuad, IS_IC_PTIMER(sysblk.regs[i]) ? "" : _("not ") ); #if defined(_FEATURE_INTERVAL_TIMER) logmsg( _(" CPU%4.4X: Interval timer %spending\n"), sysblk.regs[i]->cpuad, IS_IC_ITIMER(sysblk.regs[i]) ? "" : _("not ") ); #if defined(_FEATURE_ECPSVM) logmsg( _(" CPU%4.4X: ECPS vtimer %spending\n"), sysblk.regs[i]->cpuad, IS_IC_ECPSVTIMER(sysblk.regs[i]) ? "" : _("not ") ); #endif /*defined(_FEATURE_ECPSVM)*/ #endif /*defined(_FEATURE_INTERVAL_TIMER)*/ logmsg( _(" CPU%4.4X: External call %spending\n"), sysblk.regs[i]->cpuad, IS_IC_EXTCALL(sysblk.regs[i]) ? "" : _("not ") ); logmsg( _(" CPU%4.4X: Emergency signal %spending\n"), sysblk.regs[i]->cpuad, IS_IC_EMERSIG(sysblk.regs[i]) ? "" : _("not ") ); logmsg( _(" CPU%4.4X: Machine check interrupt %spending\n"), sysblk.regs[i]->cpuad, IS_IC_MCKPENDING(sysblk.regs[i]) ? "" : _("not ") ); logmsg( _(" CPU%4.4X: Service signal %spending\n"), sysblk.regs[i]->cpuad, IS_IC_SERVSIG ? "" : _("not ") ); logmsg( _(" CPU%4.4X: Mainlock held: %s\n"), sysblk.regs[i]->cpuad, sysblk.regs[i]->cpuad == sysblk.mainowner ? _("yes") : _("no") ); logmsg( _(" CPU%4.4X: Intlock held: %s\n"), sysblk.regs[i]->cpuad, sysblk.regs[i]->cpuad == sysblk.intowner ? _("yes") : _("no") ); logmsg( _(" CPU%4.4X: Waiting for intlock: %s\n"), sysblk.regs[i]->cpuad, sysblk.regs[i]->intwait && !(sysblk.waiting_mask & CPU_BIT(i)) ? _("yes") : _("no") ); logmsg( _(" CPU%4.4X: lock %sheld\n"), sysblk.regs[i]->cpuad, test_lock(&sysblk.cpulock[i]) ? "" : _("not ") ); if (ARCH_370 == sysblk.arch_mode) { if (0xFFFF == sysblk.regs[i]->chanset) logmsg( _(" CPU%4.4X: No channelset connected\n"), sysblk.regs[i]->cpuad ); else logmsg( _(" CPU%4.4X: Connected to channelset " "%4.4X\n"), sysblk.regs[i]->cpuad,sysblk.regs[i]->chanset ); } logmsg( _(" CPU%4.4X: state %s\n"), sysblk.regs[i]->cpuad,states[sysblk.regs[i]->cpustate]); logmsg( _(" CPU%4.4X: instcount %" I64_FMT "d\n"), sysblk.regs[i]->cpuad,(long long)INSTCOUNT(sysblk.regs[i])); logmsg( _(" CPU%4.4X: siocount %" I64_FMT "d\n"), sysblk.regs[i]->cpuad,(long long)sysblk.regs[i]->siototal); copy_psw(sysblk.regs[i], curpsw); logmsg( _(" CPU%4.4X: psw %2.2x%2.2x%2.2x%2.2x %2.2x%2.2x%2.2x%2.2x"), sysblk.regs[i]->cpuad,curpsw[0],curpsw[1],curpsw[2],curpsw[3], curpsw[4],curpsw[5],curpsw[6],curpsw[7]); if (ARCH_900 == sysblk.arch_mode) logmsg( _(" %2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x"), curpsw[8],curpsw[9],curpsw[10],curpsw[11], curpsw[12],curpsw[13],curpsw[14],curpsw[15]); logmsg("\n"); if (sysblk.regs[i]->sie_active) { logmsg( _("HHCPN123I SIE%4.4X: CPUint=%8.8X " "(State:%8.8X)&(Mask:%8.8X)\n"), sysblk.regs[i]->guestregs->cpuad, IC_INTERRUPT_CPU(sysblk.regs[i]->guestregs), sysblk.regs[i]->guestregs->ints_state, sysblk.regs[i]->guestregs->ints_mask ); logmsg( _(" SIE%4.4X: Interrupt %spending\n"), sysblk.regs[i]->guestregs->cpuad, IS_IC_INTERRUPT(sysblk.regs[i]->guestregs) ? "" : _("not ") ); logmsg( _(" SIE%4.4X: I/O interrupt %spending\n"), sysblk.regs[i]->guestregs->cpuad, IS_IC_IOPENDING ? "" : _("not ") ); logmsg( _(" SIE%4.4X: Clock comparator %spending\n"), sysblk.regs[i]->guestregs->cpuad, IS_IC_CLKC(sysblk.regs[i]->guestregs) ? "" : _("not ") ); logmsg( _(" SIE%4.4X: CPU timer %spending\n"), sysblk.regs[i]->guestregs->cpuad, IS_IC_PTIMER(sysblk.regs[i]->guestregs) ? "" : _("not ") ); logmsg( _(" SIE%4.4X: Interval timer %spending\n"), sysblk.regs[i]->guestregs->cpuad, IS_IC_ITIMER(sysblk.regs[i]->guestregs) ? "" : _("not ") ); logmsg( _(" SIE%4.4X: External call %spending\n"), sysblk.regs[i]->guestregs->cpuad, IS_IC_EXTCALL(sysblk.regs[i]->guestregs) ? "" : _("not ") ); logmsg( _(" SIE%4.4X: Emergency signal %spending\n"), sysblk.regs[i]->guestregs->cpuad, IS_IC_EMERSIG(sysblk.regs[i]->guestregs) ? "" : _("not ") ); logmsg( _(" SIE%4.4X: Machine check interrupt %spending\n"), sysblk.regs[i]->guestregs->cpuad, IS_IC_MCKPENDING(sysblk.regs[i]->guestregs) ? "" : _("not ") ); logmsg( _(" SIE%4.4X: Service signal %spending\n"), sysblk.regs[i]->guestregs->cpuad, IS_IC_SERVSIG ? "" : _("not ") ); logmsg( _(" SIE%4.4X: lock %sheld\n"), sysblk.regs[i]->guestregs->cpuad, test_lock(&sysblk.cpulock[i]) ? "" : _("not ") ); if (ARCH_370 == sysblk.arch_mode) { if (0xFFFF == sysblk.regs[i]->guestregs->chanset) logmsg( _(" SIE%4.4X: No channelset connected\n"), sysblk.regs[i]->guestregs->cpuad ); else logmsg( _(" SIE%4.4X: Connected to channelset " "%4.4X\n"), sysblk.regs[i]->guestregs->cpuad,sysblk.regs[i]->guestregs->chanset ); } logmsg( _(" SIE%4.4X: state %s\n"), sysblk.regs[i]->guestregs->cpuad,states[sysblk.regs[i]->guestregs->cpustate]); logmsg( _(" SIE%4.4X: instcount %" I64_FMT "d\n"), sysblk.regs[i]->guestregs->cpuad,(long long)sysblk.regs[i]->guestregs->instcount); logmsg( _(" SIE%4.4X: siocount %" I64_FMT "d\n"), sysblk.regs[i]->guestregs->cpuad,(long long)sysblk.regs[i]->guestregs->siototal); copy_psw(sysblk.regs[i]->guestregs, curpsw); logmsg( _(" SIE%4.4X: psw %2.2x%2.2x%2.2x%2.2x %2.2x%2.2x%2.2x%2.2x"), sysblk.regs[i]->guestregs->cpuad,curpsw[0],curpsw[1],curpsw[2],curpsw[3], curpsw[4],curpsw[5],curpsw[6],curpsw[7]); if (ARCH_900 == sysblk.regs[i]->guestregs->arch_mode) logmsg( _(" %2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x"), curpsw[8],curpsw[9],curpsw[10],curpsw[11], curpsw[12],curpsw[13],curpsw[14],curpsw[15]); logmsg("\n"); } } logmsg( _(" Config mask "F_CPU_BITMAP " started mask "F_CPU_BITMAP " waiting mask "F_CPU_BITMAP"\n"), sysblk.config_mask, sysblk.started_mask, sysblk.waiting_mask ); logmsg( _(" Syncbc mask "F_CPU_BITMAP" %s\n"), sysblk.sync_mask, sysblk.syncing ? _("Sync in progress") : "" ); logmsg( _(" Signaling facility %sbusy\n"), test_lock(&sysblk.sigplock) ? "" : _("not ") ); logmsg( _(" TOD lock %sheld\n"), test_lock(&sysblk.todlock) ? "" : _("not ") ); logmsg( _(" Mainlock %sheld; owner %4.4x\n"), test_lock(&sysblk.mainlock) ? "" : _("not "), sysblk.mainowner ); logmsg( _(" Intlock %sheld; owner %4.4x\n"), test_lock(&sysblk.intlock) ? "" : _("not "), sysblk.intowner ); #if !defined(OPTION_FISHIO) logmsg( _(" Ioq lock %sheld\n"), test_lock(&sysblk.ioqlock) ? "" : _("not ") ); #endif for (dev = sysblk.firstdev; dev != NULL; dev = dev->nextdev) { if (dev->ioactive == DEV_SYS_NONE) strcpy (sysid, "(none)"); else if (dev->ioactive == DEV_SYS_LOCAL) strcpy (sysid, "local"); else sprintf (sysid, "id=%d", dev->ioactive); if (dev->busy && !(dev->suspended && dev->ioactive == DEV_SYS_NONE)) logmsg( _(" DEV %d:%4.4X: busy %s\n"), SSID_TO_LCSS(dev->ssid), dev->devnum, sysid ); if (dev->reserved) logmsg( _(" DEV %d:%4.4X: reserved %s\n"), SSID_TO_LCSS(dev->ssid), dev->devnum, sysid ); if (dev->suspended) logmsg( _(" DEV %d:%4.4X: suspended\n"), SSID_TO_LCSS(dev->ssid), dev->devnum ); if (dev->pending && (dev->pmcw.flag5 & PMCW5_V)) logmsg( _(" DEV %d:%4.4X: I/O pending\n"), SSID_TO_LCSS(dev->ssid), dev->devnum ); if (dev->pcipending && (dev->pmcw.flag5 & PMCW5_V)) logmsg( _(" DEV %d:%4.4X: PCI pending\n"), SSID_TO_LCSS(dev->ssid), dev->devnum ); if (dev->attnpending && (dev->pmcw.flag5 & PMCW5_V)) logmsg( _(" DEV %d:%4.4X: Attn pending\n"), SSID_TO_LCSS(dev->ssid), dev->devnum ); if ((dev->crwpending) && (dev->pmcw.flag5 & PMCW5_V)) logmsg( _(" DEV %d:%4.4X: CRW pending\n"), SSID_TO_LCSS(dev->ssid), dev->devnum ); if (test_lock(&dev->lock) && (dev->pmcw.flag5 & PMCW5_V)) logmsg( _(" DEV %d:%4.4X: lock held\n"), SSID_TO_LCSS(dev->ssid), dev->devnum ); } logmsg( _(" I/O interrupt queue: ") ); if (!sysblk.iointq) logmsg( _("(NULL)") ); logmsg("\n"); for (io = sysblk.iointq; io; io = io->next) logmsg ( _(" DEV %d:%4.4X,%s%s%s%s, pri %d\n") ,SSID_TO_LCSS(io->dev->ssid) ,io->dev->devnum ,io->pending ? " normal" : "" ,io->pcipending ? " PCI" : "" ,io->attnpending ? " ATTN" : "" ,!IOPENDING(io) ? " unknown" : "" ,io->priority ); return 0; } #if defined(OPTION_INSTRUCTION_COUNTING) /*-------------------------------------------------------------------*/ /* icount command - display instruction counts */ /*-------------------------------------------------------------------*/ int icount_cmd(int argc, char *argv[], char *cmdline) { int i, i1, i2, i3; unsigned char *opcode1; unsigned char *opcode2; U64 *count; U64 total; UNREFERENCED(cmdline); obtain_lock( &sysblk.icount_lock ); if (argc > 1 && !strcasecmp(argv[1], "clear")) { memset(IMAP_FIRST,0,IMAP_SIZE); logmsg( _("HHCPN124I Instruction counts reset to zero.\n") ); release_lock( &sysblk.icount_lock ); return 0; } #define MAX_ICOUNT_INSTR 1000 /* Maximum number of instructions in architecture instruction set */ if(argc > 1 && !strcasecmp(argv[1], "sort")) { /* Allocate space */ if(!(opcode1 = malloc(MAX_ICOUNT_INSTR * sizeof(unsigned char)))) { logmsg("Sorry, not enough memory\n"); release_lock( &sysblk.icount_lock ); return 0; } if(!(opcode2 = malloc(MAX_ICOUNT_INSTR * sizeof(unsigned char)))) { logmsg("Sorry, not enough memory\n"); free(opcode1); release_lock( &sysblk.icount_lock ); return 0; } if(!(count = malloc(MAX_ICOUNT_INSTR * sizeof(U64)))) { logmsg("Sorry, not enough memory\n"); free(opcode1); free(opcode2); release_lock( &sysblk.icount_lock ); return(0); } for(i = 0; i < (MAX_ICOUNT_INSTR-1); i++) { opcode1[i] = 0; opcode2[i] = 0; count[i] = 0; } /* Collect */ i = 0; total = 0; for(i1 = 0; i1 < 256; i1++) { switch(i1) { case 0x01: { for(i2 = 0; i2 < 256; i2++) { if(sysblk.imap01[i2]) { opcode1[i] = i1; opcode2[i] = i2; count[i++] = sysblk.imap01[i2]; total += sysblk.imap01[i2]; if(i == (MAX_ICOUNT_INSTR-1)) { logmsg("Sorry, too many instructions\n"); free(opcode1); free(opcode2); free(count); release_lock( &sysblk.icount_lock ); return 0; } } } break; } case 0xA4: { for(i2 = 0; i2 < 256; i2++) { if(sysblk.imapa4[i2]) { opcode1[i] = i1; opcode2[i] = i2; count[i++] = sysblk.imapa4[i2]; total += sysblk.imapa4[i2]; if(i == (MAX_ICOUNT_INSTR-1)) { logmsg("Sorry, too many instructions\n"); free(opcode1); free(opcode2); free(count); release_lock( &sysblk.icount_lock ); return 0; } } } break; } case 0xA5: { for(i2 = 0; i2 < 16; i2++) { if(sysblk.imapa5[i2]) { opcode1[i] = i1; opcode2[i] = i2; count[i++] = sysblk.imapa5[i2]; total += sysblk.imapa5[i2]; if(i == (MAX_ICOUNT_INSTR-1)) { logmsg("Sorry, too many instructions\n"); free(opcode1); free(opcode2); free(count); release_lock( &sysblk.icount_lock ); return 0; } } } break; } case 0xA6: { for(i2 = 0; i2 < 256; i2++) { if(sysblk.imapa6[i2]) { opcode1[i] = i1; opcode2[i] = i2; count[i++] = sysblk.imapa6[i2]; total += sysblk.imapa6[i2]; if(i == (MAX_ICOUNT_INSTR-1)) { logmsg("Sorry, too many instructions\n"); free(opcode1); free(opcode2); free(count); release_lock( &sysblk.icount_lock ); return 0; } } } break; } case 0xA7: { for(i2 = 0; i2 < 16; i2++) { if(sysblk.imapa7[i2]) { opcode1[i] = i1; opcode2[i] = i2; count[i++] = sysblk.imapa7[i2]; total += sysblk.imapa7[i2]; if(i == (MAX_ICOUNT_INSTR-1)) { logmsg("Sorry, too many instructions\n"); free(opcode1); free(opcode2); free(count); release_lock( &sysblk.icount_lock ); return 0; } } } break; } case 0xB2: { for(i2 = 0; i2 < 256; i2++) { if(sysblk.imapb2[i2]) { opcode1[i] = i1; opcode2[i] = i2; count[i++] = sysblk.imapb2[i2]; total += sysblk.imapb2[i2]; if(i == (MAX_ICOUNT_INSTR-1)) { logmsg("Sorry, too many instructions\n"); free(opcode1); free(opcode2); free(count); release_lock( &sysblk.icount_lock ); return 0; } } } break; } case 0xB3: { for(i2 = 0; i2 < 256; i2++) { if(sysblk.imapb3[i2]) { opcode1[i] = i1; opcode2[i] = i2; count[i++] = sysblk.imapb3[i2]; total += sysblk.imapb3[i2]; if(i == (MAX_ICOUNT_INSTR-1)) { logmsg("Sorry, too many instructions\n"); free(opcode1); free(opcode2); free(count); release_lock( &sysblk.icount_lock ); return 0; } } } break; } case 0xB9: { for(i2 = 0; i2 < 256; i2++) { if(sysblk.imapb9[i2]) { opcode1[i] = i1; opcode2[i] = i2; count[i++] = sysblk.imapb9[i2]; total += sysblk.imapb9[i2]; if(i == (MAX_ICOUNT_INSTR-1)) { logmsg("Sorry, too many instructions\n"); free(opcode1); free(opcode2); free(count); release_lock( &sysblk.icount_lock ); return 0; } } } break; } case 0xC0: { for(i2 = 0; i2 < 16; i2++) { if(sysblk.imapc0[i2]) { opcode1[i] = i1; opcode2[i] = i2; count[i++] = sysblk.imapc0[i2]; total += sysblk.imapc0[i2]; if(i == (MAX_ICOUNT_INSTR-1)) { logmsg("Sorry, too many instructions\n"); free(opcode1); free(opcode2); free(count); release_lock( &sysblk.icount_lock ); return 0; } } } break; } case 0xC2: { for(i2 = 0; i2 < 16; i2++) { if(sysblk.imapc2[i2]) { opcode1[i] = i1; opcode2[i] = i2; count[i++] = sysblk.imapc2[i2]; total += sysblk.imapc2[i2]; if(i == (MAX_ICOUNT_INSTR-1)) { logmsg("Sorry, too many instructions\n"); free(opcode1); free(opcode2); free(count); release_lock( &sysblk.icount_lock ); return 0; } } } break; } case 0xC4: { for(i2 = 0; i2 < 16; i2++) { if(sysblk.imapc4[i2]) { opcode1[i] = i1; opcode2[i] = i2; count[i++] = sysblk.imapc4[i2]; total += sysblk.imapc4[i2]; if(i == (MAX_ICOUNT_INSTR-1)) { logmsg("Sorry, too many instructions\n"); free(opcode1); free(opcode2); free(count); release_lock( &sysblk.icount_lock ); return 0; } } } break; } case 0xC6: { for(i2 = 0; i2 < 16; i2++) { if(sysblk.imapc6[i2]) { opcode1[i] = i1; opcode2[i] = i2; count[i++] = sysblk.imapc6[i2]; total += sysblk.imapc6[i2]; if(i == (MAX_ICOUNT_INSTR-1)) { logmsg("Sorry, too many instructions\n"); free(opcode1); free(opcode2); free(count); release_lock( &sysblk.icount_lock ); return 0; } } } break; } case 0xC8: { for(i2 = 0; i2 < 16; i2++) { if(sysblk.imapc8[i2]) { opcode1[i] = i1; opcode2[i] = i2; count[i++] = sysblk.imapc8[i2]; total += sysblk.imapc8[i2]; if(i == (MAX_ICOUNT_INSTR-1)) { logmsg("Sorry, too many instructions\n"); free(opcode1); free(opcode2); free(count); release_lock( &sysblk.icount_lock ); return 0; } } } break; } case 0xE3: { for(i2 = 0; i2 < 256; i2++) { if(sysblk.imape3[i2]) { opcode1[i] = i1; opcode2[i] = i2; count[i++] = sysblk.imape3[i2]; total += sysblk.imape3[i2]; if(i == (MAX_ICOUNT_INSTR-1)) { logmsg("Sorry, too many instructions\n"); free(opcode1); free(opcode2); free(count); release_lock( &sysblk.icount_lock ); return 0; } } } break; } case 0xE4: { for(i2 = 0; i2 < 256; i2++) { if(sysblk.imape4[i2]) { opcode1[i] = i1; opcode2[i] = i2; count[i++] = sysblk.imape4[i2]; total += sysblk.imape4[i2]; if(i == (MAX_ICOUNT_INSTR-1)) { logmsg("Sorry, too many instructions\n"); free(opcode1); free(opcode2); free(count); release_lock( &sysblk.icount_lock ); return 0; } } } break; } case 0xE5: { for(i2 = 0; i2 < 256; i2++) { if(sysblk.imape5[i2]) { opcode1[i] = i1; opcode2[i] = i2; count[i++] = sysblk.imape5[i2]; total += sysblk.imape5[i2]; if(i == (MAX_ICOUNT_INSTR-1)) { logmsg("Sorry, too many instructions\n"); free(opcode1); free(opcode2); free(count); release_lock( &sysblk.icount_lock ); return 0; } } } break; } case 0xEB: { for(i2 = 0; i2 < 256; i2++) { if(sysblk.imapeb[i2]) { opcode1[i] = i1; opcode2[i] = i2; count[i++] = sysblk.imapeb[i2]; total += sysblk.imapeb[i2]; if(i == (MAX_ICOUNT_INSTR-1)) { logmsg("Sorry, too many instructions\n"); free(opcode1); free(opcode2); free(count); release_lock( &sysblk.icount_lock ); return 0; } } } break; } case 0xEC: { for(i2 = 0; i2 < 256; i2++) { if(sysblk.imapec[i2]) { opcode1[i] = i1; opcode2[i] = i2; count[i++] = sysblk.imapec[i2]; total += sysblk.imapec[i2]; if(i == (MAX_ICOUNT_INSTR-1)) { logmsg("Sorry, too many instructions\n"); free(opcode1); free(opcode2); free(count); release_lock( &sysblk.icount_lock ); return 0; } } } break; } case 0xED: { for(i2 = 0; i2 < 256; i2++) { if(sysblk.imaped[i2]) { opcode1[i] = i1; opcode2[i] = i2; count[i++] = sysblk.imaped[i2]; total += sysblk.imaped[i2]; if(i == (MAX_ICOUNT_INSTR-1)) { logmsg("Sorry, too many instructions\n"); free(opcode1); free(opcode2); free(count); release_lock( &sysblk.icount_lock ); return 0; } } } break; } default: { if(sysblk.imapxx[i1]) { opcode1[i] = i1; opcode2[i] = 0; count[i++] = sysblk.imapxx[i1]; total += sysblk.imapxx[i1]; if(i == (MAX_ICOUNT_INSTR-1)) { logmsg("Sorry, too many instructions\n"); free(opcode1); free(opcode2); free(count); release_lock( &sysblk.icount_lock ); return 0; } } break; } } } /* Sort */ for(i1 = 0; i1 < i; i1++) { /* Find Highest */ for(i2 = i1, i3 = i1; i2 < i; i2++) { if(count[i2] > count[i3]) i3 = i2; } /* Exchange */ opcode1[(MAX_ICOUNT_INSTR-1)] = opcode1[i1]; opcode2[(MAX_ICOUNT_INSTR-1)] = opcode2[i1]; count [(MAX_ICOUNT_INSTR-1)] = count [i1]; opcode1[i1] = opcode1[i3]; opcode2[i1] = opcode2[i3]; count [i1] = count [i3]; opcode1[i3] = opcode1[(MAX_ICOUNT_INSTR-1)]; opcode2[i3] = opcode2[(MAX_ICOUNT_INSTR-1)]; count [i3] = count [(MAX_ICOUNT_INSTR-1)]; } #define ICOUNT_WIDTH "12" /* Print field width */ /* Print */ logmsg(_("HHCPN125I Sorted instruction count display:\n")); for(i1 = 0; i1 < i; i1++) { switch(opcode1[i1]) { case 0x01: { logmsg(" INST=%2.2X%2.2X\tCOUNT=%" ICOUNT_WIDTH I64_FMT "u\t(%2d%%)\n", opcode1[i1], opcode2[i1], count[i1], (int) (count[i1] * 100 / total)); break; } case 0xA4: { logmsg(" INST=%2.2X%2.2X\tCOUNT=%" ICOUNT_WIDTH I64_FMT "u\t(%2d%%)\n", opcode1[i1], opcode2[i1], count[i1], (int) (count[i1] * 100 / total)); break; } case 0xA5: { logmsg(" INST=%2.2Xx%1.1X\tCOUNT=%" ICOUNT_WIDTH I64_FMT "u\t(%2d%%)\n", opcode1[i1], opcode2[i1], count[i1], (int) (count[i1] * 100 / total)); break; } case 0xA6: { logmsg(" INST=%2.2X%2.2X\tCOUNT=%" ICOUNT_WIDTH I64_FMT "u\t(%2d%%)\n", opcode1[i1], opcode2[i1], count[i1], (int) (count[i1] * 100 / total)); break; } case 0xA7: { logmsg(" INST=%2.2Xx%1.1X\tCOUNT=%" ICOUNT_WIDTH I64_FMT "u\t(%2d%%)\n", opcode1[i1], opcode2[i1], count[i1], (int) (count[i1] * 100 / total)); break; } case 0xB2: { logmsg(" INST=%2.2X%2.2X\tCOUNT=%" ICOUNT_WIDTH I64_FMT "u\t(%2d%%)\n", opcode1[i1], opcode2[i1], count[i1], (int) (count[i1] * 100 / total)); break; } case 0xB3: { logmsg(" INST=%2.2X%2.2X\tCOUNT=%" ICOUNT_WIDTH I64_FMT "u\t(%2d%%)\n", opcode1[i1], opcode2[i1], count[i1], (int) (count[i1] * 100 / total)); break; } case 0xB9: { logmsg(" INST=%2.2X%2.2X\tCOUNT=%" ICOUNT_WIDTH I64_FMT "u\t(%2d%%)\n", opcode1[i1], opcode2[i1], count[i1], (int) (count[i1] * 100 / total)); break; } case 0xC0: { logmsg(" INST=%2.2Xx%1.1X\tCOUNT=%" ICOUNT_WIDTH I64_FMT "u\t(%2d%%)\n", opcode1[i1], opcode2[i1], count[i1], (int) (count[i1] * 100 / total)); break; } case 0xC2: { logmsg(" INST=%2.2Xx%1.1X\tCOUNT=%" ICOUNT_WIDTH I64_FMT "u\t(%2d%%)\n", opcode1[i1], opcode2[i1], count[i1], (int) (count[i1] * 100 / total)); break; } case 0xC4: { logmsg(" INST=%2.2Xx%1.1X\tCOUNT=%" ICOUNT_WIDTH I64_FMT "u\t(%2d%%)\n", opcode1[i1], opcode2[i1], count[i1], (int) (count[i1] * 100 / total)); break; } case 0xC6: { logmsg(" INST=%2.2Xx%1.1X\tCOUNT=%" ICOUNT_WIDTH I64_FMT "u\t(%2d%%)\n", opcode1[i1], opcode2[i1], count[i1], (int) (count[i1] * 100 / total)); break; } case 0xC8: { logmsg(" INST=%2.2Xx%1.1X\tCOUNT=%" ICOUNT_WIDTH I64_FMT "u\t(%2d%%)\n", opcode1[i1], opcode2[i1], count[i1], (int) (count[i1] * 100 / total)); break; } case 0xE3: { logmsg(" INST=%2.2X%2.2X\tCOUNT=%" ICOUNT_WIDTH I64_FMT "u\t(%2d%%)\n", opcode1[i1], opcode2[i1], count[i1], (int) (count[i1] * 100 / total)); break; } case 0xE4: { logmsg(" INST=%2.2X%2.2X\tCOUNT=%" ICOUNT_WIDTH I64_FMT "u\t(%2d%%)\n", opcode1[i1], opcode2[i1], count[i1], (int) (count[i1] * 100 / total)); break; } case 0xE5: { logmsg(" INST=%2.2X%2.2X\tCOUNT=%" ICOUNT_WIDTH I64_FMT "u\t(%2d%%)\n", opcode1[i1], opcode2[i1], count[i1], (int) (count[i1] * 100 / total)); break; } case 0xEB: { logmsg(" INST=%2.2X%2.2X\tCOUNT=%" ICOUNT_WIDTH I64_FMT "u\t(%2d%%)\n", opcode1[i1], opcode2[i1], count[i1], (int) (count[i1] * 100 / total)); break; } case 0xEC: { logmsg(" INST=%2.2X%2.2X\tCOUNT=%" ICOUNT_WIDTH I64_FMT "u\t(%2d%%)\n", opcode1[i1], opcode2[i1], count[i1], (int) (count[i1] * 100 / total)); break; } case 0xED: { logmsg(" INST=%2.2X%2.2X\tCOUNT=%" ICOUNT_WIDTH I64_FMT "u\t(%2d%%)\n", opcode1[i1], opcode2[i1], count[i1], (int) (count[i1] * 100 / total)); break; } default: { logmsg(" INST=%2.2X \tCOUNT=%" ICOUNT_WIDTH I64_FMT "u\t(%2d%%)\n", opcode1[i1], count[i1], (int) (count[i1] * 100 / total)); break; } } } free(opcode1); free(opcode2); free(count); release_lock( &sysblk.icount_lock ); return 0; } logmsg(_("HHCPN125I Instruction count display:\n")); for (i1 = 0; i1 < 256; i1++) { switch (i1) { case 0x01: for(i2 = 0; i2 < 256; i2++) if(sysblk.imap01[i2]) logmsg(" INST=%2.2X%2.2X\tCOUNT=%" ICOUNT_WIDTH I64_FMT "u\n", i1, i2, sysblk.imap01[i2]); break; case 0xA4: for(i2 = 0; i2 < 256; i2++) if(sysblk.imapa4[i2]) logmsg(" INST=%2.2X%2.2X\tCOUNT=%" ICOUNT_WIDTH I64_FMT "u\n", i1, i2, sysblk.imapa4[i2]); break; case 0xA5: for(i2 = 0; i2 < 16; i2++) if(sysblk.imapa5[i2]) logmsg(" INST=%2.2Xx%1.1X\tCOUNT=%" ICOUNT_WIDTH I64_FMT "u\n", i1, i2, sysblk.imapa5[i2]); break; case 0xA6: for(i2 = 0; i2 < 256; i2++) if(sysblk.imapa6[i2]) logmsg(" INST=%2.2X%2.2X\tCOUNT=%" ICOUNT_WIDTH I64_FMT "u\n", i1, i2, sysblk.imapa6[i2]); break; case 0xA7: for(i2 = 0; i2 < 16; i2++) if(sysblk.imapa7[i2]) logmsg(" INST=%2.2Xx%1.1X\tCOUNT=%" ICOUNT_WIDTH I64_FMT "u\n", i1, i2, sysblk.imapa7[i2]); break; case 0xB2: for(i2 = 0; i2 < 256; i2++) if(sysblk.imapb2[i2]) logmsg(" INST=%2.2X%2.2X\tCOUNT=%" ICOUNT_WIDTH I64_FMT "u\n", i1, i2, sysblk.imapb2[i2]); break; case 0xB3: for(i2 = 0; i2 < 256; i2++) if(sysblk.imapb3[i2]) logmsg(" INST=%2.2X%2.2X\tCOUNT=%" ICOUNT_WIDTH I64_FMT "u\n", i1, i2, sysblk.imapb3[i2]); break; case 0xB9: for(i2 = 0; i2 < 256; i2++) if(sysblk.imapb9[i2]) logmsg(" INST=%2.2X%2.2X\tCOUNT=%" ICOUNT_WIDTH I64_FMT "u\n", i1, i2, sysblk.imapb9[i2]); break; case 0xC0: for(i2 = 0; i2 < 16; i2++) if(sysblk.imapc0[i2]) logmsg(" INST=%2.2Xx%1.1X\tCOUNT=%" ICOUNT_WIDTH I64_FMT "u\n", i1, i2, sysblk.imapc0[i2]); break; case 0xC2: /*@Z9*/ for(i2 = 0; i2 < 16; i2++) /*@Z9*/ if(sysblk.imapc2[i2]) /*@Z9*/ logmsg(" INST=%2.2Xx%1.1X\tCOUNT=%" ICOUNT_WIDTH I64_FMT "u\n", /*@Z9*/ i1, i2, sysblk.imapc2[i2]); /*@Z9*/ break; /*@Z9*/ case 0xC4: for(i2 = 0; i2 < 16; i2++) if(sysblk.imapc4[i2]) logmsg(" INST=%2.2Xx%1.1X\tCOUNT=%" ICOUNT_WIDTH I64_FMT "u\n", i1, i2, sysblk.imapc4[i2]); break; case 0xC6: for(i2 = 0; i2 < 16; i2++) if(sysblk.imapc6[i2]) logmsg(" INST=%2.2Xx%1.1X\tCOUNT=%" ICOUNT_WIDTH I64_FMT "u\n", i1, i2, sysblk.imapc6[i2]); break; case 0xC8: for(i2 = 0; i2 < 16; i2++) if(sysblk.imapc8[i2]) logmsg(" INST=%2.2Xx%1.1X\tCOUNT=%" ICOUNT_WIDTH I64_FMT "u\n", i1, i2, sysblk.imapc8[i2]); break; case 0xE3: for(i2 = 0; i2 < 256; i2++) if(sysblk.imape3[i2]) logmsg(" INST=%2.2X%2.2X\tCOUNT=%" ICOUNT_WIDTH I64_FMT "u\n", i1, i2, sysblk.imape3[i2]); break; case 0xE4: for(i2 = 0; i2 < 256; i2++) if(sysblk.imape4[i2]) logmsg(" INST=%2.2X%2.2X\tCOUNT=%" ICOUNT_WIDTH I64_FMT "u\n", i1, i2, sysblk.imape4[i2]); break; case 0xE5: for(i2 = 0; i2 < 256; i2++) if(sysblk.imape5[i2]) logmsg(" INST=%2.2X%2.2X\tCOUNT=%" ICOUNT_WIDTH I64_FMT "u\n", i1, i2, sysblk.imape5[i2]); break; case 0xEB: for(i2 = 0; i2 < 256; i2++) if(sysblk.imapeb[i2]) logmsg(" INST=%2.2X%2.2X\tCOUNT=%" ICOUNT_WIDTH I64_FMT "u\n", i1, i2, sysblk.imapeb[i2]); break; case 0xEC: for(i2 = 0; i2 < 256; i2++) if(sysblk.imapec[i2]) logmsg(" INST=%2.2X%2.2X\tCOUNT=%" ICOUNT_WIDTH I64_FMT "u\n", i1, i2, sysblk.imapec[i2]); break; case 0xED: for(i2 = 0; i2 < 256; i2++) if(sysblk.imaped[i2]) logmsg(" INST=%2.2X%2.2X\tCOUNT=%" ICOUNT_WIDTH I64_FMT "u\n", i1, i2, sysblk.imaped[i2]); break; default: if(sysblk.imapxx[i1]) logmsg(" INST=%2.2X \tCOUNT=%" ICOUNT_WIDTH I64_FMT "u\n", i1, sysblk.imapxx[i1]); break; } } release_lock( &sysblk.icount_lock ); return 0; } #endif /*defined(OPTION_INSTRUCTION_COUNTING)*/ #if defined(OPTION_CONFIG_SYMBOLS) /*-------------------------------------------------------------------*/ /* defsym command - define substitution symbol */ /*-------------------------------------------------------------------*/ int defsym_cmd(int argc, char *argv[], char *cmdline) { char* sym; char* value; UNREFERENCED(cmdline); if (argc < 2) { list_all_symbols(); return 0; } /* point to symbol name */ sym = argv[1]; if (argc > 3) { logmsg(_("HHCCF060S DEFSYM requires a single value" " (use quotes if necessary)\n")); return -1; } /* point to symbol value if specified, otherwise set to blank */ value = (argc > 2) ? argv[2] : ""; /* define the symbol */ set_symbol(sym,value); return 0; } #endif // defined(OPTION_CONFIG_SYMBOLS) /*-------------------------------------------------------------------*/ /* archmode command - set architecture mode */ /*-------------------------------------------------------------------*/ int archmode_cmd(int argc, char *argv[], char *cmdline) { int i; UNREFERENCED(cmdline); if (argc < 2) { logmsg( _("HHCPN126I Architecture mode = %s\n"), get_arch_mode_string(NULL) ); return 0; } OBTAIN_INTLOCK(NULL); /* Make sure all CPUs are deconfigured or stopped */ for (i = 0; i < MAX_CPU_ENGINES; i++) if (IS_CPU_ONLINE(i) && CPUSTATE_STOPPED != sysblk.regs[i]->cpustate) { RELEASE_INTLOCK(NULL); logmsg( _("HHCPN127E All CPU's must be stopped to change " "architecture\n") ); return -1; } #if defined(_370) if (!strcasecmp (argv[1], arch_name[ARCH_370])) { sysblk.arch_mode = ARCH_370; sysblk.maxcpu = sysblk.numcpu; } else #endif #if defined(_390) if (!strcasecmp (argv[1], arch_name[ARCH_390])) { sysblk.arch_mode = ARCH_390; #if defined(_FEATURE_CPU_RECONFIG) sysblk.maxcpu = MAX_CPU_ENGINES; #else sysblk.maxcpu = sysblk.numcpu; #endif } else #endif #if defined(_900) if (0 || !strcasecmp (argv[1], arch_name[ARCH_900]) || !strcasecmp (argv[1], "ESAME") ) { sysblk.arch_mode = ARCH_900; #if defined(_FEATURE_CPU_RECONFIG) sysblk.maxcpu = MAX_CPU_ENGINES; #else sysblk.maxcpu = sysblk.numcpu; #endif } else #endif { RELEASE_INTLOCK(NULL); logmsg( _("HHCPN128E Invalid architecture mode %s\n"), argv[1] ); return -1; } if (sysblk.pcpu >= MAX_CPU) sysblk.pcpu = 0; sysblk.dummyregs.arch_mode = sysblk.arch_mode; #if defined(OPTION_FISHIO) ios_arch_mode = sysblk.arch_mode; #endif /* defined(OPTION_FISHIO) */ /* Indicate if z/Architecture is supported */ sysblk.arch_z900 = sysblk.arch_mode != ARCH_390; #if defined(_FEATURE_CPU_RECONFIG) && defined(_S370) /* Configure CPUs for S/370 mode */ if (sysblk.archmode == ARCH_370) for (i = MAX_CPU_ENGINES - 1; i >= 0; i--) if (i < MAX_CPU && !IS_CPU_ONLINE(i)) configure_cpu(i); else if (i >= MAX_CPU && IS_CPU_ONLINE(i)) deconfigure_cpu(i); #endif RELEASE_INTLOCK(NULL); return 0; } /*-------------------------------------------------------------------*/ /* x+ and x- commands - turn switches on or off */ /*-------------------------------------------------------------------*/ int OnOffCommand(int argc, char *argv[], char *cmdline) { char *cmd = cmdline; /* Copy of panel command */ int oneorzero; /* 1=x+ command, 0=x- */ char *onoroff; /* "on" or "off" */ U32 aaddr; /* Absolute storage address */ DEVBLK* dev; U16 devnum; U16 lcss; REGS *regs; BYTE c; /* Character work area */ UNREFERENCED(argc); UNREFERENCED(argv); if (cmd[1] == '+') { oneorzero = 1; onoroff = _("on"); } else { oneorzero = 0; onoroff = _("off"); } OBTAIN_INTLOCK(NULL); if (!IS_CPU_ONLINE(sysblk.pcpu)) { RELEASE_INTLOCK(NULL); logmsg( _("HHCPN160W CPU%4.4X not configured\n"), sysblk.pcpu); return 0; } regs=sysblk.regs[sysblk.pcpu]; // f- and f+ commands - mark frames unusable/usable if ((cmd[0] == 'f') && sscanf(cmd+2, "%x%c", &aaddr, &c) == 1) { if (aaddr > regs->mainlim) { RELEASE_INTLOCK(NULL); logmsg( _("HHCPN130E Invalid frame address %8.8X\n"), aaddr ); return -1; } STORAGE_KEY(aaddr, regs) &= ~(STORKEY_BADFRM); if (!oneorzero) STORAGE_KEY(aaddr, regs) |= STORKEY_BADFRM; RELEASE_INTLOCK(NULL); logmsg( _("HHCPN131I Frame %8.8X marked %s\n"), aaddr, oneorzero ? _("usable") : _("unusable") ); return 0; } #ifdef OPTION_CKD_KEY_TRACING // t+ckd and t-ckd commands - turn CKD_KEY tracing on/off if ((cmd[0] == 't') && (strcasecmp(cmd+2, "ckd") == 0)) { for (dev = sysblk.firstdev; dev != NULL; dev = dev->nextdev) { if (dev->devchar[10] == 0x20) dev->ckdkeytrace = oneorzero; } RELEASE_INTLOCK(NULL); logmsg( _("HHCPN134I CKD KEY trace is now %s\n"), onoroff ); return 0; } #endif // t+devn and t-devn commands - turn CCW tracing on/off // s+devn and s-devn commands - turn CCW stepping on/off if ((cmd[0] == 't' || cmd[0] == 's') && parse_single_devnum_silent(&cmd[2],&lcss,&devnum)==0 ) { dev = find_device_by_devnum (lcss, devnum); if (dev == NULL) { devnotfound_msg(lcss,devnum); RELEASE_INTLOCK(NULL); return -1; } if (cmd[0] == 't') { dev->ccwtrace = oneorzero; logmsg( _("HHCPN136I CCW tracing is now %s for device %d:%4.4X\n"), onoroff, lcss, devnum ); } else { dev->ccwstep = oneorzero; logmsg( _("HHCPN137I CCW stepping is now %s for device %d:%4.4X\n"), onoroff, lcss, devnum ); } RELEASE_INTLOCK(NULL); return 0; } RELEASE_INTLOCK(NULL); logmsg( _("HHCPN138E Unrecognized +/- command.\n") ); return -1; } static inline char *aea_mode_str(BYTE mode) { static char *name[] = { "DAT-Off", "Primary", "AR", "Secondary", "Home", 0, 0, 0, "PER/DAT-Off", "PER/Primary", "PER/AR", "PER/Secondary", "PER/Home" }; return name[(mode & 0x0f) | ((mode & 0xf0) ? 8 : 0)]; } /*-------------------------------------------------------------------*/ /* aea - display aea values */ /*-------------------------------------------------------------------*/ int aea_cmd(int argc, char *argv[], char *cmdline) { int i; /* Index */ REGS *regs; UNREFERENCED(argc); UNREFERENCED(argv); UNREFERENCED(cmdline); obtain_lock(&sysblk.cpulock[sysblk.pcpu]); if (!IS_CPU_ONLINE(sysblk.pcpu)) { release_lock(&sysblk.cpulock[sysblk.pcpu]); logmsg( _("HHCPN160W CPU%4.4X not configured\n"), sysblk.pcpu); return 0; } regs = sysblk.regs[sysblk.pcpu]; logmsg ("aea mode %s\n",aea_mode_str(regs->aea_mode)); logmsg ("aea ar "); for (i = 16; i < 21; i++) if(regs->aea_ar[i] > 0) logmsg(" %2.2x",regs->aea_ar[i]); else logmsg(" %2d",regs->aea_ar[i]); for (i = 0; i < 16; i++) if(regs->aea_ar[i] > 0) logmsg(" %2.2x",regs->aea_ar[i]); else logmsg(" %2d",regs->aea_ar[i]); logmsg ("\n"); logmsg ("aea common "); if(regs->aea_common[32] > 0) logmsg(" %2.2x",regs->aea_common[32]); else logmsg(" %2d",regs->aea_common[32]); for (i = 0; i < 16; i++) if(regs->aea_common[i] > 0) logmsg(" %2.2x",regs->aea_common[i]); else logmsg(" %2d",regs->aea_common[i]); logmsg ("\n"); logmsg ("aea cr[1] %16.16" I64_FMT "x\n cr[7] %16.16" I64_FMT "x\n" " cr[13] %16.16" I64_FMT "x\n", regs->CR_G(1),regs->CR_G(7),regs->CR_G(13)); logmsg (" cr[r] %16.16" I64_FMT "x\n", regs->CR_G(CR_ASD_REAL)); for(i = 0; i < 16; i++) if(regs->aea_ar[i] > 15) logmsg (" alb[%d] %16.16" I64_FMT "x\n", regs->cr[CR_ALB_OFFSET + i]); if (regs->sie_active) { regs = regs->guestregs; logmsg ("aea SIE\n"); logmsg ("aea mode %s\n",aea_mode_str(regs->aea_mode)); logmsg ("aea ar "); for (i = 16; i < 21; i++) if(regs->aea_ar[i] > 0) logmsg(" %2.2x",regs->aea_ar[i]); else logmsg(" %2d",regs->aea_ar[i]); for (i = 0; i < 16; i++) if(regs->aea_ar[i] > 0) logmsg(" %2.2x",regs->aea_ar[i]); else logmsg(" %2d",regs->aea_ar[i]); logmsg ("\n"); logmsg ("aea common "); if(regs->aea_common[32] > 0) logmsg(" %2.2x",regs->aea_common[32]); else logmsg(" %2d",regs->aea_common[32]); for (i = 0; i < 16; i++) if(regs->aea_common[i] > 0) logmsg(" %2.2x",regs->aea_common[i]); else logmsg(" %2d",regs->aea_common[i]); logmsg ("\n"); logmsg ("aea cr[1] %16.16" I64_FMT "x\n cr[7] %16.16" I64_FMT "x\n" " cr[13] %16.16" I64_FMT "x\n", regs->CR_G(1),regs->CR_G(7),regs->CR_G(13)); logmsg (" cr[r] %16.16" I64_FMT "x\n", regs->CR_G(CR_ASD_REAL)); for(i = 0; i < 16; i++) if(regs->aea_ar[i] > 15) logmsg (" alb[%d] %16.16" I64_FMT "x\n", regs->cr[CR_ALB_OFFSET + i]); } release_lock (&sysblk.cpulock[sysblk.pcpu]); return 0; } /*-------------------------------------------------------------------*/ /* aia - display aia values */ /*-------------------------------------------------------------------*/ DLL_EXPORT int aia_cmd(int argc, char *argv[], char *cmdline) { REGS *regs; UNREFERENCED(argc); UNREFERENCED(argv); UNREFERENCED(cmdline); obtain_lock(&sysblk.cpulock[sysblk.pcpu]); if (!IS_CPU_ONLINE(sysblk.pcpu)) { release_lock(&sysblk.cpulock[sysblk.pcpu]); logmsg( _("HHCPN160W CPU%4.4X not configured\n"), sysblk.pcpu); return 0; } regs = sysblk.regs[sysblk.pcpu]; logmsg ("AIV %16.16" I64_FMT "x aip %p ip %p aie %p aim %p\n", regs->aiv,regs->aip,regs->ip,regs->aie,(BYTE *)regs->aim); if (regs->sie_active) { regs = regs->guestregs; logmsg ("SIE:\n"); logmsg ("AIV %16.16" I64_FMT "x aip %p ip %p aie %p\n", regs->aiv,regs->aip,regs->ip,regs->aie); } release_lock (&sysblk.cpulock[sysblk.pcpu]); return 0; } /*-------------------------------------------------------------------*/ /* tlb - display tlb table */ /*-------------------------------------------------------------------*/ /* */ /* NOTES: */ /* The "tlbid" field is part of TLB_VADDR so it must be extracted */ /* whenever it's used or displayed. The TLB_VADDR does not contain */ /* all of the effective address bits so they are created on-the-fly*/ /* with (i << shift) The "main" field of the tlb contains an XOR */ /* hash of effective address. So MAINADDR() macro is used to remove*/ /* the hash before it's displayed. */ /* */ int tlb_cmd(int argc, char *argv[], char *cmdline) { int i; /* Index */ int shift; /* Number of bits to shift */ int bytemask; /* Byte mask */ U64 pagemask; /* Page mask */ int matches = 0; /* Number aeID matches */ REGS *regs; UNREFERENCED(argc); UNREFERENCED(argv); UNREFERENCED(cmdline); obtain_lock(&sysblk.cpulock[sysblk.pcpu]); if (!IS_CPU_ONLINE(sysblk.pcpu)) { release_lock(&sysblk.cpulock[sysblk.pcpu]); logmsg( _("HHCPN160W CPU%4.4X not configured\n"), sysblk.pcpu); return 0; } regs = sysblk.regs[sysblk.pcpu]; shift = regs->arch_mode == ARCH_370 ? 11 : 12; bytemask = regs->arch_mode == ARCH_370 ? 0x1FFFFF : 0x3FFFFF; pagemask = regs->arch_mode == ARCH_370 ? 0x00E00000 : regs->arch_mode == ARCH_390 ? 0x7FC00000 : 0xFFFFFFFFFFC00000ULL; logmsg ("tlbID 0x%6.6x mainstor %p\n",regs->tlbID,regs->mainstor); logmsg (" ix asd vaddr pte id c p r w ky main\n"); for (i = 0; i < TLBN; i++) { logmsg("%s%3.3x %16.16" I64_FMT "x %16.16" I64_FMT "x %16.16" I64_FMT "x %4.4x %1d %1d %1d %1d %2.2x %8.8x\n", ((regs->tlb.TLB_VADDR_G(i) & bytemask) == regs->tlbID ? "*" : " "), i,regs->tlb.TLB_ASD_G(i), ((regs->tlb.TLB_VADDR_G(i) & pagemask) | (i << shift)), regs->tlb.TLB_PTE_G(i),(int)(regs->tlb.TLB_VADDR_G(i) & bytemask), regs->tlb.common[i],regs->tlb.protect[i], (regs->tlb.acc[i] & ACC_READ) != 0,(regs->tlb.acc[i] & ACC_WRITE) != 0, regs->tlb.skey[i], MAINADDR(regs->tlb.main[i], ((regs->tlb.TLB_VADDR_G(i) & pagemask) | (i << shift))) - regs->mainstor); matches += ((regs->tlb.TLB_VADDR(i) & bytemask) == regs->tlbID); } logmsg("%d tlbID matches\n", matches); if (regs->sie_active) { regs = regs->guestregs; shift = regs->guestregs->arch_mode == ARCH_370 ? 11 : 12; bytemask = regs->arch_mode == ARCH_370 ? 0x1FFFFF : 0x3FFFFF; pagemask = regs->arch_mode == ARCH_370 ? 0x00E00000 : regs->arch_mode == ARCH_390 ? 0x7FC00000 : 0xFFFFFFFFFFC00000ULL; logmsg ("\nSIE: tlbID 0x%4.4x mainstor %p\n",regs->tlbID,regs->mainstor); logmsg (" ix asd vaddr pte id c p r w ky main\n"); for (i = matches = 0; i < TLBN; i++) { logmsg("%s%3.3x %16.16" I64_FMT "x %16.16" I64_FMT "x %16.16" I64_FMT "x %4.4x %1d %1d %1d %1d %2.2x %p\n", ((regs->tlb.TLB_VADDR_G(i) & bytemask) == regs->tlbID ? "*" : " "), i,regs->tlb.TLB_ASD_G(i), ((regs->tlb.TLB_VADDR_G(i) & pagemask) | (i << shift)), regs->tlb.TLB_PTE_G(i),(int)(regs->tlb.TLB_VADDR_G(i) & bytemask), regs->tlb.common[i],regs->tlb.protect[i], (regs->tlb.acc[i] & ACC_READ) != 0,(regs->tlb.acc[i] & ACC_WRITE) != 0, regs->tlb.skey[i], MAINADDR(regs->tlb.main[i], ((regs->tlb.TLB_VADDR_G(i) & pagemask) | (i << shift))) - regs->mainstor); matches += ((regs->tlb.TLB_VADDR(i) & bytemask) == regs->tlbID); } logmsg("SIE: %d tlbID matches\n", matches); } release_lock (&sysblk.cpulock[sysblk.pcpu]); return 0; } #if defined(SIE_DEBUG_PERFMON) /*-------------------------------------------------------------------*/ /* spm - SIE performance monitor table */ /*-------------------------------------------------------------------*/ int spm_cmd(int argc, char *argv[], char *cmdline) { UNREFERENCED(argc); UNREFERENCED(argv); UNREFERENCED(cmdline); sie_perfmon_disp(); return 0; } #endif #if defined(_FEATURE_SYSTEM_CONSOLE) /*-------------------------------------------------------------------*/ /* ssd - signal shutdown command */ /*-------------------------------------------------------------------*/ int ssd_cmd(int argc, char *argv[], char *cmdline) { UNREFERENCED(argc); UNREFERENCED(argv); UNREFERENCED(cmdline); signal_quiesce(0, 0); return 0; } #endif #if defined(OPTION_COUNTING) /*-------------------------------------------------------------------*/ /* count - display counts */ /*-------------------------------------------------------------------*/ int count_cmd(int argc, char *argv[], char *cmdline) { int i; /* Index */ U64 instcount = 0; /* Instruction count */ UNREFERENCED(argc); UNREFERENCED(argv); UNREFERENCED(cmdline); if (argc > 1 && strcasecmp(argv[1],"clear") == 0) { for (i = 0; i < MAX_CPU; i++) if (IS_CPU_ONLINE(i)) sysblk.regs[i]->instcount = sysblk.regs[i]->prevcount = 0; for (i = 0; i < OPTION_COUNTING; i++) sysblk.count[i] = 0; } for (i = 0; i < MAX_CPU; i++) if (IS_CPU_ONLINE(i)) instcount += INSTCOUNT(sysblk.regs[i]); logmsg (" i: %12" I64_FMT "d\n", instcount); for (i = 0; i < OPTION_COUNTING; i++) logmsg ("%3d: %12" I64_FMT "d\n", i, sysblk.count[i]); return 0; } #endif #if defined(OPTION_DYNAMIC_LOAD) /*-------------------------------------------------------------------*/ /* ldmod - load a module */ /*-------------------------------------------------------------------*/ int ldmod_cmd(int argc, char *argv[], char *cmdline) { int i; /* Index */ UNREFERENCED(cmdline); if(argc <= 1) { logmsg("Usage: %s \n",argv[0]); return -1; } for(i = 1; i < argc; i++) { logmsg(_("HHCHD100I Loading %s ...\n"),argv[i]); if(!hdl_load(argv[i], 0)) logmsg(_("HHCHD101I Module %s loaded\n"),argv[i]); } return 0; } /*-------------------------------------------------------------------*/ /* rmmod - delete a module */ /*-------------------------------------------------------------------*/ int rmmod_cmd(int argc, char *argv[], char *cmdline) { int i; /* Index */ UNREFERENCED(cmdline); if(argc <= 1) { logmsg("Usage: %s \n",argv[0]); return -1; } for(i = 1; i < argc; i++) { logmsg(_("HHCHD102I Unloading %s ...\n"),argv[i]); if(!hdl_dele(argv[i])) logmsg(_("HHCHD103I Module %s unloaded\n"),argv[i]); } return 0; } /*-------------------------------------------------------------------*/ /* lsmod - list dynamic modules */ /*-------------------------------------------------------------------*/ int lsmod_cmd(int argc, char *argv[], char *cmdline) { UNREFERENCED(cmdline); UNREFERENCED(argc); UNREFERENCED(argv); hdl_list(HDL_LIST_DEFAULT); return 0; } /*-------------------------------------------------------------------*/ /* lsdep - list module dependencies */ /*-------------------------------------------------------------------*/ int lsdep_cmd(int argc, char *argv[], char *cmdline) { UNREFERENCED(cmdline); UNREFERENCED(argc); UNREFERENCED(argv); hdl_dlst(); return 0; } /*-------------------------------------------------------------------*/ /* modpath - set module path */ /*-------------------------------------------------------------------*/ int modpath_cmd(int argc, char *argv[], char *cmdline) { UNREFERENCED(cmdline); if(argc <= 1) { logmsg("Usage: %s \n",argv[0]); return -1; } else { hdl_setpath(strdup(argv[1])); return 0; } } #endif /*defined(OPTION_DYNAMIC_LOAD)*/ #ifdef FEATURE_ECPSVM /*-------------------------------------------------------------------*/ /* evm - ECPS:VM command */ /*-------------------------------------------------------------------*/ int evm_cmd_1(int argc, char *argv[], char *cmdline) { UNREFERENCED(cmdline); UNREFERENCED(argc); UNREFERENCED(argv); logmsg(_("HHCPN150W evm command is deprecated. Use \"ecpsvm\" instead\n")); ecpsvm_command(argc,argv); return 0; } /*-------------------------------------------------------------------*/ /* evm - ECPS:VM command */ /*-------------------------------------------------------------------*/ int evm_cmd(int argc, char *argv[], char *cmdline) { UNREFERENCED(cmdline); UNREFERENCED(argc); UNREFERENCED(argv); ecpsvm_command(argc,argv); return 0; } #endif /*-------------------------------------------------------------------*/ /* herclogo - Set the hercules logo file */ /*-------------------------------------------------------------------*/ int herclogo_cmd(int argc,char *argv[], char *cmdline) { UNREFERENCED(cmdline); if(argc<2) { sysblk.logofile=NULL; clearlogo(); return 0; } return readlogo(argv[1]); } /*-------------------------------------------------------------------*/ /* sizeof - Display sizes of various structures/tables */ /*-------------------------------------------------------------------*/ int sizeof_cmd(int argc, char *argv[], char *cmdline) { UNREFERENCED(cmdline); UNREFERENCED(argc); UNREFERENCED(argv); logmsg(_("HHCPN161I (void *) ..........%7d\n"),sizeof(void *)); logmsg(_("HHCPN161I (unsigned int) ....%7d\n"),sizeof(unsigned int)); logmsg(_("HHCPN161I (long) ............%7d\n"),sizeof(long)); logmsg(_("HHCPN161I (long long) .......%7d\n"),sizeof(long long)); logmsg(_("HHCPN161I (size_t) ..........%7d\n"),sizeof(size_t)); logmsg(_("HHCPN161I (off_t) ...........%7d\n"),sizeof(off_t)); logmsg(_("HHCPN161I SYSBLK ............%7d\n"),sizeof(SYSBLK)); logmsg(_("HHCPN161I REGS ..............%7d\n"),sizeof(REGS)); logmsg(_("HHCPN161I REGS (copy len) ...%7d\n"),sysblk.regs_copy_len); logmsg(_("HHCPN161I PSW ...............%7d\n"),sizeof(PSW)); logmsg(_("HHCPN161I DEVBLK ............%7d\n"),sizeof(DEVBLK)); logmsg(_("HHCPN161I TLB entry .........%7d\n"),sizeof(TLB)/TLBN); logmsg(_("HHCPN161I TLB table .........%7d\n"),sizeof(TLB)); logmsg(_("HHCPN161I FILENAME_MAX ......%7d\n"),FILENAME_MAX); logmsg(_("HHCPN161I PATH_MAX ..........%7d\n"),PATH_MAX); logmsg(_("HHCPN161I CPU_BITMAP ........%7d\n"),sizeof(CPU_BITMAP)); return 0; } #if defined(OPTION_HAO) /*-------------------------------------------------------------------*/ /* hao - Hercules Automatic Operator */ /*-------------------------------------------------------------------*/ int hao_cmd(int argc, char *argv[], char *cmdline) { UNREFERENCED(argc); UNREFERENCED(argv); hao_command(cmdline); /* (actual HAO code is in module hao.c) */ return 0; } #endif /* defined(OPTION_HAO) */ /*-------------------------------------------------------------------*/ /* conkpalv - set console session TCP keep-alive values */ /*-------------------------------------------------------------------*/ int conkpalv_cmd( int argc, char *argv[], char *cmdline ) { int idle, intv, cnt; UNREFERENCED( cmdline ); idle = sysblk.kaidle; intv = sysblk.kaintv; cnt = sysblk.kacnt; if(argc < 2) logmsg( _("HHCPN190I Keep-alive = (%d,%d,%d)\n"),idle,intv,cnt); else { if (argc == 2 && parse_conkpalv( argv[1], &idle, &intv, &cnt ) == 0) { sysblk.kaidle = idle; sysblk.kaintv = intv; sysblk.kacnt = cnt; } else { logmsg( _("HHCPN192E Invalid format. Enter \"help conkpalv\" for help.\n")); return -1; } } return 0; } /*-------------------------------------------------------------------*/ /* traceopt - perform display_inst traditionally or new */ /*-------------------------------------------------------------------*/ int traceopt_cmd(int argc, char *argv[], char *cmdline) { UNREFERENCED(cmdline); if (argc > 1) { if (strcasecmp(argv[1], "traditional") == 0) { sysblk.showregsfirst = 0; sysblk.showregsnone = 0; } if (strcasecmp(argv[1], "regsfirst") == 0) { sysblk.showregsfirst = 1; sysblk.showregsnone = 0; } if (strcasecmp(argv[1], "noregs") == 0) { sysblk.showregsfirst = 0; sysblk.showregsnone = 1; } } else logmsg(_("HHCPN162I Hercules instruction trace displayed in %s mode\n"), sysblk.showregsnone ? _("noregs") : sysblk.showregsfirst ? _("regsfirst") : _("traditional")); return 0; } #ifdef OPTION_CMDTGT /*-------------------------------------------------------------------*/ /* cmdtgt - Specify the command target */ /*-------------------------------------------------------------------*/ int cmdtgt_cmd(int argc, char *argv[], char *cmdline) { int print = 1; UNREFERENCED(cmdline); if(argc == 2) { if(!strcasecmp(argv[1], "herc")) sysblk.cmdtgt = 0; else if(!strcasecmp(argv[1], "scp")) sysblk.cmdtgt = 1; else if(!strcasecmp(argv[1], "pscp")) sysblk.cmdtgt = 2; else if(!strcasecmp(argv[1], "?")) ; else print = 0; } else print = 0; if(print) { switch(sysblk.cmdtgt) { case 0: { logmsg("cmdtgt: Commands are sent to hercules\n"); break; } case 1: { logmsg("cmdtgt: Commands are sent to scp\n"); break; } case 2: { logmsg("cmdtgt: Commands are sent as priority messages to scp\n"); break; } } } else logmsg("cmdtgt: Use cmdtgt [herc | scp | pscp | ?]\n"); return 0; } /*-------------------------------------------------------------------*/ /* scp - Send scp command in any mode */ /*-------------------------------------------------------------------*/ int scp_cmd(int argc, char *argv[], char *cmdline) { UNREFERENCED(argv); if(argc == 1) scp_command(" ", 0); else scp_command(&cmdline[4], 0); return 0; } /*-------------------------------------------------------------------*/ /* pscp - Send a priority message in any mode */ /*-------------------------------------------------------------------*/ int prioscp_cmd(int argc, char *argv[], char *cmdline) { UNREFERENCED(argv); if(argc == 1) scp_command(" ", 1); else scp_command(&cmdline[5], 1); return 0; } /*-------------------------------------------------------------------*/ /* herc - Send a Hercules command in any mode */ /*-------------------------------------------------------------------*/ int herc_cmd(int argc, char *argv[], char *cmdline) { UNREFERENCED(argv); if(argc == 1) ProcessPanelCommand(" "); else ProcessPanelCommand(&cmdline[5]); return 0; } #endif // OPTION_CMDTGT /* PATCH ISW20030220 - Script command support */ static int scr_recursion=0; /* Recursion count (set to 0) */ static int scr_aborted=0; /* Script abort flag */ static int scr_uaborted=0; /* Script user abort flag */ TID scr_tid=0; int scr_recursion_level() { return scr_recursion; } /*-------------------------------------------------------------------*/ /* cancel script command */ /*-------------------------------------------------------------------*/ int cscript_cmd(int argc, char *argv[], char *cmdline) { UNREFERENCED(cmdline); UNREFERENCED(argc); UNREFERENCED(argv); if(scr_tid!=0) { scr_uaborted=1; } return 0; } /*-------------------------------------------------------------------*/ /* script command */ /*-------------------------------------------------------------------*/ int script_cmd(int argc, char *argv[], char *cmdline) { int i; UNREFERENCED(cmdline); if(argc<2) { logmsg(_("HHCPN996E The script command requires a filename\n")); return 1; } if(scr_tid==0) { scr_tid=thread_id(); scr_aborted=0; scr_uaborted=0; } else { if(scr_tid!=thread_id()) { logmsg(_("HHCPN997E Only 1 script may be invoked from the panel at any time\n")); return 1; } } for(i=1;i=10) { logmsg(_("HHCPN998E Script aborted : Script recursion level exceeded\n")); scr_aborted=1; return 0; } /* Open RC file */ hostpath(pathname, script_name, sizeof(pathname)); if (!(scrfp = fopen(pathname, "r"))) { int save_errno = errno; if (!isrcfile) { if (ENOENT != errno) logmsg(_("HHCPN007E Script file \"%s\" open failed: %s\n"), script_name, strerror(errno)); else logmsg(_("HHCPN995E Script file \"%s\" not found\n"), script_name); } else /* (this IS the .rc file...) */ { if (ENOENT != errno) logmsg(_("HHCPN007E Script file \"%s\" open failed: %s\n"), script_name, strerror(errno)); } errno = save_errno; return -1; } scr_recursion++; if(isrcfile) { logmsg(_("HHCPN008I Script file processing started using file \"%s\"\n"), script_name); } /* Obtain storage for the SCRIPT file buffer */ if (!(scrbuf = malloc (scrbufsize))) { logmsg(_("HHCPN009E Script file buffer malloc failed: %s\n"), strerror(errno)); fclose(scrfp); return 0; } for (; ;) { script_test_userabort(); if(scr_aborted) { break; } /* Read a complete line from the SCRIPT file */ if (!fgets(scrbuf, scrbufsize, scrfp)) break; /* Remove trailing whitespace */ for (scrlen = strlen(scrbuf); scrlen && isspace(scrbuf[scrlen-1]); scrlen--); scrbuf[scrlen] = 0; /* Remove any # comments on the line before processing */ if ((p = strchr(scrbuf,'#')) && p > scrbuf) do *p = 0; while (isspace(*--p) && p >= scrbuf); if (strncasecmp(scrbuf,"pause",5) == 0) { sscanf(scrbuf+5, "%d", &scr_pause_amt); if (scr_pause_amt < 0 || scr_pause_amt > 999) { logmsg(_("HHCPN010W Ignoring invalid SCRIPT file pause " "statement: %s\n"), scrbuf+5); continue; } logmsg (_("HHCPN011I Pausing SCRIPT file processing for %d " "seconds...\n"), scr_pause_amt); SLEEP(scr_pause_amt); logmsg (_("HHCPN012I Resuming SCRIPT file processing...\n")); continue; } /* Process the command */ for (p = scrbuf; isspace(*p); p++); panel_command(p); script_test_userabort(); if(scr_aborted) { break; } } if (feof(scrfp)) logmsg (_("HHCPN013I EOF reached on SCRIPT file. Processing complete.\n")); else { if(!scr_aborted) { logmsg (_("HHCPN014E I/O error reading SCRIPT file: %s\n"), strerror(errno)); } else { logmsg (_("HHCPN999I Script \"%s\" aborted due to previous conditions\n"), script_name); scr_uaborted=1; } } fclose(scrfp); scr_recursion--; /* Decrement recursion count */ if(scr_recursion==0) { scr_aborted=0; /* reset abort flag */ scr_tid=0; /* reset script thread id */ } return 0; } /* END PATCH ISW20030220 */ hercules-3.07/hscmisc.c000644 000765 000765 00000142723 11143760543 016555 0ustar00jmaynardjmaynard000000 000000 /* HSCMISC.C (c) Copyright Roger Bowler, 1999-2009 */ /* (c) Copyright Jan Jaeger, 1999-2009 */ /* Miscellaneous System Command Routines */ // $Id: hscmisc.c 5125 2009-01-23 12:01:44Z bernard $ // // $Log$ // Revision 1.68 2008/11/04 05:56:31 fish // Put ensure consistent create_thread ATTR usage change back in // // Revision 1.67 2008/11/03 15:31:55 rbowler // Back out consistent create_thread ATTR modification // // Revision 1.66 2008/10/18 09:32:21 fish // Ensure consistent create_thread ATTR usage // // Revision 1.65 2008/05/11 22:30:37 rbowler // V command should display "dat off" instead of "primary" if addr is real // // Revision 1.64 2008/04/09 13:53:45 rbowler // Operand disassembly for RIL instructions // // Revision 1.63 2008/04/09 09:09:22 bernard // EXRL instruction // // Revision 1.62 2008/03/07 17:46:42 ptl00 // Add pri, sec, home options to v command // // Revision 1.61 2008/02/19 11:49:19 ivan // - Move setting of CPU priority after spwaning timer thread // - Added support for Posix 1003.1e capabilities // // Revision 1.60 2007/06/23 00:04:11 ivan // Update copyright notices to include current year (2007) // // Revision 1.59 2007/03/17 22:20:46 gsmith // Fix hostregs address calculation in copy_regs // // Revision 1.58 2007/03/16 22:47:10 gsmith // Reduce REGS copying by hscmisc.c // // Revision 1.57 2007/01/07 11:25:33 rbowler // Instruction tracing regsfirst and noregs modes // // Revision 1.56 2007/01/06 09:05:18 gsmith // Enable display_inst to display traditionally too // // Revision 1.55 2006/12/30 18:47:30 fish // 1. Display regs BEFORE instr being traced. // 2. Fix condition for Control Regs trace // // Revision 1.54 2006/12/18 14:01:54 rbowler // Only show CPU in FPR display if numcpu>1 // // Revision 1.53 2006/12/17 23:03:28 rbowler // Display FPR when tracing floating-point instructions // // Revision 1.52 2006/12/17 21:58:50 rbowler // FPR command to display register pairs // // Revision 1.51 2006/12/08 09:43:26 jj // Add CVS message log // #include "hstdinc.h" #if !defined(_HENGINE_DLL_) #define _HENGINE_DLL_ #endif #if !defined(_HSCMISC_C_) #define _HSCMISC_C_ #endif #include "hercules.h" #include "devtype.h" #include "opcode.h" #include "inline.h" #define DISPLAY_INSTRUCTION_OPERANDS #if !defined(_HSCMISC_C) #define _HSCMISC_C /*-------------------------------------------------------------------*/ /* System Shutdown Processing */ /*-------------------------------------------------------------------*/ /* The following 'sigq' functions are responsible for ensuring all of the CPUs are stopped ("quiesced") before continuing with Hercules shutdown processing, and should NEVER be called directly. Instead, they are called by the main 'do_shutdown' (or 'do_shutdown_wait') function(s) (defined further below) as needed and/or appropriate. */ static int wait_sigq_pending = 0; static int is_wait_sigq_pending() { int pending; OBTAIN_INTLOCK(NULL); pending = wait_sigq_pending; RELEASE_INTLOCK(NULL); return pending; } static void wait_sigq_resp() { int pending, i; /* Wait for all CPU's to stop */ do { OBTAIN_INTLOCK(NULL); wait_sigq_pending = 0; for (i = 0; i < MAX_CPU_ENGINES; i++) if (IS_CPU_ONLINE(i) && sysblk.regs[i]->cpustate != CPUSTATE_STOPPED) wait_sigq_pending = 1; pending = wait_sigq_pending; RELEASE_INTLOCK(NULL); if(pending) SLEEP(1); } while(is_wait_sigq_pending()); } static void cancel_wait_sigq() { OBTAIN_INTLOCK(NULL); wait_sigq_pending = 0; RELEASE_INTLOCK(NULL); } /* do_shutdown_now This is the main shutdown processing function. It is NEVER called directly, but is instead ONLY called by either the 'do_shutdown' or 'do_shutdown_wait' functions after all CPUs have been stopped. It is responsible for releasing the device configuration and then calling the Hercules Dynamic Loader "hdl_shut" function to invoke all registered "Hercules at-exit/termination functions" (similar to 'atexit' but unique to Hercules) (to perform any other needed miscellaneous shutdown related processing). Only after the above three tasks have been completed (stopping the CPUs, releasing the device configuration, calling registered term- ination routines/functions) can Hercules then be safely terminated. Note too that, *technically*, this function *should* wait for *all* other threads to finish terminating first before either exiting or returning back to the caller, but we don't currently enforce that (since that's *really* what hdl_adsc + hdl_shut is designed for!). At the moment, as long as the three previously mentioned three most important shutdown tasks have been completed (stop cpus, release device config, call term funcs), then we consider the brunt of our shutdown processing to be completed and thus exit (or return back to the caller to let them exit instead). If there happen to be any threads still running when that happens, they will be automatically terminated by the operating sytem as normal when a process exits. SO... If there are any threads that must be terminated completely and cleanly before Hercules can safely terminate, then you better add code to this function to ENSURE that your thread is terminated properly! (and/or add a call to 'hdl_adsc' at the appropriate place in the startup sequence). For this purpose, the use of "join_thread" is *strongly* encouraged as it *ensures* that your thread will not continue until the thread in question has completely exited first. */ static void do_shutdown_now() { logmsg("HHCIN900I Begin Hercules shutdown\n"); ASSERT( !sysblk.shutfini ); // (sanity check) sysblk.shutfini = 0; // (shutdown NOT finished yet) sysblk.shutdown = 1; // (system shutdown initiated) logmsg("HHCIN901I Releasing configuration\n"); { release_config(); } logmsg("HHCIN902I Configuration release complete\n"); logmsg("HHCIN903I Calling termination routines\n"); { hdl_shut(); } logmsg("HHCIN904I All termination routines complete\n"); /* logmsg("HHCIN905I Terminating threads\n"); { // (none we really care about at the moment...) } logmsg("HHCIN906I Threads terminations complete\n"); */ logmsg("HHCIN909I Hercules shutdown complete\n"); sysblk.shutfini = 1; // (shutdown is now complete) // PROGRAMMING NOTE // If we're NOT in "daemon_mode" (i.e. panel_display in control), // -OR- if a daemon_task DOES exist, then THEY are in control of // shutdown; THEY are responsible for exiting the system whenever // THEY feel it's proper to do so (by simply returning back to the // caller thereby allowing 'main' to return back to the operating // system). // OTHEWRWISE we ARE in "daemon_mode", but a daemon_task does NOT // exist, which means the main thread (tail end of 'impl.c') is // stuck in a loop reading log messages and writing them to the // logfile, so we need to do the exiting here since it obviously // cannot. if ( sysblk.daemon_mode #if defined(OPTION_DYNAMIC_LOAD) && !daemon_task #endif /*defined(OPTION_DYNAMIC_LOAD)*/ ) { #if defined(FISH_HANG) FishHangAtExit(); #endif #ifdef _MSVC_ socket_deinit(); #endif #ifdef DEBUG fprintf(stdout, _("DO_SHUTDOWN_NOW EXIT\n")); #endif fprintf(stdout, _("HHCIN099I Hercules terminated\n")); fflush(stdout); exit(0); } } /* do_shutdown_wait This function simply waits for the CPUs to stop and then calls the above do_shutdown_now function to perform the actual shutdown (which releases the device configuration, etc) */ static void do_shutdown_wait() { logmsg(_("HHCIN098I Shutdown initiated\n")); wait_sigq_resp(); do_shutdown_now(); } /* ***** do_shutdown ***** This is the main system shutdown function, and the ONLY function that should EVER be called to shut the system down. It calls one or more of the above static helper functions as needed. */ void do_shutdown() { TID tid; if(is_wait_sigq_pending()) cancel_wait_sigq(); else if(can_signal_quiesce() && !signal_quiesce(0,0)) create_thread(&tid, DETACHED, do_shutdown_wait, NULL, "do_shutdown_wait"); else do_shutdown_now(); } /*-------------------------------------------------------------------*/ /* The following 2 routines display an array of 32/64 registers */ /* 1st parameter is the register type (GR, CR, AR, etc..) */ /* 2nd parameter is the CPU Address involved */ /* 3rd parameter is an array of 32/64 bit regs */ /* NOTE : 32 bit regs are displayed 4 by 4, while 64 bit regs are */ /* displayed 2 by 2. Change the modulo if to change this */ /* behaviour. */ /* These routines are intended to be invoked by display_regs, */ /* display_cregs and display_aregs */ /* Ivan Warren 2005/11/07 */ /*-------------------------------------------------------------------*/ static void display_regs32(char *hdr,U16 cpuad,U32 *r,int numcpus) { int i; for(i=0;i<16;i++) { if(!(i%4)) { if(i) { logmsg("\n"); } if(numcpus>1) { logmsg("CPU%4.4X: ",cpuad); } } if(i%4) { logmsg(" "); } logmsg("%s%2.2d=%8.8"I32_FMT"X",hdr,i,r[i]); } logmsg("\n"); } #if defined(_900) static void display_regs64(char *hdr,U16 cpuad,U64 *r,int numcpus) { int i; int rpl; if(numcpus>1) { rpl=2; } else { rpl=4; } for(i=0;i<16;i++) { if(!(i%rpl)) { if(i) { logmsg("\n"); } if(numcpus>1) { logmsg("CPU%4.4X: ",cpuad); } } if(i%rpl) { logmsg(" "); } logmsg("%s%1.1X=%16.16"I64_FMT"X",hdr,i,r[i]); } logmsg("\n"); } #endif /*-------------------------------------------------------------------*/ /* Display registers for the instruction display */ /*-------------------------------------------------------------------*/ void display_inst_regs (REGS *regs, BYTE *inst, BYTE opcode) { /* Display the general purpose registers */ if (!(opcode == 0xB3 || (opcode >= 0x20 && opcode <= 0x3F)) || (opcode == 0xB3 && ( (inst[1] >= 0x80 && inst[1] <= 0xCF) || (inst[1] >= 0xE1 && inst[1] <= 0xFE) ))) { display_regs (regs); if (sysblk.showregsfirst) logmsg("\n"); } /* Display control registers if appropriate */ if (!REAL_MODE(®s->psw) || opcode == 0xB2) { display_cregs (regs); if (sysblk.showregsfirst) logmsg("\n"); } /* Display access registers if appropriate */ if (!REAL_MODE(®s->psw) && ACCESS_REGISTER_MODE(®s->psw)) { display_aregs (regs); if (sysblk.showregsfirst) logmsg("\n"); } /* Display floating-point registers if appropriate */ if (opcode == 0xB3 || opcode == 0xED || (opcode >= 0x20 && opcode <= 0x3F) || (opcode >= 0x60 && opcode <= 0x70) || (opcode >= 0x78 && opcode <= 0x7F) || (opcode == 0xB2 && inst[1] == 0x2D) /*DXR*/ || (opcode == 0xB2 && inst[1] == 0x44) /*SQDR*/ || (opcode == 0xB2 && inst[1] == 0x45) /*SQER*/ ) { display_fregs (regs); if (sysblk.showregsfirst) logmsg("\n"); } } /*-------------------------------------------------------------------*/ /* Display general purpose registers */ /*-------------------------------------------------------------------*/ void display_regs (REGS *regs) { int i; U32 gprs[16]; #if defined(_900) U64 ggprs[16]; #endif #if defined(_900) if(regs->arch_mode != ARCH_900) { #endif for(i=0;i<16;i++) { gprs[i]=regs->GR_L(i); } display_regs32("GR",regs->cpuad,gprs,sysblk.cpus); #if defined(_900) } else { for(i=0;i<16;i++) { ggprs[i]=regs->GR_G(i); } display_regs64("R",regs->cpuad,ggprs,sysblk.cpus); } #endif } /* end function display_regs */ /*-------------------------------------------------------------------*/ /* Display control registers */ /*-------------------------------------------------------------------*/ void display_cregs (REGS *regs) { int i; U32 crs[16]; #if defined(_900) U64 gcrs[16]; #endif #if defined(_900) if(regs->arch_mode != ARCH_900) { #endif for(i=0;i<16;i++) { crs[i]=regs->CR_L(i); } display_regs32("CR",regs->cpuad,crs,sysblk.cpus); #if defined(_900) } else { for(i=0;i<16;i++) { gcrs[i]=regs->CR_G(i); } display_regs64("C",regs->cpuad,gcrs,sysblk.cpus); } #endif } /* end function display_cregs */ /*-------------------------------------------------------------------*/ /* Display access registers */ /*-------------------------------------------------------------------*/ void display_aregs (REGS *regs) { int i; U32 ars[16]; for(i=0;i<16;i++) { ars[i]=regs->AR(i); } display_regs32("AR",regs->cpuad,ars,sysblk.cpus); } /* end function display_aregs */ /*-------------------------------------------------------------------*/ /* Display floating point registers */ /*-------------------------------------------------------------------*/ void display_fregs (REGS *regs) { char cpustr[10] = {0}; /* "CPU:nnnn " or "" */ if(sysblk.cpus>1) sprintf(cpustr, "CPU%4.4X: ", regs->cpuad); if(regs->CR(0) & CR0_AFP) logmsg ( "%sFPR0=%8.8X %8.8X FPR2=%8.8X %8.8X\n" "%sFPR1=%8.8X %8.8X FPR3=%8.8X %8.8X\n" "%sFPR4=%8.8X %8.8X FPR6=%8.8X %8.8X\n" "%sFPR5=%8.8X %8.8X FPR7=%8.8X %8.8X\n" "%sFPR8=%8.8X %8.8X FP10=%8.8X %8.8X\n" "%sFPR9=%8.8X %8.8X FP11=%8.8X %8.8X\n" "%sFP12=%8.8X %8.8X FP14=%8.8X %8.8X\n" "%sFP13=%8.8X %8.8X FP15=%8.8X %8.8X\n" ,cpustr, regs->fpr[0], regs->fpr[1], regs->fpr[4], regs->fpr[5] ,cpustr, regs->fpr[2], regs->fpr[3], regs->fpr[6], regs->fpr[7] ,cpustr, regs->fpr[8], regs->fpr[9], regs->fpr[12], regs->fpr[13] ,cpustr, regs->fpr[10], regs->fpr[11], regs->fpr[14], regs->fpr[15] ,cpustr, regs->fpr[16], regs->fpr[17], regs->fpr[20], regs->fpr[21] ,cpustr, regs->fpr[18], regs->fpr[19], regs->fpr[22], regs->fpr[23] ,cpustr, regs->fpr[24], regs->fpr[25], regs->fpr[28], regs->fpr[29] ,cpustr, regs->fpr[26], regs->fpr[27], regs->fpr[30], regs->fpr[31] ); else logmsg ( "%sFPR0=%8.8X %8.8X FPR2=%8.8X %8.8X\n" "%sFPR4=%8.8X %8.8X FPR6=%8.8X %8.8X\n" ,cpustr, regs->fpr[0], regs->fpr[1], regs->fpr[2], regs->fpr[3] ,cpustr, regs->fpr[4], regs->fpr[5], regs->fpr[6], regs->fpr[7] ); } /* end function display_fregs */ /*-------------------------------------------------------------------*/ /* Display subchannel */ /*-------------------------------------------------------------------*/ void display_subchannel (DEVBLK *dev) { logmsg ("%4.4X:D/T=%4.4X", dev->devnum, dev->devtype); if (ARCH_370 == sysblk.arch_mode) { logmsg (" CSW=Flags:%2.2X CCW:%2.2X%2.2X%2.2X " "Stat:%2.2X%2.2X Count:%2.2X%2.2X\n", dev->csw[0], dev->csw[1], dev->csw[2], dev->csw[3], dev->csw[4], dev->csw[5], dev->csw[6], dev->csw[7]); } else { logmsg (" Subchannel_Number=%4.4X\n", dev->subchan); logmsg (" PMCW=IntParm:%2.2X%2.2X%2.2X%2.2X Flags:%2.2X%2.2X" " Dev:%2.2X%2.2X" " LPM:%2.2X PNOM:%2.2X LPUM:%2.2X PIM:%2.2X\n" " MBI:%2.2X%2.2X POM:%2.2X PAM:%2.2X" " CHPIDs:%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X" " Misc:%2.2X%2.2X%2.2X%2.2X\n", dev->pmcw.intparm[0], dev->pmcw.intparm[1], dev->pmcw.intparm[2], dev->pmcw.intparm[3], dev->pmcw.flag4, dev->pmcw.flag5, dev->pmcw.devnum[0], dev->pmcw.devnum[1], dev->pmcw.lpm, dev->pmcw.pnom, dev->pmcw.lpum, dev->pmcw.pim, dev->pmcw.mbi[0], dev->pmcw.mbi[1], dev->pmcw.pom, dev->pmcw.pam, dev->pmcw.chpid[0], dev->pmcw.chpid[1], dev->pmcw.chpid[2], dev->pmcw.chpid[3], dev->pmcw.chpid[4], dev->pmcw.chpid[5], dev->pmcw.chpid[6], dev->pmcw.chpid[7], dev->pmcw.zone, dev->pmcw.flag25, dev->pmcw.flag26, dev->pmcw.flag27); logmsg (" SCSW=Flags:%2.2X%2.2X SCHC:%2.2X%2.2X " "Stat:%2.2X%2.2X Count:%2.2X%2.2X " "CCW:%2.2X%2.2X%2.2X%2.2X\n", dev->scsw.flag0, dev->scsw.flag1, dev->scsw.flag2, dev->scsw.flag3, dev->scsw.unitstat, dev->scsw.chanstat, dev->scsw.count[0], dev->scsw.count[1], dev->scsw.ccwaddr[0], dev->scsw.ccwaddr[1], dev->scsw.ccwaddr[2], dev->scsw.ccwaddr[3]); } } /* end function display_subchannel */ /*-------------------------------------------------------------------*/ /* Parse a storage range or storage alteration operand */ /* */ /* Valid formats for a storage range operand are: */ /* startaddr */ /* startaddr-endaddr */ /* startaddr.length */ /* where startaddr, endaddr, and length are hexadecimal values. */ /* */ /* Valid format for a storage alteration operand is: */ /* startaddr=hexstring (up to 32 pairs of digits) */ /* */ /* Return values: */ /* 0 = operand contains valid storage range display syntax; */ /* start/end of range is returned in saddr and eaddr */ /* >0 = operand contains valid storage alteration syntax; */ /* return value is number of bytes to be altered; */ /* start/end/value are returned in saddr, eaddr, newval */ /* -1 = error message issued */ /*-------------------------------------------------------------------*/ static int parse_range (char *operand, U64 maxadr, U64 *sadrp, U64 *eadrp, BYTE *newval) { U64 opnd1, opnd2; /* Address/length operands */ U64 saddr, eaddr; /* Range start/end addresses */ int rc; /* Return code */ int n; /* Number of bytes altered */ int h1, h2; /* Hexadecimal digits */ char *s; /* Alteration value pointer */ BYTE delim; /* Operand delimiter */ BYTE c; /* Character work area */ rc = sscanf(operand, "%"I64_FMT"x%c%"I64_FMT"x%c", &opnd1, &delim, &opnd2, &c); /* Process storage alteration operand */ if (rc > 2 && delim == '=' && newval) { s = strchr (operand, '='); for (n = 0; n < 32;) { h1 = *(++s); if (h1 == '\0' || h1 == '#' ) break; if (h1 == SPACE || h1 == '\t') continue; h1 = toupper(h1); h2 = *(++s); h2 = toupper(h2); h1 = (h1 >= '0' && h1 <= '9') ? h1 - '0' : (h1 >= 'A' && h1 <= 'F') ? h1 - 'A' + 10 : -1; h2 = (h2 >= '0' && h2 <= '9') ? h2 - '0' : (h2 >= 'A' && h2 <= 'F') ? h2 - 'A' + 10 : -1; if (h1 < 0 || h2 < 0 || n >= 32) { logmsg (_("HHCPN143E Invalid value: %s\n"), s); return -1; } newval[n++] = (h1 << 4) | h2; } /* end for(n) */ saddr = opnd1; eaddr = saddr + n - 1; } else { /* Process storage range operand */ saddr = opnd1; if (rc == 1) { /* If only starting address is specified, default to 64 byte display, or less if near end of storage */ eaddr = saddr + 0x3F; if (eaddr > maxadr) eaddr = maxadr; } else { /* Ending address or length is specified */ if (rc != 3 || !(delim == '-' || delim == '.')) { logmsg (_("HHCPN144E Invalid operand: %s\n"), operand); return -1; } eaddr = (delim == '.') ? saddr + opnd2 - 1 : opnd2; } /* Set n=0 to indicate storage display only */ n = 0; } /* Check for valid range */ if (saddr > maxadr || eaddr > maxadr || eaddr < saddr) { logmsg (_("HHCPN145E Invalid range: %s\n"), operand); return -1; } /* Return start/end addresses and number of bytes altered */ *sadrp = saddr; *eadrp = eaddr; return n; } /* end function parse_range */ /*-------------------------------------------------------------------*/ /* get_connected_client return IP address and hostname of the */ /* client that is connected to this device */ /*-------------------------------------------------------------------*/ void get_connected_client (DEVBLK* dev, char** pclientip, char** pclientname) { *pclientip = NULL; *pclientname = NULL; obtain_lock (&dev->lock); if (dev->bs /* if device is a socket device, */ && dev->fd != -1) /* and a client is connected to it */ { *pclientip = strdup(dev->bs->clientip); *pclientname = strdup(dev->bs->clientname); } release_lock (&dev->lock); } /*-------------------------------------------------------------------*/ /* Return the address of a regs structure to be used for address */ /* translation. This address should be freed by the caller. */ /*-------------------------------------------------------------------*/ static REGS *copy_regs (REGS *regs) { REGS *newregs, *hostregs; size_t size; size = SIE_MODE(regs) ? 2*sizeof(REGS) : sizeof(REGS); newregs = malloc(size); if (newregs == NULL) { logmsg(_("HHCMS001E malloc failed for REGS copy: %s\n"), strerror(errno)); return NULL; } /* Perform partial copy and clear the TLB */ memcpy(newregs, regs, sysblk.regs_copy_len); memset(&newregs->tlb.vaddr, 0, TLBN * sizeof(DW)); newregs->ghostregs = 1; newregs->hostregs = newregs; newregs->guestregs = NULL; /* Copy host regs if in SIE mode */ if(SIE_MODE(newregs)) { hostregs = newregs + 1; memcpy(hostregs, regs->hostregs, sysblk.regs_copy_len); memset(&hostregs->tlb.vaddr, 0, TLBN * sizeof(DW)); hostregs->ghostregs = 1; hostregs->hostregs = hostregs; hostregs->guestregs = newregs; newregs->hostregs = hostregs; newregs->guestregs = newregs; } return newregs; } #endif /*!defined(_HSCMISC_C)*/ /*-------------------------------------------------------------------*/ /* Convert virtual address to absolute address */ /* */ /* Input: */ /* vaddr Virtual address to be translated */ /* arn Access register number */ /* regs CPU register context */ /* acctype Type of access (ACCTYPE_INSTFETCH, ACCTYPE_READ, */ /* or ACCTYPE_LRA) */ /* Output: */ /* aaptr Points to word in which abs address is returned */ /* siptr Points to word to receive indication of which */ /* STD or ASCE was used to perform the translation */ /* Return value: */ /* 0=translation successful, non-zero=exception code */ /* Note: */ /* To avoid unwanted alteration of the CPU register context */ /* during translation (for example, the TEA will be updated */ /* if a translation exception occurs), the translation is */ /* performed using a temporary copy of the CPU registers. */ /*-------------------------------------------------------------------*/ static U16 ARCH_DEP(virt_to_abs) (RADR *raptr, int *siptr, VADR vaddr, int arn, REGS *regs, int acctype) { int icode; if( !(icode = setjmp(regs->progjmp)) ) { int temp_arn = arn; // bypass longjmp clobber warning if (acctype == ACCTYPE_INSTFETCH) temp_arn = USE_INST_SPACE; if (SIE_MODE(regs)) memcpy(regs->hostregs->progjmp, regs->progjmp, sizeof(jmp_buf)); ARCH_DEP(logical_to_main) (vaddr, temp_arn, regs, acctype, 0); } *siptr = regs->dat.stid; *raptr = regs->hostregs->dat.raddr; return icode; } /* end function virt_to_abs */ /*-------------------------------------------------------------------*/ /* Display real storage (up to 16 bytes, or until end of page) */ /* Prefixes display by Rxxxxx: if draflag is 1 */ /* Returns number of characters placed in display buffer */ /*-------------------------------------------------------------------*/ static int ARCH_DEP(display_real) (REGS *regs, RADR raddr, char *buf, int draflag) { RADR aaddr; /* Absolute storage address */ int i, j; /* Loop counters */ int n = 0; /* Number of bytes in buffer */ char hbuf[40]; /* Hexadecimal buffer */ BYTE cbuf[17]; /* Character buffer */ BYTE c; /* Character work area */ #if defined(FEATURE_INTERVAL_TIMER) if(ITIMER_ACCESS(raddr,16)) ARCH_DEP(store_int_timer)(regs); #endif if (draflag) { n = sprintf (buf, "R:"F_RADR":", raddr); } aaddr = APPLY_PREFIXING (raddr, regs->PX); if (aaddr > regs->mainlim) { n += sprintf (buf+n, " Real address is not valid"); return n; } n += sprintf (buf+n, "K:%2.2X=", STORAGE_KEY(aaddr, regs)); memset (hbuf, SPACE, sizeof(hbuf)); memset (cbuf, SPACE, sizeof(cbuf)); for (i = 0, j = 0; i < 16; i++) { c = regs->mainstor[aaddr++]; j += sprintf (hbuf+j, "%2.2X", c); if ((aaddr & 0x3) == 0x0) hbuf[j++] = SPACE; c = guest_to_host(c); if (!isprint(c)) c = '.'; cbuf[i] = c; if ((aaddr & PAGEFRAME_BYTEMASK) == 0x000) break; } /* end for(i) */ n += sprintf (buf+n, "%36.36s %16.16s", hbuf, cbuf); return n; } /* end function display_real */ /*-------------------------------------------------------------------*/ /* Display virtual storage (up to 16 bytes, or until end of page) */ /* Returns number of characters placed in display buffer */ /*-------------------------------------------------------------------*/ static int ARCH_DEP(display_virt) (REGS *regs, VADR vaddr, char *buf, int ar, int acctype) { RADR raddr; /* Real address */ int n; /* Number of bytes in buffer */ int stid; /* Segment table indication */ U16 xcode; /* Exception code */ n = sprintf (buf, "%c:"F_VADR":", ar == USE_REAL_ADDR ? 'R' : 'V', vaddr); xcode = ARCH_DEP(virt_to_abs) (&raddr, &stid, vaddr, ar, regs, acctype); if (xcode == 0) { n += ARCH_DEP(display_real) (regs, raddr, buf+n, 0); } else n += sprintf (buf+n," Translation exception %4.4hX",xcode); return n; } /* end function display_virt */ /*-------------------------------------------------------------------*/ /* Disassemble real */ /*-------------------------------------------------------------------*/ static void ARCH_DEP(disasm_stor) (REGS *regs, char *opnd) { U64 saddr, eaddr; /* Range start/end addresses */ U64 maxadr; /* Highest real storage addr */ RADR raddr; /* Real storage address */ RADR aaddr; /* Absolute storage address */ int stid = -1; int len; /* Number of bytes to alter */ int i; /* Loop counter */ int ilc; BYTE inst[6]; /* Storage alteration value */ BYTE opcode; U16 xcode; char type; /* Set limit for address range */ #if defined(FEATURE_ESAME) maxadr = 0xFFFFFFFFFFFFFFFFULL; #else /*!defined(FEATURE_ESAME)*/ maxadr = 0x7FFFFFFF; #endif /*!defined(FEATURE_ESAME)*/ while((opnd && *opnd != '\0') && (*opnd == ' ' || *opnd == '\t')) opnd++; if(REAL_MODE(®s->psw)) type = 'R'; else type = 'V'; switch(toupper(*opnd)) { case 'R': /* real */ case 'V': /* virtual */ case 'P': /* primary */ case 'H': /* home */ type = toupper(*opnd); opnd++; } /* Parse the range or alteration operand */ len = parse_range (opnd, maxadr, &saddr, &eaddr, NULL); if (len < 0) return; /* Display real storage */ for (i = 0; i < 999 && saddr <= eaddr; i++) { if(type == 'R') raddr = saddr; else { if((xcode = ARCH_DEP(virt_to_abs) (&raddr, &stid, saddr, 0, regs, ACCTYPE_INSTFETCH) )) { logmsg(_("Storage not accessible code = %4.4X\n"), xcode); return; } } aaddr = APPLY_PREFIXING (raddr, regs->PX); if (aaddr > regs->mainlim) { logmsg(_("Addressing exception\n")); return; } opcode = regs->mainstor[aaddr]; ilc = ILC(opcode); if (aaddr + ilc > regs->mainlim) { logmsg(_("Addressing exception\n")); return; } memcpy(inst, regs->mainstor + aaddr, ilc); logmsg("%c" F_RADR ": %2.2X%2.2X", stid == TEA_ST_PRIMARY ? 'P' : stid == TEA_ST_HOME ? 'H' : stid == TEA_ST_SECNDRY ? 'S' : 'R', raddr, inst[0], inst[1]); if(ilc > 2) { logmsg("%2.2X%2.2X", inst[2], inst[3]); if(ilc > 4) logmsg("%2.2X%2.2X ", inst[4], inst[5]); else logmsg(" "); } else logmsg(" "); DISASM_INSTRUCTION(inst); saddr += ilc; } /* end for(i) */ } /* end function disasm_stor */ /*-------------------------------------------------------------------*/ /* Process real storage alter/display command */ /*-------------------------------------------------------------------*/ static void ARCH_DEP(alter_display_real) (char *opnd, REGS *regs) { U64 saddr, eaddr; /* Range start/end addresses */ U64 maxadr; /* Highest real storage addr */ RADR raddr; /* Real storage address */ RADR aaddr; /* Absolute storage address */ int len; /* Number of bytes to alter */ int i; /* Loop counter */ BYTE newval[32]; /* Storage alteration value */ char buf[100]; /* Message buffer */ /* Set limit for address range */ #if defined(FEATURE_ESAME) maxadr = 0xFFFFFFFFFFFFFFFFULL; #else /*!defined(FEATURE_ESAME)*/ maxadr = 0x7FFFFFFF; #endif /*!defined(FEATURE_ESAME)*/ /* Parse the range or alteration operand */ len = parse_range (opnd, maxadr, &saddr, &eaddr, newval); if (len < 0) return; raddr = saddr; /* Alter real storage */ if (len > 0) { for (i = 0; i < len && raddr+i <= regs->mainlim; i++) { aaddr = raddr + i; aaddr = APPLY_PREFIXING (aaddr, regs->PX); regs->mainstor[aaddr] = newval[i]; STORAGE_KEY(aaddr, regs) |= (STORKEY_REF | STORKEY_CHANGE); } /* end for(i) */ } /* Display real storage */ for (i = 0; i < 999 && raddr <= eaddr; i++) { ARCH_DEP(display_real) (regs, raddr, buf, 1); logmsg ("%s\n", buf); raddr += 16; } /* end for(i) */ } /* end function alter_display_real */ /*-------------------------------------------------------------------*/ /* Process virtual storage alter/display command */ /*-------------------------------------------------------------------*/ static void ARCH_DEP(alter_display_virt) (char *opnd, REGS *regs) { U64 saddr, eaddr; /* Range start/end addresses */ U64 maxadr; /* Highest virt storage addr */ VADR vaddr; /* Virtual storage address */ RADR raddr; /* Real storage address */ RADR aaddr; /* Absolute storage address */ int stid; /* Segment table indication */ int len; /* Number of bytes to alter */ int i; /* Loop counter */ int n; /* Number of bytes in buffer */ int arn = 0; /* Access register number */ U16 xcode; /* Exception code */ BYTE newval[32]; /* Storage alteration value */ char buf[100]; /* Message buffer */ /* Set limit for address range */ #if defined(FEATURE_ESAME) maxadr = 0xFFFFFFFFFFFFFFFFULL; #else /*!defined(FEATURE_ESAME)*/ maxadr = 0x7FFFFFFF; #endif /*!defined(FEATURE_ESAME)*/ while((opnd && *opnd != '\0') && (*opnd == ' ' || *opnd == '\t')) opnd++; switch(toupper(*opnd)) { case 'P': /* primary */ arn = USE_PRIMARY_SPACE; opnd++; break; case 'S': /* secondary */ arn = USE_SECONDARY_SPACE; opnd++; break; case 'H': /* home */ arn = USE_HOME_SPACE; opnd++; break; } /* Parse the range or alteration operand */ len = parse_range (opnd, maxadr, &saddr, &eaddr, newval); if (len < 0) return; vaddr = saddr; /* Alter virtual storage */ if (len > 0 && ARCH_DEP(virt_to_abs) (&raddr, &stid, vaddr, arn, regs, ACCTYPE_LRA) == 0 && ARCH_DEP(virt_to_abs) (&raddr, &stid, eaddr, arn, regs, ACCTYPE_LRA) == 0) { for (i = 0; i < len && raddr+i <= regs->mainlim; i++) { ARCH_DEP(virt_to_abs) (&raddr, &stid, vaddr+i, arn, regs, ACCTYPE_LRA); aaddr = APPLY_PREFIXING (raddr, regs->PX); regs->mainstor[aaddr] = newval[i]; STORAGE_KEY(aaddr, regs) |= (STORKEY_REF | STORKEY_CHANGE); } /* end for(i) */ } /* Display virtual storage */ for (i = 0; i < 999 && vaddr <= eaddr; i++) { if (i == 0 || (vaddr & PAGEFRAME_BYTEMASK) < 16) { xcode = ARCH_DEP(virt_to_abs) (&raddr, &stid, vaddr, arn, regs, ACCTYPE_LRA); n = sprintf (buf, "V:"F_VADR" ", vaddr); if (REAL_MODE(®s->psw)) n += sprintf (buf+n, "(dat off)"); else if (stid == TEA_ST_PRIMARY) n += sprintf (buf+n, "(primary)"); else if (stid == TEA_ST_SECNDRY) n += sprintf (buf+n, "(secondary)"); else if (stid == TEA_ST_HOME) n += sprintf (buf+n, "(home)"); else n += sprintf (buf+n, "(AR%2.2d)", arn); if (xcode == 0) n += sprintf (buf+n, " R:"F_RADR, raddr); logmsg ("%s\n", buf); } ARCH_DEP(display_virt) (regs, vaddr, buf, arn, ACCTYPE_LRA); logmsg ("%s\n", buf); vaddr += 16; } /* end for(i) */ } /* end function alter_display_virt */ /*-------------------------------------------------------------------*/ /* Display instruction */ /*-------------------------------------------------------------------*/ void ARCH_DEP(display_inst) (REGS *iregs, BYTE *inst) { QWORD qword; /* Doubleword work area */ BYTE opcode; /* Instruction operation code*/ int ilc; /* Instruction length */ #ifdef DISPLAY_INSTRUCTION_OPERANDS int b1=-1, b2=-1, x1; /* Register numbers */ VADR addr1 = 0, addr2 = 0; /* Operand addresses */ #endif /*DISPLAY_INSTRUCTION_OPERANDS*/ char buf[256]; /* Message buffer */ int n; /* Number of bytes in buffer */ REGS *regs; /* Copied regs */ if (iregs->ghostregs) regs = iregs; else if ((regs = copy_regs(iregs)) == NULL) return; #if defined(_FEATURE_SIE) if(SIE_MODE(regs)) logmsg(_("SIE: ")); #endif /*defined(_FEATURE_SIE)*/ #if 0 #if _GEN_ARCH == 370 logmsg("S/370 "); #elif _GEN_ARCH == 390 logmsg("ESA/390 "); #else logmsg("Z/Arch "); #endif #endif /* Display the PSW */ memset (qword, 0x00, sizeof(qword)); copy_psw (regs, qword); if(sysblk.cpus>1) { n=sprintf(buf,"CPU%4.4X: ",regs->cpuad); } else { n=0; } n += sprintf (buf+n, "PSW=%2.2X%2.2X%2.2X%2.2X %2.2X%2.2X%2.2X%2.2X ", qword[0], qword[1], qword[2], qword[3], qword[4], qword[5], qword[6], qword[7]); #if defined(FEATURE_ESAME) n += sprintf (buf + n, "%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X ", qword[8], qword[9], qword[10], qword[11], qword[12], qword[13], qword[14], qword[15]); #endif /*defined(FEATURE_ESAME)*/ /* Exit if instruction is not valid */ if (inst == NULL) { logmsg (_("%sInstruction fetch error\n"), buf); display_regs (regs); if (!iregs->ghostregs) free(regs); return; } /* Extract the opcode and determine the instruction length */ opcode = inst[0]; ilc = ILC(opcode); /* Show registers associated with the instruction */ if (sysblk.showregsfirst) display_inst_regs (regs, inst, opcode); /* Display the instruction */ n += sprintf (buf+n, "INST=%2.2X%2.2X", inst[0], inst[1]); if (ilc > 2) n += sprintf (buf+n, "%2.2X%2.2X", inst[2], inst[3]); if (ilc > 4) n += sprintf (buf+n, "%2.2X%2.2X", inst[4], inst[5]); logmsg ("%s %s", buf,(ilc<4) ? " " : (ilc<6) ? " " : ""); DISASM_INSTRUCTION(inst); #ifdef DISPLAY_INSTRUCTION_OPERANDS /* Process the first storage operand */ if (ilc > 2 && opcode != 0x84 && opcode != 0x85 && opcode != 0xA5 && opcode != 0xA7 && opcode != 0xB3 && opcode != 0xC0 && opcode != 0xC4 && opcode != 0xC6 && opcode != 0xEC) { /* Calculate the effective address of the first operand */ b1 = inst[2] >> 4; addr1 = ((inst[2] & 0x0F) << 8) | inst[3]; if (b1 != 0) { addr1 += regs->GR(b1); addr1 &= ADDRESS_MAXWRAP(regs); } /* Apply indexing for RX/RXE/RXF instructions */ if ((opcode >= 0x40 && opcode <= 0x7F) || opcode == 0xB1 || opcode == 0xE3 || opcode == 0xED) { x1 = inst[1] & 0x0F; if (x1 != 0) { addr1 += regs->GR(x1); addr1 &= ADDRESS_MAXWRAP(regs); } } } /* Process the second storage operand */ if (ilc > 4 && opcode != 0xC0 && opcode != 0xC4 && opcode != 0xC6 && opcode != 0xE3 && opcode != 0xEB && opcode != 0xEC && opcode != 0xED) { /* Calculate the effective address of the second operand */ b2 = inst[4] >> 4; addr2 = ((inst[4] & 0x0F) << 8) | inst[5]; if (b2 != 0) { addr2 += regs->GR(b2); addr2 &= ADDRESS_MAXWRAP(regs); } } /* Calculate the operand addresses for MVCL(E) and CLCL(E) */ if (opcode == 0x0E || opcode == 0x0F || opcode == 0xA8 || opcode == 0xA9) { b1 = inst[1] >> 4; addr1 = regs->GR(b1) & ADDRESS_MAXWRAP(regs); b2 = inst[1] & 0x0F; addr2 = regs->GR(b2) & ADDRESS_MAXWRAP(regs); } /* Calculate the operand addresses for RRE instructions */ if ((opcode == 0xB2 && ((inst[1] >= 0x20 && inst[1] <= 0x2F) || (inst[1] >= 0x40 && inst[1] <= 0x6F) || (inst[1] >= 0xA0 && inst[1] <= 0xAF))) || opcode == 0xB9) { b1 = inst[3] >> 4; addr1 = regs->GR(b1) & ADDRESS_MAXWRAP(regs); b2 = inst[3] & 0x0F; if (inst[1] >= 0x29 && inst[1] <= 0x2C) addr2 = regs->GR(b2) & ADDRESS_MAXWRAP_E(regs); else if (inst[1] >= 0x29 && inst[1] <= 0x2C) addr2 = regs->GR(b2) & ADDRESS_MAXWRAP(regs); else addr2 = regs->GR(b2) & ADDRESS_MAXWRAP(regs); } /* Calculate the operand address for RIL_A instructions */ if ((opcode == 0xC0 && ((inst[1] & 0x0F) == 0x00 || (inst[1] & 0x0F) == 0x04 || (inst[1] & 0x0F) == 0x05)) || opcode == 0xC4 || opcode == 0xC6) { S64 offset = 2LL*(S32)(fetch_fw(inst+2)); addr1 = (likely(!regs->execflag)) ? PSW_IA(regs, offset) : \ (regs->ET + offset) & ADDRESS_MAXWRAP(regs); b1 = 0; } /* Display storage at first storage operand location */ if (b1 >= 0) { if(REAL_MODE(®s->psw)) n = ARCH_DEP(display_virt) (regs, addr1, buf, USE_REAL_ADDR, ACCTYPE_READ); else n = ARCH_DEP(display_virt) (regs, addr1, buf, b1, (opcode == 0x44 #if defined(FEATURE_EXECUTE_EXTENSIONS_FACILITY) || (opcode == 0xc6 && !(inst[1] & 0x0f)) #endif /*defined(FEATURE_EXECUTE_EXTENSIONS_FACILITY)*/ ? ACCTYPE_INSTFETCH : opcode == 0xB1 ? ACCTYPE_LRA : ACCTYPE_READ)); if(sysblk.cpus>1) { logmsg ("CPU%4.4X: ", regs->cpuad); } logmsg ("%s\n", buf); } /* Display storage at second storage operand location */ if (b2 >= 0) { if( (REAL_MODE(®s->psw) || (opcode == 0xB2 && inst[1] == 0x4B) /*LURA*/ || (opcode == 0xB2 && inst[1] == 0x46) /*STURA*/ || (opcode == 0xB9 && inst[1] == 0x05) /*LURAG*/ || (opcode == 0xB9 && inst[1] == 0x25))) /*STURG*/ n = ARCH_DEP(display_virt) (regs, addr2, buf, USE_REAL_ADDR, ACCTYPE_READ); else n = ARCH_DEP(display_virt) (regs, addr2, buf, b2, ACCTYPE_READ); if(sysblk.cpus>1) { logmsg ("CPU%4.4X: ", regs->cpuad); } logmsg ("%s\n", buf); } #endif /*DISPLAY_INSTRUCTION_OPERANDS*/ /* Show registers associated with the instruction */ if (!sysblk.showregsfirst && !sysblk.showregsnone) display_inst_regs (regs, inst, opcode); if (!iregs->ghostregs) free (regs); } /* end function display_inst */ #if !defined(_GEN_ARCH) #if defined(_ARCHMODE2) #define _GEN_ARCH _ARCHMODE2 #include "hscmisc.c" #endif #if defined(_ARCHMODE3) #undef _GEN_ARCH #define _GEN_ARCH _ARCHMODE3 #include "hscmisc.c" #endif /*-------------------------------------------------------------------*/ /* Wrappers for architecture-dependent functions */ /*-------------------------------------------------------------------*/ void alter_display_real (char *opnd, REGS *regs) { switch(sysblk.arch_mode) { #if defined(_370) case ARCH_370: s370_alter_display_real (opnd, regs); break; #endif #if defined(_390) case ARCH_390: s390_alter_display_real (opnd, regs); break; #endif #if defined(_900) case ARCH_900: z900_alter_display_real (opnd, regs); break; #endif } } /* end function alter_display_real */ void alter_display_virt (char *opnd, REGS *iregs) { REGS *regs; if (iregs->ghostregs) regs = iregs; else if ((regs = copy_regs(iregs)) == NULL) return; switch(sysblk.arch_mode) { #if defined(_370) case ARCH_370: s370_alter_display_virt (opnd, regs); break; #endif #if defined(_390) case ARCH_390: s390_alter_display_virt (opnd, regs); break; #endif #if defined(_900) case ARCH_900: z900_alter_display_virt (opnd, regs); break; #endif } if (!iregs->ghostregs) free(regs); } /* end function alter_display_virt */ void display_inst(REGS *iregs, BYTE *inst) { REGS *regs; if (iregs->ghostregs) regs = iregs; else if ((regs = copy_regs(iregs)) == NULL) return; switch(regs->arch_mode) { #if defined(_370) case ARCH_370: s370_display_inst(regs,inst); break; #endif #if defined(_390) case ARCH_390: s390_display_inst(regs,inst); break; #endif #if defined(_900) case ARCH_900: z900_display_inst(regs,inst); break; #endif } if (!iregs->ghostregs) free (regs); } void disasm_stor(REGS *iregs, char *opnd) { REGS *regs; if (iregs->ghostregs) regs = iregs; else if ((regs = copy_regs(iregs)) == NULL) return; switch(regs->arch_mode) { #if defined(_370) case ARCH_370: s370_disasm_stor(regs,opnd); break; #endif #if defined(_390) case ARCH_390: s390_disasm_stor(regs,opnd); break; #endif #if defined(_900) case ARCH_900: z900_disasm_stor(regs,opnd); break; #endif } if (!iregs->ghostregs) free(regs); } /*-------------------------------------------------------------------*/ /* Execute a Unix or Windows command */ /* Returns the system command status code */ /*-------------------------------------------------------------------*/ int herc_system (char* command) { #if HOW_TO_IMPLEMENT_SH_COMMAND == USE_ANSI_SYSTEM_API_FOR_SH_COMMAND return system(command); #elif HOW_TO_IMPLEMENT_SH_COMMAND == USE_W32_POOR_MANS_FORK #define SHELL_CMD_SHIM_PGM "conspawn " int rc = strlen(SHELL_CMD_SHIM_PGM) + strlen(command) + 1; char* pszNewCommandLine = malloc( rc ); strlcpy( pszNewCommandLine, SHELL_CMD_SHIM_PGM, rc ); strlcat( pszNewCommandLine, command, rc ); rc = w32_poor_mans_fork( pszNewCommandLine, NULL ); free( pszNewCommandLine ); return rc; #elif HOW_TO_IMPLEMENT_SH_COMMAND == USE_FORK_API_FOR_SH_COMMAND extern char **environ; int pid, status; if (command == 0) return 1; pid = fork(); if (pid == -1) return -1; if (pid == 0) { char *argv[4]; /* Redirect stderr (screen) to hercules log task */ dup2(STDOUT_FILENO, STDERR_FILENO); /* Drop ROOT authority (saved uid) */ SETMODE(TERM); DROP_ALL_CAPS(); argv[0] = "sh"; argv[1] = "-c"; argv[2] = command; argv[3] = 0; execve("/bin/sh", argv, environ); exit(127); } do { if (waitpid(pid, &status, 0) == -1) { if (errno != EINTR) return -1; } else return status; } while(1); #else #error 'HOW_TO_IMPLEMENT_SH_COMMAND' not #defined correctly #endif } /* end function herc_system */ #endif /*!defined(_GEN_ARCH)*/ hercules-3.07/hscutl.c000644 000765 000765 00000057240 11157241226 016422 0ustar00jmaynardjmaynard000000 000000 /*********************************************************************/ /* HSCUTL.C -- Implementation of functions used in hercules that */ /* may be missing on some platform ports, or other convenient mis- */ /* laneous global utility functions. */ /*********************************************************************/ /* (c) 2003-2006 Ivan Warren & Others -- Released under the Q Public */ /* License -- This file is portion of the HERCULES S/370, S/390 and */ /* z/Architecture emulator */ /*********************************************************************/ // $Id: hscutl.c 5177 2009-02-13 20:41:07Z jj $ // // $Log$ // Revision 1.28 2008/07/10 18:29:02 fish // Fix crash in 'resolve_symbol_string' when incomplete symbol passed // (e.g. "$(x" for example) // // Revision 1.27 2008/02/19 11:49:19 ivan // - Move setting of CPU priority after spwaning timer thread // - Added support for Posix 1003.1e capabilities // // Revision 1.26 2007/11/11 20:38:24 rbowler // Suppress msg HHCUT001I if keepalive successful // // Revision 1.25 2007/01/12 14:38:47 rbowler // Error checking for Unix keepalive // // Revision 1.24 2007/01/10 15:12:11 rbowler // Console keepalive for Unix // // Revision 1.23 2007/01/10 09:32:39 fish // Enable connection keep-alive to try and detect 3270 clients that // have died (MSVC only right now; don't know how to do it on *nix) // // Revision 1.22 2006/12/08 09:43:26 jj // Add CVS message log // #include "hstdinc.h" #define _HSCUTL_C_ #define _HUTIL_DLL_ #include "hercules.h" #if defined(NEED_GETOPT_WRAPPER) /* GETOPT DYNAMIC LINKING KLUDGE... For some odd reason, on some platforms (namely windows & possibly Darwin) dynamically linking to the libc imports STATIC versions of 'getopt' and 'getopt_long' into the link-edited shared library. If any program then link edits against BOTH the shared library AND libc, then the linker complains about 'getopt' and/or 'getopt_long' being defined multiple times. In an effort to overcome this, I am defining a stub version of 'getopt' and 'getop_long' that can be called by loadable modules instead. -- Ivan ** ZZ FIXME: the above needs to be re-verified to see whether it is ** still true or not. I suspect it may no longer be true due to the ** subtle bug fixed in the "_HC_CHECK_NEED_GETOPT_WRAPPER" m4 macro ** in the "./autoconf/hercules.m4" member. -- Fish, Feb 2005 */ int herc_opterr=0; char *herc_optarg=NULL; int herc_optopt=0; int herc_optind=1; #if defined(NEED_GETOPT_OPTRESET) int herc_optreset=0; #endif DLL_EXPORT int herc_getopt(int ac,char * const av[],const char *opt) { int rc; #if defined(NEED_GETOPT_OPTRESET) optreset=herc_optreset; #endif rc=getopt(ac,av,opt); #if defined(NEED_GETOPT_OPTRESET) herc_optreset=optreset; #endif herc_optarg=optarg; herc_optind=optind; herc_optopt=optind; herc_opterr=optind; return(rc); } #if defined(HAVE_GETOPT_LONG) struct option; // (fwd ref) int getopt_long (int, char *const *, const char *, const struct option *, int *); struct option; // (fwd ref) DLL_EXPORT int herc_getopt_long(int ac, char * const av[], const char *opt, const struct option *lo, int *li) { int rc; #if defined(NEED_GETOPT_OPTRESET) optreset=herc_optreset; #endif optind=herc_optind; rc=getopt_long(ac,av,opt,lo,li); #if defined(NEED_GETOPT_OPTRESET) herc_optreset=optreset; #endif herc_optarg=optarg; herc_optind=optind; herc_optopt=optind; herc_opterr=optind; return(rc); } #endif /* HAVE_GETOPT_LONG */ #endif /* NEED_GETOPT_WRAPPER */ #if !defined(WIN32) && !defined(HAVE_STRERROR_R) static LOCK strerror_lock; DLL_EXPORT void strerror_r_init(void) { initialize_lock(&strerror_lock); } DLL_EXPORT int strerror_r(int err,char *bfr,size_t sz) { char *wbfr; obtain_lock(&strerror_lock); wbfr=strerror(err); if(wbfr==NULL || (int)wbfr==-1) { release_lock(&strerror_lock); return(-1); } if(sz<=strlen(wbfr)) { errno=ERANGE; release_lock(&strerror_lock); return(-1); } strncpy(bfr,wbfr,sz); release_lock(&strerror_lock); return(0); } #endif // !defined(HAVE_STRERROR_R) #if !defined(HAVE_STRLCPY) /* $OpenBSD: strlcpy.c,v 1.8 2003/06/17 21:56:24 millert Exp $ */ /* ** NOTE ** returns 'size_t' and NOT 'char*' like strncpy! */ /* * Copyright (c) 1998 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, 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. */ #if defined(LIBC_SCCS) && !defined(lint) static char *rcsid = "$OpenBSD: strlcpy.c,v 1.8 2003/06/17 21:56:24 millert Exp $"; #endif /* LIBC_SCCS and not lint */ /* * Copy src to string dst of size siz. At most siz-1 characters * will be copied. Always NUL terminates (unless siz == 0). * Returns strlen(src); if retval >= siz, truncation occurred. */ /* ** NOTE ** returns 'size_t' and NOT 'char*' like strncpy! */ DLL_EXPORT size_t strlcpy(char *dst, const char *src, size_t siz) { register char *d = dst; register const char *s = src; register size_t n = siz; /* Copy as many bytes as will fit */ if (n != 0 && --n != 0) { do { if ((*d++ = *s++) == 0) break; } while (--n != 0); } /* Not enough room in dst, add NUL and traverse rest of src */ if (n == 0) { if (siz != 0) *d = '\0'; /* NUL-terminate dst */ while (*s++) ; } return(s - src - 1); /* count does not include NUL */ } #endif // !defined(HAVE_STRLCPY) #if !defined(HAVE_STRLCAT) /* $OpenBSD: strlcat.c,v 1.11 2003/06/17 21:56:24 millert Exp $ */ /* ** NOTE ** returns 'size_t' and NOT 'char*' like strncpy! */ /* * Copyright (c) 1998 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, 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. */ #if defined(LIBC_SCCS) && !defined(lint) static char *rcsid = "$OpenBSD: strlcat.c,v 1.11 2003/06/17 21:56:24 millert Exp $"; #endif /* LIBC_SCCS and not lint */ /* * Appends src to string dst of size siz (unlike strncat, siz is the * full size of dst, not space left). At most siz-1 characters * will be copied. Always NUL terminates (unless siz <= strlen(dst)). * Returns strlen(src) + MIN(siz, strlen(initial dst)). * If retval >= siz, truncation occurred. */ /* ** NOTE ** returns 'size_t' and NOT 'char*' like strncat! */ DLL_EXPORT size_t strlcat(char *dst, const char *src, size_t siz) { register char *d = dst; register const char *s = src; register size_t n = siz; size_t dlen; /* Find the end of dst and adjust bytes left but don't go past end */ while (n-- != 0 && *d != '\0') d++; dlen = d - dst; n = siz - dlen; if (n == 0) return(dlen + strlen(s)); while (*s != '\0') { if (n != 1) { *d++ = *s; n--; } s++; } *d = '\0'; return(dlen + (s - src)); /* count does not include NUL */ } #endif // !defined(HAVE_STRLCAT) #if defined(OPTION_CONFIG_SYMBOLS) /* The following structures are defined herein because they are private structures */ /* that MUST be opaque to the outside world */ typedef struct _SYMBOL_TOKEN { char *var; char *val; } SYMBOL_TOKEN; #define SYMBOL_TABLE_INCREMENT 256 #define SYMBOL_BUFFER_GROWTH 256 #define MAX_SYMBOL_SIZE 31 #define SYMBOL_QUAL_1 '$' #define SYMBOL_QUAL_2 '(' #define SYMBOL_QUAL_3 ')' static SYMBOL_TOKEN **symbols=NULL; static int symbol_count=0; static int symbol_max=0; /* This function retrieves or allocates a new SYMBOL_TOKEN */ static SYMBOL_TOKEN *get_symbol_token(const char *sym,int alloc) { SYMBOL_TOKEN *tok; int i; for(i=0;ivar,sym)==0) { return(symbols[i]); } } if(!alloc) { return(NULL); } if(symbol_count>=symbol_max) { symbol_max+=SYMBOL_TABLE_INCREMENT; if(symbols==NULL) { symbols=malloc(sizeof(SYMBOL_TOKEN *)*symbol_max); if(symbols==NULL) { symbol_max=0; symbol_count=0; return(NULL); } } else { symbols=realloc(symbols,sizeof(SYMBOL_TOKEN *)*symbol_max); if(symbols==NULL) { symbol_max=0; symbol_count=0; return(NULL); } } } tok=malloc(sizeof(SYMBOL_TOKEN)); if(tok==NULL) { return(NULL); } tok->var=malloc(MIN(MAX_SYMBOL_SIZE+1,strlen(sym)+1)); if(tok->var==NULL) { free(tok); return(NULL); } strncpy(tok->var,sym,MIN(MAX_SYMBOL_SIZE+1,strlen(sym)+1)); tok->val=NULL; symbols[symbol_count]=tok; symbol_count++; return(tok); } DLL_EXPORT void set_symbol(const char *sym,const char *value) { SYMBOL_TOKEN *tok; tok=get_symbol_token(sym,1); if(tok==NULL) { return; } if(tok->val!=NULL) { free(tok->val); } tok->val=malloc(strlen(value)+1); if(tok->val==NULL) { return; } strcpy(tok->val,value); return; } DLL_EXPORT const char *get_symbol(const char *sym) { char *val; SYMBOL_TOKEN *tok; tok=get_symbol_token(sym,0); if(tok==NULL) { val=getenv(sym); return(val); } return(tok->val); } static void buffer_addchar_and_alloc(char **bfr,char c,int *ix_p,int *max_p) { char *buf; int ix; int mx; buf=*bfr; ix=*ix_p; mx=*max_p; if((ix+1)>=mx) { mx+=SYMBOL_BUFFER_GROWTH; if(buf==NULL) { buf=malloc(mx); } else { buf=realloc(buf,mx); } *bfr=buf; *max_p=mx; } buf[ix++]=c; buf[ix]=0; *ix_p=ix; return; } static void append_string(char **bfr,char *text,int *ix_p,int *max_p) { int i; for(i=0;text[i]!=0;i++) { buffer_addchar_and_alloc(bfr,text[i],ix_p,max_p); } return; } static void append_symbol(char **bfr,char *sym,int *ix_p,int *max_p) { char *txt; txt=(char *)get_symbol(sym); if(txt==NULL) { txt="**UNRESOLVED**"; } append_string(bfr,txt,ix_p,max_p); return; } DLL_EXPORT char *resolve_symbol_string(const char *text) { char *resstr; int curix,maxix; char cursym[MAX_SYMBOL_SIZE+1]; int cursymsize=0; int q1,q2; int i; /* Quick check - look for QUAL1 ('$') or QUAL2 ('(').. if not found, return the string as-is */ if(!strchr(text,SYMBOL_QUAL_1) || !strchr(text,SYMBOL_QUAL_2)) { /* Malloc anyway - the caller will free() */ resstr=malloc(strlen(text)+1); strcpy(resstr,text); return(resstr); } q1=0; q2=0; curix=0; maxix=0; resstr=NULL; for(i=0;text[i]!=0;i++) { if(q1) { if(text[i]==SYMBOL_QUAL_2) { q2=1; q1=0; continue; } q1=0; buffer_addchar_and_alloc(&resstr,SYMBOL_QUAL_1,&curix,&maxix); buffer_addchar_and_alloc(&resstr,text[i],&curix,&maxix); continue; } if(q2) { if(text[i]==SYMBOL_QUAL_3) { append_symbol(&resstr,cursym,&curix,&maxix); cursymsize=0; q2=0; continue; } if(cursymsizevar, tok->val ? tok->val : ""); } return; } DLL_EXPORT void kill_all_symbols(void) { SYMBOL_TOKEN *tok; int i; for(i=0;ival); if(tok->var!=NULL) { free(tok->var); } free(tok); symbols[i]=NULL; } free(symbols); symbol_count=0; symbol_max=0; return; } #endif /* #if defined(OPTION_CONFIG_SYMBOLS) */ /* Subtract 'beg_timeval' from 'end_timeval' yielding 'dif_timeval' */ /* Return code: success == 0, error == -1 (difference was negative) */ DLL_EXPORT int timeval_subtract ( struct timeval *beg_timeval, struct timeval *end_timeval, struct timeval *dif_timeval ) { struct timeval begtime; struct timeval endtime; ASSERT ( beg_timeval -> tv_sec >= 0 && beg_timeval -> tv_usec >= 0 ); ASSERT ( end_timeval -> tv_sec >= 0 && end_timeval -> tv_usec >= 0 ); memcpy(&begtime,beg_timeval,sizeof(struct timeval)); memcpy(&endtime,end_timeval,sizeof(struct timeval)); dif_timeval->tv_sec = endtime.tv_sec - begtime.tv_sec; if (endtime.tv_usec >= begtime.tv_usec) { dif_timeval->tv_usec = endtime.tv_usec - begtime.tv_usec; } else { dif_timeval->tv_sec--; dif_timeval->tv_usec = (endtime.tv_usec + 1000000) - begtime.tv_usec; } return ((dif_timeval->tv_sec < 0 || dif_timeval->tv_usec < 0) ? -1 : 0); } /* Add 'dif_timeval' to 'accum_timeval' (use to accumulate elapsed times) */ /* Return code: success == 0, error == -1 (accum_timeval result negative) */ DLL_EXPORT int timeval_add ( struct timeval *dif_timeval, struct timeval *accum_timeval ) { ASSERT ( dif_timeval -> tv_sec >= 0 && dif_timeval -> tv_usec >= 0 ); ASSERT ( accum_timeval -> tv_sec >= 0 && accum_timeval -> tv_usec >= 0 ); accum_timeval->tv_sec += dif_timeval->tv_sec; accum_timeval->tv_usec += dif_timeval->tv_usec; if (accum_timeval->tv_usec > 1000000) { int nsec = accum_timeval->tv_usec / 1000000; accum_timeval->tv_sec += nsec; accum_timeval->tv_usec -= nsec * 1000000; } return ((accum_timeval->tv_sec < 0 || accum_timeval->tv_usec < 0) ? -1 : 0); } /* Easier to use timed_wait_condition that waits for the specified relative amount of time without you having to build an absolute timeout time yourself */ DLL_EXPORT int timed_wait_condition_relative_usecs ( COND* pCOND, // ptr to condition to wait on LOCK* pLOCK, // ptr to controlling lock (must be held!) U32 usecs, // max #of microseconds to wait struct timeval* pTV // [OPTIONAL] ptr to tod value (may be NULL) ) { struct timespec timeout_timespec; struct timeval now; if (!pTV) { pTV = &now; gettimeofday( pTV, NULL ); } timeout_timespec.tv_sec = pTV->tv_sec + ( usecs / 1000000 ); timeout_timespec.tv_nsec = pTV->tv_usec + ( usecs % 1000000 ); if ( timeout_timespec.tv_nsec > 1000000 ) { timeout_timespec.tv_sec += timeout_timespec.tv_nsec / 1000000; timeout_timespec.tv_nsec %= 1000000; } timeout_timespec.tv_nsec *= 1000; return timed_wait_condition( pCOND, pLOCK, &timeout_timespec ); } /********************************************************************* The following couple of Hercules 'utility' functions may be defined elsewhere depending on which host platform we're being built for... For Windows builds (e.g. MingW32), the functionality for the below functions is defined in 'w32util.c'. For other host build platforms (e.g. Linux, Apple, etc), the functionality for the below functions is defined right here in 'hscutil.c'... *********************************************************************/ #if !defined(_MSVC_) /* THIS module (hscutil.c) is to provide the below functionality.. */ /* Returns outpath as a host filesystem compatible filename path. This is a Cygwin-to-MSVC transitional period helper function. On non-Windows platforms it simply copies inpath to outpath. On Windows it converts inpath of the form "/cygdrive/x/foo.bar" to outpath in the form "x:/foo.bar" for Windows compatibility. */ DLL_EXPORT char *hostpath( char *outpath, const char *inpath, size_t buffsize ) { if (inpath && outpath && buffsize > 1) strlcpy( outpath, inpath, buffsize ); else if (outpath && buffsize) *outpath = 0; return outpath; } /* Poor man's "fcntl( fd, F_GETFL )"... */ /* (only returns access-mode flags and not any others) */ DLL_EXPORT int get_file_accmode_flags( int fd ) { int flags = fcntl( fd, F_GETFL ); return ( flags & O_ACCMODE ); } /* Set socket to blocking or non-blocking mode... */ DLL_EXPORT int socket_set_blocking_mode( int sfd, int blocking_mode ) { int flags = fcntl( sfd, F_GETFL ); if ( blocking_mode ) flags &= ~O_NONBLOCK; else flags |= O_NONBLOCK; return fcntl( sfd, F_SETFL, flags ); } /* Initialize/Deinitialize sockets package... */ int socket_init ( void ) { return 0; } DLL_EXPORT int socket_deinit ( void ) { return 0; } /* Determine whether a file descriptor is a socket or not... */ /* (returns 1==true if it's a socket, 0==false otherwise) */ DLL_EXPORT int socket_is_socket( int sfd ) { struct stat st; return ( fstat( sfd, &st ) == 0 && S_ISSOCK( st.st_mode ) ); } /* Set the SO_KEEPALIVE option and timeout values for a socket connection to detect when client disconnects */ void socket_keepalive( int sfd, int idle_time, int probe_interval, int probe_count ) { int rc, optval = 1; rc = setsockopt(sfd, SOL_SOCKET, SO_KEEPALIVE, &optval, sizeof(optval)); if (rc) logmsg("HHCUT001I SO_KEEPALIVE rc=%d %s\n", rc, strerror(errno)); #if defined(TCP_KEEPALIVE) optval = idle_time; rc = setsockopt(sfd, IPPROTO_TCP, TCP_KEEPALIVE, &optval, sizeof(optval)); if (rc) logmsg("HHCUT002I TCP_KEEPALIVE rc=%d %s\n", rc, strerror(errno)); #elif defined(TCP_KEEPIDLE) optval = idle_time; rc = setsockopt(sfd, SOL_TCP, TCP_KEEPIDLE, &optval, sizeof(optval)); if (rc) logmsg("HHCUT003I TCP_KEEPIDLE rc=%d %s\n", rc, strerror(errno)); #else UNREFERENCED(idle_time); #endif #if defined(TCP_KEEPINTVL) optval = probe_interval; rc = setsockopt(sfd, SOL_TCP, TCP_KEEPINTVL, &optval, sizeof(optval)); if (rc) logmsg("HHCUT004I TCP_KEEPINTVL rc=%d %s\n", rc, strerror(errno)); #else UNREFERENCED(probe_interval); #endif #if defined(TCP_KEEPCNT) optval = probe_count; rc = setsockopt(sfd, SOL_TCP, TCP_KEEPCNT, &optval, sizeof(optval)); if (rc) logmsg("HHCUT005I TCP_KEEPCNT rc=%d %s\n", rc, strerror(errno)); #else UNREFERENCED(probe_count); #endif } #endif // !defined(WIN32) ////////////////////////////////////////////////////////////////////////////////////////// // (testing) DLL_EXPORT void cause_crash() { static int x = 0; x = x / x - x; } ////////////////////////////////////////////////////////////////////////////////////////// /*******************************************/ /* Read/Write to socket functions */ /*******************************************/ DLL_EXPORT int hgetc(int s) { char c; int rc; rc=recv(s,&c,1,0); if(rc<1) { return EOF; } return c; } DLL_EXPORT char * hgets(char *b,size_t c,int s) { size_t ix=0; while(ix * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. */ /* * Copy src to string dst of size siz. At most siz-1 characters * will be copied. Always NUL terminates (unless siz == 0). * Returns strlen(src); if retval >= siz, truncation occurred. */ /* ** NOTE ** returns 'size_t' and NOT 'char*' like strncpy! */ HUT_DLL_IMPORT size_t strlcpy(char *dst, const char *src, size_t siz); #endif #if !defined(HAVE_STRLCAT) /* $OpenBSD: strlcat.c,v 1.11 2003/06/17 21:56:24 millert Exp $ */ /* * Copyright (c) 1998 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. */ /* * Appends src to string dst of size siz (unlike strncat, siz is the * full size of dst, not space left). At most siz-1 characters * will be copied. Always NUL terminates (unless siz <= strlen(dst)). * Returns strlen(src) + MIN(siz, strlen(initial dst)). * If retval >= siz, truncation occurred. */ /* ** NOTE ** returns 'size_t' and NOT 'char*' like strncat! */ HUT_DLL_IMPORT size_t strlcat(char *dst, const char *src, size_t siz); #endif /* Subtract/add gettimeofday struct timeval */ HUT_DLL_IMPORT int timeval_subtract (struct timeval *beg_timeval, struct timeval *end_timeval, struct timeval *dif_timeval); HUT_DLL_IMPORT int timeval_add (struct timeval *dif_timeval, struct timeval *accum_timeval); /* Easier to use timed_wait_condition that waits for the specified relative amount of time without you having to build an absolute timeout time yourself */ HUT_DLL_IMPORT int timed_wait_condition_relative_usecs ( COND* pCOND, // ptr to condition to wait on LOCK* pLOCK, // ptr to controlling lock (must be held!) U32 usecs, // max #of microseconds to wait struct timeval* pTV // [OPTIONAL] ptr to tod value (may be NULL) ); // TEST HUT_DLL_IMPORT void cause_crash(); /* Read/write to socket functions */ HUT_DLL_IMPORT int hprintf(int s,char *fmt,...); HUT_DLL_IMPORT int hwrite(int s,const char *,size_t); HUT_DLL_IMPORT int hgetc(int s); HUT_DLL_IMPORT char *hgets(char *b,size_t c,int s); /* Posix 1003.e capabilities */ #if defined(OPTION_CAPABILITIES) HUT_DLL_IMPORT int drop_privileges(int c); HUT_DLL_IMPORT int drop_all_caps(void); #endif #endif /* __HSCUTL_H__ */ hercules-3.07/hscutl2.c000644 000765 000765 00000020370 11143760542 016500 0ustar00jmaynardjmaynard000000 000000 /**********************************************************************/ /* */ /* HSCUTL2.C */ /* */ /* (c) 2003-2006 Mark L. Gaubatz and others */ /* */ /* Implementation of functions used in Hercules that may be missing */ /* on some platform ports. */ /* */ /* HSCUTL2.C differs from HSCUTL.C in that the only Hercules header */ /* files permitted are config.h and hscutl.h. This is necessary to */ /* include some header files that conflict with definitions in some */ /* Hercules header files. */ /* */ /* Released under the Q Public License */ /* (http://www.hercules-390.org/herclic.html) */ /* as modifications to Hercules. */ /* */ /* This file is portion of the HERCULES S/370, S/390 and */ /* z/Architecture emulator. */ /* */ /**********************************************************************/ // $Id: hscutl2.c 4496 2007-11-30 14:54:34Z jmaynard $ // // $Log$ // Revision 1.10 2006/12/08 09:43:26 jj // Add CVS message log // #include "hstdinc.h" #define _HSCUTL2_C_ #define _HUTIL_DLL_ #include "hercules.h" #if defined(WIN32) /**********************************************************************/ /* */ /* Win32 Patches */ /* */ /* The following functional equivalents are provided */ /* for the Win32 environment: */ /* */ /* int getpriority(int which, id_t who); */ /* int setpriority(int which, id_t who, int prio); */ /* */ /* */ /**********************************************************************/ // Windows Unix // THREAD_PRIORITY_TIME_CRITICAL 15 -20 // THREAD_PRIORITY_HIGHEST 2 -15 // THREAD_PRIORITY_ABOVE_NORMAL 1 -8 // THREAD_PRIORITY_NORMAL 0 0 // THREAD_PRIORITY_BELOW_NORMAL -1 8 // THREAD_PRIORITY_LOWEST -2 15 // THREAD_PRIORITY_IDLE -15 20 /**********************************************************************/ /* */ /* int getpriority(int which , id_t who ); */ /* */ /* Notes: */ /* */ /* 1. PRIO_USER not supported. */ /* 2. who may only be specified as 0, for the current */ /* process or process group id. */ /* */ /* */ /**********************************************************************/ static inline int getpriority_process(id_t who) { HANDLE process; DWORD priority; if (who) return EINVAL; process = (HANDLE) -1; priority = GetPriorityClass (process); switch (priority) { case REALTIME_PRIORITY_CLASS: return -20; case HIGH_PRIORITY_CLASS: return -15; case ABOVE_NORMAL_PRIORITY_CLASS: return -8; case NORMAL_PRIORITY_CLASS: return 0; case BELOW_NORMAL_PRIORITY_CLASS: return 8; } /* IDLE_PRIORITY_CLASS: */ return 15; } static inline int getpriority_thread(id_t who) { HANDLE thread; int priority; if (who) return EINVAL; thread = GetCurrentThread(); priority = GetThreadPriority (thread); switch (priority) { case THREAD_PRIORITY_TIME_CRITICAL: return -20; case THREAD_PRIORITY_HIGHEST: return -15; case THREAD_PRIORITY_ABOVE_NORMAL: return -8; case THREAD_PRIORITY_NORMAL: return 0; case THREAD_PRIORITY_BELOW_NORMAL: return 8; case THREAD_PRIORITY_LOWEST: return 15; } /* THREAD_PRIORITY_IDLE: */ return 20; } static inline int getpriority_user(id_t who) { if (who) return EINVAL; return 0; } DLL_EXPORT int getpriority(int which , id_t who ) { switch (which) { case PRIO_PROCESS: return getpriority_thread(who); case PRIO_PGRP: return getpriority_process(who); case PRIO_USER: return getpriority_user(who); } return EINVAL; } /**********************************************************************/ /* */ /* int setpriority(int which , id_t who , int prio ); */ /* */ /* Notes: */ /* */ /* 1. PRIO_USER not supported. */ /* 2. who may only be specified as 0, for the current */ /* process or process group id. */ /* */ /* */ /**********************************************************************/ DLL_EXPORT inline int setpriority_process(id_t who , int prio ) { HANDLE process; DWORD priority; if (who) return EINVAL; process = (HANDLE) -1; /* Force to current process */ if (prio < -15) priority = REALTIME_PRIORITY_CLASS; else if (prio < -8) priority = HIGH_PRIORITY_CLASS; else if (prio < 0) priority = ABOVE_NORMAL_PRIORITY_CLASS; else if (prio < 8) priority = NORMAL_PRIORITY_CLASS; else if (prio < 15) priority = BELOW_NORMAL_PRIORITY_CLASS; else priority = IDLE_PRIORITY_CLASS; if (!SetPriorityClass (process, priority)) return GetLastError(); return 0; } static inline int setpriority_thread(id_t who , int prio ) { HANDLE thread; int priority; if (who) return EINVAL; thread = GetCurrentThread(); if (prio < -15) priority = THREAD_PRIORITY_TIME_CRITICAL; else if (prio < -8) priority = THREAD_PRIORITY_HIGHEST; else if (prio < 0) priority = THREAD_PRIORITY_ABOVE_NORMAL; else if (prio < 8) priority = THREAD_PRIORITY_NORMAL; else if (prio < 15) priority = THREAD_PRIORITY_BELOW_NORMAL; else if (prio < 20) priority = THREAD_PRIORITY_LOWEST; else priority = THREAD_PRIORITY_IDLE; if (!SetThreadPriority (thread, priority)) return GetLastError(); return 0; } static inline int setpriority_user(id_t who , int prio ) { if (who) return EINVAL; return 0; /* Ignore */ prio = prio; /* Unreferenced */ } DLL_EXPORT int setpriority(int which , id_t who , int prio ) { switch (which) { case PRIO_PROCESS: return setpriority_thread(who, prio); case PRIO_PGRP: return setpriority_process(who, prio); case PRIO_USER: return setpriority_user(who, prio); } return EINVAL; } #endif // defined(WIN32) hercules-3.07/hsocket.c000644 000765 000765 00000007427 11143760543 016565 0ustar00jmaynardjmaynard000000 000000 /* HSOCKET.C (c) Copyright Hercules development, 2003-2009 */ /* Socket read/write routines */ // $Id: hsocket.c 5125 2009-01-23 12:01:44Z bernard $ // // $Log$ // Revision 1.8 2007/06/23 00:04:11 ivan // Update copyright notices to include current year (2007) // // Revision 1.7 2006/12/08 09:43:27 jj // Add CVS message log // #include "hstdinc.h" #define _HSOCKET_C_ #define _HUTIL_DLL_ #include "hercules.h" /************************************************************************ NAME: read_socket - read a passed number of bytes from a socket. PURPOSE: This routine is used in place of read to read a passed number of bytes from a socket. A read on a socket will return less than the number of bytes requested if there are less currenly available. Thus we read in a loop till we get all we want. PARAMETERS: 1. fd - int (INPUT) This is the file descriptor for the socket to be read. 2. ptr - pointer to void (OUTPUT) This is a pointer to where the data is to be put. 3. nbytes - int (INPUT) This is the number of bytes to read. FUNCTIONS : 1. Read in a loop till an error occurs or the data is read. OUTPUTS: data into the buffer *************************************************************************/ DLL_EXPORT int read_socket(int fd, void *_ptr, int nbytes) { int nleft, nread; char *ptr; nleft = nbytes; ptr=_ptr; while (nleft > 0) { #ifdef _MSVC_ nread = recv(fd, ptr, nleft, 0); if ((nread == SOCKET_ERROR) || (nread < 0)) { nread = -1; break; /* error, return < 0 */ } if (nread == 0) break; #else nread = read(fd, ptr, nleft); if (nread < 0) return(nread); /* error, return < 0 */ else if (nread == 0) /* eof */ break; #endif nleft -= nread; ptr += nread; } /* end of do while */ /* if (nleft != 0) logmsg (_("BOB123 read_socket: Read of %d bytes requested, %d bytes actually read\n"), nbytes, nbytes - nleft);*/ return (nbytes - nleft); } /* end of read_socket */ /************************************************************************ NAME: write_socket - write a passed number of bytes into a socket. PURPOSE: This routine is used in place of write to write a passed number of bytes into a socket. A write on a socket may take less than the number of bytes requested if there is currently insufficient buffer space available. Thus we write in a loop till we get all we want. PARAMETERS: 1. fd - int (OUTPUT) This is the file descriptor for the socket to be written. 2. ptr - pointer to void (INPUT) This is a pointer to where the data is to be gotten from. 3. nbytes - int (INPUT) This is the number of bytes to write. FUNCTIONS : 1. Write in a loop till an error occurs or the data is written. OUTPUTS: Data to the socket. *************************************************************************/ /* * Write "n" bytes to a descriptor. * Use in place of write() when fd is a stream socket. */ DLL_EXPORT int write_socket(int fd, const void *_ptr, int nbytes) { int nleft, nwritten; const char *ptr; nleft = nbytes; ptr=_ptr; while (nleft > 0) { #ifdef _MSVC_ nwritten = send(fd, ptr, nleft, 0); if (nwritten <= 0) { return(nwritten); /* error */ } #else nwritten = write(fd, ptr, nleft); if (nwritten <= 0) return(nwritten); /* error */ #endif nleft -= nwritten; ptr += nwritten; } /* end of do while */ return(nbytes - nleft); } /* end of write_socket */ hercules-3.07/hsocket.h000644 000765 000765 00000013667 11143760543 016575 0ustar00jmaynardjmaynard000000 000000 /* HSOCKET.H (c) Copyright Roger Bowler, 2005-2009 */ /* Equates for socket functions */ /* This header file contains equates for the socket functions */ /* and constants whose values differ between Unix and Winsock */ // $Id: hsocket.h 5125 2009-01-23 12:01:44Z bernard $ // // $Log$ // Revision 1.10 2007/06/23 00:04:11 ivan // Update copyright notices to include current year (2007) // // Revision 1.9 2006/12/08 09:43:27 jj // Add CVS message log // #if !defined(_HSOCKET_H) #define _HSOCKET_H #ifndef _HSOCKET_C_ #ifndef _HUTIL_DLL_ #define HSOCK_DLL_IMPORT DLL_IMPORT #else #define HSOCK_DLL_IMPORT extern #endif #else #define HSOCK_DLL_IMPORT DLL_EXPORT #endif /*-------------------------------------------------------------------*/ /* Socket related constants related to 'shutdown' API call */ /*-------------------------------------------------------------------*/ #ifdef _MSVC_ /* Map SUS\*nix constants to Windows socket equivalents */ #define SHUT_RD SD_RECEIVE #define SHUT_WR SD_SEND #define SHUT_RDWR SD_BOTH #endif #if defined(_WINSOCKAPI_) /*-------------------------------------------------------------------*/ /* Equates for systems which use the Winsock API */ /*-------------------------------------------------------------------*/ #define get_HSO_errno() ((int)WSAGetLastError()) #define set_HSO_errno(e) (WSASetLastError(e)) #define HSO_errno get_HSO_errno() #define HSO_EINTR WSAEINTR #define HSO_EBADF WSAEBADF #define HSO_EACCES WSAEACCES #define HSO_EFAULT WSAEFAULT #define HSO_EINVAL WSAEINVAL #define HSO_EMFILE WSAEMFILE #define HSO_EWOULDBLOCK WSAEWOULDBLOCK #define HSO_EINPROGRESS WSAEINPROGRESS #define HSO_EALREADY WSAEALREADY #define HSO_ENOTSOCK WSAENOTSOCK #define HSO_EDESTADDRREQ WSAEDESTADDRREQ #define HSO_EMSGSIZE WSAEMSGSIZE #define HSO_EPROTOTYPE WSAEPROTOTYPE #define HSO_ENOPROTOOPT WSAENOPROTOOPT #define HSO_EPROTONOSUPPORT WSAEPROTONOSUPPORT #define HSO_ESOCKTNOSUPPORT WSAESOCKTNOSUPPORT #define HSO_EOPNOTSUPP WSAEOPNOTSUPP #define HSO_EPFNOSUPPORT WSAEPFNOSUPPORT #define HSO_EAFNOSUPPORT WSAEAFNOSUPPORT #define HSO_EADDRINUSE WSAEADDRINUSE #define HSO_EADDRNOTAVAIL WSAEADDRNOTAVAIL #define HSO_ENETDOWN WSAENETDOWN #define HSO_ENETUNREACH WSAENETUNREACH #define HSO_ENETRESET WSAENETRESET #define HSO_ECONNABORTED WSAECONNABORTED #define HSO_ECONNRESET WSAECONNRESET #define HSO_ENOBUFS WSAENOBUFS #define HSO_EISCONN WSAEISCONN #define HSO_ENOTCONN WSAENOTCONN #define HSO_ESHUTDOWN WSAESHUTDOWN #define HSO_ETOOMANYREFS WSAETOOMANYREFS #define HSO_ETIMEDOUT WSAETIMEDOUT #define HSO_ECONNREFUSED WSAECONNREFUSED #define HSO_ELOOP WSAELOOP #define HSO_ENAMETOOLONG WSAENAMETOOLONG #define HSO_EHOSTDOWN WSAEHOSTDOWN #define HSO_EHOSTUNREACH WSAEHOSTUNREACH #define HSO_ENOTEMPTY WSAENOTEMPTY #define HSO_EPROCLIM WSAEPROCLIM #define HSO_EUSERS WSAEUSERS #define HSO_EDQUOT WSAEDQUOT #define HSO_ESTALE WSAESTALE #define HSO_EREMOTE WSAEREMOTE #else /*-------------------------------------------------------------------*/ /* Equates for systems which use the Berkeley sockets API */ /*-------------------------------------------------------------------*/ #define get_HSO_errno() (errno) #define set_HSO_errno(e) (errno=(e)) #define HSO_errno get_HSO_errno() #define HSO_EINTR EINTR #define HSO_EBADF EBADF #define HSO_EACCES EACCES #define HSO_EFAULT EFAULT #define HSO_EINVAL EINVAL #define HSO_EMFILE EMFILE #define HSO_EWOULDBLOCK EWOULDBLOCK #define HSO_EINPROGRESS EINPROGRESS #define HSO_EALREADY EALREADY #define HSO_ENOTSOCK ENOTSOCK #define HSO_EDESTADDRREQ EDESTADDRREQ #define HSO_EMSGSIZE EMSGSIZE #define HSO_EPROTOTYPE EPROTOTYPE #define HSO_ENOPROTOOPT ENOPROTOOPT #define HSO_EPROTONOSUPPORT EPROTONOSUPPORT #define HSO_ESOCKTNOSUPPORT ESOCKTNOSUPPORT #define HSO_EOPNOTSUPP EOPNOTSUPP #define HSO_EPFNOSUPPORT EPFNOSUPPORT #define HSO_EAFNOSUPPORT EAFNOSUPPORT #define HSO_EADDRINUSE EADDRINUSE #define HSO_EADDRNOTAVAIL EADDRNOTAVAIL #define HSO_ENETDOWN ENETDOWN #define HSO_ENETUNREACH ENETUNREACH #define HSO_ENETRESET ENETRESET #define HSO_ECONNABORTED ECONNABORTED #define HSO_ECONNRESET ECONNRESET #define HSO_ENOBUFS ENOBUFS #define HSO_EISCONN EISCONN #define HSO_ENOTCONN ENOTCONN #define HSO_ESHUTDOWN ESHUTDOWN #define HSO_ETOOMANYREFS ETOOMANYREFS #define HSO_ETIMEDOUT ETIMEDOUT #define HSO_ECONNREFUSED ECONNREFUSED #define HSO_ELOOP ELOOP #define HSO_ENAMETOOLONG ENAMETOOLONG #define HSO_EHOSTDOWN EHOSTDOWN #define HSO_EHOSTUNREACH EHOSTUNREACH #define HSO_ENOTEMPTY ENOTEMPTY #define HSO_EPROCLIM EPROCLIM #define HSO_EUSERS EUSERS #define HSO_EDQUOT EDQUOT #define HSO_ESTALE ESTALE #define HSO_EREMOTE EREMOTE #endif /*-------------------------------------------------------------------*/ /* Local function definitions */ /*-------------------------------------------------------------------*/ HSOCK_DLL_IMPORT int read_socket(int fd, void *ptr, int nbytes); HSOCK_DLL_IMPORT int write_socket(int fd, const void *ptr, int nbytes); #endif /*!defined(_HSOCKET_H)*/ hercules-3.07/hstdinc.h000644 000765 000765 00000013373 11301535255 016557 0ustar00jmaynardjmaynard000000 000000 /* HSTDINC.H (c) Copyright Roger Bowler, 1999-2009 */ /* Hercules precompilation-eligible Header Files */ /* This file contains #include statements for all of the header */ /* files which are not dependent on the mainframe architectural */ /* features selected and thus are eligible for precompilation */ // $Id: hstdinc.h 5497 2009-10-27 20:17:03Z fish $ #ifndef _HSTDINC_H #define _HSTDINC_H #ifdef HAVE_CONFIG_H #include // Hercules build configuration options/settings #endif /////////////////////////////////////////////////////////////////////// // Required and optional SYSTEM headers... ////////////////////////////////////////////////////////////////////// #define _REENTRANT /* Ensure that reentrant code is generated *JJ */ #define _THREAD_SAFE /* Some systems use this instead *JJ */ #if defined(HAVE_STRSIGNAL) && defined(__GNUC__) && !defined(_GNU_SOURCE) #define _GNU_SOURCE /* required by strsignal() *JJ */ #endif /* Required headers -- These we ALWAYS need to have... */ #ifdef _MSVC_ // The following ensures certain functions get defined... // (such as TryEnterCriticalSection and InitializeCriticalSectionAndSpinCount) #ifndef _WIN32_WINNT #define _WIN32_WINNT 0x0403 // Windows 98 or WinNT SP4 or greater #endif #include // Windows Sockets 2 #include // (need struct tcp_keepalive) #endif #ifdef WIN32 #include #endif #ifdef _MSVC_ #include #include #include #include #include #include #include #include #endif #include #include #include #include #include #include #include #include #ifndef O_BINARY #define O_BINARY 0 #endif #ifndef O_NONBLOCK #define O_NONBLOCK 0 #endif #include #include #include #if !defined(_MSVC_) #include #include #endif #include /* Optional headers -- These we can live without */ /* PROGRAMMING NOTE: On Darwin, must be included before , and on older Darwin systems, before and */ #ifdef HAVE_SYS_SOCKET_H #include #endif #ifdef HAVE_ARPA_INET_H #include #endif #if defined(BUILD_HERCIFC) #ifdef HAVE_LINUX_IF_TUN_H #include #endif #ifdef HAVE_NET_ROUTE_H #include #endif #endif // (just make it easier to #include hercifc.h) #if defined(BUILD_HERCIFC) || defined(_MSVC_) || !defined(HAVE_LINUX_IF_TUN_H) || !defined(HAVE_NET_IF_H) #define NEED_HERCIFC_H #endif #ifdef HAVE_NET_IF_H #include #endif #ifdef HAVE_NETINET_IN_H #include #endif #ifdef HAVE_NETINET_TCP_H #include #endif #ifdef HAVE_SYS_IOCTL_H #include #endif #ifdef HAVE_SYS_MMAN_H #include #endif #ifdef HAVE_SYS_PARAM_H #include #endif #ifdef HAVE_SYS_MOUNT_H #include #endif #ifdef HAVE_SYS_MTIO_H #include #endif #ifdef HAVE_SYS_RESOURCE_H #include #endif #ifdef HAVE_SYS_UN_H #include #endif #ifdef HAVE_SYS_UIO_H #include #endif #ifdef HAVE_SYS_UTSNAME_H #include #endif #ifdef HAVE_SYS_WAIT_H #include #endif #ifdef HAVE_BYTESWAP_H #ifndef NO_ASM_BYTESWAP #include #endif #endif #ifdef HAVE_BZLIB_H // windows.h #defines 'small' as char and bzlib.h // uses it for a variable name so we must #undef. #if defined(__CYGWIN__) #undef small #endif #include /* ISW 20050427 : CCKD_BZIP2/HET_BZIP2 are usually */ /* controlled by config.h (automagic). If config.h */ /* is not present however, then define them here. */ #if !defined(HAVE_CONFIG_H) #define CCKD_BZIP2 #define HET_BZIP2 #endif #endif #ifdef HAVE_DIRENT_H #include #endif #ifdef OPTION_DYNAMIC_LOAD #ifdef HDL_USE_LIBTOOL #include #else #if defined(__MINGW__) || defined(_MSVC_) #include "w32dl.h" #else #include #endif #endif #endif #ifdef HAVE_FENV_H #include #endif #ifdef HAVE_ICONV #include #endif #ifdef ENABLE_NLS #ifdef HAVE_LOCALE_H #include #else #error ENABLE_NLS requires #endif #ifdef HAVE_LIBINTL_H #include #else #error ENABLE_NLS requires #endif #endif #ifdef HAVE_INTTYPES_H #include #endif #ifdef HAVE_MALLOC_H #include #endif #ifdef HAVE_MATH_H #include #endif #ifdef HAVE_NETDB_H #include #endif #ifdef HAVE_PWD_H #include #endif #ifdef HAVE_REGEX_H #include #endif #ifdef HAVE_SCHED_H #include #endif #ifdef HAVE_SIGNAL_H #include #endif #ifdef HAVE_TIME_H #include #endif #ifdef HAVE_TERMIOS_H #include #endif #ifdef HAVE_ZLIB_H #include #endif #ifdef HAVE_SYS_CAPABILITY_H #include #endif #ifdef HAVE_SYS_PRCTL_H #include #endif // Some Hercules specific files, NOT guest arch dependent #if defined(_MSVC_) #include "hercwind.h" // Hercules definitions for Windows #else #include // Unix standard definitions #endif #ifdef C99_FLEXIBLE_ARRAYS #define FLEXIBLE_ARRAY // ("DEVBLK *memdev[];" syntax is supported) #else #define FLEXIBLE_ARRAY 0 // ("DEVBLK *memdev[0];" must be used instead) #endif #include "hostopts.h" // Must come before htypes.h #include "htypes.h" // Hercules-wide data types #endif // _HSTDINC_H hercules-3.07/hstdint.h000644 000765 000765 00000003344 11143760542 016600 0ustar00jmaynardjmaynard000000 000000 /* HSTDINT.H (c)Copyright Roger Bowler, 2009 */ /* Hercules standard integer definitions */ // $Id: hstdint.h 5125 2009-01-23 12:01:44Z bernard $ // // $Log$ // Revision 1.2 2007/06/23 00:04:11 ivan // Update copyright notices to include current year (2007) // // Revision 1.1 2006/12/10 23:18:32 rbowler // Modify decContext.h to include hstdint.h instead of stdint.h // // /*-------------------------------------------------------------------*/ /* The purpose of this file is to define the following typedefs: */ /* uint8_t, uint16_t, uint32_t, uint64_t */ /* int8_t, int16_t, int32_t, int64_t */ /* For Windows, the MSVC-specific C sized integer types are used. */ /* For Unix, definitions are included from stdint.h if it exists, */ /* otherwise from inttypes.h (if it exists), otherwise unistd.h */ /*-------------------------------------------------------------------*/ #ifndef _HSTDINT_H #define _HSTDINT_H #ifdef HAVE_CONFIG_H #include /* Hercules build configuration */ #endif #if defined(_MSVC_) typedef unsigned __int8 uint8_t; typedef unsigned __int16 uint16_t; typedef unsigned __int32 uint32_t; typedef unsigned __int64 uint64_t; typedef signed __int8 int8_t; typedef signed __int16 int16_t; typedef signed __int32 int32_t; typedef signed __int64 int64_t; #elif defined(HAVE_STDINT_H) #include /* Standard integer definitions */ #elif defined(HAVE_INTTYPES_H) #include /* Fixed size integral types */ #else #include /* Unix standard definitions */ #endif #endif /*_HSTDINT_H*/ hercules-3.07/hstructs.h000644 000765 000765 00000246551 11335365456 017023 0ustar00jmaynardjmaynard000000 000000 /* HSTRUCTS.H (c) Copyright Roger Bowler, 1999-2009 */ /* Hercules Structure Definitions */ // This header auto-#included by 'hercules.h'... // // The header and other required headers are // presumed to have already been #included ahead of it... // $Id: hstructs.h 5622 2010-02-09 00:32:03Z fish $ #ifndef _HSTRUCTS_H #define _HSTRUCTS_H #include "hercules.h" #include "opcode.h" /*-------------------------------------------------------------------*/ /* Typedefs for CPU bitmap fields */ /* */ /* A CPU bitmap contains one bit for each processing engine. */ /* The width of the bitmap depends on the maximum number of */ /* processing engines which was selected at build time. */ /*-------------------------------------------------------------------*/ #if MAX_CPU_ENGINES <= 32 typedef U32 CPU_BITMAP; #define F_CPU_BITMAP "%8.8"I32_FMT"X" #elif MAX_CPU_ENGINES <= 64 typedef U64 CPU_BITMAP; #define F_CPU_BITMAP "%16.16"I64_FMT"X" #else #error MAX_CPU_ENGINES cannot exceed 64 #endif /*-------------------------------------------------------------------*/ /* Structure definition for CPU register context */ /*-------------------------------------------------------------------*/ struct REGS { /* Processor registers */ #define HDL_VERS_REGS "3.03" /* Internal Version Number */ #define HDL_SIZE_REGS sizeof(REGS) int arch_mode; /* Architectural mode */ DW px; /* Prefix register */ PSW psw; /* Program status word */ BYTE *ip; /* Mainstor inst address */ /* AIA - Instruction fetch accelerator */ BYTE *aip; /* Mainstor page address */ uintptr_t aim; /* Mainstor xor address */ BYTE *aie; /* Mainstor page end address */ DW aiv; /* Virtual page address */ U64 bear; /* Breaking event address reg*/ BYTE *bear_ip; /* Breaking event inst ptr */ DW gr[16]; /* General registers */ DW cr[16+16+1]; /* 16 Control registers */ #define CR_ALB_OFFSET 16 /* 16 Accesslist lookaside */ #define CR_ASD_REAL 32 /* 1 Real asd register */ U32 ar[16]; /* Access registers */ U32 fpr[32]; /* Floating point registers */ U32 fpc; /* IEEE Floating Point Control Register */ U32 dxc; /* Data exception code */ DW mc; /* Monitor Code */ DW ea; /* Exception address */ DW et; /* Execute Target address */ unsigned int /* Flags (cpu thread only) */ execflag:1, /* 1=EXecuted instruction */ exrl:1, /* 1=EXRL, 0=EX instruction */ permode:1, /* 1=PER active */ instinvalid:1, /* 1=Inst field is invalid */ opinterv:1, /* 1=Operator intervening */ checkstop:1, /* 1=CPU is checkstop-ed */ hostint:1, /* 1=Host generated interrupt*/ host:1, /* REGS are hostregs */ guest:1; /* REGS are guestregs */ unsigned int /* Flags (intlock serialized)*/ dummy:1, /* 1=Dummy regs structure */ configured:1, /* 1=CPU is online */ loadstate:1, /* 1=CPU is in load state */ ghostregs:1, /* 1=Ghost registers (panel) */ invalidate:1, /* 1=Do AIA/AEA invalidation */ tracing:1, /* 1=Trace is active */ stepwait:1, /* 1=Wait in inst stepping */ sigpreset:1, /* 1=SIGP cpu reset received */ sigpireset:1; /* 1=SIGP initial cpu reset */ S64 cpu_timer; /* CPU timer epoch */ S64 int_timer; /* S/370 Interval timer */ S32 old_timer; /* S/370 Interval timer int */ U64 clkc; /* 0-7=Clock comparator epoch, 8-63=Comparator bits 0-55 */ S64 tod_epoch; /* TOD epoch for this CPU */ S64 ecps_vtimer; /* ECPS Virtual Int. timer */ S32 ecps_oldtmr; /* ECPS Virtual Int. tmr int */ BYTE *ecps_vtmrpt; /* Pointer to VTMR or zero */ U32 instcount; /* Instruction counter */ U64 prevcount; /* Previous instruction count*/ U32 mipsrate; /* Instructions per second */ U32 siocount; /* SIO/SSCH counter */ U32 siosrate; /* IOs per second */ U64 siototal; /* Total SIO/SSCH count */ int cpupct; /* Percent CPU busy */ U64 waittod; /* Time of day last wait (us)*/ U64 waittime; /* Wait time (us) in interval*/ DAT dat; /* Fields for DAT use */ #define GR_G(_r) gr[(_r)].D #define GR_H(_r) gr[(_r)].F.H.F /* Fullword bits 0-31 */ #define GR_HHH(_r) gr[(_r)].F.H.H.H.H /* Halfword bits 0-15 */ #define GR_HHL(_r) gr[(_r)].F.H.H.L.H /* Halfword low, bits 16-31 */ #define GR_L(_r) gr[(_r)].F.L.F /* Fullword low, bits 32-63 */ #define GR_LHH(_r) gr[(_r)].F.L.H.H.H /* Halfword bits 32-47 */ #define GR_LHL(_r) gr[(_r)].F.L.H.L.H /* Halfword low, bits 48-63 */ #define GR_LHHCH(_r) gr[(_r)].F.L.H.H.B.H /* Character, bits 32-39 */ #define GR_LA24(_r) gr[(_r)].F.L.A.A /* 24 bit addr, bits 40-63 */ #define GR_LA8(_r) gr[(_r)].F.L.A.B /* 24 bit addr, unused bits */ #define GR_LHLCL(_r) gr[(_r)].F.L.H.L.B.L /* Character, bits 56-63 */ #define GR_LHLCH(_r) gr[(_r)].F.L.H.L.B.H /* Character, bits 48-55 */ #define CR_G(_r) cr[(_r)].D /* Bits 0-63 */ #define CR_H(_r) cr[(_r)].F.H.F /* Fullword bits 0-31 */ #define CR_HHH(_r) cr[(_r)].F.H.H.H.H /* Halfword bits 0-15 */ #define CR_HHL(_r) cr[(_r)].F.H.H.L.H /* Halfword low, bits 16-31 */ #define CR_L(_r) cr[(_r)].F.L.F /* Fullword low, bits 32-63 */ #define CR_LHH(_r) cr[(_r)].F.L.H.H.H /* Halfword bits 32-47 */ #define CR_LHHCH(_r) cr[(_r)].F.L.H.H.B.H /* Character, bits 32-39 */ #define CR_LHL(_r) cr[(_r)].F.L.H.L.H /* Halfword low, bits 48-63 */ #define MC_G mc.D #define MC_L mc.F.L.F #define EA_G ea.D #define EA_L ea.F.L.F #define ET_G et.D #define ET_L et.F.L.F #define PX_G px.D #define PX_L px.F.L.F #define AIV_G aiv.D #define AIV_L aiv.F.L.F #define AR(_r) ar[(_r)] U16 chanset; /* Connected channel set */ U32 todpr; /* TOD programmable register */ U16 monclass; /* Monitor event class */ U16 cpuad; /* CPU address for STAP */ BYTE excarid; /* Exception access register */ BYTE opndrid; /* Operand access register */ BYTE exinst[8]; /* Target of Execute (EX) */ BYTE *mainstor; /* -> Main storage */ BYTE *storkeys; /* -> Main storage key array */ RADR mainlim; /* Central Storage limit or */ /* guest storage limit (SIE) */ PSA_3XX *psa; /* -> PSA for this CPU */ /* * The fields hostregs and guestregs have been move outside the * scope of _FEATURE_SIE to reduce conditional code. * * sysblk.regs[i] always points to the host regs * flag `host' is always 1 for the host regs * flag `guest' is always 1 for the guest regs * `hostregs' is always equal to sysblk.regs[i] (in both * hostregs and guestregs) * `guestregs' is always equal to sysblk.regs[i]->guestregs * (in both hostregs and guestregs). * sysblk.regs[i]->guestregs is NULL until the first SIE * instruction is executed on that CPU. * `sie_active' is 1 in hostregs if SIE is executing * and the current register context is `guestregs' * `sie_mode' is 1 in guestregs always * `sie_state' has the real address of the SIEBK * `siebk' has the mainstor address of the SIEBK */ REGS *hostregs; /* Pointer to the hypervisor register context */ REGS *guestregs; /* Pointer to the guest register context */ SYSBLK *sysblk; /* Pointer to sysblk */ #if defined(_FEATURE_SIE) RADR sie_state; /* Address of the SIE state descriptor block or 0 when not running under SIE */ SIEBK *siebk; /* Sie State Desc structure */ RADR sie_px; /* Host address of guest px */ RADR sie_mso; /* Main Storage Origin */ RADR sie_xso; /* eXpanded Storage Origin */ RADR sie_xsl; /* eXpanded Storage Limit */ RADR sie_rcpo; /* Ref and Change Preserv. */ RADR sie_scao; /* System Contol Area */ S64 sie_epoch; /* TOD offset in state desc. */ #endif /*defined(_FEATURE_SIE)*/ unsigned int sie_active:1, /* SIE active (host only) */ sie_mode:1, /* Running under SIE (guest) */ sie_pref:1; /* Preferred-storage mode */ // #if defined(FEATURE_PER) U16 perc; /* PER code */ RADR peradr; /* PER address */ BYTE peraid; /* PER access id */ // #endif /*defined(FEATURE_PER)*/ CPU_BITMAP cpubit; /* Only this CPU's bit is 1 */ U32 ints_state; /* CPU Interrupts Status */ U32 ints_mask; /* Respective Interrupts Mask*/ /* * Making the following flags 'stand-alone' (instead of bit- * flags like they were) addresses a compiler bit-flag serial- * ization issue that occurs with the 'SYNCHRONIZE_CPUS' macro * used during synchronize broadcast (cpu<->cpu communication) */ int intwait; /* 1=Waiting on intlock */ int syncio; /* 1=Synchronous i/o active */ BYTE cpustate; /* CPU stopped/started state */ BYTE malfcpu /* Malfuction alert flags */ [MAX_CPU_ENGINES]; /* for each CPU (1=pending) */ BYTE emercpu /* Emergency signal flags */ [MAX_CPU_ENGINES]; /* for each CPU (1=pending) */ U16 extccpu; /* CPU causing external call */ BYTE inst[8]; /* Fetched instruction when instruction crosses a page boundary */ BYTE *invalidate_main; /* Mainstor addr to invalidat*/ PSW captured_zpsw; /* Captured-z/Arch PSW reg */ #if defined(_FEATURE_VECTOR_FACILITY) VFREGS *vf; /* Vector Facility */ #endif /*defined(_FEATURE_VECTOR_FACILITY)*/ jmp_buf progjmp; /* longjmp destination for program check return */ jmp_buf archjmp; /* longjmp destination to switch architecture mode */ jmp_buf exitjmp; /* longjmp destination for CPU thread exit */ COND intcond; /* CPU interrupt condition */ LOCK *cpulock; /* CPU lock for this CPU */ /* Mainstor address lookup accelerator */ BYTE aea_mode; /* aea addressing mode */ int aea_ar[16+5]; /* arn to cr number */ /* 5 Special registers */ BYTE aea_common[16+16+1]; /* 1=asd is not private */ /* 16 Accesslist lookaside */ /* 1 Real asd register */ BYTE aea_aleprot[16]; /* ale protected */ /* Function pointers */ pi_func program_interrupt; func trace_br; /* ------------------------------------------------------------ */ U64 regs_copy_end; /* Copy regs to here */ /* ------------------------------------------------------------ */ /* Opcode table pointers */ FUNC s370_opcode_table[256]; FUNC *s370_opcode_a4xx, *s370_opcode_a5xx, *s370_opcode_a6xx, #if defined(MULTI_BYTE_ASSIST) s370_opcode_a7xx[256], s370_opcode_b2xx[256], s370_opcode_b9xx[256], s370_opcode_c0xx[256], /*@N3*/ s370_opcode_e3xx[256], /*@N3*/ s370_opcode_ebxx[256], #else *s370_opcode_a7xx, *s370_opcode_b2xx, *s370_opcode_b9xx, *s370_opcode_c0xx, /*@N3*/ *s370_opcode_e3xx, /*@N3*/ *s370_opcode_ebxx, #endif *s370_opcode_b3xx, /*FPE*/ *s370_opcode_c2xx, /*208*/ *s370_opcode_c4xx, /*208*/ *s370_opcode_c6xx, /*208*/ *s370_opcode_e4xx, *s370_opcode_e5xx, *s370_opcode_e6xx, *s370_opcode_ecxx, /*@N3*/ *s370_opcode_edxx; FUNC s390_opcode_table[256]; FUNC *s390_opcode_01xx, *s390_opcode_a4xx, *s390_opcode_a5xx, *s390_opcode_a6xx, #if defined(MULTI_BYTE_ASSIST) s390_opcode_a7xx[256], s390_opcode_b2xx[256], s390_opcode_b9xx[256], s390_opcode_c0xx[256], s390_opcode_e3xx[256], s390_opcode_ebxx[256], #else *s390_opcode_a7xx, *s390_opcode_b2xx, *s390_opcode_b9xx, *s390_opcode_c0xx, *s390_opcode_e3xx, *s390_opcode_ebxx, #endif *s390_opcode_b3xx, *s390_opcode_c2xx, *s390_opcode_c4xx, /*208*/ *s390_opcode_c6xx, /*208*/ *s390_opcode_e4xx, *s390_opcode_e5xx, *s390_opcode_ecxx, *s390_opcode_edxx; FUNC z900_opcode_table[256]; FUNC *z900_opcode_01xx, *z900_opcode_a5xx, #if defined(MULTI_BYTE_ASSIST) z900_opcode_a7xx[256], z900_opcode_b2xx[256], z900_opcode_b9xx[256], z900_opcode_c0xx[256], z900_opcode_e3xx[256], z900_opcode_ebxx[256], #else *z900_opcode_a7xx, *z900_opcode_b2xx, *z900_opcode_b9xx, *z900_opcode_c0xx, *z900_opcode_e3xx, *z900_opcode_ebxx, #endif *z900_opcode_b3xx, *z900_opcode_c2xx, *z900_opcode_c4xx, /*208*/ *z900_opcode_c6xx, /*208*/ *z900_opcode_c8xx, *z900_opcode_e5xx, *z900_opcode_ecxx, *z900_opcode_edxx; /* TLB - Translation lookaside buffer */ unsigned int tlbID; /* Validation identifier */ TLB tlb; /* Translation lookaside buf */ }; /*-------------------------------------------------------------------*/ /* Structure definition for the Vector Facility */ /*-------------------------------------------------------------------*/ #if defined(_FEATURE_VECTOR_FACILITY) struct VFREGS { /* Vector Facility Registers*/ unsigned int online:1; /* 1=VF is online */ U64 vsr; /* Vector Status Register */ U64 vac; /* Vector Activity Count */ BYTE vmr[VECTOR_SECTION_SIZE/8]; /* Vector Mask Register */ U32 vr[16][VECTOR_SECTION_SIZE]; /* Vector Registers */ }; #endif /*defined(_FEATURE_VECTOR_FACILITY)*/ // #if defined(FEATURE_REGION_RELOCATE) /*-------------------------------------------------------------------*/ /* Zone Parameter Block */ /*-------------------------------------------------------------------*/ struct ZPBLK { RADR mso; /* Main Storage Origin */ RADR msl; /* Main Storage Length */ RADR eso; /* Expanded Storage Origin */ RADR esl; /* Expanded Storage Length */ RADR mbo; /* Measurement block origin */ BYTE mbk; /* Measurement block key */ int mbm; /* Measurement block mode */ int mbd; /* Device connect time mode */ }; // #endif /*defined(FEATURE_REGION_RELOCATE)*/ /*-------------------------------------------------------------------*/ /* System configuration block */ /*-------------------------------------------------------------------*/ struct SYSBLK { #define HDL_VERS_SYSBLK "3.06" /* Internal Version Number */ #define HDL_SIZE_SYSBLK sizeof(SYSBLK) time_t impltime; /* TOD system was IMPL'ed */ int arch_mode; /* Architecturual mode */ /* 0 == S/370 (ARCH_370) */ /* 1 == ESA/390 (ARCH_390) */ /* 2 == ESAME (ARCH_900) */ int arch_z900; /* 1 == ESAME supported */ RADR mainsize; /* Main storage size (bytes) */ BYTE *mainstor; /* -> Main storage */ BYTE *storkeys; /* -> Main storage key array */ U32 xpndsize; /* Expanded size (4K pages) */ BYTE *xpndstor; /* -> Expanded storage */ U64 todstart; /* Time of initialisation */ U64 cpuid; /* CPU identifier for STIDP */ TID wdtid; /* Thread-id for watchdog */ U16 lparnuml; /* #digits (0-2) in lparnum */ U16 lparnum; /* LPAR identification number*/ U16 ipldev; /* IPL device */ int iplcpu; /* IPL cpu */ int ipllcss; /* IPL lcss */ int numcpu; /* Number of CPUs installed */ int numvec; /* Number vector processors */ int maxcpu; /* Max number of CPUs */ int cpus; /* Number CPUs configured */ int hicpu; /* Hi cpu + 1 configured */ int sysepoch; /* TOD clk epoch (1900/1960) */ int topchnge; /* 1 = Topology Change Report pending (CPU cfg on/off) */ COND cpucond; /* CPU config/deconfig cond */ LOCK cpulock[MAX_CPU_ENGINES]; /* CPU lock */ TID cputid[MAX_CPU_ENGINES]; /* CPU thread identifiers */ BYTE ptyp[MAX_CPU_ENGINES]; /* SCCB ptyp for each engine */ LOCK todlock; /* TOD clock update lock */ TID todtid; /* Thread-id for TOD update */ REGS *regs[MAX_CPU_ENGINES+1]; /* Registers for each CPU */ #if defined(_FEATURE_VECTOR_FACILITY) VFREGS vf[MAX_CPU_ENGINES]; /* Vector Facility */ #endif /*defined(_FEATURE_VECTOR_FACILITY)*/ #if defined(_FEATURE_SIE) ZPBLK zpb[FEATURE_SIE_MAXZONES]; /* SIE Zone Parameter Blk*/ #endif /*defined(_FEATURE_SIE)*/ #if defined(OPTION_FOOTPRINT_BUFFER) REGS footprregs[MAX_CPU_ENGINES][OPTION_FOOTPRINT_BUFFER]; U32 footprptr[MAX_CPU_ENGINES]; #endif #define LOCK_OWNER_NONE 0xFFFF #define LOCK_OWNER_OTHER 0xFFFE U16 mainowner; /* Mainlock owner */ U16 intowner; /* Intlock owner */ LOCK mainlock; /* Main storage lock */ LOCK intlock; /* Interrupt lock */ LOCK iointqlk; /* I/O Interrupt Queue lock */ LOCK sigplock; /* Signal processor lock */ ATTR detattr; /* Detached thread attribute */ ATTR joinattr; /* Joinable thread attribute */ #define DETACHED &sysblk.detattr /* (helper macro) */ #define JOINABLE &sysblk.joinattr /* (helper macro) */ TID cnsltid; /* Thread-id for console */ TID socktid; /* Thread-id for sockdev */ /* 3270 Console Keep-Alive: */ int kaidle; /* Keepalive idle seconds */ int kaintv; /* Keepalive probe interval */ int kacnt; /* Keepalive probe count */ #if defined( OPTION_WAKEUP_SELECT_VIA_PIPE ) LOCK cnslpipe_lock; /* signaled flag access lock */ int cnslpipe_flag; /* 1 == already signaled */ int cnslwpipe; /* fd for sending signal */ int cnslrpipe; /* fd for receiving signal */ LOCK sockpipe_lock; /* signaled flag access lock */ int sockpipe_flag; /* 1 == already signaled */ int sockwpipe; /* Sockdev signaling pipe Wr */ int sockrpipe; /* Sockdev signaling pipe Rd */ #endif // defined( OPTION_WAKEUP_SELECT_VIA_PIPE ) RADR mbo; /* Measurement block origin */ BYTE mbk; /* Measurement block key */ int mbm; /* Measurement block mode */ int mbd; /* Device connect time mode */ int diag8cmd; /* Allow diagnose 8 commands */ #define DIAG8CMD_ECHO 0x80 /* Echo command to console */ #define DIAG8CMD_ENABLE 0x01 /* Enable DIAG8 interface */ BYTE shcmdopt; /* 'sh'ell command option */ #define SHCMDOPT_DISABLE 0x80 /* Globally disable 'sh' cmd */ #define SHCMDOPT_NODIAG8 0x40 /* Disallow only for DIAG8 */ int panrate; /* Panel refresh rate */ int timerint; /* microsecs timer interval */ char *pantitle; /* Alt console panel title */ #if defined(OPTION_HAO) TID haotid; /* Herc Auto-Oper thread-id */ #endif /* defined(OPTION_HAO) */ #if defined(OPTION_SCSI_TAPE) int auto_scsi_mount_secs; /* Check for SCSI tape mount frequency; 0 == disabled */ #define DEFAULT_AUTO_SCSI_MOUNT_SECS (5) #endif DEVBLK *firstdev; /* -> First device block */ DEVBLK *sysgdev; /* -> devblk for SYSG console*/ #if defined(OPTION_FAST_DEVLOOKUP) DEVBLK ***devnum_fl; /* 1st level table for fast */ /* devnum lookup */ DEVBLK ***subchan_fl; /* Subchannel table fast */ /* lookup table */ #endif /* FAST_DEVICE_LOOKUP */ U16 highsubchan[FEATURE_LCSS_MAX]; /* Highest subchan+1 */ U32 chp_reset[8]; /* Channel path reset masks */ IOINT *iointq; /* I/O interrupt queue */ #if !defined(OPTION_FISHIO) DEVBLK *ioq; /* I/O queue */ LOCK ioqlock; /* I/O queue lock */ COND ioqcond; /* I/O queue condition */ int devtwait; /* Device threads waiting */ int devtnbr; /* Number of device threads */ int devtmax; /* Max device threads */ int devthwm; /* High water mark */ int devtunavail; /* Count thread unavailable */ #endif // !defined(OPTION_FISHIO) RADR addrlimval; /* Address limit value (SAL) */ #if defined(FEATURE_VM_BLOCKIO) U16 servcode; /* External interrupt code */ BYTE biosubcd; /* Block I/O sub int. code */ BYTE biostat; /* Block I/O status */ U64 bioparm; /* Block I/O interrupt parm */ DEVBLK *biodev; /* Block I/O device */ /* Note: biodev is only used to detect BIO interrupt tracing */ #endif /* defined(FEATURE_VM_BLOCKIO) */ U32 servparm; /* Service signal parameter */ unsigned int /* Flags */ daemon_mode:1, /* Daemon mode active */ panel_init:1, /* Panel display initialized */ npquiet:1, /* New Panel quiet indicator */ sigintreq:1, /* 1 = SIGINT request pending*/ insttrace:1, /* 1 = Instruction trace */ inststep:1, /* 1 = Instruction step */ shutdown:1, /* 1 = shutdown requested */ shutfini:1, /* 1 = shutdown complete */ main_clear:1, /* 1 = mainstor is cleared */ xpnd_clear:1, /* 1 = xpndstor is cleared */ showregsfirst:1, /* 1 = show regs before inst */ showregsnone:1, /* 1 = show no registers */ nomountedtapereinit:1, /* 1 = disallow tape devinit if tape already mounted */ legacysenseid:1, /* ena/disa senseid on */ /* legacy devices */ #if defined(OPTION_IPLPARM) haveiplparm:1, /* IPL PARM a la VM */ #endif logoptnotime:1; /* 1 = don't timestamp log */ U32 ints_state; /* Common Interrupts Status */ CPU_BITMAP config_mask; /* Configured CPUs */ CPU_BITMAP started_mask; /* Started CPUs */ CPU_BITMAP waiting_mask; /* Waiting CPUs */ U64 traceaddr[2]; /* Tracing address range */ U64 stepaddr[2]; /* Stepping address range */ #if defined(OPTION_IPLPARM) BYTE iplparmstring[64]; /* 64 bytes loadable at IPL */ #endif #ifdef FEATURE_ECPSVM // /* ECPS:VM */ struct { u_int level:16; u_int debug:1; u_int available:1; } ecpsvm; /* ECPS:VM structure */ // #endif U64 pgminttr; /* Program int trace mask */ int pcpu; /* Tgt CPU panel cmd & displ */ int hercprio; /* Hercules process priority */ int todprio; /* TOD Clock thread priority */ int cpuprio; /* CPU thread priority */ int devprio; /* Device thread priority */ TID httptid; /* HTTP listener thread id */ U16 httpport; /* HTTP port number or zero */ int httpauth; /* HTTP auth required flag */ char *httpuser; /* HTTP userid */ char *httppass; /* HTTP password */ char *httproot; /* HTTP root */ #if defined( OPTION_TAPE_AUTOMOUNT ) TAMDIR *tamdir; /* Acc/Rej AUTOMOUNT dir ctl */ char *defdir; /* Default AUTOMOUNT dir */ #endif /* Fields used by SYNCHRONIZE_CPUS */ int syncing; /* 1=Sync in progress */ CPU_BITMAP sync_mask; /* CPU mask for syncing CPUs */ COND sync_cond; /* COND for syncing CPU */ COND sync_bc_cond; /* COND for other CPUs */ #if defined(_FEATURE_ASN_AND_LX_REUSE) int asnandlxreuse; /* ASN And LX Reuse enable */ #endif #if defined(OPTION_SHARED_DEVICES) TID shrdtid; /* Shared device listener */ U16 shrdport; /* Shared device server port */ U32 shrdcount; /* IO count */ SHRD_TRACE *shrdtrace; /* Internal trace table */ SHRD_TRACE *shrdtracep; /* Current pointer */ SHRD_TRACE *shrdtracex; /* End of trace table */ int shrdtracen; /* Number of entries */ #endif #ifdef OPTION_IODELAY_KLUDGE int iodelay; /* I/O delay kludge for linux*/ #endif /*OPTION_IODELAY_KLUDGE*/ #if defined( HTTP_SERVER_CONNECT_KLUDGE ) int http_server_kludge_msecs; #endif // defined( HTTP_SERVER_CONNECT_KLUDGE ) #if !defined(NO_SETUID) uid_t ruid, euid, suid; gid_t rgid, egid, sgid; #endif /*!defined(NO_SETUID)*/ #if defined(OPTION_COUNTING) long long count[OPTION_COUNTING]; #define COUNT(n) sysblk.count[(n)]++ #else #define COUNT(n) #endif #if defined(OPTION_INSTRUCTION_COUNTING) LOCK icount_lock; #define IMAP_FIRST sysblk.imap01 U64 imap01[256]; U64 imapa4[256]; U64 imapa5[16]; U64 imapa6[256]; U64 imapa7[16]; U64 imapb2[256]; U64 imapb3[256]; U64 imapb9[256]; U64 imapc0[16]; U64 imapc2[16]; /*@Z9*/ U64 imapc4[16]; /*208*/ U64 imapc6[16]; /*208*/ U64 imapc8[16]; U64 imape3[256]; U64 imape4[256]; U64 imape5[256]; U64 imapeb[256]; U64 imapec[256]; U64 imaped[256]; U64 imapxx[256]; #define IMAP_SIZE \ ( sizeof(sysblk.imap01) \ + sizeof(sysblk.imapa4) \ + sizeof(sysblk.imapa5) \ + sizeof(sysblk.imapa6) \ + sizeof(sysblk.imapa7) \ + sizeof(sysblk.imapb2) \ + sizeof(sysblk.imapb3) \ + sizeof(sysblk.imapb9) \ + sizeof(sysblk.imapc0) \ + sizeof(sysblk.imapc2) /*@Z9*/ \ + sizeof(sysblk.imapc4) /*208*/ \ + sizeof(sysblk.imapc6) /*208*/ \ + sizeof(sysblk.imapc8) \ + sizeof(sysblk.imape3) \ + sizeof(sysblk.imape4) \ + sizeof(sysblk.imape5) \ + sizeof(sysblk.imapeb) \ + sizeof(sysblk.imapec) \ + sizeof(sysblk.imaped) \ + sizeof(sysblk.imapxx) ) #endif char *logofile; /* Fancy 3270 logo box */ char **herclogo; /* 3270 Logo data */ size_t logolines; /* Number of lines in logo */ #if defined(OPTION_MIPS_COUNTING) /* Merged Counters for all CPUs */ U64 instcount; /* Instruction counter */ U32 mipsrate; /* Instructions per second */ U32 siosrate; /* IOs per second */ #endif /*defined(OPTION_MIPS_COUNTING)*/ #ifdef OPTION_CMDTGT int cmdtgt; /* 0=herc,1=scp,2=!scp */ #endif // OPTION_CMDTGT int regs_copy_len; /* Length to copy for REGS */ REGS dummyregs; /* Regs for unconfigured CPU */ #ifdef OPTION_MSGHLD int keep_timeout_secs; /* Message hold time */ #endif }; /*-------------------------------------------------------------------*/ /* I/O interrupt queue entry */ /*-------------------------------------------------------------------*/ struct IOINT { /* I/O interrupt queue entry */ IOINT *next; /* -> next interrupt entry */ DEVBLK *dev; /* -> Device block */ int priority; /* Device priority */ unsigned int pending:1, /* 1=Normal interrupt */ pcipending:1, /* 1=PCI interrupt */ attnpending:1; /* 1=ATTN interrupt */ }; /*-------------------------------------------------------------------*/ /* Device configuration block */ /*-------------------------------------------------------------------*/ struct DEVBLK { /* Device configuration block*/ #define HDL_VERS_DEVBLK "3.05" /* Internal Version Number */ #define HDL_SIZE_DEVBLK sizeof(DEVBLK) DEVBLK *nextdev; /* -> next device block */ REGS *regs; /* -> REGS if syncio */ LOCK lock; /* Device block lock */ int allocated; /* Device block free/in use */ /* device identification */ U16 ssid; /* Subsystem ID incl. lcssid */ U16 subchan; /* Subchannel number */ U16 devnum; /* Device number */ U16 devtype; /* Device type */ U16 chanset; /* Channel Set to which this device is connected S/370 */ char *typname; /* Device type name */ int member; /* Group member number */ DEVGRP *group; /* Device Group */ int argc; /* Init number arguments */ char **argv; /* Init arguments */ /* Storage accessible by device */ BYTE *mainstor; /* -> Main storage */ BYTE *storkeys; /* -> Main storage key array */ RADR mainlim; /* Central Storage limit or */ /* guest storage limit (SIE) */ char filename[PATH_MAX+1]; /* filename (plus poss "|") */ /* device i/o fields... */ int fd; /* File desc / socket number */ FILE *fh; /* associated File handle */ bind_struct* bs; /* -> bind_struct if socket- device, NULL otherwise */ /* device buffer management fields */ int bufcur; /* Buffer data identifier */ BYTE *buf; /* -> Device data buffer */ int bufsize; /* Device data buffer size */ int buflen; /* Device buffer length used */ int bufoff; /* Offset into data buffer */ int bufoffhi; /* Highest offset allowed */ int bufupdlo; /* Lowest offset updated */ int bufupdhi; /* Highest offset updated */ U32 bufupd; /* 1=Buffer updated */ /* device cache management fields */ int cache; /* Current cache index */ int cachehits; /* Cache hits */ int cachemisses; /* Cache misses */ int cachewaits; /* Cache waits */ /* device compression support */ int comps; /* Acceptable compressions */ int comp; /* Compression used */ int compoff; /* Offset to compressed data */ /* device i/o scheduling fields... */ TID tid; /* Thread-id executing CCW */ int priority; /* I/O q scehduling priority */ DEVBLK *nextioq; /* -> next device in I/O q */ IOINT ioint; /* Normal i/o interrupt queue entry */ IOINT pciioint; /* PCI i/o interrupt queue entry */ IOINT attnioint; /* ATTN i/o interrupt queue entry */ int cpuprio; /* CPU thread priority */ int devprio; /* Device thread priority */ /* fields used during ccw execution... */ BYTE chained; /* Command chain and data chain bits from previous CCW */ BYTE prev_chained; /* Chaining flags from CCW preceding the data chain */ BYTE code; /* Current CCW opcode */ BYTE prevcode; /* Previous CCW opcode */ int ccwseq; /* CCW sequence number */ U32 ccwaddr; U16 idapmask; BYTE idawfmt; BYTE ccwfmt; BYTE ccwkey; /* device handler function pointers... */ DEVHND *hnd; /* -> Device handlers */ /* Supplemental handler functions - Set by init handler @ISW */ /* Function invoked during HDV/HIO & HSCH instructions @ISW */ /* processing occurs in channel.c in haltio et al. @ISW */ /* when the device is busy, but the channel subsystem @ISW */ /* does not know how to perform the halt itself but has @ISW */ /* to rely on the handler to perform the halt @ISW */ void ( *halt_device)(DEVBLK *); /* @ISW */ DEVIM *immed; /* Model Specific IM codes */ /* (overrides devhnd immed) */ int is_immed; /* Last command is Immediate */ /* emulated architecture fields... (MUST be aligned!) */ int reserved1; /* ---(ensure alignment)---- */ ORB orb; /* Operation request blk @IWZ*/ PMCW pmcw; /* Path management ctl word */ SCSW scsw; /* Subchannel status word(XA)*/ SCSW pciscsw; /* PCI subchannel status word*/ SCSW attnscsw; /* ATTNsubchannel status word*/ BYTE csw[8]; /* Channel status word(S/370)*/ BYTE pcicsw[8]; /* PCI channel status word */ BYTE attncsw[8]; /* ATTN channel status word */ ESW esw; /* Extended status word */ BYTE ecw[32]; /* Extended control word */ U32 numsense; /* Number of sense bytes */ BYTE sense[32]; /* Sense bytes */ U32 numdevid; /* Number of device id bytes */ BYTE devid[256]; /* Device identifier bytes */ U32 numdevchar; /* Number of devchar bytes */ BYTE devchar[64]; /* Device characteristics */ BYTE pgstat; /* Path Group Status */ BYTE pgid[11]; /* Path Group ID */ BYTE reserved2[4]; /* (pad/align/unused/avail) */ COND resumecond; /* Resume condition */ COND iocond; /* I/O active condition */ int iowaiters; /* Number of I/O waiters */ int ioactive; /* System Id active on device*/ #define DEV_SYS_NONE 0 /* No active system on device*/ #define DEV_SYS_LOCAL 0xffff /* Local system active on dev*/ BYTE drvpwd[11]; /* Password for drive */ BYTE reserved3; /* (pad/align/unused/avail) */ /* control flags... */ unsigned int /* Flags */ #ifdef OPTION_CKD_KEY_TRACING ckdkeytrace:1, /* 1=Log CKD_KEY_TRACE */ #endif /*OPTION_CKD_KEY_TRACING*/ syncio:2, /* 1=Synchronous I/Os allowed*/ shared:1, /* 1=Device is shareable */ console:1, /* 1=Console device */ connected:1, /* 1=Console client connected*/ readpending:2, /* 1=Console read pending */ connecting:1, /* 1=Connecting to remote */ localhost:1, /* 1=Remote is local */ batch:1, /* 1=Called by dasdutil */ dasdcopy:1, /* 1=Called by dasdcopy */ oslinux:1, /* 1=Linux */ ccwtrace:1, /* 1=CCW trace */ ccwstep:1, /* 1=CCW single step */ cdwmerge:1; /* 1=Channel will merge data chained write CCWs */ unsigned int /* Device state - serialized by dev->lock */ busy:1, /* 1=Device is busy */ reserved:1, /* 1=Device is reserved */ suspended:1, /* 1=Channel pgm suspended */ pending:1, /* 1=I/O interrupt pending */ pcipending:1, /* 1=PCI interrupt pending */ attnpending:1, /* 1=ATTN interrupt pending */ startpending:1, /* 1=startio pending */ resumesuspended:1; /* 1=Hresuming suspended dev */ #define IOPENDING(_dev) ((_dev)->pending || (_dev)->pcipending || (_dev)->attnpending) #define INITIAL_POWERON_370() \ ( dev->crwpending && ARCH_370 == sysblk.arch_mode ) int crwpending; /* 1=CRW pending */ int syncio_active; /* 1=Synchronous I/O active */ int syncio_retry; /* 1=Retry I/O asynchronously*/ /* Synchronous I/O */ U32 syncio_addr; /* Synchronous i/o ccw addr */ U64 syncios; /* Number synchronous I/Os */ U64 asyncios; /* Number asynchronous I/Os */ /* Device dependent data (generic) */ void *dev_data; #ifdef EXTERNALGUI /* External GUI fields */ GUISTAT* pGUIStat; /* EXTERNALGUI Dev Stat Ctl */ #endif #if defined(FEATURE_VM_BLOCKIO) /* VM DIAGNOSE X'250' Emulation Environment */ struct VMBIOENV *vmd250env; /* Established environment */ #endif /* defined(FEATURE_VM_BLOCKIO) */ /* Fields for remote devices */ struct in_addr rmtaddr; /* Remote address */ U16 rmtport; /* Remote port number */ U16 rmtnum; /* Remote device number */ int rmtid; /* Remote Id */ int rmtrel; /* Remote release level */ DBLWRD rmthdr; /* Remote header */ int rmtcomp; /* Remote compression parm */ int rmtcomps; /* Supported compressions */ int rmtpurgen; /* Remote purge count */ FWORD *rmtpurge; /* Remote purge list */ #ifdef OPTION_SHARED_DEVICES /* Fields for device sharing */ TID shrdtid; /* Device thread id */ int shrdid; /* Id for next client */ int shrdconn; /* Number connected clients */ int shrdwait; /* Signal indicator */ SHRD *shrd[SHARED_MAX_SYS]; /* ->SHRD block */ #endif /* Device dependent fields for console */ struct in_addr ipaddr; /* Client IP address */ in_addr_t acc_ipaddr; /* Allowable clients IP addr */ in_addr_t acc_ipmask; /* Allowable clients IP mask */ U32 rlen3270; /* Length of data in buffer */ int pos3270; /* Current screen position */ int keybdrem; /* Number of bytes remaining in keyboard read buffer */ u_int eab3270:1; /* 1=Extended attributes */ u_int ewa3270:1; /* 1=Last erase was EWA */ u_int prompt1052:1; /* 1=Prompt for linemode i/p */ BYTE aid3270; /* Current input AID value */ BYTE mod3270; /* 3270 model number */ /* Device dependent fields for cardrdr */ char **more_files; /* for more that one file in reader */ char **current_file; /* counts how many additional reader files are avail */ int cardpos; /* Offset of next byte to be read from data buffer */ int cardrem; /* Number of bytes remaining in data buffer */ u_int multifile:1; /* 1=auto-open next i/p file */ u_int rdreof:1; /* 1=Unit exception at EOF */ u_int ebcdic:1; /* 1=Card deck is EBCDIC */ u_int ascii:1; /* 1=Convert ASCII to EBCDIC */ u_int trunc:1; /* Truncate overlength record*/ u_int autopad:1; /* 1=Pad incomplete last rec to 80 bytes if EBCDIC */ /* Device dependent fields for ctcadpt */ DEVBLK *ctcpair; /* -> Paired device block */ int ctcpos; /* next byte offset */ int ctcrem; /* bytes remaining in buffer */ int ctclastpos; /* last packet read */ int ctclastrem; /* last packet read */ u_int ctcxmode:1; /* 0=Basic mode, 1=Extended */ BYTE ctctype; /* CTC_xxx device type */ BYTE netdevname[IFNAMSIZ]; /* network device name */ /* Device dependent fields for printer */ int printpos; /* Number of bytes already placed in print buffer */ int printrem; /* Number of bytes remaining in print buffer */ pid_t ptpcpid; /* print-to-pipe child pid */ u_int crlf:1; /* 1=CRLF delimiters, 0=LF */ u_int diaggate:1; /* 1=Diagnostic gate command */ u_int fold:1; /* 1=Fold to upper case */ u_int ispiped:1; /* 1=Piped device */ u_int stopprt:1; /* 1=stopped; 0=started */ u_int notrunc:1; /* 1=do not truncate at open */ /* Device dependent fields for tapedev */ void *omadesc; /* -> OMA descriptor array */ U16 omafiles; /* Number of OMA tape files */ U16 curfilen; /* Current file number */ U32 blockid; /* Current device block ID */ off_t nxtblkpos; /* Offset from start of file to next block */ off_t prvblkpos; /* Offset from start of file to previous block */ U16 curblkrem; /* Number of bytes unread from current block */ U16 curbufoff; /* Offset into buffer of data for next data chained CCW */ U16 tapssdlen; /* #of bytes of data prepared for Read Subsystem Data */ HETB *hetb; /* HET control block */ struct /* HET device parms */ { u_int compress:1; /* 1=Compression enabled */ u_int method:3; /* Compression method */ u_int level:4; /* Compression level */ u_int strictsize:1; /* Strictly enforce MAXSIZE */ u_int displayfeat:1; /* Device has a display */ /* feature installed */ u_int deonirq:1; /* DE on IRQ on tape motion */ /* MVS 3.8j workaround */ u_int logical_readonly:1; /* Tape is forced READ ONLY */ U16 chksize; /* Chunk size */ off_t maxsize; /* Maximum allowed TAPE file size */ } tdparms; /* HET device parms */ off_t eotmargin; /* Amount of space left before reporting EOT (in bytes) */ u_int fenced:1; /* 1=Pos err; volume fenced */ u_int readonly:1; /* 1=Tape is write-protected */ u_int sns_pending:1; /* Contingency Allegiance */ /* - means : don't build a */ /* sense on X'04' : it's */ /* aleady there */ /* NOTE : flag cleared by */ /* sense command only */ /* or a device init */ u_int SIC_supported:1; /* 1=Spec Intcpt Cond support*/ u_int SIC_active:1; /* 1=SIC active */ u_int forced_logging:1; /* 1=Forced Error Logging */ u_int eotwarning:1; /* 1=EOT warning area reached*/ #if defined( OPTION_TAPE_AUTOMOUNT ) u_int noautomount:1; /* 1=AUTOMOUNT disabled */ #endif U32 msgid; /* Message Id of async. i/o */ #if defined(OPTION_SCSI_TAPE) struct mtget mtget; /* SCSI tape status struct */ #define sstat mtget.mt_gstat /* Generic SCSI tape device- independent status field; (struct mtget->mt_gstat) */ TID stape_mountmon_tid; /* Tape-mount monitor thread */ u_int stape_close_rewinds:1; /* 1=Rewind at close */ u_int stape_blkid_32:1; /* 1=block-ids are 32 bits */ u_int stape_no_erg:1; /* 1=ignore Erase Gap CCWs */ u_int stape_getstat_busy:1; /* 1=Status wrkr thrd busy */ u_int stape_threads_exit:1; /* 1=Ask helpr thrds to exit */ TID stape_getstat_tid; /* Tape status wrkr thrd tid */ LOCK stape_getstat_lock; /* LOCK for status wrkr thrd */ COND stape_getstat_cond; /* COND for status wrkr thrd */ COND stape_exit_cond; /* thread wait for exit COND */ struct mtget stape_getstat_mtget;/* status wrkr thrd status */ #define stape_getstat_sstat stape_getstat_mtget.mt_gstat /* (gstat) */ struct timeval stape_getstat_query_tod;/* TOD of actual drive query */ #endif BYTE tapedevt; /* Hercules tape device type */ TAPEMEDIA_HANDLER *tmh; /* Tape Media Handling */ /* dispatcher */ /* ---------- Autoloader feature --------------------------- */ TAPEAUTOLOADENTRY *als; /* Autoloader stack */ int alss; /* Autoloader stack size */ int alsix; /* Current Autoloader index */ char **al_argv; /* ARGV in autoloader */ int al_argc; /* ARGC in autoloader */ /* ---------- end Autoloader feature ----------------------- */ /* 3480/3490/3590 Message display */ char tapemsg1[9]; /* 1st Host Message */ char tapemsg2[9]; /* 2nd Host Message */ char tapesysmsg[32]; /* Unit Message (SYS)*/ char *prev_tapemsg; /* Previously displayed msg */ BYTE tapedisptype; /* Type of message display */ BYTE tapedispflags; /* How the msg is displayed */ #define TAPEDISPTYP_IDLE 0 /* "READY" "NT RDY" etc (SYS)*/ #define TAPEDISPTYP_LOCATING 1 /* Locate in progress (SYS)*/ #define TAPEDISPTYP_ERASING 2 /* DSE in progress (SYS)*/ #define TAPEDISPTYP_REWINDING 3 /* Rewind in progress (SYS)*/ #define TAPEDISPTYP_UNLOADING 4 /* Unload in progress (SYS)*/ #define TAPEDISPTYP_CLEAN 5 /* Clean recommended (SYS)*/ #define TAPEDISPTYP_MOUNT 6 /* Display Until Mounted */ #define TAPEDISPTYP_UNMOUNT 7 /* Display Until Unmounted */ #define TAPEDISPTYP_UMOUNTMOUNT 8 /* Display #1 Until Unmounted, then #2 Until Mounted */ #define TAPEDISPTYP_WAITACT 9 /* Display until motion */ #define IS_TAPEDISPTYP_SYSMSG( dev ) \ (0 \ || TAPEDISPTYP_IDLE == (dev)->tapedisptype \ || TAPEDISPTYP_LOCATING == (dev)->tapedisptype \ || TAPEDISPTYP_ERASING == (dev)->tapedisptype \ || TAPEDISPTYP_REWINDING == (dev)->tapedisptype \ || TAPEDISPTYP_UNLOADING == (dev)->tapedisptype \ || TAPEDISPTYP_CLEAN == (dev)->tapedisptype \ ) #define TAPEDISPFLG_ALTERNATE 0x80 /* Alternate msgs 1 & 2 */ #define TAPEDISPFLG_BLINKING 0x40 /* Selected msg blinks */ #define TAPEDISPFLG_MESSAGE2 0x20 /* Display msg 2 instead of 1*/ #define TAPEDISPFLG_AUTOLOADER 0x10 /* Autoloader request */ #define TAPEDISPFLG_REQAUTOMNT 0x08 /* ReqAutoMount has work */ /* Device dependent fields for Comm Line */ COMMADPT *commadpt; /* Single structure pointer */ /* Device dependent fields for dasd (fba and ckd) */ char *dasdsfn; /* Shadow file name */ char *dasdsfx; /* Pointer to suffix char */ /* Device dependent fields for fbadasd */ FBADEV *fbatab; /* Device table entry */ int fbanumblk; /* Number of blocks in device*/ int fbablksiz; /* Physical block size */ off_t fbaorigin; /* Device origin block number*/ off_t fbarba; /* Relative byte offset */ off_t fbaend; /* Last RBA in file */ /* Values from define extent */ u_int fbaxtdef:1; /* 1=Extent defined */ BYTE fbamask; /* Define extent file mask */ U32 fbaxblkn; /* Offset from start of device to first block of extent */ U32 fbaxfirst; /* Block number within dataset of first block of extent */ U32 fbaxlast; /* Block number within dataset of last block of extent */ /* Values from locate */ BYTE fbaoper; /* Locate operation byte */ U16 fbalcnum; /* Block count for locate */ U32 fbalcblk; /* Block number within dataset of first block for locate */ /* Device dependent fields for ckddasd */ int ckdnumfd; /* Number of CKD image files */ int ckdfd[CKD_MAXFILES]; /* CKD image file descriptors*/ int ckdhitrk[CKD_MAXFILES]; /* Highest track number in each CKD image file */ CKDDEV *ckdtab; /* Device table entry */ CKDCU *ckdcu; /* Control unit entry */ off_t ckdtrkoff; /* Track image file offset */ int ckdcyls; /* Number of cylinders */ int ckdtrks; /* Number of tracks */ int ckdheads; /* #of heads per cylinder */ int ckdtrksz; /* Track size */ int ckdcurcyl; /* Current cylinder */ int ckdcurhead; /* Current head */ int ckdcurrec; /* Current record id */ int ckdcurkl; /* Current record key length */ int ckdorient; /* Current orientation */ int ckdcuroper; /* Curr op: read=6, write=5 */ U16 ckdcurdl; /* Current record data length*/ U16 ckdrem; /* #of bytes from current position to end of field */ U16 ckdpos; /* Offset into buffer of data for next data chained CCW */ U16 ckdxblksz; /* Define extent block size */ U16 ckdxbcyl; /* Define extent begin cyl */ U16 ckdxbhead; /* Define extent begin head */ U16 ckdxecyl; /* Define extent end cyl */ U16 ckdxehead; /* Define extent end head */ BYTE ckdfmask; /* Define extent file mask */ BYTE ckdxgattr; /* Define extent global attr */ U16 ckdltranlf; /* Locate record transfer length factor */ U16 ckdlmask; /* Locate record mask */ BYTE ckdloper; /* Locate record operation */ BYTE ckdlaux; /* Locate record aux byte */ BYTE ckdlcount; /* Locate record count */ BYTE ckdreserved1; /* Alignment */ void *cckd_ext; /* -> Compressed ckddasd extension otherwise NULL */ u_int ckd3990:1; /* 1=Control unit is 3990 */ u_int ckdxtdef:1; /* 1=Define Extent processed */ u_int ckdsetfm:1; /* 1=Set File Mask processed */ u_int ckdlocat:1; /* 1=Locate Record processed */ u_int ckdspcnt:1; /* 1=Space Count processed */ u_int ckdseek:1; /* 1=Seek command processed */ u_int ckdskcyl:1; /* 1=Seek cylinder processed */ u_int ckdrecal:1; /* 1=Recalibrate processed */ u_int ckdrdipl:1; /* 1=Read IPL processed */ u_int ckdxmark:1; /* 1=End of track mark found */ u_int ckdhaeq:1; /* 1=Search Home Addr Equal */ u_int ckdideq:1; /* 1=Search ID Equal */ u_int ckdkyeq:1; /* 1=Search Key Equal */ u_int ckdwckd:1; /* 1=Write R0 or Write CKD */ u_int ckdtrkof:1; /* 1=Track ovfl on this blk */ u_int ckdssi:1; /* 1=Set Special Intercept */ u_int ckdnolazywr:1; /* 1=Perform updates now */ u_int ckdrdonly:1; /* 1=Open read only */ u_int ckdwrha:1; /* 1=Write Home Address */ /* Line above ISW20030819-1 */ u_int ckdfakewr:1; /* 1=Fake successful write for read only file */ U16 ckdssdlen; /* #of bytes of data prepared for Read Subsystem Data */ }; /*-------------------------------------------------------------------*/ /* Device Group Structure (just a group of related devices) */ /*-------------------------------------------------------------------*/ struct DEVGRP { /* Device Group Structure */ int members; /* #of member devices in grp */ int acount; /* #allocated members in grp */ void *grp_data; /* Group dep data (generic) */ DEVBLK *memdev[FLEXIBLE_ARRAY]; /* Member devices */ }; /*-------------------------------------------------------------------*/ /* Structure definitions for CKD headers */ /*-------------------------------------------------------------------*/ struct CKDDASD_DEVHDR { /* Device header */ BYTE devid[8]; /* Device identifier */ FWORD heads; /* #of heads per cylinder (bytes in reverse order) */ FWORD trksize; /* Track size (reverse order)*/ BYTE devtype; /* Last 2 digits of device type (0x80=3380, 0x90=3390) */ BYTE fileseq; /* CKD image file sequence no. (0x00=only file, 0x01=first file of multiple files) */ HWORD highcyl; /* Highest cylinder number on this file, or zero if this is the last or only file (bytes in reverse order) */ BYTE resv[492]; /* Reserved */ }; struct CKDDASD_TRKHDR { /* Track header */ BYTE bin; /* Bin number */ HWORD cyl; /* Cylinder number */ HWORD head; /* Head number */ }; struct CKDDASD_RECHDR { /* Record header */ HWORD cyl; /* Cylinder number */ HWORD head; /* Head number */ BYTE rec; /* Record number */ BYTE klen; /* Key length */ HWORD dlen; /* Data length */ }; #define CKDDASD_DEVHDR_SIZE ((ssize_t)sizeof(CKDDASD_DEVHDR)) #define CKDDASD_TRKHDR_SIZE ((ssize_t)sizeof(CKDDASD_TRKHDR)) #define CKDDASD_RECHDR_SIZE ((ssize_t)sizeof(CKDDASD_RECHDR)) /* Null track formats */ #define CKDDASD_NULLTRK_FMT0 0 /* ha r0 r1 eot */ #define CKDDASD_NULLTRK_FMT1 1 /* ha r0 eot */ #define CKDDASD_NULLTRK_FMT2 2 /* linux (3390 only) */ #define CKDDASD_NULLTRK_FMTMAX CKDDASD_NULLTRK_FMT2 #define CKDDASD_NULLTRK_SIZE0 (5 + 8 + 8 + 8 + 8) #define CKDDASD_NULLTRK_SIZE1 (5 + 8 + 8 + 8) #define CKDDASD_NULLTRK_SIZE2 (5 + 8 + 8 + (12 * (8 + 4096)) + 8) /*-------------------------------------------------------------------*/ /* Structure definitions for Compressed CKD devices */ /*-------------------------------------------------------------------*/ struct CCKDDASD_DEVHDR { /* Compress device header */ /* 0 */BYTE vrm[3]; /* Version Release Modifier */ /* 3 */BYTE options; /* Options byte */ /* 4 */S32 numl1tab; /* Size of lvl 1 table */ /* 8 */S32 numl2tab; /* Size of lvl 2 tables */ /* 12 */U32 size; /* File size */ /* 16 */U32 used; /* File used */ /* 20 */U32 free; /* Position to free space */ /* 24 */U32 free_total; /* Total free space */ /* 28 */U32 free_largest; /* Largest free space */ /* 32 */S32 free_number; /* Number free spaces */ /* 36 */U32 free_imbed; /* Imbedded free space */ /* 40 */FWORD cyls; /* Cylinders on device */ /* 44 */BYTE nullfmt; /* Null track format */ /* 45 */BYTE compress; /* Compression algorithm */ /* 46 */S16 compress_parm; /* Compression parameter */ /* 48 */BYTE resv2[464]; /* Reserved */ }; #define CCKD_DEVHDR CCKDDASD_DEVHDR #define CCKD_VERSION 0 #define CCKD_RELEASE 3 #define CCKD_MODLVL 1 #define CCKD_NOFUDGE 1 /* [deprecated] */ #define CCKD_BIGENDIAN 2 #define CCKD_SPERRS 32 /* Space errors detected */ #define CCKD_ORDWR 64 /* Opened read/write since last chkdsk */ #define CCKD_OPENED 128 #define CCKD_COMPRESS_NONE 0x00 #define CCKD_COMPRESS_ZLIB 0x01 #define CCKD_COMPRESS_BZIP2 0x02 #define CCKD_COMPRESS_MASK 0x03 #define CCKD_STRESS_MINLEN 4096 #if defined(HAVE_LIBZ) #define CCKD_STRESS_COMP CCKD_COMPRESS_ZLIB #else #define CCKD_STRESS_COMP CCKD_COMPRESS_NONE #endif #define CCKD_STRESS_PARM1 4 #define CCKD_STRESS_PARM2 2 struct CCKD_L2ENT { /* Level 2 table entry */ U32 pos; /* Track offset */ U16 len; /* Track length */ U16 size; /* Track size (size >= len) */ }; struct CCKD_FREEBLK { /* Free block (file) */ U32 pos; /* Position next free blk */ U32 len; /* Length this free blk */ }; struct CCKD_IFREEBLK { /* Free block (internal) */ U32 pos; /* Position next free blk */ U32 len; /* Length this free blk */ int prev; /* Index to prev free blk */ int next; /* Index to next free blk */ int pending; /* 1=Free pending (don't use)*/ }; struct CCKD_RA { /* Readahead queue entry */ DEVBLK *dev; /* Readahead device */ int trk; /* Readahead track */ int prev; /* Index to prev entry */ int next; /* Index to next entry */ }; typedef U32 CCKD_L1ENT; /* Level 1 table entry */ typedef CCKD_L1ENT CCKD_L1TAB[]; /* Level 1 table */ typedef CCKD_L2ENT CCKD_L2TAB[256]; /* Level 2 table */ typedef char CCKD_TRACE[128]; /* Trace table entry */ #define CCKDDASD_DEVHDR_SIZE ((ssize_t)sizeof(CCKDDASD_DEVHDR)) #define CCKD_DEVHDR_SIZE CCKDDASD_DEVHDR_SIZE #define CCKD_DEVHDR_POS CKDDASD_DEVHDR_SIZE #define CCKD_L1ENT_SIZE ((ssize_t)sizeof(CCKD_L1ENT)) #define CCKD_L1TAB_POS ((CCKD_DEVHDR_POS)+(CCKD_DEVHDR_SIZE)) #define CCKD_L2ENT_SIZE ((ssize_t)sizeof(CCKD_L2ENT)) #define CCKD_L2TAB_SIZE ((ssize_t)sizeof(CCKD_L2TAB)) #define CCKD_FREEBLK_SIZE ((ssize_t)sizeof(CCKD_FREEBLK)) #define CCKD_FREEBLK_ISIZE ((ssize_t)sizeof(CCKD_IFREEBLK)) #define CCKD_IFREEBLK_SIZE (CCKD_FREEBLK_ISIZE) /* Flag bits */ #define CCKD_SIZE_EXACT 0x01 /* Space obtained is exact */ #define CCKD_SIZE_ANY 0x02 /* Space can be any size */ #define CCKD_L2SPACE 0x04 /* Space for a l2 table */ /* adjustable values */ #define CCKD_FREE_MIN_SIZE 96 /* Minimum free space size */ #define CCKD_FREE_MIN_INCR 32 /* Added for each 1024 spaces*/ #define CCKD_COMPRESS_MIN 512 /* Track images smaller than this won't be compressed */ #define CCKD_MAX_SF 8 /* Maximum number of shadow files: 0 to 9 [0 disables shadow file support] */ #define CCKD_MAX_READAHEADS 16 /* Max readahead trks */ #define CCKD_MAX_RA_SIZE 16 /* Readahead queue size */ #define CCKD_MAX_RA 9 /* Max readahead threads */ #define CCKD_MAX_WRITER 9 /* Max writer threads */ #define CCKD_MAX_GCOL 1 /* Max garbage collectors */ #define CCKD_MAX_TRACE 200000 /* Max nbr trace entries */ #define CCKD_MAX_FREEPEND 4 /* Max free pending cycles */ #define CCKD_MIN_READAHEADS 0 /* Min readahead trks */ #define CCKD_MIN_RA 0 /* Min readahead threads */ #define CCKD_MIN_WRITER 1 /* Min writer threads */ #define CCKD_MIN_GCOL 0 /* Min garbage collectors */ #define CCKD_DEFAULT_RA_SIZE 4 /* Readahead queue size */ #define CCKD_DEFAULT_RA 2 /* Default number readaheads */ #define CCKD_DEFAULT_WRITER 2 /* Default number writers */ #define CCKD_DEFAULT_GCOL 1 /* Default number garbage collectors */ #define CCKD_DEFAULT_GCOLWAIT 10 /* Default wait (seconds) */ #define CCKD_DEFAULT_GCOLPARM 0 /* Default adjustment parm */ #define CCKD_DEFAULT_READAHEADS 2 /* Default nbr to read ahead */ #define CCKD_DEFAULT_FREEPEND -1 /* Default freepend cycles */ #define CFBA_BLOCK_NUM 120 /* Number fba blocks / group */ #define CFBA_BLOCK_SIZE 61440 /* Size of a block group 60k */ /* Number of bytes in an fba block group. Probably should be a multiple of 512 but has to be < 64K */ struct CCKDBLK { /* Global cckd dasd block */ BYTE id[8]; /* "CCKDBLK " */ DEVBLK *dev1st; /* 1st device in cckd queue */ unsigned int batch:1, /* 1=called in batch mode */ sfmerge:1, /* 1=sf-* merge */ sfforce:1; /* 1=sf-* force */ int sflevel; /* sfk xxxx level */ BYTE comps; /* Supported compressions */ BYTE comp; /* Override compression */ int compparm; /* Override compression parm */ LOCK gclock; /* Garbage collector lock */ COND gccond; /* Garbage collector cond */ int gcs; /* Number garbage collectors */ int gcmax; /* Max garbage collectors */ int gcwait; /* Wait time in seconds */ int gcparm; /* Adjustment parm */ LOCK wrlock; /* I/O lock */ COND wrcond; /* I/O condition */ int wrpending; /* Number writes pending */ int wrwaiting; /* Number writers waiting */ int wrs; /* Number writer threads */ int wrmax; /* Max writer threads */ int wrprio; /* Writer thread priority */ LOCK ralock; /* Readahead lock */ COND racond; /* Readahead condition */ int ras; /* Number readahead threads */ int ramax; /* Max readahead threads */ int rawaiting; /* Number threads waiting */ int ranbr; /* Readahead queue size */ int readaheads; /* Nbr tracks to read ahead */ CCKD_RA ra[CCKD_MAX_RA_SIZE]; /* Readahead queue */ int ra1st; /* First readahead entry */ int ralast; /* Last readahead entry */ int rafree; /* Free readahead entry */ LOCK devlock; /* Device chain lock */ COND devcond; /* Device chain condition */ int devusers; /* Number shared users */ int devwaiters; /* Number of waiters */ int freepend; /* Number freepend cycles */ int nostress; /* 1=No stress writes */ int linuxnull; /* 1=Always check nulltrk */ int fsync; /* 1=Perform fsync() */ COND termcond; /* Termination condition */ U64 stats_switches; /* Switches */ U64 stats_cachehits; /* Cache hits */ U64 stats_cachemisses; /* Cache misses */ U64 stats_readaheads; /* Readaheads */ U64 stats_readaheadmisses;/* Readahead misses */ U64 stats_syncios; /* Synchronous i/os */ U64 stats_synciomisses; /* Missed syncios */ U64 stats_iowaits; /* Waits for i/o */ U64 stats_cachewaits; /* Waits for cache */ U64 stats_stresswrites; /* Writes under stress*/ U64 stats_l2cachehits; /* L2 cache hits */ U64 stats_l2cachemisses; /* L2 cache misses */ U64 stats_l2reads; /* L2 reads */ U64 stats_reads; /* Number reads */ U64 stats_readbytes; /* Bytes read */ U64 stats_writes; /* Number writes */ U64 stats_writebytes; /* Bytes written */ U64 stats_gcolmoves; /* Spaces moved */ U64 stats_gcolbytes; /* Bytes moved */ CCKD_TRACE *itrace; /* Internal trace table */ CCKD_TRACE *itracep; /* Current pointer */ CCKD_TRACE *itracex; /* End of trace table */ int itracen; /* Number of entries */ int bytemsgs; /* Limit for `byte 0' msgs */ }; struct CCKDDASD_EXT { /* Ext for compressed ckd */ DEVBLK *devnext; /* cckd device queue */ unsigned int ckddasd:1, /* 1=CKD dasd */ fbadasd:1, /* 1=FBA dasd */ ioactive:1, /* 1=Channel program active */ bufused:1, /* 1=newbuf was used */ updated:1, /* 1=Update occurred */ merging:1, /* 1=File merge in progress */ stopping:1, /* 1=Device is closing */ notnull:1, /* 1=Device has track images */ l2ok:1, /* 1=All l2s below bounds */ sfmerge:1, /* 1=sf-xxxx merge */ sfforce:1; /* 1=sf-xxxx force */ int sflevel; /* sfk xxxx level */ LOCK filelock; /* File lock */ LOCK iolock; /* I/O lock */ COND iocond; /* I/O condition */ long long maxsize; /* Maximum file size */ int iowaiters; /* Number I/O waiters */ int wrpending; /* Number writes pending */ int ras; /* Number readaheads active */ int sfn; /* Number active shadow files*/ int sfx; /* Active level 2 file index */ int l1x; /* Active level 2 table index*/ CCKD_L2ENT *l2; /* Active level 2 table */ int l2active; /* Active level 2 cache entry*/ off_t l2bounds; /* L2 tables boundary */ int active; /* Active cache entry */ BYTE *newbuf; /* Uncompressed buffer */ unsigned int freemin; /* Minimum free space size */ CCKD_IFREEBLK *free; /* Internal free space chain */ int freenbr; /* Number free space entries */ int free1st; /* Index of 1st entry */ int freelast; /* Index of last entry */ int freeavail; /* Index of available entry */ int lastsync; /* Time of last sync */ int ralkup[CCKD_MAX_RA_SIZE];/* Lookup table */ int ratrk; /* Track to readahead */ unsigned int totreads; /* Total nbr trk reads */ unsigned int totwrites; /* Total nbr trk writes */ unsigned int totl2reads; /* Total nbr l2 reads */ unsigned int cachehits; /* Cache hits */ unsigned int readaheads; /* Number trks read ahead */ unsigned int switches; /* Number trk switches */ unsigned int misses; /* Number readahead misses */ int fd[CCKD_MAX_SF+1]; /* File descriptors */ BYTE swapend[CCKD_MAX_SF+1]; /* Swap endian flag */ BYTE open[CCKD_MAX_SF+1]; /* Open flag */ int reads[CCKD_MAX_SF+1]; /* Nbr track reads */ int l2reads[CCKD_MAX_SF+1]; /* Nbr l2 reads */ int writes[CCKD_MAX_SF+1]; /* Nbr track writes */ CCKD_L1ENT *l1[CCKD_MAX_SF+1]; /* Level 1 tables */ CCKDDASD_DEVHDR cdevhdr[CCKD_MAX_SF+1]; /* cckd device hdr */ }; #define CCKD_OPEN_NONE 0 #define CCKD_OPEN_RO 1 #define CCKD_OPEN_RD 2 #define CCKD_OPEN_RW 3 #ifdef EXTERNALGUI struct GUISTAT { char* pszOldStatStr; char* pszNewStatStr; #define GUI_STATSTR_BUFSIZ 256 char szStatStrBuff1[GUI_STATSTR_BUFSIZ]; char szStatStrBuff2[GUI_STATSTR_BUFSIZ]; }; #endif // EXTERNALGUI #endif // _HSTRUCTS_H hercules-3.07/hsys.c000644 000765 000765 00000003276 11301535255 016105 0ustar00jmaynardjmaynard000000 000000 // $Id: hsys.c 5483 2009-10-12 05:49:53Z fish $ // // $Log$ // Revision 1.9 2008/12/24 15:42:14 jj // Add debug entry point for sclp event masks // // Revision 1.8 2008/12/22 13:10:22 jj // Add sclp debug entry points // // Revision 1.7 2008/02/12 08:42:15 fish // dyngui tweaks: new def devlist fmt, new debug_cd_cmd hook // // Revision 1.6 2006/12/08 09:43:28 jj // Add CVS message log // #include "hstdinc.h" #define _HSYS_C_ #include "hercules.h" DLL_EXPORT SYSBLK sysblk; #if defined(EXTERNALGUI) DLL_EXPORT int extgui = 0; #endif #if defined(OPTION_W32_CTCI) DLL_EXPORT int (*debug_tt32_stats)(int) = NULL; DLL_EXPORT void (*debug_tt32_tracing)(int) = NULL; #endif #if defined(OPTION_DYNAMIC_LOAD) DLL_EXPORT void *(*panel_command) (void *); DLL_EXPORT void (*panel_display) (void); DLL_EXPORT void (*daemon_task) (void); DLL_EXPORT int (*config_command) (int argc, char *argv[], char *cmdline); DLL_EXPORT int (*system_command) (int argc, char *argv[], char *cmdline); DLL_EXPORT void *(*debug_cpu_state) (REGS *); DLL_EXPORT void *(*debug_cd_cmd) (char *); DLL_EXPORT void *(*debug_device_state) (DEVBLK *); DLL_EXPORT void *(*debug_program_interrupt) (REGS *, int); DLL_EXPORT void *(*debug_diagnose) (U32, int, int, REGS *); DLL_EXPORT void *(*debug_iucv) (int, VADR, REGS *); DLL_EXPORT void *(*debug_sclp_unknown_command) (U32, void *, REGS *); DLL_EXPORT void *(*debug_sclp_unknown_event) (void *, void *, REGS *); DLL_EXPORT void *(*debug_sclp_unknown_event_mask) (void *, void *, REGS *); DLL_EXPORT void *(*debug_sclp_event_data) (void *, void *, REGS *); DLL_EXPORT void *(*debug_chsc_unknown_request) (void *, void *, REGS *); DLL_EXPORT void *(*debug_watchdog_signal) (REGS *); #endif hercules-3.07/hthreads.h000644 000765 000765 00000025645 11157241226 016733 0ustar00jmaynardjmaynard000000 000000 /*-------------------------------------------------------------------*/ /* HTHREADS.H -- Hercules threading macros and functions */ /*-------------------------------------------------------------------*/ // $Id: hthreads.h 5220 2009-03-01 09:46:32Z jj $ // // $Log$ #ifndef _HTHREADS_H #define _HTHREADS_H #include "hercules.h" #if defined(OPTION_FTHREADS) /////////////////////////////////////////////////////////////////////// // FTHREADS /////////////////////////////////////////////////////////////////////// #include "fthreads.h" typedef fthread_t TID; typedef fthread_mutex_t LOCK; typedef fthread_cond_t COND; typedef fthread_attr_t ATTR; #if defined(FISH_HANG) #define create_thread(ptid,pat,fn,arg,nm) fthread_create(PTT_LOC,(ptid),(pat),(PFT_THREAD_FUNC)&(fn),(arg),(nm)) #define join_thread(tid,pcode) fthread_join(PTT_LOC,(tid),(pcode)) #define initialize_lock(plk) fthread_mutex_init(PTT_LOC,(plk),NULL) #define destroy_lock(plk) fthread_mutex_destroy(PTT_LOC,(plk)) #define obtain_lock(plk) fthread_mutex_lock(PTT_LOC,(plk)) #define try_obtain_lock(plk) fthread_mutex_trylock(PTT_LOC,(plk)) #define test_lock(plk) \ (fthread_mutex_trylock(PTT_LOC,(plk)) ? 1 : fthread_mutex_unlock(PTT_LOC,(plk)) ) #define release_lock(plk) fthread_mutex_unlock(PTT_LOC,(plk)) #define initialize_condition(pcond) fthread_cond_init(PTT_LOC,(pcond)) #define destroy_condition(pcond) fthread_cond_destroy(PTT_LOC,(pcond)) #define signal_condition(pcond) fthread_cond_signal(PTT_LOC,(pcond)) #define broadcast_condition(pcond) fthread_cond_broadcast(PTT_LOC,(pcond)) #define wait_condition(pcond,plk) fthread_cond_wait(PTT_LOC,(pcond),(plk)) #define timed_wait_condition(pcond,plk,tm) fthread_cond_timedwait(PTT_LOC,(pcond),(plk),(tm)) #else // !defined(FISH_HANG) #define create_thread(ptid,pat,fn,arg,nm) fthread_create((ptid),(pat),(PFT_THREAD_FUNC)&(fn),(arg),nm) #define join_thread(tid,pcode) fthread_join((tid),(pcode)) #define initialize_lock(plk) fthread_mutex_init((plk),NULL) #define destroy_lock(plk) fthread_mutex_destroy((plk)) #define obtain_lock(plk) fthread_mutex_lock((plk)) #define try_obtain_lock(plk) fthread_mutex_trylock((plk)) #define test_lock(plk) \ (fthread_mutex_trylock((plk)) ? 1 : fthread_mutex_unlock((plk)) ) #define release_lock(plk) fthread_mutex_unlock((plk)) #define initialize_condition(pcond) fthread_cond_init((pcond)) #define destroy_condition(pcond) fthread_cond_destroy((pcond)) #define signal_condition(pcond) fthread_cond_signal((pcond)) #define broadcast_condition(pcond) fthread_cond_broadcast((pcond)) #define wait_condition(pcond,plk) fthread_cond_wait((pcond),(plk)) #define timed_wait_condition(pcond,plk,tm) fthread_cond_timedwait((pcond),(plk),(tm)) #endif // defined(FISH_HANG) #define initialize_detach_attr(pat) fthread_attr_init((pat)); \ fthread_attr_setstacksize((pat),1048576); \ fthread_attr_setdetachstate((pat),FTHREAD_CREATE_DETACHED) #define initialize_join_attr(pat) fthread_attr_init((pat)); \ fthread_attr_setstacksize((pat),1048576); \ fthread_attr_setdetachstate((pat),FTHREAD_CREATE_JOINABLE) #define detach_thread(tid) fthread_detach((tid)) #define signal_thread(tid,signo) fthread_kill((tid),(signo)) #define thread_id() fthread_self() #define exit_thread(exitvar_ptr) fthread_exit((exitvar_ptr)) #define equal_threads(tid1,tid2) fthread_equal((tid1),(tid2)) #else // !defined(OPTION_FTHREADS) /////////////////////////////////////////////////////////////////////// // PTHREADS /////////////////////////////////////////////////////////////////////// #include typedef pthread_t TID; typedef pthread_mutex_t LOCK; typedef pthread_cond_t COND; typedef pthread_attr_t ATTR; #define initialize_lock(plk) \ pthread_mutex_init((plk),NULL) #define destroy_lock(plk) \ pthread_mutex_destroy((plk)) #define obtain_lock(plk) \ pthread_mutex_lock((plk)) #define try_obtain_lock(plk) \ pthread_mutex_trylock((plk)) #define release_lock(plk) \ pthread_mutex_unlock((plk)) #define test_lock(plk) \ (pthread_mutex_trylock((plk)) ? 1 : pthread_mutex_unlock((plk)) ) #define initialize_condition(pcond) \ pthread_cond_init((pcond),NULL) #define destroy_condition(pcond) \ pthread_cond_destroy((pcond)) #define signal_condition(pcond) \ pthread_cond_signal((pcond)) #define broadcast_condition(pcond) \ pthread_cond_broadcast((pcond)) #define wait_condition(pcond,plk) \ pthread_cond_wait((pcond),(plk)) #define timed_wait_condition(pcond,plk,timeout) \ pthread_cond_timedwait((pcond),(plk),(timeout)) #define initialize_detach_attr(pat) \ pthread_attr_init((pat)); \ pthread_attr_setstacksize((pat),1048576); \ pthread_attr_setdetachstate((pat),PTHREAD_CREATE_DETACHED) #define initialize_join_attr(pat) \ pthread_attr_init((pat)); \ pthread_attr_setstacksize((pat),1048576); \ pthread_attr_setdetachstate((pat),PTHREAD_CREATE_JOINABLE) #define join_thread(tid,pcode) \ pthread_join((tid),(pcode)) #define detach_thread(tid) \ pthread_detach((tid)) typedef void*THREAD_FUNC(void*); #define create_thread(ptid,pat,fn,arg,nm) \ pthread_create(ptid,pat,(THREAD_FUNC*)&(fn),arg) #define exit_thread(_code) \ pthread_exit((_code)) #define signal_thread(tid,signo) \ pthread_kill((tid),(signo)) #define thread_id() \ pthread_self() #define equal_threads(tid1,tid2) \ pthread_equal(tid1,tid2) #endif // defined(OPTION_FTHREADS) /////////////////////////////////////////////////////////////////////// // 'Thread' tracing... /////////////////////////////////////////////////////////////////////// #ifdef OPTION_PTTRACE #include "pttrace.h" #undef initialize_lock #define initialize_lock(plk) \ ptt_pthread_mutex_init((plk),NULL,PTT_LOC) #undef obtain_lock #define obtain_lock(plk) \ ptt_pthread_mutex_lock((plk),PTT_LOC) #undef try_obtain_lock #define try_obtain_lock(plk) \ ptt_pthread_mutex_trylock((plk),PTT_LOC) #undef test_lock #define test_lock(plk) \ (ptt_pthread_mutex_trylock ((plk),PTT_LOC) ? 1 : \ ptt_pthread_mutex_unlock ((plk),PTT_LOC)) #undef release_lock #define release_lock(plk) \ ptt_pthread_mutex_unlock((plk),PTT_LOC) #undef initialize_condition #define initialize_condition(pcond) \ ptt_pthread_cond_init((pcond),NULL,PTT_LOC) #undef signal_condition #define signal_condition(pcond) \ ptt_pthread_cond_signal((pcond),PTT_LOC) #undef broadcast_condition #define broadcast_condition(pcond) \ ptt_pthread_cond_broadcast((pcond),PTT_LOC) #undef wait_condition #define wait_condition(pcond,plk) \ ptt_pthread_cond_wait((pcond),(plk),PTT_LOC) #undef timed_wait_condition #define timed_wait_condition(pcond,plk,timeout) \ ptt_pthread_cond_timedwait((pcond),(plk),(timeout),PTT_LOC) #undef create_thread #if defined(OPTION_FTHREADS) #define create_thread(ptid,pat,fn,arg,nm) \ ptt_pthread_create((ptid),(pat),(PFT_THREAD_FUNC)&(fn),(arg),(nm),PTT_LOC) #else #define create_thread(ptid,pat,fn,arg,nm) \ ptt_pthread_create(ptid,pat,(THREAD_FUNC*)&(fn),arg,(nm),PTT_LOC) #endif #undef join_thread #define join_thread(tid,pcode) \ ptt_pthread_join((tid),(pcode),PTT_LOC) #undef detach_thread #define detach_thread(tid) \ ptt_pthread_detach((tid),PTT_LOC) #undef signal_thread #define signal_thread(tid,signo) \ ptt_pthread_kill((tid),(signo),PTT_LOC) #endif // OPTION_PTTRACE /////////////////////////////////////////////////////////////////////// // (Misc) /////////////////////////////////////////////////////////////////////// /* Pattern for displaying the thread_id */ #define TIDPAT "%8.8lX" /*-------------------------------------------------------------------*/ /* Pipe signaling support... */ /*-------------------------------------------------------------------*/ #if defined( OPTION_WAKEUP_SELECT_VIA_PIPE ) #define RECV_PIPE_SIGNAL( rfd, lock, flag ) \ do { \ int f; int saved_errno=get_HSO_errno(); BYTE c=0; \ obtain_lock(&(lock)); \ if ((f=(flag))>=1) (flag)=0; \ release_lock(&(lock)); \ if (f>=1) \ VERIFY(read_pipe((rfd),&c,1)==1); \ set_HSO_errno(saved_errno); \ } while (0) #define SEND_PIPE_SIGNAL( wfd, lock, flag ) \ do { \ int f; int saved_errno=get_HSO_errno(); BYTE c=0; \ obtain_lock(&(lock)); \ if ((f=(flag))<=0) (flag)=1; \ release_lock(&(lock)); \ if (f<=0) \ VERIFY(write_pipe((wfd),&c,1)==1); \ set_HSO_errno(saved_errno); \ } while (0) #define SUPPORT_WAKEUP_SELECT_VIA_PIPE( pipe_rfd, maxfd, prset ) \ FD_SET((pipe_rfd),(prset)); \ (maxfd)=(maxfd)>(pipe_rfd)?(maxfd):(pipe_rfd) #define SUPPORT_WAKEUP_CONSOLE_SELECT_VIA_PIPE( maxfd, prset ) SUPPORT_WAKEUP_SELECT_VIA_PIPE( sysblk.cnslrpipe, (maxfd), (prset) ) #define SUPPORT_WAKEUP_SOCKDEV_SELECT_VIA_PIPE( maxfd, prset ) SUPPORT_WAKEUP_SELECT_VIA_PIPE( sysblk.sockrpipe, (maxfd), (prset) ) #define RECV_CONSOLE_THREAD_PIPE_SIGNAL() RECV_PIPE_SIGNAL( sysblk.cnslrpipe, sysblk.cnslpipe_lock, sysblk.cnslpipe_flag ) #define RECV_SOCKDEV_THREAD_PIPE_SIGNAL() RECV_PIPE_SIGNAL( sysblk.sockrpipe, sysblk.sockpipe_lock, sysblk.sockpipe_flag ) #define SIGNAL_CONSOLE_THREAD() SEND_PIPE_SIGNAL( sysblk.cnslwpipe, sysblk.cnslpipe_lock, sysblk.cnslpipe_flag ) #define SIGNAL_SOCKDEV_THREAD() SEND_PIPE_SIGNAL( sysblk.sockwpipe, sysblk.sockpipe_lock, sysblk.sockpipe_flag ) #else // !defined( OPTION_WAKEUP_SELECT_VIA_PIPE ) #define RECV_PIPE_SIGNAL( rfd, lock, flag ) #define SEND_PIPE_SIGNAL( wfd, lock, flag ) #define SUPPORT_WAKEUP_SELECT_VIA_PIPE( pipe_rfd, maxfd, prset ) #define SUPPORT_WAKEUP_CONSOLE_SELECT_VIA_PIPE( maxfd, prset ) #define SUPPORT_WAKEUP_SOCKDEV_SELECT_VIA_PIPE( maxfd, prset ) #define RECV_CONSOLE_THREAD_PIPE_SIGNAL() #define RECV_SOCKDEV_THREAD_PIPE_SIGNAL() #define SIGNAL_CONSOLE_THREAD() signal_thread( sysblk.cnsltid, SIGUSR2 ) #define SIGNAL_SOCKDEV_THREAD() signal_thread( sysblk.socktid, SIGUSR2 ) #endif // defined( OPTION_WAKEUP_SELECT_VIA_PIPE ) #endif // _HTHREADS_H hercules-3.07/html/000777 000765 000765 00000000000 11345533276 015724 5ustar00jmaynardjmaynard000000 000000 hercules-3.07/httpmisc.h000644 000765 000765 00000006050 11143760543 016754 0ustar00jmaynardjmaynard000000 000000 /* HTTPMISC.C (c)Copyright Jan Jaeger, 2002-2009 */ /* HTTP Server */ // $Id: httpmisc.h 5126 2009-01-23 13:05:56Z bernard $ // // $Log$ // Revision 1.26 2007/06/23 00:04:12 ivan // Update copyright notices to include current year (2007) // // Revision 1.25 2006/12/08 09:43:28 jj // Add CVS message log // #ifndef _HTTPMISC_H #define _HTTPMISC_H #ifdef _HTTPSERV_C_ /* We're building the 'httpserv.c' module, so export our entry-points so that others may import them */ #define HTTP_DLL_IMPORT DLL_EXPORT #else /* _HTTPSERV_C_ */ /* We're building the 'hengine.dll' module, so declare our entry-points as extern so we can link ourselves */ #ifdef _HENGINE_DLL_ #define HTTP_DLL_IMPORT extern #else /* _HENGINE_DLL_ */ /* Some other module is being built, so declare our entry-points as 'import' so they can import them */ #define HTTP_DLL_IMPORT DLL_IMPORT #endif /* _HENGINE_DLL_ */ #endif /* _HTTPSERV_C_ */ #if !defined(PKGDATADIR) #if !defined(_MSVC_) #define HTTP_ROOT "/usr/local/share/hercules/" #else #define HTTP_ROOT "%ProgramFiles%\\Hercules\\html\\" #endif #else #define HTTP_ROOT PKGDATADIR "/" #endif #if !defined(_MSVC_) #define HTTP_PS "/" #else #define HTTP_PS "\\" #endif #define HTTP_WELCOME "hercules.html" #define HTML_HEADER "include/header.htmlpart" #define HTML_FOOTER "include/footer.htmlpart" #define HTML_STATIC_EXPIRY_TIME (60*60*24*7) #if defined(PATH_MAX) #define HTTP_PATH_LENGTH PATH_MAX #else #define HTTP_PATH_LENGTH 1024 #endif typedef struct _CGIVAR { struct _CGIVAR *next; char *name; char *value; int type; #define VARTYPE_NONE 0 #define VARTYPE_GET 1 #define VARTYPE_POST 2 #define VARTYPE_PUT 4 #define VARTYPE_COOKIE 8 } CGIVAR; #define cgi_variable(_webblk, _varname) \ http_variable((_webblk), (_varname), (VARTYPE_GET|VARTYPE_POST)) #define cgi_cookie(_webblk, _varname) \ http_variable((_webblk), (_varname), (VARTYPE_COOKIE)) #define cgi_username(_webblk) \ ((_webblk)->user) #define cgi_baseurl(_webblk) \ ((_webblk)->baseurl) typedef struct _MIMETAB { char *suffix; char *type; } MIMETAB; typedef struct _WEBBLK { #define HDL_VERS_WEBBLK "2.17" #define HDL_SIZE_WEBBLK sizeof(WEBBLK) int sock; int request_type; #define REQTYPE_NONE 0 #define REQTYPE_GET 1 #define REQTYPE_POST 2 #define REQTYPE_PUT 4 char *request; char *baseurl; char *user; CGIVAR *cgivar; } WEBBLK; typedef void (*zz_cgibin) (WEBBLK *webblk); typedef struct _CGITAB { char *path; zz_cgibin cgibin; } CGITAB; HTTP_DLL_IMPORT void html_header (WEBBLK *webblk); HTTP_DLL_IMPORT void html_footer (WEBBLK *webblk); HTTP_DLL_IMPORT int html_include (WEBBLK *webblk, char *filename); HTTP_DLL_IMPORT char *http_variable (WEBBLK *webblk, char *name, int type); void *http_server (void *arg); #endif /* _HTTPMISC_H */ hercules-3.07/httpserv.c000644 000765 000765 00000062701 11143760543 017000 0ustar00jmaynardjmaynard000000 000000 /* HTTPSERV.C (c)Copyright Jan Jaeger, 2002-2009 */ /* HTTP Server */ // $Id: httpserv.c 5146 2009-02-01 20:09:49Z rbowler $ /* This file contains all code required for the HTTP server, */ /* when the http_server thread is started it will listen on */ /* the HTTP port specified on the HTTPPORT config statement. */ /* */ /* When a request comes in a http_request thread is started, */ /* which will handle the request. */ /* */ /* When authentification is required (auth parm on the HTTPPORT */ /* statement) then the user will be authenticated based on the */ /* userid and password supplied on the HTTPPORT statement, if */ /* these where not supplied then the userid and password of the */ /* that hercules is running under will be used. In the latter case */ /* the root userid/password will also be accepted. */ /* */ /* If the request is for a /cgi-bin/ path, then the cgibin */ /* directory in cgibin.c will be searched, for any other request */ /* the sysblk.httproot (/usr/local/hercules) will be used as the */ /* root to find the specified file. */ /* */ /* As realpath() is used to verify that the files are from within */ /* the sysblk.httproot tree symbolic links that refer to files */ /* outside the sysblk.httproot tree are not supported. */ /* */ /* */ /* Jan Jaeger - 28/03/2002 */ // $Log$ // Revision 1.80 2009/01/23 12:51:42 bernard // copyright notice // // Revision 1.79 2009/01/15 17:36:43 jj // Change http server startup // // Revision 1.78 2008/11/04 05:56:31 fish // Put ensure consistent create_thread ATTR usage change back in // // Revision 1.77 2008/11/03 15:31:54 rbowler // Back out consistent create_thread ATTR modification // // Revision 1.76 2008/10/18 09:32:21 fish // Ensure consistent create_thread ATTR usage // // Revision 1.75 2008/05/28 16:39:44 fish // (use R_OK constant) // // Revision 1.74 2007/06/23 00:04:12 ivan // Update copyright notices to include current year (2007) // // Revision 1.73 2006/12/31 23:49:00 fish // Use "access()" to validate http_server root directory and not "chdir()"!! // // Revision 1.72 2006/12/08 09:43:28 jj // Add CVS message log // #include "hstdinc.h" #define _HTTPSERV_C_ #define _HENGINE_DLL_ #include "hercules.h" #include "httpmisc.h" #include "hostinfo.h" #if defined(OPTION_HTTP_SERVER) /* External reference to the cgi-bin directory in cgibin.c */ extern CGITAB cgidir[]; static MIMETAB mime_types[] = { { NULL, NULL }, /* No suffix entry */ { "txt", "text/plain" }, { "jcl", "text/plain" }, { "gif", "image/gif" }, { "jpg", "image/jpeg" }, { "css", "text/css" }, { "html", "text/html" }, { "htm", "text/html" }, /* This one should be: { "ico", "image/vnd.microsoft.icon" }, but Apache 2 sets it as: */ { "ico", "image/x-icon" }, /* so we'll go with what's actually in use. --JRM */ { NULL, NULL } }; /* Default suffix entry */ DLL_EXPORT int html_include(WEBBLK *webblk, char *filename) { FILE *inclfile; char fullname[HTTP_PATH_LENGTH]; char buffer[HTTP_PATH_LENGTH]; int ret; strlcpy( fullname, sysblk.httproot, sizeof(fullname) ); strlcat( fullname, filename, sizeof(fullname) ); inclfile = fopen(fullname,"rb"); if (!inclfile) { logmsg(_("HHCHT011E html_include: Cannot open %s: %s\n"), fullname,strerror(errno)); hprintf(webblk->sock,_("ERROR: Cannot open %s: %s\n"), filename,strerror(errno)); return FALSE; } while (!feof(inclfile)) { ret = fread(buffer, 1, sizeof(buffer), inclfile); if (ret <= 0) break; hwrite(webblk->sock,buffer, ret); } fclose(inclfile); return TRUE; } DLL_EXPORT void html_header(WEBBLK *webblk) { if (webblk->request_type != REQTYPE_POST) hprintf(webblk->sock,"Expires: 0\n"); hprintf(webblk->sock,"Content-type: text/html\n\n"); if (!html_include(webblk,HTML_HEADER)) hprintf(webblk->sock,"\n\nHercules\n\n\n\n"); } DLL_EXPORT void html_footer(WEBBLK *webblk) { if (!html_include(webblk,HTML_FOOTER)) hprintf(webblk->sock,"\n\n\n"); } static void http_exit(WEBBLK *webblk) { CGIVAR *cgivar; int rc; if(webblk) { /* MS SDK docs state: "To assure that all data is sent and received on a connected socket before it is closed, an application should use shutdown to close connection before calling closesocket. For example, to initiate a graceful disconnect: 1, Call WSAAsyncSelect to register for FD_CLOSE notification. 2. Call shutdown with how=SD_SEND. 3. When FD_CLOSE received, call recv until zero returned, or SOCKET_ERROR. 4. Call closesocket. Note: The shutdown function does not block regardless of the SO_LINGER setting on the socket." */ // Notify other end of connection to not expect any more data from us. // They should detect this via their own 'recv' returning zero bytes // (thus letting them know they've thus received all the data from us // they're ever going to receive). They should then do their own // 'shutdown(s,SHUT_WR)' at their end letting US know we're also not // going to be receiving any more data from THEM. This is called a // "graceful close" of the connection... shutdown( webblk->sock, SHUT_WR ); // Now wait for them to shudown THEIR end of the connection (i.e. wait // for them to do their own 'shutdown(s,SHUT_WR)') by "hanging" on a // 'recv' call until we either eventually detect they've shutdown their // end of the connection (0 bytes received) or else an error occurs... do { BYTE c; rc = read_socket( webblk->sock, &c, 1 ); } while ( rc > 0 ); // NOW we can SAFELY close the socket since we now KNOW for CERTAIN // that they've received ALL of the data we previously sent to them... // (otherwise they wouldn't have close their connection on us!) close_socket( webblk->sock ); if(webblk->user) free(webblk->user); if(webblk->request) free(webblk->request); cgivar = webblk->cgivar; while(cgivar) { CGIVAR *tmpvar = cgivar->next; free(cgivar->name); free(cgivar->value); free(cgivar); cgivar = tmpvar; } free(webblk); } exit_thread(NULL); } static void http_error(WEBBLK *webblk, char *err, char *header, char *info) { hprintf(webblk->sock,"HTTP/1.0 %s\n%sConnection: close\n" "Content-Type: text/html\n\n" "%s" "

%s

%s\n\n", err, header, err, err, info); http_exit(webblk); } static char *http_timestring(char *time_buff,int buff_size, time_t t) { struct tm *tm = localtime(&t); strftime(time_buff, buff_size, "%a, %d %b %Y %H:%M:%S %Z", tm); return time_buff; } static void http_decode_base64(char *s) { char *b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; int bit_o, byte_o, idx, i, n; unsigned char *d = (unsigned char *)s; char *p; n = i = 0; while (*s && (p = strchr(b64, *s))) { idx = (int)(p - b64); byte_o = (i*6)/8; bit_o = (i*6)%8; d[byte_o] &= ~((1<<(8-bit_o))-1); if (bit_o < 3) { d[byte_o] |= (idx << (2-bit_o)); n = byte_o+1; } else { d[byte_o] |= (idx >> (bit_o-2)); d[byte_o+1] = 0; d[byte_o+1] |= (idx << (8-(bit_o-2))) & 0xFF; n = byte_o+2; } s++; i++; } /* null terminate */ d[n] = 0; } static char *http_unescape(char *buffer) { char *pointer = buffer; while ( (pointer = strchr(pointer,'+')) ) *pointer = ' '; pointer = buffer; while (pointer && *pointer && (pointer = strchr(pointer,'%'))) { int highnibble = pointer[1]; int lownibble = pointer[2]; if (highnibble >= '0' && highnibble <= '9') highnibble = highnibble - '0'; else if (highnibble >= 'A' && highnibble <= 'F') highnibble = 10 + highnibble - 'A'; else if (highnibble >= 'a' && highnibble <= 'f') highnibble = 10 + highnibble - 'a'; else { pointer++; continue; } if (lownibble >= '0' && lownibble <= '9') lownibble = lownibble - '0'; else if (lownibble >= 'A' && lownibble <= 'F') lownibble = 10 + lownibble - 'A'; else if (lownibble >= 'a' && lownibble <= 'f') lownibble = 10 + lownibble - 'a'; else { pointer++; continue; } *pointer = (highnibble<<4) | lownibble; memcpy(pointer+1, pointer+3, strlen(pointer+3)+1); pointer++; } return buffer; } static void http_interpret_variable_string(WEBBLK *webblk, char *qstring, int type) { char *name; char *value; char *strtok_str; CGIVAR **cgivar; for (cgivar = &(webblk->cgivar); *cgivar; cgivar = &((*cgivar)->next)); for (name = strtok_r(qstring,"&; ",&strtok_str); name; name = strtok_r(NULL,"&; ",&strtok_str)) { if(!(value = strchr(name,'='))) continue; *value++ = '\0'; (*cgivar) = malloc(sizeof(CGIVAR)); (*cgivar)->next = NULL; (*cgivar)->name = strdup(http_unescape(name)); (*cgivar)->value = strdup(http_unescape(value)); (*cgivar)->type = type; cgivar = &((*cgivar)->next); } } #if 0 static void http_dump_cgi_variables(WEBBLK *webblk) { CGIVAR *cv; for(cv = webblk->cgivar; cv; cv = cv->next) logmsg(_("HHCHT012I cgi_var_dump: pointer(%p) name(%s) value(%s) type(%d)\n"), cv, cv->name, cv->value, cv->type); } #endif DLL_EXPORT char *http_variable(WEBBLK *webblk, char *name, int type) { CGIVAR *cv; for(cv = webblk->cgivar; cv; cv = cv->next) if((cv->type & type) && !strcmp(name,cv->name)) return cv->value; return NULL; } static void http_verify_path(WEBBLK *webblk, char *path) { char resolved_path[HTTP_PATH_LENGTH]; #if 0 int i; for (i = 0; path[i]; i++) if (!isalnum((int)path[i]) && !strchr("/.-_", path[i])) http_error(webblk, "404 File Not Found","", "Illegal character in filename"); #endif if (!realpath( path, resolved_path )) http_error(webblk, "404 File Not Found","", "Invalid pathname"); // The following verifies the specified file does not lie // outside the specified httproot (Note: sysblk.httproot // was previously resolved to an absolute path by config.c) if (strncmp( sysblk.httproot, resolved_path, strlen(sysblk.httproot))) http_error(webblk, "404 File Not Found","", "Invalid pathname"); } static int http_authenticate(WEBBLK *webblk, char *type, char *userpass) { char *pointer ,*user, *passwd; if (!strcasecmp(type,"Basic")) { if(userpass) { http_decode_base64(userpass); /* the format is now user:password */ if ((pointer = strchr(userpass,':'))) { *pointer = 0; user = userpass; passwd = pointer+1; /* Hardcoded userid and password in configuration file */ if(sysblk.httpuser && sysblk.httppass) { if(!strcmp(user,sysblk.httpuser) && !strcmp(passwd,sysblk.httppass)) { webblk->user = strdup(user); return TRUE; } } #if !defined(WIN32) else { struct passwd *pass = NULL; /* unix userid and password check, the userid must be the same as that hercules is currently running under */ // ZZ INCOMPLETE // ZZ No password check is being performed yet... if((pass = getpwnam(user)) && (pass->pw_uid == 0 || pass->pw_uid == getuid())) { webblk->user = strdup(user); return TRUE; } } #endif /*!defined(WIN32)*/ } } } webblk->user = NULL; return FALSE; } static void http_download(WEBBLK *webblk, char *filename) { char buffer[HTTP_PATH_LENGTH]; char tbuf[80]; int fd, length; char *filetype; char fullname[HTTP_PATH_LENGTH]; struct stat st; MIMETAB *mime_type = mime_types; strlcpy( fullname, sysblk.httproot, sizeof(fullname) ); strlcat( fullname, filename, sizeof(fullname) ); http_verify_path(webblk,fullname); if(stat(fullname,&st)) http_error(webblk, "404 File Not Found","", strerror(errno)); if(!S_ISREG(st.st_mode)) http_error(webblk, "404 File Not Found","", "The requested file is not a regular file"); fd = open(fullname,O_RDONLY|O_BINARY,0); if (fd == -1) http_error(webblk, "404 File Not Found","", strerror(errno)); hprintf(webblk->sock,"HTTP/1.0 200 OK\n"); if ((filetype = strrchr(filename,'.'))) for(mime_type++;mime_type->suffix && strcasecmp(mime_type->suffix,filetype + 1); mime_type++); if(mime_type->type) hprintf(webblk->sock,"Content-Type: %s\n", mime_type->type); hprintf(webblk->sock,"Expires: %s\n", http_timestring(tbuf,sizeof(tbuf),time(NULL)+HTML_STATIC_EXPIRY_TIME)); hprintf(webblk->sock,"Content-Length: %d\n\n", (int)st.st_size); while ((length = read(fd, buffer, sizeof(buffer))) > 0) hwrite(webblk->sock,buffer, length); close(fd); http_exit(webblk); } static void *http_request(int sock) { WEBBLK *webblk; int authok = !sysblk.httpauth; char line[HTTP_PATH_LENGTH]; char *url = NULL; char *pointer; char *strtok_str; CGITAB *cgient; int content_length = 0; if(!(webblk = malloc(sizeof(WEBBLK)))) http_exit(webblk); memset(webblk,0,sizeof(WEBBLK)); webblk->sock = sock; while (hgets(line, sizeof(line), webblk->sock)) { if (*line == '\r' || *line == '\n') break; if((pointer = strtok_r(line," \t\r\n",&strtok_str))) { if(!strcasecmp(pointer,"GET")) { if((pointer = strtok_r(NULL," \t\r\n",&strtok_str))) { webblk->request_type = REQTYPE_GET; url = strdup(pointer); } } else if(!strcasecmp(pointer,"POST")) { if((pointer = strtok_r(NULL," \t\r\n",&strtok_str))) { webblk->request_type = REQTYPE_POST; url = strdup(pointer); } } else if(!strcasecmp(pointer,"PUT")) { http_error(webblk,"400 Bad Request", "", "This server does not accept PUT requests"); } else if(!strcasecmp(pointer,"Authorization:")) { if((pointer = strtok_r(NULL," \t\r\n",&strtok_str))) authok = http_authenticate(webblk,pointer, strtok_r(NULL," \t\r\n",&strtok_str)); } else if(!strcasecmp(pointer,"Cookie:")) { if((pointer = strtok_r(NULL,"\r\n",&strtok_str))) http_interpret_variable_string(webblk, pointer, VARTYPE_COOKIE); } else if(!strcasecmp(pointer,"Content-Length:")) { if((pointer = strtok_r(NULL," \t\r\n",&strtok_str))) content_length = atoi(pointer); } } } webblk->request = url; if(webblk->request_type == REQTYPE_POST && content_length != 0) { char *post_arg; if((pointer = post_arg = malloc(content_length + 1))) { int i; for(i = 0; i < content_length; i++) { *pointer = hgetc(webblk->sock); if(*pointer != '\n' && *pointer != '\r') pointer++; } *pointer = '\0'; http_interpret_variable_string(webblk, post_arg, VARTYPE_POST); free(post_arg); } } if (!authok) http_error(webblk, "401 Authorization Required", "WWW-Authenticate: Basic realm=\"HERCULES\"\n", "You must be authenticated to use this service"); if (!url) http_error(webblk,"400 Bad Request", "", "You must specify a GET or POST request"); /* anything following a ? in the URL is part of the get arguments */ if ((pointer=strchr(url,'?'))) { *pointer++ = 0; http_interpret_variable_string(webblk, pointer, VARTYPE_GET); } while(url[0] == '/' && url[1] == '/') url++; webblk->baseurl = url; if(!strcasecmp("/",url)) url = HTTP_WELCOME; if(strncasecmp("/cgi-bin/",url,9)) http_download(webblk,url); else url += 9; while(*url == '/') url++; #if 0 http_dump_cgi_variables(webblk); #endif for(cgient = cgidir; cgient->path; cgient++) { if(!strcmp(cgient->path, url)) { char tbuf[80]; hprintf(webblk->sock,"HTTP/1.0 200 OK\nConnection: close\n"); hprintf(webblk->sock,"Date: %s\n", http_timestring(tbuf,sizeof(tbuf),time(NULL))); (cgient->cgibin) (webblk); http_exit(webblk); } } #if defined(OPTION_DYNAMIC_LOAD) { zz_cgibin dyncgi; if( (dyncgi = HDL_FINDSYM(webblk->baseurl)) ) { char tbuf[80]; hprintf(webblk->sock,"HTTP/1.0 200 OK\nConnection: close\n"); hprintf(webblk->sock,"Date: %s\n", http_timestring(tbuf,sizeof(tbuf),time(NULL))); dyncgi(webblk); http_exit(webblk); } } #endif /*defined(OPTION_DYNAMIC_LOAD)*/ http_error(webblk, "404 File Not Found","", "The requested file was not found"); return NULL; } void *http_server (void *arg) { int rc; /* Return code */ int lsock; /* Socket for listening */ int csock; /* Socket for conversation */ struct sockaddr_in server; /* Server address structure */ fd_set selset; /* Read bit map for select */ int optval; /* Argument for setsockopt */ TID httptid; /* Negotiation thread id */ UNREFERENCED(arg); /* Display thread started message on control panel */ logmsg (_("HHCHT001I HTTP listener thread started: " "tid="TIDPAT", pid=%d\n"), thread_id(), getpid()); /* If the HTTP root directory is not specified, use a reasonable default */ if (!sysblk.httproot) { #if defined(_MSVC_) char process_dir[HTTP_PATH_LENGTH]; if (get_process_directory(process_dir,HTTP_PATH_LENGTH) > 0) { strlcat(process_dir,"\\html",HTTP_PATH_LENGTH); sysblk.httproot = strdup(process_dir); } else #endif /*defined(WIN32)*/ sysblk.httproot = strdup(HTTP_ROOT); } /* Convert the specified HTTPROOT value to an absolute path ending with a '/' and save in sysblk.httproot. */ { char absolute_httproot_path[HTTP_PATH_LENGTH]; int rc; #if defined(_MSVC_) /* Expand any embedded %var% environ vars */ rc = expand_environ_vars( sysblk.httproot, absolute_httproot_path, sizeof(absolute_httproot_path) ); if (rc == 0) { free(sysblk.httproot); sysblk.httproot = strdup(absolute_httproot_path); } #endif /* defined(_MSVC_) */ /* Convert to absolute path */ if (!realpath(sysblk.httproot,absolute_httproot_path)) { logmsg( _("HHCCF066E Invalid HTTPROOT: \"%s\": %s\n"), sysblk.httproot, strerror(errno)); return NULL; } /* Verify that the absolute path is valid */ // mode: 0 = exist only, 2 = write, 4 = read, 6 = read/write // rc: 0 = success, -1 = error (errno = cause) // ENOENT = File name or path not found. if (access( absolute_httproot_path, R_OK ) != 0) { logmsg( _("HHCCF066E Invalid HTTPROOT: \"%s\": %s\n"), absolute_httproot_path, strerror(errno)); return NULL; } /* Append trailing [back]slash, but only if needed */ rc = strlen(absolute_httproot_path); if (absolute_httproot_path[rc-1] != *HTTP_PS) strlcat(absolute_httproot_path,HTTP_PS,sizeof(absolute_httproot_path)); /* Save the absolute path */ free(sysblk.httproot); sysblk.httproot = strdup(absolute_httproot_path); logmsg(_("HHCHT013I Using HTTPROOT directory \"%s\"\n"),sysblk.httproot); } /* Obtain a socket */ lsock = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); if (lsock < 0) { logmsg(_("HHCHT002E socket: %s\n"), strerror(HSO_errno)); return NULL; } /* Allow previous instance of socket to be reused */ optval = 1; setsockopt (lsock, SOL_SOCKET, SO_REUSEADDR, (void*)&optval, sizeof(optval)); /* Prepare the sockaddr structure for the bind */ memset (&server, 0, sizeof(server)); server.sin_family = AF_INET; server.sin_addr.s_addr = INADDR_ANY; server.sin_port = sysblk.httpport; server.sin_port = htons(server.sin_port); /* Attempt to bind the socket to the port */ while (TRUE) { rc = bind (lsock, (struct sockaddr *)&server, sizeof(server)); if (rc == 0 || HSO_errno != HSO_EADDRINUSE) break; logmsg (_("HHCHT003W Waiting for port %u to become free\n"), sysblk.httpport); SLEEP(10); } /* end while */ if (rc != 0) { logmsg(_("HHCHT004E bind: %s\n"), strerror(HSO_errno)); return NULL; } /* Put the socket into listening state */ rc = listen (lsock, 32); if (rc < 0) { logmsg(_("HHCHT005E listen: %s\n"), strerror(HSO_errno)); return NULL; } logmsg(_("HHCHT006I Waiting for HTTP requests on port %u\n"), sysblk.httpport); /* Handle http requests */ while (sysblk.httpport) { /* Initialize the select parameters */ FD_ZERO (&selset); FD_SET (lsock, &selset); /* Wait for a file descriptor to become ready */ rc = select ( lsock+1, &selset, NULL, NULL, NULL ); if (rc == 0) continue; if (rc < 0 ) { if (HSO_errno == HSO_EINTR) continue; logmsg(_("HHCHT007E select: %s\n"), strerror(HSO_errno)); break; } /* If a http request has arrived then accept it */ if (FD_ISSET(lsock, &selset)) { /* Accept the connection and create conversation socket */ csock = accept (lsock, NULL, NULL); if (csock < 0) { logmsg(_("HHCHT008E accept: %s\n"), strerror(HSO_errno)); continue; } /* Create a thread to execute the http request */ if ( create_thread (&httptid, DETACHED, http_request, (void *)(uintptr_t)csock, "http_request") ) { logmsg(_("HHCHT010E http_request create_thread: %s\n"), strerror(errno)); close_socket (csock); } } /* end if(lsock) */ } /* end while */ /* Close the listening socket */ close_socket (lsock); /* Display thread started message on control panel */ logmsg (_("HHCHT009I HTTP listener thread ended: " "tid="TIDPAT", pid=%d\n"), thread_id(), getpid()); sysblk.httptid = 0; return NULL; } /* end function http_server */ #endif /*defined(OPTION_HTTP_SERVER)*/ hercules-3.07/htypes.h000644 000765 000765 00000020775 11321734033 016440 0ustar00jmaynardjmaynard000000 000000 /* HTYPES.H (c) Copyright Roger Bowler, 1999-2009 */ /* Hercules Type Definitions */ // $Id: htypes.h 5582 2009-12-30 21:15:23Z rbowler $ #ifndef _HTYPES_H_ #define _HTYPES_H_ /* Try to pull in as many typedef's as possible from the provided system headers for whatever system we're building on... */ #ifndef HAVE_INTTYPES_H #ifdef HAVE_U_INT #define uint8_t u_int8_t #define uint16_t u_int16_t #define uint32_t u_int32_t #define uint64_t u_int64_t #else #error Unable to find fixed-size data types #endif #endif #ifndef HAVE_U_INT8_T #ifdef HAVE_INTTYPES_H typedef uint8_t u_int8_t; typedef uint16_t u_int16_t; typedef uint32_t u_int32_t; typedef uint64_t u_int64_t; #else #error Unable to define u_intNN_t data types #endif #endif typedef int8_t S8; // signed 8-bits typedef int16_t S16; // signed 16-bits typedef int32_t S32; // signed 32-bits typedef int64_t S64; // signed 64-bits typedef uint8_t U8; // unsigned 8-bits typedef uint16_t U16; // unsigned 16-bits typedef uint32_t U32; // unsigned 32-bits typedef uint64_t U64; // unsigned 64-bits #ifndef _MSVC_ // (MSVC typedef's it too) typedef uint8_t BYTE; // unsigned byte (1 byte) #endif typedef uint8_t HWORD[2]; // unsigned halfword (2 bytes) typedef uint8_t FWORD[4]; // unsigned fullword (4 bytes) typedef uint8_t DBLWRD[8]; // unsigned doubleword (8 bytes) typedef uint8_t QWORD[16]; // unsigned quadword (16 bytes) /*-------------------------------------------------------------------*/ /* Format size modifiers for printf and scanf */ /*-------------------------------------------------------------------*/ #if defined(_MSVC_) #define I16_FMT "h" #define I32_FMT "I32" #define I64_FMT "I64" #elif defined(__PRI_64_LENGTH_MODIFIER__) // MAC #define I16_FMT "h" #define I32_FMT "" #define I64_FMT __PRI_64_LENGTH_MODIFIER__ #elif defined(SIZEOF_LONG) && SIZEOF_LONG >= 8 #define I16_FMT "h" #define I32_FMT "" #define I64_FMT "l" #else // !defined(SIZEOF_LONG) || SIZEOF_LONG < 8 #define I16_FMT "h" #define I32_FMT "" #define I64_FMT "ll" #endif #define I16_FMTx "%4.4" I16_FMT "x" #define I32_FMTx "%8.8" I32_FMT "x" #define I64_FMTx "%16.16" I64_FMT "x" #define I16_FMTX "%4.4" I16_FMT "X" #define I32_FMTX "%8.8" I32_FMT "X" #define I64_FMTX "%16.16" I64_FMT "X" #if defined(SIZEOF_INT_P) && SIZEOF_INT_P >= 8 #define UINT_PTR_FMT I64_FMT #define PTR_FMTx I64_FMTx #define PTR_FMTX I64_FMTX #else // !defined(SIZEOF_INT_P) || SIZEOF_INT_P < 8 #define UINT_PTR_FMT I32_FMT #define PTR_FMTx I32_FMTx #define PTR_FMTX I32_FMTX #endif #if defined(SIZEOF_SIZE_T) && SIZEOF_SIZE_T >= 8 #define SIZE_T_FMT I64_FMT #define SIZE_T_FMTx I64_FMTx #define SIZE_T_FMTX I64_FMTX #else // !defined(SIZEOF_SIZE_T) || SIZEOF_SIZE_T < 8 #define SIZE_T_FMT I32_FMT #define SIZE_T_FMTx I32_FMTx #define SIZE_T_FMTX I32_FMTX #endif /*-------------------------------------------------------------------*/ /* Socket stuff */ /*-------------------------------------------------------------------*/ #ifndef _BSDTYPES_DEFINED #ifndef HAVE_U_CHAR typedef unsigned char u_char; #endif #ifndef HAVE_U_SHORT typedef unsigned short u_short; #endif #ifndef HAVE_U_INT typedef unsigned int u_int; #endif #ifndef HAVE_U_LONG typedef unsigned long u_long; #endif #define _BSDTYPES_DEFINED #endif #ifndef HAVE_SOCKLEN_T typedef unsigned int socklen_t; #endif #ifndef HAVE_IN_ADDR_T typedef unsigned int in_addr_t; #endif /* FIXME : THAT'S WRONG ! BUT IT WORKS FOR THE TIME BEING */ #if defined(_MSVC_) #ifndef HAVE_USECONDS_T typedef long useconds_t; #endif #endif #if !defined( HAVE_STRUCT_IN_ADDR_S_ADDR ) && !defined( _WINSOCK_H ) struct in_addr { in_addr_t s_addr; }; #endif // (The following are simply to silence some compile time warnings) #ifdef _MSVC_ typedef char GETSET_SOCKOPT_T; typedef const char *const *EXECV_ARG2_ARGV_T; #else typedef void GETSET_SOCKOPT_T; typedef char *const *EXECV_ARG2_ARGV_T; #endif #if defined( OPTION_SCSI_TAPE ) && !defined( HAVE_SYS_MTIO_H ) struct mt_tape_info { long t_type; /* device type id (mt_type) */ char *t_name; /* descriptive name */ }; #define MT_TAPE_INFO { { 0, NULL } } #endif /*-------------------------------------------------------------------*/ /* Primary Hercules Control Structures */ /*-------------------------------------------------------------------*/ typedef struct SYSBLK SYSBLK; // System configuration block typedef struct REGS REGS; // CPU register context typedef struct VFREGS VFREGS; // Vector Facility Registers typedef struct ZPBLK ZPBLK; // Zone Parameter Block typedef struct DEVBLK DEVBLK; // Device configuration block typedef struct IOINT IOINT; // I/O interrupt queue typedef struct DEVDATA DEVDATA; // xxxxxxxxx typedef struct DEVGRP DEVGRP; // xxxxxxxxx typedef struct DEVHND DEVHND; // xxxxxxxxx typedef struct SHRD SHRD; // xxxxxxxxx #ifdef EXTERNALGUI typedef struct GUISTAT GUISTAT; // EXTERNALGUI Device Status Ctl #endif /*-------------------------------------------------------------------*/ /* Secondary Device and I/O Control Related Structures */ /*-------------------------------------------------------------------*/ typedef struct CKDDASD_DEVHDR CKDDASD_DEVHDR; // Device header typedef struct CKDDASD_TRKHDR CKDDASD_TRKHDR; // Track header typedef struct CKDDASD_RECHDR CKDDASD_RECHDR; // Record header typedef struct CCKDDASD_DEVHDR CCKDDASD_DEVHDR; // Compress device header typedef struct CCKD_L2ENT CCKD_L2ENT; // Level 2 table entry typedef struct CCKD_FREEBLK CCKD_FREEBLK; // Free block typedef struct CCKD_IFREEBLK CCKD_IFREEBLK; // Free block (internal) typedef struct CCKD_RA CCKD_RA; // Readahead queue entry typedef struct CCKDBLK CCKDBLK; // Global cckd dasd block typedef struct CCKDDASD_EXT CCKDDASD_EXT; // Ext for compressed ckd typedef struct COMMADPT COMMADPT; // Comm Adapter typedef struct bind_struct bind_struct; // Socket Device Ctl typedef struct TAPEMEDIA_HANDLER TAPEMEDIA_HANDLER; // (see tapedev.h) typedef struct TAPEAUTOLOADENTRY TAPEAUTOLOADENTRY; // (see tapedev.h) typedef struct TAMDIR TAMDIR; // (see tapedev.h) /*-------------------------------------------------------------------*/ /* Device handler function prototypes */ /*-------------------------------------------------------------------*/ typedef int DEVIF (DEVBLK *dev, int argc, char *argv[]); typedef void DEVQF (DEVBLK *dev, char **class, int buflen, char *buffer); typedef void DEVXF (DEVBLK *dev, BYTE code, BYTE flags, BYTE chained, U16 count, BYTE prevcode, int ccwseq, BYTE *iobuf, BYTE *more, BYTE *unitstat, U16 *residual); typedef int DEVCF (DEVBLK *dev); typedef void DEVSF (DEVBLK *dev); typedef int DEVRF (DEVBLK *dev, int ix, BYTE *unitstat); typedef int DEVWF (DEVBLK *dev, int rcd, int off, BYTE *buf, int len, BYTE *unitstat); typedef int DEVUF (DEVBLK *dev); typedef void DEVRR (DEVBLK *dev); typedef int DEVSA (DEVBLK *dev, U32 qmask); typedef int DEVSR (DEVBLK *dev, void *file); /*-------------------------------------------------------------------*/ /* Device handler description structures */ /*-------------------------------------------------------------------*/ typedef BYTE *DEVIM; /* Immediate CCW Codes Table */ #endif // _HTYPES_H_ hercules-3.07/ieee-w32.h000644 000765 000765 00000025447 11162654023 016450 0ustar00jmaynardjmaynard000000 000000 /* IEEE-W32.H (c) Copyright Greg Smith, 2002-2009 */ /* Hercules IEEE floating point definitions for Windows */ // $Id: ieee-w32.h 5293 2009-03-24 22:52:22Z rbowler $ // // $Log$ // Revision 1.13 2008/12/16 16:22:54 rbowler // Eliminate unknown pragma warning in ieee-w32.h for VC++ Toolkit 2003 // // Revision 1.12 2008/12/12 23:50:47 rbowler // Alternate non-asm routines in ieee-w32.h for win64 // // Revision 1.11 2008/04/16 14:58:57 rbowler // Modify style of inline assembler to conform with machdep.h // // Revision 1.10 2008/04/16 14:26:21 rbowler // Add rint function for MSVC // // Revision 1.9 2008/04/15 21:30:03 rbowler // BFP rounding mode support // // Revision 1.8 2008/02/07 00:25:42 rbowler // Add a standard file identification header // // Revision 1.7 2006/12/08 09:43:28 jj // Add CVS message log // #ifndef _IEEE_W32_H #define _IEEE_W32_H #if defined(_MSVC_) && defined(_WIN64) #include #define NO_INLINE_ASM #endif #if defined(_MSVC_) && (LDBL_MANT_DIG == DBL_MANT_DIG) #define LONG_DOUBLE_IS_SAME_AS_DOUBLE #endif #undef FP_NAN #undef FP_INFINITE #undef FP_ZERO #undef FP_SUBNORMAL #undef FP_NORMAL #undef fpclassify #undef signbit /* Inform the compiler that this module manipulates the FP status word */ #if defined(_MSVC_) && defined(_MSC_VER) && (_MSC_VER >= 1400) #pragma fenv_access(on) #endif /* All floating-point numbers can be put in one of these categories. */ enum { FP_NAN, # define FP_NAN FP_NAN FP_INFINITE, # define FP_INFINITE FP_INFINITE FP_ZERO, # define FP_ZERO FP_ZERO FP_SUBNORMAL, # define FP_SUBNORMAL FP_SUBNORMAL FP_NORMAL # define FP_NORMAL FP_NORMAL }; /* Type representing floating-point environment. This function corresponds to the layout of the block written by the `fstenv'. */ typedef struct { unsigned short int __control_word; unsigned short int __unused1; unsigned short int __status_word; unsigned short int __unused2; unsigned short int __tags; unsigned short int __unused3; unsigned int __eip; unsigned short int __cs_selector; unsigned int __opcode:11; unsigned int __unused4:5; unsigned int __data_offset; unsigned short int __data_selector; unsigned short int __unused5; } fenv_t; /* FPU control word rounding flags */ #define FE_TONEAREST 0x0000 #define FE_DOWNWARD 0x0400 #define FE_UPWARD 0x0800 #define FE_TOWARDZERO 0x0c00 /* Define bits representing the exception. We use the bit positions of the appropriate bits in the FPU control word. */ enum { FE_INVALID = 0x01, #define FE_INVALID FE_INVALID __FE_DENORM = 0x02, FE_DIVBYZERO = 0x04, #define FE_DIVBYZERO FE_DIVBYZERO FE_OVERFLOW = 0x08, #define FE_OVERFLOW FE_OVERFLOW FE_UNDERFLOW = 0x10, #define FE_UNDERFLOW FE_UNDERFLOW FE_INEXACT = 0x20 #define FE_INEXACT FE_INEXACT }; #define FE_ALL_EXCEPT \ (FE_INEXACT | FE_DIVBYZERO | FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID) #if defined(LONG_DOUBLE_IS_SAME_AS_DOUBLE) #define fpclassify(x) \ (sizeof (x) == sizeof (float) ? __fpclassifyf (x) \ : __fpclassify (x)) #else #define fpclassify(x) \ (sizeof (x) == sizeof (float) ? __fpclassifyf (x) \ : sizeof (x) == sizeof (double) ? __fpclassify (x) \ : __fpclassifyl (x)) #endif typedef union { float value; uint32_t word; } ieee_float_shape_type; #define GET_FLOAT_WORD(i,d) \ do { \ ieee_float_shape_type gf_u; \ gf_u.value = (d); \ (i) = gf_u.word; \ } while (0) typedef union { double value; struct { uint32_t lsw; uint32_t msw; } parts; } ieee_double_shape_type; #define EXTRACT_WORDS(ix0,ix1,d) \ do { \ ieee_double_shape_type ew_u; \ ew_u.value = (d); \ (ix0) = ew_u.parts.msw; \ (ix1) = ew_u.parts.lsw; \ } while (0) #if !defined(LONG_DOUBLE_IS_SAME_AS_DOUBLE) typedef union { long double value; struct { uint32_t lsw; uint32_t msw; int sign_exponent:16; unsigned int empty:16; } parts; } ieee_long_double_shape_type; /* Get three 32 bit ints from a double. */ #define GET_LDOUBLE_WORDS(exp,ix0,ix1,d) \ do { \ ieee_long_double_shape_type ew_u; \ ew_u.value = (d); \ (exp) = ew_u.parts.sign_exponent; \ (ix0) = ew_u.parts.msw; \ (ix1) = ew_u.parts.lsw; \ } while (0) #endif /*!defined(LONG_DOUBLE_IS_SAME_AS_DOUBLE)*/ int fegetenv(fenv_t *f) { f=f; return(0); } int feholdexcept(fenv_t *f) { f=f; return(0); } int __fpclassifyf (float x) { uint32_t wx; int retval = FP_NORMAL; GET_FLOAT_WORD (wx, x); wx &= 0x7fffffff; if (wx == 0) retval = FP_ZERO; else if (wx < 0x800000) retval = FP_SUBNORMAL; else if (wx >= 0x7f800000) retval = wx > 0x7f800000 ? FP_NAN : FP_INFINITE; return retval; } int __fpclassify (double x) { uint32_t hx, lx; int retval = FP_NORMAL; EXTRACT_WORDS (hx, lx, x); lx |= hx & 0xfffff; hx &= 0x7ff00000; if ((hx | lx) == 0) retval = FP_ZERO; else if (hx == 0) retval = FP_SUBNORMAL; else if (hx == 0x7ff00000) retval = lx != 0 ? FP_NAN : FP_INFINITE; return retval; } #if !defined(LONG_DOUBLE_IS_SAME_AS_DOUBLE) int __fpclassifyl (long double x) { uint32_t ex, hx, lx; int retval = FP_NORMAL; GET_LDOUBLE_WORDS (ex, hx, lx, x); ex &= 0x7fff; if ((ex | lx | hx) == 0) retval = FP_ZERO; else if (ex == 0 && (hx & 0x80000000) == 0) retval = FP_SUBNORMAL; else if (ex == 0x7fff) retval = ((hx & 0x7fffffff) | lx) != 0 ? FP_NAN : FP_INFINITE; return retval; } #endif // !defined(LONG_DOUBLE_IS_SAME_AS_DOUBLE) int fetestexcept (int excepts) { short temp; #if defined(NO_INLINE_ASM) /* Use CRT function to get current FPU status word */ unsigned int sw = _statusfp(); temp = (sw & _SW_INVALID) ? FE_INVALID : 0 | (sw & _SW_ZERODIVIDE) ? FE_DIVBYZERO : 0 | (sw & _SW_OVERFLOW) ? FE_OVERFLOW : 0 | (sw & _SW_UNDERFLOW) ? FE_UNDERFLOW : 0 | (sw & _SW_INEXACT) ? FE_INEXACT : 0 ; #else /* Use assembler to get current FPU status word */ #if defined(_MSVC_) __asm fnstsw temp #else __asm__ ("fnstsw %0" : "=a" (temp)); #endif #endif /* Return requested exception bits */ return temp & excepts & FE_ALL_EXCEPT; } int feclearexcept (int excepts) { #if defined(NO_INLINE_ASM) /* Use CRT function to clear all exceptions in FPU status word. The function _clearfp does not allow bits to be selectively cleared. However, since ieee.c only ever calls feclearexcept with the argument FE_ALL_EXCEPT we clear all bits regardless */ _clearfp(); #else /* Use assembler to clear requested exceptions in FPU status word */ fenv_t temp; /* Mask out unsupported bits/exceptions. */ excepts &= FE_ALL_EXCEPT; /* Bah, we have to clear selected exceptions. Since there is no `fldsw' instruction we have to do it the hard way. */ #if defined(_MSVC_) __asm fnstenv temp #else __asm__ ("fnstenv %0" : "=m" (*&temp)); #endif /* Clear the relevant bits. */ temp.__status_word &= excepts ^ FE_ALL_EXCEPT; /* Put the new data in effect. */ #if defined(_MSVC_) __asm fldenv temp #else __asm__ ("fldenv %0" : : "m" (*&temp)); #endif #endif /* Success. */ return 0; } /* Get current FP rounding mode */ int fegetround (void) { #if defined(NO_INLINE_ASM) /* Use CRT function to get the FPU control word */ unsigned int fcw; _controlfp_s(&fcw, 0, 0); return (fcw & RC_NEAR) ? FE_TONEAREST : 0 | (fcw & RC_CHOP) ? FE_TOWARDZERO : 0 | (fcw & RC_DOWN) ? FE_DOWNWARD : 0 | (fcw & RC_UP) ? FE_UPWARD : 0 ; #else /* Use assembler to get the FPU control word */ unsigned short _cw; /* Get the value of the FPU control word */ #if defined(_MSVC_) __asm fnstcw _cw #else __asm__ ("fnstcw %0;" : "=m" (_cw)); #endif /* Extract and return the rounding mode flags */ return _cw & (FE_TONEAREST | FE_DOWNWARD | FE_UPWARD | FE_TOWARDZERO); #endif } /* Set the FP rounding mode */ int fesetround (int mode) { #if defined(NO_INLINE_ASM) /* Use CRT function to update the FPU control word */ unsigned int fcw, bits; bits = (mode & FE_TONEAREST) ? RC_NEAR : 0 | (mode & FE_TOWARDZERO) ? RC_CHOP : 0 | (mode & FE_DOWNWARD) ? RC_DOWN : 0 | (mode & FE_UPWARD) ? RC_UP : 0 ; _controlfp_s(&fcw, bits, MCW_RC); #else /* Use assembler to update the FPU control word */ unsigned short _cw; /* Return error if new rounding mode is not valid */ if ((mode & ~(FE_TONEAREST | FE_DOWNWARD | FE_UPWARD | FE_TOWARDZERO)) != 0) return -1; /* Get the current value of the FPU control word */ #if defined(_MSVC_) __asm fnstcw _cw #else __asm__ volatile ("fnstcw %0;": "=m" (_cw)); #endif /* Replace the rounding mode bits in the FPU control word */ _cw &= ~(FE_TONEAREST | FE_DOWNWARD | FE_UPWARD | FE_TOWARDZERO); _cw |= mode; /* Update the FPU control word with the new value */ #if defined(_MSVC_) __asm fldcw _cw #else __asm__ volatile ("fldcw %0;" : : "m" (_cw)); #endif #endif return 0; } #if !defined(HAVE_RINT) && !defined(NO_INLINE_ASM) /* Round to FP integer */ double rint (double _x) { double _y; #if defined(_MSVC_) __asm { fld _x frndint fstp _y } #else __asm__ volatile ( "fld %1 ;\n\t" "frndint ;\n\t" "fstp %0 ;" : "=m" (_y) : "m" (_x) ); #endif return _y; } #define HAVE_RINT 1 #endif /*!defined(HAVE_RINT) && !defined(NO_INLINE_ASM)*/ #define GET_HIGH_WORD(i,d) \ do { \ ieee_double_shape_type gh_u; \ gh_u.value = (d); \ (i) = gh_u.parts.msw; \ } while (0) int signbit (double x) { int32_t hx; GET_HIGH_WORD (hx, x); return (hx & 0x80000000) != 0; } #if !defined(HAVE_FREXPL) #define GET_LDOUBLE_EXP(exp,d) \ do { \ ieee_long_double_shape_type ge_u; \ ge_u.value = (d); \ (exp) = ge_u.parts.sign_exponent; \ } while (0) #define SET_LDOUBLE_EXP(d,exp) \ do { \ ieee_long_double_shape_type se_u; \ se_u.value = (d); \ se_u.parts.sign_exponent = (exp); \ (d) = se_u.value; \ } while (0) long double frexpl(long double x, int *eptr) { uint32_t se, hx, ix, lx; uint64_t two64 = 0x43f0000000000000ULL; GET_LDOUBLE_WORDS(se,hx,lx,x); ix = 0x7fff&se; *eptr = 0; if(ix==0x7fff||((ix|hx|lx)==0)) return x; /* 0,inf,nan */ if (ix==0x0000) { /* subnormal */ x *= two64; GET_LDOUBLE_EXP(se,x); ix = se&0x7fff; *eptr = -64; } *eptr += ix-16382; se = (se & 0x8000) | 0x3ffe; SET_LDOUBLE_EXP(x,se); return x; } #endif /*!defined(HAVE_FREXPL)*/ #endif // _IEEE_W32_H hercules-3.07/ieee.c000644 000765 000765 00000364765 11143760543 016047 0ustar00jmaynardjmaynard000000 000000 /* * Hercules System/370, ESA/390, z/Architecture emulator * ieee.c * Binary (IEEE) Floating Point Instructions * Copyright (c) 2001-2009 Willem Konynenberg * TCEB, TCDB and TCXB contributed by Per Jessen, 20 September 2001. * THDER,THDR by Roger Bowler, 19 July 2003. * Additional instructions by Roger Bowler, November 2004: * LXDBR,LXDB,LXEBR,LXEB,LDXBR,LEXBR,CXFBR,CXGBR,CFXBR,CGXBR, * MXDBR,MXDB,MDEBR,MDEB,MADBR,MADB,MAEBR,MAEB,MSDBR,MSDB, * MSEBR,MSEB,DIEBR,DIDBR,TBEDR,TBDR. * Licensed under the Q Public License * For details, see html/herclic.html */ // $Id: ieee.c 5126 2009-01-23 13:05:56Z bernard $ /* * This module implements the ESA/390 Binary (IEEE) Floating Point * Instructions as described in * ESA/390 Principles of Operation, 6th revision, SA22-7201-05 * and * z/Architecture Principles of Operation, First Edition, SA22-7832-00 */ /* * Based very loosely on float.c by Peter Kuschnerus, (c) 2000-2006. */ /* * WARNING * For rapid implementation, this module was written to perform its * floating point arithmetic using the floating point operations of * the native C compiler. This method is a short-cut which may under * some circumstances produce results different from those required * by the Principles of Operation manuals. For complete conformance * with Principles of Operation, this module would need to be updated * to perform all floating point arithmetic using explicitly coded * bit operations, similar to how float.c implements the hexadecimal * floating point instructions. * * Rounding: * The native IEEE implementation is set to apply the rounding * as specified in the FPC register or the instruction mask. * The Rounding and Range Function is not explicitly implemented. * Most of its functionality should be covered by the native floating * point implementation. However, there are some cases where use of * this function is called for by the specification, even when no * actual arithmetic operation is performed. Here, the function would * need to be implemented explicitly. * * Precision: * This code assumes the following relations between C data types and * emulated IEEE formats: * - float can represent 32-bit short format * - double can represent 64-bit long format * - long double can represent 128-bit extended format * On some host systems (including Intel), the long double type is * actually only 80-bits, so the conversion from extended format to native * long double format will cause loss of precision and range. */ // $Log$ // Revision 1.84 2008/04/18 12:13:59 rbowler // Fix incorrect results from THDER,THDR instructions // // Revision 1.83 2008/04/16 19:57:55 rbowler // Fix condition code in LCEBR,LCDBR,LCXBR instructions // // Revision 1.82 2008/04/16 14:09:42 rbowler // Correct ieee to use BFP rounding mode not DFP rounding mode // // Revision 1.81 2008/04/15 21:30:03 rbowler // BFP rounding mode support // // Revision 1.80 2008/02/12 18:23:39 jj // TBEDR , TBDR using R1 as source, should be R2. // // Revision 1.79 2008/02/07 00:29:04 rbowler // Solaris build support by Jeff Savit // // Revision 1.78 2007/06/23 00:04:13 ivan // Update copyright notices to include current year (2007) // // Revision 1.77 2007/01/13 07:22:32 bernard // backout ccmask // // Revision 1.76 2007/01/12 15:24:07 bernard // ccmask phase 1 // // Revision 1.75 2007/01/04 23:12:04 gsmith // remove thunk calls for program_interrupt // // Revision 1.74 2006/12/08 09:43:28 jj // Add CVS message log // #include "hstdinc.h" #if !defined(_HENGINE_DLL_) #define _HENGINE_DLL_ #endif #if !defined(_IEEE_C_) #define _IEEE_C_ #endif #ifndef _GNU_SOURCE #define _GNU_SOURCE 1 #endif /* COMMENT OUT THE FOLLOWING DEFINE */ /* (_ISW_PREVENT_COMPWARN) */ /* IF IEEE FP INSTRUCTIONS ARE GIVING */ /* INCOHERENT RESULTS IN RESPECT TO */ /* INFINITY. */ #define _ISW_PREVENT_COMPWARN /* For Microsoft Visual C++, inhibit */ /* warning C4723: potential divide by 0*/ #if defined(_MSVC_) #pragma warning(disable:4723) #endif /* ABOUT THE MACRO BELOW : */ /* ISW 2004/09/15 */ /* Current GLIBC has an issue with */ /* feclearexcept that re-enables */ /* FE Traps by re-enabling Intel SSE */ /* trap mask. This leads to various */ /* machine checks from the CPU receiv- */ /* ing SIGFPE. feholdexcept reestab- */ /* lishes the proper non-stop mask */ /* */ /* Until a proper conditional can be */ /* devised to only do the feholdexcept */ /* when appropriate, it is there for */ /* all host architectures */ #ifndef FECLEAREXCEPT #define FECLEAREXCEPT(_e) \ do { \ fenv_t __fe; \ feclearexcept((_e)); \ fegetenv(&__fe); \ feholdexcept(&__fe); \ } while(0) #endif #include "hercules.h" #if defined(FEATURE_BINARY_FLOATING_POINT) && !defined(NO_IEEE_SUPPORT) #include "opcode.h" #include "inline.h" #if defined(WIN32) && !defined(HAVE_FENV_H) #include "ieee-w32.h" #endif /* jbs 01/16/2008 */ #if defined(__SOLARIS__) #include "ieee-sol.h" #endif /* Definitions of BFP rounding methods */ #define RM_DEFAULT_ROUNDING 0 #define RM_BIASED_ROUND_TO_NEAREST 1 #define RM_ROUND_TO_NEAREST 4 #define RM_ROUND_TOWARD_ZERO 5 #define RM_ROUND_TOWARD_POS_INF 6 #define RM_ROUND_TOWARD_NEG_INF 7 /* Macro to generate program check if invalid BFP rounding method */ #define BFPRM_CHECK(x,regs) \ {if (!((x)==0 || (x)==1 || ((x)>=4 && (x)<=7))) \ {regs->program_interrupt(regs, PGM_SPECIFICATION_EXCEPTION);}} #if !defined(_IEEE_C) /* Architecture independent code goes within this ifdef */ #ifndef FE_INEXACT #define FE_INEXACT 0x00 #endif struct ebfp { int sign; int exp; U64 fracth; U64 fractl; long double v; }; struct lbfp { int sign; int exp; U64 fract; double v; }; struct sbfp { int sign; int exp; int fract; float v; }; #ifndef HAVE_SQRTL #define sqrtl(x) sqrt(x) #endif #ifndef HAVE_LDEXPL #define ldexpl(x,y) ldexp(x,y) #endif #ifndef HAVE_FABSL #define fabsl(x) fabs(x) #endif #ifndef HAVE_FMODL #define fmodl(x,y) fmod(x,y) #endif #ifndef HAVE_FREXPL #define frexpl(x,y) frexp(x,y) #endif #ifndef HAVE_LDEXPF #define ldexpf(x,y) ((float)ldexp((double)(x),(y))) #endif #ifndef HAVE_FREXPF #define frexpf(x,y) ((float)frexp((double)(x),(y))) #endif #ifndef HAVE_FABSF #define fabsf(x) ((float)fabs((double)(x))) #endif #ifndef HAVE_RINT #define rint(i) (((i)-floor(i)<0.5)?floor(i):ceil(i)) #endif #endif /* !defined(_IEEE_C) */ /* externally defined architecture-dependent functions */ /* I guess this could go into an include file... */ #define vfetch4 ARCH_DEP(vfetch4) #define vfetch8 ARCH_DEP(vfetch8) /* locally defined architecture-dependent functions */ #define ieee_exception ARCH_DEP(ieee_exception) #define vfetch_lbfp ARCH_DEP(vfetch_lbfp) #define vfetch_sbfp ARCH_DEP(vfetch_sbfp) #define add_ebfp ARCH_DEP(add_ebfp) #define add_lbfp ARCH_DEP(add_lbfp) #define add_sbfp ARCH_DEP(add_sbfp) #define compare_ebfp ARCH_DEP(compare_ebfp) #define compare_lbfp ARCH_DEP(compare_lbfp) #define compare_sbfp ARCH_DEP(compare_sbfp) #define divide_ebfp ARCH_DEP(divide_ebfp) #define divide_lbfp ARCH_DEP(divide_lbfp) #define divide_sbfp ARCH_DEP(divide_sbfp) #define integer_ebfp ARCH_DEP(integer_ebfp) #define integer_lbfp ARCH_DEP(integer_lbfp) #define integer_sbfp ARCH_DEP(integer_sbfp) #define load_test_ebfp ARCH_DEP(load_test_ebfp) #define load_test_lbfp ARCH_DEP(load_test_lbfp) #define load_test_sbfp ARCH_DEP(load_test_sbfp) #define load_neg_ebfp ARCH_DEP(load_neg_ebfp) #define load_neg_lbfp ARCH_DEP(load_neg_lbfp) #define load_neg_sbfp ARCH_DEP(load_neg_sbfp) #define load_pos_ebfp ARCH_DEP(load_pos_ebfp) #define load_pos_lbfp ARCH_DEP(load_pos_lbfp) #define load_pos_sbfp ARCH_DEP(load_pos_sbfp) #define multiply_ebfp ARCH_DEP(multiply_ebfp) #define multiply_lbfp ARCH_DEP(multiply_lbfp) #define multiply_sbfp ARCH_DEP(multiply_sbfp) #define squareroot_ebfp ARCH_DEP(squareroot_ebfp) #define squareroot_lbfp ARCH_DEP(squareroot_lbfp) #define squareroot_sbfp ARCH_DEP(squareroot_sbfp) #define subtract_ebfp ARCH_DEP(subtract_ebfp) #define subtract_lbfp ARCH_DEP(subtract_lbfp) #define subtract_sbfp ARCH_DEP(subtract_sbfp) #define test_data_class_ebfp ARCH_DEP(test_data_class_ebfp) #define test_data_class_lbfp ARCH_DEP(test_data_class_lbfp) #define test_data_class_sbfp ARCH_DEP(test_data_class_sbfp) #define divint_lbfp ARCH_DEP(divint_lbfp) #define divint_sbfp ARCH_DEP(divint_sbfp) /* * Convert from C IEEE exception to Pop IEEE exception */ static inline int ieee_exception(int raised, REGS * regs) { int dxc = 0; if (raised & FE_INEXACT) { /* * C doesn't tell use whether it truncated or incremented, * so we will just always claim it truncated. */ dxc = DXC_IEEE_INEXACT_INCR; } /* This sequence sets dxc according to the priorities defined * in PoP, Ch. 6, Data Exception Code. */ if (raised & FE_UNDERFLOW) { dxc |= DXC_IEEE_UF_EXACT; } else if (raised & FE_OVERFLOW) { dxc |= DXC_IEEE_OF_EXACT; } else if (raised & FE_DIVBYZERO) { dxc = DXC_IEEE_DIV_ZERO; } else if (raised & FE_INVALID) { dxc = DXC_IEEE_INVALID_OP; } if (dxc & ((regs->fpc & FPC_MASK) >> 24)) { regs->dxc = dxc; regs->fpc |= dxc << 8; if (dxc == DXC_IEEE_DIV_ZERO || dxc == DXC_IEEE_INVALID_OP) { /* suppress operation */ regs->program_interrupt(regs, PGM_DATA_EXCEPTION); } /* * Other operations need to take appropriate action * to complete the operation. * In most cases, C will have done the right thing... */ return PGM_DATA_EXCEPTION; } else { /* Set flags in FPC */ regs->fpc |= (dxc & 0xF8) << 16; /* have caller take default action */ return 0; } } #if !defined(_IEEE_C) /* * Set rounding mode according to BFP rounding mode mask */ void set_rounding_mode(U32 fpcreg, int mask) { int brm, ferm; /* If mask is zero, obtain rounding mode from FPC register */ if (mask == RM_DEFAULT_ROUNDING) brm = ((fpcreg & FPC_BRM) >> FPC_BRM_SHIFT) + 4; else brm = mask; /* Convert BFP rounding mode to nearest equivalent FE rounding mode */ switch (brm) { case RM_ROUND_TO_NEAREST: /* Round to nearest ties to even */ ferm = FE_TONEAREST; break; case RM_ROUND_TOWARD_ZERO: /* Round toward zero */ ferm = FE_TOWARDZERO; break; case RM_ROUND_TOWARD_POS_INF: /* Round toward +infinity */ ferm = FE_UPWARD; break; case RM_ROUND_TOWARD_NEG_INF: /* Round toward -infinity */ ferm = FE_DOWNWARD; break; default: ferm = FE_TONEAREST; break; } /* end switch(brm) */ /* Switch rounding mode if necessary */ if (fegetround() != ferm) fesetround(ferm); } /* end function set_rounding_mode */ /* * Classify emulated fp values */ int ebfpclassify(struct ebfp *op) { if (op->exp == 0) { if (op->fracth == 0 && op->fractl == 0) return FP_ZERO; else return FP_SUBNORMAL; } else if (op->exp == 0x7FFF) { if (op->fracth == 0 && op->fractl == 0) return FP_INFINITE; else return FP_NAN; } else { return FP_NORMAL; } } int lbfpclassify(struct lbfp *op) { if (op->exp == 0) { if (op->fract == 0) return FP_ZERO; else return FP_SUBNORMAL; } else if (op->exp == 0x7FF) { if (op->fract == 0) return FP_INFINITE; else return FP_NAN; } else { return FP_NORMAL; } } int sbfpclassify(struct sbfp *op) { if (op->exp == 0) { if (op->fract == 0) return FP_ZERO; else return FP_SUBNORMAL; } else if (op->exp == 0xFF) { if (op->fract == 0) return FP_INFINITE; else return FP_NAN; } else { return FP_NORMAL; } } int ebfpissnan(struct ebfp *op) { return ebfpclassify(op) == FP_NAN && (op->fracth & 0x0000800000000000ULL) == 0; } int lbfpissnan(struct lbfp *op) { return lbfpclassify(op) == FP_NAN && (op->fract & 0x0008000000000000ULL) == 0; } int sbfpissnan(struct sbfp *op) { return sbfpclassify(op) == FP_NAN && (op->fract & 0x00400000) == 0; } /* * A special QNaN is supplied as the default result for * an IEEE-invalid-operation condition; it has a plus * sign and a leftmost fraction bit of one, with the * remaining fraction bits being set to zeros. */ void ebfpdnan(struct ebfp *op) { op->sign = 0; op->exp = 0x7FFF; op->fracth = 0x0000800000000000ULL; op->fractl = 0; } void lbfpdnan(struct lbfp *op) { op->sign = 0; op->exp = 0x7FF; op->fract = 0x0008000000000000ULL; } void sbfpdnan(struct sbfp *op) { op->sign = 0; op->exp = 0xFF; op->fract = 0x00400000; } void ebfpstoqnan(struct ebfp *op) { op->fracth |= 0x0000800000000000ULL; } void lbfpstoqnan(struct lbfp *op) { op->fract |= 0x0008000000000000ULL; } void sbfpstoqnan(struct sbfp *op) { op->fract |= 0x00400000; } void ebfpzero(struct ebfp *op, int sign) { op->exp = 0; op->fracth = 0; op->fractl = 0; op->sign = sign; } void lbfpzero(struct lbfp *op, int sign) { op->exp = 0; op->fract = 0; op->sign = sign; } void sbfpzero(struct sbfp *op, int sign) { op->exp = 0; op->fract = 0; op->sign = sign; } void ebfpinfinity(struct ebfp *op, int sign) { op->exp = 0x7FFF; op->fracth = 0; op->fractl = 0; op->sign = sign; } void lbfpinfinity(struct lbfp *op, int sign) { op->exp = 0x7FF; op->fract = 0; op->sign = sign; } void sbfpinfinity(struct sbfp *op, int sign) { op->exp = 0xFF; op->fract = 0; op->sign = sign; } /* * Conversion either way does not check for any loss of precision, * overflow, etc. * As noted above, it is well possible that for some formats, the native * format has less range or precision than the emulated format. * In that case, the conversion could change the value. * Similarly, if the situation is the other way around, certain exceptions * will not happen when the native operations are performed, and should * thus be raised when converting to the emulated format. * When precision is reduced, the result could be that an inexact result * is produced without proper notification. When range is reduced, a * garbled result can be produced due to an out-of-range exponent value, * where an infinity should have been produced. * Since this concerns only a few boundary conditions, few of the programs * that are going to use these instructions will care. * If you want to do high-precision number-crunching, you'll find a better way. * * This code should deal with FPC bits 0.0 and 1.0 when handling a NaN, * but it doesn't yet. */ /* * Simulated to Native conversion */ void ebfpston(struct ebfp *op) { long double h, l; #if defined(_ISW_PREVENT_COMPWARN) long double dummyzero; #endif switch (ebfpclassify(op)) { case FP_NAN: logmsg(_("ebfpston: unexpectedly converting a NaN\n")); op->v = sqrt(-1); break; case FP_INFINITE: logmsg(_("ebfpston: unexpectedly converting an Infinite\n")); if (op->sign) { op->v = log(0); } else { #if defined(_ISW_PREVENT_COMPWARN) dummyzero=0; op->v = 1/dummyzero; #else op->v = 1/0; #endif } break; case FP_ZERO: if (op->sign) { op->v = 1 / log(0); } else { op->v = 0; } break; case FP_SUBNORMAL: /* WARNING: * This code is probably not correct yet. * I only did the quick hack of removing unit bit 1. * Haven't looked at exponent handling yet. */ h = ldexpl((long double)(op->fracth), -48); l = ldexpl((long double)op->fractl, -112); if (op->sign) { h = -h; l = -l; } op->v = ldexpl(h + l, op->exp - 16383); break; case FP_NORMAL: h = ldexpl((long double)(op->fracth | 0x1000000000000ULL), -48); l = ldexpl((long double)op->fractl, -112); if (op->sign) { h = -h; l = -l; } op->v = ldexpl(h + l, op->exp - 16383); break; } //logmsg("exp=%d fracth=%" I64_FMT "x fractl=%" I64_FMT "x v=%Lg\n", op->exp, op->fracth, op->fractl, op->v); } void lbfpston(struct lbfp *op) { double t; #if defined(_ISW_PREVENT_COMPWARN) double dummyzero; #endif switch (lbfpclassify(op)) { case FP_NAN: logmsg(_("lbfpston: unexpectedly converting a NaN\n")); op->v = sqrt(-1); break; case FP_INFINITE: logmsg(_("lbfpston: unexpectedly converting an Infinite\n")); if (op->sign) { op->v = log(0); } else { #if defined(_ISW_PREVENT_COMPWARN) dummyzero=0; op->v = 1/dummyzero; #else op->v = 1/0; #endif } break; case FP_ZERO: if (op->sign) { op->v = 1 / log(0); } else { op->v = 0; } break; case FP_SUBNORMAL: /* WARNING: * This code is probably not correct yet. * I only did the quick hack of removing unit bit 1. * Haven't looked at exponent handling yet. */ t = ldexp((double)(op->fract), -52); if (op->sign) t = -t; op->v = ldexp(t, op->exp - 1023); break; case FP_NORMAL: t = ldexp((double)(op->fract | 0x10000000000000ULL), -52); if (op->sign) t = -t; op->v = ldexp(t, op->exp - 1023); break; } //logmsg("exp=%d fract=%" I64_FMT "x v=%g\n", op->exp, op->fract, op->v); } void sbfpston(struct sbfp *op) { float t; #if defined(_ISW_PREVENT_COMPWARN) float dummyzero; #endif switch (sbfpclassify(op)) { case FP_NAN: logmsg(_("sbfpston: unexpectedly converting a NaN\n")); op->v = sqrt(-1); break; case FP_INFINITE: logmsg(_("sbfpston: unexpectedly converting an Infinite\n")); if (op->sign) { op->v = log(0); } else { #if defined(_ISW_PREVENT_COMPWARN) dummyzero=0; op->v = 1/dummyzero; #else op->v = 1/0; #endif } break; case FP_ZERO: if (op->sign) { op->v = 1 / log(0); } else { op->v = 0; } break; case FP_SUBNORMAL: /* WARNING: * This code is probably not correct yet. * I only did the quick hack of removing unit bit 1. * Haven't looked at exponent handling yet. */ t = ldexpf((float)(op->fract | 0x800000), -23); if (op->sign) t = -t; op->v = ldexpf(t, op->exp - 127); break; case FP_NORMAL: t = ldexpf((float)(op->fract | 0x800000), -23); if (op->sign) t = -t; op->v = ldexpf(t, op->exp - 127); break; } //logmsg("exp=%d fract=%x v=%g\n", op->exp, op->fract, op->v); } /* * Native to Simulated conversion */ void ebfpntos(struct ebfp *op) { long double f; switch (fpclassify(op->v)) { case FP_NAN: ebfpdnan(op); break; case FP_INFINITE: ebfpinfinity(op, signbit(op->v)); break; case FP_ZERO: ebfpzero(op, signbit(op->v)); break; case FP_SUBNORMAL: /* This may need special handling, but I don't know * exactly how yet. I suspect I need to do something * to deal with the different implied unit bit. */ case FP_NORMAL: f = frexpl(op->v, &(op->exp)); op->sign = signbit(op->v); op->exp += 16383 - 1; op->fracth = (U64)ldexp(fabsl(f), 49) & 0xFFFFFFFFFFFFULL; op->fractl = (U64)fmodl(ldexp(fabsl(f), 113), pow(2, 64)); break; } //logmsg("exp=%d fracth=%" I64_FMT "x fractl=%" I64_FMT "x v=%Lg\n", op->exp, op->fracth, op->fractl, op->v); } void lbfpntos(struct lbfp *op) { double f; switch (fpclassify(op->v)) { case FP_NAN: lbfpdnan(op); break; case FP_INFINITE: lbfpinfinity(op, signbit(op->v)); break; case FP_ZERO: lbfpzero(op, signbit(op->v)); break; case FP_SUBNORMAL: /* This may need special handling, but I don't know * exactly how yet. I suspect I need to do something * to deal with the different implied unit bit. */ case FP_NORMAL: f = frexp(op->v, &(op->exp)); op->sign = signbit(op->v); op->exp += 1023 - 1; op->fract = (U64)ldexp(fabs(f), 53) & 0xFFFFFFFFFFFFFULL; break; } //logmsg("exp=%d fract=%" I64_FMT "x v=%g\n", op->exp, op->fract, op->v); } void sbfpntos(struct sbfp *op) { float f; switch (fpclassify(op->v)) { case FP_NAN: sbfpdnan(op); break; case FP_INFINITE: sbfpinfinity(op, signbit(op->v)); break; case FP_ZERO: sbfpzero(op, signbit(op->v)); break; case FP_SUBNORMAL: /* This may need special handling, but I don't * exactly how yet. I suspect I need to do something * to deal with the different implied unit bit. */ case FP_NORMAL: f = frexpf(op->v, &(op->exp)); op->sign = signbit(op->v); op->exp += 127 - 1; op->fract = (U32)ldexp(fabsf(f), 24) & 0x7FFFFF; break; } //logmsg("exp=%d fract=%x v=%g\n", op->exp, op->fract, op->v); } /* * Get/fetch binary float from registers/memory */ static void get_ebfp(struct ebfp *op, U32 *fpr) { op->sign = (fpr[0] & 0x80000000) != 0; op->exp = (fpr[0] & 0x7FFF0000) >> 16; op->fracth = (((U64)fpr[0] & 0x0000FFFF) << 32) | fpr[1]; op->fractl = ((U64)fpr[FPREX] << 32) | fpr[FPREX+1]; } static void get_lbfp(struct lbfp *op, U32 *fpr) { op->sign = (fpr[0] & 0x80000000) != 0; op->exp = (fpr[0] & 0x7FF00000) >> 20; op->fract = (((U64)fpr[0] & 0x000FFFFF) << 32) | fpr[1]; //logmsg("lget r=%8.8x%8.8x exp=%d fract=%" I64_FMT "x\n", fpr[0], fpr[1], op->exp, op->fract); } #endif /* !defined(_IEEE_C) */ static void vfetch_lbfp(struct lbfp *op, VADR addr, int arn, REGS *regs) { U64 v; v = vfetch8(addr, arn, regs); op->sign = (v & 0x8000000000000000ULL) != 0; op->exp = (v & 0x7FF0000000000000ULL) >> 52; op->fract = v & 0x000FFFFFFFFFFFFFULL; //logmsg("lfetch m=%16.16" I64_FMT "x exp=%d fract=%" I64_FMT "x\n", v, op->exp, op->fract); } #if !defined(_IEEE_C) static void get_sbfp(struct sbfp *op, U32 *fpr) { op->sign = (*fpr & 0x80000000) != 0; op->exp = (*fpr & 0x7F800000) >> 23; op->fract = *fpr & 0x007FFFFF; //logmsg("sget r=%8.8x exp=%d fract=%x\n", *fpr, op->exp, op->fract); } #endif /* !defined(_IEEE_C) */ static void vfetch_sbfp(struct sbfp *op, VADR addr, int arn, REGS *regs) { U32 v; v = vfetch4(addr, arn, regs); op->sign = (v & 0x80000000) != 0; op->exp = (v & 0x7F800000) >> 23; op->fract = v & 0x007FFFFF; //logmsg("sfetch m=%8.8x exp=%d fract=%x\n", v, op->exp, op->fract); } #if !defined(_IEEE_C) /* * Put binary float in registers */ static void put_ebfp(struct ebfp *op, U32 *fpr) { fpr[0] = (op->sign ? 1<<31 : 0) | (op->exp<<16) | (op->fracth>>32); fpr[1] = op->fracth & 0xFFFFFFFF; fpr[FPREX] = op->fractl>>32; fpr[FPREX+1] = op->fractl & 0xFFFFFFFF; } static void put_lbfp(struct lbfp *op, U32 *fpr) { fpr[0] = (op->sign ? 1<<31 : 0) | (op->exp<<20) | (op->fract>>32); fpr[1] = op->fract & 0xFFFFFFFF; //logmsg("lput exp=%d fract=%" I64_FMT "x r=%8.8x%8.8x\n", op->exp, op->fract, fpr[0], fpr[1]); } static void put_sbfp(struct sbfp *op, U32 *fpr) { fpr[0] = (op->sign ? 1<<31 : 0) | (op->exp<<23) | op->fract; //logmsg("sput exp=%d fract=%x r=%8.8x\n", op->exp, op->fract, *fpr); } /* * Convert binary float to longer format */ static void lengthen_short_to_long(struct sbfp *op2, struct lbfp *op1, REGS *regs) { switch (sbfpclassify(op2)) { case FP_ZERO: lbfpzero(op1, op2->sign); break; case FP_NAN: if (sbfpissnan(op2)) { ieee_exception(FE_INVALID, regs); lbfpstoqnan(op1); } break; case FP_INFINITE: lbfpinfinity(op1, op2->sign); break; default: sbfpston(op2); op1->v = (double)op2->v; lbfpntos(op1); break; } } static void lengthen_long_to_ext(struct lbfp *op2, struct ebfp *op1, REGS *regs) { switch (lbfpclassify(op2)) { case FP_ZERO: ebfpzero(op1, op2->sign); break; case FP_NAN: if (lbfpissnan(op2)) { ieee_exception(FE_INVALID, regs); ebfpstoqnan(op1); } break; case FP_INFINITE: ebfpinfinity(op1, op2->sign); break; default: lbfpston(op2); op1->v = (long double)op2->v; ebfpntos(op1); break; } } static void lengthen_short_to_ext(struct sbfp *op2, struct ebfp *op1, REGS *regs) { switch (sbfpclassify(op2)) { case FP_ZERO: ebfpzero(op1, op2->sign); break; case FP_NAN: if (sbfpissnan(op2)) { ieee_exception(FE_INVALID, regs); ebfpstoqnan(op1); } break; case FP_INFINITE: ebfpinfinity(op1, op2->sign); break; default: sbfpston(op2); op1->v = (long double)op2->v; ebfpntos(op1); break; } } #define _IEEE_C #endif /* !defined(_IEEE_C) */ /* * Chapter 9. Floating-Point Overview and Support Instructions */ #if defined(FEATURE_FPS_EXTENSIONS) #if !defined(_CBH_FUNC) /* * Convert binary floating point to hexadecimal long floating point * save result into long register and return condition code * Roger Bowler, 19 July 2003 */ static int cnvt_bfp_to_hfp (struct lbfp *op, int class, U32 *fpr) { int exp; U64 fract; U32 r0, r1; int cc; switch (class) { default: case FP_NAN: r0 = 0x7FFFFFFF; r1 = 0xFFFFFFFF; cc = 3; break; case FP_INFINITE: r0 = op->sign ? 0xFFFFFFFF : 0x7FFFFFFF; r1 = 0xFFFFFFFF; cc = 3; break; case FP_ZERO: r0 = op->sign ? 0x80000000 : 0; r1 = 0; cc = 0; break; case FP_SUBNORMAL: r0 = op->sign ? 0x80000000 : 0; r1 = 0; cc = op->sign ? 1 : 2; break; case FP_NORMAL: //logmsg("ieee: exp=%d (X\'%3.3x\')\tfract=%16.16"I64_FMT"x\n", // op->exp, op->exp, op->fract); /* Insert an implied 1. in front of the 52 bit binary fraction and lengthen the result to 56 bits */ fract = (U64)(op->fract | 0x10000000000000ULL) << 3; /* The binary exponent is equal to the biased exponent - 1023 adjusted by 1 to move the point before the 56 bit fraction */ exp = op->exp - 1023 + 1; //logmsg("ieee: adjusted exp=%d\tfract=%16.16"I64_FMT"x\n", exp, fract); /* Shift the fraction right one bit at a time until the binary exponent becomes a multiple of 4 */ while (exp & 3) { exp++; fract >>= 1; } //logmsg("ieee: shifted exp=%d\tfract=%16.16"I64_FMT"x\n", exp, fract); /* Convert the binary exponent into a hexadecimal exponent by dropping the last two bits (which are now zero) */ exp >>= 2; /* If the hexadecimal exponent is less than -64 then return a signed zero result with a non-zero condition code */ if (exp < -64) { r0 = op->sign ? 0x80000000 : 0; r1 = 0; cc = op->sign ? 1 : 2; break; } /* If the hexadecimal exponent exceeds +63 then return a signed maximum result with condition code 3 */ if (exp > 63) { r0 = op->sign ? 0xFFFFFFFF : 0x7FFFFFFF; r1 = 0xFFFFFFFF; cc = 3; break; } /* Convert the hexadecimal exponent to a characteristic by adding 64 */ exp += 64; /* Pack the exponent and the fraction into the result */ r0 = (op->sign ? 1<<31 : 0) | (exp << 24) | (fract >> 32); r1 = fract & 0xFFFFFFFF; cc = op->sign ? 1 : 2; break; } /* Store high and low halves of result into fp register array and return condition code */ fpr[0] = r0; fpr[1] = r1; return cc; } /* end function cnvt_bfp_to_hfp */ /* * Convert hexadecimal long floating point register to * binary floating point and return condition code * Roger Bowler, 28 Nov 2004 */ static int cnvt_hfp_to_bfp (U32 *fpr, int rounding, int bfp_fractbits, int bfp_emax, int bfp_ebias, int *result_sign, int *result_exp, U64 *result_fract) { BYTE sign; short expo; U64 fract; int roundup = 0; int cc; U64 b; /* Break the source operand into sign, characteristic, fraction */ sign = fpr[0] >> 31; expo = (fpr[0] >> 24) & 0x007F; fract = ((U64)(fpr[0] & 0x00FFFFFF) << 32) | fpr[1]; /* Determine whether to round up or down */ switch (rounding) { case RM_BIASED_ROUND_TO_NEAREST: case RM_ROUND_TO_NEAREST: roundup = 0; break; case RM_DEFAULT_ROUNDING: case RM_ROUND_TOWARD_ZERO: roundup = 0; break; case RM_ROUND_TOWARD_POS_INF: roundup = (sign ? 0 : 1); break; case RM_ROUND_TOWARD_NEG_INF: roundup = sign; break; } /* end switch(rounding) */ /* Convert HFP zero to BFP zero and return cond code 0 */ if (fract == 0) /* a = -0 or +0 */ { *result_sign = sign; *result_exp = 0; *result_fract = 0; return 0; } /* Set the condition code */ cc = sign ? 1 : 2; /* Convert the HFP characteristic to a true binary exponent */ expo = (expo - 64) * 4; /* Convert true binary exponent to a biased exponent */ expo += bfp_ebias; /* Shift the fraction left until leftmost 1 is in bit 8 */ while ((fract & 0x0080000000000000ULL) == 0) { fract <<= 1; expo -= 1; } /* Convert 56-bit fraction to 55-bit with implied 1 */ expo--; fract &= 0x007FFFFFFFFFFFFFULL; if (expo < -(bfp_fractbits-1)) /* |a| < Dmin */ { if (expo == -(bfp_fractbits-1) - 1) { if (rounding == RM_BIASED_ROUND_TO_NEAREST || rounding == RM_ROUND_TO_NEAREST) roundup = 1; } if (roundup) { expo = 0; fract = 1; } /* Dmin */ else { expo = 0; fract = 0; } /* Zero */ } else if (expo < 1) /* Dmin <= |a| < Nmin */ { /* Reinstate implied 1 in preparation for denormalization */ fract |= 0x0080000000000000ULL; /* Denormalize to get exponent back in range */ fract >>= (expo + (bfp_fractbits-1)); expo = 0; } else if (expo > (bfp_emax+bfp_ebias)) /* |a| > Nmax */ { cc = 3; if (roundup) { /* Inf */ expo = (bfp_emax+bfp_ebias) + 1; fract = 0; } else { /* Nmax */ expo = (bfp_emax+bfp_ebias); fract = 0x007FFFFFFFFFFFFFULL - (((U64)1<<(1+(55-bfp_fractbits)))-1); } /* Nmax */ } /* end Nmax < |a| */ /* Set the result sign and exponent */ *result_sign = sign; *result_exp = expo; /* Apply rounding before truncating to final fraction length */ b = ( (U64)1 ) << ( 55 - bfp_fractbits); if (roundup && (fract & b)) { fract += b; } /* Convert 55-bit fraction to result fraction length */ *result_fract = fract >> (55-bfp_fractbits); return cc; } /* end function cnvt_hfp_to_bfp */ #define _CBH_FUNC #endif /*!defined(_CBH_FUNC)*/ /* * B359 THDR - CONVERT BFP TO HFP (long) [RRE] * Roger Bowler, 19 July 2003 */ DEF_INST(convert_bfp_long_to_float_long_reg) { int r1, r2; struct lbfp op2; RRE(inst, regs, r1, r2); //logmsg("THDR r1=%d r2=%d\n", r1, r2); HFPREG2_CHECK(r1, r2, regs); /* Load lbfp operand from R2 register */ get_lbfp(&op2, regs->fpr + FPR2I(r2)); /* Convert to hfp register and set condition code */ regs->psw.cc = cnvt_bfp_to_hfp (&op2, lbfpclassify(&op2), regs->fpr + FPR2I(r1)); } /* end DEF_INST(convert_bfp_long_to_float_long_reg) */ /* * B358 THDER - CONVERT BFP TO HFP (short to long) [RRE] * Roger Bowler, 19 July 2003 */ DEF_INST(convert_bfp_short_to_float_long_reg) { int r1, r2; struct sbfp op2; struct lbfp lbfp_op2; RRE(inst, regs, r1, r2); //logmsg("THDER r1=%d r2=%d\n", r1, r2); HFPREG2_CHECK(r1, r2, regs); /* Load sbfp operand from R2 register */ get_sbfp(&op2, regs->fpr + FPR2I(r2)); /* Lengthen sbfp operand to lbfp */ lbfp_op2.sign = op2.sign; lbfp_op2.exp = op2.exp - 127 + 1023; lbfp_op2.fract = (U64)op2.fract << (52 - 23); /* Convert lbfp to hfp register and set condition code */ regs->psw.cc = cnvt_bfp_to_hfp (&lbfp_op2, sbfpclassify(&op2), regs->fpr + FPR2I(r1)); } /* end DEF_INST(convert_bfp_short_to_float_long_reg) */ /* * B351 TBDR - CONVERT HFP TO BFP (long) [RRF] */ DEF_INST(convert_float_long_to_bfp_long_reg) { int r1, r2, m3; struct lbfp op1; RRF_M(inst, regs, r1, r2, m3); //logmsg("TBDR r1=%d r2=%d\n", r1, r2); HFPREG2_CHECK(r1, r2, regs); BFPRM_CHECK(m3,regs); regs->psw.cc = cnvt_hfp_to_bfp (regs->fpr + FPR2I(r2), m3, /*fractbits*/52, /*emax*/1023, /*ebias*/1023, &(op1.sign), &(op1.exp), &(op1.fract)); put_lbfp(&op1, regs->fpr + FPR2I(r1)); } /* end DEF_INST(convert_float_long_to_bfp_long_reg) */ /* * B350 TBEDR - CONVERT HFP TO BFP (long to short) [RRF] */ DEF_INST(convert_float_long_to_bfp_short_reg) { int r1, r2, m3; struct sbfp op1; U64 fract; RRF_M(inst, regs, r1, r2, m3); //logmsg("TBEDR r1=%d r2=%d\n", r1, r2); HFPREG2_CHECK(r1, r2, regs); BFPRM_CHECK(m3,regs); regs->psw.cc = cnvt_hfp_to_bfp (regs->fpr + FPR2I(r2), m3, /*fractbits*/23, /*emax*/127, /*ebias*/127, &(op1.sign), &(op1.exp), &fract); op1.fract = (U32)fract; put_sbfp(&op1, regs->fpr + FPR2I(r1)); } /* end DEF_INST(convert_float_long_to_bfp_short_reg) */ #endif /*defined(FEATURE_FPS_EXTENSIONS)*/ /* * Chapter 19. Binary-Floating-Point Instructions * Most of these instructions were defined as an update to ESA/390. * z/Architecture has added instructions for 64-bit integers. */ /* * ADD (extended) */ static int add_ebfp(struct ebfp *op1, struct ebfp *op2, REGS *regs) { int r, cl1, cl2, raised; if (ebfpissnan(op1) || ebfpissnan(op2)) { r = ieee_exception(FE_INVALID, regs); if (r) { return r; } } cl1 = ebfpclassify(op1); cl2 = ebfpclassify(op2); if ((cl1 == FP_NORMAL || cl1 == FP_SUBNORMAL) &&(cl2 == FP_NORMAL || cl2 == FP_SUBNORMAL)) { FECLEAREXCEPT(FE_ALL_EXCEPT); ebfpston(op1); ebfpston(op2); op1->v += op2->v; ebfpntos(op1); raised = fetestexcept(FE_ALL_EXCEPT); if (raised) { r = ieee_exception(raised, regs); if (r) { return r; } } cl1 = ebfpclassify(op1); } else if (cl1 == FP_NAN) { if (ebfpissnan(op1)) { ebfpstoqnan(op1); } else if (ebfpissnan(op2)) { *op1 = *op2; ebfpstoqnan(op1); } regs->psw.cc = 3; return 0; } else if (cl2 == FP_NAN) { if (ebfpissnan(op2)) { *op1 = *op2; ebfpstoqnan(op1); } else { *op1 = *op2; } regs->psw.cc = 3; return 0; } else if (cl1 == FP_INFINITE || cl2 == FP_INFINITE) { if (cl1 == FP_INFINITE) { if (cl2 == FP_INFINITE && op1->sign != op2->sign) { r = ieee_exception(FE_INVALID, regs); if (r) { return r; } ebfpdnan(op1); regs->psw.cc = 3; return 0; } else { /* result is first operand */ } } else { *op1 = *op2; cl1 = cl2; } } else if (cl1 == FP_ZERO) { if (cl2 == FP_ZERO && op1->sign != op2->sign) { /* exact-zero difference result */ ebfpzero(op1, ((regs->fpc & FPC_BRM) == 3) ? 1 : 0); } else { *op1 = *op2; cl1 = cl2; } } else if (cl2 == FP_ZERO) { /* result is first operand */ } regs->psw.cc = cl1 == FP_ZERO ? 0 : op1->sign ? 1 : 2; return 0; } /* * B34A AXBR - ADD (extended BFP) [RRE] */ DEF_INST(add_bfp_ext_reg) { int r1, r2; struct ebfp op1, op2; int pgm_check; RRE(inst, regs, r1, r2); //logmsg("AXBR r1=%d r2=%d\n", r1, r2); BFPINST_CHECK(regs); BFPREGPAIR2_CHECK(r1, r2, regs); get_ebfp(&op1, regs->fpr + FPR2I(r1)); get_ebfp(&op2, regs->fpr + FPR2I(r2)); pgm_check = add_ebfp(&op1, &op2, regs); put_ebfp(&op1, regs->fpr + FPR2I(r1)); if (pgm_check) { regs->program_interrupt(regs, pgm_check); } } /* * ADD (long) */ static int add_lbfp(struct lbfp *op1, struct lbfp *op2, REGS *regs) { int r, cl1, cl2, raised; if (lbfpissnan(op1) || lbfpissnan(op2)) { r = ieee_exception(FE_INVALID, regs); if (r) { return r; } } cl1 = lbfpclassify(op1); cl2 = lbfpclassify(op2); if (cl1 == FP_NAN) { if (lbfpissnan(op1)) { lbfpstoqnan(op1); } else if (lbfpissnan(op2)) { *op1 = *op2; lbfpstoqnan(op1); } regs->psw.cc = 3; return 0; } else if (cl2 == FP_NAN) { if (lbfpissnan(op2)) { *op1 = *op2; lbfpstoqnan(op1); } else { *op1 = *op2; } regs->psw.cc = 3; return 0; } else if (cl1 == FP_INFINITE && cl2 == FP_INFINITE && op1->sign != op2->sign) { r = ieee_exception(FE_INVALID, regs); if (r) { return r; } lbfpdnan(op1); regs->psw.cc = 3; return 0; } else if (cl1 == FP_INFINITE) { /* result is first operand */ } else if (cl2 == FP_INFINITE) { *op1 = *op2; cl1 = cl2; } else if (cl1 == FP_ZERO) { *op1 = *op2; cl1 = cl2; } else if (cl2 == FP_ZERO) { /* result is first operand */ } else { FECLEAREXCEPT(FE_ALL_EXCEPT); lbfpston(op1); lbfpston(op2); op1->v += op2->v; lbfpntos(op1); raised = fetestexcept(FE_ALL_EXCEPT); if (raised) { r = ieee_exception(raised, regs); if (r) { return r; } } cl1 = lbfpclassify(op1); } regs->psw.cc = cl1 == FP_ZERO ? 0 : op1->sign ? 1 : 2; return 0; } /* * B31A ADBR - ADD (long BFP) [RRE] */ DEF_INST(add_bfp_long_reg) { int r1, r2; struct lbfp op1, op2; int pgm_check; RRE(inst, regs, r1, r2); //logmsg("ADBR r1=%d r2=%d\n", r1, r2); BFPINST_CHECK(regs); get_lbfp(&op1, regs->fpr + FPR2I(r1)); get_lbfp(&op2, regs->fpr + FPR2I(r2)); pgm_check = add_lbfp(&op1, &op2, regs); put_lbfp(&op1, regs->fpr + FPR2I(r1)); if (pgm_check) { regs->program_interrupt(regs, pgm_check); } } /* * ED1A ADB - ADD (long BFP) [RXE] */ DEF_INST(add_bfp_long) { int r1, b2; VADR effective_addr2; struct lbfp op1, op2; int pgm_check; RXE(inst, regs, r1, b2, effective_addr2); //logmsg("ADB r1=%d b2=%d\n", r1, b2); BFPINST_CHECK(regs); get_lbfp(&op1, regs->fpr + FPR2I(r1)); vfetch_lbfp(&op2, effective_addr2, b2, regs); pgm_check = add_lbfp(&op1, &op2, regs); put_lbfp(&op1, regs->fpr + FPR2I(r1)); if (pgm_check) { regs->program_interrupt(regs, pgm_check); } } /* * ADD (short) */ static int add_sbfp(struct sbfp *op1, struct sbfp *op2, REGS *regs) { int r, cl1, cl2, raised; if (sbfpissnan(op1) || sbfpissnan(op2)) { r = ieee_exception(FE_INVALID, regs); if (r) { return r; } } cl1 = sbfpclassify(op1); cl2 = sbfpclassify(op2); if (cl1 == FP_NAN) { if (sbfpissnan(op1)) { sbfpstoqnan(op1); } else if (sbfpissnan(op2)) { *op1 = *op2; sbfpstoqnan(op1); } regs->psw.cc = 3; return 0; } else if (cl2 == FP_NAN) { if (sbfpissnan(op2)) { *op1 = *op2; sbfpstoqnan(op1); } else { *op1 = *op2; } regs->psw.cc = 3; return 0; } else if (cl1 == FP_INFINITE && cl2 == FP_INFINITE && op1->sign != op2->sign) { r = ieee_exception(FE_INVALID, regs); if (r) { return r; } sbfpdnan(op1); regs->psw.cc = 3; return 0; } else if (cl1 == FP_INFINITE) { /* result is first operand */ } else if (cl2 == FP_INFINITE) { *op1 = *op2; cl1 = cl2; } else if (cl1 == FP_ZERO) { *op1 = *op2; cl1 = cl2; } else if (cl2 == FP_ZERO) { /* result is first operand */ } else { FECLEAREXCEPT(FE_ALL_EXCEPT); sbfpston(op1); sbfpston(op2); op1->v += op2->v; sbfpntos(op1); raised = fetestexcept(FE_ALL_EXCEPT); if (raised) { r = ieee_exception(raised, regs); if (r) { return r; } } cl1 = sbfpclassify(op1); } regs->psw.cc = cl1 == FP_ZERO ? 0 : op1->sign ? 1 : 2; return 0; } /* * B30A AEBR - ADD (short BFP) [RRE] */ DEF_INST(add_bfp_short_reg) { int r1, r2; struct sbfp op1, op2; int pgm_check; RRE(inst, regs, r1, r2); //logmsg("AEBR r1=%d r2=%d\n", r1, r2); BFPINST_CHECK(regs); get_sbfp(&op1, regs->fpr + FPR2I(r1)); get_sbfp(&op2, regs->fpr + FPR2I(r2)); pgm_check = add_sbfp(&op1, &op2, regs); put_sbfp(&op1, regs->fpr + FPR2I(r1)); if (pgm_check) { regs->program_interrupt(regs, pgm_check); } } /* * ED0A AEB - ADD (short BFP) [RXE] */ DEF_INST(add_bfp_short) { int r1, b2; VADR effective_addr2; struct sbfp op1, op2; int pgm_check; RXE(inst, regs, r1, b2, effective_addr2); //logmsg("AEB r1=%d b2=%d\n", r1, b2); BFPINST_CHECK(regs); get_sbfp(&op1, regs->fpr + FPR2I(r1)); vfetch_sbfp(&op2, effective_addr2, b2, regs); pgm_check = add_sbfp(&op1, &op2, regs); put_sbfp(&op1, regs->fpr + FPR2I(r1)); if (pgm_check) { regs->program_interrupt(regs, pgm_check); } } /* * COMPARE (extended) */ static int compare_ebfp(struct ebfp *op1, struct ebfp *op2, int sig, REGS *regs) { int r, cl1, cl2; if (ebfpissnan(op1) || ebfpissnan(op2)) { r = ieee_exception(FE_INVALID, regs); if (r) { return r; } } cl1 = ebfpclassify(op1); cl2 = ebfpclassify(op2); if (cl1 == FP_NAN || cl2 == FP_NAN) { if (sig && !ebfpissnan(op1) && !ebfpissnan(op2)) { r = ieee_exception(FE_INVALID, regs); if (r) { return r; } } regs->psw.cc = 3; } else if (cl1 == FP_INFINITE) { if (cl2 == FP_INFINITE && op1->sign == op2->sign) { regs->psw.cc = 0; } else { regs->psw.cc = op1->sign ? 1 : 2; } } else if (cl2 == FP_INFINITE) { regs->psw.cc = op2->sign ? 2 : 1; } else if (cl1 == FP_ZERO) { if (cl2 == FP_ZERO) { regs->psw.cc = 0; } else { regs->psw.cc = op2->sign ? 2 : 1; } } else if (cl2 == FP_ZERO) { regs->psw.cc = op1->sign ? 1 : 2; } else if (op1->sign != op2->sign) { regs->psw.cc = op1->sign ? 1 : 2; } else { ebfpston(op1); ebfpston(op2); if (op1->v == op2->v) { regs->psw.cc = 0; } else { regs->psw.cc = op1->v > op2->v ? 2 : 1; } } return 0; } /* * B349 CXBR - COMPARE (extended BFP) [RRE] */ DEF_INST(compare_bfp_ext_reg) { int r1, r2; struct ebfp op1, op2; int pgm_check; RRE(inst, regs, r1, r2); //logmsg("CXBR r1=%d r2=%d\n", r1, r2); BFPINST_CHECK(regs); BFPREGPAIR2_CHECK(r1, r2, regs); get_ebfp(&op1, regs->fpr + FPR2I(r1)); get_ebfp(&op2, regs->fpr + FPR2I(r2)); pgm_check = compare_ebfp(&op1, &op2, 0, regs); if (pgm_check) { regs->program_interrupt(regs, pgm_check); } } /* * COMPARE (long) */ static int compare_lbfp(struct lbfp *op1, struct lbfp *op2, int sig, REGS *regs) { int r, cl1, cl2; if (lbfpissnan(op1) || lbfpissnan(op2)) { r = ieee_exception(FE_INVALID, regs); if (r) { return r; } } cl1 = lbfpclassify(op1); cl2 = lbfpclassify(op2); if (cl1 == FP_NAN || cl2 == FP_NAN) { if (sig && !lbfpissnan(op1) && !lbfpissnan(op2)) { r = ieee_exception(FE_INVALID, regs); if (r) { return r; } } regs->psw.cc = 3; } else if (cl1 == FP_INFINITE) { if (cl2 == FP_INFINITE && op1->sign == op2->sign) { regs->psw.cc = 0; } else { regs->psw.cc = op1->sign ? 1 : 2; } } else if (cl2 == FP_INFINITE) { regs->psw.cc = op2->sign ? 2 : 1; } else if (cl1 == FP_ZERO) { if (cl2 == FP_ZERO) { regs->psw.cc = 0; } else { regs->psw.cc = op2->sign ? 2 : 1; } } else if (cl2 == FP_ZERO) { regs->psw.cc = op1->sign ? 1 : 2; } else if (op1->sign != op2->sign) { regs->psw.cc = op1->sign ? 1 : 2; } else { lbfpston(op1); lbfpston(op2); if (op1->v == op2->v) { regs->psw.cc = 0; } else { regs->psw.cc = op1->v > op2->v ? 2 : 1; } } return 0; } /* * B319 CDBR - COMPARE (long BFP) [RRE] */ DEF_INST(compare_bfp_long_reg) { int r1, r2; struct lbfp op1, op2; int pgm_check; RRE(inst, regs, r1, r2); //logmsg("CDBR r1=%d r2=%d\n", r1, r2); BFPINST_CHECK(regs); get_lbfp(&op1, regs->fpr + FPR2I(r1)); get_lbfp(&op2, regs->fpr + FPR2I(r2)); pgm_check = compare_lbfp(&op1, &op2, 0, regs); if (pgm_check) { regs->program_interrupt(regs, pgm_check); } } /* * ED19 CDB - COMPARE (long BFP) [RXE] */ DEF_INST(compare_bfp_long) { int r1, b2; VADR effective_addr2; struct lbfp op1, op2; int pgm_check; RXE(inst, regs, r1, b2, effective_addr2); //logmsg("CDB r1=%d b2=%d\n", r1, b2); BFPINST_CHECK(regs); get_lbfp(&op1, regs->fpr + FPR2I(r1)); vfetch_lbfp(&op2, effective_addr2, b2, regs); pgm_check = compare_lbfp(&op1, &op2, 0, regs); if (pgm_check) { regs->program_interrupt(regs, pgm_check); } } /* * COMPARE (short) */ static int compare_sbfp(struct sbfp *op1, struct sbfp *op2, int sig, REGS *regs) { int r, cl1, cl2; if (sbfpissnan(op1) || sbfpissnan(op2)) { r = ieee_exception(FE_INVALID, regs); if (r) { return r; } } cl1 = sbfpclassify(op1); cl2 = sbfpclassify(op2); if (cl1 == FP_NAN || cl2 == FP_NAN) { if (sig && !sbfpissnan(op1) && !sbfpissnan(op2)) { r = ieee_exception(FE_INVALID, regs); if (r) { return r; } } regs->psw.cc = 3; } else if (cl1 == FP_INFINITE) { if (cl2 == FP_INFINITE && op1->sign == op2->sign) { regs->psw.cc = 0; } else { regs->psw.cc = op1->sign ? 1 : 2; } } else if (cl2 == FP_INFINITE) { regs->psw.cc = op2->sign ? 2 : 1; } else if (cl1 == FP_ZERO) { if (cl2 == FP_ZERO) { regs->psw.cc = 0; } else { regs->psw.cc = op2->sign ? 2 : 1; } } else if (cl2 == FP_ZERO) { regs->psw.cc = op1->sign ? 1 : 2; } else if (op1->sign != op2->sign) { regs->psw.cc = op1->sign ? 1 : 2; } else { sbfpston(op1); sbfpston(op2); if (op1->v == op2->v) { regs->psw.cc = 0; } else { regs->psw.cc = op1->v > op2->v ? 2 : 1; } } return 0; } /* * B309 CEBR - COMPARE (short BFP) [RRE] */ DEF_INST(compare_bfp_short_reg) { int r1, r2; struct sbfp op1, op2; int pgm_check; RRE(inst, regs, r1, r2); //logmsg("CEBR r1=%d r2=%d\n", r1, r2); BFPINST_CHECK(regs); get_sbfp(&op1, regs->fpr + FPR2I(r1)); get_sbfp(&op2, regs->fpr + FPR2I(r2)); pgm_check = compare_sbfp(&op1, &op2, 0, regs); if (pgm_check) { regs->program_interrupt(regs, pgm_check); } } /* * ED09 CEB - COMPARE (short BFP) [RXE] */ DEF_INST(compare_bfp_short) { int r1, b2; VADR effective_addr2; struct sbfp op1, op2; int pgm_check; RXE(inst, regs, r1, b2, effective_addr2); //logmsg("CEB r1=%d b2=%d\n", r1, b2); BFPINST_CHECK(regs); get_sbfp(&op1, regs->fpr + FPR2I(r1)); vfetch_sbfp(&op2, effective_addr2, b2, regs); pgm_check = compare_sbfp(&op1, &op2, 0, regs); if (pgm_check) { regs->program_interrupt(regs, pgm_check); } } /* * B348 KXBR - COMPARE AND SIGNAL (extended BFP) [RRE] */ DEF_INST(compare_and_signal_bfp_ext_reg) { int r1, r2; struct ebfp op1, op2; int pgm_check; RRE(inst, regs, r1, r2); //logmsg("KXBR r1=%d r2=%d\n", r1, r2); BFPINST_CHECK(regs); BFPREGPAIR2_CHECK(r1, r2, regs); get_ebfp(&op1, regs->fpr + FPR2I(r1)); get_ebfp(&op2, regs->fpr + FPR2I(r2)); pgm_check = compare_ebfp(&op1, &op2, 1, regs); if (pgm_check) { regs->program_interrupt(regs, pgm_check); } } /* * B318 KDBR - COMPARE AND SIGNAL (long BFP) [RRE] */ DEF_INST(compare_and_signal_bfp_long_reg) { int r1, r2; struct lbfp op1, op2; int pgm_check; RRE(inst, regs, r1, r2); //logmsg("KDBR r1=%d r2=%d\n", r1, r2); BFPINST_CHECK(regs); get_lbfp(&op1, regs->fpr + FPR2I(r1)); get_lbfp(&op2, regs->fpr + FPR2I(r2)); pgm_check = compare_lbfp(&op1, &op2, 1, regs); if (pgm_check) { regs->program_interrupt(regs, pgm_check); } } /* * ED18 KDB - COMPARE AND SIGNAL (long BFP) [RXE] */ DEF_INST(compare_and_signal_bfp_long) { int r1, b2; VADR effective_addr2; struct lbfp op1, op2; int pgm_check; RXE(inst, regs, r1, b2, effective_addr2); //logmsg("KDB r1=%d b2=%d\n", r1, b2); BFPINST_CHECK(regs); get_lbfp(&op1, regs->fpr + FPR2I(r1)); vfetch_lbfp(&op2, effective_addr2, b2, regs); pgm_check = compare_lbfp(&op1, &op2, 1, regs); if (pgm_check) { regs->program_interrupt(regs, pgm_check); } } /* * B308 KEBR - COMPARE AND SIGNAL (short BFP) [RRE] */ DEF_INST(compare_and_signal_bfp_short_reg) { int r1, r2; struct sbfp op1, op2; int pgm_check; RRE(inst, regs, r1, r2); //logmsg("KEBR r1=%d r2=%d\n", r1, r2); BFPINST_CHECK(regs); get_sbfp(&op1, regs->fpr + FPR2I(r1)); get_sbfp(&op2, regs->fpr + FPR2I(r2)); pgm_check = compare_sbfp(&op1, &op2, 1, regs); if (pgm_check) { regs->program_interrupt(regs, pgm_check); } } /* * ED08 KEB - COMPARE AND SIGNAL (short BFP) [RXE] */ DEF_INST(compare_and_signal_bfp_short) { int r1, b2; VADR effective_addr2; struct sbfp op1, op2; int pgm_check; RXE(inst, regs, r1, b2, effective_addr2); //logmsg("KEB r1=%d b2=%d\n", r1, b2); BFPINST_CHECK(regs); get_sbfp(&op1, regs->fpr + FPR2I(r1)); vfetch_sbfp(&op2, effective_addr2, b2, regs); pgm_check = compare_sbfp(&op1, &op2, 1, regs); if (pgm_check) { regs->program_interrupt(regs, pgm_check); } } /* * B396 CXFBR - CONVERT FROM FIXED (32 to extended BFP) [RRE] */ DEF_INST(convert_fix32_to_bfp_ext_reg) { int r1, r2; struct ebfp op1; S32 op2; RRE(inst, regs, r1, r2); //logmsg("CXFBR r1=%d r2=%d\n", r1, r2); BFPINST_CHECK(regs); BFPREGPAIR_CHECK(r1, regs); op2 = regs->GR_L(r2); if (op2) { op1.v = (long double)op2; ebfpntos(&op1); } else { ebfpzero(&op1, 0); } put_ebfp(&op1, regs->fpr + FPR2I(r1)); } /* end DEF_INST(convert_fix32_to_bfp_ext_reg) */ /* * B395 CDFBR - CONVERT FROM FIXED (32 to long BFP) [RRE] */ DEF_INST(convert_fix32_to_bfp_long_reg) { int r1, r2; struct lbfp op1; S32 op2; RRE(inst, regs, r1, r2); //logmsg("CDFBR r1=%d r2=%d\n", r1, r2); BFPINST_CHECK(regs); op2 = regs->GR_L(r2); if (op2) { op1.v = (double)op2; lbfpntos(&op1); } else { lbfpzero(&op1, 0); } put_lbfp(&op1, regs->fpr + FPR2I(r1)); } /* * B394 CEFBR - CONVERT FROM FIXED (32 to short BFP) [RRE] */ DEF_INST(convert_fix32_to_bfp_short_reg) { int r1, r2; struct sbfp op1; S32 op2; RRE(inst, regs, r1, r2); //logmsg("CEFBR r1=%d r2=%d\n", r1, r2); BFPINST_CHECK(regs); op2 = regs->GR_L(r2); if (op2) { op1.v = (float)op2; sbfpntos(&op1); } else { sbfpzero(&op1, 0); } put_sbfp(&op1, regs->fpr + FPR2I(r1)); } #if defined(FEATURE_ESAME) /* * B3A6 CXGBR - CONVERT FROM FIXED (64 to extended BFP) [RRE] */ DEF_INST(convert_fix64_to_bfp_ext_reg) { int r1, r2; struct ebfp op1; S64 op2; RRE(inst, regs, r1, r2); //logmsg("CXGBR r1=%d r2=%d\n", r1, r2); BFPINST_CHECK(regs); BFPREGPAIR_CHECK(r1, regs); op2 = regs->GR_G(r2); if (op2) { op1.v = (long double)op2; ebfpntos(&op1); } else { ebfpzero(&op1, 0); } put_ebfp(&op1, regs->fpr + FPR2I(r1)); } /* end DEF_INST(convert_fix64_to_bfp_ext_reg) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /* * B3A5 CDGBR - CONVERT FROM FIXED (64 to long BFP) [RRE] */ DEF_INST(convert_fix64_to_bfp_long_reg) { int r1, r2; struct lbfp op1; S64 op2; RRE(inst, regs, r1, r2); //logmsg("CDGBR r1=%d r2=%d\n", r1, r2); BFPINST_CHECK(regs); op2 = regs->GR_G(r2); if (op2) { op1.v = (double)op2; lbfpntos(&op1); } else { lbfpzero(&op1, 0); } put_lbfp(&op1, regs->fpr + FPR2I(r1)); } #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /* * B3A4 CEGBR - CONVERT FROM FIXED (64 to short BFP) [RRE] */ DEF_INST(convert_fix64_to_bfp_short_reg) { int r1, r2; struct sbfp op1; S64 op2; RRE(inst, regs, r1, r2); //logmsg("CEGBR r1=%d r2=%d\n", r1, r2); BFPINST_CHECK(regs); op2 = regs->GR_G(r2); if (op2) { op1.v = (float)op2; sbfpntos(&op1); } else { sbfpzero(&op1, 0); } put_sbfp(&op1, regs->fpr + FPR2I(r1)); } #endif /*defined(FEATURE_ESAME)*/ /* * B39A CFXBR - CONVERT TO FIXED (extended BFP to 32) [RRF] */ DEF_INST(convert_bfp_ext_to_fix32_reg) { int r1, r2, m3, raised; S32 op1; struct ebfp op2; int pgm_check; RRF_M(inst, regs, r1, r2, m3); //logmsg("CFXBR r1=%d r2=%d\n", r1, r2); BFPINST_CHECK(regs); BFPREGPAIR_CHECK(r2, regs); BFPRM_CHECK(m3,regs); get_ebfp(&op2, regs->fpr + FPR2I(r2)); switch (ebfpclassify(&op2)) { case FP_NAN: pgm_check = ieee_exception(FE_INVALID, regs); regs->psw.cc = 3; regs->GR_L(r1) = 0x80000000; if (regs->fpc & FPC_MASK_IMX) { pgm_check = ieee_exception(FE_INEXACT, regs); if (pgm_check) { ebfpston(&op2);logmsg("INEXACT\n"); regs->program_interrupt(regs, pgm_check); } } break; case FP_ZERO: regs->psw.cc = 0; regs->GR_L(r1) = 0; break; case FP_INFINITE: pgm_check = ieee_exception(FE_INVALID, regs); regs->psw.cc = 3; if (op2.sign) { regs->GR_L(r1) = 0x80000000; } else { regs->GR_L(r1) = 0x7FFFFFFF; } if (regs->fpc & FPC_MASK_IMX) { pgm_check = ieee_exception(FE_INEXACT, regs); if (pgm_check) { regs->program_interrupt(regs, pgm_check); } } break; default: FECLEAREXCEPT(FE_ALL_EXCEPT); ebfpston(&op2); op1 = (S32)op2.v; raised = fetestexcept(FE_ALL_EXCEPT); if (raised) { pgm_check = ieee_exception(raised, regs); if (pgm_check) { regs->program_interrupt(regs, pgm_check); } } regs->GR_L(r1) = op1; regs->psw.cc = op1 > 0 ? 2 : 1; } } /* end DEF_INST(convert_bfp_ext_to_fix32_reg) */ /* * B399 CFDBR - CONVERT TO FIXED (long BFP to 32) [RRF] */ DEF_INST(convert_bfp_long_to_fix32_reg) { int r1, r2, m3, raised; S32 op1; struct lbfp op2; int pgm_check; RRF_M(inst, regs, r1, r2, m3); //logmsg("CFDBR r1=%d r2=%d\n", r1, r2); BFPINST_CHECK(regs); BFPRM_CHECK(m3,regs); get_lbfp(&op2, regs->fpr + FPR2I(r2)); switch (lbfpclassify(&op2)) { case FP_NAN: pgm_check = ieee_exception(FE_INVALID, regs); regs->psw.cc = 3; regs->GR_L(r1) = 0x80000000; if (regs->fpc & FPC_MASK_IMX) { pgm_check = ieee_exception(FE_INEXACT, regs); if (pgm_check) { lbfpston(&op2);logmsg("INEXACT\n"); regs->program_interrupt(regs, pgm_check); } } break; case FP_ZERO: regs->psw.cc = 0; regs->GR_L(r1) = 0; break; case FP_INFINITE: pgm_check = ieee_exception(FE_INVALID, regs); regs->psw.cc = 3; if (op2.sign) { regs->GR_L(r1) = 0x80000000; } else { regs->GR_L(r1) = 0x7FFFFFFF; } if (regs->fpc & FPC_MASK_IMX) { pgm_check = ieee_exception(FE_INEXACT, regs); if (pgm_check) { regs->program_interrupt(regs, pgm_check); } } break; default: FECLEAREXCEPT(FE_ALL_EXCEPT); lbfpston(&op2); op1 = (S32)op2.v; raised = fetestexcept(FE_ALL_EXCEPT); if (raised) { pgm_check = ieee_exception(raised, regs); if (pgm_check) { regs->program_interrupt(regs, pgm_check); } } regs->GR_L(r1) = op1; regs->psw.cc = op1 > 0 ? 2 : 1; } } /* * B398 CFEBR - CONVERT TO FIXED (short BFP to 32) [RRF] */ DEF_INST(convert_bfp_short_to_fix32_reg) { int r1, r2, m3, raised; S32 op1; struct sbfp op2; int pgm_check; RRF_M(inst, regs, r1, r2, m3); //logmsg("CFEBR r1=%d r2=%d\n", r1, r2); BFPINST_CHECK(regs); BFPRM_CHECK(m3,regs); get_sbfp(&op2, regs->fpr + FPR2I(r2)); switch (sbfpclassify(&op2)) { case FP_NAN: pgm_check = ieee_exception(FE_INVALID, regs); regs->psw.cc = 3; regs->GR_L(r1) = 0x80000000; if (regs->fpc & FPC_MASK_IMX) { pgm_check = ieee_exception(FE_INEXACT, regs); if (pgm_check) { regs->program_interrupt(regs, pgm_check); } } break; case FP_ZERO: regs->psw.cc = 0; regs->GR_L(r1) = 0; break; case FP_INFINITE: pgm_check = ieee_exception(FE_INVALID, regs); regs->psw.cc = 3; if (op2.sign) { regs->GR_L(r1) = 0x80000000; } else { regs->GR_L(r1) = 0x7FFFFFFF; } if (regs->fpc & FPC_MASK_IMX) { pgm_check = ieee_exception(FE_INEXACT, regs); if (pgm_check) { regs->program_interrupt(regs, pgm_check); } } break; default: FECLEAREXCEPT(FE_ALL_EXCEPT); sbfpston(&op2); op1 = (S32)op2.v; raised = fetestexcept(FE_ALL_EXCEPT); if (raised) { pgm_check = ieee_exception(raised, regs); if (pgm_check) { regs->program_interrupt(regs, pgm_check); } } regs->GR_L(r1) = op1; regs->psw.cc = op1 > 0 ? 2 : 1; } } #if defined(FEATURE_ESAME) /* * B3AA CGXBR - CONVERT TO FIXED (extended BFP to 64) [RRF] */ DEF_INST(convert_bfp_ext_to_fix64_reg) { int r1, r2, m3, raised; S64 op1; struct ebfp op2; int pgm_check; RRF_M(inst, regs, r1, r2, m3); //logmsg("CGXBR r1=%d r2=%d\n", r1, r2); BFPINST_CHECK(regs); BFPREGPAIR_CHECK(r2, regs); BFPRM_CHECK(m3,regs); get_ebfp(&op2, regs->fpr + FPR2I(r2)); switch (ebfpclassify(&op2)) { case FP_NAN: pgm_check = ieee_exception(FE_INVALID, regs); regs->psw.cc = 3; regs->GR_G(r1) = 0x8000000000000000ULL; if (regs->fpc & FPC_MASK_IMX) { pgm_check = ieee_exception(FE_INEXACT, regs); if (pgm_check) { ebfpston(&op2);logmsg("INEXACT\n"); regs->program_interrupt(regs, pgm_check); } } break; case FP_ZERO: regs->psw.cc = 0; regs->GR_G(r1) = 0; break; case FP_INFINITE: pgm_check = ieee_exception(FE_INVALID, regs); regs->psw.cc = 3; if (op2.sign) { regs->GR_G(r1) = 0x8000000000000000ULL; } else { regs->GR_G(r1) = 0x7FFFFFFFFFFFFFFFULL; } if (regs->fpc & FPC_MASK_IMX) { pgm_check = ieee_exception(FE_INEXACT, regs); if (pgm_check) { regs->program_interrupt(regs, pgm_check); } } break; default: FECLEAREXCEPT(FE_ALL_EXCEPT); ebfpston(&op2); op1 = (S64)op2.v; raised = fetestexcept(FE_ALL_EXCEPT); if (raised) { pgm_check = ieee_exception(raised, regs); if (pgm_check) { regs->program_interrupt(regs, pgm_check); } } regs->GR_G(r1) = op1; regs->psw.cc = op1 > 0 ? 2 : 1; } } /* end DEF_INST(convert_bfp_ext_to_fix64_reg) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /* * B3A9 CGDBR - CONVERT TO FIXED (long BFP to 64) [RRF] */ DEF_INST(convert_bfp_long_to_fix64_reg) { int r1, r2, m3, raised; S64 op1; struct lbfp op2; int pgm_check; RRF_M(inst, regs, r1, r2, m3); //logmsg("CGDBR r1=%d r2=%d\n", r1, r2); BFPINST_CHECK(regs); BFPRM_CHECK(m3,regs); get_lbfp(&op2, regs->fpr + FPR2I(r2)); switch (lbfpclassify(&op2)) { case FP_NAN: pgm_check = ieee_exception(FE_INVALID, regs); regs->psw.cc = 3; regs->GR_G(r1) = 0x8000000000000000ULL; if (regs->fpc & FPC_MASK_IMX) { pgm_check = ieee_exception(FE_INEXACT, regs); if (pgm_check) { lbfpston(&op2);logmsg("INEXACT\n"); regs->program_interrupt(regs, pgm_check); } } break; case FP_ZERO: regs->psw.cc = 0; regs->GR_G(r1) = 0; break; case FP_INFINITE: pgm_check = ieee_exception(FE_INVALID, regs); regs->psw.cc = 3; if (op2.sign) { regs->GR_G(r1) = 0x8000000000000000ULL; } else { regs->GR_G(r1) = 0x7FFFFFFFFFFFFFFFULL; } if (regs->fpc & FPC_MASK_IMX) { pgm_check = ieee_exception(FE_INEXACT, regs); if (pgm_check) { regs->program_interrupt(regs, pgm_check); } } break; default: FECLEAREXCEPT(FE_ALL_EXCEPT); lbfpston(&op2); op1 = (S64)op2.v; raised = fetestexcept(FE_ALL_EXCEPT); if (raised) { pgm_check = ieee_exception(raised, regs); if (pgm_check) { regs->program_interrupt(regs, pgm_check); } } regs->GR_G(r1) = op1; regs->psw.cc = op1 > 0 ? 2 : 1; } } #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) /* * B3A8 CGEBR - CONVERT TO FIXED (short BFP to 64) [RRF] */ DEF_INST(convert_bfp_short_to_fix64_reg) { int r1, r2, m3, raised; S64 op1; struct sbfp op2; int pgm_check; RRF_M(inst, regs, r1, r2, m3); //logmsg("CGEBR r1=%d r2=%d\n", r1, r2); BFPINST_CHECK(regs); BFPRM_CHECK(m3,regs); get_sbfp(&op2, regs->fpr + FPR2I(r2)); switch (sbfpclassify(&op2)) { case FP_NAN: pgm_check = ieee_exception(FE_INVALID, regs); regs->psw.cc = 3; regs->GR_G(r1) = 0x8000000000000000ULL; if (regs->fpc & FPC_MASK_IMX) { pgm_check = ieee_exception(FE_INEXACT, regs); if (pgm_check) { regs->program_interrupt(regs, pgm_check); } } break; case FP_ZERO: regs->psw.cc = 0; regs->GR_G(r1) = 0; break; case FP_INFINITE: pgm_check = ieee_exception(FE_INVALID, regs); regs->psw.cc = 3; if (op2.sign) { regs->GR_G(r1) = 0x8000000000000000ULL; } else { regs->GR_G(r1) = 0x7FFFFFFFFFFFFFFFULL; } if (regs->fpc & FPC_MASK_IMX) { pgm_check = ieee_exception(FE_INEXACT, regs); if (pgm_check) { regs->program_interrupt(regs, pgm_check); } } break; default: FECLEAREXCEPT(FE_ALL_EXCEPT); sbfpston(&op2); op1 = (S64)op2.v; raised = fetestexcept(FE_ALL_EXCEPT); if (raised) { pgm_check = ieee_exception(raised, regs); if (pgm_check) { regs->program_interrupt(regs, pgm_check); } } regs->GR_G(r1) = op1; regs->psw.cc = op1 > 0 ? 2 : 1; } } #endif /*defined(FEATURE_ESAME)*/ /* * FP INTEGER (extended) */ static int integer_ebfp(struct ebfp *op, int mode, REGS *regs) { int r, raised; UNREFERENCED(mode); switch(ebfpclassify(op)) { case FP_NAN: if (ebfpissnan(op)) { if (regs->fpc & FPC_MASK_IMI) { ebfpstoqnan(op); ieee_exception(FE_INEXACT, regs); } else { ieee_exception(FE_INVALID, regs); } } break; case FP_ZERO: case FP_INFINITE: break; default: FECLEAREXCEPT(FE_ALL_EXCEPT); ebfpston(op); set_rounding_mode(regs->fpc, mode); op->v = rint(op->v); if (regs->fpc & FPC_MASK_IMX) { ieee_exception(FE_INEXACT, regs); } else { ieee_exception(FE_INVALID, regs); } ebfpntos(op); raised = fetestexcept(FE_ALL_EXCEPT); if (raised) { r = ieee_exception(raised, regs); if (r) { return r; } } } /* end switch */ return 0; } /* end function integer_ebfp */ /* * FP INTEGER (long) */ static int integer_lbfp(struct lbfp *op, int mode, REGS *regs) { int r, raised; UNREFERENCED(mode); switch(lbfpclassify(op)) { case FP_NAN: if (lbfpissnan(op)) { if (regs->fpc & FPC_MASK_IMI) { lbfpstoqnan(op); ieee_exception(FE_INEXACT, regs); } else { ieee_exception(FE_INVALID, regs); } } break; case FP_ZERO: case FP_INFINITE: break; default: FECLEAREXCEPT(FE_ALL_EXCEPT); lbfpston(op); set_rounding_mode(regs->fpc, mode); op->v = rint(op->v); if (regs->fpc & FPC_MASK_IMX) { ieee_exception(FE_INEXACT, regs); } else { ieee_exception(FE_INVALID, regs); } lbfpntos(op); raised = fetestexcept(FE_ALL_EXCEPT); if (raised) { r = ieee_exception(raised, regs); if (r) { return r; } } } /* end switch */ return 0; } /* end function integer_lbfp */ /* * FP INTEGER (short) */ static int integer_sbfp(struct sbfp *op, int mode, REGS *regs) { int r, raised; UNREFERENCED(mode); switch(sbfpclassify(op)) { case FP_NAN: if (sbfpissnan(op)) { if (regs->fpc & FPC_MASK_IMI) { sbfpstoqnan(op); ieee_exception(FE_INEXACT, regs); } else { ieee_exception(FE_INVALID, regs); } } break; case FP_ZERO: case FP_INFINITE: break; default: FECLEAREXCEPT(FE_ALL_EXCEPT); sbfpston(op); set_rounding_mode(regs->fpc, mode); op->v = rint(op->v); if (regs->fpc & FPC_MASK_IMX) { ieee_exception(FE_INEXACT, regs); } else { ieee_exception(FE_INVALID, regs); } sbfpntos(op); raised = fetestexcept(FE_ALL_EXCEPT); if (raised) { r = ieee_exception(raised, regs); if (r) { return r; } } } /* end switch */ return 0; } /* end function integer_sbfp */ /* * DIVIDE (extended) */ static int divide_ebfp(struct ebfp *op1, struct ebfp *op2, REGS *regs) { int r, cl1, cl2, raised; if (ebfpissnan(op1) || ebfpissnan(op2)) { r = ieee_exception(FE_INVALID, regs); if (r) { return r; } } cl1 = ebfpclassify(op1); cl2 = ebfpclassify(op2); if (cl1 == FP_NAN) { if (ebfpissnan(op1)) { ebfpstoqnan(op1); } else if (ebfpissnan(op2)) { *op1 = *op2; ebfpstoqnan(op1); } } else if (cl2 == FP_NAN) { if (ebfpissnan(op2)) { *op1 = *op2; ebfpstoqnan(op1); } else { *op1 = *op2; } } else if (cl1 == FP_INFINITE && cl2 == FP_INFINITE) { r = ieee_exception(FE_INVALID, regs); if (r) { return r; } ebfpdnan(op1); } else if (cl1 == FP_INFINITE) { if (op2->sign) { op1->sign = !(op1->sign); } } else if (cl2 == FP_INFINITE) { ebfpzero(op1, op2->sign ? !(op1->sign) : op1->sign); } else if (cl1 == FP_ZERO) { if (cl2 == FP_ZERO) { r = ieee_exception(FE_INVALID, regs); if (r) { return r; } ebfpdnan(op1); } else { ebfpzero(op1, op2->sign ? !(op1->sign) : op1->sign); } } else if (cl2 == FP_ZERO) { r = ieee_exception(FE_DIVBYZERO, regs); if (r) { return r; } ebfpinfinity(op1, op2->sign ? !(op1->sign) : op1->sign); } else { FECLEAREXCEPT(FE_ALL_EXCEPT); ebfpston(op1); ebfpston(op2); op1->v /= op2->v; ebfpntos(op1); raised = fetestexcept(FE_ALL_EXCEPT); if (raised) { r = ieee_exception(raised, regs); if (r) { return r; } } } return 0; } /* * B34D DXBR - DIVIDE (extended BFP) [RRE] */ DEF_INST(divide_bfp_ext_reg) { int r1, r2; struct ebfp op1, op2; int pgm_check; RRE(inst, regs, r1, r2); //logmsg("DXBR r1=%d r2=%d\n", r1, r2); BFPINST_CHECK(regs); BFPREGPAIR2_CHECK(r1, r2, regs); get_ebfp(&op1, regs->fpr + FPR2I(r1)); get_ebfp(&op2, regs->fpr + FPR2I(r2)); pgm_check = divide_ebfp(&op1, &op2, regs); put_ebfp(&op1, regs->fpr + FPR2I(r1)); if (pgm_check) { regs->program_interrupt(regs, pgm_check); } } /* * DIVIDE (long) */ static int divide_lbfp(struct lbfp *op1, struct lbfp *op2, REGS *regs) { int r, cl1, cl2, raised; if (lbfpissnan(op1) || lbfpissnan(op2)) { r = ieee_exception(FE_INVALID, regs); if (r) { return r; } } cl1 = lbfpclassify(op1); cl2 = lbfpclassify(op2); if (cl1 == FP_NAN) { if (lbfpissnan(op1)) { lbfpstoqnan(op1); } else if (lbfpissnan(op2)) { *op1 = *op2; lbfpstoqnan(op1); } } else if (cl2 == FP_NAN) { if (lbfpissnan(op2)) { *op1 = *op2; lbfpstoqnan(op1); } else { *op1 = *op2; } } else if (cl1 == FP_INFINITE && cl2 == FP_INFINITE) { r = ieee_exception(FE_INVALID, regs); if (r) { return r; } lbfpdnan(op1); } else if (cl1 == FP_INFINITE) { if (op2->sign) { op1->sign = !(op1->sign); } } else if (cl2 == FP_INFINITE) { lbfpzero(op1, op2->sign ? !(op1->sign) : op1->sign); } else if (cl1 == FP_ZERO) { if (cl2 == FP_ZERO) { r = ieee_exception(FE_INVALID, regs); if (r) { return r; } lbfpdnan(op1); } else { lbfpzero(op1, op2->sign ? !(op1->sign) : op1->sign); } } else if (cl2 == FP_ZERO) { r = ieee_exception(FE_DIVBYZERO, regs); if (r) { return r; } lbfpinfinity(op1, op2->sign ? !(op1->sign) : op1->sign); } else { FECLEAREXCEPT(FE_ALL_EXCEPT); lbfpston(op1); lbfpston(op2); op1->v /= op2->v; lbfpntos(op1); raised = fetestexcept(FE_ALL_EXCEPT); if (raised) { r = ieee_exception(raised, regs); if (r) { return r; } } } return 0; } /* * B31D DDBR - DIVIDE (long BFP) [RRE] */ DEF_INST(divide_bfp_long_reg) { int r1, r2; struct lbfp op1, op2; int pgm_check; RRE(inst, regs, r1, r2); //logmsg("DDBR r1=%d r2=%d\n", r1, r2); BFPINST_CHECK(regs); get_lbfp(&op1, regs->fpr + FPR2I(r1)); get_lbfp(&op2, regs->fpr + FPR2I(r2)); pgm_check = divide_lbfp(&op1, &op2, regs); put_lbfp(&op1, regs->fpr + FPR2I(r1)); if (pgm_check) { regs->program_interrupt(regs, pgm_check); } } /* * ED1D DDB - DIVIDE (long BFP) [RXE] */ DEF_INST(divide_bfp_long) { int r1, b2; VADR effective_addr2; struct lbfp op1, op2; int pgm_check; RXE(inst, regs, r1, b2, effective_addr2); //logmsg("DDB r1=%d b2=%d\n", r1, b2); BFPINST_CHECK(regs); get_lbfp(&op1, regs->fpr + FPR2I(r1)); vfetch_lbfp(&op2, effective_addr2, b2, regs); pgm_check = divide_lbfp(&op1, &op2, regs); put_lbfp(&op1, regs->fpr + FPR2I(r1)); if (pgm_check) { regs->program_interrupt(regs, pgm_check); } } /* * DIVIDE (short) */ static int divide_sbfp(struct sbfp *op1, struct sbfp *op2, REGS *regs) { int r, cl1, cl2, raised; if (sbfpissnan(op1) || sbfpissnan(op2)) { r = ieee_exception(FE_INVALID, regs); if (r) { return r; } } cl1 = sbfpclassify(op1); cl2 = sbfpclassify(op2); if (cl1 == FP_NAN) { if (sbfpissnan(op1)) { sbfpstoqnan(op1); } else if (sbfpissnan(op2)) { *op1 = *op2; sbfpstoqnan(op1); } } else if (cl2 == FP_NAN) { if (sbfpissnan(op2)) { *op1 = *op2; sbfpstoqnan(op1); } else { *op1 = *op2; } } else if (cl1 == FP_INFINITE && cl2 == FP_INFINITE) { r = ieee_exception(FE_INVALID, regs); if (r) { return r; } sbfpdnan(op1); } else if (cl1 == FP_INFINITE) { if (op2->sign) { op1->sign = !(op1->sign); } } else if (cl2 == FP_INFINITE) { sbfpzero(op1, op2->sign ? !(op1->sign) : op1->sign); } else if (cl1 == FP_ZERO) { if (cl2 == FP_ZERO) { r = ieee_exception(FE_INVALID, regs); if (r) { return r; } sbfpdnan(op1); } else { sbfpzero(op1, op2->sign ? !(op1->sign) : op1->sign); } } else if (cl2 == FP_ZERO) { r = ieee_exception(FE_DIVBYZERO, regs); if (r) { return r; } sbfpinfinity(op1, op2->sign ? !(op1->sign) : op1->sign); } else { FECLEAREXCEPT(FE_ALL_EXCEPT); sbfpston(op1); sbfpston(op2); op1->v /= op2->v; sbfpntos(op1); raised = fetestexcept(FE_ALL_EXCEPT); if (raised) { r = ieee_exception(raised, regs); if (r) { return r; } } } return 0; } /* * B30D DEBR - DIVIDE (short BFP) [RRE] */ DEF_INST(divide_bfp_short_reg) { int r1, r2; struct sbfp op1, op2; int pgm_check; RRE(inst, regs, r1, r2); //logmsg("DEBR r1=%d r2=%d\n", r1, r2); BFPINST_CHECK(regs); get_sbfp(&op1, regs->fpr + FPR2I(r1)); get_sbfp(&op2, regs->fpr + FPR2I(r2)); pgm_check = divide_sbfp(&op1, &op2, regs); put_sbfp(&op1, regs->fpr + FPR2I(r1)); if (pgm_check) { regs->program_interrupt(regs, pgm_check); } } /* * ED0D DEB - DIVIDE (short BFP) [RXE] */ DEF_INST(divide_bfp_short) { int r1, b2; VADR effective_addr2; struct sbfp op1, op2; int pgm_check; RXE(inst, regs, r1, b2, effective_addr2); //logmsg("DEB r1=%d b2=%d\n", r1, b2); BFPINST_CHECK(regs); get_sbfp(&op1, regs->fpr + FPR2I(r1)); vfetch_sbfp(&op2, effective_addr2, b2, regs); pgm_check = divide_sbfp(&op1, &op2, regs); put_sbfp(&op1, regs->fpr + FPR2I(r1)); if (pgm_check) { regs->program_interrupt(regs, pgm_check); } } /* * B342 LTXBR - LOAD AND TEST (extended BFP) [RRE] */ DEF_INST(load_and_test_bfp_ext_reg) { int r1, r2; struct ebfp op; int pgm_check = 0; RRE(inst, regs, r1, r2); //logmsg("LTXBR r1=%d r2=%d\n", r1, r2); BFPINST_CHECK(regs); BFPREGPAIR2_CHECK(r1, r2, regs); get_ebfp(&op, regs->fpr + FPR2I(r2)); if (ebfpissnan(&op)) { pgm_check = ieee_exception(FE_INVALID, regs); ebfpstoqnan(&op); } if (pgm_check) { regs->program_interrupt(regs, pgm_check); } switch (ebfpclassify(&op)) { case FP_ZERO: regs->psw.cc = 0; break; case FP_NAN: regs->psw.cc = 3; break; default: regs->psw.cc = op.sign ? 1 : 2; break; } put_ebfp(&op, regs->fpr + FPR2I(r1)); } /* * B312 LTDBR - LOAD AND TEST (long BFP) [RRE] */ DEF_INST(load_and_test_bfp_long_reg) { int r1, r2; struct lbfp op; int pgm_check = 0; RRE(inst, regs, r1, r2); //logmsg("LTDBR r1=%d r2=%d\n", r1, r2); BFPINST_CHECK(regs); get_lbfp(&op, regs->fpr + FPR2I(r2)); if (lbfpissnan(&op)) { pgm_check = ieee_exception(FE_INVALID, regs); lbfpstoqnan(&op); } if (pgm_check) { regs->program_interrupt(regs, pgm_check); } switch (lbfpclassify(&op)) { case FP_ZERO: regs->psw.cc = 0; break; case FP_NAN: regs->psw.cc = 3; break; default: regs->psw.cc = op.sign ? 1 : 2; break; } put_lbfp(&op, regs->fpr + FPR2I(r1)); } /* * B302 LTEBR - LOAD AND TEST (short BFP) [RRE] */ DEF_INST(load_and_test_bfp_short_reg) { int r1, r2; struct sbfp op; int pgm_check = 0; RRE(inst, regs, r1, r2); //logmsg("LTEBR r1=%d r2=%d\n", r1, r2); BFPINST_CHECK(regs); get_sbfp(&op, regs->fpr + FPR2I(r2)); if (sbfpissnan(&op)) { pgm_check = ieee_exception(FE_INVALID, regs); sbfpstoqnan(&op); } if (pgm_check) { regs->program_interrupt(regs, pgm_check); } switch (sbfpclassify(&op)) { case FP_ZERO: regs->psw.cc = 0; break; case FP_NAN: regs->psw.cc = 3; break; default: regs->psw.cc = op.sign ? 1 : 2; break; } put_sbfp(&op, regs->fpr + FPR2I(r1)); } /* * B357 FIEBR - LOAD FP INTEGER (short BFP) [RRF] */ DEF_INST(load_fp_int_bfp_short_reg) { int r1, r2, m3, pgm_check; struct sbfp op; RRF_M(inst, regs, r1, r2, m3); //logmsg("FIEBR r1=%d, r2=%d\n", r1, r2); BFPINST_CHECK(regs); BFPRM_CHECK(m3,regs); get_sbfp(&op, regs->fpr + FPR2I(r2)); pgm_check = integer_sbfp(&op, m3, regs); if (pgm_check) { regs->program_interrupt(regs, pgm_check); } put_sbfp(&op, regs->fpr + FPR2I(r1)); } /* end DEF_INST(load_fp_int_bfp_short_reg) */ /* * B35F FIDBR - LOAD FP INTEGER (long BFP) [RRF] */ DEF_INST(load_fp_int_bfp_long_reg) { int r1, r2, m3, pgm_check; struct lbfp op; RRF_M(inst, regs, r1, r2, m3); //logmsg("FIDBR r1=%d, r2=%d\n", r1, r2); BFPINST_CHECK(regs); BFPRM_CHECK(m3,regs); get_lbfp(&op, regs->fpr + FPR2I(r2)); pgm_check = integer_lbfp(&op, m3, regs); if (pgm_check) { regs->program_interrupt(regs, pgm_check); } put_lbfp(&op, regs->fpr + FPR2I(r1)); } /* end DEF_INST(load_fp_int_bfp_long_reg) */ /* * B347 FIXBR - LOAD FP INTEGER (extended BFP) [RRF] */ DEF_INST(load_fp_int_bfp_ext_reg) { int r1, r2, m3, pgm_check; struct ebfp op; RRF_M(inst, regs, r1, r2, m3); //logmsg("FIXBR r1=%d, r2=%d\n", r1, r2); BFPINST_CHECK(regs); BFPREGPAIR2_CHECK(r1, r2, regs); BFPRM_CHECK(m3,regs); get_ebfp(&op, regs->fpr + FPR2I(r2)); pgm_check = integer_ebfp(&op, m3, regs); if (pgm_check) { regs->program_interrupt(regs, pgm_check); } put_ebfp(&op, regs->fpr + FPR2I(r1)); } /* end DEF_INST(load_fp_int_bfp_ext_reg) */ /* * B29D LFPC - LOAD FPC [S] * This instruction is in module esame.c */ /* * B304 LDEBR - LOAD LENGTHENED (short to long BFP) [RRE] */ DEF_INST(load_lengthened_bfp_short_to_long_reg) { int r1, r2; struct lbfp op1; struct sbfp op2; RRE(inst, regs, r1, r2); //logmsg("LDEBR r1=%d r2=%d\n", r1, r2); BFPINST_CHECK(regs); get_sbfp(&op2, regs->fpr + FPR2I(r2)); lengthen_short_to_long(&op2, &op1, regs); put_lbfp(&op1, regs->fpr + FPR2I(r1)); } /* * ED04 LDEB - LOAD LENGTHENED (short to long BFP) [RXE] */ DEF_INST(load_lengthened_bfp_short_to_long) { int r1, b2; VADR effective_addr2; struct lbfp op1; struct sbfp op2; RXE(inst, regs, r1, b2, effective_addr2); //logmsg("LDEB r1=%d b2=%d\n", r1, b2); BFPINST_CHECK(regs); vfetch_sbfp(&op2, effective_addr2, b2, regs); lengthen_short_to_long(&op2, &op1, regs); put_lbfp(&op1, regs->fpr + FPR2I(r1)); } /* * B305 LXDBR - LOAD LENGTHENED (long to extended BFP) [RRE] */ DEF_INST(load_lengthened_bfp_long_to_ext_reg) { int r1, r2; struct ebfp op1; struct lbfp op2; RRE(inst, regs, r1, r2); //logmsg("LXDBR r1=%d r2=%d\n", r1, r2); BFPINST_CHECK(regs); BFPREGPAIR_CHECK(r1, regs); get_lbfp(&op2, regs->fpr + FPR2I(r2)); lengthen_long_to_ext(&op2, &op1, regs); put_ebfp(&op1, regs->fpr + FPR2I(r1)); } /* * ED05 LXDB - LOAD LENGTHENED (long to extended BFP) [RXE] */ DEF_INST(load_lengthened_bfp_long_to_ext) { int r1, b2; VADR effective_addr2; struct ebfp op1; struct lbfp op2; RXE(inst, regs, r1, b2, effective_addr2); //logmsg("LXDB r1=%d b2=%d\n", r1, b2); BFPINST_CHECK(regs); BFPREGPAIR_CHECK(r1, regs); vfetch_lbfp(&op2, effective_addr2, b2, regs); lengthen_long_to_ext(&op2, &op1, regs); put_ebfp(&op1, regs->fpr + FPR2I(r1)); } /* * B306 LXEBR - LOAD LENGTHENED (short to extended BFP) [RRE] */ DEF_INST(load_lengthened_bfp_short_to_ext_reg) { int r1, r2; struct ebfp op1; struct sbfp op2; RRE(inst, regs, r1, r2); //logmsg("LXEBR r1=%d r2=%d\n", r1, r2); BFPINST_CHECK(regs); BFPREGPAIR_CHECK(r1, regs); get_sbfp(&op2, regs->fpr + FPR2I(r2)); lengthen_short_to_ext(&op2, &op1, regs); put_ebfp(&op1, regs->fpr + FPR2I(r1)); } /* * ED06 LXEB - LOAD LENGTHENED (short to extended BFP) [RXE] */ DEF_INST(load_lengthened_bfp_short_to_ext) { int r1, b2; VADR effective_addr2; struct ebfp op1; struct sbfp op2; RXE(inst, regs, r1, b2, effective_addr2); //logmsg("LXEB r1=%d b2=%d\n", r1, b2); BFPINST_CHECK(regs); BFPREGPAIR_CHECK(r1, regs); vfetch_sbfp(&op2, effective_addr2, b2, regs); lengthen_short_to_ext(&op2, &op1, regs); put_ebfp(&op1, regs->fpr + FPR2I(r1)); } /* * B341 LNXBR - LOAD NEGATIVE (extended BFP) [RRE] */ DEF_INST(load_negative_bfp_ext_reg) { int r1, r2; struct ebfp op; RRE(inst, regs, r1, r2); //logmsg("LNXBR r1=%d r2=%d\n", r1, r2); BFPINST_CHECK(regs); BFPREGPAIR2_CHECK(r1, r2, regs); get_ebfp(&op, regs->fpr + FPR2I(r2)); op.sign = 1; switch (ebfpclassify(&op)) { case FP_ZERO: regs->psw.cc = 0; break; case FP_NAN: regs->psw.cc = 3; break; default: regs->psw.cc = 1; break; } put_ebfp(&op, regs->fpr + FPR2I(r1)); } /* * B311 LNDBR - LOAD NEGATIVE (long BFP) [RRE] */ DEF_INST(load_negative_bfp_long_reg) { int r1, r2; struct lbfp op; RRE(inst, regs, r1, r2); //logmsg("LNDBR r1=%d r2=%d\n", r1, r2); BFPINST_CHECK(regs); get_lbfp(&op, regs->fpr + FPR2I(r2)); op.sign = 1; switch (lbfpclassify(&op)) { case FP_ZERO: regs->psw.cc = 0; break; case FP_NAN: regs->psw.cc = 3; break; default: regs->psw.cc = 1; break; } put_lbfp(&op, regs->fpr + FPR2I(r1)); } /* * B301 LNEBR - LOAD NEGATIVE (short BFP) [RRE] */ DEF_INST(load_negative_bfp_short_reg) { int r1, r2; struct sbfp op; RRE(inst, regs, r1, r2); //logmsg("LNEBR r1=%d r2=%d\n", r1, r2); BFPINST_CHECK(regs); get_sbfp(&op, regs->fpr + FPR2I(r2)); op.sign = 1; switch (sbfpclassify(&op)) { case FP_ZERO: regs->psw.cc = 0; break; case FP_NAN: regs->psw.cc = 3; break; default: regs->psw.cc = 1; break; } put_sbfp(&op, regs->fpr + FPR2I(r1)); } /* * B343 LCXBR - LOAD COMPLEMENT (extended BFP) [RRE] */ DEF_INST(load_complement_bfp_ext_reg) { int r1, r2; struct ebfp op; RRE(inst, regs, r1, r2); //logmsg("LCXBR r1=%d r2=%d\n", r1, r2); BFPINST_CHECK(regs); BFPREGPAIR2_CHECK(r1, r2, regs); get_ebfp(&op, regs->fpr + FPR2I(r2)); op.sign = !op.sign; switch (ebfpclassify(&op)) { case FP_ZERO: regs->psw.cc = 0; break; case FP_NAN: regs->psw.cc = 3; break; default: regs->psw.cc = op.sign ? 1 : 2; break; } put_ebfp(&op, regs->fpr + FPR2I(r1)); } /* * B313 LCDBR - LOAD COMPLEMENT (long BFP) [RRE] */ DEF_INST(load_complement_bfp_long_reg) { int r1, r2; struct lbfp op; RRE(inst, regs, r1, r2); //logmsg("LCDBR r1=%d r2=%d\n", r1, r2); BFPINST_CHECK(regs); get_lbfp(&op, regs->fpr + FPR2I(r2)); op.sign = !op.sign; switch (lbfpclassify(&op)) { case FP_ZERO: regs->psw.cc = 0; break; case FP_NAN: regs->psw.cc = 3; break; default: regs->psw.cc = op.sign ? 1 : 2; break; } put_lbfp(&op, regs->fpr + FPR2I(r1)); } /* * B303 LCEBR - LOAD COMPLEMENT (short BFP) [RRE] */ DEF_INST(load_complement_bfp_short_reg) { int r1, r2; struct sbfp op; RRE(inst, regs, r1, r2); //logmsg("LCEBR r1=%d r2=%d\n", r1, r2); BFPINST_CHECK(regs); get_sbfp(&op, regs->fpr + FPR2I(r2)); op.sign = !op.sign; switch (sbfpclassify(&op)) { case FP_ZERO: regs->psw.cc = 0; break; case FP_NAN: regs->psw.cc = 3; break; default: regs->psw.cc = op.sign ? 1 : 2; break; } put_sbfp(&op, regs->fpr + FPR2I(r1)); } /* * B340 LPXBR - LOAD POSITIVE (extended BFP) [RRE] */ DEF_INST(load_positive_bfp_ext_reg) { int r1, r2; struct ebfp op; RRE(inst, regs, r1, r2); //logmsg("LPXBR r1=%d r2=%d\n", r1, r2); BFPINST_CHECK(regs); BFPREGPAIR2_CHECK(r1, r2, regs); get_ebfp(&op, regs->fpr + FPR2I(r2)); op.sign = 0; switch (ebfpclassify(&op)) { case FP_ZERO: regs->psw.cc = 0; break; case FP_NAN: regs->psw.cc = 3; break; default: regs->psw.cc = 2; break; } put_ebfp(&op, regs->fpr + FPR2I(r1)); } /* * B310 LPDBR - LOAD POSITIVE (long BFP) [RRE] */ DEF_INST(load_positive_bfp_long_reg) { int r1, r2; struct lbfp op; RRE(inst, regs, r1, r2); //logmsg("LPDBR r1=%d r2=%d\n", r1, r2); BFPINST_CHECK(regs); get_lbfp(&op, regs->fpr + FPR2I(r2)); op.sign = 0; switch (lbfpclassify(&op)) { case FP_ZERO: regs->psw.cc = 0; break; case FP_NAN: regs->psw.cc = 3; break; default: regs->psw.cc = 2; break; } put_lbfp(&op, regs->fpr + FPR2I(r1)); } /* * B300 LPEBR - LOAD POSITIVE (short BFP) [RRE] */ DEF_INST(load_positive_bfp_short_reg) { int r1, r2; struct sbfp op; RRE(inst, regs, r1, r2); //logmsg("LPEBR r1=%d r2=%d\n", r1, r2); BFPINST_CHECK(regs); get_sbfp(&op, regs->fpr + FPR2I(r2)); op.sign = 0; switch (sbfpclassify(&op)) { case FP_ZERO: regs->psw.cc = 0; break; case FP_NAN: regs->psw.cc = 3; break; default: regs->psw.cc = 2; break; } put_sbfp(&op, regs->fpr + FPR2I(r1)); } /* * B344 LEDBR - LOAD ROUNDED (long to short BFP) [RRE] */ DEF_INST(load_rounded_bfp_long_to_short_reg) { int r1, r2, raised; struct sbfp op1; struct lbfp op2; int pgm_check; RRE(inst, regs, r1, r2); //logmsg("LEDBR r1=%d r2=%d\n", r1, r2); BFPINST_CHECK(regs); get_lbfp(&op2, regs->fpr + FPR2I(r2)); switch (lbfpclassify(&op2)) { case FP_ZERO: sbfpzero(&op1, op2.sign); break; case FP_NAN: if (lbfpissnan(&op2)) { ieee_exception(FE_INVALID, regs); sbfpstoqnan(&op1); } break; case FP_INFINITE: sbfpinfinity(&op1, op2.sign); break; default: FECLEAREXCEPT(FE_ALL_EXCEPT); lbfpston(&op2); op1.v = (double)op2.v; sbfpntos(&op1); raised = fetestexcept(FE_ALL_EXCEPT); if (raised) { pgm_check = ieee_exception(raised, regs); if (pgm_check) { regs->program_interrupt(regs, pgm_check); } } break; } put_sbfp(&op1, regs->fpr + FPR2I(r1)); } /* end DEF_INST(load_rounded_bfp_long_to_short_reg) */ /* * B345 LDXBR - LOAD ROUNDED (extended to long BFP) [RRE] */ DEF_INST(load_rounded_bfp_ext_to_long_reg) { int r1, r2, raised; struct lbfp op1; struct ebfp op2; int pgm_check; RRE(inst, regs, r1, r2); //logmsg("LDXBR r1=%d r2=%d\n", r1, r2); BFPINST_CHECK(regs); BFPREGPAIR2_CHECK(r1, r2, regs); get_ebfp(&op2, regs->fpr + FPR2I(r2)); switch (ebfpclassify(&op2)) { case FP_ZERO: lbfpzero(&op1, op2.sign); break; case FP_NAN: if (ebfpissnan(&op2)) { ieee_exception(FE_INVALID, regs); lbfpstoqnan(&op1); } break; case FP_INFINITE: lbfpinfinity(&op1, op2.sign); break; default: FECLEAREXCEPT(FE_ALL_EXCEPT); ebfpston(&op2); op1.v = op2.v; lbfpntos(&op1); raised = fetestexcept(FE_ALL_EXCEPT); if (raised) { pgm_check = ieee_exception(raised, regs); if (pgm_check) { regs->program_interrupt(regs, pgm_check); } } break; } put_lbfp(&op1, regs->fpr + FPR2I(r1)); } /* end DEF_INST(load_rounded_bfp_ext_to_long_reg) */ /* * B346 LEXBR - LOAD ROUNDED (extended to short BFP) [RRE] */ DEF_INST(load_rounded_bfp_ext_to_short_reg) { int r1, r2, raised; struct sbfp op1; struct ebfp op2; int pgm_check; RRE(inst, regs, r1, r2); //logmsg("LEXBR r1=%d r2=%d\n", r1, r2); BFPINST_CHECK(regs); BFPREGPAIR2_CHECK(r1, r2, regs); get_ebfp(&op2, regs->fpr + FPR2I(r2)); switch (ebfpclassify(&op2)) { case FP_ZERO: sbfpzero(&op1, op2.sign); break; case FP_NAN: if (ebfpissnan(&op2)) { ieee_exception(FE_INVALID, regs); sbfpstoqnan(&op1); } break; case FP_INFINITE: sbfpinfinity(&op1, op2.sign); break; default: FECLEAREXCEPT(FE_ALL_EXCEPT); ebfpston(&op2); op1.v = op2.v; sbfpntos(&op1); raised = fetestexcept(FE_ALL_EXCEPT); if (raised) { pgm_check = ieee_exception(raised, regs); if (pgm_check) { regs->program_interrupt(regs, pgm_check); } } break; } put_sbfp(&op1, regs->fpr + FPR2I(r1)); } /* end DEF_INST(load_rounded_bfp_ext_to_short_reg) */ /* * MULTIPLY (extended) */ static int multiply_ebfp(struct ebfp *op1, struct ebfp *op2, REGS *regs) { int r, cl1, cl2, raised; if (ebfpissnan(op1) || ebfpissnan(op2)) { r = ieee_exception(FE_INVALID, regs); if (r) { return r; } } cl1 = ebfpclassify(op1); cl2 = ebfpclassify(op2); if (cl1 == FP_NAN) { if (ebfpissnan(op1)) { ebfpstoqnan(op1); } else if (ebfpissnan(op2)) { *op1 = *op2; ebfpstoqnan(op1); } } else if (cl2 == FP_NAN) { if (ebfpissnan(op2)) { *op1 = *op2; ebfpstoqnan(op1); } else { *op1 = *op2; } } else if (cl1 == FP_INFINITE) { if (cl2 == FP_ZERO) { r = ieee_exception(FE_INVALID, regs); if (r) { return r; } ebfpdnan(op1); } else { if (op2->sign) { op1->sign = !(op1->sign); } } } else if (cl2 == FP_INFINITE) { if (cl1 == FP_ZERO) { r = ieee_exception(FE_INVALID, regs); if (r) { return r; } ebfpdnan(op1); } else { if (op1->sign) { op2->sign = !(op2->sign); } *op1 = *op2; } } else if (cl1 == FP_ZERO || cl2 == FP_ZERO) { ebfpzero(op1, op1->sign != op2->sign); } else { FECLEAREXCEPT(FE_ALL_EXCEPT); ebfpston(op1); ebfpston(op2); op1->v *= op2->v; ebfpntos(op1); raised = fetestexcept(FE_ALL_EXCEPT); if (raised) { r = ieee_exception(raised, regs); if (r) { return r; } } } return 0; } /* * B34C MXBR - MULTIPLY (extended BFP) [RRE] */ DEF_INST(multiply_bfp_ext_reg) { int r1, r2; struct ebfp op1, op2; int pgm_check; RRE(inst, regs, r1, r2); //logmsg("MXBR r1=%d r2=%d\n", r1, r2); BFPINST_CHECK(regs); BFPREGPAIR2_CHECK(r1, r2, regs); get_ebfp(&op1, regs->fpr + FPR2I(r1)); get_ebfp(&op2, regs->fpr + FPR2I(r2)); pgm_check = multiply_ebfp(&op1, &op2, regs); put_ebfp(&op1, regs->fpr + FPR2I(r1)); if (pgm_check) { regs->program_interrupt(regs, pgm_check); } } /* * B307 MXDBR - MULTIPLY (long to extended BFP) [RRE] */ DEF_INST(multiply_bfp_long_to_ext_reg) { int r1, r2; struct lbfp op1, op2; struct ebfp eb1, eb2; int pgm_check; RRE(inst, regs, r1, r2); //logmsg("MXDBR r1=%d r2=%d\n", r1, r2); BFPINST_CHECK(regs); BFPREGPAIR_CHECK(r1, regs); get_lbfp(&op1, regs->fpr + FPR2I(r1)); get_lbfp(&op2, regs->fpr + FPR2I(r2)); lengthen_long_to_ext(&op1, &eb1, regs); lengthen_long_to_ext(&op2, &eb2, regs); pgm_check = multiply_ebfp(&eb1, &eb2, regs); put_ebfp(&eb1, regs->fpr + FPR2I(r1)); if (pgm_check) { regs->program_interrupt(regs, pgm_check); } } /* end DEF_INST(multiply_bfp_long_to_ext_reg) */ /* * ED07 MXDB - MULTIPLY (long to extended BFP) [RXE] */ DEF_INST(multiply_bfp_long_to_ext) { int r1, b2; VADR effective_addr2; struct lbfp op1, op2; struct ebfp eb1, eb2; int pgm_check; RXE(inst, regs, r1, b2, effective_addr2); //logmsg("MXDB r1=%d b2=%d\n", r1, b2); BFPINST_CHECK(regs); BFPREGPAIR_CHECK(r1, regs); get_lbfp(&op1, regs->fpr + FPR2I(r1)); vfetch_lbfp(&op2, effective_addr2, b2, regs); lengthen_long_to_ext(&op1, &eb1, regs); lengthen_long_to_ext(&op2, &eb2, regs); pgm_check = multiply_ebfp(&eb1, &eb2, regs); put_ebfp(&eb1, regs->fpr + FPR2I(r1)); if (pgm_check) { regs->program_interrupt(regs, pgm_check); } } /* end DEF_INST(multiply_bfp_long_to_ext) */ /* * MULTIPLY (long) */ static int multiply_lbfp(struct lbfp *op1, struct lbfp *op2, REGS *regs) { int r, cl1, cl2, raised; if (lbfpissnan(op1) || lbfpissnan(op2)) { r = ieee_exception(FE_INVALID, regs); if (r) { return r; } } cl1 = lbfpclassify(op1); cl2 = lbfpclassify(op2); if (cl1 == FP_NAN) { if (lbfpissnan(op1)) { lbfpstoqnan(op1); } else if (lbfpissnan(op2)) { *op1 = *op2; lbfpstoqnan(op1); } } else if (cl2 == FP_NAN) { if (lbfpissnan(op2)) { *op1 = *op2; lbfpstoqnan(op1); } else { *op1 = *op2; } } else if (cl1 == FP_INFINITE) { if (cl2 == FP_ZERO) { r = ieee_exception(FE_INVALID, regs); if (r) { return r; } lbfpdnan(op1); } else { if (op2->sign) { op1->sign = !(op1->sign); } } } else if (cl2 == FP_INFINITE) { if (cl1 == FP_ZERO) { r = ieee_exception(FE_INVALID, regs); if (r) { return r; } lbfpdnan(op1); } else { if (op1->sign) { op2->sign = !(op2->sign); } *op1 = *op2; } } else if (cl1 == FP_ZERO || cl2 == FP_ZERO) { lbfpzero(op1, op1->sign != op2->sign); } else { FECLEAREXCEPT(FE_ALL_EXCEPT); lbfpston(op1); lbfpston(op2); op1->v *= op2->v; lbfpntos(op1); raised = fetestexcept(FE_ALL_EXCEPT); if (raised) { r = ieee_exception(raised, regs); if (r) { return r; } } } return 0; } /* * B31C MDBR - MULTIPLY (long BFP) [RRE] */ DEF_INST(multiply_bfp_long_reg) { int r1, r2; struct lbfp op1, op2; int pgm_check; RRE(inst, regs, r1, r2); //logmsg("MDBR r1=%d r2=%d\n", r1, r2); BFPINST_CHECK(regs); get_lbfp(&op1, regs->fpr + FPR2I(r1)); get_lbfp(&op2, regs->fpr + FPR2I(r2)); pgm_check = multiply_lbfp(&op1, &op2, regs); put_lbfp(&op1, regs->fpr + FPR2I(r1)); if (pgm_check) { regs->program_interrupt(regs, pgm_check); } } /* * ED1C MDB - MULTIPLY (long BFP) [RXE] */ DEF_INST(multiply_bfp_long) { int r1, b2; VADR effective_addr2; struct lbfp op1, op2; int pgm_check; RXE(inst, regs, r1, b2, effective_addr2); //logmsg("MDB r1=%d b2=%d\n", r1, b2); BFPINST_CHECK(regs); get_lbfp(&op1, regs->fpr + FPR2I(r1)); vfetch_lbfp(&op2, effective_addr2, b2, regs); pgm_check = multiply_lbfp(&op1, &op2, regs); put_lbfp(&op1, regs->fpr + FPR2I(r1)); if (pgm_check) { regs->program_interrupt(regs, pgm_check); } } /* * B30C MDEBR - MULTIPLY (short to long BFP) [RRE] */ DEF_INST(multiply_bfp_short_to_long_reg) { int r1, r2; struct sbfp op1, op2; struct lbfp lb1, lb2; int pgm_check; RRE(inst, regs, r1, r2); //logmsg("MDEBR r1=%d r2=%d\n", r1, r2); BFPINST_CHECK(regs); get_sbfp(&op1, regs->fpr + FPR2I(r1)); get_sbfp(&op2, regs->fpr + FPR2I(r2)); lengthen_short_to_long(&op1, &lb1, regs); lengthen_short_to_long(&op2, &lb2, regs); pgm_check = multiply_lbfp(&lb1, &lb2, regs); put_lbfp(&lb1, regs->fpr + FPR2I(r1)); if (pgm_check) { regs->program_interrupt(regs, pgm_check); } } /* end DEF_INST(multiply_bfp_short_to_long_reg) */ /* * ED0C MDEB - MULTIPLY (short to long BFP) [RXE] */ DEF_INST(multiply_bfp_short_to_long) { int r1, b2; VADR effective_addr2; struct sbfp op1, op2; struct lbfp lb1, lb2; int pgm_check; RXE(inst, regs, r1, b2, effective_addr2); //logmsg("MDEB r1=%d b2=%d\n", r1, b2); BFPINST_CHECK(regs); get_sbfp(&op1, regs->fpr + FPR2I(r1)); vfetch_sbfp(&op2, effective_addr2, b2, regs); lengthen_short_to_long(&op1, &lb1, regs); lengthen_short_to_long(&op2, &lb2, regs); pgm_check = multiply_lbfp(&lb1, &lb2, regs); put_lbfp(&lb1, regs->fpr + FPR2I(r1)); if (pgm_check) { regs->program_interrupt(regs, pgm_check); } } /* end DEF_INST(multiply_bfp_short_to_long) */ /* * MULTIPLY (short) */ static int multiply_sbfp(struct sbfp *op1, struct sbfp *op2, REGS *regs) { int r, cl1, cl2, raised; if (sbfpissnan(op1) || sbfpissnan(op2)) { r = ieee_exception(FE_INVALID, regs); if (r) { return r; } } cl1 = sbfpclassify(op1); cl2 = sbfpclassify(op2); if (cl1 == FP_NAN) { if (sbfpissnan(op1)) { sbfpstoqnan(op1); } else if (sbfpissnan(op2)) { *op1 = *op2; sbfpstoqnan(op1); } } else if (cl2 == FP_NAN) { if (sbfpissnan(op2)) { *op1 = *op2; sbfpstoqnan(op1); } else { *op1 = *op2; } } else if (cl1 == FP_INFINITE) { if (cl2 == FP_ZERO) { r = ieee_exception(FE_INVALID, regs); if (r) { return r; } sbfpdnan(op1); } else { if (op2->sign) { op1->sign = !(op1->sign); } } } else if (cl2 == FP_INFINITE) { if (cl1 == FP_ZERO) { r = ieee_exception(FE_INVALID, regs); if (r) { return r; } sbfpdnan(op1); } else { if (op1->sign) { op2->sign = !(op2->sign); } *op1 = *op2; } } else if (cl1 == FP_ZERO || cl2 == FP_ZERO) { sbfpzero(op1, op1->sign != op2->sign); } else { FECLEAREXCEPT(FE_ALL_EXCEPT); sbfpston(op1); sbfpston(op2); op1->v *= op2->v; sbfpntos(op1); raised = fetestexcept(FE_ALL_EXCEPT); if (raised) { r = ieee_exception(raised, regs); if (r) { return r; } } } return 0; } /* * B317 MEEBR - MULTIPLY (short BFP) [RRE] */ DEF_INST(multiply_bfp_short_reg) { int r1, r2; struct sbfp op1, op2; int pgm_check; RRE(inst, regs, r1, r2); //logmsg("MEEBR r1=%d r2=%d\n", r1, r2); BFPINST_CHECK(regs); get_sbfp(&op1, regs->fpr + FPR2I(r1)); get_sbfp(&op2, regs->fpr + FPR2I(r2)); pgm_check = multiply_sbfp(&op1, &op2, regs); put_sbfp(&op1, regs->fpr + FPR2I(r1)); if (pgm_check) { regs->program_interrupt(regs, pgm_check); } } /* * ED17 MEEB - MULTIPLY (short BFP) [RXE] */ DEF_INST(multiply_bfp_short) { int r1, b2; VADR effective_addr2; struct sbfp op1, op2; int pgm_check; RXE(inst, regs, r1, b2, effective_addr2); //logmsg("MEEB r1=%d b2=%d\n", r1, b2); BFPINST_CHECK(regs); get_sbfp(&op1, regs->fpr + FPR2I(r1)); vfetch_sbfp(&op2, effective_addr2, b2, regs); pgm_check = multiply_sbfp(&op1, &op2, regs); put_sbfp(&op1, regs->fpr + FPR2I(r1)); if (pgm_check) { regs->program_interrupt(regs, pgm_check); } } /* * B31E MADBR - MULTIPLY AND ADD (long BFP) [RRF] */ DEF_INST(multiply_add_bfp_long_reg) { int r1, r2, r3; struct lbfp op1, op2, op3; int pgm_check; RRF_R(inst, regs, r1, r2, r3); //logmsg("MADBR r1=%d r3=%d r2=%d\n", r1, r3, r2); BFPINST_CHECK(regs); get_lbfp(&op1, regs->fpr + FPR2I(r1)); get_lbfp(&op2, regs->fpr + FPR2I(r2)); get_lbfp(&op3, regs->fpr + FPR2I(r3)); multiply_lbfp(&op2, &op3, regs); pgm_check = add_lbfp(&op1, &op2, regs); put_lbfp(&op1, regs->fpr + FPR2I(r1)); if (pgm_check) { regs->program_interrupt(regs, pgm_check); } } /* end DEF_INST(multiply_add_bfp_long_reg) */ /* * ED1E MADB - MULTIPLY AND ADD (long BFP) [RXF] */ DEF_INST(multiply_add_bfp_long) { int r1, r3, b2; VADR effective_addr2; struct lbfp op1, op2, op3; int pgm_check; RXF(inst, regs, r1, r3, b2, effective_addr2); //logmsg("MADB r1=%d r3=%d b2=%d\n", r1, r3, b2); BFPINST_CHECK(regs); get_lbfp(&op1, regs->fpr + FPR2I(r1)); vfetch_lbfp(&op2, effective_addr2, b2, regs); get_lbfp(&op3, regs->fpr + FPR2I(r3)); multiply_lbfp(&op2, &op3, regs); pgm_check = add_lbfp(&op1, &op2, regs); put_lbfp(&op1, regs->fpr + FPR2I(r1)); if (pgm_check) { regs->program_interrupt(regs, pgm_check); } } /* end DEF_INST(multiply_add_bfp_long) */ /* * B30E MAEBR - MULTIPLY AND ADD (short BFP) [RRF] */ DEF_INST(multiply_add_bfp_short_reg) { int r1, r2, r3; struct sbfp op1, op2, op3; int pgm_check; RRF_R(inst, regs, r1, r2, r3); //logmsg("MAEBR r1=%d r3=%d r2=%d\n", r1, r3, r2); BFPINST_CHECK(regs); get_sbfp(&op1, regs->fpr + FPR2I(r1)); get_sbfp(&op2, regs->fpr + FPR2I(r2)); get_sbfp(&op3, regs->fpr + FPR2I(r3)); multiply_sbfp(&op2, &op3, regs); pgm_check = add_sbfp(&op1, &op2, regs); put_sbfp(&op1, regs->fpr + FPR2I(r1)); if (pgm_check) { regs->program_interrupt(regs, pgm_check); } } /* end DEF_INST(multiply_add_bfp_short_reg) */ /* * ED0E MAEB - MULTIPLY AND ADD (short BFP) [RXF] */ DEF_INST(multiply_add_bfp_short) { int r1, r3, b2; VADR effective_addr2; struct sbfp op1, op2, op3; int pgm_check; RXF(inst, regs, r1, r3, b2, effective_addr2); //logmsg("MAEB r1=%d r3=%d b2=%d\n", r1, r3, b2); BFPINST_CHECK(regs); get_sbfp(&op1, regs->fpr + FPR2I(r1)); vfetch_sbfp(&op2, effective_addr2, b2, regs); get_sbfp(&op3, regs->fpr + FPR2I(r3)); multiply_sbfp(&op2, &op3, regs); pgm_check = add_sbfp(&op1, &op2, regs); put_sbfp(&op1, regs->fpr + FPR2I(r1)); if (pgm_check) { regs->program_interrupt(regs, pgm_check); } } /* end DEF_INST(multiply_add_bfp_short) */ /* * B31F MSDBR - MULTIPLY AND SUBTRACT (long BFP) [RRF] */ DEF_INST(multiply_subtract_bfp_long_reg) { int r1, r2, r3; struct lbfp op1, op2, op3; int pgm_check; RRF_R(inst, regs, r1, r2, r3); //logmsg("MSDBR r1=%d r3=%d r2=%d\n", r1, r3, r2); BFPINST_CHECK(regs); get_lbfp(&op1, regs->fpr + FPR2I(r1)); get_lbfp(&op2, regs->fpr + FPR2I(r2)); get_lbfp(&op3, regs->fpr + FPR2I(r3)); multiply_lbfp(&op2, &op3, regs); op1.sign = !(op1.sign); pgm_check = add_lbfp(&op1, &op2, regs); put_lbfp(&op1, regs->fpr + FPR2I(r1)); if (pgm_check) { regs->program_interrupt(regs, pgm_check); } } /* end DEF_INST(multiply_subtract_bfp_long_reg) */ /* * ED1F MSDB - MULTIPLY AND SUBTRACT (long BFP) [RXF] */ DEF_INST(multiply_subtract_bfp_long) { int r1, r3, b2; VADR effective_addr2; struct lbfp op1, op2, op3; int pgm_check; RXF(inst, regs, r1, r3, b2, effective_addr2); //logmsg("MSDB r1=%d r3=%d b2=%d\n", r1, r3, b2); BFPINST_CHECK(regs); get_lbfp(&op1, regs->fpr + FPR2I(r1)); vfetch_lbfp(&op2, effective_addr2, b2, regs); get_lbfp(&op3, regs->fpr + FPR2I(r3)); multiply_lbfp(&op2, &op3, regs); op1.sign = !(op1.sign); pgm_check = add_lbfp(&op1, &op2, regs); put_lbfp(&op1, regs->fpr + FPR2I(r1)); if (pgm_check) { regs->program_interrupt(regs, pgm_check); } } /* end DEF_INST(multiply_subtract_bfp_long) */ /* * B30F MSEBR - MULTIPLY AND SUBTRACT (short BFP) [RRF] */ DEF_INST(multiply_subtract_bfp_short_reg) { int r1, r2, r3; struct sbfp op1, op2, op3; int pgm_check; RRF_R(inst, regs, r1, r2, r3); //logmsg("MSEBR r1=%d r3=%d r2=%d\n", r1, r3, r2); BFPINST_CHECK(regs); get_sbfp(&op1, regs->fpr + FPR2I(r1)); get_sbfp(&op2, regs->fpr + FPR2I(r2)); get_sbfp(&op3, regs->fpr + FPR2I(r3)); multiply_sbfp(&op2, &op3, regs); op1.sign = !(op1.sign); pgm_check = add_sbfp(&op1, &op2, regs); put_sbfp(&op1, regs->fpr + FPR2I(r1)); if (pgm_check) { regs->program_interrupt(regs, pgm_check); } } /* end DEF_INST(multiply_subtract_bfp_short_reg) */ /* * ED0F MSEB - MULTIPLY AND SUBTRACT (short BFP) [RXF] */ DEF_INST(multiply_subtract_bfp_short) { int r1, r3, b2; VADR effective_addr2; struct sbfp op1, op2, op3; int pgm_check; RXF(inst, regs, r1, r3, b2, effective_addr2); //logmsg("MSEB r1=%d r3=%d b2=%d\n", r1, r3, b2); BFPINST_CHECK(regs); get_sbfp(&op1, regs->fpr + FPR2I(r1)); vfetch_sbfp(&op2, effective_addr2, b2, regs); get_sbfp(&op3, regs->fpr + FPR2I(r3)); multiply_sbfp(&op2, &op3, regs); op1.sign = !(op1.sign); pgm_check = add_sbfp(&op1, &op2, regs); put_sbfp(&op1, regs->fpr + FPR2I(r1)); if (pgm_check) { regs->program_interrupt(regs, pgm_check); } } /* end DEF_INST(multiply_subtract_bfp_short) */ /* * B384 SFPC - SET FPC [RRE] * This instruction is in module esame.c */ /* * B299 SRNM - SET ROUNDING MODE [S] * This instruction is in module esame.c */ /* * SQUARE ROOT (extended) */ static int squareroot_ebfp(struct ebfp *op, REGS *regs) { int raised; switch (ebfpclassify(op)) { case FP_NAN: case FP_INFINITE: case FP_ZERO: break; default: if (op->sign) { return ieee_exception(FE_INVALID, regs); } FECLEAREXCEPT(FE_ALL_EXCEPT); ebfpston(op); op->v = sqrtl(op->v); ebfpntos(op); raised = fetestexcept(FE_ALL_EXCEPT); if (raised) { return ieee_exception(raised, regs); } break; } return 0; } /* * B316 SQXBR - SQUARE ROOT (extended BFP) [RRE] */ DEF_INST(squareroot_bfp_ext_reg) { int r1, r2; struct ebfp op; int pgm_check; RRE(inst, regs, r1, r2); //logmsg("SQXBR r1=%d r2=%d\n", r1, r2); BFPINST_CHECK(regs); BFPREGPAIR2_CHECK(r1, r2, regs); get_ebfp(&op, regs->fpr + FPR2I(r2)); pgm_check = squareroot_ebfp(&op, regs); put_ebfp(&op, regs->fpr + FPR2I(r1)); if (pgm_check) { regs->program_interrupt(regs, pgm_check); } } /* * SQUARE ROOT (long) */ static int squareroot_lbfp(struct lbfp *op, REGS *regs) { int raised; switch (lbfpclassify(op)) { case FP_NAN: case FP_INFINITE: case FP_ZERO: break; default: if (op->sign) { return ieee_exception(FE_INVALID, regs); } FECLEAREXCEPT(FE_ALL_EXCEPT); lbfpston(op); op->v = sqrtl(op->v); lbfpntos(op); raised = fetestexcept(FE_ALL_EXCEPT); if (raised) { return ieee_exception(raised, regs); } break; } return 0; } /* * B315 SQDBR - SQUARE ROOT (long BFP) [RRE] */ DEF_INST(squareroot_bfp_long_reg) { int r1, r2; struct lbfp op; int pgm_check; RRE(inst, regs, r1, r2); //logmsg("SQDBR r1=%d r2=%d\n", r1, r2); BFPINST_CHECK(regs); get_lbfp(&op, regs->fpr + FPR2I(r2)); pgm_check = squareroot_lbfp(&op, regs); put_lbfp(&op, regs->fpr + FPR2I(r1)); if (pgm_check) { regs->program_interrupt(regs, pgm_check); } } /* * ED15 SQDB - SQUARE ROOT (long BFP) [RXE] */ DEF_INST(squareroot_bfp_long) { int r1, b2; VADR effective_addr2; struct lbfp op; int pgm_check; RXE(inst, regs, r1, b2, effective_addr2); //logmsg("SQDB r1=%d b2=%d\n", r1, b2); BFPINST_CHECK(regs); vfetch_lbfp(&op, effective_addr2, b2, regs); pgm_check = squareroot_lbfp(&op, regs); put_lbfp(&op, regs->fpr + FPR2I(r1)); if (pgm_check) { regs->program_interrupt(regs, pgm_check); } } /* * SQUARE ROOT (short) */ static int squareroot_sbfp(struct sbfp *op, REGS *regs) { int raised; switch (sbfpclassify(op)) { case FP_NAN: case FP_INFINITE: case FP_ZERO: break; default: if (op->sign) { return ieee_exception(FE_INVALID, regs); } FECLEAREXCEPT(FE_ALL_EXCEPT); sbfpston(op); op->v = sqrtl(op->v); sbfpntos(op); raised = fetestexcept(FE_ALL_EXCEPT); if (raised) { return ieee_exception(raised, regs); } break; } return 0; } /* * B314 SQEBR - SQUARE ROOT (short BFP) [RRE] */ DEF_INST(squareroot_bfp_short_reg) { int r1, r2; struct sbfp op; int pgm_check; RRE(inst, regs, r1, r2); //logmsg("SQEBR r1=%d r2=%d\n", r1, r2); BFPINST_CHECK(regs); get_sbfp(&op, regs->fpr + FPR2I(r2)); pgm_check = squareroot_sbfp(&op, regs); put_sbfp(&op, regs->fpr + FPR2I(r1)); if (pgm_check) { regs->program_interrupt(regs, pgm_check); } } /* * ED14 SQEB - SQUARE ROOT (short BFP) [RXE] */ DEF_INST(squareroot_bfp_short) { int r1, b2; VADR effective_addr2; struct sbfp op; int pgm_check; RXE(inst, regs, r1, b2, effective_addr2); //logmsg("SQEB r1=%d b2=%d\n", r1, b2); BFPINST_CHECK(regs); vfetch_sbfp(&op, effective_addr2, b2, regs); pgm_check = squareroot_sbfp(&op, regs); put_sbfp(&op, regs->fpr + FPR2I(r1)); if (pgm_check) { regs->program_interrupt(regs, pgm_check); } } /* * B29C STFPC - STORE FPC [S] * This instruction is in module esame.c */ /* * B34B SXBR - SUBTRACT (extended BFP) [RRE] */ DEF_INST(subtract_bfp_ext_reg) { int r1, r2; struct ebfp op1, op2; int pgm_check; RRE(inst, regs, r1, r2); //logmsg("SXBR r1=%d r2=%d\n", r1, r2); BFPINST_CHECK(regs); BFPREGPAIR2_CHECK(r1, r2, regs); get_ebfp(&op1, regs->fpr + FPR2I(r1)); get_ebfp(&op2, regs->fpr + FPR2I(r2)); op2.sign = !(op2.sign); pgm_check = add_ebfp(&op1, &op2, regs); put_ebfp(&op1, regs->fpr + FPR2I(r1)); if (pgm_check) { regs->program_interrupt(regs, pgm_check); } } /* * B31B SDBR - SUBTRACT (long BFP) [RRE] */ DEF_INST(subtract_bfp_long_reg) { int r1, r2; struct lbfp op1, op2; int pgm_check; RRE(inst, regs, r1, r2); //logmsg("SDBR r1=%d r2=%d\n", r1, r2); BFPINST_CHECK(regs); get_lbfp(&op1, regs->fpr + FPR2I(r1)); get_lbfp(&op2, regs->fpr + FPR2I(r2)); op2.sign = !(op2.sign); pgm_check = add_lbfp(&op1, &op2, regs); put_lbfp(&op1, regs->fpr + FPR2I(r1)); if (pgm_check) { regs->program_interrupt(regs, pgm_check); } } /* * ED1B SDB - SUBTRACT (long BFP) [RXE] */ DEF_INST(subtract_bfp_long) { int r1, b2; VADR effective_addr2; struct lbfp op1, op2; int pgm_check; RXE(inst, regs, r1, b2, effective_addr2); //logmsg("SDB r1=%d b2=%d\n", r1, b2); BFPINST_CHECK(regs); get_lbfp(&op1, regs->fpr + FPR2I(r1)); vfetch_lbfp(&op2, effective_addr2, b2, regs); op2.sign = !(op2.sign); pgm_check = add_lbfp(&op1, &op2, regs); put_lbfp(&op1, regs->fpr + FPR2I(r1)); if (pgm_check) { regs->program_interrupt(regs, pgm_check); } } /* * B30B SEBR - SUBTRACT (short BFP) [RRE] */ DEF_INST(subtract_bfp_short_reg) { int r1, r2; struct sbfp op1, op2; int pgm_check; RRE(inst, regs, r1, r2); //logmsg("SEBR r1=%d r2=%d\n", r1, r2); BFPINST_CHECK(regs); get_sbfp(&op1, regs->fpr + FPR2I(r1)); get_sbfp(&op2, regs->fpr + FPR2I(r2)); op2.sign = !(op2.sign); pgm_check = add_sbfp(&op1, &op2, regs); put_sbfp(&op1, regs->fpr + FPR2I(r1)); if (pgm_check) { regs->program_interrupt(regs, pgm_check); } } /* * ED0B SEB - SUBTRACT (short BFP) [RXE] */ DEF_INST(subtract_bfp_short) { int r1, b2; VADR effective_addr2; struct sbfp op1, op2; int pgm_check; RXE(inst, regs, r1, b2, effective_addr2); //logmsg("SEB r1=%d b2=%d\n", r1, b2); BFPINST_CHECK(regs); get_sbfp(&op1, regs->fpr + FPR2I(r1)); vfetch_sbfp(&op2, effective_addr2, b2, regs); op2.sign = !(op2.sign); pgm_check = add_sbfp(&op1, &op2, regs); put_sbfp(&op1, regs->fpr + FPR2I(r1)); if (pgm_check) { regs->program_interrupt(regs, pgm_check); } } /* * ED10 TCEB - TEST DATA CLASS (short BFP) [RXE] * Per Jessen, Willem Konynenberg, 20 September 2001 */ DEF_INST(test_data_class_bfp_short) { int r1, b2; VADR effective_addr2; struct sbfp op1; int bit; // parse instruction RXE(inst, regs, r1, b2, effective_addr2); //logmsg("TCEB r1=%d b2=%d\n", r1, b2); BFPINST_CHECK(regs); // retrieve first operand. get_sbfp(&op1, regs->fpr + FPR2I(r1)); switch ( sbfpclassify(&op1) ) { case FP_ZERO: bit=20+op1.sign; break; case FP_NORMAL: bit=22+op1.sign; break; case FP_SUBNORMAL: bit=24+op1.sign; break; case FP_INFINITE: bit=26+op1.sign; break; case FP_NAN: if ( !sbfpissnan(&op1) ) bit=28+op1.sign; else bit=30+op1.sign; break; default: bit=0; break; } bit=31-bit; regs->psw.cc = (effective_addr2>>bit) & 1; } /* * ED11 TCDB - TEST DATA CLASS (long BFP) [RXE] * Per Jessen, Willem Konynenberg, 20 September 2001 */ DEF_INST(test_data_class_bfp_long) { int r1, b2; VADR effective_addr2; struct lbfp op1; int bit; // parse instruction RXE(inst, regs, r1, b2, effective_addr2); //logmsg("TCDB r1=%d b2=%d\n", r1, b2); BFPINST_CHECK(regs); // retrieve first operand. get_lbfp(&op1, regs->fpr + FPR2I(r1)); switch ( lbfpclassify(&op1) ) { case FP_ZERO: bit=20+op1.sign; break; case FP_NORMAL: bit=22+op1.sign; break; case FP_SUBNORMAL: bit=24+op1.sign; break; case FP_INFINITE: bit=26+op1.sign; break; case FP_NAN: if ( !lbfpissnan(&op1) ) bit=28+op1.sign; else bit=30+op1.sign; break; default: bit=0; break; } bit=31-bit; regs->psw.cc = (effective_addr2>>bit) & 1; } /* * ED12 TCXB - TEST DATA CLASS (extended BFP) [RXE] * Per Jessen, Willem Konynenberg, 20 September 2001 */ DEF_INST(test_data_class_bfp_ext) { int r1, b2; VADR effective_addr2; struct ebfp op1; int bit; // parse instruction RXE(inst, regs, r1, b2, effective_addr2); //logmsg("TCXB r1=%d b2=%d\n", r1, b2); BFPINST_CHECK(regs); BFPREGPAIR_CHECK(r1, regs); // retrieve first operand. get_ebfp(&op1, regs->fpr + FPR2I(r1)); switch ( ebfpclassify(&op1) ) { case FP_ZERO: bit=20+op1.sign; break; case FP_NORMAL: bit=22+op1.sign; break; case FP_SUBNORMAL: bit=24+op1.sign; break; case FP_INFINITE: bit=26+op1.sign; break; case FP_NAN: if ( !ebfpissnan(&op1) ) bit=28+op1.sign; else bit=30+op1.sign; break; default: bit=0; break; } bit=31-bit; regs->psw.cc = (effective_addr2>>bit) & 1; } /* * DIVIDE TO INTEGER (long) */ static int divint_lbfp(struct lbfp *op1, struct lbfp *op2, struct lbfp *op3, int mode, REGS *regs) { int r; *op3 = *op1; r = divide_lbfp(op3, op2, regs); if (r) return r; r = integer_lbfp(op3, mode, regs); if (r) return r; r = multiply_lbfp(op2, op3, regs); if (r) return r; op2->sign = !(op2->sign); r = add_lbfp(op1, op2, regs); op2->sign = !(op2->sign); if (r) return r; regs->psw.cc = 0; return 0; } /* end function divint_lbfp */ /* * B35B DIDBR - DIVIDE TO INTEGER (long BFP) [RRF] */ DEF_INST(divide_integer_bfp_long_reg) { int r1, r2, r3, m4; struct lbfp op1, op2, op3; int pgm_check; RRF_RM(inst, regs, r1, r2, r3, m4); //logmsg("DIDBR r1=%d r3=%d r2=%d m4=%d\n", r1, r3, r2, m4); BFPINST_CHECK(regs); if (r1 == r2 || r2 == r3 || r1 == r3) { regs->program_interrupt(regs, PGM_SPECIFICATION_EXCEPTION); } BFPRM_CHECK(m4,regs); get_lbfp(&op1, regs->fpr + FPR2I(r1)); get_lbfp(&op2, regs->fpr + FPR2I(r2)); pgm_check = divint_lbfp(&op1, &op2, &op3, m4, regs); put_lbfp(&op1, regs->fpr + FPR2I(r1)); put_lbfp(&op3, regs->fpr + FPR2I(r3)); if (pgm_check) { regs->program_interrupt(regs, pgm_check); } } /* end DEF_INST(divide_integer_bfp_long_reg) */ /* * DIVIDE TO INTEGER (short) */ static int divint_sbfp(struct sbfp *op1, struct sbfp *op2, struct sbfp *op3, int mode, REGS *regs) { int r; *op3 = *op1; r = divide_sbfp(op3, op2, regs); if (r) return r; r = integer_sbfp(op3, mode, regs); if (r) return r; r = multiply_sbfp(op2, op3, regs); if (r) return r; op2->sign = !(op2->sign); r = add_sbfp(op1, op2, regs); op2->sign = !(op2->sign); if (r) return r; regs->psw.cc = 0; return 0; } /* end function divint_sbfp */ /* * B353 DIEBR - DIVIDE TO INTEGER (short BFP) [RRF] */ DEF_INST(divide_integer_bfp_short_reg) { int r1, r2, r3, m4; struct sbfp op1, op2, op3; int pgm_check; RRF_RM(inst, regs, r1, r2, r3, m4); //logmsg("DIEBR r1=%d r3=%d r2=%d m4=%d\n", r1, r3, r2, m4); BFPINST_CHECK(regs); if (r1 == r2 || r2 == r3 || r1 == r3) { regs->program_interrupt(regs, PGM_SPECIFICATION_EXCEPTION); } BFPRM_CHECK(m4,regs); get_sbfp(&op1, regs->fpr + FPR2I(r1)); get_sbfp(&op2, regs->fpr + FPR2I(r2)); pgm_check = divint_sbfp(&op1, &op2, &op3, m4, regs); put_sbfp(&op1, regs->fpr + FPR2I(r1)); put_sbfp(&op3, regs->fpr + FPR2I(r3)); if (pgm_check) { regs->program_interrupt(regs, pgm_check); } } /* end DEF_INST(divide_integer_bfp_short_reg) */ #endif /* FEATURE_BINARY_FLOATING_POINT */ #if !defined(_GEN_ARCH) #if defined(_ARCHMODE2) #define _GEN_ARCH _ARCHMODE2 #include "ieee.c" #endif #if defined(_ARCHMODE3) #undef _GEN_ARCH #define _GEN_ARCH _ARCHMODE3 #include "ieee.c" #endif #endif /*!defined(_GEN_ARCH) */ /* end of ieee.c */ hercules-3.07/impl.c000644 000765 000765 00000046152 11224164171 016057 0ustar00jmaynardjmaynard000000 000000 /* IMPL.C (c) Copyright Roger Bowler, 1999-2009 */ /* Hercules Initialization Module */ // $Id: impl.c 5408 2009-06-14 18:53:34Z fish $ /*-------------------------------------------------------------------*/ /* This module initializes the Hercules S/370 or ESA/390 emulator. */ /* It builds the system configuration blocks, creates threads for */ /* central processors, HTTP server, logger task and activates the */ /* control panel which runs under the main thread when in foreground */ /* mode. */ /*-------------------------------------------------------------------*/ // $Log$ // Revision 1.130 2009/01/15 17:36:44 jj // Change http server startup // // Revision 1.129 2009/01/07 16:00:43 bernard // add msghldsec command // // Revision 1.128 2008/11/04 05:56:31 fish // Put ensure consistent create_thread ATTR usage change back in // // Revision 1.127 2008/11/03 15:31:54 rbowler // Back out consistent create_thread ATTR modification // // Revision 1.126 2008/10/24 13:47:11 fish // Fix RC file not processed nor HAO thread engaged if -d daemon mode // // Revision 1.125 2008/10/18 09:32:21 fish // Ensure consistent create_thread ATTR usage // // Revision 1.124 2007/12/10 23:12:02 gsmith // Tweaks to OPTION_MIPS_COUNTING processing // // Revision 1.123 2007/06/23 00:04:14 ivan // Update copyright notices to include current year (2007) // // Revision 1.122 2007/02/27 21:59:32 kleonard // PR# misc/87 startup messages fix completion // // Revision 1.121 2007/01/13 07:29:22 bernard // backout ccmask // // Revision 1.120 2007/01/12 16:43:44 bernard // ccmask phase 1 // // Revision 1.119 2006/12/08 09:43:28 jj // Add CVS message log // #include "hstdinc.h" #define _IMPL_C_ #define _HENGINE_DLL_ #include "hercules.h" #include "opcode.h" #include "devtype.h" #include "herc_getopt.h" #include "hostinfo.h" #include "history.h" /* (delayed_exit function defined in config.c) */ extern void delayed_exit (int exit_code); /* forward define process_script_file (ISW20030220-3) */ int process_script_file(char *,int); static LOGCALLBACK log_callback=NULL; /*-------------------------------------------------------------------*/ /* Register a LOG callback */ /*-------------------------------------------------------------------*/ DLL_EXPORT void registerLogCallback(LOGCALLBACK lcb) { log_callback=lcb; } /*-------------------------------------------------------------------*/ /* Signal handler for SIGINT signal */ /*-------------------------------------------------------------------*/ static void sigint_handler (int signo) { // logmsg ("config: sigint handler entered for thread %lu\n",/*debug*/ // thread_id()); /*debug*/ UNREFERENCED(signo); signal(SIGINT, sigint_handler); /* Ignore signal unless presented on console thread */ if ( !equal_threads( thread_id(), sysblk.cnsltid ) ) return; /* Exit if previous SIGINT request was not actioned */ if (sysblk.sigintreq) { /* Release the configuration */ release_config(); delayed_exit(1); } /* Set SIGINT request pending flag */ sysblk.sigintreq = 1; /* Activate instruction stepping */ sysblk.inststep = 1; SET_IC_TRACE; return; } /* end function sigint_handler */ #if !defined(NO_SIGABEND_HANDLER) static void *watchdog_thread(void *arg) { S64 savecount[MAX_CPU_ENGINES]; int i; UNREFERENCED(arg); /* Set watchdog priority just below cpu priority such that it will not invalidly detect an inoperable cpu */ if(sysblk.cpuprio >= 0) setpriority(PRIO_PROCESS, 0, sysblk.cpuprio+1); for (i = 0; i < MAX_CPU_ENGINES; i ++) savecount[i] = -1; while(!sysblk.shutdown) { for (i = 0; i < MAX_CPU; i++) { // obtain_lock (&sysblk.cpulock[i]); if (IS_CPU_ONLINE(i) && sysblk.regs[i]->cpustate == CPUSTATE_STARTED && (!WAITSTATE(&sysblk.regs[i]->psw) #if defined(_FEATURE_WAITSTATE_ASSIST) && !(sysblk.regs[i]->sie_active && WAITSTATE(&sysblk.regs[i]->guestregs->psw)) #endif )) { /* If the cpu is running but not executing instructions then it must be malfunctioning */ if((INSTCOUNT(sysblk.regs[i]) == (U64)savecount[i]) && !HDC1(debug_watchdog_signal, sysblk.regs[i]) ) { /* Send signal to looping CPU */ signal_thread(sysblk.cputid[i], SIGUSR1); savecount[i] = -1; } else /* Save current instcount */ savecount[i] = INSTCOUNT(sysblk.regs[i]); } else /* mark savecount invalid as CPU not in running state */ savecount[i] = -1; // release_lock (&sysblk.cpulock[i]); } /* Sleep for 20 seconds */ SLEEP(20); } return NULL; } #endif /*!defined(NO_SIGABEND_HANDLER)*/ void *log_do_callback(void *dummy) { char *msgbuf; int msgcnt = -1,msgnum; UNREFERENCED(dummy); while(msgcnt) { if((msgcnt = log_read(&msgbuf, &msgnum, LOG_BLOCK))) { log_callback(msgbuf,msgcnt); } } return(NULL); } DLL_EXPORT COMMANDHANDLER getCommandHandler(void) { return(panel_command); } /*-------------------------------------------------------------------*/ /* Process .RC file thread */ /*-------------------------------------------------------------------*/ void* process_rc_file (void* dummy) { char *rcname; /* hercules.rc name pointer */ int is_default_rc = 0; /* 1 == default name used */ int numcpu = 0; /* #of ONLINE & STOPPED CPUs */ int i; /* (work) */ UNREFERENCED(dummy); /* Wait for all installed/configured CPUs to come ONLINE and enter the STOPPED state */ OBTAIN_INTLOCK(NULL); for (;;) { numcpu = 0; for (i = 0; i < MAX_CPU_ENGINES; i++) if (IS_CPU_ONLINE(i) && CPUSTATE_STOPPED == sysblk.regs[i]->cpustate) numcpu++; if (numcpu == sysblk.numcpu) break; RELEASE_INTLOCK(NULL); usleep( 10 * 1000 ); OBTAIN_INTLOCK(NULL); } RELEASE_INTLOCK(NULL); /* Wait for panel thread to engage */ while (!sysblk.panel_init) usleep( 10 * 1000 ); /* Obtain the name of the hercules.rc file or default */ if (!(rcname = getenv("HERCULES_RC"))) { rcname = "hercules.rc"; is_default_rc = 1; } #if defined(OPTION_HAO) /* Initialize the Hercules Automatic Operator */ hao_initialize(); #endif /* defined(OPTION_HAO) */ /* Run the script processor for this file */ if (process_script_file(rcname,1) != 0) if (ENOENT == errno) if (!is_default_rc) logmsg(_("HHCPN995E .RC file \"%s\" not found.\n"), rcname); // (else error message already issued) return NULL; } /*-------------------------------------------------------------------*/ /* IMPL main entry point */ /*-------------------------------------------------------------------*/ DLL_EXPORT int impl(int argc, char *argv[]) { char *cfgfile; /* -> Configuration filename */ int c; /* Work area for getopt */ int arg_error = 0; /* 1=Invalid arguments */ char *msgbuf; /* */ int msgnum; /* */ int msgcnt; /* */ TID rctid; /* RC file thread identifier */ TID logcbtid; /* RC file thread identifier */ SET_THREAD_NAME("impl"); #if defined(FISH_HANG) /* "FishHang" debugs lock/cond/threading logic. Thus it must * be initialized BEFORE any lock/cond/threads are created. */ FishHangInit(__FILE__,__LINE__); #endif /* Initialize 'hostinfo' BEFORE display_version is called */ init_hostinfo( &hostinfo ); #ifdef _MSVC_ /* Initialize sockets package */ VERIFY( socket_init() == 0 ); #endif /* Ensure hdl_shut is called in case of shutdown hdl_shut will ensure entries are only called once */ atexit(hdl_shut); set_codepage(NULL); /* Clear the system configuration block */ memset (&sysblk, 0, sizeof(SYSBLK)); /* Save TOD of when we were first IMPL'ed */ time( &sysblk.impltime ); #ifdef OPTION_MSGHLD /* Set the default timeout value */ sysblk.keep_timeout_secs = 120; #endif /* Initialize thread creation attributes so all of hercules can use them at any time when they need to create_thread */ initialize_detach_attr (DETACHED); initialize_join_attr (JOINABLE); /* Copy length for regs */ sysblk.regs_copy_len = (int)((uintptr_t)&sysblk.dummyregs.regs_copy_end - (uintptr_t)&sysblk.dummyregs); /* Set the daemon_mode flag indicating whether we running in background/daemon mode or not (meaning both stdout/stderr are redirected to a non-tty device). Note that this flag needs to be set before logger_init gets called since the logger_logfile_write function relies on its setting. */ sysblk.daemon_mode = !isatty(STDERR_FILENO) && !isatty(STDOUT_FILENO); /* Initialize the logmsg pipe and associated logger thread. This causes all subsequent logmsg's to be redirected to the logger facility for handling by virtue of stdout/stderr being redirected to the logger facility. */ logger_init(); /* Now display the version information again after logger_init has been called so that either the panel display thread or the external gui can see the version which was previously possibly only displayed to the actual physical screen the first time we did it further above (depending on whether we're running in daemon_mode (external gui mode) or not). This it the call that the panel thread or the one the external gui actually "sees". The first call further above wasn't seen by either since it was issued before logger_init was called and thus got written directly to the physical screen whereas this one will be inter- cepted and handled by the logger facility thereby allowing the panel thread or external gui to "see" it and thus display it. */ display_version (stdout, "Hercules ", TRUE); #if defined(OPTION_DYNAMIC_LOAD) /* Initialize the hercules dynamic loader */ hdl_main(); #endif /* defined(OPTION_DYNAMIC_LOAD) */ #if defined(ENABLE_NLS) setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, HERC_LOCALEDIR); textdomain(PACKAGE); #endif #ifdef EXTERNALGUI /* Set GUI flag if specified as final argument */ if (argc >= 1 && strncmp(argv[argc-1],"EXTERNALGUI",11) == 0) { #if defined(OPTION_DYNAMIC_LOAD) if (hdl_load("dyngui",HDL_LOAD_DEFAULT) != 0) { usleep(10000); /* (give logger thread time to issue preceding HHCHD007E message) */ logmsg(_("HHCIN008S DYNGUI.DLL load failed; Hercules terminated.\n")); delayed_exit(1); } #endif /* defined(OPTION_DYNAMIC_LOAD) */ argc--; } #endif /*EXTERNALGUI*/ #if !defined(WIN32) && !defined(HAVE_STRERROR_R) strerror_r_init(); #endif /* Get name of configuration file or default to hercules.cnf */ if(!(cfgfile = getenv("HERCULES_CNF"))) cfgfile = "hercules.cnf"; /* Process the command line options */ while ((c = getopt(argc, argv, "f:p:l:db:")) != EOF) { switch (c) { case 'f': cfgfile = optarg; break; #if defined(OPTION_DYNAMIC_LOAD) case 'p': if(optarg) hdl_setpath(strdup(optarg)); break; case 'l': { char *dllname, *strtok_str; for(dllname = strtok_r(optarg,", ",&strtok_str); dllname; dllname = strtok_r(NULL,", ",&strtok_str)) hdl_load(dllname, HDL_LOAD_DEFAULT); } break; #endif /* defined(OPTION_DYNAMIC_LOAD) */ case 'b': sysblk.logofile=optarg; break; case 'd': sysblk.daemon_mode = 1; break; default: arg_error = 1; } /* end switch(c) */ } /* end while */ if (optind < argc) arg_error = 1; /* Terminate if invalid arguments were detected */ if (arg_error) { logmsg("usage: %s [-f config-filename] [-d] [-b logo-filename]" #if defined(OPTION_DYNAMIC_LOAD) " [-p dyn-load-dir] [[-l dynmod-to-load]...]" #endif /* defined(OPTION_DYNAMIC_LOAD) */ " [> logfile]\n", argv[0]); delayed_exit(1); } /* Register the SIGINT handler */ if ( signal (SIGINT, sigint_handler) == SIG_ERR ) { logmsg(_("HHCIN001S Cannot register SIGINT handler: %s\n"), strerror(errno)); delayed_exit(1); } #if defined(HAVE_DECL_SIGPIPE) && HAVE_DECL_SIGPIPE /* Ignore the SIGPIPE signal, otherwise Hercules may terminate with Broken Pipe error if the printer driver writes to a closed pipe */ if ( signal (SIGPIPE, SIG_IGN) == SIG_ERR ) { logmsg(_("HHCIN002E Cannot suppress SIGPIPE signal: %s\n"), strerror(errno)); } #endif #if defined( OPTION_WAKEUP_SELECT_VIA_PIPE ) { int fds[2]; initialize_lock(&sysblk.cnslpipe_lock); initialize_lock(&sysblk.sockpipe_lock); sysblk.cnslpipe_flag=0; sysblk.sockpipe_flag=0; VERIFY( create_pipe(fds) >= 0 ); sysblk.cnslwpipe=fds[1]; sysblk.cnslrpipe=fds[0]; VERIFY( create_pipe(fds) >= 0 ); sysblk.sockwpipe=fds[1]; sysblk.sockrpipe=fds[0]; } #endif // defined( OPTION_WAKEUP_SELECT_VIA_PIPE ) #if !defined(NO_SIGABEND_HANDLER) { struct sigaction sa; sa.sa_sigaction = (void*)&sigabend_handler; #ifdef SA_NODEFER sa.sa_flags = SA_NODEFER; #else sa.sa_flags = 0; #endif if( sigaction(SIGILL, &sa, NULL) || sigaction(SIGFPE, &sa, NULL) || sigaction(SIGSEGV, &sa, NULL) || sigaction(SIGBUS, &sa, NULL) || sigaction(SIGUSR1, &sa, NULL) || sigaction(SIGUSR2, &sa, NULL) ) { logmsg(_("HHCIN003S Cannot register SIGILL/FPE/SEGV/BUS/USR " "handler: %s\n"), strerror(errno)); delayed_exit(1); } } #endif /*!defined(NO_SIGABEND_HANDLER)*/ /* Build system configuration */ build_config (cfgfile); /* System initialisation time */ sysblk.todstart = hw_clock() << 8; #ifdef OPTION_MIPS_COUNTING /* Initialize "maxrates" command reporting intervals */ curr_int_start_time = time( NULL ); prev_int_start_time = curr_int_start_time; #endif #if !defined(NO_SIGABEND_HANDLER) /* Start the watchdog */ if ( create_thread (&sysblk.wdtid, DETACHED, watchdog_thread, NULL, "watchdog_thread") ) { logmsg(_("HHCIN004S Cannot create watchdog thread: %s\n"), strerror(errno)); delayed_exit(1); } #endif /*!defined(NO_SIGABEND_HANDLER)*/ #ifdef OPTION_SHARED_DEVICES /* Start the shared server */ if (sysblk.shrdport) if ( create_thread (&sysblk.shrdtid, DETACHED, shared_server, NULL, "shared_server") ) { logmsg(_("HHCIN006S Cannot create shared_server thread: %s\n"), strerror(errno)); delayed_exit(1); } /* Retry pending connections */ { DEVBLK *dev; TID tid; for (dev = sysblk.firstdev; dev != NULL; dev = dev->nextdev) if (dev->connecting) if ( create_thread (&tid, DETACHED, *dev->hnd->init, dev, "device connecting thread") ) { logmsg(_("HHCIN007S Cannot create %4.4X connection thread: %s\n"), dev->devnum, strerror(errno)); delayed_exit(1); } } #endif /* Start up the RC file processing thread */ create_thread(&rctid,DETACHED, process_rc_file,NULL,"process_rc_file"); if(log_callback) { // 'herclin' called us. IT'S in charge. Create its requested // logmsg intercept callback function and return back to it. create_thread(&logcbtid,DETACHED, log_do_callback,NULL,"log_do_callback"); return(0); } //--------------------------------------------------------------- // The below functions will not return until Hercules is shutdown //--------------------------------------------------------------- /* Activate the control panel */ if(!sysblk.daemon_mode) panel_display (); else { #if defined(OPTION_DYNAMIC_LOAD) if(daemon_task) daemon_task (); else #endif /* defined(OPTION_DYNAMIC_LOAD) */ { /* Tell RC file and HAO threads they may now proceed */ sysblk.panel_init = 1; /* Retrieve messages from logger and write to stderr */ while (1) if((msgcnt = log_read(&msgbuf, &msgnum, LOG_BLOCK))) if(isatty(STDERR_FILENO)) fwrite(msgbuf,msgcnt,1,stderr); } } // ----------------------------------------------------- // *** Hercules has been shutdown (PAST tense) *** // ----------------------------------------------------- ASSERT( sysblk.shutdown ); // (why else would we be here?!) #if defined(FISH_HANG) FishHangAtExit(); #endif #ifdef _MSVC_ socket_deinit(); #endif #ifdef DEBUG fprintf(stdout, _("IMPL EXIT\n")); #endif fprintf(stdout, _("HHCIN099I Hercules terminated\n")); fflush(stdout); usleep(10000); return 0; } /* end function main */ /*-------------------------------------------------------------------*/ /* System cleanup */ /*-------------------------------------------------------------------*/ DLL_EXPORT void system_cleanup (void) { // logmsg("HHCIN950I Begin system cleanup\n"); /* Currently only called by hdlmain,c's HDL_FINAL_SECTION after the main 'hercules' module has been unloaded, but that could change at some time in the future. The above and below logmsg's are commented out since this function currently doesn't do anything yet. Once it DOES something, they should be uncommented. */ // logmsg("HHCIN959I System cleanup complete\n"); } hercules-3.07/inline.h000644 000765 000765 00000076374 11143760544 016420 0ustar00jmaynardjmaynard000000 000000 /* INLINE.H (c) Copyright Jan Jaeger, 2000-2009 */ /* Inline function definitions */ // $Id: inline.h 5126 2009-01-23 13:05:56Z bernard $ /* Original author Roger Bowler, 1999 */ /* Interpretive Execution - (c) Copyright Jan Jaeger, 1999-2009 */ /* z/Architecture support - (c) Copyright Jan Jaeger, 1999-2009 */ /* Storage protection override fix Jan Jaeger 31/08/00 */ /* ESAME low-address protection v208d Roger Bowler 20/01/01 */ /* ESAME subspace replacement v208e Roger Bowler 27/01/01 */ /* Multiply/Divide Logical instructions Vic Cross 13/02/2001 */ // $Log$ // Revision 1.49 2007/06/23 00:04:14 ivan // Update copyright notices to include current year (2007) // // Revision 1.48 2007/03/20 22:28:52 gsmith // Use non-concurrent load for fetch_doubleword_absolute on 32bit hosts // // Revision 1.47 2007/03/07 15:36:56 ivan // Fix explicit store protection check for SIE'd guests // // Revision 1.46 2007/01/04 23:12:04 gsmith // remove thunk calls for program_interrupt // // Revision 1.45 2006/12/08 09:43:28 jj // Add CVS message log // // #define INLINE_STORE_FETCH_ADDR_CHECK #if defined(FEATURE_DUAL_ADDRESS_SPACE) _DAT_C_STATIC U16 ARCH_DEP(translate_asn) (U16 asn, REGS *regs, U32 *asteo, U32 aste[]); _DAT_C_STATIC int ARCH_DEP(authorize_asn) (U16 ax, U32 aste[], int atemask, REGS *regs); #endif #if defined(FEATURE_ACCESS_REGISTERS) _DAT_C_STATIC U16 ARCH_DEP(translate_alet) (U32 alet, U16 eax, int acctype, REGS *regs, U32 *asteo, U32 aste[]); _DAT_C_STATIC void ARCH_DEP(purge_alb_all) (); _DAT_C_STATIC void ARCH_DEP(purge_alb) (REGS *regs); #endif _DAT_C_STATIC int ARCH_DEP(translate_addr) (VADR vaddr, int arn, REGS *regs, int acctype); _DAT_C_STATIC void ARCH_DEP(purge_tlb_all) (); _DAT_C_STATIC void ARCH_DEP(purge_tlb) (REGS *regs); _DAT_C_STATIC void ARCH_DEP(purge_tlbe_all) (RADR pfra); _DAT_C_STATIC void ARCH_DEP(purge_tlbe) (REGS *regs, RADR pfra); _DAT_C_STATIC void ARCH_DEP(invalidate_tlb) (REGS *regs, BYTE mask); #if ARCH_MODE == ARCH_390 && defined(_900) _DAT_C_STATIC void z900_invalidate_tlb (REGS *regs, BYTE mask); #endif _DAT_C_STATIC void ARCH_DEP(invalidate_tlbe) (REGS *regs, BYTE *main); _DAT_C_STATIC void ARCH_DEP(invalidate_pte) (BYTE ibyte, int r1, int r2, REGS *regs); _LOGICAL_C_STATIC BYTE *ARCH_DEP(logical_to_main) (VADR addr, int arn, REGS *regs, int acctype, BYTE akey); #if defined(_FEATURE_SIE) && ARCH_MODE != ARCH_900 _LOGICAL_C_STATIC BYTE *s390_logical_to_main (U32 addr, int arn, REGS *regs, int acctype, BYTE akey); _DAT_C_STATIC int s390_translate_addr (U32 vaddr, int arn, REGS *regs, int acctype); #endif /*defined(_FEATURE_SIE)*/ #if defined(_FEATURE_ZSIE) _LOGICAL_C_STATIC BYTE *z900_logical_to_main (U64 addr, int arn, REGS *regs, int acctype, BYTE akey); _DAT_C_STATIC int z900_translate_addr (U64 vaddr, int arn, REGS *regs, int acctype); #endif /*defined(_FEATURE_ZSIE)*/ _VSTORE_C_STATIC void ARCH_DEP(vstorec) (void *src, BYTE len, VADR addr, int arn, REGS *regs); _VSTORE_C_STATIC void ARCH_DEP(vstoreb) (BYTE value, VADR addr, int arn, REGS *regs); _VSTORE_C_STATIC void ARCH_DEP(vstore2) (U16 value, VADR addr, int arn, REGS *regs); _VSTORE_C_STATIC void ARCH_DEP(vstore4) (U32 value, VADR addr, int arn, REGS *regs); _VSTORE_C_STATIC void ARCH_DEP(vstore8) (U64 value, VADR addr, int arn, REGS *regs); _VSTORE_C_STATIC void ARCH_DEP(vfetchc) (void *dest, BYTE len, VADR addr, int arn, REGS *regs); _VSTORE_C_STATIC BYTE ARCH_DEP(vfetchb) (VADR addr, int arn, REGS *regs); _VSTORE_C_STATIC U16 ARCH_DEP(vfetch2) (VADR addr, int arn, REGS *regs); _VSTORE_C_STATIC U32 ARCH_DEP(vfetch4) (VADR addr, int arn, REGS *regs); _VSTORE_C_STATIC U64 ARCH_DEP(vfetch8) (VADR addr, int arn, REGS *regs); _VSTORE_C_STATIC void ARCH_DEP(move_chars) (VADR addr1, int arn1, BYTE key1, VADR addr2, int arn2, BYTE key2, int len, REGS *regs); _VSTORE_C_STATIC void ARCH_DEP(validate_operand) (VADR addr, int arn, int len, int acctype, REGS *regs); _VFETCH_C_STATIC BYTE * ARCH_DEP(instfetch) (REGS *regs, int exec); #if defined(_FEATURE_SIE) && defined(_370) && !defined(_IEEE_C_) _VFETCH_C_STATIC BYTE * s370_instfetch (REGS *regs, int exec); #endif /*defined(_FEATURE_SIE)*/ #if defined(_FEATURE_ZSIE) && defined(_900) _VFETCH_C_STATIC BYTE * s390_instfetch (REGS *regs, int exec); #endif /*defined(_FEATURE_ZSIE)*/ #if !defined(_INLINE_H) #define _INLINE_H /*-------------------------------------------------------------------*/ /* Add two unsigned fullwords giving an unsigned fullword result */ /* and return the condition code for the AL or ALR instruction */ /*-------------------------------------------------------------------*/ static inline int add_logical(U32 *result, U32 op1, U32 op2) { *result = op1 + op2; return (*result == 0 ? 0 : 1) | (op1 > *result ? 2 : 0); } /* end function add_logical */ /*-------------------------------------------------------------------*/ /* Subtract two unsigned fullwords giving unsigned fullword result */ /* and return the condition code for the SL or SLR instruction */ /*-------------------------------------------------------------------*/ static inline int sub_logical(U32 *result, U32 op1, U32 op2) { *result = op1 - op2; return (*result == 0 ? 0 : 1) | (op1 < *result ? 0 : 2); } /* end function sub_logical */ /*-------------------------------------------------------------------*/ /* Add two signed fullwords giving a signed fullword result */ /* and return the condition code for the A or AR instruction */ /*-------------------------------------------------------------------*/ static inline int add_signed(U32 *result, U32 op1, U32 op2) { *result = (S32)op1 + (S32)op2; return ((S32)*result > 0) ? ((S32)op1 < 0 && (S32)op2 < 0) ? 3 : 2 : ((S32)*result < 0) ? ((S32)op1 >= 0 && (S32)op2 >= 0) ? 3 : 1 : ((S32)op1 < 0 && (S32)op2 < 0) ? 3 : 0; /* return (((S32)op1 < 0 && (S32)op2 < 0 && (S32)*result >= 0) || ((S32)op1 >= 0 && (S32)op2 >= 0 && (S32)*result < 0)) ? 3 : (S32)*result < 0 ? 1 : (S32)*result > 0 ? 2 : 0; */ } /* end function add_signed */ /*-------------------------------------------------------------------*/ /* Subtract two signed fullwords giving a signed fullword result */ /* and return the condition code for the S or SR instruction */ /*-------------------------------------------------------------------*/ static inline int sub_signed(U32 *result, U32 op1, U32 op2) { *result = (S32)op1 - (S32)op2; return ((S32)*result > 0) ? ((S32)op1 < 0 && (S32)op2 >= 0) ? 3 : 2 : ((S32)*result < 0) ? ((S32)op1 >= 0 && (S32)op2 < 0) ? 3 : 1 : ((S32)op1 < 0 && (S32)op2 >= 0) ? 3 : 0; /* return (((S32)op1 < 0 && (S32)op2 >= 0 && (S32)*result >= 0) || ((S32)op1 >= 0 && (S32)op2 < 0 && (S32)*result < 0)) ? 3 : (S32)*result < 0 ? 1 : (S32)*result > 0 ? 2 : 0; */ } /* end function sub_signed */ /*-------------------------------------------------------------------*/ /* Multiply two signed fullwords giving a signed doubleword result */ /*-------------------------------------------------------------------*/ static inline void mul_signed ( U32 *resulthi, U32 *resultlo, U32 op1, U32 op2 ) { S64 r; r = (S64)(S32)op1 * (S32)op2; *resulthi = (U32)((U64)r >> 32); *resultlo = (U32)((U64)r & 0xFFFFFFFF); } /* end function mul_signed */ /*-------------------------------------------------------------------*/ /* Divide a signed doubleword dividend by a signed fullword divisor */ /* giving a signed fullword remainder and a signed fullword quotient.*/ /* Returns 0 if successful, 1 if divide overflow. */ /*-------------------------------------------------------------------*/ static inline int div_signed ( U32 *remainder, U32 *quotient, U32 dividendhi, U32 dividendlo, U32 divisor ) { U64 dividend; S64 quot, rem; if (divisor == 0) return 1; dividend = (U64)dividendhi << 32 | dividendlo; quot = (S64)dividend / (S32)divisor; rem = (S64)dividend % (S32)divisor; if (quot < -2147483648LL || quot > 2147483647LL) return 1; *quotient = (U32)quot; *remainder = (U32)rem; return 0; } /* end function div_signed */ /* * The following routines were moved from esame.c rev 1.139 21oct2005 */ /*-------------------------------------------------------------------*/ /* Add two unsigned doublewords giving an unsigned doubleword result */ /* and return the condition code for the ALG or ALGR instruction */ /*-------------------------------------------------------------------*/ static inline int add_logical_long(U64 *result, U64 op1, U64 op2) { *result = op1 + op2; return (*result == 0 ? 0 : 1) | (op1 > *result ? 2 : 0); } /* end function add_logical_long */ /*-------------------------------------------------------------------*/ /* Subtract unsigned doublewords giving unsigned doubleword result */ /* and return the condition code for the SLG or SLGR instruction */ /*-------------------------------------------------------------------*/ static inline int sub_logical_long(U64 *result, U64 op1, U64 op2) { *result = op1 - op2; return (*result == 0 ? 0 : 1) | (op1 < *result ? 0 : 2); } /* end function sub_logical_long */ /*-------------------------------------------------------------------*/ /* Add two signed doublewords giving a signed doubleword result */ /* and return the condition code for the AG or AGR instruction */ /*-------------------------------------------------------------------*/ static inline int add_signed_long(U64 *result, U64 op1, U64 op2) { *result = (S64)op1 + (S64)op2; return (((S64)op1 < 0 && (S64)op2 < 0 && (S64)*result >= 0) || ((S64)op1 >= 0 && (S64)op2 >= 0 && (S64)*result < 0)) ? 3 : (S64)*result < 0 ? 1 : (S64)*result > 0 ? 2 : 0; } /* end function add_signed_long */ /*-------------------------------------------------------------------*/ /* Subtract two signed doublewords giving signed doubleword result */ /* and return the condition code for the SG or SGR instruction */ /*-------------------------------------------------------------------*/ static inline int sub_signed_long(U64 *result, U64 op1, U64 op2) { *result = (S64)op1 - (S64)op2; return (((S64)op1 < 0 && (S64)op2 >= 0 && (S64)*result >= 0) || ((S64)op1 >= 0 && (S64)op2 < 0 && (S64)*result < 0)) ? 3 : (S64)*result < 0 ? 1 : (S64)*result > 0 ? 2 : 0; } /* end function sub_signed_long */ /*-------------------------------------------------------------------*/ /* Divide an unsigned 128-bit dividend by an unsigned 64-bit divisor */ /* giving unsigned 64-bit remainder and unsigned 64-bit quotient. */ /* Returns 0 if successful, 1 if divide overflow. */ /*-------------------------------------------------------------------*/ static inline int div_logical_long (U64 *rem, U64 *quot, U64 high, U64 lo, U64 d) { int i; *quot = 0; if (high >= d) return 1; for (i = 0; i < 64; i++) { int ovf; ovf = high >> 63; high = (high << 1) | (lo >> 63); lo <<= 1; *quot <<= 1; if (high >= d || ovf) { *quot += 1; high -= d; } } *rem = high; return 0; } /* end function div_logical_long */ /*-------------------------------------------------------------------*/ /* Multiply two unsigned doublewords giving unsigned 128-bit result */ /*-------------------------------------------------------------------*/ static inline int mult_logical_long (U64 *high, U64 *lo, U64 md, U64 mr) { int i; *high = 0; *lo = 0; for (i = 0; i < 64; i++) { U64 ovf; ovf = *high; if (md & 1) *high += mr; md >>= 1; *lo = (*lo >> 1) | (*high << 63); if(ovf > *high) *high = (*high >> 1) | 0x8000000000000000ULL; else *high >>= 1; } return 0; } /* end function mult_logical_long */ #endif /*!defined(_INLINE_H)*/ /*-------------------------------------------------------------------*/ /* Test for fetch protected storage location. */ /* */ /* Input: */ /* addr Logical address of storage location */ /* skey Storage key with fetch, reference, and change bits */ /* and one low-order zero appended */ /* akey Access key with 4 low-order zeroes appended */ /* regs Pointer to the CPU register context */ /* regs->dat.private 1=Location is in a private address space */ /* Return value: */ /* 1=Fetch protected, 0=Not fetch protected */ /*-------------------------------------------------------------------*/ static inline int ARCH_DEP(is_fetch_protected) (VADR addr, BYTE skey, BYTE akey, REGS *regs) { UNREFERENCED_370(addr); UNREFERENCED_370(regs); /* [3.4.1] Fetch is allowed if access key is zero, regardless of the storage key and fetch protection bit */ /* [3.4.1] Fetch protection prohibits fetch if storage key fetch protect bit is on and access key does not match storage key */ if (likely(akey == 0 || akey == (skey & STORKEY_KEY) || !(skey & STORKEY_FETCH))) return 0; #ifdef FEATURE_FETCH_PROTECTION_OVERRIDE /* [3.4.1.2] Fetch protection override allows fetch from first 2K of non-private address spaces if CR0 bit 6 is set */ if (addr < 2048 && (regs->CR(0) & CR0_FETCH_OVRD) && regs->dat.private == 0) return 0; #endif /*FEATURE_FETCH_PROTECTION_OVERRIDE*/ #ifdef FEATURE_STORAGE_PROTECTION_OVERRIDE /* [3.4.1.1] Storage protection override allows access to locations with storage key 9, regardless of the access key, provided that CR0 bit 7 is set */ if ((skey & STORKEY_KEY) == 0x90 && (regs->CR(0) & CR0_STORE_OVRD)) return 0; #endif /*FEATURE_STORAGE_PROTECTION_OVERRIDE*/ /* Return one if location is fetch protected */ return 1; } /* end function is_fetch_protected */ /*-------------------------------------------------------------------*/ /* Test for low-address protection. */ /* */ /* Input: */ /* addr Logical address of storage location */ /* regs Pointer to the CPU register context */ /* regs->dat.private 1=Location is in a private address space */ /* Return value: */ /* 1=Low-address protected, 0=Not low-address protected */ /*-------------------------------------------------------------------*/ static inline int ARCH_DEP(is_low_address_protected) (VADR addr, REGS *regs) { #if defined (FEATURE_ESAME) /* For ESAME, low-address protection applies to locations 0-511 (0000-01FF) and 4096-4607 (1000-11FF) */ if (addr & 0xFFFFFFFFFFFFEE00ULL) #else /*!defined(FEATURE_ESAME)*/ /* For S/370 and ESA/390, low-address protection applies to locations 0-511 only */ if (addr > 511) #endif /*!defined(FEATURE_ESAME)*/ return 0; /* Low-address protection applies only if the low-address protection control bit in control register 0 is set */ if ((regs->CR(0) & CR0_LOW_PROT) == 0) return 0; #if defined(_FEATURE_SIE) /* Host low-address protection is not applied to guest references to guest storage */ if (regs->sie_active) return 0; #endif /*defined(_FEATURE_SIE)*/ /* Low-address protection does not apply to private address spaces */ if (regs->dat.private) return 0; /* Return one if location is low-address protected */ return 1; } /* end function is_low_address_protected */ /*-------------------------------------------------------------------*/ /* Test for store protected storage location. */ /* */ /* Input: */ /* addr Logical address of storage location */ /* skey Storage key with fetch, reference, and change bits */ /* and one low-order zero appended */ /* akey Access key with 4 low-order zeroes appended */ /* regs Pointer to the CPU register context */ /* regs->dat.private 1=Location is in a private address space */ /* regs->dat.protect 1=Access list protected or page protected */ /* Return value: */ /* 1=Store protected, 0=Not store protected */ /*-------------------------------------------------------------------*/ static inline int ARCH_DEP(is_store_protected) (VADR addr, BYTE skey, BYTE akey, REGS *regs) { /* [3.4.4] Low-address protection prohibits stores into certain locations in the prefixed storage area of non-private address address spaces, if the low-address control bit in CR0 is set, regardless of the access key and storage key */ if (ARCH_DEP(is_low_address_protected) (addr, regs)) return 1; /* Access-list controlled protection prohibits all stores into the address space, and page protection prohibits all stores into the page, regardless of the access key and storage key */ if (regs->dat.protect) return 1; #if defined(_FEATURE_SIE) if(SIE_MODE(regs) && regs->hostregs->dat.protect) return 1; #endif /* [3.4.1] Store is allowed if access key is zero, regardless of the storage key */ if (akey == 0) return 0; #ifdef FEATURE_STORAGE_PROTECTION_OVERRIDE /* [3.4.1.1] Storage protection override allows access to locations with storage key 9, regardless of the access key, provided that CR0 bit 7 is set */ if ((skey & STORKEY_KEY) == 0x90 && (regs->CR(0) & CR0_STORE_OVRD)) return 0; #endif /*FEATURE_STORAGE_PROTECTION_OVERRIDE*/ /* [3.4.1] Store protection prohibits stores if the access key does not match the storage key */ if (akey != (skey & STORKEY_KEY)) return 1; /* Return zero if location is not store protected */ return 0; } /* end function is_store_protected */ /*-------------------------------------------------------------------*/ /* Return mainstor address of absolute address. */ /* The caller is assumed to have already checked that the absolute */ /* address is within the limit of main storage. */ /*-------------------------------------------------------------------*/ #if defined(INLINE_STORE_FETCH_ADDR_CHECK) static inline BYTE *ARCH_DEP(fetch_main_absolute) (RADR addr, REGS *regs, int len) #else static inline BYTE *ARCH_DEP(fetch_main_absolute) (RADR addr, REGS *regs) #endif { #if defined(INLINE_STORE_FETCH_ADDR_CHECK) if(addr > regs->mainlim - len) regs->program_interrupt (regs, PGM_ADDRESSING_EXCEPTION); #endif /*defined(INLINE_STORE_FETCH_ADDR_CHECK)*/ SIE_TRANSLATE(&addr, ACCTYPE_READ, regs); /* Set the main storage reference bit */ STORAGE_KEY(addr, regs) |= STORKEY_REF; /* Return absolute storage mainstor address */ return (regs->mainstor + addr); } /* end function fetch_main_absolute */ /*-------------------------------------------------------------------*/ /* Fetch a doubleword from absolute storage. */ /* The caller is assumed to have already checked that the absolute */ /* address is within the limit of main storage. */ /* All bytes of the word are fetched concurrently as observed by */ /* other CPUs. The doubleword is first fetched as an integer, then */ /* the bytes are reversed into host byte order if necessary. */ /*-------------------------------------------------------------------*/ static inline U64 ARCH_DEP(fetch_doubleword_absolute) (RADR addr, REGS *regs) { // The change below affects 32 bit hosts that use something like // cmpxchg8b to fetch the doubleword concurrently. // This routine is mainly called by DAT in 64 bit guest mode // to access DAT-related values. In most `well-behaved' OS's, // other CPUs should not be interfering with these values #if !defined(OPTION_STRICT_ALIGNMENT) return CSWAP64(*(U64 *)FETCH_MAIN_ABSOLUTE(addr, regs, 8)); #else return fetch_dw(FETCH_MAIN_ABSOLUTE(addr, regs, 8)); #endif } /* end function fetch_doubleword_absolute */ /*-------------------------------------------------------------------*/ /* Fetch a fullword from absolute storage. */ /* The caller is assumed to have already checked that the absolute */ /* address is within the limit of main storage. */ /* All bytes of the word are fetched concurrently as observed by */ /* other CPUs. The fullword is first fetched as an integer, then */ /* the bytes are reversed into host byte order if necessary. */ /*-------------------------------------------------------------------*/ static inline U32 ARCH_DEP(fetch_fullword_absolute) (RADR addr, REGS *regs) { return fetch_fw(FETCH_MAIN_ABSOLUTE(addr, regs, 4)); } /* end function fetch_fullword_absolute */ /*-------------------------------------------------------------------*/ /* Fetch a halfword from absolute storage. */ /* The caller is assumed to have already checked that the absolute */ /* address is within the limit of main storage. */ /* All bytes of the halfword are fetched concurrently as observed by */ /* other CPUs. The halfword is first fetched as an integer, then */ /* the bytes are reversed into host byte order if necessary. */ /*-------------------------------------------------------------------*/ static inline U16 ARCH_DEP(fetch_halfword_absolute) (RADR addr, REGS *regs) { return fetch_hw(FETCH_MAIN_ABSOLUTE(addr, regs, 2)); } /* end function fetch_halfword_absolute */ /*-------------------------------------------------------------------*/ /* Store doubleword into absolute storage. */ /* All bytes of the word are stored concurrently as observed by */ /* other CPUs. The bytes of the word are reversed if necessary */ /* and the word is then stored as an integer in absolute storage. */ /*-------------------------------------------------------------------*/ static inline void ARCH_DEP(store_doubleword_absolute) (U64 value, RADR addr, REGS *regs) { #if defined(INLINE_STORE_FETCH_ADDR_CHECK) if(addr > regs->mainlim - 8) regs->program_interrupt (regs, PGM_ADDRESSING_EXCEPTION); #endif /*defined(INLINE_STORE_FETCH_ADDR_CHECK)*/ SIE_TRANSLATE(&addr, ACCTYPE_WRITE, regs); /* Set the main storage reference and change bits */ STORAGE_KEY(addr, regs) |= (STORKEY_REF | STORKEY_CHANGE); /* Store the doubleword into absolute storage */ store_dw(regs->mainstor + addr, value); } /* end function store_doubleword_absolute */ /*-------------------------------------------------------------------*/ /* Store a fullword into absolute storage. */ /* All bytes of the word are stored concurrently as observed by */ /* other CPUs. The bytes of the word are reversed if necessary */ /* and the word is then stored as an integer in absolute storage. */ /*-------------------------------------------------------------------*/ static inline void ARCH_DEP(store_fullword_absolute) (U32 value, RADR addr, REGS *regs) { #if defined(INLINE_STORE_FETCH_ADDR_CHECK) if(addr > regs->mainlim - 4) regs->program_interrupt (regs, PGM_ADDRESSING_EXCEPTION); #endif /*defined(INLINE_STORE_FETCH_ADDR_CHECK)*/ SIE_TRANSLATE(&addr, ACCTYPE_WRITE, regs); /* Set the main storage reference and change bits */ STORAGE_KEY(addr, regs) |= (STORKEY_REF | STORKEY_CHANGE); /* Store the fullword into absolute storage */ store_fw(regs->mainstor + addr, value); } /* end function store_fullword_absolute */ /*-------------------------------------------------------------------*/ /* Perform subspace replacement */ /* */ /* Input: */ /* std Original segment table designation (STD) or ASCE */ /* asteo ASTE origin obtained by ASN translation */ /* xcode Pointer to field to receive exception code, or NULL */ /* regs Pointer to the CPU register context */ /* */ /* Output: */ /* xcode Exception code or zero (if xcode is not NULL) */ /* */ /* Return value: */ /* On successful completion, the exception code field (if not */ /* NULL) is set to zero, and the function return value is the */ /* STD resulting from subspace replacement, or is the original */ /* STD if subspace replacement is not applicable. */ /* */ /* Operation: */ /* If the ASF control is enabled, and the STD or ASCE is a */ /* member of a subspace-group (bit 22 is one), and the */ /* dispatchable unit is subspace active (DUCT word 1 bit 0 is */ /* one), and the ASTE obtained by ASN translation is the ASTE */ /* for the base space of the dispatchable unit, then the STD */ /* or ASCE is replaced (except for the event control bits) by */ /* the STD or ASCE from the ASTE for the subspace in which the */ /* dispatchable unit last had control; otherwise the STD or */ /* ASCE remains unchanged. */ /* */ /* Error conditions: */ /* If an ASTE validity exception or ASTE sequence exception */ /* occurs, and the xcode parameter is a non-NULL pointer, */ /* then the exception code is returned in the xcode field */ /* and the function return value is zero. */ /* For all other error conditions a program check is generated */ /* and the function does not return. */ /* */ /*-------------------------------------------------------------------*/ static inline RADR ARCH_DEP(subspace_replace) (RADR std, U32 asteo, U16 *xcode, REGS *regs) { U32 ducto; /* DUCT origin */ U32 duct0; /* DUCT word 0 */ U32 duct1; /* DUCT word 1 */ U32 duct3; /* DUCT word 3 */ U32 ssasteo; /* Subspace ASTE origin */ U32 ssaste[16]; /* Subspace ASTE */ BYTE *p; /* Mainstor pointer */ /* Clear the exception code field, if provided */ if (xcode != NULL) *xcode = 0; /* Return the original STD unchanged if the address-space function control (CR0 bit 15) is zero, or if the subspace-group control (bit 22 of the STD) is zero */ if (!ASF_ENABLED(regs) || (std & SSGROUP_BIT) == 0) return std; /* Load the DUCT origin address */ ducto = regs->CR(2) & CR2_DUCTO; ducto = APPLY_PREFIXING (ducto, regs->PX); /* Program check if DUCT origin address is invalid */ if (ducto > regs->mainlim) regs->program_interrupt (regs, PGM_ADDRESSING_EXCEPTION); /* Fetch DUCT words 0, 1, and 3 from absolute storage (note: the DUCT cannot cross a page boundary) */ p = FETCH_MAIN_ABSOLUTE(ducto, regs, 16); duct0 = fetch_fw(p); duct1 = fetch_fw(p+4); duct3 = fetch_fw(p+12); /* Return the original STD unchanged if the dispatchable unit is not subspace active or if the ASTE obtained by ASN translation is not the same as the base ASTE for the dispatchable unit */ if ((duct1 & DUCT1_SA) == 0 || asteo != (duct0 & DUCT0_BASTEO)) return std; /* Load the subspace ASTE origin from the DUCT */ ssasteo = duct1 & DUCT1_SSASTEO; ssasteo = APPLY_PREFIXING (ssasteo, regs->PX); /* Program check if ASTE origin address is invalid */ if (ssasteo > regs->mainlim) regs->program_interrupt (regs, PGM_ADDRESSING_EXCEPTION); /* Fetch subspace ASTE words 0, 2, 3, and 5 from absolute storage (note: the ASTE cannot cross a page boundary) */ p = FETCH_MAIN_ABSOLUTE(ssasteo, regs, 24); ssaste[0] = fetch_fw(p); ssaste[2] = fetch_fw(p+8); #if defined(FEATURE_ESAME) ssaste[3] = fetch_fw(p+12); #endif /*defined(FEATURE_ESAME)*/ ssaste[5] = fetch_fw(p+20); /* ASTE validity exception if subspace ASTE invalid bit is one */ if (ssaste[0] & ASTE0_INVALID) { regs->excarid = 0; if (xcode == NULL) regs->program_interrupt (regs, PGM_ASTE_VALIDITY_EXCEPTION); else *xcode = PGM_ASTE_VALIDITY_EXCEPTION; return 0; } /* ASTE sequence exception if the subspace ASTE sequence number does not match the sequence number in the DUCT */ if ((ssaste[5] & ASTE5_ASTESN) != (duct3 & DUCT3_SSASTESN)) { regs->excarid = 0; if (xcode == NULL) regs->program_interrupt (regs, PGM_ASTE_SEQUENCE_EXCEPTION); else *xcode = PGM_ASTE_SEQUENCE_EXCEPTION; return 0; } /* Replace the STD or ASCE with the subspace ASTE STD or ASCE, except for the space switch event bit and the storage alteration event bit, which remain unchanged */ std &= (SSEVENT_BIT | SAEVENT_BIT); std |= (ASTE_AS_DESIGNATOR(ssaste) & ~((RADR)(SSEVENT_BIT | SAEVENT_BIT))); /* Return the STD resulting from subspace replacement */ return std; } /* end function subspace_replace */ #include "dat.h" #include "vstore.h" /* end of INLINE.H */ hercules-3.07/INSTALL000644 000765 000765 00000017227 11143760542 016010 0ustar00jmaynardjmaynard000000 000000 Basic Installation ================== These are generic installation instructions. The `configure' shell script attempts to guess correct values for various system-dependent variables used during compilation. It uses those values to create a `Makefile' in each directory of the package. It may also create one or more `.h' files containing system-dependent definitions. Finally, it creates a shell script `config.status' that you can run in the future to recreate the current configuration, a file `config.cache' that saves the results of its tests to speed up reconfiguring, and a file `config.log' containing compiler output (useful mainly for debugging `configure'). If you need to do unusual things to compile the package, please try to figure out how `configure' could check whether to do them, and mail diffs or instructions to the address given in the `README' so they can be considered for the next release. If at some point `config.cache' contains results you don't want to keep, you may remove or edit it. The file `configure.in' is used to create `configure' by a program called `autoconf'. You only need `configure.in' if you want to change it or regenerate `configure' using a newer version of `autoconf'. The simplest way to compile this package is: 1. `cd' to the directory containing the package's source code and type `./configure' to configure the package for your system. If you're using `csh' on an old version of System V, you might need to type `sh ./configure' instead to prevent `csh' from trying to execute `configure' itself. Running `configure' takes awhile. While running, it prints some messages telling which features it is checking for. 2. Type `make' to compile the package. 3. Optionally, type `make check' to run any self-tests that come with the package. 4. Type `make install' to install the programs and any data files and documentation. 5. You can remove the program binaries and object files from the source code directory by typing `make clean'. To also remove the files that `configure' created (so you can compile the package for a different kind of computer), type `make distclean'. There is also a `make maintainer-clean' target, but that is intended mainly for the package's developers. If you use it, you may have to get all sorts of other programs in order to regenerate files that came with the distribution. Compilers and Options ===================== Some systems require unusual options for compilation or linking that the `configure' script does not know about. You can give `configure' initial values for variables by setting them in the environment. Using a Bourne-compatible shell, you can do that on the command line like this: CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure Or on systems that have the `env' program, you can do it like this: env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure Compiling For Multiple Architectures ==================================== You can compile the package for more than one kind of computer at the same time, by placing the object files for each architecture in their own directory. To do this, you must use a version of `make' that supports the `VPATH' variable, such as GNU `make'. `cd' to the directory where you want the object files and executables to go and run the `configure' script. `configure' automatically checks for the source code in the directory that `configure' is in and in `..'. If you have to use a `make' that does not supports the `VPATH' variable, you have to compile the package for one architecture at a time in the source code directory. After you have installed the package for one architecture, use `make distclean' before reconfiguring for another architecture. Installation Names ================== By default, `make install' will install the package's files in `/usr/local/bin', `/usr/local/man', etc. You can specify an installation prefix other than `/usr/local' by giving `configure' the option `--prefix=PATH'. You can specify separate installation prefixes for architecture-specific files and architecture-independent files. If you give `configure' the option `--exec-prefix=PATH', the package will use PATH as the prefix for installing programs and libraries. Documentation and other data files will still use the regular prefix. In addition, if you use an unusual directory layout you can give options like `--bindir=PATH' to specify different values for particular kinds of files. Run `configure --help' for a list of the directories you can set and what kinds of files go in them. If the package supports it, you can cause programs to be installed with an extra prefix or suffix on their names by giving `configure' the option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. Optional Features ================= Some packages pay attention to `--enable-FEATURE' options to `configure', where FEATURE indicates an optional part of the package. They may also pay attention to `--with-PACKAGE' options, where PACKAGE is something like `gnu-as' or `x' (for the X Window System). The `README' should mention any `--enable-' and `--with-' options that the package recognizes. For packages that use the X Window System, `configure' can usually find the X include and library files automatically, but if it doesn't, you can use the `configure' options `--x-includes=DIR' and `--x-libraries=DIR' to specify their locations. Specifying the System Type ========================== There may be some features `configure' can not figure out automatically, but needs to determine by the type of host the package will run on. Usually `configure' can figure that out, but if it prints a message saying it can not guess the host type, give it the `--host=TYPE' option. TYPE can either be a short name for the system type, such as `sun4', or a canonical name with three fields: CPU-COMPANY-SYSTEM See the file `config.sub' for the possible values of each field. If `config.sub' isn't included in this package, then this package doesn't need to know the host type. If you are building compiler tools for cross-compiling, you can also use the `--target=TYPE' option to select the type of system they will produce code for and the `--build=TYPE' option to select the type of system on which you are compiling the package. Sharing Defaults ================ If you want to set default values for `configure' scripts to share, you can create a site shell script called `config.site' that gives default values for variables like `CC', `cache_file', and `prefix'. `configure' looks for `PREFIX/share/config.site' if it exists, then `PREFIX/etc/config.site' if it exists. Or, you can set the `CONFIG_SITE' environment variable to the location of the site script. A warning: not all `configure' scripts look for a site script. Operation Controls ================== `configure' recognizes the following options to control how it operates. `--cache-file=FILE' Use and save the results of the tests in FILE instead of `./config.cache'. Set FILE to `/dev/null' to disable caching, for debugging `configure'. `--help' Print a summary of the options to `configure', and exit. `--quiet' `--silent' `-q' Do not print messages saying which checks are being made. To suppress all normal output, redirect it to `/dev/null' (any error messages will still be shown). `--srcdir=DIR' Look for the package's source code in directory DIR. Usually `configure' can determine that directory automatically. `--version' Print the version of Autoconf used to generate the `configure' script, and exit. `configure' also accepts some other, not widely useful, options. hercules-3.07/io.c000644 000765 000765 00000113724 11157241226 015527 0ustar00jmaynardjmaynard000000 000000 /* IO.C (c) Copyright Roger Bowler, 1994-2009 */ /* ESA/390 CPU Emulator */ /* Interpretive Execution - (c) Copyright Jan Jaeger, 1999-2009 */ /* z/Architecture support - (c) Copyright Jan Jaeger, 1999-2009 */ // $Id: io.c 5242 2009-03-05 21:33:26Z jj $ /*-------------------------------------------------------------------*/ /* This module implements all I/O instructions of the */ /* S/370 and ESA/390 architectures, as described in the manuals */ /* GA22-7000-03 System/370 Principles of Operation */ /* SA22-7201-06 ESA/390 Principles of Operation */ /*-------------------------------------------------------------------*/ /*-------------------------------------------------------------------*/ /* Additional credits: */ /* STCPS and SCHM instructions by Jan Jaeger */ /* STCRW instruction by Jan Jaeger */ /* Instruction decode by macros - Jan Jaeger */ /* Instruction decode rework - Jan Jaeger */ /* Correct nullification of TIO and TSCH - Jan Jaeger */ /* Lock device during MSCH update - Jan Jaeger */ /* SIE support - Jan Jaeger */ /* SAL instruction added - Jan Jaeger */ /* RCHP instruction added - Jan Jaeger */ /* CONCS instruction added - Jan Jaeger */ /* DISCS instruction added - Jan Jaeger */ /* TPI fix - Jay Maynard, found by Greg Smith */ /* STCRW instruction nullification correction - Jan Jaeger */ /* I/O rate counter - Valery Pogonchenko */ /* 64-bit IDAW support - Roger Bowler v209 @IWZ*/ /*-------------------------------------------------------------------*/ // $Log$ // Revision 1.61 2007/06/23 00:04:14 ivan // Update copyright notices to include current year (2007) // // Revision 1.60 2007/01/13 07:23:42 bernard // backout ccmask // // Revision 1.59 2007/01/12 15:24:21 bernard // ccmask phase 1 // // Revision 1.58 2006/12/08 09:43:28 jj // Add CVS message log // #include "hstdinc.h" #if !defined(_HENGINE_DLL_) #define _HENGINE_DLL_ #endif #if !defined(_IO_C_) #define _IO_C_ #endif #include "hercules.h" #include "opcode.h" #include "inline.h" #undef PTIO #if defined(FEATURE_CHANNEL_SUBSYSTEM) #define PTIO(_class, _name) \ PTT(PTT_CL_ ## _class,_name,regs->GR_L(1),(U32)(effective_addr2 & 0xffffffff),regs->psw.IA_L) #else #define PTIO(_class, _name) \ PTT(PTT_CL_ ## _class,_name,(U32)(effective_addr2 & 0xffffffff),0,regs->psw.IA_L) #endif #if defined(FEATURE_CHANNEL_SUBSYSTEM) /*-------------------------------------------------------------------*/ /* B230 CSCH - Clear Subchannel [S] */ /*-------------------------------------------------------------------*/ DEF_INST(clear_subchannel) { int b2; /* Effective addr base */ VADR effective_addr2; /* Effective address */ DEVBLK *dev; /* -> device block */ S(inst, regs, b2, effective_addr2); PRIV_CHECK(regs); #if defined(_FEATURE_IO_ASSIST) if(SIE_STATNB(regs, EC0, IOA) && !regs->sie_pref) #endif SIE_INTERCEPT(regs); PTIO(IO,"CSCH"); /* Program check if the ssid including lcss is invalid */ SSID_CHECK(regs); /* Locate the device block for this subchannel */ dev = find_device_by_subchan (regs->GR_L(1)); /* Condition code 3 if subchannel does not exist, is not valid, or is not enabled */ if (dev == NULL || (dev->pmcw.flag5 & PMCW5_V) == 0 || (dev->pmcw.flag5 & PMCW5_E) == 0) { PTIO(ERR,"*CSCH"); #if defined(_FEATURE_IO_ASSIST) SIE_INTERCEPT(regs); #endif regs->psw.cc = 3; return; } /* Perform clear subchannel and set condition code zero */ clear_subchan (regs, dev); regs->psw.cc = 0; } /*-------------------------------------------------------------------*/ /* B231 HSCH - Halt Subchannel [S] */ /*-------------------------------------------------------------------*/ DEF_INST(halt_subchannel) { int b2; /* Effective addr base */ VADR effective_addr2; /* Effective address */ DEVBLK *dev; /* -> device block */ S(inst, regs, b2, effective_addr2); PRIV_CHECK(regs); #if defined(_FEATURE_IO_ASSIST) if(SIE_STATNB(regs, EC0, IOA) && !regs->sie_pref) #endif SIE_INTERCEPT(regs); PTIO(IO,"HSCH"); /* Program check if the ssid including lcss is invalid */ SSID_CHECK(regs); /* Locate the device block for this subchannel */ dev = find_device_by_subchan (regs->GR_L(1)); /* Condition code 3 if subchannel does not exist, is not valid, or is not enabled */ if (dev == NULL || (dev->pmcw.flag5 & PMCW5_V) == 0 || (dev->pmcw.flag5 & PMCW5_E) == 0) { PTIO(ERR,"*HSCH"); #if defined(_FEATURE_IO_ASSIST) SIE_INTERCEPT(regs); #endif regs->psw.cc = 3; return; } /* Perform halt subchannel and set condition code */ regs->psw.cc = halt_subchan (regs, dev); } /*-------------------------------------------------------------------*/ /* B232 MSCH - Modify Subchannel [S] */ /*-------------------------------------------------------------------*/ DEF_INST(modify_subchannel) { int b2; /* Effective addr base */ VADR effective_addr2; /* Effective address */ DEVBLK *dev; /* -> device block */ PMCW pmcw; /* Path management ctl word */ S(inst, regs, b2, effective_addr2); PRIV_CHECK(regs); SIE_INTERCEPT(regs); PTIO(IO,"MSCH"); FW_CHECK(effective_addr2, regs); /* Fetch the updated path management control word */ ARCH_DEP(vfetchc) ( &pmcw, sizeof(PMCW)-1, effective_addr2, b2, regs ); /* Program check if reserved bits are not zero */ if ((pmcw.flag4 & PMCW4_RESV) || (pmcw.flag5 & PMCW5_LM) == PMCW5_LM_RESV #if !defined(_FEATURE_IO_ASSIST) || (pmcw.flag4 & PMCW4_A) || (pmcw.zone != 0) || (pmcw.flag25 & PMCW25_VISC) || (pmcw.flag27 & PMCW27_I) #endif || (pmcw.flag26 != 0) || (pmcw.flag27 & PMCW27_RESV)) ARCH_DEP(program_interrupt) (regs, PGM_OPERAND_EXCEPTION); /* Program check if the ssid including lcss is invalid */ SSID_CHECK(regs); /* Locate the device block for this subchannel */ dev = find_device_by_subchan (regs->GR_L(1)); /* Condition code 3 if subchannel does not exist */ if (dev == NULL) { PTIO(ERR,"*MSCH"); regs->psw.cc = 3; return; } /* If the subchannel is invalid then return cc0 */ if (!(dev->pmcw.flag5 & PMCW5_V)) { PTIO(ERR,"*MSCH"); regs->psw.cc = 0; return; } /* Perform serialization and checkpoint-synchronization */ PERFORM_SERIALIZATION (regs); PERFORM_CHKPT_SYNC (regs); /* Obtain the device lock */ obtain_lock (&dev->lock); /* Condition code 1 if subchannel is status pending with other than intermediate status */ if ((dev->scsw.flag3 & SCSW3_SC_PEND) && !(dev->scsw.flag3 & SCSW3_SC_INTER)) { PTIO(ERR,"*MSCH"); regs->psw.cc = 1; release_lock (&dev->lock); return; } /* Condition code 2 if subchannel is busy */ if (dev->busy || IOPENDING(dev)) { PTIO(ERR,"*MSCH"); regs->psw.cc = 2; release_lock (&dev->lock); return; } /* Update the enabled (E), limit mode (LM), and measurement mode (MM), and multipath (D) bits */ dev->pmcw.flag5 &= ~(PMCW5_E | PMCW5_LM | PMCW5_MM | PMCW5_D); dev->pmcw.flag5 |= (pmcw.flag5 & (PMCW5_E | PMCW5_LM | PMCW5_MM | PMCW5_D)); /* Update the measurement block index */ memcpy (dev->pmcw.mbi, pmcw.mbi, sizeof(HWORD)); /* Update the interruption parameter */ memcpy (dev->pmcw.intparm, pmcw.intparm, sizeof(FWORD)); /* Update the ISC and A fields */ dev->pmcw.flag4 &= ~(PMCW4_ISC | PMCW4_A); dev->pmcw.flag4 |= (pmcw.flag4 & (PMCW4_ISC | PMCW4_A)); /* Update the path management (LPM and POM) fields */ dev->pmcw.lpm = pmcw.lpm; dev->pmcw.pom = pmcw.pom; /* Update zone, VISC, I and S bit */ dev->pmcw.zone = pmcw.zone; dev->pmcw.flag25 &= ~(PMCW25_VISC); dev->pmcw.flag25 |= (pmcw.flag25 & PMCW25_VISC); dev->pmcw.flag26 = pmcw.flag26; dev->pmcw.flag27 = pmcw.flag27; #if defined(_FEATURE_IO_ASSIST) /* Relate the device storage view to the requested zone */ { RADR mso, msl; mso = sysblk.zpb[dev->pmcw.zone].mso << 20; msl = (sysblk.zpb[dev->pmcw.zone].msl << 20) | 0xFFFFF; /* Ensure channel program checks on incorrect zone defs */ if(mso > (sysblk.mainsize-1) || msl > (sysblk.mainsize-1) || mso > msl) mso = msl = 0; dev->mainstor = &(sysblk.mainstor[mso]); dev->mainlim = msl - mso; dev->storkeys = &(STORAGE_KEY(mso, &sysblk)); } #endif /*defined(_FEATURE_IO_ASSIST)*/ /* Set device priority from the interruption subclass bits */ dev->priority = (dev->pmcw.flag4 & PMCW4_ISC) >> 3; release_lock (&dev->lock); /* Set condition code 0 */ regs->psw.cc = 0; } /*-------------------------------------------------------------------*/ /* B23B RCHP - Reset Channel Path [S] */ /*-------------------------------------------------------------------*/ DEF_INST(reset_channel_path) { int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ BYTE chpid; S(inst, regs, b2, effective_addr2); PRIV_CHECK(regs); SIE_INTERCEPT(regs); PTIO(IO,"RCHP"); /* Program check if reg 1 bits 0-23 not zero */ if(regs->GR_L(1) & 0xFFFFFF00) ARCH_DEP(program_interrupt) (regs, PGM_OPERAND_EXCEPTION); chpid = regs->GR_L(1) & 0xFF; if( !(regs->psw.cc = chp_reset(regs, chpid)) ) { OBTAIN_INTLOCK(regs); sysblk.chp_reset[chpid/32] |= 0x80000000 >> (chpid % 32); ON_IC_CHANRPT; WAKEUP_CPUS_MASK (sysblk.waiting_mask); RELEASE_INTLOCK(regs); } RETURN_INTCHECK(regs); } /*-------------------------------------------------------------------*/ /* B238 RSCH - Resume Subchannel [S] */ /*-------------------------------------------------------------------*/ DEF_INST(resume_subchannel) { int b2; /* Effective addr base */ VADR effective_addr2; /* Effective address */ DEVBLK *dev; /* -> device block */ S(inst, regs, b2, effective_addr2); PRIV_CHECK(regs); #if defined(_FEATURE_IO_ASSIST) if(SIE_STATNB(regs, EC0, IOA) && !regs->sie_pref) #endif SIE_INTERCEPT(regs); PTIO(IO,"RSCH"); /* Program check if the ssid including lcss is invalid */ SSID_CHECK(regs); /* Locate the device block for this subchannel */ dev = find_device_by_subchan (regs->GR_L(1)); /* Condition code 3 if subchannel does not exist, is not valid, or is not enabled */ if (dev == NULL || (dev->pmcw.flag5 & PMCW5_V) == 0 || (dev->pmcw.flag5 & PMCW5_E) == 0) { PTIO(ERR,"*RSCH"); #if defined(_FEATURE_IO_ASSIST) SIE_INTERCEPT(regs); #endif regs->psw.cc = 3; return; } /* Perform resume subchannel and set condition code */ regs->psw.cc = resume_subchan (regs, dev); regs->siocount++; } /*-------------------------------------------------------------------*/ /* B237 SAL - Set Address Limit [S] */ /*-------------------------------------------------------------------*/ DEF_INST(set_address_limit) { int b2; /* Effective addr base */ VADR effective_addr2; /* Effective address */ S(inst, regs, b2, effective_addr2); PRIV_CHECK(regs); SIE_INTERCEPT(regs); PTIO(IO,"SAL"); if(regs->GR_L(1) & 0x8000FFFF) ARCH_DEP(program_interrupt) (regs, PGM_OPERAND_EXCEPTION); else sysblk.addrlimval = regs->GR_L(1); } /*-------------------------------------------------------------------*/ /* B23C SCHM - Set Channel Monitor [S] */ /*-------------------------------------------------------------------*/ DEF_INST(set_channel_monitor) { int b2; /* Effective addr base */ VADR effective_addr2; /* Effective address */ S(inst, regs, b2, effective_addr2); PRIV_CHECK(regs); #if defined(_FEATURE_IO_ASSIST) if(SIE_STATNB(regs, EC0, IOA) && !regs->sie_pref) #endif SIE_INTERCEPT(regs); PTIO(IO,"SCHM"); /* Reserved bits in gpr1 must be zero */ if (regs->GR_L(1) & CHM_GPR1_RESV) ARCH_DEP(program_interrupt) (regs, PGM_OPERAND_EXCEPTION); /* Program check if M bit one and gpr2 address not on a 32 byte boundary or highorder bit set in ESA/390 mode */ if ((regs->GR_L(1) & CHM_GPR1_M) && (regs->GR_L(2) & CHM_GPR2_RESV)) ARCH_DEP(program_interrupt) (regs, PGM_OPERAND_EXCEPTION); #if defined(_FEATURE_IO_ASSIST) /* Virtual use of I/O Assist features must be intercepted */ if(SIE_MODE(regs) && ( (regs->GR_L(1) & CHM_GPR1_ZONE) || (regs->GR_L(1) & CHM_GPR1_A) )) SIE_INTERCEPT(regs); /* Zone must be a valid zone number */ if (((regs->GR_L(1) & CHM_GPR1_ZONE) >> 16) >= FEATURE_SIE_MAXZONES) ARCH_DEP(program_interrupt) (regs, PGM_OPERAND_EXCEPTION); if(regs->GR_L(1) & CHM_GPR1_A) #endif /*defined(_FEATURE_IO_ASSIST)*/ { /* Set the measurement block origin address */ if (regs->GR_L(1) & CHM_GPR1_M) { sysblk.mbo = regs->GR(2); sysblk.mbk = (regs->GR_L(1) & CHM_GPR1_MBK) >> 24; sysblk.mbm = 1; } else sysblk.mbm = 0; sysblk.mbd = regs->GR_L(1) & CHM_GPR1_D; } #if defined(_FEATURE_IO_ASSIST) else { int zone = SIE_MODE(regs) ? regs->siebk->zone : ((regs->GR_L(1) & CHM_GPR1_ZONE) >> 16); /* Set the measurement block origin address */ if (regs->GR_L(1) & CHM_GPR1_M) { sysblk.zpb[zone].mbo = regs->GR(2); sysblk.zpb[zone].mbk = (regs->GR_L(1) & CHM_GPR1_MBK) >> 24; sysblk.zpb[zone].mbm = 1; } else sysblk.zpb[zone].mbm = 0; sysblk.zpb[zone].mbd = regs->GR_L(1) & CHM_GPR1_D; } #endif /*defined(_FEATURE_IO_ASSIST)*/ } /*-------------------------------------------------------------------*/ /* B233 SSCH - Start Subchannel [S] */ /*-------------------------------------------------------------------*/ DEF_INST(start_subchannel) { int b2; /* Effective addr base */ VADR effective_addr2; /* Effective address */ DEVBLK *dev; /* -> device block */ ORB orb; /* Operation request block */ S(inst, regs, b2, effective_addr2); PRIV_CHECK(regs); #if defined(_FEATURE_IO_ASSIST) if(SIE_STATNB(regs, EC0, IOA) && !regs->sie_pref) #endif SIE_INTERCEPT(regs); PTIO(IO,"SSCH"); FW_CHECK(effective_addr2, regs); /* Fetch the operation request block */ ARCH_DEP(vfetchc) ( &orb, sizeof(ORB)-1, effective_addr2, b2, regs ); /* Program check if reserved bits are not zero */ if (orb.flag5 & ORB5_RESV || orb.flag7 & ORB7_RESV || orb.ccwaddr[0] & 0x80) ARCH_DEP(program_interrupt) (regs, PGM_OPERAND_EXCEPTION); #if !defined(FEATURE_INCORRECT_LENGTH_INDICATION_SUPPRESSION) /* Program check if incorrect length suppression */ if (orb.flag7 & ORB7_L) ARCH_DEP(program_interrupt) (regs, PGM_OPERAND_EXCEPTION); #endif /*!defined(FEATURE_INCORRECT_LENGTH_INDICATION_SUPPRESSION)*/ #if !defined(FEATURE_MIDAW) /*@MW*/ /* Program check if modified indirect data addressing requested */ if (orb.flag7 & ORB7_D) ARCH_DEP(program_interrupt) (regs, PGM_OPERAND_EXCEPTION); #endif /*!defined(FEATURE_MIDAW)*/ /*@MW*/ /* Program check if the ssid including lcss is invalid */ SSID_CHECK(regs); /* Locate the device block for this subchannel */ dev = find_device_by_subchan (regs->GR_L(1)); /* Condition code 3 if subchannel does not exist, is not valid, is not enabled, or no path available */ if (dev == NULL || (dev->pmcw.flag5 & PMCW5_V) == 0 || (dev->pmcw.flag5 & PMCW5_E) == 0 || (orb.lpm & dev->pmcw.pam) == 0) { PTIO(ERR,"*SSCH"); #if defined(_FEATURE_IO_ASSIST) SIE_INTERCEPT(regs); #endif regs->psw.cc = 3; return; } /* Perform serialization and checkpoint-synchronization */ PERFORM_SERIALIZATION (regs); PERFORM_CHKPT_SYNC (regs); /* Clear the path not operational mask */ dev->pmcw.pnom = 0; /* Copy the logical path mask */ dev->pmcw.lpm = orb.lpm; /* Start the channel program and set the condition code */ regs->psw.cc = ARCH_DEP(startio) (regs, dev, &orb); /*@IWZ*/ regs->siocount++; /* Set the last path used mask */ if (regs->psw.cc == 0) dev->pmcw.lpum = 0x80; } /*-------------------------------------------------------------------*/ /* B23A STCPS - Store Channel Path Status [S] */ /*-------------------------------------------------------------------*/ DEF_INST(store_channel_path_status) { int b2; /* Effective addr base */ VADR effective_addr2; /* Effective address */ BYTE work[32]; /* Work area */ S(inst, regs, b2, effective_addr2); PRIV_CHECK(regs); SIE_INTERCEPT(regs); PTIO(IO,"STCPS"); /* Program check if operand not on 32 byte boundary */ if ( effective_addr2 & 0x0000001F ) ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION); /*INCOMPLETE, SET TO ALL ZEROS*/ memset(work,0x00,32); /* Store channel path status word at operand address */ ARCH_DEP(vstorec) ( work, 32-1, effective_addr2, b2, regs ); } /*-------------------------------------------------------------------*/ /* B239 STCRW - Store Channel Report Word [S] */ /*-------------------------------------------------------------------*/ DEF_INST(store_channel_report_word) { int b2; /* Effective addr base */ VADR effective_addr2; /* Effective address */ U32 n; /* Integer work area */ S(inst, regs, b2, effective_addr2); PTIO(IO,"STCRW"); PRIV_CHECK(regs); SIE_INTERCEPT(regs); FW_CHECK(effective_addr2, regs); /* Validate write access to operand before taking any pending channel report word off the queue */ ARCH_DEP(validate_operand) (effective_addr2, b2, 0, ACCTYPE_WRITE, regs); /* Obtain any pending channel report */ n = channel_report(regs); /* Store channel report word at operand address */ ARCH_DEP(vstore4) ( n, effective_addr2, b2, regs ); /* Indicate if channel report or zeros were stored */ regs->psw.cc = (n == 0) ? 1 : 0; } /*-------------------------------------------------------------------*/ /* B234 STSCH - Store Subchannel [S] */ /*-------------------------------------------------------------------*/ DEF_INST(store_subchannel) { int b2; /* Effective addr base */ VADR effective_addr2; /* Effective address */ DEVBLK *dev; /* -> device block */ SCHIB schib; /* Subchannel information blk*/ S(inst, regs, b2, effective_addr2); PRIV_CHECK(regs); SIE_INTERCEPT(regs); PTIO(IO,"STSCH"); /* Program check if the ssid including lcss is invalid */ SSID_CHECK(regs); /* Locate the device block for this subchannel */ dev = find_device_by_subchan (regs->GR_L(1)); /* Set condition code 3 if subchannel does not exist */ if (dev == NULL) { PTIO(ERR,"*STSCH"); regs->psw.cc = 3; return; } FW_CHECK(effective_addr2, regs); /* Perform serialization and checkpoint-synchronization */ PERFORM_SERIALIZATION (regs); PERFORM_CHKPT_SYNC (regs); /* Build the subchannel information block */ schib.pmcw = dev->pmcw; obtain_lock (&dev->lock); if (dev->pciscsw.flag3 & SCSW3_SC_PEND) schib.scsw = dev->pciscsw; else schib.scsw = dev->scsw; release_lock (&dev->lock); memset (schib.moddep, 0x00, sizeof(schib.moddep)); /* Store the subchannel information block */ ARCH_DEP(vstorec) ( &schib, sizeof(SCHIB)-1, effective_addr2, b2, regs ); /* Set condition code 0 */ regs->psw.cc = 0; } /*-------------------------------------------------------------------*/ /* B236 TPI - Test Pending Interruption [S] */ /*-------------------------------------------------------------------*/ DEF_INST(test_pending_interruption) { int b2; /* Effective addr base */ VADR effective_addr2; /* Effective address */ PSA *psa; /* -> Prefixed storage area */ U64 dreg; /* Double register work area */ U32 ioid; /* I/O interruption address */ U32 ioparm; /* I/O interruption parameter*/ U32 iointid; /* I/O interruption ident */ int icode; /* Intercept code */ RADR pfx; /* Prefix */ S(inst, regs, b2, effective_addr2); PRIV_CHECK(regs); #if defined(_FEATURE_IO_ASSIST) if(SIE_STATNB(regs, EC0, IOA) && !regs->sie_pref) #endif SIE_INTERCEPT(regs); PTIO(IO,"TPI"); FW_CHECK(effective_addr2, regs); /* validate operand before taking any action */ if ( effective_addr2 != 0 ) ARCH_DEP(validate_operand) (effective_addr2, b2, 8-1, ACCTYPE_WRITE, regs); /* Perform serialization and checkpoint-synchronization */ PERFORM_SERIALIZATION (regs); PERFORM_CHKPT_SYNC (regs); if( IS_IC_IOPENDING ) { /* Obtain the interrupt lock */ OBTAIN_INTLOCK(regs); /* Test and clear pending interrupt, set condition code */ icode = ARCH_DEP(present_io_interrupt) (regs, &ioid, &ioparm, &iointid, NULL); /* Release the interrupt lock */ RELEASE_INTLOCK(regs); /* Store the SSID word and I/O parameter if an interrupt was pending */ if (icode) { if ( effective_addr2 == 0 #if defined(_FEATURE_IO_ASSIST) || icode != SIE_NO_INTERCEPT #endif ) { #if defined(_FEATURE_IO_ASSIST) if(icode != SIE_NO_INTERCEPT) { /* Point to SIE copy of PSA in state descriptor */ psa = (void*)(regs->hostregs->mainstor + SIE_STATE(regs) + SIE_II_PSA_OFFSET); STORAGE_KEY(SIE_STATE(regs), regs->hostregs) |= (STORKEY_REF | STORKEY_CHANGE); } else #endif { /* Point to PSA in main storage */ pfx = regs->PX; SIE_TRANSLATE(&pfx, ACCTYPE_SIE, regs); psa = (void*)(regs->mainstor + pfx); STORAGE_KEY(pfx, regs) |= (STORKEY_REF | STORKEY_CHANGE); } /* If operand address is zero, store in PSA */ STORE_FW(psa->ioid,ioid); STORE_FW(psa->ioparm,ioparm); #if defined(FEATURE_ESAME) || defined(_FEATURE_IO_ASSIST) STORE_FW(psa->iointid,iointid); #endif /*defined(FEATURE_ESAME)*/ #if defined(_FEATURE_IO_ASSIST) if(icode != SIE_NO_INTERCEPT) longjmp(regs->progjmp,SIE_INTERCEPT_IOINST); #endif } else { /* Otherwise store at operand location */ dreg = ((U64)ioid << 32) | ioparm; ARCH_DEP(vstore8) ( dreg, effective_addr2, b2, regs ); } } } else { #if defined(_FEATURE_IO_ASSIST) /* If no I/O assisted devices have pending interrupts then we must intercept */ SIE_INTERCEPT(regs); #endif icode = 0; } regs->psw.cc = (icode == 0) ? 0 : 1; } /*-------------------------------------------------------------------*/ /* B235 TSCH - Test Subchannel [S] */ /*-------------------------------------------------------------------*/ DEF_INST(test_subchannel) { int b2; /* Effective addr base */ VADR effective_addr2; /* Effective address */ DEVBLK *dev; /* -> device block */ IRB irb; /* Interruption response blk */ int cc; /* Condition Code */ S(inst, regs, b2, effective_addr2); PRIV_CHECK(regs); #if defined(_FEATURE_IO_ASSIST) if(SIE_STATNB(regs, EC0, IOA) && !regs->sie_pref) #endif SIE_INTERCEPT(regs); PTIO(IO,"TSCH"); FW_CHECK(effective_addr2, regs); /* Program check if the ssid including lcss is invalid */ SSID_CHECK(regs); /* Locate the device block for this subchannel */ dev = find_device_by_subchan (regs->GR_L(1)); /* Condition code 3 if subchannel does not exist, is not valid, or is not enabled */ if (dev == NULL || (dev->pmcw.flag5 & PMCW5_V) == 0 || (dev->pmcw.flag5 & PMCW5_E) == 0) { PTIO(ERR,"*TSCH"); #if defined(_FEATURE_IO_ASSIST) SIE_INTERCEPT(regs); #endif regs->psw.cc = 3; return; } /* validate operand before taking any action */ ARCH_DEP(validate_operand) (effective_addr2, b2, sizeof(IRB)-1, ACCTYPE_WRITE_SKP, regs); /* Perform serialization and checkpoint-synchronization */ PERFORM_SERIALIZATION (regs); PERFORM_CHKPT_SYNC (regs); /* Test and clear pending status, set condition code */ cc = test_subchan (regs, dev, &irb); /* Store the interruption response block */ ARCH_DEP(vstorec) ( &irb, sizeof(IRB)-1, effective_addr2, b2, regs ); regs->psw.cc = cc; } #if defined(FEATURE_CANCEL_IO_FACILITY) /*-------------------------------------------------------------------*/ /* B276 XSCH - Cancel Subchannel [S] */ /*-------------------------------------------------------------------*/ DEF_INST(cancel_subchannel) { int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ DEVBLK *dev; /* -> device block */ S(inst, regs, b2, effective_addr2); PRIV_CHECK(regs); #if defined(_FEATURE_IO_ASSIST) if(SIE_STATNB(regs, EC0, IOA) && !regs->sie_pref) #endif SIE_INTERCEPT(regs); PTIO(IO,"XSCH"); /* Program check if the ssid including lcss is invalid */ SSID_CHECK(regs); /* Locate the device block for this subchannel */ dev = find_device_by_subchan (regs->GR_L(1)); /* Condition code 3 if subchannel does not exist, is not valid, or is not enabled */ if (dev == NULL || (dev->pmcw.flag5 & PMCW5_V) == 0 || (dev->pmcw.flag5 & PMCW5_E) == 0) { PTIO(ERR,"*XSCH"); #if defined(_FEATURE_IO_ASSIST) SIE_INTERCEPT(regs); #endif regs->psw.cc = 3; return; } /* Perform cancel subchannel and set condition code */ regs->psw.cc = cancel_subchan (regs, dev); } #endif /*defined(FEATURE_CANCEL_IO_FACILITY)*/ #endif /*defined(FEATURE_CHANNEL_SUBSYSTEM)*/ #if defined(FEATURE_S370_CHANNEL) /*-------------------------------------------------------------------*/ /* 9C00 SIO - Start I/O [S] */ /* 9C01 SIOF - Start I/O Fast Release [S] */ /* 9C02 RIO - Resume I/O - ZZ INCOMPLETE [S] */ /*-------------------------------------------------------------------*/ DEF_INST(start_io) { int b2; /* Effective addr base */ VADR effective_addr2; /* Effective address */ PSA *psa; /* -> prefixed storage area */ DEVBLK *dev; /* -> device block for SIO */ ORB orb; /* Operation request blk @IZW*/ VADR ccwaddr; /* CCW address for start I/O */ BYTE ccwkey; /* Bits 0-3=key, 4=7=zeroes */ S(inst, regs, b2, effective_addr2); #if defined(FEATURE_ECPSVM) if((inst[1])!=0x02) { if(ecpsvm_dosio(regs,b2,effective_addr2)==0) { return; } } #endif PRIV_CHECK(regs); SIE_INTERCEPT(regs); PTIO(IO,"SIO"); /* Locate the device block */ if(regs->chanset == 0xFFFF || !(dev = find_device_by_devnum (regs->chanset,effective_addr2)) ) { PTIO(ERR,"*SIO"); regs->psw.cc = 3; return; } /* Fetch key and CCW address from the CAW at PSA+X'48' */ psa = (PSA*)(regs->mainstor + regs->PX); ccwkey = psa->caw[0] & 0xF0; ccwaddr = (psa->caw[1] << 16) | (psa->caw[2] << 8) | psa->caw[3]; /* Build the I/O operation request block */ /*@IZW*/ memset (&orb, 0, sizeof(ORB)); /*@IZW*/ orb.flag4 = ccwkey & ORB4_KEY; /*@IZW*/ STORE_FW(orb.ccwaddr,ccwaddr); /*@IZW*/ /* Start the channel program and set the condition code */ regs->psw.cc = ARCH_DEP(startio) (regs, dev, &orb); /*@IZW*/ regs->siocount++; } /*-------------------------------------------------------------------*/ /* 9D00 TIO - Test I/O [S] */ /* 9D01 CLRIO - Clear I/O [S] */ /*-------------------------------------------------------------------*/ DEF_INST(test_io) { int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ DEVBLK *dev; /* -> device block for SIO */ S(inst, regs, b2, effective_addr2); PRIV_CHECK(regs); SIE_INTERCEPT(regs); PTIO(IO,"TIO"); /* Locate the device block */ if(regs->chanset == 0xFFFF || !(dev = find_device_by_devnum (regs->chanset,effective_addr2)) ) { PTIO(ERR,"*TIO"); regs->psw.cc = 3; return; } /* Test the device and set the condition code */ regs->psw.cc = testio (regs, dev, inst[1]); /* Yield time slice so that device handler may get some time */ /* to possibly complete an I/O - to prevent a TIO Busy Loop */ if(regs->psw.cc == 2) { sched_yield(); } } /*-------------------------------------------------------------------*/ /* 9E00 HIO - Halt I/O [S] */ /* 9E01 HDV - Halt Device [S] */ /*-------------------------------------------------------------------*/ DEF_INST(halt_io) { int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ DEVBLK *dev; /* -> device block for SIO */ S(inst, regs, b2, effective_addr2); PRIV_CHECK(regs); SIE_INTERCEPT(regs); PTIO(IO,"HIO"); /* Locate the device block */ if(regs->chanset == 0xFFFF || !(dev = find_device_by_devnum (regs->chanset,effective_addr2)) ) { PTIO(ERR,"*HIO"); regs->psw.cc = 3; return; } /* Test the device and set the condition code */ regs->psw.cc = haltio (regs, dev, inst[1]); } /*-------------------------------------------------------------------*/ /* 9F00 TCH - Test Channel [S] */ /*-------------------------------------------------------------------*/ DEF_INST(test_channel) { int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ #if defined(_FEATURE_SIE) BYTE channelid; U16 tch_ctl; #endif /*defined(_FEATURE_SIE)*/ S(inst, regs, b2, effective_addr2); PRIV_CHECK(regs); PTIO(IO,"TCH"); #if defined(_FEATURE_SIE) if(!SIE_MODE(regs)) { #endif /*defined(_FEATURE_SIE)*/ /* Test for pending interrupt and set condition code */ regs->psw.cc = testch (regs, effective_addr2 & 0xFF00); #if defined(_FEATURE_SIE) } else { channelid = (effective_addr2 >> 8) & 0xFF; FETCH_HW(tch_ctl,((SIEBK*)(regs->siebk))->tch_ctl); if((channelid > 15) || ((0x8000 >> channelid) & tch_ctl)) longjmp(regs->progjmp, SIE_INTERCEPT_INST); else regs->psw.cc = 0; } #endif /*defined(_FEATURE_SIE)*/ } /*-------------------------------------------------------------------*/ /* B203 STIDC - Store Channel ID [S] */ /*-------------------------------------------------------------------*/ DEF_INST(store_channel_id) { int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ S(inst, regs, b2, effective_addr2); PRIV_CHECK(regs); SIE_INTERCEPT(regs); PTIO(IO,"STIDC"); /* Store Channel ID and set condition code */ regs->psw.cc = stchan_id (regs, effective_addr2 & 0xFF00); } #if defined(FEATURE_CHANNEL_SWITCHING) /*-------------------------------------------------------------------*/ /* B200 CONCS - Connect Channel Set [S] */ /*-------------------------------------------------------------------*/ DEF_INST(connect_channel_set) { int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ int i; S(inst, regs, b2, effective_addr2); PRIV_CHECK(regs); SIE_INTERCEPT(regs); PTIO(IO,"CONCS"); effective_addr2 &= 0xFFFF; /* Hercules has as many channelsets as CSS's */ if(effective_addr2 >= FEATURE_LCSS_MAX) { PTIO(ERR,"*CONCS"); regs->psw.cc = 3; return; } /* If the addressed channel set is currently connected then return with cc0 */ if(regs->chanset == effective_addr2) { regs->psw.cc = 0; return; } /* Disconnect channel set */ regs->chanset = 0xFFFF; OBTAIN_INTLOCK(regs); /* If the addressed channelset is connected to another CPU then return with cc1 */ for (i = 0; i < MAX_CPU; i++) { if (IS_CPU_ONLINE(i) && sysblk.regs[i]->chanset == effective_addr2) { RELEASE_INTLOCK(regs); regs->psw.cc = 1; return; } } /* Set channel set connected to current CPU */ regs->chanset = effective_addr2; /* Interrupts may be pending on this channelset */ ON_IC_IOPENDING; RELEASE_INTLOCK(regs); regs->psw.cc = 0; } /*-------------------------------------------------------------------*/ /* B201 DISCS - Disconnect Channel Set [S] */ /*-------------------------------------------------------------------*/ DEF_INST(disconnect_channel_set) { int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ int i; S(inst, regs, b2, effective_addr2); PRIV_CHECK(regs); SIE_INTERCEPT(regs); PTIO(IO,"DISCS"); /* Hercules has as many channelsets as CSS's */ if(effective_addr2 >= FEATURE_LCSS_MAX) { PTIO(ERR,"*DISCS"); regs->psw.cc = 3; return; } /* If the addressed channel set is currently connected then disconect channel set and return with cc0 */ if(regs->chanset == effective_addr2 && regs->chanset != 0xFFFF) { regs->chanset = 0xFFFF; regs->psw.cc = 0; return; } OBTAIN_INTLOCK(regs); /* If the addressed channelset is connected to another CPU then return with cc0 */ for(i = 0; i < MAX_CPU; i++) { if (IS_CPU_ONLINE(i) && sysblk.regs[i]->chanset == effective_addr2) { if(sysblk.regs[i]->cpustate != CPUSTATE_STARTED) { sysblk.regs[i]->chanset = 0xFFFF; regs->psw.cc = 0; } else regs->psw.cc = 1; RELEASE_INTLOCK(regs); return; } } RELEASE_INTLOCK(regs); /* The channel set is not connected, no operation is performed */ regs->psw.cc = 0; } #endif /*defined(FEATURE_CHANNEL_SWITCHING)*/ #endif /*defined(FEATURE_S370_CHANNEL)*/ #if !defined(_GEN_ARCH) #if defined(_ARCHMODE2) #define _GEN_ARCH _ARCHMODE2 #include "io.c" #endif #if defined(_ARCHMODE3) #undef _GEN_ARCH #define _GEN_ARCH _ARCHMODE3 #include "io.c" #endif #endif /*!defined(_GEN_ARCH)*/ hercules-3.07/ipl.c000644 000765 000765 00000047505 11224164171 015705 0ustar00jmaynardjmaynard000000 000000 /* IPL.C (c) Copyright Roger Bowler, 1999-2009 */ /* ESA/390 Initial Program Loader */ /* Interpretive Execution - (c) Copyright Jan Jaeger, 1999-2009 */ /* z/Architecture support - (c) Copyright Jan Jaeger, 1999-2009 */ // $Id: ipl.c 5405 2009-06-10 12:34:17Z rbowler $ /*-------------------------------------------------------------------*/ /* This module implements the Initial Program Load (IPL) function of */ /* the S/370, ESA/390 and z/Architectures, described in the manuals: */ /* */ /* GA22-7000 System/370 Principles of Operation */ /* SA22-7201 ESA/390 Principles of Operation */ /* SA22-7832 z/Architecture Principles of Operation. */ /* */ /*-------------------------------------------------------------------*/ #include "hstdinc.h" #define _IPL_C #define _HENGINE_DLL_ #include "hercules.h" #include "opcode.h" #include "inline.h" #if defined(OPTION_FISHIO) #include "w32chan.h" #endif // defined(OPTION_FISHIO) /*-------------------------------------------------------------------*/ /* Function to perform System Reset (either 'normal' or 'clear') */ /*-------------------------------------------------------------------*/ int ARCH_DEP(system_reset) (int cpu, int clear) { int rc = 0; REGS *regs; /* Configure the cpu if it is not online */ if (!IS_CPU_ONLINE(cpu)) { if (configure_cpu(cpu) != 0) { /* ZZ FIXME: we should probably present a machine-check if we encounter any errors during the reset (rc != 0) */ return -1; } ASSERT(IS_CPU_ONLINE(cpu)); } regs = sysblk.regs[cpu]; HDC1(debug_cpu_state, regs); /* Perform system-reset-normal or system-reset-clear function */ if (!clear) { /* Reset external interrupts */ OFF_IC_SERVSIG; OFF_IC_INTKEY; /* Reset all CPUs in the configuration */ for (cpu = 0; cpu < MAX_CPU; cpu++) if (IS_CPU_ONLINE(cpu)) if (ARCH_DEP(cpu_reset) (sysblk.regs[cpu])) rc = -1; /* Perform I/O subsystem reset */ io_reset (); } else { /* Reset external interrupts */ OFF_IC_SERVSIG; OFF_IC_INTKEY; /* Reset all CPUs in the configuration */ for (cpu = 0; cpu < MAX_CPU; cpu++) { if (IS_CPU_ONLINE(cpu)) { regs=sysblk.regs[cpu]; if (ARCH_DEP(initial_cpu_reset) (regs)) { rc = -1; } /* Clear all the registers (AR, GPR, FPR, VR) as part of the CPU CLEAR RESET operation */ memset (regs->ar,0,sizeof(regs->ar)); memset (regs->gr,0,sizeof(regs->gr)); memset (regs->fpr,0,sizeof(regs->fpr)); #if defined(_FEATURE_VECTOR_FACILITY) memset (regs->vf->vr,0,sizeof(regs->vf->vr)); #endif /*defined(_FEATURE_VECTOR_FACILITY)*/ } } /* Perform I/O subsystem reset */ io_reset (); /* Clear storage */ sysblk.main_clear = sysblk.xpnd_clear = 0; storage_clear(); xstorage_clear(); } #if defined(FEATURE_CONFIGURATION_TOPOLOGY_FACILITY) /* Clear topology-change-report-pending condition */ sysblk.topchnge = 0; #endif /*defined(FEATURE_CONFIGURATION_TOPOLOGY_FACILITY)*/ /* ZZ FIXME: we should probably present a machine-check if we encounter any errors during the reset (rc != 0) */ return rc; } /* end function system_reset */ /*-------------------------------------------------------------------*/ /* LOAD (aka IPL) functions... */ /*-------------------------------------------------------------------*/ /* Performing an Initial Program Load (aka IPL) involves three */ /* distinct phases: in phase 1 the system is reset (registers */ /* and, for load-clear, storage), and in phase two the actual */ /* Initial Program Loading from the IPL device takes place. Finally,*/ /* in phase three, the IPL PSW is loaded and the CPU is started. */ /*-------------------------------------------------------------------*/ int orig_arch_mode; /* Saved architecture mode */ PSW captured_zpsw; /* Captured z/Arch PSW */ /*-------------------------------------------------------------------*/ /* Common LOAD (IPL) begin: system-reset (register/storage clearing) */ /*-------------------------------------------------------------------*/ int ARCH_DEP(common_load_begin) (int cpu, int clear) { REGS *regs; /* Save the original architecture mode for later */ orig_arch_mode = sysblk.dummyregs.arch_mode = sysblk.arch_mode; #if defined(OPTION_FISHIO) ios_arch_mode = sysblk.arch_mode; #endif // defined(OPTION_FISHIO) /* Perform system-reset-normal or system-reset-clear function */ if (ARCH_DEP(system_reset(cpu,clear)) != 0) return -1; regs = sysblk.regs[cpu]; if (sysblk.arch_mode == ARCH_900) { /* Switch architecture mode to ESA390 mode for z/Arch IPL */ sysblk.arch_mode = ARCH_390; /* Capture the z/Arch PSW if this is a Load-normal IPL */ if (!clear) captured_zpsw = regs->psw; } /* Load-clear does a clear-reset (which does an initial-cpu-reset) on all cpus in the configuration, but Load-normal does an initial- cpu-reset only for the IPL CPU and a regular cpu-reset for all other CPUs in the configuration. Thus if the above system_reset call did a system-normal-reset for us, then we need to manually do a clear-reset (initial-cpu-reset) on the IPL CPU... */ if (!clear) { /* Perform initial reset on the IPL CPU */ if (ARCH_DEP(initial_cpu_reset) (regs) != 0) return -1; /* Save our captured-z/Arch-PSW if this is a Load-normal IPL since the initial_cpu_reset call cleared it to zero. */ if (orig_arch_mode == ARCH_900) regs->captured_zpsw = captured_zpsw; } /* The actual IPL (load) now begins... */ regs->loadstate = 1; return 0; } /* end function common_load_begin */ /*-------------------------------------------------------------------*/ /* Function to run initial CCW chain from IPL device and load IPLPSW */ /* Returns 0 if successful, -1 if error */ /* intlock MUST be held on entry */ /*-------------------------------------------------------------------*/ int ARCH_DEP(load_ipl) (U16 lcss, U16 devnum, int cpu, int clear) { REGS *regs; /* -> Regs */ DEVBLK *dev; /* -> Device control block */ int i; /* Array subscript */ BYTE unitstat; /* IPL device unit status */ BYTE chanstat; /* IPL device channel status */ /* Get started */ if (ARCH_DEP(common_load_begin) (cpu, clear) != 0) return -1; /* The actual IPL proper starts here... */ regs = sysblk.regs[cpu]; /* Point to IPL CPU's registers */ /* Point to the device block for the IPL device */ dev = find_device_by_devnum (lcss,devnum); if (dev == NULL) { logmsg (_("HHCCP027E Device %4.4X not in configuration%s\n"), devnum, (sysblk.arch_mode == ARCH_370 ? " or not conneceted to channelset" : "")); HDC1(debug_cpu_state, regs); return -1; } #if defined(OPTION_IPLPARM) if(sysblk.haveiplparm) { for(i=0;i<16;i++) { regs->GR_L(i)=fetch_fw(&sysblk.iplparmstring[i*4]); } sysblk.haveiplparm=0; } #endif /* Set Main Storage Reference and Update bits */ STORAGE_KEY(regs->PX, regs) |= (STORKEY_REF | STORKEY_CHANGE); sysblk.main_clear = sysblk.xpnd_clear = 0; /* Build the IPL CCW at location 0 */ regs->psa->iplpsw[0] = 0x02; /* CCW command = Read */ regs->psa->iplpsw[1] = 0; /* Data address = zero */ regs->psa->iplpsw[2] = 0; regs->psa->iplpsw[3] = 0; regs->psa->iplpsw[4] = CCW_FLAGS_CC | CCW_FLAGS_SLI; /* CCW flags */ regs->psa->iplpsw[5] = 0; /* Reserved byte */ regs->psa->iplpsw[6] = 0; /* Byte count = 24 */ regs->psa->iplpsw[7] = 24; /* Enable the subchannel for the IPL device */ dev->pmcw.flag5 |= PMCW5_E; /* Build the operation request block */ /*@IWZ*/ memset (&dev->orb, 0, sizeof(ORB)); /*@IWZ*/ dev->busy = 1; RELEASE_INTLOCK(NULL); /* Execute the IPL channel program */ ARCH_DEP(execute_ccw_chain) (dev); OBTAIN_INTLOCK(NULL); /* Clear the interrupt pending and device busy conditions */ obtain_lock (&sysblk.iointqlk); DEQUEUE_IO_INTERRUPT_QLOCKED(&dev->ioint); DEQUEUE_IO_INTERRUPT_QLOCKED(&dev->pciioint); DEQUEUE_IO_INTERRUPT_QLOCKED(&dev->attnioint); release_lock(&sysblk.iointqlk); dev->busy = 0; dev->scsw.flag2 = 0; dev->scsw.flag3 = 0; /* Check that load completed normally */ #ifdef FEATURE_S370_CHANNEL unitstat = dev->csw[4]; chanstat = dev->csw[5]; #endif /*FEATURE_S370_CHANNEL*/ #ifdef FEATURE_CHANNEL_SUBSYSTEM unitstat = dev->scsw.unitstat; chanstat = dev->scsw.chanstat; #endif /*FEATURE_CHANNEL_SUBSYSTEM*/ if (unitstat != (CSW_CE | CSW_DE) || chanstat != 0) { logmsg (_("HHCCP029E %s mode IPL failed: CSW status=%2.2X%2.2X\n" " Sense="), get_arch_mode_string(regs), unitstat, chanstat); for (i=0; i < (int)dev->numsense; i++) { logmsg ("%2.2X", dev->sense[i]); if ((i & 3) == 3) logmsg(" "); } logmsg ("\n"); HDC1(debug_cpu_state, regs); return -1; } #ifdef FEATURE_S370_CHANNEL /* Test the EC mode bit in the IPL PSW */ if (regs->psa->iplpsw[1] & 0x08) { /* In EC mode, store device address at locations 184-187 */ STORE_FW(regs->psa->ioid, dev->devnum); } else { /* In BC mode, store device address at locations 2-3 */ STORE_HW(regs->psa->iplpsw + 2, dev->devnum); } #endif /*FEATURE_S370_CHANNEL*/ #ifdef FEATURE_CHANNEL_SUBSYSTEM /* Set LPUM */ dev->pmcw.lpum = 0x80; STORE_FW(regs->psa->ioid, (dev->ssid<<16)|dev->subchan); /* Store zeroes at locations 188-191 */ memset (regs->psa->ioparm, 0, 4); #endif /*FEATURE_CHANNEL_SUBSYSTEM*/ /* Save IPL device number, cpu number and lcss */ sysblk.ipldev = devnum; sysblk.iplcpu = regs->cpuad; sysblk.ipllcss = lcss; /* Finish up... */ return ARCH_DEP(common_load_finish) (regs); } /* end function load_ipl */ /*-------------------------------------------------------------------*/ /* Common LOAD (IPL) finish: load IPL PSW and start CPU */ /*-------------------------------------------------------------------*/ int ARCH_DEP(common_load_finish) (REGS *regs) { /* Zeroize the interrupt code in the PSW */ regs->psw.intcode = 0; /* Load IPL PSW from PSA+X'0' */ if (ARCH_DEP(load_psw) (regs, regs->psa->iplpsw) != 0) { logmsg (_("HHCCP030E %s mode IPL failed: Invalid IPL PSW: " "%2.2X%2.2X%2.2X%2.2X %2.2X%2.2X%2.2X%2.2X\n"), get_arch_mode_string(regs), regs->psa->iplpsw[0], regs->psa->iplpsw[1], regs->psa->iplpsw[2], regs->psa->iplpsw[3], regs->psa->iplpsw[4], regs->psa->iplpsw[5], regs->psa->iplpsw[6], regs->psa->iplpsw[7]); HDC1(debug_cpu_state, regs); return -1; } /* Set the CPU into the started state */ regs->opinterv = 0; regs->cpustate = CPUSTATE_STARTED; /* The actual IPL (load) is now completed... */ regs->loadstate = 0; /* Signal the CPU to retest stopped indicator */ WAKEUP_CPU (regs); HDC1(debug_cpu_state, regs); return 0; } /* end function common_load_finish */ /*-------------------------------------------------------------------*/ /* Function to perform CPU Reset */ /*-------------------------------------------------------------------*/ int ARCH_DEP(cpu_reset) (REGS *regs) { int i; /* Array subscript */ regs->ip = regs->inst; /* Clear indicators */ regs->loadstate = 0; regs->checkstop = 0; regs->sigpreset = 0; regs->extccpu = 0; for (i = 0; i < MAX_CPU; i++) regs->emercpu[i] = 0; regs->instinvalid = 1; regs->instcount = regs->prevcount = 0; /* Clear interrupts */ SET_IC_INITIAL_MASK(regs); SET_IC_INITIAL_STATE(regs); /* Clear the translation exception identification */ regs->EA_G = 0; regs->excarid = 0; /* Clear monitor code */ regs->MC_G = 0; /* Purge the lookaside buffers */ ARCH_DEP(purge_tlb) (regs); #if defined(FEATURE_ACCESS_REGISTERS) ARCH_DEP(purge_alb) (regs); #endif /*defined(FEATURE_ACCESS_REGISTERS)*/ if(regs->host) { /* Put the CPU into the stopped state */ regs->opinterv = 0; regs->cpustate = CPUSTATE_STOPPED; ON_IC_INTERRUPT(regs); } #ifdef FEATURE_INTERVAL_TIMER ARCH_DEP(store_int_timer_nolock) (regs); #endif if(regs->host && regs->guestregs) { ARCH_DEP(cpu_reset)(regs->guestregs); /* CPU state of SIE copy cannot be controlled */ regs->guestregs->opinterv = 0; regs->guestregs->cpustate = CPUSTATE_STARTED; } return 0; } /* end function cpu_reset */ /*-------------------------------------------------------------------*/ /* Function to perform Initial CPU Reset */ /*-------------------------------------------------------------------*/ int ARCH_DEP(initial_cpu_reset) (REGS *regs) { /* Clear reset pending indicators */ regs->sigpireset = regs->sigpreset = 0; /* Clear the registers */ memset ( ®s->psw, 0, sizeof(regs->psw) ); memset ( ®s->captured_zpsw, 0, sizeof(regs->captured_zpsw) ); memset ( regs->cr, 0, sizeof(regs->cr) ); regs->fpc = 0; regs->PX = 0; regs->psw.AMASK_G = AMASK24; /* * ISW20060125 : Since we reset the prefix, we must also adjust * the PSA ptr */ regs->psa = (PSA_3XX *)regs->mainstor; /* Perform a CPU reset (after setting PSA) */ ARCH_DEP(cpu_reset) (regs); regs->todpr = 0; regs->clkc = 0; set_cpu_timer(regs, 0); #ifdef _FEATURE_INTERVAL_TIMER set_int_timer(regs, 0); #endif /* The breaking event address register is initialised to 1 */ regs->bear = 1; /* Initialize external interrupt masks in control register 0 */ regs->CR(0) = CR0_XM_ITIMER | CR0_XM_INTKEY | CR0_XM_EXTSIG; #ifdef FEATURE_S370_CHANNEL /* For S/370 initialize the channel masks in CR2 */ regs->CR(2) = 0xFFFFFFFF; #endif /*FEATURE_S370_CHANNEL*/ regs->chanset = #if defined(FEATURE_CHANNEL_SWITCHING) regs->cpuad < FEATURE_LCSS_MAX ? regs->cpuad : #endif /*defined(FEATURE_CHANNEL_SWITCHING)*/ 0xFFFF; /* Initialize the machine check masks in control register 14 */ regs->CR(14) = CR14_CHKSTOP | CR14_SYNCMCEL | CR14_XDMGRPT; #ifndef FEATURE_LINKAGE_STACK /* For S/370 initialize the MCEL address in CR15 */ regs->CR(15) = 512; #endif /*!FEATURE_LINKAGE_STACK*/ if(regs->host && regs->guestregs) ARCH_DEP(initial_cpu_reset)(regs->guestregs); return 0; } /* end function initial_cpu_reset */ #if !defined(_GEN_ARCH) #if defined(_ARCHMODE2) #define _GEN_ARCH _ARCHMODE2 #include "ipl.c" #endif #if defined(_ARCHMODE3) #undef _GEN_ARCH #define _GEN_ARCH _ARCHMODE3 #include "ipl.c" #endif /*********************************************************************/ /* Externally Initiated Functions... */ /*********************************************************************/ /*-------------------------------------------------------------------*/ /* Load / IPL (Load Normal -or- Load Clear) */ /*-------------------------------------------------------------------*/ int load_ipl (U16 lcss, U16 devnum, int cpu, int clear) { switch(sysblk.arch_mode) { #if defined(_370) case ARCH_370: return s370_load_ipl (lcss, devnum, cpu, clear); #endif #if defined(_390) case ARCH_390: return s390_load_ipl (lcss, devnum, cpu, clear); #endif #if defined(_900) case ARCH_900: /* z/Arch always starts out in ESA390 mode */ return s390_load_ipl (lcss, devnum, cpu, clear); #endif } return -1; } /*-------------------------------------------------------------------*/ /* Initial CPU Reset */ /*-------------------------------------------------------------------*/ int initial_cpu_reset (REGS *regs) { int rc = -1; switch(sysblk.arch_mode) { #if defined(_370) case ARCH_370: rc = s370_initial_cpu_reset (regs); break; #endif #if defined(_390) case ARCH_390: rc = s390_initial_cpu_reset (regs); break; #endif #if defined(_900) case ARCH_900: /* z/Arch always starts out in ESA390 mode */ rc = s390_initial_cpu_reset (regs); break; #endif } regs->arch_mode = sysblk.arch_mode; return rc; } /*-------------------------------------------------------------------*/ /* System Reset ( Normal reset or Clear reset ) */ /*-------------------------------------------------------------------*/ int system_reset (int cpu, int clear) { switch(sysblk.arch_mode) { #if defined(_370) case ARCH_370: return s370_system_reset (cpu, clear); #endif #if defined(_390) case ARCH_390: return s390_system_reset (cpu, clear); #endif #if defined(_900) case ARCH_900: /* z/Arch always starts out in ESA390 mode */ return s390_system_reset (cpu, clear); #endif } return -1; } /*-------------------------------------------------------------------*/ /* ordinary CPU Reset (no clearing takes place) */ /*-------------------------------------------------------------------*/ int cpu_reset (REGS *regs) { switch(sysblk.arch_mode) { #if defined(_370) case ARCH_370: return s370_cpu_reset (regs); #endif #if defined(_390) case ARCH_390: return s390_cpu_reset (regs); #endif #if defined(_900) case ARCH_900: /* z/Arch always starts out in ESA390 mode */ return s390_cpu_reset (regs); #endif } return -1; } /*-------------------------------------------------------------------*/ /* Function to clear main storage */ /*-------------------------------------------------------------------*/ void storage_clear() { if (!sysblk.main_clear) { memset(sysblk.mainstor,0,sysblk.mainsize); memset(sysblk.storkeys,0,sysblk.mainsize / STORAGE_KEY_UNITSIZE); sysblk.main_clear = 1; } } /*-------------------------------------------------------------------*/ /* Function to clear expanded storage */ /*-------------------------------------------------------------------*/ void xstorage_clear() { if(sysblk.xpndsize && !sysblk.xpnd_clear) { memset(sysblk.xpndstor,0,(size_t)sysblk.xpndsize * XSTORE_PAGESIZE); sysblk.xpnd_clear = 1; } } #endif /*!defined(_GEN_ARCH)*/ hercules-3.07/linklist.h000644 000765 000765 00000026400 11143760543 016753 0ustar00jmaynardjmaynard000000 000000 /////////////////////////////////////////////////////////////////////////////////////////// // // linklist.h linked-list macros // /////////////////////////////////////////////////////////////////////////////////////////// // $Id: linklist.h 4102 2006-12-08 09:43:35Z jj $ // // $Log$ #ifndef _LLIST_ #define _LLIST_ ////////////////////////////////////////////////////////////////////////////////////////// /* This module is a standalone collection of linked-list definition, and manipulation macros originally defined for Windows NT development. Samples: // Define a list head. LIST_ENTRY FooList; // Define a structure that will be on the list. // (NOTE: To make debugging easier, it's best to define the LIST_ENTRY field // as the very first field in your structure, but it's not a requirement.) typedef struct _FOO { LIST_ENTRY FooListEntry; . . . } FOO, *PFOO; // Initialize an empty list. InitializeListHead(&FooList); // Create an object, append it to the end of the list. FOO* pFoo; pFoo = ALLOC(sizeof(FOO)); {check for errors, initialize FOO structure} InsertListTail(&FooList,&pFoo->FooListEntry); // Scan list and delete selected items. LIST_ENTRY* pListEntry = FooList.Flink; while (pListEntry != &FooList) { pFoo = CONTAINING_RECORD(pListEntry,FOO,FooListEntry); pListEntry = pListEntry->Flink; if (SomeFunction(pFoo)) { RemoveListEntry(&pFoo->FooListEntry); FREE(pFoo); } } // Purge all items from a list. while (!IsListEmpty(&FooList)) { pListEntry = RemoveListHead(&FooList); pFoo = CONTAINING_RECORD(pListEntry,FOO,FooListEntry); FREE(pFoo); } */ ////////////////////////////////////////////////////////////////////////////////////////// #if !defined( WIN32 ) || \ ( defined( _MSVC_ ) && !defined(_WINNT_) && !defined(_WINNT_H) ) typedef struct _LIST_ENTRY { struct _LIST_ENTRY* Flink; // ptr to next link in chain struct _LIST_ENTRY* Blink; // ptr to previous link in chain } LIST_ENTRY, *PLIST_ENTRY; #endif // !defined(_WINNT_) ////////////////////////////////////////////////////////////////////////////////////////// // // * CONTAINING_RECORD // ( // VOID* address, // type, // field // ); // /* Retrieves a typed pointer to a linked list item given the address of the link storage structure embedded in the linked list item, the type of the linked list item, and the field name of the embedded link storage structure. NOTE: since this macro uses compile-time type knowledge, there is no equivalent C procedure for this macro. Arguments: address - The address of a LIST_ENTRY structure embedded in an a linked list item. type - The type name of the containing linked list item structure. field - The field name of the LIST_ENTRY structure embedded within the linked list item structure. Return Value: Pointer to the linked list item. For Example: If your record looked like this: typedef struct _MYRECORD { int alpha; int beta; LIST_ENTRY gamma; int delta; int epsilon; } MYRECORD, *PMYRECORD; Then, given a variable called "pListEntry" that pointed to the LIST_ENTRY field within your record (i.e. gamma), you can obtain a pointer to the beginning of your record by coding the following CONTAINING_RECORD macro expression: MYRECORD* pMyRecord; // the variable you wish to point to your record // LIST_ENTRY* pListEntry; // already points to the LIST_ENTRY field within // your record (i.e. points to field "gamma") pMyRecord = CONTAINING_RECORD(pListEntry,MYRECORD,gamma); --*/ #ifndef CONTAINING_RECORD #define CONTAINING_RECORD( address, type, field ) \ \ ( (type*) ((char*)(address) - (char*)(&((type*)0)->field)) ) #endif ////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// // // From NTRTL.H: Doubly-linked list manipulation routines. // // (NOTE: implemented as macros but logically these are procedures) // ////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// // // void InitializeListHead // ( // LIST_ENTRY* head // ); // /* Initializes a LIST_ENTRY structure to be the head of an initially empty linked list. Arguments: head - Reference to the structure to be initialized. Return Value: None */ #define InitializeListHead(head) \ \ ( (head)->Flink = (head)->Blink = (head) ) ////////////////////////////////////////////////////////////////////////////////////////// // (I created this one myself -- Fish) // // void InitializeListLink // ( // LIST_ENTRY* link // ); // /* Initializes a LIST_ENTRY structure to be an unlinked link. Arguments: link - Reference to the structure to be initialized. Return Value: None */ #define InitializeListLink(link) \ \ ( (link)->Flink = (link)->Blink = (NULL) ) ////////////////////////////////////////////////////////////////////////////////////////// // // IsListEmpty // ( // LIST_ENTRY* head // ); // /* Determines whether or not a list is empty. Arguments: head - Reference to the head of the linked list to be examined. Return Value: - List is empty. - List contains at least one item. --*/ #define IsListEmpty(head) \ \ ( (head)->Flink == (head) ) ////////////////////////////////////////////////////////////////////////////////////////// // // VOID InsertListHead // ( // LIST_ENTRY* head, // LIST_ENTRY* entry // ); // /* Inserts a new item as the "head" (first) item of a linked list. Arguments: head - Reference to the head of the linked list to be operated upon. entry - Reference to the linkage structure embedded in the linked list item to be added to the linked list. Return Value: None */ #define InsertListHead(head,entry) \ { \ LIST_ENTRY* _EX_Head; \ LIST_ENTRY* _EX_Next; \ \ _EX_Head = (head); \ _EX_Next = _EX_Head->Flink; \ \ (entry)->Flink = _EX_Next; \ (entry)->Blink = _EX_Head; \ \ _EX_Head->Flink = (entry); \ _EX_Next->Blink = (entry); \ } ////////////////////////////////////////////////////////////////////////////////////////// // // VOID InsertListTail // ( // LIST_ENTRY* head, // LIST_ENTRY* entry // ); // /* Inserts a new item as the "tail" (last) item of a linked list. Arguments: head - Reference to the head of the linked list to be operated upon. entry - Reference to the linkage structure embedded in the linked list item to be added to the linked list. Return Value: None */ #define InsertListTail(head,entry) \ { \ LIST_ENTRY* _EX_Head; \ LIST_ENTRY* _EX_Tail; \ \ _EX_Head = (head); \ _EX_Tail = _EX_Head->Blink; \ \ (entry)->Flink = _EX_Head; \ (entry)->Blink = _EX_Tail; \ \ _EX_Tail->Flink = (entry); \ _EX_Head->Blink = (entry); \ } ////////////////////////////////////////////////////////////////////////////////////////// // // LIST_ENTRY* RemoveListHead // ( // LIST_ENTRY* head // ); // /* Removes the "head" (first) item from a linked list, returning the pointer to the removed entry's embedded linkage structure. Attempting to remove the head item from a (properly initialized) linked list is a no-op and returns the pointer to the head of the linked list. The caller may use the CONTAINING_RECORD macro to amplify the returned linkage structure pointer to the containing linked list item structure. Arguments: head - Reference to the head of the linked list to be operated upon. Return Value: Returns a pointer to the newly removed linked list item's embedded linkage structure, or the linked list head in the case of an empty list. */ #define RemoveListHead(head) \ \ (head)->Flink; \ \ { \ RemoveListEntry((head)->Flink) \ } ////////////////////////////////////////////////////////////////////////////////////////// // // LIST_ENTRY* RemoveListTail // ( // LIST_ENTRY* head // ); // /* Removes the "tail" (last) item from a linked list, returning the pointer to the removed entry's embedded linkage structure. Attempting to remove the tail item from a (properly initialized) linked list is a no-op and returns the pointer to the head of the linked list. The caller may use the CONTAINING_RECORD macro to amplify the returned linkage structure pointer to the containing linked list item structure. Arguments: head - Reference to the head of the linked list to be operated upon. Return Value: Pointer to the newly removed linked list item's embedded linkage structure, or the linked list head in the case of an empty list. */ #define RemoveListTail(head) \ \ (head)->Blink; \ \ { \ RemoveListEntry((head)->Blink) \ } ////////////////////////////////////////////////////////////////////////////////////////// // // VOID RemoveListEntry // ( // LIST_ENTRY* entry // ); // /* Removes an item from a linked list. (Removing the head of an empty list is a no-op.) Arguments: entry - Reference to the linkage structure embedded in a linked list item structure. Return Value: None */ #define RemoveListEntry(entry) \ { \ LIST_ENTRY* _EX_Blink; \ LIST_ENTRY* _EX_Flink; \ \ _EX_Flink = (entry)->Flink; \ _EX_Blink = (entry)->Blink; \ \ _EX_Blink->Flink = _EX_Flink; \ _EX_Flink->Blink = _EX_Blink; \ } ////////////////////////////////////////////////////////////////////////////////////////// #endif // _LLIST_ hercules-3.07/loadparm.c000644 000765 000765 00000025562 11344614732 016725 0ustar00jmaynardjmaynard000000 000000 /* LOADPARM.C (c) Copyright Jan Jaeger, 2004-2009 */ /* SCLP / MSSF loadparm */ // $Id: loadparm.c 5652 2010-03-06 11:28:14Z bernard $ /*-------------------------------------------------------------------*/ /* This module contains functions which set, copy, and retrieve the */ /* values of the LOADPARM and various other environmental parameters */ /*-------------------------------------------------------------------*/ #include "hstdinc.h" #define _HENGINE_DLL_ #define _LOADPARM_C_ #include "hercules.h" /*-------------------------------------------------------------------*/ /* SUBROUTINE TO COPY A STRINGZ TO A FIXED-LENGTH EBCDIC FIELD */ /*-------------------------------------------------------------------*/ static void copy_stringz_to_ebcdic(BYTE* fld, size_t len, char *name) { size_t i; for(i = 0; name && i < strlen(name) && i < len; i++) if(isprint(name[i])) fld[i] = host_to_guest((int)(islower(name[i]) ? toupper(name[i]) : name[i])); else fld[i] = 0x40; for(; i < len; i++) fld[i] = 0x40; } /*-------------------------------------------------------------------*/ /* LOAD PARAMETER */ /* Set by: LOADPARM configuration statement or panel command */ /* Retrieved by: SERVC and MSSF_CALL instructions */ /*-------------------------------------------------------------------*/ static BYTE loadparm[8] = {0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40}; void set_loadparm(char *name) { size_t i; for(i = 0; name && i < strlen(name) && i < sizeof(loadparm); i++) if(isprint(name[i])) loadparm[i] = host_to_guest((int)(islower(name[i]) ? toupper(name[i]) : name[i])); else loadparm[i] = 0x40; for(; i < sizeof(loadparm); i++) loadparm[i] = 0x40; } void get_loadparm(BYTE *dest) { memcpy(dest, loadparm, sizeof(loadparm)); } char *str_loadparm() { static char ret_loadparm[sizeof(loadparm)+1]; int i; ret_loadparm[sizeof(loadparm)] = '\0'; for(i = sizeof(loadparm) - 1; i >= 0; i--) { ret_loadparm[i] = guest_to_host((int)loadparm[i]); if(isspace(ret_loadparm[i]) && !ret_loadparm[i+1]) ret_loadparm[i] = '\0'; } return ret_loadparm; } /*-------------------------------------------------------------------*/ /* LOGICAL PARTITION NAME */ /* Set by: LPARNAME configuration statement */ /* Retrieved by: STSI and MSSF_CALL instructions */ /*-------------------------------------------------------------------*/ static BYTE lparname[8] = {0xC8, 0xC5, 0xD9, 0xC3, 0xE4, 0xD3, 0xC5, 0xE2}; /* HERCULES */ void set_lparname(char *name) { size_t i; for(i = 0; name && i < strlen(name) && i < sizeof(lparname); i++) if(isprint(name[i])) lparname[i] = host_to_guest((int)(islower(name[i]) ? toupper(name[i]) : name[i])); else lparname[i] = 0x40; for(; i < sizeof(lparname); i++) lparname[i] = 0x40; } void get_lparname(BYTE *dest) { memcpy(dest, lparname, sizeof(lparname)); } LOADPARM_DLL_IMPORT char *str_lparname() { static char ret_lparname[sizeof(lparname)+1]; int i; ret_lparname[sizeof(lparname)] = '\0'; for(i = sizeof(lparname) - 1; i >= 0; i--) { ret_lparname[i] = guest_to_host((int)lparname[i]); if(isspace(ret_lparname[i]) && !ret_lparname[i+1]) ret_lparname[i] = '\0'; } return ret_lparname; } /*-------------------------------------------------------------------*/ /* MANUFACTURER NAME */ /* Set by: MANUFACTURER configuration statement */ /* Retrieved by: STSI instruction */ /*-------------------------------------------------------------------*/ /* "H R C" */ static BYTE manufact[16] = { 0xC8,0xD9,0xC3,0x40,0x40,0x40,0x40,0x40, 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 }; void set_manufacturer(char *name) { size_t i; for(i = 0; name && i < strlen(name) && i < sizeof(manufact); i++) if(isprint(name[i])) manufact[i] = host_to_guest((int)(islower(name[i]) ? toupper(name[i]) : name[i])); else manufact[i] = 0x40; for(; i < sizeof(manufact); i++) manufact[i] = 0x40; } void get_manufacturer(BYTE *dest) { memcpy(dest, manufact, sizeof(manufact)); } /*-------------------------------------------------------------------*/ /* MANUFACTURING PLANT NAME */ /* Set by: PLANT configuration statement */ /* Retrieved by: STSI instruction */ /*-------------------------------------------------------------------*/ /* "Z Z" */ static BYTE plant[4] = { 0xE9,0xE9,0x40,0x40 }; void set_plant(char *name) { size_t i; for(i = 0; name && i < strlen(name) && i < sizeof(plant); i++) if(isprint(name[i])) plant[i] = host_to_guest((int)(islower(name[i]) ? toupper(name[i]) : name[i])); else plant[i] = 0x40; for(; i < sizeof(plant); i++) plant[i] = 0x40; } void get_plant(BYTE *dest) { memcpy(dest, plant, sizeof(plant)); } /*-------------------------------------------------------------------*/ /* MODEL IDENTIFICATION */ /* Set by: MODEL configuration statement */ /* Retrieved by: STSI instruction */ /*-------------------------------------------------------------------*/ /* "E M U L A T O R" */ static BYTE model[16] = { 0xC5,0xD4,0xE4,0xD3,0xC1,0xE3,0xD6,0xD9, 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 }; static BYTE modelcapa[16] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }; static BYTE modelperm[16] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }; static BYTE modeltemp[16] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }; void set_model(int argc, char *m1, char *m2, char *m3, char *m4) { if (argc > 1 && m1 != NULL) copy_stringz_to_ebcdic(model, sizeof(model), m1); if (argc > 2 && m2 != NULL) copy_stringz_to_ebcdic(modelcapa, sizeof(modelcapa), m2); if (argc > 3 && m3 != NULL) copy_stringz_to_ebcdic(modelperm, sizeof(modelperm), m3); if (argc > 4 && m4 != NULL) copy_stringz_to_ebcdic(modeltemp, sizeof(modeltemp), m4); } void get_model(BYTE *dest) { memcpy(dest, model, sizeof(model)); } void get_modelcapa(BYTE *dest) { memcpy(dest, modelcapa, sizeof(modelcapa)); } void get_modelperm(BYTE *dest) { memcpy(dest, modelperm, sizeof(modelperm)); } void get_modeltemp(BYTE *dest) { memcpy(dest, modeltemp, sizeof(modeltemp)); } /*-------------------------------------------------------------------*/ /* SYSTEM TYPE IDENTIFICATION */ /* Set by: SERVC instruction */ /* Retrieved by: DIAG204 instruction */ /*-------------------------------------------------------------------*/ static BYTE systype[8] = { 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 }; void set_systype(BYTE *src) { memcpy(systype, src, sizeof(systype)); } void get_systype(BYTE *dst) { memcpy(dst, systype, sizeof(systype)); } /*-------------------------------------------------------------------*/ /* SYSTEM NAME */ /* Set by: SERVC instruction */ /* Retrieved by: DIAG204 instruction */ /*-------------------------------------------------------------------*/ static BYTE sysname[8] = { 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 }; void set_sysname(BYTE *src) { memcpy(sysname, src, sizeof(sysname)); } void get_sysname(BYTE *dst) { memcpy(dst, sysname, sizeof(sysname)); } /*-------------------------------------------------------------------*/ /* SYSPLEX NAME */ /* Set by: SERVC instruction */ /* Retrieved by: DIAG204 instruction */ /*-------------------------------------------------------------------*/ static BYTE sysplex[8] = { 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 }; void set_sysplex(BYTE *src) { memcpy(sysplex, src, sizeof(sysplex)); } void get_sysplex(BYTE *dst) { memcpy(dst, sysplex, sizeof(sysplex)); } /*-------------------------------------------------------------------*/ /* Retrieve Multiprocessing CPU-Capability Adjustment Factors */ /* */ /* This function retrieves the Multiprocessing CPU-Capability */ /* Adjustment Factor values for SYSIB (System Information Block) */ /* 1.2.2 as described in the Principles of Operations manual for */ /* the STORE SYSTEM INFORMATION instruction. */ /* */ /* Input: */ /* dest Address of where to store the information. */ /* Output: */ /* The requested MP Factor values at the address specified. */ /* Used by: */ /* B27D STSI Store System Information (Basic-machine All CPUs) */ /* B220 SERVC Service Call (read_scpinfo) */ /*-------------------------------------------------------------------*/ void get_mpfactors(BYTE *dest) { /*-------------------------------------------------------------------*/ /* The new z10 machine will use a denominator of 65535 for better */ /* granularity. But this will mess up old software. We will stick */ /* to the old value of 100. Bernard Feb 26, 2010. */ /*-------------------------------------------------------------------*/ #define MPFACTOR_DENOMINATOR 100 #define MPFACTOR_PERCENT 95 static U16 mpfactors[MAX_CPU_ENGINES-1] = {0}; static BYTE didthis = 0; if (!didthis) { /* First time: initialize array... */ U32 mpfactor = MPFACTOR_DENOMINATOR; size_t i; for (i=0; i < arraysize( mpfactors ); i++) { /* Calculate the value of each subsequent entry as percentage of the previous entry's value. */ mpfactor = (mpfactor * MPFACTOR_PERCENT) / 100; STORE_HW( &mpfactors[i], (U16) mpfactor ); } didthis = 1; } /* Return the requested information... */ memcpy( dest, &mpfactors[0], (MAX_CPU-1) * sizeof(U16) ); } hercules-3.07/logger.c000644 000765 000765 00000046427 11143760543 016407 0ustar00jmaynardjmaynard000000 000000 /* LOGGER.C (c) Copyright Jan Jaeger, 2003-2009 */ /* System logger functions */ // $Id: logger.c 5126 2009-01-23 13:05:56Z bernard $ /* If standard output or standard error is redirected then the log */ /* is written to the redirection. */ /* If standard output and standard error are both redirected then */ /* the system log is written to the redirection of standard error */ /* the redirection of standard output is ignored in this case, */ /* and background mode is assumed. */ /* Any thread can determine background mode by inspecting stderr */ /* for isatty() */ // $Log$ // Revision 1.54 2008/11/29 21:28:01 rbowler // Fix warnings C4267 because win64 declares send length as int not size_t // // Revision 1.53 2008/11/04 05:56:31 fish // Put ensure consistent create_thread ATTR usage change back in // // Revision 1.52 2008/11/03 15:31:54 rbowler // Back out consistent create_thread ATTR modification // // Revision 1.51 2008/10/18 09:32:21 fish // Ensure consistent create_thread ATTR usage // // Revision 1.50 2008/08/23 11:58:52 fish // Remove "" color string from most logfile hardcopy o/p // // Revision 1.49 2007/06/23 00:04:14 ivan // Update copyright notices to include current year (2007) // // Revision 1.48 2007/02/27 21:59:32 kleonard // PR# misc/87 startup messages fix completion // // Revision 1.47 2007/01/31 00:48:03 kleonard // Add logopt config statement and panel command // // Revision 1.46 2006/12/08 09:43:28 jj // Add CVS message log // #include "hstdinc.h" #define _LOGGER_C_ #define _HUTIL_DLL_ #include "hercules.h" #include "opcode.h" /* Required for SETMODE macro */ static COND logger_cond; static LOCK logger_lock; static TID logger_tid; static char *logger_buffer; static int logger_bufsize; static int logger_currmsg; static int logger_wrapped; static int logger_active=0; static FILE *logger_syslog[2]; /* Syslog read/write pipe */ int logger_syslogfd[2]; /* pairs */ static FILE *logger_hrdcpy; /* Hardcopy log or zero */ static int logger_hrdcpyfd; /* Hardcopt fd or -1 */ /* Find the index for a specific line number in the log, */ /* one being the most recent line */ /* Example: */ /* read the last 5 lines in the syslog: */ /* */ /* int msgnum; */ /* int msgidx; */ /* char *msgbuf; */ /* */ /* msgidx = log_line(5); */ /* while((msgcnt = log_read(&msgbuf, &msgidx, LOG_NOBLOCK))) */ /* function_to_process_log(msgbuf, msgcnt); */ /* */ DLL_EXPORT int log_line(int linenumber) { char *msgbuf[2] = {NULL, NULL}, *tmpbuf = NULL; int msgidx[2] = { -1, -1 }; int msgcnt[2] = {0, 0}; int i; if(!linenumber++) return logger_currmsg; /* Find the last two blocks in the log */ do { msgidx[0] = msgidx[1]; msgbuf[0] = msgbuf[1]; msgcnt[0] = msgcnt[1]; } while((msgcnt[1] = log_read(&msgbuf[1], &msgidx[1], LOG_NOBLOCK))); for(i = 0; i < 2 && linenumber; i++) if(msgidx[i] != -1) { for(; linenumber > 0; linenumber--) { if(!(tmpbuf = (void *)memrchr(msgbuf[i],'\n',msgcnt[i]))) break; msgcnt[i] = tmpbuf - msgbuf[i]; } if(!linenumber) break; } while(i < 2 && tmpbuf && (*tmpbuf == '\r' || *tmpbuf == '\n')) { tmpbuf++; msgcnt[i]++; } return i ? msgcnt[i] + msgidx[0] : msgcnt[i]; } /* log_read - read system log */ /* parameters: */ /* buffer - pointer to bufferpointer */ /* the bufferpointer will be returned */ /* msgindex - an index used on multiple read requests */ /* a value of -1 ensures that reading starts at the */ /* oldest entry in the log */ /* block - LOG_NOBLOCK - non blocking request */ /* LOG_BLOCK - blocking request */ /* returns: */ /* number of bytes in buffer or zero */ /* */ /* */ DLL_EXPORT int log_read(char **buffer, int *msgindex, int block) { int bytes_returned; obtain_lock(&logger_lock); if(*msgindex == logger_currmsg && block) { if(logger_active) { wait_condition(&logger_cond, &logger_lock); } else { *msgindex = logger_currmsg; *buffer = logger_buffer + logger_currmsg; release_lock(&logger_lock); return 0; } } if(*msgindex != logger_currmsg) { if(*msgindex < 0) *msgindex = logger_wrapped ? logger_currmsg : 0; if(*msgindex < 0 || *msgindex >= logger_bufsize) *msgindex = 0; *buffer = logger_buffer + *msgindex; if(*msgindex >= logger_currmsg) { bytes_returned = logger_bufsize - *msgindex; *msgindex = 0; } else { bytes_returned = logger_currmsg - *msgindex; *msgindex = logger_currmsg; } } else bytes_returned = 0; release_lock(&logger_lock); return bytes_returned; } static void logger_term(void *arg) { UNREFERENCED(arg); if(logger_active) { char* term_msg = _("HHCLG014I logger thread terminating\n"); size_t term_msg_len = strlen(term_msg); obtain_lock(&logger_lock); /* Flush all pending logger o/p before redirecting?? */ fflush(stdout); /* Redirect all output to stderr */ dup2(STDERR_FILENO, STDOUT_FILENO); /* Tell logger thread we want it to exit */ logger_active = 0; /* Send the logger a message to wake it up */ write_pipe( logger_syslogfd[LOG_WRITE], term_msg, term_msg_len ); release_lock(&logger_lock); /* Wait for the logger to terminate */ join_thread( logger_tid, NULL ); detach_thread( logger_tid ); } } static void logger_logfile_write( void* pBuff, size_t nBytes ) { if ( fwrite( pBuff, nBytes, 1, logger_hrdcpy ) != 1 ) { fprintf(logger_hrdcpy, _("HHCLG003E Error writing hardcopy log: %s\n"), strerror(errno)); } if ( sysblk.shutdown ) fflush ( logger_hrdcpy ); } #ifdef OPTION_TIMESTAMP_LOGFILE /* ZZ FIXME: * This should really be part of logmsg, as the timestamps have currently * the time when the logger reads the message from the log pipe. There can be * quite a delay at times when there is a high system activity. Moving the timestamp * to logmsg() will fix this. * The timestamp option should also NOT depend on anything like daemon mode. * logs entries should always be timestamped, in a fixed format, such that * log readers may decide to skip the timestamp when displaying (ie panel.c). */ static void logger_logfile_timestamp() { if (!sysblk.daemon_mode) { struct timeval now; time_t tt; char hhmmss[10]; gettimeofday( &now, NULL ); tt = now.tv_sec; strlcpy( hhmmss, ctime(&tt)+11, sizeof(hhmmss) ); logger_logfile_write( hhmmss, strlen(hhmmss) ); } } #endif static void logger_thread(void *arg) { int bytes_read; UNREFERENCED(arg); /* Set root mode in order to set priority */ SETMODE(ROOT); /* Set device thread priority; ignore any errors */ setpriority(PRIO_PROCESS, 0, sysblk.devprio); /* Back to user mode */ SETMODE(USER); #if !defined( _MSVC_ ) /* Redirect stdout to the logger */ if(dup2(logger_syslogfd[LOG_WRITE],STDOUT_FILENO) == -1) { if(logger_hrdcpy) fprintf(logger_hrdcpy, _("HHCLG001E Error redirecting stdout: %s\n"), strerror(errno)); exit(1); } #endif /* !defined( _MSVC_ ) */ setvbuf (stdout, NULL, _IONBF, 0); /* call logger_term on system shutdown */ hdl_adsc("logger_term",logger_term, NULL); obtain_lock(&logger_lock); logger_active = 1; /* Signal initialization complete */ signal_condition(&logger_cond); release_lock(&logger_lock); /* ZZ FIXME: We must empty the read pipe before we terminate */ /* (Couldn't we just loop waiting for a 'select(,&readset,,,timeout)' to return zero?? Or use the 'poll' function similarly?? - Fish) */ while(logger_active) { bytes_read = read_pipe(logger_syslogfd[LOG_READ],logger_buffer + logger_currmsg, ((logger_bufsize - logger_currmsg) > LOG_DEFSIZE ? LOG_DEFSIZE : logger_bufsize - logger_currmsg)); if(bytes_read == -1) { int read_pipe_errno = HSO_errno; // (ignore any/all errors at shutdown) if (sysblk.shutdown) continue; if (HSO_EINTR == read_pipe_errno) continue; if(logger_hrdcpy) fprintf(logger_hrdcpy, _("HHCLG002E Error reading syslog pipe: %s\n"), strerror(read_pipe_errno)); bytes_read = 0; } /* If Hercules is not running in daemon mode and panel initialization is not yet complete, write message to stderr so the user can see it on the terminal */ if (!sysblk.daemon_mode) { if (!sysblk.panel_init) { /* (ignore any errors; we did the best we could) */ fwrite( logger_buffer + logger_currmsg, bytes_read, 1, stderr ); } } /* Write log data to hardcopy file */ if (logger_hrdcpy) #if !defined( OPTION_TIMESTAMP_LOGFILE ) { char* pLeft2 = logger_buffer + logger_currmsg; int nLeft2 = bytes_read; #if defined( OPTION_MSGCLR ) /* Remove " 5 && strncasecmp( pLeft2, "', nLeft2-4 )) != NULL ) { pLeft2++; nLeft2 -= (pLeft2 - (logger_buffer + logger_currmsg)); } else { pLeft2 = logger_buffer + logger_currmsg; nLeft2 = bytes_read; } #endif // defined( OPTION_MSGCLR ) logger_logfile_write( pLeft2, nLeft2 ); } #else // defined( OPTION_TIMESTAMP_LOGFILE ) { /* Need to prefix each line with a timestamp. */ static int needstamp = 1; char* pLeft = logger_buffer + logger_currmsg; int nLeft = bytes_read; char* pRight = NULL; int nRight = 0; char* pNL = NULL; /* (pointer to NEWLINE character) */ if (needstamp) { if (!sysblk.logoptnotime) logger_logfile_timestamp(); needstamp = 0; } while ( (pNL = memchr( pLeft, '\n', nLeft )) != NULL ) { pRight = pNL + 1; nRight = nLeft - (pRight - pLeft); nLeft -= nRight; #if defined( OPTION_MSGCLR ) /* Remove "" color string if it exists */ { char* pLeft2 = pLeft; int nLeft2 = nLeft; if (1 && nLeft > 5 && strncasecmp( pLeft, "', nLeft-4 )) != NULL ) { pLeft2++; nLeft2 -= (pLeft2 - pLeft); } else { pLeft2 = pLeft; nLeft2 = nLeft; } logger_logfile_write( pLeft2, nLeft2 ); } #else // !defined( OPTION_MSGCLR ) logger_logfile_write( pLeft, nLeft ); #endif // defined( OPTION_MSGCLR ) pLeft = pRight; nLeft = nRight; if (!nLeft) { needstamp = 1; break; } if (!sysblk.logoptnotime) logger_logfile_timestamp(); } if (nLeft) logger_logfile_write( pLeft, nLeft ); } #endif // !defined( OPTION_TIMESTAMP_LOGFILE ) /* Increment buffer index to next available position */ logger_currmsg += bytes_read; if(logger_currmsg >= logger_bufsize) { logger_currmsg = 0; logger_wrapped = 1; } /* Notify all interested parties new log data is available */ obtain_lock(&logger_lock); broadcast_condition(&logger_cond); release_lock(&logger_lock); } /* Logger is now terminating */ obtain_lock(&logger_lock); /* Write final message to hardcopy file */ if (logger_hrdcpy) { char* term_msg = _("HHCLG014I logger thread terminating\n"); size_t term_msg_len = strlen(term_msg); #ifdef OPTION_TIMESTAMP_LOGFILE if (!sysblk.logoptnotime) logger_logfile_timestamp(); #endif logger_logfile_write( term_msg, term_msg_len ); } /* Redirect all msgs to stderr */ logger_syslog[LOG_WRITE] = stderr; logger_syslogfd[LOG_WRITE] = STDERR_FILENO; fflush(stderr); /* Signal any waiting tasks */ broadcast_condition(&logger_cond); release_lock(&logger_lock); } DLL_EXPORT void logger_init(void) { initialize_condition (&logger_cond); initialize_lock (&logger_lock); obtain_lock(&logger_lock); if(fileno(stdin)>=0 || fileno(stdout)>=0 || fileno(stderr)>=0) { logger_syslog[LOG_WRITE] = stderr; /* If standard error is redirected, then use standard error as the log file. */ if(!isatty(STDOUT_FILENO) && !isatty(STDERR_FILENO)) { /* Ignore standard output to the extent that it is treated as standard error */ logger_hrdcpyfd = dup(STDOUT_FILENO); if(dup2(STDERR_FILENO,STDOUT_FILENO) == -1) { fprintf(stderr, _("HHCLG004E Error duplicating stderr: %s\n"), strerror(errno)); exit(1); } } else { if(!isatty(STDOUT_FILENO)) { logger_hrdcpyfd = dup(STDOUT_FILENO); if(dup2(STDERR_FILENO,STDOUT_FILENO) == -1) { fprintf(stderr, _("HHCLG004E Error duplicating stderr: %s\n"), strerror(errno)); exit(1); } } if(!isatty(STDERR_FILENO)) { logger_hrdcpyfd = dup(STDERR_FILENO); if(dup2(STDOUT_FILENO,STDERR_FILENO) == -1) { fprintf(stderr, _("HHCLG005E Error duplicating stdout: %s\n"), strerror(errno)); exit(1); } } } if(logger_hrdcpyfd == -1) { logger_hrdcpyfd = 0; fprintf(stderr, _("HHCLG006E Duplicate error redirecting hardcopy log: %s\n"), strerror(errno)); } if(logger_hrdcpyfd) { if(!(logger_hrdcpy = fdopen(logger_hrdcpyfd,"w"))) fprintf(stderr, _("HHCLG007S Hardcopy log fdopen failed: %s\n"), strerror(errno)); } if(logger_hrdcpy) setvbuf(logger_hrdcpy, NULL, _IONBF, 0); } else { logger_syslog[LOG_WRITE]=fopen("LOG","a"); } logger_bufsize = LOG_DEFSIZE; if(!(logger_buffer = malloc(logger_bufsize))) { fprintf(stderr, _("HHCLG008S logbuffer malloc failed: %s\n"), strerror(errno)); exit(1); } if(create_pipe(logger_syslogfd)) { fprintf(stderr, _("HHCLG009S Syslog message pipe creation failed: %s\n"), strerror(errno)); exit(1); /* Hercules running without syslog */ } setvbuf (logger_syslog[LOG_WRITE], NULL, _IONBF, 0); if (create_thread (&logger_tid, JOINABLE, logger_thread, NULL, "logger_thread") ) { fprintf(stderr, _("HHCLG012E Cannot create logger thread: %s\n"), strerror(errno)); exit(1); } wait_condition(&logger_cond, &logger_lock); release_lock(&logger_lock); } DLL_EXPORT void log_sethrdcpy(char *filename) { FILE *temp_hrdcpy = logger_hrdcpy; FILE *new_hrdcpy; int new_hrdcpyfd; if(!filename) { if(!logger_hrdcpy) { logmsg(_("HHCLG014E log not active\n")); return; } else { obtain_lock(&logger_lock); logger_hrdcpy = 0; logger_hrdcpyfd = 0; release_lock(&logger_lock); fprintf(temp_hrdcpy,_("HHCLG015I log closed\n")); fclose(temp_hrdcpy); logmsg(_("HHCLG015I log closed\n")); return; } } else { char pathname[MAX_PATH]; hostpath(pathname, filename, sizeof(pathname)); new_hrdcpyfd = open(pathname, O_WRONLY | O_CREAT | O_TRUNC /* O_SYNC */, S_IRUSR | S_IWUSR | S_IRGRP); if(new_hrdcpyfd < 0) { logmsg(_("HHCLG016E Error opening logfile %s: %s\n"), filename,strerror(errno)); return; } else { if(!(new_hrdcpy = fdopen(new_hrdcpyfd,"w"))) { logmsg(_("HHCLG017S log file fdopen failed for %s: %s\n"), filename, strerror(errno)); return; } else { setvbuf(new_hrdcpy, NULL, _IONBF, 0); obtain_lock(&logger_lock); logger_hrdcpy = new_hrdcpy; logger_hrdcpyfd = new_hrdcpyfd; release_lock(&logger_lock); if(temp_hrdcpy) { fprintf(temp_hrdcpy,_("HHCLG018I log switched to %s\n"), filename); fclose(temp_hrdcpy); } } } } } /* log_wakeup - Wakeup any blocked threads. Useful during shutdown. */ DLL_EXPORT void log_wakeup(void *arg) { UNREFERENCED(arg); obtain_lock(&logger_lock); broadcast_condition(&logger_cond); release_lock(&logger_lock); } hercules-3.07/logger.h000644 000765 000765 00000003565 11143760543 016410 0ustar00jmaynardjmaynard000000 000000 /* LOGGER.H (c) Copyright Jan Jaeger, 2003-2009 */ /* System logger functions */ // $Id: logger.h 5126 2009-01-23 13:05:56Z bernard $ // // $Log$ // Revision 1.22 2007/06/23 00:04:14 ivan // Update copyright notices to include current year (2007) // // Revision 1.21 2006/12/08 09:43:28 jj // Add CVS message log // #ifndef __LOGGER_H__ #define __LOGGER_H__ #ifndef _LOGMSG_C_ #ifndef _HUTIL_DLL_ #define LOG_DLL_IMPORT DLL_IMPORT #else /* _HUTIL_DLL_ */ #define LOG_DLL_IMPORT extern #endif /* _HUTIL_DLL_ */ #else /* _LOGGER_C_ */ #define LOG_DLL_IMPORT DLL_EXPORT #endif /* _LOGGER_C_ */ #ifndef _LOGGER_C_ #ifndef _HUTIL_DLL_ #define LOGR_DLL_IMPORT DLL_IMPORT #else #define LOGR_DLL_IMPORT extern #endif #else #define LOGR_DLL_IMPORT DLL_EXPORT #endif #define LOG_READ 0 #define LOG_WRITE 1 extern int logger_syslogfd[2]; #define LOG_NOBLOCK 0 #define LOG_BLOCK 1 #if defined(SSIZE_MAX) && SSIZE_MAX < 1048576 #define LOG_DEFSIZE SSIZE_MAX #else #define LOG_DEFSIZE 65536 #endif /* Logging functions in logmsg.c */ LOG_DLL_IMPORT void logmsg(char *,...); LOG_DLL_IMPORT void logmsgp(char *,...); LOG_DLL_IMPORT void logmsgb(char *,...); LOG_DLL_IMPORT void logdevtr(DEVBLK *dev, char *, ...); LOGR_DLL_IMPORT void logger_init(void); LOGR_DLL_IMPORT int log_read(char **buffer, int *msgindex, int block); LOGR_DLL_IMPORT int log_line(int linenumber); LOGR_DLL_IMPORT void log_sethrdcpy(char *filename); LOGR_DLL_IMPORT void log_wakeup(void *arg); /* Log routing section */ typedef void LOG_WRITER(void *,char *); typedef void LOG_CLOSER(void *); LOG_DLL_IMPORT int log_open(LOG_WRITER*,LOG_CLOSER*,void *); LOG_DLL_IMPORT void log_close(void); LOG_DLL_IMPORT void log_write(int,char *); /* End of log routing section */ /* Log routing utility */ LOG_DLL_IMPORT char *log_capture(void *(*)(void *),void *); #endif hercules-3.07/logmsg.c000644 000765 000765 00000017312 11143760542 016406 0ustar00jmaynardjmaynard000000 000000 /* LOGMSG.C : ISW 2003 */ /* logmsg frontend routing */ // $Id: logmsg.c 4110 2006-12-11 17:14:29Z rbowler $ // // $Log$ // Revision 1.18 2006/12/08 09:43:28 jj // Add CVS message log // #include "hstdinc.h" #define _HUTIL_DLL_ #define _LOGMSG_C_ #include "hercules.h" #define BFR_CHUNKSIZE (256) /******************************************/ /* UTILITY MACRO BFR_VSNPRINTF */ /* Original design by Fish */ /* Modified by Jay Maynard */ /* Further modification by Ivan Warren */ /* */ /* Purpose : set 'bfr' to contain */ /* a C string based on a message format */ /* and a va_list of args. */ /* bfr must be free()d when over with */ /* this macro can ONLY be used from the */ /* topmost variable arg function */ /* that is the va_list cannot be passed */ /* as a parameter from another function */ /* since va_xxx functions behavio(u)r */ /* seems to be undefined in those cases */ /* char *bfr; must be originally defined */ /* int siz; must be defined and cont- */ /* ain a start size */ /* va_list vl; must be defined and init- */ /* ialised with va_start */ /* char *msg; is the message format */ /* int rc; to contain final size */ /******************************************/ #define BFR_VSNPRINTF() \ bfr=malloc(siz); \ rc=-1; \ while(bfr&&rc<0) \ { \ va_start(vl,msg); \ rc=vsnprintf(bfr,siz,msg,vl); \ va_end(vl); \ if(rc>=0 && rcccwtrace||dev->ccwstep) { logmsg("%4.4X:",dev->devnum); BFR_VSNPRINTF(); if(bfr) log_write(2,bfr); } #ifdef NEED_LOGMSG_FFLUSH fflush(stdout); #endif if(bfr) { free(bfr); } } /* end function logdevtr */ /* panel : 0 - No, 1 - Only, 2 - Also */ DLL_EXPORT void log_write(int panel,char *msg) { /* (log_write function proper starts here) */ int slot; log_route_init(); if(panel==1) { write_pipe( logger_syslogfd[LOG_WRITE], msg, strlen(msg) ); return; } obtain_lock(&log_route_lock); slot=log_route_search(thread_id()); release_lock(&log_route_lock); if(slot<0 || panel>0) { write_pipe( logger_syslogfd[LOG_WRITE], msg, strlen(msg) ); if(slot<0) return; } log_routes[slot].w(log_routes[slot].u,msg); return; } /* capture log output routine series */ /* log_capture is a sample of how to */ /* use log rerouting. */ /* log_capture takes 2 args : */ /* a ptr to a function taking 1 parm */ /* the function parm */ struct log_capture_data { char *obfr; size_t sz; }; DLL_EXPORT void log_capture_writer(void *vcd,char *msg) { struct log_capture_data *cd; if(!vcd||!msg)return; cd=(struct log_capture_data *)vcd; if(cd->sz==0) { cd->sz=strlen(msg)+1; cd->obfr=malloc(cd->sz); cd->obfr[0]=0; } else { cd->sz+=strlen(msg); cd->obfr=realloc(cd->obfr,cd->sz); } strcat(cd->obfr,msg); return; } DLL_EXPORT void log_capture_closer(void *vcd) { UNREFERENCED(vcd); return; } DLL_EXPORT char *log_capture(void *(*fun)(void *),void *p) { struct log_capture_data cd; cd.obfr=NULL; cd.sz=0; log_open(log_capture_writer,log_capture_closer,&cd); fun(p); log_close(); return(cd.obfr); } hercules-3.07/losc.c000644 000765 000765 00000004312 11321734033 016044 0ustar00jmaynardjmaynard000000 000000 /* LOSC.C (c) Copyright Jan Jaeger, 2009 */ /* Hercules Licensed Operating System Check */ // $Id: losc.c 5551 2009-12-17 13:32:54Z rbowler $ #include "hstdinc.h" #if !defined(_HENGINE_DLL_) #define _HENGINE_DLL_ #endif #if !defined(_LOSC_C_) #define _LOSC_C_ #endif #include "hercules.h" #ifdef OPTION_MSGCLR #define KEEPMSG "" #else #define KEEPMSG "" #endif static char *licensed_os[] = { "MVS", /* Generic name for MVS, OS/390, z/OS */ "VM", /* Generic name for VM, VM/XA, VM/ESA, z/VM */ "VSE", "TPF", NULL }; static int os_licensed = 0; static int check_done = 0; void losc_set (int license_status) { os_licensed = license_status; check_done = 0; } void losc_check(char *ostype) { char **lictype; int i; CPU_BITMAP mask; if(check_done) return; else check_done = 1; for(lictype = licensed_os; *lictype; lictype++) { if(!strncasecmp(ostype, *lictype, strlen(*lictype))) { if(os_licensed == PGM_PRD_OS_LICENSED) { logmsg(_( KEEPMSG "HHCCF039W PGMPRDOS LICENSED specified.\n" KEEPMSG " A licensed program product operating system is running.\n" KEEPMSG " You are responsible for meeting all conditions of your\n" KEEPMSG " software licenses.\n")); } else { logmsg(_( KEEPMSG "HHCCF079A A licensed program product operating system has been\n" KEEPMSG " detected. All processors have been stopped.\n")); mask = sysblk.started_mask; for (i = 0; mask; i++) { if (mask & 1) { REGS *regs = sysblk.regs[i]; regs->opinterv = 1; regs->cpustate = CPUSTATE_STOPPING; ON_IC_INTERRUPT(regs); signal_condition(®s->intcond); } mask >>= 1; } } } } } hercules-3.07/ltdl.c000644 000765 000765 00000310661 11143760542 016060 0ustar00jmaynardjmaynard000000 000000 /* ltdl.c -- system independent dlopen wrapper Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc. Originally by Thomas Tanner This file is part of GNU Libtool. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. As a special exception to the GNU Lesser General Public License, if you distribute this file as part of a program or library that is built using GNU libtool, you may include it under the same distribution terms that you use for the rest of that program. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #if HAVE_CONFIG_H #include "config.h" // Hercules build configuration options/settings #endif #if defined(HDL_USE_LIBTOOL) #if HAVE_UNISTD_H # include #endif #if HAVE_STDIO_H # include #endif #if HAVE_STDLIB_H # include #endif #if HAVE_STRING_H # include #else # if HAVE_STRINGS_H # include # endif #endif #if HAVE_CTYPE_H # include #endif #if HAVE_MALLOC_H # include #endif #if HAVE_MEMORY_H # include #endif #if HAVE_ERRNO_H # include #endif #ifndef __WINDOWS__ # ifdef __WIN32__ # define __WINDOWS__ # endif #endif #undef LT_USE_POSIX_DIRENT #ifdef HAVE_CLOSEDIR # ifdef HAVE_OPENDIR # ifdef HAVE_READDIR # ifdef HAVE_DIRENT_H # define LT_USE_POSIX_DIRENT # endif /* HAVE_DIRENT_H */ # endif /* HAVE_READDIR */ # endif /* HAVE_OPENDIR */ #endif /* HAVE_CLOSEDIR */ #undef LT_USE_WINDOWS_DIRENT_EMULATION #ifndef LT_USE_POSIX_DIRENT # ifdef __WINDOWS__ # define LT_USE_WINDOWS_DIRENT_EMULATION # endif /* __WINDOWS__ */ #endif /* LT_USE_POSIX_DIRENT */ #ifdef LT_USE_POSIX_DIRENT # include # define LT_D_NAMLEN(dirent) (strlen((dirent)->d_name)) #else # ifdef LT_USE_WINDOWS_DIRENT_EMULATION # define LT_D_NAMLEN(dirent) (strlen((dirent)->d_name)) # else # define dirent direct # define LT_D_NAMLEN(dirent) ((dirent)->d_namlen) # if HAVE_SYS_NDIR_H # include # endif # if HAVE_SYS_DIR_H # include # endif # if HAVE_NDIR_H # include # endif # endif #endif #if HAVE_ARGZ_H # include #endif #if HAVE_ASSERT_H # include #else # define assert(arg) ((void) 0) #endif #include "ltdl.h" #if WITH_DMALLOC # include #endif /* --- WINDOWS SUPPORT --- */ #if defined(DLL_EXPORT) && defined(WIN32) # define LT_GLOBAL_DATA __declspec(dllexport) #else # define LT_GLOBAL_DATA #endif /* fopen() mode flags for reading a text file */ #undef LT_READTEXT_MODE #ifdef __WINDOWS__ # define LT_READTEXT_MODE "rt" #else # define LT_READTEXT_MODE "r" #endif #ifdef LT_USE_WINDOWS_DIRENT_EMULATION #include #define dirent lt_dirent #define DIR lt_DIR struct dirent { char d_name[2048]; int d_namlen; }; typedef struct _DIR { HANDLE hSearch; WIN32_FIND_DATA Win32FindData; BOOL firsttime; struct dirent file_info; } DIR; #endif /* LT_USE_WINDOWS_DIRENT_EMULATION */ /* --- MANIFEST CONSTANTS --- */ /* Standard libltdl search path environment variable name */ #undef LTDL_SEARCHPATH_VAR #define LTDL_SEARCHPATH_VAR "LTDL_LIBRARY_PATH" /* Standard libtool archive file extension. */ #undef LTDL_ARCHIVE_EXT #define LTDL_ARCHIVE_EXT ".la" /* max. filename length */ #ifndef LT_FILENAME_MAX # define LT_FILENAME_MAX 1024 #endif /* This is the maximum symbol size that won't require malloc/free */ #undef LT_SYMBOL_LENGTH #define LT_SYMBOL_LENGTH 128 /* This accounts for the _LTX_ separator */ #undef LT_SYMBOL_OVERHEAD #define LT_SYMBOL_OVERHEAD 5 /* --- MEMORY HANDLING --- */ /* These are the functions used internally. In addition to making use of the associated function pointers above, they also perform error handling. */ static char *lt_estrdup LT_PARAMS((const char *str)); static lt_ptr lt_emalloc LT_PARAMS((size_t size)); static lt_ptr lt_erealloc LT_PARAMS((lt_ptr addr, size_t size)); /* static lt_ptr rpl_realloc LT_PARAMS((lt_ptr ptr, size_t size)); */ #define rpl_realloc realloc /* These are the pointers that can be changed by the caller: */ LT_GLOBAL_DATA lt_ptr (*lt_dlmalloc) LT_PARAMS((size_t size)) = (lt_ptr (*) LT_PARAMS((size_t))) malloc; LT_GLOBAL_DATA lt_ptr (*lt_dlrealloc) LT_PARAMS((lt_ptr ptr, size_t size)) = (lt_ptr (*) LT_PARAMS((lt_ptr, size_t))) rpl_realloc; LT_GLOBAL_DATA void (*lt_dlfree) LT_PARAMS((lt_ptr ptr)) = (void (*) LT_PARAMS((lt_ptr))) free; /* The following macros reduce the amount of typing needed to cast assigned memory. */ #if WITH_DMALLOC #define LT_DLMALLOC(tp, n) ((tp *) xmalloc ((n) * sizeof(tp))) #define LT_DLREALLOC(tp, p, n) ((tp *) xrealloc ((p), (n) * sizeof(tp))) #define LT_DLFREE(p) \ LT_STMT_START { if (p) (p) = (xfree (p), (lt_ptr) 0); } LT_STMT_END #define LT_EMALLOC(tp, n) ((tp *) xmalloc ((n) * sizeof(tp))) #define LT_EREALLOC(tp, p, n) ((tp *) xrealloc ((p), (n) * sizeof(tp))) #else #define LT_DLMALLOC(tp, n) ((tp *) lt_dlmalloc ((n) * sizeof(tp))) #define LT_DLREALLOC(tp, p, n) ((tp *) lt_dlrealloc ((p), (n) * sizeof(tp))) #define LT_DLFREE(p) \ LT_STMT_START { if (p) (p) = (lt_dlfree (p), (lt_ptr) 0); } LT_STMT_END #define LT_EMALLOC(tp, n) ((tp *) lt_emalloc ((n) * sizeof(tp))) #define LT_EREALLOC(tp, p, n) ((tp *) lt_erealloc ((p), (n) * sizeof(tp))) #endif #define LT_DLMEM_REASSIGN(p, q) LT_STMT_START { \ if ((p) != (q)) { if (p) lt_dlfree (p); (p) = (q); (q) = 0; } \ } LT_STMT_END /* --- REPLACEMENT FUNCTIONS --- */ #undef strdup #define strdup rpl_strdup static char *strdup LT_PARAMS((const char *str)); static char * strdup(str) const char *str; { char *tmp = 0; if (str) { tmp = LT_DLMALLOC (char, 1+ strlen (str)); if (tmp) { strcpy(tmp, str); } } return tmp; } #if ! HAVE_STRCMP #undef strcmp #define strcmp rpl_strcmp static int strcmp LT_PARAMS((const char *str1, const char *str2)); static int strcmp (str1, str2) const char *str1; const char *str2; { if (str1 == str2) return 0; if (str1 == 0) return -1; if (str2 == 0) return 1; for (;*str1 && *str2; ++str1, ++str2) { if (*str1 != *str2) break; } return (int)(*str1 - *str2); } #endif #if ! HAVE_STRCHR # if HAVE_INDEX # define strchr index # else # define strchr rpl_strchr static const char *strchr LT_PARAMS((const char *str, int ch)); static const char* strchr(str, ch) const char *str; int ch; { const char *p; for (p = str; *p != (char)ch && *p != LT_EOS_CHAR; ++p) /*NOWORK*/; return (*p == (char)ch) ? p : 0; } # endif #endif /* !HAVE_STRCHR */ #if ! HAVE_STRRCHR # if HAVE_RINDEX # define strrchr rindex # else # define strrchr rpl_strrchr static const char *strrchr LT_PARAMS((const char *str, int ch)); static const char* strrchr(str, ch) const char *str; int ch; { const char *p, *q = 0; for (p = str; *p != LT_EOS_CHAR; ++p) { if (*p == (char) ch) { q = p; } } return q; } # endif #endif /* NOTE: Neither bcopy nor the memcpy implementation below can reliably handle copying in overlapping areas of memory. Use memmove (for which there is a fallback implmentation below) if you need that behaviour. */ #if ! HAVE_MEMCPY # if HAVE_BCOPY # define memcpy(dest, src, size) bcopy (src, dest, size) # else # define memcpy rpl_memcpy static lt_ptr memcpy LT_PARAMS((lt_ptr dest, const lt_ptr src, size_t size)); static lt_ptr memcpy (dest, src, size) lt_ptr dest; const lt_ptr src; size_t size; { size_t i = 0; for (i = 0; i < size; ++i) { dest[i] = src[i]; } return dest; } # endif /* !HAVE_BCOPY */ #endif /* !HAVE_MEMCPY */ #if ! HAVE_MEMMOVE # define memmove rpl_memmove static lt_ptr memmove LT_PARAMS((lt_ptr dest, const lt_ptr src, size_t size)); static lt_ptr memmove (dest, src, size) lt_ptr dest; const lt_ptr src; size_t size; { size_t i; if (dest < src) for (i = 0; i < size; ++i) { dest[i] = src[i]; } else if (dest > src) for (i = size -1; i >= 0; --i) { dest[i] = src[i]; } return dest; } #endif /* !HAVE_MEMMOVE */ #ifdef LT_USE_WINDOWS_DIRENT_EMULATION static void closedir LT_PARAMS((DIR *entry)); static void closedir(entry) DIR *entry; { assert(entry != (DIR *) NULL); FindClose(entry->hSearch); lt_dlfree((lt_ptr)entry); } static DIR * opendir LT_PARAMS((const char *path)); static DIR* opendir (path) const char *path; { char file_specification[LT_FILENAME_MAX]; DIR *entry; assert(path != (char *) NULL); (void) strncpy(file_specification,path,LT_FILENAME_MAX-1); (void) strcat(file_specification,"\\"); entry = LT_DLMALLOC (DIR,sizeof(DIR)); if (entry != (DIR *) 0) { entry->firsttime = TRUE; entry->hSearch = FindFirstFile(file_specification,&entry->Win32FindData); } if (entry->hSearch == INVALID_HANDLE_VALUE) { (void) strcat(file_specification,"\\*.*"); entry->hSearch = FindFirstFile(file_specification,&entry->Win32FindData); if (entry->hSearch == INVALID_HANDLE_VALUE) { LT_DLFREE (entry); return (DIR *) 0; } } return(entry); } static struct dirent *readdir LT_PARAMS((DIR *entry)); static struct dirent *readdir(entry) DIR *entry; { int status; if (entry == (DIR *) 0) return((struct dirent *) 0); if (!entry->firsttime) { status = FindNextFile(entry->hSearch,&entry->Win32FindData); if (status == 0) return((struct dirent *) 0); } entry->firsttime = FALSE; (void) strncpy(entry->file_info.d_name,entry->Win32FindData.cFileName, LT_FILENAME_MAX-1); entry->file_info.d_namlen = strlen(entry->file_info.d_name); return(&entry->file_info); } #endif /* LT_USE_WINDOWS_DIRENT_EMULATION */ /* According to Alexandre Oliva , ``realloc is not entirely portable'' In any case we want to use the allocator supplied by the user without burdening them with an lt_dlrealloc function pointer to maintain. Instead implement our own version (with known boundary conditions) using lt_dlmalloc and lt_dlfree. */ /* #undef realloc #define realloc rpl_realloc */ #if 0 /* You can't (re)define realloc unless you also (re)define malloc. Right now, this code uses the size of the *destination* to decide how much to copy. That's not right, but you can't know the size of the source unless you know enough about, or wrote malloc. So this code is disabled... */ static lt_ptr realloc (ptr, size) lt_ptr ptr; size_t size; { if (size == 0) { /* For zero or less bytes, free the original memory */ if (ptr != 0) { lt_dlfree (ptr); } return (lt_ptr) 0; } else if (ptr == 0) { /* Allow reallocation of a NULL pointer. */ return lt_dlmalloc (size); } else { /* Allocate a new block, copy and free the old block. */ lt_ptr mem = lt_dlmalloc (size); if (mem) { memcpy (mem, ptr, size); lt_dlfree (ptr); } /* Note that the contents of PTR are not damaged if there is insufficient memory to realloc. */ return mem; } } #endif #if ! HAVE_ARGZ_APPEND # define argz_append rpl_argz_append static error_t argz_append LT_PARAMS((char **pargz, size_t *pargz_len, const char *buf, size_t buf_len)); static error_t argz_append (pargz, pargz_len, buf, buf_len) char **pargz; size_t *pargz_len; const char *buf; size_t buf_len; { size_t argz_len; char *argz; assert (pargz); assert (pargz_len); assert ((*pargz && *pargz_len) || (!*pargz && !*pargz_len)); /* If nothing needs to be appended, no more work is required. */ if (buf_len == 0) return 0; /* Ensure there is enough room to append BUF_LEN. */ argz_len = *pargz_len + buf_len; argz = LT_DLREALLOC (char, *pargz, argz_len); if (!argz) return ENOMEM; /* Copy characters from BUF after terminating '\0' in ARGZ. */ memcpy (argz + *pargz_len, buf, buf_len); /* Assign new values. */ *pargz = argz; *pargz_len = argz_len; return 0; } #endif /* !HAVE_ARGZ_APPEND */ #if ! HAVE_ARGZ_CREATE_SEP # define argz_create_sep rpl_argz_create_sep static error_t argz_create_sep LT_PARAMS((const char *str, int delim, char **pargz, size_t *pargz_len)); static error_t argz_create_sep (str, delim, pargz, pargz_len) const char *str; int delim; char **pargz; size_t *pargz_len; { size_t argz_len; char *argz = 0; assert (str); assert (pargz); assert (pargz_len); /* Make a copy of STR, but replacing each occurence of DELIM with '\0'. */ argz_len = 1+ LT_STRLEN (str); if (argz_len) { const char *p; char *q; argz = LT_DLMALLOC (char, argz_len); if (!argz) return ENOMEM; for (p = str, q = argz; *p != LT_EOS_CHAR; ++p) { if (*p == delim) { /* Ignore leading delimiters, and fold consecutive delimiters in STR into a single '\0' in ARGZ. */ if ((q > argz) && (q[-1] != LT_EOS_CHAR)) *q++ = LT_EOS_CHAR; else --argz_len; } else *q++ = *p; } /* Copy terminating LT_EOS_CHAR. */ *q = *p; } /* If ARGZ_LEN has shrunk to nothing, release ARGZ's memory. */ if (!argz_len) LT_DLFREE (argz); /* Assign new values. */ *pargz = argz; *pargz_len = argz_len; return 0; } #endif /* !HAVE_ARGZ_CREATE_SEP */ #if ! HAVE_ARGZ_INSERT # define argz_insert rpl_argz_insert static error_t argz_insert LT_PARAMS((char **pargz, size_t *pargz_len, char *before, const char *entry)); static error_t argz_insert (pargz, pargz_len, before, entry) char **pargz; size_t *pargz_len; char *before; const char *entry; { assert (pargz); assert (pargz_len); assert (entry && *entry); /* No BEFORE address indicates ENTRY should be inserted after the current last element. */ if (!before) return argz_append (pargz, pargz_len, entry, 1+ LT_STRLEN (entry)); /* This probably indicates a programmer error, but to preserve semantics, scan back to the start of an entry if BEFORE points into the middle of it. */ while ((before > *pargz) && (before[-1] != LT_EOS_CHAR)) --before; { size_t entry_len = 1+ LT_STRLEN (entry); size_t argz_len = *pargz_len + entry_len; size_t offset = before - *pargz; char *argz = LT_DLREALLOC (char, *pargz, argz_len); if (!argz) return ENOMEM; /* Make BEFORE point to the equivalent offset in ARGZ that it used to have in *PARGZ incase realloc() moved the block. */ before = argz + offset; /* Move the ARGZ entries starting at BEFORE up into the new space at the end -- making room to copy ENTRY into the resulting gap. */ memmove (before + entry_len, before, *pargz_len - offset); memcpy (before, entry, entry_len); /* Assign new values. */ *pargz = argz; *pargz_len = argz_len; } return 0; } #endif /* !HAVE_ARGZ_INSERT */ #if ! HAVE_ARGZ_NEXT # define argz_next rpl_argz_next static char *argz_next LT_PARAMS((char *argz, size_t argz_len, const char *entry)); static char * argz_next (argz, argz_len, entry) char *argz; size_t argz_len; const char *entry; { assert ((argz && argz_len) || (!argz && !argz_len)); if (entry) { /* Either ARGZ/ARGZ_LEN is empty, or ENTRY points into an address within the ARGZ vector. */ assert ((!argz && !argz_len) || ((argz <= entry) && (entry < (argz + argz_len)))); /* Move to the char immediately after the terminating '\0' of ENTRY. */ entry = 1+ strchr (entry, LT_EOS_CHAR); /* Return either the new ENTRY, or else NULL if ARGZ is exhausted. */ return (entry >= argz + argz_len) ? 0 : (char *) entry; } else { /* This should probably be flagged as a programmer error, since starting an argz_next loop with the iterator set to ARGZ is safer. To preserve semantics, handle the NULL case by returning the start of ARGZ (if any). */ if (argz_len > 0) return argz; else return 0; } } #endif /* !HAVE_ARGZ_NEXT */ #if ! HAVE_ARGZ_STRINGIFY # define argz_stringify rpl_argz_stringify static void argz_stringify LT_PARAMS((char *argz, size_t argz_len, int sep)); static void argz_stringify (argz, argz_len, sep) char *argz; size_t argz_len; int sep; { assert ((argz && argz_len) || (!argz && !argz_len)); if (sep) { --argz_len; /* don't stringify the terminating EOS */ while (--argz_len > 0) { if (argz[argz_len] == LT_EOS_CHAR) argz[argz_len] = sep; } } } #endif /* !HAVE_ARGZ_STRINGIFY */ /* --- TYPE DEFINITIONS -- */ /* This type is used for the array of caller data sets in each handler. */ typedef struct { lt_dlcaller_id key; lt_ptr data; } lt_caller_data; /* --- OPAQUE STRUCTURES DECLARED IN LTDL.H --- */ /* Extract the diagnostic strings from the error table macro in the same order as the enumerated indices in ltdl.h. */ static const char *lt_dlerror_strings[] = { #define LT_ERROR(name, diagnostic) (diagnostic), lt_dlerror_table #undef LT_ERROR 0 }; /* This structure is used for the list of registered loaders. */ struct lt_dlloader { struct lt_dlloader *next; const char *loader_name; /* identifying name for each loader */ const char *sym_prefix; /* prefix for symbols */ lt_module_open *module_open; lt_module_close *module_close; lt_find_sym *find_sym; lt_dlloader_exit *dlloader_exit; lt_user_data dlloader_data; }; struct lt_dlhandle_struct { struct lt_dlhandle_struct *next; lt_dlloader *loader; /* dlopening interface */ lt_dlinfo info; int depcount; /* number of dependencies */ lt_dlhandle *deplibs; /* dependencies */ lt_module module; /* system module handle */ lt_ptr system; /* system specific data */ lt_caller_data *caller_data; /* per caller associated data */ int flags; /* various boolean stats */ }; /* Various boolean flags can be stored in the flags field of an lt_dlhandle_struct... */ #define LT_DLGET_FLAG(handle, flag) (((handle)->flags & (flag)) == (flag)) #define LT_DLSET_FLAG(handle, flag) ((handle)->flags |= (flag)) #define LT_DLRESIDENT_FLAG (0x01 << 0) /* ...add more flags here... */ #define LT_DLIS_RESIDENT(handle) LT_DLGET_FLAG(handle, LT_DLRESIDENT_FLAG) #define LT_DLSTRERROR(name) lt_dlerror_strings[LT_CONC(LT_ERROR_,name)] static const char objdir[] = LTDL_OBJDIR; static const char archive_ext[] = LTDL_ARCHIVE_EXT; #ifdef LTDL_SHLIB_EXT static const char shlib_ext[] = LTDL_SHLIB_EXT; #endif #ifdef LTDL_SYSSEARCHPATH static const char sys_search_path[] = LTDL_SYSSEARCHPATH; #endif /* --- MUTEX LOCKING --- */ /* Macros to make it easier to run the lock functions only if they have been registered. The reason for the complicated lock macro is to ensure that the stored error message from the last error is not accidentally erased if the current function doesn't generate an error of its own. */ #define LT_DLMUTEX_LOCK() LT_STMT_START { \ if (lt_dlmutex_lock_func) (*lt_dlmutex_lock_func)(); \ } LT_STMT_END #define LT_DLMUTEX_UNLOCK() LT_STMT_START { \ if (lt_dlmutex_unlock_func) (*lt_dlmutex_unlock_func)();\ } LT_STMT_END #define LT_DLMUTEX_SETERROR(errormsg) LT_STMT_START { \ if (lt_dlmutex_seterror_func) \ (*lt_dlmutex_seterror_func) (errormsg); \ else lt_dllast_error = (errormsg); } LT_STMT_END #define LT_DLMUTEX_GETERROR(errormsg) LT_STMT_START { \ if (lt_dlmutex_seterror_func) \ (errormsg) = (*lt_dlmutex_geterror_func) (); \ else (errormsg) = lt_dllast_error; } LT_STMT_END /* The mutex functions stored here are global, and are necessarily the same for all threads that wish to share access to libltdl. */ static lt_dlmutex_lock *lt_dlmutex_lock_func = 0; static lt_dlmutex_unlock *lt_dlmutex_unlock_func = 0; static lt_dlmutex_seterror *lt_dlmutex_seterror_func = 0; static lt_dlmutex_geterror *lt_dlmutex_geterror_func = 0; static const char *lt_dllast_error = 0; /* Either set or reset the mutex functions. Either all the arguments must be valid functions, or else all can be NULL to turn off locking entirely. The registered functions should be manipulating a static global lock from the lock() and unlock() callbacks, which needs to be reentrant. */ int lt_dlmutex_register (lock, unlock, seterror, geterror) lt_dlmutex_lock *lock; lt_dlmutex_unlock *unlock; lt_dlmutex_seterror *seterror; lt_dlmutex_geterror *geterror; { lt_dlmutex_unlock *old_unlock = unlock; int errors = 0; /* Lock using the old lock() callback, if any. */ LT_DLMUTEX_LOCK (); if ((lock && unlock && seterror && geterror) || !(lock || unlock || seterror || geterror)) { lt_dlmutex_lock_func = lock; lt_dlmutex_unlock_func = unlock; lt_dlmutex_geterror_func = geterror; } else { LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_MUTEX_ARGS)); ++errors; } /* Use the old unlock() callback we saved earlier, if any. Otherwise record any errors using internal storage. */ if (old_unlock) (*old_unlock) (); /* Return the number of errors encountered during the execution of this function. */ return errors; } /* --- ERROR HANDLING --- */ static const char **user_error_strings = 0; static int errorcount = LT_ERROR_MAX; int lt_dladderror (diagnostic) const char *diagnostic; { int errindex = 0; int result = -1; const char **temp = (const char **) 0; assert (diagnostic); LT_DLMUTEX_LOCK (); errindex = errorcount - LT_ERROR_MAX; temp = LT_EREALLOC (const char *, user_error_strings, 1 + errindex); if (temp) { user_error_strings = temp; user_error_strings[errindex] = diagnostic; result = errorcount++; } LT_DLMUTEX_UNLOCK (); return result; } int lt_dlseterror (errindex) int errindex; { int errors = 0; LT_DLMUTEX_LOCK (); if (errindex >= errorcount || errindex < 0) { /* Ack! Error setting the error message! */ LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_ERRORCODE)); ++errors; } else if (errindex < LT_ERROR_MAX) { /* No error setting the error message! */ LT_DLMUTEX_SETERROR (lt_dlerror_strings[errindex]); } else { /* No error setting the error message! */ LT_DLMUTEX_SETERROR (user_error_strings[errindex - LT_ERROR_MAX]); } LT_DLMUTEX_UNLOCK (); return errors; } static lt_ptr lt_emalloc (size) size_t size; { lt_ptr mem = lt_dlmalloc (size); if (size && !mem) LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY)); return mem; } static lt_ptr lt_erealloc (addr, size) lt_ptr addr; size_t size; { lt_ptr mem = lt_dlrealloc (addr, size); if (size && !mem) LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY)); return mem; } static char * lt_estrdup (str) const char *str; { char *copy = strdup (str); if (LT_STRLEN (str) && !copy) LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY)); return copy; } /* --- DLOPEN() INTERFACE LOADER --- */ #if HAVE_LIBDL /* dynamic linking with dlopen/dlsym */ #if HAVE_DLFCN_H # include #endif #if HAVE_SYS_DL_H # include #endif #ifdef RTLD_GLOBAL # define LT_GLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_GLOBAL DL_GLOBAL # endif #endif /* !RTLD_GLOBAL */ #ifndef LT_GLOBAL # define LT_GLOBAL 0 #endif /* !LT_GLOBAL */ /* We may have to define LT_LAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_LAZY_OR_NOW # ifdef RTLD_LAZY # define LT_LAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_LAZY_OR_NOW DL_LAZY # endif # endif /* !RTLD_LAZY */ #endif #ifndef LT_LAZY_OR_NOW # ifdef RTLD_NOW # define LT_LAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_LAZY_OR_NOW DL_NOW # endif # endif /* !RTLD_NOW */ #endif #ifndef LT_LAZY_OR_NOW # define LT_LAZY_OR_NOW 0 #endif /* !LT_LAZY_OR_NOW */ #if HAVE_DLERROR # define DLERROR(arg) dlerror () #else # define DLERROR(arg) LT_DLSTRERROR (arg) #endif static lt_module sys_dl_open (loader_data, filename) lt_user_data loader_data; const char *filename; { lt_module module = dlopen (filename, LT_GLOBAL | LT_LAZY_OR_NOW); loader_data=loader_data; if (!module) { LT_DLMUTEX_SETERROR (DLERROR (CANNOT_OPEN)); } return module; } static int sys_dl_close (loader_data, module) lt_user_data loader_data; lt_module module; { int errors = 0; loader_data=loader_data; if (dlclose (module) != 0) { LT_DLMUTEX_SETERROR (DLERROR (CANNOT_CLOSE)); ++errors; } return errors; } static lt_ptr sys_dl_sym (loader_data, module, symbol) lt_user_data loader_data; lt_module module; const char *symbol; { lt_ptr address = dlsym (module, symbol); loader_data=loader_data; if (!address) { LT_DLMUTEX_SETERROR (DLERROR (SYMBOL_NOT_FOUND)); } return address; } static struct lt_user_dlloader sys_dl = { # ifdef NEED_USCORE "_", # else 0, # endif sys_dl_open, sys_dl_close, sys_dl_sym, 0, 0 }; #endif /* HAVE_LIBDL */ /* --- SHL_LOAD() INTERFACE LOADER --- */ #if HAVE_SHL_LOAD /* dynamic linking with shl_load (HP-UX) (comments from gmodule) */ #ifdef HAVE_DL_H # include #endif /* some flags are missing on some systems, so we provide * harmless defaults. * * Mandatory: * BIND_IMMEDIATE - Resolve symbol references when the library is loaded. * BIND_DEFERRED - Delay code symbol resolution until actual reference. * * Optionally: * BIND_FIRST - Place the library at the head of the symbol search * order. * BIND_NONFATAL - The default BIND_IMMEDIATE behavior is to treat all * unsatisfied symbols as fatal. This flag allows * binding of unsatisfied code symbols to be deferred * until use. * [Perl: For certain libraries, like DCE, deferred * binding often causes run time problems. Adding * BIND_NONFATAL to BIND_IMMEDIATE still allows * unresolved references in situations like this.] * BIND_NOSTART - Do not call the initializer for the shared library * when the library is loaded, nor on a future call to * shl_unload(). * BIND_VERBOSE - Print verbose messages concerning possible * unsatisfied symbols. * * hp9000s700/hp9000s800: * BIND_RESTRICTED - Restrict symbols visible by the library to those * present at library load time. * DYNAMIC_PATH - Allow the loader to dynamically search for the * library specified by the path argument. */ #ifndef DYNAMIC_PATH # define DYNAMIC_PATH 0 #endif #ifndef BIND_RESTRICTED # define BIND_RESTRICTED 0 #endif #define LT_BIND_FLAGS (BIND_IMMEDIATE | BIND_NONFATAL | DYNAMIC_PATH) static lt_module sys_shl_open (loader_data, filename) lt_user_data loader_data; const char *filename; { static shl_t self = (shl_t) 0; lt_module module = shl_load (filename, LT_BIND_FLAGS, 0L); /* Since searching for a symbol against a NULL module handle will also look in everything else that was already loaded and exported with the -E compiler flag, we always cache a handle saved before any modules are loaded. */ if (!self) { lt_ptr address; shl_findsym (&self, "main", TYPE_UNDEFINED, &address); } if (!filename) { module = self; } else { module = shl_load (filename, LT_BIND_FLAGS, 0L); if (!module) { LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN)); } } return module; } static int sys_shl_close (loader_data, module) lt_user_data loader_data; lt_module module; { int errors = 0; if (module && (shl_unload ((shl_t) (module)) != 0)) { LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE)); ++errors; } return errors; } static lt_ptr sys_shl_sym (loader_data, module, symbol) lt_user_data loader_data; lt_module module; const char *symbol; { lt_ptr address = 0; /* sys_shl_open should never return a NULL module handle */ if (module == (lt_module) 0) { LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE)); } else if (!shl_findsym((shl_t*) &module, symbol, TYPE_UNDEFINED, &address)) { if (!address) { LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND)); } } return address; } static struct lt_user_dlloader sys_shl = { 0, sys_shl_open, sys_shl_close, sys_shl_sym, 0, 0 }; #endif /* HAVE_SHL_LOAD */ /* --- LOADLIBRARY() INTERFACE LOADER --- */ #ifdef __WINDOWS__ /* dynamic linking for Win32 */ #include /* Forward declaration; required to implement handle search below. */ static lt_dlhandle handles; static lt_module sys_wll_open (loader_data, filename) lt_user_data loader_data; const char *filename; { lt_dlhandle cur; lt_module module = 0; const char *errormsg = 0; char *searchname = 0; char *ext; char self_name_buf[MAX_PATH]; if (!filename) { /* Get the name of main module */ *self_name_buf = 0; GetModuleFileName (NULL, self_name_buf, sizeof (self_name_buf)); filename = ext = self_name_buf; } else { ext = strrchr (filename, '.'); } if (ext) { /* FILENAME already has an extension. */ searchname = lt_estrdup (filename); } else { /* Append a `.' to stop Windows from adding an implicit `.dll' extension. */ searchname = LT_EMALLOC (char, 2+ LT_STRLEN (filename)); if (searchname) sprintf (searchname, "%s.", filename); } if (!searchname) return 0; #if __CYGWIN__ { char wpath[MAX_PATH]; cygwin_conv_to_full_win32_path(searchname, wpath); module = LoadLibrary(wpath); } #else module = LoadLibrary (searchname); #endif LT_DLFREE (searchname); /* libltdl expects this function to fail if it is unable to physically load the library. Sadly, LoadLibrary will search the loaded libraries for a match and return one of them if the path search load fails. We check whether LoadLibrary is returning a handle to an already loaded module, and simulate failure if we find one. */ LT_DLMUTEX_LOCK (); cur = handles; while (cur) { if (!cur->module) { cur = 0; break; } if (cur->module == module) { break; } cur = cur->next; } LT_DLMUTEX_UNLOCK (); if (cur || !module) { LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN)); module = 0; } return module; } static int sys_wll_close (loader_data, module) lt_user_data loader_data; lt_module module; { int errors = 0; if (FreeLibrary(module) == 0) { LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE)); ++errors; } return errors; } static lt_ptr sys_wll_sym (loader_data, module, symbol) lt_user_data loader_data; lt_module module; const char *symbol; { lt_ptr address = GetProcAddress (module, symbol); if (!address) { LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND)); } return address; } static struct lt_user_dlloader sys_wll = { 0, sys_wll_open, sys_wll_close, sys_wll_sym, 0, 0 }; #endif /* __WINDOWS__ */ /* --- LOAD_ADD_ON() INTERFACE LOADER --- */ #ifdef __BEOS__ /* dynamic linking for BeOS */ #include static lt_module sys_bedl_open (loader_data, filename) lt_user_data loader_data; const char *filename; { image_id image = 0; if (filename) { image = load_add_on (filename); } else { image_info info; int32 cookie = 0; if (get_next_image_info (0, &cookie, &info) == B_OK) image = load_add_on (info.name); } if (image <= 0) { LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN)); image = 0; } return (lt_module) image; } static int sys_bedl_close (loader_data, module) lt_user_data loader_data; lt_module module; { int errors = 0; if (unload_add_on ((image_id) module) != B_OK) { LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE)); ++errors; } return errors; } static lt_ptr sys_bedl_sym (loader_data, module, symbol) lt_user_data loader_data; lt_module module; const char *symbol; { lt_ptr address = 0; image_id image = (image_id) module; if (get_image_symbol (image, symbol, B_SYMBOL_TYPE_ANY, address) != B_OK) { LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND)); address = 0; } return address; } static struct lt_user_dlloader sys_bedl = { 0, sys_bedl_open, sys_bedl_close, sys_bedl_sym, 0, 0 }; #endif /* __BEOS__ */ /* --- DLD_LINK() INTERFACE LOADER --- */ #if HAVE_DLD /* dynamic linking with dld */ #if HAVE_DLD_H #include #endif static lt_module sys_dld_open (loader_data, filename) lt_user_data loader_data; const char *filename; { lt_module module = strdup (filename); if (dld_link (filename) != 0) { LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN)); LT_DLFREE (module); module = 0; } return module; } static int sys_dld_close (loader_data, module) lt_user_data loader_data; lt_module module; { int errors = 0; if (dld_unlink_by_file ((char*)(module), 1) != 0) { LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE)); ++errors; } else { LT_DLFREE (module); } return errors; } static lt_ptr sys_dld_sym (loader_data, module, symbol) lt_user_data loader_data; lt_module module; const char *symbol; { lt_ptr address = dld_get_func (symbol); if (!address) { LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND)); } return address; } static struct lt_user_dlloader sys_dld = { 0, sys_dld_open, sys_dld_close, sys_dld_sym, 0, 0 }; #endif /* HAVE_DLD */ /* --- DYLD() MACOSX/DARWIN INTERFACE LOADER --- */ #if HAVE_DYLD #if HAVE_MACH_O_DYLD_H #if !defined(__APPLE_CC__) && !defined(__MWERKS__) && !defined(__private_extern__) /* Is this correct? Does it still function properly? */ #define __private_extern__ extern #endif # include #endif #include /* We have to put some stuff here that isn't in older dyld.h files */ #ifndef ENUM_DYLD_BOOL # define ENUM_DYLD_BOOL # undef FALSE # undef TRUE enum DYLD_BOOL { FALSE, TRUE }; #endif #ifndef LC_REQ_DYLD # define LC_REQ_DYLD 0x80000000 #endif #ifndef LC_LOAD_WEAK_DYLIB # define LC_LOAD_WEAK_DYLIB (0x18 | LC_REQ_DYLD) #endif static const struct mach_header * (*ltdl_NSAddImage)(const char *image_name, unsigned long options) = 0; static NSSymbol (*ltdl_NSLookupSymbolInImage)(const struct mach_header *image,const char *symbolName, unsigned long options) = 0; static enum DYLD_BOOL (*ltdl_NSIsSymbolNameDefinedInImage)(const struct mach_header *image, const char *symbolName) = 0; static enum DYLD_BOOL (*ltdl_NSMakePrivateModulePublic)(NSModule module) = 0; #ifndef NSADDIMAGE_OPTION_NONE #define NSADDIMAGE_OPTION_NONE 0x0 #endif #ifndef NSADDIMAGE_OPTION_RETURN_ON_ERROR #define NSADDIMAGE_OPTION_RETURN_ON_ERROR 0x1 #endif #ifndef NSADDIMAGE_OPTION_WITH_SEARCHING #define NSADDIMAGE_OPTION_WITH_SEARCHING 0x2 #endif #ifndef NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED #define NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED 0x4 #endif #ifndef NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME #define NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME 0x8 #endif #ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_BIND #define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND 0x0 #endif #ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW #define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW 0x1 #endif #ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_FULLY #define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_FULLY 0x2 #endif #ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR #define NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR 0x4 #endif static const char * lt_int_dyld_error(othererror) char* othererror; { /* return the dyld error string, or the passed in error string if none */ NSLinkEditErrors ler; int lerno; const char *errstr; const char *file; NSLinkEditError(&ler,&lerno,&file,&errstr); if (!errstr || !strlen(errstr)) errstr = othererror; return errstr; } static const struct mach_header * lt_int_dyld_get_mach_header_from_nsmodule(module) NSModule module; { /* There should probably be an apple dyld api for this */ int i=_dyld_image_count(); int j; const char *modname=NSNameOfModule(module); const struct mach_header *mh=NULL; if (!modname) return NULL; for (j = 0; j < i; j++) { if (!strcmp(_dyld_get_image_name(j),modname)) { mh=_dyld_get_image_header(j); break; } } return mh; } static const char* lt_int_dyld_lib_install_name(mh) const struct mach_header *mh; { /* NSAddImage is also used to get the loaded image, but it only works if the lib is installed, for uninstalled libs we need to check the install_names against each other. Note that this is still broken if DYLD_IMAGE_SUFFIX is set and a different lib was loaded as a result */ int j; struct load_command *lc; unsigned long offset = sizeof(struct mach_header); const char* retStr=NULL; for (j = 0; j < mh->ncmds; j++) { lc = (struct load_command*)(((unsigned long)mh) + offset); if (LC_ID_DYLIB == lc->cmd) { retStr=(char*)(((struct dylib_command*)lc)->dylib.name.offset + (unsigned long)lc); } offset += lc->cmdsize; } return retStr; } static const struct mach_header * lt_int_dyld_match_loaded_lib_by_install_name(const char *name) { int i=_dyld_image_count(); int j; const struct mach_header *mh=NULL; const char *id=NULL; for (j = 0; j < i; j++) { id=lt_int_dyld_lib_install_name(_dyld_get_image_header(j)); if ((id) && (!strcmp(id,name))) { mh=_dyld_get_image_header(j); break; } } return mh; } static NSSymbol lt_int_dyld_NSlookupSymbolInLinkedLibs(symbol,mh) const char *symbol; const struct mach_header *mh; { /* Safe to assume our mh is good */ int j; struct load_command *lc; unsigned long offset = sizeof(struct mach_header); NSSymbol retSym = 0; const struct mach_header *mh1; if ((ltdl_NSLookupSymbolInImage) && NSIsSymbolNameDefined(symbol) ) { for (j = 0; j < mh->ncmds; j++) { lc = (struct load_command*)(((unsigned long)mh) + offset); if ((LC_LOAD_DYLIB == lc->cmd) || (LC_LOAD_WEAK_DYLIB == lc->cmd)) { mh1=lt_int_dyld_match_loaded_lib_by_install_name((char*)(((struct dylib_command*)lc)->dylib.name.offset + (unsigned long)lc)); if (!mh1) { /* Maybe NSAddImage can find it */ mh1=ltdl_NSAddImage((char*)(((struct dylib_command*)lc)->dylib.name.offset + (unsigned long)lc), NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED + NSADDIMAGE_OPTION_WITH_SEARCHING + NSADDIMAGE_OPTION_RETURN_ON_ERROR ); } if (mh1) { retSym = ltdl_NSLookupSymbolInImage(mh1, symbol, NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR ); if (retSym) break; } } offset += lc->cmdsize; } } return retSym; } static int sys_dyld_init() { int retCode = 0; int err = 0; if (!_dyld_present()) { retCode=1; } else { err = _dyld_func_lookup("__dyld_NSAddImage",(unsigned long*)<dl_NSAddImage); err = _dyld_func_lookup("__dyld_NSLookupSymbolInImage",(unsigned long*)<dl_NSLookupSymbolInImage); err = _dyld_func_lookup("__dyld_NSIsSymbolNameDefinedInImage",(unsigned long*)<dl_NSIsSymbolNameDefinedInImage); err = _dyld_func_lookup("__dyld_NSMakePrivateModulePublic",(unsigned long*)<dl_NSMakePrivateModulePublic); } return retCode; } static lt_module sys_dyld_open (loader_data, filename) lt_user_data loader_data; const char *filename; { lt_module module = 0; NSObjectFileImage ofi = 0; NSObjectFileImageReturnCode ofirc; if (!filename) return (lt_module)-1; ofirc = NSCreateObjectFileImageFromFile(filename, &ofi); switch (ofirc) { case NSObjectFileImageSuccess: module = NSLinkModule(ofi, filename, NSLINKMODULE_OPTION_RETURN_ON_ERROR | NSLINKMODULE_OPTION_PRIVATE | NSLINKMODULE_OPTION_BINDNOW); NSDestroyObjectFileImage(ofi); if (module) ltdl_NSMakePrivateModulePublic(module); break; case NSObjectFileImageInappropriateFile: if (ltdl_NSIsSymbolNameDefinedInImage && ltdl_NSLookupSymbolInImage) { module = (lt_module)ltdl_NSAddImage(filename, NSADDIMAGE_OPTION_RETURN_ON_ERROR); break; } default: LT_DLMUTEX_SETERROR (lt_int_dyld_error(LT_DLSTRERROR(CANNOT_OPEN))); return 0; } if (!module) LT_DLMUTEX_SETERROR (lt_int_dyld_error(LT_DLSTRERROR(CANNOT_OPEN))); return module; } static int sys_dyld_close (loader_data, module) lt_user_data loader_data; lt_module module; { int retCode = 0; int flags = 0; if (module == (lt_module)-1) return 0; #ifdef __BIG_ENDIAN__ if (((struct mach_header *)module)->magic == MH_MAGIC) #else if (((struct mach_header *)module)->magic == MH_CIGAM) #endif { LT_DLMUTEX_SETERROR("Can not close a dylib"); retCode = 1; } else { #if 1 /* Currently, if a module contains c++ static destructors and it is unloaded, we get a segfault in atexit(), due to compiler and dynamic loader differences of opinion, this works around that. */ if ((const struct section *)NULL != getsectbynamefromheader(lt_int_dyld_get_mach_header_from_nsmodule(module), "__DATA","__mod_term_func")) { flags += NSUNLINKMODULE_OPTION_KEEP_MEMORY_MAPPED; } #endif #ifdef __ppc__ flags += NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES; #endif if (!NSUnLinkModule(module,flags)) { retCode=1; LT_DLMUTEX_SETERROR (lt_int_dyld_error(LT_DLSTRERROR(CANNOT_CLOSE))); } } return retCode; } static lt_ptr sys_dyld_sym (loader_data, module, symbol) lt_user_data loader_data; lt_module module; const char *symbol; { lt_ptr address = 0; NSSymbol *nssym = 0; void *unused; const struct mach_header *mh=NULL; char saveError[256] = "Symbol not found"; if (module == (lt_module)-1) { _dyld_lookup_and_bind(symbol,(unsigned long*)&address,&unused); return address; } #ifdef __BIG_ENDIAN__ if (((struct mach_header *)module)->magic == MH_MAGIC) #else if (((struct mach_header *)module)->magic == MH_CIGAM) #endif { if (ltdl_NSIsSymbolNameDefinedInImage && ltdl_NSLookupSymbolInImage) { mh=module; if (ltdl_NSIsSymbolNameDefinedInImage((struct mach_header*)module,symbol)) { nssym = ltdl_NSLookupSymbolInImage((struct mach_header*)module, symbol, NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR ); } } } else { nssym = NSLookupSymbolInModule(module, symbol); } if (!nssym) { strncpy(saveError, lt_int_dyld_error(LT_DLSTRERROR(SYMBOL_NOT_FOUND)), 255); saveError[255] = 0; if (!mh) mh=lt_int_dyld_get_mach_header_from_nsmodule(module); nssym = lt_int_dyld_NSlookupSymbolInLinkedLibs(symbol,mh); } if (!nssym) { LT_DLMUTEX_SETERROR (saveError); return NULL; } return NSAddressOfSymbol(nssym); } static struct lt_user_dlloader sys_dyld = { "_", sys_dyld_open, sys_dyld_close, sys_dyld_sym, 0, 0 }; #endif /* HAVE_DYLD */ /* --- DLPREOPEN() INTERFACE LOADER --- */ /* emulate dynamic linking using preloaded_symbols */ typedef struct lt_dlsymlists_t { struct lt_dlsymlists_t *next; const lt_dlsymlist *syms; } lt_dlsymlists_t; static const lt_dlsymlist *default_preloaded_symbols = 0; static lt_dlsymlists_t *preloaded_symbols = 0; static int presym_init (loader_data) lt_user_data loader_data; { int errors = 0; loader_data=loader_data; LT_DLMUTEX_LOCK (); preloaded_symbols = 0; if (default_preloaded_symbols) { errors = lt_dlpreload (default_preloaded_symbols); } LT_DLMUTEX_UNLOCK (); return errors; } static int presym_free_symlists () { lt_dlsymlists_t *lists; LT_DLMUTEX_LOCK (); lists = preloaded_symbols; while (lists) { lt_dlsymlists_t *tmp = lists; lists = lists->next; LT_DLFREE (tmp); } preloaded_symbols = 0; LT_DLMUTEX_UNLOCK (); return 0; } static int presym_exit (loader_data) lt_user_data loader_data; { loader_data=loader_data; presym_free_symlists (); return 0; } static int presym_add_symlist (preloaded) const lt_dlsymlist *preloaded; { lt_dlsymlists_t *tmp; lt_dlsymlists_t *lists; int errors = 0; LT_DLMUTEX_LOCK (); lists = preloaded_symbols; while (lists) { if (lists->syms == preloaded) { goto done; } lists = lists->next; } tmp = LT_EMALLOC (lt_dlsymlists_t, 1); if (tmp) { memset (tmp, 0, sizeof(lt_dlsymlists_t)); tmp->syms = preloaded; tmp->next = preloaded_symbols; preloaded_symbols = tmp; } else { ++errors; } done: LT_DLMUTEX_UNLOCK (); return errors; } static lt_module presym_open (loader_data, filename) lt_user_data loader_data; const char *filename; { lt_dlsymlists_t *lists; lt_module module = (lt_module) 0; loader_data=loader_data; LT_DLMUTEX_LOCK (); lists = preloaded_symbols; if (!lists) { LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_SYMBOLS)); goto done; } /* Can't use NULL as the reflective symbol header, as NULL is used to mark the end of the entire symbol list. Self-dlpreopened symbols follow this magic number, chosen to be an unlikely clash with a real module name. */ if (!filename) { filename = "@PROGRAM@"; } while (lists) { const lt_dlsymlist *syms = lists->syms; while (syms->name) { if (!syms->address && strcmp(syms->name, filename) == 0) { module = (lt_module) syms; goto done; } ++syms; } lists = lists->next; } LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND)); done: LT_DLMUTEX_UNLOCK (); return module; } static int presym_close (loader_data, module) lt_user_data loader_data; lt_module module; { /* Just to silence gcc -Wall */ loader_data=loader_data; module = 0; return 0; } static lt_ptr presym_sym (loader_data, module, symbol) lt_user_data loader_data; lt_module module; const char *symbol; { lt_dlsymlist *syms = (lt_dlsymlist*) module; loader_data=loader_data; ++syms; while (syms->address) { if (strcmp(syms->name, symbol) == 0) { return syms->address; } ++syms; } LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND)); return 0; } static struct lt_user_dlloader presym = { 0, presym_open, presym_close, presym_sym, presym_exit, 0 }; /* --- DYNAMIC MODULE LOADING --- */ /* The type of a function used at each iteration of foreach_dirinpath(). */ typedef int foreach_callback_func LT_PARAMS((char *filename, lt_ptr data1, lt_ptr data2)); static int foreach_dirinpath LT_PARAMS((const char *search_path, const char *base_name, foreach_callback_func *func, lt_ptr data1, lt_ptr data2)); static int find_file_callback LT_PARAMS((char *filename, lt_ptr data, lt_ptr ignored)); static int find_handle_callback LT_PARAMS((char *filename, lt_ptr data, lt_ptr ignored)); static int foreachfile_callback LT_PARAMS((char *filename, lt_ptr data1, lt_ptr data2)); static int canonicalize_path LT_PARAMS((const char *path, char **pcanonical)); static int argzize_path LT_PARAMS((const char *path, char **pargz, size_t *pargz_len)); static FILE *find_file LT_PARAMS((const char *search_path, const char *base_name, char **pdir)); static lt_dlhandle *find_handle LT_PARAMS((const char *search_path, const char *base_name, lt_dlhandle *handle)); static int find_module LT_PARAMS((lt_dlhandle *handle, const char *dir, const char *libdir, const char *dlname, const char *old_name, int installed)); static int free_vars LT_PARAMS((char *dlname, char *oldname, char *libdir, char *deplibs)); static int load_deplibs LT_PARAMS((lt_dlhandle handle, char *deplibs)); static int trim LT_PARAMS((char **dest, const char *str)); static int try_dlopen LT_PARAMS((lt_dlhandle *handle, const char *filename)); static int tryall_dlopen LT_PARAMS((lt_dlhandle *handle, const char *filename)); static int unload_deplibs LT_PARAMS((lt_dlhandle handle)); static int lt_argz_insert LT_PARAMS((char **pargz, size_t *pargz_len, char *before, const char *entry)); static int lt_argz_insertinorder LT_PARAMS((char **pargz, size_t *pargz_len, const char *entry)); static int lt_argz_insertdir LT_PARAMS((char **pargz, size_t *pargz_len, const char *dirnam, struct dirent *dp)); static int lt_dlpath_insertdir LT_PARAMS((char **ppath, char *before, const char *dir)); static int list_files_by_dir LT_PARAMS((const char *dirnam, char **pargz, size_t *pargz_len)); static int file_not_found LT_PARAMS((void)); static char *user_search_path= 0; static lt_dlloader *loaders = 0; static lt_dlhandle handles = 0; static int initialized = 0; /* Initialize libltdl. */ int lt_dlinit () { int errors = 0; LT_DLMUTEX_LOCK (); /* Initialize only at first call. */ if (++initialized == 1) { handles = 0; user_search_path = 0; /* empty search path */ #if HAVE_LIBDL errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dl, "dlopen"); #endif #if HAVE_SHL_LOAD errors += lt_dlloader_add (lt_dlloader_next (0), &sys_shl, "dlopen"); #endif #ifdef __WINDOWS__ errors += lt_dlloader_add (lt_dlloader_next (0), &sys_wll, "dlopen"); #endif #ifdef __BEOS__ errors += lt_dlloader_add (lt_dlloader_next (0), &sys_bedl, "dlopen"); #endif #if HAVE_DLD errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dld, "dld"); #endif #if HAVE_DYLD errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dyld, "dyld"); errors += sys_dyld_init(); #endif errors += lt_dlloader_add (lt_dlloader_next (0), &presym, "dlpreload"); if (presym_init (presym.dlloader_data)) { LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INIT_LOADER)); ++errors; } else if (errors != 0) { LT_DLMUTEX_SETERROR (LT_DLSTRERROR (DLOPEN_NOT_SUPPORTED)); ++errors; } } LT_DLMUTEX_UNLOCK (); return errors; } int lt_dlpreload (preloaded) const lt_dlsymlist *preloaded; { int errors = 0; if (preloaded) { errors = presym_add_symlist (preloaded); } else { presym_free_symlists(); LT_DLMUTEX_LOCK (); if (default_preloaded_symbols) { errors = lt_dlpreload (default_preloaded_symbols); } LT_DLMUTEX_UNLOCK (); } return errors; } int lt_dlpreload_default (preloaded) const lt_dlsymlist *preloaded; { LT_DLMUTEX_LOCK (); default_preloaded_symbols = preloaded; LT_DLMUTEX_UNLOCK (); return 0; } int lt_dlexit () { /* shut down libltdl */ lt_dlloader *loader; int errors = 0; LT_DLMUTEX_LOCK (); loader = loaders; if (!initialized) { LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SHUTDOWN)); ++errors; goto done; } /* shut down only at last call. */ if (--initialized == 0) { int level; while (handles && LT_DLIS_RESIDENT (handles)) { handles = handles->next; } /* close all modules */ for (level = 1; handles; ++level) { lt_dlhandle cur = handles; int saw_nonresident = 0; while (cur) { lt_dlhandle tmp = cur; cur = cur->next; if (!LT_DLIS_RESIDENT (tmp)) saw_nonresident = 1; if (!LT_DLIS_RESIDENT (tmp) && tmp->info.ref_count <= level) { if (lt_dlclose (tmp)) { ++errors; } } } /* done if only resident modules are left */ if (!saw_nonresident) break; } /* close all loaders */ while (loader) { lt_dlloader *next = loader->next; lt_user_data data = loader->dlloader_data; if (loader->dlloader_exit && loader->dlloader_exit (data)) { ++errors; } LT_DLMEM_REASSIGN (loader, next); } loaders = 0; } done: LT_DLMUTEX_UNLOCK (); return errors; } static int tryall_dlopen (handle, filename) lt_dlhandle *handle; const char *filename; { lt_dlhandle cur; lt_dlloader *loader; const char *saved_error; int errors = 0; LT_DLMUTEX_GETERROR (saved_error); LT_DLMUTEX_LOCK (); cur = handles; loader = loaders; /* check whether the module was already opened */ while (cur) { /* try to dlopen the program itself? */ if (!cur->info.filename && !filename) { break; } if (cur->info.filename && filename && strcmp (cur->info.filename, filename) == 0) { break; } cur = cur->next; } if (cur) { ++cur->info.ref_count; *handle = cur; goto done; } cur = *handle; if (filename) { /* Comment out the check of file permissions using access. This call seems to always return -1 with error EACCES. */ /* We need to catch missing file errors early so that file_not_found() can detect what happened. if (access (filename, R_OK) != 0) { LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND)); ++errors; goto done; } */ cur->info.filename = lt_estrdup (filename); if (!cur->info.filename) { ++errors; goto done; } } else { cur->info.filename = 0; } while (loader) { lt_user_data data = loader->dlloader_data; cur->module = loader->module_open (data, filename); if (cur->module != 0) { break; } loader = loader->next; } if (!loader) { LT_DLFREE (cur->info.filename); ++errors; goto done; } cur->loader = loader; LT_DLMUTEX_SETERROR (saved_error); done: LT_DLMUTEX_UNLOCK (); return errors; } static int tryall_dlopen_module (handle, prefix, dirname, dlname) lt_dlhandle *handle; const char *prefix; const char *dirname; const char *dlname; { int error = 0; char *filename = 0; size_t filename_len = 0; size_t dirname_len = LT_STRLEN (dirname); assert (handle); assert (dirname); assert (dlname); #ifdef LT_DIRSEP_CHAR /* Only canonicalized names (i.e. with DIRSEP chars already converted) should make it into this function: */ assert (strchr (dirname, LT_DIRSEP_CHAR) == 0); #endif if (dirname_len > 0) if (dirname[dirname_len -1] == '/') --dirname_len; filename_len = dirname_len + 1 + LT_STRLEN (dlname); /* Allocate memory, and combine DIRNAME and MODULENAME into it. The PREFIX (if any) is handled below. */ filename = LT_EMALLOC (char, dirname_len + 1 + filename_len + 1); if (!filename) return 1; sprintf (filename, "%.*s/%s", (int) dirname_len, dirname, dlname); /* Now that we have combined DIRNAME and MODULENAME, if there is also a PREFIX to contend with, simply recurse with the arguments shuffled. Otherwise, attempt to open FILENAME as a module. */ if (prefix) { error += tryall_dlopen_module (handle, (const char *) 0, prefix, filename); } else if (tryall_dlopen (handle, filename) != 0) { ++error; } LT_DLFREE (filename); return error; } static int find_module (handle, dir, libdir, dlname, old_name, installed) lt_dlhandle *handle; const char *dir; const char *libdir; const char *dlname; const char *old_name; int installed; { /* Try to open the old library first; if it was dlpreopened, we want the preopened version of it, even if a dlopenable module is available. */ if (old_name && tryall_dlopen (handle, old_name) == 0) { return 0; } /* Try to open the dynamic library. */ if (dlname) { /* try to open the installed module */ if (installed && libdir) { if (tryall_dlopen_module (handle, (const char *) 0, libdir, dlname) == 0) return 0; } /* try to open the not-installed module */ if (!installed) { if (tryall_dlopen_module (handle, dir, objdir, dlname) == 0) return 0; } /* maybe it was moved to another directory */ { if (tryall_dlopen_module (handle, (const char *) 0, dir, dlname) == 0) return 0; } } return 1; } static int canonicalize_path (path, pcanonical) const char *path; char **pcanonical; { char *canonical = 0; assert (path && *path); assert (pcanonical); canonical = LT_EMALLOC (char, 1+ LT_STRLEN (path)); if (!canonical) return 1; { size_t dest = 0; size_t src; for (src = 0; path[src] != LT_EOS_CHAR; ++src) { /* Path separators are not copied to the beginning or end of the destination, or if another separator would follow immediately. */ if (path[src] == LT_PATHSEP_CHAR) { if ((dest == 0) || (path[1+ src] == LT_PATHSEP_CHAR) || (path[1+ src] == LT_EOS_CHAR)) continue; } /* Anything other than a directory separator is copied verbatim. */ if ((path[src] != '/') #ifdef LT_DIRSEP_CHAR && (path[src] != LT_DIRSEP_CHAR) #endif ) { canonical[dest++] = path[src]; } /* Directory separators are converted and copied only if they are not at the end of a path -- i.e. before a path separator or NULL terminator. */ else if ((path[1+ src] != LT_PATHSEP_CHAR) && (path[1+ src] != LT_EOS_CHAR) #ifdef LT_DIRSEP_CHAR && (path[1+ src] != LT_DIRSEP_CHAR) #endif && (path[1+ src] != '/')) { canonical[dest++] = '/'; } } /* Add an end-of-string marker at the end. */ canonical[dest] = LT_EOS_CHAR; } /* Assign new value. */ *pcanonical = canonical; return 0; } static int argzize_path (path, pargz, pargz_len) const char *path; char **pargz; size_t *pargz_len; { error_t error; assert (path); assert (pargz); assert (pargz_len); if ((error = argz_create_sep (path, LT_PATHSEP_CHAR, pargz, pargz_len))) { switch (error) { case ENOMEM: LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY)); break; default: LT_DLMUTEX_SETERROR (LT_DLSTRERROR (UNKNOWN)); break; } return 1; } return 0; } /* Repeatedly call FUNC with each LT_PATHSEP_CHAR delimited element of SEARCH_PATH and references to DATA1 and DATA2, until FUNC returns non-zero or all elements are exhausted. If BASE_NAME is non-NULL, it is appended to each SEARCH_PATH element before FUNC is called. */ static int foreach_dirinpath (search_path, base_name, func, data1, data2) const char *search_path; const char *base_name; foreach_callback_func *func; lt_ptr data1; lt_ptr data2; { int result = 0; size_t filenamesize = 0; size_t lenbase = LT_STRLEN (base_name); size_t argz_len = 0; char *argz = 0; char *filename = 0; char *canonical = 0; LT_DLMUTEX_LOCK (); if (!search_path || !*search_path) { LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND)); goto cleanup; } if (canonicalize_path (search_path, &canonical) != 0) goto cleanup; if (argzize_path (canonical, &argz, &argz_len) != 0) goto cleanup; { char *dir_name = 0; while ((dir_name = argz_next (argz, argz_len, dir_name))) { size_t lendir = LT_STRLEN (dir_name); if (lendir +1 +lenbase >= filenamesize) { LT_DLFREE (filename); filenamesize = lendir +1 +lenbase +1; /* "/d" + '/' + "f" + '\0' */ filename = LT_EMALLOC (char, filenamesize); if (!filename) goto cleanup; } assert (filenamesize > lendir); strcpy (filename, dir_name); if (base_name && *base_name) { if (filename[lendir -1] != '/') filename[lendir++] = '/'; strcpy (filename +lendir, base_name); } if ((result = (*func) (filename, data1, data2))) { break; } } } cleanup: LT_DLFREE (argz); LT_DLFREE (canonical); LT_DLFREE (filename); LT_DLMUTEX_UNLOCK (); return result; } /* If FILEPATH can be opened, store the name of the directory component in DATA1, and the opened FILE* structure address in DATA2. Otherwise DATA1 is unchanged, but DATA2 is set to a pointer to NULL. */ static int find_file_callback (filename, data1, data2) char *filename; lt_ptr data1; lt_ptr data2; { char **pdir = (char **) data1; FILE **pfile = (FILE **) data2; int is_done = 0; assert (filename && *filename); assert (pdir); assert (pfile); if ((*pfile = fopen (filename, LT_READTEXT_MODE))) { char *dirend = strrchr (filename, '/'); if (dirend > filename) *dirend = LT_EOS_CHAR; LT_DLFREE (*pdir); *pdir = lt_estrdup (filename); is_done = (*pdir == 0) ? -1 : 1; } return is_done; } static FILE * find_file (search_path, base_name, pdir) const char *search_path; const char *base_name; char **pdir; { FILE *file = 0; foreach_dirinpath (search_path, base_name, find_file_callback, pdir, &file); return file; } static int find_handle_callback (filename, data, ignored) char *filename; lt_ptr data; lt_ptr ignored; { lt_dlhandle *handle = (lt_dlhandle *) data; int notfound = access (filename, R_OK); ignored=ignored; /* Bail out if file cannot be read... */ if (notfound) return 0; /* Try to dlopen the file, but do not continue searching in any case. */ if (tryall_dlopen (handle, filename) != 0) *handle = 0; return 1; } /* If HANDLE was found return it, otherwise return 0. If HANDLE was found but could not be opened, *HANDLE will be set to 0. */ static lt_dlhandle * find_handle (search_path, base_name, handle) const char *search_path; const char *base_name; lt_dlhandle *handle; { if (!search_path) return 0; if (!foreach_dirinpath (search_path, base_name, find_handle_callback, handle, 0)) return 0; return handle; } static int load_deplibs (handle, deplibs) lt_dlhandle handle; char *deplibs; { #if LTDL_DLOPEN_DEPLIBS char *p, *save_search_path = 0; int depcount = 0; int i; char **names = 0; #endif int errors = 0; deplibs=deplibs; handle->depcount = 0; #if LTDL_DLOPEN_DEPLIBS if (!deplibs) { return errors; } ++errors; LT_DLMUTEX_LOCK (); if (user_search_path) { save_search_path = lt_estrdup (user_search_path); if (!save_search_path) goto cleanup; } /* extract search paths and count deplibs */ p = deplibs; while (*p) { if (!isspace ((int) *p)) { char *end = p+1; while (*end && !isspace((int) *end)) { ++end; } if (strncmp(p, "-L", 2) == 0 || strncmp(p, "-R", 2) == 0) { char save = *end; *end = 0; /* set a temporary string terminator */ if (lt_dladdsearchdir(p+2)) { goto cleanup; } *end = save; } else { ++depcount; } p = end; } else { ++p; } } /* restore the old search path */ LT_DLFREE (user_search_path); user_search_path = save_search_path; LT_DLMUTEX_UNLOCK (); if (!depcount) { errors = 0; goto cleanup; } names = LT_EMALLOC (char *, depcount * sizeof (char*)); if (!names) goto cleanup; /* now only extract the actual deplibs */ depcount = 0; p = deplibs; while (*p) { if (isspace ((int) *p)) { ++p; } else { char *end = p+1; while (*end && !isspace ((int) *end)) { ++end; } if (strncmp(p, "-L", 2) != 0 && strncmp(p, "-R", 2) != 0) { char *name; char save = *end; *end = 0; /* set a temporary string terminator */ if (strncmp(p, "-l", 2) == 0) { size_t name_len = 3+ /* "lib" */ LT_STRLEN (p + 2); name = LT_EMALLOC (char, 1+ name_len); if (name) sprintf (name, "lib%s", p+2); } else name = lt_estrdup(p); if (!name) goto cleanup_names; names[depcount++] = name; *end = save; } p = end; } } /* load the deplibs (in reverse order) At this stage, don't worry if the deplibs do not load correctly, they may already be statically linked into the loading application for instance. There will be a more enlightening error message later on if the loaded module cannot resolve all of its symbols. */ if (depcount) { int j = 0; handle->deplibs = (lt_dlhandle*) LT_EMALLOC (lt_dlhandle *, depcount); if (!handle->deplibs) goto cleanup; for (i = 0; i < depcount; ++i) { handle->deplibs[j] = lt_dlopenext(names[depcount-1-i]); if (handle->deplibs[j]) { ++j; } } handle->depcount = j; /* Number of successfully loaded deplibs */ errors = 0; } cleanup_names: for (i = 0; i < depcount; ++i) { LT_DLFREE (names[i]); } cleanup: LT_DLFREE (names); #endif return errors; } static int unload_deplibs (handle) lt_dlhandle handle; { int i; int errors = 0; if (handle->depcount) { for (i = 0; i < handle->depcount; ++i) { if (!LT_DLIS_RESIDENT (handle->deplibs[i])) { errors += lt_dlclose (handle->deplibs[i]); } } } return errors; } static int trim (dest, str) char **dest; const char *str; { /* remove the leading and trailing "'" from str and store the result in dest */ const char *end = strrchr (str, '\''); size_t len = LT_STRLEN (str); char *tmp; LT_DLFREE (*dest); if (len > 3 && str[0] == '\'') { tmp = LT_EMALLOC (char, end - str); if (!tmp) return 1; strncpy(tmp, &str[1], (end - str) - 1); tmp[len-3] = LT_EOS_CHAR; *dest = tmp; } else { *dest = 0; } return 0; } static int free_vars (dlname, oldname, libdir, deplibs) char *dlname; char *oldname; char *libdir; char *deplibs; { LT_DLFREE (dlname); LT_DLFREE (oldname); LT_DLFREE (libdir); LT_DLFREE (deplibs); return 0; } static int try_dlopen (phandle, filename) lt_dlhandle *phandle; const char *filename; { const char * ext = 0; const char * saved_error = 0; char * canonical = 0; char * base_name = 0; char * dir = 0; char * name = 0; int errors = 0; lt_dlhandle newhandle; assert (phandle); assert (*phandle == 0); LT_DLMUTEX_GETERROR (saved_error); /* dlopen self? */ if (!filename) { *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1); if (*phandle == 0) return 1; memset (*phandle, 0, sizeof(struct lt_dlhandle_struct)); newhandle = *phandle; /* lt_dlclose()ing yourself is very bad! Disallow it. */ LT_DLSET_FLAG (*phandle, LT_DLRESIDENT_FLAG); if (tryall_dlopen (&newhandle, 0) != 0) { LT_DLFREE (*phandle); return 1; } goto register_handle; } assert (filename && *filename); /* Doing this immediately allows internal functions to safely assume only canonicalized paths are passed. */ if (canonicalize_path (filename, &canonical) != 0) { ++errors; goto cleanup; } /* If the canonical module name is a path (relative or absolute) then split it into a directory part and a name part. */ base_name = strrchr (canonical, '/'); if (base_name) { size_t dirlen = (1+ base_name) - canonical; dir = LT_EMALLOC (char, 1+ dirlen); if (!dir) { ++errors; goto cleanup; } strncpy (dir, canonical, dirlen); dir[dirlen] = LT_EOS_CHAR; ++base_name; } else LT_DLMEM_REASSIGN (base_name, canonical); assert (base_name && *base_name); /* Check whether we are opening a libtool module (.la extension). */ ext = strrchr (base_name, '.'); if (ext && strcmp (ext, archive_ext) == 0) { /* this seems to be a libtool module */ FILE * file = 0; char * dlname = 0; char * old_name = 0; char * libdir = 0; char * deplibs = 0; char * line = 0; size_t line_len; /* if we can't find the installed flag, it is probably an installed libtool archive, produced with an old version of libtool */ int installed = 1; /* extract the module name from the file name */ name = LT_EMALLOC (char, ext - base_name + 1); if (!name) { ++errors; goto cleanup; } /* canonicalize the module name */ { size_t i; for (i = 0; i < (unsigned int)(ext - base_name); ++i) { if (isalnum ((int)(base_name[i]))) { name[i] = base_name[i]; } else { name[i] = '_'; } } name[ext - base_name] = LT_EOS_CHAR; } /* Now try to open the .la file. If there is no directory name component, try to find it first in user_search_path and then other prescribed paths. Otherwise (or in any case if the module was not yet found) try opening just the module name as passed. */ if (!dir) { const char *search_path; LT_DLMUTEX_LOCK (); search_path = user_search_path; if (search_path) file = find_file (user_search_path, base_name, &dir); LT_DLMUTEX_UNLOCK (); if (!file) { search_path = getenv (LTDL_SEARCHPATH_VAR); if (search_path) file = find_file (search_path, base_name, &dir); } #ifdef LTDL_SHLIBPATH_VAR if (!file) { search_path = getenv (LTDL_SHLIBPATH_VAR); if (search_path) file = find_file (search_path, base_name, &dir); } #endif #ifdef LTDL_SYSSEARCHPATH if (!file) { file = find_file (sys_search_path, base_name, &dir); } #endif } if (!file) { file = fopen (filename, LT_READTEXT_MODE); } /* If we didn't find the file by now, it really isn't there. Set the status flag, and bail out. */ if (!file) { LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND)); ++errors; goto cleanup; } line_len = LT_FILENAME_MAX; line = LT_EMALLOC (char, line_len); if (!line) { fclose (file); ++errors; goto cleanup; } /* read the .la file */ while (!feof (file)) { if (!fgets (line, (int) line_len, file)) { break; } /* Handle the case where we occasionally need to read a line that is longer than the initial buffer size. */ while ((line[LT_STRLEN(line) -1] != '\n') && (!feof (file))) { line = LT_DLREALLOC (char, line, line_len *2); if (!fgets (&line[line_len -1], (int) line_len +1, file)) { break; } line_len *= 2; } if (line[0] == '\n' || line[0] == '#') { continue; } #undef STR_DLNAME #define STR_DLNAME "dlname=" if (strncmp (line, STR_DLNAME, sizeof (STR_DLNAME) - 1) == 0) { errors += trim (&dlname, &line[sizeof (STR_DLNAME) - 1]); } #undef STR_OLD_LIBRARY #define STR_OLD_LIBRARY "old_library=" else if (strncmp (line, STR_OLD_LIBRARY, sizeof (STR_OLD_LIBRARY) - 1) == 0) { errors += trim (&old_name, &line[sizeof (STR_OLD_LIBRARY) - 1]); } #undef STR_LIBDIR #define STR_LIBDIR "libdir=" else if (strncmp (line, STR_LIBDIR, sizeof (STR_LIBDIR) - 1) == 0) { errors += trim (&libdir, &line[sizeof(STR_LIBDIR) - 1]); } #undef STR_DL_DEPLIBS #define STR_DL_DEPLIBS "dependency_libs=" else if (strncmp (line, STR_DL_DEPLIBS, sizeof (STR_DL_DEPLIBS) - 1) == 0) { errors += trim (&deplibs, &line[sizeof (STR_DL_DEPLIBS) - 1]); } else if (strcmp (line, "installed=yes\n") == 0) { installed = 1; } else if (strcmp (line, "installed=no\n") == 0) { installed = 0; } #undef STR_LIBRARY_NAMES #define STR_LIBRARY_NAMES "library_names=" else if (! dlname && strncmp (line, STR_LIBRARY_NAMES, sizeof (STR_LIBRARY_NAMES) - 1) == 0) { char *last_libname; errors += trim (&dlname, &line[sizeof (STR_LIBRARY_NAMES) - 1]); if (!errors && dlname && (last_libname = strrchr (dlname, ' ')) != 0) { last_libname = lt_estrdup (last_libname + 1); if (!last_libname) { ++errors; goto cleanup; } LT_DLMEM_REASSIGN (dlname, last_libname); } } if (errors) break; } fclose (file); LT_DLFREE (line); /* allocate the handle */ *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1); if (*phandle == 0) ++errors; if (errors) { free_vars (dlname, old_name, libdir, deplibs); LT_DLFREE (*phandle); goto cleanup; } assert (*phandle); memset (*phandle, 0, sizeof(struct lt_dlhandle_struct)); if (load_deplibs (*phandle, deplibs) == 0) { newhandle = *phandle; /* find_module may replace newhandle */ if (find_module (&newhandle, dir, libdir, dlname, old_name, installed)) { unload_deplibs (*phandle); ++errors; } } else { ++errors; } free_vars (dlname, old_name, libdir, deplibs); if (errors) { LT_DLFREE (*phandle); goto cleanup; } if (*phandle != newhandle) { unload_deplibs (*phandle); } } else { /* not a libtool module */ *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1); if (*phandle == 0) { ++errors; goto cleanup; } memset (*phandle, 0, sizeof (struct lt_dlhandle_struct)); newhandle = *phandle; /* If the module has no directory name component, try to find it first in user_search_path and then other prescribed paths. Otherwise (or in any case if the module was not yet found) try opening just the module name as passed. */ if ((dir || (!find_handle (user_search_path, base_name, &newhandle) && !find_handle (getenv (LTDL_SEARCHPATH_VAR), base_name, &newhandle) #ifdef LTDL_SHLIBPATH_VAR && !find_handle (getenv (LTDL_SHLIBPATH_VAR), base_name, &newhandle) #endif #ifdef LTDL_SYSSEARCHPATH && !find_handle (sys_search_path, base_name, &newhandle) #endif ))) { if (tryall_dlopen (&newhandle, filename) != 0) { newhandle = NULL; } } if (!newhandle) { LT_DLFREE (*phandle); ++errors; goto cleanup; } } register_handle: LT_DLMEM_REASSIGN (*phandle, newhandle); if ((*phandle)->info.ref_count == 0) { (*phandle)->info.ref_count = 1; LT_DLMEM_REASSIGN ((*phandle)->info.name, name); LT_DLMUTEX_LOCK (); (*phandle)->next = handles; handles = *phandle; LT_DLMUTEX_UNLOCK (); } LT_DLMUTEX_SETERROR (saved_error); cleanup: LT_DLFREE (dir); LT_DLFREE (name); LT_DLFREE (canonical); return errors; } lt_dlhandle lt_dlopen (filename) const char *filename; { lt_dlhandle handle = 0; /* Just incase we missed a code path in try_dlopen() that reports an error, but forgets to reset handle... */ if (try_dlopen (&handle, filename) != 0) return 0; return handle; } /* If the last error messge store was `FILE_NOT_FOUND', then return non-zero. */ static int file_not_found () { const char *error = 0; LT_DLMUTEX_GETERROR (error); if (error == LT_DLSTRERROR (FILE_NOT_FOUND)) return 1; return 0; } /* If FILENAME has an ARCHIVE_EXT or SHLIB_EXT extension, try to open the FILENAME as passed. Otherwise try appending ARCHIVE_EXT, and if a file is still not found try again with SHLIB_EXT appended instead. */ lt_dlhandle lt_dlopenext (filename) const char *filename; { lt_dlhandle handle = 0; char * tmp = 0; char * ext = 0; size_t len; int errors = 0; if (!filename) { return lt_dlopen (filename); } assert (filename); len = LT_STRLEN (filename); ext = strrchr (filename, '.'); /* If FILENAME already bears a suitable extension, there is no need to try appending additional extensions. */ if (ext && ((strcmp (ext, archive_ext) == 0) #ifdef LTDL_SHLIB_EXT || (strcmp (ext, shlib_ext) == 0) #endif )) { return lt_dlopen (filename); } /* First try appending ARCHIVE_EXT. */ tmp = LT_EMALLOC (char, len + strlen (archive_ext) + 1); if (!tmp) return 0; strcpy (tmp, filename); strcat (tmp, archive_ext); errors = try_dlopen (&handle, tmp); /* If we found FILENAME, stop searching -- whether we were able to load the file as a module or not. If the file exists but loading failed, it is better to return an error message here than to report FILE_NOT_FOUND when the alternatives (foo.so etc) are not in the module search path. */ if (handle || ((errors > 0) && !file_not_found ())) { LT_DLFREE (tmp); return handle; } #ifdef LTDL_SHLIB_EXT /* Try appending SHLIB_EXT. */ if (LT_STRLEN (shlib_ext) > strlen (archive_ext)) { LT_DLFREE (tmp); tmp = LT_EMALLOC (char, len + LT_STRLEN (shlib_ext) + 1); if (!tmp) return 0; strcpy (tmp, filename); } else { tmp[len] = LT_EOS_CHAR; } strcat(tmp, shlib_ext); errors = try_dlopen (&handle, tmp); /* As before, if the file was found but loading failed, return now with the current error message. */ if (handle || ((errors > 0) && !file_not_found ())) { LT_DLFREE (tmp); return handle; } #endif /* Still here? Then we really did fail to locate any of the file names we tried. */ LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND)); LT_DLFREE (tmp); return 0; } static int lt_argz_insert (pargz, pargz_len, before, entry) char **pargz; size_t *pargz_len; char *before; const char *entry; { error_t error; if ((error = argz_insert (pargz, pargz_len, before, entry))) { switch (error) { case ENOMEM: LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY)); break; default: LT_DLMUTEX_SETERROR (LT_DLSTRERROR (UNKNOWN)); break; } return 1; } return 0; } static int lt_argz_insertinorder (pargz, pargz_len, entry) char **pargz; size_t *pargz_len; const char *entry; { char *before = 0; assert (pargz); assert (pargz_len); assert (entry && *entry); if (*pargz) while ((before = argz_next (*pargz, *pargz_len, before))) { int cmp = strcmp (entry, before); if (cmp < 0) break; if (cmp == 0) return 0; /* No duplicates! */ } return lt_argz_insert (pargz, pargz_len, before, entry); } static int lt_argz_insertdir (pargz, pargz_len, dirnam, dp) char **pargz; size_t *pargz_len; const char *dirnam; struct dirent *dp; { char *buf = 0; size_t buf_len = 0; char *end = 0; size_t end_offset = 0; size_t dir_len = 0; int errors = 0; assert (pargz); assert (pargz_len); assert (dp); dir_len = LT_STRLEN (dirnam); end = dp->d_name + LT_D_NAMLEN(dp); /* Ignore version numbers. */ { char *p; for (p = end; p -1 > dp->d_name; --p) if (strchr (".0123456789", p[-1]) == 0) break; if (*p == '.') end = p; } /* Ignore filename extension. */ { char *p; for (p = end -1; p > dp->d_name; --p) if (*p == '.') { end = p; break; } } /* Prepend the directory name. */ end_offset = end - dp->d_name; buf_len = dir_len + 1+ end_offset; buf = LT_EMALLOC (char, 1+ buf_len); if (!buf) return ++errors; assert (buf); strcpy (buf, dirnam); strcat (buf, "/"); strncat (buf, dp->d_name, end_offset); buf[buf_len] = LT_EOS_CHAR; /* Try to insert (in order) into ARGZ/ARGZ_LEN. */ if (lt_argz_insertinorder (pargz, pargz_len, buf) != 0) ++errors; LT_DLFREE (buf); return errors; } static int list_files_by_dir (dirnam, pargz, pargz_len) const char *dirnam; char **pargz; size_t *pargz_len; { DIR *dirp = 0; int errors = 0; assert (dirnam && *dirnam); assert (pargz); assert (pargz_len); assert (dirnam[LT_STRLEN(dirnam) -1] != '/'); dirp = opendir (dirnam); if (dirp) { struct dirent *dp = 0; while ((dp = readdir (dirp))) if (dp->d_name[0] != '.') if (lt_argz_insertdir (pargz, pargz_len, dirnam, dp)) { ++errors; break; } closedir (dirp); } else ++errors; return errors; } /* If there are any files in DIRNAME, call the function passed in DATA1 (with the name of each file and DATA2 as arguments). */ static int foreachfile_callback (dirname, data1, data2) char *dirname; lt_ptr data1; lt_ptr data2; { int (*func) LT_PARAMS((const char *filename, lt_ptr data)) = (int (*) LT_PARAMS((const char *filename, lt_ptr data))) data1; int is_done = 0; char *argz = 0; size_t argz_len = 0; if (list_files_by_dir (dirname, &argz, &argz_len) != 0) goto cleanup; if (!argz) goto cleanup; { char *filename = 0; while ((filename = argz_next (argz, argz_len, filename))) if ((is_done = (*func) (filename, data2))) break; } cleanup: LT_DLFREE (argz); return is_done; } /* Call FUNC for each unique extensionless file in SEARCH_PATH, along with DATA. The filenames passed to FUNC would be suitable for passing to lt_dlopenext. The extensions are stripped so that individual modules do not generate several entries (e.g. libfoo.la, libfoo.so, libfoo.so.1, libfoo.so.1.0.0). If SEARCH_PATH is NULL, then the same directories that lt_dlopen would search are examined. */ int lt_dlforeachfile (search_path, func, data) const char *search_path; int (*func) LT_PARAMS ((const char *filename, lt_ptr data)); lt_ptr data; { int is_done = 0; if (search_path) { /* If a specific path was passed, search only the directories listed in it. */ is_done = foreach_dirinpath (search_path, 0, foreachfile_callback, func, data); } else { /* Otherwise search the default paths. */ is_done = foreach_dirinpath (user_search_path, 0, foreachfile_callback, func, data); if (!is_done) { is_done = foreach_dirinpath (getenv("LTDL_LIBRARY_PATH"), 0, foreachfile_callback, func, data); } #ifdef LTDL_SHLIBPATH_VAR if (!is_done) { is_done = foreach_dirinpath (getenv(LTDL_SHLIBPATH_VAR), 0, foreachfile_callback, func, data); } #endif #ifdef LTDL_SYSSEARCHPATH if (!is_done) { is_done = foreach_dirinpath (getenv(LTDL_SYSSEARCHPATH), 0, foreachfile_callback, func, data); } #endif } return is_done; } int lt_dlclose (handle) lt_dlhandle handle; { lt_dlhandle cur, last; int errors = 0; LT_DLMUTEX_LOCK (); /* check whether the handle is valid */ last = cur = handles; while (cur && handle != cur) { last = cur; cur = cur->next; } if (!cur) { LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE)); ++errors; goto done; } handle->info.ref_count--; /* Note that even with resident modules, we must track the ref_count correctly incase the user decides to reset the residency flag later (even though the API makes no provision for that at the moment). */ if (handle->info.ref_count <= 0 && !LT_DLIS_RESIDENT (handle)) { lt_user_data data = handle->loader->dlloader_data; if (handle != handles) { last->next = handle->next; } else { handles = handle->next; } errors += handle->loader->module_close (data, handle->module); errors += unload_deplibs(handle); /* It is up to the callers to free the data itself. */ LT_DLFREE (handle->caller_data); LT_DLFREE (handle->info.filename); LT_DLFREE (handle->info.name); LT_DLFREE (handle); goto done; } if (LT_DLIS_RESIDENT (handle)) { LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CLOSE_RESIDENT_MODULE)); ++errors; } done: LT_DLMUTEX_UNLOCK (); return errors; } lt_ptr lt_dlsym (handle, symbol) lt_dlhandle handle; const char *symbol; { size_t lensym; char lsym[LT_SYMBOL_LENGTH]; char *sym; lt_ptr address; lt_user_data data; if (!handle) { LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE)); return 0; } if (!symbol) { LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND)); return 0; } lensym = LT_STRLEN (symbol) + LT_STRLEN (handle->loader->sym_prefix) + LT_STRLEN (handle->info.name); if (lensym + LT_SYMBOL_OVERHEAD < LT_SYMBOL_LENGTH) { sym = lsym; } else { sym = LT_EMALLOC (char, lensym + LT_SYMBOL_OVERHEAD + 1); if (!sym) { LT_DLMUTEX_SETERROR (LT_DLSTRERROR (BUFFER_OVERFLOW)); return 0; } } data = handle->loader->dlloader_data; if (handle->info.name) { const char *saved_error; LT_DLMUTEX_GETERROR (saved_error); /* this is a libtool module */ if (handle->loader->sym_prefix) { strcpy(sym, handle->loader->sym_prefix); strcat(sym, handle->info.name); } else { strcpy(sym, handle->info.name); } strcat(sym, "_LTX_"); strcat(sym, symbol); /* try "modulename_LTX_symbol" */ address = handle->loader->find_sym (data, handle->module, sym); if (address) { if (sym != lsym) { LT_DLFREE (sym); } return address; } LT_DLMUTEX_SETERROR (saved_error); } /* otherwise try "symbol" */ if (handle->loader->sym_prefix) { strcpy(sym, handle->loader->sym_prefix); strcat(sym, symbol); } else { strcpy(sym, symbol); } address = handle->loader->find_sym (data, handle->module, sym); if (sym != lsym) { LT_DLFREE (sym); } return address; } const char * lt_dlerror () { const char *error; LT_DLMUTEX_GETERROR (error); LT_DLMUTEX_SETERROR (0); return error ? error : LT_DLSTRERROR (UNKNOWN); } static int lt_dlpath_insertdir (ppath, before, dir) char **ppath; char *before; const char *dir; { int errors = 0; char *canonical = 0; char *argz = 0; size_t argz_len = 0; assert (ppath); assert (dir && *dir); if (canonicalize_path (dir, &canonical) != 0) { ++errors; goto cleanup; } assert (canonical && *canonical); /* If *PPATH is empty, set it to DIR. */ if (*ppath == 0) { assert (!before); /* BEFORE cannot be set without PPATH. */ assert (dir); /* Without DIR, don't call this function! */ *ppath = lt_estrdup (dir); if (*ppath == 0) ++errors; return errors; } assert (ppath && *ppath); if (argzize_path (*ppath, &argz, &argz_len) != 0) { ++errors; goto cleanup; } /* Convert BEFORE into an equivalent offset into ARGZ. This only works if *PPATH is already canonicalized, and hence does not change length with respect to ARGZ. We canonicalize each entry as it is added to the search path, and don't call this function with (uncanonicalized) user paths, so this is a fair assumption. */ if (before) { assert (*ppath <= before); assert (before - *ppath <= (int)strlen (*ppath)); before = before - *ppath + argz; } if (lt_argz_insert (&argz, &argz_len, before, dir) != 0) { ++errors; goto cleanup; } argz_stringify (argz, argz_len, LT_PATHSEP_CHAR); LT_DLMEM_REASSIGN (*ppath, argz); cleanup: LT_DLFREE (canonical); LT_DLFREE (argz); return errors; } int lt_dladdsearchdir (search_dir) const char *search_dir; { int errors = 0; if (search_dir && *search_dir) { LT_DLMUTEX_LOCK (); if (lt_dlpath_insertdir (&user_search_path, 0, search_dir) != 0) ++errors; LT_DLMUTEX_UNLOCK (); } return errors; } int lt_dlinsertsearchdir (before, search_dir) const char *before; const char *search_dir; { int errors = 0; if (before) { LT_DLMUTEX_LOCK (); if ((before < user_search_path) || (before >= user_search_path + LT_STRLEN (user_search_path))) { LT_DLMUTEX_UNLOCK (); LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_POSITION)); return 1; } LT_DLMUTEX_UNLOCK (); } if (search_dir && *search_dir) { LT_DLMUTEX_LOCK (); if (lt_dlpath_insertdir (&user_search_path, (char *) before, search_dir) != 0) { ++errors; } LT_DLMUTEX_UNLOCK (); } return errors; } int lt_dlsetsearchpath (search_path) const char *search_path; { int errors = 0; LT_DLMUTEX_LOCK (); LT_DLFREE (user_search_path); LT_DLMUTEX_UNLOCK (); if (!search_path || !LT_STRLEN (search_path)) { return errors; } LT_DLMUTEX_LOCK (); if (canonicalize_path (search_path, &user_search_path) != 0) ++errors; LT_DLMUTEX_UNLOCK (); return errors; } const char * lt_dlgetsearchpath () { const char *saved_path; LT_DLMUTEX_LOCK (); saved_path = user_search_path; LT_DLMUTEX_UNLOCK (); return saved_path; } int lt_dlmakeresident (handle) lt_dlhandle handle; { int errors = 0; if (!handle) { LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE)); ++errors; } else { LT_DLSET_FLAG (handle, LT_DLRESIDENT_FLAG); } return errors; } int lt_dlisresident (handle) lt_dlhandle handle; { if (!handle) { LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE)); return -1; } return LT_DLIS_RESIDENT (handle); } /* --- MODULE INFORMATION --- */ const lt_dlinfo * lt_dlgetinfo (handle) lt_dlhandle handle; { if (!handle) { LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE)); return 0; } return &(handle->info); } lt_dlhandle lt_dlhandle_next (place) lt_dlhandle place; { return place ? place->next : handles; } int lt_dlforeach (func, data) int (*func) LT_PARAMS((lt_dlhandle handle, lt_ptr data)); lt_ptr data; { int errors = 0; lt_dlhandle cur; LT_DLMUTEX_LOCK (); cur = handles; while (cur) { lt_dlhandle tmp = cur; cur = cur->next; if ((*func) (tmp, data)) { ++errors; break; } } LT_DLMUTEX_UNLOCK (); return errors; } lt_dlcaller_id lt_dlcaller_register () { static lt_dlcaller_id last_caller_id = 0; int result; LT_DLMUTEX_LOCK (); result = ++last_caller_id; LT_DLMUTEX_UNLOCK (); return result; } lt_ptr lt_dlcaller_set_data (key, handle, data) lt_dlcaller_id key; lt_dlhandle handle; lt_ptr data; { int n_elements = 0; lt_ptr stale = (lt_ptr) 0; int i; /* This needs to be locked so that the caller data can be updated simultaneously by different threads. */ LT_DLMUTEX_LOCK (); if (handle->caller_data) while (handle->caller_data[n_elements].key) ++n_elements; for (i = 0; i < n_elements; ++i) { if (handle->caller_data[i].key == key) { stale = handle->caller_data[i].data; break; } } /* Ensure that there is enough room in this handle's caller_data array to accept a new element (and an empty end marker). */ if (i == n_elements) { lt_caller_data *temp = LT_DLREALLOC (lt_caller_data, handle->caller_data, 2+ n_elements); if (!temp) { stale = 0; goto done; } handle->caller_data = temp; /* We only need this if we needed to allocate a new caller_data. */ handle->caller_data[i].key = key; handle->caller_data[1+ i].key = 0; } handle->caller_data[i].data = data; done: LT_DLMUTEX_UNLOCK (); return stale; } lt_ptr lt_dlcaller_get_data (key, handle) lt_dlcaller_id key; lt_dlhandle handle; { lt_ptr result = (lt_ptr) 0; /* This needs to be locked so that the caller data isn't updated by another thread part way through this function. */ LT_DLMUTEX_LOCK (); /* Locate the index of the element with a matching KEY. */ { int i; for (i = 0; handle->caller_data[i].key; ++i) { if (handle->caller_data[i].key == key) { result = handle->caller_data[i].data; break; } } } LT_DLMUTEX_UNLOCK (); return result; } /* --- USER MODULE LOADER API --- */ int lt_dlloader_add (place, dlloader, loader_name) lt_dlloader *place; const struct lt_user_dlloader *dlloader; const char *loader_name; { int errors = 0; lt_dlloader *node = 0, *ptr = 0; if ((dlloader == 0) /* diagnose null parameters */ || (dlloader->module_open == 0) || (dlloader->module_close == 0) || (dlloader->find_sym == 0)) { LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER)); return 1; } /* Create a new dlloader node with copies of the user callbacks. */ node = LT_EMALLOC (lt_dlloader, 1); if (!node) return 1; node->next = 0; node->loader_name = loader_name; node->sym_prefix = dlloader->sym_prefix; node->dlloader_exit = dlloader->dlloader_exit; node->module_open = dlloader->module_open; node->module_close = dlloader->module_close; node->find_sym = dlloader->find_sym; node->dlloader_data = dlloader->dlloader_data; LT_DLMUTEX_LOCK (); if (!loaders) { /* If there are no loaders, NODE becomes the list! */ loaders = node; } else if (!place) { /* If PLACE is not set, add NODE to the end of the LOADERS list. */ for (ptr = loaders; ptr->next; ptr = ptr->next) { /*NOWORK*/; } ptr->next = node; } else if (loaders == place) { /* If PLACE is the first loader, NODE goes first. */ node->next = place; loaders = node; } else { /* Find the node immediately preceding PLACE. */ for (ptr = loaders; ptr->next != place; ptr = ptr->next) { /*NOWORK*/; } if (ptr->next != place) { LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER)); ++errors; } else { /* Insert NODE between PTR and PLACE. */ node->next = place; ptr->next = node; } } LT_DLMUTEX_UNLOCK (); return errors; } int lt_dlloader_remove (loader_name) const char *loader_name; { lt_dlloader *place = lt_dlloader_find (loader_name); lt_dlhandle handle; int errors = 0; if (!place) { LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER)); return 1; } LT_DLMUTEX_LOCK (); /* Fail if there are any open modules which use this loader. */ for (handle = handles; handle; handle = handle->next) { if (handle->loader == place) { LT_DLMUTEX_SETERROR (LT_DLSTRERROR (REMOVE_LOADER)); ++errors; goto done; } } if (place == loaders) { /* PLACE is the first loader in the list. */ loaders = loaders->next; } else { /* Find the loader before the one being removed. */ lt_dlloader *prev; for (prev = loaders; prev->next; prev = prev->next) { if (!strcmp (prev->next->loader_name, loader_name)) { break; } } place = prev->next; prev->next = prev->next->next; } if (place->dlloader_exit) { errors = place->dlloader_exit (place->dlloader_data); } LT_DLFREE (place); done: LT_DLMUTEX_UNLOCK (); return errors; } lt_dlloader * lt_dlloader_next (place) lt_dlloader *place; { lt_dlloader *next; LT_DLMUTEX_LOCK (); next = place ? place->next : loaders; LT_DLMUTEX_UNLOCK (); return next; } const char * lt_dlloader_name (place) lt_dlloader *place; { const char *name = 0; if (place) { LT_DLMUTEX_LOCK (); name = place ? place->loader_name : 0; LT_DLMUTEX_UNLOCK (); } else { LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER)); } return name; } lt_user_data * lt_dlloader_data (place) lt_dlloader *place; { lt_user_data *data = 0; if (place) { LT_DLMUTEX_LOCK (); data = place ? &(place->dlloader_data) : 0; LT_DLMUTEX_UNLOCK (); } else { LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER)); } return data; } lt_dlloader * lt_dlloader_find (loader_name) const char *loader_name; { lt_dlloader *place = 0; LT_DLMUTEX_LOCK (); for (place = loaders; place; place = place->next) { if (strcmp (place->loader_name, loader_name) == 0) { break; } } LT_DLMUTEX_UNLOCK (); return place; } #endif hercules-3.07/ltdl.h000644 000765 000765 00000030617 11143760542 016065 0ustar00jmaynardjmaynard000000 000000 /* ltdl.h -- generic dlopen functions Copyright (C) 1998-2000 Free Software Foundation, Inc. Originally by Thomas Tanner This file is part of GNU Libtool. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. As a special exception to the GNU Lesser General Public License, if you distribute this file as part of a program or library that is built using GNU libtool, you may include it under the same distribution terms that you use for the rest of that program. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* Only include this header file once. */ #ifndef LTDL_H #define LTDL_H 1 #include /* for size_t declaration */ /* --- MACROS FOR PORTABILITY --- */ /* Saves on those hard to debug '\0' typos.... */ #define LT_EOS_CHAR '\0' /* LTDL_BEGIN_C_DECLS should be used at the beginning of your declarations, so that C++ compilers don't mangle their names. Use LTDL_END_C_DECLS at the end of C declarations. */ #ifdef __cplusplus # define LT_BEGIN_C_DECLS extern "C" { # define LT_END_C_DECLS } #else # define LT_BEGIN_C_DECLS /* empty */ # define LT_END_C_DECLS /* empty */ #endif LT_BEGIN_C_DECLS /* LT_PARAMS is a macro used to wrap function prototypes, so that compilers that don't understand ANSI C prototypes still work, and ANSI C compilers can issue warnings about type mismatches. */ #if defined (__STDC__) || defined (_AIX) || (defined (__mips) && defined (_SYSTYPE_SVR4)) || defined(WIN32) || defined(__cplusplus) # define LT_PARAMS(protos) protos # define lt_ptr void* #else # define LT_PARAMS(protos) () # define lt_ptr char* #endif /* LT_STMT_START/END are used to create macros which expand to a a single compound statement in a portable way. */ #if defined (__GNUC__) && !defined (__STRICT_ANSI__) && !defined (__cplusplus) # define LT_STMT_START (void)( # define LT_STMT_END ) #else # if (defined (sun) || defined (__sun__)) # define LT_STMT_START if (1) # define LT_STMT_END else (void)0 # else # define LT_STMT_START do # define LT_STMT_END while (0) # endif #endif /* LT_CONC creates a new concatenated symbol for the compiler in a portable way. */ #if defined(__STDC__) || defined(__cplusplus) || defined(_MSC_VER) # define LT_CONC(s,t) s##t #else # define LT_CONC(s,t) s/**/t #endif /* LT_STRLEN can be used safely on NULL pointers. */ #define LT_STRLEN(s) (((s) && (s)[0]) ? strlen (s) : 0) /* --- WINDOWS SUPPORT --- */ /* Canonicalise Windows and Cygwin recognition macros. */ #ifdef __CYGWIN32__ # ifndef __CYGWIN__ # define __CYGWIN__ __CYGWIN32__ # endif #endif #if defined(_WIN32) || defined(WIN32) # ifndef __WINDOWS__ # ifdef _WIN32 # define __WINDOWS__ _WIN32 # else # ifdef WIN32 # define __WINDOWS__ WIN32 # endif # endif # endif #endif #ifdef __WINDOWS__ # ifndef __CYGWIN__ /* LT_DIRSEP_CHAR is accepted *in addition* to '/' as a directory separator when it is set. */ # define LT_DIRSEP_CHAR '\\' # define LT_PATHSEP_CHAR ';' # endif #endif #ifndef LT_PATHSEP_CHAR # define LT_PATHSEP_CHAR ':' #endif /* DLL building support on win32 hosts; mostly to workaround their ridiculous implementation of data symbol exporting. */ #ifndef LT_SCOPE # ifdef __WINDOWS__ # ifdef DLL_EXPORT /* defined by libtool (if required) */ # define LT_SCOPE __declspec(dllexport) # endif # ifdef LIBLTDL_DLL_IMPORT /* define if linking with this dll */ # define LT_SCOPE extern __declspec(dllimport) # endif # endif # ifndef LT_SCOPE /* static linking or !__WINDOWS__ */ # define LT_SCOPE extern # endif #endif #if defined(_MSC_VER) /* Visual Studio */ # define R_OK 4 #endif /* --- DYNAMIC MODULE LOADING API --- */ typedef struct lt_dlhandle_struct *lt_dlhandle; /* A loaded module. */ /* Initialisation and finalisation functions for libltdl. */ LT_SCOPE int lt_dlinit LT_PARAMS((void)); LT_SCOPE int lt_dlexit LT_PARAMS((void)); /* Module search path manipulation. */ LT_SCOPE int lt_dladdsearchdir LT_PARAMS((const char *search_dir)); LT_SCOPE int lt_dlinsertsearchdir LT_PARAMS((const char *before, const char *search_dir)); LT_SCOPE int lt_dlsetsearchpath LT_PARAMS((const char *search_path)); LT_SCOPE const char *lt_dlgetsearchpath LT_PARAMS((void)); LT_SCOPE int lt_dlforeachfile LT_PARAMS(( const char *search_path, int (*func) (const char *filename, lt_ptr data), lt_ptr data)); /* Portable libltdl versions of the system dlopen() API. */ LT_SCOPE lt_dlhandle lt_dlopen LT_PARAMS((const char *filename)); LT_SCOPE lt_dlhandle lt_dlopenext LT_PARAMS((const char *filename)); LT_SCOPE lt_ptr lt_dlsym LT_PARAMS((lt_dlhandle handle, const char *name)); LT_SCOPE const char *lt_dlerror LT_PARAMS((void)); LT_SCOPE int lt_dlclose LT_PARAMS((lt_dlhandle handle)); /* Module residency management. */ LT_SCOPE int lt_dlmakeresident LT_PARAMS((lt_dlhandle handle)); LT_SCOPE int lt_dlisresident LT_PARAMS((lt_dlhandle handle)); /* --- MUTEX LOCKING --- */ typedef void lt_dlmutex_lock LT_PARAMS((void)); typedef void lt_dlmutex_unlock LT_PARAMS((void)); typedef void lt_dlmutex_seterror LT_PARAMS((const char *errmsg)); typedef const char *lt_dlmutex_geterror LT_PARAMS((void)); LT_SCOPE int lt_dlmutex_register LT_PARAMS((lt_dlmutex_lock *lock, lt_dlmutex_unlock *unlock, lt_dlmutex_seterror *seterror, lt_dlmutex_geterror *geterror)); /* --- MEMORY HANDLING --- */ /* By default, the realloc function pointer is set to our internal realloc implementation which iself uses lt_dlmalloc and lt_dlfree. libltdl relies on a featureful realloc, but if you are sure yours has the right semantics then you can assign it directly. Generally, it is safe to assign just a malloc() and a free() function. */ LT_SCOPE lt_ptr (*lt_dlmalloc) LT_PARAMS((size_t size)); LT_SCOPE lt_ptr (*lt_dlrealloc) LT_PARAMS((lt_ptr ptr, size_t size)); LT_SCOPE void (*lt_dlfree) LT_PARAMS((lt_ptr ptr)); /* --- PRELOADED MODULE SUPPORT --- */ /* A preopened symbol. Arrays of this type comprise the exported symbols for a dlpreopened module. */ typedef struct { const char *name; lt_ptr address; } lt_dlsymlist; LT_SCOPE int lt_dlpreload LT_PARAMS((const lt_dlsymlist *preloaded)); LT_SCOPE int lt_dlpreload_default LT_PARAMS((const lt_dlsymlist *preloaded)); #define LTDL_SET_PRELOADED_SYMBOLS() LT_STMT_START{ \ extern const lt_dlsymlist lt_preloaded_symbols[]; \ lt_dlpreload_default(lt_preloaded_symbols); \ }LT_STMT_END /* --- MODULE INFORMATION --- */ /* Read only information pertaining to a loaded module. */ typedef struct { char *filename; /* file name */ char *name; /* module name */ int ref_count; /* number of times lt_dlopened minus number of times lt_dlclosed. */ } lt_dlinfo; LT_SCOPE const lt_dlinfo *lt_dlgetinfo LT_PARAMS((lt_dlhandle handle)); LT_SCOPE lt_dlhandle lt_dlhandle_next LT_PARAMS((lt_dlhandle place)); LT_SCOPE int lt_dlforeach LT_PARAMS(( int (*func) (lt_dlhandle handle, lt_ptr data), lt_ptr data)); /* Associating user data with loaded modules. */ typedef unsigned lt_dlcaller_id; LT_SCOPE lt_dlcaller_id lt_dlcaller_register LT_PARAMS((void)); LT_SCOPE lt_ptr lt_dlcaller_set_data LT_PARAMS((lt_dlcaller_id key, lt_dlhandle handle, lt_ptr data)); LT_SCOPE lt_ptr lt_dlcaller_get_data LT_PARAMS((lt_dlcaller_id key, lt_dlhandle handle)); /* --- USER MODULE LOADER API --- */ typedef struct lt_dlloader lt_dlloader; typedef lt_ptr lt_user_data; typedef lt_ptr lt_module; /* Function pointer types for creating user defined module loaders. */ typedef lt_module lt_module_open LT_PARAMS((lt_user_data loader_data, const char *filename)); typedef int lt_module_close LT_PARAMS((lt_user_data loader_data, lt_module handle)); typedef lt_ptr lt_find_sym LT_PARAMS((lt_user_data loader_data, lt_module handle, const char *symbol)); typedef int lt_dlloader_exit LT_PARAMS((lt_user_data loader_data)); struct lt_user_dlloader { const char *sym_prefix; lt_module_open *module_open; lt_module_close *module_close; lt_find_sym *find_sym; lt_dlloader_exit *dlloader_exit; lt_user_data dlloader_data; }; LT_SCOPE lt_dlloader *lt_dlloader_next LT_PARAMS((lt_dlloader *place)); LT_SCOPE lt_dlloader *lt_dlloader_find LT_PARAMS(( const char *loader_name)); LT_SCOPE const char *lt_dlloader_name LT_PARAMS((lt_dlloader *place)); LT_SCOPE lt_user_data *lt_dlloader_data LT_PARAMS((lt_dlloader *place)); LT_SCOPE int lt_dlloader_add LT_PARAMS((lt_dlloader *place, const struct lt_user_dlloader *dlloader, const char *loader_name)); LT_SCOPE int lt_dlloader_remove LT_PARAMS(( const char *loader_name)); /* --- ERROR MESSAGE HANDLING --- */ /* Defining error strings alongside their symbolic names in a macro in this way allows us to expand the macro in different contexts with confidence that the enumeration of symbolic names will map correctly onto the table of error strings. */ #define lt_dlerror_table \ LT_ERROR(UNKNOWN, "unknown error") \ LT_ERROR(DLOPEN_NOT_SUPPORTED, "dlopen support not available") \ LT_ERROR(INVALID_LOADER, "invalid loader") \ LT_ERROR(INIT_LOADER, "loader initialization failed") \ LT_ERROR(REMOVE_LOADER, "loader removal failed") \ LT_ERROR(FILE_NOT_FOUND, "file not found") \ LT_ERROR(DEPLIB_NOT_FOUND, "dependency library not found") \ LT_ERROR(NO_SYMBOLS, "no symbols defined") \ LT_ERROR(CANNOT_OPEN, "can't open the module") \ LT_ERROR(CANNOT_CLOSE, "can't close the module") \ LT_ERROR(SYMBOL_NOT_FOUND, "symbol not found") \ LT_ERROR(NO_MEMORY, "not enough memory") \ LT_ERROR(INVALID_HANDLE, "invalid module handle") \ LT_ERROR(BUFFER_OVERFLOW, "internal buffer overflow") \ LT_ERROR(INVALID_ERRORCODE, "invalid errorcode") \ LT_ERROR(SHUTDOWN, "library already shutdown") \ LT_ERROR(CLOSE_RESIDENT_MODULE, "can't close resident module") \ LT_ERROR(INVALID_MUTEX_ARGS, "invalid mutex handler registration") \ LT_ERROR(INVALID_POSITION, "invalid search path insert position") /* Enumerate the symbolic error names. */ enum { #define LT_ERROR(name, diagnostic) LT_CONC(LT_ERROR_, name), lt_dlerror_table #undef LT_ERROR LT_ERROR_MAX }; /* These functions are only useful from inside custom module loaders. */ LT_SCOPE int lt_dladderror LT_PARAMS((const char *diagnostic)); LT_SCOPE int lt_dlseterror LT_PARAMS((int errorcode)); /* --- SOURCE COMPATIBILITY WITH OLD LIBLTDL --- */ #ifdef LT_NON_POSIX_NAMESPACE # define lt_ptr_t lt_ptr # define lt_module_t lt_module # define lt_module_open_t lt_module_open # define lt_module_close_t lt_module_close # define lt_find_sym_t lt_find_sym # define lt_dlloader_exit_t lt_dlloader_exit # define lt_dlloader_t lt_dlloader # define lt_dlloader_data_t lt_user_data #endif LT_END_C_DECLS #endif /* !LTDL_H */ hercules-3.07/m4/000777 000765 000765 00000000000 11345533274 015276 5ustar00jmaynardjmaynard000000 000000 hercules-3.07/machchk.c000644 000765 000765 00000032305 11143760543 016514 0ustar00jmaynardjmaynard000000 000000 /* MACHCHK.C (c) Copyright Jan Jaeger, 2000-2009 */ /* ESA/390 Machine Check Functions */ /* z/Architecture support - (c) Copyright Jan Jaeger, 1999-2009 */ // $Id: machchk.c 5126 2009-01-23 13:05:56Z bernard $ /*-------------------------------------------------------------------*/ /* The machine check function supports dynamic I/O configuration. */ /* When a subchannel is added/changed/deleted an ancillary */ /* channel report is made pending. This ancillary channel */ /* report can be read by the store channel report word I/O */ /* instruction. Changes to the availability will result in */ /* Messages IOS150I and IOS151I (device xxxx now/not available) */ /* Added Instruction processing damage machine check function such */ /* that abends/waits/loops in instructions will be reflected to the */ /* system running under hercules as a machine malfunction. This */ /* includes the machine check, checkstop, and malfunction alert */ /* external interrupt as defined in the architecture. - 6/8/01 *JJ */ /*-------------------------------------------------------------------*/ // $Log$ // Revision 1.51 2009/01/15 17:36:44 jj // Change http server startup // // Revision 1.50 2007/06/23 00:04:14 ivan // Update copyright notices to include current year (2007) // // Revision 1.49 2007/01/16 01:45:33 gsmith // Tweaks to instruction stepping/tracing // // Revision 1.48 2006/12/08 09:43:28 jj // Add CVS message log // #include "hstdinc.h" #if !defined(_HENGINE_DLL_) #define _HENGINE_DLL_ #endif #if !defined(_MACHCHK_C_) #define _MACHCHK_C_ #endif #include "hercules.h" #include "opcode.h" #if !defined(_MACHCHK_C) #define _MACHCHK_C /*-------------------------------------------------------------------*/ /* Return pending channel report */ /* */ /* Returns zero if no device has CRW pending. Otherwise returns */ /* the channel report word for the first channel path or device */ /* which has a CRW pending, and resets the CRW for that device. */ /*-------------------------------------------------------------------*/ U32 channel_report(REGS *regs) { DEVBLK *dev; U32 i,j; /* Scan for channel path reset CRW's */ for(i = 0; i < 8; i++) { if(sysblk.chp_reset[i]) { OBTAIN_INTLOCK(regs); for(j = 0; j < 32; j++) { if(sysblk.chp_reset[i] & (0x80000000 >> j)) { sysblk.chp_reset[i] &= ~(0x80000000 >> j); RELEASE_INTLOCK(regs); return CRW_SOL | CRW_CHPID | CRW_AR | CRW_INIT | ((i*32)+j); } } RELEASE_INTLOCK(regs); } } /* Scan for subchannel alert CRW's */ for(dev = sysblk.firstdev; dev!= NULL; dev = dev->nextdev) { if(dev->crwpending) { obtain_lock(&dev->lock); if(dev->crwpending) { dev->crwpending = 0; release_lock(&dev->lock); return CRW_SUBCH | CRW_AR | CRW_ALERT | dev->subchan; } release_lock(&dev->lock); } } return 0; } /* end function channel_report */ /*-------------------------------------------------------------------*/ /* Indicate crw pending */ /*-------------------------------------------------------------------*/ void machine_check_crwpend() { /* Signal waiting CPUs that an interrupt may be pending */ OBTAIN_INTLOCK(NULL); ON_IC_CHANRPT; WAKEUP_CPUS_MASK (sysblk.waiting_mask); RELEASE_INTLOCK(NULL); } /* end function machine_check_crwpend */ #endif /*!defined(_MACHCHK_C)*/ /*-------------------------------------------------------------------*/ /* Present Machine Check Interrupt */ /* Input: */ /* regs Pointer to the CPU register context */ /* Output: */ /* mcic Machine check interrupt code */ /* xdmg External damage code */ /* fsta Failing storage address */ /* Return code: */ /* 0=No machine check, 1=Machine check presented */ /* */ /* Generic machine check function. At the momement the only */ /* supported machine check is the channel report. */ /* */ /* This routine must be called with the sysblk.intlock held */ /*-------------------------------------------------------------------*/ int ARCH_DEP(present_mck_interrupt)(REGS *regs, U64 *mcic, U32 *xdmg, RADR *fsta) { int rc = 0; UNREFERENCED_370(regs); UNREFERENCED_370(mcic); UNREFERENCED_370(xdmg); UNREFERENCED_370(fsta); #ifdef FEATURE_CHANNEL_SUBSYSTEM /* If there is a crw pending and we are enabled for the channel report interrupt subclass then process the interrupt */ if( OPEN_IC_CHANRPT(regs) ) { *mcic = MCIC_CP | MCIC_WP | MCIC_MS | MCIC_PM | MCIC_IA | #ifdef FEATURE_HEXADECIMAL_FLOATING_POINT MCIC_FP | #endif /*FEATURE_HEXADECIMAL_FLOATING_POINT*/ MCIC_GR | MCIC_CR | MCIC_ST | #ifdef FEATURE_ACCESS_REGISTERS MCIC_AR | #endif /*FEATURE_ACCESS_REGISTERS*/ #if defined(FEATURE_ESAME) && defined(FEATURE_EXTENDED_TOD_CLOCK) MCIC_PR | #endif /*defined(FEATURE_ESAME) && defined(FEATURE_EXTENDED_TOD_CLOCK)*/ #if defined(FEATURE_BINARY_FLOATING_POINT) MCIC_XF | #endif /*defined(FEATURE_BINARY_FLOATING_POINT)*/ MCIC_AP | MCIC_CT | MCIC_CC ; *xdmg = 0; *fsta = 0; OFF_IC_CHANRPT; rc = 1; } if(!IS_IC_CHANRPT) #endif /*FEATURE_CHANNEL_SUBSYSTEM*/ OFF_IC_CHANRPT; return rc; } /* end function present_mck_interrupt */ void ARCH_DEP(sync_mck_interrupt) (REGS *regs) { int rc; /* Return code */ PSA *psa; /* -> Prefixed storage area */ U64 mcic = MCIC_P | /* Instruction processing damage */ MCIC_WP | MCIC_MS | MCIC_PM | MCIC_IA | #ifdef FEATURE_HEXADECIMAL_FLOATING_POINT MCIC_FP | #endif /*FEATURE_HEXADECIMAL_FLOATING_POINT*/ MCIC_GR | MCIC_CR | MCIC_ST | #ifdef FEATURE_ACCESS_REGISTERS MCIC_AR | #endif /*FEATURE_ACCESS_REGISTERS*/ #if defined(FEATURE_ESAME) && defined(FEATURE_EXTENDED_TOD_CLOCK) MCIC_PR | #endif /*defined(FEATURE_ESAME) && defined(FEATURE_EXTENDED_TOD_CLOCK)*/ #if defined(FEATURE_BINARY_FLOATING_POINT) MCIC_XF | #endif /*defined(FEATURE_BINARY_FLOATING_POINT)*/ MCIC_CT | MCIC_CC ; U32 xdmg = 0; RADR fsta = 0; /* Release intlock if held */ if (regs->cpuad == sysblk.intowner) RELEASE_INTLOCK(regs); /* Release mainlock if held */ if (regs->cpuad == sysblk.mainowner) RELEASE_MAINLOCK(regs); /* Exit SIE when active */ #if defined(FEATURE_INTERPRETIVE_EXECUTION) if(regs->sie_active) ARCH_DEP(sie_exit) (regs, SIE_HOST_INTERRUPT); #endif /*defined(FEATURE_INTERPRETIVE_EXECUTION)*/ /* Set the main storage reference and change bits */ STORAGE_KEY(regs->PX, regs) |= (STORKEY_REF | STORKEY_CHANGE); /* Point to the PSA in main storage */ psa = (void*)(regs->mainstor + regs->PX); /* Store registers in machine check save area */ ARCH_DEP(store_status) (regs, regs->PX); #if !defined(FEATURE_ESAME) // ZZ /* Set the extended logout area to zeros */ memset(psa->storepsw, 0, 16); #endif /* Store the machine check interrupt code at PSA+232 */ STORE_DW(psa->mckint, mcic); /* Trace the machine check interrupt */ if (CPU_STEPPING_OR_TRACING(regs, 0)) logmsg (_("HHCCP019I Machine Check code=%16.16" I64_FMT "u\n"), (long long)mcic); /* Store the external damage code at PSA+244 */ STORE_FW(psa->xdmgcode, xdmg); #if defined(FEATURE_ESAME) /* Store the failing storage address at PSA+248 */ STORE_DW(psa->mcstorad, fsta); #else /*!defined(FEATURE_ESAME)*/ /* Store the failing storage address at PSA+248 */ STORE_FW(psa->mcstorad, fsta); #endif /*!defined(FEATURE_ESAME)*/ /* Store current PSW at PSA+X'30' */ ARCH_DEP(store_psw) ( regs, psa->mckold ); /* Load new PSW from PSA+X'70' */ rc = ARCH_DEP(load_psw) ( regs, psa->mcknew ); if ( rc ) ARCH_DEP(program_interrupt) (regs, rc); } /* end function sync_mck_interrupt */ #if !defined(_GEN_ARCH) #if defined(_ARCHMODE2) #define _GEN_ARCH _ARCHMODE2 #include "machchk.c" #endif #if defined(_ARCHMODE3) #undef _GEN_ARCH #define _GEN_ARCH _ARCHMODE3 #include "machchk.c" #endif #if !defined(NO_SIGABEND_HANDLER) void sigabend_handler (int signo) { REGS *regs = NULL; TID tid; int i; tid = thread_id(); if( signo == SIGUSR2 ) { DEVBLK *dev; if ( equal_threads( tid, sysblk.cnsltid ) || equal_threads( tid, sysblk.socktid ) || equal_threads( tid, sysblk.httptid ) ) return; for (dev = sysblk.firstdev; dev != NULL; dev = dev->nextdev) if ( equal_threads( dev->tid, tid ) || equal_threads( dev->shrdtid, tid ) ) break; if( dev == NULL) { if (!sysblk.shutdown) logmsg(_("HHCCP020E signal USR2 received for " "undetermined device\n")); } else if(dev->ccwtrace) logmsg(_("HHCCP021E signal USR2 received for device " "%4.4X\n"),dev->devnum); return; } for (i = 0; i < MAX_CPU; i++) { if ( equal_threads( sysblk.cputid[i], tid ) ) { regs = sysblk.regs[i]; break; } } if (regs == NULL) { signal(signo, SIG_DFL); raise(signo); return; } if(MACHMASK(®s->psw)) { #if defined(_FEATURE_SIE) logmsg(_("HHCCP017I CPU%4.4X: Machine check due to host error: %s\n"), regs->sie_active ? regs->guestregs->cpuad : regs->cpuad, strsignal(signo)); #else /*!defined(_FEATURE_SIE)*/ logmsg(_("HHCCP017I CPU%4.4X: Machine check due to host error: %s\n"), regs->cpuad, strsignal(signo)); #endif /*!defined(_FEATURE_SIE)*/ display_inst( #if defined(_FEATURE_SIE) regs->sie_active ? regs->guestregs : #endif /*defined(_FEATURE_SIE)*/ regs, #if defined(_FEATURE_SIE) regs->sie_active ? regs->guestregs->ip : #endif /*defined(_FEATURE_SIE)*/ regs->ip); switch(regs->arch_mode) { #if defined(_370) case ARCH_370: s370_sync_mck_interrupt(regs); break; #endif #if defined(_390) case ARCH_390: s390_sync_mck_interrupt(regs); break; #endif #if defined(_900) case ARCH_900: z900_sync_mck_interrupt(regs); break; #endif } } else { #if defined(_FEATURE_SIE) logmsg(_("HHCCP018I CPU%4.4X: Check-Stop due to host error: %s\n"), regs->sie_active ? regs->guestregs->cpuad : regs->cpuad, strsignal(signo)); #else /*!defined(_FEATURE_SIE)*/ logmsg(_("HHCCP018I CPU%4.4X: Check-Stop due to host error: %s\n"), regs->cpuad, strsignal(signo)); #endif /*!defined(_FEATURE_SIE)*/ display_inst( #if defined(_FEATURE_SIE) regs->sie_active ? regs->guestregs : #endif /*defined(_FEATURE_SIE)*/ regs, #if defined(_FEATURE_SIE) regs->sie_active ? regs->guestregs->ip : #endif /*defined(_FEATURE_SIE)*/ regs->ip); regs->cpustate = CPUSTATE_STOPPING; regs->checkstop = 1; ON_IC_INTERRUPT(regs); /* Notify other CPU's by means of a malfuction alert if possible */ if (!try_obtain_lock(&sysblk.sigplock)) { if(!try_obtain_lock(&sysblk.intlock)) { for (i = 0; i < MAX_CPU; i++) if (i != regs->cpuad && IS_CPU_ONLINE(i)) { ON_IC_MALFALT(sysblk.regs[i]); sysblk.regs[i]->malfcpu[regs->cpuad] = 1; } release_lock(&sysblk.intlock); } release_lock(&sysblk.sigplock); } } longjmp (regs->progjmp, SIE_INTERCEPT_MCK); } #endif /*!defined(NO_SIGABEND_HANDLER)*/ #endif /*!defined(_GEN_ARCH)*/ hercules-3.07/machdep.h000644 000765 000765 00000056442 11337307610 016531 0ustar00jmaynardjmaynard000000 000000 /* MACHDEP.H (c) Copyright Greg Smith, 2001-2010 */ /* Hercules machine specific code */ // $Id: machdep.h 5634 2010-02-15 15:33:56Z rbowler $ /*-------------------------------------------------------------------*/ /* */ /* This header file contains the following functions, defined as */ /* either normal unoptimzed C code, or else as hand-tuned optimized */ /* assembler-assisted functions for the given machine architecture: */ /* */ /* */ /* Atomic COMPARE-AND-EXCHANGE functions: */ /* */ /* cmpxchg1, cmpxchg4, cmpxchg8, cmpxchg16 */ /* */ /* */ /* Atomic word/double-word FETCH/STORE functions: */ /* */ /* fetch_hw, fetch_hw_noswap, store_hw, store_hw_noswap */ /* fetch_fw, fetch_fw_noswap, store_fw, store_fw_noswap */ /* fetch_dw, fetch_dw_noswap, store_dw, store_dw_noswap */ /* */ /* 64 bit architectures would normally not need to specify */ /* any of the fetch_ or store_ macros. */ /* */ /* 32 bit architectures should specify one of the `fetch_dw' */ /* and `store_dw' macros. Little-endian machines should specify */ /* the `noswap' macros. Big-endian machines can specify either, */ /* both being the same. */ /* */ /*-------------------------------------------------------------------*/ #ifndef _HERCULES_MACHDEP_H #define _HERCULES_MACHDEP_H 1 #include "opcode.h" // (need CSWAP32, et.al macros, etc) #include "htypes.h" // (need Hercules fixed-size data types) /*------------------------------------------------------------------- * Microsoft Visual C/C++... *-------------------------------------------------------------------*/ #if defined( _MSVC_ ) // PROGRAMMING NOTE: Optimizations normally only apply for release // builds, but we support optionally enabling them for debug too, // as well as purposely DISABLING them for troubleshooting... #define OPTION_ENABLE_MSVC_OPTIMIZATIONS_FOR_DEBUG_BUILDS_TOO // #define OPTION_DISABLE_MSVC_OPTIMIZATIONS #undef GEN_MSC_ASSISTS #if defined( DEBUG) || defined( _DEBUG ) #if defined(OPTION_ENABLE_MSVC_OPTIMIZATIONS_FOR_DEBUG_BUILDS_TOO) && \ !defined(OPTION_DISABLE_MSVC_OPTIMIZATIONS) #define GEN_MSC_ASSISTS #endif #else // (presumed RELEASE build) #if !defined(OPTION_DISABLE_MSVC_OPTIMIZATIONS) #define GEN_MSC_ASSISTS #endif #endif // (debug or release) #undef MSC_X86_32BIT // any 32-bit X86 (Pentium Pro, Pentium II, Pentium III or better) #undef MSC_X86_64BIT // any 64-bit X86 (AMD64 or Intel Itanium) #undef MSC_X86_AMD64 // AMD64 only #undef MSC_X86_IA64 // Intel Itanium only #if defined( _M_IX86 ) && ( _M_IX86 >= 600 ) #define MSC_X86_32BIT #endif #if defined( _M_AMD64 ) #define MSC_X86_AMD64 #define MSC_X86_64BIT #endif #if defined( _M_IA64 ) #define MSC_X86_IA64 #define MSC_X86_64BIT #endif #if defined(GEN_MSC_ASSISTS) && (defined(MSC_X86_32BIT) || defined(MSC_X86_64BIT)) // Any X86 at all (both 32/64-bit) #pragma intrinsic ( _InterlockedCompareExchange ) #define cmpxchg1( x, y, z ) cmpxchg1_x86( x, y, z ) #define cmpxchg4( x, y, z ) cmpxchg4_x86( x, y, z ) #define cmpxchg8( x, y, z ) cmpxchg8_x86( x, y, z ) #if ( _MSC_VER < 1400 ) // PROGRAMMING NOTE: compiler versions earlier than VS8 2005 // do not have the _InterlockedCompareExchange64 intrinsic so // we use our own hand-coded inline assembler routine instead. // Also note that we can't use __fastcall here since doing so // would interfere with our register usage. static __inline BYTE cmpxchg8_x86 ( U64 *pOldVal, U64 u64NewVal, volatile void *pTarget ) { // returns 0 == success, 1 otherwise BYTE rc; U32 u32NewValHigh = u64NewVal >> 32; U32 u32NewValLow = u64NewVal & 0xffffffff; __asm { mov esi, [pOldVal] mov eax, [esi + 0] mov edx, [esi + 4] mov ebx, [u32NewValLow] mov ecx, [u32NewValHigh] mov esi, [pTarget] #ifdef OPTION_SMP lock cmpxchg8b qword ptr [esi] #else cmpxchg8b qword ptr [esi] #endif setne rc jz success mov esi, [pOldVal] mov [esi + 0], eax mov [esi + 4], edx }; success: return rc; } #else // ( _MSC_VER >= 1400 ) #pragma intrinsic ( _InterlockedCompareExchange64 ) static __inline BYTE __fastcall cmpxchg8_x86 ( U64 *old, U64 new, volatile void *ptr ) { // returns 0 == success, 1 otherwise U64 tmp = *old; *old = _InterlockedCompareExchange64( ptr, new, *old ); return ((tmp == *old) ? 0 : 1); } #endif // ( _MSC_VER >= 1400 ) static __inline BYTE __fastcall cmpxchg4_x86 ( U32 *old, U32 new, volatile void *ptr ) { // returns 0 == success, 1 otherwise U32 tmp = *old; *old = _InterlockedCompareExchange( ptr, new, *old ); return ((tmp == *old) ? 0 : 1); } // (must follow cmpxchg4 since it uses it) static __inline BYTE __fastcall cmpxchg1_x86 ( BYTE *old, BYTE new, volatile void *ptr ) { // returns 0 == success, 1 otherwise LONG_PTR off, shift; BYTE cc; U32 *ptr4, val4, old4, new4; off = (LONG_PTR)ptr & 3; shift = (3 - off) * 8; ptr4 = (U32*)(((BYTE*)ptr) - off); val4 = CSWAP32(*ptr4); old4 = CSWAP32((val4 & ~(0xff << shift)) | (*old << shift)); new4 = CSWAP32((val4 & ~(0xff << shift)) | ( new << shift)); cc = cmpxchg4( &old4, new4, ptr4 ); *old = (CSWAP32(old4) >> shift) & 0xff; return cc; } #if defined(MSC_X86_32BIT) #define fetch_dw_noswap(_p) fetch_dw_x86_noswap((_p)) // (must follow cmpxchg8 since it uses it) static __inline U64 __fastcall fetch_dw_x86_noswap ( volatile void *ptr ) { U64 value = *(U64*)ptr; cmpxchg8( &value, value, (U64*)ptr ); return value; } #define store_dw_noswap(_p, _v) store_dw_x86_noswap( (_p), (_v)) // (must follow cmpxchg8 since it uses it) static __inline void __fastcall store_dw_x86_noswap ( volatile void *ptr, U64 value ) { U64 orig = *(U64*)ptr; while ( cmpxchg8( &orig, value, (U64*)ptr ) ); } #endif /* defined(MSC_X86_32BIT) */ #endif // defined(GEN_MSC_ASSISTS) && (defined(MSC_X86_32BIT) || defined(MSC_X86_64BIT)) // ------------------------------------------------------------------ #if defined(GEN_MSC_ASSISTS) && defined(MSC_X86_IA64) // (64-bit Itanium assists only) // ZZ FIXME: we should probably use the 'cmpxchg16b' instruction here // instead if the processor supports it (CPUID instruction w/EAX function // code 1 == Feature Information --> ECX bit 13 = CMPXCHG16B available) #pragma intrinsic ( _AcquireSpinLock ) #pragma intrinsic ( _ReleaseSpinLock ) #pragma intrinsic ( _ReadWriteBarrier ) #define cmpxchg16( x1, x2, y1, y2, z ) \ cmpxchg16_x86( x1, x2, y1, y2, z ) static __inline int __fastcall cmpxchg16_x86 ( U64 *old1, U64 *old2, U64 new1, U64 new2, volatile void *ptr ) { // returns 0 == success, 1 otherwise static unsigned __int64 lock = 0; int code; _AcquireSpinLock( &lock ); _ReadWriteBarrier(); if (*old1 == *(U64*)ptr && *old2 == *((U64*)ptr + 1)) { *(U64*)ptr = new1; *((U64*)ptr + 1) = new2; code = 0; } else { *old1 = *((U64*)ptr); *old2 = *((U64*)ptr + 1); code = 1; } _ReleaseSpinLock( &lock ); return code; } #endif // defined(GEN_MSC_ASSISTS) && defined(MSC_X86_IA64) #else // !defined( _MSVC_ ) /*------------------------------------------------------------------- * GNU C or other compiler... (i.e. NON-Microsoft C/C++) *-------------------------------------------------------------------*/ #if defined(__i686__) || defined(__pentiumpro__) || \ defined(__pentium4__) || defined(__athlon__) || \ defined(__athlon) #define _ext_ia32 #endif #if defined(__amd64__) #define _ext_amd64 #endif #if defined(__powerpc__) || defined(__ppc__) || \ defined(__POWERPC__) || defined(__PPC__) || \ defined(_POWER) #define _ext_ppc #endif /*------------------------------------------------------------------- * Intel pentiumpro/i686 *-------------------------------------------------------------------*/ #if defined(_ext_ia32) #undef LOCK_PREFIX #ifdef OPTION_SMP #define LOCK_PREFIX "lock\n\t" #else #define LOCK_PREFIX "" #endif /* * If PIC is defined then ebx is used as the `thunk' reg * However cmpxchg8b requires ebx * In this case we load the value into esi and then * exchange esi and ebx before and after cmpxchg8b */ #undef BREG #undef XCHG_BREG #if defined(PIC) && !defined(__CYGWIN__) #define BREG "S" #define XCHG_BREG "xchgl %%ebx,%%esi\n\t" #else #define BREG "b" #define XCHG_BREG "" #endif #define cmpxchg1(x,y,z) cmpxchg1_i686(x,y,z) static __inline__ BYTE cmpxchg1_i686(BYTE *old, BYTE new, void *ptr) { BYTE code; __asm__ __volatile__ ( LOCK_PREFIX "cmpxchgb %b3,%4\n\t" "setnz %b0" : "=q"(code), "=a"(*old) : "1" (*old), "q" (new), "m" (*(BYTE *)ptr) : "cc" ); return code; } #define cmpxchg4(x,y,z) cmpxchg4_i686(x,y,z) static __inline__ BYTE cmpxchg4_i686(U32 *old, U32 new, void *ptr) { BYTE code; __asm__ __volatile__ ( LOCK_PREFIX "cmpxchgl %3,%4\n\t" "setnz %b0" : "=q"(code), "=a"(*old) : "1" (*old), "q" (new), "m" (*(U32 *)ptr) : "cc" ); return code; } #define cmpxchg8(x,y,z) cmpxchg8_i686(x,y,z) static __inline__ BYTE cmpxchg8_i686(U64 *old, U64 new, void *ptr) { BYTE code; __asm__ __volatile__ ( XCHG_BREG LOCK_PREFIX "cmpxchg8b %5\n\t" XCHG_BREG "setnz %b0" : "=q"(code), "=A"(*old) : "1" (*old), BREG ((unsigned long)new), "c" ((unsigned long)(new >> 32)), "m" (*(U64 *)ptr) : "cc"); return code; } #define fetch_dw_noswap(x) fetch_dw_i686_noswap(x) static __inline__ U64 fetch_dw_i686_noswap(void *ptr) { U64 value = *(U64 *)ptr; __asm__ __volatile__ ( XCHG_BREG LOCK_PREFIX "cmpxchg8b (%4)\n\t" XCHG_BREG : "=A" (value) : "0" (value), BREG ((unsigned long)value), "c" ((unsigned long)(value >> 32)), "D" (ptr)); return value; } #define store_dw_noswap(x,y) store_dw_i686_noswap(x,y) static __inline__ void store_dw_i686_noswap(void *ptr, U64 value) { __asm__ __volatile__ ( XCHG_BREG "1:\t" LOCK_PREFIX "cmpxchg8b %3\n\t" "jne 1b\n\t" XCHG_BREG : : "A" (*(U64 *)ptr), BREG ((unsigned long)value), "c" ((unsigned long)(value >> 32)), "m" (*(U64 *)ptr)); } #if defined(OPTION_MULTI_BYTE_ASSIST) && defined(__linux__) #define MULTI_BYTE_ASSIST #define MULTI_BYTE_ASSIST_IA32 #endif #endif /* defined(_ext_ia32) */ /*------------------------------------------------------------------- * AMD64 *-------------------------------------------------------------------*/ #if defined(_ext_amd64) #define cmpxchg1(x,y,z) cmpxchg1_amd64(x,y,z) static __inline__ BYTE cmpxchg1_amd64(BYTE *old, BYTE new, void *ptr) { /* returns zero on success otherwise returns 1 */ BYTE code; BYTE *ptr_data=ptr; __asm__ __volatile__ ( "lock; cmpxchgb %b2,%4\n\t" "setnz %b0\n\t" : "=q"(code), "=a"(*old) : "q"(new), "1"(*old), "m"(*ptr_data) : "cc"); return code; } #define cmpxchg4(x,y,z) cmpxchg4_amd64(x,y,z) static __inline__ BYTE cmpxchg4_amd64(U32 *old, U32 new, void *ptr) { /* returns zero on success otherwise returns 1 */ BYTE code; U32 *ptr_data=ptr; __asm__ __volatile__ ( "lock; cmpxchgl %2,%4\n\t" "setnz %b0\n\t" : "=q"(code), "=a"(*old) : "q"(new), "1"(*old), "m"(*ptr_data) : "cc"); return code; } #define cmpxchg8(x,y,z) cmpxchg8_amd64(x,y,z) static __inline__ BYTE cmpxchg8_amd64(U64 *old, U64 new, void *ptr) { /* returns zero on success otherwise returns 1 */ BYTE code; U64 *ptr_data=ptr; __asm__ __volatile__ ( "lock; cmpxchgq %2,%4\n\t" "setnz %b0\n\t" : "=q"(code), "=a"(*old) : "q"(new), "1"(*old), "m"(*ptr_data) : "cc"); return code; } #endif /* defined(_ext_amd64) */ /*------------------------------------------------------------------- * PowerPC *-------------------------------------------------------------------*/ #if defined(_ext_ppc) /* From /usr/src/linux/include/asm-ppc/system.h */ /* NOTE: IBM's VisualAge compiler likes 1: style labels but GNU's gcc compiler running on AIX does not. */ #if !defined( __GNUC__ ) // (VisualAge presumed) #define LABEL1 "1:\n" #define LABEL2 "2:\n" #define BRNCH2 "2f" #define BRNCH1 "1b" #else // (else gcc...) #define LABEL1 "loop%=:\n" #define LABEL2 "exit%=:\n" #define BRNCH2 "exit%=" #define BRNCH1 "loop%=" #endif /* NOTE: Both VisualAge *and* gcc define __64BIT__ see: http://gmplib.org/list-archives/gmp-discuss/2008-July/003339.html */ #if defined( __64BIT__ ) static __inline__ U64 __cmpxchg_u64(volatile U64 *p, U64 old, U64 new) { U64 prev; __asm__ __volatile__ ("\n" LABEL1 " ldarx %0,0,%2\n\ cmpd 0,%0,%3\n\ bne "BRNCH2"\n\ stdcx. %4,0,%2\n\ bne- "BRNCH1"\n" #ifdef OPTION_SMP " sync\n" #endif /* OPTION_SMP */ LABEL2 : "=&r" (prev), "=m" (*p) : "r" (p), "r" (old), "r" (new), "m" (*p) : "cc", "memory"); return prev; } #define cmpxchg8(x,y,z) cmpxchg8_ppc(x,y,z) static __inline__ BYTE cmpxchg8_ppc(U64 *old, U64 new, void *ptr) { /* returns zero on success otherwise returns 1 */ U64 prev = *old; return (prev != (*old = __cmpxchg_u64((U64*)ptr, prev, new))); } #endif // defined( __64BIT__ ) static __inline__ U32 __cmpxchg_u32(volatile U32 *p, U32 old, U32 new) { U32 prev; __asm__ __volatile__ ("\n" LABEL1 " lwarx %0,0,%2\n\ cmpw 0,%0,%3\n\ bne "BRNCH2"\n\ stwcx. %4,0,%2\n\ bne- "BRNCH1"\n" #ifdef OPTION_SMP " sync\n" #endif /* OPTION_SMP */ LABEL2 : "=&r" (prev), "=m" (*p) : "r" (p), "r" (old), "r" (new), "m" (*p) : "cc", "memory"); return prev; } #define cmpxchg4(x,y,z) cmpxchg4_ppc(x,y,z) static __inline__ BYTE cmpxchg4_ppc(U32 *old, U32 new, void *ptr) { /* returns zero on success otherwise returns 1 */ U32 prev = *old; return (prev != (*old = __cmpxchg_u32((U32*)ptr, prev, new))); } #define cmpxchg1(x,y,z) cmpxchg1_ppc(x,y,z) static __inline__ BYTE cmpxchg1_ppc(BYTE *old, BYTE new, void *ptr) { /* returns zero on success otherwise returns 1 */ long off, shift; BYTE cc; U32 *ptr4, val4, old4, new4; off = (long)ptr & 3; shift = (3 - off) * 8; ptr4 = ptr - off; val4 = *ptr4; old4 = (val4 & ~(0xff << shift)) | (*old << shift); new4 = (val4 & ~(0xff << shift)) | (new << shift); cc = cmpxchg4_ppc(&old4, new4, ptr4); *old = (old4 >> shift) & 0xff; return cc; } #endif /* defined(_ext_ppc) */ #endif // !defined( _MSVC_ ) /*------------------------------------------------------------------- * Define the ASSIST_ macros *-------------------------------------------------------------------*/ #if defined(cmpxchg1) #define ASSIST_CMPXCHG1 #endif #if defined(cmpxchg4) #define ASSIST_CMPXCHG4 #endif #if defined(cmpxchg8) #define ASSIST_CMPXCHG8 #endif #if defined(cmpxchg16) #define ASSIST_CMPXCHG16 #endif #if defined(fetch_dw) || defined(fetch_dw_noswap) #define ASSIST_FETCH_DW #endif #if defined(store_dw) || defined(store_dw_noswap) #define ASSIST_STORE_DW #endif /*------------------------------------------------------------------- * Decide if strict alignment is required *-------------------------------------------------------------------*/ #if !defined(OPTION_STRICT_ALIGNMENT) && !defined(OPTION_NO_STRICT_ALIGNMENT) #if !defined(_MSVC_) && !defined(_ext_ia32) && !defined(_ext_amd64) \ && !defined(_ext_ppc) #define OPTION_STRICT_ALIGNMENT #endif #endif /*------------------------------------------------------------------- * fetch_hw_noswap and fetch_hw *-------------------------------------------------------------------*/ #if !defined(fetch_hw_noswap) #if defined(fetch_hw) #define fetch_hw_noswap(_p) CSWAP16(fetch_hw((_p))) #else #if !defined(OPTION_STRICT_ALIGNMENT) static __inline__ U16 fetch_hw_noswap(void *ptr) { return *(U16 *)ptr; } #else static __inline__ U16 fetch_hw_noswap(void *ptr) { U16 value; memcpy(&value, (BYTE *)ptr, 2); return value; } #endif #endif #endif #if !defined(fetch_hw) #define fetch_hw(_p) CSWAP16(fetch_hw_noswap((_p))) #endif /*------------------------------------------------------------------- * store_hw_noswap and store_hw *-------------------------------------------------------------------*/ #if !defined(store_hw_noswap) #if defined(store_hw) #define store_hw_noswap(_p, _v) store_hw((_p), CSWAP16(_v)) #else #if !defined(OPTION_STRICT_ALIGNMENT) static __inline__ void store_hw_noswap(void *ptr, U16 value) { *(U16 *)ptr = value; } #else static __inline__ void store_hw_noswap(void *ptr, U16 value) { memcpy((BYTE *)ptr, (BYTE *)&value, 2); } #endif #endif #endif #if !defined(store_hw) #define store_hw(_p, _v) store_hw_noswap((_p), CSWAP16((_v))) #endif /*------------------------------------------------------------------- * fetch_fw_noswap and fetch_fw *-------------------------------------------------------------------*/ #if !defined(fetch_fw_noswap) #if defined(fetch_fw) #define fetch_fw_noswap(_p) CSWAP32(fetch_fw((_p))) #else #if !defined(OPTION_STRICT_ALIGNMENT) static __inline__ U32 fetch_fw_noswap(const void *ptr) { return *(U32 *)ptr; } #else static __inline__ U32 fetch_fw_noswap(const void *ptr) { U32 value; memcpy(&value, (BYTE *)ptr, 4); return value; } #endif #endif #endif #if !defined(fetch_fw) #define fetch_fw(_p) CSWAP32(fetch_fw_noswap((_p))) #endif /*------------------------------------------------------------------- * store_fw_noswap and store_fw *-------------------------------------------------------------------*/ #if !defined(store_fw_noswap) #if defined(store_fw) #define store_fw_noswap(_p, _v) store_fw((_p), CSWAP32(_v)) #else #if !defined(OPTION_STRICT_ALIGNMENT) static __inline__ void store_fw_noswap(void *ptr, U32 value) { *(U32 *)ptr = value; } #else static __inline__ void store_fw_noswap(void *ptr, U32 value) { memcpy((BYTE *)ptr, (BYTE *)&value, 4); } #endif #endif #endif #if !defined(store_fw) #define store_fw(_p, _v) store_fw_noswap((_p), CSWAP32((_v))) #endif /*------------------------------------------------------------------- * fetch_dw_noswap and fetch_dw *-------------------------------------------------------------------*/ #if !defined(fetch_dw_noswap) #if defined(fetch_dw) #define fetch_dw_noswap(_p) CSWAP64(fetch_dw((_p))) #else #if !defined(OPTION_STRICT_ALIGNMENT) static __inline__ U64 fetch_dw_noswap(void *ptr) { return *(U64 *)ptr; } #else static __inline__ U64 fetch_dw_noswap(void *ptr) { U64 value; memcpy(&value, (BYTE *)ptr, 8); return value; } #endif #endif #endif #if !defined(fetch_dw) #define fetch_dw(_p) CSWAP64(fetch_dw_noswap((_p))) #endif /*------------------------------------------------------------------- * store_dw_noswap and store_dw *-------------------------------------------------------------------*/ #if !defined(store_dw_noswap) #if defined(store_dw) #define store_dw_noswap(_p, _v) store_dw((_p), CSWAP64(_v)) #else #if !defined(OPTION_STRICT_ALIGNMENT) static __inline__ void store_dw_noswap(void *ptr, U64 value) { *(U64 *)ptr = value; } #else static __inline__ void store_dw_noswap(void *ptr, U64 value) { memcpy((BYTE *)ptr, (BYTE *)&value, 8); } #endif #endif #endif #if !defined(store_dw) #define store_dw(_p, _v) store_dw_noswap((_p), CSWAP64((_v))) #endif /*------------------------------------------------------------------- * cmpxchg1 *-------------------------------------------------------------------*/ #ifndef cmpxchg1 static __inline__ BYTE cmpxchg1(BYTE *old, BYTE new, volatile void *ptr) { BYTE code; if (*old == *(BYTE *)ptr) { *(BYTE *)ptr = new; code = 0; } else { *old = *(BYTE *)ptr; code = 1; } return code; } #endif /*------------------------------------------------------------------- * cmpxchg4 *-------------------------------------------------------------------*/ #ifndef cmpxchg4 static __inline__ BYTE cmpxchg4(U32 *old, U32 new, volatile void *ptr) { BYTE code; if (*old == *(U32 *)ptr) { *(U32 *)ptr = new; code = 0; } else { *old = *(U32 *)ptr; code = 1; } return code; } #endif /*------------------------------------------------------------------- * cmpxchg8 *-------------------------------------------------------------------*/ #ifndef cmpxchg8 static __inline__ BYTE cmpxchg8(U64 *old, U64 new, volatile void *ptr) { BYTE code; if (*old == *(U64 *)ptr) { *(U64 *)ptr = new; code = 0; } else { *old = *(U64 *)ptr; code = 1; } return code; } #endif /*------------------------------------------------------------------- * cmpxchg16 *-------------------------------------------------------------------*/ #ifndef cmpxchg16 static __inline__ int cmpxchg16(U64 *old1, U64 *old2, U64 new1, U64 new2, volatile void *ptr) { int code; if (*old1 == *(U64 *)ptr && *old2 == *((U64 *)ptr + 1)) { *(U64 *)ptr = new1; *((U64 *)ptr + 1) = new2; code = 0; } else { *old1 = *((U64 *)ptr); *old2 = *((U64 *)ptr + 1); code = 1; } return code; } #endif #ifndef BIT #define BIT(nr) (1<<(nr)) #endif #endif /* _HERCULES_MACHDEP_H */ hercules-3.07/makefile-dllmod.msvc000644 000765 000765 00000014636 11335365456 020710 0ustar00jmaynardjmaynard000000 000000 # *************************************************************************** # MAKEFILE-DLLMOD.MSVC (c) Copyright Roger Bowler, 2005-2007 # Build Hercules for Win32 using MSVC and nmake (DLL version with loadable modules) # # $Id: makefile-dllmod.msvc 5617 2010-02-09 00:00:41Z fish $ # # DD/MM/YY Description....................................................... # 17/02/05 Created by - Roger Bowler # 01/03/05 Place debug/retail builds into separate directories - Fish # 06/03/05 DLL version - Ivan Warren # 07/03/05 Precompiled headers for faster compilation - Ivan Warren # 08/03/05 Added /QIfist to cflags - JJ # 08/03/05 Modified to build DLL version in its own subdirectories separate # from the static build version, and to place the generated .lib # and .exp files into the object module sub-directory instead of # the executable sub-directory - R.Bowler # 08/03/05 Modified to do "batch build" for faster builds - Fish # 08/03/05 Fixed optimization flags - Fish # 08/03/05 Added support for DEBUG builds - Fish # 08/03/05 Use XCOPY instead of COPY - Fish # 10/03/05 Fixed creation of directories - R.Bowler # 12/03/05 first attempt at loadable modules - jj # 21/03/05 Support for new VS 8.0 compiler (version 14.00) - Fish # 04/04/05 VS8: _CRT_SECURE_NO_DEPRECATE - Fish # 15/04/05 BZIP2 support (libbz2.dll) - Fish # 17/04/05 Resource file support (with version numbering) - Fish # 18/04/05 SCSI tape: w32stape.c - Fish # 22/04/05 'ftol2' moved to w32util.c - Fish # 01/05/05 Move "MAX_CPU_ENGINES" to here instead of 'hercwind.h' - Fish # 03/05/05 Remove '/map 'options and replace with /Zi and /DEBUG options # instead in order to produce .PDB files so we can more easily # debug/analyze "crash dumps" should we ever need to - Fish # 06/05/05 Eliminate duplicate link commands like makefile.dll - Roger Bowler # 06/05/05 Place .pdb files in separate directory - Roger Bowler # 06/05/05 Can we agree on these o/p directory names?? - Fish # 07/05/05 /MANIFEST:NO in wrong spot (is only for VS8.0) - Fish # 02/07/05 VS8: _CRT_NONSTDC_NO_DEPRECATE to prevent compiler warning: # "C4996 'function': was declared deprecated" # 02/07/05 VS8: Add pre-compiled header object file (build_pch.obj) # to both 'linkexe' and 'linkdll' to prevent linker error: # "LNK2011 "precompiled object not linked in; image may not run" # 02/07/05 VS8: _USE_32BIT_TIME_T to prevent problems with presumed # assumed size of timeval tv.tv_sec and time(time_t) - Fish # 31/07/05 Change default release (non-DEBUG) build optimization options # to simply /O2 (maximize speed), and remove the /GF (Eliminate # Duplicate Strings) option (which is the default for /O2 anyway) # and the /GS (Buffer Security Check) option (which seems to slow # things down WAY too much). # 02/08/05 Add optional compilation of cryptographic modules (nmake crypto) # 14/11/05 Add /map option back again; make similar to dll version. - Fish # 22/11/05 Crypto module now included standard - Ivan # 24/11/05 Rebase all DLLs at 0x400000 (same as executables default) - Fish # 29/11/05 Create assembly listings if 'ASSEMBLY_LISTINGS' defined - Fish # 01/12/05 Fix for VS 8.0 "manifest" files issue - Volker Bandke # 02/12/05 Added 'conspawn' utility to build - Fish # 30/03/06 (just changed some tabs to spaces) - Fish # 04/05/06 clean: skip 'del' (delete) if files don't exist - Fish # 04/09/06 PCRE (Regular Expressions) support (http://www.pcre.org) - Fish # 06/09/06 HAO (Hercules Automatic Operator) support - Fish # 06/12/06 Add decNumber for DFP (Decimal Floating Point) support - Roger Bowler # 26/12/06 Broke sections out into separate !INCLUDE-able files for easier # maintenance and use by externally built dynamic modules. - Fish # 30/01/10 Dynamic module builds now use same makefile as Hercules. - Fish # # $Log$ # Revision 1.30 2008/05/06 19:56:29 rbowler # Default BZIP2_DIR to winbuild/bzip2 if it exists # # Revision 1.29 2006/12/28 19:03:38 fish # New makefile restructuring # # Revision 1.28 2006/12/08 09:43:29 jj # Add CVS message log # # *************************************************************************** INCDIR = msvc.makefile.includes # --------------------------------------------------------------------- !INCLUDE $(INCDIR)\CONFIG.msvc !INCLUDE $(INCDIR)\VERSION.msvc !INCLUDE $(INCDIR)\OUTPUT_DIRS.msvc !INCLUDE $(INCDIR)\MODULES.msvc !INCLUDE $(INCDIR)\OBJ_CODE.msvc !INCLUDE $(INCDIR)\ZLIB_DIR.msvc !INCLUDE $(INCDIR)\BZIP2_DIR.msvc !INCLUDE $(INCDIR)\PCRE_DIR.msvc # --------------------------------------------------------------------- ################################################### # NOTE! must set the 'NODEBUG' variable properly # BEFORE calling win32.mak since it uses it. ################################################### # --------------------------------------------------------------------- !INCLUDE # --------------------------------------------------------------------- ################################################### # NOTE! must set our prefered 'cdebug' value(s) # AFTER calling win32.mak since it sets it. ################################################### # --------------------------------------------------------------------- !INCLUDE $(INCDIR)\DEBUG_RETAIL.msvc !INCLUDE $(INCDIR)\ZLIB_FLAGS.msvc !INCLUDE $(INCDIR)\BZIP2_FLAGS.msvc !INCLUDE $(INCDIR)\PCRE_FLAGS.msvc !INCLUDE $(INCDIR)\HERC_FLAGS.msvc # --------------------------------------------------------------------- !IFDEF DYNDIR !INCLUDE $(DYNDIR)$(DYNMOD).msvc MODULES = $(MODULES) $(X)$(DYNMOD).dll rcflags = $(rcflags) -D TARGETFILENAME=\"$(DYNMOD).dll\" -D MAX_CPU_ENGINES_STR=\"$(MAX_CPU_ENGINES)\" !ENDIF # --------------------------------------------------------------------- !INCLUDE $(INCDIR)\PRIM_RULES.msvc !INCLUDE $(INCDIR)\OUTDIR_RULES.msvc !INCLUDE $(INCDIR)\MOD_RULES1.msvc !INCLUDE $(INCDIR)\MOD_RULES2.msvc !INCLUDE $(INCDIR)\ZLIB_RULES.msvc !INCLUDE $(INCDIR)\BZIP2_RULES.msvc !INCLUDE $(INCDIR)\PCRE_RULES.msvc # --------------------------------------------------------------------- !IFDEF DYNDIR $(O)$(DYNMOD).res: $(DYNDIR)$(DYNMOD).rc $(rc) $(rcflags) $(rcvars) -fo $(O)$(DYNMOD).res $(DYNDIR)$(DYNMOD).rc $(X)$(DYNMOD).dll: $(O)$(DYNMOD).res $(DYNOBJ) $(O)hengine.lib $(O)hutil.lib $(O)hsys.lib $(linkdll) {$(DYNDIR)}.c{$(OBJDIR)}.obj:: $(cc) $(cdebug) $(cflags) /Fp"$(OBJDIR)\\build_pch.pch" /Yu"hstdinc.h" $(cvarsdll) /Fo"$(OBJDIR)\\" /Fd"$(OBJDIR)\\" $< !ENDIF hercules-3.07/Makefile.am000644 000765 000765 00000062302 11335365456 017015 0ustar00jmaynardjmaynard000000 000000 # *************************************************************************** # Makefile for Hercules S/370, ESA/390 and z/Architecture emulator # Process this file with 'automake' to produce Makefile.in # # $Id: Makefile.am 5617 2010-02-09 00:00:41Z fish $ # # $Log$ # Revision 1.187 2009/01/18 00:52:19 jmaynard # Fix Gentoo reported bug: unable to do multithreaded "make install" reliably # if --enable-setuid-hercifc is specified. # # Revision 1.186 2008/12/29 11:03:10 jj # Move HMC disk I/O functions to scedasd.c # # Revision 1.185 2008/12/04 17:39:02 rbowler # Add ability to configure group name with --enable-setuid-hercifc=name # # Revision 1.184 2008/12/01 16:19:49 jj # Check for licensed operating systems without impairing architectural # compliance of IFL's # # Revision 1.183 2008/05/22 19:25:58 fish # Flex FakeTape support # # Revision 1.182 2008/03/25 11:41:31 fish # SCSI TAPE MODS part 1: groundwork: non-functional changes: # rename some functions, comments, general restructuring, etc. # New source modules awstape.c, omatape.c, hettape.c and # tapeccws.c added, but not yet used (all will be used in a future # commit though when tapedev.c code is eventually split) # # Revision 1.181 2008/03/02 22:50:35 rbowler # Restore tabs corrupted by previous modification # # Revision 1.180 2008/03/01 14:19:29 rbowler # Add new module general3.c for general-instructions-extension facility # # Revision 1.179 2008/02/19 11:49:18 ivan # - Move setting of CPU priority after spwaning timer thread # - Added support for Posix 1003.1e capabilities # # Revision 1.178 2007/06/02 13:46:41 rbowler # PFPO framework # # Revision 1.177 2006/12/30 21:13:37 rbowler # Backout rev 1.176 # # Revision 1.175 2006/12/30 16:54:07 rbowler # Reinstate missing changelog entries # # Revision 1.174 2006/12/30 15:37:01 jmaynard # Removed a coupple of stray ^Ms. # # Revision 1.173 2006/12/30 01:20:09 fish # Add new MSVC makefile includes to distribution # # Revision 1.172 2006/12/18 13:35:51 rbowler # Add hstdint.h to make dist # # Revision 1.171 2006/12/13 17:16:30 rbowler # Make libherc depend on libdecNumber # # Revision 1.170 2006/12/11 16:56:59 rbowler # Update Makefile.am to search decNumber for include files # # Revision 1.169 2006/12/09 01:05:59 ivan # Remove makefile-dll.msvc from Makefile.am dist list since it has been removed from the repository # # Revision 1.168 2006/12/08 09:43:16 jj # Add CVS message log # # DD/MM/YY Description....................................................... # 06/09/06 Change History added - Fish # 06/09/06 HAO (Hercules Automatic Operator) support - Fish # *************************************************************************** AUTOMAKE_OPTIONS = foreign 1.5 ACLOCAL_AMFLAGS = -I m4 lns=@LN_S@ SUBDIRS = decNumber m4 po util html man . crypto LDADD = @LTLIBICONV@ @LTLIBINTL@ @LIBS@ AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/decNumber if BUILD_HERCIFC HERCIFC = hercifc else HERCIFC= endif if BUILD_SHARED HERCLIN=herclin else HERCLIN= endif fthreads_SRC = fthreads.c fishio_SRC = w32chan.c fishhang_SRC = fishhang.c if BUILD_FTHREADS FTHREADS = $(fthreads_SRC) FISHIO = $(fishio_SRC) if BUILD_FISHHANG FISHHANG = $(fishhang_SRC) else FISHHANG = endif else FTHREADS = FISHHANG = FISHIO = endif # We need to still include the source for the dynamic modules # in with the distribution regardless of whether or not the dyanmic # modules themselves are to be built so if dynamic load not possible, # then we need to include the source on the EXTRA_hercules_SOURCES # statement so even though they won't/don't actually get built, they # still nonetheless get included into distribution tarball. This is # *similar* to (bit not identical to) the way the fthreads sources # are handled. With the fthreads sources though, they can at least always # be built (even though they may not always generate any actual code # whenever they do) whereas the dynamic module source CANNOT (MUST not) # even be *attempted* to be "built" if support for building dynamic modules # doesn't even exist on the system doing the building. dynamic_SRC = dyngui.c \ dyninst.c \ hdteq.c dyndev_SRC = commadpt.c \ comm3705.c \ console.c \ cardpch.c \ cardrdr.c \ sockdev.c \ printer.c \ tapedev.c \ tapeccws.c \ sllib.c \ hetlib.c \ awstape.c \ faketape.c \ hettape.c \ omatape.c \ scsitape.c \ w32stape.c \ ctc_lcs.c \ ctc_ctci.c \ ctcadpt.c \ w32ctca.c \ hchan.c \ tuntap.c \ qeth.c \ con1052c.c # -module : create a dlopen'able module # -no-undefined : required on all platform that do not allow shared modules # to have undefined symbols # $(LDADD) : Misc Linker flags set by autoconf # -export-dynamic : so dlsym works (to be verified - not sure it is necessary) # -avoid-version : needed.. Otherwise libtool gives crazy names to Windows # DLLs # if BUILD_SHARED XSTATIC = else XSTATIC = -static endif if OPTION_DYNAMIC_LOAD DYNSRC = LTDL = ltdl.c DYNMOD_LD_FLAGS = -module \ -no-undefined \ $(XSTATIC) \ -export-dynamic \ -avoid-version DYNMOD_LD_ADD = libherc.la \ libhercs.la \ libhercu.la \ $(LDADD) LIB_LD_FLAGS = -export-dynamic \ $(XSTATIC) \ -no-undefined \ -avoid-version else DYNSRC = $(dyndev_SRC) LTDL = DYNMOD_LD_FLAGS = DYNMOD_LD_ADD = LIB_LD_FLAGS = $(XSTATIC) \ -no-undefined \ -avoid-version endif # # List of Libtool shared libraries & loadable modules # HERCLIBS = HERCLIBS2 = libhercs.la \ libhercu.la \ libherct.la \ libhercd.la \ libherc.la HERCMODS = dyngui.la \ dyninst.la \ hdteq.la \ hdt1403.la \ hdt2703.la \ hdt3705.la \ hdt3088.la \ hdt3270.la \ hdt3420.la \ hdt3505.la \ hdt2880.la \ hdt3525.la \ hdtqeth.la \ hdt1052c.la if OPTION_DYNAMIC_LOAD modexec_LTLIBRARIES = $(HERCMODS) endif noinst_LTLIBRARIES = $(HERCLIBS) lib_LTLIBRARIES = $(HERCLIBS2) # The following causes the dyanmic modules to not even get built # unless support for building dynamic modules exists on the build system bin_PROGRAMS = hercules \ dasdinit dasdisup dasdload dasdconv dasdls dasdcat dasdpdsu dasdseq \ tapecopy tapemap tapesplt \ cckdcdsk cckdcomp cckddiag cckdswap \ dasdcopy \ hetget hetinit hetmap hetupd \ dmap2hrc \ $(HERCIFC) \ $(HERCLIN) EXTRA_PROGRAMS = hercifc if OPTION_DYNAMIC_LOAD # # For each module: # # ModuleName_la_SOURCES = # ModuleName_la_LDFLAGS = $(DYNMOD_LD_FLAGS) (see above) # ModuleName_la_LIBADD = libherc.la (the Core Hercules Shared Library) # ModuleName_la_DEPENDENCIES = libherc.la (may not be necessary) # dyngui_la_SOURCES = dyngui.c dyngui_la_LDFLAGS = $(DYNMOD_LD_FLAGS) dyngui_la_LIBADD = $(DYNMOD_LD_ADD) dyninst_la_SOURCES = dyninst.c dyninst_la_LDFLAGS = $(DYNMOD_LD_FLAGS) dyninst_la_LIBADD = $(DYNMOD_LD_ADD) hdteq_la_SOURCES = hdteq.c hdteq_la_LDFLAGS = $(DYNMOD_LD_FLAGS) hdteq_la_LIBADD = $(DYNMOD_LD_ADD) hdt1403_la_SOURCES = printer.c sockdev.c hdt1403_la_LDFLAGS = $(DYNMOD_LD_FLAGS) hdt1403_la_LIBADD = $(DYNMOD_LD_ADD) hdt2880_la_SOURCES = hchan.c hdt2880_la_LDFLAGS = $(DYNMOD_LD_FLAGS) hdt2880_la_LIBADD = $(DYNMOD_LD_ADD) hdt2703_la_SOURCES = commadpt.c hdt2703_la_LDFLAGS = $(DYNMOD_LD_FLAGS) hdt2703_la_LIBADD = $(DYNMOD_LD_ADD) hdt3705_la_SOURCES = comm3705.c hdt3705_la_LDFLAGS = $(DYNMOD_LD_FLAGS) hdt3705_la_LIBADD = $(DYNMOD_LD_ADD) hdt3088_la_SOURCES = ctc_lcs.c ctc_ctci.c ctcadpt.c w32ctca.c tuntap.c hdt3088_la_LDFLAGS = $(DYNMOD_LD_FLAGS) hdt3088_la_LIBADD = $(DYNMOD_LD_ADD) hdt3270_la_SOURCES = console.c hdt3270_la_LDFLAGS = $(DYNMOD_LD_FLAGS) hdt3270_la_LIBADD = $(DYNMOD_LD_ADD) hdt3420_la_SOURCES = tapedev.c tapeccws.c awstape.c faketape.c hettape.c omatape.c scsitape.c w32stape.c hdt3420_la_LDFLAGS = $(DYNMOD_LD_FLAGS) hdt3420_la_LIBADD = $(DYNMOD_LD_ADD) libherct.la hdt3505_la_SOURCES = cardrdr.c sockdev.c hdt3505_la_LDFLAGS = $(DYNMOD_LD_FLAGS) hdt3505_la_LIBADD = $(DYNMOD_LD_ADD) hdt3525_la_SOURCES = cardpch.c hdt3525_la_LDFLAGS = $(DYNMOD_LD_FLAGS) hdt3525_la_LIBADD = $(DYNMOD_LD_ADD) hdtqeth_la_SOURCES = qeth.c hdtqeth_la_LDFLAGS = $(DYNMOD_LD_FLAGS) hdtqeth_la_LIBADD = $(DYNMOD_LD_ADD) hdt1052c_la_SOURCES = con1052c.c hdt1052c_la_LDFLAGS = $(DYNMOD_LD_FLAGS) hdt1052c_la_LIBADD = $(DYNMOD_LD_ADD) endif # # Common data areas (shared) library # libhercs_la_SOURCES = hsys.c libhercs_la_LDFLAGS = $(LIB_LD_FLAGS) libhercs_la_LIBADD = $(LDADD) # # Tape utility subroutines (shared) library # libherct_la_SOURCES = sllib.c \ hetlib.c libherct_la_LDFLAGS = $(LIB_LD_FLAGS) libherct_la_LIBADD = $(LDADD) libhercs.la libhercu.la # # DASD utility subroutines (shared) library # libhercd_la_SOURCES = ckddasd.c \ fbadasd.c \ cckddasd.c \ cckdutil.c \ dasdtab.c \ cache.c \ dasdutil.c \ shared.c libhercd_la_LDFLAGS = $(LIB_LD_FLAGS) libhercd_la_LIBADD = $(LDADD) libhercs.la libhercu.la # ## Pure Utility functions # libhercu_la_SOURCES = version.c \ hscutl.c \ hscutl2.c \ codepage.c \ logger.c \ logmsg.c \ hdl.c \ hostinfo.c \ hsocket.c \ memrchr.c \ parser.c \ pttrace.c \ $(FTHREADS) \ $(FISHHANG) \ $(LTDL) libhercu_la_LDFLAGS = $(LIB_LD_FLAGS) libhercu_la_LIBADD = $(LDADD) libhercs.la # # Core Hercules (shared) library # libherc_la_SOURCES = hconsole.c \ w32util.c \ strsignal.c \ impl.c \ config.c \ bldcfg.c \ panel.c \ history.c \ fillfnam.c \ ipl.c \ assist.c \ dat.c \ stack.c \ cpu.c \ vstore.c \ general1.c \ general2.c \ general3.c \ pfpo.c \ plo.c \ control.c \ crypto.c \ io.c \ decimal.c \ service.c \ scedasd.c \ losc.c \ chsc.c \ opcode.c \ diagnose.c \ diagmssf.c \ vm.c \ vmd250.c \ channel.c \ external.c \ float.c \ trace.c \ machchk.c \ vector.c \ xstore.c \ cmpsc.c \ sie.c \ qdio.c \ clock.c \ timer.c \ esame.c \ ieee.c \ dfp.c \ machdep.h \ httpserv.c \ cgibin.c \ loadparm.c \ hsccmd.c \ cmdtab.c \ hao.c \ hscmisc.c \ sr.c \ $(FISHIO) \ $(DYNSRC) \ ecpsvm.c EXTRA_libherc_la_SOURCES = $(fthreads_SRC) \ $(fishhang_SRC) \ $(fishio_SRC) \ memrchr.c \ $(dynamic_SRC) \ $(extra_SRC) \ $(dyndev_SRC) \ ltdl.c libherc_la_LDFLAGS = $(LIB_LD_FLAGS) libherc_la_LIBADD = libhercs.la \ libhercu.la \ libherct.la \ libhercd.la \ decNumber/libdecNumber.la \ $(LDADD) # # THIS is the hercules executable. # hdlmain.c is requires so that dlopen(self) retrieves # the 'main' hdl symbols # if OPTION_DYNAMIC_LOAD if BUILD_SHARED HLDFLAGS = -dlopen self HDEPS = else HLDFLAGS = -dlopen self \ -dlopen dyngui.la \ -dlopen dyninst.la \ -dlopen hdteq.la \ -dlopen hdt1403.la \ -dlopen hdt3420.la \ -dlopen hdt2703.la \ -dlopen hdt3705.la \ -dlopen hdt3088.la \ -dlopen hdt3270.la \ -dlopen hdt3505.la \ -dlopen hdt3525.la \ -dlopen hdtqeth.la \ -dlopen hdt1052c.la HDEPS = dyngui.la \ dyninst.la \ hdteq.la \ hdt1403.la \ hdt3420.la \ hdt2703.la \ hdt3705.la \ hdt3088.la \ hdt3270.la \ hdt3505.la \ hdt3525.la \ hdtqeth.la \ hdt1052c.la \ libherc.la \ libherct.la \ libhercd.la endif else HLDFLAGS = HDEPS = endif hercules_SOURCES = bootstrap.c \ hdlmain.c hercules_LDADD = libherc.la libhercs.la $(LDADD) hercules_LDFLAGS = $(HLDFLAGS) hercules_DEPENDENCIES = libherc.la libhercs.la $(HDEPS) if BUILD_SHARED herclin_SOURCES = herclin.c hdlmain.c herclin_LDADD = libherc.la libhercs.la $(LDADD) herclin_LDFLAGS = $(HLDFLAGS) herclin_DEPENDENCIES = libherc.la libhercs.la $(HDEPS) endif # # side binaries # tools_LD_FLAGS = tools_ADDLIBS = $(HERCLIBS2) $(LDADD) if BUILD_HERCIFC hercifc_SOURCES = hercifc.c hercifc_LDADD = $(tools_ADDLIBS) hercifc_LDFLAGS = $(tools_LD_FLAGS) endif dasdinit_SOURCES = dasdinit.c dasdinit_LDADD = $(tools_ADDLIBS) dasdinit_LDFLAGS = $(tools_LD_FLAGS) dasdisup_SOURCES = dasdisup.c dasdisup_LDADD = $(tools_ADDLIBS) dasdisup_LDFLAGS = $(tools_LD_FLAGS) dasdload_SOURCES = dasdload.c dasdload_LDADD = $(tools_ADDLIBS) dasdload_LDFLAGS = $(tools_LD_FLAGS) dasdconv_SOURCES = dasdconv.c dasdconv_LDADD = $(tools_ADDLIBS) dasdconv_LDFLAGS = $(tools_LD_FLAGS) dasdls_SOURCES = dasdls.c dasdls_LDADD = $(tools_ADDLIBS) dasdls_LDFLAGS = $(tools_LD_FLAGS) dasdcat_SOURCES = dasdcat.c dasdcat_LDADD = $(tools_ADDLIBS) dasdcat_LDFLAGS = $(tools_LD_FLAGS) dasdpdsu_SOURCES = dasdpdsu.c dasdpdsu_LDADD = $(tools_ADDLIBS) dasdpdsu_LDFLAGS = $(tools_LD_FLAGS) dasdseq_SOURCES = dasdseq.c dasdseq_LDADD = $(tools_ADDLIBS) dasdseq_LDFLAGS = $(tools_LD_FLAGS) tapecopy_SOURCES = tapecopy.c tapecopy_LDADD = $(tools_ADDLIBS) tapecopy_LDFLAGS = $(tools_LD_FLAGS) tapemap_SOURCES = tapemap.c tapemap_LDADD = $(tools_ADDLIBS) tapemap_LDFLAGS = $(tools_LD_FLAGS) tapesplt_SOURCES = tapesplt.c tapesplt_LDADD = $(tools_ADDLIBS) tapesplt_LDFLAGS = $(tools_LD_FLAGS) cckdcdsk_SOURCES = cckdcdsk.c cckdcdsk_LDADD = $(tools_ADDLIBS) cckdcdsk_LDFLAGS = $(tools_LD_FLAGS) cckdcomp_SOURCES = cckdcomp.c cckdcomp_LDADD = $(tools_ADDLIBS) cckdcomp_LDFLAGS = $(tools_LD_FLAGS) cckddiag_SOURCES = cckddiag.c cckddiag_LDADD = $(tools_ADDLIBS) cckddiag_LDFLAGS = $(tools_LD_FLAGS) dasdcopy_SOURCES = dasdcopy.c dasdcopy_LDADD = $(tools_ADDLIBS) dasdcopy_LDFLAGS = $(tools_LD_FLAGS) cckdswap_SOURCES = cckdswap.c cckdswap_LDADD = $(tools_ADDLIBS) cckdswap_LDFLAGS = $(tools_LD_FLAGS) hetget_SOURCES = hetget.c hetget_LDADD = $(tools_ADDLIBS) hetget_LDFLAGS = $(tools_LD_FLAGS) hetinit_SOURCES = hetinit.c hetinit_LDADD = $(tools_ADDLIBS) hetinit_LDFLAGS = $(tools_LD_FLAGS) hetmap_SOURCES = hetmap.c hetmap_LDADD = $(tools_ADDLIBS) hetmap_LDFLAGS = $(tools_LD_FLAGS) hetupd_SOURCES = hetupd.c hetupd_LDADD = $(tools_ADDLIBS) hetupd_LDFLAGS = $(tools_LD_FLAGS) dmap2hrc_SOURCES = dmap2hrc.c dmap2hrc_LDADD = $(tools_ADDLIBS) dmap2hrc_LDFLAGS = $(tools_LD_FLAGS) # # files that are not 'built' per-se # # # Also contains some WIN32 only source files # EXTRA_DIST = autoconf/config.rpath \ autoconf/mkinstalldirs \ COPYRIGHT \ hercules.cnf \ cckdfix.c \ README.COMMADPT \ README.CVS \ README.DYNMOD \ README.ECPSVM \ README.HAO \ README.HDL \ README.ISSUES \ README.MINGW \ README.NETWORKING \ README.OSX \ README.TAPE \ README.HERCLOGO \ CHANGES \ RELEASE.NOTES \ README.MSVC \ README.SUN \ _TODO.txt \ makefile.msvc \ makefile-dllmod.msvc \ msvc.makefile.includes/BZIP2_DIR.msvc \ msvc.makefile.includes/BZIP2_FLAGS.msvc \ msvc.makefile.includes/BZIP2_RULES.msvc \ msvc.makefile.includes/CONFIG.msvc \ msvc.makefile.includes/DEBUG_RETAIL.msvc \ msvc.makefile.includes/HERC_FLAGS.msvc \ msvc.makefile.includes/MOD_RULES1.msvc \ msvc.makefile.includes/MOD_RULES2.msvc \ msvc.makefile.includes/MODULES.msvc \ msvc.makefile.includes/OBJ_CODE.msvc \ msvc.makefile.includes/OUTDIR_RULES.msvc \ msvc.makefile.includes/OUTPUT_DIRS.msvc \ msvc.makefile.includes/PCRE_DIR.msvc \ msvc.makefile.includes/PCRE_FLAGS.msvc \ msvc.makefile.includes/PCRE_RULES.msvc \ msvc.makefile.includes/PRIM_RULES.msvc \ msvc.makefile.includes/VERSION.msvc \ msvc.makefile.includes/ZLIB_DIR.msvc \ msvc.makefile.includes/ZLIB_FLAGS.msvc \ msvc.makefile.includes/ZLIB_RULES.msvc \ makefile.bat \ dynmake.bat \ Hercules.dsp \ Hercules.dsw \ Hercules.vcproj \ Hercules.sln \ hercver.rc \ build_pch.c \ conspawn.c \ getopt.c \ herclogo.txt \ hercules.ico # # Source Header files. No 'build' for those # noinst_HEADERS = fishhang.h \ hostinfo.h \ cpuint.h \ feat370.h \ feat390.h \ feat900.h \ featall.h \ featchk.h \ feature.h \ esa390.h \ opcode.h \ clock.h \ hercules.h \ inline.h \ dat.h \ vstore.h \ hbyteswp.h \ dasdblks.h \ hetlib.h \ version.h \ parser.h \ dasdtab.h \ sllib.h \ htypes.h \ fthreads.h \ w32chan.h \ w32ctca.h \ tt32api.h \ linklist.h \ ieee-w32.h \ httpmisc.h \ devtype.h \ codepage.h \ ctcadpt.h \ hercifc.h \ tuntap.h \ tapedev.h \ scsitape.h \ logger.h \ commadpt.h \ comm3705.h \ cache.h \ ecpsvm.h \ memrchr.h \ shared.h \ hscutl.h \ cmdtab.h \ hdl.h \ crypto.h \ sockdev.h \ ltdl.h \ herc_getopt.h \ service.h \ chsc.h \ pttrace.h \ history.h \ sr.h \ hchan.h \ fillfnam.h \ hthreads.h \ hostopts.h \ w32util.h \ hconsts.h \ hmacros.h \ hstructs.h \ hexterns.h \ hconsole.h \ hextapi.h \ hstdinc.h \ hstdint.h \ hsocket.h \ w32stape.h \ w32dl.h \ hercwind.h \ getopt.h \ w32mtio.h \ vmd250.h \ $(extra_dynamic_SRC) cckd: cckd2ckd$(EXEEXT) \ cckdcdsk$(EXEEXT) \ cckddiag$(EXEEXT) \ cckdcomp$(EXEEXT) \ cckdswap$(EXEEXT) \ dasdcopy$(EXEEXT) ######################################################### # B U I L D R U L E S . . . ######################################################### # # *** PROGRAMMING NOTE! *** # # The tabs in the below statements ARE significant! # Not all make programs accept (handle correctly) # make files that use blanks instead of tabs in their # build rules. Thus in order to remain compatible # with older make programs the below build rules # MUST use *tabs* and NOT BLANKS! # ######################################################### tar: dist install-exec-local: install-exec-hook: if BUILD_SHARED rm -f $(DESTDIR)$(libdir)/libherc*.a rm -f $(DESTDIR)$(modexecdir)/dyn*.a rm -f $(DESTDIR)$(modexecdir)/hdt*.a else rm -f $(DESTDIR)$(libdir)/libherc* endif # # NOTE : symbolic links point to FINAL destination (not to staged install) # rm -f $(DESTDIR)$(bindir)/fba2cfba$(EXEEXT) (cd $(DESTDIR)$(bindir); @LN_S@ ./dasdcopy$(EXEEXT) fba2cfba$(EXEEXT)) rm -f $(DESTDIR)$(bindir)/ckd2cckd$(EXEEXT) (cd $(DESTDIR)$(bindir); @LN_S@ ./dasdcopy$(EXEEXT) ckd2cckd$(EXEEXT)) rm -f $(DESTDIR)$(bindir)/cfba2fba$(EXEEXT) (cd $(DESTDIR)$(bindir); @LN_S@ ./dasdcopy$(EXEEXT) cfba2fba$(EXEEXT)) rm -f $(DESTDIR)$(bindir)/cckd2ckd$(EXEEXT) (cd $(DESTDIR)$(bindir); @LN_S@ ./dasdcopy$(EXEEXT) cckd2ckd$(EXEEXT)) if SETUID_HERCIFC chown root $(DESTDIR)$(bindir)/hercifc if HERCIFC_GROUPSET chgrp $(HERCIFC_GROUPNAME) $(DESTDIR)$(bindir)/hercifc endif chmod 0750 $(DESTDIR)$(bindir)/hercifc chmod +s $(DESTDIR)$(bindir)/hercifc rm hercifc endif uninstall-local: uninstall-hook: rm -f $(DESTDIR)$(bindir)/fba2cfba$(EXEEXT) rm -f $(DESTDIR)$(bindir)/ckd2cckd$(EXEEXT) rm -f $(DESTDIR)$(bindir)/cfba2fba$(EXEEXT) rm -f $(DESTDIR)$(bindir)/cckd2ckd$(EXEEXT) %.s: %.c $(COMPILE) -S $< hercules-3.07/makefile.bat000644 000765 000765 00000042552 11340774747 017236 0ustar00jmaynardjmaynard000000 000000 @REM $Id: makefile.bat 5640 2010-02-20 02:13:36Z fish $ @if defined TRACEON (@echo on) else (@echo off) :: Uncomment the below to set a custom build description. ::set CUSTOM_BUILD_STRING="(whatever you want it to be)" :: Uncomment the below to ALWAYS generate assembly (.cod) listings, or :: define it yourself via 'set' command before invoking this batch file. :: set ASSEMBLY_LISTINGS=1 ::***************************************************************************** ::***************************************************************************** ::***************************************************************************** ::*** *** ::*** MAKEFILE.BAT *** ::*** *** ::***************************************************************************** ::***************************************************************************** ::***************************************************************************** ::* * ::* Designed to be called either from the command line or by a * ::* Visual Studio makefile project with the "Build command line" * ::* set to: "makefile.bat ". See 'HELP' section * ::* further below for details regarding use. * ::* * ::* If this batch file works okay then it was written by Fish. * ::* If it doesn't work then I don't know who the heck wrote it. * ::* * ::***************************************************************************** ::* * ::* PROGRAMMING NOTE * ::* * ::* All error messages *MUST* be issued in the following strict format: * ::* * ::* echo %~nx0^(1^) : error C9999 : error-message-text... * ::* * ::* in order for the Visual Studio IDE to detect it as a build error since * ::* exiting with a non-zero return code doesn't do the trick. Visual Studio * ::* apparently examines the message-text looking for error/warning strings. * ::* * ::***************************************************************************** set rc=0 set "TRACE=if defined TRACEON echo" if "%~1" == "" goto :help if "%~1" == "?" goto :help if "%~1" == "/?" goto :help if "%~1" == "-?" goto :help if "%~1" == "--help" goto :help set build_type=%~1 set makefile_name=%~2 set num_cpus=%~3 set extra_nmake_arg=%~4 set SolutionDir=%~5 :extra_args if "%~5" == "" goto :begin set extra_nmake_arg=%extra_nmake_arg% %~5 shift /1 goto :extra_args ::----------------------------------------------------------------------------- :: HELP ::----------------------------------------------------------------------------- :help echo. echo %~nx0^(1^) : error C9999 : Help information is as follows: echo. echo. echo. echo %~nx0 echo. echo. echo Initializes the Windows software development build envionment and invokes echo nmake to build the desired 32 or 64-bit version of the Hercules emulator. echo. echo. echo Format: echo. echo. echo %~nx0 {build-type} {makefile-name} {num-cpu-engines} [-a^|clean] echo. echo. echo Where: echo. echo {build-type} The desired build configuration. Valid values are echo DEBUG / RETAIL for building a 32-bit Hercules, or echo DEBUG-X64 / RETAIL-X64 to build a 64-bit version echo of Hercules targeting (favoring) AMD64 processors, echo or DEBUG-IA64 / RETAIL-IA64 for a 64-bit version echo of Hercules favoring Intel Itanium-64 processors. echo. echo {makefile-name} The name of our makefile: 'makefile.msvc' echo. echo {num-cpu-engines} The maximum number of emulated CPUs (NUMCPU=) you echo want this build of Hercules to support: 1 to 64. echo. echo [-a^|clean] Use '-a' to perform a full rebuild of all Hercules echo binaries, or 'clean' to delete all temporary work echo files from all work/output directories, including echo any/all previously built binaries. If not specified echo then only those modules that need to be rebuilt are echo actually rebuilt, usually resulting in much quicker echo build. However, when doing a 'RETAIL' build it is echo HIGHLY RECOMMENDED that you always specify the '-a' echo option to ensure that a complete rebuild is done. echo. exit /b 1 ::----------------------------------------------------------------------------- :: BEGIN ::----------------------------------------------------------------------------- :begin call :set_build_env if %rc% NEQ 0 exit /b 1 call :validate_makefile if %rc% NEQ 0 exit /b 1 call :validate_num_cpus if %rc% NEQ 0 exit /b 1 call :set_cfg if %rc% NEQ 0 exit /b 1 call :set_targ_arch if %rc% NEQ 0 exit /b 1 goto :%build_env% ::----------------------------------------------------------------------------- :: PROGRAMMING NOTE ::----------------------------------------------------------------------------- :: :: It's important to use 'setlocal' before calling the Microsoft batch file :: that sets up the build environment and to call 'endlocal' before exiting. :: :: Doing this ensures the build environment is freshly initialized each time :: this batch file is invoked, thereby ensuing a valid build environment is :: created each time a build is performed. Failure to do so runs the risk of :: not only an incompatible (invalid) build environment being constructed as :: a result of subsequent build setting being created on top of the previous :: build settings, but also risks overflowing the environment area since the :: PATH and LIB variables would thus keep growing ever longer and longer. :: :: Thus to ensure that never happens and that we always start with a freshly :: initialized and (hopefully!) valid build environment each time, we use :: setlocal and endlocal to push/pop the local environment space each time :: we are called. :: :: Also note that while it would be simpler to simply create a "front end" :: batch file to issue the setlocal before invoking this batch file (and :: then do the endlocal once we return), doing it that way leaves open the :: possibility that some smart-aleck newbie developer who doesn't know any :: better from bypassing the font-end batch file altogether and invoking us :: directly and then asking for support when he has problems because builds :: their Hercules builds are not working correctly. :: :: Yes it's more effort to do things this way but as long as you're careful :: it's worth it in my personal opinion. :: :: -- Fish, March 2009 :: ::----------------------------------------------------------------------------- :: VS2005 or VS2008 ::----------------------------------------------------------------------------- :vs90 :vs80 if /i "%targ_arch%" == "all" goto :multi_build call :set_host_arch if %rc% NEQ 0 exit /b 1 :: (see PROGRAMMING NOTE further above!) setlocal call "%VSTOOLSDIR%..\..\VC\vcvarsall.bat" %host_arch%%targ_arch% goto :nmake ::----------------------------------------------------------------------------- :: Platform SDK or VCToolkit ::----------------------------------------------------------------------------- :sdk :toolkit :: (see PROGRAMMING NOTE further above!) setlocal if /i "%build_env%" == "toolkit" call "%bat_dir%vcvars32.bat" call "%bat_dir%setenv" /%BLD% /%CFG% goto :nmake ::----------------------------------------------------------------------------- :: CALLED SUBROUTINES ::----------------------------------------------------------------------------- :set_build_env set rc=0 set build_env= if "%VS90COMNTOOLS%" == "" goto :try_vs80 set build_env=vs90 set VSTOOLSDIR=%VS90COMNTOOLS% goto :EOF :try_vs80 if "%VS80COMNTOOLS%" == "" goto :try_sdk set build_env=vs80 set VSTOOLSDIR=%VS80COMNTOOLS% goto :EOF :try_sdk if "%MSSdk%" == "" goto :try_toolkit set build_env=sdk set bat_dir=%MSSdk% goto :EOF :try_toolkit if "%VCToolkitInstallDir%" == "" goto :try_xxxx set build_env=toolkit set bat_dir=%VCToolkitInstallDir% goto :EOF :try_xxxx echo. echo %~nx0^(1^) : error C9999 : No suitable Windows development product is installed set rc=1 goto :EOF ::----------------------------------------------------------------------------- :validate_makefile set rc=0 if exist "%makefile_name%" goto :EOF echo. echo %~nx0^(1^) : error C9999 : makefile "%makefile_name%" not found set rc=1 goto :EOF ::----------------------------------------------------------------------------- :validate_num_cpus set rc=1 for /f "delims=0123456789" %%i in ("%num_cpus%\") do if "%%i" == "\" set rc=0 if %rc% NEQ 0 goto :bad_num_cpus if %num_cpus% LSS 1 goto :bad_num_cpus if %num_cpus% GTR 64 goto :bad_num_cpus goto :EOF :bad_num_cpus echo. echo %~nx0^(1^) : error C9999 : "%num_cpus%": Invalid number of cpu engines set rc=1 goto :EOF ::----------------------------------------------------------------------------- :set_cfg set rc=0 set CFG= if /i "%build_type%" == "DEBUG" set CFG=DEBUG if /i "%build_type%" == "DEBUG-X64" set CFG=DEBUG if /i "%build_type%" == "DEBUG-IA64" set CFG=DEBUG if /i "%build_type%" == "RETAIL" set CFG=RETAIL if /i "%build_type%" == "RETAIL-X64" set CFG=RETAIL if /i "%build_type%" == "RETAIL-IA64" set CFG=RETAIL :: Check for VS2008 multi-configuration multi-platform parallel build... if not "%CFG%" == "" goto :EOF if /i not "%build_env%" == "vs90" goto :bad_cfg if /i "%build_type%" == "DEBUG-ALL" set CFG=debug if /i "%build_type%" == "RETAIL-ALL" set CFG=retail if /i "%build_type%" == "ALL-ALL" set CFG=all if not "%CFG%" == "" goto :EOF :bad_cfg echo. echo %~nx0^(1^) : error C9999 : "%build_type%": Invalid build-type set rc=1 goto :EOF ::----------------------------------------------------------------------------- :set_targ_arch set rc=0 set targ_arch= if /i "%build_type%" == "DEBUG" set targ_arch=x86 if /i "%build_type%" == "RETAIL" set targ_arch=x86 if /i "%build_type%" == "DEBUG-X64" set targ_arch=amd64 if /i "%build_type%" == "RETAIL-X64" set targ_arch=amd64 if /i "%build_type%" == "DEBUG-IA64" set targ_arch=ia64 if /i "%build_type%" == "RETAIL-IA64" set targ_arch=ia64 :: Check for VS2008 multi-configuration multi-platform parallel build... if not "%targ_arch%" == "" goto :set_CPU_etc if /i not "%build_env%" == "vs90" goto :bad_targ_arch if /i "%build_type%" == "DEBUG-ALL" set targ_arch=all if /i "%build_type%" == "RETAIL-ALL" set targ_arch=all if /i "%build_type%" == "ALL-ALL" set targ_arch=all if not "%targ_arch%" == "" goto :EOF :bad_targ_arch echo. echo %~nx0^(1^) : error C9999 : "%build_type%": Invalid build-type set rc=1 goto :EOF :set_CPU_etc set CPU= if /i "%targ_arch%" == "x86" set CPU=i386 if /i "%targ_arch%" == "amd64" set CPU=AMD64 if /i "%targ_arch%" == "ia64" set CPU=IA64 set BLD= if /i "%targ_arch%" == "x86" set BLD=XP32 if /i "%targ_arch%" == "amd64" set BLD=XP64 if /i "%targ_arch%" == "ia64" set BLD=IA64 set _WIN64= if /i "%targ_arch%" == "amd64" set _WIN64=1 if /i "%targ_arch%" == "ia64" set _WIN64=1 goto :EOF ::----------------------------------------------------------------------------- :set_host_arch set rc=0 set host_arch= if /i "%PROCESSOR_ARCHITECTURE%" == "x86" set host_arch=x86 if /i "%PROCESSOR_ARCHITECTURE%" == "AMD64" set host_arch=amd64 if /i "%PROCESSOR_ARCHITECTURE%" == "IA64" set host_arch=ia64 :: PROGRAMMING NOTE: there MUST NOT be any spaces before the ')'!!! if /i not "%host_arch%" == "%targ_arch%" goto :cross set host_arch= if exist "%VSTOOLSDIR%..\..\VC\bin\vcvars32.bat" goto :EOF goto :missing :cross set host_arch=x86_ if exist "%VSTOOLSDIR%..\..\VC\bin\%host_arch%%targ_arch%\vcvars%host_arch%%targ_arch%.bat" goto :EOF goto :missing :missing echo. echo %~nx0^(1^) : error C9999 : Build support for target architecture %targ_arch% is not installed set rc=1 goto :EOF ::----------------------------------------------------------------------------- :fullpath :: Search the Windows PATH for the file in question and return its :: fully qualified path if found. Otherwise return an empty string. :: Note: the below does not work for directories, only files. set save_path=%path% set path=.;%path% set fullpath=%~dpnx$PATH:1 set path=%save_path% goto :EOF ::----------------------------------------------------------------------------- :re_set :: The following called when set= contains (), which confuses poor windoze set %~1=%~2 goto :EOF ::----------------------------------------------------------------------------- :ifallorclean set @= set #= :ifallorclean_loop if "%1" == "" goto :EOF if /i "%1" == "-a" set @=1 if /i "%1" == "/a" set @=1 if /i "%1" == "all" set @=1 if /i "%1" == "clean" set #=1 shift /1 goto :ifallorclean_loop ::----------------------------------------------------------------------------- :: CALL NMAKE ::----------------------------------------------------------------------------- :nmake set MAX_CPU_ENGINES=%num_cpus% :: Additional nmake arguments (for reference): :: :: -nologo suppress copyright banner :: -s silent (suppress commands echoing) :: -k keep going if error(s) :: -g display !INCLUDEd files (VS2005 or greater only) nmake -nologo -f "%makefile_name%" -s %extra_nmake_arg% set rc=%errorlevel% :: (see the PROGRAMMING NOTE at the beginning of this batch file!) endlocal & set rc=%rc% exit /b %rc% ::----------------------------------------------------------------------------- :: VS2008 multi-configuration multi-platform parallel build ::----------------------------------------------------------------------------- :: :: The following is special logic to leverage Fish's "RunJobs" tool :: that allows us to build multiple different project configurations :: in parallel with one another which Microsoft does not yet support. :: :: Refer to the CodeProject article entitled "RunJobs" at the following :: URL for more details: http://www.codeproject.com/KB/cpp/runjobs.aspx :: ::----------------------------------------------------------------------------- :multi_build ::------------------------------------------------- :: Make sure the below defined command exists... ::------------------------------------------------- set runjobs_cmd=runjobs.exe call :fullpath "%runjobs_cmd%" if "%fullpath%" == "" goto :no_runjobs set runjobs_cmd=%fullpath% ::------------------------------------------------------------------- :: VCBUILD requires that both $(SolutionDir) and $(SolutionPath) :: are defined properly. Note however that while $(SolutionDir) :: *must* be accurate (so that VCBUILD can find the Solution and :: Projects you wish to build), the actual Solution file defined :: in the $(SolutionPath) variable does not need to exist since :: it is never used. (But the directory portion of its path must :: match $(SolutionDir) of course). Also note that we must call :: vsvars32.bat in order to setup the proper environment so that :: VCBUILD can work properly (and so that RunJobs can find it!) ::------------------------------------------------------------------- if not defined SolutionDir call :re_set SolutionDir "%cd%\" call :re_set SolutionPath "%SolutionDir%notused.sln" call "%VSTOOLSDIR%vsvars32.bat" call :ifallorclean %extra_nmake_arg% if defined # ( set VCBUILDOPT=/clean ) else if defined @ ( set VCBUILDOPT=/rebuild ) else ( set VCBUILDOPT=/nocolor ) "%runjobs_cmd%" %CFG%-%targ_arch%.jobs set rc=%errorlevel% exit /b %rc% :no_runjobs echo. echo %~nx0^(1^) : error C9999 : Could not find "%runjobs_cmd%" anywhere on your system set rc=1 exit /b %rc% ::----------------------------------------------------------------------------- :: ((( EOF ))) ::----------------------------------------------------------------------------- hercules-3.07/Makefile.in000644 000765 000765 00000252243 11344713141 017017 0ustar00jmaynardjmaynard000000 000000 # Makefile.in generated by automake 1.9.6 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ # *************************************************************************** # Makefile for Hercules S/370, ESA/390 and z/Architecture emulator # Process this file with 'automake' to produce Makefile.in # # $Id: Makefile.am 5617 2010-02-09 00:00:41Z fish $ # # $Log$ # Revision 1.187 2009/01/18 00:52:19 jmaynard # Fix Gentoo reported bug: unable to do multithreaded "make install" reliably # if --enable-setuid-hercifc is specified. # # Revision 1.186 2008/12/29 11:03:10 jj # Move HMC disk I/O functions to scedasd.c # # Revision 1.185 2008/12/04 17:39:02 rbowler # Add ability to configure group name with --enable-setuid-hercifc=name # # Revision 1.184 2008/12/01 16:19:49 jj # Check for licensed operating systems without impairing architectural # compliance of IFL's # # Revision 1.183 2008/05/22 19:25:58 fish # Flex FakeTape support # # Revision 1.182 2008/03/25 11:41:31 fish # SCSI TAPE MODS part 1: groundwork: non-functional changes: # rename some functions, comments, general restructuring, etc. # New source modules awstape.c, omatape.c, hettape.c and # tapeccws.c added, but not yet used (all will be used in a future # commit though when tapedev.c code is eventually split) # # Revision 1.181 2008/03/02 22:50:35 rbowler # Restore tabs corrupted by previous modification # # Revision 1.180 2008/03/01 14:19:29 rbowler # Add new module general3.c for general-instructions-extension facility # # Revision 1.179 2008/02/19 11:49:18 ivan # - Move setting of CPU priority after spwaning timer thread # - Added support for Posix 1003.1e capabilities # # Revision 1.178 2007/06/02 13:46:41 rbowler # PFPO framework # # Revision 1.177 2006/12/30 21:13:37 rbowler # Backout rev 1.176 # # Revision 1.175 2006/12/30 16:54:07 rbowler # Reinstate missing changelog entries # # Revision 1.174 2006/12/30 15:37:01 jmaynard # Removed a coupple of stray ^Ms. # # Revision 1.173 2006/12/30 01:20:09 fish # Add new MSVC makefile includes to distribution # # Revision 1.172 2006/12/18 13:35:51 rbowler # Add hstdint.h to make dist # # Revision 1.171 2006/12/13 17:16:30 rbowler # Make libherc depend on libdecNumber # # Revision 1.170 2006/12/11 16:56:59 rbowler # Update Makefile.am to search decNumber for include files # # Revision 1.169 2006/12/09 01:05:59 ivan # Remove makefile-dll.msvc from Makefile.am dist list since it has been removed from the repository # # Revision 1.168 2006/12/08 09:43:16 jj # Add CVS message log # # DD/MM/YY Description....................................................... # 06/09/06 Change History added - Fish # 06/09/06 HAO (Hercules Automatic Operator) support - Fish # *************************************************************************** srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = . am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd INSTALL = @INSTALL@ install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ bin_PROGRAMS = hercules$(EXEEXT) dasdinit$(EXEEXT) dasdisup$(EXEEXT) \ dasdload$(EXEEXT) dasdconv$(EXEEXT) dasdls$(EXEEXT) \ dasdcat$(EXEEXT) dasdpdsu$(EXEEXT) dasdseq$(EXEEXT) \ tapecopy$(EXEEXT) tapemap$(EXEEXT) tapesplt$(EXEEXT) \ cckdcdsk$(EXEEXT) cckdcomp$(EXEEXT) cckddiag$(EXEEXT) \ cckdswap$(EXEEXT) dasdcopy$(EXEEXT) hetget$(EXEEXT) \ hetinit$(EXEEXT) hetmap$(EXEEXT) hetupd$(EXEEXT) \ dmap2hrc$(EXEEXT) $(am__EXEEXT_1) $(am__EXEEXT_2) EXTRA_PROGRAMS = hercifc$(EXEEXT) DIST_COMMON = $(am__configure_deps) $(noinst_HEADERS) \ $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ $(srcdir)/config.h.in $(top_srcdir)/configure ABOUT-NLS \ INSTALL autoconf/README autoconf/config.guess \ autoconf/config.rpath autoconf/config.sub autoconf/depcomp \ autoconf/install-sh autoconf/ltmain.sh autoconf/missing \ autoconf/mkinstalldirs subdir = . ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/autoconf/hercules.m4 \ $(top_srcdir)/autoconf/libtool.m4 \ $(top_srcdir)/autoconf/ltdl.m4 $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ configure.lineno configure.status.lineno mkinstalldirs = $(SHELL) $(top_srcdir)/autoconf/mkinstalldirs CONFIG_HEADER = config.h CONFIG_CLEAN_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(modexecdir)" \ "$(DESTDIR)$(bindir)" libLTLIBRARIES_INSTALL = $(INSTALL) modexecLTLIBRARIES_INSTALL = $(INSTALL) LTLIBRARIES = $(lib_LTLIBRARIES) $(modexec_LTLIBRARIES) \ $(noinst_LTLIBRARIES) am__DEPENDENCIES_1 = @OPTION_DYNAMIC_LOAD_TRUE@am__DEPENDENCIES_2 = libherc.la libhercs.la \ @OPTION_DYNAMIC_LOAD_TRUE@ libhercu.la $(am__DEPENDENCIES_1) @OPTION_DYNAMIC_LOAD_TRUE@dyngui_la_DEPENDENCIES = \ @OPTION_DYNAMIC_LOAD_TRUE@ $(am__DEPENDENCIES_2) am__dyngui_la_SOURCES_DIST = dyngui.c @OPTION_DYNAMIC_LOAD_TRUE@am_dyngui_la_OBJECTS = dyngui.lo dyngui_la_OBJECTS = $(am_dyngui_la_OBJECTS) @OPTION_DYNAMIC_LOAD_TRUE@am_dyngui_la_rpath = -rpath $(modexecdir) @OPTION_DYNAMIC_LOAD_TRUE@dyninst_la_DEPENDENCIES = \ @OPTION_DYNAMIC_LOAD_TRUE@ $(am__DEPENDENCIES_2) am__dyninst_la_SOURCES_DIST = dyninst.c @OPTION_DYNAMIC_LOAD_TRUE@am_dyninst_la_OBJECTS = dyninst.lo dyninst_la_OBJECTS = $(am_dyninst_la_OBJECTS) @OPTION_DYNAMIC_LOAD_TRUE@am_dyninst_la_rpath = -rpath $(modexecdir) @OPTION_DYNAMIC_LOAD_TRUE@hdt1052c_la_DEPENDENCIES = \ @OPTION_DYNAMIC_LOAD_TRUE@ $(am__DEPENDENCIES_2) am__hdt1052c_la_SOURCES_DIST = con1052c.c @OPTION_DYNAMIC_LOAD_TRUE@am_hdt1052c_la_OBJECTS = con1052c.lo hdt1052c_la_OBJECTS = $(am_hdt1052c_la_OBJECTS) @OPTION_DYNAMIC_LOAD_TRUE@am_hdt1052c_la_rpath = -rpath $(modexecdir) @OPTION_DYNAMIC_LOAD_TRUE@hdt1403_la_DEPENDENCIES = \ @OPTION_DYNAMIC_LOAD_TRUE@ $(am__DEPENDENCIES_2) am__hdt1403_la_SOURCES_DIST = printer.c sockdev.c @OPTION_DYNAMIC_LOAD_TRUE@am_hdt1403_la_OBJECTS = printer.lo \ @OPTION_DYNAMIC_LOAD_TRUE@ sockdev.lo hdt1403_la_OBJECTS = $(am_hdt1403_la_OBJECTS) @OPTION_DYNAMIC_LOAD_TRUE@am_hdt1403_la_rpath = -rpath $(modexecdir) @OPTION_DYNAMIC_LOAD_TRUE@hdt2703_la_DEPENDENCIES = \ @OPTION_DYNAMIC_LOAD_TRUE@ $(am__DEPENDENCIES_2) am__hdt2703_la_SOURCES_DIST = commadpt.c @OPTION_DYNAMIC_LOAD_TRUE@am_hdt2703_la_OBJECTS = commadpt.lo hdt2703_la_OBJECTS = $(am_hdt2703_la_OBJECTS) @OPTION_DYNAMIC_LOAD_TRUE@am_hdt2703_la_rpath = -rpath $(modexecdir) @OPTION_DYNAMIC_LOAD_TRUE@hdt2880_la_DEPENDENCIES = \ @OPTION_DYNAMIC_LOAD_TRUE@ $(am__DEPENDENCIES_2) am__hdt2880_la_SOURCES_DIST = hchan.c @OPTION_DYNAMIC_LOAD_TRUE@am_hdt2880_la_OBJECTS = hchan.lo hdt2880_la_OBJECTS = $(am_hdt2880_la_OBJECTS) @OPTION_DYNAMIC_LOAD_TRUE@am_hdt2880_la_rpath = -rpath $(modexecdir) @OPTION_DYNAMIC_LOAD_TRUE@hdt3088_la_DEPENDENCIES = \ @OPTION_DYNAMIC_LOAD_TRUE@ $(am__DEPENDENCIES_2) am__hdt3088_la_SOURCES_DIST = ctc_lcs.c ctc_ctci.c ctcadpt.c w32ctca.c \ tuntap.c @OPTION_DYNAMIC_LOAD_TRUE@am_hdt3088_la_OBJECTS = ctc_lcs.lo \ @OPTION_DYNAMIC_LOAD_TRUE@ ctc_ctci.lo ctcadpt.lo w32ctca.lo \ @OPTION_DYNAMIC_LOAD_TRUE@ tuntap.lo hdt3088_la_OBJECTS = $(am_hdt3088_la_OBJECTS) @OPTION_DYNAMIC_LOAD_TRUE@am_hdt3088_la_rpath = -rpath $(modexecdir) @OPTION_DYNAMIC_LOAD_TRUE@hdt3270_la_DEPENDENCIES = \ @OPTION_DYNAMIC_LOAD_TRUE@ $(am__DEPENDENCIES_2) am__hdt3270_la_SOURCES_DIST = console.c @OPTION_DYNAMIC_LOAD_TRUE@am_hdt3270_la_OBJECTS = console.lo hdt3270_la_OBJECTS = $(am_hdt3270_la_OBJECTS) @OPTION_DYNAMIC_LOAD_TRUE@am_hdt3270_la_rpath = -rpath $(modexecdir) @OPTION_DYNAMIC_LOAD_TRUE@hdt3420_la_DEPENDENCIES = \ @OPTION_DYNAMIC_LOAD_TRUE@ $(am__DEPENDENCIES_2) libherct.la am__hdt3420_la_SOURCES_DIST = tapedev.c tapeccws.c awstape.c \ faketape.c hettape.c omatape.c scsitape.c w32stape.c @OPTION_DYNAMIC_LOAD_TRUE@am_hdt3420_la_OBJECTS = tapedev.lo \ @OPTION_DYNAMIC_LOAD_TRUE@ tapeccws.lo awstape.lo faketape.lo \ @OPTION_DYNAMIC_LOAD_TRUE@ hettape.lo omatape.lo scsitape.lo \ @OPTION_DYNAMIC_LOAD_TRUE@ w32stape.lo hdt3420_la_OBJECTS = $(am_hdt3420_la_OBJECTS) @OPTION_DYNAMIC_LOAD_TRUE@am_hdt3420_la_rpath = -rpath $(modexecdir) @OPTION_DYNAMIC_LOAD_TRUE@hdt3505_la_DEPENDENCIES = \ @OPTION_DYNAMIC_LOAD_TRUE@ $(am__DEPENDENCIES_2) am__hdt3505_la_SOURCES_DIST = cardrdr.c sockdev.c @OPTION_DYNAMIC_LOAD_TRUE@am_hdt3505_la_OBJECTS = cardrdr.lo \ @OPTION_DYNAMIC_LOAD_TRUE@ sockdev.lo hdt3505_la_OBJECTS = $(am_hdt3505_la_OBJECTS) @OPTION_DYNAMIC_LOAD_TRUE@am_hdt3505_la_rpath = -rpath $(modexecdir) @OPTION_DYNAMIC_LOAD_TRUE@hdt3525_la_DEPENDENCIES = \ @OPTION_DYNAMIC_LOAD_TRUE@ $(am__DEPENDENCIES_2) am__hdt3525_la_SOURCES_DIST = cardpch.c @OPTION_DYNAMIC_LOAD_TRUE@am_hdt3525_la_OBJECTS = cardpch.lo hdt3525_la_OBJECTS = $(am_hdt3525_la_OBJECTS) @OPTION_DYNAMIC_LOAD_TRUE@am_hdt3525_la_rpath = -rpath $(modexecdir) @OPTION_DYNAMIC_LOAD_TRUE@hdt3705_la_DEPENDENCIES = \ @OPTION_DYNAMIC_LOAD_TRUE@ $(am__DEPENDENCIES_2) am__hdt3705_la_SOURCES_DIST = comm3705.c @OPTION_DYNAMIC_LOAD_TRUE@am_hdt3705_la_OBJECTS = comm3705.lo hdt3705_la_OBJECTS = $(am_hdt3705_la_OBJECTS) @OPTION_DYNAMIC_LOAD_TRUE@am_hdt3705_la_rpath = -rpath $(modexecdir) @OPTION_DYNAMIC_LOAD_TRUE@hdteq_la_DEPENDENCIES = \ @OPTION_DYNAMIC_LOAD_TRUE@ $(am__DEPENDENCIES_2) am__hdteq_la_SOURCES_DIST = hdteq.c @OPTION_DYNAMIC_LOAD_TRUE@am_hdteq_la_OBJECTS = hdteq.lo hdteq_la_OBJECTS = $(am_hdteq_la_OBJECTS) @OPTION_DYNAMIC_LOAD_TRUE@am_hdteq_la_rpath = -rpath $(modexecdir) @OPTION_DYNAMIC_LOAD_TRUE@hdtqeth_la_DEPENDENCIES = \ @OPTION_DYNAMIC_LOAD_TRUE@ $(am__DEPENDENCIES_2) am__hdtqeth_la_SOURCES_DIST = qeth.c @OPTION_DYNAMIC_LOAD_TRUE@am_hdtqeth_la_OBJECTS = qeth.lo hdtqeth_la_OBJECTS = $(am_hdtqeth_la_OBJECTS) @OPTION_DYNAMIC_LOAD_TRUE@am_hdtqeth_la_rpath = -rpath $(modexecdir) libherc_la_DEPENDENCIES = libhercs.la libhercu.la libherct.la \ libhercd.la decNumber/libdecNumber.la $(am__DEPENDENCIES_1) am__libherc_la_SOURCES_DIST = hconsole.c w32util.c strsignal.c impl.c \ config.c bldcfg.c panel.c history.c fillfnam.c ipl.c assist.c \ dat.c stack.c cpu.c vstore.c general1.c general2.c general3.c \ pfpo.c plo.c control.c crypto.c io.c decimal.c service.c \ scedasd.c losc.c chsc.c opcode.c diagnose.c diagmssf.c vm.c \ vmd250.c channel.c external.c float.c trace.c machchk.c \ vector.c xstore.c cmpsc.c sie.c qdio.c clock.c timer.c esame.c \ ieee.c dfp.c machdep.h httpserv.c cgibin.c loadparm.c hsccmd.c \ cmdtab.c hao.c hscmisc.c sr.c w32chan.c commadpt.c comm3705.c \ console.c cardpch.c cardrdr.c sockdev.c printer.c tapedev.c \ tapeccws.c sllib.c hetlib.c awstape.c faketape.c hettape.c \ omatape.c scsitape.c w32stape.c ctc_lcs.c ctc_ctci.c ctcadpt.c \ w32ctca.c hchan.c tuntap.c qeth.c con1052c.c ecpsvm.c am__objects_1 = w32chan.lo @BUILD_FTHREADS_TRUE@am__objects_2 = $(am__objects_1) am__objects_3 = commadpt.lo comm3705.lo console.lo cardpch.lo \ cardrdr.lo sockdev.lo printer.lo tapedev.lo tapeccws.lo \ sllib.lo hetlib.lo awstape.lo faketape.lo hettape.lo \ omatape.lo scsitape.lo w32stape.lo ctc_lcs.lo ctc_ctci.lo \ ctcadpt.lo w32ctca.lo hchan.lo tuntap.lo qeth.lo con1052c.lo @OPTION_DYNAMIC_LOAD_FALSE@am__objects_4 = $(am__objects_3) am_libherc_la_OBJECTS = hconsole.lo w32util.lo strsignal.lo impl.lo \ config.lo bldcfg.lo panel.lo history.lo fillfnam.lo ipl.lo \ assist.lo dat.lo stack.lo cpu.lo vstore.lo general1.lo \ general2.lo general3.lo pfpo.lo plo.lo control.lo crypto.lo \ io.lo decimal.lo service.lo scedasd.lo losc.lo chsc.lo \ opcode.lo diagnose.lo diagmssf.lo vm.lo vmd250.lo channel.lo \ external.lo float.lo trace.lo machchk.lo vector.lo xstore.lo \ cmpsc.lo sie.lo qdio.lo clock.lo timer.lo esame.lo ieee.lo \ dfp.lo httpserv.lo cgibin.lo loadparm.lo hsccmd.lo cmdtab.lo \ hao.lo hscmisc.lo sr.lo $(am__objects_2) $(am__objects_4) \ ecpsvm.lo libherc_la_OBJECTS = $(am_libherc_la_OBJECTS) libhercd_la_DEPENDENCIES = $(am__DEPENDENCIES_1) libhercs.la \ libhercu.la am_libhercd_la_OBJECTS = ckddasd.lo fbadasd.lo cckddasd.lo cckdutil.lo \ dasdtab.lo cache.lo dasdutil.lo shared.lo libhercd_la_OBJECTS = $(am_libhercd_la_OBJECTS) libhercs_la_DEPENDENCIES = $(am__DEPENDENCIES_1) am_libhercs_la_OBJECTS = hsys.lo libhercs_la_OBJECTS = $(am_libhercs_la_OBJECTS) libherct_la_DEPENDENCIES = $(am__DEPENDENCIES_1) libhercs.la \ libhercu.la am_libherct_la_OBJECTS = sllib.lo hetlib.lo libherct_la_OBJECTS = $(am_libherct_la_OBJECTS) libhercu_la_DEPENDENCIES = $(am__DEPENDENCIES_1) libhercs.la am__libhercu_la_SOURCES_DIST = version.c hscutl.c hscutl2.c codepage.c \ logger.c logmsg.c hdl.c hostinfo.c hsocket.c memrchr.c \ parser.c pttrace.c fthreads.c fishhang.c ltdl.c am__objects_5 = fthreads.lo @BUILD_FTHREADS_TRUE@am__objects_8 = $(am__objects_5) am__objects_6 = fishhang.lo @BUILD_FISHHANG_TRUE@@BUILD_FTHREADS_TRUE@am__objects_9 = \ @BUILD_FISHHANG_TRUE@@BUILD_FTHREADS_TRUE@ $(am__objects_6) @OPTION_DYNAMIC_LOAD_TRUE@am__objects_10 = ltdl.lo am_libhercu_la_OBJECTS = version.lo hscutl.lo hscutl2.lo codepage.lo \ logger.lo logmsg.lo hdl.lo hostinfo.lo hsocket.lo memrchr.lo \ parser.lo pttrace.lo $(am__objects_8) $(am__objects_9) \ $(am__objects_10) libhercu_la_OBJECTS = $(am_libhercu_la_OBJECTS) @BUILD_HERCIFC_TRUE@am__EXEEXT_1 = hercifc$(EXEEXT) @BUILD_SHARED_TRUE@am__EXEEXT_2 = herclin$(EXEEXT) binPROGRAMS_INSTALL = $(INSTALL_PROGRAM) PROGRAMS = $(bin_PROGRAMS) am_cckdcdsk_OBJECTS = cckdcdsk.$(OBJEXT) cckdcdsk_OBJECTS = $(am_cckdcdsk_OBJECTS) am__DEPENDENCIES_3 = libhercs.la libhercu.la libherct.la libhercd.la \ libherc.la am__DEPENDENCIES_4 = $(am__DEPENDENCIES_3) $(am__DEPENDENCIES_1) cckdcdsk_DEPENDENCIES = $(am__DEPENDENCIES_4) am_cckdcomp_OBJECTS = cckdcomp.$(OBJEXT) cckdcomp_OBJECTS = $(am_cckdcomp_OBJECTS) cckdcomp_DEPENDENCIES = $(am__DEPENDENCIES_4) am_cckddiag_OBJECTS = cckddiag.$(OBJEXT) cckddiag_OBJECTS = $(am_cckddiag_OBJECTS) cckddiag_DEPENDENCIES = $(am__DEPENDENCIES_4) am_cckdswap_OBJECTS = cckdswap.$(OBJEXT) cckdswap_OBJECTS = $(am_cckdswap_OBJECTS) cckdswap_DEPENDENCIES = $(am__DEPENDENCIES_4) am_dasdcat_OBJECTS = dasdcat.$(OBJEXT) dasdcat_OBJECTS = $(am_dasdcat_OBJECTS) dasdcat_DEPENDENCIES = $(am__DEPENDENCIES_4) am_dasdconv_OBJECTS = dasdconv.$(OBJEXT) dasdconv_OBJECTS = $(am_dasdconv_OBJECTS) dasdconv_DEPENDENCIES = $(am__DEPENDENCIES_4) am_dasdcopy_OBJECTS = dasdcopy.$(OBJEXT) dasdcopy_OBJECTS = $(am_dasdcopy_OBJECTS) dasdcopy_DEPENDENCIES = $(am__DEPENDENCIES_4) am_dasdinit_OBJECTS = dasdinit.$(OBJEXT) dasdinit_OBJECTS = $(am_dasdinit_OBJECTS) dasdinit_DEPENDENCIES = $(am__DEPENDENCIES_4) am_dasdisup_OBJECTS = dasdisup.$(OBJEXT) dasdisup_OBJECTS = $(am_dasdisup_OBJECTS) dasdisup_DEPENDENCIES = $(am__DEPENDENCIES_4) am_dasdload_OBJECTS = dasdload.$(OBJEXT) dasdload_OBJECTS = $(am_dasdload_OBJECTS) dasdload_DEPENDENCIES = $(am__DEPENDENCIES_4) am_dasdls_OBJECTS = dasdls.$(OBJEXT) dasdls_OBJECTS = $(am_dasdls_OBJECTS) dasdls_DEPENDENCIES = $(am__DEPENDENCIES_4) am_dasdpdsu_OBJECTS = dasdpdsu.$(OBJEXT) dasdpdsu_OBJECTS = $(am_dasdpdsu_OBJECTS) dasdpdsu_DEPENDENCIES = $(am__DEPENDENCIES_4) am_dasdseq_OBJECTS = dasdseq.$(OBJEXT) dasdseq_OBJECTS = $(am_dasdseq_OBJECTS) dasdseq_DEPENDENCIES = $(am__DEPENDENCIES_4) am_dmap2hrc_OBJECTS = dmap2hrc.$(OBJEXT) dmap2hrc_OBJECTS = $(am_dmap2hrc_OBJECTS) dmap2hrc_DEPENDENCIES = $(am__DEPENDENCIES_4) am__hercifc_SOURCES_DIST = hercifc.c @BUILD_HERCIFC_TRUE@am_hercifc_OBJECTS = hercifc.$(OBJEXT) hercifc_OBJECTS = $(am_hercifc_OBJECTS) @BUILD_HERCIFC_TRUE@hercifc_DEPENDENCIES = $(am__DEPENDENCIES_4) am__herclin_SOURCES_DIST = herclin.c hdlmain.c @BUILD_SHARED_TRUE@am_herclin_OBJECTS = herclin.$(OBJEXT) \ @BUILD_SHARED_TRUE@ hdlmain.$(OBJEXT) herclin_OBJECTS = $(am_herclin_OBJECTS) am_hercules_OBJECTS = bootstrap.$(OBJEXT) hdlmain.$(OBJEXT) hercules_OBJECTS = $(am_hercules_OBJECTS) am_hetget_OBJECTS = hetget.$(OBJEXT) hetget_OBJECTS = $(am_hetget_OBJECTS) hetget_DEPENDENCIES = $(am__DEPENDENCIES_4) am_hetinit_OBJECTS = hetinit.$(OBJEXT) hetinit_OBJECTS = $(am_hetinit_OBJECTS) hetinit_DEPENDENCIES = $(am__DEPENDENCIES_4) am_hetmap_OBJECTS = hetmap.$(OBJEXT) hetmap_OBJECTS = $(am_hetmap_OBJECTS) hetmap_DEPENDENCIES = $(am__DEPENDENCIES_4) am_hetupd_OBJECTS = hetupd.$(OBJEXT) hetupd_OBJECTS = $(am_hetupd_OBJECTS) hetupd_DEPENDENCIES = $(am__DEPENDENCIES_4) am_tapecopy_OBJECTS = tapecopy.$(OBJEXT) tapecopy_OBJECTS = $(am_tapecopy_OBJECTS) tapecopy_DEPENDENCIES = $(am__DEPENDENCIES_4) am_tapemap_OBJECTS = tapemap.$(OBJEXT) tapemap_OBJECTS = $(am_tapemap_OBJECTS) tapemap_DEPENDENCIES = $(am__DEPENDENCIES_4) am_tapesplt_OBJECTS = tapesplt.$(OBJEXT) tapesplt_OBJECTS = $(am_tapesplt_OBJECTS) tapesplt_DEPENDENCIES = $(am__DEPENDENCIES_4) DEFAULT_INCLUDES = -I. -I$(srcdir) -I. depcomp = $(SHELL) $(top_srcdir)/autoconf/depcomp am__depfiles_maybe = depfiles COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ SOURCES = $(dyngui_la_SOURCES) $(dyninst_la_SOURCES) \ $(hdt1052c_la_SOURCES) $(hdt1403_la_SOURCES) \ $(hdt2703_la_SOURCES) $(hdt2880_la_SOURCES) \ $(hdt3088_la_SOURCES) $(hdt3270_la_SOURCES) \ $(hdt3420_la_SOURCES) $(hdt3505_la_SOURCES) \ $(hdt3525_la_SOURCES) $(hdt3705_la_SOURCES) \ $(hdteq_la_SOURCES) $(hdtqeth_la_SOURCES) \ $(libherc_la_SOURCES) $(EXTRA_libherc_la_SOURCES) \ $(libhercd_la_SOURCES) $(libhercs_la_SOURCES) \ $(libherct_la_SOURCES) $(libhercu_la_SOURCES) \ $(cckdcdsk_SOURCES) $(cckdcomp_SOURCES) $(cckddiag_SOURCES) \ $(cckdswap_SOURCES) $(dasdcat_SOURCES) $(dasdconv_SOURCES) \ $(dasdcopy_SOURCES) $(dasdinit_SOURCES) $(dasdisup_SOURCES) \ $(dasdload_SOURCES) $(dasdls_SOURCES) $(dasdpdsu_SOURCES) \ $(dasdseq_SOURCES) $(dmap2hrc_SOURCES) $(hercifc_SOURCES) \ $(herclin_SOURCES) $(hercules_SOURCES) $(hetget_SOURCES) \ $(hetinit_SOURCES) $(hetmap_SOURCES) $(hetupd_SOURCES) \ $(tapecopy_SOURCES) $(tapemap_SOURCES) $(tapesplt_SOURCES) DIST_SOURCES = $(am__dyngui_la_SOURCES_DIST) \ $(am__dyninst_la_SOURCES_DIST) $(am__hdt1052c_la_SOURCES_DIST) \ $(am__hdt1403_la_SOURCES_DIST) $(am__hdt2703_la_SOURCES_DIST) \ $(am__hdt2880_la_SOURCES_DIST) $(am__hdt3088_la_SOURCES_DIST) \ $(am__hdt3270_la_SOURCES_DIST) $(am__hdt3420_la_SOURCES_DIST) \ $(am__hdt3505_la_SOURCES_DIST) $(am__hdt3525_la_SOURCES_DIST) \ $(am__hdt3705_la_SOURCES_DIST) $(am__hdteq_la_SOURCES_DIST) \ $(am__hdtqeth_la_SOURCES_DIST) $(am__libherc_la_SOURCES_DIST) \ $(EXTRA_libherc_la_SOURCES) $(libhercd_la_SOURCES) \ $(libhercs_la_SOURCES) $(libherct_la_SOURCES) \ $(am__libhercu_la_SOURCES_DIST) $(cckdcdsk_SOURCES) \ $(cckdcomp_SOURCES) $(cckddiag_SOURCES) $(cckdswap_SOURCES) \ $(dasdcat_SOURCES) $(dasdconv_SOURCES) $(dasdcopy_SOURCES) \ $(dasdinit_SOURCES) $(dasdisup_SOURCES) $(dasdload_SOURCES) \ $(dasdls_SOURCES) $(dasdpdsu_SOURCES) $(dasdseq_SOURCES) \ $(dmap2hrc_SOURCES) $(am__hercifc_SOURCES_DIST) \ $(am__herclin_SOURCES_DIST) $(hercules_SOURCES) \ $(hetget_SOURCES) $(hetinit_SOURCES) $(hetmap_SOURCES) \ $(hetupd_SOURCES) $(tapecopy_SOURCES) $(tapemap_SOURCES) \ $(tapesplt_SOURCES) RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ html-recursive info-recursive install-data-recursive \ install-exec-recursive install-info-recursive \ install-recursive installcheck-recursive installdirs-recursive \ pdf-recursive ps-recursive uninstall-info-recursive \ uninstall-recursive HEADERS = $(noinst_HEADERS) ETAGS = etags CTAGS = ctags DIST_SUBDIRS = $(SUBDIRS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) distdir = $(PACKAGE)-$(VERSION) top_distdir = $(distdir) am__remove_distdir = \ { test ! -d $(distdir) \ || { find $(distdir) -type d ! -perm -200 -exec chmod u+w {} ';' \ && rm -fr $(distdir); }; } DIST_ARCHIVES = $(distdir).tar.gz GZIP_ENV = --best distuninstallcheck_listfiles = find . -type f -print distcleancheck_listfiles = find . -type f -print ACLOCAL = @ACLOCAL@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BUILD_FISHHANG_FALSE = @BUILD_FISHHANG_FALSE@ BUILD_FISHHANG_TRUE = @BUILD_FISHHANG_TRUE@ BUILD_FTHREADS_FALSE = @BUILD_FTHREADS_FALSE@ BUILD_FTHREADS_TRUE = @BUILD_FTHREADS_TRUE@ BUILD_HERCIFC_FALSE = @BUILD_HERCIFC_FALSE@ BUILD_HERCIFC_TRUE = @BUILD_HERCIFC_TRUE@ BUILD_SHARED_FALSE = @BUILD_SHARED_FALSE@ BUILD_SHARED_TRUE = @BUILD_SHARED_TRUE@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CONVENIENCE_LTDL_FALSE = @CONVENIENCE_LTDL_FALSE@ CONVENIENCE_LTDL_TRUE = @CONVENIENCE_LTDL_TRUE@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ ECHO = @ECHO@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ F77 = @F77@ FFLAGS = @FFLAGS@ GMSGFMT = @GMSGFMT@ GREP = @GREP@ HERCIFC_GROUPNAME = @HERCIFC_GROUPNAME@ HERCIFC_GROUPSET_FALSE = @HERCIFC_GROUPSET_FALSE@ HERCIFC_GROUPSET_TRUE = @HERCIFC_GROUPSET_TRUE@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_LTDL_FALSE = @INSTALL_LTDL_FALSE@ INSTALL_LTDL_TRUE = @INSTALL_LTDL_TRUE@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ LDFLAGS = @LDFLAGS@ LIBADD_DL = @LIBADD_DL@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBTOOL_DEPS = @LIBTOOL_DEPS@ LN_S = @LN_S@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@ MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@ MAKEINFO = @MAKEINFO@ MKINSTALLDIRS = @MKINSTALLDIRS@ MSGFMT = @MSGFMT@ MSGMERGE = @MSGMERGE@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPTION_DYNAMIC_LOAD_FALSE = @OPTION_DYNAMIC_LOAD_FALSE@ OPTION_DYNAMIC_LOAD_TRUE = @OPTION_DYNAMIC_LOAD_TRUE@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ POSUB = @POSUB@ RANLIB = @RANLIB@ SETUID_HERCIFC_FALSE = @SETUID_HERCIFC_FALSE@ SETUID_HERCIFC_TRUE = @SETUID_HERCIFC_TRUE@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ USE_DLLTOOL_FALSE = @USE_DLLTOOL_FALSE@ USE_DLLTOOL_TRUE = @USE_DLLTOOL_TRUE@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_F77 = @ac_ct_F77@ am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ modexecdir = @modexecdir@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ AUTOMAKE_OPTIONS = foreign 1.5 ACLOCAL_AMFLAGS = -I m4 lns = @LN_S@ SUBDIRS = decNumber m4 po util html man . crypto LDADD = @LTLIBICONV@ @LTLIBINTL@ @LIBS@ AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/decNumber @BUILD_HERCIFC_FALSE@HERCIFC = @BUILD_HERCIFC_TRUE@HERCIFC = hercifc @BUILD_SHARED_FALSE@HERCLIN = @BUILD_SHARED_TRUE@HERCLIN = herclin fthreads_SRC = fthreads.c fishio_SRC = w32chan.c fishhang_SRC = fishhang.c @BUILD_FTHREADS_FALSE@FTHREADS = @BUILD_FTHREADS_TRUE@FTHREADS = $(fthreads_SRC) @BUILD_FTHREADS_FALSE@FISHIO = @BUILD_FTHREADS_TRUE@FISHIO = $(fishio_SRC) @BUILD_FISHHANG_FALSE@@BUILD_FTHREADS_TRUE@FISHHANG = @BUILD_FISHHANG_TRUE@@BUILD_FTHREADS_TRUE@FISHHANG = $(fishhang_SRC) @BUILD_FTHREADS_FALSE@FISHHANG = # We need to still include the source for the dynamic modules # in with the distribution regardless of whether or not the dyanmic # modules themselves are to be built so if dynamic load not possible, # then we need to include the source on the EXTRA_hercules_SOURCES # statement so even though they won't/don't actually get built, they # still nonetheless get included into distribution tarball. This is # *similar* to (bit not identical to) the way the fthreads sources # are handled. With the fthreads sources though, they can at least always # be built (even though they may not always generate any actual code # whenever they do) whereas the dynamic module source CANNOT (MUST not) # even be *attempted* to be "built" if support for building dynamic modules # doesn't even exist on the system doing the building. dynamic_SRC = dyngui.c \ dyninst.c \ hdteq.c dyndev_SRC = commadpt.c \ comm3705.c \ console.c \ cardpch.c \ cardrdr.c \ sockdev.c \ printer.c \ tapedev.c \ tapeccws.c \ sllib.c \ hetlib.c \ awstape.c \ faketape.c \ hettape.c \ omatape.c \ scsitape.c \ w32stape.c \ ctc_lcs.c \ ctc_ctci.c \ ctcadpt.c \ w32ctca.c \ hchan.c \ tuntap.c \ qeth.c \ con1052c.c @BUILD_SHARED_FALSE@XSTATIC = -static # -module : create a dlopen'able module # -no-undefined : required on all platform that do not allow shared modules # to have undefined symbols # $(LDADD) : Misc Linker flags set by autoconf # -export-dynamic : so dlsym works (to be verified - not sure it is necessary) # -avoid-version : needed.. Otherwise libtool gives crazy names to Windows # DLLs # @BUILD_SHARED_TRUE@XSTATIC = @OPTION_DYNAMIC_LOAD_FALSE@DYNSRC = $(dyndev_SRC) @OPTION_DYNAMIC_LOAD_TRUE@DYNSRC = @OPTION_DYNAMIC_LOAD_FALSE@LTDL = @OPTION_DYNAMIC_LOAD_TRUE@LTDL = ltdl.c @OPTION_DYNAMIC_LOAD_FALSE@DYNMOD_LD_FLAGS = @OPTION_DYNAMIC_LOAD_TRUE@DYNMOD_LD_FLAGS = -module \ @OPTION_DYNAMIC_LOAD_TRUE@ -no-undefined \ @OPTION_DYNAMIC_LOAD_TRUE@ $(XSTATIC) \ @OPTION_DYNAMIC_LOAD_TRUE@ -export-dynamic \ @OPTION_DYNAMIC_LOAD_TRUE@ -avoid-version @OPTION_DYNAMIC_LOAD_FALSE@DYNMOD_LD_ADD = @OPTION_DYNAMIC_LOAD_TRUE@DYNMOD_LD_ADD = libherc.la \ @OPTION_DYNAMIC_LOAD_TRUE@ libhercs.la \ @OPTION_DYNAMIC_LOAD_TRUE@ libhercu.la \ @OPTION_DYNAMIC_LOAD_TRUE@ $(LDADD) @OPTION_DYNAMIC_LOAD_FALSE@LIB_LD_FLAGS = $(XSTATIC) \ @OPTION_DYNAMIC_LOAD_FALSE@ -no-undefined \ @OPTION_DYNAMIC_LOAD_FALSE@ -avoid-version @OPTION_DYNAMIC_LOAD_TRUE@LIB_LD_FLAGS = -export-dynamic \ @OPTION_DYNAMIC_LOAD_TRUE@ $(XSTATIC) \ @OPTION_DYNAMIC_LOAD_TRUE@ -no-undefined \ @OPTION_DYNAMIC_LOAD_TRUE@ -avoid-version # # List of Libtool shared libraries & loadable modules # HERCLIBS = HERCLIBS2 = libhercs.la \ libhercu.la \ libherct.la \ libhercd.la \ libherc.la HERCMODS = dyngui.la \ dyninst.la \ hdteq.la \ hdt1403.la \ hdt2703.la \ hdt3705.la \ hdt3088.la \ hdt3270.la \ hdt3420.la \ hdt3505.la \ hdt2880.la \ hdt3525.la \ hdtqeth.la \ hdt1052c.la @OPTION_DYNAMIC_LOAD_TRUE@modexec_LTLIBRARIES = $(HERCMODS) noinst_LTLIBRARIES = $(HERCLIBS) lib_LTLIBRARIES = $(HERCLIBS2) # # For each module: # # ModuleName_la_SOURCES = # ModuleName_la_LDFLAGS = $(DYNMOD_LD_FLAGS) (see above) # ModuleName_la_LIBADD = libherc.la (the Core Hercules Shared Library) # ModuleName_la_DEPENDENCIES = libherc.la (may not be necessary) # @OPTION_DYNAMIC_LOAD_TRUE@dyngui_la_SOURCES = dyngui.c @OPTION_DYNAMIC_LOAD_TRUE@dyngui_la_LDFLAGS = $(DYNMOD_LD_FLAGS) @OPTION_DYNAMIC_LOAD_TRUE@dyngui_la_LIBADD = $(DYNMOD_LD_ADD) @OPTION_DYNAMIC_LOAD_TRUE@dyninst_la_SOURCES = dyninst.c @OPTION_DYNAMIC_LOAD_TRUE@dyninst_la_LDFLAGS = $(DYNMOD_LD_FLAGS) @OPTION_DYNAMIC_LOAD_TRUE@dyninst_la_LIBADD = $(DYNMOD_LD_ADD) @OPTION_DYNAMIC_LOAD_TRUE@hdteq_la_SOURCES = hdteq.c @OPTION_DYNAMIC_LOAD_TRUE@hdteq_la_LDFLAGS = $(DYNMOD_LD_FLAGS) @OPTION_DYNAMIC_LOAD_TRUE@hdteq_la_LIBADD = $(DYNMOD_LD_ADD) @OPTION_DYNAMIC_LOAD_TRUE@hdt1403_la_SOURCES = printer.c sockdev.c @OPTION_DYNAMIC_LOAD_TRUE@hdt1403_la_LDFLAGS = $(DYNMOD_LD_FLAGS) @OPTION_DYNAMIC_LOAD_TRUE@hdt1403_la_LIBADD = $(DYNMOD_LD_ADD) @OPTION_DYNAMIC_LOAD_TRUE@hdt2880_la_SOURCES = hchan.c @OPTION_DYNAMIC_LOAD_TRUE@hdt2880_la_LDFLAGS = $(DYNMOD_LD_FLAGS) @OPTION_DYNAMIC_LOAD_TRUE@hdt2880_la_LIBADD = $(DYNMOD_LD_ADD) @OPTION_DYNAMIC_LOAD_TRUE@hdt2703_la_SOURCES = commadpt.c @OPTION_DYNAMIC_LOAD_TRUE@hdt2703_la_LDFLAGS = $(DYNMOD_LD_FLAGS) @OPTION_DYNAMIC_LOAD_TRUE@hdt2703_la_LIBADD = $(DYNMOD_LD_ADD) @OPTION_DYNAMIC_LOAD_TRUE@hdt3705_la_SOURCES = comm3705.c @OPTION_DYNAMIC_LOAD_TRUE@hdt3705_la_LDFLAGS = $(DYNMOD_LD_FLAGS) @OPTION_DYNAMIC_LOAD_TRUE@hdt3705_la_LIBADD = $(DYNMOD_LD_ADD) @OPTION_DYNAMIC_LOAD_TRUE@hdt3088_la_SOURCES = ctc_lcs.c ctc_ctci.c ctcadpt.c w32ctca.c tuntap.c @OPTION_DYNAMIC_LOAD_TRUE@hdt3088_la_LDFLAGS = $(DYNMOD_LD_FLAGS) @OPTION_DYNAMIC_LOAD_TRUE@hdt3088_la_LIBADD = $(DYNMOD_LD_ADD) @OPTION_DYNAMIC_LOAD_TRUE@hdt3270_la_SOURCES = console.c @OPTION_DYNAMIC_LOAD_TRUE@hdt3270_la_LDFLAGS = $(DYNMOD_LD_FLAGS) @OPTION_DYNAMIC_LOAD_TRUE@hdt3270_la_LIBADD = $(DYNMOD_LD_ADD) @OPTION_DYNAMIC_LOAD_TRUE@hdt3420_la_SOURCES = tapedev.c tapeccws.c awstape.c faketape.c hettape.c omatape.c scsitape.c w32stape.c @OPTION_DYNAMIC_LOAD_TRUE@hdt3420_la_LDFLAGS = $(DYNMOD_LD_FLAGS) @OPTION_DYNAMIC_LOAD_TRUE@hdt3420_la_LIBADD = $(DYNMOD_LD_ADD) libherct.la @OPTION_DYNAMIC_LOAD_TRUE@hdt3505_la_SOURCES = cardrdr.c sockdev.c @OPTION_DYNAMIC_LOAD_TRUE@hdt3505_la_LDFLAGS = $(DYNMOD_LD_FLAGS) @OPTION_DYNAMIC_LOAD_TRUE@hdt3505_la_LIBADD = $(DYNMOD_LD_ADD) @OPTION_DYNAMIC_LOAD_TRUE@hdt3525_la_SOURCES = cardpch.c @OPTION_DYNAMIC_LOAD_TRUE@hdt3525_la_LDFLAGS = $(DYNMOD_LD_FLAGS) @OPTION_DYNAMIC_LOAD_TRUE@hdt3525_la_LIBADD = $(DYNMOD_LD_ADD) @OPTION_DYNAMIC_LOAD_TRUE@hdtqeth_la_SOURCES = qeth.c @OPTION_DYNAMIC_LOAD_TRUE@hdtqeth_la_LDFLAGS = $(DYNMOD_LD_FLAGS) @OPTION_DYNAMIC_LOAD_TRUE@hdtqeth_la_LIBADD = $(DYNMOD_LD_ADD) @OPTION_DYNAMIC_LOAD_TRUE@hdt1052c_la_SOURCES = con1052c.c @OPTION_DYNAMIC_LOAD_TRUE@hdt1052c_la_LDFLAGS = $(DYNMOD_LD_FLAGS) @OPTION_DYNAMIC_LOAD_TRUE@hdt1052c_la_LIBADD = $(DYNMOD_LD_ADD) # # Common data areas (shared) library # libhercs_la_SOURCES = hsys.c libhercs_la_LDFLAGS = $(LIB_LD_FLAGS) libhercs_la_LIBADD = $(LDADD) # # Tape utility subroutines (shared) library # libherct_la_SOURCES = sllib.c \ hetlib.c libherct_la_LDFLAGS = $(LIB_LD_FLAGS) libherct_la_LIBADD = $(LDADD) libhercs.la libhercu.la # # DASD utility subroutines (shared) library # libhercd_la_SOURCES = ckddasd.c \ fbadasd.c \ cckddasd.c \ cckdutil.c \ dasdtab.c \ cache.c \ dasdutil.c \ shared.c libhercd_la_LDFLAGS = $(LIB_LD_FLAGS) libhercd_la_LIBADD = $(LDADD) libhercs.la libhercu.la # # libhercu_la_SOURCES = version.c \ hscutl.c \ hscutl2.c \ codepage.c \ logger.c \ logmsg.c \ hdl.c \ hostinfo.c \ hsocket.c \ memrchr.c \ parser.c \ pttrace.c \ $(FTHREADS) \ $(FISHHANG) \ $(LTDL) libhercu_la_LDFLAGS = $(LIB_LD_FLAGS) libhercu_la_LIBADD = $(LDADD) libhercs.la # # Core Hercules (shared) library # libherc_la_SOURCES = hconsole.c \ w32util.c \ strsignal.c \ impl.c \ config.c \ bldcfg.c \ panel.c \ history.c \ fillfnam.c \ ipl.c \ assist.c \ dat.c \ stack.c \ cpu.c \ vstore.c \ general1.c \ general2.c \ general3.c \ pfpo.c \ plo.c \ control.c \ crypto.c \ io.c \ decimal.c \ service.c \ scedasd.c \ losc.c \ chsc.c \ opcode.c \ diagnose.c \ diagmssf.c \ vm.c \ vmd250.c \ channel.c \ external.c \ float.c \ trace.c \ machchk.c \ vector.c \ xstore.c \ cmpsc.c \ sie.c \ qdio.c \ clock.c \ timer.c \ esame.c \ ieee.c \ dfp.c \ machdep.h \ httpserv.c \ cgibin.c \ loadparm.c \ hsccmd.c \ cmdtab.c \ hao.c \ hscmisc.c \ sr.c \ $(FISHIO) \ $(DYNSRC) \ ecpsvm.c EXTRA_libherc_la_SOURCES = $(fthreads_SRC) \ $(fishhang_SRC) \ $(fishio_SRC) \ memrchr.c \ $(dynamic_SRC) \ $(extra_SRC) \ $(dyndev_SRC) \ ltdl.c libherc_la_LDFLAGS = $(LIB_LD_FLAGS) libherc_la_LIBADD = libhercs.la \ libhercu.la \ libherct.la \ libhercd.la \ decNumber/libdecNumber.la \ $(LDADD) @BUILD_SHARED_FALSE@@OPTION_DYNAMIC_LOAD_TRUE@HLDFLAGS = -dlopen self \ @BUILD_SHARED_FALSE@@OPTION_DYNAMIC_LOAD_TRUE@ -dlopen dyngui.la \ @BUILD_SHARED_FALSE@@OPTION_DYNAMIC_LOAD_TRUE@ -dlopen dyninst.la \ @BUILD_SHARED_FALSE@@OPTION_DYNAMIC_LOAD_TRUE@ -dlopen hdteq.la \ @BUILD_SHARED_FALSE@@OPTION_DYNAMIC_LOAD_TRUE@ -dlopen hdt1403.la \ @BUILD_SHARED_FALSE@@OPTION_DYNAMIC_LOAD_TRUE@ -dlopen hdt3420.la \ @BUILD_SHARED_FALSE@@OPTION_DYNAMIC_LOAD_TRUE@ -dlopen hdt2703.la \ @BUILD_SHARED_FALSE@@OPTION_DYNAMIC_LOAD_TRUE@ -dlopen hdt3705.la \ @BUILD_SHARED_FALSE@@OPTION_DYNAMIC_LOAD_TRUE@ -dlopen hdt3088.la \ @BUILD_SHARED_FALSE@@OPTION_DYNAMIC_LOAD_TRUE@ -dlopen hdt3270.la \ @BUILD_SHARED_FALSE@@OPTION_DYNAMIC_LOAD_TRUE@ -dlopen hdt3505.la \ @BUILD_SHARED_FALSE@@OPTION_DYNAMIC_LOAD_TRUE@ -dlopen hdt3525.la \ @BUILD_SHARED_FALSE@@OPTION_DYNAMIC_LOAD_TRUE@ -dlopen hdtqeth.la \ @BUILD_SHARED_FALSE@@OPTION_DYNAMIC_LOAD_TRUE@ -dlopen hdt1052c.la # # THIS is the hercules executable. # hdlmain.c is requires so that dlopen(self) retrieves # the 'main' hdl symbols # @BUILD_SHARED_TRUE@@OPTION_DYNAMIC_LOAD_TRUE@HLDFLAGS = -dlopen self @OPTION_DYNAMIC_LOAD_FALSE@HLDFLAGS = @BUILD_SHARED_FALSE@@OPTION_DYNAMIC_LOAD_TRUE@HDEPS = dyngui.la \ @BUILD_SHARED_FALSE@@OPTION_DYNAMIC_LOAD_TRUE@ dyninst.la \ @BUILD_SHARED_FALSE@@OPTION_DYNAMIC_LOAD_TRUE@ hdteq.la \ @BUILD_SHARED_FALSE@@OPTION_DYNAMIC_LOAD_TRUE@ hdt1403.la \ @BUILD_SHARED_FALSE@@OPTION_DYNAMIC_LOAD_TRUE@ hdt3420.la \ @BUILD_SHARED_FALSE@@OPTION_DYNAMIC_LOAD_TRUE@ hdt2703.la \ @BUILD_SHARED_FALSE@@OPTION_DYNAMIC_LOAD_TRUE@ hdt3705.la \ @BUILD_SHARED_FALSE@@OPTION_DYNAMIC_LOAD_TRUE@ hdt3088.la \ @BUILD_SHARED_FALSE@@OPTION_DYNAMIC_LOAD_TRUE@ hdt3270.la \ @BUILD_SHARED_FALSE@@OPTION_DYNAMIC_LOAD_TRUE@ hdt3505.la \ @BUILD_SHARED_FALSE@@OPTION_DYNAMIC_LOAD_TRUE@ hdt3525.la \ @BUILD_SHARED_FALSE@@OPTION_DYNAMIC_LOAD_TRUE@ hdtqeth.la \ @BUILD_SHARED_FALSE@@OPTION_DYNAMIC_LOAD_TRUE@ hdt1052c.la \ @BUILD_SHARED_FALSE@@OPTION_DYNAMIC_LOAD_TRUE@ libherc.la \ @BUILD_SHARED_FALSE@@OPTION_DYNAMIC_LOAD_TRUE@ libherct.la \ @BUILD_SHARED_FALSE@@OPTION_DYNAMIC_LOAD_TRUE@ libhercd.la @BUILD_SHARED_TRUE@@OPTION_DYNAMIC_LOAD_TRUE@HDEPS = @OPTION_DYNAMIC_LOAD_FALSE@HDEPS = hercules_SOURCES = bootstrap.c \ hdlmain.c hercules_LDADD = libherc.la libhercs.la $(LDADD) hercules_LDFLAGS = $(HLDFLAGS) hercules_DEPENDENCIES = libherc.la libhercs.la $(HDEPS) @BUILD_SHARED_TRUE@herclin_SOURCES = herclin.c hdlmain.c @BUILD_SHARED_TRUE@herclin_LDADD = libherc.la libhercs.la $(LDADD) @BUILD_SHARED_TRUE@herclin_LDFLAGS = $(HLDFLAGS) @BUILD_SHARED_TRUE@herclin_DEPENDENCIES = libherc.la libhercs.la $(HDEPS) # # side binaries # tools_LD_FLAGS = tools_ADDLIBS = $(HERCLIBS2) $(LDADD) @BUILD_HERCIFC_TRUE@hercifc_SOURCES = hercifc.c @BUILD_HERCIFC_TRUE@hercifc_LDADD = $(tools_ADDLIBS) @BUILD_HERCIFC_TRUE@hercifc_LDFLAGS = $(tools_LD_FLAGS) dasdinit_SOURCES = dasdinit.c dasdinit_LDADD = $(tools_ADDLIBS) dasdinit_LDFLAGS = $(tools_LD_FLAGS) dasdisup_SOURCES = dasdisup.c dasdisup_LDADD = $(tools_ADDLIBS) dasdisup_LDFLAGS = $(tools_LD_FLAGS) dasdload_SOURCES = dasdload.c dasdload_LDADD = $(tools_ADDLIBS) dasdload_LDFLAGS = $(tools_LD_FLAGS) dasdconv_SOURCES = dasdconv.c dasdconv_LDADD = $(tools_ADDLIBS) dasdconv_LDFLAGS = $(tools_LD_FLAGS) dasdls_SOURCES = dasdls.c dasdls_LDADD = $(tools_ADDLIBS) dasdls_LDFLAGS = $(tools_LD_FLAGS) dasdcat_SOURCES = dasdcat.c dasdcat_LDADD = $(tools_ADDLIBS) dasdcat_LDFLAGS = $(tools_LD_FLAGS) dasdpdsu_SOURCES = dasdpdsu.c dasdpdsu_LDADD = $(tools_ADDLIBS) dasdpdsu_LDFLAGS = $(tools_LD_FLAGS) dasdseq_SOURCES = dasdseq.c dasdseq_LDADD = $(tools_ADDLIBS) dasdseq_LDFLAGS = $(tools_LD_FLAGS) tapecopy_SOURCES = tapecopy.c tapecopy_LDADD = $(tools_ADDLIBS) tapecopy_LDFLAGS = $(tools_LD_FLAGS) tapemap_SOURCES = tapemap.c tapemap_LDADD = $(tools_ADDLIBS) tapemap_LDFLAGS = $(tools_LD_FLAGS) tapesplt_SOURCES = tapesplt.c tapesplt_LDADD = $(tools_ADDLIBS) tapesplt_LDFLAGS = $(tools_LD_FLAGS) cckdcdsk_SOURCES = cckdcdsk.c cckdcdsk_LDADD = $(tools_ADDLIBS) cckdcdsk_LDFLAGS = $(tools_LD_FLAGS) cckdcomp_SOURCES = cckdcomp.c cckdcomp_LDADD = $(tools_ADDLIBS) cckdcomp_LDFLAGS = $(tools_LD_FLAGS) cckddiag_SOURCES = cckddiag.c cckddiag_LDADD = $(tools_ADDLIBS) cckddiag_LDFLAGS = $(tools_LD_FLAGS) dasdcopy_SOURCES = dasdcopy.c dasdcopy_LDADD = $(tools_ADDLIBS) dasdcopy_LDFLAGS = $(tools_LD_FLAGS) cckdswap_SOURCES = cckdswap.c cckdswap_LDADD = $(tools_ADDLIBS) cckdswap_LDFLAGS = $(tools_LD_FLAGS) hetget_SOURCES = hetget.c hetget_LDADD = $(tools_ADDLIBS) hetget_LDFLAGS = $(tools_LD_FLAGS) hetinit_SOURCES = hetinit.c hetinit_LDADD = $(tools_ADDLIBS) hetinit_LDFLAGS = $(tools_LD_FLAGS) hetmap_SOURCES = hetmap.c hetmap_LDADD = $(tools_ADDLIBS) hetmap_LDFLAGS = $(tools_LD_FLAGS) hetupd_SOURCES = hetupd.c hetupd_LDADD = $(tools_ADDLIBS) hetupd_LDFLAGS = $(tools_LD_FLAGS) dmap2hrc_SOURCES = dmap2hrc.c dmap2hrc_LDADD = $(tools_ADDLIBS) dmap2hrc_LDFLAGS = $(tools_LD_FLAGS) # # files that are not 'built' per-se # # # Also contains some WIN32 only source files # EXTRA_DIST = autoconf/config.rpath \ autoconf/mkinstalldirs \ COPYRIGHT \ hercules.cnf \ cckdfix.c \ README.COMMADPT \ README.CVS \ README.DYNMOD \ README.ECPSVM \ README.HAO \ README.HDL \ README.ISSUES \ README.MINGW \ README.NETWORKING \ README.OSX \ README.TAPE \ README.HERCLOGO \ CHANGES \ RELEASE.NOTES \ README.MSVC \ README.SUN \ _TODO.txt \ makefile.msvc \ makefile-dllmod.msvc \ msvc.makefile.includes/BZIP2_DIR.msvc \ msvc.makefile.includes/BZIP2_FLAGS.msvc \ msvc.makefile.includes/BZIP2_RULES.msvc \ msvc.makefile.includes/CONFIG.msvc \ msvc.makefile.includes/DEBUG_RETAIL.msvc \ msvc.makefile.includes/HERC_FLAGS.msvc \ msvc.makefile.includes/MOD_RULES1.msvc \ msvc.makefile.includes/MOD_RULES2.msvc \ msvc.makefile.includes/MODULES.msvc \ msvc.makefile.includes/OBJ_CODE.msvc \ msvc.makefile.includes/OUTDIR_RULES.msvc \ msvc.makefile.includes/OUTPUT_DIRS.msvc \ msvc.makefile.includes/PCRE_DIR.msvc \ msvc.makefile.includes/PCRE_FLAGS.msvc \ msvc.makefile.includes/PCRE_RULES.msvc \ msvc.makefile.includes/PRIM_RULES.msvc \ msvc.makefile.includes/VERSION.msvc \ msvc.makefile.includes/ZLIB_DIR.msvc \ msvc.makefile.includes/ZLIB_FLAGS.msvc \ msvc.makefile.includes/ZLIB_RULES.msvc \ makefile.bat \ dynmake.bat \ Hercules.dsp \ Hercules.dsw \ Hercules.vcproj \ Hercules.sln \ hercver.rc \ build_pch.c \ conspawn.c \ getopt.c \ herclogo.txt \ hercules.ico # # Source Header files. No 'build' for those # noinst_HEADERS = fishhang.h \ hostinfo.h \ cpuint.h \ feat370.h \ feat390.h \ feat900.h \ featall.h \ featchk.h \ feature.h \ esa390.h \ opcode.h \ clock.h \ hercules.h \ inline.h \ dat.h \ vstore.h \ hbyteswp.h \ dasdblks.h \ hetlib.h \ version.h \ parser.h \ dasdtab.h \ sllib.h \ htypes.h \ fthreads.h \ w32chan.h \ w32ctca.h \ tt32api.h \ linklist.h \ ieee-w32.h \ httpmisc.h \ devtype.h \ codepage.h \ ctcadpt.h \ hercifc.h \ tuntap.h \ tapedev.h \ scsitape.h \ logger.h \ commadpt.h \ comm3705.h \ cache.h \ ecpsvm.h \ memrchr.h \ shared.h \ hscutl.h \ cmdtab.h \ hdl.h \ crypto.h \ sockdev.h \ ltdl.h \ herc_getopt.h \ service.h \ chsc.h \ pttrace.h \ history.h \ sr.h \ hchan.h \ fillfnam.h \ hthreads.h \ hostopts.h \ w32util.h \ hconsts.h \ hmacros.h \ hstructs.h \ hexterns.h \ hconsole.h \ hextapi.h \ hstdinc.h \ hstdint.h \ hsocket.h \ w32stape.h \ w32dl.h \ hercwind.h \ getopt.h \ w32mtio.h \ vmd250.h \ $(extra_dynamic_SRC) all: config.h $(MAKE) $(AM_MAKEFLAGS) all-recursive .SUFFIXES: .SUFFIXES: .c .lo .o .obj am--refresh: @: $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ echo ' cd $(srcdir) && $(AUTOMAKE) --foreign '; \ cd $(srcdir) && $(AUTOMAKE) --foreign \ && exit 0; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \ cd $(top_srcdir) && \ $(AUTOMAKE) --foreign Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ echo ' $(SHELL) ./config.status'; \ $(SHELL) ./config.status;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) $(SHELL) ./config.status --recheck $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(srcdir) && $(AUTOCONF) $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) config.h: stamp-h1 @if test ! -f $@; then \ rm -f stamp-h1; \ $(MAKE) stamp-h1; \ else :; fi stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status @rm -f stamp-h1 cd $(top_builddir) && $(SHELL) ./config.status config.h $(srcdir)/config.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_srcdir) && $(AUTOHEADER) rm -f stamp-h1 touch $@ distclean-hdr: -rm -f config.h stamp-h1 install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) test -z "$(libdir)" || $(mkdir_p) "$(DESTDIR)$(libdir)" @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ if test -f $$p; then \ f=$(am__strip_dir) \ echo " $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(libdir)/$$f"; \ else :; fi; \ done uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @set -x; list='$(lib_LTLIBRARIES)'; for p in $$list; do \ p=$(am__strip_dir) \ echo " $(LIBTOOL) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$p'"; \ $(LIBTOOL) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$p"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ test "$$dir" != "$$p" || dir=.; \ echo "rm -f \"$${dir}/so_locations\""; \ rm -f "$${dir}/so_locations"; \ done install-modexecLTLIBRARIES: $(modexec_LTLIBRARIES) @$(NORMAL_INSTALL) test -z "$(modexecdir)" || $(mkdir_p) "$(DESTDIR)$(modexecdir)" @list='$(modexec_LTLIBRARIES)'; for p in $$list; do \ if test -f $$p; then \ f=$(am__strip_dir) \ echo " $(LIBTOOL) --mode=install $(modexecLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(modexecdir)/$$f'"; \ $(LIBTOOL) --mode=install $(modexecLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(modexecdir)/$$f"; \ else :; fi; \ done uninstall-modexecLTLIBRARIES: @$(NORMAL_UNINSTALL) @set -x; list='$(modexec_LTLIBRARIES)'; for p in $$list; do \ p=$(am__strip_dir) \ echo " $(LIBTOOL) --mode=uninstall rm -f '$(DESTDIR)$(modexecdir)/$$p'"; \ $(LIBTOOL) --mode=uninstall rm -f "$(DESTDIR)$(modexecdir)/$$p"; \ done clean-modexecLTLIBRARIES: -test -z "$(modexec_LTLIBRARIES)" || rm -f $(modexec_LTLIBRARIES) @list='$(modexec_LTLIBRARIES)'; for p in $$list; do \ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ test "$$dir" != "$$p" || dir=.; \ echo "rm -f \"$${dir}/so_locations\""; \ rm -f "$${dir}/so_locations"; \ done clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ test "$$dir" != "$$p" || dir=.; \ echo "rm -f \"$${dir}/so_locations\""; \ rm -f "$${dir}/so_locations"; \ done dyngui.la: $(dyngui_la_OBJECTS) $(dyngui_la_DEPENDENCIES) $(LINK) $(am_dyngui_la_rpath) $(dyngui_la_LDFLAGS) $(dyngui_la_OBJECTS) $(dyngui_la_LIBADD) $(LIBS) dyninst.la: $(dyninst_la_OBJECTS) $(dyninst_la_DEPENDENCIES) $(LINK) $(am_dyninst_la_rpath) $(dyninst_la_LDFLAGS) $(dyninst_la_OBJECTS) $(dyninst_la_LIBADD) $(LIBS) hdt1052c.la: $(hdt1052c_la_OBJECTS) $(hdt1052c_la_DEPENDENCIES) $(LINK) $(am_hdt1052c_la_rpath) $(hdt1052c_la_LDFLAGS) $(hdt1052c_la_OBJECTS) $(hdt1052c_la_LIBADD) $(LIBS) hdt1403.la: $(hdt1403_la_OBJECTS) $(hdt1403_la_DEPENDENCIES) $(LINK) $(am_hdt1403_la_rpath) $(hdt1403_la_LDFLAGS) $(hdt1403_la_OBJECTS) $(hdt1403_la_LIBADD) $(LIBS) hdt2703.la: $(hdt2703_la_OBJECTS) $(hdt2703_la_DEPENDENCIES) $(LINK) $(am_hdt2703_la_rpath) $(hdt2703_la_LDFLAGS) $(hdt2703_la_OBJECTS) $(hdt2703_la_LIBADD) $(LIBS) hdt2880.la: $(hdt2880_la_OBJECTS) $(hdt2880_la_DEPENDENCIES) $(LINK) $(am_hdt2880_la_rpath) $(hdt2880_la_LDFLAGS) $(hdt2880_la_OBJECTS) $(hdt2880_la_LIBADD) $(LIBS) hdt3088.la: $(hdt3088_la_OBJECTS) $(hdt3088_la_DEPENDENCIES) $(LINK) $(am_hdt3088_la_rpath) $(hdt3088_la_LDFLAGS) $(hdt3088_la_OBJECTS) $(hdt3088_la_LIBADD) $(LIBS) hdt3270.la: $(hdt3270_la_OBJECTS) $(hdt3270_la_DEPENDENCIES) $(LINK) $(am_hdt3270_la_rpath) $(hdt3270_la_LDFLAGS) $(hdt3270_la_OBJECTS) $(hdt3270_la_LIBADD) $(LIBS) hdt3420.la: $(hdt3420_la_OBJECTS) $(hdt3420_la_DEPENDENCIES) $(LINK) $(am_hdt3420_la_rpath) $(hdt3420_la_LDFLAGS) $(hdt3420_la_OBJECTS) $(hdt3420_la_LIBADD) $(LIBS) hdt3505.la: $(hdt3505_la_OBJECTS) $(hdt3505_la_DEPENDENCIES) $(LINK) $(am_hdt3505_la_rpath) $(hdt3505_la_LDFLAGS) $(hdt3505_la_OBJECTS) $(hdt3505_la_LIBADD) $(LIBS) hdt3525.la: $(hdt3525_la_OBJECTS) $(hdt3525_la_DEPENDENCIES) $(LINK) $(am_hdt3525_la_rpath) $(hdt3525_la_LDFLAGS) $(hdt3525_la_OBJECTS) $(hdt3525_la_LIBADD) $(LIBS) hdt3705.la: $(hdt3705_la_OBJECTS) $(hdt3705_la_DEPENDENCIES) $(LINK) $(am_hdt3705_la_rpath) $(hdt3705_la_LDFLAGS) $(hdt3705_la_OBJECTS) $(hdt3705_la_LIBADD) $(LIBS) hdteq.la: $(hdteq_la_OBJECTS) $(hdteq_la_DEPENDENCIES) $(LINK) $(am_hdteq_la_rpath) $(hdteq_la_LDFLAGS) $(hdteq_la_OBJECTS) $(hdteq_la_LIBADD) $(LIBS) hdtqeth.la: $(hdtqeth_la_OBJECTS) $(hdtqeth_la_DEPENDENCIES) $(LINK) $(am_hdtqeth_la_rpath) $(hdtqeth_la_LDFLAGS) $(hdtqeth_la_OBJECTS) $(hdtqeth_la_LIBADD) $(LIBS) libherc.la: $(libherc_la_OBJECTS) $(libherc_la_DEPENDENCIES) $(LINK) -rpath $(libdir) $(libherc_la_LDFLAGS) $(libherc_la_OBJECTS) $(libherc_la_LIBADD) $(LIBS) libhercd.la: $(libhercd_la_OBJECTS) $(libhercd_la_DEPENDENCIES) $(LINK) -rpath $(libdir) $(libhercd_la_LDFLAGS) $(libhercd_la_OBJECTS) $(libhercd_la_LIBADD) $(LIBS) libhercs.la: $(libhercs_la_OBJECTS) $(libhercs_la_DEPENDENCIES) $(LINK) -rpath $(libdir) $(libhercs_la_LDFLAGS) $(libhercs_la_OBJECTS) $(libhercs_la_LIBADD) $(LIBS) libherct.la: $(libherct_la_OBJECTS) $(libherct_la_DEPENDENCIES) $(LINK) -rpath $(libdir) $(libherct_la_LDFLAGS) $(libherct_la_OBJECTS) $(libherct_la_LIBADD) $(LIBS) libhercu.la: $(libhercu_la_OBJECTS) $(libhercu_la_DEPENDENCIES) $(LINK) -rpath $(libdir) $(libhercu_la_LDFLAGS) $(libhercu_la_OBJECTS) $(libhercu_la_LIBADD) $(LIBS) install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) test -z "$(bindir)" || $(mkdir_p) "$(DESTDIR)$(bindir)" @list='$(bin_PROGRAMS)'; for p in $$list; do \ p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ if test -f $$p \ || test -f $$p1 \ ; then \ f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; \ else :; fi; \ done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; for p in $$list; do \ f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \ rm -f "$(DESTDIR)$(bindir)/$$f"; \ done clean-binPROGRAMS: @list='$(bin_PROGRAMS)'; for p in $$list; do \ f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ echo " rm -f $$p $$f"; \ rm -f $$p $$f ; \ done cckdcdsk$(EXEEXT): $(cckdcdsk_OBJECTS) $(cckdcdsk_DEPENDENCIES) @rm -f cckdcdsk$(EXEEXT) $(LINK) $(cckdcdsk_LDFLAGS) $(cckdcdsk_OBJECTS) $(cckdcdsk_LDADD) $(LIBS) cckdcomp$(EXEEXT): $(cckdcomp_OBJECTS) $(cckdcomp_DEPENDENCIES) @rm -f cckdcomp$(EXEEXT) $(LINK) $(cckdcomp_LDFLAGS) $(cckdcomp_OBJECTS) $(cckdcomp_LDADD) $(LIBS) cckddiag$(EXEEXT): $(cckddiag_OBJECTS) $(cckddiag_DEPENDENCIES) @rm -f cckddiag$(EXEEXT) $(LINK) $(cckddiag_LDFLAGS) $(cckddiag_OBJECTS) $(cckddiag_LDADD) $(LIBS) cckdswap$(EXEEXT): $(cckdswap_OBJECTS) $(cckdswap_DEPENDENCIES) @rm -f cckdswap$(EXEEXT) $(LINK) $(cckdswap_LDFLAGS) $(cckdswap_OBJECTS) $(cckdswap_LDADD) $(LIBS) dasdcat$(EXEEXT): $(dasdcat_OBJECTS) $(dasdcat_DEPENDENCIES) @rm -f dasdcat$(EXEEXT) $(LINK) $(dasdcat_LDFLAGS) $(dasdcat_OBJECTS) $(dasdcat_LDADD) $(LIBS) dasdconv$(EXEEXT): $(dasdconv_OBJECTS) $(dasdconv_DEPENDENCIES) @rm -f dasdconv$(EXEEXT) $(LINK) $(dasdconv_LDFLAGS) $(dasdconv_OBJECTS) $(dasdconv_LDADD) $(LIBS) dasdcopy$(EXEEXT): $(dasdcopy_OBJECTS) $(dasdcopy_DEPENDENCIES) @rm -f dasdcopy$(EXEEXT) $(LINK) $(dasdcopy_LDFLAGS) $(dasdcopy_OBJECTS) $(dasdcopy_LDADD) $(LIBS) dasdinit$(EXEEXT): $(dasdinit_OBJECTS) $(dasdinit_DEPENDENCIES) @rm -f dasdinit$(EXEEXT) $(LINK) $(dasdinit_LDFLAGS) $(dasdinit_OBJECTS) $(dasdinit_LDADD) $(LIBS) dasdisup$(EXEEXT): $(dasdisup_OBJECTS) $(dasdisup_DEPENDENCIES) @rm -f dasdisup$(EXEEXT) $(LINK) $(dasdisup_LDFLAGS) $(dasdisup_OBJECTS) $(dasdisup_LDADD) $(LIBS) dasdload$(EXEEXT): $(dasdload_OBJECTS) $(dasdload_DEPENDENCIES) @rm -f dasdload$(EXEEXT) $(LINK) $(dasdload_LDFLAGS) $(dasdload_OBJECTS) $(dasdload_LDADD) $(LIBS) dasdls$(EXEEXT): $(dasdls_OBJECTS) $(dasdls_DEPENDENCIES) @rm -f dasdls$(EXEEXT) $(LINK) $(dasdls_LDFLAGS) $(dasdls_OBJECTS) $(dasdls_LDADD) $(LIBS) dasdpdsu$(EXEEXT): $(dasdpdsu_OBJECTS) $(dasdpdsu_DEPENDENCIES) @rm -f dasdpdsu$(EXEEXT) $(LINK) $(dasdpdsu_LDFLAGS) $(dasdpdsu_OBJECTS) $(dasdpdsu_LDADD) $(LIBS) dasdseq$(EXEEXT): $(dasdseq_OBJECTS) $(dasdseq_DEPENDENCIES) @rm -f dasdseq$(EXEEXT) $(LINK) $(dasdseq_LDFLAGS) $(dasdseq_OBJECTS) $(dasdseq_LDADD) $(LIBS) dmap2hrc$(EXEEXT): $(dmap2hrc_OBJECTS) $(dmap2hrc_DEPENDENCIES) @rm -f dmap2hrc$(EXEEXT) $(LINK) $(dmap2hrc_LDFLAGS) $(dmap2hrc_OBJECTS) $(dmap2hrc_LDADD) $(LIBS) hercifc$(EXEEXT): $(hercifc_OBJECTS) $(hercifc_DEPENDENCIES) @rm -f hercifc$(EXEEXT) $(LINK) $(hercifc_LDFLAGS) $(hercifc_OBJECTS) $(hercifc_LDADD) $(LIBS) herclin$(EXEEXT): $(herclin_OBJECTS) $(herclin_DEPENDENCIES) @rm -f herclin$(EXEEXT) $(LINK) $(herclin_LDFLAGS) $(herclin_OBJECTS) $(herclin_LDADD) $(LIBS) hercules$(EXEEXT): $(hercules_OBJECTS) $(hercules_DEPENDENCIES) @rm -f hercules$(EXEEXT) $(LINK) $(hercules_LDFLAGS) $(hercules_OBJECTS) $(hercules_LDADD) $(LIBS) hetget$(EXEEXT): $(hetget_OBJECTS) $(hetget_DEPENDENCIES) @rm -f hetget$(EXEEXT) $(LINK) $(hetget_LDFLAGS) $(hetget_OBJECTS) $(hetget_LDADD) $(LIBS) hetinit$(EXEEXT): $(hetinit_OBJECTS) $(hetinit_DEPENDENCIES) @rm -f hetinit$(EXEEXT) $(LINK) $(hetinit_LDFLAGS) $(hetinit_OBJECTS) $(hetinit_LDADD) $(LIBS) hetmap$(EXEEXT): $(hetmap_OBJECTS) $(hetmap_DEPENDENCIES) @rm -f hetmap$(EXEEXT) $(LINK) $(hetmap_LDFLAGS) $(hetmap_OBJECTS) $(hetmap_LDADD) $(LIBS) hetupd$(EXEEXT): $(hetupd_OBJECTS) $(hetupd_DEPENDENCIES) @rm -f hetupd$(EXEEXT) $(LINK) $(hetupd_LDFLAGS) $(hetupd_OBJECTS) $(hetupd_LDADD) $(LIBS) tapecopy$(EXEEXT): $(tapecopy_OBJECTS) $(tapecopy_DEPENDENCIES) @rm -f tapecopy$(EXEEXT) $(LINK) $(tapecopy_LDFLAGS) $(tapecopy_OBJECTS) $(tapecopy_LDADD) $(LIBS) tapemap$(EXEEXT): $(tapemap_OBJECTS) $(tapemap_DEPENDENCIES) @rm -f tapemap$(EXEEXT) $(LINK) $(tapemap_LDFLAGS) $(tapemap_OBJECTS) $(tapemap_LDADD) $(LIBS) tapesplt$(EXEEXT): $(tapesplt_OBJECTS) $(tapesplt_DEPENDENCIES) @rm -f tapesplt$(EXEEXT) $(LINK) $(tapesplt_LDFLAGS) $(tapesplt_OBJECTS) $(tapesplt_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/assist.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/awstape.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bldcfg.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bootstrap.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cache.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cardpch.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cardrdr.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cckdcdsk.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cckdcomp.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cckddasd.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cckddiag.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cckdswap.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cckdutil.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cgibin.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/channel.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/chsc.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ckddasd.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clock.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmdtab.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmpsc.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/codepage.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/comm3705.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/commadpt.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/con1052c.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/config.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/console.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/control.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/crypto.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ctc_ctci.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ctc_lcs.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ctcadpt.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dasdcat.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dasdconv.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dasdcopy.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dasdinit.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dasdisup.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dasdload.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dasdls.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dasdpdsu.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dasdseq.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dasdtab.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dasdutil.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dat.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/decimal.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dfp.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/diagmssf.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/diagnose.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dmap2hrc.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dyngui.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dyninst.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ecpsvm.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/esame.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/external.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/faketape.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fbadasd.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fillfnam.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fishhang.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/float.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fthreads.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/general1.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/general2.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/general3.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hao.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hchan.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hconsole.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hdl.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hdlmain.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hdteq.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hercifc.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/herclin.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hetget.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hetinit.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hetlib.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hetmap.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hettape.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hetupd.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/history.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hostinfo.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hsccmd.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hscmisc.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hscutl.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hscutl2.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hsocket.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hsys.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/httpserv.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ieee.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/impl.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/io.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipl.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/loadparm.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/logger.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/logmsg.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/losc.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ltdl.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/machchk.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/memrchr.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/omatape.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/opcode.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/panel.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parser.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pfpo.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plo.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/printer.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pttrace.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qdio.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qeth.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/scedasd.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/scsitape.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/service.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/shared.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sie.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sllib.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sockdev.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sr.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stack.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/strsignal.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tapeccws.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tapecopy.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tapedev.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tapemap.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tapesplt.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/timer.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trace.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tuntap.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vector.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/version.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vm.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vmd250.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vstore.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/w32chan.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/w32ctca.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/w32stape.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/w32util.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xstore.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ @am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c $< .c.obj: @am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \ @am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ if $(LTCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ @am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs distclean-libtool: -rm -f libtool uninstall-info-am: # This directory's subdirectories are mostly independent; you can cd # into them and run `make' without going through this Makefile. # To change the values of `make' variables: instead of editing Makefiles, # (1) if the variable is set in `config.status', edit `config.status' # (which will cause the Makefiles to be regenerated when you run `make'); # (2) otherwise, pass the desired values on the `make' command line. $(RECURSIVE_TARGETS): @failcom='exit 1'; \ for f in x $$MAKEFLAGS; do \ case $$f in \ *=* | --[!k]*);; \ *k*) failcom='fail=yes';; \ esac; \ done; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ list='$(SUBDIRS)'; for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" mostlyclean-recursive clean-recursive distclean-recursive \ maintainer-clean-recursive: @failcom='exit 1'; \ for f in x $$MAKEFLAGS; do \ case $$f in \ *=* | --[!k]*);; \ *k*) failcom='fail=yes';; \ esac; \ done; \ dot_seen=no; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ rev=''; for subdir in $$list; do \ if test "$$subdir" = "."; then :; else \ rev="$$subdir $$rev"; \ fi; \ done; \ rev="$$rev ."; \ target=`echo $@ | sed s/-recursive//`; \ for subdir in $$rev; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done && test -z "$$fail" tags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ done ctags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ done ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ mkid -fID $$unique tags: TAGS TAGS: tags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$tags $$unique; \ fi ctags: CTAGS CTAGS: ctags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(CTAGS_ARGS)$$tags$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$tags $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && cd $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) $$here distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) $(am__remove_distdir) mkdir $(distdir) $(mkdir_p) $(distdir)/autoconf $(distdir)/m4 $(distdir)/msvc.makefile.includes $(distdir)/po @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ list='$(DISTFILES)'; for file in $$list; do \ case $$file in \ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ esac; \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ if test "$$dir" != "$$file" && test "$$dir" != "."; then \ dir="/$$dir"; \ $(mkdir_p) "$(distdir)$$dir"; \ else \ dir=''; \ fi; \ if test -d $$d/$$file; then \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ fi; \ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test -d "$(distdir)/$$subdir" \ || $(mkdir_p) "$(distdir)/$$subdir" \ || exit 1; \ distdir=`$(am__cd) $(distdir) && pwd`; \ top_distdir=`$(am__cd) $(top_distdir) && pwd`; \ (cd $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$top_distdir" \ distdir="$$distdir/$$subdir" \ distdir) \ || exit 1; \ fi; \ done -find $(distdir) -type d ! -perm -777 -exec chmod a+rwx {} \; -o \ ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ ! -type d ! -perm -444 -exec $(SHELL) $(install_sh) -c -m a+r {} {} \; \ || chmod -R a+r $(distdir) dist-gzip: distdir tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz $(am__remove_distdir) dist-bzip2: distdir tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2 $(am__remove_distdir) dist-tarZ: distdir tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z $(am__remove_distdir) dist-shar: distdir shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz $(am__remove_distdir) dist-zip: distdir -rm -f $(distdir).zip zip -rq $(distdir).zip $(distdir) $(am__remove_distdir) dist dist-all: distdir tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz $(am__remove_distdir) # This target untars the dist file and tries a VPATH configuration. Then # it guarantees that the distribution is self-contained by making another # tarfile. distcheck: dist case '$(DIST_ARCHIVES)' in \ *.tar.gz*) \ GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | $(am__untar) ;;\ *.tar.bz2*) \ bunzip2 -c $(distdir).tar.bz2 | $(am__untar) ;;\ *.tar.Z*) \ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ *.shar.gz*) \ GZIP=$(GZIP_ENV) gunzip -c $(distdir).shar.gz | unshar ;;\ *.zip*) \ unzip $(distdir).zip ;;\ esac chmod -R a-w $(distdir); chmod a+w $(distdir) mkdir $(distdir)/_build mkdir $(distdir)/_inst chmod a-w $(distdir) dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ && cd $(distdir)/_build \ && ../configure --srcdir=.. --prefix="$$dc_install_base" \ $(DISTCHECK_CONFIGURE_FLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) dvi \ && $(MAKE) $(AM_MAKEFLAGS) check \ && $(MAKE) $(AM_MAKEFLAGS) install \ && $(MAKE) $(AM_MAKEFLAGS) installcheck \ && $(MAKE) $(AM_MAKEFLAGS) uninstall \ && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ distuninstallcheck \ && chmod -R a-w "$$dc_install_base" \ && ({ \ (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ } || { rm -rf "$$dc_destdir"; exit 1; }) \ && rm -rf "$$dc_destdir" \ && $(MAKE) $(AM_MAKEFLAGS) dist \ && rm -rf $(DIST_ARCHIVES) \ && $(MAKE) $(AM_MAKEFLAGS) distcleancheck $(am__remove_distdir) @(echo "$(distdir) archives ready for distribution: "; \ list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ sed -e '1{h;s/./=/g;p;x;}' -e '$${p;x;}' distuninstallcheck: @cd $(distuninstallcheck_dir) \ && test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \ || { echo "ERROR: files left after uninstall:" ; \ if test -n "$(DESTDIR)"; then \ echo " (check DESTDIR support)"; \ fi ; \ $(distuninstallcheck_listfiles) ; \ exit 1; } >&2 distcleancheck: distclean @if test '$(srcdir)' = . ; then \ echo "ERROR: distcleancheck can only run from a VPATH build" ; \ exit 1 ; \ fi @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ || { echo "ERROR: files left in build directory after distclean:" ; \ $(distcleancheck_listfiles) ; \ exit 1; } >&2 check-am: all-am check: check-recursive all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(HEADERS) config.h install-binPROGRAMS: install-libLTLIBRARIES installdirs: installdirs-recursive installdirs-am: for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(modexecdir)" "$(DESTDIR)$(bindir)"; do \ test -z "$$dir" || $(mkdir_p) "$$dir"; \ done install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-binPROGRAMS clean-generic clean-libLTLIBRARIES \ clean-libtool clean-modexecLTLIBRARIES clean-noinstLTLIBRARIES \ mostlyclean-am distclean: distclean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-hdr distclean-libtool distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive info: info-recursive info-am: install-data-am: install-exec-am: install-binPROGRAMS install-exec-local \ install-libLTLIBRARIES install-modexecLTLIBRARIES @$(NORMAL_INSTALL) $(MAKE) $(AM_MAKEFLAGS) install-exec-hook install-info: install-info-recursive install-man: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -rf $(top_srcdir)/autom4te.cache -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: uninstall-binPROGRAMS uninstall-info-am \ uninstall-libLTLIBRARIES uninstall-local \ uninstall-modexecLTLIBRARIES @$(NORMAL_INSTALL) $(MAKE) $(AM_MAKEFLAGS) uninstall-hook uninstall-info: uninstall-info-recursive .PHONY: $(RECURSIVE_TARGETS) CTAGS GTAGS all all-am am--refresh check \ check-am clean clean-binPROGRAMS clean-generic \ clean-libLTLIBRARIES clean-libtool clean-modexecLTLIBRARIES \ clean-noinstLTLIBRARIES clean-recursive ctags ctags-recursive \ dist dist-all dist-bzip2 dist-gzip dist-shar dist-tarZ \ dist-zip distcheck distclean distclean-compile \ distclean-generic distclean-hdr distclean-libtool \ distclean-recursive distclean-tags distcleancheck distdir \ distuninstallcheck dvi dvi-am html html-am info info-am \ install install-am install-binPROGRAMS install-data \ install-data-am install-exec install-exec-am install-exec-hook \ install-exec-local install-info install-info-am \ install-libLTLIBRARIES install-man install-modexecLTLIBRARIES \ install-strip installcheck installcheck-am installdirs \ installdirs-am maintainer-clean maintainer-clean-generic \ maintainer-clean-recursive mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool mostlyclean-recursive \ pdf pdf-am ps ps-am tags tags-recursive uninstall uninstall-am \ uninstall-binPROGRAMS uninstall-hook uninstall-info-am \ uninstall-libLTLIBRARIES uninstall-local \ uninstall-modexecLTLIBRARIES cckd: cckd2ckd$(EXEEXT) \ cckdcdsk$(EXEEXT) \ cckddiag$(EXEEXT) \ cckdcomp$(EXEEXT) \ cckdswap$(EXEEXT) \ dasdcopy$(EXEEXT) ######################################################### # B U I L D R U L E S . . . ######################################################### # # *** PROGRAMMING NOTE! *** # # The tabs in the below statements ARE significant! # Not all make programs accept (handle correctly) # make files that use blanks instead of tabs in their # build rules. Thus in order to remain compatible # with older make programs the below build rules # MUST use *tabs* and NOT BLANKS! # ######################################################### tar: dist install-exec-local: install-exec-hook: @BUILD_SHARED_TRUE@ rm -f $(DESTDIR)$(libdir)/libherc*.a @BUILD_SHARED_TRUE@ rm -f $(DESTDIR)$(modexecdir)/dyn*.a @BUILD_SHARED_TRUE@ rm -f $(DESTDIR)$(modexecdir)/hdt*.a @BUILD_SHARED_FALSE@ rm -f $(DESTDIR)$(libdir)/libherc* # # NOTE : symbolic links point to FINAL destination (not to staged install) # rm -f $(DESTDIR)$(bindir)/fba2cfba$(EXEEXT) (cd $(DESTDIR)$(bindir); @LN_S@ ./dasdcopy$(EXEEXT) fba2cfba$(EXEEXT)) rm -f $(DESTDIR)$(bindir)/ckd2cckd$(EXEEXT) (cd $(DESTDIR)$(bindir); @LN_S@ ./dasdcopy$(EXEEXT) ckd2cckd$(EXEEXT)) rm -f $(DESTDIR)$(bindir)/cfba2fba$(EXEEXT) (cd $(DESTDIR)$(bindir); @LN_S@ ./dasdcopy$(EXEEXT) cfba2fba$(EXEEXT)) rm -f $(DESTDIR)$(bindir)/cckd2ckd$(EXEEXT) (cd $(DESTDIR)$(bindir); @LN_S@ ./dasdcopy$(EXEEXT) cckd2ckd$(EXEEXT)) @SETUID_HERCIFC_TRUE@ chown root $(DESTDIR)$(bindir)/hercifc @HERCIFC_GROUPSET_TRUE@@SETUID_HERCIFC_TRUE@ chgrp $(HERCIFC_GROUPNAME) $(DESTDIR)$(bindir)/hercifc @SETUID_HERCIFC_TRUE@ chmod 0750 $(DESTDIR)$(bindir)/hercifc @SETUID_HERCIFC_TRUE@ chmod +s $(DESTDIR)$(bindir)/hercifc @SETUID_HERCIFC_TRUE@ rm hercifc uninstall-local: uninstall-hook: rm -f $(DESTDIR)$(bindir)/fba2cfba$(EXEEXT) rm -f $(DESTDIR)$(bindir)/ckd2cckd$(EXEEXT) rm -f $(DESTDIR)$(bindir)/cfba2fba$(EXEEXT) rm -f $(DESTDIR)$(bindir)/cckd2ckd$(EXEEXT) %.s: %.c $(COMPILE) -S $< # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: hercules-3.07/makefile.msvc000644 000765 000765 00000000563 11143760543 017422 0ustar00jmaynardjmaynard000000 000000 # *************************************************************************** # MAKEFILE.MSVC (c) Copyright Roger Bowler, 2005 # Build Hercules for Win32 using MSVC and nmake (static link version) # # $Id: makefile.msvc 4102 2006-12-08 09:43:35Z jj $ # # $Log$ # # *************************************************************************** !include makefile-dllmod.msvc hercules-3.07/man/000777 000765 000765 00000000000 11345533276 015533 5ustar00jmaynardjmaynard000000 000000 hercules-3.07/memrchr.c000644 000765 000765 00000001725 11143760543 016555 0ustar00jmaynardjmaynard000000 000000 /************************************************************************/ /* */ /* memrchr Right to Left memory scan */ /* */ /************************************************************************/ // $Id: memrchr.c 4102 2006-12-08 09:43:35Z jj $ // // $Log$ #include "hstdinc.h" #define _MEMRCHR_C_ #define _HUTIL_DLL_ #include "hercules.h" #if !defined( HAVE_MEMRCHR ) #include "memrchr.h" DLL_EXPORT void *memrchr(const void *buf, int c, size_t num) { unsigned char *pMem; if (num == 0) { return NULL; } for (pMem = (unsigned char *) buf + num - 1; pMem >= (unsigned char *) buf; pMem--) { if (*pMem == (unsigned char) c) break; } if (pMem >= (unsigned char *) buf) { return ((void *) pMem); } return NULL; } #endif // !defined(HAVE_MEMRCHR) hercules-3.07/memrchr.h000644 000765 000765 00000002373 11143760543 016562 0ustar00jmaynardjmaynard000000 000000 /************************************************************************/ /* */ /* memrchr -- Right to Left memory scan */ /* */ /* Scans the memory block and reports the last occurrence of */ /* the specified byte in the buffer. Returns a pointer to */ /* the byte if found, or NULL if not found. */ /* */ /************************************************************************/ // $Id: memrchr.h 4102 2006-12-08 09:43:35Z jj $ // // $Log$ #ifndef MEMRCHR_H #define MEMRCHR_H #include "hercules.h" #ifndef _MEMRCHR_C_ #ifndef _HUTIL_DLL_ #define MEM_DLL_IMPORT DLL_IMPORT #else /* _HUTIL_DLL_ */ #define MEM_DLL_IMPORT extern #endif /* _HUTIL_DLL_ */ #else #define MEM_DLL_IMPORT DLL_EXPORT #endif #if !defined(HAVE_MEMRCHR) // (only if we need it) #ifdef __cplusplus extern "C" { #endif /*__cplusplus*/ MEM_DLL_IMPORT void *memrchr(const void *buf, int c, size_t num); #ifdef __cplusplus } #endif /*__cplusplus*/ #endif // !defined(HAVE_MEMRCHR) #endif // MEMRCHR_H hercules-3.07/msvc.makefile.includes/000777 000765 000765 00000000000 11345533273 021306 5ustar00jmaynardjmaynard000000 000000 hercules-3.07/omatape.c000644 000765 000765 00000131721 11321734033 016537 0ustar00jmaynardjmaynard000000 000000 /* OMATAPE.C (c) Copyright Roger Bowler, 1999-2009 */ /* Hercules Tape Device Handler for OMATAPE */ /* Original Author: Roger Bowler */ /* Prime Maintainer: Ivan Warren */ /* Secondary Maintainer: "Fish" (David B. Trout) */ // $Id: omatape.c 5587 2009-12-31 15:05:57Z rbowler $ /*-------------------------------------------------------------------*/ /* This module contains the OMATAPE emulated tape format support. */ /* */ /* The subroutines in this module are called by the general tape */ /* device handler (tapedev.c) when the tape format is OMATAPE. */ /* */ /* Messages issued by this module are prefixed HHCTA2nn */ /*-------------------------------------------------------------------*/ /*-------------------------------------------------------------------*/ /* Reference information: */ /* SC53-1200 S/370 and S/390 Optical Media Attach/2 User's Guide */ /* SC53-1201 S/370 and S/390 Optical Media Attach/2 Technical Ref */ /*-------------------------------------------------------------------*/ #include "hstdinc.h" #include "hercules.h" /* need Hercules control blocks */ #include "tapedev.h" /* Main tape handler header file */ //#define ENABLE_TRACING_STMTS // (Fish: DEBUGGING) #ifdef ENABLE_TRACING_STMTS #if !defined(DEBUG) #warning DEBUG required for ENABLE_TRACING_STMTS #endif // (TRACE, ASSERT, and VERIFY macros are #defined in hmacros.h) #else #undef TRACE #undef ASSERT #undef VERIFY #define TRACE 1 ? ((void)0) : logmsg #define ASSERT(a) #define VERIFY(a) ((void)(a)) #endif /*-------------------------------------------------------------------*/ /* Read the OMA tape descriptor file */ /*-------------------------------------------------------------------*/ int read_omadesc (DEVBLK *dev) { int rc; /* Return code */ int i; /* Array subscript */ int pathlen; /* Length of TDF path name */ int tdfsize; /* Size of TDF file in bytes */ int filecount; /* Number of files */ int stmt; /* TDF file statement number */ int fd; /* TDF file descriptor */ struct stat statbuf; /* TDF file information */ U32 blklen; /* Fixed block length */ int tdfpos; /* Position in TDF buffer */ char *tdfbuf; /* -> TDF file buffer */ char *tdfrec; /* -> TDF record */ char *tdffilenm; /* -> Filename in TDF record */ char *tdfformat; /* -> Format in TDF record */ char *tdfreckwd; /* -> Keyword in TDF record */ char *tdfblklen; /* -> Length in TDF record */ OMATAPE_DESC *tdftab; /* -> Tape descriptor array */ BYTE c; /* Work area for sscanf */ char pathname[MAX_PATH]; /* file path in host format */ /* Isolate the base path name of the TDF file */ for (pathlen = strlen(dev->filename); pathlen > 0; ) { pathlen--; if (dev->filename[pathlen-1] == '/') break; } #if 0 // JCS thinks this is bad if (pathlen < 7 || strncasecmp(dev->filename+pathlen-7, "/tapes/", 7) != 0) { logmsg (_("HHCTA232I %4.4X: Invalid filename %s: " "TDF files must be in the TAPES subdirectory\n"), dev->devnum, dev->filename+pathlen); return -1; } pathlen -= 7; #endif /* Open the tape descriptor file */ hostpath(pathname, dev->filename, sizeof(pathname)); fd = open (pathname, O_RDONLY | O_BINARY); if (fd < 0) { logmsg (_("HHCTA239E %4.4X: Error opening TDF file %s: %s\n"), dev->devnum, dev->filename, strerror(errno)); return -1; } /* Determine the size of the tape descriptor file */ rc = fstat (fd, &statbuf); if (rc < 0) { logmsg (_("HHCTA240E %4.4X: File %s fstat error: %s\n"), dev->devnum, dev->filename, strerror(errno)); close (fd); return -1; } tdfsize = statbuf.st_size; /* Obtain a buffer for the tape descriptor file */ tdfbuf = malloc (tdfsize); if (tdfbuf == NULL) { logmsg (_("HHCTA241E %4.4X: Cannot obtain buffer for TDF file %s: %s\n"), dev->devnum, dev->filename, strerror(errno)); close (fd); return -1; } /* Read the tape descriptor file into the buffer */ rc = read (fd, tdfbuf, tdfsize); if (rc < tdfsize) { logmsg (_("HHCTA242E %4.4X: Error reading TDF file %s: %s\n"), dev->devnum, dev->filename, strerror(errno)); free (tdfbuf); close (fd); return -1; } /* Close the tape descriptor file */ close (fd); fd = -1; /* Check that the first record is a TDF header */ if (memcmp(tdfbuf, "@TDF", 4) != 0) { logmsg (_("HHCTA243E %4.4X: %s is not a valid TDF file\n"), dev->devnum, dev->filename); free (tdfbuf); return -1; } /* Count the number of linefeeds in the tape descriptor file to determine the size of the descriptor array required */ for (i = 0, filecount = 0; i < tdfsize; i++) { if (tdfbuf[i] == '\n') filecount++; } /* end for(i) */ /* ISW Add 1 to filecount to add an extra EOT marker */ filecount++; /* Obtain storage for the tape descriptor array */ tdftab = (OMATAPE_DESC*)malloc (filecount * sizeof(OMATAPE_DESC)); if (tdftab == NULL) { logmsg (_("HHCTA244E %4.4X: Cannot obtain buffer for TDF array: %s\n"), dev->devnum, strerror(errno)); free (tdfbuf); return -1; } /* Build the tape descriptor array */ for (filecount = 0, tdfpos = 0, stmt = 1; ; filecount++) { /* Clear the tape descriptor array entry */ memset (&(tdftab[filecount]), 0, sizeof(OMATAPE_DESC)); /* Point past the next linefeed in the TDF file */ while (tdfpos < tdfsize && tdfbuf[tdfpos++] != '\n'); stmt++; /* Exit at end of TDF file */ if (tdfpos >= tdfsize) break; /* Mark the end of the TDF record with a null terminator */ tdfrec = tdfbuf + tdfpos; while (tdfpos < tdfsize && tdfbuf[tdfpos]!='\r' && tdfbuf[tdfpos]!='\n') tdfpos++; c = tdfbuf[tdfpos]; if (tdfpos >= tdfsize) break; tdfbuf[tdfpos] = '\0'; /* Exit if TM or EOT record */ if (strcasecmp(tdfrec, "TM") == 0) { tdftab[filecount].format='X'; tdfbuf[tdfpos] = c; continue; } if(strcasecmp(tdfrec, "EOT") == 0) { tdftab[filecount].format='E'; break; } /* Parse the TDF record */ tdffilenm = strtok (tdfrec, " \t"); tdfformat = strtok (NULL, " \t"); tdfreckwd = strtok (NULL, " \t"); tdfblklen = strtok (NULL, " \t"); /* Check for missing fields */ if (tdffilenm == NULL || tdfformat == NULL) { logmsg (_("HHCTA245E %4.4X: Filename or format missing in " "line %d of file %s\n"), dev->devnum, stmt, dev->filename); free (tdftab); free (tdfbuf); return -1; } /* Check that the file name is not too long */ if (pathlen + 1 + strlen(tdffilenm) > sizeof(tdftab[filecount].filename) - 1) { logmsg (_("HHCTA246E %4.4X: Filename %s too long in " "line %d of file %s\n"), dev->devnum, tdffilenm, stmt, dev->filename); free (tdftab); free (tdfbuf); return -1; } /* Convert the file name to Unix format */ for (i = 0; i < (int)strlen(tdffilenm); i++) { if (tdffilenm[i] == '\\') tdffilenm[i] = '/'; /* JCS */ // else // tdffilenm[i] = tolower(tdffilenm[i]); } /* end for(i) */ /* Prefix the file name with the base path name and save it in the tape descriptor array */ /* but only if the filename lacks a leading slash - JCS */ /* strncpy (tdftab[filecount].filename, dev->filename, pathlen); if (tdffilenm[0] != '/') stlrcat ( tdftab[filecount].filename, "/", sizeof(tdftab[filecount].filename) ); strlcat ( tdftab[filecount].filename, tdffilenm, sizeof(tdftab[filecount].filename) ); */ tdftab[filecount].filename[0] = 0; if ((tdffilenm[0] != '/') && (tdffilenm[1] != ':')) { strncpy (tdftab[filecount].filename, dev->filename, pathlen); strlcat (tdftab[filecount].filename, "/", sizeof(tdftab[filecount].filename) ); } strlcat (tdftab[filecount].filename, tdffilenm, sizeof(tdftab[filecount].filename) ); /* Check for valid file format code */ if (strcasecmp(tdfformat, "HEADERS") == 0) { tdftab[filecount].format = 'H'; } else if (strcasecmp(tdfformat, "TEXT") == 0) { tdftab[filecount].format = 'T'; } else if (strcasecmp(tdfformat, "FIXED") == 0) { /* Check for RECSIZE keyword */ if (tdfreckwd == NULL || strcasecmp(tdfreckwd, "RECSIZE") != 0) { logmsg (_("HHCTA247E %4.4X: RECSIZE keyword missing in " "line %d of file %s\n"), dev->devnum, stmt, dev->filename); free (tdftab); free (tdfbuf); return -1; } /* Check for valid fixed block length */ if (tdfblklen == NULL || sscanf(tdfblklen, "%u%c", &blklen, &c) != 1 || blklen < 1 || blklen > MAX_BLKLEN) { logmsg (_("HHCTA248E %4.4X: Invalid record size %s in " "line %d of file %s\n"), dev->devnum, tdfblklen, stmt, dev->filename); free (tdftab); free (tdfbuf); return -1; } /* Set format and block length in descriptor array */ tdftab[filecount].format = 'F'; tdftab[filecount].blklen = blklen; } else { logmsg (_("HHCTA249E %4.4X: Invalid record format %s in " "line %d of file %s\n"), dev->devnum, tdfformat, stmt, dev->filename); free (tdftab); free (tdfbuf); return -1; } tdfbuf[tdfpos] = c; } /* end for(filecount) */ /* Force an EOT as last entry (filecount is correctly adjusted here) */ tdftab[filecount].format='E'; /* Save the file count and TDF array pointer in the device block */ dev->omafiles = filecount+1; dev->omadesc = tdftab; /* Release the TDF file buffer and exit */ free (tdfbuf); return 0; } /* end function read_omadesc */ /*-------------------------------------------------------------------*/ /* Open the OMATAPE file defined by the current file number */ /* */ /* The OMA tape descriptor file is read if necessary. */ /* If successful, the file descriptor is stored in the device block */ /* and the return value is zero. Otherwise the return value is -1. */ /*-------------------------------------------------------------------*/ int open_omatape (DEVBLK *dev, BYTE *unitstat,BYTE code) { int fd; /* File descriptor integer */ int rc; /* Return code */ OMATAPE_DESC *omadesc; /* -> OMA descriptor entry */ char pathname[MAX_PATH]; /* file path in host format */ /* Check for no tape in drive */ if (!strcmp (dev->filename, TAPE_UNLOADED)) { build_senseX(TAPE_BSENSE_TAPEUNLOADED,dev,unitstat,code); return -1; } /* Read the OMA descriptor file if necessary */ if (dev->omadesc == NULL) { rc = read_omadesc (dev); if (rc < 0) { build_senseX(TAPE_BSENSE_TAPELOADFAIL,dev,unitstat,code); return -1; } dev->blockid = 0; } dev->fenced = 0; /* Unit exception if beyond end of tape */ /* ISW: CHANGED PROCESSING - RETURN UNDEFINITE Tape Marks */ /* NOTE: The last entry in the TDF table is ALWAYS */ /* an EOT Condition */ /* This is ensured by the TDF reading routine */ #if 0 if (dev->curfilen >= dev->omafiles) { logmsg (_("HHCTA250E %4.4X: Attempt to access beyond end of tape %s\n"), dev->devnum, dev->filename); build_senseX(TAPE_BSENSE_ENDOFTAPE,dev,unitstat,code); return -1; } #else if(dev->curfilen>dev->omafiles) { dev->curfilen=dev->omafiles; return(0); } #endif /* Point to the current file entry in the OMA descriptor table */ omadesc = (OMATAPE_DESC*)(dev->omadesc); omadesc += (dev->curfilen-1); if(omadesc->format=='X') { return 0; } if(omadesc->format=='E') { return 0; } /* Open the OMATAPE file */ hostpath(pathname, omadesc->filename, sizeof(pathname)); fd = open (pathname, O_RDONLY | O_BINARY); /* Check for successful open */ if (fd < 0 || lseek (fd, 0, SEEK_END) > LONG_MAX) { if (fd >= 0) /* (if open was successful, then it) */ errno = EOVERFLOW; /* (must have been a lseek overflow) */ logmsg (_("HHCTA251E %4.4X: Error opening %s: %s\n"), dev->devnum, omadesc->filename, strerror(errno)); if (fd >= 0) close(fd); /* (close the file if it was opened) */ build_senseX(TAPE_BSENSE_TAPELOADFAIL,dev,unitstat,code); return -1; } /* OMA tapes are always read-only */ dev->readonly = 1; /* Store the file descriptor in the device block */ dev->fd = fd; return 0; } /* end function open_omatape */ /*-------------------------------------------------------------------*/ /* Read a block header from an OMA tape file in OMA headers format */ /* */ /* If successful, return value is zero, and the current block */ /* length and previous and next header offsets are returned. */ /* If error, return value is -1 and unitstat is set to CE+DE+UC */ /*-------------------------------------------------------------------*/ int readhdr_omaheaders (DEVBLK *dev, OMATAPE_DESC *omadesc, long blkpos, S32 *pcurblkl, S32 *pprvhdro, S32 *pnxthdro, BYTE *unitstat,BYTE code) { int rc; /* Return code */ off_t rcoff; /* Return code from lseek() */ int padding; /* Number of padding bytes */ OMATAPE_BLKHDR omahdr; /* OMATAPE block header */ S32 curblkl; /* Length of current block */ S32 prvhdro; /* Offset of previous header */ S32 nxthdro; /* Offset of next header */ /* Seek to start of block header */ rcoff = lseek (dev->fd, blkpos, SEEK_SET); if (rcoff < 0) { /* Handle seek error condition */ logmsg (_("HHCTA252E %4.4X: Error seeking to offset "I32_FMTX" " "in file %s: %s\n"), dev->devnum, blkpos, omadesc->filename, strerror(errno)); /* Set unit check with equipment check */ build_senseX(TAPE_BSENSE_LOCATEERR,dev,unitstat,code); return -1; } /* Read the 16-byte block header */ rc = read (dev->fd, &omahdr, sizeof(omahdr)); /* Handle read error condition */ if (rc < 0) { logmsg (_("HHCTA253E %4.4X: Error reading block header " "at offset "I32_FMTX" in file %s: %s\n"), dev->devnum, blkpos, omadesc->filename, strerror(errno)); /* Set unit check with equipment check */ build_senseX(TAPE_BSENSE_READFAIL,dev,unitstat,code); return -1; } /* Handle end of file within block header */ if (rc < (int)sizeof(omahdr)) { logmsg (_("HHCTA254E %4.4X: Unexpected end of file in block header " "at offset "I32_FMTX" in file %s\n"), dev->devnum, blkpos, omadesc->filename); /* Set unit check with data check and partial record */ build_senseX(TAPE_BSENSE_BLOCKSHORT,dev,unitstat,code); return -1; } /* Extract the current block length and previous header offset */ curblkl = (S32)(((U32)(omahdr.curblkl[3]) << 24) | ((U32)(omahdr.curblkl[2]) << 16) | ((U32)(omahdr.curblkl[1]) << 8) | omahdr.curblkl[0]); prvhdro = (S32)((U32)(omahdr.prvhdro[3]) << 24) | ((U32)(omahdr.prvhdro[2]) << 16) | ((U32)(omahdr.prvhdro[1]) << 8) | omahdr.prvhdro[0]; /* Check for valid block header */ if (curblkl < -1 || curblkl == 0 || curblkl > MAX_BLKLEN || memcmp(omahdr.omaid, "@HDF", 4) != 0) { logmsg (_("HHCTA255E %4.4X: Invalid block header " "at offset "I32_FMTX" in file %s\n"), dev->devnum, blkpos, omadesc->filename); build_senseX(TAPE_BSENSE_READFAIL,dev,unitstat,code); return -1; } /* Calculate the number of padding bytes which follow the data */ padding = (16 - (curblkl & 15)) & 15; /* Calculate the offset of the next block header */ nxthdro = blkpos + sizeof(OMATAPE_BLKHDR) + curblkl + padding; /* Return current block length and previous/next header offsets */ *pcurblkl = curblkl; *pprvhdro = prvhdro; *pnxthdro = nxthdro; return 0; } /* end function readhdr_omaheaders */ /*-------------------------------------------------------------------*/ /* Read a block from an OMA tape file in OMA headers format */ /* */ /* If successful, return value is block length read. */ /* If a tapemark was read, the file is closed, the current file */ /* number in the device block is incremented so that the next file */ /* will be opened by the next CCW, and the return value is zero. */ /* If error, return value is -1 and unitstat is set to CE+DE+UC */ /*-------------------------------------------------------------------*/ int read_omaheaders (DEVBLK *dev, OMATAPE_DESC *omadesc, BYTE *buf, BYTE *unitstat,BYTE code) { int rc; /* Return code */ long blkpos; /* Offset to block header */ S32 curblkl; /* Length of current block */ S32 prvhdro; /* Offset of previous header */ S32 nxthdro; /* Offset of next header */ /* Read the 16-byte block header */ blkpos = dev->nxtblkpos; rc = readhdr_omaheaders (dev, omadesc, blkpos, &curblkl, &prvhdro, &nxthdro, unitstat,code); if (rc < 0) return -1; /* Update the offsets of the next and previous blocks */ dev->nxtblkpos = nxthdro; dev->prvblkpos = blkpos; /* Increment file number and return zero if tapemark */ if (curblkl == -1) { close (dev->fd); dev->fd = -1; dev->curfilen++; dev->nxtblkpos = 0; dev->prvblkpos = -1; return 0; } /* Read data block from tape file */ rc = read (dev->fd, buf, curblkl); /* Handle read error condition */ if (rc < 0) { logmsg (_("HHCTA256E %4.4X: Error reading data block " "at offset "I32_FMTX" in file %s: %s\n"), dev->devnum, blkpos, omadesc->filename, strerror(errno)); /* Set unit check with equipment check */ build_senseX(TAPE_BSENSE_READFAIL,dev,unitstat,code); return -1; } /* Handle end of file within data block */ if (rc < curblkl) { logmsg (_("HHCTA257E %4.4X: Unexpected end of file in data block " "at offset "I32_FMTX" in file %s\n"), dev->devnum, blkpos, omadesc->filename); /* Set unit check with data check and partial record */ build_senseX(TAPE_BSENSE_BLOCKSHORT,dev,unitstat,code); return -1; } /* Return block length */ return curblkl; } /* end function read_omaheaders */ /*-------------------------------------------------------------------*/ /* Read a block from an OMA tape file in fixed block format */ /* */ /* If successful, return value is block length read. */ /* If a tapemark was read, the file is closed, the current file */ /* number in the device block is incremented so that the next file */ /* will be opened by the next CCW, and the return value is zero. */ /* If error, return value is -1 and unitstat is set to CE+DE+UC */ /*-------------------------------------------------------------------*/ int read_omafixed (DEVBLK *dev, OMATAPE_DESC *omadesc, BYTE *buf, BYTE *unitstat,BYTE code) { off_t rcoff; /* Return code from lseek() */ int blklen; /* Block length */ long blkpos; /* Offset of block in file */ /* Initialize current block position */ blkpos = dev->nxtblkpos; /* Seek to new current block position */ rcoff = lseek (dev->fd, blkpos, SEEK_SET); if (rcoff < 0) { /* Handle seek error condition */ logmsg (_("HHCTA258E %4.4X: Error seeking to offset "I32_FMTX" " "in file %s: %s\n"), dev->devnum, blkpos, omadesc->filename, strerror(errno)); /* Set unit check with equipment check */ build_senseX(TAPE_BSENSE_LOCATEERR,dev,unitstat,code); return -1; } /* Read fixed length block or short final block */ blklen = read (dev->fd, buf, omadesc->blklen); /* Handle read error condition */ if (blklen < 0) { logmsg (_("HHCTA259E %4.4X: Error reading data block " "at offset "I32_FMTX" in file %s: %s\n"), dev->devnum, blkpos, omadesc->filename, strerror(errno)); build_senseX(TAPE_BSENSE_READFAIL,dev,unitstat,code); return -1; } /* At end of file return zero to indicate tapemark */ if (blklen == 0) { close (dev->fd); dev->fd = -1; dev->curfilen++; dev->nxtblkpos = 0; dev->prvblkpos = -1; return 0; } /* Calculate the offsets of the next and previous blocks */ dev->nxtblkpos = blkpos + blklen; dev->prvblkpos = blkpos; /* Return block length, or zero to indicate tapemark */ return blklen; } /* end function read_omafixed */ /*-------------------------------------------------------------------*/ /* Read a block from an OMA tape file in ASCII text format */ /* */ /* If successful, return value is block length read. */ /* If a tapemark was read, the file is closed, the current file */ /* number in the device block is incremented so that the next file */ /* will be opened by the next CCW, and the return value is zero. */ /* If error, return value is -1 and unitstat is set to CE+DE+UC */ /* */ /* The buf parameter points to the I/O buffer during a read */ /* operation, or is NULL for a forward space block operation. */ /*-------------------------------------------------------------------*/ int read_omatext (DEVBLK *dev, OMATAPE_DESC *omadesc, BYTE *buf, BYTE *unitstat,BYTE code) { int rc; /* Return code */ off_t rcoff; /* Return code from lseek() */ int num; /* Number of characters read */ int pos; /* Position in I/O buffer */ long blkpos; /* Offset of block in file */ BYTE c; /* Character work area */ /* Initialize current block position */ blkpos = dev->nxtblkpos; /* Seek to new current block position */ rcoff = lseek (dev->fd, blkpos, SEEK_SET); if (rcoff < 0) { /* Handle seek error condition */ logmsg (_("HHCTA260E %4.4X: Error seeking to offset "I32_FMTX" " "in file %s: %s\n"), dev->devnum, blkpos, omadesc->filename, strerror(errno)); /* Set unit check with equipment check */ build_senseX(TAPE_BSENSE_LOCATEERR,dev,unitstat,code); return -1; } /* Read data from tape file until end of line */ for (num = 0, pos = 0; ; ) { rc = read (dev->fd, &c, 1); if (rc < 1) break; /* Treat X'1A' as end of file */ if (c == '\x1A') { rc = 0; break; } /* Count characters read */ num++; /* Ignore carriage return character */ if (c == '\r') continue; /* Exit if newline character */ if (c == '\n') break; /* Ignore characters in excess of I/O buffer length */ if (pos >= MAX_BLKLEN) continue; /* Translate character to EBCDIC and copy to I/O buffer */ if (buf != NULL) buf[pos] = host_to_guest(c); /* Count characters copied or skipped */ pos++; } /* end for(num) */ /* At end of file return zero to indicate tapemark */ if (rc == 0 && num == 0) { close (dev->fd); dev->fd = -1; dev->curfilen++; dev->nxtblkpos = 0; dev->prvblkpos = -1; return 0; } /* Handle read error condition */ if (rc < 0) { logmsg (_("HHCTA261E %4.4X: Error reading data block " "at offset "I32_FMTX" in file %s: %s\n"), dev->devnum, blkpos, omadesc->filename, strerror(errno)); build_senseX(TAPE_BSENSE_READFAIL,dev,unitstat,code); return -1; } /* Check for block not terminated by newline */ if (rc < 1) { logmsg (_("HHCTA262E %4.4X: Unexpected end of file in data block " "at offset "I32_FMTX" in file %s\n"), dev->devnum, blkpos, omadesc->filename); /* Set unit check with data check and partial record */ build_senseX(TAPE_BSENSE_BLOCKSHORT,dev,unitstat,code); return -1; } /* Check for invalid zero length block */ if (pos == 0) { logmsg (_("HHCTA263E %4.4X: Invalid zero length block " "at offset "I32_FMTX" in file %s\n"), dev->devnum, blkpos, omadesc->filename); /* Set unit check with equipment check */ build_senseX(TAPE_BSENSE_BLOCKSHORT,dev,unitstat,code); return -1; } /* Calculate the offsets of the next and previous blocks */ dev->nxtblkpos = blkpos + num; dev->prvblkpos = blkpos; /* Return block length */ return pos; } /* end function read_omatext */ /*-------------------------------------------------------------------*/ /* Read a block from an OMA - Selection of format done here */ /* */ /* If successful, return value is block length read. */ /* If a tapemark was read, the file is closed, the current file */ /* number in the device block is incremented so that the next file */ /* will be opened by the next CCW, and the return value is zero. */ /* If error, return value is -1 and unitstat is set to CE+DE+UC */ /* */ /* The buf parameter points to the I/O buffer during a read */ /* operation, or is NULL for a forward space block operation. */ /*-------------------------------------------------------------------*/ int read_omatape (DEVBLK *dev, BYTE *buf, BYTE *unitstat,BYTE code) { int len; OMATAPE_DESC *omadesc; omadesc = (OMATAPE_DESC*)(dev->omadesc); omadesc += (dev->curfilen-1); switch (omadesc->format) { default: case 'H': len = read_omaheaders (dev, omadesc, buf, unitstat,code); break; case 'F': len = read_omafixed (dev, omadesc, buf, unitstat,code); break; case 'T': len = read_omatext (dev, omadesc, buf, unitstat,code); break; case 'X': len=0; dev->curfilen++; break; case 'E': len=0; break; } /* end switch(omadesc->format) */ if (len >= 0) dev->blockid++; return len; } /*-------------------------------------------------------------------*/ /* Forward space to next file of OMA tape device */ /* */ /* For OMA tape devices, the forward space file operation is */ /* achieved by closing the current file, and incrementing the */ /* current file number in the device block, which causes the */ /* next file will be opened when the next CCW is processed. */ /* If error, return value is -1 and unitstat is set to CE+DE+UC */ /*-------------------------------------------------------------------*/ int fsf_omatape (DEVBLK *dev, BYTE *unitstat,BYTE code) { UNREFERENCED(unitstat); UNREFERENCED(code); /* Close the current OMA file */ if (dev->fd >= 0) close (dev->fd); dev->fd = -1; dev->nxtblkpos = 0; dev->prvblkpos = -1; /* Increment the current file number */ dev->curfilen++; /* Return normal status */ return 0; } /* end function fsf_omatape */ /*-------------------------------------------------------------------*/ /* Forward space over next block of OMA file in OMA headers format */ /* */ /* If successful, return value is the length of the block skipped. */ /* If the block skipped was a tapemark, the return value is zero, */ /* the file is closed, and the current file number in the device */ /* block is incremented so that the next file belonging to the OMA */ /* tape will be opened when the next CCW is executed. */ /* If error, return value is -1 and unitstat is set to CE+DE+UC */ /*-------------------------------------------------------------------*/ int fsb_omaheaders (DEVBLK *dev, OMATAPE_DESC *omadesc, BYTE *unitstat,BYTE code) { int rc; /* Return code */ long blkpos; /* Offset of block header */ S32 curblkl; /* Length of current block */ S32 prvhdro; /* Offset of previous header */ S32 nxthdro; /* Offset of next header */ /* Initialize current block position */ blkpos = dev->nxtblkpos; /* Read the 16-byte block header */ rc = readhdr_omaheaders (dev, omadesc, blkpos, &curblkl, &prvhdro, &nxthdro, unitstat,code); if (rc < 0) return -1; /* Check if tapemark was skipped */ if (curblkl == -1) { /* Close the current OMA file */ if (dev->fd >= 0) close (dev->fd); dev->fd = -1; dev->nxtblkpos = 0; dev->prvblkpos = -1; /* Increment the file number */ dev->curfilen++; /* Return zero to indicate tapemark */ return 0; } /* Update the offsets of the next and previous blocks */ dev->nxtblkpos = nxthdro; dev->prvblkpos = blkpos; /* Return block length */ return curblkl; } /* end function fsb_omaheaders */ /*-------------------------------------------------------------------*/ /* Forward space over next block of OMA file in fixed block format */ /* */ /* If successful, return value is the length of the block skipped. */ /* If already at end of file, the return value is zero, */ /* the file is closed, and the current file number in the device */ /* block is incremented so that the next file belonging to the OMA */ /* tape will be opened when the next CCW is executed. */ /* If error, return value is -1 and unitstat is set to CE+DE+UC */ /*-------------------------------------------------------------------*/ int fsb_omafixed (DEVBLK *dev, OMATAPE_DESC *omadesc, BYTE *unitstat,BYTE code) { off_t eofpos; /* Offset of end of file */ off_t blkpos; /* Offset of current block */ int curblkl; /* Length of current block */ /* Initialize current block position */ blkpos = dev->nxtblkpos; /* Seek to end of file to determine file size */ eofpos = lseek (dev->fd, 0, SEEK_END); if (eofpos < 0 || eofpos >= LONG_MAX) { /* Handle seek error condition */ if ( eofpos >= LONG_MAX) errno = EOVERFLOW; logmsg (_("HHCTA264E %4.4X: Error seeking to end of file %s: %s\n"), dev->devnum, omadesc->filename, strerror(errno)); /* Set unit check with equipment check */ build_senseX(TAPE_BSENSE_LOCATEERR,dev,unitstat,code); return -1; } /* Check if already at end of file */ if (blkpos >= eofpos) { /* Close the current OMA file */ if (dev->fd >= 0) close (dev->fd); dev->fd = -1; dev->nxtblkpos = 0; dev->prvblkpos = -1; /* Increment the file number */ dev->curfilen++; /* Return zero to indicate tapemark */ return 0; } /* Calculate current block length */ curblkl = (int)(eofpos - blkpos); if (curblkl > omadesc->blklen) curblkl = omadesc->blklen; /* Update the offsets of the next and previous blocks */ dev->nxtblkpos = (long)(blkpos + curblkl); dev->prvblkpos = (long)(blkpos); /* Return block length */ return curblkl; } /* end function fsb_omafixed */ /*-------------------------------------------------------------------*/ /* Forward space to next block of OMA file */ /* */ /* If successful, return value is the length of the block skipped. */ /* If forward spaced over end of file, return value is 0. */ /* If error, return value is -1 and unitstat is set to CE+DE+UC */ /*-------------------------------------------------------------------*/ int fsb_omatape (DEVBLK *dev, BYTE *unitstat,BYTE code) { int rc; /* Return code */ OMATAPE_DESC *omadesc; /* -> OMA descriptor entry */ /* Point to the current file entry in the OMA descriptor table */ omadesc = (OMATAPE_DESC*)(dev->omadesc); omadesc += (dev->curfilen-1); /* Forward space block depending on OMA file type */ switch (omadesc->format) { default: case 'H': rc = fsb_omaheaders (dev, omadesc, unitstat,code); break; case 'F': rc = fsb_omafixed (dev, omadesc, unitstat,code); break; case 'T': rc = read_omatext (dev, omadesc, NULL, unitstat,code); break; } /* end switch(omadesc->format) */ if (rc >= 0) dev->blockid++; return rc; } /* end function fsb_omatape */ /*-------------------------------------------------------------------*/ /* Backspace to previous file of OMA tape device */ /* */ /* If the current file number is 1, then backspace file simply */ /* closes the file, setting the current position to start of tape. */ /* Otherwise, the current file is closed, the current file number */ /* is decremented, the new file is opened, and the new file is */ /* repositioned to just before the tape mark at the end of the file. */ /* If error, return value is -1 and unitstat is set to CE+DE+UC */ /*-------------------------------------------------------------------*/ int bsf_omatape (DEVBLK *dev, BYTE *unitstat,BYTE code) { int rc; /* Return code */ off_t pos; /* File position */ OMATAPE_DESC *omadesc; /* -> OMA descriptor entry */ S32 curblkl; /* Length of current block */ S32 prvhdro; /* Offset of previous header */ S32 nxthdro; /* Offset of next header */ /* Close the current OMA file */ if (dev->fd >= 0) close (dev->fd); dev->fd = -1; dev->nxtblkpos = 0; dev->prvblkpos = -1; /* Exit with tape at load point if currently on first file */ if (dev->curfilen <= 1) { build_senseX(TAPE_BSENSE_LOADPTERR,dev,unitstat,code); return -1; } /* Decrement current file number */ dev->curfilen--; /* Point to the current file entry in the OMA descriptor table */ omadesc = (OMATAPE_DESC*)(dev->omadesc); omadesc += (dev->curfilen-1); /* Open the new current file */ rc = open_omatape (dev, unitstat,code); if (rc < 0) return rc; /* Reposition before tapemark header at end of file, or to end of file for fixed block or ASCII text files */ pos = 0; if ( 'H' == omadesc->format ) pos -= sizeof(OMATAPE_BLKHDR); pos = lseek (dev->fd, pos, SEEK_END); if (pos < 0) { /* Handle seek error condition */ logmsg (_("HHCTA265E %4.4X: Error seeking to end of file %s: %s\n"), dev->devnum, omadesc->filename, strerror(errno)); /* Set unit check with equipment check */ build_senseX(TAPE_BSENSE_LOCATEERR,dev,unitstat,code); dev->sense[0] = SENSE_EC; *unitstat = CSW_CE | CSW_DE | CSW_UC; return -1; } dev->nxtblkpos = pos; dev->prvblkpos = -1; /* Determine the offset of the previous block */ switch (omadesc->format) { case 'H': /* For OMA headers files, read the tapemark header and extract the previous block offset */ rc = readhdr_omaheaders (dev, omadesc, pos, &curblkl, &prvhdro, &nxthdro, unitstat,code); if (rc < 0) return -1; dev->prvblkpos = prvhdro; break; case 'F': /* For OMA fixed block files, calculate the previous block offset allowing for a possible short final block */ pos = (pos + omadesc->blklen - 1) / omadesc->blklen; dev->prvblkpos = (pos > 0 ? (pos - 1) * omadesc->blklen : -1); break; case 'T': /* For OMA ASCII text files, the previous block is unknown */ dev->prvblkpos = -1; break; } /* end switch(omadesc->format) */ /* Return normal status */ return 0; } /* end function bsf_omatape */ /*-------------------------------------------------------------------*/ /* Backspace to previous block of OMA file */ /* */ /* If successful, return value is +1. */ /* If current position is at start of a file, then a backspace file */ /* operation is performed to reset the position to the end of the */ /* previous file, and the return value is zero. */ /* If error, return value is -1 and unitstat is set to CE+DE+UC */ /* */ /* Note that for ASCII text files, the previous block position is */ /* known only if the previous CCW was a read or a write, so any */ /* attempt to issue more than one consecutive backspace block on */ /* an ASCII text file will fail with unit check status. */ /*-------------------------------------------------------------------*/ int bsb_omatape (DEVBLK *dev, BYTE *unitstat,BYTE code) { int rc; /* Return code */ OMATAPE_DESC *omadesc; /* -> OMA descriptor entry */ long blkpos; /* Offset of block header */ S32 curblkl; /* Length of current block */ S32 prvhdro; /* Offset of previous header */ S32 nxthdro; /* Offset of next header */ /* Point to the current file entry in the OMA descriptor table */ omadesc = (OMATAPE_DESC*)(dev->omadesc); omadesc += (dev->curfilen-1); /* Backspace file if current position is at start of file */ if (dev->nxtblkpos == 0) { /* Unit check if already at start of tape */ if (dev->curfilen <= 1) { build_senseX(TAPE_BSENSE_LOADPTERR,dev,unitstat,code); return -1; } /* Perform backspace file operation */ rc = bsf_omatape (dev, unitstat,code); if (rc < 0) return -1; dev->blockid--; /* Return zero to indicate tapemark detected */ return 0; } /* Unit check if previous block position is unknown */ if (dev->prvblkpos < 0) { build_senseX(TAPE_BSENSE_LOADPTERR,dev,unitstat,code); return -1; } /* Backspace to previous block position */ blkpos = dev->prvblkpos; /* Determine new previous block position */ switch (omadesc->format) { case 'H': /* For OMA headers files, read the previous block header to extract the block length and new previous block offset */ rc = readhdr_omaheaders (dev, omadesc, blkpos, &curblkl, &prvhdro, &nxthdro, unitstat,code); if (rc < 0) return -1; break; case 'F': /* For OMA fixed block files, calculate the new previous block offset by subtracting the fixed block length */ if (blkpos >= omadesc->blklen) prvhdro = blkpos - omadesc->blklen; else prvhdro = -1; break; case 'T': /* For OMA ASCII text files, new previous block is unknown */ prvhdro = -1; break; } /* end switch(omadesc->format) */ /* Update the offsets of the next and previous blocks */ dev->nxtblkpos = blkpos; dev->prvblkpos = prvhdro; dev->blockid--; /* Return +1 to indicate backspace successful */ return +1; } /* end function bsb_omatape */ /*-------------------------------------------------------------------*/ /* Close an OMA tape file set */ /* */ /* All errors are ignored */ /*-------------------------------------------------------------------*/ void close_omatape2(DEVBLK *dev) { if (dev->fd >= 0) close (dev->fd); dev->fd=-1; if (dev->omadesc != NULL) { free (dev->omadesc); dev->omadesc = NULL; } /* Reset the device dependent fields */ dev->nxtblkpos=0; dev->prvblkpos=-1; dev->curfilen=1; dev->blockid=0; dev->fenced = 0; dev->omafiles = 0; return; } /*-------------------------------------------------------------------*/ /* Close an OMA tape file set */ /* */ /* All errors are ignored */ /* Change the filename to '*' - unloaded */ /* TAPE REALLY UNLOADED */ /*-------------------------------------------------------------------*/ void close_omatape(DEVBLK *dev) { close_omatape2(dev); strcpy(dev->filename,TAPE_UNLOADED); dev->blockid = 0; dev->fenced = 0; return; } /*-------------------------------------------------------------------*/ /* Rewind an OMA tape file set */ /* */ /* All errors are ignored */ /*-------------------------------------------------------------------*/ int rewind_omatape(DEVBLK *dev,BYTE *unitstat,BYTE code) { UNREFERENCED(unitstat); UNREFERENCED(code); close_omatape2(dev); dev->fenced = 0; return 0; } hercules-3.07/opcode.c000644 000765 000765 00000676621 11321734033 016377 0ustar00jmaynardjmaynard000000 000000 /* OPCODE.C (c) Copyright Jan Jaeger, 2000-2009 */ /* Instruction decoding functions */ /* Interpretive Execution - (c) Copyright Jan Jaeger, 1999-2009 */ /* z/Architecture support - (c) Copyright Jan Jaeger, 1999-2009 */ // $Id: opcode.c 5574 2009-12-29 13:13:41Z bernard $ #include "hstdinc.h" #if !defined(_HENGINE_DLL_) #define _HENGINE_DLL_ #endif #if !defined(_OPCODE_C_) #define _OPCODE_C_ #endif #include "feature.h" #if !defined(_GEN_ARCH) #if defined(_ARCHMODE3) #define _GEN_ARCH _ARCHMODE3 #include "opcode.c" #undef _GEN_ARCH #endif #if defined(_ARCHMODE2) #define _GEN_ARCH _ARCHMODE2 #include "opcode.c" #undef _GEN_ARCH #endif #endif /*!defined(_GEN_ARCH)*/ #include "hercules.h" #include "opcode.h" #define UNDEF_INST(_x) \ DEF_INST(_x) { ARCH_DEP(operation_exception) \ (inst,regs); } #if !defined(FEATURE_CHANNEL_SUBSYSTEM) UNDEF_INST(clear_subchannel) UNDEF_INST(halt_subchannel) UNDEF_INST(modify_subchannel) UNDEF_INST(reset_channel_path) UNDEF_INST(resume_subchannel) UNDEF_INST(set_address_limit) UNDEF_INST(set_channel_monitor) UNDEF_INST(start_subchannel) UNDEF_INST(store_channel_path_status) UNDEF_INST(store_channel_report_word) UNDEF_INST(store_subchannel) UNDEF_INST(test_pending_interruption) UNDEF_INST(test_subchannel) #endif /*!defined(FEATURE_CHANNEL_SUBSYSTEM)*/ #if !defined(FEATURE_S370_CHANNEL) UNDEF_INST(start_io) UNDEF_INST(test_io) UNDEF_INST(halt_io) UNDEF_INST(test_channel) UNDEF_INST(store_channel_id) #endif /*!defined(FEATURE_S370_CHANNEL)*/ #if !defined(FEATURE_IMMEDIATE_AND_RELATIVE) UNDEF_INST(test_under_mask_high) UNDEF_INST(test_under_mask_low) UNDEF_INST(branch_relative_on_condition) UNDEF_INST(branch_relative_and_save) UNDEF_INST(branch_relative_on_count) UNDEF_INST(load_halfword_immediate) UNDEF_INST(add_halfword_immediate) UNDEF_INST(multiply_halfword_immediate) UNDEF_INST(compare_halfword_immediate) UNDEF_INST(multiply_single_register) UNDEF_INST(multiply_single) UNDEF_INST(branch_relative_on_index_high) UNDEF_INST(branch_relative_on_index_low_or_equal) #endif /*!defined(FEATURE_IMMEDIATE_AND_RELATIVE)*/ #if !defined(FEATURE_STRING_INSTRUCTION) UNDEF_INST(compare_logical_string) UNDEF_INST(compare_until_substring_equal) UNDEF_INST(move_string) UNDEF_INST(search_string) #endif /*!defined(FEATURE_STRING_INSTRUCTION)*/ #if !defined(FEATURE_COMPARE_AND_MOVE_EXTENDED) UNDEF_INST(compare_logical_long_extended) UNDEF_INST(move_long_extended) #endif /*!defined(FEATURE_COMPARE_AND_MOVE_EXTENDED)*/ #if !defined(FEATURE_CHECKSUM_INSTRUCTION) UNDEF_INST(checksum) #endif /*!defined(FEATURE_CHECKSUM_INSTRUCTION)*/ #if !defined(FEATURE_PERFORM_LOCKED_OPERATION) UNDEF_INST(perform_locked_operation) #endif /*!defined(FEATURE_PERFORM_LOCKED_OPERATION)*/ #if !defined(FEATURE_SUBSPACE_GROUP) UNDEF_INST(branch_in_subspace_group) #endif /*!defined(FEATURE_SUBSPACE_GROUP)*/ #if !defined(FEATURE_SET_ADDRESS_SPACE_CONTROL_FAST) UNDEF_INST(set_address_space_control_fast) #else /*!defined(FEATURE_SET_ADDRESS_SPACE_CONTROL_FAST)*/ #define s390_set_address_space_control_fast s390_set_address_space_control #define z900_set_address_space_control_fast z900_set_address_space_control #endif /*!defined(FEATURE_SET_ADDRESS_SPACE_CONTROL_FAST)*/ #if !defined(FEATURE_BRANCH_AND_SET_AUTHORITY) UNDEF_INST(branch_and_set_authority) #endif /*!defined(FEATURE_BRANCH_AND_SET_AUTHORITY)*/ #if !defined(FEATURE_EXPANDED_STORAGE) UNDEF_INST(page_in) UNDEF_INST(page_out) #endif /*!defined(FEATURE_EXPANDED_STORAGE)*/ #if !defined(FEATURE_BROADCASTED_PURGING) UNDEF_INST(compare_and_swap_and_purge) #endif /*!defined(FEATURE_BROADCASTED_PURGING)*/ #if !defined(FEATURE_BIMODAL_ADDRESSING) UNDEF_INST(branch_and_set_mode) UNDEF_INST(branch_and_save_and_set_mode) #endif /*!defined(FEATURE_BIMODAL_ADDRESSING)*/ #if !defined(FEATURE_MOVE_PAGE_FACILITY_2) UNDEF_INST(move_page) UNDEF_INST(invalidate_expanded_storage_block_entry) #endif /*!defined(FEATURE_MOVE_PAGE_FACILITY_2)*/ #if !defined(FEATURE_BASIC_STORAGE_KEYS) UNDEF_INST(insert_storage_key) UNDEF_INST(set_storage_key) UNDEF_INST(reset_reference_bit) #endif /*!defined(FEATURE_BASIC_STORAGE_KEYS)*/ #if !defined(FEATURE_LINKAGE_STACK) UNDEF_INST(branch_and_stack) UNDEF_INST(modify_stacked_state) UNDEF_INST(extract_stacked_registers) UNDEF_INST(extract_stacked_state) UNDEF_INST(program_return) UNDEF_INST(trap2) UNDEF_INST(trap4) #endif /*!defined(FEATURE_LINKAGE_STACK)*/ #if !defined(FEATURE_DUAL_ADDRESS_SPACE) UNDEF_INST(extract_primary_asn) UNDEF_INST(extract_secondary_asn) UNDEF_INST(insert_address_space_control) UNDEF_INST(insert_virtual_storage_key) UNDEF_INST(load_address_space_parameters) UNDEF_INST(move_to_primary) UNDEF_INST(move_to_secondary) UNDEF_INST(move_with_key) UNDEF_INST(program_call) UNDEF_INST(program_transfer) UNDEF_INST(set_address_space_control) UNDEF_INST(set_secondary_asn) #endif /*!defined(FEATURE_DUAL_ADDRESS_SPACE)*/ #if !defined(FEATURE_ASN_AND_LX_REUSE) UNDEF_INST(extract_primary_asn_and_instance) UNDEF_INST(extract_secondary_asn_and_instance) UNDEF_INST(program_transfer_with_instance) UNDEF_INST(set_secondary_asn_with_instance) #endif /*!defined(FEATURE_ASN_AND_LX_REUSE)*/ #if !defined(FEATURE_ACCESS_REGISTERS) UNDEF_INST(load_access_multiple) UNDEF_INST(store_access_multiple) UNDEF_INST(purge_accesslist_lookaside_buffer) UNDEF_INST(test_access) UNDEF_INST(copy_access) UNDEF_INST(set_access_register) UNDEF_INST(extract_access_register) #endif /*!defined(FEATURE_ACCESS_REGISTERS)*/ #if !defined(FEATURE_EXTENDED_STORAGE_KEYS) UNDEF_INST(insert_storage_key_extended) UNDEF_INST(reset_reference_bit_extended) UNDEF_INST(set_storage_key_extended) #endif /*!defined(FEATURE_EXTENDED_STORAGE_KEYS)*/ #if !defined(FEATURE_TOD_CLOCK_STEERING) UNDEF_INST(perform_timing_facility_function) #endif #if !defined(FEATURE_EXTENDED_TOD_CLOCK) UNDEF_INST(set_clock_programmable_field) UNDEF_INST(store_clock_extended) #endif /*!defined(FEATURE_EXTENDED_TOD_CLOCK)*/ #if !defined(FEATURE_MOVE_WITH_OPTIONAL_SPECIFICATIONS) UNDEF_INST(move_with_optional_specifications) #endif /*!defined(FEATURE_MOVE_WITH_OPTIONAL_SPECIFICATIONS)*/ #if !defined(FEATURE_EXTRACT_CPU_TIME) UNDEF_INST(extract_cpu_time) #endif /*!defined(FEATURE_EXTRACT_CPU_TIME)*/ #if !defined(FEATURE_COMPARE_AND_SWAP_AND_STORE) UNDEF_INST(compare_and_swap_and_store) #endif /*!defined(FEATURE_COMPARE_AND_SWAP_AND_STORE)*/ #if !defined(FEATURE_STORE_SYSTEM_INFORMATION) UNDEF_INST(store_system_information) #endif /*!defined(FEATURE_STORE_SYSTEM_INFORMATION)*/ #if !defined(FEATURE_CONFIGURATION_TOPOLOGY_FACILITY) /*208*/ UNDEF_INST(perform_topology_function) /*208*/ #endif /*!defined(FEATURE_CONFIGURATION_TOPOLOGY_FACILITY)*/ /*208*/ #if !defined(FEATURE_ENHANCED_DAT_FACILITY) /*208*/ UNDEF_INST(perform_frame_management_function) /*208*/ #endif /*!defined(FEATURE_ENHANCED_DAT_FACILITY)*/ /*208*/ #if !defined(FEATURE_EXECUTE_EXTENSIONS_FACILITY) /*208*/ UNDEF_INST(execute_relative_long) /*208*/ #endif /*!defined(FEATURE_EXECUTE_EXTENSIONS_FACILITY)*/ /*208*/ #if !defined(FEATURE_GENERAL_INSTRUCTIONS_EXTENSION_FACILITY) /*208*/ UNDEF_INST(add_immediate_long_storage) UNDEF_INST(add_immediate_storage) UNDEF_INST(add_logical_with_signed_immediate) UNDEF_INST(add_logical_with_signed_immediate_long) UNDEF_INST(compare_and_branch_register) UNDEF_INST(compare_and_branch_long_register) UNDEF_INST(compare_and_branch_relative_register) UNDEF_INST(compare_and_branch_relative_long_register) UNDEF_INST(compare_and_trap_long_register) UNDEF_INST(compare_and_trap_register) UNDEF_INST(compare_halfword_immediate_halfword_storage) UNDEF_INST(compare_halfword_immediate_long_storage) UNDEF_INST(compare_halfword_immediate_storage) UNDEF_INST(compare_halfword_long) UNDEF_INST(compare_halfword_relative_long) UNDEF_INST(compare_halfword_relative_long_long) UNDEF_INST(compare_immediate_and_branch) UNDEF_INST(compare_immediate_and_branch_long) UNDEF_INST(compare_immediate_and_branch_relative) UNDEF_INST(compare_immediate_and_branch_relative_long) UNDEF_INST(compare_immediate_and_trap) UNDEF_INST(compare_immediate_and_trap_long) UNDEF_INST(compare_logical_and_branch_long_register) UNDEF_INST(compare_logical_and_branch_register) UNDEF_INST(compare_logical_and_branch_relative_long_register) UNDEF_INST(compare_logical_and_branch_relative_register) UNDEF_INST(compare_logical_and_trap_long_register) UNDEF_INST(compare_logical_and_trap_register) UNDEF_INST(compare_logical_immediate_and_branch) UNDEF_INST(compare_logical_immediate_and_branch_long) UNDEF_INST(compare_logical_immediate_and_branch_relative) UNDEF_INST(compare_logical_immediate_and_branch_relative_long) UNDEF_INST(compare_logical_immediate_and_trap_fullword) UNDEF_INST(compare_logical_immediate_and_trap_long) UNDEF_INST(compare_logical_immediate_fullword_storage) UNDEF_INST(compare_logical_immediate_halfword_storage) UNDEF_INST(compare_logical_immediate_long_storage) UNDEF_INST(compare_logical_relative_long) UNDEF_INST(compare_logical_relative_long_halfword) UNDEF_INST(compare_logical_relative_long_long) UNDEF_INST(compare_logical_relative_long_long_fullword) UNDEF_INST(compare_logical_relative_long_long_halfword) UNDEF_INST(compare_relative_long) UNDEF_INST(compare_relative_long_long) UNDEF_INST(compare_relative_long_long_fullword) UNDEF_INST(extract_cache_attribute) UNDEF_INST(load_address_extended_y) UNDEF_INST(load_and_test_long_fullword) UNDEF_INST(load_halfword_relative_long) UNDEF_INST(load_halfword_relative_long_long) UNDEF_INST(load_logical_halfword_relative_long) UNDEF_INST(load_logical_halfword_relative_long_long) UNDEF_INST(load_logical_relative_long_long_fullword) UNDEF_INST(load_relative_long) UNDEF_INST(load_relative_long_long) UNDEF_INST(load_relative_long_long_fullword) UNDEF_INST(move_fullword_from_halfword_immediate) UNDEF_INST(move_halfword_from_halfword_immediate) UNDEF_INST(move_long_from_halfword_immediate) UNDEF_INST(multiply_halfword_y) UNDEF_INST(multiply_single_immediate_fullword) UNDEF_INST(multiply_single_immediate_long_fullword) UNDEF_INST(multiply_y) UNDEF_INST(prefetch_data) UNDEF_INST(prefetch_data_relative_long) UNDEF_INST(rotate_then_and_selected_bits_long_reg) UNDEF_INST(rotate_then_exclusive_or_selected_bits_long_reg) UNDEF_INST(rotate_then_insert_selected_bits_long_reg) UNDEF_INST(rotate_then_or_selected_bits_long_reg) UNDEF_INST(store_halfword_relative_long) UNDEF_INST(store_relative_long) UNDEF_INST(store_relative_long_long) #endif /*!defined(FEATURE_GENERAL_INSTRUCTIONS_EXTENSION_FACILITY)*/ /*208*/ #if !defined(FEATURE_PARSING_ENHANCEMENT_FACILITY) /*208*/ UNDEF_INST(translate_and_test_extended) /*208*/ UNDEF_INST(translate_and_test_reverse_extended) /*208*/ #endif /*!defined(FEATURE_PARSING_ENHANCEMENT_FACILITY)*/ /*208*/ #if !defined(FEATURE_VECTOR_FACILITY) UNDEF_INST(execute_a4xx) #if !defined(FEATURE_ESAME) && !defined(FEATURE_ESAME_N3_ESA390) UNDEF_INST(execute_a5xx) #endif /*!defined(FEATURE_ESAME) && !defined(FEATURE_ESAME_N3_ESA390)*/ UNDEF_INST(execute_a6xx) UNDEF_INST(execute_e4xx) UNDEF_INST(v_test_vmr) UNDEF_INST(v_complement_vmr) UNDEF_INST(v_count_left_zeros_in_vmr) UNDEF_INST(v_count_ones_in_vmr) UNDEF_INST(v_extract_vct) UNDEF_INST(v_extract_vector_modes) UNDEF_INST(v_restore_vr) UNDEF_INST(v_save_changed_vr) UNDEF_INST(v_save_vr) UNDEF_INST(v_load_vmr) UNDEF_INST(v_load_vmr_complement) UNDEF_INST(v_store_vmr) UNDEF_INST(v_and_to_vmr) UNDEF_INST(v_or_to_vmr) UNDEF_INST(v_exclusive_or_to_vmr) UNDEF_INST(v_save_vsr) UNDEF_INST(v_save_vmr) UNDEF_INST(v_restore_vsr) UNDEF_INST(v_restore_vmr) UNDEF_INST(v_load_vct_from_address) UNDEF_INST(v_clear_vr) UNDEF_INST(v_set_vector_mask_mode) UNDEF_INST(v_load_vix_from_address) UNDEF_INST(v_store_vector_parameters) UNDEF_INST(v_save_vac) UNDEF_INST(v_restore_vac) #endif /*!defined(FEATURE_VECTOR_FACILITY)*/ #if !defined(FEATURE_ESAME) && !defined(FEATURE_ESAME_N3_ESA390) UNDEF_INST(execute_e3xx) UNDEF_INST(execute_ecxx) UNDEF_INST(execute_c0xx) UNDEF_INST(execute_c2xx) /*@Z9*/ #endif /*!defined(FEATURE_ESAME) && !defined(FEATURE_ESAME_N3_ESA390)*/ #if !defined(FEATURE_ESAME) UNDEF_INST(execute_c8xx) #endif /*!defined(FEATURE_ESAME)*/ #if !defined(FEATURE_BASIC_FP_EXTENSIONS) UNDEF_INST(execute_b3xx) UNDEF_INST(execute_edxx) #endif /*!defined(FEATURE_BASIC_FP_EXTENSIONS)*/ #if !defined(FEATURE_HEXADECIMAL_FLOATING_POINT) UNDEF_INST(load_positive_float_long_reg) UNDEF_INST(load_negative_float_long_reg) UNDEF_INST(load_and_test_float_long_reg) UNDEF_INST(load_complement_float_long_reg) UNDEF_INST(halve_float_long_reg) UNDEF_INST(load_rounded_float_long_reg) UNDEF_INST(multiply_float_ext_reg) UNDEF_INST(multiply_float_long_to_ext_reg) UNDEF_INST(load_float_long_reg) UNDEF_INST(compare_float_long_reg) UNDEF_INST(add_float_long_reg) UNDEF_INST(subtract_float_long_reg) UNDEF_INST(multiply_float_long_reg) UNDEF_INST(divide_float_long_reg) UNDEF_INST(add_unnormal_float_long_reg) UNDEF_INST(subtract_unnormal_float_long_reg) UNDEF_INST(load_positive_float_short_reg) UNDEF_INST(load_negative_float_short_reg) UNDEF_INST(load_and_test_float_short_reg) UNDEF_INST(load_complement_float_short_reg) UNDEF_INST(halve_float_short_reg) UNDEF_INST(load_rounded_float_short_reg) UNDEF_INST(add_float_ext_reg) UNDEF_INST(subtract_float_ext_reg) UNDEF_INST(load_float_short_reg) UNDEF_INST(compare_float_short_reg) UNDEF_INST(add_float_short_reg) UNDEF_INST(subtract_float_short_reg) UNDEF_INST(multiply_float_short_to_long_reg) UNDEF_INST(divide_float_short_reg) UNDEF_INST(add_unnormal_float_short_reg) UNDEF_INST(subtract_unnormal_float_short_reg) UNDEF_INST(store_float_long) UNDEF_INST(multiply_float_long_to_ext) UNDEF_INST(load_float_long) UNDEF_INST(compare_float_long) UNDEF_INST(add_float_long) UNDEF_INST(subtract_float_long) UNDEF_INST(multiply_float_long) UNDEF_INST(divide_float_long) UNDEF_INST(add_unnormal_float_long) UNDEF_INST(subtract_unnormal_float_long) UNDEF_INST(store_float_short) UNDEF_INST(load_float_short) UNDEF_INST(compare_float_short) UNDEF_INST(add_float_short) UNDEF_INST(subtract_float_short) UNDEF_INST(multiply_float_short_to_long) UNDEF_INST(divide_float_short) UNDEF_INST(add_unnormal_float_short) UNDEF_INST(subtract_unnormal_float_short) UNDEF_INST(divide_float_ext_reg) #endif /*!defined(FEATURE_HEXADECIMAL_FLOATING_POINT)*/ #if !defined(FEATURE_HFP_EXTENSIONS) UNDEF_INST(load_lengthened_float_short_to_long_reg) UNDEF_INST(load_lengthened_float_long_to_ext_reg) UNDEF_INST(load_lengthened_float_short_to_ext_reg) UNDEF_INST(squareroot_float_ext_reg) UNDEF_INST(multiply_float_short_reg) UNDEF_INST(load_positive_float_ext_reg) UNDEF_INST(load_negative_float_ext_reg) UNDEF_INST(load_and_test_float_ext_reg) UNDEF_INST(load_complement_float_ext_reg) UNDEF_INST(load_rounded_float_ext_to_short_reg) UNDEF_INST(load_fp_int_float_ext_reg) UNDEF_INST(compare_float_ext_reg) UNDEF_INST(load_fp_int_float_short_reg) UNDEF_INST(load_fp_int_float_long_reg) UNDEF_INST(convert_fixed_to_float_short_reg) UNDEF_INST(convert_fixed_to_float_long_reg) UNDEF_INST(convert_fixed_to_float_ext_reg) UNDEF_INST(convert_float_short_to_fixed_reg) UNDEF_INST(convert_float_long_to_fixed_reg) UNDEF_INST(convert_float_ext_to_fixed_reg) UNDEF_INST(load_lengthened_float_short_to_long) UNDEF_INST(load_lengthened_float_long_to_ext) UNDEF_INST(load_lengthened_float_short_to_ext) UNDEF_INST(squareroot_float_short) UNDEF_INST(squareroot_float_long) UNDEF_INST(multiply_float_short) #endif /*!defined(FEATURE_HFP_EXTENSIONS)*/ #if !defined(FEATURE_FPS_EXTENSIONS) UNDEF_INST(convert_bfp_long_to_float_long_reg) UNDEF_INST(convert_bfp_short_to_float_long_reg) UNDEF_INST(convert_float_long_to_bfp_long_reg) UNDEF_INST(convert_float_long_to_bfp_short_reg) UNDEF_INST(load_float_ext_reg) UNDEF_INST(load_zero_float_ext_reg) UNDEF_INST(load_zero_float_long_reg) UNDEF_INST(load_zero_float_short_reg) #endif /*!defined(FEATURE_FPS_EXTENSIONS)*/ #if !defined(FEATURE_FPS_ENHANCEMENT) UNDEF_INST(copy_sign_fpr_long_reg) UNDEF_INST(load_complement_fpr_long_reg) UNDEF_INST(load_fpr_from_gr_long_reg) UNDEF_INST(load_gr_from_fpr_long_reg) UNDEF_INST(load_negative_fpr_long_reg) UNDEF_INST(load_positive_fpr_long_reg) UNDEF_INST(set_dfp_rounding_mode) #endif /*!defined(FEATURE_FPS_ENHANCEMENT)*/ #if !defined(FEATURE_IEEE_EXCEPTION_SIMULATION) UNDEF_INST(load_fpc_and_signal) UNDEF_INST(set_fpc_and_signal) #endif /*!defined(FEATURE_IEEE_EXCEPTION_SIMULATION)*/ #if !defined(FEATURE_HFP_MULTIPLY_ADD_SUBTRACT) UNDEF_INST(multiply_add_float_short_reg) UNDEF_INST(multiply_add_float_long_reg) UNDEF_INST(multiply_add_float_short) UNDEF_INST(multiply_add_float_long) UNDEF_INST(multiply_subtract_float_short_reg) UNDEF_INST(multiply_subtract_float_long_reg) UNDEF_INST(multiply_subtract_float_short) UNDEF_INST(multiply_subtract_float_long) #endif /*!defined(FEATURE_HFP_MULTIPLY_ADD_SUBTRACT)*/ #if !defined(FEATURE_HFP_UNNORMALIZED_EXTENSION) /*@Z9*/ UNDEF_INST(multiply_unnormal_float_long_to_ext_reg) /*@Z9*/ UNDEF_INST(multiply_unnormal_float_long_to_ext_low_reg) /*@Z9*/ UNDEF_INST(multiply_unnormal_float_long_to_ext_high_reg) /*@Z9*/ UNDEF_INST(multiply_add_unnormal_float_long_to_ext_reg) /*@Z9*/ UNDEF_INST(multiply_add_unnormal_float_long_to_ext_low_reg) /*@Z9*/ UNDEF_INST(multiply_add_unnormal_float_long_to_ext_high_reg) /*@Z9*/ UNDEF_INST(multiply_unnormal_float_long_to_ext) /*@Z9*/ UNDEF_INST(multiply_unnormal_float_long_to_ext_low) /*@Z9*/ UNDEF_INST(multiply_unnormal_float_long_to_ext_high) /*@Z9*/ UNDEF_INST(multiply_add_unnormal_float_long_to_ext) /*@Z9*/ UNDEF_INST(multiply_add_unnormal_float_long_to_ext_low) /*@Z9*/ UNDEF_INST(multiply_add_unnormal_float_long_to_ext_high) /*@Z9*/ #endif /*!defined(FEATURE_HFP_UNNORMALIZED_EXTENSION)*/ /*@Z9*/ #if !defined(FEATURE_BINARY_FLOATING_POINT) UNDEF_INST(store_fpc) UNDEF_INST(load_fpc) UNDEF_INST(set_fpc) UNDEF_INST(extract_fpc) UNDEF_INST(set_bfp_rounding_mode) #endif /*!defined(FEATURE_BINARY_FLOATING_POINT)*/ #if !defined(FEATURE_BINARY_FLOATING_POINT) || defined(NO_IEEE_SUPPORT) UNDEF_INST(add_bfp_ext_reg) UNDEF_INST(add_bfp_long) UNDEF_INST(add_bfp_long_reg) UNDEF_INST(add_bfp_short) UNDEF_INST(add_bfp_short_reg) UNDEF_INST(compare_and_signal_bfp_ext_reg) UNDEF_INST(compare_and_signal_bfp_long) UNDEF_INST(compare_and_signal_bfp_long_reg) UNDEF_INST(compare_and_signal_bfp_short) UNDEF_INST(compare_and_signal_bfp_short_reg) UNDEF_INST(compare_bfp_ext_reg) UNDEF_INST(compare_bfp_long) UNDEF_INST(compare_bfp_long_reg) UNDEF_INST(compare_bfp_short) UNDEF_INST(compare_bfp_short_reg) UNDEF_INST(convert_bfp_ext_to_fix32_reg) UNDEF_INST(convert_bfp_long_to_fix32_reg) UNDEF_INST(convert_bfp_short_to_fix32_reg) UNDEF_INST(convert_fix32_to_bfp_ext_reg) UNDEF_INST(convert_fix32_to_bfp_long_reg) UNDEF_INST(convert_fix32_to_bfp_short_reg) UNDEF_INST(convert_fix64_to_bfp_ext_reg); UNDEF_INST(convert_fix64_to_bfp_long_reg); UNDEF_INST(convert_fix64_to_bfp_short_reg); UNDEF_INST(convert_bfp_ext_to_fix64_reg); UNDEF_INST(convert_bfp_long_to_fix64_reg); UNDEF_INST(convert_bfp_short_to_fix64_reg); UNDEF_INST(divide_bfp_ext_reg) UNDEF_INST(divide_bfp_long) UNDEF_INST(divide_bfp_long_reg) UNDEF_INST(divide_bfp_short) UNDEF_INST(divide_bfp_short_reg) UNDEF_INST(divide_integer_bfp_long_reg) UNDEF_INST(divide_integer_bfp_short_reg) UNDEF_INST(load_and_test_bfp_ext_reg) UNDEF_INST(load_and_test_bfp_long_reg) UNDEF_INST(load_and_test_bfp_short_reg) UNDEF_INST(load_fp_int_bfp_ext_reg) UNDEF_INST(load_fp_int_bfp_long_reg) UNDEF_INST(load_fp_int_bfp_short_reg) UNDEF_INST(load_complement_bfp_ext_reg) UNDEF_INST(load_complement_bfp_long_reg) UNDEF_INST(load_complement_bfp_short_reg) UNDEF_INST(load_negative_bfp_ext_reg) UNDEF_INST(load_negative_bfp_long_reg) UNDEF_INST(load_negative_bfp_short_reg) UNDEF_INST(load_positive_bfp_ext_reg) UNDEF_INST(load_positive_bfp_long_reg) UNDEF_INST(load_positive_bfp_short_reg) UNDEF_INST(load_lengthened_bfp_short_to_long) UNDEF_INST(load_lengthened_bfp_short_to_long_reg) UNDEF_INST(load_lengthened_bfp_long_to_ext) UNDEF_INST(load_lengthened_bfp_long_to_ext_reg) UNDEF_INST(load_lengthened_bfp_short_to_ext) UNDEF_INST(load_lengthened_bfp_short_to_ext_reg) UNDEF_INST(load_rounded_bfp_long_to_short_reg) UNDEF_INST(load_rounded_bfp_ext_to_long_reg) UNDEF_INST(load_rounded_bfp_ext_to_short_reg) UNDEF_INST(multiply_bfp_ext_reg) UNDEF_INST(multiply_bfp_long_to_ext_reg) UNDEF_INST(multiply_bfp_long_to_ext) UNDEF_INST(multiply_bfp_long) UNDEF_INST(multiply_bfp_long_reg) UNDEF_INST(multiply_bfp_short_to_long_reg) UNDEF_INST(multiply_bfp_short_to_long) UNDEF_INST(multiply_bfp_short) UNDEF_INST(multiply_bfp_short_reg) UNDEF_INST(multiply_add_bfp_long_reg) UNDEF_INST(multiply_add_bfp_long) UNDEF_INST(multiply_add_bfp_short_reg) UNDEF_INST(multiply_add_bfp_short) UNDEF_INST(multiply_subtract_bfp_long_reg) UNDEF_INST(multiply_subtract_bfp_long) UNDEF_INST(multiply_subtract_bfp_short_reg) UNDEF_INST(multiply_subtract_bfp_short) UNDEF_INST(squareroot_bfp_ext_reg) UNDEF_INST(squareroot_bfp_long) UNDEF_INST(squareroot_bfp_long_reg) UNDEF_INST(squareroot_bfp_short) UNDEF_INST(squareroot_bfp_short_reg) UNDEF_INST(subtract_bfp_ext_reg) UNDEF_INST(subtract_bfp_long) UNDEF_INST(subtract_bfp_long_reg) UNDEF_INST(subtract_bfp_short) UNDEF_INST(subtract_bfp_short_reg) UNDEF_INST(test_data_class_bfp_short) UNDEF_INST(test_data_class_bfp_long) UNDEF_INST(test_data_class_bfp_ext) #endif /*!defined(FEATURE_BINARY_FLOATING_POINT)*/ #if !defined(FEATURE_DECIMAL_FLOATING_POINT) UNDEF_INST(add_dfp_ext_reg) UNDEF_INST(add_dfp_long_reg) UNDEF_INST(compare_dfp_ext_reg) UNDEF_INST(compare_dfp_long_reg) UNDEF_INST(compare_and_signal_dfp_ext_reg) UNDEF_INST(compare_and_signal_dfp_long_reg) UNDEF_INST(compare_exponent_dfp_ext_reg) UNDEF_INST(compare_exponent_dfp_long_reg) UNDEF_INST(convert_fix64_to_dfp_ext_reg) UNDEF_INST(convert_fix64_to_dfp_long_reg) UNDEF_INST(convert_sbcd128_to_dfp_ext_reg) UNDEF_INST(convert_sbcd64_to_dfp_long_reg) UNDEF_INST(convert_ubcd128_to_dfp_ext_reg) UNDEF_INST(convert_ubcd64_to_dfp_long_reg) UNDEF_INST(convert_dfp_ext_to_fix64_reg) UNDEF_INST(convert_dfp_long_to_fix64_reg) UNDEF_INST(convert_dfp_ext_to_sbcd128_reg) UNDEF_INST(convert_dfp_long_to_sbcd64_reg) UNDEF_INST(convert_dfp_ext_to_ubcd128_reg) UNDEF_INST(convert_dfp_long_to_ubcd64_reg) UNDEF_INST(divide_dfp_ext_reg) UNDEF_INST(divide_dfp_long_reg) UNDEF_INST(extract_biased_exponent_dfp_ext_to_fix64_reg) UNDEF_INST(extract_biased_exponent_dfp_long_to_fix64_reg) UNDEF_INST(extract_significance_dfp_ext_reg) UNDEF_INST(extract_significance_dfp_long_reg) UNDEF_INST(insert_biased_exponent_fix64_to_dfp_ext_reg) UNDEF_INST(insert_biased_exponent_fix64_to_dfp_long_reg) UNDEF_INST(load_and_test_dfp_ext_reg) UNDEF_INST(load_and_test_dfp_long_reg) UNDEF_INST(load_fp_int_dfp_ext_reg) UNDEF_INST(load_fp_int_dfp_long_reg) UNDEF_INST(load_lengthened_dfp_long_to_ext_reg) UNDEF_INST(load_lengthened_dfp_short_to_long_reg) UNDEF_INST(load_rounded_dfp_ext_to_long_reg) UNDEF_INST(load_rounded_dfp_long_to_short_reg) UNDEF_INST(multiply_dfp_ext_reg) UNDEF_INST(multiply_dfp_long_reg) UNDEF_INST(quantize_dfp_ext_reg) UNDEF_INST(quantize_dfp_long_reg) UNDEF_INST(reround_dfp_ext_reg) UNDEF_INST(reround_dfp_long_reg) UNDEF_INST(shift_coefficient_left_dfp_ext) UNDEF_INST(shift_coefficient_left_dfp_long) UNDEF_INST(shift_coefficient_right_dfp_ext) UNDEF_INST(shift_coefficient_right_dfp_long) UNDEF_INST(subtract_dfp_ext_reg) UNDEF_INST(subtract_dfp_long_reg) UNDEF_INST(test_data_class_dfp_ext) UNDEF_INST(test_data_class_dfp_long) UNDEF_INST(test_data_class_dfp_short) UNDEF_INST(test_data_group_dfp_ext) UNDEF_INST(test_data_group_dfp_long) UNDEF_INST(test_data_group_dfp_short) #endif /*!defined(FEATURE_DECIMAL_FLOATING_POINT)*/ #if !defined(FEATURE_PFPO) UNDEF_INST(perform_floating_point_operation) #endif /*!defined(FEATURE_PFPO)*/ #if !defined(FEATURE_EMULATE_VM) UNDEF_INST(inter_user_communication_vehicle) #endif /*!defined(FEATURE_EMULATE_VM)*/ #if !defined(FEATURE_RESUME_PROGRAM) UNDEF_INST(resume_program) #endif /*!defined(FEATURE_RESUME_PROGRAM)*/ #if !defined(FEATURE_COMPRESSION) UNDEF_INST(compression_call) #endif /*!defined(FEATURE_COMPRESSION)*/ #if !defined(FEATURE_LOCK_PAGE) UNDEF_INST(lock_page) #endif /*!defined(FEATURE_LOCK_PAGE)*/ #if !defined(FEATURE_SQUARE_ROOT) UNDEF_INST(squareroot_float_long_reg) UNDEF_INST(squareroot_float_short_reg) #endif /*!defined(FEATURE_SQUARE_ROOT)*/ #if !defined(FEATURE_INTERPRETIVE_EXECUTION) UNDEF_INST(start_interpretive_execution) #endif /*!defined(FEATURE_INTERPRETIVE_EXECUTION)*/ #if !defined(FEATURE_REGION_RELOCATE) UNDEF_INST(store_zone_parameter) UNDEF_INST(set_zone_parameter) #endif /*!defined(FEATURE_REGION_RELOCATE)*/ #if !defined(FEATURE_IO_ASSIST) UNDEF_INST(test_pending_zone_interrupt) #endif /*!defined(FEATURE_IO_ASSIST)*/ #if !defined(FEATURE_QUEUED_DIRECT_IO) UNDEF_INST(signal_adapter) #endif /*!defined(FEATURE_QUEUED_DIRECT_IO)*/ #if !defined(FEATURE_CHANNEL_SWITCHING) UNDEF_INST(connect_channel_set) UNDEF_INST(disconnect_channel_set) #endif /*!defined(FEATURE_CHANNEL_SWITCHING)*/ #if !defined(FEATURE_SET_PROGRAM_PARAMETER_FACILITY) UNDEF_INST(set_program_parameter) #endif /*!defined(FEATURE_SET_PROGRAM_PARAMETER_FACILITY)*/ #if !defined(FEATURE_CPU_MEASUREMENT_COUNTER_FACILITY) UNDEF_INST(extract_coprocessor_group_address) UNDEF_INST(extract_cpu_counter) UNDEF_INST(extract_peripheral_counter) UNDEF_INST(query_counter_information) UNDEF_INST(set_cpu_counter) UNDEF_INST(set_cpu_counter_set_controls) UNDEF_INST(set_peripheral_counter) UNDEF_INST(set_peripheral_counter_set_controls) #endif /*!defined(FEATURE_CPU_MEASUREMENT_COUNTER_FACILITY)*/ #if !defined(FEATURE_CPU_MEASUREMENT_SAMPLING_FACILITY) UNDEF_INST(query_sampling_information) UNDEF_INST(set_sampling_controls) #endif /*!defined(FEATURE_CPU_MEASUREMENT_SAMPLING_FACILITY)*/ #if !defined(FEATURE_EXTENDED_TRANSLATION) UNDEF_INST(translate_extended) UNDEF_INST(convert_utf16_to_utf8) UNDEF_INST(convert_utf8_to_utf16) #endif /*!defined(FEATURE_EXTENDED_TRANSLATION)*/ #if !defined(FEATURE_EXTENDED_TRANSLATION_FACILITY_2) UNDEF_INST(compare_logical_long_unicode) UNDEF_INST(move_long_unicode) UNDEF_INST(pack_ascii) UNDEF_INST(pack_unicode) UNDEF_INST(test_decimal) UNDEF_INST(translate_one_to_one) UNDEF_INST(translate_one_to_two) UNDEF_INST(translate_two_to_one) UNDEF_INST(translate_two_to_two) UNDEF_INST(unpack_ascii) UNDEF_INST(unpack_unicode) #endif /*!defined(FEATURE_EXTENDED_TRANSLATION_FACILITY_2)*/ #if !defined(FEATURE_EXTENDED_TRANSLATION_FACILITY_3) UNDEF_INST(convert_utf16_to_utf32) UNDEF_INST(convert_utf32_to_utf16) UNDEF_INST(convert_utf32_to_utf8) UNDEF_INST(convert_utf8_to_utf32) UNDEF_INST(search_string_unicode) UNDEF_INST(translate_and_test_reverse) #endif /*!defined(FEATURE_EXTENDED_TRANSLATION_FACILITY_3)*/ #if !defined(FEATURE_LOAD_REVERSED) && !defined(FEATURE_ESAME_N3_ESA390) UNDEF_INST(load_reversed_register) UNDEF_INST(load_reversed) UNDEF_INST(load_reversed_half) UNDEF_INST(store_reversed) UNDEF_INST(store_reversed_half) #if !defined(FEATURE_ESAME) UNDEF_INST(load_reversed_long_register) UNDEF_INST(store_reversed_long) #endif /*!defined(FEATURE_ESAME)*/ #endif /*!defined(FEATURE_LOAD_REVERSED) && !defined(FEATURE_ESAME_N3_ESA390)*/ #if !defined(FEATURE_SERVICE_PROCESSOR) UNDEF_INST(service_call) #endif /*!defined(FEATURE_SERVICE_PROCESSOR)*/ #if !defined(FEATURE_CHSC) UNDEF_INST(channel_subsystem_call) #endif /*!defined(FEATURE_CHSC)*/ #if !defined(FEATURE_ESAME_N3_ESA390) && !defined(FEATURE_ESAME) UNDEF_INST(add_logical_carry) UNDEF_INST(add_logical_carry_register) UNDEF_INST(branch_relative_and_save_long) UNDEF_INST(branch_relative_on_condition_long) UNDEF_INST(divide_logical) UNDEF_INST(divide_logical_register) UNDEF_INST(extract_psw) UNDEF_INST(load_address_relative_long) UNDEF_INST(multiply_logical) UNDEF_INST(multiply_logical_register) UNDEF_INST(rotate_left_single_logical) UNDEF_INST(set_addressing_mode_24) UNDEF_INST(set_addressing_mode_31) UNDEF_INST(subtract_logical_borrow) UNDEF_INST(subtract_logical_borrow_register) UNDEF_INST(test_addressing_mode) #endif /*!defined(FEATURE_ESAME_N3_ESA390) && !defined(FEATURE_ESAME)*/ #if !defined(FEATURE_ESAME_N3_ESA390) && !defined(_900) && !defined(FEATURE_ESAME) UNDEF_INST(store_facility_list); #endif /*!defined(FEATURE_ESAME_N3_ESA390) && !defined(_900) && !defined(FEATURE_ESAME)*/ #if !defined(FEATURE_CANCEL_IO_FACILITY) UNDEF_INST(cancel_subchannel) #endif /*!defined(FEATURE_CANCEL_IO_FACILITY)*/ #if !defined(FEATURE_ECPSVM) UNDEF_INST(ecpsvm_basic_freex) UNDEF_INST(ecpsvm_basic_fretx) UNDEF_INST(ecpsvm_lock_page) UNDEF_INST(ecpsvm_unlock_page) UNDEF_INST(ecpsvm_decode_next_ccw) UNDEF_INST(ecpsvm_free_ccwstor) UNDEF_INST(ecpsvm_locate_vblock) UNDEF_INST(ecpsvm_disp1) UNDEF_INST(ecpsvm_tpage) UNDEF_INST(ecpsvm_tpage_lock) UNDEF_INST(ecpsvm_inval_segtab) UNDEF_INST(ecpsvm_inval_ptable) UNDEF_INST(ecpsvm_decode_first_ccw) UNDEF_INST(ecpsvm_dispatch_main) UNDEF_INST(ecpsvm_locate_rblock) UNDEF_INST(ecpsvm_comm_ccwproc) UNDEF_INST(ecpsvm_unxlate_ccw) UNDEF_INST(ecpsvm_disp2) UNDEF_INST(ecpsvm_store_level) UNDEF_INST(ecpsvm_loc_chgshrpg) UNDEF_INST(ecpsvm_extended_freex) UNDEF_INST(ecpsvm_extended_fretx) UNDEF_INST(ecpsvm_prefmach_assist) #endif /*!defined(FEATURE_ECPSVM)*/ #if !defined(FEATURE_LONG_DISPLACEMENT) UNDEF_INST(add_y) UNDEF_INST(add_halfword_y) UNDEF_INST(add_logical_y) UNDEF_INST(and_immediate_y) UNDEF_INST(and_y) UNDEF_INST(compare_y) UNDEF_INST(compare_and_swap_y) UNDEF_INST(compare_double_and_swap_y) UNDEF_INST(compare_halfword_y) UNDEF_INST(compare_logical_y) UNDEF_INST(compare_logical_immediate_y) UNDEF_INST(compare_logical_characters_under_mask_y) UNDEF_INST(convert_to_binary_y) UNDEF_INST(convert_to_decimal_y) UNDEF_INST(exclusive_or_immediate_y) UNDEF_INST(exclusive_or_y) UNDEF_INST(insert_character_y) UNDEF_INST(insert_characters_under_mask_y) UNDEF_INST(load_y) UNDEF_INST(load_address_y) UNDEF_INST(load_byte) UNDEF_INST(load_byte_long) UNDEF_INST(load_halfword_y) UNDEF_INST(load_multiple_y) UNDEF_INST(load_real_address_y) UNDEF_INST(move_immediate_y) UNDEF_INST(multiply_single_y) UNDEF_INST(or_immediate_y) UNDEF_INST(or_y) UNDEF_INST(store_y) UNDEF_INST(store_character_y) UNDEF_INST(store_characters_under_mask_y) UNDEF_INST(store_halfword_y) UNDEF_INST(store_multiple_y) UNDEF_INST(subtract_y) UNDEF_INST(subtract_halfword_y) UNDEF_INST(subtract_logical_y) UNDEF_INST(test_under_mask_y) #endif /*!defined(FEATURE_LONG_DISPLACEMENT)*/ #if !defined(FEATURE_LONG_DISPLACEMENT) \ || !defined(FEATURE_ACCESS_REGISTERS) UNDEF_INST(load_access_multiple_y) UNDEF_INST(store_access_multiple_y) #endif /*!defined(FEATURE_LONG_DISPLACEMENT) || !defined(FEATURE_ACCESS_REGISTERS)*/ #if !defined(FEATURE_LONG_DISPLACEMENT) \ || !defined(FEATURE_HEXADECIMAL_FLOATING_POINT) UNDEF_INST(load_float_long_y) UNDEF_INST(load_float_short_y) UNDEF_INST(store_float_long_y) UNDEF_INST(store_float_short_y) #endif /*!defined(FEATURE_LONG_DISPLACEMENT) || !defined(FEATURE_HEXADECIMAL_FLOATING_POINT)*/ #if !defined(FEATURE_MESSAGE_SECURITY_ASSIST) UNDEF_INST(cipher_message_r) UNDEF_INST(cipher_message_with_chaining_r) UNDEF_INST(compute_message_digest_r) UNDEF_INST(compute_message_authentication_code_r) #endif /*!defined(FEATURE_MESSAGE_SECURITY_ASSIST)*/ #if !defined(FEATURE_DAT_ENHANCEMENT) UNDEF_INST(compare_and_swap_and_purge_long) UNDEF_INST(invalidate_dat_table_entry) #endif /*!defined(FEATURE_DAT_ENHANCEMENT)*/ #if !defined(FEATURE_EXTENDED_IMMEDIATE) /*@Z9*/ UNDEF_INST(add_fullword_immediate) /*@Z9*/ UNDEF_INST(add_long_fullword_immediate) /*@Z9*/ UNDEF_INST(add_logical_fullword_immediate) /*@Z9*/ UNDEF_INST(add_logical_long_fullword_immediate) /*@Z9*/ UNDEF_INST(and_immediate_high_fullword) /*@Z9*/ UNDEF_INST(and_immediate_low_fullword) /*@Z9*/ UNDEF_INST(compare_fullword_immediate) /*@Z9*/ UNDEF_INST(compare_long_fullword_immediate) /*@Z9*/ UNDEF_INST(compare_logical_fullword_immediate) /*@Z9*/ UNDEF_INST(compare_logical_long_fullword_immediate) /*@Z9*/ UNDEF_INST(exclusive_or_immediate_high_fullword) /*@Z9*/ UNDEF_INST(exclusive_or_immediate_low_fullword) /*@Z9*/ UNDEF_INST(insert_immediate_high_fullword) /*@Z9*/ UNDEF_INST(insert_immediate_low_fullword) /*@Z9*/ UNDEF_INST(load_long_fullword_immediate) /*@Z9*/ UNDEF_INST(load_logical_immediate_high_fullword) /*@Z9*/ UNDEF_INST(load_logical_immediate_low_fullword) /*@Z9*/ UNDEF_INST(or_immediate_high_fullword) /*@Z9*/ UNDEF_INST(or_immediate_low_fullword) /*@Z9*/ UNDEF_INST(subtract_logical_fullword_immediate) /*@Z9*/ UNDEF_INST(subtract_logical_long_fullword_immediate) /*@Z9*/ #endif /*!defined(FEATURE_EXTENDED_IMMEDIATE)*/ /*@Z9*/ #if !defined(FEATURE_EXTENDED_IMMEDIATE) /*@Z9*/ UNDEF_INST(load_and_test) /*@Z9*/ UNDEF_INST(load_and_test_long) /*@Z9*/ UNDEF_INST(load_byte_register) /*@Z9*/ UNDEF_INST(load_long_byte_register) /*@Z9*/ UNDEF_INST(load_halfword_register) /*@Z9*/ UNDEF_INST(load_long_halfword_register) /*@Z9*/ UNDEF_INST(load_logical_character) /*@Z9*/ UNDEF_INST(load_logical_character_register) /*@Z9*/ UNDEF_INST(load_logical_long_character_register) /*@Z9*/ UNDEF_INST(load_logical_halfword) /*@Z9*/ UNDEF_INST(load_logical_halfword_register) /*@Z9*/ UNDEF_INST(load_logical_long_halfword_register) /*@Z9*/ UNDEF_INST(find_leftmost_one_long_register) /*@Z9*/ #endif /*!defined(FEATURE_EXTENDED_IMMEDIATE)*/ /*@Z9*/ #if !defined(FEATURE_DAT_ENHANCEMENT_FACILITY_2) /*@Z9*/ UNDEF_INST(load_page_table_entry_address) /*@Z9*/ #endif /*!defined(FEATURE_DAT_ENHANCEMENT_FACILITY_2)*/ /*@Z9*/ #if !defined(FEATURE_STORE_CLOCK_FAST) UNDEF_INST(store_clock_fast) #else /*!defined(FEATURE_STORE_CLOCK_FAST)*/ #define z900_store_clock_fast z900_store_clock #endif /*!defined(FEATURE_STORE_CLOCK_FAST)*/ #if !defined(FEATURE_STORE_FACILITY_LIST_EXTENDED) /*@Z9*/ UNDEF_INST(store_facility_list_extended) /*@Z9*/ #endif /*!defined(FEATURE_STORE_FACILITY_LIST_EXTENDED)*/ /*@Z9*/ /* The following execute_xxxx routines can be optimized by the compiler to an indexed jump, leaving the stack frame untouched as the called routine has the same arguments, and the routine exits immediately after the call. *JJ */ #if ARCH_MODE != ARCH_370 DEF_INST(execute_01xx) { regs->ARCH_DEP(opcode_01xx)[inst[1]](inst, regs); } #endif DEF_INST(execute_a7xx) { regs->ARCH_DEP(opcode_a7xx)[inst[1]](inst, regs); } DEF_INST(execute_b2xx) { regs->ARCH_DEP(opcode_b2xx)[inst[1]](inst, regs); } DEF_INST(execute_b9xx) { regs->ARCH_DEP(opcode_b9xx)[inst[1]](inst, regs); } DEF_INST(execute_ebxx) { regs->ARCH_DEP(opcode_ebxx)[inst[5]](inst, regs); } #if defined(FEATURE_BASIC_FP_EXTENSIONS) DEF_INST(execute_b3xx) { regs->ARCH_DEP(opcode_b3xx)[inst[1]](inst, regs); } DEF_INST(execute_edxx) { regs->ARCH_DEP(opcode_edxx)[inst[5]](inst, regs); } #endif /*defined(FEATURE_BASIC_FP_EXTENSIONS)*/ DEF_INST(execute_e5xx) { regs->ARCH_DEP(opcode_e5xx)[inst[1]](inst, regs); } #if ARCH_MODE == ARCH_370 DEF_INST(execute_e6xx) { regs->ARCH_DEP(opcode_e6xx)[inst[1]](inst, regs); } #endif #if defined(FEATURE_ESAME) || defined(FEATURE_ESAME_N3_ESA390) DEF_INST(execute_a5xx) { regs->ARCH_DEP(opcode_a5xx)[inst[1]](inst, regs); } DEF_INST(execute_e3xx) { regs->ARCH_DEP(opcode_e3xx)[inst[5]](inst, regs); } DEF_INST(execute_ecxx) { regs->ARCH_DEP(opcode_ecxx[inst[5]])(inst, regs); } DEF_INST(execute_c0xx) { regs->ARCH_DEP(opcode_c0xx)[inst[1]](inst, regs); } DEF_INST(execute_c2xx) /*@Z9*/ { /*@Z9*/ regs->ARCH_DEP(opcode_c2xx)[inst[1]](inst, regs); /*@Z9*/ } /*@Z9*/ #endif /*defined(FEATURE_ESAME) || defined(FEATURE_ESAME_N3_ESA390)*/ DEF_INST(execute_c4xx) /*208*/ { /*208*/ regs->ARCH_DEP(opcode_c4xx)[inst[1]](inst, regs); /*208*/ } /*208*/ DEF_INST(execute_c6xx) /*208*/ { /*208*/ regs->ARCH_DEP(opcode_c6xx)[inst[1]](inst, regs); /*208*/ } /*208*/ #if defined(FEATURE_ESAME) DEF_INST(execute_c8xx) { regs->ARCH_DEP(opcode_c8xx)[inst[1]](inst, regs); } #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_VECTOR_FACILITY) DEF_INST(execute_a4xx) { regs->ARCH_DEP(opcode_a4xx)[inst[1]](inst, regs); } DEF_INST(execute_a5xx) { regs->ARCH_DEP(opcode_a5xx)[inst[1]](inst, regs); } DEF_INST(execute_a6xx) { regs->ARCH_DEP(opcode_a6xx)[inst[1]](inst, regs); } DEF_INST(execute_e4xx) { regs->ARCH_DEP(opcode_e4xx)[inst[1]](inst, regs); } #endif /*defined(FEATURE_VECTOR_FACILITY)*/ DEF_INST(operation_exception) { INST_UPDATE_PSW (regs, ILC(inst[0]), ILC(inst[0])); #if defined(MODEL_DEPENDENT) #if defined(_FEATURE_SIE) /* The B2XX extended opcodes which are not defined are always intercepted by SIE when issued in supervisor state */ if(!PROBSTATE(®s->psw) && inst[0] == 0xB2) SIE_INTERCEPT(regs); #endif /*defined(_FEATURE_SIE)*/ #endif /*defined(MODEL_DEPENDENT)*/ ARCH_DEP(program_interrupt)(regs, PGM_OPERATION_EXCEPTION); } DEF_INST(dummy_instruction) { // logmsg(_("Dummy instruction: ")); ARCH_DEP(display_inst) (regs, inst); INST_UPDATE_PSW (regs, ILC(inst[0]), ILC(inst[0])); } #if !defined(_GEN_ARCH) #define DISASM_ROUTE(_table,_route) \ void disasm_ ## _table (BYTE inst[], char unused[]) \ { \ func disasm_fn; \ char* mnemonic; \ UNREFERENCED(unused); \ mnemonic = (void*)opcode_ ## _table [inst _route ][GEN_MAXARCH-1]; \ disasm_fn = (void*)opcode_ ## _table [inst _route ][GEN_MAXARCH-2]; \ disasm_fn(inst, mnemonic); \ } DISASM_ROUTE(table,[0]) DISASM_ROUTE(01xx,[1]) DISASM_ROUTE(a5xx,[1] & 0x0F) DISASM_ROUTE(a7xx,[1] & 0x0F) DISASM_ROUTE(b2xx,[1]) DISASM_ROUTE(b3xx,[1]) DISASM_ROUTE(b9xx,[1]) DISASM_ROUTE(c0xx,[1] & 0x0F) DISASM_ROUTE(c2xx,[1] & 0x0F) /*@Z9*/ DISASM_ROUTE(c4xx,[1] & 0x0F) /*208*/ DISASM_ROUTE(c6xx,[1] & 0x0F) /*208*/ DISASM_ROUTE(c8xx,[1] & 0x0F) DISASM_ROUTE(e3xx,[5]) DISASM_ROUTE(e5xx,[1]) DISASM_ROUTE(e6xx,[1]) DISASM_ROUTE(ebxx,[5]) DISASM_ROUTE(ecxx,[5]) DISASM_ROUTE(edxx,[5]) #if defined(FEATURE_VECTOR_FACILITY) #define opcode_a4xx v_opcode_a4xx DISASM_ROUTE(a4xx,[1]) #undef opcode_a4xx #define opcode_a6xx v_opcode_a6xx DISASM_ROUTE(a6xx,[1]) #undef opcode_a6xx #define opcode_e4xx v_opcode_e4xx DISASM_ROUTE(e4xx,[1]) #undef opcode_e4xx #else /*defined(FEATURE_VECTOR_FACILITY)*/ #define disasm_a4xx disasm_none #define disasm_a6xx disasm_none #define disasm_e4xx disasm_none #endif /*defined(FEATURE_VECTOR_FACILITY)*/ #define DISASM_COMMON_VARS \ char* name; \ char operands[64] #define DISASM_SET_NAME \ name = mnemonic+1; while(*name++) #define DISASM_PRINT_OPERANDS \ snprintf(operands,sizeof(operands)-1, #define DISASM_LOGMSG \ operands[sizeof(operands)-1]=0; \ logmsg("%-6.6s%-19s %s\n",mnemonic,operands,name) void disasm_none (BYTE inst[], char mnemonic[]) { DISASM_COMMON_VARS; UNREFERENCED(inst); DISASM_SET_NAME; DISASM_PRINT_OPERANDS "%c",','); DISASM_LOGMSG; } void disasm_E (BYTE inst[], char mnemonic[]) { DISASM_COMMON_VARS; UNREFERENCED(inst); DISASM_SET_NAME; DISASM_PRINT_OPERANDS "%c",','); DISASM_LOGMSG; } void disasm_RR (BYTE inst[], char mnemonic[]) { DISASM_COMMON_VARS; int r1, r2; r1 = inst[1] >> 4; r2 = inst[1] & 0x0F; DISASM_SET_NAME; DISASM_PRINT_OPERANDS "%d,%d",r1,r2); DISASM_LOGMSG; } // "Mnemonic R1" void disasm_RR_R1 (BYTE inst[], char mnemonic[]) { DISASM_COMMON_VARS; int r1; r1 = inst[1] >> 4; DISASM_SET_NAME; DISASM_PRINT_OPERANDS "%d",r1); DISASM_LOGMSG; } void disasm_RR_SVC (BYTE inst[], char mnemonic[]) { DISASM_COMMON_VARS; DISASM_SET_NAME; DISASM_PRINT_OPERANDS "%d",inst[1]); DISASM_LOGMSG; } void disasm_RRE (BYTE inst[], char mnemonic[]) { DISASM_COMMON_VARS; int r1, r2; r1 = inst[3] >> 4; r2 = inst[3] & 0x0F; DISASM_SET_NAME; DISASM_PRINT_OPERANDS "%d,%d",r1,r2); DISASM_LOGMSG; } // "Mnemonic R1" void disasm_RRE_R1 (BYTE inst[], char mnemonic[]) { DISASM_COMMON_VARS; int r1; r1 = inst[3] >> 4; DISASM_SET_NAME; DISASM_PRINT_OPERANDS "%d",r1); DISASM_LOGMSG; } void disasm_RRF_R (BYTE inst[], char mnemonic[]) { DISASM_COMMON_VARS; int r1,r3,r2; r1 = inst[2] >> 4; r3 = inst[3] >> 4; r2 = inst[3] & 0x0F; DISASM_SET_NAME; DISASM_PRINT_OPERANDS "%d,%d,%d",r1,r3,r2); DISASM_LOGMSG; } void disasm_RRF_M (BYTE inst[], char mnemonic[]) { DISASM_COMMON_VARS; int m3,r1,r2; m3 = inst[2] >> 4; r1 = inst[3] >> 4; r2 = inst[3] & 0x0F; DISASM_SET_NAME; DISASM_PRINT_OPERANDS "%d,%d,%d",r1,m3,r2); DISASM_LOGMSG; } void disasm_RRF_M3 (BYTE inst[], char mnemonic[]) { DISASM_COMMON_VARS; int m3,r1,r2; m3 = inst[2] >> 4; r1 = inst[3] >> 4; r2 = inst[3] & 0x0F; DISASM_SET_NAME; DISASM_PRINT_OPERANDS "%d,%d,%d",r1,r2,m3); DISASM_LOGMSG; } void disasm_RRF_M4 (BYTE inst[], char mnemonic[]) { DISASM_COMMON_VARS; int m4,r1,r2; m4 = inst[2] & 0x0F; r1 = inst[3] >> 4; r2 = inst[3] & 0x0F; DISASM_SET_NAME; DISASM_PRINT_OPERANDS "%d,%d,%d",r1,r2,m4); DISASM_LOGMSG; } void disasm_RRF_MM (BYTE inst[], char mnemonic[]) { DISASM_COMMON_VARS; int m3,m4,r1,r2; m3 = inst[2] >> 4; m4 = inst[2] & 0x0F; r1 = inst[3] >> 4; r2 = inst[3] & 0x0F; DISASM_SET_NAME; DISASM_PRINT_OPERANDS "%d,%d,%d,%d",r1,m3,r2,m4); DISASM_LOGMSG; } void disasm_RRF_RM (BYTE inst[], char mnemonic[]) { DISASM_COMMON_VARS; int r3,m4,r1,r2; r3 = inst[2] >> 4; m4 = inst[2] & 0x0F; r1 = inst[3] >> 4; r2 = inst[3] & 0x0F; DISASM_SET_NAME; DISASM_PRINT_OPERANDS "%d,%d,%d,%d",r1,r3,r2,m4); DISASM_LOGMSG; } void disasm_RRR (BYTE inst[], char mnemonic[]) { DISASM_COMMON_VARS; int r1,r2,r3; r3 = inst[2] >> 4; r1 = inst[3] >> 4; r2 = inst[3] & 0x0F; DISASM_SET_NAME; DISASM_PRINT_OPERANDS "%d,%d,%d",r1,r2,r3); DISASM_LOGMSG; } void disasm_RX (BYTE inst[], char mnemonic[]) { DISASM_COMMON_VARS; int r1,x2,b2,d2; r1 = inst[1] >> 4; x2 = inst[1] & 0x0F; b2 = inst[2] >> 4; d2 = (inst[2] & 0x0F) << 8 | inst[3]; DISASM_SET_NAME; DISASM_PRINT_OPERANDS "%d,%d(%d,%d)",r1,d2,x2,b2); DISASM_LOGMSG; } void disasm_RXE (BYTE inst[], char mnemonic[]) { DISASM_COMMON_VARS; int r1,x2,b2,d2; r1 = inst[1] >> 4; x2 = inst[1] & 0x0F; b2 = inst[2] >> 4; d2 = (inst[2] & 0x0F) << 8 | inst[3]; DISASM_SET_NAME; DISASM_PRINT_OPERANDS "%d,%d(%d,%d)",r1,d2,x2,b2); DISASM_LOGMSG; } void disasm_RXY (BYTE inst[], char mnemonic[]) { DISASM_COMMON_VARS; int r1,x2,b2,d2; r1 = inst[1] >> 4; x2 = inst[1] & 0x0F; b2 = inst[2] >> 4; d2 = (((S8)inst[4]) << 12) | (inst[2] & 0x0F) << 8 | inst[3]; DISASM_SET_NAME; DISASM_PRINT_OPERANDS "%d,%d(%d,%d)",r1,d2,x2,b2); DISASM_LOGMSG; } void disasm_RXF (BYTE inst[], char mnemonic[]) { DISASM_COMMON_VARS; int r1,r3,x2,b2,d2; r1 = inst[4] >> 4; r3 = inst[1] >> 4; x2 = inst[1] & 0x0F; b2 = inst[2] >> 4; d2 = (inst[2] & 0x0F) << 8 | inst[3]; DISASM_SET_NAME; DISASM_PRINT_OPERANDS "%d,%d,%d(%d,%d)",r1,r3,d2,x2,b2); DISASM_LOGMSG; } void disasm_RS (BYTE inst[], char mnemonic[]) { DISASM_COMMON_VARS; int r1,r3,b2,d2; r1 = inst[1] >> 4; r3 = inst[1] & 0x0F; b2 = inst[2] >> 4; d2 = (inst[2] & 0x0F) << 8 | inst[3]; DISASM_SET_NAME; DISASM_PRINT_OPERANDS "%d,%d,%d(%d)",r1,r3,d2,b2); DISASM_LOGMSG; } // "Mnemonic R1,D2(B2)" void disasm_RS_R1D2B2 (BYTE inst[], char mnemonic[]) { DISASM_COMMON_VARS; int r1,b2,d2; r1 = inst[1] >> 4; b2 = inst[2] >> 4; d2 = (inst[2] & 0x0F) << 8 | inst[3]; DISASM_SET_NAME; DISASM_PRINT_OPERANDS "%d,%d(%d)",r1,d2,b2); DISASM_LOGMSG; } void disasm_RSE (BYTE inst[], char mnemonic[]) { DISASM_COMMON_VARS; int r1,r3,b2,d2; r1 = inst[1] >> 4; r3 = inst[1] & 0x0F; b2 = inst[2] >> 4; d2 = (inst[2] & 0x0F) << 8 | inst[3]; DISASM_SET_NAME; DISASM_PRINT_OPERANDS "%d,%d,%d(%d)",r1,r3,d2,b2); DISASM_LOGMSG; } void disasm_RSY (BYTE inst[], char mnemonic[]) { DISASM_COMMON_VARS; int r1,r3,b2,d2; r1 = inst[1] >> 4; r3 = inst[1] & 0x0F; b2 = inst[2] >> 4; d2 = (((S8)inst[4]) << 12) | (inst[2] & 0x0F) << 8 | inst[3]; DISASM_SET_NAME; DISASM_PRINT_OPERANDS "%d,%d,%d(%d)",r1,r3,d2,b2); DISASM_LOGMSG; } void disasm_RSL (BYTE inst[], char mnemonic[]) { DISASM_COMMON_VARS; int l1,b1,d1; l1 = inst[1] >> 4; b1 = inst[2] >> 4; d1 = (inst[2] & 0x0F) << 8 | inst[3]; DISASM_SET_NAME; DISASM_PRINT_OPERANDS "%d(%d,%d)",d1,l1+1,b1); DISASM_LOGMSG; } void disasm_RSI (BYTE inst[], char mnemonic[]) { DISASM_COMMON_VARS; int r1,r3,i2; r1 = inst[1] >> 4; r3 = inst[1] & 0x0F; i2 = (S16)(((U16)inst[2] << 8) | inst[3]); DISASM_SET_NAME; DISASM_PRINT_OPERANDS "%d,%d,*%+d",r1,r3,i2*2); DISASM_LOGMSG; } void disasm_RI (BYTE inst[], char mnemonic[]) { DISASM_COMMON_VARS; int r1,i2; r1 = inst[1] >> 4; i2 = (S16)(((U16)inst[2] << 8) | inst[3]); DISASM_SET_NAME; DISASM_PRINT_OPERANDS "%d,%d",r1,i2); DISASM_LOGMSG; } void disasm_RI_B (BYTE inst[], char mnemonic[]) { DISASM_COMMON_VARS; int r1,i2; r1 = inst[1] >> 4; i2 = (S16)(((U16)inst[2] << 8) | inst[3]); DISASM_SET_NAME; DISASM_PRINT_OPERANDS "%d,*%+d",r1,i2*2); DISASM_LOGMSG; } void disasm_RIE (BYTE inst[], char mnemonic[]) { DISASM_COMMON_VARS; int r1,r3,i2; r1 = inst[1] >> 4; r3 = inst[1] & 0x0F; i2 = (S16)(((U16)inst[2] << 8) | inst[3]); DISASM_SET_NAME; DISASM_PRINT_OPERANDS "%d,%d,*%+d",r1,r3,i2*2); DISASM_LOGMSG; } void disasm_RIE_RIM (BYTE inst[], char mnemonic[]) /*208*/ { DISASM_COMMON_VARS; int r1,i2,m3; r1 = inst[1] >> 4; i2 = (S16)(((U16)inst[2] << 8) | inst[3]); m3 = inst[4] >> 4; DISASM_SET_NAME; DISASM_PRINT_OPERANDS "%d,%d,%d",r1,i2,m3); DISASM_LOGMSG; } void disasm_RIE_RRIM (BYTE inst[], char mnemonic[]) /*208*/ { DISASM_COMMON_VARS; int r1,r2,i4,m3; r1 = inst[1] >> 4; r2 = inst[1] & 0x0F; i4 = (S16)(((U16)inst[2] << 8) | inst[3]); m3 = inst[4] >> 4; DISASM_SET_NAME; DISASM_PRINT_OPERANDS "%d,%d,%d,*%+d",r1,r2,m3,i4*2); DISASM_LOGMSG; } void disasm_RIE_RMII (BYTE inst[], char mnemonic[]) /*208*/ { DISASM_COMMON_VARS; int r1,m3,i4,i2; r1 = inst[1] >> 4; m3 = inst[1] & 0x0F; i4 = (S16)(((U16)inst[2] << 8) | inst[3]); i2 = inst[4]; DISASM_SET_NAME; DISASM_PRINT_OPERANDS "%d,%d,%d,*%+d",r1,i2,m3,i4*2); DISASM_LOGMSG; } void disasm_RIE_RRIII (BYTE inst[], char mnemonic[]) /*208*/ { DISASM_COMMON_VARS; int r1,r2,i3,i4,i5; r1 = inst[1] >> 4; r2 = inst[1] & 0x0F; i3 = inst[2]; i4 = inst[3]; i5 = inst[4]; DISASM_SET_NAME; DISASM_PRINT_OPERANDS "%d,%d,%d,%d,%d",r1,r2,i3,i4,i5); DISASM_LOGMSG; } void disasm_RIL (BYTE inst[], char mnemonic[]) { DISASM_COMMON_VARS; int r1,i2; r1 = inst[1] >> 4; i2 = (S32)((((U32)inst[2] << 24) | ((U32)inst[3] << 16) | ((U32)inst[4] << 8)) | inst[5]); DISASM_SET_NAME; DISASM_PRINT_OPERANDS "%d,%"I32_FMT"d",r1,i2); DISASM_LOGMSG; } void disasm_RIL_A (BYTE inst[], char mnemonic[]) /*208*/ { DISASM_COMMON_VARS; int r1,i2; const S64 Two_S64=2; r1 = inst[1] >> 4; i2 = (S32)((((U32)inst[2] << 24) | ((U32)inst[3] << 16) | ((U32)inst[4] << 8)) | inst[5]); DISASM_SET_NAME; DISASM_PRINT_OPERANDS "%d,*%+"I64_FMT"d",r1,i2*Two_S64); DISASM_LOGMSG; } void disasm_RIS (BYTE inst[], char mnemonic[]) /*208*/ { DISASM_COMMON_VARS; int r1,i2,m3,b4,d4; r1 = inst[1] >> 4; m3 = inst[1] & 0x0F; b4 = inst[2] >> 4; d4 = (inst[2] & 0x0F) << 8 | inst[3]; i2 = inst[4]; DISASM_SET_NAME; DISASM_PRINT_OPERANDS "%d,%d,%d,%d(%d)",r1,i2,m3,d4,b4); DISASM_LOGMSG; } void disasm_RRS (BYTE inst[], char mnemonic[]) /*208*/ { DISASM_COMMON_VARS; int r1,r2,m3,b4,d4; r1 = inst[1] >> 4; r2 = inst[1] & 0x0F; b4 = inst[2] >> 4; d4 = (inst[2] & 0x0F) << 8 | inst[3]; m3 = inst[4] >> 4; DISASM_SET_NAME; DISASM_PRINT_OPERANDS "%d,%d,%d,%d(%d)",r1,r2,m3,d4,b4); DISASM_LOGMSG; } void disasm_SI (BYTE inst[], char mnemonic[]) { DISASM_COMMON_VARS; int i2,b1,d1; i2 = inst[1]; b1 = inst[2] >> 4; d1 = (inst[2] & 0x0F) << 8 | inst[3]; DISASM_SET_NAME; DISASM_PRINT_OPERANDS "%d(%d),%d",d1,b1,i2); DISASM_LOGMSG; } void disasm_SIY (BYTE inst[], char mnemonic[]) { DISASM_COMMON_VARS; int i2,b1,d1; i2 = inst[1]; b1 = inst[2] >> 4; d1 = (((S8)inst[4]) << 12) | (inst[2] & 0x0F) << 8 | inst[3]; DISASM_SET_NAME; DISASM_PRINT_OPERANDS "%d(%d),%d",d1,b1,i2); DISASM_LOGMSG; } void disasm_SIL (BYTE inst[], char mnemonic[]) /*208*/ { DISASM_COMMON_VARS; int b1,d1,i2; b1 = inst[2] >> 4; d1 = (inst[2] & 0x0F) << 8 | inst[3]; i2 = (S16)(((U16)inst[4] << 8) | inst[5]); DISASM_SET_NAME; DISASM_PRINT_OPERANDS "%d(%d),%d",d1,b1,i2); DISASM_LOGMSG; } void disasm_S (BYTE inst[], char mnemonic[]) { DISASM_COMMON_VARS; int d2,b2; b2 = inst[2] >> 4; d2 = (inst[2] & 0x0F) << 8 | inst[3]; DISASM_SET_NAME; DISASM_PRINT_OPERANDS "%d(%d)",d2,b2); DISASM_LOGMSG; } void disasm_SS (BYTE inst[], char mnemonic[]) { DISASM_COMMON_VARS; int l1,l2,b1,d1,b2,d2; l1 = inst[1] >> 4; l2 = inst[1] & 0x0F; b1 = inst[2] >> 4; d1 = (inst[2] & 0x0F) << 8 | inst[3]; b2 = inst[4] >> 4; d2 = (inst[4] & 0x0F) << 8 | inst[5]; DISASM_SET_NAME; DISASM_PRINT_OPERANDS "%d(%d,%d),%d(%d,%d)",d1,l1+1,b1,d2,l2+1,b2); DISASM_LOGMSG; } void disasm_SS_L (BYTE inst[], char mnemonic[]) { DISASM_COMMON_VARS; int l1,b1,d1,b2,d2; l1 = inst[1]; b1 = inst[2] >> 4; d1 = (inst[2] & 0x0F) << 8 | inst[3]; b2 = inst[4] >> 4; d2 = (inst[4] & 0x0F) << 8 | inst[5]; DISASM_SET_NAME; DISASM_PRINT_OPERANDS "%d(%d,%d),%d(%d)",d1,l1+1,b1,d2,b2); DISASM_LOGMSG; } // "Mnemonic D1(B1),D2(L2,B2)" void disasm_SS_L2 (BYTE inst[], char mnemonic[]) { DISASM_COMMON_VARS; int l2,b1,d1,b2,d2; l2 = inst[1]; b1 = inst[2] >> 4; d1 = (inst[2] & 0x0F) << 8 | inst[3]; b2 = inst[4] >> 4; d2 = (inst[4] & 0x0F) << 8 | inst[5]; DISASM_SET_NAME; DISASM_PRINT_OPERANDS "%d(%d),%d(%d,%d)",d1,b1,d2,l2+1,b2); DISASM_LOGMSG; } void disasm_SS_R (BYTE inst[], char mnemonic[]) { DISASM_COMMON_VARS; int r1,r3,b2,d2,b4,d4; r1 = inst[1] >> 4; r3 = inst[1] & 0x0F; b2 = inst[2] >> 4; d2 = (inst[2] & 0x0F) << 8 | inst[3]; b4 = inst[4] >> 4; d4 = (inst[4] & 0x0F) << 8 | inst[5]; DISASM_SET_NAME; DISASM_PRINT_OPERANDS "%d,%d,%d(%d),%d(%d)",r1,r3,d2,b2,d4,b4); DISASM_LOGMSG; } // "Mnemonic D1(R1,B1),D2(B2),R3" void disasm_SS_R3 (BYTE inst[], char mnemonic[]) { DISASM_COMMON_VARS; int r1,r3,b1,d1,b2,d2; r1 = inst[1] >> 4; r3 = inst[1] & 0x0F; b1 = inst[2] >> 4; d1 = (inst[2] & 0x0F) << 8 | inst[3]; b2 = inst[4] >> 4; d2 = (inst[4] & 0x0F) << 8 | inst[5]; DISASM_SET_NAME; DISASM_PRINT_OPERANDS "%d(%d,%d),%d(%d),%d",d1,r1,b1,d2,b2,r3); DISASM_LOGMSG; } // "Mnemonic R1,D2(B2),R3,D4(B4)" void disasm_SS_RSRS (BYTE inst[], char mnemonic[]) { DISASM_COMMON_VARS; int r1,r3,b2,d2,b4,d4; r1 = inst[1] >> 4; r3 = inst[1] & 0x0F; b2 = inst[2] >> 4; d2 = (inst[2] & 0x0F) << 8 | inst[3]; b4 = inst[4] >> 4; d4 = (inst[4] & 0x0F) << 8 | inst[5]; DISASM_SET_NAME; DISASM_PRINT_OPERANDS "%d,%d(%d),%d,%d(%d)",r1,d2,b2,r3,d4,b4); DISASM_LOGMSG; } // "Mnemonic D1(L1,B1),D2(B2),I3" void disasm_SS_I (BYTE inst[], char mnemonic[]) { DISASM_COMMON_VARS; int l1,i3,b1,d1,b2,d2; l1 = inst[1] >> 4; i3 = inst[1] & 0x0F; b1 = inst[2] >> 4; d1 = (inst[2] & 0x0F) << 8 | inst[3]; b2 = inst[4] >> 4; d2 = (inst[4] & 0x0F) << 8 | inst[5]; DISASM_SET_NAME; DISASM_PRINT_OPERANDS "%d(%d,%d),%d(%d),%d",d1,l1,b1,d2,b2,i3); DISASM_LOGMSG; } void disasm_SSE (BYTE inst[], char mnemonic[]) { DISASM_COMMON_VARS; int b1,d1,b2,d2; b1 = inst[2] >> 4; d1 = (inst[2] & 0x0F) << 8 | inst[3]; b2 = inst[4] >> 4; d2 = (inst[4] & 0x0F) << 8 | inst[5]; DISASM_SET_NAME; DISASM_PRINT_OPERANDS "%d(%d),%d(%d)",d1,b1,d2,b2); DISASM_LOGMSG; } void disasm_SSF (BYTE inst[], char mnemonic[]) { DISASM_COMMON_VARS; int r3,b1,d1,b2,d2; r3 = inst[1] >> 4; b1 = inst[2] >> 4; d1 = (inst[2] & 0x0F) << 8 | inst[3]; b2 = inst[4] >> 4; d2 = (inst[4] & 0x0F) << 8 | inst[5]; DISASM_SET_NAME; DISASM_PRINT_OPERANDS "%d(%d),%d(%d),%d",d1,b1,d2,b2,r3); DISASM_LOGMSG; } void disasm_VST (BYTE inst[], char mnemonic[]) { DISASM_COMMON_VARS; int vr3,rt2,vr1,rs2; vr3 = inst[2] >> 4; rt2 = inst[2] & 0x0F; vr1 = inst[3] >> 4; rs2 = inst[3] & 0x0F; DISASM_SET_NAME; DISASM_PRINT_OPERANDS "%d,%d,%d(%d)",vr1,vr3,rs2,rt2); DISASM_LOGMSG; } void disasm_VR (BYTE inst[], char mnemonic[]) { DISASM_COMMON_VARS; int vr1,fr3,gr2; fr3 = inst[2] >> 4; vr1 = inst[3] >> 4; gr2 = inst[3] & 0x0F; DISASM_SET_NAME; DISASM_PRINT_OPERANDS "%d,%d,%d",vr1,fr3,gr2); DISASM_LOGMSG; } void disasm_VS (BYTE inst[], char mnemonic[]) { DISASM_COMMON_VARS; int rs2; rs2 = inst[3] & 0x0F; DISASM_SET_NAME; DISASM_PRINT_OPERANDS "%d",rs2); DISASM_LOGMSG; } void disasm_VRSE (BYTE inst[], char mnemonic[]) { DISASM_COMMON_VARS; int vr1,vr3,d2,b2; vr3 = inst[2] >> 4; vr1 = inst[3] >> 4; b2 = inst[4] >> 4; d2 = (inst[4] & 0x0F) << 8 | inst[5]; DISASM_SET_NAME; DISASM_PRINT_OPERANDS "%d,%d,%d(%d)",vr1,vr3,d2,b2); DISASM_LOGMSG; } void disasm_S_NW (BYTE inst[], char mnemonic[]) { DISASM_COMMON_VARS; int d2,b2; b2 = inst[2] >> 4; d2 = (inst[2] & 0x0F) << 8 | inst[3]; DISASM_SET_NAME; DISASM_PRINT_OPERANDS "%d(%d)",d2,b2); DISASM_LOGMSG; } /* Gabor Hoffer (performance option) */ DLL_EXPORT zz_func s370_opcode_table[256]; static zz_func s370_opcode_a4xx[256]; static zz_func s370_opcode_a5xx[256]; static zz_func s370_opcode_a6xx[256]; static zz_func s370_opcode_a7xx[256]; static zz_func s370_opcode_b2xx[256]; static zz_func s370_opcode_b3xx[256]; /*FPE*/ static zz_func s370_opcode_b9xx[256]; static zz_func s370_opcode_c0xx[256]; /*@N3*/ static zz_func s370_opcode_c2xx[256]; /*208*/ static zz_func s370_opcode_c4xx[256]; /*208*/ static zz_func s370_opcode_c6xx[256]; /*208*/ static zz_func s370_opcode_e3xx[256]; /*@N3*/ static zz_func s370_opcode_e4xx[256]; static zz_func s370_opcode_e5xx[256]; static zz_func s370_opcode_e6xx[256]; static zz_func s370_opcode_ebxx[256]; static zz_func s370_opcode_ecxx[256]; /*@N3*/ zz_func s390_opcode_table[256]; static zz_func s390_opcode_01xx[256]; static zz_func s390_opcode_a4xx[256]; static zz_func s390_opcode_a5xx[256]; static zz_func s390_opcode_a6xx[256]; static zz_func s390_opcode_a7xx[256]; static zz_func s390_opcode_b2xx[256]; static zz_func s390_opcode_b3xx[256]; static zz_func s390_opcode_b9xx[256]; static zz_func s390_opcode_c0xx[256]; static zz_func s390_opcode_c2xx[256]; /*@Z9*/ static zz_func s390_opcode_c4xx[256]; /*208*/ static zz_func s390_opcode_c6xx[256]; /*208*/ static zz_func s390_opcode_e3xx[256]; static zz_func s390_opcode_e4xx[256]; static zz_func s390_opcode_e5xx[256]; static zz_func s390_opcode_ebxx[256]; static zz_func s390_opcode_ecxx[256]; static zz_func s390_opcode_edxx[256]; zz_func z900_opcode_table[256]; static zz_func z900_opcode_01xx[256]; static zz_func z900_opcode_a5xx[256]; static zz_func z900_opcode_a7xx[256]; static zz_func z900_opcode_b2xx[256]; static zz_func z900_opcode_b3xx[256]; static zz_func z900_opcode_b9xx[256]; static zz_func z900_opcode_c0xx[256]; static zz_func z900_opcode_c2xx[256]; /*@Z9*/ static zz_func z900_opcode_c4xx[256]; /*208*/ static zz_func z900_opcode_c6xx[256]; /*208*/ static zz_func z900_opcode_c8xx[256]; static zz_func z900_opcode_e3xx[256]; static zz_func z900_opcode_e5xx[256]; static zz_func z900_opcode_ebxx[256]; static zz_func z900_opcode_ecxx[256]; static zz_func z900_opcode_edxx[256]; DLL_EXPORT void copy_opcode_tables() { int i; for (i = 0; i < 256; i++) { #if defined(_370) s370_opcode_table[i] = opcode_table[i][ARCH_370]; s370_opcode_a4xx [i] = v_opcode_a4xx [i][ARCH_370]; s370_opcode_a5xx [i] = v_opcode_a5xx [i][ARCH_370]; s370_opcode_a6xx [i] = v_opcode_a6xx [i][ARCH_370]; s370_opcode_a7xx [i] = opcode_a7xx [i&0x0F][ARCH_370]; s370_opcode_b2xx [i] = opcode_b2xx [i][ARCH_370]; s370_opcode_b3xx [i] = opcode_b3xx [i][ARCH_370]; /*FPE*/ s370_opcode_b9xx [i] = opcode_b9xx [i][ARCH_370]; s370_opcode_c0xx [i] = opcode_c0xx [i&0x0F][ARCH_370]; /*@N3*/ s370_opcode_c2xx [i] = opcode_c2xx [i&0x0F][ARCH_370]; /*208*/ s370_opcode_c4xx [i] = opcode_c4xx [i&0x0F][ARCH_370]; /*208*/ s370_opcode_c6xx [i] = opcode_c6xx [i&0x0F][ARCH_370]; /*208*/ s370_opcode_e3xx [i] = opcode_e3xx [i][ARCH_370]; /*@N3*/ s370_opcode_e4xx [i] = v_opcode_e4xx [i][ARCH_370]; s370_opcode_e5xx [i] = opcode_e5xx [i][ARCH_370]; s370_opcode_e6xx [i] = opcode_e6xx [i][ARCH_370]; s370_opcode_ebxx [i] = opcode_ebxx [i][ARCH_370]; s370_opcode_ecxx [i] = opcode_ecxx [i][ARCH_370]; /*@N3*/ #endif #if defined(_390) s390_opcode_table[i] = opcode_table[i][ARCH_390]; s390_opcode_01xx [i] = opcode_01xx [i][ARCH_390]; s390_opcode_a4xx [i] = v_opcode_a4xx [i][ARCH_390]; s390_opcode_a5xx [i] = v_opcode_a5xx [i][ARCH_390]; s390_opcode_a6xx [i] = v_opcode_a6xx [i][ARCH_390]; s390_opcode_a7xx [i] = opcode_a7xx [i&0x0F][ARCH_390]; s390_opcode_b2xx [i] = opcode_b2xx [i][ARCH_390]; s390_opcode_b3xx [i] = opcode_b3xx [i][ARCH_390]; s390_opcode_b9xx [i] = opcode_b9xx [i][ARCH_390]; s390_opcode_c0xx [i] = opcode_c0xx [i&0x0F][ARCH_390]; s390_opcode_c2xx [i] = opcode_c2xx [i&0x0F][ARCH_390]; /*@Z9*/ s390_opcode_c4xx [i] = opcode_c4xx [i&0x0F][ARCH_390]; /*208*/ s390_opcode_c6xx [i] = opcode_c6xx [i&0x0F][ARCH_390]; /*208*/ s390_opcode_e3xx [i] = opcode_e3xx [i][ARCH_390]; s390_opcode_e4xx [i] = v_opcode_e4xx [i][ARCH_390]; s390_opcode_e5xx [i] = opcode_e5xx [i][ARCH_390]; s390_opcode_ebxx [i] = opcode_ebxx [i][ARCH_390]; s390_opcode_ecxx [i] = opcode_ecxx [i][ARCH_390]; s390_opcode_edxx [i] = opcode_edxx [i][ARCH_390]; #endif #if defined(_900) z900_opcode_table[i] = opcode_table[i][ARCH_900]; z900_opcode_01xx [i] = opcode_01xx [i][ARCH_900]; z900_opcode_a5xx [i] = opcode_a5xx [i&0x0F][ARCH_900]; z900_opcode_a7xx [i] = opcode_a7xx [i&0x0F][ARCH_900]; z900_opcode_b2xx [i] = opcode_b2xx [i][ARCH_900]; z900_opcode_b3xx [i] = opcode_b3xx [i][ARCH_900]; z900_opcode_b9xx [i] = opcode_b9xx [i][ARCH_900]; z900_opcode_c0xx [i] = opcode_c0xx [i&0x0F][ARCH_900]; z900_opcode_c2xx [i] = opcode_c2xx [i&0x0F][ARCH_900]; /*@Z9*/ z900_opcode_c4xx [i] = opcode_c4xx [i&0x0F][ARCH_900]; /*208*/ z900_opcode_c6xx [i] = opcode_c6xx [i&0x0F][ARCH_900]; /*208*/ z900_opcode_c8xx [i] = opcode_c8xx [i&0x0F][ARCH_900]; z900_opcode_e3xx [i] = opcode_e3xx [i][ARCH_900]; z900_opcode_e5xx [i] = opcode_e5xx [i][ARCH_900]; z900_opcode_ebxx [i] = opcode_ebxx [i][ARCH_900]; z900_opcode_ecxx [i] = opcode_ecxx [i][ARCH_900]; z900_opcode_edxx [i] = opcode_edxx [i][ARCH_900]; #endif } } void set_opcode_pointers(REGS *regs) { #if defined(_370) memcpy(regs->s370_opcode_table, s370_opcode_table, sizeof(s370_opcode_table)); regs->s370_opcode_a4xx = s370_opcode_a4xx; regs->s370_opcode_a5xx = s370_opcode_a5xx; regs->s370_opcode_a6xx = s370_opcode_a6xx; #if defined(MULTI_BYTE_ASSIST) memcpy(regs->s370_opcode_a7xx, s370_opcode_a7xx, sizeof(s370_opcode_a7xx)); memcpy(regs->s370_opcode_b2xx, s370_opcode_b2xx, sizeof(s370_opcode_b2xx)); memcpy(regs->s370_opcode_b9xx, s370_opcode_b9xx, sizeof(s370_opcode_b9xx)); memcpy(regs->s370_opcode_c0xx, s370_opcode_c0xx, /*@N3*/ sizeof(s370_opcode_c0xx)); /*@N3*/ memcpy(regs->s370_opcode_e3xx, s370_opcode_e3xx, /*@N3*/ sizeof(s370_opcode_e3xx)); /*@N3*/ memcpy(regs->s370_opcode_ebxx, s370_opcode_ebxx, sizeof(s370_opcode_ebxx)); #else regs->s370_opcode_a7xx = s370_opcode_a7xx; regs->s370_opcode_b2xx = s370_opcode_b2xx; regs->s370_opcode_b9xx = s370_opcode_b9xx; regs->s370_opcode_c0xx = s370_opcode_c0xx; /*@N3*/ regs->s370_opcode_e3xx = s370_opcode_e3xx; /*@N3*/ regs->s370_opcode_ebxx = s370_opcode_ebxx; #endif regs->s370_opcode_b3xx = s370_opcode_b3xx; /*FPE*/ regs->s370_opcode_c2xx = s370_opcode_c2xx; /*208*/ regs->s370_opcode_c4xx = s370_opcode_c4xx; /*208*/ regs->s370_opcode_c6xx = s370_opcode_c6xx; /*208*/ regs->s370_opcode_e4xx = s370_opcode_e4xx; regs->s370_opcode_e5xx = s370_opcode_e5xx; regs->s370_opcode_e6xx = s370_opcode_e6xx; regs->s370_opcode_ecxx = s370_opcode_ecxx; /*@N3*/ #endif #if defined(_390) memcpy(regs->s390_opcode_table, s390_opcode_table, sizeof(s390_opcode_table)); regs->s390_opcode_01xx = s390_opcode_01xx; regs->s390_opcode_a4xx = s390_opcode_a4xx; regs->s390_opcode_a5xx = s390_opcode_a5xx; regs->s390_opcode_a6xx = s390_opcode_a6xx; #if defined(MULTI_BYTE_ASSIST) memcpy(regs->s390_opcode_a7xx, s390_opcode_a7xx, sizeof(s390_opcode_a7xx)); memcpy(regs->s390_opcode_b2xx, s390_opcode_b2xx, sizeof(s390_opcode_b2xx)); memcpy(regs->s390_opcode_b9xx, s390_opcode_b9xx, sizeof(s390_opcode_b9xx)); memcpy(regs->s390_opcode_c0xx, s390_opcode_c0xx, sizeof(s390_opcode_c0xx)); memcpy(regs->s390_opcode_e3xx, s390_opcode_e3xx, sizeof(s390_opcode_e3xx)); memcpy(regs->s390_opcode_ebxx, s390_opcode_ebxx, sizeof(s390_opcode_ebxx)); #else regs->s390_opcode_a7xx = s390_opcode_a7xx; regs->s390_opcode_b2xx = s390_opcode_b2xx; regs->s390_opcode_b9xx = s390_opcode_b9xx; regs->s390_opcode_c0xx = s390_opcode_c0xx; regs->s390_opcode_e3xx = s390_opcode_e3xx; regs->s390_opcode_ebxx = s390_opcode_ebxx; #endif regs->s390_opcode_b3xx = s390_opcode_b3xx; regs->s390_opcode_c2xx = s390_opcode_c2xx; /*@Z9*/ regs->s390_opcode_c4xx = s390_opcode_c4xx; /*208*/ regs->s390_opcode_c6xx = s390_opcode_c6xx; /*208*/ regs->s390_opcode_e4xx = s390_opcode_e4xx; regs->s390_opcode_e5xx = s390_opcode_e5xx; regs->s390_opcode_ecxx = s390_opcode_ecxx; regs->s390_opcode_edxx = s390_opcode_edxx; #endif #if defined(_900) memcpy(regs->z900_opcode_table, z900_opcode_table, sizeof(z900_opcode_table)); regs->z900_opcode_01xx = z900_opcode_01xx; regs->z900_opcode_a5xx = z900_opcode_a5xx; #if defined(MULTI_BYTE_ASSIST) memcpy(regs->z900_opcode_a7xx, z900_opcode_a7xx, sizeof(z900_opcode_a7xx)); memcpy(regs->z900_opcode_b2xx, z900_opcode_b2xx, sizeof(z900_opcode_b2xx)); memcpy(regs->z900_opcode_b9xx, z900_opcode_b9xx, sizeof(z900_opcode_b9xx)); memcpy(regs->z900_opcode_c0xx, z900_opcode_c0xx, sizeof(z900_opcode_c0xx)); memcpy(regs->z900_opcode_e3xx, z900_opcode_e3xx, sizeof(z900_opcode_e3xx)); memcpy(regs->z900_opcode_ebxx, z900_opcode_ebxx, sizeof(z900_opcode_ebxx)); #else regs->z900_opcode_a7xx = z900_opcode_a7xx; regs->z900_opcode_b2xx = z900_opcode_b2xx; regs->z900_opcode_b9xx = z900_opcode_b9xx; regs->z900_opcode_c0xx = z900_opcode_c0xx; regs->z900_opcode_e3xx = z900_opcode_e3xx; regs->z900_opcode_ebxx = z900_opcode_ebxx; #endif regs->z900_opcode_b3xx = z900_opcode_b3xx; regs->z900_opcode_c2xx = z900_opcode_c2xx; /*@Z9*/ regs->z900_opcode_c4xx = z900_opcode_c4xx; /*208*/ regs->z900_opcode_c6xx = z900_opcode_c6xx; /*208*/ regs->z900_opcode_c8xx = z900_opcode_c8xx; regs->z900_opcode_e5xx = z900_opcode_e5xx; regs->z900_opcode_ecxx = z900_opcode_ecxx; regs->z900_opcode_edxx = z900_opcode_edxx; #endif } DLL_EXPORT zz_func opcode_table[256][GEN_MAXARCH] = { /*00*/ GENx___x___x___ , /*01*/ GENx___x390x900 (execute_01xx,01xx,""), /*02*/ GENx___x___x___ , /*03*/ GENx___x___x___ , /*04*/ GENx370x390x900 (set_program_mask,RR_R1,"SPM"), /*05*/ GENx370x390x900 (branch_and_link_register,RR,"BALR"), /*06*/ GENx370x390x900 (branch_on_count_register,RR,"BCTR"), /*07*/ GENx370x390x900 (branch_on_condition_register,RR,"BCR"), /*08*/ GENx370x___x___ (set_storage_key,RR,"SSK"), /*09*/ GENx370x___x___ (insert_storage_key,RR,"ISK"), /*0A*/ GENx370x390x900 (supervisor_call,RR_SVC,"SVC"), /*0B*/ GENx___x390x900 (branch_and_set_mode,RR,"BSM"), /*0C*/ GENx___x390x900 (branch_and_save_and_set_mode,RR,"BASSM"), /*0D*/ GENx370x390x900 (branch_and_save_register,RR,"BASR"), /*0E*/ GENx370x390x900 (move_long,RR,"MVCL"), /*0F*/ GENx370x390x900 (compare_logical_character_long,RR,"CLCL"), /*10*/ GENx370x390x900 (load_positive_register,RR,"LPR"), /*11*/ GENx370x390x900 (load_negative_register,RR,"LNR"), /*12*/ GENx370x390x900 (load_and_test_register,RR,"LTR"), /*13*/ GENx370x390x900 (load_complement_register,RR,"LCR"), /*14*/ GENx370x390x900 (and_register,RR,"NR"), /*15*/ GENx370x390x900 (compare_logical_register,RR,"CLR"), /*16*/ GENx370x390x900 (or_register,RR,"OR"), /*17*/ GENx370x390x900 (exclusive_or_register,RR,"XR"), /*18*/ GENx370x390x900 (load_register,RR,"LR"), /*19*/ GENx370x390x900 (compare_register,RR,"CR"), /*1A*/ GENx370x390x900 (add_register,RR,"AR"), /*1B*/ GENx370x390x900 (subtract_register,RR,"SR"), /*1C*/ GENx370x390x900 (multiply_register,RR,"MR"), /*1D*/ GENx370x390x900 (divide_register,RR,"DR"), /*1E*/ GENx370x390x900 (add_logical_register,RR,"ALR"), /*1F*/ GENx370x390x900 (subtract_logical_register,RR,"SLR"), /*20*/ GENx370x390x900 (load_positive_float_long_reg,RR,"LPDR"), /*21*/ GENx370x390x900 (load_negative_float_long_reg,RR,"LNDR"), /*22*/ GENx370x390x900 (load_and_test_float_long_reg,RR,"LTDR"), /*23*/ GENx370x390x900 (load_complement_float_long_reg,RR,"LCDR"), /*24*/ GENx370x390x900 (halve_float_long_reg,RR,"HDR"), /*25*/ GENx370x390x900 (load_rounded_float_long_reg,RR,"LDXR"), /*26*/ GENx370x390x900 (multiply_float_ext_reg,RR,"MXR"), /*27*/ GENx370x390x900 (multiply_float_long_to_ext_reg,RR,"MXDR"), /*28*/ GENx370x390x900 (load_float_long_reg,RR,"LDR"), /*29*/ GENx370x390x900 (compare_float_long_reg,RR,"CDR"), /*2A*/ GENx370x390x900 (add_float_long_reg,RR,"ADR"), /*2B*/ GENx370x390x900 (subtract_float_long_reg,RR,"SDR"), /*2C*/ GENx370x390x900 (multiply_float_long_reg,RR,"MDR"), /*2D*/ GENx370x390x900 (divide_float_long_reg,RR,"DDR"), /*2E*/ GENx370x390x900 (add_unnormal_float_long_reg,RR,"AWR"), /*2F*/ GENx370x390x900 (subtract_unnormal_float_long_reg,RR,"SWR"), /*30*/ GENx370x390x900 (load_positive_float_short_reg,RR,"LPER"), /*31*/ GENx370x390x900 (load_negative_float_short_reg,RR,"LNER"), /*32*/ GENx370x390x900 (load_and_test_float_short_reg,RR,"LTER"), /*33*/ GENx370x390x900 (load_complement_float_short_reg,RR,"LCER"), /*34*/ GENx370x390x900 (halve_float_short_reg,RR,"HER"), /*35*/ GENx370x390x900 (load_rounded_float_short_reg,RR,"LEDR"), /*36*/ GENx370x390x900 (add_float_ext_reg,RR,"AXR"), /*37*/ GENx370x390x900 (subtract_float_ext_reg,RR,"SXR"), /*38*/ GENx370x390x900 (load_float_short_reg,RR,"LER"), /*39*/ GENx370x390x900 (compare_float_short_reg,RR,"CER"), /*3A*/ GENx370x390x900 (add_float_short_reg,RR,"AER"), /*3B*/ GENx370x390x900 (subtract_float_short_reg,RR,"SER"), /*3C*/ GENx370x390x900 (multiply_float_short_to_long_reg,RR,"MDER"), /*3D*/ GENx370x390x900 (divide_float_short_reg,RR,"DER"), /*3E*/ GENx370x390x900 (add_unnormal_float_short_reg,RR,"AUR"), /*3F*/ GENx370x390x900 (subtract_unnormal_float_short_reg,RR,"SUR"), /*40*/ GENx370x390x900 (store_halfword,RX,"STH"), /*41*/ GENx370x390x900 (load_address,RX,"LA"), /*42*/ GENx370x390x900 (store_character,RX,"STC"), /*43*/ GENx370x390x900 (insert_character,RX,"IC"), /*44*/ GENx370x390x900 (execute,RX,"EX"), /*45*/ GENx370x390x900 (branch_and_link,RX,"BAL"), /*46*/ GENx370x390x900 (branch_on_count,RX,"BCT"), /*47*/ GENx370x390x900 (branch_on_condition,RX,"BC"), /*48*/ GENx370x390x900 (load_halfword,RX,"LH"), /*49*/ GENx370x390x900 (compare_halfword,RX,"CH"), /*4A*/ GENx370x390x900 (add_halfword,RX,"AH"), /*4B*/ GENx370x390x900 (subtract_halfword,RX,"SH"), /*4C*/ GENx370x390x900 (multiply_halfword,RX,"MH"), /*4D*/ GENx370x390x900 (branch_and_save,RX,"BAS"), /*4E*/ GENx370x390x900 (convert_to_decimal,RX,"CVD"), /*4F*/ GENx370x390x900 (convert_to_binary,RX,"CVB"), /*50*/ GENx370x390x900 (store,RX,"ST"), /*51*/ GENx___x390x900 (load_address_extended,RX,"LAE"), /*52*/ GENx___x___x___ , /*53*/ GENx___x___x___ , /*54*/ GENx370x390x900 (and,RX,"N"), /*55*/ GENx370x390x900 (compare_logical,RX,"CL"), /*56*/ GENx370x390x900 (or,RX,"O"), /*57*/ GENx370x390x900 (exclusive_or,RX,"X"), /*58*/ GENx370x390x900 (load,RX,"L"), /*59*/ GENx370x390x900 (compare,RX,"C"), /*5A*/ GENx370x390x900 (add,RX,"A"), /*5B*/ GENx370x390x900 (subtract,RX,"S"), /*5C*/ GENx370x390x900 (multiply,RX,"M"), /*5D*/ GENx370x390x900 (divide,RX,"D"), /*5E*/ GENx370x390x900 (add_logical,RX,"AL"), /*5F*/ GENx370x390x900 (subtract_logical,RX,"SL"), /*60*/ GENx370x390x900 (store_float_long,RX,"STD"), /*61*/ GENx___x___x___ , /*62*/ GENx___x___x___ , /*63*/ GENx___x___x___ , /*64*/ GENx___x___x___ , /*65*/ GENx___x___x___ , /*66*/ GENx___x___x___ , /*67*/ GENx370x390x900 (multiply_float_long_to_ext,RX,"MXD"), /*68*/ GENx370x390x900 (load_float_long,RX,"LD"), /*69*/ GENx370x390x900 (compare_float_long,RX,"CD"), /*6A*/ GENx370x390x900 (add_float_long,RX,"AD"), /*6B*/ GENx370x390x900 (subtract_float_long,RX,"SD"), /*6C*/ GENx370x390x900 (multiply_float_long,RX,"MD"), /*6D*/ GENx370x390x900 (divide_float_long,RX,"DD"), /*6E*/ GENx370x390x900 (add_unnormal_float_long,RX,"AW"), /*6F*/ GENx370x390x900 (subtract_unnormal_float_long,RX,"SW"), /*70*/ GENx370x390x900 (store_float_short,RX,"STE"), /*71*/ GENx37Xx390x900 (multiply_single,RX,"MS"), /*72*/ GENx___x___x___ , /*73*/ GENx___x___x___ , /*74*/ GENx___x___x___ , /*75*/ GENx___x___x___ , /*76*/ GENx___x___x___ , /*77*/ GENx___x___x___ , /*78*/ GENx370x390x900 (load_float_short,RX,"LE"), /*79*/ GENx370x390x900 (compare_float_short,RX,"CE"), /*7A*/ GENx370x390x900 (add_float_short,RX,"AE"), /*7B*/ GENx370x390x900 (subtract_float_short,RX,"SE"), /*7C*/ GENx370x390x900 (multiply_float_short_to_long,RX,"MDE"), /*7D*/ GENx370x390x900 (divide_float_short,RX,"DE"), /*7E*/ GENx370x390x900 (add_unnormal_float_short,RX,"AU"), /*7F*/ GENx370x390x900 (subtract_unnormal_float_short,RX,"SU"), /*80*/ GENx370x390x900 (set_system_mask,S,"SSM"), /*81*/ GENx___x___x___ , /*82*/ GENx370x390x900 (load_program_status_word,S,"LPSW"), /*83*/ GENx370x390x900 (diagnose,RS,"DIAG"), /*84*/ GENx37Xx390x900 (branch_relative_on_index_high,RSI,"BRXH"), /*85*/ GENx37Xx390x900 (branch_relative_on_index_low_or_equal,RSI,"BRXLE"), /*86*/ GENx370x390x900 (branch_on_index_high,RS,"BXH"), /*87*/ GENx370x390x900 (branch_on_index_low_or_equal,RS,"BXLE"), /*88*/ GENx370x390x900 (shift_right_single_logical,RS_R1D2B2,"SRL"), /*89*/ GENx370x390x900 (shift_left_single_logical,RS_R1D2B2,"SLL"), /*8A*/ GENx370x390x900 (shift_right_single,RS_R1D2B2,"SRA"), /*8B*/ GENx370x390x900 (shift_left_single,RS_R1D2B2,"SLA"), /*8C*/ GENx370x390x900 (shift_right_double_logical,RS_R1D2B2,"SRDL"), /*8D*/ GENx370x390x900 (shift_left_double_logical,RS_R1D2B2,"SLDL"), /*8E*/ GENx370x390x900 (shift_right_double,RS_R1D2B2,"SRDA"), /*8F*/ GENx370x390x900 (shift_left_double,RS_R1D2B2,"SLDA"), /*90*/ GENx370x390x900 (store_multiple,RS,"STM"), /*91*/ GENx370x390x900 (test_under_mask,SI,"TM"), /*92*/ GENx370x390x900 (move_immediate,SI,"MVI"), /*93*/ GENx370x390x900 (test_and_set,S,"TS"), /*94*/ GENx370x390x900 (and_immediate,SI,"NI"), /*95*/ GENx370x390x900 (compare_logical_immediate,SI,"CLI"), /*96*/ GENx370x390x900 (or_immediate,SI,"OI"), /*97*/ GENx370x390x900 (exclusive_or_immediate,SI,"XI"), /*98*/ GENx370x390x900 (load_multiple,RS,"LM"), /*99*/ GENx___x390x900 (trace,RS,"TRACE"), /*9A*/ GENx___x390x900 (load_access_multiple,RS,"LAM"), /*9B*/ GENx___x390x900 (store_access_multiple,RS,"STAM"), /*9C*/ GENx370x___x___ (start_io,S,"SIO"), /*9D*/ GENx370x___x___ (test_io,S,"TIO"), /*9E*/ GENx370x___x___ (halt_io,S,"HIO"), /*9F*/ GENx370x___x___ (test_channel,S,"TCH"), /*A0*/ GENx___x___x___ , /*A1*/ GENx___x___x___ , /*A2*/ GENx___x___x___ , /*A3*/ GENx___x___x___ , /*A4*/ GENx370x390x___ (execute_a4xx,a4xx,""), /*A5*/ GENx370x390x900 (execute_a5xx,a5xx,""), /*A6*/ GENx370x390x___ (execute_a6xx,a6xx,""), /*A7*/ GENx37Xx390x900 (execute_a7xx,a7xx,""), /*A8*/ GENx370x390x900 (move_long_extended,RS,"MVCLE"), /*A9*/ GENx370x390x900 (compare_logical_long_extended,RS,"CLCLE"), /*AA*/ GENx___x___x___ , /*AB*/ GENx___x___x___ , /*AC*/ GENx370x390x900 (store_then_and_system_mask,SI,"STNSM"), /*AD*/ GENx370x390x900 (store_then_or_system_mask,SI,"STOSM"), /*AE*/ GENx370x390x900 (signal_procesor,RS,"SIGP"), /*AF*/ GENx370x390x900 (monitor_call,SI,"MC"), /*B0*/ GENx___x___x___ , /*B1*/ GENx370x390x900 (load_real_address,RX,"LRA"), /*B2*/ GENx370x390x900 (execute_b2xx,b2xx,""), /*B3*/ GENx37Xx390x900 (execute_b3xx,b3xx,""), /*B4*/ GENx___x___x___ , /*B5*/ GENx___x___x___ , /*B6*/ GENx370x390x900 (store_control,RS,"STCTL"), /*B7*/ GENx370x390x900 (load_control,RS,"LCTL"), /*B8*/ GENx___x___x___ , /*B9*/ GENx37Xx390x900 (execute_b9xx,b9xx,""), /*BA*/ GENx370x390x900 (compare_and_swap,RS,"CS"), /*BB*/ GENx370x390x900 (compare_double_and_swap,RS,"CDS"), /*BC*/ GENx___x___x___ , /*BD*/ GENx370x390x900 (compare_logical_characters_under_mask,RS,"CLM"), /*BE*/ GENx370x390x900 (store_characters_under_mask,RS,"STCM"), /*BF*/ GENx370x390x900 (insert_characters_under_mask,RS,"ICM"), /*C0*/ GENx37Xx390x900 (execute_c0xx,c0xx,""), /*C1*/ GENx___x___x___ , /*C2*/ GENx37Xx390x900 (execute_c2xx,c2xx,""), /*@Z9*/ /*C3*/ GENx___x___x___ , /*C4*/ GENx37Xx390x900 (execute_c4xx,c4xx,""), /*208*/ /*C5*/ GENx___x___x___ , /*C6*/ GENx37Xx390x900 (execute_c6xx,c6xx,""), /*208*/ /*C7*/ GENx___x___x___ , /*C8*/ GENx___x___x900 (execute_c8xx,c8xx,""), /*C9*/ GENx___x___x___ , /*CA*/ GENx___x___x___ , /*CB*/ GENx___x___x___ , /*CC*/ GENx___x___x___ , /*CD*/ GENx___x___x___ , /*CE*/ GENx___x___x___ , /*CF*/ GENx___x___x___ , /*D0*/ GENx37Xx390x900 (translate_and_test_reverse,SS_L,"TRTR"), /*D1*/ GENx370x390x900 (move_numerics,SS_L,"MVN"), /*D2*/ GENx370x390x900 (move_character,SS_L,"MVC"), /*D3*/ GENx370x390x900 (move_zones,SS_L,"MVZ"), /*D4*/ GENx370x390x900 (and_character,SS_L,"NC"), /*D5*/ GENx370x390x900 (compare_logical_character,SS_L,"CLC"), /*D6*/ GENx370x390x900 (or_character,SS_L,"OC"), /*D7*/ GENx370x390x900 (exclusive_or_character,SS_L,"XC"), /*D8*/ GENx___x___x___ , /*D9*/ GENx370x390x900 (move_with_key,SS_R3,"MVCK"), /*DA*/ GENx370x390x900 (move_to_primary,SS_R3,"MVCP"), /*DB*/ GENx370x390x900 (move_to_secondary,SS_R3,"MVCS"), /*DC*/ GENx370x390x900 (translate,SS_L,"TR"), /*DD*/ GENx370x390x900 (translate_and_test,SS_L,"TRT"), /*DE*/ GENx370x390x900 (edit_x_edit_and_mark,SS_L,"ED"), /*DF*/ GENx370x390x900 (edit_x_edit_and_mark,SS_L,"EDMK"), /*E0*/ GENx___x___x___ , /*E1*/ GENx37Xx390x900 (pack_unicode,SS_L2,"PKU"), /*E2*/ GENx37Xx390x900 (unpack_unicode,SS_L,"UNPKU"), /*E3*/ GENx37Xx390x900 (execute_e3xx,e3xx,""), /*E4*/ GENx370x390x___ (execute_e4xx,e4xx,""), /*E5*/ GENx370x390x900 (execute_e5xx,e5xx,""), /*E6*/ GENx370x___x___ (execute_e6xx,e6xx,""), /*E7*/ GENx___x___x___ , /*E8*/ GENx370x390x900 (move_inverse,SS_L,"MVCIN"), /*E9*/ GENx37Xx390x900 (pack_ascii,SS_L2,"PKA"), /*EA*/ GENx37Xx390x900 (unpack_ascii,SS_L,"UNPKA"), /*EB*/ GENx37Xx390x900 (execute_ebxx,ebxx,""), /*EC*/ GENx37Xx390x900 (execute_ecxx,ecxx,""), /*ED*/ GENx37Xx390x900 (execute_edxx,edxx,""), /*EE*/ GENx___x390x900 (perform_locked_operation,SS_RSRS,"PLO"), /*EF*/ GENx___x___x900 (load_multiple_disjoint,SS_R,"LMD"), /*F0*/ GENx370x390x900 (shift_and_round_decimal,SS_I,"SRP"), /*F1*/ GENx370x390x900 (move_with_offset,SS,"MVO"), /*F2*/ GENx370x390x900 (pack,SS,"PACK"), /*F3*/ GENx370x390x900 (unpack,SS,"UNPK"), /*F4*/ GENx___x___x___ , /*F5*/ GENx___x___x___ , /*F6*/ GENx___x___x___ , /*F7*/ GENx___x___x___ , /*F8*/ GENx370x390x900 (zero_and_add,SS,"ZAP"), /*F9*/ GENx370x390x900 (compare_decimal,SS,"CP"), /*FA*/ GENx370x390x900 (add_decimal,SS,"AP"), /*FB*/ GENx370x390x900 (subtract_decimal,SS,"SP"), /*FC*/ GENx370x390x900 (multiply_decimal,SS,"MP"), /*FD*/ GENx370x390x900 (divide_decimal,SS,"DP"), /*FE*/ GENx___x___x___ , /*FF*/ GENx___x___x___ }; DLL_EXPORT zz_func opcode_01xx[256][GEN_MAXARCH] = { /*0100*/ GENx___x___x___ , /*0101*/ GENx___x390x900 (program_return,E,"PR"), /*0102*/ GENx___x390x900 (update_tree,E,"UPT"), /*0103*/ GENx___x___x___ , /*0104*/ GENx___x___x900 (perform_timing_facility_function,E,"PTFF"), /*0105*/ GENx___x___x___ , /*(clear_message,?,"CMSG"),*/ /*0106*/ GENx___x___x___ , /*(test_message,?,"TMSG"),*/ /*0107*/ GENx___x390x900 (set_clock_programmable_field,E,"SCKPF"), /*0108*/ GENx___x___x___ , /*(test_message_path_state,?,"TMPS"),*/ /*0109*/ GENx___x___x___ , /*(clear_message_path_state,?,"CMPS"),*/ /*010A*/ GENx___x390x900 (perform_floating_point_operation,E,"PFPO"), /*010B*/ GENx___x390x900 (test_addressing_mode,E,"TAM"), /*010C*/ GENx___x390x900 (set_addressing_mode_24,E,"SAM24"), /*010D*/ GENx___x390x900 (set_addressing_mode_31,E,"SAM31"), /*010E*/ GENx___x___x900 (set_addressing_mode_64,E,"SAM64"), /*010F*/ GENx___x___x___ , /*0110*/ GENx___x___x___ , /*0111*/ GENx___x___x___ , /*0112*/ GENx___x___x___ , /*0113*/ GENx___x___x___ , /*0114*/ GENx___x___x___ , /*0115*/ GENx___x___x___ , /*0116*/ GENx___x___x___ , /*0117*/ GENx___x___x___ , /*0118*/ GENx___x___x___ , /*0119*/ GENx___x___x___ , /*011A*/ GENx___x___x___ , /*011B*/ GENx___x___x___ , /*011C*/ GENx___x___x___ , /*011D*/ GENx___x___x___ , /*011E*/ GENx___x___x___ , /*011F*/ GENx___x___x___ , /*0120*/ GENx___x___x___ , /*0121*/ GENx___x___x___ , /*0122*/ GENx___x___x___ , /*0123*/ GENx___x___x___ , /*0124*/ GENx___x___x___ , /*0125*/ GENx___x___x___ , /*0126*/ GENx___x___x___ , /*0127*/ GENx___x___x___ , /*0128*/ GENx___x___x___ , /*0129*/ GENx___x___x___ , /*012A*/ GENx___x___x___ , /*012B*/ GENx___x___x___ , /*012C*/ GENx___x___x___ , /*012D*/ GENx___x___x___ , /*012E*/ GENx___x___x___ , /*012F*/ GENx___x___x___ , /*0130*/ GENx___x___x___ , /*0131*/ GENx___x___x___ , /*0132*/ GENx___x___x___ , /*0133*/ GENx___x___x___ , /*0134*/ GENx___x___x___ , /*0135*/ GENx___x___x___ , /*0136*/ GENx___x___x___ , /*0137*/ GENx___x___x___ , /*0138*/ GENx___x___x___ , /*0139*/ GENx___x___x___ , /*013A*/ GENx___x___x___ , /*013B*/ GENx___x___x___ , /*013C*/ GENx___x___x___ , /*013D*/ GENx___x___x___ , /*013E*/ GENx___x___x___ , /*013F*/ GENx___x___x___ , /*0140*/ GENx___x___x___ , /*0141*/ GENx___x___x___ , /*0142*/ GENx___x___x___ , /*0143*/ GENx___x___x___ , /*0144*/ GENx___x___x___ , /*0145*/ GENx___x___x___ , /*0146*/ GENx___x___x___ , /*0147*/ GENx___x___x___ , /*0148*/ GENx___x___x___ , /*0149*/ GENx___x___x___ , /*014A*/ GENx___x___x___ , /*014B*/ GENx___x___x___ , /*014C*/ GENx___x___x___ , /*014D*/ GENx___x___x___ , /*014E*/ GENx___x___x___ , /*014F*/ GENx___x___x___ , /*0150*/ GENx___x___x___ , /*0151*/ GENx___x___x___ , /*0152*/ GENx___x___x___ , /*0153*/ GENx___x___x___ , /*0154*/ GENx___x___x___ , /*0155*/ GENx___x___x___ , /*0156*/ GENx___x___x___ , /*0157*/ GENx___x___x___ , /*0158*/ GENx___x___x___ , /*0159*/ GENx___x___x___ , /*015A*/ GENx___x___x___ , /*015B*/ GENx___x___x___ , /*015C*/ GENx___x___x___ , /*015D*/ GENx___x___x___ , /*015E*/ GENx___x___x___ , /*015F*/ GENx___x___x___ , /*0160*/ GENx___x___x___ , /*0161*/ GENx___x___x___ , /*0162*/ GENx___x___x___ , /*0163*/ GENx___x___x___ , /*0164*/ GENx___x___x___ , /*0165*/ GENx___x___x___ , /*0166*/ GENx___x___x___ , /*0167*/ GENx___x___x___ , /*0168*/ GENx___x___x___ , /*0169*/ GENx___x___x___ , /*016A*/ GENx___x___x___ , /*016B*/ GENx___x___x___ , /*016C*/ GENx___x___x___ , /*016D*/ GENx___x___x___ , /*016E*/ GENx___x___x___ , /*016F*/ GENx___x___x___ , /*0170*/ GENx___x___x___ , /*0171*/ GENx___x___x___ , /*0172*/ GENx___x___x___ , /*0173*/ GENx___x___x___ , /*0174*/ GENx___x___x___ , /*0175*/ GENx___x___x___ , /*0176*/ GENx___x___x___ , /*0177*/ GENx___x___x___ , /*0178*/ GENx___x___x___ , /*0179*/ GENx___x___x___ , /*017A*/ GENx___x___x___ , /*017B*/ GENx___x___x___ , /*017C*/ GENx___x___x___ , /*017D*/ GENx___x___x___ , /*017E*/ GENx___x___x___ , /*017F*/ GENx___x___x___ , /*0180*/ GENx___x___x___ , /*0181*/ GENx___x___x___ , /*0182*/ GENx___x___x___ , /*0183*/ GENx___x___x___ , /*0184*/ GENx___x___x___ , /*0185*/ GENx___x___x___ , /*0186*/ GENx___x___x___ , /*0187*/ GENx___x___x___ , /*0188*/ GENx___x___x___ , /*0189*/ GENx___x___x___ , /*018A*/ GENx___x___x___ , /*018B*/ GENx___x___x___ , /*018C*/ GENx___x___x___ , /*018D*/ GENx___x___x___ , /*018E*/ GENx___x___x___ , /*018F*/ GENx___x___x___ , /*0190*/ GENx___x___x___ , /*0191*/ GENx___x___x___ , /*0192*/ GENx___x___x___ , /*0193*/ GENx___x___x___ , /*0194*/ GENx___x___x___ , /*0195*/ GENx___x___x___ , /*0196*/ GENx___x___x___ , /*0197*/ GENx___x___x___ , /*0198*/ GENx___x___x___ , /*0199*/ GENx___x___x___ , /*019A*/ GENx___x___x___ , /*019B*/ GENx___x___x___ , /*019C*/ GENx___x___x___ , /*019D*/ GENx___x___x___ , /*019E*/ GENx___x___x___ , /*019F*/ GENx___x___x___ , /*01A0*/ GENx___x___x___ , /*01A1*/ GENx___x___x___ , /*01A2*/ GENx___x___x___ , /*01A3*/ GENx___x___x___ , /*01A4*/ GENx___x___x___ , /*01A5*/ GENx___x___x___ , /*01A6*/ GENx___x___x___ , /*01A7*/ GENx___x___x___ , /*01A8*/ GENx___x___x___ , /*01A9*/ GENx___x___x___ , /*01AA*/ GENx___x___x___ , /*01AB*/ GENx___x___x___ , /*01AC*/ GENx___x___x___ , /*01AD*/ GENx___x___x___ , /*01AE*/ GENx___x___x___ , /*01AF*/ GENx___x___x___ , /*01B0*/ GENx___x___x___ , /*01B1*/ GENx___x___x___ , /*01B2*/ GENx___x___x___ , /*01B3*/ GENx___x___x___ , /*01B4*/ GENx___x___x___ , /*01B5*/ GENx___x___x___ , /*01B6*/ GENx___x___x___ , /*01B7*/ GENx___x___x___ , /*01B8*/ GENx___x___x___ , /*01B9*/ GENx___x___x___ , /*01BA*/ GENx___x___x___ , /*01BB*/ GENx___x___x___ , /*01BC*/ GENx___x___x___ , /*01BD*/ GENx___x___x___ , /*01BE*/ GENx___x___x___ , /*01BF*/ GENx___x___x___ , /*01C0*/ GENx___x___x___ , /*01C1*/ GENx___x___x___ , /*01C2*/ GENx___x___x___ , /*01C3*/ GENx___x___x___ , /*01C4*/ GENx___x___x___ , /*01C5*/ GENx___x___x___ , /*01C6*/ GENx___x___x___ , /*01C7*/ GENx___x___x___ , /*01C8*/ GENx___x___x___ , /*01C9*/ GENx___x___x___ , /*01CA*/ GENx___x___x___ , /*01CB*/ GENx___x___x___ , /*01CC*/ GENx___x___x___ , /*01CD*/ GENx___x___x___ , /*01CE*/ GENx___x___x___ , /*01CF*/ GENx___x___x___ , /*01D0*/ GENx___x___x___ , /*01D1*/ GENx___x___x___ , /*01D2*/ GENx___x___x___ , /*01D3*/ GENx___x___x___ , /*01D4*/ GENx___x___x___ , /*01D5*/ GENx___x___x___ , /*01D6*/ GENx___x___x___ , /*01D7*/ GENx___x___x___ , /*01D8*/ GENx___x___x___ , /*01D9*/ GENx___x___x___ , /*01DA*/ GENx___x___x___ , /*01DB*/ GENx___x___x___ , /*01DC*/ GENx___x___x___ , /*01DD*/ GENx___x___x___ , /*01DE*/ GENx___x___x___ , /*01DF*/ GENx___x___x___ , /*01E0*/ GENx___x___x___ , /*01E1*/ GENx___x___x___ , /*01E2*/ GENx___x___x___ , /*01E3*/ GENx___x___x___ , /*01E4*/ GENx___x___x___ , /*01E5*/ GENx___x___x___ , /*01E6*/ GENx___x___x___ , /*01E7*/ GENx___x___x___ , /*01E8*/ GENx___x___x___ , /*01E9*/ GENx___x___x___ , /*01EA*/ GENx___x___x___ , /*01EB*/ GENx___x___x___ , /*01EC*/ GENx___x___x___ , /*01ED*/ GENx___x___x___ , /*01EE*/ GENx___x___x___ , /*01EF*/ GENx___x___x___ , /*01F0*/ GENx___x___x___ , /*01F1*/ GENx___x___x___ , /*01F2*/ GENx___x___x___ , /*01F3*/ GENx___x___x___ , /*01F4*/ GENx___x___x___ , /*01F5*/ GENx___x___x___ , /*01F6*/ GENx___x___x___ , /*01F7*/ GENx___x___x___ , /*01F8*/ GENx___x___x___ , /*01F9*/ GENx___x___x___ , /*01FA*/ GENx___x___x___ , /*01FB*/ GENx___x___x___ , /*01FC*/ GENx___x___x___ , /*01FD*/ GENx___x___x___ , /*01FE*/ GENx___x___x___ , /*01FF*/ GENx___x390x900 (trap2,E,"TRAP2") }; // #if defined(FEATURE_ESAME) DLL_EXPORT zz_func opcode_a4xx[256][GEN_MAXARCH] = { /*A400*/ GENx___x___x___ , /*A401*/ GENx___x___x___ , /*A402*/ GENx___x___x___ , /*A403*/ GENx___x___x___ , /*A404*/ GENx___x___x___ , /*A405*/ GENx___x___x___ , /*A406*/ GENx___x___x___ , /*A407*/ GENx___x___x___ , /*A408*/ GENx___x___x___ , /*A409*/ GENx___x___x___ , /*A40A*/ GENx___x___x___ , /*A40B*/ GENx___x___x___ , /*A40C*/ GENx___x___x___ , /*A40D*/ GENx___x___x___ , /*A40E*/ GENx___x___x___ , /*A40F*/ GENx___x___x___ , /*A410*/ GENx___x___x___ , /*A411*/ GENx___x___x___ , /*A412*/ GENx___x___x___ , /*A413*/ GENx___x___x___ , /*A414*/ GENx___x___x___ , /*A415*/ GENx___x___x___ , /*A416*/ GENx___x___x___ , /*A417*/ GENx___x___x___ , /*A418*/ GENx___x___x___ , /*A419*/ GENx___x___x___ , /*A41A*/ GENx___x___x___ , /*A41B*/ GENx___x___x___ , /*A41C*/ GENx___x___x___ , /*A41D*/ GENx___x___x___ , /*A41E*/ GENx___x___x___ , /*A41F*/ GENx___x___x___ , /*A420*/ GENx___x___x___ , /*A421*/ GENx___x___x___ , /*A422*/ GENx___x___x___ , /*A423*/ GENx___x___x___ , /*A424*/ GENx___x___x___ , /*A425*/ GENx___x___x___ , /*A426*/ GENx___x___x___ , /*A427*/ GENx___x___x___ , /*A428*/ GENx___x___x___ , /*A429*/ GENx___x___x___ , /*A42A*/ GENx___x___x___ , /*A42B*/ GENx___x___x___ , /*A42C*/ GENx___x___x___ , /*A42D*/ GENx___x___x___ , /*A42E*/ GENx___x___x___ , /*A42F*/ GENx___x___x___ , /*A430*/ GENx___x___x___ , /*A431*/ GENx___x___x___ , /*A432*/ GENx___x___x___ , /*A433*/ GENx___x___x___ , /*A434*/ GENx___x___x___ , /*A435*/ GENx___x___x___ , /*A436*/ GENx___x___x___ , /*A437*/ GENx___x___x___ , /*A438*/ GENx___x___x___ , /*A439*/ GENx___x___x___ , /*A43A*/ GENx___x___x___ , /*A43B*/ GENx___x___x___ , /*A43C*/ GENx___x___x___ , /*A43D*/ GENx___x___x___ , /*A43E*/ GENx___x___x___ , /*A43F*/ GENx___x___x___ , /*A440*/ GENx___x___x___ , /*A441*/ GENx___x___x___ , /*A442*/ GENx___x___x___ , /*A443*/ GENx___x___x___ , /*A444*/ GENx___x___x___ , /*A445*/ GENx___x___x___ , /*A446*/ GENx___x___x___ , /*A447*/ GENx___x___x___ , /*A448*/ GENx___x___x___ , /*A449*/ GENx___x___x___ , /*A44A*/ GENx___x___x___ , /*A44B*/ GENx___x___x___ , /*A44C*/ GENx___x___x___ , /*A44D*/ GENx___x___x___ , /*A44E*/ GENx___x___x___ , /*A44F*/ GENx___x___x___ , /*A450*/ GENx___x___x___ , /*A451*/ GENx___x___x___ , /*A452*/ GENx___x___x___ , /*A453*/ GENx___x___x___ , /*A454*/ GENx___x___x___ , /*A455*/ GENx___x___x___ , /*A456*/ GENx___x___x___ , /*A457*/ GENx___x___x___ , /*A458*/ GENx___x___x___ , /*A459*/ GENx___x___x___ , /*A45A*/ GENx___x___x___ , /*A45B*/ GENx___x___x___ , /*A45C*/ GENx___x___x___ , /*A45D*/ GENx___x___x___ , /*A45E*/ GENx___x___x___ , /*A45F*/ GENx___x___x___ , /*A460*/ GENx___x___x___ , /*A461*/ GENx___x___x___ , /*A462*/ GENx___x___x___ , /*A463*/ GENx___x___x___ , /*A464*/ GENx___x___x___ , /*A465*/ GENx___x___x___ , /*A466*/ GENx___x___x___ , /*A467*/ GENx___x___x___ , /*A468*/ GENx___x___x___ , /*A469*/ GENx___x___x___ , /*A46A*/ GENx___x___x___ , /*A46B*/ GENx___x___x___ , /*A46C*/ GENx___x___x___ , /*A46D*/ GENx___x___x___ , /*A46E*/ GENx___x___x___ , /*A46F*/ GENx___x___x___ , /*A470*/ GENx___x___x___ , /*A471*/ GENx___x___x___ , /*A472*/ GENx___x___x___ , /*A473*/ GENx___x___x___ , /*A474*/ GENx___x___x___ , /*A475*/ GENx___x___x___ , /*A476*/ GENx___x___x___ , /*A477*/ GENx___x___x___ , /*A478*/ GENx___x___x___ , /*A479*/ GENx___x___x___ , /*A47A*/ GENx___x___x___ , /*A47B*/ GENx___x___x___ , /*A47C*/ GENx___x___x___ , /*A47D*/ GENx___x___x___ , /*A47E*/ GENx___x___x___ , /*A47F*/ GENx___x___x___ , /*A480*/ GENx___x___x___ , /*A481*/ GENx___x___x___ , /*A482*/ GENx___x___x___ , /*A483*/ GENx___x___x___ , /*A484*/ GENx___x___x___ , /*A485*/ GENx___x___x___ , /*A486*/ GENx___x___x___ , /*A487*/ GENx___x___x___ , /*A488*/ GENx___x___x___ , /*A489*/ GENx___x___x___ , /*A48A*/ GENx___x___x___ , /*A48B*/ GENx___x___x___ , /*A48C*/ GENx___x___x___ , /*A48D*/ GENx___x___x___ , /*A48E*/ GENx___x___x___ , /*A48F*/ GENx___x___x___ , /*A490*/ GENx___x___x___ , /*A491*/ GENx___x___x___ , /*A492*/ GENx___x___x___ , /*A493*/ GENx___x___x___ , /*A494*/ GENx___x___x___ , /*A495*/ GENx___x___x___ , /*A496*/ GENx___x___x___ , /*A497*/ GENx___x___x___ , /*A498*/ GENx___x___x___ , /*A499*/ GENx___x___x___ , /*A49A*/ GENx___x___x___ , /*A49B*/ GENx___x___x___ , /*A49C*/ GENx___x___x___ , /*A49D*/ GENx___x___x___ , /*A49E*/ GENx___x___x___ , /*A49F*/ GENx___x___x___ , /*A4A0*/ GENx___x___x___ , /*A4A1*/ GENx___x___x___ , /*A4A2*/ GENx___x___x___ , /*A4A3*/ GENx___x___x___ , /*A4A4*/ GENx___x___x___ , /*A4A5*/ GENx___x___x___ , /*A4A6*/ GENx___x___x___ , /*A4A7*/ GENx___x___x___ , /*A4A8*/ GENx___x___x___ , /*A4A9*/ GENx___x___x___ , /*A4AA*/ GENx___x___x___ , /*A4AB*/ GENx___x___x___ , /*A4AC*/ GENx___x___x___ , /*A4AD*/ GENx___x___x___ , /*A4AE*/ GENx___x___x___ , /*A4AF*/ GENx___x___x___ , /*A4B0*/ GENx___x___x___ , /*A4B1*/ GENx___x___x___ , /*A4B2*/ GENx___x___x___ , /*A4B3*/ GENx___x___x___ , /*A4B4*/ GENx___x___x___ , /*A4B5*/ GENx___x___x___ , /*A4B6*/ GENx___x___x___ , /*A4B7*/ GENx___x___x___ , /*A4B8*/ GENx___x___x___ , /*A4B9*/ GENx___x___x___ , /*A4BA*/ GENx___x___x___ , /*A4BB*/ GENx___x___x___ , /*A4BC*/ GENx___x___x___ , /*A4BD*/ GENx___x___x___ , /*A4BE*/ GENx___x___x___ , /*A4BF*/ GENx___x___x___ , /*A4C0*/ GENx___x___x___ , /*A4C1*/ GENx___x___x___ , /*A4C2*/ GENx___x___x___ , /*A4C3*/ GENx___x___x___ , /*A4C4*/ GENx___x___x___ , /*A4C5*/ GENx___x___x___ , /*A4C6*/ GENx___x___x___ , /*A4C7*/ GENx___x___x___ , /*A4C8*/ GENx___x___x___ , /*A4C9*/ GENx___x___x___ , /*A4CA*/ GENx___x___x___ , /*A4CB*/ GENx___x___x___ , /*A4CC*/ GENx___x___x___ , /*A4CD*/ GENx___x___x___ , /*A4CE*/ GENx___x___x___ , /*A4CF*/ GENx___x___x___ , /*A4D0*/ GENx___x___x___ , /*A4D1*/ GENx___x___x___ , /*A4D2*/ GENx___x___x___ , /*A4D3*/ GENx___x___x___ , /*A4D4*/ GENx___x___x___ , /*A4D5*/ GENx___x___x___ , /*A4D6*/ GENx___x___x___ , /*A4D7*/ GENx___x___x___ , /*A4D8*/ GENx___x___x___ , /*A4D9*/ GENx___x___x___ , /*A4DA*/ GENx___x___x___ , /*A4DB*/ GENx___x___x___ , /*A4DC*/ GENx___x___x___ , /*A4DD*/ GENx___x___x___ , /*A4DE*/ GENx___x___x___ , /*A4DF*/ GENx___x___x___ , /*A4E0*/ GENx___x___x___ , /*A4E1*/ GENx___x___x___ , /*A4E2*/ GENx___x___x___ , /*A4E3*/ GENx___x___x___ , /*A4E4*/ GENx___x___x___ , /*A4E5*/ GENx___x___x___ , /*A4E6*/ GENx___x___x___ , /*A4E7*/ GENx___x___x___ , /*A4E8*/ GENx___x___x___ , /*A4E9*/ GENx___x___x___ , /*A4EA*/ GENx___x___x___ , /*A4EB*/ GENx___x___x___ , /*A4EC*/ GENx___x___x___ , /*A4ED*/ GENx___x___x___ , /*A4EE*/ GENx___x___x___ , /*A4EF*/ GENx___x___x___ , /*A4F0*/ GENx___x___x___ , /*A4F1*/ GENx___x___x___ , /*A4F2*/ GENx___x___x___ , /*A4F3*/ GENx___x___x___ , /*A4F4*/ GENx___x___x___ , /*A4F5*/ GENx___x___x___ , /*A4F6*/ GENx___x___x___ , /*A4F7*/ GENx___x___x___ , /*A4F8*/ GENx___x___x___ , /*A4F9*/ GENx___x___x___ , /*A4FA*/ GENx___x___x___ , /*A4FB*/ GENx___x___x___ , /*A4FC*/ GENx___x___x___ , /*A4FD*/ GENx___x___x___ , /*A4FE*/ GENx___x___x___ , /*A4FF*/ GENx___x___x___ }; // #endif /*defined(FEATURE_ESAME)*/ // #if defined(FEATURE_ESAME) DLL_EXPORT zz_func opcode_a5xx[16][GEN_MAXARCH] = { /*A5x0*/ GENx___x___x900 (insert_immediate_high_high,RI,"IIHH"), /*A5x1*/ GENx___x___x900 (insert_immediate_high_low,RI,"IIHL"), /*A5x2*/ GENx___x___x900 (insert_immediate_low_high,RI,"IILH"), /*A5x3*/ GENx___x___x900 (insert_immediate_low_low,RI,"IILL"), /*A5x4*/ GENx___x___x900 (and_immediate_high_high,RI,"NIHH"), /*A5x5*/ GENx___x___x900 (and_immediate_high_low,RI,"NIHL"), /*A5x6*/ GENx___x___x900 (and_immediate_low_high,RI,"NILH"), /*A5x7*/ GENx___x___x900 (and_immediate_low_low,RI,"NILL"), /*A5x8*/ GENx___x___x900 (or_immediate_high_high,RI,"OIHH"), /*A5x9*/ GENx___x___x900 (or_immediate_high_low,RI,"OIHL"), /*A5xA*/ GENx___x___x900 (or_immediate_low_high,RI,"OILH"), /*A5xB*/ GENx___x___x900 (or_immediate_low_low,RI,"OILL"), /*A5xC*/ GENx___x___x900 (load_logical_immediate_high_high,RI,"LLIHH"), /*A5xD*/ GENx___x___x900 (load_logical_immediate_high_low,RI,"LLIHL"), /*A5xE*/ GENx___x___x900 (load_logical_immediate_low_high,RI,"LLILH"), /*A5xF*/ GENx___x___x900 (load_logical_immediate_low_low,RI,"LLILL") } ; // #endif /*defined(FEATURE_ESAME)*/ DLL_EXPORT zz_func opcode_a7xx[16][GEN_MAXARCH] = { /*A7x0*/ GENx37Xx390x900 (test_under_mask_high,RI,"TMLH"), /*A7x1*/ GENx37Xx390x900 (test_under_mask_low,RI,"TMLL"), /*A7x2*/ GENx___x___x900 (test_under_mask_high_high,RI,"TMHH"), /*A7x3*/ GENx___x___x900 (test_under_mask_high_low,RI,"TMHL"), /*A7x4*/ GENx37Xx390x900 (branch_relative_on_condition,RI_B,"BRC"), /*A7x5*/ GENx37Xx390x900 (branch_relative_and_save,RI_B,"BRAS"), /*A7x6*/ GENx37Xx390x900 (branch_relative_on_count,RI_B,"BRCT"), /*A7x7*/ GENx___x___x900 (branch_relative_on_count_long,RI_B,"BRCTG"), /*A7x8*/ GENx37Xx390x900 (load_halfword_immediate,RI,"LHI"), /*A7x9*/ GENx___x___x900 (load_long_halfword_immediate,RI,"LGHI"), /*A7xA*/ GENx37Xx390x900 (add_halfword_immediate,RI,"AHI"), /*A7xB*/ GENx___x___x900 (add_long_halfword_immediate,RI,"AGHI"), /*A7xC*/ GENx37Xx390x900 (multiply_halfword_immediate,RI,"MHI"), /*A7xD*/ GENx___x___x900 (multiply_long_halfword_immediate,RI,"MGHI"), /*A7xE*/ GENx37Xx390x900 (compare_halfword_immediate,RI,"CHI"), /*A7xF*/ GENx___x___x900 (compare_long_halfword_immediate,RI,"CGHI") }; DLL_EXPORT zz_func opcode_b2xx[256][GEN_MAXARCH] = { /*B200*/ GENx370x___x___ (connect_channel_set,S,"CONCS"), /*B201*/ GENx370x___x___ (disconnect_channel_set,S,"DISCS"), /*B202*/ GENx370x390x900 (store_cpu_id,S,"STIDP"), /*B203*/ GENx370x___x___ (store_channel_id,S,"STIDC"), /*B204*/ GENx370x390x900 (set_clock,S,"SCK"), /*B205*/ GENx370x390x900 (store_clock,S,"STCK"), /*B206*/ GENx370x390x900 (set_clock_comparator,S,"SCKC"), /*B207*/ GENx370x390x900 (store_clock_comparator,S,"STCKC"), /*B208*/ GENx370x390x900 (set_cpu_timer,S,"SPT"), /*B209*/ GENx370x390x900 (store_cpu_timer,S,"STPT"), /*B20A*/ GENx370x390x900 (set_psw_key_from_address,S,"SPKA"), /*B20B*/ GENx370x390x900 (insert_psw_key,none,"IPK"), /*B20C*/ GENx___x___x___ , /*B20D*/ GENx370x390x900 (purge_translation_lookaside_buffer,none,"PTLB"), /*B20E*/ GENx___x___x___ , /*B20F*/ GENx___x___x___ , /*B210*/ GENx370x390x900 (set_prefix,S,"SPX"), /*B211*/ GENx370x390x900 (store_prefix,S,"STPX"), /*B212*/ GENx370x390x900 (store_cpu_address,S,"STAP"), /*B213*/ GENx370x___x___ (reset_reference_bit,S,"RRB"), /*B214*/ GENx___x390x900 (start_interpretive_execution,S,"SIE"), /*B215*/ GENx___x___x___ , /*B216*/ GENx___x___x___ , /*%SETR/SSYN */ /*B217*/ GENx___x___x___ , /*%STETR/STSYN */ /*B218*/ GENx370x390x900 (program_call,S,"PC"), /*B219*/ GENx370x390x900 (set_address_space_control,S,"SAC"), /*B21A*/ GENx___x390x900 (compare_and_form_codeword,S,"CFC"), /*B21B*/ GENx___x___x___ , /*B21C*/ GENx___x___x___ , /*B21D*/ GENx___x___x___ , /*B21E*/ GENx___x___x___ , /*B21F*/ GENx___x___x___ , /*B220*/ GENx___x390x900 (service_call,RRE,"SERVC"), /*B221*/ GENx370x390x900 (invalidate_page_table_entry,RRE,"IPTE"), /*B222*/ GENx370x390x900 (insert_program_mask,RRE_R1,"IPM"), /*B223*/ GENx370x390x900 (insert_virtual_storage_key,RRE,"IVSK"), /*B224*/ GENx370x390x900 (insert_address_space_control,RRE_R1,"IAC"), /*B225*/ GENx370x390x900 (set_secondary_asn,RRE_R1,"SSAR"), /*B226*/ GENx370x390x900 (extract_primary_asn,RRE_R1,"EPAR"), /*B227*/ GENx370x390x900 (extract_secondary_asn,RRE_R1,"ESAR"), /*B228*/ GENx370x390x900 (program_transfer,RRE,"PT"), /*B229*/ GENx370x390x900 (insert_storage_key_extended,RRE,"ISKE"), /*B22A*/ GENx370x390x900 (reset_reference_bit_extended,RRE,"RRBE"), /*B22B*/ GENx370x390x900 (set_storage_key_extended,RRF_M,"SSKE"), /*B22C*/ GENx370x390x900 (test_block,RRE,"TB"), /*B22D*/ GENx370x390x900 (divide_float_ext_reg,RRE,"DXR"), /*B22E*/ GENx___x390x900 (page_in,RRE,"PGIN"), /*B22F*/ GENx___x390x900 (page_out,RRE,"PGOUT"), /*B230*/ GENx___x390x900 (clear_subchannel,none,"CSCH"), /*B231*/ GENx___x390x900 (halt_subchannel,none,"HSCH"), /*B232*/ GENx___x390x900 (modify_subchannel,S,"MSCH"), /*B233*/ GENx___x390x900 (start_subchannel,S,"SSCH"), /*B234*/ GENx___x390x900 (store_subchannel,S,"STSCH"), /*B235*/ GENx___x390x900 (test_subchannel,S,"TSCH"), /*B236*/ GENx___x390x900 (test_pending_interruption,S,"TPI"), /*B237*/ GENx___x390x900 (set_address_limit,none,"SAL"), /*B238*/ GENx___x390x900 (resume_subchannel,none,"RSCH"), /*B239*/ GENx___x390x900 (store_channel_report_word,S,"STCRW"), /*B23A*/ GENx___x390x900 (store_channel_path_status,S,"STCPS"), /*B23B*/ GENx___x390x900 (reset_channel_path,none,"RCHP"), /*B23C*/ GENx___x390x900 (set_channel_monitor,none,"SCHM"), /*B23D*/ GENx___x390x900 (store_zone_parameter,S,"STZP"), /*B23E*/ GENx___x390x900 (set_zone_parameter,S,"SZP"), /*B23F*/ GENx___x390x900 (test_pending_zone_interrupt,S,"TPZI"), /*B240*/ GENx___x390x900 (branch_and_stack,RRE,"BAKR"), /*B241*/ GENx37Xx390x900 (checksum,RRE,"CKSM"), /*B242*/ GENx___x___x___ , /**Add FRR */ /*B243*/ GENx___x___x___ , /*#MA */ /*B244*/ GENx37Xx390x900 (squareroot_float_long_reg,RRE,"SQDR"), /*B245*/ GENx37Xx390x900 (squareroot_float_short_reg,RRE,"SQER"), /*B246*/ GENx___x390x900 (store_using_real_address,RRE,"STURA"), /*B247*/ GENx___x390x900 (modify_stacked_state,RRE_R1,"MSTA"), /*B248*/ GENx___x390x900 (purge_accesslist_lookaside_buffer,none,"PALB"), /*B249*/ GENx___x390x900 (extract_stacked_registers,RRE,"EREG"), /*B24A*/ GENx___x390x900 (extract_stacked_state,RRE,"ESTA"), /*B24B*/ GENx___x390x900 (load_using_real_address,RRE,"LURA"), /*B24C*/ GENx___x390x900 (test_access,RRE,"TAR"), /*B24D*/ GENx___x390x900 (copy_access,RRE,"CPYA"), /*B24E*/ GENx___x390x900 (set_access_register,RRE,"SAR"), /*B24F*/ GENx___x390x900 (extract_access_register,RRE,"EAR"), /*B250*/ GENx___x390x900 (compare_and_swap_and_purge,RRE,"CSP"), /*B251*/ GENx___x___x___ , /*B252*/ GENx37Xx390x900 (multiply_single_register,RRE,"MSR"), /*B253*/ GENx___x___x___ , /*B254*/ GENx___x390x900 (move_page,RRE,"MVPG"), /*B255*/ GENx37Xx390x900 (move_string,RRE,"MVST"), /*B256*/ GENx___x___x___ , /*B257*/ GENx37Xx390x900 (compare_until_substring_equal,RRE,"CUSE"), /*B258*/ GENx___x390x900 (branch_in_subspace_group,RRE,"BSG"), /*B259*/ GENx___x390x900 (invalidate_expanded_storage_block_entry,RRE,"IESBE"), /*B25A*/ GENx___x390x900 (branch_and_set_authority,RRE,"BSA"), /*B25B*/ GENx___x___x___ , /*%PGXIN */ /*B25C*/ GENx___x___x___ , /*%PGXOUT */ /*B25D*/ GENx37Xx390x900 (compare_logical_string,RRE,"CLST"), /*B25E*/ GENx37Xx390x900 (search_string,RRE,"SRST"), /*B25F*/ GENx___x390x900 (channel_subsystem_call,RRE,"CHSC"), /*B260*/ GENx___x___x___ , /* Sysplex */ /*B261*/ GENx___x___x___ , /* Sysplex */ /*B262*/ GENx___x390x900 (lock_page,RRE,"LKPG"), /*B263*/ GENx37Xx390x900 (compression_call,RRE,"CMPSC"), /*B264*/ GENx___x___x___ , /* Sysplex */ /*B265*/ GENx___x___x___ , /*(set_vector_summary,?,"SVS"),*/ /* Sysplex */ /*B266*/ GENx___x___x___ , /* Sysplex */ /*B267*/ GENx___x___x___ , /* Sysplex */ /*B268*/ GENx___x___x___ , /*(define_vector,?,"DV"),*/ /* Sysplex */ /*B269*/ GENx___x___x___ , /* Crypto */ /*B26A*/ GENx___x___x___ , /* Crypto */ /*B26B*/ GENx___x___x___ , /* Crypto */ /*B26C*/ GENx___x___x___ , /* Crypto */ /*B26D*/ GENx___x___x___ , /* Crypto */ /*B26E*/ GENx___x___x___ , /* Crypto */ /*B26F*/ GENx___x___x___ , /* Crypto */ /*B270*/ GENx___x___x___ , /*%SPCS */ /*B271*/ GENx___x___x___ , /*%STPCS */ /*B272*/ GENx___x___x___ , /* Sysplex */ /*B273*/ GENx___x___x___ , /*B274*/ GENx___x390x900 (signal_adapter,S,"SIGA"), /*B275*/ GENx___x___x___ , /*B276*/ GENx___x390x900 (cancel_subchannel,none,"XSCH"), /*B277*/ GENx___x390x900 (resume_program,S,"RP"), /*B278*/ GENx___x390x900 (store_clock_extended,S,"STCKE"), /*B279*/ GENx___x390x900 (set_address_space_control_fast,S,"SACF"), /*B27A*/ GENx___x___x___ , /* Sysplex */ /*B27B*/ GENx___x___x___ , /* TFF/Sysplx*/ /*B27C*/ GENx___x___x900 (store_clock_fast,S,"STCKF"), /*B27D*/ GENx370x390x900 (store_system_information,S,"STSI"), /*B27E*/ GENx___x___x___ , /* Sysplex */ /*B27F*/ GENx___x___x___ , /* Sysplex */ /*B280*/ GENx___x___x900 (set_program_parameter,S,"SPP"), /*#LN L */ /*B281*/ GENx___x___x___ , /*#LN S */ /*B282*/ GENx___x___x___ , /*#EXP L */ /*B283*/ GENx___x___x___ , /*#EXP S */ /*B284*/ GENx___x___x900 (set_cpu_counter_set_controls,S,"SCCTL"), /*#LOG L */ /*B285*/ GENx___x___x900 (set_peripheral_counter_set_controls,S,"SPCTL"),/*#LOG S*/ /*B286*/ GENx___x___x900 (query_sampling_information,S,"QSI"), /*#POWER L */ /*B287*/ GENx___x___x900 (set_sampling_controls,S,"SSCTL"), /*#POWER S */ /*B288*/ GENx___x___x___ , /*#SIN L */ /*B289*/ GENx___x___x___ , /*#SIN S */ /*B28A*/ GENx___x___x___ , /*#COS L */ /*B28B*/ GENx___x___x___ , /*#COS S */ /*B28C*/ GENx___x___x___ , /*B28D*/ GENx___x___x___ , /*B28E*/ GENx___x___x900 (query_counter_information,S,"QCTRI"), /*B28F*/ GENx___x___x___ , /*B290*/ GENx___x___x___ , /*B291*/ GENx___x___x___ , /*B292*/ GENx___x___x___ , /*B293*/ GENx___x___x___ , /*B294*/ GENx___x___x___ , /*#ARCTAN L */ /*B295*/ GENx___x___x___ , /*#ARCTAN S */ /*B296*/ GENx___x___x___ , /*B297*/ GENx___x___x___ , /*B298*/ GENx___x___x___ , /*B299*/ GENx37Xx390x900 (set_bfp_rounding_mode,S,"SRNM"), /*B29A*/ GENx___x___x___ , /*B29B*/ GENx___x___x___ , /*B29C*/ GENx37Xx390x900 (store_fpc,S,"STFPC"), /*B29D*/ GENx37Xx390x900 (load_fpc,S,"LFPC"), /*B29E*/ GENx___x___x___ , /*B29F*/ GENx___x___x___ , /*B2A0*/ GENx___x___x___ , /*B2A1*/ GENx___x___x___ , /*B2A2*/ GENx___x___x___ , /*B2A3*/ GENx___x___x___ , /*B2A4*/ GENx___x___x___ , /*(move_channel_buffer_data_multiple,?,"MCBDM"),*//*Sysplex*/ /*B2A5*/ GENx37Xx390x900 (translate_extended,RRE,"TRE"), /*B2A6*/ GENx37Xx390x900 (convert_utf16_to_utf8,RRF_M3,"CU21 (CUUTF)"), /*B2A7*/ GENx37Xx390x900 (convert_utf8_to_utf16,RRF_M3,"CU12 (CUTFU)"), /*B2A8*/ GENx___x___x___ , /* Sysplex */ /*B2A9*/ GENx___x___x___ , /*B2AA*/ GENx___x___x___ , /*B2AB*/ GENx___x___x___ , /*B2AC*/ GENx___x___x___ , /*B2AD*/ GENx___x___x___ , /*B2AE*/ GENx___x___x___ , /*B2AF*/ GENx___x___x___ , /*B2B0*/ GENx___x390x900 (store_facility_list_extended,S,"STFLE"), /*!SARCH */ /*@Z9*/ /*B2B1*/ GENx___x390x900 (store_facility_list,S,"STFL"), /*B2B2*/ GENx___x___x900 (load_program_status_word_extended,S,"LPSWE"), /*B2B3*/ GENx___x___x___ , /*(store_etr_attachment_information,?,"STEAI"),*/ /*B2B4*/ GENx___x___x___ , /*B2B5*/ GENx___x___x___ , /*B2B6*/ GENx___x___x___ , /*B2B7*/ GENx___x___x___ , /*B2B8*/ GENx___x___x___ , /*B2B9*/ GENx___x390x900 (set_dfp_rounding_mode,S,"SRNMT"), /*B2BA*/ GENx___x___x___ , /*B2BB*/ GENx___x___x___ , /*B2BC*/ GENx___x___x___ , /*B2BD*/ GENx37Xx390x900 (load_fpc_and_signal,S,"LFAS"), /*B2BE*/ GENx___x___x___ , /*B2BF*/ GENx___x___x___ , /*B2C0*/ GENx___x___x___ , /*$ADRN */ /*B2C1*/ GENx___x___x___ , /*$AERN */ /*B2C2*/ GENx___x___x___ , /*$SDRN */ /*B2C3*/ GENx___x___x___ , /*$SERN */ /*B2C4*/ GENx___x___x___ , /*$MDRN */ /*B2C5*/ GENx___x___x___ , /*$MERN */ /*B2C6*/ GENx___x___x___ , /*$DDRN */ /*B2C7*/ GENx___x___x___ , /*$DERN */ /*B2C8*/ GENx___x___x___ , /*$LERN */ /*B2C9*/ GENx___x___x___ , /*B2CA*/ GENx___x___x___ , /*B2CB*/ GENx___x___x___ , /*B2CC*/ GENx___x___x___ , /*B2CD*/ GENx___x___x___ , /*B2CE*/ GENx___x___x___ , /*B2CF*/ GENx___x___x___ , /*B2D0*/ GENx___x___x___ , /*$AACDR */ /*B2D1*/ GENx___x___x___ , /*$AACER */ /*B2D2*/ GENx___x___x___ , /*$SACDR */ /*B2D3*/ GENx___x___x___ , /*$SACER */ /*B2D4*/ GENx___x___x___ , /*$MACD */ /*B2D5*/ GENx___x___x___ , /*B2D6*/ GENx___x___x___ , /*$RACD */ /*B2D7*/ GENx___x___x___ , /*$RACE */ /*B2D8*/ GENx___x___x___ , /*$AACAC */ /*B2D9*/ GENx___x___x___ , /*$SACAC */ /*B2DA*/ GENx___x___x___ , /*$CLAC */ /*B2DB*/ GENx___x___x___ , /*B2DC*/ GENx___x___x___ , /*B2DD*/ GENx___x___x___ , /*B2DE*/ GENx___x___x___ , /*B2DF*/ GENx___x___x___ , /*B2E0*/ GENx___x___x900 (set_cpu_counter,RRE,"SCCTR"), /*B2E1*/ GENx___x___x900 (set_peripheral_counter,RRE,"SPCTR"), /*B2E2*/ GENx___x___x___ , /*B2E3*/ GENx___x___x___ , /*B2E4*/ GENx___x___x900 (extract_cpu_counter,RRE,"ECCTR"), /*B2E5*/ GENx___x___x900 (extract_peripheral_counter,RRE,"EPCTR"), /*B2E6*/ GENx___x___x___ , /*B2E7*/ GENx___x___x___ , /*B2E8*/ GENx___x___x___ , /*B2E9*/ GENx___x___x___ , /*B2EA*/ GENx___x___x___ , /*B2EB*/ GENx___x___x___ , /*B2EC*/ GENx___x___x___ , /*B2ED*/ GENx___x___x900 (extract_coprocessor_group_address,RRE,"ECA"), /*B2EE*/ GENx___x___x___ , /*B2EF*/ GENx___x___x___ , /*B2F0*/ GENx370x390x900 (inter_user_communication_vehicle,S,"IUCV"), /*B2F1*/ GENx___x___x___ , /* Sysplex */ /*B2F2*/ GENx___x___x___ , /*B2F3*/ GENx___x___x___ , /*B2F4*/ GENx___x___x___ , /*B2F5*/ GENx___x___x___ , /*B2F6*/ GENx___x___x___ , /* Sysplex */ /*B2F7*/ GENx___x___x___ , /*B2F8*/ GENx___x___x___ , /*B2F9*/ GENx___x___x___ , /*B2FA*/ GENx___x___x___ , /*B2FB*/ GENx___x___x___ , /*B2FC*/ GENx___x___x___ , /*B2FD*/ GENx___x___x___ , /*B2FE*/ GENx___x___x___ , /*B2FF*/ GENx___x390x900 (trap4,S,"TRAP4") }; // #if defined(FEATURE_BASIC_FP_EXTENSIONS) DLL_EXPORT zz_func opcode_b3xx[256][GEN_MAXARCH] = { /*B300*/ GENx37Xx390x900 (load_positive_bfp_short_reg,RRE,"LPEBR"), /*B301*/ GENx37Xx390x900 (load_negative_bfp_short_reg,RRE,"LNEBR"), /*B302*/ GENx37Xx390x900 (load_and_test_bfp_short_reg,RRE,"LTEBR"), /*B303*/ GENx37Xx390x900 (load_complement_bfp_short_reg,RRE,"LCEBR"), /*B304*/ GENx37Xx390x900 (load_lengthened_bfp_short_to_long_reg,RRE,"LDEBR"), /*B305*/ GENx37Xx390x900 (load_lengthened_bfp_long_to_ext_reg,RRE,"LXDBR"), /*B306*/ GENx37Xx390x900 (load_lengthened_bfp_short_to_ext_reg,RRE,"LXEBR"), /*B307*/ GENx37Xx390x900 (multiply_bfp_long_to_ext_reg,RRE,"MXDBR"), /*B308*/ GENx37Xx390x900 (compare_and_signal_bfp_short_reg,RRE,"KEBR"), /*B309*/ GENx37Xx390x900 (compare_bfp_short_reg,RRE,"CEBR"), /*B30A*/ GENx37Xx390x900 (add_bfp_short_reg,RRE,"AEBR"), /*B30B*/ GENx37Xx390x900 (subtract_bfp_short_reg,RRE,"SEBR"), /*B30C*/ GENx37Xx390x900 (multiply_bfp_short_to_long_reg,RRE,"MDEBR"), /*B30D*/ GENx37Xx390x900 (divide_bfp_short_reg,RRE,"DEBR"), /*B30E*/ GENx37Xx390x900 (multiply_add_bfp_short_reg,RRF_R,"MAEBR"), /*B30F*/ GENx37Xx390x900 (multiply_subtract_bfp_short_reg,RRF_R,"MSEBR"), /*B310*/ GENx37Xx390x900 (load_positive_bfp_long_reg,RRE,"LPDBR"), /*B311*/ GENx37Xx390x900 (load_negative_bfp_long_reg,RRE,"LNDBR"), /*B312*/ GENx37Xx390x900 (load_and_test_bfp_long_reg,RRE,"LTDBR"), /*B313*/ GENx37Xx390x900 (load_complement_bfp_long_reg,RRE,"LCDBR"), /*B314*/ GENx37Xx390x900 (squareroot_bfp_short_reg,RRE,"SQEBR"), /*B315*/ GENx37Xx390x900 (squareroot_bfp_long_reg,RRE,"SQDBR"), /*B316*/ GENx37Xx390x900 (squareroot_bfp_ext_reg,RRE,"SQXBR"), /*B317*/ GENx37Xx390x900 (multiply_bfp_short_reg,RRE,"MEEBR"), /*B318*/ GENx37Xx390x900 (compare_and_signal_bfp_long_reg,RRE,"KDBR"), /*B319*/ GENx37Xx390x900 (compare_bfp_long_reg,RRE,"CDBR"), /*B31A*/ GENx37Xx390x900 (add_bfp_long_reg,RRE,"ADBR"), /*B31B*/ GENx37Xx390x900 (subtract_bfp_long_reg,RRE,"SDBR"), /*B31C*/ GENx37Xx390x900 (multiply_bfp_long_reg,RRE,"MDBR"), /*B31D*/ GENx37Xx390x900 (divide_bfp_long_reg,RRE,"DDBR"), /*B31E*/ GENx37Xx390x900 (multiply_add_bfp_long_reg,RRF_R,"MADBR"), /*B31F*/ GENx37Xx390x900 (multiply_subtract_bfp_long_reg,RRF_R,"MSDBR"), /*B320*/ GENx___x___x___ , /*B321*/ GENx___x___x___ , /*B322*/ GENx___x___x___ , /*B323*/ GENx___x___x___ , /*B324*/ GENx37Xx390x900 (load_lengthened_float_short_to_long_reg,RRE,"LDER"), /*B325*/ GENx37Xx390x900 (load_lengthened_float_long_to_ext_reg,RRE,"LXDR"), /*B326*/ GENx37Xx390x900 (load_lengthened_float_short_to_ext_reg,RRE,"LXER"), /*B327*/ GENx___x___x___ , /*B328*/ GENx___x___x___ , /*B329*/ GENx___x___x___ , /*B32A*/ GENx___x___x___ , /*B32B*/ GENx___x___x___ , /*B32C*/ GENx___x___x___ , /*B32D*/ GENx___x___x___ , /*B32E*/ GENx37Xx390x900 (multiply_add_float_short_reg,RRF_R,"MAER"), /*B32F*/ GENx37Xx390x900 (multiply_subtract_float_short_reg,RRF_R,"MSER"), /*B330*/ GENx___x___x___ , /*B331*/ GENx___x___x___ , /*B332*/ GENx___x___x___ , /*B333*/ GENx___x___x___ , /*B334*/ GENx___x___x___ , /*B335*/ GENx___x___x___ , /*B336*/ GENx37Xx390x900 (squareroot_float_ext_reg,RRE,"SQXR"), /*B337*/ GENx37Xx390x900 (multiply_float_short_reg,RRE,"MEER"), /*B338*/ GENx37Xx___x900 (multiply_add_unnormal_float_long_to_ext_low_reg,RRF_R,"MAYLR"), /*@Z9*/ /*B339*/ GENx37Xx___x900 (multiply_unnormal_float_long_to_ext_low_reg,RRF_R,"MYLR"), /*@Z9*/ /*B33A*/ GENx37Xx___x900 (multiply_add_unnormal_float_long_to_ext_reg,RRF_R,"MAYR"), /*@Z9*/ /*B33B*/ GENx37Xx___x900 (multiply_unnormal_float_long_to_ext_reg,RRF_R,"MYR"), /*@Z9*/ /*B33C*/ GENx37Xx___x900 (multiply_add_unnormal_float_long_to_ext_high_reg,RRF_R,"MAYHR"), /*@Z9*/ /*B33D*/ GENx37Xx___x900 (multiply_unnormal_float_long_to_ext_high_reg,RRF_R,"MYHR"), /*@Z9*/ /*B33E*/ GENx37Xx390x900 (multiply_add_float_long_reg,RRF_R,"MADR"), /*B33F*/ GENx37Xx390x900 (multiply_subtract_float_long_reg,RRF_R,"MSDR"), /*B340*/ GENx37Xx390x900 (load_positive_bfp_ext_reg,RRE,"LPXBR"), /*B341*/ GENx37Xx390x900 (load_negative_bfp_ext_reg,RRE,"LNXBR"), /*B342*/ GENx37Xx390x900 (load_and_test_bfp_ext_reg,RRE,"LTXBR"), /*B343*/ GENx37Xx390x900 (load_complement_bfp_ext_reg,RRE,"LCXBR"), /*B344*/ GENx37Xx390x900 (load_rounded_bfp_long_to_short_reg,RRE,"LEDBR"), /*B345*/ GENx37Xx390x900 (load_rounded_bfp_ext_to_long_reg,RRE,"LDXBR"), /*B346*/ GENx37Xx390x900 (load_rounded_bfp_ext_to_short_reg,RRE,"LEXBR"), /*B347*/ GENx37Xx390x900 (load_fp_int_bfp_ext_reg,RRF_M,"FIXBR"), /*B348*/ GENx37Xx390x900 (compare_and_signal_bfp_ext_reg,RRE,"KXBR"), /*B349*/ GENx37Xx390x900 (compare_bfp_ext_reg,RRE,"CXBR"), /*B34A*/ GENx37Xx390x900 (add_bfp_ext_reg,RRE,"AXBR"), /*B34B*/ GENx37Xx390x900 (subtract_bfp_ext_reg,RRE,"SXBR"), /*B34C*/ GENx37Xx390x900 (multiply_bfp_ext_reg,RRE,"MXBR"), /*B34D*/ GENx37Xx390x900 (divide_bfp_ext_reg,RRE,"DXBR"), /*B34E*/ GENx___x___x___ , /*B34F*/ GENx___x___x___ , /*B350*/ GENx37Xx390x900 (convert_float_long_to_bfp_short_reg,RRF_M,"TBEDR"), /*B351*/ GENx37Xx390x900 (convert_float_long_to_bfp_long_reg,RRF_M,"TBDR"), /*B352*/ GENx___x___x___ , /*B353*/ GENx37Xx390x900 (divide_integer_bfp_short_reg,RRF_RM,"DIEBR"), /*B354*/ GENx___x___x___ , /*B355*/ GENx___x___x___ , /*B356*/ GENx___x___x___ , /*B357*/ GENx37Xx390x900 (load_fp_int_bfp_short_reg,RRF_M,"FIEBR"), /*B358*/ GENx37Xx390x900 (convert_bfp_short_to_float_long_reg,RRE,"THDER"), /*B359*/ GENx37Xx390x900 (convert_bfp_long_to_float_long_reg,RRE,"THDR"), /*B35A*/ GENx___x___x___ , /*B35B*/ GENx37Xx390x900 (divide_integer_bfp_long_reg,RRF_RM,"DIDBR"), /*B35C*/ GENx___x___x___ , /*B35D*/ GENx___x___x___ , /*B35E*/ GENx___x___x___ , /*B35F*/ GENx37Xx390x900 (load_fp_int_bfp_long_reg,RRF_M,"FIDBR"), /*B360*/ GENx37Xx390x900 (load_positive_float_ext_reg,RRE,"LPXR"), /*B361*/ GENx37Xx390x900 (load_negative_float_ext_reg,RRE,"LNXR"), /*B362*/ GENx37Xx390x900 (load_and_test_float_ext_reg,RRE,"LTXR"), /*B363*/ GENx37Xx390x900 (load_complement_float_ext_reg,RRE,"LCXR"), /*B364*/ GENx___x___x___ , /*B365*/ GENx37Xx390x900 (load_float_ext_reg,RRE,"LXR"), /*B366*/ GENx37Xx390x900 (load_rounded_float_ext_to_short_reg,RRE,"LEXR"), /*B367*/ GENx37Xx390x900 (load_fp_int_float_ext_reg,RRE,"FIXR"), /*B368*/ GENx___x___x___ , /*B369*/ GENx37Xx390x900 (compare_float_ext_reg,RRE,"CXR"), /*B36A*/ GENx___x___x___ , /*B36B*/ GENx___x___x___ , /*B36C*/ GENx___x___x___ , /*B36D*/ GENx___x___x___ , /*B36E*/ GENx___x___x___ , /*B36F*/ GENx___x___x___ , /*B370*/ GENx37Xx390x900 (load_positive_fpr_long_reg,RRE,"LPDFR"), /*B371*/ GENx37Xx390x900 (load_negative_fpr_long_reg,RRE,"LNDFR"), /*B372*/ GENx37Xx390x900 (copy_sign_fpr_long_reg,RRF_M,"CPSDR"), /*B373*/ GENx37Xx390x900 (load_complement_fpr_long_reg,RRE,"LCDFR"), /*B374*/ GENx37Xx390x900 (load_zero_float_short_reg,RRE_R1,"LZER"), /*B375*/ GENx37Xx390x900 (load_zero_float_long_reg,RRE_R1,"LZDR"), /*B376*/ GENx37Xx390x900 (load_zero_float_ext_reg,RRE_R1,"LZXR"), /*B377*/ GENx37Xx390x900 (load_fp_int_float_short_reg,RRE,"FIER"), /*B378*/ GENx___x___x___ , /*B379*/ GENx___x___x___ , /*B37A*/ GENx___x___x___ , /*B37B*/ GENx___x___x___ , /*B37C*/ GENx___x___x___ , /*B37D*/ GENx___x___x___ , /*B37E*/ GENx___x___x___ , /*B37F*/ GENx37Xx390x900 (load_fp_int_float_long_reg,RRE,"FIDR"), /*B380*/ GENx___x___x___ , /*B381*/ GENx___x___x___ , /*B382*/ GENx___x___x___ , /*B383*/ GENx___x___x___ , /*B384*/ GENx37Xx390x900 (set_fpc,RRE_R1,"SFPC"), /*B385*/ GENx37Xx390x900 (set_fpc_and_signal,RRE_R1,"SFASR"), /*B386*/ GENx___x___x___ , /*B387*/ GENx___x___x___ , /*B388*/ GENx___x___x___ , /*B389*/ GENx___x___x___ , /*B38A*/ GENx___x___x___ , /*B38B*/ GENx___x___x___ , /*B38C*/ GENx37Xx390x900 (extract_fpc,RRE_R1,"EFPC"), /*B38D*/ GENx___x___x___ , /*B38E*/ GENx___x___x___ , /*B38F*/ GENx___x___x___ , /*B390*/ GENx___x___x___ , /*B391*/ GENx___x___x___ , /*B392*/ GENx___x___x___ , /*B393*/ GENx___x___x___ , /*B394*/ GENx37Xx390x900 (convert_fix32_to_bfp_short_reg,RRE,"CEFBR"), /*B395*/ GENx37Xx390x900 (convert_fix32_to_bfp_long_reg,RRE,"CDFBR"), /*B396*/ GENx37Xx390x900 (convert_fix32_to_bfp_ext_reg,RRE,"CXFBR"), /*B397*/ GENx___x___x___ , /*B398*/ GENx37Xx390x900 (convert_bfp_short_to_fix32_reg,RRF_M,"CFEBR"), /*B399*/ GENx37Xx390x900 (convert_bfp_long_to_fix32_reg,RRF_M,"CFDBR"), /*B39A*/ GENx37Xx390x900 (convert_bfp_ext_to_fix32_reg,RRF_M,"CFXBR"), /*B39B*/ GENx___x___x___ , /*B39C*/ GENx___x___x___ , /*B39D*/ GENx___x___x___ , /*B39E*/ GENx___x___x___ , /*B39F*/ GENx___x___x___ , /*B3A0*/ GENx___x___x___ , /*B3A1*/ GENx___x___x___ , /*B3A2*/ GENx___x___x___ , /*B3A3*/ GENx___x___x___ , /*B3A4*/ GENx___x___x900 (convert_fix64_to_bfp_short_reg,RRE,"CEGBR"), /*B3A5*/ GENx___x___x900 (convert_fix64_to_bfp_long_reg,RRE,"CDGBR"), /*B3A6*/ GENx___x___x900 (convert_fix64_to_bfp_ext_reg,RRE,"CXGBR"), /*B3A7*/ GENx___x___x___ , /*B3A8*/ GENx___x___x900 (convert_bfp_short_to_fix64_reg,RRF_M,"CGEBR"), /*B3A9*/ GENx___x___x900 (convert_bfp_long_to_fix64_reg,RRF_M,"CGDBR"), /*B3AA*/ GENx___x___x900 (convert_bfp_ext_to_fix64_reg,RRF_M,"CGXBR"), /*B3AB*/ GENx___x___x___ , /*B3AC*/ GENx___x___x___ , /*B3AD*/ GENx___x___x___ , /*B3AE*/ GENx___x___x___ , /*B3AF*/ GENx___x___x___ , /*B3B0*/ GENx___x___x___ , /*B3B1*/ GENx___x___x___ , /*B3B2*/ GENx___x___x___ , /*B3B3*/ GENx___x___x___ , /*B3B4*/ GENx37Xx390x900 (convert_fixed_to_float_short_reg,RRE,"CEFR"), /*B3B5*/ GENx37Xx390x900 (convert_fixed_to_float_long_reg,RRE,"CDFR"), /*B3B6*/ GENx37Xx390x900 (convert_fixed_to_float_ext_reg,RRE,"CXFR"), /*B3B7*/ GENx___x___x___ , /*B3B8*/ GENx37Xx390x900 (convert_float_short_to_fixed_reg,RRF_M,"CFER"), /*B3B9*/ GENx37Xx390x900 (convert_float_long_to_fixed_reg,RRF_M,"CFDR"), /*B3BA*/ GENx37Xx390x900 (convert_float_ext_to_fixed_reg,RRF_M,"CFXR"), /*B3BB*/ GENx___x___x___ , /*B3BC*/ GENx___x___x___ , /*B3BD*/ GENx___x___x___ , /*B3BE*/ GENx___x___x___ , /*B3BF*/ GENx___x___x___ , /*B3C0*/ GENx___x___x___ , /*B3C1*/ GENx___x___x900 (load_fpr_from_gr_long_reg,RRE,"LDGR"), /*B3C2*/ GENx___x___x___ , /*B3C3*/ GENx___x___x___ , /*B3C4*/ GENx___x___x900 (convert_fix64_to_float_short_reg,RRE,"CEGR"), /*B3C5*/ GENx___x___x900 (convert_fix64_to_float_long_reg,RRE,"CDGR"), /*B3C6*/ GENx___x___x900 (convert_fix64_to_float_ext_reg,RRE,"CXGR"), /*B3C7*/ GENx___x___x___ , /*B3C8*/ GENx___x___x900 (convert_float_short_to_fix64_reg,RRF_M,"CGER"), /*B3C9*/ GENx___x___x900 (convert_float_long_to_fix64_reg,RRF_M,"CGDR"), /*B3CA*/ GENx___x___x900 (convert_float_ext_to_fix64_reg,RRF_M,"CGXR"), /*B3CB*/ GENx___x___x___ , /*B3CC*/ GENx___x___x___ , /*B3CD*/ GENx___x___x900 (load_gr_from_fpr_long_reg,RRE,"LGDR"), /*B3CE*/ GENx___x___x___ , /*B3CF*/ GENx___x___x___ , /*B3D0*/ GENx___x390x900 (multiply_dfp_long_reg,RRR,"MDTR"), /*B3D1*/ GENx___x390x900 (divide_dfp_long_reg,RRR,"DDTR"), /*B3D2*/ GENx___x390x900 (add_dfp_long_reg,RRR,"ADTR"), /*B3D3*/ GENx___x390x900 (subtract_dfp_long_reg,RRR,"SDTR"), /*B3D4*/ GENx___x390x900 (load_lengthened_dfp_short_to_long_reg,RRF_M4,"LDETR"), /*B3D5*/ GENx___x390x900 (load_rounded_dfp_long_to_short_reg,RRF_MM,"LEDTR"), /*B3D6*/ GENx___x390x900 (load_and_test_dfp_long_reg,RRE,"LTDTR"), /*B3D7*/ GENx___x390x900 (load_fp_int_dfp_long_reg,RRF_MM,"FIDTR"), /*B3D8*/ GENx___x390x900 (multiply_dfp_ext_reg,RRR,"MXTR"), /*B3D9*/ GENx___x390x900 (divide_dfp_ext_reg,RRR,"DXTR"), /*B3DA*/ GENx___x390x900 (add_dfp_ext_reg,RRR,"AXTR"), /*B3DB*/ GENx___x390x900 (subtract_dfp_ext_reg,RRR,"SXTR"), /*B3DC*/ GENx___x390x900 (load_lengthened_dfp_long_to_ext_reg,RRF_M4,"LXDTR"), /*B3DD*/ GENx___x390x900 (load_rounded_dfp_ext_to_long_reg,RRF_MM,"LDXTR"), /*B3DE*/ GENx___x390x900 (load_and_test_dfp_ext_reg,RRE,"LTXTR"), /*B3DF*/ GENx___x390x900 (load_fp_int_dfp_ext_reg,RRF_MM,"FIXTR"), /*B3E0*/ GENx___x390x900 (compare_and_signal_dfp_long_reg,RRE,"KDTR"), /*B3E1*/ GENx___x390x900 (convert_dfp_long_to_fix64_reg,RRF_M,"CGDTR"), /*B3E2*/ GENx___x390x900 (convert_dfp_long_to_ubcd64_reg,RRE,"CUDTR"), /*B3E3*/ GENx___x390x900 (convert_dfp_long_to_sbcd64_reg,RRF_M4,"CSDTR"), /*B3E4*/ GENx___x390x900 (compare_dfp_long_reg,RRE,"CDTR"), /*B3E5*/ GENx___x390x900 (extract_biased_exponent_dfp_long_to_fix64_reg,RRE,"EEDTR"), /*B3E6*/ GENx___x___x___ , /*B3E7*/ GENx___x390x900 (extract_significance_dfp_long_reg,RRE,"ESDTR"), /*B3E8*/ GENx___x390x900 (compare_and_signal_dfp_ext_reg,RRE,"KXTR"), /*B3E9*/ GENx___x390x900 (convert_dfp_ext_to_fix64_reg,RRF_M,"CGXTR"), /*B3EA*/ GENx___x390x900 (convert_dfp_ext_to_ubcd128_reg,RRE,"CUXTR"), /*B3EB*/ GENx___x390x900 (convert_dfp_ext_to_sbcd128_reg,RRF_M4,"CSXTR"), /*B3EC*/ GENx___x390x900 (compare_dfp_ext_reg,RRE,"CXTR"), /*B3ED*/ GENx___x390x900 (extract_biased_exponent_dfp_ext_to_fix64_reg,RRE,"EEXTR"), /*B3EE*/ GENx___x___x___ , /*B3EF*/ GENx___x390x900 (extract_significance_dfp_ext_reg,RRE,"ESXTR"), /*B3F0*/ GENx___x___x___ , /*B3F1*/ GENx___x390x900 (convert_fix64_to_dfp_long_reg,RRE,"CDGTR"), /*B3F2*/ GENx___x390x900 (convert_ubcd64_to_dfp_long_reg,RRE,"CDUTR"), /*B3F3*/ GENx___x390x900 (convert_sbcd64_to_dfp_long_reg,RRE,"CDSTR"), /*B3F4*/ GENx___x390x900 (compare_exponent_dfp_long_reg,RRE,"CEDTR"), /*B3F5*/ GENx___x390x900 (quantize_dfp_long_reg,RRF_RM,"QADTR"), /*B3F6*/ GENx___x390x900 (insert_biased_exponent_fix64_to_dfp_long_reg,RRF_M,"IEDTR"), /*B3F7*/ GENx___x390x900 (reround_dfp_long_reg,RRF_RM,"RRDTR"), /*B3F8*/ GENx___x___x___ , /*B3F9*/ GENx___x390x900 (convert_fix64_to_dfp_ext_reg,RRE,"CXGTR"), /*B3FA*/ GENx___x390x900 (convert_ubcd128_to_dfp_ext_reg,RRE,"CXUTR"), /*B3FB*/ GENx___x390x900 (convert_sbcd128_to_dfp_ext_reg,RRE,"CXSTR"), /*B3FC*/ GENx___x390x900 (compare_exponent_dfp_ext_reg,RRE,"CEXTR"), /*B3FD*/ GENx___x390x900 (quantize_dfp_ext_reg,RRF_RM,"QAXTR"), /*B3FE*/ GENx___x390x900 (insert_biased_exponent_fix64_to_dfp_ext_reg,RRF_M,"IEXTR"), /*B3FF*/ GENx___x390x900 (reround_dfp_ext_reg,RRF_RM,"RRXTR") }; // #endif /*defined(FEATURE_BASIC_FP_EXTENSIONS)*/ // #if defined(FEATURE_ESAME) DLL_EXPORT zz_func opcode_b9xx[256][GEN_MAXARCH] = { /*B900*/ GENx___x___x900 (load_positive_long_register,RRE,"LPGR"), /*B901*/ GENx___x___x900 (load_negative_long_register,RRE,"LNGR"), /*B902*/ GENx___x___x900 (load_and_test_long_register,RRE,"LTGR"), /*B903*/ GENx___x___x900 (load_complement_long_register,RRE,"LCGR"), /*B904*/ GENx___x___x900 (load_long_register,RRE,"LGR"), /*B905*/ GENx___x___x900 (load_using_real_address_long,RRE,"LURAG"), /*B906*/ GENx___x___x900 (load_long_byte_register,RRE,"LGBR"), /*@Z9*/ /*B907*/ GENx___x___x900 (load_long_halfword_register,RRE,"LGHR"), /*@Z9*/ /*B908*/ GENx___x___x900 (add_long_register,RRE,"AGR"), /*B909*/ GENx___x___x900 (subtract_long_register,RRE,"SGR"), /*B90A*/ GENx___x___x900 (add_logical_long_register,RRE,"ALGR"), /*B90B*/ GENx___x___x900 (subtract_logical_long_register,RRE,"SLGR"), /*B90C*/ GENx___x___x900 (multiply_single_long_register,RRE,"MSGR"), /*B90D*/ GENx___x___x900 (divide_single_long_register,RRE,"DSGR"), /*B90E*/ GENx___x___x900 (extract_stacked_registers_long,RRE,"EREGG"), /*B90F*/ GENx___x___x900 (load_reversed_long_register,RRE,"LRVGR"), /*B910*/ GENx___x___x900 (load_positive_long_fullword_register,RRE,"LPGFR"), /*B911*/ GENx___x___x900 (load_negative_long_fullword_register,RRE,"LNGFR"), /*B912*/ GENx___x___x900 (load_and_test_long_fullword_register,RRE,"LTGFR"), /*B913*/ GENx___x___x900 (load_complement_long_fullword_register,RRE,"LCGFR"), /*B914*/ GENx___x___x900 (load_long_fullword_register,RRE,"LGFR"), /*B915*/ GENx___x___x___ , /*B916*/ GENx___x___x900 (load_logical_long_fullword_register,RRE,"LLGFR"), /*B917*/ GENx___x___x900 (load_logical_long_thirtyone_register,RRE,"LLGTR"), /*B918*/ GENx___x___x900 (add_long_fullword_register,RRE,"AGFR"), /*B919*/ GENx___x___x900 (subtract_long_fullword_register,RRE,"SGFR"), /*B91A*/ GENx___x___x900 (add_logical_long_fullword_register,RRE,"ALGFR"), /*B91B*/ GENx___x___x900 (subtract_logical_long_fullword_register,RRE,"SLGFR"), /*B91C*/ GENx___x___x900 (multiply_single_long_fullword_register,RRE,"MSGFR"), /*B91D*/ GENx___x___x900 (divide_single_long_fullword_register,RRE,"DSGFR"), /*B91E*/ GENx37Xx390x900 (compute_message_authentication_code_r,RRE,"KMAC"), /*B91F*/ GENx___x390x900 (load_reversed_register,RRE,"LRVR"), /*B920*/ GENx___x___x900 (compare_long_register,RRE,"CGR"), /*B921*/ GENx___x___x900 (compare_logical_long_register,RRE,"CLGR"), /*B922*/ GENx___x___x___ , /*B923*/ GENx___x___x___ , /*B924*/ GENx___x___x___ , /*B925*/ GENx___x___x900 (store_using_real_address_long,RRE,"STURG"), /*B926*/ GENx37Xx390x900 (load_byte_register,RRE,"LBR"), /*@Z9*/ /*B927*/ GENx37Xx390x900 (load_halfword_register,RRE,"LHR"), /*@Z9*/ /*B928*/ GENx___x___x___ , /*B929*/ GENx___x___x___ , /*B92A*/ GENx___x___x___ , /*B92B*/ GENx___x___x___ , /*B92C*/ GENx___x___x___ , /*B92D*/ GENx___x___x___ , /*B92E*/ GENx37Xx390x900 (cipher_message_r,RRE,"KM"), /*B92F*/ GENx37Xx390x900 (cipher_message_with_chaining_r,RRE,"KMC"), /*B930*/ GENx___x___x900 (compare_long_fullword_register,RRE,"CGFR"), /*B931*/ GENx___x___x900 (compare_logical_long_fullword_register,RRE,"CLGFR"), /*B932*/ GENx___x___x___ , /*B933*/ GENx___x___x___ , /*B934*/ GENx___x___x___ , /*B935*/ GENx___x___x___ , /*B936*/ GENx___x___x___ , /*B937*/ GENx___x___x___ , /*B938*/ GENx___x___x___ , /*B939*/ GENx___x___x___ , /*B93A*/ GENx___x___x___ , /*B93B*/ GENx___x___x___ , /*B93C*/ GENx___x___x___ , /*B93D*/ GENx___x___x___ , /*B93E*/ GENx37Xx390x900 (compute_message_digest_r,RRE,"KIMD"), /*B93F*/ GENx37Xx390x900 (compute_message_digest_r,RRE,"KLMD"), /*B940*/ GENx___x___x___ , /*B941*/ GENx___x___x___ , /*B942*/ GENx___x___x___ , /*B943*/ GENx___x___x___ , /*B944*/ GENx___x___x___ , /*B945*/ GENx___x___x___ , /*B946*/ GENx___x___x900 (branch_on_count_long_register,RRE,"BCTGR"), /*B947*/ GENx___x___x___ , /*B948*/ GENx___x___x___ , /*B949*/ GENx___x___x___ , /*B94A*/ GENx___x___x___ , /*B94B*/ GENx___x___x___ , /*B94C*/ GENx___x___x___ , /*B94D*/ GENx___x___x___ , /*B94E*/ GENx___x___x___ , /*B94F*/ GENx___x___x___ , /*B950*/ GENx___x___x___ , /*B951*/ GENx___x___x___ , /*B952*/ GENx___x___x___ , /*B953*/ GENx___x___x___ , /*B954*/ GENx___x___x___ , /*B955*/ GENx___x___x___ , /*B956*/ GENx___x___x___ , /*B957*/ GENx___x___x___ , /*B958*/ GENx___x___x___ , /*B959*/ GENx___x___x___ , /*B95A*/ GENx___x___x___ , /*B95B*/ GENx___x___x___ , /*B95C*/ GENx___x___x___ , /*B95D*/ GENx___x___x___ , /*B95E*/ GENx___x___x___ , /*B95F*/ GENx___x___x___ , /*B960*/ GENx___x___x900 (compare_and_trap_long_register,RRF_M3,"CGRT"), /*208*/ /*B961*/ GENx___x___x900 (compare_logical_and_trap_long_register,RRF_M3,"CLGRT"), /*208*/ /*B962*/ GENx___x___x___ , /*B963*/ GENx___x___x___ , /*B964*/ GENx___x___x___ , /*B965*/ GENx___x___x___ , /*B966*/ GENx___x___x___ , /*B967*/ GENx___x___x___ , /*B968*/ GENx___x___x___ , /*B969*/ GENx___x___x___ , /*B96A*/ GENx___x___x___ , /*B96B*/ GENx___x___x___ , /*B96C*/ GENx___x___x___ , /*B96D*/ GENx___x___x___ , /*B96E*/ GENx___x___x___ , /*B96F*/ GENx___x___x___ , /*B970*/ GENx___x___x___ , /*B971*/ GENx___x___x___ , /*B972*/ GENx37Xx390x900 (compare_and_trap_register,RRF_M3,"CRT"), /*208*/ /*B973*/ GENx37Xx390x900 (compare_logical_and_trap_register,RRF_M3,"CLRT"), /*208*/ /*B974*/ GENx___x___x___ , /*B975*/ GENx___x___x___ , /*B976*/ GENx___x___x___ , /*B977*/ GENx___x___x___ , /*B978*/ GENx___x___x___ , /*B979*/ GENx___x___x___ , /*B97A*/ GENx___x___x___ , /*B97B*/ GENx___x___x___ , /*B97C*/ GENx___x___x___ , /*B97D*/ GENx___x___x___ , /*B97E*/ GENx___x___x___ , /*B97F*/ GENx___x___x___ , /*B980*/ GENx___x___x900 (and_long_register,RRE,"NGR"), /*B981*/ GENx___x___x900 (or_long_register,RRE,"OGR"), /*B982*/ GENx___x___x900 (exclusive_or_long_register,RRE,"XGR"), /*B983*/ GENx___x___x900 (find_leftmost_one_long_register,RRE,"FLOGR"), /*@Z9*/ /*B984*/ GENx___x___x900 (load_logical_long_character_register,RRE,"LLGCR"), /*@Z9*/ /*B985*/ GENx___x___x900 (load_logical_long_halfword_register,RRE,"LLGHR"), /*@Z9*/ /*B986*/ GENx___x___x900 (multiply_logical_long_register,RRE,"MLGR"), /*B987*/ GENx___x___x900 (divide_logical_long_register,RRE,"DLGR"), /*B988*/ GENx___x___x900 (add_logical_carry_long_register,RRE,"ALCGR"), /*B989*/ GENx___x___x900 (subtract_logical_borrow_long_register,RRE,"SLBGR"), /*B98A*/ GENx___x___x900 (compare_and_swap_and_purge_long,RRE,"CSPG"), /*B98B*/ GENx___x___x___ , /*B98C*/ GENx___x___x___ , /*B98D*/ GENx37Xx390x900 (extract_psw,RRE,"EPSW"), /*B98E*/ GENx___x___x900 (invalidate_dat_table_entry,RRF_R,"IDTE"), /*B98F*/ GENx___x___x___ , /*B990*/ GENx37Xx390x900 (translate_two_to_two,RRF_M3,"TRTT"), /*B991*/ GENx37Xx390x900 (translate_two_to_one,RRF_M3,"TRTO"), /*B992*/ GENx37Xx390x900 (translate_one_to_two,RRF_M3,"TROT"), /*B993*/ GENx37Xx390x900 (translate_one_to_one,RRF_M3,"TROO"), /*B994*/ GENx37Xx390x900 (load_logical_character_register,RRE,"LLCR"), /*@Z9*/ /*B995*/ GENx37Xx390x900 (load_logical_halfword_register,RRE,"LLHR"), /*@Z9*/ /*B996*/ GENx37Xx390x900 (multiply_logical_register,RRE,"MLR"), /*B997*/ GENx37Xx390x900 (divide_logical_register,RRE,"DLR"), /*B998*/ GENx37Xx390x900 (add_logical_carry_register,RRE,"ALCR"), /*B999*/ GENx37Xx390x900 (subtract_logical_borrow_register,RRE,"SLBR"), /*B99A*/ GENx___x___x900 (extract_primary_asn_and_instance,RRE_R1,"EPAIR"), /*B99B*/ GENx___x___x900 (extract_secondary_asn_and_instance,RRE_R1,"ESAIR"), /*B99C*/ GENx___x___x___ , /*(extract_qdio_buffer_state,?,"EQBS"),*/ /*B99D*/ GENx___x___x900 (extract_and_set_extended_authority,RRE_R1,"ESEA"), /*B99E*/ GENx___x___x900 (program_transfer_with_instance,RRE,"PTI"), /*B99F*/ GENx___x___x900 (set_secondary_asn_with_instance,RRE_R1,"SSAIR"), /*B9A0*/ GENx___x___x___ , /*B9A1*/ GENx___x___x___ , /*B9A2*/ GENx___x___x900 (perform_topology_function,RRE,"PTF"), /*B9A3*/ GENx___x___x___ , /*B9B9*/ GENx___x___x___ , /*B9A5*/ GENx___x___x___ , /*B9A6*/ GENx___x___x___ , /*B9A7*/ GENx___x___x___ , /*B9A8*/ GENx___x___x___ , /*B9A9*/ GENx___x___x___ , /*B9AA*/ GENx___x___x900 (load_page_table_entry_address,RRF_RM,"LPTEA"), /*@Z9*/ /*B9AB*/ GENx___x___x___ , /*(extract_and_set_storage_attributes,?,"ESSA"),*/ /*B9AC*/ GENx___x___x___ , /*B9AD*/ GENx___x___x___ , /*B9AE*/ GENx___x___x___ , /*B9AF*/ GENx___x___x900 (perform_frame_management_function,RRE,"PFMF"), /*B9B0*/ GENx37Xx390x900 (convert_utf8_to_utf32,RRF_M3,"CU14"), /*B9B1*/ GENx37Xx390x900 (convert_utf16_to_utf32,RRF_M3,"CU24"), /*B9B2*/ GENx37Xx390x900 (convert_utf32_to_utf8,RRE,"CU41"), /*B9B3*/ GENx37Xx390x900 (convert_utf32_to_utf16,RRE,"CU42"), /*B9B4*/ GENx___x___x___ , /*B9B5*/ GENx___x___x___ , /*B9B6*/ GENx___x___x___ , /*B9B7*/ GENx___x___x___ , /*B9B8*/ GENx___x___x___ , /*B9B9*/ GENx___x___x___ , /*B9BA*/ GENx___x___x___ , /*B9BB*/ GENx___x___x___ , /*B9BC*/ GENx___x___x___ , /*B9BD*/ GENx37Xx390x900 (translate_and_test_reverse_extended,RRF_M3,"TRTRE"), /*B9BE*/ GENx37Xx390x900 (search_string_unicode,RRE,"SRSTU"), /*B9BF*/ GENx37Xx390x900 (translate_and_test_extended,RRF_M3,"TRTE"), /*B9C0*/ GENx___x___x___ , /*B9C1*/ GENx___x___x___ , /*B9C2*/ GENx___x___x___ , /*B9C3*/ GENx___x___x___ , /*B9C4*/ GENx___x___x___ , /*B9C5*/ GENx___x___x___ , /*B9C6*/ GENx___x___x___ , /*B9C7*/ GENx___x___x___ , /*B9C8*/ GENx___x___x___ , /*B9C9*/ GENx___x___x___ , /*B9CA*/ GENx___x___x___ , /*B9CB*/ GENx___x___x___ , /*B9CC*/ GENx___x___x___ , /*B9CD*/ GENx___x___x___ , /*B9CE*/ GENx___x___x___ , /*B9CF*/ GENx___x___x___ , /*B9D0*/ GENx___x___x___ , /*B9D1*/ GENx___x___x___ , /*B9D2*/ GENx___x___x___ , /*B9D3*/ GENx___x___x___ , /*B9D4*/ GENx___x___x___ , /*B9D5*/ GENx___x___x___ , /*B9D6*/ GENx___x___x___ , /*B9D7*/ GENx___x___x___ , /*B9D8*/ GENx___x___x___ , /*B9D9*/ GENx___x___x___ , /*B9DA*/ GENx___x___x___ , /*B9DB*/ GENx___x___x___ , /*B9DC*/ GENx___x___x___ , /*B9DD*/ GENx___x___x___ , /*B9DE*/ GENx___x___x___ , /*B9DF*/ GENx___x___x___ , /*B9E0*/ GENx___x___x___ , /*B9E1*/ GENx___x___x___ , /*B9E2*/ GENx___x___x___ , /*B9E3*/ GENx___x___x___ , /*B9E4*/ GENx___x___x___ , /*B9E5*/ GENx___x___x___ , /*B9E6*/ GENx___x___x___ , /*B9E7*/ GENx___x___x___ , /*B9E8*/ GENx___x___x___ , /*B9E9*/ GENx___x___x___ , /*B9EA*/ GENx___x___x___ , /*B9EB*/ GENx___x___x___ , /*B9EC*/ GENx___x___x___ , /*B9ED*/ GENx___x___x___ , /*B9EE*/ GENx___x___x___ , /*B9EF*/ GENx___x___x___ , /*B9F0*/ GENx___x___x___ , /*B9F1*/ GENx___x___x___ , /*B9F2*/ GENx___x___x___ , /*B9F3*/ GENx___x___x___ , /*B9F4*/ GENx___x___x___ , /*B9F5*/ GENx___x___x___ , /*B9F6*/ GENx___x___x___ , /*B9F7*/ GENx___x___x___ , /*B9F8*/ GENx___x___x___ , /*B9F9*/ GENx___x___x___ , /*B9FA*/ GENx___x___x___ , /*B9FB*/ GENx___x___x___ , /*B9FC*/ GENx___x___x___ , /*B9FD*/ GENx___x___x___ , /*B9FE*/ GENx___x___x___ , /*B9FF*/ GENx___x___x___ }; // #endif /*defined(FEATURE_ESAME)*/ // #if defined(FEATURE_ESAME) DLL_EXPORT zz_func opcode_c0xx[16][GEN_MAXARCH] = { /*C0x0*/ GENx37Xx390x900 (load_address_relative_long,RIL_A,"LARL"), /*C0x1*/ GENx___x___x900 (load_long_fullword_immediate,RIL,"LGFI"), /*@Z9*/ /*C0x2*/ GENx___x___x___ , /*C0x3*/ GENx___x___x___ , /*C0x4*/ GENx37Xx390x900 (branch_relative_on_condition_long,RIL_A,"BRCL"), /*C0x5*/ GENx37Xx390x900 (branch_relative_and_save_long,RIL_A,"BRASL"), /*C0x6*/ GENx___x___x900 (exclusive_or_immediate_high_fullword,RIL,"XIHF"), /*@Z9*/ /*C0x7*/ GENx___x___x900 (exclusive_or_immediate_low_fullword,RIL,"XILF"), /*@Z9*/ /*C0x8*/ GENx___x___x900 (insert_immediate_high_fullword,RIL,"IIHF"), /*@Z9*/ /*C0x9*/ GENx___x___x900 (insert_immediate_low_fullword,RIL,"IILF"), /*@Z9*/ /*C0xA*/ GENx___x___x900 (and_immediate_high_fullword,RIL,"NIHF"), /*@Z9*/ /*C0xB*/ GENx___x___x900 (and_immediate_low_fullword,RIL,"NILF"), /*@Z9*/ /*C0xC*/ GENx___x___x900 (or_immediate_high_fullword,RIL,"OIHF"), /*@Z9*/ /*C0xD*/ GENx___x___x900 (or_immediate_low_fullword,RIL,"OILF"), /*@Z9*/ /*C0xE*/ GENx___x___x900 (load_logical_immediate_high_fullword,RIL,"LLIHF"), /*@Z9*/ /*C0xF*/ GENx___x___x900 (load_logical_immediate_low_fullword,RIL,"LLILF") }; /*@Z9*/ DLL_EXPORT zz_func opcode_c2xx[16][GEN_MAXARCH] = { /*@Z9*/ /*C2x0*/ GENx___x___x900 (multiply_single_immediate_long_fullword,RIL,"MSGFI"), /*208*/ /*C2x1*/ GENx37Xx390x900 (multiply_single_immediate_fullword,RIL,"MSFI"), /*208*/ /*C2x2*/ GENx___x___x___ , /*@Z9*/ /*C2x3*/ GENx___x___x___ , /*@Z9*/ /*C2x4*/ GENx___x___x900 (subtract_logical_long_fullword_immediate,RIL,"SLGFI"), /*@Z9*/ /*C2x5*/ GENx37Xx390x900 (subtract_logical_fullword_immediate,RIL,"SLFI"), /*@Z9*/ /*C2x6*/ GENx___x___x___ , /*@Z9*/ /*C2x7*/ GENx___x___x___ , /*@Z9*/ /*C2x8*/ GENx___x___x900 (add_long_fullword_immediate,RIL,"AGFI"), /*@Z9*/ /*C2x9*/ GENx37Xx390x900 (add_fullword_immediate,RIL,"AFI"), /*@Z9*/ /*C2xA*/ GENx___x___x900 (add_logical_long_fullword_immediate,RIL,"ALGFI"), /*@Z9*/ /*C2xB*/ GENx37Xx390x900 (add_logical_fullword_immediate,RIL,"ALFI"), /*@Z9*/ /*C2xC*/ GENx___x___x900 (compare_long_fullword_immediate,RIL,"CGFI"), /*@Z9*/ /*C2xD*/ GENx37Xx390x900 (compare_fullword_immediate,RIL,"CFI"), /*@Z9*/ /*C2xE*/ GENx___x___x900 (compare_logical_long_fullword_immediate,RIL,"CLGFI"), /*@Z9*/ /*C2xF*/ GENx37Xx390x900 (compare_logical_fullword_immediate,RIL,"CLFI") }; /*@Z9*/ DLL_EXPORT zz_func opcode_c4xx[16][GEN_MAXARCH] = { /*208*/ /*C4x0*/ GENx___x___x___ , /*208*/ /*C4x1*/ GENx___x___x___ , /*208*/ /*C4x2*/ GENx37Xx390x900 (load_logical_halfword_relative_long,RIL_A,"LLHRL"), /*208*/ /*C4x3*/ GENx___x___x___ , /*208*/ /*C4x4*/ GENx___x___x900 (load_halfword_relative_long_long,RIL_A,"LGHRL"), /*208*/ /*C4x5*/ GENx37Xx390x900 (load_halfword_relative_long,RIL_A,"LHRL"), /*208*/ /*C4x6*/ GENx___x___x900 (load_logical_halfword_relative_long_long,RIL_A,"LLGHRL"), /*208*/ /*C4x7*/ GENx37Xx390x900 (store_halfword_relative_long,RIL_A,"STHRL"), /*208*/ /*C4x8*/ GENx___x___x900 (load_relative_long_long,RIL_A,"LGRL"), /*208*/ /*C4x9*/ GENx___x___x___ , /*208*/ /*C4xA*/ GENx___x___x___ , /*208*/ /*C4xB*/ GENx___x___x900 (store_relative_long_long,RIL_A,"STGRL"), /*208*/ /*C4xC*/ GENx___x___x900 (load_relative_long_long_fullword,RIL_A,"LGFRL"), /*208*/ /*C4xD*/ GENx37Xx390x900 (load_relative_long,RIL_A,"LRL"), /*208*/ /*C4xE*/ GENx___x___x900 (load_logical_relative_long_long_fullword,RIL_A,"LLGFRL"), /*208*/ /*C4xF*/ GENx37Xx390x900 (store_relative_long,RIL_A,"STRL") }; /*208*/ DLL_EXPORT zz_func opcode_c6xx[16][GEN_MAXARCH] = { /*208*/ /*C6x0*/ GENx37Xx390x900 (execute_relative_long,RIL_A,"EXRL"), /*208*/ /*C6x1*/ GENx___x___x___ , /*208*/ /*C6x2*/ GENx37Xx390x900 (prefetch_data_relative_long,RIL_A,"PFDRL"), /*208*/ /*C6x3*/ GENx___x___x___ , /*208*/ /*C6x4*/ GENx___x___x900 (compare_halfword_relative_long_long,RIL_A,"CGHRL"), /*208*/ /*C6x5*/ GENx37Xx390x900 (compare_halfword_relative_long,RIL_A,"CHRL"), /*208*/ /*C6x6*/ GENx___x___x900 (compare_logical_relative_long_long_halfword,RIL_A,"CLGHRL"), /*208*/ /*C6x7*/ GENx37Xx390x900 (compare_logical_relative_long_halfword,RIL_A,"CLHRL"), /*208*/ /*C6x8*/ GENx___x___x900 (compare_relative_long_long,RIL_A,"CGRL"), /*208*/ /*C6x9*/ GENx___x___x___ , /*208*/ /*C6xA*/ GENx___x___x900 (compare_logical_relative_long_long,RIL_A,"CLGRL"), /*208*/ /*C6xB*/ GENx___x___x___ , /*208*/ /*C6xC*/ GENx___x___x900 (compare_relative_long_long_fullword,RIL_A,"CGFRL"), /*208*/ /*C6xD*/ GENx37Xx390x900 (compare_relative_long,RIL_A,"CRL"), /*208*/ /*C6xE*/ GENx___x___x900 (compare_logical_relative_long_long_fullword,RIL_A,"CLGFRL"), /*208*/ /*C6xF*/ GENx37Xx390x900 (compare_logical_relative_long,RIL_A,"CLRL") }; /*208*/ DLL_EXPORT zz_func opcode_c8xx[16][GEN_MAXARCH] = { /*C8x0*/ GENx___x___x900 (move_with_optional_specifications,SSF,"MVCOS"), /*C8x1*/ GENx___x___x900 (extract_cpu_time,SSF,"ECTG"), /*C8x2*/ GENx___x___x900 (compare_and_swap_and_store,SSF,"CSST"), /*C8x3*/ GENx___x___x___ , /*C8x4*/ GENx___x___x___ , /*C8x5*/ GENx___x___x___ , /*C8x6*/ GENx___x___x___ , /*C8x7*/ GENx___x___x___ , /*C8x8*/ GENx___x___x___ , /*C8x9*/ GENx___x___x___ , /*C8xA*/ GENx___x___x___ , /*C8xB*/ GENx___x___x___ , /*C8xC*/ GENx___x___x___ , /*C8xD*/ GENx___x___x___ , /*C8xE*/ GENx___x___x___ , /*C8xF*/ GENx___x___x___ }; // #endif /*defined(FEATURE_ESAME)*/ // #if defined(FEATURE_ESAME) DLL_EXPORT zz_func opcode_e3xx[256][GEN_MAXARCH] = { /*E300*/ GENx___x___x___ , /*E301*/ GENx___x___x___ , /*E302*/ GENx___x___x900 (load_and_test_long,RXY,"LTG"), /*@Z9*/ /*E303*/ GENx___x___x900 (load_real_address_long,RXY,"LRAG"), /*E304*/ GENx___x___x900 (load_long,RXY,"LG"), /*E305*/ GENx___x___x___ , /*E306*/ GENx___x___x900 (convert_to_binary_y,RXY,"CVBY"), /*E307*/ GENx___x___x___ , /*E308*/ GENx___x___x900 (add_long,RXY,"AG"), /*E309*/ GENx___x___x900 (subtract_long,RXY,"SG"), /*E30A*/ GENx___x___x900 (add_logical_long,RXY,"ALG"), /*E30B*/ GENx___x___x900 (subtract_logical_long,RXY,"SLG"), /*E30C*/ GENx___x___x900 (multiply_single_long,RXY,"MSG"), /*E30D*/ GENx___x___x900 (divide_single_long,RXY,"DSG"), /*E30E*/ GENx___x___x900 (convert_to_binary_long,RXY,"CVBG"), /*E30F*/ GENx___x___x900 (load_reversed_long,RXY,"LRVG"), /*E310*/ GENx___x___x___ , /*E311*/ GENx___x___x___ , /*E312*/ GENx37Xx390x900 (load_and_test,RXY,"LT"), /*@Z9*/ /*E313*/ GENx___x___x900 (load_real_address_y,RXY,"LRAY"), /*E314*/ GENx___x___x900 (load_long_fullword,RXY,"LGF"), /*E315*/ GENx___x___x900 (load_long_halfword,RXY,"LGH"), /*E316*/ GENx___x___x900 (load_logical_long_fullword,RXY,"LLGF"), /*E317*/ GENx___x___x900 (load_logical_long_thirtyone,RXY,"LLGT"), /*E318*/ GENx___x___x900 (add_long_fullword,RXY,"AGF"), /*E319*/ GENx___x___x900 (subtract_long_fullword,RXY,"SGF"), /*E31A*/ GENx___x___x900 (add_logical_long_fullword,RXY,"ALGF"), /*E31B*/ GENx___x___x900 (subtract_logical_long_fullword,RXY,"SLGF"), /*E31C*/ GENx___x___x900 (multiply_single_long_fullword,RXY,"MSGF"), /*E31D*/ GENx___x___x900 (divide_single_long_fullword,RXY,"DSGF"), /*E31E*/ GENx___x390x900 (load_reversed,RXY,"LRV"), /*E31F*/ GENx___x390x900 (load_reversed_half,RXY,"LRVH"), /*E320*/ GENx___x___x900 (compare_long,RXY,"CG"), /*E321*/ GENx___x___x900 (compare_logical_long,RXY,"CLG"), /*E322*/ GENx___x___x___ , /*E323*/ GENx___x___x___ , /*E324*/ GENx___x___x900 (store_long,RXY,"STG"), /*E325*/ GENx___x___x___ , /*E326*/ GENx___x___x900 (convert_to_decimal_y,RXY,"CVDY"), /*E327*/ GENx___x___x___ , /*E328*/ GENx___x___x___ , /*E329*/ GENx___x___x___ , /*E32A*/ GENx___x___x___ , /*E32B*/ GENx___x___x___ , /*E32C*/ GENx___x___x___ , /*E32D*/ GENx___x___x___ , /*E32E*/ GENx___x___x900 (convert_to_decimal_long,RXY,"CVDG"), /*E32F*/ GENx___x___x900 (store_reversed_long,RXY,"STRVG"), /*E330*/ GENx___x___x900 (compare_long_fullword,RXY,"CGF"), /*E331*/ GENx___x___x900 (compare_logical_long_fullword,RXY,"CLGF"), /*E332*/ GENx___x___x900 (load_and_test_long_fullword,RXY,"LTGF"), /*208*/ /*E333*/ GENx___x___x___ , /*E334*/ GENx___x___x900 (compare_halfword_long,RXY,"CGH"), /*208*/ /*E335*/ GENx___x___x___ , /*E336*/ GENx37Xx390x900 (prefetch_data,RXY,"PFD"), /*208*/ /*E337*/ GENx___x___x___ , /*E338*/ GENx___x___x___ , /*E339*/ GENx___x___x___ , /*E33A*/ GENx___x___x___ , /*E33B*/ GENx___x___x___ , /*E33C*/ GENx___x___x___ , /*E33D*/ GENx___x___x___ , /*E33E*/ GENx___x390x900 (store_reversed,RXY,"STRV"), /*E33F*/ GENx___x390x900 (store_reversed_half,RXY,"STRVH"), /*E340*/ GENx___x___x___ , /*E341*/ GENx___x___x___ , /*E342*/ GENx___x___x___ , /*E343*/ GENx___x___x___ , /*E344*/ GENx___x___x___ , /*E345*/ GENx___x___x___ , /*E346*/ GENx___x___x900 (branch_on_count_long,RXY,"BCTG"), /*E347*/ GENx___x___x___ , /*E348*/ GENx___x___x___ , /*E349*/ GENx___x___x___ , /*E34A*/ GENx___x___x___ , /*E34B*/ GENx___x___x___ , /*E34C*/ GENx___x___x___ , /*E34D*/ GENx___x___x___ , /*E34E*/ GENx___x___x___ , /*E34F*/ GENx___x___x___ , /*E350*/ GENx___x___x900 (store_y,RXY,"STY"), /*E351*/ GENx___x___x900 (multiply_single_y,RXY,"MSY"), /*E352*/ GENx___x___x___ , /*E353*/ GENx___x___x___ , /*E354*/ GENx___x___x900 (and_y,RXY,"NY"), /*E355*/ GENx___x___x900 (compare_logical_y,RXY,"CLY"), /*E356*/ GENx___x___x900 (or_y,RXY,"OY"), /*E357*/ GENx___x___x900 (exclusive_or_y,RXY,"XY"), /*E358*/ GENx___x___x900 (load_y,RXY,"LY"), /*E359*/ GENx___x___x900 (compare_y,RXY,"CY"), /*E35A*/ GENx___x___x900 (add_y,RXY,"AY"), /*E35B*/ GENx___x___x900 (subtract_y,RXY,"SY"), /*E35C*/ GENx___x___x900 (multiply_y,RXY,"MFY"), /*208*/ /*E35D*/ GENx___x___x___ , /*E35E*/ GENx___x___x900 (add_logical_y,RXY,"ALY"), /*E35F*/ GENx___x___x900 (subtract_logical_y,RXY,"SLY"), /*E360*/ GENx___x___x___ , /*E361*/ GENx___x___x___ , /*E362*/ GENx___x___x___ , /*E363*/ GENx___x___x___ , /*E364*/ GENx___x___x___ , /*E365*/ GENx___x___x___ , /*E366*/ GENx___x___x___ , /*E367*/ GENx___x___x___ , /*E368*/ GENx___x___x___ , /*E369*/ GENx___x___x___ , /*E36A*/ GENx___x___x___ , /*E36B*/ GENx___x___x___ , /*E36C*/ GENx___x___x___ , /*E36D*/ GENx___x___x___ , /*E36E*/ GENx___x___x___ , /*E36F*/ GENx___x___x___ , /*E370*/ GENx___x___x900 (store_halfword_y,RXY,"STHY"), /*E371*/ GENx___x___x900 (load_address_y,RXY,"LAY"), /*E372*/ GENx___x___x900 (store_character_y,RXY,"STCY"), /*E373*/ GENx___x___x900 (insert_character_y,RXY,"ICY"), /*E374*/ GENx___x___x___ , /*E375*/ GENx___x___x900 (load_address_extended_y,RXY,"LAEY"), /*208*/ /*E376*/ GENx___x___x900 (load_byte,RXY,"LB"), /*E377*/ GENx___x___x900 (load_byte_long,RXY,"LGB"), /*E378*/ GENx___x___x900 (load_halfword_y,RXY,"LHY"), /*E379*/ GENx___x___x900 (compare_halfword_y,RXY,"CHY"), /*E37A*/ GENx___x___x900 (add_halfword_y,RXY,"AHY"), /*E37B*/ GENx___x___x900 (subtract_halfword_y,RXY,"SHY"), /*E37C*/ GENx___x___x900 (multiply_halfword_y,RXY,"MHY"), /*208*/ /*E37D*/ GENx___x___x___ , /*E37E*/ GENx___x___x___ , /*E37F*/ GENx___x___x___ , /*E380*/ GENx___x___x900 (and_long,RXY,"NG"), /*E381*/ GENx___x___x900 (or_long,RXY,"OG"), /*E382*/ GENx___x___x900 (exclusive_or_long,RXY,"XG"), /*E383*/ GENx___x___x___ , /*E384*/ GENx___x___x___ , /*E385*/ GENx___x___x___ , /*E386*/ GENx___x___x900 (multiply_logical_long,RXY,"MLG"), /*E387*/ GENx___x___x900 (divide_logical_long,RXY,"DLG"), /*E388*/ GENx___x___x900 (add_logical_carry_long,RXY,"ALCG"), /*E389*/ GENx___x___x900 (subtract_logical_borrow_long,RXY,"SLBG"), /*E38A*/ GENx___x___x___ , /*E38B*/ GENx___x___x___ , /*E38C*/ GENx___x___x___ , /*E38D*/ GENx___x___x___ , /*E38E*/ GENx___x___x900 (store_pair_to_quadword,RXY,"STPQ"), /*E38F*/ GENx___x___x900 (load_pair_from_quadword,RXY,"LPQ"), /*E390*/ GENx___x___x900 (load_logical_long_character,RXY,"LLGC"), /*E391*/ GENx___x___x900 (load_logical_long_halfword,RXY,"LLGH"), /*E392*/ GENx___x___x___ , /*E393*/ GENx___x___x___ , /*E394*/ GENx37Xx390x900 (load_logical_character,RXY,"LLC"), /*@Z9*/ /*E395*/ GENx37Xx390x900 (load_logical_halfword,RXY,"LLH"), /*@Z9*/ /*E396*/ GENx37Xx390x900 (multiply_logical,RXY,"ML"), /*E397*/ GENx37Xx390x900 (divide_logical,RXY,"DL"), /*E398*/ GENx37Xx390x900 (add_logical_carry,RXY,"ALC"), /*E399*/ GENx37Xx390x900 (subtract_logical_borrow,RXY,"SLB"), /*E39A*/ GENx___x___x___ , /*E39B*/ GENx___x___x___ , /*E39C*/ GENx___x___x___ , /*E39D*/ GENx___x___x___ , /*E39E*/ GENx___x___x___ , /*E39F*/ GENx___x___x___ , /*E3A0*/ GENx___x___x___ , /*E3A1*/ GENx___x___x___ , /*E3A2*/ GENx___x___x___ , /*E3A3*/ GENx___x___x___ , /*E3E3*/ GENx___x___x___ , /*E3A5*/ GENx___x___x___ , /*E3A6*/ GENx___x___x___ , /*E3A7*/ GENx___x___x___ , /*E3A8*/ GENx___x___x___ , /*E3A9*/ GENx___x___x___ , /*E3AA*/ GENx___x___x___ , /*E3AB*/ GENx___x___x___ , /*E3AC*/ GENx___x___x___ , /*E3AD*/ GENx___x___x___ , /*E3AE*/ GENx___x___x___ , /*E3AF*/ GENx___x___x___ , /*E3B0*/ GENx___x___x___ , /*E3B1*/ GENx___x___x___ , /*E3B2*/ GENx___x___x___ , /*E3B3*/ GENx___x___x___ , /*E3B4*/ GENx___x___x___ , /*E3B5*/ GENx___x___x___ , /*E3B6*/ GENx___x___x___ , /*E3B7*/ GENx___x___x___ , /*E3B8*/ GENx___x___x___ , /*E3E3*/ GENx___x___x___ , /*E3BA*/ GENx___x___x___ , /*E3BB*/ GENx___x___x___ , /*E3BC*/ GENx___x___x___ , /*E3BD*/ GENx___x___x___ , /*E3BE*/ GENx___x___x___ , /*E3BF*/ GENx___x___x___ , /*E3C0*/ GENx___x___x___ , /*E3C1*/ GENx___x___x___ , /*E3C2*/ GENx___x___x___ , /*E3C3*/ GENx___x___x___ , /*E3C4*/ GENx___x___x___ , /*E3C5*/ GENx___x___x___ , /*E3C6*/ GENx___x___x___ , /*E3C7*/ GENx___x___x___ , /*E3C8*/ GENx___x___x___ , /*E3C9*/ GENx___x___x___ , /*E3CA*/ GENx___x___x___ , /*E3CB*/ GENx___x___x___ , /*E3CC*/ GENx___x___x___ , /*E3CD*/ GENx___x___x___ , /*E3CE*/ GENx___x___x___ , /*E3CF*/ GENx___x___x___ , /*E3D0*/ GENx___x___x___ , /*E3D1*/ GENx___x___x___ , /*E3D2*/ GENx___x___x___ , /*E3D3*/ GENx___x___x___ , /*E3D4*/ GENx___x___x___ , /*E3D5*/ GENx___x___x___ , /*E3D6*/ GENx___x___x___ , /*E3D7*/ GENx___x___x___ , /*E3D8*/ GENx___x___x___ , /*E3D9*/ GENx___x___x___ , /*E3DA*/ GENx___x___x___ , /*E3DB*/ GENx___x___x___ , /*E3DC*/ GENx___x___x___ , /*E3DD*/ GENx___x___x___ , /*E3DE*/ GENx___x___x___ , /*E3DF*/ GENx___x___x___ , /*E3E0*/ GENx___x___x___ , /*E3E1*/ GENx___x___x___ , /*E3E2*/ GENx___x___x___ , /*E3E3*/ GENx___x___x___ , /*E3E4*/ GENx___x___x___ , /*E3E5*/ GENx___x___x___ , /*E3E6*/ GENx___x___x___ , /*E3E7*/ GENx___x___x___ , /*E3E8*/ GENx___x___x___ , /*E3E9*/ GENx___x___x___ , /*E3EA*/ GENx___x___x___ , /*E3EB*/ GENx___x___x___ , /*E3EC*/ GENx___x___x___ , /*E3ED*/ GENx___x___x___ , /*E3EE*/ GENx___x___x___ , /*E3EF*/ GENx___x___x___ , /*E3F0*/ GENx___x___x___ , /*E3F1*/ GENx___x___x___ , /*E3F2*/ GENx___x___x___ , /*E3F3*/ GENx___x___x___ , /*E3F4*/ GENx___x___x___ , /*E3F5*/ GENx___x___x___ , /*E3F6*/ GENx___x___x___ , /*E3F7*/ GENx___x___x___ , /*E3F8*/ GENx___x___x___ , /*E3F9*/ GENx___x___x___ , /*E3FA*/ GENx___x___x___ , /*E3FB*/ GENx___x___x___ , /*E3FC*/ GENx___x___x___ , /*E3FD*/ GENx___x___x___ , /*E3FE*/ GENx___x___x___ , /*E3FF*/ GENx___x___x___ }; // #endif /*defined(FEATURE_ESAME)*/ DLL_EXPORT zz_func opcode_e5xx[256][GEN_MAXARCH] = { /*E500*/ GENx370x390x900 (load_address_space_parameters,SSE,"LASP"), /*E501*/ GENx370x390x900 (test_protection,SSE,"TPROT"), /* The following opcode has been re-used in z/Arch */ #define s370_store_real_address s370_fix_page /*E502*/ GENx370x___x900 (store_real_address,SSE,"STRAG"), /*E503*/ GENx370x390x900 (svc_assist,SSE,"Assist"), /*E504*/ GENx370x390x900 (obtain_local_lock,SSE,"Assist"), /*E505*/ GENx370x390x900 (release_local_lock,SSE,"Assist"), /*E506*/ GENx370x390x900 (obtain_cms_lock,SSE,"Assist"), /*E507*/ GENx370x390x900 (release_cms_lock,SSE,"Assist"), /*E508*/ GENx370x___x___ (trace_svc_interruption,SSE,"Assist"), /*E509*/ GENx370x___x___ (trace_program_interruption,SSE,"Assist"), /*E50A*/ GENx370x___x___ (trace_initial_srb_dispatch,SSE,"Assist"), /*E50B*/ GENx370x___x___ (trace_io_interruption,SSE,"Assist"), /*E50C*/ GENx370x___x___ (trace_task_dispatch,SSE,"Assist"), /*E50D*/ GENx370x___x___ (trace_svc_return,SSE,"Assist"), /*E50E*/ GENx___x390x900 (move_with_source_key,SSE,"MVCSK"), /*E50F*/ GENx___x390x900 (move_with_destination_key,SSE,"MVCDK"), /*E510*/ GENx___x___x___ , /*E511*/ GENx___x___x___ , /*E512*/ GENx___x___x___ , /*E513*/ GENx___x___x___ , /*E514*/ GENx___x___x___ , /*E515*/ GENx___x___x___ , /*E516*/ GENx___x___x___ , /*E517*/ GENx___x___x___ , /*E518*/ GENx___x___x___ , /*E519*/ GENx___x___x___ , /*E51A*/ GENx___x___x___ , /*E51B*/ GENx___x___x___ , /*E51C*/ GENx___x___x___ , /*E51D*/ GENx___x___x___ , /*E51E*/ GENx___x___x___ , /*E51F*/ GENx___x___x___ , /*E520*/ GENx___x___x___ , /*E521*/ GENx___x___x___ , /*E522*/ GENx___x___x___ , /*E523*/ GENx___x___x___ , /*E524*/ GENx___x___x___ , /*E525*/ GENx___x___x___ , /*E526*/ GENx___x___x___ , /*E527*/ GENx___x___x___ , /*E528*/ GENx___x___x___ , /*E529*/ GENx___x___x___ , /*E52A*/ GENx___x___x___ , /*E52B*/ GENx___x___x___ , /*E52C*/ GENx___x___x___ , /*E52D*/ GENx___x___x___ , /*E52E*/ GENx___x___x___ , /*E52F*/ GENx___x___x___ , /*E530*/ GENx___x___x___ , /*E531*/ GENx___x___x___ , /*E532*/ GENx___x___x___ , /*E533*/ GENx___x___x___ , /*E534*/ GENx___x___x___ , /*E535*/ GENx___x___x___ , /*E536*/ GENx___x___x___ , /*E537*/ GENx___x___x___ , /*E538*/ GENx___x___x___ , /*E539*/ GENx___x___x___ , /*E53A*/ GENx___x___x___ , /*E53B*/ GENx___x___x___ , /*E53C*/ GENx___x___x___ , /*E53D*/ GENx___x___x___ , /*E53E*/ GENx___x___x___ , /*E53F*/ GENx___x___x___ , /*E540*/ GENx___x___x___ , /*E541*/ GENx___x___x___ , /*E542*/ GENx___x___x___ , /*E543*/ GENx___x___x___ , /*E544*/ GENx37Xx390x900 (move_halfword_from_halfword_immediate,SIL,"MVHHI"), /*208*/ /*E545*/ GENx___x___x___ , /*E546*/ GENx___x___x___ , /*E547*/ GENx___x___x___ , /*E548*/ GENx37Xx390x900 (move_long_from_halfword_immediate,SIL,"MVGHI"), /*208*/ /*E549*/ GENx___x___x___ , /*E54A*/ GENx___x___x___ , /*E54B*/ GENx___x___x___ , /*E54C*/ GENx37Xx390x900 (move_fullword_from_halfword_immediate,SIL,"MVHI"), /*208*/ /*E54D*/ GENx___x___x___ , /*E54E*/ GENx___x___x___ , /*E54F*/ GENx___x___x___ , /*E550*/ GENx___x___x___ , /*E551*/ GENx___x___x___ , /*E552*/ GENx___x___x___ , /*E553*/ GENx___x___x___ , /*E554*/ GENx37Xx390x900 (compare_halfword_immediate_halfword_storage,SIL,"CHHSI"), /*208*/ /*E555*/ GENx37Xx390x900 (compare_logical_immediate_halfword_storage,SIL,"CLHHSI"), /*208*/ /*E556*/ GENx___x___x___ , /*E557*/ GENx___x___x___ , /*E558*/ GENx37Xx390x900 (compare_halfword_immediate_long_storage,SIL,"CGHSI"), /*208*/ /*E559*/ GENx37Xx390x900 (compare_logical_immediate_long_storage,SIL,"CLGHSI"), /*208*/ /*E55A*/ GENx___x___x___ , /*E55B*/ GENx___x___x___ , /*E55C*/ GENx37Xx390x900 (compare_halfword_immediate_storage,SIL,"CHSI"), /*208*/ /*E55D*/ GENx37Xx390x900 (compare_logical_immediate_fullword_storage,SIL,"CLFHSI"), /*208*/ /*E55E*/ GENx___x___x___ , /*E55F*/ GENx___x___x___ , /*E560*/ GENx___x___x___ , /*E561*/ GENx___x___x___ , /*E562*/ GENx___x___x___ , /*E563*/ GENx___x___x___ , /*E564*/ GENx___x___x___ , /*E565*/ GENx___x___x___ , /*E566*/ GENx___x___x___ , /*E567*/ GENx___x___x___ , /*E568*/ GENx___x___x___ , /*E569*/ GENx___x___x___ , /*E56A*/ GENx___x___x___ , /*E56B*/ GENx___x___x___ , /*E56C*/ GENx___x___x___ , /*E56D*/ GENx___x___x___ , /*E56E*/ GENx___x___x___ , /*E56F*/ GENx___x___x___ , /*E570*/ GENx___x___x___ , /*E571*/ GENx___x___x___ , /*E572*/ GENx___x___x___ , /*E573*/ GENx___x___x___ , /*E574*/ GENx___x___x___ , /*E575*/ GENx___x___x___ , /*E576*/ GENx___x___x___ , /*E577*/ GENx___x___x___ , /*E578*/ GENx___x___x___ , /*E579*/ GENx___x___x___ , /*E57A*/ GENx___x___x___ , /*E57B*/ GENx___x___x___ , /*E57C*/ GENx___x___x___ , /*E57D*/ GENx___x___x___ , /*E57E*/ GENx___x___x___ , /*E57F*/ GENx___x___x___ , /*E580*/ GENx___x___x___ , /*E581*/ GENx___x___x___ , /*E582*/ GENx___x___x___ , /*E583*/ GENx___x___x___ , /*E584*/ GENx___x___x___ , /*E585*/ GENx___x___x___ , /*E586*/ GENx___x___x___ , /*E587*/ GENx___x___x___ , /*E588*/ GENx___x___x___ , /*E589*/ GENx___x___x___ , /*E58A*/ GENx___x___x___ , /*E58B*/ GENx___x___x___ , /*E58C*/ GENx___x___x___ , /*E58D*/ GENx___x___x___ , /*E58E*/ GENx___x___x___ , /*E58F*/ GENx___x___x___ , /*E590*/ GENx___x___x___ , /*E591*/ GENx___x___x___ , /*E592*/ GENx___x___x___ , /*E593*/ GENx___x___x___ , /*E594*/ GENx___x___x___ , /*E595*/ GENx___x___x___ , /*E596*/ GENx___x___x___ , /*E597*/ GENx___x___x___ , /*E598*/ GENx___x___x___ , /*E599*/ GENx___x___x___ , /*E59A*/ GENx___x___x___ , /*E59B*/ GENx___x___x___ , /*E59C*/ GENx___x___x___ , /*E59D*/ GENx___x___x___ , /*E59E*/ GENx___x___x___ , /*E59F*/ GENx___x___x___ , /*E5A0*/ GENx___x___x___ , /*E5A1*/ GENx___x___x___ , /*E5A2*/ GENx___x___x___ , /*E5A3*/ GENx___x___x___ , /*E5A4*/ GENx___x___x___ , /*E5A5*/ GENx___x___x___ , /*E5A6*/ GENx___x___x___ , /*E5A7*/ GENx___x___x___ , /*E5A8*/ GENx___x___x___ , /*E5A9*/ GENx___x___x___ , /*E5AA*/ GENx___x___x___ , /*E5AB*/ GENx___x___x___ , /*E5AC*/ GENx___x___x___ , /*E5AD*/ GENx___x___x___ , /*E5AE*/ GENx___x___x___ , /*E5AF*/ GENx___x___x___ , /*E5B0*/ GENx___x___x___ , /*E5B1*/ GENx___x___x___ , /*E5B2*/ GENx___x___x___ , /*E5B3*/ GENx___x___x___ , /*E5B4*/ GENx___x___x___ , /*E5B5*/ GENx___x___x___ , /*E5B6*/ GENx___x___x___ , /*E5B7*/ GENx___x___x___ , /*E5B8*/ GENx___x___x___ , /*E5B9*/ GENx___x___x___ , /*E5BA*/ GENx___x___x___ , /*E5BB*/ GENx___x___x___ , /*E5BC*/ GENx___x___x___ , /*E5BD*/ GENx___x___x___ , /*E5BE*/ GENx___x___x___ , /*E5BF*/ GENx___x___x___ , /*E5C0*/ GENx___x___x___ , /*E5C1*/ GENx___x___x___ , /*E5C2*/ GENx___x___x___ , /*E5C3*/ GENx___x___x___ , /*E5C4*/ GENx___x___x___ , /*E5C5*/ GENx___x___x___ , /*E5C6*/ GENx___x___x___ , /*E5C7*/ GENx___x___x___ , /*E5C8*/ GENx___x___x___ , /*E5C9*/ GENx___x___x___ , /*E5CA*/ GENx___x___x___ , /*E5CB*/ GENx___x___x___ , /*E5CC*/ GENx___x___x___ , /*E5CD*/ GENx___x___x___ , /*E5CE*/ GENx___x___x___ , /*E5CF*/ GENx___x___x___ , /*E5D0*/ GENx___x___x___ , /*E5D1*/ GENx___x___x___ , /*E5D2*/ GENx___x___x___ , /*E5D3*/ GENx___x___x___ , /*E5D4*/ GENx___x___x___ , /*E5D5*/ GENx___x___x___ , /*E5D6*/ GENx___x___x___ , /*E5D7*/ GENx___x___x___ , /*E5D8*/ GENx___x___x___ , /*E5D9*/ GENx___x___x___ , /*E5DA*/ GENx___x___x___ , /*E5DB*/ GENx___x___x___ , /*E5DC*/ GENx___x___x___ , /*E5DD*/ GENx___x___x___ , /*E5DE*/ GENx___x___x___ , /*E5DF*/ GENx___x___x___ , /*E5E0*/ GENx___x___x___ , /*E5E1*/ GENx___x___x___ , /*E5E2*/ GENx___x___x___ , /*E5E3*/ GENx___x___x___ , /*E5E4*/ GENx___x___x___ , /*E5E5*/ GENx___x___x___ , /*E5E6*/ GENx___x___x___ , /*E5E7*/ GENx___x___x___ , /*E5E8*/ GENx___x___x___ , /*E5E9*/ GENx___x___x___ , /*E5EA*/ GENx___x___x___ , /*E5EB*/ GENx___x___x___ , /*E5EC*/ GENx___x___x___ , /*E5ED*/ GENx___x___x___ , /*E5EE*/ GENx___x___x___ , /*E5EF*/ GENx___x___x___ , /*E5F0*/ GENx___x___x___ , /*E5F1*/ GENx___x___x___ , /*E5F2*/ GENx___x___x___ , /*E5F3*/ GENx___x___x___ , /*E5F4*/ GENx___x___x___ , /*E5F5*/ GENx___x___x___ , /*E5F6*/ GENx___x___x___ , /*E5F7*/ GENx___x___x___ , /*E5F8*/ GENx___x___x___ , /*E5F9*/ GENx___x___x___ , /*E5FA*/ GENx___x___x___ , /*E5FB*/ GENx___x___x___ , /*E5FC*/ GENx___x___x___ , /*E5FD*/ GENx___x___x___ , /*E5FE*/ GENx___x___x___ , /*E5FF*/ GENx___x___x___ }; DLL_EXPORT zz_func opcode_e6xx[256][GEN_MAXARCH] = { /*E600*/ GENx370x___x___ (ecpsvm_basic_freex,SSE,"FREE"), /*E601*/ GENx370x___x___ (ecpsvm_basic_fretx,SSE,"FRET"), /*E602*/ GENx370x___x___ (ecpsvm_lock_page,SSE,"VLKPG"), /*E603*/ GENx370x___x___ (ecpsvm_unlock_page,SSE,"VULKP"), /*E604*/ GENx370x___x___ (ecpsvm_decode_next_ccw,SSE,"DNCCW"), /*E605*/ GENx370x___x___ (ecpsvm_free_ccwstor,SSE,"FCCWS"), /*E606*/ GENx370x___x___ (ecpsvm_locate_vblock,SSE,"SCNVU"), /*E607*/ GENx370x___x___ (ecpsvm_disp1,SSE,"ECPS:DISP1"), /*E608*/ GENx370x___x___ (ecpsvm_tpage,SSE,"ECPS:TRBRG"), /*E609*/ GENx370x___x___ (ecpsvm_tpage_lock,SSE,"TRLCK"), /*E60A*/ GENx370x___x___ (ecpsvm_inval_segtab,SSE,"VIST"), /*E60B*/ GENx370x___x___ (ecpsvm_inval_ptable,SSE,"VIPT"), /*E60C*/ GENx370x___x___ (ecpsvm_decode_first_ccw,SSE,"DFCCW"), /*E60D*/ GENx370x___x___ (ecpsvm_dispatch_main,SSE,"DISP0"), /*E60E*/ GENx370x___x___ (ecpsvm_locate_rblock,SSE,"SCNRU"), /*E60F*/ GENx370x___x___ (ecpsvm_comm_ccwproc,SSE,"CCWGN"), /*E610*/ GENx370x___x___ (ecpsvm_unxlate_ccw,SSE,"UXCCW"), /*E611*/ GENx370x___x___ (ecpsvm_disp2,SSE,"DISP2"), /*E612*/ GENx370x___x___ (ecpsvm_store_level,SSE,"STEVL"), /*E613*/ GENx370x___x___ (ecpsvm_loc_chgshrpg,SSE,"LCSPG"), /*E614*/ GENx370x___x___ (ecpsvm_extended_freex,SSE,"FREEX"), /*E615*/ GENx370x___x___ (ecpsvm_extended_fretx,SSE,"FRETX"), /*E616*/ GENx370x___x___ (ecpsvm_prefmach_assist,SSE,"PRFMA"), /*E617*/ GENx___x___x___ , /*E618*/ GENx___x___x___ , /*E619*/ GENx___x___x___ , /*E61A*/ GENx___x___x___ , /*E61B*/ GENx___x___x___ , /*E61C*/ GENx___x___x___ , /*E61D*/ GENx___x___x___ , /*E61E*/ GENx___x___x___ , /*E61F*/ GENx___x___x___ , /*E620*/ GENx___x___x___ , /*E621*/ GENx___x___x___ , /*E622*/ GENx___x___x___ , /*E623*/ GENx___x___x___ , /*E624*/ GENx___x___x___ , /*E625*/ GENx___x___x___ , /*E626*/ GENx___x___x___ , /*E627*/ GENx___x___x___ , /*E628*/ GENx___x___x___ , /*E629*/ GENx___x___x___ , /*E62A*/ GENx___x___x___ , /*E62B*/ GENx___x___x___ , /*E62C*/ GENx___x___x___ , /*E62D*/ GENx___x___x___ , /*E62E*/ GENx___x___x___ , /*E62F*/ GENx___x___x___ , /*E630*/ GENx___x___x___ , /*E631*/ GENx___x___x___ , /*E632*/ GENx___x___x___ , /*E633*/ GENx___x___x___ , /*E634*/ GENx___x___x___ , /*E635*/ GENx___x___x___ , /*E636*/ GENx___x___x___ , /*E637*/ GENx___x___x___ , /*E638*/ GENx___x___x___ , /*E639*/ GENx___x___x___ , /*E63A*/ GENx___x___x___ , /*E63B*/ GENx___x___x___ , /*E63C*/ GENx___x___x___ , /*E63D*/ GENx___x___x___ , /*E63E*/ GENx___x___x___ , /*E63F*/ GENx___x___x___ , /*E640*/ GENx___x___x___ , /*E641*/ GENx___x___x___ , /*E642*/ GENx___x___x___ , /*E643*/ GENx___x___x___ , /*E644*/ GENx___x___x___ , /*E645*/ GENx___x___x___ , /*E646*/ GENx___x___x___ , /*E647*/ GENx___x___x___ , /*E648*/ GENx___x___x___ , /*E649*/ GENx___x___x___ , /*E64A*/ GENx___x___x___ , /*E64B*/ GENx___x___x___ , /*E64C*/ GENx___x___x___ , /*E64D*/ GENx___x___x___ , /*E64E*/ GENx___x___x___ , /*E64F*/ GENx___x___x___ , /*E650*/ GENx___x___x___ , /*E651*/ GENx___x___x___ , /*E652*/ GENx___x___x___ , /*E653*/ GENx___x___x___ , /*E654*/ GENx___x___x___ , /*E655*/ GENx___x___x___ , /*E656*/ GENx___x___x___ , /*E657*/ GENx___x___x___ , /*E658*/ GENx___x___x___ , /*E659*/ GENx___x___x___ , /*E65A*/ GENx___x___x___ , /*E65B*/ GENx___x___x___ , /*E65C*/ GENx___x___x___ , /*E65D*/ GENx___x___x___ , /*E65E*/ GENx___x___x___ , /*E65F*/ GENx___x___x___ , /*E660*/ GENx___x___x___ , /*E661*/ GENx___x___x___ , /*E662*/ GENx___x___x___ , /*E663*/ GENx___x___x___ , /*E664*/ GENx___x___x___ , /*E665*/ GENx___x___x___ , /*E666*/ GENx___x___x___ , /*E667*/ GENx___x___x___ , /*E668*/ GENx___x___x___ , /*E669*/ GENx___x___x___ , /*E66A*/ GENx___x___x___ , /*E66B*/ GENx___x___x___ , /*E66C*/ GENx___x___x___ , /*E66D*/ GENx___x___x___ , /*E66E*/ GENx___x___x___ , /*E66F*/ GENx___x___x___ , /*E670*/ GENx___x___x___ , /*E671*/ GENx___x___x___ , /*E672*/ GENx___x___x___ , /*E673*/ GENx___x___x___ , /*E674*/ GENx___x___x___ , /*E675*/ GENx___x___x___ , /*E676*/ GENx___x___x___ , /*E677*/ GENx___x___x___ , /*E678*/ GENx___x___x___ , /*E679*/ GENx___x___x___ , /*E67A*/ GENx___x___x___ , /*E67B*/ GENx___x___x___ , /*E67C*/ GENx___x___x___ , /*E67D*/ GENx___x___x___ , /*E67E*/ GENx___x___x___ , /*E67F*/ GENx___x___x___ , /*E680*/ GENx___x___x___ , /*E681*/ GENx___x___x___ , /*E682*/ GENx___x___x___ , /*E683*/ GENx___x___x___ , /*E684*/ GENx___x___x___ , /*E685*/ GENx___x___x___ , /*E686*/ GENx___x___x___ , /*E687*/ GENx___x___x___ , /*E688*/ GENx___x___x___ , /*E689*/ GENx___x___x___ , /*E68A*/ GENx___x___x___ , /*E68B*/ GENx___x___x___ , /*E68C*/ GENx___x___x___ , /*E68D*/ GENx___x___x___ , /*E68E*/ GENx___x___x___ , /*E68F*/ GENx___x___x___ , /*E690*/ GENx___x___x___ , /*E691*/ GENx___x___x___ , /*E692*/ GENx___x___x___ , /*E693*/ GENx___x___x___ , /*E694*/ GENx___x___x___ , /*E695*/ GENx___x___x___ , /*E696*/ GENx___x___x___ , /*E697*/ GENx___x___x___ , /*E698*/ GENx___x___x___ , /*E699*/ GENx___x___x___ , /*E69A*/ GENx___x___x___ , /*E69B*/ GENx___x___x___ , /*E69C*/ GENx___x___x___ , /*E69D*/ GENx___x___x___ , /*E69E*/ GENx___x___x___ , /*E69F*/ GENx___x___x___ , /*E6A0*/ GENx___x___x___ , /*E6A1*/ GENx___x___x___ , /*E6A2*/ GENx___x___x___ , /*E6A3*/ GENx___x___x___ , /*E6A4*/ GENx___x___x___ , /*E6A5*/ GENx___x___x___ , /*E6A6*/ GENx___x___x___ , /*E6A7*/ GENx___x___x___ , /*E6A8*/ GENx___x___x___ , /*E6A9*/ GENx___x___x___ , /*E6AA*/ GENx___x___x___ , /*E6AB*/ GENx___x___x___ , /*E6AC*/ GENx___x___x___ , /*E6AD*/ GENx___x___x___ , /*E6AE*/ GENx___x___x___ , /*E6AF*/ GENx___x___x___ , /*E6B0*/ GENx___x___x___ , /*E6B1*/ GENx___x___x___ , /*E6B2*/ GENx___x___x___ , /*E6B3*/ GENx___x___x___ , /*E6B4*/ GENx___x___x___ , /*E6B5*/ GENx___x___x___ , /*E6B6*/ GENx___x___x___ , /*E6B7*/ GENx___x___x___ , /*E6B8*/ GENx___x___x___ , /*E6B9*/ GENx___x___x___ , /*E6BA*/ GENx___x___x___ , /*E6BB*/ GENx___x___x___ , /*E6BC*/ GENx___x___x___ , /*E6BD*/ GENx___x___x___ , /*E6BE*/ GENx___x___x___ , /*E6BF*/ GENx___x___x___ , /*E6C0*/ GENx___x___x___ , /*E6C1*/ GENx___x___x___ , /*E6C2*/ GENx___x___x___ , /*E6C3*/ GENx___x___x___ , /*E6C4*/ GENx___x___x___ , /*E6C5*/ GENx___x___x___ , /*E6C6*/ GENx___x___x___ , /*E6C7*/ GENx___x___x___ , /*E6C8*/ GENx___x___x___ , /*E6C9*/ GENx___x___x___ , /*E6CA*/ GENx___x___x___ , /*E6CB*/ GENx___x___x___ , /*E6CC*/ GENx___x___x___ , /*E6CD*/ GENx___x___x___ , /*E6CE*/ GENx___x___x___ , /*E6CF*/ GENx___x___x___ , /*E6D0*/ GENx___x___x___ , /*E6D1*/ GENx___x___x___ , /*E6D2*/ GENx___x___x___ , /*E6D3*/ GENx___x___x___ , /*E6D4*/ GENx___x___x___ , /*E6D5*/ GENx___x___x___ , /*E6D6*/ GENx___x___x___ , /*E6D7*/ GENx___x___x___ , /*E6D8*/ GENx___x___x___ , /*E6D9*/ GENx___x___x___ , /*E6DA*/ GENx___x___x___ , /*E6DB*/ GENx___x___x___ , /*E6DC*/ GENx___x___x___ , /*E6DD*/ GENx___x___x___ , /*E6DE*/ GENx___x___x___ , /*E6DF*/ GENx___x___x___ , /*E6E0*/ GENx___x___x___ , /*E6E1*/ GENx___x___x___ , /*E6E2*/ GENx___x___x___ , /*E6E3*/ GENx___x___x___ , /*E6E4*/ GENx___x___x___ , /*E6E5*/ GENx___x___x___ , /*E6E6*/ GENx___x___x___ , /*E6E7*/ GENx___x___x___ , /*E6E8*/ GENx___x___x___ , /*E6E9*/ GENx___x___x___ , /*E6EA*/ GENx___x___x___ , /*E6EB*/ GENx___x___x___ , /*E6EC*/ GENx___x___x___ , /*E6ED*/ GENx___x___x___ , /*E6EE*/ GENx___x___x___ , /*E6EF*/ GENx___x___x___ , /*E6F0*/ GENx___x___x___ , /*E6F1*/ GENx___x___x___ , /*E6F2*/ GENx___x___x___ , /*E6F3*/ GENx___x___x___ , /*E6F4*/ GENx___x___x___ , /*E6F5*/ GENx___x___x___ , /*E6F6*/ GENx___x___x___ , /*E6F7*/ GENx___x___x___ , /*E6F8*/ GENx___x___x___ , /*E6F9*/ GENx___x___x___ , /*E6FA*/ GENx___x___x___ , /*E6FB*/ GENx___x___x___ , /*E6FC*/ GENx___x___x___ , /*E6FD*/ GENx___x___x___ , /*E6FE*/ GENx___x___x___ , /*E6FF*/ GENx___x___x___ }; // #if defined(FEATURE_ESAME) /* opcodes EBxxxxxx00 */ DLL_EXPORT zz_func opcode_ebxx[256][GEN_MAXARCH] = { /*EB00*/ GENx___x___x___ , /*EB01*/ GENx___x___x___ , /*EB02*/ GENx___x___x___ , /*EB03*/ GENx___x___x___ , /*EB04*/ GENx___x___x900 (load_multiple_long,RSY,"LMG"), /*EB05*/ GENx___x___x___ , /*EB06*/ GENx___x___x___ , /*EB07*/ GENx___x___x___ , /*EB08*/ GENx___x___x___ , /*EB09*/ GENx___x___x___ , /*EB0A*/ GENx___x___x900 (shift_right_single_long,RSY,"SRAG"), /*EB0B*/ GENx___x___x900 (shift_left_single_long,RSY,"SLAG"), /*EB0C*/ GENx___x___x900 (shift_right_single_logical_long,RSY,"SRLG"), /*EB0D*/ GENx___x___x900 (shift_left_single_logical_long,RSY,"SLLG"), /*EB0E*/ GENx___x___x___ , /*EB0F*/ GENx___x___x900 (trace_long,RSY,"TRACG"), /*EB10*/ GENx___x___x___ , /*EB11*/ GENx___x___x___ , /*EB12*/ GENx___x___x___ , /*EB13*/ GENx___x___x___ , /*EB14*/ GENx___x___x900 (compare_and_swap_y,RSY,"CSY"), /*EB15*/ GENx___x___x___ , /*EB16*/ GENx___x___x___ , /*EB17*/ GENx___x___x___ , /*EB18*/ GENx___x___x___ , /*EB19*/ GENx___x___x___ , /*EB1A*/ GENx___x___x___ , /*EB1B*/ GENx___x___x___ , /*EB1C*/ GENx___x___x900 (rotate_left_single_logical_long,RSY,"RLLG"), /*EB1D*/ GENx37Xx390x900 (rotate_left_single_logical,RSY,"RLL"), /*EB1E*/ GENx___x___x___ , /*EB1F*/ GENx___x___x___ , /*EB20*/ GENx___x___x900 (compare_logical_characters_under_mask_high,RSY,"CLMH"), /*EB21*/ GENx___x___x900 (compare_logical_characters_under_mask_y,RSY,"CLMY"), /*EB22*/ GENx___x___x___ , /*EB23*/ GENx___x___x___ , /*EB24*/ GENx___x___x900 (store_multiple_long,RSY,"STMG"), /*EB25*/ GENx___x___x900 (store_control_long,RSY,"STCTG"), /*EB26*/ GENx___x___x900 (store_multiple_high,RSY,"STMH"), /*EB27*/ GENx___x___x___ , /*EB28*/ GENx___x___x___ , /*EB29*/ GENx___x___x___ , /*EB2A*/ GENx___x___x___ , /*EB2B*/ GENx___x___x___ , /*EB2C*/ GENx___x___x900 (store_characters_under_mask_high,RSY,"STCMH"), /*EB2D*/ GENx___x___x900 (store_characters_under_mask_y,RSY,"STCMY"), /*EB2E*/ GENx___x___x___ , /*EB2F*/ GENx___x___x900 (load_control_long,RSY,"LCTLG"), /*EB30*/ GENx___x___x900 (compare_and_swap_long,RSY,"CSG"), /*EB31*/ GENx___x___x900 (compare_double_and_swap_y,RSY,"CDSY"), /*EB32*/ GENx___x___x___ , /*EB33*/ GENx___x___x___ , /*EB34*/ GENx___x___x___ , /*EB35*/ GENx___x___x___ , /*EB36*/ GENx___x___x___ , /*EB37*/ GENx___x___x___ , /*EB38*/ GENx___x___x___ , /*EB39*/ GENx___x___x___ , /*EB3A*/ GENx___x___x___ , /*EB3B*/ GENx___x___x___ , /*EB3C*/ GENx___x___x___ , /*EB3D*/ GENx___x___x___ , /*EB3E*/ GENx___x___x900 (compare_double_and_swap_long,RSY,"CDSG"), /*EB3F*/ GENx___x___x___ , /*EB40*/ GENx___x___x___ , /*EB41*/ GENx___x___x___ , /*EB42*/ GENx___x___x___ , /*EB43*/ GENx___x___x___ , /*EB44*/ GENx___x___x900 (branch_on_index_high_long,RSY,"BXHG"), /*EB45*/ GENx___x___x900 (branch_on_index_low_or_equal_long,RSY,"BXLEG"), /*EB46*/ GENx___x___x___ , /*EB47*/ GENx___x___x___ , /*EB48*/ GENx___x___x___ , /*EB49*/ GENx___x___x___ , /*EB4A*/ GENx___x___x___ , /*EB4B*/ GENx___x___x___ , /*EB4C*/ GENx___x___x900 (extract_cache_attribute,RSY,"ECAG"), /*208*/ /*EB4D*/ GENx___x___x___ , /*EB4E*/ GENx___x___x___ , /*EB4F*/ GENx___x___x___ , /*EB50*/ GENx___x___x___ , /*EB51*/ GENx___x___x900 (test_under_mask_y,SIY,"TMY"), /*EB52*/ GENx___x___x900 (move_immediate_y,SIY,"MVIY"), /*EB53*/ GENx___x___x___ , /*EB54*/ GENx___x___x900 (and_immediate_y,SIY,"NIY"), /*EB55*/ GENx___x___x900 (compare_logical_immediate_y,SIY,"CLIY"), /*EB56*/ GENx___x___x900 (or_immediate_y,SIY,"OIY"), /*EB57*/ GENx___x___x900 (exclusive_or_immediate_y,SIY,"XIY"), /*EB58*/ GENx___x___x___ , /*EB59*/ GENx___x___x___ , /*EB5A*/ GENx___x___x___ , /*EB5B*/ GENx___x___x___ , /*EB5C*/ GENx___x___x___ , /*EB5D*/ GENx___x___x___ , /*EB5E*/ GENx___x___x___ , /*EB5F*/ GENx___x___x___ , /*EB60*/ GENx___x___x___ , /*EB61*/ GENx___x___x___ , /*EB62*/ GENx___x___x___ , /*EB63*/ GENx___x___x___ , /*EB64*/ GENx___x___x___ , /*EB65*/ GENx___x___x___ , /*EB66*/ GENx___x___x___ , /*EB67*/ GENx___x___x___ , /*EB68*/ GENx___x___x___ , /*EB69*/ GENx___x___x___ , /*EB6A*/ GENx37Xx390x900 (add_immediate_storage,SIY,"ASI"), /*208*/ /*EB6B*/ GENx___x___x___ , /*EB6C*/ GENx___x___x___ , /*EB6D*/ GENx___x___x___ , /*EB6E*/ GENx37Xx390x900 (add_logical_with_signed_immediate,SIY,"ALSI"), /*208*/ /*EB6F*/ GENx___x___x___ , /*EB70*/ GENx___x___x___ , /*EB71*/ GENx___x___x___ , /*EB72*/ GENx___x___x___ , /*EB73*/ GENx___x___x___ , /*EB74*/ GENx___x___x___ , /*EB75*/ GENx___x___x___ , /*EB76*/ GENx___x___x___ , /*EB77*/ GENx___x___x___ , /*EB78*/ GENx___x___x___ , /*EB79*/ GENx___x___x___ , /*EB7A*/ GENx37Xx390x900 (add_immediate_long_storage,SIY,"AGSI"), /*208*/ /*EB7B*/ GENx___x___x___ , /*EB7C*/ GENx___x___x___ , /*EB7D*/ GENx___x___x___ , /*EB7E*/ GENx37Xx390x900 (add_logical_with_signed_immediate_long,SIY,"ALGSI"), /*208*/ /*EB7F*/ GENx___x___x___ , /*EB80*/ GENx___x___x900 (insert_characters_under_mask_high,RSY,"ICMH"), /*EB81*/ GENx___x___x900 (insert_characters_under_mask_y,RSY,"ICMY"), /*EB82*/ GENx___x___x___ , /*EB83*/ GENx___x___x___ , /*EB84*/ GENx___x___x___ , /*EB85*/ GENx___x___x___ , /*EB86*/ GENx___x___x___ , /*EB87*/ GENx___x___x___ , /*EB88*/ GENx___x___x___ , /*EB89*/ GENx___x___x___ , /*EB8A*/ GENx___x___x___ , /*(set_qdio_buffer_state,?,"SQBS"),*/ /*EB8B*/ GENx___x___x___ , /*EB8C*/ GENx___x___x___ , /*EB8D*/ GENx___x___x___ , /*EB8E*/ GENx37Xx390x900 (move_long_unicode,RSY,"MVCLU"), /*EB8F*/ GENx37Xx390x900 (compare_logical_long_unicode,RSY,"CLCLU"), /*EB90*/ GENx___x___x900 (store_multiple_y,RSY,"STMY"), /*EB91*/ GENx___x___x___ , /*EB92*/ GENx___x___x___ , /*EB93*/ GENx___x___x___ , /*EB94*/ GENx___x___x___ , /*EB95*/ GENx___x___x___ , /*EB96*/ GENx___x___x900 (load_multiple_high,RSY,"LMH"), /*EB97*/ GENx___x___x___ , /*EB98*/ GENx___x___x900 (load_multiple_y,RSY,"LMY"), /*EB99*/ GENx___x___x___ , /*EB9A*/ GENx___x___x900 (load_access_multiple_y,RSY,"LAMY"), /*EB9B*/ GENx___x___x900 (store_access_multiple_y,RSY,"STAMY"), /*EB9C*/ GENx___x___x___ , /*EB9D*/ GENx___x___x___ , /*EB9E*/ GENx___x___x___ , /*EB9F*/ GENx___x___x___ , /*EBA0*/ GENx___x___x___ , /*EBA1*/ GENx___x___x___ , /*EBA2*/ GENx___x___x___ , /*EBA3*/ GENx___x___x___ , /*EBEB*/ GENx___x___x___ , /*EBA5*/ GENx___x___x___ , /*EBA6*/ GENx___x___x___ , /*EBA7*/ GENx___x___x___ , /*EBA8*/ GENx___x___x___ , /*EBA9*/ GENx___x___x___ , /*EBAA*/ GENx___x___x___ , /*EBAB*/ GENx___x___x___ , /*EBAC*/ GENx___x___x___ , /*EBAD*/ GENx___x___x___ , /*EBAE*/ GENx___x___x___ , /*EBAF*/ GENx___x___x___ , /*EBB0*/ GENx___x___x___ , /*EBB1*/ GENx___x___x___ , /*EBB2*/ GENx___x___x___ , /*EBB3*/ GENx___x___x___ , /*EBB4*/ GENx___x___x___ , /*EBB5*/ GENx___x___x___ , /*EBB6*/ GENx___x___x___ , /*EBB7*/ GENx___x___x___ , /*EBB8*/ GENx___x___x___ , /*EBEB*/ GENx___x___x___ , /*EBBA*/ GENx___x___x___ , /*EBBB*/ GENx___x___x___ , /*EBBC*/ GENx___x___x___ , /*EBBD*/ GENx___x___x___ , /*EBBE*/ GENx___x___x___ , /*EBBF*/ GENx___x___x___ , /*EBC0*/ GENx37Xx390x900 (test_decimal,RSL,"TP"), /*EBC1*/ GENx___x___x___ , /*EBC2*/ GENx___x___x___ , /*EBC3*/ GENx___x___x___ , /*EBC4*/ GENx___x___x___ , /*EBC5*/ GENx___x___x___ , /*EBC6*/ GENx___x___x___ , /*EBC7*/ GENx___x___x___ , /*EBC8*/ GENx___x___x___ , /*EBC9*/ GENx___x___x___ , /*EBCA*/ GENx___x___x___ , /*EBCB*/ GENx___x___x___ , /*EBCC*/ GENx___x___x___ , /*EBCD*/ GENx___x___x___ , /*EBCE*/ GENx___x___x___ , /*EBCF*/ GENx___x___x___ , /*EBD0*/ GENx___x___x___ , /*EBD1*/ GENx___x___x___ , /*EBD2*/ GENx___x___x___ , /*EBD3*/ GENx___x___x___ , /*EBD4*/ GENx___x___x___ , /*EBD5*/ GENx___x___x___ , /*EBD6*/ GENx___x___x___ , /*EBD7*/ GENx___x___x___ , /*EBD8*/ GENx___x___x___ , /*EBD9*/ GENx___x___x___ , /*EBDA*/ GENx___x___x___ , /*EBDB*/ GENx___x___x___ , /*EBDC*/ GENx___x___x___ , /*EBDD*/ GENx___x___x___ , /*EBDE*/ GENx___x___x___ , /*EBDF*/ GENx___x___x___ , /*EBE0*/ GENx___x___x___ , /*EBE1*/ GENx___x___x___ , /*EBE2*/ GENx___x___x___ , /*EBEB*/ GENx___x___x___ , /*EBE4*/ GENx___x___x___ , /*EBE5*/ GENx___x___x___ , /*EBE6*/ GENx___x___x___ , /*EBE7*/ GENx___x___x___ , /*EBE8*/ GENx___x___x___ , /*EBE9*/ GENx___x___x___ , /*EBEA*/ GENx___x___x___ , /*EBEB*/ GENx___x___x___ , /*EBEC*/ GENx___x___x___ , /*EBED*/ GENx___x___x___ , /*EBEE*/ GENx___x___x___ , /*EBEF*/ GENx___x___x___ , /*EBF0*/ GENx___x___x___ , /*EBF1*/ GENx___x___x___ , /*EBF2*/ GENx___x___x___ , /*EBF3*/ GENx___x___x___ , /*EBF4*/ GENx___x___x___ , /*EBF5*/ GENx___x___x___ , /*EBF6*/ GENx___x___x___ , /*EBF7*/ GENx___x___x___ , /*EBF8*/ GENx___x___x___ , /*EBF9*/ GENx___x___x___ , /*EBFA*/ GENx___x___x___ , /*EBFB*/ GENx___x___x___ , /*EBFC*/ GENx___x___x___ , /*EBFD*/ GENx___x___x___ , /*EBFE*/ GENx___x___x___ , /*EBFF*/ GENx___x___x___ }; // #endif /*defined(FEATURE_ESAME)*/ // #if defined(FEATURE_ESAME) DLL_EXPORT zz_func opcode_ecxx[256][GEN_MAXARCH] = { /*EC00*/ GENx___x___x___ , /*EC01*/ GENx___x___x___ , /*EC02*/ GENx___x___x___ , /*EC03*/ GENx___x___x___ , /*EC04*/ GENx___x___x___ , /*EC05*/ GENx___x___x___ , /*EC06*/ GENx___x___x___ , /*EC07*/ GENx___x___x___ , /*EC08*/ GENx___x___x___ , /*EC09*/ GENx___x___x___ , /*EC0A*/ GENx___x___x___ , /*EC0B*/ GENx___x___x___ , /*EC0C*/ GENx___x___x___ , /*EC0D*/ GENx___x___x___ , /*EC0E*/ GENx___x___x___ , /*EC0F*/ GENx___x___x___ , /*EC10*/ GENx___x___x___ , /*EC11*/ GENx___x___x___ , /*EC12*/ GENx___x___x___ , /*EC13*/ GENx___x___x___ , /*EC14*/ GENx___x___x___ , /*EC15*/ GENx___x___x___ , /*EC16*/ GENx___x___x___ , /*EC17*/ GENx___x___x___ , /*EC18*/ GENx___x___x___ , /*EC19*/ GENx___x___x___ , /*EC1A*/ GENx___x___x___ , /*EC1B*/ GENx___x___x___ , /*EC1C*/ GENx___x___x___ , /*EC1D*/ GENx___x___x___ , /*EC1E*/ GENx___x___x___ , /*EC1F*/ GENx___x___x___ , /*EC20*/ GENx___x___x___ , /*EC21*/ GENx___x___x___ , /*EC22*/ GENx___x___x___ , /*EC23*/ GENx___x___x___ , /*EC24*/ GENx___x___x___ , /*EC25*/ GENx___x___x___ , /*EC26*/ GENx___x___x___ , /*EC27*/ GENx___x___x___ , /*EC28*/ GENx___x___x___ , /*EC29*/ GENx___x___x___ , /*EC2A*/ GENx___x___x___ , /*EC2B*/ GENx___x___x___ , /*EC2C*/ GENx___x___x___ , /*EC2D*/ GENx___x___x___ , /*EC2E*/ GENx___x___x___ , /*EC2F*/ GENx___x___x___ , /*EC30*/ GENx___x___x___ , /*EC31*/ GENx___x___x___ , /*EC32*/ GENx___x___x___ , /*EC33*/ GENx___x___x___ , /*EC34*/ GENx___x___x___ , /*EC35*/ GENx___x___x___ , /*EC36*/ GENx___x___x___ , /*EC37*/ GENx___x___x___ , /*EC38*/ GENx___x___x___ , /*EC39*/ GENx___x___x___ , /*EC3A*/ GENx___x___x___ , /*EC3B*/ GENx___x___x___ , /*EC3C*/ GENx___x___x___ , /*EC3D*/ GENx___x___x___ , /*EC3E*/ GENx___x___x___ , /*EC3F*/ GENx___x___x___ , /*EC40*/ GENx___x___x___ , /*EC41*/ GENx___x___x___ , /*EC42*/ GENx___x___x___ , /*EC43*/ GENx___x___x___ , /*EC44*/ GENx___x___x900 (branch_relative_on_index_high_long,RIE,"BRXHG"), /*EC45*/ GENx___x___x900 (branch_relative_on_index_low_or_equal_long,RIE,"BRXLG"), /*EC46*/ GENx___x___x___ , /*EC47*/ GENx___x___x___ , /*EC48*/ GENx___x___x___ , /*EC49*/ GENx___x___x___ , /*EC4A*/ GENx___x___x___ , /*EC4B*/ GENx___x___x___ , /*EC4C*/ GENx___x___x___ , /*EC4D*/ GENx___x___x___ , /*EC4E*/ GENx___x___x___ , /*EC4F*/ GENx___x___x___ , /*EC50*/ GENx___x___x___ , /*EC51*/ GENx___x___x___ , /*EC52*/ GENx___x___x___ , /*EC53*/ GENx___x___x___ , /*EC54*/ GENx___x___x900 (rotate_then_and_selected_bits_long_reg,RIE_RRIII,"RNSBG"), /*208*/ /*EC55*/ GENx___x___x900 (rotate_then_insert_selected_bits_long_reg,RIE_RRIII,"RISBG"), /*208*/ /*EC56*/ GENx___x___x900 (rotate_then_or_selected_bits_long_reg,RIE_RRIII,"ROSBG"), /*208*/ /*EC57*/ GENx___x___x900 (rotate_then_exclusive_or_selected_bits_long_reg,RIE_RRIII,"RXSBG"), /*208*/ /*EC58*/ GENx___x___x___ , /*EC59*/ GENx___x___x___ , /*EC5A*/ GENx___x___x___ , /*EC5B*/ GENx___x___x___ , /*EC5C*/ GENx___x___x___ , /*EC5D*/ GENx___x___x___ , /*EC5E*/ GENx___x___x___ , /*EC5F*/ GENx___x___x___ , /*EC60*/ GENx___x___x___ , /*EC61*/ GENx___x___x___ , /*EC62*/ GENx___x___x___ , /*EC63*/ GENx___x___x___ , /*EC64*/ GENx___x___x900 (compare_and_branch_relative_long_register,RIE_RRIM,"CGRJ"), /*208*/ /*EC65*/ GENx___x___x900 (compare_logical_and_branch_relative_long_register,RIE_RRIM,"CLGRJ"), /*208*/ /*EC66*/ GENx___x___x___ , /*EC67*/ GENx___x___x___ , /*EC68*/ GENx___x___x___ , /*EC69*/ GENx___x___x___ , /*EC6A*/ GENx___x___x___ , /*EC6B*/ GENx___x___x___ , /*EC6C*/ GENx___x___x___ , /*EC6D*/ GENx___x___x___ , /*EC6E*/ GENx___x___x___ , /*EC6F*/ GENx___x___x___ , /*EC70*/ GENx___x___x900 (compare_immediate_and_trap_long,RIE_RIM,"CGIT"), /*208*/ /*EC71*/ GENx___x___x900 (compare_logical_immediate_and_trap_long,RIE_RIM,"CLGIT"), /*208*/ /*EC72*/ GENx37Xx390x900 (compare_immediate_and_trap,RIE_RIM,"CIT"), /*208*/ /*EC73*/ GENx37Xx390x900 (compare_logical_immediate_and_trap_fullword,RIE_RIM,"CLFIT"), /*208*/ /*EC74*/ GENx___x___x___ , /*EC75*/ GENx___x___x___ , /*EC76*/ GENx37Xx390x900 (compare_and_branch_relative_register,RIE_RRIM,"CRJ"), /*208*/ /*EC77*/ GENx37Xx390x900 (compare_logical_and_branch_relative_register,RIE_RRIM,"CLRJ"), /*208*/ /*EC78*/ GENx___x___x___ , /*EC79*/ GENx___x___x___ , /*EC7A*/ GENx___x___x___ , /*EC7B*/ GENx___x___x___ , /*EC7C*/ GENx___x___x900 (compare_immediate_and_branch_relative_long,RIE_RMII,"CGIJ"), /*208*/ /*EC7D*/ GENx___x___x900 (compare_logical_immediate_and_branch_relative_long,RIE_RMII,"CLGIJ"), /*208*/ /*EC7E*/ GENx37Xx390x900 (compare_immediate_and_branch_relative,RIE_RMII,"CIJ"), /*208*/ /*EC7F*/ GENx37Xx390x900 (compare_logical_immediate_and_branch_relative,RIE_RMII,"CLIJ"), /*208*/ /*EC80*/ GENx___x___x___ , /*EC81*/ GENx___x___x___ , /*EC82*/ GENx___x___x___ , /*EC83*/ GENx___x___x___ , /*EC84*/ GENx___x___x___ , /*EC85*/ GENx___x___x___ , /*EC86*/ GENx___x___x___ , /*EC87*/ GENx___x___x___ , /*EC88*/ GENx___x___x___ , /*EC89*/ GENx___x___x___ , /*EC8A*/ GENx___x___x___ , /*EC8B*/ GENx___x___x___ , /*EC8C*/ GENx___x___x___ , /*EC8D*/ GENx___x___x___ , /*EC8E*/ GENx___x___x___ , /*EC8F*/ GENx___x___x___ , /*EC90*/ GENx___x___x___ , /*EC91*/ GENx___x___x___ , /*EC92*/ GENx___x___x___ , /*EC93*/ GENx___x___x___ , /*EC94*/ GENx___x___x___ , /*EC95*/ GENx___x___x___ , /*EC96*/ GENx___x___x___ , /*EC97*/ GENx___x___x___ , /*EC98*/ GENx___x___x___ , /*EC99*/ GENx___x___x___ , /*EC9A*/ GENx___x___x___ , /*EC9B*/ GENx___x___x___ , /*EC9C*/ GENx___x___x___ , /*EC9D*/ GENx___x___x___ , /*EC9E*/ GENx___x___x___ , /*EC9F*/ GENx___x___x___ , /*ECA0*/ GENx___x___x___ , /*ECA1*/ GENx___x___x___ , /*ECA2*/ GENx___x___x___ , /*ECA3*/ GENx___x___x___ , /*ECA4*/ GENx___x___x___ , /*ECA5*/ GENx___x___x___ , /*ECA6*/ GENx___x___x___ , /*ECA7*/ GENx___x___x___ , /*ECA8*/ GENx___x___x___ , /*ECA9*/ GENx___x___x___ , /*ECAA*/ GENx___x___x___ , /*ECAB*/ GENx___x___x___ , /*ECAC*/ GENx___x___x___ , /*ECAD*/ GENx___x___x___ , /*ECAE*/ GENx___x___x___ , /*ECAF*/ GENx___x___x___ , /*ECB0*/ GENx___x___x___ , /*ECB1*/ GENx___x___x___ , /*ECB2*/ GENx___x___x___ , /*ECB3*/ GENx___x___x___ , /*ECB4*/ GENx___x___x___ , /*ECB5*/ GENx___x___x___ , /*ECB6*/ GENx___x___x___ , /*ECB7*/ GENx___x___x___ , /*ECB8*/ GENx___x___x___ , /*ECB9*/ GENx___x___x___ , /*ECBA*/ GENx___x___x___ , /*ECBB*/ GENx___x___x___ , /*ECBC*/ GENx___x___x___ , /*ECBD*/ GENx___x___x___ , /*ECBE*/ GENx___x___x___ , /*ECBF*/ GENx___x___x___ , /*ECC0*/ GENx___x___x___ , /*ECC1*/ GENx___x___x___ , /*ECC2*/ GENx___x___x___ , /*ECC3*/ GENx___x___x___ , /*ECC4*/ GENx___x___x___ , /*ECC5*/ GENx___x___x___ , /*ECC6*/ GENx___x___x___ , /*ECC7*/ GENx___x___x___ , /*ECC8*/ GENx___x___x___ , /*ECC9*/ GENx___x___x___ , /*ECCA*/ GENx___x___x___ , /*ECCB*/ GENx___x___x___ , /*ECCC*/ GENx___x___x___ , /*ECCD*/ GENx___x___x___ , /*ECCE*/ GENx___x___x___ , /*ECCF*/ GENx___x___x___ , /*ECD0*/ GENx___x___x___ , /*ECD1*/ GENx___x___x___ , /*ECD2*/ GENx___x___x___ , /*ECD3*/ GENx___x___x___ , /*ECD4*/ GENx___x___x___ , /*ECD5*/ GENx___x___x___ , /*ECD6*/ GENx___x___x___ , /*ECD7*/ GENx___x___x___ , /*ECD8*/ GENx___x___x___ , /*ECD9*/ GENx___x___x___ , /*ECDA*/ GENx___x___x___ , /*ECDB*/ GENx___x___x___ , /*ECDC*/ GENx___x___x___ , /*ECDD*/ GENx___x___x___ , /*ECDE*/ GENx___x___x___ , /*ECDF*/ GENx___x___x___ , /*ECE0*/ GENx___x___x___ , /*ECE1*/ GENx___x___x___ , /*ECE2*/ GENx___x___x___ , /*ECE3*/ GENx___x___x___ , /*ECE4*/ GENx___x___x900 (compare_and_branch_long_register,RRS,"CGRB"), /*208*/ /*ECE5*/ GENx___x___x900 (compare_logical_and_branch_long_register,RRS,"CLGRB"), /*208*/ /*ECE6*/ GENx___x___x___ , /*ECE7*/ GENx___x___x___ , /*ECE8*/ GENx___x___x___ , /*ECE9*/ GENx___x___x___ , /*ECEA*/ GENx___x___x___ , /*ECEB*/ GENx___x___x___ , /*ECEC*/ GENx___x___x___ , /*ECED*/ GENx___x___x___ , /*ECEE*/ GENx___x___x___ , /*ECEF*/ GENx___x___x___ , /*ECF0*/ GENx___x___x___ , /*ECF1*/ GENx___x___x___ , /*ECF2*/ GENx___x___x___ , /*ECF3*/ GENx___x___x___ , /*ECF4*/ GENx___x___x___ , /*ECF5*/ GENx___x___x___ , /*ECF6*/ GENx37Xx390x900 (compare_and_branch_register,RRS,"CRB"), /*208*/ /*ECF7*/ GENx37Xx390x900 (compare_logical_and_branch_register,RRS,"CLRB"), /*208*/ /*ECF8*/ GENx___x___x___ , /*ECF9*/ GENx___x___x___ , /*ECFA*/ GENx___x___x___ , /*ECFB*/ GENx___x___x___ , /*ECFC*/ GENx___x___x900 (compare_immediate_and_branch_long,RIS,"CGIB"), /*208*/ /*ECFD*/ GENx___x___x900 (compare_logical_immediate_and_branch_long,RIS,"CLGIB"), /*208*/ /*ECFE*/ GENx37Xx390x900 (compare_immediate_and_branch,RIS,"CIB"), /*208*/ /*ECFF*/ GENx37Xx390x900 (compare_logical_immediate_and_branch,RIS,"CLIB") }; /*208*/ // #endif /*defined(FEATURE_ESAME)*/ // #if defined(FEATURE_BASIC_FP_EXTENSIONS) DLL_EXPORT zz_func opcode_edxx[256][GEN_MAXARCH] = { /*ED00*/ GENx___x___x___ , /*ED01*/ GENx___x___x___ , /*ED02*/ GENx___x___x___ , /*ED03*/ GENx___x___x___ , /*ED04*/ GENx37Xx390x900 (load_lengthened_bfp_short_to_long,RXE,"LDEB"), /*ED05*/ GENx37Xx390x900 (load_lengthened_bfp_long_to_ext,RXE,"LXDB"), /*ED06*/ GENx37Xx390x900 (load_lengthened_bfp_short_to_ext,RXE,"LXEB"), /*ED07*/ GENx37Xx390x900 (multiply_bfp_long_to_ext,RXE,"MXDB"), /*ED08*/ GENx37Xx390x900 (compare_and_signal_bfp_short,RXE,"KEB"), /*ED09*/ GENx37Xx390x900 (compare_bfp_short,RXE,"CEB"), /*ED0A*/ GENx37Xx390x900 (add_bfp_short,RXE,"AEB"), /*ED0B*/ GENx37Xx390x900 (subtract_bfp_short,RXE,"SEB"), /*ED0C*/ GENx37Xx390x900 (multiply_bfp_short_to_long,RXE,"MDEB"), /*ED0D*/ GENx37Xx390x900 (divide_bfp_short,RXE,"DEB"), /*ED0E*/ GENx37Xx390x900 (multiply_add_bfp_short,RXF,"MAEB"), /*ED0F*/ GENx37Xx390x900 (multiply_subtract_bfp_short,RXF,"MSEB"), /*ED10*/ GENx37Xx390x900 (test_data_class_bfp_short,RXE,"TCEB"), /*ED11*/ GENx37Xx390x900 (test_data_class_bfp_long,RXE,"TCDB"), /*ED12*/ GENx37Xx390x900 (test_data_class_bfp_ext,RXE,"TCXB"), /*ED13*/ GENx___x___x___ , /*ED14*/ GENx37Xx390x900 (squareroot_bfp_short,RXE,"SQEB"), /*ED15*/ GENx37Xx390x900 (squareroot_bfp_long,RXE,"SQDB"), /*ED16*/ GENx___x___x___ , /*ED17*/ GENx37Xx390x900 (multiply_bfp_short,RXE,"MEEB"), /*ED18*/ GENx37Xx390x900 (compare_and_signal_bfp_long,RXE,"KDB"), /*ED19*/ GENx37Xx390x900 (compare_bfp_long,RXE,"CDB"), /*ED1A*/ GENx37Xx390x900 (add_bfp_long,RXE,"ADB"), /*ED1B*/ GENx37Xx390x900 (subtract_bfp_long,RXE,"SDB"), /*ED1C*/ GENx37Xx390x900 (multiply_bfp_long,RXE,"MDB"), /*ED1D*/ GENx37Xx390x900 (divide_bfp_long,RXE,"DDB"), /*ED1E*/ GENx37Xx390x900 (multiply_add_bfp_long,RXF,"MADB"), /*ED1F*/ GENx37Xx390x900 (multiply_subtract_bfp_long,RXF,"MSDB"), /*ED20*/ GENx___x___x___ , /*ED21*/ GENx___x___x___ , /*ED22*/ GENx___x___x___ , /*ED23*/ GENx___x___x___ , /*ED24*/ GENx37Xx390x900 (load_lengthened_float_short_to_long,RXE,"LDE"), /*ED25*/ GENx37Xx390x900 (load_lengthened_float_long_to_ext,RXE,"LXD"), /*ED26*/ GENx37Xx390x900 (load_lengthened_float_short_to_ext,RXE,"LXE"), /*ED27*/ GENx___x___x___ , /*ED28*/ GENx___x___x___ , /*ED29*/ GENx___x___x___ , /*ED2A*/ GENx___x___x___ , /*ED2B*/ GENx___x___x___ , /*ED2C*/ GENx___x___x___ , /*ED2D*/ GENx___x___x___ , /*ED2E*/ GENx37Xx390x900 (multiply_add_float_short,RXF,"MAE"), /*ED2F*/ GENx37Xx390x900 (multiply_subtract_float_short,RXF,"MSE"), /*ED30*/ GENx___x___x___ , /*ED31*/ GENx___x___x___ , /*ED32*/ GENx___x___x___ , /*ED33*/ GENx___x___x___ , /*ED34*/ GENx37Xx390x900 (squareroot_float_short,RXE,"SQE"), /*ED35*/ GENx37Xx390x900 (squareroot_float_long,RXE,"SQD"), /*ED36*/ GENx___x___x___ , /*ED37*/ GENx37Xx390x900 (multiply_float_short,RXE,"MEE"), /*ED38*/ GENx37Xx___x900 (multiply_add_unnormal_float_long_to_ext_low,RXF,"MAYL"), /*@Z9*/ /*ED39*/ GENx37Xx___x900 (multiply_unnormal_float_long_to_ext_low,RXF,"MYL"), /*@Z9*/ /*ED3A*/ GENx37Xx___x900 (multiply_add_unnormal_float_long_to_ext,RXF,"MAY"), /*@Z9*/ /*ED3B*/ GENx37Xx___x900 (multiply_unnormal_float_long_to_ext,RXF,"MY"), /*@Z9*/ /*ED3C*/ GENx37Xx___x900 (multiply_add_unnormal_float_long_to_ext_high,RXF,"MAYH"), /*@Z9*/ /*ED3D*/ GENx37Xx___x900 (multiply_unnormal_float_long_to_ext_high,RXF,"MYH"), /*@Z9*/ /*ED3E*/ GENx37Xx390x900 (multiply_add_float_long,RXF,"MAD"), /*ED3F*/ GENx37Xx390x900 (multiply_subtract_float_long,RXF,"MSD"), /*ED40*/ GENx___x390x900 (shift_coefficient_left_dfp_long,RXF,"SLDT"), /*ED41*/ GENx___x390x900 (shift_coefficient_right_dfp_long,RXF,"SRDT"), /*ED42*/ GENx___x___x___ , /*ED43*/ GENx___x___x___ , /*ED44*/ GENx___x___x___ , /*ED45*/ GENx___x___x___ , /*ED46*/ GENx___x___x___ , /*ED47*/ GENx___x___x___ , /*ED48*/ GENx___x390x900 (shift_coefficient_left_dfp_ext,RXF,"SLXT"), /*ED49*/ GENx___x390x900 (shift_coefficient_right_dfp_ext,RXF,"SRXT"), /*ED4A*/ GENx___x___x___ , /*ED4B*/ GENx___x___x___ , /*ED4C*/ GENx___x___x___ , /*ED4D*/ GENx___x___x___ , /*ED4E*/ GENx___x___x___ , /*ED4F*/ GENx___x___x___ , /*ED50*/ GENx___x390x900 (test_data_class_dfp_short,RXE,"TDCET"), /*ED51*/ GENx___x390x900 (test_data_group_dfp_short,RXE,"TDGET"), /*ED52*/ GENx___x___x___ , /*ED53*/ GENx___x___x___ , /*ED54*/ GENx___x390x900 (test_data_class_dfp_long,RXE,"TDCDT"), /*ED55*/ GENx___x390x900 (test_data_group_dfp_long,RXE,"TDGDT"), /*ED56*/ GENx___x___x___ , /*ED57*/ GENx___x___x___ , /*ED58*/ GENx___x390x900 (test_data_class_dfp_ext,RXE,"TDCXT"), /*ED59*/ GENx___x390x900 (test_data_group_dfp_ext,RXE,"TDGXT"), /*ED5A*/ GENx___x___x___ , /*ED5B*/ GENx___x___x___ , /*ED5C*/ GENx___x___x___ , /*ED5D*/ GENx___x___x___ , /*ED5E*/ GENx___x___x___ , /*ED5F*/ GENx___x___x___ , /*ED60*/ GENx___x___x___ , /*ED61*/ GENx___x___x___ , /*ED62*/ GENx___x___x___ , /*ED63*/ GENx___x___x___ , /*ED64*/ GENx___x___x900 (load_float_short_y,RXY,"LEY"), /*ED65*/ GENx___x___x900 (load_float_long_y,RXY,"LDY"), /*ED66*/ GENx___x___x900 (store_float_short_y,RXY,"STEY"), /*ED67*/ GENx___x___x900 (store_float_long_y,RXY,"STDY"), /*ED68*/ GENx___x___x___ , /*ED69*/ GENx___x___x___ , /*ED6A*/ GENx___x___x___ , /*ED6B*/ GENx___x___x___ , /*ED6C*/ GENx___x___x___ , /*ED6D*/ GENx___x___x___ , /*ED6E*/ GENx___x___x___ , /*ED6F*/ GENx___x___x___ , /*ED70*/ GENx___x___x___ , /*ED71*/ GENx___x___x___ , /*ED72*/ GENx___x___x___ , /*ED73*/ GENx___x___x___ , /*ED74*/ GENx___x___x___ , /*ED75*/ GENx___x___x___ , /*ED76*/ GENx___x___x___ , /*ED77*/ GENx___x___x___ , /*ED78*/ GENx___x___x___ , /*ED79*/ GENx___x___x___ , /*ED7A*/ GENx___x___x___ , /*ED7B*/ GENx___x___x___ , /*ED7C*/ GENx___x___x___ , /*ED7D*/ GENx___x___x___ , /*ED7E*/ GENx___x___x___ , /*ED7F*/ GENx___x___x___ , /*ED80*/ GENx___x___x___ , /*ED81*/ GENx___x___x___ , /*ED82*/ GENx___x___x___ , /*ED83*/ GENx___x___x___ , /*ED84*/ GENx___x___x___ , /*ED85*/ GENx___x___x___ , /*ED86*/ GENx___x___x___ , /*ED87*/ GENx___x___x___ , /*ED88*/ GENx___x___x___ , /*ED89*/ GENx___x___x___ , /*ED8A*/ GENx___x___x___ , /*ED8B*/ GENx___x___x___ , /*ED8C*/ GENx___x___x___ , /*ED8D*/ GENx___x___x___ , /*ED8E*/ GENx___x___x___ , /*ED8F*/ GENx___x___x___ , /*ED90*/ GENx___x___x___ , /*ED91*/ GENx___x___x___ , /*ED92*/ GENx___x___x___ , /*ED93*/ GENx___x___x___ , /*ED94*/ GENx___x___x___ , /*ED95*/ GENx___x___x___ , /*ED96*/ GENx___x___x___ , /*ED97*/ GENx___x___x___ , /*ED98*/ GENx___x___x___ , /*ED99*/ GENx___x___x___ , /*ED9A*/ GENx___x___x___ , /*ED9B*/ GENx___x___x___ , /*ED9C*/ GENx___x___x___ , /*ED9D*/ GENx___x___x___ , /*ED9E*/ GENx___x___x___ , /*ED9F*/ GENx___x___x___ , /*EDA0*/ GENx___x___x___ , /*EDA1*/ GENx___x___x___ , /*EDA2*/ GENx___x___x___ , /*EDA3*/ GENx___x___x___ , /*EDA4*/ GENx___x___x___ , /*EDA5*/ GENx___x___x___ , /*EDA6*/ GENx___x___x___ , /*EDA7*/ GENx___x___x___ , /*EDA8*/ GENx___x___x___ , /*EDA9*/ GENx___x___x___ , /*EDAA*/ GENx___x___x___ , /*EDAB*/ GENx___x___x___ , /*EDAC*/ GENx___x___x___ , /*EDAD*/ GENx___x___x___ , /*EDAE*/ GENx___x___x___ , /*EDAF*/ GENx___x___x___ , /*EDB0*/ GENx___x___x___ , /*EDB1*/ GENx___x___x___ , /*EDB2*/ GENx___x___x___ , /*EDB3*/ GENx___x___x___ , /*EDB4*/ GENx___x___x___ , /*EDB5*/ GENx___x___x___ , /*EDB6*/ GENx___x___x___ , /*EDB7*/ GENx___x___x___ , /*EDB8*/ GENx___x___x___ , /*EDB3*/ GENx___x___x___ , /*EDBA*/ GENx___x___x___ , /*EDBB*/ GENx___x___x___ , /*EDBC*/ GENx___x___x___ , /*EDBD*/ GENx___x___x___ , /*EDBE*/ GENx___x___x___ , /*EDBF*/ GENx___x___x___ , /*EDC0*/ GENx___x___x___ , /*EDC1*/ GENx___x___x___ , /*EDC2*/ GENx___x___x___ , /*EDC3*/ GENx___x___x___ , /*EDC4*/ GENx___x___x___ , /*EDC5*/ GENx___x___x___ , /*EDC6*/ GENx___x___x___ , /*EDC7*/ GENx___x___x___ , /*EDC8*/ GENx___x___x___ , /*EDC9*/ GENx___x___x___ , /*EDCA*/ GENx___x___x___ , /*EDCB*/ GENx___x___x___ , /*EDCC*/ GENx___x___x___ , /*EDCD*/ GENx___x___x___ , /*EDCE*/ GENx___x___x___ , /*EDCF*/ GENx___x___x___ , /*EDD0*/ GENx___x___x___ , /*EDD1*/ GENx___x___x___ , /*EDD2*/ GENx___x___x___ , /*EDD3*/ GENx___x___x___ , /*EDD4*/ GENx___x___x___ , /*EDD5*/ GENx___x___x___ , /*EDD6*/ GENx___x___x___ , /*EDD7*/ GENx___x___x___ , /*EDD8*/ GENx___x___x___ , /*EDD9*/ GENx___x___x___ , /*EDDA*/ GENx___x___x___ , /*EDDB*/ GENx___x___x___ , /*EDDC*/ GENx___x___x___ , /*EDDD*/ GENx___x___x___ , /*EDDE*/ GENx___x___x___ , /*EDDF*/ GENx___x___x___ , /*EDE0*/ GENx___x___x___ , /*EDE1*/ GENx___x___x___ , /*EDE2*/ GENx___x___x___ , /*EDE3*/ GENx___x___x___ , /*EDE4*/ GENx___x___x___ , /*EDE5*/ GENx___x___x___ , /*EDE6*/ GENx___x___x___ , /*EDE7*/ GENx___x___x___ , /*EDE8*/ GENx___x___x___ , /*EDE9*/ GENx___x___x___ , /*EDEA*/ GENx___x___x___ , /*EDEB*/ GENx___x___x___ , /*EDEC*/ GENx___x___x___ , /*EDED*/ GENx___x___x___ , /*EDEE*/ GENx___x___x___ , /*EDEF*/ GENx___x___x___ , /*EDF0*/ GENx___x___x___ , /*EDF1*/ GENx___x___x___ , /*EDF2*/ GENx___x___x___ , /*EDF3*/ GENx___x___x___ , /*EDF4*/ GENx___x___x___ , /*EDF5*/ GENx___x___x___ , /*EDF6*/ GENx___x___x___ , /*EDF7*/ GENx___x___x___ , /*EDF8*/ GENx___x___x___ , /*EDF9*/ GENx___x___x___ , /*EDFA*/ GENx___x___x___ , /*EDFB*/ GENx___x___x___ , /*EDFC*/ GENx___x___x___ , /*EDFD*/ GENx___x___x___ , /*EDFE*/ GENx___x___x___ , /*EDFF*/ GENx___x___x___ }; // #endif /*defined(FEATURE_BASIC_FP_EXTENSIONS)*/ // #if defined (FEATURE_VECTOR_FACILITY) zz_func v_opcode_a4xx[256][GEN_MAXARCH] = { /*A400*/ GENx___x___x___ , /*A401*/ GENx___x___x___ , /*A402*/ GENx___x___x___ , /*A403*/ GENx___x___x___ , /*A404*/ GENx___x___x___ , /*A405*/ GENx___x___x___ , /*A406*/ GENx___x___x___ , /*A407*/ GENx___x___x___ , /*A408*/ GENx___x___x___ , /*A409*/ GENx___x___x___ , /*A40A*/ GENx___x___x___ , /*A40B*/ GENx___x___x___ , /*A40C*/ GENx___x___x___ , /*A40D*/ GENx___x___x___ , /*A40E*/ GENx___x___x___ , /*A40F*/ GENx___x___x___ , /*A410*/ GENx___x___x___ , /*A411*/ GENx___x___x___ , /*A412*/ GENx___x___x___ , /*A413*/ GENx___x___x___ , /*A414*/ GENx___x___x___ , /*A415*/ GENx___x___x___ , /*A416*/ GENx___x___x___ , /*A417*/ GENx___x___x___ , /*A418*/ GENx___x___x___ , /*A419*/ GENx___x___x___ , /*A41A*/ GENx___x___x___ , /*A41B*/ GENx___x___x___ , /*A41C*/ GENx___x___x___ , /*A41D*/ GENx___x___x___ , /*A41E*/ GENx___x___x___ , /*A41F*/ GENx___x___x___ , /*A420*/ GENx___x___x___ , /*A421*/ GENx___x___x___ , /*A422*/ GENx___x___x___ , /*A423*/ GENx___x___x___ , /*A424*/ GENx___x___x___ , /*A425*/ GENx___x___x___ , /*A426*/ GENx___x___x___ , /*A427*/ GENx___x___x___ , /*A428*/ GENx___x___x___ , /*A429*/ GENx___x___x___ , /*A42A*/ GENx___x___x___ , /*A42B*/ GENx___x___x___ , /*A42C*/ GENx___x___x___ , /*A42D*/ GENx___x___x___ , /*A42E*/ GENx___x___x___ , /*A42F*/ GENx___x___x___ , /*A430*/ GENx___x___x___ , /*A431*/ GENx___x___x___ , /*A432*/ GENx___x___x___ , /*A433*/ GENx___x___x___ , /*A434*/ GENx___x___x___ , /*A435*/ GENx___x___x___ , /*A436*/ GENx___x___x___ , /*A437*/ GENx___x___x___ , /*A438*/ GENx___x___x___ , /*A439*/ GENx___x___x___ , /*A43A*/ GENx___x___x___ , /*A43B*/ GENx___x___x___ , /*A43C*/ GENx___x___x___ , /*A43D*/ GENx___x___x___ , /*A43E*/ GENx___x___x___ , /*A43F*/ GENx___x___x___ , /*A440*/ GENx___x___x___ , /*A441*/ GENx___x___x___ , /*A442*/ GENx___x___x___ , /*A443*/ GENx___x___x___ , /*A444*/ GENx___x___x___ , /*A445*/ GENx___x___x___ , /*A446*/ GENx___x___x___ , /*A447*/ GENx___x___x___ , /*A448*/ GENx___x___x___ , /*A449*/ GENx___x___x___ , /*A44A*/ GENx___x___x___ , /*A44B*/ GENx___x___x___ , /*A44C*/ GENx___x___x___ , /*A44D*/ GENx___x___x___ , /*A44E*/ GENx___x___x___ , /*A44F*/ GENx___x___x___ , /*A450*/ GENx___x___x___ , /*A451*/ GENx___x___x___ , /*A452*/ GENx___x___x___ , /*A453*/ GENx___x___x___ , /*A454*/ GENx___x___x___ , /*A455*/ GENx___x___x___ , /*A456*/ GENx___x___x___ , /*A457*/ GENx___x___x___ , /*A458*/ GENx___x___x___ , /*A459*/ GENx___x___x___ , /*A45A*/ GENx___x___x___ , /*A45B*/ GENx___x___x___ , /*A45C*/ GENx___x___x___ , /*A45D*/ GENx___x___x___ , /*A45E*/ GENx___x___x___ , /*A45F*/ GENx___x___x___ , /*A460*/ GENx___x___x___ , /*A461*/ GENx___x___x___ , /*A462*/ GENx___x___x___ , /*A463*/ GENx___x___x___ , /*A464*/ GENx___x___x___ , /*A465*/ GENx___x___x___ , /*A466*/ GENx___x___x___ , /*A467*/ GENx___x___x___ , /*A468*/ GENx___x___x___ , /*A469*/ GENx___x___x___ , /*A46A*/ GENx___x___x___ , /*A46B*/ GENx___x___x___ , /*A46C*/ GENx___x___x___ , /*A46D*/ GENx___x___x___ , /*A46E*/ GENx___x___x___ , /*A46F*/ GENx___x___x___ , /*A470*/ GENx___x___x___ , /*A471*/ GENx___x___x___ , /*A472*/ GENx___x___x___ , /*A473*/ GENx___x___x___ , /*A474*/ GENx___x___x___ , /*A475*/ GENx___x___x___ , /*A476*/ GENx___x___x___ , /*A477*/ GENx___x___x___ , /*A478*/ GENx___x___x___ , /*A479*/ GENx___x___x___ , /*A47A*/ GENx___x___x___ , /*A47B*/ GENx___x___x___ , /*A47C*/ GENx___x___x___ , /*A47D*/ GENx___x___x___ , /*A47E*/ GENx___x___x___ , /*A47F*/ GENx___x___x___ , /*A480*/ GENx___x___x___ , /*A481*/ GENx___x___x___ , /*A482*/ GENx___x___x___ , /*A483*/ GENx___x___x___ , /*A484*/ GENx___x___x___ , /*A485*/ GENx___x___x___ , /*A486*/ GENx___x___x___ , /*A487*/ GENx___x___x___ , /*A488*/ GENx___x___x___ , /*A489*/ GENx___x___x___ , /*A48A*/ GENx___x___x___ , /*A48B*/ GENx___x___x___ , /*A48C*/ GENx___x___x___ , /*A48D*/ GENx___x___x___ , /*A48E*/ GENx___x___x___ , /*A48F*/ GENx___x___x___ , /*A490*/ GENx___x___x___ , /*A491*/ GENx___x___x___ , /*A492*/ GENx___x___x___ , /*A493*/ GENx___x___x___ , /*A494*/ GENx___x___x___ , /*A495*/ GENx___x___x___ , /*A496*/ GENx___x___x___ , /*A497*/ GENx___x___x___ , /*A498*/ GENx___x___x___ , /*A499*/ GENx___x___x___ , /*A49A*/ GENx___x___x___ , /*A49B*/ GENx___x___x___ , /*A49C*/ GENx___x___x___ , /*A49D*/ GENx___x___x___ , /*A49E*/ GENx___x___x___ , /*A49F*/ GENx___x___x___ , /*A4A0*/ GENx___x___x___ , /*A4A1*/ GENx___x___x___ , /*A4A2*/ GENx___x___x___ , /*A4A3*/ GENx___x___x___ , /*A4A4*/ GENx___x___x___ , /*A4A5*/ GENx___x___x___ , /*A4A6*/ GENx___x___x___ , /*A4A7*/ GENx___x___x___ , /*A4A8*/ GENx___x___x___ , /*A4A9*/ GENx___x___x___ , /*A4AA*/ GENx___x___x___ , /*A4AB*/ GENx___x___x___ , /*A4AC*/ GENx___x___x___ , /*A4AD*/ GENx___x___x___ , /*A4AE*/ GENx___x___x___ , /*A4AF*/ GENx___x___x___ , /*A4B0*/ GENx___x___x___ , /*A4B1*/ GENx___x___x___ , /*A4B2*/ GENx___x___x___ , /*A4B3*/ GENx___x___x___ , /*A4B4*/ GENx___x___x___ , /*A4B5*/ GENx___x___x___ , /*A4B6*/ GENx___x___x___ , /*A4B7*/ GENx___x___x___ , /*A4B8*/ GENx___x___x___ , /*A4B9*/ GENx___x___x___ , /*A4BA*/ GENx___x___x___ , /*A4BB*/ GENx___x___x___ , /*A4BC*/ GENx___x___x___ , /*A4BD*/ GENx___x___x___ , /*A4BE*/ GENx___x___x___ , /*A4BF*/ GENx___x___x___ , /*A4C0*/ GENx___x___x___ , /*A4C1*/ GENx___x___x___ , /*A4C2*/ GENx___x___x___ , /*A4C3*/ GENx___x___x___ , /*A4C4*/ GENx___x___x___ , /*A4C5*/ GENx___x___x___ , /*A4C6*/ GENx___x___x___ , /*A4C7*/ GENx___x___x___ , /*A4C8*/ GENx___x___x___ , /*A4C9*/ GENx___x___x___ , /*A4CA*/ GENx___x___x___ , /*A4CB*/ GENx___x___x___ , /*A4CC*/ GENx___x___x___ , /*A4CD*/ GENx___x___x___ , /*A4CE*/ GENx___x___x___ , /*A4CF*/ GENx___x___x___ , /*A4D0*/ GENx___x___x___ , /*A4D1*/ GENx___x___x___ , /*A4D2*/ GENx___x___x___ , /*A4D3*/ GENx___x___x___ , /*A4D4*/ GENx___x___x___ , /*A4D5*/ GENx___x___x___ , /*A4D6*/ GENx___x___x___ , /*A4D7*/ GENx___x___x___ , /*A4D8*/ GENx___x___x___ , /*A4D9*/ GENx___x___x___ , /*A4DA*/ GENx___x___x___ , /*A4DB*/ GENx___x___x___ , /*A4DC*/ GENx___x___x___ , /*A4DD*/ GENx___x___x___ , /*A4DE*/ GENx___x___x___ , /*A4DF*/ GENx___x___x___ , /*A4E0*/ GENx___x___x___ , /*A4E1*/ GENx___x___x___ , /*A4E2*/ GENx___x___x___ , /*A4E3*/ GENx___x___x___ , /*A4E4*/ GENx___x___x___ , /*A4E5*/ GENx___x___x___ , /*A4E6*/ GENx___x___x___ , /*A4E7*/ GENx___x___x___ , /*A4E8*/ GENx___x___x___ , /*A4E9*/ GENx___x___x___ , /*A4EA*/ GENx___x___x___ , /*A4EB*/ GENx___x___x___ , /*A4EC*/ GENx___x___x___ , /*A4ED*/ GENx___x___x___ , /*A4EE*/ GENx___x___x___ , /*A4EF*/ GENx___x___x___ , /*A4F0*/ GENx___x___x___ , /*A4F1*/ GENx___x___x___ , /*A4F2*/ GENx___x___x___ , /*A4F3*/ GENx___x___x___ , /*A4F4*/ GENx___x___x___ , /*A4F5*/ GENx___x___x___ , /*A4F6*/ GENx___x___x___ , /*A4F7*/ GENx___x___x___ , /*A4F8*/ GENx___x___x___ , /*A4F9*/ GENx___x___x___ , /*A4FA*/ GENx___x___x___ , /*A4FB*/ GENx___x___x___ , /*A4FC*/ GENx___x___x___ , /*A4FD*/ GENx___x___x___ , /*A4FE*/ GENx___x___x___ , /*A4FF*/ GENx___x___x___ }; // #endif /*defined (FEATURE_VECTOR_FACILITY)*/ // #if defined (FEATURE_VECTOR_FACILITY) zz_func v_opcode_a5xx[256][GEN_MAXARCH] = { /*A500*/ GENx___x___x___ , /*A501*/ GENx___x___x___ , /*A502*/ GENx___x___x___ , /*A503*/ GENx___x___x___ , /*A504*/ GENx___x___x___ , /*A505*/ GENx___x___x___ , /*A506*/ GENx___x___x___ , /*A507*/ GENx___x___x___ , /*A508*/ GENx___x___x___ , /*A509*/ GENx___x___x___ , /*A50A*/ GENx___x___x___ , /*A50B*/ GENx___x___x___ , /*A50C*/ GENx___x___x___ , /*A50D*/ GENx___x___x___ , /*A50E*/ GENx___x___x___ , /*A50F*/ GENx___x___x___ , /*A510*/ GENx___x___x___ , /*A511*/ GENx___x___x___ , /*A512*/ GENx___x___x___ , /*A513*/ GENx___x___x___ , /*A514*/ GENx___x___x___ , /*A515*/ GENx___x___x___ , /*A516*/ GENx___x___x___ , /*A517*/ GENx___x___x___ , /*A518*/ GENx___x___x___ , /*A519*/ GENx___x___x___ , /*A51A*/ GENx___x___x___ , /*A51B*/ GENx___x___x___ , /*A51C*/ GENx___x___x___ , /*A51D*/ GENx___x___x___ , /*A51E*/ GENx___x___x___ , /*A51F*/ GENx___x___x___ , /*A520*/ GENx___x___x___ , /*A521*/ GENx___x___x___ , /*A522*/ GENx___x___x___ , /*A523*/ GENx___x___x___ , /*A524*/ GENx___x___x___ , /*A525*/ GENx___x___x___ , /*A526*/ GENx___x___x___ , /*A527*/ GENx___x___x___ , /*A528*/ GENx___x___x___ , /*A529*/ GENx___x___x___ , /*A52A*/ GENx___x___x___ , /*A52B*/ GENx___x___x___ , /*A52C*/ GENx___x___x___ , /*A52D*/ GENx___x___x___ , /*A52E*/ GENx___x___x___ , /*A52F*/ GENx___x___x___ , /*A530*/ GENx___x___x___ , /*A531*/ GENx___x___x___ , /*A532*/ GENx___x___x___ , /*A533*/ GENx___x___x___ , /*A534*/ GENx___x___x___ , /*A535*/ GENx___x___x___ , /*A536*/ GENx___x___x___ , /*A537*/ GENx___x___x___ , /*A538*/ GENx___x___x___ , /*A539*/ GENx___x___x___ , /*A53A*/ GENx___x___x___ , /*A53B*/ GENx___x___x___ , /*A53C*/ GENx___x___x___ , /*A53D*/ GENx___x___x___ , /*A53E*/ GENx___x___x___ , /*A53F*/ GENx___x___x___ , /*A540*/ GENx___x___x___ , /*A541*/ GENx___x___x___ , /*A542*/ GENx___x___x___ , /*A543*/ GENx___x___x___ , /*A544*/ GENx___x___x___ , /*A545*/ GENx___x___x___ , /*A546*/ GENx___x___x___ , /*A547*/ GENx___x___x___ , /*A548*/ GENx___x___x___ , /*A549*/ GENx___x___x___ , /*A54A*/ GENx___x___x___ , /*A54B*/ GENx___x___x___ , /*A54C*/ GENx___x___x___ , /*A54D*/ GENx___x___x___ , /*A54E*/ GENx___x___x___ , /*A54F*/ GENx___x___x___ , /*A550*/ GENx___x___x___ , /*A551*/ GENx___x___x___ , /*A552*/ GENx___x___x___ , /*A553*/ GENx___x___x___ , /*A554*/ GENx___x___x___ , /*A555*/ GENx___x___x___ , /*A556*/ GENx___x___x___ , /*A557*/ GENx___x___x___ , /*A558*/ GENx___x___x___ , /*A559*/ GENx___x___x___ , /*A55A*/ GENx___x___x___ , /*A55B*/ GENx___x___x___ , /*A55C*/ GENx___x___x___ , /*A55D*/ GENx___x___x___ , /*A55E*/ GENx___x___x___ , /*A55F*/ GENx___x___x___ , /*A560*/ GENx___x___x___ , /*A561*/ GENx___x___x___ , /*A562*/ GENx___x___x___ , /*A563*/ GENx___x___x___ , /*A564*/ GENx___x___x___ , /*A565*/ GENx___x___x___ , /*A566*/ GENx___x___x___ , /*A567*/ GENx___x___x___ , /*A568*/ GENx___x___x___ , /*A569*/ GENx___x___x___ , /*A56A*/ GENx___x___x___ , /*A56B*/ GENx___x___x___ , /*A56C*/ GENx___x___x___ , /*A56D*/ GENx___x___x___ , /*A56E*/ GENx___x___x___ , /*A56F*/ GENx___x___x___ , /*A570*/ GENx___x___x___ , /*A571*/ GENx___x___x___ , /*A572*/ GENx___x___x___ , /*A573*/ GENx___x___x___ , /*A574*/ GENx___x___x___ , /*A575*/ GENx___x___x___ , /*A576*/ GENx___x___x___ , /*A577*/ GENx___x___x___ , /*A578*/ GENx___x___x___ , /*A579*/ GENx___x___x___ , /*A57A*/ GENx___x___x___ , /*A57B*/ GENx___x___x___ , /*A57C*/ GENx___x___x___ , /*A57D*/ GENx___x___x___ , /*A57E*/ GENx___x___x___ , /*A57F*/ GENx___x___x___ , /*A580*/ GENx___x___x___ , /*A581*/ GENx___x___x___ , /*A582*/ GENx___x___x___ , /*A583*/ GENx___x___x___ , /*A584*/ GENx___x___x___ , /*A585*/ GENx___x___x___ , /*A586*/ GENx___x___x___ , /*A587*/ GENx___x___x___ , /*A588*/ GENx___x___x___ , /*A589*/ GENx___x___x___ , /*A58A*/ GENx___x___x___ , /*A58B*/ GENx___x___x___ , /*A58C*/ GENx___x___x___ , /*A58D*/ GENx___x___x___ , /*A58E*/ GENx___x___x___ , /*A58F*/ GENx___x___x___ , /*A590*/ GENx___x___x___ , /*A591*/ GENx___x___x___ , /*A592*/ GENx___x___x___ , /*A593*/ GENx___x___x___ , /*A594*/ GENx___x___x___ , /*A595*/ GENx___x___x___ , /*A596*/ GENx___x___x___ , /*A597*/ GENx___x___x___ , /*A598*/ GENx___x___x___ , /*A599*/ GENx___x___x___ , /*A59A*/ GENx___x___x___ , /*A59B*/ GENx___x___x___ , /*A59C*/ GENx___x___x___ , /*A59D*/ GENx___x___x___ , /*A59E*/ GENx___x___x___ , /*A59F*/ GENx___x___x___ , /*A5A0*/ GENx___x___x___ , /*A5A1*/ GENx___x___x___ , /*A5A2*/ GENx___x___x___ , /*A5A3*/ GENx___x___x___ , /*A5A4*/ GENx___x___x___ , /*A5A5*/ GENx___x___x___ , /*A5A6*/ GENx___x___x___ , /*A5A7*/ GENx___x___x___ , /*A5A8*/ GENx___x___x___ , /*A5A9*/ GENx___x___x___ , /*A5AA*/ GENx___x___x___ , /*A5AB*/ GENx___x___x___ , /*A5AC*/ GENx___x___x___ , /*A5AD*/ GENx___x___x___ , /*A5AE*/ GENx___x___x___ , /*A5AF*/ GENx___x___x___ , /*A5B0*/ GENx___x___x___ , /*A5B1*/ GENx___x___x___ , /*A5B2*/ GENx___x___x___ , /*A5B3*/ GENx___x___x___ , /*A5B4*/ GENx___x___x___ , /*A5B5*/ GENx___x___x___ , /*A5B6*/ GENx___x___x___ , /*A5B7*/ GENx___x___x___ , /*A5B8*/ GENx___x___x___ , /*A5B9*/ GENx___x___x___ , /*A5BA*/ GENx___x___x___ , /*A5BB*/ GENx___x___x___ , /*A5BC*/ GENx___x___x___ , /*A5BD*/ GENx___x___x___ , /*A5BE*/ GENx___x___x___ , /*A5BF*/ GENx___x___x___ , /*A5C0*/ GENx___x___x___ , /*A5C1*/ GENx___x___x___ , /*A5C2*/ GENx___x___x___ , /*A5C3*/ GENx___x___x___ , /*A5C4*/ GENx___x___x___ , /*A5C5*/ GENx___x___x___ , /*A5C6*/ GENx___x___x___ , /*A5C7*/ GENx___x___x___ , /*A5C8*/ GENx___x___x___ , /*A5C9*/ GENx___x___x___ , /*A5CA*/ GENx___x___x___ , /*A5CB*/ GENx___x___x___ , /*A5CC*/ GENx___x___x___ , /*A5CD*/ GENx___x___x___ , /*A5CE*/ GENx___x___x___ , /*A5CF*/ GENx___x___x___ , /*A5D0*/ GENx___x___x___ , /*A5D1*/ GENx___x___x___ , /*A5D2*/ GENx___x___x___ , /*A5D3*/ GENx___x___x___ , /*A5D4*/ GENx___x___x___ , /*A5D5*/ GENx___x___x___ , /*A5D6*/ GENx___x___x___ , /*A5D7*/ GENx___x___x___ , /*A5D8*/ GENx___x___x___ , /*A5D9*/ GENx___x___x___ , /*A5DA*/ GENx___x___x___ , /*A5DB*/ GENx___x___x___ , /*A5DC*/ GENx___x___x___ , /*A5DD*/ GENx___x___x___ , /*A5DE*/ GENx___x___x___ , /*A5DF*/ GENx___x___x___ , /*A5E0*/ GENx___x___x___ , /*A5E1*/ GENx___x___x___ , /*A5E2*/ GENx___x___x___ , /*A5E3*/ GENx___x___x___ , /*A5E4*/ GENx___x___x___ , /*A5E5*/ GENx___x___x___ , /*A5E6*/ GENx___x___x___ , /*A5E7*/ GENx___x___x___ , /*A5E8*/ GENx___x___x___ , /*A5E9*/ GENx___x___x___ , /*A5EA*/ GENx___x___x___ , /*A5EB*/ GENx___x___x___ , /*A5EC*/ GENx___x___x___ , /*A5ED*/ GENx___x___x___ , /*A5EE*/ GENx___x___x___ , /*A5EF*/ GENx___x___x___ , /*A5F0*/ GENx___x___x___ , /*A5F1*/ GENx___x___x___ , /*A5F2*/ GENx___x___x___ , /*A5F3*/ GENx___x___x___ , /*A5F4*/ GENx___x___x___ , /*A5F5*/ GENx___x___x___ , /*A5F6*/ GENx___x___x___ , /*A5F7*/ GENx___x___x___ , /*A5F8*/ GENx___x___x___ , /*A5F9*/ GENx___x___x___ , /*A5FA*/ GENx___x___x___ , /*A5FB*/ GENx___x___x___ , /*A5FC*/ GENx___x___x___ , /*A5FD*/ GENx___x___x___ , /*A5FE*/ GENx___x___x___ , /*A5FF*/ GENx___x___x___ }; // #endif /*defined (FEATURE_VECTOR_FACILITY)*/ // #if defined (FEATURE_VECTOR_FACILITY) zz_func v_opcode_a6xx[256][GEN_MAXARCH] = { /*A600*/ GENx___x___x___ , /*A601*/ GENx___x___x___ , /*A602*/ GENx___x___x___ , /*A603*/ GENx___x___x___ , /*A604*/ GENx___x___x___ , /*A605*/ GENx___x___x___ , /*A606*/ GENx___x___x___ , /*A607*/ GENx___x___x___ , /*A608*/ GENx___x___x___ , /*A609*/ GENx___x___x___ , /*A60A*/ GENx___x___x___ , /*A60B*/ GENx___x___x___ , /*A60C*/ GENx___x___x___ , /*A60D*/ GENx___x___x___ , /*A60E*/ GENx___x___x___ , /*A60F*/ GENx___x___x___ , /*A610*/ GENx___x___x___ , /*A611*/ GENx___x___x___ , /*A612*/ GENx___x___x___ , /*A613*/ GENx___x___x___ , /*A614*/ GENx___x___x___ , /*A615*/ GENx___x___x___ , /*A616*/ GENx___x___x___ , /*A617*/ GENx___x___x___ , /*A618*/ GENx___x___x___ , /*A619*/ GENx___x___x___ , /*A61A*/ GENx___x___x___ , /*A61B*/ GENx___x___x___ , /*A61C*/ GENx___x___x___ , /*A61D*/ GENx___x___x___ , /*A61E*/ GENx___x___x___ , /*A61F*/ GENx___x___x___ , /*A620*/ GENx___x___x___ , /*A621*/ GENx___x___x___ , /*A622*/ GENx___x___x___ , /*A623*/ GENx___x___x___ , /*A624*/ GENx___x___x___ , /*A625*/ GENx___x___x___ , /*A626*/ GENx___x___x___ , /*A627*/ GENx___x___x___ , /*A628*/ GENx___x___x___ , /*A629*/ GENx___x___x___ , /*A62A*/ GENx___x___x___ , /*A62B*/ GENx___x___x___ , /*A62C*/ GENx___x___x___ , /*A62D*/ GENx___x___x___ , /*A62E*/ GENx___x___x___ , /*A62F*/ GENx___x___x___ , /*A630*/ GENx___x___x___ , /*A631*/ GENx___x___x___ , /*A632*/ GENx___x___x___ , /*A633*/ GENx___x___x___ , /*A634*/ GENx___x___x___ , /*A635*/ GENx___x___x___ , /*A636*/ GENx___x___x___ , /*A637*/ GENx___x___x___ , /*A638*/ GENx___x___x___ , /*A639*/ GENx___x___x___ , /*A63A*/ GENx___x___x___ , /*A63B*/ GENx___x___x___ , /*A63C*/ GENx___x___x___ , /*A63D*/ GENx___x___x___ , /*A63E*/ GENx___x___x___ , /*A63F*/ GENx___x___x___ , /*A640*/ GENx370x390x___ (v_test_vmr,RRE,"VTVM"), /*A641*/ GENx370x390x___ (v_complement_vmr,RRE,"VCVM"), /*A642*/ GENx370x390x___ (v_count_left_zeros_in_vmr,RRE,"VCZVM"), /*A643*/ GENx370x390x___ (v_count_ones_in_vmr,RRE,"VCOVM"), /*A644*/ GENx370x390x___ (v_extract_vct,RRE,"VXVC"), /*A645*/ GENx___x___x___ , /*A646*/ GENx370x390x___ (v_extract_vector_modes,RRE,"VXVMM"), /*A647*/ GENx___x___x___ , /*A648*/ GENx370x390x___ (v_restore_vr,RRE,"VRRS"), /*A649*/ GENx370x390x___ (v_save_changed_vr,RRE,"VRSVC"), /*A64A*/ GENx370x390x___ (v_save_vr,RRE,"VRSV"), /*A64B*/ GENx___x___x___ , /*A64C*/ GENx___x___x___ , /*A64D*/ GENx___x___x___ , /*A64E*/ GENx___x___x___ , /*A64F*/ GENx___x___x___ , /*A650*/ GENx___x___x___ , /*A651*/ GENx___x___x___ , /*A652*/ GENx___x___x___ , /*A653*/ GENx___x___x___ , /*A654*/ GENx___x___x___ , /*A655*/ GENx___x___x___ , /*A656*/ GENx___x___x___ , /*A657*/ GENx___x___x___ , /*A658*/ GENx___x___x___ , /*A659*/ GENx___x___x___ , /*A65A*/ GENx___x___x___ , /*A65B*/ GENx___x___x___ , /*A65C*/ GENx___x___x___ , /*A65D*/ GENx___x___x___ , /*A65E*/ GENx___x___x___ , /*A65F*/ GENx___x___x___ , /*A660*/ GENx___x___x___ , /*A661*/ GENx___x___x___ , /*A662*/ GENx___x___x___ , /*A663*/ GENx___x___x___ , /*A664*/ GENx___x___x___ , /*A665*/ GENx___x___x___ , /*A666*/ GENx___x___x___ , /*A667*/ GENx___x___x___ , /*A668*/ GENx___x___x___ , /*A669*/ GENx___x___x___ , /*A66A*/ GENx___x___x___ , /*A66B*/ GENx___x___x___ , /*A66C*/ GENx___x___x___ , /*A66D*/ GENx___x___x___ , /*A66E*/ GENx___x___x___ , /*A66F*/ GENx___x___x___ , /*A670*/ GENx___x___x___ , /*A671*/ GENx___x___x___ , /*A672*/ GENx___x___x___ , /*A673*/ GENx___x___x___ , /*A674*/ GENx___x___x___ , /*A675*/ GENx___x___x___ , /*A676*/ GENx___x___x___ , /*A677*/ GENx___x___x___ , /*A678*/ GENx___x___x___ , /*A679*/ GENx___x___x___ , /*A67A*/ GENx___x___x___ , /*A67B*/ GENx___x___x___ , /*A67C*/ GENx___x___x___ , /*A67D*/ GENx___x___x___ , /*A67E*/ GENx___x___x___ , /*A67F*/ GENx___x___x___ , /*A680*/ GENx370x390x___ (v_load_vmr,VS,"VLVM"), /*A681*/ GENx370x390x___ (v_load_vmr_complement,VS,"VLCVM"), /*A682*/ GENx370x390x___ (v_store_vmr,VS,"VSTVM"), /*A683*/ GENx___x___x___ , /*A684*/ GENx370x390x___ (v_and_to_vmr,VS,"VNVM"), /*A685*/ GENx370x390x___ (v_or_to_vmr,VS,"VOVM"), /*A686*/ GENx370x390x___ (v_exclusive_or_to_vmr,VS,"VXVM"), /*A687*/ GENx___x___x___ , /*A688*/ GENx___x___x___ , /*A689*/ GENx___x___x___ , /*A68A*/ GENx___x___x___ , /*A68B*/ GENx___x___x___ , /*A68C*/ GENx___x___x___ , /*A68D*/ GENx___x___x___ , /*A68E*/ GENx___x___x___ , /*A68F*/ GENx___x___x___ , /*A690*/ GENx___x___x___ , /*A691*/ GENx___x___x___ , /*A692*/ GENx___x___x___ , /*A693*/ GENx___x___x___ , /*A694*/ GENx___x___x___ , /*A695*/ GENx___x___x___ , /*A696*/ GENx___x___x___ , /*A697*/ GENx___x___x___ , /*A698*/ GENx___x___x___ , /*A699*/ GENx___x___x___ , /*A69A*/ GENx___x___x___ , /*A69B*/ GENx___x___x___ , /*A69C*/ GENx___x___x___ , /*A69D*/ GENx___x___x___ , /*A69E*/ GENx___x___x___ , /*A69F*/ GENx___x___x___ , /*A6A0*/ GENx___x___x___ , /*A6A1*/ GENx___x___x___ , /*A6A2*/ GENx___x___x___ , /*A6A3*/ GENx___x___x___ , /*A6A4*/ GENx___x___x___ , /*A6A5*/ GENx___x___x___ , /*A6A6*/ GENx___x___x___ , /*A6A7*/ GENx___x___x___ , /*A6A8*/ GENx___x___x___ , /*A6A9*/ GENx___x___x___ , /*A6AA*/ GENx___x___x___ , /*A6AB*/ GENx___x___x___ , /*A6AC*/ GENx___x___x___ , /*A6AD*/ GENx___x___x___ , /*A6AE*/ GENx___x___x___ , /*A6AF*/ GENx___x___x___ , /*A6B0*/ GENx___x___x___ , /*A6B1*/ GENx___x___x___ , /*A6B2*/ GENx___x___x___ , /*A6B3*/ GENx___x___x___ , /*A6B4*/ GENx___x___x___ , /*A6B5*/ GENx___x___x___ , /*A6B6*/ GENx___x___x___ , /*A6B7*/ GENx___x___x___ , /*A6B8*/ GENx___x___x___ , /*A6B9*/ GENx___x___x___ , /*A6BA*/ GENx___x___x___ , /*A6BB*/ GENx___x___x___ , /*A6BC*/ GENx___x___x___ , /*A6BD*/ GENx___x___x___ , /*A6BE*/ GENx___x___x___ , /*A6BF*/ GENx___x___x___ , /*A6C0*/ GENx370x390x___ (v_save_vsr,S,"VSRSV"), /*A6C1*/ GENx370x390x___ (v_save_vmr,S,"VMRSV"), /*A6C2*/ GENx370x390x___ (v_restore_vsr,S,"VSRRS"), /*A6C3*/ GENx370x390x___ (v_restore_vmr,S,"VMRRS"), /*A6C4*/ GENx370x390x___ (v_load_vct_from_address,S,"VLVCA"), /*A6C5*/ GENx370x390x___ (v_clear_vr,S,"VRCL"), /*A6C6*/ GENx370x390x___ (v_set_vector_mask_mode,S,"VSVMM"), /*A6C7*/ GENx370x390x___ (v_load_vix_from_address,S,"VLVXA"), /*A6C8*/ GENx370x390x___ (v_store_vector_parameters,S,"VSTVP"), /*A6C9*/ GENx___x___x___ , /*A6CA*/ GENx370x390x___ (v_save_vac,S,"VACSV"), /*A6CB*/ GENx370x390x___ (v_restore_vac,S,"VACRS"), /*A6CC*/ GENx___x___x___ , /*A6CD*/ GENx___x___x___ , /*A6CE*/ GENx___x___x___ , /*A6CF*/ GENx___x___x___ , /*A6D0*/ GENx___x___x___ , /*A6D1*/ GENx___x___x___ , /*A6D2*/ GENx___x___x___ , /*A6D3*/ GENx___x___x___ , /*A6D4*/ GENx___x___x___ , /*A6D5*/ GENx___x___x___ , /*A6D6*/ GENx___x___x___ , /*A6D7*/ GENx___x___x___ , /*A6D8*/ GENx___x___x___ , /*A6D9*/ GENx___x___x___ , /*A6DA*/ GENx___x___x___ , /*A6DB*/ GENx___x___x___ , /*A6DC*/ GENx___x___x___ , /*A6DD*/ GENx___x___x___ , /*A6DE*/ GENx___x___x___ , /*A6DF*/ GENx___x___x___ , /*A6E0*/ GENx___x___x___ , /*A6E1*/ GENx___x___x___ , /*A6E2*/ GENx___x___x___ , /*A6E3*/ GENx___x___x___ , /*A6E4*/ GENx___x___x___ , /*A6E5*/ GENx___x___x___ , /*A6E6*/ GENx___x___x___ , /*A6E7*/ GENx___x___x___ , /*A6E8*/ GENx___x___x___ , /*A6E9*/ GENx___x___x___ , /*A6EA*/ GENx___x___x___ , /*A6EB*/ GENx___x___x___ , /*A6EC*/ GENx___x___x___ , /*A6ED*/ GENx___x___x___ , /*A6EE*/ GENx___x___x___ , /*A6EF*/ GENx___x___x___ , /*A6F0*/ GENx___x___x___ , /*A6F1*/ GENx___x___x___ , /*A6F2*/ GENx___x___x___ , /*A6F3*/ GENx___x___x___ , /*A6F4*/ GENx___x___x___ , /*A6F5*/ GENx___x___x___ , /*A6F6*/ GENx___x___x___ , /*A6F7*/ GENx___x___x___ , /*A6F8*/ GENx___x___x___ , /*A6F9*/ GENx___x___x___ , /*A6FA*/ GENx___x___x___ , /*A6FB*/ GENx___x___x___ , /*A6FC*/ GENx___x___x___ , /*A6FD*/ GENx___x___x___ , /*A6FE*/ GENx___x___x___ , /*A6FF*/ GENx___x___x___ }; // #endif /*defined (FEATURE_VECTOR_FACILITY)*/ // #if defined (FEATURE_VECTOR_FACILITY) zz_func v_opcode_e4xx[256][GEN_MAXARCH] = { /*E400*/ GENx___x___x___ , /*E401*/ GENx___x___x___ , /*E402*/ GENx___x___x___ , /*E403*/ GENx___x___x___ , /*E404*/ GENx___x___x___ , /*E405*/ GENx___x___x___ , /*E406*/ GENx___x___x___ , /*E407*/ GENx___x___x___ , /*E408*/ GENx___x___x___ , /*E409*/ GENx___x___x___ , /*E40A*/ GENx___x___x___ , /*E40B*/ GENx___x___x___ , /*E40C*/ GENx___x___x___ , /*E40D*/ GENx___x___x___ , /*E40E*/ GENx___x___x___ , /*E40F*/ GENx___x___x___ , /*E410*/ GENx___x___x___ , /*E411*/ GENx___x___x___ , /*E412*/ GENx___x___x___ , /*E413*/ GENx___x___x___ , /*E414*/ GENx___x___x___ , /*E415*/ GENx___x___x___ , /*E416*/ GENx___x___x___ , /*E417*/ GENx___x___x___ , /*E418*/ GENx___x___x___ , /*E419*/ GENx___x___x___ , /*E41A*/ GENx___x___x___ , /*E41B*/ GENx___x___x___ , /*E41C*/ GENx___x___x___ , /*E41D*/ GENx___x___x___ , /*E41E*/ GENx___x___x___ , /*E41F*/ GENx___x___x___ , /*E420*/ GENx___x___x___ , /*E421*/ GENx___x___x___ , /*E422*/ GENx___x___x___ , /*E423*/ GENx___x___x___ , /*E424*/ GENx___x___x___ , /*E425*/ GENx___x___x___ , /*E426*/ GENx___x___x___ , /*E427*/ GENx___x___x___ , /*E428*/ GENx___x___x___ , /*E429*/ GENx___x___x___ , /*E42A*/ GENx___x___x___ , /*E42B*/ GENx___x___x___ , /*E42C*/ GENx___x___x___ , /*E42D*/ GENx___x___x___ , /*E42E*/ GENx___x___x___ , /*E42F*/ GENx___x___x___ , /*E430*/ GENx___x___x___ , /*E431*/ GENx___x___x___ , /*E432*/ GENx___x___x___ , /*E433*/ GENx___x___x___ , /*E434*/ GENx___x___x___ , /*E435*/ GENx___x___x___ , /*E436*/ GENx___x___x___ , /*E437*/ GENx___x___x___ , /*E438*/ GENx___x___x___ , /*E439*/ GENx___x___x___ , /*E43A*/ GENx___x___x___ , /*E43B*/ GENx___x___x___ , /*E43C*/ GENx___x___x___ , /*E43D*/ GENx___x___x___ , /*E43E*/ GENx___x___x___ , /*E43F*/ GENx___x___x___ , /*E440*/ GENx___x___x___ , /*E441*/ GENx___x___x___ , /*E442*/ GENx___x___x___ , /*E443*/ GENx___x___x___ , /*E444*/ GENx___x___x___ , /*E445*/ GENx___x___x___ , /*E446*/ GENx___x___x___ , /*E447*/ GENx___x___x___ , /*E448*/ GENx___x___x___ , /*E449*/ GENx___x___x___ , /*E44A*/ GENx___x___x___ , /*E44B*/ GENx___x___x___ , /*E44C*/ GENx___x___x___ , /*E44D*/ GENx___x___x___ , /*E44E*/ GENx___x___x___ , /*E44F*/ GENx___x___x___ , /*E450*/ GENx___x___x___ , /*E451*/ GENx___x___x___ , /*E452*/ GENx___x___x___ , /*E453*/ GENx___x___x___ , /*E454*/ GENx___x___x___ , /*E455*/ GENx___x___x___ , /*E456*/ GENx___x___x___ , /*E457*/ GENx___x___x___ , /*E458*/ GENx___x___x___ , /*E459*/ GENx___x___x___ , /*E45A*/ GENx___x___x___ , /*E45B*/ GENx___x___x___ , /*E45C*/ GENx___x___x___ , /*E45D*/ GENx___x___x___ , /*E45E*/ GENx___x___x___ , /*E45F*/ GENx___x___x___ , /*E460*/ GENx___x___x___ , /*E461*/ GENx___x___x___ , /*E462*/ GENx___x___x___ , /*E463*/ GENx___x___x___ , /*E464*/ GENx___x___x___ , /*E465*/ GENx___x___x___ , /*E466*/ GENx___x___x___ , /*E467*/ GENx___x___x___ , /*E468*/ GENx___x___x___ , /*E469*/ GENx___x___x___ , /*E46A*/ GENx___x___x___ , /*E46B*/ GENx___x___x___ , /*E46C*/ GENx___x___x___ , /*E46D*/ GENx___x___x___ , /*E46E*/ GENx___x___x___ , /*E46F*/ GENx___x___x___ , /*E470*/ GENx___x___x___ , /*E471*/ GENx___x___x___ , /*E472*/ GENx___x___x___ , /*E473*/ GENx___x___x___ , /*E474*/ GENx___x___x___ , /*E475*/ GENx___x___x___ , /*E476*/ GENx___x___x___ , /*E477*/ GENx___x___x___ , /*E478*/ GENx___x___x___ , /*E479*/ GENx___x___x___ , /*E47A*/ GENx___x___x___ , /*E47B*/ GENx___x___x___ , /*E47C*/ GENx___x___x___ , /*E47D*/ GENx___x___x___ , /*E47E*/ GENx___x___x___ , /*E47F*/ GENx___x___x___ , /*E480*/ GENx___x___x___ , /*E481*/ GENx___x___x___ , /*E482*/ GENx___x___x___ , /*E483*/ GENx___x___x___ , /*E484*/ GENx___x___x___ , /*E485*/ GENx___x___x___ , /*E486*/ GENx___x___x___ , /*E487*/ GENx___x___x___ , /*E488*/ GENx___x___x___ , /*E489*/ GENx___x___x___ , /*E48A*/ GENx___x___x___ , /*E48B*/ GENx___x___x___ , /*E48C*/ GENx___x___x___ , /*E48D*/ GENx___x___x___ , /*E48E*/ GENx___x___x___ , /*E48F*/ GENx___x___x___ , /*E490*/ GENx___x___x___ , /*E491*/ GENx___x___x___ , /*E492*/ GENx___x___x___ , /*E493*/ GENx___x___x___ , /*E494*/ GENx___x___x___ , /*E495*/ GENx___x___x___ , /*E496*/ GENx___x___x___ , /*E497*/ GENx___x___x___ , /*E498*/ GENx___x___x___ , /*E499*/ GENx___x___x___ , /*E49A*/ GENx___x___x___ , /*E49B*/ GENx___x___x___ , /*E49C*/ GENx___x___x___ , /*E49D*/ GENx___x___x___ , /*E49E*/ GENx___x___x___ , /*E49F*/ GENx___x___x___ , /*E4A0*/ GENx___x___x___ , /*E4A1*/ GENx___x___x___ , /*E4A2*/ GENx___x___x___ , /*E4A3*/ GENx___x___x___ , /*E4A4*/ GENx___x___x___ , /*E4A5*/ GENx___x___x___ , /*E4A6*/ GENx___x___x___ , /*E4A7*/ GENx___x___x___ , /*E4A8*/ GENx___x___x___ , /*E4A9*/ GENx___x___x___ , /*E4AA*/ GENx___x___x___ , /*E4AB*/ GENx___x___x___ , /*E4AC*/ GENx___x___x___ , /*E4AD*/ GENx___x___x___ , /*E4AE*/ GENx___x___x___ , /*E4AF*/ GENx___x___x___ , /*E4B0*/ GENx___x___x___ , /*E4B1*/ GENx___x___x___ , /*E4B2*/ GENx___x___x___ , /*E4B3*/ GENx___x___x___ , /*E4B4*/ GENx___x___x___ , /*E4B5*/ GENx___x___x___ , /*E4B6*/ GENx___x___x___ , /*E4B7*/ GENx___x___x___ , /*E4B8*/ GENx___x___x___ , /*E4B9*/ GENx___x___x___ , /*E4BA*/ GENx___x___x___ , /*E4BB*/ GENx___x___x___ , /*E4BC*/ GENx___x___x___ , /*E4BD*/ GENx___x___x___ , /*E4BE*/ GENx___x___x___ , /*E4BF*/ GENx___x___x___ , /*E4C0*/ GENx___x___x___ , /*E4C1*/ GENx___x___x___ , /*E4C2*/ GENx___x___x___ , /*E4C3*/ GENx___x___x___ , /*E4C4*/ GENx___x___x___ , /*E4C5*/ GENx___x___x___ , /*E4C6*/ GENx___x___x___ , /*E4C7*/ GENx___x___x___ , /*E4C8*/ GENx___x___x___ , /*E4C9*/ GENx___x___x___ , /*E4CA*/ GENx___x___x___ , /*E4CB*/ GENx___x___x___ , /*E4CC*/ GENx___x___x___ , /*E4CD*/ GENx___x___x___ , /*E4CE*/ GENx___x___x___ , /*E4CF*/ GENx___x___x___ , /*E4D0*/ GENx___x___x___ , /*E4D1*/ GENx___x___x___ , /*E4D2*/ GENx___x___x___ , /*E4D3*/ GENx___x___x___ , /*E4D4*/ GENx___x___x___ , /*E4D5*/ GENx___x___x___ , /*E4D6*/ GENx___x___x___ , /*E4D7*/ GENx___x___x___ , /*E4D8*/ GENx___x___x___ , /*E4D9*/ GENx___x___x___ , /*E4DA*/ GENx___x___x___ , /*E4DB*/ GENx___x___x___ , /*E4DC*/ GENx___x___x___ , /*E4DD*/ GENx___x___x___ , /*E4DE*/ GENx___x___x___ , /*E4DF*/ GENx___x___x___ , /*E4E0*/ GENx___x___x___ , /*E4E1*/ GENx___x___x___ , /*E4E2*/ GENx___x___x___ , /*E4E3*/ GENx___x___x___ , /*E4E4*/ GENx___x___x___ , /*E4E5*/ GENx___x___x___ , /*E4E6*/ GENx___x___x___ , /*E4E7*/ GENx___x___x___ , /*E4E8*/ GENx___x___x___ , /*E4E9*/ GENx___x___x___ , /*E4EA*/ GENx___x___x___ , /*E4EB*/ GENx___x___x___ , /*E4EC*/ GENx___x___x___ , /*E4ED*/ GENx___x___x___ , /*E4EE*/ GENx___x___x___ , /*E4EF*/ GENx___x___x___ , /*E4F0*/ GENx___x___x___ , /*E4F1*/ GENx___x___x___ , /*E4F2*/ GENx___x___x___ , /*E4F3*/ GENx___x___x___ , /*E4F4*/ GENx___x___x___ , /*E4F5*/ GENx___x___x___ , /*E4F6*/ GENx___x___x___ , /*E4F7*/ GENx___x___x___ , /*E4F8*/ GENx___x___x___ , /*E4F9*/ GENx___x___x___ , /*E4FA*/ GENx___x___x___ , /*E4FB*/ GENx___x___x___ , /*E4FC*/ GENx___x___x___ , /*E4FD*/ GENx___x___x___ , /*E4FE*/ GENx___x___x___ , /*E4FF*/ GENx___x___x___ }; // #endif /*defined (FEATURE_VECTOR_FACILITY)*/ #endif /*!defined (_GEN_ARCH)*/ /* end of OPCODE.C */ hercules-3.07/opcode.h000644 000765 000765 00000421441 11321734033 016370 0ustar00jmaynardjmaynard000000 000000 /* OPCODE.H (c) Copyright Jan Jaeger, 2000-2009 */ /* Instruction decoding macros and prototypes */ /* Interpretive Execution - (c) Copyright Jan Jaeger, 1999-2009 */ /* z/Architecture support - (c) Copyright Jan Jaeger, 1999-2009 */ // $Id: opcode.h 5573 2009-12-29 13:13:29Z bernard $ #ifndef _OPCODE_H #define _OPCODE_H #include "hercules.h" #ifndef _CPU_C_ #ifndef _HENGINE_DLL_ #define CPU_DLL_IMPORT DLL_IMPORT #else /* _HENGINE_DLL_ */ #define CPU_DLL_IMPORT extern #endif /* _HENGINE_DLL_ */ #else /* _CPU_C_ */ #define CPU_DLL_IMPORT DLL_EXPORT #endif /* _CPU_C_ */ #ifndef _OPCODE_C_ #ifndef _HENGINE_DLL_ #define OPC_DLL_IMPORT DLL_IMPORT #else /* _HENGINE_DLL_ */ #define OPC_DLL_IMPORT extern #endif /* _HENGINE_DLL_ */ #else /* _OPCODE_C_ */ #define OPC_DLL_IMPORT DLL_EXPORT #endif /* _OPCODE_C_ */ #if defined(_370) #define _GEN370(_name) &s370_ ## _name, #else #define _GEN370(_name) #endif #if defined(_390) #define _GEN390(_name) &s390_ ## _name, #else #define _GEN390(_name) #endif #if defined(_900) #define _GEN900(_name) &z900_ ## _name, #else #define _GEN900(_name) #endif #define GENx___x___x___ \ { \ _GEN370(operation_exception) \ _GEN390(operation_exception) \ _GEN900(operation_exception) \ (void*)&disasm_none, \ (void*)&"?????" "\0" "?" \ } #define GENx370x___x___(_name,_format,_mnemonic) \ { \ _GEN370(_name) \ _GEN390(operation_exception) \ _GEN900(operation_exception) \ (void*)&disasm_ ## _format, \ (void*)& _mnemonic "\0" #_name \ } #define GENx___x390x___(_name,_format,_mnemonic) \ { \ _GEN370(operation_exception) \ _GEN390(_name) \ _GEN900(operation_exception) \ (void*)&disasm_ ## _format, \ (void*)& _mnemonic "\0" #_name \ } #define GENx370x390x___(_name,_format,_mnemonic) \ { \ _GEN370(_name) \ _GEN390(_name) \ _GEN900(operation_exception) \ (void*)&disasm_ ## _format, \ (void*)& _mnemonic "\0" #_name \ } #define GENx___x___x900(_name,_format,_mnemonic) \ { \ _GEN370(operation_exception) \ _GEN390(operation_exception) \ _GEN900(_name) \ (void*)&disasm_ ## _format, \ (void*)& _mnemonic "\0" #_name \ } #define GENx370x___x900(_name,_format,_mnemonic) \ { \ _GEN370(_name) \ _GEN390(operation_exception) \ _GEN900(_name) \ (void*)&disasm_ ## _format, \ (void*)& _mnemonic "\0" #_name \ } #define GENx___x390x900(_name,_format,_mnemonic) \ { \ _GEN370(operation_exception) \ _GEN390(_name) \ _GEN900(_name) \ (void*)&disasm_ ## _format, \ (void*)& _mnemonic "\0" #_name \ } #define GENx370x390x900(_name,_format,_mnemonic) \ { \ _GEN370(_name) \ _GEN390(_name) \ _GEN900(_name) \ (void*)&disasm_ ## _format, \ (void*)& _mnemonic "\0" #_name \ } /* The following variants of the opcode table definition macros specify 37X (370 EXTENSIONS) instead of 370 to indicate that they are ESA/390 and ESAME instructions back-ported to S/370 */ #define GENx37Xx390x___ GENx370x390x___ #define GENx37Xx___x900 GENx370x___x900 #define GENx37Xx390x900 GENx370x390x900 typedef void (ATTR_REGPARM(2) *zz_func) (BYTE inst[], REGS *regs); #define ILC(_b) ((_b) < 0x40 ? 2 : (_b) < 0xc0 ? 4 : 6) #define REAL_ILC(_regs) \ (likely(!(_regs)->execflag) ? (_regs)->psw.ilc : (_regs)->exrl ? 6 : 4) /* Gabor Hoffer (performance option) */ OPC_DLL_IMPORT zz_func s370_opcode_table[]; OPC_DLL_IMPORT zz_func s390_opcode_table[]; OPC_DLL_IMPORT zz_func z900_opcode_table[]; OPC_DLL_IMPORT zz_func opcode_table[][GEN_MAXARCH]; OPC_DLL_IMPORT zz_func opcode_01xx[][GEN_MAXARCH]; extern zz_func v_opcode_a4xx[][GEN_MAXARCH]; OPC_DLL_IMPORT zz_func opcode_a5xx[][GEN_MAXARCH]; extern zz_func v_opcode_a5xx[][GEN_MAXARCH]; extern zz_func v_opcode_a6xx[][GEN_MAXARCH]; OPC_DLL_IMPORT zz_func opcode_a7xx[][GEN_MAXARCH]; OPC_DLL_IMPORT zz_func opcode_b2xx[][GEN_MAXARCH]; OPC_DLL_IMPORT zz_func opcode_b3xx[][GEN_MAXARCH]; OPC_DLL_IMPORT zz_func opcode_b9xx[][GEN_MAXARCH]; OPC_DLL_IMPORT zz_func opcode_c0xx[][GEN_MAXARCH]; OPC_DLL_IMPORT zz_func opcode_c2xx[][GEN_MAXARCH]; /*@Z9*/ OPC_DLL_IMPORT zz_func opcode_c4xx[][GEN_MAXARCH]; /*208*/ OPC_DLL_IMPORT zz_func opcode_c6xx[][GEN_MAXARCH]; /*208*/ OPC_DLL_IMPORT zz_func opcode_c8xx[][GEN_MAXARCH]; OPC_DLL_IMPORT zz_func opcode_e3xx[][GEN_MAXARCH]; OPC_DLL_IMPORT zz_func opcode_e4xx[256][GEN_MAXARCH]; extern zz_func v_opcode_e4xx[][GEN_MAXARCH]; OPC_DLL_IMPORT zz_func opcode_e5xx[][GEN_MAXARCH]; OPC_DLL_IMPORT zz_func opcode_e6xx[][GEN_MAXARCH]; OPC_DLL_IMPORT zz_func opcode_ebxx[][GEN_MAXARCH]; OPC_DLL_IMPORT zz_func opcode_ecxx[][GEN_MAXARCH]; OPC_DLL_IMPORT zz_func opcode_edxx[][GEN_MAXARCH]; #define DISASM_INSTRUCTION(_inst) \ disasm_table((_inst), 0) typedef void (*func) (); extern void disasm_table (BYTE inst[], char mnemonic[]); #if defined(OPTION_INSTRUCTION_COUNTING) #define COUNT_INST(_inst, _regs) \ do { \ int used; \ switch((_inst)[0]) { \ case 0x01: \ used = sysblk.imap01[(_inst)[1]]++; \ break; \ case 0xA4: \ used = sysblk.imapa4[(_inst)[1]]++; \ break; \ case 0xA5: \ used = sysblk.imapa5[(_inst)[1] & 0x0F]++; \ break; \ case 0xA6: \ used = sysblk.imapa6[(_inst)[1]]++; \ break; \ case 0xA7: \ used = sysblk.imapa7[(_inst)[1] & 0x0F]++; \ break; \ case 0xB2: \ used = sysblk.imapb2[(_inst)[1]]++; \ break; \ case 0xB3: \ used = sysblk.imapb3[(_inst)[1]]++; \ break; \ case 0xB9: \ used = sysblk.imapb9[(_inst)[1]]++; \ break; \ case 0xC0: \ used = sysblk.imapc0[(_inst)[1] & 0x0F]++; \ break; \ case 0xC2: /*@Z9*/ \ used = sysblk.imapc2[(_inst)[1] & 0x0F]++; /*@Z9*/ \ break; /*@Z9*/ \ case 0xC4: /*208*/ \ used = sysblk.imapc4[(_inst)[1] & 0x0F]++; /*208*/ \ break; /*208*/ \ case 0xC6: /*208*/ \ used = sysblk.imapc6[(_inst)[1] & 0x0F]++; /*208*/ \ break; /*208*/ \ case 0xC8: \ used = sysblk.imapc8[(_inst)[1] & 0x0F]++; \ break; \ case 0xE3: \ used = sysblk.imape3[(_inst)[5]]++; \ break; \ case 0xE4: \ used = sysblk.imape4[(_inst)[1]]++; \ break; \ case 0xE5: \ used = sysblk.imape5[(_inst)[1]]++; \ break; \ case 0xEB: \ used = sysblk.imapeb[(_inst)[5]]++; \ break; \ case 0xEC: \ used = sysblk.imapec[(_inst)[5]]++; \ break; \ case 0xED: \ used = sysblk.imaped[(_inst)[5]]++; \ break; \ default: \ used = sysblk.imapxx[(_inst)[0]]++; \ } \ if(!used) \ { \ obtain_lock( &sysblk.icount_lock ); \ logmsg("First use: "); \ ARCH_DEP(display_inst) ((_regs), (_inst)); \ release_lock( &sysblk.icount_lock ); \ } \ } while(0) #else #define COUNT_INST(_inst, _regs) #endif #if defined(_FEATURE_SIE) #define SIE_MODE(_register_context) \ unlikely((_register_context)->sie_mode) #define SIE_STATE(_register_context) \ ((_register_context)->sie_state) #define SIE_FEATB(_regs, _feat_byte, _feat_name) \ (((_regs)->siebk->SIE_ ## _feat_byte) & (SIE_ ## _feat_byte ## _ ## _feat_name)) #define SIE_STATB(_regs, _feat_byte, _feat_name) \ (SIE_MODE((_regs)) && SIE_FEATB((_regs), _feat_byte, _feat_name) ) #define SIE_STATNB(_regs, _feat_byte, _feat_name) \ (SIE_MODE((_regs)) && !SIE_FEATB((_regs), _feat_byte, _feat_name) ) #else #define SIE_MODE(_register_context) (0) #define SIE_STATE(_register_context) (0) #define SIE_FEATB(_register_context, _feat_byte, _feat_name) (0) #define SIE_STATB(_register_context, _feat_byte, _feat_name) (0) #endif /* The footprint_buffer option saves a copy of the register context every time an instruction is executed. This is for problem determination only, as it severely impacts performance. *JJ */ #if defined(OPTION_FOOTPRINT_BUFFER) #define FOOTPRINT(_regs) \ do { \ sysblk.footprregs[(_regs)->cpuad][sysblk.footprptr[(_regs)->cpuad]] = *(_regs); \ memcpy(&sysblk.footprregs[(_regs)->cpuad][sysblk.footprptr[(_regs)->cpuad]++].inst,(_inst),6); \ sysblk.footprptr[(_regs)->cpuad] &= OPTION_FOOTPRINT_BUFFER - 1; \ } while(0) #endif #if !defined(FOOTPRINT) #define FOOTPRINT(_regs) #endif /* PSW Instruction Address manipulation */ #define _PSW_IA(_regs, _n) \ (VADR)((_regs)->AIV + ((intptr_t)(_regs)->ip - (intptr_t)(_regs)->aip) + (_n)) #define PSW_IA(_regs, _n) \ (_PSW_IA((_regs), (_n)) & ADDRESS_MAXWRAP((_regs))) #define SET_PSW_IA(_regs) \ do { \ if ((_regs)->aie) (_regs)->psw.IA = PSW_IA((_regs), 0); \ } while (0) #define UPD_PSW_IA(_regs, _addr) \ do { \ (_regs)->psw.IA = (_addr) & ADDRESS_MAXWRAP(_regs); \ if (likely((_regs)->aie != NULL)) { \ if (likely((_regs)->AIV == ((_regs)->psw.IA & (PAGEFRAME_PAGEMASK|1)))) \ (_regs)->ip = _PSW_IA_MAIN((_regs), (_regs)->psw.IA); \ else \ (_regs)->aie = NULL; \ } \ } while (0) /* * The next three macros are used by branch-and-link type instructions * where the addressing mode is known. * Note that wrap is not performed for PSW_IA64 and for PSW_IA31. * For the latter, we expect branch-and-link code to `or' the hi bit * on so there is no need to `and' it off. */ #define PSW_IA64(_regs, _n) \ ((_regs)->AIV \ + (((uintptr_t)(_regs)->ip + (unsigned int)(_n)) - (uintptr_t)(_regs)->aip)) #define PSW_IA31(_regs, _n) \ ((_regs)->AIV_L + ((uintptr_t)(_regs)->ip + (unsigned int)(_n)) \ - (uintptr_t)(_regs)->aip) #define PSW_IA24(_regs, _n) \ (((_regs)->AIV_L + ((uintptr_t)(_regs)->ip + (unsigned int)(_n)) \ - (uintptr_t)(_regs)->aip) & AMASK24) /* Accelerator for instruction addresses */ #define INVALIDATE_AIA(_regs) \ do { \ if ((_regs)->aie) { \ (_regs)->psw.IA = PSW_IA((_regs), 0); \ (_regs)->aie = NULL; \ } \ } while (0) #define INVALIDATE_AIA_MAIN(_regs, _main) \ do { \ if ((_main) == (_regs)->aip && (_regs)->aie) { \ (_regs)->psw.IA = PSW_IA((_regs), 0); \ (_regs)->aie = NULL; \ } \ } while (0) #if 1 #define _PSW_IA_MAIN(_regs, _addr) \ ((BYTE *)((uintptr_t)(_regs)->aip | (uintptr_t)((_addr) & PAGEFRAME_BYTEMASK))) #else #define _PSW_IA_MAIN(_regs, _addr) \ ((BYTE *)((_regs)->aim ^ (uintptr_t)(_addr))) #endif #define _VALID_IP(_regs, _exec) \ ( \ ( !(_exec) && (_regs)->ip < (_regs)->aie ) \ || \ ( (_exec) && ((_regs)->ET & (PAGEFRAME_PAGEMASK|0x01)) == (_regs)->AIV \ && _PSW_IA_MAIN((_regs), (_regs)->ET) < (_regs)->aie \ ) \ ) /* Instruction fetching */ #define INSTRUCTION_FETCH(_regs, _exec) \ likely(_VALID_IP((_regs),(_exec))) \ ? ((_exec) ? _PSW_IA_MAIN((_regs), (_regs)->ET) : (_regs)->ip) \ : ARCH_DEP(instfetch) ((_regs), (_exec)) /* Instruction execution */ #define EXECUTE_INSTRUCTION(_ip, _regs) \ do { \ FOOTPRINT ((_regs)); \ COUNT_INST ((_ip), (_regs)); \ (_regs)->ARCH_DEP(opcode_table)[_ip[0]]((_ip), (_regs)); \ } while(0) #define UNROLLED_EXECUTE(_regs) \ if ((_regs)->ip >= (_regs)->aie) break; \ EXECUTE_INSTRUCTION((_regs)->ip, (_regs)) /* Branching */ #define SUCCESSFUL_BRANCH(_regs, _addr, _len) \ do { \ VADR _newia; \ UPDATE_BEAR((_regs), 0); \ _newia = (_addr) & ADDRESS_MAXWRAP((_regs)); \ if (likely(!(_regs)->permode && !(_regs)->execflag) \ && likely((_newia & (PAGEFRAME_PAGEMASK|0x01)) == (_regs)->AIV)) { \ (_regs)->ip = (BYTE *)((uintptr_t)(_regs)->aim ^ (uintptr_t)_newia); \ return; \ } else { \ if (unlikely((_regs)->execflag)) \ UPDATE_BEAR((_regs), (_len) - ((_regs)->exrl ? 6 : 4)); \ (_regs)->psw.IA = _newia; \ (_regs)->aie = NULL; \ PER_SB((_regs), (_regs)->psw.IA); \ } \ } while (0) #define SUCCESSFUL_RELATIVE_BRANCH(_regs, _offset, _len) \ do { \ UPDATE_BEAR((_regs), 0); \ if (likely(!(_regs)->permode && !(_regs)->execflag) \ && likely((_regs)->ip + (_offset) >= (_regs)->aip) \ && likely((_regs)->ip + (_offset) < (_regs)->aie)) { \ (_regs)->ip += (_offset); \ return; \ } else { \ if (likely(!(_regs)->execflag)) \ (_regs)->psw.IA = PSW_IA((_regs), (_offset)); \ else { \ UPDATE_BEAR((_regs), (_len) - ((_regs)->exrl ? 6 : 4)); \ (_regs)->psw.IA = (_regs)->ET + (_offset); \ (_regs)->psw.IA &= ADDRESS_MAXWRAP((_regs)); \ } \ (_regs)->aie = NULL; \ PER_SB((_regs), (_regs)->psw.IA); \ } \ } while (0) /* BRCL, BRASL can branch +/- 4G. This is problematic on a 32 bit host */ #define SUCCESSFUL_RELATIVE_BRANCH_LONG(_regs, _offset) \ do { \ UPDATE_BEAR((_regs), 0); \ if (likely(!(_regs)->permode && !(_regs)->execflag) \ && likely((_offset) > -4096) \ && likely((_offset) < 4096) \ && likely((_regs)->ip + (_offset) >= (_regs)->aip) \ && likely((_regs)->ip + (_offset) < (_regs)->aie)) { \ (_regs)->ip += (_offset); \ return; \ } else { \ if (likely(!(_regs)->execflag)) \ (_regs)->psw.IA = PSW_IA((_regs), (_offset)); \ else { \ UPDATE_BEAR((_regs), 6 - ((_regs)->exrl ? 6 : 4)); \ (_regs)->psw.IA = (_regs)->ET + (_offset); \ (_regs)->psw.IA &= ADDRESS_MAXWRAP((_regs)); \ } \ (_regs)->aie = NULL; \ PER_SB((_regs), (_regs)->psw.IA); \ } \ } while (0) /* CPU Stepping or Tracing */ #define CPU_STEPPING(_regs, _ilc) \ ( \ sysblk.inststep \ && ( \ (sysblk.stepaddr[0] == 0 && sysblk.stepaddr[1] == 0) \ || (sysblk.stepaddr[0] <= sysblk.stepaddr[1] \ && PSW_IA((_regs), -(_ilc)) >= sysblk.stepaddr[0] \ && PSW_IA((_regs), -(_ilc)) <= sysblk.stepaddr[1] \ ) \ || (sysblk.stepaddr[0] > sysblk.stepaddr[1] \ && PSW_IA((_regs), -(_ilc)) >= sysblk.stepaddr[1] \ && PSW_IA((_regs), -(_ilc)) <= sysblk.stepaddr[0] \ ) \ ) \ ) #define CPU_TRACING(_regs, _ilc) \ ( \ sysblk.insttrace \ && ( \ (sysblk.traceaddr[0] == 0 && sysblk.traceaddr[1] == 0) \ || (sysblk.traceaddr[0] <= sysblk.traceaddr[1] \ && PSW_IA((_regs), -(_ilc)) >= sysblk.traceaddr[0] \ && PSW_IA((_regs), -(_ilc)) <= sysblk.traceaddr[1] \ ) \ || (sysblk.traceaddr[0] > sysblk.traceaddr[1] \ && PSW_IA((_regs), -(_ilc)) >= sysblk.traceaddr[1] \ && PSW_IA((_regs), -(_ilc)) <= sysblk.traceaddr[0] \ ) \ ) \ ) #define CPU_STEPPING_OR_TRACING(_regs, _ilc) \ ( unlikely((_regs)->tracing) && \ (CPU_STEPPING((_regs), (_ilc)) || CPU_TRACING((_regs), (_ilc))) \ ) #define CPU_TRACING_ALL \ (sysblk.insttrace && sysblk.traceaddr[0] == 0 && sysblk.traceaddr[1] == 0) #define CPU_STEPPING_ALL \ (sysblk.inststep && sysblk.stepaddr[0] == 0 && sysblk.stepaddr[1] == 0) #define CPU_STEPPING_OR_TRACING_ALL \ ( CPU_TRACING_ALL || CPU_STEPPING_ALL ) #define RETURN_INTCHECK(_regs) \ longjmp((_regs)->progjmp, SIE_NO_INTERCEPT) #define ODD_CHECK(_r, _regs) \ if( (_r) & 1 ) \ (_regs)->program_interrupt( (_regs), PGM_SPECIFICATION_EXCEPTION) #define ODD2_CHECK(_r1, _r2, _regs) \ if( ((_r1) & 1) || ((_r2) & 1) ) \ (_regs)->program_interrupt( (_regs), PGM_SPECIFICATION_EXCEPTION) #define HW_CHECK(_value, _regs) \ if( (_value) & 1 ) \ (_regs)->program_interrupt( (_regs), PGM_SPECIFICATION_EXCEPTION) #define FW_CHECK(_value, _regs) \ if( (_value) & 3 ) \ (_regs)->program_interrupt( (_regs), PGM_SPECIFICATION_EXCEPTION) #define DW_CHECK(_value, _regs) \ if( (_value) & 7 ) \ (_regs)->program_interrupt( (_regs), PGM_SPECIFICATION_EXCEPTION) #define QW_CHECK(_value, _regs) \ if( (_value) & 15 ) \ (_regs)->program_interrupt( (_regs), PGM_SPECIFICATION_EXCEPTION) /* Program check if m is not 0, 1, or 4 to 7 */ #define HFPM_CHECK(_m, _regs) \ if (((_m) == 2) || ((_m) == 3) || ((_m) & 8)) \ (_regs)->program_interrupt( (_regs), PGM_SPECIFICATION_EXCEPTION) #define PRIV_CHECK(_regs) \ if( PROBSTATE(&(_regs)->psw) ) \ (_regs)->program_interrupt( (_regs), PGM_PRIVILEGED_OPERATION_EXCEPTION) /* Program check if r is not 0,1,4,5,8,9,12, or 13 (designating the lower-numbered register of a floating-point register pair) */ #define BFPREGPAIR_CHECK(_r, _regs) \ if( ((_r) & 2) ) \ (_regs)->program_interrupt( (_regs), PGM_SPECIFICATION_EXCEPTION) /* Program check if r1 and r2 are not both 0,1,4,5,8,9,12, or 13 (lower-numbered register of a floating-point register pair) */ #define BFPREGPAIR2_CHECK(_r1, _r2, _regs) \ if( ((_r1) & 2) || ((_r2) & 2) ) \ (_regs)->program_interrupt( (_regs), PGM_SPECIFICATION_EXCEPTION) /* Program check if r is not 0,1,4,5,8,9,12, or 13 (designating the lower-numbered register of a floating-point register pair) */ #define DFPREGPAIR_CHECK(_r, _regs) \ if( ((_r) & 2) ) \ (_regs)->program_interrupt( (_regs), PGM_SPECIFICATION_EXCEPTION) /* Program check if r1 and r2 are not both 0,1,4,5,8,9,12, or 13 (lower-numbered register of a floating-point register pair) */ #define DFPREGPAIR2_CHECK(_r1, _r2, _regs) \ if( ((_r1) & 2) || ((_r2) & 2) ) \ (_regs)->program_interrupt( (_regs), PGM_SPECIFICATION_EXCEPTION) /* Program check if r1, r2, r3 are not all 0,1,4,5,8,9,12, or 13 (lower-numbered register of a floating-point register pair) */ #define DFPREGPAIR3_CHECK(_r1, _r2, _r3, _regs) \ if( ((_r1) & 2) || ((_r2) & 2) || ((_r3) & 2) ) \ (_regs)->program_interrupt( (_regs), PGM_SPECIFICATION_EXCEPTION) /* Program check if fpc is not valid contents for FPC register */ #define FPC_CHECK(_fpc, _regs) \ if((_fpc) & FPC_RESERVED) \ (_regs)->program_interrupt( (_regs), PGM_SPECIFICATION_EXCEPTION) #define SSID_CHECK(_regs) \ if((!((_regs)->GR_LHH(1) & 0x0001)) \ || (_regs)->GR_LHH(1) > (0x0001|((FEATURE_LCSS_MAX-1) << 1))) \ (_regs)->program_interrupt( (_regs), PGM_OPERAND_EXCEPTION) #define IOID_TO_SSID(_ioid) \ ((_ioid) >> 16) #define IOID_TO_LCSS(_ioid) \ ((_ioid) >> 17) #define SSID_TO_LCSS(_ssid) \ ((_ssid) >> 1) #define LCSS_TO_SSID(_lcss) \ (((_lcss) << 1) | 1) #define PER_RANGE_CHECK(_addr, _low, _high) \ ( (((_high) & MAXADDRESS) >= ((_low) & MAXADDRESS)) ? \ (((_addr) >= ((_low) & MAXADDRESS)) && (_addr) <= ((_high) & MAXADDRESS)) : \ (((_addr) >= ((_low) & MAXADDRESS)) || (_addr) <= ((_high) & MAXADDRESS)) ) #define PER_RANGE_CHECK2(_addr1, _addr2, _low, _high) \ ( (((_high) & MAXADDRESS) >= ((_low) & MAXADDRESS)) ? \ (((_addr1) >= ((_low) & MAXADDRESS)) && (_addr1) <= ((_high) & MAXADDRESS)) || \ (((_addr2) >= ((_low) & MAXADDRESS)) && (_addr2) <= ((_high) & MAXADDRESS)) || \ (((_addr1) <= ((_low) & MAXADDRESS)) && (_addr2) >= ((_high) & MAXADDRESS)) : \ (((_addr2) >= ((_low) & MAXADDRESS)) || (_addr1) <= ((_high) & MAXADDRESS)) ) #ifdef WORDS_BIGENDIAN #define CSWAP16(_x) (_x) #define CSWAP32(_x) (_x) #define CSWAP64(_x) (_x) #else #define CSWAP16(_x) bswap_16(_x) #define CSWAP32(_x) bswap_32(_x) #define CSWAP64(_x) bswap_64(_x) #endif #define FETCH_HW(_value, _storage) (_value) = fetch_hw(_storage) #define FETCH_FW(_value, _storage) (_value) = fetch_fw(_storage) #define FETCH_DW(_value, _storage) (_value) = fetch_dw(_storage) #define STORE_HW(_storage, _value) store_hw(_storage, _value) #define STORE_FW(_storage, _value) store_fw(_storage, _value) #define STORE_DW(_storage, _value) store_dw(_storage, _value) #include "machdep.h" #endif /*!defined(_OPCODE_H)*/ #undef SIE_ACTIVE #if defined(FEATURE_INTERPRETIVE_EXECUTION) #define SIE_ACTIVE(_regs) ((_regs)->sie_active) #else #define SIE_ACTIVE(_regs) (0) #endif #undef MULTIPLE_CONTROLLED_DATA_SPACE #if defined(_FEATURE_MULTIPLE_CONTROLLED_DATA_SPACE) #define MULTIPLE_CONTROLLED_DATA_SPACE(_regs) \ ( SIE_FEATB((_regs), MX, XC) && AR_BIT(&(_regs)->psw) ) #else #define MULTIPLE_CONTROLLED_DATA_SPACE(_regs) (0) #endif /* PER3 Breaking Event Address Recording (BEAR) */ #undef UPDATE_BEAR #undef SET_BEAR_REG #if defined(FEATURE_PER3) #define UPDATE_BEAR(_regs, _n) (_regs)->bear_ip = (_regs)->ip + (_n) #define SET_BEAR_REG(_regs, _ip) \ do { \ if ((_ip)) { \ (_regs)->bear = (_regs)->AIV \ + (intptr_t)((_ip) - (_regs)->aip); \ (_regs)->bear &= ADDRESS_MAXWRAP((_regs)); \ regs->bear_ip = NULL; \ } \ } while (0) #else #define UPDATE_BEAR(_regs, _n) while (0) #define SET_BEAR_REG(_regs, _ip) while (0) #endif /* Set addressing mode (BASSM, BSM) */ #undef SET_ADDRESSING_MODE #if defined(FEATURE_ESAME) #define SET_ADDRESSING_MODE(_regs, _addr) \ do { \ if ((_addr) & 1) { \ (_regs)->psw.amode64 = regs->psw.amode = 1; \ (_regs)->psw.AMASK = AMASK64; \ (_addr) ^= 1; \ } else if ((_addr) & 0x80000000) { \ (_regs)->psw.amode64 = 0; \ (_regs)->psw.amode = 1; \ (_regs)->psw.AMASK = AMASK31; \ } else { \ (_regs)->psw.amode64 = (_regs)->psw.amode = 0; \ (_regs)->psw.AMASK = AMASK24; \ } \ } while (0) #else /* !defined(FEATURE_ESAME) */ #define SET_ADDRESSING_MODE(_regs, _addr) \ do { \ if ((_addr) & 0x80000000) { \ (_regs)->psw.amode = 1; \ (_regs)->psw.AMASK = AMASK31; \ } else { \ (_regs)->psw.amode = 0; \ (_regs)->psw.AMASK = AMASK24; \ } \ } while (0) #endif #undef HFPREG_CHECK #undef HFPREG2_CHECK #undef HFPODD_CHECK #undef HFPODD2_CHECK #undef FPR2I #undef FPREX #if defined(FEATURE_BASIC_FP_EXTENSIONS) #if defined(_FEATURE_SIE) /* Program check if BFP instruction is executed when AFP control is zero */ #define BFPINST_CHECK(_regs) \ if( !((_regs)->CR(0) & CR0_AFP) \ || (SIE_MODE((_regs)) && !((_regs)->hostregs->CR(0) & CR0_AFP)) ) { \ (_regs)->dxc = DXC_BFP_INSTRUCTION; \ (_regs)->program_interrupt( (_regs), PGM_DATA_EXCEPTION); \ } /* Program check if DFP instruction is executed when AFP control is zero */ #define DFPINST_CHECK(_regs) \ if( !((_regs)->CR(0) & CR0_AFP) \ || (SIE_MODE((_regs)) && !((_regs)->hostregs->CR(0) & CR0_AFP)) ) { \ (_regs)->dxc = DXC_DFP_INSTRUCTION; \ (_regs)->program_interrupt( (_regs), PGM_DATA_EXCEPTION); \ } /* Program check if r1 is not 0, 2, 4, or 6 */ #define HFPREG_CHECK(_r, _regs) \ if( !((_regs)->CR(0) & CR0_AFP) \ || (SIE_MODE((_regs)) && !((_regs)->hostregs->CR(0) & CR0_AFP)) ) { \ if( (_r) & 9 ) { \ (_regs)->dxc = DXC_AFP_REGISTER; \ (_regs)->program_interrupt( (_regs), PGM_DATA_EXCEPTION); \ } \ } /* Program check if r1 and r2 are not 0, 2, 4, or 6 */ #define HFPREG2_CHECK(_r1, _r2, _regs) \ if( !((_regs)->CR(0) & CR0_AFP) \ || (SIE_MODE((_regs)) && !((_regs)->hostregs->CR(0) & CR0_AFP)) ) { \ if( ((_r1) & 9) || ((_r2) & 9) ) { \ (_regs)->dxc = DXC_AFP_REGISTER; \ (_regs)->program_interrupt( (_regs), PGM_DATA_EXCEPTION); \ } \ } /* Program check if r1 is not 0 or 4 */ #define HFPODD_CHECK(_r, _regs) \ if( (_r) & 2 ) \ (_regs)->program_interrupt( (_regs), PGM_SPECIFICATION_EXCEPTION); \ else if( !((_regs)->CR(0) & CR0_AFP) \ || (SIE_MODE((_regs)) && !((_regs)->hostregs->CR(0) & CR0_AFP)) ) { \ if( (_r) & 9 ) { \ (_regs)->dxc = DXC_AFP_REGISTER; \ (_regs)->program_interrupt( (_regs), PGM_DATA_EXCEPTION); \ } \ } /* Program check if r1 and r2 are not 0 or 4 */ #define HFPODD2_CHECK(_r1, _r2, _regs) \ if( ((_r1) & 2) || ((_r2) & 2) ) \ (_regs)->program_interrupt( (_regs), PGM_SPECIFICATION_EXCEPTION); \ else if( !((_regs)->CR(0) & CR0_AFP) \ || (SIE_MODE((_regs)) && !((_regs)->hostregs->CR(0) & CR0_AFP)) ) { \ if( ((_r1) & 9) || ((_r2) & 9) ) { \ (_regs)->dxc = DXC_AFP_REGISTER; \ (_regs)->program_interrupt( (_regs), PGM_DATA_EXCEPTION); \ } \ } #else /*!defined(_FEATURE_SIE)*/ /* Program check if BFP instruction is executed when AFP control is zero */ #define BFPINST_CHECK(_regs) \ if( !((_regs)->CR(0) & CR0_AFP) ) { \ (_regs)->dxc = DXC_BFP_INSTRUCTION; \ (_regs)->program_interrupt( (_regs), PGM_DATA_EXCEPTION); \ } /* Program check if DFP instruction is executed when AFP control is zero */ #define DFPINST_CHECK(_regs) \ if( !((_regs)->CR(0) & CR0_AFP) ) { \ (_regs)->dxc = DXC_DFP_INSTRUCTION; \ (_regs)->program_interrupt( (_regs), PGM_DATA_EXCEPTION); \ } /* Program check if r1 is not 0, 2, 4, or 6 */ #define HFPREG_CHECK(_r, _regs) \ if( !((_regs)->CR(0) & CR0_AFP) ) { \ if( (_r) & 9 ) { \ (_regs)->dxc = DXC_AFP_REGISTER; \ (_regs)->program_interrupt( (_regs), PGM_DATA_EXCEPTION); \ } \ } /* Program check if r1 and r2 are not 0, 2, 4, or 6 */ #define HFPREG2_CHECK(_r1, _r2, _regs) \ if( !((_regs)->CR(0) & CR0_AFP) ) { \ if( ((_r1) & 9) || ((_r2) & 9) ) { \ (_regs)->dxc = DXC_AFP_REGISTER; \ (_regs)->program_interrupt( (_regs), PGM_DATA_EXCEPTION); \ } \ } /* Program check if r1 is not 0 or 4 */ #define HFPODD_CHECK(_r, _regs) \ if( (_r) & 2 ) \ (_regs)->program_interrupt( (_regs), PGM_SPECIFICATION_EXCEPTION); \ else if( !((_regs)->CR(0) & CR0_AFP) ) { \ if( (_r) & 9 ) { \ (_regs)->dxc = DXC_AFP_REGISTER; \ (_regs)->program_interrupt( (_regs), PGM_DATA_EXCEPTION); \ } \ } /* Program check if r1 and r2 are not 0 or 4 */ #define HFPODD2_CHECK(_r1, _r2, _regs) \ if( ((_r1) & 2) || ((_r2) & 2) ) \ (_regs)->program_interrupt( (_regs), PGM_SPECIFICATION_EXCEPTION); \ else if( !((_regs)->CR(0) & CR0_AFP) ) { \ if( ((_r1) & 9) || ((_r2) & 9) ) { \ (_regs)->dxc = DXC_AFP_REGISTER; \ (_regs)->program_interrupt( (_regs), PGM_DATA_EXCEPTION); \ } \ } #endif /*!defined(_FEATURE_SIE)*/ /* Convert fpr to index */ #define FPR2I(_r) \ ((_r) << 1) /* Offset of extended register */ #define FPREX 4 #else /*!defined(FEATURE_BASIC_FP_EXTENSIONS)*/ /* Program check if r1 is not 0, 2, 4, or 6 */ #define HFPREG_CHECK(_r, _regs) \ if( (_r) & 9 ) \ (_regs)->program_interrupt( (_regs), PGM_SPECIFICATION_EXCEPTION) /* Program check if r1 and r2 are not 0, 2, 4, or 6 */ #define HFPREG2_CHECK(_r1, _r2, _regs) \ if( ((_r1) & 9) || ((_r2) & 9) ) \ (_regs)->program_interrupt( (_regs), PGM_SPECIFICATION_EXCEPTION) /* Program check if r1 is not 0 or 4 */ #define HFPODD_CHECK(_r, _regs) \ if( (_r) & 11 ) \ (_regs)->program_interrupt( (_regs), PGM_SPECIFICATION_EXCEPTION) /* Program check if r1 and r2 are not 0 or 4 */ #define HFPODD2_CHECK(_r1, _r2, _regs) \ if( ((_r1) & 11) || ((_r2) & 11) ) \ (_regs)->program_interrupt( (_regs), PGM_SPECIFICATION_EXCEPTION) /* Convert fpr to index */ #define FPR2I(_r) \ (_r) /* Offset of extended register */ #define FPREX 2 #endif /*!defined(FEATURE_BASIC_FP_EXTENSIONS)*/ #define TLBIX(_addr) (((VADR_L)(_addr) >> TLB_PAGESHIFT) & TLB_MASK) #define MAINADDR(_main, _addr) \ (BYTE*)((uintptr_t)(_main) ^ (uintptr_t)(_addr)) #define NEW_MAINADDR(_regs, _addr, _aaddr) \ (BYTE*)((uintptr_t)((_regs)->mainstor \ + (uintptr_t)(_aaddr)) \ ^ (uintptr_t)((_addr) & TLB_PAGEMASK)) /* Perform invalidation after storage key update. * If the REF or CHANGE bit is turned off for an absolute * address then we need to invalidate any cached entries * for that address on *all* CPUs. * FIXME: Synchronization, esp for the CHANGE bit, should * be tighter than what is provided here. */ #define STORKEY_INVALIDATE(_regs, _n) \ do { \ BYTE *mn; \ mn = (_regs)->mainstor + ((_n) & PAGEFRAME_PAGEMASK); \ ARCH_DEP(invalidate_tlbe)((_regs), mn); \ if (sysblk.cpus > 1) { \ int i; \ OBTAIN_INTLOCK ((_regs)); \ for (i = 0; i < HI_CPU; i++) { \ if (IS_CPU_ONLINE(i) && i != (_regs)->cpuad) { \ if ( sysblk.waiting_mask & CPU_BIT(i) ) \ ARCH_DEP(invalidate_tlbe)(sysblk.regs[i], mn); \ else { \ ON_IC_INTERRUPT(sysblk.regs[i]); \ if (!sysblk.regs[i]->invalidate) { \ sysblk.regs[i]->invalidate = 1; \ sysblk.regs[i]->invalidate_main = mn; \ } else \ sysblk.regs[i]->invalidate_main = NULL; \ } \ } \ } \ RELEASE_INTLOCK((_regs)); \ } \ } while (0) #if defined(INLINE_STORE_FETCH_ADDR_CHECK) #define FETCH_MAIN_ABSOLUTE(_addr, _regs, _len) \ ARCH_DEP(fetch_main_absolute)((_addr), (_regs), (_len)) #else #define FETCH_MAIN_ABSOLUTE(_addr, _regs, _len) \ ARCH_DEP(fetch_main_absolute)((_addr), (_regs)) #endif #define INST_UPDATE_PSW(_regs, _len, _ilc) \ do { \ if (_len) (_regs)->ip += (_len); \ if (_ilc) (_regs)->psw.ilc = (_ilc); \ } while(0) /* Instruction decoders */ /* * A decoder is placed at the start of each instruction. The purpose * of a decoder is to extract the operand fields according to the * instruction format; to increment the instruction address (IA) field * of the PSW by 2, 4, or 6 bytes; and to set the instruction length * code (ILC) field of the PSW in case a program check occurs. * * Certain decoders have additional forms with 0 and _B suffixes. * - the 0 suffix version does not update the PSW ILC. * - the _B suffix version updates neither the PSW ILC nor the PSW IA. * * The "0" versions of the decoders are chosen whenever we know * that past this point, no program interrupt will be generated * (like most general instructions when no storage access is needed) * therefore needing simpler prologue code. * The "_B" versions for some of the decoders are intended for * "branch" type operations where updating the PSW IA to IA+ILC * should only be done after the branch is deemed impossible. */ #undef DECODER_TEST_RRE #define DECODER_TEST_RRF_R #define DECODER_TEST_RRF_M #define DECODER_TEST_RRF_M4 #define DECODER_TEST_RRF_RM #define DECODER_TEST_RRF_MM #define DECODER_TEST_RRR #undef DECODER_TEST_RX #define DECODER_TEST_RXE #define DECODER_TEST_RXF #define DECODER_TEST_RXY #undef DECODER_TEST_RS #define DECODER_TEST_RSY #undef DECODER_TEST_RSL #undef DECODER_TEST_RSI #undef DECODER_TEST_RI #define DECODER_TEST_RIL #define DECODER_TEST_RIL_A #undef DECODER_TEST_RIS #undef DECODER_TEST_RRS #undef DECODER_TEST_SI #define DECODER_TEST_SIY #undef DECODER_TEST_SIL #undef DECODER_TEST_S #define DECODER_TEST_SS #define DECODER_TEST_SS_L #define DECODER_TEST_SSE #define DECODER_TEST_SSF /* E implied operands and extended op code */ #undef E #define E(_inst,_regs) E_DECODER((_inst), (_regs), 2, 2) #define E_DECODER(_inst, _regs, _len, _ilc) \ { \ INST_UPDATE_PSW((_regs), (_len), (_ilc)); \ } /* RR register to register */ #undef RR #undef RR0 #undef RR_B #define RR(_inst, _regs, _r1, _r2) \ RR_DECODER(_inst, _regs, _r1, _r2, 2, 2) #define RR0(_inst, _regs, _r1, _r2) \ RR_DECODER(_inst, _regs, _r1, _r2, 2, 0) #define RR_B(_inst, _regs, _r1, _r2) \ RR_DECODER(_inst, _regs, _r1, _r2, 0, 0) #define RR_DECODER(_inst, _regs, _r1, _r2, _len, _ilc) \ { \ int i = (_inst)[1]; \ (_r1) = i >> 4; \ (_r2) = i & 0x0F; \ INST_UPDATE_PSW((_regs), (_len), (_ilc)); \ } /* RR special format for SVC instruction */ #undef RR_SVC #define RR_SVC(_inst, _regs, _svc) \ RR_SVC_DECODER(_inst, _regs, _svc, 2, 2) #define RR_SVC_DECODER(_inst, _regs, _svc, _ilc, _len) \ { \ (_svc) = (_inst)[1]; \ INST_UPDATE_PSW((_regs), (_ilc), (_len)); \ } /* RRE register to register with extended op code */ #undef RRE #undef RRE0 #undef RRE_B #if !defined(DECODER_TEST)&&!defined(DECODER_TEST_RRE) #define RRE(_inst, _regs, _r1, _r2) \ RRE_DECODER(_inst, _regs, _r1, _r2, 4, 4) #define RRE0(_inst, _regs, _r1, _r2) \ RRE_DECODER(_inst, _regs, _r1, _r2, 4, 0) #define RRE_B(_inst, _regs, _r1, _r2) \ RRE_DECODER(_inst, _regs, _r1, _r2, 0, 0) #else #define RRE(_inst, _regs, _r1, _r2) \ RRE_DECODER_TEST(_inst, _regs, _r1, _r2, 4, 4) #define RRE0(_inst, _regs, _r1, _r2) \ RRE_DECODER_TEST(_inst, _regs, _r1, _r2, 4, 0) #define RRE_B(_inst, _regs, _r1, _r2) \ RRE_DECODER_TEST(_inst, _regs, _r1, _r2, 0, 0) #endif #define RRE_DECODER(_inst, _regs, _r1, _r2, _len, _ilc) \ { \ int i = (_inst)[3]; \ (_r1) = i >> 4; \ (_r2) = i & 0xf; \ INST_UPDATE_PSW((_regs), (_len), (_ilc)); \ } #define RRE_DECODER_TEST(_inst, _regs, _r1, _r2, _len, _ilc) \ { \ int i = (_inst)[3]; \ (_r2) = i & 0xf; \ (_r1) = i >> 4; \ INST_UPDATE_PSW((_regs), (_len), (_ilc)); \ } /* RRF register to register with additional R3 field */ #undef RRF_R #if !defined(DECODER_TEST)&&!defined(DECODER_TEST_RRF_R) #define RRF_R(_inst, _regs, _r1, _r2, _r3) \ RRF_R_DECODER(_inst, _regs, _r1, _r2, _r3, 4, 4) #else #define RRF_R(_inst, _regs, _r1, _r2, _r3) \ RRF_R_DECODER_TEST(_inst, _regs, _r1, _r2, _r3, 4, 4) #endif #define RRF_R_DECODER(_inst, _regs, _r1, _r2, _r3, _len, _ilc) \ { \ int i = (_inst)[2]; \ (_r1) = i >> 4; \ i = (_inst)[3]; \ (_r3) = i >> 4; \ (_r2) = i & 0xf; \ INST_UPDATE_PSW((_regs), (_len), (_ilc)); \ } #define RRF_R_DECODER_TEST(_inst, _regs, _r1, _r2, _r3, _len, _ilc) \ { U32 temp = fetch_fw(_inst); \ (_r2) = (temp ) & 0xf; \ (_r3) = (temp >> 4) & 0xf; \ (_r1) = (temp >> 12) & 0xf; \ INST_UPDATE_PSW((_regs), (_len), (_ilc)); \ } /* RRF register to register with additional M3 field */ #undef RRF_M #if !defined(DECODER_TEST)&&!defined(DECODER_TEST_RRF_M) #define RRF_M(_inst, _regs, _r1, _r2, _m3) \ RRF_M_DECODER(_inst, _regs, _r1, _r2, _m3, 4, 4) #else #define RRF_M(_inst, _regs, _r1, _r2, _m3) \ RRF_M_DECODER_TEST(_inst, _regs, _r1, _r2, _m3, 4, 4) #endif #define RRF_M_DECODER(_inst, _regs, _r1, _r2, _m3, _len, _ilc) \ { \ int i = (_inst)[2]; \ (_m3) = i >> 4; \ i = (_inst)[3]; \ (_r1) = i >> 4; \ (_r2) = i & 0xf; \ INST_UPDATE_PSW((_regs), (_len), (_ilc)); \ } #define RRF_M_DECODER_TEST(_inst, _regs, _r1, _r2, _m3, _len, _ilc) \ { U32 temp = fetch_fw(_inst); \ (_m3) = (temp >> 12) & 0xf; \ (_r2) = (temp ) & 0xf; \ (_r1) = (temp >> 4) & 0xf; \ INST_UPDATE_PSW((_regs), (_len), (_ilc)); \ } /* RRF register to register with additional M4 field */ #undef RRF_M4 #if !defined(DECODER_TEST)&&!defined(DECODER_TEST_RRF_M4) #define RRF_M4(_inst, _regs, _r1, _r2, _m4) \ RRF_M4_DECODER(_inst, _regs, _r1, _r2, _m4, 4, 4) #else #define RRF_M4(_inst, _regs, _r1, _r2, _m4) \ RRF_M4_DECODER_TEST(_inst, _regs, _r1, _r2, _m4, 4, 4) #endif #define RRF_M4_DECODER(_inst, _regs, _r1, _r2, _m4, _len, _ilc) \ { \ int i = (_inst)[2]; \ (_m4) = i & 0xf; \ i = (_inst)[3]; \ (_r1) = i >> 4; \ (_r2) = i & 0xf; \ INST_UPDATE_PSW((_regs), (_len), (_ilc)); \ } #define RRF_M4_DECODER_TEST(_inst, _regs, _r1, _r2, _m4, _len, _ilc) \ { U32 temp = fetch_fw(_inst); \ (_m4) = (temp >> 8) & 0xf; \ (_r2) = (temp ) & 0xf; \ (_r1) = (temp >> 4) & 0xf; \ INST_UPDATE_PSW((_regs), (_len), (_ilc)); \ } /* RRF register to register with additional R3 and M4 fields */ #undef RRF_RM #if !defined(DECODER_TEST)&&!defined(DECODER_TEST_RRF_RM) #define RRF_RM(_inst, _regs, _r1, _r2, _r3, _m4) \ RRF_RM_DECODER(_inst, _regs, _r1, _r2, _r3, _m4, 4, 4) #else #define RRF_RM(_inst, _regs, _r1, _r2, _r3, _m4) \ RRF_RM_DECODER_TEST(_inst, _regs, _r1, _r2, _r3, _m4, 4, 4) #endif #define RRF_RM_DECODER(_inst, _regs, _r1, _r2, _r3, _m4, _len, _ilc) \ { \ int i = (_inst)[2]; \ (_r3) = i >> 4; \ (_m4) = i & 0xf; \ i = (_inst)[3]; \ (_r1) = i >> 4; \ (_r2) = i & 0xf; \ INST_UPDATE_PSW((_regs), (_len), (_ilc)); \ } #define RRF_RM_DECODER_TEST(_inst, _regs, _r1, _r2, _r3, _m4, _len, _ilc) \ { U32 temp = fetch_fw(_inst); \ (_r3) = (temp >> 12) & 0xf; \ (_m4) = (temp >> 8) & 0xf; \ (_r2) = (temp ) & 0xf; \ (_r1) = (temp >> 4) & 0xf; \ INST_UPDATE_PSW((_regs), (_len), (_ilc)); \ } /* RRF register to register with additional M3 and M4 fields */ #undef RRF_MM #if !defined(DECODER_TEST)&&!defined(DECODER_TEST_RRF_MM) #define RRF_MM(_inst, _regs, _r1, _r2, _m3, _m4) \ RRF_MM_DECODER(_inst, _regs, _r1, _r2, _m3, _m4, 4, 4) #else #define RRF_MM(_inst, _regs, _r1, _r2, _m3, _m4) \ RRF_MM_DECODER_TEST(_inst, _regs, _r1, _r2, _m3, _m4, 4, 4) #endif #define RRF_MM_DECODER(_inst, _regs, _r1, _r2, _m3, _m4, _len, _ilc) \ { \ int i = (_inst)[2]; \ (_m3) = i >> 4; \ (_m4) = i & 0xf; \ i = (_inst)[3]; \ (_r1) = i >> 4; \ (_r2) = i & 0xf; \ INST_UPDATE_PSW((_regs), (_len), (_ilc)); \ } #define RRF_MM_DECODER_TEST(_inst, _regs, _r1, _r2, _m3, _m4, _len, _ilc) \ { U32 temp = fetch_fw(_inst); \ (_m3) = (temp >> 12) & 0xf; \ (_m4) = (temp >> 8) & 0xf; \ (_r2) = (temp ) & 0xf; \ (_r1) = (temp >> 4) & 0xf; \ INST_UPDATE_PSW((_regs), (_len), (_ilc)); \ } /* RRR register to register with register */ #undef RRR #if !defined(DECODER_TEST)&&!defined(DECODER_TEST_RRR) #define RRR(_inst, _regs, _r1, _r2, _r3) \ RRR_DECODER(_inst, _regs, _r1, _r2, _r3, 4, 4) #else #define RRR(_inst, _regs, _r1, _r2, _r3) \ RRR_DECODER_TEST(_inst, _regs, _r1, _r2, _r3, 4, 4) #endif #define RRR_DECODER(_inst, _regs, _r1, _r2, _r3, _len, _ilc) \ { \ int i = (_inst)[2]; \ (_r3) = i >> 4; \ i = (_inst)[3]; \ (_r1) = i >> 4; \ (_r2) = i & 0xf; \ INST_UPDATE_PSW((_regs), (_len), (_ilc)); \ } #define RRR_DECODER_TEST(_inst, _regs, _r1, _r2, _r3, _len, _ilc) \ { U32 temp = fetch_fw(_inst); \ (_r3) = (temp >> 12) & 0xf; \ (_r2) = (temp ) & 0xf; \ (_r1) = (temp >> 4) & 0xf; \ INST_UPDATE_PSW((_regs), (_len), (_ilc)); \ } /* RX register and indexed storage */ #undef RX #undef RX0 #undef RX_B #if !defined(DECODER_TEST)&&!defined(DECODER_TEST_RX) #define RX(_inst, _regs, _r1, _b2, _effective_addr2) \ RX_DECODER(_inst, _regs, _r1, _b2, _effective_addr2, 4, 4) #define RX0(_inst, _regs, _r1, _b2, _effective_addr2) \ RX_DECODER(_inst, _regs, _r1, _b2, _effective_addr2, 4, 0) #define RX_B(_inst, _regs, _r1, _b2, _effective_addr2) \ RX_DECODER(_inst, _regs, _r1, _b2, _effective_addr2, 0, 0) #else #define RX(_inst, _regs, _r1, _b2, _effective_addr2) \ RX_DECODER_TEST(_inst, _regs, _r1, _b2, _effective_addr2, 4, 4) #define RX0(_inst, _regs, _r1, _b2, _effective_addr2) \ RX_DECODER_TEST(_inst, _regs, _r1, _b2, _effective_addr2, 4, 0) #define RX_B(_inst, _regs, _r1, _b2, _effective_addr2) \ RX_DECODER_TEST(_inst, _regs, _r1, _b2, _effective_addr2, 0, 0) #endif #define RX_DECODER(_inst, _regs, _r1, _b2, _effective_addr2, _len, _ilc) \ { U32 temp = fetch_fw(_inst); \ (_r1) = (temp >> 20) & 0xf; \ (_b2) = (temp >> 16) & 0xf; \ (_effective_addr2) = temp & 0xfff; \ if((_b2)) \ (_effective_addr2) += (_regs)->GR((_b2)); \ (_b2) = (temp >> 12) & 0xf; \ if((_b2)) \ (_effective_addr2) += (_regs)->GR((_b2)); \ if ((_len)) \ (_effective_addr2) &= ADDRESS_MAXWRAP((_regs)); \ INST_UPDATE_PSW((_regs), (_len), (_ilc)); \ } #define RX_DECODER_TEST(_inst, _regs, _r1, _b2, _effective_addr2, _len, _ilc) \ { U32 temp = fetch_fw(_inst); \ (_effective_addr2) = temp & 0xfff; \ (_b2) = (temp >> 16) & 0xf; \ if((_b2)) \ (_effective_addr2) += (_regs)->GR((_b2)); \ (_b2) = (temp >> 12) & 0xf; \ if((_b2)) \ (_effective_addr2) += (_regs)->GR((_b2)); \ if ((_len)) \ (_effective_addr2) &= ADDRESS_MAXWRAP((_regs)); \ (_r1) = (temp >> 20) & 0xf; \ INST_UPDATE_PSW((_regs), (_len), (_ilc)); \ } /* RX_BC register and indexed storage - optimized for BC */ #undef RX_BC #define RX_BC(_inst, _regs, _b2, _effective_addr2) \ RX_BC_DECODER(_inst, _regs, _b2, _effective_addr2, 0, 0) #define RX_BC_DECODER(_inst, _regs, _b2, _effective_addr2, _len, _ilc) \ { U32 temp = fetch_fw(_inst); \ (_effective_addr2) = temp & 0xfff; \ (_b2) = (temp >> 16) & 0xf; \ if(unlikely((_b2))) \ (_effective_addr2) += (_regs)->GR((_b2)); \ (_b2) = (temp >> 12) & 0xf; \ if(likely((_b2))) \ (_effective_addr2) += (_regs)->GR((_b2)); \ } /* RXE register and indexed storage with extended op code */ #undef RXE #if !defined(DECODER_TEST)&&!defined(DECODER_TEST_RXE) #define RXE(_inst, _regs, _r1, _b2, _effective_addr2) \ RXE_DECODER(_inst, _regs, _r1, _b2, _effective_addr2, 6, 6) #else #define RXE(_inst, _regs, _r1, _b2, _effective_addr2) \ RXE_DECODER_TEST(_inst, _regs, _r1, _b2, _effective_addr2, 6, 6) #endif #define RXE_DECODER(_inst, _regs, _r1, _b2, _effective_addr2, _len, _ilc) \ { U32 temp = fetch_fw(_inst); \ (_r1) = (temp >> 20) & 0xf; \ (_b2) = (temp >> 16) & 0xf; \ (_effective_addr2) = temp & 0xfff; \ if((_b2)) \ { \ (_effective_addr2) += (_regs)->GR((_b2)); \ (_effective_addr2) &= ADDRESS_MAXWRAP((_regs)); \ } \ (_b2) = (temp >> 12) & 0xf; \ if((_b2)) \ { \ (_effective_addr2) += (_regs)->GR((_b2)); \ (_effective_addr2) &= ADDRESS_MAXWRAP((_regs)); \ } \ INST_UPDATE_PSW((_regs), (_len), (_ilc)); \ } #define RXE_DECODER_TEST(_inst, _regs, _r1, _b2, _effective_addr2, _len, _ilc) \ { U32 temp = fetch_fw(_inst); \ (_effective_addr2) = temp & 0xfff; \ (_b2) = (temp >> 16) & 0xf; \ if((_b2)) \ (_effective_addr2) += (_regs)->GR((_b2)); \ (_b2) = (temp >> 12) & 0xf; \ if((_b2)) \ (_effective_addr2) += (_regs)->GR((_b2)); \ (_effective_addr2) &= ADDRESS_MAXWRAP((_regs)); \ (_r1) = (temp >> 20) & 0xf; \ INST_UPDATE_PSW((_regs), (_len), (_ilc)); \ } /* RXF register and indexed storage with ext.opcode and additional R3 */ #undef RXF #if !defined(DECODER_TEST)&&!defined(DECODER_TEST_RXF) #define RXF(_inst, _regs, _r1, _r3, _b2, _effective_addr2) \ RXF_DECODER(_inst, _regs, _r1, _r3, _b2, _effective_addr2, 6, 6) #else #define RXF(_inst, _regs, _r1, _r3, _b2, _effective_addr2) \ RXF_DECODER_TEST(_inst, _regs, _r1, _r3, _b2, _effective_addr2, 6, 6) #endif #define RXF_DECODER(_inst, _regs, _r1, _r3, _b2, _effective_addr2, _len, _ilc) \ { U32 temp; \ (_r1) = (_inst)[4] >> 4; \ memcpy (&temp, (_inst), 4); \ temp = CSWAP32(temp); \ (_r3) = (temp >> 20) & 0xf; \ (_b2) = (temp >> 16) & 0xf; \ (_effective_addr2) = temp & 0xfff; \ if((_b2)) \ { \ (_effective_addr2) += (_regs)->GR((_b2)); \ (_effective_addr2) &= ADDRESS_MAXWRAP((_regs)); \ } \ (_b2) = (temp >> 12) & 0xf; \ if((_b2)) \ { \ (_effective_addr2) += (_regs)->GR((_b2)); \ (_effective_addr2) &= ADDRESS_MAXWRAP((_regs)); \ } \ INST_UPDATE_PSW((_regs), (_len), (_ilc)); \ } #define RXF_DECODER_TEST(_inst, _regs, _r1, _r3, _b2, _effective_addr2, _len, _ilc) \ { U32 temp = fetch_fw(_inst); \ (_effective_addr2) = temp & 0xfff; \ (_b2) = (temp >> 16) & 0xf; \ if((_b2)) \ (_effective_addr2) += (_regs)->GR((_b2)); \ (_b2) = (temp >> 12) & 0xf; \ if((_b2)) \ (_effective_addr2) += (_regs)->GR((_b2)); \ (_effective_addr2) &= ADDRESS_MAXWRAP((_regs)); \ (_r3) = (temp >> 20) & 0xf; \ (_r1) = (_inst)[4] >> 4; \ INST_UPDATE_PSW((_regs), (_len), (_ilc)); \ } /* RXY register and indexed storage with extended op code and long displacement */ #undef RXY #undef RXY0 #undef RXY_B #if defined(FEATURE_LONG_DISPLACEMENT) #if !defined(DECODER_TEST)&&!defined(DECODER_TEST_RXY) #define RXY(_inst, _regs, _r1, _b2, _effective_addr2) \ RXY_DECODER_LD(_inst, _regs, _r1, _b2, _effective_addr2, 6, 6) #define RXY0(_inst, _regs, _r1, _b2, _effective_addr2) \ RXY_DECODER_LD(_inst, _regs, _r1, _b2, _effective_addr2, 6, 0) #define RXY_B(_inst, _regs, _r1, _b2, _effective_addr2) \ RXY_DECODER_LD(_inst, _regs, _r1, _b2, _effective_addr2, 0, 0) #else #define RXY(_inst, _regs, _r1, _b2, _effective_addr2) \ RXY_DECODER_LD_TEST(_inst, _regs, _r1, _b2, _effective_addr2, 6, 6) #define RXY0(_inst, _regs, _r1, _b2, _effective_addr2) \ RXY_DECODER_LD_TEST(_inst, _regs, _r1, _b2, _effective_addr2, 6, 0) #define RXY_B(_inst, _regs, _r1, _b2, _effective_addr2) \ RXY_DECODER_LD_TEST(_inst, _regs, _r1, _b2, _effective_addr2, 0, 0) #endif #else /* !defined(FEATURE_LONG_DISPLACEMENT) */ #if !defined(DECODER_TEST)&&!defined(DECODER_TEST_RXY) #define RXY(_inst, _regs, _r1, _b2, _effective_addr2) \ RXY_DECODER(_inst, _regs, _r1, _b2, _effective_addr2, 6, 6) #define RXY0(_inst, _regs, _r1, _b2, _effective_addr2) \ RXY_DECODER(_inst, _regs, _r1, _b2, _effective_addr2, 6, 0) #define RXY_B(_inst, _regs, _r1, _b2, _effective_addr2) \ RXY_DECODER(_inst, _regs, _r1, _b2, _effective_addr2, 0, 0) #else #define RXY(_inst, _regs, _r1, _b2, _effective_addr2) \ RXY_DECODER_TEST(_inst, _regs, _r1, _b2, _effective_addr2, 6, 6) #define RXY0(_inst, _regs, _r1, _b2, _effective_addr2) \ RXY_DECODER_TEST(_inst, _regs, _r1, _b2, _effective_addr2, 6, 0) #define RXY_B(_inst, _regs, _r1, _b2, _effective_addr2) \ RXY_DECODER_TEST(_inst, _regs, _r1, _b2, _effective_addr2, 0, 0) #endif #endif #define RXY_DECODER_LD(_inst, _regs, _r1, _b2, _effective_addr2, _len, _ilc) \ { U32 temp; S32 temp2; int tempx; \ temp = fetch_fw(_inst); \ (_r1) = (temp >> 20) & 0xf; \ tempx = (temp >> 16) & 0xf; \ (_b2) = (temp >> 12) & 0xf; \ temp2 = (_inst[4] << 12) | (temp & 0xfff); \ if (temp2 & 0x80000) temp2 |= 0xfff00000; \ (_effective_addr2) = \ (tempx ? (_regs)->GR(tempx) : (GREG)0) + \ ((_b2) ? (_regs)->GR((_b2)) : (GREG)0) + \ temp2; \ if ((_len)) \ (_effective_addr2) &= ADDRESS_MAXWRAP((_regs)); \ INST_UPDATE_PSW((_regs), (_len), (_ilc)); \ } #define RXY_DECODER_LD_TEST(_inst, _regs, _r1, _b2, _effective_addr2, _len, _ilc) \ { U32 temp; S32 disp2; \ temp = fetch_fw(_inst); \ (_effective_addr2) = 0; \ (_b2) = (temp >> 16) & 0xf; \ if ((_b2)) \ (_effective_addr2) += (_regs)->GR((_b2)); \ (_b2) = (temp >> 12) & 0xf; \ if ((_b2)) \ (_effective_addr2) += (_regs)->GR((_b2)); \ disp2 = temp & 0xfff; \ if (unlikely((_inst)[4])) { \ disp2 |= (_inst[4] << 12); \ if (disp2 & 0x80000) disp2 |= 0xfff00000; \ } \ (_effective_addr2) += disp2; \ if ((_len)) \ (_effective_addr2) &= ADDRESS_MAXWRAP((_regs)); \ (_r1) = (temp >> 20) & 0xf; \ INST_UPDATE_PSW((_regs), (_len), (_ilc)); \ } #define RXY_DECODER(_inst, _regs, _r1, _b2, _effective_addr2, _len, _ilc) \ { U32 temp = fetch_fw(_inst); \ (_r1) = (temp >> 20) & 0xf; \ (_b2) = (temp >> 16) & 0xf; \ (_effective_addr2) = temp & 0xfff; \ if((_b2)) \ { \ (_effective_addr2) += (_regs)->GR((_b2)); \ if ((_len)) \ (_effective_addr2) &= ADDRESS_MAXWRAP((_regs)); \ } \ (_b2) = (temp >> 12) & 0xf; \ if((_b2)) \ { \ (_effective_addr2) += (_regs)->GR((_b2)); \ if ((_len)) \ (_effective_addr2) &= ADDRESS_MAXWRAP((_regs)); \ } \ INST_UPDATE_PSW((_regs), (_len), (_ilc)); \ } #define RXY_DECODER_TEST(_inst, _regs, _r1, _b2, _effective_addr2, _len, _ilc) \ { U32 temp = fetch_fw(_inst); \ (_effective_addr2) = temp & 0xfff; \ (_b2) = (temp >> 16) & 0xf; \ if((_b2)) \ (_effective_addr2) += (_regs)->GR((_b2)); \ (_b2) = (temp >> 12) & 0xf; \ if((_b2)) \ (_effective_addr2) += (_regs)->GR((_b2)); \ if ((_len)) \ (_effective_addr2) &= ADDRESS_MAXWRAP((_regs)); \ (_r1) = (temp >> 20) & 0xf; \ INST_UPDATE_PSW((_regs), (_len), (_ilc)); \ } /* RS register and storage with additional R3 or M3 field */ #undef RS #undef RS0 #undef RS_B #if !defined(DECODER_TEST)&&!defined(DECODER_TEST_RS) #define RS(_inst, _regs, _r1, _r3, _b2, _effective_addr2) \ RS_DECODER(_inst, _regs, _r1, _r3, _b2, _effective_addr2, 4, 4) #define RS0(_inst, _regs, _r1, _r3, _b2, _effective_addr2) \ RS_DECODER(_inst, _regs, _r1, _r3, _b2, _effective_addr2, 4, 0) #define RS_B(_inst, _regs, _r1, _r3, _b2, _effective_addr2) \ RS_DECODER(_inst, _regs, _r1, _r3, _b2, _effective_addr2, 0, 0) #else #define RS(_inst, _regs, _r1, _r3, _b2, _effective_addr2) \ RS_DECODER_TEST(_inst, _regs, _r1, _r3, _b2, _effective_addr2, 4, 4) #define RS0(_inst, _regs, _r1, _r3, _b2, _effective_addr2) \ RS_DECODER_TEST(_inst, _regs, _r1, _r3, _b2, _effective_addr2, 4, 0) #define RS_B(_inst, _regs, _r1, _r3, _b2, _effective_addr2) \ RS_DECODER_TEST(_inst, _regs, _r1, _r3, _b2, _effective_addr2, 0, 0) #endif #define RS_DECODER(_inst, _regs, _r1, _r3, _b2, _effective_addr2, _len, _ilc) \ { U32 temp = fetch_fw(_inst); \ (_r1) = (temp >> 20) & 0xf; \ (_r3) = (temp >> 16) & 0xf; \ (_b2) = (temp >> 12) & 0xf; \ (_effective_addr2) = temp & 0xfff; \ if((_b2)) \ { \ (_effective_addr2) += (_regs)->GR((_b2)); \ if ((_len)) \ (_effective_addr2) &= ADDRESS_MAXWRAP((_regs)); \ } \ INST_UPDATE_PSW((_regs), (_len), (_ilc)); \ } #define RS_DECODER_TEST(_inst, _regs, _r1, _r3, _b2, _effective_addr2, _len, _ilc) \ { U32 temp = fetch_fw(_inst); \ (_effective_addr2) = temp & 0xfff; \ (_b2) = (temp >> 12) & 0xf; \ if((_b2)) \ { \ (_effective_addr2) += (_regs)->GR((_b2)); \ if ((_len)) \ (_effective_addr2) &= ADDRESS_MAXWRAP((_regs)); \ } \ (_r3) = (temp >> 16) & 0xf; \ (_r1) = (temp >> 20) & 0xf; \ INST_UPDATE_PSW((_regs), (_len), (_ilc)); \ } #if 0 /* RSE register and storage with extended op code and additional R3 or M3 field (note, this is NOT the ESA/390 vector RSE format) */ /* Note: Effective June 2003, RSE is retired and replaced by RSY */ #undef RSE #define RSE(_inst, _regs, _r1, _r3, _b2, _effective_addr2) \ { U32 temp; \ memcpy (&temp, (_inst), 4); \ temp = CSWAP32(temp); \ (_r1) = (temp >> 20) & 0xf; \ (_r3) = (temp >> 16) & 0xf; \ (_b2) = (temp >> 12) & 0xf; \ (_effective_addr2) = temp & 0xfff; \ if((_b2) != 0) \ { \ (_effective_addr2) += (_regs)->GR((_b2)); \ (_effective_addr2) &= ADDRESS_MAXWRAP((_regs)); \ } \ INST_UPDATE_PSW((_regs), 6, 6); \ } #endif /* RSY register and storage with extended op code, long displacement, and additional R3 or M3 field */ #undef RSY #undef RSY0 #undef RSY_B #if defined(FEATURE_LONG_DISPLACEMENT) #if !defined(DECODER_TEST)&&!defined(DECODER_TEST_RSY) #define RSY(_inst, _regs, _r1, _r3, _b2, _effective_addr2) \ RSY_DECODER_LD(_inst, _regs, _r1, _r3, _b2, _effective_addr2, 6, 6) #define RSY0(_inst, _regs, _r1, _r3, _b2, _effective_addr2) \ RSY_DECODER_LD(_inst, _regs, _r1, _r3, _b2, _effective_addr2, 6, 0) #define RSY_B(_inst, _regs, _r1, _r3, _b2, _effective_addr2) \ RSY_DECODER_LD(_inst, _regs, _r1, _r3, _b2, _effective_addr2, 0, 0) #else #define RSY(_inst, _regs, _r1, _r3, _b2, _effective_addr2) \ RSY_DECODER_LD_TEST(_inst, _regs, _r1, _r3, _b2, _effective_addr2, 6, 6) #define RSY0(_inst, _regs, _r1, _r3, _b2, _effective_addr2) \ RSY_DECODER_LD_TEST(_inst, _regs, _r1, _r3, _b2, _effective_addr2, 6, 0) #define RSY_B(_inst, _regs, _r1, _r3, _b2, _effective_addr2) \ RSY_DECODER_LD_TEST(_inst, _regs, _r1, _r3, _b2, _effective_addr2, 0, 0) #endif #else #if !defined(DECODER_TEST)&&!defined(DECODER_TEST_RSY) #define RSY(_inst, _regs, _r1, _r3, _b2, _effective_addr2) \ RSY_DECODER(_inst, _regs, _r1, _r3, _b2, _effective_addr2, 6, 6) #define RSY0(_inst, _regs, _r1, _r3, _b2, _effective_addr2) \ RSY_DECODER(_inst, _regs, _r1, _r3, _b2, _effective_addr2, 6, 0) #define RSY_B(_inst, _regs, _r1, _r3, _b2, _effective_addr2) \ RSY_DECODER(_inst, _regs, _r1, _r3, _b2, _effective_addr2, 0, 0) #else #define RSY(_inst, _regs, _r1, _r3, _b2, _effective_addr2) \ RSY_DECODER_TEST(_inst, _regs, _r1, _r3, _b2, _effective_addr2, 6, 6) #define RSY0(_inst, _regs, _r1, _r3, _b2, _effective_addr2) \ RSY_DECODER_TEST(_inst, _regs, _r1, _r3, _b2, _effective_addr2, 6, 0) #define RSY_B(_inst, _regs, _r1, _r3, _b2, _effective_addr2) \ RSY_DECODER_TEST(_inst, _regs, _r1, _r3, _b2, _effective_addr2, 0, 0) #endif #endif #define RSY_DECODER_LD(_inst, _regs, _r1, _r3, _b2, _effective_addr2, _len, _ilc) \ { U32 temp; S32 temp2; \ temp = fetch_fw(_inst); \ (_r1) = (temp >> 20) & 0xf; \ (_r3) = (temp >> 16) & 0xf; \ (_b2) = (temp >> 12) & 0xf; \ temp2 = (_inst[4] << 12) | (temp & 0xfff); \ if (temp2 & 0x80000) temp2 |= 0xfff00000; \ (_effective_addr2) = \ ((_b2) ? (_regs)->GR((_b2)) : (GREG)0) + \ temp2; \ if ((_len)) \ (_effective_addr2) &= ADDRESS_MAXWRAP((_regs)); \ INST_UPDATE_PSW((_regs), (_len), (_ilc)); \ } #define RSY_DECODER_LD_TEST(_inst, _regs, _r1, _r3, _b2, _effective_addr2, _len, _ilc) \ { U32 temp; S32 disp2; \ temp = fetch_fw(_inst); \ (_effective_addr2) = 0; \ (_b2) = (temp >> 12) & 0xf; \ if ((_b2)) \ _effective_addr2 += (_regs)->GR((_b2)); \ disp2 = temp & 0xfff; \ if (unlikely((_inst)[4])) { \ disp2 |= (_inst[4] << 12); \ if (disp2 & 0x80000) disp2 |= 0xfff00000; \ } \ (_effective_addr2) += disp2; \ if ((_len)) \ (_effective_addr2) &= ADDRESS_MAXWRAP((_regs)); \ (_r3) = (temp >> 16) & 0xf; \ (_r1) = (temp >> 20) & 0xf; \ INST_UPDATE_PSW((_regs), (_len), (_ilc)); \ } #define RSY_DECODER(_inst, _regs, _r1, _r3, _b2, _effective_addr2, _len, _ilc) \ { U32 temp = fetch_fw(_inst); \ (_r1) = (temp >> 20) & 0xf; \ (_r3) = (temp >> 16) & 0xf; \ (_b2) = (temp >> 12) & 0xf; \ (_effective_addr2) = temp & 0xfff; \ if((_b2) != 0) \ { \ (_effective_addr2) += (_regs)->GR((_b2)); \ if ((_len)) \ (_effective_addr2) &= ADDRESS_MAXWRAP((_regs)); \ } \ INST_UPDATE_PSW((_regs), (_len), (_ilc)); \ } #define RSY_DECODER_TEST(_inst, _regs, _r1, _r3, _b2, _effective_addr2, _len, _ilc) \ { U32 temp = fetch_fw(_inst); \ (_effective_addr2) = temp & 0xfff; \ (_b2) = (temp >> 12) & 0xf; \ if((_b2)) \ (_effective_addr2) += (_regs)->GR((_b2)); \ if ((_len)) \ (_effective_addr2) &= ADDRESS_MAXWRAP((_regs)); \ (_r3) = (temp >> 16) & 0xf; \ (_r1) = (temp >> 20) & 0xf; \ INST_UPDATE_PSW((_regs), (_len), (_ilc)); \ } /* RSL storage operand with extended op code and 4-bit L field */ #undef RSL #if !defined(DECODER_TEST)&&!defined(DECODER_TEST_RSL) #define RSL(_inst, _regs, _l1, _b1, _effective_addr1) \ RSL_DECODER(_inst, _regs, _l1, _b1, _effective_addr1, 6, 6) #else #define RSL(_inst, _regs, _l1, _b1, _effective_addr1) \ RSL_DECODER_TEST(_inst, _regs, _l1, _b1, _effective_addr1, 6, 6) #endif #define RSL_DECODER(_inst, _regs, _l1, _b1, _effective_addr1, _len, _ilc) \ { U32 temp = fetch_fw(_inst); \ (_l1) = (temp >> 20) & 0xf; \ (_b1) = (temp >> 12) & 0xf; \ (_effective_addr1) = temp & 0xfff; \ if((_b1) != 0) \ { \ (_effective_addr1) += (_regs)->GR((_b1)); \ (_effective_addr1) &= ADDRESS_MAXWRAP((_regs)); \ } \ INST_UPDATE_PSW((_regs), (_len), (_ilc)); \ } #define RSL_DECODER_TEST(_inst, _regs, _l1, _b1, _effective_addr1, _len, _ilc) \ { U32 temp = fetch_fw(_inst); \ (_effective_addr1) = temp & 0xfff; \ (_b1) = (temp >> 12) & 0xf; \ if((_b1)) { \ (_effective_addr1) += (_regs)->GR((_b1)); \ (_effective_addr1) &= ADDRESS_MAXWRAP((_regs)); \ } \ (_l1) = (temp >> 20) & 0xf; \ INST_UPDATE_PSW((_regs), (_len), (_ilc)); \ } /* RSI register and immediate with additional R3 field */ #undef RSI #undef RSI0 #if !defined(DECODER_TEST)&&!defined(DECODER_TEST_RSI) #define RSI(_inst, _regs, _r1, _r3, _i2) \ RSI_DECODER(_inst, _regs, _r1, _r3, _i2, 4, 4) #define RSI0(_inst, _regs, _r1, _r3, _i2) \ RSI_DECODER(_inst, _regs, _r1, _r3, _i2, 4, 0) #else #define RSI(_inst, _regs, _r1, _r3, _i2) \ RSI_DECODER_TEST(_inst, _regs, _r1, _r3, _i2, 4, 4) #define RSI0(_inst, _regs, _r1, _r3, _i2) \ RSI_DECODER_TEST(_inst, _regs, _r1, _r3, _i2, 4, 0) #endif #define RSI_DECODER(_inst, _regs, _r1, _r3, _i2, _len, _ilc) \ { U32 temp = fetch_fw(_inst); \ (_r1) = (temp >> 20) & 0xf; \ (_r3) = (temp >> 16) & 0xf; \ (_i2) = temp & 0xffff; \ INST_UPDATE_PSW((_regs), (_len), (_ilc)); \ } #define RSI_DECODER_TEST(_inst, _regs, _r1, _r3, _i2, _len, _ilc) \ { U32 temp = fetch_fw(_inst); \ (_i2) = temp & 0xffff; \ (_r3) = (temp >> 16) & 0xf; \ (_r1) = (temp >> 20) & 0xf; \ INST_UPDATE_PSW((_regs), (_len), (_ilc)); \ } /* RI register and immediate with extended 4-bit op code */ #undef RI #undef RI0 #undef RI_B #if !defined(DECODER_TEST)&&!defined(DECODER_TEST_RI) #define RI(_inst, _regs, _r1, _op, _i2) \ RI_DECODER(_inst, _regs, _r1, _op, _i2, 4, 4) #define RI0(_inst, _regs, _r1, _op, _i2) \ RI_DECODER(_inst, _regs, _r1, _op, _i2, 4, 0) #define RI_B(_inst, _regs, _r1, _op, _i2) \ RI_DECODER(_inst, _regs, _r1, _op, _i2, 0, 0) #else #define RI(_inst, _regs, _r1, _op, _i2) \ RI_DECODER_TEST(_inst, _regs, _r1, _op, _i2, 4, 4) #define RI0(_inst, _regs, _r1, _op, _i2) \ RI_DECODER_TEST(_inst, _regs, _r1, _op, _i2, 4, 0) #define RI_B(_inst, _regs, _r1, _op, _i2) \ RI_DECODER_TEST(_inst, _regs, _r1, _op, _i2, 0, 0) #endif #define RI_DECODER(_inst, _regs, _r1, _op, _i2, _len, _ilc) \ { U32 temp = fetch_fw(_inst); \ (_r1) = (temp >> 20) & 0xf; \ (_op) = (temp >> 16) & 0xf; \ (_i2) = temp & 0xffff; \ INST_UPDATE_PSW((_regs), (_len), (_ilc)); \ } #define RI_DECODER_TEST(_inst, _regs, _r1, _op, _i2) \ { U32 temp = fetch_fw(_inst); \ (_op) = (temp >> 16) & 0xf; \ (_i2) = temp & 0xffff; \ (_r1) = (temp >> 20) & 0xf; \ INST_UPDATE_PSW((_regs), (_len), (_ilc)); \ } /* RIE register and immediate with ext.opcode and additional R3 */ #undef RIE #undef RIE0 #undef RIE_B #define RIE(_inst, _regs, _r1, _r3, _i2) \ RIE_DECODER(_inst, _regs, _r1, _r3, _i2, 6, 6) #define RIE0(_inst, _regs, _r1, _r3, _i2) \ RIE_DECODER(_inst, _regs, _r1, _r3, _i2, 6, 0) #define RIE_B(_inst, _regs, _r1, _r3, _i2) \ RIE_DECODER(_inst, _regs, _r1, _r3, _i2, 0, 0) #define RIE_DECODER(_inst, _regs, _r1, _r3, _i2, _len, _ilc) \ { U32 temp = fetch_fw(_inst); \ (_r1) = (temp >> 20) & 0xf; \ (_r3) = (temp >> 16) & 0xf; \ (_i2) = temp & 0xffff; \ INST_UPDATE_PSW((_regs), (_len), (_ilc)); \ } /* RIE register and immediate with mask */ /*208*/ #undef RIE_RIM #define RIE_RIM(_inst, _regs, _r1, _i2, _m3) \ RIE_RIM_DECODER(_inst, _regs, _r1, _i2, _m3, 6, 6) #define RIE_RIM_DECODER(_inst, _regs, _r1, _i2, _m3, _len, _ilc) \ { U32 temp = fetch_fw(&(_inst)[1]); \ (_m3) = (temp >> 4) & 0xf; \ (_i2) = (temp >> 8) & 0xffff; \ (_r1) = (temp >> 28) & 0xf; \ INST_UPDATE_PSW((_regs), (_len), (_ilc)); \ } /* RIE register to register with immediate and mask */ /*208*/ #undef RIE_RRIM #undef RIE_RRIM0 #undef RIE_RRIM_B #define RIE_RRIM(_inst, _regs, _r1, _r2, _i4, _m3) \ RIE_RRIM_DECODER(_inst, _regs, _r1, _r2, _i4, _m3, 6, 6) #define RIE_RRIM0(_inst, _regs, _r1, _r2, _i4, _m3) \ RIE_RRIM_DECODER(_inst, _regs, _r1, _r2, _i4, _m3, 6, 0) #define RIE_RRIM_B(_inst, _regs, _r1, _r2, _i4, _m3) \ RIE_RRIM_DECODER(_inst, _regs, _r1, _r2, _i4, _m3, 0, 0) #define RIE_RRIM_DECODER(_inst, _regs, _r1, _r2, _i4, _m3, _len, _ilc) \ { U32 temp = fetch_fw(&(_inst)[1]); \ (_m3) = (temp >> 4) & 0xf; \ (_i4) = (temp >> 8) & 0xffff; \ (_r2) = (temp >> 24) & 0xf; \ (_r1) = (temp >> 28) & 0xf; \ INST_UPDATE_PSW((_regs), (_len), (_ilc)); \ } /* RIE register and mask with longer immediate and immediate */ /*208*/ #undef RIE_RMII #undef RIE_RMII0 #undef RIE_RMII_B #define RIE_RMII(_inst, _regs, _r1, _i2, _m3, _i4) \ RIE_RMII_DECODER(_inst, _regs, _r1, _i2, _m3, _i4, 6, 6) #define RIE_RMII0(_inst, _regs, _r1, _i2, _m3, _i4) \ RIE_RMII_DECODER(_inst, _regs, _r1, _i2, _m3, _i4, 6, 0) #define RIE_RMII_B(_inst, _regs, _r1, _i2, _m3, _i4) \ RIE_RMII_DECODER(_inst, _regs, _r1, _i2, _m3, _i4, 0, 0) #define RIE_RMII_DECODER(_inst, _regs, _r1, _i2, _m3, _i4, _len, _ilc) \ { U32 temp = fetch_fw(&(_inst)[1]); \ (_i2) = temp & 0xff; \ (_i4) = (temp >> 8) & 0xffff; \ (_m3) = (temp >> 24) & 0xf; \ (_r1) = (temp >> 28) & 0xf; \ INST_UPDATE_PSW((_regs), (_len), (_ilc)); \ } /* RIE register to register with three immediate fields */ /*208*/ #undef RIE_RRIII #define RIE_RRIII(_inst, _regs, _r1, _r2, _i3, _i4, _i5) \ RIE_RRIII_DECODER(_inst, _regs, _r1, _r2, _i3, _i4, _i5, 6, 6) #define RIE_RRIII_DECODER(_inst, _regs, _r1, _r2, _i3, _i4, _i5, _len, _ilc) \ { U32 temp = fetch_fw(&(_inst)[1]); \ (_i5) = temp & 0xff; \ (_i4) = (temp >> 8) & 0xff; \ (_i3) = (temp >> 16) & 0xff; \ (_r2) = (temp >> 24) & 0xf; \ (_r1) = (temp >> 28) & 0xf; \ INST_UPDATE_PSW((_regs), (_len), (_ilc)); \ } /* RIL register and longer immediate with extended 4 bit op code */ #undef RIL #undef RIL0 #undef RIL_B #if !defined(DECODER_TEST)&&!defined(DECODER_TEST_RIL) #define RIL(_inst, _regs, _r1, _op, _i2) \ RIL_DECODER(_inst, _regs, _r1, _op, _i2, 6, 6) #define RIL0(_inst, _regs, _r1, _op, _i2) \ RIL_DECODER(_inst, _regs, _r1, _op, _i2, 6, 0) #define RIL_B(_inst, _regs, _r1, _op, _i2) \ RIL_DECODER(_inst, _regs, _r1, _op, _i2, 0, 0) #else #define RIL(_inst, _regs, _r1, _op, _i2) \ RIL_DECODER_TEST(_inst, _regs, _r1, _op, _i2, 6, 6) #define RIL0(_inst, _regs, _r1, _op, _i2) \ RIL_DECODER_TEST(_inst, _regs, _r1, _op, _i2, 6, 0) #define RIL_B(_inst, _regs, _r1, _op, _i2) \ RIL_DECODER_TEST(_inst, _regs, _r1, _op, _i2, 0, 0) #endif #define RIL_DECODER(_inst, _regs, _r1, _op, _i2, _len, _ilc) \ { U32 temp = fetch_fw(_inst); \ (_r1) = (temp >> 20) & 0xf; \ (_op) = (temp >> 16) & 0xf; \ (_i2) = ((temp & 0xffff) << 16) \ | ((_inst)[4] << 8) \ | (_inst)[5]; \ INST_UPDATE_PSW((_regs), (_len), (_ilc)); \ } #define RIL_DECODER_TEST(_inst, _regs, _r1, _op, _i2, _len, _ilc) \ { \ (_i2) = fetch_fw(&(_inst)[2]); \ (_op) = ((_inst)[1] ) & 0xf; \ (_r1) = ((_inst)[1] >> 4) & 0xf; \ INST_UPDATE_PSW((_regs), (_len), (_ilc)); \ } /* RIL register and longer immediate relative address */ #undef RIL_A #if !defined(DECODER_TEST)&&!defined(DECODER_TEST_RIL_A) #define RIL_A(_inst, _regs, _r1, _addr2) \ RIL_A_DECODER(_inst, _regs, _r1, _addr2, 6, 6) #else #define RIL_A(_inst, _regs, _r1, _addr2) \ RIL_A_DECODER_TEST(_inst, _regs, _r1, _addr2, 6, 6) #endif #define RIL_A_DECODER(_inst, _regs, _r1, _addr2, _len, _ilc) \ { U32 temp = fetch_fw(_inst); \ S64 offset; \ (_r1) = (temp >> 20) & 0xf; \ offset = 2LL*(S32)(((temp & 0xffff) << 16) \ | ((_inst)[4] << 8) \ | (_inst)[5]); \ (_addr2) = (likely(!(_regs)->execflag)) ? \ PSW_IA((_regs), offset) : \ ((_regs)->ET + offset) & ADDRESS_MAXWRAP((_regs)); \ INST_UPDATE_PSW((_regs), (_len), (_ilc)); \ } #define RIL_A_DECODER_TEST(_inst, _regs, _r1, _addr2, _len, _ilc) \ { \ S64 offset = 2LL*(S32)(fetch_fw(&(_inst)[2])); \ (_r1) = ((_inst)[1] >> 4) & 0xf; \ (_addr2) = (likely(!(_regs)->execflag)) ? \ PSW_IA((_regs), offset) : \ ((_regs)->ET + offset) & ADDRESS_MAXWRAP((_regs)); \ INST_UPDATE_PSW((_regs), (_len), (_ilc)); \ } /* RIS register, immediate, mask, and storage */ /*208*/ #undef RIS #undef RIS0 #undef RIS_B #if !defined(DECODER_TEST)&&!defined(DECODER_TEST_RIS) #define RIS(_inst, _regs, _r1, _i2, _m3, _b4, _effective_addr4) \ RIS_DECODER(_inst, _regs, _r1, _i2, _m3, _b4, _effective_addr4, 6, 6) #define RIS0(_inst, _regs, _r1, _i2, _m3, _b4, _effective_addr4) \ RIS_DECODER(_inst, _regs, _r1, _i2, _m3, _b4, _effective_addr4, 6, 0) #define RIS_B(_inst, _regs, _r1, _i2, _m3, _b4, _effective_addr4) \ RIS_DECODER(_inst, _regs, _r1, _i2, _m3, _b4, _effective_addr4, 0, 0) #else #define RIS(_inst, _regs, _r1, _i2, _m3, _b4, _effective_addr4) \ RIS_DECODER_TEST(_inst, _regs, _r1, _i2, _m3, _b4, _effective_addr4, 6, 6) #define RISO(_inst, _regs, _r1, _i2, _m3, _b4, _effective_addr4) \ RIS_DECODER_TEST(_inst, _regs, _r1, _i2, _m3, _b4, _effective_addr4, 6, 0) #define RIS_B(_inst, _regs, _r1, _i2, _m3, _b4, _effective_addr4) \ RIS_DECODER_TEST(_inst, _regs, _r1, _i2, _m3, _b4, _effective_addr4, 0, 0) #endif #define RIS_DECODER(_inst, _regs, _r1, _i2, _m3, _b4, _effective_addr4, _len, _ilc) \ { U32 temp = fetch_fw(_inst); \ (_effective_addr4) = temp & 0xfff; \ (_b4) = (temp >> 12) & 0xf; \ if((_b4) != 0) \ { \ (_effective_addr4) += (_regs)->GR((_b4)); \ (_effective_addr4) &= ADDRESS_MAXWRAP((_regs)); \ } \ (_m3) = (temp >> 16) & 0xf; \ (_r1) = (temp >> 20) & 0xf; \ (_i2) = (_inst)[4]; \ INST_UPDATE_PSW((_regs), (_len), (_ilc)); \ } #define RIS_DECODER_TEST(_inst, _regs, _r1, _i2, _m3, _b4, _effective_addr4, _len, _ilc) \ { U32 temp = fetch_fw(_inst); \ (_effective_addr4) = temp & 0xfff; \ (_b4) = (temp >> 12) & 0xf; \ if((_b4)) { \ (_effective_addr4) += (_regs)->GR((_b4)); \ (_effective_addr4) &= ADDRESS_MAXWRAP((_regs)); \ } \ (_m3) = (temp >> 16) & 0xf; \ (_r1) = (temp >> 20) & 0xf; \ (_i2) = (_inst)[4]; \ INST_UPDATE_PSW((_regs), (_len), (_ilc)); \ } /* RRS register, immediate, mask, and storage */ /*208*/ #undef RRS #undef RRS0 #undef RRS_B #if !defined(DECODER_TEST)&&!defined(DECODER_TEST_RRS) #define RRS(_inst, _regs, _r1, _r2, _m3, _b4, _effective_addr4) \ RRS_DECODER(_inst, _regs, _r1, _r2, _m3, _b4, _effective_addr4, 6, 6) #define RRS0(_inst, _regs, _r1, _r2, _m3, _b4, _effective_addr4) \ RRS_DECODER(_inst, _regs, _r1, _r2, _m3, _b4, _effective_addr4, 6, 0) #define RRS_B(_inst, _regs, _r1, _r2, _m3, _b4, _effective_addr4) \ RRS_DECODER(_inst, _regs, _r1, _r2, _m3, _b4, _effective_addr4, 0, 0) #else #define RRS(_inst, _regs, _r1, _r2, _m3, _b4, _effective_addr4) \ RRS_DECODER_TEST(_inst, _regs, _r1, _r2, _m3, _b4, _effective_addr4, 6, 6) #define RRS0(_inst, _regs, _r1, _r2, _m3, _b4, _effective_addr4) \ RRS_DECODER_TEST(_inst, _regs, _r1, _r2, _m3, _b4, _effective_addr4, 6, 0) #define RRS_B(_inst, _regs, _r1, _r2, _m3, _b4, _effective_addr4) \ RRS_DECODER_TEST(_inst, _regs, _r1, _r2, _m3, _b4, _effective_addr4, 0, 0) #endif #define RRS_DECODER(_inst, _regs, _r1, _r2, _m3, _b4, _effective_addr4, _len, _ilc) \ { U32 temp = fetch_fw(_inst); \ (_effective_addr4) = temp & 0xfff; \ (_b4) = (temp >> 12) & 0xf; \ if((_b4) != 0) \ { \ (_effective_addr4) += (_regs)->GR((_b4)); \ (_effective_addr4) &= ADDRESS_MAXWRAP((_regs)); \ } \ (_r2) = (temp >> 16) & 0xf; \ (_r1) = (temp >> 20) & 0xf; \ (_m3) = ((_inst)[4] >> 4) & 0xf; \ INST_UPDATE_PSW((_regs), (_len), (_ilc)); \ } #define RRS_DECODER_TEST(_inst, _regs, _r1, _r2, _m3, _b4, _effective_addr4, _len, _ilc) \ { U32 temp = fetch_fw(_inst); \ (_effective_addr4) = temp & 0xfff; \ (_b4) = (temp >> 12) & 0xf; \ if((_b4)) { \ (_effective_addr4) += (_regs)->GR((_b4)); \ (_effective_addr4) &= ADDRESS_MAXWRAP((_regs)); \ } \ (_r2) = (temp >> 16) & 0xf; \ (_r1) = (temp >> 20) & 0xf; \ (_m3) = ((_inst)[4] >> 4) & 0xf; \ INST_UPDATE_PSW((_regs), (_len), (_ilc)); \ } /* SI storage and immediate */ #undef SI #if !defined(DECODER_TEST)&&!defined(DECODER_TEST_SI) #define SI(_inst, _regs, _i2, _b1, _effective_addr1) \ SI_DECODER(_inst, _regs, _i2, _b1, _effective_addr1, 4, 4) #else #define SI(_inst, _regs, _i2, _b1, _effective_addr1) \ SI_DECODER_TEST(_inst, _regs, _i2, _b1, _effective_addr1, 4, 4) #endif #define SI_DECODER(_inst, _regs, _i2, _b1, _effective_addr1, _len, _ilc) \ { U32 temp = fetch_fw(_inst); \ (_i2) = (temp >> 16) & 0xff; \ (_b1) = (temp >> 12) & 0xf; \ (_effective_addr1) = temp & 0xfff; \ if((_b1) != 0) \ { \ (_effective_addr1) += (_regs)->GR((_b1)); \ (_effective_addr1) &= ADDRESS_MAXWRAP((_regs)); \ } \ INST_UPDATE_PSW((_regs), (_len), (_ilc)); \ } #define SI_DECODER_TEST(_inst, _regs, _i2, _b1, _effective_addr1, _len, _ilc) \ { U32 temp = fetch_fw(_inst); \ (_effective_addr1) = temp & 0xfff; \ (_b1) = (temp >> 12) & 0xf; \ if((_b1)) { \ (_effective_addr1) += (_regs)->GR((_b1)); \ (_effective_addr1) &= ADDRESS_MAXWRAP((_regs)); \ } \ (_i2) = (temp >> 16) & 0xff; \ INST_UPDATE_PSW((_regs), (_len), (_ilc)); \ } /* SIY storage and immediate with long displacement */ #undef SIY #if defined(FEATURE_LONG_DISPLACEMENT) #if !defined(DECODER_TEST)&&!defined(DECODER_TEST_SIY) #define SIY(_inst, _regs, _i2, _b1, _effective_addr1) \ SIY_DECODER_LD(_inst, _regs, _i2, _b1, _effective_addr1, 6, 6) #else #define SIY(_inst, _regs, _i2, _b1, _effective_addr1) \ SIY_DECODER_LD_TEST(_inst, _regs, _i2, _b1, _effective_addr1, 6, 6) #endif #endif /* defined(FEATURE_LONG_DISPLACEMENT) */ #define SIY_DECODER_LD(_inst, _regs, _i2, _b1, _effective_addr1, _len, _ilc) \ { U32 temp; S32 temp1; \ temp = fetch_fw(_inst); \ (_i2) = (temp >> 16) & 0xff; \ (_b1) = (temp >> 12) & 0xf; \ temp1 = (_inst[4] << 12) | (temp & 0xfff); \ if (temp1 & 0x80000) temp1 |= 0xfff00000; \ (_effective_addr1) = \ ((_b1) ? (_regs)->GR((_b1)) : (GREG)0) + \ temp1; \ (_effective_addr1) &= ADDRESS_MAXWRAP((_regs)); \ INST_UPDATE_PSW((_regs), (_len), (_ilc)); \ } #define SIY_DECODER_LD_TEST(_inst, _regs, _i2, _b1, _effective_addr1, _len, _ilc) \ { U32 temp; S32 disp; \ temp = fetch_fw(_inst); \ (_effective_addr1) = 0; \ (_b1) = (temp >> 12) & 0xf; \ if ((_b1)) \ (_effective_addr1) += (_regs)->GR((_b1)); \ disp = temp & 0xfff; \ if (unlikely((_inst)[4])) { \ disp |= (_inst[4] << 12); \ if (disp & 0x80000) disp |= 0xfff00000; \ } \ (_effective_addr1) += disp; \ (_effective_addr1) &= ADDRESS_MAXWRAP((_regs)); \ INST_UPDATE_PSW((_regs), (_len), (_ilc)); \ (_i2) = (temp >> 16) & 0xff; \ } /* SIL storage and longer immediate */ /*208*/ #undef SIL #if !defined(DECODER_TEST)&&!defined(DECODER_TEST_SIL) #define SIL(_inst, _regs, _i2, _b1, _effective_addr1) \ SIL_DECODER(_inst, _regs, _i2, _b1, _effective_addr1, 6, 6) #else #define SIL(_inst, _regs, _i2, _b1, _effective_addr1) \ SIL_DECODER_TEST(_inst, _regs, _i2, _b1, _effective_addr1, 6, 6) #endif #define SIL_DECODER(_inst, _regs, _i2, _b1, _effective_addr1, _len, _ilc) \ { U32 temp = fetch_fw(&(_inst)[2]); \ (_i2) = temp & 0xffff; \ (_effective_addr1) = (temp >> 16) & 0xfff; \ (_b1) = (temp >> 28) & 0xf; \ if((_b1) != 0) \ { \ (_effective_addr1) += (_regs)->GR((_b1)); \ (_effective_addr1) &= ADDRESS_MAXWRAP((_regs)); \ } \ INST_UPDATE_PSW((_regs), (_len), (_ilc)); \ } #define SIL_DECODER_TEST(_inst, _regs, _i2, _b1, _effective_addr1, _len, _ilc) \ { U32 temp = fetch_fw(&(_inst)[2]); \ (_i2) = temp & 0xffff; \ (_effective_addr1) = (temp >> 16) & 0xfff; \ (_b1) = (temp >> 28) & 0xf; \ if((_b1) != 0) \ { \ (_effective_addr1) += (_regs)->GR((_b1)); \ (_effective_addr1) &= ADDRESS_MAXWRAP((_regs)); \ } \ INST_UPDATE_PSW((_regs), (_len), (_ilc)); \ } /* S storage operand only */ #undef S #if !defined(DECODER_TEST)&&!defined(DECODER_TEST_S) #define S(_inst, _regs, _b2, _effective_addr2) \ S_DECODER(_inst, _regs, _b2, _effective_addr2, 4, 4) #else #define S(_inst, _regs, _b2, _effective_addr2) \ S_DECODER_TEST(_inst, _regs, _b2, _effective_addr2, 4, 4) #endif #define S_DECODER(_inst, _regs, _b2, _effective_addr2, _len, _ilc) \ { U32 temp = fetch_fw(_inst); \ (_b2) = (temp >> 12) & 0xf; \ (_effective_addr2) = temp & 0xfff; \ if((_b2) != 0) \ { \ (_effective_addr2) += (_regs)->GR((_b2)); \ (_effective_addr2) &= ADDRESS_MAXWRAP((_regs)); \ } \ INST_UPDATE_PSW((_regs), (_len), (_ilc)); \ } #define S_DECODER_TEST(_inst, _regs, _b2, _effective_addr2, _len, _ilc) \ { U32 temp = fetch_fw(_inst); \ (_effective_addr2) = temp & 0xfff; \ (_b2) = (temp >> 12) & 0xf; \ if((_b2) != 0) { \ (_effective_addr2) += (_regs)->GR((_b2)); \ (_effective_addr2) &= ADDRESS_MAXWRAP((_regs)); \ } \ INST_UPDATE_PSW((_regs), (_len), (_ilc)); \ } /* SS storage to storage with two 4-bit L or R fields */ #undef SS #if !defined(DECODER_TEST)&&!defined(DECODER_TEST_SS) #define SS(_inst, _regs, _r1, _r3, \ _b1, _effective_addr1, _b2, _effective_addr2) \ SS_DECODER(_inst, _regs, _r1, _r3, \ _b1, _effective_addr1, _b2, _effective_addr2, 6, 6) #else #define SS(_inst, _regs, _r1, _r3, \ _b1, _effective_addr1, _b2, _effective_addr2) \ SS_DECODER_TEST(_inst, _regs, _r1, _r3, \ _b1, _effective_addr1, _b2, _effective_addr2, 6, 6) #endif #define SS_DECODER(_inst, _regs, _r1, _r3, \ _b1, _effective_addr1, _b2, _effective_addr2, _len, _ilc) \ { U32 temp = fetch_fw(_inst); \ (_r1) = (temp >> 20) & 0xf; \ (_r3) = (temp >> 16) & 0xf; \ (_b1) = (temp >> 12) & 0xf; \ (_effective_addr1) = temp & 0xfff; \ if((_b1) != 0) \ { \ (_effective_addr1) += (_regs)->GR((_b1)); \ (_effective_addr1) &= ADDRESS_MAXWRAP((_regs)); \ } \ (_b2) = (_inst)[4] >> 4; \ (_effective_addr2) = (((_inst)[4] & 0x0F) << 8) | (_inst)[5]; \ if((_b2) != 0) \ { \ (_effective_addr2) += (_regs)->GR((_b2)); \ (_effective_addr2) &= ADDRESS_MAXWRAP((_regs)); \ } \ INST_UPDATE_PSW((_regs), (_len), (_ilc)); \ } #define SS_DECODER_TEST(_inst, _regs, _r1, _r3, \ _b1, _effective_addr1, _b2, _effective_addr2, _len, _ilc) \ { U32 temp; \ temp = fetch_fw((_inst)+2); \ (_effective_addr1) = (temp >> 16) & 0xfff; \ (_b1) = (temp >> 28); \ if ((_b1)) { \ (_effective_addr1) += (_regs)->GR((_b1)); \ (_effective_addr1) &= ADDRESS_MAXWRAP((_regs)); \ } \ (_effective_addr2) = temp & 0xfff; \ (_b2) = (temp >> 12) & 0xf; \ if ((_b2)) { \ (_effective_addr2) += (_regs)->GR((_b2)); \ (_effective_addr2) &= ADDRESS_MAXWRAP((_regs)); \ } \ (_r3) = ((_inst)[1] ) & 0xf; \ (_r1) = ((_inst)[1] >> 4) & 0xf; \ INST_UPDATE_PSW((_regs), (_len), (_ilc)); \ } /* SS storage to storage with one 8-bit L field */ #undef SS_L #if !defined(DECODER_TEST)&&!defined(DECODER_TEST_SS_L) #define SS_L(_inst, _regs, _l, \ _b1, _effective_addr1, _b2, _effective_addr2) \ SS_L_DECODER(_inst, _regs, _l, \ _b1, _effective_addr1, _b2, _effective_addr2, 6, 6) #else #define SS_L(_inst, _regs, _l, \ _b1, _effective_addr1, _b2, _effective_addr2) \ SS_L_DECODER_TEST(_inst, _regs, _l, \ _b1, _effective_addr1, _b2, _effective_addr2, 6, 6) #endif #define SS_L_DECODER(_inst, _regs, _l, \ _b1, _effective_addr1, _b2, _effective_addr2, _len, _ilc) \ { U32 temp = fetch_fw(_inst); \ (_l) = (temp >> 16) & 0xff; \ (_b1) = (temp >> 12) & 0xf; \ (_effective_addr1) = temp & 0xfff; \ if((_b1) != 0) \ { \ (_effective_addr1) += (_regs)->GR((_b1)); \ (_effective_addr1) &= ADDRESS_MAXWRAP((_regs)); \ } \ (_b2) = (_inst)[4] >> 4; \ (_effective_addr2) = (((_inst)[4] & 0x0F) << 8) | (_inst)[5]; \ if((_b2) != 0) \ { \ (_effective_addr2) += (_regs)->GR((_b2)); \ (_effective_addr2) &= ADDRESS_MAXWRAP((_regs)); \ } \ INST_UPDATE_PSW((_regs), (_len), (_ilc)); \ } #define SS_L_DECODER_TEST(_inst, _regs, _l, \ _b1, _effective_addr1, _b2, _effective_addr2, _len, _ilc) \ { U32 temp; \ temp = fetch_fw((_inst)+2); \ (_effective_addr1) = (temp >> 16) & 0xfff; \ (_b1) = (temp >> 28); \ if((_b1)) { \ (_effective_addr1) += (_regs)->GR((_b1)); \ (_effective_addr1) &= ADDRESS_MAXWRAP((_regs)); \ } \ (_effective_addr2) = temp & 0xfff; \ (_b2) = (temp >> 12) & 0xf; \ if ((_b2)) { \ (_effective_addr2) += (_regs)->GR((_b2)); \ (_effective_addr2) &= ADDRESS_MAXWRAP((_regs)); \ } \ (_l) = (_inst)[1]; \ INST_UPDATE_PSW((_regs), (_len), (_ilc)); \ } /* SSE storage to storage with extended op code */ #undef SSE #if !defined(DECODER_TEST)&&!defined(DECODER_TEST_SSE) #define SSE(_inst, _regs, _b1, _effective_addr1, \ _b2, _effective_addr2) \ SSE_DECODER(_inst, _regs, _b1, _effective_addr1, \ _b2, _effective_addr2, 6, 6) #else #define SSE(_inst, _regs, _b1, _effective_addr1, \ _b2, _effective_addr2) \ SSE_DECODER_TEST(_inst, _regs, _b1, _effective_addr1, \ _b2, _effective_addr2, 6, 6) #endif #define SSE_DECODER(_inst, _regs, _b1, _effective_addr1, \ _b2, _effective_addr2, _len, _ilc) \ { U32 temp = fetch_fw(_inst); \ (_b1) = (temp >> 12) & 0xf; \ (_effective_addr1) = temp & 0xfff; \ if((_b1) != 0) \ { \ (_effective_addr1) += (_regs)->GR((_b1)); \ (_effective_addr1) &= ADDRESS_MAXWRAP((_regs)); \ } \ (_b2) = (_inst)[4] >> 4; \ (_effective_addr2) = (((_inst)[4] & 0x0F) << 8) | (_inst)[5]; \ if((_b2) != 0) \ { \ (_effective_addr2) += (_regs)->GR((_b2)); \ (_effective_addr2) &= ADDRESS_MAXWRAP((_regs)); \ } \ INST_UPDATE_PSW((_regs), (_len), (_ilc)); \ } #define SSE_DECODER_TEST(_inst, _regs, _b1, _effective_addr1, \ _b2, _effective_addr2, _len, _ilc) \ { U32 temp = fetch_fw((_inst)+2); \ (_effective_addr1) = (temp >> 16) & 0xfff; \ (_b1) = (temp >> 28); \ if((_b1)) { \ (_effective_addr1) += (_regs)->GR((_b1)); \ (_effective_addr1) &= ADDRESS_MAXWRAP((_regs)); \ } \ (_effective_addr2) = temp & 0xfff; \ (_b2) = (temp >> 12) & 0xf; \ if ((_b2)) { \ (_effective_addr2) += (_regs)->GR((_b2)); \ (_effective_addr2) &= ADDRESS_MAXWRAP((_regs)); \ } \ INST_UPDATE_PSW((_regs), (_len), (_ilc)); \ } /* SSF storage to storage with additional register */ #undef SSF #if !defined(DECODER_TEST)&&!defined(DECODER_TEST_SSF) #define SSF(_inst, _regs, _b1, _effective_addr1, \ _b2, _effective_addr2, _r3) \ SSF_DECODER(_inst, _regs, _b1, _effective_addr1, \ _b2, _effective_addr2, _r3, 6, 6) #else #define SSF(_inst, _regs, _b1, _effective_addr1, \ _b2, _effective_addr2, _r3) \ SSF_DECODER_TEST(_inst, _regs, _b1, _effective_addr1, \ _b2, _effective_addr2, _r3, 6, 6) #endif #define SSF_DECODER(_inst, _regs, _b1, _effective_addr1, \ _b2, _effective_addr2, _r3, _len, _ilc) \ { U32 temp = fetch_fw(_inst); \ (_r3) = (temp >> 20) & 0xf; \ (_b1) = (temp >> 12) & 0xf; \ (_effective_addr1) = temp & 0xfff; \ if((_b1) != 0) \ { \ (_effective_addr1) += (_regs)->GR((_b1)); \ (_effective_addr1) &= ADDRESS_MAXWRAP((_regs)); \ } \ (_b2) = (_inst)[4] >> 4; \ (_effective_addr2) = (((_inst)[4] & 0x0F) << 8) | (_inst)[5]; \ if((_b2) != 0) \ { \ (_effective_addr2) += (_regs)->GR((_b2)); \ (_effective_addr2) &= ADDRESS_MAXWRAP((_regs)); \ } \ INST_UPDATE_PSW((_regs), (_len), (_ilc)); \ } #define SSF_DECODER_TEST(_inst, _regs, _b1, _effective_addr1, \ _b2, _effective_addr2, _r3, _len, _ilc) \ { U32 temp; \ temp = fetch_fw((_inst)+2); \ (_effective_addr1) = (temp >> 16) & 0xfff; \ (_b1) = (temp >> 28); \ if((_b1)) { \ (_effective_addr1) += (_regs)->GR((_b1)); \ (_effective_addr1) &= ADDRESS_MAXWRAP((_regs)); \ } \ (_effective_addr2) = temp & 0xfff; \ (_b2) = (temp >> 12) & 0xf; \ if ((_b2)) { \ (_effective_addr2) += (_regs)->GR((_b2)); \ (_effective_addr2) &= ADDRESS_MAXWRAP((_regs)); \ } \ (_b1) = ((_inst)[1] ) & 0xf;\ (_r3) = ((_inst)[1] >> 4) & 0xf; \ INST_UPDATE_PSW((_regs), (_len), (_ilc)); \ } #undef SIE_TRANSLATE_ADDR #undef SIE_LOGICAL_TO_ABS #undef SIE_INTERCEPT #undef SIE_TRANSLATE #if defined(_FEATURE_SIE) #define SIE_SET_VI(_who, _when, _why, _regs) \ { \ (_regs)->siebk->vi_who = (_who); \ (_regs)->siebk->vi_when = (_when); \ STORE_HW((_regs)->siebk->vi_why, (_why)); \ memset((_regs)->siebk->vi_zero, 0, 6); \ } #if __GEN_ARCH == 900 || (__GEN_ARCH == 390 && !defined(_FEATURE_ZSIE)) #define SIE_TRANSLATE_ADDR(_addr, _arn, _regs, _acctype) \ ARCH_DEP(translate_addr)((_addr), (_arn), (_regs), (_acctype)) #define SIE_LOGICAL_TO_ABS(_addr, _arn, _regs, _acctype, _akey) \ ( \ ARCH_DEP(logical_to_main)((_addr), (_arn), (_regs), (_acctype), (_akey)), \ (_regs)->dat.aaddr \ ) #elif __GEN_ARCH == 370 && defined(_FEATURE_SIE) #define SIE_TRANSLATE_ADDR(_addr, _arn, _regs, _acctype) \ s390_translate_addr((_addr), (_arn), (_regs), (_acctype)) #define SIE_LOGICAL_TO_ABS(_addr, _arn, _regs, _acctype, _akey) \ ( \ s390_logical_to_main((_addr), (_arn), (_regs), (_acctype), (_akey)), \ (_regs)->dat.aaddr \ ) #else /*__GEN_ARCH == 390 && defined(_FEATURE_ZSIE)*/ #define SIE_TRANSLATE_ADDR(_addr, _arn, _regs, _acctype) \ ( ((_regs)->arch_mode == ARCH_390) ? \ s390_translate_addr((_addr), (_arn), (_regs), (_acctype)) : \ z900_translate_addr((_addr), (_arn), (_regs), (_acctype)) ) #define SIE_LOGICAL_TO_ABS(_addr, _arn, _regs, _acctype, _akey) \ ( \ (((_regs)->arch_mode == ARCH_390) \ ? s390_logical_to_main((_addr), (_arn), (_regs), (_acctype), (_akey)) \ : z900_logical_to_main((_addr), (_arn), (_regs), (_acctype), (_akey))), \ (_regs)->dat.aaddr \ ) #endif #define SIE_INTERCEPT(_regs) \ do { \ if(SIE_MODE((_regs))) \ longjmp((_regs)->progjmp, SIE_INTERCEPT_INST); \ } while(0) #define SIE_TRANSLATE(_addr, _acctype, _regs) \ do { \ if(SIE_MODE((_regs)) && !(_regs)->sie_pref) \ *(_addr) = SIE_LOGICAL_TO_ABS ((_regs)->sie_mso + *(_addr), \ USE_PRIMARY_SPACE, (_regs)->hostregs, (_acctype), 0); \ } while(0) #else /*!defined(_FEATURE_SIE)*/ #define SIE_TRANSLATE_ADDR(_addr, _arn, _regs, _acctype) #define SIE_LOGICAL_TO_ABS(_addr, _arn, _regs, _acctype, _akey) #define SIE_INTERCEPT(_regs) #define SIE_TRANSLATE(_addr, _acctype, _regs) #endif /*!defined(_FEATURE_SIE)*/ #undef SIE_XC_INTERCEPT #if defined(FEATURE_MULTIPLE_CONTROLLED_DATA_SPACE) #define SIE_XC_INTERCEPT(_regs) \ if(SIE_STATB((_regs), MX, XC)) \ SIE_INTERCEPT((_regs)) #else /*!defined(FEATURE_MULTIPLE_CONTROLLED_DATA_SPACE)*/ #define SIE_XC_INTERCEPT(_regs) #endif /*!defined(FEATURE_MULTIPLE_CONTROLLED_DATA_SPACE)*/ #if defined(FEATURE_VECTOR_FACILITY) #if !defined(_VFDEFS) #define _VFDEFS #define VOP_CHECK(_regs) \ if(!((_regs)->CR(0) & CR0_VOP) || !(_regs)->vf->online) \ (_regs)->program_interrupt((_regs), PGM_VECTOR_OPERATION_EXCEPTION) #define VR_INUSE(_vr, _regs) \ ((_regs)->vf->vsr & (VSR_VIU0 >> ((_vr) >> 1))) #define VR_CHANGED(_vr, _regs) \ ((_regs)->vf->vsr & (VSR_VCH0 >> ((_vr) >> 1))) #define SET_VR_INUSE(_vr, _regs) \ (_regs)->vf->vsr |= (VSR_VIU0 >> ((_vr) >> 1)) #define SET_VR_CHANGED(_vr, _regs) \ (_regs)->vf->vsr |= (VSR_VCH0 >> ((_vr) >> 1)) #define RESET_VR_INUSE(_vr, _regs) \ (_regs)->vf->vsr &= ~(VSR_VIU0 >> ((_vr) >> 1)) #define RESET_VR_CHANGED(_vr, _regs) \ (_regs)->vf->vsr &= ~(VSR_VCH0 >> ((_vr) >> 1)) #define VMR_SET(_section, _regs) \ ((_regs)->vf->vmr[(_section) >> 3] & (0x80 >> ((_section) & 7))) #define MASK_MODE(_regs) \ ((_regs)->vf->vsr & VSR_M) #define VECTOR_COUNT(_regs) \ (((_regs)->vf->vsr & VSR_VCT) >> 32) #define VECTOR_IX(_regs) \ (((_regs)->vf->vsr & VSR_VIX) >> 16) #endif /*!defined(_VFDEFS)*/ /* VST and QST formats are the same */ #undef VST #define VST(_inst, _regs, _vr3, _rt2, _vr1, _rs2) \ { \ (_qr3) = (_inst)[2] >> 4; \ (_rt2) = (_inst)[2] & 0x0F; \ (_vr1) = (_inst)[3] >> 4; \ (_rs2) = (_inst)[3] & 0x0F; \ INST_UPDATE_PSW((_regs), 4, 4); \ } /* VR, VV and QV formats are the same */ #undef VR #define VR(_inst, _regs, _qr3, _vr1, _vr2) \ { \ (_qr3) = (_inst)[2] >> 4; \ (_vr1) = (_inst)[3] >> 4; \ (_vr2) = (_inst)[3] & 0x0F; \ INST_UPDATE_PSW((_regs), 4, 4); \ } #undef VS #define VS(_inst, _regs, _rs2) \ { \ (_rs2) = (_inst)[3] & 0x0F; \ INST_UPDATE_PSW((_regs), 4, 4); \ } /* The RSE vector instruction format of ESA/390 is referred to as VRSE to avoid conflict with the ESAME RSE instruction format */ #undef VRSE #define VRSE(_inst, _regs, _r3, _vr1, \ _b2, _effective_addr2) \ { \ (_r3) = (_inst)[2] >> 4; \ (_vr1) = (_inst)[3] >> 4; \ (_b2) = (_inst)[4] >> 4; \ (_effective_addr2) = (((_inst)[4] & 0x0F) << 8) | (_inst)[5]; \ if((_b2) != 0) \ { \ (_effective_addr2) += (_regs)->GR((_b2)); \ (_effective_addr2) &= ADDRESS_MAXWRAP((_regs)); \ } \ INST_UPDATE_PSW((_regs), 6, 6); \ } /* S format instructions where the effective address does not wrap */ #undef S_NW #define S_NW(_inst, _regs, _b2, _effective_addr2) \ { \ (_b2) = (_inst)[2] >> 4; \ (_effective_addr2) = (((_inst)[2] & 0x0F) << 8) | (_inst)[3]; \ if((_b2) != 0) \ { \ (_effective_addr2) += (_regs)->GR((_b2)); \ } \ INST_UPDATE_PSW((_regs), 4, 4); \ } #endif /*defined(FEATURE_VECTOR_FACILITY)*/ #define PERFORM_SERIALIZATION(_regs) do { } while (0) #define PERFORM_CHKPT_SYNC(_regs) do { } while (0) /* Functions in module channel.c */ int ARCH_DEP(startio) (REGS *regs, DEVBLK *dev, ORB *orb); void *s370_execute_ccw_chain (DEVBLK *dev); void *s390_execute_ccw_chain (DEVBLK *dev); void *z900_execute_ccw_chain (DEVBLK *dev); int stchan_id (REGS *regs, U16 chan); int testch (REGS *regs, U16 chan); int testio (REGS *regs, DEVBLK *dev, BYTE ibyte); int test_subchan (REGS *regs, DEVBLK *dev, IRB *irb); int cancel_subchan (REGS *regs, DEVBLK *dev); void clear_subchan (REGS *regs, DEVBLK *dev); int halt_subchan (REGS *regs, DEVBLK *dev); int haltio (REGS *regs, DEVBLK *dev, BYTE ibyte); int resume_subchan (REGS *regs, DEVBLK *dev); int ARCH_DEP(present_io_interrupt) (REGS *regs, U32 *ioid, U32 *ioparm, U32 *iointid, BYTE *csw); int ARCH_DEP(present_zone_io_interrupt) (U32 *ioid, U32 *ioparm, U32 *iointid, BYTE zone); void io_reset (void); int chp_reset(REGS *, BYTE chpid); void channelset_reset(REGS *regs); DLL_EXPORT int device_attention (DEVBLK *dev, BYTE unitstat); DLL_EXPORT int ARCH_DEP(device_attention) (DEVBLK *dev, BYTE unitstat); /* Functions in module cpu.c */ /* define all arch_load|store_psw */ /* regardless of current architecture (if any) */ #if defined(_370) void s370_store_psw (REGS *regs, BYTE *addr); int s370_load_psw (REGS *regs, BYTE *addr); void s370_process_trace (REGS *regs); #endif #if defined(_390) int s390_load_psw (REGS *regs, BYTE *addr); void s390_store_psw (REGS *regs, BYTE *addr); void s390_process_trace (REGS *regs); #endif /*defined(_FEATURE_ZSIE)*/ #if defined(_900) int z900_load_psw (REGS *regs, BYTE *addr); void z900_store_psw (REGS *regs, BYTE *addr); void z900_process_trace (REGS *regs); #endif int cpu_init (int cpu, REGS *regs, REGS *hostregs); void ARCH_DEP(perform_io_interrupt) (REGS *regs); void ARCH_DEP(checkstop_config)(void); #if defined(_FEATURE_SIE) CPU_DLL_IMPORT void (ATTR_REGPARM(2) s370_program_interrupt) (REGS *regs, int code); #endif /*!defined(_FEATURE_SIE)*/ #if defined(_FEATURE_ZSIE) CPU_DLL_IMPORT void (ATTR_REGPARM(2) s390_program_interrupt) (REGS *regs, int code); #endif /*!defined(_FEATURE_ZSIE)*/ CPU_DLL_IMPORT void (ATTR_REGPARM(2) ARCH_DEP(program_interrupt)) (REGS *regs, int code); void *cpu_thread (int *cpu); DLL_EXPORT void copy_psw (REGS *regs, BYTE *addr); void display_psw (REGS *regs); /* Functions in module vm.c */ int ARCH_DEP(diag_devtype) (int r1, int r2, REGS *regs); int ARCH_DEP(syncblk_io) (int r1, int r2, REGS *regs); int ARCH_DEP(syncgen_io) (int r1, int r2, REGS *regs); void ARCH_DEP(extid_call) (int r1, int r2, REGS *regs); int ARCH_DEP(cpcmd_call) (int r1, int r2, REGS *regs); void ARCH_DEP(pseudo_timer) (U32 code, int r1, int r2, REGS *regs); void ARCH_DEP(access_reipl_data) (int r1, int r2, REGS *regs); int ARCH_DEP(diag_ppagerel) (int r1, int r2, REGS *regs); void ARCH_DEP(vm_info) (int r1, int r2, REGS *regs); int ARCH_DEP(device_info) (int r1, int r2, REGS *regs); /* Functions in module vmd250.c */ int ARCH_DEP(vm_blockio) (int r1, int r2, REGS *regs); /* Functions in module control.c */ void ARCH_DEP(load_real_address_proc) (REGS *regs, int r1, int b2, VADR effective_addr2); /* Functions in module decimal.c */ void packed_to_binary (BYTE *dec, int len, U64 *result, int *ovf, int *dxf); void binary_to_packed (S64 bin, BYTE *result); /* Functions in module diagnose.c */ void ARCH_DEP(diagnose_call) (VADR effective_addr2, int b2, int r1, int r3, REGS *regs); /* Functions in module diagmssf.c */ void ARCH_DEP(scpend_call) (void); int ARCH_DEP(mssf_call) (int r1, int r2, REGS *regs); void ARCH_DEP(diag204_call) (int r1, int r2, REGS *regs); void ARCH_DEP(diag224_call) (int r1, int r2, REGS *regs); /* Functions in module external.c */ void ARCH_DEP(perform_external_interrupt) (REGS *regs); void ARCH_DEP(store_status) (REGS *ssreg, RADR aaddr); void store_status (REGS *ssreg, U64 aaddr); /* Functions in module ipl.c */ int load_ipl (U16 lcss, U16 devnum, int cpu, int clear); int ARCH_DEP(load_ipl) (U16 lcss, U16 devnum, int cpu, int clear); int system_reset ( int cpu, int clear); int ARCH_DEP(system_reset) ( int cpu, int clear); int cpu_reset (REGS *regs); int ARCH_DEP(cpu_reset) (REGS *regs); int initial_cpu_reset (REGS *regs); int ARCH_DEP(initial_cpu_reset) (REGS *regs); int ARCH_DEP(common_load_begin) (int cpu, int clear); int ARCH_DEP(common_load_finish) (REGS *regs); void storage_clear(void); void xstorage_clear(void); /* Functions in module scedasd.c */ void set_sce_dir (char *path); char *get_sce_dir (); int load_main (char *fname, RADR startloc); int ARCH_DEP(load_main) (char *fname, RADR startloc); int load_hmc (char *fname, int cpu, int clear); int ARCH_DEP(load_hmc) (char *fname, int cpu, int clear); void ARCH_DEP(sclp_scedio_request) (SCCB_HEADER *); void ARCH_DEP(sclp_scedio_event) (SCCB_HEADER *); /* Functions in module machchk.c */ int ARCH_DEP(present_mck_interrupt) (REGS *regs, U64 *mcic, U32 *xdmg, RADR *fsta); U32 channel_report (REGS *); void machine_check_crwpend (void); void ARCH_DEP(sync_mck_interrupt) (REGS *regs); void sigabend_handler (int signo); /* Functions in module opcode.c */ OPC_DLL_IMPORT void copy_opcode_tables (); void set_opcode_pointers (REGS *regs); /* Functions in module panel.c */ void ARCH_DEP(display_inst) (REGS *regs, BYTE *inst); void display_inst (REGS *regs, BYTE *inst); /* Functions in module sie.c */ void ARCH_DEP(sie_exit) (REGS *regs, int code); void ARCH_DEP(diagnose_002) (REGS *regs, int r1, int r3); /* Functions in module stack.c */ void ARCH_DEP(trap_x) (int trap_is_trap4, REGS *regs, U32 trap_operand); void ARCH_DEP(form_stack_entry) (BYTE etype, VADR retna, VADR calla, U32 csi, U32 pcnum, REGS *regs); VADR ARCH_DEP(locate_stack_entry) (int prinst, LSED *lsedptr, REGS *regs); void ARCH_DEP(stack_modify) (VADR lsea, U32 m1, U32 m2, REGS *regs); void ARCH_DEP(stack_extract) (VADR lsea, int r1, int code, REGS *regs); void ARCH_DEP(unstack_registers) (int gtype, VADR lsea, int r1, int r2, REGS *regs); int ARCH_DEP(program_return_unstack) (REGS *regs, RADR *lsedap, int *rc); /* Functions in module trace.c */ CREG ARCH_DEP(trace_br) (int amode, VADR ia, REGS *regs); #if defined(_FEATURE_ZSIE) U32 s390_trace_br (int amode, U32 ia, REGS *regs); #endif /*!defined(_FEATURE_ZSIE)*/ CREG ARCH_DEP(trace_bsg) (U32 alet, VADR ia, REGS *regs); CREG ARCH_DEP(trace_ssar) (int ssair, U16 sasn, REGS *regs); CREG ARCH_DEP(trace_pc) (U32 pcea, REGS *regs); CREG ARCH_DEP(trace_pr) (REGS *newregs, REGS *regs); CREG ARCH_DEP(trace_pt) (int pti, U16 pasn, GREG gpr2, REGS *regs); CREG ARCH_DEP(trace_tr) (int r1, int r3, U32 op, REGS *regs); CREG ARCH_DEP(trace_tg) (int r1, int r3, U32 op, REGS *regs); CREG ARCH_DEP(trace_ms) (int br_ind, VADR ia, REGS *regs); /* Functions in module plo.c */ int ARCH_DEP(plo_cl) (int r1, int r3, VADR effective_addr2, int b2, VADR effective_addr4, int b4, REGS *regs); int ARCH_DEP(plo_clg) (int r1, int r3, VADR effective_addr2, int b2, VADR effective_addr4, int b4, REGS *regs); int ARCH_DEP(plo_clgr) (int r1, int r3, VADR effective_addr2, int b2, VADR effective_addr4, int b4, REGS *regs); int ARCH_DEP(plo_clx) (int r1, int r3, VADR effective_addr2, int b2, VADR effective_addr4, int b4, REGS *regs); int ARCH_DEP(plo_cs) (int r1, int r3, VADR effective_addr2, int b2, VADR effective_addr4, int b4, REGS *regs); int ARCH_DEP(plo_csg) (int r1, int r3, VADR effective_addr2, int b2, VADR effective_addr4, int b4, REGS *regs); int ARCH_DEP(plo_csgr) (int r1, int r3, VADR effective_addr2, int b2, VADR effective_addr4, int b4, REGS *regs); int ARCH_DEP(plo_csx) (int r1, int r3, VADR effective_addr2, int b2, VADR effective_addr4, int b4, REGS *regs); int ARCH_DEP(plo_dcs) (int r1, int r3, VADR effective_addr2, int b2, VADR effective_addr4, int b4, REGS *regs); int ARCH_DEP(plo_dcsg) (int r1, int r3, VADR effective_addr2, int b2, VADR effective_addr4, int b4, REGS *regs); int ARCH_DEP(plo_dcsgr) (int r1, int r3, VADR effective_addr2, int b2, VADR effective_addr4, int b4, REGS *regs); int ARCH_DEP(plo_dcsx) (int r1, int r3, VADR effective_addr2, int b2, VADR effective_addr4, int b4, REGS *regs); int ARCH_DEP(plo_csst) (int r1, int r3, VADR effective_addr2, int b2, VADR effective_addr4, int b4, REGS *regs); int ARCH_DEP(plo_csstg) (int r1, int r3, VADR effective_addr2, int b2, VADR effective_addr4, int b4, REGS *regs); int ARCH_DEP(plo_csstgr) (int r1, int r3, VADR effective_addr2, int b2, VADR effective_addr4, int b4, REGS *regs); int ARCH_DEP(plo_csstx) (int r1, int r3, VADR effective_addr2, int b2, VADR effective_addr4, int b4, REGS *regs); int ARCH_DEP(plo_csdst) (int r1, int r3, VADR effective_addr2, int b2, VADR effective_addr4, int b4, REGS *regs); int ARCH_DEP(plo_csdstg) (int r1, int r3, VADR effective_addr2, int b2, VADR effective_addr4, int b4, REGS *regs); int ARCH_DEP(plo_csdstgr) (int r1, int r3, VADR effective_addr2, int b2, VADR effective_addr4, int b4, REGS *regs); int ARCH_DEP(plo_csdstx) (int r1, int r3, VADR effective_addr2, int b2, VADR effective_addr4, int b4, REGS *regs); int ARCH_DEP(plo_cstst) (int r1, int r3, VADR effective_addr2, int b2, VADR effective_addr4, int b4, REGS *regs); int ARCH_DEP(plo_cststg) (int r1, int r3, VADR effective_addr2, int b2, VADR effective_addr4, int b4, REGS *regs); int ARCH_DEP(plo_cststgr) (int r1, int r3, VADR effective_addr2, int b2, VADR effective_addr4, int b4, REGS *regs); int ARCH_DEP(plo_cststx) (int r1, int r3, VADR effective_addr2, int b2, VADR effective_addr4, int b4, REGS *regs); /* Instruction functions in opcode.c */ DEF_INST(execute_01xx); DEF_INST(execute_a4xx); DEF_INST(execute_a5xx); DEF_INST(execute_a6xx); DEF_INST(execute_a7xx); DEF_INST(execute_b2xx); DEF_INST(execute_b3xx); DEF_INST(execute_b9xx); DEF_INST(execute_c0xx); DEF_INST(execute_e3xx); DEF_INST(execute_e4xx); DEF_INST(execute_e5xx); DEF_INST(execute_ebxx); DEF_INST(execute_ecxx); DEF_INST(execute_edxx); DEF_INST(operation_exception); DEF_INST(dummy_instruction); /* Instructions in assist.c */ DEF_INST(fix_page); DEF_INST(svc_assist); DEF_INST(obtain_local_lock); DEF_INST(release_local_lock); DEF_INST(obtain_cms_lock); DEF_INST(release_cms_lock); DEF_INST(trace_svc_interruption); DEF_INST(trace_program_interruption); DEF_INST(trace_initial_srb_dispatch); DEF_INST(trace_io_interruption); DEF_INST(trace_task_dispatch); DEF_INST(trace_svc_return); /* Instructions in cmpsc.c */ DEF_INST(compression_call); /* Instructions in crypto.c */ DEF_INST(cipher_message_r); DEF_INST(cipher_message_with_chaining_r); DEF_INST(compute_message_digest_r); DEF_INST(compute_message_authentication_code_r); /* Instructions in control.c */ DEF_INST(branch_and_set_authority); DEF_INST(branch_in_subspace_group); DEF_INST(branch_and_stack); DEF_INST(compare_and_swap_and_purge); DEF_INST(diagnose); DEF_INST(extract_primary_asn); DEF_INST(extract_primary_asn_and_instance); DEF_INST(extract_secondary_asn); DEF_INST(extract_secondary_asn_and_instance); DEF_INST(extract_stacked_registers); DEF_INST(extract_stacked_state); DEF_INST(insert_address_space_control); DEF_INST(insert_psw_key); DEF_INST(insert_storage_key); DEF_INST(insert_storage_key_extended); DEF_INST(insert_virtual_storage_key); DEF_INST(invalidate_page_table_entry); DEF_INST(load_address_space_parameters); DEF_INST(load_control); DEF_INST(load_program_status_word); DEF_INST(load_real_address); DEF_INST(load_using_real_address); DEF_INST(lock_page); DEF_INST(modify_stacked_state); DEF_INST(move_to_primary); DEF_INST(move_to_secondary); DEF_INST(move_with_destination_key); DEF_INST(move_with_key); DEF_INST(move_with_optional_specifications); /*208*/ DEF_INST(move_with_source_key); DEF_INST(program_call); DEF_INST(program_return); DEF_INST(program_transfer); DEF_INST(program_transfer_with_instance); DEF_INST(purge_accesslist_lookaside_buffer); DEF_INST(purge_translation_lookaside_buffer); DEF_INST(reset_reference_bit); DEF_INST(reset_reference_bit_extended); DEF_INST(set_address_space_control); DEF_INST(set_address_space_control_fast); DEF_INST(set_clock); DEF_INST(set_clock_comparator); DEF_INST(set_clock_programmable_field); DEF_INST(set_cpu_timer); DEF_INST(set_prefix); DEF_INST(set_psw_key_from_address); DEF_INST(set_secondary_asn); DEF_INST(set_secondary_asn_with_instance); DEF_INST(set_storage_key); DEF_INST(set_storage_key_extended); DEF_INST(set_system_mask); DEF_INST(signal_procesor); DEF_INST(store_clock_comparator); DEF_INST(store_control); DEF_INST(store_cpu_address); DEF_INST(store_cpu_id); DEF_INST(store_cpu_timer); DEF_INST(store_prefix); DEF_INST(store_system_information); DEF_INST(store_then_and_system_mask); DEF_INST(store_then_or_system_mask); DEF_INST(store_using_real_address); DEF_INST(test_access); DEF_INST(test_block); DEF_INST(test_protection); DEF_INST(trace); /* Instructions in decimal.c */ DEF_INST(add_decimal); DEF_INST(compare_decimal); DEF_INST(divide_decimal); DEF_INST(edit_x_edit_and_mark); DEF_INST(multiply_decimal); DEF_INST(shift_and_round_decimal); DEF_INST(subtract_decimal); DEF_INST(zero_and_add); DEF_INST(test_decimal); /* Instructions in vm.c */ DEF_INST(inter_user_communication_vehicle); /* Instructions in sie.c */ DEF_INST(start_interpretive_execution); DEF_INST(store_zone_parameter); DEF_INST(set_zone_parameter); DEF_INST(test_pending_zone_interrupt); /* Instructions in qdio.c */ DEF_INST(signal_adapter); /* Instructions in float.c */ DEF_INST(load_positive_float_long_reg); DEF_INST(load_negative_float_long_reg); DEF_INST(load_and_test_float_long_reg); DEF_INST(load_complement_float_long_reg); DEF_INST(halve_float_long_reg); DEF_INST(load_rounded_float_long_reg); DEF_INST(multiply_float_ext_reg); DEF_INST(multiply_float_long_to_ext_reg); DEF_INST(load_float_long_reg); DEF_INST(compare_float_long_reg); DEF_INST(add_float_long_reg); DEF_INST(subtract_float_long_reg); DEF_INST(multiply_float_long_reg); DEF_INST(divide_float_long_reg); DEF_INST(add_unnormal_float_long_reg); DEF_INST(subtract_unnormal_float_long_reg); DEF_INST(load_positive_float_short_reg); DEF_INST(load_negative_float_short_reg); DEF_INST(load_and_test_float_short_reg); DEF_INST(load_complement_float_short_reg); DEF_INST(halve_float_short_reg); DEF_INST(load_rounded_float_short_reg); DEF_INST(add_float_ext_reg); DEF_INST(subtract_float_ext_reg); DEF_INST(load_float_short_reg); DEF_INST(compare_float_short_reg); DEF_INST(add_float_short_reg); DEF_INST(subtract_float_short_reg); DEF_INST(multiply_float_short_to_long_reg); DEF_INST(divide_float_short_reg); DEF_INST(add_unnormal_float_short_reg); DEF_INST(subtract_unnormal_float_short_reg); DEF_INST(store_float_long); DEF_INST(multiply_float_long_to_ext); DEF_INST(load_float_long); DEF_INST(compare_float_long); DEF_INST(add_float_long); DEF_INST(subtract_float_long); DEF_INST(multiply_float_long); DEF_INST(divide_float_long); DEF_INST(add_unnormal_float_long); DEF_INST(subtract_unnormal_float_long); DEF_INST(store_float_short); DEF_INST(load_float_short); DEF_INST(compare_float_short); DEF_INST(add_float_short); DEF_INST(subtract_float_short); DEF_INST(multiply_float_short_to_long); DEF_INST(divide_float_short); DEF_INST(add_unnormal_float_short); DEF_INST(subtract_unnormal_float_short); DEF_INST(divide_float_ext_reg); DEF_INST(squareroot_float_long_reg); DEF_INST(squareroot_float_short_reg); DEF_INST(load_lengthened_float_short_to_long_reg); DEF_INST(load_lengthened_float_long_to_ext_reg); DEF_INST(load_lengthened_float_short_to_ext_reg); DEF_INST(squareroot_float_ext_reg); DEF_INST(multiply_float_short_reg); DEF_INST(load_positive_float_ext_reg); DEF_INST(load_negative_float_ext_reg); DEF_INST(load_and_test_float_ext_reg); DEF_INST(load_complement_float_ext_reg); DEF_INST(load_rounded_float_ext_to_short_reg); DEF_INST(load_fp_int_float_ext_reg); DEF_INST(compare_float_ext_reg); DEF_INST(load_fp_int_float_short_reg); DEF_INST(load_fp_int_float_long_reg); DEF_INST(convert_fixed_to_float_short_reg); DEF_INST(convert_fixed_to_float_long_reg); DEF_INST(convert_fixed_to_float_ext_reg); DEF_INST(convert_fix64_to_float_short_reg); DEF_INST(convert_fix64_to_float_long_reg); DEF_INST(convert_fix64_to_float_ext_reg); DEF_INST(convert_float_short_to_fixed_reg); DEF_INST(convert_float_long_to_fixed_reg); DEF_INST(convert_float_ext_to_fixed_reg); DEF_INST(convert_float_short_to_fix64_reg); /* under construction! Bernard van der Helm */ DEF_INST(convert_float_long_to_fix64_reg); /* under construction! Bernard van der Helm */ DEF_INST(convert_float_ext_to_fix64_reg); /* under construction! Bernard van der Helm */ DEF_INST(load_lengthened_float_short_to_long); DEF_INST(load_lengthened_float_long_to_ext); DEF_INST(load_lengthened_float_short_to_ext); DEF_INST(squareroot_float_short); DEF_INST(squareroot_float_long); DEF_INST(multiply_float_short); DEF_INST(load_float_ext_reg); DEF_INST(load_zero_float_short_reg); DEF_INST(load_zero_float_long_reg); DEF_INST(load_zero_float_ext_reg); DEF_INST(multiply_add_float_short_reg); DEF_INST(multiply_add_float_long_reg); DEF_INST(multiply_add_float_short); DEF_INST(multiply_add_float_long); DEF_INST(multiply_subtract_float_short_reg); DEF_INST(multiply_subtract_float_long_reg); DEF_INST(multiply_subtract_float_short); DEF_INST(multiply_subtract_float_long); DEF_INST(multiply_unnormal_float_long_to_ext_reg); /*@Z9*/ DEF_INST(multiply_unnormal_float_long_to_ext_low_reg); /*@Z9*/ DEF_INST(multiply_unnormal_float_long_to_ext_high_reg); /*@Z9*/ DEF_INST(multiply_add_unnormal_float_long_to_ext_reg); /*@Z9*/ DEF_INST(multiply_add_unnormal_float_long_to_ext_low_reg); /*@Z9*/ DEF_INST(multiply_add_unnormal_float_long_to_ext_high_reg); /*@Z9*/ DEF_INST(multiply_unnormal_float_long_to_ext); /*@Z9*/ DEF_INST(multiply_unnormal_float_long_to_ext_low); /*@Z9*/ DEF_INST(multiply_unnormal_float_long_to_ext_high); /*@Z9*/ DEF_INST(multiply_add_unnormal_float_long_to_ext); /*@Z9*/ DEF_INST(multiply_add_unnormal_float_long_to_ext_low); /*@Z9*/ DEF_INST(multiply_add_unnormal_float_long_to_ext_high); /*@Z9*/ DEF_INST(load_float_long_y); DEF_INST(load_float_short_y); DEF_INST(store_float_long_y); DEF_INST(store_float_short_y); /* Instructions in general1.c */ DEF_INST(add_register); DEF_INST(add); DEF_INST(add_halfword); DEF_INST(add_halfword_immediate); DEF_INST(add_logical_register); DEF_INST(add_logical); DEF_INST(and_register); DEF_INST(and); DEF_INST(and_immediate); DEF_INST(and_character); DEF_INST(branch_and_link_register); DEF_INST(branch_and_link); DEF_INST(branch_and_save_register); DEF_INST(branch_and_save); DEF_INST(branch_and_save_and_set_mode); DEF_INST(branch_and_set_mode); DEF_INST(branch_on_condition_register); DEF_INST(branch_on_condition); DEF_INST(branch_on_count_register); DEF_INST(branch_on_count); DEF_INST(branch_on_index_high); DEF_INST(branch_on_index_low_or_equal); DEF_INST(branch_relative_on_condition); DEF_INST(branch_relative_and_save); DEF_INST(branch_relative_on_count); DEF_INST(branch_relative_on_index_high); DEF_INST(branch_relative_on_index_low_or_equal); DEF_INST(checksum); DEF_INST(compare_register); DEF_INST(compare); DEF_INST(compare_and_form_codeword); DEF_INST(compare_and_swap); DEF_INST(compare_double_and_swap); DEF_INST(compare_and_swap_and_store); DEF_INST(compare_halfword); DEF_INST(compare_halfword_immediate); DEF_INST(compare_logical_register); DEF_INST(compare_logical); DEF_INST(compare_logical_immediate); DEF_INST(compare_logical_character); DEF_INST(compare_logical_characters_under_mask); DEF_INST(compare_logical_character_long); DEF_INST(compare_logical_long_extended); DEF_INST(compare_logical_string); DEF_INST(compare_until_substring_equal); DEF_INST(convert_utf16_to_utf8); DEF_INST(convert_utf16_to_utf32); DEF_INST(convert_utf32_to_utf16); DEF_INST(convert_utf32_to_utf8); DEF_INST(convert_utf8_to_utf16); DEF_INST(convert_utf8_to_utf32); DEF_INST(convert_to_binary); DEF_INST(convert_to_decimal); DEF_INST(copy_access); DEF_INST(divide_register); DEF_INST(divide); DEF_INST(exclusive_or_register); DEF_INST(exclusive_or); DEF_INST(exclusive_or_immediate); DEF_INST(exclusive_or_character); DEF_INST(execute); DEF_INST(execute_relative_long); /*208*/ DEF_INST(extract_access_register); DEF_INST(insert_character); DEF_INST(insert_characters_under_mask); DEF_INST(insert_program_mask); DEF_INST(load); DEF_INST(load_register); DEF_INST(load_access_multiple); DEF_INST(load_address); DEF_INST(load_address_extended); DEF_INST(load_and_test_register); DEF_INST(load_complement_register); DEF_INST(load_halfword); DEF_INST(load_halfword_immediate); DEF_INST(load_multiple); DEF_INST(load_negative_register); DEF_INST(load_positive_register); DEF_INST(monitor_call); DEF_INST(move_immediate); DEF_INST(move_character); DEF_INST(move_inverse); DEF_INST(move_long); DEF_INST(move_long_extended); DEF_INST(move_numerics); DEF_INST(move_string); DEF_INST(move_with_offset); DEF_INST(move_zones); DEF_INST(multiply_register); DEF_INST(multiply); DEF_INST(multiply_halfword); DEF_INST(multiply_halfword_immediate); DEF_INST(multiply_single_register); DEF_INST(multiply_single); /* Instructions in general2.c */ DEF_INST(or_register); DEF_INST(or); DEF_INST(or_immediate); DEF_INST(or_character); DEF_INST(perform_locked_operation); DEF_INST(pack); DEF_INST(search_string); DEF_INST(search_string_unicode); DEF_INST(set_access_register); DEF_INST(set_program_mask); DEF_INST(shift_left_double); DEF_INST(shift_left_double_logical); DEF_INST(shift_left_single); DEF_INST(shift_left_single_logical); DEF_INST(shift_right_double); DEF_INST(shift_right_double_logical); DEF_INST(shift_right_single); DEF_INST(shift_right_single_logical); DEF_INST(store); DEF_INST(store_access_multiple); DEF_INST(store_character); DEF_INST(store_characters_under_mask); DEF_INST(store_clock); DEF_INST(store_clock_extended); DEF_INST(store_clock_fast); /*@Z9*/ DEF_INST(store_halfword); DEF_INST(store_multiple); DEF_INST(subtract_register); DEF_INST(subtract); DEF_INST(subtract_halfword); DEF_INST(subtract_logical_register); DEF_INST(subtract_logical); DEF_INST(supervisor_call); DEF_INST(test_and_set); DEF_INST(test_under_mask); DEF_INST(test_under_mask_high); DEF_INST(test_under_mask_low); DEF_INST(translate); DEF_INST(translate_and_test); DEF_INST(translate_and_test_reverse); DEF_INST(translate_and_test_extended); /*208*/ DEF_INST(translate_and_test_reverse_extended); /*208*/ DEF_INST(translate_extended); DEF_INST(unpack); DEF_INST(update_tree); /* Instructions in general3.c */ DEF_INST(add_immediate_long_storage); /*208*/ DEF_INST(add_immediate_storage); /*208*/ DEF_INST(add_logical_with_signed_immediate); /*208*/ DEF_INST(add_logical_with_signed_immediate_long); /*208*/ DEF_INST(compare_and_branch_register); /*208*/ DEF_INST(compare_and_branch_long_register); /*208*/ DEF_INST(compare_and_branch_relative_register); /*208*/ DEF_INST(compare_and_branch_relative_long_register); /*208*/ DEF_INST(compare_and_trap_long_register); /*208*/ DEF_INST(compare_and_trap_register); /*208*/ DEF_INST(compare_halfword_immediate_halfword_storage); /*208*/ DEF_INST(compare_halfword_immediate_long_storage); /*208*/ DEF_INST(compare_halfword_immediate_storage); /*208*/ DEF_INST(compare_halfword_long); /*208*/ DEF_INST(compare_halfword_relative_long); /*208*/ DEF_INST(compare_halfword_relative_long_long); /*208*/ DEF_INST(compare_immediate_and_branch); /*208*/ DEF_INST(compare_immediate_and_branch_long); /*208*/ DEF_INST(compare_immediate_and_branch_relative); /*208*/ DEF_INST(compare_immediate_and_branch_relative_long); /*208*/ DEF_INST(compare_immediate_and_trap); /*208*/ DEF_INST(compare_immediate_and_trap_long); /*208*/ DEF_INST(compare_logical_and_branch_long_register); /*208*/ DEF_INST(compare_logical_and_branch_register); /*208*/ DEF_INST(compare_logical_and_branch_relative_long_register); /*208*/ DEF_INST(compare_logical_and_branch_relative_register); /*208*/ DEF_INST(compare_logical_and_trap_long_register); /*208*/ DEF_INST(compare_logical_and_trap_register); /*208*/ DEF_INST(compare_logical_immediate_and_branch); /*208*/ DEF_INST(compare_logical_immediate_and_branch_long); /*208*/ DEF_INST(compare_logical_immediate_and_branch_relative); /*208*/ DEF_INST(compare_logical_immediate_and_branch_relative_long); /*208*/ DEF_INST(compare_logical_immediate_and_trap_fullword); /*208*/ DEF_INST(compare_logical_immediate_and_trap_long); /*208*/ DEF_INST(compare_logical_immediate_fullword_storage); /*208*/ DEF_INST(compare_logical_immediate_halfword_storage); /*208*/ DEF_INST(compare_logical_immediate_long_storage); /*208*/ DEF_INST(compare_logical_relative_long); /*208*/ DEF_INST(compare_logical_relative_long_halfword); /*208*/ DEF_INST(compare_logical_relative_long_long); /*208*/ DEF_INST(compare_logical_relative_long_long_fullword); /*208*/ DEF_INST(compare_logical_relative_long_long_halfword); /*208*/ DEF_INST(compare_relative_long); /*208*/ DEF_INST(compare_relative_long_long); /*208*/ DEF_INST(compare_relative_long_long_fullword); /*208*/ DEF_INST(extract_cache_attribute); /*208*/ DEF_INST(load_address_extended_y); /*208*/ DEF_INST(load_and_test_long_fullword); /*208*/ DEF_INST(load_halfword_relative_long); /*208*/ DEF_INST(load_halfword_relative_long_long); /*208*/ DEF_INST(load_logical_halfword_relative_long); /*208*/ DEF_INST(load_logical_halfword_relative_long_long); /*208*/ DEF_INST(load_logical_relative_long_long_fullword); /*208*/ DEF_INST(load_relative_long); /*208*/ DEF_INST(load_relative_long_long); /*208*/ DEF_INST(load_relative_long_long_fullword); /*208*/ DEF_INST(move_fullword_from_halfword_immediate); /*208*/ DEF_INST(move_halfword_from_halfword_immediate); /*208*/ DEF_INST(move_long_from_halfword_immediate); /*208*/ DEF_INST(multiply_halfword_y); /*208*/ DEF_INST(multiply_single_immediate_fullword); /*208*/ DEF_INST(multiply_single_immediate_long_fullword); /*208*/ DEF_INST(multiply_y); /*208*/ DEF_INST(prefetch_data); /*208*/ DEF_INST(prefetch_data_relative_long); /*208*/ DEF_INST(rotate_then_and_selected_bits_long_reg); /*208*/ DEF_INST(rotate_then_exclusive_or_selected_bits_long_reg); /*208*/ DEF_INST(rotate_then_insert_selected_bits_long_reg); /*208*/ DEF_INST(rotate_then_or_selected_bits_long_reg); /*208*/ DEF_INST(store_halfword_relative_long); /*208*/ DEF_INST(store_relative_long); /*208*/ DEF_INST(store_relative_long_long); /*208*/ /* Instructions in io.c */ DEF_INST(clear_subchannel); DEF_INST(halt_subchannel); DEF_INST(modify_subchannel); DEF_INST(resume_subchannel); DEF_INST(set_address_limit); DEF_INST(set_channel_monitor); DEF_INST(reset_channel_path); DEF_INST(start_subchannel); DEF_INST(cancel_subchannel); DEF_INST(store_channel_path_status); DEF_INST(store_channel_report_word); DEF_INST(store_subchannel); DEF_INST(test_pending_interruption); DEF_INST(test_subchannel); DEF_INST(start_io); DEF_INST(test_io); DEF_INST(halt_io); DEF_INST(test_channel); DEF_INST(store_channel_id); DEF_INST(connect_channel_set); DEF_INST(disconnect_channel_set); /* Instructions in service.c */ DEF_INST(service_call); /* Instructions in chsc.c */ DEF_INST(channel_subsystem_call); /* Instructions in xstore.c */ DEF_INST(page_in); DEF_INST(page_out); DEF_INST(move_page); DEF_INST(invalidate_expanded_storage_block_entry); /* Instructions in vector.c */ DEF_INST(v_test_vmr); DEF_INST(v_complement_vmr); DEF_INST(v_count_left_zeros_in_vmr); DEF_INST(v_count_ones_in_vmr); DEF_INST(v_extract_vct); DEF_INST(v_extract_vector_modes); DEF_INST(v_restore_vr); DEF_INST(v_save_changed_vr); DEF_INST(v_save_vr); DEF_INST(v_load_vmr); DEF_INST(v_load_vmr_complement); DEF_INST(v_store_vmr); DEF_INST(v_and_to_vmr); DEF_INST(v_or_to_vmr); DEF_INST(v_exclusive_or_to_vmr); DEF_INST(v_save_vsr); DEF_INST(v_save_vmr); DEF_INST(v_restore_vsr); DEF_INST(v_restore_vmr); DEF_INST(v_load_vct_from_address); DEF_INST(v_clear_vr); DEF_INST(v_set_vector_mask_mode); DEF_INST(v_load_vix_from_address); DEF_INST(v_store_vector_parameters); DEF_INST(v_save_vac); DEF_INST(v_restore_vac); /* Instructions in esame.c */ DEF_INST(store_fpc); DEF_INST(load_fpc); DEF_INST(set_fpc); DEF_INST(extract_fpc); DEF_INST(set_bfp_rounding_mode); DEF_INST(trap2); DEF_INST(trap4); DEF_INST(resume_program); DEF_INST(trace_long); DEF_INST(convert_to_binary_long); DEF_INST(convert_to_decimal_long); DEF_INST(multiply_logical); DEF_INST(multiply_logical_long); DEF_INST(multiply_logical_register); DEF_INST(multiply_logical_long_register); DEF_INST(divide_logical); DEF_INST(divide_logical_long); DEF_INST(divide_logical_register); DEF_INST(divide_logical_long_register); DEF_INST(add_logical_carry_long_register); DEF_INST(subtract_logical_borrow_long_register); DEF_INST(add_logical_carry_long); DEF_INST(subtract_logical_borrow_long); DEF_INST(add_logical_carry_register); DEF_INST(subtract_logical_borrow_register); DEF_INST(add_logical_carry); DEF_INST(subtract_logical_borrow); DEF_INST(divide_single_long); DEF_INST(divide_single_long_fullword); DEF_INST(divide_single_long_register); DEF_INST(divide_single_long_fullword_register); DEF_INST(load_logical_long_character); DEF_INST(load_logical_long_halfword); DEF_INST(store_pair_to_quadword); DEF_INST(load_pair_from_quadword); DEF_INST(extract_stacked_registers_long); DEF_INST(extract_psw); DEF_INST(extract_and_set_extended_authority); DEF_INST(load_address_relative_long); DEF_INST(perform_frame_management_function); /*208*/ DEF_INST(perform_timing_facility_function); /*@Z9*/ DEF_INST(perform_topology_function); /*208*/ DEF_INST(store_facility_list); DEF_INST(store_facility_list_extended); /*@Z9*/ DEF_INST(load_long_halfword_immediate); DEF_INST(add_long_halfword_immediate); DEF_INST(multiply_long_halfword_immediate); DEF_INST(compare_long_halfword_immediate); DEF_INST(and_long); DEF_INST(or_long); DEF_INST(exclusive_or_long); DEF_INST(and_long_register); DEF_INST(or_long_register); DEF_INST(exclusive_or_long_register); DEF_INST(load_long_register); DEF_INST(add_logical_long_register); DEF_INST(add_logical_long_fullword_register); DEF_INST(subtract_logical_long_register); DEF_INST(subtract_logical_long_fullword_register); DEF_INST(load_control_long); DEF_INST(store_control_long); DEF_INST(load_multiple_disjoint); DEF_INST(load_multiple_high); DEF_INST(load_multiple_long); DEF_INST(store_multiple_high); DEF_INST(store_multiple_long); DEF_INST(load_using_real_address_long); DEF_INST(store_using_real_address_long); DEF_INST(test_addressing_mode); DEF_INST(set_addressing_mode_24); DEF_INST(set_addressing_mode_31); DEF_INST(set_addressing_mode_64); DEF_INST(load_program_status_word_extended); DEF_INST(store_long); DEF_INST(store_real_address); DEF_INST(load_long); DEF_INST(multiply_single_long_register); DEF_INST(multiply_single_long_fullword_register); DEF_INST(multiply_single_long); DEF_INST(multiply_single_long_fullword); DEF_INST(rotate_left_single_logical_long); DEF_INST(rotate_left_single_logical); DEF_INST(shift_right_single_long); DEF_INST(shift_left_single_long); DEF_INST(shift_right_single_logical_long); DEF_INST(shift_left_single_logical_long); DEF_INST(compare_logical_long); DEF_INST(compare_logical_long_fullword); DEF_INST(compare_logical_long_fullword_register); DEF_INST(load_logical_long_thirtyone_register); DEF_INST(compare_logical_long_register); DEF_INST(test_under_mask_high_high); DEF_INST(test_under_mask_high_low); DEF_INST(branch_relative_on_count_long); DEF_INST(load_positive_long_register); DEF_INST(load_negative_long_register); DEF_INST(load_and_test_long_register); DEF_INST(load_complement_long_register); DEF_INST(load_real_address_long); DEF_INST(load_long_fullword_register); DEF_INST(add_long_register); DEF_INST(add_long_fullword_register); DEF_INST(subtract_long_register); DEF_INST(subtract_long_fullword_register); DEF_INST(add_logical_long); DEF_INST(add_logical_long_fullword); DEF_INST(add_long); DEF_INST(add_long_fullword); DEF_INST(subtract_logical_long); DEF_INST(subtract_logical_long_fullword); DEF_INST(subtract_long); DEF_INST(subtract_long_fullword); DEF_INST(compare_long_register); DEF_INST(compare_long); DEF_INST(branch_on_count_long_register); DEF_INST(branch_on_count_long); DEF_INST(compare_and_swap_long); DEF_INST(compare_double_and_swap_long); DEF_INST(branch_on_index_high_long); DEF_INST(branch_on_index_low_or_equal_long); DEF_INST(branch_relative_on_index_high_long); DEF_INST(branch_relative_on_index_low_or_equal_long); DEF_INST(compare_logical_characters_under_mask_high); DEF_INST(store_characters_under_mask_high); DEF_INST(insert_characters_under_mask_high); DEF_INST(branch_relative_on_condition_long); DEF_INST(branch_relative_and_save_long); DEF_INST(compare_long_fullword_register); DEF_INST(load_positive_long_fullword_register); DEF_INST(load_negative_long_fullword_register); DEF_INST(load_and_test_long_fullword_register); DEF_INST(load_complement_long_fullword_register); DEF_INST(load_long_fullword); DEF_INST(load_long_halfword); DEF_INST(compare_long_fullword); DEF_INST(load_logical_long_fullword_register); DEF_INST(load_logical_long_fullword); DEF_INST(load_logical_long_thirtyone); DEF_INST(insert_immediate_high_high); DEF_INST(insert_immediate_high_low); DEF_INST(insert_immediate_low_high); DEF_INST(insert_immediate_low_low); DEF_INST(and_immediate_high_high); DEF_INST(and_immediate_high_low); DEF_INST(and_immediate_low_high); DEF_INST(and_immediate_low_low); DEF_INST(or_immediate_high_high); DEF_INST(or_immediate_high_low); DEF_INST(or_immediate_low_high); DEF_INST(or_immediate_low_low); DEF_INST(load_logical_immediate_high_high); DEF_INST(load_logical_immediate_high_low); DEF_INST(load_logical_immediate_low_high); DEF_INST(load_logical_immediate_low_low); DEF_INST(load_reversed_long_register); DEF_INST(load_reversed_register); DEF_INST(load_reversed_long); DEF_INST(load_reversed); DEF_INST(load_reversed_half); DEF_INST(store_reversed_long); DEF_INST(store_reversed); DEF_INST(store_reversed_half); DEF_INST(pack_ascii); DEF_INST(pack_unicode); DEF_INST(unpack_ascii); DEF_INST(unpack_unicode); DEF_INST(translate_two_to_two); DEF_INST(translate_two_to_one); DEF_INST(translate_one_to_two); DEF_INST(translate_one_to_one); DEF_INST(move_long_unicode); DEF_INST(compare_logical_long_unicode); DEF_INST(add_y); DEF_INST(add_halfword_y); DEF_INST(add_logical_y); DEF_INST(and_immediate_y); DEF_INST(and_y); DEF_INST(compare_y); DEF_INST(compare_and_swap_y); DEF_INST(compare_double_and_swap_y); DEF_INST(compare_halfword_y); DEF_INST(compare_logical_y); DEF_INST(compare_logical_immediate_y); DEF_INST(compare_logical_characters_under_mask_y); DEF_INST(convert_to_binary_y); DEF_INST(convert_to_decimal_y); DEF_INST(exclusive_or_immediate_y); DEF_INST(exclusive_or_y); DEF_INST(insert_character_y); DEF_INST(insert_characters_under_mask_y); DEF_INST(load_y); DEF_INST(load_access_multiple_y); DEF_INST(load_address_y); DEF_INST(load_byte); DEF_INST(load_byte_long); DEF_INST(load_halfword_y); DEF_INST(load_multiple_y); DEF_INST(load_real_address_y); DEF_INST(move_immediate_y); DEF_INST(multiply_single_y); DEF_INST(or_immediate_y); DEF_INST(or_y); DEF_INST(store_y); DEF_INST(store_access_multiple_y); DEF_INST(store_character_y); DEF_INST(store_characters_under_mask_y); DEF_INST(store_halfword_y); DEF_INST(store_multiple_y); DEF_INST(subtract_y); DEF_INST(subtract_halfword_y); DEF_INST(subtract_logical_y); DEF_INST(test_under_mask_y); DEF_INST(compare_and_swap_and_purge_long); DEF_INST(invalidate_dat_table_entry); DEF_INST(load_page_table_entry_address); /*@Z9*/ DEF_INST(add_fullword_immediate); /*@Z9*/ DEF_INST(add_long_fullword_immediate); /*@Z9*/ DEF_INST(add_logical_fullword_immediate); /*@Z9*/ DEF_INST(add_logical_long_fullword_immediate); /*@Z9*/ DEF_INST(and_immediate_high_fullword); /*@Z9*/ DEF_INST(and_immediate_low_fullword); /*@Z9*/ DEF_INST(compare_fullword_immediate); /*@Z9*/ DEF_INST(compare_long_fullword_immediate); /*@Z9*/ DEF_INST(compare_logical_fullword_immediate); /*@Z9*/ DEF_INST(compare_logical_long_fullword_immediate); /*@Z9*/ DEF_INST(exclusive_or_immediate_high_fullword); /*@Z9*/ DEF_INST(exclusive_or_immediate_low_fullword); /*@Z9*/ DEF_INST(insert_immediate_high_fullword); /*@Z9*/ DEF_INST(insert_immediate_low_fullword); /*@Z9*/ DEF_INST(load_long_fullword_immediate); /*@Z9*/ DEF_INST(load_logical_immediate_high_fullword); /*@Z9*/ DEF_INST(load_logical_immediate_low_fullword); /*@Z9*/ DEF_INST(or_immediate_high_fullword); /*@Z9*/ DEF_INST(or_immediate_low_fullword); /*@Z9*/ DEF_INST(subtract_logical_fullword_immediate); /*@Z9*/ DEF_INST(subtract_logical_long_fullword_immediate); /*@Z9*/ DEF_INST(load_and_test); /*@Z9*/ DEF_INST(load_and_test_long); /*@Z9*/ DEF_INST(load_byte_register); /*@Z9*/ DEF_INST(load_long_byte_register); /*@Z9*/ DEF_INST(load_halfword_register); /*@Z9*/ DEF_INST(load_long_halfword_register); /*@Z9*/ DEF_INST(load_logical_character); /*@Z9*/ DEF_INST(load_logical_character_register); /*@Z9*/ DEF_INST(load_logical_long_character_register); /*@Z9*/ DEF_INST(load_logical_halfword); /*@Z9*/ DEF_INST(load_logical_halfword_register); /*@Z9*/ DEF_INST(load_logical_long_halfword_register); /*@Z9*/ DEF_INST(find_leftmost_one_long_register); /*@Z9*/ DEF_INST(extract_cpu_time); /* Instructions in ecpsvm.c */ DEF_INST(ecpsvm_basic_freex); DEF_INST(ecpsvm_basic_fretx); DEF_INST(ecpsvm_lock_page); DEF_INST(ecpsvm_unlock_page); DEF_INST(ecpsvm_decode_next_ccw); DEF_INST(ecpsvm_free_ccwstor); DEF_INST(ecpsvm_locate_vblock); DEF_INST(ecpsvm_disp1); DEF_INST(ecpsvm_tpage); DEF_INST(ecpsvm_tpage_lock); DEF_INST(ecpsvm_inval_segtab); DEF_INST(ecpsvm_inval_ptable); DEF_INST(ecpsvm_decode_first_ccw); DEF_INST(ecpsvm_dispatch_main); DEF_INST(ecpsvm_locate_rblock); DEF_INST(ecpsvm_comm_ccwproc); DEF_INST(ecpsvm_unxlate_ccw); DEF_INST(ecpsvm_disp2); DEF_INST(ecpsvm_store_level); DEF_INST(ecpsvm_loc_chgshrpg); DEF_INST(ecpsvm_extended_freex); DEF_INST(ecpsvm_extended_fretx); DEF_INST(ecpsvm_prefmach_assist); /* Instructions in ieee.c */ DEF_INST(convert_bfp_long_to_float_long_reg); DEF_INST(convert_bfp_short_to_float_long_reg); DEF_INST(convert_float_long_to_bfp_long_reg); DEF_INST(convert_float_long_to_bfp_short_reg); DEF_INST(add_bfp_ext_reg); DEF_INST(add_bfp_long_reg); DEF_INST(add_bfp_long); DEF_INST(add_bfp_short_reg); DEF_INST(add_bfp_short); DEF_INST(compare_bfp_ext_reg); DEF_INST(compare_bfp_long_reg); DEF_INST(compare_bfp_long); DEF_INST(compare_bfp_short_reg); DEF_INST(compare_bfp_short); DEF_INST(compare_and_signal_bfp_ext_reg); DEF_INST(compare_and_signal_bfp_long_reg); DEF_INST(compare_and_signal_bfp_long); DEF_INST(compare_and_signal_bfp_short_reg); DEF_INST(compare_and_signal_bfp_short); DEF_INST(convert_fix32_to_bfp_ext_reg); DEF_INST(convert_fix32_to_bfp_long_reg); DEF_INST(convert_fix32_to_bfp_short_reg); DEF_INST(convert_fix64_to_bfp_ext_reg); DEF_INST(convert_fix64_to_bfp_long_reg); DEF_INST(convert_fix64_to_bfp_short_reg); DEF_INST(convert_bfp_ext_to_fix32_reg); DEF_INST(convert_bfp_long_to_fix32_reg); DEF_INST(convert_bfp_short_to_fix32_reg); DEF_INST(convert_bfp_ext_to_fix64_reg); DEF_INST(convert_bfp_long_to_fix64_reg); DEF_INST(convert_bfp_short_to_fix64_reg); DEF_INST(divide_bfp_ext_reg); DEF_INST(divide_bfp_long_reg); DEF_INST(divide_bfp_long); DEF_INST(divide_bfp_short_reg); DEF_INST(divide_bfp_short); DEF_INST(divide_integer_bfp_long_reg); DEF_INST(divide_integer_bfp_short_reg); DEF_INST(load_and_test_bfp_ext_reg); DEF_INST(load_and_test_bfp_long_reg); DEF_INST(load_and_test_bfp_short_reg); DEF_INST(load_fp_int_bfp_ext_reg); DEF_INST(load_fp_int_bfp_long_reg); DEF_INST(load_fp_int_bfp_short_reg); DEF_INST(load_lengthened_bfp_short_to_long_reg); DEF_INST(load_lengthened_bfp_short_to_long); DEF_INST(load_lengthened_bfp_long_to_ext_reg); DEF_INST(load_lengthened_bfp_long_to_ext); DEF_INST(load_lengthened_bfp_short_to_ext_reg); DEF_INST(load_lengthened_bfp_short_to_ext); DEF_INST(load_negative_bfp_ext_reg); DEF_INST(load_negative_bfp_long_reg); DEF_INST(load_negative_bfp_short_reg); DEF_INST(load_complement_bfp_ext_reg); DEF_INST(load_complement_bfp_long_reg); DEF_INST(load_complement_bfp_short_reg); DEF_INST(load_positive_bfp_ext_reg); DEF_INST(load_positive_bfp_long_reg); DEF_INST(load_positive_bfp_short_reg); DEF_INST(load_rounded_bfp_long_to_short_reg); DEF_INST(load_rounded_bfp_ext_to_long_reg); DEF_INST(load_rounded_bfp_ext_to_short_reg); DEF_INST(multiply_bfp_ext_reg); DEF_INST(multiply_bfp_long_to_ext_reg); DEF_INST(multiply_bfp_long_to_ext); DEF_INST(multiply_bfp_long_reg); DEF_INST(multiply_bfp_long); DEF_INST(multiply_bfp_short_to_long_reg); DEF_INST(multiply_bfp_short_to_long); DEF_INST(multiply_bfp_short_reg); DEF_INST(multiply_bfp_short); DEF_INST(multiply_add_bfp_long_reg); DEF_INST(multiply_add_bfp_long); DEF_INST(multiply_add_bfp_short_reg); DEF_INST(multiply_add_bfp_short); DEF_INST(multiply_subtract_bfp_long_reg); DEF_INST(multiply_subtract_bfp_long); DEF_INST(multiply_subtract_bfp_short_reg); DEF_INST(multiply_subtract_bfp_short); DEF_INST(squareroot_bfp_ext_reg); DEF_INST(squareroot_bfp_long_reg); DEF_INST(squareroot_bfp_long); DEF_INST(squareroot_bfp_short_reg); DEF_INST(squareroot_bfp_short); DEF_INST(subtract_bfp_ext_reg); DEF_INST(subtract_bfp_long_reg); DEF_INST(subtract_bfp_long); DEF_INST(subtract_bfp_short_reg); DEF_INST(subtract_bfp_short); DEF_INST(test_data_class_bfp_short); DEF_INST(test_data_class_bfp_long); DEF_INST(test_data_class_bfp_ext); /* Instructions in dfp.c */ DEF_INST(copy_sign_fpr_long_reg); DEF_INST(load_complement_fpr_long_reg); DEF_INST(load_fpr_from_gr_long_reg); DEF_INST(load_gr_from_fpr_long_reg); DEF_INST(load_negative_fpr_long_reg); DEF_INST(load_positive_fpr_long_reg); DEF_INST(set_dfp_rounding_mode); DEF_INST(load_fpc_and_signal); DEF_INST(set_fpc_and_signal); DEF_INST(add_dfp_ext_reg); DEF_INST(add_dfp_long_reg); DEF_INST(compare_dfp_ext_reg); DEF_INST(compare_dfp_long_reg); DEF_INST(compare_and_signal_dfp_ext_reg); DEF_INST(compare_and_signal_dfp_long_reg); DEF_INST(compare_exponent_dfp_ext_reg); DEF_INST(compare_exponent_dfp_long_reg); DEF_INST(convert_fix64_to_dfp_ext_reg); DEF_INST(convert_fix64_to_dfp_long_reg); DEF_INST(convert_sbcd128_to_dfp_ext_reg); DEF_INST(convert_sbcd64_to_dfp_long_reg); DEF_INST(convert_ubcd128_to_dfp_ext_reg); DEF_INST(convert_ubcd64_to_dfp_long_reg); DEF_INST(convert_dfp_ext_to_fix64_reg); DEF_INST(convert_dfp_long_to_fix64_reg); DEF_INST(convert_dfp_ext_to_sbcd128_reg); DEF_INST(convert_dfp_long_to_sbcd64_reg); DEF_INST(convert_dfp_ext_to_ubcd128_reg); DEF_INST(convert_dfp_long_to_ubcd64_reg); DEF_INST(divide_dfp_ext_reg); DEF_INST(divide_dfp_long_reg); DEF_INST(extract_biased_exponent_dfp_ext_to_fix64_reg); DEF_INST(extract_biased_exponent_dfp_long_to_fix64_reg); DEF_INST(extract_significance_dfp_ext_reg); DEF_INST(extract_significance_dfp_long_reg); DEF_INST(insert_biased_exponent_fix64_to_dfp_ext_reg); DEF_INST(insert_biased_exponent_fix64_to_dfp_long_reg); DEF_INST(load_and_test_dfp_ext_reg); DEF_INST(load_and_test_dfp_long_reg); DEF_INST(load_fp_int_dfp_ext_reg); DEF_INST(load_fp_int_dfp_long_reg); DEF_INST(load_lengthened_dfp_long_to_ext_reg); DEF_INST(load_lengthened_dfp_short_to_long_reg); DEF_INST(load_rounded_dfp_ext_to_long_reg); DEF_INST(load_rounded_dfp_long_to_short_reg); DEF_INST(multiply_dfp_ext_reg); DEF_INST(multiply_dfp_long_reg); DEF_INST(quantize_dfp_ext_reg); DEF_INST(quantize_dfp_long_reg); DEF_INST(reround_dfp_ext_reg); DEF_INST(reround_dfp_long_reg); DEF_INST(shift_coefficient_left_dfp_ext); DEF_INST(shift_coefficient_left_dfp_long); DEF_INST(shift_coefficient_right_dfp_ext); DEF_INST(shift_coefficient_right_dfp_long); DEF_INST(subtract_dfp_ext_reg); DEF_INST(subtract_dfp_long_reg); DEF_INST(test_data_class_dfp_ext); DEF_INST(test_data_class_dfp_long); DEF_INST(test_data_class_dfp_short); DEF_INST(test_data_group_dfp_ext); DEF_INST(test_data_group_dfp_long); DEF_INST(test_data_group_dfp_short); /* Instructions in pfpo.c */ DEF_INST(perform_floating_point_operation); /* end of OPCODE.H */ hercules-3.07/panel.c000644 000765 000765 00000314555 11344073445 016230 0ustar00jmaynardjmaynard000000 000000 /* PANEL.C (c) Copyright Roger Bowler, 1999-2010 */ /* Hercules Control Panel Commands */ // $Id: panel.c 5646 2010-03-03 15:25:14Z rbowler $ /* Modified for New Panel Display =NP= */ /*-------------------------------------------------------------------*/ /* This module is the control panel for the ESA/390 emulator. */ /* It provides a command interface into hercules, and it displays */ /* messages that are issued by various hercules components. */ /*-------------------------------------------------------------------*/ /*-------------------------------------------------------------------*/ /* Additional credits: */ /* breakpoint command contributed by Dan Horak */ /* devinit command contributed by Jay Maynard */ /* New Panel Display contributed by Dutch Owen */ /* HMC system console commands contributed by Jan Jaeger */ /* Set/reset bad frame indicator command by Jan Jaeger */ /* attach/detach/define commands by Jan Jaeger */ /* Panel refresh rate triva by Reed H. Petty */ /* z/Architecture support - (c) Copyright Jan Jaeger, 1999-2007 */ /* 64-bit address support by Roger Bowler */ /* Display subchannel command by Nobumichi Kozawa */ /* External GUI logic contributed by "Fish" (David B. Trout) */ /* Socket Devices originally designed by Malcolm Beattie; */ /* actual implementation by "Fish" (David B. Trout). */ /*-------------------------------------------------------------------*/ #include "hstdinc.h" #define _PANEL_C_ #define _HENGINE_DLL_ #include "hercules.h" #include "devtype.h" #include "opcode.h" #include "history.h" // #include "inline.h" #include "fillfnam.h" #include "hconsole.h" #define DISPLAY_INSTRUCTION_OPERANDS #define PANEL_MAX_ROWS (256) #define PANEL_MAX_COLS (256) int redraw_msgs; /* 1=Redraw message area */ int redraw_cmd; /* 1=Redraw command line */ int redraw_status; /* 1=Redraw status line */ /*=NP================================================================*/ /* Global data for new panel display */ /* (Note: all NPD mods are identified by the string =NP= */ /*===================================================================*/ static int NPDup = 0; /* 1 = new panel is up */ static int NPDinit = 0; /* 1 = new panel initialized */ static int NPhelpup = 0; /* 1 = help panel showing */ static int NPhelppaint = 1; /* 1 = help pnl s/b painted */ static int NPhelpdown = 0; /* 1 = help pnl coming down */ static int NPregdisp = 0; /* which regs are displayed: */ /* 0=gpr, 1=cr, 2=ar, 3=fpr */ static int NPcmd = 0; /* 1 = NP in command mode */ static int NPdataentry = 0; /* 1 = NP in data-entry mode */ static int NPdevsel = 0; /* 1 = device being selected */ static char NPpending; /* pending data entry cmd */ static char NPentered[256]; /* Data which was entered */ static char NPprompt1[40]; /* Left bottom screen prompt */ static char NPoldprompt1[40]; /* Left bottom screen prompt */ static char NPprompt2[40]; /* Right bottom screen prompt*/ static char NPoldprompt2[40]; /* Right bottom screen prompt*/ static char NPsel2; /* dev sel part 2 cmd letter */ static char NPdevice; /* Which device is selected */ static int NPasgn; /* Index to dev being init'ed*/ static int NPlastdev; /* Number of devices */ static int NPcpugraph_ncpu; /* Number of CPUs to display */ static char *NPregnum[] = {" 0"," 1"," 2"," 3"," 4"," 5"," 6"," 7", " 8"," 9","10","11","12","13","14","15" }; static char *NPregnum64[] = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F" }; /* Boolean fields; redraw the corresponding data field if false */ static int NPcpunum_valid, NPcpupct_valid, NPpsw_valid, NPpswstate_valid, NPregs_valid, NPaddr_valid, NPdata_valid, #ifdef OPTION_MIPS_COUNTING NPmips_valid, NPsios_valid, #endif // OPTION_MIPS_COUNTING NPdevices_valid, NPcpugraph_valid; /* Current CPU states */ static U16 NPcpunum; static int NPcpupct; static int NPpswmode; static int NPpswzhost; static QWORD NPpsw; static char NPpswstate[16]; static int NPregmode; static int NPregzhost; static U64 NPregs64[16]; static U32 NPregs[16]; static U32 NPaddress; static U32 NPdata; #ifdef OPTION_MIPS_COUNTING static U32 NPmips; static U32 NPsios; #else static U64 NPinstcount; #endif // OPTION_MIPS_COUNTING static int NPcpugraph; static int NPcpugraphpct[MAX_CPU_ENGINES]; /* Current device states */ #define NP_MAX_DEVICES (PANEL_MAX_ROWS - 3) static int NPonline[NP_MAX_DEVICES]; static U16 NPdevnum[NP_MAX_DEVICES]; static int NPbusy[NP_MAX_DEVICES]; static U16 NPdevtype[NP_MAX_DEVICES]; static int NPopen[NP_MAX_DEVICES]; static char NPdevnam[NP_MAX_DEVICES][128]; static short NPcurrow, NPcurcol; static int NPcolorSwitch; static short NPcolorFore; static short NPcolorBack; static int NPdatalen; static char *NPhelp[] = { "All commands consist of one character keypresses. The various commands are", "highlighted onscreen by bright white versus the gray of other lettering.", " ", "Press the escape key to terminate the control panel and go to command mode.", " ", "Display Controls: G - General purpose regs C - Control regs", " A - Access registers F - Floating Point regs", " I - Display main memory at 'ADDRESS'", "CPU controls: L - IPL S - Start CPU", " E - External interrupt P - Stop CPU", " W - Exit Hercules T - Restart interrupt", "Storage update: R - Enter ADDRESS to be updated", " D - Enter DATA to be updated at ADDRESS", " O - place DATA value at ADDRESS", " ", "Peripherals: N - enter a new name for the device file assignment", " U - send an I/O attention interrupt", " ", "In the display of devices, a green device letter means the device is online,", "a lighted device address means the device is busy, and a green model number", "means the attached file is open to the device", " ", " Press Escape to return to control panel operations", "" }; /////////////////////////////////////////////////////////////////////// #define MSG_SIZE PANEL_MAX_COLS /* Size of one message */ #define MAX_MSGS 2048 /* Number of slots in buffer */ //#define MAX_MSGS 300 /* (for testing scrolling) */ #define MSG_LINES (cons_rows - 2) /* #lines in message area */ #define SCROLL_LINES (MSG_LINES - numkept) /* #of scrollable lines */ #define CMD_SIZE 256 /* cmdline buffer size */ /////////////////////////////////////////////////////////////////////// static int cons_rows = 0; /* console height in lines */ static int cons_cols = 0; /* console width in chars */ static short cur_cons_row = 0; /* current console row */ static short cur_cons_col = 0; /* current console column */ static char *cons_term = NULL; /* TERM env value */ static char cmdins = 1; /* 1==insert mode, 0==overlay*/ static char cmdline[CMD_SIZE+1]; /* Command line buffer */ static int cmdlen = 0; /* cmdline data len in bytes */ static int cmdoff = 0; /* cmdline buffer cursor pos */ static int cursor_on_cmdline = 1; /* bool: cursor on cmdline */ static char saved_cmdline[CMD_SIZE+1]; /* Saved command */ static int saved_cmdlen = 0; /* Saved cmdline data len */ static int saved_cmdoff = 0; /* Saved cmdline buffer pos */ static short saved_cons_row = 0; /* Saved console row */ static short saved_cons_col = 0; /* Saved console column */ static int cmdcols = 0; /* visible cmdline width cols*/ static int cmdcol = 0; /* cols cmdline scrolled righ*/ static FILE *confp = NULL; /* Console file pointer */ /////////////////////////////////////////////////////////////////////// #define CMD_PREFIX_STR "Command ==> " /* Keep same len as below! */ #ifdef OPTION_CMDTGT #define CMD_PREFIX_STR1 "SCP ======> " /* Keep same len as above! */ #define CMD_PREFIX_STR2 "PrioSCP ==> " /* Keep same len as above! */ #endif // OPTION_CMDTGT #define CMD_PREFIX_LEN (strlen(CMD_PREFIX_STR)) #define CMDLINE_ROW ((short)(cons_rows-1)) #define CMDLINE_COL ((short)(CMD_PREFIX_LEN+1)) /////////////////////////////////////////////////////////////////////// #define ADJ_SCREEN_SIZE() \ do { \ int rows, cols; \ get_dim (&rows, &cols); \ if (rows != cons_rows || cols != cons_cols) { \ cons_rows = rows; \ cons_cols = cols; \ cmdcols = cons_cols - CMDLINE_COL; \ redraw_msgs = redraw_cmd = redraw_status = 1; \ NPDinit = 0; \ clr_screen(); \ } \ } while (0) #define ADJ_CMDCOL() /* (called after modifying cmdoff) */ \ do { \ if (cmdoff-cmdcol > cmdcols) { /* past right edge of screen */ \ cmdcol = cmdoff-cmdcols; \ } else if (cmdoff < cmdcol) { /* past left edge of screen */ \ cmdcol = cmdoff; \ } \ } while (0) #define PUTC_CMDLINE() \ do { \ ASSERT(cmdcol <= cmdlen); \ for (i=0; cmdcol+i < cmdlen && i < cmdcols; i++) \ draw_char (cmdline[cmdcol+i]); \ } while (0) /////////////////////////////////////////////////////////////////////// typedef struct _PANMSG /* Panel message control block structure */ { struct _PANMSG* next; /* --> next entry in chain */ struct _PANMSG* prev; /* --> prev entry in chain */ int msgnum; /* msgbuf 0-relative entry# */ char msg[MSG_SIZE]; /* text of panel message */ #if defined(OPTION_MSGCLR) short fg; /* text color */ short bg; /* screen background color */ #if defined(OPTION_MSGHLD) int keep:1; /* sticky flag */ struct timeval expiration; /* when to unstick if sticky */ #endif // defined(OPTION_MSGHLD) #endif // defined(OPTION_MSGCLR) } PANMSG; /* Panel message control block structure */ static PANMSG* msgbuf; /* Circular message buffer */ static PANMSG* topmsg; /* message at top of screen */ static PANMSG* curmsg; /* newest message */ static int wrapped = 0; /* wrapped-around flag */ static int numkept = 0; /* count of kept messages */ static int npquiet = 0; /* screen updating flag */ /////////////////////////////////////////////////////////////////////// static char *lmsbuf = NULL; /* xxx */ static int lmsndx = 0; /* xxx */ static int lmsnum = -1; /* xxx */ static int lmscnt = -1; /* xxx */ static int lmsmax = LOG_DEFSIZE/2; /* xxx */ static int keybfd = -1; /* Keyboard file descriptor */ static REGS copyregs, copysieregs; /* Copied regs */ /////////////////////////////////////////////////////////////////////// #if defined(OPTION_MSGCLR) /* -- Message coloring build option -- */ #if defined(OPTION_MSGHLD) /* -- Sticky messages build option -- */ #define KEEP_TIMEOUT_SECS 120 /* #seconds kept msgs expire */ static PANMSG* keptmsgs; /* start of keep chain */ static PANMSG* lastkept; /* last entry in keep chain */ /*-------------------------------------------------------------------*/ /* Remove and Free a keep chain entry from the keep chain */ /*-------------------------------------------------------------------*/ static void unkeep( PANMSG* pk ) { if (pk->prev) pk->prev->next = pk->next; if (pk->next) pk->next->prev = pk->prev; if (pk == keptmsgs) keptmsgs = pk->next; if (pk == lastkept) lastkept = pk->prev; free( pk ); numkept--; } /*-------------------------------------------------------------------*/ /* Allocate and Add a new kept message to the keep chain */ /*-------------------------------------------------------------------*/ static void keep( PANMSG* p ) { PANMSG* pk; ASSERT( p->keep ); pk = malloc( sizeof(PANMSG) ); memcpy( pk, p, sizeof(PANMSG) ); if (!keptmsgs) keptmsgs = pk; pk->next = NULL; pk->prev = lastkept; if (lastkept) lastkept->next = pk; lastkept = pk; numkept++; /* Must ensure we always have at least 2 scrollable lines */ while (SCROLL_LINES < 2) { /* Permanently unkeep oldest kept message */ msgbuf[keptmsgs->msgnum].keep = 0; unkeep( keptmsgs ); } } /*-------------------------------------------------------------------*/ /* Remove a kept message from the kept chain */ /*-------------------------------------------------------------------*/ static void unkeep_by_keepnum( int keepnum, int perm ) { PANMSG* pk; int i; /* Validate call */ if (!numkept || keepnum < 0 || keepnum > numkept-1) { ASSERT(FALSE); // bad 'keepnum' passed! return; } /* Chase keep chain to find kept message to be unkept */ for (i=0, pk=keptmsgs; pk && i != keepnum; pk = pk->next, i++); /* If kept message found, unkeep it */ if (pk) { if (perm) { msgbuf[pk->msgnum].keep = 0; #if defined(_DEBUG) || defined(DEBUG) msgbuf[pk->msgnum].fg = COLOR_YELLOW; #endif // defined(_DEBUG) || defined(DEBUG) } unkeep(pk); } } #endif // defined(OPTION_MSGHLD) #endif // defined(OPTION_MSGCLR) /*-------------------------------------------------------------------*/ /* unkeep messages once expired */ /*-------------------------------------------------------------------*/ void expire_kept_msgs(int unconditional) { #if defined(OPTION_MSGHLD) struct timeval now; PANMSG *pk = keptmsgs; int i; gettimeofday(&now, NULL); while (pk) { for (i=0, pk=keptmsgs; pk; i++, pk = pk->next) { if (unconditional || now.tv_sec >= pk->expiration.tv_sec) { unkeep_by_keepnum(i,1); // remove message from chain break; // start over again from the beginning } } } #endif // defined(OPTION_MSGHLD) } #if defined(OPTION_MSGCLR) /* -- Message coloring build option -- */ /*-------------------------------------------------------------------*/ /* Get the color name from a string */ /*-------------------------------------------------------------------*/ #define CHECKCOLOR(s, cs, c, cc) if(!strncasecmp(s, cs, sizeof(cs) - 1)) { *c = cc; return(sizeof(cs) - 1); } int get_color(char *string, short *color) { CHECKCOLOR(string, "black", color, COLOR_BLACK) else CHECKCOLOR(string, "cyan", color, COLOR_CYAN) else CHECKCOLOR(string, "blue", color, COLOR_BLUE) else CHECKCOLOR(string, "darkgrey", color, COLOR_DARK_GREY) else CHECKCOLOR(string, "green", color, COLOR_GREEN) else CHECKCOLOR(string, "lightblue", color, COLOR_LIGHT_BLUE) else CHECKCOLOR(string, "lightcyan", color, COLOR_LIGHT_CYAN) else CHECKCOLOR(string, "lightgreen", color, COLOR_LIGHT_GREEN) else CHECKCOLOR(string, "lightgrey", color, COLOR_LIGHT_GREY) else CHECKCOLOR(string, "lightmagenta", color, COLOR_LIGHT_MAGENTA) else CHECKCOLOR(string, "lightred", color, COLOR_LIGHT_RED) else CHECKCOLOR(string, "lightyellow", color, COLOR_LIGHT_YELLOW) else CHECKCOLOR(string, "magenta", color, COLOR_MAGENTA) else CHECKCOLOR(string, "red", color, COLOR_RED) else CHECKCOLOR(string, "white", color, COLOR_WHITE) else CHECKCOLOR(string, "yellow", color, COLOR_YELLOW) else return(0); } /*-------------------------------------------------------------------*/ /* Read, process and remove the "" colorizing message prefix */ /* Syntax: */ /* */ /* Mandatory prefix "" */ /* Valid tokens: */ /* color(fg, bg) specifies the message's color */ /* keep keeps message on screen until removed */ /*-------------------------------------------------------------------*/ void colormsg(PANMSG *p) { int i = 0; // current message text index int len; // length of color-name token if(!strncasecmp(p->msg, "" panel command(s) i += 4; while(p->msg[i] == ',') { i += 1; // skip , if(!strncasecmp(&p->msg[i], "color(", 6)) { // inspect color command i += 6; // skip color( len = get_color(&p->msg[i], &p->fg); if(!len) break; // no valid color found i += len; // skip colorname if(p->msg[i] != ',') break; // no , i++; // skip , len = get_color(&p->msg[i], &p->bg); if(!len) break; // no valid color found i += len; // skip colorname if(p->msg[i] != ')') break; // no ) i++; // skip ) } else if(!strncasecmp(&p->msg[i], "keep", 4)) { #if defined(OPTION_MSGHLD) p->keep = 1; gettimeofday(&p->expiration, NULL); p->expiration.tv_sec += sysblk.keep_timeout_secs; #endif // defined(OPTION_MSGHLD) i += 4; // skip keep } else break; // rubbish } if(p->msg[i] == '>') { // Remove "" string from message i += 1; memmove(p->msg, &p->msg[i], MSG_SIZE - i); memset(&p->msg[MSG_SIZE - i], SPACE, i); return; } } /* rubbish or no panel command */ p->fg = COLOR_DEFAULT_FG; p->bg = COLOR_DEFAULT_BG; #if defined(OPTION_MSGHLD) p->keep = 0; #endif // defined(OPTION_MSGHLD) } #endif // defined(OPTION_MSGCLR) /*-------------------------------------------------------------------*/ /* Screen manipulation primitives */ /*-------------------------------------------------------------------*/ static void beep() { console_beep( confp ); } static PANMSG* oldest_msg() { return (wrapped) ? curmsg->next : msgbuf; } static PANMSG* newest_msg() { return curmsg; } static int lines_scrolled() { /* return # of lines 'up' from current line that we're scrolled. */ if (topmsg->msgnum <= curmsg->msgnum) return curmsg->msgnum - topmsg->msgnum; return MAX_MSGS - (topmsg->msgnum - curmsg->msgnum); } static int visible_lines() { return (lines_scrolled() + 1); } static int is_currline_visible() { return (visible_lines() <= SCROLL_LINES); } static int lines_remaining() { return (SCROLL_LINES - visible_lines()); } static void scroll_up_lines( int numlines, int doexpire ) { int i; if (doexpire) expire_kept_msgs(0); for (i=0; i < numlines && topmsg != oldest_msg(); i++) { topmsg = topmsg->prev; // If new topmsg is simply the last entry in the keep chain // then we didn't really backup a line (all we did was move // our topmsg ptr), so if that's the case then we need to // continue backing up until we reach a non-kept message. // Only then is the screen actually scrolled up one line. while (1 && topmsg->keep && lastkept && lastkept->msgnum == topmsg->msgnum ) { unkeep( lastkept ); if (topmsg == oldest_msg()) break; topmsg = topmsg->prev; } } } static void scroll_down_lines( int numlines, int doexpire ) { int i; if (doexpire) expire_kept_msgs(0); for (i=0; i < numlines && topmsg != newest_msg(); i++) { // If the topmsg should be kept and is not already in our // keep chain, then adding it to our keep chain before // setting topmsg to the next entry does not really scroll // the screen any (all it does is move the topmsg ptr), // so if that's the case then we need to keep doing that // until we eventually find the next non-kept message. // Only then is the screen really scrolled down one line. while (1 && topmsg->keep && (!lastkept || topmsg->msgnum != lastkept->msgnum) ) { keep( topmsg ); topmsg = topmsg->next; if (topmsg == newest_msg()) break; } if (topmsg != newest_msg()) topmsg = topmsg->next; } } static void page_up( int doexpire ) { if (doexpire) expire_kept_msgs(0); scroll_up_lines( SCROLL_LINES - 1, 0 ); } static void page_down( int doexpire ) { if (doexpire) expire_kept_msgs(0); scroll_down_lines( SCROLL_LINES - 1, 0 ); } static void scroll_to_top_line( int doexpire ) { if (doexpire) expire_kept_msgs(0); topmsg = oldest_msg(); while (keptmsgs) unkeep( keptmsgs ); } static void scroll_to_bottom_line( int doexpire ) { if (doexpire) expire_kept_msgs(0); while (topmsg != newest_msg()) scroll_down_lines( 1, 0 ); } static void scroll_to_bottom_screen( int doexpire ) { if (doexpire) expire_kept_msgs(0); scroll_to_bottom_line( 0 ); page_up( 0 ); } static void do_panel_command( void* cmd ) { if (!is_currline_visible()) scroll_to_bottom_screen( 1 ); strlcpy( cmdline, cmd, sizeof(cmdline) ); panel_command( cmdline ); cmdline[0] = '\0'; cmdlen = 0; cmdoff = 0; ADJ_CMDCOL(); } static void do_prev_history() { if (history_prev() != -1) { strcpy(cmdline, historyCmdLine); cmdlen = strlen(cmdline); cmdoff = cmdlen < cmdcols ? cmdlen : 0; ADJ_CMDCOL(); } } static void do_next_history() { if (history_next() != -1) { strcpy(cmdline, historyCmdLine); cmdlen = strlen(cmdline); cmdoff = cmdlen < cmdcols ? cmdlen : 0; ADJ_CMDCOL(); } } static void clr_screen () { clear_screen (confp); } static void get_dim (int *y, int *x) { get_console_dim( confp, y, x); if (*y > PANEL_MAX_ROWS) *y = PANEL_MAX_ROWS; if (*x > PANEL_MAX_COLS) *x = PANEL_MAX_COLS; #if defined(WIN32) && !defined( _MSVC_ ) /* If running from a cygwin command prompt we do * better with one less row. */ if (!cons_term || strcmp(cons_term, "xterm")) (*y)--; #endif // defined(WIN32) && !defined( _MSVC_ ) } int get_keepnum_by_row( int row ) { // PROGRAMMING NOTE: right now all of our kept messages are // always placed at the very top of the screen (starting on // line 1), but should we at some point in the future decide // to use the very top line of the screen for something else // (such as a title or status line for example), then all we // need to do is modify the below variable and the code then // adjusts itself automatically. (I try to avoid hard-coded // constants whenever possible). -- Fish static int keep_beg_row = 1; // screen 1-relative line# of first kept msg if (0 || row < keep_beg_row || row > (keep_beg_row + numkept - 1) ) return -1; return (row - keep_beg_row); } static void set_color (short fg, short bg) { set_screen_color (confp, fg, bg); } static void set_pos (short y, short x) { cur_cons_row = y; cur_cons_col = x; y = y < 1 ? 1 : y > cons_rows ? cons_rows : y; x = x < 1 ? 1 : x > cons_cols ? cons_cols : x; set_screen_pos (confp, y, x); } static int is_cursor_on_cmdline() { #if defined(OPTION_EXTCURS) get_cursor_pos( keybfd, confp, &cur_cons_row, &cur_cons_col ); cursor_on_cmdline = (1 && cur_cons_row == CMDLINE_ROW && cur_cons_col >= CMDLINE_COL && cur_cons_col <= CMDLINE_COL + cmdcols ); #else // !defined(OPTION_EXTCURS) cursor_on_cmdline = 1; #endif // defined(OPTION_EXTCURS) return cursor_on_cmdline; } static void cursor_cmdline_home() { cmdoff = 0; ADJ_CMDCOL(); set_pos( CMDLINE_ROW, CMDLINE_COL ); } static void cursor_cmdline_end() { cmdoff = cmdlen; ADJ_CMDCOL(); set_pos( CMDLINE_ROW, CMDLINE_COL + cmdoff - cmdcol ); } static void save_command_line() { memcpy( saved_cmdline, cmdline, sizeof(saved_cmdline) ); saved_cmdlen = cmdlen; saved_cmdoff = cmdoff; saved_cons_row = cur_cons_row; saved_cons_col = cur_cons_col; } static void restore_command_line() { memcpy( cmdline, saved_cmdline, sizeof(cmdline) ); cmdlen = saved_cmdlen; cmdoff = saved_cmdoff; cur_cons_row = saved_cons_row; cur_cons_col = saved_cons_col; } static void draw_text (char *text) { int len; char *short_text; if (cur_cons_row < 1 || cur_cons_row > cons_rows || cur_cons_col < 1 || cur_cons_col > cons_cols) return; len = strlen(text); if ((cur_cons_col + len - 1) <= cons_cols) fprintf (confp, "%s", text); else { len = cons_cols - cur_cons_col + 1; if ((short_text = strdup(text)) == NULL) return; short_text[len] = '\0'; fprintf (confp, "%s", short_text); free (short_text); } cur_cons_col += len; } static void write_text (char *text, int size) { if (cur_cons_row < 1 || cur_cons_row > cons_rows || cur_cons_col < 1 || cur_cons_col > cons_cols) return; if (cons_cols - cur_cons_col + 1 < size) size = cons_cols - cur_cons_col + 1; fwrite (text, size, 1, confp); cur_cons_col += size; } static void draw_char (int c) { if (cur_cons_row < 1 || cur_cons_row > cons_rows || cur_cons_col < 1 || cur_cons_col > cons_cols) return; fputc (c, confp); cur_cons_col++; } static void draw_fw (U32 fw) { char buf[9]; sprintf (buf, "%8.8X", fw); draw_text (buf); } static void draw_dw (U64 dw) { char buf[17]; sprintf (buf, "%16.16"I64_FMT"X", dw); draw_text (buf); } static void fill_text (char c, short x) { char buf[PANEL_MAX_COLS+1]; int len; if (x > PANEL_MAX_COLS) x = PANEL_MAX_COLS; len = x + 1 - cur_cons_col; if (len <= 0) return; memset (buf, c, len); buf[len] = '\0'; draw_text (buf); } static void draw_button (short bg, short fg, short hfg, char *left, char *mid, char *right) { set_color (fg, bg); draw_text (left); set_color (hfg, bg); draw_text (mid); set_color (fg, bg); draw_text (right); } static void set_console_title () { if (!sysblk.pantitle) return; #if defined( _MSVC_ ) w32_set_console_title(sysblk.pantitle); #else /*!defined(_MSVC_) */ /* For Unix systems we set the window title by sending a special escape sequence (depends on terminal type) to the console. See http://www.faqs.org/docs/Linux-mini/Xterm-Title.html */ if (!cons_term) return; if (strcmp(cons_term,"xterm")==0 || strcmp(cons_term,"rxvt")==0 || strcmp(cons_term,"dtterm")==0 || strcmp(cons_term,"screen")==0) { fprintf(confp,"%c]0;%s%c",'\033',sysblk.pantitle,'\007'); } #endif /*!defined(_MSVC_) */ } /*=NP================================================================*/ /* Initialize the NP data */ /*===================================================================*/ static void NP_init() { NPdataentry = 0; strcpy(NPprompt1, ""); strcpy(NPprompt2, ""); } /*=NP================================================================*/ /* This draws the initial screen template */ /*===================================================================*/ static void NP_screen_redraw (REGS *regs) { int i, line; char buf[1024]; /* Force all data to be redrawn */ NPcpunum_valid = NPcpupct_valid = NPpsw_valid = NPpswstate_valid = NPregs_valid = NPaddr_valid = NPdata_valid = NPdevices_valid = NPcpugraph_valid = 0; #if defined(OPTION_MIPS_COUNTING) NPmips_valid = NPsios_valid = 0; #endif /*defined(OPTION_MIPS_COUNTING)*/ #if defined(_FEATURE_SIE) if(regs->sie_active) regs = regs->guestregs; #endif /*defined(_FEATURE_SIE)*/ /* * Draw the static parts of the NP screen */ set_color (COLOR_LIGHT_GREY, COLOR_BLACK ); clr_screen (); /* Line 1 - title line */ set_color (COLOR_WHITE, COLOR_BLUE ); set_pos (1, 1); draw_text (" Hercules CPU : %"); fill_text (' ', 30); draw_text ((char *)get_arch_mode_string(NULL)); fill_text (' ', 38); set_color (COLOR_LIGHT_GREY, COLOR_BLUE ); draw_text ("| "); set_color (COLOR_WHITE, COLOR_BLUE ); /* Center "Peripherals" on the right-hand-side */ if (cons_cols > 52) fill_text (' ', 40 + (cons_cols - 52) / 2); draw_text ("Peripherals"); fill_text (' ', (short)cons_cols); /* Line 2 - peripheral headings */ set_pos (2, 41); set_color (COLOR_WHITE, COLOR_BLACK); draw_char ('U'); set_color (COLOR_LIGHT_GREY, COLOR_BLACK); draw_text(" Addr Modl Type Assig"); set_color (COLOR_WHITE, COLOR_BLACK); draw_char ('n'); set_color (COLOR_LIGHT_GREY, COLOR_BLACK); draw_text("ment"); /* 4th line - PSW */ NPpswmode = (regs->arch_mode == ARCH_900); NPpswzhost = #if defined(_FEATURE_SIE) !NPpswmode && SIE_MODE(regs) && regs->hostregs->arch_mode == ARCH_900; #else 0; #endif /*defined(_FEATURE_SIE)*/ set_pos (4, NPpswmode || NPpswzhost ? 19 : 10); draw_text ("PSW"); /* Lines 6 .. 13 : register area */ set_color (COLOR_LIGHT_GREY, COLOR_BLACK); NPregmode = (regs->arch_mode == ARCH_900 && (NPregdisp == 0 || NPregdisp == 1)); NPregzhost = #if defined(_FEATURE_SIE) (regs->arch_mode != ARCH_900 && SIE_MODE(regs) && regs->hostregs->arch_mode == ARCH_900 && (NPregdisp == 0 || NPregdisp == 1)); #else 0; #endif /*defined(_FEATURE_SIE)*/ if (NPregmode == 1 || NPregzhost) { for (i = 0; i < 8; i++) { set_pos (i+6, 1); draw_text (NPregnum64[i*2]); set_pos (i+6, 20); draw_text (NPregnum64[i*2+1]); } } else { for (i = 0; i < 4; i++) { set_pos (i*2+7,9); draw_text (NPregnum[i*4]); set_pos (i*2+7,18); draw_text (NPregnum[i*4+1]); set_pos (i*2+7,27); draw_text (NPregnum[i*4+2]); set_pos (i*2+7,36); draw_text (NPregnum[i*4+3]); } } /* Line 14 : register selection */ set_color (COLOR_LIGHT_GREY, COLOR_BLACK); set_pos (14, 6); draw_text ("GPR"); set_pos (14, 14); draw_text ("CR"); set_pos (14, 22); draw_text ("AR"); set_pos (14, 30); draw_text ("FPR"); /* Line 16 .. 17 : Address and data */ set_pos (16, 2); draw_text ("ADD"); set_color (COLOR_WHITE, COLOR_BLACK); draw_char ('R'); set_color (COLOR_LIGHT_GREY, COLOR_BLACK); draw_text ("ESS:"); set_pos (16, 22); set_color (COLOR_WHITE, COLOR_BLACK); draw_char ('D'); set_color (COLOR_LIGHT_GREY, COLOR_BLACK); draw_text ("ATA:"); /* Line 18 : separator */ set_pos (18, 1); fill_text ('-', 38); /* Lines 19 .. 23 : buttons */ set_pos (19, 16); draw_button(COLOR_BLUE, COLOR_LIGHT_GREY, COLOR_WHITE, " ST", "O", " " ); set_pos (19, 24); draw_button(COLOR_BLUE, COLOR_LIGHT_GREY, COLOR_WHITE, " D", "I", "S " ); set_pos (19, 32); draw_button(COLOR_BLUE, COLOR_LIGHT_GREY, COLOR_WHITE, " RS", "T", " " ); #if defined(OPTION_MIPS_COUNTING) set_pos (20, 3); set_color (COLOR_LIGHT_GREY, COLOR_BLACK); draw_text ("MIPS"); set_pos (20, 9); draw_text ("SIO/s"); #endif /*defined(OPTION_MIPS_COUNTING)*/ set_pos (22, 2); draw_button(COLOR_GREEN, COLOR_LIGHT_GREY, COLOR_WHITE, " ", "S", "TR "); set_pos (22, 9); draw_button(COLOR_RED, COLOR_LIGHT_GREY, COLOR_WHITE, " ST", "P", " " ); set_pos (22, 16); draw_button(COLOR_BLUE, COLOR_LIGHT_GREY, COLOR_WHITE, " ", "E", "XT "); set_pos (22, 24); draw_button(COLOR_BLUE, COLOR_LIGHT_GREY, COLOR_WHITE, " IP", "L", " " ); set_pos (22, 32); draw_button(COLOR_RED, COLOR_LIGHT_GREY, COLOR_WHITE, " P", "W", "R " ); set_color (COLOR_LIGHT_GREY, COLOR_BLACK); /* CPU busy graph */ line = 24; NPcpugraph_ncpu = MIN(cons_rows - line - 2, HI_CPU); if (HI_CPU > 0) { NPcpugraph = 1; NPcpugraph_valid = 0; set_pos (line++, 1); fill_text ('-', 38); set_pos (line++, 1); draw_text ("CPU"); for (i = 0; i < NPcpugraph_ncpu; i++) { sprintf (buf, "%02X ", i); set_pos (line++, 1); draw_text (buf); } } else NPcpugraph = 0; /* Vertical separators */ for (i = 2; i <= cons_rows; i++) { set_pos (i , 39); draw_char ('|'); } /* Last line : horizontal separator */ if (cons_rows >= 24) { set_pos (cons_rows, 1); fill_text ('-', 38); draw_char ('|'); fill_text ('-', cons_cols); } /* positions the cursor */ set_pos (cons_rows, cons_cols); } /*=NP================================================================*/ /* This refreshes the screen with new data every cycle */ /*===================================================================*/ static void NP_update(REGS *regs) { int i, n; int mode, zhost; QWORD curpsw; U32 addr, aaddr; DEVBLK *dev; int online, busy, open; char *devclass; char devnam[128]; char buf[1024]; if (NPhelpup == 1) { if (NPhelpdown == 1) { NP_init(); NP_screen_redraw(regs); NPhelpup = 0; NPhelpdown = 0; NPhelppaint = 1; } else { if (NPhelppaint) { set_color (COLOR_LIGHT_GREY, COLOR_BLACK); clr_screen (); for (i = 0; strcmp(NPhelp[i], ""); i++) { set_pos (i+1, 1); draw_text (NPhelp[i]); } NPhelppaint = 0; } return; } } #if defined(_FEATURE_SIE) if(SIE_MODE(regs)) regs = regs->hostregs; #endif /*defined(_FEATURE_SIE)*/ /* line 1 : cpu number and percent busy */ if (!NPcpunum_valid || NPcpunum != regs->cpuad) { set_color (COLOR_WHITE, COLOR_BLUE); set_pos (1, 16); sprintf (buf, "%4.4X:",regs->cpuad); draw_text (buf); NPcpunum_valid = 1; NPcpunum = regs->cpuad; } #if defined(OPTION_MIPS_COUNTING) if (!NPcpupct_valid || NPcpupct != regs->cpupct) { set_color (COLOR_WHITE, COLOR_BLUE); set_pos (1, 22); sprintf(buf, "%3d", regs->cpupct); draw_text (buf); NPcpupct_valid = 1; NPcpupct = regs->cpupct; } #else // !defined(OPTION_MIPS_COUNTING) if (!NPcpupct_valid) { set_color (COLOR_WHITE, COLOR_BLUE); set_pos (1, 21); draw_text (" "); NPcpupct_valid = 1; } #endif /*defined(OPTION_MIPS_COUNTING)*/ #if defined(_FEATURE_SIE) if(regs->sie_active) regs = regs->guestregs; #endif /*defined(_FEATURE_SIE)*/ mode = (regs->arch_mode == ARCH_900); zhost = #if defined(_FEATURE_SIE) !mode && SIE_MODE(regs) && regs->hostregs->arch_mode == ARCH_900; #else // !defined(_FEATURE_SIE) 0; #endif // defined(_FEATURE_SIE) /* Redraw the psw template if the mode changed */ if (NPpswmode != mode || NPpswzhost != zhost) { NPpswmode = mode; NPpswzhost = zhost; NPpsw_valid = NPpswstate_valid = 0; set_color (COLOR_LIGHT_GREY, COLOR_BLACK); set_pos (3, 1); fill_text (' ',38); set_pos (4, 1); fill_text (' ', 38); set_pos (4, NPpswmode || NPpswzhost ? 19 : 10); draw_text ("PSW"); } /* Display the psw */ memset (curpsw, 0, sizeof(QWORD)); copy_psw (regs, curpsw); if (!NPpsw_valid || memcmp(NPpsw, curpsw, sizeof(QWORD))) { set_color (COLOR_LIGHT_YELLOW, COLOR_BLACK); set_pos (3, 3); if (mode) { draw_dw (fetch_dw(curpsw)); set_pos (3, 22); draw_dw (fetch_dw(curpsw+8)); } else if (zhost) { draw_fw (fetch_fw(curpsw)); // draw_fw (0); draw_fw (fetch_fw(curpsw+4)); /* *JJ */ set_pos (3, 22); // draw_fw (fetch_fw(curpsw+4) & 0x80000000 ? 0x80000000 : 0); // draw_fw (fetch_fw(curpsw+4) & 0x7fffffff); draw_text("----------------"); /* *JJ */ } else { draw_fw (fetch_fw(curpsw)); set_pos (3, 12); draw_fw (fetch_fw(curpsw+4)); } NPpsw_valid = 1; memcpy (NPpsw, curpsw, sizeof(QWORD)); } /* Display psw state */ sprintf (buf, "%2d%c%c%c%c%c%c%c%c", regs->psw.amode64 ? 64 : regs->psw.amode ? 31 : 24, regs->cpustate == CPUSTATE_STOPPED ? 'M' : '.', sysblk.inststep ? 'T' : '.', WAITSTATE (®s->psw) ? 'W' : '.', regs->loadstate ? 'L' : '.', regs->checkstop ? 'C' : '.', PROBSTATE(®s->psw) ? 'P' : '.', SIE_MODE(regs) ? 'S' : '.', mode ? 'Z' : '.'); if (!NPpswstate_valid || strcmp(NPpswstate, buf)) { set_color (COLOR_LIGHT_YELLOW, COLOR_BLACK ); set_pos (mode || zhost ? 4 : 3, 28); draw_text (buf); NPpswstate_valid = 1; strcpy (NPpswstate, buf); } /* Redraw the register template if the regmode switched */ mode = (regs->arch_mode == ARCH_900 && (NPregdisp == 0 || NPregdisp == 1)); zhost = #if defined(_FEATURE_SIE) (regs->arch_mode != ARCH_900 && SIE_MODE(regs) && regs->hostregs->arch_mode == ARCH_900 && (NPregdisp == 0 || NPregdisp == 1)); #else // !defined(_FEATURE_SIE) 0; #endif /*defined(_FEATURE_SIE)*/ if (NPregmode != mode || NPregzhost != zhost) { NPregmode = mode; NPregzhost = zhost; NPregs_valid = 0; set_color (COLOR_LIGHT_GREY, COLOR_BLACK); if (NPregmode || NPregzhost) { /* 64 bit registers */ for (i = 0; i < 8; i++) { set_pos (i+6, 1); fill_text (' ', 38); set_pos (i+6, 1); draw_text (NPregnum64[i*2]); set_pos (i+6, 20); draw_text (NPregnum64[i*2+1]); } } else { /* 32 bit registers */ for (i = 0; i < 4; i++) { set_pos (i*2+6,1); fill_text (' ', 38); set_pos (i*2+7,1); fill_text (' ', 38); set_pos (i*2+7,9); draw_text (NPregnum[i*4]); set_pos (i*2+7,18); draw_text (NPregnum[i*4+1]); set_pos (i*2+7,27); draw_text (NPregnum[i*4+2]); set_pos (i*2+7,36); draw_text (NPregnum[i*4+3]); } } } /* Display register values */ set_color (COLOR_LIGHT_YELLOW, COLOR_BLACK ); if (NPregmode) { /* 64 bit registers */ for (i = 0; i < 16; i++) { switch (NPregdisp) { case 0: if (!NPregs_valid || NPregs64[i] != regs->GR_G(i)) { set_pos (6 + i/2, 3 + (i%2)*19); draw_dw (regs->GR_G(i)); NPregs64[i] = regs->GR_G(i); } break; case 1: if (!NPregs_valid || NPregs64[i] != regs->CR_G(i)) { set_pos (6 + i/2, 3 + (i%2)*19); draw_dw (regs->CR_G(i)); NPregs64[i] = regs->CR_G(i); } break; } } } else if (NPregzhost) { /* 32 bit registers on 64 bit template */ for (i = 0; i < 16; i++) { switch (NPregdisp) { case 0: if (!NPregs_valid || NPregs[i] != regs->GR_L(i)) { set_pos (6 + i/2, 3 + (i%2)*19); // draw_fw (0); draw_text("--------"); draw_fw (regs->GR_L(i)); NPregs[i] = regs->GR_L(i); } break; case 1: if (!NPregs_valid || NPregs[i] != regs->CR_L(i)) { set_pos (6 + i/2, 3 + (i%2)*19); // draw_fw (0); draw_text("--------"); draw_fw (regs->CR_L(i)); NPregs[i] = regs->CR_L(i); } break; } } } else { /* 32 bit registers */ addr = NPaddress; for (i = 0; i < 16; i++) { switch (NPregdisp) { default: case 0: if (!NPregs_valid || NPregs[i] != regs->GR_L(i)) { set_pos (6 + (i/4)*2, 3 + (i%4)*9); draw_fw (regs->GR_L(i)); NPregs[i] = regs->GR_L(i); } break; case 1: if (!NPregs_valid || NPregs[i] != regs->CR_L(i)) { set_pos (6 + (i/4)*2, 3 + (i%4)*9); draw_fw (regs->CR_L(i)); NPregs[i] = regs->CR_L(i); } break; case 2: if (!NPregs_valid || NPregs[i] != regs->AR(i)) { set_pos (6 + (i/4)*2, 3 + (i%4)*9); draw_fw (regs->AR(i)); NPregs[i] = regs->AR(i); } break; case 3: if (!NPregs_valid || NPregs[i] != regs->fpr[i]) { set_pos (6 + (i/4)*2, 3 + (i%4)*9); draw_fw (regs->fpr[i]); NPregs[i] = regs->fpr[i]; } break; case 4: aaddr = APPLY_PREFIXING (addr, regs->PX); addr += 4; if (aaddr + 3 > regs->mainlim) break; if (!NPregs_valid || NPregs[i] != fetch_fw(regs->mainstor + aaddr)) { set_pos (6 + (i/4)*2, 3 + (i%4)*9); draw_fw (fetch_fw(regs->mainstor + aaddr)); NPregs[i] = fetch_fw(regs->mainstor + aaddr); } break; } } } /* Update register selection indicator */ if (!NPregs_valid) { set_pos (14, 6); set_color (NPregdisp == 0 ? COLOR_LIGHT_YELLOW : COLOR_WHITE, COLOR_BLACK); draw_char ('G'); set_pos (14, 14); set_color (NPregdisp == 1 ? COLOR_LIGHT_YELLOW : COLOR_WHITE, COLOR_BLACK); draw_char ('C'); set_pos (14, 22); set_color (NPregdisp == 2 ? COLOR_LIGHT_YELLOW : COLOR_WHITE, COLOR_BLACK); draw_char ('A'); set_pos (14, 30); set_color (NPregdisp == 3 ? COLOR_LIGHT_YELLOW : COLOR_WHITE, COLOR_BLACK); draw_char ('F'); } NPregs_valid = 1; /* Address & Data */ if (!NPaddr_valid) { set_color (COLOR_LIGHT_YELLOW, COLOR_BLACK); set_pos (16, 12); draw_fw (NPaddress); NPaddr_valid = 1; } if (!NPdata_valid) { set_color (COLOR_LIGHT_YELLOW, COLOR_BLACK); set_pos (16, 30); draw_fw (NPdata); NPdata_valid = 1; } /* Rates */ #ifdef OPTION_MIPS_COUNTING if (!NPmips_valid || sysblk.mipsrate != NPmips) { set_color (COLOR_LIGHT_YELLOW, COLOR_BLACK); set_pos (19, 1); sprintf(buf, "%3.1d.%2.2d", sysblk.mipsrate / 1000000, (sysblk.mipsrate % 1000000) / 10000); draw_text (buf); NPmips = sysblk.mipsrate; NPmips_valid = 1; } if (!NPsios_valid || NPsios != sysblk.siosrate) { set_color (COLOR_LIGHT_YELLOW, COLOR_BLACK); set_pos (19, 7); sprintf(buf, "%7d", sysblk.siosrate); draw_text (buf); NPsios = sysblk.siosrate; NPsios_valid = 1; } #endif /* OPTION_MIPS_COUNTING */ /* Optional cpu graph */ if (NPcpugraph) { for (i = 0; i < NPcpugraph_ncpu; i++) { if (!IS_CPU_ONLINE(i)) { if (!NPcpugraph_valid || NPcpugraphpct[i] != -2.0) { set_color (COLOR_RED, COLOR_BLACK); set_pos (26+i, 4); draw_text ("OFFLINE"); fill_text (' ', 38); NPcpugraphpct[i] = -2.0; } } else if (sysblk.regs[i]->cpustate != CPUSTATE_STARTED) { if (!NPcpugraph_valid || NPcpugraphpct[i] != -1.0) { set_color (COLOR_LIGHT_YELLOW, COLOR_BLACK); set_pos (26+i, 4); draw_text ("STOPPED"); fill_text (' ', 38); NPcpugraphpct[i] = -1.0; } } else if (!NPcpugraph_valid || NPcpugraphpct[i] != sysblk.regs[i]->cpupct) { n = (34 * sysblk.regs[i]->cpupct) / 100; if (n == 0 && sysblk.regs[i]->cpupct > 0) n = 1; else if (n > 34) n = 34; set_color (n > 17 ? COLOR_WHITE : COLOR_LIGHT_GREY, COLOR_BLACK); set_pos (26+i, 4); fill_text ('*', n+3); fill_text (' ', 38); NPcpugraphpct[i] = sysblk.regs[i]->cpupct; } set_color (COLOR_LIGHT_GREY, COLOR_BLACK); } NPcpugraph_valid = 1; } /* Process devices */ for (i = 0, dev = sysblk.firstdev; dev != NULL; i++, dev = dev->nextdev) { if (i >= cons_rows - 3) break; if (!dev->allocated) continue; online = (dev->console && dev->connected) || strlen(dev->filename) > 0; busy = dev->busy != 0 || IOPENDING(dev) != 0; open = dev->fd > 2; /* device identifier */ if (!NPdevices_valid || online != NPonline[i]) { set_pos (i+3, 41); set_color (online ? COLOR_LIGHT_GREEN : COLOR_LIGHT_GREY, COLOR_BLACK); draw_char (i < 26 ? 'A' + i : '.'); NPonline[i] = online; } /* device number */ if (!NPdevices_valid || dev->devnum != NPdevnum[i] || NPbusy[i] != busy) { set_pos (i+3, 43); set_color (busy ? COLOR_LIGHT_YELLOW : COLOR_LIGHT_GREY, COLOR_BLACK); sprintf (buf, "%4.4X", dev->devnum); draw_text (buf); NPdevnum[i] = dev->devnum; NPbusy[i] = busy; } /* device type */ if (!NPdevices_valid || dev->devtype != NPdevtype[i] || open != NPopen[i]) { set_pos (i+3, 48); set_color (open ? COLOR_LIGHT_GREEN : COLOR_LIGHT_GREY, COLOR_BLACK); sprintf (buf, "%4.4X", dev->devtype); draw_text (buf); NPdevtype[i] = dev->devtype; NPopen[i] = open; } /* device class and name */ (dev->hnd->query)(dev, &devclass, sizeof(devnam), devnam); if (!NPdevices_valid || strcmp(NPdevnam[i], devnam)) { set_color (COLOR_LIGHT_GREY, COLOR_BLACK); set_pos (i+3, 53); sprintf (buf, "%-4.4s", devclass); draw_text (buf); /* Draw device name only if they're NOT assigning a new one */ if (0 || NPdataentry != 1 || NPpending != 'n' || NPasgn != i ) { set_pos (i+3, 58); draw_text (devnam); fill_text (' ', PANEL_MAX_COLS); } } } /* Complete the device state table */ if (!NPdevices_valid) { NPlastdev = i > 26 ? 26 : i - 1; for ( ; i < NP_MAX_DEVICES; i++) { NPonline[i] = NPdevnum[i] = NPbusy[i] = NPdevtype[i] = NPopen[i] = 0; strcpy (NPdevnam[i], ""); } NPdevices_valid = 1; } /* Prompt 1 */ if (strcmp(NPprompt1, NPoldprompt1)) { strcpy(NPoldprompt1, NPprompt1); if (strlen(NPprompt1) > 0) { set_color (COLOR_WHITE, COLOR_BLUE); set_pos (cons_rows, (40 - strlen(NPprompt1)) / 2); draw_text (NPprompt1); } else if (cons_rows >= 24) { set_color (COLOR_LIGHT_GREY, COLOR_BLACK); set_pos (cons_rows, 1); fill_text ('-', 38); } } /* Prompt 2 */ if (strcmp(NPprompt2, NPoldprompt2)) { strcpy(NPoldprompt2, NPprompt2); if (strlen(NPprompt2) > 0) { set_color (COLOR_WHITE, COLOR_BLUE); set_pos (cons_rows, 41); draw_text (NPprompt2); } else if (cons_rows >= 24) { set_color (COLOR_LIGHT_GREY, COLOR_BLACK); set_pos (cons_rows, 41); fill_text ('-', cons_cols); } } /* Data entry field */ if (NPdataentry && redraw_cmd) { set_pos (NPcurrow, NPcurcol); if (NPcolorSwitch) set_color (NPcolorFore, NPcolorBack); fill_text (' ', NPcurcol + NPdatalen - 1); set_pos (NPcurrow, NPcurcol); PUTC_CMDLINE(); redraw_cmd = 0; } else /* Position the cursor to the bottom right */ set_pos(cons_rows, cons_cols); } /* ============== End of the main NP block of code =============*/ static void panel_cleanup(void *unused); // (forward reference) #ifdef OPTION_MIPS_COUNTING /////////////////////////////////////////////////////////////////////// // "maxrates" command support... #define DEF_MAXRATES_RPT_INTVL ( 1440 ) DLL_EXPORT U32 curr_high_mips_rate = 0; // (high water mark for current interval) DLL_EXPORT U32 curr_high_sios_rate = 0; // (high water mark for current interval) DLL_EXPORT U32 prev_high_mips_rate = 0; // (saved high water mark for previous interval) DLL_EXPORT U32 prev_high_sios_rate = 0; // (saved high water mark for previous interval) DLL_EXPORT time_t curr_int_start_time = 0; // (start time of current interval) DLL_EXPORT time_t prev_int_start_time = 0; // (start time of previous interval) DLL_EXPORT U32 maxrates_rpt_intvl = DEF_MAXRATES_RPT_INTVL; DLL_EXPORT void update_maxrates_hwm() // (update high-water-mark values) { time_t current_time = 0; U32 elapsed_secs = 0; if (curr_high_mips_rate < sysblk.mipsrate) curr_high_mips_rate = sysblk.mipsrate; if (curr_high_sios_rate < sysblk.siosrate) curr_high_sios_rate = sysblk.siosrate; // Save high water marks for current interval... time( ¤t_time ); elapsed_secs = current_time - curr_int_start_time; if ( elapsed_secs >= ( maxrates_rpt_intvl * 60 ) ) { prev_high_mips_rate = curr_high_mips_rate; prev_high_sios_rate = curr_high_sios_rate; curr_high_mips_rate = 0; curr_high_sios_rate = 0; prev_int_start_time = curr_int_start_time; curr_int_start_time = current_time; } } #endif // OPTION_MIPS_COUNTING /////////////////////////////////////////////////////////////////////// REGS *copy_regs(int cpu) { REGS *regs; if (cpu < 0 || cpu >= MAX_CPU_ENGINES) cpu = 0; obtain_lock (&sysblk.cpulock[cpu]); if ((regs = sysblk.regs[cpu]) == NULL) { release_lock(&sysblk.cpulock[cpu]); return &sysblk.dummyregs; } memcpy (©regs, regs, sysblk.regs_copy_len); if (copyregs.hostregs == NULL) { release_lock(&sysblk.cpulock[cpu]); return &sysblk.dummyregs; } #if defined(_FEATURE_SIE) if (regs->sie_active) { memcpy (©sieregs, regs->guestregs, sysblk.regs_copy_len); copyregs.guestregs = ©sieregs; copysieregs.hostregs = ©regs; regs = ©sieregs; } else #endif // defined(_FEATURE_SIE) regs = ©regs; SET_PSW_IA(regs); release_lock(&sysblk.cpulock[cpu]); return regs; } static char *format_int(uint64_t ic) { static char obfr[32]; /* Enough for displaying 2^64-1 */ char grps[7][4]; /* 7 groups of 3 digits */ int maxg=0; int i; strcpy(grps[0],"0"); while(ic>0) { int grp; grp=ic%1000; ic/=1000; if(ic==0) { sprintf(grps[maxg],"%u",grp); } else { sprintf(grps[maxg],"%3.3u",grp); } maxg++; } if(maxg) maxg--; obfr[0]=0; for(i=maxg;i>=0;i--) { strcat(obfr,grps[i]); if(i) { strcat(obfr,","); } } return obfr; } /*-------------------------------------------------------------------*/ /* Panel display thread */ /* */ /* This function runs on the main thread. It receives messages */ /* from the log task and displays them on the screen. It accepts */ /* panel commands from the keyboard and executes them. It samples */ /* the PSW periodically and displays it on the screen status line. */ /*-------------------------------------------------------------------*/ #if defined(OPTION_DYNAMIC_LOAD) void panel_display_r (void) #else void panel_display (void) #endif // defined(OPTION_DYNAMIC_LOAD) { #ifndef _MSVC_ int rc; /* Return code */ int maxfd; /* Highest file descriptor */ fd_set readset; /* Select file descriptors */ struct timeval tv; /* Select timeout structure */ #endif // _MSVC_ int i; /* Array subscripts */ int len; /* Length */ REGS *regs; /* -> CPU register context */ QWORD curpsw; /* Current PSW */ QWORD prvpsw; /* Previous PSW */ BYTE prvstate = 0xFF; /* Previous stopped state */ U64 prvicount = 0; /* Previous instruction count*/ #if defined(OPTION_MIPS_COUNTING) U64 prvtcount = 0; /* Previous total count */ #endif /*defined(OPTION_MIPS_COUNTING)*/ int prvcpupct = 0; /* Previous cpu percentage */ #if defined(OPTION_SHARED_DEVICES) U32 prvscount = 0; /* Previous shrdcount */ #endif // defined(OPTION_SHARED_DEVICES) char readbuf[MSG_SIZE]; /* Message read buffer */ int readoff = 0; /* Number of bytes in readbuf*/ BYTE c; /* Character work area */ size_t kbbufsize = CMD_SIZE; /* Size of keyboard buffer */ char *kbbuf = NULL; /* Keyboard input buffer */ int kblen; /* Number of chars in kbbuf */ U32 aaddr; /* Absolute address for STO */ char buf[1024]; /* Buffer workarea */ SET_THREAD_NAME("panel_display"); /* Display thread started message on control panel */ logmsg (_("HHCPN001I Control panel thread started: " "tid="TIDPAT", pid=%d\n"), thread_id(), getpid()); /* Notify logger_thread we're in control */ sysblk.panel_init = 1; hdl_adsc("panel_cleanup",panel_cleanup, NULL); history_init(); /* Set up the input file descriptors */ confp = stderr; keybfd = STDIN_FILENO; /* Initialize screen dimensions */ cons_term = getenv ("TERM"); get_dim (&cons_rows, &cons_cols); /* Clear the command-line buffer */ memset (cmdline, 0, sizeof(cmdline)); cmdcols = cons_cols - CMDLINE_COL; /* Obtain storage for the keyboard buffer */ if (!(kbbuf = malloc (kbbufsize))) { logmsg(_("HHCPN002S Cannot obtain keyboard buffer: %s\n"), strerror(errno)); return; } /* Obtain storage for the circular message buffer */ msgbuf = malloc (MAX_MSGS * sizeof(PANMSG)); if (msgbuf == NULL) { fprintf (stderr, _("HHCPN003S Cannot obtain message buffer: %s\n"), strerror(errno)); return; } /* Initialize circular message buffer */ for (curmsg = msgbuf, i=0; i < MAX_MSGS; curmsg++, i++) { curmsg->next = curmsg + 1; curmsg->prev = curmsg - 1; curmsg->msgnum = i; memset(curmsg->msg,SPACE,MSG_SIZE); #if defined(OPTION_MSGCLR) curmsg->bg = COLOR_DEFAULT_FG; curmsg->fg = COLOR_DEFAULT_BG; #if defined(OPTION_MSGHLD) curmsg->keep = 0; memset( &curmsg->expiration, 0, sizeof(curmsg->expiration)); #endif // defined(OPTION_MSGHLD) #endif // defined(OPTION_MSGCLR) } /* Complete the circle */ msgbuf->prev = msgbuf + MAX_MSGS - 1; msgbuf->prev->next = msgbuf; /* Indicate "first-time" state */ curmsg = topmsg = NULL; wrapped = 0; numkept = 0; #if defined(OPTION_MSGHLD) keptmsgs = lastkept = NULL; #endif // defined(OPTION_MSGHLD) /* Set screen output stream to NON-buffered */ setvbuf (confp, NULL, _IONBF, 0); /* Put the terminal into cbreak mode */ set_or_reset_console_mode( keybfd, 1 ); /* Set console title */ set_console_title(); /* Clear the screen */ set_color (COLOR_DEFAULT_FG, COLOR_DEFAULT_BG); clr_screen (); redraw_msgs = redraw_cmd = redraw_status = 1; /* Process messages and commands */ while ( 1 ) { #if defined(OPTION_MIPS_COUNTING) update_maxrates_hwm(); // (update high-water-mark values) #endif // defined(OPTION_MIPS_COUNTING) #if defined( _MSVC_ ) /* Wait for keyboard input */ #define WAIT_FOR_KEYBOARD_INPUT_SLEEP_MILLISECS (20) for (i=sysblk.panrate/WAIT_FOR_KEYBOARD_INPUT_SLEEP_MILLISECS; i && !kbhit(); i--) Sleep(WAIT_FOR_KEYBOARD_INPUT_SLEEP_MILLISECS); ADJ_SCREEN_SIZE(); /* If keyboard input has [finally] arrived, then process it */ if ( kbhit() ) { /* Read character(s) from the keyboard */ kbbuf[0] = getch(); kbbuf[kblen=1] = '\0'; translate_keystroke( kbbuf, &kblen ); #else // !defined( _MSVC_ ) /* Set the file descriptors for select */ FD_ZERO (&readset); FD_SET (keybfd, &readset); maxfd = keybfd; /* Wait for a message to arrive, a key to be pressed, or the inactivity interval to expire */ tv.tv_sec = sysblk.panrate / 1000; tv.tv_usec = (sysblk.panrate * 1000) % 1000000; rc = select (maxfd + 1, &readset, NULL, NULL, &tv); if (rc < 0 ) { if (errno == EINTR) continue; fprintf (stderr, _("HHCPN004E select: %s\n"), strerror(errno)); break; } ADJ_SCREEN_SIZE(); /* If keyboard input has arrived then process it */ if (FD_ISSET(keybfd, &readset)) { /* Read character(s) from the keyboard */ kblen = read (keybfd, kbbuf, kbbufsize-1); if (kblen < 0) { fprintf (stderr, _("HHCPN005E keyboard read: %s\n"), strerror(errno)); break; } kbbuf[kblen] = '\0'; #endif // defined( _MSVC_ ) /* =NP= : Intercept NP commands & process */ if (NPDup == 1) { if (NPdevsel == 1) { NPdevsel = 0; NPdevice = kbbuf[0]; /* save the device selected */ kbbuf[0] = NPsel2; /* setup for 2nd part of rtn */ } if (NPdataentry == 0 && kblen == 1) { /* We are in command mode */ if (NPhelpup == 1) { if (kbbuf[0] == 0x1b) NPhelpdown = 1; kbbuf[0] = '\0'; redraw_status = 1; } cmdline[0] = '\0'; cmdlen = 0; cmdoff = 0; ADJ_CMDCOL(); switch(kbbuf[0]) { case 0x1B: /* ESC */ NPDup = 0; restore_command_line(); ADJ_CMDCOL(); redraw_msgs = redraw_cmd = redraw_status = 1; npquiet = 0; // (forced for one paint cycle) break; case '?': NPhelpup = 1; redraw_status = 1; break; case 'S': /* START */ case 's': do_panel_command("herc startall"); break; case 'P': /* STOP */ case 'p': do_panel_command("herc stopall"); break; case 'O': /* Store */ case 'o': regs = copy_regs(sysblk.pcpu); aaddr = APPLY_PREFIXING (NPaddress, regs->PX); if (aaddr > regs->mainlim) break; store_fw (regs->mainstor + aaddr, NPdata); redraw_status = 1; break; case 'I': /* Display */ case 'i': NPregdisp = 4; NPregs_valid = 0; redraw_status = 1; break; case 'g': /* display GPR */ case 'G': NPregdisp = 0; NPregs_valid = 0; redraw_status = 1; break; case 'a': /* Display AR */ case 'A': NPregdisp = 2; NPregs_valid = 0; redraw_status = 1; break; case 'c': case 'C': /* Case CR */ NPregdisp = 1; NPregs_valid = 0; redraw_status = 1; break; case 'f': /* Case FPR */ case 'F': NPregdisp = 3; NPregs_valid = 0; redraw_status = 1; break; case 'r': /* Enter address */ case 'R': NPdataentry = 1; redraw_cmd = 1; NPpending = 'r'; NPcurrow = 16; NPcurcol = 12; NPdatalen = 8; NPcolorSwitch = 1; NPcolorFore = COLOR_WHITE; NPcolorBack = COLOR_BLUE; strcpy(NPentered, ""); strcpy(NPprompt1, "Enter Address"); redraw_status = 1; break; case 'd': /* Enter data */ case 'D': NPdataentry = 1; redraw_cmd = 1; NPpending = 'd'; NPcurrow = 16; NPcurcol = 30; NPdatalen = 8; NPcolorSwitch = 1; NPcolorFore = COLOR_WHITE; NPcolorBack = COLOR_BLUE; strcpy(NPentered, ""); strcpy(NPprompt1, "Enter Data Value"); redraw_status = 1; break; case 'l': /* IPL */ case 'L': NPdevsel = 1; NPsel2 = 1; strcpy(NPprompt2, "Select Device for IPL"); redraw_status = 1; break; case 1: /* IPL - 2nd part */ i = toupper(NPdevice) - 'A'; if (i < 0 || i > NPlastdev) { strcpy(NPprompt2, ""); redraw_status = 1; break; } sprintf (cmdline, "herc ipl %4.4x", NPdevnum[i]); do_panel_command(cmdline); strcpy(NPprompt2, ""); redraw_status = 1; break; case 'u': /* Device interrupt */ case 'U': NPdevsel = 1; NPsel2 = 2; strcpy(NPprompt2, "Select Device for Interrupt"); redraw_status = 1; break; case 2: /* Device int: part 2 */ i = toupper(NPdevice) - 'A'; if (i < 0 || i > NPlastdev) { strcpy(NPprompt2, ""); redraw_status = 1; break; } sprintf (cmdline, "herc i %4.4x", NPdevnum[i]); do_panel_command(cmdline); strcpy(NPprompt2, ""); redraw_status = 1; break; case 'n': /* Device Assignment */ case 'N': NPdevsel = 1; NPsel2 = 3; strcpy(NPprompt2, "Select Device to Reassign"); redraw_status = 1; break; case 3: /* Device asgn: part 2 */ i = toupper(NPdevice) - 'A'; if (i < 0 || i > NPlastdev) { strcpy(NPprompt2, ""); redraw_status = 1; break; } NPdataentry = 1; redraw_cmd = 1; NPpending = 'n'; NPasgn = i; NPcurrow = 3 + i; NPcurcol = 58; NPdatalen = cons_cols - 57; NPcolorSwitch = 1; NPcolorFore = COLOR_DEFAULT_LIGHT; NPcolorBack = COLOR_BLUE; strcpy(NPentered, ""); strcpy(NPprompt2, "New Name, or [enter] to Reload"); redraw_status = 1; break; case 'W': /* POWER */ case 'w': NPdevsel = 1; NPsel2 = 4; strcpy(NPprompt1, "Confirm Powerdown Y or N"); redraw_status = 1; break; case 4: /* POWER - 2nd part */ if (NPdevice == 'y' || NPdevice == 'Y') do_panel_command("herc quit"); strcpy(NPprompt1, ""); redraw_status = 1; break; case 'T': /* Restart */ case 't': NPdevsel = 1; NPsel2 = 5; strcpy(NPprompt1, "Confirm Restart Y or N"); redraw_status = 1; break; case 5: /* Restart - part 2 */ if (NPdevice == 'y' || NPdevice == 'Y') do_panel_command("herc restart"); strcpy(NPprompt1, ""); redraw_status = 1; break; case 'E': /* Ext int */ case 'e': NPdevsel = 1; NPsel2 = 6; strcpy(NPprompt1, "Confirm External Interrupt Y or N"); redraw_status = 1; break; case 6: /* External - part 2 */ if (NPdevice == 'y' || NPdevice == 'Y') do_panel_command("herc ext"); strcpy(NPprompt1, ""); redraw_status = 1; break; default: break; } NPcmd = 1; } else { /* We are in data entry mode */ if (kbbuf[0] == 0x1B) { /* Switch back to command mode */ NPdataentry = 0; NPaddr_valid = 0; NPdata_valid = 0; strcpy(NPprompt1, ""); strcpy(NPprompt2, ""); NPcmd = 1; } else NPcmd = 0; } if (NPcmd == 1) kblen = 0; /* don't process as command */ } /* =NP END= */ /* Process characters in the keyboard buffer */ for (i = 0; i < kblen; ) { /* Test for HOME */ if (strcmp(kbbuf+i, KBD_HOME) == 0) { if (NPDup == 1 || !is_cursor_on_cmdline() || cmdlen) { cursor_cmdline_home(); redraw_cmd = 1; } else { scroll_to_top_line( 1 ); redraw_msgs = 1; } break; } /* Test for END */ if (strcmp(kbbuf+i, KBD_END) == 0) { if (NPDup == 1 || !is_cursor_on_cmdline() || cmdlen) { cursor_cmdline_end(); redraw_cmd = 1; } else { scroll_to_bottom_screen( 1 ); redraw_msgs = 1; } break; } /* Test for CTRL+HOME */ if (NPDup == 0 && strcmp(kbbuf+i, KBD_CTRL_HOME) == 0) { scroll_to_top_line( 1 ); redraw_msgs = 1; break; } /* Test for CTRL+END */ if (NPDup == 0 && strcmp(kbbuf+i, KBD_CTRL_END) == 0) { scroll_to_bottom_line( 1 ); redraw_msgs = 1; break; } /* Process UPARROW */ if (NPDup == 0 && strcmp(kbbuf+i, KBD_UP_ARROW) == 0) { do_prev_history(); redraw_cmd = 1; break; } /* Process DOWNARROW */ if (NPDup == 0 && strcmp(kbbuf+i, KBD_DOWN_ARROW) == 0) { do_next_history(); redraw_cmd = 1; break; } #if defined(OPTION_EXTCURS) /* Process ALT+UPARROW */ if (NPDup == 0 && strcmp(kbbuf+i, KBD_ALT_UP_ARROW) == 0) { get_cursor_pos( keybfd, confp, &cur_cons_row, &cur_cons_col ); if (cur_cons_row <= 1) cur_cons_row = cons_rows + 1; set_pos( --cur_cons_row, cur_cons_col ); break; } /* Process ALT+DOWNARROW */ if (NPDup == 0 && strcmp(kbbuf+i, KBD_ALT_DOWN_ARROW) == 0) { get_cursor_pos( keybfd, confp, &cur_cons_row, &cur_cons_col ); if (cur_cons_row >= cons_rows) cur_cons_row = 1 - 1; set_pos( ++cur_cons_row, cur_cons_col ); break; } #endif // defined(OPTION_EXTCURS) /* Test for PAGEUP */ if (NPDup == 0 && strcmp(kbbuf+i, KBD_PAGE_UP) == 0) { page_up( 1 ); redraw_msgs = 1; break; } /* Test for PAGEDOWN */ if (NPDup == 0 && strcmp(kbbuf+i, KBD_PAGE_DOWN) == 0) { page_down( 1 ); redraw_msgs = 1; break; } /* Test for CTRL+UPARROW */ if (NPDup == 0 && strcmp(kbbuf+i, KBD_CTRL_UP_ARROW) == 0) { scroll_up_lines(1,1); redraw_msgs = 1; break; } /* Test for CTRL+DOWNARROW */ if (NPDup == 0 && strcmp(kbbuf+i, KBD_CTRL_DOWN_ARROW) == 0) { scroll_down_lines(1,1); redraw_msgs = 1; break; } /* Process BACKSPACE */ if (kbbuf[i] == '\b' || kbbuf[i] == '\x7F') { if (NPDup == 0 && !is_cursor_on_cmdline()) beep(); else { if (cmdoff > 0) { int j; for (j = cmdoff-1; j 0) cmdoff--; ADJ_CMDCOL(); i++; redraw_cmd = 1; break; } /* Process RIGHTARROW */ if (strcmp(kbbuf+i, KBD_RIGHT_ARROW) == 0) { if (cmdoff < cmdlen) cmdoff++; ADJ_CMDCOL(); i++; redraw_cmd = 1; break; } #if defined(OPTION_EXTCURS) /* Process ALT+LEFTARROW */ if (NPDup == 0 && strcmp(kbbuf+i, KBD_ALT_LEFT_ARROW) == 0) { get_cursor_pos( keybfd, confp, &cur_cons_row, &cur_cons_col ); if (cur_cons_col <= 1) { cur_cons_row--; cur_cons_col = cons_cols + 1; } if (cur_cons_row < 1) cur_cons_row = cons_rows; set_pos( cur_cons_row, --cur_cons_col ); break; } /* Process ALT+RIGHTARROW */ if (NPDup == 0 && strcmp(kbbuf+i, KBD_ALT_RIGHT_ARROW) == 0) { get_cursor_pos( keybfd, confp, &cur_cons_row, &cur_cons_col ); if (cur_cons_col >= cons_cols) { cur_cons_row++; cur_cons_col = 0; } if (cur_cons_row > cons_rows) cur_cons_row = 1; set_pos( cur_cons_row, ++cur_cons_col ); break; } #endif // defined(OPTION_EXTCURS) /* Process INSERT */ if (strcmp(kbbuf+i, KBD_INSERT) == 0 ) { cmdins = !cmdins; set_console_cursor_shape( confp, cmdins ); i++; break; } /* Process ESCAPE */ if (kbbuf[i] == '\x1B') { /* If data on cmdline, erase it */ if ((NPDup == 1 || is_cursor_on_cmdline()) && cmdlen) { cmdline[0] = '\0'; cmdlen = 0; cmdoff = 0; ADJ_CMDCOL(); redraw_cmd = 1; } else { /* =NP= : Switch to new panel display */ save_command_line(); NP_init(); NPDup = 1; /* =END= */ } break; } /* Process TAB */ if (kbbuf[i] == '\t' || kbbuf[i] == '\x7F') { if (NPDup == 1 || !is_cursor_on_cmdline()) { cursor_cmdline_home(); redraw_cmd = 1; } else { tab_pressed(cmdline, &cmdoff); cmdlen = strlen(cmdline); ADJ_CMDCOL(); i++; redraw_cmd = 1; } break; } #if defined(OPTION_EXTCURS) /* ENTER key special handling */ if (NPDup == 0 && kbbuf[i] == '\n') { /* Get cursor pos and check if on cmdline */ if (!is_cursor_on_cmdline()) { int keepnum = get_keepnum_by_row( cur_cons_row ); if (keepnum >= 0) { /* ENTER pressed on kept msg; remove msg */ unkeep_by_keepnum( keepnum, 1 ); redraw_msgs = 1; break; } /* ENTER pressed NOT on cmdline */ beep(); break; } /* ENTER pressed on cmdline; fall through for normal ENTER keypress handling... */ } #endif // defined(OPTION_EXTCURS) /* Process the command when the ENTER key is pressed */ if (kbbuf[i] == '\n') { if (cmdlen == 0 && NPDup == 0 && !sysblk.inststep && sysblk.cmdtgt == 0) { history_show(); } else { cmdline[cmdlen] = '\0'; /* =NP= create_thread replaced with: */ if (NPDup == 0) { if ('#' == cmdline[0] || '*' == cmdline[0]) { if (!is_currline_visible()) scroll_to_bottom_screen( 1 ); history_requested = 0; do_panel_command(cmdline); redraw_cmd = 1; cmdlen = 0; cmdoff = 0; ADJ_CMDCOL(); redraw_cmd = 1; } else { history_requested = 0; do_panel_command(cmdline); redraw_cmd = 1; if (history_requested == 1) { strcpy(cmdline, historyCmdLine); cmdlen = strlen(cmdline); cmdoff = cmdlen; ADJ_CMDCOL(); NPDup = 0; NPDinit = 1; } } } else { NPdataentry = 0; NPcurrow = cons_rows; NPcurcol = cons_cols; NPcolorSwitch = 0; switch (NPpending) { case 'r': sscanf(cmdline, "%x", &NPaddress); NPaddr_valid = 0; strcpy(NPprompt1, ""); break; case 'd': sscanf(cmdline, "%x", &NPdata); NPdata_valid = 0; strcpy(NPprompt1, ""); break; case 'n': if (strlen(cmdline) < 1) { strcpy(cmdline, NPdevnam[NPasgn]); } strcpy(NPdevnam[NPasgn], ""); sprintf (NPentered, "herc devinit %4.4x %s", NPdevnum[NPasgn], cmdline); do_panel_command(NPentered); strcpy(NPprompt2, ""); break; default: break; } redraw_status = 1; cmdline[0] = '\0'; cmdlen = 0; cmdoff = 0; ADJ_CMDCOL(); } /* =END= */ redraw_cmd = 1; } break; } /* end if (kbbuf[i] == '\n') */ /* Ignore non-printable characters */ if (!isprint(kbbuf[i])) { beep(); i++; continue; } /* Ignore all other keystrokes not on cmdline */ if (NPDup == 0 && !is_cursor_on_cmdline()) { beep(); break; } /* Append the character to the command buffer */ ASSERT(cmdlen <= CMD_SIZE-1 && cmdoff <= cmdlen); if (0 || (cmdoff >= CMD_SIZE-1) || (cmdins && cmdlen >= CMD_SIZE-1) ) { /* (no more room!) */ beep(); } else /* (there's still room) */ { ASSERT(cmdlen < CMD_SIZE-1 || (!cmdins && cmdoff < cmdlen)); if (cmdoff >= cmdlen) { /* Append to end of buffer */ ASSERT(!(cmdoff > cmdlen)); // (sanity check) cmdline[cmdoff++] = kbbuf[i]; cmdline[cmdoff] = '\0'; cmdlen++; } else { ASSERT(cmdoff < cmdlen); if (cmdins) { /* Insert: make room by sliding all following chars right one position */ int j; for (j=cmdlen-1; j>=cmdoff; j--) cmdline[j+1] = cmdline[j]; cmdline[cmdoff++] = kbbuf[i]; cmdlen++; } else { /* Overlay: replace current position */ cmdline[cmdoff++] = kbbuf[i]; } } ADJ_CMDCOL(); redraw_cmd = 1; } i++; } /* end for(i) */ } /* end if keystroke */ FinishShutdown: // If we finished processing all of the message data // the last time we were here, then get some more... if ( lmsndx >= lmscnt ) // (all previous data processed?) { lmscnt = log_read( &lmsbuf, &lmsnum, LOG_NOBLOCK ); lmsndx = 0; } else if ( lmsndx >= lmsmax ) { lmsbuf += lmsndx; // pick up where we left off at... lmscnt -= lmsndx; // pick up where we left off at... lmsndx = 0; } // Process all message data or until limit reached... // (limiting the amount of data we process a console message flood // from preventing keyboard from being read since we need to break // out of the below message data processing loop to loop back up // to read the keyboard again...) /* Read message bytes until newline... */ while ( lmsndx < lmscnt && lmsndx < lmsmax ) { /* Initialize the read buffer */ if (!readoff || readoff >= MSG_SIZE) { memset (readbuf, SPACE, MSG_SIZE); readoff = 0; } /* Read message bytes and copy into read buffer until we either encounter a newline character or our buffer is completely filled with data. */ while ( lmsndx < lmscnt && lmsndx < lmsmax ) { /* Read a byte from the message pipe */ c = *(lmsbuf + lmsndx); lmsndx++; /* Break to process received message whenever a newline is encountered */ if (c == '\n' || c == '\r') { readoff = 0; /* (for next time) */ break; } /* Handle tab character */ if (c == '\t') { readoff += 8; readoff &= 0xFFFFFFF8; /* Messages longer than one screen line will be continued on the very next screen line */ if (readoff >= MSG_SIZE) break; else continue; } /* Eliminate non-displayable characters */ if (!isgraph(c)) c = SPACE; /* Stuff byte into message processing buffer */ readbuf[readoff++] = c; /* Messages longer than one screen line will be continued on the very next screen line */ if (readoff >= MSG_SIZE) break; } /* end while ( lmsndx < lmscnt && lmsndx < lmsmax ) */ /* If we have a message to be displayed (or a complete part of one), then copy it to the circular buffer. */ if (!readoff || readoff >= MSG_SIZE) { /* First-time here? */ if (curmsg == NULL) { curmsg = topmsg = msgbuf; } else { /* Perform autoscroll if needed */ if (is_currline_visible()) { while (lines_remaining() < 1) scroll_down_lines(1,1); /* Set the display update indicator */ redraw_msgs = 1; } /* Go on to next available msg buffer */ curmsg = curmsg->next; /* Updated wrapped indicator */ if (curmsg == msgbuf) wrapped = 1; } /* Copy message into next available PANMSG slot */ memcpy( curmsg->msg, readbuf, MSG_SIZE ); #if defined(OPTION_MSGCLR) /* Colorize and/or keep new message if needed */ colormsg(curmsg); #endif // defined(OPTION_MSGCLR) } /* end if (!readoff || readoff >= MSG_SIZE) */ } /* end Read message bytes until newline... */ /* Don't read or otherwise process any input once system shutdown has been initiated */ if ( sysblk.shutdown ) { if ( sysblk.shutfini ) break; /* wait for system to finish shutting down */ usleep(10000); lmsmax = INT_MAX; goto FinishShutdown; } /* =NP= : Reinit traditional panel if NP is down */ if (NPDup == 0 && NPDinit == 1) { redraw_msgs = redraw_status = redraw_cmd = 1; set_color (COLOR_DEFAULT_FG, COLOR_DEFAULT_BG); clr_screen (); } /* =END= */ /* Obtain the PSW for target CPU */ regs = copy_regs(sysblk.pcpu); memset (curpsw, 0x00, sizeof(curpsw)); copy_psw (regs, curpsw); /* Set the display update indicator if the PSW has changed or if the instruction counter has changed, or if the CPU stopped state has changed */ if (memcmp(curpsw, prvpsw, sizeof(curpsw)) != 0 || prvicount != INSTCOUNT(regs) || prvcpupct != regs->cpupct #if defined(OPTION_SHARED_DEVICES) || prvscount != sysblk.shrdcount #endif // defined(OPTION_SHARED_DEVICES) || prvstate != regs->cpustate #if defined(OPTION_MIPS_COUNTING) || (NPDup && NPcpugraph && prvtcount != sysblk.instcount) #endif /*defined(OPTION_MIPS_COUNTING)*/ ) { redraw_status = 1; memcpy (prvpsw, curpsw, sizeof(prvpsw)); prvicount = INSTCOUNT(regs); prvcpupct = regs->cpupct; prvstate = regs->cpustate; #if defined(OPTION_SHARED_DEVICES) prvscount = sysblk.shrdcount; #endif // defined(OPTION_SHARED_DEVICES) #if defined(OPTION_MIPS_COUNTING) prvtcount = sysblk.instcount; #endif /*defined(OPTION_MIPS_COUNTING)*/ } /* =NP= : Display the screen - traditional or NP */ /* Note: this is the only code block modified rather */ /* than inserted. It makes the block of 3 ifs in the */ /* original code dependent on NPDup == 0, and inserts */ /* the NP display as an else after those ifs */ if (NPDup == 0) { /* Rewrite the screen if display update indicators are set */ if (redraw_msgs && !npquiet) { /* Display messages in scrolling area */ PANMSG* p; /* Save cursor location */ saved_cons_row = cur_cons_row; saved_cons_col = cur_cons_col; /* Unkeep kept messages if needed */ expire_kept_msgs(0); /* Draw kept messages first */ for (i=0, p=keptmsgs; i < (SCROLL_LINES + numkept) && p; i++, p = p->next) { set_pos (i+1, 1); #if defined(OPTION_MSGCLR) set_color (p->fg, p->bg); #else // !defined(OPTION_MSGCLR) set_color (COLOR_DEFAULT_FG, COLOR_DEFAULT_BG); #endif // defined(OPTION_MSGCLR) write_text (p->msg, MSG_SIZE); } /* Then draw current screen */ for (p=topmsg; i < (SCROLL_LINES + numkept) && (p != curmsg->next || p == topmsg); i++, p = p->next) { set_pos (i+1, 1); #if defined(OPTION_MSGCLR) set_color (p->fg, p->bg); #else // !defined(OPTION_MSGCLR) set_color (COLOR_DEFAULT_FG, COLOR_DEFAULT_BG); #endif // defined(OPTION_MSGCLR) write_text (p->msg, MSG_SIZE); } /* Pad remainder of screen with blank lines */ for (; i < (SCROLL_LINES + numkept); i++) { set_pos (i+1, 1); set_color (COLOR_DEFAULT_FG, COLOR_DEFAULT_BG); erase_to_eol( confp ); } /* Display the scroll indicators */ if (topmsg != oldest_msg()) { /* More messages precede top line */ set_pos (1, cons_cols); set_color (COLOR_DEFAULT_LIGHT, COLOR_DEFAULT_BG); draw_text ("+"); } if (!is_currline_visible()) { /* More messages follow bottom line */ set_pos (cons_rows-2, cons_cols); set_color (COLOR_DEFAULT_LIGHT, COLOR_DEFAULT_BG); draw_text ("V"); } /* restore cursor location */ cur_cons_row = saved_cons_row; cur_cons_col = saved_cons_col; } /* end if(redraw_msgs) */ if (redraw_cmd) { /* Save cursor location */ saved_cons_row = cur_cons_row; saved_cons_col = cur_cons_col; /* Display the command line */ set_pos (CMDLINE_ROW, 1); set_color (COLOR_DEFAULT_LIGHT, COLOR_DEFAULT_BG); #if defined(OPTION_CMDTGT) switch(sysblk.cmdtgt) { case 0: // cmdtgt herc { draw_text(CMD_PREFIX_STR); break; } case 1: // cmdtgt scp { draw_text(CMD_PREFIX_STR1); break; } case 2: // cmdtgt pscp { draw_text(CMD_PREFIX_STR2); break; } } #else // !defined(OPTION_CMDTGT) draw_text (CMD_PREFIX_STR); #endif // defined(OPTION_CMDTGT) set_color (COLOR_DEFAULT_FG, COLOR_DEFAULT_BG); PUTC_CMDLINE (); fill_text (' ',cons_cols); /* restore cursor location */ cur_cons_row = saved_cons_row; cur_cons_col = saved_cons_col; } /* end if(redraw_cmd) */ if (redraw_status && !npquiet) { /* Save cursor location */ saved_cons_row = cur_cons_row; saved_cons_col = cur_cons_col; memset (buf, ' ', cons_cols); len = sprintf (buf, "CPU%4.4X ", sysblk.pcpu); if (IS_CPU_ONLINE(sysblk.pcpu)) { char ibuf[32]; len += sprintf(buf+len, "PSW=%8.8X%8.8X ", fetch_fw(curpsw), fetch_fw(curpsw+4)); if (regs->arch_mode == ARCH_900) len += sprintf (buf+len, "%16.16"I64_FMT"X ", fetch_dw (curpsw+8)); #if defined(_FEATURE_SIE) else if( SIE_MODE(regs) ) { for(i = 0;i < 16;i++) buf[len++] = '-'; buf[len++] = ' '; } #endif /*defined(_FEATURE_SIE)*/ len += sprintf (buf+len, "%2d%c%c%c%c%c%c%c%c", regs->psw.amode64 ? 64 : regs->psw.amode ? 31 : 24, regs->cpustate == CPUSTATE_STOPPED ? 'M' : '.', sysblk.inststep ? 'T' : '.', WAITSTATE(®s->psw) ? 'W' : '.', regs->loadstate ? 'L' : '.', regs->checkstop ? 'C' : '.', PROBSTATE(®s->psw) ? 'P' : '.', SIE_MODE(regs) ? 'S' : '.', regs->arch_mode == ARCH_900 ? 'Z' : '.'); buf[len++] = ' '; sprintf (ibuf, "instcount=%s", format_int(INSTCOUNT(regs))); if (len + (int)strlen(ibuf) < cons_cols) len = cons_cols - strlen(ibuf); strcpy (buf + len, ibuf); } else { len += sprintf (buf+len,"%s", "Offline"); buf[len++] = ' '; } buf[cons_cols] = '\0'; set_pos (cons_rows, 1); set_color (COLOR_LIGHT_YELLOW, COLOR_RED); draw_text (buf); /* restore cursor location */ cur_cons_row = saved_cons_row; cur_cons_col = saved_cons_col; } /* end if(redraw_status) */ /* Flush screen buffer and reset display update indicators */ if (redraw_msgs || redraw_cmd || redraw_status) { set_color (COLOR_DEFAULT_FG, COLOR_DEFAULT_BG); if (NPDup == 0 && NPDinit == 1) { NPDinit = 0; restore_command_line(); set_pos (cur_cons_row, cur_cons_col); } else if (redraw_cmd) set_pos (CMDLINE_ROW, CMDLINE_COL + cmdoff - cmdcol); else set_pos (cur_cons_row, cur_cons_col); fflush (confp); redraw_msgs = redraw_cmd = redraw_status = 0; } } else { /* (NPDup == 1) */ if (redraw_status || (NPDinit == 0 && NPDup == 1) || (redraw_cmd && NPdataentry == 1)) { if (NPDinit == 0) { NPDinit = 1; NP_screen_redraw(regs); NP_update(regs); fflush (confp); } } /* Update New Panel every panrate interval */ if (!npquiet) { NP_update(regs); fflush (confp); } redraw_msgs = redraw_cmd = redraw_status = 0; } /* =END= */ /* Force full screen repaint if needed */ if (!sysblk.npquiet && npquiet) redraw_msgs = redraw_cmd = redraw_status = 1; npquiet = sysblk.npquiet; } /* end while */ ASSERT( sysblk.shutdown ); // (why else would we be here?!) } /* end function panel_display */ static void panel_cleanup(void *unused) { int i; PANMSG* p; UNREFERENCED(unused); log_wakeup(NULL); set_screen_color( stderr, COLOR_DEFAULT_FG, COLOR_DEFAULT_BG ); clear_screen( stderr ); /* Scroll to last full screen's worth of messages */ scroll_to_bottom_screen( 1 ); /* Display messages in scrolling area */ for (i=0, p = topmsg; i < SCROLL_LINES && p != curmsg->next; i++, p = p->next) { set_pos (i+1, 1); #if defined(OPTION_MSGCLR) set_color (p->fg, p->bg); #else // !defined(OPTION_MSGCLR) set_color (COLOR_DEFAULT_FG, COLOR_DEFAULT_BG); #endif // defined(OPTION_MSGCLR) write_text (p->msg, MSG_SIZE); } /* Restore the terminal mode */ set_or_reset_console_mode( keybfd, 0 ); /* Position to next line */ fwrite("\n",1,1,stderr); /* Read and display any msgs still remaining in the system log */ while((lmscnt = log_read(&lmsbuf, &lmsnum, LOG_NOBLOCK))) fwrite(lmsbuf,lmscnt,1,stderr); fflush(stderr); } hercules-3.07/parser.c000644 000765 000765 00000010444 11143760543 016412 0ustar00jmaynardjmaynard000000 000000 /* PARSER.C (c) Copyright Nobody, 1999-2001 */ /* Simple parameter parser */ // $Id: parser.c 4102 2006-12-08 09:43:35Z jj $ // // $Log$ #include "hstdinc.h" #define _PARSER_C_ #define _HUTIL_DLL_ #include "hercules.h" #include "parser.h" #if !defined( NULL ) #define NULL 0 #endif /* NAME parser - parse parameter strings SYNOPSIS #include "parser.h" int parser( PARSER *pp, char *str, void *res ) DESCRIPTION The parser() function breaks the str parameter into a keyword and value using the "=" as a delimiter. The pp table is then scanned for the keyword. If found and the table entry specifies a format string, then parser() will use sscanf() to store the value at the location specifed by res. The PARSER table entries consist of a string pointer that designates the keyword and a string pointer that designates the format of the associated value. The format may be set to NULL if the keyword does not take a value. The table must be terminated with an entry that specifies NULL for the keyword string. RETURN VALUE If no errors are detected then the returned value will be the index+1 of the matching table entry. The res argument will be updated only when a format string is specified. If an entry couldn't be found, zero will be returned and res will remain untouched. If an entry is found, but an error is detected while processing the str parameter then a negative value is returned. This value will be the index-1 of the matching table entry. EXAMPLE #include "parser.h" #include PARSER ptab[] = { { "switchkey", NULL }, { "numkey", "%d" }, { "strkey", "%s" }, }; int main( int argc, char *argv[] ) { int rc; union { int num; char str[ 80 ]; } res; while( --argc ) { rc = parser( &ptab[0], argv[ argc ], &res ); printf( "parser() rc = %d\n", rc ); if( rc < 0 ) { printf( "error parsing keyword: %s\n", ptab[ abs( rc 1 ) ].key ); } else if( rc == 0 ) { printf( "unrecognized keyword: %s\n", argv[ argc ] ); } else { switch( rc ) { case 1: printf( "found switchkey\n" ); break; case 2: printf( "numkey value is: %d\n", res.num ); break; case 3: printf( "strkey value is: %s\n", res.str ); break; } } } } SEE ALSO sscanf(3) */ DLL_EXPORT int parser( PARSER *pp, char *str, void *res ) { int ndx; char *key; char *val; ndx = 1; key = strtok( str, "=" ); val = strtok( NULL, "=" ); while( pp->key != NULL ) { if( strcasecmp( key, pp->key ) == 0 ) { if( pp->fmt == NULL ) { if( val != NULL ) { return( -ndx ); } } else { if( val == NULL ) { return( -ndx ); } if( sscanf( val, pp->fmt, res ) != 1 ) { return( -ndx ); } } return( ndx ); } pp++; ndx++; } return( 0 ); } hercules-3.07/parser.h000644 000765 000765 00000001175 11143760543 016420 0ustar00jmaynardjmaynard000000 000000 /* PARSER.H (c) Copyright Nobody, 1999-2001 */ /* Simple parameter parser */ // $Id: parser.h 4102 2006-12-08 09:43:35Z jj $ // // $Log$ #if !defined( _PARSER_H_ ) #define _PARSER_H_ #include "hercules.h" #ifndef _PARSER_C_ #ifndef _HUTIL_DLL_ #define PAR_DLL_IMPORT DLL_IMPORT #else /* _HUTIL_DLL_ */ #define PAR_DLL_IMPORT extern #endif /* _HUTIL_DLL_ */ #else #define PAR_DLL_IMPORT DLL_EXPORT #endif typedef struct _parser { char *key; char *fmt; } PARSER; PAR_DLL_IMPORT int parser( PARSER *, char *, void * ); #endif /* !defined( _PARSER_H_ ) */ hercules-3.07/pfpo.c000644 000765 000765 00000027601 11301535255 016061 0ustar00jmaynardjmaynard000000 000000 /* PFPO.C (c) Copyright Roger Bowler, 2009 */ /* (c) Copyright Bernard van der Helm, 2009 */ /* Noordwijkerhout, The Netherlands */ /* Perform Floating Point Operation instruction */ // $Id: pfpo.c 5453 2009-08-14 07:18:18Z bernard $ /*-------------------------------------------------------------------*/ /* This module implements the Perform Floating Point Operation */ /* instruction described in the manual SA22-7832-05. */ /*-------------------------------------------------------------------*/ #include "hstdinc.h" #if !defined(_HENGINE_DLL_) #define _HENGINE_DLL_ #endif #if !defined(_PFPO_C_) #define _PFPO_C_ #endif #include "hercules.h" #include "opcode.h" #include "inline.h" #include "decimal128.h" #include "decimal64.h" #include "decimal32.h" #include "decPacked.h" #if defined(FEATURE_PFPO) #define CLASS_ZERO 1 #define CLASS_SUBNORMAL 2 #define CLASS_INFINITY 3 #define CLASS_QNAN 4 #define CLASS_SNAN 5 #define CLASS_NORMAL 6 #define INFINITYSTR "Infinity" #define QNANSTR "NaN" #define SNANSTR "sNaN" typedef struct { unsigned base; unsigned class; char str[256]; } FLOAT; /*-------------------------------------------------------------------*/ /* Binairy floating point routines */ /*-------------------------------------------------------------------*/ void BFPshortGet(FLOAT *f, U32 r) { unsigned exp; U32 frac; unsigned i; U32 mask; unsigned sign; sign = r & 0x80000000 ? 1 : 0; exp = (r & 0x7f800000) >> 23; frac = r & 0x007fffff; if(exp == 127) { if(!frac) f->class = CLASS_ZERO; else f->class = CLASS_SUBNORMAL; } else if(exp == 0xff) { if(!frac) f->class = CLASS_INFINITY; else { if(frac & 0x80000000) f->class = CLASS_QNAN; else f->class = CLASS_SNAN; } } else f->class = CLASS_NORMAL; f->base = 2; switch(f->class) { case CLASS_ZERO: strcpy(f->str, "0"); break; case CLASS_INFINITY: if(sign) strcpy(f->str, "-" INFINITYSTR); else strcpy(f->str, INFINITYSTR); break; case CLASS_QNAN: strcpy(f->str, QNANSTR); break; case CLASS_SNAN: strcpy(f->str, SNANSTR); break; case CLASS_NORMAL: case CLASS_SUBNORMAL: if(sign) strcpy(f->str, "-0."); else strcpy(f->str, "0."); if(f->class == CLASS_NORMAL) strcat(f->str, "1"); else strcat(f->str, "0"); mask = 0x00400000; for(i = 0; i < 23; i++) { if(frac & mask) strcat(f->str, "1"); else strcat(f->str, "0"); mask >>= 1; } strcat(f->str, "@"); if(f->class == CLASS_NORMAL) sprintf(&f->str[strlen(f->str)], "%d", exp - 127); else strcat(f->str, "1"); break; } } void BFPlongGet(FLOAT *f, U64 r) { unsigned exp; U64 frac; unsigned i; U64 mask; unsigned sign; sign = r & 0x8000000000000000 ? 1 : 0; exp = (r & 0x7ff0000000000000) >> 52; frac = r & 0x000fffffffffffff; if(exp == 1023) { if(!frac) f->class = CLASS_ZERO; else f->class = CLASS_SUBNORMAL; } else if(exp == 0x7ff) { if(!frac) f->class = CLASS_INFINITY; else { if(frac & 0x8000000000000000) f->class = CLASS_QNAN; else f->class = CLASS_SNAN; } } else f->class = CLASS_NORMAL; f->base = 2; switch(f->class) { case CLASS_ZERO: strcpy(f->str, "0"); break; case CLASS_INFINITY: if(sign) strcpy(f->str, "-" INFINITYSTR); else strcpy(f->str, INFINITYSTR); break; case CLASS_QNAN: strcpy(f->str, QNANSTR); break; case CLASS_SNAN: strcpy(f->str, SNANSTR); break; case CLASS_NORMAL: case CLASS_SUBNORMAL: if(sign) strcpy(f->str, "-0."); else strcpy(f->str, "0."); if(f->class == CLASS_NORMAL) strcat(f->str, "1"); else strcat(f->str, "0"); mask = 0x0008000000000000; for(i = 0; i < 52; i++) { if(frac & mask) strcat(f->str, "1"); else strcat(f->str, "0"); mask >>= 1; } strcat(f->str, "@"); if(f->class == CLASS_NORMAL) sprintf(&f->str[strlen(f->str)], "%d", exp - 1023); else strcat(f->str, "1"); break; } } void BFPextGet(FLOAT *f, U64 h, U64 l) { unsigned exp; U64 frach; U64 fracl; unsigned i; U64 mask; unsigned sign; sign = h & 0x8000000000000000 ? 1 : 0; exp = (h & 0x7fff000000000000) >> 48; frach = h & 0x0000ffffffffffff; fracl = l; if(exp == 16383) { if(!frach && !fracl) f->class = CLASS_ZERO; else f->class = CLASS_SUBNORMAL; } else if(exp == 0x7fff) { if(!frach && !fracl) f->class = CLASS_INFINITY; else { if(frach & 0x8000000000000000) f->class = CLASS_QNAN; else f->class = CLASS_SNAN; } } else f->class = CLASS_NORMAL; f->base = 2; switch(f->class) { case CLASS_ZERO: strcpy(f->str, "0"); break; case CLASS_INFINITY: if(sign) strcpy(f->str, "-" INFINITYSTR); else strcpy(f->str, INFINITYSTR); break; case CLASS_QNAN: strcpy(f->str, QNANSTR); break; case CLASS_SNAN: strcpy(f->str, SNANSTR); break; case CLASS_NORMAL: case CLASS_SUBNORMAL: if(sign) strcpy(f->str, "-0."); else strcpy(f->str, "0."); if(f->class == CLASS_NORMAL) strcat(f->str, "1"); else strcat(f->str, "0"); mask = 0x0000800000000000; for(i = 0; i < 48; i++) { if(frach & mask) strcat(f->str, "1"); else strcat(f->str, "0"); mask >>= 1; } mask = 0x8000000000000000; for(i = 0; i < 64; i++) { if(fracl & mask) strcat(f->str, "1"); else strcat(f->str, "0"); mask >>= 1; } strcat(f->str, "@"); if(f->class == CLASS_NORMAL) sprintf(&f->str[strlen(f->str)], "%d", exp - 16383); else strcat(f->str, "1"); break; } } /*-------------------------------------------------------------------*/ /* Decimal floating point routines */ /*-------------------------------------------------------------------*/ void DFPshortGet(FLOAT *f, U32 r) { unsigned class; decimal32 dec32; unsigned i; U32 temp; temp = r; for(i = 0; i < 4; i++) { dec32.bytes[i] = temp & 0xff; temp >>= 8; } decimal32ToString(&dec32, f->str); f->base = 10; if(!strncmp(f->str, "-0E", 2) || !strncmp(f->str, "0E", 2)) f->class = CLASS_ZERO; else if(strstr(f->str, "E0")) f->class = CLASS_SUBNORMAL; else if(!strcmp(f->str, "Ininity")) f->class = CLASS_INFINITY; else if(!strcmp(f->str, "NaN")) f->class = CLASS_QNAN; else if(!strcmp(f->str, "sNaN")) f->class = CLASS_SNAN; else f->class = CLASS_NORMAL; } void DFPlongGet(FLOAT *f, U64 r) { unsigned class; decimal64 dec64; unsigned i; U64 temp; temp = r; for(i = 0; i < 8; i++) { dec64.bytes[i] = temp & 0xff; temp >>= 8; } decimal64ToString(&dec64, f->str); f->base = 10; if(!strncmp(f->str, "-0E", 2) || !strncmp(f->str, "0E", 2)) f->class = CLASS_ZERO; else if(strstr(f->str, "E0")) f->class = CLASS_SUBNORMAL; else if(!strcmp(f->str, "Ininity")) f->class = CLASS_INFINITY; else if(!strcmp(f->str, "NaN")) f->class = CLASS_QNAN; else if(!strcmp(f->str, "sNaN")) f->class = CLASS_SNAN; else f->class = CLASS_NORMAL; } void DFPextGet(FLOAT *f, U64 h, U64 l) { unsigned class; decimal128 dec128; unsigned i; U64 temph; U64 templ; temph = h; templ = l; for(i = 0; i < 8; i++) { dec128.bytes[i] = templ & 0xff; dec128.bytes[i + 8] = temph & 0xff; templ >>= 8; temph >>= 8; } decimal128ToString(&dec128, f->str); f->base = 10; if(!strncmp(f->str, "-0E", 2) || !strncmp(f->str, "0E", 2)) f->class = CLASS_ZERO; else if(strstr(f->str, "E0")) f->class = CLASS_SUBNORMAL; else if(!strcmp(f->str, "Ininity")) f->class = CLASS_INFINITY; else if(!strcmp(f->str, "NaN")) f->class = CLASS_QNAN; else if(!strcmp(f->str, "sNaN")) f->class = CLASS_SNAN; else f->class = CLASS_NORMAL; } /*-------------------------------------------------------------------*/ /* Hexadecimal floating point routines */ /*-------------------------------------------------------------------*/ void HFPshortGet(FLOAT *f, U32 r) { unsigned exp; U32 frac; unsigned i; U32 mask; unsigned sign; sign = r & 0x80000000 ? 1 : 0; exp = (r & 0x7f000000) >> 24; frac = r & 0x00ffffff; if(!frac) f->class = CLASS_ZERO; else f->class = CLASS_NORMAL; f->base = 16; switch(f->class) { case CLASS_ZERO: strcpy(f->str, "0"); break; case CLASS_NORMAL: if(sign) strcpy(f->str, "-0."); else strcpy(f->str, "0."); mask = 0x00ff0000; for(i = 0; i < 3; i++) { sprintf(&f->str[strlen(f->str)], "%02x", (r & mask) >> (16 - (i * 8))); mask >>= 8; } strcat(f->str, "@"); sprintf(&f->str[strlen(f->str)], "%d", exp - 64); break; } } void HFPlongGet(FLOAT *f, U64 r) { unsigned class; unsigned exp; U64 frac; unsigned i; U64 mask; unsigned sign; sign = r & 0x8000000000000000 ? 1 : 0; exp = (r & 0x7f00000000000000) >> 56; frac = r & 0x00ffffffffffffff; if(!frac) f->class = CLASS_ZERO; else f->class = CLASS_NORMAL; f->base = 16; switch(class) { case CLASS_ZERO: strcpy(f->str, "0"); break; case CLASS_NORMAL: if(sign) strcpy(f->str, "-0."); else strcpy(f->str, "0."); mask = 0x00ff000000000000; for(i = 0; i < 7; i++) { sprintf(&f->str[strlen(f->str)], "%02x", (r & mask) >> (48 - (i * 8))); mask >>= 8; } strcat(f->str, "@"); sprintf(&f->str[strlen(f->str)], "%d", exp - 64); break; } } void HFPextGet(FLOAT *f, U64 h, U64 l) { unsigned class; unsigned exp; U64 frach; U64 fracl; unsigned i; U64 mask; unsigned sign; sign = h & 0x8000000000000000 ? 1 : 0; exp = (h & 0x7f00000000000000) >> 56; frach = h & 0x00ffffffffffffff; fracl = l & 0x00ffffffffffffff; if(!frach && !fracl) f->class = CLASS_ZERO; else f->class = CLASS_NORMAL; f->base = 16; switch(f->class) { case CLASS_ZERO: strcpy(f->str, "0"); break; case CLASS_NORMAL: if(sign) strcpy(f->str, "-0."); else strcpy(f->str, "0."); mask = 0x00ff000000000000; for(i = 0; i < 7; i++) { sprintf(&f->str[strlen(f->str)], "%02x", (h & mask) >> (48 - (i * 8))); mask >>= 8; } mask = 0x00ff000000000000; for(i = 0; i < 7; i++) { sprintf(&f->str[strlen(f->str)], "%02x", (l & mask) >> (48 - (i * 8))); mask >>= 8; } strcat(f->str, "@"); sprintf(&f->str[strlen(f->str)], "%d", exp - 64); break; } } /*-------------------------------------------------------------------*/ /* 010A PFPO - Perform Floating Point Operation [E] */ /*-------------------------------------------------------------------*/ DEF_INST(perform_floating_point_operation) { E(inst, regs); ARCH_DEP(program_interrupt)(regs, PGM_OPERATION_EXCEPTION); } /* end DEF_INST(perform_floating_point_operation) */ #endif /*defined(FEATURE_PFPO)*/ #if !defined(_GEN_ARCH) #if defined(_ARCHMODE2) #define _GEN_ARCH _ARCHMODE2 #include "pfpo.c" #endif #if defined(_ARCHMODE3) #undef _GEN_ARCH #define _GEN_ARCH _ARCHMODE3 #include "pfpo.c" #endif #endif /*!defined(_GEN_ARCH)*/ hercules-3.07/plo.c000644 000765 000765 00000134554 11143760544 015722 0ustar00jmaynardjmaynard000000 000000 /* PLO.C (c) Copyright Jan Jaeger, 2000-2009 */ /* Perform Locked Operation functions codes */ /* Interpretive Execution - (c) Copyright Jan Jaeger, 1999-2009 */ /* z/Architecture support - (c) Copyright Jan Jaeger, 1999-2009 */ // $Id: plo.c 5126 2009-01-23 13:05:56Z bernard $ // // $Log$ // Revision 1.24 2008/03/05 23:15:13 ptl00 // Fix fc=3 fc=19 and qword chks // // Revision 1.23 2007/06/23 00:04:15 ivan // Update copyright notices to include current year (2007) // // Revision 1.22 2006/12/08 09:43:29 jj // Add CVS message log // #include "hstdinc.h" #if !defined(_HENGINE_DLL_) #define _HENGINE_DLL_ #endif #if !defined(_PLO_C_) #define _PLO_C_ #endif #include "hercules.h" #include "opcode.h" #include "inline.h" #if defined(FEATURE_PERFORM_LOCKED_OPERATION) int ARCH_DEP(plo_cl) (int r1, int r3, VADR effective_addr2, int b2, VADR effective_addr4, int b4, REGS *regs) { U32 op2, op4; FW_CHECK(effective_addr2, regs); FW_CHECK(effective_addr4, regs); /* Load second operand from operand address */ op2 = ARCH_DEP(vfetch4) ( effective_addr2, b2, regs ); if(regs->GR_L(r1) == op2) { op4 = ARCH_DEP(vfetch4) ( effective_addr4, b4, regs ); regs->GR_L(r3) = op4; return 0; } else { regs->GR_L(r1) = op2; return 1; } } int ARCH_DEP(plo_clg) (int r1, int r3, VADR effective_addr2, int b2, VADR effective_addr4, int b4, REGS *regs) { U64 op1c, op2, op4; U32 op4alet = 0; VADR op4addr; UNREFERENCED(r1); DW_CHECK(effective_addr4, regs); DW_CHECK(effective_addr2, regs); /* load second operand */ op2 = ARCH_DEP(vfetch8)(effective_addr2, b2, regs); /* load 1st op. compare value */ op1c = ARCH_DEP(wfetch8)(effective_addr4 + 8, b4, regs); if(op1c == op2) { /* When in ar mode, ar3 is used to access the operand. The alet is fetched from the pl */ if(!REAL_MODE(®s->psw) && ACCESS_REGISTER_MODE(®s->psw)) { if(r3 == 0) ARCH_DEP(program_interrupt)(regs, PGM_SPECIFICATION_EXCEPTION); op4alet = ARCH_DEP(wfetch4)(effective_addr4 + 68, b4, regs); regs->AR(r3) = op4alet; SET_AEA_AR(regs, r3); } /* Load address of operand 4 */ #if defined(FEATURE_ESAME) op4addr = ARCH_DEP(wfetch8)(effective_addr4 + 72, b4, regs); #else op4addr = ARCH_DEP(wfetch4)(effective_addr4 + 76, b4, regs); #endif op4addr &= ADDRESS_MAXWRAP(regs); DW_CHECK(op4addr, regs); /* Load operand 4, using ar3 when in ar mode */ op4 = ARCH_DEP(vfetch8)(op4addr, r3, regs); /* replace the 3rd operand with the 4th operand */ ARCH_DEP(wstore8)(op4, effective_addr4 + 40, b4, regs); return 0; } else { /* replace the first op compare value with 2nd op */ ARCH_DEP(wstore8)(op2, effective_addr4 + 8, b4, regs); return 1; } } #if defined(FEATURE_ESAME) int ARCH_DEP(plo_clgr) (int r1, int r3, VADR effective_addr2, int b2, VADR effective_addr4, int b4, REGS *regs) { U64 op2, op4; DW_CHECK(effective_addr2, regs); DW_CHECK(effective_addr4, regs); /* Load second operand from operand address */ op2 = ARCH_DEP(vfetch8) ( effective_addr2, b2, regs ); if(regs->GR_G(r1) == op2) { op4 = ARCH_DEP(vfetch8) ( effective_addr4, b4, regs ); regs->GR_G(r3) = op4; return 0; } else { regs->GR_G(r1) = op2; return 1; } } #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) int ARCH_DEP(plo_clx) (int r1, int r3, VADR effective_addr2, int b2, VADR effective_addr4, int b4, REGS *regs) { BYTE op1c[16], op2[16], op4[16]; U32 op4alet = 0; VADR op4addr; UNREFERENCED(r1); DW_CHECK(effective_addr4, regs); QW_CHECK(effective_addr2, regs); /* load second operand */ ARCH_DEP(vfetchc) ( op2, 16-1, effective_addr2, b2, regs ); /* load 1st op. compare value */ ARCH_DEP(vfetchc) ( op1c, 16-1, effective_addr4 + 0, b4, regs ); if(memcmp(op1c,op2,16) == 0) { /* When in ar mode, ar3 is used to access the operand. The alet is fetched from the pl */ if(!REAL_MODE(®s->psw) && ACCESS_REGISTER_MODE(®s->psw)) { if(r3 == 0) ARCH_DEP(program_interrupt)(regs, PGM_SPECIFICATION_EXCEPTION); op4alet = ARCH_DEP(wfetch4)(effective_addr4 + 68, b4, regs); regs->AR(r3) = op4alet; SET_AEA_AR(regs, r3); } /* Load address of operand 4 */ op4addr = ARCH_DEP(wfetch8)(effective_addr4 + 72, b4, regs); op4addr &= ADDRESS_MAXWRAP(regs); QW_CHECK(op4addr, regs); /* Load operand 4, using ar3 when in ar mode */ ARCH_DEP(vfetchc) ( op4, 16-1, op4addr, r3, regs ); /* replace the 3rd operand with the 4th operand */ ARCH_DEP(wstorec) ( op4, 16-1, effective_addr4 + 32, b4, regs ); return 0; } else { /* replace the first op compare value with 2nd op */ ARCH_DEP(vstorec) ( op2, 16-1, effective_addr4 + 0, b4, regs ); return 1; } } #endif /*defined(FEATURE_ESAME)*/ int ARCH_DEP(plo_cs) (int r1, int r3, VADR effective_addr2, int b2, VADR effective_addr4, int b4, REGS *regs) { U32 op2; UNREFERENCED(r3); UNREFERENCED(effective_addr4); UNREFERENCED(b4); ODD_CHECK(r1, regs); FW_CHECK(effective_addr2, regs); /* Load second operand from operand address */ op2 = ARCH_DEP(vfetch4) ( effective_addr2, b2, regs ); /* Compare operand with R1 register contents */ if ( regs->GR_L(r1) == op2 ) { /* If equal, store R1+1 at operand loc and set cc=0 */ ARCH_DEP(vstore4) ( regs->GR_L(r1+1), effective_addr2, b2, regs ); return 0; } else { /* If unequal, load R1 from operand and set cc=1 */ regs->GR_L(r1) = op2; return 1; } } int ARCH_DEP(plo_csg) (int r1, int r3, VADR effective_addr2, int b2, VADR effective_addr4, int b4, REGS *regs) { U64 op1c, op1r, op2; UNREFERENCED(r1); UNREFERENCED(r3); DW_CHECK(effective_addr4, regs); DW_CHECK(effective_addr2, regs); /* Load first op compare value */ op1c = ARCH_DEP(wfetch8)(effective_addr4 + 8, b4, regs); /* Load 2nd operand */ op2 = ARCH_DEP(vfetch8)(effective_addr2, b2, regs); if(op1c == op2) { /* Load 1st op replacement value */ op1r = ARCH_DEP(wfetch8)(effective_addr4 + 24, b4, regs); /* Store at 2nd operand location */ ARCH_DEP(vstore8)(op1r, effective_addr2, b2, regs); return 0; } else { /* Replace 1st op comp value by 2nd op */ ARCH_DEP(wstore8)(op2, effective_addr4 + 8, b4, regs); return 1; } } #if defined(FEATURE_ESAME) int ARCH_DEP(plo_csgr) (int r1, int r3, VADR effective_addr2, int b2, VADR effective_addr4, int b4, REGS *regs) { U64 op2; UNREFERENCED(r3); UNREFERENCED(effective_addr4); UNREFERENCED(b4); ODD_CHECK(r1, regs); DW_CHECK(effective_addr2, regs); /* Load second operand from operand address */ op2 = ARCH_DEP(vfetch8) ( effective_addr2, b2, regs ); /* Compare operand with R1 register contents */ if ( regs->GR_G(r1) == op2 ) { /* If equal, store R1+1 at operand loc and set cc=0 */ ARCH_DEP(vstore8) ( regs->GR_G(r1+1), effective_addr2, b2, regs ); return 0; } else { /* If unequal, load R1 from operand and set cc=1 */ regs->GR_G(r1) = op2; return 1; } } #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) int ARCH_DEP(plo_csx) (int r1, int r3, VADR effective_addr2, int b2, VADR effective_addr4, int b4, REGS *regs) { BYTE op1c[16], op1r[16], op2[16]; UNREFERENCED(r1); UNREFERENCED(r3); DW_CHECK(effective_addr4, regs); QW_CHECK(effective_addr2, regs); /* Load first op compare value */ ARCH_DEP(vfetchc) ( op1c, 16-1, effective_addr4 + 0, b4, regs ); /* Load 2nd operand */ ARCH_DEP(vfetchc) ( op2, 16-1, effective_addr2, b2, regs ); if(memcmp(op1c,op2,16) == 0) { /* Load 1st op replacement value */ ARCH_DEP(wfetchc) ( op1r, 16-1, effective_addr4 + 16, b4, regs ); /* Store at 2nd operand location */ ARCH_DEP(vstorec) ( op1r, 16-1, effective_addr2, b2, regs ); return 0; } else { /* Replace 1st op comp value by 2nd op */ ARCH_DEP(vstorec) ( op2, 16-1, effective_addr4 + 0, b4, regs ); return 1; } } #endif /*defined(FEATURE_ESAME)*/ int ARCH_DEP(plo_dcs) (int r1, int r3, VADR effective_addr2, int b2, VADR effective_addr4, int b4, REGS *regs) { U32 op2, op4; ODD2_CHECK(r1, r3, regs); FW_CHECK(effective_addr2, regs); FW_CHECK(effective_addr4, regs); /* Load second operands from operand addresses */ op2 = ARCH_DEP(vfetch4) ( effective_addr2, b2, regs ); if(regs->GR_L(r1) != op2) { regs->GR_L(r1) = op2; return 1; } else { op4 = ARCH_DEP(vfetch4) ( effective_addr4, b4, regs ); /* Compare operand with register contents */ if (regs->GR_L(r3) != op4) { /* If unequal, load r3 from op and set cc=2 */ regs->GR_L(r3) = op4; return 2; } else { /* Verify access to 2nd operand */ ARCH_DEP(validate_operand) (effective_addr2, b2, 4-1, ACCTYPE_WRITE_SKP, regs); /* If equal, store replacement and set cc=0 */ ARCH_DEP(vstore4) ( regs->GR_L(r3+1), effective_addr4, b4, regs ); ARCH_DEP(vstore4) ( regs->GR_L(r1+1), effective_addr2, b2, regs ); return 0; } } } int ARCH_DEP(plo_dcsg) (int r1, int r3, VADR effective_addr2, int b2, VADR effective_addr4, int b4, REGS *regs) { U64 op1c, op1r, op2, op3c, op3r, op4; U32 op4alet = 0; VADR op4addr; UNREFERENCED(r1); DW_CHECK(effective_addr2, regs); DW_CHECK(effective_addr4, regs); /* load 1st op compare value from the pl */ op1c = ARCH_DEP(wfetch8)(effective_addr4 + 8, b4, regs); /* load 2nd operand */ op2 = ARCH_DEP(vfetch8)(effective_addr2, b2, regs); if(op1c != op2) { /* replace the 1st op compare value with 2nd op */ ARCH_DEP(wstore8)(op2, effective_addr4 + 8, b4, regs); return 1; } else { /* Load 3rd op compare value */ op3c = ARCH_DEP(wfetch8)(effective_addr4 + 40, b4, regs); /* When in ar mode, ar3 is used to access the operand. The alet is fetched from the pl */ if(!REAL_MODE(®s->psw) && ACCESS_REGISTER_MODE(®s->psw)) { if(r3 == 0) ARCH_DEP(program_interrupt)(regs, PGM_SPECIFICATION_EXCEPTION); op4alet = ARCH_DEP(wfetch4)(effective_addr4 + 68, b4, regs); regs->AR(r3) = op4alet; SET_AEA_AR(regs, r3); } /* Load address of operand 4 */ #if defined(FEATURE_ESAME) op4addr = ARCH_DEP(wfetch8)(effective_addr4 + 72, b4, regs); #else op4addr = ARCH_DEP(wfetch4)(effective_addr4 + 76, b4, regs); #endif op4addr &= ADDRESS_MAXWRAP(regs); DW_CHECK(op4addr, regs); /* Load operand 4, using ar3 when in ar mode */ op4 = ARCH_DEP(vfetch8)(op4addr, r3, regs); if(op3c != op4) { ARCH_DEP(wstore8)(op4, effective_addr4 + 40, b4, regs); return 2; } else { /* load replacement values */ op1r = ARCH_DEP(wfetch8)(effective_addr4 + 24, b4, regs); op3r = ARCH_DEP(wfetch8)(effective_addr4 + 56, b4, regs); /* Verify access to 2nd operand */ ARCH_DEP(validate_operand) (effective_addr2, b2, 8-1, ACCTYPE_WRITE_SKP, regs); /* Store 3rd op replacement at 4th op */ ARCH_DEP(vstore8)(op3r, op4addr, r3, regs); /* Store 1st op replacement at 2nd op */ ARCH_DEP(vstore8)(op1r, effective_addr2, b2, regs); return 0; } } } #if defined(FEATURE_ESAME) int ARCH_DEP(plo_dcsgr) (int r1, int r3, VADR effective_addr2, int b2, VADR effective_addr4, int b4, REGS *regs) { U64 op2, op4; ODD2_CHECK(r1, r3, regs); DW_CHECK(effective_addr2, regs); DW_CHECK(effective_addr4, regs); /* Load second operands from operand addresses */ op2 = ARCH_DEP(vfetch8) ( effective_addr2, b2, regs ); if(regs->GR_G(r1) != op2) { regs->GR_G(r1) = op2; return 1; } else { op4 = ARCH_DEP(vfetch8) ( effective_addr4, b4, regs ); /* Compare operand with register contents */ if (regs->GR_G(r3) != op4) { /* If unequal, load r3 from op and set cc=2 */ regs->GR_G(r3) = op4; return 2; } else { /* Verify access to 2nd operand */ ARCH_DEP(validate_operand) (effective_addr2, b2, 4-1, ACCTYPE_WRITE_SKP, regs); /* If equal, store replacement and set cc=0 */ ARCH_DEP(vstore8) ( regs->GR_G(r3+1), effective_addr4, b4, regs ); ARCH_DEP(vstore8) ( regs->GR_G(r1+1), effective_addr2, b2, regs ); return 0; } } } #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) int ARCH_DEP(plo_dcsx) (int r1, int r3, VADR effective_addr2, int b2, VADR effective_addr4, int b4, REGS *regs) { BYTE op1c[16], op1r[16], op2[16], op3c[16], op3r[16], op4[16]; U32 op4alet = 0; VADR op4addr; UNREFERENCED(r1); QW_CHECK(effective_addr2, regs); DW_CHECK(effective_addr4, regs); /* load 1st op compare value from the pl */ ARCH_DEP(vfetchc) ( op1c, 16-1, effective_addr4 + 0, b4, regs ); /* load 2nd operand */ ARCH_DEP(vfetchc) ( op2, 16-1, effective_addr2, b2, regs ); if(memcmp(op1c,op2,16) != 0) { /* replace the 1st op compare value with 2nd op */ ARCH_DEP(vstorec) ( op2, 16-1, effective_addr4 + 0, b4, regs ); return 1; } else { /* Load 3rd op compare value */ ARCH_DEP(wfetchc) ( op3c, 16-1, effective_addr4 + 32, b4, regs ); /* When in ar mode, ar3 is used to access the operand. The alet is fetched from the pl */ if(!REAL_MODE(®s->psw) && ACCESS_REGISTER_MODE(®s->psw)) { if(r3 == 0) ARCH_DEP(program_interrupt)(regs, PGM_SPECIFICATION_EXCEPTION); op4alet = ARCH_DEP(wfetch4)(effective_addr4 + 68, b4, regs); regs->AR(r3) = op4alet; SET_AEA_AR(regs, r3); } /* Load address of operand 4 */ op4addr = ARCH_DEP(wfetch8)(effective_addr4 + 72, b4, regs); op4addr &= ADDRESS_MAXWRAP(regs); QW_CHECK(op4addr, regs); /* Load operand 4, using ar3 when in ar mode */ ARCH_DEP(vfetchc) ( op4, 16-1, op4addr, r3, regs ); if(memcmp(op3c,op4,16) != 0) { ARCH_DEP(wstorec) ( op4, 16-1, effective_addr4 + 32, b4, regs ); return 2; } else { /* load replacement values */ ARCH_DEP(wfetchc) ( op1r, 16-1, effective_addr4 + 16, b4, regs ); ARCH_DEP(wfetchc) ( op3r, 16-1, effective_addr4 + 48, b4, regs ); /* Verify access to 2nd operand */ ARCH_DEP(validate_operand) (effective_addr2, b2, 16-1, ACCTYPE_WRITE_SKP, regs); /* Store 3rd op replacement at 4th op */ ARCH_DEP(vstorec) ( op3r, 16-1, op4addr, r3, regs); /* Store 1st op replacement at 2nd op */ ARCH_DEP(vstorec) ( op1r, 16-1, effective_addr2, b2, regs); return 0; } } } #endif /*defined(FEATURE_ESAME)*/ int ARCH_DEP(plo_csst) (int r1, int r3, VADR effective_addr2, int b2, VADR effective_addr4, int b4, REGS *regs) { U32 op2; ODD_CHECK(r1, regs); FW_CHECK(effective_addr2, regs); FW_CHECK(effective_addr4, regs); /* Load second operand from operand address */ op2 = ARCH_DEP(vfetch4) ( effective_addr2, b2, regs ); /* Compare operand with register contents */ if ( regs->GR_L(r1) == op2) { /* Verify access to 2nd operand */ ARCH_DEP(validate_operand) (effective_addr2, b2, 4-1, ACCTYPE_WRITE_SKP, regs); /* If equal, store replacement and set cc=0 */ ARCH_DEP(vstore4) ( regs->GR_L(r3), effective_addr4, b4, regs ); ARCH_DEP(vstore4) ( regs->GR_L(r1+1), effective_addr2, b2, regs ); return 0; } else { regs->GR_L(r1) = op2; return 1; } } int ARCH_DEP(plo_csstg) (int r1, int r3, VADR effective_addr2, int b2, VADR effective_addr4, int b4, REGS *regs) { U64 op1c, op1r, op2, op3; U32 op4alet = 0; VADR op4addr; UNREFERENCED(r1); DW_CHECK(effective_addr2, regs); DW_CHECK(effective_addr4, regs); op1c = ARCH_DEP(wfetch8)(effective_addr4 + 8, b4, regs); op2 = ARCH_DEP(vfetch8)(effective_addr2, b2, regs); if(op1c == op2) { op1r = ARCH_DEP(wfetch8)(effective_addr4 + 24, b4, regs); op3 = ARCH_DEP(wfetch8)(effective_addr4 + 56, b4, regs); /* Verify access to 2nd operand */ ARCH_DEP(validate_operand) (effective_addr2, b2, 8-1, ACCTYPE_WRITE_SKP, regs); /* When in ar mode, ar3 is used to access the operand. The alet is fetched from the pl */ if(!REAL_MODE(®s->psw) && ACCESS_REGISTER_MODE(®s->psw)) { if(r3 == 0) ARCH_DEP(program_interrupt)(regs, PGM_SPECIFICATION_EXCEPTION); op4alet = ARCH_DEP(wfetch4)(effective_addr4 + 68, b4, regs); regs->AR(r3) = op4alet; SET_AEA_AR(regs, r3); } /* Load address of operand 4 */ #if defined(FEATURE_ESAME) op4addr = ARCH_DEP(wfetch8)(effective_addr4 + 72, b4, regs); #else op4addr = ARCH_DEP(wfetch4)(effective_addr4 + 76, b4, regs); #endif op4addr &= ADDRESS_MAXWRAP(regs); DW_CHECK(op4addr, regs); ARCH_DEP(vstore8)(op3, op4addr, r3, regs); ARCH_DEP(vstore8)(op1r, effective_addr2, b2, regs); return 0; } else { /* Store 2nd op at 1st op comare value */ ARCH_DEP(wstore8)(op2, effective_addr4 + 8, b4, regs); return 1; } } #if defined(FEATURE_ESAME) int ARCH_DEP(plo_csstgr) (int r1, int r3, VADR effective_addr2, int b2, VADR effective_addr4, int b4, REGS *regs) { U64 op2; ODD_CHECK(r1, regs); DW_CHECK(effective_addr2, regs); DW_CHECK(effective_addr4, regs); /* Load second operand from operand address */ op2 = ARCH_DEP(vfetch8) ( effective_addr2, b2, regs ); /* Compare operand with register contents */ if ( regs->GR_G(r1) == op2) { /* Verify access to 2nd operand */ ARCH_DEP(validate_operand) (effective_addr2, b2, 8-1, ACCTYPE_WRITE_SKP, regs); /* If equal, store replacement and set cc=0 */ ARCH_DEP(vstore8) ( regs->GR_G(r3), effective_addr4, b4, regs ); ARCH_DEP(vstore8) ( regs->GR_G(r1+1), effective_addr2, b2, regs ); return 0; } else { regs->GR_G(r1) = op2; return 1; } } #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) int ARCH_DEP(plo_csstx) (int r1, int r3, VADR effective_addr2, int b2, VADR effective_addr4, int b4, REGS *regs) { BYTE op1c[16], op1r[16], op2[16], op3[16]; U32 op4alet = 0; VADR op4addr; UNREFERENCED(r1); QW_CHECK(effective_addr2, regs); DW_CHECK(effective_addr4, regs); ARCH_DEP(vfetchc) ( op1c, 16-1, effective_addr4 + 0, b4, regs ); ARCH_DEP(vfetchc) ( op2, 16-1, effective_addr2, b2, regs ); if(memcmp(op1c,op2,16) == 0) { ARCH_DEP(wfetchc) ( op1r, 16-1, effective_addr4 + 16, b4, regs ); ARCH_DEP(wfetchc) ( op3, 16-1, effective_addr4 + 48, b4, regs ); /* Verify access to 2nd operand */ ARCH_DEP(validate_operand) (effective_addr2, b2, 16-1, ACCTYPE_WRITE_SKP, regs); /* When in ar mode, ar3 is used to access the operand. The alet is fetched from the pl */ if(!REAL_MODE(®s->psw) && ACCESS_REGISTER_MODE(®s->psw)) { if(r3 == 0) ARCH_DEP(program_interrupt)(regs, PGM_SPECIFICATION_EXCEPTION); op4alet = ARCH_DEP(wfetch4)(effective_addr4 + 68, b4, regs); regs->AR(r3) = op4alet; SET_AEA_AR(regs, r3); } /* Load address of operand 4 */ op4addr = ARCH_DEP(wfetch8)(effective_addr4 + 72, b4, regs); op4addr &= ADDRESS_MAXWRAP(regs); QW_CHECK(op4addr, regs); ARCH_DEP(vstorec)(op3, 16-1, op4addr, r3, regs); ARCH_DEP(vstorec)(op1r, 16-1, effective_addr2, b2, regs); return 0; } else { /* Store 2nd op at 1st op comare value */ ARCH_DEP(vstorec)(op2, 16-1, effective_addr4 + 0, b4, regs); return 1; } } #endif /*defined(FEATURE_ESAME)*/ int ARCH_DEP(plo_csdst) (int r1, int r3, VADR effective_addr2, int b2, VADR effective_addr4, int b4, REGS *regs) { U32 op2, op3, op4alet = 0, op5, op6alet = 0; VADR op4addr, op6addr; ODD_CHECK(r1, regs); FW_CHECK(effective_addr2, regs); FW_CHECK(effective_addr4, regs); op2 = ARCH_DEP(vfetch4)(effective_addr2, b2, regs); op3 = ARCH_DEP(wfetch4)(effective_addr4 + 60, b4, regs); op5 = ARCH_DEP(wfetch4)(effective_addr4 + 92, b4, regs); if(regs->GR_L(r1) == op2) { /* Verify access to 2nd operand */ ARCH_DEP(validate_operand) (effective_addr2, b2, 4-1, ACCTYPE_WRITE_SKP, regs); /* When in ar mode, ar3 is used to access the operand. The alet is fetched from the pl */ if(!REAL_MODE(®s->psw) && ACCESS_REGISTER_MODE(®s->psw)) { if(r3 == 0) ARCH_DEP(program_interrupt)(regs, PGM_SPECIFICATION_EXCEPTION); op4alet = ARCH_DEP(wfetch4)(effective_addr4 + 68, b4, regs); op6alet = ARCH_DEP(wfetch4)(effective_addr4 + 100, b4, regs); regs->AR(r3) = op6alet; SET_AEA_AR(regs, r3); } /* Load address of operand 4 */ #if defined(FEATURE_ESAME) op4addr = ARCH_DEP(wfetch8)(effective_addr4 + 72, b4, regs); #else op4addr = ARCH_DEP(wfetch4)(effective_addr4 + 76, b4, regs); #endif op4addr &= ADDRESS_MAXWRAP(regs); FW_CHECK(op4addr, regs); /* Load address of operand 6 */ #if defined(FEATURE_ESAME) op6addr = ARCH_DEP(wfetch8)(effective_addr4 + 104, b4, regs); #else op6addr = ARCH_DEP(wfetch4)(effective_addr4 + 108, b4, regs); #endif op6addr &= ADDRESS_MAXWRAP(regs); FW_CHECK(op6addr, regs); /* Verify access to 6th operand */ ARCH_DEP(validate_operand) (op6addr, r3, 4-1,ACCTYPE_WRITE_SKP, regs); /* Store 3th op at 4th op */ if(!REAL_MODE(®s->psw) && ACCESS_REGISTER_MODE(®s->psw)) { regs->AR(r3) = op4alet; SET_AEA_AR(regs, r3); } ARCH_DEP(vstore4)(op3, op4addr, r3, regs); /* Store 5th op at 6th op */ if(!REAL_MODE(®s->psw) && ACCESS_REGISTER_MODE(®s->psw)) { regs->AR(r3) = op6alet; SET_AEA_AR(regs, r3); } ARCH_DEP(vstore4)(op5, op6addr, r3, regs); /* Store 1st op at 2nd op */ ARCH_DEP(vstore4)(regs->GR_L(r1+1), effective_addr2, b2, regs); return 0; } else { regs->GR_L(r1) = op2; return 1; } } int ARCH_DEP(plo_csdstg) (int r1, int r3, VADR effective_addr2, int b2, VADR effective_addr4, int b4, REGS *regs) { U64 op1c, op1r, op2, op3, op5; U32 op4alet = 0, op6alet = 0; VADR op4addr, op6addr; UNREFERENCED(r1); DW_CHECK(effective_addr2, regs); DW_CHECK(effective_addr4, regs); op1c = ARCH_DEP(wfetch8)(effective_addr4 + 8, b4, regs); op2 = ARCH_DEP(vfetch8)(effective_addr2, b2, regs); if(op1c == op2) { op1r = ARCH_DEP(wfetch8)(effective_addr4 + 24, b4, regs); op3 = ARCH_DEP(wfetch8)(effective_addr4 + 56, b4, regs); op5 = ARCH_DEP(wfetch8)(effective_addr4 + 88, b4, regs); /* Verify access to 2nd operand */ ARCH_DEP(validate_operand) (effective_addr2, b2, 8-1, ACCTYPE_WRITE_SKP, regs); /* When in ar mode, ar3 is used to access the operand. The alet is fetched from the pl */ if(!REAL_MODE(®s->psw) && ACCESS_REGISTER_MODE(®s->psw)) { if(r3 == 0) ARCH_DEP(program_interrupt)(regs, PGM_SPECIFICATION_EXCEPTION); op4alet = ARCH_DEP(wfetch4)(effective_addr4 + 68, b4, regs); op6alet = ARCH_DEP(wfetch4)(effective_addr4 + 100, b4, regs); regs->AR(r3) = op6alet; SET_AEA_AR(regs, r3); } /* Load address of operand 4 */ #if defined(FEATURE_ESAME) op4addr = ARCH_DEP(wfetch8)(effective_addr4 + 72, b4, regs); #else op4addr = ARCH_DEP(wfetch4)(effective_addr4 + 76, b4, regs); #endif op4addr &= ADDRESS_MAXWRAP(regs); DW_CHECK(op4addr, regs); /* Load address of operand 6 */ #if defined(FEATURE_ESAME) op6addr = ARCH_DEP(wfetch8)(effective_addr4 + 104, b4, regs); #else op6addr = ARCH_DEP(wfetch4)(effective_addr4 + 108, b4, regs); #endif op6addr &= ADDRESS_MAXWRAP(regs); DW_CHECK(op6addr, regs); /* Verify access to 6th operand */ ARCH_DEP(validate_operand) (op6addr, r3, 8-1, ACCTYPE_WRITE_SKP, regs); /* Store 3th op at 4th op */ if(!REAL_MODE(®s->psw) && ACCESS_REGISTER_MODE(®s->psw)) { regs->AR(r3) = op4alet; SET_AEA_AR(regs, r3); } ARCH_DEP(vstore8)(op3, op4addr, r3, regs); /* Store 5th op at 6th op */ if(!REAL_MODE(®s->psw) && ACCESS_REGISTER_MODE(®s->psw)) { regs->AR(r3) = op6alet; SET_AEA_AR(regs, r3); } ARCH_DEP(vstore8)(op5, op6addr, r3, regs); /* Store 1st op replacement at 2nd op */ ARCH_DEP(vstore8)(op1r, effective_addr2, b2, regs); return 0; } else { ARCH_DEP(wstore8)(op2, effective_addr4 + 8, b4, regs); return 1; } } #if defined(FEATURE_ESAME) int ARCH_DEP(plo_csdstgr) (int r1, int r3, VADR effective_addr2, int b2, VADR effective_addr4, int b4, REGS *regs) { U64 op2, op3, op5; U32 op4alet = 0, op6alet = 0; VADR op4addr, op6addr; ODD_CHECK(r1, regs); DW_CHECK(effective_addr2, regs); DW_CHECK(effective_addr4, regs); op2 = ARCH_DEP(vfetch8)(effective_addr2, b2, regs); if(regs->GR_G(r1) == op2) { op3 = ARCH_DEP(wfetch8)(effective_addr4 + 56, b4, regs); op5 = ARCH_DEP(wfetch8)(effective_addr4 + 88, b4, regs); /* Verify access to 2nd operand */ ARCH_DEP(validate_operand) (effective_addr2, b2, 8-1, ACCTYPE_WRITE_SKP, regs); /* When in ar mode, ar3 is used to access the operand. The alet is fetched from the pl */ if(!REAL_MODE(®s->psw) && ACCESS_REGISTER_MODE(®s->psw)) { if(r3 == 0) ARCH_DEP(program_interrupt)(regs, PGM_SPECIFICATION_EXCEPTION); op4alet = ARCH_DEP(wfetch4)(effective_addr4 + 68, b4, regs); op6alet = ARCH_DEP(wfetch4)(effective_addr4 + 100, b4, regs); regs->AR(r3) = op6alet; SET_AEA_AR(regs, r3); } /* Load address of operand 4 */ op4addr = ARCH_DEP(wfetch8)(effective_addr4 + 72, b4, regs); op4addr &= ADDRESS_MAXWRAP(regs); DW_CHECK(op4addr, regs); /* Load address of operand 6 */ op6addr = ARCH_DEP(wfetch8)(effective_addr4 + 104, b4, regs); op6addr &= ADDRESS_MAXWRAP(regs); DW_CHECK(op6addr, regs); /* Verify access to 6th operand */ ARCH_DEP(validate_operand) (op6addr, r3, 8-1,ACCTYPE_WRITE_SKP, regs); /* Store 3th op at 4th op */ if(!REAL_MODE(®s->psw) && ACCESS_REGISTER_MODE(®s->psw)) { regs->AR(r3) = op4alet; SET_AEA_AR(regs, r3); } ARCH_DEP(vstore8)(op3, op4addr, r3, regs); /* Store 5th op at 6th op */ if(!REAL_MODE(®s->psw) && ACCESS_REGISTER_MODE(®s->psw)) { regs->AR(r3) = op6alet; SET_AEA_AR(regs, r3); } ARCH_DEP(vstore8)(op5, op6addr, r3, regs); /* Store 1st op at 2nd op */ ARCH_DEP(vstore8)(regs->GR_G(r1+1), effective_addr2, b2, regs); return 0; } else { regs->GR_G(r1) = op2; return 1; } } #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) int ARCH_DEP(plo_csdstx) (int r1, int r3, VADR effective_addr2, int b2, VADR effective_addr4, int b4, REGS *regs) { BYTE op1c[16], op1r[16], op2[16], op3[16], op5[16]; U32 op4alet = 0, op6alet = 0; VADR op4addr, op6addr; UNREFERENCED(r1); QW_CHECK(effective_addr2, regs); DW_CHECK(effective_addr4, regs); ARCH_DEP(vfetchc)(op1c, 16-1, effective_addr4 + 0, b4, regs); ARCH_DEP(vfetchc)(op2, 16-1, effective_addr2, b2, regs); if(memcmp(op1c,op2,16) == 0) { ARCH_DEP(wfetchc)(op1r, 16-1, effective_addr4 + 16, b4, regs); ARCH_DEP(wfetchc)(op3, 16-1, effective_addr4 + 48, b4, regs); ARCH_DEP(wfetchc)(op5, 16-1, effective_addr4 + 80, b4, regs); /* Verify access to 2nd operand */ ARCH_DEP(validate_operand) (effective_addr2, b2, 16-1, ACCTYPE_WRITE_SKP, regs); /* When in ar mode, ar3 is used to access the operand. The alet is fetched from the pl */ if(!REAL_MODE(®s->psw) && ACCESS_REGISTER_MODE(®s->psw)) { if(r3 == 0) ARCH_DEP(program_interrupt)(regs, PGM_SPECIFICATION_EXCEPTION); op4alet = ARCH_DEP(wfetch4)(effective_addr4 + 68, b4, regs); op6alet = ARCH_DEP(wfetch4)(effective_addr4 + 100, b4, regs); regs->AR(r3) = op6alet; SET_AEA_AR(regs, r3); } /* Load address of operand 4 */ op4addr = ARCH_DEP(wfetch8)(effective_addr4 + 72, b4, regs); op4addr &= ADDRESS_MAXWRAP(regs); QW_CHECK(op4addr, regs); /* Load address of operand 6 */ op6addr = ARCH_DEP(wfetch8)(effective_addr4 + 104, b4, regs); op6addr &= ADDRESS_MAXWRAP(regs); QW_CHECK(op6addr, regs); /* Verify access to 6th operand */ ARCH_DEP(validate_operand) (op6addr, r3, 16-1,ACCTYPE_WRITE_SKP, regs); /* Store 3th op at 4th op */ if(!REAL_MODE(®s->psw) && ACCESS_REGISTER_MODE(®s->psw)) { regs->AR(r3) = op4alet; SET_AEA_AR(regs, r3); } ARCH_DEP(vstorec)(op3, 16-1, op4addr, r3, regs); /* Store 5th op at 6th op */ if(!REAL_MODE(®s->psw) && ACCESS_REGISTER_MODE(®s->psw)) { regs->AR(r3) = op6alet; SET_AEA_AR(regs, r3); } ARCH_DEP(vstorec)(op5, 16-1, op6addr, r3, regs); /* Store 1st op replacement at 2nd op */ ARCH_DEP(vstorec)(op1r, 16-1, effective_addr2, b2, regs); return 0; } else { ARCH_DEP(vstorec)(op2, 16-1, effective_addr4 + 0, b4, regs); return 1; } } #endif /*defined(FEATURE_ESAME)*/ int ARCH_DEP(plo_cstst) (int r1, int r3, VADR effective_addr2, int b2, VADR effective_addr4, int b4, REGS *regs) { U32 op2, op3, op4alet = 0, op5, op6alet = 0, op7, op8alet = 0; VADR op4addr, op6addr, op8addr; ODD_CHECK(r1, regs); FW_CHECK(effective_addr2, regs); FW_CHECK(effective_addr4, regs); op2 = ARCH_DEP(vfetch4)(effective_addr2, b2, regs); op3 = ARCH_DEP(wfetch4)(effective_addr4 + 60, b4, regs); op5 = ARCH_DEP(wfetch4)(effective_addr4 + 92, b4, regs); op7 = ARCH_DEP(wfetch4)(effective_addr4 + 124, b4, regs); if(regs->GR_L(r1) == op2) { /* Verify access to 2nd operand */ ARCH_DEP(validate_operand) (effective_addr2, b2, 4-1, ACCTYPE_WRITE_SKP, regs); /* When in ar mode, ar3 is used to access the operand. The alet is fetched from the pl */ if(!REAL_MODE(®s->psw) && ACCESS_REGISTER_MODE(®s->psw)) { if(r3 == 0) ARCH_DEP(program_interrupt)(regs, PGM_SPECIFICATION_EXCEPTION); op4alet = ARCH_DEP(wfetch4)(effective_addr4 + 68, b4, regs); op6alet = ARCH_DEP(wfetch4)(effective_addr4 + 100, b4, regs); op8alet = ARCH_DEP(wfetch4)(effective_addr4 + 132, b4, regs); regs->AR(r3) = op8alet; SET_AEA_AR(regs, r3); } /* Load address of operand 4 */ #if defined(FEATURE_ESAME) op4addr = ARCH_DEP(wfetch8)(effective_addr4 + 72, b4, regs); #else op4addr = ARCH_DEP(wfetch4)(effective_addr4 + 76, b4, regs); #endif op4addr &= ADDRESS_MAXWRAP(regs); FW_CHECK(op4addr, regs); /* Load address of operand 6 */ #if defined(FEATURE_ESAME) op6addr = ARCH_DEP(wfetch8)(effective_addr4 + 104, b4, regs); #else op6addr = ARCH_DEP(wfetch4)(effective_addr4 + 108, b4, regs); #endif op6addr &= ADDRESS_MAXWRAP(regs); FW_CHECK(op6addr, regs); /* Load address of operand 8 */ #if defined(FEATURE_ESAME) op8addr = ARCH_DEP(wfetch8)(effective_addr4 + 136, b4, regs); #else op8addr = ARCH_DEP(wfetch4)(effective_addr4 + 140, b4, regs); #endif op8addr &= ADDRESS_MAXWRAP(regs); FW_CHECK(op8addr, regs); /* Verify access to 8th operand */ ARCH_DEP(validate_operand) (op8addr, r3, 4-1,ACCTYPE_WRITE_SKP, regs); /* Verify access to 6th operand */ if(!REAL_MODE(®s->psw) && ACCESS_REGISTER_MODE(®s->psw)) { regs->AR(r3) = op6alet; SET_AEA_AR(regs, r3); } ARCH_DEP(validate_operand) (op6addr, r3, 4-1, ACCTYPE_WRITE_SKP, regs); /* Store 3rd op at 4th op */ if(!REAL_MODE(®s->psw) && ACCESS_REGISTER_MODE(®s->psw)) { regs->AR(r3) = op4alet; SET_AEA_AR(regs, r3); } ARCH_DEP(vstore4)(op3, op4addr, r3, regs); /* Store 5th op at 6th op */ if(!REAL_MODE(®s->psw) && ACCESS_REGISTER_MODE(®s->psw)) { regs->AR(r3) = op6alet; SET_AEA_AR(regs, r3); } ARCH_DEP(vstore4)(op5, op6addr, r3, regs); /* Store 7th op at 8th op */ if(!REAL_MODE(®s->psw) && ACCESS_REGISTER_MODE(®s->psw)) { regs->AR(r3) = op8alet; SET_AEA_AR(regs, r3); } ARCH_DEP(vstore4)(op7, op8addr, r3, regs); /* Store 1st op replacement at 2nd op */ ARCH_DEP(vstore4)(regs->GR_L(r1+1), effective_addr2, b2, regs); return 0; } else { regs->GR_L(r1) = op2; return 1; } } int ARCH_DEP(plo_cststg) (int r1, int r3, VADR effective_addr2, int b2, VADR effective_addr4, int b4, REGS *regs) { U64 op1c, op1r, op2, op3, op5, op7; U32 op4alet = 0, op6alet = 0, op8alet = 0; VADR op4addr, op6addr, op8addr; UNREFERENCED(r1); DW_CHECK(effective_addr2, regs); DW_CHECK(effective_addr4, regs); op1c = ARCH_DEP(wfetch8)(effective_addr4 + 8, b4, regs); op2 = ARCH_DEP(vfetch8)(effective_addr2, b2, regs); if(op1c == op2) { op1r = ARCH_DEP(wfetch8)(effective_addr4 + 24, b4, regs); op3 = ARCH_DEP(wfetch8)(effective_addr4 + 56, b4, regs); op5 = ARCH_DEP(wfetch8)(effective_addr4 + 88, b4, regs); op7 = ARCH_DEP(wfetch8)(effective_addr4 + 120, b4, regs); /* Verify access to 2nd operand */ ARCH_DEP(validate_operand) (effective_addr2, b2, 8-1, ACCTYPE_WRITE_SKP, regs); /* When in ar mode, ar3 is used to access the operand. The alet is fetched from the pl */ if(!REAL_MODE(®s->psw) && ACCESS_REGISTER_MODE(®s->psw)) { if(r3 == 0) ARCH_DEP(program_interrupt)(regs, PGM_SPECIFICATION_EXCEPTION); op4alet = ARCH_DEP(wfetch4)(effective_addr4 + 68, b4, regs); op6alet = ARCH_DEP(wfetch4)(effective_addr4 + 100, b4, regs); op8alet = ARCH_DEP(wfetch4)(effective_addr4 + 132, b4, regs); regs->AR(r3) = op8alet; SET_AEA_AR(regs, r3); } /* Load address of operand 4 */ #if defined(FEATURE_ESAME) op4addr = ARCH_DEP(wfetch8)(effective_addr4 + 72, b4, regs); #else op4addr = ARCH_DEP(wfetch4)(effective_addr4 + 76, b4, regs); #endif op4addr &= ADDRESS_MAXWRAP(regs); DW_CHECK(op4addr, regs); /* Load address of operand 6 */ #if defined(FEATURE_ESAME) op6addr = ARCH_DEP(wfetch8)(effective_addr4 + 104, b4, regs); #else op6addr = ARCH_DEP(wfetch4)(effective_addr4 + 108, b4, regs); #endif op6addr &= ADDRESS_MAXWRAP(regs); DW_CHECK(op6addr, regs); /* Load address of operand 8 */ #if defined(FEATURE_ESAME) op8addr = ARCH_DEP(wfetch8)(effective_addr4 + 136, b4, regs); #else op8addr = ARCH_DEP(wfetch4)(effective_addr4 + 140, b4, regs); #endif op8addr &= ADDRESS_MAXWRAP(regs); DW_CHECK(op8addr, regs); /* Verify access to 8th operand */ ARCH_DEP(validate_operand) (op8addr, r3, 8-1,ACCTYPE_WRITE_SKP, regs); /* Verify access to 6th operand */ if(!REAL_MODE(®s->psw) && ACCESS_REGISTER_MODE(®s->psw)) { regs->AR(r3) = op6alet; SET_AEA_AR(regs, r3); } ARCH_DEP(validate_operand) (op6addr, r3, 8-1,ACCTYPE_WRITE_SKP, regs); /* Store 3th op at 4th op */ if(!REAL_MODE(®s->psw) && ACCESS_REGISTER_MODE(®s->psw)) { regs->AR(r3) = op4alet; SET_AEA_AR(regs, r3); } ARCH_DEP(vstore8)(op3, op4addr, r3, regs); /* Store 5th op at 6th op */ if(!REAL_MODE(®s->psw) && ACCESS_REGISTER_MODE(®s->psw)) { regs->AR(r3) = op6alet; SET_AEA_AR(regs, r3); } ARCH_DEP(vstore8)(op5, op6addr, r3, regs); /* Store 7th op at 8th op */ if(!REAL_MODE(®s->psw) && ACCESS_REGISTER_MODE(®s->psw)) { regs->AR(r3) = op8alet; SET_AEA_AR(regs, r3); } ARCH_DEP(vstore8)(op7, op8addr, r3, regs); /* Store 1st op replacement value at 2nd op */ ARCH_DEP(vstore8)(op1r, effective_addr2, b2, regs); return 0; } else { ARCH_DEP(wstore8)(op2, effective_addr4 + 8, b4, regs); return 1; } } #if defined(FEATURE_ESAME) int ARCH_DEP(plo_cststgr) (int r1, int r3, VADR effective_addr2, int b2, VADR effective_addr4, int b4, REGS *regs) { U64 op2, op3, op5, op7; U32 op4alet = 0, op6alet = 0, op8alet = 0; VADR op4addr, op6addr, op8addr; ODD_CHECK(r1, regs); DW_CHECK(effective_addr2, regs); DW_CHECK(effective_addr4, regs); op2 = ARCH_DEP(vfetch8)(effective_addr2, b2, regs); if(regs->GR_G(r1) == op2) { op3 = ARCH_DEP(wfetch8)(effective_addr4 + 56, b4, regs); op5 = ARCH_DEP(wfetch8)(effective_addr4 + 88, b4, regs); op7 = ARCH_DEP(wfetch8)(effective_addr4 + 120, b4, regs); /* Verify access to 2nd operand */ ARCH_DEP(validate_operand) (effective_addr2, b2, 8-1, ACCTYPE_WRITE_SKP, regs); /* When in ar mode, ar3 is used to access the operand. The alet is fetched from the pl */ if(!REAL_MODE(®s->psw) && ACCESS_REGISTER_MODE(®s->psw)) { if(r3 == 0) ARCH_DEP(program_interrupt)(regs, PGM_SPECIFICATION_EXCEPTION); op4alet = ARCH_DEP(wfetch4)(effective_addr4 + 68, b4, regs); op6alet = ARCH_DEP(wfetch4)(effective_addr4 + 100, b4, regs); op8alet = ARCH_DEP(wfetch4)(effective_addr4 + 132, b4, regs); regs->AR(r3) = op8alet; SET_AEA_AR(regs, r3); } /* Load address of operand 4 */ op4addr = ARCH_DEP(wfetch8)(effective_addr4 + 72, b4, regs); op4addr &= ADDRESS_MAXWRAP(regs); DW_CHECK(op4addr, regs); /* Load address of operand 6 */ op6addr = ARCH_DEP(wfetch8)(effective_addr4 + 104, b4, regs); op6addr &= ADDRESS_MAXWRAP(regs); DW_CHECK(op6addr, regs); /* Load address of operand 8 */ op8addr = ARCH_DEP(wfetch8)(effective_addr4 + 136, b4, regs); op8addr &= ADDRESS_MAXWRAP(regs); DW_CHECK(op8addr, regs); /* Verify access to 8th operand */ ARCH_DEP(validate_operand) (op8addr, r3, 8-1,ACCTYPE_WRITE_SKP, regs); /* Verify access to 6th operand */ if(!REAL_MODE(®s->psw) && ACCESS_REGISTER_MODE(®s->psw)) { regs->AR(r3) = op6alet; SET_AEA_AR(regs, r3); } ARCH_DEP(validate_operand) (op6addr, r3, 8-1,ACCTYPE_WRITE_SKP, regs); /* Store 3rd op at 4th op */ if(!REAL_MODE(®s->psw) && ACCESS_REGISTER_MODE(®s->psw)) { regs->AR(r3) = op4alet; SET_AEA_AR(regs, r3); } ARCH_DEP(vstore8)(op3, op4addr, r3, regs); /* Store 5th op at 6th op */ if(!REAL_MODE(®s->psw) && ACCESS_REGISTER_MODE(®s->psw)) { regs->AR(r3) = op6alet; SET_AEA_AR(regs, r3); } ARCH_DEP(vstore8)(op5, op6addr, r3, regs); /* Store 7th op at 8th op */ if(!REAL_MODE(®s->psw) && ACCESS_REGISTER_MODE(®s->psw)) { regs->AR(r3) = op8alet; SET_AEA_AR(regs, r3); } ARCH_DEP(vstore8)(op7, op8addr, r3, regs); /* Store 1st op replacement at 2nd op */ ARCH_DEP(vstore8)(regs->GR_G(r1+1), effective_addr2, b2, regs); return 0; } else { regs->GR_G(r1) = op2; return 1; } } #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ESAME) int ARCH_DEP(plo_cststx) (int r1, int r3, VADR effective_addr2, int b2, VADR effective_addr4, int b4, REGS *regs) { BYTE op1c[16], op1r[16], op2[16], op3[16], op5[16], op7[16]; U32 op4alet = 0, op6alet = 0, op8alet = 0; VADR op4addr, op6addr, op8addr; UNREFERENCED(r1); QW_CHECK(effective_addr2, regs); DW_CHECK(effective_addr4, regs); ARCH_DEP(vfetchc)(op1c, 16-1, effective_addr4 + 0, b4, regs); ARCH_DEP(vfetchc)(op2, 16-1, effective_addr2, b2, regs); if(memcmp(op1c,op2,16) == 0) { ARCH_DEP(wfetchc)(op1r, 16-1, effective_addr4 + 16, b4, regs); ARCH_DEP(wfetchc)(op3, 16-1, effective_addr4 + 48, b4, regs); ARCH_DEP(wfetchc)(op5, 16-1, effective_addr4 + 80, b4, regs); ARCH_DEP(wfetchc)(op7, 16-1, effective_addr4 + 112, b4, regs); /* Verify access to 2nd operand */ ARCH_DEP(validate_operand) (effective_addr2, b2, 16-1, ACCTYPE_WRITE_SKP, regs); /* When in ar mode, ar3 is used to access the operand. The alet is fetched from the pl */ if(!REAL_MODE(®s->psw) && ACCESS_REGISTER_MODE(®s->psw)) { if(r3 == 0) ARCH_DEP(program_interrupt)(regs, PGM_SPECIFICATION_EXCEPTION); op4alet = ARCH_DEP(wfetch4)(effective_addr4 + 68, b4, regs); op6alet = ARCH_DEP(wfetch4)(effective_addr4 + 100, b4, regs); op8alet = ARCH_DEP(wfetch4)(effective_addr4 + 132, b4, regs); regs->AR(r3) = op8alet; SET_AEA_AR(regs, r3); } /* Load address of operand 4 */ op4addr = ARCH_DEP(wfetch8)(effective_addr4 + 72, b4, regs); op4addr &= ADDRESS_MAXWRAP(regs); QW_CHECK(op4addr, regs); /* Load address of operand 6 */ op6addr = ARCH_DEP(wfetch8)(effective_addr4 + 104, b4, regs); op6addr &= ADDRESS_MAXWRAP(regs); QW_CHECK(op6addr, regs); /* Load address of operand 8 */ op8addr = ARCH_DEP(wfetch8)(effective_addr4 + 136, b4, regs); op8addr &= ADDRESS_MAXWRAP(regs); QW_CHECK(op8addr, regs); /* Verify access to 8th operand */ ARCH_DEP(validate_operand) (op8addr, r3, 16-1,ACCTYPE_WRITE_SKP, regs); /* Verify access to 6th operand */ if(!REAL_MODE(®s->psw) && ACCESS_REGISTER_MODE(®s->psw)) { regs->AR(r3) = op6alet; SET_AEA_AR(regs, r3); } ARCH_DEP(validate_operand) (op6addr, r3, 16-1, ACCTYPE_WRITE_SKP, regs); /* Store 3th op at 4th op */ if(!REAL_MODE(®s->psw) && ACCESS_REGISTER_MODE(®s->psw)) { regs->AR(r3) = op4alet; SET_AEA_AR(regs, r3); } ARCH_DEP(vstorec)(op3, 16-1, op4addr, r3, regs); /* Store 5th op at 6th op */ if(!REAL_MODE(®s->psw) && ACCESS_REGISTER_MODE(®s->psw)) { regs->AR(r3) = op6alet; SET_AEA_AR(regs, r3); } ARCH_DEP(vstorec)(op5, 16-1, op6addr, r3, regs); /* Store 7th op at 8th op */ if(!REAL_MODE(®s->psw) && ACCESS_REGISTER_MODE(®s->psw)) { regs->AR(r3) = op8alet; SET_AEA_AR(regs, r3); } ARCH_DEP(vstorec)(op7, 16-1, op8addr, r3, regs); /* Store 1st op replacement value at 2nd op */ ARCH_DEP(vstorec)(op1r, 16-1, effective_addr2, b2, regs); return 0; } else { ARCH_DEP(vstorec)(op2, 16-1, effective_addr4 + 0, b4, regs); return 1; } } #endif /*defined(FEATURE_ESAME)*/ #endif /*defined(FEATURE_PERFORM_LOCKED_OPERATION)*/ #if !defined(_GEN_ARCH) #if defined(_ARCHMODE2) #define _GEN_ARCH _ARCHMODE2 #include "plo.c" #endif #if defined(_ARCHMODE3) #undef _GEN_ARCH #define _GEN_ARCH _ARCHMODE3 #include "plo.c" #endif #endif /*!defined(_GEN_ARCH)*/ hercules-3.07/po/000777 000765 000765 00000000000 11345533275 015375 5ustar00jmaynardjmaynard000000 000000 hercules-3.07/printer.c000644 000765 000765 00000105077 11301535255 016604 0ustar00jmaynardjmaynard000000 000000 /* PRINTER.C (c) Copyright Roger Bowler, 1999-2009 */ /* ESA/390 Line Printer Device Handler */ // $Id: printer.c 5487 2009-10-14 04:43:58Z fish $ /*-------------------------------------------------------------------*/ /* This module contains device handling functions for emulated */ /* System/370 line printer devices. */ /*-------------------------------------------------------------------*/ #include "hstdinc.h" #include "hercules.h" #include "devtype.h" #include "opcode.h" /*-------------------------------------------------------------------*/ /* Ivan Warren 20040227 */ /* This table is used by channel.c to determine if a CCW code is an */ /* immediate command or not */ /* The tape is addressed in the DEVHND structure as 'DEVIMM immed' */ /* 0 : Command is NOT an immediate command */ /* 1 : Command is an immediate command */ /* Note : An immediate command is defined as a command which returns */ /* CE (channel end) during initialisation (that is, no data is */ /* actually transfered. In this case, IL is not indicated for a CCW */ /* Format 0 or for a CCW Format 1 when IL Suppression Mode is in */ /* effect */ /*-------------------------------------------------------------------*/ /* Printer Specific : 1403 */ /* The following are considered IMMEDIATE commands : */ /* CTL-NOOP, Skip Channel 'n' Immediate, Block Data check , Allow Data Check * Space 1,2,3 Lines Immediate, UCS Gate Load, Load UCS Buffer & Fold, * Load UCS Buffer (No Fold) */ static BYTE printer_immed_commands[256]= /* *0 1 2 3 4 5 6 7 8 9 A B C D E F */ { 0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0}; /*-------------------------------------------------------------------*/ /* Internal macro definitions */ /*-------------------------------------------------------------------*/ #define LINE_LENGTH 150 static void* spthread (DEVBLK* dev); /* (forward reference) */ /*-------------------------------------------------------------------*/ /* Sockdev "OnConnection" callback function */ /*-------------------------------------------------------------------*/ static int onconnect_callback (DEVBLK* dev) { TID tid; if (create_thread( &tid, DETACHED, spthread, dev, NULL )) { logmsg( _( "HHCPR015E Create spthread failed for %4.4X: errno=%d: %s\n" ), dev->devnum, errno, strerror( errno ) ); return 0; } return 1; } /*-------------------------------------------------------------------*/ /* Thread to monitor the sockdev remote print spooler connection */ /*-------------------------------------------------------------------*/ static void* spthread (DEVBLK* dev) { BYTE byte; fd_set readset, errorset; struct timeval tv; int rc, fd = dev->fd; // (save original fd) /* Fix thread name */ { char thread_name[32]; thread_name[sizeof(thread_name)-1] = 0; snprintf( thread_name, sizeof(thread_name)-1, "spthread %4.4X", dev->devnum ); SET_THREAD_NAME( thread_name ); } // Looooop... until shutdown or disconnect... // PROGRAMMING NOTE: we do our select specifying an immediate // timeout to prevent our select from holding up (slowing down) // the device thread (which does the actual writing of data to // the client). The only purpose for our thread even existing // is to detect a severed connection (i.e. to detect when the // client disconnects)... while ( !sysblk.shutdown && dev->fd == fd ) { if (dev->busy) { SLEEP(3); continue; } FD_ZERO( &readset ); FD_ZERO( &errorset ); FD_SET( fd, &readset ); FD_SET( fd, &errorset ); tv.tv_sec = 0; tv.tv_usec = 0; rc = select( fd+1, &readset, NULL, &errorset, &tv ); if (rc < 0) break; if (rc == 0) { SLEEP(3); continue; } if (FD_ISSET( fd, &errorset )) break; // Read and ignore any data they send us... // Note: recv should complete immediately // as we know data is waiting to be read. ASSERT( FD_ISSET( fd, &readset ) ); rc = recv( fd, &byte, sizeof(byte), 0 ); if (rc <= 0) break; } obtain_lock( &dev->lock ); // PROGRAMMING NOTE: the following tells us whether we detected // the error or if the device thread already did. If the device // thread detected it while we were sleeping (and subsequently // closed the connection) then we don't need to do anything at // all; just exit. If we were the ones that detected the error // however, then we need to close the connection so the device // thread can learn of it... if (dev->fd == fd) { dev->fd = -1; close_socket( fd ); logmsg (_("HHCPR016I %s (%s) disconnected from device %4.4X (%s)\n"), dev->bs->clientname, dev->bs->clientip, dev->devnum, dev->bs->spec); } release_lock( &dev->lock ); return NULL; } /* end function spthread */ /*-------------------------------------------------------------------*/ /* Subroutine to open the printer file or pipe */ /*-------------------------------------------------------------------*/ static int open_printer (DEVBLK *dev) { pid_t pid; /* Child process identifier */ char pathname[MAX_PATH]; /* file path in host format */ int open_flags; /* File open flags */ #if !defined( _MSVC_ ) int pipefd[2]; /* Pipe descriptors */ int rc; /* Return code */ #endif /* Regular open if 1st char of filename is not vertical bar */ if (!dev->ispiped) { int fd; /* Socket printer? */ if (dev->bs) return (dev->fd < 0 ? -1 : 0); /* Normal printer */ hostpath(pathname, dev->filename, sizeof(pathname)); open_flags = O_BINARY | O_WRONLY | O_CREAT /* | O_SYNC */; if (dev->notrunc != 1) { open_flags |= O_TRUNC; } fd = open (pathname, open_flags, S_IRUSR | S_IWUSR | S_IRGRP); if (fd < 0) { logmsg (_("HHCPR004E Error opening file %s: %s\n"), dev->filename, strerror(errno)); return -1; } /* Save file descriptor in device block and return */ dev->fd = fd; return 0; } /* Filename is in format |xxx, set up pipe to program xxx */ #if defined( _MSVC_ ) /* "Poor man's" fork... */ pid = w32_poor_mans_fork ( dev->filename+1, &dev->fd ); if (pid < 0) { logmsg (_("HHCPR006E %4.4X device initialization error: fork: %s\n"), dev->devnum, strerror(errno)); return -1; } /* Log start of child process */ logmsg (_("HHCPR007I pipe receiver (pid=%d) starting for %4.4X\n"), pid, dev->devnum); dev->ptpcpid = pid; #else /* !defined( _MSVC_ ) */ /* Create a pipe */ rc = create_pipe (pipefd); if (rc < 0) { logmsg (_("HHCPR005E %4.4X device initialization error: pipe: %s\n"), dev->devnum, strerror(errno)); return -1; } /* Fork a child process to receive the pipe data */ pid = fork(); if (pid < 0) { logmsg (_("HHCPR006E %4.4X device initialization error: fork: %s\n"), dev->devnum, strerror(errno)); close_pipe ( pipefd[0] ); close_pipe ( pipefd[1] ); return -1; } /* The child process executes the pipe receiver program... */ if (pid == 0) { /* Log start of child process */ logmsg (_("HHCPR007I pipe receiver (pid=%d) starting for %4.4X\n"), getpid(), dev->devnum); /* Close the write end of the pipe */ close_pipe ( pipefd[1] ); /* Duplicate the read end of the pipe onto STDIN */ if (pipefd[0] != STDIN_FILENO) { rc = dup2 (pipefd[0], STDIN_FILENO); if (rc != STDIN_FILENO) { logmsg (_("HHCPR008E %4.4X dup2 error: %s\n"), dev->devnum, strerror(errno)); close_pipe ( pipefd[0] ); _exit(127); } } /* end if(pipefd[0] != STDIN_FILENO) */ /* Close the original descriptor now duplicated to STDIN */ close_pipe ( pipefd[0] ); /* Redirect stderr (screen) to hercules log task */ dup2(STDOUT_FILENO, STDERR_FILENO); /* Relinquish any ROOT authority before calling shell */ SETMODE(TERM); /* Execute the specified pipe receiver program */ rc = system (dev->filename+1); if (rc == 0) { /* Log end of child process */ logmsg (_("HHCPR011I pipe receiver (pid=%d) terminating for %4.4X\n"), getpid(), dev->devnum); } else { /* Log error */ logmsg (_("HHCPR012E %4.4X Unable to execute %s: %s\n"), dev->devnum, dev->filename+1, strerror(errno)); } /* The child process terminates using _exit instead of exit to avoid invoking the panel atexit cleanup routine */ _exit(rc); } /* end if(pid==0) */ /* The parent process continues as the pipe sender */ /* Close the read end of the pipe */ close_pipe ( pipefd[0] ); /* Save pipe write descriptor in the device block */ dev->fd = pipefd[1]; dev->ptpcpid = pid; #endif /* defined( _MSVC_ ) */ return 0; } /* end function open_printer */ /*-------------------------------------------------------------------*/ /* Subroutine to write data to the printer */ /*-------------------------------------------------------------------*/ static void write_buffer (DEVBLK *dev, char *buf, int len, BYTE *unitstat) { int rc; /* Return code */ /* Write data to the printer file */ if (dev->bs) { /* (socket printer) */ rc = write_socket (dev->fd, buf, len); /* Check for socket error */ if (rc < len) { /* Close the connection */ if (dev->fd != -1) { int fd = dev->fd; dev->fd = -1; close_socket( fd ); logmsg (_("HHCPR017I %s (%s) disconnected from device %4.4X (%s)\n"), dev->bs->clientname, dev->bs->clientip, dev->devnum, dev->bs->spec); } /* Set unit check with intervention required */ dev->sense[0] = SENSE_IR; *unitstat = CSW_CE | CSW_DE | CSW_UC; } } else { /* Write data to the printer file */ rc = write (dev->fd, buf, len); /* Equipment check if error writing to printer file */ if (rc < len) { logmsg (_("HHCPR003E %4.4X Error writing to %s: %s\n"), dev->devnum, dev->filename, (errno == 0 ? _("incomplete"): strerror(errno))); dev->sense[0] = SENSE_EC; *unitstat = CSW_CE | CSW_DE | CSW_UC; } } } /* end function write_buffer */ /*-------------------------------------------------------------------*/ /* Initialize the device handler */ /*-------------------------------------------------------------------*/ static int printer_init_handler (DEVBLK *dev, int argc, char *argv[]) { int i; /* Array subscript */ int sockdev = 0; /* 1 == is socket device */ /* Forcibly disconnect anyone already currently connected */ if (dev->bs && !unbind_device_ex(dev,1)) return -1; // (error msg already issued) /* The first argument is the file name */ if (argc == 0 || strlen(argv[0]) > sizeof(dev->filename)-1) { logmsg (_("HHCPR001E File name missing or invalid for printer %4.4X\n"), dev->devnum); return -1; } /* Save the file name in the device block */ strncpy (dev->filename, argv[0], sizeof(dev->filename)); if(!sscanf(dev->typname,"%hx",&(dev->devtype))) dev->devtype = 0x1403; /* Initialize device dependent fields */ dev->fd = -1; dev->printpos = 0; dev->printrem = LINE_LENGTH; dev->diaggate = 0; dev->fold = 0; dev->crlf = 0; dev->stopprt = 0; dev->notrunc = 0; dev->ispiped = (dev->filename[0] == '|'); /* Process the driver arguments */ for (i = 1; i < argc; i++) { if (strcasecmp(argv[i], "crlf") == 0) { dev->crlf = 1; continue; } /* sockdev means the device file is actually a connected socket instead of a disk file. The file name is the socket_spec (host:port) to listen for connections on. */ if (!dev->ispiped && strcasecmp(argv[i], "sockdev") == 0) { sockdev = 1; continue; } if (strcasecmp(argv[i], "noclear") == 0) { dev->notrunc = 1; continue; } logmsg (_("HHCPR002E Invalid argument for printer %4.4X: %s\n"), dev->devnum, argv[i]); return -1; } /* Check for incompatible options */ if (sockdev && dev->crlf) { logmsg (_("HHCPR019E Incompatible option specified for socket printer %4.4X: 'crlf'\n"), dev->devnum); return -1; } if (sockdev && dev->notrunc) { logmsg (_("HHCPR019E Incompatible option specified for socket printer %4.4X: 'noclear'\n"), dev->devnum); return -1; } /* If socket device, create a listening socket to accept connections on. */ if (sockdev && !bind_device_ex( dev, dev->filename, onconnect_callback, dev )) { return -1; // (error msg already issued) } /* Set length of print buffer */ dev->bufsize = LINE_LENGTH + 8; /* Set number of sense bytes */ dev->numsense = 1; /* Initialize the device identifier bytes */ dev->devid[0] = 0xFF; dev->devid[1] = 0x28; /* Control unit type is 2821-1 */ dev->devid[2] = 0x21; dev->devid[3] = 0x01; dev->devid[4] = dev->devtype >> 8; dev->devid[5] = dev->devtype & 0xFF; dev->devid[6] = 0x01; dev->numdevid = 7; /* Activate I/O tracing */ // dev->ccwtrace = 1; return 0; } /* end function printer_init_handler */ /*-------------------------------------------------------------------*/ /* Query the device definition */ /*-------------------------------------------------------------------*/ static void printer_query_device (DEVBLK *dev, char **class, int buflen, char *buffer) { BEGIN_DEVICE_CLASS_QUERY( "PRT", dev, class, buflen, buffer ); snprintf (buffer, buflen, "%s%s%s%s%s", dev->filename, (dev->bs ? " sockdev" : ""), (dev->crlf ? " crlf" : ""), (dev->notrunc ? " noclear" : ""), (dev->stopprt ? " (stopped)" : "")); } /* end function printer_query_device */ /*-------------------------------------------------------------------*/ /* Close the device */ /*-------------------------------------------------------------------*/ static int printer_close_device ( DEVBLK *dev ) { int fd = dev->fd; if (fd == -1) return 0; dev->fd = -1; dev->stopprt = 0; /* Close the device file */ if ( dev->ispiped ) { #if !defined( _MSVC_ ) close_pipe (fd); #else /* defined( _MSVC_ ) */ close (fd); /* Log end of child process */ logmsg (_("HHCPR011I pipe receiver (pid=%d) terminating for %4.4X\n"), dev->ptpcpid, dev->devnum); #endif /* defined( _MSVC_ ) */ dev->ptpcpid = 0; } else { if (dev->bs) { /* Socket printer */ close_socket (fd); logmsg (_("HHCPR018I %s (%s) disconnected from device %4.4X (%s)\n"), dev->bs->clientname, dev->bs->clientip, dev->devnum, dev->bs->spec); } else { /* Regular printer */ close (fd); } } return 0; } /* end function printer_close_device */ /*-------------------------------------------------------------------*/ /* Execute a Channel Command Word */ /*-------------------------------------------------------------------*/ static void printer_execute_ccw (DEVBLK *dev, BYTE code, BYTE flags, BYTE chained, U16 count, BYTE prevcode, int ccwseq, BYTE *iobuf, BYTE *more, BYTE *unitstat, U16 *residual) { int rc = 0; /* Return code */ int i; /* Loop counter */ int num; /* Number of bytes to move */ char *eor; /* -> end of record string */ BYTE c; /* Print character */ /* Reset flags at start of CCW chain */ if (chained == 0) { dev->diaggate = 0; } /* Open the device file if necessary */ if (dev->fd < 0 && !IS_CCW_SENSE(code)) rc = open_printer (dev); else { /* If printer stopped, return intervention required */ if (dev->stopprt && !IS_CCW_SENSE(code)) rc = -1; else rc = 0; } if (rc < 0) { /* Set unit check with intervention required */ dev->sense[0] = SENSE_IR; *unitstat = CSW_CE | CSW_DE | CSW_UC; return; } /* Process depending on CCW opcode */ switch (code) { case 0x01: /*---------------------------------------------------------------*/ /* WRITE WITHOUT SPACING */ /*---------------------------------------------------------------*/ eor = "\r"; goto write; case 0x09: /*---------------------------------------------------------------*/ /* WRITE AND SPACE 1 LINE */ /*---------------------------------------------------------------*/ eor = dev->crlf ? "\r\n" : "\n"; goto write; case 0x11: /*---------------------------------------------------------------*/ /* WRITE AND SPACE 2 LINES */ /*---------------------------------------------------------------*/ eor = dev->crlf ? "\r\n\n" : "\n\n"; goto write; case 0x19: /*---------------------------------------------------------------*/ /* WRITE AND SPACE 3 LINES */ /*---------------------------------------------------------------*/ eor = dev->crlf ? "\r\n\n\n" : "\n\n\n"; goto write; case 0x89: /*---------------------------------------------------------------*/ /* WRITE AND SKIP TO CHANNEL 1 */ /*---------------------------------------------------------------*/ eor = dev->crlf ? "\r\f" : "\f"; goto write; case 0xC9: /*---------------------------------------------------------------*/ /* WRITE AND SKIP TO CHANNEL 9 */ /*---------------------------------------------------------------*/ eor = dev->crlf ? "\r\n" : "\n"; goto write; case 0xE1: /*---------------------------------------------------------------*/ /* WRITE AND SKIP TO CHANNEL 12 */ /*---------------------------------------------------------------*/ eor = dev->crlf ? "\r\n" : "\n"; goto write; write: /* Start a new record if not data-chained from previous CCW */ if ((chained & CCW_FLAGS_CD) == 0) { dev->printpos = 0; dev->printrem = LINE_LENGTH; } /* end if(!data-chained) */ /* Calculate number of bytes to write and set residual count */ num = (count < dev->printrem) ? count : dev->printrem; *residual = count - num; /* Copy data from channel buffer to print buffer */ for (i = 0; i < num; i++) { c = guest_to_host(iobuf[i]); if (dev->fold) c = toupper(c); if (c == 0) c = SPACE; dev->buf[dev->printpos] = c; dev->printpos++; dev->printrem--; } /* end for(i) */ /* Perform end of record processing if not data-chaining */ if ((flags & CCW_FLAGS_CD) == 0) { /* Truncate trailing blanks from print line */ for (i = dev->printpos; i > 0; i--) if (dev->buf[i-1] != SPACE) break; /* Append carriage return and line feed(s) */ strcpy ((char *)(dev->buf + i), eor); i += strlen(eor); /* Write print line */ write_buffer (dev, (char *)dev->buf, i, unitstat); if (*unitstat != 0) break; } /* end if(!data-chaining) */ /* Return normal status */ *unitstat = CSW_CE | CSW_DE; break; case 0x03: /*---------------------------------------------------------------*/ /* CONTROL NO-OPERATION */ /*---------------------------------------------------------------*/ *unitstat = CSW_CE | CSW_DE; break; case 0x06: /*---------------------------------------------------------------*/ /* DIAGNOSTIC CHECK READ */ /*---------------------------------------------------------------*/ /* If not 1403, reject if not preceded by DIAGNOSTIC GATE */ if (dev->devtype != 0x1403 && dev->diaggate == 0) { dev->sense[0] = SENSE_CR; *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Return normal status */ *unitstat = CSW_CE | CSW_DE; break; case 0x07: /*---------------------------------------------------------------*/ /* DIAGNOSTIC GATE */ /*---------------------------------------------------------------*/ /* Command reject if 1403, or if chained to another CCW except a no-operation at the start of the CCW chain */ if (dev->devtype == 1403 || ccwseq > 1 || (chained && prevcode != 0x03)) { dev->sense[0] = SENSE_CR; *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Set diagnostic gate flag */ dev->diaggate = 1; /* Return normal status */ *unitstat = CSW_CE | CSW_DE; break; case 0x0A: /*---------------------------------------------------------------*/ /* DIAGNOSTIC READ UCS BUFFER */ /*---------------------------------------------------------------*/ /* Reject if 1403 or not preceded by DIAGNOSTIC GATE */ if (dev->devtype == 0x1403 || dev->diaggate == 0) { dev->sense[0] = SENSE_CR; *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Return normal status */ *unitstat = CSW_CE | CSW_DE; break; case 0x12: /*---------------------------------------------------------------*/ /* DIAGNOSTIC READ FCB */ /*---------------------------------------------------------------*/ /* Reject if 1403 or not preceded by DIAGNOSTIC GATE */ if (dev->devtype == 0x1403 || dev->diaggate == 0) { dev->sense[0] = SENSE_CR; *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Return normal status */ *unitstat = CSW_CE | CSW_DE; break; case 0x0B: /*---------------------------------------------------------------*/ /* SPACE 1 LINE IMMEDIATE */ /*---------------------------------------------------------------*/ eor = dev->crlf ? "\r\n" : "\n"; write_buffer (dev, eor, strlen(eor), unitstat); if (*unitstat != 0) break; /* *residual = 0; */ *unitstat = CSW_CE | CSW_DE; break; case 0x13: /*---------------------------------------------------------------*/ /* SPACE 2 LINES IMMEDIATE */ /*---------------------------------------------------------------*/ eor = dev->crlf ? "\r\n\n" : "\n\n"; write_buffer (dev, eor, strlen(eor), unitstat); if (*unitstat != 0) break; /* *residual = 0; */ *unitstat = CSW_CE | CSW_DE; break; case 0x1B: /*---------------------------------------------------------------*/ /* SPACE 3 LINES IMMEDIATE */ /*---------------------------------------------------------------*/ eor = dev->crlf ? "\r\n\n\n" : "\n\n\n"; write_buffer (dev, eor, strlen(eor), unitstat); if (*unitstat != 0) break; /* *residual = 0; */ *unitstat = CSW_CE | CSW_DE; break; case 0x23: /*---------------------------------------------------------------*/ /* UNFOLD */ /*---------------------------------------------------------------*/ dev->fold = 0; *unitstat = CSW_CE | CSW_DE; break; case 0x43: /*---------------------------------------------------------------*/ /* FOLD */ /*---------------------------------------------------------------*/ dev->fold = 1; *unitstat = CSW_CE | CSW_DE; break; case 0x73: /*---------------------------------------------------------------*/ /* BLOCK DATA CHECK */ /*---------------------------------------------------------------*/ /* *residual = 0; */ *unitstat = CSW_CE | CSW_DE; break; case 0x7B: /*---------------------------------------------------------------*/ /* ALLOW DATA CHECK */ /*---------------------------------------------------------------*/ /* *residual = 0; */ *unitstat = CSW_CE | CSW_DE; break; case 0x8B: /*---------------------------------------------------------------*/ /* SKIP TO CHANNEL 1 IMMEDIATE */ /*---------------------------------------------------------------*/ eor = dev->crlf ? "\r\f" : "\f"; write_buffer (dev, eor, strlen(eor), unitstat); if (*unitstat != 0) break; /* *residual = 0; */ *unitstat = CSW_CE | CSW_DE; break; case 0xCB: /*---------------------------------------------------------------*/ /* SKIP TO CHANNEL 9 IMMEDIATE */ /*---------------------------------------------------------------*/ eor = dev->crlf ? "\r\n" : "\n"; write_buffer (dev, eor, strlen(eor), unitstat); if (*unitstat != 0) break; /* *residual = 0; */ *unitstat = CSW_CE | CSW_DE; break; case 0xE3: case 0xDB: /*---------------------------------------------------------------*/ /* SKIP TO CHANNEL 12 IMMEDIATE (or 11) */ /*---------------------------------------------------------------*/ eor = dev->crlf ? "\r\n" : "\n"; write_buffer (dev, eor, strlen(eor), unitstat); if (*unitstat != 0) break; /* *residual = 0; */ *unitstat = CSW_CE | CSW_DE; break; case 0x63: /*---------------------------------------------------------------*/ /* LOAD FORMS CONTROL BUFFER */ /*---------------------------------------------------------------*/ /* Return normal status */ *residual = 0; *unitstat = CSW_CE | CSW_DE; break; case 0xEB: /*---------------------------------------------------------------*/ /* UCS GATE LOAD */ /*---------------------------------------------------------------*/ /* Command reject if not first command in chain */ if (chained != 0) { dev->sense[0] = SENSE_CR; *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Return normal status */ *unitstat = CSW_CE | CSW_DE; break; case 0xF3: /*---------------------------------------------------------------*/ /* LOAD UCS BUFFER AND FOLD */ /*---------------------------------------------------------------*/ /* For 1403, command reject if not chained to UCS GATE */ /* Also allow ALLOW DATA CHECK to get TSS/370 working */ /* -- JRM 11/28/2007 */ if (dev->devtype == 0x1403 && ((prevcode != 0xEB) && (prevcode != 0x7B))) { dev->sense[0] = SENSE_CR; *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Set fold indicator and return normal status */ dev->fold = 1; /* *residual = 0; */ *unitstat = CSW_CE | CSW_DE; break; case 0xFB: /*---------------------------------------------------------------*/ /* LOAD UCS BUFFER (NO FOLD) */ /*---------------------------------------------------------------*/ /* For 1403, command reject if not chained to UCS GATE */ if (dev->devtype == 0x1403 && prevcode != 0xEB) { dev->sense[0] = SENSE_CR; *unitstat = CSW_CE | CSW_DE | CSW_UC; break; } /* Reset fold indicator and return normal status */ dev->fold = 0; /* *residual = 0; */ *unitstat = CSW_CE | CSW_DE; break; case 0x04: /*---------------------------------------------------------------*/ /* SENSE */ /*---------------------------------------------------------------*/ /* Calculate residual byte count */ num = (count < dev->numsense) ? count : dev->numsense; *residual = count - num; if (count < dev->numsense) *more = 1; /* Copy device sense bytes to channel I/O buffer */ memcpy (iobuf, dev->sense, num); /* Clear the device sense bytes */ memset (dev->sense, 0, sizeof(dev->sense)); /* Return unit status */ *unitstat = CSW_CE | CSW_DE; break; case 0xE4: /*---------------------------------------------------------------*/ /* SENSE ID */ /*---------------------------------------------------------------*/ /* Calculate residual byte count */ num = (count < dev->numdevid) ? count : dev->numdevid; *residual = count - num; if (count < dev->numdevid) *more = 1; /* Copy device identifier bytes to channel I/O buffer */ memcpy (iobuf, dev->devid, num); /* Return unit status */ *unitstat = CSW_CE | CSW_DE; break; default: /*---------------------------------------------------------------*/ /* INVALID OPERATION */ /*---------------------------------------------------------------*/ /* Set command reject sense byte, and unit check status */ dev->sense[0] = SENSE_CR; *unitstat = CSW_CE | CSW_DE | CSW_UC; } /* end switch(code) */ } /* end function printer_execute_ccw */ #if defined(OPTION_DYNAMIC_LOAD) static #endif DEVHND printer_device_hndinfo = { &printer_init_handler, /* Device Initialisation */ &printer_execute_ccw, /* Device CCW execute */ &printer_close_device, /* Device Close */ &printer_query_device, /* Device Query */ NULL, /* Device Start channel pgm */ NULL, /* Device End channel pgm */ NULL, /* Device Resume channel pgm */ NULL, /* Device Suspend channel pgm */ NULL, /* Device Read */ NULL, /* Device Write */ NULL, /* Device Query used */ NULL, /* Device Reserve */ NULL, /* Device Release */ NULL, /* Device Attention */ printer_immed_commands, /* Immediate CCW Codes */ NULL, /* Signal Adapter Input */ NULL, /* Signal Adapter Output */ NULL, /* Hercules suspend */ NULL /* Hercules resume */ }; /* Libtool static name colision resolution */ /* note : lt_dlopen will look for symbol & modulename_LTX_symbol */ #if !defined(HDL_BUILD_SHARED) && defined(HDL_USE_LIBTOOL) #define hdl_ddev hdt1403_LTX_hdl_ddev #define hdl_depc hdt1403_LTX_hdl_depc #define hdl_reso hdt1403_LTX_hdl_reso #define hdl_init hdt1403_LTX_hdl_init #define hdl_fini hdt1403_LTX_hdl_fini #endif #if defined(OPTION_DYNAMIC_LOAD) HDL_DEPENDENCY_SECTION; { HDL_DEPENDENCY(HERCULES); HDL_DEPENDENCY(DEVBLK); } END_DEPENDENCY_SECTION HDL_DEVICE_SECTION; { HDL_DEVICE(1403, printer_device_hndinfo ); HDL_DEVICE(3211, printer_device_hndinfo ); } END_DEVICE_SECTION #endif hercules-3.07/pttrace.c000644 000765 000765 00000046711 11321734033 016557 0ustar00jmaynardjmaynard000000 000000 /* PTTRACE.C (c) Copyright Greg Smith, 2003-2009 */ /* pthreads trace debugger */ // $Id: pttrace.c 5599 2010-01-07 15:09:20Z rbowler $ /*-------------------------------------------------------------------*/ /* Trace threading calls */ /*-------------------------------------------------------------------*/ #include "hstdinc.h" #define _PTTRACE_C_ #define _HUTIL_DLL_ #include "hercules.h" #ifdef OPTION_PTTRACE PTT_TRACE *pttrace; /* Pthreads trace table */ int pttracex; /* Pthreads trace index */ int pttracen; /* Pthreads trace entries */ LOCK pttlock; /* Pthreads trace lock */ int pttnolock; /* 1=no PTT locking */ int pttnotod; /* 1=don't call gettimeofday */ int pttnowrap; /* 1=don't wrap */ int pttto; /* timeout in seconds */ TID ptttotid; /* timeout thread id */ LOCK ptttolock; /* timeout thread lock */ COND ptttocond; /* timeout thread condition */ DLL_EXPORT void ptt_trace_init (int n, int init) { if (n > 0) pttrace = calloc (n, PTT_TRACE_SIZE); else pttrace = NULL; if (pttrace) pttracen = n; else pttracen = 0; pttracex = 0; if (init) { #if defined(OPTION_FTHREADS) fthread_mutex_init (&pttlock, NULL); #else pthread_mutex_init (&pttlock, NULL); #endif pttnolock = 0; pttnotod = 0; pttnowrap = 0; pttto = 0; ptttotid = 0; #if defined(OPTION_FTHREADS) fthread_mutex_init (&ptttolock, NULL); #if defined(FISH_HANG) fthread_cond_init (__FILE__, __LINE__, &ptttocond); #else fthread_cond_init (&ptttocond); #endif #else pthread_mutex_init (&ptttolock, NULL); pthread_cond_init (&ptttocond, NULL); #endif } } DLL_EXPORT int ptt_cmd(int argc, char *argv[], char* cmdline) { int rc = 0; int n, to = -1; char c; UNREFERENCED(cmdline); if (argc > 1) { /* process arguments; last arg can be trace table size */ for (--argc, argv++; argc; --argc, ++argv) { if (strcasecmp("opts", argv[0]) == 0) continue; else if (strcasecmp("error", argv[0]) == 0) { pttclass |= PTT_CL_ERR; continue; } else if (strcasecmp("noerror", argv[0]) == 0) { pttclass &= ~PTT_CL_ERR; continue; } else if (strcasecmp("control", argv[0]) == 0) { pttclass |= PTT_CL_INF; continue; } else if (strcasecmp("nocontrol", argv[0]) == 0) { pttclass &= ~PTT_CL_INF; continue; } else if (strcasecmp("prog", argv[0]) == 0) { pttclass |= PTT_CL_PGM; continue; } else if (strcasecmp("noprog", argv[0]) == 0) { pttclass &= ~PTT_CL_PGM; continue; } else if (strcasecmp("inter", argv[0]) == 0) { pttclass |= PTT_CL_CSF; continue; } else if (strcasecmp("nointer", argv[0]) == 0) { pttclass &= ~PTT_CL_CSF; continue; } else if (strcasecmp("sie", argv[0]) == 0) { pttclass |= PTT_CL_SIE; continue; } else if (strcasecmp("nosie", argv[0]) == 0) { pttclass &= ~PTT_CL_SIE; continue; } else if (strcasecmp("signal", argv[0]) == 0) { pttclass |= PTT_CL_SIG; continue; } else if (strcasecmp("nosignal", argv[0]) == 0) { pttclass &= ~PTT_CL_SIG; continue; } else if (strcasecmp("io", argv[0]) == 0) { pttclass |= PTT_CL_IO; continue; } else if (strcasecmp("noio", argv[0]) == 0) { pttclass &= ~PTT_CL_IO; continue; } else if (strcasecmp("timer", argv[0]) == 0) { pttclass |= PTT_CL_TMR; continue; } else if (strcasecmp("notimer", argv[0]) == 0) { pttclass &= ~PTT_CL_TMR; continue; } else if (strcasecmp("logger", argv[0]) == 0) { pttclass |= PTT_CL_LOG; continue; } else if (strcasecmp("nologger", argv[0]) == 0) { pttclass &= ~PTT_CL_LOG; continue; } else if (strcasecmp("nothreads", argv[0]) == 0) { pttclass &= ~PTT_CL_THR; continue; } else if (strcasecmp("threads", argv[0]) == 0) { pttclass |= PTT_CL_THR; continue; } else if (strcasecmp("nolock", argv[0]) == 0) { pttnolock = 1; continue; } else if (strcasecmp("lock", argv[0]) == 0) { pttnolock = 0; continue; } else if (strcasecmp("notod", argv[0]) == 0) { pttnotod = 1; continue; } else if (strcasecmp("tod", argv[0]) == 0) { pttnotod = 0; continue; } else if (strcasecmp("nowrap", argv[0]) == 0) { pttnowrap = 1; continue; } else if (strcasecmp("wrap", argv[0]) == 0) { pttnowrap = 0; continue; } else if (strncasecmp("to=", argv[0], 3) == 0 && strlen(argv[0]) > 3 && (sscanf(&argv[0][3], "%d%c", &to, &c) == 1 && to >= 0)) { pttto = to; continue; } else if (argc == 1 && sscanf(argv[0], "%d%c", &n, &c) == 1 && n >= 0) { OBTAIN_PTTLOCK; if (pttracen == 0) { if (pttrace != NULL) { RELEASE_PTTLOCK; logmsg( _("HHCPT002E Trace is busy\n")); return -1; } } else if (pttrace) { pttracen = 0; RELEASE_PTTLOCK; usleep(1000); OBTAIN_PTTLOCK; free (pttrace); pttrace = NULL; } ptt_trace_init (n, 0); RELEASE_PTTLOCK; } else { logmsg( _("HHCPT001E Invalid value: %s\n"), argv[0]); rc = -1; break; } } /* for each ptt argument */ /* wakeup timeout thread if to= specified */ if (to >= 0 && ptttotid) { obtain_lock (&ptttolock); ptttotid = 0; signal_condition (&ptttocond); release_lock (&ptttolock); } /* start timeout thread if positive to= specified */ if (to > 0) { obtain_lock (&ptttolock); ptttotid = 0; create_thread (&ptttotid, NULL, ptt_timeout, NULL, "ptt_timeout"); release_lock (&ptttolock); } } else { if (pttracen) rc = ptt_pthread_print(); logmsg( _("HHCPT003I ptt %s%s%s%s%s%s%s%s%s%s%s %s %s to=%d %d\n"), (pttclass & PTT_CL_INF) ? "control " : "", (pttclass & PTT_CL_ERR) ? "error " : "", (pttclass & PTT_CL_PGM) ? "prog " : "", (pttclass & PTT_CL_CSF) ? "inter " : "", (pttclass & PTT_CL_SIE) ? "sie " : "", (pttclass & PTT_CL_SIG) ? "signal " : "", (pttclass & PTT_CL_IO) ? "io " : "", (pttclass & PTT_CL_TMR) ? "timer " : "", (pttclass & PTT_CL_THR) ? "threads " : "", (pttclass & PTT_CL_LOG) ? "logger " : "", pttnolock ? "nolock" : "lock", pttnotod ? "notod" : "tod", pttnowrap ? "nowrap" : "wrap", pttto, pttracen); } return rc; } /* thread to print trace after timeout */ void *ptt_timeout() { struct timeval now; struct timespec tm; obtain_lock (&ptttolock); gettimeofday (&now, NULL); tm.tv_sec = now.tv_sec + pttto; tm.tv_nsec = now.tv_usec * 1000; timed_wait_condition (&ptttocond, &ptttolock, &tm); if (thread_id() == ptttotid) { ptt_pthread_print(); pttto = 0; ptttotid = 0; } release_lock (&ptttolock); return NULL; } #ifndef OPTION_FTHREADS DLL_EXPORT int ptt_pthread_mutex_init(LOCK *mutex, pthread_mutexattr_t *attr, char *loc) { PTTRACE ("lock init", mutex, attr, loc, PTT_MAGIC); return pthread_mutex_init(mutex, attr); } DLL_EXPORT int ptt_pthread_mutex_lock(LOCK *mutex, char *loc) { int result; PTTRACE ("lock before", mutex, NULL, loc, PTT_MAGIC); result = pthread_mutex_lock(mutex); PTTRACE ("lock after", mutex, NULL, loc, result); return result; } DLL_EXPORT int ptt_pthread_mutex_trylock(LOCK *mutex, char *loc) { int result; PTTRACE ("try before", mutex, NULL, loc, PTT_MAGIC); result = pthread_mutex_trylock(mutex); PTTRACE ("try after", mutex, NULL, loc, result); return result; } DLL_EXPORT int ptt_pthread_mutex_unlock(LOCK *mutex, char *loc) { int result; result = pthread_mutex_unlock(mutex); PTTRACE ("unlock", mutex, NULL, loc, result); return result; } DLL_EXPORT int ptt_pthread_cond_init(COND *cond, pthread_condattr_t *attr, char *loc) { PTTRACE ("cond init", NULL, cond, loc, PTT_MAGIC); return pthread_cond_init(cond, attr); } DLL_EXPORT int ptt_pthread_cond_signal(COND *cond, char *loc) { int result; result = pthread_cond_signal(cond); PTTRACE ("signal", NULL, cond, loc, result); return result; } DLL_EXPORT int ptt_pthread_cond_broadcast(COND *cond, char *loc) { int result; result = pthread_cond_broadcast(cond); PTTRACE ("broadcast", NULL, cond, loc, result); return result; } DLL_EXPORT int ptt_pthread_cond_wait(COND *cond, LOCK *mutex, char *loc) { int result; PTTRACE ("wait before", mutex, cond, loc, PTT_MAGIC); result = pthread_cond_wait(cond, mutex); PTTRACE ("wait after", mutex, cond, loc, result); return result; } DLL_EXPORT int ptt_pthread_cond_timedwait(COND *cond, LOCK *mutex, const struct timespec *time, char *loc) { int result; PTTRACE ("tw before", mutex, cond, loc, PTT_MAGIC); result = pthread_cond_timedwait(cond, mutex, time); PTTRACE ("tw after", mutex, cond, loc, result); return result; } DLL_EXPORT int ptt_pthread_create(pthread_t *tid, ATTR *attr, void *(*start)(), void *arg, char *nm, char *loc) { int result; UNREFERENCED(nm); result = pthread_create(tid, attr, start, arg); PTTRACE ("create", (void *)*tid, NULL, loc, result); return result; } DLL_EXPORT int ptt_pthread_join(pthread_t tid, void **value, char *loc) { int result; PTTRACE ("join before", (void *)tid, value ? *value : NULL, loc, PTT_MAGIC); result = pthread_join(tid,value); PTTRACE ("join after", (void *)tid, value ? *value : NULL, loc, result); return result; } DLL_EXPORT int ptt_pthread_detach(pthread_t tid, char *loc) { int result; PTTRACE ("dtch before", (void *)tid, NULL, loc, PTT_MAGIC); result = pthread_detach(tid); PTTRACE ("dtch after", (void *)tid, NULL, loc, result); return result; } DLL_EXPORT int ptt_pthread_kill(pthread_t tid, int sig, char *loc) { PTTRACE ("kill", (void *)tid, (void *)(long)sig, loc, PTT_MAGIC); return pthread_kill(tid, sig); } #else /* OPTION_FTHREADS */ DLL_EXPORT int ptt_pthread_mutex_init(LOCK *mutex, void *attr, char *loc) { PTTRACE ("lock init", mutex, attr, loc, PTT_MAGIC); return fthread_mutex_init(mutex,attr); } DLL_EXPORT int ptt_pthread_mutex_lock(LOCK *mutex, char *loc) { int result; PTTRACE ("lock before", mutex, NULL, loc, PTT_MAGIC); result = fthread_mutex_lock(mutex); PTTRACE ("lock after", mutex, NULL, loc, result); return result; } DLL_EXPORT int ptt_pthread_mutex_trylock(LOCK *mutex, char *loc) { int result; PTTRACE ("try before", mutex, NULL, loc, PTT_MAGIC); result = fthread_mutex_trylock(mutex); PTTRACE ("try after", mutex, NULL, loc, result); return result; } DLL_EXPORT int ptt_pthread_mutex_unlock(LOCK *mutex, char *loc) { int result; result = fthread_mutex_unlock(mutex); PTTRACE ("unlock", mutex, NULL, loc, result); return result; } DLL_EXPORT int ptt_pthread_cond_init(COND *cond, void *attr, char *loc) { UNREFERENCED(attr); PTTRACE ("cond init", NULL, cond, loc, PTT_MAGIC); return fthread_cond_init(cond); } DLL_EXPORT int ptt_pthread_cond_signal(COND *cond, char *loc) { int result; result = fthread_cond_signal(cond); PTTRACE ("signal", NULL, cond, loc, result); return result; } DLL_EXPORT int ptt_pthread_cond_broadcast(COND *cond, char *loc) { int result; result = fthread_cond_broadcast(cond); PTTRACE ("broadcast", NULL, cond, loc, result); return result; } DLL_EXPORT int ptt_pthread_cond_wait(COND *cond, LOCK *mutex, char *loc) { int result; PTTRACE ("wait before", mutex, cond, loc, PTT_MAGIC); result = fthread_cond_wait(cond, mutex); PTTRACE ("wait after", mutex, cond, loc, result); return result; } DLL_EXPORT int ptt_pthread_cond_timedwait(COND *cond, LOCK *mutex, struct timespec *time, char *loc) { int result; PTTRACE ("tw before", mutex, cond, loc, PTT_MAGIC); result = fthread_cond_timedwait(cond, mutex, time); PTTRACE ("tw after", mutex, cond, loc, result); return result; } DLL_EXPORT int ptt_pthread_create(fthread_t *tid, ATTR *attr, PFT_THREAD_FUNC start, void *arg, char *nm, char *loc) { int result; result = fthread_create(tid, attr, start, arg, nm); PTTRACE ("create", (void *)(uintptr_t)(*tid), NULL, loc, result); return result; } DLL_EXPORT int ptt_pthread_join(fthread_t tid, void **value, char *loc) { int result; PTTRACE ("join before", (void *)(uintptr_t)tid, value ? *value : NULL, loc, PTT_MAGIC); result = fthread_join(tid,value); PTTRACE ("join after", (void *)(uintptr_t)tid, value ? *value : NULL, loc, result); return result; } DLL_EXPORT int ptt_pthread_detach(fthread_t tid, char *loc) { int result; PTTRACE ("dtch before", (void *)(uintptr_t)tid, NULL, loc, PTT_MAGIC); result = fthread_detach(tid); PTTRACE ("dtch after", (void *)(uintptr_t)tid, NULL, loc, result); return result; } DLL_EXPORT int ptt_pthread_kill(fthread_t tid, int sig, char *loc) { PTTRACE ("kill", (void *)(uintptr_t)tid, (void *)(uintptr_t)sig, loc, PTT_MAGIC); return fthread_kill(tid, sig); } #endif DLL_EXPORT void ptt_pthread_trace (int class, char * type, void *data1, void *data2, char *loc, int result) { int i, n; if (pttrace == NULL || pttracen == 0 || !(pttclass & class) ) return; /* ** Fish debug: it appears MSVC sometimes sets the __FILE__ macro ** to a full path filename (rather than just the filename only) ** under certain circumstances. (I think maybe it's only for .h ** files since vstore.h is the one that's messing up). Therefore ** for MSVC we need to convert it to just the filename. ((sigh)) */ #if defined( _MSVC_ ) // fish debug; appears to be vstore.h // maybe all *.h files are this way?? { char* p = strrchr( loc, '\\' ); if (!p) p = strrchr( loc, '/' ); if (p) loc = p+1; } #endif /* * Messages from timer.c, clock.c and/or logger.c are not usually * that interesting and take up table space. Check the flags to * see if we want to trace them. */ if (!strncasecmp(loc, "timer.c:", 8) && !(pttclass & PTT_CL_TMR)) return; if (!strncasecmp(loc, "clock.c:", 8) && !(pttclass & PTT_CL_TMR)) return; if (!strncasecmp(loc, "logger.c:", 9) && !(pttclass & PTT_CL_LOG)) return; /* check for `nowrap' */ if (pttnowrap && pttracex + 1 >= pttracen) return; OBTAIN_PTTLOCK; if (pttrace == NULL || (n = pttracen) == 0) { RELEASE_PTTLOCK; return; } i = pttracex++; if (pttracex >= n) pttracex = 0; RELEASE_PTTLOCK; pttrace[i].tid = thread_id(); pttrace[i].class = class; pttrace[i].type = type; pttrace[i].data1 = data1; pttrace[i].data2 = data2; pttrace[i].loc = loc; if (pttnotod == 0) gettimeofday(&pttrace[i].tv,NULL); pttrace[i].result = result; } DLL_EXPORT int ptt_pthread_print () { int i, n, count = 0; char result[32]; // (result is 'int'; if 64-bits, 19 digits or more!) char tbuf[256]; time_t tt; const char dot = '.'; if (pttrace == NULL || pttracen == 0) return count; OBTAIN_PTTLOCK; n = pttracen; pttracen = 0; RELEASE_PTTLOCK; i = pttracex; do { if (pttrace[i].tid) { tt = pttrace[i].tv.tv_sec; strcpy(tbuf, ctime(&tt)); tbuf[19] = '\0'; if (pttrace[i].result == PTT_MAGIC && (pttrace[i].class & PTT_CL_THR)) result[0] = '\0'; else if((pttrace[i].class & ~PTT_CL_THR)) sprintf(result, "%8.8x", pttrace[i].result); else sprintf(result, "%d", pttrace[i].result); logmsg ( "%8.8"I32_FMT"x " // Thread id (low 32 bits) "%-12.12s " // Trace type (string; 12 chars) PTR_FMTx" " // Data value 1 PTR_FMTx" " // Data value 2 "%-14.14s " // File name "%s%c%6.6ld " // Time of day (HH:MM:SS.usecs) "%s\n" // Numeric result (or empty string) ,(U32)(uintptr_t)(pttrace[i].tid) // Thread id (low 32 bits) ,pttrace[i].type // Trace type (string; 12 chars) ,(uintptr_t)pttrace[i].data1 // Data value 1 ,(uintptr_t)pttrace[i].data2 // Data value 2 ,pttrace[i].loc // File name ,tbuf + 11 // Time of day (HH:MM:SS) ,dot // Time of day (decimal point) ,pttrace[i].tv.tv_usec // Time of day (microseconds) ,result // Numeric result (or empty string) ); count++; } if (++i >= n) i = 0; } while (i != pttracex); memset (pttrace, 0, PTT_TRACE_SIZE * n); pttracex = 0; pttracen = n; return count; } #endif hercules-3.07/pttrace.h000644 000765 000765 00000012076 11321734033 016561 0ustar00jmaynardjmaynard000000 000000 /* PTTRACE.H (c) Copyright Greg Smith, 2003-2009 */ /* Header file for pthreads trace debugger */ // $Id: pttrace.h 5598 2010-01-07 15:05:15Z rbowler $ /*-------------------------------------------------------------------*/ /* Pthread tracing structures and prototypes */ /*-------------------------------------------------------------------*/ #if !defined( _PTTHREAD_H_ ) #define _PTTHREAD_H_ #ifndef _PTTRACE_C_ #ifndef _HUTIL_DLL_ #define PTT_DLL_IMPORT DLL_IMPORT #else /* _HUTIL_DLL_ */ #define PTT_DLL_IMPORT extern #endif /* _HUTIL_DLL_ */ #else /* _PTTRACE_C_ */ #define PTT_DLL_IMPORT DLL_EXPORT #endif /* _PTTRACE_C_ */ #if defined(OPTION_FTHREADS) #define OBTAIN_PTTLOCK \ do { \ if (!pttnolock) fthread_mutex_lock(&pttlock); \ } while (0) #define RELEASE_PTTLOCK \ do { \ if (!pttnolock) fthread_mutex_unlock(&pttlock); \ } while (0) PTT_DLL_IMPORT int ptt_pthread_mutex_init(LOCK *, void *, char *); PTT_DLL_IMPORT int ptt_pthread_mutex_lock(LOCK *, char *); PTT_DLL_IMPORT int ptt_pthread_mutex_trylock(LOCK *, char *); PTT_DLL_IMPORT int ptt_pthread_mutex_unlock(LOCK *, char *); PTT_DLL_IMPORT int ptt_pthread_cond_init(COND *, void *, char *); PTT_DLL_IMPORT int ptt_pthread_cond_signal(COND *, char *); PTT_DLL_IMPORT int ptt_pthread_cond_broadcast(COND *, char *); PTT_DLL_IMPORT int ptt_pthread_cond_wait(COND *, LOCK *, char *); PTT_DLL_IMPORT int ptt_pthread_cond_timedwait(COND *, LOCK *, struct timespec *, char *); PTT_DLL_IMPORT int ptt_pthread_create(TID *, ATTR *, PFT_THREAD_FUNC, void *, char *, char *); PTT_DLL_IMPORT int ptt_pthread_join(TID, void **, char *); PTT_DLL_IMPORT int ptt_pthread_detach(TID, char *); PTT_DLL_IMPORT int ptt_pthread_kill(TID, int, char *); #else #define OBTAIN_PTTLOCK \ do { \ if (!pttnolock) pthread_mutex_lock(&pttlock); \ } while (0) #define RELEASE_PTTLOCK \ do { \ if (!pttnolock) pthread_mutex_unlock(&pttlock); \ } while (0) PTT_DLL_IMPORT int ptt_pthread_mutex_init(LOCK *, pthread_mutexattr_t *, char *); PTT_DLL_IMPORT int ptt_pthread_mutex_lock(LOCK *, char *); PTT_DLL_IMPORT int ptt_pthread_mutex_trylock(LOCK *, char *); PTT_DLL_IMPORT int ptt_pthread_mutex_unlock(LOCK *, char *); PTT_DLL_IMPORT int ptt_pthread_cond_init(COND *, pthread_condattr_t *, char *); PTT_DLL_IMPORT int ptt_pthread_cond_signal(COND *, char *); PTT_DLL_IMPORT int ptt_pthread_cond_broadcast(COND *, char *); PTT_DLL_IMPORT int ptt_pthread_cond_wait(COND *, LOCK *, char *); PTT_DLL_IMPORT int ptt_pthread_cond_timedwait(COND *, LOCK *, const struct timespec *, char *); PTT_DLL_IMPORT int ptt_pthread_create(TID *, ATTR *, void *(*)(), void *, char *, char *); PTT_DLL_IMPORT int ptt_pthread_join(TID, void **, char *); PTT_DLL_IMPORT int ptt_pthread_detach(TID, char *); PTT_DLL_IMPORT int ptt_pthread_kill(TID, int, char *); #endif PTT_DLL_IMPORT void ptt_trace_init (int n, int init); PTT_DLL_IMPORT int ptt_cmd(int argc, char *argv[], char*cmdline); PTT_DLL_IMPORT void ptt_pthread_trace (int, char *, void *, void *, char *, int); PTT_DLL_IMPORT int ptt_pthread_print (); PTT_DLL_IMPORT int pttclass; void *ptt_timeout(); typedef struct _PTT_TRACE { TID tid; /* Thread id */ int class; /* Trace record class */ #define PTT_CL_LOG 0x0001 /* Logger records */ #define PTT_CL_TMR 0x0002 /* Timer/Clock records */ #define PTT_CL_THR 0x0004 /* Thread records */ #define PTT_CL_INF 0x0100 /* Instruction info */ #define PTT_CL_ERR 0x0200 /* Instruction error/unsup */ #define PTT_CL_PGM 0x0400 /* Program interrupt */ #define PTT_CL_CSF 0x0800 /* Compare&Swap failure */ #define PTT_CL_SIE 0x1000 /* Interpretive Execution */ #define PTT_CL_SIG 0x2000 /* SIGP signalling */ #define PTT_CL_IO 0x4000 /* IO */ char *type; /* Trace type */ void *data1; /* Data 1 */ void *data2; /* Data 2 */ char *loc; /* File name:line number */ struct timeval tv; /* Time of day */ int result; /* Result */ } PTT_TRACE; #define PTT_LOC_Q( _string ) #_string #define PTT_LOC_M( _string ) PTT_LOC_Q( _string ) #define PTT_LOC __FILE__ ":" PTT_LOC_M( __LINE__ ) #define PTT_TRACE_SIZE sizeof(PTT_TRACE) #define PTT_MAGIC -99 #define PTT(_class,_type,_data1,_data2,_result) \ do { \ if (pttclass & (_class)) \ ptt_pthread_trace(_class,_type,(void *)(uintptr_t)(_data1),(void *)(uintptr_t)(_data2),PTT_LOC,(int)(_result)); \ } while(0) #define PTTRACE(_type,_data1,_data2,_loc,_result) \ do { \ if (pttclass & PTT_CL_THR) \ ptt_pthread_trace(PTT_CL_THR,_type,_data1,_data2,_loc,_result); \ } while(0) #endif /* defined( _PTTHREAD_H_ ) */ hercules-3.07/qdio.c000644 000765 000765 00000006642 11157241226 016054 0ustar00jmaynardjmaynard000000 000000 /* QDIO.C (c) Copyright Jan Jaeger, 2003-2009 */ /* Queued Direct Input Output */ // $Id: qdio.c 5243 2009-03-06 06:33:40Z jj $ /* This module contains the Signal Adapter instruction */ // $Log$ // Revision 1.23 2007/06/23 00:04:15 ivan // Update copyright notices to include current year (2007) // // Revision 1.22 2007/01/13 07:24:14 bernard // backout ccmask // // Revision 1.21 2007/01/12 15:24:33 bernard // ccmask phase 1 // // Revision 1.20 2006/12/08 09:43:29 jj // Add CVS message log // #include "hstdinc.h" #if !defined(_HENGINE_DLL_) #define _HENGINE_DLL_ #endif #if !defined(_QDIO_C_) #define _QDIO_C_ #endif #include "hercules.h" #include "opcode.h" #include "inline.h" #undef PTIO #define PTIO(_class, _name) \ PTT(PTT_CL_ ## _class,_name,regs->GR_L(1),(U32)(effective_addr2 & 0xffffffff),regs->psw.IA_L) #if defined(FEATURE_QUEUED_DIRECT_IO) /*-------------------------------------------------------------------*/ /* B274 SIGA - Signal Adapter [S] */ /*-------------------------------------------------------------------*/ DEF_INST(signal_adapter) { int b2; RADR effective_addr2; DEVBLK *dev; /* -> device block */ S(inst, regs, b2, effective_addr2); PRIV_CHECK(regs); SIE_INTERCEPT(regs); PTIO(IO,"SIGA"); /* Specification exception if invalid function code */ if(regs->GR_L(0) > SIGA_FC_MAX) ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION); /* Program check if the ssid including lcss is invalid */ SSID_CHECK(regs); /* Locate the device block for this subchannel */ dev = find_device_by_subchan (regs->GR_L(1)); /* Condition code 3 if subchannel does not exist, is not valid, or is not enabled or is not a QDIO subchannel */ if (dev == NULL || (dev->pmcw.flag5 & PMCW5_V) == 0 || (dev->pmcw.flag5 & PMCW5_E) == 0 || (dev->pmcw.flag4 & PMCW4_Q) == 0) { PTIO(ERR,"*SIGA"); #if defined(_FEATURE_QUEUED_DIRECT_IO_ASSIST) SIE_INTERCEPT(regs); #endif regs->psw.cc = 3; return; } /* Obtain the device lock */ obtain_lock (&dev->lock); /* Check that device is QDIO active */ if ((dev->scsw.flag2 & SCSW2_Q) == 0) { PTIO(ERR,"*SIGA"); release_lock (&dev->lock); regs->psw.cc = 1; return; } switch(regs->GR_L(0)) { case SIGA_FC_R: if(dev->hnd->siga_r) regs->psw.cc = (dev->hnd->siga_r) (dev, regs->GR_L(2) ); else { PTIO(ERR,"*SIGA"); regs->psw.cc = 3; } break; case SIGA_FC_W: if(dev->hnd->siga_w) regs->psw.cc = (dev->hnd->siga_w) (dev, regs->GR_L(2) ); else { PTIO(ERR,"*SIGA"); regs->psw.cc = 3; } break; case SIGA_FC_S: /* No signalling required for sync requests as we emulate a real machine */ regs->psw.cc = 0; break; default: PTIO(ERR,"*SIGA"); } release_lock (&dev->lock); } #endif /*defined(FEATURE_QUEUED_DIRECT_IO)*/ #if !defined(_GEN_ARCH) #if defined(_ARCHMODE2) #define _GEN_ARCH _ARCHMODE2 #include "qdio.c" #endif #if defined(_ARCHMODE3) #undef _GEN_ARCH #define _GEN_ARCH _ARCHMODE3 #include "qdio.c" #endif #endif /*!defined(_GEN_ARCH)*/ hercules-3.07/qeth.c000644 000765 000765 00000030670 11143760543 016062 0ustar00jmaynardjmaynard000000 000000 /* QETH.C (c) Copyright Jan Jaeger, 1999-2009 */ /* OSA Express */ // $Id: qeth.c 5126 2009-01-23 13:05:56Z bernard $ /* This module contains device handling functions for the */ /* OSA Express emulated card */ /* Device module hdtqeth.dll devtype QETH (config) */ /* hercules.cnf: */ /* 0A00-0A02 QETH */ // $Log$ // Revision 1.11 2007/11/21 22:54:14 fish // Use new BEGIN_DEVICE_CLASS_QUERY macro // // Revision 1.10 2007/06/23 00:04:15 ivan // Update copyright notices to include current year (2007) // // Revision 1.9 2006/12/08 09:43:29 jj // Add CVS message log // #include "hstdinc.h" #include "hercules.h" #include "devtype.h" #if defined(WIN32) && defined(OPTION_DYNAMIC_LOAD) && !defined(HDL_USE_LIBTOOL) && !defined(_MSVC_) SYSBLK *psysblk; #define sysblk (*psysblk) #endif static BYTE sense_id_bytes[] = { 0xff, 0x17, 0x31, 0x01, /* D/T */ 0x17, 0x32, 0x01, /* CU/T */ 0x00, 0x40, 0xfa, 0x01, 0x00, /* RCD CIW */ 0x03, 0xfc, 0x01, 0x00, /*Ena Q CIW */ 0x04, 0xfd, 0x01, 0x00 /* Act Q CIW */ }; /*-------------------------------------------------------------------*/ /* Initialize the device handler */ /*-------------------------------------------------------------------*/ static int qeth_init_handler ( DEVBLK *dev, int argc, char *argv[] ) { UNREFERENCED(argc); UNREFERENCED(argv); logmsg(D_("dev(%4.4x) experimental driver\n"),dev->devnum); dev->numdevid = sizeof(sense_id_bytes); logmsg(D_("senseidnum=%d\n"),dev->numdevid); memcpy(dev->devid, sense_id_bytes, sizeof(sense_id_bytes)); dev->devtype = dev->devid[1] << 8 | dev->devid[2]; dev->pmcw.flag4 |= PMCW4_Q; if(!group_device(dev,3)) { logmsg(D_("group device(%4.4x) pending\n"),dev->devnum); return 0; } else { int i; logmsg(D_("group = ( ")); for(i = 0; i < dev->group->acount; i++) logmsg("%4.4x ",dev->group->memdev[i]->devnum); logmsg(") complete\n"); } return 0; } /* end function qeth_init_handler */ /*-------------------------------------------------------------------*/ /* Query the device definition */ /*-------------------------------------------------------------------*/ static void qeth_query_device (DEVBLK *dev, char **class, int buflen, char *buffer) { BEGIN_DEVICE_CLASS_QUERY( "QETH", dev, class, buflen, buffer ); snprintf (buffer, buflen, "\n"); } /* end function qeth_query_device */ /*-------------------------------------------------------------------*/ /* Close the device */ /*-------------------------------------------------------------------*/ static int qeth_close_device ( DEVBLK *dev ) { UNREFERENCED(dev); /* Close the device file */ return 0; } /* end function qeth_close_device */ /*-------------------------------------------------------------------*/ /* Execute a Channel Command Word */ /*-------------------------------------------------------------------*/ static void qeth_execute_ccw ( DEVBLK *dev, BYTE code, BYTE flags, BYTE chained, U16 count, BYTE prevcode, int ccwseq, BYTE *iobuf, BYTE *more, BYTE *unitstat, U16 *residual ) { int rc = 0; /* Return code */ int num; /* Number of bytes to move */ int blocksize = 1024; #define CONFIG_DATA_SIZE 1024 UNREFERENCED(flags); UNREFERENCED(prevcode); UNREFERENCED(ccwseq); UNREFERENCED(chained); UNREFERENCED(rc); UNREFERENCED(blocksize); /* Process depending on CCW opcode */ switch (code) { case 0x01: /*---------------------------------------------------------------*/ /* WRITE */ /*---------------------------------------------------------------*/ logmsg(D_("Write dev(%4.4x)\n"),dev->devnum); #define WR_SIZE 0x22 /* Calculate number of bytes to read and set residual count */ num = (count < WR_SIZE) ? count : WR_SIZE; *residual = count - num; if (count < WR_SIZE) *more = 1; /* Return normal status */ *unitstat = CSW_CE | CSW_DE; break; case 0x02: /*---------------------------------------------------------------*/ /* READ */ /*---------------------------------------------------------------*/ logmsg(D_("Read dev(%4.4x)\n"),dev->devnum); #define RD_SIZE 0x22 /* Calculate number of bytes to read and set residual count */ num = (count < RD_SIZE) ? count : RD_SIZE; *residual = count - num; if (count < RD_SIZE) *more = 1; /* Return normal status */ *unitstat = CSW_CE | CSW_DE; break; case 0x03: /*---------------------------------------------------------------*/ /* CONTROL NO-OPERATION */ /*---------------------------------------------------------------*/ logmsg(D_("NOP dev(%4.4x)\n"),dev->devnum); *residual = 0; *unitstat = CSW_CE | CSW_DE; break; case 0x04: /*---------------------------------------------------------------*/ /* SENSE */ /*---------------------------------------------------------------*/ logmsg(D_("Sense dev(%4.4x)\n"),dev->devnum); /* Calculate residual byte count */ num = (count < dev->numsense) ? count : dev->numsense; *residual = count - num; if (count < dev->numsense) *more = 1; /* Copy device sense bytes to channel I/O buffer */ memcpy (iobuf, dev->sense, num); /* Clear the device sense bytes */ memset (dev->sense, 0, sizeof(dev->sense)); /* Return unit status */ *unitstat = CSW_CE | CSW_DE; break; case 0xE4: /*---------------------------------------------------------------*/ /* SENSE ID */ /*---------------------------------------------------------------*/ logmsg(D_("Sense ID dev(%4.4x)\n"),dev->devnum); /* Calculate residual byte count */ num = (count < dev->numdevid) ? count : dev->numdevid; *residual = count - num; if (count < dev->numdevid) *more = 1; /* Copy device identifier bytes to channel I/O buffer */ memcpy (iobuf, dev->devid, num); /* Return unit status */ *unitstat = CSW_CE | CSW_DE; break; case 0xFA: /*---------------------------------------------------------------*/ /* READ CONFIGURATION DATA */ /*---------------------------------------------------------------*/ logmsg(D_("Read Configuration Data dev(%4.4x)\n"),dev->devnum); /* Calculate residual byte count */ num = (count < CONFIG_DATA_SIZE) ? count : CONFIG_DATA_SIZE; *residual = count - num; if (count < CONFIG_DATA_SIZE) *more = 1; /* Clear the configuration data area */ memset (iobuf, 0x00, CONFIG_DATA_SIZE); /* Return unit status */ *unitstat = CSW_CE | CSW_DE; break; case 0xFC: /*---------------------------------------------------------------*/ /* ESTABLISH QUEUES */ /*---------------------------------------------------------------*/ logmsg(D_("Establish Queues dev(%4.4x)\n"),dev->devnum); /* Calculate residual byte count */ num = (count < CONFIG_DATA_SIZE) ? count : CONFIG_DATA_SIZE; *residual = count - num; if (count < CONFIG_DATA_SIZE) *more = 1; memset (iobuf, 0x00, CONFIG_DATA_SIZE); /* INCOMPLETE ZZ * QUEUES MUST BE SETUP HERE */ /* Return unit status */ *unitstat = CSW_CE | CSW_DE; break; case 0xFD: /*---------------------------------------------------------------*/ /* ACTIVATE QUEUES */ /*---------------------------------------------------------------*/ logmsg(D_("Activate Queues dev(%4.4x)\n"),dev->devnum); /* Calculate residual byte count */ num = (count < CONFIG_DATA_SIZE) ? count : CONFIG_DATA_SIZE; *residual = count - num; if (count < CONFIG_DATA_SIZE) *more = 1; memset (iobuf, 0x00, CONFIG_DATA_SIZE); /* INCOMPLETE ZZ * QUEUES MUST BE HANDLED HERE, THIS CCW WILL ONLY EXIT * IN CASE OF AN ERROR OR A HALT, CLEAR OR CANCEL SIGNAL */ /* Return unit status */ *unitstat = CSW_CE | CSW_DE; break; default: /*---------------------------------------------------------------*/ /* INVALID OPERATION */ /*---------------------------------------------------------------*/ logmsg(D_("Unkown CCW dev(%4.4x) code(%2.2x)\n"),dev->devnum,code); /* Set command reject sense byte, and unit check status */ dev->sense[0] = SENSE_CR; *unitstat = CSW_CE | CSW_DE | CSW_UC; } /* end switch(code) */ } /* end function qeth_execute_ccw */ /*-------------------------------------------------------------------*/ /* Signal Adapter Initiate Input */ /*-------------------------------------------------------------------*/ static int qeth_initiate_input(DEVBLK *dev, U32 qmask) { UNREFERENCED(qmask); logmsg(D_("SIGA-r dev(%4.4x) qmask(%8.8x)\n"),dev->devnum); return 0; } /*-------------------------------------------------------------------*/ /* Signal Adapter Initiate Output */ /*-------------------------------------------------------------------*/ static int qeth_initiate_output(DEVBLK *dev, U32 qmask) { UNREFERENCED(qmask); logmsg(D_("SIGA-w dev(%4.4x) qmask(%8.8x)\n"),dev->devnum); return 0; } #if defined(OPTION_DYNAMIC_LOAD) static #endif DEVHND qeth_device_hndinfo = { &qeth_init_handler, /* Device Initialisation */ &qeth_execute_ccw, /* Device CCW execute */ &qeth_close_device, /* Device Close */ &qeth_query_device, /* Device Query */ NULL, /* Device Start channel pgm */ NULL, /* Device End channel pgm */ NULL, /* Device Resume channel pgm */ NULL, /* Device Suspend channel pgm */ NULL, /* Device Read */ NULL, /* Device Write */ NULL, /* Device Query used */ NULL, /* Device Reserve */ NULL, /* Device Release */ NULL, /* Device Attention */ NULL, /* Immediate CCW Codes */ &qeth_initiate_input, /* Signal Adapter Input */ &qeth_initiate_output, /* Signal Adapter Output */ NULL, /* Hercules suspend */ NULL /* Hercules resume */ }; /* Libtool static name colision resolution */ /* note : lt_dlopen will look for symbol & modulename_LTX_symbol */ #if !defined(HDL_BUILD_SHARED) && defined(HDL_USE_LIBTOOL) #define hdl_ddev hdtqeth_LTX_hdl_ddev #define hdl_depc hdtqeth_LTX_hdl_depc #define hdl_reso hdtqeth_LTX_hdl_reso #define hdl_init hdtqeth_LTX_hdl_init #define hdl_fini hdtqeth_LTX_hdl_fini #endif #if defined(OPTION_DYNAMIC_LOAD) HDL_DEPENDENCY_SECTION; { HDL_DEPENDENCY(HERCULES); HDL_DEPENDENCY(DEVBLK); HDL_DEPENDENCY(SYSBLK); } END_DEPENDENCY_SECTION #if defined(WIN32) && !defined(HDL_USE_LIBTOOL) && !defined(_MSVC_) #undef sysblk HDL_RESOLVER_SECTION; { HDL_RESOLVE_PTRVAR( psysblk, sysblk ); } END_RESOLVER_SECTION #endif HDL_DEVICE_SECTION; { HDL_DEVICE(QETH, qeth_device_hndinfo ); } END_DEVICE_SECTION #endif hercules-3.07/README.COMMADPT000644 000765 000765 00000013113 11143760543 017031 0ustar00jmaynardjmaynard000000 000000 Preliminary 2703 BSC Support Only allows Point to Point connection. Hercules device statement : CCUU 2703 lport=port lhost=host rhost=host rport=port dial=IN|OUT|INOUT|NO [pto=nnn|0|-1] [rto=nnn|0|-1] [eto=nnn|0|-1] lport : the local TCP port number or service name on which the line will listen for incoming TCP calls This parameter is irrelevant and is ignored for DIAL=OUT for DIAL=IN|INOUT|NO, this parameter is mandatory cwlhost : The local interface IP address on which to listen. if not specified, all interfaces will be used. ex: lhost=127.0.0.1 : Only accept calls from local host lhost=192.168.0.1 : Only accept calls from hosts that can be routed through the interface that has an IP address of 192.168.0.1 If there is no 192.168.0.1 local IP address, this will fail. This parameter is irrelevant and is ignored for DIAL=OUT for DIAL=IN|INOUT|NO, this parameter is mandatory rhost : the remote host ip address or name This parameter is irrelevant and is ignored for DIAL=IN for DIAL=OUT|INOUT|NO, this parameter is mandatory rport : the remote port number or service name This parameter is irrelevant and is ignored for DIAL=IN for DIAL=OUT|INOUT|NO, this parameter is mandatory rto, pto, eto : Read, Poll and Enable Timeout values in miliseconds. specifying 0 means No Timeout (infinite wait). -1 Means immediate timeout. The read timeout is how long the handler will wait for an ending character after the last character was received or the I/O initiated. The read timeout default is 3000 Miliseconds (3 Seconds) The poll timeout is how long the handler will wait for a polled station to respond to a poll request. The poll timeout default is 3000 Miliseconds (3 Seconds) The enable timeout is how long the handler will wait for the TCP connection to be established. The enable timeout default is 10000 Miliseconds (10 Seconds), except if DIAL=NO is also specified, in which case the enable timeout defaults to 0. Note : the ETO parameter is ignored if DIAL=NO is not specified. for a dialed line, there is no enable timeout. If the eto parameter is specified and DIAL is not "NO", then a warning message is issued and the parameter is ignored. dial=IN|OUT|INOUT|NO Indicate call direction (if any). This parameter also modifies the behaviour of certain CCWS as well as TCP incoming call handling : ENABLE : DIAL=IN|DIAL=INOUT Wait forever for an incoming call DIAL=NO Completes immediatelly if a call is already present Otherwise, attemps connecting to the remote end if the call fails, ENABLE exits with Int Req status DIAL=OUT Enable is not a valid CCW for a DIALOUT only line DIAL : DIAL=IN|DIAL=NO DIAL is not a valid CCW for a DIAL IN or non-switched line DIAL=OUT|DIAL=INOUT The outgoing call is attempted Incomming TCP call : In any case, if a call is already present, the call is rejected. DIAL=NO : The call is accepted, even if no CCW is currently executing DIAL=OUT : The call is rejected DIAL=IN|DIAL=INOUT The call is accepted if the line is currently executing an ENABLE ccw. The communication protocol : The communication protocol is basic. Every character written by the guest program with a WRITE CCW is transfered to the remote end, untranslated and untouched (except for Transparent BSC rules which deem that DLE characters are doubled when the program has previously written a DLE/STX sequence). Dial data format Dial data is originally as follows : x x x x 0 0 0 0 : Dial # 0 ......... x x x x 1 0 0 1 : Dial # 9 x x x x 1 1 0 0 : EON x x x x 1 1 0 1 : SEP In order to perform an outgoing call, the data must follow these specifications : N[N[N]]SEPN[N[N]]SEPN[N[N]]SEPN[N[N]]]SEPN[..[N]][EON] Where N is any dialing number from 0 to 9 and SEP is the separator. The 4 first group of digits represet the IP address. The last group represent a TCP port number. For example (* is the SEP character representation) : 192*168*0*1*8888 : will issue a TCP connection to 192.168.0.1 port 8888 The EON is optional. If it is present, it must be the last character of the dial data. Bugs, Caveats The Address Prepare is not implemented The POLL CCW Has not been tested Group DIAL IN is not implemented DIAL CCW Not tested There is 1 thread per line, when there should be 1 thread for ALL lines. MAXDEVT may have to be adjusted under WINDOWS to accomodate for a large number of lines (because some I/O may take an undefinite amount of time). There is no 'REAL' Bsc line support yet. hercules-3.07/README.CVS000644 000765 000765 00000014162 11143760543 016265 0ustar00jmaynardjmaynard000000 000000 B u i l d i n g H e r c u l e s If you're simply trying to figure out how to build Hercules from the distributed source files (i.e. NOT from the CVS sources), then skip to the "Building Hercules" section further below. BUILD PREPARATION ----------------- In order to build Hercules from the CVS sources, you must have installed: Package Version (or greater!) ---------------------------------- autoconf 2.54 (or greater!) automake 1.7 (or greater!) flex 2.5 (or greater!) gawk 3.0 (or greater!) gcc 2.95 (or greater!) gettext 0.11 (or greater!) (--enable-nls only) grep 2.5 (or greater!) libiconv 1.8 (or greater!) libintl 0.10 (or greater!) libtool ?.?? (or greater!) m4 0.0 (or greater!) make 3.79 (or greater!) perl 5.6 (or greater!) sed 3.02 (or greater!) The following package(s) is(are) optional Package Version (or greater!) ---------------------------------- libgcrypt 0.4.4 (or greater!) (for z990 crypto instructions) zlib ? (for ZLIB compression) libbz2 ? (for BZIP2 compression) * If an optional package is not installed, the resulting build may lack an optional feature, but should be usable otherwise. All of these tools can be found at www.gnu.org in source code form, and are also widely available in packaged form (RPM, DEB, Solaris packages, etc.). +------------------------------------------------------------+ | | | ** NOTE ** | | | | There is a handy utility (script) found in the 'util' | | subdirectory that will check for the required version | | of all of the above mentioned packages. Simply 'cd' to | | that subdirectory (in the hercules source code tree) and | | enter the command 'cvslvlck'. It will then simply check | | and report for you whether or not you have all of the | | required version(s) of all the packages needed to build | | Hercules from CVS source. | | | +------------------------------------------------------------+ Once you have these tools installed, simply enter the command: sh ./autogen.sh This will, among other things, create you a shell script called "configure". The resulting configure script (created by the above 'autogen' command) is then what you use to build Hercules with. (It will probably create a bunch of other directories and files too, but we're mostly concerned about the configure script). BUILDING HERCULES ----------------- Now that a 'configure' script has been built for us, let's use it! :) (Note: if you're simply trying to build Hercules from the distributed source files (i.e. NOT from the CVS sources), then just use the 'configure' script that should have been included with the source distribution tarball.) +------------------------------------------------------------+ | | | ** NOTE ** | | | | See also the boxed Note in the BUILD PREPARATION section | | further above regarding the 'cvslvlck' script which can | | be used to check to see if you have all of the required | | packages installed or not to build Hercules from source. | | | +------------------------------------------------------------+ Before you trying using the configure script, you may wish to review the information in the INSTALL file. It contains generic installation instructions for how to build/install most any package. The instructions there pertain just as much to Hercules as they do to any other package. Since the information there is pretty detailed however, rather than try to slog your way through it all, you may wish to first review the below summarized version first. Briefly, the way you build Herc is to first "configure" the building process and then invoke your pre-configured building process. The build process basically consists of a 'make' command which processes a 'makefile'. The makfile however needs to be customized for your system. That's what the "configure" script does. It contructs a customized makefile and that is what is meant by "configuring your building process". Here's the entire build process step-by-step: To build Herc, first switch to the directory where the source files are and then configure the build process by entering the following command: ./configure (Note: you may or may not wish to enter additional parameters to the configure command. See further below) Then simply invoke your pre-configured build process by entering the following command: make That's it! The 'make' command should build Hercules for you. After it's been built, you may or may not wish to "install" it. To "install" Hercules into the default package installation directory after building it, enter the following command: make install That will copy the just built binaries to their proper place. To uninstall Hercules once it's been installed, simply enter the command: make uninstall and the previously copied files will be removed (deleted). Note: you may or may not wish to add some additional parameters to the above mentioned "configure" command. One of the more common ones for those who are building Herc under Cygwin is "--enable-fthreads". Enter "./configure --help" for more information regarding the various parameters that Hercules's customized "configure" script supports for building Hercules. -- Matt Zimmerman 08 Oct, 2001 updated in detail by: "Fish" (David B. Trout) 30 Jul, 2002 hercules-3.07/README.DYNMOD000644 000765 000765 00000010534 11335365456 016632 0ustar00jmaynardjmaynard000000 000000 ------------------------------------------------------------------------------- Hercules Dynamic Modules (on Windows) ------------------------------------------------------------------------------- Required Files Required files: makefile: "{modname}.msvc" defines module name and source file(s) resource file: "{modname}.rc" the module's version resource file ------------------------------------------------------------------------------- makefile stub format Required makefile format: # Module name: DYNMOD = {modname} # Source files: DYNOBJ = \ $(O){srcfile1}.obj \ $(O){srcfile2}.obj \ $(O){srcfile3}.obj ... etc... Your makefile is !INCLUDEd as part of Hercules's main makefile and thus your dynamic module gets built along with the rest of Hercules. ------------------------------------------------------------------------------- The MAKE/BUILD command Building (making): dynmake.bat {projdir} {modname} {build_type} {num_cpus} [-a|clean] e.g.: "X:\Hercules\dynmake.bat" "$(SolutionDir)" {modname} RETAIL 32 -a The {projdir} value you pass MUST be a fully qualified path to your dynamic module's project directory where all of your files are. The dynamke.bat command you invoke should also be a fully qualifed path to the desired Hercules dynmake.bat file. The other arguments (i.e. {build_type}, {num_cpus}, etc) are identical to the values normally specified for the main Hercules "makefile.bat" command used to build Hercules with. Refer to makefile.bat for details. ------------------------------------------------------------------------------- Pre-Build event and Post-Build event callbacks Optional files: prebuild.bat Called before the main Hercules makefile.bat is called. postbld.bat Called after the main Hercules makefile.bat is called. During the build process, dynmake.bat checks if the file exists in your specified project directory and if it does, calls it with the following parameters: {hercdir} {modname} {build_type} {num_cpus} [-a|clean] The {hercdir} value is the fully qualified path the main Hercules source code directory. The other parameters are the same values that you passed to the dynmake.bat command. ------------------------------------------------------------------------------- Resource Compiler For your convenience the following #defines are also passed to the resource compiler on the command-line during the actual build process: VERSION The Hercules version string (e.g. "3.06-svn-5602") TARGETFILENAME Your module name string (e.g. "{modname}.dll") MAX_CPU_ENGINES_STR Number of CPUs as a string (e.g. "32") Use them in your .rc resource file's VERSIONINFO structure as needed. ------------------------------------------------------------------------------- The Build Process Dynmake.bat first creates a work subdirectory beneath Hercules's main source code directory using the same name as the {modname} you passed to it. It then calls your prebuild.bat file if it exists. Use this callback to perform any pre-build adjustments to your source files that may be necessary before the actual build process begins. When your prebuild.bat returns, it then copys all *.c, *.h, *.rc, *.rc2 and *.msvc files from your project directory into its {modname} subdirectory and invokes Hercules's primary "makefile.bat" script to perform the actual build. When the build is done it then calls your postbld.bat callback if it exists. You can use this callback to copy the resulting binary from Hercules's output directory to your project directory or whatever other post-build processing your product may require. ------------------------------------------------------------------------------- More Information For additional information regarding dynamic modules please see the "Hercules Dynamic Loader" readme document called "README.HDL". ------------------------------------------------------------------------------- hercules-3.07/README.ECPSVM000644 000765 000765 00000014633 11143760543 016632 0ustar00jmaynardjmaynard000000 000000 ECPS:VM : Extended Control Program Support : VM/370 - AND - Extended VM Assists - Partial Privop Simulation And Virtual Interval Timer ************ CHANGE LOG **************** 07/07/03 : Changed description for configuration and commands ECPS:VM changed to ECPSVM (config) ecpsvm changed to ecpsvm (command) - PARTIAL IMPLEMENTATION DOCUMENTATION - ************************* Affected operating systems : VM/370 Release 6 (PTFs required - PLC 029 works fine) up to VM/SP 6 (with or without HPO option) --- VM/XA SF, VM/XA SP, VM/ESA and z/VM do NOT use these Assists, but rely on the SIE instruction to perform some of these functions. A VM/SP Guest (or VM/370 Guest with 4K Storage key updates) running under [z/]VM[/[XA|ESA]] will NOT have access to either the CP assists or VM Assists. The ECPS:VM Feature is disabled when running under SIE. ************************ How to enable VM Assists : In the HERCULES.CNF file, in the configuration section : ECPSVM YES|NO|LEVEL n (where n is the requested level.) If "YES" is specified, the most appropriate level is returned (Level 20) n Doesn't affect the operations of the assist but what level is reported to the program. - CAUTION - Use the 'n' form is not recommended, and is only provided for engineering use. ********** New panel command : 'ecpsvm' Subcommands : ecpsvm stats : Shows ECPS:VM Call/Hit statistics ecpsvm enable/disable feature : Enable/Disable named feature ecpsvm help : (guess) ecpsvm debug [feature|ALL|CPASSIST|VMASSIST] : Turn on debugging messages for a specific feature ecpsvm nodebug [feature|ALL|CPASSIST|VMASSIST] : Turn off... ecpsvm level [nn] : Force ECPS:VM to report a certain support level (or display the current support level) NOTE : ecpsvm disable does NOT entirelly disables CP ASSISTS. If it did (i.e. generate a program interrupt whenever a E6xx instruction is invoked) VM would abend immediatelly. Rather, ommit the ECPSVM statement in the configuration file. To determine the feature names, type "ecpsvm enable ALL". All the enabled features will be listed. the ecpsvm command is NOT case sensitive ********** Determining if the assist is used by VM : Use the 2 following CLASS A commands : CP QUERY CPASSIST CP QUERY SASSIST Both queries should return 'ON'. Also use the following CLASS G Command : CP QUERY SET 2nd line should indicate : ASSIST ON SVC TMR *********** Technical information the CP Assists provides The VM SCP with various microcoded instructions to shorten the supervisor pathlength. All microcoded instructions are priviledged instructions and have an opcode of E6xx. They are native representation of what the SCP would do in a similar case. For all cases where the assist is not able to resolve a situation, the E6XX instructions resolve to a no-op, thus leaving the responsability of the task to the original CP Code. The VM Assists alters the behaviour of certain priviledged instructions when executed in problem state (controled by the Problem State bit in the PSW) either by completely simulating the instruction (when feasable), Branching directly to the CP support module for that instruction (therefore bypassing Program interruption processing and instruction decoding), or generating a Program interruption otherwise. The VM Virtual Interval Timer assist allows updating of a Virtual Machine virtual interval timer directly by the microcode. Both CP And VM Assists are controled by real Control Register 6 which control availability, and behaviour of the assists. ************ Troubleshooting In the event that a certain CP or VM Assist disrupts normal operations, it is possible to selectivelly disable each discrete component. The best method is to disable ALL VM and CP Assists (Except STEVL and SSM if done prior to IPL) and to enable each feature until the problem occurs. If it is unknown whether the problem lies in the VM or CP Assist, it is also possible to enable/disable the entire group of assists. See the EVM ENA|DISA Commands. EVM STA allows to see how often each assist is invoked. The hit and hit ration makes it possible to determine how effective the assists are. A Low hit ratio may be normal in some situations (for example, the LPSW Hit ration will be very low when running VM under VM, because most PSW switches cannot be resolved by the assist) A Low invocation count simply shows that in THAT particular situation, the related assist is not used often (For example, there are very few LCTLs when running CMS). Some assists are just invoked once at IPL (STEVL). This is normal behaviour. ************ Implemented Assists : CP ASSISTS : FREEX, FRETX (CP Free Storage management) DISP0, DISP1, DISP2 (CP Dispatching) PGLOCK, PGULOCK (Real frame locking/unlocking) TRANBRNG, TRANLOCK (Virtual frame addressing/locking) SCNRU, SCNVU (Real/Virtual Device control block scan) STEVL (Store ECPS:VM support level) VM ASSISTS : Virtual Interval Timer LPSW Simulation SSM Simulation SVC Simulation LCTL Simulation Non-Implemented assists : CP ASSISTS : FREE/FRET : (Original (up to level 19) CP Storage Management - replaced by FREEX/FRETX) CCWGN, DFCCW, DNCCW, UXCCW : CCW/CSW Translation assists (Soon) LCSPG : Locate Changed Shared Page (Soon) VIPT, VIST : Virtual Translation Page/Segment Invalidation (Soon) LINK/RETURN (SVC 8/SVC 12) (Soon) Prefered Machine Assists (Insufficient information) .. Maybe others ... VM ASSISTS : V=R Shadow Table Bypass assists (Including LRA instruction) (note : The V=R Shadow Table Bypass assist is a feature which requires the guest program to be aware of the feature (Page 0 Relocation)) SIO (In progress - Partial sim) DIAG (In progress - Partial sim) IUCV (In Progress - Partial sim - VM/SP4 or later only) STxSM (Almost never invoked - ECMODE Only) ISK/SSK/ISKE/SSKE/IVSK (Extended Key Ops assist) VM Assists for MVS .. Maybe others ... ***************** BUGS & Caveats : ECPS:VM will NOT work in an AP or MP system. An AP or MP generated system locks the control blocks being manipulated by the assisted functions (VMBLOK, RDEVBLOK, VDEVBLOK, etc..). However, the current ECPS:VM implementation doesn't lock any of those structures. Therefore, CP will fairly quickly abend because it will find some of the control blocks to not have been locked when they should (various LOKXXX abends). Consequently, ECPS:VM must be disabled when a AP or MP system is used. ***************** Have Fun, --Ivan hercules-3.07/README.HAO000644 000765 000765 00000010220 11143760544 016231 0ustar00jmaynardjmaynard000000 000000 Hercules Automatic Operator The Hercules Automatic Operator (HAO) feature is a facility that allows one to automatically issue panel commands in response to certain messages being issued. To use the Hercules Automatic Operator facility, one first defines a "rule" consisting of a "target" and an associated "command". The "target" is just a regular expression pattern used to match against the text of the various messages that Hercules issues as it runs. Whenever a match is found, the rule "fires" and its associated command is automatically issued. The Hercules Automatic Operator facility is ONLY for those messages issued BY HERCULES to its HMC (hardware console). It CANNOT be used for whatever messages the guest operating system may issue to any of its terminals. It is only a HERCULES automatic operator and NOT a "VSE", "MVS", "VM", etc, automatic operator! Defining a Rule To define a HAO rule, enter the command: hao to define the rule's "target" match pattern (a simple regular expression), followed by the command: hao to define the rule's associated panel-command. The target pattern is a simple regular expression value as defined by whatever regular expression support your supported host build platform happens to support. For Windows it must be a Perl Compatible Regular Expression (PCRE). For other supported build platforms it might be some other supported regular expression syntax. Check your host platform's programming documentation for further details. The associated panel-command is whatever valid Hercules command you wish to issue in response to a message being issued that matches the given pattern (target). (Okay, that's not completely true. The "command" is actually any text string one desires. It doesn't have to be a valid Hercules command, but it makes infinitely more sense if it is one). Other commands and limitations To delete a fully or partially defined HAO rule, first use the 'hao list' command to list all of the defined (or partially defined) rules, and then use the 'hao del ' command to delete the specific rule identified by 'nnn'. (All rules are assigned numbers as they are defined and are thus identified by their numeric value). Optionally, one may delete ALL defined or partially defined rules by issuing the command 'hao clear'. The current implementation limits the total number of defined rules to 10. If you need to define more than 10 rules you will either have to build Hercules for yourself (increasing the value of the HAO_MAXRULE constant in hao.c) or else beg one of the Hercules developers to please do it for you. Note that there is currently no way to define a command whose arguments varies based on actual message text. That is to say, there is currently no way to say "Reply with the command 'devinit filename' in response to message text 'HHCXXnnnI Device 'cuu' intervention required.' where 'cuu' is whatever cuu was identified in the message." The HAO is *not* that sophisticated (yet). Only simple plain-text commands may be defined and issued. No automatic substitution is done based on message text (although normal 'DEFSYM' symbol substitution *is* supported however, as that is a normal panel-command feature supported separately from the HAO). This may possibly change in the future however, depending on user need/demand. ALL defined rules are checked for a match each time Hercules issues a message. There is no way to specify "stop processing subsequent rules". If a message is issued that matches two or more rules, each associated command is then issued in sequence. Thus the advice to choose your rules' target patterns carefully very much applies here. Giving credit where credit is due The Hercules Automatic Operator facility was designed eons ago (or so it seems anyway) by Bernard van der Helm of Noordwijkerhout, The Netherlands, and is thus copyrighted by him. All I did was FINALLY get around to implementing it in the current release of Hercules. If you like it and find it to be useful, I think it'd be real nice if you'd let Bernard know that. Thanks. -- Fish Sep 25, 2006 hercules-3.07/README.HDL000644 000765 000765 00000047766 11143760542 016260 0ustar00jmaynardjmaynard000000 000000 /* Hercules Dynamic Loader The dynamic loader is intended to supply a loading and linking mechanism, whereby routines, commands, instructions and functions can be dynamically added to hercules, without the need to rebuild or even restart hercules. The loader can be controlled by the following hercules commands: ldmod - Load modules named in module list rmmod - Unload modules named in list lsmod - List all modules and entry points lsdep - List all dependencies The ldmod statement may also appear in the hercules configuration file. configuration statement: modpath - Specifies where modules are loaded from The loader has 2 basic functions module load and module unload. Module load: int hdl_load(char *name, int flags); Where name is the module name, this name may include the path. If no path is given then the module is loaded from the default library search order. Note that this is different from the standard search order. flags may be one of the following: HDL_LOAD_DEFAULT or 0 - Default load HDL_LOAD_MAIN - Reserved for hercules use HDL_LOAD_NOUNLOAD - Module cannot be unloaded HDL_LOAD_FORCE - Override dependency check HDL_LOAD_NOMSG - Do not issue any error messages This function returns a zero value when the load is successful. Module unload: int hdl_dele(char *name); Where name is the name of the module that is to be unloaded. This function returns a zero value when the unload is successful. Resolving Symbols: void * HDL_FINDSYM(char *symbolname); This function will return the entry point of symbolname or zero when the symbol cannot be resolved. void * HDL_FINDNXT(current_entry point); This function will return the previous entry point. That is, the entry point which was current before the entry point as identified by current_entry point was registered. This function is intended to allow a module to call the original routine. An example of this is given in the panel_command entry as listed below. There are some special considerations for systems that do not support the concept of back-linking. Back-linking is the operating system support of dynamically resolving unresolved external references in a dynamic module, with the main module, or other loaded modules. Cygwin does not support back-linking and Cygwin specials are listed in this example with #if defined(WIN32). Some additional notes: Unload will remove all references to a specific module, but currently it will not actually remove the loaded module from memory. This is because there is no safe way (yet) to synchronize unloading of code and, besides, it may still be in use. This should however pose no practical limitations. When a module lists a new dependency, that dependency will be regis- tered. Unloading the module does not remove the dependency, this is to be consistent with the previous note about unloading. Diagnose F14 - dll interface Purpose: Allow external routines to be called from OS running under hercules external routines must reside in hercules dll's Instruction: Format: 83 r1 r3 d2(b2) r1: register containing real address of external routine name to be called this routine name is defined as CL32, and is subject to EBCDIC to ASCII translation under control of hercules codepages. This parameter must be 32 byte aligned. r3: register containing user parameter. d2(b2): 0xF14 External routine: void xxxx_diagf14_routine_name(int r1, int r3, REGS *regs); xxxx_diagf14_ prefix to routine_name xxxx being either s370, s390 or z900 depending on architecture mode. The instruction is subject to machine malfunction checking. The external routine may be interrupted when an extended wait or loop occurs. */ #include "hercules.h" #include "devtype.h" #include "opcode.h" /* Local definitions */ static void *gui_cpu_state(REGS *regs) { void *(*prev_cpu_state)(REGS *); /* CPU status update processing */ /* Call higher level routine if one exists */ if((prev_cpu_state = HDL_FINDNXT(gui_cpu_state))) return prev_cpu_state(regs); return NULL; } void *ProcessCommand (char *command) { void * (*prev_panel_command)(char *); if (strncasecmp(command,"ourcmd",6) == 0) { logmsg ("This is our command\n"); } else /* Call higher level command handler */ if((prev_panel_command = HDL_FINDNXT(ProcessCommand))) return prev_panel_command(command); return NULL; } /* The dependency section is - for all intents and purposes - called before the module is loaded. Its function is to check that there are no incompatibilities between this module and the version of hercules that we are running. Dependencies are identified by name, this name is given on the HDL_DEPENDENCY statement. Each dependency then has a version code, and a size code, where the version code is a character string, and the size code an integer value. If the version or size codes do not match with those in the hercules main module, the module cannot be loaded. The version is usually a character string that identifies the version of the component, and the size is to be the size of the component in the case of structures or unions. Version and size should be coded as following: #define HDL_VERS_SOMETHING "1.0" #define HDL_SIZE_SOMETHING sizeof(SOMETHING) where SOMETHING can be a structure or other component. the associated dependency statement: HDL_DEPENDENCY(SOMETHING); When a dependency is given that has not yet been registered, it will be registered, such that it can be checked in subsequent module loads. The dependency section is mandatory. */ HDL_DEPENDENCY_SECTION; { /* Define version dependencies that this module requires */ HDL_DEPENDENCY ( HERCULES ); HDL_DEPENDENCY ( SYSBLK ); HDL_DEPENDENCY ( REGS ); HDL_DEPENDENCY ( DEVBLK ); } END_DEPENDENCY_SECTION; /* The registration exports labels and their associated entry points to hercules, such that the symbols and associated entry points may be known to hercules and any other module that may have been loaded. The registration section is called once during module load. If we have registered a function that is also called from this DLL, then it must also be listed in the resolver section. This to ensure that the symbol is properly resolved when other modules are loaded. The registration section is optional. */ HDL_REGISTER_SECTION; { /* These are the entry points we export to Hercules All functions and labels used this dll must be static and non exportable, this to ensure that no foreign names are included by the system loader on systems that provide back-link support (mostly *nix systems) */ HDL_REGISTER ( daemon_task, external_gui_interface ); HDL_REGISTER ( debug_cpu_state, gui_cpu_state ); HDL_REGISTER ( panel_command, ProcessCommand ); } END_REGISTER_SECTION; /* The resolver section imports the entry points of symbols that have been previously registered. When a symbol is requested that has not been previously registered then the resolve function will search the loaded modules for that symbol, and register it implicitly. This latter function is mainly provided to support systems that do not have back-link support (most notably Cygwin). Entry points that are resolved should be indirect pointers, for example the panel_command routine is defined as: void *(*panel_command)(char *) The resolver may be called multiple times, the first time it is called is during module load, immediately after the registration section is called. It is subsequently called when other modules are loaded or unloaded. When a symbol cannot be resolved it will be set to NULL. The resolver section is optional. */ HDL_RESOLVER_SECTION; { /* These are Hercules's entry points that we need access to these may be updated by other loadable modules, so we need to resolve them here. */ HDL_RESOLVE ( panel_command ); HDL_RESOLVE ( debug_cpu_state ); HDL_RESOLVE_PTRVAR ( my_sysblk_ptr, sysblk ); } END_RESOLVER_SECTION; /* The device section is to register device drivers with hercules. It associates device types with device handlers If a device handler is not registered for a specific device type then and a loadable mode with the name of "hdtxxxx" (where xxxx is the device type) exists then that module is loaded Search order: 1) The most recently registered (ie loaded) device of the requested device type. 2) Device driver in external loadable module, where the module name is hdtxxxx (where xxxx is the device type ie module name hdtlcs for device type LCS or hdt2703 for device type 2703) 3) If the device is listed in the alias table (hdteq.c) then external module hdtyyyy will be loaded, where yyyy is the base name as listed in hdteq.c. The device name is always mapped to lower case when searching for loadable modules. The device section is optional */ HDL_DEVICE_SECTION; { HDL_DEVICE(1052,constty_device_hndinfo); HDL_DEVICE(3215,constty_device_hndinfo); } END_DEVICE_SECTION; /* The final section is called once, when the module is unloaded or when hercules terminates. A dll can reject being unloaded by returning a non-zero value in the final section. The final section is intended to be used to perform cleanup or indicate cleanup action to be taken. It may set a shutdown flag that is used within this dll that all local functions must now terminate. The final section is optional */ HDL_FINAL_SECTION; { } END_FINAL_SECTION; Below is Fish's sample code... /* Define version dependencies that this module requires... ** ** The following are the various Hercules structures whose layout your ** module depends on. The layout of the following structures (size and ** version) MUST match the layout that was used to build Hercules with. ** If the size/version of any of the following structures changes (and ** a new version of Hercules is built using the new layout), then YOUR ** module must also be built with the new layout as well. The layout of ** the structures as they were when your module is built MUST MATCH the ** layout as it was when the version of Hercules you're using was built. ** Further note that the below HDL_DEPENDENCY_SECTION is actually just ** a function that the hdl logic calls, and thus allows you to insert ** directly into the below section any specialized 'C' code you need. */ HDL_DEPENDENCY_SECTION; { HDL_DEPENDENCY(HERCULES); HDL_DEPENDENCY(REGS); HDL_DEPENDENCY(DEVBLK); HDL_DEPENDENCY(SYSBLK); HDL_DEPENDENCY(WEBBLK); } END_DEPENDENCY_SECTION; /* Register re-bindable entry point with resident version, or UNRESOLVED ** ** The following section defines the entry points within Hercules that ** your module is overriding (replacing). Your module's functions will ** be called by Hercules instead of the normal Hercules function (if any). ** The functions defined below thus provide additional/new functionality ** above/beyond the functionality normally provided by Hercules. Be aware ** however that it is entirely possible for other dlls to subsequently ** override the same functions that you've overridden such that they end ** up being called before your override does and your override may thus ** not get called at all (depending on how their override is written). ** Note that the "entry-point name" does not need to correspond to any ** existing variable or function (i.e. the entry-point name is just that: ** a name, and nothing more. There does not need to be a variable defined ** anywhere in your module with that name). Further note that the below ** HDL_REGISTER_SECTION is actually just a function that the hdl logic ** calls, thus allowing you to insert directly into the below section ** any specialized 'C' code that you may need. */ HDL_REGISTER_SECTION; { /* register this as the address of entry-point name, this var or func */ HDL_REGISTER( panel_command, my_panel_command ); HDL_REGISTER( panel_display, my_panel_display ); HDL_REGISTER( some_exitpoint, UNRESOLVED ); } END_REGISTER_SECTION; /* Resolve re-bindable entry point on module load or unload... ** ** The following entries "resolve" entry points that your module ** needs. These entries define the names of registered entry points ** that you need "imported" into your dll so that you may call them ** directly yourself. The HDL_RESOLVE_PTRVAR macro is used to auto- ** matically set one of your own pointer variables to the registered ** entry point's currently registered value (usually an address of ** a function or variable). Note that the HDL_RESOLVER_SECTION is ** actually just a function that the hdl logic calls, thus allowing ** you to insert directly into the below section any specialized 'C' ** code that you may need. */ HDL_RESOLVER_SECTION; { /* Herc's registered entry points that you need to call directly yourself */ HDL_RESOLVE( config_command ); HDL_RESOLVE( some_exitpoint ); HDL_RESOLVE( debug_cpu_state ); HDL_RESOLVE( debug_program_interrupt ); HDL_RESOLVE( debug_diagnose ); /* The following illustrates how to use HDL_RESOLVE_PTRVAR macro to retrieve the address of one of Herc's registered entry points. Your pointer- Herc's registered variable name entry-point name */ HDL_RESOLVE_PTRVAR( my_sysblk_ptr, sysblk ); } END_RESOLVER_SECTION; /* The following section defines what should be done just before ** your module is unloaded. It is nothing more than a function that ** is called by hdl logic just before your module is unloaded, and ** nothing more. Thus you can place any 'C' code here that you want. */ HDL_FINAL_SECTION; { my_cleanup(); } END_FINAL_SECTION; /* DYNDIAG.C (c) Copyright Jan Jaeger, 2003 */ /* Hercules Dynamic Loader */ /* Sample diagf14 dll routine */ /* */ /* Assembler to call routine: */ /* */ /* LRA R1,=CL32'test' */ /* LRA R2,=X'01020304' USERPARM */ /* DC X'83120F14' DIAG R1,R2,X'F14' */ /* */ #include "hercules.h" #include "opcode.h" #include "inline.h" void ARCH_DEP(diagf14_test) (int r1, int r3, REGS *regs) { U32 r3loc; logmsg("diagf14: r3 = %8.8X\n",regs->GR_L(r3)); r3loc = ARCH_DEP(vfetch4) (regs->GR_L(r3), USE_REAL_ADDR, regs); logmsg("diagf14: *r3 = %8.8X\n",r3loc); } #if !defined(_GEN_ARCH) #if defined(_ARCHMODE2) #define _GEN_ARCH _ARCHMODE2 #include "dyndiag.c" #endif #if defined(_ARCHMODE3) #undef _GEN_ARCH #define _GEN_ARCH _ARCHMODE3 #include "dyndiag.c" #endif HDL_DEPENDENCY_SECTION; { HDL_DEPENDENCY (HERCULES); HDL_DEPENDENCY (REGS); HDL_DEPENDENCY (DEVBLK); HDL_DEPENDENCY (SYSBLK); } END_DEPENDENCY_SECTION; HDL_REGISTER_SECTION; { HDL_REGISTER(s370_diagf14_test,s370_diagf14_test); HDL_REGISTER(s390_diagf14_test,s390_diagf14_test); HDL_REGISTER(z900_diagf14_test,z900_diagf14_test); } END_REGISTER_SECTION; HDL_RESOLVER_SECTION; { } END_RESOLVER_SECTION; HDL_FINAL_SECTION; { } END_FINAL_SECTION; #endif /*!defined(_GEN_ARCH)*/ /* END DYNDIAG.C */ /* DYNCGI.C (c)Copyright Jan Jaeger, 2002-2003 */ /* HTTP cgi-bin routines */ /* This file contains cgi routines that may be executed on the */ /* server (ie under control of a hercules thread) */ /* */ /* */ /* Dynamically loaded cgi routines must be registered under the */ /* pathname that they are accessed with (ie /cgi-bin/test) */ /* All cgi pathnames must start with /cgi-bin/ */ /* */ /* */ /* The cgi-bin routines may call the following HTTP service routines */ /* */ /* char *cgi_variable(WEBBLK *webblk, char *name); */ /* This call returns a pointer to the cgi variable requested */ /* or a NULL pointer if the variable is not found */ /* */ /* char *cgi_cookie(WEBBLK *webblk, char *name); */ /* This call returns a pointer to the cookie requested */ /* or a NULL pointer if the cookie is not found */ /* */ /* char *cgi_username(WEBBLK *webblk); */ /* Returns the username for which the user has been authenticated */ /* or NULL if not authenticated (refer to auth/noauth parameter */ /* on the HTTPPORT configuration statement) */ /* */ /* char *cgi_baseurl(WEBBLK *webblk); */ /* Returns the url as requested by the user */ /* */ /* void html_header(WEBBLK *webblk); */ /* Sets up the standard html header, and includes the */ /* html/header.htmlpart file. */ /* */ /* void html_footer(WEBBLK *webblk); */ /* Sets up the standard html footer, and includes the */ /* html/footer.htmlpart file. */ /* */ /* int html_include(WEBBLK *webblk, char *filename); */ /* Includes an html file */ /* */ /* */ /* Jan Jaeger - 28/03/2002 */ #include "hstdinc.h" #include "hercules.h" #include "devtype.h" #include "opcode.h" #include "httpmisc.h" #if defined(OPTION_HTTP_SERVER) void cgibin_test(WEBBLK *webblk) { html_header(webblk); hprintf(webblk->hsock, "

Sample cgi routine

\n"); html_footer(webblk); } HDL_DEPENDENCY_SECTION; { HDL_DEPENDENCY(HERCULES); // HDL_DEPENDENCY(REGS); // HDL_DEPENDENCY(DEVBLK); // HDL_DEPENDENCY(SYSBLK); HDL_DEPENDENCY(WEBBLK); } END_DEPENDENCY_SECTION; HDL_REGISTER_SECTION; { HDL_REGISTER( /cgi-bin/test, cgibin_test ); } END_REGISTER_SECTION; HDL_RESOLVER_SECTION; { } END_RESOLVER_SECTION; HDL_FINAL_SECTION; { } END_FINAL_SECTION; #endif /*defined(OPTION_HTTP_SERVER)*/ hercules-3.07/README.HERCLOGO000644 000765 000765 00000004614 11143760543 017035 0ustar00jmaynardjmaynard000000 000000 Customizable hercules 3270 Logo The initial welcome screen presented when a TN 3270 terminal connects to a hercules 3270 device can now be customized. The customized logo is stored in a plain text file which contains positioning orders, attributes and variable substitutions. hercules also contains a built-in logo should no suitable file be found. Upon startup, hercules will first look for a file named "herclogo.txt" in the current directory. The name of the logo file can also be specified as a startup option by using the '-b' flag. Additionally, the file may also be specified by using the 'HERCLOGO' configuration statement. (NOTE : The statement was previously LOGOFILE, but LOGOFILE has been deprecated). The file may also be specified by using the 'HERCLOGO' environment variable. The file to be used can also be specified at run time using the 'HERCLOGO' panel command. Each line in the file represent either an order or a plain text line. The orders are as follows : @SBA X,Y Position the current buffer position to Row X col Y (X and Y start at 0) @SF [H][P] Set the Highlight and/or Protected attribute @NL Forces going to the next line @ALIGN NONE|LEFT|RIGHT|CENTER Specified the text alignement (relative to the left and right borders of the terminal). When ALIGN is other than "NONE", a new line is automatically inserted after each line of text. If ALIGN is "NONE", then the text will be written without skipping to the next line. It is also possible to embbed substitution variables in outgoing text. Substition is indicated by enclosing the variable name between $( and ) The following variables are defined in that environment : VERSION : The hercules version HOSTNAME : The host name on which hercules is running HOSTOS : The host operating system HOSTOSREL : The Host operating system release HOSTOSVER : The host operating system version HOSTARCH : The host architecture HOSTNUMCPUS : UP (for 1) or MP=X (for more than 1) LPARNAME : The LPAR name specified in the configuration file CCUU,ccuu,CUU,cuu : Various forms of the device number of the terminal CSS : The Logical Channel Subsystem Set or Channel Set for the terminal SUBCHAN : The Subchannel number for the terminal Additionally, it is also possible to specify environment variable names. The file 'herclogo.txt' is provided in the distribution as a sample template. It reflects the contents of the built-in logo. Ivan Warren 3/1/2006 hercules-3.07/README.ISSUES000644 000765 000765 00000007317 11143760543 016651 0ustar00jmaynardjmaynard000000 000000 Please update this file whenever appropriate! Unresolved Issues ================= *** XXX *** Marks the functional subsystem affected *** TAPE DEVICE HANDLER *** CE+DE on tape rewind-unload: Technically, they should be presented separately to the guest o/s: CE upon completion the actual rewind-unload CCW and then DE once the tape actually finishes unloading, but doing so is somewhat problematic especially for SCSI tapes. (Might be possible to do for AWS/HET tapes but I haven't looked into it yet). Addendum (Ivan 2004/10/02) Final DE on Rewind Unload must be accompanied by UC (Unit Check) (all D/Ts) and possibly CUE (Control Unit End) for 3420 (3803 CU Type, to indicate an end of Control Unit Busy condition). It is possible the CUE should only occur if a BUSY was presented at some point, but I am not 100% sure about that (and that's not supported either - as we don't support shared CUs). However, VM/370 for example insists that CUE be presented. On the same line, VM/370 DDR is failing on Rewind unload. This could be part of the above problem. *** I/O SUBSYSTEM *** Incorrect Channel program check reporting (Ivan 2004/10/02) Because of the current I/O design, where we prefetch all write data prior to issuing the I/O, program check is presented unconditionally (except for immediate commands which are declared as such by the device handlers) - while it should only be presented if the control unit (device handler) attempts to consume data from the offending address. *** DEVICE HANDLERS *** Some units still returning CE+DE+UC on not-ready conditions (Ivan 2004/10/02) I/O architecture requires non-ready units to return UC only. This is done at the device handler lever and has not been implemented in all device handlers *** TAPE DEVICE HANDLER *** AWS handler fails to read FLEX Generated AWS files (Ivan 2004/10/02) The current AWS handler is not capable of processing multi-segment blocks. However, this can be bypassed by forcing the use of the HET handler which is backward compatible. *** I/O SUBSYSTEM *** I/O Subsystem reset/Device reset not always effective (Ivan 2004/10/02) The I/O subsystem reset function does not actually send a reset signal (as described in 17.2.2.2 in POO) to the device handlers. If an I/O is in progress, it will not be terminated. Subsequently, if status is stacked after the I/O reset, the device may be left in an unusable state, with status pending and E bit off effectivelly preventing an MSCH to be issued with the E bit on - requiring a Power On Reset (hercules stop and start). Only ESA/390 and ESAME are affected. *** Hardware panel *** Change to Enter key function (Ivan 2004/10/02) Pressing enter while in single step mode used to be the equivalent of pressing the start button (which was quite handy for debugging). It now displays the last commands typed. Instead, 'start' must be typed every time to execute the next instruction. *** Codepage translator *** Specifying some codepages produce garbled output and/or crash hercules (Ivan 2004/10/12) Specifying some codepages (mostly complex type codepages such as unicode) can lead to various output issues and crashes. This is because hercules only uses a single "iconv" descriptor while multiple threads may be attempting to use this descriptor, something that is specifically forbidden by the iconv API. hercules-3.07/README.MINGW000644 000765 000765 00000062251 11143760543 016515 0ustar00jmaynardjmaynard000000 000000 ****************************************************************** ****************************************************************** NOTE! This file is OBSOLETE and should probably be deleted! Once we got Herc to build successfully using MSVC, I/we stopped all effort on trying to make sure it continued to build under MinGW. At this late stage I doubt it will build at all under MinGW! That is to say, it more than likely will NOT build under MinGW, and thus the reason why this README should be deleted. The only reason I haven't deleted it yet is simply because of its historical value since it might be beneficial to someone should they decide to try on their own to get Herc to build under MinGW. -- Fish ****************************************************************** ****************************************************************** ------------------------- > > > N O T E < < < ------------------------- While the below information is probably reasonably accurate, it should be noted that building Herc with MinGW may no longer work. (It hasn't been tested in a long time). The prefered method (and indeed the only SUPPORTED method) for building the Win32 version of Hercules is via Microsoft's free compiler toolkit as explained in the README.MSVC document. The below information is mostly for historical purposes. ****************************************************************** ****************************************************************** MINGW PORTING NOTES: ./configure --enable-fthreads --disable-shared --enable-static \ --disable-nls --disable-dynamic-load --disable-external-gui ./configure --enable-fthreads --disable-shared --enable-static \ --disable-nls --disable-dynamic-load --disable-external-gui \ --enable-debug --enable-optimization="-O0 -g" ****************************************************************** ****************************************************************** ================================================================ ================================================================ INSTALLING MSYS + MINGW ================================================================ ================================================================ -------------------------------------------------------------- http://www.mingw.org/download.shtml 1. Install MSYS-1.0.10.exe --> d:/msys/1.0 2. Install msysDTK-1.0.1.exe --> d:/msys/1.0 3. Install MinGW-3.1.0-1.exe --> d:/MinGW In that order! -------------------------------------------------------------- Create /etc/fstab to point to the mingw dir: #Win32_Path Mount_Point d:/mingw /mingw -------------------------------------------------------------- Create .inputrc in home dir with desired terminal settings. #-------------------------------------------------------------------------------- # Fish: The following from: http://www.ibb.net/~anne/keyboard/keyboard.html#Bash #-------------------------------------------------------------------------------- "\e[3~": delete-char # this is actually equivalent to "\C-?": delete-char # VT "\e[1~": beginning-of-line "\e[4~": end-of-line # kvt "\e[H":beginning-of-line "\e[F":end-of-line # rxvt and konsole (i.e. the KDE-app...) "\e[7~":beginning-of-line "\e[8~":end-of-line # --- (eof) --- -------------------------------------------------------------- Update /etc/profile with desired aliases # ------- Fish's preferences... ------- export HISTCONTROL=ignoredups alias less='less -r' # alias rm='rm -i' alias whence='type -a' alias ls='ls -F --color=tty' alias dir='ls --color=auto --format=vertical' alias vdir='ls --color=auto --format=long' alias ll='ls -l' alias la='ls -A' alias l='ls -CF' alias cls='clear' # --- (eof) --- -------------------------------------------------------------- (((Optional: you only need to do the following (if desired) if you plan on using the provided msys shell window (NOT recommended) instead of your own MSYS Command Prompt window (HIGHLY recommended) which I explain how to do in the next step just below))))... Make a copy of the 'msys.bat' file in "d:\msys\1.0" and update it with your prefered colors and window geometry settings: rem (deleted by Fish) if "x%MINGW32BGCOLOR%" == "x" set MINGW32BGCOLOR=LightYellow rem (deleted by Fish) if "x%MINGW32FGCOLOR%" == "x" set MINGW32FGCOLOR=Navy rem (replaced with the following instead) if "x%MINGW32BGCOLOR%" == "x" set MINGW32BGCOLOR=Black if "x%MINGW32FGCOLOR%" == "x" set MINGW32FGCOLOR=#C0C0C0 rem (deleted by Fish) start rxvt -backspacekey . -sl 2500 -fg %FGCOLOR% -bg %BGCOLOR% -sr -fn Courier-12 -tn msys -geometry 80x25 -e /bin/sh --login -i rem (replaced with the following instead) start rxvt -backspacekey . -sl 2500 -fg %FGCOLOR% -bg %BGCOLOR% -sr -fn Courier-12 -tn msys -geometry 100x50 -e /bin/sh --login -i *** IMPORTANT NOTE! *** Be VERY CAREFUL when modifiying the above "start rxvt..." line! The actual .BAT file contains an embedded backspace character which does not appear on the above example statements! Do NOT use the above example statements as-is! Instead, use notepad to manually edit the .bat file itself (being very careful when you do!). ALSO, it's important to MAKE A COPY of the msys.bat file and make your changes to it. This is because the MSYS.BAT file is REPLACED whenever msys/mingw is updated! Thus, if you fail to make your own copy of it, your changes will be lost!! -------------------------------------------------------------- MINGW Command Prompt As an alternative to the crappy 'GNU' shell window used by default by MSYS (rxvt?), it's easy enough to setup a native WinNT Command Prompt window to be your "shell window" instead. First, create a .bat (batch) file in the 'd:\msys\1.0' directory called, for example, "fish_msys.bat" (try NOT to use a name with spaces in it!), with the following statements in it: @echo off SET CYGWIN="tty binmode title strip_title" codepage:oem D: chdir \msys\1.0\bin bash --login -i Yep! That's right. We're setting a 'CYGWIN' environment variable with the above batch file. The msys/mingw package was ported FROM Cygwin after all, so, interestingly enough, the above does indeed do what one expects it to: displays the name of the program being executed in the window title ('title'), but with the path removed ('strip_title'), just like Cygwin's shell window does. Next, make a copy of Windows's "Command Prompt" shortcut and modify it as desired (width, height, etc -- i.e. the window's 'layout'). To turn it into a MINGW Command Prompt window (instead of the native WinNT Command Prompt window it starts out as), simply modify the shortcut's "Properties" as follows: Target: D:\msys\1.0\fish_msys.bat Start in: D:\msys\1.0\bin Comment: MINGW Command Prompt Optional: Click the "Change Icon..." button, followed by the "Browse..." button, and navigate to the root MSYS directory ("D:\msys\1.0") and select the desired icon ("m.ico" or "msys.ico"). DONE!! Now whenever you click on that shortcut, Windows will open a normal Command Prompt window with the MINGW (MSYS) shell already started! Your working directory will automatically be you 'home' directory, and you'll be able to enter whatever shell commands and/or execute any shell scripts you need, and the name of the program that's being executed (without the path) will be displayed in the window's title! COOL!! :)) (and MUCH better than the crappy window msys/mingw provides IMO) -------------------------------------------------------------- (Optional): Create a symbolic link for bash. "sh.exe" is actually bash (at least according to the msys docu- mentation), so symlink 'bash.exe' to 'sh.exe': ln -s sh.exe bash.exe so all of your scripts that start with #!/bin/bash will work. -------------------------------------------------------------- The handling of quotes on command-lines is different in the msys shell than it is with cygwin. Thus whereas: ./configure --enable-custom="value with spaces" used to work fine with cygwin, it no longer works with the msys shell. Instead, you need to use MICROSOFT command-line escape rules, and enter the command as follows instead: ./configure --enable-custom=\"value with spaces\" Note: as far as I know this only applies to manually entering commands in the msys shell window (i.e. at the command prompt). I don't believe it applies (i.e. I believe it does NOT apply) to scripts that happen to issue shell commands for example. -------------------------------------------------------------- (Optional): Create the '/usr/local/bin' directory so you can use all of your previously created scripts and private override programs, etc. NOTE: the "d:/msys/1.0" directory is actually the "/usr" directory[*]. Thus, to add our own "/usr/local/bin" directory, we need to create a "d:/msys/1.0/local/bin" directory. ----------- * As well as the '/' root directory too, interestingly/confusingly enough! Refer to the "Automatic file system maps" table in the "README.rtf" document in the "D:\msys\1.0\doc\msys" directory for details regarding hard-coded mount points. -------------------------------------------------------------- Do a hercules 'cvslvlck' to make sure you have everything that autoconf needs... Fish@SYSTEM2 ~ $ cd hercules Fish@SYSTEM2 ~/hercules $ cd util Fish@SYSTEM2 ~/hercules/util $ cvslvlck This utility will check the level of various utilities needed to build hercules. Checking is done against versions that are KNOWN to work. This doesn't mean a build will NOT succeed with older versions of the utilities, but will give a hint as to what package may need an upgrade if the build ever fails with some odd reason. OK cvs (informational), found 1.11 OK autoconf requires 2.5, found 2.56 OK automake requires 1.6, found 1.7.1 INSTALL flex not found URL: http://www.gnu.org/directory/flex.html OK gawk requires 3.0, found 3.0.4 OK gcc requires 2.95, found 3.2.3 INSTALL gettext not found URL: http://www.gnu.org/directory/gettext.html OK grep requires 0, found 2.5.1 INSTALL iconv not found URL: http://www.gnu.org/directory/libiconv.html For first-time Libiconv installs, a recompile and reinstall of gettext is recommended. Source: libiconv-1.8/README OK m4 requires 0.0, found 1.4 OK make requires 3.79, found 3.79.1 OK perl requires 5.6, found 5.6.1 OK sed requires 3.02, found 3.02 Do you wish to set CVSROOT for this userid? (y, n, default y) New CVS users are recommended to reply y to this prompt. n Hercules CVSROOT=:pserver:anonymous@cvs.hercules-390.org:/usr/cvs/hercules -------------------------------------------------------------- "http://sourceforge.net/projects/gnuwin32/" lists MANY GnuWin32 packages. Use the "Download" link in the FAR RIGHT COLUMN to download the following needed packages: +------------------------------------------------------- | | *** FISH ADDENDUM -- Feb 2005 **** | | The below "instructions" are WRONG(?) (I think) | as far as the copying/installation is concerned. | | I now believe the PROPER way to "install" an | external package meant for MSYS is to simply un- | zip it (extract it) directly into the main msys | directory, letting WinZip (or whatever zip util | you happen to be using), allowing it to automatically | overlay whatever files it needs to overlay/replace | and allowing it to automatically create whatever | directories it needs to create (as needed according | to whatever is contained in the zip file). | | I haven't yet tried it myself yet, but I believe | that's all you need to do: unzip into msys and | that's it. (But as I said, I haven't confirmed | that yet). | | So in the below instructions, try: | | replace: "copy to /usr/local/bin" | with: "unzip into msys" | | instead. | +------------------------------------------------------- gettext-0.14.1-bin.zip contains "gettext.exe" (and many other exes/dlls) in the 'bin' directory copy "gettext.exe" (and many other exes/dlls) to /usr/local/bin. (Recall that according to msys documentation the "d:/msys/1.0" directory is actually your '/usr' directory) gettext-0.14.1-dep.zip contains "libiconv2.dll" in the 'bin' directory needed by gettext.exe copy "libiconv2.dll" to /usr/local/bin libiconv-1.8-1-bin.zip contains "iconv.exe" and most (but not all!) support dlls in the 'bin' directory copy "iconv.exe" and most (but not all!) support dlls to /usr/local/bin libintl-0.11.5-2-bin.zip contains "libintl-2.dll" in the 'bin' directory needed by iconv.exe copy "libintl-2.dll" to /usr/local/bin. --------------------------------------- Do we need the below?? I'm thinking that maybe we might for linking Herc --------------------------------------- libiconv-1.8-1-lib.zip contains ".a" and ".lib" files in the 'lib' directory used to link hercules with copy ".a" and ".lib" files to ??????? contains *.h files in the 'include' directory used to compile hercules with copy *.h files to ??????? ================================================================ ================================================================ HERCULES MODIFICATIONS ================================================================ ================================================================ --------------------------------------- >>> NLS disabled for the time being <<< --------------------------------------- I keep getting errors when the intl directory is built: plural.y: In function `__gettextlex': plural.y:263: error: argument "pexp" doesn't match prototype plural.y:69: error: prototype declaration plural.y: In function `__gettexterror': plural.y:407: error: argument "str" doesn't match prototype plural.y:70: error: prototype declaration plural.y: At top level: plural.y:406: warning: unused parameter 'str' For the time being I'm skipping past it via "--disable-nls" but it needs to be looked into. -------------------------------------------------------------- No biggee, but '-traditional-cpp', while originally (and for now) added (by Jay?) specifically for Apple builds, doesn't work for non-Apple builds. (I tried it.) It keeps issuing warnings regarding extra tokens on #endif and #include statements. I added '-Wno-endif-labels" to get rid of the warnings for #endifs, but can't find an option to suppress the warnings for #includes! But as I said, it's not a big problem right now since, as it's coded right now, we're only adding '-traditional-cpp' for Apple and ONLY for Apple builds. Note too, that we COULD get rid of all such warnings by simply coding our comments (on #endif and #include statements) using /* */ instead of //, but I'm too lazy to change them all right now; maybe later if I'm in the mood... -------------------------------------------------------------- Created 'hthreads.h', 'hostopts.h', w32util.h/c'. 'hostopts.h' now contains the host specific options that used to be in featall.h. (I want to try and place all host- specific tests in one convenient place, replacing all #ifdef WIN32 and #ifdef __APPLE__, etc tests with #ifdef FEATURE_XXX. Doing that is more portable and makes porting efforts easier. -------------------------------------------------------------- I was hoping to avoid having to do it, but in the end I had no other choice; trying to keep it was simply causing too much trouble and making the code too sloppy trying to finagle things to try and keep it. Soooooo..... I had to rename the Hercules 'DWORD' type to 'DBLWRD' so as to not conflict with Microsoft's existing DWORD typedef. I kept the HWORD and FWORD typedefs as-is. -------------------------------------------------------------- sie.c: added "#if !defined(NO_SIGABEND_HANDLER)": DEF_INST(start_interpretive_execution) ... logmsg (_("HHCCP079E CPU%4.4X: calloc failed... ... #if !defined(NO_SIGABEND_HANDLER) signal_thread(sysblk.cputid[regs->cpuad], SIGUSR1); #endif ... -------------------------------------------------------------- ieee-w32.h: Changed all instances of: u_int32_t to: uint32_t since that seems to be the "Hercules standard" according to what I can see in the 'htypes.h' header. (Same with 'u_int64_t' too: changed them all to 'uint64_t'). -------------------------------------------------------------- cckddasd, cckdutil, etc... Created: 'get_file_accmode_flags' --> "Poor man's" fcntl( fd, F_GETFL ) (only returns access mode flags not any others...) -------------------------------------------------------------- Created: 'hconsts.h', 'hmacros.h', 'hstructs.h', 'hexterns.h' to make "hercules.h" smaller/simpler and to basically make things a bit easier to maintain... (helps to keep things more organized IMO) -------------------------------------------------------------- commadpt.c: rc = fcntl( tempfd, F_GETFL ); rc |= O_NONBLOCK; fcntl( tempfd, F_SETFL, rc ); Changed to: socket_set_blocking_mode(tempfd,0); Also created: 'socket_init()' and 'socket_deinit()' functions since Windows Socket 2 requires calling 'WSAStartup' and 'WSACleanup'. (calls are in 'impl' function in impl.c) -------------------------------------------------------------- Started trying to remove all #ifdef WIN32, etc, and replace with #ifdef XXXXX (where 'XXXX' is some feature name), (see next item for good example), but haven't finished yet... -------------------------------------------------------------- hercifc.c: ctc_ctci.c: ctc_lcs.c: tuntap.c: Changed #ifndef __APPLE__ with #ifdef OPTION_TUNTAP_SETNETMASK, etc, and #defined or #undef'ed OPTION_TUNTAP_SETNETMASK, etc as needed in new 'hostopts.h' member. -------------------------------------------------------------- feature.h: I see: #if defined(WIN32) && !defined(__WORDSIZE) #define __WORDSIZE 32 #endif but __WORDSIZE doesn't seem to be used at all (there are a few statements but they're commented out). Can this be safely removed?? (it probably cam, but I'm thinking it might be something in preparation for 64-bit builds, which is why I'm asking) -------------------------------------------------------------- vm.c: void ARCH_DEP(extid_call) (int r1, int r2, REGS *regs) ... /* Bytes 16-23 contain the userid in EBCDIC */ #if defined( HAVE_GETLOGIN_R ) memset( unam, 0, sizeof(unam) ); VERIFY( getlogin_r ( unam, sizeof(unam) ) == 0 ); puser = unam; #else puser = ""; #endif for (i = 0; i < 8; i++) { c = (*puser == '\0' ? SPACE : *(puser++)); buf[16+i] = host_to_guest(toupper(c)); } -------------------------------------------------------------- You will see a LOT of "comparison between signed and unsigned" warnings during the build (esp. in 'commadpt.c' for example) due to Microsoft's 'FD_SET' macro implementation. There's no simple way to work around it so just ignore it for now... -------------------------------------------------------------- tapedev.c: Had to make extensive modifications to 'mountnewtape' function due to non-existence of regular expression library in MinGW. Luckily the patterns we're checking for are rather simple, so it wasn't that difficult to do. My question is WHY we're doing it via regular expressions in the first place?? -------------------------------------------------------------- ctcadpt.c: Support for VMNET is gen'ed, but will not work until Win32 equivalent for 'fork' is developed. 'fork' simply returns -1 at the moment. ('fork' might take a while to port!) -------------------------------------------------------------- hdl.h: minor fix: check if LTDL_SHLIB_EXT defined too when #defining HDL_MODULE_SUFFIX. -------------------------------------------------------------- Various... (many different places...) Unfortunately, MinGW always links with Micro$oft's MSVCRT runtime library. Thus, all scanf/printf format flags must use the Micro$oft format, which, for 64-bit values, is completely different from the GNU format. GNU uses "%lld", "%llx", %16.16llX, etc. whereas Micro$oft uses "%I64d", "%I64x", %16.16I64X, etc. Thus I had to #define the following (in 'hconsts.h'): #ifdef WIN32 # define LL_FMT "I64" #else # define LL_FMT "ll" #endif and change all occurrences of: "%lld" with: "%"LL_FMT"d" which is so UGLY beyond belief it's pitiful. :( -------------------------------------------------------------- (Various): workaround inability to redirect 'stdout'... The logger thread in logger.c redirects the write end of the logmsg pipe into STDOUT via dup2, but unfortunately, the way I'm currently handling the logmsg pipes for this MinGW port (wherein the pipe is actually just a socketpair connected to each other), that technique no longer works (since in Win32 you can't do 'dup2' on sockets) and thus I have it commented out (since we actually don't really need to do the dup2 at all as long as everyone uses the 'logmsg' macro for their i/o). Unfortunately however, the "display_version" function (and indirectly the "display_hostinfo" function which display_version calls) are coded to "fprintf" to whatever FILE* is passed (which is usually stderr for the utilities and stdout for Hercules (impl.c)). Thus, in those two places -- and only in those two places -- I had to code a duplicate 'print' call: one that fprintf'd to stderr, and the other to do a 'logmsg'. When the utilities call it (display_version), they pass stderr and I do fprintf to stderr, but when if stdout is passed (as it is when impl.c calls it), then I do a logmsg. I haven't thought whether there's an easier/better way to do things; I just want to get this damn port FINISHED for now! I can go back and clean things up later. Okay? *********************************************************************** *********************************************************************** *********************************************************************** ** TODO ** (( U N R E S O L V E D I S S U E S )) (moved to README.MSVC) *********************************************************************** *********************************************************************** *********************************************************************** From the MinGW 'FAQ' @ ... How can an MSVC program call a MinGW DLL, and vice versa? --------- Assume we have a testdll.h, testdll.c, and testmain.c. In the first case, we will compile testdll.c with MinGW, and let the MSVC-compiled testmain call it. You should use gcc -shared -o testdll.dll testdll.c \ -Wl,--output-def,testdll.def,--out-implib,libtestdll.a to produce the DLL and DEF files. MSVC cannot use the MinGW library, but since you already have the DEF file you may easily produce one by the Microsoft LIB tool: lib /machine:i386 /def:testdll.def Once you have testdll.lib, it is trivial to produce the executable with MSVC: cl testmain.c testdll.lib --------- Now for MinGW programs calling an MSVC DLL. We have two methods. One way is to specify the LIB files directly on the command line after the main program. For example, after cl /LD testdll.c use gcc -o testmain testmain.c testdll.lib The other way is to produce the .a files for GCC. For __cdecl functions (in most cases), it is simple: you only need to apply the 'reimp' tool from Anders Norlander (since his web site is no longer available, you may choose to download here a version enhanced by Jose Fonseca): reimp testdll.lib gcc -o testmain testmain.c -L. -ltestdll However, for __stdcall functions, the above method does not work. For MSVC will prefix an underscore to __stdcall functions while MinGW will not. The right way is to produce the DEF file using the 'pexports' tool included in the mingw-utils package and filter off the first underscore by sed: pexports testdll.dll | sed "s/^_//" > testdll.def Then, when using dlltool to produce the import library, add `-U' to the command line: dlltool -U -d testdll.def -l libtestdll.a And now, you can proceed in the usual way: gcc -o testmain testmain.c -L. -ltestdll Hooray, we got it. *********************************************************************** *********************************************************************** *********************************************************************** hercules-3.07/README.MSVC000644 000765 000765 00000027771 11143760544 016415 0ustar00jmaynardjmaynard000000 000000 ****************************************************************** ****************************************************************** NOTE! This file is OUT OF DATE and should probably be deleted! FOR MORE UP-TO-DATE INFORMATION, PLEASE REFER TO http://www.softdevlabs.com/Hercules/hercules-msvc-build.html OR http://www.cbttape.org/~fish/hercules-msvc-build.html ****************************************************************** ****************************************************************** ---------------------------------------------------------------- HOW TO BUILD HERCULES FOR WINDOWS WITH MICROSOFT VISUAL C ---------------------------------------------------------------- This file gives some hints on how you can build Hercules for the Microsoft Windows environment using the Visual C/C++ compiler, without the need for Cygwin or Mingw. ----------------------------------------------------------------------- SETTING UP THE ENVIRONMENT VARIABLES Run this .cmd file to set the PATH, INCLUDE, and LIB variables: @echo off path=%MSSdk%\bin\Win64;%PATH% Call "%VCToolkitInstallDir%vcvars32.bat" Call "%MSSdk%\setenv" /XP32 /RETAIL Additional Note regarding environment variables: if you are using the makefile.bat && makefile-dllmod.msvc to build Herc (see further below) you may also wish to define the ZLIB_DIR and BZIP2_DIR variables in order for Herc to support ZLIB && BZIP2 disk/tape compression. See also the "Note Regarding ZLIB_DIR" and "Obtaining ZLIB" sections further below (as well as the ones for BZIP2) for further information regarding building Herc with compression support. ----------------------------------------------------------------------- THE BUILD COMMAND Before you can build Hercules, you must install the Visual C++ compiler and the Windows SDK, as well as the msvcrt.lib file as explained below. As an alternative, you may install Visual Studio (version 7 or above) To build the MSVC version of Hercules: nmake /f makefile-dllmod.msvc The executable modules are placed in the msvc.dllmod.bin subdirectory. DOWNLOAD THE MICROSOFT VISUAL C++ COMPILER AND SDK http://msdn.microsoft.com/visualc/vctoolkit2003/ The Microsoft Visual C++ Toolkit 2003 includes the command line versions of the Visual C/C++ compiler and linker, as well as the standard C/C++ Library. http://www.microsoft.com/msdownload/platformsdk/sdkupdate/ The Windows Server 2003 Core SDK contains the include files and libraries needed to create applications for Win95/98/ME/NT/2000/XP. Notes: 1. You may need to add "download.microsoft.com" to the Internet Explorer trusted zone before you can install the SDK 2. You also need to download "Build Environment Intel 64 bit" to obtain the nmake utility in mssdk/bin/win64 ----------------------------------------------------------------------- HOW TO OBTAIN THE MSVCRT.LIB FILE If you want to build the DLL version of Hercules then you will also need the Microsoft file msvcrt.lib which is not included in the free Visual C++ Toolkit 2003. You can however obtain this file by downloading and installing the ".NET Framework Version 1.1 Software Development Kit (SDK)" which is available as a free download from: http://msdn.microsoft.com/netframework/downloads/updates/default.aspx Be aware, however, that this is a 108MB download, of which the only directory you need is c:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\lib After installation, copy msvcrt.lib from this directory to c:\Program Files\Microsoft Visual C++ Toolkit 2003\lib You may also want to copy nmake.exe and msvcr71.dll from C:\Program Files\Microsoft.NET\v1.1\Bin after which you can delete the .NET Framework SDK. ----------------------------------------------------------------------- GCC EXTENSIONS TO BE AVOIDED 1. Variadic macro definitions, eg #define logmsg(format,parms...) 2. __attribute__((unused)) should be replaced by UNREFERENCED macro 3. void* pointer arithmetic, eg (void*)p + 1 4. __attribute__((packed)) ----------------------------------------------------------------------- C99 EXTENSIONS TO BE AVOIDED 1. Field names in structure initialisers. --rbowler ----------------------------------------------------------------------- How to build Hercules using Visual Studio IDE: Please see Fish's detailed instructions at: http://www.softdevlabs.com/Hercules/hercules-msvc-build.html ----------------------------------------------------------------------- *** NOTE REGARDING PRECOMPILED HEADERS *** EACH AND EVERY source file must start with : #include "hstdinc.h" These contain the system headers (those enclosed in <>) and that are not dependent on the guest architecture. This file, along with build_pch.c allows building a precompiled header file that significantly speeds up the MSVC Windows build. I REPEAT !! EACH AND EVERY SOURCE FILE MUST START WITH THIS FILE !! No macros (#define).. No nothing. --Ivan ----------------------------------------------------------------------- *** NOTE REGARDING ZLIB_DIR *** ZLIB_DIR defines the location of the ZLIB libraries If ZLIB_DIR is undefined, then an attempt is made to locate the ZLIB library in winbuild\zlib\win32_32 If ZLIB_DIR contains a bad path, nmake exits with an error EXCEPT if ZLIB_DIR is set to the special keyword "NONE". ZLIB_DIR should contain the *BASE* path for ZLIB. That means that the following files are expected : - $(ZLIB_DIR)\zlib1.dll - $(ZLIB_DIR)\lib\zdll.lib - $(ZLIB_DIR)\include\zlib.h - $(ZLIB_DIR)\include\zconf.h REMEMBER TO "nmake clean" if the build type is changed, the ZLIB location modified, etc.. NOTE : The zlib1.dll Dynamic Link Library will be copied to the appropriate build target directory as part of the build process in order to ensure that the DLL is obtainable by the platform PE(*) loader at run time. --Ivan (*) PE stands for Program Executable and designates WIndows .EXE & .DLL executable file formats. *** Obtaining ZLIB *** Building from the distributed hercules source tree does not by default incorporate ZLIB as a compression mechanism, since 1) ZLIB is an external project, completelly separate from the hercules project itself. 2) MS Windows (tm) does not provide any well known location (if at all) for the ZLIB library runtime and/or header files. .. Therefore .. In order for HERCULES to be built with ZLIB support (DASD, TAPE), go to http://www.zlib.net - and locate the download for the 'zlib compiled DLL'. NOTE : This is a 75KB download. Extract that ZIP file to the winbuild\zlib\win32_32 directory, relative to the source directory. You may extract the file to an alternate location, and then set the ZLIB_DIR environment variable accordingly (as explained above). The hercules project is currently known to succesfully build with version 1.2.2 (current at the time of writing) of the ZLIB compression library. ZLIB is a compression algorithm written by Jean Loup Gailly and Mark Adler. ZLIB is used in the hercules project pursuant to the ZLIB License (http://www.zlib.net/zlib_license.html). In source form, the hercules project DOES NOT contain ZLIB. In Binary form, the hercules project MAY contain an UNMODIFIED version of the ZLIB runtime. --Ivan ----------------------------------------------------------------------- *** NOTE REGARDING BZIP2_DIR *** BZIP2_DIR defines the location of the BZIP2 libraries. If BZIP2_DIR is undefined, If BZIP2_DIR contains a bad path, nmake exits with an error EXCEPT if BZIP2_DIR is set to the special keyword "NONE". BZIP2_DIR should contain the *BASE* path for BZIP2. That means that the following files are expected: - $(BZIP2_DIR)\bzlib.h - $(BZIP2_DIR)\libbz2.lib - $(BZIP2_DIR)\libbz2.dll REMEMBER TO "nmake clean" if the build type is changed, the BZIP2_DIR location modified, etc.. NOTE : The libbz2.dll Dynamic Link Library will be copied to the appropriate build target directory as part of the build process in order to ensure that the DLL is obtainable by the platform PE(*) loader at run time. -- Fish (copied blatantly from Ivan's ZLIB documentation further above) (*) PE stands for Program Executable and designates WIndows .EXE & .DLL executable file formats. *** Obtaining BZIP2 *** Building from the distributed Hercules source tree does not by default incorporate BZIP2 as a compression mechanism, since 1) BZIP2 is an external project, completelly separate from the Hercules project itself. 2) MS Windows (tm) does not provide any well known location (if at all) for the BZIP2 library runtime and/or header files. .. Therefore .. In order for HERCULES to be built with BZIP2 support (DASD, TAPE), go to "http://www.bzip.org/downloads.html" and locate the hyperlink entitled: "Here is the 1.0.3 source tarball , which includes full documentation. md5: 8a716bebecb6e647d2e8a29ea5d8447f" (Yep, that's right! You're going to have to build the BZIP2 dll for yourself from source!) (either that or obtain a pre-built copy of it (and associated header/lib files) from someone else you trust). NOTE: This is a 650KB download, and the file is in tar.gz format, so you'll need WinZip or other utility to unzip it. Extract the files to a directory of your choosing and build the DLL using the supplied makefile.msc. Once it's built, then copy the resulting DLL, lib, and bzip2.h header file to your defined BZIP2_DIR location and rebuild Herc. BZIP2 is a freely available (open-source (BSD-style) license), patent free (as far as the author knows), high-quality data compressor written by Julian R Seward. It typically compresses files to within 10% to 15% of the best available techniques (the PPM family of statistical compressors), whilst being around twice as fast at compression and six times faster at decompression. In source form, the Hercules project does not contain any BZIP2 source code at all. In binary form however, the Hercules project may include an unmodified version of the BZIP2 runtime DLL in addition to its own distribution binaries. -- Fish (updated 2005-12-02) ----------------------------------------------------------------------- MSVC AND CRYPTO Bernard Van Der Helm's crypto modules (Message Security Assist 1 & 2 Feature) is now built automatically as part of the MSVC build. Should it be necessary to build a version *WITHOUT* the crypto DLL, it is possible to instruct the makefile-dllmod.msvc file to bypass building that particular code by defining the environment variable NOCRYPTO. Nov 22nd 2005 --Ivan Warren ----------------------------------------------------------------------- *** NOTE REGARDING PCRE_DIR *** The following is an excerpt from "makefile-dllmod.msvc" # --------------------------------------------------------------------- # To enable PCRE (Perl-Compatible Regular Expressions) support, first # download 'Binaries' and 'Developer files' packages from the GNUWin32 # PCRE website at: http://gnuwin32.sourceforge.net/packages/pcre.htm. # Then create a permanent directory somewhere called whatever you want # with a 'bin', 'lib' and 'include' subdirectory, and then define an # environment variable called "PCRE_DIR" pointing to that directory. # Finally, make sure the below names of the include (header), lib and # DLL names are correct, making whatever adjustments may be necessary. # --------------------------------------------------------------------- !IFDEF PCRE_DIR !IF "$(PCRE_DIR)" == "NONE" !UNDEF PCRE_DIR !ELSE PCRE_INCNAME = pcreposix.h PCRE_LIBNAME1 = pcre.lib PCRE_LIBNAME2 = pcreposix.lib PCRE_DLLNAME1 = pcre3.dll PCRE_DLLNAME2 = pcreposix3.dll PCRE_INCDIR = $(PCRE_DIR)\include PCRE_INCPATH = $(PCRE_DIR)\include\$(PCRE_INCNAME) PCRE_LIBPATH1 = $(PCRE_DIR)\lib\$(PCRE_LIBNAME1) PCRE_LIBPATH2 = $(PCRE_DIR)\lib\$(PCRE_LIBNAME2) PCRE_DLLPATH1 = $(PCRE_DIR)\bin\$(PCRE_DLLNAME1) PCRE_DLLPATH2 = $(PCRE_DIR)\bin\$(PCRE_DLLNAME2) Sep 22 2006 -- Fish ----------------------------------------------------------------------- hercules-3.07/README.NETWORKING000644 000765 000765 00000034140 11143760542 017316 0ustar00jmaynardjmaynard000000 000000 ----------------------------------------------------------------- Hercules Networking ----------------------------------------------------------------- *** Please read herctcp.html as Roger explains how *** *** to set up TCP/IP networking with Hercules. *** All of the communications emulation implemented within Hercules use a CTCA (Channel to Channel Adapter) type device. Depending on the "flavor", the CTCA device will provide either a point-to-point or a virtual network adapter interface to the driving system's TCP/IP stack or in the case of CTCT, a "true" CTCA connection to another instance of Hercules via a TCP/IP connection. All current emulations, with the exception of VMNET and CTCT use the Universal TUN/TAP driver on *nix and TunTap32 (WinPCap) on the Windows platforms which creates a network interface on the driving system which allow Hercules to present frames to, and receive frames from the TCP/IP stack. This network interface is configured on *nix platforms by the hercifc program which is invoked by Hercules after the TUN/TAP device is opened. The hercifc program runs as root. Please read herctcp.html for more information on the security implications of the hercifc program. Now for the gory details: --------------------------------------------------------------- *** Important information about changes to the *** *** Hercules configuration files - PLEASE READ *** The format of the Hercules configuration file statements for all of the networking emulations have changed from the previous releases of Hercules. The older format will still be accepted to maintain compatibility, however it is the recommendation of the maintainer that the new format be used. Also note that there is no distinction between the CTCI and CTCI-W32 modes any more, in fact CTCI-W32 does not exist in this release (other than to maintain compatibility with previous configuration files). --------------------------------------------------------------- *** Important information about changes to the *** *** Hercules configuration files - PLEASE READ *** In releases prior to Hercules version 3.00, all of the TCP/IP emulations required two addresses to be defined in the Hercules configuration file: one address for the read subchannel and the other for write. --------------------------------------------------------------- *** Important information about changes to the *** *** Hercules configuration files - PLEASE READ *** Hercules release version 3.00, however, [temporarily] changed the rules: With [ONLY!] version 3.00 of Hercules, only the FIRST address address need be specified in the configuration file. Hercules version 3.00 automatically creates the second address. Care must be taken to NOT define the second address [with Hercules version 3.00 ONLY!] or a configuration error will occur. --------------------------------------------------------------- *** Important information about changes to the *** *** Hercules configuration files - PLEASE READ *** Starting with Hercules version 3.01 however, we've gone back to doing things the way we ORIGINALLY were (and the way most users are used to (i.e. the way most users EXPECT things to work)): With Hercules version 3.01 you need to define BOTH addresses! Both the even numbered read device AS WELL AS the odd numbered write device must BOTH be defined in your Hercules configuration file starting with Hercules version 3.01. We apologize for the mess, but we thought having Herc automatically define the write device for you (as it does in version 3.00) would be easier for everyone. Turns out it caused a lot of problems with a lot of people, so we decided to go back to the original way. Again, we apologize for whatever headaches this may have caused anyone. --------------------------------------------------------------- *** Important information about changes to the *** *** Hercules configuration files - PLEASE READ *** Note that the VMNET and CTCT protocols have ALWAYS required BOTH addresses to be defined (i.e. ALL versions of Hercules, including version 3.00 as well, require BOTH even/odd read/write devices to be defined separately [in your Hercules configuration file]). --------------------------------------------------------------- The currently supported emulation modes are: CTCT - CTCA Emulation via TCP connection CTCI - Point-to-point connection to the host IP stack. LCS - LAN Channel Station (3172/OSA) VMNET - Point-to-point link via SLIP/VMNET ----------------------------------------------------------------- CTCT - Channel to Channel Emulation via TCP connection ----------------------------------------------------------------- This emulation mode provides protocol-independent communication with another instance of this driver via a TCP connection. This mode appears to the operating system running in the Hercules machine as an IBM 3088 Channel to Channel Adapter and can operate in either Basic or Extended mode. The configuration statement for CTCT is as follows: 3088 CTCT where: is the address of the CTCT device. is the TCP/IP port on the local system. is the IP address on the remote. is the TCP/IP port on the remote system. ----------------------------------------------------------------- CTCI - Channel to Channel link to Linux TCP/IP stack ----------------------------------------------------------------- This is a point-to-point link to the driving system's TCP/IP stack. From the point of view of the operating system running in the Hercules machine it appears to be a CTC link to a machine running TCP/IP for MVS or VM. CTCI uses the Universal TUN/TAP driver on *nix and Politecnico di Torino's WinPCap packet driver as well as Fish's TunTap32 and FishPack DLLs on Windows[1]. The configuration statement for CTCI is as follows: CTCI [options] where: is the address pair of the CTCI device. is the IP address of the Hercules (guest OS) side. is the IP address on the driving system. [options] can be any of the following: -n or --dev where is: [*nix] the name of the TUN/TAP special character device, normally /dev/net/tun. [Windows] is either the IP or MAC address of the driving systems network card. TunTap32 will automatically select the first network card it finds if this option is omitted, this may not be desirable for some users. -t or --mtu [*nix only] where is the maximum transmission unit size, normally 1500 -s or --netmask [*nix only] where is the netmask to be configured on the link. Note: Since this is a point-to-point link netmask is meaningless from the perspective of the actual network device. -m or --mac [Windows only] where is the optional hardware address of the interface in the format of either xx:xx:xx:xx:xx:xx or xx-xx-xx-xx-xx-xx. -k or --kbuff [Windows only] where is the size of the WinPCap kernel buffer size, normally 1024. -i or --ibuff [Windows only] where is the size of the WinPCap I/O buffer size, normally 64. -d or --debug this will turn on the internal debugging routines. Warning: This will produce a tremendous amount of output to the Hercules console. It is suggested that you only enable this at the request of the maintainers. ----------------------------------------------------------------- LCS - LAN Channel Station ----------------------------------------------------------------- This emulation mode appears to the operating system running in the Hercules machine as an IBM 8232 LCS device, an IBM 2216 router, a 3172 running ICP (Interconnect Communications Program), the LCS3172 driver of a P/390, or an IBM Open Systems Adapter. Rather than a point-to-point link, this emulation creates a virtual ethernet adapter through which the guest operating system running in the Hercules machine can communicate. As such, this mode is not limited to TCP/IP traffic, but in fact will handle any ethernet frame. The configuration statement for LCS is as follows: LCS [options] [] where: is the address pair of the LCS device. This pair must be an even-odd address. [] is an optional IP address of the Hercules (guest OS) side. Note: This is only used to establish a point-to-point routing table entry on driving system. If you use the --oat option, do not specify an address here. There are no required parameters for the LCS emulation, however there are several options that can be specified on the config statement: -n or --dev where is: [*nix] the name of the TUN/TAP special character device, normally /dev/net/tun. [Windows] is either the IP or MAC address of the driving systems network card. TunTap32 will automatically select the first network card it finds if this option is omitted, this may not be desirable for some users. -o or --oat where specifies the filename of the Address Translation file. If this option is specified, the optional and --mac entries are ignored in preference to statements in the OAT. (See below for the format of the OAT) -m or --mac where is the optional hardware address of the interface in the format: xx:xx:xx:xx:xx:xx -d or --debug this will turn on the internal debugging routines. Warning: This will produce a tremendous amount of output to the Hercules console. It is suggested that you only enable this at the request of the maintainers. If no Address Translation file is specified, the emulation module will create the following: An ethernet adapter (port 0) for TCP/IP traffic only. Two device addresses will be defined (devnum and devnum + 1). The syntax for the Address Translation file is as follows: ********************************************************* * Dev Mode Port Entry specific information * ********************************************************* 0400 IP 00 PRI 172.021.003.032 0402 IP 00 SEC 172.021.003.033 0404 IP 00 NO 172.021.003.038 0406 IP 01 NO 172.021.002.016 040E SNA 00 HWADD 00 02:00:FE:DF:00:42 HWADD 01 02:00:FE:DF:00:43 ROUTE 00 172.021.003.032 255.255.255.224 where: Dev is the base device address Mode is the operation mode - IP or SNA Port is the virtual (relative) adapter number. When the device is specifies the odd address of the pair, then the read/write functions of the pair will be swapped. For IP modes, the entry specific information is as follows: PRI|SEC|NO specifies where a packet with an unknown IP address is forwarded to. PRI is the primary default entry, SEC specifies the entry to use when the primary is not available, and NO specifies that this is not a default entry. nnn.nnn.nnn.nnn specifies the home IP address When the operation mode is IP, specify only the even (read) address. The odd (write) address will be create automatically. Note: SNA mode does not currently work. Additionally, two other statements can be included in the address translation file. The HWADD and ROUTE statements. Use the HWADD to specify a hardware (MAC) address for a virtual adapter. The first parameter after HWADD specifies with relative adapter for which the address is applied. The ROUTE statement is included for convenience. This allows the hercifc program to create a network route for this specified virtual adapter. Please note that it is not necessary to include point-to-point routes for each IP address in the table. This is done automatically by the emulation module. Up to 4 virtual (relative) adapters 00-03 are currently supported. ----------------------------------------------------------------- SLIP/VMNET - Channel to Channel link to TCP/IP via SLIP/VMNET ----------------------------------------------------------------- If the emulation mode is not specified on the configuration statement, it is assumed to be a point-to-point link to the driving system's TCP/IP stack using Willem Konynenberg's VMNET package. This provides the same function as the CTCI mode of operation, except that it uses a virtual SLIP interface instead of the TUN/TAP driver. Refer to http://www.kiyoinc.com/herc3088.html for more details. ================================================================= [1] The TunTap32.dll and FishPack.dll are part of Fish's CTCI-W32 http://www.softdevlabs.com/Hercules/ctci-w32-index.html package, but the required WinPCap packet driver must be installed separately from http://www.winpcap.org See Fish's web page for details. ALSO NOTE that it is HIGHLY RECOMMENDED that you stick with using only the current RELEASE version of WinPCap and NOT any type of 'alpha' OR 'beta' version! Alpha and Beta versions of WinPCap are NOT SUPPORTED! Only official *release* version are supported! When you visit the WinPCap download web page, you need need to scroll down the page a bit to reach the OFFICIAL RELEASE VERSION of WinPcap. They usually put their Beta versions at the top of the page, and BETA versions ARE NOT SUPPORTED. *Please* scroll down the page and use and official RELEASE version. Thanks. You may, if you want, use a beta version of WinPCap, but if you do, then you're on your own if you have any problems with it. -- Fish, May 2004. hercules-3.07/README.OSX000644 000765 000765 00000005202 11143760544 016277 0ustar00jmaynardjmaynard000000 000000 (The previous contents of this file were removed, as they haven't applied in years.) To compile on OS X for another architecture than the one running, or another OS version, you have to supply several arguments to the configure command. To force a particular architecture, you need to specify the machine architecture to the gcc command with the "-arch " operand. You also need to tell configure what environment you're building for, with --host. ARCHITECTURE -arch --host 32-bit Intel i386 i686 64-bit Intel x86_64 x86_64 32-bit PowerPC ppc powerpc 64-bit PowerPC ppc64 powerpc64 The argument for --host is the first part of a build triplet, specified as --. The vendor is apple for all OS X builds. OS is "darwin8.8.0" for OS X 10.4 (Tiger), and "darwin9.6.0" for OS X 10.5 (Leopard). This makes, for example, building for 64-bit Intel on Leopard use "--host x86_64-apple-darwin9.6.0". The -arch argument is specified by overriding the CC (C compiler) value and adding it to the end, as in CC="gcc -arch x86_64". If you're building for an OS that's not the one you're running on, you also need to tell the build environment that you're doing so. For building for Tiger on Leopard, you need to add two arguments to the configure invocation: "CFLAGS='-isysroot /Developer/SDKs/MacOSX10.4u.sdk' LDFLAGS='-isysroot/Developer/SDKs/MacOSX10.4u.sdk -Wl,-syslibroot,/Developer/SDKs/MacOSX10.4u.sdk'". (All on one line, of course.) You also need to add an environment variable that's passed to gcc upon invocation, and this takes adding it to the beginning of the CC value, as in CC="/usr/bin/env MACOSX_DEPLOYMENT_TARGET=10.4 gcc -arch ix86_64". This makes a complete invocation for building for 32-bit Intel for Tiger on Leopard (again, all on one line): CC="/usr/bin/env MACOSX_DEPLOYMENT_TARGET=10.4 gcc -arch i386" CFLAGS='-isysroot /Developer/SDKs/MacOSX10.4u.sdk' LDFLAGS='-isysroot /Developer/SDKs/MacOSX10.4u.sdk -Wl,-syslibroot,/Developer/SDKs/MacOSX10.4u.sdk' ./configure --enable-setuid-hercifc --host=i686-apple-darwin8.8.0 Building 32-bit Intel for Leopard on Leopard is easier: CC="gcc -arch i386" ./configure --enable-setuid-hercifc --host=i686-apple-darwin9.6.0 (Note that building a 64-bit Intel version on a Mac with a 64-bit Intel processor still requires explicitly setting the architecture. If you don't, you'll get a 32-bit Intel version.) Once you have the various architectures built, you can combine them into one binary with lipo. This is done by saying "lipo -output -create". The best approach is to automate this with a shell script; I've done this for my own use. hercules-3.07/README.SUN000644 000765 000765 00000011240 11224164171 016264 0ustar00jmaynardjmaynard000000 000000 HOW TO BUILD HERCULES FROM SVN UNDER SOLARIS 1. DOWNLOAD AND INSTALL THE GNU COMPILER AND TOOLS (a) You can obtain all the required tools from http://www.sunfreeware.com To download the tools you will need wget which is installed in /usr/sfw/bin on Solaris 9 and 10. First add this directory to your path using the command: PATH=${PATH}:/usr/sfw/bin (b) Follow instructions on http://www.blastwave.org/pkg-get.php to install the pkg-get package. Choose /opt/csw as the package base directory. Choose a local mirror site from the list at http://www.blastwave.org/mirrors.html and update /opt/csw/etc/pkg-get.conf to point to the /stable directory at the mirror site, for example: url=http://blastwave.informatik.uni-erlangen.de/csw/stable Add /opt/csw/bin to your path using the command: PATH=/opt/csw/bin:${PATH} (c) Then install the GNU compiler and tools using these commands: pkg-get install textutils pkg-get install automake pkg-get install autoconf pkg-get install subversion pkg-get install flex pkg-get install gmake pkg-get install ggrep pkg-get install gcc3 (d) Check that all the required tools are installed: pkg-get compare subversion autoconf automake flex gawk gcc3 pkg-get compare ggettext ggrep libiconv gm4 gmake perl gsed which should produce output something like this: software localrev remoterev subversion 1.4.5,REV=2007.11.18 SAME autoconf 2.61,REV=2007.07.13 SAME automake 1.9.6 SAME flex 2.5.4,REV=2005.10.03 SAME gawk 3.1.5 SAME gcc3 3.4.5 SAME ggettext 0.14.1,REV=2005.06.29 SAME ggrep 2.5,REV=2004.12.01 SAME libiconv 1.9.2 SAME gm4 1.4.5,REV=2006.07.27 SAME gmake 3.81 SAME perl 5.8.8,REV=2007.10.05 SAME gsed 4.1.4 SAME (e) Finally, add symbolic links to allow certain GNU tools to be invoked using standard Unix names: cd /opt/csw/bin ln -s /opt/csw/gcc3/bin/gcc gcc ln -s /opt/csw/bin/ggettext gettext ln -s /opt/csw/bin/ggrep grep ln -s /opt/csw/bin/gm4 m4 ln -s /opt/csw/bin/gmake make ln -s /opt/csw/bin/gsed sed 2. DOWNLOAD THE HERCULES SOURCE FROM SVN Add the following line to your .profile file: PATH=/opt/csw/bin:${PATH} From your home directory issue this command: svn checkout svn://svn.hercules-390.org/hercules/trunk hercules Note: svn will fail if you do not have libuuid installed on your system ld.so.1: svn: fatal: libuuid.so.1: open failed: No such file or directory If you get this message, you will need to install a patch from Sun: 1. Go to sunsolve.sun.com and select "Patch Finder" 2. Scroll down to "Download Product Specific Patches" and select your version of Solaris (for example, Solaris 2.9 SPARC) 3. Look for a patch which contains libuuid (for example, 114129-02) 4. Download the patch and unzip it into /var/spool/patch 5. patchadd /var/spool/patch/114129-02 3. CHECK THAT THE REQUIRED LEVELS OF TOOLS ARE INSTALLED From your home directory issue these commands: cd hercules util/cvslvlck which should produce output something like this: OK cvs (informational), found 1.11.22 OK autoconf requires 2.5, found 2.61 OK automake requires 1.9, found 1.9.6 OK flex requires 2.5, found 2.5.4 OK gawk requires 3.0, found 3.1.5 OK gcc requires 2.95, found 3.4.5 OK gettext requires 0.11, found 0.14.1 OK grep requires 0, found 2.5 OK libiconv requires 1.8, found 1.9 For first-time Libiconv installs, a recompile and reinstall of gettext is recommended. Source: libiconv-1.8/README OK m4 requires 0.0, found 1.4 OK make requires 3.79, found 3.81 OK perl requires 5.6, found 5.8.8 OK sed requires 3.02, found 4.1.4 4. BUILD HERCULES In the hercules directory issue these commands: sh ./autogen.sh ./configure make hercules-3.07/README.TAPE000644 000765 000765 00000023102 11143760543 016355 0ustar00jmaynardjmaynard000000 000000 ------------------------------------------------------------------------------- * Hercules Tape Support Enhancements SPE/Fixes * * V1.0 - By Ivan S. Warren * ------------------------------------------------------------------------------- 0 - Version History * 08 Mar 2003 : ISW : Initial Release I - Supported Device Type emulations : Device Types supported as of yet : 3410/3411, 3420, 3480, 3490, 9347 Upcoming Device type support : 3422, 3424, 3490E, 3590, 3430, 8809 II - Basic ACF support The ACF (Automatic Cartridge Feeder) is a feature on Cartridge type tape drives (3480, 3490, etc..) that automatically loads a new tape when a tape is removed from the drive. There is no real control over this device by the host, as it just keeps on feeding tapes one after the other. Although the ACF feature is unique to cartridge type systems, the emulation accepts to use the same technique for emulated 1/2 inch tapes reel drives as well. ACF is supported as follows : hercules.cnf syntax : CUU DEVT @filename devinit syntax : devinit CUU @filename the 'filename' (without the prefixing @) contains a list of files that will be loaded one after the other. The filenames contained in the file list cannot describe another ACF file nor an SCSI tape handle (/dev/stX). However, the files may be standard AWS, HET or OMA files. To manually reset the ACF to the top of the stack, the devinit can be used to 'reload' the ACF feature. If the filename in the ACF description file contains a '*', any option(s) that follow(s) the '*' (is)are applied to each file, followed by the option(s) specified on the devinit or hercules.cnf entry, followed by the option(s) specified on each individual entry. Example : hercules.cnf: 180 3420 @newstack compress=1 newstack: # Sample file * maxsizeM=16 eotmargin=131072 tape01.aws compress=0 tape02.het maxsizeM=32 eotmargin=65536 tape03.het maxsize=0 This is equivalent to issuing (one at the start and one after each tape unload event) 180 3420 tape01.aws maxsizeM=16 eotmargin=131072 compress=1 compress=0 devinit 180 tape02.het maxsizeM=16 eotmargin=131072 compress=1 maxsizeM=32 eotmargin=65536 devinit 180 tape03.het maxsizeM=16 eotmargin=131072 compress=1 maxsize=0 Options are processed in the order in which they appear. Any conflicting parameter overrides the previous one. For example, on the 1st entry, the resuling "compress" will be 0. Care must be taken that '*' line entries are all proecessed at once. For example : * compress=0 tape01.aws * compress=1 tape02.aws is EQUIVALENT to * compress=0 compress=1 tape01.aws tape02.aws NOTE : This may change in the future though, so ACF description files should not rely on this feature. III - Multivolume support - End of tape indication, Tape file size limitation Numerous requests have been made in order to support multi-volume tape handling, as well as limiting the file size generated by any individual tape file. Because multivolume support is not necesserally VOL1-HDR1/EOV/EOF based, a certain number of new features have to be implemented in order to let the guest program manage the multivolume on it's own. (ex: VM/DDR, DOS Tape Spooled output, etc..) Multivolume support resides in the capacity of a drive to indicate to the controling program that it is about to reach the end of the physical tape and that measures have to be taken to close the current volume and request a new media. 3 new options are introduced : maxsize[K|M]=nnnn : The resulting file size is limited to the amount specified. maxsize specifies bytes, maxsizeK specifies a multiple of 10$24 bytes and maxsizeM specifies a multiple of 1024*1024 bytes. specifying a size of 0 indicates that there is no limit on the size of the file. the default is 0 (unlimited file size) strictsize=0|1 : Upon reaching the tape file size limit, depending on strictsize, the tape file will or will not be truncated to enforce the maxsize limit. The limit is only enforced during a write type operation (that is : if the file already exists and the program only reads the file, then the file will NOT be truncated, regardless of the strictsize setting). This affects any write that starts BELOW the limit, but that would extend BEYOND the limit. This parameter only affects compress HET files. On AWS tapes, the limit is always enforced, but the file is not truncated (i.e. the write does not occur, because 1) AWS tapes are never truncated, 2) the effects of the write are known in advance (no compression)). Regardless of strictsize, any write operation (Write, Write TM) will return a Unit Check with Equip Check to the program if the file size exceeds the predefined limit. If strictsize is 0, the write will actually have been performed on the tape file. If strictsize is 1, the file will be truncated on the preceeding tape block boundary. If an attempt is made to write beyond the maxsize li Care must be taken that regardless of the 'strictsize' setting, the tape may become unusable for the guest program should such an event occur (absence of a Tape Mark for example). This option has no effect if maxsize is 0 This option only affects HET file tapes The default is 0 (do not truncate) eotmargin=nnnn : This option specifies, in bytes, the threshold before reaching maxsize during which an indication will be returned to the program to indicate that an EOT marker has been reached for a write type operation. The indication of reaching near-capacity is indicated to the program by presenting Unit Exception in the CSW on a Write type operation, along with Channel End and Device End. For certain device types, sense information may also indicate this information independently of a write operation. The purpose of this option is to allow the program to determine that it is time to change to ask for a new tape. For example : maxsizeM=2 eotmargin=131072 all writes up to 2Mb - 128Kb will occur normally All writes between 2Mb-128Kb and 2Mb will receive Unit Exception All writes beyond 2Mb will receive Unit Check This option has no effect if maxsize is 0 The default is 131072 (128Kb) Caveats : If the emulated tape file resides on a disk media that reaches full capacity before the tape image exceeds it's size limit, the tape emulation will not detect that situation and will simulate reaching physical end of tape BEFORE reaching the EOT marker. This behaviour may be changed at a later time. IV - Various other changes / Corrections IV.1 : Device End Suppression for Tape motion CCWs on a non-ready tape drive IV.2 : Control Unit End is presented on Rewind Unload status IV.3 : Sense Pending status support When certain conditions arise during an I/O operation, A sense is built and Unit Check is presented to the program. The program is then responsible for retrieving the sense information. However, if the sense is not the result of a previously occuring Unit Check, a new sense is built to reflect the current device status. Also, this management is a necessary step in order to eventually implement multipath operations (Contengency Allegiance status). IV.4 : readonly=0|1 : force an emulated tape device read only. (1/2 Inch tape ring or 38k Cartridge Protect tab) (support for this feature is incomplete) --Ivan 8 Mar 2003 ------------------------------------------------------------------------------- * AUTOMOUNT support * ------------------------------------------------------------------------------- Starting with Hercules version 3.06 a new AUTOMOUNT option is available that allows guest operating systems to directly mount, unmount and query tape device filenames for themselves, without any intervention on the part of the Hercules operator. Automount support is enabled via the AUTOMOUNT configuration file statement. An example guest automount program for VSE called "TMOUNT" is provided in the util subdirectory of the Hercules source code distribution. Briefly, the 0x4B (Set Diagnose) CCW is used to mount (or unmount) a file onto a tape drive, and the 0xE4 (Sense Id) CCW opcode is used to query the name of the currently mounted file. For mounts, the 0x4B CCW specifies the filename of the file to be mounted onto the drive. The file MUST reside in the specified AUTOMOUNT directory or the automount request will be rejected. To unmount the currently mounted file, simply do a mount of the special filename "OFFLINE". To query the name of the currently mounted file, the 0xE4 CCW is used. Note however that the 0xE4 (Sense Id) CCW opcode cannot be used by itself since the drive may also already natively support the Sense Id CCW opcode. Instead, it must be preceded by (command-chained from) a 0x4B CCW with a data transfer length of one byte. The following 0xE4 command is the one that then specifies the i/o buffer and buffer length of where the query function is to place the device's currently mounted host filename. In summary: MOUNT: X'4B', , X'20', UNMOUNT: (same thing but use filename "OFFLINE" instead) QUERY: X'4B', , X'60', 1 X'E4', , X'20', Again, please refer to the provided TMOUNT sample for a simple example. -- Fish 28 May 2008 hercules-3.07/RELEASE.NOTES000644 000765 000765 00000040441 11143760543 016644 0ustar00jmaynardjmaynard000000 000000 ------------------------------------------------------------------------------- Version 3.06 RELEASE NOTES * Tape "AUTOMOUNT" support Starting with Hercules version 3.06 a new AUTOMOUNT option is available that allows guest operating systems to directly mount, unmount and query tape device filenames for themselves, without any intervention on the part of the Hercules operator. Automount support is enabled via the AUTOMOUNT configuration file statement. An example guest automount program for VSE called "TMOUNT" is provided in the util subdirectory of the Hercules source code distribution. Briefly, the 0x4B (Set Diagnose) CCW is used to mount (or unmount) a file onto a tape drive, and the 0xE4 (Sense Id) CCW opcode is used to query the name of the currently mounted file. For mounts, the 0x4B CCW specifies the filename of the file to be mounted onto the drive. The file MUST reside in the specified AUTOMOUNT directory or the automount request will be rejected. To unmount the currently mounted file, simply do a mount of the special filename "OFFLINE". To query the name of the currently mounted file, the 0xE4 CCW is used. Note however that the 0xE4 (Sense Id) CCW opcode cannot be used by itself since the drive may also already natively support the Sense Id CCW opcode. Instead, it must be preceded by (command-chained from) a 0x4B CCW with a data transfer length of one byte. The following 0xE4 command is the one that then specifies the i/o buffer and buffer length of where the query function is to place the device's currently mounted host filename. In summary: MOUNT: X'4B', , X'20', UNMOUNT: (same thing but use filename "OFFLINE" instead) QUERY: X'4B', , X'60', 1 X'E4', , X'20', Again please refer to the provided TMOUNT program for a simple example of how automount support might be implmented on a guest operating system. ------------------------------------------------------------------------------- Version 3.05 RELEASE NOTES * The 'conspawn' utility used to process 'sh' commands now recognizes a specially designed keyword "startgui" to accomodate automatic starting of Windows GUI applications via the .RC file or panel command-line. If the first word following 'sh' is "startgui", then the "ShellExecute" API is used to start the requested program rather than the 'system()' API as otherwise. This is to address an issue related to running Hercules via the HercGUI graphical front end wherein programs started via the .RC file would cause HercGUI to hang at PowerOff until all programs started by Hercules (via the .RC file or panel command-line) were first closed. If the program you wish to invoke via the 'sh' command is a command-line program (that thus uses stdio to read from stdin and write to stdout) then "startgui" should NOT be used. Instead, simply start the program as before (e.g. "sh cmd /c myprog myargs..."). If the application you wish to start is a normal Windows GUI application however, then the "startgui" keyword should be used instead. For example, to automatically start the Vista 3270 terminal emulator from your .RC file, use: "sh startgui D:\Vista32\Vista32.exe Hercules.ses". Again, this is only for starting Windows GUI programs and thus does not impact non-GUI (command-line) programs nor, obviously, non-MSVC builds of Hercules nor when Hercules is run via the command-line (in non-GUI mode). This is only for the Window MSVC build of Hercules and only when Hercules is started via HercGUI and only when starting a Windows GUI program via the 'sh' command either via the panel command-line or the .RC file. (Note: the panel command-line also includes commands entered via the http server interface as well) * Real SCSI tape drives used with Hercules must provide a certain minimum set is "IBM compatible" support in their SCSI command set/behavior in order to work properly with Hercules. Furthermore, the Hercules device-type used on your device statement in your Hercules configuration file should match the the level of support/behavior that they provide. For example, all SCSI tape drives used with Hercules must provide the ability to set variable-length blocks as well as long erase-gaps (long erase-gaps allows new data to be appended to the end of existing data without having to write a tape-mark to separate the new data from the old existing data first). Another example would be using a model of SCSI tape drive that happens to report physical block-id values in a format different from the way real IBM mainframe tape drives report them. 3480/3490 tape drives for example report their block-ids (used in Read Block Id and Locate CCWs) in a very specific format wherein bits 1-7 of the high-order byte of the reported 4-byte block- id indicates the tape's physical "segment" location of where the lower 22- bit block number is physically located on the tape. (The block-id segment is used to allow the tape drive to quickly position itself to the approximate location where the desired block acually resides on the tape and thus allows high-speed positioning for the Locate CCW). If the model of SCSI tape drive you are actually using with Hercules does not use this same block-id format however, then it cannot be used with Hercules as a 3480 or 3490 model tape drive with specially defined options. If the SCSI tape drive you are using reports its block-ids using a 32-bit block-id value (the same way a 3590 model tape drive does), then similarly, it should be defined to Hercules as a model 3590 device-type as well (since that is how it is behaving with respect the format of the returned blockid values). It you wish to define it in Hercules as a model 3480 or 3490, then you will need to use specially defined options before it will work properly as the model drive you wish it to emulate. With all that being said, it should be noted that PARTIAL support for 3590 device emulation is possible with judicious use the aforementioned special options, but full/complete 3590 support is unlikely due to lack of publicly available documentation. Details regarding 3590 CCW handling is restricted (confidential) IBM proprietary information, and is not normally available outside of IBM. Not long ago IBM was required by US law to publish such information, but unfortunately for Hercules, such is no longer the case. For further information regarding use of SCSI attached tape drives with Hercules and their associated specially defined options, please refer to the section on SCSI tape drives in the Hercules's Device Configuration documentation. * In order to ensure proper functioning of the TOD clock with older versions of guest operating systems, the default values of Hercules's internal thread priorities for the Windows version of Hercules were changed to be identical to those used by all other supported platforms. Originally, the default thread priority values for the Windows version of Hercules were: *** 3.04 (and prior) Default Priorities *** Thread Priority Meaning ------- -------- ------------------------ HERCPRIO 0 Normal Process priority DEVPRIO -8 Above Normal Thread priority TODPRIO 0 Normal Thread priority CPUPRIO 0 Normal Thread priority which caused acceptable performance/functioning on most, but not all, guest operating systems. Beginning with version 3.05 however, the prioriries now default to: *** 3.05 (and later) Default Priorities *** Thread Priority Meaning ------- -------- ------------------------ HERCPRIO 0 Normal Process priority TODPRIO -20 Time Critical Thread priority DEVPRIO 8 Below Normal Thread priority CPUPRIO 15 Lowest Thread priority which may on more modern guest operating systems (which handle the TOD clock differently than do older less sophticated versions) cause a slight decrease in overall performance. If such is the case, the original default priorities (and thus the original behavior) can be obtained via addition of appropriate HERCPRIO, TODPRIO, DEVPRIO and CPUPRIO control file statements with values identical to the original version 3.04 default values. * Additional configuration file usability enhancements have been implemented in the form of a new 'INCLUDE' (and associated 'IGNORE') statement, allowing configuration files to "include" statements from a different named file. Additonally, a new "enhanced" symbolic substitution syntax is now also supported. Refer to the Hercules "Configuration File" documentation for further information and details. A rather nifty "Automatic Operator" facility has also been implemented in the current release as well. While not exactly a "configuration file usability enhancement", it is nevertheless something we hope might prove to be more useful/helpful to our many users. See the "README.HAO" document for more information. ------------------------------------------------------------------------------- Version 3.01 RELEASE NOTES - Support for z990 crypto instructions is conditional on the presence of the glibcrypt library. If Hercules is BUILT, the development files for glibcrypt should be available. When hercules is RUN, the runtime files for glibcrypt should be installed. Depending on the level of glibcrypt used to *build* hercules, the associated level of glibcrypt should also be present on the target machine. On systems supporting shared library versioning, multiple levels of the glibcrypt runtime libraries can be installed simultaneously, ensuring availability of the z990 crypto instructions, regardless of the level of glibcrypt with which hercules was initially built. - CTC and LCS devices now ++MUST++ specify ALL addresses on the configuration statement. Example: 0A00.2 LCS ..... 0B00.2 CTCI .... or 0A00.4 LCS -oat hercules.oat or 0A00-0A03 LCS -oat hercules.oat or 0A00 LCS -oat hercules.oat 0A01 LCS 0A02 LCS 0A03 LCS Previously (i.e. with version 3.00), only the first (even numbered) device needed to be defined and Herc would automatically define the odd numbered device for you. Starting with Hercules version 3.01 however, you now need to define BOTH devices, just like you did with versions prior to 3.00. Once again, starting with version 3.01, you **MUST** define BOTH DEVICES. ------------------------------------------------------------------------------- Version 3.00 RELEASE NOTES - Reminder that CTCI device handling was changed as follows: - The CTCI-W32 protocol is deprecated. You should use the CTCI protocol instead. - You MUST NOT define both even/odd CTCI device pairs in your configuration file. You should ONLY define the first even numbered device. Hercules will automatically define the odd numbered device for you. If you define the odd numbered device by mistake, an open error will occur on that device. This is by design. See the README.NETWORKING document for further details. - Hercules Dynamic Loader support: starting with version 3.00, Hercules now contains support for the dynamic loading of certain modules upon startup on some platforms (e.g. Linux and Windows for example). As a result of this new feature, "Hercules" itself now no longer consists of just the 'hercules.exe' module by itself, but rather consists of BOTH the 'hercules.exe' program AS WELL AS whatever dynamic modules (DLLs) that accompany it. As a result if this change, whenever you install a new version of Hercules, you must ensure that you ALSO install the accompanying new versions of the new dynamic modules as well. Attempting to use a version of Hercules with a dynamic module that was not specifically built for that version will cause loading of that dynamic module to fail. You CANNOT mix versions of Hercules with differing versions of dynamically loaded modules. Ensure that your library path LD_LIBRARY_PATH is set correctly such that it includes the directory of your Hercules executables. Especially, message HHCCF042E will indicate that system is unable to locate necessary loadable modules. - ECPS:VM: Do not use ECPS:VM (See README.ECPSVM) in an AP or MP environment in VM/370. If AP=YES or MP=YES is coded in DMKSYS and the AP/MP control file is used to build the CP nucleus and NUMCPU is set to more than 1 in the hercules.cnf file, any of LOK001, LOK003 or other abends will occur. This occurs because the Hercules ECPS:VM CP Assist implementation is not MP safe, and particularily, attemps VM dispatching without holding necessary AP or MP locks. - Due to the change in Hercules' "mainstor" memory allocation technique to address a "double memory consumption" bug in Cygwin's malloc implementation, some Windows Hercules users may experience an "out of memory" error whenever Hercules is started with a large MAINSIZE configuration file value: "HHCCF031S Cannot obtain nnnMB main storage" This error will most likely occur (if it does at all) for those users who have manually adjusted their Cygwin "heap_chunk_in_mb" Windows registry setting value (in order to allow them to specify a large MAINSIZE value when running Hercules). If this problem does occur (i.e. if you DO happen to experience the above mentioned "HHCCF031S Cannot obtain main storage" error with this new release of Hercules), then either REDUCE your "heap_ chunk_in_mb" value (yes, that's correct: REDUCE it; i.e. change it to a SMALLER value) or else remove it altogether (so as to let it default). Detailed explanation: History/background: Cygwin has a built-in limit to the amount of memory that may be allocated in one chunk. If you try 'malloc'ing more than this limit, you will receive an "out of memory" error. Since many Hercules users specify large MAINSIZE values in their configuration file, they sometimes experience this problem. The suggested workaround to this "problem" was to add a "heap_chunk_in_mb" registry value to Cygwin's registry settings with a large enough value such that Cygwin would then be able to satisfy Hercules' 'malloc' request for such a large MAINSIZE value. This worked fine until sometime around version 1.3.15 of Cygwin, at which time they began using a different 'malloc' technique that unfortunately causes TWICE as much Windows virtual memory to be allocated for any large memory allocation (the technical reasons of which are explained in comments in source member config.c where mainsize is being allocated). In order to address this double memory allocation issue in Cygwin's malloc implementation, Hercules was changed to use mmap to allocate its mainstor rather than malloc (which, unlike malloc, does NOT inadvertently allocate twice as Windows virtual storage than was requested), which did indeed re- solve the "double memory allocation" problem. Unfortunately however, because Cygwin's malloc and mmap logic each consume completely different portions of Windows' virtual memory, the more memory that is reserved for malloc usage (via using a larger "heap_chunk_in_mb" value), the LESS becomes available for mmap usage! Thus, while increasing your "heap_chunk_in_mb" registry value USED to HELP [to allow you to allocate larger amounts of mainstor (MAINSIZE)], it NOW causes the complete OPPOSITE effect: it ends up PREVENTING you from being able to 'mmap' as much storage as you'd like to have! Conclusion: Therefore, if you are currently using the "heap_chunk_in_mb" registry value setting to allow you to allocate large MAINSIZE values, then starting with version 3.00 of Hercules you need to DESCREASE your "heap_chunk_in_mb" value (or remove it altogether and let it default) in order to leave enough memory remaining for Hercules (Cygwin actually) to be able to satisfy its 'mmap' request for your desired MAINSIZE amount. ------------------------------------------------------------------------------- hercules-3.07/scedasd.c000644 000765 000765 00000061511 11202676512 016523 0ustar00jmaynardjmaynard000000 000000 /* SCEDASD.C (c) Copyright Jan Jaeger, 1999-2009 */ /* Service Control Element DASD I/O functions */ // $Id: scedasd.c 5306 2009-04-03 17:57:43Z rbowler $ #include "hstdinc.h" #define _HENGINE_DLL_ #include "hercules.h" #include "opcode.h" #if !defined(_SCEDASD_C) #define _SCEDASD_C static TID scedio_tid; /* Thread id of the i/o driver */ static char *sce_basedir = NULL; char *get_sce_dir() { return sce_basedir; } void set_sce_dir(char *path) { char realdir[MAX_PATH]; char tempdir[MAX_PATH]; if(sce_basedir) { free(sce_basedir); sce_basedir = NULL; } if(!path) sce_basedir = NULL; else if(!realpath(path,tempdir)) { logmsg(_("HHCSC011E set_sce_dir: %s: %s\n"),path,strerror(errno)); sce_basedir = NULL; } else { hostpath(realdir, tempdir, sizeof(realdir)); strlcat(realdir,"/",sizeof(realdir)); sce_basedir = strdup(realdir); } } static char *set_sce_basedir(char *path) { char *basedir; char realdir[MAX_PATH]; char tempdir[MAX_PATH]; if(sce_basedir) { free(sce_basedir); sce_basedir = NULL; } if(!realpath(path,tempdir)) { logmsg(_("HHCSC012E set_sce_basedir: %s: %s\n"),path,strerror(errno)); sce_basedir = NULL; return NULL; } hostpath(realdir, tempdir, sizeof(realdir)); if((basedir = strrchr(realdir,'/'))) { *(++basedir) = '\0'; sce_basedir = strdup(realdir); return (basedir = strrchr(path,'/')) ? ++basedir : path; } else { sce_basedir = NULL; return path; } } static char *check_sce_filepath(const char *path, char *fullpath) { char temppath[MAX_PATH]; char tempreal[MAX_PATH]; /* Return file access error if no basedir has been set */ if(!sce_basedir) { strlcpy(fullpath,path,sizeof(temppath)); errno = EACCES; return NULL; } /* Establish the full path of the file we are trying to access */ strlcpy(temppath,sce_basedir,sizeof(temppath)); strlcat(temppath,path,sizeof(temppath)); if(!realpath(temppath,tempreal)) { hostpath(fullpath, tempreal, sizeof(temppath)); if(strncmp( sce_basedir, fullpath, strlen(sce_basedir))) errno = EACCES; return NULL; } hostpath(fullpath, tempreal, sizeof(temppath)); if(strncmp( sce_basedir, fullpath, strlen(sce_basedir))) { errno = EACCES; return NULL; } return fullpath; } #endif /* !defined(_SCEDASD_C) */ /*-------------------------------------------------------------------*/ /* function load_hmc simulates the load from the service processor */ /* the filename pointed to is a descriptor file which has the */ /* following format: */ /* */ /* '*' in col 1 is comment */ /* core image file followed by address where it should be loaded */ /* */ /* For example: */ /* */ /* * Linux/390 cdrom boot image */ /* boot_images/tapeipl.ikr 0x00000000 */ /* boot_images/initrd 0x00800000 */ /* boot_images/parmfile 0x00010480 */ /* */ /* The location of the image files is relative to the location of */ /* the descriptor file. Jan Jaeger 10-11-01 */ /* */ /*-------------------------------------------------------------------*/ int ARCH_DEP(load_hmc) (char *fname, int cpu, int clear) { REGS *regs; /* -> Regs */ FILE *fp; char inputbuff[MAX_PATH]; char *inputline; char filename[MAX_PATH]; /* filename of image file */ char pathname[MAX_PATH]; /* pathname of image file */ U32 fileaddr; int rc = 0; /* Return codes (work) */ /* Get started */ if (ARCH_DEP(common_load_begin) (cpu, clear) != 0) return -1; /* The actual IPL proper starts here... */ regs = sysblk.regs[cpu]; /* Point to IPL CPU's registers */ if(fname == NULL) /* Default ipl from DASD */ fname = "HERCULES.ins"; /* from HERCULES.ins */ hostpath(pathname, fname, sizeof(pathname)); if(!(fname = set_sce_basedir(pathname))) return -1; /* Construct and check full pathname */ if(!check_sce_filepath(fname,filename)) { logmsg(_("HHCSC001E Load from %s failed: %s\n"),fname,strerror(errno)); return -1; } fp = fopen(filename, "r"); if(fp == NULL) { logmsg(_("HHCSC002E Load from %s failed: %s\n"),fname,strerror(errno)); return -1; } do { inputline = fgets(inputbuff,sizeof(inputbuff),fp); #if !defined(_MSVC_) if(inputline && *inputline == 0x1a) inputline = NULL; #endif /*!defined(_MSVC_)*/ if(inputline) { rc = sscanf(inputline,"%" MSTRING(MAX_PATH) "s %i",filename,&fileaddr); } /* If no load address was found load to location zero */ if(inputline && rc < 2) fileaddr = 0; if(inputline && rc > 0 && *filename != '*' && *filename != '#') { hostpath(pathname, filename, sizeof(pathname)); /* Construct and check full pathname */ if(!check_sce_filepath(pathname,filename)) { logmsg(_("HHCSC003E Load from %s failed: %s\n"),pathname,strerror(errno)); return -1; } if( ARCH_DEP(load_main) (filename, fileaddr) < 0 ) { fclose(fp); HDC1(debug_cpu_state, regs); return -1; } sysblk.main_clear = sysblk.xpnd_clear = 0; } } while(inputline); fclose(fp); /* Finish up... */ return ARCH_DEP(common_load_finish) (regs); } /* end function load_hmc */ /*-------------------------------------------------------------------*/ /* Function to Load (read) specified file into absolute main storage */ /*-------------------------------------------------------------------*/ int ARCH_DEP(load_main) (char *fname, RADR startloc) { int fd; int len; int rc = 0; RADR pageaddr; U32 pagesize; fd = open (fname, O_RDONLY|O_BINARY); if (fd < 0) { if(errno != ENOENT) logmsg(_("HHCSC031E load_main: %s: %s\n"), fname, strerror(errno)); return fd; } pagesize = PAGEFRAME_PAGESIZE - (startloc & PAGEFRAME_BYTEMASK); pageaddr = startloc; for( ; ; ) { if (pageaddr >= sysblk.mainsize) { logmsg(_("HHCSC032W load_main: terminated at end of mainstor\n")); close(fd); return rc; } len = read(fd, sysblk.mainstor + pageaddr, pagesize); if (len > 0) { STORAGE_KEY(pageaddr, &sysblk) |= STORKEY_REF|STORKEY_CHANGE; rc += len; } if (len < (int)pagesize) { close(fd); return rc; } pageaddr += PAGEFRAME_PAGESIZE; pageaddr &= PAGEFRAME_PAGEMASK; pagesize = PAGEFRAME_PAGESIZE; } } /* end function load_main */ #if defined(FEATURE_SCEDIO) /*-------------------------------------------------------------------*/ /* Function to write to a file on the service processor disk */ /*-------------------------------------------------------------------*/ static S64 ARCH_DEP(write_file)(char *fname, int mode, CREG sto, S64 size) { int fd, nwrite; U64 totwrite = 0; fd = open (fname, mode |O_WRONLY|O_BINARY, #if defined(_MSVC_) S_IREAD|S_IWRITE); #else S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); #endif if (fd < 0) { logmsg (_("HHCSC041E %s open error: %s\n"), fname, strerror(errno)); return -1; } #if defined(FEATURE_ESAME) sto &= ASCE_TO; #else /*!defined(FEATURE_ESAME)*/ sto &= STD_STO; #endif /*!defined(FEATURE_ESAME)*/ for( ; size > 0 ; sto += sizeof(sto)) { #if defined(FEATURE_ESAME) DBLWRD *ste; #else /*!defined(FEATURE_ESAME)*/ FWORD *ste; #endif /*!defined(FEATURE_ESAME)*/ CREG pto, pti; /* Fetch segment table entry and calc Page Table Origin */ if( sto >= sysblk.mainsize) goto eof; #if defined(FEATURE_ESAME) ste = (DBLWRD*)(sysblk.mainstor + sto); #else /*!defined(FEATURE_ESAME)*/ ste = (FWORD*)(sysblk.mainstor + sto); #endif /*!defined(FEATURE_ESAME)*/ FETCH_W(pto, ste); STORAGE_KEY(sto, &sysblk) |= (STORKEY_REF); if( pto & SEGTAB_INVALID ) goto eof; #if defined(FEATURE_ESAME) pto &= ZSEGTAB_PTO; #else /*!defined(FEATURE_ESAME)*/ pto &= SEGTAB_PTO; #endif /*!defined(FEATURE_ESAME)*/ for(pti = 0; pti < 256 && size > 0; pti++, pto += sizeof(pto)) { #if defined(FEATURE_ESAME) DBLWRD *pte; #else /*!defined(FEATURE_ESAME)*/ FWORD *pte; #endif /*!defined(FEATURE_ESAME)*/ CREG pgo; BYTE *page; /* Fetch Page Table Entry to get page origin */ if( pto >= sysblk.mainsize) goto eof; #if defined(FEATURE_ESAME) pte = (DBLWRD*)(sysblk.mainstor + pto); #else /*!defined(FEATURE_ESAME)*/ pte = (FWORD*)(sysblk.mainstor + pto); #endif /*!defined(FEATURE_ESAME)*/ FETCH_W(pgo, pte); STORAGE_KEY(pto, &sysblk) |= (STORKEY_REF); if( !(pgo & PAGETAB_INVALID) ) { #if defined(FEATURE_ESAME) pgo &= ZPGETAB_PFRA; #else /*!defined(FEATURE_ESAME)*/ pgo &= PAGETAB_PFRA; #endif /*!defined(FEATURE_ESAME)*/ /* Write page to SCE disk */ if( pgo >= sysblk.mainsize) goto eof; page = sysblk.mainstor + pgo; nwrite = write(fd, page, STORAGE_KEY_PAGESIZE); totwrite += nwrite; if( nwrite != STORAGE_KEY_PAGESIZE ) goto eof; STORAGE_KEY(pgo, &sysblk) |= (STORKEY_REF); } size -= STORAGE_KEY_PAGESIZE; } } eof: close(fd); return totwrite; } /*-------------------------------------------------------------------*/ /* Function to read from a file on the service processor disk */ /*-------------------------------------------------------------------*/ static S64 ARCH_DEP(read_file)(char *fname, CREG sto, S64 seek, S64 size) { int fd, nread; U64 totread = 0; fd = open (fname, O_RDONLY|O_BINARY); if (fd < 0) { if(errno != ENOENT) logmsg (_("HHCSC051E %s open error: %s\n"), fname, strerror(errno)); return -1; } if(lseek(fd, (off_t)seek, SEEK_SET) == (off_t)seek) { #if defined(FEATURE_ESAME) sto &= ASCE_TO; #else /*!defined(FEATURE_ESAME)*/ sto &= STD_STO; #endif /*!defined(FEATURE_ESAME)*/ for( ; size > 0 ; sto += sizeof(sto)) { #if defined(FEATURE_ESAME) DBLWRD *ste; #else /*!defined(FEATURE_ESAME)*/ FWORD *ste; #endif /*!defined(FEATURE_ESAME)*/ CREG pto, pti; /* Fetch segment table entry and calc Page Table Origin */ if( sto >= sysblk.mainsize) goto eof; #if defined(FEATURE_ESAME) ste = (DBLWRD*)(sysblk.mainstor + sto); #else /*!defined(FEATURE_ESAME)*/ ste = (FWORD*)(sysblk.mainstor + sto); #endif /*!defined(FEATURE_ESAME)*/ FETCH_W(pto, ste); STORAGE_KEY(sto, &sysblk) |= (STORKEY_REF); if( pto & SEGTAB_INVALID ) goto eof; #if defined(FEATURE_ESAME) pto &= ZSEGTAB_PTO; #else /*!defined(FEATURE_ESAME)*/ pto &= SEGTAB_PTO; #endif /*!defined(FEATURE_ESAME)*/ for(pti = 0; pti < 256 && size > 0; pti++, pto += sizeof(pto)) { #if defined(FEATURE_ESAME) DBLWRD *pte; #else /*!defined(FEATURE_ESAME)*/ FWORD *pte; #endif /*!defined(FEATURE_ESAME)*/ CREG pgo; BYTE *page; /* Fetch Page Table Entry to get page origin */ if( pto >= sysblk.mainsize) goto eof; #if defined(FEATURE_ESAME) pte = (DBLWRD*)(sysblk.mainstor + pto); #else /*!defined(FEATURE_ESAME)*/ pte = (FWORD*)(sysblk.mainstor + pto); #endif /*!defined(FEATURE_ESAME)*/ FETCH_W(pgo, pte); STORAGE_KEY(pto, &sysblk) |= (STORKEY_REF); if( pgo & PAGETAB_INVALID ) goto eof; #if defined(FEATURE_ESAME) pgo &= ZPGETAB_PFRA; #else /*!defined(FEATURE_ESAME)*/ pgo &= PAGETAB_PFRA; #endif /*!defined(FEATURE_ESAME)*/ /* Read page into main storage */ if( pgo >= sysblk.mainsize) goto eof; page = sysblk.mainstor + pgo; nread = read(fd, page, STORAGE_KEY_PAGESIZE); totread += nread; size -= nread; if( nread != STORAGE_KEY_PAGESIZE ) goto eof; STORAGE_KEY(pgo, &sysblk) |= (STORKEY_REF|STORKEY_CHANGE); } } } eof: close(fd); return totread; } static int ARCH_DEP(scedio_ior)(SCCB_SCEDIOR_BK *scedior_bk) { U32 origin; char image[9]; S32 size; unsigned int i; char filename[MAX_PATH]; FETCH_FW(origin,scedior_bk->origin); /* Convert image filename to null terminated ascii string */ for(i = 0; i < sizeof(image)-1 && scedior_bk->image[i] != 0x40; i++) image[i] = guest_to_host((int)scedior_bk->image[i]); image[i] = '\0'; /* Ensure file access is allowed and within specified directory */ if(!check_sce_filepath(image,filename)) { if(errno != ENOENT) logmsg (_("HHCSC101E access error: %s: %s\n"), image, strerror(errno)); return FALSE; } size = ARCH_DEP(load_main)(filename,origin); return (size >= 0) ? TRUE : FALSE; } static int ARCH_DEP(scedio_iov)(SCCB_SCEDIOV_BK *scediov_bk) { S64 seek; S64 length; S64 totread, totwrite; U64 sto; char fname[MAX_PATH]; switch(scediov_bk->type) { case SCCB_SCEDIOV_TYPE_INIT: return TRUE; break; case SCCB_SCEDIOV_TYPE_READ: /* Ensure file access is allowed and within specified directory */ if(!check_sce_filepath((char*)scediov_bk->filename,fname)) { if(errno != ENOENT) logmsg (_("HHCSC201E access error: %s: %s\n"), fname, strerror(errno)); return FALSE; } FETCH_DW(sto,scediov_bk->sto); FETCH_DW(seek,scediov_bk->seek); FETCH_DW(length,scediov_bk->length); totread = ARCH_DEP(read_file)(fname, sto, seek, length); if(totread > 0) { STORE_DW(scediov_bk->length,totread); if(totread == length) STORE_DW(scediov_bk->ncomp,0); else STORE_DW(scediov_bk->ncomp,seek+totread); return TRUE; } else return FALSE; break; case SCCB_SCEDIOV_TYPE_CREATE: case SCCB_SCEDIOV_TYPE_APPEND: /* Ensure file access is allowed and within specified directory */ if(!check_sce_filepath((char*)scediov_bk->filename,fname)) { if(errno != ENOENT) logmsg (_("HHCSC202I access error: %s: %s\n"), fname, strerror(errno)); /* A file not found error may be expected for a create request */ if(!(errno == ENOENT && scediov_bk->type == SCCB_SCEDIOV_TYPE_CREATE)) return FALSE; } FETCH_DW(sto,scediov_bk->sto); FETCH_DW(seek,scediov_bk->seek); FETCH_DW(length,scediov_bk->length); totwrite = ARCH_DEP(write_file)(fname, ((scediov_bk->type == SCCB_SCEDIOV_TYPE_CREATE) ? (O_CREAT|O_TRUNC) : O_APPEND), sto, length); if(totwrite >= 0) { STORE_DW(scediov_bk->ncomp,totwrite); return TRUE; } else return FALSE; break; default: PTT(PTT_CL_ERR,"*SERVC",(U32)scediov_bk->type,(U32)scediov_bk->flag1,scediov_bk->flag2); return FALSE; } } /*-------------------------------------------------------------------*/ /* Thread to perform service processor I/O functions */ /*-------------------------------------------------------------------*/ static void ARCH_DEP(scedio_thread)(SCCB_SCEDIO_BK *scedio_bk) { SCCB_SCEDIOV_BK *scediov_bk; SCCB_SCEDIOR_BK *scedior_bk; switch(scedio_bk->flag1) { case SCCB_SCEDIO_FLG1_IOV: scediov_bk = (SCCB_SCEDIOV_BK*)(scedio_bk + 1); if( ARCH_DEP(scedio_iov)(scediov_bk) ) scedio_bk->flag3 |= SCCB_SCEDIO_FLG3_COMPLETE; else scedio_bk->flag3 &= ~SCCB_SCEDIO_FLG3_COMPLETE; break; case SCCB_SCEDIO_FLG1_IOR: scedior_bk = (SCCB_SCEDIOR_BK*)(scedio_bk + 1); if( ARCH_DEP(scedio_ior)(scedior_bk) ) scedio_bk->flag3 |= SCCB_SCEDIO_FLG3_COMPLETE; else scedio_bk->flag3 &= ~SCCB_SCEDIO_FLG3_COMPLETE; break; default: PTT(PTT_CL_ERR,"*SERVC",(U32)scedio_bk->flag0,(U32)scedio_bk->flag1,scedio_bk->flag3); } OBTAIN_INTLOCK(NULL); while(IS_IC_SERVSIG) { RELEASE_INTLOCK(NULL); sched_yield(); OBTAIN_INTLOCK(NULL); } sclp_attention(SCCB_EVD_TYPE_SCEDIO); scedio_tid = 0; RELEASE_INTLOCK(NULL); } /*-------------------------------------------------------------------*/ /* Function to interface with the service processor I/O thread */ /*-------------------------------------------------------------------*/ static int ARCH_DEP(scedio_request)(U32 sclp_command, SCCB_EVD_HDR *evd_hdr) { SCCB_SCEDIO_BK *scedio_bk = (SCCB_SCEDIO_BK*)(evd_hdr + 1); SCCB_SCEDIOV_BK *scediov_bk; SCCB_SCEDIOR_BK *scedior_bk; static struct { SCCB_SCEDIO_BK scedio_bk; union { SCCB_SCEDIOV_BK v; SCCB_SCEDIOR_BK r; } io; } static_scedio_bk ; static int scedio_pending; if(sclp_command == SCLP_READ_EVENT_DATA) { int pending_req = scedio_pending; U16 evd_len; /* Return no data if the scedio thread is still active */ if(scedio_tid) return 0; /* Update the scedio_bk copy in the SCCB */ if(scedio_pending) { /* Zero all fields */ memset (evd_hdr, 0, sizeof(SCCB_EVD_HDR)); /* Set type in event header */ evd_hdr->type = SCCB_EVD_TYPE_SCEDIO; /* Store scedio header */ *scedio_bk = static_scedio_bk.scedio_bk; /* Calculate event response length */ evd_len = sizeof(SCCB_EVD_HDR) + sizeof(SCCB_SCEDIO_BK); switch(scedio_bk->flag1) { case SCCB_SCEDIO_FLG1_IOR: scedior_bk = (SCCB_SCEDIOR_BK*)(scedio_bk + 1); *scedior_bk = static_scedio_bk.io.r; evd_len += sizeof(SCCB_SCEDIOR_BK); break; case SCCB_SCEDIO_FLG1_IOV: scediov_bk = (SCCB_SCEDIOV_BK*)(scedio_bk + 1); *scediov_bk = static_scedio_bk.io.v ; evd_len += sizeof(SCCB_SCEDIOV_BK); break; default: PTT(PTT_CL_ERR,"*SERVC",(U32)evd_hdr->type,(U32)scedio_bk->flag1,scedio_bk->flag3); } /* Set length in event header */ STORE_HW(evd_hdr->totlen, evd_len); } /* Reset the pending flag */ scedio_pending = 0; /* Return true if a request was pending */ return pending_req; } else { #if !defined(NO_SIGABEND_HANDLER) switch(scedio_bk->flag1) { case SCCB_SCEDIO_FLG1_IOV: scediov_bk = (SCCB_SCEDIOV_BK*)(scedio_bk + 1); switch(scediov_bk->type) { case SCCB_SCEDIOV_TYPE_INIT: /* Kill the scedio thread if it is active */ if( scedio_tid ) { OBTAIN_INTLOCK(NULL); signal_thread(scedio_tid, SIGKILL); scedio_tid = 0; scedio_pending = 0; RELEASE_INTLOCK(NULL); } break; } break; } #endif /* Take a copy of the scedio_bk in the SCCB */ static_scedio_bk.scedio_bk = *scedio_bk; switch(scedio_bk->flag1) { case SCCB_SCEDIO_FLG1_IOR: scedior_bk = (SCCB_SCEDIOR_BK*)(scedio_bk + 1); static_scedio_bk.io.r = *scedior_bk; break; case SCCB_SCEDIO_FLG1_IOV: scediov_bk = (SCCB_SCEDIOV_BK*)(scedio_bk + 1); static_scedio_bk.io.v = *scediov_bk; break; default: PTT(PTT_CL_ERR,"*SERVC",(U32)evd_hdr->type,(U32)scedio_bk->flag1,scedio_bk->flag3); } /* Create the scedio thread */ if( create_thread(&scedio_tid, &sysblk.detattr, ARCH_DEP(scedio_thread), &static_scedio_bk, "scedio_thread") ) return -1; scedio_pending = 1; } return 0; } /*-------------------------------------------------------------------*/ /* Function to request service processor I/O */ /*-------------------------------------------------------------------*/ void ARCH_DEP(sclp_scedio_request) (SCCB_HEADER *sccb) { SCCB_EVD_HDR *evd_hdr = (SCCB_EVD_HDR*)(sccb + 1); if( ARCH_DEP(scedio_request)(SCLP_WRITE_EVENT_DATA, evd_hdr) ) { /* Set response code X'0040' in SCCB header */ sccb->reas = SCCB_REAS_NONE; sccb->resp = SCCB_RESP_BACKOUT; } else { /* Set response code X'0020' in SCCB header */ sccb->reas = SCCB_REAS_NONE; sccb->resp = SCCB_RESP_COMPLETE; } /* Indicate Event Processed */ evd_hdr->flag |= SCCB_EVD_FLAG_PROC; } /*-------------------------------------------------------------------*/ /* Function to read service processor I/O event data */ /*-------------------------------------------------------------------*/ void ARCH_DEP(sclp_scedio_event) (SCCB_HEADER *sccb) { SCCB_EVD_HDR *evd_hdr = (SCCB_EVD_HDR*)(sccb + 1); U16 sccb_len; U16 evd_len; if( ARCH_DEP(scedio_request)(SCLP_READ_EVENT_DATA, evd_hdr) ) { /* Update SCCB length field if variable request */ if (sccb->type & SCCB_TYPE_VARIABLE) { FETCH_HW(evd_len, evd_hdr->totlen); sccb_len = evd_len + sizeof(SCCB_HEADER); STORE_HW(sccb->length, sccb_len); sccb->type &= ~SCCB_TYPE_VARIABLE; } /* Set response code X'0020' in SCCB header */ sccb->reas = SCCB_REAS_NONE; sccb->resp = SCCB_RESP_COMPLETE; } } #endif /*defined(FEATURE_SCEDIO)*/ #if !defined(_GEN_ARCH) #if defined(_ARCHMODE2) #define _GEN_ARCH _ARCHMODE2 #include "scedasd.c" #endif #if defined(_ARCHMODE3) #undef _GEN_ARCH #define _GEN_ARCH _ARCHMODE3 #include "scedasd.c" #endif /*-------------------------------------------------------------------*/ /* Service Processor Load (load/ipl from the specified file) */ /*-------------------------------------------------------------------*/ int load_hmc (char *fname, int cpu, int clear) { switch(sysblk.arch_mode) { #if defined(_370) case ARCH_370: return s370_load_hmc (fname, cpu, clear); #endif #if defined(_390) case ARCH_390: return s390_load_hmc (fname, cpu, clear); #endif #if defined(_900) case ARCH_900: /* z/Arch always starts out in ESA390 mode */ return s390_load_hmc (fname, cpu, clear); #endif } return -1; } /*-------------------------------------------------------------------*/ /* Load/Read specified file into absolute main storage */ /*-------------------------------------------------------------------*/ int load_main (char *fname, RADR startloc) { switch(sysblk.arch_mode) { #if defined(_370) case ARCH_370: return s370_load_main (fname, startloc); #endif #if defined(_390) case ARCH_390: return s390_load_main (fname, startloc); #endif #if defined(_900) case ARCH_900: return z900_load_main (fname, startloc); #endif } return -1; } #endif /*!defined(_GEN_ARCH)*/ hercules-3.07/scsitape.c000644 000765 000765 00000236675 11321734033 016742 0ustar00jmaynardjmaynard000000 000000 //////////////////////////////////////////////////////////////////////////////////// // SCSITAPE.C -- Hercules SCSI tape handling module // // (c) Copyright "Fish" (David B. Trout), 2005-2009. Released under // the Q Public License (http://www.hercules-390.org/herclic.html) // as modifications to Hercules. //////////////////////////////////////////////////////////////////////////////////// // // This module contains only the support for SCSI tapes. Please see // the 'tapedev.c' (and possibly other) source module(s) for infor- // mation regarding other supported emulated tape/media formats. // //////////////////////////////////////////////////////////////////////////////////// // $Id: scsitape.c 5587 2009-12-31 15:05:57Z rbowler $ #include "hstdinc.h" #include "hercules.h" #include "scsitape.h" #if defined(OPTION_SCSI_TAPE) /*-------------------------------------------------------------------*/ /* Messages issued by this module are prefixed HHCTA3nn */ /*-------------------------------------------------------------------*/ //#define ENABLE_TRACING_STMTS // (Fish: DEBUGGING) #ifdef ENABLE_TRACING_STMTS #if !defined(DEBUG) #warning DEBUG required for ENABLE_TRACING_STMTS #endif // (TRACE, ASSERT, and VERIFY macros are #defined in hmacros.h) #else #undef TRACE #define TRACE 1 ? ((void)0) : logmsg #undef ASSERT #define ASSERT(a) #undef VERIFY #define VERIFY(a) ((void)(a)) #endif // (the following is just a [slightly] shorter name for our own internal use) #define SLOW_UPDATE_STATUS_TIMEOUT MAX_NORMAL_SCSI_DRIVE_QUERY_RESPONSE_TIMEOUT_USECS /*-------------------------------------------------------------------*/ /* Open a SCSI tape device */ /* */ /* If successful, the file descriptor is stored in the device block */ /* and the return value is zero. Otherwise the return value is -1. */ /* */ /* Note that not having a tape mounted is a non-fatal error (rc==0)) */ /* */ /* If the status indicates the tape is not mounted or a good status */ /* cannot otherwise be obtained, the file descriptor is CLOSED but */ /* THE RETURN CODE IS STILL == 0 !!!! */ /* */ /* ** WARNING! ** */ /* */ /* The caller MUST check for a valid (non-negative) file descriptor */ /* before trying to use it if this function returns 0 == success!! */ /* */ /* A success == 0 return means the device filename CAN be opened, */ /* but not necessarily that the file can be used! If the file cannot */ /* be used (i.e. no tape mounted), the file is CLOSED but the return */ /* code is still == 0. */ /* */ /* The return code is -1 ONLY when the filename itself is invalid */ /* and the device file thus cannot even be opened. */ /* */ /*-------------------------------------------------------------------*/ int open_scsitape (DEVBLK *dev, BYTE *unitstat, BYTE code) { int rc; /* Is an open for this device already in progress? */ obtain_lock( &dev->stape_getstat_lock ); if ( dev->stape_mountmon_tid ) { release_lock( &dev->stape_getstat_lock ); /* Yes. Device is good but no tape is mounted (yet) */ build_senseX(TAPE_BSENSE_TAPEUNLOADED,dev,unitstat,code); return 0; // (quick exit; in progress == open success) } ASSERT( dev->fd < 0 ); // (sanity check) dev->fd = -1; dev->sstat = GMT_DR_OPEN( -1 ); release_lock( &dev->stape_getstat_lock ); /* Open the SCSI tape device */ dev->readonly = 0; rc = open_tape (dev->filename, O_RDWR | O_BINARY | O_NONBLOCK); if (rc < 0 && EROFS == errno ) { dev->readonly = 1; rc = open_tape (dev->filename, O_RDONLY | O_BINARY | O_NONBLOCK); } /* Check for successful open */ if (rc < 0) { logmsg (_("HHCTA324E Error opening %u:%4.4X=%s; errno=%d: %s\n"), SSID_TO_LCSS(dev->ssid), dev->devnum, dev->filename, errno, strerror(errno)); sysblk.auto_scsi_mount_secs = 0; // (forced) build_senseX(TAPE_BSENSE_ITFERROR,dev,unitstat,code); return -1; // (FATAL error; device cannot be opened) } define_BOT_pos( dev ); // (always after successful open) /* Store the file descriptor in the device block */ obtain_lock( &dev->stape_getstat_lock ); dev->fd = rc; release_lock( &dev->stape_getstat_lock ); /* Obtain the initial tape device/media status information */ /* and start the mount-monitoring thread if option enabled */ int_scsi_status_update( dev, 0 ); /* Asynchronous open now in progress? */ obtain_lock( &dev->stape_getstat_lock ); if ( dev->stape_mountmon_tid ) { release_lock( &dev->stape_getstat_lock ); /* Yes. Device is good but no tape is mounted (yet) */ build_senseX(TAPE_BSENSE_TAPEUNLOADED,dev,unitstat,code); return 0; // (quick exit; in progress == open success) } release_lock( &dev->stape_getstat_lock ); /* Finish up the open process... */ if ( STS_NOT_MOUNTED( dev ) ) { /* Intervention required if no tape is currently mounted. Note: we return "success" because the filename is good (device CAN be opened) but close the file descriptor since there's no tape currently mounted on the drive.*/ #if !defined( _MSVC_ ) obtain_lock( &dev->stape_getstat_lock ); dev->fd = -1; release_lock( &dev->stape_getstat_lock ); close_tape( rc ); #endif // !_MSVC_ build_senseX(TAPE_BSENSE_TAPEUNLOADED,dev,unitstat,code); return 0; // (because device file IS valid and CAN be opened) } /* Set variable length block processing to complete the open */ if ( finish_scsitape_open( dev, unitstat, code ) != 0 ) { /* We cannot use this device; fail the open. 'finish_scsitape_open' has already issued the error message and closed the device. */ return -1; // (open failure) } return 0; // (open success) } /* end function open_scsitape */ /*-------------------------------------------------------------------*/ /* Finish SCSI Tape open: sets variable length block i/o mode... */ /* Returns 0 == success, -1 = failure. */ /*-------------------------------------------------------------------*/ /* THIS FUNCTION IS AN INTEGRAL PART OF TAPE OPEN PROCESSING! */ /* If this function fails then the overall tape device open fails! */ /*-------------------------------------------------------------------*/ int finish_scsitape_open( DEVBLK *dev, BYTE *unitstat, BYTE code ) { int rc; /* Return code */ int oflags; /* re-open flags */ struct mtop opblk; /* Area for MTIOCTOP ioctl */ /* Switch drive over to BLOCKING-mode i/o... */ close_tape( dev->fd ); oflags = O_BINARY | (dev->readonly ? O_RDONLY : O_RDWR); VERIFY( (dev->fd = open_tape (dev->filename, oflags)) > 0); /* Since a tape was just mounted, reset the blockid back to zero */ dev->blockid = 0; dev->fenced = 0; /* Set the tape device to process variable length blocks */ opblk.mt_op = MTSETBLK; opblk.mt_count = 0; rc = ioctl_tape (dev->fd, MTIOCTOP, (char*)&opblk); if (rc < 0) { /* Device cannot be used; fail the open */ int save_errno = errno; rc = dev->fd; dev->fd = -1; close_tape( rc ); errno = save_errno; logmsg (_("HHCTA330E Error setting attributes for %u:%4.4X=%s; errno=%d: %s\n"), SSID_TO_LCSS(dev->ssid), dev->devnum, dev->filename, errno, strerror(errno)); build_senseX(TAPE_BSENSE_ITFERROR,dev,unitstat,code); return -1; /* (fatal error) */ } #if defined( HAVE_DECL_MTEWARN ) && HAVE_DECL_MTEWARN // Try to request EOM/EOT (end-of-media/tape) early-warning // Note: if it fails, oh well. There's no need to scare the // user with a warning message. We'll either get the warning // or we won't. Either way there's nothing we can do about it. // We did the best we could. opblk.mt_op = MTEWARN; opblk.mt_count = dev->eotmargin; ioctl_tape (dev->fd, MTIOCTOP, (char*)&opblk); // (ignore any error; it either worked or it didn't) #endif // defined( HAVE_DECL_MTEWARN ) && HAVE_DECL_MTEWARN return 0; /* (success) */ } /* end function finish_scsitape_open */ /*-------------------------------------------------------------------*/ /* Close SCSI tape device file */ /*-------------------------------------------------------------------*/ void close_scsitape(DEVBLK *dev) { int rc = 0; obtain_lock( &dev->stape_getstat_lock ); dev->stape_threads_exit = 1; // (state our intention) // Close the file if it's open... if (dev->fd >= 0) { if (dev->stape_close_rewinds) { struct mtop opblk; // opblk.mt_op = MTLOAD; // (not sure which is more correct) opblk.mt_op = MTREW; opblk.mt_count = 1; if ((rc = ioctl_tape ( dev->fd, MTIOCTOP, (char*)&opblk)) != 0) { logmsg (_("HHCTA373W Error rewinding %u:%4.4X=%s; errno=%d: %s\n"), SSID_TO_LCSS(dev->ssid), dev->devnum, dev->filename, errno, strerror(errno)); } } // Shutdown the worker threads // if they're still running... shutdown_worker_threads( dev ); // Close tape drive... close_tape( dev->fd ); dev->fd = -1; dev->blockid = -1; dev->curfilen = 0; dev->nxtblkpos = 0; dev->prvblkpos = -1; } else { // Shutdown the worker threads // if they're still running... shutdown_worker_threads( dev ); } dev->sstat = GMT_DR_OPEN(-1); dev->stape_getstat_sstat = GMT_DR_OPEN(-1); dev->stape_getstat_busy = 0; dev->stape_threads_exit = 0; dev->fenced = rc >= 0 ? 0 : 1; release_lock( &dev->stape_getstat_lock ); } /* end function close_scsitape */ /*-------------------------------------------------------------------*/ /* Read a block from a SCSI tape device */ /* */ /* If successful, return value is block length read. */ /* If a tapemark was read, the return value is zero, and the */ /* current file number in the device block is incremented. */ /* If error, return value is -1 and unitstat is set to CE+DE+UC */ /*-------------------------------------------------------------------*/ int read_scsitape (DEVBLK *dev, BYTE *buf, BYTE *unitstat,BYTE code) { int rc; /* int save_errno; */ rc = read_tape (dev->fd, buf, MAX_BLKLEN); if (rc >= 0) { dev->blockid++; /* Increment current file number if tapemark was read */ if (rc == 0) dev->curfilen++; /* Return block length or zero if tapemark */ return rc; } /* Handle read error condition */ logmsg (_("HHCTA332E Error reading data block from %u:%4.4X=%s; errno=%d: %s\n"), SSID_TO_LCSS(dev->ssid), dev->devnum, dev->filename, errno, strerror(errno)); if ( STS_NOT_MOUNTED( dev ) ) build_senseX(TAPE_BSENSE_TAPEUNLOADED,dev,unitstat,code); else build_senseX(TAPE_BSENSE_READFAIL,dev,unitstat,code); return -1; } /* end function read_scsitape */ /*-------------------------------------------------------------------*/ /* Write a block to a SCSI tape device */ /* */ /* If successful, return value is zero. */ /* If error, return value is -1 and unitstat is set to CE+DE+UC */ /*-------------------------------------------------------------------*/ int write_scsitape (DEVBLK *dev, BYTE *buf, U16 len, BYTE *unitstat, BYTE code) { int rc; int save_errno; /* Write data block to SCSI tape device */ rc = write_tape (dev->fd, buf, len); #if defined( _MSVC_ ) if (errno == ENOSPC) dev->eotwarning = 1; #endif if (rc >= len) { dev->blockid++; return 0; } /* LINUX EOM BEHAVIOUR WHEN WRITING When the end of medium early warning is encountered, the current write is finished and the number of bytes is returned. The next write returns -1 and errno is set to ENOSPC. To enable writing a trailer, the next write is allowed to proceed and, if successful, the number of bytes is returned. After this, -1 and the number of bytes are alternately returned until the physical end of medium (or some other error) occurs. */ if (errno == ENOSPC) { int_scsi_status_update( dev, 0 ); rc = write_tape (dev->fd, buf, len); if (rc >= len) { dev->eotwarning = 1; dev->blockid++; return 0; } } /* Handle write error condition... */ save_errno = errno; { logmsg (_("HHCTA333E Error writing data block to %u:%4.4X=%s; errno=%d: %s\n"), SSID_TO_LCSS(dev->ssid), dev->devnum, dev->filename, errno, strerror(errno)); int_scsi_status_update( dev, 0 ); } errno = save_errno; if ( STS_NOT_MOUNTED( dev ) ) build_senseX(TAPE_BSENSE_TAPEUNLOADED,dev,unitstat,code); else { if (errno == EIO) { if(STS_EOT(dev)) build_senseX(TAPE_BSENSE_ENDOFTAPE,dev,unitstat,code); else build_senseX(TAPE_BSENSE_WRITEFAIL,dev,unitstat,code); } else build_senseX(TAPE_BSENSE_ITFERROR,dev,unitstat,code); } return -1; } /* end function write_scsitape */ /*-------------------------------------------------------------------*/ /* Write a tapemark to a SCSI tape device */ /* */ /* If successful, return value is zero. */ /* If error, return value is -1 and unitstat is set to CE+DE+UC */ /*-------------------------------------------------------------------*/ int write_scsimark (DEVBLK *dev, BYTE *unitstat,BYTE code) { int rc, save_errno; /* Write tape mark to SCSI tape */ rc = int_write_scsimark( dev ); #if defined( _MSVC_ ) if (errno == ENOSPC) dev->eotwarning = 1; #endif if (rc >= 0) return 0; /* LINUX EOM BEHAVIOUR WHEN WRITING When the end of medium early warning is encountered, the current write is finished and the number of bytes is returned. The next write returns -1 and errno is set to ENOSPC. To enable writing a trailer, the next write is allowed to proceed and, if successful, the number of bytes is returned. After this, -1 and the number of bytes are alternately returned until the physical end of medium (or some other error) occurs. */ if (errno == ENOSPC) { int_scsi_status_update( dev, 0 ); if (int_write_scsimark( dev ) >= 0) { dev->eotwarning = 1; return 0; } } /* Handle write error condition... */ save_errno = errno; { logmsg (_("HHCTA334E Error writing tapemark to %u:%4.4X=%s; errno=%d: %s\n"), SSID_TO_LCSS(dev->ssid), dev->devnum, dev->filename, errno, strerror(errno)); int_scsi_status_update( dev, 0 ); } errno = save_errno; if ( STS_NOT_MOUNTED( dev ) ) { build_senseX(TAPE_BSENSE_TAPEUNLOADED,dev,unitstat,code); } else { switch(errno) { case EIO: if(STS_EOT(dev)) build_senseX(TAPE_BSENSE_ENDOFTAPE,dev,unitstat,code); else build_senseX(TAPE_BSENSE_WRITEFAIL,dev,unitstat,code); break; case ENOSPC: build_senseX(TAPE_BSENSE_ENDOFTAPE,dev,unitstat,code); break; default: build_senseX(TAPE_BSENSE_ITFERROR,dev,unitstat,code); break; } } return -1; } /* end function write_scsimark */ /*-------------------------------------------------------------------*/ /* (internal 'write_scsimark' helper function) */ /*-------------------------------------------------------------------*/ int int_write_scsimark (DEVBLK *dev) // (internal function) { int rc; struct mtop opblk; opblk.mt_op = MTWEOF; opblk.mt_count = 1; rc = ioctl_tape (dev->fd, MTIOCTOP, (char*)&opblk); if (rc >= 0) { /* Increment current file number since tapemark was written */ /*dev->curfilen++;*/ /* (CCW processor handles this automatically so there's no need for us to do it here) */ /* (tapemarks count as block identifiers too!) */ dev->blockid++; } return rc; } /*-------------------------------------------------------------------*/ /* Synchronize a SCSI tape device (i.e. commit its data to tape) */ /* */ /* If successful, return value is zero. */ /* If error, return value is -1 and unitstat is set to CE+DE+UC */ /*-------------------------------------------------------------------*/ int sync_scsitape (DEVBLK *dev, BYTE *unitstat,BYTE code) { int rc; int save_errno; struct mtop opblk; /* GA32-0566-02 ("IBM Tape Device Drivers - Programming Reference"): STIOCQRYPOS "[...] A write filemark of count 0 is always issued to the drive, which flushes all data from the buffers to the tape media. After the write filemark completes, the query is issued." Write Tapemark "[...] The WriteTapemark entry point may also be called with the dwTapemarkCount parameter set to 0 and the bImmediate parameter set to FALSE. This has the effect of committing any uncommitted data written by previous WriteFile calls ... to the media." */ opblk.mt_op = MTWEOF; opblk.mt_count = 0; // (zero to force a commit) if ((rc = ioctl_tape (dev->fd, MTIOCTOP, (char*)&opblk)) >= 0) { #if defined( _MSVC_ ) if (errno == ENOSPC) dev->eotwarning = 1; #endif return 0; // (success) } /* LINUX EOM BEHAVIOUR WHEN WRITING When the end of medium early warning is encountered, the current write is finished and the number of bytes is returned. The next write returns -1 and errno is set to ENOSPC. To enable writing a trailer, the next write is allowed to proceed and, if successful, the number of bytes is returned. After this, -1 and the number of bytes are alternately returned until the physical end of medium (or some other error) occurs. */ if (errno == ENOSPC) { int_scsi_status_update( dev, 0 ); opblk.mt_op = MTWEOF; opblk.mt_count = 0; // (zero to force a commit) if ((rc = ioctl_tape (dev->fd, MTIOCTOP, (char*)&opblk)) >= 0) { dev->eotwarning = 1; return 0; } } /* Handle write error condition... */ save_errno = errno; { logmsg (_("HHCTA389E Synchronize error on " "%u:%4.4X=%s; errno=%d: %s\n"), SSID_TO_LCSS(dev->ssid), dev->devnum, dev->filename, errno, strerror(errno)); int_scsi_status_update( dev, 0 ); } errno = save_errno; if ( STS_NOT_MOUNTED( dev ) ) { build_senseX(TAPE_BSENSE_TAPEUNLOADED,dev,unitstat,code); } else { switch(errno) { case EIO: if(STS_EOT(dev)) build_senseX(TAPE_BSENSE_ENDOFTAPE,dev,unitstat,code); else build_senseX(TAPE_BSENSE_WRITEFAIL,dev,unitstat,code); break; case ENOSPC: build_senseX(TAPE_BSENSE_ENDOFTAPE,dev,unitstat,code); break; default: build_senseX(TAPE_BSENSE_ITFERROR,dev,unitstat,code); break; } } return -1; } /* end function sync_scsitape */ /*-------------------------------------------------------------------*/ /* Forward space over next block of SCSI tape device */ /* */ /* If successful, return value is +1. */ /* If the block skipped was a tapemark, the return value is zero, */ /* and the current file number in the device block is incremented. */ /* If error, return value is -1 and unitstat is set to CE+DE+UC */ /*-------------------------------------------------------------------*/ int fsb_scsitape (DEVBLK *dev, BYTE *unitstat,BYTE code) { int rc; int save_errno; struct mtop opblk; /* Forward space block on SCSI tape */ opblk.mt_op = MTFSR; opblk.mt_count = 1; rc = ioctl_tape (dev->fd, MTIOCTOP, (char*)&opblk); if ( rc >= 0 ) { dev->blockid++; /* Return +1 to indicate forward space successful */ return +1; } /* Check for spacing over a tapemark... */ save_errno = errno; { int_scsi_status_update( dev, 0 ); } errno = save_errno; // PROGRAMMING NOTE: please see the "Programming Note" in the // 'bsb_scsitape' function regarding usage of the 'EOF' status // to detect spacing over tapemarks. if ( EIO == errno && STS_EOF(dev) ) // (fwd-spaced over tapemark?) { dev->curfilen++; dev->blockid++; /* Return 0 to indicate tapemark was spaced over */ return 0; } /* Bona fide forward space block error ... */ save_errno = errno; { logmsg (_("HHCTA335E Forward space block error on %u:%4.4X=%s; errno=%d: %s\n"), SSID_TO_LCSS(dev->ssid), dev->devnum, dev->filename, errno, strerror(errno)); } errno = save_errno; if ( STS_NOT_MOUNTED( dev ) ) { build_senseX(TAPE_BSENSE_TAPEUNLOADED,dev,unitstat,code); } else { switch(errno) { case EIO: if(STS_EOT(dev)) build_senseX(TAPE_BSENSE_ENDOFTAPE,dev,unitstat,code); else build_senseX(TAPE_BSENSE_READFAIL,dev,unitstat,code); break; case ENOSPC: build_senseX(TAPE_BSENSE_ENDOFTAPE,dev,unitstat,code); break; default: build_senseX(TAPE_BSENSE_ITFERROR,dev,unitstat,code); break; } } return -1; } /* end function fsb_scsitape */ /*-------------------------------------------------------------------*/ /* Backspace to previous block of SCSI tape device */ /* */ /* If successful, return value is +1. */ /* If the block is a tapemark, the return value is zero, */ /* and the current file number in the device block is decremented. */ /* If error, return value is -1 and unitstat is set to CE+DE+UC */ /*-------------------------------------------------------------------*/ int bsb_scsitape (DEVBLK *dev, BYTE *unitstat,BYTE code) { int rc; int save_errno; struct mtop opblk; struct mtget starting_mtget; /* PROGRAMMING NOTE: There is currently no way to distinguish ** between a "normal" backspace-block error and a "backspaced- ** into-loadpoint" i/o error, since the only error indication ** we get [in response to a backspace block attempt] is simply ** 'EIO'. (Interrogating the status AFTER the fact (to see if ** we're positioned at loadpoint) doesn't tell us whether we ** were already positioned at loadpoint *before* the error was ** was encountered or whether we're only positioned at load- ** point because we *did* in fact backspace over the very first ** block on the tape (and are thus now, after the fact, sitting ** at loadpoint because we *did* backspace over a block but it ** just got an error for some reason). ** ** Thus, we have absolutely no choice here but to retrieve the ** status BEFORE we attempt the i/o to see if we're ALREADY at ** loadpoint. If we are, then we immediately return an error ** ("backspaced-into-loadpoint") *without* even attemting the ** i/o at all. If we're *not* already sitting at loadpoint how- ** ever, then we go ahead an attempt the i/o and then check for ** an error afterwards. */ /* Obtain tape status before backward space... */ int_scsi_status_update( dev, 0 ); /* (save the current status before the i/o in case of error) */ memcpy( &starting_mtget, &dev->mtget, sizeof( struct mtget ) ); /* Unit check if already at start of tape */ if ( STS_BOT( dev ) ) { dev->eotwarning = 0; build_senseX(TAPE_BSENSE_LOADPTERR,dev,unitstat,code); return -1; } /* Attempt the backspace i/o...*/ opblk.mt_op = MTBSR; opblk.mt_count = 1; rc = ioctl_tape (dev->fd, MTIOCTOP, (char*)&opblk); if ( rc >= 0 ) { dev->blockid--; /* Return +1 to indicate backspace successful */ return +1; } /* Retrieve new status after the [supposed] i/o error... */ save_errno = errno; { int_scsi_status_update( dev, 0 ); } errno = save_errno; /* Check for backspacing over tapemark... */ /* PROGRAMMING NOTE: on Windows, our scsi tape driver (w32stape.c) ** sets 'EOF' status whenever a tapemark is spaced over in EITHER ** direction (forward OR backward), whereas *nix operating systems ** do not. They set 'EOF' status only when FORWARD spacing over a ** tapemark but not when BACKSPACING over one. ** ** (Apparently the EOF status was actually meant to mean that the ** tape is "PHYSICALLY POSITIONED PAST [physical] eof" (i.e. past ** an "eof marker" (i.e. a tapemark)) and nothing more. That is to ** say, it is apparently NOT meant to mean a tapemark was passed ** over, but rather only that you're "POSITIONED PAST" a tapemark.) ** ** Therefore since 'EOF' status will thus *NEVER* be set whenever ** a tapemark is spaced over in the *BACKWARD* direction [on non- ** Windows operating systems], we need some other means of distin- ** guishing between true backspace-block i/o errors and ordinary ** spacing over a tapemark (which is NOT an i/o error but which ** *is* an "out of the ordinary" (unit exception) type of event). ** ** Extensive research on this issue has revealed the *ONLY* semi- ** reliable means of distinguishing between them is by checking ** the "file#" and "block#" fields of the status structure after ** the supposed i/o error. If the file# is one less than it was ** before and the block# is -1, then a tapemark was simply spaced ** over. If the file# and block# is anything else however, then ** the originally reported error was a bona-fide i/o error (i.e. ** the original backspace-block (MTBSR) actually *failed*). ** ** I say "semi-reliable" because comments seem to indicate that ** the "file#" and "block#" fields of the mtget status structure ** "are not always used". The best that I can tell however, is ** most *nix operating systems *do* seem to maintain them. Thus, ** for now, we're going to rely on their accuracy since without ** them there's really no way whatsoever to distingish between ** a normal backspacing over a tapemark unit exception condition ** and a bona-fide i/o error (other than doing our own SCSI i/o ** of course (which we don't support (yet))). -- Fish, May 2008 */ if ( EIO == errno ) { #if defined( _MSVC_ ) /* Windows always sets 'EOF' status whenever a tapemark is spaced over in EITHER direction (forward OR backward) */ if ( STS_EOF(dev) ) /* (passed over tapemark?) */ #else // !defined( _MSVC_ ) /* Unix-type systems unfortunately do NOT set 'EOF' whenever backspacing over a tapemark (see PROGRAMMING NOTE above), so we need to check the status struct's file# and block# fields instead... */ /* (passed over tapemark?) */ if (1 && dev->mtget.mt_fileno == (starting_mtget.mt_fileno - 1) && dev->mtget.mt_blkno == -1 ) #endif // defined( _MSVC_ ) { dev->curfilen--; dev->blockid--; /* Return 0 to indicate tapemark was spaced over */ return 0; } } /* Bona fide backspace block i/o error ... */ save_errno = errno; { logmsg (_("HHCTA336E Backspace block error on %u:%4.4X=%s; errno=%d: %s\n"), SSID_TO_LCSS(dev->ssid), dev->devnum, dev->filename, errno, strerror(errno)); } errno = save_errno; if ( STS_NOT_MOUNTED( dev ) ) build_senseX(TAPE_BSENSE_TAPEUNLOADED,dev,unitstat,code); else { if ( EIO == errno && STS_BOT(dev) ) { dev->eotwarning = 0; build_senseX(TAPE_BSENSE_LOADPTERR,dev,unitstat,code); } else build_senseX(TAPE_BSENSE_LOCATEERR,dev,unitstat,code); } return -1; } /* end function bsb_scsitape */ /*-------------------------------------------------------------------*/ /* Forward space to next file of SCSI tape device */ /* */ /* If successful, the return value is zero, and the current file */ /* number in the device block is incremented. */ /* If error, return value is -1 and unitstat is set to CE+DE+UC */ /*-------------------------------------------------------------------*/ int fsf_scsitape (DEVBLK *dev, BYTE *unitstat,BYTE code) { int rc; int save_errno; struct mtop opblk; /* Forward space file on SCSI tape */ opblk.mt_op = MTFSF; opblk.mt_count = 1; rc = ioctl_tape (dev->fd, MTIOCTOP, (char*)&opblk); /* Since we have no idea how many blocks we've skipped over (as a result of doing the forward-space file), we now have no clue as to what the proper current blockid should be. */ dev->blockid = -1; // (actual position now unknown!) if ( rc >= 0 ) { dev->curfilen++; return 0; } /* Handle error condition */ dev->fenced = 1; // (actual position now unknown!) save_errno = errno; { logmsg (_("HHCTA337E Forward space file error on %u:%4.4X=%s; errno=%d: %s\n"), SSID_TO_LCSS(dev->ssid), dev->devnum, dev->filename, errno, strerror(errno)); } errno = save_errno; if ( STS_NOT_MOUNTED( dev ) ) { build_senseX(TAPE_BSENSE_TAPEUNLOADED,dev,unitstat,code); } else { switch(errno) { case EIO: if(STS_EOT(dev)) build_senseX(TAPE_BSENSE_ENDOFTAPE,dev,unitstat,code); else build_senseX(TAPE_BSENSE_READFAIL,dev,unitstat,code); break; case ENOSPC: build_senseX(TAPE_BSENSE_ENDOFTAPE,dev,unitstat,code); break; default: build_senseX(TAPE_BSENSE_ITFERROR,dev,unitstat,code); break; } } return -1; } /* end function fsf_scsitape */ /*-------------------------------------------------------------------*/ /* Backspace to previous file of SCSI tape device */ /* */ /* If successful, the return value is zero, and the current file */ /* number in the device block is decremented. */ /* If error, return value is -1 and unitstat is set to CE+DE+UC */ /*-------------------------------------------------------------------*/ int bsf_scsitape (DEVBLK *dev, BYTE *unitstat,BYTE code) { int rc; int save_errno; struct mtop opblk; /* PROGRAMMING NOTE: There is currently no way to distinguish ** between a "normal" backspace-file error and a "backspaced- ** into-loadpoint" i/o error, since the only error indication ** we get [in response to a backspace file attempt] is simply ** 'EIO'. (Interrogating the status AFTER the fact (to see if ** we're positioned at loadpoint) doesn't tell us whether we ** were already positioned at loadpoint *before* the error was ** was encountered or whether we're only positioned ar load- ** point because we *did* in fact backspace over a BOT tape- ** mark on the tape (and are thus now, after the fact, sitting ** at loadpoint because we *did* backspace over a tape-mark ** but it just got an error for some reason). ** ** Thus, we have absolutely no choice here but to retrieve the ** status BEFORE we attempt the i/o to see if we're ALREADY at ** loadpoint. If we are, then we immediately return an error ** ("backspaced-into-loadpoint") *without* even attemting the ** i/o at all. If we're *not* already sitting at loadpoint how- ** ever, then we go ahead an attempt the i/o and then check for ** an error afterwards. */ /* Obtain tape status before backward space... (no choice!) */ int_scsi_status_update( dev, 0 ); /* Unit check if already at start of tape */ if ( STS_BOT( dev ) ) { dev->eotwarning = 0; build_senseX(TAPE_BSENSE_LOADPTERR,dev,unitstat,code); return -1; } /* Attempt the backspace i/o...*/ opblk.mt_op = MTBSF; opblk.mt_count = 1; rc = ioctl_tape (dev->fd, MTIOCTOP, (char*)&opblk); /* Since we have no idea how many blocks we've skipped over (as a result of doing the back-space file), we now have no clue as to what the proper current blockid should be. */ dev->blockid = -1; // (actual position now unknown!) if ( rc >= 0 ) { dev->curfilen--; return 0; } /* Handle error condition */ dev->fenced = 1; // (actual position now unknown!) save_errno = errno; { logmsg (_("HHCTA338E Backspace file error on %u:%4.4X=%s; errno=%d: %s\n"), SSID_TO_LCSS(dev->ssid), dev->devnum, dev->filename, errno, strerror(errno)); } errno = save_errno; if ( STS_NOT_MOUNTED( dev ) ) build_senseX(TAPE_BSENSE_TAPEUNLOADED,dev,unitstat,code); else { if ( EIO == errno && STS_BOT(dev) ) { dev->eotwarning = 0; build_senseX(TAPE_BSENSE_LOADPTERR,dev,unitstat,code); } else build_senseX(TAPE_BSENSE_LOCATEERR,dev,unitstat,code); } return -1; } /* end function bsf_scsitape */ /*-------------------------------------------------------------------*/ /* Rewind an SCSI tape device */ /*-------------------------------------------------------------------*/ int rewind_scsitape(DEVBLK *dev,BYTE *unitstat,BYTE code) { int rc; /* int save_errno; */ struct mtop opblk; // opblk.mt_op = MTLOAD; // (not sure which is more correct) opblk.mt_op = MTREW; opblk.mt_count = 1; rc = ioctl_tape (dev->fd, MTIOCTOP, (char*)&opblk); if ( rc >= 0 ) { dev->sstat |= GMT_BOT( -1 ); // (forced) dev->blockid = 0; dev->curfilen = 0; dev->fenced = 0; return 0; } dev->fenced = 1; // (because the rewind failed) dev->blockid = -1; // (because the rewind failed) dev->curfilen = -1; // (because the rewind failed) logmsg (_("HHCTA373E Error rewinding %u:%4.4X=%s; errno=%d: %s\n"), SSID_TO_LCSS(dev->ssid), dev->devnum, dev->filename, errno, strerror(errno)); if ( STS_NOT_MOUNTED( dev ) ) build_senseX(TAPE_BSENSE_TAPEUNLOADED,dev,unitstat,code); else build_senseX(TAPE_BSENSE_REWINDFAILED,dev,unitstat,code); return -1; } /* end function rewind_scsitape */ /*-------------------------------------------------------------------*/ /* Rewind Unload a SCSI tape device (and CLOSE it too!) */ /*-------------------------------------------------------------------*/ void int_scsi_rewind_unload(DEVBLK *dev, BYTE *unitstat, BYTE code ) { int rc; struct mtop opblk; // opblk.mt_op = MTUNLOAD; // (not sure which is more correct) opblk.mt_op = MTOFFL; opblk.mt_count = 1; rc = ioctl_tape (dev->fd, MTIOCTOP, (char*)&opblk); if ( rc >= 0 ) { dev->fenced = 0; if ( dev->ccwtrace || dev->ccwstep ) logmsg (_("HHCTA377I Tape %u:%4.4X unloaded\n"), SSID_TO_LCSS(dev->ssid), dev->devnum); // PR# tape/88: no sense with 'close_scsitape' // attempting a rewind if the tape is unloaded! dev->stape_close_rewinds = 0; // (skip rewind attempt) close_scsitape( dev ); // (required for REW UNLD) return; } dev->fenced = 1; // (because the rewind-unload failed) dev->curfilen = -1; // (because the rewind-unload failed) dev->blockid = -1; // (because the rewind-unload failed) logmsg ( _("HHCTA376E Error unloading %u:%4.4X=%s; errno=%d: %s\n" ), SSID_TO_LCSS(dev->ssid), dev->devnum, dev->filename, errno, strerror( errno ) ); if ( STS_NOT_MOUNTED( dev ) ) build_senseX(TAPE_BSENSE_TAPEUNLOADED,dev,unitstat,code); else build_senseX(TAPE_BSENSE_REWINDFAILED,dev,unitstat,code); } /* end function int_scsi_rewind_unload */ /*-------------------------------------------------------------------*/ /* Erase Gap */ /*-------------------------------------------------------------------*/ int erg_scsitape( DEVBLK *dev, BYTE *unitstat, BYTE code ) { #if defined( OPTION_SCSI_ERASE_GAP ) int rc; if (!dev->stape_no_erg) { struct mtop opblk; opblk.mt_op = MTERASE; opblk.mt_count = 0; // (zero means "short" erase-gap) rc = ioctl_tape( dev->fd, MTIOCTOP, (char*)&opblk ); #if defined( _MSVC_ ) if (errno == ENOSPC) dev->eotwarning = 1; #endif if ( rc < 0 ) { /* LINUX EOM BEHAVIOUR WHEN WRITING When the end of medium early warning is encountered, the current write is finished and the number of bytes is returned. The next write returns -1 and errno is set to ENOSPC. To enable writing a trailer, the next write is allowed to proceed and, if successful, the number of bytes is returned. After this, -1 and the number of bytes are alternately returned until the physical end of medium (or some other error) occurs. */ if (errno == ENOSPC) { int_scsi_status_update( dev, 0 ); opblk.mt_op = MTERASE; opblk.mt_count = 0; // (zero means "short" erase-gap) if ( (rc = ioctl_tape( dev->fd, MTIOCTOP, (char*)&opblk )) >= 0 ) dev->eotwarning = 1; } if ( rc < 0) { logmsg (_("HHCTA380E Erase Gap error on %u:%4.4X=%s; errno=%d: %s\n"), SSID_TO_LCSS(dev->ssid), dev->devnum, dev->filename, errno, strerror(errno)); build_senseX(TAPE_BSENSE_WRITEFAIL,dev,unitstat,code); return -1; } } } return 0; // (success) #else // !defined( OPTION_SCSI_ERASE_GAP ) UNREFERENCED ( dev ); UNREFERENCED ( code ); UNREFERENCED ( unitstat ); return 0; // (treat as nop) #endif // defined( OPTION_SCSI_ERASE_GAP ) } /* end function erg_scsitape */ /*-------------------------------------------------------------------*/ /* Data Security Erase */ /*-------------------------------------------------------------------*/ int dse_scsitape( DEVBLK *dev, BYTE *unitstat, BYTE code ) { #if defined( OPTION_SCSI_ERASE_TAPE ) struct mtop opblk; opblk.mt_op = MTERASE; opblk.mt_count = 1; // (one means "long" erase-tape) if ( ioctl_tape( dev->fd, MTIOCTOP, (char*)&opblk ) < 0 ) { logmsg (_("HHCTA381E Data Security Erase error on %u:%4.4X=%s; errno=%d: %s\n"), SSID_TO_LCSS(dev->ssid), dev->devnum, dev->filename, errno, strerror(errno)); build_senseX(TAPE_BSENSE_WRITEFAIL,dev,unitstat,code); return -1; } return 0; // (success) #else // !defined( OPTION_SCSI_ERASE_TAPE ) UNREFERENCED ( dev ); UNREFERENCED ( code ); UNREFERENCED ( unitstat ); return 0; // (treat as nop) #endif // defined( OPTION_SCSI_ERASE_TAPE ) } /* end function dse_scsitape */ /*-------------------------------------------------------------------*/ /* readblkid_scsitape */ /*-------------------------------------------------------------------*/ /* Output values are returned in BIG-ENDIAN guest format... */ /*-------------------------------------------------------------------*/ int readblkid_scsitape ( DEVBLK* dev, BYTE* logical, BYTE* physical ) { // ZZ FIXME: The two blockid fields that READ BLOCK ID // are returning are the "Channel block ID" and "Device // block ID" fields, which correspond directly to the // SCSI "First block location" and "Last block location" // fields (as returned by a READ POSITION scsi command), // so we really SHOULD be doing our own direct scsi i/o // for ourselves so we can retrieve BOTH of those values // directly from the real/actual physical device itself, // but until we can add code to Herc to do that, we must // return the same value for each since ioctl(MTIOCPOS) // only returns us one value (the logical position) and // not both that we really prefer... // (And for the record, we want the "Channel block ID" // value, also known as the SCSI "First block location" // value, also known as the >>LOGICAL<< value and *NOT* // the absolute/physical device-relative value) struct mtpos mtpos; BYTE blockid[4]; if (ioctl_tape( dev->fd, MTIOCPOS, (char*) &mtpos ) < 0 ) { /* Informative ERROR message if tracing */ int save_errno = errno; { if ( dev->ccwtrace || dev->ccwstep ) logmsg(_("HHCTA382W ioctl_tape(MTIOCPOS=MTTELL) failed on %4.4X = %s: %s\n") ,dev->devnum ,dev->filename ,strerror(errno) ); } errno = save_errno; return -1; // (errno should already be set) } // Convert MTIOCPOS value to guest BIG-ENDIAN format... mtpos.mt_blkno = CSWAP32( mtpos.mt_blkno ); // (guest <- host) // Handle emulated vs. physical tape-device block-id format issue... blockid_actual_to_emulated( dev, (BYTE*)&mtpos.mt_blkno, blockid ); // Until we can add code to Herc to do direct SCSI i/o (so that // we can retrieve BOTH values directly from the device itself), // we have no choice but to return the same value for each since // the ioctl(MTIOCPOS) call only returns the logical value and // not also the physical value that we wish it would... if (logical) memcpy( logical, &blockid[0], 4 ); if (physical) memcpy( physical, &blockid[0], 4 ); return 0; // (success) } /* end function readblkid_scsitape */ /*-------------------------------------------------------------------*/ /* locateblk_scsitape */ /*-------------------------------------------------------------------*/ /* Input value is passed in little-endian host format... */ /*-------------------------------------------------------------------*/ int locateblk_scsitape ( DEVBLK* dev, U32 blockid, BYTE *unitstat, BYTE code ) { int rc; struct mtop mtop; UNREFERENCED( unitstat ); // (not used) UNREFERENCED( code ); // (not used) // Convert the passed host-format blockid value into the proper // 32-bit vs. 22-bit guest-format the physical device expects ... blockid = CSWAP32( blockid ); // (guest <- host) blockid_emulated_to_actual( dev, (BYTE*)&blockid, (BYTE*)&mtop.mt_count ); mtop.mt_count = CSWAP32( mtop.mt_count ); // (host <- guest) mtop.mt_op = MTSEEK; // Ask the actual hardware to do an actual physical locate... if ((rc = ioctl_tape( dev->fd, MTIOCTOP, (char*)&mtop )) < 0) { int save_errno = errno; { if ( dev->ccwtrace || dev->ccwstep ) logmsg(_("HHCTA383W ioctl_tape(MTIOCTOP=MTSEEK) failed on %4.4X = %s: %s\n") ,dev->devnum ,dev->filename ,strerror(errno) ); } errno = save_errno; } return rc; } /*********************************************************************/ /** **/ /** BLOCK-ID ADJUSTMENT FUNCTIONS **/ /** **/ /*********************************************************************/ /* The following conversion functions compensate for the fact that the emulated device type might actually be completely different from the actual real [SCSI] device being used for the emulation. That is to say, the actual SCSI device being used may actually be a 3590 type device but is defined in Hercules as a 3480 (or vice-versa). Thus while the device actually behaves as a 3590, we need to emulate 3480 functionality instead (and vice-versa). For 3480/3490 devices, the block ID has the following format: __________ ________________________________________________ | Bit | Description | |__________|________________________________________________| | 0 | Direction Bit | | | | | | 0 Wrap 1 | | | 1 Wrap 2 | |__________|________________________________________________| | 1-7 | Segment Number | |__________|________________________________________________| | 8-9 | Format Mode | | | | | | 00 3480 format | | | 01 3480-2 XF format | | | 10 3480 XF format | | | 11 Reserved | | | | | | Note: The 3480 format does not support IDRC. | |__________|________________________________________________| | 10-31 | Logical Block Number | |__________|________________________________________________| For 3480's and 3490's, first block recorded on the tape has a block ID value of X'01000000', whereas for 3590 devices the block ID is a full 32 bits and the first block on the tape is block ID x'00000000'. For the 32-bit to 22-bit (and vice versa) conversion, we're relying on (hoping really!) that an actual 32-bit block-id value will never actually exceed 30 bits (1-bit wrap + 7-bit segment# + 22-bit block-id) since we perform the conversion by simply splitting the low-order 30 bits of a 32-bit block-id into a sep- arate 8-bit (wrap and segment#) and 22-bit (block-id) fields, and then shifting them into their appropriate position (and of course combining/appending them for the opposite conversion). As such, this of course implies that we are thus treating the wrap bit and 7-bit segment number values of a 3480/3490 "22-bit format" blockid as simply the high-order 8 bits of an actual 30-bit physical blockid (which may or may not work properly on actual SCSI hardware depending on how[*] it handles inaccurate blockid values). ----------------- [*] Most(?) [SCSI] devices treat the blockid value used in a Locate CCW as simply an "approximate location" of where the block in question actually resides on the physical tape, and will, after positioning itself to the *approximate* physical location of where the block is *believed* to reside, proceed to then perform the final positioning at low-speed based on its reading of its actual internally-recorded blockid values. Thus, even when the supplied Locate block-id value is wrong, the Locate should still succeed, albeit less efficiently since it may be starting at a physical position quite distant from where the actual block is actually physically located on the actual media. */ /*-------------------------------------------------------------------*/ /* blockid_emulated_to_actual */ /*-------------------------------------------------------------------*/ /* Locate CCW helper: convert guest-supplied 3480 or 3590 blockid */ /* to the actual SCSI hardware blockid format */ /* Both I/P AND O/P are presumed to be in BIG-ENDIAN guest format */ /*-------------------------------------------------------------------*/ void blockid_emulated_to_actual ( DEVBLK *dev, // ptr to Hercules device BYTE *emu_blkid, // ptr to i/p 4-byte block-id in guest storage BYTE *act_blkid // ptr to o/p 4-byte block-id for actual SCSI i/o ) { if ( TAPEDEVT_SCSITAPE != dev->tapedevt ) { memcpy( act_blkid, emu_blkid, 4 ); return; } #if defined(OPTION_SCSI_TAPE) if (0x3590 == dev->devtype) { // 3590 being emulated; guest block-id is full 32-bits... if (dev->stape_blkid_32) { // SCSI using full 32-bit block-ids too. Just copy as-is... memcpy( act_blkid, emu_blkid, 4 ); } else { // SCSI using 22-bit block-ids. Use low-order 30 bits // of 32-bit guest-supplied blockid and convert it // into a "22-bit format" blockid value for SCSI... blockid_32_to_22 ( emu_blkid, act_blkid ); } } else // non-3590 being emulated; guest block-id is 22-bits... { if (dev->stape_blkid_32) { // SCSI using full 32-bit block-ids. Extract the wrap, // segment# and 22-bit blockid bits from the "22-bit // format" guest-supplied blockid value and combine // (append) them into a contiguous low-order 30 bits // of a 32-bit blockid value for SCSI to use... blockid_22_to_32 ( emu_blkid, act_blkid ); } else { // SCSI using 22-bit block-ids too. Just copy as-is... memcpy( act_blkid, emu_blkid, 4 ); } } #endif /* defined(OPTION_SCSI_TAPE) */ } /* end function blockid_emulated_to_actual */ /*-------------------------------------------------------------------*/ /* blockid_actual_to_emulated */ /*-------------------------------------------------------------------*/ /* Read Block Id CCW helper: convert an actual SCSI block-id */ /* to guest emulated 3480/3590 format */ /* Both i/p and o/p are presumed to be in big-endian guest format */ /*-------------------------------------------------------------------*/ void blockid_actual_to_emulated ( DEVBLK *dev, // ptr to Hercules device (for 'devtype') BYTE *act_blkid, // ptr to i/p 4-byte block-id from actual SCSI i/o BYTE *emu_blkid // ptr to o/p 4-byte block-id in guest storage ) { if ( TAPEDEVT_SCSITAPE != dev->tapedevt ) { memcpy( emu_blkid, act_blkid, 4 ); return; } #if defined(OPTION_SCSI_TAPE) if (dev->stape_blkid_32) { // SCSI using full 32-bit block-ids... if (0x3590 == dev->devtype) { // Emulated device is a 3590 too. Just copy as-is... memcpy( emu_blkid, act_blkid, 4 ); } else { // Emulated device using 22-bit format. Convert... blockid_32_to_22 ( act_blkid, emu_blkid ); } } else { // SCSI using 22-bit format block-ids... if (0x3590 == dev->devtype) { // Emulated device using full 32-bit format. Convert... blockid_22_to_32 ( act_blkid, emu_blkid ); } else { // Emulated device using 22-bit format too. Just copy as-is... memcpy( emu_blkid, act_blkid, 4 ); } } #endif /* defined(OPTION_SCSI_TAPE) */ } /* end function blockid_actual_to_emulated */ /*-------------------------------------------------------------------*/ /* blockid_32_to_22 */ /*-------------------------------------------------------------------*/ /* Convert a 3590 32-bit blockid into 3480 "22-bit format" blockid */ /* Both i/p and o/p are presumed to be in big-endian guest format */ /*-------------------------------------------------------------------*/ void blockid_32_to_22 ( BYTE *in_32blkid, BYTE *out_22blkid ) { out_22blkid[0] = ((in_32blkid[0] << 2) & 0xFC) | ((in_32blkid[1] >> 6) & 0x03); out_22blkid[1] = in_32blkid[1] & 0x3F; out_22blkid[2] = in_32blkid[2]; out_22blkid[3] = in_32blkid[3]; } /*-------------------------------------------------------------------*/ /* blockid_22_to_32 */ /*-------------------------------------------------------------------*/ /* Convert a 3480 "22-bit format" blockid into a 3590 32-bit blockid */ /* Both i/p and o/p are presumed to be in big-endian guest format */ /*-------------------------------------------------------------------*/ void blockid_22_to_32 ( BYTE *in_22blkid, BYTE *out_32blkid ) { out_32blkid[0] = (in_22blkid[0] >> 2) & 0x3F; out_32blkid[1] = ((in_22blkid[0] << 6) & 0xC0) | (in_22blkid[1] & 0x3F); out_32blkid[2] = in_22blkid[2]; out_32blkid[3] = in_22blkid[3]; } /*********************************************************************/ /** **/ /** INTERNAL STATUS & AUTOMOUNT FUNCTIONS **/ /** **/ /*********************************************************************/ /* Forward references... */ extern void int_scsi_status_update ( DEVBLK* dev, int mountstat_only ); static void scsi_get_status_fast ( DEVBLK* dev ); static void* get_stape_status_thread ( void* db ); /*-------------------------------------------------------------------*/ /* get_stape_status_thread */ /*-------------------------------------------------------------------*/ static void* get_stape_status_thread( void *db ) { DEVBLK* dev = db; /* Pointer to device block */ struct mtget mtget; /* device status work field */ int rc; /* return code */ struct timeval beg_tod; struct timeval end_tod; // PROGRAMMING NOTE: it is EXTREMELY IMPORTANT that the status- // retrieval thread (i.e. ourselves) be set to a priority that // is AT LEAST one priority slot ABOVE what the device-threads // are currently set to in order to prevent their request for // new/updated status from erroneously timing out (thereby mis- // leading them to mistakenly believe no tape is mounted when // in acuality there is!). The issue is, the caller only waits // for so long for us to return the status to them so we better // ensure we return it to them in a timely fashion else they be // mislead to believe there's no tape mounted (since, by virtue // of their request having timed out, they presume no tape is // mounted since the retrieval took too long (which only occurs // whenever (duh!) there's no tape mounted!)). Thus, if there // *is* a tape mounted, we better be DARN sure to return them // the status as quickly as possible in order to prevent their // wait from timing out. We ensure this by setting our own pri- // ority HIGHER than theirs. // PROGRAMMING NOTE: currently, it looks like each priority slot // differs from each other priority slot by '8' units, which is // why we use the value '10' here (to ensure OUR priority gets // set to the next higher slot). If this ever changes then the // below code will need to be adjusted appropriately. -- Fish SETMODE( ROOT ); { setpriority( PRIO_PROCESS, 0, (sysblk.devprio - 10) ); } SETMODE( USER ); // Begin work... obtain_lock( &dev->stape_getstat_lock ); do { gettimeofday( &beg_tod, NULL ); // Notify requestors we received their request(s)... dev->stape_getstat_busy = 1; broadcast_condition( &dev->stape_getstat_cond ); // PROGRAMMING NOTE: We need to ensure we do not query the // tape drive for its status too frequently since doing so // causes serious problems on certain operating systems with // certain specific hardware (such as a fast multi-processor // Windows 2003 Server with Adaptec AHA2944UW SCSI controller, // wherein it can literally cause the keyboard/mouse to stop // functioning! (due, presumably, to the resulting flood of // SCSI bus interrupts resulting from our frequent querys)) if (1 && (dev->stape_getstat_query_tod.tv_sec) && (dev->fd < 0 || GMT_DR_OPEN( dev->stape_getstat_sstat )) ) { // This isn't the first time and no tape is mounted. // Engage throttle to prevent too-frequent querying... int timeout; for (;;) { timeout = timed_wait_condition_relative_usecs ( &dev->stape_exit_cond, // ptr to condition to wait on &dev->stape_getstat_lock, // ptr to controlling lock (must be held!) 1000000, // max #of microseconds to wait &dev->stape_getstat_query_tod // ptr to relative tod value ); if (sysblk.shutdown || dev->stape_threads_exit) break; if (timeout) break; // (we've waited long enough) } // (else spurious wakeup; keep waiting) } if (sysblk.shutdown || dev->stape_threads_exit) break; // Time to do the actual query... if ( dev->fd > 0 ) { // Since this may take quite a while to do if there's no tape // mounted, we release the lock before attempting to retrieve // the status and then reacquire it afterwards before moving // the results back into the device block... define_BOT_pos( dev ); // (always before status retrieval) release_lock( &dev->stape_getstat_lock ); { // NOTE: the following may take up to *>10<* seconds to // complete on Windows whenever there's no tape mounted, // but apparently only with certain hardware. On a fast // multi-cpu Windows 2003 Server system with an Adaptec // AHA2944UW SCSI control for example, it completes right // away (i.e. IMMEDIATELY), whereas on a medium dual-proc // Windows 2000 Server system with TEKRAM SCSI controller // it takes *>> 10 <<* seconds!... rc = ioctl_tape( dev->fd, MTIOCGET, (char*)&mtget ); } obtain_lock( &dev->stape_getstat_lock ); } else rc = -1; // Query complete. Save results, indicate work complete, // and prepare for next time... if (sysblk.shutdown || dev->stape_threads_exit) break; if ( 0 == rc ) { memcpy( &dev->stape_getstat_mtget, &mtget, sizeof( struct mtget ) ); } else { memset( &dev->stape_getstat_mtget, 0, sizeof( struct mtget ) ); dev->stape_getstat_mtget.mt_blkno = -1; // (forced) dev->stape_getstat_mtget.mt_fileno = -1; // (forced) dev->stape_getstat_sstat = GMT_DR_OPEN(-1); // (presumed and forced) } // Notify requestors new updated status is available // and go back to sleep to wait for the next request... { // PROGRAMMING NOTE: it's IMPORTANT to save the time // of the last query AFTER it returns and not before. // Otherwise if the actual query takes longer than 1 // second we'd end up not waiting at all (0 seconds) // between each query! (which is the very thing we // are trying to prevent from happening!) gettimeofday( &end_tod, NULL ); } dev->stape_getstat_busy = 0; // (idle; waiting for work) broadcast_condition( &dev->stape_getstat_cond ); // (new status available) { dev->stape_getstat_query_tod.tv_sec = end_tod.tv_sec; dev->stape_getstat_query_tod.tv_usec = end_tod.tv_usec; } wait_condition( &dev->stape_getstat_cond, &dev->stape_getstat_lock ); } while ( !sysblk.shutdown && !dev->stape_threads_exit ); // Indicate we're going away... dev->stape_getstat_tid = 0; broadcast_condition( &dev->stape_exit_cond ); broadcast_condition( &dev->stape_getstat_cond ); release_lock( &dev->stape_getstat_lock ); return NULL; } /* end function get_stape_status_thread */ /*-------------------------------------------------------------------*/ /* scsi_get_status_fast */ /*-------------------------------------------------------------------*/ static void scsi_get_status_fast( DEVBLK* dev ) { if (unlikely( dev->fd < 0 )) // (has drive been opened yet?) return; // (cannot proceed until it is) obtain_lock( &dev->stape_getstat_lock ); // Create the status retrieval thread if it hasn't been yet. // We do the actual retrieval of the status in a worker thread // because retrieving the status from a drive that doesn't have // a tape mounted may take a long time (at least on Windows). if (unlikely( !dev->stape_getstat_tid && !dev->stape_threads_exit )) { dev->stape_getstat_sstat = GMT_DR_OPEN(-1); // (until we learn otherwise) VERIFY ( create_thread ( &dev->stape_getstat_tid, JOINABLE, get_stape_status_thread, dev, "get_stape_status_thread" ) == 0 ); } // Wake up the status retrieval thread (if needed)... while ( !dev->stape_getstat_busy && !dev->stape_threads_exit ) { broadcast_condition( &dev->stape_getstat_cond ); wait_condition( &dev->stape_getstat_cond, &dev->stape_getstat_lock ); } // Wait only so long for the status to be retrieved... if (timed_wait_condition_relative_usecs ( &dev->stape_getstat_cond, // ptr to condition to wait on &dev->stape_getstat_lock, // ptr to controlling lock (must be held!) SLOW_UPDATE_STATUS_TIMEOUT, // max #of microseconds to wait NULL // [OPTIONAL] ptr to tod value (may be NULL) )) { // Timeout (status retrieval took too long). // We therefore presume no tape is mounted. memset( &dev->mtget, 0, sizeof( struct mtget ) ); dev->mtget.mt_blkno = -1; // (forced) dev->mtget.mt_fileno = -1; // (forced) dev->sstat = GMT_DR_OPEN(-1); // (presumed and forced) } else // Request finished in time... { memcpy( &dev->mtget, &dev->stape_getstat_mtget, sizeof( struct mtget ) ); } release_lock( &dev->stape_getstat_lock ); } /* end function scsi_get_status_fast */ /*-------------------------------------------------------------------*/ /* Check if a SCSI tape is positioned past the EOT reflector or not */ /*-------------------------------------------------------------------*/ int passedeot_scsitape( DEVBLK *dev ) { return dev->eotwarning; // (1==past EOT reflector; 0==not) } /*-------------------------------------------------------------------*/ /* Determine if the tape is Ready (tape drive door status) */ /* Returns: true/false: 1 = ready, 0 = NOT ready */ /*-------------------------------------------------------------------*/ int is_tape_mounted_scsitape( DEVBLK *dev, BYTE *unitstat, BYTE code ) { UNREFERENCED(unitstat); UNREFERENCED(code); /* Update tape mounted status */ int_scsi_status_update( dev, 1 ); // (safe/fast internal call) return ( !STS_NOT_MOUNTED( dev ) ); } /* end function driveready_scsitape */ /*-------------------------------------------------------------------*/ /* Force a manual status refresh/update (DANGEROUS!) */ /*-------------------------------------------------------------------*/ int update_status_scsitape( DEVBLK *dev ) // (external tmh call) { // * * WARNING! * * // PROGRAMMING NOTE: do NOT call this function indiscriminately, // as doing so COULD cause improper functioning of the guest o/s! // How? Simple: if there's already a tape job running on the guest // using the tape drive and we just so happen to request a status // update at the precise moment a guest i/o encounters a tapemark, // it's possible for US to receive the "tapemark" status and thus // cause the guest to end up NOT SEEING the tapemark! Therefore, // you should ONLY call this function whenever the current status // indicates there's no tape mounted. If the current status says // there *is* a tape mounted, you must NOT call this function! // If the current status says there's a tape mounted and the user // knows this to be untrue (e.g. they manually unloaded it maybe) // then to kick off the auto-scsi-mount thread they must manually // issue the 'devinit' command themselves. We CANNOT presume that // a "mounted" status is bogus. We can ONLY safely presume that a // "UNmounted" status may possibly be bogus. Thus we only ask for // a status refresh if the current status is "not mounted" but we // purposely do NOT force a refresh if the status is "mounted"!! if ( STS_NOT_MOUNTED( dev ) ) // (if no tape mounted) int_scsi_status_update( dev, 0 ); // (then probably safe) return 0; } /* end function update_status_scsitape */ /*-------------------------------------------------------------------*/ /* Update SCSI tape status (and display it if CCW tracing is active) */ /*-------------------------------------------------------------------*/ void int_scsi_status_update( DEVBLK* dev, int mountstat_only ) // (internal call) { create_automount_thread( dev ); // (only if needed of course) obtain_lock( &dev->stape_getstat_lock ); if (unlikely( dev->fd < 0 )) { // The device is offline and cannot currently be used. dev->sstat = GMT_DR_OPEN(-1); } release_lock( &dev->stape_getstat_lock ); // PROGRAMMING NOTE: only normal i/o requests (as well as the // scsi_tapemountmon_thread thread whenever AUTO_SCSI_MOUNT is // enabled and active) ever actually call us with mountstat_only // set to zero (in order to update our actual status value). // // Thus if we're called with a non-zero mountstat_only argument // (meaning all the caller is interested in is whether or not // there's a tape mounted on the drive (which only the panel // and GUI threads normally do (and which they do continuously // whenever they do do it!))) then we simply return immediately // so as to cause the caller to continue using whatever status // happens to already be set for the drive (which should always // be accurate). // // This prevents us from continuously "banging on the drive" // asking for the status when in reality the status we already // have should already be accurate (since it is updated after // every i/o or automatically by the auto-mount thread) if (likely(mountstat_only)) // (if only want mount status) return; // (then current should be ok) // Retrieve actual status... scsi_get_status_fast( dev ); // (doesn't take long time) create_automount_thread( dev ); // (in case status changed) /* Display tape status if tracing is active */ if (unlikely( dev->ccwtrace || dev->ccwstep )) { char buf[256]; snprintf ( buf, sizeof(buf), "%u:%4.4X filename=%s (%s), sstat=0x%8.8lX: %s %s" ,SSID_TO_LCSS(dev->ssid) ,dev->devnum ,( (dev->filename[0]) ? (dev->filename) : ("(undefined)") ) ,( (dev->fd < 0 ) ? ("closed") : ( "opened" ) ) ,dev->sstat ,STS_ONLINE(dev) ? "ON-LINE" : "OFF-LINE" ,STS_NOT_MOUNTED(dev) ? "NO-TAPE" : "READY" ); if ( STS_TAPEMARK(dev) ) strlcat ( buf, " TAPE-MARK" , sizeof(buf) ); if ( STS_EOF (dev) ) strlcat ( buf, " END-OF-FILE" , sizeof(buf) ); if ( STS_BOT (dev) ) strlcat ( buf, " LOAD-POINT" , sizeof(buf) ); if ( STS_EOT (dev) ) strlcat ( buf, " END-OF-TAPE" , sizeof(buf) ); if ( STS_EOD (dev) ) strlcat ( buf, " END-OF-DATA" , sizeof(buf) ); if ( STS_WR_PROT (dev) ) strlcat ( buf, " WRITE-PROTECT", sizeof(buf) ); if ( STS_BOT(dev) ) dev->eotwarning = 0; logmsg ( _("HHCTA323I %s\n"), buf ); } } /* end function int_scsi_status_update */ /*-------------------------------------------------------------------*/ /* ASYNCHRONOUS TAPE OPEN */ /* SCSI tape tape-mount monitoring thread (monitors for tape mounts) */ /* Auto-started by 'int_scsi_status_update' when it notices there is */ /* no tape mounted on whatever device it's checking the status of, */ /* or by the ReqAutoMount function for unsatisfied mount requests. */ /*-------------------------------------------------------------------*/ void create_automount_thread( DEVBLK* dev ) { // AUTO-SCSI-MOUNT // // If no tape is currently mounted on this device, // kick off the tape mount monitoring thread that // will monitor for tape mounts (if it doesn't al- // ready still exist)... obtain_lock( &dev->stape_getstat_lock ); if (1 && sysblk.auto_scsi_mount_secs && STS_NOT_MOUNTED( dev ) && !dev->stape_mountmon_tid && !dev->stape_threads_exit ) { VERIFY ( create_thread ( &dev->stape_mountmon_tid, DETACHED, scsi_tapemountmon_thread, dev, "scsi_tapemountmon_thread" ) == 0 ); } release_lock( &dev->stape_getstat_lock ); } /*-------------------------------------------------------------------*/ /* ASYNCHRONOUS TAPE OPEN */ /*-------------------------------------------------------------------*/ /* AUTO_SCSI_MOUNT thread... */ /*-------------------------------------------------------------------*/ void *scsi_tapemountmon_thread( void *db ) { struct timeval interval_tod; BYTE tape_was_mounted=0; DEVBLK* dev = db; int fd, timeout, shutdown = 0; logmsg ( _( "HHCTA300I SCSI-Tape mount-monitoring thread started;\n" " dev=%u:%4.4X, tid="TIDPAT", pri=%d, pid=%d\n" ) ,SSID_TO_LCSS(dev->ssid) ,dev->devnum ,thread_id() ,getpriority(PRIO_PROCESS,0) ,getpid() ); while (!shutdown) { // Open drive if needed... obtain_lock( &dev->stape_getstat_lock ); if ( (fd = dev->fd) < 0 ) { dev->readonly = 0; fd = open_tape (dev->filename, O_RDWR | O_BINARY | O_NONBLOCK); if (fd < 0 && EROFS == errno ) { dev->readonly = 1; fd = open_tape (dev->filename, O_RDONLY | O_BINARY | O_NONBLOCK); } // Check for successful open if (fd < 0) { logmsg (_("HHCTA324E Error opening SCSI device %u:%4.4X=%s; errno=%d: %s\n"), SSID_TO_LCSS(dev->ssid), dev->devnum, dev->filename, errno, strerror(errno)); sysblk.auto_scsi_mount_secs = 0; // (forced) release_lock( &dev->stape_getstat_lock ); shutdown = 1; break; // (can't open device!) } define_BOT_pos( dev ); // (always after successful open) dev->fd = fd; // (so far so good) } release_lock( &dev->stape_getstat_lock ); // Retrieve the current status... int_scsi_status_update( dev, 0 ); obtain_lock( &dev->stape_getstat_lock ); // (check for exit/shutdown) if (0 || sysblk.shutdown || !sysblk.auto_scsi_mount_secs || dev->stape_threads_exit ) { release_lock( &dev->stape_getstat_lock ); shutdown = 1; break; } // Has a tape [finally] been mounted yet?? if ( !STS_NOT_MOUNTED( dev ) ) { tape_was_mounted = 1; release_lock( &dev->stape_getstat_lock ); break; // YEP! } // NOPE! Close drive and go back to sleep... #if !defined( _MSVC_ ) dev->fd = -1; close_tape( fd ); #endif // Wait for timeout interval to expire // or for someone to signal us to exit... gettimeofday( &interval_tod, NULL ); for (;;) { timeout = timed_wait_condition_relative_usecs ( &dev->stape_exit_cond, // ptr to condition to wait on &dev->stape_getstat_lock, // ptr to controlling lock (must be held!) sysblk.auto_scsi_mount_secs * 1000000, // max #of microseconds to wait &interval_tod // [OPTIONAL] ptr to tod value (may be NULL) ); // Either we timed out or else we were purposely // woken up (signaled). Break from our wait loop // and either retry our status query (if this was // a timeout) or exit our function altogether (if // we were woken up for that purpose) if (0 || sysblk.shutdown || !sysblk.auto_scsi_mount_secs || dev->stape_threads_exit ) shutdown = 1; // (time to exit) break; // (stop sleeping) } release_lock( &dev->stape_getstat_lock ); } // while (!shutdown) // Either a tape has FINALLY been mounted on the drive or // else we were requested to exit. Finish open processing // as needed (depending on if a tape was actually mounted). if ( tape_was_mounted ) { // Set drive to variable length block processing mode, etc... if ( finish_scsitape_open( dev, NULL, 0 ) == 0 ) { // Notify the guest that the tape has now been loaded by // presenting an unsolicited device attention interrupt... device_attention( dev, CSW_DE ); } else { /* We cannot use this device; fail the open. 'finish_scsitape_open' has already issued the error message and closed the device. */ } } logmsg ( _( "HHCTA301I SCSI-Tape mount-monitoring thread ended;\n" " dev=%u:%4.4X, tid="TIDPAT", pid=%d\n" ) ,SSID_TO_LCSS(dev->ssid) ,dev->devnum ,thread_id() ,getpid() ); // Notify the interested parties that we're done // so they can know to start us back up again // if this drive ever has its tape unloaded again... obtain_lock( &dev->stape_getstat_lock ); dev->stape_mountmon_tid = 0; // (we're going away) broadcast_condition( &dev->stape_exit_cond ); broadcast_condition( &dev->stape_getstat_cond ); release_lock( &dev->stape_getstat_lock ); return NULL; } /* end function scsi_tapemountmon_thread */ /*-------------------------------------------------------------------*/ /* shutdown_worker_threads... */ /*-------------------------------------------------------------------*/ void shutdown_worker_threads( DEVBLK *dev ) { while ( dev->stape_getstat_tid || dev->stape_mountmon_tid ) { dev->stape_threads_exit = 1; // (always each loop) broadcast_condition( &dev->stape_exit_cond ); broadcast_condition( &dev->stape_getstat_cond ); timed_wait_condition_relative_usecs ( &dev->stape_exit_cond, // ptr to condition to wait on &dev->stape_getstat_lock, // ptr to controlling lock (must be held!) 25000, // max #of microseconds to wait NULL // ptr to relative tod value (may be NULL) ); } } /*-------------------------------------------------------------------*/ /* Tell driver (if needed) what a BOT position looks like... */ /*-------------------------------------------------------------------*/ void define_BOT_pos( DEVBLK *dev ) { #ifdef _MSVC_ // PROGRAMMING NOTE: Need to tell 'w32stape.c' here the // information it needs to detect physical BOT (load-point). // This is not normally needed as most drivers determine // it for themselves based on the type (manufacturer/model) // of tape drive being used, but since I haven't added the // code to 'w32stape.c' to do that yet (involves talking // directly to the SCSI device itself) we thus, for now, // need to pass that information directly to 'w32stape.c' // ourselves... U32 msk = 0xFF3FFFFF; // (3480/3490 default) U32 bot = 0x01000000; // (3480/3490 default) if ( dev->stape_blkid_32 ) { msk = 0xFFFFFFFF; // (3590 default) bot = 0x00000000; // (3590 default) } VERIFY( 0 == w32_define_BOT( dev->fd, msk, bot ) ); #else UNREFERENCED(dev); #endif // _MSVC_ } #endif // defined(OPTION_SCSI_TAPE) hercules-3.07/scsitape.h000644 000765 000765 00000015474 11143760544 016747 0ustar00jmaynardjmaynard000000 000000 //////////////////////////////////////////////////////////////////////////////////// // SCSITAPE.H -- Hercules SCSI tape handling module // // (c) Copyright "Fish" (David B. Trout), 2005-2009. Released under // the Q Public License (http://www.hercules-390.org/herclic.html) // as modifications to Hercules. //////////////////////////////////////////////////////////////////////////////////// // // This module contains only the support for SCSI tapes. Please see // the 'tapedev.c' (and possibly other) source module(s) for infor- // mation regarding other supported emulated tape/media formats. // //////////////////////////////////////////////////////////////////////////////////// // $Id: scsitape.h 5126 2009-01-23 13:05:56Z bernard $ // // $Log$ // Revision 1.20 2008/03/25 11:41:31 fish // SCSI TAPE MODS part 1: groundwork: non-functional changes: // rename some functions, comments, general restructuring, etc. // New source modules awstape.c, omatape.c, hettape.c and // tapeccws.c added, but not yet used (all will be used in a future // commit though when tapedev.c code is eventually split) // // Revision 1.19 2007/11/30 14:54:33 jmaynard // Changed conmicro.cx to hercules-390.org or conmicro.com, as needed. // // Revision 1.18 2007/07/24 22:36:33 fish // Fix tape Synchronize CCW (x'43') to do actual commit // // Revision 1.17 2007/06/23 00:04:15 ivan // Update copyright notices to include current year (2007) // // Revision 1.16 2006/12/08 09:43:30 jj // Add CVS message log // #ifndef _SCSITAPE_H_ #define _SCSITAPE_H_ #if defined(OPTION_SCSI_TAPE) #include "tapedev.h" #include "w32stape.h" // External TMH-vector calls... extern int update_status_scsitape ( DEVBLK *dev ); // (via "generic" vector) extern int open_scsitape ( DEVBLK *dev, BYTE *unitstat, BYTE code ); extern int finish_scsitape_open ( DEVBLK *dev, BYTE *unitstat, BYTE code ); extern void close_scsitape ( DEVBLK *dev ); extern int read_scsitape ( DEVBLK *dev, BYTE *buf, BYTE *unitstat, BYTE code ); extern int write_scsitape ( DEVBLK *dev, BYTE *buf, U16 len, BYTE *unitstat, BYTE code ); extern int rewind_scsitape ( DEVBLK *dev, BYTE *unitstat, BYTE code ); extern int bsb_scsitape ( DEVBLK *dev, BYTE *unitstat, BYTE code ); extern int fsb_scsitape ( DEVBLK *dev, BYTE *unitstat, BYTE code ); extern int bsf_scsitape ( DEVBLK *dev, BYTE *unitstat, BYTE code ); extern int fsf_scsitape ( DEVBLK *dev, BYTE *unitstat, BYTE code ); extern int write_scsimark ( DEVBLK *dev, BYTE *unitstat, BYTE code ); extern int sync_scsitape ( DEVBLK *dev, BYTE *unitstat, BYTE code ); extern int dse_scsitape ( DEVBLK *dev, BYTE *unitstat, BYTE code ); extern int erg_scsitape ( DEVBLK *dev, BYTE *unitstat, BYTE code ); extern int is_tape_mounted_scsitape ( DEVBLK *dev, BYTE *unitstat, BYTE code ); extern int passedeot_scsitape ( DEVBLK *dev ); extern int readblkid_scsitape ( DEVBLK* dev, BYTE* logical, BYTE* physical ); extern int locateblk_scsitape ( DEVBLK* dev, U32 blockid, BYTE *unitstat, BYTE code ); // Internal functions... extern void int_scsi_rewind_unload( DEVBLK *dev, BYTE *unitstat, BYTE code ); extern void int_scsi_status_update( DEVBLK *dev, int mountstat_only ); extern int int_write_scsimark ( DEVBLK *dev ); extern void blockid_emulated_to_actual( DEVBLK *dev, BYTE *emu_blkid, BYTE *act_blkid ); extern void blockid_actual_to_emulated( DEVBLK *dev, BYTE *act_blkid, BYTE *emu_blkid ); extern void blockid_32_to_22( BYTE *in_32blkid, BYTE *out_22blkid ); extern void blockid_22_to_32( BYTE *in_22blkid, BYTE *out_32blkid ); extern void create_automount_thread( DEVBLK* dev ); extern void *scsi_tapemountmon_thread( void* devblk ); extern void shutdown_worker_threads( DEVBLK *dev ); extern void define_BOT_pos( DEVBLK *dev ); // PROGRAMMING NOTE: I'm not sure of what the the actual/proper value // should be (or is) for the following value but I've coded what seems // to me to be a reasonable value for it. As you can probably guess // based on its [admittedly rather verbose] name, it's the maximum // amount of time that a SCSI tape drive query call should take (i.e. // asking the system for the drive's status shouldn't, under normal // circumstances, take any longer than this time). It should be set // to the most pessimistic value we can reasonably stand, and should // probably be at least as long as the host operating system's thread // scheduling time-slice quantum. -- Fish, April 2006 // August, 2006: further testing/experimentation has revealed that the // "proper" value (i.e. one that causes the fewest potential problems) // for the below timeout setting varies greatly from one system to an- // other with different host CPU speeds and different hardware (SCSI // adapter cards, etc) being the largest factors. Thus, in order to try // and define it to a value likely to cause the LEAST number of problems // on the largest number of systems, I am changing it from its original // 25 millisecond value to the EXTREMELY PESSIMISTIC (but nonetheless // completely(?) safe (since it is afterall only a timeout setting!)) // value of 250 milliseconds. // This is because I happened to notice on some systems with moderate // host (Windows) workload, etc, querying the status of the tape drive, // while *usally* only taking 4 - 6 milliseonds maximum, would sometimes // take up to 113 or more milliseconds! (thereby sometimes causing the // guest to experience intermittent/sporadic unsolicited ATTN interrupts // on the tape drive as their tape jobs ran (since "not mounted" status // was thus getting set as a result of the status query taking longer // than expected, causing the auto-mount thread to kick-in and then // immediately exit again (with an ATTN interrupt of course) whenever // it eventually noticed a tape was indeed still mounted on the drive)). // Thus, even though such unsolicited ATTN interrupts occuring in the // middle of (i.e. during) an already running tape job should NOT, under // ordinary circumstances, cause any problems (as long as auto-scsi-mount // is enabled of course), in order to reduce the likelihood of it happening, // I am increasing the below timeout setting to a value that, ideally, // *should* work on most *all* systems, even under the most pessimistic // of host workloads. -- Fish, August 2006. // ZZ FIXME: should we maybe make this a config file option?? #define MAX_NORMAL_SCSI_DRIVE_QUERY_RESPONSE_TIMEOUT_USECS (250*1000) #endif // defined(OPTION_SCSI_TAPE) #endif // _SCSITAPE_H_ hercules-3.07/service.c000644 000765 000765 00000207544 11335365456 016576 0ustar00jmaynardjmaynard000000 000000 /* SERVICE.C (c) Copyright Roger Bowler, 1999-2009 */ /* ESA/390 Service Processor */ /* Interpretive Execution - (c) Copyright Jan Jaeger, 1999-2009 */ /* z/Architecture support - (c) Copyright Jan Jaeger, 1999-2009 */ // $Id: service.c 5623 2010-02-09 00:46:57Z fish $ /*-------------------------------------------------------------------*/ /* This module implements service processor functions */ /* for the Hercules ESA/390 emulator. */ /*-------------------------------------------------------------------*/ /*-------------------------------------------------------------------*/ /* Additional credits: */ /* Corrections contributed by Jan Jaeger */ /* HMC system console functions by Jan Jaeger 2000-02-08 */ /* Expanded storage support by Jan Jaeger */ /* Dynamic CPU reconfiguration - Jan Jaeger */ /* Suppress superflous HHC701I/HHC702I messages - Jan Jaeger */ /* Break syscons output if too long - Jan Jaeger */ /* Added CPI - Control Program Information ev. - JJ 2001-11-19 */ /*-------------------------------------------------------------------*/ #include "hstdinc.h" #if !defined(_HENGINE_DLL_) #define _HENGINE_DLL_ #endif #if !defined(_SERVICE_C_) #define _SERVICE_C_ #endif #include "hercules.h" #include "opcode.h" #include "inline.h" #include "sr.h" #if !defined(_SERVICE_C) #define _SERVICE_C /*-------------------------------------------------------------------*/ /* Service processor state data */ /*-------------------------------------------------------------------*/ static U32 servc_cp_recv_mask; /* Syscons CP receive mask */ static U32 servc_cp_send_mask; /* Syscons CP send mask */ static U32 servc_attn_pending; /* Attention pending mask */ static char servc_scpcmdstr[123+1]; /* Operator command string */ static U16 servc_signal_quiesce_count; static BYTE servc_signal_quiesce_unit; static BYTE servc_sysg_cmdcode; /* Pending SYSG read command */ #define SCLP_RECV_ENABLED(_type) \ (servc_cp_recv_mask & (0x80000000 >> ((_type)-1))) /*-------------------------------------------------------------------*/ /* Reset the service processor to its initial state */ /*-------------------------------------------------------------------*/ void sclp_reset() { servc_cp_recv_mask = 0; servc_cp_send_mask = 0; servc_attn_pending = 0; servc_signal_quiesce_count = 0; servc_signal_quiesce_unit = 0; servc_sysg_cmdcode = 0; sysblk.servparm = 0; } // #ifdef FEATURE_SYSTEM_CONSOLE /*-------------------------------------------------------------------*/ /* Raise service signal external interrupt */ /* (the caller is expected to hold the interrupt lock) */ /*-------------------------------------------------------------------*/ void sclp_attention(U16 type) { /* Set pending mask */ servc_attn_pending |= 0x80000000 >> (type -1); /* Ignore request if already pending */ if (!(IS_IC_SERVSIG && (sysblk.servparm & SERVSIG_PEND))) { /* Set event pending flag in service parameter */ sysblk.servparm |= SERVSIG_PEND; /* Set service signal interrupt pending for read event data */ ON_IC_SERVSIG; WAKEUP_CPUS_MASK (sysblk.waiting_mask); } } void sclp_attn_thread(U16 *type) { OBTAIN_INTLOCK(NULL); // The VM boys appear to have made an error in not // allowing for asyncronous attentions to be merged // with pending interrupts as such we will wait here // until a pending interrupt has been cleared. *JJ while(IS_IC_SERVSIG) { RELEASE_INTLOCK(NULL); sched_yield(); OBTAIN_INTLOCK(NULL); } sclp_attention(*type); free(type); RELEASE_INTLOCK(NULL); } void sclp_attn_async(U16 type) { if(!IS_IC_SERVSIG) sclp_attention(type); else { TID sclp_attn_tid; U16 *typ; typ=malloc(sizeof(U16)); *typ=type; create_thread(&sclp_attn_tid, &sysblk.detattr, sclp_attn_thread, typ, "attn_thread"); } } static U32 sclp_attn_pending(U16 type) { U32 pending; if(type) { pending = servc_attn_pending & (0x80000000 >> (type -1)); servc_attn_pending &= ~pending; return pending; } else return servc_attn_pending; } /*-------------------------------------------------------------------*/ /* Issue SCP command */ /* */ /* This function is called from the control panel when the operator */ /* enters an HMC system console SCP command or SCP priority message. */ /* The command is queued for processing by the SCLP_READ_EVENT_DATA */ /* service call, and a service signal interrupt is made pending. */ /* */ /* Input: */ /* command Null-terminated ASCII command string */ /* priomsg 0=SCP command, 1=SCP priority message */ /*-------------------------------------------------------------------*/ void scp_command (char *command, int priomsg) { /* Error if disabled for priority messages */ if (priomsg && !SCLP_RECV_ENABLED(SCCB_EVD_TYPE_PRIOR)) { logmsg (_("HHCCP036E SCP not receiving priority messages\n")); return; } /* Error if disabled for commands */ if (!priomsg && !SCLP_RECV_ENABLED(SCCB_EVD_TYPE_OPCMD)) { logmsg (_("HHCCP037E SCP not receiving commands\n")); return; } /* Error if command string is missing */ if (strlen(command) < 1) { logmsg (_("HHCCP038E No SCP command\n")); return; } /* Obtain the interrupt lock */ OBTAIN_INTLOCK(NULL); /* Save command string and message type for read event data */ strncpy (servc_scpcmdstr, command, sizeof(servc_scpcmdstr)); /* Ensure termination of the command string */ servc_scpcmdstr[sizeof(servc_scpcmdstr)-1] = '\0'; /* Raise attention service signal */ sclp_attention( priomsg ? SCCB_EVD_TYPE_PRIOR : SCCB_EVD_TYPE_OPCMD ); /* Release the interrupt lock */ RELEASE_INTLOCK(NULL); } /* end function scp_command */ static void sclp_opcmd_event(SCCB_HEADER *sccb, U16 type) { static BYTE const1_template[] = { 0x13,0x10, /* MDS message unit */ 0x00,0x25,0x13,0x11, /* MDS routine info */ 0x0E,0x81, /* origin location name */ 0x03,0x01,0x00, /* Net ID */ 0x03,0x02,0x00, /* NAU Name */ 0x06,0x03,0x00,0x00,0x00,0x00, /* Appl id */ 0x0E,0x82, /* Destinition location name */ 0x03,0x01,0x00, /* Net ID */ 0x03,0x02,0x00, /* NAU Name */ 0x06,0x03,0x00,0x00,0x00,0x00, /* Appl id */ 0x05,0x90,0x00,0x00,0x00, /* Flags (MDS type = req) */ 0x00,0x0C,0x15,0x49, /* Agent unit-of-work */ 0x08,0x01, /* Requestor loc name */ 0x03,0x01,0x00, /* Requestor Net ID */ 0x03,0x02,0x00 /* Requestor Node ID */ }; static BYTE const2_template[] = { 0x12,0x12, /* CP-MSU */ 0x00,0x12,0x15,0x4D, /* RTI */ 0x0E,0x06, /* Name List */ 0x06,0x10,0x00,0x03,0x00,0x00, /* Cascaded resource list */ 0x06,0x60,0xD6,0xC3,0xC6,0xC1, /* OAN (C'OCFA') */ 0x00,0x04,0x80,0x70 /* Operate request */ }; static BYTE const3_template[] = { 0x13,0x20 /* Text data */ }; static BYTE const4_template = { 0x31 /* Self-defining */ }; static BYTE const5_template = { 0x30 /* Text data */ }; U16 sccb_len; U16 evd_len; int event_msglen; int i; SCCB_EVD_HDR *evd_hdr = (SCCB_EVD_HDR*)(sccb+1); SCCB_EVD_BK *evd_bk = (SCCB_EVD_BK*)(evd_hdr+1); BYTE *event_msg = (BYTE*)(evd_bk+1); /* Get SCCB length */ FETCH_HW(sccb_len, sccb->length); /* Command length */ event_msglen = strlen(servc_scpcmdstr); /* Calculate required EVD length */ evd_len = event_msglen + sizeof(SCCB_EVD_HDR) + sizeof(SCCB_EVD_BK); /* Set response code X'75F0' if SCCB length exceeded */ if ((evd_len + sizeof(SCCB_HEADER)) > sccb_len) { sccb->reas = SCCB_REAS_EXCEEDS_SCCB; sccb->resp = SCCB_RESP_EXCEEDS_SCCB; return; } /* Zero all fields */ memset (evd_hdr, 0, evd_len); /* Update SCCB length field if variable request */ if (sccb->type & SCCB_TYPE_VARIABLE) { /* Set new SCCB length */ sccb_len = evd_len + sizeof(SCCB_HEADER); STORE_HW(sccb->length, sccb_len); sccb->type &= ~SCCB_TYPE_VARIABLE; } /* Set length in event header */ STORE_HW(evd_hdr->totlen, evd_len); /* Set type in event header */ evd_hdr->type = type; /* Set message length in event data block */ i = evd_len - sizeof(SCCB_EVD_HDR); STORE_HW(evd_bk->msglen, i); memcpy (evd_bk->const1, const1_template, sizeof(const1_template)); i -= sizeof(const1_template) + 2; STORE_HW(evd_bk->cplen, i); memcpy (evd_bk->const2, const2_template, sizeof(const2_template)); i -= sizeof(const2_template) + 2; STORE_HW(evd_bk->tdlen, i); memcpy (evd_bk->const3, const3_template, sizeof(const3_template)); i -= sizeof(const3_template) + 2; evd_bk->sdtlen = i; evd_bk->const4 = const4_template; i -= 2; evd_bk->tmlen = i; evd_bk->const5 = const5_template; /* Copy and translate command */ for (i = 0; i < event_msglen; i++) event_msg[i] = host_to_guest(servc_scpcmdstr[i]); /* Set response code X'0020' in SCCB header */ sccb->reas = SCCB_REAS_NONE; sccb->resp = SCCB_RESP_COMPLETE; } void sclp_cpident(SCCB_HEADER *sccb) { SCCB_EVD_HDR *evd_hdr = (SCCB_EVD_HDR*)(sccb + 1); SCCB_CPI_BK *cpi_bk = (SCCB_CPI_BK*)(evd_hdr + 1); int i; char systype[9], sysname[9], sysplex[9]; U64 syslevel; if(*(cpi_bk->system_type)) set_systype(cpi_bk->system_type); if(*(cpi_bk->system_name)) set_sysname(cpi_bk->system_name); if(*(cpi_bk->sysplex_name)) set_sysplex(cpi_bk->sysplex_name); for(i = 0; i < 8; i++) { systype[i] = guest_to_host(cpi_bk->system_type[i]); sysname[i] = guest_to_host(cpi_bk->system_name[i]); sysplex[i] = guest_to_host(cpi_bk->sysplex_name[i]); } systype[8] = sysname[8] = sysplex[8] = 0; FETCH_DW(syslevel,cpi_bk->system_level); #if 1 logmsg(_("HHCCP040I CPI: System Type: %s Name: %s " "Sysplex: %s\n"), systype,sysname,sysplex); #else logmsg(_("HHC770I Control Program Information:\n")); logmsg(_("HHC771I System Type = %s\n",systype)); logmsg(_("HHC772I System Name = %s\n",sysname)); logmsg(_("HHC773I Sysplex Name = %s\n",sysplex)); logmsg(_("HHC774I System Level = %16.16" I64_FMT "X\n"),syslevel); #endif losc_check(systype); /* Indicate Event Processed */ evd_hdr->flag |= SCCB_EVD_FLAG_PROC; /* Set response code X'0020' in SCCB header */ sccb->reas = SCCB_REAS_NONE; sccb->resp = SCCB_RESP_COMPLETE; } /*-------------------------------------------------------------------*/ /* Test whether SCP is enabled for QUIESCE signal */ /* */ /* This function tests whether the SCP is willing to be notified */ /* of a system shutdown via the SCLP_READ_EVENT_DATA service call. */ /* */ /* Return code: */ /* Zero = SCP not receiving quiesce event notification */ /* Non-zero = SCP ready to receive quiesce event notification */ /*-------------------------------------------------------------------*/ int can_signal_quiesce() { return SCLP_RECV_ENABLED(SCCB_EVD_TYPE_SIGQ); } /*-------------------------------------------------------------------*/ /* Send QUIESCE signal to SCP */ /* */ /* This function is called during system shutdown to notify the SCP */ /* that a shutdown event is occurring. The shutdown event is queued */ /* for processing by the SCLP_READ_EVENT_DATA service call, and a */ /* service signal interrupt is made pending. */ /* */ /* Input: */ /* count and unit values to be returned by SCLP_READ_EVENT_DATA */ /*-------------------------------------------------------------------*/ int signal_quiesce (U16 count, BYTE unit) { /* Error if disabled for commands */ if (!SCLP_RECV_ENABLED(SCCB_EVD_TYPE_SIGQ)) { logmsg (_("HHCCP081E SCP not receiving quiesce signals\n")); return -1; } /* Obtain the interrupt lock */ OBTAIN_INTLOCK(NULL); /* Save delay values for signal shutdown event read */ servc_signal_quiesce_count = count; servc_signal_quiesce_unit = unit; sclp_attention(SCCB_EVD_TYPE_SIGQ); /* Release the interrupt lock */ RELEASE_INTLOCK(NULL); return 0; } /* end function signal_quiesce */ static void sclp_sigq_event(SCCB_HEADER *sccb) { U16 sccb_len; U16 evd_len; SCCB_EVD_HDR *evd_hdr = (SCCB_EVD_HDR*)(sccb+1); SCCB_SGQ_BK *sgq_bk = (SCCB_SGQ_BK*)(evd_hdr+1); FETCH_HW(sccb_len, sccb->length); evd_len = sizeof(SCCB_EVD_HDR) + sizeof(SCCB_SGQ_BK); /* Set response code X'75F0' if SCCB length exceeded */ if ((evd_len + sizeof(SCCB_HEADER)) > sccb_len) { sccb->reas = SCCB_REAS_EXCEEDS_SCCB; sccb->resp = SCCB_RESP_EXCEEDS_SCCB; return; } /* Zero all fields */ memset (evd_hdr, 0, evd_len); /* Update SCCB length field if variable request */ if (sccb->type & SCCB_TYPE_VARIABLE) { /* Set new SCCB length */ sccb_len = evd_len + sizeof(SCCB_HEADER); STORE_HW(sccb->length, sccb_len); sccb->type &= ~SCCB_TYPE_VARIABLE; } /* Set length in event header */ STORE_HW(evd_hdr->totlen, evd_len); /* Set type in event header */ evd_hdr->type = SCCB_EVD_TYPE_SIGQ; STORE_HW(sgq_bk->count, servc_signal_quiesce_count); sgq_bk->unit = servc_signal_quiesce_unit; /* Set response code X'0020' in SCCB header */ sccb->reas = SCCB_REAS_NONE; sccb->resp = SCCB_RESP_COMPLETE; } #if defined(_FEATURE_INTEGRATED_3270_CONSOLE) /*-------------------------------------------------------------------*/ /* Write data to the SYSG console */ /* */ /* The datastream to be written to the SYSG console is in the SCCB */ /* immediately following the Event Data Header. It consists of a */ /* one-byte local 3270 CCW command code, followed by a 3270 WCC, */ /* followed by 3270 orders and data. */ /* */ /* Input: */ /* sccb Address of SCCB */ /* evd_hdr Address of event data header within SCCB */ /* Output: */ /* Reason and response codes are set in the SCCB */ /* */ /*-------------------------------------------------------------------*/ void sclp_sysg_write(SCCB_HEADER *sccb) { SCCB_EVD_HDR *evd_hdr = (SCCB_EVD_HDR*)(sccb+1); U16 evd_len; /* SCCB event data length */ U16 sysg_len; /* SYSG output data length */ DEVBLK *dev; /* -> SYSG console devblk */ BYTE *sysg_data; /* -> SYSG output data */ BYTE unitstat; /* Unit status */ BYTE more = 0; /* Flag for device handler */ U16 residual; /* Residual data count */ BYTE cmdcode; /* 3270 read/write command */ /* Calculate the address and length of the 3270 datastream */ FETCH_HW(evd_len,evd_hdr->totlen); sysg_data = (BYTE*)(evd_hdr+1); sysg_len = evd_len - sizeof(SCCB_EVD_HDR); /* The first data byte is the 3270 command code */ cmdcode = *sysg_data; /* Look for the SYSG console device block */ dev = sysblk.sysgdev; if (dev == NULL) { PTT(PTT_CL_ERR,"*SERVC",(U32)cmdcode,(U32)sysg_len,0); /* Set response code X'05F0' in SCCB header */ sccb->reas = SCCB_REAS_IMPROPER_RSC; sccb->resp = SCCB_RESP_REJECT; return; } /* If it is a read CCW then save the command until READ_EVENT_DATA */ if (IS_CCW_READ(cmdcode)) { servc_sysg_cmdcode = cmdcode; /* Indicate Event Processed */ evd_hdr->flag |= SCCB_EVD_FLAG_PROC; /* Generate a service call interrupt to trigger READ_EVENT_DATA */ sclp_attn_async(SCCB_EVD_TYPE_SYSG); /* Set response code X'0020' in SCCB header */ sccb->reas = SCCB_REAS_NONE; sccb->resp = SCCB_RESP_COMPLETE; return; } else { servc_sysg_cmdcode = 0x00; /* Execute the 3270 command in data block */ /* dev->hnd->exec points to loc3270_execute_ccw */ (dev->hnd->exec) (dev, /*ccw opcode*/ cmdcode, /*flags*/ CCW_FLAGS_SLI, /*chained*/0, /*count*/ sysg_len - 1, /*prevcode*/ 0, /*ccwseq*/ 0, /*iobuf*/ sysg_data+1, &more, &unitstat, &residual); /* Indicate Event Processed */ evd_hdr->flag |= SCCB_EVD_FLAG_PROC; /* If unit check occured, set response code X'0040' */ if (unitstat & CSW_UC) { PTT(PTT_CL_ERR,"*SERVC",(U32)more,(U32)unitstat,residual); /* Set response code X'0040' in SCCB header */ sccb->reas = SCCB_REAS_NONE; sccb->resp = SCCB_RESP_BACKOUT; return; } /* Set response code X'0020' in SCCB header */ sccb->reas = SCCB_REAS_NONE; sccb->resp = SCCB_RESP_COMPLETE; } } /*-------------------------------------------------------------------*/ /* Read data from the SYSG console */ /* */ /* If the SYSG console has data to send, copy it into the SCCB */ /* immediately following the Event Data Header. The data consists */ /* of a 3270 AID byte, followed by a two-byte 3270 cursor address, */ /* followed by 3270 orders and data. */ /* */ /* Output: */ /* Data, reason and response codes are set in the SCCB */ /* */ /*-------------------------------------------------------------------*/ void sclp_sysg_poll(SCCB_HEADER *sccb) { SCCB_EVD_HDR *evd_hdr = (SCCB_EVD_HDR*)(sccb+1); U16 sccblen; /* SCCB total length */ U16 evd_len; /* SCCB event data length */ U16 sysg_len; /* SYSG input data length */ DEVBLK *dev; /* -> SYSG console devblk */ BYTE *sysg_data; /* -> SYSG input data */ BYTE *sysg_cmd; /* -> SYSG input data */ BYTE unitstat; /* Unit status */ BYTE more = 0; /* Flag for device handler */ U16 residual; /* Residual data count */ dev = sysblk.sysgdev; if (dev != NULL) { /* Zeroize the event data header */ memset (evd_hdr, 0, sizeof(SCCB_EVD_HDR)); /* Calculate maximum data length */ FETCH_HW(sccblen, sccb->length); evd_len = sccblen - sizeof(SCCB_HEADER); sysg_data = (BYTE*)(evd_hdr+1); sysg_len = evd_len - sizeof(SCCB_EVD_HDR); /* Insert flag byte before the 3270 input data */ sysg_cmd = sysg_data; sysg_len-=1; sysg_data+=1; /* Execute previously saved 3270 read command */ if (servc_sysg_cmdcode) { *sysg_cmd = 0x00; /* Execute a 3270 read-modified command */ /* dev->hnd->exec points to loc3270_execute_ccw */ (dev->hnd->exec) (dev, /*ccw opcode*/ servc_sysg_cmdcode, /*flags*/ CCW_FLAGS_SLI, /*chained*/0, /*count*/ sysg_len, /*prevcode*/ 0, /*ccwseq*/ 0, /*iobuf*/ sysg_data, &more, &unitstat, &residual); servc_sysg_cmdcode = 0; /* Set response code X'0040' if unit check occurred */ if (unitstat & CSW_UC) { PTT(PTT_CL_ERR,"*SERVC",(U32)more,(U32)unitstat,residual); /* Set response code X'0040' in SCCB header */ sccb->reas = SCCB_REAS_NONE; sccb->resp = SCCB_RESP_BACKOUT; return; } /* Set response code X'75F0' if SCCB length exceeded */ if (more) { PTT(PTT_CL_ERR,"*SERVC",(U32)more,(U32)unitstat,residual); sccb->reas = SCCB_REAS_EXCEEDS_SCCB; sccb->resp = SCCB_RESP_EXCEEDS_SCCB; return; } /* Calculate actual length read */ sysg_len -= residual; evd_len = sizeof(SCCB_EVD_HDR) + sysg_len + 1; /* Set response code X'0020' in SCCB header */ sccb->reas = SCCB_REAS_NONE; sccb->resp = SCCB_RESP_COMPLETE; } else { evd_len = sizeof(SCCB_EVD_HDR) + 1; *sysg_cmd = 0x80; /* Set response code X'0020' in SCCB header */ sccb->reas = SCCB_REAS_NONE; sccb->resp = SCCB_RESP_COMPLETE; } /* Update SCCB length field if variable request */ if (sccb->type & SCCB_TYPE_VARIABLE) { /* Set new SCCB length */ sccblen = evd_len + sizeof(SCCB_HEADER); STORE_HW(sccb->length, sccblen); sccb->type &= ~SCCB_TYPE_VARIABLE; } /* Set length in event header */ STORE_HW(evd_hdr->totlen, evd_len); /* Set type in event header */ evd_hdr->type = SCCB_EVD_TYPE_SYSG; } } /*-------------------------------------------------------------------*/ /* Handle attention interrupt from the SYSG console */ /* */ /* This function is called by console.c when it receives input */ /* from the SYSG console. It sets the SYSG read flag and raises */ /* a service signal external interrupt, which should prompt the */ /* SCP to issue a SCLP_READ_EVENT_DATA service call to retrieve */ /* the input data. */ /*-------------------------------------------------------------------*/ SERV_DLL_IMPORT void sclp_sysg_attention() { OBTAIN_INTLOCK(NULL); sclp_attn_async(SCCB_EVD_TYPE_SYSG); RELEASE_INTLOCK(NULL); } #endif /*defined(_FEATURE_INTEGRATED_3270_CONSOLE)*/ #if defined(_FEATURE_INTEGRATED_ASCII_CONSOLE) int sclp_sysa_write(SCCB_HEADER *sccb) { SCCB_EVD_HDR *evd_hdr = (SCCB_EVD_HDR*)(sccb+1); U16 evd_len; U16 sysa_len; BYTE *sysa_data; int i; logmsg(D_("SYSA write:")); FETCH_HW(evd_len,evd_hdr->totlen); sysa_data = (BYTE*)(evd_hdr+1); sysa_len = evd_len - sizeof(SCCB_EVD_HDR); for(i = 0; i < sysa_len; i++) { if(!(i & 15)) logmsg("\n %4.4X:", i); logmsg(" %2.2X", sysa_data[i]); } if(i & 15) logmsg("\n"); /* Indicate Event Processed */ evd_hdr->flag |= SCCB_EVD_FLAG_PROC; /* Set response code X'0020' in SCCB header */ sccb->reas = SCCB_REAS_NONE; sccb->resp = SCCB_RESP_COMPLETE; // maybe this needs to be INFO //sclp_attention(SCCB_EVD_TYPE_VT220); return 0; // write ok } int sclp_sysa_poll(SCCB_HEADER *sccb) { SCCB_EVD_HDR *evd_hdr = (SCCB_EVD_HDR*)(sccb+1); UNREFERENCED(sccb); UNREFERENCED(evd_hdr); logmsg(D_("VT220 poll\n")); } #endif /*defined(_FEATURE_INTEGRATED_ASCII_CONSOLE)*/ /*-------------------------------------------------------------------*/ /* Suspend and resume functions */ /*-------------------------------------------------------------------*/ #define SR_SYS_SERVC_RECVMASK ( SR_SYS_SERVC | 0x001 ) #define SR_SYS_SERVC_SENDMASK ( SR_SYS_SERVC | 0x002 ) #define SR_SYS_SERVC_PENDING ( SR_SYS_SERVC | 0x003 ) #define SR_SYS_SERVC_SCPCMD ( SR_SYS_SERVC | 0x004 ) #define SR_SYS_SERVC_SQC ( SR_SYS_SERVC | 0x005 ) #define SR_SYS_SERVC_SQU ( SR_SYS_SERVC | 0x006 ) #define SR_SYS_SERVC_PARM ( SR_SYS_SERVC | 0x007 ) int servc_hsuspend(void *file) { SR_WRITE_VALUE(file, SR_SYS_SERVC_RECVMASK, servc_cp_recv_mask, sizeof(servc_cp_recv_mask)); SR_WRITE_VALUE(file, SR_SYS_SERVC_SENDMASK, servc_cp_send_mask, sizeof(servc_cp_send_mask)); SR_WRITE_VALUE(file, SR_SYS_SERVC_PENDING, servc_attn_pending, sizeof(servc_attn_pending)); SR_WRITE_STRING(file, SR_SYS_SERVC_SCPCMD, servc_scpcmdstr); SR_WRITE_VALUE(file, SR_SYS_SERVC_SQC, servc_signal_quiesce_count, sizeof(servc_signal_quiesce_count)); SR_WRITE_VALUE(file, SR_SYS_SERVC_SQU, servc_signal_quiesce_unit, sizeof(servc_signal_quiesce_unit)); SR_WRITE_VALUE(file, SR_SYS_SERVC_PARM, sysblk.servparm, sizeof(sysblk.servparm)); return 0; } int servc_hresume(void *file) { size_t key, len; sclp_reset(); do { SR_READ_HDR(file, key, len); switch (key) { case SR_SYS_SERVC_RECVMASK: SR_READ_VALUE(file, len, &servc_cp_recv_mask, sizeof(servc_cp_recv_mask)); break; case SR_SYS_SERVC_SENDMASK: SR_READ_VALUE(file, len, &servc_cp_send_mask, sizeof(servc_cp_send_mask)); break; case SR_SYS_SERVC_PENDING: SR_READ_VALUE(file, len, &servc_attn_pending, sizeof(servc_attn_pending)); break; case SR_SYS_SERVC_SCPCMD: SR_READ_STRING(file, servc_scpcmdstr, sizeof(servc_scpcmdstr)); break; case SR_SYS_SERVC_SQC: SR_READ_VALUE(file, len, &servc_signal_quiesce_count, sizeof(servc_signal_quiesce_count)); break; case SR_SYS_SERVC_SQU: SR_READ_VALUE(file, len, &servc_signal_quiesce_unit, sizeof(servc_signal_quiesce_unit)); break; case SR_SYS_SERVC_PARM: SR_READ_VALUE(file, len, &sysblk.servparm, sizeof(sysblk.servparm)); break; default: SR_READ_SKIP(file, len); break; } } while ((key & SR_SYS_MASK) == SR_SYS_SERVC); return 0; } #endif /*!defined(_SERVICE_C)*/ // #endif /*FEATURE_SYSTEM_CONSOLE*/ #if defined(FEATURE_SERVICE_PROCESSOR) /*-------------------------------------------------------------------*/ /* Architecture-dependent service processor bit strings */ /*-------------------------------------------------------------------*/ BYTE ARCH_DEP(scpinfo_ifm)[8] = { 0 | SCCB_IFM0_CHANNEL_PATH_INFORMATION | SCCB_IFM0_CHANNEL_PATH_SUBSYSTEM_COMMAND // | SCCB_IFM0_CHANNEL_PATH_RECONFIG // | SCCB_IFM0_CPU_INFORMATION #ifdef FEATURE_CPU_RECONFIG | SCCB_IFM0_CPU_RECONFIG #endif /*FEATURE_CPU_RECONFIG*/ , 0 // | SCCB_IFM1_SIGNAL_ALARM // | SCCB_IFM1_WRITE_OPERATOR_MESSAGE // | SCCB_IFM1_STORE_STATUS_ON_LOAD // | SCCB_IFM1_RESTART_REASONS // | SCCB_IFM1_INSTRUCTION_ADDRESS_TRACE_BUFFER | SCCB_IFM1_LOAD_PARAMETER , 0 // | SCCB_IFM2_REAL_STORAGE_INCREMENT_RECONFIG // | SCCB_IFM2_REAL_STORAGE_ELEMENT_INFO // | SCCB_IFM2_REAL_STORAGE_ELEMENT_RECONFIG // | SCCB_IFM2_COPY_AND_REASSIGN_STORAGE #ifdef FEATURE_EXPANDED_STORAGE | SCCB_IFM2_EXTENDED_STORAGE_USABILITY_MAP #endif /*FEATURE_EXPANDED_STORAGE*/ // | SCCB_IFM2_EXTENDED_STORAGE_ELEMENT_INFO // | SCCB_IFM2_EXTENDED_STORAGE_ELEMENT_RECONFIG , 0 #if defined(FEATURE_VECTOR_FACILITY) && defined(FEATURE_CPU_RECONFIG) | SCCB_IFM3_VECTOR_FEATURE_RECONFIG #endif /*FEATURE_VECTOR_FACILITY*/ #ifdef FEATURE_SYSTEM_CONSOLE | SCCB_IFM3_READ_WRITE_EVENT_FEATURE #endif /*FEATURE_SYSTEM_CONSOLE*/ // | SCCB_IFM3_READ_RESOURCE_GROUP_INFO , 0, 0, 0, 0 }; BYTE ARCH_DEP(scpinfo_cfg)[6] = { 0 #if defined(FEATURE_HYPERVISOR) | SCCB_CFG0_LOGICALLY_PARTITIONED #endif /*defined(FEATURE_HYPERVISOR)*/ #ifdef FEATURE_SUPPRESSION_ON_PROTECTION | SCCB_CFG0_SUPPRESSION_ON_PROTECTION #endif /*FEATURE_SUPPRESSION_ON_PROTECTION*/ // | SCCB_CFG0_INITIATE_RESET #if defined(FEATURE_CHSC) | SCCB_CFG0_STORE_CHANNEL_SUBSYS_CHARACTERISTICS #endif /*defined(FEATURE_CHSC)*/ #if defined(FEATURE_MOVE_PAGE_FACILITY_2) | SCCB_CFG0_MVPG_FOR_ALL_GUESTS #endif /*defined(FEATURE_MOVE_PAGE_FACILITY_2)*/ #if defined(FEATURE_FAST_SYNC_DATA_MOVER) /* The Fast Sync Data Mover facility is simply a flag which indicates that the MVPG instruction performs faster than the Asynchronous Data Mover facility (see GA22-1030-03) */ | SCCB_CFG0_FAST_SYNCHRONOUS_DATA_MOVER #endif /*defined(FEATURE_FAST_SYNC_DATA_MOVER)*/ , 0 // | SCCB_CFG1_CSLO , 0 // | SCCB_CFG2_DEVICE_ACTIVE_ONLY_MEASUREMENT #ifdef FEATURE_CALLED_SPACE_IDENTIFICATION | SCCB_CFG2_CALLED_SPACE_IDENTIFICATION #endif /*FEATURE_CALLED_SPACE_IDENTIFICATION*/ #ifdef FEATURE_CHECKSUM_INSTRUCTION | SCCB_CFG2_CHECKSUM_INSTRUCTION #endif /*FEATURE_CHECKSUM_INSTRUCTION*/ , 0 #if defined(FEATURE_RESUME_PROGRAM) | SCCB_CFG3_RESUME_PROGRAM #endif /*defined(FEATURE_RESUME_PROGRAM)*/ #if defined(FEATURE_PERFORM_LOCKED_OPERATION) | SCCB_CFG3_PERFORM_LOCKED_OPERATION #endif /*defined(FEATURE_PERFORM_LOCKED_OPERATION)*/ #ifdef FEATURE_IMMEDIATE_AND_RELATIVE | SCCB_CFG3_IMMEDIATE_AND_RELATIVE #endif /*FEATURE_IMMEDIATE_AND_RELATIVE*/ #ifdef FEATURE_COMPARE_AND_MOVE_EXTENDED | SCCB_CFG3_COMPARE_AND_MOVE_EXTENDED #endif /*FEATURE_COMPARE_AND_MOVE_EXTENDED*/ #ifdef FEATURE_BRANCH_AND_SET_AUTHORITY | SCCB_CFG3_BRANCH_AND_SET_AUTHORITY #endif /*FEATURE_BRANCH_AND_SET_AUTHORITY*/ #if defined(FEATURE_BASIC_FP_EXTENSIONS) | SCCB_CFG3_EXTENDED_FLOATING_POINT #endif /*defined(FEATURE_BASIC_FP_EXTENSIONS)*/ /*ZZ*/ | SCCB_CFG3_EXTENDED_LOGICAL_COMPUTATION_FACILITY , 0 #ifdef FEATURE_EXTENDED_TOD_CLOCK | SCCB_CFG4_EXTENDED_TOD_CLOCK #endif /*FEATURE_EXTENDED_TOD_CLOCK*/ #if defined(FEATURE_EXTENDED_TRANSLATION) | SCCB_CFG4_EXTENDED_TRANSLATION #endif /*defined(FEATURE_EXTENDED_TRANSLATION)*/ #if defined(FEATURE_LOAD_REVERSED) | SCCB_CFG4_LOAD_REVERSED_FACILITY #endif /*defined(FEATURE_LOAD_REVERSED)*/ #if defined(FEATURE_EXTENDED_TRANSLATION_FACILITY_2) | SCCB_CFG4_EXTENDED_TRANSLATION_FACILITY2 #endif /*defined(FEATURE_EXTENDED_TRANSLATION_FACILITY_2)*/ #if defined(FEATURE_STORE_SYSTEM_INFORMATION) | SCCB_CFG4_STORE_SYSTEM_INFORMATION #endif /*FEATURE_STORE_SYSTEM_INFORMATION*/ // | SCCB_CFG4_LPAR_CLUSTERING | SCCB_CFG4_IFA_FACILITY , 0 #if defined(FEATURE_SENSE_RUNNING_STATUS) | SCCB_CFG5_SENSE_RUNNING_STATUS #endif /*FEATURE_SENSE_RUNNING_STATUS*/ }; BYTE ARCH_DEP(scpinfo_cfg11) = 0 #if defined(FEATURE_PER3) | SCCB_CFGB_PER_3 #endif | SCCB_CFGB_LIST_DIRECTED_IPL; BYTE ARCH_DEP(scpinfo_cpf)[12] = { 0 #if defined(FEATURE_INTERPRETIVE_EXECUTION) #if defined(_370) && !defined(FEATURE_ESAME) | SCCB_CPF0_SIE_370_MODE #endif /*defined(_370) && !defined(FEATURE_ESAME)*/ | SCCB_CPF0_SIE_XA_MODE #endif /*defined(FEATURE_INTERPRETIVE_EXECUTION)*/ // | SCCB_CPF0_SIE_SET_II_370_MODE #if defined(FEATURE_IO_ASSIST) | SCCB_CPF0_SIE_SET_II_XA_MODE #endif /*defined(FEATURE_IO_ASSIST)*/ #if defined(FEATURE_INTERPRETIVE_EXECUTION) | SCCB_CPF0_SIE_NEW_INTERCEPT_FORMAT #endif /*defined(FEATURE_INTERPRETIVE_EXECUTION)*/ #if defined(FEATURE_STORAGE_KEY_ASSIST) | SCCB_CPF0_STORAGE_KEY_ASSIST #endif /*defined(FEATURE_STORAGE_KEY_ASSIST)*/ #if defined(_FEATURE_MULTIPLE_CONTROLLED_DATA_SPACE) | SCCB_CPF0_MULTIPLE_CONTROLLED_DATA_SPACE #endif /*defined(_FEATURE_MULTIPLE_CONTROLLED_DATA_SPACE)*/ , 0 #if defined(FEATURE_IO_ASSIST) | SCCB_CPF1_IO_INTERPRETATION_LEVEL_2 #endif /*defined(FEATURE_IO_ASSIST)*/ #if defined(FEATURE_INTERPRETIVE_EXECUTION) | SCCB_CPF1_GUEST_PER_ENHANCED #endif /*defined(FEATURE_INTERPRETIVE_EXECUTION)*/ // | SCCB_CPF1_SIGP_INTERPRETATION_ASSIST #if defined(FEATURE_STORAGE_KEY_ASSIST) | SCCB_CPF1_RCP_BYPASS_FACILITY #endif /*defined(FEATURE_STORAGE_KEY_ASSIST)*/ #if defined(FEATURE_REGION_RELOCATE) | SCCB_CPF1_REGION_RELOCATE_FACILITY #endif /*defined(FEATURE_REGION_RELOCATE)*/ #if defined(FEATURE_EXPEDITED_SIE_SUBSET) | SCCB_CPF1_EXPEDITE_TIMER_PROCESSING #endif /*defined(FEATURE_EXPEDITED_SIE_SUBSET)*/ , 0 #if defined(FEATURE_CRYPTO) | SCCB_CPF2_CRYPTO_FEATURE_ACCESSED #endif /*defined(FEATURE_CRYPTO)*/ #if defined(FEATURE_EXPEDITED_SIE_SUBSET) | SCCB_CPF2_EXPEDITE_RUN_PROCESSING #endif /*defined(FEATURE_EXPEDITED_SIE_SUBSET)*/ , 0 #ifdef FEATURE_PRIVATE_SPACE | SCCB_CPF3_PRIVATE_SPACE_FEATURE | SCCB_CPF3_FETCH_ONLY_BIT #endif /*FEATURE_PRIVATE_SPACE*/ #if defined(FEATURE_PER2) | SCCB_CPF3_PER2_INSTALLED #endif /*defined(FEATURE_PER2)*/ , 0 #if defined(FEATURE_PER2) | SCCB_CPF4_OMISION_GR_ALTERATION_370 #endif /*defined(FEATURE_PER2)*/ , 0 #if defined(FEATURE_WAITSTATE_ASSIST) | SCCB_CPF5_GUEST_WAIT_STATE_ASSIST #endif /*defined(FEATURE_WAITSTATE_ASSIST)*/ , 0, 0, 0, 0, 0, 0 } ; U32 ARCH_DEP(sclp_recv_mask) = (0x80000000 >> (SCCB_EVD_TYPE_MSG-1)) | (0x80000000 >> (SCCB_EVD_TYPE_PRIOR-1)) | #if defined(FEATURE_SCEDIO) (0x80000000 >> (SCCB_EVD_TYPE_SCEDIO-1)) | #endif /*defined(FEATURE_SCEDIO)*/ #if defined(FEATURE_INTEGRATED_ASCII_CONSOLE) (0x80000000 >> (SCCB_EVD_TYPE_VT220-1)) | #endif /*defined(FEATURE_INTEGRATED_ASCII_CONSOLE)*/ #if defined(FEATURE_INTEGRATED_3270_CONSOLE) (0x80000000 >> (SCCB_EVD_TYPE_SYSG-1)) | #endif /*defined(FEATURE_INTEGRATED_3270_CONSOLE)*/ (0x80000000 >> (SCCB_EVD_TYPE_CPIDENT-1)) ; U32 ARCH_DEP(sclp_send_mask) = (0x80000000 >> (SCCB_EVD_TYPE_OPCMD-1)) | (0x80000000 >> (SCCB_EVD_TYPE_STATECH-1)) | (0x80000000 >> (SCCB_EVD_TYPE_PRIOR-1)) | (0x80000000 >> (SCCB_EVD_TYPE_SIGQ-1)) | #if defined(FEATURE_SCEDIO) (0x80000000 >> (SCCB_EVD_TYPE_SCEDIO-1)) | #endif /*defined(FEATURE_SCEDIO)*/ #if defined(FEATURE_INTEGRATED_ASCII_CONSOLE) (0x80000000 >> (SCCB_EVD_TYPE_VT220-1)) | #endif /*defined(FEATURE_INTEGRATED_ASCII_CONSOLE)*/ #if defined(FEATURE_INTEGRATED_3270_CONSOLE) (0x80000000 >> (SCCB_EVD_TYPE_SYSG-1)) | #endif /*defined(FEATURE_INTEGRATED_3270_CONSOLE)*/ (0x80000000 >> (SCCB_EVD_TYPE_CPCMD-1)) ; /*-------------------------------------------------------------------*/ /* B220 SERVC - Service Call [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(service_call) { U32 r1, r2; /* Values of R fields */ U32 sclp_command; /* SCLP command code */ U32 sccb_real_addr; /* SCCB real address */ int i; /* Array subscripts */ U32 realmb; /* Real storage size in MB */ U32 sccb_absolute_addr; /* Absolute address of SCCB */ U32 sccblen; /* Length of SCCB */ SCCB_HEADER *sccb; /* -> SCCB header */ SCCB_SCP_INFO *sccbscp; /* -> SCCB SCP information */ SCCB_CPU_INFO *sccbcpu; /* -> SCCB CPU information */ #if defined(FEATURE_MPF_INFO) SCCB_MPF_INFO *sccbmpf; /* -> SCCB MPF information */ #endif /*defined(FEATURE_MPF_INFO)*/ #ifdef FEATURE_CHANNEL_SUBSYSTEM SCCB_CHP_INFO *sccbchp; /* -> SCCB channel path info */ #else SCCB_CHSET_INFO *sccbchp; /* -> SCCB channel path info */ #endif SCCB_CSI_INFO *sccbcsi; /* -> SCCB channel subsys inf*/ U16 offset; /* Offset from start of SCCB */ #ifdef FEATURE_CHANNEL_SUBSYSTEM DEVBLK *dev; /* Used to find CHPIDs */ U32 chpbyte; /* Offset to byte for CHPID */ U32 chpbit; /* Bit number for CHPID */ #endif /*FEATURE_CHANNEL_SUBSYSTEM*/ #ifdef FEATURE_SYSTEM_CONSOLE SCCB_EVENT_MASK*evd_mask; /* Event mask */ SCCB_EVD_HDR *evd_hdr; /* Event header */ U16 evd_len; /* Length of event data */ SCCB_MCD_BK *mcd_bk; /* Message Control Data */ U16 mcd_len; /* Length of MCD */ SCCB_OBJ_HDR *obj_hdr; /* Object Header */ U16 obj_len; /* Length of Object */ U16 obj_type; /* Object type */ SCCB_MTO_BK *mto_bk; /* Message Text Object */ BYTE *event_msg; /* Message Text pointer */ int event_msglen; /* Message Text length */ BYTE message[4089]; /* Maximum event data buffer length plus one for \0 */ U32 masklen; /* Length of event mask */ U32 old_cp_recv_mask; /* Masks before write event */ U32 old_cp_send_mask; /* mask command */ #endif /*FEATURE_SYSTEM_CONSOLE*/ #ifdef FEATURE_EXPANDED_STORAGE SCCB_XST_MAP *sccbxmap; /* Xstore usability map */ U32 xstincnum; /* Number of expanded storage increments */ U32 xstblkinc; /* Number of expanded storage blocks per increment */ BYTE *xstmap; /* Xstore bitmap, zero means available */ #endif /*FEATURE_EXPANDED_STORAGE*/ RRE(inst, regs, r1, r2); PRIV_CHECK(regs); SIE_INTERCEPT(regs); PTT(PTT_CL_INF,"SERVC",regs->GR_L(r1),regs->GR_L(r2),regs->psw.IA_L); /* R1 is SCLP command word */ sclp_command = regs->GR_L(r1); /* R2 is real address of service call control block */ sccb_real_addr = regs->GR_L(r2); /* Obtain the absolute address of the SCCB */ sccb_absolute_addr = APPLY_PREFIXING(sccb_real_addr, regs->PX); /* Program check if SCCB is not on a doubleword boundary */ if ( sccb_absolute_addr & 0x00000007 ) ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION); /* Program check if SCCB is outside main storage */ if ( sccb_absolute_addr > regs->mainlim ) ARCH_DEP(program_interrupt) (regs, PGM_ADDRESSING_EXCEPTION); /* Point to service call control block */ sccb = (SCCB_HEADER*)(regs->mainstor + sccb_absolute_addr); /* Load SCCB length from header */ FETCH_HW(sccblen, sccb->length); /* Set the main storage reference bit */ STORAGE_KEY(sccb_absolute_addr, regs) |= STORKEY_REF; /* Program check if end of SCCB falls outside main storage */ if ( sccb_absolute_addr + sccblen > regs->mainlim + 1) ARCH_DEP(program_interrupt) (regs, PGM_ADDRESSING_EXCEPTION); /* Obtain lock if immediate response is not requested */ if (!(sccb->flag & SCCB_FLAG_SYNC) || (sclp_command & SCLP_COMMAND_CLASS) == 0x01) { /* Obtain the interrupt lock */ OBTAIN_INTLOCK(regs); /* If a service signal is pending then return condition code 2 to indicate that service processor is busy */ if (IS_IC_SERVSIG && (sysblk.servparm & SERVSIG_ADDR)) { RELEASE_INTLOCK(regs); regs->psw.cc = 2; return; } } /* Test SCLP command word */ switch (sclp_command & SCLP_COMMAND_MASK) { case SCLP_READ_IFL_INFO: /* READ_IFL_INFO is only valid for processor type IFL */ if(sysblk.ptyp[regs->cpuad] != SCCB_PTYP_IFL) goto invalidcmd; else goto read_scpinfo; case SCLP_READ_SCP_INFO: /* READ_SCP_INFO is only valid for processor type CP */ if(sysblk.ptyp[regs->cpuad] != SCCB_PTYP_CP) { #ifdef OPTION_MSGCLR logmsg(""); #endif logmsg("HHCCP090W The configuration has been placed into a system check-stop state because of an incompatible service call\n\n"); goto docheckstop; /* * Replace the following 2 lines with * goto invalidcmd * if this behavior is not satisfactory * ISW 20081221 */ } read_scpinfo: /* Set the main storage change bit */ STORAGE_KEY(sccb_absolute_addr, regs) |= STORKEY_CHANGE; /* Set response code X'0100' if SCCB crosses a page boundary */ if ((sccb_absolute_addr & STORAGE_KEY_PAGEMASK) != ((sccb_absolute_addr + sccblen - 1) & STORAGE_KEY_PAGEMASK)) { sccb->reas = SCCB_REAS_NOT_PGBNDRY; sccb->resp = SCCB_RESP_BLOCK_ERROR; break; } /* Set response code X'0300' if SCCB length is insufficient to contain SCP info */ if ( sccblen < sizeof(SCCB_HEADER) + sizeof(SCCB_SCP_INFO) + (sizeof(SCCB_CPU_INFO) * MAX_CPU)) { sccb->reas = SCCB_REAS_TOO_SHORT; sccb->resp = SCCB_RESP_BLOCK_ERROR; break; } /* Point to SCCB data area following SCCB header */ sccbscp = (SCCB_SCP_INFO*)(sccb+1); memset (sccbscp, 0, sizeof(SCCB_SCP_INFO)); /* Set main storage size in SCCB */ realmb = sysblk.mainsize >> 20; STORE_HW(sccbscp->realinum, realmb); sccbscp->realiszm = 1; sccbscp->realbszk = 4; STORE_HW(sccbscp->realiint, 1); #if defined(_900) || defined(FEATURE_ESAME) /* SIE supports the full address range */ sccbscp->maxvm = 0; /* realiszm is valid */ STORE_FW(sccbscp->grzm, 0); /* Number of storage increments installed in esame mode */ STORE_DW(sccbscp->grnmx, realmb); #endif /*defined(_900) || defined(FEATURE_ESAME)*/ #ifdef FEATURE_EXPANDED_STORAGE /* Set expanded storage size in SCCB */ xstincnum = sysblk.xpndsize / (XSTORE_INCREMENT_SIZE >> XSTORE_PAGESHIFT); STORE_FW(sccbscp->xpndinum, xstincnum); xstblkinc = XSTORE_INCREMENT_SIZE >> XSTORE_PAGESHIFT; STORE_FW(sccbscp->xpndsz4K, xstblkinc); #endif /*FEATURE_EXPANDED_STORAGE*/ #ifdef FEATURE_VECTOR_FACILITY /* Set the Vector section size in the SCCB */ STORE_HW(sccbscp->vectssiz, VECTOR_SECTION_SIZE); /* Set the Vector partial sum number in the SCCB */ STORE_HW(sccbscp->vectpsum, VECTOR_PARTIAL_SUM_NUMBER); #endif /*FEATURE_VECTOR_FACILITY*/ /* Set CPU array count and offset in SCCB */ STORE_HW(sccbscp->numcpu, MAX_CPU); offset = sizeof(SCCB_HEADER) + sizeof(SCCB_SCP_INFO); STORE_HW(sccbscp->offcpu, offset); #if defined(FEATURE_MPF_INFO) /* Set MPF array count and offset in SCCB */ STORE_HW(sccbscp->nummpf, MAX_CPU-1); #endif /*defined(FEATURE_MPF_INFO)*/ offset += sizeof(SCCB_CPU_INFO) * MAX_CPU; STORE_HW(sccbscp->offmpf, offset); /* Set HSA array count and offset in SCCB */ STORE_HW(sccbscp->numhsa, 0); #if defined(FEATURE_MPF_INFO) offset += sizeof(SCCB_MPF_INFO) * MAX_CPU-1; #endif /*defined(FEATURE_MPF_INFO)*/ STORE_HW(sccbscp->offhsa, offset); /* Build the MPF information array after the CPU info */ /* Move IPL load parameter to SCCB */ get_loadparm (sccbscp->loadparm); /* Set installed features bit mask in SCCB */ memcpy(sccbscp->ifm, ARCH_DEP(scpinfo_ifm), sizeof(sccbscp->ifm)); memcpy(sccbscp->cfg, ARCH_DEP(scpinfo_cfg), sizeof(sccbscp->cfg)); /* sccbscp->cfg11 = ARCH_DEP(scpinfo_cfg11); */ #if defined(_900) || defined(FEATURE_ESAME) if(sysblk.arch_z900) sccbscp->cfg[5] |= SCCB_CFG5_ESAME; #endif /*defined(_900) || defined(FEATURE_ESAME)*/ ; /* Build the CPU information array after the SCP info */ sccbcpu = (SCCB_CPU_INFO*)(sccbscp+1); for (i = 0; i < MAX_CPU; i++, sccbcpu++) { memset (sccbcpu, 0, sizeof(SCCB_CPU_INFO)); sccbcpu->cpa = i; sccbcpu->tod = 0; memcpy(sccbcpu->cpf, ARCH_DEP(scpinfo_cpf), sizeof(sccbcpu->cpf)); sccbcpu->ptyp = sysblk.ptyp[i]; #if defined(FEATURE_CRYPTO) // sccbcpu->ksid = SCCB_KSID_CRYPTO_UNIT_ID; #endif /*defined(FEATURE_CRYPTO)*/ #ifdef FEATURE_VECTOR_FACILITY if(IS_CPU_ONLINE(i) && sysblk.regs[i]->vf->online) sccbcpu->cpf[2] |= SCCB_CPF2_VECTOR_FEATURE_INSTALLED; if(IS_CPU_ONLINE(i) && sysblk.regs[i]->vf->online) sccbcpu->cpf[2] |= SCCB_CPF2_VECTOR_FEATURE_CONNECTED; if(!IS_CPU_ONLINE(i)) sccbcpu->cpf[2] |= SCCB_CPF2_VECTOR_FEATURE_STANDBY_STATE; #endif /*FEATURE_VECTOR_FACILITY*/ } #if defined(FEATURE_MPF_INFO) /* Define machine capacity */ STORE_FW(sccbscp->rcci, 10000); /* Fill in the MP Factors array */ sccbmpf = (SCCB_MPF_INFO*)(sccbcpu); get_mpfactors((BYTE*)sccbmpf); #endif /*defined(FEATURE_MPF_INFO)*/ /* Set response code X'0010' in SCCB header */ sccb->reas = SCCB_REAS_NONE; sccb->resp = SCCB_RESP_INFO; break; docheckstop: ARCH_DEP(checkstop_config)(); RELEASE_INTLOCK(regs); longjmp(regs->progjmp,SIE_NO_INTERCEPT); break; case SCLP_READ_CHP_INFO: /* Set the main storage change bit */ STORAGE_KEY(sccb_absolute_addr, regs) |= STORKEY_CHANGE; /* Set response code X'0100' if SCCB crosses a page boundary */ if ((sccb_absolute_addr & STORAGE_KEY_PAGEMASK) != ((sccb_absolute_addr + sccblen - 1) & STORAGE_KEY_PAGEMASK)) { sccb->reas = SCCB_REAS_NOT_PGBNDRY; sccb->resp = SCCB_RESP_BLOCK_ERROR; break; } /* Set response code X'0300' if SCCB length is insufficient to contain channel path info */ if ( sccblen < sizeof(SCCB_HEADER) + sizeof(SCCB_CHP_INFO)) { sccb->reas = SCCB_REAS_TOO_SHORT; sccb->resp = SCCB_RESP_BLOCK_ERROR; break; } #ifdef FEATURE_S370_CHANNEL /* Point to SCCB data area following SCCB header */ sccbchp = (SCCB_CHSET_INFO*)(sccb+1); memset (sccbchp, 0, sizeof(SCCB_CHSET_INFO)); #else /* Point to SCCB data area following SCCB header */ sccbchp = (SCCB_CHP_INFO*)(sccb+1); memset (sccbchp, 0, sizeof(SCCB_CHP_INFO)); #endif #ifdef FEATURE_CHANNEL_SUBSYSTEM /* Identify CHPIDs installed, standby, and online */ for (dev = sysblk.firstdev; dev != NULL; dev = dev->nextdev) { chpbyte = dev->devnum >> 11; chpbit = (dev->devnum >> 8) & 7; sccbchp->installed[chpbyte] |= 0x80 >> chpbit; if (dev->pmcw.flag5 & PMCW5_V) sccbchp->online[chpbyte] |= 0x80 >> chpbit; else sccbchp->standby[chpbyte] |= 0x80 >> chpbit; } #endif /*FEATURE_CHANNEL_SUBSYSTEM*/ #ifdef FEATURE_S370_CHANNEL /* For S/370, initialize identifiers for channel set 0A */ for (i = 0; i < 16; i++) { sccbchp->chanset0a[2*i] = 0x80; sccbchp->chanset0a[2*i+1] = i; } /* end for(i) */ /* Set the channel set configuration byte */ sccbchp->csconfig = 0xC0; #endif /*FEATURE_S370_CHANNEL*/ /* Set response code X'0010' in SCCB header */ sccb->reas = SCCB_REAS_NONE; sccb->resp = SCCB_RESP_INFO; break; case SCLP_READ_CSI_INFO: /* Set the main storage change bit */ STORAGE_KEY(sccb_absolute_addr, regs) |= STORKEY_CHANGE; /* Set response code X'0100' if SCCB crosses a page boundary */ if ((sccb_absolute_addr & STORAGE_KEY_PAGEMASK) != ((sccb_absolute_addr + sccblen - 1) & STORAGE_KEY_PAGEMASK)) { sccb->reas = SCCB_REAS_NOT_PGBNDRY; sccb->resp = SCCB_RESP_BLOCK_ERROR; break; } /* Set response code X'0300' if SCCB length is insufficient to contain channel path info */ if ( sccblen < sizeof(SCCB_HEADER) + sizeof(SCCB_CSI_INFO)) { sccb->reas = SCCB_REAS_TOO_SHORT; sccb->resp = SCCB_RESP_BLOCK_ERROR; break; } /* Point to SCCB data area following SCCB header */ sccbcsi = (SCCB_CSI_INFO*)(sccb+1); memset (sccbcsi, 0, sizeof(SCCB_CSI_INFO)); sccbcsi->csif[0] = 0 #if defined(FEATURE_CANCEL_IO_FACILITY) | SCCB_CSI0_CANCEL_IO_REQUEST_FACILITY #endif /*defined(FEATURE_CANCEL_IO_FACILITY)*/ | SCCB_CSI0_CONCURRENT_SENSE_FACILITY ; /* Set response code X'0010' in SCCB header */ sccb->reas = SCCB_REAS_NONE; sccb->resp = SCCB_RESP_INFO; break; #ifdef FEATURE_SYSTEM_CONSOLE case SCLP_WRITE_EVENT_DATA: /* Set the main storage change bit */ STORAGE_KEY(sccb_absolute_addr, regs) |= STORKEY_CHANGE; /* Set response code X'0100' if SCCB crosses a page boundary */ if ((sccb_absolute_addr & STORAGE_KEY_PAGEMASK) != ((sccb_absolute_addr + sccblen - 1) & STORAGE_KEY_PAGEMASK)) { sccb->reas = SCCB_REAS_NOT_PGBNDRY; sccb->resp = SCCB_RESP_BLOCK_ERROR; break; } /* Point to SCCB data area following SCCB header */ evd_hdr = (SCCB_EVD_HDR*)(sccb+1); FETCH_HW(evd_len,evd_hdr->totlen); switch(evd_hdr->type) { case SCCB_EVD_TYPE_MSG: case SCCB_EVD_TYPE_PRIOR: /* Point to the Message Control Data Block */ mcd_bk = (SCCB_MCD_BK*)(evd_hdr+1); FETCH_HW(mcd_len,mcd_bk->length); obj_hdr = (SCCB_OBJ_HDR*)(mcd_bk+1); while (mcd_len > sizeof(SCCB_MCD_BK)) { FETCH_HW(obj_len,obj_hdr->length); if (obj_len == 0) { sccb->reas = SCCB_REAS_BUFF_LEN_ERR; sccb->resp = SCCB_RESP_BUFF_LEN_ERR; break; } FETCH_HW(obj_type,obj_hdr->type); if (obj_type == SCCB_OBJ_TYPE_MESSAGE) { mto_bk = (SCCB_MTO_BK*)(obj_hdr+1); event_msg = (BYTE*)(mto_bk+1); event_msglen = obj_len - (sizeof(SCCB_OBJ_HDR) + sizeof(SCCB_MTO_BK)); if (event_msglen < 0) { sccb->reas = SCCB_REAS_BUFF_LEN_ERR; sccb->resp = SCCB_RESP_BUFF_LEN_ERR; break; } /* Print line unless it is a response prompt */ if (!(mto_bk->ltflag[0] & SCCB_MTO_LTFLG0_PROMPT)) { for (i = 0; i < event_msglen; i++) { message[i] = isprint(guest_to_host(event_msg[i])) ? guest_to_host(event_msg[i]) : 0x20; } message[i] = '\0'; #ifdef OPTION_MSGCLR if(evd_hdr->type == SCCB_EVD_TYPE_MSG) { if(mto_bk->presattr[3] == SCCB_MTO_PRATTR3_HIGH) logmsg("%s\n", message); else logmsg ("%s\n", message); } else logmsg ("%s\n", message); #else logmsg ("%s\n", message); #endif } } mcd_len -= obj_len; obj_hdr=(SCCB_OBJ_HDR *)((BYTE*)obj_hdr + obj_len); } /* Indicate Event Processed */ evd_hdr->flag |= SCCB_EVD_FLAG_PROC; /* Set response code X'0020' in SCCB header */ sccb->reas = SCCB_REAS_NONE; sccb->resp = SCCB_RESP_COMPLETE; break; case SCCB_EVD_TYPE_CPIDENT: sclp_cpident(sccb); break; #if defined(FEATURE_SCEDIO) case SCCB_EVD_TYPE_SCEDIO: ARCH_DEP(sclp_scedio_request)(sccb); break; #endif /*defined(FEATURE_SCEDIO)*/ #if defined(FEATURE_INTEGRATED_3270_CONSOLE) case SCCB_EVD_TYPE_SYSG: sclp_sysg_write(sccb); break; #endif /*defined(FEATURE_INTEGRATED_3270_CONSOLE)*/ #if defined(FEATURE_INTEGRATED_ASCII_CONSOLE) case SCCB_EVD_TYPE_VT220: sclp_sysa_write(sccb); break; #endif /*defined(FEATURE_INTEGRATED_ASCII_CONSOLE)*/ default: PTT(PTT_CL_ERR,"*SERVC",regs->GR_L(r1),regs->GR_L(r2),evd_hdr->type); if( HDC3(debug_sclp_unknown_event, evd_hdr, sccb, regs) ) break; /* Set response code X'73F0' in SCCB header */ sccb->reas = SCCB_REAS_SYNTAX_ERROR; sccb->resp = SCCB_RESP_SYNTAX_ERROR; break; } break; case SCLP_READ_EVENT_DATA: /* Set the main storage change bit */ STORAGE_KEY(sccb_absolute_addr, regs) |= STORKEY_CHANGE; /* Set response code X'0100' if SCCB crosses a page boundary */ if ((sccb_absolute_addr & STORAGE_KEY_PAGEMASK) != ((sccb_absolute_addr + sccblen - 1) & STORAGE_KEY_PAGEMASK)) { sccb->reas = SCCB_REAS_NOT_PGBNDRY; sccb->resp = SCCB_RESP_BLOCK_ERROR; break; } /* Point to SCCB data area following SCCB header */ evd_hdr = (SCCB_EVD_HDR*)(sccb+1); if(SCLP_RECV_ENABLED(SCCB_EVD_TYPE_PRIOR) && sclp_attn_pending(SCCB_EVD_TYPE_PRIOR)) { sclp_opcmd_event(sccb, SCCB_EVD_TYPE_PRIOR); break; } if(SCLP_RECV_ENABLED(SCCB_EVD_TYPE_OPCMD) && sclp_attn_pending(SCCB_EVD_TYPE_OPCMD)) { sclp_opcmd_event(sccb, SCCB_EVD_TYPE_OPCMD); break; } #if defined(FEATURE_SCEDIO) if(SCLP_RECV_ENABLED(SCCB_EVD_TYPE_SCEDIO) && sclp_attn_pending(SCCB_EVD_TYPE_SCEDIO)) { ARCH_DEP(sclp_scedio_event)(sccb); break; } #endif /*defined(FEATURE_SCEDIO)*/ #if defined(FEATURE_INTEGRATED_3270_CONSOLE) if(SCLP_RECV_ENABLED(SCCB_EVD_TYPE_SYSG) && sclp_attn_pending(SCCB_EVD_TYPE_SYSG)) { sclp_sysg_poll(sccb); break; } #endif /*defined(FEATURE_INTEGRATED_3270_CONSOLE)*/ #if defined(FEATURE_INTEGRATED_ASCII_CONSOLE) if(SCLP_RECV_ENABLED(SCCB_EVD_TYPE_VT220) && sclp_attn_pending(SCCB_EVD_TYPE_VT220)) { sclp_sysa_poll(sccb); break; } #endif /*defined(FEATURE_INTEGRATED_ASCII_CONSOLE)*/ if(SCLP_RECV_ENABLED(SCCB_EVD_TYPE_SIGQ) && sclp_attn_pending(SCCB_EVD_TYPE_SIGQ)) { sclp_sigq_event(sccb); break; } PTT(PTT_CL_ERR,"*SERVC",regs->GR_L(r1),regs->GR_L(r2),regs->psw.IA_L); if( HDC3(debug_sclp_event_data, evd_hdr, sccb, regs) ) break; /* Set response code X'62F0' if events are pending but suppressed */ if(sclp_attn_pending(0)) { sccb->reas = SCCB_REAS_EVENTS_SUP; sccb->resp = SCCB_RESP_EVENTS_SUP; break; } else { /* Set response code X'60F0' if no outstanding events */ sccb->reas = SCCB_REAS_NO_EVENTS; sccb->resp = SCCB_RESP_NO_EVENTS; } break; case SCLP_WRITE_EVENT_MASK: /* Set the main storage change bit */ STORAGE_KEY(sccb_absolute_addr, regs) |= STORKEY_CHANGE; /* Set response code X'0100' if SCCB crosses a page boundary */ if ((sccb_absolute_addr & STORAGE_KEY_PAGEMASK) != ((sccb_absolute_addr + sccblen - 1) & STORAGE_KEY_PAGEMASK)) { sccb->reas = SCCB_REAS_NOT_PGBNDRY; sccb->resp = SCCB_RESP_BLOCK_ERROR; break; } /* Point to SCCB data area following SCCB header */ evd_mask = (SCCB_EVENT_MASK*)(sccb+1); /* Get length of single mask field */ FETCH_HW(masklen, evd_mask->length); /* Save old mask settings in order to suppress superflous messages */ old_cp_recv_mask = servc_cp_recv_mask & ARCH_DEP(sclp_send_mask) & SCCB_EVENT_CONS_RECV_MASK; old_cp_send_mask = servc_cp_send_mask & ARCH_DEP(sclp_recv_mask) & SCCB_EVENT_CONS_SEND_MASK; for (i = 0; i < 4; i++) { servc_cp_recv_mask <<= 8; servc_cp_send_mask <<= 8; if ((U32)i < masklen) { servc_cp_recv_mask |= evd_mask->masks[i+(0*masklen)]; servc_cp_send_mask |= evd_mask->masks[i+(1*masklen)]; } } if((servc_cp_recv_mask & ~ARCH_DEP(sclp_recv_mask)) || (servc_cp_send_mask & ~ARCH_DEP(sclp_send_mask))) HDC3(debug_sclp_unknown_event_mask, evd_mask, sccb, regs); /* Write the events that we support back */ memset (&evd_mask->masks[2 * masklen], 0, 2 * masklen); for (i = 0; (i < 4) && ((U32)i < masklen); i++) { evd_mask->masks[i+(2*masklen)] |= (ARCH_DEP(sclp_recv_mask) >> ((3-i)*8)) & 0xFF; evd_mask->masks[i+(3*masklen)] |= (ARCH_DEP(sclp_send_mask) >> ((3-i)*8)) & 0xFF; } /* Issue message only when supported mask has changed */ if ((servc_cp_recv_mask & ARCH_DEP(sclp_send_mask) & SCCB_EVENT_CONS_RECV_MASK) != old_cp_recv_mask || (servc_cp_send_mask & ARCH_DEP(sclp_recv_mask) & SCCB_EVENT_CONS_SEND_MASK) != old_cp_send_mask) { if ((servc_cp_recv_mask & SCCB_EVENT_CONS_RECV_MASK) != 0 || (servc_cp_send_mask & SCCB_EVENT_CONS_SEND_MASK) != 0) logmsg (_("HHCCP041I SYSCONS interface active\n")); else logmsg (_("HHCCP042I SYSCONS interface inactive\n")); } /* Set response code X'0020' in SCCB header */ sccb->reas = SCCB_REAS_NONE; sccb->resp = SCCB_RESP_COMPLETE; break; #endif /*FEATURE_SYSTEM_CONSOLE*/ #ifdef FEATURE_EXPANDED_STORAGE case SCLP_READ_XST_MAP: /* Set the main storage change bit */ STORAGE_KEY(sccb_absolute_addr, regs) |= STORKEY_CHANGE; /* Set response code X'0100' if SCCB crosses a page boundary */ if ((sccb_absolute_addr & STORAGE_KEY_PAGEMASK) != ((sccb_absolute_addr + sccblen - 1) & STORAGE_KEY_PAGEMASK)) { sccb->reas = SCCB_REAS_NOT_PGBNDRY; sccb->resp = SCCB_RESP_BLOCK_ERROR; break; } /* Calculate number of blocks per increment */ xstblkinc = XSTORE_INCREMENT_SIZE / XSTORE_PAGESIZE; /* Set response code X'0300' if SCCB length is insufficient to contain xstore info */ if ( sccblen < sizeof(SCCB_HEADER) + sizeof(SCCB_XST_MAP) + xstblkinc/8) { sccb->reas = SCCB_REAS_TOO_SHORT; sccb->resp = SCCB_RESP_BLOCK_ERROR; break; } /* Point to SCCB data area following SCCB header */ sccbxmap = (SCCB_XST_MAP*)(sccb+1); /* Verify expanded storage increment number */ xstincnum = sysblk.xpndsize / (XSTORE_INCREMENT_SIZE >> XSTORE_PAGESHIFT); FETCH_FW(i, sccbxmap->incnum); if ( i < 1 || (U32)i > xstincnum ) { sccb->reas = SCCB_REAS_INVALID_RSC; sccb->resp = SCCB_RESP_REJECT; break; } /* Point to bitmap */ xstmap = (BYTE*)(sccbxmap+1); /* Set all blocks available */ memset (xstmap, 0x00, xstblkinc/8); /* Set response code X'0010' in SCCB header */ sccb->reas = SCCB_REAS_NONE; sccb->resp = SCCB_RESP_INFO; break; #endif /*FEATURE_EXPANDED_STORAGE*/ #ifdef FEATURE_CPU_RECONFIG case SCLP_CONFIGURE_CPU: i = (sclp_command & SCLP_RESOURCE_MASK) >> SCLP_RESOURCE_SHIFT; /* Return invalid resource in parm if target does not exist */ if(i >= MAX_CPU) { sccb->reas = SCCB_REAS_INVALID_RSCP; sccb->resp = SCCB_RESP_REJECT; break; } /* Add cpu to the configuration */ configure_cpu(i); /* Set response code X'0020' in SCCB header */ sccb->reas = SCCB_REAS_NONE; sccb->resp = SCCB_RESP_COMPLETE; break; case SCLP_DECONFIGURE_CPU: i = (sclp_command & SCLP_RESOURCE_MASK) >> SCLP_RESOURCE_SHIFT; /* Return invalid resource in parm if target does not exist */ if(i >= MAX_CPU) { sccb->reas = SCCB_REAS_INVALID_RSCP; sccb->resp = SCCB_RESP_REJECT; break; } /* Take cpu out of the configuration */ deconfigure_cpu(i); /* Set response code X'0020' in SCCB header */ sccb->reas = SCCB_REAS_NONE; sccb->resp = SCCB_RESP_COMPLETE; break; #ifdef FEATURE_VECTOR_FACILITY case SCLP_DISCONNECT_VF: i = (sclp_command & SCLP_RESOURCE_MASK) >> SCLP_RESOURCE_SHIFT; /* Return invalid resource in parm if target does not exist */ if(i >= MAX_CPU || !IS_CPU_ONLINE(i)) { sccb->reas = SCCB_REAS_INVALID_RSCP; sccb->resp = SCCB_RESP_REJECT; break; } if(sysblk.regs[i]->vf->online) logmsg(_("CPU%4.4X: Vector Facility configured offline\n"),i); /* Take the VF out of the configuration */ sysblk.regs[i]->vf->online = 0; /* Set response code X'0020' in SCCB header */ sccb->reas = SCCB_REAS_NONE; sccb->resp = SCCB_RESP_COMPLETE; break; case SCLP_CONNECT_VF: i = (sclp_command & SCLP_RESOURCE_MASK) >> SCLP_RESOURCE_SHIFT; /* Return invalid resource in parm if target does not exist */ if(i >= MAX_CPU) { sccb->reas = SCCB_REAS_INVALID_RSCP; sccb->resp = SCCB_RESP_REJECT; break; } /* Return improper state if associated cpu is offline */ if(!IS_CPU_ONLINE(i)) { sccb->reas = SCCB_REAS_IMPROPER_RSC; sccb->resp = SCCB_RESP_REJECT; break; } if(!sysblk.regs[i]->vf->online) logmsg(_("CPU%4.4X: Vector Facility configured online\n"),i); /* Mark the VF online to the CPU */ sysblk.regs[i]->vf->online = 1; /* Set response code X'0020' in SCCB header */ sccb->reas = SCCB_REAS_NONE; sccb->resp = SCCB_RESP_COMPLETE; break; #endif /*FEATURE_VECTOR_FACILITY*/ #endif /*FEATURE_CPU_RECONFIG*/ default: invalidcmd: PTT(PTT_CL_INF|PTT_CL_ERR,"*SERVC",regs->GR_L(r1),regs->GR_L(r2),regs->psw.IA_L); if( HDC3(debug_sclp_unknown_command, sclp_command, sccb, regs) ) break; /* Set response code X'01F0' for invalid SCLP command */ sccb->reas = SCCB_REAS_INVALID_CMD; sccb->resp = SCCB_RESP_REJECT; break; } /* end switch(sclp_command) */ /* If immediate response is requested, return condition code 1 */ if ((sccb->flag & SCCB_FLAG_SYNC) && (sclp_command & SCLP_COMMAND_CLASS) != 0x01) { regs->psw.cc = 1; return; } /* Set service signal external interrupt pending */ sysblk.servparm &= ~SERVSIG_ADDR; sysblk.servparm |= sccb_absolute_addr; ON_IC_SERVSIG; /* Release the interrupt lock */ RELEASE_INTLOCK(regs); /* Set condition code 0 */ regs->psw.cc = 0; } /* end function service_call */ #endif /*defined(FEATURE_SERVICE_PROCESSOR)*/ #if !defined(_GEN_ARCH) #if defined(_ARCHMODE2) #define _GEN_ARCH _ARCHMODE2 #include "service.c" #endif #if defined(_ARCHMODE3) #undef _GEN_ARCH #define _GEN_ARCH _ARCHMODE3 #include "service.c" #endif #endif /*!defined(_GEN_ARCH)*/ hercules-3.07/service.h000644 000765 000765 00000061401 11301535255 016556 0ustar00jmaynardjmaynard000000 000000 /* SERVICE.H (c) Copyright Jan Jaeger, 1999-2009 */ /* Service Processor Architectured fields */ // $Id: service.h 5452 2009-08-12 09:53:50Z rbowler $ #if !defined(_SERVICE_H) #define _SERVICE_H /*-------------------------------------------------------------------*/ /* Service Call Logical Processor command word definitions */ /*-------------------------------------------------------------------*/ #define SCLP_READ_SCP_INFO 0x00020001 #define SCLP_READ_IFL_INFO 0x00120001 #define SCLP_READ_CHP_INFO 0x00030001 #define SCLP_READ_CSI_INFO 0x001C0001 #define SCLP_READ_XST_MAP 0x00250001 #define SCLP_WRITE_EVENT_DATA 0x00760005 #define SCLP_READ_EVENT_DATA 0x00770005 #define SCLP_WRITE_EVENT_MASK 0x00780005 #define SCLP_DECONFIGURE_CPU 0x00100001 #define SCLP_CONFIGURE_CPU 0x00110001 #define SCLP_DISCONNECT_VF 0x001A0001 #define SCLP_CONNECT_VF 0x001B0001 #define SCLP_COMMAND_MASK 0xFFFF00FF #define SCLP_COMMAND_CLASS 0x000000FF #define SCLP_RESOURCE_MASK 0x0000FF00 #define SCLP_RESOURCE_SHIFT 8 /*-------------------------------------------------------------------*/ /* Service Call Control Block structure definitions */ /*-------------------------------------------------------------------*/ typedef struct _SCCB_HEADER { HWORD length; /* Total length of SCCB */ BYTE flag; /* Flag byte */ BYTE resv1[2]; /* Reserved */ BYTE type; /* Request type */ BYTE reas; /* Reason code */ BYTE resp; /* Response class code */ } SCCB_HEADER; /* Bit definitions for SCCB header flag byte */ #define SCCB_FLAG_SYNC 0x80 /* Synchronous request */ /* Bit definitions for SCCB header request type */ #define SCCB_TYPE_VARIABLE 0x80 /* Variable request */ /* Bit definitions for SCCB header reason code */ #define SCCB_REAS_NONE 0x00 /* No reason */ #define SCCB_REAS_NOT_PGBNDRY 0x01 /* SCCB crosses page boundary*/ #define SCCB_REAS_ODD_LENGTH 0x02 /* Length not multiple of 8 */ #define SCCB_REAS_TOO_SHORT 0x03 /* Length is inadequate */ #define SCCB_REAS_NOACTION 0x02 /* Resource in req. state */ #define SCCB_REAS_STANDBY 0x04 /* Resource in standby state */ #define SCCB_REAS_INVALID_CMD 0x01 /* Invalid SCLP command code */ #define SCCB_REAS_INVALID_RSCP 0x03 /* Invalid resource in parm */ #define SCCB_REAS_IMPROPER_RSC 0x05 /* Resource in improper state*/ #define SCCB_REAS_INVALID_RSC 0x09 /* Invalid resource */ /* Bit definitions for SCCB header response class code */ #define SCCB_RESP_BLOCK_ERROR 0x00 /* Data block error */ #define SCCB_RESP_INFO 0x10 /* Information returned */ #define SCCB_RESP_COMPLETE 0x20 /* Command complete */ #define SCCB_RESP_BACKOUT 0x40 /* Command backed out */ #define SCCB_RESP_REJECT 0xF0 /* Command reject */ // #ifdef FEATURE_SYSTEM_CONSOLE #define SCCB_REAS_NO_EVENTS 0x60 /* No outstanding EVENTs */ #define SCCB_RESP_NO_EVENTS 0xF0 #define SCCB_REAS_EVENTS_SUP 0x62 /* All events suppressed */ #define SCCB_RESP_EVENTS_SUP 0xF0 #define SCCB_REAS_INVALID_MASK 0x70 /* Invalid events mask */ #define SCCB_RESP_INVALID_MASK 0xF0 #define SCCB_REAS_MAX_BUFF 0x71 /* Buffer exceeds maximum */ #define SCCB_RESP_MAX_BUFF 0xF0 #define SCCB_REAS_BUFF_LEN_ERR 0x72 /* Buffer len verification */ #define SCCB_RESP_BUFF_LEN_ERR 0xF0 #define SCCB_REAS_SYNTAX_ERROR 0x73 /* Buffer syntax error */ #define SCCB_RESP_SYNTAX_ERROR 0xF0 #define SCCB_REAS_INVALID_MSKL 0x74 /* Invalid mask length */ #define SCCB_RESP_INVALID_MSKL 0xF0 #define SCCB_REAS_EXCEEDS_SCCB 0x75 /* Exceeds SCCB max capacity */ #define SCCB_RESP_EXCEEDS_SCCB 0xF0 // #endif /*FEATURE_SYSTEM_CONSOLE*/ /* SCP information data area */ typedef struct _SCCB_SCP_INFO { HWORD realinum; /* Number of real storage increments installed */ BYTE realiszm; /* Size of each real storage increment in MB */ BYTE realbszk; /* Size of each real storage block in KB */ HWORD realiint; /* Real storage increment block interleave interval */ HWORD resv2; /* Reserved */ HWORD numcpu; /* Number of CPUs installed */ HWORD offcpu; /* Offset from start of SCCB to CPU information array */ HWORD numhsa; /* Number of HSAs */ HWORD offhsa; /* Offset from start of SCCB to HSA information array */ BYTE loadparm[8]; /* Load parameter */ FWORD xpndinum; /* Number of expanded storage increments installed */ FWORD xpndsz4K; /* Number of 4KB blocks in an expanded storage increment*/ HWORD xpndenum; /* Number of expanded storage elements installed */ HWORD resv3; /* Reserved */ HWORD vectssiz; /* Vector section size */ HWORD vectpsum; /* Vector partial sum number */ BYTE ifm[8]; /* Installed facilities */ BYTE resv4[8]; /* Reserved */ HWORD maxresgp; /* Maximum resource group */ BYTE resv5[6]; /* Reserved */ HWORD nummpf; /* Number of entries in MPF information array */ HWORD offmpf; /* Offset from start of SCCB to MPF information array */ BYTE resv6[4]; /* Reserved */ BYTE cfg[6]; /* Config characteristics */ FWORD rcci; /* Capacity */ BYTE cfg11; /* Config char. byte 11 */ BYTE numcrl; /* Max #of copy and reassign list elements allowed */ FWORD etrtol; /* ETR sync check tolerance */ BYTE resv60[3]; BYTE maxvm; /* Max guest storage size >= 31 and <= 64 (2**pow)-1 is the max supported guest real size. 0 means not constrained. */ FWORD grzm; /* Addess increment size in units of 1M, valid only if realiszm is zero */ DBLWRD grnmx; /* Maximum increment number when it is larger then 64K or when ESAME is on */ BYTE resv8[16]; /* Reserved */ } SCCB_SCP_INFO; /* Bit definitions for installed facilities */ #define SCCB_IFM0_CHANNEL_PATH_INFORMATION 0x80 #define SCCB_IFM0_CHANNEL_PATH_SUBSYSTEM_COMMAND 0x40 #define SCCB_IFM0_CHANNEL_PATH_RECONFIG 0x20 #define SCCB_IFM0_CPU_INFORMATION 0x08 #define SCCB_IFM0_CPU_RECONFIG 0x04 #define SCCB_IFM1_SIGNAL_ALARM 0x80 #define SCCB_IFM1_WRITE_OPERATOR_MESSAGE 0x40 #define SCCB_IFM1_STORE_STATUS_ON_LOAD 0x20 #define SCCB_IFM1_RESTART_REASONS 0x10 #define SCCB_IFM1_INSTRUCTION_ADDRESS_TRACE_BUFFER 0x08 #define SCCB_IFM1_LOAD_PARAMETER 0x04 #define SCCB_IFM1_READ_AND_WRITE_DATA 0x02 #define SCCB_IFM2_REAL_STORAGE_INCREMENT_RECONFIG 0x80 #define SCCB_IFM2_REAL_STORAGE_ELEMENT_INFO 0x40 #define SCCB_IFM2_REAL_STORAGE_ELEMENT_RECONFIG 0x20 #define SCCB_IFM2_COPY_AND_REASSIGN_STORAGE 0x10 #define SCCB_IFM2_EXTENDED_STORAGE_USABILITY_MAP 0x08 #define SCCB_IFM2_EXTENDED_STORAGE_ELEMENT_INFO 0x04 #define SCCB_IFM2_EXTENDED_STORAGE_ELEMENT_RECONFIG 0x02 #define SCCB_IFM2_COPY_AND_REASSIGN_STORAGE_LIST 0x01 #define SCCB_IFM3_VECTOR_FEATURE_RECONFIG 0x80 #define SCCB_IFM3_READ_WRITE_EVENT_FEATURE 0x40 #define SCCB_IFM3_EXTENDED_STORAGE_USABILITY_MAP_EXT 0x20 #define SCCB_IFM3_READ_RESOURCE_GROUP_INFO 0x08 #define SCCB_IFM4_READ_STORAGE_STATUS 0x80 /* Bit definitions for configuration characteristics */ #define SCCB_CFG0_LOGICALLY_PARTITIONED 0x80 #define SCCB_CFG0_SUPPRESSION_ON_PROTECTION 0x20 #define SCCB_CFG0_INITIATE_RESET 0x10 #define SCCB_CFG0_STORE_CHANNEL_SUBSYS_CHARACTERISTICS 0x08 #define SCCB_CFG0_FAST_SYNCHRONOUS_DATA_MOVER 0x01 #define SCCB_CFG0_MVPG_FOR_ALL_GUESTS 0x04 #define SCCB_CFG0_UNKNOWN_BUT_SET_UNDER_VM 0x02 #define SCCB_CFG1_CSLO 0x40 #define SCCB_CFG2_DEVICE_ACTIVE_ONLY_MEASUREMENT 0x40 #define SCCB_CFG2_CALLED_SPACE_IDENTIFICATION 0x02 #define SCCB_CFG2_CHECKSUM_INSTRUCTION 0x01 #define SCCB_CFG3_RESUME_PROGRAM 0x80 #define SCCB_CFG3_PERFORM_LOCKED_OPERATION 0x40 #define SCCB_CFG3_IMMEDIATE_AND_RELATIVE 0x10 #define SCCB_CFG3_COMPARE_AND_MOVE_EXTENDED 0x08 #define SCCB_CFG3_BRANCH_AND_SET_AUTHORITY 0x04 #define SCCB_CFG3_EXTENDED_FLOATING_POINT 0x02 #define SCCB_CFG3_EXTENDED_LOGICAL_COMPUTATION_FACILITY 0x01 #define SCCB_CFG4_EXTENDED_TOD_CLOCK 0x80 #define SCCB_CFG4_EXTENDED_TRANSLATION 0x40 #define SCCB_CFG4_LOAD_REVERSED_FACILITY 0x20 #define SCCB_CFG4_EXTENDED_TRANSLATION_FACILITY2 0x10 #define SCCB_CFG4_STORE_SYSTEM_INFORMATION 0x08 #define SCCB_CFG4_LPAR_CLUSTERING 0x02 #define SCCB_CFG4_IFA_FACILITY 0x01 #define SCCB_CFG5_SENSE_RUNNING_STATUS 0x08 #define SCCB_CFG5_ESAME 0x01 #define SCCB_CFGB_PER_3 0x04 #define SCCB_CFGB_LOAD_WITH_DUMP 0x02 #define SCCB_CFGB_LIST_DIRECTED_IPL 0x01 /* CPU information array entry */ typedef struct _SCCB_CPU_INFO { BYTE cpa; /* CPU address */ BYTE tod; /* TOD clock number */ BYTE cpf[12]; /* RCPU facility map */ BYTE ptyp; /* Processor type */ BYTE ksid; /* Crypto unit identifier */ } SCCB_CPU_INFO; /* Bit definitions for CPU installed features */ #define SCCB_CPF0_SIE_370_MODE 0x80 #define SCCB_CPF0_SIE_XA_MODE 0x40 #define SCCB_CPF0_SIE_SET_II_370_MODE 0x20 #define SCCB_CPF0_SIE_SET_II_XA_MODE 0x10 #define SCCB_CPF0_SIE_NEW_INTERCEPT_FORMAT 0x08 #define SCCB_CPF0_STORAGE_KEY_ASSIST 0x04 #define SCCB_CPF0_MULTIPLE_CONTROLLED_DATA_SPACE 0x02 #define SCCB_CPF1_IO_INTERPRETATION_LEVEL_2 0x40 #define SCCB_CPF1_GUEST_PER_ENHANCED 0x20 #define SCCB_CPF1_SIGP_INTERPRETATION_ASSIST 0x08 #define SCCB_CPF1_RCP_BYPASS_FACILITY 0x04 #define SCCB_CPF1_REGION_RELOCATE_FACILITY 0x02 #define SCCB_CPF1_EXPEDITE_TIMER_PROCESSING 0x01 #define SCCB_CPF2_VECTOR_FEATURE_INSTALLED 0x80 #define SCCB_CPF2_VECTOR_FEATURE_CONNECTED 0x40 #define SCCB_CPF2_VECTOR_FEATURE_STANDBY_STATE 0x20 #define SCCB_CPF2_CRYPTO_FEATURE_ACCESSED 0x10 #define SCCB_CPF2_EXPEDITE_RUN_PROCESSING 0x04 #define SCCB_CPF3_PRIVATE_SPACE_FEATURE 0x80 #define SCCB_CPF3_FETCH_ONLY_BIT 0x40 #define SCCB_CPF3_PER2_INSTALLED 0x01 #define SCCB_CPF4_OMISION_GR_ALTERATION_370 0x80 #define SCCB_CPF5_GUEST_WAIT_STATE_ASSIST 0x40 /* Definitions for processor type code */ #define SCCB_PTYP_CP 0 #define SCCB_PTYP_ICF 1 #define SCCB_PTYP_IFA 2 #define SCCB_PTYP_IFL 3 #define SCCB_PTYP_SUP 5 #define SCCB_PTYP_MAX 5 /*(maximum value)*/ /* Definitions for crypto unit identifier */ #define SCCB_KSID_CRYPTO_UNIT_ID 0x01 /* HSA information array entry */ typedef struct _SCCB_HSA_INFO { HWORD hssz; /* Size of HSA in 4K blocks */ FWORD ahsa; /* Address of HSA */ } SCCB_HSA_INFO; /* MPF information array entry */ typedef struct _SCCB_MPF_INFO { HWORD mpfy; /* MPF info array entry */ } SCCB_MPF_INFO; /* Channel path information data area */ typedef struct _SCCB_CHP_INFO { BYTE installed[32]; /* Channels installed bits */ BYTE standby[32]; /* Channels standby bits */ BYTE online[32]; /* Channels online bits */ } SCCB_CHP_INFO; /* Channel path information data area */ typedef struct _SCCB_CHSET { BYTE chanset0a[32]; /* 370 channel set 0A */ BYTE chanset1a[32]; /* 370 channel set 1A */ BYTE chanset0b[32]; /* 370 channel set 0B */ BYTE chanset1b[32]; /* 370 channel set 1B */ BYTE csconfig; /* Channel set configuration */ BYTE resv[23]; /* Reserved, set to zero */ } SCCB_CHSET_INFO; /* Read Channel Subsystem Information data area */ typedef struct _SCCB_CSI_INFO { BYTE csif[8]; /* Channel Subsystem installed facility field */ BYTE resv[48]; } SCCB_CSI_INFO; /* Bit definitions for channel subsystem installed facilities */ #define SCCB_CSI0_CANCEL_IO_REQUEST_FACILITY 0x02 #define SCCB_CSI0_CONCURRENT_SENSE_FACILITY 0x01 // #ifdef FEATURE_SYSTEM_CONSOLE /* Write Event Mask */ typedef struct _SCCB_EVENT_MASK { HWORD reserved; HWORD length; /* Event mask length */ BYTE masks[32]; /* Event masks */ // FWORD cp_recv_mask; /* These mask fields have */ // FWORD cp_send_mask; /* the length defined by */ // FWORD sclp_recv_mask; /* the length halfword */ // FWORD sclp_send_mask; } SCCB_EVENT_MASK; #define SCCB_EVENT_CONS_RECV_MASK ( \ (0x80000000 >> (SCCB_EVD_TYPE_MSG-1)) | \ (0x80000000 >> (SCCB_EVD_TYPE_PRIOR-1)) ) #define SCCB_EVENT_CONS_SEND_MASK ( \ (0x80000000 >> (SCCB_EVD_TYPE_OPCMD-1)) | \ (0x80000000 >> (SCCB_EVD_TYPE_PRIOR-1)) | \ (0x80000000 >> (SCCB_EVD_TYPE_CPCMD-1)) ) /* Read/Write Event Data Header */ typedef struct _SCCB_EVD_HDR { HWORD totlen; /* Event Data Buffer total length */ BYTE type; #define SCCB_EVD_TYPE_OPCMD 0x01 /* Operator command */ #define SCCB_EVD_TYPE_MSG 0x02 /* Message from Control Pgm */ // #if defined(FEATURE_SCEDIO ) #define SCCB_EVD_TYPE_SCEDIO 0x07 /* SCE DASD I/O */ // #endif /*defined(FEATURE_SCEDIO )*/ #define SCCB_EVD_TYPE_STATECH 0x08 /* State Change */ #define SCCB_EVD_TYPE_PRIOR 0x09 /* Priority message/command */ #define SCCB_EVD_TYPE_CPIDENT 0x0B /* CntlProgIdent */ #define SCCB_EVD_TYPE_VT220 0x1A /* VT220 Msg */ #define SCCB_EVD_TYPE_SYSG 0x1B /* 3270 Msg (SYSG console) */ #define SCCB_EVD_TYPE_SIGQ 0x1D /* SigQuiesce */ #define SCCB_EVD_TYPE_CPCMD 0x20 /* CntlProgOpCmd */ BYTE flag; #define SCCB_EVD_FLAG_PROC 0x80 /* Event successful */ HWORD resv; /* Reserved for future use */ } SCCB_EVD_HDR; /* Read/Write Event Data Buffer */ typedef struct _SCCB_EVD_BK { HWORD msglen; BYTE const1[51]; HWORD cplen; /* CP message length */ BYTE const2[24]; HWORD tdlen; /* Text Data length */ BYTE const3[2]; BYTE sdtlen; BYTE const4; /* Self defining tag */ BYTE tmlen; BYTE const5; /* Text Message format */ // BYTE txtmsg[n]; } SCCB_EVD_BK; /* Message Control Data Block */ typedef struct _SCCB_MCD_BK { HWORD length; /* Total length of MCD */ HWORD type; /* Type must be 0x0001 */ FWORD tag; /* Tag must be 0xD4C4C240 */ FWORD revcd; /* Revision code 0x00000001 */ } SCCB_MCD_BK; /* Message Control Data Block Header */ typedef struct _SCCB_OBJ_HDR { HWORD length; /* Total length of OBJ */ HWORD type; /* Object type */ #define SCCB_OBJ_TYPE_GENERAL 0x0001 /* General Object */ #define SCCB_OBJ_TYPE_CPO 0x0002 /* Control Program Object */ #define SCCB_OBJ_TYPE_NLS 0x0003 /* NLS data Object */ #define SCCB_OBJ_TYPE_MESSAGE 0x0004 /* Message Text Object */ } SCCB_OBJ_HDR; /* Message Control Data Block Message Text Object */ typedef struct _SCCB_MTO_BK { BYTE ltflag[2]; /* Line type flag */ #define SCCB_MTO_LTFLG0_CNTL 0x80 /* Control text line */ #define SCCB_MTO_LTFLG0_LABEL 0x40 /* Label text line */ #define SCCB_MTO_LTFLG0_DATA 0x20 /* Data text line */ #define SCCB_MTO_LTFLG0_END 0x10 /* Last line of message */ #define SCCB_MTO_LTFLG0_PROMPT 0x08 /* Prompt line - response requested (WTOR) */ #define SCCB_MTO_LTFLG0_DBCS 0x04 /* DBCS text */ #define SCCB_MTO_LTFLG0_MIX 0x02 /* Mixed SBCS/DBCS text */ #define SCCB_MTO_LTFLG1_OVER 0x01 /* Foreground presentation field override */ BYTE presattr[4]; /* Presentation Attribute Byte 0 - control Byte 1 - color Byte 2 - highlighting Byte 3 - intensity */ #define SCCB_MTO_PRATTR0_ALARM 0x80 /* Sound alarm (console) */ #define SCCB_MTO_PRATTR3_HIGH 0xE8 /* Highlighted */ #define SCCB_MTO_PRATTR3_NORM 0xE4 /* Normal */ } SCCB_MTO_BK; /* Message Control Data Block General Object */ typedef struct _SCCB_MGO_BK { FWORD seq; /* Message DOM ID */ BYTE time[11]; /* C'HH.MM.SS.th' */ BYTE resv1; BYTE date[7]; /* C'YYYYDDD' */ BYTE resv2; BYTE mflag[2]; /* Message Flags */ #define SCCB_MGO_MFLAG0_DOM 0x80 /* Delete Operator Message */ #define SCCB_MGO_MFLAG0_ALARM 0x40 /* Sound the SCLP alarm */ #define SCCB_MGO_MFLAG0_HOLD 0x20 /* Hold message until DOM */ BYTE presattr[4]; /* Presentation Attribute Byte 0 - control Byte 1 - color Byte 2 - highlighting Byte 3 - intensity */ #define SCCB_MGO_PRATTR0_ALARM 0x80 /* Sound alarm (console) */ #define SCCB_MGO_PRATTR3_HIGH 0xE8 /* Highlighted */ #define SCCB_MGO_PRATTR3_NORM 0xE4 /* Normal */ BYTE bckattr[4]; /* Background presentation attributes - covers all message-test foreground presentation attribute field overrides */ BYTE sysname[8]; /* Originating system name */ BYTE jobname[8]; /* Jobname or guestname */ } SCCB_MGO_BK; /* Control Program Information */ typedef struct _SCCB_CPI_BK { BYTE id_fmt; BYTE resv0; BYTE system_type[8]; DBLWRD resv1; BYTE system_name[8]; DBLWRD resv2; DBLWRD system_level; DBLWRD resv3; BYTE sysplex_name[8]; BYTE resv4[16]; } SCCB_CPI_BK; /* Message Control Data Block NLS Object */ typedef struct _SCCB_NLS_BK { HWORD scpgid; /* CPGID for SBCS (def 037) */ HWORD scpsgid; /* CPSGID for SBCS (def 637) */ HWORD dcpgid; /* CPGID for DBCS (def 037) */ HWORD dcpsgid; /* CPSGID for DBCS (def 637) */ } SCCB_NLS_BK; /* Signal Quiesce */ typedef struct _SCCB_SGQ_BK { HWORD count; /* Countdown in units */ BYTE unit; /* Unit type */ #define SCCB_SGQ_SEC 0 #define SCCB_SGQ_MIN 1 #define SCCB_SGQ_HR 2 } SCCB_SGQ_BK; // #endif /*FEATURE_SYSTEM_CONSOLE*/ // #ifdef FEATURE_EXPANDED_STORAGE typedef struct _SCCB_XST_INFO { HWORD elmid; /* Extended storage element id */ BYTE resv1[6]; FWORD elmsin; /* Starting increment number */ FWORD elmein; /* Ending increment number */ BYTE elmchar; /* Element characteristics */ #define SCCB_XST_INFO_ELMCHAR_REQ 0x80; /* Required element */ BYTE resv2[39]; } SCCB_XST_INFO; typedef struct _SCCB_XST_MAP { FWORD incnum; /* Increment number */ FWORD resv; // BYTE map[]; /* Bitmap of all usable // expanded storage blocks */ } SCCB_XST_MAP; // #endif /*FEATURE_EXPANDED_STORAGE*/ // #if defined(FEATURE_SCEDIO ) /* SCE DASD I/O Request */ typedef struct _SCCB_SCEDIO_BK { BYTE flag0; BYTE flag1; #define SCCB_SCEDIO_FLG1_IOR 0x03 #define SCCB_SCEDIO_FLG1_IOV 0x04 BYTE flag2; BYTE flag3; #define SCCB_SCEDIO_FLG3_COMPLETE 0x80 } SCCB_SCEDIO_BK; typedef struct _SCCB_SCEDIOV_BK { BYTE type; #define SCCB_SCEDIOV_TYPE_INIT 0x00 #define SCCB_SCEDIOV_TYPE_READ 0x01 #define SCCB_SCEDIOV_TYPE_CREATE 0x02 #define SCCB_SCEDIOV_TYPE_APPEND 0x03 BYTE flag1; BYTE flag2; BYTE flag3; DBLWRD seek; DBLWRD ncomp; DBLWRD length; DBLWRD resv2; DBLWRD resv3; DBLWRD sto; BYTE filename[256]; } SCCB_SCEDIOV_BK; typedef struct _SCCB_SCEDIOR_BK { BYTE type; #define SCCB_SCEDIOR_TYPE_INIT 0x00 #define SCCB_SCEDIOR_TYPE_READ 0x01 BYTE flag1; BYTE flag2; BYTE flag3; FWORD origin; FWORD resv1; FWORD resv2; BYTE image[8]; } SCCB_SCEDIOR_BK; // #endif /*defined(FEATURE_SCEDIO )*/ #endif /*!defined(_SERVICE_H)*/ hercules-3.07/shared.c000644 000765 000765 00000305743 11143760544 016376 0ustar00jmaynardjmaynard000000 000000 /* SHARED.C (c)Copyright Greg Smith, 2002-2009 */ /* Shared Device Server */ // $Id: shared.c 5172 2009-02-08 16:26:06Z rbowler $ // // $Log$ // Revision 1.41 2009/01/23 13:01:34 bernard // copyright notice // // Revision 1.40 2008/11/04 05:56:31 fish // Put ensure consistent create_thread ATTR usage change back in // // Revision 1.39 2008/11/03 15:31:53 rbowler // Back out consistent create_thread ATTR modification // // Revision 1.38 2008/10/18 09:32:21 fish // Ensure consistent create_thread ATTR usage // // Revision 1.37 2008/03/29 08:36:46 fish // More complete/extensive 3490/3590 tape support // // Revision 1.36 2007/06/23 00:04:15 ivan // Update copyright notices to include current year (2007) // // Revision 1.35 2006/12/28 20:32:54 fish // Fix "HHCSH043I 0.0.0.0 disconnected from ..."; save clientip in SHRD block at connect and use at disconnect. // // Revision 1.34 2006/12/08 09:43:30 jj // Add CVS message log // #include "hstdinc.h" #define _HERCULES_SHARED_C #define _SHARED_C_ #define _HDASD_DLL_ #include "hercules.h" #include "opcode.h" #include "devtype.h" #define FBA_BLKGRP_SIZE (120*512) /* Change the following to "define" when Shared FBA support is implemented */ #undef FBA_SHARED /*-------------------------------------------------------------------*/ /* Definitions for sense data format codes and message codes */ /*-------------------------------------------------------------------*/ #define FORMAT_0 0 /* Program or System Checks */ #define FORMAT_1 1 /* Device Equipment Checks */ #define FORMAT_2 2 /* 3990 Equipment Checks */ #define FORMAT_3 3 /* 3990 Control Checks */ #define FORMAT_4 4 /* Data Checks */ #define FORMAT_5 5 /* Data Check + Displacement */ #define FORMAT_6 6 /* Usage Stats/Overrun Errors*/ #define FORMAT_7 7 /* Device Control Checks */ #define FORMAT_8 8 /* Device Equipment Checks */ #define FORMAT_9 9 /* Device Rd/Wrt/Seek Checks */ #define FORMAT_F 15 /* Cache Storage Checks */ #define MESSAGE_0 0 /* Message 0 */ #define MESSAGE_1 1 /* Message 1 */ #define MESSAGE_2 2 /* Message 2 */ #define MESSAGE_3 3 /* Message 3 */ #define MESSAGE_4 4 /* Message 4 */ #define MESSAGE_5 5 /* Message 5 */ #define MESSAGE_6 6 /* Message 6 */ #define MESSAGE_7 7 /* Message 7 */ #define MESSAGE_8 8 /* Message 8 */ #define MESSAGE_9 9 /* Message 9 */ #define MESSAGE_A 10 /* Message A */ #define MESSAGE_B 11 /* Message B */ #define MESSAGE_C 12 /* Message C */ #define MESSAGE_D 13 /* Message D */ #define MESSAGE_E 14 /* Message E */ #define MESSAGE_F 15 /* Message F */ #if defined(OPTION_SHARED_DEVICES) DEVHND shared_ckd_device_hndinfo; DEVHND shared_fba_device_hndinfo; static BYTE eighthexFF[] = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}; /*------------------------------------------------------------------- * Update notify - called by device handlers for sharable devices *-------------------------------------------------------------------*/ int shared_update_notify (DEVBLK *dev, int block) { int i, j; /* Indexes */ /* Return if no remotes are connected */ if (dev->shrdconn == 0) return 0; for (i = 0; i < SHARED_MAX_SYS; i++) { /* Ignore the entry if it doesn't exist or if it's ours our if it's already maxed out */ if (dev->shrd[i] == NULL || dev->shrd[i]->id == dev->ioactive || dev->shrd[i]->purgen < 0) continue; /* Check if the block is already entered */ for (j = 0; j < dev->shrd[i]->purgen; j++) if (fetch_fw(dev->shrd[i]->purge[j]) == (U32)block) break; /* Add the block if it's not already there */ if (j >= dev->shrd[i]->purgen) { if (dev->shrd[i]->purgen >= SHARED_PURGE_MAX) dev->shrd[i]->purgen = -1; else store_fw (dev->shrd[i]->purge[dev->shrd[i]->purgen++], block); shrdtrc(dev,"notify %d added for id=%d, n=%d\n", block, dev->shrd[i]->id, dev->shrd[i]->purgen); } } /* for each possible remote system */ return 0; } /* shared_update_notify */ /*------------------------------------------------------------------- * CKD init exit (client side) *-------------------------------------------------------------------*/ int shared_ckd_init (DEVBLK *dev, int argc, char *argv[] ) { int rc; /* Return code */ int i; /* Loop index */ int retry; /* 1=Connection being retried*/ char *ipname; /* Remote name or address */ char *port = NULL; /* Remote port */ char *rmtnum = NULL; /* Remote device number */ struct hostent *he; /* -> hostent structure */ char *kw; /* Argument keyword */ char *op; /* Argument operand */ BYTE c; /* Used for parsing */ char *cu = NULL; /* Specified control unit */ FWORD cyls; /* Remote number cylinders */ char *p, buf[1024]; /* Work buffer */ retry = dev->connecting; /* Process the arguments */ if (!retry) { if (argc < 1 || strlen(argv[0]) >= sizeof(buf)) return -1; strcpy (buf, argv[0]); /* First argument is `ipname:port:devnum' */ ipname = buf; if (strchr(ipname,'/') || strchr(ipname,'\\')) return -1; p = strchr (buf, ':'); if (p) { *p = '\0'; port = p + 1; p = strchr (port, ':'); } if (p) { *p = '\0'; rmtnum = p + 1; } #if defined( HAVE_SYS_UN_H ) if ( strcmp (ipname, "localhost") == 0) dev->localhost = 1; else #endif { if ( (he = gethostbyname (ipname)) == NULL ) return -1; memcpy(&dev->rmtaddr, he->h_addr_list[0], sizeof(dev->rmtaddr)); } if (port && strlen(port)) { if (sscanf(port, "%hu%c", &dev->rmtport, &c) != 1) return -1; } else dev->rmtport = SHARED_DEFAULT_PORT; if (rmtnum && strlen(rmtnum)) { if (strlen (rmtnum) > 4 || sscanf (rmtnum, "%hx%c", &dev->rmtnum, &c) != 1) return -1; } else dev->rmtnum = dev->devnum; /* Process the remaining arguments */ for (i = 1; i < argc; i++) { if (strcasecmp ("readonly", argv[i]) == 0 || strcasecmp ("rdonly", argv[i]) == 0 || strcasecmp ("ro", argv[i]) == 0) { dev->ckdrdonly = 1; continue; } if (strcasecmp ("fakewrite", argv[i]) == 0 || strcasecmp ("fakewrt", argv[i]) == 0 || strcasecmp ("fw", argv[i]) == 0) { dev->ckdfakewr = 1; continue; } if (strlen (argv[i]) > 3 && memcmp("cu=", argv[i], 3) == 0) { kw = strtok (argv[i], "="); op = strtok (NULL, " \t"); cu = op; continue; } #ifdef HAVE_LIBZ if (strlen (argv[i]) > 5 && memcmp("comp=", argv[i], 5) == 0) { kw = strtok (argv[i], "="); op = strtok (NULL, " \t"); dev->rmtcomp = atoi (op); if (dev->rmtcomp < 0 || dev->rmtcomp > 9) dev->rmtcomp = 0; continue; } #endif logmsg (_("HHCSH001S parameter %d is invalid: %s\n"), i + 1, argv[i]); return -1; } } /* Set suported compression */ dev->rmtcomps = 0; #ifdef HAVE_LIBZ dev->rmtcomps |= SHRD_LIBZ; #endif #ifdef CCKD_BZIP2 dev->rmtcomps |= SHRD_BZIP2; #endif /* Update the device handler vector */ dev->hnd = &shared_ckd_device_hndinfo; dev->connecting = 1; init_retry: do { rc = clientConnect (dev, retry); if (rc < 0) { logmsg (_("HHCSH002W %4.4X connect pending to %s\n"), dev->devnum, dev->filename); if (retry) SLEEP(5); } } while (retry && rc < 0); /* Return if unable to connect */ if (rc < 0) return 0; dev->ckdnumfd = 1; dev->ckdfd[0] = dev->fd; /* Get the number of cylinders */ rc = clientRequest (dev, cyls, 4, SHRD_QUERY, SHRD_CKDCYLS, NULL, NULL); if (rc < 0) goto init_retry; else if (rc != 4) { logmsg (_("HHCSH003S %4.4X Error retrieving cylinders\n"), dev->devnum); return -1; } dev->ckdcyls = fetch_fw (cyls); /* Get the device characteristics */ rc = clientRequest (dev, dev->devchar, sizeof(dev->devchar), SHRD_QUERY, SHRD_DEVCHAR, NULL, NULL); if (rc < 0) goto init_retry; else if (rc == 0 || rc > (int)sizeof(dev->devchar)) { logmsg (_("HHCSH004S %4.4X Error retrieving device" " characteristics\n"), dev->devnum); return -1; } dev->numdevchar = rc; /* Get number of heads from devchar */ dev->ckdheads = fetch_hw (dev->devchar + 14); /* Calculate number of tracks */ dev->ckdtrks = dev->ckdcyls * dev->ckdheads; dev->ckdhitrk[0] = dev->ckdtrks; /* Check the device type */ if (dev->devtype == 0) dev->devtype = fetch_hw (dev->devchar + 3); else if (dev->devtype != fetch_hw (dev->devchar + 3)) { logmsg (_("HHCSH005S %4.4X Remote device %4.4X is a %4.4X\n"), dev->devnum, dev->rmtnum, fetch_hw (dev->devchar + 3)); return -1; } /* Get the device id */ rc = clientRequest (dev, dev->devid, sizeof(dev->devid), SHRD_QUERY, SHRD_DEVID, NULL, NULL); if (rc < 0) goto init_retry; else if (rc == 0 || rc > (int)sizeof(dev->devid)) { logmsg (_("HHCSH006S %4.4X Error retrieving device id\n"), dev->devnum); return -1; } dev->numdevid = rc; /* Indicate no active track */ dev->cache = dev->bufcur = -1; dev->buf = NULL; /* Set number of sense bytes */ dev->numsense = 32; /* Locate the CKD dasd table entry */ dev->ckdtab = dasd_lookup (DASD_CKDDEV, NULL, dev->devtype, dev->ckdcyls); if (dev->ckdtab == NULL) { logmsg (_("HHCSH007S %4.4X device type %4.4X not found in dasd table\n"), dev->devnum, dev->devtype); return -1; } /* Set the track size */ dev->ckdtrksz = (dev->ckdtab->r1 + 511) & ~511; /* Locate the CKD control unit dasd table entry */ dev->ckdcu = dasd_lookup (DASD_CKDCU, cu ? cu : dev->ckdtab->cu, 0, 0); if (dev->ckdcu == NULL) { logmsg (_("HHCSH008S %4.4X control unit %s not found in dasd table\n"), dev->devnum, cu ? cu : dev->ckdtab->cu); return -1; } /* Set flag bit if 3990 controller */ if (dev->ckdcu->devt == 0x3990) dev->ckd3990 = 1; /* Clear the DPA */ memset(dev->pgid, 0, sizeof(dev->pgid)); /* Request the channel to merge data chained write CCWs into a single buffer before passing data to the device handler */ dev->cdwmerge = 1; /* Purge the cache */ clientPurge (dev, 0, NULL); /* Log the device geometry */ if (!dev->batch) logmsg (_("HHCSH009I %s cyls=%d heads=%d tracks=%d trklen=%d\n"), dev->filename, dev->ckdcyls, dev->ckdheads, dev->ckdtrks, dev->ckdtrksz); dev->connecting = 0; return 0; } /* shared_ckd_init */ /*------------------------------------------------------------------- * CKD close exit (client side) *-------------------------------------------------------------------*/ static int shared_ckd_close ( DEVBLK *dev ) { /* Purge the cached entries */ clientPurge (dev, 0, NULL); /* Disconnect and close */ if (dev->fd >= 0) { clientRequest (dev, NULL, 0, SHRD_DISCONNECT, 0, NULL, NULL); close_socket (dev->fd); dev->fd = -1; } return 0; } /* shared_ckd_close */ /*------------------------------------------------------------------- * FBA init exit (client side) *-------------------------------------------------------------------*/ int shared_fba_init (DEVBLK *dev, int argc, char *argv[] ) { int rc; /* Return code */ int i; /* Loop index */ int retry; /* 1=Connection being retried*/ char *ipname; /* Remote name or address */ char *port = NULL; /* Remote port */ char *rmtnum = NULL; /* Remote device number */ struct hostent *he; /* -> hostent structure */ char *kw; /* Argument keyword */ char *op; /* Argument operand */ char c; /* Work for sscanf */ FWORD origin; /* FBA origin */ FWORD numblks; /* FBA number blocks */ FWORD blksiz; /* FBA block size */ char *p, buf[1024]; /* Work buffer */ retry = dev->connecting; /* Process the arguments */ if (!retry) { kw = op = NULL; if (argc < 1 || strlen(argv[0]) >= sizeof(buf)) return -1; strcpy (buf, argv[0]); /* First argument is `ipname:port:devnum' */ ipname = buf; p = strchr (buf, ':'); if (p) { *p = '\0'; port = p + 1; p = strchr (port, ':'); } if (p) { *p = '\0'; rmtnum = p + 1; } if ( (he = gethostbyname (ipname)) == NULL ) return -1; memcpy(&dev->rmtaddr, he->h_addr_list[0], sizeof(dev->rmtaddr)); if (port) { if (sscanf(port, "%hu%c", &dev->rmtport, &c) != 1) return -1; } else dev->rmtport = SHARED_DEFAULT_PORT; if (rmtnum) { if (strlen (rmtnum) > 4 || sscanf (rmtnum, "%hx%c", &dev->rmtnum, &c) != 0) return -1; } else dev->rmtnum = dev->devnum; /* Process the remaining arguments */ for (i = 1; i < argc; i++) { #ifdef HAVE_LIBZ if (strlen (argv[i]) > 5 && memcmp("comp=", argv[i], 5) == 0) { kw = strtok (argv[i], "="); op = strtok (NULL, " \t"); dev->rmtcomp = atoi (op); if (dev->rmtcomp < 0 || dev->rmtcomp > 9) dev->rmtcomp = 0; continue; } #endif logmsg (_("HHCSH010S parameter %d is invalid: %s\n"), i + 1, argv[i]); return -1; } } /* Set suported compression */ dev->rmtcomps = 0; #ifdef HAVE_LIBZ dev->rmtcomps |= SHRD_LIBZ; #endif #ifdef CCKD_BZIP2 dev->rmtcomps |= SHRD_BZIP2; #endif /* Update the device handler vector */ dev->hnd = &shared_fba_device_hndinfo; dev->connecting = 1; init_retry: do { rc = clientConnect (dev, retry); if (rc < 0) { logmsg (_("HHCSH011I %4.4X connect pending to %s\n"), dev->devnum, dev->filename); if (retry) SLEEP(5); } } while (retry && rc < 0); /* Return if unable to connect */ if (rc < 0) return 0; /* Get the fba origin */ rc = clientRequest (dev, origin, 4, SHRD_QUERY, SHRD_FBAORIGIN, NULL, NULL); if (rc < 0) goto init_retry; else if (rc != 4) { logmsg (_("HHCSH012S %4.4X Error retrieving fba origin\n"), dev->devnum); return -1; } dev->fbaorigin = fetch_fw (origin); /* Get the number of blocks */ rc = clientRequest (dev, numblks, 4, SHRD_QUERY, SHRD_FBANUMBLK, NULL, NULL); if (rc < 0) goto init_retry; else if (rc != 4) { logmsg (_("HHCSH013S %4.4X Error retrieving fba number blocks\n"), dev->devnum); return -1; } dev->fbanumblk = fetch_fw (numblks); /* Get the block size */ rc = clientRequest (dev, blksiz, 4, SHRD_QUERY, SHRD_FBABLKSIZ, NULL, NULL); if (rc < 0) goto init_retry; else if (rc != 4) { logmsg (_("HHCSH014S %4.4X Error retrieving fba block size\n"), dev->devnum); return -1; } dev->fbablksiz = fetch_fw (blksiz); dev->fbaend = (dev->fbaorigin + dev->fbanumblk) * dev->fbablksiz; /* Get the device id */ rc = clientRequest (dev, dev->devid, sizeof(dev->devid), SHRD_QUERY, SHRD_DEVID, NULL, NULL); if (rc < 0) goto init_retry; else if (rc == 0 || rc > (int)sizeof(dev->devid)) { logmsg (_("HHCSH015S %4.4X Error retrieving device id\n"), dev->devnum); return -1; } dev->numdevid = rc; /* Check the device type */ if (dev->devtype != fetch_hw (dev->devid + 4)) { logmsg (_("HHCSH016S %4.4X Remote device %4.4X is a %4.4X\n"), dev->devnum, dev->rmtnum, fetch_hw (dev->devid + 4)); return -1; } /* Get the device characteristics */ rc = clientRequest (dev, dev->devchar, sizeof(dev->devchar), SHRD_QUERY, SHRD_DEVCHAR, NULL, NULL); if (rc < 0) goto init_retry; else if (rc == 0 || rc > (int)sizeof(dev->devchar)) { logmsg (_("HHCSH017S %4.4X Error retrieving device" " characteristics\n"), dev->devnum); return -1; } dev->numdevchar = rc; /* Indicate no active track */ dev->cache = dev->bufcur = -1; dev->buf = NULL; /* Set number of sense bytes */ dev->numsense = 32; /* Locate the FBA dasd table entry */ dev->fbatab = dasd_lookup (DASD_FBADEV, NULL, dev->devtype, dev->fbanumblk); if (dev->fbatab == NULL) { logmsg (_("HHCSH018S %4.4X device type %4.4X not found in dasd table\n"), dev->devnum, dev->devtype); return -1; } /* Purge the cache */ clientPurge (dev, 0, NULL); /* Log the device geometry */ logmsg (_("HHCSH019I %s origin=%d blks=%d\n"), dev->filename, dev->fbaorigin, dev->fbanumblk); dev->connecting = 0; return 0; } /*------------------------------------------------------------------- * FBA close exit (client side) *-------------------------------------------------------------------*/ static int shared_fba_close (DEVBLK *dev) { /* Purge the cached entries */ clientPurge (dev, 0, NULL); /* Disconnect and close */ if (dev->fd >= 0) { clientRequest (dev, NULL, 0, SHRD_DISCONNECT, 0, NULL, NULL); close_socket (dev->fd); dev->fd = -1; } return 0; } /*------------------------------------------------------------------- * Start I/O exit (client side) *-------------------------------------------------------------------*/ static void shared_start(DEVBLK *dev) { int rc; /* Return code */ U16 devnum; /* Cache device number */ int trk; /* Cache track number */ int code; /* Response code */ BYTE buf[SHARED_PURGE_MAX * 4]; /* Purge list */ shrdtrc(dev,"start cur %d cache %d\n",dev->bufcur,dev->cache); /* Send the START request */ rc = clientRequest (dev, buf, sizeof(buf), SHRD_START, 0, &code, NULL); if (rc < 0) { logmsg(_("HHCSH020E %4.4X error during channel program start\n"), dev->devnum); clientPurge (dev, 0, NULL); dev->cache = dev->bufcur = -1; dev->buf = NULL; return; } /* Check for purge */ if (code & SHRD_PURGE) { if (rc / 4 > SHARED_PURGE_MAX) rc = 0; clientPurge (dev, rc / 4, buf); } /* Make previous active entry active again */ if (dev->cache >= 0) { cache_lock (CACHE_DEVBUF); SHRD_CACHE_GETKEY (dev->cache, devnum, trk); if (dev->devnum == devnum && dev->bufcur == trk) cache_setflag(CACHE_DEVBUF, dev->cache, ~0, SHRD_CACHE_ACTIVE); else { dev->cache = dev->bufcur = -1; dev->buf = NULL; } cache_unlock (CACHE_DEVBUF); } } /* shared_start */ /*------------------------------------------------------------------- * End I/O exit (client side) *-------------------------------------------------------------------*/ static void shared_end (DEVBLK *dev) { int rc; /* Return code */ shrdtrc(dev,"end cur %d cache %d\n",dev->bufcur,dev->cache); /* Write the previous active entry if it was updated */ if (dev->bufupd) clientWrite (dev, dev->bufcur); dev->bufupd = 0; /* Mark the active entry inactive */ if (dev->cache >= 0) { cache_lock (CACHE_DEVBUF); cache_setflag (CACHE_DEVBUF, dev->cache, ~SHRD_CACHE_ACTIVE, 0); cache_unlock (CACHE_DEVBUF); } /* Send the END request */ rc = clientRequest (dev, NULL, 0, SHRD_END, 0, NULL, NULL); if (rc < 0) { logmsg(_("HHCSH021E %4.4X error during channel program end\n"), dev->devnum); clientPurge (dev, 0, NULL); dev->cache = dev->bufcur = -1; dev->buf = NULL; return; } } /* shared_end */ /*------------------------------------------------------------------- * Shared ckd read track exit (client side) *-------------------------------------------------------------------*/ static int shared_ckd_read (DEVBLK *dev, int trk, BYTE *unitstat) { int rc; /* Return code */ int retries = 10; /* Number read retries */ int cache; /* Lookup index */ int lru; /* Available index */ int len; /* Response length */ int id; /* Response id */ BYTE *buf; /* Cache buffer */ BYTE code; /* Response code */ U16 devnum; /* Response device number */ BYTE hdr[SHRD_HDR_SIZE + 4]; /* Read request header */ /* Initialize the unit status */ *unitstat = 0; /* Return if reading the same track image */ if (trk == dev->bufcur && dev->cache >= 0) { dev->bufoff = 0; dev->bufoffhi = dev->ckdtrksz; return 0; } shrdtrc(dev,"ckd_read trk %d\n",trk); /* Write the previous active entry if it was updated */ if (dev->bufupd) clientWrite (dev, dev->bufcur); dev->bufupd = 0; /* Reset buffer offsets */ dev->bufoff = 0; dev->bufoffhi = dev->ckdtrksz; cache_lock (CACHE_DEVBUF); /* Inactivate the previous image */ if (dev->cache >= 0) cache_setflag (CACHE_DEVBUF, dev->cache, ~SHRD_CACHE_ACTIVE, 0); dev->cache = dev->bufcur = -1; cache_retry: /* Lookup the track in the cache */ cache = cache_lookup (CACHE_DEVBUF, SHRD_CACHE_SETKEY(dev->devnum, trk), &lru); /* Process cache hit */ if (cache >= 0) { cache_setflag (CACHE_DEVBUF, cache, ~0, SHRD_CACHE_ACTIVE); cache_unlock (CACHE_DEVBUF); dev->cachehits++; dev->cache = cache; dev->buf = cache_getbuf (CACHE_DEVBUF, cache, 0); dev->bufcur = trk; dev->bufoff = 0; dev->bufoffhi = dev->ckdtrksz; dev->buflen = shared_ckd_trklen (dev, dev->buf); dev->bufsize = cache_getlen (CACHE_DEVBUF, cache); shrdtrc(dev,"ckd_read trk %d cache hit %d\n",trk,dev->cache); return 0; } /* Special processing if no available cache entry */ if (lru < 0) { shrdtrc(dev,"ckd_read trk %d cache wait\n",trk); dev->cachewaits++; cache_wait (CACHE_DEVBUF); goto cache_retry; } /* Process cache miss */ shrdtrc(dev,"ckd_read trk %d cache miss %d\n",trk,dev->cache); dev->cachemisses++; cache_setflag (CACHE_DEVBUF, lru, 0, SHRD_CACHE_ACTIVE|DEVBUF_TYPE_SCKD); cache_setkey (CACHE_DEVBUF, lru, SHRD_CACHE_SETKEY(dev->devnum, trk)); cache_setage (CACHE_DEVBUF, lru); buf = cache_getbuf (CACHE_DEVBUF, lru, dev->ckdtrksz); cache_unlock (CACHE_DEVBUF); read_retry: /* Send the read request for the track to the remote host */ SHRD_SET_HDR (hdr, SHRD_READ, 0, dev->rmtnum, dev->rmtid, 4); store_fw (hdr + SHRD_HDR_SIZE, trk); rc = clientSend (dev, hdr, NULL, 0); if (rc < 0) { ckd_build_sense (dev, SENSE_EC, 0, 0, FORMAT_1, MESSAGE_0); *unitstat = CSW_CE | CSW_DE | CSW_UC; logmsg(_("HHCSH022E %4.4X error reading track %d\n"), dev->devnum, trk); return -1; } /* Read the track from the remote host */ rc = clientRecv (dev, hdr, buf, dev->ckdtrksz); SHRD_GET_HDR (hdr, code, *unitstat, devnum, id, len); if (rc < 0 || code & SHRD_ERROR) { if (rc < 0 && retries--) goto read_retry; ckd_build_sense (dev, SENSE_EC, 0, 0, FORMAT_1, MESSAGE_0); *unitstat = CSW_CE | CSW_DE | CSW_UC; logmsg(_("HHCSH023E %4.4X error reading track %d\n"), dev->devnum, trk); return -1; } /* Read the sense data if an i/o error occurred */ if (code & SHRD_IOERR) clientRequest (dev, dev->sense, dev->numsense, SHRD_SENSE, 0, NULL, NULL); /* Read complete */ dev->cache = lru; dev->buf = cache_getbuf (CACHE_DEVBUF, lru, 0); dev->bufcur = trk; dev->bufoff = 0; dev->bufoffhi = dev->ckdtrksz; dev->buflen = shared_ckd_trklen (dev, dev->buf); dev->bufsize = cache_getlen (CACHE_DEVBUF, lru); dev->buf[0] = 0; return 0; } /* shared_ckd_read */ /*------------------------------------------------------------------- * Shared ckd write track exit (client side) *-------------------------------------------------------------------*/ static int shared_ckd_write (DEVBLK *dev, int trk, int off, BYTE *buf, int len, BYTE *unitstat) { int rc; /* Return code */ /* Immediately return if fake writing */ if (dev->ckdfakewr) return len; /* Error if opened read-only */ if (dev->ckdrdonly) { ckd_build_sense (dev, SENSE_EC, SENSE1_WRI, 0, FORMAT_1, MESSAGE_0); *unitstat = CSW_CE | CSW_DE | CSW_UC; return -1; } shrdtrc(dev,"ckd_write trk %d off %d len %d\n",trk,off,len); /* If the track is not current then read it */ if (trk != dev->bufcur) { rc = (dev->hnd->read) (dev, trk, unitstat); if (rc < 0) { dev->bufcur = dev->cache = -1; return -1; } } /* Invalid track format if going past buffer end */ if (off + len > dev->bufoffhi) { ckd_build_sense (dev, 0, SENSE1_ITF, 0, 0, 0); *unitstat = CSW_CE | CSW_DE | CSW_UC; return -1; } /* Copy the data into the buffer */ if (buf) memcpy (dev->buf + off, buf, len); /* Set low and high updated offsets */ if (!dev->bufupd || off < dev->bufupdlo) dev->bufupdlo = off; if (dev->bufoff + len > dev->bufupdhi) dev->bufupdhi = off + len; /* Indicate track image has been modified */ if (!dev->bufupd) { dev->bufupd = 1; shared_update_notify (dev, trk); } return len; } /* shared_ckd_write */ /*------------------------------------------------------------------- * Return track image length *-------------------------------------------------------------------*/ static int shared_ckd_trklen (DEVBLK *dev, BYTE *buf) { int sz; /* Size so far */ for (sz = CKDDASD_TRKHDR_SIZE; memcmp (buf + sz, &eighthexFF, 8) != 0; ) { /* add length of count, key, and data fields */ sz += CKDDASD_RECHDR_SIZE + buf[sz+5] + (buf[sz+6] << 8) + buf[sz+7]; if (sz > dev->ckdtrksz - 8) break; } /* add length for end-of-track indicator */ sz += CKDDASD_RECHDR_SIZE; if (sz > dev->ckdtrksz) sz = dev->ckdtrksz; return sz; } #if defined(FBA_SHARED) /*------------------------------------------------------------------- * Shared fba read block exit (client side) *-------------------------------------------------------------------*/ static int shared_fba_read (DEVBLK *dev, int blkgrp, BYTE *unitstat) { int rc; /* Return code */ int retries = 10; /* Number read retries */ int i, o; /* Cache indexes */ BYTE code; /* Response code */ U16 devnum; /* Response device number */ int len; /* Response length */ int id; /* Response id */ BYTE hdr[SHRD_HDR_SIZE + 4]; /* Read request header */ /* Return if reading the same block group */ if (blkgrp >= 0 && blkgrp == dev->bufcur) return 0; shrdtrc(dev,"fba_read blkrp %d\n",blkgrp); /* Write the previous active entry if it was updated */ if (dev->bufupd) clientWrite (dev, dev->bufcur); dev->bufupd = 0; /* Reset buffer offsets */ dev->bufoff = 0; dev->bufoffhi = FBA_BLKGRP_SIZE; cache_lock (CACHE_DEVBUF); /* Make the previous cache entry inactive */ if (dev->cache >= 0) cache_setflag(CACHE_DEVBUF, dev->cache, ~FBA_CACHE_ACTIVE, 0); dev->bufcur = dev->cache = -1; cache_retry: /* Search the cache */ i = cache_lookup (CACHE_DEVBUF, FBA_CACHE_SETKEY(dev->devnum, blkgrp), &o); /* Cache hit */ if (i >= 0) { cache_setflag(CACHE_DEVBUF, dev->cache, ~0, FBA_CACHE_ACTIVE); cache_setage(CACHE_DEVBUF, dev->cache); cache_unlock(CACHE_DEVBUF); dev->cachehits++; dev->cache = i; dev->buf = cache_getbuf(CACHE_DEVBUF, dev->cache, 0); dev->bufcur = blkgrp; dev->bufoff = 0; dev->bufoffhi = shared_fba_blkgrp_len (dev, blkgrp); dev->buflen = shared_fba_blkgrp_len (dev, blkgrp); dev->bufsize = cache_getlen(CACHE_DEVBUF, dev->cache); shrdtrc(dev,"fba_read blkgrp %d cache hit %d\n",blkgrp,dev->cache); return 0; } /* Wait if no available cache entry */ if (o < 0) { shrdtrc(dev,"fba_read blkgrp %d cache wait\n",blkgrp); dev->cachewaits++; cache_wait(CACHE_DEVBUF); goto cache_retry; } /* Cache miss */ shrdtrc(dev,"fba_read blkgrp %d cache miss %d\n",blkgrp,dev->cache); dev->cachemisses++; cache_setflag(CACHE_DEVBUF, o, 0, FBA_CACHE_ACTIVE|DEVBUF_TYPE_SFBA); cache_setkey (CACHE_DEVBUF, o, FBA_CACHE_SETKEY(dev->devnum, blkgrp)); cache_setage (CACHE_DEVBUF, o); dev->buf = cache_getbuf(CACHE_DEVBUF, o, FBA_BLKGRP_SIZE); cache_unlock (CACHE_DEVBUF); read_retry: /* Send the read request for the blkgrp to the remote host */ SHRD_SET_HDR (hdr, SHRD_READ, 0, dev->rmtnum, dev->rmtid, 4); store_fw (hdr + SHRD_HDR_SIZE, blkgrp); rc = clientSend (dev, hdr, NULL, 0); if (rc < 0) { dev->sense[0] = SENSE_EC; *unitstat = CSW_CE | CSW_DE | CSW_UC; logmsg(_("HHCSH024E %4.4X error reading block group %d\n"), dev->devnum, blkgrp); return -1; } /* Read the blkgrp from the remote host */ rc = clientRecv (dev, hdr, dev->buf, FBA_BLKGRP_SIZE); SHRD_GET_HDR (hdr, code, *unitstat, devnum, id, len); if (rc < 0 || code & SHRD_ERROR) { if (rc < 0 && retries--) goto read_retry; dev->sense[0] = SENSE_EC; *unitstat = CSW_CE | CSW_DE | CSW_UC; logmsg(_("HHCSH025E %4.4X error reading block group %d\n"), dev->devnum, blkgrp); return -1; } /* Read the sense data if an i/o error occurred */ if (code & SHRD_IOERR) clientRequest (dev, dev->sense, dev->numsense, SHRD_SENSE, 0, NULL, NULL); dev->cache = o; dev->buf = cache_getbuf(CACHE_DEVBUF, dev->cache, 0); dev->buf[0] = 0; dev->bufcur = blkgrp; dev->bufoff = 0; dev->bufoffhi = shared_fba_blkgrp_len (dev, blkgrp); dev->buflen = shared_fba_blkgrp_len (dev, blkgrp); dev->bufsize = cache_getlen(CACHE_DEVBUF, dev->cache); return 0; } /*------------------------------------------------------------------- * Shared fba write block exit (client side) *-------------------------------------------------------------------*/ static int shared_fba_write (DEVBLK *dev, int blkgrp, int off, BYTE *buf, int len, BYTE *unitstat) { int rc; /* Return code */ /* Read the block group */ if (blkgrp != dev->bufcur) { rc = (dev->hnd->read) (dev, blkgrp, unitstat); if (rc < 0) { dev->bufcur = dev->cache = -1; return -1; } } /* Copy to the device buffer */ if (buf) memcpy (dev->buf + off, buf, len); /* Update high/low offsets */ if (!dev->bufupd || off < dev->bufupdlo) dev->bufupdlo = off; if (off + len > dev-> bufupdhi) dev->bufupdhi = off + len; /* Indicate block group has been modified */ if (!dev->bufupd) { dev->bufupd = 1; shared_update_notify (dev, blkgrp); } return len; } /*-------------------------------------------------------------------*/ /* Calculate length of an FBA block group */ /*-------------------------------------------------------------------*/ static int shared_fba_blkgrp_len (DEVBLK *dev, int blkgrp) { off_t offset; /* Offset of block group */ offset = blkgrp * FBA_BLKGRP_SIZE; if (dev->fbaend - offset < FBA_BLKGRP_SIZE) return (int)(dev->fbaend - offset); else return FBA_BLKGRP_SIZE; } #endif /* FBA_SHARED */ /*------------------------------------------------------------------- * Shared usage exit (client side) *-------------------------------------------------------------------*/ static int shared_used (DEVBLK *dev) { int rc; /* Return code */ FWORD usage; /* Usage buffer */ /* Get usage information */ rc = clientRequest (dev, usage, 4, SHRD_USED, 0, NULL, NULL); if (rc != 4) { logmsg (_("HHCSH026E %4.4X Error retrieving usage information\n"), dev->devnum); return -1; } return fetch_fw (usage); } /* shared_used */ /*------------------------------------------------------------------- * Shared reserve exit (client side) *-------------------------------------------------------------------*/ static void shared_reserve (DEVBLK *dev) { int rc; /* Return code */ /* Issue reserve request */ rc = clientRequest (dev, NULL, 0, SHRD_RESERVE, 0, NULL, NULL); } /* shared_reserve */ /*------------------------------------------------------------------- * Shared release exit (client side) *-------------------------------------------------------------------*/ static void shared_release (DEVBLK *dev) { int rc; /* Return code */ /* Issue release request */ rc = clientRequest (dev, NULL, 0, SHRD_RELEASE, 0, NULL, NULL); } /* shared_release */ /*------------------------------------------------------------------- * Write to host * * NOTE - writes are deferred until a switch occurs or the * channel program ends. We are called from either the * read exit or the end channel program exit. *-------------------------------------------------------------------*/ static int clientWrite (DEVBLK *dev, int block) { int rc; /* Return code */ int retries = 10; /* Number write retries */ int len; /* Data length */ BYTE hdr[SHRD_HDR_SIZE + 2 + 4]; /* Write header */ BYTE code; /* Response code */ int status; /* Response status */ int id; /* Response identifier */ U16 devnum; /* Response device number */ BYTE errmsg[SHARED_MAX_MSGLEN+1];/* Error message */ /* Calculate length to write */ len = dev->bufupdhi - dev->bufupdlo; if (len <= 0 || dev->bufcur < 0) { dev->bufupdlo = dev->bufupdhi = 0; return 0; } shrdtrc(dev,"write rcd %d off %d len %d\n",block,dev->bufupdlo,len); write_retry: /* The write request contains a 2 byte offset and 4 byte id, followed by the data */ SHRD_SET_HDR (hdr, SHRD_WRITE, 0, dev->rmtnum, dev->rmtid, len + 6); store_hw (hdr + SHRD_HDR_SIZE, dev->bufupdlo); store_fw (hdr + SHRD_HDR_SIZE + 2, block); rc = clientSend (dev, hdr, dev->buf + dev->bufupdlo, len); if (rc < 0) { logmsg(_("HHCSH027E %4.4X error writing track %d\n"), dev->devnum, dev->bufcur); dev->bufupdlo = dev->bufupdhi = 0; clientPurge (dev, 0, NULL); return -1; } /* Get the response */ rc = clientRecv (dev, hdr, errmsg, sizeof(errmsg)); SHRD_GET_HDR (hdr, code, status, devnum, id, len); if (rc < 0 || (code & SHRD_ERROR) || (code & SHRD_IOERR)) { if (rc < 0 && retries--) goto write_retry; logmsg(_("HHCSH028E %4.4X remote error writing track %d: " "%2.2X-%2.2X\n"), dev->devnum, dev->bufcur, code, status); dev->bufupdlo = dev->bufupdhi = 0; clientPurge (dev, 0, NULL); return -1; } dev->bufupdlo = dev->bufupdhi = 0; return rc; } /* clientWrite */ /*------------------------------------------------------------------- * Purge cache entries (client side) *-------------------------------------------------------------------*/ static void clientPurge (DEVBLK *dev, int n, void *buf) { cache_lock(CACHE_DEVBUF); dev->rmtpurgen = n; dev->rmtpurge = (FWORD *)buf; cache_scan (CACHE_DEVBUF, clientPurgescan, dev); cache_unlock(CACHE_DEVBUF); } static int clientPurgescan (int *answer, int ix, int i, void *data) { U16 devnum; /* Cached device number */ int trk; /* Cached track */ int p; /* Purge index */ DEVBLK *dev = data; /* -> device block */ UNREFERENCED(answer); SHRD_CACHE_GETKEY(i, devnum, trk); if (devnum == dev->devnum) { if (dev->rmtpurgen == 0) { cache_release (ix, i, 0); shrdtrc(dev,"purge %d\n",trk); } else { for (p = 0; p < dev->rmtpurgen; p++) { if (trk == (int)fetch_fw (dev->rmtpurge[p])) { shrdtrc(dev,"purge %d\n",trk); cache_release (ix, i, 0); break; } } } } return 0; } /* clientPurge */ /*------------------------------------------------------------------- * Connect to the server (client side) *-------------------------------------------------------------------*/ static int clientConnect (DEVBLK *dev, int retry) { int rc; /* Return code */ struct sockaddr *server; /* -> server descriptor */ int flag; /* Flags (version | release) */ int len; /* Length server descriptor */ struct sockaddr_in iserver; /* inet server descriptor */ #if defined( HAVE_SYS_UN_H ) struct sockaddr_un userver; /* unix server descriptor */ #endif int retries = 10; /* Number of retries */ HWORD id; /* Returned identifier */ HWORD comp; /* Returned compression parm */ do { /* Close previous connection */ if (dev->fd >= 0) close_socket (dev->fd); /* Get a socket */ if (dev->localhost) { #if defined( HAVE_SYS_UN_H ) dev->fd = dev->ckdfd[0] = socket (AF_UNIX, SOCK_STREAM, 0); #else // !defined( HAVE_SYS_UN_H ) dev->fd = dev->ckdfd[0] = -1; #endif // defined( HAVE_SYS_UN_H ) if (dev->fd < 0) { logmsg (_("HHCSH029E %4.4X socket failed: %s\n"), dev->devnum, strerror(HSO_errno)); return -1; } #if defined( HAVE_SYS_UN_H ) userver.sun_family = AF_UNIX; sprintf(userver.sun_path, "/tmp/hercules_shared.%d", dev->rmtport); server = (struct sockaddr *)&userver; len = sizeof(userver); #endif // !defined( HAVE_SYS_UN_H ) } else { dev->fd = dev->ckdfd[0] = socket (AF_INET, SOCK_STREAM, 0); if (dev->fd < 0) { logmsg (_("HHCSH030E %4.4X socket failed: %s\n"), dev->devnum, strerror(HSO_errno)); return -1; } iserver.sin_family = AF_INET; iserver.sin_port = htons(dev->rmtport); memcpy(&iserver.sin_addr.s_addr,&dev->rmtaddr,sizeof(struct in_addr)); server = (struct sockaddr *)&iserver; len = sizeof(iserver); } /* Connect to the server */ store_hw (id, dev->rmtid); rc = connect (dev->fd, server, len); shrdtrc(dev,"connect rc=%d errno=%d\n",rc, HSO_errno); if (rc >= 0) { if (!dev->batch) logmsg(_("HHCSH031I %4.4X Connected to %s\n"), dev->devnum, dev->filename); /* Request device connection */ flag = (SHARED_VERSION << 4) | SHARED_RELEASE; rc = clientRequest (dev, id, 2, SHRD_CONNECT, flag, NULL, &flag); if (rc >= 0) { dev->rmtid = fetch_hw (id); dev->rmtrel = flag & 0x0f; } /* * Negotiate compression - top 4 bits have the compression * algorithms we support (00010000 -> libz; 00100000 ->bzip2, * 00110000 -> both) and the bottom 4 bits indicates the * libz parm we want to use when sending data back & forth. * If the server returns `0' back, then we won't use libz to * compress data to the server. What the `compression * algorithms we support' means is that if the data source is * cckd or cfba then the server doesn't have to uncompress * the data for us if we support the compression algorithm. */ if (rc >= 0 && (dev->rmtcomp || dev->rmtcomps)) { rc = clientRequest (dev, comp, 2, SHRD_COMPRESS, (dev->rmtcomps << 4) | dev->rmtcomp, NULL, NULL); if (rc >= 0) dev->rmtcomp = fetch_hw (comp); } } else if (!retry) logmsg(_("HHCSH032E %4.4X Connect %s %d: %s\n"), dev->devnum, dev->filename, HSO_errno, strerror(HSO_errno)); if (rc < 0 && retry) usleep (20000); } while (retry && retries-- && rc < 0); return rc; } /* clientConnect */ /*------------------------------------------------------------------- * Send request to host and get the response * * No data is sent on the request, buf gets the response. * If an uncorrectable connection error occurs -1 is returned. * Otherwise *code and *status is set from the response header * * Since `buf' may be NULL or not very long, response data is * received in a temporary buffer. This enables us to receive * an error message from the remote system. *-------------------------------------------------------------------*/ static int clientRequest (DEVBLK *dev, BYTE *buf, int len, int cmd, int flags, int *code, int *status) { int rc; /* Return code */ int retries = 10; /* Number retries */ BYTE rcode; /* Request return code */ BYTE rstatus; /* Request return status */ U16 rdevnum; /* Request return devnum */ int rid; /* Request return id */ int rlen; /* Request return length */ BYTE hdr[SHRD_HDR_SIZE]; /* Header */ BYTE temp[256]; /* Temporary buffer */ retry : /* Send the request */ SHRD_SET_HDR(hdr, cmd, flags, dev->rmtnum, dev->rmtid, 0); shrdtrc(dev,"client_request %2.2x %2.2x %2.2x %d\n", cmd,flags,dev->rmtnum,dev->rmtid); rc = clientSend (dev, hdr, NULL, 0); if (rc < 0) return rc; /* Receive the response */ rc = clientRecv (dev, hdr, temp, sizeof(temp)); /* Retry recv errors */ if (rc < 0) { if (cmd != SHRD_CONNECT && retries--) { SLEEP (1); clientConnect (dev, 1); goto retry; } return -1; } /* Set code and status */ SHRD_GET_HDR(hdr, rcode, rstatus, rdevnum, rid, rlen); shrdtrc(dev,"client_response %2.2x %2.2x %2.2x %d %d\n", rcode,rstatus,rdevnum,rid,rlen); if (code) *code = rcode; if (status) *status = rstatus; /* Copy the data into the caller's buffer */ if (buf && len > 0 && rlen > 0) memcpy (buf, temp, len < rlen ? len : rlen); return rlen; } /* clientRequest */ /*------------------------------------------------------------------- * Send a request to the host * * `buf' may be NULL * `buflen' is the length in `buf' (should be 0 if `buf' is NULL) * `hdr' may contain additional data; this is detected by the * difference between `buflen' and the length in the header * * If `buf' is adjacent to `hdr' then `buf' should be NULL * *-------------------------------------------------------------------*/ static int clientSend (DEVBLK *dev, BYTE *hdr, BYTE *buf, int buflen) { int rc; /* Return code */ BYTE cmd; /* Header command */ BYTE flag; /* Header flags */ U16 devnum; /* Header device nu */ int len; /* Header length */ int id; /* Header identifier */ int hdrlen; /* Header length + other data*/ int off; /* Offset to buffer data */ BYTE *sendbuf; /* Send buffer */ int sendlen; /* Send length */ BYTE cbuf[SHRD_HDR_SIZE + 65536]; /* Combined buffer */ /* Make buf, buflen consistent if no additional data to be sent */ if (buf == NULL) buflen = 0; else if (buflen == 0) buf = NULL; /* Calculate length of header, may contain additional data */ SHRD_GET_HDR(hdr, cmd, flag, devnum, id, len); shrdtrc(dev,"client_send %2.2x %2.2x %2.2x %d %d\n", cmd,flag,devnum,id,len); hdrlen = SHRD_HDR_SIZE + (len - buflen); off = len - buflen; if (dev->fd < 0) { rc = clientConnect (dev, 1); if (rc < 0) return -1; } #ifdef HAVE_LIBZ /* Compress the buf */ if (dev->rmtcomp != 0 && flag == 0 && off <= SHRD_COMP_MAX_OFF && buflen >= SHARED_COMPRESS_MINLEN) { unsigned long newlen; newlen = 65536 - hdrlen; memcpy (cbuf, hdr, hdrlen); rc = compress2 (cbuf + hdrlen, &newlen, buf, buflen, dev->rmtcomp); if (rc == Z_OK && (int)newlen < buflen) { cmd |= SHRD_COMP; flag = (SHRD_LIBZ << 4) | off; hdr = cbuf; hdrlen += newlen; buf = NULL; buflen = 0; } } #endif /* Combine header and data unless there's no buffer */ if (buflen == 0) { sendbuf = hdr; sendlen = hdrlen; } else { memcpy (cbuf, hdr, hdrlen); memcpy (cbuf + hdrlen, buf, buflen); sendbuf = cbuf; sendlen = hdrlen + buflen; } SHRD_SET_HDR(sendbuf, cmd, flag, devnum, id, (U16)(sendlen - SHRD_HDR_SIZE)); if (cmd & SHRD_COMP) shrdtrc(dev,"client_send %2.2x %2.2x %2.2x %d %d (compressed)\n", cmd, flag, devnum, id, (int)(sendlen - SHRD_HDR_SIZE)); retry: /* Send the header and data */ rc = send (dev->fd, sendbuf, sendlen, 0); if (rc < 0) { rc = clientConnect (dev, 0); if (rc >= 0) goto retry; } /* Process return code */ if (rc < 0) { logmsg(_("HHCSH033E %4.4X send error %d for %2.2X-%2.2X: %s\n"), dev->devnum, HSO_errno, cmd, flag, strerror(HSO_errno)); return -1; } return rc; } /* clientSend */ /*------------------------------------------------------------------- * Receive a response (client side) *-------------------------------------------------------------------*/ static int clientRecv (DEVBLK *dev, BYTE *hdr, BYTE *buf, int buflen) { int rc; /* Return code */ BYTE code; /* Response code */ BYTE status; /* Response status */ U16 devnum; /* Response device number */ int id; /* Response identifier */ int len; /* Response length */ /* Clear the header to zeroes */ memset (hdr, 0, SHRD_HDR_SIZE); /* Return error if not connected */ if (dev->fd < 0) { logmsg(_("HHCSH034E %4.4X Not connected to %s\n"), dev->devnum, dev->filename); return -1; } /* Receive the header */ rc = recvData (dev->fd, hdr, buf, buflen, 0); if (rc < 0) { if (rc != -ENOTCONN) logmsg(_("HHCSH035E %4.4X recv error %d: %s\n"), dev->devnum, -rc, strerror(-rc)); return rc; } SHRD_GET_HDR(hdr, code, status, devnum, id, len); shrdtrc(dev,"client_recv %2.2x %2.2x %2.2x %d %d\n", code,status,devnum,id,len); /* Handle remote logical error */ if (code & SHRD_ERROR) { logmsg(_("HHCSH036E %4.4X Remote error %2.2X-%2.2X: %s\n"), dev->devnum, code, status, buf); len = 0; } /* Reset code/status if response was compressed */ if (len > 0 && code == SHRD_COMP) { code = SHRD_OK; status = 0; } /* Reset the header */ SHRD_SET_HDR(hdr, code, status, devnum, id, len); return len; } /* clientRecv */ /*------------------------------------------------------------------- * Receive data (server or client) *-------------------------------------------------------------------*/ static int recvData(int sock, BYTE *hdr, BYTE *buf, int buflen, int server) { int rc; /* Return code */ int rlen; /* Data length to recv */ int recvlen; /* Total length */ BYTE *recvbuf; /* Receive buffer */ BYTE cmd; /* Header command */ BYTE flag; /* Header flags */ U16 devnum; /* Header device number */ int id; /* Header identifier */ int len; /* Header length */ int comp = 0; /* Compression type */ int off = 0; /* Offset to compressed data */ DEVBLK *dev = NULL; /* For `shrdtrc' */ BYTE cbuf[65536]; /* Compressed buffer */ /* Receive the header */ for (recvlen = 0; recvlen < (int)SHRD_HDR_SIZE; recvlen += rc) { rc = recv (sock, hdr + recvlen, SHRD_HDR_SIZE - recvlen, 0); if (rc < 0) return -HSO_errno; else if (rc == 0) return -HSO_ENOTCONN; } SHRD_GET_HDR (hdr, cmd, flag, devnum, id, len); shrdtrc(dev,"recvData %2.2x %2.2x %2.2x %d %d\n", cmd, flag, devnum, id, len); /* Return if no data */ if (len == 0) return 0; /* Check for compressed data */ if ((server && (cmd & SHRD_COMP)) || (!server && cmd == SHRD_COMP)) { comp = (flag & SHRD_COMP_MASK) >> 4; off = flag & SHRD_COMP_OFF; cmd &= ~SHRD_COMP; flag = 0; recvbuf = cbuf; rlen = len; } else { recvbuf = buf; rlen = buflen < len ? buflen : len; } /* Receive the data */ for (recvlen = 0; recvlen < rlen; recvlen += rc) { rc = recv (sock, recvbuf + recvlen, len - recvlen, 0); if (rc < 0) return -HSO_errno; else if (rc == 0) return -HSO_ENOTCONN; } /* Flush any remaining data */ for (; rlen < len; rlen += rc) { BYTE buf[256]; rc = recv (sock, buf, len - rlen < 256 ? len - rlen : 256, 0); if (rc < 0) return -HSO_errno; else if (rc == 0) return -HSO_ENOTCONN; } /* Check for compression */ if (comp == SHRD_LIBZ) { #ifdef HAVE_LIBZ unsigned long newlen; if (off > 0) memcpy (buf, cbuf, off); newlen = buflen - off; rc = uncompress(buf + off, &newlen, cbuf + off, len - off); if (rc == Z_OK) recvlen = (int)newlen + off; else { logmsg(_("HHCSH037E uncompress error %d, off %d len %d\n"), rc, off, len - off); recvlen = -1; } #else logmsg(_("HHCSH038E data compressed using libz, unsupported\n")); recvlen = -1; #endif } else if (comp == SHRD_BZIP2) { #ifdef CCKD_BZIP2 unsigned int newlen; if (off > 0) memcpy (buf, cbuf, off); newlen = buflen - off; rc = BZ2_bzBuffToBuffDecompress((void *)(buf + off), &newlen, (void *)(cbuf + off), len - off, 0, 0); if (rc == BZ_OK) recvlen = (int)newlen + off; else { logmsg(_("HHCSH039E decompress error %d, off %d len %d\n"), rc, off, len - off); recvlen = -1; } #else logmsg(_("HHCSH040E data compressed using bzip2, unsupported\n")); recvlen = -1; #endif } if (recvlen > 0) { SHRD_SET_HDR (hdr, cmd, flag, devnum, id, recvlen); if (comp) shrdtrc(dev,"recvData %2.2x %2.2x %2.2x %d %d (uncompressed)\n", cmd, flag, devnum, id, recvlen); } return recvlen; } /* recvData */ /*------------------------------------------------------------------- * Process a request (server side) *-------------------------------------------------------------------*/ static void serverRequest (DEVBLK *dev, int ix, BYTE *hdr, BYTE *buf) { int rc; /* Return code */ int i; /* Loop index */ BYTE cmd; /* Header command */ BYTE flag; /* Header flags */ U16 devnum; /* Header device number */ int id; /* Header identifier */ int len; /* Header length */ int code; /* Response code */ int rcd; /* Record to read/write */ int off; /* Offset into record */ /* Extract header information */ SHRD_GET_HDR (hdr, cmd, flag, devnum, id, len); shrdtrc(dev,"server_request [%d] %2.2x %2.2x %2.2x %d %d\n", ix, cmd, flag, devnum, id, len); dev->shrd[ix]->time = time (NULL); switch (cmd) { case SHRD_CONNECT: if (dev->connecting) { serverError (dev, ix, SHRD_ERROR_NOTINIT, cmd, "device not initialized"); break; } if ((flag >> 4) != SHARED_VERSION) { serverError (dev, ix, SHRD_ERROR_BADVERS, cmd, "shared version mismatch"); break; } dev->shrd[ix]->release = flag & 0x0f; SHRD_SET_HDR (hdr, 0, (SHARED_VERSION << 4) | SHARED_RELEASE, dev->devnum, id, 2); store_hw (buf, id); serverSend (dev, ix, hdr, buf, 2); break; case SHRD_DISCONNECT: SHRD_SET_HDR (hdr, 0, 0, dev->devnum, id, 0); serverSend (dev, ix, hdr, NULL, 0); dev->shrd[ix]->disconnect = 1; obtain_lock (&dev->lock); /* Make the device available if this system active on it */ if (dev->ioactive == id) { if (!dev->suspended) { dev->busy = 0; dev->ioactive = DEV_SYS_NONE; } else dev->ioactive = DEV_SYS_LOCAL; if (dev->iowaiters) signal_condition (&dev->iocond); } release_lock (&dev->lock); break; case SHRD_START: case SHRD_RESUME: obtain_lock (&dev->lock); /* If the device is suspended locally then grab it */ if (dev->ioactive == DEV_SYS_LOCAL && dev->suspended && !dev->reserved) dev->ioactive = id; /* Check if the device is busy */ if (dev->ioactive != id && dev->ioactive != DEV_SYS_NONE) { shrdtrc(dev,"server_request busy id=%d ioactive=%d reserved=%d\n", id,dev->ioactive,dev->reserved); /* If the `nowait' bit is on then respond `busy' */ if (flag & SHRD_NOWAIT) { release_lock (&dev->lock); SHRD_SET_HDR (hdr, SHRD_BUSY, 0, dev->devnum, id, 0); serverSend (dev, ix, hdr, NULL, 0); break; } dev->shrd[ix]->waiting = 1; /* Wait while the device is busy by the local system */ while (dev->ioactive == DEV_SYS_LOCAL && !dev->suspended) { dev->iowaiters++; wait_condition (&dev->iocond, &dev->lock); dev->iowaiters--; } /* Return with the `waiting' bit on if busy by a remote system */ if (dev->ioactive != DEV_SYS_NONE && dev->ioactive != DEV_SYS_LOCAL) { release_lock (&dev->lock); break; } dev->shrd[ix]->waiting = 0; } /* Make this system active on the device */ dev->ioactive = id; dev->busy = 1; dev->syncio_active = dev->syncio_retry = 0; sysblk.shrdcount++; shrdtrc(dev,"server_request active id=%d\n", id); release_lock(&dev->lock); /* Call the i/o start or resume exit */ if (cmd == SHRD_START && dev->hnd->start) (dev->hnd->start) (dev); else if (cmd == SHRD_RESUME && dev->hnd->resume) (dev->hnd->resume) (dev); /* Get the purge list */ if (dev->shrd[ix]->purgen == 0) code = len = 0; else { code = SHRD_PURGE; if (dev->shrd[ix]->purgen < 0) len = 0; else len = 4 * dev->shrd[ix]->purgen; } /* Send the response */ SHRD_SET_HDR (hdr, code, 0, dev->devnum, id, len); rc = serverSend (dev, ix, hdr, (BYTE *)dev->shrd[ix]->purge, len); if (rc >= 0) dev->shrd[ix]->purgen = 0; break; case SHRD_END: case SHRD_SUSPEND: /* Must be active on the device for this command */ if (dev->ioactive != id) { serverError (dev, ix, SHRD_ERROR_NOTACTIVE, cmd, "not active on this device"); break; } /* Call the I/O end/suspend exit */ if (cmd == SHRD_END && dev->hnd->end) (dev->hnd->end) (dev); else if (cmd == SHRD_SUSPEND && dev->hnd->suspend) (dev->hnd->suspend) (dev); obtain_lock (&dev->lock); /* Make the device available if it's not reserved */ if (!dev->reserved) { /* If locally suspended then return the device to local */ if (dev->suspended) { dev->ioactive = DEV_SYS_LOCAL; dev->busy = 1; } else { dev->ioactive = DEV_SYS_NONE; dev->busy = 0; } /* Reset any `waiting' bits */ for (i = 0; i < SHARED_MAX_SYS; i++) if (dev->shrd[i]) dev->shrd[i]->waiting = 0; /* Notify any waiters */ if (dev->iowaiters) signal_condition (&dev->iocond); } shrdtrc(dev,"server_request inactive id=%d\n", id); release_lock (&dev->lock); /* Send response back */ SHRD_SET_HDR (hdr, 0, 0, dev->devnum, id, 0); serverSend (dev, ix, hdr, NULL, 0); break; case SHRD_RESERVE: /* Must be active on the device for this command */ if (dev->ioactive != id) { serverError (dev, ix, SHRD_ERROR_NOTACTIVE, cmd, "not active on this device"); break; } obtain_lock (&dev->lock); dev->reserved = 1; release_lock (&dev->lock); shrdtrc(dev,"server_request reserved id=%d\n", id); /* Call the I/O reserve exit */ if (dev->hnd->reserve) (dev->hnd->reserve) (dev); /* Send response back */ SHRD_SET_HDR (hdr, 0, 0, dev->devnum, id, 0); serverSend (dev, ix, hdr, NULL, 0); break; case SHRD_RELEASE: /* Must be active on the device for this command */ if (dev->ioactive != id) { serverError (dev, ix, SHRD_ERROR_NOTACTIVE, cmd, "not active on this device"); break; } /* Call the I/O release exit */ if (dev->hnd->release) (dev->hnd->release) (dev); obtain_lock (&dev->lock); dev->reserved = 0; release_lock (&dev->lock); shrdtrc(dev,"server_request released id=%d\n", id); /* Send response back */ SHRD_SET_HDR (hdr, 0, 0, dev->devnum, id, 0); serverSend (dev, ix, hdr, NULL, 0); break; case SHRD_READ: /* Must be active on the device for this command */ if (dev->ioactive != id) { serverError (dev, ix, SHRD_ERROR_NOTACTIVE, cmd, "not active on this device"); break; } /* Set the compressions client is willing to accept */ dev->comps = dev->shrd[ix]->comps; dev->comp = dev->compoff = 0; /* Call the I/O read exit */ rcd = (int)fetch_fw (buf); rc = (dev->hnd->read) (dev, rcd, &flag); shrdtrc(dev,"server_request read rcd %d flag %2.2x rc=%d\n", rcd, flag, rc); if (rc < 0) code = SHRD_IOERR; else { code = dev->comp ? SHRD_COMP : 0; flag = (dev->comp << 4) | dev->compoff; } /* Reset compression stuff */ dev->comps = dev->comp = dev->compoff = 0; SHRD_SET_HDR (hdr, code, flag, dev->devnum, id, dev->buflen); serverSend (dev, ix, hdr, dev->buf, dev->buflen); break; case SHRD_WRITE: /* Must be active on the device for this command */ if (dev->ioactive != id) { serverError (dev, ix, SHRD_ERROR_NOTACTIVE, cmd, "not active on this device"); break; } /* Call the I/O write exit */ off = fetch_hw (buf); rcd = fetch_fw (buf + 2); rc = (dev->hnd->write) (dev, rcd, off, buf + 6, len - 6, &flag); shrdtrc(dev,"server_request write rcd %d off %d len %d flag %2.2x rc=%d\n", rcd, off, len - 6, flag, rc); if (rc < 0) code = SHRD_IOERR; else code = 0; /* Send response back */ SHRD_SET_HDR (hdr, code, flag, dev->devnum, id, 0); serverSend (dev, ix, hdr, NULL, 0); break; case SHRD_SENSE: /* Must be active on the device for this command */ if (dev->ioactive != id) { serverError (dev, ix, SHRD_ERROR_NOTACTIVE, cmd, "not active on this device"); break; } /* Send the sense */ SHRD_SET_HDR (hdr, 0, CSW_CE | CSW_DE, dev->devnum, id, dev->numsense); serverSend (dev, ix, hdr, dev->sense, dev->numsense); memset (dev->sense, 0, sizeof(dev->sense)); dev->sns_pending = 0; break; case SHRD_QUERY: switch (flag) { case SHRD_USED: if (dev->hnd->used) rc = (dev->hnd->used) (dev); else rc = 0; store_fw (buf, rc); SHRD_SET_HDR (hdr, 0, 0, dev->devnum, id, 4); serverSend (dev, ix, hdr, buf, 4); break; case SHRD_DEVCHAR: SHRD_SET_HDR (hdr, 0, 0, dev->devnum, id, dev->numdevchar); serverSend (dev, ix, hdr, dev->devchar, dev->numdevchar); break; case SHRD_DEVID: SHRD_SET_HDR (hdr, 0, 0, dev->devnum, id, dev->numdevid); serverSend (dev, ix, hdr, dev->devid, dev->numdevid); break; case SHRD_CKDCYLS: store_fw (buf, dev->ckdcyls); SHRD_SET_HDR (hdr, 0, 0, dev->devnum, id, 4); serverSend (dev, ix, hdr, buf, 4); break; case SHRD_FBAORIGIN: store_fw (buf, dev->fbaorigin); SHRD_SET_HDR (hdr, 0, 0, dev->devnum, id, 4); serverSend (dev, ix, hdr, buf, 4); break; case SHRD_FBANUMBLK: store_fw (buf, dev->fbanumblk); SHRD_SET_HDR (hdr, 0, 0, dev->devnum, id, 4); serverSend (dev, ix, hdr, buf, 4); break; case SHRD_FBABLKSIZ: store_fw (buf, dev->fbablksiz); SHRD_SET_HDR (hdr, 0, 0, dev->devnum, id, 4); serverSend (dev, ix, hdr, buf, 4); break; default: serverError (dev, ix, SHRD_ERROR_INVALID, cmd, "invalid query request"); break; } /* switch (flag) for SHRD_QUERY */ break; case SHRD_COMPRESS: #ifdef HAVE_LIBZ dev->shrd[ix]->comp = (flag & 0x0f); store_hw (buf, dev->shrd[ix]->comp); #else store_hw (buf, 0); #endif dev->shrd[ix]->comps = (flag & 0xf0) >> 4; SHRD_SET_HDR (hdr, 0, 0, dev->devnum, id, 2); serverSend (dev, ix, hdr, buf, 2); break; default: serverError (dev, ix, SHRD_ERROR_INVALID, cmd, "invalid request"); break; } /* switch (cmd) */ } /* serverRequest */ /*------------------------------------------------------------------- * Locate the SHRD block for a socket (server side) *-------------------------------------------------------------------*/ static int serverLocate (DEVBLK *dev, int id, int *avail) { int i; /* Loop index */ if (avail) *avail = -1; for (i = 0; i < SHARED_MAX_SYS; i++) { if (dev->shrd[i]) { if (dev->shrd[i]->id == id) return i; } else if (avail && *avail < 0) *avail = i; } return -1; } /* serverLocate */ /*------------------------------------------------------------------- * Return a new Identifier (server side) *-------------------------------------------------------------------*/ static int serverId (DEVBLK *dev) { int i; /* Loop index */ int id; /* Identifier */ do { dev->shrdid = (++dev->shrdid) & 0xffff; if (dev->shrdid == DEV_SYS_LOCAL || dev->shrdid == DEV_SYS_NONE) dev->shrdid = 1; id = dev->shrdid; for (i = 0; i < SHARED_MAX_SYS; i++) if (dev->shrd[i] && dev->shrd[i]->id == id) break; } while (i < SHARED_MAX_SYS); return id; } /* serverId */ /*------------------------------------------------------------------- * Respond with an error message (server side) *-------------------------------------------------------------------*/ static int serverError (DEVBLK *dev, int ix, int code, int status, char *msg) { int rc; /* Return code */ size_t len; /* Message length */ BYTE hdr[SHRD_HDR_SIZE]; /* Header */ /* Get message length */ len = strlen(msg) + 1; if (len > SHARED_MAX_MSGLEN) len = SHARED_MAX_MSGLEN; SHRD_SET_HDR (hdr, code, status, dev ? dev->devnum : 0, ix < 0 ? 0 : dev->shrd[ix]->id, (U16)len); shrdtrc(dev,"server_error %2.2x %2.2x: %s\n", code, status, msg); rc = serverSend (dev, ix, hdr, (BYTE *)msg, (int)len); return rc; } /* serverError */ /*------------------------------------------------------------------- * Send data (server side) *-------------------------------------------------------------------*/ static int serverSend (DEVBLK *dev, int ix, BYTE *hdr, BYTE *buf, int buflen) { int rc; /* Return code */ int sock; /* Socket number */ BYTE code; /* Header code */ BYTE status; /* Header status */ U16 devnum; /* Header device number */ int id; /* Header identifier */ int len; /* Header length */ int hdrlen; /* Header length + other data*/ BYTE *sendbuf = NULL; /* Send buffer */ int sendlen; /* Send length */ BYTE cbuf[SHRD_HDR_SIZE + 65536]; /* Combined buffer */ /* Make buf, buflen consistent if no additional data to be sent */ if (buf == NULL) buflen = 0; else if (buflen == 0) buf = NULL; /* Calculate length of header, may contain additional data */ SHRD_GET_HDR(hdr, code, status, devnum, id, len); hdrlen = SHRD_HDR_SIZE + (len - buflen); sendlen = hdrlen + buflen; /* Check if buf is adjacent to the header */ if (buf && hdr + hdrlen == buf) { hdrlen += buflen; buf = NULL; buflen = 0; } /* Send only the header buffer if `buf' is empty */ if (buflen == 0) sendbuf = hdr; /* Get socket number; if `ix' < 0 we don't have a device yet */ if (ix >= 0) sock = dev->shrd[ix]->fd; else { sock = -ix; dev = NULL; } shrdtrc(dev,"server_send %2.2x %2.2x %2.2x %d %d\n", code, status, devnum, id, len); #ifdef HAVE_LIBZ /* Compress the buf */ if (ix >= 0 && dev->shrd[ix]->comp != 0 && code == SHRD_OK && status == 0 && hdrlen - SHRD_HDR_SIZE <= SHRD_COMP_MAX_OFF && buflen >= SHARED_COMPRESS_MINLEN) { unsigned long newlen; int off = hdrlen - SHRD_HDR_SIZE; sendbuf = cbuf; newlen = sizeof(cbuf) - hdrlen; memcpy (cbuf, hdr, hdrlen); rc = compress2 (cbuf + hdrlen, &newlen, buf, buflen, dev->shrd[ix]->comp); if (rc == Z_OK && (int)newlen < buflen) { /* Setup to use the compressed buffer */ sendlen = hdrlen + newlen; buflen = 0; code = SHRD_COMP; status = (SHRD_LIBZ << 4) | off; SHRD_SET_HDR (cbuf, code, status, devnum, id, newlen + off); shrdtrc(dev,"server_send %2.2x %2.2x %2.2x %d %d (compressed)\n", code,status,devnum,id,(int)newlen+off); } } #endif /* Build combined (hdr + data) buffer */ if (buflen > 0) { sendbuf = cbuf; memcpy (cbuf, hdr, hdrlen); memcpy (cbuf + hdrlen, buf, buflen); } /* Send the combined header and data */ rc = send (sock, sendbuf, sendlen, 0); /* Process return code */ if (rc < 0) { logmsg(_("HHCSH041E %4.4X send error %d id=%d: %s\n"), dev->devnum, HSO_errno, id, strerror(HSO_errno)); dev->shrd[ix]->disconnect = 1; } return rc; } /* serverSend */ /*------------------------------------------------------------------- * Determine if a client can be disconnected (server side) *-------------------------------------------------------------------*/ static int serverDisconnectable (DEVBLK *dev, int ix) { if (dev->shrd[ix]->waiting || dev->shrd[ix]->pending || dev->ioactive == dev->shrd[ix]->id) return 0; else return 1; } /* serverDisconnectable */ /*------------------------------------------------------------------- * Disconnect a client (server side) * dev->lock *must* be held *-------------------------------------------------------------------*/ static void serverDisconnect (DEVBLK *dev, int ix) { int id; /* Client identifier */ int i; /* Loop index */ id = dev->shrd[ix]->id; //FIXME: Handle a disconnected busy client better // Perhaps a disconnect timeout value... this will // give the client time to reconnect. /* If the device is active by the client then extricate it. This is *not* a good situation */ if (dev->ioactive == id) { logmsg(_("HHCSH042W %4.4X busy client being removed id=%d %s\n"), dev->devnum, id, dev->reserved ? "reserved" : ""); /* Call the I/O release exit if reserved by this client */ if (dev->reserved && dev->hnd->release) (dev->hnd->release) (dev); /* Call the channel program end exit */ if (dev->hnd->end) (dev->hnd->end) (dev); /* Reset any `waiting' bits */ for (i = 0; i < SHARED_MAX_SYS; i++) if (dev->shrd[i]) dev->shrd[i]->waiting = 0; /* Make the device available */ if (dev->suspended) { dev->ioactive = DEV_SYS_LOCAL; dev->busy = 1; } else { dev->ioactive = DEV_SYS_NONE; dev->busy = 0; } /* Notify any waiters */ if (dev->iowaiters) signal_condition (&dev->iocond); } logmsg(_("HHCSH043I %s disconnected from %4.4X id=%d\n"), dev->shrd[ix]->ipaddr, dev->devnum, id); /* Release the SHRD block */ close_socket (dev->shrd[ix]->fd); free (dev->shrd[ix]->ipaddr); free (dev->shrd[ix]); dev->shrd[ix] = NULL; dev->shrdconn--; } /* serverDisconnect */ /*------------------------------------------------------------------- * Return client ip *-------------------------------------------------------------------*/ static char *clientip (int sock) { int rc; /* Return code */ struct sockaddr_in client; /* Client address structure */ socklen_t namelen; /* Length of client structure*/ namelen = sizeof(client); rc = getpeername (sock, (struct sockaddr *)&client, &namelen); return inet_ntoa(client.sin_addr); } /* clientip */ /*------------------------------------------------------------------- * Find device by device number *-------------------------------------------------------------------*/ static DEVBLK *findDevice (U16 devnum) { DEVBLK *dev; /* -> Device block */ for (dev = sysblk.firstdev; dev != NULL; dev = dev->nextdev) if (dev->devnum == devnum) break; return dev; } /* findDevice */ /*------------------------------------------------------------------- * Connect a new client *-------------------------------------------------------------------*/ static void *serverConnect (int *psock) { int csock; /* Connection socket */ int rc; /* Return code */ BYTE cmd; /* Request command */ BYTE flag; /* Request flag */ U16 devnum; /* Request device number */ int id; /* Request id */ int len; /* Request data length */ int ix; /* Client index */ DEVBLK *dev=NULL; /* -> Device block */ time_t now; /* Current time */ fd_set selset; /* Read bit map for select */ int maxfd; /* Max fd for select */ struct timeval wait; /* Wait time for select */ BYTE hdr[SHRD_HDR_SIZE + 65536]; /* Header + buffer */ BYTE *buf = hdr + SHRD_HDR_SIZE; /* Buffer */ char *ipaddr = NULL; /* IP addr of connected peer */ csock = *psock; free (psock); ipaddr = clientip(csock); shrdtrc(dev,"server_connect %s sock %d\n",ipaddr,csock); rc = recvData(csock, hdr, buf, 65536, 1); if (rc < 0) { logmsg(_("HHCSH0474 %s connect failed\n"), ipaddr); close_socket (csock); return NULL; } SHRD_GET_HDR (hdr, cmd, flag, devnum, id, len); /* Error if not a connect request */ if (id == 0 && cmd != SHRD_CONNECT) { serverError (NULL, -csock, SHRD_ERROR_NOTCONN, cmd, "not a connect request"); close_socket (csock); return NULL; } /* Locate the device */ dev = findDevice (devnum); /* Error if device not found */ if (dev == NULL) { serverError (NULL, -csock, SHRD_ERROR_NODEVICE, cmd, "device not found"); close_socket (csock); return NULL; } /* Obtain the device lock */ obtain_lock (&dev->lock); /* Find an available slot for the connection */ rc = serverLocate (dev, id, &ix); /* Error if already connected */ if (rc >= 0) { release_lock (&dev->lock); serverError (NULL, -csock, SHRD_ERROR_NODEVICE, cmd, "already connected"); close_socket (csock); return NULL; } /* Error if no available slot */ if (ix < 0) { release_lock (&dev->lock); serverError (NULL, -csock, SHRD_ERROR_NOTAVAIL, cmd, "too many connections"); close_socket (csock); return NULL; } /* Obtain SHRD block */ dev->shrd[ix] = calloc (sizeof(SHRD), 1); /* Error if not obtained */ if (dev->shrd[ix] == NULL) { release_lock (&dev->lock); serverError (NULL, -csock, SHRD_ERROR_NOMEM, cmd, "calloc() failure"); close_socket (csock); return NULL; } /* Initialize the SHRD block */ dev->shrd[ix]->pending = 1; dev->shrd[ix]->havehdr = 1; if (id == 0) id = serverId (dev); dev->shrd[ix]->id = id; dev->shrd[ix]->fd = csock; dev->shrd[ix]->ipaddr = strdup(ipaddr); dev->shrd[ix]->time = time (NULL); dev->shrd[ix]->purgen = -1; dev->shrdconn++; SHRD_SET_HDR (dev->shrd[ix]->hdr, cmd, flag, devnum, id, len); logmsg (_("HHCSH053I %s connected to %4.4X id=%d\n"), ipaddr, devnum, id); /* Return if device thread already active */ if (dev->shrdtid) { if (dev->shrdwait) { signal_thread (dev->shrdtid, SIGUSR2); } release_lock (&dev->lock); return NULL; } dev->shrdtid = thread_id(); /* This thread will be the shared device thread */ logmsg (_("HHCSH045I Shared device %4.4X thread started: " "tid="TIDPAT", pid=%d\n"), dev->devnum, thread_id(), getpid()); while (dev->shrdconn) { FD_ZERO (&selset); maxfd = -1; /* Get the current time */ now = time (NULL); for (ix = 0; ix < SHARED_MAX_SYS; ix++) { if (dev->shrd[ix]) { /* Exit loop if pending and not waiting */ if (dev->shrd[ix]->pending && !dev->shrd[ix]->waiting) break; /* Disconnect if not a valid socket */ if ( !socket_is_socket( dev->shrd[ix]->fd ) ) dev->shrd[ix]->disconnect = 1; /* See if the connection can be timed out */ else if (now - dev->shrd[ix]->time > SHARED_TIMEOUT && serverDisconnectable (dev, ix)) dev->shrd[ix]->disconnect = 1; /* Disconnect if the disconnect bit is set */ if (dev->shrd[ix]->disconnect) serverDisconnect (dev, ix); /* Otherwise set the fd if not waiting */ else if (!dev->shrd[ix]->waiting) { FD_SET (dev->shrd[ix]->fd, &selset); if (dev->shrd[ix]->fd >= maxfd) maxfd = dev->shrd[ix]->fd + 1; shrdtrc(dev,"select set %d id=%d\n",dev->shrd[ix]->fd,dev->shrd[ix]->id); } } } /* Wait for a request if no pending requests */ if (ix >= SHARED_MAX_SYS) { /* Exit thread if nothing to select */ if (maxfd < 0) continue; /* Wait for a file descriptor to become busy */ wait.tv_sec = 10; /*SHARED_SELECT_WAIT;*/ wait.tv_usec = 0; release_lock (&dev->lock); dev->shrdwait = 1; rc = select ( maxfd, &selset, NULL, NULL, &wait ); dev->shrdwait = 0; obtain_lock (&dev->lock); shrdtrc(dev,"select rc %d\n",rc); if (rc == 0) continue; if (rc < 0 ) { if (HSO_errno == HSO_EINTR || HSO_errno == HSO_EBADF) continue; logmsg(_("HHCSH046E select: %s\n"), strerror(HSO_errno)); break; } /* Find any pending requests */ for (ix = 0; ix < SHARED_MAX_SYS; ix++) { if (dev->shrd[ix] && FD_ISSET(dev->shrd[ix]->fd, &selset)) { dev->shrd[ix]->pending = 1; shrdtrc(dev,"select isset %d id=%d\n",dev->shrd[ix]->fd,dev->shrd[ix]->id); } } continue; } /* Found a pending request */ release_lock (&dev->lock); shrdtrc(dev,"select ready %d id=%d\n",dev->shrd[ix]->fd,dev->shrd[ix]->id); if (dev->shrd[ix]->havehdr) { /* Copy the saved start/resume packet */ memcpy (hdr, dev->shrd[ix]->hdr, SHRD_HDR_SIZE); dev->shrd[ix]->havehdr = dev->shrd[ix]->waiting = 0; } else { /* Read the request packet */ rc = recvData (dev->shrd[ix]->fd, hdr, buf, 65536, 1); if (rc < 0) { logmsg(_("HHCSH047E %4.4X %s recv error id=%d\n"), dev->devnum, dev->shrd[ix]->ipaddr, dev->shrd[ix]->id); dev->shrd[ix]->disconnect = 1; dev->shrd[ix]->pending = 0; obtain_lock (&dev->lock); continue; } } /* Process the request */ serverRequest (dev, ix, hdr, buf); obtain_lock (&dev->lock); /* If the `waiting' bit is on then the start/resume request failed because the device is busy on some other remote system. We only need to save the header because the data is ignored for start/resume. */ if (dev->shrd[ix]->waiting) { memcpy (dev->shrd[ix]->hdr, hdr, SHRD_HDR_SIZE); dev->shrd[ix]->havehdr = 1; } else dev->shrd[ix]->pending = 0; } dev->shrdtid = 0; release_lock (&dev->lock); logmsg (_("HHCSH048I Shared device %4.4X thread stopping\n"), dev->devnum); return NULL; } /* serverConnect */ /*------------------------------------------------------------------- * General trace routine for shared devices *-------------------------------------------------------------------*/ static void shrdtrc (DEVBLK *dev, char *msg, ...) { int dt; struct timeval tv; SHRD_TRACE s; va_list vl; dt = (dev != NULL && (dev->ccwtrace||dev->ccwstep)); if (dt == 0 && sysblk.shrdtrace == 0) return; va_start(vl,msg); gettimeofday(&tv, NULL); sprintf ((char *)s, "%6.6ld" "." "%6.6ld %4.4X:", tv.tv_sec, tv.tv_usec, dev ? dev->devnum : 0); vsnprintf ((char *)s + strlen(s), sizeof(s) - strlen(s), msg, vl); if (dt) { logmsg (s+14); } if (sysblk.shrdtrace) { SHRD_TRACE *p = sysblk.shrdtracep++; if (p >= sysblk.shrdtracex) { p = sysblk.shrdtrace; sysblk.shrdtracep = p + 1; } if (p) memcpy(p, s, sizeof(*p)); } } /* shrdtrc */ /*------------------------------------------------------------------- * Shared device server *-------------------------------------------------------------------*/ DLL_EXPORT void *shared_server (void *arg) { int rc; /* Return code */ int hi; /* Hi fd for select */ int lsock; /* inet socket for listening */ int usock; /* unix socket for listening */ int rsock; /* Ready socket */ int csock; /* Socket for conversation */ int *psock; /* Pointer to socket */ struct sockaddr_in server; /* Server address structure */ #if defined( HAVE_SYS_UN_H ) struct sockaddr_un userver; /* Unix address structure */ #endif int optval; /* Argument for setsockopt */ fd_set selset; /* Read bit map for select */ TID tid; /* Negotiation thread id */ UNREFERENCED(arg); /* Display thread started message on control panel */ logmsg (_("HHCSH049I Shared device %d" "." "%d thread started: " "tid="TIDPAT", pid=%d\n"), SHARED_VERSION, SHARED_RELEASE, thread_id(), getpid()); /* Obtain a internet socket */ lsock = socket (AF_INET, SOCK_STREAM, 0); if (lsock < 0) { logmsg(_("HHCSH050E inet socket: %s\n"), strerror(HSO_errno)); return NULL; } /* Obtain a unix socket */ #if defined( HAVE_SYS_UN_H ) usock = socket (AF_UNIX, SOCK_STREAM, 0); if (usock < 0) { logmsg(_("HHCSH051W unix socket: %s\n"), strerror(HSO_errno)); } #else usock = -1; #endif /* Allow previous instance of socket to be reused */ optval = 1; setsockopt (lsock, SOL_SOCKET, SO_REUSEADDR, (GETSET_SOCKOPT_T*)&optval, sizeof(optval)); /* Prepare the sockaddr structure for the bind */ memset (&server, 0, sizeof(server)); server.sin_family = AF_INET; server.sin_addr.s_addr = INADDR_ANY; server.sin_port = sysblk.shrdport; server.sin_port = htons(server.sin_port); /* Attempt to bind the internet socket to the port */ while (1) { rc = bind (lsock, (struct sockaddr *)&server, sizeof(server)); if (rc == 0 || HSO_errno != HSO_EADDRINUSE) break; logmsg (_("HHCSH052W Waiting for port %u to become free\n"), sysblk.shrdport); SLEEP(10); } /* end while */ if (rc != 0) { logmsg(_("HHCSH053E inet bind: %s\n"), strerror(HSO_errno)); close_socket(lsock); close_socket(usock); return NULL; } #if defined( HAVE_SYS_UN_H ) /* Bind the unix socket */ if (usock >= 0) { userver.sun_family = AF_UNIX; sprintf(userver.sun_path, "/tmp/hercules_shared.%d", sysblk.shrdport); unlink(userver.sun_path); fchmod (usock, 0700); rc = bind (usock, (struct sockaddr *)&userver, sizeof(userver)); if (rc < 0) { logmsg(_("HHCSH054W unix bind: %s\n"), strerror(errno)); close(usock); usock = -1; } } #endif // defined( HAVE_SYS_UN_H ) /* Put the sockets into listening state */ rc = listen (lsock, SHARED_MAX_SYS); if (rc < 0) { logmsg(_("HHCSH055E inet listen: %s\n"), strerror(HSO_errno)); close_socket(lsock); close_socket(usock); return NULL; } if (usock >= 0) { rc = listen (usock, SHARED_MAX_SYS); if (rc < 0) { logmsg(_("HHCSH056W unix listen: %s\n"), strerror(HSO_errno)); close_socket(usock); usock = -1; } } sysblk.shrdtid = thread_id(); csock = -1; if (lsock < usock) hi = usock + 1; else hi = lsock + 1; logmsg(_("HHCSH057I Waiting for shared device requests on port %u\n"), sysblk.shrdport); /* Handle connection requests and attention interrupts */ while (!sysblk.shutdown) { /* Initialize the select parameters */ FD_ZERO (&selset); FD_SET (lsock, &selset); if (usock >= 0) FD_SET (usock, &selset); /* Wait for a file descriptor to become ready */ rc = select ( hi, &selset, NULL, NULL, NULL ); if (rc == 0) continue; if (rc < 0 ) { if (HSO_errno == HSO_EINTR) continue; logmsg(_("HHCSH058E select: %s\n"), strerror(HSO_errno)); break; } /* If a client connection request has arrived then accept it */ if (FD_ISSET(lsock, &selset)) rsock = lsock; else if (usock >= 0 && FD_ISSET(usock, &selset)) rsock = usock; else rsock = -1; if (rsock > 0) { /* Accept a connection and create conversation socket */ csock = accept (rsock, NULL, NULL); if (csock < 0) { logmsg(_("HHCSH059E accept: %s\n"), strerror(HSO_errno)); continue; } psock = malloc (sizeof (csock)); if (psock == NULL) { logmsg(_("HHCSH060E malloc size %d: %s\n"), sizeof(csock), strerror(HSO_errno)); close_socket (csock); continue; } *psock = csock; /* Create a thread to complete the client connection */ if ( create_thread (&tid, DETACHED, serverConnect, psock, "serverConnect") ) { logmsg(_("HHCSH061E serverConnect create_thread: %s\n"), strerror(HSO_errno)); close_socket (csock); } } /* end if(rsock) */ } /* end while */ /* Close the listening sockets */ close_socket (lsock); #if defined( HAVE_SYS_UN_H ) if (usock >= 0) { close_socket (usock); unlink(userver.sun_path); } #endif sysblk.shrdtid = 0; return NULL; } /* end function shared_server */ /*------------------------------------------------------------------- * Shared device command processor *-------------------------------------------------------------------*/ DLL_EXPORT int shared_cmd(int argc, char *argv[], char *cmdline) { char buf[256]; char *kw, *op, c; UNREFERENCED(cmdline); /* Get keyword and operand */ if (argc != 2 || strlen(argv[1]) > 255) { logmsg (_("HHCSH062E Invalid or missing argument 1\n")); return 0; } strcpy (buf, argv[1]); kw = strtok (buf, "="); op = strtok (NULL, " \t"); if (kw == NULL) { logmsg (_("HHCSH063E Invalid or missing keyword 2\n")); return 0; } if (strcasecmp(kw, "trace") == 0) { int n; SHRD_TRACE *s, *p, *x, *i; s = sysblk.shrdtrace; p = sysblk.shrdtracep; x = sysblk.shrdtracex; n = sysblk.shrdtracen; /* Get a new trace table if an operand was specified */ if (op) { if (sscanf (op, "%d%c", &n, &c) != 1) { logmsg (_("HHCSH064E Invalid or missing value %s\n"),op); return 0; } if (s != NULL) { sysblk.shrdtrace = sysblk.shrdtracex = sysblk.shrdtracep = NULL; SLEEP (1); free (s); } sysblk.shrdtrace = sysblk.shrdtracex = sysblk.shrdtracep = NULL; sysblk.shrdtracen = 0; if (n > 0) { s = calloc (sizeof(SHRD_TRACE), n); if (s == NULL) { logmsg (_("HHCSH065E calloc() size=%d: %s\n"), sizeof(SHRD_TRACE) * n, strerror(errno)); return 0; } sysblk.shrdtracen = n; sysblk.shrdtrace = sysblk.shrdtracep = s; sysblk.shrdtracex = s + n; } return 0; } /* Print the trace table */ sysblk.shrdtrace = sysblk.shrdtracex = sysblk.shrdtracep = NULL; i = p; SLEEP(1); do { if (i[0] != '\0') logmsg ("%s",(char *)i); if (++i >= x) i = s; } while (i != p); memset (s, 0, n * sizeof(SHRD_TRACE)); sysblk.shrdtrace = s; sysblk.shrdtracep = s; sysblk.shrdtracex = x; sysblk.shrdtracen = n; } else { logmsg (_("HHCSH066E Invalid or missing keyword %s\n"), kw); return 0; } return 0; } DEVHND shared_ckd_device_hndinfo = { &shared_ckd_init, /* Device Initialisation */ &ckddasd_execute_ccw, /* Device CCW execute */ &shared_ckd_close, /* Device Close */ &ckddasd_query_device, /* Device Query */ &shared_start, /* Device Start channel pgm */ &shared_end, /* Device End channel pgm */ &shared_start, /* Device Resume channel pgm */ &shared_end, /* Device Suspend channel pgm */ &shared_ckd_read, /* Device Read */ &shared_ckd_write, /* Device Write */ &shared_used, /* Device Query used */ &shared_reserve, /* Device Reserve */ &shared_release, /* Device Release */ NULL, /* Device Attention */ NULL, /* Immediate CCW Codes */ NULL, /* Signal Adapter Input */ NULL, /* Signal Adapter Output */ &ckddasd_hsuspend, /* Hercules suspend */ &ckddasd_hresume /* Hercules resume */ }; DEVHND shared_fba_device_hndinfo = { &shared_fba_init, /* Device Initialisation */ &fbadasd_execute_ccw, /* Device CCW execute */ &shared_fba_close, /* Device Close */ &fbadasd_query_device, /* Device Query */ &shared_start, /* Device Start channel pgm */ &shared_end, /* Device End channel pgm */ &shared_start, /* Device Resume channel pgm */ &shared_end, /* Device Suspend channel pgm */ &shared_ckd_read, /* Device Read */ &shared_ckd_write, /* Device Write */ &shared_used, /* Device Query used */ &shared_reserve, /* Device Reserve */ &shared_release, /* Device Release */ NULL, /* Device Attention */ NULL, /* Immediate CCW Codes */ NULL, /* Signal Adapter Input */ NULL, /* Signal Adapter Output */ &fbadasd_hsuspend, /* Hercules suspend */ &fbadasd_hresume /* Hercules resume */ }; #else int shared_update_notify (DEVBLK *dev, int block) { UNREFERENCED(dev); UNREFERENCED(block); return 0; } int shared_ckd_init (DEVBLK *dev, int argc, BYTE *argv[] ) { UNREFERENCED(dev); UNREFERENCED(argc); UNREFERENCED(argv); return -1; } int shared_fba_init (DEVBLK *dev, int argc, BYTE *argv[] ) { UNREFERENCED(dev); UNREFERENCED(argc); UNREFERENCED(argv); return -1; } void *shared_server (void *arg) { UNREFERENCED(arg); logmsg (_("HHCSH999E OPTION_SHARED_DEVICES not defined")); return NULL; } int shared_cmd(int argc, char *argv[], char *cmdline); UNREFERENCED(cmdline); UNREFERENCED(argc); UNREFERENCED(argv); logmsg (_("HHCSH999E OPTION_SHARED_DEVICES not defined")); return 0; } #endif /*defined(OPTION_SHARED_DEVICES)*/ hercules-3.07/shared.h000644 000765 000765 00000061100 11143760544 016365 0ustar00jmaynardjmaynard000000 000000 /*------------------------------------------------------------------- * Shared device support (c)Copyright Greg Smith, 2002-2009 * * $Id: shared.h 5126 2009-01-23 13:05:56Z bernard $ * * Shared device support allows multiple Hercules instances to share * devices. The device will be `local' to one instance and `remote' * to all other instances. The local instance is the * `server' for * that device and the remote instance is the `client'. You do not * have to IPL an operating system on the device server. Any number * of Hercules instances can act as a server in a Hercplex ;-) * * To use a device on a remote system, instead of specifying a file * name on the device config statement, you specify * * ip_address_or_name:port:devnum * * For example: * * 0100 3350 localhost:3990:0100 * * which says there is a device server on the local host listening * on port 3990 and we want to use its 0100 device as 0100. The * default port is 3990 and the default remote device number is the * local device number. So we could say * * 0100 3350 localhost * * instead, providing we don't actually have a file `localhost'. * Interestingly, the instance on the local host listening on 3990 * could have a statement * * 0100 3350 192.168.200.1::0200 * * which means that instance in turn will use device 0200 on the * server at 192.168.200.1 listening on port 3990. The original * instance will have to `hop' thru the second instance to get * to the real device. * * Device sharing can be `split' between multiple instances. * For example, suppose instance A has * * SHRDPORT 3990 * 0100 3350 localhost:3991 * 0101 3350 mvscat * * and instance B has * * SHRDPORT 3991 * 0100 3350 mvsres * 0101 3350 localhost * * Then each instance acts as both a client and as a server. * * When `SHRDPORT' is specified, thread `shared_server' is started * at the end of Hercules initialization. In the example above, * neither Hercules instance can initialize their devices until the * server is started on each system. In this case, the device trying * to access a server gets the `connecting' bit set on in the DEVBLK * and the device still needs to initialize. After the shared server * is started, a thread is attached for each device that is connecting * to complete the connection (which is the device init handler). * * TECHNICAL BS: * * There are (at least) two approaches to sharing devices. One is to * execute the channel program on the server system. The server will * need to request from the client system information such as the ccw * and the data to be written, and will need to send to the client * data that has been read and status information. The second is to * execute the channel program on the client system. Here the client * system makes requests to the server system to read and write data. * * The second approach is currently implemented. The first approach * arguably emulates `more correctly'. However, an advantage of the * implemented approach is that it is easier because only the * client sends requests and only the server sends responses. * * Both client and server have a DEVBLK structure for the device. * Absurdly, perhaps, in originally designing an implementation for * shared devices it was not clear what type of process should be the * server. It was a quantum leap forward to realize that it could * just be another hercules instance. * * PROTOCOL: * (If this section is as boring for you to read as it was for me * to write then please skip to the next section ;-) * * The client sends an 8 byte request header and maybe some data: * * +-----+-----+-----+-----+-----+-----+-----+-----+ * | cmd |flag | devnum | id | length | * +-----+-----+-----+-----+-----+-----+-----+-----+ * * <-------- length ---------> * +----- . . . . . -----+ * | data | * +----- . . . . . -----+ * * `cmd' identifies the client request. The requests are: * * 0xe0 CONNECT Connect to the server. This requires * the server to allocate resources to * support the connection. Typically issued * during device initialization or after being * disconnected after a network error or timeout. * 0xe1 DISCONNECT Disconnect from the server. The server * can now release the allocated resources * for the connection. Typically issued during * device close or detach. * 0xe2 START Start a channel program on the device. * If the device is busy or reserved by * another system then wait until the device * is available unless the NOWAIT flag bit * is set, then return a BUSY code. Once * START succeeds then the device is unavailable * until the END request. * 0xe3 END Channel program has ended. Any waiters * for the device can now retry. * 0xe4 RESUME Similar to START except a suspended * channel program has resumed. * 0xe5 SUSPEND Similar to END except a channel program * has suspended itself. If the channel * program is not resumed then the END * request is *not* issued. * 0xe6 RESERVE Makes the device unavailable to any other * system until a RELEASE request is issued. * *Must* be issued within the scope of START/END. * 0xe7 RELEASE Makes the device available to other systems * after the next END request. * *Must* be issued within the scope of * START/END. * 0xe8 READ Read from a device. A 4-byte `record' * identifier is specified in the request * data to identify what data to read in the * device context. * *Must* be issued within the scope of START/END. * 0xe9 WRITE Write to a device. A 2-byte `offset' and * a 4-byte `record' is specified in the request * data, followed by the data to be written. * `record' identifies what data is to be written * in the device context and `offset' and `length' * identify what to update in `record'. * *Must* be issued within the scope of START/END. * 0xea SENSE Retrieves the sense information after an i/o * error has occurred on the server side. This * is typically issued within the scope of the * channel program having the error. Client side * sense or concurrent sense will then pick up the * sense data relevant to the i/o error. * *Must* be issued within the scope of START/END. * 0xeb QUERY Obtain device information, typically during * device initialization. * 0xec COMPRESS Negotiate compression parameters. Notifies the * server what compression algorithms are supported * by the client and whether or not data sent back * and forth from the client or server should be * compressed or not. Typically issued after CONNECT. * *NOTE* This action should actually be SETOPT or * some such; it was just easier to code a COMPRESS * specific SETOPT (less code). * * `flag' qualifies the client request and varies by the request. * * 0x80 NOWAIT For START, if the device is unavailable then * return BUSY instead of waiting for the device. * 0x40 QUERY Identifies the QUERY request: * 0x41 DEVCHAR Device characteristics data * 0x42 DEVID Device identifier data * 0x43 DEVUSED Hi used track/block (for dasdcopy) * 0x48 CKDCYLS Number cylinders for CKD device * 0x4c FBAORIGIN Origin block for FBA * 0x4d FBANUMBLK Number of FBA blocks * 0x4e FBABLKSIZ Size of an FBA block * 0x3x COMP For WRITE, data is compressed at offset `x': * 0x2x BZIP2 using bzip2 * 0x1x LIBZ using zlib * 0xxy For COMPRESS, identifies the compression * algorithms supported by the client (0x2y for bzip2, * 0x1y for zlib, 0x3y for both) and the zlib compression * parameter `y' for sending otherwise uncompressed data * back and forth. If `y' is zero (default) then no * uncompressed data is compressed between client & server. * * `devnum' identifies the device by number on the server instance. * The device number may be different than the * device number on the client instance. * `id' identifies the client to the server. Each client has a unique * positive (non-zero) identifier. For the initial * CONNECT request `id' is zero. After a successful * CONNECT, the server returns in the response header * the identifier to be used for all other requests * (including subsequent CONNECT requests). This is * saved in dev->rmtid. * `length' specifies the length of the data following the request header. * Currently length is non-zero for READ/WRITE requests. * * The server sends an 8 byte response header and maybe some data: * * +-----+-----+-----+-----+-----+-----+-----+-----+ * |code |stat | devnum | id | length | * +-----+-----+-----+-----+-----+-----+-----+-----+ * * <-------- length ---------> * +----- . . . . . -----+ * | data | * +----- . . . . . -----+ * * `code' indicates the response to the request. OK (0x00) indicates * success however other codes also indicate success * but qualified in some manner: * 0x80 ERROR An error occurred. The server provides an error * message in the data section. * 0x40 IOERR An i/o error occurred during a READ/WRITE * request. The status byte has the `unitstat' * data. This should signal the client to issue the * SENSE request to obtain the current sense data. * 0x20 BUSY Device was not available for a START request and * the NOWAIT flag bit was turned on. * 0x10 COMP Data returned is compressed. The status byte * indicates how the data is compressed (zlib or * bzip2) and at what offset the compressed data * starts (0 .. 15). This bit is only turned on * when both the `code' and `status' bytes would * otherwise be zero. * 0x08 PURGE START request was issued by the client. A list * of `records' to be purged from local cache is * returned. These are `records' that have been * updated since the last START/END request from * the client by other systems. Each record identifier * is a 4-byte field in the data segment. The number * of records then is `length'/4. If the number of * records exceeds a threshold (16) then `length' * will be zero indicating that the client should * purge all locally cached records for the device. * * `stat' contains status information as a result of the request. * For READ/WRITE requests this contains the `unitstat' * information if an IOERR occurred. * * `devnum' specifies the server device number * * `id' specifies the system identifier for the request. * * `length' is the size of the data returned. * * * CACHING * * Cached records (eg CKD tracks or FBA blocks) are kept independently on * both the client and server sides. Whenever the client issues a START * request to initiate a channel program the server will return a list * of records to purge from the client's cache that have been updated by * other clients since the last START request. If the list is too large * the server will indicate that the client should purge all records for * the device. * * COMPRESSION * * Data that would normally be transferred uncompressed between client * and host can optionally be compressed by specifying the `comp=' * keyword on the device configuration statement or attach command. * For example * * 0100 3350 192.168.2.12 comp=3 * * The value of the `comp=' keyword is the zlib compression parameter * which should be a number between 1 .. 9. A value closer to 1 means * less compression but less processor time to perform the compression. * A value closer to 9 means the data is compressed more but more processor * time is required. * * If the server is on `localhost' then you should not specify `comp='. * Otherwise you are just stealing processor time to do compression/ * uncompression from hercules. If the server is on a local network * then I would recommend specifying a low value such as 1, 2 or 3. * We are on a curve here, trying to trade cpu cycles for network traffic * to derive an optimal throughput. * * If the devices on the server are compressed devices (eg CCKD or CFBA) * then the `records' (eg. track images or block groups) may be transferred * compressed regardless of the `comp=' setting. This depends on whether * the client supports the compression type (zlib or bzip2) of the record * on the server and whether the record is actually compressed in the * server cache. * * For example: * * Suppose on the client that you execute one or more channel programs * to read a record on a ckd track, update a record on the same track, * and then read another (or the same) record on the track. * * For the first read the server will read the track image and * pass it to the client as it was originally compressed in the file. * To update a portion of the track image the server must uncompress * the track image so data in it can be updated. When the client next * reads from the track image, the track image is uncompressed. * * Specifying `comp=' means that uncompressed data sent to the client * will be compressed. If the data to be sent to the client is already * compressed then the data is sent as is, unless the client has indicated * that it does not support that compression algorithm. * * * TODO * * 1. More doc (sorry, I got winded) * 2. Delays observed during short transfers (redrive select ?) * 3. Better server side behaviour due to disconnect * 3. etc. * * * * $Log$ * Revision 1.16 2007/06/23 00:04:15 ivan * Update copyright notices to include current year (2007) * * Revision 1.15 2006/12/28 20:32:54 fish * Fix "HHCSH043I 0.0.0.0 disconnected from ..."; save clientip in SHRD block at connect and use at disconnect. * * Revision 1.14 2006/12/08 09:43:30 jj * Add CVS message log * * *-------------------------------------------------------------------*/ #ifndef _HERCULES_SHARED_H #define _HERCULES_SHARED_H 1 #include "hercules.h" #ifndef _SHARED_C_ #ifndef _HDASD_DLL_ #define SHR_DLL_IMPORT DLL_IMPORT #else /* _HDASD_DLL_ */ #define SHR_DLL_IMPORT extern #endif /* _HDASD_DLL_ */ #else #define SHR_DLL_IMPORT DLL_EXPORT #endif #define OPTION_SHARED_DEVICES #undef FBA_SHARED /* * Differing version levels are not compatible * Differing release levels are compatible */ #define SHARED_VERSION 0 /* Version level (0 .. 15) */ #define SHARED_RELEASE 1 /* Release level (0 .. 15) */ #define SHARED_MAX_SYS 8 /* Max number connections */ typedef char SHRD_TRACE[128]; /* Trace entry */ #include "hercules.h" /* Requests */ #define SHRD_CONNECT 0xe0 /* Connect */ #define SHRD_DISCONNECT 0xe1 /* Disconnect */ #define SHRD_START 0xe2 /* Start channel program */ #define SHRD_END 0xe3 /* End channel program */ #define SHRD_RESUME 0xe4 /* Resume channel program */ #define SHRD_SUSPEND 0xe5 /* Suspend channel program */ #define SHRD_RESERVE 0xe6 /* Reserve */ #define SHRD_RELEASE 0xe7 /* Release */ #define SHRD_READ 0xe8 /* Read data */ #define SHRD_WRITE 0xe9 /* Write data */ #define SHRD_SENSE 0xea /* Sense */ #define SHRD_QUERY 0xeb /* Query */ #define SHRD_COMPRESS 0xec /* Compress request */ /* Response codes */ #define SHRD_OK 0x00 /* Success */ #define SHRD_ERROR 0x80 /* Failure */ #define SHRD_IOERR 0x40 /* I/O error */ #define SHRD_BUSY 0x20 /* Resource is busy */ #define SHRD_COMP 0x10 /* Data is compressed */ #define SHRD_PURGE 0x08 /* Purge list provided */ #define SHRD_ERROR_INVALID 0xf0 /* Invalid request */ #define SHRD_ERROR_BADVERS 0xf1 /* Version mismatch */ #define SHRD_ERROR_NOTINIT 0xf2 /* Device not initialized */ #define SHRD_ERROR_NOTCONN 0xf3 /* Not connected to device */ #define SHRD_ERROR_NOTAVAIL 0xf4 /* No available SHRD */ #define SHRD_ERROR_NOMEM 0xf5 /* Out of memory */ #define SHRD_ERROR_NOTACTIVE 0xf6 /* Not device owner */ #define SHRD_ERROR_NODEVICE 0xf7 /* No such device */ #define SHRD_ERROR_CONNECTED 0xf8 /* Already connected */ /* Flags */ #define SHRD_NOWAIT 0x80 /* Don't wait if busy */ #define SHRD_QUERY_REQUEST 0x40 /* Query request */ #define SHRD_COMP_MASK 0x30 /* Mask to detect compression*/ #define SHRD_COMP_OFF 0x0f /* Offset to compressed data */ #define SHRD_COMP_MAX_OFF 15 /* Max offset allowed */ #define SHRD_LIBZ 0x01 /* Compressed using zlib */ #define SHRD_BZIP2 0x02 /* Compressed using bzip2 */ /* Query Types */ #define SHRD_DEVCHAR 0x41 /* Device characteristics */ #define SHRD_DEVID 0x42 /* Device identifier */ #define SHRD_USED 0x43 /* Device usage */ #define SHRD_CKDCYLS 0x48 /* CKD number cylinders */ #define SHRD_FBAORIGIN 0x4c /* FBA origin */ #define SHRD_FBANUMBLK 0x4d /* FBA number blocks */ #define SHRD_FBABLKSIZ 0x4e /* FBA block size */ /* Constraints */ #define SHARED_DEFAULT_PORT 3990 /* Default shared port */ #define SHARED_PURGE_MAX 16 /* Max size of purge list */ #define SHARED_MAX_MSGLEN 255 /* Max message length */ #define SHARED_TIMEOUT 120 /* Disconnect timeout (sec) */ #define SHARED_FORCE_TIMEOUT 300 /* Force disconnect (sec) */ #define SHARED_SELECT_WAIT 10 /* Select timeout (sec) */ #define SHARED_COMPRESS_MINLEN 512 /* Min length for compression*/ struct SHRD { int id; /* Identifier */ int fd; /* Socket */ char *ipaddr; /* IP addr of connected peer */ time_t time; /* Time last request */ int release; /* Client release level */ int comp; /* Compression parameter */ int comps; /* Compression supported */ int pending:1, /* 1=Request pending */ waiting:1, /* 1=Waiting for device */ havehdr:1, /* 1=Header already read */ disconnect:1; /* 1=Disconnect device */ DBLWRD hdr; /* Header */ int purgen; /* Number purge entries */ FWORD purge[SHARED_PURGE_MAX];/* Purge list */ }; typedef struct _SHRD_HDR { BYTE cmd; /* 0 Command */ BYTE code; /* 1 Flags and Codes */ U16 devnum; /* 2 Device number */ U16 id; /* 4 Identifier */ U16 len; /* 6 Data length */ } SHRD_HDR; /* Size must be 8 bytes */ #define SHRD_HDR_SIZE sizeof(DBLWRD) #define SHRD_SET_HDR(_buf, _cmd, _code, _devnum, _len, _id) \ do { \ SHRD_HDR *shdr = (SHRD_HDR *)(_buf); \ shdr->cmd = (_cmd); \ shdr->code = (_code); \ store_hw (&shdr->devnum, (_devnum)); \ store_hw (&shdr->len, (_len)); \ store_hw (&shdr->id, (_id)); \ } while (0) #define SHRD_GET_HDR(_buf, _cmd, _code, _devnum, _len, _id) \ do { \ SHRD_HDR *shdr = (SHRD_HDR *)(_buf); \ (_cmd) = shdr->cmd; \ (_code) = shdr->code; \ (_devnum) = (U16)fetch_hw (&shdr->devnum); \ (_len) = (int)fetch_hw (&shdr->len); \ (_id) = (int)fetch_hw (&shdr->id); \ } while (0) int shared_update_notify (DEVBLK *dev, int block); int shared_ckd_init (DEVBLK *dev, int argc, char *argv[] ); int shared_fba_init (DEVBLK *dev, int argc, char *argv[] ); SHR_DLL_IMPORT void *shared_server (void *arg); SHR_DLL_IMPORT int shared_cmd(int argc, char *argv[], char *cmdline); #ifdef _SHARED_C_ static int shared_ckd_close ( DEVBLK *dev ); static int shared_fba_close (DEVBLK *dev); static void shared_start(DEVBLK *dev); static void shared_end (DEVBLK *dev); static int shared_ckd_read (DEVBLK *dev, int trk, BYTE *unitstat); static int shared_ckd_write (DEVBLK *dev, int trk, int off, BYTE *buf, int len, BYTE *unitstat); static int shared_ckd_trklen (DEVBLK *dev, BYTE *buf); #if defined(FBA_SHARED) static int shared_fba_read (DEVBLK *dev, int blkgrp, BYTE *unitstat); static int shared_fba_write (DEVBLK *dev, int blkgrp, int off, BYTE *buf, int len, BYTE *unitstat); static int shared_fba_blkgrp_len (DEVBLK *dev, int blkgrp); #endif static int shared_used (DEVBLK *dev); static void shared_reserve (DEVBLK *dev); static void shared_release (DEVBLK *dev); static int clientWrite (DEVBLK *dev, int block); static void clientPurge (DEVBLK *dev, int n, void *buf); static int clientPurgescan (int *answer, int ix, int i, void *data); static int clientConnect (DEVBLK *dev, int retry); static int clientRequest (DEVBLK *dev, BYTE *buf, int len, int cmd, int flags, int *code, int *status); static int clientSend (DEVBLK *dev, BYTE *hdr, BYTE *buf, int buflen); static int clientRecv (DEVBLK *dev, BYTE *hdr, BYTE *buf, int buflen); static int recvData(int sock, BYTE *hdr, BYTE *buf, int buflen, int server); static void serverRequest (DEVBLK *dev, int ix, BYTE *hdr, BYTE *buf); static int serverLocate (DEVBLK *dev, int id, int *avail); static int serverId (DEVBLK *dev); static int serverError (DEVBLK *dev, int ix, int code, int status, char *msg); static int serverSend (DEVBLK *dev, int ix, BYTE *hdr, BYTE *buf, int buflen); static int serverDisconnectable (DEVBLK *dev, int ix); static void serverDisconnect (DEVBLK *dev, int ix); static char *clientip (int sock); static DEVBLK *findDevice (U16 devnum); static void *serverConnect (int *psock); static void shrdtrc (DEVBLK *dev, char *msg, ...); #endif /* _SHARED_C_ */ #endif /* _HERCULES_SHARED_H */ hercules-3.07/sie.c000644 000765 000765 00000137102 11157241226 015674 0ustar00jmaynardjmaynard000000 000000 /* SIE.C (c) Copyright Jan Jaeger, 1999-2009 */ /* Interpretive Execution */ /* This module contains the SIE instruction as */ /* described in IBM S/370 Extended Architecture */ /* Interpretive Execution, SA22-7095-01 */ /* and */ /* Enterprise Systems Architecture / Extended Configuration */ /* Principles of Operation, SC24-5594-02 and SC24-5965-00 */ /* z/Architecture support - (c) Copyright Jan Jaeger, 1999-2007 */ // $Id: sie.c 5249 2009-03-06 15:33:02Z jj $ // // $Log$ // Revision 1.109 2008/08/21 18:34:48 fish // Fix i/o-interrupt-queue race condition // // Revision 1.108 2008/04/10 10:28:03 bernard // Allign instruction executing to real instructions (12 unrolled instead of 8) // // Revision 1.107 2008/04/09 09:03:58 bernard // EXRL instruction implementation // // Revision 1.106 2007/12/10 23:12:02 gsmith // Tweaks to OPTION_MIPS_COUNTING processing // // Revision 1.105 2007/06/23 00:04:15 ivan // Update copyright notices to include current year (2007) // // Revision 1.104 2007/06/06 22:14:58 gsmith // Fix SYNCHRONIZE_CPUS when numcpu > number of host processors - Greg // // Revision 1.103 2007/02/09 23:59:58 ivan // Fix some PER issue (tentative) // // Revision 1.102 2007/01/13 07:25:51 bernard // backout ccmask // // Revision 1.101 2007/01/12 15:25:00 bernard // ccmask phase 1 // // Revision 1.100 2007/01/04 23:12:04 gsmith // remove thunk calls for program_interrupt // // Revision 1.99 2006/12/21 22:39:39 gsmith // 21 Dec 2006 Range for s+, t+ - Greg Smith // // Revision 1.98 2006/12/20 04:26:20 gsmith // 19 Dec 2006 ip_all.pat - performance patch - Greg Smith // // Revision 1.97 2006/12/08 09:43:30 jj // Add CVS message log // #include "hstdinc.h" // #define SIE_DEBUG // #if !defined(_HENGINE_DLL_) #define _HENGINE_DLL_ #endif #if !defined(_SIE_C_) #define _SIE_C_ #endif #include "hercules.h" #include "opcode.h" #include "inline.h" #if defined(_FEATURE_SIE) #if !defined(_SIE_C) #define _SIE_C int s370_run_sie (REGS *regs); int s390_run_sie (REGS *regs); #if defined(_900) int z900_run_sie (REGS *regs); #endif /*defined(_900)*/ static int (* run_sie[GEN_MAXARCH]) (REGS *regs) = { #if defined(_370) s370_run_sie, #endif #if defined(_390) s390_run_sie, #endif #if defined(_900) z900_run_sie #endif }; #define GUESTREGS (regs->guestregs) #define STATEBK ((SIEBK *)GUESTREGS->siebk) #define SIE_I_STOP(_guestregs) \ ((_guestregs)->siebk->v & SIE_V_STOP) #define SIE_I_EXT(_guestregs) \ (((_guestregs)->siebk->v & SIE_V_EXT) \ && ((_guestregs)->psw.sysmask & PSW_EXTMASK)) #define SIE_I_HOST(_hostregs) IC_INTERRUPT_CPU(_hostregs) #if defined(SIE_DEBUG_PERFMON) #define SIE_PERF_MAXNEG 0x1F static int sie_perfmon[0x41 + SIE_PERF_MAXNEG]; #define SIE_PERFMON(_code) \ do { \ sie_perfmon[(_code) + SIE_PERF_MAXNEG] ++; \ } while(0) #define SIE_PERF_PGMINT \ (code <= 0 ? code : (((code-1) & 0x3F)+1)) void *sie_perfmon_disp() { static char *dbg_name[] = { /* -31 */ "SIE re-dispatch state descriptor", /* -30 */ "SIE exit", /* -29 */ "SIE run", /* -28 */ "SIE runloop 1", /* -27 */ "SIE runloop 2", /* -26 */ "SIE interrupt check", /* -25 */ "SIE execute instruction", /* -24 */ "SIE unrolled execute", /* -23 */ NULL, /* -22 */ NULL, /* -21 */ NULL, /* -20 */ NULL, /* -19 */ NULL, /* -18 */ NULL, /* -17 */ "SIE intercept I/O instruction", /* -16 */ "SIE intercept I/O interrupt pending", /* -15 */ "SIE intercept I/O interrupt", /* -14 */ "SIE intercept PER interrupt", /* -13 */ "SIE validity check", /* -12 */ "SIE intercept external interrupt pending", /* -11 */ "SIE intercept machine check interrupt", /* -10 */ "SIE intercept restart interrupt", /* -9 */ "SIE intercept stop request", /* -8 */ "SIE intercept virtual machine wait", /* -7 */ "SIE intercept I/O interrupt request", /* -6 */ "SIE intercept external interrupt request", /* -5 */ "SIE intercept instruction completion", /* -4 */ "SIE intercept instruction", /* -3 */ "SIE host program interrupt", /* -2 */ "SIE host interrupt", /* -1 */ "SIE no intercept", /* 0 */ "SIE entry", /* 01 */ "SIE intercept Operation exception", /* 02 */ "SIE intercept Privileged-operation exception", /* 03 */ "SIE intercept Execute exception", /* 04 */ "SIE intercept Protection exception", /* 05 */ "SIE intercept Addressing exception", /* 06 */ "SIE intercept Specification exception", /* 07 */ "SIE intercept Data exception", /* 08 */ "SIE intercept Fixed-point-overflow exception", /* 09 */ "SIE intercept Fixed-point-divide exception", /* 0A */ "SIE intercept Decimal-overflow exception", /* 0B */ "SIE intercept Decimal-divide exception", /* 0C */ "SIE intercept HFP-exponent-overflow exception", /* 0D */ "SIE intercept HFP-exponent-underflow exception", /* 0E */ "SIE intercept HFP-significance exception", /* 0F */ "SIE intercept HFP-floating-point-divide exception", /* 10 */ "SIE intercept Segment-translation exception", /* 11 */ "SIE intercept Page-translation exception", /* 12 */ "SIE intercept Translation-specification exception", /* 13 */ "SIE intercept Special-operation exception", /* 14 */ "SIE intercept Pseudo-page-fault exception", /* 15 */ "SIE intercept Operand exception", /* 16 */ "SIE intercept Trace-table exception", /* 17 */ "SIE intercept ASN-translation exception", /* 18 */ "SIE intercept Page access exception", /* 19 */ "SIE intercept Vector/Crypto operation exception", /* 1A */ "SIE intercept Page state exception", /* 1B */ "SIE intercept Page transition exception", /* 1C */ "SIE intercept Space-switch event", /* 1D */ "SIE intercept Square-root exception", /* 1E */ "SIE intercept Unnormalized-operand exception", /* 1F */ "SIE intercept PC-translation specification exception", /* 20 */ "SIE intercept AFX-translation exception", /* 21 */ "SIE intercept ASX-translation exception", /* 22 */ "SIE intercept LX-translation exception", /* 23 */ "SIE intercept EX-translation exception", /* 24 */ "SIE intercept Primary-authority exception", /* 25 */ "SIE intercept LFX-translation exception", /* 26 */ "SIE intercept LSX-translation exception", /* 27 */ "SIE intercept Control-switch exception", /* 28 */ "SIE intercept ALET-specification exception", /* 29 */ "SIE intercept ALEN-translation exception", /* 2A */ "SIE intercept ALE-sequence exception", /* 2B */ "SIE intercept ASTE-validity exception", /* 2C */ "SIE intercept ASTE-sequence exception", /* 2D */ "SIE intercept Extended-authority exception", /* 2E */ "SIE intercept LSTE-sequence exception", /* 2F */ "SIE intercept ASTE-instance exception", /* 30 */ "SIE intercept Stack-full exception", /* 31 */ "SIE intercept Stack-empty exception", /* 32 */ "SIE intercept Stack-specification exception", /* 33 */ "SIE intercept Stack-type exception", /* 34 */ "SIE intercept Stack-operation exception", /* 35 */ NULL, /* 36 */ NULL, /* 37 */ NULL, /* 38 */ "SIE intercept ASCE-type exception", /* 39 */ "SIE intercept Region-first-translation exception", /* 3A */ "SIE intercept Region-second-translation exception", /* 3B */ "SIE intercept Region-third-translation exception", /* 3C */ NULL, /* 3D */ NULL, /* 3E */ NULL, /* 3F */ NULL, /* 40 */ "SIE intercept Monitor event" }; if(sie_perfmon[SIE_PERF_ENTER+SIE_PERF_MAXNEG]) { int i; for(i = 0; i < 0x61; i++) if(sie_perfmon[i]) logmsg("%9u: %s\n",sie_perfmon[i],dbg_name[i]); logmsg("%9u: Average instructions/SIE invocation\n", (sie_perfmon[SIE_PERF_EXEC+SIE_PERF_MAXNEG] + sie_perfmon[SIE_PERF_EXEC_U+SIE_PERF_MAXNEG]*7) / sie_perfmon[SIE_PERF_ENTER+SIE_PERF_MAXNEG]); } else logmsg("No SIE performance data\n"); } #else #define SIE_PERFMON(_code) #endif #endif /*!defined(_SIE_C)*/ #undef SIE_I_WAIT #if defined(_FEATURE_WAITSTATE_ASSIST) #define SIE_I_WAIT(_guestregs) \ (WAITSTATE(&(_guestregs)->psw) && !((_guestregs)->siebk->ec[0] & SIE_EC0_WAIA)) #else #define SIE_I_WAIT(_guestregs) \ (WAITSTATE(&(_guestregs)->psw)) #endif #undef SIE_I_IO #if defined(FEATURE_BCMODE) #define SIE_I_IO(_guestregs) \ (((_guestregs)->siebk->v & SIE_V_IO) \ && ((_guestregs)->psw.sysmask \ & (ECMODE(&(_guestregs)->psw) ? PSW_IOMASK : 0xFE) )) #else /*!defined(FEATURE_BCMODE)*/ #define SIE_I_IO(_guestregs) \ (((_guestregs)->siebk->v & SIE_V_IO) \ && ((_guestregs)->psw.sysmask & PSW_IOMASK )) #endif /*!defined(FEATURE_BCMODE)*/ #endif /*defined(_FEATURE_SIE)*/ #if defined(FEATURE_INTERPRETIVE_EXECUTION) /*-------------------------------------------------------------------*/ /* B214 SIE - Start Interpretive Execution [S] */ /*-------------------------------------------------------------------*/ DEF_INST(start_interpretive_execution) { int b2; /* Values of R fields */ RADR effective_addr2; /* address of state desc. */ int n; /* Loop counter */ U16 lhcpu; /* Last Host CPU address */ int icode = 0; /* Interception code */ U64 dreg; S(inst, regs, b2, effective_addr2); SIE_INTERCEPT(regs); PRIV_CHECK(regs); PTT(PTT_CL_SIE,"SIE", regs->GR_L(14), regs->GR_L(15), (U32)(effective_addr2 & 0xffffffff)); SIE_PERFMON(SIE_PERF_ENTER); #if !defined(FEATURE_ESAME) && !defined(FEATURE_MULTIPLE_CONTROLLED_DATA_SPACE) if(!regs->psw.amode || !PRIMARY_SPACE_MODE(&(regs->psw))) ARCH_DEP(program_interrupt) (regs, PGM_SPECIAL_OPERATION_EXCEPTION); #endif if((effective_addr2 & (sizeof(SIEBK)-1)) != 0 #if defined(FEATURE_ESAME) || (effective_addr2 & 0xFFFFFFFFFFFFF000ULL) == 0 || (effective_addr2 & 0xFFFFFFFFFFFFF000ULL) == regs->PX) #else /*!defined(FEATURE_ESAME)*/ || (effective_addr2 & 0x7FFFF000) == 0 || (effective_addr2 & 0x7FFFF000) == regs->PX) #endif /*!defined(FEATURE_ESAME)*/ ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION); /* Perform serialization and checkpoint synchronization */ PERFORM_SERIALIZATION (regs); PERFORM_CHKPT_SYNC (regs); #if defined(SIE_DEBUG) logmsg(_("SIE: state descriptor " F_RADR "\n"),effective_addr2); ARCH_DEP(display_inst) (regs, regs->instinvalid ? NULL : regs->ip); #endif /*defined(SIE_DEBUG)*/ if(effective_addr2 > regs->mainlim - (sizeof(SIEBK)-1)) ARCH_DEP(program_interrupt) (regs, PGM_ADDRESSING_EXCEPTION); /* * As long as regs->sie_active is off, no serialization is * required for GUESTREGS. sie_active should always be off here. * Any other thread looking at sie_active holds the intlock. */ if (regs->sie_active) { OBTAIN_INTLOCK(regs); regs->sie_active = 0; RELEASE_INTLOCK(regs); } /* Initialize guestregs if first time */ if (GUESTREGS == NULL) { GUESTREGS = calloc (sizeof(REGS), 1); if (GUESTREGS == NULL) { logmsg (_("HHCCP079E CPU%4.4X: calloc failed for sie regs: %s\n"), regs->cpuad, strerror(errno)); #if !defined(NO_SIGABEND_HANDLER) signal_thread(sysblk.cputid[regs->cpuad], SIGUSR1); #endif return; } cpu_init (regs->cpuad, GUESTREGS, regs); } /* Direct pointer to state descriptor block */ GUESTREGS->siebk = (void*)(regs->mainstor + effective_addr2); #if defined(FEATURE_ESAME) if (STATEBK->mx & SIE_MX_ESAME) { GUESTREGS->arch_mode = ARCH_900; GUESTREGS->program_interrupt = &z900_program_interrupt; GUESTREGS->trace_br = (func)&z900_trace_br; icode = z900_load_psw(GUESTREGS, STATEBK->psw); } #else /*!defined(FEATURE_ESAME)*/ if (STATEBK->m & SIE_M_370) { #if defined(_370) GUESTREGS->arch_mode = ARCH_370; GUESTREGS->program_interrupt = &s370_program_interrupt; icode = s370_load_psw(GUESTREGS, STATEBK->psw); #else /* Validity intercept when 370 mode not installed */ SIE_SET_VI(SIE_VI_WHO_CPU, SIE_VI_WHEN_SIENT, SIE_VI_WHY_370NI, GUESTREGS); STATEBK->c = SIE_C_VALIDITY; return; #endif } #endif /*!defined(FEATURE_ESAME)*/ else #if !defined(FEATURE_ESAME) if (STATEBK->m & SIE_M_XA) #endif /*!defined(FEATURE_ESAME)*/ { GUESTREGS->arch_mode = ARCH_390; GUESTREGS->program_interrupt = &s390_program_interrupt; GUESTREGS->trace_br = (func)&s390_trace_br; icode = s390_load_psw(GUESTREGS, STATEBK->psw); } #if !defined(FEATURE_ESAME) else { /* Validity intercept for invalid mode */ SIE_SET_VI(SIE_VI_WHO_CPU, SIE_VI_WHEN_SIENT, SIE_VI_WHY_MODE, GUESTREGS); STATEBK->c = SIE_C_VALIDITY; return; } #endif /*!defined(FEATURE_ESAME)*/ /* Prefered guest indication */ GUESTREGS->sie_pref = (STATEBK->m & SIE_M_VR) ? 1 : 0; /* Load prefix from state descriptor */ FETCH_FW(GUESTREGS->PX, STATEBK->prefix); GUESTREGS->PX &= #if !defined(FEATURE_ESAME) PX_MASK; #else /*defined(FEATURE_ESAME)*/ (GUESTREGS->arch_mode == ARCH_900) ? PX_MASK : 0x7FFFF000; #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_REGION_RELOCATE) if(STATEBK->mx & SIE_MX_RRF) { RADR mso, msl, eso = 0, esl = 0; if(STATEBK->zone >= FEATURE_SIE_MAXZONES) { /* Validity intercept for invalid zone */ SIE_SET_VI(SIE_VI_WHO_CPU, SIE_VI_WHEN_SIENT, SIE_VI_WHY_AZNNI, GUESTREGS); STATEBK->c = SIE_C_VALIDITY; return; } mso = sysblk.zpb[STATEBK->zone].mso << 20; msl = (sysblk.zpb[STATEBK->zone].msl << 20) | 0xFFFFF; eso = sysblk.zpb[STATEBK->zone].eso << 20; esl = (sysblk.zpb[STATEBK->zone].esl << 20) | 0xFFFFF; if(mso > msl) { /* Validity intercept for invalid zone */ SIE_SET_VI(SIE_VI_WHO_CPU, SIE_VI_WHEN_SIENT, SIE_VI_WHY_MSDEF, GUESTREGS); STATEBK->c = SIE_C_VALIDITY; return; } /* Ensure addressing exceptions on incorrect zone defs */ if(mso > regs->mainlim || msl > regs->mainlim) mso = msl = 0; #if defined(SIE_DEBUG) logmsg(_("SIE: zone %d: mso=" F_RADR " msl=" F_RADR "\n"), STATEBK->zone, mso, msl); #endif /*defined(SIE_DEBUG)*/ GUESTREGS->sie_pref = 1; GUESTREGS->sie_mso = 0; GUESTREGS->mainstor = &(sysblk.mainstor[mso]); GUESTREGS->mainlim = msl - mso; GUESTREGS->storkeys = &(STORAGE_KEY(mso, &sysblk)); GUESTREGS->sie_xso = eso; GUESTREGS->sie_xsl = esl; GUESTREGS->sie_xso *= (XSTORE_INCREMENT_SIZE >> XSTORE_PAGESHIFT); GUESTREGS->sie_xsl *= (XSTORE_INCREMENT_SIZE >> XSTORE_PAGESHIFT); } else #endif /*defined(FEATURE_REGION_RELOCATE)*/ { GUESTREGS->mainstor = sysblk.mainstor; GUESTREGS->storkeys = sysblk.storkeys; if(STATEBK->zone) { /* Validity intercept for invalid zone */ SIE_SET_VI(SIE_VI_WHO_CPU, SIE_VI_WHEN_SIENT, SIE_VI_WHY_AZNNZ, GUESTREGS); STATEBK->c = SIE_C_VALIDITY; return; } #if defined(FEATURE_ESAME) /* Load main storage origin */ FETCH_DW(GUESTREGS->sie_mso,STATEBK->mso); GUESTREGS->sie_mso &= SIE2_MS_MASK; /* Load main storage extend */ FETCH_DW(GUESTREGS->mainlim,STATEBK->mse); GUESTREGS->mainlim |= ~SIE2_MS_MASK; if(GUESTREGS->sie_mso > GUESTREGS->mainlim) { SIE_SET_VI(SIE_VI_WHO_CPU, SIE_VI_WHEN_SIENT, SIE_VI_WHY_MSDEF, GUESTREGS); STATEBK->c = SIE_C_VALIDITY; return; } /* Calculate main storage size */ GUESTREGS->mainlim -= GUESTREGS->sie_mso; #else /*!defined(FEATURE_ESAME)*/ /* Load main storage origin */ FETCH_HW(GUESTREGS->sie_mso,STATEBK->mso); GUESTREGS->sie_mso <<= 16; /* Load main storage extend */ FETCH_HW(GUESTREGS->mainlim,STATEBK->mse); GUESTREGS->mainlim = ((GUESTREGS->mainlim + 1) << 16) - 1; #endif /*!defined(FEATURE_ESAME)*/ /* Load expanded storage origin */ GUESTREGS->sie_xso = STATEBK->xso[0] << 16 | STATEBK->xso[1] << 8 | STATEBK->xso[2]; GUESTREGS->sie_xso *= (XSTORE_INCREMENT_SIZE >> XSTORE_PAGESHIFT); /* Load expanded storage limit */ GUESTREGS->sie_xsl = STATEBK->xsl[0] << 16 | STATEBK->xsl[1] << 8 | STATEBK->xsl[2]; GUESTREGS->sie_xsl *= (XSTORE_INCREMENT_SIZE >> XSTORE_PAGESHIFT); } /* Validate Guest prefix */ if(GUESTREGS->PX > GUESTREGS->mainlim) { SIE_SET_VI(SIE_VI_WHO_CPU, SIE_VI_WHEN_SIENT, SIE_VI_WHY_PFOUT, GUESTREGS); STATEBK->c = SIE_C_VALIDITY; return; } /* System Control Area Origin */ FETCH_FW(GUESTREGS->sie_scao, STATEBK->scao); if(GUESTREGS->sie_scao > regs->mainlim) { SIE_SET_VI(SIE_VI_WHO_CPU, SIE_VI_WHEN_SIENT, SIE_VI_WHY_SCADR, GUESTREGS); STATEBK->c = SIE_C_VALIDITY; return; } /* Validate MSO */ if (GUESTREGS->sie_mso) { /* Preferred guest must have zero MSO */ if (GUESTREGS->sie_pref) { SIE_SET_VI(SIE_VI_WHO_CPU, SIE_VI_WHEN_SIENT, SIE_VI_WHY_MSONZ, GUESTREGS); STATEBK->c = SIE_C_VALIDITY; return; } /* MCDS guest must have zero MSO */ if (STATEBK->mx & SIE_MX_XC) { SIE_SET_VI(SIE_VI_WHO_CPU, SIE_VI_WHEN_SIENT, SIE_VI_WHY_MSODS, GUESTREGS); STATEBK->c = SIE_C_VALIDITY; return; } } #if !defined(FEATURE_ESAME) /* Reference and Change Preservation Origin */ FETCH_FW(GUESTREGS->sie_rcpo, STATEBK->rcpo); if (!GUESTREGS->sie_rcpo && !GUESTREGS->sie_pref) { SIE_SET_VI(SIE_VI_WHO_CPU, SIE_VI_WHEN_SIENT, SIE_VI_WHY_RCZER, GUESTREGS); STATEBK->c = SIE_C_VALIDITY; return; } #endif /*!defined(FEATURE_ESAME)*/ /* Load the CPU timer */ FETCH_DW(dreg, STATEBK->cputimer); set_cpu_timer(GUESTREGS, dreg); /* Load the TOD clock offset for this guest */ FETCH_DW(GUESTREGS->sie_epoch, STATEBK->epoch); GUESTREGS->tod_epoch = regs->tod_epoch + (GUESTREGS->sie_epoch >> 8); /* Load the clock comparator */ FETCH_DW(GUESTREGS->clkc, STATEBK->clockcomp); GUESTREGS->clkc >>= 8; /* Internal Hercules format */ /* Load TOD Programmable Field */ FETCH_HW(GUESTREGS->todpr, STATEBK->todpf); /* Load the guest registers */ memcpy(GUESTREGS->gr, regs->gr, 14 * sizeof(regs->gr[0])); memcpy(GUESTREGS->ar, regs->ar, 16 * sizeof(regs->ar[0])); memcpy(GUESTREGS->fpr, regs->fpr, 32 * sizeof(regs->fpr[0])); #if defined(FEATURE_BINARY_FLOATING_POINT) GUESTREGS->fpc = regs->fpc; #endif /*defined(FEATURE_BINARY_FLOATING_POINT)*/ /* Load GR14 */ FETCH_W(GUESTREGS->GR(14), STATEBK->gr14); /* Load GR15 */ FETCH_W(GUESTREGS->GR(15), STATEBK->gr15); /* Load control registers */ for(n = 0;n < 16; n++) FETCH_W(GUESTREGS->CR(n), STATEBK->cr[n]); FETCH_HW(lhcpu, STATEBK->lhcpu); /* * If this is not the last host cpu that dispatched this state * descriptor then clear the guest TLB entries */ if (regs->cpuad != lhcpu || SIE_STATE(GUESTREGS) != effective_addr2) { SIE_PERFMON(SIE_PERF_ENTER_F); /* Absolute address of state descriptor block */ SIE_STATE(GUESTREGS) = effective_addr2; /* Update Last Host CPU address */ STORE_HW(STATEBK->lhcpu, regs->cpuad); /* Purge guest TLB entries */ ARCH_DEP(purge_tlb) (GUESTREGS); ARCH_DEP(purge_alb) (GUESTREGS); } /* Initialize interrupt mask and state */ SET_IC_MASK(GUESTREGS); SET_IC_INITIAL_STATE(GUESTREGS); SET_IC_PER(GUESTREGS); /* Initialize accelerated address lookup values */ SET_AEA_MODE(GUESTREGS); SET_AEA_COMMON(GUESTREGS); INVALIDATE_AIA(GUESTREGS); GUESTREGS->tracing = regs->tracing; /* * Do setjmp(progjmp) because translate_addr() may result in * longjmp(progjmp) for addressing exceptions. */ if(!setjmp(GUESTREGS->progjmp)) { /* * Set sie_active to 1. This means other threads may now * access guestregs when holding intlock. * This is the *only* place sie_active is set to one. */ OBTAIN_INTLOCK(regs); regs->sie_active = 1; RELEASE_INTLOCK(regs); /* Get PSA pointer and ensure PSA is paged in */ if(GUESTREGS->sie_pref) { GUESTREGS->psa = (PSA_3XX*)(GUESTREGS->mainstor + GUESTREGS->PX); GUESTREGS->sie_px = GUESTREGS->PX; } else { if (ARCH_DEP(translate_addr) (GUESTREGS->sie_mso + GUESTREGS->PX, USE_PRIMARY_SPACE, regs, ACCTYPE_SIE)) { SIE_SET_VI(SIE_VI_WHO_CPU, SIE_VI_WHEN_SIENT, SIE_VI_WHY_PFACC, GUESTREGS); STATEBK->c = SIE_C_VALIDITY; OBTAIN_INTLOCK(regs); regs->sie_active = 0; RELEASE_INTLOCK(regs); return; } /* Convert host real address to host absolute address */ GUESTREGS->sie_px = APPLY_PREFIXING (regs->dat.raddr, regs->PX); if (regs->dat.protect || GUESTREGS->sie_px > regs->mainlim) { SIE_SET_VI(SIE_VI_WHO_CPU, SIE_VI_WHEN_SIENT, SIE_VI_WHY_PFACC, GUESTREGS); STATEBK->c = SIE_C_VALIDITY; OBTAIN_INTLOCK(regs); regs->sie_active = 0; RELEASE_INTLOCK(regs); return; } GUESTREGS->psa = (PSA_3XX*)(GUESTREGS->mainstor + GUESTREGS->sie_px); } /* Intialize guest timers */ OBTAIN_INTLOCK(regs); /* CPU timer */ if(CPU_TIMER(GUESTREGS) < 0) ON_IC_PTIMER(GUESTREGS); /* Clock comparator */ if( TOD_CLOCK(GUESTREGS) > GUESTREGS->clkc ) ON_IC_CLKC(GUESTREGS); #if !defined(FEATURE_ESAME) /* Interval timer if S/370 and timer is enabled */ if((STATEBK->m & SIE_M_370) && !(STATEBK->m & SIE_M_ITMOF)) { S32 itimer, olditimer; U32 residue; /* Set the interval timer pending according to the T bit in the state control */ if(STATEBK->s & SIE_S_T) ON_IC_ITIMER(GUESTREGS); /* Fetch the residu from the state descriptor */ FETCH_FW(residue,STATEBK->residue); /* Fetch the timer value from location 80 */ FETCH_FW(olditimer,GUESTREGS->psa->inttimer); /* Bit position 23 of the interval timer is decremented once for each multiple of 3,333 usecs containded in bit position 0-19 of the residue counter */ itimer = olditimer - ((residue / 3333) >> 4); /* Store the timer back */ STORE_FW(GUESTREGS->psa->inttimer, itimer); /* Set interrupt flag and interval timer interrupt pending if the interval timer went from positive to negative */ if (itimer < 0 && olditimer >= 0) ON_IC_ITIMER(GUESTREGS); } #endif /*!defined(FEATURE_ESAME)*/ RELEASE_INTLOCK(regs); /* Early exceptions associated with the guest load_psw() */ if(icode) GUESTREGS->program_interrupt (GUESTREGS, icode); /* Run SIE in guests architecture mode */ icode = run_sie[GUESTREGS->arch_mode] (regs); } /* if (setjmp(GUESTREGS->progjmp)) */ ARCH_DEP(sie_exit) (regs, icode); /* Perform serialization and checkpoint synchronization */ PERFORM_SERIALIZATION (regs); PERFORM_CHKPT_SYNC (regs); longjmp(regs->progjmp, SIE_NO_INTERCEPT); } /* Exit SIE state, restore registers and update the state descriptor */ void ARCH_DEP(sie_exit) (REGS *regs, int code) { int n; #if defined(OPTION_PTTRACE) if(pttclass & PTT_CL_SIE) { U32 nt1 = 0, nt2 = 0; BYTE *ip; if(!GUESTREGS->instinvalid) { if(GUESTREGS->ip[0] == 0x44 #if defined(FEATURE_EXECUTE_EXTENSIONS_FACILITY) || (GUESTREGS->ip[0] == 0xc6 && !(GUESTREGS->ip[1] & 0x0f)) #endif /*defined(FEATURE_EXECUTE_EXTENSIONS_FACILITY)*/ ) { ip = GUESTREGS->exinst; nt2 = (GUESTREGS->ip[0] == 0x44) ? 0x44 : ((0xc6 << 8) | (GUESTREGS->ip[1] & 0x0f)); } else ip = GUESTREGS->ip; nt1 = (ip[0] << 24) | (ip[1] << 16); if(ILC(ip[0]) > 2) nt1 |= (ip[2] << 8) | ip[3]; if(ILC(ip[0]) > 4) nt2 |= (ip[4] << 24) | (ip[5] << 16); } PTT(PTT_CL_SIE,"*SIE", nt1, nt2, code); } #endif /*defined(OPTION_PTTRACE)*/ #if defined(SIE_DEBUG) logmsg(_("SIE: interception code %d\n"),code); ARCH_DEP(display_inst) (GUESTREGS, GUESTREGS->instinvalid ? NULL : GUESTREGS->ip); #endif /*defined(SIE_DEBUG)*/ SIE_PERFMON(SIE_PERF_EXIT); SIE_PERFMON(SIE_PERF_PGMINT); /* Indicate we have left SIE mode */ OBTAIN_INTLOCK(regs); regs->sie_active = 0; RELEASE_INTLOCK(regs); /* zeroize interception status */ STATEBK->f = 0; switch(code > 0 ? code & ~PGM_PER_EVENT : code) { case SIE_HOST_INTERRUPT: /* If a host interrupt is pending then backup the psw and exit */ SET_PSW_IA(regs); UPD_PSW_IA (regs, regs->psw.IA -REAL_ILC(regs)); break; case SIE_HOST_PGMINT: break; case SIE_INTERCEPT_INST: STATEBK->c = SIE_C_INST; break; case SIE_INTERCEPT_PER: STATEBK->f |= SIE_F_IF; /*fallthru*/ case SIE_INTERCEPT_INSTCOMP: STATEBK->c = SIE_C_PGMINST; break; case SIE_INTERCEPT_WAIT: STATEBK->c = SIE_C_WAIT; break; case SIE_INTERCEPT_STOPREQ: STATEBK->c = SIE_C_STOPREQ; break; case SIE_INTERCEPT_IOREQ: STATEBK->c = SIE_C_IOREQ; break; case SIE_INTERCEPT_EXTREQ: STATEBK->c = SIE_C_EXTREQ; break; case SIE_INTERCEPT_EXT: STATEBK->c = SIE_C_EXTINT; break; case SIE_INTERCEPT_VALIDITY: STATEBK->c = SIE_C_VALIDITY; break; case SIE_INTERCEPT_IOINT: case SIE_INTERCEPT_IOINTP: STATEBK->c = SIE_C_IOINT; break; case SIE_INTERCEPT_IOINST: STATEBK->c = SIE_C_IOINST; break; case PGM_OPERATION_EXCEPTION: STATEBK->c = SIE_C_OPEREXC; break; default: STATEBK->c = SIE_C_PGMINT; break; } /* Save CPU timer */ STORE_DW(STATEBK->cputimer, cpu_timer(GUESTREGS)); /* Save clock comparator */ STORE_DW(STATEBK->clockcomp, GUESTREGS->clkc << 8); #if defined(_FEATURE_INTERVAL_TIMER) && !defined(FEATURE_ESAME) /* If this is a S/370 guest, and the interval timer is enabled then save the timer state control bit */ if( (STATEBK->m & SIE_M_370) && !(STATEBK->m & SIE_M_ITMOF)) { /* Save the shadow interval timer */ s370_store_int_timer(regs); if(IS_IC_ITIMER(GUESTREGS)) STATEBK->s |= SIE_S_T; else STATEBK->s &= ~SIE_S_T; } #endif /*defined(_FEATURE_INTERVAL_TIMER) && !defined(FEATURE_ESAME)*/ /* Save TOD Programmable Field */ STORE_HW(STATEBK->todpf, GUESTREGS->todpr); /* Save GR14 */ STORE_W(STATEBK->gr14, GUESTREGS->GR(14)); /* Save GR15 */ STORE_W(STATEBK->gr15, GUESTREGS->GR(15)); /* Store the PSW */ if(GUESTREGS->arch_mode == ARCH_390) s390_store_psw (GUESTREGS, STATEBK->psw); #if defined(_370) || defined(_900) else #endif #if defined(FEATURE_ESAME) z900_store_psw (GUESTREGS, STATEBK->psw); #else /*!defined(FEATURE_ESAME)*/ #if defined(_370) s370_store_psw (GUESTREGS, STATEBK->psw); #endif #endif /*!defined(FEATURE_ESAME)*/ /* save control registers */ for(n = 0;n < 16; n++) STORE_W(STATEBK->cr[n], GUESTREGS->CR(n)); /* Update the approprate host registers */ memcpy(regs->gr, GUESTREGS->gr, 14 * sizeof(regs->gr[0])); memcpy(regs->ar, GUESTREGS->ar, 16 * sizeof(regs->ar[0])); memcpy(regs->fpr, GUESTREGS->fpr, 32 * sizeof(regs->fpr[0])); #if defined(FEATURE_BINARY_FLOATING_POINT) regs->fpc = GUESTREGS->fpc; #endif /*defined(FEATURE_BINARY_FLOATING_POINT)*/ INVALIDATE_AIA(regs); SET_AEA_MODE(regs); /* Zeroize the interruption parameters */ memset(STATEBK->ipa, 0, 10); if( STATEBK->c == SIE_C_INST || STATEBK->c == SIE_C_PGMINST || STATEBK->c == SIE_C_OPEREXC || STATEBK->c == SIE_C_IOINST ) { /* Indicate interception format 2 */ STATEBK->f |= SIE_F_IN; #if defined(_FEATURE_PER) /* Handle PER or concurrent PER event */ if( OPEN_IC_PER(GUESTREGS) && ECMODE(&GUESTREGS->psw) && (GUESTREGS->psw.sysmask & PSW_PERMODE) ) { PSA *psa; #if defined(_FEATURE_PER2) GUESTREGS->perc |= OPEN_IC_PER(GUESTREGS) >> ((32 - IC_CR9_SHIFT) - 16); /* Positions 14 and 15 contain zeros if a storage alteration event was not indicated */ if( !(OPEN_IC_PER_SA(GUESTREGS)) || (OPEN_IC_PER_STURA(GUESTREGS)) ) GUESTREGS->perc &= 0xFFFC; #endif /*defined(_FEATURE_PER2)*/ /* Point to PSA fields in state descriptor */ psa = (void*)(regs->mainstor + SIE_STATE(GUESTREGS) + SIE_IP_PSA_OFFSET); STORE_HW(psa->perint, GUESTREGS->perc); STORE_W(psa->peradr, GUESTREGS->peradr); } if (IS_IC_PER_IF(GUESTREGS)) STATEBK->f |= SIE_F_IF; /* Reset any pending PER indication */ OFF_IC_PER(GUESTREGS); #endif /*defined(_FEATURE_PER)*/ /* Backup to the previous instruction */ GUESTREGS->ip -= REAL_ILC(GUESTREGS); if (GUESTREGS->ip < GUESTREGS->aip) GUESTREGS->ip = GUESTREGS->inst; /* Update interception parameters in the state descriptor */ if(GUESTREGS->ip[0] == 0x44 #if defined(FEATURE_EXECUTE_EXTENSIONS_FACILITY) || (GUESTREGS->ip[0] == 0xc6 && !(GUESTREGS->ip[1] & 0x0f)) #endif /*defined(FEATURE_EXECUTE_EXTENSIONS_FACILITY)*/ ) { int exilc; STATEBK->f |= SIE_F_EX; exilc = ILC(GUESTREGS->exinst[0]); memcpy(STATEBK->ipa, GUESTREGS->exinst, exilc); } else { if(!GUESTREGS->instinvalid) memcpy(STATEBK->ipa, GUESTREGS->ip, ILC(GUESTREGS->ip[0])); } } } #endif /*defined(FEATURE_INTERPRETIVE_EXECUTION)*/ #if defined(_FEATURE_SIE) /* Execute guest instructions */ int ARCH_DEP(run_sie) (REGS *regs) { int icode; /* SIE longjmp intercept code */ BYTE oldv; /* siebk->v change check reference */ BYTE *ip; /* instruction pointer */ SIE_PERFMON(SIE_PERF_RUNSIE); #if defined(_FEATURE_PER) /* Reset any PER pending indication */ OFF_IC_PER(GUESTREGS); #endif /*defined(_FEATURE_PER)*/ #ifdef FEATURE_INTERVAL_TIMER /* Load the shadow interval timer */ { S32 itimer; FETCH_FW(itimer,GUESTREGS->psa->inttimer); set_int_timer(GUESTREGS, itimer); } #endif do { SIE_PERFMON(SIE_PERF_RUNLOOP_1); if(!(icode = setjmp(GUESTREGS->progjmp))) do { SIE_PERFMON(SIE_PERF_RUNLOOP_2); /* Keep a copy if SIEBK 'v' field for later checks */ oldv=GUESTREGS->siebk->v; /* Set `execflag' to 0 in case EXecuted instruction did progjmp */ GUESTREGS->execflag = 0; if( SIE_I_STOP(GUESTREGS) || SIE_I_EXT(GUESTREGS) || SIE_I_IO(GUESTREGS) ) break; if( SIE_IC_INTERRUPT_CPU(GUESTREGS) ) { SIE_PERFMON(SIE_PERF_INTCHECK); /* Process PER program interrupts */ if( OPEN_IC_PER(GUESTREGS) ) ARCH_DEP(program_interrupt) (GUESTREGS, PGM_PER_EVENT); OBTAIN_INTLOCK(regs); OFF_IC_INTERRUPT(GUESTREGS); /* Set psw.IA and invalidate the aia */ INVALIDATE_AIA(GUESTREGS); if( OPEN_IC_EXTPENDING(GUESTREGS) ) ARCH_DEP(perform_external_interrupt) (GUESTREGS); if( (STATEBK->ec[0] & SIE_EC0_IOA) && OPEN_IC_IOPENDING(GUESTREGS) ) { PERFORM_SERIALIZATION (GUESTREGS); PERFORM_CHKPT_SYNC (GUESTREGS); ARCH_DEP (perform_io_interrupt) (GUESTREGS); } #if defined(_FEATURE_WAITSTATE_ASSIST) /* Wait state assist */ if (WAITSTATE(&GUESTREGS->psw) && (STATEBK->ec[0] & SIE_EC0_WAIA)) { /* Test for disabled wait PSW and issue message */ if( IS_IC_DISABLED_WAIT_PSW(GUESTREGS) ) { RELEASE_INTLOCK(regs); longjmp(GUESTREGS->progjmp, SIE_INTERCEPT_WAIT); } if( SIE_I_STOP(GUESTREGS) || SIE_I_EXT(GUESTREGS) || SIE_I_IO(GUESTREGS) || SIE_I_HOST(regs) ) { RELEASE_INTLOCK(regs); break; } SET_AEA_MODE(GUESTREGS); { struct timespec waittime; U64 now = host_tod(); waittime.tv_sec = now / 1000000; waittime.tv_nsec = ((now % 1000000) + 3333) * 1000; #ifdef OPTION_MIPS_COUNTING regs->waittod = now; #endif sysblk.waiting_mask |= regs->cpubit; sysblk.intowner = LOCK_OWNER_NONE; timed_wait_condition (®s->intcond, &sysblk.intlock, &waittime); while (sysblk.syncing) wait_condition (&sysblk.sync_bc_cond, &sysblk.intlock); sysblk.intowner = regs->cpuad; sysblk.waiting_mask ^= regs->cpubit; #ifdef OPTION_MIPS_COUNTING regs->waittime += host_tod() - regs->waittod; regs->waittod = 0; #endif } RELEASE_INTLOCK(regs); break; } /* end if(wait) */ #endif RELEASE_INTLOCK(regs); } if( SIE_I_WAIT(GUESTREGS) ) break; ip = INSTRUCTION_FETCH(GUESTREGS, 0); #if defined(SIE_DEBUG) /* Display the instruction */ ARCH_DEP(display_inst) (GUESTREGS, GUESTREGS->instinvalid ? NULL : ip); #endif /*defined(SIE_DEBUG)*/ SIE_PERFMON(SIE_PERF_EXEC); GUESTREGS->instcount = 1; EXECUTE_INSTRUCTION(ip, GUESTREGS); do { SIE_PERFMON(SIE_PERF_EXEC_U); UNROLLED_EXECUTE(GUESTREGS); UNROLLED_EXECUTE(GUESTREGS); UNROLLED_EXECUTE(GUESTREGS); UNROLLED_EXECUTE(GUESTREGS); UNROLLED_EXECUTE(GUESTREGS); UNROLLED_EXECUTE(GUESTREGS); GUESTREGS->instcount += 12; UNROLLED_EXECUTE(GUESTREGS); UNROLLED_EXECUTE(GUESTREGS); UNROLLED_EXECUTE(GUESTREGS); UNROLLED_EXECUTE(GUESTREGS); UNROLLED_EXECUTE(GUESTREGS); UNROLLED_EXECUTE(GUESTREGS); } while( likely(!SIE_I_HOST(regs) && GUESTREGS->siebk->v==oldv && !SIE_INTERRUPT_PENDING(GUESTREGS))); /******************************************/ /* ABOVE : Keep executing instructions */ /* in a tight loop until... */ /* - A Host Interrupt is made pending */ /* - An external source changes siebk->v */ /* - A guest interrupt is made pending */ /******************************************/ regs->instcount += GUESTREGS->instcount; } while( unlikely(!SIE_I_HOST(regs) && !SIE_I_WAIT(GUESTREGS) && !SIE_I_EXT(GUESTREGS) && !SIE_I_IO(GUESTREGS) && !SIE_INTERRUPT_PENDING(GUESTREGS))); /******************************************/ /* ABOVE : Remain in SIE until... */ /* - A Host Interrupt is made pending */ /* - A Sie defined irpt becomes enabled */ /* - A guest interrupt is made pending */ /******************************************/ if(icode == 0 || icode == SIE_NO_INTERCEPT) { /* Check PER first, higher priority */ if( OPEN_IC_PER(GUESTREGS) ) ARCH_DEP(program_interrupt) (GUESTREGS, PGM_PER_EVENT); if( SIE_I_EXT(GUESTREGS) ) icode = SIE_INTERCEPT_EXTREQ; else if( SIE_I_IO(GUESTREGS) ) icode = SIE_INTERCEPT_IOREQ; else if( SIE_I_STOP(GUESTREGS) ) icode = SIE_INTERCEPT_STOPREQ; else if( SIE_I_WAIT(GUESTREGS) ) icode = SIE_INTERCEPT_WAIT; else if( SIE_I_HOST(regs) ) icode = SIE_HOST_INTERRUPT; } } while(icode == 0 || icode == SIE_NO_INTERCEPT); return icode; } #if defined(FEATURE_INTERPRETIVE_EXECUTION) #if defined(FEATURE_REGION_RELOCATE) /*-------------------------------------------------------------------*/ /* B23D STZP - Store Zone Parameter [S] */ /*-------------------------------------------------------------------*/ DEF_INST(store_zone_parameter) { int b2; /* Values of R fields */ RADR effective_addr2; /* address of state desc. */ ZPB zpb; /* Zone Parameter Block */ int zone; /* Zone number */ S(inst, regs, b2, effective_addr2); PRIV_CHECK(regs); SIE_INTERCEPT(regs); PTT(PTT_CL_IO,"STZP", regs->GR_L(1), regs->GR_L(2),regs->psw.IA_L); FW_CHECK(regs->GR(2), regs); zone = regs->GR_LHLCL(1); if(zone >= FEATURE_SIE_MAXZONES) { regs->psw.cc = 3; return; } STORE_W(zpb.mso,sysblk.zpb[zone].mso); STORE_W(zpb.msl,sysblk.zpb[zone].msl); STORE_W(zpb.eso,sysblk.zpb[zone].eso); STORE_W(zpb.esl,sysblk.zpb[zone].esl); ARCH_DEP(vstorec(&zpb, sizeof(ZPB)-1,regs->GR(2), 2, regs)); regs->psw.cc = 0; } /*-------------------------------------------------------------------*/ /* B23E SZP - Set Zone Parameter [S] */ /*-------------------------------------------------------------------*/ DEF_INST(set_zone_parameter) { int b2; /* Values of R fields */ RADR effective_addr2; /* address of state desc. */ ZPB zpb; /* Zone Parameter Block */ int zone; /* Zone number */ RADR mso, /* Main Storage Origin */ msl, /* Main Storage Length */ eso, /* Expanded Storage Origin */ esl; /* Expanded Storage Length */ S(inst, regs, b2, effective_addr2); PRIV_CHECK(regs); SIE_INTERCEPT(regs); PTT(PTT_CL_IO,"SZP", regs->GR_L(1), regs->GR_L(2),regs->psw.IA_L); FW_CHECK(regs->GR(2), regs); zone = regs->GR_LHLCL(1); if(zone == 0 || zone >= FEATURE_SIE_MAXZONES) { PTT(PTT_CL_ERR,"*SZP", regs->GR_L(1), regs->GR_L(2),regs->psw.IA_L); regs->psw.cc = 3; return; } ARCH_DEP(vfetchc(&zpb, sizeof(ZPB)-1,regs->GR(2), 2, regs)); FETCH_W(mso,zpb.mso); FETCH_W(msl,zpb.msl); FETCH_W(eso,zpb.eso); FETCH_W(esl,zpb.esl); #if defined(FEATURE_ESAME) if( (mso & ~ZPB2_MS_VALID) || (msl & ~ZPB2_MS_VALID) || (eso & ~ZPB2_ES_VALID) || (esl & ~ZPB2_ES_VALID) ) ARCH_DEP(program_interrupt) (regs, PGM_OPERAND_EXCEPTION); #endif /*defined(FEATURE_ESAME)*/ sysblk.zpb[zone].mso = mso; sysblk.zpb[zone].msl = msl; sysblk.zpb[zone].eso = eso; sysblk.zpb[zone].esl = esl; regs->psw.cc = 0; } #endif /*defined(FEATURE_REGION_RELOCATE)*/ #if defined(FEATURE_IO_ASSIST) /*-------------------------------------------------------------------*/ /* B23F TPZI - Test Pending Zone Interrupt [S] */ /*-------------------------------------------------------------------*/ DEF_INST(test_pending_zone_interrupt) { int b2; /* Values of R fields */ RADR effective_addr2; /* address of state desc. */ U32 ioid; /* I/O interruption address */ U32 ioparm; /* I/O interruption parameter*/ U32 iointid; /* I/O interruption ident */ FWORD tpziid[3]; int zone; /* Zone number */ S(inst, regs, b2, effective_addr2); PRIV_CHECK(regs); SIE_INTERCEPT(regs); PTT(PTT_CL_IO,"TPZI", regs->GR_L(1),(U32)(effective_addr2 & 0xffffffff),regs->psw.IA_L); FW_CHECK(regs->GR(2), regs); /* Perform serialization and checkpoint-synchronization */ PERFORM_SERIALIZATION (regs); PERFORM_CHKPT_SYNC (regs); zone = regs->GR_LHLCL(1); if(zone >= FEATURE_SIE_MAXZONES) { PTT(PTT_CL_ERR,"*TPZI", regs->GR_L(1),(U32)(effective_addr2 & 0xffffffff),regs->psw.IA_L); regs->psw.cc = 0; return; } if( IS_IC_IOPENDING ) { /* Obtain the interrupt lock */ OBTAIN_INTLOCK(regs); /* Test (but don't clear!) pending interrupt, and set condition code */ if( ARCH_DEP(present_zone_io_interrupt) (&ioid, &ioparm, &iointid, zone) ) /* Store the SSID word and I/O parameter if an interrupt was pending */ { /* Store interruption parms */ STORE_FW(tpziid[0],ioid); STORE_FW(tpziid[1],ioparm); STORE_FW(tpziid[2],iointid); /* Release the interrupt lock */ RELEASE_INTLOCK(regs); ARCH_DEP(vstorec(&tpziid, sizeof(tpziid)-1,regs->GR(2), 2, regs)); regs->psw.cc = 1; } else { /* Release the interrupt lock */ RELEASE_INTLOCK(regs); regs->psw.cc = 0; } } else regs->psw.cc = 0; } /*-------------------------------------------------------------------*/ /* DIAG 002 - Update Interrupt Interlock Control Bit in PMCW */ /*-------------------------------------------------------------------*/ void ARCH_DEP(diagnose_002) (REGS *regs, int r1, int r3) { DEVBLK *dev; U32 newgr1; /* Program check if the ssid including lcss is invalid */ SSID_CHECK(regs); /* Locate the device block for this subchannel */ dev = find_device_by_subchan (regs->GR_L(1)); /* Condition code 3 if subchannel does not exist, is not valid, or is not enabled */ if (dev == NULL || (dev->pmcw.flag5 & PMCW5_V) == 0 || (dev->pmcw.flag5 & PMCW5_E) == 0) { PTT(PTT_CL_ERR,"*DIAG002", regs->GR_L(r1),regs->GR_L(r3),regs->GR_L(1)); regs->psw.cc = 3; return; } /* Obtain the device lock */ obtain_lock (&dev->lock); /* Set newgr1 to the current value of pending and interlock control */ newgr1 = ((dev->scsw.flag3 & SCSW3_SC_PEND) || (dev->pciscsw.flag3 & SCSW3_SC_PEND)) ? 0x02 : 0; if(dev->pmcw.flag27 & PMCW27_I) newgr1 |= 0x01; /* Do a compare-and-swap operation on the interrupt interlock control bit where both interlock and pending bits are compared, but only the interlock bit is swapped */ if((regs->GR_L(r1) & 0x03) == newgr1) { dev->pmcw.flag27 &= ~PMCW27_I; dev->pmcw.flag27 |= (regs->GR_L(r3) & 0x01) ? PMCW27_I : 0; regs->psw.cc = 0; } else { regs->GR_L(r1) &= ~0x03; regs->GR_L(r1) |= newgr1; regs->psw.cc = 1; } /* Release the device lock */ release_lock (&dev->lock); } #endif /*defined(FEATURE_IO_ASSIST)*/ #endif /*defined(FEATURE_INTERPRETIVE_EXECUTION)*/ #endif #if !defined(_GEN_ARCH) #if defined(_ARCHMODE2) #define _GEN_ARCH _ARCHMODE2 #include "sie.c" #endif #if defined(_ARCHMODE3) #undef _GEN_ARCH #define _GEN_ARCH _ARCHMODE3 #include "sie.c" #endif #endif /*!defined(_GEN_ARCH)*/ hercules-3.07/sllib.c000644 000765 000765 00000120240 11202676511 016214 0ustar00jmaynardjmaynard000000 000000 /* || ---------------------------------------------------------------------------- || || SLLIB.C (c) Copyright Leland Lucius, 2000-2009 || Released under terms of the Q Public License. || || Library for managing Standard Label tapes. || || ---------------------------------------------------------------------------- */ // $Id: sllib.c 5313 2009-04-06 23:13:26Z rbowler $ #include "hstdinc.h" #define _SLLIB_C_ #define _HTAPE_DLL_ #include "hercules.h" #include "sllib.h" /* || Local constant data */ /* || Label IDs in EBCDIC */ static const char *sl_elabs[] = { "\x00\x00\x00", /* Placeholder */ "\xE5\xD6\xD3", /* EBCDIC characters "VOL" */ "\xC8\xC4\xD9", /* EBCDIC characters "HDR" */ "\xE4\xC8\xD3", /* EBCDIC characters "UHL" */ "\xC5\xD6\xC6", /* EBCDIC characters "EOF" */ "\xC5\xD6\xE5", /* EBCDIC characters "EOV" */ "\xE4\xE3\xD3", /* EBCDIC characters "UTL" */ }; #define SL_ELABS_MAX ( sizeof( sl_elabs ) / sizeof( sl_elabs[ 0 ] ) ) /* || Label IDs in ASCII */ static const char *sl_alabs[] = { "\x00\x00\x00", /* Placeholder */ "\x56\x4f\x4c", /* ASCII characters "VOL" */ "\x48\x44\x52", /* ASCII characters "HDR" */ "\x55\x48\x4c", /* ASCII characters "UHL" */ "\x45\x4f\x46", /* ASCII characters "EOF" */ "\x45\x4f\x56", /* ASCII characters "EOV" */ "\x55\x54\x4c", /* ASCII characters "UTL" */ }; #define SL_ALABS_MAX ( sizeof( sl_alabs ) / sizeof( sl_alabs[ 0 ] ) ) /* || Minimum and maximum ranges for each label type */ static const struct { int min; int max; } sl_ranges[] = { { 0, 0 }, /* Placeholder */ { 1, 1 }, /* ASCII characters "VOL" */ { 1, 2 }, /* ASCII characters "HDR" */ { 1, 8 }, /* ASCII characters "UHL" */ { 1, 2 }, /* ASCII characters "EOF" */ { 1, 2 }, /* ASCII characters "EOV" */ { 1, 8 }, /* ASCII characters "UTL" */ }; /* || Text descriptions for errors */ static const char *sl_errstr[] = { "No error", "Block size out of range", "Data set sequence out of range", "Invalid expiration date", "Missing or invalid job name", "Missing or invalid record length", "Owner string invalid or too long", "Missing or invalid record format", "Missing or invalid step name", "Invalid recording technique", "Volume sequence out of range", "Missing or invalid volume serial", "User data too long", "Label type invalid", "Label number invalid", "Invalid error code", }; #define SL_ERRSTR_MAX ( sizeof( sl_errstr) / sizeof( sl_errstr[ 0 ] ) ) /* || Valid characters for a Standard Label || (from: SC26-4565-01 "3.4 Label Definition and Organization") */ static const char sl_cset[] = { "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 !\"%&'()*+,-./:;<=>?" }; /* || Valid record formats */ static const struct { char *recfm; char f; char b; char c; } valfm[] = { { "U", 'U', ' ', ' ' }, { "UA", 'U', ' ', 'A' }, { "UM", 'U', ' ', 'M' }, { "F", 'F', ' ', ' ' }, { "FA", 'F', ' ', 'A' }, { "FM", 'F', ' ', 'M' }, { "FB", 'F', 'B', ' ' }, { "FBA", 'F', 'B', 'A' }, { "FBM", 'F', 'B', 'M' }, { "FS", 'F', 'S', ' ' }, { "FSA", 'F', 'S', 'A' }, { "FSM", 'F', 'S', 'M' }, { "FBS", 'F', 'R', ' ' }, { "FBSA", 'F', 'R', 'A' }, { "FBSM", 'F', 'R', 'M' }, { "V", 'V', ' ', ' ' }, { "VA", 'V', ' ', 'A' }, { "VM", 'V', ' ', 'M' }, { "VB", 'V', 'B', ' ' }, { "VBA", 'V', 'B', 'A' }, { "VBM", 'V', 'B', 'M' }, { "VS", 'V', 'S', ' ' }, { "VSA", 'V', 'S', 'A' }, { "VSM", 'V', 'S', 'M' }, { "VBS", 'V', 'R', ' ' }, { "VBSA", 'V', 'R', 'A' }, { "VBSM", 'V', 'R', 'M' }, }; #define VALFMCNT ( sizeof( valfm ) / sizeof( valfm[ 0 ] ) ) /*==DOC== NAME sl_atoe - Translate input buffer from ASCII to EBCDIC SYNOPSIS #include "sllib.h" char *sl_atoe( void *dbuf, void *sbuf, int slen ) DESCRIPTION Translates, and optionally copies, "sbuf" from ASCII to EBCDIC for "slen" characters. If "dbuf" is specified as NULL, then "sbuf" is translated in place. Otherwise, "dbuf" specifies the buffer where the translated characters will be stored. RETURN VALUE The return value will be either "sbuf" or "dbuf" depending on whether "dbuf" was passed as NULL. EXAMPLE // // Convert buffer // #include "sllib.h" unsigned char ascii[] = "\x48\x65\x72\x63\x75\x6c\x65\x73\x2e\x2e\x2e" "\x20\x52\x65\x73\x75\x72\x72\x65\x63\x74\x69" "\x6e\x67\x20\x74\x68\x65\x20\x64\x69\x6e\x6f" "\x73\x61\x75\x72\x73\x21"; unsigned char ebcdic[ sizeof( ascii ) ]; int main( int argc, char *argv[] ) { int len; int i; len = strlen( ascii ); sl_atoe( ebcdic, ascii, len ); printf( "ascii string: " ); for( i = 0 ; i < len ; i++ ) { printf( "%02x ", ascii[ i ] ); } printf( "\nebcdic string: " ); for( i = 0 ; i < len ; i++ ) { printf( "%02x ", ebcdic[ i ] ); } printf( "\n" ); return( 0 ); } SEE ALSO ==DOC==*/ DLL_EXPORT char * sl_atoe( void *dbuf, void *sbuf, int slen ) { unsigned char *sptr; unsigned char *dptr; sptr = sbuf; dptr = dbuf; if( dptr == NULL ) { dptr = sptr; } while( slen > 0 ) { slen--; dptr[ slen ] = host_to_guest( sptr[ slen ] ); } return( (char *)dptr ); } /*==DOC== NAME sl_etoa - Translate input buffer from EBCDIC to ASCII SYNOPSIS #include "sllib.h" char *sl_etoa( void *dbuf, void *sbuf, int slen ) DESCRIPTION Translates, and optionally copies, "sbuf" from EBCDIC to ASCII for "slen" characters. If "dbuf" is specified as NULL, then "sbuf" is translated in place. Otherwise, "dbuf" specifies the buffer where the translated characters will be stored. RETURN VALUE The return value will be either "sbuf" or "dbuf" depending on whether "dbuf" was passed as NULL. EXAMPLE // // Convert buffer // #include "sllib.h" unsigned char ebcdic[] = "\xc8\x85\x99\x83\xa4\x93\x85\xa2\x4b\x4b\x4b" "\x40\xd9\x85\xa2\xa4\x99\x99\x85\x83\xa3\x89" "\x95\x87\x40\xa3\x88\x85\x40\x84\x89\x95\x96" "\xa2\x81\xa4\x99\xa2\x5a"; unsigned char ascii[ sizeof( ebcdic ) ]; int main( int argc, char *argv[] ) { int len; int i; len = strlen( ebcdic ); sl_etoa( ascii, ebcdic, len ); printf( "ebcdic string: " ); for( i = 0 ; i < len ; i++ ) { printf( "%02x ", ebcdic[ i ] ); } printf( "\nascii string: " ); for( i = 0 ; i < len ; i++ ) { printf( "%02x ", ascii[ i ] ); } printf( "\n" ); return( 0 ); } SEE ALSO ==DOC==*/ DLL_EXPORT char * sl_etoa( void *dbuf, void *sbuf, int slen ) { unsigned char *sptr; unsigned char *dptr; sptr = sbuf; dptr = dbuf; if( dptr == NULL ) { dptr = sptr; } while( slen > 0 ) { slen--; dptr[ slen ] = guest_to_host( sptr[ slen ] ); } return( (char *)dptr ); } /*==DOC== NAME sl_islabel - Determines if passed data represents a standard label SYNOPSIS #include "sllib.h" int sl_islabel( SLLABEL *dlab, void *buf, int len ) DESCRIPTION This function performs several tests to determine if the "buf" parameter points to a valid standard label. The "len" parameter must be the length of the data pointed to by the "buf" parameter. If "dlab" does not contain NULL, then the data pointed to by "buf" will be converted to ASCII and placed at the "dlab" location. RETURN VALUE TRUE is returned if the data appears to be a standard label. Otherwise, FALSE is returned. NOTES The input label may be in either ASCII or EBCDIC. Currently, the tests are quite trival, but they may become more strict. EXAMPLE // // Test validity of a label // #include "sllib.h" int main( int argc, char *argv[] ) { SLLABEL sllab = { 0 }; printf( "Label is%s valid\n", ( sl_islabel( NULL, &sllab, sizeof( sllab ) ? "" : " not" ) ); sl_vol1( &sllab, "HET001", "HERCULES" ); printf( "Label is: %s valid\n", ( sl_islabel( NULL, &sllab, sizeof( sllab ) ? "" : " not" ) ); return( 0 ); } SEE ALSO sl_vol1() ==DOC==*/ DLL_EXPORT int sl_islabel( SLLABEL *lab, void *buf, int len ) { int i; int num; unsigned char *ptr; if( len != sizeof( SLLABEL ) ) { return FALSE; } for( i = 1 ; i < (int)SL_ELABS_MAX ; i++ ) { if( memcmp( sl_elabs[ i ], buf, 3 ) == 0 ) { ptr = buf; num = ptr[ 3 ] - (unsigned char) '\xF0'; if( ( num >= sl_ranges[ i ].min ) && ( num <= sl_ranges[ i ].max ) ) { if( lab != NULL ) { sl_etoa( lab, buf, len ); } return( TRUE ); } } if( memcmp( sl_alabs[ i ], buf, 3 ) == 0 ) { ptr = buf; num = ptr[ 3 ] - (unsigned char) '\x30'; if( ( num >= sl_ranges[ i ].min ) && ( num <= sl_ranges[ i ].max ) ) { if( lab != NULL ) { memcpy( lab, buf, len ); } return( TRUE ); } } } return( FALSE ); } /*==DOC== NAME sl_istype - Verifies data is of specified standard label type SYNOPSIS #include "sllib.h" int sl_istype( void *buf, int type, int num ) DESCRIPTION This function verifies that the data pointed to by the "buf" parameter contains a standard label as determined by the "type" and "num" parameters. The "type" parameter can be one of the "SLT_*" defines found in the "sllib.h" header file. The "num" parameter further defines the type and is usually 1 or 2. However, 0 may be specified to only test using the "type" parameter. RETURN VALUE TRUE is returned if the data is of the given type. Otherwise, FALSE is returned. NOTES The input data may be in either ASCII or EBCDIC. This routine is "usually" not called directly by user programs. The "sl_is*" macros in "sllib.h" should be used instead. EXAMPLE // // Determine if data is a VOL1 or HDR2 label. // #include "sllib.h" int main( int argc, char *argv[] ) { SLLABEL sllab = { 0 }; sl_vol1( &sllab, "HET001", "HERCULES" ); printf( "Label is%s a VOL1\n", ( sl_istype( &sllab, SLT_VOL, 1 ) ? "" : " not" ) ); printf( "Label is%s a HDR2\n", ( sl_istype( &sllab, SLT_HDR, 2 ) ? "" : " not" ) ); return( 0 ); } SEE ALSO sl_vol1() ==DOC==*/ DLL_EXPORT int sl_istype( void *buf, int type, int num ) { unsigned char *ptr; ptr = buf; /* || Check EBCDIC table */ if( memcmp( buf, sl_elabs[ type ], 3 ) == 0 ) { if( ( num == 0 ) || ( ptr[ 3 ] == ( ( (unsigned char) '\xF0' ) + num ) ) ) { return( TRUE ); } } /* || Check ASCII table */ if( memcmp( buf, sl_alabs[ type ], 3 ) == 0 ) { if( ( num == 0 ) || ( ptr[ 3 ] == ( ( (unsigned char) '\x30') + num ) ) ) { return( TRUE ); } } return( FALSE ); } /*==DOC== NAME sl_fmtdate - Converts dates to/from SL format SYNOPSIS #include "sllib.h" char *sl_fmtdate( char *dest, char *src, int fromto ) DESCRIPTION Converts the "src" date from or to the SL format and places the result at the "dest" location. If the "src" parameter is specified as NULL, then the current date will automatically be supplied. The "fromto" parameter controls the type of conversion. Specify FALSE to convert to SL format and TRUE from convert from SL format. When converting to the SL format, the "src" parameter must contain a valid Julian date in one of the following formats: YYDDD YY.DDD YYYYDDD YYYY.DDD RETURN VALUE If "src" contains an invalid date, then NULL will be returned. Otherwise, the "dest" value is returned. EXAMPLE // // Convert julian date to SL format // #include "sllib.h" char sldate[ SL_DATELEN ]; char jdate[] = "1998.212"; int main( int argc, char *argv[] ) { sl_fmtdate( sldate, jdate, FALSE ); printf( "Julian date : %s\n", jdate ); printf( "SL date : %-6.6s\n", sldate ); return( 0 ); } SEE ALSO ==DOC==*/ DLL_EXPORT char * sl_fmtdate( char *dest, char *src, int fromto ) { char wbuf[ 9 ]; char sbuf[ 9 ]; char *ptr; time_t curtime; struct tm tm; int ret; /* || If source represents an SL date, then convert it to julian */ if( fromto ) { if( src == NULL ) { return( NULL ); } if( src[ 5 ] == '0' ) { dest[ 0 ] = src[ 1 ]; dest[ 1 ] = src[ 2 ]; } else if( src[ 0 ] == ' ' ) { dest[ 0 ] = '1'; dest[ 1 ] = '9'; } else { dest[ 0 ] = '2'; dest[ 1 ] = src[ 0 ]; } memcpy( &dest[ 2 ], &src[ 1 ] , 2 ); dest[ 4 ] = '.'; memcpy( &dest[ 5 ], &src[ 3 ] , 3 ); } else { /* || Supply current date if source is null */ if( src == NULL ) { strftime( sbuf, sizeof( sbuf ), "%Y%j", localtime( &curtime ) ); src = sbuf; } /* || Base initial guess at format on length of src date */ switch( strlen( src ) ) { case 5: ptr = "%2u%3u"; break; case 6: ptr = "%2u.%3u"; break; case 7: ptr = "%4u%3u"; break; case 8: ptr = "%4u.%3u"; break; default: return( NULL ); break; } /* || Convert src to "tm" format */ ret = sscanf( src, ptr, &tm.tm_year, &tm.tm_yday ); if( ret != 2 || tm.tm_yday < 1 || tm.tm_yday > 366 ) { return( NULL ); } tm.tm_yday--; /* || Now, convert to SL tape format */ strftime( wbuf, sizeof( wbuf ), "%Y%j", &tm ); if( tm.tm_year < 100 ) { /* || 1900s are indicated by a blank. */ wbuf[ 1 ] = ' '; } /* || Finally, copy SL date to destination */ memcpy( dest, &wbuf[ 1 ], 6 ); } /* || Return dest pointer */ return( dest ); } /*==DOC== NAME sl_fmtlab - Transforms an SL label from raw to cooked format SYNOPSIS #include "sllib.h" void sl_fmtlab( SLFMT *fmt, SLLABEL *lab ) DESCRIPTION Converts the SL label specified by "lab" into a "cooked" format that's easier to process. Text descriptions are supplied for each field are also supplied. RETURN VALUE Nothing is returned. NOTES The input label may be in either ASCII or EBCDIC. It will be converted to ASCII before building the cooked version. The first two fields of the SLFMT structure are arrays that contain the text description and value for each field based on the label type. The arrays are terminated with NULL pointers. EXAMPLE // // Convert an SL label to cooked format // #include "sllib.h" int main( int argc, char *argv[] ) { SLFMT slfmt; SLLABEL sllab; int i; sl_vol1( &sllab, "HET001", "HERCULES" ); sl_fmtlab( &slfmt, &sllab ); for( i = 0 ; slfmt.key[ i ] != NULL ; i++ ) { printf("%-20.20s: '%s'\n", slfmt.key[ i ] , slfmt.val[ i ] ); } return( 0 ); } SEE ALSO sl_vol1() ==DOC==*/ #define lab2fmt( i1, f2, l3, k4 ) \ fmt->key[ i1 ] = k4; \ fmt->val[ i1 ] = fmt->f2; \ memcpy( fmt->f2, lab->f2, l3 ); DLL_EXPORT void sl_fmtlab( SLFMT *fmt, SLLABEL *lab ) { SLLABEL templab; /* || Initialize */ memset( fmt, 0, sizeof( SLFMT ) ); /* || If label appears to be EBCDIC, convert to ASCII before processing */ if( sl_islabel( &templab, lab, sizeof( SLLABEL ) ) == FALSE ) { return; } lab = &templab; /* || Store label type (combine ID and NUM) */ fmt->key[ 0 ] = "Label"; fmt->val[ 0 ] = fmt->type; memcpy( fmt->type, lab->id, 4 ); /* || Build remaining fields based on label type */ if( memcmp( lab->id, "VOL", 3 ) == 0 ) { if( lab->num[ 0 ] == '1' ) { lab2fmt( 1, slvol.volser, 6, "Volume Serial" ); lab2fmt( 2, slvol.idrc, 1, "Improved Data Rec." ); lab2fmt( 3, slvol.owner, 10, "Owner Code" ); } } else if( ( memcmp( lab->id, "HDR", 3 ) == 0 ) || ( memcmp( lab->id, "EOF", 3 ) == 0 ) || ( memcmp( lab->id, "EOV", 3 ) == 0 ) ) { if( lab->num[ 0 ] == '1' ) { lab2fmt( 1, slds1.dsid, 17, "Dataset ID" ); lab2fmt( 2, slds1.volser, 6, "Volume Serial" ); lab2fmt( 3, slds1.volseq, 4, "Volume Sequence" ); lab2fmt( 4, slds1.dsseq, 4, "Dataset Sequence" ); lab2fmt( 5, slds1.genno, 4, "GDG Number" ); lab2fmt( 6, slds1.verno, 2, "GDG Version" ); lab2fmt( 7, slds1.crtdt, 6, "Creation Date" ); lab2fmt( 8, slds1.expdt, 6, "Expiration Date" ); lab2fmt( 9, slds1.dssec, 1, "Dataset Security" ); lab2fmt( 10, slds1.blklo, 6, "Block Count Low" ); lab2fmt( 11, slds1.syscd, 13, "System Code" ); lab2fmt( 12, slds1.blkhi, 4, "Block Count High" ); } else if( lab->num[ 0 ] == '2' ) { lab2fmt( 1, slds2.recfm, 1, "Record Format" ); lab2fmt( 2, slds2.blksize, 5, "Block Size" ); lab2fmt( 3, slds2.lrecl, 5, "Record Length" ); lab2fmt( 4, slds2.den, 1, "Density" ); lab2fmt( 5, slds2.dspos, 1, "Dataset Position" ); lab2fmt( 6, slds2.jobid, 17, "Job/Step ID" ); lab2fmt( 7, slds2.trtch, 2, "Recording Technique" ); lab2fmt( 8, slds2.ctrl, 1, "Control Character" ); lab2fmt( 9, slds2.blkattr, 1, "Block Attribute" ); lab2fmt( 10, slds2.devser, 6, "Device Serial" ); lab2fmt( 11, slds2.ckptid, 1, "Checkpoint ID" ); lab2fmt( 12, slds2.lblkln, 10, "Large Block Length" ); } } else if( memcmp( lab->id, "USR", 3 ) == 0 ) { lab2fmt( 1, slusr.data, 76, "User Data" ); } return; } #undef lab2fmt /*==DOC== NAME sl_vol - Generate a volume label SYNOPSIS #include "sllib.h" int sl_vol( SLLABEL *lab, char *volser, char *owner ) DESCRIPTION This function builds a volume label based on the parameters provided and places it at the location pointed to by the "lab" parameter in EBCDIC. The remaining parameters correspond to fields within the label and are converted to EBCDIC before storing. The "owner" parameter may be specified as NULL, in which case blanks are supplied. RETURN VALUE The return value will be >= 0 if no errors are detected. If an error is detected, then the return value will be < 0 and will be one of the following: SLE_VOLSER Missing or invalid volume serial SLE_OWNER Owner string too long NOTES This routine is normally accessed using the supplied "sl_vol1" macro. Only the "most common" label fields have corresponding parameters so the user must supply any other desired values. EXAMPLE // // Create a VOL1 label // #include "sllib.h" int main( int argc, char *argv[] ) { SLFMT slfmt; SLLABEL sllab; int i; sl_vol( &sllab, "HET001", "HERCULES" ); sl_fmtlab( &slfmt, &sllab ); for( i = 0 ; slfmt.key[ i ] != NULL ; i++ ) { printf("%-20.20s: '%s'\n", slfmt.key[ i ] , slfmt.val[ i ] ); } return( 0 ); } SEE ALSO sl_fmtlab() ==DOC==*/ DLL_EXPORT int sl_vol( SLLABEL *lab, char *volser, char *owner ) { size_t len; /* || Initialize */ memset( lab, ' ', sizeof( SLLABEL ) ); /* || Label ID */ memcpy( lab->id, sl_alabs[ SLT_VOL ], 3 ); /* || Label number */ lab->num[ 0 ] = '1'; /* || Volser */ if( volser == NULL ) { return( SLE_VOLSER ); } len = strlen( volser ); if( ( len > 6 ) || ( strspn( volser, sl_cset ) != len ) ) { return( SLE_VOLSER ); } memcpy( lab->slvol.volser, volser, len ); /* || Owner */ if( owner != NULL ) { len = strlen( owner ); if( len > 10 ) { return( SLE_OWNER ); } memcpy( lab->slvol.owner, owner, len ); } /* || Convert to EBCDIC */ sl_atoe( NULL, lab, sizeof( SLLABEL ) ); return 0; } /*==DOC== NAME sl_ds1 - Generate a data set label 1 SYNOPSIS #include "sllib.h" int sl_ds1( SLLABEL *lab, int type, char *dsn, char *volser, int volseq, int dsseq, char *expdt, int blocks ) DESCRIPTION This function builds a data set label 1 based on the parameters provided and places it at the location pointed to by the "lab" parameter in EBCDIC. The "type" parameter must be "SLT_HDR", "SLT_EOF", or "SLT_EOV". The remaining parameters correspond to fields within the label and are converted to EBCDIC before storing. The "dsn" parameter may be set to "SL_INITDSN" if "SLT_HDR" is specified for the "type" parameter. This will create an IEHINITT format HDR1 label. The "blocks" parameter is forced to 0 for "SLT_HDR" types. RETURN VALUE The return value will be >= 0 if no errors are detected. If an error is detected, then the return value will be < 0 and will be one of the following: SLE_INVALIDTYPE Invalid label type specified SLE_VOLSER Missing or invalid volume serial SLE_OWNER Owner string too long NOTES This routine is normally accessed using the supplied "sl_hdr1", "sl_eof1", or "sl_eov1" macros. Only the "most common" label fields have corresponding parameters so the user must supply any other desired values. EXAMPLE // // Create a EOF1 label // #include "sllib.h" int main( int argc, char *argv[] ) { SLFMT slfmt; SLLABEL sllab; int i; sl_ds1( &sllab, SLT_EOF, "HERCULES.TAPE.G0010V00", "HERC01", 1, 1, "2001.321", 289 ); sl_fmtlab( &slfmt, &sllab ); for( i = 0 ; slfmt.key[ i ] != NULL ; i++ ) { printf("%-20.20s: '%s'\n", slfmt.key[ i ] , slfmt.val[ i ] ); } return( 0 ); } SEE ALSO sl_fmtlab() ==DOC==*/ DLL_EXPORT int sl_ds1( SLLABEL *lab, int type, char *dsn, char *volser, int volseq, int dsseq, char *expdt, int blocks ) { int gdg; size_t len; size_t ndx; char wbuf[ 80 ]; /* || Initialize */ memset( lab, ' ', sizeof( SLLABEL ) ); /* || Label ID */ if( ( type != SLT_HDR ) && ( type != SLT_EOF ) && ( type != SLT_EOV ) ) { return( SLE_INVALIDTYPE ); } memcpy( lab->id, sl_alabs[ type ], 3 ); /* || Label number */ lab->num[ 0 ] = '1'; /* || Special IEHINITT dataset name? */ if( ( type == SLT_HDR ) && ( strcmp( dsn, SL_INITDSN ) == 0 ) ) { memset( &lab->slds1, '0', sizeof( lab->slds1 ) ); sl_atoe( NULL, lab, sizeof( SLLABEL ) ); return( 0 ); } /* || Dataset ID */ ndx = 0; len = strlen( dsn ); if( len > 17 ) { ndx = len - 17; len = 17; } memcpy( lab->slds1.dsid, &dsn[ ndx ], len ); /* || GDG generation and version */ if( len > 9 ) { gdg = 0; gdg += ( dsn[ len - 9 ] == '.' ); gdg += ( dsn[ len - 8 ] == 'G' ); gdg += ( isdigit( dsn[ len - 7 ] ) != 0 ); gdg += ( isdigit( dsn[ len - 6 ] ) != 0 ); gdg += ( isdigit( dsn[ len - 5 ] ) != 0 ); gdg += ( isdigit( dsn[ len - 4 ] ) != 0 ); gdg += ( dsn[ len - 3 ] == 'V' ); gdg += ( isdigit( dsn[ len - 2 ] ) != 0 ); gdg += ( isdigit( dsn[ len - 1 ] ) != 0 ); if( gdg == 9 ) { memcpy( lab->slds1.genno, &dsn[ len - 7 ], 4 ); memcpy( lab->slds1.verno, &dsn[ len - 2 ], 2 ); } } /* || Volser */ len = strlen( volser ); if( len > 6 ) { return( SLE_VOLSER ); } memcpy( lab->slds1.volser, volser, len ); /* || Volume sequence */ if( volseq > 9999 ) { return( SLE_VOLSEQ ); } sprintf( wbuf, "%04u", volseq ); memcpy( lab->slds1.volseq, wbuf, 4 ); /* || Dataset sequence */ if( dsseq > 9999 ) { return( SLE_DSSEQ ); } sprintf( wbuf, "%04u", dsseq ); memcpy( lab->slds1.dsseq, wbuf, 4 ); /* || Creation Date */ sl_fmtdate( lab->slds1.crtdt, NULL, FALSE ); /* || Expiration Date */ if( sl_fmtdate( lab->slds1.expdt, expdt, FALSE ) == NULL ) { return( SLE_EXPDT ); } /* || Dataset security */ memset( lab->slds1.dssec, '0', 1 ); /* || Block count - low */ if( type == SLT_HDR ) { blocks = 0; } sprintf( wbuf, "%010u", blocks ); memcpy( lab->slds1.blklo, &wbuf[ 4 ], 6 ); /* || System code */ memcpy( lab->slds1.syscd, "IBM OS/VS 370", 13 ); /* || Block count - high */ sprintf( wbuf, "%10u", blocks ); memcpy( lab->slds1.blkhi, wbuf, 4 ); /* || Convert to EBCDIC */ sl_atoe( NULL, lab, sizeof( SLLABEL ) ); return 0; } /*==DOC== NAME sl_ds2 - Generate a data set label 2 SYNOPSIS #include "sllib.h" int sl_ds2( SLLABEL *lab, int type, char *recfm, int lrecl, int blksize, char *jobname, char *stepname, char *trtch ) DESCRIPTION This function builds a data set label 2 based on the parameters provided and places it at the location pointed to by the "lab" parameter in EBCDIC. The "type" parameter must be "SLT_HDR", "SLT_EOF", or "SLT_EOV". The remaining parameters correspond to fields within the label and are converted to EBCDIC before storing. The "recfm" parameter may be one of the following: F FS V VS U FA FSA VA VSA UA FM FSM VM VSM UM FB FBS VB VBS FBA FBSA VBA VBSA FBM FBSM VBM VBSM The "trtch" parameter may be blank or one of the following: T C E ET P RETURN VALUE The return value will be >= 0 if no errors are detected. If an error is detected, then the return value will be < 0 and will be one of the following: SLE_INVALIDTYPE Invalid label type specified SLE_RECFM Missing or invalid record format SLE_LRECL Invalid record length SLE_BLKSIZE Block size out of range SLE_JOBNAME Missing or invalid job name SLE_STEPNAME Missing or invalid step name SLE_TRTCH Invalid recording technique NOTES This routine is normally accessed using the supplied "sl_hdr1", "sl_eof1", or "sl_eov1" macros. Only the "most common" label fields have corresponding parameters so the user must supply any other desired values. EXAMPLE // // Create a EOV2 label // #include "sllib.h" int main( int argc, char *argv[] ) { SLFMT slfmt; SLLABEL sllab; int i; sl_ds2( &sllab, SLT_EOF, "FB", 80, 32720, "HERCJOB", "HERCSTEP", "P" ); sl_fmtlab( &slfmt, &sllab ); for( i = 0 ; slfmt.key[ i ] != NULL ; i++ ) { printf("%-20.20s: '%s'\n", slfmt.key[ i ] , slfmt.val[ i ] ); } return( 0 ); } SEE ALSO sl_fmtlab() ==DOC==*/ DLL_EXPORT int sl_ds2( SLLABEL *lab, int type, char *recfm, int lrecl, int blksize, char *jobname, char *stepname, char *trtch ) { int i; size_t len; char wbuf[ 80 ]; /* || Initialize */ memset( lab, ' ', sizeof( SLLABEL ) ); /* || Label ID */ if( ( type != SLT_HDR ) && ( type != SLT_EOF ) && ( type != SLT_EOV ) ) { return( SLE_INVALIDTYPE ); } memcpy( lab->id, sl_alabs[ type ], 3 ); /* || Label number */ lab->num[ 0 ] = '1'; /* || Record format/Block Attribute/Control */ if( recfm == NULL ) { return( SLE_RECFM ); } for( i = 0 ; i < (int)VALFMCNT ; i++ ) { if( strcmp( recfm, valfm[ i ].recfm ) == 0 ) { break; } } if( i == VALFMCNT ) { return( SLE_RECFM ); } lab->slds2.recfm[ 0 ] = valfm[ i ].f; lab->slds2.blkattr[ 0 ] = valfm[ i ].b; lab->slds2.ctrl[ 0 ] = valfm[ i ].c; /* || Block size */ if( blksize == 0 ) { return( SLE_BLKSIZE ); } if( blksize > 32760 ) { sprintf( wbuf, "%10u", blksize ); memcpy( lab->slds2.lblkln, wbuf, 10 ); memcpy( lab->slds2.blksize, "00000", 5 ); } else { sprintf( wbuf, "%05u", blksize ); memcpy( lab->slds2.blksize, wbuf, 5 ); } /* || Logical record length */ switch( lab->slds2.recfm[ 0 ] ) { case 'F': if( ( valfm[ i ].b == 'S' ) || ( valfm[ i ].b == ' ' ) ) { if( lrecl != blksize ) { return( SLE_LRECL ); } } else { if( ( blksize % lrecl ) != 0 ) { return( SLE_LRECL ); } } break; case 'V': if( valfm[ i ].b == ' ' ) { if( ( lrecl + 4 ) != blksize ) { return( SLE_LRECL ); } } else if( valfm[ i ].b == 'B' ) { if( ( lrecl + 4 ) > blksize ) { return( SLE_LRECL ); } } break; case 'U': if( lrecl != 0 ) { return( SLE_LRECL ); } break; } sprintf( wbuf, "%05u", lrecl ); memcpy( lab->slds2.lrecl, wbuf, 5 ); /* || Jobname and stepname */ if( jobname != NULL ) { if( stepname == NULL ) { return( SLE_STEPNAME ); } len = strlen( jobname ); if( len > 8 ) { return( SLE_JOBNAME ); } len = strlen( stepname ); if( len > 8 ) { return( SLE_STEPNAME ); } } else { if( stepname != NULL ) { return( SLE_JOBNAME ); } } sprintf( wbuf, "%-8.8s/%-8.8s", jobname, stepname ); memcpy( lab->slds2.jobid, wbuf, 17 ); /* || Density */ lab->slds2.den[ 0 ] = '0'; /* || Dataset position */ lab->slds2.dspos[ 0 ] = '0'; /* || Tape recording technique */ if( trtch != NULL ) { len = strlen( trtch ); if( len < 1 || len > 2 ) { return( SLE_TRTCH ); } switch( trtch[ 0 ] ) { case 'T': case 'C': case 'P': case ' ': lab->slds2.trtch[ 0 ] = trtch[ 0 ]; break; case 'E': lab->slds2.trtch[ 0 ] = trtch[ 0 ]; if( len == 2 ) { if( trtch[ 1 ] != 'T' ) { return( SLE_TRTCH ); } lab->slds2.trtch[ 1 ] = trtch[ 1 ]; } break; default: return( SLE_TRTCH ); break; } } /* || Device serial number */ sprintf( wbuf, "%06u", rand() ); memcpy( lab->slds2.devser, wbuf, 6 ); /* || Checkpoint dataset identifier */ lab->slds2.ckptid[ 0 ] = ' '; /* || Convert to EBCDIC */ sl_atoe( NULL, lab, sizeof( SLLABEL ) ); return 0; } /*==DOC== NAME sl_usr - Generate a user label SYNOPSIS #include "sllib.h" int sl_usr( SLLABEL *lab, int type, int num, char *data ) DESCRIPTION This function builds a user label based on the parameters provided and places it at the location pointed to by the "lab" parameter in EBCDIC. The "type" parameter must be "SLT_UHL" or "SLT_UTL" and the "num" parameter must be 1 through 8. The remaining parameter corresponds to fields within the label and is converted to EBCDIC before storing. RETURN VALUE The return value will be >= 0 if no errors are detected. If an error is detected, then the return value will be < 0 and will be one of the following: SLE_DATA Missing or invalid user data NOTES This routine is normally accessed using the supplied "sl_uhl*" or "sl_utl*" macros. EXAMPLE // // Create a UHL6 label // #include "sllib.h" int main( int argc, char *argv[] ) { SLFMT slfmt; SLLABEL sllab; int i; sl_usr( &sllab, SLT_EOF, 6, "Hercules Emulated Tape" ); sl_fmtlab( &slfmt, &sllab ); for( i = 0 ; slfmt.key[ i ] != NULL ; i++ ) { printf("%-20.20s: '%s'\n", slfmt.key[ i ] , slfmt.val[ i ] ); } return( 0 ); } SEE ALSO sl_fmtlab() ==DOC==*/ DLL_EXPORT int sl_usr( SLLABEL *lab, int type, int num, char *data ) { size_t len; /* || Initialize */ memset( lab, ' ', sizeof( SLLABEL ) ); /* || Label ID */ if( ( type != SLT_UHL ) && ( type != SLT_UTL ) ) { return( SLE_INVALIDTYPE ); } memcpy( lab->id, sl_elabs[ type ], 3 ); /* || Label number */ if( ( num < 1 ) || ( num > 8 ) ) { return( SLE_INVALIDNUM ); } lab->num[ 0 ] = '0' + num; /* || User data */ if( data == NULL ) { return( SLE_DATA ); } len = strlen( data ); if( len == 0 || len > 76 ) { return( SLE_DATA ); } memcpy( lab->slusr.data, data, len ); /* || Convert to EBCDIC */ sl_atoe( NULL, lab, sizeof( SLLABEL ) ); return 0; } /*==DOC== NAME sl_error - Returns a text message for an SL error code SYNOPSIS #include "sllib.h" char *sl_error( int rc ) DESCRIPTION Simply returns a pointer to a string that describes the error code passed in the "rc" parameter. RETURN VALUE The return value is always valid and no errors are returned. EXAMPLE // // Print text for SLE_DSSEQ. // #include "sllib.h" int main( int argc, char *argv[] ) { printf( "SLLIB error: %d = %s\n", SLE_DSSEQ, sl_error( SLE_DSSEQ ) ); return( 0 ); } SEE ALSO ==DOC==*/ DLL_EXPORT const char * sl_error( int rc ) { /* || If not an error just return the "OK" string */ if( rc >= 0 ) { rc = 0; } /* || Turn it into an index */ rc = -rc; /* || Within range? */ if( rc >= (int)SL_ERRSTR_MAX ) { rc = SL_ERRSTR_MAX - 1; } /* || Return string */ return( sl_errstr[ rc ] ); } hercules-3.07/sllib.h000644 000765 000765 00000017470 11202676511 016233 0ustar00jmaynardjmaynard000000 000000 // $Id: sllib.h 5313 2009-04-06 23:13:26Z rbowler $ #if !defined( _SLLIB_H_ ) #define _SLLIB_H_ #include "hercules.h" #ifndef _SLLIB_C_ #ifndef _HTAPE_DLL_ #define SLL_DLL_IMPORT DLL_IMPORT #else /* _HUTIL_DLL_ */ #define SLL_DLL_IMPORT extern #endif /* _HUTIL_DLL_ */ #else #define SLL_DLL_IMPORT DLL_EXPORT #endif /* || ---------------------------------------------------------------------------- || || SLLIB.H (c) Copyright Leland Lucius, 2000-2009 || Released under terms of the Q Public License. || || Header for Standard Label library. || || ---------------------------------------------------------------------------- */ #if !defined( TRUE ) #define TRUE 1 #endif #if !defined( FALSE ) #define FALSE 0 #endif /* || Raw label structure */ typedef struct _sllabel { char id[ 3 ]; char num[ 1 ]; union { struct { char volser[ 6 ]; char rsvd1[ 25 ]; char idrc[ 1 ]; char rsvd2[ 5 ]; char owner[ 10 ]; char rsvd3[ 29 ]; } vol; struct { char dsid[ 17 ]; char volser[ 6 ]; char volseq[ 4 ]; char dsseq[ 4 ]; char genno[ 4 ]; char verno[ 2 ]; char crtdt[ 6 ]; char expdt[ 6 ]; char dssec[ 1 ]; char blklo[ 6 ]; char syscd[ 13 ]; char rsvd1[ 3 ]; char blkhi[ 4 ]; } ds1; struct { char recfm[ 1 ]; char blksize[ 5 ]; char lrecl[ 5 ]; char den[ 1 ]; char dspos[ 1 ]; char jobid[ 17 ]; char trtch[ 2 ]; char ctrl[ 1 ]; char rsvd1[ 1 ]; char blkattr[ 1 ]; char rsvd2[ 2 ]; char devser[ 6 ]; char ckptid[ 1 ]; char rsvd3[ 22 ]; char lblkln[ 10 ]; } ds2; struct { char data[ 76 ]; } usr; } u; } SLLABEL; /* || Cooked label structure */ typedef struct _slfmt { char *key[ 14 ]; char *val[ 14 ]; char type[ 4 + 1 ]; union { struct { char volser[ 6 + 1 ]; char idrc[ 1 + 1 ]; char owner[ 10 + 1 ]; } vol; struct { char dsid[ 17 + 1 ]; char volser[ 6 + 1 ]; char volseq[ 4 + 1 ]; char dsseq[ 4 + 1 ]; char genno[ 4 + 1 ]; char verno[ 2 + 1 ]; char crtdt[ 6 + 1 ]; char expdt[ 6 + 1 ]; char dssec[ 1 + 1 ]; char blklo[ 6 + 1 ]; char syscd[ 13 + 1 ]; char blkhi[ 4 + 1 ]; } ds1; struct { char recfm[ 1 + 1 ]; char blksize[ 5 + 1 ]; char lrecl[ 5 + 1 ]; char den[ 1 + 1 ]; char dspos[ 1 + 1 ]; char jobid[ 17 + 1 ]; char trtch[ 2 + 1 ]; char ctrl[ 1 + 1 ]; char blkattr[ 1 + 1 ]; char devser[ 6 + 1 ]; char ckptid[ 1 + 1 ]; char lblkln[ 10 + 1 ]; } ds2; struct { char data[ 76 + 1 ]; } usr; } u; } SLFMT; /* || Prettier label structure mappings */ #define slvol u.vol #define slds1 u.ds1 #define slds2 u.ds2 #define slusr u.usr /* || Special dataset name used to generate an IEHINITT HDR1 label */ #define SL_INITDSN "_IEHINITT_" /* || Length of SL format date */ #define SL_DATELEN 6 /* || Label types */ #define SLT_UNKOWN 0 #define SLT_VOL 1 #define SLT_HDR 2 #define SLT_UHL 3 #define SLT_EOF 4 #define SLT_EOV 5 #define SLT_UTL 6 /* || Macros to test label type */ #define sl_isvol( s, n ) sl_istype( (s), SLT_VOL, (n) ) #define sl_ishdr( s, n ) sl_istype( (s), SLT_HDR, (n) ) #define sl_isuhl( s, n ) sl_istype( (s), SLT_UHL, (n) ) #define sl_iseof( s, n ) sl_istype( (s), SLT_EOF, (n) ) #define sl_iseov( s, n ) sl_istype( (s), SLT_EOV, (n) ) #define sl_isutl( s, n ) sl_istype( (s), SLT_UTL, (n) ) /* || Macros to define specific labels */ #define sl_vol1( p1, p2, p3 ) \ sl_vol( p1, p2, p3 ) #define sl_hdr1( p1, p2, p3, p4, p5, p6, p7 ) \ sl_ds1( p1, SLT_HDR, p2, p3, p4, p5, p6, p7 ) #define sl_eof1( p1, p2, p3, p4, p5, p6 ) \ sl_ds1( p1, SLT_EOF, p2, p3, p4, p5, p6 ) #define sl_eov1( p1, p2, p3, p4, p5, p6 ) \ sl_ds1( p1, SLT_EOV, p2, p3, p4, p5, p6 ) #define sl_hdr2( p1, p2, p3, p4, p5, p6, p7, p8 ) \ sl_ds2( p1, SLT_HDR, p2, p3, p4, p5, p6, p7, p8 ) #define sl_eof2( p1, p2, p3, p4, p5, p6, p7, p8 ) \ sl_ds2( p1, SLT_EOF, p2, p3, p4, p5, p6, p7, p8 ) #define sl_eov2( p1, p2, p3, p4, p5, p6, p7, p8 ) \ sl_ds2( p1, SLT_EOV, p2, p3, p4, p5, p6, p7, p8 ) #define sl_uhl1( p1, p2 ) sl_usr( p1, SLT_UHL, 1, p2 ) #define sl_uhl2( p1, p2 ) sl_usr( p1, SLT_UHL, 2, p2 ) #define sl_uhl3( p1, p2 ) sl_usr( p1, SLT_UHL, 3, p2 ) #define sl_uhl4( p1, p2 ) sl_usr( p1, SLT_UHL, 4, p2 ) #define sl_uhl5( p1, p2 ) sl_usr( p1, SLT_UHL, 5, p2 ) #define sl_uhl6( p1, p2 ) sl_usr( p1, SLT_UHL, 6, p2 ) #define sl_uhl7( p1, p2 ) sl_usr( p1, SLT_UHL, 7, p2 ) #define sl_uhl8( p1, p2 ) sl_usr( p1, SLT_UHL, 8, p2 ) #define sl_utl1( p1, p2 ) sl_usr( p1, SLT_UTL, 1, p2 ) #define sl_utl2( p1, p2 ) sl_usr( p1, SLT_UTL, 2, p2 ) #define sl_utl3( p1, p2 ) sl_usr( p1, SLT_UTL, 3, p2 ) #define sl_utl4( p1, p2 ) sl_usr( p1, SLT_UTL, 4, p2 ) #define sl_utl5( p1, p2 ) sl_usr( p1, SLT_UTL, 5, p2 ) #define sl_utl6( p1, p2 ) sl_usr( p1, SLT_UTL, 6, p2 ) #define sl_utl7( p1, p2 ) sl_usr( p1, SLT_UTL, 7, p2 ) #define sl_utl8( p1, p2 ) sl_usr( p1, SLT_UTL, 8, p2 ) /* || Error definitions */ #define SLE_BLKSIZE -1 /* Block size out of range */ #define SLE_DSSEQ -2 /* Data set sequence out of range */ #define SLE_EXPDT -3 /* Invalid expiration date */ #define SLE_JOBNAME -4 /* Missing or invalid job name */ #define SLE_LRECL -5 /* Invalid record length */ #define SLE_OWNER -6 /* Owner string too long */ #define SLE_RECFM -7 /* Missing or invalid record format */ #define SLE_STEPNAME -8 /* Missing or invalid step name */ #define SLE_TRTCH -9 /* Invalid recording technique */ #define SLE_VOLSEQ -10 /* Volume sequence out of range */ #define SLE_VOLSER -11 /* Missing or invalid volume serial */ #define SLE_DATA -12 /* User data too long */ #define SLE_INVALIDTYPE -13 /* Label type invalid */ #define SLE_INVALIDNUM -14 /* Label number invalid */ /* || Public functions/data */ SLL_DLL_IMPORT char *sl_atoe( void *, void *, int ); SLL_DLL_IMPORT char *sl_etoa( void *, void *, int ); SLL_DLL_IMPORT char *sl_fmtdate( char *, char *, int ); SLL_DLL_IMPORT void sl_fmtlab( SLFMT *, SLLABEL * ); SLL_DLL_IMPORT int sl_islabel( SLLABEL *, void *, int ); SLL_DLL_IMPORT int sl_istype( void *, int type, int num ); SLL_DLL_IMPORT int sl_vol( SLLABEL *, char *, char * ); SLL_DLL_IMPORT int sl_ds1( SLLABEL *, int type, char *, char *, int, int, char *, int ); SLL_DLL_IMPORT int sl_ds2( SLLABEL *, int type, char *, int, int, char *, char *, char * ); SLL_DLL_IMPORT int sl_usr( SLLABEL *, int type, int num, char * ); SLL_DLL_IMPORT const char *sl_error( int rc ); #endif /* defined( _SLLIB_H_ ) */ hercules-3.07/sockdev.c000644 000765 000765 00000042755 11321734033 016557 0ustar00jmaynardjmaynard000000 000000 /* SOCKDEV.C (c) Copyright Hercules development, 2003-2009 */ /* Socketdevice support */ // $Id: sockdev.c 5535 2009-12-11 20:23:07Z bernard $ // // $Log$ // Revision 1.29 2008/11/04 05:56:31 fish // Put ensure consistent create_thread ATTR usage change back in // // Revision 1.28 2008/11/03 15:31:53 rbowler // Back out consistent create_thread ATTR modification // // Revision 1.27 2008/10/18 09:32:21 fish // Ensure consistent create_thread ATTR usage // // Revision 1.26 2007/06/23 00:04:15 ivan // Update copyright notices to include current year (2007) // // Revision 1.25 2006/12/08 09:43:30 jj // Add CVS message log // #include "hstdinc.h" #include "hercules.h" #include "opcode.h" #if defined(WIN32) && defined(OPTION_DYNAMIC_LOAD) && !defined(HDL_USE_LIBTOOL) && !defined(_MSVC_) extern SYSBLK *psysblk; #define sysblk (*psysblk) #endif /*===================================================================*/ /* S o c k e t D e v i c e s ... */ /*===================================================================*/ // #define DEBUG_SOCKDEV #ifdef DEBUG_SOCKDEV #define logdebug logmsg #else #define logdebug 1 ? ((void)0) : logmsg #endif /*-------------------------------------------------------------------*/ /* Working storage */ /*-------------------------------------------------------------------*/ static int init_done = FALSE; static LIST_ENTRY bind_head; /* (bind_struct list anchor) */ static LOCK bind_lock; /* (lock for accessing list) */ /*-------------------------------------------------------------------*/ /* Initialization / termination functions... */ /*-------------------------------------------------------------------*/ static void init_sockdev ( void ); static void term_sockdev ( void* ); static void init_sockdev ( void ) { if (init_done) return; InitializeListHead( &bind_head ); initialize_lock( &bind_lock ); hdl_adsc( "term_sockdev", term_sockdev, NULL ); init_done = TRUE; } static void term_sockdev ( void* arg ) { UNREFERENCED( arg ); if (!init_done) init_sockdev(); SIGNAL_SOCKDEV_THREAD(); join_thread ( sysblk.socktid, NULL ); detach_thread ( sysblk.socktid ); } /*-------------------------------------------------------------------*/ /* unix_socket create and bind a Unix domain socket */ /*-------------------------------------------------------------------*/ int unix_socket (char* path) { #if !defined( HAVE_SYS_UN_H ) UNREFERENCED(path); logmsg (_("HHCSD024E This build does not support Unix domain sockets.\n") ); return -1; #else // defined( HAVE_SYS_UN_H ) struct sockaddr_un addr; int sd; logdebug ("unix_socket(%s)\n", path); if (strlen (path) > sizeof(addr.sun_path) - 1) { logmsg (_("HHCSD008E Socket pathname \"%s\" exceeds limit of %d\n"), path, (int) sizeof(addr.sun_path) - 1); return -1; } addr.sun_family = AF_UNIX; strcpy (addr.sun_path, path); /* guaranteed room by above check */ sd = socket (PF_UNIX, SOCK_STREAM, 0); if (sd == -1) { logmsg (_("HHCSD009E Error creating socket for %s: %s\n"), path, strerror(HSO_errno)); return -1; } unlink (path); fchmod (sd, 0700); if (0 || bind (sd, (struct sockaddr*) &addr, sizeof(addr)) == -1 || listen (sd, 0) == -1 ) { logmsg (_("HHCSD010E Failed to bind or listen on socket %s: %s\n"), path, strerror(HSO_errno)); return -1; } return sd; #endif // !defined( HAVE_SYS_UN_H ) } /*-------------------------------------------------------------------*/ /* inet_socket create and bind a regular TCP/IP socket */ /*-------------------------------------------------------------------*/ int inet_socket (char* spec) { /* We need a copy of the path to overwrite a ':' with '\0' */ char buf[sizeof(((DEVBLK*)0)->filename)]; char* colon; char* node; char* service; int sd; int one = 1; struct sockaddr_in sin; logdebug("inet_socket(%s)\n", spec); memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; strcpy(buf, spec); colon = strchr(buf, ':'); if (colon) { *colon = '\0'; node = buf; service = colon + 1; } else { node = NULL; service = buf; } if (!node) sin.sin_addr.s_addr = INADDR_ANY; else { struct hostent* he = gethostbyname(node); if (!he) { logmsg (_("HHCSD011E Failed to determine IP address from %s\n"), node); return -1; } memcpy(&sin.sin_addr, he->h_addr_list[0], sizeof(sin.sin_addr)); } if (isdigit(service[0])) { sin.sin_port = htons(atoi(service)); } else { struct servent* se = getservbyname(service, "tcp"); if (!se) { logmsg (_("HHCSD012E Failed to determine port number from %s\n"), service); return -1; } sin.sin_port = se->s_port; } sd = socket (PF_INET, SOCK_STREAM, 0); if (sd == -1) { logmsg (_("HHCSD013E Error creating socket for %s: %s\n"), spec, strerror(HSO_errno)); return -1; } setsockopt (sd, SOL_SOCKET, SO_REUSEADDR, (GETSET_SOCKOPT_T*)&one, sizeof(one)); if (0 || bind (sd, (struct sockaddr*) &sin, sizeof(sin)) == -1 || listen (sd, 0) == -1 ) { logmsg (_("HHCSD014E Failed to bind or listen on socket %s: %s\n"), spec, strerror(HSO_errno)); return -1; } return sd; } /*-------------------------------------------------------------------*/ /* add_socket_devices_to_fd_set add all bound socket devices' */ /* listening sockets to the FD_SET */ /*-------------------------------------------------------------------*/ int add_socket_devices_to_fd_set (int maxfd, fd_set* readset) { DEVBLK* dev; bind_struct* bs; LIST_ENTRY* pListEntry; obtain_lock(&bind_lock); pListEntry = bind_head.Flink; while (pListEntry != &bind_head) { bs = CONTAINING_RECORD(pListEntry,bind_struct,bind_link); if (bs->sd != -1) /* if listening for connections, */ { dev = bs->dev; FD_SET(bs->sd, readset); /* then add file to set */ if (bs->sd > maxfd) maxfd = bs->sd; } pListEntry = pListEntry->Flink; } release_lock(&bind_lock); return maxfd; } /*-------------------------------------------------------------------*/ /* socket_device_connection_handler */ /*-------------------------------------------------------------------*/ void socket_device_connection_handler (bind_struct* bs) { struct sockaddr_in client; /* Client address structure */ struct hostent* pHE; /* Addr of hostent structure */ socklen_t namelen; /* Length of client structure*/ char* clientip; /* Addr of client ip address */ char* clientname; /* Addr of client hostname */ DEVBLK* dev; /* Device Block pointer */ int csock; /* Client socket */ dev = bs->dev; logdebug("socket_device_connection_handler(dev=%4.4X)\n", dev->devnum); /* Accept the connection... */ csock = accept(bs->sd, 0, 0); if (csock == -1) { logmsg (_("HHCSD017E Connect to device %4.4X (%s) failed: %s\n"), dev->devnum, bs->spec, strerror(HSO_errno)); return; } /* Determine the connected client's IP address and hostname */ namelen = sizeof(client); clientip = NULL; clientname = ""; if (1 && getpeername(csock, (struct sockaddr*) &client, &namelen) == 0 && (clientip = inet_ntoa(client.sin_addr)) != NULL && (pHE = gethostbyaddr((unsigned char*)(&client.sin_addr), sizeof(client.sin_addr), AF_INET)) != NULL && pHE->h_name && *pHE->h_name ) { clientname = (char*) pHE->h_name; } if (!clientip) clientip = ""; /* Obtain the device lock */ obtain_lock (&dev->lock); /* Reject if device is busy or interrupt pending */ if (dev->busy || IOPENDING(dev) || (dev->scsw.flag3 & SCSW3_SC_PEND)) { close_socket( csock ); logmsg (_("HHCSD015E Client %s (%s) connection to device %4.4X " "(%s) rejected: device busy or interrupt pending\n"), clientname, clientip, dev->devnum, bs->spec); release_lock (&dev->lock); return; } /* Reject new client if previous client still connected */ if (dev->fd != -1) { close_socket( csock ); logmsg (_("HHCSD016E Client %s (%s) connection to device %4.4X " "(%s) rejected: client %s (%s) still connected\n"), clientname, clientip, dev->devnum, bs->spec, bs->clientname, bs->clientip); release_lock (&dev->lock); return; } /* Indicate that a client is now connected to this device */ dev->fd = csock; if (bs->clientip) free(bs->clientip); if (bs->clientname) free(bs->clientname); bs->clientip = strdup(clientip); bs->clientname = strdup(clientname); /* Call the boolean onconnect callback */ if (bs->fn && !bs->fn( bs->arg )) { /* Callback says it can't accept it */ close_socket( dev->fd ); dev->fd = -1; logmsg (_("HHCSD026E Client %s (%s) connection to device %4.4X " "(%s) rejected: by onconnect callback\n"), clientname, clientip, dev->devnum, bs->spec); release_lock (&dev->lock); return; } logmsg (_("HHCSD018I Client %s (%s) connected to device %4.4X (%s)\n"), clientname, clientip, dev->devnum, bs->spec); release_lock (&dev->lock); device_attention (dev, CSW_DE); } /*-------------------------------------------------------------------*/ /* check_socket_devices_for_connections */ /*-------------------------------------------------------------------*/ void check_socket_devices_for_connections (fd_set* readset) { bind_struct* bs; LIST_ENTRY* pListEntry; obtain_lock(&bind_lock); pListEntry = bind_head.Flink; while (pListEntry != &bind_head) { bs = CONTAINING_RECORD(pListEntry,bind_struct,bind_link); if (bs->sd != -1 && FD_ISSET(bs->sd, readset)) { /* Note: there may be other connection requests * waiting to be serviced, but we'll catch them * the next time the panel thread calls us. */ release_lock(&bind_lock); socket_device_connection_handler(bs); return; } pListEntry = pListEntry->Flink; } release_lock(&bind_lock); } /*-------------------------------------------------------------------*/ /* socket_thread listen for socket device connections */ /*-------------------------------------------------------------------*/ void* socket_thread( void* arg ) { int rc; fd_set sockset; int maxfd = 0; int select_errno; int exit_now; UNREFERENCED( arg ); /* Display thread started message on control panel */ logmsg (_("HHCSD020I Socketdevice listener thread started: " "tid="TIDPAT", pid=%d\n"), thread_id(), getpid()); for (;;) { /* Set the file descriptors for select */ FD_ZERO ( &sockset ); maxfd = add_socket_devices_to_fd_set ( 0, &sockset ); SUPPORT_WAKEUP_SOCKDEV_SELECT_VIA_PIPE( maxfd, &sockset ); /* Do the select and save results */ rc = select ( maxfd+1, &sockset, NULL, NULL, NULL ); select_errno = HSO_errno; /* Clear the pipe signal if necessary */ RECV_SOCKDEV_THREAD_PIPE_SIGNAL(); /* Check if it's time to exit yet */ obtain_lock( &bind_lock ); exit_now = ( sysblk.shutdown || IsListEmpty( &bind_head ) ); release_lock( &bind_lock ); if ( exit_now ) break; /* Log select errors */ if ( rc < 0 ) { if ( HSO_EINTR != select_errno ) logmsg( _( "HHCSD021E select failed; errno=%d: %s\n"), select_errno, strerror( select_errno ) ); continue; } /* Check if any sockets have received new connections */ check_socket_devices_for_connections( &sockset ); } logmsg( _( "HHCSD022I Socketdevice listener thread terminated\n" ) ); return NULL; } /* (end socket_thread) */ /*-------------------------------------------------------------------*/ /* bind_device bind a device to a socket (adds entry to our list */ /* of bound devices) (1=success, 0=failure) */ /*-------------------------------------------------------------------*/ int bind_device_ex (DEVBLK* dev, char* spec, ONCONNECT fn, void* arg ) { bind_struct* bs; int was_list_empty; if (!init_done) init_sockdev(); if (sysblk.shutdown) return 0; logdebug("bind_device (%4.4X, %s)\n", dev->devnum, spec); /* Error if device already bound */ if (dev->bs) { logmsg (_("HHCSD001E Device %4.4X already bound to socket %s\n"), dev->devnum, dev->bs->spec); return 0; /* (failure) */ } /* Create a new bind_struct entry */ bs = malloc(sizeof(bind_struct)); if (!bs) { logmsg (_("HHCSD002E bind_device malloc() failed for device %4.4X\n"), dev->devnum); return 0; /* (failure) */ } memset(bs,0,sizeof(bind_struct)); bs->fn = fn; bs->arg = arg; if (!(bs->spec = strdup(spec))) { logmsg (_("HHCSD003E bind_device strdup() failed for device %4.4X\n"), dev->devnum); free (bs); return 0; /* (failure) */ } /* Create a listening socket */ if (bs->spec[0] == '/') bs->sd = unix_socket (bs->spec); else bs->sd = inet_socket (bs->spec); if (bs->sd == -1) { /* (error message already issued) */ free( bs->spec ); free( bs ); return 0; /* (failure) */ } /* Chain device and bind_struct to each other */ dev->bs = bs; bs->dev = dev; /* Add the new entry to our list of bound devices and create the socket thread that will listen for connections (if it doesn't already exist) */ obtain_lock( &bind_lock ); was_list_empty = IsListEmpty( &bind_head ); InsertListTail( &bind_head, &bs->bind_link ); if ( was_list_empty ) { if ( create_thread( &sysblk.socktid, JOINABLE, socket_thread, NULL, "socket_thread" ) ) { logmsg( _( "HHCSD023E Cannot create socketdevice thread: errno=%d: %s\n" ), errno, strerror( errno ) ); RemoveListEntry( &bs->bind_link ); close_socket(bs->sd); free( bs->spec ); free( bs ); release_lock( &bind_lock ); return 0; /* (failure) */ } } SIGNAL_SOCKDEV_THREAD(); release_lock( &bind_lock ); logmsg (_("HHCSD004I Device %4.4X bound to socket %s\n"), dev->devnum, dev->bs->spec); return 1; /* (success) */ } /*-------------------------------------------------------------------*/ /* unbind_device unbind a device from a socket (removes entry from */ /* our list and discards it) (1=success, 0=failure) */ /*-------------------------------------------------------------------*/ int unbind_device_ex (DEVBLK* dev, int forced) { bind_struct* bs; logdebug("unbind_device(%4.4X)\n", dev->devnum); /* Error if device not bound */ if (!(bs = dev->bs)) { logmsg (_("HHCSD005E Device %4.4X not bound to any socket\n"), dev->devnum); return 0; /* (failure) */ } /* Is anyone still connected? */ if (dev->fd != -1) { /* Yes. Should we forcibly disconnect them? */ if (forced) { /* Yes. Then do so... */ close_socket( dev->fd ); dev->fd = -1; logmsg (_("HHCSD025I Client %s (%s) disconnected from device %4.4X (%s)\n"), dev->bs->clientip, dev->bs->clientname, dev->devnum, dev->bs->spec); } else { /* No. Then fail the request. */ logmsg (_("HHCSD006E Client %s (%s) still connected to device %4.4X (%s)\n"), dev->bs->clientip, dev->bs->clientname, dev->devnum, dev->bs->spec); return 0; /* (failure) */ } } /* Remove the entry from our list */ obtain_lock( &bind_lock ); RemoveListEntry( &bs->bind_link ); SIGNAL_SOCKDEV_THREAD(); release_lock( &bind_lock ); logmsg (_("HHCSD007I Device %4.4X unbound from socket %s\n"), dev->devnum, bs->spec); if (bs->sd != -1) close_socket (bs->sd); /* Unchain device and bind_struct from each another */ dev->bs = NULL; bs->dev = NULL; /* Discard the entry */ if ( bs->clientname ) free( bs->clientname ); if ( bs->clientip ) free( bs->clientip ); bs->clientname = NULL; bs->clientip = NULL; free ( bs->spec ); free ( bs ); return 1; /* (success) */ } hercules-3.07/sockdev.h000644 000765 000765 00000005260 11321734033 016552 0ustar00jmaynardjmaynard000000 000000 /* SOCKDEV.H (c) Copyright Hercules development, 2003-2009 */ /* SocketDevice support */ // $Id: sockdev.h 5536 2009-12-11 20:23:16Z bernard $ // // $Log$ // Revision 1.9 2007/06/23 00:04:16 ivan // Update copyright notices to include current year (2007) // // Revision 1.8 2006/12/08 09:43:30 jj // Add CVS message log // #include "htypes.h" // need Herc's struct typedefs #ifndef _SOCKDEV_H_ #define _SOCKDEV_H_ /*-------------------------------------------------------------------*/ /* The sockdev callback function is an optional callback function */ /* that the sockdev connection handler calls after the connection */ /* has been established but before it has logged the connection to */ /* the console. The boolean return code from the callback indicates */ /* true or false (!0 or 0) whether the connection should be accepted */ /* or not. If the return from the callback is 0 (false), the socket */ /* is immediately closed and the "connection not accepted" message */ /* is logged to the console. You should NOT perform any significant */ /* processing in your callback. If you need to do any significant */ /* processing you should instead create a worker to perform it in. */ /*-------------------------------------------------------------------*/ typedef int (*ONCONNECT)( DEVBLK* ); // onconnect callback function (opt) /*-------------------------------------------------------------------*/ /* Bind structure for "Socket Devices" */ /*-------------------------------------------------------------------*/ struct bind_struct // Bind structure for "Socket Devices" { LIST_ENTRY bind_link; // (just a link in the chain) DEVBLK *dev; // ptr to corresponding device block char *spec; // socket_spec for listening socket int sd; // listening socket to use in select // NOTE: Following 2 fields malloc'ed. char *clientname; // connected client's hostname char *clientip; // conencted client's ip address ONCONNECT fn; // ptr to onconnect callback func (opt) void *arg; // argument for callback function (opt) }; /* "Socket Device" functions */ extern int bind_device_ex (DEVBLK* dev, char* spec, ONCONNECT fn, void* arg ); extern int unbind_device_ex (DEVBLK* dev, int forced); static inline int bind_device (DEVBLK* dev, char* spec) { return bind_device_ex ( dev, spec, NULL, NULL ); } static inline int unbind_device (DEVBLK* dev) { return unbind_device_ex ( dev, 0 ); } #endif // _SOCKDEV_H_ hercules-3.07/sr.c000644 000765 000765 00000130371 11321734033 015535 0ustar00jmaynardjmaynard000000 000000 /* SR.C (c)Copyright Greg Smith, 2005-2009 */ /* Suspend/Resume a Hercules session */ // $Id: sr.c 5553 2009-12-23 17:34:16Z ivan $ #include "hstdinc.h" #define _HERCULES_SR_C #define _HENGINE_DLL_ #include "hercules.h" #include "opcode.h" #ifdef OPTION_FISHIO #include "w32chan.h" #endif #include "sr.h" /* subroutine to check for active devices */ DEVBLK *sr_active_devices() { DEVBLK *dev; for (dev = sysblk.firstdev; dev; dev = dev->nextdev) { obtain_lock (&dev->lock); if (dev->busy && !dev->suspended) { if (dev->devtype != 0x3088) { release_lock (&dev->lock); return dev; } else { usleep(50000); dev->busy = 0; } } release_lock (&dev->lock); } return NULL; } int suspend_cmd(int argc, char *argv[],char *cmdline) { char *fn = SR_DEFAULT_FILENAME; SR_FILE *file; CPU_BITMAP started_mask; struct timeval tv; time_t tt; int i, j, rc; REGS *regs; DEVBLK *dev; IOINT *ioq; BYTE psw[16]; UNREFERENCED(cmdline); if (argc > 2) { logmsg( _("HHCSR101E Too many arguments\n")); return -1; } if (argc == 2) fn = argv[1]; file = SR_OPEN (fn, "wb"); if (file == NULL) { logmsg( _("HHCSR102E %s open error: %s\n"),fn,strerror(errno)); return -1; } /* Save CPU state and stop all CPU's */ OBTAIN_INTLOCK(NULL); started_mask = sysblk.started_mask; while (sysblk.started_mask) { for (i = 0; i < MAX_CPU_ENGINES; i++) { if (IS_CPU_ONLINE(i)) { sysblk.regs[i]->cpustate = CPUSTATE_STOPPING; ON_IC_INTERRUPT(sysblk.regs[i]); signal_condition(&sysblk.regs[i]->intcond); } } RELEASE_INTLOCK(NULL); usleep (1000); OBTAIN_INTLOCK(NULL); } RELEASE_INTLOCK(NULL); /* Wait for I/O queue to clear out */ #ifdef OPTION_FISHIO SLEEP (2); #else obtain_lock (&sysblk.ioqlock); while (sysblk.ioq) { release_lock (&sysblk.ioqlock); usleep (1000); obtain_lock (&sysblk.ioqlock); } release_lock (&sysblk.ioqlock); #endif /* Wait for active I/Os to complete */ for (i = 1; i < 5000; i++) { dev = sr_active_devices(); if (dev == NULL) break; if (i % 500 == 0) logmsg( _("HHCSR103W Waiting for device %4.4X\n"), dev->devnum); usleep (10000); } if (dev != NULL) logmsg( _("HHCSR104W Device %4.4X still busy, proceeding anyway\n"), dev->devnum); /* Write header */ SR_WRITE_STRING(file, SR_HDR_ID, SR_ID); SR_WRITE_STRING(file, SR_HDR_VERSION, VERSION); gettimeofday(&tv, NULL); tt = tv.tv_sec; SR_WRITE_STRING(file, SR_HDR_DATE, ctime(&tt)); /* Write system data */ SR_WRITE_STRING(file,SR_SYS_ARCH_NAME,arch_name[sysblk.arch_mode]); SR_WRITE_VALUE (file,SR_SYS_STARTED_MASK,started_mask,sizeof(started_mask)); SR_WRITE_VALUE (file,SR_SYS_MAINSIZE,sysblk.mainsize,sizeof(sysblk.mainsize)); SR_WRITE_BUF (file,SR_SYS_MAINSTOR,sysblk.mainstor,sysblk.mainsize); SR_WRITE_VALUE (file,SR_SYS_SKEYSIZE,sysblk.mainsize/STORAGE_KEY_UNITSIZE,sizeof(int)); SR_WRITE_BUF (file,SR_SYS_STORKEYS,sysblk.storkeys,sysblk.mainsize/STORAGE_KEY_UNITSIZE); SR_WRITE_VALUE (file,SR_SYS_XPNDSIZE,sysblk.xpndsize,sizeof(sysblk.xpndsize)); SR_WRITE_BUF (file,SR_SYS_XPNDSTOR,sysblk.xpndstor,sysblk.xpndsize); SR_WRITE_VALUE (file,SR_SYS_CPUID,sysblk.cpuid,sizeof(sysblk.cpuid)); SR_WRITE_VALUE (file,SR_SYS_IPLDEV,sysblk.ipldev,sizeof(sysblk.ipldev)); SR_WRITE_VALUE (file,SR_SYS_IPLCPU,sysblk.iplcpu,sizeof(sysblk.iplcpu)); SR_WRITE_VALUE (file,SR_SYS_MBO,sysblk.mbo,sizeof(sysblk.mbo)); SR_WRITE_VALUE (file,SR_SYS_MBK,sysblk.mbk,sizeof(sysblk.mbk)); SR_WRITE_VALUE (file,SR_SYS_MBM,sysblk.mbm,sizeof(sysblk.mbm)); SR_WRITE_VALUE (file,SR_SYS_MBD,sysblk.mbd,sizeof(sysblk.mbd)); for (ioq = sysblk.iointq; ioq; ioq = ioq->next) if (ioq->pcipending) { SR_WRITE_VALUE(file,SR_SYS_PCIPENDING_LCSS, SSID_TO_LCSS(ioq->dev->ssid),sizeof(U16)); SR_WRITE_VALUE(file,SR_SYS_PCIPENDING, ioq->dev->devnum,sizeof(ioq->dev->devnum)); } else if (ioq->attnpending) { SR_WRITE_VALUE(file,SR_SYS_ATTNPENDING_LCSS, SSID_TO_LCSS(ioq->dev->ssid),sizeof(U16)); SR_WRITE_VALUE(file,SR_SYS_ATTNPENDING, ioq->dev->devnum,sizeof(ioq->dev->devnum)); } else { SR_WRITE_VALUE(file,SR_SYS_IOPENDING_LCSS, SSID_TO_LCSS(ioq->dev->ssid),sizeof(U16)); SR_WRITE_VALUE(file,SR_SYS_IOPENDING, ioq->dev->devnum,sizeof(ioq->dev->devnum)); } for (i = 0; i < 8; i++) SR_WRITE_VALUE(file,SR_SYS_CHP_RESET+i,sysblk.chp_reset[i],sizeof(sysblk.chp_reset[0])); SR_WRITE_VALUE (file,SR_SYS_SERVPARM,sysblk.servparm,sizeof(sysblk.servparm)); SR_WRITE_VALUE (file,SR_SYS_SIGINTREQ,sysblk.sigintreq,1); SR_WRITE_STRING(file,SR_SYS_LOADPARM,str_loadparm()); SR_WRITE_VALUE (file,SR_SYS_INTS_STATE,sysblk.ints_state,sizeof(sysblk.ints_state)); SR_WRITE_HDR(file, SR_DELIMITER, 0); /* Save service console state */ SR_WRITE_HDR(file, SR_SYS_SERVC, 0); servc_hsuspend(file); SR_WRITE_HDR(file, SR_DELIMITER, 0); /* Save clock state */ SR_WRITE_HDR(file, SR_SYS_CLOCK, 0); clock_hsuspend(file); SR_WRITE_HDR(file, SR_DELIMITER, 0); /* Write CPU data */ for (i = 0; i < MAX_CPU_ENGINES; i++) { if (!IS_CPU_ONLINE(i)) continue; regs = sysblk.regs[i]; SR_WRITE_VALUE(file, SR_CPU, i, sizeof(i)); SR_WRITE_VALUE(file, SR_CPU_ARCHMODE, regs->arch_mode,sizeof(regs->arch_mode)); SR_WRITE_VALUE(file, SR_CPU_PX, regs->PX_G,sizeof(regs->PX_G)); copy_psw (regs, psw); SR_WRITE_BUF(file, SR_CPU_PSW, psw, 16); for (j = 0; j < 16; j++) SR_WRITE_VALUE(file, SR_CPU_GR+j, regs->GR_G(j),sizeof(regs->GR_G(0))); for (j = 0; j < 16; j++) SR_WRITE_VALUE(file, SR_CPU_CR+j, regs->CR_G(j),sizeof(regs->CR_G(0))); for (j = 0; j < 16; j++) SR_WRITE_VALUE(file, SR_CPU_AR+j, regs->ar[j],sizeof(regs->ar[0])); for (j = 0; j < 32; j++) SR_WRITE_VALUE(file, SR_CPU_FPR+j, regs->fpr[j],sizeof(regs->fpr[0])); SR_WRITE_VALUE(file, SR_CPU_FPC, regs->fpc, sizeof(regs->fpc)); SR_WRITE_VALUE(file, SR_CPU_DXC, regs->dxc, sizeof(regs->dxc)); SR_WRITE_VALUE(file, SR_CPU_MC, regs->MC_G, sizeof(regs->MC_G)); SR_WRITE_VALUE(file, SR_CPU_EA, regs->EA_G, sizeof(regs->EA_G)); SR_WRITE_VALUE(file, SR_CPU_PTIMER, cpu_timer(regs), sizeof(S64)); SR_WRITE_VALUE(file, SR_CPU_CLKC, regs->clkc, sizeof(regs->clkc)); SR_WRITE_VALUE(file, SR_CPU_CHANSET, regs->chanset, sizeof(regs->chanset)); SR_WRITE_VALUE(file, SR_CPU_TODPR, regs->todpr, sizeof(regs->todpr)); SR_WRITE_VALUE(file, SR_CPU_MONCLASS, regs->monclass, sizeof(regs->monclass)); SR_WRITE_VALUE(file, SR_CPU_EXCARID, regs->excarid, sizeof(regs->excarid)); SR_WRITE_VALUE(file, SR_CPU_BEAR, regs->bear, sizeof(regs->bear)); SR_WRITE_VALUE(file, SR_CPU_OPNDRID, regs->opndrid, sizeof(regs->opndrid)); SR_WRITE_VALUE(file, SR_CPU_CHECKSTOP, regs->checkstop, 1); SR_WRITE_VALUE(file, SR_CPU_HOSTINT, regs->hostint, 1); SR_WRITE_VALUE(file, SR_CPU_EXECFLAG, regs->execflag, 1); // SR_WRITE_VALUE(file, SR_CPU_INSTVALID, regs->instvalid, 1); SR_WRITE_VALUE(file, SR_CPU_PERMODE, regs->permode, 1); SR_WRITE_VALUE(file, SR_CPU_LOADSTATE, regs->loadstate, 1); SR_WRITE_VALUE(file, SR_CPU_INVALIDATE, regs->invalidate, 1); SR_WRITE_VALUE(file, SR_CPU_SIGPRESET, regs->sigpreset, 1); SR_WRITE_VALUE(file, SR_CPU_SIGPIRESET, regs->sigpireset, 1); SR_WRITE_VALUE(file, SR_CPU_INTS_STATE, regs->ints_state, sizeof(regs->ints_state)); SR_WRITE_VALUE(file, SR_CPU_INTS_MASK, regs->ints_mask, sizeof(regs->ints_mask)); for (j = 0; j < MAX_CPU_ENGINES; j++) SR_WRITE_VALUE(file, SR_CPU_MALFCPU+j, regs->malfcpu[j], sizeof(regs->malfcpu[0])); for (j = 0; j < MAX_CPU_ENGINES; j++) SR_WRITE_VALUE(file, SR_CPU_EMERCPU+j, regs->emercpu[j], sizeof(regs->emercpu[0])); SR_WRITE_VALUE(file, SR_CPU_EXTCCPU, regs->extccpu, sizeof(regs->extccpu)); SR_WRITE_HDR(file, SR_DELIMITER, 0); } /* Write Device data */ for (dev = sysblk.firstdev; dev; dev = dev->nextdev) { if (!(dev->pmcw.flag5 & PMCW5_V)) continue; /* These fields must come first so the device could be attached */ SR_WRITE_VALUE(file, SR_DEV, dev->devnum, sizeof(dev->devnum)); SR_WRITE_VALUE(file, SR_DEV_LCSS, SSID_TO_LCSS(dev->ssid), sizeof(U16)); SR_WRITE_VALUE(file, SR_DEV_ARGC, dev->argc, sizeof(dev->argc)); for (i = 0; i < dev->argc; i++) if (dev->argv[i]) { SR_WRITE_STRING(file, SR_DEV_ARGV, dev->argv[i]); } else { SR_WRITE_STRING(file, SR_DEV_ARGV, ""); } SR_WRITE_STRING(file, SR_DEV_TYPNAME, dev->typname); /* Common device fields */ SR_WRITE_BUF (file, SR_DEV_ORB, &dev->orb, sizeof(ORB)); SR_WRITE_BUF (file, SR_DEV_PMCW, &dev->pmcw, sizeof(PMCW)); SR_WRITE_BUF (file, SR_DEV_SCSW, &dev->scsw, sizeof(SCSW)); SR_WRITE_BUF (file, SR_DEV_PCISCSW, &dev->pciscsw, sizeof(SCSW)); SR_WRITE_BUF (file, SR_DEV_ATTNSCSW, &dev->attnscsw, sizeof(SCSW)); SR_WRITE_BUF (file, SR_DEV_CSW, dev->csw, 8); SR_WRITE_BUF (file, SR_DEV_PCICSW, dev->pcicsw, 8); SR_WRITE_BUF (file, SR_DEV_ATTNCSW, dev->attncsw, 8); SR_WRITE_BUF (file, SR_DEV_ESW, &dev->esw, sizeof(ESW)); SR_WRITE_BUF (file, SR_DEV_ECW, dev->ecw, 32); SR_WRITE_BUF (file, SR_DEV_SENSE, dev->sense, 32); SR_WRITE_VALUE(file, SR_DEV_PGSTAT, dev->pgstat, sizeof(dev->pgstat)); SR_WRITE_BUF (file, SR_DEV_PGID, dev->pgid, 11); /* By Adrian - SR_DEV_DRVPWD */ SR_WRITE_BUF (file, SR_DEV_DRVPWD, dev->drvpwd, 11); SR_WRITE_VALUE(file, SR_DEV_BUSY, dev->busy, 1); SR_WRITE_VALUE(file, SR_DEV_RESERVED, dev->reserved, 1); SR_WRITE_VALUE(file, SR_DEV_SUSPENDED, dev->suspended, 1); SR_WRITE_VALUE(file, SR_DEV_PCIPENDING, dev->pcipending, 1); SR_WRITE_VALUE(file, SR_DEV_ATTNPENDING, dev->attnpending, 1); SR_WRITE_VALUE(file, SR_DEV_PENDING, dev->pending, 1); SR_WRITE_VALUE(file, SR_DEV_STARTPENDING, dev->startpending, 1); SR_WRITE_VALUE(file, SR_DEV_CRWPENDING, dev->crwpending, 1); SR_WRITE_VALUE(file, SR_DEV_CCWADDR, dev->ccwaddr, sizeof(dev->ccwaddr)); SR_WRITE_VALUE(file, SR_DEV_IDAPMASK, dev->idapmask, sizeof(dev->idapmask)); SR_WRITE_VALUE(file, SR_DEV_IDAWFMT, dev->idawfmt, sizeof(dev->idawfmt)); SR_WRITE_VALUE(file, SR_DEV_CCWFMT, dev->ccwfmt, sizeof(dev->ccwfmt)); SR_WRITE_VALUE(file, SR_DEV_CCWKEY, dev->ccwkey, sizeof(dev->ccwkey)); /* Device type specific data */ SR_WRITE_VALUE(file, SR_DEV_DEVTYPE, dev->devtype, sizeof(dev->devtype)); if (dev->hnd->hsuspend) { rc = (dev->hnd->hsuspend) (dev, file); if (rc < 0) goto sr_error_exit; } SR_WRITE_HDR(file, SR_DELIMITER, 0); } SR_WRITE_HDR(file, SR_EOF, 0); SR_CLOSE (file); /* Shutdown */ do_shutdown(); return 0; sr_write_error: logmsg(_("HHCSR010E write error: %s\n"), strerror(errno)); goto sr_error_exit; sr_value_error: logmsg(_("HHCSR013E value error, incorrect length\n")); goto sr_error_exit; sr_string_error: logmsg(_("HHCSR014E string error, incorrect length\n")); goto sr_error_exit; sr_error_exit: logmsg(_("HHCSR015E error processing file %s\n"),fn); SR_CLOSE (file); return -1; } int resume_cmd(int argc, char *argv[],char *cmdline) { char *fn = SR_DEFAULT_FILENAME; SR_FILE *file; U32 key = 0, len = 0; CPU_BITMAP started_mask = 0; int i, rc; REGS *regs = NULL; U16 devnum=0; U16 lcss=0; U16 hw; int devargc; char *devargv[16]; int devargx=0; DEVBLK *dev = NULL; IOINT *ioq = NULL; char buf[SR_MAX_STRING_LENGTH+1]; char zeros[16]; S64 dreg; UNREFERENCED(cmdline); if (argc > 2) { logmsg( _("HHCSR101E Too many arguments\n")); return -1; } if (argc == 2) fn = argv[1]; memset (zeros, 0, sizeof(zeros)); /* Make sure all CPUs are deconfigured or stopped */ OBTAIN_INTLOCK(NULL); for (i = 0; i < MAX_CPU_ENGINES; i++) if (IS_CPU_ONLINE(i) && CPUSTATE_STOPPED != sysblk.regs[i]->cpustate) { RELEASE_INTLOCK(NULL); logmsg( _("HHCSR103E All CPU's must be stopped to resume\n") ); return -1; } RELEASE_INTLOCK(NULL); file = SR_OPEN (fn, "rb"); if (file == NULL) { logmsg( _("HHCSR102E %s open error: %s\n"),fn,strerror(errno)); return -1; } /* First key must be SR_HDR_ID and string must match SR_ID */ SR_READ_HDR(file, key, len); if (key == SR_HDR_ID) SR_READ_STRING(file, buf, len); if (key != SR_HDR_ID || strcmp(buf, SR_ID)) { logmsg( _("HHCSR104E File identifier error\n")); goto sr_error_exit; } /* Deconfigure all CPUs */ OBTAIN_INTLOCK(NULL); for (i = 0; i < MAX_CPU_ENGINES; i++) if (IS_CPU_ONLINE(i)) deconfigure_cpu(i); RELEASE_INTLOCK(NULL); while (key != SR_EOF) { SR_READ_HDR(file, key, len); switch (key) { case SR_HDR_DATE: SR_READ_STRING(file, buf, len); logmsg( _("HHCSR001I Resuming suspended file created %s"), buf); break; case SR_SYS_STARTED_MASK: SR_READ_VALUE(file, len, &started_mask, sizeof(started_mask)); break; case SR_SYS_ARCH_NAME: SR_READ_STRING(file, buf, len); i = -1; #if defined (_370) if (strcasecmp (buf, arch_name[ARCH_370]) == 0) { i = ARCH_370; sysblk.maxcpu = sysblk.numcpu; } #endif #if defined (_390) if (strcasecmp (buf, arch_name[ARCH_390]) == 0) { i = ARCH_390; #if defined(_FEATURE_CPU_RECONFIG) sysblk.maxcpu = MAX_CPU_ENGINES; #else sysblk.maxcpu = sysblk.numcpu; #endif } #endif #if defined (_900) if (0 || strcasecmp (buf, arch_name[ARCH_900]) == 0 || strcasecmp (buf, "ESAME") == 0 ) { i = ARCH_900; #if defined(_FEATURE_CPU_RECONFIG) sysblk.maxcpu = MAX_CPU_ENGINES; #else sysblk.maxcpu = sysblk.numcpu; #endif } #endif if (i < 0) { logmsg( _("HHCSR105E Archmode %s not supported\n"), buf); goto sr_error_exit; } sysblk.arch_mode = i; #if defined (_900) sysblk.arch_z900 = sysblk.arch_mode != ARCH_390; #endif sysblk.pcpu = 0; sysblk.dummyregs.arch_mode = sysblk.arch_mode; #if defined(OPTION_FISHIO) ios_arch_mode = sysblk.arch_mode; #endif break; case SR_SYS_MAINSIZE: SR_READ_VALUE(file, len, &len, sizeof(len)); if (len > sysblk.mainsize) { logmsg( _("HHCSR106E Mainsize mismatch: %d" "M expected %d" "M\n"), len / (1024*1024), sysblk.mainsize / (1024*1024)); goto sr_error_exit; } break; case SR_SYS_MAINSTOR: if (len > sysblk.mainsize) { logmsg( _("HHCSR107E Mainsize mismatch: %d" "M expected %d" "M\n"), len / (1024*1024), sysblk.mainsize / (1024*1024)); goto sr_error_exit; } SR_READ_BUF(file, sysblk.mainstor, len); break; case SR_SYS_SKEYSIZE: SR_READ_VALUE(file, len, &len, sizeof(len)); if (len > sysblk.mainsize/STORAGE_KEY_UNITSIZE) { logmsg( _("HHCSR108E Storkey size mismatch: %d expected %d\n"), len, sysblk.mainsize/STORAGE_KEY_UNITSIZE); goto sr_error_exit; } break; case SR_SYS_STORKEYS: if (len > sysblk.mainsize/STORAGE_KEY_UNITSIZE) { logmsg( _("HHCSR109E Storkey size mismatch: %d expected %d\n"), len, sysblk.mainsize/STORAGE_KEY_UNITSIZE); goto sr_error_exit; } SR_READ_BUF(file, sysblk.storkeys, len); break; case SR_SYS_XPNDSIZE: SR_READ_VALUE(file, len, &len, sizeof(len)); if (len > sysblk.xpndsize) { logmsg( _("HHCSR110E Xpndsize mismatch: %d" "M expected %d" "M\n"), len / (1024*1024), sysblk.xpndsize / (1024*1024)); goto sr_error_exit; } break; case SR_SYS_XPNDSTOR: if (len > sysblk.xpndsize) { logmsg( _("HHCSR111E Xpndsize mismatch: %d" "M expected %d" "M\n"), len / (1024*1024), sysblk.xpndsize / (1024*1024)); goto sr_error_exit; } SR_READ_BUF(file, sysblk.xpndstor, len); break; case SR_SYS_IPLDEV: SR_READ_VALUE(file, len, &sysblk.ipldev, sizeof(sysblk.ipldev)); break; case SR_SYS_IPLCPU: SR_READ_VALUE(file, len, &sysblk.iplcpu, sizeof(sysblk.iplcpu)); break; case SR_SYS_MBO: SR_READ_VALUE(file, len, &sysblk.mbo, sizeof(sysblk.mbo)); break; case SR_SYS_MBK: SR_READ_VALUE(file, len, &sysblk.mbk, sizeof(sysblk.mbk)); break; case SR_SYS_MBM: SR_READ_VALUE(file, len, &sysblk.mbm, sizeof(sysblk.mbm)); break; case SR_SYS_MBD: SR_READ_VALUE(file, len, &sysblk.mbd, sizeof(sysblk.mbd)); break; case SR_SYS_IOPENDING_LCSS: SR_READ_VALUE(file,len,&lcss,sizeof(lcss)); break; case SR_SYS_IOPENDING: SR_READ_VALUE(file, len, &hw, sizeof(hw)); dev = find_device_by_devnum(lcss,hw); if (dev == NULL) break; if (ioq == NULL) sysblk.iointq = &dev->ioint; else ioq->next = &dev->ioint; ioq = &dev->ioint; dev = NULL; lcss = 0; break; case SR_SYS_PCIPENDING_LCSS: SR_READ_VALUE(file,len,&lcss,sizeof(lcss)); break; case SR_SYS_PCIPENDING: SR_READ_VALUE(file, len, &hw, sizeof(hw)); dev = find_device_by_devnum(lcss,hw); if (dev == NULL) break; if (ioq == NULL) sysblk.iointq = &dev->pciioint; else ioq->next = &dev->pciioint; ioq = &dev->pciioint; dev = NULL; lcss = 0; break; case SR_SYS_ATTNPENDING_LCSS: SR_READ_VALUE(file,len,&lcss,sizeof(lcss)); break; case SR_SYS_ATTNPENDING: SR_READ_VALUE(file, len, &hw, sizeof(hw)); dev = find_device_by_devnum(lcss,hw); if (dev == NULL) break; if (ioq == NULL) sysblk.iointq = &dev->attnioint; else ioq->next = &dev->attnioint; ioq = &dev->attnioint; dev = NULL; lcss = 0; break; case SR_SYS_CHP_RESET_0: case SR_SYS_CHP_RESET_1: case SR_SYS_CHP_RESET_2: case SR_SYS_CHP_RESET_3: case SR_SYS_CHP_RESET_4: case SR_SYS_CHP_RESET_5: case SR_SYS_CHP_RESET_6: case SR_SYS_CHP_RESET_7: i = key - SR_SYS_CHP_RESET; SR_READ_VALUE(file, len, &sysblk.chp_reset[i], sizeof(sysblk.chp_reset[0])); break; case SR_SYS_SERVPARM: SR_READ_VALUE(file, len, &sysblk.servparm, sizeof(sysblk.servparm)); break; case SR_SYS_SIGINTREQ: SR_READ_VALUE(file, len, &rc, sizeof(rc)); sysblk.sigintreq = rc; break; case SR_SYS_LOADPARM: SR_READ_STRING(file, buf, len); set_loadparm ((char *)buf); break; case SR_SYS_SERVC: rc = servc_hresume(file); if (rc < 0) goto sr_error_exit; break; case SR_SYS_CLOCK: rc = clock_hresume(file); if (rc < 0) goto sr_error_exit; break; case SR_CPU: SR_READ_VALUE(file, len, &i, sizeof(i)); if (i >= MAX_CPU_ENGINES) { logmsg( _("HHCSR113E CPU%4.4d exceeds max allowed cpu (%d)\n"), i, MAX_CPU_ENGINES-1); goto sr_error_exit; } OBTAIN_INTLOCK(NULL); if (IS_CPU_ONLINE(i)) { RELEASE_INTLOCK(NULL); logmsg( _("HHCSR114E CPU%4.4d already configured\n"), i); goto sr_error_exit; } rc = configure_cpu(i); RELEASE_INTLOCK(NULL); if (rc < 0) { logmsg( _("HHCSR115E CPU%4.4d unable to configure online\n"), i); goto sr_error_exit; } regs = sysblk.regs[i]; break; case SR_CPU_PX: if (regs == NULL) goto sr_null_regs_exit; SR_READ_VALUE(file, len, ®s->px, sizeof(regs->px)); break; case SR_CPU_PSW: if (regs == NULL) goto sr_null_regs_exit; if (len != 8 && len != 16) { logmsg( _("HHCSR116E CPU%4.4d invalid psw length (%d)\n"), regs->cpuad, len); goto sr_error_exit; } memset(buf, 0, 16); SR_READ_BUF(file, buf, len); switch (regs->arch_mode) { #if defined (_370) case ARCH_370: len = 8; rc = s370_load_psw(regs, (BYTE *)&buf); break; #endif #if defined (_390) case ARCH_390: len = 8; rc = s390_load_psw(regs, (BYTE *)&buf); break; #endif #if defined (_900) case ARCH_900: len = 16; rc = z900_load_psw(regs, (BYTE *)&buf); break; #endif } /* switch (regs->arch_mode) */ if (rc != 0 && memcmp(buf, zeros, len)) { logmsg( _("HHCSR117E CPU%4.4d error loading psw (%d)\n"), regs->cpuad, rc); goto sr_error_exit; } break; case SR_CPU_GR_0: case SR_CPU_GR_1: case SR_CPU_GR_2: case SR_CPU_GR_3: case SR_CPU_GR_4: case SR_CPU_GR_5: case SR_CPU_GR_6: case SR_CPU_GR_7: case SR_CPU_GR_8: case SR_CPU_GR_9: case SR_CPU_GR_10: case SR_CPU_GR_11: case SR_CPU_GR_12: case SR_CPU_GR_13: case SR_CPU_GR_14: case SR_CPU_GR_15: if (regs == NULL) goto sr_null_regs_exit; i = key - SR_CPU_GR; SR_READ_VALUE(file, len, ®s->gr[i], sizeof(regs->gr[0])); break; case SR_CPU_CR_0: case SR_CPU_CR_1: case SR_CPU_CR_2: case SR_CPU_CR_3: case SR_CPU_CR_4: case SR_CPU_CR_5: case SR_CPU_CR_6: case SR_CPU_CR_7: case SR_CPU_CR_8: case SR_CPU_CR_9: case SR_CPU_CR_10: case SR_CPU_CR_11: case SR_CPU_CR_12: case SR_CPU_CR_13: case SR_CPU_CR_14: case SR_CPU_CR_15: if (regs == NULL) goto sr_null_regs_exit; i = key - SR_CPU_CR; SR_READ_VALUE(file, len, ®s->cr[i], sizeof(regs->cr[0])); break; case SR_CPU_AR_0: case SR_CPU_AR_1: case SR_CPU_AR_2: case SR_CPU_AR_3: case SR_CPU_AR_4: case SR_CPU_AR_5: case SR_CPU_AR_6: case SR_CPU_AR_7: case SR_CPU_AR_8: case SR_CPU_AR_9: case SR_CPU_AR_10: case SR_CPU_AR_11: case SR_CPU_AR_12: case SR_CPU_AR_13: case SR_CPU_AR_14: case SR_CPU_AR_15: if (regs == NULL) goto sr_null_regs_exit; i = key - SR_CPU_AR; SR_READ_VALUE(file, len, ®s->ar[i], sizeof(regs->ar[0])); break; case SR_CPU_FPR_0: case SR_CPU_FPR_1: case SR_CPU_FPR_2: case SR_CPU_FPR_3: case SR_CPU_FPR_4: case SR_CPU_FPR_5: case SR_CPU_FPR_6: case SR_CPU_FPR_7: case SR_CPU_FPR_8: case SR_CPU_FPR_9: case SR_CPU_FPR_10: case SR_CPU_FPR_11: case SR_CPU_FPR_12: case SR_CPU_FPR_13: case SR_CPU_FPR_14: case SR_CPU_FPR_15: case SR_CPU_FPR_16: case SR_CPU_FPR_17: case SR_CPU_FPR_18: case SR_CPU_FPR_19: case SR_CPU_FPR_20: case SR_CPU_FPR_21: case SR_CPU_FPR_22: case SR_CPU_FPR_23: case SR_CPU_FPR_24: case SR_CPU_FPR_25: case SR_CPU_FPR_26: case SR_CPU_FPR_27: case SR_CPU_FPR_28: case SR_CPU_FPR_29: case SR_CPU_FPR_30: case SR_CPU_FPR_31: if (regs == NULL) goto sr_null_regs_exit; i = key - SR_CPU_FPR; SR_READ_VALUE(file, len, ®s->fpr[i], sizeof(regs->fpr[0])); break; case SR_CPU_FPC: if (regs == NULL) goto sr_null_regs_exit; SR_READ_VALUE(file, len, ®s->fpc, sizeof(regs->fpc)); break; case SR_CPU_DXC: if (regs == NULL) goto sr_null_regs_exit; SR_READ_VALUE(file, len, ®s->dxc, sizeof(regs->dxc)); break; case SR_CPU_MC: if (regs == NULL) goto sr_null_regs_exit; SR_READ_VALUE(file, len, ®s->mc, sizeof(regs->mc)); break; case SR_CPU_EA: if (regs == NULL) goto sr_null_regs_exit; SR_READ_VALUE(file, len, ®s->ea, sizeof(regs->ea)); break; case SR_CPU_PTIMER: if (regs == NULL) goto sr_null_regs_exit; SR_READ_VALUE(file, len, &dreg, sizeof(S64)); set_cpu_timer(regs, dreg); break; case SR_CPU_CLKC: if (regs == NULL) goto sr_null_regs_exit; SR_READ_VALUE(file, len, ®s->clkc, sizeof(regs->clkc)); break; case SR_CPU_CHANSET: if (regs == NULL) goto sr_null_regs_exit; SR_READ_VALUE(file, len, ®s->chanset, sizeof(regs->chanset)); break; case SR_CPU_TODPR: if (regs == NULL) goto sr_null_regs_exit; SR_READ_VALUE(file, len, ®s->todpr, sizeof(regs->todpr)); break; case SR_CPU_MONCLASS: if (regs == NULL) goto sr_null_regs_exit; SR_READ_VALUE(file, len, ®s->monclass, sizeof(regs->monclass)); break; case SR_CPU_EXCARID: if (regs == NULL) goto sr_null_regs_exit; SR_READ_VALUE(file, len, ®s->excarid, sizeof(regs->excarid)); break; case SR_CPU_BEAR: if (regs == NULL) goto sr_null_regs_exit; SR_READ_VALUE(file, len, ®s->bear, sizeof(regs->bear)); break; case SR_CPU_OPNDRID: if (regs == NULL) goto sr_null_regs_exit; SR_READ_VALUE(file, len, ®s->opndrid, sizeof(regs->opndrid)); break; case SR_CPU_CHECKSTOP: if (regs == NULL) goto sr_null_regs_exit; SR_READ_VALUE(file, len, &rc, sizeof(rc)); regs->checkstop = rc; break; case SR_CPU_HOSTINT: if (regs == NULL) goto sr_null_regs_exit; SR_READ_VALUE(file, len, &rc, sizeof(rc)); regs->hostint = rc; break; case SR_CPU_LOADSTATE: if (regs == NULL) goto sr_null_regs_exit; SR_READ_VALUE(file, len, &rc, sizeof(rc)); regs->loadstate = rc; break; case SR_CPU_INVALIDATE: if (regs == NULL) goto sr_null_regs_exit; SR_READ_VALUE(file, len, &rc, sizeof(rc)); regs->invalidate = rc; break; case SR_CPU_SIGPRESET: if (regs == NULL) goto sr_null_regs_exit; SR_READ_VALUE(file, len, &rc, sizeof(rc)); regs->sigpreset = rc; break; case SR_CPU_SIGPIRESET: if (regs == NULL) goto sr_null_regs_exit; SR_READ_VALUE(file, len, &rc, sizeof(rc)); regs->sigpireset = rc; break; case SR_CPU_INTS_STATE: if (regs == NULL) goto sr_null_regs_exit; SR_READ_VALUE(file, len, ®s->ints_state, sizeof(regs->ints_state)); /* Force CPU to examine the interrupt state */ ON_IC_INTERRUPT(regs); break; case SR_CPU_INTS_MASK: if (regs == NULL) goto sr_null_regs_exit; SR_READ_VALUE(file, len, ®s->ints_mask, sizeof(regs->ints_mask)); break; case SR_CPU_MALFCPU_0: case SR_CPU_MALFCPU_1: case SR_CPU_MALFCPU_2: case SR_CPU_MALFCPU_3: case SR_CPU_MALFCPU_4: case SR_CPU_MALFCPU_5: case SR_CPU_MALFCPU_6: case SR_CPU_MALFCPU_7: case SR_CPU_MALFCPU_8: case SR_CPU_MALFCPU_9: case SR_CPU_MALFCPU_10: case SR_CPU_MALFCPU_11: case SR_CPU_MALFCPU_12: case SR_CPU_MALFCPU_13: case SR_CPU_MALFCPU_14: case SR_CPU_MALFCPU_15: case SR_CPU_MALFCPU_16: case SR_CPU_MALFCPU_17: case SR_CPU_MALFCPU_18: case SR_CPU_MALFCPU_19: case SR_CPU_MALFCPU_20: case SR_CPU_MALFCPU_21: case SR_CPU_MALFCPU_22: case SR_CPU_MALFCPU_23: case SR_CPU_MALFCPU_24: case SR_CPU_MALFCPU_25: case SR_CPU_MALFCPU_26: case SR_CPU_MALFCPU_27: case SR_CPU_MALFCPU_28: case SR_CPU_MALFCPU_29: case SR_CPU_MALFCPU_30: case SR_CPU_MALFCPU_31: if (regs == NULL) goto sr_null_regs_exit; i = key - SR_CPU_MALFCPU; if (i < MAX_CPU_ENGINES) SR_READ_VALUE(file, len, ®s->malfcpu[i], sizeof(regs->malfcpu[0])); break; case SR_CPU_EMERCPU_0: case SR_CPU_EMERCPU_1: case SR_CPU_EMERCPU_2: case SR_CPU_EMERCPU_3: case SR_CPU_EMERCPU_4: case SR_CPU_EMERCPU_5: case SR_CPU_EMERCPU_6: case SR_CPU_EMERCPU_7: case SR_CPU_EMERCPU_8: case SR_CPU_EMERCPU_9: case SR_CPU_EMERCPU_10: case SR_CPU_EMERCPU_11: case SR_CPU_EMERCPU_12: case SR_CPU_EMERCPU_13: case SR_CPU_EMERCPU_14: case SR_CPU_EMERCPU_15: case SR_CPU_EMERCPU_16: case SR_CPU_EMERCPU_17: case SR_CPU_EMERCPU_18: case SR_CPU_EMERCPU_19: case SR_CPU_EMERCPU_20: case SR_CPU_EMERCPU_21: case SR_CPU_EMERCPU_22: case SR_CPU_EMERCPU_23: case SR_CPU_EMERCPU_24: case SR_CPU_EMERCPU_25: case SR_CPU_EMERCPU_26: case SR_CPU_EMERCPU_27: case SR_CPU_EMERCPU_28: case SR_CPU_EMERCPU_29: case SR_CPU_EMERCPU_30: case SR_CPU_EMERCPU_31: if (regs == NULL) goto sr_null_regs_exit; i = key - SR_CPU_EMERCPU; if (i < MAX_CPU_ENGINES) SR_READ_VALUE(file, len, ®s->emercpu[i], sizeof(regs->emercpu[0])); break; case SR_DEV: SR_READ_VALUE(file, len, &devnum, sizeof(devnum)); lcss=0; break; case SR_DEV_LCSS: SR_READ_VALUE(file, len, &lcss, sizeof(U16)); break; case SR_DEV_ARGC: SR_READ_VALUE(file, len, &devargc, sizeof(devargc)); if (devargc > 16) devargc = 16; for (i = 0; i < devargc; i++) devargv[i] = NULL; devargx = 0; break; case SR_DEV_ARGV: SR_READ_STRING(file, buf, len); if (devargx < devargc) devargv[devargx++] = strdup(buf); break; case SR_DEV_TYPNAME: SR_READ_STRING(file, buf, len); dev = find_device_by_devnum(lcss,devnum); if (dev == NULL) { if (attach_device (lcss, devnum, buf, devargc, devargv)) { logmsg( _("HHCSR118W Device %4.4X initialization failed\n"), devnum); } } else if (strcmp(dev->typname, buf)) { logmsg( _("HHCSR119W Device %4.4X type mismatch; %s expected %s\n"), devnum, buf, dev->typname); dev = NULL; } for (i = 0; i < devargx; i++) { if (devargv[i]) free(devargv[i]); devargv[i] = NULL; } devnum = devargc = devargx = 0; break; case SR_DEV_ORB: SR_SKIP_NULL_DEV(dev, file, len); if (len != sizeof(ORB)) { logmsg( _("HHCSR120E Device %4.4X ORB size mismatch: %d expected %d\n"), dev->devnum, len, sizeof(ORB)); goto sr_error_exit; } SR_READ_BUF(file, &dev->orb, len); break; case SR_DEV_PMCW: SR_SKIP_NULL_DEV(dev, file, len); if (len != sizeof(PMCW)) { logmsg( _("HHCSR121E Device %4.4X PMCW size mismatch: %d expected %d\n"), dev->devnum, len, sizeof(PMCW)); goto sr_error_exit; } SR_READ_BUF(file, &dev->pmcw, len); break; case SR_DEV_SCSW: SR_SKIP_NULL_DEV(dev, file, len); if (len != sizeof(SCSW)) { logmsg( _("HHCSR122E Device %4.4X SCSW size mismatch: %d expected %d\n"), dev->devnum, len, sizeof(SCSW)); goto sr_error_exit; } SR_READ_BUF(file, &dev->scsw, len); break; case SR_DEV_PCISCSW: SR_SKIP_NULL_DEV(dev, file, len); if (len != sizeof(SCSW)) { logmsg( _("HHCSR123E Device %4.4X PCI SCSW size mismatch: %d expected %d\n"), dev->devnum, len, sizeof(SCSW)); goto sr_error_exit; } SR_READ_BUF(file, &dev->pciscsw, len); break; case SR_DEV_ATTNSCSW: SR_SKIP_NULL_DEV(dev, file, len); if (len != sizeof(SCSW)) { logmsg( _("HHCSR124E Device %4.4X Attn SCSW size mismatch: %d expected %d\n"), dev->devnum, len, sizeof(SCSW)); goto sr_error_exit; } SR_READ_BUF(file, &dev->attnscsw, len); break; case SR_DEV_CSW: SR_SKIP_NULL_DEV(dev, file, len); if (len != 8) { logmsg( _("HHCSR125E Device %4.4X CSW size mismatch: %d expected %d\n"), dev->devnum, len, 8); goto sr_error_exit; } SR_READ_BUF(file, &dev->csw, len); break; case SR_DEV_PCICSW: SR_SKIP_NULL_DEV(dev, file, len); if (len != 8) { logmsg( _("HHCSR126E Device %4.4X PCI CSW size mismatch: %d expected %d\n"), dev->devnum, len, 8); goto sr_error_exit; } SR_READ_BUF(file, &dev->pcicsw, len); break; case SR_DEV_ATTNCSW: SR_SKIP_NULL_DEV(dev, file, len); if (len != 8) { logmsg( _("HHCSR127E Device %4.4X Attn CSW size mismatch: %d expected %d\n"), dev->devnum, len, 8); goto sr_error_exit; } SR_READ_BUF(file, &dev->attncsw, len); break; case SR_DEV_ESW: SR_SKIP_NULL_DEV(dev, file, len); if (len != sizeof(ESW)) { logmsg( _("HHCSR128E Device %4.4X ESW size mismatch: %d expected %d\n"), dev->devnum, len, sizeof(ESW)); goto sr_error_exit; } SR_READ_BUF(file, &dev->esw, len); break; case SR_DEV_ECW: SR_SKIP_NULL_DEV(dev, file, len); if (len != 32) { logmsg( _("HHCSR129E Device %4.4X ECW size mismatch: %d expected %d\n"), dev->devnum, len, 32); goto sr_error_exit; } SR_READ_BUF(file, &dev->ecw, len); break; case SR_DEV_SENSE: SR_SKIP_NULL_DEV(dev, file, len); if (len != 32) { logmsg( _("HHCSR130E Device %4.4X Sense size mismatch: %d expected %d\n"), dev->devnum, len, 32); goto sr_error_exit; } SR_READ_BUF(file, &dev->ecw, len); break; case SR_DEV_PGSTAT: SR_SKIP_NULL_DEV(dev, file, len); SR_READ_VALUE(file, len, &dev->pgstat, sizeof(dev->pgstat)); break; case SR_DEV_PGID: SR_SKIP_NULL_DEV(dev, file, len); if (len != 11) { logmsg( _("HHCSR131E Device %4.4X PGID size mismatch: %d expected %d\n"), dev->devnum, len, 11); goto sr_error_exit; } SR_READ_BUF(file, &dev->pgid, len); break; /* By Adrian - SR_DEV_DRVPWD */ case SR_DEV_DRVPWD: SR_SKIP_NULL_DEV(dev, file, len); if (len != 11) { logmsg( _("HHCSR134E Device %4.4X DRVPWD size mismatch: %d expected %d\n"), dev->devnum, len, 11); goto sr_error_exit; } SR_READ_BUF(file, &dev->drvpwd, len); break; case SR_DEV_BUSY: SR_SKIP_NULL_DEV(dev, file, len); SR_READ_VALUE(file, len, &rc, sizeof(rc)); dev->busy = rc; break; case SR_DEV_RESERVED: SR_SKIP_NULL_DEV(dev, file, len); SR_READ_VALUE(file, len, &rc, sizeof(rc)); dev->reserved = rc; break; case SR_DEV_SUSPENDED: SR_SKIP_NULL_DEV(dev, file, len); SR_READ_VALUE(file, len, &rc, sizeof(rc)); dev->suspended = rc; break; case SR_DEV_PENDING: SR_SKIP_NULL_DEV(dev, file, len); SR_READ_VALUE(file, len, &rc, sizeof(rc)); dev->pending = rc; QUEUE_IO_INTERRUPT(&dev->ioint); break; case SR_DEV_PCIPENDING: SR_SKIP_NULL_DEV(dev, file, len); SR_READ_VALUE(file, len, &rc, sizeof(rc)); dev->pcipending = rc; QUEUE_IO_INTERRUPT(&dev->pciioint); break; case SR_DEV_ATTNPENDING: SR_SKIP_NULL_DEV(dev, file, len); SR_READ_VALUE(file, len, &rc, sizeof(rc)); dev->attnpending = rc; QUEUE_IO_INTERRUPT(&dev->attnioint); break; case SR_DEV_STARTPENDING: SR_SKIP_NULL_DEV(dev, file, len); SR_READ_VALUE(file, len, &rc, sizeof(rc)); dev->startpending = rc; break; case SR_DEV_CRWPENDING: SR_SKIP_NULL_DEV(dev, file, len); SR_READ_VALUE(file, len, &rc, sizeof(rc)); dev->crwpending = rc; break; case SR_DEV_CCWADDR: SR_SKIP_NULL_DEV(dev, file, len); SR_READ_VALUE(file, len, &dev->ccwaddr, sizeof(dev->ccwaddr)); break; case SR_DEV_IDAPMASK: SR_SKIP_NULL_DEV(dev, file, len); SR_READ_VALUE(file, len, &dev->idapmask, sizeof(dev->idapmask)); break; case SR_DEV_IDAWFMT: SR_SKIP_NULL_DEV(dev, file, len); SR_READ_VALUE(file, len, &dev->idawfmt, sizeof(dev->idawfmt)); break; case SR_DEV_CCWFMT: SR_SKIP_NULL_DEV(dev, file, len); SR_READ_VALUE(file, len, &dev->ccwfmt, sizeof(dev->ccwfmt)); break; case SR_DEV_CCWKEY: SR_SKIP_NULL_DEV(dev, file, len); SR_READ_VALUE(file, len, &dev->ccwkey, sizeof(dev->ccwkey)); break; /* This is the trigger to call the device dependent resume routine */ case SR_DEV_DEVTYPE: SR_SKIP_NULL_DEV(dev, file, len); SR_READ_VALUE(file, len, &hw, sizeof(hw)); if (hw != dev->devtype) { logmsg( _("HHCSR132E Device %4.4X type mismatch: %4.4x expected %4.4x\n"), dev->devnum, hw, dev->devtype); goto sr_error_exit; } if (dev->hnd->hresume) { rc = (dev->hnd->hresume) (dev, file); if (rc < 0) goto sr_error_exit; } break; default: if ((key & SR_KEY_ID_MASK) != SR_KEY_ID) { logmsg( _("HHCSR999E Invalid key %8.8x\n"), key); goto sr_error_exit; } SR_READ_SKIP(file, len); break; } /* switch (key) */ } /* while (key != SR_EOF) */ /* For all suspended devices, resume the `suspended' state */ for (dev = sysblk.firstdev; dev; dev = dev->nextdev) { if (dev->suspended && (dev->pmcw.flag5 & PMCW5_V)) { dev->resumesuspended=1; switch (sysblk.arch_mode) { #if defined(_370) case ARCH_370: rc = create_thread (&dev->tid, DETACHED, s370_execute_ccw_chain, dev, "device thread"); break; #endif #if defined(_390) case ARCH_390: rc = create_thread (&dev->tid, DETACHED, s390_execute_ccw_chain, dev, "device thread"); break; #endif #if defined(_900) case ARCH_900: rc = create_thread (&dev->tid, DETACHED, z900_execute_ccw_chain, dev, "device thread"); break; #endif } /* switch (sysblk.arch_mode) */ if (rc != 0) { logmsg( _("HHCSR133E %4.4X Unable to resume suspended device: %s\n"), dev->devnum, strerror(errno)); goto sr_error_exit; } } /* If suspended device */ } /* For each device */ /* Indicate crw pending for any new devices */ #if defined(_370) if (sysblk.arch_mode != ARCH_370) #endif machine_check_crwpend(); /* Start the CPUs */ OBTAIN_INTLOCK(NULL); ON_IC_IOPENDING; for (i = 0; i < MAX_CPU_ENGINES; i++) if (IS_CPU_ONLINE(i) && (started_mask & CPU_BIT(i))) { sysblk.regs[i]->opinterv = 0; sysblk.regs[i]->cpustate = CPUSTATE_STARTED; sysblk.regs[i]->checkstop = 0; WAKEUP_CPU(sysblk.regs[i]); } RELEASE_INTLOCK(NULL); return 0; sr_read_error: logmsg(_("HHCSR011E read error: %s\n"), strerror(errno)); goto sr_error_exit; /* sr_seek_error: logmsg(_("HHCSR012E seek error: %s\n"), strerror(errno)); goto sr_error_exit; */ sr_string_error: logmsg(_("HHCSR014E string error, incorrect length\n")); goto sr_error_exit; sr_value_error: logmsg(_("HHCSR001E value error, incorrect length\n"), fn); goto sr_error_exit; sr_null_regs_exit: logmsg(_("HHCSR016E CPU key %8.8x found but no active CPU\n"), key); goto sr_error_exit; sr_error_exit: logmsg(_("HHCSR015E Error processing file %s\n"), fn); SR_CLOSE (file); return -1; } hercules-3.07/sr.h000644 000765 000765 00000054313 11143760543 015552 0ustar00jmaynardjmaynard000000 000000 /* SR.H (c)Copyright Greg Smith, 2004-2009 */ /* Suspend/Resume a Hercules session */ // $Id: sr.h 5126 2009-01-23 13:05:56Z bernard $ /* * The suspend/resume functions allow a hercules instance to be * captured to a file and later resumed. Note that the suspend * function also terminates the hercules instance. * * In order for an instance to be resumed, hercules must be started * with a config file describing the configuration at suspend time. * For example, mainsize and xpndsize must match. Also, all devices * present at suspend time must be present at resume time. * * Disk devices must be at the same state as they were at suspend * time. They can, however, be a different file type. That is, * a disk could be a cckd disk at suspend time. Then a ckd disk * could be created using dasdcopy and hercules resumed using the * ckd disk instead. * * Also, hercules must be configured similarly as at suspend time. * For example, if 4 emulated CPUs were active at suspend time * then the session can not be resumed on a hercules with a * maximum of two CPUs. Another example, you will not be able * to resume a session in z900 architecture mode for a hercules * that was built without z900 architecture. * * Device state * * Currently, device state is only fully saved for CKD disks. * Each device class (eg TAPE, RDR, PUN, CTC) will need code * to save and restore their state. Some states may not be * possible to restore (eg active tcp/ip connections at the * time of suspend). * * Further limitations * * Currently the vector facility state is not saved. * Also, the ecpsvm state is not currently saved. * * File Structure * * The suspend/resume file (.srf) contains some number of `text * units'. A text unit has an 8 byte header followed by zero or * more bytes of data. * * The file is designed to be hercules release independent and * to be host architecture independent. For example, I should be * able to take an srf file created on hercules 3.02 on an intel * machine and resume on a Sun machine running hercules 3.04. * * The header contains a 4 byte key and a 4 byte length. Both * the key and the length are stored in big-endian byte order. * * There are 3 types of data: STRING, BUF and VALUE. * * A string is a null terminated sequence of bytes. The string * includes the null terminator byte. The total length of a * string cannot exceed SR_MAX_STRING_LENGTH (4096). The * length is checked by SR_READ_STRING. * * A buf is a sequence of bytes whose length must be provided. * The length should be checked before issuing SR_READ_BUF. * * A value is an arithmetic number. It's length can be * 0, 1, 2, 4 or 8 bytes. Values are stored in big-endian * byte order. A zero length indicates the value is 0. * * Text Units * * There are 4 categories (so far) of text units: * HDR ... fields that describe the file * SYS ... fields from SYSBLK * CPU ... fields from REGS * DEV ... fields from DEVBLK * * The format of a text unit key value is * ace c t xxx * * ace -- all keys start with 0xace * c -- category (0 - HDR, 1 - SYS, 2 - CPU, 3 - DEV) * t -- for DEV keys, identifies the subtype for the * device type (0 - general, 1 - CKD, ...) * xxx -- field identifier * * Note that there is no array data type. When an array * needs to be used, the elements should have ascending * text unit key values. For example: * * #define SR_CPU_GR 0xace20020 * #define SR_CPU_GR_0 0xace20020 * #define SR_CPU_GR_1 0xace20021 * #define SR_CPU_GR_2 0xace20022 * #define SR_CPU_GR_3 0xace20023 * . . . . . . * * The array can be written during suspend as follows: * * for (i = 0; i < 16; i++) * SR_WRITE_VALUE(fd, SR_CPU_GR+i, regs->gr[i], sizeof(regs->gr[0])); * * The array can be processed during resume as follows * * case SR_CPU_GR_0: * case SR_CPU_GR_1: * case SR_CPU_GR_2: * case SR_CPU_GR_3: * . . . . . . * i = key - SR_CPU_GR; * SR_READ_VALUE(fd, len, ®s->gr[i], sizeof(regs->gr[0])); * break; * * The format of the .srf file is deliberately unstructured to * allow for flexibility in future enhancements. However there * are a few restrictions. * * o Key SR_SYS_ARCHNAME shoud be specified before any * SR_CPU keys. The corresponding CPU is configured * when the SR_CPU key is read, so sysblk.arch_mode must * already be correctly set. * o SR_CPU_ keys must follow the corresponding SR_CPU key. * o Likewise SR_DEV_ keys must follow the corresponding SR_DEV key * * There may be other instances where the processing of one * key requires that another key has been previously processed. * */ // $Log$ // Revision 1.15 2007/06/23 00:04:16 ivan // Update copyright notices to include current year (2007) // // Revision 1.14 2006/12/08 09:43:30 jj // Add CVS message log // #ifndef _HERCULES_SR_H #define _HERCULES_SR_H #include "opcode.h" #define SR_ID "Hercules suspend/resume file" #define SR_MAX_STRING_LENGTH 4096 #define SR_KEY_ID_MASK 0xfff00000 #define SR_KEY_ID 0xace00000 #define SR_HDR_ID 0xace00000 #define SR_HDR_VERSION 0xace00001 #define SR_HDR_DATE 0xace00002 #define SR_SYS_MASK 0xfffff000 #define SR_SYS_STARTED_MASK 0xace10000 #define SR_SYS_INTS_STATE 0xace10001 #define SR_SYS_ARCH_NAME 0xace10002 #define SR_SYS_MAINSIZE 0xace10007 #define SR_SYS_MAINSTOR 0xace10008 #define SR_SYS_SKEYSIZE 0xace10009 #define SR_SYS_STORKEYS 0xace1000a #define SR_SYS_XPNDSIZE 0xace1000b #define SR_SYS_XPNDSTOR 0xace1000c #define SR_SYS_CPUID 0xace1000d #define SR_SYS_IPLDEV 0xace1000e #define SR_SYS_IPLCPU 0xace1000f #define SR_SYS_MBO 0xace10010 #define SR_SYS_MBK 0xace10011 #define SR_SYS_MBM 0xace10012 #define SR_SYS_MBD 0xace10013 #define SR_SYS_IOINTQ 0xace10020 #define SR_SYS_IOPENDING 0xace10021 #define SR_SYS_PCIPENDING 0xace10022 #define SR_SYS_ATTNPENDING 0xace10023 #define SR_SYS_CHP_RESET 0xace10030 #define SR_SYS_CHP_RESET_0 0xace10030 #define SR_SYS_CHP_RESET_1 0xace10031 #define SR_SYS_CHP_RESET_2 0xace10032 #define SR_SYS_CHP_RESET_3 0xace10033 #define SR_SYS_CHP_RESET_4 0xace10034 #define SR_SYS_CHP_RESET_5 0xace10035 #define SR_SYS_CHP_RESET_6 0xace10036 #define SR_SYS_CHP_RESET_7 0xace10037 #define SR_SYS_SERVPARM 0xace10040 #define SR_SYS_SIGINTREQ 0xace10041 #define SR_SYS_VMACTIVE 0xace10042 #define SR_SYS_MSCHDELAY 0xace10043 #define SR_SYS_LOADPARM 0xace10044 /* * Following 3 tags added for Multiple * Logical Channel Subsystem support */ #define SR_SYS_IOPENDING_LCSS 0xace10045 #define SR_SYS_PCIPENDING_LCSS 0xace10046 #define SR_SYS_ATTNPENDING_LCSS 0xace10047 #define SR_SYS_SERVC 0xace11000 #define SR_SYS_CLOCK 0xace12000 #define SR_CPU 0xace20000 #define SR_CPU_ARCHMODE 0xace20001 #define SR_CPU_PX 0xace20002 #define SR_CPU_PSW 0xace20003 #define SR_CPU_GR 0xace20020 #define SR_CPU_GR_0 0xace20020 #define SR_CPU_GR_1 0xace20021 #define SR_CPU_GR_2 0xace20022 #define SR_CPU_GR_3 0xace20023 #define SR_CPU_GR_4 0xace20024 #define SR_CPU_GR_5 0xace20025 #define SR_CPU_GR_6 0xace20026 #define SR_CPU_GR_7 0xace20027 #define SR_CPU_GR_8 0xace20028 #define SR_CPU_GR_9 0xace20029 #define SR_CPU_GR_10 0xace2002a #define SR_CPU_GR_11 0xace2002b #define SR_CPU_GR_12 0xace2002c #define SR_CPU_GR_13 0xace2002d #define SR_CPU_GR_14 0xace2002e #define SR_CPU_GR_15 0xace2002f #define SR_CPU_CR 0xace20040 #define SR_CPU_CR_0 0xace20040 #define SR_CPU_CR_1 0xace20041 #define SR_CPU_CR_2 0xace20042 #define SR_CPU_CR_3 0xace20043 #define SR_CPU_CR_4 0xace20044 #define SR_CPU_CR_5 0xace20045 #define SR_CPU_CR_6 0xace20046 #define SR_CPU_CR_7 0xace20047 #define SR_CPU_CR_8 0xace20048 #define SR_CPU_CR_9 0xace20049 #define SR_CPU_CR_10 0xace2004a #define SR_CPU_CR_11 0xace2004b #define SR_CPU_CR_12 0xace2004c #define SR_CPU_CR_13 0xace2004d #define SR_CPU_CR_14 0xace2004e #define SR_CPU_CR_15 0xace2004f #define SR_CPU_AR 0xace20060 #define SR_CPU_AR_0 0xace20060 #define SR_CPU_AR_1 0xace20061 #define SR_CPU_AR_2 0xace20062 #define SR_CPU_AR_3 0xace20063 #define SR_CPU_AR_4 0xace20064 #define SR_CPU_AR_5 0xace20065 #define SR_CPU_AR_6 0xace20066 #define SR_CPU_AR_7 0xace20067 #define SR_CPU_AR_8 0xace20068 #define SR_CPU_AR_9 0xace20069 #define SR_CPU_AR_10 0xace2006a #define SR_CPU_AR_11 0xace2006b #define SR_CPU_AR_12 0xace2006c #define SR_CPU_AR_13 0xace2006d #define SR_CPU_AR_14 0xace2006e #define SR_CPU_AR_15 0xace2006f #define SR_CPU_FPR 0xace20080 #define SR_CPU_FPR_0 0xace20080 #define SR_CPU_FPR_1 0xace20081 #define SR_CPU_FPR_2 0xace20082 #define SR_CPU_FPR_3 0xace20083 #define SR_CPU_FPR_4 0xace20084 #define SR_CPU_FPR_5 0xace20085 #define SR_CPU_FPR_6 0xace20086 #define SR_CPU_FPR_7 0xace20087 #define SR_CPU_FPR_8 0xace20088 #define SR_CPU_FPR_9 0xace20089 #define SR_CPU_FPR_10 0xace2008a #define SR_CPU_FPR_11 0xace2008b #define SR_CPU_FPR_12 0xace2008c #define SR_CPU_FPR_13 0xace2008d #define SR_CPU_FPR_14 0xace2008e #define SR_CPU_FPR_15 0xace2008f #define SR_CPU_FPR_16 0xace20090 #define SR_CPU_FPR_17 0xace20091 #define SR_CPU_FPR_18 0xace20092 #define SR_CPU_FPR_19 0xace20093 #define SR_CPU_FPR_20 0xace20094 #define SR_CPU_FPR_21 0xace20095 #define SR_CPU_FPR_22 0xace20096 #define SR_CPU_FPR_23 0xace20097 #define SR_CPU_FPR_24 0xace20098 #define SR_CPU_FPR_25 0xace20099 #define SR_CPU_FPR_26 0xace2009a #define SR_CPU_FPR_27 0xace2009b #define SR_CPU_FPR_28 0xace2009c #define SR_CPU_FPR_29 0xace2009d #define SR_CPU_FPR_30 0xace2009e #define SR_CPU_FPR_31 0xace2009f #define SR_CPU_FPC 0xace20100 #define SR_CPU_DXC 0xace20101 #define SR_CPU_MC 0xace20102 #define SR_CPU_EA 0xace20103 #define SR_CPU_PTIMER 0xace20104 #define SR_CPU_CLKC 0xace20105 #define SR_CPU_CHANSET 0xace20106 #define SR_CPU_TODPR 0xace20107 #define SR_CPU_MONCLASS 0xace20108 #define SR_CPU_EXCARID 0xace20109 #define SR_CPU_INTS_STATE 0xace2010a #define SR_CPU_INTS_MASK 0xace2010b #define SR_CPU_EXTCCPU 0xace2010c #define SR_CPU_BEAR 0xace2010d #define SR_CPU_OPNDRID 0xace20110 #define SR_CPU_CHECKSTOP 0xace20111 #define SR_CPU_HOSTINT 0xace20112 #define SR_CPU_EXECFLAG 0xace20113 #define SR_CPU_INSTVALID 0xace20114 #define SR_CPU_PERMODE 0xace20115 #define SR_CPU_LOADSTATE 0xace20116 #define SR_CPU_INVALIDATE 0xace20117 #define SR_CPU_RESET_OPCTAB 0xace20118 #define SR_CPU_SIGPRESET 0xace20119 #define SR_CPU_SIGPIRESET 0xace2011a #define SR_CPU_VTIMERINT 0xace2011b #define SR_CPU_RTIMERINT 0xace2011c #define SR_CPU_MALFCPU 0xace20120 #define SR_CPU_MALFCPU_0 0xace20120 #define SR_CPU_MALFCPU_1 0xace20121 #define SR_CPU_MALFCPU_2 0xace20122 #define SR_CPU_MALFCPU_3 0xace20123 #define SR_CPU_MALFCPU_4 0xace20124 #define SR_CPU_MALFCPU_5 0xace20125 #define SR_CPU_MALFCPU_6 0xace20126 #define SR_CPU_MALFCPU_7 0xace20127 #define SR_CPU_MALFCPU_8 0xace20128 #define SR_CPU_MALFCPU_9 0xace20129 #define SR_CPU_MALFCPU_10 0xace2012a #define SR_CPU_MALFCPU_11 0xace2012b #define SR_CPU_MALFCPU_12 0xace2012c #define SR_CPU_MALFCPU_13 0xace2012d #define SR_CPU_MALFCPU_14 0xace2012e #define SR_CPU_MALFCPU_15 0xace2012f #define SR_CPU_MALFCPU_16 0xace20130 #define SR_CPU_MALFCPU_17 0xace20131 #define SR_CPU_MALFCPU_18 0xace20132 #define SR_CPU_MALFCPU_19 0xace20133 #define SR_CPU_MALFCPU_20 0xace20134 #define SR_CPU_MALFCPU_21 0xace20135 #define SR_CPU_MALFCPU_22 0xace20136 #define SR_CPU_MALFCPU_23 0xace20137 #define SR_CPU_MALFCPU_24 0xace20138 #define SR_CPU_MALFCPU_25 0xace20139 #define SR_CPU_MALFCPU_26 0xace2013a #define SR_CPU_MALFCPU_27 0xace2013b #define SR_CPU_MALFCPU_28 0xace2013c #define SR_CPU_MALFCPU_29 0xace2013d #define SR_CPU_MALFCPU_30 0xace2013e #define SR_CPU_MALFCPU_31 0xace2013f #define SR_CPU_EMERCPU 0xace20140 #define SR_CPU_EMERCPU_0 0xace20140 #define SR_CPU_EMERCPU_1 0xace20141 #define SR_CPU_EMERCPU_2 0xace20142 #define SR_CPU_EMERCPU_3 0xace20143 #define SR_CPU_EMERCPU_4 0xace20144 #define SR_CPU_EMERCPU_5 0xace20145 #define SR_CPU_EMERCPU_6 0xace20146 #define SR_CPU_EMERCPU_7 0xace20147 #define SR_CPU_EMERCPU_8 0xace20148 #define SR_CPU_EMERCPU_9 0xace20149 #define SR_CPU_EMERCPU_10 0xace2014a #define SR_CPU_EMERCPU_11 0xace2014b #define SR_CPU_EMERCPU_12 0xace2014c #define SR_CPU_EMERCPU_13 0xace2014d #define SR_CPU_EMERCPU_14 0xace2014e #define SR_CPU_EMERCPU_15 0xace2014f #define SR_CPU_EMERCPU_16 0xace20150 #define SR_CPU_EMERCPU_17 0xace20151 #define SR_CPU_EMERCPU_18 0xace20152 #define SR_CPU_EMERCPU_19 0xace20153 #define SR_CPU_EMERCPU_20 0xace20154 #define SR_CPU_EMERCPU_21 0xace20155 #define SR_CPU_EMERCPU_22 0xace20156 #define SR_CPU_EMERCPU_23 0xace20157 #define SR_CPU_EMERCPU_24 0xace20158 #define SR_CPU_EMERCPU_25 0xace20159 #define SR_CPU_EMERCPU_26 0xace2015a #define SR_CPU_EMERCPU_27 0xace2015b #define SR_CPU_EMERCPU_28 0xace2015c #define SR_CPU_EMERCPU_29 0xace2015d #define SR_CPU_EMERCPU_30 0xace2015e #define SR_CPU_EMERCPU_31 0xace2015f #define SR_DEV 0xace30000 #define SR_DEV_DEVTYPE 0xace30001 #define SR_DEV_ARGC 0xace30002 #define SR_DEV_ARGV 0xace30003 #define SR_DEV_TYPNAME 0xace30004 /* * Following tag added for multiple Logical * Channel subsystem support */ #define SR_DEV_LCSS 0xace30005 #define SR_DEV_ORB 0xace30010 #define SR_DEV_PMCW 0xace30011 #define SR_DEV_SCSW 0xace30012 #define SR_DEV_PCISCSW 0xace30013 #define SR_DEV_ATTNSCSW 0xace30014 #define SR_DEV_CSW 0xace30015 #define SR_DEV_PCICSW 0xace30016 #define SR_DEV_ATTNCSW 0xace30017 #define SR_DEV_ESW 0xace30018 #define SR_DEV_ECW 0xace30019 #define SR_DEV_SENSE 0xace3001a #define SR_DEV_PGSTAT 0xace3001b #define SR_DEV_PGID 0xace3001c /* By Adrian - SR_DEV_DRVPWD */ #define SR_DEV_DRVPWD 0xace3001d #define SR_DEV_BUSY 0xace30020 #define SR_DEV_RESERVED 0xace30021 #define SR_DEV_SUSPENDED 0xace30022 #define SR_DEV_PENDING 0xace30023 #define SR_DEV_PCIPENDING 0xace30024 #define SR_DEV_ATTNPENDING 0xace30025 #define SR_DEV_STARTPENDING 0xace30026 #define SR_DEV_CRWPENDING 0xace30027 #define SR_DEV_CCWADDR 0xace30028 #define SR_DEV_IDAPMASK 0xace30029 #define SR_DEV_IDAWFMT 0xace3002a #define SR_DEV_CCWFMT 0xace3002b #define SR_DEV_CCWKEY 0xace3002c #define SR_DEV_MASK 0xfffff000 #define SR_DEV_CKD 0xace31000 #define SR_DEV_FBA 0xace32000 #define SR_DEV_TTY 0xace33000 #define SR_DEV_3270 0xace34000 #define SR_DEV_RDR 0xace35000 #define SR_DEV_PUN 0xace36000 #define SR_DEV_PRT 0xace37000 #define SR_DEV_TAPE 0xace38000 #define SR_DEV_COMM 0xace39000 #define SR_DEV_CTC 0xace3a000 #define SR_DEV_CTCI 0xace3b000 #define SR_DEV_CTCT 0xace3c000 #define SR_DEV_VMNET 0xace3d000 #define SR_DEV_LCS 0xace3e000 #define SR_DELIMITER 0xaceffffe #define SR_EOF 0xacefffff #if defined (_HERCULES_SR_C) #define SR_WRITE_ERROR goto sr_write_error #define SR_READ_ERROR goto sr_read_error #define SR_SEEK_ERROR goto sr_seek_error #define SR_VALUE_ERROR goto sr_value_error #define SR_STRING_ERROR goto sr_string_error #else #define SR_WRITE_ERROR \ do { \ logmsg(_("HHCSR010E write error: %s\n"), strerror(errno)); \ return -1; \ } while (0) #define SR_READ_ERROR \ do { \ logmsg(_("HHCSR011E read error: %s\n"), strerror(errno)); \ return -1; \ } while (0) #define SR_SEEK_ERROR \ do { \ logmsg(_("HHCSR012E seek error: %s\n"), strerror(errno)); \ return -1; \ } while (0) #define SR_VALUE_ERROR \ do { \ logmsg(_("HHCSR013E value error, incorrect length\n")); \ return -1; \ } while (0) #define SR_STRING_ERROR \ do { \ logmsg(_("HHCSR014E string error, incorrect length\n")); \ return -1; \ } while (0) #endif #ifdef HAVE_LIBZ #define SR_DEFAULT_FILENAME "hercules.srf.gz" #define SR_FILE gzFile #define SR_OPEN(_path, _mode) \ gzopen((_path), (_mode)) #define SR_READ(_ptr, _size, _nmemb, _stream) \ gzread((_stream), (_ptr), (unsigned int)((_size) * (_nmemb))) #define SR_WRITE(_ptr, _size, _nmemb, _stream) \ gzwrite((_stream), (_ptr), (unsigned int)((_size) * (_nmemb))) #define SR_SEEK(_stream, _offset, _whence) \ gzseek((_stream), (_offset), (_whence)) #define SR_CLOSE(_stream) \ gzclose((_stream)) #else #define SR_DEFAULT_FILENAME "hercules.srf" #define SR_FILE FILE #define SR_OPEN(_path, _mode) \ fopen((_path), (_mode)) #define SR_READ(_ptr, _size, _nmemb, _stream) \ fread((_ptr), (_size), (_nmemb), (_stream)) #define SR_WRITE(_ptr, _size, _nmemb, _stream) \ fwrite((_ptr), (_size), (_nmemb), (_stream)) #define SR_SEEK(_stream, _offset, _whence) \ fseek((_stream), (_offset), (_whence)) #define SR_CLOSE(_stream) \ fclose((_stream)) #endif #define SR_WRITE_HDR(_file, _key, _len) \ do { \ size_t _rc; \ BYTE _buf[8]; \ store_fw (_buf, (_key)); \ store_fw (_buf+4, (_len)); \ _rc = SR_WRITE(_buf, 1, 8, (_file)); \ if (_rc != 8) SR_WRITE_ERROR; \ } while (0) #define SR_WRITE_STRING(_file, _key, _s) \ do { \ size_t _rc; \ if (strlen((_s)) + 1 > SR_MAX_STRING_LENGTH) SR_STRING_ERROR; \ SR_WRITE_HDR((_file), (_key), strlen((_s)) + 1); \ _rc = SR_WRITE((_s), 1, strlen((_s)) + 1, (_file)); \ if (_rc != strlen((_s)) + 1) SR_WRITE_ERROR; \ } while (0); #define SR_WRITE_BUF(_file, _key, _buf, _len) \ do { \ size_t _rc; \ if ((_len)) { \ SR_WRITE_HDR((_file), (_key), (_len)); \ _rc = SR_WRITE((_buf), 1, (_len), (_file)); \ if (_rc != (_len)) SR_WRITE_ERROR; \ } else \ SR_WRITE_HDR((_file), (_key), 0); \ } while (0) #define SR_WRITE_VALUE(_file, _key, _val, _len) \ do { \ size_t _rc; \ BYTE _buf[8]; \ if ((_len) != 1 && (_len) != 2 && (_len) != 4 && (_len) != 8) \ SR_VALUE_ERROR; \ SR_WRITE_HDR((_file), (_key), (_len)); \ switch ((_len)) { \ case 1: _buf[0] = (_val); break; \ case 2: store_hw(_buf, (_val)); break; \ case 4: store_fw(_buf, (_val)); break; \ case 8: store_dw(_buf, (_val)); break; \ } \ _rc = SR_WRITE(_buf, 1, (_len), (_file)); \ if (_rc != (_len)) SR_WRITE_ERROR; \ } while (0) #define SR_READ_HDR(_file, _key, _len) \ do { \ size_t _rc; \ BYTE _buf[8]; \ _rc = SR_READ(_buf, 1, 8, (_file)); \ if (_rc != 8) SR_READ_ERROR; \ (_key) = fetch_fw(_buf); \ (_len) = fetch_fw(_buf+4); \ } while (0) //FIXME: Workaround for problem involving gzseek // and large files. Just read the data. #define SR_READ_SKIP(_file, _len) \ do { \ size_t _rc; \ size_t _l; \ BYTE _buf[256]; \ _l = (_len); \ while (_l) { \ _rc = SR_READ(_buf, 1, _l < 256 ? _l : 256, (_file)); \ if (_rc == (size_t)-1) SR_READ_ERROR; \ _l -= _l < 256 ? _l : 256; \ } \ } while (0) #define SR_READ_STRING(_file, _p, _len) \ do { \ size_t _rc; \ if ((_len) > SR_MAX_STRING_LENGTH) SR_STRING_ERROR; \ _rc = SR_READ((_p), 1, (_len), (_file)); \ if (_rc != (_len)) SR_READ_ERROR; \ } while (0) #define SR_READ_BUF(_file, _p, _len) \ do { \ size_t _rc; \ _rc = SR_READ((_p), 1, (_len), (_file)); \ if (_rc != (_len)) SR_READ_ERROR; \ } while (0) #define SR_READ_VALUE(_file, _len1, _p, _len2) \ do { \ size_t _rc; \ BYTE _buf[8]; \ U64 _value; \ if ((_len1) != 1 && (_len1) != 2 && (_len1) != 4 && (_len1) != 8) \ SR_VALUE_ERROR; \ _rc = SR_READ(_buf, 1, (_len1), (_file)); \ if (_rc != (_len1)) SR_READ_ERROR; \ switch ((_len1)) { \ case 1: _value = _buf[0]; break; \ case 2: _value = fetch_hw(_buf); break; \ case 4: _value = fetch_fw(_buf); break; \ case 8: _value = fetch_dw(_buf); break; \ default: _value=0; break; /* To ward off gcc -Wall */ \ } \ switch ((_len2)) { \ case 1: \ { \ BYTE *_ptr = (void *)(_p); \ *_ptr = _value & 0xff; \ break; \ } \ case 2: \ { \ U16 *_ptr = (void *)(_p); \ *_ptr = _value & 0xffff; \ break; \ } \ case 4: \ { \ U32 *_ptr = (void *)(_p); \ *_ptr = _value & 0xffffffff; \ break; \ } \ case 8: \ { \ U64 *_ptr = (void *)(_p); \ *_ptr = _value; \ break; \ } \ } \ } while (0) #define SR_SKIP_NULL_DEV(_dev, _file, _len) \ if ((_dev) == NULL) { \ SR_READ_SKIP((_file),(_len)); \ break; \ } #endif /* !defined(_HERCULES_SR_H) */ hercules-3.07/stack.c000644 000765 000765 00000162300 11143760543 016222 0ustar00jmaynardjmaynard000000 000000 /* STACK.C (c) Copyright Roger Bowler, 1999-2009 */ /* ESA/390 Linkage Stack Operations */ /* Interpretive Execution - (c) Copyright Jan Jaeger, 1999-2009 */ /* z/Architecture support - (c) Copyright Jan Jaeger, 1999-2009 */ // $Id: stack.c 5126 2009-01-23 13:05:56Z bernard $ /*-------------------------------------------------------------------*/ /* This module implements the linkage stack functions of ESA/390 */ /* described in SA22-7201-04 ESA/390 Principles of Operation. */ /* The numbers in square brackets refer to sections in the manual. */ /*-------------------------------------------------------------------*/ /*-------------------------------------------------------------------*/ /* Fix CR15 corruption in form_stack_entry Jan Jaeger */ /* Fix nullification in form_stack_entry Jan Jaeger */ /* Fix nullification in unstack_registers Jan Jaeger */ /* Modifications for Interpretive Execution (SIE) Jan Jaeger */ /* ESAME low-address protection v208d Roger Bowler */ /* ESAME linkage stack operations v208e Roger Bowler */ /* TRAP support added Jan Jaeger */ /* Correction to stack types in ESAME mode Jan Jaeger */ /* ASN-and-LX-reuse facility June 2004 Roger Bowler */ /*-------------------------------------------------------------------*/ // $Log$ // Revision 1.89 2008/04/11 14:29:28 bernard // Integrate regs->exrl into base Hercules code. // // Revision 1.88 2008/04/09 07:38:58 bernard // Allign to Rogers terminal ;-) // // Revision 1.87 2008/04/08 17:15:10 bernard // Added execute relative long instruction // // Revision 1.86 2008/03/01 00:00:34 ptl00 // Fix TRAP in z/Arch mode // // Revision 1.85 2008/02/12 18:23:39 jj // 1. SPKA was missing protection check (PIC04) because // AIA regs were not purged. // // 2. BASR with branch trace and PIC16, the pgm old was pointing // 2 bytes before the BASR. // // 3. TBEDR , TBDR using R1 as source, should be R2. // // 4. PR with page crossing stack (1st page invalid) and PSW real // in stack, missed the PIC 11. Fixed by invoking abs_stck_addr // for previous stack entry descriptor before doing the load_psw. // // Revision 1.84 2007/06/23 00:04:16 ivan // Update copyright notices to include current year (2007) // // Revision 1.83 2006/12/20 04:26:20 gsmith // 19 Dec 2006 ip_all.pat - performance patch - Greg Smith // // Revision 1.82 2006/12/08 09:43:30 jj // Add CVS message log // #include "hstdinc.h" // #define STACK_DEBUG #if !defined(_HENGINE_DLL_) #define _HENGINE_DLL_ #endif #if !defined(_STACK_C_) #define _STACK_C_ #endif #include "hercules.h" #include "opcode.h" #include "inline.h" /*-------------------------------------------------------------------*/ /* Linkage stack macro definitions */ /*-------------------------------------------------------------------*/ #undef CR15_LSEA #undef LSEA_WRAP #undef LSSE_SIZE #undef LSSE_REGSIZE #undef FETCH_BSEA #undef STORE_BSEA #undef LSHE_BSEA #undef LSHE_RESV #undef LSHE_BVALID #undef FETCH_FSHA #undef LSTE_FSHA #undef LSTE_RESV #undef LSTE_FVALID #if defined(FEATURE_ESAME) #define CR15_LSEA CR15_LSEA_900 /* Bit mask for ESAME linkage stack entry addr in CR15 */ #define LSEA_WRAP(_lsea) /* No address wrap for ESAME */ #define LSSE_SIZE 296 /* Size of an ESAME linkage stack state entry */ #define LSSE_REGSIZE 8 /* Size of a general register in ESAME state entry */ /* ESAME linkage stack header entry */ /* LSHE words 1 and 2 contain the backward stack entry address */ #define FETCH_BSEA(_bsea,_lshe) FETCH_DW(_bsea,_lshe) #define STORE_BSEA(_lshe,_bsea) STORE_DW(_lshe,_bsea) #define LSHE_BSEA 0xFFFFFFFFFFFFFFF8ULL /* Backward address */ #define LSHE_RESV 0x06 /* Reserved bits - must be 0 */ #define LSHE_BVALID 0x01 /* Backward address is valid */ /* LSHE words 2 and 3 contain a linkage stack entry descriptor */ /* ESAME linkage stack trailer entry */ /* LSTE words 1 and 2 contain the forward section header address */ #define FETCH_FSHA(_fsha,_lste) FETCH_DW(_fsha,_lste) #define LSTE_FSHA 0xFFFFFFFFFFFFFFF8ULL /* Forward address */ #define LSTE_RESV 0x06 /* Reserved bits - must be 0 */ #define LSTE_FVALID 0x01 /* Forward address is valid */ /* LSTE words 2 and 3 contain a linkage stack entry descriptor */ #else /*!defined(FEATURE_ESAME)*/ #define CR15_LSEA CR15_LSEA_390 /* Bit mask for ESA/390 linkage stack entry addr in CR15 */ #define LSEA_WRAP(_lsea) \ _lsea &= 0x7FFFFFFF /* Wrap linkage stack address*/ #define LSSE_SIZE 168 /* Size of an ESA/390 linkage stack state entry */ #define LSSE_REGSIZE 4 /* Size of a general register in ESA/390 state entry */ /* ESA/390 linkage stack header entry */ /* LSHE word 0 is reserved for control program use */ /* LSHE word 1 contains the backward stack entry address */ #define FETCH_BSEA(_bsea,_lshe) FETCH_FW(_bsea,(_lshe)+4) #define STORE_BSEA(_lshe,_bsea) STORE_FW((_lshe)+4,_bsea) #define LSHE_BVALID 0x80000000 /* Backward address is valid */ #define LSHE_BSEA 0x7FFFFFF8 /* Backward stack entry addr */ #define LSHE_RESV 0x00000007 /* Reserved bits - must be 0 */ /* LSHE words 2 and 3 contain a linkage stack entry descriptor */ /* ESA/390 linkage stack trailer entry */ /* LSTE word 0 is reserved for control program use */ /* LSTE word 1 contains the forward section header address */ #define FETCH_FSHA(_fsha,_lste) FETCH_FW(_fsha,(_lste)+4) #define LSTE_FVALID 0x80000000 /* Forward address is valid */ #define LSTE_FSHA 0x7FFFFFF8 /* Forward section hdr addr */ #define LSTE_RESV 0x00000007 /* Reserved bits - must be 0 */ /* LSTE words 2 and 3 contain a linkage stack entry descriptor */ #endif /*!defined(FEATURE_ESAME)*/ #if defined(FEATURE_LINKAGE_STACK) static inline RADR ARCH_DEP(abs_stack_addr) (VADR vaddr, REGS *regs, int acctype) { return MADDR(vaddr, USE_HOME_SPACE, regs, acctype, 0) - regs->mainstor; } static inline RADR ARCH_DEP(abs_trap_addr) (VADR vaddr, REGS *regs, int acctype) { return MADDR(vaddr, USE_HOME_SPACE, regs, acctype, regs->psw.pkey) - regs->mainstor; } /*-------------------------------------------------------------------*/ /* Subroutine called by the TRAP2 and TRAP4 instructions */ /* */ /* Input: */ /* trap4 0=TRAP2 instruction, 1=TRAP4 instruction */ /* regs Pointer to the CPU register context */ /* operand Effective address if TRAP4 */ /*-------------------------------------------------------------------*/ void ARCH_DEP(trap_x) (int trap_is_trap4, REGS *regs, U32 trap_operand) { RADR ducto; U32 duct11; U32 tcba; RADR atcba; #if defined(FEATURE_ESAME) U32 tcba0; #endif /*defined(FEATURE_ESAME)*/ U32 tsao; RADR tsaa1, tsaa2; VADR lastbyte; U32 trap_ia; U32 trap_flags; QWORD trap_psw; int i; if(SIE_STATB(regs, MX, XC)) ARCH_DEP(program_interrupt)(regs, PGM_SPECIAL_OPERATION_EXCEPTION); if ( REAL_MODE(®s->psw) || !(PRIMARY_SPACE_MODE(®s->psw) || ACCESS_REGISTER_MODE(®s->psw)) ) ARCH_DEP(program_interrupt) (regs, PGM_SPECIAL_OPERATION_EXCEPTION); /* Obtain the DUCT origin from control register 2 */ ducto = regs->CR(2) & CR2_DUCTO; /* Program check if DUCT origin address is invalid */ if (ducto > regs->mainlim) ARCH_DEP(program_interrupt) (regs, PGM_ADDRESSING_EXCEPTION); /* Fetch DUCT bytes 44-47 */ duct11 = ARCH_DEP(fetch_fullword_absolute) (ducto + 44, regs); if(!(duct11 & DUCT11_TE)) ARCH_DEP(program_interrupt) (regs, PGM_SPECIAL_OPERATION_EXCEPTION); /* Isolate the Trap Control Block Address */ tcba = duct11 & DUCT11_TCBA; #if defined(FEATURE_ESAME) /* Fetch word 0 of the TCB */ atcba = ARCH_DEP(abs_trap_addr) (tcba, regs, ACCTYPE_READ); FETCH_FW(tcba0, regs->mainstor + atcba); #endif /*defined(FEATURE_ESAME)*/ /* Advance to offset +12 */ tcba += 12; atcba = ARCH_DEP(abs_trap_addr) (tcba, regs, ACCTYPE_READ); /* Fetch word 3 of the TCB */ FETCH_FW(tsao, regs->mainstor + atcba); tsao &= 0x7FFFFFF8; /* Advance to offset +20 */ tcba += 8; atcba += 8; if((atcba & PAGEFRAME_BYTEMASK) < 8) atcba = ARCH_DEP(abs_trap_addr) (tcba, regs, ACCTYPE_READ); /* Fetch word 5 of the TCB */ FETCH_FW(trap_ia, regs->mainstor + atcba); trap_ia &= 0x7FFFFFFF; /* Calculate last byte stored */ lastbyte = tsao + 95 #if defined(FEATURE_ESAME) + ((tcba0 & TCB0_R) ? 64 : 0) #endif /*defined(FEATURE_ESAME)*/ ; /* Use abs_trap_addr as it conforms to trap save area access */ tsaa1 = tsaa2 = ARCH_DEP(abs_trap_addr) (tsao, regs, ACCTYPE_WRITE); if((tsaa1 & PAGEFRAME_PAGEMASK) != (lastbyte & PAGEFRAME_PAGEMASK)) { tsao = lastbyte & PAGEFRAME_PAGEMASK; tsaa2 = ARCH_DEP(abs_trap_addr) (tsao, regs, ACCTYPE_WRITE); } STORAGE_KEY(tsaa1, regs) |= STORKEY_CHANGE; if (tsaa1 != tsaa2) STORAGE_KEY(tsaa2, regs) |= STORKEY_CHANGE; #if defined(FEATURE_ESAME) /* Special operation exception if P == 0 and EA == 1 */ if(!(tcba0 & TCB0_P) && regs->psw.amode64) ARCH_DEP(program_interrupt) (regs, PGM_SPECIAL_OPERATION_EXCEPTION); #endif /*defined(FEATURE_ESAME)*/ #ifdef FEATURE_TRACING if (regs->CR(12) & CR12_BRTRACE) regs->CR(12) = ARCH_DEP(trace_br) (1, trap_ia, regs); #endif /*FEATURE_TRACING*/ PER_SB(regs, trap_ia); trap_flags = REAL_ILC(regs) << 16; if(regs->execflag) trap_flags |= TRAP0_EXECUTE; if(trap_is_trap4) trap_flags |= TRAP0_TRAP4; /* Trap flags at offset +0 */ STORE_FW(regs->mainstor + tsaa1, trap_flags); /* Reserved zero's stored at offset +4 */ STORE_FW(regs->mainstor + tsaa1 + 4, 0); tsaa1 += 8; if((tsaa1 & PAGEFRAME_BYTEMASK) == 0) tsaa1 = tsaa2; /* Bits 33-63 of Second-Op address of TRAP4 at offset +8 */ STORE_FW(regs->mainstor + tsaa1, trap_operand); /* Access register 15 at offset +12 */ STORE_FW(regs->mainstor + tsaa1 + 4, regs->AR(15)); tsaa1 += 8; if((tsaa1 & PAGEFRAME_BYTEMASK) == 0) tsaa1 = tsaa2; #if defined(FEATURE_ESAME) /* If the P bit is one then store the PSW in esame format */ if(tcba0 & TCB0_P) ARCH_DEP(store_psw) (regs, trap_psw); else #endif /*defined(FEATURE_ESAME)*/ { s390_store_psw(regs, trap_psw); #if defined(FEATURE_ESAME) /* Set the notesame mode bit for a esa/390 psw */ trap_psw[1] |= 0x08; #endif /*defined(FEATURE_ESAME)*/ } /* bits 0-63 of PSW at offset +16 */ memcpy(regs->mainstor + tsaa1, trap_psw, 8); tsaa1 += 8; if((tsaa1 & PAGEFRAME_BYTEMASK) == 0) { tsaa1 = tsaa2; } #if defined(FEATURE_ESAME) /* If the P bit is one then store the PSW in esame format */ /* bits 64-127 of PSW at offset +24 */ if(tcba0 & TCB0_P) { memcpy(regs->mainstor + tsaa1, trap_psw + 8, 8); } else { #endif /*defined(FEATURE_ESAME)*/ memset(regs->mainstor + tsaa1, 0, 8); #if defined(FEATURE_ESAME) } #endif /*defined(FEATURE_ESAME)*/ tsaa1 += 8; if((tsaa1 & PAGEFRAME_BYTEMASK) == 0) tsaa1 = tsaa2; #if defined(FEATURE_ESAME) /* General registers at offset +32 */ if(tcba0 & TCB0_R) for(i = 0; i < 16; i++) { STORE_DW(regs->mainstor + tsaa1, regs->GR_G(i)); tsaa1 += 8; if((tsaa1 & PAGEFRAME_BYTEMASK) == 0) tsaa1 = tsaa2; } else #endif /*defined(FEATURE_ESAME)*/ for(i = 0; i < 16; i++) { STORE_FW(regs->mainstor + tsaa1, regs->GR_L(i)); tsaa1 += 4; if((tsaa1 & PAGEFRAME_BYTEMASK) == 0) tsaa1 = tsaa2; } /* Load the Trap Control Block Address in gr15 */ #if defined(FEATURE_ESAME) if(regs->psw.amode64) regs->GR(15) = duct11 & DUCT11_TCBA & 0x00000000FFFFFFFF; else #endif /*defined(FEATURE_ESAME)*/ regs->GR_L(15) = duct11 & DUCT11_TCBA; /* Ensure psw.IA is set */ SET_PSW_IA(regs); /* Set the Breaking Event Address Register */ SET_BEAR_REG(regs, regs->ip - (trap_is_trap4 ? 4 : regs->execflag ? regs->exrl ? 6 : 4 : 2)); regs->psw.amode = 1; regs->psw.AMASK = AMASK31; UPD_PSW_IA(regs, trap_ia); /* set PSW to primary space */ regs->psw.asc = 0; SET_AEA_MODE(regs); } /*-------------------------------------------------------------------*/ /* Form a new entry on the linkage stack */ /* */ /* Input: */ /* etype Linkage stack entry type (LSED_UET_PC/BAKR) */ /* retna Return amode and instruction address to be stored */ /* in the saved PSW in the new stack entry */ /* calla Called amode and instruction address (for BAKR) */ /* csi 32-bit called-space identification (for PC) */ /* pcnum Called PC number (for PC) */ /* regs Pointer to the CPU register context */ /* */ /* This function performs the stacking process for the */ /* Branch and Stack (BAKR) and Program Call (PC) instructions. */ /* */ /* For ESAME, bit 63 of retna/calla indicate a 64-bit address, */ /* otherwise bit 32 indicates a 31-bit address. */ /* For ESA/390, bit 0 of retna/calla indicate a 31-bit address. */ /* */ /* For ESAME, bit 0 of pcnum indicates resulting 64-bit mode. */ /* */ /* In the event of any stack error, this function generates */ /* a program check and does not return. */ /*-------------------------------------------------------------------*/ void ARCH_DEP(form_stack_entry) (BYTE etype, VADR retna, VADR calla, U32 csi, U32 pcnum, REGS *regs) { QWORD currpsw; /* Current PSW */ VADR lsea; /* Linkage stack entry addr */ VADR lseaold; /* Linkage stack old addr */ RADR abs, abs2 = 0; /* Absolute addr new entry */ RADR absold; /* Absolute addr old entry */ LSED lsed; /* Linkage stack entry desc. */ LSED lsed2; /* New entry descriptor */ U16 rfs; /* Remaining free space */ VADR fsha; /* Forward section hdr addr */ VADR bsea = 0; /* Backward stack entry addr */ RADR absea = 0; /* Absolute address of bsea */ int i; /* Array subscript */ /* [5.12.3.1] Locate space for a new linkage stack entry */ /* Obtain the virtual address of the current entry from CR15 */ lsea = regs->CR(15) & CR15_LSEA; /* Fetch the entry descriptor of the current entry */ absold = ARCH_DEP(abs_stack_addr) (lsea, regs, ACCTYPE_READ); memcpy (&lsed, regs->mainstor+absold, sizeof(LSED)); lseaold = lsea; #ifdef STACK_DEBUG logmsg (_("stack: Current stack entry at " F_VADR "\n"), lsea); logmsg (_("stack: et=%2.2X si=%2.2X rfs=%2.2X%2.2X nes=%2.2X%2.2X\n"), lsed.uet, lsed.si, lsed.rfs[0], lsed.rfs[1], lsed.nes[0], lsed.nes[1]); #endif /*STACK_DEBUG*/ /* Check whether the current linkage stack section has enough remaining free space to contain the new stack entry */ FETCH_HW(rfs,lsed.rfs); if (rfs < LSSE_SIZE) { /* Program check if remaining free space not a multiple of 8 */ if ((rfs & 0x07) != 0) ARCH_DEP(program_interrupt) (regs, PGM_STACK_SPECIFICATION_EXCEPTION); /* Not enough space, so fetch the forward section header addr from the trailer entry of current linkage stack section */ lsea += sizeof(LSED) + rfs; LSEA_WRAP(lsea); abs = ARCH_DEP(abs_stack_addr) (lsea, regs, ACCTYPE_READ); FETCH_FSHA(fsha, regs->mainstor + abs); #ifdef STACK_DEBUG logmsg (_("stack: Forward section header addr " F_VADR "\n"), fsha); #endif /*STACK_DEBUG*/ /* Stack full exception if forward address is not valid */ if ((fsha & LSTE_FVALID) == 0) ARCH_DEP(program_interrupt) (regs, PGM_STACK_FULL_EXCEPTION); /* Extract the forward section header address, which points to the entry descriptor (words 2-3) of next section's header */ fsha &= LSTE_FSHA; /* Fetch the entry descriptor of the next section's header */ absold = ARCH_DEP(abs_stack_addr) (fsha, regs, ACCTYPE_READ); memcpy (&lsed, regs->mainstor+absold, sizeof(LSED)); lseaold = fsha; #ifdef STACK_DEBUG logmsg (_("stack: et=%2.2X si=%2.2X rfs=%2.2X%2.2X " "nes=%2.2X%2.2X\n"), lsed.uet, lsed.si, lsed.rfs[0], lsed.rfs[1], lsed.nes[0], lsed.nes[1]); #endif /*STACK_DEBUG*/ /* Program check if the next linkage stack section does not have enough free space to contain the new stack entry */ FETCH_HW(rfs,lsed.rfs); if (rfs < LSSE_SIZE) ARCH_DEP(program_interrupt) (regs, PGM_STACK_SPECIFICATION_EXCEPTION); /* Calculate the virtual address of the new section's header entry, which is 8 bytes before the entry descriptor */ lsea = fsha - 8; LSEA_WRAP(lsea); /* Form the backward stack entry address */ bsea = LSHE_BVALID | (regs->CR(15) & CR15_LSEA); absea = ARCH_DEP(abs_stack_addr) (lsea, regs, ACCTYPE_WRITE); /* Use the virtual address of the entry descriptor of the new section's header entry as the current entry address */ lsea = fsha; } /* end if(rfsmainstor + absea, bsea); /* Store general registers 0-15 in bytes 0-63 (ESA/390) or bytes 0-127 (ESAME) of the new state entry */ for (i = 0; i < 16; i++) { #if defined(FEATURE_ESAME) /* Store the 64-bit general register in the stack entry */ STORE_DW(regs->mainstor + abs, regs->GR_G(i)); #ifdef STACK_DEBUG logmsg (_("stack: GPR%d=" F_GREG " stored at V:" F_VADR " A:" F_RADR "\n"), i, regs->GR_G(i), lsea, abs); #endif /*STACK_DEBUG*/ #else /*!defined(FEATURE_ESAME)*/ /* Store the 32-bit general register in the stack entry */ STORE_FW(regs->mainstor + abs, regs->GR_L(i)); #ifdef STACK_DEBUG logmsg (_("stack: GPR%d=" F_GREG " stored at V:" F_VADR " A:" F_RADR "\n"), i, regs->GR_L(i), lsea, abs); #endif /*STACK_DEBUG*/ #endif /*!defined(FEATURE_ESAME)*/ /* Update the virtual and absolute addresses */ lsea += LSSE_REGSIZE; LSEA_WRAP(lsea); abs += LSSE_REGSIZE; /* Recalculate absolute address if page boundary crossed */ if ((lsea & PAGEFRAME_BYTEMASK) == 0x000) abs = abs2; } /* end for(i) */ #if !defined(FEATURE_ESAME) /* For ESA/390, store access registers 0-15 in bytes 64-127 */ for (i = 0; i < 16; i++) { /* Store the access register in the stack entry */ STORE_FW(regs->mainstor + abs, regs->AR(i)); #ifdef STACK_DEBUG logmsg (_("stack: AR%d=" F_AREG " stored at V:" F_VADR " A:" F_RADR "\n"), i, regs->AR(i), lsea, abs); #endif /*STACK_DEBUG*/ /* Update the virtual and absolute addresses */ lsea += 4; LSEA_WRAP(lsea); abs += 4; /* Recalculate absolute address if page boundary crossed */ if ((lsea & PAGEFRAME_BYTEMASK) == 0x000) abs = abs2; } /* end for(i) */ #endif /*!defined(FEATURE_ESAME)*/ /* Store the PKM, SASN, EAX, and PASN in bytes 128-135 */ STORE_FW(regs->mainstor + abs, regs->CR_L(3)); STORE_HW(regs->mainstor + abs + 4, regs->CR_LHH(8)); STORE_HW(regs->mainstor + abs + 6, regs->CR_LHL(4)); #ifdef STACK_DEBUG logmsg (_("stack: PKM=%2.2X%2.2X SASN=%2.2X%2.2X " "EAX=%2.2X%2.2X PASN=%2.2X%2.2X \n" "stored at V:" F_VADR " A:" F_RADR "\n"), regs->mainstor[abs], regs->mainstor[abs+1], regs->mainstor[abs+2], regs->mainstor[abs+3], regs->mainstor[abs+4], regs->mainstor[abs+5], regs->mainstor[abs+6], regs->mainstor[abs+7], lsea, abs); #endif /*STACK_DEBUG*/ /* Update virtual and absolute addresses to point to byte 136 */ lsea += 8; LSEA_WRAP(lsea); abs += 8; /* Recalculate absolute address if page boundary crossed */ if ((lsea & PAGEFRAME_BYTEMASK) == 0x000) abs = abs2; /* Store bits 0-63 of the current PSW in bytes 136-143 */ ARCH_DEP(store_psw) (regs, currpsw); memcpy (regs->mainstor + abs, currpsw, 8); #if defined(FEATURE_ESAME) /* For ESAME, use the addressing mode bits from the return address to set bits 31 and 32 of bytes 136-143 */ if (retna & 0x01) { /* For a 64-bit return address, set bits 31 and 32 */ regs->mainstor[abs+3] |= 0x01; regs->mainstor[abs+4] |= 0x80; retna &= 0xFFFFFFFFFFFFFFFEULL; } else if (retna & 0x80000000) { /* For a 31-bit return address, clear bit 31 and set bit 32 */ regs->mainstor[abs+3] &= 0xFE; regs->mainstor[abs+4] |= 0x80; retna &= 0x7FFFFFFF; } else { /* For a 24-bit return address, clear bits 31 and 32 */ regs->mainstor[abs+3] &= 0xFE; regs->mainstor[abs+4] &= 0x7F; retna &= 0x00FFFFFF; } #else /*!defined(FEATURE_ESAME)*/ /* For ESA/390, replace bytes 140-143 by the return address, with the high-order bit indicating the addressing mode */ STORE_FW(regs->mainstor + abs + 4, retna); #endif /*!defined(FEATURE_ESAME)*/ #ifdef STACK_DEBUG logmsg (_("stack: PSW=%2.2X%2.2X%2.2X%2.2X %2.2X%2.2X%2.2X%2.2X " "stored at V:" F_VADR " A:" F_RADR "\n"), regs->mainstor[abs], regs->mainstor[abs+1], regs->mainstor[abs+2], regs->mainstor[abs+3], regs->mainstor[abs+4], regs->mainstor[abs+5], regs->mainstor[abs+6], regs->mainstor[abs+7], lsea, abs); #endif /*STACK_DEBUG*/ /* Update virtual and absolute addresses to point to byte 144 */ lsea += 8; LSEA_WRAP(lsea); abs += 8; /* Recalculate absolute address if page boundary crossed */ if ((lsea & PAGEFRAME_BYTEMASK) == 0x000) abs = abs2; /* Store bytes 144-151 according to PC or BAKR */ if (etype == LSED_UET_PC) { #if defined(FEATURE_CALLED_SPACE_IDENTIFICATION) /* Store the called-space identification in bytes 144-147 */ STORE_FW(regs->mainstor + abs, csi); #endif /*defined(FEATURE_CALLED_SPACE_IDENTIFICATION)*/ /* Store the PC number in bytes 148-151 */ STORE_FW(regs->mainstor + abs + 4, pcnum); } else { #if defined(FEATURE_ESAME) /* Store the called address and amode in bytes 144-151 */ STORE_DW(regs->mainstor + abs, calla); #else /*!defined(FEATURE_ESAME)*/ /* Store the called address and amode in bytes 148-151 */ STORE_FW(regs->mainstor + abs + 4, calla); #endif /*!defined(FEATURE_ESAME)*/ } /* Update virtual and absolute addresses to point to byte 152 */ lsea += 8; LSEA_WRAP(lsea); abs += 8; /* Recalculate absolute address if page boundary crossed */ if ((lsea & PAGEFRAME_BYTEMASK) == 0x000) abs = abs2; /* Store zeroes in bytes 152-159 */ memset (regs->mainstor+abs, 0, 8); /* Update virtual and absolute addresses to point to byte 160 */ lsea += 8; LSEA_WRAP(lsea); abs += 8; /* Recalculate absolute address if page boundary crossed */ if ((lsea & PAGEFRAME_BYTEMASK) == 0x000) abs = abs2; #if defined(FEATURE_ESAME) /* For ESAME, store zeroes in bytes 160-167 */ memset (regs->mainstor+abs, 0, 8); /* Update virtual and absolute addresses to point to byte 168 */ lsea += 8; LSEA_WRAP(lsea); abs += 8; /* Recalculate absolute address if page boundary crossed */ if ((lsea & PAGEFRAME_BYTEMASK) == 0x000) abs = abs2; /* For ESAME, store the return address in bytes 168-175 */ STORE_DW (regs->mainstor + abs, retna); #ifdef STACK_DEBUG logmsg (_("stack: PSW2=%2.2X%2.2X%2.2X%2.2X %2.2X%2.2X%2.2X%2.2X " "stored at V:" F_VADR " A:" F_RADR "\n"), regs->mainstor[abs], regs->mainstor[abs+1], regs->mainstor[abs+2], regs->mainstor[abs+3], regs->mainstor[abs+4], regs->mainstor[abs+5], regs->mainstor[abs+6], regs->mainstor[abs+7], lsea, abs); #endif /*STACK_DEBUG*/ /* Update virtual and absolute addresses to point to byte 176 */ lsea += 8; LSEA_WRAP(lsea); abs += 8; /* Recalculate absolute address if page boundary crossed */ if ((lsea & PAGEFRAME_BYTEMASK) == 0x000) abs = abs2; /* If ASN-and-LX-reuse is installed and active, store the SASTEIN (CR3 bits 0-31) in bytes 176-179, and store the PASTEIN (CR4 bits 0-31) in bytes 180-183 */ if (ASN_AND_LX_REUSE_ENABLED(regs)) { STORE_FW(regs->mainstor + abs, regs->CR_H(3)); STORE_FW(regs->mainstor + abs + 4, regs->CR_H(4)); #ifdef STACK_DEBUG logmsg (_("stack: SASTEIN=%2.2X%2.2X%2.2X%2.2X " "PASTEIN=%2.2X%2.2X%2.2X%2.2X \n" "stored at V:" F_VADR " A:" F_RADR "\n"), regs->mainstor[abs], regs->mainstor[abs+1], regs->mainstor[abs+2], regs->mainstor[abs+3], regs->mainstor[abs+4], regs->mainstor[abs+5], regs->mainstor[abs+6], regs->mainstor[abs+7], lsea, abs); #endif /*STACK_DEBUG*/ } /* end if(ASN_AND_LX_REUSE_ENABLED) */ /* Skip bytes 176-223 of the new stack entry */ lsea += 48; LSEA_WRAP(lsea); abs += 48; /* Recalculate absolute address if page boundary crossed */ if ((lsea & PAGEFRAME_BYTEMASK) < 48) abs = abs2 | (lsea & PAGEFRAME_BYTEMASK); /* For ESAME, store access registers 0-15 in bytes 224-287 */ for (i = 0; i < 16; i++) { /* Store the access register in the stack entry */ STORE_FW(regs->mainstor + abs, regs->AR(i)); #ifdef STACK_DEBUG logmsg (_("stack: AR%d=" F_AREG " stored at V:" F_VADR " A:" F_RADR "\n"), i, regs->AR(i), lsea, abs); #endif /*STACK_DEBUG*/ /* Update the virtual and absolute addresses */ lsea += 4; LSEA_WRAP(lsea); abs += 4; /* Recalculate absolute address if page boundary crossed */ if ((lsea & PAGEFRAME_BYTEMASK) == 0x000) abs = abs2; } /* end for(i) */ #endif /*defined(FEATURE_ESAME)*/ /* Build the new linkage stack entry descriptor */ memset (&lsed2, 0, sizeof(LSED)); lsed2.uet = etype & LSED_UET_ET; lsed2.si = lsed.si; rfs -= LSSE_SIZE; STORE_HW(lsed2.rfs,rfs); /* Store the linkage stack entry descriptor in the last eight bytes of the new state entry (bytes 160-167 for ESA/390, or bytes 288-295 for ESAME) */ memcpy (regs->mainstor+abs, &lsed2, sizeof(LSED)); #ifdef STACK_DEBUG logmsg (_("stack: New stack entry at " F_VADR "\n"), lsea); logmsg (_("stack: et=%2.2X si=%2.2X rfs=%2.2X%2.2X nes=%2.2X%2.2X\n"), lsed2.uet, lsed2.si, lsed2.rfs[0], lsed2.rfs[1], lsed2.nes[0], lsed2.nes[1]); #endif /*STACK_DEBUG*/ /* [5.12.3.3] Update the current entry */ STORE_HW(lsed.nes, LSSE_SIZE); absold = ARCH_DEP(abs_stack_addr) (lseaold, regs, ACCTYPE_WRITE); memcpy (regs->mainstor+absold, &lsed, sizeof(LSED)); #ifdef STACK_DEBUG logmsg (_("stack: Previous stack entry updated at A:" F_RADR "\n"), absold); logmsg (_("stack: et=%2.2X si=%2.2X rfs=%2.2X%2.2X nes=%2.2X%2.2X\n"), lsed.uet, lsed.si, lsed.rfs[0], lsed.rfs[1], lsed.nes[0], lsed.nes[1]); #endif /*STACK_DEBUG*/ /* [5.12.3.4] Update control register 15 */ regs->CR(15) = lsea & CR15_LSEA; #ifdef STACK_DEBUG logmsg (_("stack: CR15=" F_CREG "\n"), regs->CR(15)); #endif /*STACK_DEBUG*/ } /* end function ARCH_DEP(form_stack_entry) */ /*-------------------------------------------------------------------*/ /* Locate the current linkage stack entry */ /* */ /* Input: */ /* prinst 1=PR instruction, 0=EREG/EREGG/ESTA/MSTA instruction */ /* lsedptr Pointer to an LSED structure */ /* regs Pointer to the CPU register context */ /* Output: */ /* The entry descriptor for the current state entry in the */ /* linkage stack is copied into the LSED structure. */ /* The home virtual address of the entry descriptor is */ /* returned as the function return value. */ /* */ /* This function performs the first part of the unstacking */ /* process for the Program Return (PR), Extract Stacked */ /* Registers (EREG/EREGG), Extract Stacked State (ESTA), */ /* and Modify Stacked State (MSTA) instructions. */ /* */ /* In the event of any stack error, this function generates */ /* a program check and does not return. */ /*-------------------------------------------------------------------*/ VADR ARCH_DEP(locate_stack_entry) (int prinst, LSED *lsedptr, REGS *regs) { VADR lsea; /* Linkage stack entry addr */ RADR abs; /* Absolute address */ VADR bsea; /* Backward stack entry addr */ /* [5.12.4] Special operation exception if ASF is not enabled, or if DAT is off, or if in secondary-space mode */ if (!ASF_ENABLED(regs) || REAL_MODE(®s->psw) || SECONDARY_SPACE_MODE(®s->psw)) ARCH_DEP(program_interrupt) (regs, PGM_SPECIAL_OPERATION_EXCEPTION); /* Special operation exception if home space mode PR instruction */ if (prinst && HOME_SPACE_MODE(®s->psw)) ARCH_DEP(program_interrupt) (regs, PGM_SPECIAL_OPERATION_EXCEPTION); /* [5.12.4.1] Locate current entry and process header entry */ /* Obtain the virtual address of the current entry from CR15 */ lsea = regs->CR(15) & CR15_LSEA; /* Fetch the entry descriptor of the current entry */ abs = ARCH_DEP(abs_stack_addr) (lsea, regs, ACCTYPE_READ); memcpy (lsedptr, regs->mainstor+abs, sizeof(LSED)); #ifdef STACK_DEBUG logmsg (_("stack: Stack entry located at " F_VADR "\n"), lsea); logmsg (_("stack: et=%2.2X si=%2.2X rfs=%2.2X%2.2X nes=%2.2X%2.2X\n"), lsedptr->uet, lsedptr->si, lsedptr->rfs[0], lsedptr->rfs[1], lsedptr->nes[0], lsedptr->nes[1]); #endif /*STACK_DEBUG*/ /* Check for a header entry */ if ((lsedptr->uet & LSED_UET_ET) == LSED_UET_HDR) { /* For PR instruction only, generate stack operation exception if the unstack suppression bit in the header entry is set */ if (prinst && (lsedptr->uet & LSED_UET_U)) ARCH_DEP(program_interrupt) (regs, PGM_STACK_OPERATION_EXCEPTION); /* Calculate the virtual address of the header entry, which is 8 bytes before the entry descriptor */ lsea -= 8; LSEA_WRAP(lsea); /* Fetch the backward stack entry address from the header */ abs = ARCH_DEP(abs_stack_addr) (lsea, regs, ACCTYPE_READ); FETCH_BSEA(bsea,regs->mainstor + abs); #ifdef STACK_DEBUG logmsg (_("stack: Stack entry located at " F_VADR "\n"), bsea); #endif /*STACK_DEBUG*/ /* Stack empty exception if backward address is not valid */ if ((bsea & LSHE_BVALID) == 0) ARCH_DEP(program_interrupt) (regs, PGM_STACK_EMPTY_EXCEPTION); /* Extract the virtual address of the entry descriptor of the last entry in the previous section */ lsea = bsea & LSHE_BSEA; /* Fetch the entry descriptor of the designated entry */ abs = ARCH_DEP(abs_stack_addr) (lsea, regs, ACCTYPE_READ); memcpy (lsedptr, regs->mainstor+abs, sizeof(LSED)); #ifdef STACK_DEBUG logmsg (_("stack: et=%2.2X si=%2.2X rfs=%2.2X%2.2X " "nes=%2.2X%2.2X\n"), lsedptr->uet, lsedptr->si, lsedptr->rfs[0], lsedptr->rfs[1], lsedptr->nes[0], lsedptr->nes[1]); #endif /*STACK_DEBUG*/ /* Stack specification exception if this is also a header */ if ((lsedptr->uet & LSED_UET_ET) == LSED_UET_HDR) ARCH_DEP(program_interrupt) (regs, PGM_STACK_SPECIFICATION_EXCEPTION); } /* end if(LSED_UET_HDR) */ /* [5.12.4.2] Check for a state entry */ /* Stack type exception if this is not a state entry */ if ((lsedptr->uet & LSED_UET_ET) != LSED_UET_BAKR && (lsedptr->uet & LSED_UET_ET) != LSED_UET_PC) ARCH_DEP(program_interrupt) (regs, PGM_STACK_TYPE_EXCEPTION); /* [5.12.4.3] For PR instruction only, stack operation exception if the unstack suppression bit in the state entry is set */ if (prinst && (lsedptr->uet & LSED_UET_U)) ARCH_DEP(program_interrupt) (regs, PGM_STACK_OPERATION_EXCEPTION); /* Return the virtual address of the entry descriptor */ return lsea; } /* end function ARCH_DEP(locate_stack_entry) */ /*-------------------------------------------------------------------*/ /* Stack modify */ /* */ /* Input: */ /* lsea Virtual address of linkage stack entry descriptor */ /* m1 Left 32 bits to be stored in state entry */ /* m2 Right 32 bits to be stored in state entry */ /* regs Pointer to the CPU register context */ /* */ /* This function places eight bytes of information into the */ /* modifiable area of a state entry in the linkage stack. It */ /* is called by the Modify Stacked State (MSTA) instruction */ /* after it has located the current state entry. */ /* */ /* If a translation exception occurs when accessing the stack */ /* entry, then a program check will be generated by the */ /* abs_stack_addr subroutine, and the function will not return. */ /*-------------------------------------------------------------------*/ void ARCH_DEP(stack_modify) (VADR lsea, U32 m1, U32 m2, REGS *regs) { RADR abs; /* Absolute address */ /* Point back to byte 152 of the state entry */ lsea -= LSSE_SIZE - sizeof(LSED); lsea += 152; LSEA_WRAP(lsea); /* Store the modify values into the state entry */ abs = ARCH_DEP(abs_stack_addr) (lsea, regs, ACCTYPE_WRITE); STORE_FW(regs->mainstor + abs, m1); STORE_FW(regs->mainstor + abs + 4, m2); } /* end function ARCH_DEP(stack_modify) */ /*-------------------------------------------------------------------*/ /* Stack extract */ /* */ /* Input: */ /* lsea Virtual address of linkage stack entry descriptor */ /* r1 The number of an even-odd pair of registers */ /* code A code indicating which bytes are to be extracted: */ /* 0 = Bytes 128-135 (PKN/SASN/EAX/PASN) */ /* 1 = ESA/390: Bytes 136-143 (PSW) */ /* ESAME: Bytes 136-139, 140.0, 168-175.33-63 */ /* (ESA/390-format PSW) */ /* 2 = Bytes 144-151 (Branch address or PC number) */ /* 3 = Bytes 152-159 (Modifiable area) */ /* 4 = Bytes 136-143 and 168-175 (ESAME-format PSW) */ /* 5 = Bytes 176-183 (SASTEIN,PASTEIN) */ /* regs Pointer to the CPU register context */ /* */ /* This function extracts 64 or 128 bits of information from */ /* the status area of a state entry in the linkage stack. It */ /* is called by the Extract Stacked State (ESTA) instruction */ /* after it has located the current state entry. */ /* */ /* For codes 0 through 3, the rightmost 32 bits of the R1 and */ /* R1+1 registers are updated (the leftmost 32 bits remain */ /* unchanged for ESAME). For code 4, which is valid only for */ /* ESAME, all 64 bits of the R1 and R1+1 registers are loaded. */ /* For code 5 (valid only if the ASN-and-LX-reuse facility is */ /* installed), the leftmost 32 bits of the R1 and R1+1 regs */ /* are updated, and the rightmost 32 bits remain unchanged. */ /* */ /* If a translation exception occurs when accessing the stack */ /* entry, then a program check will be generated by the */ /* abs_stack_addr subroutine, and the function will not return. */ /*-------------------------------------------------------------------*/ void ARCH_DEP(stack_extract) (VADR lsea, int r1, int code, REGS *regs) { RADR abs; /* Absolute address */ /* Point back to byte 128 of the state entry */ lsea -= LSSE_SIZE - sizeof(LSED); lsea += 128; #if defined(FEATURE_ESAME) /* For codes 1 and 4, extract bytes 136-143 and 168-175 */ if (code == 1 || code == 4) { U64 psw1, psw2; /* Point to byte 136 of the state entry */ lsea += 8; LSEA_WRAP(lsea); /* Load bits 0-63 of ESAME PSW from bytes 136-143 */ abs = ARCH_DEP(abs_stack_addr) (lsea, regs, ACCTYPE_READ); FETCH_DW(psw1, regs->mainstor + abs); /* Point to byte 168 of the state entry */ lsea += 32; abs += 32; /* Recalculate absolute address if page boundary crossed */ if ((lsea & PAGEFRAME_BYTEMASK) < 32) abs = ARCH_DEP(abs_stack_addr) (lsea, regs, ACCTYPE_READ); /* Load bits 64-127 of ESAME PSW from bytes 168-175 */ FETCH_DW(psw2, regs->mainstor + abs); /* For code 4, return ESAME PSW in general register pair */ if (code == 4) { regs->GR_G(r1) = psw1; regs->GR_G(r1+1) = psw2; return; } /* For code 1, convert ESAME PSW to ESA/390 format */ regs->GR_L(r1) = (psw1 >> 32) | 0x00080000; regs->GR_L(r1+1) = (psw1 & 0x80000000) | (psw2 & 0x7FFFFFFF); /* Set low-order bit of R1+1 if IA exceeds 31-bit address */ if (psw2 > 0x7FFFFFFF) regs->GR_L(r1+1) |= 0x01; return; } /* if(code==1||code==4) */ #endif /*defined(FEATURE_ESAME)*/ #if defined(FEATURE_ASN_AND_LX_REUSE) /* For code 5, extract bytes 176-183 */ if (code == 5) { /* Point to byte 176 of the state entry */ lsea += 48; LSEA_WRAP(lsea); /* Load the SASTEIN, PASTEIN from bytes 176-179, 180-183*/ abs = ARCH_DEP(abs_stack_addr) (lsea, regs, ACCTYPE_READ); FETCH_FW(regs->GR_H(r1), regs->mainstor + abs); FETCH_FW(regs->GR_H(r1+1), regs->mainstor + abs + 4); return; } /* if(code==5) */ #endif /*defined(FEATURE_ASN_AND_LX_REUSE)*/ /* For codes 0,2,3 in ESAME, and codes 0,1,2,3 in ESA/390 */ /* Point to byte 128, 136, 144, or 152 depending on the code */ lsea += code * 8; LSEA_WRAP(lsea); /* Load the general register pair from the state entry */ abs = ARCH_DEP(abs_stack_addr) (lsea, regs, ACCTYPE_READ); FETCH_FW(regs->GR_L(r1), regs->mainstor + abs); FETCH_FW(regs->GR_L(r1+1), regs->mainstor + abs + 4); } /* end function ARCH_DEP(stack_extract) */ /*-------------------------------------------------------------------*/ /* Unstack registers */ /* */ /* Input: */ /* gtype 0=EREG instruction, 1=EREGG or PR instruction */ /* lsea Virtual address of linkage stack entry descriptor */ /* r1 The number of the first register to be loaded */ /* r2 The number of the last register to be loaded */ /* regs Pointer to the CPU register context */ /* */ /* This function loads a range of general registers and */ /* access registers from the specified linkage stack entry. */ /* It is called by the Extract Stacked Registers (EREG/EREGG) */ /* and Program Return (PR) instructions after they have located */ /* the current state entry in the linkage stack. */ /* */ /* If a translation exception occurs when accessing the stack */ /* entry, then a program check will be generated by the */ /* abs_stack_addr subroutine, and the function will not return. */ /* Since the stack entry can only span at most two pages, and */ /* the caller will have already successfully accessed the */ /* entry descriptor which is at the end of the stack entry, */ /* the only place a translation exception can occur is when */ /* attempting to load the first register, in which case the */ /* operation is nullified with all registers unchanged. */ /*-------------------------------------------------------------------*/ void ARCH_DEP(unstack_registers) (int gtype, VADR lsea, int r1, int r2, REGS *regs) { RADR abs, abs2 = 0; /* Absolute address */ VADR firstbyte, /* First byte to be fetched */ lastbyte; /* Last byte to be fetched */ int i; /* Array subscript */ UNREFERENCED(gtype); /* Point back to byte 0 of the state entry */ lsea -= LSSE_SIZE - sizeof(LSED); LSEA_WRAP(lsea); /* Determine first and last byte to fetch from the state entry */ firstbyte = lsea + ((r1 > r2) ? 0 : r1) * LSSE_REGSIZE; lastbyte = lsea + (LSSE_SIZE - 69) + (((r1 > r2) ? 15 : r2) * 4); lsea = firstbyte; /* Obtain absolute address of the state entry */ abs = ARCH_DEP(abs_stack_addr) (lsea, regs, ACCTYPE_READ); /* If the state entry crosses a page boundary, obtain the absolute address of the second page of the stack entry */ if( (firstbyte & PAGEFRAME_PAGEMASK) != (lastbyte & PAGEFRAME_PAGEMASK)) abs2 = ARCH_DEP(abs_stack_addr) (lastbyte & PAGEFRAME_PAGEMASK, regs, ACCTYPE_READ); #ifdef STACK_DEBUG logmsg (_("stack: Unstacking registers %d-%d from " F_VADR "\n"), r1, r2, lsea); #endif /*STACK_DEBUG*/ /* Load general registers from bytes 0-63 (for ESA/390), or bytes 0-127 (for ESAME) of the state entry */ for (i = ((r1 > r2) ? 0 : r1); i <= 15; i++) { /* Load the general register from the stack entry */ if ((r1 <= r2 && i >= r1 && i <= r2) || (r1 > r2 && (i >= r1 || i <= r2))) { #if defined(FEATURE_ESAME) if (gtype) { /* For ESAME PR and EREGG instructions, load all 64 bits of the register */ FETCH_DW(regs->GR_G(i), regs->mainstor + abs); } else { /* For ESAME EREG instruction, load bits 32-63 of the register, and leave bits 0-31 unchanged */ FETCH_FW(regs->GR_L(i), regs->mainstor + abs + 4); } #ifdef STACK_DEBUG logmsg (_("stack: GPR%d=" F_GREG " loaded from V:" F_VADR " A:" F_RADR "\n"), i, regs->GR(i), lsea, abs); #endif /*STACK_DEBUG*/ #else /*!defined(FEATURE_ESAME)*/ /* For ESA/390, load a 32-bit general register */ FETCH_FW(regs->GR_L(i), regs->mainstor + abs); #ifdef STACK_DEBUG logmsg (_("stack: GPR%d=" F_GREG " loaded from V:" F_VADR " A:" F_RADR "\n"), i, regs->GR(i), lsea, abs); #endif /*STACK_DEBUG*/ #endif /*!defined(FEATURE_ESAME)*/ } /* Update the virtual and absolute addresses */ lsea += LSSE_REGSIZE; LSEA_WRAP(lsea); abs += LSSE_REGSIZE; /* Recalculate absolute address if page boundary crossed */ if ((lsea & PAGEFRAME_BYTEMASK) == 0x000) abs = abs2; } /* end for(i) */ #if defined(FEATURE_ESAME) /* For ESAME, skip the next 96 bytes of the state entry */ lsea += 96; abs += 96; /* Recalculate absolute address if page boundary crossed */ if ((lsea & PAGEFRAME_BYTEMASK) < 96) abs = abs2 | (lsea & PAGEFRAME_BYTEMASK); #endif /*defined(FEATURE_ESAME)*/ /* Load access registers from bytes 64-127 (for ESA/390), or bytes 224-280 (for ESAME) of the state entry */ for (i = 0; i <= ((r1 > r2) ? 15 : r2); i++) { /* Load the access register from the stack entry */ if ((r1 <= r2 && i >= r1 && i <= r2) || (r1 > r2 && (i >= r1 || i <= r2))) { FETCH_FW(regs->AR(i),regs->mainstor + abs); SET_AEA_AR(regs, i); #ifdef STACK_DEBUG logmsg (_("stack: AR%d=" F_AREG " loaded from V:" F_VADR " A:" F_RADR "\n"), i, regs->AR(i), lsea, abs); #endif /*STACK_DEBUG*/ } /* Update the virtual and absolute addresses */ lsea += 4; LSEA_WRAP(lsea); abs += 4; /* Recalculate absolute address if page boundary crossed */ if ((lsea & PAGEFRAME_BYTEMASK) == 0x000) abs = abs2; } /* end for(i) */ } /* end function ARCH_DEP(unstack_registers) */ /*-------------------------------------------------------------------*/ /* Program return unstack */ /* */ /* Input: */ /* regs Pointer to a copy of the CPU register context */ /* Output: */ /* lsedap The absolute address of the entry descriptor of */ /* the new current entry on the linkage stack. */ /* rc Return code from load_psw, checked later for PIC 06 */ /* Return value: */ /* The type of entry unstacked: LSED_UET_BAKR or LSED_UET_PC */ /* */ /* This function performs the restoring and updating parts */ /* of the unstacking process for the Program Return (PR) */ /* instruction. If a program exception occurs during the PR */ /* instruction (either during or after the unstack), then the */ /* effects of the instruction must be nullified or suppressed. */ /* This is achieved by updating a copy of the CPU register */ /* context instead of the actual register context. */ /* The current register context is replaced by the copy */ /* only on successful completion of the PR instruction. */ /* */ /* In the event of any stack error, this function generates */ /* a program check and does not return. */ /*-------------------------------------------------------------------*/ int ARCH_DEP(program_return_unstack) (REGS *regs, RADR *lsedap, int *rc) { QWORD newpsw; /* New PSW */ LSED lsed; /* Linkage stack entry desc. */ VADR lsea; /* Linkage stack entry addr */ RADR abs; /* Absolute address */ int permode; /* 1=PER mode is set in PSW */ U16 pkm; /* PSW key mask */ U16 sasn; /* Secondary ASN */ U16 eax; /* Extended AX */ U16 pasn; /* Primary ASN */ VADR lsep; /* Virtual addr of entry desc. of previous stack entry */ /* Find the virtual address of the entry descriptor of the current state entry in the linkage stack */ lsea = ARCH_DEP(locate_stack_entry) (1, &lsed, regs); /* [5.12.4.3] Restore information from stack entry */ /* Load registers 2-14 from the stack entry */ ARCH_DEP(unstack_registers) (1, lsea, 2, 14, regs); /* Point back to the entry descriptor of previous stack entry */ lsep = lsea - LSSE_SIZE; LSEA_WRAP(lsep); /* Point back to byte 128 of the current state entry */ lsea -= LSSE_SIZE - sizeof(LSED); lsea += 128; LSEA_WRAP(lsea); /* Translate virtual address to absolute address */ abs = ARCH_DEP(abs_stack_addr) (lsea, regs, ACCTYPE_READ); /* For a call state entry, replace the PKM, SASN, EAX, and PASN */ if ((lsed.uet & LSED_UET_ET) == LSED_UET_PC) { /* Fetch the PKM from bytes 128-129 of the stack entry */ FETCH_HW(pkm,regs->mainstor + abs); /* Fetch the SASN from bytes 130-131 of the stack entry */ FETCH_HW(sasn,regs->mainstor + abs + 2); /* Fetch the EAX from bytes 132-133 of the stack entry */ FETCH_HW(eax,regs->mainstor + abs + 4); /* Fetch the PASN from bytes 134-135 of the stack entry */ FETCH_HW(pasn,regs->mainstor + abs + 6); #ifdef STACK_DEBUG logmsg (_("stack: PKM=%2.2X%2.2X SASN=%2.2X%2.2X " "EAX=%2.2X%2.2X PASN=%2.2X%2.2X \n" "loaded from V:" F_VADR " A:" F_RADR "\n"), regs->mainstor[abs], regs->mainstor[abs+1], regs->mainstor[abs+2], regs->mainstor[abs+3], regs->mainstor[abs+4], regs->mainstor[abs+5], regs->mainstor[abs+6], regs->mainstor[abs+7], lsea, abs); #endif /*STACK_DEBUG*/ /* Load PKM into CR3 bits 0-15 (32-47) */ regs->CR_LHH(3) = pkm; /* Load SASN into CR3 bits 16-31 (48-63) */ regs->CR_LHL(3) = sasn; /* Load EAX into CR8 bits 0-15 (32-47) */ regs->CR_LHH(8) = eax; /* Load PASN into CR4 bits 16-31 (48-63) */ regs->CR_LHL(4) = pasn; } /* end if(LSED_UET_PC) */ /* Update virtual and absolute addresses to point to byte 136 */ lsea += 8; LSEA_WRAP(lsea); abs += 8; /* Recalculate absolute address if page boundary crossed */ if ((lsea & PAGEFRAME_BYTEMASK) == 0x000) abs = ARCH_DEP(abs_stack_addr) (lsea, regs, ACCTYPE_READ); /* Save the PER mode bit from the current PSW */ permode = (regs->psw.sysmask & PSW_PERMODE) ? 1 : 0; #ifdef STACK_DEBUG logmsg (_("stack: PSW=%2.2X%2.2X%2.2X%2.2X %2.2X%2.2X%2.2X%2.2X " "loaded from V:" F_VADR " A:" F_RADR "\n"), regs->mainstor[abs], regs->mainstor[abs+1], regs->mainstor[abs+2], regs->mainstor[abs+3], regs->mainstor[abs+4], regs->mainstor[abs+5], regs->mainstor[abs+6], regs->mainstor[abs+7], lsea, abs); #endif /*STACK_DEBUG*/ /* Copy PSW bits 0-63 from bytes 136-143 of the stack entry */ memcpy (newpsw, regs->mainstor + abs, 8); #if defined(FEATURE_ESAME) /* For ESAME, advance to byte 168 of the stack entry */ lsea += 32; LSEA_WRAP(lsea); abs += 32; /* Recalculate absolute address if page boundary crossed */ if ((lsea & PAGEFRAME_BYTEMASK) < 32) abs = ARCH_DEP(abs_stack_addr) (lsea, regs, ACCTYPE_READ); /* Copy ESAME PSW bits 64-127 from bytes 168-175 */ memcpy (newpsw + 8, regs->mainstor + abs, 8); /* Update virtual and absolute addresses to point to byte 176 */ lsea += 8; LSEA_WRAP(lsea); abs += 8; /* Recalculate absolute address if page boundary crossed */ if ((lsea & PAGEFRAME_BYTEMASK) == 0x000) abs = ARCH_DEP(abs_stack_addr) (lsea, regs, ACCTYPE_READ); /* For a call state entry only, if ASN-and-LX-reuse is installed and active, load the SASTEIN (high word of CR3) from bytes 176-179, and load the PASTEIN (high word of CR4) from bytes 180-183 */ if ((lsed.uet & LSED_UET_ET) == LSED_UET_PC && ASN_AND_LX_REUSE_ENABLED(regs)) { FETCH_FW(regs->CR_H(3), regs->mainstor + abs); FETCH_FW(regs->CR_H(4), regs->mainstor + abs + 4); #ifdef STACK_DEBUG logmsg (_("stack: SASTEIN=%2.2X%2.2X%2.2X%2.2X " "PASTEIN=%2.2X%2.2X%2.2X%2.2X \n" "loaded from V:" F_VADR " A:" F_RADR "\n"), regs->mainstor[abs], regs->mainstor[abs+1], regs->mainstor[abs+2], regs->mainstor[abs+3], regs->mainstor[abs+4], regs->mainstor[abs+5], regs->mainstor[abs+6], regs->mainstor[abs+7], lsea, abs); #endif /*STACK_DEBUG*/ } /* end if(LSED_UET_PC && ASN_AND_LX_REUSE_ENABLED) */ #endif /*defined(FEATURE_ESAME)*/ /* [5.12.4.4] Pass back the absolute address of the entry descriptor of the preceding linkage stack entry. The next entry size field of this entry will be cleared on successful completion of the PR instruction */ *lsedap = ARCH_DEP(abs_stack_addr) (lsep, regs, ACCTYPE_WRITE); /* [5.12.4.5] Update CR15 to point to the previous entry */ regs->CR(15) = lsep & CR15_LSEA; /* Load new PSW using the bytes extracted from the stack entry */ /* The rc will be checked by calling routine for PIC 06 */ *rc = ARCH_DEP(load_psw) (regs, newpsw); /* Restore the PER mode bit from the current PSW */ if (permode) regs->psw.sysmask |= PSW_PERMODE; else regs->psw.sysmask &= ~PSW_PERMODE; /* restore PER masks which could have been wiped out by load_psw */ SET_IC_MASK(regs); #ifdef STACK_DEBUG logmsg (_("stack: CR15=" F_CREG "\n"), regs->CR(15)); #endif /*STACK_DEBUG*/ /* Return the entry type of the unstacked state entry */ return (lsed.uet & LSED_UET_ET); } /* end function ARCH_DEP(program_return_unstack) */ #endif /*defined(FEATURE_LINKAGE_STACK)*/ #if !defined(_GEN_ARCH) #if defined(_ARCHMODE2) #define _GEN_ARCH _ARCHMODE2 #include "stack.c" #endif #if defined(_ARCHMODE3) #undef _GEN_ARCH #define _GEN_ARCH _ARCHMODE3 #include "stack.c" #endif #endif /*!defined(_GEN_ARCH)*/ hercules-3.07/strsignal.c000644 000765 000765 00000024543 11143760543 017131 0ustar00jmaynardjmaynard000000 000000 /* strsignal.c -- implement strsignal() for architectures without it Written by Fred Fish. fnf@cygnus.com This file is in the public domain. */ // $Id: strsignal.c 4102 2006-12-08 09:43:35Z jj $ // // $Log$ #include "hstdinc.h" #include "hercules.h" #if !defined(HAVE_STRSIGNAL) /* We need to declare sys_siglist, because even if the system provides it we can't assume that it is declared in (for example, SunOS provides sys_siglist, but it does not declare it in any header file). fHowever, we can't declare sys_siglist portably, because on some systems it is declared with const and on some systems it is declared without const. If we were using autoconf, we could work out the right declaration. Until, then we just ignore any declaration in the system header files, and always declare it ourselves. With luck, this will always work. */ #define sys_siglist no_such_symbol /* Routines imported from standard C runtime libraries. */ #ifdef __STDC__ #include extern void *malloc (size_t size); /* 4.10.3.3 */ extern void *memset (void *s, int c, size_t n); /* 4.11.6.1 */ #else /* !__STDC__ */ extern char *malloc (); /* Standard memory allocater */ extern char *memset (); #endif /* __STDC__ */ /* Undefine the macro we used to hide the definition of sys_siglist found in the system header files. */ #undef sys_siglist #ifndef NULL # ifdef __STDC__ # define NULL (void *) 0 # else # define NULL 0 # endif #endif #ifndef MAX # define MAX(a,b) ((a) > (b) ? (a) : (b)) #endif /* Translation table for signal values. Note that this table is generally only accessed when it is used at runtime to initialize signal name and message tables that are indexed by signal value. Not all of these signals will exist on all systems. This table is the only thing that should have to be updated as new signal numbers are introduced. It's sort of ugly, but at least its portable. */ struct signal_info { int value; /* The numeric value from */ const char *name; /* The equivalent symbolic value */ #ifndef HAVE_SYS_SIGLIST const char *msg; /* Short message about this value */ #endif }; #ifndef HAVE_SYS_SIGLIST # define ENTRY(value, name, msg) {value, name, msg} #else # define ENTRY(value, name, msg) {value, name} #endif static const struct signal_info signal_table[] = { #if defined (SIGHUP) ENTRY(SIGHUP, "SIGHUP", "Hangup"), #endif #if defined (SIGINT) ENTRY(SIGINT, "SIGINT", "Interrupt"), #endif #if defined (SIGQUIT) ENTRY(SIGQUIT, "SIGQUIT", "Quit"), #endif #if defined (SIGILL) ENTRY(SIGILL, "SIGILL", "Illegal instruction"), #endif #if defined (SIGTRAP) ENTRY(SIGTRAP, "SIGTRAP", "Trace/breakpoint trap"), #endif /* Put SIGIOT before SIGABRT, so that if SIGIOT==SIGABRT then SIGABRT overrides SIGIOT. SIGABRT is in ANSI and POSIX.1, and SIGIOT isn't. */ #if defined (SIGIOT) ENTRY(SIGIOT, "SIGIOT", "IOT trap"), #endif #if defined (SIGABRT) ENTRY(SIGABRT, "SIGABRT", "Aborted"), #endif #if defined (SIGEMT) ENTRY(SIGEMT, "SIGEMT", "Emulation trap"), #endif #if defined (SIGFPE) ENTRY(SIGFPE, "SIGFPE", "Arithmetic exception"), #endif #if defined (SIGKILL) ENTRY(SIGKILL, "SIGKILL", "Killed"), #endif #if defined (SIGBUS) ENTRY(SIGBUS, "SIGBUS", "Bus error"), #endif #if defined (SIGSEGV) ENTRY(SIGSEGV, "SIGSEGV", "Segmentation fault"), #endif #if defined (SIGSYS) ENTRY(SIGSYS, "SIGSYS", "Bad system call"), #endif #if defined (SIGPIPE) ENTRY(SIGPIPE, "SIGPIPE", "Broken pipe"), #endif #if defined (SIGALRM) ENTRY(SIGALRM, "SIGALRM", "Alarm clock"), #endif #if defined (SIGTERM) ENTRY(SIGTERM, "SIGTERM", "Terminated"), #endif #if defined (SIGUSR1) ENTRY(SIGUSR1, "SIGUSR1", "User defined signal 1"), #endif #if defined (SIGUSR2) ENTRY(SIGUSR2, "SIGUSR2", "User defined signal 2"), #endif /* Put SIGCLD before SIGCHLD, so that if SIGCLD==SIGCHLD then SIGCHLD overrides SIGCLD. SIGCHLD is in POXIX.1 */ #if defined (SIGCLD) ENTRY(SIGCLD, "SIGCLD", "Child status changed"), #endif #if defined (SIGCHLD) ENTRY(SIGCHLD, "SIGCHLD", "Child status changed"), #endif #if defined (SIGPWR) ENTRY(SIGPWR, "SIGPWR", "Power fail/restart"), #endif #if defined (SIGWINCH) ENTRY(SIGWINCH, "SIGWINCH", "Window size changed"), #endif #if defined (SIGURG) ENTRY(SIGURG, "SIGURG", "Urgent I/O condition"), #endif #if defined (SIGIO) /* "I/O pending" has also been suggested, but is misleading since the signal only happens when the process has asked for it, not everytime I/O is pending. */ ENTRY(SIGIO, "SIGIO", "I/O possible"), #endif #if defined (SIGPOLL) ENTRY(SIGPOLL, "SIGPOLL", "Pollable event occurred"), #endif #if defined (SIGSTOP) ENTRY(SIGSTOP, "SIGSTOP", "Stopped (signal)"), #endif #if defined (SIGTSTP) ENTRY(SIGTSTP, "SIGTSTP", "Stopped (user)"), #endif #if defined (SIGCONT) ENTRY(SIGCONT, "SIGCONT", "Continued"), #endif #if defined (SIGTTIN) ENTRY(SIGTTIN, "SIGTTIN", "Stopped (tty input)"), #endif #if defined (SIGTTOU) ENTRY(SIGTTOU, "SIGTTOU", "Stopped (tty output)"), #endif #if defined (SIGVTALRM) ENTRY(SIGVTALRM, "SIGVTALRM", "Virtual timer expired"), #endif #if defined (SIGPROF) ENTRY(SIGPROF, "SIGPROF", "Profiling timer expired"), #endif #if defined (SIGXCPU) ENTRY(SIGXCPU, "SIGXCPU", "CPU time limit exceeded"), #endif #if defined (SIGXFSZ) ENTRY(SIGXFSZ, "SIGXFSZ", "File size limit exceeded"), #endif #if defined (SIGWIND) ENTRY(SIGWIND, "SIGWIND", "SIGWIND"), #endif #if defined (SIGPHONE) ENTRY(SIGPHONE, "SIGPHONE", "SIGPHONE"), #endif #if defined (SIGLOST) ENTRY(SIGLOST, "SIGLOST", "Resource lost"), #endif #if defined (SIGWAITING) ENTRY(SIGWAITING, "SIGWAITING", "Process's LWPs are blocked"), #endif #if defined (SIGLWP) ENTRY(SIGLWP, "SIGLWP", "Signal LWP"), #endif #if defined (SIGDANGER) ENTRY(SIGDANGER, "SIGDANGER", "Swap space dangerously low"), #endif #if defined (SIGGRANT) ENTRY(SIGGRANT, "SIGGRANT", "Monitor mode granted"), #endif #if defined (SIGRETRACT) ENTRY(SIGRETRACT, "SIGRETRACT", "Need to relinguish monitor mode"), #endif #if defined (SIGMSG) ENTRY(SIGMSG, "SIGMSG", "Monitor mode data available"), #endif #if defined (SIGSOUND) ENTRY(SIGSOUND, "SIGSOUND", "Sound completed"), #endif #if defined (SIGSAK) ENTRY(SIGSAK, "SIGSAK", "Secure attention"), #endif ENTRY(0, NULL, NULL) }; /* Translation table allocated and initialized at runtime. Indexed by the signal value to find the equivalent symbolic value. */ static const char **signal_names; static int num_signal_names = 0; /* Translation table allocated and initialized at runtime, if it does not already exist in the host environment. Indexed by the signal value to find the descriptive string. We don't export it for use in other modules because even though it has the same name, it differs from other implementations in that it is dynamically initialized rather than statically initialized. */ #ifndef HAVE_SYS_SIGLIST static int sys_nsig; static const char **sys_siglist; #else #ifdef NSIG static int sys_nsig = NSIG; #else #ifdef _NSIG static int sys_nsig = _NSIG; #endif #endif extern const char * const sys_siglist[]; #endif #ifndef HAVE_SYS_SIGLIST /* NAME init_signal_tables -- initialize the name and message tables SYNOPSIS static void init_signal_tables (); DESCRIPTION Using the signal_table, which is initialized at compile time, generate the signal_names and the sys_siglist (if needed) tables, which are indexed at runtime by a specific signal value. BUGS The initialization of the tables may fail under low memory conditions, in which case we don't do anything particularly useful, but we don't bomb either. Who knows, it might succeed at a later point if we free some memory in the meantime. In any case, the other routines know how to deal with lack of a table after trying to initialize it. This may or may not be considered to be a bug, that we don't specifically warn about this particular failure mode. */ static void init_signal_tables () { const struct signal_info *eip; int nbytes; /* If we haven't already scanned the signal_table once to find the maximum signal value, then go find it now. */ if (num_signal_names == 0) { for (eip = signal_table; eip -> name != NULL; eip++) { if (eip -> value >= num_signal_names) { num_signal_names = eip -> value + 1; } } } /* Now attempt to allocate the sys_siglist table, zero it out, and then initialize it from the statically initialized signal_table. */ if (sys_siglist == NULL) { nbytes = num_signal_names * sizeof (char *); if ((sys_siglist = (const char **) malloc (nbytes)) != NULL) { memset (sys_siglist, 0, nbytes); sys_nsig = num_signal_names; for (eip = signal_table; eip -> name != NULL; eip++) { sys_siglist[eip -> value] = eip -> msg; } } } } #endif /* NAME strsignal -- map a signal number to a signal message string SYNOPSIS const char *strsignal (int signo) DESCRIPTION Maps an signal number to an signal message string, the contents of which are implementation defined. On systems which have the external variable sys_siglist, these strings will be the same as the ones used by psignal(). If the supplied signal number is within the valid range of indices for the sys_siglist, but no message is available for the particular signal number, then returns the string "Signal NUM", where NUM is the signal number. If the supplied signal number is not a valid index into sys_siglist, returns NULL. The returned string is only guaranteed to be valid only until the next call to strsignal. */ const char * strsignal (signo) int signo; { const char *msg; static char buf[32]; #ifndef HAVE_SYS_SIGLIST if (signal_names == NULL) { init_signal_tables (); } #endif if ((signo < 0) || (signo >= sys_nsig)) { /* Out of range, just return NULL */ msg = NULL; } else if ((sys_siglist == NULL) || (sys_siglist[signo] == NULL)) { /* In range, but no sys_siglist or no entry at this index. */ sprintf (buf, "Signal %d", signo); msg = (const char *) buf; } else { /* In range, and a valid message. Just return the message. */ msg = (const char *) sys_siglist[signo]; } return (msg); } #endif // !defined(HAVE_STRSIGNAL) hercules-3.07/tapeccws.c000644 000765 000765 00000522640 11337307610 016732 0ustar00jmaynardjmaynard000000 000000 /* TAPECCWS.C (c) Copyright Roger Bowler, 1999-2009 */ /* Hercules Tape Device Handler CCW Processing */ /* Original Author: Roger Bowler */ /* Prime Maintainer: Ivan Warren */ /* Secondary Maintainer: "Fish" (David B. Trout) */ // $Id: tapeccws.c 5637 2010-02-16 15:25:07Z fish $ /*-------------------------------------------------------------------*/ /* This module contains the CCW handling functions for tape devices. */ /* */ /* The subroutines in this module are called by the general tape */ /* device handler (tapedev.c) when the tape format is AWSTAPE. */ /* */ /* Messages issued by this module are prefixed HHCTA0nn */ /*-------------------------------------------------------------------*/ /*-------------------------------------------------------------------*/ /* Reference information: */ /* SG24-2506 IBM 3590 Tape Subsystem Technical Guide */ /* GA32-0331 IBM 3590 Hardware Reference */ /* GA32-0329 IBM 3590 Introduction and Planning Guide */ /* SG24-2594 IBM 3590 Multiplatform Implementation */ /* ANSI INCITS 131-1994 (R1999) SCSI-2 Reference */ /* GA32-0127 IBM 3490E Hardware Reference */ /* GC35-0152 EREP Release 3.5.0 Reference */ /* SA22-7204 ESA/390 Common I/O-Device Commands */ /*-------------------------------------------------------------------*/ #include "hstdinc.h" #include "hercules.h" /* need Hercules control blocks */ #include "tapedev.h" /* Main tape handler header file */ //#define ENABLE_TRACING_STMTS // (Fish: DEBUGGING) #ifdef ENABLE_TRACING_STMTS #if !defined(DEBUG) #warning DEBUG required for ENABLE_TRACING_STMTS #endif // (TRACE, ASSERT, and VERIFY macros are #defined in hmacros.h) #else #undef TRACE #undef ASSERT #undef VERIFY #define TRACE 1 ? ((void)0) : logmsg #define ASSERT(a) #define VERIFY(a) ((void)(a)) #endif /*-------------------------------------------------------------------*/ /* (forward declarations needed by below tables) */ /*-------------------------------------------------------------------*/ extern BYTE TapeCommands3410 []; extern BYTE TapeCommands3420 []; extern BYTE TapeCommands3422 []; extern BYTE TapeCommands3430 []; extern BYTE TapeCommands3480 []; extern BYTE TapeCommands3490 []; extern BYTE TapeCommands3590 []; extern BYTE TapeCommands9347 []; extern TapeSenseFunc build_sense_3410; extern TapeSenseFunc build_sense_3420; #define build_sense_3422 build_sense_3420 #define build_sense_3430 build_sense_3420 extern TapeSenseFunc build_sense_3480_etal; extern TapeSenseFunc build_sense_3490; extern TapeSenseFunc build_sense_3590; extern TapeSenseFunc build_sense_Streaming; /*-------------------------------------------------------------------*/ /* TapeDevtypeList */ /* Format: */ /* */ /* A: Supported Device Type, */ /* B: Command table index, (TapeCommandTable) */ /* C: UC on RewUnld, (1/0 = true/false) */ /* D: CUE on RewUnld, (1/0 = true/false) */ /* E: Sense Build Function table index (TapeSenseTable) */ /* */ /*-------------------------------------------------------------------*/ int TapeDevtypeList [] = { /* A B C D E */ 0x3410, 0, 1, 0, 0, 0x3411, 0, 1, 0, 0, 0x3420, 1, 1, 1, 1, 0x3422, 2, 0, 0, 2, 0x3430, 3, 0, 0, 3, 0x3480, 4, 0, 0, 4, 0x3490, 5, 0, 0, 5, 0x3590, 6, 0, 0, 6, 0x9347, 7, 0, 0, 7, 0x9348, 7, 0, 0, 7, 0x8809, 7, 0, 0, 7, 0x0000, 0, 0, 0, 0 /* (end of table marker) */ }; /*-------------------------------------------------------------------*/ /* TapeCommandTable */ /* */ /* Specific supported CCW codes for each device type. Index is */ /* fetched by TapeCommandIsValid from "TapeDevtypeList[ n+1 ]". */ /* */ /*-------------------------------------------------------------------*/ BYTE* TapeCommandTable [] = { TapeCommands3410, /* 0 3410/3411 */ TapeCommands3420, /* 1 3420 */ TapeCommands3422, /* 2 3422 */ TapeCommands3430, /* 3 3430 */ TapeCommands3480, /* 4 3480 (Maybe all 38K Tapes) */ TapeCommands3490, /* 5 3490 */ TapeCommands3590, /* 6 3590 */ TapeCommands9347, /* 7 9347 (Maybe all streaming tapes) */ NULL }; /*-------------------------------------------------------------------*/ /* TapeSenseTable */ /* */ /* SENSE function routing table. Index is fetched by 'build_senseX' */ /* function from table entry "TapeDevtypeList[ i+4 ]". */ /*-------------------------------------------------------------------*/ TapeSenseFunc* TapeSenseTable [] = { build_sense_3410, /* 0 3410/3411 */ build_sense_3420, /* 1 3420 */ build_sense_3422, /* 2 3422 */ build_sense_3430, /* 3 3430 */ build_sense_3480_etal, /* 4 3480 (Maybe all 38K Tapes) */ build_sense_3490, /* 5 3490 */ build_sense_3590, /* 6 3590 */ build_sense_Streaming, /* 7 9347 (Maybe all streaming tapes) */ NULL }; /*-------------------------------------------------------------------*/ /* CCW opcode Validity Tables by Device Type */ /*-------------------------------------------------------------------*/ /* */ /* The below tables are used by 'TapeCommandIsValid' to determine */ /* if a CCW code is initially valid or not for the given device. */ /* */ /* 0: Command is NOT valid */ /* * 1: Command is Valid, Tape MUST be loaded */ /* * 2: Command is Valid, Tape NEED NOT be loaded */ /* 3: Command is Valid, But is a NO-OP (return CE+DE now) */ /* 4: Command is Valid, But is a NO-OP (for virtual tapes) */ /* * 5: Command is Valid, Tape MUST be loaded (add DE to status) */ /* */ /* * Note that CCWs codes marked as valid might still get rejected */ /* upon more stringent validity testing done by the actual CCW */ /* processing function itself. */ /* */ /* SOURCES: */ /* */ /* GX20-1850-2 "S/370 Reference Summary" (3410/3411/3420) */ /* GX20-0157-1 "370/XA Reference Summary" (3420/3422/3430/3480) */ /* GA33-1510-0 "S/370 Model 115 FC" (3410/3411) */ /* */ /* Ivan Warren, 2003-02-24 */ /*-------------------------------------------------------------------*/ BYTE TapeCommands3410 [256] = { /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ 0,1,1,1,2,0,0,5,0,0,0,0,1,0,0,5, /* 00 */ 0,0,0,4,0,0,0,1,0,0,0,1,0,0,0,1, /* 10 */ 0,0,0,4,0,0,0,1,0,0,0,4,0,0,0,1, /* 20 */ 0,0,0,4,0,0,0,1,0,0,0,4,0,0,0,1, /* 30 */ 0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0, /* 40 */ 0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0, /* 50 */ 0,0,0,4,0,0,0,0,0,0,0,4,0,0,0,0, /* 60 */ 0,0,0,4,0,0,0,0,0,0,0,4,0,0,0,0, /* 70 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 80 */ 0,0,0,4,0,0,0,1,0,0,0,0,0,0,0,0, /* 90 */ 0,0,0,4,0,0,0,0,0,0,0,4,0,0,0,0, /* A0 */ 0,0,0,4,0,0,0,0,0,0,0,4,0,0,0,0, /* B0 */ 0,0,0,4,0,0,0,0,0,0,0,4,0,0,0,0, /* C0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* D0 */ 0,0,0,0,2,0,0,0,0,0,0,3,0,0,0,0, /* E0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* F0 */ }; BYTE TapeCommands3420 [256] = { /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ 0,1,1,1,2,0,0,5,0,0,0,2,1,0,0,5, /* 00 */ 0,0,0,4,0,0,0,1,0,0,0,1,0,0,0,1, /* 10 */ 0,0,0,4,0,0,0,1,0,0,0,4,0,0,0,1, /* 20 */ 0,0,0,4,0,0,0,1,0,0,0,4,0,0,0,1, /* 30 */ 0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0, /* 40 */ 0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0, /* 50 */ 0,0,0,4,0,0,0,0,0,0,0,4,0,0,0,0, /* 60 */ 0,0,0,4,0,0,0,0,0,0,0,4,0,0,0,0, /* 70 */ 0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0, /* 80 */ 0,0,0,4,0,0,0,1,0,0,0,0,0,0,0,0, /* 90 */ 0,0,0,4,0,0,0,0,0,0,0,4,0,0,0,0, /* A0 */ 0,0,0,4,0,0,0,0,0,0,0,4,0,0,0,0, /* B0 */ 0,0,0,4,0,0,0,0,0,0,0,4,0,0,0,0, /* C0 */ 0,0,0,4,4,0,0,0,0,0,0,0,0,0,0,0, /* D0 */ 0,0,0,0,2,0,0,0,0,0,0,3,0,0,0,0, /* E0 */ 0,0,0,2,4,0,0,0,0,0,0,0,0,2,0,0 /* F0 */ }; BYTE TapeCommands3422 [256] = { /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ 0,1,1,1,2,0,0,5,0,0,0,2,1,0,0,5, /* 00 */ 0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1, /* 10 */ 0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1, /* 20 */ 0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1, /* 30 */ 0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0, /* 40 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 50 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 60 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 70 */ 0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0, /* 80 */ 0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0, /* 90 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* A0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* B0 */ 0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0, /* C0 */ 0,0,0,4,4,0,0,0,0,0,0,0,0,0,0,0, /* D0 */ 0,0,0,0,2,0,0,0,0,0,0,3,0,0,0,0, /* E0 */ 0,0,0,2,4,0,0,0,0,0,0,0,0,2,0,0 /* F0 */ }; BYTE TapeCommands3430 [256] = { /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ 0,1,1,1,2,0,0,5,0,0,0,2,1,0,0,5, /* 00 */ 0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,1, /* 10 */ 0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1, /* 20 */ 0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1, /* 30 */ 0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0, /* 40 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 50 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 60 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 70 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 80 */ 0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0, /* 90 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* A0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* B0 */ 0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0, /* C0 */ 0,0,0,4,4,0,0,0,0,0,0,0,0,0,0,0, /* D0 */ 0,0,0,0,2,0,0,0,0,0,0,3,0,0,0,0, /* E0 */ 0,0,0,2,4,0,0,0,0,0,0,0,0,2,0,0 /* F0 */ }; BYTE TapeCommands3480 [256] = { /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ 3,1,1,1,2,0,0,5,0,0,0,0,1,0,0,5, /* 00 */ 0,0,1,3,0,0,0,1,0,0,0,0,0,0,0,1, /* 10 */ 0,0,1,3,2,0,0,1,0,0,0,3,0,0,0,1, /* 20 */ 0,0,0,3,2,0,0,1,0,0,0,3,0,0,0,1, /* 30 */ 0,0,0,1,0,0,0,0,0,0,0,2,0,0,0,1, /* 40 */ 0,0,0,3,0,0,0,0,0,0,0,3,0,0,0,0, /* 50 */ 0,0,0,3,2,0,0,0,0,0,0,3,0,0,0,0, /* 60 */ 0,0,0,3,0,0,0,2,0,0,0,3,0,0,0,0, /* 70 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 80 */ 0,0,0,3,0,0,0,1,0,0,0,0,0,0,0,2, /* 90 */ 0,0,0,3,0,0,0,0,0,0,0,3,0,0,0,2, /* A0 */ 0,0,0,3,0,0,0,2,0,0,0,3,0,0,0,0, /* B0 */ 0,0,0,2,0,0,0,2,0,0,0,3,0,0,0,0, /* C0 */ 0,0,0,3,0,0,0,0,0,0,0,2,0,0,0,0, /* D0 */ 0,0,0,2,2,0,0,0,0,0,0,0,0,0,0,0, /* E0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* F0 */ }; BYTE TapeCommands3490 [256] = { /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ 3,1,1,1,2,0,0,5,0,0,0,0,1,0,0,5, /* 00 */ 0,0,1,3,0,0,0,1,0,0,0,0,0,0,0,1, /* 10 */ 0,0,1,3,2,0,0,1,0,0,0,3,0,0,0,1, /* 20 */ 0,0,0,3,2,0,0,1,0,0,0,3,0,0,2,1, /* 30 */ 0,0,0,1,0,0,0,0,0,0,0,2,0,0,2,1, /* 40 */ 0,0,0,3,0,0,0,0,0,0,0,2,0,0,0,0, /* 50 */ 0,0,0,3,2,0,0,0,0,0,0,3,0,0,0,0, /* 60 */ 0,0,0,3,0,0,0,2,0,0,0,3,0,0,0,0, /* 70 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 80 */ 0,0,0,3,0,0,0,1,0,0,0,0,0,0,0,2, /* 90 */ 0,0,0,3,0,0,0,0,0,0,0,3,0,0,0,2, /* A0 */ 0,0,0,3,0,0,0,2,0,0,0,3,0,0,0,0, /* B0 */ 0,0,0,2,0,0,0,2,0,0,0,0,0,0,0,0, /* C0 */ 0,0,0,3,0,0,0,0,0,0,0,2,0,0,0,0, /* D0 */ 0,0,0,2,2,0,0,0,0,0,0,0,0,0,0,0, /* E0 */ 0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0 /* F0 */ }; BYTE TapeCommands3590 [256] = { /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ 3,1,1,1,2,0,1,5,0,0,1,0,1,0,0,5, /* 00 */ 0,0,1,3,0,0,0,1,0,0,0,0,0,0,0,1, /* 10 */ 0,0,1,3,2,0,0,1,0,0,0,3,0,0,0,1, /* 20 */ 0,0,0,3,2,0,0,1,0,0,0,3,0,0,2,1, /* 30 */ 0,0,0,1,0,0,0,0,0,0,0,2,0,0,2,1, /* 40 */ 0,0,0,3,0,0,0,0,0,0,0,2,0,0,0,0, /* 50 */ 0,0,1,3,2,0,0,0,0,0,0,3,0,0,0,0, /* 60 */ 0,0,0,3,0,0,0,2,0,0,0,3,0,0,0,0, /* 70 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 80 */ 0,0,0,3,0,0,0,1,0,0,0,0,0,0,0,2, /* 90 */ 0,0,0,3,0,0,0,0,0,0,0,3,0,0,0,2, /* A0 */ 0,0,0,3,0,0,0,2,0,0,0,3,0,0,0,0, /* B0 */ 0,0,2,2,0,0,0,2,0,0,0,0,0,0,0,2, /* C0 */ 0,0,0,3,0,0,0,0,0,0,0,2,0,0,0,0, /* D0 */ 0,0,0,2,2,0,0,0,0,0,0,0,0,0,0,0, /* E0 */ 0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0 /* F0 */ }; BYTE TapeCommands9347 [256] = { /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ 0,1,1,1,2,0,0,5,0,0,0,2,1,0,0,5, /* 00 */ 0,0,0,4,0,0,0,1,0,0,0,1,0,0,0,1, /* 10 */ 0,0,0,4,0,0,0,1,0,0,0,4,0,0,0,1, /* 20 */ 0,0,0,4,0,0,0,1,0,0,0,4,0,0,0,1, /* 30 */ 0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0, /* 40 */ 0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0, /* 50 */ 0,0,0,4,0,0,0,0,0,0,0,4,0,0,0,0, /* 60 */ 0,0,0,4,0,0,0,0,0,0,0,4,0,0,0,0, /* 70 */ 0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0, /* 80 */ 0,0,0,4,0,0,0,1,0,0,0,0,0,0,0,0, /* 90 */ 0,0,0,4,2,0,0,0,0,0,0,4,0,0,0,0, /* A0 */ 0,0,0,4,0,0,0,0,0,0,0,4,0,0,0,0, /* B0 */ 0,0,0,4,0,0,0,0,0,0,0,4,0,0,0,0, /* C0 */ 0,0,0,4,4,0,0,0,0,0,0,0,0,0,0,0, /* D0 */ 0,0,0,0,2,0,0,0,0,0,0,3,0,0,0,0, /* E0 */ 0,0,0,2,4,0,0,0,0,0,0,0,0,2,0,0 /* F0 */ }; /*-------------------------------------------------------------------*/ /* Ivan Warren 20040227 */ /* */ /* This table is used by channel.c to determine if a CCW code */ /* is an immediate command or not. */ /* */ /* The tape is addressed in the DEVHND structure as 'DEVIMM immed' */ /* */ /* 0: ("false") Command is *NOT* an immediate command */ /* 1: ("true") Command *IS* an immediate command */ /* */ /* Note: An immediate command is defined as a command which returns */ /* CE (channel end) during initialization (that is, no data is */ /* actually transfered). In this case, IL is not indicated for a */ /* Format 0 or Format 1 CCW when IL Suppression Mode is in effect. */ /* */ /*-------------------------------------------------------------------*/ BYTE TapeImmedCommands [256] = { /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ 0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,1, /* 00 */ 0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1, /* 10 */ 0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1, /* 20 */ 0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1, /* 30 */ 0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0, /* 40 */ 0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1, /* 50 */ 0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1, /* 60 */ 0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,1, /* 70 */ /* Adrian Trenkwalder - 77 was 1 */ 0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1, /* 80 */ 0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0, /* 90 */ 0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0, /* A0 */ 0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,1, /* B0 */ 0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,1, /* C0 */ 0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,1, /* D0 */ 0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,1, /* E0 */ 0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1 /* F0 */ }; /*-------------------------------------------------------------------*/ /* TapeCommandIsValid (Ivan Warren 20030224) */ /*-------------------------------------------------------------------*/ /* */ /* Determine if a CCW code is valid for the Device */ /* */ /* rc 0: is *NOT* valid */ /* rc 1: is Valid, tape MUST be loaded */ /* rc 2: is Valid, tape NEED NOT be loaded */ /* rc 3: is Valid, But is a NO-OP (Return CE+DE now) */ /* rc 4: is Valid, But is a NO-OP for virtual tapes */ /* rc 5: is Valid, Tape Must be loaded - Add DE to status */ /* rc 6: is Valid, Tape load attempted - but not an error */ /* (used for sense and no contingency allegiance exists) */ /* */ /*-------------------------------------------------------------------*/ int TapeCommandIsValid (BYTE code, U16 devtype, BYTE *rustat) { int i, rc, tix = 0, devtfound = 0; /* ** Find the D/T in the table ** If not found, treat as invalid CCW code */ *rustat = 0; for (i = 0; TapeDevtypeList[i] != 0; i += TAPEDEVTYPELIST_ENTRYSIZE) { if (TapeDevtypeList[i] == devtype) { devtfound = 1; tix = TapeDevtypeList[i+1]; if (TapeDevtypeList[i+2]) { *rustat |= CSW_UC; } if (TapeDevtypeList[i+3]) { *rustat |= CSW_CUE; } break; } } if (!devtfound) return 0; rc = TapeCommandTable[tix][code]; return rc; } /* end function TapeCommandIsValid */ /*********************************************************************/ /*********************************************************************/ /** **/ /** MAIN TAPE CCW PROCESSING FUNCTION **/ /** **/ /*********************************************************************/ /*********************************************************************/ #if defined( OPTION_TAPE_AUTOMOUNT ) static TAMDIR* findtamdir( int rej, int minlen, const char* pszDir ); #endif void tapedev_execute_ccw (DEVBLK *dev, BYTE code, BYTE flags, BYTE chained, U16 count, BYTE prevcode, int ccwseq, BYTE *iobuf, BYTE *more, BYTE *unitstat, U16 *residual) { int rc; /* Return code */ int len; /* Length of data block */ long num; /* Number of bytes to read */ int drc; /* code disposition */ BYTE rustat; /* Addl CSW stat on Rewind Unload */ static BYTE supvr_inhibit = 0; /* Supvr-Inhibit mode active */ static BYTE write_immed = 0; /* Write-Immed. mode active */ UNREFERENCED(ccwseq); /* Reset flags at start of CCW chain */ if (dev->ccwseq == 0) { supvr_inhibit = 0; /* (reset to default mode) */ write_immed = 0; /* (reset to default mode) */ dev->tapssdlen = 0; /* (clear all subsys data) */ } /* If this is a data-chained READ, then return any data remaining in the buffer which was not used by the previous CCW */ if (chained & CCW_FLAGS_CD) { if (IS_CCW_RDBACK(code)) { /* We don't need to move anything in this case - just set length */ } else { memmove (iobuf, iobuf + dev->curbufoff, dev->curblkrem); } RESIDUAL_CALC (dev->curblkrem); dev->curblkrem -= num; dev->curbufoff = num; *unitstat = CSW_CE | CSW_DE; return; } /* Command reject if data chaining and command is not a read type */ if ((flags & CCW_FLAGS_CD) && !(IS_CCW_READ(code) || IS_CCW_RDBACK(code))) { logmsg(_("HHCTA072E Data chaining not supported for CCW %2.2X\n"), code); build_senseX(TAPE_BSENSE_BADCOMMAND,dev,unitstat,code); return; } /* Command reject if command is not Read Subsystem Data command if the previous one was a Perform Subsystem Function command that prepared some subsystem data for subsequent reading */ if (0x77 == prevcode && dev->tapssdlen && 0x3E != code) { build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code); return; } /* Early determination of CCW validity via TapeCommandTable lookup... */ drc = TapeCommandIsValid (code, dev->devtype, &rustat); switch (drc) { default: /* Should NOT occur! */ ASSERT(0); // (fall thru to case 0 = unsupported) case 0: /* Unsupported CCW code for given device-type */ build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code); return; case 1: /* Valid - Tape MUST be loaded */ break; case 2: /* Valid - Tape NEED NOT be loaded */ break; case 3: /* Valid - But is a NO-OP (return CE+DE now) */ /* Command reject if the volume is currently fenced */ if (dev->fenced) { build_senseX (TAPE_BSENSE_FENCED, dev, unitstat, code); return; } build_senseX (TAPE_BSENSE_STATUSONLY, dev, unitstat, code); return; case 4: /* Valid, But is a NO-OP (for virtual tapes) */ /* Command reject if the volume is currently fenced */ if (dev->fenced) { build_senseX (TAPE_BSENSE_FENCED, dev, unitstat, code); return; } /* If non-virtual (SCSI) then further processing required */ if (dev->tapedevt == TAPEDEVT_SCSITAPE) break; build_senseX (TAPE_BSENSE_STATUSONLY, dev, unitstat, code); return; case 5: /* Valid - Tape MUST be loaded (add DE to status) */ break; } // end switch (drc) /* Verify a tape is loaded if that is required for this CCW... */ if ((1 == drc || 5 == drc) && // (tape MUST be loaded?) (dev->fd < 0 || TAPEDEVT_SCSITAPE == dev->tapedevt)) // (no tape loaded or non-virtual?) { *residual = count; /* Error if tape unloaded */ if (!strcmp (dev->filename, TAPE_UNLOADED)) { build_senseX (TAPE_BSENSE_TAPEUNLOADED, dev, unitstat, code); return; } /* Open the device file if necessary */ if (dev->fd < 0) { rc = dev->tmh->open( dev, unitstat, code ); if (rc < 0) /* Did open fail? */ { return; /* Yes, exit with unit status */ } } /* Error if tape is not loaded */ if (!dev->tmh->tapeloaded( dev, unitstat, code )) { build_senseX (TAPE_BSENSE_TAPEUNLOADED, dev, unitstat, code); return; } } /* Process depending on CCW opcode */ switch (code) { /*---------------------------------------------------------------*/ /* MODE SET (pre-3480 and earlier drives) */ /*---------------------------------------------------------------*/ /* Patch to no-op modeset 1 (7-track) commands - */ /* causes VM problems */ /* Andy Norrie 2002/10/06 */ case 0x13: case 0x23: case 0x33: case 0x3B: case 0x53: case 0x63: case 0x6B: // case 0x73: // Mode Set (7-track 556/Odd/Normal) for 3420-3/5/7 // with 7-track feature installed, No-op for 3420-2/4/6 // and 3480, Invalid for 3422/3430, "Set Interface // Identifier" for 3490 and later. NOTE: 3480 and earlier // interpretation handled by command-table; 3490 and // and later handled further below. case 0x7B: case 0x93: case 0xA3: case 0xAB: case 0xB3: case 0xBB: // case 0xC3: // Mode Set (9-track 1600 bpi) for models earlier than // 3480, "Set Tape-Write-Immediate" for 3480 and later. // NOTE: handled by command-table for all models earlier // than 3480; 3480 and later handled further below. case 0xCB: /* 9-track 800 bpi */ case 0xD3: /* 9-track 6250 bpi */ case 0xEB: /* invalid mode set issued by DOS/VS */ { build_senseX(TAPE_BSENSE_STATUSONLY,dev,unitstat,code); break; } /*---------------------------------------------------------------*/ /* WRITE */ /*---------------------------------------------------------------*/ case 0x01: { /* Command reject if the volume is currently fenced */ if (dev->fenced) { build_senseX (TAPE_BSENSE_FENCED, dev, unitstat, code); break; } /* Unit check if tape is write-protected */ if (dev->readonly || dev->tdparms.logical_readonly) { build_senseX (TAPE_BSENSE_WRITEPROTECT, dev, unitstat, code); break; } /* Update matrix display if needed */ if ( TAPEDISPTYP_WAITACT == dev->tapedisptype ) { dev->tapedisptype = TAPEDISPTYP_IDLE; UpdateDisplay( dev ); } /* Assign a unique Message Id for this I/O if needed */ INCREMENT_MESSAGEID(dev); /* Write a block to the tape according to device type */ if ((rc = dev->tmh->write( dev, iobuf, count, unitstat, code)) < 0) break; // (error) *residual = 0; /* Perform flush/sync and/or set normal completion status */ if (!write_immed || (rc = dev->tmh->sync( dev, unitstat, code )) == 0) build_senseX( TAPE_BSENSE_STATUSONLY, dev, unitstat, code ); break; } /*---------------------------------------------------------------*/ /* READ FORWARD (3590 only) */ /*---------------------------------------------------------------*/ case 0x06: { /* SG24-2506 IBM 3590 Tape Subsystem Technical Guide 5.2.1 Separate Channel Commands for IPL Read and Normal Read On IBM 3480/3490 tape devices there is only one Read Forward CCW, the X'02' command code. This CCW is used to perform not only normal read operations but also an IPL Read from tape, for example, DFSMSdss Stand-Alone Restore. When the CCW is used as an IPL Read, it is not subject to resetting event notification, by definition. Because there is only one Read Forward CCW, it cannot be subject to resetting event notification on IBM 3480 and 3490 devices. To differentiate between an IPL Read and a normal read forward operation, the X'02' command code has been redefined to be the IPL Read CCW, and a new X'06' command code has been defined to be the Read Forward CCW. The new Read Forward CCW, X'06', is subject to resetting event notification, as should be the case for normal read CCWs issued by applications or other host software. */ // PROGRAMMING NOTE: I'm not sure what they mean by "resetting // event notification" above, but for now we'll just FALL THROUGH // to the below IPL READ logic... } // (purposely FALL THROUGH to below IPL READ logic for now) /*---------------------------------------------------------------*/ /* IPL READ (non-3590) */ /*---------------------------------------------------------------*/ case 0x02: { /* Command reject if the volume is currently fenced */ if (dev->fenced) { build_senseX (TAPE_BSENSE_FENCED, dev, unitstat, code); break; } /* Update matrix display if needed */ if ( TAPEDISPTYP_WAITACT == dev->tapedisptype ) { dev->tapedisptype = TAPEDISPTYP_IDLE; UpdateDisplay( dev ); } /* Assign a unique Message Id for this I/O if needed */ INCREMENT_MESSAGEID(dev); /* Read a block from the tape according to device type */ /* Exit with unit check status if read error condition */ if ((len = dev->tmh->read( dev, iobuf, unitstat, code)) < 0) break; // (error) /* Calculate number of bytes to read and residual byte count */ RESIDUAL_CALC (len); /* Save size and offset of data not used by this CCW */ dev->curblkrem = len - num; dev->curbufoff = num; /* Exit with unit exception status if tapemark was read */ if (len == 0) build_senseX (TAPE_BSENSE_READTM, dev, unitstat, code); else build_senseX (TAPE_BSENSE_STATUSONLY, dev, unitstat, code); break; } /*---------------------------------------------------------------*/ /* CONTROL NO-OPERATION */ /*---------------------------------------------------------------*/ case 0x03: { /* Command reject if the volume is currently fenced */ if (dev->fenced) { build_senseX (TAPE_BSENSE_FENCED, dev, unitstat, code); break; } build_senseX (TAPE_BSENSE_STATUSONLY, dev, unitstat, code); break; } /*---------------------------------------------------------------*/ /* SENSE */ /*---------------------------------------------------------------*/ case 0x04: { /* Calculate residual byte count */ RESIDUAL_CALC (dev->numsense); /* If we don't already have some sense already pre-built and ready and waiting, then we'll have to build it fresh for this call... Otherwise, we use whatever we already have waiting for them pre-built from a previous call... */ if (!dev->sns_pending) build_senseX (TAPE_BSENSE_UNSOLICITED, dev, unitstat, code); *unitstat = CSW_CE|CSW_DE; /* Need to do this ourselves as */ /* we might not have gone thru */ /* build_senseX... */ /* Copy device sense bytes to channel I/O buffer, clear them for the next time, and then finally, reset the Contengent Allegiance condition... */ memcpy (iobuf, dev->sense, num); memset (dev->sense, 0, sizeof(dev->sense)); dev->sns_pending = 0; break; } /*---------------------------------------------------------------*/ /* READ FORWARD (3590 only) */ /*---------------------------------------------------------------*/ // case 0x06: // { // (handled by case 0x02: IPL READ) // } /*---------------------------------------------------------------*/ /* REWIND */ /*---------------------------------------------------------------*/ case 0x07: { /* Update matrix display if needed */ if ( TAPEDISPTYP_IDLE == dev->tapedisptype || TAPEDISPTYP_WAITACT == dev->tapedisptype ) { dev->tapedisptype = TAPEDISPTYP_REWINDING; UpdateDisplay( dev ); } /* Assign a unique Message Id for this I/O if needed */ INCREMENT_MESSAGEID(dev); /* Do the rewind */ rc = dev->tmh->rewind( dev, unitstat, code); /* Update matrix display if needed */ if ( TAPEDISPTYP_REWINDING == dev->tapedisptype ) { dev->tapedisptype = TAPEDISPTYP_IDLE; UpdateDisplay( dev ); } /* Check for error */ if (rc < 0) { dev->fenced = 1; break; } dev->eotwarning = 0; dev->fenced = 0; build_senseX (TAPE_BSENSE_STATUSONLY, dev, unitstat, code); break; } /*---------------------------------------------------------------*/ /* READ PREVIOUS (3590) */ /*---------------------------------------------------------------*/ case 0x0A: { /* SG24-2506 IBM 3590 Tape Subsystem Technical Guide 5.2.2 Read Previous to Replace Read Backward: The ESCON-attached Magstar tape drive does not support the Read Backward CCW (command code, X'0C'). It supports a new Read Previous CCW that allows processing of an IBM 3590 High Performance Tape Cartridge in the backward direction without the performance penalties that exist with the Read Backward CCW. IBM 3480 and 3490 devices had to reread the physical block from the medium for each request of a logical block. The Magstar tape drive retains the physical block in the device buffer and satisfies any subsequent Read Previous from the buffer, similar to how Read Forward operates. The Read Previous CCW operates somewhat like the Read Backward CCW in that it can be used to process the volumes in the backward direction. It is different from the Read Backward, however, because the data is transferred to the host in the same order in which it was written, rather than in reverse order like Read Backward. */ /* SG24-2594 IBM 3590 Multiplatform Implementation 5.1.2 New and Changed Read Channel Commands [...] That is, the Read Backward command's data address will point to the end of the storage area, while a Read Previous command points to the beginning of the storage area... */ // PROGRAMMING NOTE: luckily, channel.c's buffer handling // causes transparent handling of Read Backward/Reverse, // so the above buffer alignment and data transfer order // is not a concern for us here. // PROGRAMMING NOTE: until we can add support to Hercules // allowing direct SCSI i/o (so that we can issue the 'Read // Reverse' command directly to the SCSI device), we will // simply FALL THROUGH to our existing "Read Backward" logic. } // (purposely FALL THROUGH to the 'READ BACKWARD' logic below) /*---------------------------------------------------------------*/ /* READ BACKWARD */ /*---------------------------------------------------------------*/ case 0x0C: { /* Update matrix display if needed */ if ( TAPEDISPTYP_WAITACT == dev->tapedisptype ) { dev->tapedisptype = TAPEDISPTYP_IDLE; UpdateDisplay( dev ); } /* Backspace to previous block according to device type */ /* Exit with unit check status if error condition */ if ((rc = dev->tmh->bsb( dev, unitstat, code )) < 0) break; // (error) /* Exit with unit exception status if tapemark was sensed */ if (rc == 0) { *residual = 0; build_senseX (TAPE_BSENSE_READTM, dev, unitstat, code); break; } /* Assign a unique Message Id for this I/O if needed */ INCREMENT_MESSAGEID(dev); /* Now read in a forward direction the actual data block we just backspaced over, and exit with unit check status on any read error condition */ if ((len = dev->tmh->read( dev, iobuf, unitstat, code )) < 0) break; // (error) /* Calculate number of bytes to read and residual byte count */ RESIDUAL_CALC (len); /* Save size and offset of data not used by this CCW */ dev->curblkrem = len - num; dev->curbufoff = num; /* Backspace to previous block according to device type, and exit with unit check status if error condition */ if ((rc = dev->tmh->bsb( dev, unitstat, code )) < 0) break; // (error) /* Set normal status */ build_senseX (TAPE_BSENSE_STATUSONLY, dev, unitstat, code); break; } /* End case 0x0C: READ BACKWARD */ /*---------------------------------------------------------------*/ /* REWIND UNLOAD */ /*---------------------------------------------------------------*/ case 0x0F: { /* Update matrix display if needed */ if ( dev->tdparms.displayfeat ) { if ( TAPEDISPTYP_UMOUNTMOUNT == dev->tapedisptype ) { dev->tapedisptype = TAPEDISPTYP_MOUNT; dev->tapedispflags |= TAPEDISPFLG_REQAUTOMNT; strlcpy( dev->tapemsg1, dev->tapemsg2, sizeof(dev->tapemsg1) ); } else if ( TAPEDISPTYP_UNMOUNT == dev->tapedisptype ) { dev->tapedisptype = TAPEDISPTYP_IDLE; } } if ( TAPEDISPTYP_IDLE == dev->tapedisptype || TAPEDISPTYP_WAITACT == dev->tapedisptype ) { dev->tapedisptype = TAPEDISPTYP_UNLOADING; UpdateDisplay( dev ); } /* Assign a unique Message Id for this I/O if needed */ INCREMENT_MESSAGEID(dev); /* Do the Rewind-Unload */ #if defined(OPTION_SCSI_TAPE) if ( TAPEDEVT_SCSITAPE == dev->tapedevt ) int_scsi_rewind_unload( dev, unitstat, code ); else #endif dev->tmh->close(dev); /* Update matrix display if needed */ if ( TAPEDISPTYP_UNLOADING == dev->tapedisptype ) { dev->tapedisptype = TAPEDISPTYP_IDLE; UpdateDisplay( dev ); } if ((*unitstat & CSW_UC) != 0) // (did it work?) break; // (no it didn't) dev->curfilen = 1; dev->nxtblkpos = 0; dev->prvblkpos = -1; dev->eotwarning = 0; // dev->fenced = 0; // (handler already did this) /* Update matrix display */ UpdateDisplay( dev ); build_senseX(TAPE_BSENSE_RUN_SUCCESS,dev,unitstat,code); if ( dev->als ) { TID dummy_tid; char thread_name[64]; snprintf(thread_name,sizeof(thread_name), "autoload wait for %4.4X tapemount thread", dev->devnum); thread_name[sizeof(thread_name)-1] = 0; create_thread( &dummy_tid, DETACHED, autoload_wait_for_tapemount_thread, dev, thread_name ); } ReqAutoMount( dev ); break; } /* End case 0x0F: REWIND UNLOAD */ /*---------------------------------------------------------------*/ /* READ BUFFER (3480 and later) */ /*---------------------------------------------------------------*/ case 0x12: { /* GA32-0127 IBM 3490E Hardware Reference Read Buffer (X'12') The Read Buffer command transfers data from the control unit to the channel if any buffered write data is in the control unit's buffer. For each Read Buffer command completed, the controlling computer retrieves one block of data in last-in/ first-out (LIFO) sequence until the buffer for the addressed tape drive is empty. The controlling computer usually issues this command when the tape drive or subsystem malfunctions and cannot write data from the buffer to the tape. */ /* Command reject if the volume is currently fenced */ if (dev->fenced) { build_senseX (TAPE_BSENSE_FENCED, dev, unitstat, code); break; } // PROGRAMMING NOTE: until we can add support for performing // SCSI i/o directly to the actual real device, we simply do // the same thing for non-virtual devices as we do for virtual // ones: we force-flush the data to the device (i.e. sync) // and then tell the truth: that there's zero bytes of data // still buffered (which is true if we just flushed it all) // Once we add direct SCSI i/o support though, we can change // the below to do an actual read-buffer SCSI command for // non-virtual devices. (We will still always need the below // for virtual devices though) /* Assign a unique Message Id for this I/O if needed */ INCREMENT_MESSAGEID(dev); // Perform flush/sync; exit on error... if ((rc = dev->tmh->sync( dev, unitstat, code )) < 0) break; // (i/o error) // Flush complete. Our buffer is now empty. Tell them that. RESIDUAL_CALC (0); dev->curblkrem = 0; dev->curbufoff = 0; break; } /*---------------------------------------------------------------*/ /* ERASE GAP */ /*---------------------------------------------------------------*/ case 0x17: { /* Command reject if the volume is currently fenced */ if (dev->fenced) { build_senseX (TAPE_BSENSE_FENCED, dev, unitstat, code); break; } /* Unit check if tape is write-protected */ if (dev->readonly || dev->tdparms.logical_readonly) { build_senseX (TAPE_BSENSE_WRITEPROTECT, dev, unitstat, code); break; } /* Update matrix display if needed */ if ( TAPEDISPTYP_WAITACT == dev->tapedisptype ) { dev->tapedisptype = TAPEDISPTYP_IDLE; UpdateDisplay( dev ); } /* Assign a unique Message Id for this I/O if needed */ INCREMENT_MESSAGEID(dev); /* Do the ERG; exit if error */ if ((rc = dev->tmh->erg( dev, unitstat, code )) < 0) break; // (error) /* Perform flush/sync and/or set normal completion status */ if (0 || !write_immed || (rc = dev->tmh->sync( dev, unitstat, code )) == 0 ) build_senseX( TAPE_BSENSE_STATUSONLY, dev, unitstat, code ); break; } /*---------------------------------------------------------------*/ /* WRITE TAPE MARK */ /*---------------------------------------------------------------*/ case 0x1F: { /* Command reject if the volume is currently fenced */ if (dev->fenced) { build_senseX (TAPE_BSENSE_FENCED, dev, unitstat, code); break; } /* Unit check if tape is write-protected */ if (dev->readonly || dev->tdparms.logical_readonly) { build_senseX (TAPE_BSENSE_WRITEPROTECT, dev, unitstat, code); break; } /* Update matrix display if needed */ if ( TAPEDISPTYP_WAITACT == dev->tapedisptype ) { dev->tapedisptype = TAPEDISPTYP_IDLE; UpdateDisplay( dev ); } /* Assign a unique Message Id for this I/O if needed */ INCREMENT_MESSAGEID(dev); /* Do the WTM; exit if error */ if ((rc = dev->tmh->wtm(dev,unitstat,code)) < 0) break; // (error) dev->curfilen++; /* Perform flush/sync and/or set normal completion status */ if (0 || !write_immed || (rc = dev->tmh->sync( dev, unitstat, code )) == 0 ) build_senseX( TAPE_BSENSE_STATUSONLY, dev, unitstat, code ); break; } /*---------------------------------------------------------------*/ /* READ BLOCK ID */ /*---------------------------------------------------------------*/ case 0x22: { BYTE log_blockid [4]; // (temp; BIG-ENDIAN format) BYTE phys_blockid [4]; // (temp; BIG-ENDIAN format) int errcode = TAPE_BSENSE_STATUSONLY; // (presume success) /* Command reject if the volume is currently fenced */ if (dev->fenced) { build_senseX (TAPE_BSENSE_FENCED, dev, unitstat, code); break; } /* Assign a unique Message Id for this I/O if needed */ INCREMENT_MESSAGEID(dev); /* Calculate number of bytes and residual byte count */ RESIDUAL_CALC( 2 * sizeof(dev->blockid) ); /* Ask media handler for actual value(s)... */ if ((rc = dev->tmh->readblkid( dev, log_blockid, phys_blockid )) < 0) errcode = TAPE_BSENSE_LOCATEERR; else { /* Copy results to channel I/O buffer... */ memcpy( &iobuf[0], log_blockid, 4 ); memcpy( &iobuf[4], phys_blockid, 4 ); } /* Set completion status... */ build_senseX( errcode, dev, unitstat, code ); break; } /*---------------------------------------------------------------*/ /* READ BUFFERED LOG */ /*---------------------------------------------------------------*/ case 0x24: { /* Calculate residual byte count... */ // PROGRAMMING NOTE: technically we *should* have up to // 64 bytes to give them, but we may not have that many. /* How many bytes we SHOULD have depends on whether Extended Buffered Log support is enabled or not */ len = (dev->devchar[8] & 0x01) ? 64 : 32; RESIDUAL_CALC (len); /* Clear the device sense bytes */ memset (iobuf, 0, num); /* Copy device sense bytes to channel I/O buffer */ memcpy (iobuf, dev->sense, dev->numsense < (U32)num ? dev->numsense : (U32)num); /* Return unit status */ build_senseX (TAPE_BSENSE_STATUSONLY, dev, unitstat, code); break; } /*---------------------------------------------------------------*/ /* BACKSPACE BLOCK */ /*---------------------------------------------------------------*/ case 0x27: { /* Command reject if the volume is currently fenced */ if (dev->fenced) { build_senseX (TAPE_BSENSE_FENCED, dev, unitstat, code); break; } /* Update matrix display if needed */ if ( TAPEDISPTYP_WAITACT == dev->tapedisptype ) { dev->tapedisptype = TAPEDISPTYP_IDLE; UpdateDisplay( dev ); } /* Assign a unique Message Id for this I/O if needed */ INCREMENT_MESSAGEID(dev); /* Backspace to previous block according to device type, and exit with unit check status on error condition */ if ((rc = dev->tmh->bsb( dev, unitstat, code )) < 0) break; /* Exit with unit exception status if tapemark was sensed */ if (rc == 0) { build_senseX (TAPE_BSENSE_READTM, dev, unitstat, code); break; } /* Set normal status */ build_senseX (TAPE_BSENSE_STATUSONLY, dev, unitstat, code); break; } /*---------------------------------------------------------------*/ /* BACKSPACE FILE */ /*---------------------------------------------------------------*/ case 0x2F: { /* Command reject if the volume is currently fenced */ if (dev->fenced) { build_senseX (TAPE_BSENSE_FENCED, dev, unitstat, code); break; } /* Update matrix display if needed */ if ( TAPEDISPTYP_WAITACT == dev->tapedisptype ) { dev->tapedisptype = TAPEDISPTYP_IDLE; UpdateDisplay( dev ); } /* Assign a unique Message Id for this I/O if needed */ INCREMENT_MESSAGEID(dev); /* Backspace to previous file according to device type, and exit with unit check status on error condition */ if ((rc = dev->tmh->bsf( dev, unitstat, code )) < 0) break; /* Set normal status */ build_senseX (TAPE_BSENSE_STATUSONLY, dev, unitstat, code); break; } /*---------------------------------------------------------------*/ /* SENSE PATH GROUP ID */ /*---------------------------------------------------------------*/ case 0x34: { /* GA32-0127 IBM 3490E Hardware Reference Sense Path Group ID (X'34') The Sense Path Group ID command transfers 12 bytes of information from the control unit to the channel. The first byte (byte 0) is the path state byte, and the remaining 11 bytes (bytes 1-11) contain the path-group ID. The bit assignments in the path state byte (byte 0) are: ________ ________ ____________________________________ | Bit | Value | Description | |________|________|____________________________________| | 0, 1 | | Pathing Status | |________|________|____________________________________| | | 00 | Reset | |________|________|____________________________________| | | 01 | Reserved | |________|________|____________________________________| | | 10 | Ungrouped | |________|________|____________________________________| | | 11 | Grouped | |________|________|____________________________________| | 2, 3 | | Partitioning State | |________|________|____________________________________| | | 00 | Implicitly Enabled | |________|________|____________________________________| | | 01 | Reserved | |________|________|____________________________________| | | 10 | Disabled | |________|________|____________________________________| | | 11 | Explicitly Enabled | |________|________|____________________________________| | 4 | | Path Mode | |________|________|____________________________________| | | 0 | Single path mode. | | | 1 | Reserved, invalid for this device. | |________|________|____________________________________| | 5-7 | 000 | Reserved | |________|________|____________________________________| */ /* Command Reject if Supervisor-Inhibit */ if (supvr_inhibit) { build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code); break; } /* Command reject if the command is not the ONLY command in the channel program */ if (chained & CCW_FLAGS_CC) { build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code); break; } /* Calculate residual byte count */ RESIDUAL_CALC (12); /* Byte 0 is the path group state byte */ iobuf[0] = dev->pgstat; /* Bytes 1-11 contain the path group identifier */ if (num > 1) memcpy (iobuf+1, dev->pgid, num-1); /* Return unit status */ build_senseX (TAPE_BSENSE_STATUSONLY, dev, unitstat, code); break; } /* End case 0x34: SENSE PATH GROUP ID */ /*---------------------------------------------------------------*/ /* FORWARD SPACE BLOCK */ /*---------------------------------------------------------------*/ case 0x37: { /* Command reject if the volume is currently fenced */ if (dev->fenced) { build_senseX (TAPE_BSENSE_FENCED, dev, unitstat, code); break; } /* Update matrix display if needed */ if ( TAPEDISPTYP_WAITACT == dev->tapedisptype ) { dev->tapedisptype = TAPEDISPTYP_IDLE; UpdateDisplay( dev ); } /* Assign a unique Message Id for this I/O if needed */ INCREMENT_MESSAGEID(dev); /* Forward to next block according to device type */ /* Exit with unit check status if error condition */ if ((rc = dev->tmh->fsb( dev, unitstat, code )) < 0) break; /* Exit with unit exception status if tapemark was sensed */ if (rc == 0) { build_senseX (TAPE_BSENSE_READTM, dev, unitstat, code); break; } /* Set normal status */ build_senseX (TAPE_BSENSE_STATUSONLY, dev, unitstat, code); break; } /*---------------------------------------------------------------*/ /* READ SUBSYSTEM DATA (3490/3590) */ /*---------------------------------------------------------------*/ case 0x3E: { /* GA32-0127 IBM 3490E Hardware Reference Read Subsystem Data (X'3E') The Read Subsystem Data command obtains various types of information from the 3480/3490 subsystem. The data presented is dependent on the command immediately preceding the Read Subsystem Data command in the command chain. If the preceding command in the command chain is a Perform Subsystem Function command with the Prepare for Read Subsystem Data order, the data presented is a function of the sub-order in the data transferred with the order. */ /* Command reject if not chained from either a Set Interface Identifier or Perform Subsystem Function command */ if (!((chained & CCW_FLAGS_CC) && (0x77 == prevcode || 0x73 == prevcode))) { build_senseX(TAPE_BSENSE_BADCOMMAND,dev,unitstat,code); break; } /* Command reject if no subsystem data was prepared by a previous Perform Subsystem Function command */ if (!dev->tapssdlen) // (any subsystem data?) { build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code); break; } /* Calculate residual byte count */ RESIDUAL_CALC (dev->tapssdlen); /* PROGRAMMING NOTE: the Prepare for Read Subsystem Data order of the previous Perform Subsystem Function command has already prepared the subsystem data directly in the channel buffer itself (iobuf), so there isn't any data that actually needs to be moved/copied; the data is already sitting in the channel buffer. All we need do is return a normal status. */ build_senseX (TAPE_BSENSE_STATUSONLY, dev, unitstat, code); break; } /* End case 0x3E: READ SUBSYSTEM DATA */ /*---------------------------------------------------------------*/ /* FORWARD SPACE FILE */ /*---------------------------------------------------------------*/ case 0x3F: { /* Command reject if the volume is currently fenced */ if (dev->fenced) { build_senseX (TAPE_BSENSE_FENCED, dev, unitstat, code); break; } /* Update matrix display if needed */ if ( TAPEDISPTYP_WAITACT == dev->tapedisptype ) { dev->tapedisptype = TAPEDISPTYP_IDLE; UpdateDisplay( dev ); } /* Assign a unique Message Id for this I/O if needed */ INCREMENT_MESSAGEID(dev); /* Forward to next file according to device type */ /* Exit with unit check status if error condition */ if ((rc = dev->tmh->fsf( dev, unitstat, code )) < 0) break; /* Set normal status */ build_senseX (TAPE_BSENSE_STATUSONLY, dev, unitstat, code); break; } /*---------------------------------------------------------------*/ /* SYNCHRONIZE (3480 or later) */ /*---------------------------------------------------------------*/ case 0x43: { /* Command reject if the volume is currently fenced */ if (dev->fenced) { build_senseX (TAPE_BSENSE_FENCED, dev, unitstat, code); break; } /* Update matrix display if needed */ if ( TAPEDISPTYP_WAITACT == dev->tapedisptype ) { dev->tapedisptype = TAPEDISPTYP_IDLE; UpdateDisplay( dev ); } /* Assign a unique Message Id for this I/O if needed */ INCREMENT_MESSAGEID(dev); /* Do the sync */ if ((rc = dev->tmh->sync( dev, unitstat, code )) == 0) build_senseX( TAPE_BSENSE_STATUSONLY, dev, unitstat, code ); break; } #if defined( OPTION_TAPE_AUTOMOUNT ) /*---------------------------------------------------------------*/ /* SET DIAGNOSE -- Special AUTOMOUNT support -- */ /*---------------------------------------------------------------*/ case 0x4B: { int argc, i; /* work */ char **argv; /* work */ char newfile [ sizeof(dev->filename) ]; /* work */ char lcss[8]; /* work */ /* Command reject if AUTOMOUNT support not enabled */ if (0 || dev->tapedevt == TAPEDEVT_SCSITAPE || sysblk.tamdir == NULL || dev->noautomount ) { build_senseX(TAPE_BSENSE_BADCOMMAND,dev,unitstat,code); break; } /* Command Reject if Supervisor-Inhibit */ if (supvr_inhibit) { build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code); break; } /* Command Reject if command-chained and i/o length not 1 */ if (flags & CCW_FLAGS_CC) { if (count != 1) { build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code); break; } /* AUTOMOUNT QUERY - part 1 (chained 0xE4 SENSE ID = part 2) */ /* Set normal status but do nothing else; the next CCW should be a SENSE ID (0xE4) which will do the query */ build_senseX( TAPE_BSENSE_STATUSONLY, dev, unitstat, code ); break; } /* AUTOMOUNT MOUNT... */ /* Calculate residual byte count */ RESIDUAL_CALC (sizeof(newfile)-1); /* (minus-1 for NULL) */ /* Copy the device's new filename from guest storage */ for (i=0; i < num; i++) newfile[i] = guest_to_host( iobuf[i] ); newfile[num] = 0; /* Change "OFFLINE" to "*" (tape unloaded) */ if (strcasecmp (newfile, "OFFLINE") == 0) strlcpy (newfile, TAPE_UNLOADED, sizeof(newfile)); /* (messages looks better without LCSS if not needed) */ lcss[0] = 0; if (SSID_TO_LCSS(dev->ssid) != 0) snprintf( lcss, sizeof(lcss), "%u:", SSID_TO_LCSS(dev->ssid) ); lcss[sizeof(lcss)-1] = 0; /* Obtain the device lock */ obtain_lock (&dev->lock); /* Validate the given path... */ if ( strcmp( newfile, TAPE_UNLOADED ) != 0 ) { TAMDIR *tamdir = NULL; int minlen = 0; int rej = 0; /* (because i hate typing) */ #define HHCTA090E(_file,_reason) \ { \ logmsg(_("HHCTA090E Auto-mount of file \"%s\" on drive %s%4.4X failed: " \ "%s\n"), _file, lcss, dev->devnum, _reason); \ build_senseX (TAPE_BSENSE_TAPELOADFAIL, dev, unitstat, code); \ release_lock (&dev->lock); \ break; \ } // Resolve given path... { char resolve_in [ MAX_PATH ] = {0}; /* (work) */ char resolve_out[ MAX_PATH ] = {0}; /* (work) */ /* (build path to be resolved...) */ if (0 #if defined(_MSVC_) || newfile[1] == ':' /* (fullpath given?) */ #else /* !_MSVC_ */ || newfile[0] == '/' /* (fullpath given?) */ #endif /* _MSVC_ */ || newfile[0] == '.' /* (relative path given?) */ ) resolve_in[0] = 0; /* (then use just given spec) */ else /* (else prepend with default) */ strlcpy( resolve_in, sysblk.defdir, sizeof(resolve_in) ); /* (finish building path to be resolved) */ strlcat( resolve_in, newfile, sizeof(resolve_in) ); /* (fully resolvable path?) */ if (realpath( resolve_in, resolve_out ) == NULL) HHCTA090E( resolve_in, "unresolvable path" ); /* Switch to fully resolved path */ strlcpy( newfile, resolve_out, sizeof(newfile) ); } /* Verify file is in an allowable directory... */ rej = 0; minlen = 0; while ((tamdir = findtamdir( rej, minlen, newfile )) != NULL) { rej = !rej; minlen = tamdir->len; } /* Error if "allowable" directory not found... */ if (!rej) HHCTA090E( newfile, "impermissible directory" ); /* Verify file exists... */ if (access( newfile, R_OK ) != 0) HHCTA090E( newfile, "file not found" ); } /* Prevent accidental re-init'ing of an already loaded tape drive */ if (1 && sysblk.nomountedtapereinit && strcmp (newfile, TAPE_UNLOADED) != 0 && strcmp (dev->filename, TAPE_UNLOADED) != 0 ) { logmsg(_("HHCTA091E Tape file auto-mount for drive %s%4.4X rejected: " "drive not empty\n"), lcss, dev->devnum); build_senseX (TAPE_BSENSE_TAPELOADFAIL, dev, unitstat, code); release_lock (&dev->lock); break; } /* Build re-initialization parameters using new filename */ argc = dev->argc; argv = malloc (dev->argc * sizeof(char*)); for (i=0; i < argc; i++) { if (dev->argv[i]) argv[i] = strdup(dev->argv[i]); else argv[i] = NULL; } /* (replace filename argument with new filename) */ free( argv[0] ); argv[0] = strdup( newfile ); /* Attempt reinitializing the device using the new filename... */ rc = tapedev_init_handler( dev, argc, argv ); /* (free temp copy of parms to prevent memory leak) */ for (i=0; i < argc; i++) if (argv[i]) free(argv[i]); /* Issue message and set status based on whether it worked or not... */ if (0 || rc < 0 || strfilenamecmp( dev->filename, newfile ) != 0 ) { // (failure) if (strcmp( newfile, TAPE_UNLOADED ) == 0) { /* (an error message explaining the reason for the failure should hopefully already have been issued) */ logmsg(_("HHCTA092E Tape file auto-unmount for drive %s%4.4X failed\n"), lcss, dev->devnum); } else HHCTA090E( newfile, "file not found" ); // (presumed) /* (the load or unload attempt failed) */ build_senseX (TAPE_BSENSE_TAPELOADFAIL, dev, unitstat, code); } else { // (success) if (strcmp( newfile, TAPE_UNLOADED ) == 0) logmsg(_("HHCTA093I Tape file on drive %s%4.4X auto-unmounted\n"), lcss, dev->devnum); else logmsg(_("HHCTA094I Tape file \"%s\" auto-mounted onto drive %s%4.4X\n"), dev->filename, lcss, dev->devnum); /* (save new parms for next time) */ free( dev->argv[0] ); dev->argv[0] = strdup( newfile ); /* (set normal status for this ccw) */ build_senseX( TAPE_BSENSE_STATUSONLY, dev, unitstat, code ); } /* Release the device lock and exit function... */ release_lock (&dev->lock); break; } /* End case 0x4B: SET DIAGNOSE */ #endif /* OPTION_TAPE_AUTOMOUNT */ /*---------------------------------------------------------------*/ /* READ MESSAGE ID */ /*---------------------------------------------------------------*/ case 0x4E: { /* GA32-0127 IBM 3490E Hardware Reference Read Message ID (X'4E') The Read Message ID command is used to read the message identifier that was assigned by the control unit to commands that indicated the message-required flag requesting notification when an asynchronous operation is complete. The Read Message ID command must be chained directly from the specific command that requested the message notification or the command will be presented unit check status with associated sense indicating ERA code 27. If the Read Message ID command is chained to a specific command that requests notification, but the command does not result in an asynchronous operation, the message identifier field returned will be all zeroes. The data returned has the following format: ________ ____________________________________________________ | Byte | Description | |________|____________________________________________________| | 0,1 | Length (set to X'000A') | |________|____________________________________________________| | 2 | Format (set to X'02') | |________|____________________________________________________| | 3 | Message Code | | | | | | Value Description | | | | | | X'01' Delayed-Response Message | |________|____________________________________________________| | 4-7 | Message ID | | | | | | This field contains the message identifier | | | assigned by the control unit to the requested | | | operation. If the operation was executed by | | | the subsystem as an immediate operation, this | | | field contains all zeroes and a later delayed- | | | response message is not generated. | |________|____________________________________________________| | 8 | Flags (set to X'00') | |________|____________________________________________________| | 9 | Reserved (set to X'00') | |________|____________________________________________________| */ /* Command reject if not chained from a write command */ if (!((chained & CCW_FLAGS_CC) && IS_CCW_WRITE(prevcode))) { build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code); break; } /* Calculate residual byte count */ RESIDUAL_CALC( 10 ); // PROGRAMMING NOTE: at the moment all of our i/o's are synchronous. // Thus we always return zero indicating the i/o was not asynchronous. STORE_HW ( &iobuf[0], 10 ); // 0-1 iobuf[2] = 0x02; // 2 iobuf[3] = 0x01; // 3 STORE_FW ( &iobuf[4], 0 ); // 4-7 (Message Id) iobuf[8] = 0x00; // 8 iobuf[9] = 0x00; // 9 build_senseX (TAPE_BSENSE_STATUSONLY, dev, unitstat,code); break; } /* End case 0x4E: READ MESSAGE ID */ /*---------------------------------------------------------------*/ /* LOCATE BLOCK */ /*---------------------------------------------------------------*/ case 0x4F: { U32 locblock; /* Block Id for Locate Block */ int errcode = TAPE_BSENSE_STATUSONLY; /* Presumed success */ /* Command reject if the volume is currently fenced */ if (dev->fenced) { build_senseX (TAPE_BSENSE_FENCED, dev, unitstat, code); break; } /* Check for minimum count field */ if (count < sizeof(dev->blockid)) { build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code); break; } /* Block to seek */ ASSERT( count >= sizeof(locblock) ); FETCH_FW(locblock, iobuf); /* Check for invalid/reserved Format Mode bits */ if (0x3590 != dev->devtype) { if (0x00C00000 == (locblock & 0x00C00000)) { build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code); break; } /* We only want the Block Number in the low-order 22 bits */ locblock &= 0x003FFFFF; } /* Calculate residual byte count */ RESIDUAL_CALC( sizeof(locblock) ); /* Informative message if tracing */ if ( dev->ccwtrace || dev->ccwstep ) logmsg(_("HHCTA081I Locate block 0x%8.8"I32_FMT"X on %s%s%4.4X\n") ,locblock ,TAPEDEVT_SCSITAPE == dev->tapedevt ? (char*)dev->filename : "" ,TAPEDEVT_SCSITAPE == dev->tapedevt ? " = " : "" ,dev->devnum ); /* Update display if needed */ if ( TAPEDISPTYP_IDLE == dev->tapedisptype || TAPEDISPTYP_WAITACT == dev->tapedisptype ) { dev->tapedisptype = TAPEDISPTYP_LOCATING; UpdateDisplay( dev ); } /* Assign a unique Message Id for this I/O if needed */ INCREMENT_MESSAGEID(dev); /* Ask media handler to perform the locate... */ if ((rc = dev->tmh->locateblk( dev, locblock, unitstat, code )) < 0) { errcode = TAPE_BSENSE_LOCATEERR; dev->fenced = 1; // (position lost; fence the volume) } /* Update display if needed */ if ( TAPEDISPTYP_LOCATING == dev->tapedisptype ) { dev->tapedisptype = TAPEDISPTYP_IDLE; UpdateDisplay( dev ); } /* Set completion status... */ build_senseX( errcode, dev, unitstat, code ); break; } /* End case 0x4F: LOCATE BLOCK */ /*---------------------------------------------------------------*/ /* SUSPEND MULTIPATH RECONNECTION (3480 and later) */ /*---------------------------------------------------------------*/ case 0x5B: { /* GA32-0127 IBM 3490E Hardware Reference Suspend Multipath Reconnection (X'5B') The Suspend Multipath Reconnection command performs as a No-Operation command because all controlling-computer-to- subsystem operations occur in single-path status. */ /* Command Reject if Supervisor-Inhibit */ if (supvr_inhibit) { build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code); break; } /* Set normal status */ build_senseX (TAPE_BSENSE_STATUSONLY, dev, unitstat, code); break; } /*---------------------------------------------------------------*/ /* READ MEDIA CHARACTERISTICS (3590 only) */ /*---------------------------------------------------------------*/ case 0x62: { /* SG24-2506 IBM 3590 Tape Subsystem Technical Guide 5.2.3 New Read Media Characteristics The new Read Media Characteristics CCW (command code x'62') provides up to 256 bytes of information about the media and formats supported by the Magstar tape drive." */ // ZZ FIXME: not coded yet. /* Set command reject sense byte, and unit check status */ build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code); break; } /*---------------------------------------------------------------*/ /* READ DEVICE CHARACTERISTICS */ /*---------------------------------------------------------------*/ case 0x64: { /* Command reject if device characteristics not available */ if (dev->numdevchar == 0) { build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code); break; } /* Calculate residual byte count */ RESIDUAL_CALC (dev->numdevchar); /* Copy device characteristics bytes to channel buffer */ memcpy (iobuf, dev->devchar, num); /* Return unit status */ build_senseX (TAPE_BSENSE_STATUSONLY, dev, unitstat, code); break; } #if 0 /*---------------------------------------------------------------*/ /* SET INTERFACE IDENTIFIER (3490 and later) */ /*---------------------------------------------------------------*/ case 0x73: { // PROGRAMMING NOTE: the 3480 and earlier "Mode Set" interpretation // of this CCW is handled in the command-table as a no-op; the "Set // Interface Identifier" interpretation of this CCW for 3490 and // later model tape drives is *ALSO* handled in the command-table // as a no-op as well, so there's really no reason for this switch // case to even exist until such time as we need to support a model // that happens to require special handling (which is unlikely). // I'm keeping the code here however for documentation purposes // only, but of course disabling it from compilation via #if 0. build_senseX (TAPE_BSENSE_STATUSONLY, dev, unitstat, code); break; } #endif /*---------------------------------------------------------------*/ /* PERFORM SUBSYSTEM FUNCTION */ /*---------------------------------------------------------------*/ case 0x77: { BYTE order = iobuf[0]; BYTE flag = iobuf[1]; BYTE parm = iobuf[2]; /* Command Reject if Supervisor-Inhibit */ if (supvr_inhibit) { build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code); break; } /* The flag byte must be zero for all orders because none of our supported orders supports a flag byte */ if (PSF_FLAG_ZERO != flag) { build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code); break; } /* Byte 0 is the PSF order */ switch (order) { /*-----------------------------------------------------------*/ /* Activate/Deactivate Forced Error Logging */ /* 0x8000nn / 0x8100nn */ /*-----------------------------------------------------------*/ case PSF_ORDER_AFEL: case PSF_ORDER_DFEL: { BYTE bEnable = (PSF_ORDER_AFEL == order) ? 1 : 0; /* Calculate residual byte count */ RESIDUAL_CALC (3); /* Control information length must be 3 bytes long */ /* and the parameter byte must be one or the other */ if ( (count < len) || ((PSF_ACTION_FEL_IMPLICIT != parm) && (PSF_ACTION_FEL_EXPLICIT != parm)) ) { build_senseX(TAPE_BSENSE_BADCOMMAND,dev,unitstat,code); break; } /* Enable/Disabled Forced Error Logging as requested... */ #if 0 // (implicit enabling for all devices not currently supported; treat as explicit instead) if (PSF_ACTION_FEL_IMPLICIT == parm) { // Implicit: for ALL devices... dev->forced_logging = bEnable ? 1 : 0; } else // (PSF_ACTION_FEL_EXPLICIT == parm) #endif // (implicit not supported) { // Explicit: for only THIS device... dev->forced_logging = bEnable ? 1 : 0; } build_senseX(TAPE_BSENSE_STATUSONLY,dev,unitstat,code); break; } /*-----------------------------------------------------------*/ /* Activate/Deactivate Access Control */ /* 0x8200nn00 / 0x8300nn00 */ /*-----------------------------------------------------------*/ case PSF_ORDER_AAC: // (Activate) case PSF_ORDER_DAC: // (Dectivate) { BYTE bEnable = (PSF_ORDER_AAC == order) ? 1 : 0; /* Calculate residual byte count */ RESIDUAL_CALC (4); /* Control information length must be 4 bytes long */ /* and the parameter byte must not be invalid */ if (0 || (count < len) || (parm & ~(PSF_ACTION_AC_LWP | PSF_ACTION_AC_DCD | // (bits on that shouldn't be) PSF_ACTION_AC_DCR | PSF_ACTION_AC_ER)) || !(parm & (PSF_ACTION_AC_LWP | PSF_ACTION_AC_DCD | // (bits on that should be) PSF_ACTION_AC_DCR | PSF_ACTION_AC_ER)) ) { build_senseX(TAPE_BSENSE_BADCOMMAND,dev,unitstat,code); break; } /* Enable/Disable Logical Write Protect if requested */ if (parm & PSF_ACTION_AC_LWP) dev->tdparms.logical_readonly = bEnable ? 1 : 0; /* Enable/Disable Data Compaction (compression) if requested */ if (parm & PSF_ACTION_AC_DCD) { if (TAPEDEVT_HETTAPE == dev->tapedevt) { rc = het_cntl( dev->hetb, HETCNTL_SET | HETCNTL_COMPRESS, bEnable ? TRUE : FALSE ); } #if defined(OPTION_SCSI_TAPE) else if (TAPEDEVT_SCSITAPE == dev->tapedevt) { // ZZ FIXME: future place for direct SCSI i/o // to enable/disable compression for 3480/later. } #endif } build_senseX(TAPE_BSENSE_STATUSONLY,dev,unitstat,code); break; } /*-----------------------------------------------------------*/ /* Reset Volume Fenced */ /* 0x9000 */ /*-----------------------------------------------------------*/ case PSF_ORDER_RVF: { /* GA32-0127 IBM 3490E Hardware Reference Volume Fencing When a condition results in a volume integrity exposure, the control unit will prevent further access to the volume. This process is called Volume Fencing and is primarily related to loss of buffered write data, tape positioning, or assignment protection. The control unit prevents further access to the tape volume by conditioning itself to generate deferred unit checks with associated sense data indicating ERA code 47, for all commands that are eligible to receive the deferred unit check until the condition is reset or until the cartridge is unloaded. The condition that caused the fencing to occur has already been indicated by the previous unit check and associated sense data. */ /* Calculate residual byte count */ RESIDUAL_CALC (2); /* Control information length must be 2 bytes long */ if (count < len) { build_senseX(TAPE_BSENSE_BADCOMMAND,dev,unitstat,code); break; } dev->fenced = 0; // (as requested!) build_senseX(TAPE_BSENSE_STATUSONLY,dev,unitstat,code); break; } /*-----------------------------------------------------------*/ /* Pin Device */ /* 0xA100nn */ /*-----------------------------------------------------------*/ case PSF_ORDER_PIN_DEV: { /* Calculate residual byte count */ RESIDUAL_CALC (3); /* Control information length must be 3 bytes long and the parameter byte must not be invalid */ if ( (count < len) || ((parm != PSF_ACTION_PIN_CU0) && (parm != PSF_ACTION_PIN_CU1)) ) { build_senseX(TAPE_BSENSE_BADCOMMAND,dev,unitstat,code); break; } /* Not currently supported; treat as no-op */ build_senseX(TAPE_BSENSE_STATUSONLY,dev,unitstat,code); break; } /*-----------------------------------------------------------*/ /* Unpin Device */ /* 0xA200 */ /*-----------------------------------------------------------*/ case PSF_ORDER_UNPIN_DEV: { /* Calculate residual byte count */ RESIDUAL_CALC (2); /* Control information length must be 2 bytes long */ if (count < len) { build_senseX(TAPE_BSENSE_BADCOMMAND,dev,unitstat,code); break; } /* Not currently supported; treat as no-op */ build_senseX(TAPE_BSENSE_STATUSONLY,dev,unitstat,code); break; } /*-----------------------------------------------------------*/ /* Prepare for Read Subsystem Data */ /* 0x180000000000mm00iiiiiiii */ /*-----------------------------------------------------------*/ case PSF_ORDER_PRSD: { /* GA32-0127 IBM 3490E Hardware Reference Prepare for Read Subsystem Data (X'18') The order transfers 12 bytes of data used for processing a Read Subsystem Data command that immediately follows the Perform Subsystem Function command specifying this order in the command chain. If a Read Subsystem Data command is not issued as the next command in the command chain, the data is discarded and no other action is performed. If a Read Subsystem Data command is issued as the next command in the command chain, the data determines what type of information is presented to the Read Subsystem Data command. When the Prepare for Subsystem Data order with the attention message sub-order is specified in a Perform Subsystem Function command, the command is treated as a global command. If the command is issued while the Special Intercept Condition is active, a unit check status is presented with the associated sense data indicating ERA code 53. The Prepare for Read Subsystem Data order requires an order byte (byte 0), a flag byte (byte 1), and parameter bytes. The flag byte is set to 0. The parameter bytes are defined as follows: ________ ___________________________________________________ | Byte | Description | |________|___________________________________________________| | 2-5 | Reserved (X'00') | |________|___________________________________________________| | 6 | Attention Message (X'03') | | | | | | When active and bytes 8-11 contain X'00000000', | | | the program is requesting the control unit | | | to present any pending attention message or | | | unsolicited unit check condition that is | | | associated with the addressed device-path pair. | | | If there is no message or unit check condition | | | present, the subsystem displays the "No Message" | | | message. | | | | | | When active and bytes 8-11 contain anything | | | other than X'00000000', the program is re- | | | questing the control unit to present the status | | | of the asynchronous operation as identified by | | | the contents of bytes 8-11. | |________|___________________________________________________| | 7 | Reserved (X'00') | |________|___________________________________________________| | 8-11 | Message ID | |________|___________________________________________________| */ /* Calculate residual byte count */ RESIDUAL_CALC (12); /* Control information length must be 12 bytes long the */ /* parameter must be valid and all reserved bytes zero. */ /* Also note that the only sub-order we support is the */ /* only sub-order that is defined: attention message. */ if (0 || (count < len) || (iobuf[6] != PSF_ACTION_SSD_ATNMSG) || (memcmp( &iobuf[2], "\00\00\00\00", 4 ) != 0) || (iobuf[7] != 0x00) ) { build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code); break; } /* If the Special Intercept Condition is active, present unit check status with sense indicating ERA code 53 */ if (dev->SIC_active) { build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code); dev->SIC_active = 0; break; } // Build the requested Subsystem Data... // PROGRAMMING NOTE: note that we build the requested data // directly in the channel i/o buffer itself (iobuf). This // relieves us from having to allocate/maintain a separate // buffer for it somewhere, and relieves the READ SUBSYSTEM // DATA command (0x3E) from having to copy the data into // the channel buffer from somewhere. Instead it can return // immediately since the data is already in the buffer. (See // the 0x3E: READ SUBSYSTEM DATA command for information). // PROGRAMMING NOTE: since at the moment we don't support // asynchronous i/o (all of our i/o's are synchronous), we // return either a Format x'00' (No Message) response if the // Message Id they specified was x'00000000' or, if they // requested the status for a specific Message Id, a format // x'02' (Message Id Status) response with x'00' Operation // Completion Status (I/O Completed). if (memcmp( &iobuf[8], "\00\00\00\00", 4 ) == 0) { /* Format x'00': "No Message" */ dev->tapssdlen = 9; // (Length) STORE_HW ( &iobuf[0], dev->tapssdlen ); // (Length = 9 bytes) iobuf[2] = 0x00; // (Format = x'00': "No Message") iobuf[3] = 0x00; // (Message Code = none) memcpy( &iobuf[4], &iobuf[8], 4 ); // (Message Id = same as requested) iobuf[8] = 0x00; // (Flags = none) } else { /* Format x'02': "Message Id Status" */ dev->tapssdlen = 10; // (Length) STORE_HW ( &iobuf[0], dev->tapssdlen ); // (Length = 10 bytes) iobuf[2] = 0x02; // (Format = x'01: Message Id Status) iobuf[3] = 0x01; // (Message Code = Delayed Response) memcpy( &iobuf[4], &iobuf[8], 4 ); // (Message Id = same as requested) iobuf[8] = 0x00; // (Reserved) iobuf[9] = 0x00; // (Status = "I/O Completed") } break; } /* End case PSF_ORDER_PRSD */ /*-----------------------------------------------------------*/ /* Set Special Intercept Condition */ /* 0x1B00 */ /*-----------------------------------------------------------*/ case PSF_ORDER_SSIC: { /* GA32-0127 IBM 3490E Hardware Reference Set Special Intercept Condition (X'1B') The order controls the activation or deactivation of the special intercept condition associated with the device-path group pair to which the command is issued. The order is supported by the model if byte 8 bit 4 is active in the data presented to the Read Device Characteristics command. The order requires an order byte (byte 0) and a flag byte (byte 1). The flag byte is set to 0. When processed, the command activates the special intercept condition for the device on each channel path that has the same path group ID as the issuing channel path. The path group ID is considered valid on a given channel path if it is valid for any device on the channel path. The special intercept condition controls the presentation of attention- intercept status. The sense data associated with the attention-intercept status indicates ERA code 57. The special intercept condition also causes the next global command issued to the device-path group pair to be presented unit check status with associated sense data indicating ERA code 53. The special intercept condition is deactivated on a channel path if a reset signal is received on the channel path. The special intercept condition is deactivated for the device-group pair if a global command is presented unit check status with associated sense data indicating ERA code 53, or if the last path in the associated set of channel paths (that is, with the same valid path group ID) is reset. After the Set Special Intercept Condition order is specified in a Perform Subsystem Function command, the command is treated as a global command. If the command is issued while the special intercept condition is active, a unit check status is presented with associated sense data indicating ERA code 53. If a command is issued to a channel path without a valid path group ID (that is, all devices in the reset state), unit check status is presented with associated sense data indicating ERA code 27. */ /* Command reject if Special Intercept Condition not supported */ if (!dev->SIC_supported) // (not supported?) { build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code); break; } /* If the command is issued while the Special Intercept */ /* Condition is active, a unit check status is presented */ /* with associated sense data indicating ERA code 53. */ if (dev->SIC_active) // (already active?) { build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code); dev->SIC_active = 0; // (reset after UC) break; } /* Activate Special Intercept Condition */ dev->SIC_active = 1; break; } /* End case PSF_ORDER_SSIC */ /*-----------------------------------------------------------*/ /* Message Not Supported */ /* 0x1C00xxccnnnn0000iiiiii... */ /*-----------------------------------------------------------*/ case PSF_ORDER_MNS: { /* GA32-0127 IBM 3490E Hardware Reference Message Not Supported (X'1C') The order transfers 20 bytes of data that identify the host that does not support a prior attention message containing the Notify Nonsupport flag. The order requires an order byte (byte 0), a flag byte (byte 1), and parameter bytes. The flag byte is set to 0. The parameter bytes are defined as follows: ________ ________ ____________________________________________ | Byte | Value | Description | |________|________|____________________________________________| | 2 | | Response Code | |________|________|____________________________________________| | | 0 | Reserved (invalid). | |________|________|____________________________________________| | | 1 | Message rejected. Unknown format. | |________|________|____________________________________________| | | 2 | Message rejected. Function not supported. | |________|________|____________________________________________| | | 3-255 | Reserved (invalid). | |________|________|____________________________________________| | 3 | | Channel Path ID (CHPID) | | | | | | | | The byte identifies the channel path that | | | | received the attention message. | |________|________|____________________________________________| | 4, 5 | | Device Number | | | | | | | | The bytes identify the device number of | | | | the device that received the attention | | | | message. | |________|________|____________________________________________| | 6, 7 | | Reserved (must be X'00'). | |________|________|____________________________________________| | 8-11 | | Message ID | | | | | | | | The field contains the message ID that | | | | was presented to the host in the attention | | | | message. | |________|________|____________________________________________| | 12-19 | | System ID | | | | | | | | The field contains an 8-byte system ID | | | | that identifies the host or host partition | | | | responding to the attention message. | |________|________|____________________________________________| */ // PROGRAMMING NOTE: none of our responses to the Perform Sub- // System Function order Attention Message sub-order (see the // PSF_ORDER_PRSD case further above) support any flags. Thus // because we never set/request the "Notify Nonsupport" flag // in our Attention Message sub-order response, the host should // never actually ever be issuing this particular order of the // Perform Subsystem Functon command since it shouldn't be // trying to tell us what we never asked it to. Nevertheless // we should probably support it anyway just in case it does // by treating it as a no-op (as long as it's valid of course). /* Check for valid data (Note: we don't bother validating the Channel Path ID, Device Number, Message ID or System ID) */ if (0 // || flag != 0x00 // (flag byte) (note: already checked) || (parm != 0x01 && parm != 0x02) // (response code) || iobuf[6] != 0x00 // (reserved) || iobuf[7] != 0x00 // (reserved) ) { build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code); break; } /* Calculate residual byte count */ RESIDUAL_CALC (20); /* Treat as No-op */ build_senseX (TAPE_BSENSE_STATUSONLY, dev, unitstat, code); break; } /* End case PSF_ORDER_MNS */ /*-----------------------------------------------------------*/ /* Unknown/Supported PSF order */ /*-----------------------------------------------------------*/ default: { build_senseX(TAPE_BSENSE_BADCOMMAND,dev,unitstat,code); break; } } /* End PSF switch (order) */ break; } /* End case 0x77: PERFORM SUBSYSTEM FUNCTION */ /*---------------------------------------------------------------*/ /* DATA SECURITY ERASE */ /*---------------------------------------------------------------*/ case 0x97: { /* GA32-0127 IBM 3490E Hardware Reference Data Security Erase (X'97') The Data Security Erase command writes a random pattern from the position of the tape where the command is issued to the physical end of tape. The Data Security Erase command must be command-chained from an Erase Gap command. Most operating systems signal that the channel program is complete when the channel ending status is returned for the final command in the chain. If the Data Security Erase command is the last command in a channel program, another command should be chained after the Data Security Erase command. (The No-Operation command is appropriate.) This practice ensures that any error status returns with device ending status after the Data Security Erase command is completed. */ /* Command reject if not chained from Erase Gap command */ if (!((chained & CCW_FLAGS_CC) && 0x17 == prevcode)) { build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code); break; } /* Command reject if the volume is currently fenced */ if (dev->fenced) { build_senseX (TAPE_BSENSE_FENCED, dev, unitstat, code); break; } /* Command reject if tape is write-protected */ if (dev->readonly || dev->tdparms.logical_readonly) { build_senseX (TAPE_BSENSE_WRITEPROTECT, dev, unitstat, code); break; } /* Update matrix display if needed */ if ( TAPEDISPTYP_IDLE == dev->tapedisptype || TAPEDISPTYP_WAITACT == dev->tapedisptype ) { dev->tapedisptype = TAPEDISPTYP_ERASING; UpdateDisplay( dev ); } /* Assign a unique Message Id for this I/O if needed */ INCREMENT_MESSAGEID(dev); /* Do the DSE; exit if error */ if ((rc = dev->tmh->dse( dev, unitstat, code )) < 0) break; // (error) /* Update matrix display if needed */ if ( TAPEDISPTYP_ERASING == dev->tapedisptype ) { dev->tapedisptype = TAPEDISPTYP_IDLE; UpdateDisplay( dev ); } /* Perform flush/sync and/or set normal completion status */ if (0 || !write_immed || (rc = dev->tmh->sync( dev, unitstat, code )) == 0 ) build_senseX( TAPE_BSENSE_STATUSONLY, dev, unitstat, code ); break; } /* End case 0x97: DATA SECURITY ERASE */ /*---------------------------------------------------------------*/ /* LOAD DISPLAY */ /*---------------------------------------------------------------*/ case 0x9F: { /* Command Reject if Supervisor-Inhibit */ if (supvr_inhibit) { build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code); break; } /* Calculate residual byte count */ RESIDUAL_CALC (17); /* Issue message on 3480 matrix display */ load_display (dev, iobuf, count); /* Return unit status */ build_senseX (TAPE_BSENSE_STATUSONLY, dev, unitstat, code); break; } /*---------------------------------------------------------------*/ /* Read and Reset Buffered Log (9347) */ /*---------------------------------------------------------------*/ case 0xA4: { /* Calculate residual byte count */ RESIDUAL_CALC (dev->numsense); /* Reset SENSE Data */ memset (dev->sense, 0, sizeof(dev->sense)); *unitstat = CSW_CE|CSW_DE; /* Copy device Buffered log data (Bunch of 0s for now) */ memcpy (iobuf, dev->sense, num); /* Indicate Contengency Allegiance has been cleared */ dev->sns_pending = 0; break; } /*---------------------------------------------------------------*/ /* SET PATH GROUP ID */ /*---------------------------------------------------------------*/ case 0xAF: { /* GA32-0127 IBM 3490E Hardware Reference Set Path Group ID (X'AF') The Set Path Group ID command identifies a controlling computer and specific channel path to the addressed control unit and tape drive. The Set Path Group ID command transfers 12 bytes of path group ID information to the subsystem. The first byte (byte 0) is a function control byte, and the remaining 11 bytes (bytes 1-11) contain the path-group ID. The bit assignments in the function control byte (byte 0) are: ________ ________ ___________________________________________ | Bit | Value | Description | |________|________|___________________________________________| | 0 | | Path Mode | |________|________|___________________________________________| | | 0 | Single-path Mode | |________|________|___________________________________________| | | 1 | Multipath Mode (not supported by Models | | | | C10, C11, and C22) | |________|________|___________________________________________| | 1, 2 | | Group Code | |________|________|___________________________________________| | | 00 | Establish Group | |________|________|___________________________________________| | | 01 | Disband Group | |________|________|___________________________________________| | | 10 | Resign from Group | |________|________|___________________________________________| | | 11 | Reserved | |________|________|___________________________________________| | 3-7 | 00000 | Reserved | |________|________|___________________________________________| The final 11 bytes of the Set Path Group ID command identify the path group ID. The path group ID identifies the channel paths that belong to the same controlling computer. Path group ID bytes must be the same for all devices in a control unit on a given path. The Path Group ID bytes cannot be all zeroes. */ /* Command Reject if Supervisor-Inhibit */ if (supvr_inhibit) { build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code); break; } /* Command reject if the command is not the ONLY command in the channel program */ if (chained & CCW_FLAGS_CC) { build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code); break; } /* Calculate residual byte count */ RESIDUAL_CALC (12); /* Control information length must be at least 12 bytes */ if (count < 12) { build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code); break; } /* Byte 0 is the path group state byte */ switch((iobuf[0] & SPG_SET_COMMAND)) { case SPG_SET_ESTABLISH: /* Only accept the new pathgroup id when 1) it has not yet been set (ie contains zeros) or 2) It is set, but we are setting the same value */ if(memcmp(dev->pgid, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 11) && memcmp(dev->pgid, iobuf+1, 11)) { build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code); break; } /* Bytes 1-11 contain the path group identifier */ memcpy (dev->pgid, iobuf+1, 11); // (set initial value) dev->pgstat = SPG_PATHSTAT_GROUPED | SPG_PARTSTAT_IENABLED; build_senseX (TAPE_BSENSE_STATUSONLY, dev, unitstat, code); break; case SPG_SET_DISBAND: dev->pgstat = 0; build_senseX (TAPE_BSENSE_STATUSONLY, dev, unitstat, code); break; default: case SPG_SET_RESIGN: dev->pgstat = 0; memset (dev->pgid, 0, 11); // (reset to zero) build_senseX (TAPE_BSENSE_STATUSONLY, dev, unitstat, code); break; } // end switch((iobuf[0] & SPG_SET_COMMAND)) break; } /* End case 0xAF: SET PATH GROUP ID */ /*---------------------------------------------------------------*/ /* ASSIGN */ /*---------------------------------------------------------------*/ case 0xB7: { /* Command Reject if Supervisor-Inhibit */ if (supvr_inhibit) { build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code); break; } /* Calculate residual byte count */ RESIDUAL_CALC (11); /* Control information length must be at least 11 bytes */ if (count < len) { build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code); break; } if((memcmp(iobuf,"\00\00\00\00\00\00\00\00\00\00",11)==0) || (memcmp(iobuf,dev->pgid,11)==0)) { dev->pgstat |= SPG_PARTSTAT_XENABLED; /* Set Explicit Partition Enabled */ } else { build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code); break; } /* Return unit status */ build_senseX (TAPE_BSENSE_STATUSONLY, dev, unitstat, code); break; } /*---------------------------------------------------------------*/ /* MEDIUM SENSE (3590) */ /*---------------------------------------------------------------*/ case 0xC2: { /* GA32-0331 IBM 3590 Hardware Reference The 3590 Hardware Reference manual lists many different "Mode Sense" Pages that the 3590 supports, with one of the supported pages being Mode Page X'23': the "Medium Sense" mode page: The Medium Sense page provides information about the state of the medium currently associated with the device, if any. */ #if 0 // ZZ FIXME: not coded yet // PROGRAMMING NOTE: until we can add support to Hercules // allowing direct SCSI i/o (so that we can issue the 10-byte // Mode Sense (X'5A') command to ask for Mode Page x'23' = // Medium Sense) we have no choice but to reject the command. // ZZ FIXME: not written yet. build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code); #else // ++++ BEGIN MEDIUM SENSE HACK ++++ /* ZZ FIXME: *** TEMPORARY(?) HACK *** The following clues were gleaned from Linux 390 source: struct tape_3590_med_sense { unsigned int macst:4; unsigned int masst:4; char pad[127]; } #define MSENSE_UNASSOCIATED 0x00 #define MSENSE_ASSOCIATED_MOUNT 0x01 #define MSENSE_ASSOCIATED_UMOUNT 0x02 case TO_MSEN: sense = (struct tape_3590_med_sense *) request->cpdata; if (sense->masst == MSENSE_UNASSOCIATED) tape_med_state_set(device, MS_UNLOADED); if (sense->masst == MSENSE_ASSOCIATED_MOUNT) tape_med_state_set(device, MS_LOADED); break; */ /* Calculate residual byte count */ RESIDUAL_CALC (128); /* Return Media Sense data... */ memset( iobuf, 0, num ); // (init to all zeroes first) if (dev->tmh->tapeloaded( dev, unitstat, code )) iobuf[0] |= (0x01 & 0x0F); // MSENSE_ASSOCIATED_MOUNT // else // iobuf[0] |= (0x00 & 0x0F); // MSENSE_UNASSOCIATED /* Return unit status */ build_senseX (TAPE_BSENSE_STATUSONLY, dev, unitstat, code); #endif // ++++ END MEDIUM SENSE HACK ++++ break; } /* End case 0xC2: MEDIUM SENSE */ /*---------------------------------------------------------------*/ /* SET TAPE-WRITE IMMEDIATE (3480 and later) */ /*---------------------------------------------------------------*/ case 0xC3: { // NOTE: the "Mode Set" interpretation of this CCW for all // models earlier than 3480 are handled by the command-table; // the "Set Tape-Write Immediate" interpretation of this CCW // for 3480 and later models is handled below. /* Command reject if the volume is currently fenced */ if (dev->fenced) { build_senseX (TAPE_BSENSE_FENCED, dev, unitstat, code); break; } /* GA32-0127 IBM 3490E Hardware Reference Set Tape-Write-Immediate (X'C3') The Set Tape-Write-Immediate command causes all subsequent Write commands in the channel program to perform as write- immediate commands. The tape-write-immediate command is explicitly requested by a Mode Set or Set Tape-Write-Immediate command. The subsystem forces the tape-write-immediate command while the tape is positioned beyond logical end of volume. This prevents more than one record from being in the buffer if the physical end of volume is reached. It may also be forced when load balancing is performed or on drives that write the 3480-2 XF format just before end of wrap processing. */ /* GA32-0329 3590 Introduction and Planning Guide When data is physically transferred to the tape medium it is always immediately reread and verified. The writing of data is normally buffered, however, which defers the physical transfer of the logical blocks to the tape until the buffer conditions require the offloading of the data or until a synchronizing command requires the transfer. If immediate validation of a successful transfer of data to the tape is required at the time that each logical block is written, then Tape Write Immediate mode may be programmatically invoked. This results in block-by-block synchronization and verification of successful transfer all the way to the medium, but at a very substantial cost in application performance. */ /* Assign a unique Message Id for this I/O if needed */ INCREMENT_MESSAGEID(dev); /* set write-immedediate mode and perform sync function */ write_immed = 1; if ((rc = dev->tmh->sync( dev, unitstat, code )) == 0) build_senseX( TAPE_BSENSE_STATUSONLY, dev, unitstat, code ); break; } /* End case 0xC3: SET TAPE-WRITE IMMEDIATE */ /*---------------------------------------------------------------*/ /* UNASSIGN */ /*---------------------------------------------------------------*/ case 0xC7: { /* Command Reject if Supervisor-Inhibit */ if (supvr_inhibit) { build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code); break; } /* Calculate residual byte count */ RESIDUAL_CALC (11); /* Control information length must be at least 11 bytes */ if (count < len) { build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code); break; } /* Reset to All Implicitly enabled */ dev->pgstat=0; /* Reset Path group ID password */ memset(dev->pgid,0,11); /* Reset drive password */ memset(dev->drvpwd,0,sizeof(dev->drvpwd)); /* Return unit status */ build_senseX (TAPE_BSENSE_STATUSONLY, dev, unitstat, code); break; } /*---------------------------------------------------------------*/ /* MODE SENSE (3590) */ /*---------------------------------------------------------------*/ case 0xCF: { /* ANSI INCITS 131-1994 (R1999) SCSI-2 Reference The MODE SENSE command provides a means for a target to report parameters to the initiator. It is a complementary command to the MODE SELECT command. */ /* GA32-0331 IBM 3590 Hardware Reference The 3590 Hardware Reference manual lists many different "Mode Sense" Pages that the 3590 supports. */ // ZZ FIXME: not written yet. /* Set command reject sense byte, and unit check status */ build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code); break; } /*---------------------------------------------------------------*/ /* MODE SET (3480 or later) */ /*---------------------------------------------------------------*/ case 0xDB: { /* GA32-0127 IBM 3490E Hardware Reference Mode Set (X'DB') The Mode Set command controls specific aspects of command processing within a given command chain. The Mode Set command requires one byte of information from the channel. The format of the byte is: ________ __________________________________________________________ | Bit | Description | |________|__________________________________________________________| | 0,1 | Reserved | |________|__________________________________________________________| | 2 | Tape-Write-Immediate Mode | | | | | | If active, any subsequent Write commands within the | | | current command chain are processed in tape-write- | | | immediate mode if no other conditions preclude this | | | mode. If inactive, Write commands are processed in | | | buffered mode if no other conditions preclude this | | | mode. The default is inactivate. | |________|__________________________________________________________| | 3 | Supervisor Inhibit | | | | | | If active, any subsequent supervisor command within | | | the current command chain is presented unit check | | | status with associated sense data indicating ERA code | | | 27. The supervisor inhibit control also determines | | | if pending buffered log data is reset when a Read | | | Buffered Log command is issued. The default is | | | inactivate. | |________|__________________________________________________________| | 4 | Improved Data Recording Capability (IDRC) | | | | | | If active, IDRC is invoked for any subsequent Write | | | commands within the current command chain. See Table | | | 7 in topic 1.16.6 for the default settings. | |________|__________________________________________________________| | 5-7 | Reserved | |________|__________________________________________________________| The Mode Set command is a supervisor command and cannot be performed if preceded by a Mode Set command that inhibits supervisor commands. */ /* Command reject if the volume is currently fenced */ if (dev->fenced) { build_senseX (TAPE_BSENSE_FENCED, dev, unitstat, code); break; } /* Calculate residual byte count */ RESIDUAL_CALC (1); /* Check for count field of at least 1 byte, and that supvr-inhibit mode hasn't already been established */ if (0 || count < len || supvr_inhibit ) { build_senseX(TAPE_BSENSE_BADCOMMAND,dev,unitstat,code); break; } /* Assign a unique Message Id for this I/O if needed */ INCREMENT_MESSAGEID(dev); /* Process request */ if (iobuf[0] & MSET_SUPVR_INHIBIT) supvr_inhibit = 1; /* set supvr-inhibit mode*/ if (iobuf[0] & MSET_WRITE_IMMED) write_immed = 1; /* set write-immed. mode */ build_senseX(TAPE_BSENSE_STATUSONLY,dev,unitstat,code); break; } /* End case 0xDB: MODE SET */ /*---------------------------------------------------------------*/ /* CONTROL ACCESS */ /*---------------------------------------------------------------*/ case 0xE3: { /* GA32-0127 IBM 3490E Hardware Reference Control Access (X'E3') The Control Access command is used to perform the set-password, conditional-enable, and conditional-disable functions of dynamic partitioning. The command requires 12 bytes of data to be transferred from the channel to the control unit which is defined as follows: ________ ________ ___________________________________________ | Byte | Bit | Description | |________|________|___________________________________________| | 0 | | Function Control | |________|________|___________________________________________| | | 0,1 | 0 (x'00') Set Password | | | | 1 (x'40') Conditional Disable | | | | 2 (x'80') Conditional Enable | | | | 3 (x'C0') Reserved (Invalid) | |________|________|___________________________________________| | | 2-7 | Reserved (must be B'0') | |________|________|___________________________________________| | 1-11 | | Password | |________|________|___________________________________________| */ /* Command Reject if Supervisor-Inhibit */ if (supvr_inhibit) { build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code); break; } /* Calculate residual byte count */ RESIDUAL_CALC (12); /* Control information length must be at least 12 bytes */ if (count < len) { build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code); break; } /* Byte 0 is the CAC mode-of-use */ switch (iobuf[0]) { /*-----------------------------------------------------------*/ /* Set Password */ /* 0x00nnnnnnnnnnnnnnnnnnnnnn */ /*-----------------------------------------------------------*/ case CAC_SET_PASSWORD: { /* Password must not be zero and the device path must be Explicitly Enabled */ if (0 || memcmp( iobuf+1, "\00\00\00\00\00\00\00\00\00\00\00", 11 ) == 0 || (dev->pgstat & SPG_PARTSTAT_XENABLED) == 0 ) { build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code); break; } /* Set Password if none set yet */ if (memcmp( dev->drvpwd, "\00\00\00\00\00\00\00\00\00\00\00", 11 ) == 0) { memcpy (dev->drvpwd, iobuf+1, 11); } else /* Password already set - they must match */ { if (memcmp( dev->drvpwd, iobuf+1, 11 ) != 0) { build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code); break; } } build_senseX (TAPE_BSENSE_STATUSONLY, dev, unitstat, code); break; } /*-----------------------------------------------------------*/ /* Conditional Enable */ /* 0x80nnnnnnnnnnnnnnnnnnnnnn */ /*-----------------------------------------------------------*/ case CAC_COND_ENABLE: { /* A drive password must be set and it must match the one given as input */ if (0 || memcmp( dev->drvpwd, "\00\00\00\00\00\00\00\00\00\00\00", 11 ) == 0 || memcmp( dev->drvpwd, iobuf+1, 11 ) != 0 ) { build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code); break; } build_senseX (TAPE_BSENSE_STATUSONLY, dev, unitstat, code); break; } /*-----------------------------------------------------------*/ /* Conditional Disable */ /* 0x40nnnnnnnnnnnnnnnnnnnnnn */ /*-----------------------------------------------------------*/ case CAC_COND_DISABLE: { /* A drive password is set, it must match the one given as input */ if (1 && memcmp (dev->drvpwd, "\00\00\00\00\00\00\00\00\00\00\00", 11) != 0 && memcmp (dev->drvpwd, iobuf+1, 11) != 0 ) { build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code); break; } build_senseX (TAPE_BSENSE_STATUSONLY, dev, unitstat, code); break; } default: /* Unsupported Control Access Function */ { build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code); break; } } /* End switch (iobuf[0]) */ break; } /* End case 0xE3 CONTROL ACCESS */ /*---------------------------------------------------------------*/ /* SENSE ID (3422 and later) */ /*---------------------------------------------------------------*/ case 0xE4: { #if defined( OPTION_TAPE_AUTOMOUNT ) /* AUTOMOUNT QUERY - part 2 (if command-chained from prior 0x4B) */ if (1 && dev->tapedevt != TAPEDEVT_SCSITAPE && sysblk.tamdir != NULL && !dev->noautomount && (chained & CCW_FLAGS_CC) && 0x4B == prevcode ) { int i; // (work) /* Calculate residual byte count */ RESIDUAL_CALC (strlen(dev->filename)); /* Copy device filename to guest storage */ for (i=0; i < num; i++) iobuf[i] = host_to_guest( dev->filename[i] ); /* Return normal status */ build_senseX (TAPE_BSENSE_STATUSONLY, dev, unitstat, code); break; } #endif /* OPTION_TAPE_AUTOMOUNT */ /* SENSE ID did not exist on the 3803 */ /* If numdevid is 0, then 0xE4 not supported */ if (dev->numdevid==0) { build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code); break; } /* Calculate residual byte count */ RESIDUAL_CALC (dev->numdevid); /* Copy device identifier bytes to channel I/O buffer */ memcpy (iobuf, dev->devid, num); /* Return unit status */ build_senseX (TAPE_BSENSE_STATUSONLY, dev, unitstat, code); break; } /*---------------------------------------------------------------*/ /* READ CONFIGURATION DATA (3490 and later) */ /*---------------------------------------------------------------*/ case 0xFA: { /* GA32-0127 IBM 3490E Hardware Reference Read Configuration Data (X'FA') A Read Configuration Data command causes 160 bytes of data to be transferred from the control unit to the channel. The data transferred by this command is referred to as a configuration record and is associated with the addressed device-path pair. The configuration record from each device-path pair provides the host with identifiers of node elements internal to the subsystem. */ static const BYTE cfgdata[] = // (prototype data) { // ---------------- Device NED --------------------------------------------------- 0xCC, // 0: NED code 0x01, // 1: Type (X'01' = I/O Device) 0x02, // 2: Class (X'02' = Magnetic Tape) 0x00, // 3: (Reserved) 0xF0,0xF0,0xF3,0xF4,0xF9,0xF0, // 4-9: Type ('003490') 0xC3,0xF1,0xF0, // 10-12: Model ('C10') 0xC8,0xD9,0xC3, // 13-15: Manufacturer ('HRC' = Hercules) 0xE9,0xE9, // 16-17: Plant of Manufacture ('ZZ' = Herc) 0xF0,0xF0,0xF0,0xF0,0xF0,0xF0, // 18-29: Sequence Number 0xF0,0xF0,0xF0,0xF0,0xF0,0xF0, // 0x00, 0x00, // 30-31: Tag (x'000n', n = Logical Drive Address) // ---------------- Control Unit NED --------------------------------------------- 0xC4, // 32: NED code 0x02, // 33: Type (X'02' = Control Unit) 0x00, // 34: Class (X'00' = Undefined) 0x00, // 35: (Reserved) 0xF0,0xF0,0xF3,0xF4,0xF9,0xF0, // 36-41: Type ('003490') 0xC3,0xF1,0xF0, // 42-44: Model ('C10') 0xC8,0xD9,0xC3, // 45-47: Manufacturer ('HRC' = Hercules) 0xE9,0xE9, // 48-49: Plant of Manufacture ('ZZ' = Herc) 0xF0,0xF0,0xF0,0xF0,0xF0,0xF0, // 50-61: Sequence Number 0xF0,0xF0,0xF0,0xF0,0xF0,0xF0, // 0x00, 0x00, // 62-63: Tag (x'0000') // ---------------- Library NED -------------------------------------------------- 0x00, // 64: NED code (x'00' = Not Used) 0x00, // 65: Type 0x00, // 66: Class 0x00, // 67: (Reserved) 0x00,0x00,0x00,0x00,0x00,0x00, // 68-73: Type 0x00,0x00,0x00, // 74-76: Model 0x00,0x00,0x00, // 77-79: Manufacturer 0x00,0x00, // 80-81: Plant of Manufacture 0x00,0x00,0x00,0x00,0x00,0x00, // 82-93: Sequence Number 0x00,0x00,0x00,0x00,0x00,0x00, // 0x00, 0x00, // 94-95: Tag // ---------------- Token NED --------------------------------------------------- 0xEC, // 96: NED code 0x00, // 97: Type (X'00' = Unspecified) 0x00, // 98: Class (X'00' = Undefined) 0x00, // 99: (Reserved) 0xF0,0xF0,0xF3,0xF4,0xF9,0xF0, // 100-105: Type ('003490') 0xC3,0xF1,0xF0, // 106-108: Model ('C10') 0xC8,0xD9,0xC3, // 109-111: Manufacturer ('HRC' = Hercules) 0xE9,0xE9, // 112-113: Plant of Manufacture ('ZZ' = Herc) 0xF0,0xF0,0xF0,0xF0,0xF0,0xF0, // 114-125: Sequence Number 0xF0,0xF0,0xF0,0xF0,0xF0,0xF0, // 0x00, 0x00, // 126-127: Tag (x'0000') // ---------------- General NEQ -------------------------------------------------- 0x80, // 128: NED code 0x80, // 129: Record Selector: // x'80' = Control Unit 0 // x'81' = Control Unit 1 0x00,0x80, // 130-131: Interface Id: // x'0080' = CU Channel Adapter A // x'0040' = CU Channel Adapter B 0x00, // 132: Device-Dependent Timeout 0x00,0x00,0x00, // 133-135: (Reserved) 0x00, // 136: Extended Information: // x'00' for Logical Drive Addresses 0-7 // x'01' for Logical Drive Addresses 8-F 0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 137-159: (Reserved) 0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00, }; ASSERT( sizeof(cfgdata) == 160 ); /* Calculate residual byte count */ RESIDUAL_CALC (160); /* Copy prototype Configuration Data to channel I/O buffer */ memcpy (iobuf, cfgdata, sizeof(cfgdata)); /* Fixup values for this particular device/type... NOTE: we only fixup the Device and Control Unit NEDs here. The Token NED's type/model values come from the Device NED's values. */ if (0x3480 == dev->devtype) { memcpy (&iobuf[7], "\xF4\xF8", 2); // '48' memcpy (&iobuf[39], "\xF4\xF8", 2); // '48' memcpy (&iobuf[10], "\xC4\xF3\xF1", 3); // 'D31' memcpy (&iobuf[42], "\xC4\xF3\xF1", 3); // 'D31' } else if (0x3490 == dev->devtype) { // memcpy (&iobuf[7], "\xF4\xF9", 2); // '49' // memcpy (&iobuf[39], "\xF4\xF9", 2); // '49' // memcpy (&iobuf[10], "\xC3\xF1\xF0", 3); // 'C10' // memcpy (&iobuf[42], "\xC3\xF1\xF0", 3); // 'C10' } else if (0x3590 == dev->devtype) { memcpy (&iobuf[7], "\xF5\xF9", 2); // '59' memcpy (&iobuf[39], "\xF5\xF9", 2); // '59' memcpy (&iobuf[10], "\xC2\xF1\xC1", 3); // 'B1A' memcpy (&iobuf[42], "\xC1\xF5\xF0", 3); // 'A50' } memcpy (&iobuf[100], &iobuf[4], 9); // (set Token NED Type/Model from Device NED) iobuf[31] |= (dev->devnum & 0x0F); // (set Logical Drive Address) if ((dev->devnum & 0x0F) > 7) iobuf[136] = 0x01; // (set Extended Information) /* Return normal status */ build_senseX (TAPE_BSENSE_STATUSONLY, dev, unitstat, code); break; } /* End case 0xFA: READ CONFIGURATION DATA */ /*---------------------------------------------------------------*/ /* INVALID OPERATION */ /*---------------------------------------------------------------*/ default: { /* Set command reject sense byte, and unit check status */ build_senseX (TAPE_BSENSE_BADCOMMAND, dev, unitstat, code); } } /* end switch (code) */ } /* end function tapedev_execute_ccw */ #if defined( OPTION_TAPE_AUTOMOUNT ) /*-------------------------------------------------------------------*/ /* Find next more-restrictive TAMDIR subdirectory entry... */ /*-------------------------------------------------------------------*/ static TAMDIR* findtamdir( int rej, int minlen, const char* pszDir ) { TAMDIR *pTAMDIR = sysblk.tamdir; /* always search entire list */ do if (1 && pTAMDIR->rej == rej && pTAMDIR->len > minlen && strnfilenamecmp( pszDir, pTAMDIR->dir, pTAMDIR->len ) == 0 ) return pTAMDIR; while ((pTAMDIR = pTAMDIR->next) != NULL); return NULL; } #endif // defined( OPTION_TAPE_AUTOMOUNT ) /*-------------------------------------------------------------------*/ /* Load Display channel command processing... */ /*-------------------------------------------------------------------*/ void load_display (DEVBLK *dev, BYTE *buf, U16 count) { U16 i; /* Array subscript */ char msg1[9], msg2[9]; /* Message areas (ASCIIZ) */ BYTE fcb; /* Format Control Byte */ BYTE tapeloaded; /* (boolean true/false) */ BYTE* msg; /* (work buf ptr) */ if ( !count ) return; /* Pick up format control byte */ fcb = *buf; /* Copy and translate messages... */ memset( msg1, 0, sizeof(msg1) ); memset( msg2, 0, sizeof(msg2) ); msg = buf+1; for (i=0; *msg && i < 8 && ((i+1)+0) < count; i++) msg1[i] = guest_to_host(*msg++); msg = buf+1+8; for (i=0; *msg && i < 8 && ((i+1)+8) < count; i++) msg2[i] = guest_to_host(*msg++); msg1[ sizeof(msg1) - 1 ] = 0; msg2[ sizeof(msg2) - 1 ] = 0; tapeloaded = dev->tmh->tapeloaded( dev, NULL, 0 ); switch ( fcb & FCB_FS ) // (high-order 3 bits) { case FCB_FS_READYGO: // 0x00 /* || 000b: "The message specified in bytes 1-8 and 9-16 is || maintained until the tape drive next starts tape || motion, or until the message is updated." */ dev->tapedispflags = 0; strlcpy( dev->tapemsg1, msg1, sizeof(dev->tapemsg1) ); strlcpy( dev->tapemsg2, msg2, sizeof(dev->tapemsg2) ); dev->tapedisptype = TAPEDISPTYP_WAITACT; break; case FCB_FS_UNMOUNT: // 0x20 /* || 001b: "The message specified in bytes 1-8 is maintained || until the tape cartridge is physically removed from || the tape drive, or until the next unload/load cycle. || If the drive does not contain a cartridge when the || Load Display command is received, the display will || contain the message that existed prior to the receipt || of the command." */ dev->tapedispflags = 0; if ( tapeloaded ) { dev->tapedisptype = TAPEDISPTYP_UNMOUNT; dev->tapedispflags = TAPEDISPFLG_REQAUTOMNT; strlcpy( dev->tapemsg1, msg1, sizeof(dev->tapemsg1) ); if ( dev->ccwtrace || dev->ccwstep ) logmsg(_("HHCTA099I %4.4X: Tape Display \"%s\" Until Unmounted\n"), dev->devnum, dev->tapemsg1 ); } break; case FCB_FS_MOUNT: // 0x40 /* || 010b: "The message specified in bytes 1-8 is maintained || until the drive is next loaded. If the drive is || loaded when the Load Display command is received, || the display will contain the message that existed || prior to the receipt of the command." */ dev->tapedispflags = 0; if ( !tapeloaded ) { dev->tapedisptype = TAPEDISPTYP_MOUNT; dev->tapedispflags = TAPEDISPFLG_REQAUTOMNT; strlcpy( dev->tapemsg1, msg1, sizeof(dev->tapemsg1) ); if ( dev->ccwtrace || dev->ccwstep ) logmsg(_("HHCTA099I %4.4X: Tape Display \"%s\" Until Mounted\n"), dev->devnum, dev->tapemsg1 ); } break; case FCB_FS_NOP: // 0x60 default: /* || 011b: "This value is used to physically access a drive || without changing the message display. This option || can be used to test whether a control unit can || physically communicate with a drive." */ return; case FCB_FS_RESET_DISPLAY: // 0x80 /* || 100b: "The host message being displayed is cancelled and || a unit message is displayed instead." */ dev->tapedispflags = 0; dev->tapedisptype = TAPEDISPTYP_IDLE; break; case FCB_FS_UMOUNTMOUNT: // 0xE0 /* || 111b: "The message in bytes 1-8 is displayed until a tape || cartridge is physically removed from the tape drive, || or until the drive is next loaded. The message in || bytes 9-16 is displayed until the drive is next loaded. || If no cartridge is present in the drive, the first || message is ignored and only the second message is || displayed until the drive is next loaded." */ dev->tapedispflags = 0; strlcpy( dev->tapemsg1, msg1, sizeof(dev->tapemsg1) ); strlcpy( dev->tapemsg2, msg2, sizeof(dev->tapemsg2) ); if ( tapeloaded ) { dev->tapedisptype = TAPEDISPTYP_UMOUNTMOUNT; dev->tapedispflags = TAPEDISPFLG_REQAUTOMNT; if ( dev->ccwtrace || dev->ccwstep ) logmsg(_("HHCTA099I %4.4X: Tape Display \"%s\" Until Unmounted, then \"%s\" Until Mounted\n"), dev->devnum, dev->tapemsg1, dev->tapemsg2 ); } else { dev->tapedisptype = TAPEDISPTYP_MOUNT; dev->tapedispflags = TAPEDISPFLG_MESSAGE2 | TAPEDISPFLG_REQAUTOMNT; if ( dev->ccwtrace || dev->ccwstep ) logmsg(_("HHCTA099I %4.4X: Tape \"%s\" Until Mounted\n"), dev->devnum, dev->tapemsg2 ); } break; } /* Set the flags... */ /* "When bit 7 (FCB_AL) is active and bits 0-2 (FCB_FS) specify a Mount Message, then only the first eight characters of the message are displayed and bits 3-5 (FCB_AM, FCB_BM, FCB_M2) are ignored." */ if (1 && ( fcb & FCB_AL ) && ( ( fcb & FCB_FS ) == FCB_FS_MOUNT ) ) { fcb &= ~( FCB_AM | FCB_BM | FCB_M2 ); dev->tapedispflags &= ~TAPEDISPFLG_MESSAGE2; } /* "When bit 7 (FCB_AL) is active and bits 0-2 (FCB_FS) specify a Demount/Mount message, then only the last eight characters of the message are displayed. Bits 3-5 (FCB_AM, FCB_BM, FCB_M2) are ignored." */ if (1 && ( fcb & FCB_AL ) && ( ( fcb & FCB_FS ) == FCB_FS_UMOUNTMOUNT ) ) { fcb &= ~( FCB_AM | FCB_BM | FCB_M2 ); dev->tapedispflags |= TAPEDISPFLG_MESSAGE2; } /* "When bit 3 (FCB_AM) is set to 1, then bits 4 (FCB_BM) and 5 (FCB_M2) are ignored." */ if ( fcb & FCB_AM ) fcb &= ~( FCB_BM | FCB_M2 ); dev->tapedispflags |= (((fcb & FCB_AM) ? TAPEDISPFLG_ALTERNATE : 0 ) | ( (fcb & FCB_BM) ? TAPEDISPFLG_BLINKING : 0 ) | ( (fcb & FCB_M2) ? TAPEDISPFLG_MESSAGE2 : 0 ) | ( (fcb & FCB_AL) ? TAPEDISPFLG_AUTOLOADER : 0 )); UpdateDisplay( dev ); ReqAutoMount( dev ); } /* end function load_display */ /*********************************************************************/ /*********************************************************************/ /** **/ /** SENSE CCW HANDLING FUNCTIONS **/ /** **/ /*********************************************************************/ /*********************************************************************/ /*-------------------------------------------------------------------*/ /* build_senseX */ /*-------------------------------------------------------------------*/ /* Construct sense bytes and unit status */ /* Note: name changed because semantic changed */ /* ERCode is our internal ERror-type code */ /* */ /* Uses the 'TapeSenseTable' table index */ /* from the 'TapeDevtypeList' table to route call to */ /* one of the below device-specific sense functions */ /*-------------------------------------------------------------------*/ void build_senseX (int ERCode, DEVBLK *dev, BYTE *unitstat, BYTE ccwcode) { int i; BYTE usr; int sense_built; sense_built = 0; if(unitstat==NULL) { unitstat = &usr; } for(i = 0;TapeDevtypeList[i] != 0; i += TAPEDEVTYPELIST_ENTRYSIZE) { if (TapeDevtypeList[i] == dev->devtype) { // Clear old sense if we're going to completely rebuild it... if (TAPE_BSENSE_STATUSONLY != ERCode) { memset( dev->sense, 0, sizeof(dev->sense) ); dev->sns_pending = 0; } // Call the primary sense function (e.g. "build_sense_3480_etal")... TapeSenseTable[TapeDevtypeList[i+4]](ERCode,dev,unitstat,ccwcode); sense_built = 1; // Unit-exception s/b signalled for all write operations // once the end-of-tape (EOT) reflector has been passed... if (1 && TAPE_BSENSE_STATUSONLY == ERCode && (0 || 0x01 == ccwcode // write || 0x17 == ccwcode // erase gap || 0x1F == ccwcode // write tapemark ) && dev->tmh->passedeot(dev) ) { // We're still in the "Early Warning Zone", // so keep warning them... *unitstat |= CSW_UX; // ("Warning!") } break; } } if (!sense_built) { memset( dev->sense, 0, sizeof(dev->sense) ); dev->sense[0]=SENSE_EC; *unitstat = CSW_CE|CSW_DE|CSW_UC; } if (*unitstat & CSW_UC) { dev->sns_pending = 1; } return; } /* end function build_senseX */ /*-------------------------------------------------------------------*/ /* build_sense_3410_3420 */ /*-------------------------------------------------------------------*/ void build_sense_3410_3420 (int ERCode, DEVBLK *dev, BYTE *unitstat, BYTE ccwcode) { // NOTE: caller should have cleared sense area to zeros // if this isn't a 'TAPE_BSENSE_STATUSONLY' call switch(ERCode) { case TAPE_BSENSE_TAPEUNLOADED: switch(ccwcode) { case 0x01: // write case 0x02: // read case 0x0C: // read backward *unitstat = CSW_CE | CSW_UC | (dev->tdparms.deonirq?CSW_DE:0); break; case 0x03: // nop *unitstat = CSW_UC; break; case 0x0f: // rewind unload /* *unitstat = CSW_CE | CSW_UC | CSW_DE | CSW_CUE; */ *unitstat = CSW_UC | CSW_DE | CSW_CUE; break; default: *unitstat = CSW_CE | CSW_UC | CSW_DE; break; } // end switch(ccwcode) dev->sense[0] = SENSE_IR; dev->sense[1] = SENSE1_TAPE_TUB; break; case TAPE_BSENSE_RUN_SUCCESS: /* RewUnld op */ *unitstat = CSW_UC | CSW_DE | CSW_CUE; /* *unitstat = CSW_CE | CSW_UC | CSW_DE | CSW_CUE; */ dev->sense[0] = SENSE_IR; dev->sense[1] = SENSE1_TAPE_TUB; break; case TAPE_BSENSE_REWINDFAILED: case TAPE_BSENSE_FENCED: case TAPE_BSENSE_EMPTYTAPE: case TAPE_BSENSE_ENDOFTAPE: case TAPE_BSENSE_BLOCKSHORT: /* On 3411/3420 the tape runs off the reel in that case */ /* this will cause pressure loss in both columns */ case TAPE_BSENSE_LOCATEERR: /* Locate error: This is more like improperly formatted tape */ /* i.e. the tape broke inside the drive */ /* So EC instead of DC */ case TAPE_BSENSE_TAPELOADFAIL: *unitstat = CSW_CE|CSW_DE|CSW_UC; dev->sense[0] = SENSE_EC; dev->sense[1] = SENSE1_TAPE_TUB; dev->sense[7] = 0x60; break; case TAPE_BSENSE_ITFERROR: *unitstat = CSW_CE|CSW_DE|CSW_UC; dev->sense[0] = SENSE_EC; dev->sense[1] = SENSE1_TAPE_TUB; dev->sense[4] = 0x80; /* Tape Unit Reject */ break; case TAPE_BSENSE_READFAIL: case TAPE_BSENSE_BADALGORITHM: *unitstat = CSW_CE|CSW_DE|CSW_UC; dev->sense[0] = SENSE_DC; dev->sense[3] = 0xC0; /* Vertical CRC check & Multitrack error */ break; case TAPE_BSENSE_WRITEFAIL: *unitstat = CSW_CE|CSW_DE|CSW_UC; dev->sense[0] = SENSE_DC; dev->sense[3] = 0x60; /* Longitudinal CRC check & Multitrack error */ break; case TAPE_BSENSE_BADCOMMAND: case TAPE_BSENSE_INCOMPAT: *unitstat = CSW_CE|CSW_DE|CSW_UC; dev->sense[0] = SENSE_CR; dev->sense[4] = 0x01; break; case TAPE_BSENSE_WRITEPROTECT: *unitstat = CSW_CE|CSW_DE|CSW_UC; dev->sense[0] = SENSE_CR; break; case TAPE_BSENSE_LOADPTERR: *unitstat = CSW_CE|CSW_DE|CSW_UC; dev->sense[0] = 0; break; case TAPE_BSENSE_READTM: *unitstat = CSW_CE|CSW_DE|CSW_UX; break; case TAPE_BSENSE_UNSOLICITED: *unitstat = CSW_CE|CSW_DE; break; case TAPE_BSENSE_STATUSONLY: *unitstat = CSW_CE|CSW_DE; break; } // end switch(ERCode) if (TAPE_BSENSE_STATUSONLY == ERCode) return; // (mission accomplished) /* Fill in the common sense information */ if (strcmp(dev->filename,TAPE_UNLOADED) == 0 || !dev->tmh->tapeloaded(dev,NULL,0)) { dev->sense[0] |= SENSE_IR; dev->sense[1] |= SENSE1_TAPE_FP; } else { dev->sense[0] &= ~SENSE_IR; dev->sense[1] |= IsAtLoadPoint( dev ) ? SENSE1_TAPE_LOADPT : 0; dev->sense[1] |= dev->readonly || dev->tdparms.logical_readonly ? SENSE1_TAPE_FP : 0; } if (dev->tmh->passedeot(dev)) { dev->sense[4] |= 0x40; } } /* end function build_sense_3410_3420 */ /*-------------------------------------------------------------------*/ /* build_sense_3410 */ /*-------------------------------------------------------------------*/ void build_sense_3410 (int ERCode, DEVBLK *dev, BYTE *unitstat, BYTE ccwcode) { build_sense_3410_3420(ERCode,dev,unitstat,ccwcode); dev->sense[5] &= 0x80; dev->sense[5] |= 0x40; dev->sense[6] = 0x22; /* Dual Dens - 3410/3411 Model 2 */ dev->numsense = 9; } /* end function build_sense_3410 */ /*-------------------------------------------------------------------*/ /* build_sense_3420 */ /*-------------------------------------------------------------------*/ void build_sense_3420 (int ERCode, DEVBLK *dev, BYTE *unitstat, BYTE ccwcode) { build_sense_3410_3420(ERCode,dev,unitstat,ccwcode); /* Following stripped from original 'build_sense' */ dev->sense[5] |= 0xC0; dev->sense[6] |= 0x03; dev->sense[13] = 0x80; dev->sense[14] = 0x01; dev->sense[15] = 0x00; dev->sense[16] = 0x01; dev->sense[19] = 0xFF; dev->sense[20] = 0xFF; dev->numsense = 24; } /* end function build_sense_3420 */ /*-------------------------------------------------------------------*/ /* build_sense_3480_etal */ /*-------------------------------------------------------------------*/ void build_sense_3480_etal (int ERCode,DEVBLK *dev,BYTE *unitstat,BYTE ccwcode) { int sns4mat = 0x20; // NOTE: caller should have cleared sense area to zeros // if this isn't a 'TAPE_BSENSE_STATUSONLY' call switch(ERCode) { case TAPE_BSENSE_TAPEUNLOADED: switch(ccwcode) { case 0x01: // write case 0x02: // read case 0x0C: // read backward *unitstat = CSW_CE | CSW_UC; break; case 0x03: // nop *unitstat = CSW_UC; break; case 0x0f: // rewind unload *unitstat = CSW_CE | CSW_UC | CSW_DE | CSW_CUE; break; default: *unitstat = CSW_CE | CSW_UC | CSW_DE; break; } // end switch(ccwcode) dev->sense[0] = SENSE_IR; dev->sense[3] = 0x43; /* ERA 43 = Int Req */ break; case TAPE_BSENSE_RUN_SUCCESS: /* Not an error */ *unitstat = CSW_CE|CSW_DE; dev->sense[0] = SENSE_IR; dev->sense[3] = 0x2B; sns4mat = 0x21; break; case TAPE_BSENSE_TAPELOADFAIL: *unitstat = CSW_CE|CSW_DE|CSW_UC; dev->sense[0] = SENSE_IR|0x02; dev->sense[3] = 0x33; /* ERA 33 = Load Failed */ break; case TAPE_BSENSE_READFAIL: *unitstat = CSW_CE|CSW_DE|CSW_UC; dev->sense[0] = SENSE_DC; dev->sense[3] = 0x23; break; case TAPE_BSENSE_WRITEFAIL: *unitstat = CSW_CE|CSW_DE|CSW_UC; dev->sense[0] = SENSE_DC; dev->sense[3] = 0x25; break; case TAPE_BSENSE_BADCOMMAND: *unitstat = CSW_CE|CSW_DE|CSW_UC; dev->sense[0] = SENSE_CR; dev->sense[3] = 0x27; break; case TAPE_BSENSE_INCOMPAT: *unitstat = CSW_CE|CSW_DE|CSW_UC; dev->sense[0] = SENSE_CR; dev->sense[3] = 0x29; break; case TAPE_BSENSE_WRITEPROTECT: *unitstat = CSW_CE|CSW_DE|CSW_UC; dev->sense[0] = SENSE_CR; dev->sense[3] = 0x30; break; case TAPE_BSENSE_EMPTYTAPE: *unitstat = CSW_CE|CSW_DE|CSW_UC; dev->sense[0] = SENSE_DC; dev->sense[3] = 0x31; break; case TAPE_BSENSE_ENDOFTAPE: *unitstat = CSW_CE|CSW_DE|CSW_UC; dev->sense[0] = SENSE_EC; dev->sense[3] = 0x38; break; case TAPE_BSENSE_LOADPTERR: *unitstat = CSW_CE|CSW_DE|CSW_UC; dev->sense[0] = 0; dev->sense[3] = 0x39; break; case TAPE_BSENSE_FENCED: *unitstat = CSW_CE|CSW_DE|CSW_UC; dev->sense[0] = SENSE_EC|0x02; /* Deffered UC */ dev->sense[3] = 0x47; break; case TAPE_BSENSE_BADALGORITHM: *unitstat = CSW_CE|CSW_DE|CSW_UC; dev->sense[0] = SENSE_EC; if (dev->devtype==0x3480) { dev->sense[3] = 0x47; // (volume fenced) } else // 3490, 3590, etc. { dev->sense[3] = 0x5E; // (bad compaction algorithm) } break; case TAPE_BSENSE_LOCATEERR: *unitstat = CSW_CE|CSW_DE|CSW_UC; dev->sense[0] = SENSE_EC; dev->sense[3] = 0x44; break; case TAPE_BSENSE_BLOCKSHORT: *unitstat = CSW_CE|CSW_DE|CSW_UC; dev->sense[0] = SENSE_EC; dev->sense[3] = 0x36; break; case TAPE_BSENSE_ITFERROR: *unitstat = CSW_CE|CSW_DE|CSW_UC; dev->sense[0] = SENSE_EC; dev->sense[3] = 0x22; break; case TAPE_BSENSE_REWINDFAILED: *unitstat = CSW_CE|CSW_DE|CSW_UC; dev->sense[0] = SENSE_EC; dev->sense[3] = 0x2C; /* Generic Equipment Malfunction ERP code */ break; case TAPE_BSENSE_READTM: *unitstat = CSW_CE|CSW_DE|CSW_UX; break; case TAPE_BSENSE_UNSOLICITED: *unitstat = CSW_CE|CSW_DE; dev->sense[3] = 0x00; break; case TAPE_BSENSE_STATUSONLY: default: *unitstat = CSW_CE|CSW_DE; break; } // end switch(ERCode) if (TAPE_BSENSE_STATUSONLY == ERCode) return; // (mission accomplished) /* Fill in the common sense information */ switch(sns4mat) { default: case 0x20: case 0x21: dev->sense[7] = sns4mat; memset(&dev->sense[8],0,31-8); break; } // end switch(sns4mat) if (strcmp(dev->filename,TAPE_UNLOADED) == 0 || !dev->tmh->tapeloaded(dev,NULL,0)) { dev->sense[0] |= SENSE_IR; dev->sense[1] |= SENSE1_TAPE_FP; } else { dev->sense[0] &= ~SENSE_IR; dev->sense[1] &= ~(SENSE1_TAPE_LOADPT|SENSE1_TAPE_FP); dev->sense[1] |= IsAtLoadPoint( dev ) ? SENSE1_TAPE_LOADPT : 0; dev->sense[1] |= dev->readonly || dev->tdparms.logical_readonly ? SENSE1_TAPE_FP : 0; } dev->sense[1] |= SENSE1_TAPE_TUA; } /* end function build_sense_3480_etal */ /*-------------------------------------------------------------------*/ /* build_sense_3490 */ /*-------------------------------------------------------------------*/ void build_sense_3490 (int ERCode, DEVBLK *dev, BYTE *unitstat, BYTE ccwcode) { // Until we know for sure that we have to do something different, // we should be able to safely use the 3480 sense function here... build_sense_3480_etal ( ERCode, dev, unitstat, ccwcode ); } /*-------------------------------------------------------------------*/ /* build_sense_3590 */ /*-------------------------------------------------------------------*/ void build_sense_3590 (int ERCode, DEVBLK *dev, BYTE *unitstat, BYTE ccwcode) { // Until we know for sure that we have to do something different, // we should be able to safely use the 3480 sense function here... build_sense_3480_etal ( ERCode, dev, unitstat, ccwcode ); } /*-------------------------------------------------------------------*/ /* build_sense_Streaming */ /* (8809, 9347, 9348) */ /*-------------------------------------------------------------------*/ void build_sense_Streaming (int ERCode, DEVBLK *dev, BYTE *unitstat, BYTE ccwcode) { // NOTE: caller should have cleared sense area to zeros // if this isn't a 'TAPE_BSENSE_STATUSONLY' call switch(ERCode) { case TAPE_BSENSE_TAPEUNLOADED: switch(ccwcode) { case 0x01: // write case 0x02: // read case 0x0C: // read backward *unitstat = CSW_CE | CSW_UC | (dev->tdparms.deonirq?CSW_DE:0); break; case 0x03: // nop *unitstat = CSW_UC; break; case 0x0f: // rewind unload /* *unitstat = CSW_CE | CSW_UC | CSW_DE | CSW_CUE; */ *unitstat = CSW_UC | CSW_DE | CSW_CUE; break; default: *unitstat = CSW_CE | CSW_UC | CSW_DE; break; } // end switch(ccwcode) dev->sense[0] = SENSE_IR; dev->sense[3] = 6; /* Int Req ERAC */ break; case TAPE_BSENSE_RUN_SUCCESS: /* RewUnld op */ *unitstat = CSW_UC | CSW_DE | CSW_CUE; /* *unitstat = CSW_CE | CSW_UC | CSW_DE | CSW_CUE; */ dev->sense[0] = SENSE_IR; dev->sense[3] = 6; /* Int Req ERAC */ break; case TAPE_BSENSE_REWINDFAILED: case TAPE_BSENSE_ITFERROR: dev->sense[0] = SENSE_EC; dev->sense[3] = 0x03; /* Perm Equip Check */ *unitstat = CSW_CE|CSW_DE|CSW_UC; break; case TAPE_BSENSE_TAPELOADFAIL: case TAPE_BSENSE_LOCATEERR: case TAPE_BSENSE_ENDOFTAPE: case TAPE_BSENSE_EMPTYTAPE: case TAPE_BSENSE_FENCED: case TAPE_BSENSE_BLOCKSHORT: case TAPE_BSENSE_INCOMPAT: dev->sense[0] = SENSE_EC; dev->sense[3] = 0x10; /* PE-ID Burst Check */ *unitstat = CSW_CE|CSW_DE|CSW_UC; break; case TAPE_BSENSE_BADALGORITHM: case TAPE_BSENSE_READFAIL: dev->sense[0] = SENSE_DC; dev->sense[3] = 0x09; /* Read Data Check */ *unitstat = CSW_CE|CSW_DE|CSW_UC; break; case TAPE_BSENSE_WRITEFAIL: dev->sense[0] = SENSE_DC; dev->sense[3] = 0x07; /* Write Data Check (Media Error) */ *unitstat = CSW_CE|CSW_DE|CSW_UC; break; case TAPE_BSENSE_BADCOMMAND: dev->sense[0] = SENSE_CR; dev->sense[3] = 0x0C; /* Bad Command */ *unitstat = CSW_CE|CSW_DE|CSW_UC; break; case TAPE_BSENSE_WRITEPROTECT: dev->sense[0] = SENSE_CR; dev->sense[3] = 0x0B; /* File Protect */ *unitstat = CSW_CE|CSW_DE|CSW_UC; break; case TAPE_BSENSE_LOADPTERR: dev->sense[0] = SENSE_CR; dev->sense[3] = 0x0D; /* Backspace at Load Point */ *unitstat = CSW_CE|CSW_DE|CSW_UC; break; case TAPE_BSENSE_READTM: *unitstat = CSW_CE|CSW_DE|CSW_UX; break; case TAPE_BSENSE_UNSOLICITED: *unitstat = CSW_CE|CSW_DE; break; case TAPE_BSENSE_STATUSONLY: *unitstat = CSW_CE|CSW_DE; break; } // end switch(ERCode) if (TAPE_BSENSE_STATUSONLY == ERCode) return; // (mission accomplished) /* Fill in the common sense information */ if (strcmp(dev->filename,TAPE_UNLOADED) == 0 || !dev->tmh->tapeloaded(dev,NULL,0)) { dev->sense[0] |= SENSE_IR; dev->sense[1] |= SENSE1_TAPE_FP; dev->sense[1] &= ~SENSE1_TAPE_TUA; dev->sense[1] |= SENSE1_TAPE_TUB; } else { dev->sense[0] &= ~SENSE_IR; dev->sense[1] |= IsAtLoadPoint( dev ) ? SENSE1_TAPE_LOADPT : 0; dev->sense[1] |= dev->readonly || dev->tdparms.logical_readonly ? SENSE1_TAPE_FP : 0; dev->sense[1] |= SENSE1_TAPE_TUA; dev->sense[1] &= ~SENSE1_TAPE_TUB; } if (dev->tmh->passedeot(dev)) { dev->sense[4] |= 0x40; } } /* end function build_sense_Streaming */ /*********************************************************************/ /*********************************************************************/ /** **/ /** (( I N C O M P L E T E )) **/ /** **/ /** (experimental possible new sense handling function) **/ /** **/ /*********************************************************************/ /*********************************************************************/ #if 0 // ZZ FIXME: To Do... /*-------------------------------------------------------------------*/ /* Error Recovery Action codes */ /*-------------------------------------------------------------------*/ /* Even though ERA codes are, technically, only applicable for model 3480/3490/3590 tape drives (the sense information that is returned for model 3480/3490/3590 tape drives include the ERA code in them), we can nonetheless still use them as an argument for our 'BuildTapeSense' function even for other model tape drives (e.g. 3420's for example). That is to say, even though model 3420's for example, don't have an ERA code anywhere in their sense information, we can still use the ERA code as an argument in our call to our 'BuildTapeSense' function without actually using it anywhere in our sense info. In such a case we would be just using it as an internal value to tell us what type of sense information to build for the model 3420, but not for any other purpose. For 3480/3490/3590 model drives however, we not only use it for the same purpose (i.e. as an internal value to tell us what format of sense we need to build) but ALSO as an actual value to be placed into the actual formatted sense information itself too. */ #define TAPE_ERA_UNSOLICITED_SENSE 0x00 #define TAPE_ERA_DATA_STREAMING_NOT_OPER 0x21 #define TAPE_ERA_PATH_EQUIPMENT_CHECK 0x22 #define TAPE_ERA_READ_DATA_CHECK 0x23 #define TAPE_ERA_LOAD_DISPLAY_CHECK 0x24 #define TAPE_ERA_WRITE_DATA_CHECK 0x25 #define TAPE_ERA_READ_OPPOSITE 0x26 #define TAPE_ERA_COMMAND_REJECT 0x27 #define TAPE_ERA_WRITE_ID_MARK_CHECK 0x28 #define TAPE_ERA_FUNCTION_INCOMPATIBLE 0x29 #define TAPE_ERA_UNSOL_ENVIRONMENTAL_DATA 0x2A #define TAPE_ERA_ENVIRONMENTAL_DATA_PRESENT 0x2B #define TAPE_ERA_PERMANENT_EQUIPMENT_CHECK 0x2C #define TAPE_ERA_DATA_SECURE_ERASE_FAILURE 0x2D #define TAPE_ERA_NOT_CAPABLE_BOT_ERROR 0x2E #define TAPE_ERA_WRITE_PROTECTED 0x30 #define TAPE_ERA_TAPE_VOID 0x31 #define TAPE_ERA_TENSION_LOST 0x32 #define TAPE_ERA_LOAD_FAILURE 0x33 #define TAPE_ERA_UNLOAD_FAILURE 0x34 #define TAPE_ERA_DRIVE_EQUIPMENT_CHECK 0x35 #define TAPE_ERA_END_OF_DATA 0x36 #define TAPE_ERA_TAPE_LENGTH_ERROR 0x37 #define TAPE_ERA_PHYSICAL_END_OF_TAPE 0x38 #define TAPE_ERA_BACKWARD_AT_BOT 0x39 #define TAPE_ERA_DRIVE_SWITCHED_NOT_READY 0x3A #define TAPE_ERA_MANUAL_REWIND_OR_UNLOAD 0x3B #define TAPE_ERA_OVERRUN 0x40 #define TAPE_ERA_RECORD_SEQUENCE_ERROR 0x41 #define TAPE_ERA_DEGRADED_MODE 0x42 #define TAPE_ERA_DRIVE_NOT_READY 0x43 #define TAPE_ERA_LOCATE_BLOCK_FAILED 0x44 #define TAPE_ERA_DRIVE_ASSIGNED_ELSEWHERE 0x45 #define TAPE_ERA_DRIVE_NOT_ONLINE 0x46 #define TAPE_ERA_VOLUME_FENCED 0x47 #define TAPE_ERA_UNSOL_INFORMATIONAL_DATA 0x48 #define TAPE_ERA_BUS_OUT_CHECK 0x49 #define TAPE_ERA_CONTROL_UNIT_ERP_FAILURE 0x4A #define TAPE_ERA_CU_AND_DRIVE_INCOMPATIBLE 0x4B #define TAPE_ERA_RECOVERED_CHECKONE_FAILED 0x4C #define TAPE_ERA_RESETTING_EVENT 0x4D #define TAPE_ERA_MAX_BLOCKSIZE_EXCEEDED 0x4E #define TAPE_ERA_BUFFERED_LOG_OVERFLOW 0x50 #define TAPE_ERA_BUFFERED_LOG_END_OF_VOLUME 0x51 #define TAPE_ERA_END_OF_VOLUME_COMPLETE 0x52 #define TAPE_ERA_GLOBAL_COMMAND_INTERCEPT 0x53 #define TAPE_ERA_TEMP_CHANN_INTFACE_ERROR 0x54 #define TAPE_ERA_PERM_CHANN_INTFACE_ERROR 0x55 #define TAPE_ERA_CHANN_PROTOCOL_ERROR 0x56 #define TAPE_ERA_GLOBAL_STATUS_INTERCEPT 0x57 #define TAPE_ERA_TAPE_LENGTH_INCOMPATIBLE 0x5A #define TAPE_ERA_FORMAT_3480_XF_INCOMPAT 0x5B #define TAPE_ERA_FORMAT_3480_2_XF_INCOMPAT 0x5C #define TAPE_ERA_TAPE_LENGTH_VIOLATION 0x5D #define TAPE_ERA_COMPACT_ALGORITHM_INCOMPAT 0x5E // Sense byte 0 #define TAPE_SNS0_CMDREJ 0x80 // Command Reject #define TAPE_SNS0_INTVREQ 0x40 // Intervention Required #define TAPE_SNS0_BUSCHK 0x20 // Bus-out Check #define TAPE_SNS0_EQUIPCHK 0x10 // Equipment Check #define TAPE_SNS0_DATACHK 0x08 // Data check #define TAPE_SNS0_OVERRUN 0x04 // Overrun #define TAPE_SNS0_DEFUNITCK 0x02 // Deferred Unit Check #define TAPE_SNS0_ASSIGNED 0x01 // Assigned Elsewhere // Sense byte 1 #define TAPE_SNS1_LOCFAIL 0x80 // Locate Failure #define TAPE_SNS1_ONLINE 0x40 // Drive Online to CU #define TAPE_SNS1_RSRVD 0x20 // Reserved #define TAPE_SNS1_RCDSEQ 0x10 // Record Sequence Error #define TAPE_SNS1_BOT 0x08 // Beginning of Tape #define TAPE_SNS1_WRTMODE 0x04 // Write Mode #define TAPE_SNS1_FILEPROT 0x02 // Write Protect #define TAPE_SNS1_NOTCAPBL 0x01 // Not Capable // Sense byte 2 //efine TAPE_SNS2_XXXXXXX 0x80-0x04 // (not defined) #define TAPE_SNS2_SYNCMODE 0x02 // Tape Synchronous Mode #define TAPE_SNS2_POSITION 0x01 // Tape Positioning #define BUILD_TAPE_SENSE( _era ) BuildTapeSense( _era, dev, unitstat, code ) // BUILD_TAPE_SENSE( TAPE_ERA_COMMAND_REJECT ); /*-------------------------------------------------------------------*/ /* BuildTapeSense */ /*-------------------------------------------------------------------*/ /* Build appropriate sense information based on passed ERA code... */ /*-------------------------------------------------------------------*/ void BuildTapeSense( BYTE era, DEVBLK *dev, BYTE *unitstat, BYTE ccwcode ) { BYTE fmt; // ---------------- Determine Sense Format ----------------------- switch (era) { default: fmt = 0x20; break; case TAPE_ERA_UNSOL_ENVIRONMENTAL_DATA: // ERA 2A fmt = 0x21; break; case TAPE_ERA_ENVIRONMENTAL_DATA_PRESENT: // ERA 2B if (dev->devchar[8] & 0x01) // Extended Buffered Log support enabled? fmt = 0x30; // Yes, IDRC; 64-bytes of sense data else fmt = 0x21; // No, no IDRC; only 32-bytes of sense break; case TAPE_ERA_UNSOL_INFORMATIONAL_DATA: // ERA 48 if (dev->forced_logging) // Forced Error Logging enabled? fmt = 0x19; // Yes, Forced Error Logging sense else fmt = 0x20; // No, Normal Informational sense break; case TAPE_ERA_END_OF_VOLUME_COMPLETE: // ERA 52 fmt = 0x22; break; case TAPE_ERA_FORMAT_3480_2_XF_INCOMPAT: // ERA 5C fmt = 0x24; break; } // End switch (era) // ---------------- Build Sense Format ----------------------- switch (fmt) { case 0x19: break; default: case 0x20: break; case 0x21: break; case 0x22: break; case 0x24: break; case 0x30: break; } // End switch (fmt) } /* end function BuildTapeSense */ #endif // ZZ FIXME: To Do... /*********************************************************************/ /*********************************************************************/ hercules-3.07/tapecopy.c000644 000765 000765 00000075376 11321734033 016752 0ustar00jmaynardjmaynard000000 000000 /* TAPECOPY.C (c) Copyright Roger Bowler, 1999-2010 */ /* Convert SCSI tape into AWSTAPE format */ // $Id: tapecopy.c 5593 2010-01-05 14:25:19Z rbowler $ /* Read from AWSTAPE and write to SCSI tape mods */ /* Copyright 2005-2009 James R. Maynard III */ /*-------------------------------------------------------------------*/ /* This program reads a SCSI tape and produces a disk file with */ /* each block of the tape prefixed by an AWSTAPE block header. */ /* If no disk file name is supplied, then the program simply */ /* prints a summary of the tape files and blocksizes. */ /*-------------------------------------------------------------------*/ #include "hstdinc.h" #include "hercules.h" #include "tapedev.h" #include "scsitape.h" /*-------------------------------------------------------------------*/ /* (if no SCSI tape support generated, do nothing) */ /*-------------------------------------------------------------------*/ #if !defined(OPTION_SCSI_TAPE) // SYSBLK sysblk; int main (int argc, char *argv[]) { UNREFERENCED(argc); UNREFERENCED(argv); printf( _("HHCTC017E SCSI tape not supported with this build\n") ); return 0; } #else /*-------------------------------------------------------------------*/ /* External GUI flag... */ /*-------------------------------------------------------------------*/ #if defined(EXTERNALGUI) time_t curr_progress_time = 0; time_t prev_progress_time = 0; #define PROGRESS_INTERVAL_SECS ( 3 ) /* (just what it says) */ #endif /*defined(EXTERNALGUI)*/ /*-------------------------------------------------------------------*/ /* Return Codes... */ /*-------------------------------------------------------------------*/ #define RC_SUCCESS ( 0) #define RC_ERROR_BAD_ARGUMENTS ( 1) #define RC_ERROR_OPENING_SCSI_DEVICE ( 3) #define RC_ERROR_OPENING_AWS_FILE ( 4) #define RC_ERROR_SETTING_SCSI_VARBLK_PROCESSING ( 5) #define RC_ERROR_REWINDING_SCSI ( 6) #define RC_ERROR_OBTAINING_SCSI_STATUS ( 7) #define RC_ERROR_READING_AWS_HEADER ( 8) #define RC_ERROR_READING_DATA ( 9) #define RC_ERROR_AWSTAPE_BLOCK_TOO_LARGE (10) #define RC_ERROR_WRITING_TAPEMARK (11) #define RC_ERROR_WRITING_OUTPUT_AWS_HEADER_BLOCK (12) #define RC_ERROR_WRITING_DATA (13) /*-------------------------------------------------------------------*/ /* Static data areas */ /*-------------------------------------------------------------------*/ static BYTE vollbl[] = "\xE5\xD6\xD3"; /* EBCDIC characters "VOL" */ static BYTE hdrlbl[] = "\xC8\xC4\xD9"; /* EBCDIC characters "HDR" */ static BYTE eoflbl[] = "\xC5\xD6\xC6"; /* EBCDIC characters "EOF" */ static BYTE eovlbl[] = "\xC5\xD6\xE5"; /* EBCDIC characters "EOV" */ static struct mt_tape_info tapeinfo[] = MT_TAPE_INFO; static struct mt_tape_info densinfo[] = { {0x01, "NRZI (800 bpi)" }, {0x02, "PE (1600 bpi)" }, {0x03, "GCR (6250 bpi)" }, {0x05, "QIC-45/60 (GCR, 8000 bpi)" }, {0x06, "PE (3200 bpi)" }, {0x07, "IMFM (6400 bpi)" }, {0x08, "GCR (8000 bpi)" }, {0x09, "GCR (37871 bpi)" }, {0x0A, "MFM (6667 bpi)" }, {0x0B, "PE (1600 bpi)" }, {0x0C, "GCR (12960 bpi)" }, {0x0D, "GCR (25380 bpi)" }, {0x0F, "QIC-120 (GCR 10000 bpi)" }, {0x10, "QIC-150/250 (GCR 10000 bpi)" }, {0x11, "QIC-320/525 (GCR 16000 bpi)" }, {0x12, "QIC-1350 (RLL 51667 bpi)" }, {0x13, "DDS (61000 bpi)" }, {0x14, "EXB-8200 (RLL 43245 bpi)" }, {0x15, "EXB-8500 (RLL 45434 bpi)" }, {0x16, "MFM 10000 bpi" }, {0x17, "MFM 42500 bpi" }, {0x24, "DDS-2" }, {0x8C, "EXB-8505 compressed" }, {0x90, "EXB-8205 compressed" }, {0, NULL }, }; /*-------------------------------------------------------------------*/ /* Maximum blocksized SCSI tape I/O buffer... */ /*-------------------------------------------------------------------*/ static BYTE buf[ 65535 ]; /*-------------------------------------------------------------------*/ /* Global variables used by main and the read/write functions */ /*-------------------------------------------------------------------*/ int len; /* Block length */ int prevlen; /* Previous block length */ int64_t bytes_written; /* Bytes written to o/p file */ char *devnamein; /* -> Input tape device name */ char *devnameout; /* -> Output tape device name*/ char *filenamein; /* -> Input AWS file name */ char *filenameout; /* -> Output AWS file name */ /*-------------------------------------------------------------------*/ /* Custom exit function... */ /*-------------------------------------------------------------------*/ void delayed_exit (int exit_code) { if (RC_SUCCESS != exit_code) printf( _( "HHCTC000I Abnormal termination\n" ) ); /* Delay exiting is to give the system * time to display the error message. */ usleep(100000); exit(exit_code); } #define EXIT(rc) delayed_exit(rc) /* (use this macro to exit) */ /*-------------------------------------------------------------------*/ /* Subroutine to print tape status */ /*-------------------------------------------------------------------*/ static void print_status (char *devname, long stat) { printf (_("HHCTC015I %s status: %8.8lX"), devname, stat); if (GMT_EOF ( stat )) printf (" EOF" ); if (GMT_BOT ( stat )) printf (" BOT" ); if (GMT_EOT ( stat )) printf (" EOT" ); if (GMT_SM ( stat )) printf (" SETMARK"); if (GMT_EOD ( stat )) printf (" EOD" ); if (GMT_WR_PROT( stat )) printf (" WRPROT" ); if (GMT_ONLINE ( stat )) printf (" ONLINE" ); if (GMT_D_6250 ( stat )) printf (" 6250" ); if (GMT_D_1600 ( stat )) printf (" 1600" ); if (GMT_D_800 ( stat )) printf (" 800" ); if (GMT_DR_OPEN( stat )) printf (" NOTAPE" ); printf ("\n"); } /* end function print_status */ /*-------------------------------------------------------------------*/ /* Subroutine to print usage message */ /*-------------------------------------------------------------------*/ static void print_usage (void) { printf ( _( "\n" // 1...5...10...15...20...25...30...35...40...45...50...55...60...65...70...75...80 "Copies a SCSI tape to or from an AWSTAPE disk file.\n\n" "Tapecopy reads a SCSI tape and outputs an AWSTAPE file representation\n" "of the tape, or else reads an AWSTAPE file and creates an identical copy\n" "of its contents on a tape mounted on a SCSI tape drive.\n\n" "Usage:\n\n" " tapecopy [tapedrive] [awsfile] or\n" " tapecopy [awsfile] [tapedrive]\n\n" "Where:\n\n" " tapedrive specifies the device filename of the SCSI tape drive.\n" " Must begin with /dev to be recognized.\n" " awsfile specifies the filename of the AWSTAPE disk file.\n\n" "The first filename is the input; the second is the output.\n\n" "If the input file is a SCSI tape, it is read and processed until physical EOD\n" "(end-of-data) is reached (i.e. it does not stop whenever multiple tapemarks or\n" "filemarks are read; it continues processing until the SCSI tape drive says\n" "there is no more data on the tape). The resulting AWSTAPE output disk file,\n" "when specified for the filename on a Hercules tape device configuration\n" "statement, can then be used instead in order for the Hercules guest O/S to\n" "read the exact same data without having to have a SCSI tape drive physically\n" "attached to the host system. This allows you to easily transfer SCSI tape data\n" "to other systems that may not have SCSI tape drives attached to them.\n\n" "The possible return codes and their meaning are:\n\n" " %2d Successful completion.\n" " %2d Invalid arguments or no arguments given.\n" " %2d Unable to open SCSI tape drive device file.\n" " %2d Unable to open AWSTAPE disk file.\n" " %2d Unrecoverable I/O error setting variable length block\n" " processing for SCSI tape device.\n" " %2d Unrecoverable I/O error rewinding SCSI tape device.\n" " %2d Unrecoverable I/O error obtaining status of SCSI device.\n" " %2d Unrecoverable I/O error reading block header\n" " from AWSTAPE disk file.\n" " %2d AWSTAPE block size too large.\n" " %2d Unrecoverable I/O error reading data block.\n" " %2d Unrecoverable I/O error writing tapemark.\n" " %2d Unrecoverable I/O error writing block header\n" " to AWSTAPE disk file.\n" " %2d Unrecoverable I/O error writing data block.\n" "\n" ) ,RC_SUCCESS ,RC_ERROR_BAD_ARGUMENTS ,RC_ERROR_OPENING_SCSI_DEVICE ,RC_ERROR_OPENING_AWS_FILE ,RC_ERROR_SETTING_SCSI_VARBLK_PROCESSING ,RC_ERROR_REWINDING_SCSI ,RC_ERROR_OBTAINING_SCSI_STATUS ,RC_ERROR_READING_AWS_HEADER ,RC_ERROR_AWSTAPE_BLOCK_TOO_LARGE ,RC_ERROR_READING_DATA ,RC_ERROR_WRITING_TAPEMARK ,RC_ERROR_WRITING_OUTPUT_AWS_HEADER_BLOCK ,RC_ERROR_WRITING_DATA ); } /* end function print_usage */ /*-------------------------------------------------------------------*/ /* Subroutine to obtain SCSI tape status... */ /* */ /* Return value: 0 == normal */ /* +1 == end-of-tape */ /* -1 == error */ /*-------------------------------------------------------------------*/ static int obtain_status (char *devname, int devfd, struct mtget* mtget) { int rc; /* Return code */ rc = ioctl_tape (devfd, MTIOCGET, (char*)mtget); if (rc < 0) { if (1 && EIO == errno && (0 || GMT_EOD( mtget->mt_gstat ) || GMT_EOT( mtget->mt_gstat ) ) ) return +1; printf (_("HHCTC016E Error reading status of %s: rc=%d, errno=%d: %s\n"), devname, rc, errno, strerror(errno)); return -1; } if (GMT_EOD( mtget->mt_gstat ) || GMT_EOT( mtget->mt_gstat )) return +1; return 0; } /* end function obtain_status */ /*-------------------------------------------------------------------*/ /* Read a block from SCSI tape */ /*-------------------------------------------------------------------*/ int read_scsi_tape (int devfd, void *buf, size_t bufsize, struct mtget* mtget) { int rc; int save_errno; len = read_tape (devfd, buf, bufsize); if (len < 0) { /* Determine whether end-of-tape has been read */ save_errno = errno; ASSERT( devnamein ); rc = obtain_status (devnamein, devfd, mtget); if (rc == +1) { printf (_("HHCTC011I End of tape.\n")); errno = save_errno; return(-1); } printf (_("HHCTC008E Error reading %s: errno=%d: %s\n"), devnamein, errno, strerror(errno)); EXIT( RC_ERROR_READING_DATA ); } return(len); } /* end function read_scsi_tape */ /*-------------------------------------------------------------------*/ /* Read a block from AWSTAPE disk file */ /*-------------------------------------------------------------------*/ int read_aws_disk (int diskfd, void *buf, size_t bufsize) { AWSTAPE_BLKHDR awshdr; /* AWSTAPE block header */ int rc; unsigned int count_read = 0; unsigned int blksize; int end_block; BYTE *bufptr = buf; while (1) { /* Read block header */ rc = read (diskfd, &awshdr, sizeof(AWSTAPE_BLKHDR)); if (rc == 0) { printf (_("HHCTC018I End of AWSTAPE input file.\n")); return (-1); } if (rc < (int)sizeof(AWSTAPE_BLKHDR)) { printf (_("HHCTC019E Error reading AWSTAPE header from %s: rc=%d, errno=%d: %s\n"), filenamein, rc, errno, strerror(errno)); EXIT( RC_ERROR_READING_AWS_HEADER ); } /* end if(rc) */ /* Interpret the block header */ blksize = ((int)awshdr.curblkl[1] << 8) + awshdr.curblkl[0]; end_block = (awshdr.flags1 & AWSTAPE_FLAG1_ENDREC) != 0; /* If this is a tapemark, return immediately */ if (blksize == 0) return (0); /* Check maximum block length */ if ((count_read + blksize) > bufsize) { printf (_("HHCTC020E AWSTAPE block too large on %s: block size=%d, maximum=%d\n"), filenamein, count_read+blksize, (int)bufsize); EXIT( RC_ERROR_AWSTAPE_BLOCK_TOO_LARGE ); } /* end if(count) */ /* Read data block */ rc = read (diskfd, bufptr, blksize); if (rc < (int)blksize) { printf (_("HHCTC021E Error reading data block from %s: rc=%d, errno=%d: %s\n"), filenamein, rc, errno, strerror(errno)); EXIT( RC_ERROR_READING_DATA ); } /* end if(rc) */ bufptr += blksize; count_read += blksize; if (end_block) break; } return(count_read); } /* end function read_aws_disk */ /*-------------------------------------------------------------------*/ /* Write a block to SCSI tape */ /*-------------------------------------------------------------------*/ int write_scsi_tape (int devfd, void *buf, size_t len) { int rc; rc = write_tape (devfd, buf, len); if (rc < (int)len) { printf (_("HHCTC022E Error writing data block to %s: rc=%d, errno=%d: %s\n"), devnameout, rc, errno, strerror(errno)); EXIT( RC_ERROR_WRITING_DATA ); } /* end if(rc) */ bytes_written += rc; return(rc); } /* end function write_scsi_tape */ /*-------------------------------------------------------------------*/ /* Write a block to AWSTAPE disk file */ /*-------------------------------------------------------------------*/ int write_aws_disk (int diskfd, void *buf, size_t len) { AWSTAPE_BLKHDR awshdr; /* AWSTAPE block header */ int rc; /* Build the block header */ awshdr.curblkl[0] = len & 0xFF; awshdr.curblkl[1] = ( len >> 8 ) & 0xFF; awshdr.prvblkl[0] = prevlen & 0xFF; awshdr.prvblkl[1] = ( prevlen >> 8 ) & 0xFF; awshdr.flags1 = 0 | AWSTAPE_FLAG1_NEWREC | AWSTAPE_FLAG1_ENDREC ; awshdr.flags2 = 0; /* Write block header to output file */ rc = write (diskfd, &awshdr, sizeof(AWSTAPE_BLKHDR)); if (rc < (int)sizeof(AWSTAPE_BLKHDR)) { printf (_("HHCTC013E Error writing AWSTAPE header on %s: rc=%d, errno=%d: %s\n"), filenameout, rc, errno, strerror(errno)); EXIT( RC_ERROR_WRITING_OUTPUT_AWS_HEADER_BLOCK ); } /* end if(rc) */ bytes_written += rc; /* Write data block to output file */ rc = write (diskfd, buf, len); if (rc < (int)len) { printf (_("HHCTC014E Error writing data block to %s: rc=%d, errno=%d: %s\n"), filenameout, rc, errno, strerror(errno)); EXIT( RC_ERROR_WRITING_DATA ); } /* end if(rc) */ bytes_written += rc; return(rc); } /* end function write_aws_disk */ /*-------------------------------------------------------------------*/ /* Write a tapemark to SCSI tape */ /*-------------------------------------------------------------------*/ int write_tapemark_scsi_tape (int devfd) { struct mtop opblk; /* Area for MTIOCTOP ioctl */ int rc; opblk.mt_op = MTWEOF; opblk.mt_count = 1; rc = ioctl_tape (devfd, MTIOCTOP, (char*)&opblk); if (rc < 0) { printf (_("HHCTC023E Error writing tapemark on %s: rc=%d, errno=%d: %s\n"), devnameout, rc, errno, strerror(errno)); EXIT( RC_ERROR_WRITING_TAPEMARK ); } return(rc); } /* end function write_tapemark_scsi_tape */ /*-------------------------------------------------------------------*/ /* Write a tapemark to AWSTAPE disk file */ /*-------------------------------------------------------------------*/ int write_tapemark_aws_disk (int diskfd) { AWSTAPE_BLKHDR awshdr; /* AWSTAPE block header */ int rc; /* Build block header for tape mark */ awshdr.curblkl[0] = 0; awshdr.curblkl[1] = 0; awshdr.prvblkl[0] = prevlen & 0xFF; awshdr.prvblkl[1] = ( prevlen >> 8 ) & 0xFF; awshdr.flags1 = AWSTAPE_FLAG1_TAPEMARK; awshdr.flags2 = 0; /* Write block header to output file */ rc = write (diskfd, &awshdr, sizeof(AWSTAPE_BLKHDR)); if (rc < (int)sizeof(AWSTAPE_BLKHDR)) { printf (_("HHCTC010E Error writing tapemark on %s: rc=%d, errno=%d, %s\n"), filenameout, rc, errno, strerror(errno)); EXIT( RC_ERROR_WRITING_TAPEMARK ); } /* end if(rc) */ bytes_written += rc; return(rc); } /* end function write_tapemark_aws_disk */ /*-------------------------------------------------------------------*/ /* TAPECOPY main entry point */ /*-------------------------------------------------------------------*/ int main (int argc, char *argv[]) { int rc; /* Return code */ int i; /* Array subscript */ int devfd; /* Tape file descriptor */ int diskfd = -1; /* Disk file descriptor */ int fileno; /* Tape file number */ int blkcount; /* Block count */ int totalblks = 0; /* Block count */ int minblksz; /* Minimum block size */ int maxblksz; /* Maximum block size */ struct mtop opblk; /* Area for MTIOCTOP ioctl */ long density; /* Tape density code */ BYTE labelrec[81]; /* Standard label (ASCIIZ) */ int64_t bytes_read; /* Bytes read from i/p file */ int64_t file_bytes; /* Byte count for curr file */ char pathname[MAX_PATH]; /* file name in host format */ struct mtget mtget; /* Area for MTIOCGET ioctl */ #if defined(EXTERNALGUI) struct mtpos mtpos; /* Area for MTIOCPOS ioctl */ int is3590 = 0; /* 1 == 3590, 0 == 3480/3490 */ #endif /*defined(EXTERNALGUI)*/ INITIALIZE_UTILITY("tapecopy"); /* Display the program identification message */ display_version (stderr, "Hercules tape copy program ", FALSE); /* The first argument is the input file name (either AWS disk file or SCSI tape device) */ if ((argc < 2) || (argv[1] == NULL)) { print_usage(); EXIT( RC_ERROR_BAD_ARGUMENTS ); return(0); /* Make gcc -Wall happy */ } if (0 || ( strlen( argv[1] ) > 5 && strnfilenamecmp( argv[1], "/dev/", 5 ) == 0 ) || ( strlen( argv[1] ) > 4 && strnfilenamecmp( argv[1], "\\\\.\\", 4 ) == 0 ) ) { devnamein = argv[1]; filenamein = NULL; } else { filenamein = argv[1]; devnamein = NULL; } /* The second argument is the output file name (either AWS disk file or SCSI tape device) */ if (argc > 2 && argv[2] ) { if (0 || ( strlen( argv[2] ) > 5 && strnfilenamecmp( argv[2], "/dev/", 5 ) == 0 ) || ( strlen( argv[2] ) > 4 && strnfilenamecmp( argv[2], "\\\\.\\", 4 ) == 0 ) ) { devnameout = argv[2]; filenameout = NULL; } else { filenameout = argv[2]; devnameout = NULL; } } else { print_usage(); EXIT( RC_ERROR_BAD_ARGUMENTS ); } /* Check input arguments and disallow tape-to-tape or disk-to-disk copy */ if ((!devnamein && !devnameout) || (!filenamein && !filenameout)) { print_usage(); EXIT( RC_ERROR_BAD_ARGUMENTS ); } /* Open the SCSI tape device */ if (devnamein) { hostpath( pathname, devnamein, sizeof(pathname) ); devfd = open_tape (pathname, O_RDONLY|O_BINARY); } else // (devnameout) { hostpath( pathname, devnameout, sizeof(pathname) ); devfd = open_tape (pathname, O_RDWR|O_BINARY); } if (devfd < 0) { printf (_("HHCTC001E Error opening %s: errno=%d: %s\n"), (devnamein ? devnamein : devnameout), errno, strerror(errno)); EXIT( RC_ERROR_OPENING_SCSI_DEVICE ); } usleep(50000); /* Set the tape device to process variable length blocks */ opblk.mt_op = MTSETBLK; opblk.mt_count = 0; rc = ioctl_tape (devfd, MTIOCTOP, (char*)&opblk); if (rc < 0) { printf (_("HHCTC005E Error setting attributes for %s: rc=%d, errno=%d: %s\n"), (devnamein ? devnamein : devnameout), rc, errno, strerror(errno)); EXIT( RC_ERROR_SETTING_SCSI_VARBLK_PROCESSING ); } usleep(50000); /* Rewind the tape to the beginning */ opblk.mt_op = MTREW; opblk.mt_count = 1; rc = ioctl_tape (devfd, MTIOCTOP, (char*)&opblk); if (rc < 0) { printf (_("HHCTC006E Error rewinding %s: rc=%d, errno=%d: %s\n"), (devnamein ? devnamein : devnameout), rc, errno, strerror(errno)); EXIT( RC_ERROR_REWINDING_SCSI ); } usleep(50000); /* Obtain the tape status */ rc = obtain_status ((devnamein ? devnamein : devnameout), devfd, &mtget); if (rc < 0) EXIT( RC_ERROR_OBTAINING_SCSI_STATUS ); /* Display tape status information */ for (i = 0; tapeinfo[i].t_type != 0 && tapeinfo[i].t_type != mtget.mt_type; i++); if (tapeinfo[i].t_name) printf (_("HHCTC003I %s device type: %s\n"), (devnamein ? devnamein : devnameout), tapeinfo[i].t_name); else printf (_("HHCTC003I %s device type: 0x%lX\n"), (devnamein ? devnamein : devnameout), mtget.mt_type); density = (mtget.mt_dsreg & MT_ST_DENSITY_MASK) >> MT_ST_DENSITY_SHIFT; for (i = 0; densinfo[i].t_type != 0 && densinfo[i].t_type != density; i++); if (densinfo[i].t_name) printf (_("HHCTC004I %s tape density: %s\n"), (devnamein ? devnamein : devnameout), densinfo[i].t_name); else printf (_("HHCTC004I %s tape density code: 0x%lX\n"), (devnamein ? devnamein : devnameout), density); if (mtget.mt_gstat != 0) print_status ((devnamein ? devnamein : devnameout), mtget.mt_gstat); /* Open the disk file */ if (filenamein) { hostpath( pathname, filenamein, sizeof(pathname) ); diskfd = open (pathname, O_RDONLY | O_BINARY); } else { hostpath( pathname, filenameout, sizeof(pathname) ); diskfd = open (pathname, O_WRONLY | O_CREAT | O_BINARY, S_IRUSR | S_IWUSR | S_IRGRP); } if (diskfd < 0) { printf (_("HHCTC007E Error opening %s: errno=%d: %s\n"), (filenamein ? filenamein : filenameout), errno, strerror(errno)); EXIT( RC_ERROR_OPENING_AWS_FILE ); } /* Copy blocks from input to output */ fileno = 1; blkcount = 0; totalblks = 0; minblksz = 0; maxblksz = 0; len = 0; bytes_read = 0; bytes_written = 0; file_bytes = 0; #if defined(EXTERNALGUI) // Notify the GUI of the high-end of the copy-progress range... if ( extgui ) { // Retrieve BOT block-id... VERIFY( 0 == ioctl_tape( devfd, MTIOCPOS, (char*)&mtpos ) ); is3590 = ((mtpos.mt_blkno & 0x7F000000) != 0x01000000) ? 1 : 0; if (!is3590) { // The seg# portion the SCSI tape physical // block-id number values ranges from 1 to 95... fprintf( stderr, "BLKS=%d\n", 95 ); } else { // FIXME: 3590s (e.g. Magstar) use 32-bit block addressing, // and thus its block-id does not contain a seg# value, so // we must use some other technique. For now, we'll simply // presume the last block on the tape is block# 0x003FFFFF // (just to keep things simple). fprintf( stderr, "BLKS=%d\n", 0x003FFFFF ); } // Init time of last issued progress message prev_progress_time = time( NULL ); } #endif /*defined(EXTERNALGUI)*/ /* Perform the copy... */ while (1) { #if defined(EXTERNALGUI) /* Issue a progress message every few seconds... */ if ( extgui ) { if ( ( curr_progress_time = time( NULL ) ) >= ( prev_progress_time + PROGRESS_INTERVAL_SECS ) ) { prev_progress_time = curr_progress_time; if ( ioctl_tape( devfd, MTIOCPOS, (char*)&mtpos ) == 0 ) { if (!is3590) fprintf( stderr, "BLK=%ld\n", (mtpos.mt_blkno >> 24) & 0x0000007F ); else fprintf( stderr, "BLK=%ld\n", mtpos.mt_blkno ); } } } #endif /*defined(EXTERNALGUI)*/ /* Save previous block length */ prevlen = len; /* Read a block */ if (devnamein) len = read_scsi_tape(devfd, buf, sizeof(buf), &mtget); else len = read_aws_disk(diskfd, buf, sizeof(buf)); /* If returned with -1, end of tape; errors are handled by the read functions themselves */ if (len < 0) break; /* Check for tape mark */ if (len == 0) { /* Write tape mark to output file */ if (filenameout) write_tapemark_aws_disk(diskfd); else write_tapemark_scsi_tape(devfd); /* Print summary of current file */ if (blkcount) { ASSERT( file_bytes ); // (sanity check) printf (_("HHCTC009I File %u: Blocks=%u, Bytes=%"I64_FMT"d, Block size min=%u, " "max=%u, avg=%u\n"), fileno, blkcount, file_bytes, minblksz, maxblksz, (int)file_bytes/blkcount); } else { ASSERT( !file_bytes ); // (sanity check) } /* Show the 'tapemark' AFTER the above file summary since that's the actual physical sequence of events; i.e. the file data came first THEN it was followed by a tapemark */ printf(_(" (tapemark)\n")); // (align past HHCmsg#) /* Reset counters for next file */ if (blkcount) fileno++; minblksz = 0; maxblksz = 0; blkcount = 0; file_bytes = 0; continue; } /* Count blocks and block sizes */ blkcount++; totalblks++; bytes_read += len; file_bytes += len; if (len > maxblksz) maxblksz = len; if (minblksz == 0 || len < minblksz) minblksz = len; /* Print standard labels */ if (1 && blkcount < 4 && len == 80 && (0 || memcmp( buf, vollbl, 3 ) == 0 || memcmp( buf, hdrlbl, 3 ) == 0 || memcmp( buf, eoflbl, 3 ) == 0 || memcmp( buf, eovlbl, 3 ) == 0 ) ) { for (i=0; i < 80; i++) labelrec[i] = guest_to_host(buf[i]); labelrec[i] = '\0'; printf (_("HHCTC012I %s\n"), labelrec); } else { ASSERT(blkcount); #if defined(EXTERNALGUI) if ( !extgui ) #endif printf( _("File %u: Block %u\r"), fileno, blkcount ); } /* Write block to output file */ if (filenameout) write_aws_disk(diskfd, buf, len); else write_scsi_tape(devfd, buf, len); } /* end while */ /* Print run totals, close files, and exit... */ #define ONE_MEGABYTE ( 1024 * 1024 ) #define HALF_MEGABYTE ( ONE_MEGABYTE / 2 ) printf ( _( "HHCTC000I Successful completion;\n" " Bytes read: %"I64_FMT"d (%3.1f MB), Blocks=%u, avg=%u\n" ) , bytes_read ,(double) ( bytes_read + HALF_MEGABYTE ) / (double) ONE_MEGABYTE ,totalblks ,totalblks ? (int)bytes_read/totalblks : -1 ); printf ( _( " Bytes written: %"I64_FMT"d (%3.1f MB)\n" ) , bytes_written ,(double) ( bytes_written + HALF_MEGABYTE ) / (double) ONE_MEGABYTE ); close (diskfd); /* Rewind the tape back to the beginning again before exiting */ opblk.mt_op = MTREW; opblk.mt_count = 1; rc = ioctl_tape (devfd, MTIOCTOP, (char*)&opblk); if (rc < 0) { printf (_("HHCTC006E Error rewinding %s: rc=%d, errno=%d: %s\n"), (devnamein ? devnamein : devnameout), rc, errno, strerror(errno)); EXIT( RC_ERROR_REWINDING_SCSI ); } close_tape (devfd); EXIT( RC_SUCCESS ); return(0); /* Make -Wall happy */ } /* end function main */ #endif /* defined(OPTION_SCSI_TAPE) */ hercules-3.07/tapedev.c000644 000765 000765 00000256770 11321734033 016555 0ustar00jmaynardjmaynard000000 000000 /* TAPEDEV.C (c) Copyright Roger Bowler, 1999-2009 */ /* Hercules Tape Device Handler */ /* Original Author: Roger Bowler */ /* Prime Maintainer: Ivan Warren */ /* Secondary Maintainer: "Fish" (David B. Trout) */ // $Id: tapedev.c 5587 2009-12-31 15:05:57Z rbowler $ /*-------------------------------------------------------------------*/ /* This module contains device handling functions for emulated */ /* magnetic tape devices for the Hercules ESA/390 emulator. */ /*-------------------------------------------------------------------*/ /* Messages issued by the TAPEDEV.C module are prefixed HHCTA0nn */ /* CCW processing functions have been moved to module TAPECCW.C */ /* */ /* Five emulated tape formats are supported: */ /* */ /* 1. AWSTAPE This is the format used by the P/390. */ /* The entire tape is contained in a single flat file. */ /* A tape block consists of one or more block segments. */ /* Each block segment is preceded by a 6-byte header. */ /* Files are separated by tapemarks, which consist */ /* of headers with zero block length. */ /* AWSTAPE files are readable and writable. */ /* */ /* Support for AWSTAPE is in the "AWSTAPE.C" member. */ /* */ /* 2. OMATAPE This is the Optical Media Attach device format. */ /* Each physical file on the tape is represented by */ /* a separate flat file. The collection of files that */ /* make up the physical tape is obtained from an ASCII */ /* text file called the "tape description file", whose */ /* file name is always tapes/xxxxxx.tdf (where xxxxxx */ /* is the volume serial number of the tape). */ /* Three formats of tape files are supported: */ /* * FIXED files contain fixed length EBCDIC blocks */ /* with no headers or delimiters. The block length */ /* is specified in the TDF file. */ /* * TEXT files contain variable length ASCII blocks */ /* delimited by carriage return line feed sequences. */ /* The data is translated to EBCDIC by this module. */ /* * HEADER files contain variable length blocks of */ /* EBCDIC data prefixed by a 16-byte header. */ /* The TDF file and all of the tape files must reside */ /* reside under the same directory which is normally */ /* on CDROM but can be on disk. */ /* OMATAPE files are supported as read-only media. */ /* */ /* OMATAPE tape Support is in the "OMATAPE.C" member. */ /* */ /* 3. SCSITAPE This format allows reading and writing of 4mm or */ /* 8mm DAT tape, 9-track open-reel tape, or 3480-type */ /* cartridge on an appropriate SCSI-attached drive. */ /* All SCSI tapes are processed using the generalized */ /* SCSI tape driver (st.c) which is controlled using */ /* the MTIOCxxx set of IOCTL commands. */ /* PROGRAMMING NOTE: the 'tape' portability macros for */ /* physical (SCSI) tapes MUST be used for all tape i/o! */ /* */ /* SCSI tape Support is in the "SCSITAPE.C" member. */ /* */ /* 4. HET This format is based on the AWSTAPE format but has */ /* been extended to support compression. Since the */ /* basic file format has remained the same, AWSTAPEs */ /* can be read/written using the HET routines. */ /* */ /* Support for HET is in the "HETTAPE.C" member. */ /* */ /* 5. FAKETAPE This is the format used by Fundamental Software */ /* on their FLEX-ES systems. It it similar to the AWS */ /* format. The entire tape is contained in a single */ /* flat file. A tape block is preceded by a 12-ASCII- */ /* hex-characters header which indicate the size of */ /* the previous and next blocks. Files are separated */ /* by tapemarks which consist of headers with a zero */ /* current block length. FakeTapes are both readable */ /* and writable. */ /* */ /* Support for FAKETAPE is in the "FAKETAPE.C" member. */ /* */ /*-------------------------------------------------------------------*/ /*-------------------------------------------------------------------*/ /* Additional credits: */ /* 3480 commands contributed by Jan Jaeger */ /* Sense byte improvements by Jan Jaeger */ /* 3480 Read Block ID and Locate CCWs by Brandon Hill */ /* Unloaded tape support by Brandon Hill v209*/ /* HET format support by Leland Lucius v209*/ /* JCS - minor changes by John Summerfield 2003*/ /* PERFORM SUBSYSTEM FUNCTION / CONTROL ACCESS support by */ /* Adrian Trenkwalder (with futher enhancements by Fish) */ /* **INCOMPLETE** 3590 support by Fish (David B. Trout) */ /*-------------------------------------------------------------------*/ /*-------------------------------------------------------------------*/ /* Reference information: */ /* SC53-1200 S/370 and S/390 Optical Media Attach/2 User's Guide */ /* SC53-1201 S/370 and S/390 Optical Media Attach/2 Technical Ref */ /* SG24-2506 IBM 3590 Tape Subsystem Technical Guide */ /* GA32-0331 IBM 3590 Hardware Reference */ /* GA32-0329 IBM 3590 Introduction and Planning Guide */ /* SG24-2594 IBM 3590 Multiplatform Implementation */ /* ANSI INCITS 131-1994 (R1999) SCSI-2 Reference */ /* GA32-0127 IBM 3490E Hardware Reference */ /* GC35-0152 EREP Release 3.5.0 Reference */ /* SA22-7204 ESA/390 Common I/O-Device Commands */ /*-------------------------------------------------------------------*/ #include "hstdinc.h" #include "hercules.h" /* need Hercules control blocks */ #include "tapedev.h" /* Main tape handler header file */ //#define ENABLE_TRACING_STMTS // (Fish: DEBUGGING) #ifdef ENABLE_TRACING_STMTS #if !defined(DEBUG) #warning DEBUG required for ENABLE_TRACING_STMTS #endif // (TRACE, ASSERT, and VERIFY macros are #defined in hmacros.h) #else #undef TRACE #undef ASSERT #undef VERIFY #define TRACE 1 ? ((void)0) : logmsg #define ASSERT(a) #define VERIFY(a) ((void)(a)) #endif /*-------------------------------------------------------------------*/ #if defined(WIN32) && defined(OPTION_DYNAMIC_LOAD) && !defined(HDL_USE_LIBTOOL) && !defined(_MSVC_) SYSBLK *psysblk; #define sysblk (*psysblk) #endif /*-------------------------------------------------------------------*/ DEVHND tapedev_device_hndinfo = { &tapedev_init_handler, /* Device Initialisation */ &tapedev_execute_ccw, /* Device CCW execute */ &tapedev_close_device, /* Device Close */ &tapedev_query_device, /* Device Query */ NULL, /* Device Start channel pgm */ NULL, /* Device End channel pgm */ NULL, /* Device Resume channel pgm */ NULL, /* Device Suspend channel pgm */ NULL, /* Device Read */ NULL, /* Device Write */ NULL, /* Device Query used */ NULL, /* Device Reserve */ NULL, /* Device Release */ NULL, /* Device Attention */ TapeImmedCommands, /* Immediate CCW Codes */ NULL, /* Signal Adapter Input */ NULL, /* Signal Adapter Output */ NULL, /* Hercules suspend */ NULL /* Hercules resume */ }; /*-------------------------------------------------------------------*/ /* Libtool static name colision resolution... */ /* Note: lt_dlopen will look for symbol & modulename_LTX_symbol */ /*-------------------------------------------------------------------*/ #if !defined(HDL_BUILD_SHARED) && defined(HDL_USE_LIBTOOL) #define hdl_ddev hdt3420_LTX_hdl_ddev #define hdl_depc hdt3420_LTX_hdl_depc #define hdl_reso hdt3420_LTX_hdl_reso #define hdl_init hdt3420_LTX_hdl_init #define hdl_fini hdt3420_LTX_hdl_fini #endif /*-------------------------------------------------------------------*/ #if defined(OPTION_DYNAMIC_LOAD) HDL_DEPENDENCY_SECTION; { HDL_DEPENDENCY ( HERCULES ); HDL_DEPENDENCY ( DEVBLK ); HDL_DEPENDENCY ( SYSBLK ); } END_DEPENDENCY_SECTION /*-------------------------------------------------------------------*/ HDL_DEVICE_SECTION; { HDL_DEVICE ( 3410, tapedev_device_hndinfo ); HDL_DEVICE ( 3411, tapedev_device_hndinfo ); HDL_DEVICE ( 3420, tapedev_device_hndinfo ); HDL_DEVICE ( 3422, tapedev_device_hndinfo ); HDL_DEVICE ( 3430, tapedev_device_hndinfo ); HDL_DEVICE ( 3480, tapedev_device_hndinfo ); HDL_DEVICE ( 3490, tapedev_device_hndinfo ); HDL_DEVICE ( 3590, tapedev_device_hndinfo ); HDL_DEVICE ( 8809, tapedev_device_hndinfo ); HDL_DEVICE ( 9347, tapedev_device_hndinfo ); HDL_DEVICE ( 9348, tapedev_device_hndinfo ); } END_DEVICE_SECTION /*-------------------------------------------------------------------*/ #if defined(WIN32) && !defined(HDL_USE_LIBTOOL) && !defined(_MSVC_) #undef sysblk HDL_RESOLVER_SECTION; { HDL_RESOLVE_PTRVAR ( psysblk, sysblk ); } END_RESOLVER_SECTION #endif // defined(WIN32) && !defined(HDL_USE_LIBTOOL) && !defined(_MSVC_) #endif // defined(OPTION_DYNAMIC_LOAD) /*-------------------------------------------------------------------*/ /* (see 'tapedev.h' for layout of TAPEMEDIA_HANDLER structure) */ /*-------------------------------------------------------------------*/ TAPEMEDIA_HANDLER tmh_aws = { &generic_tmhcall, &open_awstape, &close_awstape, &read_awstape, &write_awstape, &rewind_awstape, &bsb_awstape, &fsb_awstape, &bsf_awstape, &fsf_awstape, &write_awsmark, &sync_awstape, &no_operation, // (DSE) ZZ FIXME: not coded yet &no_operation, // (ERG) &is_tapeloaded_filename, &passedeot_awstape, &readblkid_virtual, &locateblk_virtual }; /*-------------------------------------------------------------------*/ TAPEMEDIA_HANDLER tmh_het = { &generic_tmhcall, &open_het, &close_het, &read_het, &write_het, &rewind_het, &bsb_het, &fsb_het, &bsf_het, &fsf_het, &write_hetmark, &sync_het, &no_operation, // (DSE) ZZ FIXME: not coded yet &no_operation, // (ERG) &is_tapeloaded_filename, &passedeot_het, &readblkid_virtual, &locateblk_virtual }; /*-------------------------------------------------------------------*/ TAPEMEDIA_HANDLER tmh_fake = { &generic_tmhcall, &open_faketape, &close_faketape, &read_faketape, &write_faketape, &rewind_faketape, &bsb_faketape, &fsb_faketape, &bsf_faketape, &fsf_faketape, &write_fakemark, &sync_faketape, &no_operation, // (DSE) ZZ FIXME: not coded yet &no_operation, // (ERG) &is_tapeloaded_filename, &passedeot_faketape, &readblkid_virtual, &locateblk_virtual }; /*-------------------------------------------------------------------*/ TAPEMEDIA_HANDLER tmh_oma = { &generic_tmhcall, &open_omatape, &close_omatape, &read_omatape, &write_READONLY5, // WRITE &rewind_omatape, &bsb_omatape, &fsb_omatape, &bsf_omatape, &fsf_omatape, &write_READONLY, // WTM &write_READONLY, // SYNC &write_READONLY, // DSE &write_READONLY, // ERG &is_tapeloaded_filename, &return_false1, // passedeot &readblkid_virtual, &locateblk_virtual }; /*-------------------------------------------------------------------*/ #if defined(OPTION_SCSI_TAPE) TAPEMEDIA_HANDLER tmh_scsi = { &generic_tmhcall, &open_scsitape, &close_scsitape, &read_scsitape, &write_scsitape, &rewind_scsitape, &bsb_scsitape, &fsb_scsitape, &bsf_scsitape, &fsf_scsitape, &write_scsimark, &sync_scsitape, &dse_scsitape, &erg_scsitape, &is_tape_mounted_scsitape, &passedeot_scsitape, &readblkid_scsitape, &locateblk_scsitape }; #endif /* defined(OPTION_SCSI_TAPE) */ /*-------------------------------------------------------------------*/ /* Device-Type Initialization Table (DEV/CU MODEL, FEATURES, ETC) */ /*-------------------------------------------------------------------*/ /* PROGRAMMING NOTE: the MDR/OBR code (Device Characteristics bytes 40-41) are apparently CRITICALLY IMPORTANT for proper tape drive functioning for certain operating systems. If the bytes are not provided (set to zero) or are set incorrectly, certain operating systems end up using unusual/undesirable Mode Set values in their Channel Programs (such as x'20' Write Immediate for example). I only note it here because these two particular bytes are rather innocuous looking based upon their name and sparsely documented and largely unexplained values, thereby possibly misleading one into believing they weren't important and thus could be safely set to zero if their values were unknown. Rest assured they are NOT unimportant! Quite the opposite: the are, for some operating systems, CRITICALLY IMPORTANT and must NOT be returned as zeros. The following were obtained from "EREP Release 3.5.0 Reference" (GC35-0152-03): Model MDR OBR ------- ----- ----- 3480 0x41 0x80 3490 0x42 0x81 3590 0x46 0x83 3590 (3591/3490 EMU) 0x47 0x84 3590 (3590/3490 EMU) 0x48 0x85 NOTE: only models 3480, 3490 and 3590 support the RDC (Read Device Characteristics) channel command, and thus they're the only ones we must know the MDR/OBR codes for (since the MDR/OBR codes are only used in the RDC CCW and not anwhere else). That is to say, NONE of the Channel Commands (CCWs) that all the OTHER models happen to support have an MDR/OBR code anywhere in their data. Only models 3480, 3490 and 3590 have MDR/OBR codes buried in their CCW data (specifically the RDC CCW data). Also note that, at the moment, we do not support emulating 3590's or 3591's running in 3490 Emulation Mode (i.e. 3591/3490 EMU or 3590/3490 EMU). The user is free to use such a device with Herc- ules however, but if they do, it should be specified as a 3490. ---------------------------------------------------------------------*/ typedef struct DEVINITTAB /* Initialization values */ { U16 devtype; /* Device type */ BYTE devmodel; /* Device model number */ U16 cutype; /* Control unit type */ BYTE cumodel; /* Control unit model number */ U32 sctlfeat; /* Storage control features */ BYTE devclass; /* Device class code */ BYTE devtcode; /* Device type code */ BYTE MDR; /* Misc. Data Record ID */ BYTE OBR; /* Outboard Recorder ID */ int numdevid; /* #of SNSID bytes (see NOTE)*/ int numsense; /* #of SENSE bytes */ int haverdc; /* RDC Supported */ int displayfeat; /* Has LCD display */ } DEVINITTAB; DEVINITTAB DevInitTab[] = /* Initialization table */ { // PROGRAMMING NOTE: we currently do not support a #of Sense-ID bytes // value (numdevid) greater than 7 since our current channel-subsystem // design does not support the concept of hardware physical attachment // "Nodes" (i.e. separate control-unit, device and interface elements). // Supporting more than 7 bytes of Sense-ID information would require // support for Node Descriptors (ND) and Node Element Descriptors (NED) // and the associated commands (CCWs) to query them (Read Configuration // Data (0xFA) , Set Interface Identifier (0x73) and associated support // in the Read Subsystem Data (0x3E) command), which is vast overkill // and a complete waste of time given our current overly-simple channel // subsystem design. // //-------------------------------------------------------------------- // 3410/3411/3420/3422/3430/8809/9347/9348 //-------------------------------------------------------------------- // // devtype/mod cutype/mod sctlfeat cls typ MDR OBR sid sns rdc dsp { 0x3410,0x01, 0x3115,0x01, 0x00000000, 0, 0, 0, 0, 0, 9, 0, 0 }, { 0x3411,0x01, 0x3115,0x01, 0x00000000, 0, 0, 0, 0, 0, 9, 0, 0 }, { 0x3420,0x06, 0x3803,0x02, 0x00000000, 0, 0, 0, 0, 0, 24, 0, 0 }, // (DEFAULT: 3420) { 0x3422,0x01, 0x3422,0x01, 0x00000000, 0, 0, 0, 0, 7, 32, 0, 0 }, { 0x3430,0x01, 0x3422,0x01, 0x00000000, 0, 0, 0, 0, 7, 32, 0, 0 }, { 0x8809,0x01, 0x8809,0x01, 0x00000000, 0, 0, 0, 0, 0, 32, 0, 0 }, { 0x9347,0x01, 0x9347,0x01, 0x00000000, 0, 0, 0, 0, 7, 32, 0, 0 }, { 0x9348,0x01, 0x9348,0x01, 0x00000000, 0, 0, 0, 0, 7, 32, 0, 0 }, //-------------------------------------------------------------------- // 3480/3490/3590 //-------------------------------------------------------------------- // // PROGRAMMING NOTE: we currently do not support a #of Sense-ID bytes // value (numdevid) greater than 7 since our current channel-subsystem // design does not support the concept of hardware physical attachment // "Nodes" (i.e. separate control-unit, device and interface elements). // Supporting more than 7 bytes of Sense-ID information would require // support for Node Descriptors (ND) and Node Element Descriptors (NED) // and the associated commands (CCWs) to query them (Read Configuration // Data (0xFA) , Set Interface Identifier (0x73) and associated support // in the Read Subsystem Data (0x3E) command), which is vast overkill // and a complete waste of time given our current overly-simple channel // subsystem design. // // PROGRAMMING NOTE: if you change the below devtype/mod or cutype/mod // values, be sure to ALSO change tapeccws.c's READ CONFIGURATION DATA // (CCW opcode 0xFA) values as well! // // PROGRAMMING NOTE: the bit values of the 'sctlfeat' field are: // // ....40.. (unknown) // ....08.. Set Special Intercept Condition (SIC) supported // ....04.. Channel Path No-Operation supported (always // on if Library Attachment Facility installed) // ....02.. Logical Write-Protect supported (always on // if Read Device Characteristics is supported) // ....01.. Extended Buffered Log support enabled (if 64 // bytes of buffered log data, else 32 bytes) // ......80 Automatic Cartridge Loader installed/enabled // ......40 Improved Data Recording Capability (i.e. // compression support) installed/enabled // ......20 Suppress Volume Fencing // ......10 Library Interface online/enabled // ......08 Library Attachment Facility installed // ......04 (unknown) // // PROGRAMMING NOTE: the below "0x00004EC4" value for the 'sctlfeat' // field for Model 3590 was determined empirically on a real machine. // // devtype/mod cutype/mod sctlfeat cls typ MDR OBR sid sns rdc dsp { 0x3480,0x31, 0x3480,0x31, 0x000002C0, 0x80,0x80, 0x41,0x80, 7, 24, 1, 1 }, // 0x31 = D31 { 0x3490,0x50, 0x3490,0x50, 0x000002C0, 0x80,0x80, 0x42,0x81, 7, 32, 1, 1 }, // 0x50 = C10 { 0x3590,0x10, 0x3590,0x50, 0x00004EC4, 0x80,0x80, 0x46,0x83, 7, 32, 1, 1 }, // 0x10 = B1A, 0x50 = A50 { 0xFFFF,0xFF, 0xFFFF,0xFF, 0xFFFFFFFF, 0xFF,0xFF, 0xFF,0xFF, -1, -1, -1, -1 }, //**** END OF TABLE **** { 0x3420,0x06, 0x3803,0x02, 0x00000000, 0, 0, 0, 0, 0, 24, 0, 0 }, // (DEFAULT: 3420) }; /*-------------------------------------------------------------------*/ /* Initialize the device handler */ /*-------------------------------------------------------------------*/ int tapedev_init_handler (DEVBLK *dev, int argc, char *argv[]) { int rc; DEVINITTAB* pDevInitTab; /* Close current tape */ if(dev->fd>=0) { dev->tmh->close(dev); dev->fd=-1; } autoload_close(dev); dev->tdparms.displayfeat=0; /* Determine the control unit type and model number */ /* Support for 3490/3422/3430/8809/9347, etc.. */ if (!sscanf( dev->typname, "%hx", &dev->devtype )) dev->devtype = 0x3420; // PROGAMMING NOTE: we use hard-coded values from our DevInitTab // for virtual (non-SCSI) devices and, for the time being, for non- // virtual (SCSI) devices too. Once we add direct SCSI I/O support // we will need to add code to get this information directly from // the actual SCSI device itself. for ( pDevInitTab = &DevInitTab[0]; pDevInitTab->devtype != 0xFFFF && pDevInitTab->devtype != dev->devtype; pDevInitTab++ ); if (pDevInitTab->devtype == 0xFFFF) /* (entry not found?) */ { logmsg ( _("Unsupported device type specified %4.4x\n"), dev->devtype ); pDevInitTab++; /* (default entry; s/b same as 0x3420) */ pDevInitTab->devtype = dev->devtype; /* (don't know what else to do really) */ pDevInitTab->cutype = dev->devtype; /* (don't know what else to do really) */ } /* Allow SENSE ID for certain specific legacy devices if requested */ dev->numdevid = pDevInitTab->numdevid; // (default == from table) if (1 && sysblk.legacysenseid // (if option requested, AND is) && (0 // (for allowable legacy device) || 0x3410 == dev->devtype || 0x3411 == dev->devtype || 0x3420 == dev->devtype || 0x8809 == dev->devtype ) ) { dev->numdevid = 7; // (allow for this legacy device) } /* Initialize the Sense-Id bytes if needed... */ if (dev->numdevid > 0) { dev->devid[0] = 0xFF; dev->devid[1] = (pDevInitTab->cutype >> 8) & 0xFF; dev->devid[2] = (pDevInitTab->cutype >> 0) & 0xFF; dev->devid[3] = pDevInitTab->cumodel; dev->devid[4] = (pDevInitTab->devtype >> 8) & 0xFF; dev->devid[5] = (pDevInitTab->devtype >> 0) & 0xFF; dev->devid[6] = pDevInitTab->devmodel; /* Initialize the CIW information if needed... */ if (dev->numdevid > 7) { // PROGRAMMING NOTE: see note near 'DEVINITTAB' // struct definition regarding requirements for // supporting more than 7 bytes of SNSID info. memcpy (&dev->devid[8], "\x40\xFA\x00\xA0", 4); // CIW Read Configuration Data (0xFA) memcpy (&dev->devid[12], "\x41\x73\x00\x04", 4); // CIW Set Interface Identifier (0x73) memcpy (&dev->devid[16], "\x42\x3E\x00\x60", 4); // CIW Read Subsystem Data (0x3E) } } /* Initialize the Read Device Characteristics (RDC) bytes... */ if (pDevInitTab->haverdc) { dev->numdevchar = 64; memset (dev->devchar, 0, sizeof(dev->devchar)); memcpy (dev->devchar, dev->devid+1, 6); // Bytes 6-9: Subsystem Facilities... dev->devchar[6] = (pDevInitTab->sctlfeat >> 24) & 0xFF; dev->devchar[7] = (pDevInitTab->sctlfeat >> 16) & 0xFF; dev->devchar[8] = (pDevInitTab->sctlfeat >> 8) & 0xFF; dev->devchar[9] = (pDevInitTab->sctlfeat >> 0) & 0xFF; // Bytes 10/11: Device Class/Type ... dev->devchar[10] = pDevInitTab->devclass; dev->devchar[11] = pDevInitTab->devtcode; // Bytes 24-29: cutype/model & devtype/model ... // (Note: undocumented; determined empirically) dev->devchar[24] = (pDevInitTab->cutype >> 8) & 0xFF; dev->devchar[25] = (pDevInitTab->cutype >> 0) & 0xFF; dev->devchar[26] = pDevInitTab->cumodel; dev->devchar[27] = (pDevInitTab->devtype >> 8) & 0xFF; dev->devchar[28] = (pDevInitTab->devtype >> 0) & 0xFF; dev->devchar[29] = pDevInitTab->devmodel; // Bytes 40-41: MDR/OBR code... dev->devchar[40] = pDevInitTab->MDR; dev->devchar[41] = pDevInitTab->OBR; } /* Initialize other fields */ // dev->numdevid = pDevInitTab->numdevid; // (handled above) dev->numsense = pDevInitTab->numsense; dev->tdparms.displayfeat = pDevInitTab->displayfeat; dev->fenced = 0; // (always, initially) dev->SIC_active = 0; // (always, initially) dev->SIC_supported = 0; // (until we're sure) dev->forced_logging = 0; // (always, initially) #if defined( OPTION_TAPE_AUTOMOUNT ) dev->noautomount = 0; // (always, initially) #endif /* Initialize SCSI tape control fields */ #if defined(OPTION_SCSI_TAPE) dev->sstat = GMT_DR_OPEN(-1); dev->stape_getstat_sstat = GMT_DR_OPEN(-1); #endif /* Clear the DPA */ memset (dev->pgid, 0, sizeof(dev->pgid)); /* Clear Drive password - Adrian */ memset (dev->drvpwd, 0, sizeof(dev->drvpwd)); /* Request the channel to merge data chained write CCWs into a single buffer before passing data to the device handler */ dev->cdwmerge = 1; /* Tape is a syncio type 2 device */ dev->syncio = 2; /* ISW */ /* Build a 'clear' sense */ memset (dev->sense, 0, sizeof(dev->sense)); dev->sns_pending = 0; // Initialize the [non-SCSI] auto-loader... // PROGRAMMING NOTE: we don't [yet] know at this early stage // what type of tape device we're dealing with (SCSI (non-virtual) // or non-SCSI (virtual)) since 'mountnewtape' hasn't been called // yet (which is the function that determines which media handler // should be used and is the one that initializes dev->tapedevt) // The only thing we know (or WILL know once 'autoload_init' // is called) is whether or not there was a [non-SCSI] auto- // loader defined for the device. That's it and nothing more. autoload_init( dev, argc, argv ); // Was an auto-loader defined for this device? if ( !dev->als ) { // No. Just mount whatever tape there is (if any)... rc = mountnewtape( dev, argc, argv ); } else { // Yes. Try mounting the FIRST auto-loader slot... if ( (rc = autoload_mount_first( dev )) != 0 ) { // If that doesn't work, try subsequent slots... while ( dev->als && (rc = autoload_mount_next( dev )) != 0 ) { ; // (nop; just go on to next slot) } rc = dev->als ? rc : -1; } } if (dev->devchar[8] & 0x08) // SIC supported? dev->SIC_supported = 1; // remember that fact return rc; } /* end function tapedev_init_handler */ /*-------------------------------------------------------------------*/ /* Close the device */ /*-------------------------------------------------------------------*/ int tapedev_close_device ( DEVBLK *dev ) { autoload_close(dev); dev->tmh->close(dev); ASSERT( dev->fd < 0 ); dev->curfilen = 1; dev->nxtblkpos = 0; dev->prvblkpos = -1; dev->curblkrem = 0; dev->curbufoff = 0; dev->blockid = 0; dev->fenced = 0; return 0; } /* end function tapedev_close_device */ /*-------------------------------------------------------------------*/ /* Tape format determination REGEXPS. Used by gettapetype below */ /*-------------------------------------------------------------------*/ struct tape_format_entry /* (table layout) */ { char* fmtreg; /* A regular expression */ int fmtcode; /* the device code */ TAPEMEDIA_HANDLER* tmh; /* The media dispatcher */ char* descr; /* readable description */ char* short_descr; /* (same but shorter) */ }; /*-------------------------------------------------------------------*/ /* Tape format determination REGEXPS. Used by gettapetype below */ /*-------------------------------------------------------------------*/ struct tape_format_entry fmttab [] = /* (table itself) */ { /* This entry matches a filename ending with .aws */ #define AWSTAPE_FMTENTRY 0 #define DEFAULT_FMTENTRY AWSTAPE_FMTENTRY { "\\.aws$", TAPEDEVT_AWSTAPE, &tmh_aws, "AWS Format tape file", "AWS tape" }, /* This entry matches a filename ending with .het */ #define HETTAPE_FMTENTRY 1 { "\\.het$", TAPEDEVT_HETTAPE, &tmh_het, "Hercules Emulated Tape file", "HET tape" }, /* This entry matches a filename ending with .tdf */ #define OMATAPE_FMTENTRY 2 { "\\.tdf$", TAPEDEVT_OMATAPE, &tmh_oma, "Optical Media Attachment (OMA) tape", "OMA tape" }, /* This entry matches a filename ending with .fkt */ #define FAKETAPE_FMTENTRY 3 { "\\.fkt$", TAPEDEVT_FAKETAPE, &tmh_fake, "Flex FakeTape file", "FakeTape" }, #if defined(OPTION_SCSI_TAPE) /* This entry matches a filename starting with /dev/ */ #define SCSITAPE_FMTENTRY 4 { "^/dev/", TAPEDEVT_SCSITAPE, &tmh_scsi, "SCSI attached tape drive", "SCSI tape" }, #if defined(_MSVC_) /* (same idea but for Windows SCSI tape device names) */ #undef SCSITAPE_FMTENTRY #define SCSITAPE_FMTENTRY 5 { "^\\\\\\\\\\.\\\\\\w", TAPEDEVT_SCSITAPE, &tmh_scsi, "SCSI attached tape drive", "SCSI tape" }, #endif // _MSVC_ #endif // OPTION_SCSI_TAPE }; /*-------------------------------------------------------------------*/ /* gettapetype_byname determine tape device type by filename */ /*-------------------------------------------------------------------*/ /* returns fmttab entry# on success, -1 on error/unable to determine */ /*-------------------------------------------------------------------*/ int gettapetype_byname (DEVBLK *dev) { #if defined(HAVE_REGEX_H) || defined(HAVE_PCRE) regex_t regwrk; /* REGEXP work area */ regmatch_t regwrk2; /* REGEXP match area */ char errbfr[1024]; /* Working storage */ int i; /* Loop control */ #endif // HAVE_REGEX_H int rc; /* various rtns return codes */ /* Use the file name to determine the device type */ #if defined(HAVE_REGEX_H) || defined(HAVE_PCRE) for (i=0; i < (int)arraysize( fmttab ); i++) { rc = regcomp (®wrk, fmttab[i].fmtreg, REG_ICASE); if (rc < 0) { regerror (rc, ®wrk, errbfr, 1024); logmsg (_("HHCTA001E %4.4X: Unable to determine tape format type for %s: Internal error: Regcomp error %s on index %d\n"), dev->devnum, dev->filename, errbfr, i); return -1; } rc = regexec (®wrk, dev->filename, 1, ®wrk2, 0); if (rc < 0) { regerror (rc, ®wrk, errbfr, 1024); regfree ( ®wrk ); logmsg (_("HHCTA002E %4.4X: Unable to determine tape format type for %s: Internal error: Regexec error %s on index %d\n"), dev->devnum, dev->filename, errbfr, i); return -1; } regfree (®wrk); if (rc == 0) /* MATCH? */ return i; ASSERT( rc == REG_NOMATCH ); } #else // !HAVE_REGEX_H if (1 && (rc = strlen(dev->filename)) > 4 && (rc = strcasecmp( &dev->filename[rc-4], ".aws" )) == 0 ) { return AWSTAPE_FMTENTRY; } if (1 && (rc = strlen(dev->filename)) > 4 && (rc = strcasecmp( &dev->filename[rc-4], ".het" )) == 0 ) { return HETTAPE_FMTENTRY; } if (1 && (rc = strlen(dev->filename)) > 4 && (rc = strcasecmp( &dev->filename[rc-4], ".tdf" )) == 0 ) { return OMATAPE_FMTENTRY; } if (1 && (rc = strlen(dev->filename)) > 4 && (rc = strcasecmp( &dev->filename[rc-4], ".fkt" )) == 0 ) { return FAKETAPE_FMTENTRY; } #if defined(OPTION_SCSI_TAPE) if (1 && (rc = strlen(dev->filename)) > 5 && (rc = strncasecmp( dev->filename, "/dev/", 5 )) == 0 ) { if (strncasecmp( dev->filename+5, "st", 2 ) == 0) dev->stape_close_rewinds = 1; // (rewind at close) else dev->stape_close_rewinds = 0; // (otherwise don't) return SCSITAPE_FMTENTRY; } #if defined(_MSVC_) if (1 && strncasecmp(dev->filename, "\\\\.\\", 4) == 0 && *(dev->filename + 4) != 0 ) { return SCSITAPE_FMTENTRY; } #endif // _MSVC_ #endif // OPTION_SCSI_TAPE #endif // HAVE_REGEX_H return -1; /* -1 == "unable to determine" */ } /* end function gettapetype_byname */ /*-------------------------------------------------------------------*/ /* gettapetype_bydata determine tape device type by file data */ /*-------------------------------------------------------------------*/ /* returns fmttab entry# on success, -1 on error/unable to determine */ /*-------------------------------------------------------------------*/ int gettapetype_bydata (DEVBLK *dev) { char pathname[MAX_PATH]; /* file path in host format */ int rc; /* various rtns return codes */ /* Try to determine the type based on actual file contents */ hostpath( pathname, dev->filename, sizeof(pathname) ); rc = open ( pathname, O_RDONLY | O_BINARY ); if (rc >= 0) { BYTE hdr[6]; /* block header i/o buffer */ int fd = rc; /* save file descriptor */ /* Read the header. If bytes 0-3 are ASCII "0000", then the * tape is likely a Flex FakeTape. Otherwise if bytes 2-3 are * binary zero (x'0000'), it's likely an AWS type tape. If byte * 4 (first flag byte) has either of the ZLIB or BZIP2 flags on, * then it's a HET tape. Otherwise it's just an ordinary AWS tape. */ rc = read (fd, hdr, sizeof(hdr)); close(fd); if (rc >= 6) { /* Use the data to make the possible determination */ if (memcmp(hdr, "@TDF", 4) == 0) return OMATAPE_FMTENTRY; if (1 && hdr[0] == 0x30 /* "ASCII"-zero len prev block? */ && hdr[1] == 0x30 && hdr[2] == 0x30 && hdr[3] == 0x30 ) return FAKETAPE_FMTENTRY; /* Then obviously Flex FakeTape */ if (hdr[2] == 0 && hdr[3] == 0) /* 0 len prev blk? */ { if (hdr[4] & HETHDR_FLAGS1_TAPEMARK) /* If tapemark then */ return -1; /* can't tell type. */ if (hdr[4] & HETHDR_FLAGS1_COMPRESS || /* ZLIB or BZIP2 or */ hdr[5] & HETHDR_FLAGS2_COMPRESS) /* Bus-Tech ZLIB? */ return HETTAPE_FMTENTRY; /* Then HET format. */ else return AWSTAPE_FMTENTRY; /* Else default AWS */ } } } return -1; /* -1 == "unable to determine" */ } /* end function gettapetype_bydata */ /*-------------------------------------------------------------------*/ /* gettapetype determine tape device type */ /*-------------------------------------------------------------------*/ /* returns fmttab entry# on success, -1 on error/unable to determine */ /*-------------------------------------------------------------------*/ int gettapetype (DEVBLK *dev, char **short_descr) { char* descr; /* Device descr from fmttab */ int i; /* fmttab entry# */ i = gettapetype_byname( dev ); /* Get type based on name */ #if defined(OPTION_SCSI_TAPE) if (i != SCSITAPE_FMTENTRY) /* If not SCSI tape... */ #endif { int i2 = gettapetype_bydata( dev ); // Get type based on data.. if (i2 >= 0 && // If valid type by data, AND (i2 != AWSTAPE_FMTENTRY || // *not* AWS by data (or if it i != HETTAPE_FMTENTRY) // is, if it's not HET by name).. ) i = i2; // ..Use type based on data. } /* If file type still unknown, use a reasonable default value... */ if (i < 0) { i = DEFAULT_FMTENTRY; if (strcmp (dev->filename, TAPE_UNLOADED) != 0) logmsg (_("HHCTA003W %4.4X: Unable to determine tape format type for %s; presuming %s.\n"), dev->devnum, dev->filename, fmttab[i].short_descr ); } dev->tapedevt = fmttab[i].fmtcode; dev->tmh = fmttab[i].tmh; descr = fmttab[i].descr; *short_descr = fmttab[i].short_descr; if (strcmp (dev->filename, TAPE_UNLOADED) != 0) logmsg (_("HHCTA004I %4.4X: %s is a %s\n"), dev->devnum, dev->filename, descr); return 0; // (success) } /* end function gettapetype */ /*-------------------------------------------------------------------*/ /* The following table goes hand-in-hand with the 'enum' values */ /* that immediately follow. Used by 'mountnewtape' function. */ /*-------------------------------------------------------------------*/ PARSER ptab [] = { { "awstape", NULL }, { "idrc", "%d" }, { "compress", "%d" }, { "method", "%d" }, { "level", "%d" }, { "chunksize", "%d" }, { "maxsize", "%d" }, { "maxsizeK", "%d" }, { "maxsizeM", "%d" }, { "eotmargin", "%d" }, { "strictsize", "%d" }, { "readonly", "%d" }, { "ro", NULL }, { "noring", NULL }, { "rw", NULL }, { "ring", NULL }, { "deonirq", "%d" }, #if defined( OPTION_TAPE_AUTOMOUNT ) { "noautomount",NULL }, #endif { "--blkid-22", NULL }, { "--blkid-24", NULL }, /* (synonym for --blkid-22) */ { "--blkid-32", NULL }, { "--no-erg", NULL }, { NULL, NULL }, /* (end of table) */ }; /*-------------------------------------------------------------------*/ /* The following table goes hand-in-hand with the 'ptab' PARSER */ /* table immediately above. Used by 'mountnewtape' function. */ /*-------------------------------------------------------------------*/ enum { TDPARM_NONE, TDPARM_AWSTAPE, TDPARM_IDRC, TDPARM_COMPRESS, TDPARM_METHOD, TDPARM_LEVEL, TDPARM_CHKSIZE, TDPARM_MAXSIZE, TDPARM_MAXSIZEK, TDPARM_MAXSIZEM, TDPARM_EOTMARGIN, TDPARM_STRICTSIZE, TDPARM_READONLY, TDPARM_RO, TDPARM_NORING, TDPARM_RW, TDPARM_RING, TDPARM_DEONIRQ, #if defined( OPTION_TAPE_AUTOMOUNT ) TDPARM_NOAUTOMOUNT, #endif TDPARM_BLKID22, TDPARM_BLKID24, TDPARM_BLKID32, TDPARM_NOERG }; /*-------------------------------------------------------------------*/ /* mountnewtape -- mount a tape in the drive */ /*-------------------------------------------------------------------*/ /* */ /* Syntax: filename [options] */ /* */ /* where options are any of the entries in the 'ptab' PARSER */ /* table defined further above. Some commonly used options are: */ /* */ /* awstape sets the HET parms to be compatible with the */ /* R|P/390|'s tape file Format (HET files) */ /* */ /* idrc|compress 0|1: Write tape blocks with compression */ /* (std deviation: Read backward allowed on */ /* compressed HET tapes while it is not on */ /* IDRC formated 3480 tapes) */ /* */ /* --no-erg for SCSI tape only, means the hardware does */ /* not support the "Erase Gap" command and all */ /* such i/o's should return 'success' instead. */ /* */ /* --blkid-32 for SCSI tape only, means the hardware */ /* only supports full 32-bit block-ids. */ /* */ /*-------------------------------------------------------------------*/ int mountnewtape ( DEVBLK *dev, int argc, char **argv ) { char* short_descr; /* Short descr from fmttab */ int i; /* Loop control */ int rc, optrc; /* various rtns return codes */ union { /* Parser results */ U32 num; /* Parser results */ BYTE str[ 80 ]; /* Parser results */ } res; /* Parser results */ /* Release the previous OMA descriptor array if allocated */ if (dev->omadesc != NULL) { free (dev->omadesc); dev->omadesc = NULL; } /* The first argument is the file name */ if (argc == 0 || strlen(argv[0]) > sizeof(dev->filename)-1) strcpy (dev->filename, TAPE_UNLOADED); else /* Save the file name in the device block */ strcpy (dev->filename, argv[0]); /* Determine tape device type... */ VERIFY( gettapetype( dev, &short_descr ) == 0 ); /* (sanity check) */ ASSERT(dev->tapedevt != TAPEDEVT_UNKNOWN); ASSERT(dev->tmh != NULL); ASSERT(short_descr != NULL); /* Initialize device dependent fields */ dev->fd = -1; #if defined(OPTION_SCSI_TAPE) dev->sstat = GMT_DR_OPEN(-1); dev->stape_getstat_sstat = GMT_DR_OPEN(-1); #endif dev->omadesc = NULL; dev->omafiles = 0; dev->curfilen = 1; dev->nxtblkpos = 0; dev->prvblkpos = -1; dev->curblkrem = 0; dev->curbufoff = 0; dev->readonly = 0; dev->hetb = NULL; dev->tdparms.compress = HETDFLT_COMPRESS; dev->tdparms.method = HETDFLT_METHOD; dev->tdparms.level = HETDFLT_LEVEL; dev->tdparms.chksize = HETDFLT_CHKSIZE; dev->tdparms.maxsize = 0; // no max size (default) dev->eotmargin = 128*1024; // 128K EOT margin (default) dev->tdparms.logical_readonly = 0; // read/write (default) #if defined( OPTION_TAPE_AUTOMOUNT ) dev->noautomount = 0; #endif #if defined(OPTION_SCSI_TAPE) // Real 3590's support Erase Gap and use 32-bit blockids. if (TAPEDEVT_SCSITAPE == dev->tapedevt && 0x3590 == dev->devtype) { dev->stape_no_erg = 0; // (default for 3590 SCSI) dev->stape_blkid_32 = 1; // (default for 3590 SCSI) } #endif #define HHCTA078E() logmsg (_("HHCTA078E %4.4X: option '%s' not valid for %s\n"), \ dev->devnum, argv[i], short_descr) /* Process remaining options */ rc = 0; for (i = 1; i < argc; i++) { optrc = 0; switch (parser (&ptab[0], argv[i], &res)) { case TDPARM_NONE: logmsg (_("HHCTA067E %4.4X: option '%s' unrecognized\n"), dev->devnum, argv[i]); optrc = -1; break; case TDPARM_AWSTAPE: if (0 || TAPEDEVT_SCSITAPE == dev->tapedevt || TAPEDEVT_FAKETAPE == dev->tapedevt ) { HHCTA078E(); optrc = -1; break; } dev->tdparms.compress = FALSE; dev->tdparms.chksize = 4096; break; case TDPARM_IDRC: case TDPARM_COMPRESS: if (0 || TAPEDEVT_SCSITAPE == dev->tapedevt || TAPEDEVT_FAKETAPE == dev->tapedevt ) { HHCTA078E(); optrc = -1; break; } dev->tdparms.compress = (res.num ? TRUE : FALSE); break; case TDPARM_METHOD: if (0 || TAPEDEVT_SCSITAPE == dev->tapedevt || TAPEDEVT_FAKETAPE == dev->tapedevt ) { HHCTA078E(); optrc = -1; break; } if (res.num < HETMIN_METHOD || res.num > HETMAX_METHOD) { logmsg(_("HHCTA068E %4.4X: option '%s': method must be within %u-%u\n"), dev->devnum, argv[i], HETMIN_METHOD, HETMAX_METHOD); optrc = -1; break; } dev->tdparms.method = res.num; break; case TDPARM_LEVEL: if (0 || TAPEDEVT_SCSITAPE == dev->tapedevt || TAPEDEVT_FAKETAPE == dev->tapedevt ) { HHCTA078E(); optrc = -1; break; } if (res.num < HETMIN_LEVEL || res.num > HETMAX_LEVEL) { logmsg(_("HHCTA069E %4.4X: option '%s': level must be within %u-%u\n"), dev->devnum, argv[i], HETMIN_LEVEL, HETMAX_LEVEL); optrc = -1; break; } dev->tdparms.level = res.num; break; case TDPARM_CHKSIZE: if (0 || TAPEDEVT_SCSITAPE == dev->tapedevt || TAPEDEVT_FAKETAPE == dev->tapedevt ) { HHCTA078E(); optrc = -1; break; } if (res.num < HETMIN_CHUNKSIZE || res.num > HETMAX_CHUNKSIZE) { logmsg (_("HHCTA070E %4.4X: option '%s': chunksize must be within %u-%u\n"), dev->devnum, argv[i], HETMIN_CHUNKSIZE, HETMAX_CHUNKSIZE); optrc = -1; break; } dev->tdparms.chksize = res.num; break; case TDPARM_MAXSIZE: if (TAPEDEVT_SCSITAPE == dev->tapedevt) { HHCTA078E(); optrc = -1; break; } dev->tdparms.maxsize=res.num; break; case TDPARM_MAXSIZEK: if (TAPEDEVT_SCSITAPE == dev->tapedevt) { HHCTA078E(); optrc = -1; break; } dev->tdparms.maxsize=res.num*1024; break; case TDPARM_MAXSIZEM: if (TAPEDEVT_SCSITAPE == dev->tapedevt) { HHCTA078E(); optrc = -1; break; } dev->tdparms.maxsize=res.num*1024*1024; break; case TDPARM_EOTMARGIN: dev->eotmargin=res.num; break; case TDPARM_STRICTSIZE: if (TAPEDEVT_SCSITAPE == dev->tapedevt) { HHCTA078E(); optrc = -1; break; } dev->tdparms.strictsize=res.num; break; case TDPARM_READONLY: if (TAPEDEVT_SCSITAPE == dev->tapedevt) { HHCTA078E(); optrc = -1; break; } dev->tdparms.logical_readonly=(res.num ? 1 : 0 ); break; case TDPARM_RO: case TDPARM_NORING: if (TAPEDEVT_SCSITAPE == dev->tapedevt) { HHCTA078E(); optrc = -1; break; } dev->tdparms.logical_readonly=1; break; case TDPARM_RW: case TDPARM_RING: if (TAPEDEVT_SCSITAPE == dev->tapedevt) { HHCTA078E(); optrc = -1; break; } dev->tdparms.logical_readonly=0; break; case TDPARM_DEONIRQ: if (TAPEDEVT_SCSITAPE == dev->tapedevt) { HHCTA078E(); optrc = -1; break; } dev->tdparms.deonirq=(res.num ? 1 : 0 ); break; #if defined( OPTION_TAPE_AUTOMOUNT ) case TDPARM_NOAUTOMOUNT: if (TAPEDEVT_SCSITAPE == dev->tapedevt) { HHCTA078E(); optrc = -1; break; } dev->noautomount = 1; break; #endif /* OPTION_TAPE_AUTOMOUNT */ #if defined(OPTION_SCSI_TAPE) case TDPARM_BLKID22: case TDPARM_BLKID24: if (TAPEDEVT_SCSITAPE != dev->tapedevt) { HHCTA078E(); optrc = -1; break; } dev->stape_blkid_32 = 0; break; case TDPARM_BLKID32: if (TAPEDEVT_SCSITAPE != dev->tapedevt) { HHCTA078E(); optrc = -1; break; } dev->stape_blkid_32 = 1; break; case TDPARM_NOERG: if (TAPEDEVT_SCSITAPE != dev->tapedevt) { HHCTA078E(); optrc = -1; break; } dev->stape_no_erg = 1; break; #endif /* defined(OPTION_SCSI_TAPE) */ default: logmsg(_("HHCTA071E %4.4X: option '%s': parse error\n"), dev->devnum, argv[i]); optrc = -1; break; } // end switch (parser (&ptab[0], argv[i], &res)) if (optrc < 0) rc = -1; else logmsg (_("HHCTA066I %4.4X: option '%s' accepted.\n"), dev->devnum, argv[i]); } // end for (i = 1; i < argc; i++) if (0 != rc) return -1; /* Adjust the display if necessary */ if(dev->tdparms.displayfeat) { if(strcmp(dev->filename,TAPE_UNLOADED)==0) { /* NO tape is loaded */ if(TAPEDISPTYP_UMOUNTMOUNT == dev->tapedisptype) { /* A new tape SHOULD be mounted */ dev->tapedisptype = TAPEDISPTYP_MOUNT; dev->tapedispflags |= TAPEDISPFLG_REQAUTOMNT; strlcpy( dev->tapemsg1, dev->tapemsg2, sizeof(dev->tapemsg1) ); } else if(TAPEDISPTYP_UNMOUNT == dev->tapedisptype) { dev->tapedisptype = TAPEDISPTYP_IDLE; } } else { /* A tape IS already loaded */ dev->tapedisptype = TAPEDISPTYP_IDLE; } } UpdateDisplay(dev); ReqAutoMount(dev); return 0; } /* end function mountnewtape */ /*-------------------------------------------------------------------*/ /* Query the device definition */ /*-------------------------------------------------------------------*/ void tapedev_query_device ( DEVBLK *dev, char **class, int buflen, char *buffer ) { char devparms[ MAX_PATH+1 + 128 ]; char dispmsg [ 256 ]; BEGIN_DEVICE_CLASS_QUERY( "TAPE", dev, class, buflen, buffer ); *buffer = 0; devparms[0]=0; dispmsg [0]=0; GetDisplayMsg( dev, dispmsg, sizeof(dispmsg) ); if (strchr(dev->filename,' ')) strlcat( devparms, "\"", sizeof(devparms)); strlcat( devparms, dev->filename, sizeof(devparms)); if (strchr(dev->filename,' ')) strlcat( devparms, "\"", sizeof(devparms)); #if defined( OPTION_TAPE_AUTOMOUNT ) if (dev->noautomount) strlcat( devparms, " noautomount", sizeof(devparms)); #endif /* OPTION_TAPE_AUTOMOUNT */ if ( strcmp( dev->filename, TAPE_UNLOADED ) == 0 ) { #if defined(OPTION_SCSI_TAPE) if ( TAPEDEVT_SCSITAPE == dev->tapedevt ) { if (0x3590 == dev->devtype) // emulating 3590 { if (!dev->stape_blkid_32 ) strlcat( devparms, " --blkid-22", sizeof(devparms) ); } else // emulating 3480, 3490 { if ( dev->stape_blkid_32 ) strlcat( devparms, " --blkid-32", sizeof(devparms) ); } if ( dev->stape_no_erg ) strlcat( devparms, " --no-erg", sizeof(devparms) ); } #endif snprintf(buffer, buflen, "%s%s%s", devparms, dev->tdparms.displayfeat ? ", Display: " : "", dev->tdparms.displayfeat ? dispmsg : ""); } else // (filename was specified) { char tapepos[64]; tapepos[0]=0; if ( TAPEDEVT_SCSITAPE != dev->tapedevt ) { snprintf( tapepos, sizeof(tapepos), "[%d:%08"I64_FMT"X] ", dev->curfilen, dev->nxtblkpos ); tapepos[sizeof(tapepos)-1] = 0; } #if defined(OPTION_SCSI_TAPE) else // (this is a SCSI tape drive) { if (STS_BOT( dev )) { dev->eotwarning = 0; strlcat(tapepos,"*BOT* ",sizeof(tapepos)); } // If tape has a display, then GetDisplayMsg already // appended *FP* for us. Otherwise we need to do it. if ( !dev->tdparms.displayfeat ) if (STS_WR_PROT( dev )) strlcat(tapepos,"*FP* ",sizeof(tapepos)); if (0x3590 == dev->devtype) // emulating 3590 { if (!dev->stape_blkid_32 ) strlcat( devparms, " --blkid-22", sizeof(devparms) ); } else // emulating 3480, 3490 { if ( dev->stape_blkid_32 ) strlcat( devparms, " --blkid-32", sizeof(devparms) ); } if ( dev->stape_no_erg ) strlcat( devparms, " --no-erg", sizeof(devparms) ); } #endif if ( TAPEDEVT_SCSITAPE != dev->tapedevt #if defined(OPTION_SCSI_TAPE) || !STS_NOT_MOUNTED(dev) #endif ) { // Not a SCSI tape, -or- mounted SCSI tape... snprintf (buffer, buflen, "%s%s %s%s%s", devparms, (dev->readonly ? " ro" : ""), tapepos, dev->tdparms.displayfeat ? "Display: " : "", dev->tdparms.displayfeat ? dispmsg : ""); } else /* ( TAPEDEVT_SCSITAPE == dev->tapedevt && STS_NOT_MOUNTED(dev) ) */ { // UNmounted SCSI tape... snprintf (buffer, buflen, "%s%s (%sNOTAPE)%s%s", devparms, (dev->readonly ? " ro" : ""), dev->fd < 0 ? "closed; " : "", dev->tdparms.displayfeat ? ", Display: " : "", dev->tdparms.displayfeat ? dispmsg : "" ); } } buffer[buflen-1] = 0; } /* end function tapedev_query_device */ /*-------------------------------------------------------------------*/ /* Issue a message on the console indicating the display status */ /*-------------------------------------------------------------------*/ void UpdateDisplay( DEVBLK *dev ) { if ( dev->tdparms.displayfeat ) { char msgbfr[256]; GetDisplayMsg( dev, msgbfr, sizeof(msgbfr) ); if ( dev->prev_tapemsg ) { if ( strcmp( msgbfr, dev->prev_tapemsg ) == 0 ) return; free( dev->prev_tapemsg ); dev->prev_tapemsg = NULL; } dev->prev_tapemsg = strdup( msgbfr ); logmsg(_("HHCTA010I %4.4X: Now Displays: %s\n"), dev->devnum, msgbfr ); } #if defined(OPTION_SCSI_TAPE) else if (TAPEDEVT_SCSITAPE == dev->tapedevt) int_scsi_status_update( dev, 1 ); #endif } /*-------------------------------------------------------------------*/ /* Issue Automatic Mount Requests as defined by the display */ /*-------------------------------------------------------------------*/ void ReqAutoMount( DEVBLK *dev ) { char volser[7]; BYTE tapeloaded, autoload, mountreq, unmountreq, stdlbled, ascii, scratch; char* lbltype; char* tapemsg = ""; /////////////////////////////////////////////////////////////////// // The Automatic Cartridge Loader or "ACL" (sometimes also referred // to as an "Automatic Cartridge Feeder" (ACF) too) automatically // loads the next cartridge [from the magazine] whenever a tape is // unloaded, BUT ONLY IF the 'Index Automatic Load' bit (bit 7) of // the FCB (Format Control Byte, byte 0) was on whenever the Load // Display ccw was sent to the drive. If the bit was not on when // the Load Display ccw was issued, then the requested message (if // any) is displayed until the next tape mount/dismount and the ACL // is NOT activated (i.e. the next tape is NOT automatically loaded). // If the bit was on however, then, as stated, the ACF component of // the drive will automatically load the next [specified] cartridge. // Whenever the ACL facility is activated (via bit 7 of byte 0 of // the Load Display ccw), then only bytes 1-8 of the "Display Until // Mounted" message (or bytes 9-17 of a "Display Until Dismounted // Then Mounted" message) are displayed to let the operator know // which tape is currently being processed by the autoloader and // thus is basically for informational purposes only (the operator // does NOT need to do anything since the auto-loader is handling // tape mounts for them automatically; i.e. the message is NOT an // operator mount/dismount request). // If the 'Index Automatic Load' bit was not set in the Load Display // CCW however, then the specified "Display Until Mounted", "Display // Until Unmounted" or "Display Until Unmounted Then Display Until // Mounted" message is meant as a mount, unmount, or unmount-then- // mount request for the actual [human being] operator, and thus // they DO need to take some sort of action (since the ACL automatic // loader facility is not active; i.e. the message is a request to // the operator to manually unload, load or unload then load a tape). // THUS... If the TAPEDISPFLG_AUTOLOADER flag is set (indicating // the autoloader is (or should be) active), then the message we // issue is simply for INFORMATIONAL purposes only (i.e. "FYI: the // following tape is being *automatically* loaded; you don't need // to actually do anything") // If the TAPEDISPFLG_AUTOLOADER is flag is NOT set however, then // we need to issue a message notifying the operator of what they // are *expected* to do (e.g. either unload, load or unload/load // the specified tape volume). // Also please note that while there are no formally established // standards regarding the format of the Load Display CCW message // text, there are however certain established conventions (estab- // lished by IBM naturally). If the first character is an 'M', it // means "Please MOUNT the indicated volume". An 'R' [apparently] // means "Retain", and, similarly, 'K' means "Keep" (same thing as // "Retain"). If the LAST character is an 'S', then it means that // a Standard Labeled volume is being requested, whereas an 'N' // (or really, anything OTHER than an 'S' (except 'A')) means an // unlabeled (or non-labeled) tape volume is being requested. An // 'A' as the last character means a Standard Labeled ASCII tape // is being requested. If the message is "SCRTCH" (or something // similar), then a either a standard labeled or unlabeled scratch // tape is obviously being requested (there doesn't seem to be any // convention/consensus regarding the format for requesting scratch // tapes; some shops for example use 'XXXSCR' to indicate that a // scratch tape from tape pool 'XXX' should be mounted). /////////////////////////////////////////////////////////////////// /* Open the file/drive if needed (kick off auto-mount if needed) */ if (dev->fd < 0) { BYTE unitstat = 0, code = 0; dev->tmh->open( dev, &unitstat, code ); #if defined(OPTION_SCSI_TAPE) if (TAPEDEVT_SCSITAPE == dev->tapedevt) { // PROGRAMMING NOTE: it's important to do TWO refreshes here // to cause the auto-mount thread to get created. Doing only // one doesn't work and doing two shouldn't cause any harm. GENTMH_PARMS gen_parms; gen_parms.action = GENTMH_SCSI_ACTION_UPDATE_STATUS; gen_parms.dev = dev; // (refresh potentially stale status) VERIFY( dev->tmh->generic( &gen_parms ) == 0 ); // (force auto-mount thread creation) VERIFY( dev->tmh->generic( &gen_parms ) == 0 ); } #endif /* defined(OPTION_SCSI_TAPE) */ } /* Disabled when [non-SCSI] ACL in use */ if ( dev->als ) return; /* Do we actually have any work to do? */ if ( !( dev->tapedispflags & TAPEDISPFLG_REQAUTOMNT ) ) return; // (nothing to do!) /* Reset work flag */ dev->tapedispflags &= ~TAPEDISPFLG_REQAUTOMNT; /* If the drive doesn't have a display, then it can't have an auto-loader either */ if ( !dev->tdparms.displayfeat ) return; /* Determine if mount or unmount request and get pointer to correct message */ tapeloaded = dev->tmh->tapeloaded( dev, NULL, 0 ) ? TRUE : FALSE; mountreq = FALSE; // (default) unmountreq = FALSE; // (default) if (tapeloaded) { // A tape IS already loaded... // 1st byte of message1 non-blank, *AND*, // unmount request or, // unmountmount request and not message2-only flag? if (' ' != *(tapemsg = dev->tapemsg1) && (0 || TAPEDISPTYP_UNMOUNT == dev->tapedisptype || (1 && TAPEDISPTYP_UMOUNTMOUNT == dev->tapedisptype && !(dev->tapedispflags & TAPEDISPFLG_MESSAGE2) ) ) ) unmountreq = TRUE; } else { // NO TAPE is loaded yet... // mount request and 1st byte of msg1 non-blank, *OR*, // unmountmount request and 1st byte of msg2 non-blank? if ( (1 && TAPEDISPTYP_MOUNT == dev->tapedisptype && ' ' != *(tapemsg = dev->tapemsg1) ) || (1 && TAPEDISPTYP_UMOUNTMOUNT == dev->tapedisptype && ' ' != *(tapemsg = dev->tapemsg2) )) mountreq = TRUE; } /* Extract volser from message */ strncpy( volser, tapemsg+1, 6 ); volser[6]=0; /* Set some boolean flags */ autoload = ( dev->tapedispflags & TAPEDISPFLG_AUTOLOADER ) ? TRUE : FALSE; stdlbled = ( 'S' == tapemsg[7] ) ? TRUE : FALSE; ascii = ( 'A' == tapemsg[7] ) ? TRUE : FALSE; scratch = ( 'S' == tapemsg[0] ) ? TRUE : FALSE; lbltype = stdlbled ? "SL" : "UL"; #if defined(OPTION_SCSI_TAPE) #if 1 // **************************************************************** // ZZ FIXME: ZZ TODO: *** Programming Note *** // Since we currently don't have any way of activating a SCSI tape // drive's REAL autoloader mechanism whenever we receive an auto- // mount message [from the guest o/s via the Load Display CCW], we // leave it to the operator to action the mount message displayed // Once ASPI code eventually gets added to Herc (and/or something // similar for the Linux world), then the following workaround can // be safely removed. autoload = FALSE; // (temporarily forced; see above) // **************************************************************** #endif #endif /* defined(OPTION_SCSI_TAPE) */ if ( autoload ) { // ZZ TODO: Here is where we'd issue i/o (ASPI?) to the actual // hardware autoloader facility (i.e. the SCSI medium changer) // to unload and/or load the tape(s) if this were a SCSI auto- // loading tape drive. if ( unmountreq ) { if ( scratch ) logmsg(_("AutoMount: %s%s scratch tape being auto-unloaded on %4.4X = %s\n"), ascii ? "ASCII " : "",lbltype, dev->devnum, dev->filename); else logmsg(_("AutoMount: %s%s tape volume \"%s\" being auto-unloaded on %4.4X = %s\n"), ascii ? "ASCII " : "",lbltype, volser, dev->devnum, dev->filename); } if ( mountreq ) { if ( scratch ) logmsg(_("AutoMount: %s%s scratch tape being auto-loaded on %4.4X = %s\n"), ascii ? "ASCII " : "",lbltype, dev->devnum, dev->filename); else logmsg(_("AutoMount: %s%s tape volume \"%s\" being auto-loaded on %4.4X = %s\n"), ascii ? "ASCII " : "",lbltype, volser, dev->devnum, dev->filename); } } } /* end function ReqAutoMount */ /*-------------------------------------------------------------------*/ /* Get 3480/3490/3590 Display text in 'human' form */ /* If not a 3480/3490/3590, then just update status if a SCSI tape */ /*-------------------------------------------------------------------*/ void GetDisplayMsg( DEVBLK *dev, char *msgbfr, size_t lenbfr ) { msgbfr[0]=0; if ( !dev->tdparms.displayfeat ) { // (drive doesn't have a display) #if defined(OPTION_SCSI_TAPE) if (TAPEDEVT_SCSITAPE == dev->tapedevt) int_scsi_status_update( dev, 1 ); #endif return; } if ( !IS_TAPEDISPTYP_SYSMSG( dev ) ) { // ------------------------- // Display Host message // ------------------------- // "When bit 3 (alternate) is set to 1, then // bits 4 (blink) and 5 (low/high) are ignored." strlcpy( msgbfr, "\"", lenbfr ); if ( dev->tapedispflags & TAPEDISPFLG_ALTERNATE ) { char msg1[9]; char msg2[9]; strlcpy ( msg1, dev->tapemsg1, sizeof(msg1) ); strlcat ( msg1, " ", sizeof(msg1) ); strlcpy ( msg2, dev->tapemsg2, sizeof(msg2) ); strlcat ( msg2, " ", sizeof(msg2) ); strlcat ( msgbfr, msg1, lenbfr ); strlcat ( msgbfr, "\" / \"", lenbfr ); strlcat ( msgbfr, msg2, lenbfr ); strlcat ( msgbfr, "\"", lenbfr ); strlcat ( msgbfr, " (alternating)", lenbfr ); } else { if ( dev->tapedispflags & TAPEDISPFLG_MESSAGE2 ) strlcat( msgbfr, dev->tapemsg2, lenbfr ); else strlcat( msgbfr, dev->tapemsg1, lenbfr ); strlcat ( msgbfr, "\"", lenbfr ); if ( dev->tapedispflags & TAPEDISPFLG_BLINKING ) strlcat ( msgbfr, " (blinking)", lenbfr ); } if ( dev->tapedispflags & TAPEDISPFLG_AUTOLOADER ) strlcat( msgbfr, " (AUTOLOADER)", lenbfr ); return; } // ---------------------------------------------- // Display SYS message (Unit/Device message) // ---------------------------------------------- // First, build the system message, then move it into // the caller's buffer... strlcpy( dev->tapesysmsg, "\"", sizeof(dev->tapesysmsg) ); switch ( dev->tapedisptype ) { case TAPEDISPTYP_IDLE: case TAPEDISPTYP_WAITACT: default: // Blank display if no tape loaded... if ( !dev->tmh->tapeloaded( dev, NULL, 0 ) ) { strlcat( dev->tapesysmsg, " ", sizeof(dev->tapesysmsg) ); break; } // " NT RDY " if tape IS loaded, but not ready... // (IBM docs say " NT RDY " means "Loaded but not ready") ASSERT( dev->tmh->tapeloaded( dev, NULL, 0 ) ); if (0 || dev->fd < 0 #if defined(OPTION_SCSI_TAPE) || (1 && TAPEDEVT_SCSITAPE == dev->tapedevt && !STS_ONLINE( dev ) ) #endif ) { strlcat( dev->tapesysmsg, " NT RDY ", sizeof(dev->tapesysmsg) ); break; } // Otherwise tape is loaded and ready --> "READY" ASSERT( dev->tmh->tapeloaded( dev, NULL, 0 ) ); strlcat ( dev->tapesysmsg, " READY ", sizeof(dev->tapesysmsg) ); strlcat( dev->tapesysmsg, "\"", sizeof(dev->tapesysmsg) ); if (0 || dev->readonly #if defined(OPTION_SCSI_TAPE) || (1 && TAPEDEVT_SCSITAPE == dev->tapedevt && STS_WR_PROT( dev ) ) #endif ) // (append "file protect" indicator) strlcat ( dev->tapesysmsg, " *FP*", sizeof(dev->tapesysmsg) ); // Copy system message to caller's buffer strlcpy( msgbfr, dev->tapesysmsg, lenbfr ); return; case TAPEDISPTYP_ERASING: strlcat ( dev->tapesysmsg, " ERASING", sizeof(dev->tapesysmsg) ); break; case TAPEDISPTYP_REWINDING: strlcat ( dev->tapesysmsg, "REWINDNG", sizeof(dev->tapesysmsg) ); break; case TAPEDISPTYP_UNLOADING: strlcat ( dev->tapesysmsg, "UNLOADNG", sizeof(dev->tapesysmsg) ); break; case TAPEDISPTYP_CLEAN: strlcat ( dev->tapesysmsg, "*CLEAN ", sizeof(dev->tapesysmsg) ); break; } strlcat( dev->tapesysmsg, "\"", sizeof(dev->tapesysmsg) ); // Copy system message to caller's buffer strlcpy( msgbfr, dev->tapesysmsg, lenbfr ); } /* end function GetDisplayMsg */ /*-------------------------------------------------------------------*/ /* IsAtLoadPoint */ /*-------------------------------------------------------------------*/ /* Called by the device-type-specific 'build_sense_xxxx' functions */ /* (indirectly via the 'build_senseX' function) when building sense */ /* for any i/o error (non-"TAPE_BSENSE_STATUSONLY" type call) */ /*-------------------------------------------------------------------*/ int IsAtLoadPoint (DEVBLK *dev) { int ldpt=0; if ( dev->fd >= 0 ) { /* Set load point indicator if tape is at load point */ switch (dev->tapedevt) { default: case TAPEDEVT_AWSTAPE: if (dev->nxtblkpos==0) { ldpt=1; } break; case TAPEDEVT_HETTAPE: if (dev->hetb->cblk == 0) { ldpt=1; } break; #if defined(OPTION_SCSI_TAPE) case TAPEDEVT_SCSITAPE: int_scsi_status_update( dev, 0 ); // (internal call) if ( STS_BOT( dev ) ) { dev->eotwarning = 0; ldpt=1; } break; #endif /* defined(OPTION_SCSI_TAPE) */ case TAPEDEVT_OMATAPE: if (dev->nxtblkpos == 0 && dev->curfilen == 1) { ldpt=1; } break; } /* end switch(dev->tapedevt) */ } else // ( dev->fd < 0 ) { if ( TAPEDEVT_SCSITAPE == dev->tapedevt ) ldpt=0; /* (tape cannot possibly be at loadpoint if the device cannot even be opened!) */ else if ( strcmp( dev->filename, TAPE_UNLOADED ) != 0 ) { /* If the tape has a filename but the tape is not yet */ /* opened, then we are at loadpoint */ ldpt=1; } } return ldpt; } /* end function IsAtLoadPoint */ /*********************************************************************/ /*********************************************************************/ /** **/ /** AUTOLOADER FUNCTIONS **/ /** **/ /*********************************************************************/ /*********************************************************************/ /*-------------------------------------------------------------------*/ /* autoload_init */ /*-------------------------------------------------------------------*/ /* initialise the Autoloader feature */ /*-------------------------------------------------------------------*/ void autoload_init(DEVBLK *dev,int ac,char **av) { char bfr[4096]; char *rec; FILE *aldf; char *verb; int i; char *strtokw; char pathname[MAX_PATH]; autoload_close(dev); if(ac<1) { return; } if(av[0][0]!='@') { return; } logmsg(_("TAPE: Autoloader file request fn=%s\n"),&av[0][1]); hostpath(pathname, &av[0][1], sizeof(pathname)); if(!(aldf=fopen(pathname,"r"))) { return; } for(i=1;i=0;i--) { rec[i]=0; } if(strlen(rec)==0) { continue; } verb=strtok_r(rec," \t",&strtokw); if(verb==NULL) { continue; } if(verb[0]==0) { continue; } if(verb[0]=='#') { continue; } if(strcmp(verb,"*")==0) { while((verb=strtok_r(NULL," \t",&strtokw))) { autoload_global_parms(dev,verb); } continue; } autoload_tape_entry(dev,verb,&strtokw); } // end while((rec=fgets(bfr,4096,aldf))) fclose(aldf); return; } /* end function autoload_init */ /*-------------------------------------------------------------------*/ /* autoload_close */ /*-------------------------------------------------------------------*/ /* terminate autoloader operations: release all storage that */ /* was allocated by the autoloader facility */ /*-------------------------------------------------------------------*/ void autoload_close(DEVBLK *dev) { int i; if(dev->al_argv!=NULL) { for(i=0;ial_argc;i++) { free(dev->al_argv[i]); dev->al_argv[i]=NULL; } free(dev->al_argv); dev->al_argv=NULL; dev->al_argc=0; } dev->al_argc=0; if(dev->als!=NULL) { for(i=0;ialss;i++) { autoload_clean_entry(dev,i); } free(dev->als); dev->als=NULL; dev->alss=0; } } /* end function autoload_close */ /*-------------------------------------------------------------------*/ /* autoload_clean_entry */ /*-------------------------------------------------------------------*/ /* release storage allocated for an autoloader slot */ /* (except the slot itself) */ /*-------------------------------------------------------------------*/ void autoload_clean_entry(DEVBLK *dev,int ix) { int i; for(i=0;ials[ix].argc;i++) { free(dev->als[ix].argv[i]); dev->als[ix].argv[i]=NULL; } dev->als[ix].argc=0; if(dev->als[ix].filename!=NULL) { free(dev->als[ix].filename); dev->als[ix].filename=NULL; } } /* end function autoload_clean_entry */ /*-------------------------------------------------------------------*/ /* autoload_global_parms */ /*-------------------------------------------------------------------*/ /* Appends a blank delimited word to the list of parameters */ /* that will be passed for every tape mounted by the autoloader */ /*-------------------------------------------------------------------*/ void autoload_global_parms(DEVBLK *dev,char *par) { logmsg(_("TAPE Autoloader - Adding global parm %s\n"),par); if(dev->al_argv==NULL) { dev->al_argv=malloc(sizeof(char *)*256); dev->al_argc=0; } dev->al_argv[dev->al_argc]=(char *)malloc(strlen(par)+sizeof(char)); strcpy(dev->al_argv[dev->al_argc],par); dev->al_argc++; } /* end function autoload_global_parms */ /*-------------------------------------------------------------------*/ /* autoload_tape_entry */ /*-------------------------------------------------------------------*/ /* populate an autoloader slot (creates new slot if needed) */ /*-------------------------------------------------------------------*/ void autoload_tape_entry(DEVBLK *dev,char *fn,char **strtokw) { char *p; TAPEAUTOLOADENTRY tae; logmsg(_("TAPE Autoloader: Adding tape entry %s\n"),fn); memset(&tae,0,sizeof(tae)); tae.filename=malloc(strlen(fn)+sizeof(char)+1); strcpy(tae.filename,fn); while((p=strtok_r(NULL," \t",strtokw))) { if(tae.argv==NULL) { tae.argv=malloc(sizeof(char *)*256); } tae.argv[tae.argc]=malloc(strlen(p)+sizeof(char)+1); strcpy(tae.argv[tae.argc],p); tae.argc++; } if(dev->als==NULL) { dev->als=malloc(sizeof(tae)); dev->alss=0; } else { dev->als=realloc(dev->als,sizeof(tae)*(dev->alss+1)); } memcpy(&dev->als[dev->alss],&tae,sizeof(tae)); dev->alss++; } /* end function autoload_tape_entry */ /*-------------------------------------------------------------------*/ /* autoload_wait_for_tapemount_thread */ /*-------------------------------------------------------------------*/ void *autoload_wait_for_tapemount_thread(void *db) { int rc = -1; DEVBLK *dev = (DEVBLK*) db; obtain_lock(&dev->lock); { while ( dev->als && (rc = autoload_mount_next( dev )) != 0 ) { release_lock( &dev->lock ); SLEEP(AUTOLOAD_WAIT_FOR_TAPEMOUNT_INTERVAL_SECS); obtain_lock( &dev->lock ); } } release_lock(&dev->lock); if ( rc == 0 ) device_attention(dev,CSW_DE); return NULL; } /* end function autoload_wait_for_tapemount_thread */ /*-------------------------------------------------------------------*/ /* autoload_mount_first */ /*-------------------------------------------------------------------*/ /* mount in the drive the tape which is */ /* positionned in the 1st autoloader slot */ /*-------------------------------------------------------------------*/ int autoload_mount_first(DEVBLK *dev) { dev->alsix=0; return(autoload_mount_tape(dev,0)); } /*-------------------------------------------------------------------*/ /* autoload_mount_next */ /*-------------------------------------------------------------------*/ /* mount in the drive the tape whch is */ /* positionned in the slot after the currently mounted tape. */ /* if this is the last tape, close the autoloader */ /*-------------------------------------------------------------------*/ int autoload_mount_next(DEVBLK *dev) { if(dev->alsix>=dev->alss) { autoload_close(dev); return -1; } dev->alsix++; return(autoload_mount_tape(dev,dev->alsix)); } /*-------------------------------------------------------------------*/ /* autoload_mount_tape */ /*-------------------------------------------------------------------*/ /* mount in the drive the tape which is */ /* positionned in the autoloader slot #alix */ /*-------------------------------------------------------------------*/ int autoload_mount_tape(DEVBLK *dev,int alix) { char **pars; int pcount=1; int i; int rc; if(alix>=dev->alss) { return -1; } pars=malloc(sizeof(BYTE *)*256); pars[0]=dev->als[alix].filename; for(i=0;ial_argc;i++,pcount++) { pars[pcount]=malloc(strlen(dev->al_argv[i])+10); strcpy(pars[pcount],dev->al_argv[i]); if(pcount>255) { break; } } for(i=0;ials[alix].argc;i++,pcount++) { pars[pcount]=malloc(strlen(dev->als[alix].argv[i])+10); strcpy(pars[pcount],dev->als[alix].argv[i]); if(pcount>255) { break; } } rc=mountnewtape(dev,pcount,pars); for(i=1;ifilename, TAPE_UNLOADED ) != 0 ? 1 : 0; } /*-------------------------------------------------------------------*/ /* return_false1 */ /*-------------------------------------------------------------------*/ int return_false1 ( DEVBLK *dev ) { UNREFERENCED(dev); return 0; } /*-------------------------------------------------------------------*/ /* write_READONLY */ /*-------------------------------------------------------------------*/ int write_READONLY ( DEVBLK *dev, BYTE *unitstat, BYTE code ) { build_senseX(TAPE_BSENSE_WRITEPROTECT,dev,unitstat,code); return -1; } /*-------------------------------------------------------------------*/ /* write_READONLY5 */ /*-------------------------------------------------------------------*/ int write_READONLY5 ( DEVBLK *dev, BYTE *bfr, U16 blklen, BYTE *unitstat, BYTE code ) { UNREFERENCED(bfr); UNREFERENCED(blklen); build_senseX(TAPE_BSENSE_WRITEPROTECT,dev,unitstat,code); return -1; } /*-------------------------------------------------------------------*/ /* no_operation */ /*-------------------------------------------------------------------*/ int no_operation ( DEVBLK *dev, BYTE *unitstat, BYTE code ) { build_senseX( TAPE_BSENSE_STATUSONLY, dev, unitstat, code ); return 0; } /*-------------------------------------------------------------------*/ /* readblkid_virtual */ /*-------------------------------------------------------------------*/ int readblkid_virtual ( DEVBLK* dev, BYTE* logical, BYTE* physical ) { // NOTE: returned value is always in guest BIG-ENDIAN format... BYTE blockid[4]; if (0x3590 == dev->devtype) { // Full 32-bit block-id... blockid[0] = (dev->blockid >> 24) & 0xFF; blockid[1] = (dev->blockid >> 16) & 0xFF; blockid[2] = (dev->blockid >> 8 ) & 0xFF; blockid[3] = (dev->blockid ) & 0xFF; } else // (3480 et. al) { // "22-bit" block-id... blockid[0] = 0x01; // ("wrap" value) blockid[1] = (dev->blockid >> 16) & 0x3F; blockid[2] = (dev->blockid >> 8 ) & 0xFF; blockid[3] = (dev->blockid ) & 0xFF; } // NOTE: For virtual tape devices, we return the same value // for both the logical "Channel block ID" value as well as // the physical "Device block ID" value... if (logical) memcpy( logical, &blockid[0], 4 ); if (physical) memcpy( physical, &blockid[0], 4 ); return 0; } /*-------------------------------------------------------------------*/ /* locateblk_virtual */ /*-------------------------------------------------------------------*/ int locateblk_virtual ( DEVBLK* dev, U32 blockid, BYTE *unitstat, BYTE code ) { // NOTE: 'blockid' passed in host (little-endian) format... int rc; /* Do it the hard way: rewind to load-point and then keep doing fsb, fsb, fsb... until we find our block */ if ((rc = dev->tmh->rewind( dev, unitstat, code)) >= 0) { /* Reset position counters to start of file */ dev->curfilen = 1; dev->nxtblkpos = 0; dev->prvblkpos = -1; dev->blockid = 0; /* Do it the hard way */ while ( dev->blockid < blockid && ( rc >= 0 ) ) rc = dev->tmh->fsb( dev, unitstat, code ); } return rc; } /*-------------------------------------------------------------------*/ /* generic_tmhcall generic media-type-handler call... */ /*-------------------------------------------------------------------*/ int generic_tmhcall ( GENTMH_PARMS* pGenParms ) { if (!pGenParms) { errno = EINVAL; // (invalid arguments) return -1; // (return failure) } switch (pGenParms->action) { #if defined(OPTION_SCSI_TAPE) case GENTMH_SCSI_ACTION_UPDATE_STATUS: { return update_status_scsitape( pGenParms->dev ); } #endif /* defined(OPTION_SCSI_TAPE) */ default: { errno = EINVAL; // (invalid arguments) return -1; // (return failure) } } return -1; // (never reached) } hercules-3.07/tapedev.h000644 000765 000765 00000073737 11321734033 016562 0ustar00jmaynardjmaynard000000 000000 /* TAPEDEV.H (c) Copyright Ivan Warren and others, 2003-2009 */ /* Tape Device Handler Structure Definitions */ /*-------------------------------------------------------------------*/ /* This header file contains tape related structures and defines */ /* for the Hercules ESA/390 emulator. */ /*-------------------------------------------------------------------*/ // $Id: tapedev.h 5587 2009-12-31 15:05:57Z rbowler $ #ifndef __TAPEDEV_H__ #define __TAPEDEV_H__ #include "scsitape.h" /* SCSI Tape handling functions */ #include "htypes.h" /* Hercules struct typedefs */ #include "opcode.h" /* device_attention, SETMODE, etc. */ #include "parser.h" /* generic parameter string parser */ /*-------------------------------------------------------------------*/ /* Internal macro definitions */ /*-------------------------------------------------------------------*/ #define MAX_BLKLEN 65535 /* Maximum I/O buffer size */ #define TAPE_UNLOADED "*" /* Name for unloaded drive */ /*-------------------------------------------------------------------*/ /* Definitions for 3420/3480 sense bytes */ /*-------------------------------------------------------------------*/ #define SENSE1_TAPE_NOISE 0x80 /* Noise */ #define SENSE1_TAPE_TUA 0x40 /* TU Status A (ready) */ #define SENSE1_TAPE_TUB 0x20 /* TU Status B (not ready) */ #define SENSE1_TAPE_7TRK 0x10 /* 7-track feature */ #define SENSE1_TAPE_RSE 0x10 /* Record sequence error */ #define SENSE1_TAPE_LOADPT 0x08 /* Tape is at load point */ #define SENSE1_TAPE_WRT 0x04 /* Tape is in write status */ #define SENSE1_TAPE_FP 0x02 /* File protect status */ #define SENSE1_TAPE_NCA 0x01 /* Not capable */ #define SENSE4_TAPE_EOT 0x20 /* Tape indicate (EOT) */ #define SENSE5_TAPE_SRDCHK 0x08 /* Start read check */ #define SENSE5_TAPE_PARTREC 0x04 /* Partial record */ #define SENSE7_TAPE_LOADFAIL 0x01 /* Load failure */ /*-------------------------------------------------------------------*/ /* ISW : Internal error types used to build Device Dependent Sense */ /*-------------------------------------------------------------------*/ #define TAPE_BSENSE_TAPEUNLOADED 0 /* I/O Attempted but no tape loaded */ #define TAPE_BSENSE_TAPELOADFAIL 1 /* I/O and load failed */ #define TAPE_BSENSE_READFAIL 2 /* Error reading block */ #define TAPE_BSENSE_WRITEFAIL 3 /* Error writing block */ #define TAPE_BSENSE_BADCOMMAND 4 /* The CCW code is not known or sequence error */ #define TAPE_BSENSE_INCOMPAT 5 /* The CCW code is known but is not unsupported */ #define TAPE_BSENSE_WRITEPROTECT 6 /* Write CCW code was issued to a read-only media */ #define TAPE_BSENSE_EMPTYTAPE 7 /* A read was issued but the tape is empty */ #define TAPE_BSENSE_ENDOFTAPE 8 /* A read was issued past the end of the tape or a write was issued and there is no space left on the tape */ #define TAPE_BSENSE_LOADPTERR 9 /* BSF/BSR/RdBW attempted from BOT */ #define TAPE_BSENSE_FENCED 10 /* Media damaged - unload or /reload required */ #define TAPE_BSENSE_BADALGORITHM 11 /* Bad compression - HET tape compressed with an unsuported method */ #define TAPE_BSENSE_RUN_SUCCESS 12 /* Rewind Unload success */ #define TAPE_BSENSE_STATUSONLY 13 /* No exception occured */ #define TAPE_BSENSE_LOCATEERR 14 /* Can't find block or TM */ #define TAPE_BSENSE_READTM 15 /* A Tape Mark was read */ #define TAPE_BSENSE_BLOCKSHORT 17 /* Short Tape block */ #define TAPE_BSENSE_ITFERROR 18 /* Interface error (SCSI driver unexpected err) */ #define TAPE_BSENSE_REWINDFAILED 19 /* Rewind operation failed */ #define TAPE_BSENSE_UNSOLICITED 20 /* Sense without UC */ /*-------------------------------------------------------------------*/ /* Definitions for 3480 and later commands */ /*-------------------------------------------------------------------*/ /* Format control byte for Load Display command */ #define FCB_FS 0xE0 /* Function Select bits... */ #define FCB_FS_READYGO 0x00 /* Display msg until motion, */ /* or until msg is updated */ #define FCB_FS_UNMOUNT 0x20 /* Display msg until unloaded*/ #define FCB_FS_MOUNT 0x40 /* Display msg until loaded */ #define FCB_FS_RESET_DISPLAY 0x80 /* Reset display (clear Host */ /* msg; replace w/Unit msg) */ #define FCB_FS_NOP 0x60 /* No-op */ #define FCB_FS_UMOUNTMOUNT 0xE0 /* Display msg 1 until tape */ /* is unloaded, then msg 2 */ /* until tape is loaded */ #define FCB_AM 0x10 /* Alternate between msg 1/2 */ #define FCB_BM 0x08 /* Blink message */ #define FCB_M2 0x04 /* Display only message 2 */ #define FCB_RESV 0x02 /* (reserved) */ #define FCB_AL 0x01 /* Activate AutoLoader on */ /* mount/unmount messages */ /* Mode Set commands */ #define MSET_WRITE_IMMED 0x20 /* Tape-Write-Immediate mode */ #define MSET_SUPVR_INHIBIT 0x10 /* Supervisor Inhibit mode */ #define MSET_IDRC 0x08 /* IDRC mode */ /* Path state byte for Sense Path Group ID command */ #define SPG_PATHSTAT 0xC0 /* Pathing status bits... */ #define SPG_PATHSTAT_RESET 0x00 /* ...reset */ #define SPG_PATHSTAT_RESV 0x40 /* ...reserved bit setting */ #define SPG_PATHSTAT_UNGROUPED 0x80 /* ...ungrouped */ #define SPG_PATHSTAT_GROUPED 0xC0 /* ...grouped */ #define SPG_PARTSTAT 0x30 /* Partitioning status bits..*/ #define SPG_PARTSTAT_IENABLED 0x00 /* ...implicitly enabled */ #define SPG_PARTSTAT_RESV 0x10 /* ...reserved bit setting */ #define SPG_PARTSTAT_DISABLED 0x20 /* ...disabled */ #define SPG_PARTSTAT_XENABLED 0x30 /* ...explicitly enabled */ #define SPG_PATHMODE 0x08 /* Path mode bit... */ #define SPG_PATHMODE_SINGLE 0x00 /* ...single path mode */ #define SPG_PATHMODE_RESV 0x08 /* ...reserved bit setting */ #define SPG_RESERVED 0x07 /* Reserved bits, must be 0 */ /* Function control byte for Set Path Group ID command */ #define SPG_SET_MULTIPATH 0x80 /* Set multipath mode */ #define SPG_SET_COMMAND 0x60 /* Set path command bits... */ #define SPG_SET_ESTABLISH 0x00 /* ...establish group */ #define SPG_SET_DISBAND 0x20 /* ...disband group */ #define SPG_SET_RESIGN 0x40 /* ...resign from group */ #define SPG_SET_COMMAND_RESV 0x60 /* ...reserved bit setting */ #define SPG_SET_RESV 0x1F /* Reserved bits, must be 0 */ /* Perform Subsystem Function order byte for PSF command */ #define PSF_ORDER_PRSD 0x18 /* Prep for Read Subsys Data */ #define PSF_ACTION_SSD_ATNMSG 0x03 /* ..Attention Message */ #define PSF_ORDER_SSIC 0x1B /* Set Special Intercept Cond*/ #define PSF_ORDER_MNS 0x1C /* Message Not Supported */ #define PSF_ORDER_AFEL 0x80 /* Activate Forced Error Log.*/ #define PSF_ORDER_DFEL 0x81 /* Deact. Forced Error Log. */ #define PSF_ACTION_FEL_IMPLICIT 0x01 /* ..Implicit (De)Activate */ #define PSF_ACTION_FEL_EXPLICIT 0x02 /* ..Explicit (De)Activate */ #define PSF_ORDER_AAC 0x82 /* Activate Access Control */ #define PSF_ORDER_DAC 0x83 /* Deact. Access Control */ #define PSF_ACTION_AC_LWP 0x80 /* ..Logical Write Protect */ #define PSF_ACTION_AC_DCD 0x10 /* ..Data Compaction Default */ #define PSF_ACTION_AC_DCR 0x02 /* ..Data Check Recovery */ #define PSF_ACTION_AC_ER 0x01 /* ..Extended Recovery */ #define PSF_ORDER_RVF 0x90 /* Reset Volume Fenced */ #define PSF_ORDER_PIN_DEV 0xA1 /* Pin Device */ #define PSF_ACTION_PIN_CU0 0x00 /* ..Control unit 0 */ #define PSF_ACTION_PIN_CU1 0x01 /* ..Control unit 1 */ #define PSF_ORDER_UNPIN_DEV 0xA2 /* Unpin Device */ #define PSF_FLAG_ZERO 0x00 /* Must be zero for all ord. */ /* Control Access Function Control */ #define CAC_FUNCTION 0xC0 /* Function control bits */ #define CAC_SET_PASSWORD 0x00 /* ..Set Password */ #define CAC_COND_ENABLE 0x80 /* ..Conditional Enable */ #define CAC_COND_DISABLE 0x40 /* ..Conditional Disable */ /*-------------------------------------------------------------------*/ /* Definitions for tape device type field in device block */ /*-------------------------------------------------------------------*/ #define TAPEDEVT_UNKNOWN 0 /* AWSTAPE format disk file */ #define TAPEDEVT_AWSTAPE 1 /* AWSTAPE format disk file */ #define TAPEDEVT_OMATAPE 2 /* OMATAPE format disk files */ #define TAPEDEVT_SCSITAPE 3 /* Physical SCSI tape */ #define TAPEDEVT_HETTAPE 4 /* HET format disk file */ #define TAPEDEVT_FAKETAPE 5 /* Flex FakeTape disk format */ /*-------------------------------------------------------------------*/ /* Fish - macros for checking SCSI tape device-independent status */ /*-------------------------------------------------------------------*/ #if defined(OPTION_SCSI_TAPE) #define STS_TAPEMARK(dev) GMT_SM ( (dev)->sstat ) #define STS_EOF(dev) GMT_EOF ( (dev)->sstat ) #define STS_BOT(dev) GMT_BOT ( (dev)->sstat ) #define STS_EOT(dev) GMT_EOT ( (dev)->sstat ) #define STS_EOD(dev) GMT_EOD ( (dev)->sstat ) #define STS_WR_PROT(dev) GMT_WR_PROT ( (dev)->sstat ) #define STS_ONLINE(dev) GMT_ONLINE ( (dev)->sstat ) #define STS_NOT_MOUNTED(dev) (GMT_DR_OPEN ( (dev)->sstat ) || (dev)->fd < 0) #endif #define AUTOLOAD_WAIT_FOR_TAPEMOUNT_INTERVAL_SECS (5) /* (default) */ /*-------------------------------------------------------------------*/ /* Structure definition for HET/AWS/OMA tape block headers */ /*-------------------------------------------------------------------*/ /* * The integer fields in the HET, AWSTAPE and OMATAPE headers are * encoded in the Intel format (i.e. the bytes of the integer are held * in reverse order). For this reason the integers are defined as byte * arrays, and the bytes are fetched individually in order to make * the code portable across architectures which use either the Intel * format or the S/370 format. * * Block length fields contain the length of the emulated tape block * and do not include the length of the header. * * For the AWSTAPE and HET formats: * - the first block has a previous block length of zero * - a tapemark is indicated by a header with a block length of zero * and a flag byte of X'40' * * For the OMATAPE format: * - the first block has a previous header offset of X'FFFFFFFF' * - a tapemark is indicated by a header with a block length of * X'FFFFFFFF' * - each block is followed by padding bytes if necessary to ensure * that the next header starts on a 16-byte boundary * */ typedef struct _AWSTAPE_BLKHDR { /* * PROGRAMMING NOTE: note that for AWS tape files, the "current * chunk size" comes FIRST and the "previous chunk size" comes * second. This is the complete opposite from the way it is for * Flex FakeTape. Also note that for AWS the size fields are in * LITTLE endian binary whereas for Flex FakeTape they're a BIG * endian ASCII hex-string. */ HWORD curblkl; /* Length of this block */ HWORD prvblkl; /* Length of previous block */ BYTE flags1; /* Flags byte 1 (see below) */ BYTE flags2; /* Flags byte 2 */ /* Definitions for AWSTAPE_BLKHDR flags byte 1 */ #define AWSTAPE_FLAG1_NEWREC 0x80 /* Start of new record */ #define AWSTAPE_FLAG1_TAPEMARK 0x40 /* Tape mark */ #define AWSTAPE_FLAG1_ENDREC 0x20 /* End of record */ } AWSTAPE_BLKHDR; /*-------------------------------------------------------------------*/ /* Structure definition for OMA block header */ /*-------------------------------------------------------------------*/ typedef struct _OMATAPE_BLKHDR { FWORD curblkl; /* Length of this block */ FWORD prvhdro; /* Offset of previous block header from start of file */ FWORD omaid; /* OMA identifier (contains ASCII characters "@HDF") */ FWORD resv; /* Reserved */ } OMATAPE_BLKHDR; /*-------------------------------------------------------------------*/ /* Structure definition for OMA tape descriptor array */ /*-------------------------------------------------------------------*/ typedef struct _OMATAPE_DESC { int fd; /* File Descriptor for file */ char filename[256]; /* Filename of data file */ char format; /* H=HEADERS,T=TEXT,F=FIXED,X=Tape Mark */ BYTE resv; /* Reserved for alignment */ U16 blklen; /* Fixed block length */ } OMATAPE_DESC; /*-------------------------------------------------------------------*/ /* Structure definition for Flex FakeTape block headers */ /*-------------------------------------------------------------------*/ /* * The character length fields in a Flex FakeTape header are in BIG * endian ASCII hex. That is to say, when the length field is ASCII * "0123" (i.e. 0x30, 0x31, 0x32, 0x33), the length of the block is * decimal 291 bytes (0x0123 == 291). * * The two block length fields are followed by an XOR "check" field * calculated as the XOR of the two preceding length fields and is * used to verify the integrity of the header. * * The Flex FakeTape tape format does not support any flag fields * in its header and thus does not support any type of compression. */ typedef struct _FAKETAPE_BLKHDR { /* * PROGRAMMING NOTE: note that for Flex FakeTapes, the "previous * chunk size" comes FIRST, followed by the "current chunk size" * second. This is the complete opposite from the way it is for * AWS tape files. Also note that for Flex FakeTape the size fields * are in BIG endian ASCII hex-string whereas for AWS tapes * they're LITTLE endian binary. */ char sprvblkl[4]; /* length of previous block */ char scurblkl[4]; /* length of this block */ char sxorblkl[4]; /* XOR both lengths together */ } FAKETAPE_BLKHDR; /*-------------------------------------------------------------------*/ /* Tape Auto-Loader table entry */ /*-------------------------------------------------------------------*/ struct TAPEAUTOLOADENTRY { char *filename; int argc; char **argv; }; /*-------------------------------------------------------------------*/ /* Tape AUTOMOUNT CCWS directory control */ /*-------------------------------------------------------------------*/ struct TAMDIR { TAMDIR *next; /* ptr to next entry or NULL */ char *dir; /* resolved directory value */ int len; /* strlen(dir) */ int rej; /* 1 == reject, 0 == accept */ }; /*-------------------------------------------------------------------*/ /* Generic media-handler-call parameters block */ /*-------------------------------------------------------------------*/ typedef struct _GENTMH_PARMS { int action; // action code (i.e. "what to do") DEVBLK* dev; // -> device block BYTE* unitstat; // -> unit status BYTE code; // CCW opcode // TODO: define whatever additional arguments may be needed... } GENTMH_PARMS; /*-------------------------------------------------------------------*/ /* Generic media-handler-call action codes */ /*-------------------------------------------------------------------*/ #define GENTMH_SCSI_ACTION_UPDATE_STATUS (0) //efine GENTMH_AWS_ACTION_xxxxx... (x) //efine GENTMH_HET_ACTION_xxxxx... (x) //efine GENTMH_OMA_ACTION_xxxxx... (x) /*-------------------------------------------------------------------*/ /* Tape media I/O function vector table layout */ /*-------------------------------------------------------------------*/ struct TAPEMEDIA_HANDLER { int (*generic) (GENTMH_PARMS*); // (generic call) int (*open) (DEVBLK*, BYTE *unitstat, BYTE code); void (*close) (DEVBLK*); int (*read) (DEVBLK*, BYTE *buf, BYTE *unitstat, BYTE code); int (*write) (DEVBLK*, BYTE *buf, U16 blklen, BYTE *unitstat, BYTE code); int (*rewind) (DEVBLK*, BYTE *unitstat, BYTE code); int (*bsb) (DEVBLK*, BYTE *unitstat, BYTE code); int (*fsb) (DEVBLK*, BYTE *unitstat, BYTE code); int (*bsf) (DEVBLK*, BYTE *unitstat, BYTE code); int (*fsf) (DEVBLK*, BYTE *unitstat, BYTE code); int (*wtm) (DEVBLK*, BYTE *unitstat, BYTE code); int (*sync) (DEVBLK*, BYTE *unitstat, BYTE code); int (*dse) (DEVBLK*, BYTE *unitstat, BYTE code); int (*erg) (DEVBLK*, BYTE *unitstat, BYTE code); int (*tapeloaded) (DEVBLK*, BYTE *unitstat, BYTE code); int (*passedeot) (DEVBLK*); /* readblkid o/p values are returned in BIG-ENDIAN guest format */ int (*readblkid) (DEVBLK*, BYTE* logical, BYTE* physical); /* locateblk i/p value is passed in little-endian host format */ int (*locateblk) (DEVBLK*, U32 blockid, BYTE *unitstat, BYTE code); }; /*-------------------------------------------------------------------*/ /* Functions defined in TAPEDEV.C */ /*-------------------------------------------------------------------*/ extern int tapedev_init_handler (DEVBLK *dev, int argc, char *argv[]); extern int tapedev_close_device (DEVBLK *dev ); extern void tapedev_query_device (DEVBLK *dev, char **class, int buflen, char *buffer); extern void autoload_init (DEVBLK *dev, int ac, char **av); extern int autoload_mount_first (DEVBLK *dev); extern int autoload_mount_next (DEVBLK *dev); extern void autoload_close (DEVBLK *dev); extern void autoload_global_parms (DEVBLK *dev, char *par); extern void autoload_clean_entry (DEVBLK *dev, int ix); extern void autoload_tape_entry (DEVBLK *dev, char *fn, char **strtokw); extern int autoload_mount_tape (DEVBLK *dev, int alix); extern void* autoload_wait_for_tapemount_thread (void *db); extern int gettapetype (DEVBLK *dev, char **short_descr); extern int gettapetype_byname (DEVBLK *dev); extern int gettapetype_bydata (DEVBLK *dev); extern int mountnewtape (DEVBLK *dev, int argc, char **argv); extern void GetDisplayMsg (DEVBLK *dev, char *msgbfr, size_t lenbfr); extern int IsAtLoadPoint (DEVBLK *dev); extern void ReqAutoMount (DEVBLK *dev); extern void UpdateDisplay (DEVBLK *dev); extern int return_false1 (DEVBLK *dev); extern int write_READONLY5 (DEVBLK *dev, BYTE *bfr, U16 blklen, BYTE *unitstat, BYTE code); extern int is_tapeloaded_filename (DEVBLK *dev, BYTE *unitstat, BYTE code); extern int write_READONLY (DEVBLK *dev, BYTE *unitstat, BYTE code); extern int no_operation (DEVBLK *dev, BYTE *unitstat, BYTE code); extern int readblkid_virtual (DEVBLK*, BYTE* logical, BYTE* physical); extern int locateblk_virtual (DEVBLK*, U32 blockid, BYTE *unitstat, BYTE code); extern int generic_tmhcall (GENTMH_PARMS*); /*-------------------------------------------------------------------*/ /* Functions (and data areas) defined in TAPECCWS.C */ /*-------------------------------------------------------------------*/ typedef void TapeSenseFunc( int, DEVBLK*, BYTE*, BYTE ); // (sense handling function) #define TAPEDEVTYPELIST_ENTRYSIZE (5) // #of int's per 'TapeDevtypeList' table entry extern int TapeDevtypeList[]; extern BYTE* TapeCommandTable[]; extern TapeSenseFunc* TapeSenseTable[]; //tern BYTE TapeCommandsXXXX[256]... extern BYTE TapeImmedCommands[]; extern int TapeCommandIsValid (BYTE code, U16 devtype, BYTE *rustat); extern void tapedev_execute_ccw (DEVBLK *dev, BYTE code, BYTE flags, BYTE chained, U16 count, BYTE prevcode, int ccwseq, BYTE *iobuf, BYTE *more, BYTE *unitstat, U16 *residual); extern void load_display (DEVBLK *dev, BYTE *buf, U16 count); extern void build_senseX (int ERCode, DEVBLK *dev, BYTE *unitstat, BYTE ccwcode); extern void build_sense_3410 (int ERCode, DEVBLK *dev, BYTE *unitstat, BYTE ccwcode); extern void build_sense_3420 (int ERCode, DEVBLK *dev, BYTE *unitstat, BYTE ccwcode); extern void build_sense_3410_3420 (int ERCode, DEVBLK *dev, BYTE *unitstat, BYTE ccwcode); extern void build_sense_3480_etal (int ERCode, DEVBLK *dev, BYTE *unitstat, BYTE ccwcode); extern void build_sense_3490 (int ERCode, DEVBLK *dev, BYTE *unitstat, BYTE ccwcode); extern void build_sense_3590 (int ERCode, DEVBLK *dev, BYTE *unitstat, BYTE ccwcode); extern void build_sense_Streaming (int ERCode, DEVBLK *dev, BYTE *unitstat, BYTE ccwcode); /*-------------------------------------------------------------------*/ /* Calculate I/O Residual */ /*-------------------------------------------------------------------*/ #define RESIDUAL_CALC(_data_len) \ len = (_data_len); \ num = (count < len) ? count : len; \ *residual = count - num; \ if (count < len) *more = 1 /*-------------------------------------------------------------------*/ /* Assign a unique Message Id for this asynchronous I/O if needed */ /*-------------------------------------------------------------------*/ #if defined(OPTION_SCSI_TAPE) #define INCREMENT_MESSAGEID(_dev) \ if ((_dev)->SIC_active) \ (_dev)->msgid++ #else #define INCREMENT_MESSAGEID(_dev) #endif // defined(OPTION_SCSI_TAPE) /*-------------------------------------------------------------------*/ /* Functions defined in AWSTAPE.C */ /*-------------------------------------------------------------------*/ extern int open_awstape (DEVBLK *dev, BYTE *unitstat, BYTE code); extern void close_awstape (DEVBLK *dev); extern int passedeot_awstape (DEVBLK *dev); extern int rewind_awstape (DEVBLK *dev, BYTE *unitstat, BYTE code); extern int write_awsmark (DEVBLK *dev, BYTE *unitstat, BYTE code); extern int sync_awstape (DEVBLK *dev, BYTE *unitstat, BYTE code); extern int fsb_awstape (DEVBLK *dev, BYTE *unitstat, BYTE code); extern int bsb_awstape (DEVBLK *dev, BYTE *unitstat, BYTE code); extern int fsf_awstape (DEVBLK *dev, BYTE *unitstat, BYTE code); extern int bsf_awstape (DEVBLK *dev, BYTE *unitstat, BYTE code); extern int readhdr_awstape (DEVBLK *dev, off_t blkpos, AWSTAPE_BLKHDR *buf, BYTE *unitstat, BYTE code); extern int read_awstape (DEVBLK *dev, BYTE *buf, BYTE *unitstat, BYTE code); extern int write_awstape (DEVBLK *dev, BYTE *buf, U16 blklen, BYTE *unitstat, BYTE code); /*-------------------------------------------------------------------*/ /* Functions defined in FAKETAPE.C */ /*-------------------------------------------------------------------*/ extern int open_faketape (DEVBLK *dev, BYTE *unitstat, BYTE code); extern void close_faketape (DEVBLK *dev); extern int passedeot_faketape (DEVBLK *dev); extern int rewind_faketape (DEVBLK *dev, BYTE *unitstat, BYTE code); extern int write_fakemark (DEVBLK *dev, BYTE *unitstat, BYTE code); extern int sync_faketape (DEVBLK *dev, BYTE *unitstat, BYTE code); extern int fsb_faketape (DEVBLK *dev, BYTE *unitstat, BYTE code); extern int bsb_faketape (DEVBLK *dev, BYTE *unitstat, BYTE code); extern int fsf_faketape (DEVBLK *dev, BYTE *unitstat, BYTE code); extern int bsf_faketape (DEVBLK *dev, BYTE *unitstat, BYTE code); extern int readhdr_faketape (DEVBLK *dev, off_t blkpos, U16* pprvblkl, U16* pcurblkl, BYTE *unitstat, BYTE code); extern int writehdr_faketape (DEVBLK *dev, off_t blkpos, U16 prvblkl, U16 curblkl, BYTE *unitstat, BYTE code); extern int read_faketape (DEVBLK *dev, BYTE *buf, BYTE *unitstat, BYTE code); extern int write_faketape (DEVBLK *dev, BYTE *buf, U16 blklen, BYTE *unitstat, BYTE code); /*-------------------------------------------------------------------*/ /* Functions defined in HETTAPE.C */ /*-------------------------------------------------------------------*/ extern int open_het (DEVBLK *dev, BYTE *unitstat, BYTE code); extern void close_het (DEVBLK *dev); extern int passedeot_het (DEVBLK *dev); extern int rewind_het (DEVBLK *dev, BYTE *unitstat, BYTE code); extern int write_hetmark (DEVBLK *dev, BYTE *unitstat, BYTE code); extern int sync_het (DEVBLK *dev, BYTE *unitstat, BYTE code); extern int fsb_het (DEVBLK *dev, BYTE *unitstat, BYTE code); extern int bsb_het (DEVBLK *dev, BYTE *unitstat, BYTE code); extern int fsf_het (DEVBLK *dev, BYTE *unitstat, BYTE code); extern int bsf_het (DEVBLK *dev, BYTE *unitstat, BYTE code); extern int read_het (DEVBLK *dev, BYTE *buf, BYTE *unitstat, BYTE code); extern int write_het (DEVBLK *dev, BYTE *buf, U16 blklen, BYTE *unitstat, BYTE code); /*-------------------------------------------------------------------*/ /* Functions defined in OMATAPE.C */ /*-------------------------------------------------------------------*/ extern int open_omatape (DEVBLK *dev, BYTE *unitstat, BYTE code); extern void close_omatape (DEVBLK *dev); extern void close_omatape2 (DEVBLK *dev); extern int rewind_omatape (DEVBLK *dev, BYTE *unitstat, BYTE code); extern int fsb_omatape (DEVBLK *dev, BYTE *unitstat, BYTE code); extern int bsb_omatape (DEVBLK *dev, BYTE *unitstat, BYTE code); extern int fsf_omatape (DEVBLK *dev, BYTE *unitstat, BYTE code); extern int bsf_omatape (DEVBLK *dev, BYTE *unitstat, BYTE code); extern int read_omadesc (DEVBLK *dev); extern int fsb_omaheaders (DEVBLK *dev, OMATAPE_DESC *omadesc, BYTE *unitstat, BYTE code); extern int fsb_omafixed (DEVBLK *dev, OMATAPE_DESC *omadesc, BYTE *unitstat, BYTE code); extern int read_omaheaders (DEVBLK *dev, OMATAPE_DESC *omadesc, BYTE *buf, BYTE *unitstat, BYTE code); extern int read_omafixed (DEVBLK *dev, OMATAPE_DESC *omadesc, BYTE *buf, BYTE *unitstat, BYTE code); extern int read_omatext (DEVBLK *dev, OMATAPE_DESC *omadesc, BYTE *buf, BYTE *unitstat, BYTE code); extern int read_omatape (DEVBLK *dev, BYTE *buf, BYTE *unitstat, BYTE code); extern int readhdr_omaheaders (DEVBLK *dev, OMATAPE_DESC *omadesc, long blkpos, S32 *pcurblkl, S32 *pprvhdro, S32 *pnxthdro, BYTE *unitstat, BYTE code); /*-------------------------------------------------------------------*/ /* Functions defined in SCSITAPE.C */ /*-------------------------------------------------------------------*/ // (see SCSITAPE.H) #endif // __TAPEDEV_H__ hercules-3.07/tapemap.c000644 000765 000765 00000017372 11143760542 016553 0ustar00jmaynardjmaynard000000 000000 /* TAPEMAP.C (c) Copyright Jay Maynard, 2000-2009 */ /* Map AWSTAPE format tape image */ // $Id: tapemap.c 5127 2009-01-23 13:25:01Z bernard $ /*-------------------------------------------------------------------*/ /* This program reads an AWSTAPE format tape image file and produces */ /* a map of the tape, printing any standard label records it finds. */ /*-------------------------------------------------------------------*/ // $Log$ // Revision 1.27 2008/11/04 04:50:46 fish // Ensure consistent utility startup // // Revision 1.26 2007/06/23 00:04:18 ivan // Update copyright notices to include current year (2007) // // Revision 1.25 2006/12/08 09:43:31 jj // Add CVS message log // #include "hstdinc.h" #include "hercules.h" /*-------------------------------------------------------------------*/ /* Structure definition for AWSTAPE block header */ /*-------------------------------------------------------------------*/ typedef struct _AWSTAPE_BLKHDR { HWORD curblkl; /* Length of this block */ HWORD prvblkl; /* Length of previous block */ BYTE flags1; /* Flags byte 1 */ BYTE flags2; /* Flags byte 2 */ } AWSTAPE_BLKHDR; /* Definitions for AWSTAPE_BLKHDR flags byte 1 */ #define AWSTAPE_FLAG1_NEWREC 0x80 /* Start of new record */ #define AWSTAPE_FLAG1_TAPEMARK 0x40 /* Tape mark */ #define AWSTAPE_FLAG1_ENDREC 0x20 /* End of record */ /*-------------------------------------------------------------------*/ /* Static data areas */ /*-------------------------------------------------------------------*/ static BYTE vollbl[] = "\xE5\xD6\xD3"; /* EBCDIC characters "VOL" */ static BYTE hdrlbl[] = "\xC8\xC4\xD9"; /* EBCDIC characters "HDR" */ static BYTE eoflbl[] = "\xC5\xD6\xC6"; /* EBCDIC characters "EOF" */ static BYTE eovlbl[] = "\xC5\xD6\xE5"; /* EBCDIC characters "EOV" */ static BYTE buf[65536]; #ifdef EXTERNALGUI /* Report progress every this many bytes */ #define PROGRESS_MASK (~0x3FFFF /* 256K */) /* How many bytes we've read so far. */ long curpos = 0; long prevpos = 0; #endif /*EXTERNALGUI*/ /*-------------------------------------------------------------------*/ /* TAPEMAP main entry point */ /*-------------------------------------------------------------------*/ int main (int argc, char *argv[]) { int i; /* Array subscript */ int len; /* Block length */ int prevlen; /* Previous block length */ char *filename; /* -> Input file name */ int infd = -1; /* Input file descriptor */ int fileno; /* Tape file number */ int blkcount; /* Block count */ int curblkl; /* Current block length */ int minblksz; /* Minimum block size */ int maxblksz; /* Maximum block size */ BYTE labelrec[81]; /* Standard label (ASCIIZ) */ AWSTAPE_BLKHDR awshdr; /* AWSTAPE block header */ char pathname[MAX_PATH]; /* file path in host format */ INITIALIZE_UTILITY("tapemap"); /* Display the program identification message */ display_version (stderr, "Hercules tape map program ", FALSE); /* The only argument is the tape image file name */ if (argc == 2 && argv[1] != NULL) { filename = argv[1]; } else { printf ("Usage: tapemap filename\n"); exit (1); } /* Open the tape device */ hostpath(pathname, filename, sizeof(pathname)); infd = open (pathname, O_RDONLY | O_BINARY); if (infd < 0) { printf ("tapemap: Error opening %s: %s\n", filename, strerror(errno)); exit (2); } /* Read blocks from the input file and report on them */ fileno = 1; blkcount = 0; minblksz = 0; maxblksz = 0; len = 0; while (1) { #ifdef EXTERNALGUI if (extgui) { /* Report progress every nnnK */ if( ( curpos & PROGRESS_MASK ) != ( prevpos & PROGRESS_MASK ) ) { prevpos = curpos; fprintf( stderr, "IPOS=%ld\n", curpos ); } } #endif /*EXTERNALGUI*/ /* Save previous block length */ prevlen = len; /* Read a block from the tape */ len = read (infd, buf, sizeof(AWSTAPE_BLKHDR)); #ifdef EXTERNALGUI if (extgui) curpos += len; #endif /*EXTERNALGUI*/ if (len < 0) { printf ("tapemap: error reading header block from %s: %s\n", filename, strerror(errno)); exit (3); } /* Did we finish too soon? */ if ((len > 0) && (len < (int)sizeof(AWSTAPE_BLKHDR))) { printf ("tapemap: incomplete block header on %s\n", filename); exit(4); } /* Check for end of tape. */ if (len == 0) { printf ("End of tape.\n"); break; } /* Parse the block header */ memcpy(&awshdr, buf, sizeof(AWSTAPE_BLKHDR)); /* Tapemark? */ if ((awshdr.flags1 & AWSTAPE_FLAG1_TAPEMARK) != 0) { /* Print summary of current file */ printf ("File %u: Blocks=%u, block size min=%u, max=%u\n", fileno, blkcount, minblksz, maxblksz); /* Reset counters for next file */ fileno++; minblksz = 0; maxblksz = 0; blkcount = 0; } else /* if(tapemark) */ { /* Count blocks and block sizes */ blkcount++; curblkl = awshdr.curblkl[0] + (awshdr.curblkl[1] << 8); if (curblkl > maxblksz) maxblksz = curblkl; if (minblksz == 0 || curblkl < minblksz) minblksz = curblkl; /* Read the data block. */ len = read (infd, buf, curblkl); #ifdef EXTERNALGUI if (extgui) curpos += len; #endif /*EXTERNALGUI*/ if (len < 0) { printf ("tapemap: error reading data block from %s: %s\n", filename, strerror(errno)); exit (5); } /* Did we finish too soon? */ if ((len > 0) && (len < curblkl)) { printf ("tapemap: incomplete final data block on %s, " "expected %d bytes, got %d\n", filename, curblkl, len); exit(6); } /* Check for end of tape */ if (len == 0) { printf ("tapemap: header block with no data on %s\n", filename); exit(7); } /* Print standard labels */ if (len == 80 && blkcount < 4 && (memcmp(buf, vollbl, 3) == 0 || memcmp(buf, hdrlbl, 3) == 0 || memcmp(buf, eoflbl, 3) == 0 || memcmp(buf, eovlbl, 3) == 0)) { for (i=0; i < 80; i++) labelrec[i] = guest_to_host(buf[i]); labelrec[i] = '\0'; printf ("%s\n", labelrec); } } /* end if(tapemark) */ } /* end while */ /* Close files and exit */ close (infd); return 0; } /* end function main */ hercules-3.07/tapesplt.c000644 000765 000765 00000025122 11143760542 016750 0ustar00jmaynardjmaynard000000 000000 /* tapesplt.C (c) Copyright Jay Maynard, 2000-2009 */ /* Split AWSTAPE format tape image */ // $Id: tapesplt.c 5127 2009-01-23 13:25:01Z bernard $ /*-------------------------------------------------------------------*/ /* This program reads an AWSTAPE format tape image file and produces */ /* output files containing pieces of it, controlled by command line */ /* options. */ /*-------------------------------------------------------------------*/ // $Log$ // Revision 1.27 2008/11/04 04:50:46 fish // Ensure consistent utility startup // // Revision 1.26 2007/06/23 00:04:18 ivan // Update copyright notices to include current year (2007) // // Revision 1.25 2006/12/08 09:43:31 jj // Add CVS message log // #include "hstdinc.h" #include "hercules.h" /*-------------------------------------------------------------------*/ /* Structure definition for AWSTAPE block header */ /*-------------------------------------------------------------------*/ typedef struct _AWSTAPE_BLKHDR { HWORD curblkl; /* Length of this block */ HWORD prvblkl; /* Length of previous block */ BYTE flags1; /* Flags byte 1 */ BYTE flags2; /* Flags byte 2 */ } AWSTAPE_BLKHDR; /* Definitions for AWSTAPE_BLKHDR flags byte 1 */ #define AWSTAPE_FLAG1_NEWREC 0x80 /* Start of new record */ #define AWSTAPE_FLAG1_TAPEMARK 0x40 /* Tape mark */ #define AWSTAPE_FLAG1_ENDREC 0x20 /* End of record */ /*-------------------------------------------------------------------*/ /* Static data areas */ /*-------------------------------------------------------------------*/ static BYTE vollbl[] = "\xE5\xD6\xD3"; /* EBCDIC characters "VOL" */ static BYTE hdrlbl[] = "\xC8\xC4\xD9"; /* EBCDIC characters "HDR" */ static BYTE eoflbl[] = "\xC5\xD6\xC6"; /* EBCDIC characters "EOF" */ static BYTE eovlbl[] = "\xC5\xD6\xE5"; /* EBCDIC characters "EOV" */ static BYTE buf[65536]; #ifdef EXTERNALGUI /* Report progress every this many bytes */ #define PROGRESS_MASK (~0x3FFFF /* 256K */) /* How many bytes we've read so far. */ long curpos = 0; long prevpos = 0; #endif /*EXTERNALGUI*/ /*-------------------------------------------------------------------*/ /* tapesplt main entry point */ /*-------------------------------------------------------------------*/ int main (int argc, char *argv[]) { int rc; /* Return code */ int i; /* Array subscript */ int len; /* Block length */ int prevlen; /* Previous block length */ char *infilename; /* -> Input file name */ char *outfilename; /* -> Current out file name */ int infd = -1; /* Input file descriptor */ int outfd = -1; /* Current out file desc */ int fileno; /* Tape file number */ int blkcount; /* Block count */ int curblkl; /* Current block length */ int minblksz; /* Minimum block size */ int maxblksz; /* Maximum block size */ int outfilenum; /* Current out file# in argv */ int outfilecount; /* Current # files copied */ int files2copy; /* Current # files to copy */ BYTE labelrec[81]; /* Standard label (ASCIIZ) */ AWSTAPE_BLKHDR awshdr; /* AWSTAPE block header */ char pathname[MAX_PATH]; /* file path in host format */ INITIALIZE_UTILITY("tapesplt"); /* Display the program identification message */ display_version (stderr, "Hercules tape split program ", FALSE); /* The only argument is the tape image file name */ if (argc > 3 && argv[1] != NULL) { infilename = argv[1]; } else { printf ("Usage: tapesplt infilename outfilename count [...]\n"); exit (1); } /* Open the tape device */ hostpath(pathname, infilename, sizeof(pathname)); infd = open (pathname, O_RDONLY | O_BINARY); if (infd < 0) { printf ("tapesplt: error opening input file %s: %s\n", infilename, strerror(errno)); exit (2); } /* Copy blocks from input to output files */ fileno = 1; blkcount = 0; minblksz = 0; maxblksz = 0; len = 0; for (outfilenum = 2; outfilenum < argc; outfilenum += 2) { outfilename = argv[outfilenum]; printf ("Writing output file %s.\n", outfilename); hostpath(pathname, outfilename, sizeof(pathname)); outfd = open (pathname, O_WRONLY | O_CREAT | O_BINARY, S_IRUSR | S_IWUSR | S_IRGRP); if (outfd < 0) { printf ("tapesplt: error opening output file %s: %s\n", outfilename, strerror(errno)); exit (3); } if (outfilenum == argc) { /* count not specified for last file, so use big number */ files2copy = 32767; } else { files2copy = atoi(argv[outfilenum + 1]); } /* Copy just that many files */ for (outfilecount = 0; outfilecount < files2copy; ) { /* Save previous block length */ prevlen = len; /* Read a block from the tape */ len = read (infd, buf, sizeof(AWSTAPE_BLKHDR)); if (len < 0) { printf ("tapesplt: error reading header block from %s: %s\n", infilename, strerror(errno)); exit (4); } /* Did we finish too soon? */ if ((len > 0) && (len < (int)sizeof(AWSTAPE_BLKHDR))) { printf ("tapesplt: incomplete block header on %s\n", infilename); exit(5); } #ifdef EXTERNALGUI if (extgui) { curpos += len; /* Report progress every nnnK */ if( ( curpos & PROGRESS_MASK ) != ( prevpos & PROGRESS_MASK ) ) { prevpos = curpos; fprintf( stderr, "IPOS=%ld\n", curpos ); } } #endif /*EXTERNALGUI*/ /* Check for end of tape. */ if (len == 0) { printf ("End of input tape.\n"); break; } /* Copy the header to the output file. */ rc = write(outfd, buf, sizeof(AWSTAPE_BLKHDR)); if (rc < (int)sizeof(AWSTAPE_BLKHDR)) { printf ("tapesplt: error writing block header to %s: %s\n", outfilename, strerror(errno)); exit(6); } /* Parse the block header */ memcpy(&awshdr, buf, sizeof(AWSTAPE_BLKHDR)); /* Tapemark? */ if ((awshdr.flags1 & AWSTAPE_FLAG1_TAPEMARK) != 0) { /* Print summary of current file */ printf ("File %u: Blocks=%u, block size min=%u, max=%u\n", fileno, blkcount, minblksz, maxblksz); /* Reset counters for next file */ fileno++; minblksz = 0; maxblksz = 0; blkcount = 0; /* Count the file we just copied. */ outfilecount++; } else /* if(tapemark) */ { /* Count blocks and block sizes */ blkcount++; curblkl = awshdr.curblkl[0] + (awshdr.curblkl[1] << 8); if (curblkl > maxblksz) maxblksz = curblkl; if (minblksz == 0 || curblkl < minblksz) minblksz = curblkl; /* Read the data block. */ len = read (infd, buf, curblkl); if (len < 0) { printf ("tapesplt: error reading data block from %s: %s\n", infilename, strerror(errno)); exit (7); } /* Did we finish too soon? */ if ((len > 0) && (len < curblkl)) { printf ("tapesplt: incomplete final data block on %s: " "expected %d bytes, got %d\n", infilename, curblkl, len); exit(8); } /* Check for end of tape */ if (len == 0) { printf ("tapesplt: header block with no data on %s\n", infilename); exit(9); } #ifdef EXTERNALGUI if (extgui) { curpos += len; /* Report progress every nnnK */ if( ( curpos & PROGRESS_MASK ) != ( prevpos & PROGRESS_MASK ) ) { prevpos = curpos; fprintf( stderr, "IPOS=%ld\n", curpos ); } } #endif /*EXTERNALGUI*/ /* Copy the header to the output file. */ rc = write(outfd, buf, len); if (rc < len) { printf ("tapesplt: error writing data block to %s: %s\n", outfilename, strerror(errno)); exit(10); } /* Print standard labels */ if (len == 80 && blkcount < 4 && (memcmp(buf, vollbl, 3) == 0 || memcmp(buf, hdrlbl, 3) == 0 || memcmp(buf, eoflbl, 3) == 0 || memcmp(buf, eovlbl, 3) == 0)) { for (i=0; i < 80; i++) labelrec[i] = guest_to_host(buf[i]); labelrec[i] = '\0'; printf ("%s\n", labelrec); } } /* end if(tapemark) */ } /* end for(outfilecount) */ close(outfd); } /* end for(outfilenum) */ /* Close files and exit */ close (infd); return 0; } /* end function main */ hercules-3.07/timer.c000644 000765 000765 00000023444 11321734033 016233 0ustar00jmaynardjmaynard000000 000000 /* TIMER.C */ /* z/Architecture support - (c) Copyright Jan Jaeger, 1999-2009 */ // $Id: timer.c 5558 2009-12-24 01:49:18Z fish $ // // $Log$ // Revision 1.67 2007/12/10 23:12:02 gsmith // Tweaks to OPTION_MIPS_COUNTING processing // // Revision 1.66 2007/09/05 00:24:18 gsmith // Use integer arithmetic calculating cpupct // // Revision 1.65 2007/06/23 00:04:18 ivan // Update copyright notices to include current year (2007) // // Revision 1.64 2006/12/08 09:43:31 jj // Add CVS message log // #include "hstdinc.h" #include "hercules.h" #include "opcode.h" #include "feat390.h" #include "feat370.h" // ZZ int ecpsvm_testvtimer(REGS *,int); /*-------------------------------------------------------------------*/ /* Check for timer event */ /* */ /* Checks for the following interrupts: */ /* [1] Clock comparator */ /* [2] CPU timer */ /* [3] Interval timer */ /* CPUs with an outstanding interrupt are signalled */ /* */ /* tod_delta is in hercules internal clock format (>> 8) */ /*-------------------------------------------------------------------*/ void update_cpu_timer(void) { int cpu; /* CPU counter */ REGS *regs; /* -> CPU register context */ CPU_BITMAP intmask = 0; /* Interrupt CPU mask */ /* Access the diffent register contexts with the intlock held */ OBTAIN_INTLOCK(NULL); /* Check for [1] clock comparator, [2] cpu timer, and * [3] interval timer interrupts for each CPU. */ for (cpu = 0; cpu < HI_CPU; cpu++) { /* Ignore this CPU if it is not started */ if (!IS_CPU_ONLINE(cpu) || CPUSTATE_STOPPED == sysblk.regs[cpu]->cpustate) continue; /* Point to the CPU register context */ regs = sysblk.regs[cpu]; /*-------------------------------------------* * [1] Check for clock comparator interrupt * *-------------------------------------------*/ if (TOD_CLOCK(regs) > regs->clkc) { if (!IS_IC_CLKC(regs)) { ON_IC_CLKC(regs); intmask |= regs->cpubit; } } else if (IS_IC_CLKC(regs)) OFF_IC_CLKC(regs); #if defined(_FEATURE_SIE) /* If running under SIE also check the SIE copy */ if(regs->sie_active) { /* Signal clock comparator interrupt if needed */ if(TOD_CLOCK(regs->guestregs) > regs->guestregs->clkc) { ON_IC_CLKC(regs->guestregs); intmask |= regs->cpubit; } else OFF_IC_CLKC(regs->guestregs); } #endif /*defined(_FEATURE_SIE)*/ /*-------------------------------------------* * [2] Decrement the CPU timer for each CPU * *-------------------------------------------*/ /* Set interrupt flag if the CPU timer is negative */ if (CPU_TIMER(regs) < 0) { if (!IS_IC_PTIMER(regs)) { ON_IC_PTIMER(regs); intmask |= regs->cpubit; } } else if(IS_IC_PTIMER(regs)) OFF_IC_PTIMER(regs); #if defined(_FEATURE_SIE) /* When running under SIE also update the SIE copy */ if(regs->sie_active) { /* Set interrupt flag if the CPU timer is negative */ if (CPU_TIMER(regs->guestregs) < 0) { ON_IC_PTIMER(regs->guestregs); intmask |= regs->cpubit; } else OFF_IC_PTIMER(regs->guestregs); } #endif /*defined(_FEATURE_SIE)*/ #if defined(_FEATURE_INTERVAL_TIMER) /*-------------------------------------------* * [3] Check for interval timer interrupt * *-------------------------------------------*/ if(regs->arch_mode == ARCH_370) { if( chk_int_timer(regs) ) intmask |= regs->cpubit; } #if defined(_FEATURE_SIE) /* When running under SIE also update the SIE copy */ if(regs->sie_active) { if(SIE_STATB(regs->guestregs, M, 370) && SIE_STATNB(regs->guestregs, M, ITMOF)) { if( chk_int_timer(regs->guestregs) ) intmask |= regs->cpubit; } } #endif /*defined(_FEATURE_SIE)*/ #endif /*defined(_FEATURE_INTERVAL_TIMER)*/ } /* end for(cpu) */ /* If a timer interrupt condition was detected for any CPU then wake up those CPUs if they are waiting */ WAKEUP_CPUS_MASK (intmask); RELEASE_INTLOCK(NULL); } /* end function check_timer_event */ /*-------------------------------------------------------------------*/ /* TOD clock and timer thread */ /* */ /* This function runs as a separate thread. It wakes up every */ /* 1 microsecond, updates the TOD clock, and decrements the */ /* CPU timer for each CPU. If any CPU timer goes negative, or */ /* if the TOD clock exceeds the clock comparator for any CPU, */ /* it signals any waiting CPUs to wake up and process interrupts. */ /*-------------------------------------------------------------------*/ void *timer_update_thread (void *argp) { #ifdef OPTION_MIPS_COUNTING int i; /* Loop index */ REGS *regs; /* -> REGS */ U64 now; /* Current time of day (us) */ U64 then; /* Previous time of day (us) */ U64 diff; /* Interval (us) */ U64 mipsrate; /* Calculated MIPS rate */ U64 siosrate; /* Calculated SIO rate */ U64 cpupct; /* Calculated cpu percentage */ U64 total_mips; /* Total MIPS rate */ U64 total_sios; /* Total SIO rate */ #endif /*OPTION_MIPS_COUNTING*/ UNREFERENCED(argp); /* Set root mode in order to set priority */ SETMODE(ROOT); /* Set timer thread priority */ if (setpriority(PRIO_PROCESS, 0, sysblk.todprio)) logmsg (_("HHCTT001W Timer thread set priority %d failed: %s\n"), sysblk.todprio, strerror(errno)); /* Back to user mode */ SETMODE(USER); /* Display thread started message on control panel */ logmsg (_("HHCTT002I Timer thread started: tid="TIDPAT", pid=%d, " "priority=%d\n"), thread_id(), getpid(), getpriority(PRIO_PROCESS,0)); #ifdef OPTION_MIPS_COUNTING then = host_tod(); #endif while (sysblk.cpus) { /* Update TOD clock */ update_tod_clock(); #ifdef OPTION_MIPS_COUNTING now = host_tod(); diff = now - then; if (diff >= 1000000) { then = now; total_mips = total_sios = 0; #if defined(OPTION_SHARED_DEVICES) total_sios = sysblk.shrdcount; sysblk.shrdcount = 0; #endif for (i = 0; i < HI_CPU; i++) { obtain_lock (&sysblk.cpulock[i]); if (!IS_CPU_ONLINE(i)) { release_lock(&sysblk.cpulock[i]); continue; } regs = sysblk.regs[i]; /* 0% if CPU is STOPPED */ if (regs->cpustate == CPUSTATE_STOPPED) { regs->mipsrate = regs->siosrate = regs->cpupct = 0; release_lock(&sysblk.cpulock[i]); continue; } /* Calculate instructions per second */ mipsrate = regs->instcount; regs->instcount = 0; regs->prevcount += mipsrate; mipsrate = (mipsrate*1000000 + diff/2) / diff; if (mipsrate > MAX_REPORTED_MIPSRATE) mipsrate = 0; regs->mipsrate = mipsrate; total_mips += mipsrate; /* Calculate SIOs per second */ siosrate = regs->siocount; regs->siocount = 0; regs->siototal += siosrate; siosrate = (siosrate*1000000 + diff/2) / diff; if (siosrate > MAX_REPORTED_SIOSRATE) siosrate = 0; regs->siosrate = siosrate; total_sios += siosrate; /* Calculate CPU busy percentage */ cpupct = regs->waittime; regs->waittime = 0; if (regs->waittod) { cpupct += now - regs->waittod; regs->waittod = now; } cpupct = ((diff - cpupct)*100) / diff; if (cpupct > 100) cpupct = 100; regs->cpupct = cpupct; release_lock(&sysblk.cpulock[i]); } /* end for(cpu) */ /* Total for ALL CPUs together */ sysblk.mipsrate = total_mips; sysblk.siosrate = total_sios; } /* end if(diff >= 1000000) */ #endif /*OPTION_MIPS_COUNTING*/ /* Sleep for another timer update interval... */ usleep ( sysblk.timerint ); } /* end while */ logmsg (_("HHCTT003I Timer thread ended\n")); sysblk.todtid = 0; return NULL; } /* end function timer_update_thread */ hercules-3.07/trace.c000644 000765 000765 00000116676 11143760543 016232 0ustar00jmaynardjmaynard000000 000000 /* TRACE.C (c) Copyright Jan Jaeger, 2000-2009 */ /* Implicit tracing functions */ // $Id: trace.c 5127 2009-01-23 13:25:01Z bernard $ /* Interpretive Execution - (c) Copyright Jan Jaeger, 1999-2009 */ /* z/Architecture support - (c) Copyright Jan Jaeger, 1999-2009 */ /*-------------------------------------------------------------------*/ /* This module contains procedures for creating entries in the */ /* system trace table as described in the manuals: */ /* SA22-7201 ESA/390 Principles of Operation */ /* SA22-7832 z/Architecture Principles of Operation */ /*-------------------------------------------------------------------*/ /*-------------------------------------------------------------------*/ /* Additional credits: */ /* ASN-and-LX-reuse facility - Roger Bowler July 2004*/ /*-------------------------------------------------------------------*/ // $Log$ // Revision 1.32 2008/02/28 22:06:34 ptl00 // Fix mode switch trace // // Revision 1.31 2007/06/23 00:04:19 ivan // Update copyright notices to include current year (2007) // // Revision 1.30 2006/12/20 04:26:20 gsmith // 19 Dec 2006 ip_all.pat - performance patch - Greg Smith // // Revision 1.29 2006/12/08 09:43:31 jj // Add CVS message log // #include "hstdinc.h" #if !defined(_HENGINE_DLL_) #define _HENGINE_DLL_ #endif #if !defined(_TRACE_C_) #define _TRACE_C_ #endif #include "hercules.h" #include "opcode.h" #include "inline.h" #if defined(FEATURE_TRACING) #if !defined(_TRACE_H) #define _TRACE_H /*-------------------------------------------------------------------*/ /* Format definitions for trace table entries */ /*-------------------------------------------------------------------*/ typedef struct _TRACE_F1_BR { FWORD newia24; /* Bits 0-7 are zeros */ } TRACE_F1_BR; typedef struct _TRACE_F2_BR { FWORD newia31; /* Bit 0 is one */ } TRACE_F2_BR; typedef struct _TRACE_F3_BR { BYTE format; /* B'01010010' */ #define TRACE_F3_BR_FMT 0x52 BYTE fmt2; /* B'1100' B'0000' */ #define TRACE_F3_BR_FM2 0xC0 HWORD resv; DBLWRD newia64; } TRACE_F3_BR; typedef struct _TRACE_F1_BSG { BYTE format; /* B'01000001' */ #define TRACE_F1_BSG_FMT 0x41 BYTE alet[3]; FWORD newia; } TRACE_F1_BSG; typedef struct _TRACE_F2_BSG { BYTE format; /* B'01000010' */ #define TRACE_F2_BSG_FMT 0x42 BYTE alet[3]; DBLWRD newia; } TRACE_F2_BSG; typedef struct _TRACE_F1_MS { BYTE format; #define TRACE_F1_MS_FMT 0x51 BYTE fmt2; #define TRACE_F1_MS_FM2 0x30 HWORD resv; FWORD newia; } TRACE_F1_MS; typedef struct _TRACE_F2_MS { BYTE format; #define TRACE_F2_MS_FMT 0x51 BYTE fmt2; #define TRACE_F2_MS_FM2 0x20 HWORD resv; FWORD newia; } TRACE_F2_MS; typedef struct _TRACE_F3_MS { BYTE format; #define TRACE_F3_MS_FMT 0x52 BYTE fmt2; #define TRACE_F3_MS_FM2 0x60 HWORD resv; DBLWRD newia; } TRACE_F3_MS; typedef struct _TRACE_F1_MSB { BYTE format; #define TRACE_F1_MSB_FMT 0x51 BYTE fmt2; #define TRACE_F1_MSB_FM2 0xA0 HWORD resv; FWORD newia; } TRACE_F1_MSB; typedef struct _TRACE_F2_MSB { BYTE format; #define TRACE_F2_MSB_FMT 0x51 BYTE fmt2; #define TRACE_F2_MSB_FM2 0xB0 HWORD resv; FWORD newia; } TRACE_F2_MSB; typedef struct _TRACE_F3_MSB { BYTE format; #define TRACE_F3_MSB_FMT 0x52 BYTE fmt2; #define TRACE_F3_MSB_FM2 0xF0 HWORD resv; DBLWRD newia; } TRACE_F3_MSB; typedef struct _TRACE_F1_PT { BYTE format; #define TRACE_F1_PT_FMT 0x31 BYTE pswkey; #define TRACE_F1_PT_FM2 0x00 HWORD newpasn; FWORD r2; } TRACE_F1_PT; typedef struct _TRACE_F2_PT { BYTE format; #define TRACE_F2_PT_FMT 0x31 BYTE pswkey; #define TRACE_F2_PT_FM2 0x08 HWORD newpasn; FWORD r2; } TRACE_F2_PT; typedef struct _TRACE_F3_PT { BYTE format; #define TRACE_F3_PT_FMT 0x32 BYTE pswkey; #define TRACE_F3_PT_FM2 0x0C HWORD newpasn; DBLWRD r2; } TRACE_F3_PT; typedef struct _TRACE_F1_SSAR { BYTE format; #define TRACE_F1_SSAR_FMT 0x10 BYTE extfmt; HWORD newsasn; } TRACE_F1_SSAR; typedef struct _TRACE_F1_TRACE { BYTE format; BYTE zero; HWORD tod1631; FWORD tod3263; FWORD operand; FWORD regs[16]; } TRACE_F1_TRACE; typedef struct _TRACE_F2_TRACE { BYTE format; BYTE extfmt; HWORD tod1631; DBLWRD tod3279; FWORD operand; DBLWRD regs[16]; } TRACE_F2_TRACE; typedef struct _TRACE_F1_PR { BYTE format; #define TRACE_F1_PR_FMT 0x32 BYTE pswkey; #define TRACE_F1_PR_FM2 0x00 HWORD newpasn; FWORD retna; FWORD newia; } TRACE_F1_PR; typedef struct _TRACE_F2_PR { BYTE format; #define TRACE_F2_PR_FMT 0x32 BYTE pswkey; #define TRACE_F2_PR_FM2 0x02 HWORD newpasn; FWORD retna; FWORD newia; } TRACE_F2_PR; typedef struct _TRACE_F3_PR { BYTE format; #define TRACE_F3_PR_FMT 0x33 BYTE pswkey; #define TRACE_F3_PR_FM2 0x03 HWORD newpasn; FWORD retna; DBLWRD newia; } TRACE_F3_PR; typedef struct _TRACE_F4_PR { BYTE format; #define TRACE_F4_PR_FMT 0x32 BYTE pswkey; #define TRACE_F4_PR_FM2 0x08 HWORD newpasn; FWORD retna; FWORD newia; } TRACE_F4_PR; typedef struct _TRACE_F5_PR { BYTE format; #define TRACE_F5_PR_FMT 0x32 BYTE pswkey; #define TRACE_F5_PR_FM2 0x0A HWORD newpasn; FWORD retna; FWORD newia; } TRACE_F5_PR; typedef struct _TRACE_F6_PR { BYTE format; #define TRACE_F6_PR_FMT 0x33 BYTE pswkey; #define TRACE_F6_PR_FM2 0x0B HWORD newpasn; FWORD retna; DBLWRD newia; } TRACE_F6_PR; typedef struct _TRACE_F7_PR { BYTE format; #define TRACE_F7_PR_FMT 0x33 BYTE pswkey; #define TRACE_F7_PR_FM2 0x0C HWORD newpasn; DBLWRD retna; FWORD newia; } TRACE_F7_PR; typedef struct _TRACE_F8_PR { BYTE format; #define TRACE_F8_PR_FMT 0x33 BYTE pswkey; #define TRACE_F8_PR_FM2 0x0E HWORD newpasn; DBLWRD retna; FWORD newia; } TRACE_F8_PR; typedef struct _TRACE_F9_PR { BYTE format; #define TRACE_F9_PR_FMT 0x34 BYTE pswkey; #define TRACE_F9_PR_FM2 0x0F HWORD newpasn; DBLWRD retna; DBLWRD newia; } TRACE_F9_PR; typedef struct _TRACE_F1_PC { BYTE format; #define TRACE_F1_PC_FMT 0x21 BYTE pswkey_pcnum_hi; HWORD pcnum_lo; FWORD retna; } TRACE_F1_PC; typedef struct _TRACE_F2_PC { BYTE format; #define TRACE_F2_PC_FMT 0x22 BYTE pswkey_pcnum_hi; HWORD pcnum_lo; DBLWRD retna; } TRACE_F2_PC; typedef struct _TRACE_F3_PC { BYTE format; #define TRACE_F3_PC_FMT 0x21 BYTE pswkey_pcnum_hi; HWORD pcnum_lo; FWORD retna; } TRACE_F3_PC; typedef struct _TRACE_F4_PC { BYTE format; #define TRACE_F4_PC_FMT 0x22 BYTE pswkey_pcnum_hi; HWORD pcnum_lo; DBLWRD retna; } TRACE_F4_PC; typedef struct _TRACE_F5_PC { BYTE format; #define TRACE_F5_PC_FMT 0x22 BYTE pswkey; #define TRACE_F5_PC_FM2 0x08 HWORD resv; FWORD retna; FWORD pcnum; } TRACE_F5_PC; typedef struct _TRACE_F6_PC { BYTE format; #define TRACE_F6_PC_FMT 0x22 BYTE pswkey; #define TRACE_F6_PC_FM2 0x0A HWORD resv; FWORD retna; FWORD pcnum; } TRACE_F6_PC; typedef struct _TRACE_F7_PC { BYTE format; #define TRACE_F7_PC_FMT 0x23 BYTE pswkey; #define TRACE_F7_PC_FM2 0x0E HWORD resv; DBLWRD retna; FWORD pcnum; } TRACE_F7_PC; typedef struct _TRACE_F1_TR { BYTE format; #define TRACE_F1_TR_FMT 0x70 BYTE fmt2; #define TRACE_F1_TR_FM2 0x00 HWORD clk16; FWORD clk32; FWORD operand; FWORD reg[16]; } TRACE_F1_TR; typedef struct _TRACE_F2_TR { BYTE format; #define TRACE_F2_TR_FMT 0x70 BYTE fmt2; #define TRACE_F2_TR_FM2 0x80 HWORD clk0; FWORD clk16; FWORD clk48; FWORD operand; DBLWRD reg[16]; } TRACE_F2_TR; #endif /*!defined(_TRACE_H)*/ /*-------------------------------------------------------------------*/ /* Reserve space for a new trace entry */ /* */ /* Input: */ /* size Number of bytes required for trace entry */ /* regs Pointer to the CPU register context */ /* Output: */ /* abs_guest Guest absolute address of trace entry (if SIE) */ /* Return value: */ /* Absolute address of new trace entry */ /* */ /* This function does not return if a program check occurs. */ /*-------------------------------------------------------------------*/ static inline RADR ARCH_DEP(get_trace_entry) (RADR *abs_guest, int size, REGS *regs) { RADR n; /* Addr of trace table entry */ /* Obtain the trace entry address from control register 12 */ n = regs->CR(12) & CR12_TRACEEA; /* Apply low-address protection to trace entry address */ if (ARCH_DEP(is_low_address_protected) (n, regs)) { #ifdef FEATURE_SUPPRESSION_ON_PROTECTION regs->TEA = (n & STORAGE_KEY_PAGEMASK); regs->excarid = 0; #endif /*FEATURE_SUPPRESSION_ON_PROTECTION*/ ARCH_DEP(program_interrupt) (regs, PGM_PROTECTION_EXCEPTION); } /* Program check if trace entry is outside main storage */ if ( n > regs->mainlim ) ARCH_DEP(program_interrupt) (regs, PGM_ADDRESSING_EXCEPTION); /* Program check if storing would overflow a 4K page boundary */ if ( ((n + size) & PAGEFRAME_PAGEMASK) != (n & PAGEFRAME_PAGEMASK) ) ARCH_DEP(program_interrupt) (regs, PGM_TRACE_TABLE_EXCEPTION); /* Convert trace entry real address to absolute address */ n = APPLY_PREFIXING (n, regs->PX); #if defined(_FEATURE_SIE) *abs_guest = n; SIE_TRANSLATE(&n, ACCTYPE_WRITE, regs); #endif /*defined(_FEATURE_SIE)*/ return n; } /* end function ARCH_DEP(get_trace_entry) */ /*-------------------------------------------------------------------*/ /* Commit a new trace entry */ /* */ /* Input: */ /* abs_guest Guest absolute address of trace entry (if SIE) */ /* raddr Absolute address of trace entry */ /* size Number of bytes reserved for trace entry */ /* regs Pointer to the CPU register context */ /* Return value: */ /* Updated value for CR12 after committing the trace entry */ /*-------------------------------------------------------------------*/ static inline CREG ARCH_DEP(set_trace_entry) (RADR abs_guest, RADR raddr, int size, REGS *regs) { #if defined(_FEATURE_SIE) RADR abs_host; abs_host = raddr; #endif /*defined(_FEATURE_SIE)*/ raddr += size; #if defined(_FEATURE_SIE) /* Recalculate the Guest absolute address */ raddr = abs_guest + (raddr - abs_host); #endif /*defined(_FEATURE_SIE)*/ /* Convert trace entry absolute address back to real address */ raddr = APPLY_PREFIXING (raddr, regs->PX); /* Return updated value of control register 12 */ return (regs->CR(12) & ~CR12_TRACEEA) | raddr; } /* end function ARCH_DEP(set_trace_entry) */ /*-------------------------------------------------------------------*/ /* Form implicit branch trace entry */ /* */ /* Input: */ /* amode Non-zero if branch destination is a 31-bit address */ /* or a 64 bit address */ /* ia Branch destination address */ /* regs Pointer to the CPU register context */ /* Return value: */ /* Updated value for CR12 after adding new trace entry */ /* */ /* This function does not return if a program check occurs. */ /*-------------------------------------------------------------------*/ CREG ARCH_DEP(trace_br) (int amode, VADR ia, REGS *regs) { RADR raddr; RADR ag; int size; #if defined(FEATURE_ESAME) if(amode && ia > 0xFFFFFFFFULL) { TRACE_F3_BR *tte; size = sizeof(TRACE_F3_BR); raddr = ARCH_DEP(get_trace_entry) (&ag, size, regs); tte = (void*)(regs->mainstor + raddr); tte->format = TRACE_F3_BR_FMT; tte->fmt2 = TRACE_F3_BR_FM2; STORE_HW(tte->resv,0); STORE_DW(tte->newia64,ia); } else #endif /*defined(FEATURE_ESAME)*/ if(amode) { TRACE_F2_BR *tte; size = sizeof(TRACE_F2_BR); raddr = ARCH_DEP(get_trace_entry) (&ag, size, regs); tte = (void*)(regs->mainstor + raddr); STORE_FW(tte->newia31,ia | 0x80000000); } else { TRACE_F1_BR *tte; size = sizeof(TRACE_F1_BR); raddr = ARCH_DEP(get_trace_entry) (&ag, size, regs); tte = (void*)(regs->mainstor + raddr); STORE_FW(tte->newia24,ia & 0x00FFFFFF); } return ARCH_DEP(set_trace_entry) (ag, raddr, size, regs); } /* end function ARCH_DEP(trace_br) */ #if defined(FEATURE_SUBSPACE_GROUP) /*-------------------------------------------------------------------*/ /* Form implicit BSG trace entry */ /* */ /* Input: */ /* alet Destination address space ALET */ /* ia Branch destination address */ /* regs Pointer to the CPU register context */ /* Return value: */ /* Updated value for CR12 after adding new trace entry */ /* */ /* This function does not return if a program check occurs. */ /*-------------------------------------------------------------------*/ CREG ARCH_DEP(trace_bsg) (U32 alet, VADR ia, REGS *regs) { RADR raddr; RADR ag; int size; #if defined(FEATURE_ESAME) if(regs->psw.amode64) { TRACE_F2_BSG *tte; size = sizeof(TRACE_F2_BSG); raddr = ARCH_DEP(get_trace_entry) (&ag, size, regs); tte = (void*)(regs->mainstor + raddr); tte->format = TRACE_F2_BSG_FMT; tte->alet[0] = (alet >> 16) & 0xFF; tte->alet[1] = (alet >> 8) & 0xFF; tte->alet[2] = alet & 0xFF; STORE_DW(tte->newia,ia); } else #endif /*defined(FEATURE_ESAME)*/ { TRACE_F1_BSG *tte; size = sizeof(TRACE_F1_BSG); raddr = ARCH_DEP(get_trace_entry) (&ag, size, regs); tte = (void*)(regs->mainstor + raddr); tte->format = TRACE_F1_BSG_FMT; tte->alet[0] = ((alet >> 17) & 0x80) | ((alet >> 16) & 0x7F); tte->alet[1] = (alet >> 8) & 0xFF; tte->alet[2] = alet & 0xFF; if ((ia & 0x80000000) == 0) ia &=0x00FFFFFF; STORE_FW(tte->newia,ia); } return ARCH_DEP(set_trace_entry) (ag, raddr, size, regs); } /* end function ARCH_DEP(trace_bsg) */ #endif /*defined(FEATURE_SUBSPACE_GROUP)*/ /*-------------------------------------------------------------------*/ /* Form implicit SSAR/SSAIR trace entry */ /* */ /* Input: */ /* ssair 1=SSAIR instruction, 0=SSAR instruction */ /* sasn Secondary address space number */ /* regs Pointer to the CPU register context */ /* Return value: */ /* Updated value for CR12 after adding new trace entry */ /* */ /* This function does not return if a program check occurs. */ /*-------------------------------------------------------------------*/ CREG ARCH_DEP(trace_ssar) (int ssair, U16 sasn, REGS *regs) { RADR raddr; RADR ag; int size; BYTE nbit = (ssair ? 1 : 0); { TRACE_F1_SSAR *tte; size = sizeof(TRACE_F1_SSAR); raddr = ARCH_DEP(get_trace_entry) (&ag, size, regs); tte = (void*)(regs->mainstor + raddr); tte->format = TRACE_F1_SSAR_FMT; tte->extfmt = 0 | nbit; STORE_HW(tte->newsasn,sasn); } return ARCH_DEP(set_trace_entry) (ag, raddr, size, regs); } /* end function ARCH_DEP(trace_ssar) */ /*-------------------------------------------------------------------*/ /* Form implicit PC trace entry */ /* */ /* Input: */ /* pcea PC instruction effective address (20 or 32 bits) */ /* regs Pointer to the CPU register context */ /* Return value: */ /* Updated value for CR12 after adding new trace entry */ /* */ /* This function does not return if a program check occurs. */ /*-------------------------------------------------------------------*/ CREG ARCH_DEP(trace_pc) (U32 pcea, REGS *regs) { RADR raddr; RADR ag; int size; int eamode; SET_PSW_IA(regs); eamode = regs->psw.amode64; #if defined(FEATURE_ESAME) if (ASN_AND_LX_REUSE_ENABLED(regs)) { if ((pcea & PC_BIT44) && regs->psw.amode64 && regs->psw.IA_H) { /* In 64-bit mode, regardless of resulting mode, when ASN-and-LX-reuse is enabled, 32-bit PC number is used, and bits 0-31 of return address are not all zeros */ TRACE_F7_PC *tte; size = sizeof(TRACE_F7_PC); raddr = ARCH_DEP(get_trace_entry) (&ag, size, regs); tte = (void*)(regs->mainstor + raddr); tte->format = TRACE_F7_PC_FMT; tte->pswkey = regs->psw.pkey | TRACE_F7_PC_FM2 | eamode; STORE_HW(tte->resv, 0x0000); STORE_DW(tte->retna, regs->psw.IA_G | PROBSTATE(®s->psw)); STORE_FW(tte->pcnum, pcea); } else if ((pcea & PC_BIT44) && regs->psw.amode64) { /* In 64-bit mode, regardless of resulting mode, when ASN-and-LX-reuse is enabled, 32-bit PC number is used, and bits 0-31 of return address are all zeros */ TRACE_F6_PC *tte; size = sizeof(TRACE_F6_PC); raddr = ARCH_DEP(get_trace_entry) (&ag, size, regs); tte = (void*)(regs->mainstor + raddr); tte->format = TRACE_F6_PC_FMT; tte->pswkey = regs->psw.pkey | TRACE_F6_PC_FM2 | eamode; STORE_HW(tte->resv, 0x0000); STORE_FW(tte->retna, regs->psw.IA_L | PROBSTATE(®s->psw)); STORE_FW(tte->pcnum, pcea); } else if ((pcea & PC_BIT44)) { /* In 24-bit or 31-bit mode, regardless of resulting mode, when ASN-and-LX-reuse is enabled and 32-bit PC number is used */ TRACE_F5_PC *tte; size = sizeof(TRACE_F5_PC); raddr = ARCH_DEP(get_trace_entry) (&ag, size, regs); tte = (void*)(regs->mainstor + raddr); tte->format = TRACE_F5_PC_FMT; tte->pswkey = regs->psw.pkey | TRACE_F5_PC_FM2 | eamode; STORE_HW(tte->resv, 0x0000); STORE_FW(tte->retna, (regs->psw.amode << 31) | regs->psw.IA_L | PROBSTATE(®s->psw)); STORE_FW(tte->pcnum, pcea); } else if(regs->psw.amode64) { /* In 64-bit mode, regardless of resulting mode, when ASN-and-LX-reuse is enabled and 20-bit PC number is used */ TRACE_F4_PC *tte; size = sizeof(TRACE_F4_PC); raddr = ARCH_DEP(get_trace_entry) (&ag, size, regs); tte = (void*)(regs->mainstor + raddr); tte->format = TRACE_F4_PC_FMT; tte->pswkey_pcnum_hi = regs->psw.pkey | ((pcea & 0xF0000) >> 16); STORE_HW(tte->pcnum_lo, pcea & 0x0FFFF); STORE_DW(tte->retna, regs->psw.IA_G | PROBSTATE(®s->psw)); } else { /* In 24-bit or 31-bit mode, regardless of resulting mode, when ASN-and-LX-reuse is enabled and 20-bit PC number is used */ TRACE_F3_PC *tte; size = sizeof(TRACE_F3_PC); raddr = ARCH_DEP(get_trace_entry) (&ag, size, regs); tte = (void*)(regs->mainstor + raddr); tte->format = TRACE_F3_PC_FMT; tte->pswkey_pcnum_hi = regs->psw.pkey | ((pcea & 0xF0000) >> 16); STORE_HW(tte->pcnum_lo, pcea & 0x0FFFF); STORE_FW(tte->retna, (regs->psw.amode << 31) | regs->psw.IA_L | PROBSTATE(®s->psw)); } } /* end ASN_AND_LX_REUSE_ENABLED */ else if(regs->psw.amode64) { /* In 64-bit mode, regardless of resulting mode, when ASN-and-LX-reuse is not enabled */ TRACE_F2_PC *tte; size = sizeof(TRACE_F2_PC); raddr = ARCH_DEP(get_trace_entry) (&ag, size, regs); tte = (void*)(regs->mainstor + raddr); tte->format = TRACE_F2_PC_FMT; tte->pswkey_pcnum_hi = regs->psw.pkey | ((pcea & 0xF0000) >> 16); STORE_HW(tte->pcnum_lo, pcea & 0x0FFFF); STORE_DW(tte->retna, regs->psw.IA_G | PROBSTATE(®s->psw)); } else #endif /*defined(FEATURE_ESAME)*/ { /* In 24-bit or 31-bit mode, regardless of resulting mode, when ASN-and-LX-reuse is not enabled */ TRACE_F1_PC *tte; size = sizeof(TRACE_F1_PC); raddr = ARCH_DEP(get_trace_entry) (&ag, size, regs); tte = (void*)(regs->mainstor + raddr); tte->format = TRACE_F1_PC_FMT; tte->pswkey_pcnum_hi = regs->psw.pkey | ((pcea & 0xF0000) >> 16); STORE_HW(tte->pcnum_lo, pcea & 0x0FFFF); STORE_FW(tte->retna, (regs->psw.amode << 31) | regs->psw.IA_L | PROBSTATE(®s->psw)); } return ARCH_DEP(set_trace_entry) (ag, raddr, size, regs); } /* end function ARCH_DEP(trace_pc) */ #if defined(_MSVC_) /* Workaround for "fatal error C1001: INTERNAL COMPILER ERROR" in MSVC */ #pragma optimize("",off) #endif /*defined(_MSVC_)*/ #if defined(FEATURE_LINKAGE_STACK) /*-------------------------------------------------------------------*/ /* Form implicit PR trace entry */ /* */ /* Input: */ /* newregs Pointer to registers after PR instruction */ /* regs Pointer to registers before PR instruction */ /* Return value: */ /* Updated value for CR12 after adding new trace entry */ /* */ /* This function does not return if a program check occurs. */ /*-------------------------------------------------------------------*/ CREG ARCH_DEP(trace_pr) (REGS *newregs, REGS *regs) { RADR raddr; RADR ag; int size; SET_PSW_IA(regs); SET_PSW_IA(newregs); #if defined(FEATURE_ESAME) if(!regs->psw.amode64 && !newregs->psw.amode64) #endif /*defined(FEATURE_ESAME)*/ { TRACE_F1_PR *tte; size = sizeof(TRACE_F1_PR); raddr = ARCH_DEP(get_trace_entry) (&ag, size, regs); tte = (void*)(regs->mainstor + raddr); tte->format = TRACE_F1_PR_FMT; tte->pswkey = regs->psw.pkey | TRACE_F1_PR_FM2; STORE_HW(tte->newpasn, newregs->CR_LHL(4)); STORE_FW(tte->retna, (newregs->psw.amode << 31) | newregs->psw.IA_L | PROBSTATE(&newregs->psw)); STORE_FW(tte->newia, (regs->psw.amode << 31) | regs->psw.IA_L); } #if defined(FEATURE_ESAME) else if(regs->psw.amode64 && regs->psw.IA_H == 0 && !newregs->psw.amode64) { TRACE_F2_PR *tte; size = sizeof(TRACE_F2_PR); raddr = ARCH_DEP(get_trace_entry) (&ag, size, regs); tte = (void*)(regs->mainstor + raddr); tte->format = TRACE_F2_PR_FMT; tte->pswkey = regs->psw.pkey | TRACE_F2_PR_FM2; STORE_HW(tte->newpasn, newregs->CR_LHL(4)); STORE_FW(tte->retna, (newregs->psw.amode << 31) | newregs->psw.IA_L | PROBSTATE(&newregs->psw)); STORE_FW(tte->newia, regs->psw.IA_L); } else if(regs->psw.amode64 && regs->psw.IA_H != 0 && !newregs->psw.amode64) { TRACE_F3_PR *tte; size = sizeof(TRACE_F3_PR); raddr = ARCH_DEP(get_trace_entry) (&ag, size, regs); tte = (void*)(regs->mainstor + raddr); tte->format = TRACE_F3_PR_FMT; tte->pswkey = regs->psw.pkey | TRACE_F3_PR_FM2; STORE_HW(tte->newpasn, newregs->CR_LHL(4)); STORE_FW(tte->retna, (newregs->psw.amode << 31) | newregs->psw.IA_L | PROBSTATE(&newregs->psw)); STORE_DW(tte->newia, regs->psw.IA_G); } else if(!regs->psw.amode64 && newregs->psw.amode64 && newregs->psw.IA_H == 0) { TRACE_F4_PR *tte; size = sizeof(TRACE_F4_PR); raddr = ARCH_DEP(get_trace_entry) (&ag, size, regs); tte = (void*)(regs->mainstor + raddr); tte->format = TRACE_F4_PR_FMT; tte->pswkey = regs->psw.pkey | TRACE_F4_PR_FM2; STORE_HW(tte->newpasn, newregs->CR_LHL(4)); STORE_FW(tte->retna, newregs->psw.IA_L | PROBSTATE(&newregs->psw)); STORE_FW(tte->newia, (regs->psw.amode << 31) | regs->psw.IA_L); } else if(regs->psw.amode64 && regs->psw.IA_H == 0 && newregs->psw.amode64 && newregs->psw.IA_H == 0) { TRACE_F5_PR *tte; size = sizeof(TRACE_F5_PR); raddr = ARCH_DEP(get_trace_entry) (&ag, size, regs); tte = (void*)(regs->mainstor + raddr); tte->format = TRACE_F5_PR_FMT; tte->pswkey = regs->psw.pkey | TRACE_F5_PR_FM2; STORE_HW(tte->newpasn, newregs->CR_LHL(4)); STORE_FW(tte->retna, newregs->psw.IA_L | PROBSTATE(&newregs->psw)); STORE_FW(tte->newia, regs->psw.IA_L); } else if(regs->psw.amode64 && regs->psw.IA_H != 0 && newregs->psw.amode64 && newregs->psw.IA_H == 0) { TRACE_F6_PR *tte; size = sizeof(TRACE_F6_PR); raddr = ARCH_DEP(get_trace_entry) (&ag, size, regs); tte = (void*)(regs->mainstor + raddr); tte->format = TRACE_F6_PR_FMT; tte->pswkey = regs->psw.pkey | TRACE_F6_PR_FM2; STORE_HW(tte->newpasn, newregs->CR_LHL(4)); STORE_FW(tte->retna, newregs->psw.IA_L | PROBSTATE(&newregs->psw)); STORE_DW(tte->newia, regs->psw.IA_G); } else if(!regs->psw.amode64 && newregs->psw.amode64 && newregs->psw.IA_H != 0) { TRACE_F7_PR *tte; size = sizeof(TRACE_F7_PR); raddr = ARCH_DEP(get_trace_entry) (&ag, size, regs); tte = (void*)(regs->mainstor + raddr); tte->format = TRACE_F7_PR_FMT; tte->pswkey = regs->psw.pkey | TRACE_F7_PR_FM2; STORE_HW(tte->newpasn, newregs->CR_LHL(4)); STORE_DW(tte->retna, newregs->psw.IA_G | PROBSTATE(&newregs->psw)); STORE_FW(tte->newia, (regs->psw.amode << 31) | regs->psw.IA_L); } else if(regs->psw.amode64 && regs->psw.IA_H == 0 && newregs->psw.amode64 && newregs->psw.IA_H != 0) { TRACE_F8_PR *tte; size = sizeof(TRACE_F8_PR); raddr = ARCH_DEP(get_trace_entry) (&ag, size, regs); tte = (void*)(regs->mainstor + raddr); tte->format = TRACE_F8_PR_FMT; tte->pswkey = regs->psw.pkey | TRACE_F8_PR_FM2; STORE_HW(tte->newpasn, newregs->CR_LHL(4)); STORE_DW(tte->retna, newregs->psw.IA_G | PROBSTATE(&newregs->psw)); STORE_FW(tte->newia, regs->psw.IA_L); } else /* if(regs->psw.amode64 && regs->psw.IA_H != 0 && newregs->psw.amode64 && newregs->psw.IA_H != 0) */ { TRACE_F9_PR *tte; size = sizeof(TRACE_F9_PR); raddr = ARCH_DEP(get_trace_entry) (&ag, size, regs); tte = (void*)(regs->mainstor + raddr); tte->format = TRACE_F9_PR_FMT; tte->pswkey = regs->psw.pkey | TRACE_F9_PR_FM2; STORE_HW(tte->newpasn, newregs->CR_LHL(4)); STORE_DW(tte->retna, newregs->psw.IA_G | PROBSTATE(&newregs->psw)); STORE_DW(tte->newia, regs->psw.IA_G); } #endif /*defined(FEATURE_ESAME)*/ return ARCH_DEP(set_trace_entry) (ag, raddr, size, regs); } /* end function ARCH_DEP(trace_pr) */ #endif /*defined(FEATURE_LINKAGE_STACK)*/ #if defined(_MSVC_) /* Workaround for "fatal error C1001: INTERNAL COMPILER ERROR" in MSVC */ #pragma optimize("",on) #endif /*defined(_MSVC_)*/ /*-------------------------------------------------------------------*/ /* Form implicit PT/PTI trace entry */ /* */ /* Input: */ /* pti 1=PTI instruction, 0=PT instruction */ /* pasn Primary address space number */ /* gpr2 Contents of PT second operand register */ /* regs Pointer to the CPU register context */ /* Return value: */ /* Updated value for CR12 after adding new trace entry */ /* */ /* This function does not return if a program check occurs. */ /*-------------------------------------------------------------------*/ CREG ARCH_DEP(trace_pt) (int pti, U16 pasn, GREG gpr2, REGS *regs) { RADR raddr; RADR ag; int size; BYTE nbit = (pti ? 1 : 0); #if defined(FEATURE_ESAME) if(regs->psw.amode64 && gpr2 > 0xFFFFFFFFULL) { TRACE_F3_PT *tte; size = sizeof(TRACE_F3_PT); raddr = ARCH_DEP(get_trace_entry) (&ag, size, regs); tte = (void*)(regs->mainstor + raddr); tte->format = TRACE_F3_PT_FMT; tte->pswkey = regs->psw.pkey | TRACE_F3_PT_FM2 | nbit; STORE_HW(tte->newpasn, pasn); STORE_DW(tte->r2, gpr2); } else if(regs->psw.amode64) { TRACE_F2_PT *tte; size = sizeof(TRACE_F2_PT); raddr = ARCH_DEP(get_trace_entry) (&ag, size, regs); tte = (void*)(regs->mainstor + raddr); tte->format = TRACE_F2_PT_FMT; tte->pswkey = regs->psw.pkey | TRACE_F2_PT_FM2 | nbit; STORE_HW(tte->newpasn, pasn); STORE_FW(tte->r2, gpr2 & 0xFFFFFFFF); } else #endif /*defined(FEATURE_ESAME)*/ { TRACE_F1_PT *tte; size = sizeof(TRACE_F1_PT); raddr = ARCH_DEP(get_trace_entry) (&ag, size, regs); tte = (void*)(regs->mainstor + raddr); tte->format = TRACE_F1_PT_FMT; tte->pswkey = regs->psw.pkey | TRACE_F1_PT_FM2 | nbit; STORE_HW(tte->newpasn, pasn); STORE_FW(tte->r2, gpr2 & 0xFFFFFFFF); } return ARCH_DEP(set_trace_entry) (ag, raddr, size, regs); } /* end function ARCH_DEP(trace_pt) */ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* Form implicit MS trace entry */ /* */ /* Input: */ /* br Mode switch branch indicator */ /* baddr Branch address for mode switch branch */ /* regs Pointer to the CPU register context */ /* Return value: */ /* Updated value for CR12 after adding new trace entry */ /* */ /* This function does not return if a program check occurs. */ /*-------------------------------------------------------------------*/ CREG ARCH_DEP(trace_ms) (int br, VADR baddr, REGS *regs) { RADR raddr; RADR ag; int size; SET_PSW_IA(regs); if(!br) { if(!regs->psw.amode64) { TRACE_F1_MS *tte; size = sizeof(TRACE_F1_MS); raddr = ARCH_DEP(get_trace_entry) (&ag, size, regs); tte = (void*)(regs->mainstor + raddr); tte->format = TRACE_F1_MS_FMT; tte->fmt2 = TRACE_F1_MS_FM2; STORE_HW(tte->resv, 0); STORE_FW(tte->newia, regs->psw.IA | (regs->psw.amode << 31)); } else if(regs->psw.amode64 && regs->psw.IA <= 0x7FFFFFFF) { TRACE_F2_MS *tte; size = sizeof(TRACE_F2_MS); raddr = ARCH_DEP(get_trace_entry) (&ag, size, regs); tte = (void*)(regs->mainstor + raddr); tte->format = TRACE_F2_MS_FMT; tte->fmt2 = TRACE_F2_MS_FM2; STORE_HW(tte->resv, 0); STORE_FW(tte->newia, regs->psw.IA); } else { TRACE_F3_MS *tte; size = sizeof(TRACE_F3_MS); raddr = ARCH_DEP(get_trace_entry) (&ag, size, regs); tte = (void*)(regs->mainstor + raddr); tte->format = TRACE_F3_MS_FMT; tte->fmt2 = TRACE_F3_MS_FM2; STORE_HW(tte->resv, 0); STORE_DW(tte->newia, regs->psw.IA); } } else { /* if currently in 64-bit, we are switching out */ if(regs->psw.amode64) { TRACE_F1_MSB *tte; size = sizeof(TRACE_F1_MSB); raddr = ARCH_DEP(get_trace_entry) (&ag, size, regs); tte = (void*)(regs->mainstor + raddr); tte->format = TRACE_F1_MSB_FMT; tte->fmt2 = TRACE_F1_MSB_FM2; STORE_HW(tte->resv, 0); STORE_FW(tte->newia, baddr); } else if(!regs->psw.amode64 && baddr <= 0x7FFFFFFF) { TRACE_F2_MSB *tte; size = sizeof(TRACE_F2_MSB); raddr = ARCH_DEP(get_trace_entry) (&ag, size, regs); tte = (void*)(regs->mainstor + raddr); tte->format = TRACE_F2_MSB_FMT; tte->fmt2 = TRACE_F2_MSB_FM2; STORE_HW(tte->resv, 0); STORE_FW(tte->newia, baddr); } else { TRACE_F3_MSB *tte; size = sizeof(TRACE_F3_MSB); raddr = ARCH_DEP(get_trace_entry) (&ag, size, regs); tte = (void*)(regs->mainstor + raddr); tte->format = TRACE_F3_MSB_FMT; tte->fmt2 = TRACE_F3_MSB_FM2; STORE_HW(tte->resv, 0); STORE_DW(tte->newia, baddr); } } return ARCH_DEP(set_trace_entry) (ag, raddr, size, regs); } /* end function ARCH_DEP(trace_ms) */ #endif /*defined(FEATURE_ESAME)*/ /*-------------------------------------------------------------------*/ /* Form explicit TRACE trace entry */ /* */ /* Input: */ /* r1, r3 registers identifying register space to be written */ /* op Trace operand */ /* regs Pointer to the CPU register context */ /* Return value: */ /* Updated value for CR12 after adding new trace entry */ /* */ /* This function does not return if a program check occurs. */ /*-------------------------------------------------------------------*/ CREG ARCH_DEP(trace_tr) (int r1, int r3, U32 op, REGS *regs) { RADR raddr; RADR ag; int size; int i, j, n; U64 dreg; { TRACE_F1_TR *tte; size = sizeof(TRACE_F1_TR); raddr = ARCH_DEP(get_trace_entry) (&ag, size, regs); tte = (void*)(regs->mainstor + raddr); /* Calculate the number of registers to be traced, minus 1 */ n = ( r3 < r1 ) ? r3 + 16 - r1 : r3 - r1; /* Retrieve the TOD clock value and shift out the epoch */ dreg = (tod_clock(regs) << 8) | regs->cpuad; tte->format = TRACE_F1_TR_FMT | n; tte->fmt2 = TRACE_F1_TR_FM2; STORE_HW(tte->clk16, (dreg >> 32) & 0xFFFF); STORE_FW(tte->clk32, dreg & 0xFFFFFFFF); STORE_FW(tte->operand, op); for(i = r1, j = 0; ; ) { STORE_FW(tte->reg[j++], regs->GR_L(i)); /* Regdump is complete when r3 is done */ if(r3 == i) break; /* Update register number and wrap */ i++; i &= 15; } } return ARCH_DEP(set_trace_entry) (ag, raddr, size - (4 * (15 - n)), regs); } /* end function ARCH_DEP(trace_tr) */ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* Form explicit TRACG trace entry */ /* */ /* Input: */ /* r1, r3 registers identifying register space to be written */ /* op Trace operand */ /* regs Pointer to the CPU register context */ /* Return value: */ /* Updated value for CR12 after adding new trace entry */ /* */ /* This function does not return if a program check occurs. */ /*-------------------------------------------------------------------*/ CREG ARCH_DEP(trace_tg) (int r1, int r3, U32 op, REGS *regs) { RADR raddr; RADR ag; int size; int i, j, n; U64 dreg; { TRACE_F2_TR *tte; size = sizeof(TRACE_F2_TR); raddr = ARCH_DEP(get_trace_entry) (&ag, size, regs); tte = (void*)(regs->mainstor + raddr); /* Calculate the number of registers to be traced, minus 1 */ n = ( r3 < r1 ) ? r3 + 16 - r1 : r3 - r1; /* Retrieve the TOD clock value including the epoch */ dreg = tod_clock(regs); tte->format = TRACE_F2_TR_FMT | n; tte->fmt2 = TRACE_F2_TR_FM2; STORE_HW(tte->clk0, (dreg >> 48) & 0xFFFF); /* shift out the epoch */ dreg = (dreg << 8) | regs->cpuad; STORE_FW(tte->clk16, (dreg >> 32) & 0xFFFFFFFF); STORE_FW(tte->clk48, dreg & 0xFFFFFFFF); STORE_FW(tte->operand, op); for(i = r1, j = 0; ; ) { STORE_DW(tte->reg[j++], regs->GR_G(i)); /* Regdump is complete when r3 is done */ if(r3 == i) break; /* Update register number and wrap */ i++; i &= 15; } } return ARCH_DEP(set_trace_entry) (ag, raddr, size - (8 * (15 - n)), regs); } /* end function ARCH_DEP(trace_tg) */ #endif /*defined(FEATURE_ESAME)*/ #endif /*defined(FEATURE_TRACING)*/ #if !defined(_GEN_ARCH) #if defined(_ARCHMODE2) #define _GEN_ARCH _ARCHMODE2 #include "trace.c" #endif #if defined(_ARCHMODE3) #undef _GEN_ARCH #define _GEN_ARCH _ARCHMODE3 #include "trace.c" #endif #endif /*!defined(_GEN_ARCH)*/ hercules-3.07/tt32api.h000644 000765 000765 00000030001 11224164171 016373 0ustar00jmaynardjmaynard000000 000000 // Copyright (c) 2002-2008, Software Development Laboratories, "Fish" (David B. Trout) ///////////////////////////////////////////////////////////////////////////////////////// // // TT32API.h -- TunTap32 DLL exported functions interface // ///////////////////////////////////////////////////////////////////////////////////////// // // T U N T A P 3 2 . D L L // // EXPORTED FUNCTION DEFINITIONS // // These functions provide a 'C' language interface and can be called from // any type of app that can access a DLL: VB, C/C++, PowerBuilder, etc. // ///////////////////////////////////////////////////////////////////////////////////////// // // Change History: // // 12/22/01 1.0.0 Created. // 07/20/02 2.0.0 JAP: LCS modifications/enhancements. // 07/02/03 2.0.2 use std 'uint32_t' type instead of Win32 DWORD // 06/16/04 2.1.0 'ex' variant functions to pass errno value. // 11/01/03 3.1.0 TT32MINMTU, TT32MAXMTU, TT32DEFMTU // 11/03/03 3.1.0 TT32_MAX_MULTICAST_LIST_ENTRIES // 12/31/03 3.1.0 support for deprecated functions dropped/deleted. // 02/05/06 3.1.0 New exported function: 'tuntap32_build_herc_iface_mac' // 02/14/06 3.1.0 Added #defines for TUNTAP32_DLLNAME // 04/14/06 3.1.0 Added 'tuntap32_calc_checksum' function // 07/02/06 3.1.2 Added #defines for min/max/def buffer sizes // 08/09/06 3.1.6 Added 'tuntap32_calc_checksum' function // mm/dd/07 3.2.0 VS2005 + x64 + WinPCap 4.0 // 11/06/08 3.3.0 VS2008 + auto-link pragma. // 11/06/08 3.3.0 Additional counters... // ////////////////////////////////////////////////////////////////////////////////////////// #ifndef _TT32API_H_ #define _TT32API_H_ ///////////////////////////////////////////////////////////////////////////////////////// // TunTap32.dll name ///////////////////////////////////////////////////////////////////////////////////////// #if defined(_WIN64) #if defined(_UNICODE) || defined(UNICODE) #if defined(_DEBUG) || defined(DEBUG) #define BASE_TUNTAP32_NAME "TunTap64UD" #else #define BASE_TUNTAP32_NAME "TunTap64U" #endif #else #if defined(_DEBUG) || defined(DEBUG) #define BASE_TUNTAP32_NAME "TunTap64D" #else #define BASE_TUNTAP32_NAME "TunTap64" #endif #endif #else #if defined(_UNICODE) || defined(UNICODE) #if defined(_DEBUG) || defined(DEBUG) #define BASE_TUNTAP32_NAME "TunTap32UD" #else #define BASE_TUNTAP32_NAME "TunTap32U" #endif #else #if defined(_DEBUG) || defined(DEBUG) #define BASE_TUNTAP32_NAME "TunTap32D" #else #define BASE_TUNTAP32_NAME "TunTap32" #endif #endif #endif #if defined( _MSC_VER ) && defined( AUTOLINK_TUNTAP32_LIB ) #pragma comment ( lib, BASE_TUNTAP32_NAME ".lib" ) #endif #define TUNTAP32_DLLNAME BASE_TUNTAP32_NAME ".dll" ///////////////////////////////////////////////////////////////////////////////////////// // TunTap32 structures, #defines and typedefs, etc... ///////////////////////////////////////////////////////////////////////////////////////// #ifdef __cplusplus extern "C" { #endif #define TT32MINMTU ( 60) // minimum MTU value #define TT32DEFMTU ( 1500) // default MTU value #define TT32MAXMTU ((64*1024)-14) // maximum MTU value (14 == eth_hdr_size) #define TT32_MAX_MULTICAST_LIST_ENTRIES (32) #define TT32SDEVBUFF _IOW('T', 220, int) #define TT32GDEVBUFF _IOR('T', 220, int) #define TT32SIOBUFF _IOW('T', 221, int) #define TT32GIOBUFF _IOR('T', 221, int) #define TT32STIMEOUT _IOW('T', 222, int) #define TT32GTIMEOUT _IOR('T', 222, int) #define TT32GSTATS _IOR('T', 223, int) struct tt32ctl { union { char ctln_name[IFNAMSIZ]; // iface name (e.g. "tun0") } tt32_ctln; union { int ctlu_devbuffsize; // Kernel buffer size int ctlu_iobuffsize; // Read buffer size int ctlu_readtimeout; // Read timeout value } tt32_ctlu; }; #define tt32ctl_name tt32_ctln.ctln_name #define tt32ctl_devbuffsize tt32_ctlu.ctlu_devbuffsize #define tt32ctl_iobuffsize tt32_ctlu.ctlu_iobuffsize #define tt32ctl_readtimeout tt32_ctlu.ctlu_readtimeout // WinPCap device driver capture buffer sizes #define MIN_CAPTURE_BUFFSIZE (64*1024) // minimum = 64K #define DEF_CAPTURE_BUFFSIZE (1*1024*1024) // default = 1M #define MAX_CAPTURE_BUFFSIZE (16*1024*1024) // maximum = 16M // FishPack I/O buffer sizes #define MIN_PACKET_BUFFSIZE (16*1024) // minimum = 16K #define DEF_PACKET_BUFFSIZE (1*64*1024) // default = 64K #define MAX_PACKET_BUFFSIZE (1024*1024) // maximum = 1M typedef struct TT32STATS { uint32_t dwStructSize; // size of this structure uint32_t dwKernelBuffSize; // size of kernel capture buffer uint32_t dwReadBuffSize; // size of dll I/O buffer uint32_t dwMaxBytesReceived; // max dll I/O bytes received int64_t n64WriteCalls; // total #of write requests int64_t n64WriteIOs; // total #of write I/Os int64_t n64ReadCalls; // total #of read requests int64_t n64ReadIOs; // total #of read I/Os int64_t n64PacketsRead; // total #of packets read int64_t n64PacketsWritten; // total #of packets written int64_t n64BytesRead; // total #of bytes read int64_t n64BytesWritten; // total #of bytes written int64_t n64InternalPackets; // total #of packets handled internally int64_t n64IgnoredPackets; // total #of packets ignored // New version 3.3 counters... int64_t n64OwnPacketsIgnored; // total #of packets read with our source MAC int64_t n64ZeroMACPacketsRead; // total #of packets read with dest MAC all zeros int64_t n64ZeroMACPacketsWritten; // total #of packets written with dest MAC all zeros } TT32STATS, *PTT32STATS; #ifndef EXPORT #define EXPORT // we must be importing instead of exporting) #endif ///////////////////////////////////////////////////////////////////////////////////////// // TunTap32.dll exported functions... ///////////////////////////////////////////////////////////////////////////////////////// typedef void (__cdecl *ptr_to_print_debug_string_func)(const char* debug_string); extern const char* WINAPI EXPORT tuntap32_copyright_string (); extern const char* WINAPI EXPORT tuntap32_version_string (); extern void WINAPI EXPORT tuntap32_version_numbers (int* major, int* inter, int* minor, int* build); extern int WINAPI EXPORT tuntap32_set_debug_output_func (ptr_to_print_debug_string_func pfn); extern int WINAPI EXPORT tuntap32_open (char* gatewaydev, int flags); extern int WINAPI EXPORT tuntap32_write (int fd, u_char* buffer, u_long len); extern int WINAPI EXPORT tuntap32_read (int fd, u_char* buffer, u_long len); extern int WINAPI EXPORT tuntap32_close (int fd); extern int WINAPI EXPORT tuntap32_ioctl (int fd, int request, char* argp); extern int WINAPI EXPORT tuntap32_get_stats (int fd, TT32STATS* stats); extern const char* WINAPI EXPORT tuntap32_get_default_iface (); extern void WINAPI EXPORT tuntap32_build_herc_iface_mac (u_char* mac, const u_char* ip); extern u_short WINAPI EXPORT tuntap32_calc_inet_checksum (u_char* buffer, u_long bytes); extern u_short WINAPI EXPORT tuntap32_calc_checksum (u_char* buffer, u_long bytes); // (functions to work around an as-yet unidentified/unresolved 'errno' bug) extern const char* WINAPI EXPORT tuntap32_copyright_string_ex ( int* eno); extern const char* WINAPI EXPORT tuntap32_version_string_ex ( int* eno); extern void WINAPI EXPORT tuntap32_version_numbers_ex (int* major, int* inter, int* minor, int* build, int* eno); extern int WINAPI EXPORT tuntap32_set_debug_output_func_ex (ptr_to_print_debug_string_func pfn, int* eno); extern int WINAPI EXPORT tuntap32_open_ex (char* gatewaydev, int flags, int* eno); extern int WINAPI EXPORT tuntap32_write_ex (int fd, u_char* buffer, u_long len, int* eno); extern int WINAPI EXPORT tuntap32_read_ex (int fd, u_char* buffer, u_long len, int* eno); extern int WINAPI EXPORT tuntap32_close_ex (int fd, int* eno); extern int WINAPI EXPORT tuntap32_ioctl_ex (int fd, int request, char* argp, int* eno); extern int WINAPI EXPORT tuntap32_get_stats_ex (int fd, TT32STATS* stats, int* eno); extern const char* WINAPI EXPORT tuntap32_get_default_iface_ex ( int* eno); // (in case they want to use LoadLibrary and GetProcAddress instead) typedef const char* (WINAPI *ptuntap32_copyright_string) (); typedef const char* (WINAPI *ptuntap32_version_string) (); typedef void (WINAPI *ptuntap32_version_numbers) (int*,int*,int*,int*); typedef int (WINAPI *ptuntap32_set_debug_output_func) (ptr_to_print_debug_string_func); typedef int (WINAPI *ptuntap32_open) (char*,int); typedef int (WINAPI *ptuntap32_write) (int,u_char*,u_long); typedef int (WINAPI *ptuntap32_read) (int,u_char*,u_long); typedef int (WINAPI *ptuntap32_close) (int); typedef int (WINAPI *ptuntap32_ioctl) (int,int,char*); typedef int (WINAPI *ptuntap32_get_stats) (int fd, TT32STATS* stats); typedef const char* (WINAPI *ptuntap32_get_default_iface) (); typedef void (WINAPI *ptuntap32_build_herc_iface_mac) (u_char* mac, const u_char* ip); typedef u_short (WINAPI *ptuntap32_calc_inet_checksum) (u_char*, u_long); typedef u_short (WINAPI *ptuntap32_calc_checksum) (u_char*, u_long); // (functions to work around an as-yet unidentified/unresolved 'errno' bug) typedef const char* (WINAPI *ptuntap32_copyright_string_ex) ( int* eno); typedef const char* (WINAPI *ptuntap32_version_string_ex) ( int* eno); typedef void (WINAPI *ptuntap32_version_numbers_ex) (int* major, int* inter, int* minor, int* build, int* eno); typedef int (WINAPI *ptuntap32_set_debug_output_func_ex) (ptr_to_print_debug_string_func pfn, int* eno); typedef int (WINAPI *ptuntap32_open_ex) (char* gatewaydev, int flags, int* eno); typedef int (WINAPI *ptuntap32_write_ex) (int fd, u_char* buffer, u_long len, int* eno); typedef int (WINAPI *ptuntap32_read_ex) (int fd, u_char* buffer, u_long len, int* eno); typedef int (WINAPI *ptuntap32_close_ex) (int fd, int* eno); typedef int (WINAPI *ptuntap32_ioctl_ex) (int fd, int request, char* argp, int* eno); typedef int (WINAPI *ptuntap32_get_stats_ex) (int fd, TT32STATS* stats, int* eno); typedef const char* (WINAPI *ptuntap32_get_default_iface_ex) ( int* eno); ///////////////////////////////////////////////////////////////////////////////////////// #ifdef __cplusplus } #endif #endif /* _TT32API_H_ */ ///////////////////////////////////////////////////////////////////////////////////////// hercules-3.07/tuntap.c000644 000765 000765 00000070465 11143760543 016442 0ustar00jmaynardjmaynard000000 000000 // ==================================================================== // Hercules - TUN/TAP Abstraction Layer // ==================================================================== // // Copyright (C) 2002-2009 by James A. Pierson // (C) 2002-2009 by "Fish" (David B. Trout) // // TUN/TAP implementations differ among platforms. Linux and FreeBSD // offer much the same functionality but with differing semantics. // Windows does not have TUN/TAP but thanks to "Fish" (David B. Trout) // we have a way of emulating the TUN/TAP interface through a set of // custom DLLs he has provided us. // // This abstraction layer is an attempt to create a common API set // that works on all platforms with (hopefully) equal results. // // $Id: tuntap.c 5127 2009-01-23 13:25:01Z bernard $ // // $Log$ // Revision 1.46 2008/02/07 00:29:04 rbowler // Solaris build support by Jeff Savit // // Revision 1.45 2007/06/23 00:04:19 ivan // Update copyright notices to include current year (2007) // // Revision 1.44 2006/12/08 09:43:31 jj // Add CVS message log // #include "hstdinc.h" /* jbs 1/19/2008 added ifdef on __SOLARIS__ */ #if !defined(__SOLARIS__) #include "hercules.h" #include "tuntap.h" #include "devtype.h" #include "ctcadpt.h" #include "hercifc.h" #if defined( OPTION_W32_CTCI ) #include "w32ctca.h" #endif // ==================================================================== // Declarations // ==================================================================== #ifndef OPTION_W32_CTCI static int IFC_IOCtl( int fd, unsigned long int iRequest, char* argp ); static int ifc_fd[2] = { -1, -1 }; static pid_t ifc_pid = 0; static void tuntap_term(void) { close(ifc_fd[0]); close(ifc_fd[1]); ifc_fd[0] = ifc_fd[1] = -1; kill(ifc_pid, SIGINT); } #endif // ==================================================================== // Primary Module Entry Points // ==================================================================== static int TUNTAP_SetMode (int fd, struct ifreq *ifr) { int rc; /* Try TUNTAP_ioctl first */ rc = TUNTAP_IOCtl (fd, TUNSETIFF, (char *) ifr); #if !defined(OPTION_W32_CTCI) /* If invalid value, try with the pre-2.4.5 value */ if (rc != 0 && errno == EINVAL) rc = TUNTAP_IOCtl (fd, ('T' << 8) | 202, (char *) ifr); /* kludge for EPERM and linux 2.6.18 */ if (rc != 0 && errno == EPERM) { int ifd[2]; char *hercifc; pid_t pid; CTLREQ ctlreq; fd_set selset; struct timeval tv; int sv_err; int status; if (socketpair (AF_UNIX, SOCK_STREAM, 0, ifd) < 0) return -1; if (!(hercifc = getenv ("HERCULES_IFC"))) hercifc = HERCIFC_CMD; pid = fork(); if (pid < 0) return -1; else if (pid == 0) { /* child */ dup2 (ifd[0], STDIN_FILENO); dup2 (STDOUT_FILENO, STDERR_FILENO); dup2 (ifd[0], STDOUT_FILENO); close (ifd[1]); rc = execlp (hercifc, hercifc, NULL ); return -1; } /* parent */ close(ifd[0]); /* Request hercifc to issue the TUNSETIFF ioctl */ memset (&ctlreq, 0, CTLREQ_SIZE); ctlreq.iCtlOp = TUNSETIFF; ctlreq.iProcID = fd; memcpy (&ctlreq.iru.ifreq, ifr, sizeof (struct ifreq)); write (ifd[1], &ctlreq, CTLREQ_SIZE); /* Get response, if any, from hercifc */ FD_ZERO (&selset); FD_SET (ifd[1], &selset); tv.tv_sec = 5; tv.tv_usec = 0; rc = select (ifd[1]+1, &selset, NULL, NULL, &tv); if (rc > 0) { rc = read (ifd[1], &ctlreq, CTLREQ_SIZE); if (rc > 0) memcpy (ifr, &ctlreq.iru.ifreq, sizeof (struct ifreq)); } else if (rc == 0) { logmsg (_("HHCTU001E %s timeout, possible older version?\n"), hercifc); errno = EPERM; rc = -1; } /* clean-up */ sv_err = errno; close (ifd[1]); kill (pid, SIGINT); waitpid (pid, &status, 0); errno = sv_err; } #endif /* if !defined(OPTION_W32_CTCI) */ return rc; } // // TUNTAP_CreateInterface // // // Creates a new network interface using TUN/TAP. Reading from or // writing to the file descriptor returned from this call will pass // network packets to/from the virtual network interface. // // A TUN interface is a Point-To-Point connection from the driving // system's IP stack to the guest OS running within Hercules. // // A TAP interface in a virtual network adapter that "tap's" off the // driving system's network stack. // // On *nix boxen, this is accomplished by opening the special TUN/TAP // character device (usually /dev/net/tun). Once the character device // is opened, an ioctl call is done to set they type of interface to be // created, IFF_TUN or IFF_TAP. Once the interface is created, the // interface name is returned in pszNetDevName. // // Input: // pszTUNDevice Pointer to the name of the TUN/TAP char device // iFlags Flags for the new interface: // IFF_TAP - Create a TAP interface or // IFF_TUN - Create a TUN interface // IFF_NO_PI - Do not include packet information // // On Win32, calls are made to Fish's TT32 DLL's to accomplish the same // functionality. There are a few differences in regards to the arguments // however: // // Input: // pszTUNDevice Pointer to a string that describes the physical // adapter to attach the TUN/TAP interface to. // This string can contain any of the following: // 1) IP address (in a.b.c.d notation) // 2) MAC address (in xx-xx-xx-xx-xx-xx or // xx:xx:xx:xx:xx:xx notation). // 3) Name of the adapter as displayed on your // Network and Dial-ip Connections window // (Windows 2000 only future implementation) // iFlags Flags for the new interface: // IFF_TAP - Create a TAP interface or // IFF_TUN - Create a TUN interface // IFF_NO_PI - Do not include packet information // // Output: // pfd Pointer to receive the file descriptor of the // TUN/TAP interface. // pszNetDevName Pointer to receive the name if the interface. // int TUNTAP_CreateInterface( char* pszTUNDevice, int iFlags, int* pfd, char* pszNetDevName ) { int fd; // File descriptor #if !defined( OPTION_W32_CTCI ) struct utsname utsbuf; if( uname( &utsbuf ) != 0 ) { logmsg( _("HHCTU001E Unable to determine operating system type: %s\n"), strerror( errno ) ); return -1; } #endif // Open TUN device fd = TUNTAP_Open( pszTUNDevice, O_RDWR ); if( fd < 0 ) { logmsg( _("HHCTU002E Error opening TUN/TAP device: %s: %s\n"), pszTUNDevice, strerror( errno ) ); return -1; } *pfd = fd; #if !defined( OPTION_W32_CTCI ) if ( strncasecmp( utsbuf.sysname, "linux", 5 ) == 0 ) #endif { // Linux kernel (builtin tun device) or Windows struct ifreq ifr; memset( &ifr, 0, sizeof( ifr ) ); ifr.ifr_flags = iFlags; if( TUNTAP_SetMode (fd, &ifr) < 0 ) { logmsg( _("HHCTU003E Error setting TUN/TAP mode: %s: %s\n"), pszTUNDevice, strerror( errno ) ); return -1; } strcpy( pszNetDevName, ifr.ifr_name ); } #if !defined( OPTION_W32_CTCI ) else { // Other OS: Simply use basename of the device // Notes: (JAP) This is problematic at best. Until we have a // clean FreeBSD compile from the base tree I can't // spend a lot of time on this... so it will remain. // My best guess is that this will cause other functions // to fail miserably but I have no way to test it. // This should work on OS X with Christoph Pfisterer's TUN driver, // since it does set the device name to the basename of the // file. -- JRM char *p = strrchr( pszTUNDevice, '/' ); if( p ) strncpy( pszNetDevName, ++p, IFNAMSIZ ); else { logmsg( _("HHCTU004E Invalid TUN/TAP device name: %s\n"), pszTUNDevice ); return -1; } } #endif return 0; } // // Redefine 'TUNTAP_IOCtl' for the remainder of the functions. // This forces all 'ioctl' calls to go to 'hercifc'. // #if !defined( OPTION_W32_CTCI ) #undef TUNTAP_IOCtl #define TUNTAP_IOCtl IFC_IOCtl #endif #ifdef OPTION_TUNTAP_CLRIPADDR // // TUNTAP_ClrIPAddr // int TUNTAP_ClrIPAddr( char* pszNetDevName ) { struct ifreq ifreq; memset( &ifreq, 0, sizeof( struct ifreq ) ); if( !pszNetDevName || !*pszNetDevName ) { logmsg( _("HHCTU005E Invalid net device name specified: %s\n"), pszNetDevName ? pszNetDevName : "(null pointer)" ); return -1; } strcpy( ifreq.ifr_name, pszNetDevName ); return TUNTAP_IOCtl( 0, SIOCDIFADDR, (char*)&ifreq ); } #endif /* OPTION_TUNTAP_CLRIPADDR */ // // TUNTAP_SetIPAddr // int TUNTAP_SetIPAddr( char* pszNetDevName, char* pszIPAddr ) { struct ifreq ifreq; struct sockaddr_in* sin; memset( &ifreq, 0, sizeof( struct ifreq ) ); sin = (struct sockaddr_in*)&ifreq.ifr_addr; sin->sin_family = AF_INET; set_sockaddr_in_sin_len( sin ); if( !pszNetDevName || !*pszNetDevName ) { logmsg( _("HHCTU005E Invalid net device name specified: %s\n"), pszNetDevName ? pszNetDevName : "(null pointer)" ); return -1; } strcpy( ifreq.ifr_name, pszNetDevName ); if( !pszIPAddr || !inet_aton( pszIPAddr, &sin->sin_addr ) ) { logmsg( _("HHCTU006E %s: Invalid IP address: %s.\n"), pszNetDevName, !pszIPAddr ? "NULL" : pszIPAddr ); return -1; } return TUNTAP_IOCtl( 0, SIOCSIFADDR, (char*)&ifreq ); } // // TUNTAP_SetDestAddr // int TUNTAP_SetDestAddr( char* pszNetDevName, char* pszDestAddr ) { struct ifreq ifreq; struct sockaddr_in* sin; memset( &ifreq, 0, sizeof( struct ifreq ) ); sin = (struct sockaddr_in*)&ifreq.ifr_addr; sin->sin_family = AF_INET; set_sockaddr_in_sin_len( sin ); if( !pszNetDevName || !*pszNetDevName ) { logmsg( _("HHCTU007E Invalid net device name specified: %s\n"), pszNetDevName ? pszNetDevName : "(null pointer)" ); return -1; } strcpy( ifreq.ifr_name, pszNetDevName ); if( !pszDestAddr || !inet_aton( pszDestAddr, &sin->sin_addr ) ) { logmsg( _("HHCTU008E %s: Invalid destination address: %s.\n"), pszNetDevName, !pszDestAddr ? "NULL" : pszDestAddr ); return -1; } return TUNTAP_IOCtl( 0, SIOCSIFDSTADDR, (char*)&ifreq ); } // // TUNTAP_SetNetMask // #ifdef OPTION_TUNTAP_SETNETMASK int TUNTAP_SetNetMask( char* pszNetDevName, char* pszNetMask ) { struct ifreq ifreq; struct sockaddr_in* sin; memset( &ifreq, 0, sizeof( struct ifreq ) ); sin = (struct sockaddr_in*)&ifreq.ifr_netmask; sin->sin_family = AF_INET; set_sockaddr_in_sin_len( sin ); if( !pszNetDevName || !*pszNetDevName ) { logmsg( _("HHCTU009E Invalid net device name specified: %s\n"), pszNetDevName ? pszNetDevName : "(null pointer)" ); return -1; } strcpy( ifreq.ifr_name, pszNetDevName ); if( !pszNetMask || !inet_aton( pszNetMask, &sin->sin_addr ) ) { logmsg( _("HHCTU010E %s: Invalid net mask: %s.\n"), pszNetDevName, !pszNetMask ? "NULL" : pszNetMask ); return -1; } return TUNTAP_IOCtl( 0, SIOCSIFNETMASK, (char*)&ifreq ); } #endif // OPTION_TUNTAP_SETNETMASK // // TUNTAP_SetMTU // int TUNTAP_SetMTU( char* pszNetDevName, char* pszMTU ) { struct ifreq ifreq; struct sockaddr_in* sin; int iMTU; memset( &ifreq, 0, sizeof( struct ifreq ) ); sin = (struct sockaddr_in*)&ifreq.ifr_addr; sin->sin_family = AF_INET; set_sockaddr_in_sin_len( sin ); if( !pszNetDevName || !*pszNetDevName ) { logmsg( _("HHCTU011E Invalid net device name specified: %s\n"), pszNetDevName ? pszNetDevName : "(null pointer)" ); return -1; } strcpy( ifreq.ifr_name, pszNetDevName ); if( !pszMTU || !*pszMTU ) { logmsg( _("HHCTU012E %s: Invalid null or empty MTU.\n"), pszNetDevName ); return -1; } iMTU = atoi( pszMTU ); if( iMTU < 46 || iMTU > 65536 ) { logmsg( _("HHCTU013E %s: Invalid MTU: %s.\n"), pszNetDevName, pszMTU ); return -1; } ifreq.ifr_mtu = iMTU; return TUNTAP_IOCtl( 0, SIOCSIFMTU, (char*)&ifreq ); } // // TUNTAP_SetMACAddr // #ifdef OPTION_TUNTAP_SETMACADDR int TUNTAP_SetMACAddr( char* pszNetDevName, char* pszMACAddr ) { struct ifreq ifreq; struct sockaddr* addr; MAC mac; memset( &ifreq, 0, sizeof( struct ifreq ) ); addr = (struct sockaddr*)&ifreq.ifr_hwaddr; addr->sa_family = AF_UNIX; if( !pszNetDevName || !*pszNetDevName ) { logmsg( _("HHCTU014E Invalid net device name specified: %s\n"), pszNetDevName ? pszNetDevName : "(null pointer)" ); return -1; } strcpy( ifreq.ifr_name, pszNetDevName ); if( !pszMACAddr || ParseMAC( pszMACAddr, mac ) != 0 ) { logmsg( _("HHCTU015E %s: Invalid MAC address: %s.\n"), pszNetDevName, !pszMACAddr ? "NULL" : pszMACAddr ); return -1; } memcpy( addr->sa_data, mac, IFHWADDRLEN ); return TUNTAP_IOCtl( 0, SIOCSIFHWADDR, (char*)&ifreq ); } #endif // OPTION_TUNTAP_SETMACADDR // // TUNTAP_SetFlags // int TUNTAP_SetFlags ( char* pszNetDevName, int iFlags ) { struct ifreq ifreq; struct sockaddr_in* sin; memset( &ifreq, 0, sizeof( struct ifreq ) ); sin = (struct sockaddr_in*)&ifreq.ifr_addr; sin->sin_family = AF_INET; set_sockaddr_in_sin_len( sin ); if( !pszNetDevName || !*pszNetDevName ) { logmsg( _("HHCTU016E Invalid net device name specified: %s\n"), pszNetDevName ? pszNetDevName : "(null pointer)" ); return -1; } strlcpy( ifreq.ifr_name, pszNetDevName, sizeof(ifreq.ifr_name) ); ifreq.ifr_flags = iFlags; return TUNTAP_IOCtl( 0, SIOCSIFFLAGS, (char*)&ifreq ); } // // TUNTAP_GetFlags // int TUNTAP_GetFlags ( char* pszNetDevName, int* piFlags ) { struct ifreq ifreq; struct sockaddr_in* sin; int rc; memset( &ifreq, 0, sizeof( struct ifreq ) ); sin = (struct sockaddr_in*)&ifreq.ifr_addr; sin->sin_family = AF_INET; if( !pszNetDevName || !*pszNetDevName ) { logmsg( _("HHCTU016E Invalid net device name specified: %s\n"), pszNetDevName ? pszNetDevName : "(null pointer)" ); return -1; } strlcpy( ifreq.ifr_name, pszNetDevName, sizeof(ifreq.ifr_name) ); // PROGRAMMING NOTE: hercifc can't "get" information, // only "set" it. Thus because we normally use hercifc // to issue ioctl codes to the interface (on non-Win32) // we bypass hercifc altogether and issue the ioctl // ourselves directly to the device itself, bypassing // hercifc completely. Note that for Win32 however, // 'TUNTAP_IOCtl' routes to a TunTap32.DLL call and // thus works just fine. We need special handling // only for non-Win32 platforms. - Fish #if defined( OPTION_W32_CTCI ) rc = TUNTAP_IOCtl( 0, SIOCGIFFLAGS, (char*)&ifreq ); #else // (non-Win32 platforms) { int sockfd = socket( AF_INET, SOCK_DGRAM, 0 ); rc = ioctl( sockfd, SIOCGIFFLAGS, &ifreq ); } #endif *piFlags = ifreq.ifr_flags; return rc; } // // TUNTAP_AddRoute // #ifdef OPTION_TUNTAP_DELADD_ROUTES int TUNTAP_AddRoute( char* pszNetDevName, char* pszDestAddr, char* pszNetMask, char* pszGWAddr, int iFlags ) { struct rtentry rtentry; struct sockaddr_in* sin; memset( &rtentry, 0, sizeof( struct rtentry ) ); if( !pszNetDevName || !*pszNetDevName ) { logmsg( _("HHCTU017E Invalid net device name specified: %s\n"), pszNetDevName ? pszNetDevName : "(null pointer)" ); return -1; } rtentry.rt_dev = pszNetDevName; sin = (struct sockaddr_in*)&rtentry.rt_dst; sin->sin_family = AF_INET; set_sockaddr_in_sin_len( sin ); if( !pszDestAddr || !inet_aton( pszDestAddr, &sin->sin_addr ) ) { logmsg( _("HHCTU018E %s: Invalid destiniation address: %s.\n"), pszNetDevName, !pszDestAddr ? "NULL" : pszDestAddr ); return -1; } sin = (struct sockaddr_in*)&rtentry.rt_genmask; sin->sin_family = AF_INET; set_sockaddr_in_sin_len( sin ); if( !pszNetMask || !inet_aton( pszNetMask, &sin->sin_addr ) ) { logmsg( _("HHCTU019E %s: Invalid net mask: %s.\n"), pszNetDevName, !pszNetMask ? "NULL" : pszNetMask ); return -1; } sin = (struct sockaddr_in*)&rtentry.rt_gateway; sin->sin_family = AF_INET; set_sockaddr_in_sin_len( sin ); if( pszGWAddr ) { if( !inet_aton( pszGWAddr, &sin->sin_addr ) ) { logmsg( _("HHCTU020E %s: Invalid gateway address: %s.\n"), pszNetDevName, pszGWAddr ); return -1; } } rtentry.rt_flags = iFlags; return TUNTAP_IOCtl( 0, SIOCADDRT, (char*)&rtentry ); } #endif // OPTION_TUNTAP_DELADD_ROUTES // // TUNTAP_DelRoute // #ifdef OPTION_TUNTAP_DELADD_ROUTES int TUNTAP_DelRoute( char* pszNetDevName, char* pszDestAddr, char* pszNetMask, char* pszGWAddr, int iFlags ) { struct rtentry rtentry; struct sockaddr_in* sin; memset( &rtentry, 0, sizeof( struct rtentry ) ); if( !pszNetDevName || !*pszNetDevName ) { logmsg( _("HHCTU021E Invalid net device name specified: %s\n"), pszNetDevName ? pszNetDevName : "(null pointer)" ); return -1; } rtentry.rt_dev = pszNetDevName; sin = (struct sockaddr_in*)&rtentry.rt_dst; sin->sin_family = AF_INET; set_sockaddr_in_sin_len( sin ); if( !pszDestAddr || !inet_aton( pszDestAddr, &sin->sin_addr ) ) { logmsg( _("HHCTU022E %s: Invalid destiniation address: %s.\n"), pszNetDevName, !pszDestAddr ? "NULL" : pszDestAddr ); return -1; } sin = (struct sockaddr_in*)&rtentry.rt_genmask; sin->sin_family = AF_INET; set_sockaddr_in_sin_len( sin ); if( !pszNetMask || !inet_aton( pszNetMask, &sin->sin_addr ) ) { logmsg( _("HHCTU023E %s: Invalid net mask: %s.\n"), pszNetDevName, !pszNetMask ? "NULL" : pszNetMask ); return -1; } sin = (struct sockaddr_in*)&rtentry.rt_gateway; sin->sin_family = AF_INET; set_sockaddr_in_sin_len( sin ); if( pszGWAddr ) { if( !inet_aton( pszGWAddr, &sin->sin_addr ) ) { logmsg( _("HHCTU024E %s: Invalid gateway address: %s.\n"), pszNetDevName, pszGWAddr ); return -1; } } rtentry.rt_flags = iFlags; return TUNTAP_IOCtl( 0, SIOCDELRT, (char*)&rtentry ); } #endif // OPTION_TUNTAP_DELADD_ROUTES #if !defined( OPTION_W32_CTCI ) // ==================================================================== // HercIFC Helper Functions // ==================================================================== // // IFC_IOCtl // static int IFC_IOCtl( int fd, unsigned long int iRequest, char* argp ) { char* pszCfgCmd; // Interface config command int rc; CTLREQ ctlreq; char* request_name; // debugging: name of ioctl request #if defined(DEBUG) || defined(_DEBUG) char unknown_request[] = "Unknown (0x00000000)"; #endif UNREFERENCED( fd ); memset( &ctlreq, 0, CTLREQ_SIZE ); ctlreq.iCtlOp = iRequest; #if defined(DEBUG) || defined(_DEBUG) // Select string to represent ioctl request for debugging. switch (iRequest) { #ifdef OPTION_TUNTAP_CLRIPADDR case SIOCDIFADDR: request_name="SIOCDIFADDR"; break; #endif case SIOCSIFADDR: request_name="SIOCSIFADDR"; break; case SIOCSIFDSTADDR: request_name="SIOCSIFDSTADDR"; break; case SIOCSIFMTU: request_name="SIOCSIFMTU"; break; case SIOCSIFFLAGS: request_name="SIOCSIFFLAGS"; break; case SIOCGIFFLAGS: request_name="SIOCGIFFLAGS"; break; #ifdef OPTION_TUNTAP_SETNETMASK case SIOCSIFNETMASK: request_name="SIOCSIFNETMASK"; break; #endif #ifdef OPTION_TUNTAP_SETMACADDR case SIOCSIFHWADDR: request_name="SIOCSIFHWADDR"; break; #endif #ifdef OPTION_TUNTAP_DELADD_ROUTES case SIOCADDRT: request_name="SIOCADDRT"; break; case SIOCDELRT: request_name="SIOCDELRT"; break; #endif default: sprintf(unknown_request,"Unknown (0x%x)",iRequest); request_name=unknown_request; } #endif // defined(DEBUG) || defined(_DEBUG) #ifdef OPTION_TUNTAP_DELADD_ROUTES if( iRequest == SIOCADDRT || iRequest == SIOCDELRT ) { strcpy( ctlreq.szIFName, ((struct rtentry*)argp)->rt_dev ); memcpy( &ctlreq.iru.rtentry, argp, sizeof( struct rtentry ) ); ((struct rtentry*)argp)->rt_dev = NULL; } else #endif { memcpy( &ctlreq.iru.ifreq, argp, sizeof( struct ifreq ) ); } if( ifc_fd[0] == -1 && ifc_fd[1] == -1 ) { if( socketpair( AF_UNIX, SOCK_STREAM, 0, ifc_fd ) < 0 ) { logmsg( _("HHCTU025E Call to socketpair failed: %s\n"), strerror( errno ) ); return -1; } // Obtain the name of the interface config program or default if( !( pszCfgCmd = getenv( "HERCULES_IFC" ) ) ) pszCfgCmd = HERCIFC_CMD; TRACE(_("HHCTU029I Executing '%s' to configure interface\n"), pszCfgCmd); // Fork a process to execute the hercifc ifc_pid = fork(); if( ifc_pid < 0 ) { logmsg( _("HHCTU026E Call to fork failed: %s\n"), strerror( errno ) ); return -1; } // The child process executes the configuration command if( ifc_pid == 0 ) { /* @ISW@ Close all file descriptors * (except ifc_fd[1] and STDOUT FILENO) * (otherwise some devices are never closed) * (ex: SCSI tape devices can never be re-opened) */ struct rlimit rlim; int i; rlim_t file_limit; getrlimit(RLIMIT_NOFILE,&rlim); /* While Linux and Cygwin have limits of 1024 files by default, * Mac OS X does not - its default is -1, or completely unlimited. * The following hack is to defend against trying to close 2 * billion files. -- JRM */ file_limit=rlim.rlim_max; file_limit=(file_limit>1024)?1024:file_limit; TRACE(_("HHCTU031I Closing %" I64_FMT "d files\n"), (long long)file_limit); for(i=0;(unsigned int)isin_len = sizeof( struct sockaddr_in ) #else #define set_sockaddr_in_sin_len( sockaddr_in_ptr ) #endif // ==================================================================== // Declarations // ==================================================================== // // Create TUN/TAP Interface // extern int TUNTAP_CreateInterface ( char* pszTUNDevice, int iFlags, int* pfd, char* pszNetDevName ); // // Configure TUN/TAP Interface // #ifdef OPTION_TUNTAP_CLRIPADDR extern int TUNTAP_ClrIPAddr ( char* pszNetDevName ); #endif extern int TUNTAP_SetIPAddr ( char* pszNetDevName, char* pszIPAddr ); extern int TUNTAP_SetDestAddr ( char* pszNetDevName, char* pszDestAddr ); #ifdef OPTION_TUNTAP_SETNETMASK extern int TUNTAP_SetNetMask ( char* pszNetDevName, char* pszNetMask ); #endif extern int TUNTAP_SetMTU ( char* pszNetDevName, char* pszMTU ); #ifdef OPTION_TUNTAP_SETMACADDR extern int TUNTAP_SetMACAddr ( char* pszNetDevName, char* pszMACAddr ); #endif extern int TUNTAP_SetFlags ( char* pszNetDevName, int iFlags ); extern int TUNTAP_GetFlags ( char* pszNetDevName, int* piFlags ); #ifdef OPTION_TUNTAP_DELADD_ROUTES extern int TUNTAP_AddRoute ( char* pszNetDevName, char* pszDestAddr, char* pszNetMask, char* pszGWAddr, int iFlags ); extern int TUNTAP_DelRoute ( char* pszNetDevName, char* pszDestAddr, char* pszNetMask, char* pszGWAddr, int iFlags ); #endif // (the following function used by Win32 *and* NON-Win32 platforms) extern void build_herc_iface_mac ( BYTE* out_mac, const BYTE* in_ip ); // // Helper Macros // #if defined( WIN32 ) #define TUNTAP_Open tt32_open #define TUNTAP_Close tt32_close #define TUNTAP_Read tt32_read #define TUNTAP_Write tt32_write #define TUNTAP_IOCtl tt32_ioctl #else #define TUNTAP_Open open #define TUNTAP_Close close #define TUNTAP_Read read #define TUNTAP_Write write #define TUNTAP_IOCtl ioctl #endif // defined( WIN32 ) #if defined( WIN32 ) // Win32 (MinGW/Cygwin/MSVC) does not have these // so we need to define them ourselves... struct rtentry { unsigned long int rt_pad1; struct sockaddr rt_dst; // Target address. struct sockaddr rt_gateway; // Gateway addr (RTF_GATEWAY) struct sockaddr rt_genmask; // Target network mask (IP) unsigned short int rt_flags; short int rt_pad2; unsigned long int rt_pad3; unsigned char rt_tos; unsigned char rt_class; short int rt_pad4; short int rt_metric; // +1 for binary compatibility! char * rt_dev; // Forcing the device at add. unsigned long int rt_mtu; // Per route MTU/Window. unsigned long int rt_window; // Window clamping. unsigned short int rt_irtt; // Initial RTT. }; #define RTF_UP 0x0001 /* Route usable. */ #define RTF_GATEWAY 0x0002 /* Destination is a gateway. */ #define RTF_HOST 0x0004 /* Host entry (net otherwise). */ #define RTF_REINSTATE 0x0008 /* Reinstate route after timeout. */ #define RTF_DYNAMIC 0x0010 /* Created dyn. (by redirect). */ #define RTF_MODIFIED 0x0020 /* Modified dyn. (by redirect). */ #define RTF_MTU 0x0040 /* Specific MTU for this route. */ #define RTF_MSS RTF_MTU /* Compatibility. */ #define RTF_WINDOW 0x0080 /* Per route window clamping. */ #define RTF_IRTT 0x0100 /* Initial round trip time. */ #define RTF_REJECT 0x0200 /* Reject route. */ #define RTF_STATIC 0x0400 /* Manually injected route. */ #define RTF_XRESOLVE 0x0800 /* External resolver. */ #define RTF_NOFORWARD 0x1000 /* Forwarding inhibited. */ #define RTF_THROW 0x2000 /* Go to next class. */ #define RTF_NOPMTUDISC 0x4000 /* Do not send packets with DF. */ /* for IPv6 */ #define RTF_DEFAULT 0x00010000 /* default - learned via ND */ #define RTF_ALLONLINK 0x00020000 /* fallback, no routers on link */ #define RTF_ADDRCONF 0x00040000 /* addrconf route - RA */ #define RTF_LINKRT 0x00100000 /* link specific - device match */ #define RTF_NONEXTHOP 0x00200000 /* route with no nexthop */ #define RTF_CACHE 0x01000000 /* cache entry */ #define RTF_FLOW 0x02000000 /* flow significant route */ #define RTF_POLICY 0x04000000 /* policy route */ #define RTCF_VALVE 0x00200000 #define RTCF_MASQ 0x00400000 #define RTCF_NAT 0x00800000 #define RTCF_DOREDIRECT 0x01000000 #define RTCF_LOG 0x02000000 #define RTCF_DIRECTSRC 0x04000000 #define RTF_LOCAL 0x80000000 #define RTF_INTERFACE 0x40000000 #define RTF_MULTICAST 0x20000000 #define RTF_BROADCAST 0x10000000 #define RTF_NAT 0x08000000 #define RTF_ADDRCLASSMASK 0xF8000000 #define RT_ADDRCLASS(flags) ((__u_int32_t) flags >> 23) #define RT_TOS(tos) ((tos) & IPTOS_TOS_MASK) #define RT_LOCALADDR(flags) ((flags & RTF_ADDRCLASSMASK) \ == (RTF_LOCAL|RTF_INTERFACE)) #define RT_CLASS_UNSPEC 0 #define RT_CLASS_DEFAULT 253 #define RT_CLASS_MAIN 254 #define RT_CLASS_LOCAL 255 #define RT_CLASS_MAX 255 #define RTMSG_ACK NLMSG_ACK #define RTMSG_OVERRUN NLMSG_OVERRUN #define RTMSG_NEWDEVICE 0x11 #define RTMSG_DELDEVICE 0x12 #define RTMSG_NEWROUTE 0x21 #define RTMSG_DELROUTE 0x22 #define RTMSG_NEWRULE 0x31 #define RTMSG_DELRULE 0x32 #define RTMSG_CONTROL 0x40 #define RTMSG_AR_FAILED 0x51 /* Address Resolution failed. */ /* Use the definitions from the kernel header files. */ //#include // PROGRAMMING NOTE: Cygwin's headers define some (but not all) // of the below values, but we unfortunately MUST use the below // defined values since they're what TunTap32 expects... #undef SIOCGIFCONF // (discard Cygwin's value to use below instead) #undef SIOCGIFFLAGS // (discard Cygwin's value to use below instead) #undef SIOCGIFADDR // (discard Cygwin's value to use below instead) #undef SIOCGIFBRDADDR // (discard Cygwin's value to use below instead) #undef SIOCGIFNETMASK // (discard Cygwin's value to use below instead) #undef SIOCGIFMETRIC // (discard Cygwin's value to use below instead) #undef SIOCGIFMTU // (discard Cygwin's value to use below instead) #undef SIOCGIFHWADDR // (discard Cygwin's value to use below instead) /* Routing table calls. */ #define SIOCADDRT 0x890B /* add routing table entry */ #define SIOCDELRT 0x890C /* delete routing table entry */ #define SIOCRTMSG 0x890D /* call to routing system */ /* Socket configuration controls. */ #define SIOCGIFNAME 0x8910 /* get iface name */ #define SIOCSIFLINK 0x8911 /* set iface channel */ #define SIOCGIFCONF 0x8912 /* get iface list */ #define SIOCGIFFLAGS 0x8913 /* get flags */ #define SIOCSIFFLAGS 0x8914 /* set flags */ #define SIOCGIFADDR 0x8915 /* get PA address */ #define SIOCSIFADDR 0x8916 /* set PA address */ #define SIOCGIFDSTADDR 0x8917 /* get remote PA address */ #define SIOCSIFDSTADDR 0x8918 /* set remote PA address */ #define SIOCGIFBRDADDR 0x8919 /* get broadcast PA address */ #define SIOCSIFBRDADDR 0x891a /* set broadcast PA address */ #define SIOCGIFNETMASK 0x891b /* get network PA mask */ #define SIOCSIFNETMASK 0x891c /* set network PA mask */ #define SIOCGIFMETRIC 0x891d /* get metric */ #define SIOCSIFMETRIC 0x891e /* set metric */ #define SIOCGIFMEM 0x891f /* get memory address (BSD) */ #define SIOCSIFMEM 0x8920 /* set memory address (BSD) */ #define SIOCGIFMTU 0x8921 /* get MTU size */ #define SIOCSIFMTU 0x8922 /* set MTU size */ #define SIOCSIFHWADDR 0x8924 /* set hardware address */ #define SIOCGIFENCAP 0x8925 /* get/set encapsulations */ #define SIOCSIFENCAP 0x8926 #define SIOCGIFHWADDR 0x8927 /* Get hardware address */ #define SIOCGIFSLAVE 0x8929 /* Driver slaving support */ #define SIOCSIFSLAVE 0x8930 #define SIOCADDMULTI 0x8931 /* Multicast address lists */ #define SIOCDELMULTI 0x8932 #define SIOCGIFINDEX 0x8933 /* name -> if_index mapping */ #define SIOGIFINDEX SIOCGIFINDEX /* misprint compatibility :-) */ #define SIOCSIFPFLAGS 0x8934 /* set/get extended flags set */ #define SIOCGIFPFLAGS 0x8935 #define SIOCDIFADDR 0x8936 /* delete PA address */ #define SIOCSIFHWBROADCAST 0x8937 /* set hardware broadcast addr */ #define SIOCGIFCOUNT 0x8938 /* get number of devices */ #define SIOCGIFBR 0x8940 /* Bridging support */ #define SIOCSIFBR 0x8941 /* Set bridging options */ #define SIOCGIFTXQLEN 0x8942 /* Get the tx queue length */ #define SIOCSIFTXQLEN 0x8943 /* Set the tx queue length */ /* ARP cache control calls. */ /* 0x8950 - 0x8952 * obsolete calls, don't re-use */ #define SIOCDARP 0x8953 /* delete ARP table entry */ #define SIOCGARP 0x8954 /* get ARP table entry */ #define SIOCSARP 0x8955 /* set ARP table entry */ /* RARP cache control calls. */ #define SIOCDRARP 0x8960 /* delete RARP table entry */ #define SIOCGRARP 0x8961 /* get RARP table entry */ #define SIOCSRARP 0x8962 /* set RARP table entry */ /* Driver configuration calls */ #define SIOCGIFMAP 0x8970 /* Get device parameters */ #define SIOCSIFMAP 0x8971 /* Set device parameters */ /* DLCI configuration calls */ #define SIOCADDDLCI 0x8980 /* Create new DLCI device */ #define SIOCDELDLCI 0x8981 /* Delete DLCI device */ /* Device private ioctl calls. */ /* These 16 ioctls are available to devices via the do_ioctl() device vector. Each device should include this file and redefine these names as their own. Because these are device dependent it is a good idea _NOT_ to issue them to random objects and hope. */ #define SIOCDEVPRIVATE 0x89F0 /* to 89FF */ /* * These 16 ioctl calls are protocol private */ #define SIOCPROTOPRIVATE 0x89E0 /* to 89EF */ #endif // defined( WIN32 ) #endif // __TUNTAP_H_ hercules-3.07/util/000777 000765 000765 00000000000 11345533275 015734 5ustar00jmaynardjmaynard000000 000000 hercules-3.07/vector.c000644 000765 000765 00000064330 11143760544 016424 0ustar00jmaynardjmaynard000000 000000 /* vector.c S/370 and ESA/390 Vector Operations */ // $Id: vector.c 5127 2009-01-23 13:25:01Z bernard $ /*-------------------------------------------------------------------*/ /* This module implements the Vector Facility instruction execution */ /* function of the S/370 and ESA/390 architectures, as described in */ /* SA22-7125-03 Vector Operations (S/370 & ESA/370) */ /* SA22-7207-00 Vector Operations (ESA/390) */ /* 28/05/2000 Jan Jaeger */ /* */ /* Instruction decoding rework 09/07/2000 Jan Jaeger */ /* Interpretive Execution - (c) Copyright Jan Jaeger, 1999-2009 */ /* z/Architecture support - (c) Copyright Jan Jaeger, 1999-2009 */ /*-------------------------------------------------------------------*/ // $Log$ // Revision 1.21 2007/06/23 00:04:19 ivan // Update copyright notices to include current year (2007) // // Revision 1.20 2007/01/13 07:26:30 bernard // backout ccmask // // Revision 1.19 2007/01/12 15:25:11 bernard // ccmask phase 1 // // Revision 1.18 2006/12/20 04:26:20 gsmith // 19 Dec 2006 ip_all.pat - performance patch - Greg Smith // // Revision 1.17 2006/12/08 09:43:31 jj // Add CVS message log // #include "hstdinc.h" #include "hercules.h" #include "opcode.h" #include "inline.h" #if defined(FEATURE_VECTOR_FACILITY) /* The vector save area must be aligned on a boundary 8 times the section size, however VM stores at 4 times the section size. I do not know if the book or VM is wrong. *JJ */ #define VSA_ALIGN 4 /*-------------------------------------------------------------------*/ /* A640 VTVM - Test VMR [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(v_test_vmr) { int unused1, unused2; U32 n, n1; RRE(inst, regs, unused1, unused2); VOP_CHECK(regs); /* Extract vector count (number of active bits in vmr) */ n = VECTOR_COUNT(regs); /* cc0 when the vector count is zero */ if( n == 0) { regs->psw.cc = 0; return; } /* Preset condition code according to first bit */ regs->psw.cc = VMR_SET(0, regs) ? 3 : 0; /* Check VMR bit to be equal to the first, exit with cc1 if an unequal bit found */ for(n1 = 1; n1 < n; n1++) if((regs->psw.cc == 0) != (VMR_SET(n1, regs) == 0)) { regs->psw.cc = 1; return; } } /*-------------------------------------------------------------------*/ /* A641 VCVM - Complement VMR [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(v_complement_vmr) { int unused1, unused2; U32 n, n1, n2; RRE(inst, regs, unused1, unused2); VOP_CHECK(regs); /* Extract vector count (number of active bits in vmr) */ n = VECTOR_COUNT(regs); /* Bytes - 1 */ n1 = n >> 3; /* Complement VMR */ for(n2 = 0; n2 <= n1; n2++) regs->vf->vmr[n2] ^= 0xFF; /* zeroize remainder */ regs->vf->vmr[n1] &= 0x7F00 >> (n & 7); for(n1++; n1 < sizeof(regs->vf->vmr); n1++) regs->vf->vmr[n1] = 0; } /*-------------------------------------------------------------------*/ /* A642 VCZVM - Count Left Zeros in VMR [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(v_count_left_zeros_in_vmr) { int gr1, unused2; U32 n, n1; RRE(inst, regs, gr1, unused2); VOP_CHECK(regs); /* Extract vector count (number of active bits in vmr) */ n = VECTOR_COUNT(regs); /* cc0 when the vector count is zero */ if( n == 0) { regs->psw.cc = 0; return; } /* Preset condition code according to first bit */ regs->psw.cc = VMR_SET(0, regs) ? 3 : 0; /* If the VCT is 1 and the first bit is one then exit wirh gr1 set to zero */ regs->GR_L(gr1) = 0; if(n == 1 && VMR_SET(0, regs)) return; /* Count left zeros, set cc1 and exit if a one is found */ regs->GR_L(gr1) = 1; for(n1 = 1; n1 < n; n1++) { if(!VMR_SET(n1, regs)) regs->GR_L(gr1)++; else { regs->psw.cc = 1; return; } } } /*-------------------------------------------------------------------*/ /* A643 VCOVM - Count Ones In VMR [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(v_count_ones_in_vmr) { int gr1, unused2; U32 n, n1; RRE(inst, regs, gr1, unused2); VOP_CHECK(regs); /* Extract vector count (number of active bits in vmr) */ n = VECTOR_COUNT(regs); /* cc0 when the vector count is zero */ if( n == 0) { regs->psw.cc = 0; return; } /* Preset condition code according to first bit */ regs->psw.cc = VMR_SET(0, regs) ? 3 : 0; /* Check VMR bit to be equal to the first, Count all ones, set cc1 if a bit is unequal */ regs->GR_L(gr1) = 0; for(n1 = 0; n1 < n; n1++) { if(VMR_SET(n1, regs)) { regs->GR_L(gr1)++; if(!VMR_SET(0, regs)) regs->psw.cc = 1; } else if(VMR_SET(0, regs)) regs->psw.cc = 1; } } /*-------------------------------------------------------------------*/ /* A644 VXVC - Exctract VCT [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(v_extract_vct) { int gr1, unused2; RRE(inst, regs, gr1, unused2); VOP_CHECK(regs); regs->GR_L(gr1) = VECTOR_COUNT(regs); } /*-------------------------------------------------------------------*/ /* A646 VXVMM - Extract Vector Modes [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(v_extract_vector_modes) { int gr1, unused2; RRE(inst, regs, gr1, unused2); VOP_CHECK(regs); regs->GR_L(gr1) = (regs->vf->vsr >> 48); } /*-------------------------------------------------------------------*/ /* A648 VRRS - Restore VR [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(v_restore_vr) { int gr1, unused2; U32 n, n1, n2; U64 d; RRE(inst, regs, gr1, unused2); VOP_CHECK(regs); ODD_CHECK(gr1, regs); /* n contrains the current save area address */ n = regs->GR_L(gr1) & ADDRESS_MAXWRAP(regs); /* n1 contains the starting element number */ if((n1 = regs->GR_L(gr1 + 1) >> 16) >= VECTOR_SECTION_SIZE) ARCH_DEP(program_interrupt)(regs, PGM_SPECIFICATION_EXCEPTION); /* Starting address must be eight times the section size aligned */ if((n - (8 * n1)) & ((VECTOR_SECTION_SIZE * VSA_ALIGN) - 1) ) ARCH_DEP(program_interrupt)(regs, PGM_SPECIFICATION_EXCEPTION); /* n2 contains VR pair, which must be an even reg */ if((n2 = regs->GR_L(gr1 + 1) & 0x0000FFFF) & 0x0000FFF1) ARCH_DEP(program_interrupt)(regs, PGM_SPECIFICATION_EXCEPTION); if( VR_INUSE(n2, regs) ) { /* Set the vector changed bit if in problem state */ if( PROBSTATE(®s->psw) ) SET_VR_CHANGED(n2, regs); for(; n1 < VECTOR_SECTION_SIZE; n1++) { /* Fetch vr pair from central storage */ d = ARCH_DEP(vfetch8)(n, gr1, regs); regs->vf->vr[n2][n1] = d >> 32; regs->vf->vr[n2+1][n1] = d; /* Increment element number */ n1++; regs->GR_L(gr1 + 1) &= 0x0000FFFF; regs->GR_L(gr1 + 1) |= n1 << 16; /* Update savearea address */ regs->GR_L(gr1) += 8; #if 0 /* This is where the instruction may be interrupted */ UPD_PSW_IA(regs, PSW_IA(regs, -4)); return; #endif } /* Indicate vr pair restored */ regs->psw.cc = 2; } else { regs->GR_L(gr1) += 8 * (VECTOR_SECTION_SIZE - n1); /* indicate v2 pair not restored */ regs->psw.cc = 0; } /* Set 2 if vr 14 is restored, 0 if not restored, 3 and 1 for other VR's respectively */ if(n2 != 14) regs->psw.cc++; /* Update the vector pair number, and zero element number */ n2 += 2; regs->GR_L(gr1 + 1) = n2; } /*-------------------------------------------------------------------*/ /* A649 VRSVC - Save Changed VR [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(v_save_changed_vr) { int gr1, unused2; U32 n, n1, n2; U64 d; RRE(inst, regs, gr1, unused2); VOP_CHECK(regs); PRIV_CHECK(regs); ODD_CHECK(gr1, regs); /* n contrains the current save area address */ n = regs->GR_L(gr1) & ADDRESS_MAXWRAP(regs); /* n1 contains the starting element number */ if((n1 = regs->GR_L(gr1 + 1) >> 16) >= VECTOR_SECTION_SIZE) ARCH_DEP(program_interrupt)(regs, PGM_SPECIFICATION_EXCEPTION); /* Starting address must be eight times the section size aligned */ if((n - (8 * n1)) & ((VECTOR_SECTION_SIZE * VSA_ALIGN) - 1) ) ARCH_DEP(program_interrupt)(regs, PGM_SPECIFICATION_EXCEPTION); /* n2 contains VR pair, which must be an even reg */ if((n2 = regs->GR_L(gr1 + 1) & 0x0000FFFF) & 0x0000FFF1) ARCH_DEP(program_interrupt)(regs, PGM_SPECIFICATION_EXCEPTION); if( VR_CHANGED(n2, regs) ) { for(; n1 < VECTOR_SECTION_SIZE; n1++) { /* Store vr pair in savearea */ d = ((U64)regs->vf->vr[n2][n1] << 32) | regs->vf->vr[n2+1][n1]; ARCH_DEP(vstore8)(d, n, gr1, regs); /* Update element number */ n1++; regs->GR_L(gr1 + 1) &= 0x0000FFFF; regs->GR_L(gr1 + 1) |= n1 << 16; regs->GR_L(gr1) += 8; #if 0 /* This is where the instruction may be interrupted */ UPD_PSW_IA(regs, PSW_IA(regs, -4)); return; #endif } /* Indicate vr pair saved */ regs->psw.cc = 2; /* Reset the VR changed bit */ RESET_VR_CHANGED(n2, regs); } else { regs->GR_L(gr1) += 8 * (VECTOR_SECTION_SIZE - n1); /* vr pair not saved */ regs->psw.cc = 0; } /* Set 2 if vr 14 is restored, 0 if not restored, 3 and 1 for other VR's respectively */ if(n2 != 14) regs->psw.cc++; /* Update the vector pair number, and zero element number */ n2 += 2; regs->GR_L(gr1 + 1) = n2; } /*-------------------------------------------------------------------*/ /* A64A VRSV - Save VR [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(v_save_vr) { int gr1, unused2; U32 n, n1, n2; U64 d; RRE(inst, regs, gr1, unused2); VOP_CHECK(regs); ODD_CHECK(gr1, regs); /* n contrains the current save area address */ n = regs->GR_L(gr1) & ADDRESS_MAXWRAP(regs); /* n1 contains the starting element number */ if((n1 = regs->GR_L(gr1 + 1) >> 16) >= VECTOR_SECTION_SIZE) ARCH_DEP(program_interrupt)(regs, PGM_SPECIFICATION_EXCEPTION); /* Starting address must be eight times the section size aligned */ if((n - (8 * n1)) & ((VECTOR_SECTION_SIZE * VSA_ALIGN) - 1) ) ARCH_DEP(program_interrupt)(regs, PGM_SPECIFICATION_EXCEPTION); /* n2 contains VR pair, which must be an even reg */ if((n2 = regs->GR_L(gr1 + 1) & 0x0000FFFF) & 0x0000FFF1) ARCH_DEP(program_interrupt)(regs, PGM_SPECIFICATION_EXCEPTION); if( VR_INUSE(n2, regs) ) { for(; n1 < VECTOR_SECTION_SIZE; n1++) { /* Store vr pair in savearea */ d = ((U64)regs->vf->vr[n2][n1] << 32) | regs->vf->vr[n2+1][n1]; ARCH_DEP(vstore8)(d, n, gr1, regs); /* Update element number */ n1++; regs->GR_L(gr1 + 1) &= 0x0000FFFF; regs->GR_L(gr1 + 1) |= n1 << 16; regs->GR_L(gr1) += 8; #if 0 /* This is where the instruction may be interrupted */ UPD_PSW_IA(regs, PSW_IA(regs, -4)); return; #endif } /* Indicate vr pair restored */ regs->psw.cc = 2; } else { regs->GR_L(gr1) += 8 * (VECTOR_SECTION_SIZE - n1); /* Indicate vr pair not restored */ regs->psw.cc = 0; } /* Set 2 if vr 14 is restored, 0 if not restored, 3 and 1 for other VR's respectively */ if(n2 != 14) regs->psw.cc++; /* Update the vector pair number, and zero element number */ n2 += 2; regs->GR_L(gr1 + 1) = n2; } /*-------------------------------------------------------------------*/ /* A680 VLVM - Load VMR [VS] */ /*-------------------------------------------------------------------*/ DEF_INST(v_load_vmr) { int rs2; U32 n, n1; VS(inst, regs, rs2); VOP_CHECK(regs); /* Extract vector count (number of active bits in vmr) */ n = VECTOR_COUNT(regs); n1 = n >> 3; ARCH_DEP(vfetchc)(regs->vf->vmr, n1, regs->GR_L(rs2) & ADDRESS_MAXWRAP(regs), rs2, regs); /* Set the inactive bits to zero */ regs->vf->vmr[n1] &= 0x7F00 >> (n & 7); for(n1++; n1 < sizeof(regs->vf->vmr); n1++) regs->vf->vmr[n1] = 0; } /*-------------------------------------------------------------------*/ /* A681 VLCVM - Load VMR Complement [VS] */ /*-------------------------------------------------------------------*/ DEF_INST(v_load_vmr_complement) { int rs2; U32 n, n1, n2; VS(inst, regs, rs2); VOP_CHECK(regs); /* Extract vector count (number of active bits in vmr) */ n = VECTOR_COUNT(regs); /* Number of bytes - 1 */ n1 = n >> 3; ARCH_DEP(vfetchc)(regs->vf->vmr, n1, regs->GR_L(rs2) & ADDRESS_MAXWRAP(regs), rs2, regs); /* Complement all bits loaded */ for(n2 = 0; n2 <= n1; n2++) regs->vf->vmr[n2] ^= 0xFF; /* Set the inactive bits to zero */ regs->vf->vmr[n1] &= 0x7F00 >> (n & 7); for(n1++; n1 < sizeof(regs->vf->vmr); n1++) regs->vf->vmr[n1] = 0; } /*-------------------------------------------------------------------*/ /* A682 VSTVM - Store VMR [VS] */ /*-------------------------------------------------------------------*/ DEF_INST(v_store_vmr) { int rs2; U32 n; VS(inst, regs, rs2); VOP_CHECK(regs); /* Extract vector count (number of active bits in vmr) */ n = VECTOR_COUNT(regs); ARCH_DEP(vstorec)(regs->vf->vmr, n >> 3, regs->GR_L(rs2) & ADDRESS_MAXWRAP(regs), rs2, regs); } /*-------------------------------------------------------------------*/ /* A684 VNVM - AND To VMR [VS] */ /*-------------------------------------------------------------------*/ DEF_INST(v_and_to_vmr) { int rs2; U32 n, n1, n2; BYTE workvmr[VECTOR_SECTION_SIZE/8]; VS(inst, regs, rs2); VOP_CHECK(regs); /* Extract vector count (number of active bits in vmr) */ n = VECTOR_COUNT(regs); /* Number of bytes - 1 */ n1 = n >> 3; ARCH_DEP(vfetchc)(workvmr, n1, regs->GR_L(rs2) & ADDRESS_MAXWRAP(regs), rs2, regs); /* And VMR with workvmr */ for(n2 = 0; n2 <= n1; n2++) regs->vf->vmr[n2] &= workvmr[n2]; /* zeroize remainder */ regs->vf->vmr[n1] &= 0x7F00 >> (n & 7); for(n1++; n1 < sizeof(regs->vf->vmr); n1++) regs->vf->vmr[n1] = 0; } /*-------------------------------------------------------------------*/ /* A685 VOVM - OR To VMR [VS] */ /*-------------------------------------------------------------------*/ DEF_INST(v_or_to_vmr) { int rs2; U32 n, n1, n2; BYTE workvmr[VECTOR_SECTION_SIZE/8]; VS(inst, regs, rs2); VOP_CHECK(regs); /* Extract vector count (number of active bits in vmr) */ n = VECTOR_COUNT(regs); /* Number of bytes - 1 */ n1 = n >> 3; ARCH_DEP(vfetchc)(workvmr, n1, regs->GR_L(rs2) & ADDRESS_MAXWRAP(regs), rs2, regs); /* OR VMR with workvmr */ for(n2 = 0; n2 <= n1; n2++) regs->vf->vmr[n2] |= workvmr[n2]; /* zeroize remainder */ regs->vf->vmr[n1] &= 0x7F00 >> (n & 7); for(n1++; n1 < sizeof(regs->vf->vmr); n1++) regs->vf->vmr[n1] = 0; } /*-------------------------------------------------------------------*/ /* A686 VXVM - Exclusive OR To VMR [VS] */ /*-------------------------------------------------------------------*/ DEF_INST(v_exclusive_or_to_vmr) { int rs2; U32 n, n1, n2; BYTE workvmr[VECTOR_SECTION_SIZE/8]; VS(inst, regs, rs2); VOP_CHECK(regs); /* Extract vector count (number of active bits in vmr) */ n = VECTOR_COUNT(regs); /* Number of bytes - 1 */ n1 = n >> 3; ARCH_DEP(vfetchc)(workvmr, n1, regs->GR_L(rs2) & ADDRESS_MAXWRAP(regs), rs2, regs); /* OR VMR with workvmr */ for(n2 = 0; n2 <= n1; n2++) regs->vf->vmr[n2] ^= workvmr[n2]; /* zeroize remainder */ regs->vf->vmr[n1] &= 0x7F00 >> (n & 7); for(n1++; n1 < sizeof(regs->vf->vmr); n1++) regs->vf->vmr[n1] = 0; } /*-------------------------------------------------------------------*/ /* A6C0 VSRSV - Save VSR [S] */ /*-------------------------------------------------------------------*/ DEF_INST(v_save_vsr) { int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ S(inst, regs, b2, effective_addr2); VOP_CHECK(regs); DW_CHECK(effective_addr2, regs); ARCH_DEP(vstore8)(regs->vf->vsr, effective_addr2, b2, regs); } /*-------------------------------------------------------------------*/ /* A6C1 VMRSV - Save VMR [S] */ /*-------------------------------------------------------------------*/ DEF_INST(v_save_vmr) { int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ S(inst, regs, b2, effective_addr2); VOP_CHECK(regs); ARCH_DEP(vstorec)(regs->vf->vmr, sizeof(regs->vf->vmr) - 1, effective_addr2, b2, regs); } /*-------------------------------------------------------------------*/ /* A6C2 VSRRS - Restore VSR [S] */ /*-------------------------------------------------------------------*/ DEF_INST(v_restore_vsr) { int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ U32 n1, n2; U64 d; S(inst, regs, b2, effective_addr2); VOP_CHECK(regs); DW_CHECK(effective_addr2, regs); /* Fetch operand */ d = ARCH_DEP(vfetch8)(effective_addr2, b2, regs); /* Check for reserved bits nonzero, vector count not greater then section size and vector interruption index not greater then section size */ if((d & VSR_RESV) || ((d & VSR_VCT) >> 32) > VECTOR_SECTION_SIZE || ((d & VSR_VIX) >> 16) >= VECTOR_SECTION_SIZE) ARCH_DEP(program_interrupt)(regs, PGM_SPECIFICATION_EXCEPTION); /* In problem state the change bit are set corresponding the inuse bits */ if(PROBSTATE(®s->psw)) { d &= ~VSR_VCH; d |= (d & VSR_VIU) >> 8; } /* Clear any VRs whose inuse bits are being set to zero */ for(n1 = 0; n1 < 16; n1 += 2) { if( VR_INUSE(n1, regs) && !((d & VSR_VIU) & (VSR_VCH0 >> (n1 >> 1))) ) for(n2 = 0; n2 < VECTOR_SECTION_SIZE; n2++) { regs->vf->vr[n1][n2] = 0; regs->vf->vr[n1+1][n2] = 0; } } /* Update the vector status register */ regs->vf->vsr = d; } /*-------------------------------------------------------------------*/ /* A6C3 VMRRS - Restore VMR [S] */ /*-------------------------------------------------------------------*/ DEF_INST(v_restore_vmr) { int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ S(inst, regs, b2, effective_addr2); VOP_CHECK(regs); ARCH_DEP(vfetchc)(regs->vf->vmr, sizeof(regs->vf->vmr) - 1, effective_addr2, b2, regs); } /*-------------------------------------------------------------------*/ /* A6C4 VLVCA - Load VCT from Address [S] */ /*-------------------------------------------------------------------*/ DEF_INST(v_load_vct_from_address) { int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ U32 n; S_NW(inst, regs, b2, effective_addr2); VOP_CHECK(regs); regs->psw.cc = ((S32)effective_addr2 == 0) ? 0 : ((S32)effective_addr2 < 0) ? 1 : ((S32)effective_addr2 > VECTOR_SECTION_SIZE) ? 2 : 3; n = (S32)effective_addr2 < 0 ? 0 : (S32)effective_addr2 > VECTOR_SECTION_SIZE ? VECTOR_SECTION_SIZE : (S32)effective_addr2; regs->vf->vsr &= ~VSR_VCT; regs->vf->vsr |= (U64)n << 32; } /*-------------------------------------------------------------------*/ /* A6C5 VRCL - Clear VR [S] */ /*-------------------------------------------------------------------*/ DEF_INST(v_clear_vr) { int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ U32 n, n1, n2; S(inst, regs, b2, effective_addr2); VOP_CHECK(regs); /* Set vector interruption index to zero */ regs->vf->vsr &= ~VSR_VIX; /* Clear vr's identified in the bit mask n1 contains the vr number n2 contains the bitmask identifying the vr number n contains the element number */ for(n1 = 0, n2 = 0x80; n1 <= 14; n1 += 2, n2 >>= 1) if(effective_addr2 & n2) { for(n = 0; n < VECTOR_SECTION_SIZE; n++) { regs->vf->vr[n1][n] = 0; regs->vf->vr[n1+1][n] = 0; } RESET_VR_INUSE(n1, regs); } } /*-------------------------------------------------------------------*/ /* A6C6 VSVMM - Set Vector Mask Mode [S] */ /*-------------------------------------------------------------------*/ DEF_INST(v_set_vector_mask_mode) { int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ S(inst, regs, b2, effective_addr2); VOP_CHECK(regs); if(effective_addr2 & 1) regs->vf->vsr |= VSR_M; else regs->vf->vsr &= ~VSR_M; } /*-------------------------------------------------------------------*/ /* A6C7 VLVXA - Load VIX from Address [S] */ /*-------------------------------------------------------------------*/ DEF_INST(v_load_vix_from_address) { int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ U32 n; S_NW(inst, regs, b2, effective_addr2); VOP_CHECK(regs); regs->psw.cc = ((S32)effective_addr2 == 0) ? 0 : ((S32)effective_addr2 < 0) ? 1 : ((S32)effective_addr2 < VECTOR_COUNT(regs)) ? 2 : 3; n = (S32)effective_addr2 < 0 ? 0 : (S32)effective_addr2 > VECTOR_SECTION_SIZE ? VECTOR_SECTION_SIZE : (S32)effective_addr2; regs->vf->vsr &= ~VSR_VIX; regs->vf->vsr |= (U64)n << 16; } /*-------------------------------------------------------------------*/ /* A6C8 VSTVP - Store Vector Parameters [S] */ /*-------------------------------------------------------------------*/ DEF_INST(v_store_vector_parameters) { int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ S(inst, regs, b2, effective_addr2); VOP_CHECK(regs); FW_CHECK(effective_addr2, regs); /* Store the section size and partial sum number */ ARCH_DEP(vstore4)(VECTOR_SECTION_SIZE << 16 | VECTOR_PARTIAL_SUM_NUMBER, effective_addr2, b2, regs); } /*-------------------------------------------------------------------*/ /* A6CA VACSV - Save VAC [S] */ /*-------------------------------------------------------------------*/ DEF_INST(v_save_vac) { int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ S(inst, regs, b2, effective_addr2); VOP_CHECK(regs); PRIV_CHECK(regs); DW_CHECK(effective_addr2, regs); #if defined(_FEATURE_SIE) if(SIE_STATB(regs, IC3, VACSV)) longjmp(regs->progjmp, SIE_INTERCEPT_INST); #endif /*defined(_FEATURE_SIE)*/ ARCH_DEP(vstore8)(regs->vf->vac, effective_addr2, b2, regs); } /*-------------------------------------------------------------------*/ /* A6CB VACRS - Restore VAC [S] */ /*-------------------------------------------------------------------*/ DEF_INST(v_restore_vac) { int b2; /* Base of effective addr */ VADR effective_addr2; /* Effective address */ S(inst, regs, b2, effective_addr2); VOP_CHECK(regs); PRIV_CHECK(regs); DW_CHECK(effective_addr2, regs); #if defined(_FEATURE_SIE) if(SIE_STATB(regs, IC3, VACRS)) longjmp(regs->progjmp, SIE_INTERCEPT_INST); #endif /*defined(_FEATURE_SIE)*/ regs->vf->vac = ARCH_DEP(vfetch8)(effective_addr2, b2, regs) & VAC_MASK; } #endif /*defined(FEATURE_VECTOR_FACILITY)*/ #if !defined(_GEN_ARCH) #if defined(_ARCHMODE2) #define _GEN_ARCH _ARCHMODE2 #include "vector.c" #endif #if defined(_ARCHMODE3) #undef _GEN_ARCH #define _GEN_ARCH _ARCHMODE3 #include "vector.c" #endif #endif /*!defined(_GEN_ARCH)*/ hercules-3.07/version.c000644 000765 000765 00000016733 11301535255 016606 0ustar00jmaynardjmaynard000000 000000 /* VERSION.C (c) Copyright Roger Bowler, 1999-2009 */ /* Hercules Version Display Module */ // $Id: version.c 5480 2009-10-09 13:10:39Z fish $ /*-------------------------------------------------------------------*/ /* This module displays the Hercules program name, version, build */ /* date and time, and copyright notice to the indicated file. */ /*-------------------------------------------------------------------*/ // $Log$ // Revision 1.52 2009/01/23 13:12:19 bernard // copyright notice // // Revision 1.51 2009/01/14 15:23:20 jj // Move modpath logic to hsccmd.c // // Revision 1.50 2007/12/07 12:50:22 rbowler // Show multi_byte assist status at startup // // Revision 1.49 2007/06/23 00:04:19 ivan // Update copyright notices to include current year (2007) // // Revision 1.48 2006/12/08 09:43:31 jj // Add CVS message log // #include "hstdinc.h" #define _VERSION_C_ #define _HUTIL_DLL_ #include "hercules.h" #include "machdep.h" /*--------------------------------------------------*/ /* "Unusual" (i.e. noteworthy) build options... */ /*--------------------------------------------------*/ static const char *build_info[] = { #if defined(_MSVC_) "Windows (MSVC) " #if defined(DEBUG) "** DEBUG ** " #endif "build for " MSTRING(HOST_ARCH) #if defined(CUSTOM_BUILD_STRING) ": \"" CUSTOM_BUILD_STRING "\"" #endif , #elif defined(CUSTOM_BUILD_STRING) CUSTOM_BUILD_STRING, #endif #if !defined(_ARCHMODE2) "Mode:" #else "Modes:" #endif #if defined(_370) " " _ARCH_370_NAME #endif #if defined(_390) " " _ARCH_390_NAME #endif #if defined(_900) " " _ARCH_900_NAME #endif , "Max CPU Engines: " MSTRING(MAX_CPU_ENGINES), #if !defined(_MSVC_) #if defined(NO_SETUID) "No setuid support", #else "Using " #if defined(HAVE_SETRESUID) "setresuid()" #elif defined(HAVE_SETREUID) "setreuid()" #else "(UNKNOWN)" #endif " for setting privileges", #endif #endif #if defined(OPTION_FTHREADS) "Using fthreads instead of pthreads", #endif #if defined(OPTION_DYNAMIC_LOAD) "Dynamic loading support", #else "No Dynamic loading support", #endif #if defined(HDL_BUILD_SHARED) "Using shared libraries", #else "Using static libraries", #endif #if !defined(EXTERNALGUI) "No External GUI support", #endif #if defined(OPTION_HTTP_SERVER) "HTTP Server support", #if defined(PKGDATADIR) && defined(DEBUG) "HTTP document default root directory is "PKGDATADIR, #endif #endif #if defined(NO_IEEE_SUPPORT) "No IEEE support", #else #if !defined(HAVE_SQRTL) "No sqrtl support", #endif #endif #if defined(NO_SIGABEND_HANDLER) "No SIGABEND handler", #endif #if !defined(CCKD_BZIP2) "No CCKD BZIP2 support", #endif #if !defined(HAVE_LIBZ) "No ZLIB support", #endif #if defined(HAVE_REGEX_H) || defined(HAVE_PCRE) "Regular Expressions support", #endif #if defined(OPTION_HAO) "Automatic Operator support", #endif #if !defined(HET_BZIP2) "No HET BZIP2 support", #endif #if defined(ENABLE_NLS) "National Language Support", #endif "Machine dependent assists:" #if !defined( ASSIST_CMPXCHG1 ) \ && !defined( ASSIST_CMPXCHG4 ) \ && !defined( ASSIST_CMPXCHG8 ) \ && !defined( ASSIST_CMPXCHG16 ) \ && !defined( ASSIST_FETCH_DW ) \ && !defined( ASSIST_STORE_DW ) \ && !defined( MULTI_BYTE_ASSIST) " (none)", #else #if defined( ASSIST_CMPXCHG1 ) " cmpxchg1" #endif #if defined( ASSIST_CMPXCHG4 ) " cmpxchg4" #endif #if defined( ASSIST_CMPXCHG8 ) " cmpxchg8" #endif #if defined( ASSIST_CMPXCHG16 ) " cmpxchg16" #endif #if defined( ASSIST_FETCH_DW ) " fetch_dw" #endif #if defined( ASSIST_STORE_DW ) " store_dw" #endif #if defined( MULTI_BYTE_ASSIST ) " multi_byte" #endif , #endif }; /*-------------------------------------------------------------------*/ /* Retrieve ptr to build information strings array... */ /* (returns #of entries in array) */ /*-------------------------------------------------------------------*/ DLL_EXPORT int get_buildinfo_strings(const char*** pppszBldInfoStr) { if (!pppszBldInfoStr) return 0; *pppszBldInfoStr = build_info; return ( sizeof(build_info) / sizeof(build_info[0]) ); } /*-------------------------------------------------------------------*/ /* Display version and copyright */ /*-------------------------------------------------------------------*/ DLL_EXPORT void display_version_2 (FILE *f, char *prog, const char verbose,int httpfd) { unsigned int i; const char** ppszBldInfoStr = NULL; #if defined(EXTERNALGUI) /* If external gui being used, set stdout & stderr streams to unbuffered so we don't have to flush them all the time in order to ensure consistent sequence of log messages. */ if (extgui) { setvbuf(stderr, NULL, _IONBF, 0); setvbuf(stdout, NULL, _IONBF, 0); } #endif /*EXTERNALGUI*/ /* Log version */ if ( f != stdout ) if(httpfd<0) fprintf (f, _("%sVersion %s\n"), prog, VERSION); else hprintf (httpfd, _("%sVersion %s\n"), prog, VERSION); else logmsg ( _("%sVersion %s\n"), prog, VERSION); /* Log Copyright */ if ( f != stdout ) if(httpfd<0) fprintf (f, "%s\n", HERCULES_COPYRIGHT); else hprintf (httpfd, "%s\n", HERCULES_COPYRIGHT); else logmsg ( "%s\n", HERCULES_COPYRIGHT); /* If we're being verbose, display the rest of the info */ if (verbose) { /* Log build date/time */ if ( f != stdout ) if(httpfd<0) fprintf (f, _("Built on %s at %s\n"), __DATE__, __TIME__); else hprintf (httpfd, _("Built on %s at %s\n"), __DATE__, __TIME__); else logmsg ( _("Built on %s at %s\n"), __DATE__, __TIME__); /* Log "unusual" build options */ if ( f != stdout ) if(httpfd<0) fprintf (f, _("Build information:\n")); else hprintf (httpfd, _("Build information:\n")); else logmsg ( _("Build information:\n")); if (!(i = get_buildinfo_strings( &ppszBldInfoStr ))) { if ( f != stdout ) if(httpfd<0) fprintf (f, " (none)\n"); else hprintf (httpfd, " (none)\n"); else logmsg ( " (none)\n"); } else { for(; i; i--, ppszBldInfoStr++ ) { if ( f != stdout ) if(httpfd<0) fprintf (f, " %s\n", *ppszBldInfoStr); else hprintf (httpfd, " %s\n", *ppszBldInfoStr); else logmsg ( " %s\n", *ppszBldInfoStr); } } if(f != stdout) if(httpfd<0) display_hostinfo( &hostinfo, f, -1 ); else display_hostinfo( &hostinfo, (FILE *)-1,httpfd ); else display_hostinfo( &hostinfo, f, -1 ); } } /* end function display_version */ DLL_EXPORT void display_version(FILE *f,char *prog,const char verbose) { display_version_2(f,prog,verbose,-1); } hercules-3.07/version.h000644 000765 000765 00000003460 11333023063 016576 0ustar00jmaynardjmaynard000000 000000 /* VERSION.H (c) Copyright Roger Bowler, 1999-2009 */ /* ESA/390 Emulator Version definition */ // $Id: version.h 5604 2010-02-05 14:07:42Z jmaynard $ /*-------------------------------------------------------------------*/ /* Header file defining the Hercules version number. */ /* */ /* NOTE: If you're looking for the place to actually change the */ /* number, it's in configure.ac, near the top. */ /*-------------------------------------------------------------------*/ // $Log$ // Revision 1.18 2007/06/23 00:04:19 ivan // Update copyright notices to include current year (2007) // // Revision 1.17 2006/12/08 09:43:31 jj // Add CVS message log // #ifndef _HERCULES_H_ #define _HERCULES_H_ #include "hercules.h" #ifndef _VERSION_C_ #ifndef _HUTIL_DLL_ #define VER_DLL_IMPORT DLL_IMPORT #else /* _HUTIL_DLL_ */ #define VER_DLL_IMPORT extern #endif /* _HUTIL_DLL_ */ #else /* _LOGGER_C_ */ #define VER_DLL_IMPORT DLL_EXPORT #endif /* _LOGGER_C_ */ #if !defined(VERSION) #ifndef _MSVC_ #warning No version specified #else #pragma message( MSVC_MESSAGE_LINENUM "warning: No version specified" ) #endif #define VERSION "(unknown!)" #define CUSTOM_BUILD_STRING "('VERSION' was not defined!)" #endif #define HDL_VERS_HERCULES VERSION #define HDL_SIZE_HERCULES sizeof(VERSION) VER_DLL_IMPORT void display_version(FILE *f, char *prog, const char verbose); VER_DLL_IMPORT void display_version_2(FILE *f, char *prog, const char verbose,int httpfd); VER_DLL_IMPORT int get_buildinfo_strings(const char*** pppszBldInfoStr); #define HERCULES_COPYRIGHT \ "(c)Copyright 1999-2010 by Roger Bowler, Jan Jaeger, and others" #endif // _HERCULES_H_ hercules-3.07/vm.c000644 000765 000765 00000172211 11321734033 015532 0ustar00jmaynardjmaynard000000 000000 /* VM.C (c) Copyright Roger Bowler, 2000-2009 */ /* ESA/390 VM Diagnose calls and IUCV instruction */ /* Interpretive Execution - (c) Copyright Jan Jaeger, 1999-2009 */ // $Id: vm.c 5532 2009-12-11 19:28:19Z bernard $ /*-------------------------------------------------------------------*/ /* This module implements miscellaneous diagnose functions */ /* described in SC24-5670 VM/ESA CP Programming Services */ /* and SC24-5855 VM/ESA CP Diagnosis Reference */ /* and SC24-6084 z/VM 5.4 CP Programming Services. */ /* Modifications for Interpretive Execution (SIE) by Jan Jaeger */ /* z/Architecture support - (c) Copyright Jan Jaeger, 1999-2009 */ /*-------------------------------------------------------------------*/ #include "hstdinc.h" #if !defined(_HENGINE_DLL_) #define _HENGINE_DLL_ #endif /*_HENGINE_DLL_*/ #if !defined(_VM_C_) #define _VM_C_ #endif /* _VM_C_ */ #include "hercules.h" #include "opcode.h" #include "inline.h" #include "commadpt.h" #if defined(FEATURE_EMULATE_VM) #if !defined(_VM_C) #define _VM_C /*-------------------------------------------------------------------*/ /* Internal macro definitions */ /*-------------------------------------------------------------------*/ #define DEV024(_type,_cls,_typ) \ { _type,_cls,_typ,0xC0 } #define DEV210(_type,_cls,_typ) \ { _type,_cls,_typ,0x40 } /*-------------------------------------------------------------------*/ /* Synchronous Block I/O Parameter List */ /*-------------------------------------------------------------------*/ typedef struct _HCPSBIOP { HWORD devnum; /* Device number */ BYTE akey; /* Bits 0-3=key, 4-7=zeroes */ BYTE type; /* I/O request type */ FWORD blksize; /* Fixed block size */ FWORD sbiaddr; /* Address of SBILIST */ FWORD sbicount; /* Number of SBILIST entries */ FWORD blkcount; /* Number of blocks processed*/ BYTE unitstat; /* Device status */ BYTE chanstat; /* Subchannel status */ HWORD residual; /* Residual byte count */ BYTE lpm; /* Logical path mask */ BYTE resv1[5]; /* Reserved bytes, must be 0 */ HWORD sensecount; /* Number of sense bytes */ BYTE resv2[24]; /* Reserved bytes, must be 0 */ BYTE sense[32]; /* Sense bytes */ } HCPSBIOP; /* Definitions for I/O request type */ #define HCPSBIOP_WRITE 0x01 #define HCPSBIOP_READ 0x02 /*-------------------------------------------------------------------*/ /* Synchronous General I/O Parameter List */ /*-------------------------------------------------------------------*/ typedef struct _HCPSGIOP { HWORD devnum; /* Device number */ BYTE akey; /* Bits 0-3=key, 4-7=zeroes */ BYTE flag; /* Flags */ FWORD resv1; /* Reserved word, must be 0 */ FWORD ccwaddr; /* Address of channel program*/ FWORD resv2; /* Reserved word, must be 0 */ FWORD lastccw; /* CCW address at interrupt */ BYTE unitstat; /* Device status */ BYTE chanstat; /* Subchannel status */ HWORD residual; /* Residual byte count */ BYTE lpm; /* Logical path mask */ BYTE resv3[5]; /* Reserved bytes, must be 0 */ HWORD sensecount; /* Number of sense bytes */ BYTE resv4[24]; /* Reserved bytes, must be 0 */ BYTE sense[32]; /* Sense bytes */ } HCPSGIOP; /* Bit definitions for flags */ #define HCPSGIOP_FORMAT1_CCW 0x80 /* 1=Format-1 CCW */ #define HCPSGIOP_FLAG_RESV 0x7F /* Reserved bits, must be 0 */ /*-------------------------------------------------------------------*/ /* DIAGNOSE X'24' and DIAGNOSE X'210' Structures and Table */ /*-------------------------------------------------------------------*/ /* VM Device Class Definitions */ #define DC_TERM 0x80 #define DC_GRAF 0x40 #define DC_URI 0x20 #define DC_URO 0x10 #define DC_TAPE 0x08 #define DC_DASD 0x04 #define DC_SPEC 0x02 #define DC_FBA 0x01 /* VM Device Type Definitions */ #define DT_CTCA 0x80 #define DT_FBA 0x00 #define DT_OSA 0x20 /* Not yet supported */ #define DT_UNKN 0x01 #define DT_0671 0x20 #define DT_1052 0x00 #define DT_1403 0x41 #define DT_1442 0x88 #define DT_2305 0x02 #define DT_2311 0x80 #define DT_2314 0x40 #define DT_2501 0x81 #define DT_2703 0x40 #define DT_3211 0x42 #define DT_3215 0x00 #define DT_3277 0x04 #define DT_3287 0x02 #define DT_3310 0x01 #define DT_3330 0x10 #define DT_3340 0x01 #define DT_3350 0x08 #define DT_3370 0x02 #define DT_3375 0x04 #define DT_3380 0x20 #define DT_3390 0x82 #define DT_3410 0x08 #define DT_3420 0x10 #define DT_3422 0x82 #define DT_3430 0x02 #define DT_3480 0x01 #define DT_3490 0x81 #define DT_3505 0x84 #define DT_3525 0x84 #define DT_3590 0x83 #define DT_370x 0x40 #define DT_8809 0x04 #define DT_9332 0x08 #define DT_9335 0x04 #define DT_9336 0x40 #define DT_9345 0x81 #define DT_9347 0x84 /* VM Virtual Device Status Definitions */ #define DS_DED 0x01 /* Dedicated device */ #define DS_BUSY 0x20 /* Device is busy */ /* VM Virtual Device Flag Definitions */ #define DF_ENA 0x80 /* 270x line enabled */ #define DF_CONN 0x40 /* 270x line connected */ #define DF_RSRL 0x02 /* Reserve/Release supported */ #define DF_MIDAW 0x01 /* MIDAW's supported */ /* VM Real Device Features */ #define DRF_RPS 0x80 /* Device has RPS */ #define DRF_EXTSNS 0x40 /* Extended Sense */ #define DRF_CTCA 0x40 /* CTCA device */ #define DRF_35M 0x08 /* 3340 has 35M data module */ #define DRF_70M 0x04 /* 3340 has 70M data module */ #define DRF_RSRL 0x02 /* Reserve/Release valid */ /*-------------------------------------------------------------------*/ /* Hercules-to-VM Device Table */ /*-------------------------------------------------------------------*/ typedef struct _VMDEVTBL { U16 vmhtype; /* Hercules device type */ BYTE vmdevcls; /* VM Device Class */ BYTE vmdevtyp; /* VM Device Type */ BYTE vmdiags; /* DIAGS recognizing device */ #define VMDIAG024 0x80 /* Device recognized by DIAGNOSE X'24' */ #define VMDIAG210 0x40 /* Device recognized by DIAGNOSE X'210' */ } VMDEVTBL; #define VMDEV_SIZE sizeof(VMDEVTBL) static VMDEVTBL vmdev[] = { DEV024(0x0671,DC_FBA, DT_0671), DEV024(0x1052,DC_TERM,DT_1052), DEV024(0x1403,DC_URO, DT_1403), DEV024(0x1442,DC_URI, DT_1442), DEV024(0x2305,DC_DASD,DT_2305), DEV024(0x2311,DC_DASD,DT_2311), DEV024(0x2314,DC_DASD,DT_2314), DEV024(0x2501,DC_URI, DT_2501), DEV024(0x2703,DC_TERM,DT_2703), DEV024(0x3088,DC_SPEC,DT_CTCA), DEV024(0x3211,DC_URI, DT_3211), DEV024(0x3215,DC_TERM,DT_3215), DEV024(0x3270,DC_GRAF,DT_3277), DEV024(0x3287,DC_GRAF,DT_3287), DEV024(0x3310,DC_FBA, DT_3310), DEV024(0x3330,DC_DASD,DT_3330), DEV024(0x3340,DC_DASD,DT_3340), DEV024(0x3350,DC_DASD,DT_3350), DEV024(0x3370,DC_FBA, DT_3370), DEV024(0x3375,DC_DASD,DT_3375), DEV024(0x3380,DC_DASD,DT_3380), DEV210(0x3390,DC_DASD,DT_3390), DEV024(0x3410,DC_TAPE,DT_3410), DEV024(0x3420,DC_TAPE,DT_3420), DEV024(0x3422,DC_TAPE,DT_3422), DEV024(0x3430,DC_TAPE,DT_3430), DEV024(0x3480,DC_TAPE,DT_3480), DEV210(0x3490,DC_TAPE,DT_3490), DEV024(0x3505,DC_URI, DT_3505), DEV024(0x3525,DC_URO, DT_3525), DEV024(0x3590,DC_TAPE,DT_3590), DEV024(0x3705,DC_SPEC,DT_370x), DEV024(0x8809,DC_TAPE,DT_8809), DEV024(0x9332,DC_FBA, DT_9332), DEV024(0x9335,DC_FBA, DT_9335), DEV024(0x9336,DC_FBA, DT_9336), DEV210(0x9345,DC_DASD,DT_9345), DEV024(0x9347,DC_TAPE,DT_9347) }; #define VMDEV_NUM (sizeof(vmdev)/VMDEV_SIZE) /*-------------------------------------------------------------------*/ /* Virtual Device Data */ /*-------------------------------------------------------------------*/ typedef struct _VRDCVDAT { BYTE vdevcls; /* Virtual device class */ BYTE vdevtyp; /* Virtual device type */ BYTE vdevstat; /* Virtual device status */ BYTE vdevflag; /* Virtual device flag */ } VRDCVDAT; /*-------------------------------------------------------------------*/ /* Real Device Data */ /*-------------------------------------------------------------------*/ typedef struct _VRDCRCDT { BYTE rdevcls; /* Real device class */ BYTE rdevtyp; /* Real device type */ BYTE rdevmodl; /* Real device model */ BYTE rdevfeat; /* Real device features */ } VRDCRCDT; /*-------------------------------------------------------------------*/ /* Virtual/Real Device Characteristics Block */ /*-------------------------------------------------------------------*/ typedef struct _VRDCBLOK { /*00*/ HWORD vrdcdvno; /* Device number */ /*02*/ HWORD vrdclen; /* VRDCBLOK length */ /*04*/ VRDCVDAT vrdcvdat; /* Virtual device data */ /*08*/ VRDCRCDT vrdcrcdt; /* Real device data */ /*0C*/ BYTE vrdcundv; /* Real underlying device */ /*0D*/ BYTE vrdcrdaf; /* Real device additional features */ #define VRDCEMRD 0x02 /* No emulated real device */ /*0E*/ HWORD vrdcrsvd; /* Reserved - must be zeros */ /*10*/ BYTE vrdcrdc[64]; /* READ DEVICE CHARACTERISTICS data */ /*50*/ BYTE vrdcpgid[11]; /* Path Group Identifier */ /*5B*/ BYTE resv5[5]; /* reserved */ /*60*/ BYTE vrdcvers; /* version */ /*61*/ BYTE vrdcrsio[31]; /* reserved for Input/Output */ /*80*/ HWORD vrdcrdev; /* Real device number */ /*82*/ BYTE vrdcrsve[126]; /* reserverd */ /*100*/ } VRDCBLOK; #define VRDCBLOK_SIZE sizeof(VRDCBLOK) #endif /*!defined(_VM_C)*/ /*-------------------------------------------------------------------*/ /* Internal Function Prototypes */ /*-------------------------------------------------------------------*/ DEVBLK* ARCH_DEP(vmdevice_data)(int, U16, VRDCVDAT *, VRDCRCDT *); /*-------------------------------------------------------------------*/ /* Provide VM Virtual and Real Device Data based upon device number */ /*-------------------------------------------------------------------*/ DEVBLK* ARCH_DEP(vmdevice_data)(int code, U16 devnum, VRDCVDAT *vdat, VRDCRCDT *rdat) { U32 i; /* loop index */ VMDEVTBL *vmentry; /* -> VMDEVTBL entry found */ DEVBLK *dev; /* -> DEVBLK */ /* Clear vdat and rdat */ memset (vdat, 0x00, sizeof(*vdat)); memset (rdat, 0x00, sizeof(*rdat)); /* Locate the device block */ dev = find_device_by_devnum (0,devnum); /* Return 0 if device is not found */ if (!dev) return 0; /* Indicate the device is dedicated - all Hercules devices are */ vdat->vdevstat = DS_DED; /* Find the device in the VM table */ vmentry=NULL; for (i = 0; i < (int)VMDEV_NUM; i++) { #if 0 logmsg ("vmdevice_data: i=%i %4.4X %2.2X %2.2X %2.2X\n",i, vmdev[i].vmhtype,vmdev[i].vmdevcls,vmdev[i].vmdevtyp,vmdev[i].vmdiags); #endif if (dev->devtype == vmdev[i].vmhtype) { vmentry = &vmdev[i]; break; } } #if 0 logmsg ("FOUND: %4.4X %2.2X %2.2X %2.2X\n", vmentry->vmhtype,vmentry->vmdevcls,vmentry->vmdevtyp,vmentry->vmdiags); #endif /* If device is not in the table or it isn't recognized by DIAG X'24' */ if ( !vmentry || ( code==0x24 && !(vmentry->vmdiags & VMDIAG024 ) ) ) { /* Set the real and virtual data to an unsupported device */ vdat->vdevcls = DC_SPEC; vdat->vdevtyp = DT_UNKN; rdat->rdevcls = DC_SPEC; rdat->rdevtyp = DT_UNKN; return dev; } /* Set the virtual and real data to the device's VM class and type */ vdat->vdevcls = vmentry->vmdevcls; vdat->vdevtyp = vmentry->vmdevtyp; rdat->rdevcls = vmentry->vmdevcls; rdat->rdevtyp = vmentry->vmdevtyp; /* Indicate if the device is busy */ if ( (dev->busy && dev->ioactive == DEV_SYS_LOCAL) || dev->startpending ) vdat->vdevstat |= DS_BUSY; /* Set virtual device flags, and real device model and features */ vdat->vdevflag = 0x00; rdat->rdevmodl = 0x00; rdat->rdevfeat = 0x00; if (dev->hnd->reserve) /* Indicate if RESERVE/RELEASE supported */ vdat->vdevflag |= DF_RSRL; #if defined(FEATURE_MIDAW) /* If DIAGNOSE X'210', indicate if MIDAW's are supported */ if (code==0x210) vdat->vdevflag |= DF_MIDAW; #endif /* FEATURE_MIDAW */ switch (rdat->rdevcls) { case DC_DASD: if (dev->hnd->reserve) rdat->rdevfeat |= DRF_RSRL; if (dev->numsense==24) rdat->rdevfeat |= DRF_EXTSNS; if (dev->ckdtab->sectors) rdat->rdevfeat |= DRF_RPS; if (dev->devtype == 0x3340) { if (dev->ckdtab->model==0x01) rdat->rdevfeat |= DRF_35M; else rdat->rdevfeat |= DRF_70M; } if ( dev->devtype == 0x3380 && code == 0x24) rdat->rdevmodl = (dev->ckdtab->model & 0x0F) | (dev->ckdcu->model & 0xF0); else rdat->rdevmodl = dev->ckdtab->model; break; case DC_FBA: rdat->rdevmodl = dev->fbatab->model; break; case DC_TERM: if (dev->devtype==0x3215) { rdat->rdevfeat = 0x50; /* Note: 0x50 is carried forward from the previous version of */ /* DIAGNOSE X'24'. The actual meaning was not previously documented */ } else { if (dev->devtype==0x2703 && dev->commadpt) { if (dev->commadpt->enabled) vdat->vdevflag |= DF_ENA; if (dev->commadpt->connect) vdat->vdevflag |= DF_CONN; } } break; case DC_SPEC: if (rdat->rdevtyp==DT_CTCA) rdat->rdevfeat = DRF_CTCA; } /* Return the located DEVBLK to the caller */ return dev; } /* end function vmdevice_data */ /*-------------------------------------------------------------------*/ /* Device Type and Features (Function code 0x024) */ /*-------------------------------------------------------------------*/ int ARCH_DEP(diag_devtype) (int r1, int r2, REGS *regs) { DEVBLK *dev; /* -> Device block */ U16 devnum; /* Device number */ VRDCVDAT vdat; /* Virtual device data */ VRDCRCDT rdat; /* Real device data */ #if defined(FEATURE_ESAME) /* Program check if 64-bit addressing is being used. */ if (regs->psw.amode64) { ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION); } #endif /* FEATURE_ESAME */ /* Return console information if R1 register is all ones */ if (regs->GR_L(r1) == 0xFFFFFFFF) { for (dev = sysblk.firstdev; dev != NULL; dev = dev->nextdev) if ( dev->allocated && ( dev->devtype == 0x3215 || dev->devtype == 0x1503 ) ) { regs->GR_L(r1) = dev->devnum; break; } } /* Extract the device number from the R1 register */ devnum = regs->GR_L(r1); /* Locate the device block and set the virtual and real device information */ dev = ARCH_DEP(vmdevice_data) (0x24,devnum,&vdat,&rdat); /* Return condition code 3 if device does not exist */ if (!dev) return 3; /* Return virtual device information in the R2 register */ FETCH_FW(regs->GR_L(r2),&vdat); /* Return real device information in the R2+1 register */ if (r2 != 15) FETCH_FW(regs->GR_L(r2+1),&rdat); #if 0 logmsg ("Diagnose X\'024\':" "devnum=%4.4X VRDCVDAT=%8.8X VRDCRCDT=%8.8X\n", devnum, vdat, rdat); #endif /* Return condition code 0 */ return 0; } /* end function diag_devtype */ /*-------------------------------------------------------------------*/ /* Process Synchronous Fixed Block I/O call (Function code 0x0A4) */ /*-------------------------------------------------------------------*/ int ARCH_DEP(syncblk_io) (int r1, int r2, REGS *regs) { U32 i; /* Array subscript */ U32 numsense; /* Number of sense bytes */ U32 iopaddr; /* Address of HCPSBIOP */ HCPSBIOP ioparm; /* I/O parameter list */ DEVBLK *dev; /* -> Device block */ U16 devnum; /* Device number */ U16 residual; /* Residual byte count */ U32 blksize; /* Fixed block size */ U32 sbiaddr; /* Addr of SBILIST */ U32 sbicount; /* Number of SBILIST entries */ U32 blkcount; /* Number of blocks processed*/ U32 blknum; /* Block number */ U32 absadr; /* Absolute storage address */ BYTE accum; /* Work area */ BYTE unitstat = 0; /* Device status */ BYTE chanstat = 0; /* Subchannel status */ BYTE skey1, skey2; /* Storage keys of first and last byte of I/O buffer */ //FIXME: code not right for shared devices UNREFERENCED(r2); /* Register R1 contains the real address of the parameter list */ iopaddr = regs->GR_L(r1); /* Program check if parameter list not on fullword boundary */ if (iopaddr & 0x00000003) { ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION); return 0; } /* Ensure that parameter list operand is addressable */ ARCH_DEP(validate_operand) (iopaddr, USE_REAL_ADDR, sizeof(ioparm)-1, ACCTYPE_WRITE, regs); /* Fetch the parameter list from real storage */ ARCH_DEP(vfetchc) (&ioparm, sizeof(ioparm)-1, iopaddr, USE_REAL_ADDR, regs); /* Load numeric fields from the parameter list */ devnum = (ioparm.devnum[0] << 8) | ioparm.devnum[1]; blksize = (ioparm.blksize[0] << 24) | (ioparm.blksize[1] << 16) | (ioparm.blksize[2] << 8) | ioparm.blksize[3]; sbiaddr = (ioparm.sbiaddr[0] << 24) | (ioparm.sbiaddr[1] << 16) | (ioparm.sbiaddr[2] << 8) | ioparm.sbiaddr[3]; sbicount = (ioparm.sbicount[0] << 24) | (ioparm.sbicount[1] << 16) | (ioparm.sbicount[2] << 8) | ioparm.sbicount[3]; /* Locate the device block */ dev = find_device_by_devnum (0,devnum); /* Set return code 2 and cond code 1 if device does not exist or does not support the synchronous I/O call */ if (dev == NULL || dev->devtype != 0x3370) { regs->GR_L(15) = 2; return 1; } /* Program check if protect key bits 4-7 are not zero or if I/O request type is not read or write */ if ((ioparm.akey & 0x0F) || !(ioparm.type == HCPSBIOP_WRITE || ioparm.type == HCPSBIOP_READ)) { ARCH_DEP(program_interrupt) (regs, PGM_OPERAND_EXCEPTION); return 0; } /* Set return code 8 and cond code 2 if blocksize is invalid */ if (!(blksize == 512 || blksize == 1024 || blksize == 2048 || blksize == 4096)) { regs->GR_L(15) = 8; return 2; } /* Program check if SBILIST is not on a doubleword boundary */ if (sbiaddr & 0x00000007) { ARCH_DEP(program_interrupt) (regs, PGM_OPERAND_EXCEPTION); return 0; } /* Program check if reserved fields are not zero */ for (accum = 0, i = 0; i < sizeof(ioparm.resv1); i++) accum |= ioparm.resv1[i]; for (i = 0; i < sizeof(ioparm.resv2); i++) accum |= ioparm.resv2[i]; if (accum != 0) { ARCH_DEP(program_interrupt) (regs, PGM_OPERAND_EXCEPTION); return 0; } /* Set return code 11 and cond code 2 if SBI count is invalid */ if (sbicount < 1 || sbicount > 500) { regs->GR_L(15) = 11; return 2; } /* Obtain the device lock */ obtain_lock (&dev->lock); #ifdef FEATURE_CHANNEL_SUBSYSTEM /* Return code 5 and condition code 1 if status pending */ if ((dev->scsw.flag3 & SCSW3_SC_PEND) || (dev->pciscsw.flag3 & SCSW3_SC_PEND)) { release_lock (&dev->lock); regs->GR_L(15) = 5; return 1; } #endif /*FEATURE_CHANNEL_SUBSYSTEM*/ /* Return code 5 and condition code 1 if device is busy */ if (dev->busy || IOPENDING(dev)) { release_lock (&dev->lock); regs->GR_L(15) = 5; return 1; } /* Set the device busy indicator */ dev->busy = 1; /* Release the device lock */ release_lock (&dev->lock); /* Process each entry in the SBILIST */ for (blkcount = 0; blkcount < sbicount; blkcount++) { /* Return code 10 and cond code 2 if SBILIST entry is outside main storage or is fetch protected. Note that the SBI address is an absolute address and is not subject to fetch-protection override or storage-protection override mechanisms, and an SBILIST entry cannot cross a page boundary */ if (sbiaddr > regs->mainlim || ((STORAGE_KEY(sbiaddr, regs) & STORKEY_FETCH) && (STORAGE_KEY(sbiaddr, regs) & STORKEY_KEY) != ioparm.akey && ioparm.akey != 0)) { regs->GR_L(15) = 10; return 2; } /* Load block number and data address from SBILIST */ blknum = ARCH_DEP(fetch_fullword_absolute)(sbiaddr, regs); absadr = ARCH_DEP(fetch_fullword_absolute)(sbiaddr+4, regs); if (dev->ccwtrace || dev->ccwstep) { logmsg ("%4.4X:Diagnose X\'0A4\':%s " "blk=%8.8X adr=%8.8X len=%8.8X\n", dev->devnum, (ioparm.type == HCPSBIOP_WRITE ? "WRITE" : "READ"), blknum, absadr, blksize); } /* Return code 12 and cond code 2 if buffer exceeds storage */ if (absadr > regs->mainlim - blksize) { regs->GR_L(15) = 12; return 2; } /* Channel protection check if access key does not match storage keys of buffer. Note that the buffer address is an absolute address, the buffer cannot span more than two pages, and the access is not subject to fetch-protection override, storage-protection override, or low-address protection */ skey1 = STORAGE_KEY(absadr, regs); skey2 = STORAGE_KEY(absadr + blksize - 1, regs); if (ioparm.akey != 0 && ( ((skey1 & STORKEY_KEY) != ioparm.akey && ((skey1 & STORKEY_FETCH) || ioparm.type == HCPSBIOP_READ)) || ((skey2 & STORKEY_KEY) != ioparm.akey && ((skey2 & STORKEY_FETCH) || ioparm.type == HCPSBIOP_READ)) )) { chanstat |= CSW_PROTC; break; } /* Call device handler to read or write one block */ fbadasd_syncblk_io (dev, ioparm.type, blknum, blksize, regs->mainstor + absadr, &unitstat, &residual); /* Set incorrect length if residual count is non-zero */ if (residual != 0) chanstat |= CSW_IL; /* Exit if any unusual status */ if (unitstat != (CSW_CE | CSW_DE) || chanstat != 0) break; /* Point to next SBILIST entry */ sbiaddr += 8; } /* end for(blkcount) */ /* Reset the device busy indicator */ dev->busy = 0; /* Store the block count in the parameter list */ ioparm.blkcount[0] = (blkcount >> 24) & 0xFF; ioparm.blkcount[1] = (blkcount >> 16) & 0xFF; ioparm.blkcount[2] = (blkcount >> 8) & 0xFF; ioparm.blkcount[3] = blkcount & 0xFF; /* Store the device and subchannel status in the parameter list */ ioparm.unitstat = unitstat; ioparm.chanstat = chanstat; /* Store the residual byte count in the parameter list */ ioparm.residual[0] = (residual >> 8) & 0xFF; ioparm.residual[1] = residual & 0xFF; /* Return sense data if unit check occurred */ if (unitstat & CSW_UC) { numsense = dev->numsense; if (numsense > sizeof(ioparm.sense)) numsense = sizeof(ioparm.sense); ioparm.sensecount[0] = (numsense >> 8) & 0xFF; ioparm.sensecount[1] = numsense & 0xFF; memcpy (ioparm.sense, dev->sense, numsense); } /* Store the updated parameter list in real storage */ ARCH_DEP(vstorec) (&ioparm, sizeof(ioparm)-1, iopaddr, USE_REAL_ADDR, regs); /* If I/O error occurred, set return code 13 and cond code 3 */ if (unitstat != (CSW_CE | CSW_DE) || chanstat != 0) { regs->GR_L(15) = 13; return 3; } /* Set return code 0 and cond code 0 */ regs->GR_L(15) = 0; return 0; } /* end function syncblk_io */ /*-------------------------------------------------------------------*/ /* Process Synchronous General I/O call (Function code 0x0A8) */ /*-------------------------------------------------------------------*/ int ARCH_DEP(syncgen_io) (int r1, int r2, REGS *regs) { U32 i; /* Array subscript */ U32 numsense; /* Number of sense bytes */ U32 iopaddr; /* Address of HCPSGIOP */ HCPSGIOP ioparm; /* I/O parameter list */ DEVBLK *dev; /* -> Device block */ U16 devnum; /* Device number */ U16 residual; /* Residual byte count */ U32 ccwaddr; /* Address of channel program*/ U32 lastccw; /* CCW address at interrupt */ BYTE accum; /* Work area */ BYTE unitstat = 0; /* Device status */ BYTE chanstat = 0; /* Subchannel status */ //FIXME: code not right for shared devices UNREFERENCED(r2); /* Register R1 contains the real address of the parameter list */ iopaddr = regs->GR_L(r1); /* Program check if parameter list not on fullword boundary */ if (iopaddr & 0x00000003) { ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION); return 0; } /* Ensure that parameter list operand is addressable */ ARCH_DEP(validate_operand) (iopaddr, USE_REAL_ADDR, sizeof(ioparm)-1, ACCTYPE_WRITE, regs); /* Fetch the parameter list from real storage */ ARCH_DEP(vfetchc) (&ioparm, sizeof(ioparm)-1, iopaddr, USE_REAL_ADDR, regs); /* Load numeric fields from the parameter list */ devnum = (ioparm.devnum[0] << 8) | ioparm.devnum[1]; ccwaddr = (ioparm.ccwaddr[0] << 24) | (ioparm.ccwaddr[1] << 16) | (ioparm.ccwaddr[2] << 8) | ioparm.ccwaddr[3]; /* Locate the device block */ dev = find_device_by_devnum (0,devnum); /* Set return code 1 and cond code 1 if device does not exist */ if (dev == NULL) { regs->GR_L(15) = 1; return 1; } /* Program check if protect key bits 4-7 are not zero or if the reserved bits in the flag byte are not zero */ if ((ioparm.akey & 0x0F) || (ioparm.flag & HCPSGIOP_FLAG_RESV)) { ARCH_DEP(program_interrupt) (regs, PGM_OPERAND_EXCEPTION); return 0; } #ifdef FEATURE_S370_CHANNEL /* Program check if flag byte specifies format-1 CCW */ if (ioparm.flag & HCPSGIOP_FORMAT1_CCW) { ARCH_DEP(program_interrupt) (regs, PGM_OPERAND_EXCEPTION); return 0; } #endif /*FEATURE_S370_CHANNEL*/ /* Program check if CCW is not on a doubleword boundary, or if CCW address exceeds maximum according to CCW format */ if ((ccwaddr & 0x00000007) || ccwaddr > ((ioparm.flag & HCPSGIOP_FORMAT1_CCW) ? (U32)0x7FFFFFFF : (U32)0x00FFFFFF)) { ARCH_DEP(program_interrupt) (regs, PGM_OPERAND_EXCEPTION); return 0; } /* Program check if reserved fields are not zero */ for (accum = 0, i = 0; i < sizeof(ioparm.resv1); i++) accum |= ioparm.resv1[i]; for (i = 0; i < sizeof(ioparm.resv2); i++) accum |= ioparm.resv2[i]; for (i = 0; i < sizeof(ioparm.resv3); i++) accum |= ioparm.resv3[i]; for (i = 0; i < sizeof(ioparm.resv4); i++) accum |= ioparm.resv4[i]; if (accum != 0) { ARCH_DEP(program_interrupt) (regs, PGM_OPERAND_EXCEPTION); return 0; } /* Obtain the interrupt lock */ obtain_lock (&dev->lock); #ifdef FEATURE_CHANNEL_SUBSYSTEM /* Return code 5 and condition code 1 if status pending */ if ((dev->scsw.flag3 & SCSW3_SC_PEND) || (dev->pciscsw.flag3 & SCSW3_SC_PEND)) { release_lock (&dev->lock); regs->GR_L(15) = 5; return 1; } #endif /*FEATURE_CHANNEL_SUBSYSTEM*/ /* Return code 5 and condition code 1 if device is busy */ if (dev->busy || IOPENDING(dev)) { release_lock (&dev->lock); regs->GR_L(15) = 5; return 1; } /* Set the device busy indicator */ dev->busy = 1; /* Release the device lock */ release_lock (&dev->lock); /* Build the operation request block */ /*@IWZ*/ memset (&dev->orb, 0, sizeof(ORB)); /*@IWZ*/ STORE_FW(dev->orb.ccwaddr, ccwaddr); /*@IWZ*/ dev->orb.flag4 = ioparm.akey & ORB4_KEY; /*@IWZ*/ if (ioparm.flag & HCPSGIOP_FORMAT1_CCW) /*@IWZ*/ dev->orb.flag5 |= ORB5_F; /*@IWZ*/ /* Execute the channel program synchronously */ ARCH_DEP(execute_ccw_chain) (dev); /* Obtain status, CCW address, and residual byte count */ #ifdef FEATURE_S370_CHANNEL lastccw = (dev->csw[1] << 16) || (dev->csw[2] << 8) || dev->csw[3]; unitstat = dev->csw[4]; chanstat = dev->csw[5]; residual = (dev->csw[6] << 8) || dev->csw[7]; #endif /*FEATURE_S370_CHANNEL*/ #ifdef FEATURE_CHANNEL_SUBSYSTEM lastccw = (dev->scsw.ccwaddr[0] << 24) || (dev->scsw.ccwaddr[1] << 16) || (dev->scsw.ccwaddr[2] << 8) || dev->scsw.ccwaddr[3]; unitstat = dev->scsw.unitstat; chanstat = dev->scsw.chanstat; residual = (dev->scsw.count[0] << 8) || dev->scsw.count[1]; #endif /*FEATURE_CHANNEL_SUBSYSTEM*/ /* Clear the interrupt pending and device busy conditions */ obtain_lock (&dev->lock); dev->busy = dev->pending = 0; dev->scsw.flag2 = 0; dev->scsw.flag3 = 0; release_lock (&dev->lock); /* Store the last CCW address in the parameter list */ ioparm.lastccw[0] = (lastccw >> 24) & 0xFF; ioparm.lastccw[1] = (lastccw >> 16) & 0xFF; ioparm.lastccw[2] = (lastccw >> 8) & 0xFF; ioparm.lastccw[3] = lastccw & 0xFF; /* Store the device and subchannel status in the parameter list */ ioparm.unitstat = unitstat; ioparm.chanstat = chanstat; /* Store the residual byte count in the parameter list */ ioparm.residual[0] = (residual >> 8) & 0xFF; ioparm.residual[1] = residual & 0xFF; /* Return sense data if unit check occurred */ if (unitstat & CSW_UC) { numsense = dev->numsense; if (numsense > sizeof(ioparm.sense)) numsense = sizeof(ioparm.sense); ioparm.sensecount[0] = (numsense >> 8) & 0xFF; ioparm.sensecount[1] = numsense & 0xFF; memcpy (ioparm.sense, dev->sense, numsense); } /* Store the updated parameter list in real storage */ ARCH_DEP(vstorec) (&ioparm, sizeof(ioparm)-1, iopaddr, USE_REAL_ADDR, regs); /* If I/O error occurred, set return code 13 and cond code 3 */ if (unitstat != (CSW_CE | CSW_DE) || chanstat != 0) { regs->GR_L(15) = 13; return 3; } /* Return with condition code 0 and register 15 unchanged */ return 0; } /* end function syncgen_io */ /*-------------------------------------------------------------------*/ /* Store Extended Identification Code (Function code 0x000) */ /*-------------------------------------------------------------------*/ void ARCH_DEP(extid_call) (int r1, int r2, REGS *regs) { int i; /* Array subscript */ int ver, rel; /* Version and release number*/ U32 idaddr; /* Address of storage operand*/ U32 idlen; /* Length of storage operand */ BYTE buf[40]; /* Extended identification */ #if defined( HAVE_GETLOGIN_R ) #if !defined(LOGIN_NAME_MAX) #define LOGIN_NAME_MAX 100 #endif char unam[LOGIN_NAME_MAX+1]; /* User name */ #endif char *puser; /* Pointer to user name */ BYTE c; /* Character work area */ /* Load storage operand address from R1 register */ idaddr = regs->GR_L(r1); /* Program check if operand is not on a doubleword boundary */ if (idaddr & 0x00000007) { ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION); return; } /* Load storage operand length from R2 register */ idlen = regs->GR_L(r2); /* Program check if operand length is invalid */ if (idlen < 1) { ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION); return; } /* Bytes 0-7 contain the system name ("HERCULES" in EBCDIC) */ get_lparname(buf); /* Bytes 8-9 contain the execution environment bits */ buf[8] = 0x00; buf[9] = 0x00; /* Byte 10 contains the system product version number */ sscanf (MSTRING(VERSION), "%d.%d", &ver, &rel); buf[10] = ver; /* Byte 11 contains version number from STIDP */ buf[11] = sysblk.cpuid >> 56; /* Bytes 12-13 contain MCEL length from STIDP */ buf[12] = (sysblk.cpuid >> 8) & 0xFF; buf[13] = sysblk.cpuid & 0xFF; /* Bytes 14-15 contain the CP address */ buf[14] = (regs->cpuad >> 8) & 0xFF; buf[15] = regs->cpuad & 0xFF; /* Bytes 16-23 contain the userid in EBCDIC */ #if defined( HAVE_GETLOGIN_R ) memset( unam, 0, sizeof(unam) ); VERIFY( getlogin_r ( unam, sizeof(unam) ) == 0 ); puser = unam; #else puser = ""; #endif for (i = 0; i < 8; i++) { c = (*puser == '\0' ? SPACE : *(puser++)); buf[16+i] = host_to_guest(toupper(c)); } /* Bytes 24-31 contain the program product bitmap */ memcpy (buf+24, "\x7F\xFE\x00\x00\x00\x00\x00\x00", 8); /* Bytes 32-35 contain the time zone differential */ memset (buf+32, '\0', 4); /* Bytes 36-39 contain version, level, and service level */ buf[36] = ver; buf[37] = rel; buf[38] = 0x00; buf[39] = 0x00; #if 0 logmsg ("Diagnose X\'000\':" "%2.2X%2.2X%2.2X%2.2X %2.2X%2.2X%2.2X%2.2X " "%2.2X%2.2X%2.2X%2.2X %2.2X%2.2X%2.2X%2.2X\n\t\t" "%2.2X%2.2X%2.2X%2.2X %2.2X%2.2X%2.2X%2.2X " "%2.2X%2.2X%2.2X%2.2X %2.2X%2.2X%2.2X%2.2X\n\t\t" "%2.2X%2.2X%2.2X%2.2X %2.2X%2.2X%2.2X%2.2X\n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7], buf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15], buf[16], buf[17], buf[18], buf[19], buf[20], buf[21], buf[22], buf[23], buf[24], buf[25], buf[26], buf[27], buf[28], buf[29], buf[30], buf[31], buf[32], buf[33], buf[34], buf[35], buf[36], buf[37], buf[38], buf[39]); #endif /* Enforce maximum length to store */ if (idlen > sizeof(buf)) idlen = sizeof(buf); /* Store the extended identification code at operand address */ ARCH_DEP(vstorec) (buf, idlen-1, idaddr, USE_REAL_ADDR, regs); /* Deduct number of bytes from the R2 register */ regs->GR_L(r2) -= idlen; } /* end function extid_call */ /*-------------------------------------------------------------------*/ /* Process CP command (Function code 0x008) */ /*-------------------------------------------------------------------*/ int ARCH_DEP(cpcmd_call) (int r1, int r2, REGS *regs) { U32 i; /* Array subscript */ U32 cc = 0; /* Condition code */ U32 cmdaddr; /* Address of command string */ U32 cmdlen; /* Length of command string */ U32 respadr; /* Address of response buffer*/ U32 maxrlen; /* Length of response buffer */ U32 resplen; /* Length of actual response */ BYTE cmdflags; /* Command flags */ #define CMDFLAGS_REJPASSW 0x80 /* Reject password in command*/ #define CMDFLAGS_RESPONSE 0x40 /* Return response in buffer */ #define CMDFLAGS_REQPASSW 0x20 /* Prompt for password */ #define CMDFLAGS_RESERVED 0x1F /* Reserved bits, must be 0 */ char bufi[256]; /* Command buffer (ASCIIZ) */ char bufo[257]; /* Command buffer (ASCIIZ) */ char resp[256]; /* Response buffer (ASCIIZ) */ char *dresp; /* Default response (ASCIIZ) */ int freeresp; /* Flag to free resp bfr */ U32 j,k; /* Obtain command address from R1 register */ cmdaddr = regs->GR_L(r1); /* Obtain command length and flags from R2 register */ cmdflags = regs->GR_L(r2) >> 24; cmdlen = regs->GR_L(r2) & 0x00FFFFFF; /* Program check if invalid flags, or if command string is too long, or if response buffer is specified and registers are consecutive or either register specifies register 15 */ if ((cmdflags & CMDFLAGS_RESERVED) || cmdlen > sizeof(bufi)-1 || ((cmdflags & CMDFLAGS_RESPONSE) && (r1 == 15 || r2 == 15 || r1 == r2 + 1 || r2 == r1 + 1))) { ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION); return 0; } /* Put machine into stopped state if command length is zero */ if (cmdlen == 0) { regs->opinterv = 0; regs->cpustate = CPUSTATE_STOPPED; ON_IC_INTERRUPT(regs); return 0; } /* Obtain the command string from storage */ ARCH_DEP(vfetchc) (bufi, cmdlen-1, cmdaddr, USE_REAL_ADDR, regs); /* Prepend '-' if noecho is requested */ i=0; if(!(sysblk.diag8cmd & DIAG8CMD_ECHO)) { bufo[0]='-'; i=1; } /* Translate EBCDIC command to ASCII */ for (j=0; j < cmdlen; i++,j++) { bufo[i] = guest_to_host(bufi[j]); } bufo[i] = '\0'; dresp=""; freeresp=0; if(*bufo) { #ifdef FEATURE_HERCULES_DIAGCALLS int shcmd = 0; { char* p = bufo; while (*p && isspace(*p)) p++; if ((*(p+0) == 's' || *(p+0) == 'S') && (*(p+1) == 'h' || *(p+1) == 'H') && isspace(*(p+2))) shcmd = 1; } if ((sysblk.diag8cmd & DIAG8CMD_ENABLE) && (!shcmd || !(sysblk.shcmdopt & (SHCMDOPT_DISABLE | SHCMDOPT_NODIAG8))) ) { if(sysblk.diag8cmd & DIAG8CMD_ECHO) logmsgp (_("HHCVM001I *%s* panel command issued by guest\n"), bufo); if (cmdflags & CMDFLAGS_RESPONSE) { dresp=log_capture(panel_command,bufo); if(dresp!=NULL) { freeresp=1; } else { dresp=""; } } else { panel_command(bufo); if(sysblk.diag8cmd & DIAG8CMD_ECHO) logmsgp (_("HHCVM002I *%s* command complete\n"), bufo); } } else { if(sysblk.diag8cmd & DIAG8CMD_ECHO) { logmsgp (_("HHCVM005W *%s* panel command issued by guest (but disabled)\n"), bufo); } dresp=_("HHCVM003I Host command processing disabled by configuration statement"); } #else dresp=_("HHCVM004E Host command processing not included in engine build"); #endif } /* Store the response and set length if response requested */ if (cmdflags & CMDFLAGS_RESPONSE) { if(!freeresp) { strlcpy (resp, dresp, sizeof(resp)); dresp=resp; } resplen = strlen(dresp); for (i = 0; i < resplen; i++) dresp[i] = host_to_guest(dresp[i]); respadr = regs->GR_L(r1+1); maxrlen = regs->GR_L(r2+1); i=(resplen<=maxrlen) ? resplen : maxrlen; j=0; while(i>0) { k=(i<255 ? i : 255); ARCH_DEP(vstorec) (&dresp[j], k-1 , respadr+j, USE_REAL_ADDR, regs); i-=k; j+=k; } regs->GR_L(r2+1) = (resplen<=maxrlen) ? resplen : resplen-maxrlen; cc = (resplen<=maxrlen) ? 0 : 1; } if(freeresp) { free(dresp); } /* Set R2 register to CP completion code */ regs->GR_L(r2) = 0; /* Return condition code */ return cc; } /* end function cpcmd_call */ /*-------------------------------------------------------------------*/ /* Access Re-IPL data (Function code 0x0B0) */ /*-------------------------------------------------------------------*/ void ARCH_DEP(access_reipl_data) (int r1, int r2, REGS *regs) { U32 bufadr; /* Real addr of data buffer */ U32 buflen; /* Length of data buffer */ /* Obtain buffer address and length from R1 and R2 registers */ bufadr = regs->GR_L(r1); buflen = regs->GR_L(r2); /* Program check if buffer length is negative */ if ((S32)buflen < 0) { ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION); return; } /* Store IPL information if buffer length is non-zero */ if (buflen > 0) { /* Store one byte of zero to indicate no IPL information */ ARCH_DEP(vstoreb) (0, bufadr, USE_REAL_ADDR, regs); } PTT(PTT_CL_ERR,"*DIAG0B0",regs->GR_L(r1),regs->GR_L(r2),regs->psw.IA_L); /* Return code 4 means no re-IPL information available */ regs->GR_L(r2) = 4; } /* end function access_reipl_data */ /*-------------------------------------------------------------------*/ /* Access Device Information (Function code 0x210) */ /*-------------------------------------------------------------------*/ /* Note: This implementation emulates z/VM 5.4 */ int ARCH_DEP(device_info) (int r1, int r2, REGS *regs) { DEVBLK *dev; /* -> Device block */ VRDCBLOK vrdc; /* VRDCBLOK */ RADR blokaddr; /* Location of the VRDCBLOK */ U16 bloklen; /* Length from the VRDCBLOK */ #if 0 /* Only required if implementation is for the z/VM 5.3 level */ U16 reserved; /* Bytes 14 and 15 */ #endif U16 devnum; /* Device number from the VRDCBLOK */ UNREFERENCED(r2); if (regs->GR_L(r1) & 0x3 #if defined(FEATURE_ESAME) || (regs->psw.amode64) #endif /* FEATURE_ESAME */ ) { ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION); } blokaddr = regs->GR_L(r1); /* Fetch the first 4 bytes of the VRDCBLOK */ ARCH_DEP(vfetchc) (&vrdc, 3, blokaddr, USE_REAL_ADDR, regs); /* Get the VRDCBLOK length from the working VRDC */ FETCH_HW(bloklen,&vrdc.vrdclen); /* VRDCBLOK length must be at least 8 bytes */ if (bloklen<8) { ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION); } /* Fetch remainder of supplied VRDCBLOK, but no more */ if (bloklen>VRDCBLOK_SIZE) bloklen=VRDCBLOK_SIZE; ARCH_DEP(vfetchc) (&vrdc.vrdcvdat,bloklen-5,blokaddr+4, USE_REAL_ADDR, regs); #if 0 /* If length is 16 or greater, bytes 14 and 15 must be zero on z/VM 5.3.0 or earlier */ if ( bloklen>=16) { FETCH_HW(reserved,&vrdc.vrdcrsvd); if (reserved != 0) { ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION); } } #endif /* Get the device number from the working VRDC */ FETCH_HW(devnum,&vrdc.vrdcdvno); /* Locate the device block and set the virtual and real device information */ dev = ARCH_DEP(vmdevice_data) (0x210,devnum,&vrdc.vrdcvdat,&vrdc.vrdcrcdt); /* Return condition code 3 if device does not exist */ if (!dev) { PTT(PTT_CL_ERR,"*DIAG210",regs->GR_L(r1),regs->GR_L(r2),regs->psw.IA_L); return 3; } /* Set the underlying device and real device features */ vrdc.vrdcundv=0x00; vrdc.vrdcrdaf=0x00; /* Create device dependent mappings */ if (vrdc.vrdcvdat.vdevcls == DC_DASD) { memcpy(&vrdc.vrdcrdc,dev->devchar,42); switch (dev->devtype) { case 0x2311: case 0x2314: case 0x2305: case 0x3330: case 0x3340: case 0x3350: /* Set non-keyed overhead */ STORE_HW(&vrdc.vrdcrdc[0x18],dev->ckdtab->f2); /* Set keyed overhead */ STORE_HW(&vrdc.vrdcrdc[0x1A],dev->ckdtab->f1); /* Note: for all other DASD devices these fields contain bytes 24-27 of the RDC */ } /* Set Control Unit ID */ vrdc.vrdcrdc[0x2A]=dev->devchar[56]; } else if (vrdc.vrdcvdat.vdevcls == DC_FBA) memcpy(&vrdc.vrdcrdc,dev->devchar,32); /* Set Path Group ID */ memcpy(&vrdc.vrdcpgid,dev->pgid,11); /* Set version */ if (bloklen>0x60) vrdc.vrdcvers=0x01; /* Set underlying real device */ if (!(vrdc.vrdcrdaf & VRDCEMRD)) memcpy(&vrdc.vrdcrdev,&vrdc.vrdcdvno,2); /* Update the VRDC in main storage */ ARCH_DEP(vstorec) (&vrdc, bloklen-1, blokaddr, USE_REAL_ADDR, regs); /* Return condition code 0 for success */ return 0; } /* end function device_info */ /*-------------------------------------------------------------------*/ /* Access Certain Virtual Machine Information (Function code 0x260) */ /*-------------------------------------------------------------------*/ /* Note: This implementation emulates z/VM 5.4 */ void ARCH_DEP(vm_info) (int r1, int r2, REGS *regs) { DEVBLK *dev; /* -> Device block */ U16 devnum; /* Device number */ #if defined(FEATURE_ESAME) RADR stgarea; /* Storage extent area */ S64 stglen; /* Storage extent area length */ #endif /* FEATURE_ESAME */ /* Ry contains the subcode */ switch(regs->GR_L(r2)) { case 0x00000000: /* Highest addressable byte */ #if defined(FEATURE_ESAME) /* Program check if running in z/Architecture mode and */ /* 64-bit addressing is being used. */ if (regs->psw.amode64) { ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION); } #endif /* FEATURE_ESAME */ regs->GR_L(r1) = regs->mainlim; /* provide highest addressable byte */ return; case 0x00000004: /* Provide BYUSER ID value */ /* Program check if Rx and Ry are the same registers or */ /* or Ry is not an even register or the address provided */ /* in Rx is not on a doubleword boundary or if running */ /* in z/Architecture mode and 64-bit addressing is being used. */ if ( r1 == r2 || r2 & 0x1 || regs->GR_L(r1) & 0x7 #if defined(FEATURE_ESAME) || (regs->psw.amode64) #endif /* FEATURE_ESAME */ ) { ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION); } regs->GR_L(r2+1)=0x4; /* Indicate no BYUSER ID for Hercules */ return; case 0x00000008: /* Return number of lines per page */ #if defined(FEATURE_ESAME) /* Program check if running in z/Architecture mode and */ /* 64-bit addressing is being used. */ if (regs->psw.amode64) { ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION); } #endif /* FEATURE_ESAME */ /* Get the device number from the Rx register */ devnum=regs->GR_LHL(r1); /* Locate the device block */ dev = find_device_by_devnum(0,devnum); /* Set 0 lines per page for a valid printer or console (meaning SPOOL is OFF) */ if (dev != NULL && (dev->devtype == 0x1403 || dev->devtype == 0x3211 || dev->devtype == 0x1052 || dev->devtype == 0x3215 ) ) { regs->GR_L(r1) = 0; /* Set zero lines per page */ regs->GR_L(r2) = 0; /* Set return code to indicate a valid device */ } else { regs->GR_L(r2) = 4; /* Set return code to indicate an invalid device */ } return; #if defined(FEATURE_ESAME) case 0x0000000C: /* Return highest addressable byte for z/Architecture machine */ regs->GR_G(r1) = regs->mainlim; regs->GR_G(r2) = regs->mainlim; return; case 0x00000010: /* Set storage extent */ /* Obtain the storage extent area real address from Rx */ /* and its length from Rx+1 */ stgarea=regs->GR_G(r1); stglen=regs->GR_G(r1+1); /* Length is treated as a signed value */ /* Program check if Rx is not an even register or the address */ /* provided in Rx is not on a quadword boundary or the length */ /* provided in Rx+1 is not positive or not a multiple of 16 */ if ( r1 & 1 || stgarea & 0xF || stglen <= 0 || stglen & 0xF ) { ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION); } /* Convert real addres to absolute address */ stgarea=APPLY_PREFIXING(stgarea,regs->PX ); /* Check to ensure extent information can be stored */ if (stgarea > regs->mainlim - 16) { regs->program_interrupt (regs, PGM_ADDRESSING_EXCEPTION); } /* Set start of storage extent to zero */ ARCH_DEP(store_doubleword_absolute)(0,stgarea,regs); /* Set end of storage extent to last addressable byte of main storage */ ARCH_DEP(store_doubleword_absolute)(regs->mainlim,stgarea+8,regs); /* Set number of extents to 1 in Ry */ regs->GR_G(r2) = 1; /* Indicate all extents returned */ regs->psw.cc = 0; return; #endif /* FEATURE_ESAME */ default: /* Invalid subcode */ ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION); } } /*-------------------------------------------------------------------*/ /* Pseudo Timer Extended (Function code 0x270) */ /* Pseudo Timer (Function code 0x00C) */ /*-------------------------------------------------------------------*/ void ARCH_DEP(pseudo_timer) (U32 code, int r1, int r2, REGS *regs) { int i; /* Array subscript */ time_t timeval; /* Current time */ struct tm *tmptr; /* -> Current time structure */ U32 bufadr; /* Real addr of data buffer */ U32 buflen; /* Length of data buffer */ char buf[64]; /* Response buffer */ BYTE dattim[64]; /* Date and time (EBCDIC) */ #define DIAG_DATEFMT_SHORT 0x80 /* Date format mm/dd/yy */ #define DIAG_DATEFMT_FULL 0x40 /* Date format mm/dd/yyyy */ #define DIAG_DATEFMT_ISO 0x20 /* Date format yyyy-mm-dd */ #define DIAG_DATEFMT_SYSDFLT 0x10 /* System-wide default format*/ static char timefmt[]="%m/%d/%y%H:%M:%S%m/%d/%Y%Y-%m-%d"; /* Get the current date and time in EBCDIC */ timeval = time(NULL); tmptr = localtime(&timeval); strftime((char *)dattim, sizeof(dattim), timefmt, tmptr); for (i = 0; dattim[i] != '\0'; i++) dattim[i] = host_to_guest(dattim[i]); /* Obtain buffer address and length from R1 and R2 registers */ bufadr = regs->GR_L(r1); buflen = regs->GR_L(r2); /* Use length 32 if R2 is zero or function code is 00C */ if (r2 == 0 || code == 0x00C) buflen = 32; /* Program check if R1 and R2 specify the same non-zero register number, or if buffer length is less than or equal to zero, or if buffer address is zero, or if buffer is not on a doubleword boundary */ if ((r2 != 0 && r2 == r1) || (S32)buflen <= 0 || bufadr == 0 || (bufadr & 0x00000007)) { ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION); return; } /* Build the response buffer */ memset (buf, 0x00, sizeof(buf)); /* Bytes 0-7 contain the date as EBCDIC MM/DD/YY */ memcpy (buf, dattim, 8); /* Bytes 8-15 contain the time as EBCDIC HH:MM:SS */ memcpy (buf+8, dattim+8, 8); /* Bytes 16-23 contain the virtual CPU time used in microseconds */ /* Bytes 24-31 contain the total CPU time used in microseconds */ /* Bytes 32-41 contain the date as EBCDIC MM/DD/YYYY */ memcpy (buf+32, dattim+16, 10); /* Bytes 42-47 contain binary zeroes */ /* Bytes 48-57 contain the date as EBCDIC YYYY-MM-DD */ memcpy (buf+48, dattim+26, 10); /* Byte 58 contains the diagnose 270 version code */ buf[58] = 0x01; /* Byte 59 contains the user's default date format */ buf[59] = DIAG_DATEFMT_ISO; /* Byte 60 contains the system default date format */ buf[60] = DIAG_DATEFMT_ISO; /* Bytes 61-63 contain binary zeroes */ #if 0 logmsg ("Diagnose X\'%3.3X\':" "%2.2X%2.2X%2.2X%2.2X %2.2X%2.2X%2.2X%2.2X " "%2.2X%2.2X%2.2X%2.2X %2.2X%2.2X%2.2X%2.2X\n\t\t" "%2.2X%2.2X%2.2X%2.2X %2.2X%2.2X%2.2X%2.2X " "%2.2X%2.2X%2.2X%2.2X %2.2X%2.2X%2.2X%2.2X\n\t\t" "%2.2X%2.2X%2.2X%2.2X %2.2X%2.2X%2.2X%2.2X " "%2.2X%2.2X%2.2X%2.2X %2.2X%2.2X%2.2X%2.2X\n\t\t" "%2.2X%2.2X%2.2X%2.2X %2.2X%2.2X%2.2X%2.2X " "%2.2X%2.2X%2.2X%2.2X %2.2X%2.2X%2.2X%2.2X\n", code, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7], buf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15], buf[16], buf[17], buf[18], buf[19], buf[20], buf[21], buf[22], buf[23], buf[24], buf[25], buf[26], buf[27], buf[28], buf[29], buf[30], buf[31], buf[32], buf[33], buf[34], buf[35], buf[36], buf[37], buf[38], buf[39], buf[40], buf[41], buf[42], buf[43], buf[44], buf[45], buf[46], buf[47], buf[48], buf[49], buf[50], buf[51], buf[52], buf[53], buf[54], buf[55], buf[56], buf[57], buf[58], buf[59], buf[60], buf[61], buf[63], buf[63]); #endif /* Enforce maximum length to store */ if (buflen > sizeof(buf)) buflen = sizeof(buf); /* Store the response buffer at the operand location */ ARCH_DEP(vstorec) (buf, buflen-1, bufadr, USE_REAL_ADDR, regs); } /* end function pseudo_timer */ /*-------------------------------------------------------------------*/ /* Pending Page Release (Function code 0x214) */ /*-------------------------------------------------------------------*/ int ARCH_DEP(diag_ppagerel) (int r1, int r2, REGS *regs) { U32 abs, start, end; /* Absolute frame addresses */ BYTE skey; /* Specified storage key */ BYTE func; /* Function code... */ #define DIAG214_EPR 0x00 /* Establish pending release */ #define DIAG214_CPR 0x01 /* Cancel pending release */ #define DIAG214_CAPR 0x02 /* Cancel all pending release*/ #define DIAG214_CPRV 0x03 /* Cancel and validate */ /* Program check if R1 is not an even-numbered register */ if (r1 & 1) { ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION); return 0; } /* Extract the function code from R1+1 register bits 24-31 */ func = regs->GR_L(r1+1) & 0xFF; /* Extract the start/end addresses from R1 and R1+1 registers */ start = regs->GR_L(r1) & STORAGE_KEY_PAGEMASK; end = regs->GR_L(r1+1) & STORAGE_KEY_PAGEMASK; /* Validate start/end addresses if function is not CAPR */ if (func != DIAG214_CAPR && (start > end || end > regs->mainlim)) { ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION); return 0; } /* Process depending on function code */ switch (func) { case DIAG214_EPR: /* Establish Pending Release */ break; case DIAG214_CPR: /* Cancel Pending Release */ case DIAG214_CPRV: /* Cancel Pending Release and Validate */ /* Do not set storage keys if R2 is register 0 */ if (r2 == 0) break; /* Obtain key from R2 register bits 24-28 */ skey = regs->GR_L(r2) & (STORKEY_KEY | STORKEY_FETCH); /* Set storage key for each frame within specified range */ for (abs = start; abs <= end; abs += STORAGE_KEY_PAGESIZE) { STORAGE_KEY(abs, regs) &= ~(STORKEY_KEY | STORKEY_FETCH); STORAGE_KEY(abs, regs) |= skey; } /* end for(abs) */ break; case DIAG214_CAPR: /* Cancel All Pending Releases */ break; default: /* Invalid function code */ ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION); return 0; } /* end switch(func) */ /* Return condition code zero */ return 0; } /* end function diag_ppagerel */ /*-------------------------------------------------------------------*/ /* B2F0 IUCV - Inter User Communications Vehicle [S] */ /*-------------------------------------------------------------------*/ DEF_INST(inter_user_communication_vehicle) { int b2; /* Effective addr base */ VADR effective_addr2; /* Effective address */ S(inst, regs, b2, effective_addr2); #if defined(FEATURE_ECPSVM) if(ecpsvm_doiucv(regs,b2,effective_addr2)==0) { return; } #endif /* Program check if in problem state, the IUCV instruction generates an operation exception rather then a priviliged operation exception when executed in problem state *JJ */ if ( PROBSTATE(®s->psw) ) ARCH_DEP(program_interrupt) (regs, PGM_OPERATION_EXCEPTION); SIE_INTERCEPT(regs); if( HDC3(debug_iucv, b2, effective_addr2, regs) ) return; PTT(PTT_CL_ERR,"*IUCV",b2,effective_addr2,regs->psw.IA_L); /* Set condition code to indicate IUCV not available */ regs->psw.cc = 3; } #endif /*FEATURE_EMULATE_VM*/ #if !defined(_GEN_ARCH) #if defined(_ARCHMODE2) #define _GEN_ARCH _ARCHMODE2 #include "vm.c" #endif #if defined(_ARCHMODE3) #undef _GEN_ARCH #define _GEN_ARCH _ARCHMODE3 #include "vm.c" #endif #endif /*!defined(_GEN_ARCH)*/ hercules-3.07/vmd250.c000644 000765 000765 00000246527 11301535254 016143 0ustar00jmaynardjmaynard000000 000000 /* VMD250.C (c) Copyright Harold Grovesteen, 2009 */ /* z/VM 5.4 DIAGNOSE code X'250' */ /*-------------------------------------------------------------------*/ /* This module implements DIAGNOSE code X'250' */ /* described in SC24-6084 z/VM 5.4 CP Programming Services. */ /*-------------------------------------------------------------------*/ /* Hercules extends the use to System/370 with 4K pages and 2K pages */ /* with recommended constraints */ // $Id: vmd250.c 5470 2009-10-04 10:40:58Z hsg001 $ /* Unconditional log messages generated */ /* HHCVM006E - Could not allocate storage for Block I/O environment */ /* HHCVM009E - Invalid list processor status code returned */ /* HHCVM010E - Error creating asynchronous thread */ /* HHCVM011E - Could not allocate storage for asynchronous I/O request*/ /* Conditional log messages when device tracing is enabled */ /* HHCVM007I - BLKTAB information used when device tracing is enabled */ /* HHCVM008I - Established environment when device tracing is enabled */ /* HHCVM012I - Block I/O owns device */ /* HHCVM013I - Block I/O returned device */ /* HHCVM014I - BIOE status returned */ /* HHCVM015I - List processor parameters */ /* HHCVM016I - BIOE operation being performed */ /* HHCVM017I - List processor status code */ /* HHCVM018I - Read/Write I/O operation */ /* HHCVM019I - Syncronous or asynchronous request information */ /* HHCVM020I - Address checking results */ /* HHCVM021I - Device driver results */ /* HHCVM022I - Block I/O environment removed */ /* HHCVM023I - Triggered Block I/O interrupt */ /* The following structure exists between the different functions */ /* */ /* From diagnose.c */ /* */ /* AD:vm_blockio */ /* | */ /* INIT: */ /* +---> d250_init32---+ */ /* | +---> d250_init */ /* +---> d250_init64---+ */ /* | */ /* IOREQ: */ /* +-> AD:d250_iorq32--+---SYNC----> d250_list32--+ */ /* | V ^ | */ /* | ASYNC Thread | | d250_read */ /* | +-> AD:d250_async32-+ +--> d250_write */ /* | d250_bio_interrupt | (calls */ /* | | drivers) */ /* +-> AD:d250_iorq64--+----SYNC---> d250_list64--+ */ /* | V ^ */ /* | ASYNC Thread | */ /* | +-> AD:d250_async64-+ */ /* | d250_bio_interrupt */ /* REMOVE: */ /* +---> d250_remove */ /* */ /* Function ARCH_DEP On CPU On Async Owns */ /* thread thread device */ /* */ /* vm_blockio Yes Yes No No */ /* d250_init32/64 No Yes No No */ /* d250_init No Yes No No */ /* d250_iorq32/64 Yes Yes No No */ /* d250_async32/64 Yes No Yes No */ /* d250_list32/64 Yes Yes Yes Yes */ /* d250_bio_interrup No No Yes N/A */ /* d250_read No Yes Yes Yes */ /* d250_write No Yes Yes Yes */ /* d250_remove No Yes No No */ /* d250_addrck Yes Yes Yes No */ #include "hstdinc.h" #if !defined(_HENGINE_DLL_) #define _HENGINE_DLL_ #endif /*_HENGINE_DLL_*/ #if !defined(_VMD250_C_) #define _VMD250_C_ #endif /* !defined(_VMD250_C_) */ #include "hercules.h" #include "opcode.h" #include "inline.h" #include "vmd250.h" #if defined(FEATURE_VM_BLOCKIO) #if !defined(_VMD250_C) #define _VMD250_C #if !defined(_VMD250_H) #define _VMD250_H /*-------------------------------------------------------------------*/ /* Internal macro definitions */ /*-------------------------------------------------------------------*/ /*-------------------------------------------------------------------*/ /* Block I/O Function, Condition and Return Codes */ /*-------------------------------------------------------------------*/ /* Function Codes (Ry) */ #define INIT 0x00 /* Initialize Block I/O environment */ #define IOREQ 0x01 /* Perform I/O request */ #define REMOVE 0x02 /* Remove the Block I/O environment */ /* Condition Codes (cc) */ #define CC_SUCCESS 0 /* Function completed successfully */ #define CC_PARTIAL 1 /* Function partially completed */ #define CC_FAILED 2 /* Function failed */ /* Note: cc 3 is not returned by Block I/O */ /* General Return Codes (Rx+1)- All functions */ #define RC_SUCCESS 0 /* Function competed successfully */ #define RC_NODEV 16 /* Device not defined */ #define RC_STATERR 28 /* Env. state error */ #define RC_ERROR 255 /* Irrecoverable error */ /* Note: RC_ERROR is used to indicate an internal Hercules error */ /* and it should be accompanied by a log message */ /* INIT Return Codes (Rx+1) */ #define RC_READONLY 4 /* Successful for R/O device */ #define RC_NOSUPP 20 /* Not a supported DASD device */ #define RC_BADBLKSZ 24 /* Unsupported block size */ /* IOREQ Return Codes (Rx+1) */ #define RC_ASYNC 8 /* Asynchronous request initiated */ #define RC_SYN_PART 12 /* Synchronous request partially successful */ #define RC_CNT_ERR 36 /* Block count not between 1 and 256 */ #define RC_ALL_BAD 40 /* All blocks unsuccessful */ #define RC_REM_PART 44 /* Remove aborted request - should not occur */ #define RC_EXI_PART 48 /* Exigent aborted req. - should not occur */ /* Note: Because the DEVBLK lock is held RC_REM_PART and RC_EXI_PART */ /* should not occur in Hercules */ /*-------------------------------------------------------------------*/ /* Block I/O Parameter List Formats (BIOPL) */ /*-------------------------------------------------------------------*/ #define INIT32R1_LEN 21 #define INIT32R2_LEN 24 typedef struct _BIOPL_INIT32 { HWORD devnum; /* Device number */ BYTE flaga; /* Addressing mode flag */ BYTE resv1[INIT32R1_LEN]; /* reserved - must be zeros */ FWORD blksize; /* Block size */ FWORD offset; /* Physical block 1 offset */ FWORD startblk; /* First physical block number */ FWORD endblk; /* Last physical block number */ BYTE resv2[INIT32R2_LEN]; /* reserved - must be zeros */ } BIOPL_INIT32; #define INIT64R1_LEN 21 #define INIT64R2_LEN 4 #define INIT64R3_LEN 8 typedef struct _BIOPL_INIT64 { HWORD devnum; /* Device number */ BYTE flaga; /* Addressing mode flag */ BYTE resv1[INIT64R1_LEN]; /* reserved - must be zeros */ FWORD blksize; /* Block size */ BYTE resv2[INIT64R2_LEN]; /* Physical block 1 offset */ DBLWRD offset; /* Physical block 1 offset */ DBLWRD startblk; /* First physical block number */ DBLWRD endblk; /* Last physical block number */ BYTE resv3[INIT64R3_LEN]; /* reserved - must be zeros */ } BIOPL_INIT64; #define IORQ32R1_LEN 21 #define IORQ32R2_LEN 2 #define IORQ32R3_LEN 20 typedef struct _BIOPL_IORQ32 { HWORD devnum; /* Device number */ BYTE flaga; /* Addressing mode flag */ BYTE resv1[IORQ32R1_LEN]; /* reserved - must be zeros */ BYTE key; /* Storage key */ BYTE flags; /* I/O request flags */ BYTE resv2[IORQ32R2_LEN]; /* reserved - must be zeros */ FWORD blkcount; /* Block count of request */ FWORD bioealet; /* BIOE list ALET */ FWORD bioeladr; /* BIOE list address */ FWORD intparm; /* Interrupt parameter */ BYTE resv3[IORQ32R3_LEN]; /* reserved - must be zeros */ } BIOPL_IORQ32; #define IORQ64R1_LEN 21 #define IORQ64R2_LEN 2 #define IORQ64R3_LEN 4 #define IORQ64R4_LEN 8 typedef struct _BIOPL_IORQ64 { HWORD devnum; /* Device number */ BYTE flaga; /* Addressing mode flag */ BYTE resv1[IORQ64R1_LEN]; /* reserved - must be zeros */ BYTE key; /* Storage key */ BYTE flags; /* I/O request flags */ BYTE resv2[IORQ64R2_LEN]; /* reserved - must be zeros */ FWORD blkcount; /* Block count of request */ FWORD bioealet; /* BIOE list ALET */ BYTE resv3[IORQ64R3_LEN]; /* reserved - must be zeros */ DBLWRD intparm; /* Interrupt parameter */ DBLWRD bioeladr; /* BIOE list address */ BYTE resv4[IORQ64R4_LEN]; /* reserved - must be zeros */ } BIOPL_IORQ64; #define REMOVER1_LEN 62 typedef struct _BIOPL_REMOVE { HWORD devnum; /* Device number */ BYTE resv1[REMOVER1_LEN]; /* reserved - must be zeros */ } BIOPL_REMOVE; typedef struct _BIOPL { HWORD devnum; /* Device number */ BYTE flaga; /* Addressing mode flag */ BYTE resv1[61]; /* Additional Parameters */ } BIOPL; /* BIOPL flaga field related values */ #define BIOPL_FLAGARSV 0x7F /* Reserved bits must be zero */ #define BIOPL_FLAGAMSK 0x80 /* Addressing flag */ #define BIOPL_32BIT 0x00 /* 32-bit BIOPL/BIOE Formats */ #define BIOPL_64BIT 0x80 /* 64-bit BIOPL/BIOE Formats */ /* BIOPL flags field related values */ #define BIOPL_FLAGSRSV 0xFC /* Reserved bits must be zero */ #define BIOPL_ASYNC 0x02 /* Asynchronous request */ #define BIOPL_CACHE 0x01 /* Not used - z/VM specific */ /* BIOPL key field values */ #define BIOPL_KEYRSV 0x0F /* Reserved bits must be zero */ /*-------------------------------------------------------------------*/ /* Block I/O Entry Formats (BIOE) */ /*-------------------------------------------------------------------*/ typedef struct _BIOE32 { BYTE type; /* Type of I/O request */ BYTE status; /* Status of I/O request */ BYTE resv1[2]; /* reserved - must be zeros */ FWORD blknum; /* Requested block number */ FWORD bufalet; /* Data buffer ALET */ FWORD bufaddr; /* Data buffer absolute address */ } BIOE32; typedef struct _BIOE64 { BYTE type; /* Type of I/O request */ BYTE status; /* Status of I/O request */ BYTE resv1[2]; /* reserved - must be zeros */ FWORD bufalet; /* Data buffer ALET */ DBLWRD blknum; /* Requested block number */ DBLWRD bufaddr; /* Data buffer absolute address */ } BIOE64; /* BIOE type field values */ #define BIOE_WRITE 0x01 /* Write block request type */ #define BIOE_READ 0x02 /* Read block request type */ /* BIOE status field values */ #define BIOE_SUCCESS 0x00 /* Request successful */ #define BIOE_BADBLOCK 0x01 /* Invalid block specified */ #define BIOE_ADDREXC 0x02 /* Data buffer address exception */ #define BIOE_DASDRO 0x03 /* Write request to read-only device */ #define BIOE_CKDRECL 0x04 /* CKD record size not block size */ #define BIOE_IOERROR 0x05 /* I/O error on device */ #define BIOE_BADREQ 0x06 /* Request type invalid */ #define BIOE_PROTEXC 0x07 /* A protection exception occurred */ #define BIOE_ADRCAP 0x08 /* Not used - z/VM specific */ #define BIOE_ALENEXC 0x09 /* Not used - z/VM specific */ #define BIOE_ALETEXC 0x0A /* Not used - z/VM specific */ #define BIOE_NOTZERO 0x0B /* Reserved fields not zero */ #define BIOE_ABORTED 0x0C /* Request aborted */ /*-------------------------------------------------------------------*/ /* I/O Request Control Structures and Flags */ /*-------------------------------------------------------------------*/ #if 0 #define ADDR32 0 /* 32-bit addressing fields being used */ #define ADDR64 1 /* 64-bit addressing fields being used */ #endif #define SYNC 0 /* Synchronous request being processed */ #define ASYNC 1 /* Asynchronous request being processed */ /* Synchronous or asynchronous processing status codes */ #define PSC_SUCCESS 0x00 /* Successful processing */ #define PSC_PARTIAL 0x01 /* Partial success */ #define PSC_STGERR 0x02 /* Error on storage of BIOE */ #define PSC_REMOVED 0x03 /* Block I/O environment removed */ /* Structure passed to the asynchronous thread */ typedef struct _IOCTL32 { /* Hercules structures involved in the request */ REGS *regs; /* CPU register structure */ DEVBLK *dev; /* Device block */ /* External interrupt related values */ BYTE subintcod; /* Sub-interruption code */ BYTE statuscod; /* Interruption status code */ U32 intrparm; /* 32-bit interrupt parm */ /* List control structure */ S32 blkcount; /* Block count */ U32 listaddr; /* BIOE list address */ BYTE key; /* Storage Key */ int goodblks; /* Number of successful I/O's */ int badblks; /* Number of unsuccessful I/O's */ } IOCTL32; /* Structure passed to the asynchronous thread */ typedef struct _IOCTL64 { /* Hercules structures involved in the request */ REGS *regs; /* CPU register structure */ DEVBLK *dev; /* Device block */ /* External interrupt related values related values */ BYTE subintcod; /* Sub-interruption code */ BYTE statuscod; /* Interruption status code */ U64 intrparm; /* 64-bit interrupt parm */ /* List control structure */ S64 blkcount; /* Block count */ U64 listaddr; /* BIOE list address */ BYTE key; /* Storage Key */ int goodblks; /* Number of successful I/O's */ int badblks; /* Number of unsuccessful I/O's */ } IOCTL64; #endif /* !defined(_VMD250_H) */ /*-------------------------------------------------------------------*/ /* Internal Architecture Independent Function Prototypes */ /*-------------------------------------------------------------------*/ /* Initialization Functions */ int d250_init32(DEVBLK *, int *, BIOPL_INIT32 *, REGS *); int d250_init64(DEVBLK *, int *, BIOPL_INIT64 *, REGS *); struct VMBIOENV* d250_init(DEVBLK *, U32, S64, int *, int *); /* Input/Output Request Functions */ void d250_preserve(DEVBLK *); void d250_restore(DEVBLK *); int d250_read(DEVBLK *, S64, S32, void *); int d250_write(DEVBLK *, S64, S32, void *); /* Note: some I/O request functions are architecture dependent */ /* Removal Function */ int d250_remove(DEVBLK *, int *, BIOPL_REMOVE *, REGS *); /* Asynchronous Interrupt Generation */ void d250_bio_interrupt(DEVBLK *, U64 intparm, BYTE status, BYTE code); /*-------------------------------------------------------------------*/ /* Trigger Block I/O External Interrupt */ /*-------------------------------------------------------------------*/ void d250_bio_interrupt(DEVBLK *dev, U64 intparm, BYTE status, BYTE subcode) { OBTAIN_INTLOCK(NULL); /* This is inspired by sclp_attn_thread function in service.c */ /* Make sure a service signal interrupt is not pending */ while(IS_IC_SERVSIG) { RELEASE_INTLOCK(NULL); sched_yield(); OBTAIN_INTLOCK(NULL); } /* Can now safely store my interrupt information */ sysblk.bioparm = intparm; /* Trigger with the interrupt parameter */ sysblk.biostat = status; /* Trigger with the status */ sysblk.biosubcd = subcode; /* Trigger with the subcode */ sysblk.biodev = dev; /* Trigger for this device */ sysblk.servcode = EXT_BLOCKIO_INTERRUPT; /* The Block I/O external interrupt is enabled by the same CR0 bit */ /* as are service signal interrupts. This means the guest will */ /* be interrupted when it has enabled service signals. For this */ /* reason the Block I/O is being treated like a service signal and */ /* handled by the service signal handling logic in external.c */ /* Make the "service signal" interrupt pending */ ON_IC_SERVSIG; /* Wake up any waiters */ WAKEUP_CPUS_MASK (sysblk.waiting_mask); if (dev->ccwtrace) { logmsg (_("%4.4X:HHCVM023I Triggered Block I/O interrupt: " "code=%4.4X parm=%16.16X status=%2.2X subcode=%2.2X\n"), sysblk.biodev->devnum, sysblk.servcode, sysblk.bioparm, sysblk.biostat, sysblk.biosubcd ); } /* Free the interrupt lock */ RELEASE_INTLOCK(NULL); } /*-------------------------------------------------------------------*/ /* Initialize Environment - 32-bit Addressing */ /*-------------------------------------------------------------------*/ int d250_init32(DEVBLK *dev, int *diag_rc, BIOPL_INIT32 *biopl, REGS *regs) { BIOPL_INIT32 bioplx00; /* Use to check reserved fields */ /* Passed to the generic INIT function */ U32 blksize; /* Blocksize */ S32 offset; /* Offset */ /* Returned by generic INIT function */ struct VMBIOENV *bioenv; /* -->allocated environement */ int rc; /* return code */ int cc; /* Condition code to return */ /* Clear the reserved BIOPL */ memset(&bioplx00,0x00,sizeof(BIOPL_INIT32)); /* Make sure reserved fields are binary zeros */ if ((memcmp(&biopl->resv1,&bioplx00,INIT32R1_LEN)!=0) || (memcmp(&biopl->resv2,&bioplx00,INIT32R2_LEN)!=0)) { ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION); } /* Fetch the block size from the BIOPL */ FETCH_FW(blksize,&biopl->blksize); /* Fetch the offset from the BIOPL provided by the guest */ FETCH_FW(offset,&biopl->offset); /* Call the addressing independent initialization function */ bioenv=d250_init(dev, blksize, (S64)offset, &cc, &rc); if (bioenv) { /* Save the values in the BIOPL for return to guest */ STORE_FW(&biopl->startblk,(U32)bioenv->begblk); STORE_FW(&biopl->endblk,(U32)bioenv->endblk); if (dev->ccwtrace) { logmsg ("%4.4X:HHCVM008I d250_init32 s=%i,o=%i,b=%i,e=%i\n", dev->devnum, blksize, offset, bioenv->begblk, bioenv->endblk ); } } *diag_rc = rc; return cc; } /* end function d250_init32 */ /*-------------------------------------------------------------------*/ /* Initialize Environment - 64-bit Addressing */ /*-------------------------------------------------------------------*/ int d250_init64(DEVBLK *dev, int *diag_rc, BIOPL_INIT64 *biopl, REGS *regs) { BIOPL_INIT64 bioplx00; /* Use to check reserved fields */ /* Passed to the generic INIT function */ U32 blksize; /* Blocksize */ S64 offset; /* Offset */ /* Returned by generic INIT function */ struct VMBIOENV *bioenv; /* -->allocated environement */ int rc; /* return code */ int cc; /* condition code */ /* Clear the reserved BIOPL */ memset(&bioplx00,0x00,sizeof(BIOPL_INIT64)); /* Make sure reserved fields are binary zeros */ if ((memcmp(&biopl->resv1,&bioplx00,INIT64R1_LEN)!=0) || (memcmp(&biopl->resv2,&bioplx00,INIT64R2_LEN)!=0) || (memcmp(&biopl->resv3,&bioplx00,INIT64R3_LEN)!=0)) { ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION); } /* Fetch the block size from the BIOPL */ FETCH_FW(blksize,&biopl->blksize); /* Fetch the offset from the BIOPL provided by the guest */ FETCH_DW(offset,&biopl->offset); bioenv=d250_init(dev, blksize, offset, &cc, &rc); if (bioenv) { /* Save the values in the BIOPL for return to guest */ STORE_DW(&biopl->startblk,bioenv->begblk); STORE_DW(&biopl->endblk,bioenv->endblk); if (dev->ccwtrace) { logmsg ("%4.4X:HHCVM008I d250_init64 s=%i,o=%lli,b=%lli,e=%lli\n", dev->devnum, blksize, offset, bioenv->begblk, bioenv->endblk ); } } *diag_rc = rc; return cc; } /* end function d250_init64 */ /*-------------------------------------------------------------------*/ /* Initialize Environment - Addressing Independent */ /*-------------------------------------------------------------------*/ struct VMBIOENV* d250_init(DEVBLK *dev, U32 blksize, S64 offset, int *cc, int *rc ) { int isCKD; /* Flag for CKD device */ int isRO; /* Flag for readonly device */ int seccyl;/* Number of sectors/block or records/track for dev. */ int numblks; /* Number of blocks on the device */ S32 begblk; /* Starting block number */ S32 endblk; /* Ending block number */ BLKTAB *blktab; /* Pointer to device std block-to-physical info */ /* Established environement */ struct VMBIOENV *bioenv; /* -->allocated environement */ /* Return with an error if the device does not exist */ if (!dev) { *rc = RC_NODEV; /* Set the return code for no device */ *cc = CC_FAILED; /* Indicate the function failed */ return 0; } /* Look up the block-to-phyical mapping information */ blktab=dasd_lookup(DASD_STDBLK,NULL,(U32)dev->devtype,0); if (!blktab) { *rc = RC_NOSUPP; /* Set the return code for unsuppored device */ *cc = CC_FAILED; /* Indicate the function failed */ return NULL; } if (dev->ccwtrace) { logmsg (_("%4.4X:HHCVM007I d250_init BLKTAB: " "type=%4.4X arch=%i,512=%i,1024=%i,2048=%i,4096=%i\n"), dev->devnum, blktab->devt, blktab->darch, blktab->phys512, blktab->phys1024, blktab->phys2048, blktab->phys4096 ); } /* Save the device architecture */ isCKD = blktab->darch; /* Determine if the blocksize is valid and its physical/block value */ switch(blksize) { case 4096: seccyl=blktab->phys4096; break; case 512: seccyl=blktab->phys512; break; case 1024: seccyl=blktab->phys1024; break; case 2048: seccyl=blktab->phys2048; break; default: *rc = RC_BADBLKSZ; *cc = CC_FAILED; return NULL; } isRO = 0; /* Assume device is read-write */ if (isCKD) { /* Number of standard blocks is based upon number of primary */ /* cylinders */ numblks=(dev->ckdtab->cyls * dev->ckdtab->heads * seccyl); if (dev->ckdrdonly) { isRO = 1; } } else { numblks=(dev->fbanumblk*dev->fbablksiz)/blksize; /* FBA devices are never read only */ } /* Establish the environment's beginning and ending block numbers */ /* Block numbers in the environment are relative to 1, not zero */ begblk=1-offset; endblk=numblks-offset; if (!(bioenv=(struct VMBIOENV *)malloc(sizeof(struct VMBIOENV)))) { logmsg (_("HHCVM006E VM BLOCK I/O environment malloc failed\n")); *rc = RC_ERROR; /* Indicate an irrecoverable error occurred */ *cc = CC_FAILED; return NULL; } /* Set the fields in the environment structure */ bioenv->dev = dev ; /* Set device block pointer */ bioenv->blksiz = blksize ; /* Pass the block size */ bioenv->offset = offset ; /* Pass the offset */ bioenv->begblk = begblk ; /* Save the starting block */ bioenv->endblk = endblk ; /* Save the ending block */ bioenv->isCKD = isCKD ; /* Save the device type */ bioenv->isRO = isRO ; /* Save the read/write status */ bioenv->blkphys = seccyl ; /* Save the block-to-phys mapping */ /* Attach the environment to the DEVBLK */ /* Lock the DEVBLK in case another thread wants it */ obtain_lock (&dev->lock); if (dev->vmd250env == NULL) { /* If an environment does not exist, establish it */ dev->vmd250env = bioenv ; /* No need to hold the device lock now, environment is set */ release_lock (&dev->lock); /* Set the appropriate successful return and condition codes */ if (isRO) { *rc = RC_READONLY ; /* Set READ ONLY success return code */ } else { *rc = RC_SUCCESS ; /* Set the READ/WRITE success return code */ } *cc = CC_SUCCESS ; /* Set that the function has succeeded */ } else { /* If an environment already exists, this is an error: */ /* 1. Release the device block */ /* 2. free the environment just built */ /* 3. Reset the retuned environment to NULL and */ /* 4. Reset return and condition codes to reflect */ /* the error condition */ release_lock (&dev->lock); free(bioenv); bioenv = NULL ; *rc = RC_STATERR; *cc = CC_FAILED; } /* Return the bioenv so that the start and end blocks can */ /* be returned to the guest in the addressing mode specific */ /* BIOPL format */ return bioenv ; } /* end function d250_init */ /*-------------------------------------------------------------------*/ /* Preserve Device Status */ /*-------------------------------------------------------------------*/ /* WARNING: This function must NOT be called with the device lock held */ /* From the perspective of Hercules, Block I/O is occurring at the */ /* level of the device, NOT the channel or channel subsystem. For */ /* the channel subsytem or other CPU's, the device is made to */ /* appear busy and reserved if shared. */ /* */ /* It is possible for block I/O to take control between the */ /* completion of a CCW chain and the presentation by the device of */ /* related sense information. The device related sense information*/ /* is therefore stored in the Block I/O environment and restored */ /* upon completion. This also allows the device drivers to set */ /* sense information during Block I/O operations, which they do. */ /* A pointer is used by the device drivers for unit status, so */ /* this can be redirected to a Block I/O location. */ /* */ /* A cleaner but more intrusive change would be to have the */ /* the drivers use a pointer for where sense is stored rather than */ /* assume the device block. This is deferred for a possible future*/ /* enhancement. */ void d250_preserve(DEVBLK *dev) { /* Note: this logic comes from the beginning of */ /* channel.c ARCH_DEP(execute_ccw_chain) */ obtain_lock(&dev->lock); if ( dev->shared ) { while (dev->ioactive != DEV_SYS_NONE && dev->ioactive != DEV_SYS_LOCAL) { dev->iowaiters++; wait_condition(&dev->iocond, &dev->lock); dev->iowaiters--; } dev->ioactive = DEV_SYS_LOCAL; } else { dev->ioactive = DEV_SYS_LOCAL; } dev->busy = 1; dev->startpending = 0; if (dev->sns_pending) { /* Save the pending sense */ memcpy(&dev->vmd250env->sense,&dev->sense,sizeof(dev->sense)); if (dev->ccwtrace) { logmsg(_("%4.4X:HHCVM012I d250_preserve pending sense preserved\n"), dev->devnum); } } /* Both fbadasd.c and ckddasd.c set the local reserved flag before */ /* calling the shared device client */ dev->reserved = 1; if (dev->hnd->reserve) { release_lock(&dev->lock); (dev->hnd->reserve)(dev); } else { release_lock(&dev->lock); } } /*-------------------------------------------------------------------*/ /* Restore Device Status */ /*-------------------------------------------------------------------*/ /* WARNING: This function MUST not be called with the device lock held */ void d250_restore(DEVBLK *dev) { obtain_lock(&dev->lock); if (dev->hnd->release) { release_lock(&dev->lock); (dev->hnd->release)(dev); obtain_lock(&dev->lock); } /* Both fbadasd.c and ckddasd.c reset the local reserved flag */ /* after calling the shared device client */ dev->reserved = 0; if (dev->sns_pending) { /* Restore the pending sense */ memcpy(&dev->sense,&dev->vmd250env->sense,sizeof(dev->sense)); if (dev->ccwtrace) { logmsg (_("%4.4X:HHCVM013I d250_restore pending sense restored\n"), dev->devnum); } } dev->ioactive = DEV_SYS_NONE; dev->busy = 0; release_lock(&dev->lock); } /*-------------------------------------------------------------------*/ /* Environment Remove - Any Addressing */ /*-------------------------------------------------------------------*/ int d250_remove(DEVBLK *dev, int *rc, BIOPL_REMOVE * biopl, REGS *regs) { BIOPL_REMOVE bioplx00; /* Use to check reserved fields */ struct VMBIOENV *bioenv; /* -->allocated environement */ int cc; /* Condition code to return */ /* Clear the reserved BIOPL */ memset(&bioplx00,0x00,sizeof(BIOPL_REMOVE)); /* Make sure reserved fields are binary zeros */ if (memcmp(&biopl->resv1,&bioplx00,REMOVER1_LEN)!=0) { ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION); } /* Return with an error if the device does not exist */ if (!dev) { *rc = RC_NODEV; /* Set the return code for no device */ return CC_FAILED; /* Indicate the function failed */ } /* Attach the environment to the DEVBLK */ /* Lock the DEVBLK in case another CPU is trying something */ obtain_lock (&dev->lock); bioenv=dev->vmd250env; if (dev->vmd250env == NULL) { /* If an environment does not exist, it should be */ /* Return the environment state error return code */ /* and failed condition code */ release_lock (&dev->lock); *rc = RC_STATERR; cc = CC_FAILED; } else { /* 1. Restore pending sense, if any */ /* 2. Free the environment previously established */ /* 3. Set the device environment pointer to NULL, */ /* telling others that the environment doesn't exist */ /* 4. Release the device block */ /* 5. Free the environment previously established */ /* 6. Return successful return and condition codes */ if (dev->sns_pending) { memcpy(&dev->sense,dev->vmd250env->sense,sizeof(dev->sense)); } dev->vmd250env = NULL ; /* No need to hold the device lock while freeing the environment */ release_lock (&dev->lock); free(bioenv); if (dev->ccwtrace) { logmsg(_("%4.4X:HHCVM022I d250_remove Block I/O environment removed\n"), dev->devnum); } *rc = RC_SUCCESS; cc = CC_SUCCESS ; /* Set that the function has succeeded */ } return cc ; } /* end function d250_remove */ /*-------------------------------------------------------------------*/ /* Device Independent Read Block */ /*-------------------------------------------------------------------*/ int d250_read(DEVBLK *dev, S64 pblknum, S32 blksize, void *buffer) { BYTE unitstat; /* Device unit status */ U16 residual; /* Residual byte count */ /* Note: Not called with device lock held */ obtain_lock(&dev->lock); if (dev->ccwtrace) { logmsg(_("%4.4X:HHCVM018I d250_read %d-byte block (rel. to 0): %d\n"), dev->devnum, blksize, pblknum); } if (dev->vmd250env->isCKD) { release_lock(&dev->lock); /* Do CKD I/O */ /* CKD to be supplied */ return BIOE_IOERROR; } else { /* Do FBA I/O */ /* Call the I/O start exit */ if (dev->hnd->start) (dev->hnd->start) (dev); unitstat = 0; /* Call the FBA driver's read standard block routine */ fbadasd_read_block(dev, (int)pblknum, (int)blksize, dev->vmd250env->blkphys, buffer, &unitstat, &residual ); if (dev->ccwtrace) { logmsg(_("%4.4X:HHCVM021I d250_read " "FBA unit status=%2.2X residual=%d\n"), dev->devnum, unitstat, residual ); } /* Call the I/O end exit */ if (dev->hnd->end) (dev->hnd->end) (dev); release_lock(&dev->lock); } /* If an I/O error occurred, return status of I/O Error */ if ( unitstat != ( CSW_CE | CSW_DE ) ) { return BIOE_IOERROR; } /* If there was a residual count, block size error, return status of 2 */ /* Note: This can only happen for CKD devices */ if ( residual != 0 ) { return BIOE_CKDRECL; } /* Success! return 0 status */ return BIOE_SUCCESS; } /*-------------------------------------------------------------------*/ /* Device Independent Write Block */ /*-------------------------------------------------------------------*/ int d250_write(DEVBLK *dev, S64 pblknum, S32 blksize, void *buffer) { BYTE unitstat; /* Device unit status */ U16 residual; /* Residual byte count */ obtain_lock(&dev->lock); if (dev->ccwtrace) { logmsg(_("%4.4X:HHCVM018I d250_write %d-byte block (rel. to 0): %d\n"), dev->devnum, blksize, pblknum); } if (!dev->vmd250env) { release_lock(&dev->lock); return BIOE_ABORTED; } if (dev->vmd250env->isCKD) { release_lock(&dev->lock); /* Do CKD I/O */ /* CKD to be supplied */ return BIOE_IOERROR; } else { /* Do FBA I/O */ /* Call the I/O start exit */ if (dev->hnd->start) (dev->hnd->start) (dev); unitstat = 0; /* Call the FBA driver's write standard block routine */ fbadasd_write_block(dev, (int)pblknum, (int)blksize, dev->vmd250env->blkphys, buffer, &unitstat, &residual ); if (dev->ccwtrace) { logmsg(_("%4.4X:HHCVM021I d250_write " "FBA unit status=%2.2X residual=%d\n"), dev->devnum, unitstat, residual ); } /* Call the I/O end exit */ if (dev->hnd->end) (dev->hnd->end) (dev); release_lock(&dev->lock); } /* If an I/O error occurred, return status of 1 */ if ( unitstat != ( CSW_CE | CSW_DE ) ) { return BIOE_IOERROR; } /* If there was a residual count, block size error, return status of 2 */ /* Note: This can only happen for CKD devices */ if ( residual != 0 ) { return BIOE_CKDRECL; } /* Success! */ return BIOE_SUCCESS; } #endif /*!defined(_VMD250_C)*/ /*-------------------------------------------------------------------*/ /* Internal Architecture Dependent Function Prototypes */ /*-------------------------------------------------------------------*/ /* Input/Output Request Functions */ int ARCH_DEP(d250_iorq32)(DEVBLK *, int *, BIOPL_IORQ32 *, REGS *); int ARCH_DEP(d250_list32)(IOCTL32 *, int); U16 ARCH_DEP(d250_addrck)(RADR, RADR, int, BYTE, REGS *); #if defined(FEATURE_ESAME) int ARCH_DEP(d250_iorq64)(DEVBLK *, int *, BIOPL_IORQ64 *, REGS *); /* void *ARCH_DEP(d250_async64)(void *); */ int ARCH_DEP(d250_list64)(IOCTL64 *, int); #endif /* defined(FEATURE_ESAME) */ /*-------------------------------------------------------------------*/ /* Process Standard Block I/O (Function code 0x250) */ /*-------------------------------------------------------------------*/ int ARCH_DEP(vm_blockio) (int r1, int r2, REGS *regs) { /* Guest related paramters and values */ RADR biopaddr; /* BIOPL address */ union parmlist{ /* BIOPL formats that */ BIOPL biopl; /* May be supplied by the */ BIOPL_INIT32 init32; /* guest */ BIOPL_IORQ32 iorq32; BIOPL_REMOVE remove; #if defined(FEATURE_ESAME) BIOPL_INIT64 init64; BIOPL_IORQ64 iorq64; #endif /* defined(FEATURE_ESAME) */ }; union parmlist bioplin; /* BIOPL from/to guest */ U16 devnum; /* Device number */ DEVBLK *dev; /* --> Device block */ int rc; /* return code in Rx+1 */ int cc; /* condition code */ rc = RC_ERROR; /* Initialize the return code to error */ cc = CC_FAILED; /* Failure assumed unless otherwise successful */ #if 0 if (sizeof(BIOPL) != 64) { logmsg("BIOPL size not 64: %d\n",sizeof(BIOPL)); } if (sizeof(BIOPL_INIT32) != 64) { logmsg("BIOPL_INIT32 size not 64: %d\n",sizeof(BIOPL_INIT32)); } if (sizeof(BIOPL_INIT64) != 64) { logmsg("BIOPL_INIT64 size not 64: %d\n",sizeof(BIOPL_INIT64)); } if (sizeof(BIOPL_IORQ32) != 64) { logmsg("BIOPL_IORQ32 size not 64: %d\n",sizeof(BIOPL_IORQ32)); } if (sizeof(BIOPL_REMOVE) != 64) { logmsg("BIOPL_REMOVE size not 64: %d\n",sizeof(BIOPL_REMOVE)); } if (sizeof(BIOPL_IORQ64) != 64) { logmsg("BIOPL_IORQ64 size not 64: %d\n",sizeof(BIOPL_IORQ64)); } if (sizeof(BIOE32) != 16) { logmsg("BIOE32 size not 16: %d\n",sizeof(BIOE32)); } if (sizeof(BIOE64) != 24) { logmsg("BIOE64 size not 24: %d\n",sizeof(BIOE64)); } #endif /* Retrieve the BIOPL address from R1 */ biopaddr = regs->GR(r1); /* Specification exception if the BIOPL is not on a doubleword boundary */ if (biopaddr & 0x00000007) { ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION); } /* Fetch the BIOPL from guest storage */ ARCH_DEP(wfetchc) (&bioplin, sizeof(bioplin)-1, biopaddr, USE_REAL_ADDR, regs); /* Access the targeted device number from the BIOPL*/ FETCH_HW(devnum,&bioplin.biopl.devnum); /* Locate the device by the number */ dev = find_device_by_devnum (0,devnum); /* Device not found will be checked by the called function */ switch(regs->GR_L(r2)) { /*--------------------------------------------------------*/ /* Initialize the Block I/O Device Environment */ /*--------------------------------------------------------*/ case INIT: #if !defined(FEATURE_ESAME) /* 64-bit formats not supported for S/370 or ESA/390 */ /* and bits 1-7 must be zero */ if (bioplin.biopl.flaga != 0x00) { ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION); } /* Call the 32-bit addressing function */ cc = d250_init32(dev,&rc,&bioplin.init32,regs); #else /* Bits 1-7 must be zero for z/Architecture */ if (bioplin.biopl.flaga & BIOPL_FLAGARSV) { ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION); } /* Call the addressing sensitive function */ if (bioplin.biopl.flaga & BIOPL_FLAGAMSK) { cc = d250_init64(dev,&rc,&bioplin.init64,regs); } else { cc = d250_init32(dev,&rc,&bioplin.init32,regs); } #endif /* !FEATURE_ESAME */ break; /*--------------------------------------------------------*/ /* Perform block I/O read/write requests to the device */ /*--------------------------------------------------------*/ case IOREQ: #if !defined(FEATURE_ESAME) /* 64-bit formats not supported for S/370 or ESA/390 */ /* and bits 1-7 must be zero */ if (bioplin.biopl.flaga != 0x00) { ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION); } cc = ARCH_DEP(d250_iorq32)(dev,&rc,&bioplin.iorq32,regs); #else /* Bits 1-7 must be zero for z/Architecture */ if (bioplin.biopl.flaga & BIOPL_FLAGARSV) { ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION); } if (bioplin.biopl.flaga & BIOPL_FLAGAMSK) { cc = ARCH_DEP(d250_iorq64)(dev,&rc,&bioplin.iorq64,regs); } else { cc = ARCH_DEP(d250_iorq32)(dev,&rc,&bioplin.iorq32,regs); } #endif /* !FEATURE_ESAME */ break; /*--------------------------------------------------------*/ /* Remove the Block I/O Device Environment */ /*--------------------------------------------------------*/ case REMOVE: cc = d250_remove(dev,&rc,&bioplin.remove,regs); break; default: ARCH_DEP(program_interrupt)(regs, PGM_SPECIFICATION_EXCEPTION); } /* end switch(regs->GR_L(r2)) */ /* Update the BIOPL in main storage */ ARCH_DEP(wstorec) (&bioplin, sizeof(bioplin)-1, biopaddr, USE_REAL_ADDR, regs); /* Set the return code in Rx+1 */ regs->GR_L((r1+1)&0xF) = rc; /* Return the condition code */ return cc; } /* end function vm_blockio */ /*-------------------------------------------------------------------*/ /* Asynchronous Input/Outut 32-bit Driver Thread */ /*-------------------------------------------------------------------*/ static void *ARCH_DEP(d250_async32)(void *ctl) { IOCTL32 *ioctl; /* 32-bit IO request controls */ BYTE psc; /* List processing status code */ /* Fetch the IO request control structure */ ioctl=(IOCTL32 *)ctl; /* Call the 32-bit BIOE request processor on this async thread*/ psc=ARCH_DEP(d250_list32)(ioctl, ASYNC); /* Trigger the external interrupt here */ d250_bio_interrupt(ioctl->dev, ioctl->intrparm, psc, 0x03); free(ioctl); return NULL; } /* end function ARCH_DEP(d250_async32) */ /*-------------------------------------------------------------------*/ /* Input/Output Request - 32-bit Addressing */ /*-------------------------------------------------------------------*/ int ARCH_DEP(d250_iorq32)(DEVBLK *dev, int *rc, BIOPL_IORQ32 *biopl, REGS *regs) { BIOPL_IORQ32 bioplx00; /* Used to check reserved fields */ IOCTL32 ioctl; /* Request information */ BYTE psc; /* List processing status code */ /* Asynchronous request related fields */ TID tid; /* Asynchronous thread ID */ char tname[32]; /* Thread name */ IOCTL32 *asyncp; /* Pointer to async thread's storage */ /* Clear the reserved BIOPL */ memset(&bioplx00,0x00,sizeof(BIOPL_IORQ32)); /* Make sure reserved fields and bits are binary zeros */ if ((memcmp(&biopl->resv1,&bioplx00,IORQ32R1_LEN)!=0) || (memcmp(&biopl->resv2,&bioplx00,IORQ32R2_LEN)!=0) || (memcmp(&biopl->resv3,&bioplx00,IORQ32R3_LEN)!=0) || (biopl->flags & BIOPL_FLAGSRSV) || (biopl->key & BIOPL_KEYRSV) ) { ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION); } /* Return with an error return code if the device does not exist */ if (!dev) { *rc = RC_NODEV; /* Set the return code for no device */ return CC_FAILED; /* Indicate the function failed */ } /* If no environment, return with an error */ if (!(dev->vmd250env)) { *rc = RC_STATERR; return CC_FAILED; } /* Fetch the block count from the BIOPL */ FETCH_FW(ioctl.blkcount,&biopl->blkcount); /* Block count must be between 1 and 256, inclusive */ if ((ioctl.blkcount<1) || (ioctl.blkcount>256)) { *rc = RC_CNT_ERR; return CC_FAILED; } /* Fetch the address of the BIO entry list from the BIOPL */ FETCH_FW(ioctl.listaddr,&biopl->bioeladr); /* Extract the storage key from the BIOPL */ ioctl.key=biopl->key; /* Set the structures that are involved in this request */ ioctl.dev = dev; ioctl.regs = regs; /* Set I/O success/failure counts to zero */ ioctl.goodblks = 0; ioctl.badblks = 0; if (biopl->flags & BIOPL_ASYNC) { /* Build the request structure */ /* Extract the 32-bit interrupt parameter from the BIOPL */ FETCH_FW(ioctl.intrparm,biopl->intparm); if (dev->ccwtrace) { logmsg(_("%4.4X:HHCVM019I ASYNC BIOEL=%8.8X, " "Entries=%d, Key=%2.2X, Intp=%8.8X\n"), dev->devnum, ioctl.listaddr, ioctl.blkcount, ioctl.key, ioctl.intrparm); } /* Set the default status code to an aborted list */ /* Note: This should be set correctly from the returned PSC */ ioctl.statuscod = PSC_STGERR; /* Get the storage for the thread's parameters */ if (!(asyncp=(IOCTL32 *)malloc(sizeof(IOCTL32)))) { logmsg (_("HHCVM011E VM BLOCK I/O request malloc failed\n")); *rc = RC_ERROR; return CC_FAILED; } /* Copy the thread's parameters to its own storage */ memcpy(asyncp,&ioctl,sizeof(IOCTL32)); /* Launch the asynchronous request on a separate thread */ snprintf(tname,sizeof(tname),"d250_async %4.4X",dev->devnum); tname[sizeof(tname)-1]=0; if ( create_thread (&tid, DETACHED, ARCH_DEP(d250_async32), asyncp, tname) ) { logmsg (_("%4.4X:HHCVM010E Block I/O create_thread error: %s"), dev->devnum, strerror(errno)); release_lock (&dev->lock); *rc = RC_ERROR; return CC_FAILED; } /* Launched the async request successfully */ *rc = RC_ASYNC; return CC_SUCCESS; } else { /* Perform the I/O request synchronously on this thread */ /* Call the 32-bit BIOE request processor */ if (dev->ccwtrace) { logmsg(_("%4.4X:HHCVM019I d250_iorq32 SYNC BIOEL=%8.8X, " "Entries=%d, Key=%2.2X\n"), dev->devnum, ioctl.listaddr, ioctl.blkcount, ioctl.key); } psc=ARCH_DEP(d250_list32)(&ioctl, SYNC); if (dev->ccwtrace) { logmsg(_("%4.4X:HHCVM017I d250_iorq32 " "PSC=%d, succeeded=%d, failed=%d\n"), dev->devnum,psc,ioctl.goodblks,ioctl.badblks); } } /* Processor status used to determine return and condition codes */ switch(psc) { case PSC_SUCCESS: *rc = RC_SUCCESS; return CC_SUCCESS; case PSC_PARTIAL: if (ioctl.goodblks == 0) { *rc = RC_ALL_BAD; return CC_FAILED; } else { *rc = RC_SYN_PART; return CC_PARTIAL; } case PSC_REMOVED: *rc = RC_REM_PART; return CC_PARTIAL; default: logmsg (_("HHCVM009E d250_list32 error: PSC=%i\n"), psc); *rc = RC_ERROR; return CC_FAILED; } } /* end function ARCH_DEP(d250_iorq32) */ /* BIOE Address and Status Handling (32-bit and 64-bit formats) */ /* */ /* The entire BIOE is fetched from storage, but only the status */ /* field will be updated. BIOE addresses and block addresses are */ /* handled the same. Only key protection and addressing */ /* exceptions are recognized for these absolute addresses. */ /* Architecture will determine the maximum address allowed not the */ /* addressing mode specified in the PSW. An addressing exception */ /* will be recognized if a BIOE extends beyond the architecture */ /* maximum address. */ /* */ /* Setting of reference bit in a storage key is based upon */ /* inline.h ARCH_DEP(fetch_xxx_absolute) functions */ /* Setting of changed bit in a storage key is based upon */ /* inline.h ARCH_DEP(store_xxx_absolute) functions */ /*-------------------------------------------------------------------*/ /* Input/Outut 32-bit List Processor - Sychronicity Independent */ /*-------------------------------------------------------------------*/ int ARCH_DEP(d250_list32)(IOCTL32* ioctl, int async) /* WARNING: Device Block lock must be released before returning */ { BIOE32 bioe; /* 32-bit BIOE fetched from absolute storage */ RADR bioebeg; /* Starting address of the BIOE */ RADR bioeend; /* Address of last byte of BIOE */ U16 xcode; /* Detected exception condition */ int blocks; /* Number of blocks being processed */ int block; /* counter used in block I/O loop */ S32 blknum; /* Block number of the request */ BYTE status; /* Returned BIOE status */ /* Passed to generic block I/O function */ int physblk; /* Physical block number */ RADR bufbeg; /* Address where the read/write will occur */ RADR bufend; /* Last byte read or written */ xcode = 0; /* Initialize the address check exception code */ /* Preserve pending sense if any and establish my ownership */ /* of the device by reserving it if shared and locking it */ if (ioctl->dev->ccwtrace) { logmsg ("%4.4X:HHCVM015I d250_list32 BIOE's=%i A:" F_RADR " I/O key=%2.2X\n", ioctl->dev->devnum, ioctl->blkcount, ioctl->listaddr, ioctl->key ); } /* Take ownership of the device */ d250_preserve(ioctl->dev); /* Note: the DEVBLK is now locked */ if (!ioctl->dev->vmd250env) { d250_restore(ioctl->dev); /* Note: the device lock is now released */ return PSC_REMOVED; } blocks=(int)ioctl->blkcount; bioebeg=ioctl->listaddr & AMASK31 ; /* Process each of the BIOE's supplied by the BIOPL count field */ for ( block = 0 ; block < blocks ; block++ ) { status = 0xFF; /* Set undefined status */ bioeend=( bioebeg + sizeof(BIOE32) - 1 ) & AMASK31; xcode=ARCH_DEP(d250_addrck) (bioebeg,bioeend,ACCTYPE_READ,ioctl->key,ioctl->regs); if (ioctl->dev->ccwtrace) { logmsg(_("%4.4X:HHCVM020I d250_list32 xcode=%4.4X " "BIOE32=%8.8X-%8.8X FETCH key=%2.2X\n"), ioctl->dev->devnum,xcode,bioebeg,bioeend,ioctl->key); } if ( xcode ) { break; } /* Fetch the BIOE from storage */ memcpy(&bioe,ioctl->regs->mainstor+bioebeg,sizeof(BIOE32)); STORAGE_KEY(bioebeg, ioctl->regs) |= (STORKEY_REF); STORAGE_KEY(bioeend, ioctl->regs) |= (STORKEY_REF); /* Process a single BIOE */ do { /* Make sure reserved field is zeros */ if ( bioe.resv1[0]!=0x00 || bioe.resv1[1]!=0x00 ) { status=BIOE_NOTZERO; continue; } /* Fetch and validate block number */ FETCH_FW(blknum,&bioe.blknum); if ( (blknum < ioctl->dev->vmd250env->begblk) || (blknum > ioctl->dev->vmd250env->endblk) ) { status=BIOE_BADBLOCK; continue; } /* Fetch the storage address used for I/O */ FETCH_FW(bufbeg,&bioe.bufaddr); bufbeg &= AMASK31; /* Ensure the environment still exists */ if (!ioctl->dev->vmd250env) { d250_restore(ioctl->dev); /* Note: the device lock is now released */ status=BIOE_ABORTED; return PSC_REMOVED; } /* The I/O handler routines are normally called without the */ /* device lock being held. The device is reserved by the */ /* busy status. */ /* Determine the last byte of the I/O buffer */ bufend=( bufbeg + ioctl->dev->vmd250env->blksiz -1 ) & AMASK31 ; if (ioctl->dev->ccwtrace) { logmsg (_("%4.4X:HHCVM016I d250_list32 BIOE %8.8X" ", oper=%2.2X, block=%i" ", buffer=%8.8X\n"), ioctl->dev->devnum, bioebeg, bioe.type, blknum, bufbeg ); } /* Determine the physical block on the device relative to zero */ physblk=(S64)blknum+ioctl->dev->vmd250env->offset-1; /* The read/write routines will convert this to a physical disk */ /* location for reading or writing */ if (bioe.type == BIOE_READ) { xcode=ARCH_DEP(d250_addrck) (bufbeg,bufend,ACCTYPE_READ,ioctl->key,ioctl->regs); if (ioctl->dev->ccwtrace) { logmsg(_("%4.4X:HHCVM020I d250_list32 xcode=%4.4X " "Rd Buf=%8.8X-%8.8X FETCH key=%2.2X\n"), ioctl->dev->devnum,xcode,bufbeg,bufend,ioctl->key); } switch ( xcode ) { case PGM_ADDRESSING_EXCEPTION: status=BIOE_ADDREXC; continue; case PGM_PROTECTION_EXCEPTION: status=BIOE_PROTEXC; continue; } /* At this point, the block number has been validated */ /* and the buffer is addressable and accessible */ status=d250_read(ioctl->dev, physblk, ioctl->dev->vmd250env->blksiz, ioctl->regs->mainstor+bufbeg); /* Set I/O storage key references if successful */ if (!status) { STORAGE_KEY(bufbeg, ioctl->regs) |= (STORKEY_REF); STORAGE_KEY(bufend, ioctl->regs) |= (STORKEY_REF); #if defined(FEATURE_2K_STORAGE_KEYS) if ( ioctl->dev->vmd250env->blksiz == 4096 ) { STORAGE_KEY(bufbeg+2048, ioctl->regs) |= (STORKEY_REF); } #endif } continue; } /* end of BIOE_READ */ else { if (bioe.type == BIOE_WRITE) { xcode=ARCH_DEP(d250_addrck) (bufbeg,bufend,ACCTYPE_WRITE,ioctl->key,ioctl->regs); if (ioctl->dev->ccwtrace) { logmsg(_("%4.4X:HHCVM020I d250_list32 xcode=%4.4X " "Wr Buf=%8.8X-%8.8X STORE key=%2.2X\n"), ioctl->dev->devnum, xcode,bufbeg, bufend, ioctl->key); } switch ( xcode ) { case PGM_ADDRESSING_EXCEPTION: status=BIOE_ADDREXC; continue; case PGM_PROTECTION_EXCEPTION: status=BIOE_PROTEXC; continue; } if (ioctl->dev->vmd250env->isRO) { status=BIOE_DASDRO; continue; } status=d250_write(ioctl->dev, physblk, ioctl->dev->vmd250env->blksiz, ioctl->regs->mainstor+bufbeg); /* Set I/O storage key references if good I/O */ if (!status) { STORAGE_KEY(bufbeg, ioctl->regs) |= (STORKEY_REF | STORKEY_CHANGE); STORAGE_KEY(bufend, ioctl->regs) |= (STORKEY_REF | STORKEY_CHANGE); #if defined(FEATURE_2K_STORAGE_KEYS) if ( ioctl->dev->vmd250env->blksiz == 4096 ) { STORAGE_KEY(bufbeg+2048, ioctl->regs) |= (STORKEY_REF | STORKEY_CHANGE); } #endif } continue; } /* end of if BIOE_WRITE */ else { status=BIOE_BADREQ; continue; } /* end of else BIOE_WRITE */ } /* end of else BIOE_READ */ }while(0); /* end of do */ /* Determine if we can store the status in the BIOE */ xcode=ARCH_DEP(d250_addrck) (bioebeg+1,bioebeg+1,ACCTYPE_WRITE,ioctl->key,ioctl->regs); if (ioctl->dev->ccwtrace) { logmsg(_("%4.4X:HHCVM020I d250_list32 xcode=%4.4X " "Status=%8.8X-%8.8X STORE key=%2.2X\n"), ioctl->dev->devnum,xcode,bioebeg+1,bioebeg+1,ioctl->key); } /* If the status byte is store protected, give up on processing any */ /* more BIOE's. Leave the BIOE list process for loop */ if ( xcode ) { break; } /* Store the status in the BIOE */ memcpy(ioctl->regs->mainstor+bioebeg+1,&status,1); /* Set the storage key change bit */ STORAGE_KEY(bioebeg+1, ioctl->regs) |= (STORKEY_REF | STORKEY_CHANGE); if (ioctl->dev->ccwtrace) { logmsg (_("%4.4X:HHCVM014I d250_list32 BIOE=%8.8X status=%2.2X\n"), ioctl->dev->devnum,bioebeg,status); } /* Count if this BIOE was a success or failure */ if ( status ) { ioctl->badblks+=1; if ( status == BIOE_ABORTED ) { break; } } else { ioctl->goodblks+=1; } /* Determine the address of the next BIOE */ bioebeg += sizeof(BIOE32); bioebeg &= AMASK31; } /* end of for loop */ #if 0 logmsg(_("(d250_list32) BIOE's processed: %d\n"),block); #endif /* Restore device to guest ownership */ d250_restore(ioctl->dev); /* Note: device lock not held */ /* If an access exception occurred: */ /* If this is a synchronous request, generate a program exception */ /* or if this is asynchrnous, just return with a storage error */ if ( xcode ) { if (async) return PSC_STGERR; else ARCH_DEP(program_interrupt)(ioctl->regs, xcode); } if ( status == BIOE_ABORTED ) { return PSC_REMOVED; } /* Determine if we were completely successful or only partially */ /* successful. 'Partial' includes none successful. */ /* Synchronous and asynchronous requests handle all failed */ /* differently. The good and bad blocks field are used by the */ /* caller */ if (ioctl->goodblks < blocks) { return PSC_PARTIAL; } return PSC_SUCCESS; } /* end function d250_list32 */ /*-------------------------------------------------------------------*/ /* Absolue Address Checking without Reference and Change Recording */ /*-------------------------------------------------------------------*/ U16 ARCH_DEP(d250_addrck) (RADR beg, RADR end, int acctype, BYTE key, REGS *regs) /* Note: inline.h and vstore.c functions are not used because they */ /* will generate program exceptions automatically. DIAGNOSE X'250' in */ /* the asynchronous case, must not do that, but rather reflect the */ /* error in the interrupt status code or BIOE status field. So this */ /* function only detects and reports the error. */ /* The caller must decide whether to generate a program interrupt or */ /* just report the encountered error without a program interruption */ /* and must set the reference and change bit as appropriate */ { BYTE sk1; /* Storage key of first byte of area */ BYTE sk2; /* Storage key of last byte of area */ #if defined(FEATURE_2K_STORAGE_KEYS) BYTE skmid; /* Storage key of middle byte of area */ #endif /* defined(FEATURE_2K_STORAGE_KEYS) */ if ( (end > regs->mainlim) || (end > MAXADDRESS) || end < beg ) { return PGM_ADDRESSING_EXCEPTION; } /* Note this logic is inspired by */ /* inline.h ARCH_DEP(is_fetch_protected) */ /* inline.h ARCH_DEP(is_store_protected) */ if (key == 0) { return 0; } sk1=STORAGE_KEY(beg,regs); sk2=STORAGE_KEY(end,regs); #if defined(FEATURE_2K_STORAGE_KEYS) if ( ( end - beg ) > 2048 ) { skmid=STORAGE_KEY(beg + 2048,regs); } else { skmid = sk2; } #endif /* defined(FEATURE_2K_STORAGE_KEYS) */ if (acctype == ACCTYPE_READ) { /* Check for fetch protection */ if ( ((sk1 & STORKEY_FETCH) && (key != (sk1 & STORKEY_KEY))) ||((sk2 & STORKEY_FETCH) && (key != (sk2 & STORKEY_KEY))) #if defined(FEATURE_2K_STORAGE_KEYS) ||((skmid & STORKEY_FETCH) && (key != (skmid & STORKEY_KEY))) #endif /* defined(FEATURE_2K_STORAGE_KEYS) */ ) { return PGM_PROTECTION_EXCEPTION; } } else /* assume ACCTYPE_WRITE */ { /* Check for store protection */ if ( (key != (sk1 & STORKEY_KEY)) ||(key != (sk2 & STORKEY_KEY)) #if defined(FEATURE_2K_STORAGE_KEYS) ||(key != (skmid & STORKEY_KEY)) #endif /* defined(FEATURE_2K_STORAGE_KEYS) */ ) { return PGM_PROTECTION_EXCEPTION; } } return 0; } /* end of function ARCH_DEP(d250_addrck) */ #if defined(FEATURE_ESAME) /*-------------------------------------------------------------------*/ /* Asynchronous Input/Output 64-bit Driver Thread */ /*-------------------------------------------------------------------*/ void ARCH_DEP(d250_async64)(void *ctl) { IOCTL64 *ioctl; /* 64-bit IO request controls */ BYTE psc; /* List processing status code */ /* Fetch the IO request control structure */ ioctl=(IOCTL64 *)ctl; /* Call the 32-bit BIOE request processor on this async thread*/ psc=ARCH_DEP(d250_list64)(ioctl, ASYNC); d250_bio_interrupt(ioctl->dev, ioctl->intrparm, psc, 0x07); free(ioctl); } /* end function ARCH_DEP(d250_async64) */ /*-------------------------------------------------------------------*/ /* Input/Output Request - 64-bit Addressing */ /*-------------------------------------------------------------------*/ int ARCH_DEP(d250_iorq64)(DEVBLK *dev, int *rc, BIOPL_IORQ64 *biopl, REGS *regs) { BIOPL_IORQ64 bioplx00; /* Used to check reserved fields */ IOCTL64 ioctl; /* Request information */ BYTE psc; /* List processing status code */ /* Asynchronous request related fields */ TID tid; /* Asynchronous thread ID */ char tname[32]; /* Thread name */ IOCTL64 *asyncp; /* Pointer to async thread's free standing storage */ #if 0 logmsg("(d250_iorq64) Entered\n"); #endif /* Clear the reserved BIOPL */ memset(&bioplx00,0x00,sizeof(BIOPL_IORQ64)); /* Make sure reserved fields are binary zeros */ if ((memcmp(&biopl->resv1,&bioplx00,IORQ64R1_LEN)!=0) || (memcmp(&biopl->resv2,&bioplx00,IORQ64R2_LEN)!=0) || (memcmp(&biopl->resv3,&bioplx00,IORQ64R3_LEN)!=0) || (memcmp(&biopl->resv4,&bioplx00,IORQ64R4_LEN)!=0) || (biopl->flags & BIOPL_FLAGSRSV) || (biopl->key & BIOPL_KEYRSV) ) { ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION); } /* Return with an error return code if the device does not exist */ if (!dev) { *rc = RC_NODEV; /* Set the return code for no device */ return CC_FAILED; /* Indicate the function failed */ } /* If no environment, return with an error */ if (!dev->vmd250env) { *rc = RC_STATERR; return CC_FAILED; } /* Fetch the block count from the BIOPL */ FETCH_FW(ioctl.blkcount,&biopl->blkcount); #if 0 logmsg("(d250_iorq64) ioctl.blkcount=%d,\n", ioctl.blkcount); #endif /* Block count must be between 1 and 256, inclusive */ if ((ioctl.blkcount<1) || (ioctl.blkcount>256)) { *rc = RC_CNT_ERR; return CC_FAILED; } /* Fetch the address of the BIO entry list from the BIOPL */ FETCH_DW(ioctl.listaddr,&biopl->bioeladr); #if 0 logmsg (_("(d250_iorq64) ioctl.listaddr=%16.16X,\n"), ioctl.listaddr); #endif /* Extract the storage key from the BIOPL */ ioctl.key=biopl->key; /* Set the structures that are involved in this request */ ioctl.dev = dev; ioctl.regs = regs; /* Set I/O success/failure counts to zero */ ioctl.goodblks = 0; ioctl.badblks = 0; /* Determine if request is an asynchronous or synchronous */ if (biopl->flags & BIOPL_ASYNC) { /* Build the request structure */ /* Extract the 64-bit interrupt parameter from the BIOPL */ FETCH_DW(ioctl.intrparm,&biopl->intparm); if (dev->ccwtrace) { logmsg(_("%4.4X:HHCVM019I ASYNC BIOEL=%16.16X, " "Entries=%d, Key=%2.2X, Intp=%16.16X\n"), dev->devnum, ioctl.listaddr, ioctl.blkcount, ioctl.key, ioctl.intrparm); } /* Set the default status code to an aborted list */ /* Note: This should be set correctly from the returned PSC */ ioctl.statuscod = PSC_STGERR; /* Get the storage for the thread's parameters */ if (!(asyncp=(IOCTL64 *)malloc(sizeof(IOCTL64)))) { logmsg (_("HHCVM011E VM BLOCK I/O request malloc failed\n")); *rc = RC_ERROR; return CC_FAILED; } /* Copy the thread's parameters to its own storage */ memcpy(asyncp,&ioctl,sizeof(IOCTL64)); /* Launch the asynchronous request on a separate thread */ snprintf(tname,sizeof(tname),"d250_async %4.4X",dev->devnum); tname[sizeof(tname)-1]=0; if ( create_thread (&tid, DETACHED, ARCH_DEP(d250_async64), asyncp, tname) ) { logmsg (_("%4.4X:HHCVM010E create_thread error: %s"), dev->devnum, strerror(errno)); release_lock (&dev->lock); *rc = RC_ERROR; return CC_FAILED; } /* Launched the async request successfully */ *rc = RC_ASYNC; return CC_SUCCESS; } else { if (dev->ccwtrace) { logmsg(_("%4.4X:HHCVM019I d250_iorq64 SYNC BIOEL=%16.16X, " "Entries=%d, Key=%2.2X\n"), dev->devnum, ioctl.listaddr, ioctl.blkcount, ioctl.key); } psc=ARCH_DEP(d250_list64)(&ioctl, SYNC); if (dev->ccwtrace) { logmsg(_("%4.4X:HHCVM017I d250_iorq64 " "PSC=%d, succeeded=%d, failed=%d\n"), dev->devnum,psc,ioctl.goodblks,ioctl.badblks); } } /* Processor status used to determine return and condition codes */ switch(psc) { case PSC_SUCCESS: *rc = RC_SUCCESS; return CC_SUCCESS; case PSC_PARTIAL: if (ioctl.goodblks == 0) { *rc = RC_ALL_BAD; return CC_FAILED; } else { *rc = RC_SYN_PART; return CC_PARTIAL; } case PSC_REMOVED: *rc = RC_REM_PART; return CC_PARTIAL; default: logmsg (_("HHCVM009E d250_list64 error: PSC=%i\n"), psc); *rc = RC_ERROR; return CC_FAILED; } /* end switch(psc) */ } /* end function d250_iorq64 */ /*-------------------------------------------------------------------*/ /* Input/Outut 64-bit List Processor - Sychronicity Independent */ /*-------------------------------------------------------------------*/ int ARCH_DEP(d250_list64)(IOCTL64* ioctl, int async) /* WARNING: Device Block lock must be released before returning */ { BIOE64 bioe; /* 32-bit BIOE fetched from absolute storage */ RADR bioebeg; /* Starting address of the BIOE */ RADR bioeend; /* Address of last byte of BIOE */ U16 xcode; /* Detected exception condition */ int blocks; /* Number of blocks being processed */ int block; /* counter used in block I/O loop */ S64 blknum; /* Block number of the request */ BYTE status; /* Returned BIOE status */ /* Passed to generic block I/O function */ int physblk; /* Physical block number */ RADR bufbeg; /* Address where the read/write will occur */ RADR bufend; /* Last byte read or written */ xcode = 0; /* Initialize the address check exception code */ /* Preserve pending sense if any and establish my ownership */ /* of the device by reserving it if shared and locking it */ if (ioctl->dev->ccwtrace) { logmsg (_("%4.4X:HHCVM015I d250_list64 BIOE's=%i A:" F_RADR " I/O key=%2.2X\n"), ioctl->dev->devnum, ioctl->blkcount, ioctl->listaddr, ioctl->key ); } /* Take ownership of the device */ d250_preserve(ioctl->dev); /* Note: the DEVBLK is now locked */ if (!ioctl->dev->vmd250env) { d250_restore(ioctl->dev); /* Note: the device lock is now released */ return PSC_REMOVED; } blocks=(int)ioctl->blkcount; bioebeg=ioctl->listaddr & AMASK64 ; /* Process each of the BIOE's supplied by the BIOPL count field */ for ( block = 0 ; block < blocks ; block++ ) { status = 0xFF; /* Set undefined status */ bioeend=( bioebeg + sizeof(BIOE32) - 1 ) & AMASK31; xcode=ARCH_DEP(d250_addrck) (bioebeg,bioeend,ACCTYPE_READ,ioctl->key,ioctl->regs); if (ioctl->dev->ccwtrace) { logmsg(_("%4.4X:HHCVM020I d250_list64 xcode=%4.4X " "BIOE64=%8.8X-%8.8X FETCH key=%2.2X\n"), ioctl->dev->devnum,xcode,bioebeg,bioeend,ioctl->key); } if ( xcode ) { break; } /* Fetch the BIOE from storage */ memcpy(&bioe,ioctl->regs->mainstor+bioebeg,sizeof(BIOE64)); STORAGE_KEY(bioebeg, ioctl->regs) |= (STORKEY_REF); STORAGE_KEY(bioeend, ioctl->regs) |= (STORKEY_REF); /* Process a single BIOE */ do { /* Make sure reserved field is zeros */ if ( bioe.resv1[0]!=0x00 || bioe.resv1[1]!=0x00 ) { status=BIOE_NOTZERO; continue; } /* Fetch and validate block number */ FETCH_DW(blknum,&bioe.blknum); if ( (blknum < ioctl->dev->vmd250env->begblk) || (blknum > ioctl->dev->vmd250env->endblk) ) { status=BIOE_BADBLOCK; continue; } /* Fetch the storage address used for I/O */ FETCH_DW(bufbeg,&bioe.bufaddr); bufbeg &= AMASK64; /* Ensure the environment still exists */ if (!ioctl->dev->vmd250env) { d250_restore(ioctl->dev); /* Note: the device lock is now released */ status=BIOE_ABORTED; return PSC_REMOVED; } /* The I/O handler routines are normally called without the */ /* device lock being held. The device is reserved by the */ /* busy status. */ /* Determine the last byte of the I/O buffer */ bufend=( bufbeg + ioctl->dev->vmd250env->blksiz -1 ) & AMASK64 ; if (ioctl->dev->ccwtrace) { logmsg (_("%4.4X:HHCVM016I d250_list64 BIOE %16.16X" ", oper=%2.2X, block=%i" ", buffer=%16.16X\n"), ioctl->dev->devnum, bioebeg, bioe.type, blknum, bufbeg ); } /* Determine the physical block on the device relative to zero */ physblk=(S64)blknum+ioctl->dev->vmd250env->offset-1; /* The read/write routines will convert this to a physical disk */ /* location for reading or writing */ if (bioe.type == BIOE_READ) { xcode=ARCH_DEP(d250_addrck) (bufbeg,bufend,ACCTYPE_READ,ioctl->key,ioctl->regs); if (ioctl->dev->ccwtrace) { logmsg(_("%4.4X:HHCVM020I d250_list64 xcode=%4.4X " "Rd Buf=%16.16X-%16.16X FETCH key=%2.2X\n"), ioctl->dev->devnum,xcode,bufbeg,bufend,ioctl->key); } switch ( xcode ) { case PGM_ADDRESSING_EXCEPTION: status=BIOE_ADDREXC; continue; case PGM_PROTECTION_EXCEPTION: status=BIOE_PROTEXC; continue; } /* At this point, the block number has been validated */ /* and the buffer is addressable and accessible */ status=d250_read(ioctl->dev, physblk, ioctl->dev->vmd250env->blksiz, ioctl->regs->mainstor+bufbeg); /* Set I/O storage key references if successful */ if (!status) { STORAGE_KEY(bufbeg, ioctl->regs) |= (STORKEY_REF); STORAGE_KEY(bufend, ioctl->regs) |= (STORKEY_REF); } continue; } /* end of BIOE_READ */ else { if (bioe.type == BIOE_WRITE) { xcode=ARCH_DEP(d250_addrck) (bufbeg,bufend,ACCTYPE_WRITE,ioctl->key,ioctl->regs); if (ioctl->dev->ccwtrace) { logmsg(_("%4.4X:HHCVM020I d250_list64 xcode=%4.4X " "Wr Buf=%16.16X-%16.16X STORE key=%2.2X\n"), ioctl->dev->devnum, xcode,bufbeg, bufend, ioctl->key); } switch ( xcode ) { case PGM_ADDRESSING_EXCEPTION: status=BIOE_ADDREXC; continue; case PGM_PROTECTION_EXCEPTION: status=BIOE_PROTEXC; continue; } if (ioctl->dev->vmd250env->isRO) { status=BIOE_DASDRO; continue; } status=d250_write(ioctl->dev, physblk, ioctl->dev->vmd250env->blksiz, ioctl->regs->mainstor+bufbeg); /* Set I/O storage key references if good I/O */ if (!status) { STORAGE_KEY(bufbeg, ioctl->regs) |= (STORKEY_REF | STORKEY_CHANGE); STORAGE_KEY(bufend, ioctl->regs) |= (STORKEY_REF | STORKEY_CHANGE); } continue; } /* end of if BIOE_WRITE */ else { status=BIOE_BADREQ; continue; } /* end of else BIOE_WRITE */ } /* end of else BIOE_READ */ }while(0); /* end of do */ /* Determine if we can store the status in the BIOE */ xcode=ARCH_DEP(d250_addrck) (bioebeg+1,bioebeg+1,ACCTYPE_WRITE,ioctl->key,ioctl->regs); if (ioctl->dev->ccwtrace) { logmsg(_("%4.4X:HHCVM020I d250_list64 xcode=%4.4X " "Status=%16.16X-%16.16X STORE key=%2.2X\n"), ioctl->dev->devnum,xcode,bioebeg+1,bioebeg+1,ioctl->key); } /* If the status byte is store protected, give up on processing any */ /* more BIOE's. Leave the BIOE list process for loop */ if ( xcode ) { break; } /* Store the status in the BIOE */ memcpy(ioctl->regs->mainstor+bioebeg+1,&status,1); /* Set the storage key change bit */ STORAGE_KEY(bioebeg+1, ioctl->regs) |= (STORKEY_REF | STORKEY_CHANGE); if (ioctl->dev->ccwtrace) { logmsg (_("%4.4X:HHCVM014I d250_list64 BIOE=%16.16X status=%2.2X\n"), ioctl->dev->devnum,bioebeg,status); } /* Count if this BIOE was a success or failure */ if ( status ) { ioctl->badblks+=1; if ( status == BIOE_ABORTED ) { break; } } else { ioctl->goodblks+=1; } /* Determine the address of the next BIOE */ bioebeg += sizeof(BIOE64); bioebeg &= AMASK64; } /* end of for loop */ #if 0 /* remove after testing */ logmsg(_("(d250_list64) BIOE's processed: %d\n"),block); #endif /* Restore device to guest ownership */ d250_restore(ioctl->dev); /* Note: device lock not held */ /* If an access exception occurred: */ /* If this is a synchronous request, generate a program exception */ /* or if this is asynchrnous, just return with a storage error */ if ( xcode ) { if (async) return PSC_STGERR; else ARCH_DEP(program_interrupt)(ioctl->regs, xcode); } if ( status == BIOE_ABORTED ) { return PSC_REMOVED; } /* Determine if we were completely successful or only partially */ /* successful. 'Partial' includes none successful. */ /* Synchronous and asynchronous requests handle all failed */ /* differently. The good and bad blocks field are used by the */ /* caller */ if (ioctl->goodblks < blocks) { return PSC_PARTIAL; } return PSC_SUCCESS; } /* end function ARCH_DEP(d250_list64) */ #endif /* defined(FEATURE_ESAME) */ #endif /*FEATURE_VM_BLOCKIO*/ #if !defined(_GEN_ARCH) #if defined(_ARCHMODE2) #define _GEN_ARCH _ARCHMODE2 #include "vmd250.c" #endif #if defined(_ARCHMODE3) #undef _GEN_ARCH #define _GEN_ARCH _ARCHMODE3 #include "vmd250.c" #endif #endif /*!defined(_GEN_ARCH)*/ hercules-3.07/vmd250.h000644 000765 000765 00000002442 11301535254 016132 0ustar00jmaynardjmaynard000000 000000 /* VMD250.H (c) Copyright Harold Grovesteen, 2009 */ /* z/VM 5.4 DIAGNOSE call X'250' */ // $Id: vmd250.h 5448 2009-08-10 08:20:51Z rbowler $ #if !defined(__VMD250_H__) #define __VMD250_H__ /*-------------------------------------------------------------------*/ /* DIAGNOSE X'250' Block I/O - Device Environment */ /*-------------------------------------------------------------------*/ struct VMBIOENV { DEVBLK *dev; /* Device block pointer of device */ S32 blksiz; /* Block size being used by the guest */ S64 offset; /* Guest provided offset */ S64 begblk; /* BIO established beginning block number */ S64 endblk; /* BIO established ending block number */ int isCKD; /* Count-Key-Data device */ int isRO; /* Device is read-only */ int blkphys; /* Block to physical relationship */ /* For FBA: physical sectors per block */ /* For CKD: physical blocks per track */ BYTE sense[32]; /* Save area for any pending sense data */ }; #endif /* !defined(__VMD250_H__) */ hercules-3.07/vstore.c000644 000765 000765 00000001436 11143760542 016440 0ustar00jmaynardjmaynard000000 000000 /* VSTORE.C */ /* z/Architecture support - (c) Copyright Jan Jaeger, 1999-2009 */ // $Id: vstore.c 5127 2009-01-23 13:25:01Z bernard $ // // $Log$ // Revision 1.11 2007/06/23 00:04:19 ivan // Update copyright notices to include current year (2007) // // Revision 1.10 2006/12/08 09:43:31 jj // Add CVS message log // #include "hstdinc.h" #include "hercules.h" #if defined(OPTION_NO_INLINE_VSTORE) | defined(OPTION_NO_INLINE_IFETCH) #define _VSTORE_C #include "opcode.h" #include "inline.h" #if !defined(_GEN_ARCH) #if defined(_ARCHMODE2) #define _GEN_ARCH _ARCHMODE2 #include "vstore.c" #endif #if defined(_ARCHMODE3) #undef _GEN_ARCH #define _GEN_ARCH _ARCHMODE3 #include "vstore.c" #endif #endif /*!defined(_GEN_ARCH)*/ #endif /*!defined(OPTION_NO_INLINE_VSTORE)*/ hercules-3.07/vstore.h000644 000765 000765 00000152015 11224164170 016440 0ustar00jmaynardjmaynard000000 000000 /* VSTORE.H (c) Copyright Roger Bowler, 1999-2009 */ /* ESA/390 Virtual Storage Functions */ /* Interpretive Execution - (c) Copyright Jan Jaeger, 1999-2009 */ /* z/Architecture support - (c) Copyright Jan Jaeger, 1999-2009 */ // $Id: vstore.h 5401 2009-06-08 03:54:27Z fish $ /*-------------------------------------------------------------------*/ /* This module contains various functions which store, fetch, and */ /* copy values to, from, or between virtual storage locations. */ /* */ /* Functions provided in this module are: */ /* vstorec Store 1 to 256 characters into virtual storage */ /* vstoreb Store a single byte into virtual storage */ /* vstore2 Store a two-byte integer into virtual storage */ /* vstore4 Store a four-byte integer into virtual storage */ /* vstore8 Store an eight-byte integer into virtual storage */ /* vfetchc Fetch 1 to 256 characters from virtual storage */ /* vfetchb Fetch a single byte from virtual storage */ /* vfetch2 Fetch a two-byte integer from virtual storage */ /* vfetch4 Fetch a four-byte integer from virtual storage */ /* vfetch8 Fetch an eight-byte integer from virtual storage */ /* instfetch Fetch instruction from virtual storage */ /* move_chars Move characters using specified keys and addrspaces */ /* move_charx Move characters with optional specifications */ /* validate_operand Validate addressing, protection, translation */ /*-------------------------------------------------------------------*/ /* And provided by means of macro's address wrapping versions of */ /* the above: */ /* wstoreX */ /* wfetchX */ /* wmove_chars */ /* wvalidate_operand */ /*-------------------------------------------------------------------*/ // $Log$ // Revision 1.85 2009/01/23 13:13:46 bernard // copyright notice // // Revision 1.84 2009/01/17 17:02:15 jj // Fix change recording on page crossing first op of MVC - Reported by Greg Price // // Revision 1.83 2008/04/02 21:52:19 rbowler // Fix PIC4 when MVCOS operand finishes on page boundary // // Revision 1.82 2008/03/23 06:13:07 rbowler // Add MVCOS instruction (part 3) // // Revision 1.81 2008/03/23 03:03:45 gsmith // 22 Mar 2008 fix unbalanced comment - Peter J Farley III - by Greg // // Revision 1.80 2008/03/16 00:09:57 rbowler // Add MVCOS instruction (part 2) // // Revision 1.79 2008/02/20 23:47:22 ptl00 // Fix branch to odd address so pgm old is bumped // // Revision 1.78 2007/06/23 00:04:19 ivan // Update copyright notices to include current year (2007) // // Revision 1.77 2007/03/13 00:11:14 gsmith // Updates to concpy for 64-bit hosts // // Revision 1.76 2007/03/09 00:54:31 gsmith // concpy rework // // Revision 1.75 2007/03/08 01:27:02 gsmith // Remove inline attr from vfetchx/vstorex _full functions // // Revision 1.74 2007/02/18 16:27:36 gsmith // Fix instfetch when instruction crosses 0x800 // // Revision 1.73 2007/01/11 02:44:25 gsmith // Temp patch to help messed up gcc v4 optimizations // // Revision 1.72 2007/01/09 23:19:35 gsmith // Tweaks to sloppy fetch // // Revision 1.71 2007/01/04 23:12:04 gsmith // remove thunk calls for program_interrupt // // Revision 1.70 2007/01/04 01:08:41 gsmith // 03 Jan 2007 single_cpu_dw fetch/store patch for ia32 // // Revision 1.69 2007/01/04 00:29:17 gsmith // 03 Jan 2007 vstorex patch to vstore2, vstore4, vstore8 // // Revision 1.68 2007/01/03 05:53:34 gsmith // 03 Jan 2007 Sloppy fetch - Greg Smith // // Revision 1.67 2006/12/20 04:26:20 gsmith // 19 Dec 2006 ip_all.pat - performance patch - Greg Smith // // Revision 1.66 2006/12/08 09:43:31 jj // Add CVS message log // #define s370_wstorec(_src, _len, _addr, _arn, _regs) \ s370_vstorec((_src), (_len), ((_addr) & ADDRESS_MAXWRAP((_regs))), (_arn), (_regs)) #define s370_wstoreb(_value, _addr, _arn, _regs) \ s370_vstoreb((_value), ((_addr) & ADDRESS_MAXWRAP((_regs))), (_arn), (_regs)) #define s370_wstore2(_value, _addr, _arn, _regs) \ s370_vstore2((_value), ((_addr) & ADDRESS_MAXWRAP((_regs))), (_arn), (_regs)) #define s370_wstore4(_value, _addr, _arn, _regs) \ s370_vstore4((_value), ((_addr) & ADDRESS_MAXWRAP((_regs))), (_arn), (_regs)) #define s370_wstore8(_value, _addr, _arn, _regs) \ s370_vstore8((_value), ((_addr) & ADDRESS_MAXWRAP((_regs))), (_arn), (_regs)) #define s370_wfetchc(_dest, _len, _addr, _arn, _regs) \ s370_vfetchc((_dest), (_len), ((_addr) & ADDRESS_MAXWRAP((_regs))), (_arn), (_regs)) #define s370_wfetchb(_addr, _arn, _regs) \ s370_vfetchb(((_addr) & ADDRESS_MAXWRAP((_regs))), (_arn), (_regs)) #define s370_wfetch2(_addr, _arn, _regs) \ s370_vfetch2(((_addr) & ADDRESS_MAXWRAP((_regs))), (_arn), (_regs)) #define s370_wfetch4(_addr, _arn, _regs) \ s370_vfetch4(((_addr) & ADDRESS_MAXWRAP((_regs))), (_arn), (_regs)) #define s370_wfetch8(_addr, _arn, _regs) \ s370_vfetch8(((_addr) & ADDRESS_MAXWRAP((_regs))), (_arn), (_regs)) #define s370_wmove_chars(_addr1, _arn1, _key1, _addr2, _arn2, _key2, _len, _regs) \ s370_move_chars(((_addr1) & ADDRESS_MAXWRAP((_regs))), (_arn1), (_key1), \ ((_addr2) & ADDRESS_MAXWRAP((_regs))), (_arn2), (_key2), (_len), (_regs)) #define s370_wvalidate_operand(_addr, _arn, _len, _acctype, _regs) \ s370_validate_operand(((_addr) & ADDRESS_MAXWRAP((_regs))), (_arn), (_len), (_acctype), (_regs)) #define s390_wstorec(_src, _len, _addr, _arn, _regs) \ s390_vstorec((_src), (_len), ((_addr) & ADDRESS_MAXWRAP((_regs))), (_arn), (_regs)) #define s390_wstoreb(_value, _addr, _arn, _regs) \ s390_vstoreb((_value), ((_addr) & ADDRESS_MAXWRAP((_regs))), (_arn), (_regs)) #define s390_wstore2(_value, _addr, _arn, _regs) \ s390_vstore2((_value), ((_addr) & ADDRESS_MAXWRAP((_regs))), (_arn), (_regs)) #define s390_wstore4(_value, _addr, _arn, _regs) \ s390_vstore4((_value), ((_addr) & ADDRESS_MAXWRAP((_regs))), (_arn), (_regs)) #define s390_wstore8(_value, _addr, _arn, _regs) \ s390_vstore8((_value), ((_addr) & ADDRESS_MAXWRAP((_regs))), (_arn), (_regs)) #define s390_wfetchc(_dest, _len, _addr, _arn, _regs) \ s390_vfetchc((_dest), (_len), ((_addr) & ADDRESS_MAXWRAP((_regs))), (_arn), (_regs)) #define s390_wfetchb(_addr, _arn, _regs) \ s390_vfetchb(((_addr) & ADDRESS_MAXWRAP((_regs))), (_arn), (_regs)) #define s390_wfetch2(_addr, _arn, _regs) \ s390_vfetch2(((_addr) & ADDRESS_MAXWRAP((_regs))), (_arn), (_regs)) #define s390_wfetch4(_addr, _arn, _regs) \ s390_vfetch4(((_addr) & ADDRESS_MAXWRAP((_regs))), (_arn), (_regs)) #define s390_wfetch8(_addr, _arn, _regs) \ s390_vfetch8(((_addr) & ADDRESS_MAXWRAP((_regs))), (_arn), (_regs)) #define s390_wmove_chars(_addr1, _arn1, _key1, _addr2, _arn2, _key2, _len, _regs) \ s390_move_chars(((_addr1) & ADDRESS_MAXWRAP((_regs))), (_arn1), (_key1), \ ((_addr2) & ADDRESS_MAXWRAP((_regs))), (_arn2), (_key2), (_len), (_regs)) #define s390_wvalidate_operand(_addr, _arn, _len, _acctype, _regs) \ s390_validate_operand(((_addr) & ADDRESS_MAXWRAP((_regs))), (_arn), (_len), (_acctype), (_regs)) #define z900_wstorec(_src, _len, _addr, _arn, _regs) \ z900_vstorec((_src), (_len), ((_addr) & ADDRESS_MAXWRAP((_regs))), (_arn), (_regs)) #define z900_wstoreb(_value, _addr, _arn, _regs) \ z900_vstoreb((_value), ((_addr) & ADDRESS_MAXWRAP((_regs))), (_arn), (_regs)) #define z900_wstore2(_value, _addr, _arn, _regs) \ z900_vstore2((_value), ((_addr) & ADDRESS_MAXWRAP((_regs))), (_arn), (_regs)) #define z900_wstore4(_value, _addr, _arn, _regs) \ z900_vstore4((_value), ((_addr) & ADDRESS_MAXWRAP((_regs))), (_arn), (_regs)) #define z900_wstore8(_value, _addr, _arn, _regs) \ z900_vstore8((_value), ((_addr) & ADDRESS_MAXWRAP((_regs))), (_arn), (_regs)) #define z900_wfetchc(_dest, _len, _addr, _arn, _regs) \ z900_vfetchc((_dest), (_len), ((_addr) & ADDRESS_MAXWRAP((_regs))), (_arn), (_regs)) #define z900_wfetchb(_addr, _arn, _regs) \ z900_vfetchb(((_addr) & ADDRESS_MAXWRAP((_regs))), (_arn), (_regs)) #define z900_wfetch2(_addr, _arn, _regs) \ z900_vfetch2(((_addr) & ADDRESS_MAXWRAP((_regs))), (_arn), (_regs)) #define z900_wfetch4(_addr, _arn, _regs) \ z900_vfetch4(((_addr) & ADDRESS_MAXWRAP((_regs))), (_arn), (_regs)) #define z900_wfetch8(_addr, _arn, _regs) \ z900_vfetch8(((_addr) & ADDRESS_MAXWRAP((_regs))), (_arn), (_regs)) #define z900_wmove_chars(_addr1, _arn1, _key1, _addr2, _arn2, _key2, _len, _regs) \ z900_move_chars(((_addr1) & ADDRESS_MAXWRAP((_regs))), (_arn1), (_key1), \ ((_addr2) & ADDRESS_MAXWRAP((_regs))), (_arn2), (_key2), (_len), (_regs)) #define z900_wvalidate_operand(_addr, _arn, _len, _acctype, _regs) \ z900_validate_operand(((_addr) & ADDRESS_MAXWRAP((_regs))), (_arn), (_len), (_acctype), (_regs)) /*-------------------------------------------------------------------*/ /* Operand Length Checking Macros */ /* */ /* The following macros are used to determine whether an operand */ /* storage access will cross a 2K page boundary or not. */ /* */ /* The first 'plain' pair of macros (without the 'L') are used for */ /* 0-based lengths wherein zero = 1 byte is being referenced and 255 */ /* means 256 bytes are being referenced. They are obviously designed */ /* for maximum length values of 0-255 as used w/MVC instructions. */ /* */ /* The second pair of 'L' macros are using for 1-based lengths where */ /* 0 = no bytes are being referenced, 1 = one byte, etc. They are */ /* designed for 'Large' maximum length values such as occur with the */ /* MVCL instruction for example (where the length can be up to 16MB) */ /*-------------------------------------------------------------------*/ #define NOCROSS2K(_addr,_len) likely( ( (int)((_addr) & 0x7FF)) <= ( 0x7FF - (_len) ) ) #define CROSS2K(_addr,_len) unlikely( ( (int)((_addr) & 0x7FF)) > ( 0x7FF - (_len) ) ) #define NOCROSS2KL(_addr,_len) likely( ( (int)((_addr) & 0x7FF)) <= ( 0x800 - (_len) ) ) #define CROSS2KL(_addr,_len) unlikely( ( (int)((_addr) & 0x7FF)) > ( 0x800 - (_len) ) ) #if !defined(OPTION_NO_INLINE_VSTORE) || defined(_VSTORE_C) /*-------------------------------------------------------------------*/ /* Store 1 to 256 characters into virtual storage operand */ /* */ /* Input: */ /* src 1 to 256 byte input buffer */ /* len Size of operand minus 1 */ /* addr Logical address of leftmost character of operand */ /* arn Access register number */ /* regs CPU register context */ /* */ /* A program check may be generated if the logical address */ /* range causes an addressing, translation, or protection */ /* exception, and in this case no real storage locations are */ /* updated, and the function does not return. */ /*-------------------------------------------------------------------*/ _VSTORE_C_STATIC void ARCH_DEP(vstorec) (void *src, BYTE len, VADR addr, int arn, REGS *regs) { BYTE *main1, *main2; /* Mainstor addresses */ BYTE *sk; /* Storage key addresses */ int len2; /* Length to end of page */ if ( NOCROSS2K(addr,len) ) { memcpy(MADDR(addr, arn, regs, ACCTYPE_WRITE, regs->psw.pkey), src, len + 1); ITIMER_UPDATE(addr,len,regs); } else { len2 = 0x800 - (addr & 0x7FF); main1 = MADDR(addr, arn, regs, ACCTYPE_WRITE_SKP, regs->psw.pkey); sk = regs->dat.storkey; main2 = MADDR((addr + len2) & ADDRESS_MAXWRAP(regs), arn, regs, ACCTYPE_WRITE, regs->psw.pkey); *sk |= (STORKEY_REF | STORKEY_CHANGE); memcpy (main1, src, len2); memcpy (main2, (BYTE*)src + len2, len + 1 - len2); } } /* end function ARCH_DEP(vstorec) */ /*-------------------------------------------------------------------*/ /* Store a single byte into virtual storage operand */ /* */ /* Input: */ /* value Byte value to be stored */ /* addr Logical address of operand byte */ /* arn Access register number */ /* regs CPU register context */ /* */ /* A program check may be generated if the logical address */ /* causes an addressing, translation, or protection */ /* exception, and in this case the function does not return. */ /*-------------------------------------------------------------------*/ _VSTORE_C_STATIC void ARCH_DEP(vstoreb) (BYTE value, VADR addr, int arn, REGS *regs) { BYTE *main1; /* Mainstor address */ main1 = MADDR(addr, arn, regs, ACCTYPE_WRITE, regs->psw.pkey); *main1 = value; ITIMER_UPDATE(addr,1-1,regs); } /* end function ARCH_DEP(vstoreb) */ /*-------------------------------------------------------------------*/ /* Store a two-byte integer into virtual storage operand */ /* */ /* Input: */ /* value 16-bit integer value to be stored */ /* addr Logical address of leftmost operand byte */ /* arn Access register number */ /* regs CPU register context */ /* */ /* A program check may be generated if the logical address */ /* causes an addressing, translation, or protection */ /* exception, and in this case the function does not return. */ /*-------------------------------------------------------------------*/ _VSTORE_FULL_C_STATIC void ARCH_DEP(vstore2_full)(U16 value, VADR addr, int arn, REGS *regs) { BYTE *main1, *main2; /* Mainstor addresses */ BYTE *sk; /* Storage key addresses */ main1 = MADDR(addr, arn, regs, ACCTYPE_WRITE_SKP, regs->psw.pkey); sk = regs->dat.storkey; main2 = MADDR((addr + 1) & ADDRESS_MAXWRAP(regs), arn, regs, ACCTYPE_WRITE, regs->psw.pkey); *sk |= (STORKEY_REF | STORKEY_CHANGE); *main1 = value >> 8; *main2 = value & 0xFF; } /* end function ARCH_DEP(vstore2_full) */ /* vstore2 accelerator - Simple case only (better inline candidate) */ _VSTORE_C_STATIC void ARCH_DEP(vstore2) (U16 value, VADR addr, int arn, REGS *regs) { /* Most common case : Aligned & not crossing page boundary */ if (likely(!((VADR_L)addr & 1) || ((VADR_L)addr & 0x7FF) != 0x7FF)) { BYTE *mn; mn = MADDR (addr, arn, regs, ACCTYPE_WRITE, regs->psw.pkey); STORE_HW(mn, value); ITIMER_UPDATE(addr,2-1,regs); } else ARCH_DEP(vstore2_full)(value, addr, arn, regs); } /* end function ARCH_DEP(vstore2) */ /*-------------------------------------------------------------------*/ /* Store a four-byte integer into virtual storage operand */ /* */ /* Input: */ /* value 32-bit integer value to be stored */ /* addr Logical address of leftmost operand byte */ /* arn Access register number */ /* regs CPU register context */ /* */ /* A program check may be generated if the logical address */ /* causes an addressing, translation, or protection */ /* exception, and in this case the function does not return. */ /*-------------------------------------------------------------------*/ _VSTORE_FULL_C_STATIC void ARCH_DEP(vstore4_full)(U32 value, VADR addr, int arn, REGS *regs) { BYTE *main1, *main2; /* Mainstor addresses */ BYTE *sk; /* Storage key addresses */ int len; /* Length to end of page */ BYTE temp[4]; /* Copied value */ len = 0x800 - (addr & 0x7FF); main1 = MADDR(addr, arn, regs, ACCTYPE_WRITE_SKP, regs->psw.pkey); sk = regs->dat.storkey; main2 = MADDR((addr + len) & ADDRESS_MAXWRAP(regs), arn, regs, ACCTYPE_WRITE, regs->psw.pkey); *sk |= (STORKEY_REF | STORKEY_CHANGE); STORE_FW(temp, value); memcpy(main1, temp, len); memcpy(main2, temp+len, 4-len); } /* end function ARCH_DEP(vstore4_full) */ /* vstore4 accelerator - Simple case only (better inline candidate) */ _VSTORE_C_STATIC void ARCH_DEP(vstore4) (U32 value, VADR addr, int arn, REGS *regs) { /* Most common case : Aligned & not crossing page boundary */ if(likely(!((VADR_L)addr & 0x03)) || (((VADR_L)addr & 0x7ff) <= 0x7fc)) { BYTE *mn; mn = MADDR(addr, arn, regs, ACCTYPE_WRITE, regs->psw.pkey); STORE_FW(mn, value); ITIMER_UPDATE(addr,4-1,regs); } else ARCH_DEP(vstore4_full)(value,addr,arn,regs); } /*-------------------------------------------------------------------*/ /* Store an eight-byte integer into virtual storage operand */ /* */ /* Input: */ /* value 64-bit integer value to be stored */ /* addr Logical address of leftmost operand byte */ /* arn Access register number */ /* regs CPU register context */ /* */ /* A program check may be generated if the logical address */ /* causes an addressing, translation, or protection */ /* exception, and in this case the function does not return. */ /* */ /* NOTE that vstore8_full should only be invoked when a page */ /* boundary IS going to be crossed. */ /*-------------------------------------------------------------------*/ _VSTORE_FULL_C_STATIC void ARCH_DEP(vstore8_full)(U64 value, VADR addr, int arn, REGS *regs) { BYTE *main1, *main2; /* Mainstor addresses */ BYTE *sk; /* Storage key addresses */ int len; /* Length to end of page */ BYTE temp[8]; /* Copied value */ len = 0x800 - (addr & 0x7FF); main1 = MADDR(addr, arn, regs, ACCTYPE_WRITE_SKP, regs->psw.pkey); sk = regs->dat.storkey; main2 = MADDR((addr + len) & ADDRESS_MAXWRAP(regs), arn, regs, ACCTYPE_WRITE, regs->psw.pkey); *sk |= (STORKEY_REF | STORKEY_CHANGE); STORE_DW(temp, value); memcpy(main1, temp, len); memcpy(main2, temp+len, 8-len); } /* end function ARCH_DEP(vstore8) */ _VSTORE_C_STATIC void ARCH_DEP(vstore8) (U64 value, VADR addr, int arn, REGS *regs) { /* Check alignement. If aligned then we are guaranteed not to cross a page boundary */ if(likely(!((VADR_L)addr & 0x07))) { /* Most common case : Aligned */ U64 *mn; mn = (U64*)MADDR(addr,arn,regs,ACCTYPE_WRITE,regs->psw.pkey); #if defined(OPTION_SINGLE_CPU_DW) && defined(ASSIST_STORE_DW) if (regs->cpubit == regs->sysblk->started_mask) *mn = CSWAP64(value); else #endif STORE_DW(mn, value); } else { /* We're not aligned. So we have to check whether we are crossing a page boundary. This cannot be the same code as above because casting U64 * to a non aligned pointer may break on those architectures mandating strict alignement */ if((((VADR_L)addr & 0x7ff) <= 0x7f8)) { /* Non aligned but not crossing page boundary */ BYTE *mn; mn = MADDR(addr,arn,regs,ACCTYPE_WRITE,regs->psw.pkey); /* invoking STORE_DW ensures endianness correctness */ STORE_DW(mn,value); } else /* Crossing page boundary */ ARCH_DEP(vstore8_full)(value,addr,arn,regs); } ITIMER_UPDATE(addr,8-1,regs); } /*-------------------------------------------------------------------*/ /* Fetch a 1 to 256 character operand from virtual storage */ /* */ /* Input: */ /* len Size of operand minus 1 */ /* addr Logical address of leftmost character of operand */ /* arn Access register number */ /* regs CPU register context */ /* Output: */ /* dest 1 to 256 byte output buffer */ /* */ /* A program check may be generated if the logical address */ /* causes an addressing, translation, or fetch protection */ /* exception, and in this case the function does not return. */ /*-------------------------------------------------------------------*/ _VSTORE_C_STATIC void ARCH_DEP(vfetchc) (void *dest, BYTE len, VADR addr, int arn, REGS *regs) { BYTE *main1, *main2; /* Main storage addresses */ int len2; /* Length to copy on page */ main1 = MADDR(addr,arn,regs,ACCTYPE_READ,regs->psw.pkey); if ( NOCROSS2K(addr,len) ) { ITIMER_SYNC(addr,len,regs); memcpy (dest, main1, len + 1); } else { len2 = 0x800 - (addr & 0x7FF); main2 = MADDR ((addr + len2) & ADDRESS_MAXWRAP(regs), arn, regs, ACCTYPE_READ, regs->psw.pkey); memcpy (dest, main1, len2); memcpy ((BYTE*)dest + len2, main2, len + 1 - len2); } } /* end function ARCH_DEP(vfetchc) */ /*-------------------------------------------------------------------*/ /* Fetch a single byte operand from virtual storage */ /* */ /* Input: */ /* addr Logical address of operand character */ /* arn Access register number */ /* regs CPU register context */ /* Returns: */ /* Operand byte */ /* */ /* A program check may be generated if the logical address */ /* causes an addressing, translation, or fetch protection */ /* exception, and in this case the function does not return. */ /*-------------------------------------------------------------------*/ _VSTORE_C_STATIC BYTE ARCH_DEP(vfetchb) (VADR addr, int arn, REGS *regs) { BYTE *mn; /* Main storage address */ ITIMER_SYNC(addr,1-1,regs); mn = MADDR (addr, arn, regs, ACCTYPE_READ, regs->psw.pkey); return *mn; } /* end function ARCH_DEP(vfetchb) */ /*-------------------------------------------------------------------*/ /* Fetch a two-byte integer operand from virtual storage */ /* */ /* Input: */ /* addr Logical address of leftmost byte of operand */ /* arn Access register number */ /* regs CPU register context */ /* Returns: */ /* Operand in 16-bit integer format */ /* */ /* A program check may be generated if the logical address */ /* causes an addressing, translation, or fetch protection */ /* exception, and in this case the function does not return. */ /*-------------------------------------------------------------------*/ _VSTORE_FULL_C_STATIC U16 ARCH_DEP(vfetch2_full) (VADR addr, int arn, REGS *regs) { BYTE *mn; /* Main storage addresses */ U16 value; mn = MADDR (addr, arn, regs, ACCTYPE_READ, regs->psw.pkey); value = *mn << 8; mn = MADDR ((addr + 1) & ADDRESS_MAXWRAP(regs), arn, regs, ACCTYPE_READ, regs->psw.pkey); value |= *mn; return value; } /* end function ARCH_DEP(vfetch2) */ _VSTORE_C_STATIC U16 ARCH_DEP(vfetch2) (VADR addr, int arn, REGS *regs) { if(likely(!((VADR_L)addr & 0x01)) || (((VADR_L)addr & 0x7ff) !=0x7ff )) { BYTE *mn; ITIMER_SYNC(addr,2-1,regs); mn = MADDR(addr,arn,regs,ACCTYPE_READ,regs->psw.pkey); return fetch_hw(mn); } return(ARCH_DEP(vfetch2_full)(addr,arn,regs)); } /*-------------------------------------------------------------------*/ /* Fetch a four-byte integer operand from virtual storage */ /* */ /* Input: */ /* addr Logical address of leftmost byte of operand */ /* arn Access register number */ /* regs CPU register context */ /* Returns: */ /* Operand in 32-bit integer format */ /* */ /* A program check may be generated if the logical address */ /* causes an addressing, translation, or fetch protection */ /* exception, and in this case the function does not return. */ /*-------------------------------------------------------------------*/ _VSTORE_FULL_C_STATIC U32 ARCH_DEP(vfetch4_full) (VADR addr, int arn, REGS *regs) { BYTE *mn; /* Main storage addresses */ int len; /* Length to end of page */ BYTE temp[8]; /* Copy destination */ mn = MADDR (addr, arn, regs, ACCTYPE_READ, regs->psw.pkey); memcpy(temp, mn, 4); len = 0x800 - (addr & 0x7FF); mn = MADDR ((addr + len) & ADDRESS_MAXWRAP(regs), arn, regs, ACCTYPE_READ, regs->psw.pkey); memcpy(temp+len, mn, 4); return fetch_fw(temp); } /* end function ARCH_DEP(vfetch4_full) */ _VSTORE_C_STATIC U32 ARCH_DEP(vfetch4) (VADR addr, int arn, REGS *regs) { if ( (likely(!((VADR_L)addr & 0x03)) || (((VADR_L)addr & 0x7ff) <= 0x7fc ))) { BYTE *mn; ITIMER_SYNC(addr,4-1,regs); mn=MADDR(addr,arn,regs,ACCTYPE_READ,regs->psw.pkey); return fetch_fw(mn); } return(ARCH_DEP(vfetch4_full)(addr,arn,regs)); } /*-------------------------------------------------------------------*/ /* Fetch an eight-byte integer operand from virtual storage */ /* */ /* Input: */ /* addr Logical address of leftmost byte of operand */ /* arn Access register number */ /* regs CPU register context */ /* Returns: */ /* Operand in 64-bit integer format */ /* */ /* A program check may be generated if the logical address */ /* causes an addressing, translation, or fetch protection */ /* exception, and in this case the function does not return. */ /*-------------------------------------------------------------------*/ _VSTORE_FULL_C_STATIC U64 ARCH_DEP(vfetch8_full) (VADR addr, int arn, REGS *regs) { BYTE *mn; /* Main storage addresses */ int len; /* Length to end of page */ BYTE temp[16]; /* Copy destination */ /* Get absolute address of first byte of operand */ mn = MADDR (addr, arn, regs, ACCTYPE_READ, regs->psw.pkey); memcpy(temp, mn, 8); len = 0x800 - (addr & 0x7FF); mn = MADDR ((addr + len) & ADDRESS_MAXWRAP(regs), arn, regs, ACCTYPE_READ, regs->psw.pkey); memcpy(temp+len, mn, 8); return fetch_dw(temp); } /* end function ARCH_DEP(vfetch8) */ _VSTORE_C_STATIC U64 ARCH_DEP(vfetch8) (VADR addr, int arn, REGS *regs) { if(likely(!((VADR_L)addr & 0x07))) { /* doubleword aligned fetch */ U64 *mn; ITIMER_SYNC(addr,8-1,regs); mn=(U64*)MADDR (addr, arn, regs, ACCTYPE_READ, regs->psw.pkey); #if defined(OPTION_SINGLE_CPU_DW) && defined(ASSIST_FETCH_DW) if (regs->cpubit == regs->sysblk->started_mask) return CSWAP64(*mn); #endif return fetch_dw(mn); } else { if((((VADR_L)addr & 0x7ff) <= 0x7f8 )) { /* unaligned, non-crossing doubleword fetch */ BYTE *mn; ITIMER_SYNC(addr,8-1,regs); mn=MADDR (addr, arn, regs, ACCTYPE_READ, regs->psw.pkey); return fetch_dw(mn); } } /* page crossing doubleword fetch */ return ARCH_DEP(vfetch8_full)(addr,arn,regs); } #endif #if !defined(OPTION_NO_INLINE_IFETCH) || defined(_VSTORE_C) /*-------------------------------------------------------------------*/ /* Fetch instruction from halfword-aligned virtual storage location */ /* */ /* Input: */ /* regs Pointer to the CPU register context */ /* exec If 1 then called by EXecute otherwise called by */ /* INSTRUCTION_FETCH */ /* */ /* If called by INSTRUCTION_FETCH then */ /* addr regs->psw.IA */ /* dest regs->inst */ /* */ /* If called by EXecute then */ /* addr regs->ET */ /* dest regs->exinst */ /* */ /* Output: */ /* If successful, a pointer is returned to the instruction. If */ /* the instruction crossed a page boundary then the instruction */ /* is copied either to regs->inst or regs->exinst (depending on */ /* the exec flag). Otherwise the pointer points into mainstor. */ /* */ /* If the exec flag is 0 and tracing or PER is not active then */ /* the AIA is updated. This forces interrupts to be checked */ /* instfetch to be call for each instruction. Note that */ /* process_trace() is called from here if tracing is active. */ /* */ /* A program check may be generated if the instruction address */ /* is odd, or causes an addressing or translation exception, */ /* and in this case the function does not return. In the */ /* latter case, regs->instinvalid is 1 which indicates to */ /* program_interrupt that the exception occurred during */ /* instruction fetch. */ /* */ /* Because this function is inlined and `exec' is a constant */ /* (either 0 or 1) the references to exec are optimized out by */ /* the compiler. */ /*-------------------------------------------------------------------*/ _VFETCH_C_STATIC BYTE * ARCH_DEP(instfetch) (REGS *regs, int exec) { VADR addr; /* Instruction address */ BYTE *ia; /* Instruction pointer */ BYTE *dest; /* Copied instruction */ int pagesz; /* Effective page size */ int offset; /* Address offset into page */ int len; /* Length for page crossing */ SET_BEAR_REG(regs, regs->bear_ip); addr = exec ? regs->ET : likely(regs->aie == NULL) ? regs->psw.IA : PSW_IA(regs,0); offset = (int)(addr & PAGEFRAME_BYTEMASK); /* Program check if instruction address is odd */ if ( unlikely(offset & 0x01) ) { if (!exec) regs->instinvalid = 1; regs->program_interrupt(regs, PGM_SPECIFICATION_EXCEPTION); } pagesz = unlikely(addr < 0x800) ? 0x800 : PAGEFRAME_PAGESIZE; #if defined(FEATURE_PER) /* Save the address address used to fetch the instruction */ if( EN_IC_PER(regs) ) { #if defined(FEATURE_PER2) regs->perc = 0x40 /* ATMID-validity */ | (regs->psw.amode64 << 7) | (regs->psw.amode << 5) | (!REAL_MODE(®s->psw) ? 0x10 : 0) | (SPACE_BIT(®s->psw) << 3) | (AR_BIT(®s->psw) << 2); #else /*!defined(FEATURE_PER2)*/ regs->perc = 0; #endif /*!defined(FEATURE_PER2)*/ if(!exec) regs->peradr = addr; /* Test for PER instruction-fetching event */ if( EN_IC_PER_IF(regs) && PER_RANGE_CHECK(addr,regs->CR(10),regs->CR(11)) ) { ON_IC_PER_IF(regs); #if defined(FEATURE_PER3) /* If CR9_IFNUL (PER instruction-fetching nullification) is set, take a program check immediately, without executing the instruction or updating the PSW instruction address */ if ( EN_IC_PER_IFNUL(regs) ) { ON_IC_PER_IFNUL(regs); regs->psw.IA = addr; regs->psw.zeroilc = 1; regs->program_interrupt(regs, PGM_PER_EVENT); } #endif /*defined(FEATURE_PER3)*/ } /* Quick exit if aia valid */ if (!exec && !regs->tracing && regs->aie && regs->ip < regs->aip + pagesz - 5) return regs->ip; } #endif /*defined(FEATURE_PER)*/ if (!exec) regs->instinvalid = 1; /* Get instruction address */ ia = MADDR (addr, USE_INST_SPACE, regs, ACCTYPE_INSTFETCH, regs->psw.pkey); /* If boundary is crossed then copy instruction to destination */ if ( offset + ILC(ia[0]) > pagesz ) { /* Note - dest is 8 bytes */ dest = exec ? regs->exinst : regs->inst; memcpy (dest, ia, 4); len = pagesz - offset; offset = 0; addr = (addr + len) & ADDRESS_MAXWRAP(regs); ia = MADDR(addr, USE_INST_SPACE, regs, ACCTYPE_INSTFETCH, regs->psw.pkey); if (!exec) regs->ip = ia - len; memcpy(dest + len, ia, 4); } else { dest = ia; if (!exec) regs->ip = ia; } if (!exec) { regs->instinvalid = 0; /* Update the AIA */ regs->AIV = addr & PAGEFRAME_PAGEMASK; regs->aip = (BYTE *)((uintptr_t)ia & ~PAGEFRAME_BYTEMASK); regs->aim = (uintptr_t)regs->aip ^ (uintptr_t)regs->AIV; if (likely(!regs->tracing && !regs->permode)) regs->aie = regs->aip + pagesz - 5; else { regs->aie = (BYTE *)1; if (regs->tracing) ARCH_DEP(process_trace)(regs); } } return dest; } /* end function ARCH_DEP(instfetch) */ #endif /*-------------------------------------------------------------------*/ /* Copy 8 bytes at a time concurrently */ /*-------------------------------------------------------------------*/ #ifndef _VSTORE_CONCPY #define _VSTORE_CONCPY static __inline__ void concpy (REGS *regs, void *d, void *s, int n) { int n2; BYTE *dest = (BYTE *)d, *src = (BYTE *)s; /* Byte for byte copy if short length or possible overlap */ if (n < 8 || (dest <= src && dest + 8 > src) || (src <= dest && src + 8 > dest)) { /* use memset directly when the copy's effect is to propagate a byte over an area - like in MVC 1(255,2),0(2) */ if(dest==src+1) { memset(dest,*src,n); } else { for ( ; n; n--) *(dest++) = *(src++); } return; } /* copy to an 8 byte boundary */ n2 = (intptr_t)dest & 7; n -= n2; for ( ; n2; n2--) *(dest++) = *(src++); #if !defined(OPTION_STRICT_ALIGNMENT) && \ ((!defined(_MSVC_) && defined(SIZEOF_LONG) && SIZEOF_LONG >= 8) || \ ( defined(_MSVC_) && defined(SIZEOF_INT_P) && SIZEOF_INT_P >= 8)) /* Below for 64-bit BUILDS ONLY, since the below C code does NOT generate atomic 64-bit load/store assembler code sequence compatible with Concurrent Block Update except when building for 64-bit systems... */ UNREFERENCED(regs); /* copy 8 bytes at a time */ for ( ; n >= 8; n -= 8, dest += 8, src += 8) *(U64 *)dest = *(U64 *)src; #else /* 32-bit builds... */ #if !defined(OPTION_STRICT_ALIGNMENT) /* copy 4 bytes at a time if only one cpu started */ if (regs->cpubit == regs->sysblk->started_mask) for ( ; n >= 4; n -= 4, dest += 4, src += 4) *(U32 *)dest = *(U32 *)src; else #else /* defined(OPTION_STRICT_ALIGNMENT) */ UNREFERENCED(regs); #endif /* else copy 8 bytes at a time concurrently */ for ( ; n >= 8; n -= 8, dest += 8, src += 8) store_dw_noswap(dest,fetch_dw_noswap(src)); #endif /* (64-bit builds test...) */ /* copy leftovers */ for ( ; n; n--) *(dest++) = *(src++); } #endif /* !defined(_VSTORE_CONCPY) */ #if !defined(OPTION_NO_INLINE_VSTORE) || defined(_VSTORE_C) /*-------------------------------------------------------------------*/ /* Move characters using specified keys and address spaces */ /* */ /* Input: */ /* addr1 Effective address of first operand */ /* arn1 Access register number for first operand, */ /* or USE_PRIMARY_SPACE or USE_SECONDARY_SPACE */ /* key1 Bits 0-3=first operand access key, 4-7=zeroes */ /* addr2 Effective address of second operand */ /* arn2 Access register number for second operand, */ /* or USE_PRIMARY_SPACE or USE_SECONDARY_SPACE */ /* key2 Bits 0-3=second operand access key, 4-7=zeroes */ /* len Operand length minus 1 (range 0-255) */ /* regs Pointer to the CPU register context */ /* */ /* This function implements the MVC, MVCP, MVCS, MVCK, MVCSK, */ /* and MVCDK instructions. These instructions move up to 256 */ /* characters using the address space and key specified by */ /* the caller for each operand. Operands are moved byte by */ /* byte to ensure correct processing of overlapping operands. */ /* */ /* The arn parameter for each operand may be an access */ /* register number, in which case the operand is in the */ /* primary, secondary, or home space, or in the space */ /* designated by the specified access register, according to */ /* the current PSW addressing mode. */ /* */ /* Alternatively the arn parameter may be one of the special */ /* values USE_PRIMARY_SPACE or USE_SECONDARY_SPACE in which */ /* case the operand is in the specified space regardless of */ /* the current PSW addressing mode. */ /* */ /* A program check may be generated if either logical address */ /* causes an addressing, protection, or translation exception, */ /* and in this case the function does not return. */ /*-------------------------------------------------------------------*/ _VSTORE_C_STATIC void ARCH_DEP(move_chars) (VADR addr1, int arn1, BYTE key1, VADR addr2, int arn2, BYTE key2, int len, REGS *regs) { BYTE *dest1, *dest2; /* Destination addresses */ BYTE *source1, *source2; /* Source addresses */ BYTE *sk1, *sk2; /* Storage key addresses */ int len2, len3; /* Lengths to copy */ ITIMER_SYNC(addr2,len,regs); /* Quick out if copying just 1 byte */ if (unlikely(len == 0)) { source1 = MADDR (addr2, arn2, regs, ACCTYPE_READ, key2); dest1 = MADDR (addr1, arn1, regs, ACCTYPE_WRITE, key1); *dest1 = *source1; ITIMER_UPDATE(addr1,len,regs); return; } /* Translate addresses of leftmost operand bytes */ source1 = MADDR (addr2, arn2, regs, ACCTYPE_READ, key2); dest1 = MADDR (addr1, arn1, regs, ACCTYPE_WRITE_SKP, key1); sk1 = regs->dat.storkey; /* There are several scenarios (in optimal order): * (1) dest boundary and source boundary not crossed * (2) dest boundary not crossed and source boundary crossed * (3) dest boundary crossed and source boundary not crossed * (4) dest boundary and source boundary are crossed * (a) dest and source boundary cross at the same time * (b) dest boundary crossed first * (c) source boundary crossed first * Note: since the operand length is limited to 256 bytes, * neither operand can cross more than one 2K boundary. */ if ( NOCROSS2K(addr1,len) ) { if ( NOCROSS2K(addr2,len) ) { /* (1) - No boundaries are crossed */ concpy (regs, dest1, source1, len + 1); } else { /* (2) - Second operand crosses a boundary */ len2 = 0x800 - (addr2 & 0x7FF); source2 = MADDR ((addr2 + len2) & ADDRESS_MAXWRAP(regs), arn2, regs, ACCTYPE_READ, key2); concpy (regs, dest1, source1, len2); concpy (regs, dest1 + len2, source2, len - len2 + 1); } *sk1 |= (STORKEY_REF | STORKEY_CHANGE); } else { /* First operand crosses a boundary */ len2 = 0x800 - (addr1 & 0x7FF); dest2 = MADDR ((addr1 + len2) & ADDRESS_MAXWRAP(regs), arn1, regs, ACCTYPE_WRITE_SKP, key1); sk2 = regs->dat.storkey; if ( NOCROSS2K(addr2,len) ) { /* (3) - First operand crosses a boundary */ concpy (regs, dest1, source1, len2); concpy (regs, dest2, source1 + len2, len - len2 + 1); } else { /* (4) - Both operands cross a boundary */ len3 = 0x800 - (addr2 & 0x7FF); source2 = MADDR ((addr2 + len3) & ADDRESS_MAXWRAP(regs), arn2, regs, ACCTYPE_READ, key2); if (len2 == len3) { /* (4a) - Both operands cross at the same time */ concpy (regs, dest1, source1, len2); concpy (regs, dest2, source2, len - len2 + 1); } else if (len2 < len3) { /* (4b) - First operand crosses first */ concpy (regs, dest1, source1, len2); concpy (regs, dest2, source1 + len2, len3 - len2); concpy (regs, dest2 + len3 - len2, source2, len - len3 + 1); } else { /* (4c) - Second operand crosses first */ concpy (regs, dest1, source1, len3); concpy (regs, dest1 + len3, source2, len2 - len3); concpy (regs, dest2, source2 + len2 - len3, len - len2 + 1); } } *sk1 |= (STORKEY_REF | STORKEY_CHANGE); *sk2 |= (STORKEY_REF | STORKEY_CHANGE); } ITIMER_UPDATE(addr1,len,regs); } /* end function ARCH_DEP(move_chars) */ #if defined(FEATURE_MOVE_WITH_OPTIONAL_SPECIFICATIONS) /*-------------------------------------------------------------------*/ /* Move characters with optional specifications */ /* */ /* Input: */ /* addr1 Effective address of first operand */ /* space1 Address space for first operand: */ /* USE_PRIMARY_SPACE */ /* USE_SECONDARY_SPACE */ /* USE_ARMODE + access register number */ /* USE_HOME_SPACE */ /* key1 Bits 0-3=first operand access key, 4-7=zeroes */ /* addr2 Effective address of second operand */ /* space1 Address space for second operand (values as space1) */ /* key2 Bits 0-3=second operand access key, 4-7=zeroes */ /* len Operand length (range 0-4096) */ /* regs Pointer to the CPU register context */ /* */ /* This function implements the MVCOS instruction which moves */ /* up to 4096 characters using the address space and key */ /* specified by the caller for each operand. Results are */ /* unpredictable if destructive overlap exists. */ /* */ /* The space1 and space2 parameters force the use of the */ /* specified address space, or the use of the specified */ /* access register, regardless of the current PSW addressing */ /* mode. */ /* */ /* A program check may be generated if either logical address */ /* causes an addressing, protection, or translation exception, */ /* and in this case the function does not return. */ /*-------------------------------------------------------------------*/ _VSTORE_C_STATIC void ARCH_DEP(move_charx) (VADR addr1, int space1, BYTE key1, VADR addr2, int space2, BYTE key2, int len, REGS *regs) { BYTE *main1, *main2; /* Main storage pointers */ int len1, len2, len3; /* Work areas for lengths */ /* Ultra quick out if copying zero bytes */ if (unlikely(len == 0)) return; ITIMER_SYNC(addr2,len-1,regs); /* Quick out if copying just 1 byte */ if (unlikely(len == 1)) { main2 = MADDR (addr2, space2, regs, ACCTYPE_READ, key2); main1 = MADDR (addr1, space1, regs, ACCTYPE_WRITE, key1); *main1 = *main2; ITIMER_UPDATE(addr1,len-1,regs); return; } /* Translate addresses of leftmost operand bytes */ main2 = MADDR (addr2, space2, regs, ACCTYPE_READ, key2); main1 = MADDR (addr1, space1, regs, ACCTYPE_WRITE, key1); /* Copy the largest chunks which do not cross a 2K boundary of either source or destination operand */ while (len > 0) { /* Calculate distance to next 2K boundary */ len1 = NOCROSS2KL(addr1,len) ? len : (int)(0x800 - (addr1 & 0x7FF)); len2 = NOCROSS2KL(addr2,len) ? len : (int)(0x800 - (addr2 & 0x7FF)); len3 = len1 < len2 ? len1 : len2; /* Copy bytes from source to destination */ concpy (regs, main1, main2, len3); /* Calculate virtual addresses for next chunk */ addr1 = (addr1 + len3) & ADDRESS_MAXWRAP(regs); addr2 = (addr2 + len3) & ADDRESS_MAXWRAP(regs); /* Adjust remaining length */ len -= len3; /* Exit if no more bytes to move */ if (len == 0) break; /* Adjust addresses for start of next chunk, or translate again if a 2K boundary was crossed */ main2 = (addr2 & 0x7FF) ? main2 + len3 : MADDR (addr2, space2, regs, ACCTYPE_READ, key2); main1 = (addr1 & 0x7FF) ? main1 + len3 : MADDR (addr1, space1, regs, ACCTYPE_WRITE, key1); } /* end while(len) */ ITIMER_UPDATE(addr1,len-1,regs); } /* end function ARCH_DEP(move_charx) */ #endif /*defined(FEATURE_MOVE_WITH_OPTIONAL_SPECIFICATIONS)*/ /*-------------------------------------------------------------------*/ /* Validate operand for addressing, protection, translation */ /* */ /* Input: */ /* addr Effective address of operand */ /* arn Access register number */ /* len Operand length minus 1 (range 0-255) */ /* acctype Type of access requested: READ or WRITE */ /* regs Pointer to the CPU register context */ /* */ /* The purpose of this function is to allow an instruction */ /* operand to be validated for addressing, protection, and */ /* translation exceptions, thus allowing the instruction to */ /* be nullified or suppressed before any updates occur. */ /* */ /* A program check is generated if the operand causes an */ /* addressing, protection, or translation exception, and */ /* in this case the function does not return. */ /*-------------------------------------------------------------------*/ _VSTORE_C_STATIC void ARCH_DEP(validate_operand) (VADR addr, int arn, int len, int acctype, REGS *regs) { /* Translate address of leftmost operand byte */ MADDR (addr, arn, regs, acctype, regs->psw.pkey); /* Translate next page if boundary crossed */ if ( CROSS2K(addr,len) ) { MADDR ((addr + len) & ADDRESS_MAXWRAP(regs), arn, regs, acctype, regs->psw.pkey); } #ifdef FEATURE_INTERVAL_TIMER else ITIMER_SYNC(addr,len,regs); #endif /*FEATURE_INTERVAL_TIMER*/ } /* end function ARCH_DEP(validate_operand) */ #endif /*!defined(OPTION_NO_INLINE_VSTORE) || defined(_VSTORE_C)*/ hercules-3.07/w32chan.c000644 000765 000765 00000076425 11143760544 016377 0ustar00jmaynardjmaynard000000 000000 //////////////////////////////////////////////////////////////////////////////////// // w32chan.c Fish's new i/o scheduling logic //////////////////////////////////////////////////////////////////////////////////// // (c) Copyright "Fish" (David B. Trout), 2001-2009. Released under the Q Public License // (http://www.hercules-390.org/herclic.html) as modifications to Hercules. //////////////////////////////////////////////////////////////////////////////////// // $Id: w32chan.c 5127 2009-01-23 13:25:01Z bernard $ // // $Log$ // Revision 1.28 2007/11/30 14:54:33 jmaynard // Changed conmicro.cx to hercules-390.org or conmicro.com, as needed. // // Revision 1.27 2007/06/23 00:04:19 ivan // Update copyright notices to include current year (2007) // // Revision 1.26 2006/12/08 09:43:31 jj // Add CVS message log // #include "hstdinc.h" #define _W32CHAN_C_ #define _HENGINE_DLL_ #include "hercules.h" #include "w32chan.h" #if defined(OPTION_FISHIO) ///////////////////////////////////////////////////////////////////////////// // Internal scheduler helper macros... #if defined(FISH_HANG) #define LockScheduler() (FishHang_EnterCriticalSection(__FILE__,__LINE__,&IOSchedulerLock)) #define LockThreadParms(pThreadParms) (FishHang_EnterCriticalSection(__FILE__,__LINE__,&pThreadParms->IORequestListLock)) #define UnlockScheduler() (FishHang_LeaveCriticalSection(__FILE__,__LINE__,&IOSchedulerLock)) #define UnlockThreadParms(pThreadParms) (FishHang_LeaveCriticalSection(__FILE__,__LINE__,&pThreadParms->IORequestListLock)) #else #define LockScheduler() (EnterCriticalSection(&IOSchedulerLock)) #define LockThreadParms(pThreadParms) (EnterCriticalSection(&pThreadParms->IORequestListLock)) #define UnlockScheduler() (LeaveCriticalSection(&IOSchedulerLock)) #define UnlockThreadParms(pThreadParms) (LeaveCriticalSection(&pThreadParms->IORequestListLock)) #endif ///////////////////////////////////////////////////////////////////////////// // i/o scheduler variables... (some private, some externally visible) int ios_arch_mode = 0; // current architecture mode int ios_devthread_timeout = 30; // max device thread wait time int* ios_devthread_prio = NULL; // pointer to sysblk.devprio LIST_ENTRY ThreadListHeadListEntry; // anchor for DEVTHREADPARMS linked list CRITICAL_SECTION IOSchedulerLock; // lock for accessing above list // and below variables long ios_devtwait = 0; // #of threads currently idle int ios_devtnbr = 0; // #of threads currently active int ios_devthwm = 0; // max #of threads that WERE active int ios_devtmax = 0; // max #of threads there can be int ios_devtunavail = 0; // #of times 'idle' thread unavailable ///////////////////////////////////////////////////////////////////////////// // initialize i/o scheduler variables and work areas... void InitIOScheduler ( int arch_mode, // (for calling execute_ccw_chain) int* devt_prio, // (ptr to device thread priority) int devt_timeout, // (MAX_DEVICE_THREAD_IDLE_SECS) long devt_max // (maximum #of device threads allowed) ) { ios_arch_mode = arch_mode; ios_devthread_prio = devt_prio; ios_devthread_timeout = devt_timeout; ios_devtmax = devt_max; InitializeListHead(&ThreadListHeadListEntry); MyInitializeCriticalSection(&IOSchedulerLock); } ///////////////////////////////////////////////////////////////////////////// // device_thread parms block... typedef struct _DevThreadParms { DWORD dwThreadID; // device_thread thread id LIST_ENTRY ThreadListLinkingListEntry; // (just a link in the chain) HANDLE hShutdownEvent; // tells device thread to exit HANDLE hRequestQueuedEvent; // tells device thread it has work LIST_ENTRY IORequestListHeadListEntry; // anchor for DEVIOREQUEST list CRITICAL_SECTION IORequestListLock; // (for accessing above list) BOOL bThreadIsDead; // TRUE = thread has exited } DEVTHREADPARMS; ///////////////////////////////////////////////////////////////////////////// // i/o request block... typedef struct _DevIORequest { LIST_ENTRY IORequestListLinkingListEntry; // (just a link in the chain) void* pDevBlk; // (ptr to device block) int* pnDevPrio; // (ptr to device i/o priority) unsigned short wDevNum; // (device number for debugging) } DEVIOREQUEST; ///////////////////////////////////////////////////////////////////////////// // (forward references for some of our functions...) DEVTHREADPARMS* SelectDeviceThread(); DEVTHREADPARMS* CreateDeviceThread(unsigned short wDevNum); void AdjustThreadPriority(int* pCurPrio, int* pNewPrio); void* DeviceThread(void* pThreadParms); void RemoveDeadThreadsFromList(); void RemoveThisThreadFromOurList(DEVTHREADPARMS* pThreadParms); ///////////////////////////////////////////////////////////////////////////// // Schedule a DeviceThread for this i/o request... (called by the 'startio' // function whenever the startio or start subchannel instruction is executed) int ScheduleIORequest(void* pDevBlk, unsigned short wDevNum, int* pnDevPrio) { ///////////////////////////////////////////////////////////////// // PROGRAMMING NOTE: The various errors that can occur in this // function should probably be reported by returning cc1 with // 'channel control check' set (or something similar), but until // I can work out the details, I'm going to be lazy and just // return cc2 (subchannel busy) for now to allow the system to // retry the i/o request if it so desires. Hopefully the problem // was only intermittent and will work the second time around. ///////////////////////////////////////////////////////////////// DEVIOREQUEST* pIORequest; // ptr to i/o request DEVTHREADPARMS* pThreadParms; // ptr to device_thread parameters // Create an i/o request queue entry for this i/o request pIORequest = (DEVIOREQUEST*) malloc(sizeof(DEVIOREQUEST)); if (!pIORequest) { logmsg(_("HHCCP084E malloc(DEVIOREQUEST) failed; device=%4.4X, strerror=\"%s\"\n"), wDevNum,strerror(errno)); return 2; } InitializeListLink(&pIORequest->IORequestListLinkingListEntry); pIORequest->pDevBlk = pDevBlk; pIORequest->wDevNum = wDevNum; pIORequest->pnDevPrio = pnDevPrio; // Schedule a device_thread to process this i/o request LockScheduler(); // (lock scheduler vars) if (ios_devtmax < 0) { // Create new "one time only" thread each time... // (Note: the device thread's parms will automatically // be locked upon return if creation was successful.) RemoveDeadThreadsFromList(); // (prevent runaway list) if (!(pThreadParms = CreateDeviceThread(wDevNum))) { UnlockScheduler(); // (unlock scheduler vars) free(pIORequest); // (discard i/o request) return 2; // (return device busy) } } else { // Select a non-busy device thread to handle this i/o request... // (Note: the device thread's parms will automatically // be locked upon return if selection was successful.) if (!(pThreadParms = SelectDeviceThread())) { // All threads are currently busy or no threads exist yet. // Since the possibility of a deadlock[1] can easily occur if we schedule // an i/o request to a currently busy device thread[2], we have no choice // but to create another device thread. // [1] Not an actual programmatic deadlock of course, but nonetheless // a deadlock from the guest operating system's point of view. // [2] A curently busy device thread could easily have its channel program // suspended and thus would never see the queued request until such time // its suspended channel program was resumed and allowed to complete, and // if the request we queued (that would end up waiting to be processed // by the currently suspended device thread) just so happens to be one // that the operating system needs to have completed before it can resume // the currently suspended channel program, then the operating system will // obviously hang. (It would end up waiting for an i/o to complete that // would never complete until the currently suspended channel program was // resumed, which would never be resumed until the queued i/o completes, // which would never even be processed until the currently suspended // channel program is resumed ..... etc.) if (ios_devtmax && ios_devtnbr >= ios_devtmax) // max threads already created? { logmsg(_("HHCCP085W *WARNING* max device threads exceeded.\n")); ios_devtunavail++; // (count occurrences) } // Create a new device thread for this i/o request... // (Note: the device thread's parms will automatically // be locked upon return if creation was successful.) if (!(pThreadParms = CreateDeviceThread(wDevNum))) { UnlockScheduler(); // (unlock scheduler vars) free(pIORequest); // (discard i/o request) return 2; // (return device busy) } } } // (Note: the thread parms lock should still be held at this point) // Queue the i/o request to the selected device_thread's i/o request queue... InsertListTail(&pThreadParms->IORequestListHeadListEntry,&pIORequest->IORequestListLinkingListEntry); // Tell device_thread it has work (must do this while its request list is still // locked to prevent it from prematurely exiting in case it's just about to die) MySetEvent(pThreadParms->hRequestQueuedEvent); // Now unlock its request queue so it can process the request we just gave it UnlockThreadParms(pThreadParms); // (let it proceed) // We're done, so unlock the scheduler vars so another cpu thread // in the configuration can schedule and i/o request and then exit // back the the startio function... UnlockScheduler(); // (unlock vars and exit; we're done) return 0; // (success) } ///////////////////////////////////////////////////////////////////////////// // Select a non-busy DeviceThread... // NOTE! the IOSchedulerLock must be acquired before calling this function! // NOTE! the selected thread's parms will be locked upon return! DEVTHREADPARMS* SelectDeviceThread() { DEVTHREADPARMS* pThreadParms; // ptr to selected device thread LIST_ENTRY* pListEntry; // (work) pListEntry = ThreadListHeadListEntry.Flink; while (pListEntry != &ThreadListHeadListEntry) { pThreadParms = CONTAINING_RECORD(pListEntry,DEVTHREADPARMS,ThreadListLinkingListEntry); LockThreadParms(pThreadParms); // (freeze moving target) if (pThreadParms->bThreadIsDead) { UnlockThreadParms(pThreadParms); RemoveThisThreadFromOurList(pThreadParms); pListEntry = ThreadListHeadListEntry.Flink; continue; } if (!IsEventSet(pThreadParms->hRequestQueuedEvent)) { RemoveListEntry(pListEntry); InsertListTail(&ThreadListHeadListEntry,pListEntry); return pThreadParms; } UnlockThreadParms(pThreadParms); // (can't use this one) pListEntry = pListEntry->Flink; } return NULL; // (all of them are busy) } ///////////////////////////////////////////////////////////////////////////// // create a new device thread and add it to the list... // NOTE! the IOSchedulerLock must be acquired before calling this function! // NOTE! the created thread's parms will be locked upon return! DEVTHREADPARMS* CreateDeviceThread(unsigned short wDevNum) { DEVTHREADPARMS* pThreadParms; // ptr to returned device_thread parameters DWORD dwThreadID; // (work) pThreadParms = malloc(sizeof(DEVTHREADPARMS)); // (allocate structure) if (!pThreadParms) { logmsg(_("HHCCP086E malloc(DEVTHREADPARMS) failed; device=%4.4X, strerror=\"%s\"\n"), wDevNum,strerror(errno)); return NULL; // (error) } pThreadParms->hShutdownEvent = MyCreateEvent(NULL,TRUE,FALSE,NULL); if (!pThreadParms->hShutdownEvent) { logmsg(_("HHCCP087E CreateEvent(hShutdownEvent) failed; device=%4.4X, strerror=\"%s\"\n"), wDevNum,strerror(errno)); free(pThreadParms); return NULL; // (error) } pThreadParms->hRequestQueuedEvent = MyCreateEvent(NULL,TRUE,FALSE,NULL); if (!pThreadParms->hRequestQueuedEvent) { logmsg(_("HHCCP088E CreateEvent(hRequestQueuedEvent) failed; device=%4.4X, strerror=\"%s\"\n"), wDevNum,strerror(errno)); MyCloseHandle(pThreadParms->hShutdownEvent); free(pThreadParms); return NULL; // (error) } MyInitializeCriticalSection(&pThreadParms->IORequestListLock); InitializeListLink(&pThreadParms->ThreadListLinkingListEntry); InitializeListHead(&pThreadParms->IORequestListHeadListEntry); pThreadParms->bThreadIsDead = FALSE; pThreadParms->dwThreadID = 0; #ifdef FISH_HANG if (fthread_create(__FILE__,__LINE__,&dwThreadID,NULL,DeviceThread,pThreadParms,"DeviceThread") != 0) #else if (fthread_create(&dwThreadID,NULL,DeviceThread,pThreadParms,"DeviceThread") != 0) #endif { logmsg(_("HHCCP089E fthread_create(DeviceThread) failed; device=%4.4X, strerror=\"%s\"\n"), wDevNum,strerror(errno)); MyCloseHandle(pThreadParms->hShutdownEvent); MyCloseHandle(pThreadParms->hRequestQueuedEvent); MyDeleteCriticalSection(&pThreadParms->IORequestListLock); free(pThreadParms); return NULL; // (error) } // Add the newly created device_thread to the end of our list of managed threads. InsertListTail(&ThreadListHeadListEntry,&pThreadParms->ThreadListLinkingListEntry); if (++ios_devtnbr > ios_devthwm) ios_devthwm = ios_devtnbr; LockThreadParms(pThreadParms); // (lock thread parms before using) return pThreadParms; // (success) } ///////////////////////////////////////////////////////////////////////////// // helper function to set a thread's priority to its proper value void AdjustThreadPriority(int* pCurPrio, int* pNewPrio) { if (*pCurPrio != *pNewPrio) { setpriority(PRIO_PROCESS, 0, *pNewPrio); *pCurPrio = *pNewPrio; } } ///////////////////////////////////////////////////////////////////////////// // the device_thread itself... (processes queued i/o request // by calling "execute_ccw_chain" function in channel.c...) extern void call_execute_ccw_chain(int arch_mode, void* pDevBlk); void* DeviceThread (void* pArg) { DEVTHREADPARMS* pThreadParms; // ptr to thread parms LIST_ENTRY* pListEntry; // (work) DEVIOREQUEST* pIORequest; // ptr to i/o request void* pDevBlk; // ptr to device block int* pnDevPrio; // ptr to device i/o priority int nCurPrio; // current thread priority pThreadParms = (DEVTHREADPARMS*) pArg; pThreadParms->dwThreadID = GetCurrentThreadId(); nCurPrio = getpriority(PRIO_PROCESS, 0); AdjustThreadPriority(&nCurPrio,ios_devthread_prio); for (;;) { // Wait for an i/o request to be queued... InterlockedIncrement(&ios_devtwait); MyWaitForSingleObject(pThreadParms->hRequestQueuedEvent,ios_devthread_timeout * 1000); InterlockedDecrement(&ios_devtwait); if (IsEventSet(pThreadParms->hShutdownEvent)) break; // Lock our queue so it doesn't change while we take a look at it... LockThreadParms(pThreadParms); // (freeze moving target) // Check to see if we have any work... if (IsListEmpty(&pThreadParms->IORequestListHeadListEntry)) { // We've waited long enough... pThreadParms->bThreadIsDead = TRUE; // (keep scheduler informed) UnlockThreadParms(pThreadParms); // (let go of our parms block) return NULL; // (return, NOT break!) } // Remove the i/o request from our queue... // It's important that we remove the request from our queue but // NOT reset our flag (if the list is now empty) until AFTER we've // processed the request (see further below for details as to why). pListEntry = RemoveListHead(&pThreadParms->IORequestListHeadListEntry); UnlockThreadParms(pThreadParms); // (done with thread parms for now) pIORequest = CONTAINING_RECORD(pListEntry,DEVIOREQUEST,IORequestListLinkingListEntry); pDevBlk = pIORequest->pDevBlk; // (need ptr to devblk) pnDevPrio = pIORequest->pnDevPrio; // (need ptr to devprio) free(pIORequest); // (not needed anymore) // Process the i/o request by calling the proper 'execute_ccw_chain' // function (based on architectural mode) in source module channel.c // Set thread priority to requested device level AdjustThreadPriority(&nCurPrio,pnDevPrio); call_execute_ccw_chain(ios_arch_mode, pDevBlk); // (process i/o request) // Reset thread priority, if necessary if (nCurPrio > *ios_devthread_prio) AdjustThreadPriority(&nCurPrio,ios_devthread_prio); //////////////////////////////////////////////////////////////////////////// // // * * * I M P O R T A N T * * * // // It's important that we reset our flag AFTER we're done with our request // in order to prevent the scheduler from trying to give us more work while // we're still busy processing the current i/o request (in case the channel // program we're processing gets suspended). If the channel program we're // processing gets suspended and the scheduler places another request in our // queue, it won't ever get processed until our suspended channel program is // resumed, and if the request that was placed in our queue was a request // for an i/o to another device that the operating system needs to complete // in order to obtain the information needed to resume our suspended channel // program, a deadlock will occur! (i.e. if the operating system needs to // read data from another device before it can resume our channel program, // then the i/o request to read from that device better not be given to us // because we're suspended and will never get around to executing it until // we're resumed, which will never happen until the i/o request waiting in // our queue is completed, which will never happend until we're resumed, // etc...) // //////////////////////////////////////////////////////////////////////////// // Now that we're done this i/o, reset our flag. LockThreadParms(pThreadParms); // (freeze moving target) if (IsListEmpty(&pThreadParms->IORequestListHeadListEntry)) MyResetEvent(pThreadParms->hRequestQueuedEvent); UnlockThreadParms(pThreadParms); // (thaw moving target) if (IsEventSet(pThreadParms->hShutdownEvent)) break; // If we're a "one time only" thread, then we're done. if (ios_devtmax < 0) { // Note: no need to lock our thread parms before setting 'dead' flag // since the scheduler should never queue us another request anyway // because we're a "one-time-only" thread. pThreadParms->bThreadIsDead = TRUE; // (let garbage collector discard us) return NULL; // (return, NOT break!) } } // The only time we reach here is if the shutdown event was signalled (i.e. we // were manually "cancelled" or asked to stop processing; i.e. the i/o subsystem // was reset). Discard all i/o requests that may still be remaining in our queue. TRACE("** DeviceThread %8.8X: shutdown detected\n", (unsigned int)pThreadParms->dwThreadID); LockThreadParms(pThreadParms); // (freeze moving target) // Discard all queued i/o requests... while (!IsListEmpty(&pThreadParms->IORequestListHeadListEntry)) { pListEntry = RemoveListHead(&pThreadParms->IORequestListHeadListEntry); pIORequest = CONTAINING_RECORD(pListEntry,DEVIOREQUEST,IORequestListLinkingListEntry); TRACE("** DeviceThread %8.8X: discarding i/o request for device %4.4X\n", (unsigned int)pThreadParms->dwThreadID,pIORequest->wDevNum); free(pIORequest); } pThreadParms->bThreadIsDead = TRUE; // (tell scheduler we've died) TRACE("** DeviceThread %8.8X: shutdown complete\n", (unsigned int)pThreadParms->dwThreadID); UnlockThreadParms(pThreadParms); // (thaw moving target) return NULL; } ///////////////////////////////////////////////////////////////////////////// // shutdown idle threads (if possible) until number drops below threshold... void TrimDeviceThreads() { DEVTHREADPARMS* pThreadParms; BOOL bThreadIsBusy; LIST_ENTRY* pListEntry; LockScheduler(); // (lock scheduler vars) pListEntry = ThreadListHeadListEntry.Flink; while (pListEntry != &ThreadListHeadListEntry && ios_devtnbr > ios_devtmax) { pThreadParms = CONTAINING_RECORD(pListEntry,DEVTHREADPARMS,ThreadListLinkingListEntry); pListEntry = pListEntry->Flink; LockThreadParms(pThreadParms); bThreadIsBusy = IsEventSet(pThreadParms->hRequestQueuedEvent); UnlockThreadParms(pThreadParms); if (bThreadIsBusy) continue; // Thread is currently idle and awaiting work. Tell it to exit. // (Note: we need to signal the hRequestQueuedEvent event too so that // it can wake up and notice that the hShutdownEvent event is signaled) MySetEvent(pThreadParms->hShutdownEvent); MySetEvent(pThreadParms->hRequestQueuedEvent); // (wakeup thread) Sleep(10); // (give it time to die) RemoveDeadThreadsFromList(); } UnlockScheduler(); // (unlock shceduler vars) } #if 0 // (the following is not needed yet) ///////////////////////////////////////////////////////////////////////////// // ask all device_threads to exit... (i.e. i/o subsystem reset) void KillAllDeviceThreads() { DEVTHREADPARMS* pThreadParms; LIST_ENTRY* pListEntry; TRACE("** ENTRY KillAllDeviceThreads\n"); LockScheduler(); // (lock scheduler vars) RemoveDeadThreadsFromList(); // (discard dead threads) while (!IsListEmpty(&ThreadListHeadListEntry)) { pListEntry = ThreadListHeadListEntry.Flink; // (get starting link in chain) while (pListEntry != &ThreadListHeadListEntry) // (while not end of chain reached...) { pThreadParms = CONTAINING_RECORD(pListEntry,DEVTHREADPARMS,ThreadListLinkingListEntry); // (Note: we need to signal the hRequestQueuedEvent event too so that // it can wake up and notice that the hShutdownEvent event is signaled) TRACE("** KillAllDeviceThreads: setting shutdown event for thread %8.8X\n", pThreadParms->dwThreadID); LockThreadParms(pThreadParms); // (lock thread parms) MySetEvent(pThreadParms->hShutdownEvent); // (request shutdown) MySetEvent(pThreadParms->hRequestQueuedEvent); // (wakeup thread) UnlockThreadParms(pThreadParms); // (unlock thread parms) pListEntry = pListEntry->Flink; // (go on to next link in chain) } UnlockScheduler(); // (unlock scheduler vars) TRACE("** KillAllDeviceThreads: waiting for thread(s) to shutdown\n"); Sleep(10); // (give them time to die) LockScheduler(); // (re-lock scheduler vars) RemoveDeadThreadsFromList(); // (discard dead threads) } UnlockScheduler(); // (unlock scheduler vars) TRACE("** EXIT KillAllDeviceThreads\n"); } #endif // (the preceding is not needed yet) ///////////////////////////////////////////////////////////////////////////// // remove all dead threads from our list of threads... // NOTE! the IOSchedulerLock must be acquired before calling this function! void RemoveDeadThreadsFromList() { DEVTHREADPARMS* pThreadParms; BOOL bThreadIsDead; LIST_ENTRY* pListEntry = ThreadListHeadListEntry.Flink; while (pListEntry != &ThreadListHeadListEntry) { pThreadParms = CONTAINING_RECORD(pListEntry,DEVTHREADPARMS,ThreadListLinkingListEntry); pListEntry = pListEntry->Flink; LockThreadParms(pThreadParms); bThreadIsDead = pThreadParms->bThreadIsDead; UnlockThreadParms(pThreadParms); if (bThreadIsDead) RemoveThisThreadFromOurList(pThreadParms); } } ///////////////////////////////////////////////////////////////////////////// // private function to remove an entry from our list and discard it... // NOTE! the IOSchedulerLock must be acquired before calling this function! void RemoveThisThreadFromOurList(DEVTHREADPARMS* pThreadParms) { RemoveListEntry(&pThreadParms->ThreadListLinkingListEntry); MyCloseHandle(pThreadParms->hShutdownEvent); MyCloseHandle(pThreadParms->hRequestQueuedEvent); MyDeleteCriticalSection(&pThreadParms->IORequestListLock); free(pThreadParms); ios_devtnbr--; // (track number of active device_thread) } ///////////////////////////////////////////////////////////////////////////// // Debugging... #if defined(FISH_HANG) char PrintDEVIOREQUESTBuffer[2048]; char* PrintDEVIOREQUEST(DEVIOREQUEST* pIORequest, DEVTHREADPARMS* pDEVTHREADPARMS) { LIST_ENTRY* pListEntry; DEVIOREQUEST* pNextDEVIOREQUEST; pListEntry = pIORequest->IORequestListLinkingListEntry.Flink; if (pListEntry != &pDEVTHREADPARMS->IORequestListHeadListEntry) { pNextDEVIOREQUEST = CONTAINING_RECORD(pListEntry,DEVIOREQUEST,IORequestListLinkingListEntry); } else pNextDEVIOREQUEST = (DEVIOREQUEST*) &pDEVTHREADPARMS->IORequestListHeadListEntry; snprintf(PrintDEVIOREQUESTBuffer,sizeof(PrintDEVIOREQUESTBuffer), "DEVIOREQUEST @ %8.8X\n" " pDevBlk = %8.8X\n" " wDevNum = %4.4X\n" " IORequestListLinkingListEntry = %8.8X\n", (int)pIORequest, (int)pIORequest->pDevBlk, pIORequest->wDevNum, (int)pNextDEVIOREQUEST ); PrintDEVIOREQUESTBuffer[ sizeof(PrintDEVIOREQUESTBuffer) - 1 ] = 0; return PrintDEVIOREQUESTBuffer; } ///////////////////////////////////////////////////////////////////////////// void PrintAllDEVIOREQUESTs(DEVTHREADPARMS* pDEVTHREADPARMS) { DEVIOREQUEST* pDEVIOREQUEST; LIST_ENTRY* pListEntry; pListEntry = pDEVTHREADPARMS->IORequestListHeadListEntry.Flink; while (pListEntry != &pDEVTHREADPARMS->IORequestListHeadListEntry) { pDEVIOREQUEST = CONTAINING_RECORD(pListEntry,DEVIOREQUEST,IORequestListLinkingListEntry); pListEntry = pListEntry->Flink; FishHang_Printf("%s\n",PrintDEVIOREQUEST(pDEVIOREQUEST,pDEVTHREADPARMS)); } } ///////////////////////////////////////////////////////////////////////////// char PrintDEVTHREADPARMSBuffer[4096]; char* PrintDEVTHREADPARMS(DEVTHREADPARMS* pDEVTHREADPARMS) { LIST_ENTRY* pListEntry; DEVIOREQUEST* pDEVIOREQUEST; DEVTHREADPARMS* pNextDEVTHREADPARMS; pListEntry = pDEVTHREADPARMS->IORequestListHeadListEntry.Flink; if (pListEntry != &pDEVTHREADPARMS->IORequestListHeadListEntry) { pDEVIOREQUEST = CONTAINING_RECORD(pListEntry,DEVIOREQUEST,IORequestListLinkingListEntry); } else pDEVIOREQUEST = NULL; pListEntry = pDEVTHREADPARMS->ThreadListLinkingListEntry.Flink; if (pListEntry != &ThreadListHeadListEntry) { pNextDEVTHREADPARMS = CONTAINING_RECORD(pListEntry,DEVTHREADPARMS,ThreadListLinkingListEntry); } else pNextDEVTHREADPARMS = (DEVTHREADPARMS*) &ThreadListHeadListEntry; snprintf(PrintDEVTHREADPARMSBuffer,sizeof(PrintDEVTHREADPARMSBuffer), "DEVTHREADPARMS @ %8.8X\n" " dwThreadID = %8.8X\n" " bThreadIsDead = %s\n" " hShutdownEvent = %8.8X %s\n" " hRequestQueuedEvent = %8.8X %s\n" " IORequestListHeadListEntry = %8.8X\n" " ThreadListLinkingListEntry = %8.8X\n" ,(int)pDEVTHREADPARMS ,(int)pDEVTHREADPARMS->dwThreadID ,pDEVTHREADPARMS->bThreadIsDead ? "TRUE" : "false" ,(unsigned int)pDEVTHREADPARMS->hShutdownEvent , IsEventSet(pDEVTHREADPARMS->hShutdownEvent) ? "** SIGNALED **" : "(not signaled)" ,(unsigned int)pDEVTHREADPARMS->hRequestQueuedEvent , IsEventSet(pDEVTHREADPARMS->hRequestQueuedEvent) ? "** SIGNALED **" : "(not signaled)" ,(int)pDEVIOREQUEST ,(int)pNextDEVTHREADPARMS ); PrintDEVTHREADPARMSBuffer[ sizeof(PrintDEVTHREADPARMSBuffer) - 1 ] = 0; return PrintDEVTHREADPARMSBuffer; } ///////////////////////////////////////////////////////////////////////////// // (called by panel.c "FishHangReport" command...) void PrintAllDEVTHREADPARMSs() { LIST_ENTRY* pListEntry; DEVTHREADPARMS* pDEVTHREADPARMS; LockScheduler(); pListEntry = ThreadListHeadListEntry.Flink; if (pListEntry != &ThreadListHeadListEntry) { pDEVTHREADPARMS = CONTAINING_RECORD(pListEntry,DEVTHREADPARMS,ThreadListLinkingListEntry); } else pDEVTHREADPARMS = (DEVTHREADPARMS*) &ThreadListHeadListEntry; FishHang_Printf("\nDEVTHREADPARMS LIST ANCHOR @ %8.8X --> %8.8X\n\n", (int)&ThreadListHeadListEntry,(int)pDEVTHREADPARMS); while (pListEntry != &ThreadListHeadListEntry) { pDEVTHREADPARMS = CONTAINING_RECORD(pListEntry,DEVTHREADPARMS,ThreadListLinkingListEntry); LockThreadParms(pDEVTHREADPARMS); FishHang_Printf("%s\n",PrintDEVTHREADPARMS(pDEVTHREADPARMS)); PrintAllDEVIOREQUESTs(pDEVTHREADPARMS); UnlockThreadParms(pDEVTHREADPARMS); pListEntry = pListEntry->Flink; } UnlockScheduler(); } ///////////////////////////////////////////////////////////////////////////// #endif // defined(FISH_HANG) ///////////////////////////////////////////////////////////////////////////// #endif // !defined(OPTION_FISHIO) hercules-3.07/w32chan.h000644 000765 000765 00000004610 11143760544 016367 0ustar00jmaynardjmaynard000000 000000 //////////////////////////////////////////////////////////////////////////////////// // w32chan.h Fish's new i/o scheduling logic //////////////////////////////////////////////////////////////////////////////////// // (c) Copyright "Fish" (David B. Trout), 2001-2009. Released under the Q Public License // (http://www.hercules-390.org/herclic.html) as modifications to Hercules. //////////////////////////////////////////////////////////////////////////////////// // $Id: w32chan.h 5127 2009-01-23 13:25:01Z bernard $ // // $Log$ // Revision 1.15 2007/11/30 14:54:33 jmaynard // Changed conmicro.cx to hercules-390.org or conmicro.com, as needed. // // Revision 1.14 2007/06/23 00:04:19 ivan // Update copyright notices to include current year (2007) // // Revision 1.13 2006/12/08 09:43:31 jj // Add CVS message log // #ifndef _W32CHANN_H_ #define _W32CHANN_H_ ///////////////////////////////////////////////////////////////////////////// // I/O Scheduler functions... extern void InitIOScheduler // initialize i/o scheduler vars // Only call this function ONCE -- at startup! From // then on, just set the variables directly as needed. ( int arch_mode, // (for calling execute_ccw_chain) int* devt_prio, // (ptr to device thread priority) int devt_timeout, // (maximum device thread wait time) long devt_max // (maximum #of device threads allowed) ); extern int ScheduleIORequest(void* pDevBlk, unsigned short wDevNum, int* pnDevPrio); extern void TrimDeviceThreads(); extern void KillAllDeviceThreads(); ///////////////////////////////////////////////////////////////////////////// // Debugging... (called by panel.c "FishHangReport" command...) #if defined(FISH_HANG) extern void PrintAllDEVTHREADPARMSs(); #endif // defined(FISH_HANG) ///////////////////////////////////////////////////////////////////////////// // I/O Scheduler variables... extern long ios_devtwait; // #of threads currently idle extern int ios_devtnbr; // #of threads currently active extern int ios_devthwm; // max #of threads that WERE active extern int ios_devtmax; // max #of threads there can be extern int ios_devtunavail; // #of times 'idle' thread unavailable extern int ios_arch_mode; // architectural mode ///////////////////////////////////////////////////////////////////////////// #endif // _W32CHANN_H_ hercules-3.07/w32ctca.c000644 000765 000765 00000036525 11224164171 016367 0ustar00jmaynardjmaynard000000 000000 //////////////////////////////////////////////////////////////////////////////////// // w32ctca.c CTCI-W32 (Channel to Channel link to Win32 TCP/IP stack) //////////////////////////////////////////////////////////////////////////////////// // (c) Copyright "Fish" (David B. Trout), 2002-2009. Released under the Q Public License // (http://www.hercules-390.org/herclic.html) as modifications to Hercules. //////////////////////////////////////////////////////////////////////////////////// // $Id: w32ctca.c 5368 2009-06-02 03:58:49Z fish $ // // $Log$ // Revision 1.26 2007/11/30 14:54:33 jmaynard // Changed conmicro.cx to hercules-390.org or conmicro.com, as needed. // // Revision 1.25 2007/06/23 00:04:19 ivan // Update copyright notices to include current year (2007) // // Revision 1.24 2006/12/08 09:43:31 jj // Add CVS message log // #include "hstdinc.h" #include "hercules.h" #if !defined(OPTION_W32_CTCI) int w32ctca_dummy = 0; #else // defined(OPTION_W32_CTCI) #include "w32ctca.h" #include "tt32api.h" // (exported TunTap32.dll functions) #ifdef __CYGWIN__ #include // (for cygwin_conv_to_full_win32_path) #endif /////////////////////////////////////////////////////////////////////////////////////////// // We prefer the '_ex' variety as they resolve the "no error" errno issue... // But if they're not available we'll settle for the older version... #define TT32_PROCADDRS( name ) \ \ ptuntap32_ ## name ## _ex g_tt32_pfn_ ## name ## _ex = NULL; \ ptuntap32_ ## name g_tt32_pfn_ ## name = NULL #define GET_TT32_PROCADDRS( name ) \ \ g_tt32_pfn_ ## name ## _ex = \ (ptuntap32_ ## name ## _ex ) GetProcAddress( g_tt32_hmoddll, \ "tuntap32_" # name "_ex" ); \ g_tt32_pfn_ ## name = \ (ptuntap32_ ## name ) GetProcAddress( g_tt32_hmoddll, \ "tuntap32_" # name ); if (! \ g_tt32_pfn_ ## name ) goto error /////////////////////////////////////////////////////////////////////////////////////////// // Global variables... #define TT32_DEFAULT_IFACE "00-00-5E-80-00-00" CRITICAL_SECTION g_tt32_lock; // (lock for accessing ALL below variables) char g_tt32_dllname [ MAX_TT32_DLLNAMELEN ] = {0}; HMODULE g_tt32_hmoddll = NULL; TT32_PROCADDRS ( open ); TT32_PROCADDRS ( close ); TT32_PROCADDRS ( read ); TT32_PROCADDRS ( write ); TT32_PROCADDRS ( ioctl ); TT32_PROCADDRS ( get_stats ); TT32_PROCADDRS ( get_default_iface ); TT32_PROCADDRS ( set_debug_output_func ); TT32_PROCADDRS ( version_string ); TT32_PROCADDRS ( version_numbers ); TT32_PROCADDRS ( copyright_string ); // (NOTE: the following function only exists in v3.0+) ptuntap32_build_herc_iface_mac g_tt32_pfn_build_herc_iface_mac = NULL; /////////////////////////////////////////////////////////////////////////////////////////// BOOL GetTT32ProcAddrs() { GET_TT32_PROCADDRS ( open ); GET_TT32_PROCADDRS ( close ); GET_TT32_PROCADDRS ( read ); GET_TT32_PROCADDRS ( write ); GET_TT32_PROCADDRS ( ioctl ); GET_TT32_PROCADDRS ( get_stats ); GET_TT32_PROCADDRS ( get_default_iface ); GET_TT32_PROCADDRS ( set_debug_output_func ); GET_TT32_PROCADDRS ( version_string ); GET_TT32_PROCADDRS ( version_numbers ); GET_TT32_PROCADDRS ( copyright_string ); // (NOTE: we don't NEED this function (since it's new to // v3.0+ of tuntap32) so it's okay if it doesn't exist) g_tt32_pfn_build_herc_iface_mac = (ptuntap32_build_herc_iface_mac ) GetProcAddress( g_tt32_hmoddll, "tuntap32_build_herc_iface_mac" ); LeaveCriticalSection(&g_tt32_lock); return TRUE; error: FreeLibrary( g_tt32_hmoddll ); g_tt32_hmoddll = NULL; logmsg( "** tt32_loaddll: One of the GetProcAddress calls failed\n" ); LeaveCriticalSection(&g_tt32_lock); return FALSE; } /////////////////////////////////////////////////////////////////////////////////////////// // Debug string output function for use by the TUNTAP32.DLL... void __cdecl tt32_output_debug_string( const char* debug_string ) { logmsg( "%s", debug_string ); } void enable_tt32_debug_tracing( int enable ) { // Pass to TunTap32 DLL a pointer to the function it can use to // display debug messages with. This function of our's (that we // are passing it a pointer to) will then display its debugging // message (string) on the Hercules console so we can see it. g_tt32_pfn_set_debug_output_func( enable ? &tt32_output_debug_string : NULL ); } /////////////////////////////////////////////////////////////////////////////////////////// // Load the TUNTAP32.DLL... BOOL tt32_loaddll() { char* pszDLLName; char tt32_dllname_in_buff [ MAX_PATH ]; char tt32_dllname_out_buff [ MAX_PATH ] = {0}; static int tt32_init_done = 0; if (!tt32_init_done) { InitializeCriticalSection( &g_tt32_lock ); tt32_init_done = 1; } EnterCriticalSection(&g_tt32_lock); if (g_tt32_hmoddll) { LeaveCriticalSection(&g_tt32_lock); return TRUE; } // First, determine the name of the DLL we should try loading... if ( !( pszDLLName = getenv( "HERCULES_IFC" ) ) ) pszDLLName = DEF_TT32_DLLNAME; ASSERT( pszDLLName && *pszDLLName ); // Then check to see if the "name" contains path information or not... if ( strchr( pszDLLName, '/' ) || strchr( pszDLLName, '\\' ) ) { // It's already a path... strlcpy( tt32_dllname_in_buff, pszDLLName, sizeof(tt32_dllname_in_buff) ); } else { // It's not a path, so make it one... strlcpy( tt32_dllname_in_buff, MODULESDIR, sizeof(tt32_dllname_in_buff) ); strlcat( tt32_dllname_in_buff, "/" , sizeof(tt32_dllname_in_buff) ); strlcat( tt32_dllname_in_buff, pszDLLName, sizeof(tt32_dllname_in_buff) ); } // Now convert it to a full path... // PROGRAMMING NOTE: It's important here to ensure that our end result is a path // with BACKWARD slashes in it and NOT forward slashes! LoadLibrary is one of the // few Win32 functions that cannot handle paths with forward slashes in it. For // 'open', etc, yeah, forward slashes are fine, but for LoadLibrary they're not! #ifdef _MSVC_ if ( !_fullpath( tt32_dllname_out_buff, tt32_dllname_in_buff, sizeof(tt32_dllname_out_buff) ) ) strlcpy( tt32_dllname_out_buff, tt32_dllname_in_buff, sizeof(tt32_dllname_out_buff) ); #else // (presumed cygwin) cygwin_conv_to_full_win32_path( tt32_dllname_in_buff, tt32_dllname_out_buff ); #endif // _MSVC_ tt32_dllname_out_buff[ sizeof(tt32_dllname_out_buff) - 1 ] = 0; // Finally, copy it to our global home for it... strlcpy( g_tt32_dllname, tt32_dllname_out_buff, sizeof(g_tt32_dllname) ); ASSERT(g_tt32_dllname[0]); g_tt32_hmoddll = LoadLibraryEx( g_tt32_dllname, NULL, LOAD_WITH_ALTERED_SEARCH_PATH ); if (!g_tt32_hmoddll) { // Try again WITHOUT the path this time... strlcpy( g_tt32_dllname, pszDLLName, sizeof(g_tt32_dllname) ); g_tt32_hmoddll = LoadLibraryEx( g_tt32_dllname, NULL, LOAD_WITH_ALTERED_SEARCH_PATH ); if (!g_tt32_hmoddll) { DWORD dwLastError = GetLastError(); LeaveCriticalSection(&g_tt32_lock); logmsg("** tt32_loaddll: LoadLibraryEx(\"%s\") failed; rc=%ld: %s\n", g_tt32_dllname,dwLastError,strerror(dwLastError)); return FALSE; } } // Resolve our required DLL entry-point variables... if (!GetTT32ProcAddrs()) return FALSE; logmsg("%s version %s initiated\n", g_tt32_dllname, g_tt32_pfn_version_string()); #if defined(DEBUG) || defined(_DEBUG) enable_tt32_debug_tracing(1); // (enable debug tracing by default for DEBUG builds) #endif return TRUE; } /////////////////////////////////////////////////////////////////////////////////////////// int tt32_open( char* pszGatewayDevice, int iFlags ) { int rc, errnum; if (!tt32_loaddll()) return -1; if (! g_tt32_pfn_open_ex ) return g_tt32_pfn_open ( pszGatewayDevice, iFlags ); rc = g_tt32_pfn_open_ex ( pszGatewayDevice, iFlags, &errnum ); errno = errnum; return rc; } /////////////////////////////////////////////////////////////////////////////////////////// int tt32_read( int fd, u_char* buffer, u_long size ) { int rc, errnum; if (!tt32_loaddll()) return -1; if (! g_tt32_pfn_read_ex ) return g_tt32_pfn_read ( fd, buffer, size ); rc = g_tt32_pfn_read_ex ( fd, buffer, size, &errnum ); errno = errnum; return rc; } /////////////////////////////////////////////////////////////////////////////////////////// int tt32_write( int fd, u_char* buffer, u_long size ) { int rc, errnum; if (!tt32_loaddll()) return -1; if (! g_tt32_pfn_write_ex ) return g_tt32_pfn_write ( fd, buffer, size ); rc = g_tt32_pfn_write_ex ( fd, buffer, size, &errnum ); errno = errnum; return rc; } /////////////////////////////////////////////////////////////////////////////////////////// int tt32_close( int fd ) { int rc, errnum; if (!tt32_loaddll()) return -1; #if defined(DEBUG) || defined(_DEBUG) display_tt32_stats(fd); #endif if (! g_tt32_pfn_close_ex ) return g_tt32_pfn_close ( fd ); rc = g_tt32_pfn_close_ex ( fd, &errnum ); errno = errnum; return rc; } /////////////////////////////////////////////////////////////////////////////////////////// int tt32_ioctl( int fd, int iRequest, char* argp ) { int rc, errnum; if (!tt32_loaddll()) return -1; if (! g_tt32_pfn_ioctl_ex ) return g_tt32_pfn_ioctl ( fd, iRequest, argp ); rc = g_tt32_pfn_ioctl_ex ( fd, iRequest, argp, &errnum ); errno = errnum; return rc; } /////////////////////////////////////////////////////////////////////////////////////////// const char* tt32_get_default_iface() { int errnum; const char* pszDefaultIFace = NULL; if (tt32_loaddll()) { if (! g_tt32_pfn_get_default_iface_ex ) pszDefaultIFace = g_tt32_pfn_get_default_iface (); else { pszDefaultIFace = g_tt32_pfn_get_default_iface_ex ( &errnum ); errno = errnum; } } return ( pszDefaultIFace ? pszDefaultIFace : TT32_DEFAULT_IFACE ); } /////////////////////////////////////////////////////////////////////////////////////////// int display_tt32_stats( int fd ) { int errnum; TT32STATS stats; if (!tt32_loaddll()) return -1; memset(&stats,0,sizeof(stats)); stats.dwStructSize = sizeof(stats); if (! g_tt32_pfn_get_stats_ex ) g_tt32_pfn_get_stats ( fd, &stats ); else { g_tt32_pfn_get_stats_ex ( fd, &stats, &errnum ); errno = errnum; } if (stats.dwStructSize >= sizeof(stats)) { // New version 3.3 stats logmsg ( "\n%s Statistics:\n\n" "Size of Kernel Hold Buffer: %5luK\n" "Size of DLL I/O Buffer: %5luK\n" "Maximum DLL I/O Bytes Received: %5luK\n\n" "%12" I64_FMT "d Total Write Calls\n" "%12" I64_FMT "d Total Write I/Os\n" "%12" I64_FMT "d Packets To All Zeroes MAC Written\n" "%12" I64_FMT "d Total Packets Written\n" "%12" I64_FMT "d Total Bytes Written\n\n" "%12" I64_FMT "d Total Read Calls\n" "%12" I64_FMT "d Total Read I/Os\n" "%12" I64_FMT "d Internally Handled ARP Packets\n" "%12" I64_FMT "d Packets From Ourself\n" "%12" I64_FMT "d Total Ignored Packets\n" "%12" I64_FMT "d Packets To All Zeroes MAC Read\n" "%12" I64_FMT "d Total Packets Read\n" "%12" I64_FMT "d Total Bytes Read\n\n" ,g_tt32_dllname ,(stats.dwKernelBuffSize + 1023) / 1024 ,(stats.dwReadBuffSize + 1023) / 1024 ,(stats.dwMaxBytesReceived + 1023) / 1024 ,stats.n64WriteCalls ,stats.n64WriteIOs ,stats.n64ZeroMACPacketsWritten ,stats.n64PacketsWritten ,stats.n64BytesWritten ,stats.n64ReadCalls ,stats.n64ReadIOs ,stats.n64InternalPackets ,stats.n64OwnPacketsIgnored ,stats.n64IgnoredPackets ,stats.n64ZeroMACPacketsRead ,stats.n64PacketsRead ,stats.n64BytesRead ); } else { // Old pre version 3.3 stats logmsg ( "\n%s Statistics:\n\n" "Size of Kernel Hold Buffer: %5luK\n" "Size of DLL I/O Buffer: %5luK\n" "Maximum DLL I/O Bytes Received: %5luK\n\n" "%12" I64_FMT "d Write Calls\n" "%12" I64_FMT "d Write I/Os\n" "%12" I64_FMT "d Read Calls\n" "%12" I64_FMT "d Read I/Os\n" "%12" I64_FMT "d Packets Read\n" "%12" I64_FMT "d Packets Written\n" "%12" I64_FMT "d Bytes Read\n" "%12" I64_FMT "d Bytes Written\n" "%12" I64_FMT "d Internal Packets\n" "%12" I64_FMT "d Ignored Packets\n\n" , g_tt32_dllname ,(stats.dwKernelBuffSize + 1023) / 1024 ,(stats.dwReadBuffSize + 1023) / 1024 ,(stats.dwMaxBytesReceived + 1023) / 1024 ,stats.n64WriteCalls ,stats.n64WriteIOs ,stats.n64ReadCalls ,stats.n64ReadIOs ,stats.n64PacketsRead ,stats.n64PacketsWritten ,stats.n64BytesRead ,stats.n64BytesWritten ,stats.n64InternalPackets ,stats.n64IgnoredPackets ); } return 0; } /////////////////////////////////////////////////////////////////////////////////////////// // BOOLEAN FUNCTION int tt32_build_herc_iface_mac ( BYTE* out_mac, const BYTE* in_ip ) { // We prefer to let TunTap32 do it for us (since IT'S the one // that decides what it should really be) but if they're using // an older version of TunTap32 that doesn't have the function // then we'll do it ourselves just like before... if (!g_tt32_pfn_build_herc_iface_mac) return 0; // (FALSE: must do it yourself) g_tt32_pfn_build_herc_iface_mac( out_mac, in_ip ); return 1; // (TRUE: ok we did it for you) } /////////////////////////////////////////////////////////////////////////////////////////// #endif // !defined(OPTION_W32_CTCI) /////////////////////////////////////////////////////////////////////////////////////////// hercules-3.07/w32ctca.h000644 000765 000765 00000003736 11224164171 016372 0ustar00jmaynardjmaynard000000 000000 //////////////////////////////////////////////////////////////////////////////////// // w32ctca.h CTCI-W32 (Channel to Channel link to Win32 TCP/IP stack) //////////////////////////////////////////////////////////////////////////////////// // (c) Copyright "Fish" (David B. Trout), 2002-2009. Released under the Q Public License // (http://www.hercules-390.org/herclic.html) as modifications to Hercules. //////////////////////////////////////////////////////////////////////////////////// // $Id: w32ctca.h 5368 2009-06-02 03:58:49Z fish $ // // $Log$ // Revision 1.16 2007/11/30 14:54:33 jmaynard // Changed conmicro.cx to hercules-390.org or conmicro.com, as needed. // // Revision 1.15 2007/06/23 00:04:19 ivan // Update copyright notices to include current year (2007) // // Revision 1.14 2006/12/08 09:43:32 jj // Add CVS message log // #ifndef _W32CTCA_H_ #define _W32CTCA_H_ #if defined(OPTION_W32_CTCI) #include "tt32api.h" // (#define TUNTAP32_DLLNAME) #define MAX_TT32_DLLNAMELEN (512) #define DEF_TT32_DLLNAME TUNTAP32_DLLNAME // (from tt32api.h) #ifndef MODULESDIR #define MODULESDIR "." // (i.e. "Current Directory") #endif extern char g_tt32_dllname [MAX_TT32_DLLNAMELEN]; extern void tt32_init ( ); extern int tt32_open ( char* pszGatewayDevice, int iFlags ); extern int tt32_read ( int fd, u_char* buffer, u_long size ); extern int tt32_write ( int fd, u_char* buffer, u_long size ); extern int tt32_close ( int fd ); extern int tt32_ioctl ( int fd, int iRequest, char* argp ); extern const char* tt32_get_default_iface (); extern int display_tt32_stats ( int fd ); extern void enable_tt32_debug_tracing( int enable ); // (boolean helper function) extern int tt32_build_herc_iface_mac ( BYTE* out_mac, const BYTE* in_ip ); #endif // defined(OPTION_W32_CTCI) #endif // _W32CTCA_H_ hercules-3.07/w32dl.h000644 000765 000765 00000001454 11143760543 016057 0ustar00jmaynardjmaynard000000 000000 /* W32DL.H (c) Copyright Jan Jaeger, 2004-2009 */ /* dlopen compat */ // $Id: w32dl.h 5127 2009-01-23 13:25:01Z bernard $ // // $Log$ // Revision 1.6 2007/06/23 00:04:19 ivan // Update copyright notices to include current year (2007) // // Revision 1.5 2006/12/08 09:43:33 jj // Add CVS message log // #ifndef _W32_DL_H #define _W32_DL_H #ifdef _WIN32 #define RTLD_NOW 0 #define dlopen(_name, _flags) \ (void*) ((_name) ? LoadLibrary((_name)) : GetModuleHandle( NULL ) ) #define dlsym(_handle, _symbol) \ (void*)GetProcAddress((HMODULE)(_handle), (_symbol)) #define dlclose(_handle) \ FreeLibrary((HMODULE)(_handle)) #define dlerror() \ ("(unknown)") #endif /* _WIN32 */ #endif /* _W32_DL_H */ hercules-3.07/w32mtio.h000644 000765 000765 00000040462 11143760543 016432 0ustar00jmaynardjmaynard000000 000000 //////////////////////////////////////////////////////////////////////////////////// // W32MTIO.H -- Win32 'mtio.h' (Magnetic Tape structures) // // (c) Copyright "Fish" (David B. Trout), 2005-2009. Released under // the Q Public License (http://www.hercules-390.org/herclic.html) // as modifications to Hercules. //////////////////////////////////////////////////////////////////////////////////// // // From the Koders.com (http://www.koders.com/) entry for // the Unununium(uuu) project (http://unununium.org/) which, // believe it or not, states their source code is COMPLETELY // FREE (i.e. no licensing restrictions AT ALL!). // Modified as needed by Fish for Hercules Win32 port. // Original filename: mtio.h; new filename: w32mtio.h // //////////////////////////////////////////////////////////////////////////////////// // $Id: w32mtio.h 5127 2009-01-23 13:25:01Z bernard $ // // $Log$ // Revision 1.7 2008/03/25 11:41:31 fish // SCSI TAPE MODS part 1: groundwork: non-functional changes: // rename some functions, comments, general restructuring, etc. // New source modules awstape.c, omatape.c, hettape.c and // tapeccws.c added, but not yet used (all will be used in a future // commit though when tapedev.c code is eventually split) // // Revision 1.6 2007/11/30 14:54:33 jmaynard // Changed conmicro.cx to hercules-390.org or conmicro.com, as needed. // // Revision 1.5 2007/06/23 00:04:19 ivan // Update copyright notices to include current year (2007) // // Revision 1.4 2006/12/08 09:43:33 jj // Add CVS message log // #ifndef _W32MTIO_H_ #define _W32MTIO_H_ #ifdef _MSVC_ // (Fish: only needed for MSVC) //#include // (Fish: not needed) #define _IOWR _IOW // (Fish: see 'winsock2.h') //__BEGIN_DECLS // (Fish: not needed) /* structure for MTIOCTOP - mag tape op command */ struct mtop { short int mt_op; /* operations defined below */ int mt_count; /* how many of them */ }; /* Magnetic Tape operations [Not all operations supported by all drivers]: */ #define MTRESET 0 /* +reset drive in case of problems */ #define MTFSF 1 /* forward space over FileMark, * position at first record of next file */ #define MTBSF 2 /* backward space FileMark (position before FM) */ #define MTFSR 3 /* forward space record */ #define MTBSR 4 /* backward space record */ #define MTWEOF 5 /* write an end-of-file record (mark) */ #define MTREW 6 /* rewind */ #define MTOFFL 7 /* rewind and put the drive offline (eject?) */ #define MTNOP 8 /* no op, set status only (read with MTIOCGET) */ #define MTRETEN 9 /* retension tape */ #define MTBSFM 10 /* +backward space FileMark, position at FM */ #define MTFSFM 11 /* +forward space FileMark, position at FM */ #define MTEOM 12 /* goto end of recorded media (for appending files). * MTEOM positions after the last FM, ready for * appending another file. */ #define MTERASE 13 /* erase tape -- be careful! */ #define MTRAS1 14 /* run self test 1 (nondestructive) */ #define MTRAS2 15 /* run self test 2 (destructive) */ #define MTRAS3 16 /* reserved for self test 3 */ #define MTEOTWARN 17 /* Fish: Warning Zone size (0 bytes == disable) */ /* Some BSD's only support an "MTEWARN" boolean */ #define MTEWARN MTEOTWARN /* (for transparency/portability) */ #define MTSETBLK 20 /* set block length (SCSI) */ #define MTSETDENSITY 21 /* set tape density (SCSI) */ #define MTSEEK 22 /* seek to block (Tandberg, etc.) */ #define MTTELL 23 /* tell block (Tandberg, etc.) */ #define MTSETDRVBUFFER 24 /* set the drive buffering according to SCSI-2 */ /* ordinary buffered operation with code 1 */ #define MTFSS 25 /* space forward over setmarks */ #define MTBSS 26 /* space backward over setmarks */ #define MTWSM 27 /* write setmarks */ #define MTLOCK 28 /* lock the drive door */ #define MTUNLOCK 29 /* unlock the drive door */ #define MTLOAD 30 /* execute the SCSI load command */ #define MTUNLOAD 31 /* execute the SCSI unload command */ #define MTCOMPRESSION 32 /* control compression with SCSI mode page 15 */ #define MTSETPART 33 /* Change the active tape partition */ #define MTMKPART 34 /* Format the tape with one or two partitions */ /* structure for MTIOCGET - mag tape get status command */ struct mtget { long int mt_type; /* type of magtape device */ long int mt_resid; /* residual count: (not sure) * number of bytes ignored, or * number of files not skipped, or * number of records not skipped. */ /* the following registers are device dependent */ long int mt_dsreg; /* status register */ long int mt_gstat; /* generic (device independent) status */ long int mt_erreg; /* error register */ /* The next two fields are not always used */ /* these really are daddr_t, but that is only declared with _BSD_SOURCE */ long mt_fileno; /* number of current file on tape */ long mt_blkno; /* current block number */ }; /* * Constants for mt_type. Not all of these are supported, * and these are not all of the ones that are supported. */ #define MT_ISUNKNOWN 0x01 #define MT_ISQIC02 0x02 /* Generic QIC-02 tape streamer */ #define MT_ISWT5150 0x03 /* Wangtek 5150EQ, QIC-150, QIC-02 */ #define MT_ISARCHIVE_5945L2 0x04 /* Archive 5945L-2, QIC-24, QIC-02? */ #define MT_ISCMSJ500 0x05 /* CMS Jumbo 500 (QIC-02?) */ #define MT_ISTDC3610 0x06 /* Tandberg 6310, QIC-24 */ #define MT_ISARCHIVE_VP60I 0x07 /* Archive VP60i, QIC-02 */ #define MT_ISARCHIVE_2150L 0x08 /* Archive Viper 2150L */ #define MT_ISARCHIVE_2060L 0x09 /* Archive Viper 2060L */ #define MT_ISARCHIVESC499 0x0A /* Archive SC-499 QIC-36 controller */ #define MT_ISQIC02_ALL_FEATURES 0x0F/* Generic QIC-02 with all features */ #define MT_ISWT5099EEN24 0x11 /* Wangtek 5099-een24, 60MB, QIC-24 */ #define MT_ISTEAC_MT2ST 0x12 /* Teac MT-2ST 155mb drive, Teac DC-1 card (Wangtek type) */ #define MT_ISEVEREX_FT40A 0x32 /* Everex FT40A (QIC-40) */ #define MT_ISDDS1 0x51 /* DDS device without partitions */ #define MT_ISDDS2 0x52 /* DDS device with partitions */ #define MT_ISONSTREAM_SC 0x61 /* OnStream SCSI tape drives (SC-x0) and SCSI emulated (DI, DP, USB) */ #define MT_ISSCSI1 0x71 /* Generic ANSI SCSI-1 tape unit */ #define MT_ISSCSI2 0x72 /* Generic ANSI SCSI-2 tape unit */ /* QIC-40/80/3010/3020 ftape supported drives. * 20bit vendor ID + 0x800000 (see ftape-vendors.h) */ #define MT_ISFTAPE_UNKNOWN 0x800000 /* obsolete */ #define MT_ISFTAPE_FLAG 0x800000 struct mt_tape_info { long int t_type; /* device type id (mt_type) */ char* t_name; /* descriptive name */ }; #define MT_TAPE_INFO { \ {MT_ISUNKNOWN, "Unknown type of tape device"}, \ {MT_ISQIC02, "Generic QIC-02 tape streamer"}, \ {MT_ISWT5150, "Wangtek 5150, QIC-150"}, \ {MT_ISARCHIVE_5945L2, "Archive 5945L-2"}, \ {MT_ISCMSJ500, "CMS Jumbo 500"}, \ {MT_ISTDC3610, "Tandberg TDC 3610, QIC-24"}, \ {MT_ISARCHIVE_VP60I, "Archive VP60i, QIC-02"}, \ {MT_ISARCHIVE_2150L, "Archive Viper 2150L"}, \ {MT_ISARCHIVE_2060L, "Archive Viper 2060L"}, \ {MT_ISARCHIVESC499, "Archive SC-499 QIC-36 controller"}, \ {MT_ISQIC02_ALL_FEATURES, "Generic QIC-02 tape, all features"}, \ {MT_ISWT5099EEN24, "Wangtek 5099-een24, 60MB"}, \ {MT_ISTEAC_MT2ST, "Teac MT-2ST 155mb data cassette drive"}, \ {MT_ISEVEREX_FT40A, "Everex FT40A, QIC-40"}, \ {MT_ISONSTREAM_SC, "OnStream SC-, DI-, DP-, or USB tape drive"}, \ {MT_ISSCSI1, "Generic SCSI-1 tape"}, \ {MT_ISSCSI2, "Generic SCSI-2 tape"}, \ {0, NULL} \ } /* structure for MTIOCPOS - mag tape get position command */ struct mtpos { long int mt_blkno; /* current block number */ }; /* structure for MTIOCGETCONFIG/MTIOCSETCONFIG primarily intended * as an interim solution for QIC-02 until DDI is fully implemented. */ struct mtconfiginfo { long int mt_type; /* drive type */ long int ifc_type; /* interface card type */ unsigned short int irqnr; /* IRQ number to use */ unsigned short int dmanr; /* DMA channel to use */ unsigned short int port; /* IO port base address */ unsigned long int debug; /* debugging flags */ unsigned int have_dens:1; unsigned int have_bsf:1; unsigned int have_fsr:1; unsigned int have_bsr:1; unsigned int have_eod:1; unsigned int have_seek:1; unsigned int have_tell:1; unsigned int have_ras1:1; unsigned int have_ras2:1; unsigned int have_ras3:1; unsigned int have_qfa:1; unsigned int pad1:5; char reserved[10]; }; /* structure for MTIOCVOLINFO, query information about the volume * currently positioned at (zftape) */ struct mtvolinfo { unsigned int mt_volno; /* vol-number */ unsigned int mt_blksz; /* blocksize used when recording */ unsigned int mt_rawsize; /* raw tape space consumed, in kb */ unsigned int mt_size; /* volume size after decompression, in kb */ unsigned int mt_cmpr:1; /* this volume has been compressed */ }; /* raw access to a floppy drive, read and write an arbitrary segment. * For ftape/zftape to support formatting etc. */ #define MT_FT_RD_SINGLE 0 #define MT_FT_RD_AHEAD 1 #define MT_FT_WR_ASYNC 0 /* start tape only when all buffers are full */ #define MT_FT_WR_MULTI 1 /* start tape, continue until buffers are empty */ #define MT_FT_WR_SINGLE 2 /* write a single segment and stop afterwards */ #define MT_FT_WR_DELETE 3 /* write deleted data marks, one segment at time */ struct mtftseg { unsigned int mt_segno; /* the segment to read or write */ unsigned int mt_mode; /* modes for read/write (sync/async etc.) */ int mt_result; /* result of r/w request, not of the ioctl */ void *mt_data; /* User space buffer: must be 29kb */ }; /* get tape capacity (ftape/zftape) */ struct mttapesize { unsigned long mt_capacity; /* entire, uncompressed capacity of a cartridge */ unsigned long mt_used; /* what has been used so far, raw uncompressed amount */ }; /* possible values of the ftfmt_op field */ #define FTFMT_SET_PARMS 1 /* set software parms */ #define FTFMT_GET_PARMS 2 /* get software parms */ #define FTFMT_FORMAT_TRACK 3 /* start formatting a tape track */ #define FTFMT_STATUS 4 /* monitor formatting a tape track */ #define FTFMT_VERIFY 5 /* verify the given segment */ struct ftfmtparms { unsigned char ft_qicstd; /* QIC-40/QIC-80/QIC-3010/QIC-3020 */ unsigned char ft_fmtcode; /* Refer to the QIC specs */ unsigned char ft_fhm; /* floppy head max */ unsigned char ft_ftm; /* floppy track max */ unsigned short ft_spt; /* segments per track */ unsigned short ft_tpc; /* tracks per cartridge */ }; struct ftfmttrack { unsigned int ft_track; /* track to format */ unsigned char ft_gap3; /* size of gap3, for FORMAT_TRK */ }; struct ftfmtstatus { unsigned int ft_segment; /* segment currently being formatted */ }; struct ftfmtverify { unsigned int ft_segment; /* segment to verify */ unsigned long ft_bsm; /* bsm as result of VERIFY cmd */ }; struct mtftformat { unsigned int fmt_op; /* operation to perform */ union fmt_arg { struct ftfmtparms fmt_parms; /* format parameters */ struct ftfmttrack fmt_track; /* ctrl while formatting */ struct ftfmtstatus fmt_status; struct ftfmtverify fmt_verify; /* for verifying */ } fmt_arg; }; /* mag tape io control commands */ #define MTIOCTOP _IOW('m', 1, struct mtop) /* do a mag tape op */ #define MTIOCGET _IOR('m', 2, struct mtget) /* get tape status */ #define MTIOCPOS _IOR('m', 3, struct mtpos) /* get tape position */ /* The next two are used by the QIC-02 driver for runtime reconfiguration. * See tpqic02.h for struct mtconfiginfo. */ #define MTIOCGETCONFIG _IOR('m', 4, struct mtconfiginfo) /* get tape config */ #define MTIOCSETCONFIG _IOW('m', 5, struct mtconfiginfo) /* set tape config */ /* the next six are used by the floppy ftape drivers and its frontends * sorry, but MTIOCTOP commands are write only. */ #define MTIOCRDFTSEG _IOWR('m', 6, struct mtftseg) /* read a segment */ #define MTIOCWRFTSEG _IOWR('m', 7, struct mtftseg) /* write a segment */ #define MTIOCVOLINFO _IOR('m', 8, struct mtvolinfo) /* info about volume */ #define MTIOCGETSIZE _IOR('m', 9, struct mttapesize) /* get cartridge size*/ #define MTIOCFTFORMAT _IOWR('m', 10, struct mtftformat) /* format ftape */ #define MTIOCFTCMD _IOWR('m', 11, struct mtftcmd) /* send QIC-117 cmd */ /* Generic Mag Tape (device independent) status macros for examining * mt_gstat -- HP-UX compatible. * There is room for more generic status bits here, but I don't * know which of them are reserved. At least three or so should * be added to make this really useful. */ #define GMT_EOF(x) ((x) & 0x80000000) #define GMT_BOT(x) ((x) & 0x40000000) #define GMT_EOT(x) ((x) & 0x20000000) #define GMT_SM(x) ((x) & 0x10000000) /* DDS setmark */ #define GMT_EOD(x) ((x) & 0x08000000) /* DDS EOD */ #define GMT_WR_PROT(x) ((x) & 0x04000000) /* #define GMT_ ? ((x) & 0x02000000) */ #define GMT_ONLINE(x) ((x) & 0x01000000) #define GMT_D_6250(x) ((x) & 0x00800000) #define GMT_D_1600(x) ((x) & 0x00400000) #define GMT_D_800(x) ((x) & 0x00200000) /* #define GMT_ ? ((x) & 0x00100000) */ /* #define GMT_ ? ((x) & 0x00080000) */ #define GMT_DR_OPEN(x) ((x) & 0x00040000) /* door open (no tape) */ /* #define GMT_ ? ((x) & 0x00020000) */ #define GMT_IM_REP_EN(x) ((x) & 0x00010000) /* immediate report mode */ /* 16 generic status bits unused */ /* SCSI-tape specific definitions */ /* Bitfield shifts in the status */ #define MT_ST_BLKSIZE_SHIFT 0 #define MT_ST_BLKSIZE_MASK 0xffffff #define MT_ST_DENSITY_SHIFT 24 #define MT_ST_DENSITY_MASK 0xff000000 #define MT_ST_SOFTERR_SHIFT 0 #define MT_ST_SOFTERR_MASK 0xffff /* Bitfields for the MTSETDRVBUFFER ioctl */ #define MT_ST_OPTIONS 0xf0000000 #define MT_ST_BOOLEANS 0x10000000 #define MT_ST_SETBOOLEANS 0x30000000 #define MT_ST_CLEARBOOLEANS 0x40000000 #define MT_ST_WRITE_THRESHOLD 0x20000000 #define MT_ST_DEF_BLKSIZE 0x50000000 #define MT_ST_DEF_OPTIONS 0x60000000 #define MT_ST_TIMEOUTS 0x70000000 #define MT_ST_SET_TIMEOUT (MT_ST_TIMEOUTS | 0x000000) #define MT_ST_SET_LONG_TIMEOUT (MT_ST_TIMEOUTS | 0x100000) #define MT_ST_BUFFER_WRITES 0x0001 #define MT_ST_ASYNC_WRITES 0x0002 #define MT_ST_READ_AHEAD 0x0004 #define MT_ST_DEBUGGING 0x0008 #define MT_ST_TWO_FM 0x0010 #define MT_ST_FAST_MTEOM 0x0020 #define MT_ST_AUTO_LOCK 0x0040 #define MT_ST_DEF_WRITES 0x0080 #define MT_ST_CAN_BSR 0x0100 #define MT_ST_NO_BLKLIMS 0x0200 #define MT_ST_CAN_PARTITIONS 0x0400 #define MT_ST_SCSI2LOGICAL 0x0800 #define MT_ST_SYSV 0x1000 /* The mode parameters to be controlled. Parameter chosen with bits 20-28 */ #define MT_ST_CLEAR_DEFAULT 0xfffff #define MT_ST_DEF_DENSITY (MT_ST_DEF_OPTIONS | 0x100000) #define MT_ST_DEF_COMPRESSION (MT_ST_DEF_OPTIONS | 0x200000) #define MT_ST_DEF_DRVBUFFER (MT_ST_DEF_OPTIONS | 0x300000) /* The offset for the arguments for the special HP changer load command. */ #define MT_ST_HPLOADER_OFFSET 10000 /* Specify default tape device. */ #ifndef DEFTAPE #define DEFTAPE "/dev/tape/0" #endif //__END_DECLS // (Fish: not needed) #endif // _MSVC_ #endif // _W32MTIO_H_ hercules-3.07/w32stape.c000644 000765 000765 00000120071 11224164170 016556 0ustar00jmaynardjmaynard000000 000000 //////////////////////////////////////////////////////////////////////////////////// // W32STAPE.C -- Hercules Win32 SCSI Tape handling module // // (c) Copyright "Fish" (David B. Trout), 2005-2009. Released under // the Q Public License (http://www.hercules-390.org/herclic.html) // as modifications to Hercules. //////////////////////////////////////////////////////////////////////////////////// // // This module contains only WIN32 support for SCSI tapes. // Primary SCSI Tape support is in module 'scsitape.c'... // // PROGRAMMING NOTE: we rely on the known fact that // 'NO_ERROR' == 0 and 'INVALID_HANDLE_VALUE' == -1. // //////////////////////////////////////////////////////////////////////////////////// // $Id: w32stape.c 5365 2009-06-02 03:10:33Z fish $ // // $Log$ // Revision 1.19 2009/01/23 13:17:44 bernard // copyright notice // // Revision 1.18 2008/03/31 06:36:49 fish // (untab) // // Revision 1.17 2008/03/30 02:51:34 fish // Fix SCSI tape EOV (end of volume) processing // // Revision 1.16 2007/11/30 14:54:33 jmaynard // Changed conmicro.cx to hercules-390.org or conmicro.com, as needed. // // Revision 1.15 2007/07/24 22:36:33 fish // Fix tape Synchronize CCW (x'43') to do actual commit // // Revision 1.14 2007/07/24 21:57:29 fish // Fix Win32 SCSI tape "Locate" and "ReadBlockId" SNAFU // // Revision 1.13 2007/06/23 00:04:19 ivan // Update copyright notices to include current year (2007) // // Revision 1.12 2006/12/08 09:43:33 jj // Add CVS message log // #include "hstdinc.h" #define _W32STAPE_C_ #define _HTAPE_DLL_ #include "hercules.h" #include "w32stape.h" #include "tapedev.h" // (need IS_TAPE_BLKID_BOT) #ifdef _MSVC_ //////////////////////////////////////////////////////////////////////////////////// // Global data... #define W32STAPE_MAX_FDNUMS (32) // (admitedly low, but easily increased) typedef int ifd_t; // (internal fd) typedef int ufd_t; // (user fd) #define W32STAPE_IFD2UFD( ifd ) ((ufd_t)( (ifd) | 0x7F000000 )) #define W32STAPE_UFD2IFD( ufd ) ((ifd_t)( (ufd) & ~0x7F000000 )) static BYTE g_ifds [ W32STAPE_MAX_FDNUMS ] = {0}; // (0 == avail, 0xFF == used) static HANDLE g_handles [ W32STAPE_MAX_FDNUMS ] = {0}; // (WIN32 handles) static char* g_fnames [ W32STAPE_MAX_FDNUMS ] = {0}; // (for posterity) static U32 g_fstats [ W32STAPE_MAX_FDNUMS ] = {0}; // (running status) static U32 g_BOTmsk [ W32STAPE_MAX_FDNUMS ] = {0}; // (BOT block-id mask) static U32 g_BOTbot [ W32STAPE_MAX_FDNUMS ] = {0}; // (BOT block-id value) static TAPE_GET_DRIVE_PARAMETERS g_drive_parms [ W32STAPE_MAX_FDNUMS ] = {0}; // (drive parameters) static LOCK g_lock; // (master global access lock) #define lock() obtain_w32stape_lock() #define unlock() release_lock( &g_lock ) static void obtain_w32stape_lock() { static int bDidInit = 0; static int bInitBusy = 1; if (!bDidInit) { bDidInit = 1; initialize_lock ( &g_lock ); memset( g_ifds, 0x00, sizeof ( g_ifds ) ); memset( g_handles, 0x00, sizeof ( g_handles ) ); memset( g_fnames, 0x00, sizeof ( g_fnames ) ); memset( g_fstats, 0x00, sizeof ( g_fstats ) ); memset( g_BOTmsk, 0xFF, sizeof ( g_BOTmsk ) ); memset( g_BOTbot, 0x00, sizeof ( g_BOTbot ) ); bInitBusy = 0; } while (bInitBusy) Sleep(10); obtain_lock ( &g_lock ); } //////////////////////////////////////////////////////////////////////////////////// // Allocate an internal fd number... static ifd_t w32_alloc_ifd() { ifd_t ifd = -1; errno = EMFILE; lock(); { BYTE* pifd_slot = memchr( g_ifds, 0, W32STAPE_MAX_FDNUMS ); if (pifd_slot) { int n = (int) (pifd_slot - g_ifds); if ( n >= 0 && n < W32STAPE_MAX_FDNUMS ) { *pifd_slot = 1; errno = 0; ifd = n; } } } unlock(); return ifd; } //////////////////////////////////////////////////////////////////////////////////// // Release an internal fd number... static int w32_free_ifd( ifd_t ifd ) { int rc = 0; errno = 0; lock(); { if ( ifd >= 0 && ifd < W32STAPE_MAX_FDNUMS ) g_ifds [ ifd ] = 0; else { rc = -1; errno = EBADF; } } unlock(); return rc; } //////////////////////////////////////////////////////////////////////////////////// // Retrieve the status of the tape drive... static DWORD w32_get_tape_status ( HANDLE hFile ) { // *************************************************************** // PROGRAMMING NOTE: it is THIS LOOP (retrieving the status // of the tape drive) that takes UP TO *10* SECONDS TO COMPLETE // if there is no tape mounted on the drive whereas it completes // immediately when there IS a tape mounted! I have no idea why // Windows behave so unusually/inefficiently in this way! - Fish // *************************************************************** DWORD dwTapeStatus; // (NOTE: see also: KB 111837: "ERROR_BUS_RESET May Be Benign") do dwTapeStatus = GetTapeStatus( hFile ); while (ERROR_BUS_RESET == dwTapeStatus); return dwTapeStatus; } //////////////////////////////////////////////////////////////////////////////////// // Open tape device... DLL_EXPORT ufd_t w32_open_tape ( const char* path, int oflag, ... ) { ifd_t ifd; HANDLE hFile; char szTapeDeviceName[10]; const char* pszTapeDevNum; DWORD dwDesiredAccess, dwSizeofDriveParms, dwRetCode; // Reserve an fd number right away and bail if none available... if ( (ifd = w32_alloc_ifd()) < 0 ) return -1; // If they specified a Windows device name, // use it as-is. if (1 && strnfilenamecmp( path, "\\\\.\\", 4 ) == 0 && path [4] != 0 ) { strlcpy( szTapeDeviceName, path, sizeof(szTapeDeviceName) ); } else // (not a Windows device name) { // The device name is a Cygwin/*nix device name. // Name must be either "/dev/nst0" or "/dev/st0" if (1 && strnfilenamecmp( path, "/dev/", 5 ) == 0 && ( strnfilenamecmp( (pszTapeDevNum=path+8)-3, "nst", 3 ) == 0 || strnfilenamecmp( (pszTapeDevNum=path+7)-2, "st", 2 ) == 0 ) && strlen(pszTapeDevNum) == 1 && isdigit(*pszTapeDevNum) ) { // Change it to a Windows device name (e.g. \\.\Tape0) strlcpy( szTapeDeviceName, WIN32_TAPE_DEVICE_NAME, sizeof(szTapeDeviceName) ); szTapeDeviceName[8] = *pszTapeDevNum; szTapeDeviceName[9] = 0; // PROGRAMMING NOTE: the "rewind at close" option (implied by // virtue of the filename being "/dev/st0" and not "/dev/nst0") // was handled (detected/remembered) by the higher-level caller. } else { VERIFY( w32_free_ifd( ifd ) == 0 ); errno = EINVAL; // (bad device name) return -1; // (open failure) } } // We only support O_BINARY with either O_RDWR or O_RDONLY if (1 && (( O_BINARY | O_RDWR ) != oflag) && (( O_BINARY | O_RDONLY) != oflag) ) { VERIFY( w32_free_ifd( ifd ) == 0 ); errno = EINVAL; // (invalid open flags) return -1; // (open failure) } // Set desired access dwDesiredAccess = GENERIC_READ; if ( oflag & O_RDWR ) dwDesiredAccess |= GENERIC_WRITE; // Open the tape drive... hFile = CreateFile ( szTapeDeviceName, // filename dwDesiredAccess, // desired access 0, // share mode (0 == exclusive) NULL, // security == default OPEN_EXISTING, // "file" (device actually) must already exist 0, // no special access flags needed NULL // not using template ); if ( INVALID_HANDLE_VALUE == hFile ) { int save_errno = w32_trans_w32error( GetLastError() ); VERIFY( w32_free_ifd( ifd ) == 0 ); errno = save_errno; return -1; } // Save drive parameters for later... memset( &g_drive_parms[ifd], 0, sizeof(TAPE_GET_DRIVE_PARAMETERS) ); dwSizeofDriveParms = sizeof(TAPE_GET_DRIVE_PARAMETERS); do { dwRetCode = GetTapeParameters ( hFile, GET_TAPE_DRIVE_INFORMATION, &dwSizeofDriveParms, &g_drive_parms[ifd] ); } while ((NO_ERROR != dwRetCode) // (if not normal completion, && // check for retry conditions) (0 || ERROR_MEDIA_CHANGED == dwRetCode // (likely but unimportant; retry) || ERROR_BUS_RESET == dwRetCode // (unlikely but possible; retry) )); // Did that work? if (NO_ERROR != dwRetCode) { int save_errno = w32_trans_w32error( GetLastError() ); CloseHandle( hFile ); VERIFY( w32_free_ifd( ifd ) == 0 ); errno = save_errno; return -1; } ASSERT( NO_ERROR == dwRetCode ); ASSERT( sizeof(TAPE_GET_DRIVE_PARAMETERS) == dwSizeofDriveParms ); // Save control info & return their file descriptor... g_handles [ ifd ] = hFile; // (WIN32 handle) g_fnames [ ifd ] = strdup( path ); // (for posterity) g_fstats [ ifd ] = GMT_ONLINE (0xFFFFFFFF); // (initial status) g_BOTmsk [ ifd ] = 0xFFFFFFFF; // (BOT block-id mask) g_BOTbot [ ifd ] = 0x00000000; // (BOT block-id value) return W32STAPE_IFD2UFD( ifd ); // (user fd result) } //////////////////////////////////////////////////////////////////////////////////// // Define physical BOT block-id mask / value... // PROGRAMMING NOTE: For the time being, we require 'tapedev.c' to provide to us // the information we need in order to detect physical BOT (load-point). This is // only until such time as I can add SCSI PassThru support to Hercules so that we // can talk SCSI directly to the device ourselves (to determine such things as // what type of device (manufacturer/model) we're dealing with, etc). DLL_EXPORT int w32_define_BOT ( ufd_t ufd, U32 msk, U32 bot ) { ifd_t ifd = W32STAPE_UFD2IFD( ufd ); lock(); if (0 || ifd < 0 || ifd >= W32STAPE_MAX_FDNUMS || g_ifds[ ifd ] == 0 ) { unlock(); errno = EBADF; return -1; } g_BOTmsk [ ifd ] = msk; // (BOT block-id mask) g_BOTbot [ ifd ] = bot; // (BOT block-id value) unlock(); return 0; } //////////////////////////////////////////////////////////////////////////////////// // Post-process a tape i/o return code... // // Examine 'errno' (which should have been manually set to the return // code from the current i/o) and update the internal status appropriately, // depending on what type of error it was (tapemark, etc)... // // ------------------------------------------------------------- // *** THIS FUNCTION SHOULD BE CALLED AFTER EVERY TAPE I/O *** // ------------------------------------------------------------- // // An errno of 'EINTR' means the error was spurious (media changed, etc) // and that the caller should try the same i/o again (retry their i/o). // // EXAMPLE: // // do // { // errno = SetTapePosition( ... ); // errno = w32_internal_rc ( pStat ); // } // while ( EINTR == errno ); // return errno ? -1 : 0; // //////////////////////////////////////////////////////////////////////////////////// // *** THIS FUNCTION SHOULD BE CALLED AFTER EVERY TAPE I/O *** static int w32_internal_rc ( U32* pStat ) { ASSERT( pStat ); // (sanity check) // PROGRAMMING NOTE: the 'door open' (no tape in drive) and the // 'write protected' statuses are "sticky" in that they never change // until a new/different tape is mounted. All the other statuses // however, change dynamically as one does i/o to the tape... if (0 || ERROR_BUS_RESET == errno // (See KB 111837: "ERROR_BUS_RESET May Be Benign") || ERROR_MEDIA_CHANGED == errno || ERROR_DEVICE_NOT_CONNECTED == errno // (shouldn't occur but we'll check anyway) || ERROR_DEV_NOT_EXIST == errno // (shouldn't occur but we'll check anyway) || ERROR_FILE_NOT_FOUND == errno // (shouldn't occur but we'll check anyway) ) { *pStat &= ~GMT_DR_OPEN (0xFFFFFFFF); *pStat &= ~GMT_WR_PROT (0xFFFFFFFF); } // (see PROGRAMMING NOTE above) *pStat &= ~GMT_BOT (0xFFFFFFFF); *pStat &= ~GMT_SM (0xFFFFFFFF); *pStat &= ~GMT_EOF (0xFFFFFFFF); *pStat &= ~GMT_EOT (0xFFFFFFFF); *pStat &= ~GMT_EOD (0xFFFFFFFF); if (0 || ERROR_BUS_RESET == errno // (spurious error; retry) || ERROR_MEDIA_CHANGED == errno // (spurious error; retry) // || ERROR_DEVICE_NOT_CONNECTED == errno // (PERM ERROR! NO RETRY!) // || ERROR_DEV_NOT_EXIST == errno // (PERM ERROR! NO RETRY!) // || ERROR_FILE_NOT_FOUND == errno // (PERM ERROR! NO RETRY!) ) { return EINTR; // (Interrupted system call; Retry) } // (see PROGRAMMING NOTE further above) switch (errno) { default: break; // (leave errno set to whatever it already is) case NO_ERROR: errno = 0; break; // (normal expected i/o result) case ERROR_BEGINNING_OF_MEDIA: *pStat |= GMT_BOT (0xFFFFFFFF); errno = EIO; break; case ERROR_END_OF_MEDIA: *pStat |= GMT_EOT (0xFFFFFFFF); errno = ENOSPC; break; // "ERROR_END_OF_MEDIA" // // Msg: "The physical end of the tape has been reached." // // The EOT warning reflector has been reached or passed (i.e. you're // now/still in the "EOT Warning Zone" area). Writing additional data // and/or tapemarks may still be possible depending on the size of the // EOT Warning Zone (as set by a SetTapeParameters call with a non-zero // EOTWarningZoneSize value (if supported; see further below)) and // how much data you've already written to the EOT Warning Zone area // (i.e. once you're in the warning area, this "error" occurs after // EACH and EVERY I/O [in the warning zone area] until the ABSOLUTE // physical end-of-tape (ERROR_EOM_OVERFLOW) is reached; see below). // // // *********************** // ** IMPORTANT NOTE! ** // *********************** // // This is NOT actually an "error"!!! // // // When this "error" occurs, your "ReadFile" and/or "WriteFile" call // returns 'FALSE' even though ALL of your requested data was actually // written successfully!! This can be verified by checking to ensure // the returned "number of bytes written" actually matches the amount // you asked to be written. If they're the same (and they ALWAYS will // be for this specific "error" code), then it means this "error" is // NOT actually an error at all, but rather just a WARNING instead!! // (Had it been an actual i/o error, the error code would have been // some other DIFFERENT error code value instead!!) // // // *********************** // ** ALSO IMPORTANT! ** // *********************** // See also: // // http://fixunix.com/storage/205622-bug-dlttape-sys-no-eot-warning.html // // for ADDITIONAL IMPORTANT INFORMATION regarding always having to // specifically request that this "error" code be returned to you: // // Even when a drive reports it does not support the setting of the // the 'EOTWarningZoneSize' value (i.e. the FeaturesLow field of the // GetTapeParameters call returns '0' for TAPE_DRIVE_SET_EOT_WZ_SIZE // field), it may still be possible for "ERROR_END_OF_MEDIA" warnings // to be generated anyway by simply calling SetTapeParameters with a // non-zero 'EOTWarningZoneSize' value anyway. // // The reason for this is because some drives may not allow CHANGING // the value (thus the reason for it reporting that setting the value // is not supported), but may nevertheless still support the ENABLING // of their own hard-coded internal value. That is to say, while the // size of the warning zone may not be modifiable (as it may be hard- // coded and thus unchangeable), the drive may still have the ability // to REPORT reaching the EOT Warning zone IF SPECIFICALLY REQUESTED // TO DO SO! (which is presumably what requesting a non-zero Warning // Zone size would end up doing: i.e. even though such calls APPEAR // to fail, they actually DO succeed in accomplishing SOMETHING, just // not what you originally/specifically requested). // // Thus calling SetTapeParameters with a non-zero 'EOTWarningZoneSize' // value might very well succeed anyway even though GetTapeParameters // reports that doing so is not supported, and by so doing, may cause // the drive to begin reporting of "ERROR_END_OF_MEDIA" (whereas not // attempting to do so would end up leaving the drive in its default // non-reporting mode. That is to say, you should ALWAYS try setting // a non-zero 'EOTWarningZoneSize' value, ignoring any "unsupported" // error code that may be returned from such a call.) case ERROR_EOM_OVERFLOW: *pStat |= GMT_EOT (0xFFFFFFFF); errno = EIO; break; // "ERROR_EOM_OVERFLOW" // // Msg: "Physical end of tape encountered." // // This error code means that the actual physical end-of-media has been // reached, and no more data can be written to the tape. This includes // tapemarks as well. // // *********************** // ** IMPORTANT NOTE! ** // *********************** // // This is a HARD (UNRECOVERABLE) error!! // // To be programmatically informed of when you are coming close to the // physical end-of-the-tape (such that you could be assured room still // remained to write logical end-of-volume labels for example), simply // call SetTapeParameters with a non-zero 'EOTWarningZoneSize' value // and treat any "ERROR_END_OF_MEDIA" "errors" received when writing // as warnings instead. (See prior discussion of "ERROR_END_OF_MEDIA" // return code further above) case ERROR_NO_DATA_DETECTED: *pStat |= GMT_EOD (0xFFFFFFFF); errno = EIO; break; case ERROR_FILEMARK_DETECTED: *pStat |= GMT_EOF (0xFFFFFFFF); errno = EIO; break; case ERROR_SETMARK_DETECTED: *pStat |= GMT_SM (0xFFFFFFFF); errno = EIO; break; case ERROR_NOT_READY: *pStat |= GMT_DR_OPEN (0xFFFFFFFF); errno = ENOMEDIUM; break; case ERROR_NO_MEDIA_IN_DRIVE: *pStat |= GMT_DR_OPEN (0xFFFFFFFF); errno = ENOMEDIUM; break; case ERROR_WRITE_PROTECT: *pStat |= GMT_WR_PROT (0xFFFFFFFF); errno = EROFS; break; } return errno; } //////////////////////////////////////////////////////////////////////////////////// // (forward references for private helper functions) int w32_internal_mtop ( HANDLE hFile, U32* pStat, struct mtop* mtop, ifd_t ifd ); int w32_internal_mtget ( HANDLE hFile, U32* pStat, struct mtget* mtget, ifd_t ifd ); int w32_internal_mtpos ( HANDLE hFile, U32* pStat, DWORD* pdwLogPos, DWORD* pdwAbsPos, ifd_t ifd ); //////////////////////////////////////////////////////////////////////////////////// // Close tape device... DLL_EXPORT int w32_close_tape ( ufd_t ufd ) { ifd_t ifd = W32STAPE_UFD2IFD( ufd ); int rc = -1; errno = EBADF; lock(); if (1 && ifd >= 0 && ifd < W32STAPE_MAX_FDNUMS && g_ifds[ ifd ] != 0 ) { // Deallocate resources HANDLE hFile = g_handles[ ifd ]; char* pName = g_fnames [ ifd ]; g_handles[ ifd ] = NULL; g_fnames [ ifd ] = NULL; g_fstats [ ifd ] = GMT_DR_OPEN (0xFFFFFFFF); g_BOTmsk [ ifd ] = 0xFFFFFFFF; g_BOTbot [ ifd ] = 0x00000000; VERIFY( w32_free_ifd( ifd ) == 0 ); // Close the file... free( pName ); errno = CloseHandle( hFile ) ? 0 : w32_trans_w32error( GetLastError() ); rc = errno ? -1 : 0; } unlock(); return rc; } //////////////////////////////////////////////////////////////////////////////////// // Read tape... DLL_EXPORT ssize_t w32_read_tape ( ufd_t ufd, void* buf, size_t nbyte ) { BOOL bSuccess; DWORD dwBytesRead; DWORD dwLastError; ifd_t ifd = W32STAPE_UFD2IFD( ufd ); U32* pStat = NULL; HANDLE hFile; if (!buf) { errno = EINVAL; return -1; } lock(); if (0 || ifd < 0 || ifd >= W32STAPE_MAX_FDNUMS || g_ifds[ ifd ] == 0 ) { unlock(); errno = EBADF; return -1; } unlock(); hFile = g_handles[ ifd ]; pStat = &g_fstats[ ifd ]; // Do the i/o, save results, update device status // (based on the results), then check results... do { dwBytesRead = 0; bSuccess = ReadFile( hFile, buf, (DWORD)nbyte, &dwBytesRead, NULL ); errno = (dwLastError = GetLastError()); errno = w32_internal_rc ( pStat ); } while ( !bSuccess && EINTR == errno ); // Success? (see: "ERROR_END_OF_MEDIA" in function 'w32_internal_rc') if (bSuccess || ERROR_END_OF_MEDIA == dwLastError) { ASSERT( bSuccess || ENOSPC == errno ); return ( (ssize_t) dwBytesRead ); } ASSERT( !bSuccess && ERROR_END_OF_MEDIA != dwLastError && ENOSPC != errno ); // The i/o "failed". Check to see if it was just a tapemark... if ( EIO == errno && GMT_EOF( *pStat ) ) { ASSERT( ERROR_FILEMARK_DETECTED == dwLastError ); return 0; // (tapemark) } // EIO != errno || !GMT_EOF( *pStat ) --> bona fide i/o error... ASSERT( ERROR_FILEMARK_DETECTED != dwLastError ); return -1; } //////////////////////////////////////////////////////////////////////////////////// // Write tape... DLL_EXPORT ssize_t w32_write_tape ( ufd_t ufd, const void* buf, size_t nbyte ) { BOOL bSuccess; DWORD dwBytesWritten; DWORD dwLastError; ifd_t ifd = W32STAPE_UFD2IFD( ufd ); U32* pStat = NULL; HANDLE hFile; if (!buf) { errno = EINVAL; return -1; } lock(); if (0 || ifd < 0 || ifd >= W32STAPE_MAX_FDNUMS || g_ifds[ ifd ] == 0 ) { unlock(); errno = EBADF; return -1; } unlock(); hFile = g_handles[ ifd ]; pStat = &g_fstats[ ifd ]; // Do the i/o, save results, update device status // (based on the results), then check results... do { dwBytesWritten = 0; bSuccess = WriteFile( hFile, buf, (DWORD)nbyte, &dwBytesWritten, NULL ); errno = (dwLastError = GetLastError()); errno = w32_internal_rc ( pStat ); } while ( !bSuccess && EINTR == errno ); // Success? (see: "ERROR_END_OF_MEDIA" in function 'w32_internal_rc') if (bSuccess || ERROR_END_OF_MEDIA == dwLastError) { ASSERT( bSuccess || ENOSPC == errno ); ASSERT( ((size_t)dwBytesWritten) == nbyte ); // (MUST be true!!) return ( (ssize_t) dwBytesWritten ); } // I/O error... ASSERT( !bSuccess && ERROR_END_OF_MEDIA != dwLastError && ENOSPC != errno ); return -1; } //////////////////////////////////////////////////////////////////////////////////// // ioctl... (perform some type of control function, e.g. fsf, rewind, etc) DLL_EXPORT int w32_ioctl_tape ( ufd_t ufd, int request, ... ) { va_list vl; void* ptr = NULL; int rc = 0; ifd_t ifd = W32STAPE_UFD2IFD( ufd ); U32* pStat = NULL; HANDLE hFile; lock(); if (0 || ifd < 0 || ifd >= W32STAPE_MAX_FDNUMS || g_ifds[ ifd ] == 0 ) { unlock(); errno = EBADF; return -1; } unlock(); hFile = g_handles[ ifd ]; pStat = &g_fstats[ ifd ]; va_start ( vl, request ); ptr = va_arg( vl, void* ); if ( !ptr ) { errno = EINVAL; return -1; } switch (request) { case MTIOCTOP: // (perform tape operation) { struct mtop* mtop = ptr; rc = w32_internal_mtop ( hFile, pStat, mtop, ifd ); } break; case MTIOCGET: // (retrieve tape status) { struct mtget* mtget = ptr; memset( mtget, 0, sizeof(*mtget) ); rc = w32_internal_mtget ( hFile, pStat, mtget, ifd ); } break; case MTIOCPOS: // (retrieve tape position) { struct mtpos* mtpos = ptr; memset( mtpos, 0, sizeof(*mtpos) ); rc = w32_internal_mtpos( hFile, pStat, &mtpos->mt_blkno, NULL, ifd ); } break; default: // (invalid/unsupported ioctl code) { errno = EINVAL; rc = -1; } break; } return rc; } //////////////////////////////////////////////////////////////////////////////////// // Private internal helper function... return 0 == success, -1 == failure static int w32_internal_mtop ( HANDLE hFile, U32* pStat, struct mtop* mtop, ifd_t ifd ) { int rc = 0; ASSERT( pStat && mtop ); // (sanity check) // General technique: do the i/o, save results, update the // device status (based on the results), then check results... switch ( mtop->mt_op ) { case MTLOAD: // (load media) { if ( 1 != mtop->mt_count ) { errno = EINVAL; rc = -1; } else { do { errno = PrepareTape( hFile, TAPE_LOAD, FALSE ); errno = w32_internal_rc ( pStat ); } while ( EINTR == errno ); } } break; case MTUNLOAD: // (unload media) case MTOFFL: // (make media offline (same as unload)) { if ( 1 != mtop->mt_count ) { errno = EINVAL; rc = -1; } else { do { errno = PrepareTape( hFile, TAPE_UNLOAD, FALSE ); errno = w32_internal_rc ( pStat ); } while ( EINTR == errno ); } } break; case MTSEEK: // (position media) { do { errno = SetTapePosition( hFile, TAPE_LOGICAL_BLOCK, 0, mtop->mt_count, 0, FALSE ); errno = w32_internal_rc ( pStat ); } while ( EINTR == errno ); } break; case MTREW: // (rewind) { if ( 1 != mtop->mt_count ) { errno = EINVAL; rc = -1; } else { do { errno = SetTapePosition( hFile, TAPE_REWIND, 0, 0, 0, FALSE ); errno = w32_internal_rc ( pStat ); } while ( EINTR == errno ); } } break; case MTFSF: // (FORWARD space FILE) case MTBSF: // (BACKWARD space FILE) { if ( !mtop->mt_count ) { errno = EINVAL; rc = -1; } else { LARGE_INTEGER liCount; liCount.QuadPart = mtop->mt_count; if ( MTBSF == mtop->mt_op ) liCount.QuadPart = -liCount.QuadPart; // (negative == backwards) do { errno = SetTapePosition( hFile, TAPE_SPACE_FILEMARKS, 0, liCount.LowPart, liCount.HighPart, FALSE ); errno = w32_internal_rc ( pStat ); } while ( EINTR == errno ); } } break; case MTFSR: // (FORWARD space BLOCK) case MTBSR: // (BACKWARD space BLOCK) { if ( !mtop->mt_count ) { errno = EINVAL; rc = -1; } else { LARGE_INTEGER liCount; liCount.QuadPart = mtop->mt_count; if ( MTBSR == mtop->mt_op ) liCount.QuadPart = -liCount.QuadPart; // (negative == backwards) do { errno = SetTapePosition( hFile, TAPE_SPACE_RELATIVE_BLOCKS, 0, liCount.LowPart, liCount.HighPart, FALSE ); errno = w32_internal_rc ( pStat ); } while ( EINTR == errno ); } } break; case MTSETBLK: // (set blocksize) { TAPE_SET_MEDIA_PARAMETERS media_parms; media_parms.BlockSize = mtop->mt_count; do { errno = SetTapeParameters( hFile, SET_TAPE_MEDIA_INFORMATION, &media_parms ); errno = w32_internal_rc ( pStat ); } while ( EINTR == errno ); } break; case MTEOTWARN: // (set EOT Warning Zone size in bytes) { TAPE_SET_DRIVE_PARAMETERS set_drive_parms; set_drive_parms.ECC = g_drive_parms[ifd].ECC; set_drive_parms.Compression = g_drive_parms[ifd].Compression; set_drive_parms.DataPadding = g_drive_parms[ifd].DataPadding; set_drive_parms.ReportSetmarks = g_drive_parms[ifd].ReportSetmarks; set_drive_parms.EOTWarningZoneSize = mtop->mt_count; do { errno = SetTapeParameters( hFile, SET_TAPE_DRIVE_INFORMATION, &set_drive_parms ); errno = w32_internal_rc ( pStat ); } while ( EINTR == errno ); } break; case MTWEOF: // (write TAPEMARK) { if ( mtop->mt_count < 0 ) { errno = EINVAL; rc = -1; } else { // PROGRAMMING NOTE: We prefer "long" filemarks over any other type // because, according to the SDK documentaion: // // "A short filemark contains a short erase gap that cannot be // overwritten unless the write operation is performed from the // beginning of the partition or from an earlier long filemark." // // "A long filemark contains a long erase gap that allows an // application to position the tape at the beginning of the filemark // and to overwrite the filemark and the erase gap." // // Thus if TAPE_LONG_FILEMARKS is not supported we try ONLY the generic // TAPE_FILEMARKS variety and return an error if that fails; we do NOT // ever attempt the TAPE_SHORT_FILEMARKS or TAPE_SETMARKS variety. DWORD dwTapemarkType = TAPE_LONG_FILEMARKS; if ( !( g_drive_parms[ifd].FeaturesHigh & TAPE_DRIVE_WRITE_LONG_FMKS ) ) dwTapemarkType = TAPE_FILEMARKS; do { errno = WriteTapemark( hFile, dwTapemarkType, mtop->mt_count, FALSE ); errno = w32_internal_rc ( pStat ); } while ( EINTR == errno ); } } break; case MTERASE: // (write erase gap or erase entire tape (data security erase)) { if (1 && 0 != mtop->mt_count // (0 == write erase gap at current position) && 1 != mtop->mt_count // (1 == erases the remainder of entire tape) ) { errno = EINVAL; rc = -1; } else { DWORD dwEraseType = mtop->mt_count ? TAPE_ERASE_LONG : TAPE_ERASE_SHORT; do { errno = EraseTape( hFile, dwEraseType, FALSE ); errno = w32_internal_rc ( pStat ); } while ( EINTR == errno ); } } break; case MTNOP: // (no operation) { errno = 0; rc = 0; } break; default: // (invalid/unsupported tape operation) { errno = EINVAL; rc = -1; } break; } return (rc = (0 == errno || ENOSPC == errno) ? 0 : /* errno != 0 && errno != ENOSPC */ -1); } //////////////////////////////////////////////////////////////////////////////////// // Private internal helper function... return 0 == success, -1 == failure static int w32_internal_mtget ( HANDLE hFile, U32* pStat, struct mtget* mtget, ifd_t ifd ) { TAPE_GET_MEDIA_PARAMETERS media_parms; DWORD dwRetCode, dwSize, dwLogicalPosition; ASSERT( pStat && mtget ); mtget->mt_resid = 0; // (unknown/unsupported) mtget->mt_erreg = 0; // (unknown/unsupported) mtget->mt_fileno = -1; // (unknown/unsupported) mtget->mt_blkno = -1; // (unknown as of yet; set further below) mtget->mt_type = MT_ISSCSI2; // "Generic ANSI SCSI-2 tape unit" mtget->mt_gstat = -1; // (purposely invalid; set correctly below) // Reset the mounted status; it will get set further below... *pStat &= ~GMT_DR_OPEN (0xFFFFFFFF); // Attempt to retrieve the status of the tape-drive... dwRetCode = w32_get_tape_status( hFile ); // Windows returns 'ERROR_NOT_READY' if no tape is mounted // instead of the usual expected 'ERROR_NO_MEDIA_IN_DRIVE' if ( ERROR_NOT_READY == dwRetCode ) dwRetCode = ERROR_NO_MEDIA_IN_DRIVE; // If there is not tape mounted OR a new tape was mounted, // then the following status bits are now unknown/obsolete if (0 || ERROR_NO_MEDIA_IN_DRIVE == dwRetCode || ERROR_MEDIA_CHANGED == dwRetCode ) { // (these statuse are now obsolete) *pStat &= ~GMT_WR_PROT (0xFFFFFFFF); *pStat &= ~GMT_BOT (0xFFFFFFFF); *pStat &= ~GMT_EOT (0xFFFFFFFF); *pStat &= ~GMT_EOD (0xFFFFFFFF); *pStat &= ~GMT_EOF (0xFFFFFFFF); *pStat &= ~GMT_SM (0xFFFFFFFF); } // There's no sense trying to get media parameters // unless there's some media loaded on the drive! if ( ERROR_NO_MEDIA_IN_DRIVE == dwRetCode ) { *pStat |= GMT_DR_OPEN (0xFFFFFFFF); // (no tape mounted in drive) mtget->mt_gstat = *pStat; // (return current status) return 0; // (nothing more we can do) } // A tape appears to be mounted on the drive... // Retrieve the media parameters information... dwSize = sizeof(media_parms); memset( &media_parms, 0, dwSize ); dwRetCode = GetTapeParameters( hFile, GET_TAPE_MEDIA_INFORMATION, &dwSize, &media_parms ); ASSERT( sizeof(media_parms) == dwSize ); if ( NO_ERROR == dwRetCode ) { mtget->mt_dsreg = media_parms.BlockSize; if (media_parms.WriteProtected) *pStat |= GMT_WR_PROT (0xFFFFFFFF); else *pStat &= ~GMT_WR_PROT (0xFFFFFFFF); } else mtget->mt_dsreg = 0; // (unknown; variable blocks presumed) // Lastly, attempt to determine if we are at BOT (i.e. load-point)... if ( 0 != ( errno = w32_internal_mtpos( hFile, pStat, &dwLogicalPosition, NULL, ifd ) ) ) { mtget->mt_gstat = *pStat; return -1; } mtget->mt_blkno = dwLogicalPosition; if ( ( dwLogicalPosition & g_BOTmsk[ ifd ] ) == g_BOTbot[ ifd ] ) *pStat |= GMT_BOT (0xFFFFFFFF); else *pStat &= ~GMT_BOT (0xFFFFFFFF); mtget->mt_gstat = *pStat; return 0; } //////////////////////////////////////////////////////////////////////////////////// // Private internal helper function... return 0 == success, -1 == failure static int w32_internal_mtpos ( HANDLE hFile, U32* pStat, DWORD* pdwLogPos, DWORD* pdwAbsPos, ifd_t ifd ) { DWORD dwDummyPartition, dwDummyPositionHigh; ASSERT( pStat && pdwLogPos ); // (sanity check) // PROGRAMMING NOTE: the SDK docs state that for the 'lpdwOffsetHigh' // parameter (i.e. dwDummyPositionHigh, the 5th paramater): // // "This parameter can be NULL if the // high-order bits are not required." // // But it LIES! Simple expirical observation reveals that ALL parameters // are in fact required. If any are NULL then 'GetTapePosition' crashes // and burns (which is unusual since usually when you pass invalid args // to an API it usually just returns an error code, but in this case it // doesn't. It actually crashes) do { U32 dummy_stat = 0; errno = GetTapePosition ( hFile, TAPE_LOGICAL_POSITION, &dwDummyPartition, pdwLogPos, &dwDummyPositionHigh ); errno = w32_internal_rc ( &dummy_stat ); } while ( EINTR == errno ); if (errno) return -1; if (pdwAbsPos) // (may be NULL if they're not interested in it) { do { U32 dummy_stat = 0; errno = GetTapePosition ( hFile, TAPE_ABSOLUTE_POSITION, &dwDummyPartition, pdwAbsPos, &dwDummyPositionHigh ); errno = w32_internal_rc ( &dummy_stat ); } while ( EINTR == errno ); if (errno) return -1; } // PROGRAMMING NOTE: the Windows 'GetTapePosition' API returns either // a LOGICAL position value or an ABSOLUTE position value. Based on // trial and error it was determined the LOGICAL position corresponds // to the SCSI "READ POSITION" command's "first block location" value, // and the ABSOLUTE tape position appears to correspond to the SCSI // "last block location". // Since what we want is what IBM calls the "Channel block ID" (which // itself appears to correspond to what the SCSI documentation refers // to as the "First block location"), then what we want here is what // Windows refers to as the LOGICAL position, not the ABSOLUTE (i.e. // device-relative) position I originally thought we needed/wanted. if ( ( *pdwLogPos & g_BOTmsk[ ifd ] ) == g_BOTbot[ ifd ] ) *pStat |= GMT_BOT (0xFFFFFFFF); else *pStat &= ~GMT_BOT (0xFFFFFFFF); return 0; } //////////////////////////////////////////////////////////////////////////////////// #endif /* _MSVC_ */ hercules-3.07/w32stape.h000644 000765 000765 00000003434 11143760542 016573 0ustar00jmaynardjmaynard000000 000000 //////////////////////////////////////////////////////////////////////////////////// // W32STAPE.H -- Hercules Win32 SCSI Tape handling module // // (c) Copyright "Fish" (David B. Trout), 2005-2009. Released under // the Q Public License (http://www.hercules-390.org/herclic.html) // as modifications to Hercules. //////////////////////////////////////////////////////////////////////////////////// // // This module contains only MSVC support for SCSI tapes. // Primary SCSI Tape support is in module 'scsitape.c'... // //////////////////////////////////////////////////////////////////////////////////// // $Id: w32stape.h 5127 2009-01-23 13:25:01Z bernard $ // // $Log$ // Revision 1.8 2007/11/30 14:54:34 jmaynard // Changed conmicro.cx to hercules-390.org or conmicro.com, as needed. // // Revision 1.7 2007/06/23 00:04:19 ivan // Update copyright notices to include current year (2007) // // Revision 1.6 2006/12/08 09:43:34 jj // Add CVS message log // #ifndef _W32STAPE_H_ #define _W32STAPE_H_ #ifdef _MSVC_ #include "w32mtio.h" // Win32 version of 'mtio.h' #define WIN32_TAPE_DEVICE_NAME "\\\\.\\Tape0" #ifndef _W32STAPE_C_ #ifndef _HTAPE_DLL_ #define W32ST_DLL_IMPORT DLL_IMPORT #else #define W32ST_DLL_IMPORT extern #endif #else #define W32ST_DLL_IMPORT DLL_EXPORT #endif W32ST_DLL_IMPORT int w32_open_tape ( const char* path, int oflag, ... ); W32ST_DLL_IMPORT int w32_define_BOT ( int fd, U32 msk, U32 bot ); W32ST_DLL_IMPORT int w32_ioctl_tape ( int fd, int request, ... ); W32ST_DLL_IMPORT int w32_close_tape ( int fd ); W32ST_DLL_IMPORT ssize_t w32_read_tape ( int fd, void* buf, size_t nbyte ); W32ST_DLL_IMPORT ssize_t w32_write_tape ( int fd, const void* buf, size_t nbyte ); #endif // _MSVC_ #endif // _W32STAPE_H_ hercules-3.07/w32util.c000644 000765 000765 00000313730 11321734033 016424 0ustar00jmaynardjmaynard000000 000000 ////////////////////////////////////////////////////////////////////////////////////////// // w32util.c Windows porting functions ////////////////////////////////////////////////////////////////////////////////////////// // (c) Copyright "Fish" (David B. Trout), 2005-2009. Released under the Q Public License // (http://www.hercules-390.org/herclic.html) as modifications to Hercules. ////////////////////////////////////////////////////////////////////////////////////////// // // IMPORTANT PROGRAMMING NOTE! // // Please see the "VERY IMPORTANT SPECIAL NOTE" comments accompanying the // select, fdopen, etc, #undef's in the Windows Socket Handling section!! // ////////////////////////////////////////////////////////////////////////////////////////// // $Id: w32util.c 5586 2009-12-31 10:29:11Z rbowler $ // // $Log$ // Revision 1.33 2008/11/23 22:27:43 rbowler // Fix win64 type conversion warnings in w32util.c // // Revision 1.32 2008/08/29 07:08:41 fish // Fix parsing bug/issue in "w32_parse_piped_process_stdxxx_data" function // // Revision 1.31 2007/11/30 14:54:34 jmaynard // Changed conmicro.cx to hercules-390.org or conmicro.com, as needed. // // Revision 1.30 2007/08/04 19:04:33 fish // gethostid // // Revision 1.29 2007/06/23 00:04:19 ivan // Update copyright notices to include current year (2007) // // Revision 1.28 2007/01/11 19:54:34 fish // Addt'l keep-alive mods: create associated supporting config-file stmt and panel command where individual customer-preferred values can be specified and/or dynamically modified. // // Revision 1.27 2007/01/10 15:12:11 rbowler // Console keepalive for Unix // // Revision 1.26 2007/01/10 09:32:39 fish // Enable connection keep-alive to try and detect 3270 clients that have died (MSVC only right now; don't know how to do it on *nix) // // Revision 1.25 2007/01/03 22:02:31 fish // Minor correction to PR# build_msc/103 fix // // Revision 1.24 2006/12/30 18:48:11 fish // PR# build_msc/103: fix MSVC diag 8 'sh' capture // // Revision 1.23 2006/12/28 15:49:35 fish // Use _beginthreadex/_endthreadex instead of CreateThread/ExitThread in continuing effort to try and resolve our still existing long-standing 'errno' issue... // // Revision 1.22 2006/12/28 04:04:33 fish // (just a very minor update to some comments) // // Revision 1.21 2006/12/08 09:43:34 jj // Add CVS message log // #include "hstdinc.h" #define _W32UTIL_C_ #define _HUTIL_DLL_ #include "hercules.h" #if defined( _MSVC_ ) /////////////////////////////////////////////////////////////////////////////// // Support for disabling of CRT Invalid Parameter Handler... #if defined( _MSVC_ ) && defined( _MSC_VER ) && ( _MSC_VER >= 1400 ) static void DummyCRTInvalidParameterHandler ( const wchar_t* expression, const wchar_t* function, const wchar_t* file, unsigned int line, uintptr_t pReserved ) { // Do nothing to cause CRT to simply ignore the invalid parameter // and to instead just pass back the return code to the caller. } static _invalid_parameter_handler old_iph = NULL; static int prev_rm = 0; // This function's sole purpose is to bypass Microsoft's default handling of // invalid parameters being passed to CRT functions, which ends up causing // two completely different assertion dialogs to appear for each problem DLL_EXPORT void DisableInvalidParameterHandling() { if ( old_iph ) return; old_iph = _set_invalid_parameter_handler( DummyCRTInvalidParameterHandler ); #if defined(DEBUG) || defined(_DEBUG) prev_rm = _CrtSetReportMode( _CRT_ASSERT, 0 ); #endif } DLL_EXPORT void EnableInvalidParameterHandling() { if ( !old_iph ) return; _set_invalid_parameter_handler( old_iph ); old_iph = NULL; #if defined(DEBUG) || defined(_DEBUG) _CrtSetReportMode( _CRT_ASSERT, prev_rm ); #endif } #endif // defined( _MSVC_ ) && defined( _MSC_VER ) && ( _MSC_VER >= 1400 ) ////////////////////////////////////////////////////////////////////////////////////////// struct ERRNOTAB { DWORD dwLastError; // Win32 error from GetLastError() int nErrNo; // corresponding 'errno' value }; typedef struct ERRNOTAB ERRNOTAB; // PROGRAMMING NOTE: we only need to translate values which // are in the same range as existing defined errno values. If // the Win32 GetLastError() value is outside the defined errno // value range, then we just use the raw GetLastError() value. // The current 'errno' value range is 0 - 43, so only those // GetLastError() values (defined in winerror.h) which are 43 // or less need to be remapped. ERRNOTAB w32_errno_tab[] = { { ERROR_TOO_MANY_OPEN_FILES, EMFILE }, { ERROR_ACCESS_DENIED, EACCES }, { ERROR_INVALID_HANDLE, EBADF }, { ERROR_NOT_ENOUGH_MEMORY, ENOMEM }, { ERROR_OUTOFMEMORY, ENOMEM }, { ERROR_INVALID_DRIVE, ENOENT }, { ERROR_WRITE_PROTECT, EACCES }, { ERROR_NOT_READY, EIO }, { ERROR_CRC, EIO }, { ERROR_WRITE_FAULT, EIO }, { ERROR_READ_FAULT, EIO }, { ERROR_GEN_FAILURE, EIO }, { ERROR_SHARING_VIOLATION, EACCES }, }; #define NUM_ERRNOTAB_ENTRIES (sizeof(w32_errno_tab)/sizeof(w32_errno_tab[0])) ////////////////////////////////////////////////////////////////////////////////////////// // Translates a Win32 '[WSA]GetLastError()' value into a 'errno' value (if possible // and/or if needed) that can then be used in the below 'w32_strerror' string function... DLL_EXPORT int w32_trans_w32error( const DWORD dwLastError ) { int i; for ( i=0; i < NUM_ERRNOTAB_ENTRIES; i++ ) if ( dwLastError == w32_errno_tab[i].dwLastError ) return w32_errno_tab[i].nErrNo; return (int) dwLastError; } ////////////////////////////////////////////////////////////////////////////////////////// // ("unsafe" version -- use "safer" 'w32_strerror_r' instead if possible) DLL_EXPORT char* w32_strerror( int errnum ) { static char szMsgBuff[ 256 ]; // (s/b plenty big enough) w32_strerror_r( errnum, szMsgBuff, sizeof(szMsgBuff) ); return szMsgBuff; } ////////////////////////////////////////////////////////////////////////////////////////// // Handles both regular 'errno' values as well as [WSA]GetLastError() values too... DLL_EXPORT int w32_strerror_r( int errnum, char* buffer, size_t buffsize ) { // Route all 'errno' values outside the normal CRT (C Runtime) error // message table range to the Win32 'w32_w32errmsg' function instead. // Otherwise simply use the CRT's error message table directly... if ( !buffer || !buffsize ) return -1; if ( errnum >= 0 && errnum < _sys_nerr ) { // Use CRT's error message table directly... strlcpy( buffer, _sys_errlist[ errnum ], buffsize ); } else { // 'errno' value is actually a Win32 [WSA]GetLastError value... w32_w32errmsg( errnum, buffer, buffsize ); } return 0; } ////////////////////////////////////////////////////////////////////////////////////////// // Return Win32 error message text associated with an error number value // as returned by a call to either GetLastError() or WSAGetLastError()... DLL_EXPORT char* w32_w32errmsg( int errnum, char* pszBuffer, size_t nBuffSize ) { DWORD dwBytesReturned = 0; DWORD dwBuffSize = (DWORD)nBuffSize; ASSERT( pszBuffer && nBuffSize ); dwBytesReturned = FormatMessageA ( 0 | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS , NULL, errnum, MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), pszBuffer, dwBuffSize, NULL ); ASSERT( dwBytesReturned ); // (remove trailing whitespace) { char* p = pszBuffer + dwBytesReturned - 1; while ( p >= pszBuffer && isspace(*p) ) p--; *++p = 0; } return pszBuffer; } ////////////////////////////////////////////////////////////////////////////////////////// // Large File Support... #if (_MSC_VER < 1400) //---------------------------------------------------------------------------------------- #if defined( _POSIX_ ) // (promote/demote long to/from __int64) #define FPOS_T_TO_INT64(pos) ((__int64)(pos)) #define INT64_TO_FPOS_T(i64,pos) ((pos) = (long)(i64)) #if _INTEGRAL_MAX_BITS < 64 #pragma message( MSVC_MESSAGE_LINENUM "warning: fseek/ftell use offset arguments of insufficient size" ) #endif #else #if !__STDC__ && _INTEGRAL_MAX_BITS >= 64 // (already __int64!) #define FPOS_T_TO_INT64(pos) (pos) #define INT64_TO_FPOS_T(i64,pos) ((pos) = (i64)) #else // (construct an __int64 from fpos_t structure members and vice-versa) #define FPOS_T_TO_INT64(pos) ((__int64)(((unsigned __int64)(pos).hipart << 32) | \ (unsigned __int64)(pos).lopart)) #define INT64_TO_FPOS_T(i64,pos) ((pos).hipart = (int)((i64) >> 32), \ (pos).lopart = (unsigned int)(i64)) #endif #endif //---------------------------------------------------------------------------------------- DLL_EXPORT __int64 w32_ftelli64 ( FILE* stream ) { fpos_t pos; if ( fgetpos( stream, &pos ) != 0 ) return -1; else return FPOS_T_TO_INT64( pos ); } //---------------------------------------------------------------------------------------- DLL_EXPORT int w32_fseeki64 ( FILE* stream, __int64 offset, int origin ) { __int64 offset_from_beg; fpos_t pos; if (SEEK_CUR == origin) { if ( (offset_from_beg = w32_ftelli64( stream )) < 0 ) return -1; offset_from_beg += offset; } else if (SEEK_END == origin) { struct stat fst; if ( fstat( fileno( stream ), &fst ) != 0 ) return -1; offset_from_beg = (__int64)fst.st_size + offset; } else if (SEEK_SET == origin) { offset_from_beg = offset; } else { errno = EINVAL; return -1; } INT64_TO_FPOS_T( offset_from_beg, pos ); return fsetpos( stream, &pos ); } //---------------------------------------------------------------------------------------- DLL_EXPORT int w32_ftrunc64 ( int fd, __int64 new_size ) { HANDLE hFile; int rc = 0, save_errno; __int64 old_pos, old_size; if ( new_size < 0 ) { errno = EINVAL; return -1; } hFile = (HANDLE) _get_osfhandle( fd ); if ( (HANDLE) -1 == hFile ) { errno = EBADF; // (probably not a valid opened file descriptor) return -1; } // The value of the seek pointer shall not be modified by a call to ftruncate(). if ( ( old_pos = _telli64( fd ) ) < 0 ) return -1; // PROGRAMMING NOTE: from here on, all errors // need to goto error_return to restore the original // seek pointer... if ( ( old_size = _lseeki64( fd, 0, SEEK_END ) ) < 0 ) { rc = -1; goto error_return; } // pad with zeros out to new_size if needed rc = 0; // (think positively) if ( new_size > old_size ) { #define ZEROPAD_BUFFSIZE ( 128 * 1024 ) BYTE zeros[ZEROPAD_BUFFSIZE]; size_t write_amount = sizeof(zeros); memset( zeros, 0, sizeof(zeros) ); do { write_amount = min( sizeof(zeros), ( new_size - old_size ) ); if ( !WriteFile( hFile, zeros, write_amount, NULL, NULL ) ) { errno = (int) GetLastError(); rc = -1; break; } } while ( ( old_size += write_amount ) < new_size ); save_errno = errno; ASSERT( old_size == new_size || rc < 0 ); errno = save_errno; } if ( rc < 0 ) goto error_return; // set the new file size (eof) if ( _lseeki64( fd, new_size, SEEK_SET ) < 0 ) { rc = -1; goto error_return; } if ( !SetEndOfFile( hFile ) ) { errno = (int) GetLastError(); rc = -1; goto error_return; } rc = 0; // success! error_return: // restore the original seek pointer and return save_errno = errno; _lseeki64( fd, old_pos, SEEK_SET ); errno = save_errno; return rc; } #endif // (_MSC_VER < 1400) ////////////////////////////////////////////////////////////////////////////////////////// #if !defined( HAVE_FORK ) DLL_EXPORT pid_t fork( void ) { errno = ENOTSUP; return -1; // *** NOT SUPPORTED *** } #endif ////////////////////////////////////////////////////////////////////////////////////////// #if !defined( HAVE_SCHED_YIELD ) DLL_EXPORT int sched_yield ( void ) { Sleep(0); return 0; } #endif ////////////////////////////////////////////////////////////////////////////////////////// // Win32's runtime library functions are reentrant as long as you link // with one of the multi-threaded libraries (i.e. LIBCMT, MSVCRT, etc.) #if !defined( HAVE_STRTOK_R ) DLL_EXPORT char* strtok_r ( char* s, const char* sep, char** lasts ) { UNREFERENCED( lasts ); return strtok( s, sep ); } #endif ////////////////////////////////////////////////////////////////////////////////////////// // Can't use "HAVE_SLEEP" since Win32's "Sleep" causes HAVE_SLEEP to // be erroneously #defined due to autoconf AC_CHECK_FUNCS case issues... //#if !defined( HAVE_SLEEP ) DLL_EXPORT unsigned sleep ( unsigned seconds ) { Sleep( seconds * 1000 ); return 0; } //#endif ////////////////////////////////////////////////////////////////////////////////////////// // high resolution sleep #if !defined( HAVE_NANOSLEEP ) || !defined( HAVE_USLEEP ) static int w32_nanosleep ( const struct timespec* rqtp ) { /* DESCRIPTION The nanosleep() function shall cause the current thread to be suspended from execution until either the time interval specified by the rqtp argument has elapsed or a signal is delivered to the calling thread, and its action is to invoke a signal-catching function or to terminate the process. The suspension time may be longer than requested because the argument value is rounded up to an integer multiple of the sleep resolution or because of the scheduling of other activity by the system. But, except for the case of being interrupted by a signal, the suspension time shall not be less than the time specified by rqtp, as measured by the system clock CLOCK_REALTIME. The use of the nanosleep() function has no effect on the action or blockage of any signal. RETURN VALUE If the nanosleep() function returns because the requested time has elapsed, its return value shall be zero. If the nanosleep() function returns because it has been interrupted by a signal, it shall return a value of -1 and set errno to indicate the interruption. If the rmtp argument is non-NULL, the timespec structure referenced by it is updated to contain the amount of time remaining in the interval (the requested time minus the time actually slept). If the rmtp argument is NULL, the remaining time is not returned. If nanosleep() fails, it shall return a value of -1 and set errno to indicate the error. ERRORS The nanosleep() function shall fail if: [EINTR] The nanosleep() function was interrupted by a signal. [EINVAL] The rqtp argument specified a nanosecond value less than zero or greater than or equal to 1000 million. */ static BOOL bDidInit = FALSE; static HANDLE hTimer = NULL; LARGE_INTEGER liDueTime; // Create the waitable timer if needed... if (unlikely( !bDidInit )) { bDidInit = TRUE; VERIFY( ( hTimer = CreateWaitableTimer( NULL, TRUE, NULL ) ) != NULL ); } // Check passed parameters... if (unlikely(!rqtp || rqtp->tv_nsec < 0 || rqtp->tv_nsec >= 1000000000 )) { errno = EINVAL; return -1; } // Note: Win32 waitable timers: parameter is #of 100-nanosecond intervals. // Positive values indicate absolute UTC time. Negative values indicate // relative time. The actual timer accuracy depends on the capability // of your hardware. liDueTime.QuadPart = -( // (negative means relative) (((__int64)rqtp->tv_sec * 10000000)) + (((__int64)rqtp->tv_nsec + 99) / 100) ); // Set the waitable timer... VERIFY( SetWaitableTimer( hTimer, &liDueTime, 0, NULL, NULL, FALSE ) ); // Wait for the waitable timer to expire... VERIFY( WaitForSingleObject( hTimer, INFINITE ) == WAIT_OBJECT_0 ); return 0; } #endif ////////////////////////////////////////////////////////////////////////////////////////// // nanosleep - high resolution sleep #if !defined( HAVE_NANOSLEEP ) DLL_EXPORT int nanosleep ( const struct timespec* rqtp, struct timespec* rmtp ) { if (unlikely(rmtp)) { rmtp->tv_sec = 0; rmtp->tv_nsec = 0; } return w32_nanosleep ( rqtp ); } #endif ////////////////////////////////////////////////////////////////////////////////////////// // usleep - suspend execution for an interval #if !defined( HAVE_USLEEP ) DLL_EXPORT int usleep ( useconds_t useconds ) { // "The useconds argument shall be less than one million. If the value of // useconds is 0, then the call has no effect." // "Implementations may place limitations on the granularity of timer values. // For each interval timer, if the requested timer value requires a finer // granularity than the implementation supports, the actual timer value shall // be rounded up to the next supported value." // "Upon successful completion, usleep() shall return 0; otherwise, it shall // return -1 and set errno to indicate the error." // "The usleep() function may fail if: // // [EINVAL] The time interval specified // one million or more microseconds" struct timespec rqtp; if (unlikely( useconds < 0 || useconds >= 1000000 )) { errno = EINVAL; return -1; } rqtp.tv_sec = 0; rqtp.tv_nsec = useconds * 1000; return w32_nanosleep ( &rqtp ); } #endif ////////////////////////////////////////////////////////////////////////////////////////// // gettimeofday... #if !defined( HAVE_GETTIMEOFDAY ) // Number of 100-nanosecond units from 1 Jan 1601 to 1 Jan 1970 #define EPOCH_BIAS 116444736000000000ULL // Helper function to convert Windows system-time value to microseconds... static LARGE_INTEGER FileTimeToMicroseconds( const FILETIME* pFT ) { LARGE_INTEGER liWork; // (work area) // Copy value to be converted to work area liWork.HighPart = pFT->dwHighDateTime; liWork.LowPart = pFT->dwLowDateTime; // Convert to 100-nanosecond units since 1 Jan 1970 liWork.QuadPart -= EPOCH_BIAS; // Convert to microseconds since 1 Jan 1970 liWork.QuadPart /= (LONGLONG) 10; return liWork; } DLL_EXPORT int gettimeofday ( struct timeval* pTV, void* pTZ ) { LARGE_INTEGER liCurrentHPCValue; // (high-performance-counter tick count) static LARGE_INTEGER liStartingHPCValue; // (high-performance-counter tick count) static LARGE_INTEGER liStartingSystemTime; // (time of last resync in microseconds) static struct timeval tvPrevSyncVal = {0,0}; // (time of last resync as timeval) static struct timeval tvPrevRetVal = {0,0}; // (previously returned value) static double dHPCTicksPerMicrosecond; // (just what it says) static BOOL bInSync = FALSE; // (work flag) UNREFERENCED(pTZ); // One-time (and periodic!) initialization... if (unlikely( !bInSync )) { FILETIME ftStartingSystemTime; LARGE_INTEGER liHPCTicksPerSecond; // The "GetSystemTimeAsFileTime" function obtains the current system date // and time. The information is in Coordinated Universal Time (UTC) format. GetSystemTimeAsFileTime( &ftStartingSystemTime ); VERIFY( QueryPerformanceCounter( &liStartingHPCValue ) ); VERIFY( QueryPerformanceFrequency( &liHPCTicksPerSecond ) ); dHPCTicksPerMicrosecond = (double) liHPCTicksPerSecond.QuadPart / 1000000.0; liStartingSystemTime = FileTimeToMicroseconds( &ftStartingSystemTime ); tvPrevSyncVal.tv_sec = 0; // (to force init further below) tvPrevSyncVal.tv_usec = 0; // (to force init further below) bInSync = TRUE; } // The following check for user error must FOLLOW the above initialization // code block so the above initialization code block ALWAYS gets executed! if (unlikely( !pTV )) return EFAULT; // Query current high-performance counter value... VERIFY( QueryPerformanceCounter( &liCurrentHPCValue ) ); // Calculate elapsed HPC ticks... liCurrentHPCValue.QuadPart -= liStartingHPCValue.QuadPart; // Convert to elapsed microseconds... liCurrentHPCValue.QuadPart = (LONGLONG) ( (double) liCurrentHPCValue.QuadPart / dHPCTicksPerMicrosecond ); // Add to starting system time... liCurrentHPCValue.QuadPart += liStartingSystemTime.QuadPart; // Build results... pTV->tv_sec = (long)(liCurrentHPCValue.QuadPart / 1000000); pTV->tv_usec = (long)(liCurrentHPCValue.QuadPart % 1000000); // Re-sync to system clock every so often to prevent clock drift // since high-performance timer updated independently from clock. #define RESYNC_GTOD_EVERY_SECS 30 // (initialize time of previous 'sync') if (unlikely( !tvPrevSyncVal.tv_sec )) { tvPrevSyncVal.tv_sec = pTV->tv_sec; tvPrevSyncVal.tv_usec = pTV->tv_usec; } // (is is time to resync again?) if (unlikely( (pTV->tv_sec - tvPrevSyncVal.tv_sec ) > RESYNC_GTOD_EVERY_SECS )) { bInSync = FALSE; // (force resync) return gettimeofday( pTV, NULL ); } // Ensure that each call returns a unique, ever-increasing value... if (unlikely( !tvPrevRetVal.tv_sec )) { tvPrevRetVal.tv_sec = pTV->tv_sec; tvPrevRetVal.tv_usec = pTV->tv_usec; } if (unlikely (0 || pTV->tv_sec < tvPrevRetVal.tv_sec || (1 && pTV->tv_sec == tvPrevRetVal.tv_sec && pTV->tv_usec <= tvPrevRetVal.tv_usec ) )) { pTV->tv_usec = tvPrevRetVal.tv_sec; pTV->tv_usec = tvPrevRetVal.tv_usec + 1; if (unlikely(pTV->tv_usec >= 1000000)) { pTV->tv_sec += pTV->tv_usec / 1000000; pTV->tv_usec = pTV->tv_usec % 1000000; } } // Save previously returned value for next time... tvPrevRetVal.tv_sec = pTV->tv_sec; tvPrevRetVal.tv_usec = pTV->tv_usec; // Done! return 0; // (always unless user error) } #endif ////////////////////////////////////////////////////////////////////////////////////////// // scandir... #if !defined( HAVE_SCANDIR ) // (fishfix: fix benign "passing incompatible pointer type" compiler warning..) typedef int (*PFN_QSORT_COMPARE_FUNC)( const void* elem1, const void* elem2 ); // Found the following on Koders.com ... (http://www.koders.com/) ... /* Copyright (c) 2000 Petter Reinholdtsen 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 AUTHORS OR COPYRIGHT HOLDERS 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. */ DLL_EXPORT int scandir ( const char *dir, struct dirent ***namelist, int (*filter)(const struct dirent *), int (*compar)(const struct dirent **, const struct dirent **) ) { WIN32_FIND_DATA file_data; HANDLE handle; int count, pos; struct dirent **names; char *pattern; /* 3 for "*.*", 1 for "\", 1 for zero termination */ pattern = (char*)malloc(strlen(dir) + 3 +1 +1); strcpy(pattern, dir); if (pattern[ strlen(pattern) - 1] != '\\') strcat(pattern, "\\"); strcat(pattern, "*.*"); /* 1st pass thru is just to count them */ handle = FindFirstFile(pattern, &file_data); if (handle == INVALID_HANDLE_VALUE) { free(pattern); return -1; } count = 0; while (1) { count++; if (!FindNextFile(handle, &file_data)) break; } FindClose(handle); /* Now we know how many, we can alloc & make 2nd pass to copy them */ names = (struct dirent**)malloc(sizeof(struct dirent*) * count); memset(names, 0, sizeof(*names)); handle = FindFirstFile(pattern, &file_data); if (handle == INVALID_HANDLE_VALUE) { free(pattern); free(names); return -1; } /* Now let caller filter them if requested */ pos = 0; while (1) { int rtn; struct dirent current; strcpy(current.d_name, file_data.cFileName); if (!filter || filter(¤t)) { struct dirent *copyentry = malloc(sizeof(struct dirent)); strcpy(copyentry->d_name, current.d_name); names[pos] = copyentry; pos++; } rtn = FindNextFile(handle, &file_data); if (!rtn || rtn==ERROR_NO_MORE_FILES) break; } free(pattern); /* Now sort them */ if (compar) // (fishfix: fix benign "passing incompatible pointer type" compiler warning..) qsort(names, pos, sizeof(names[0]), (PFN_QSORT_COMPARE_FUNC)compar); *namelist = names; return pos; } #endif ////////////////////////////////////////////////////////////////////////////////////////// #if !defined( HAVE_ALPHASORT ) DLL_EXPORT int alphasort ( const struct dirent **a, const struct dirent **b ) { return strfilenamecmp ( (*a)->d_name, (*b)->d_name ); } #endif ////////////////////////////////////////////////////////////////////////////////////////// // "Poor man's" getrusage... #if !defined(HAVE_SYS_RESOURCE_H) static int DoGetRUsage( HANDLE hProcess, struct rusage* r_usage ) { FILETIME ftCreation; // When the process was created(*) FILETIME ftExit; // When the process exited(*) // (*) Windows standard FILETIME format: date/time expressed as the // amount of time that has elapsed since midnight January 1, 1601. FILETIME ftKernel; // CPU time spent in kernel mode (in #of 100-nanosecond units) FILETIME ftUser; // CPU time spent in user mode (in #of 100-nanosecond units) LARGE_INTEGER liWork; // (work area) if ( !GetProcessTimes( hProcess, &ftCreation, &ftExit, &ftKernel, &ftUser ) ) { ftCreation.dwHighDateTime = ftCreation.dwLowDateTime = 0; ftExit .dwHighDateTime = ftExit .dwLowDateTime = 0; ftKernel .dwHighDateTime = ftKernel .dwLowDateTime = 0; ftUser .dwHighDateTime = ftUser .dwLowDateTime = 0; } // Kernel time... liWork.HighPart = ftKernel.dwHighDateTime; liWork.LowPart = ftKernel.dwLowDateTime; liWork.QuadPart /= 10; // (convert to microseconds) r_usage->ru_stime.tv_sec = (long)(liWork.QuadPart / 1000000); r_usage->ru_stime.tv_usec = (long)(liWork.QuadPart % 1000000); // User time... liWork.HighPart = ftUser.dwHighDateTime; liWork.LowPart = ftUser.dwLowDateTime; liWork.QuadPart /= 10; // (convert to microseconds) r_usage->ru_utime.tv_sec = (long)(liWork.QuadPart / 1000000); r_usage->ru_utime.tv_usec = (long)(liWork.QuadPart % 1000000); return 0; } DLL_EXPORT int getrusage ( int who, struct rusage* r_usage ) { if ( !r_usage ) { errno = EFAULT; return -1; } if ( RUSAGE_SELF == who ) return DoGetRUsage( GetCurrentProcess(), r_usage ); if ( RUSAGE_CHILDREN != who ) { errno = EINVAL; return -1; } // RUSAGE_CHILDREN ... { DWORD dwOurProcessId = GetCurrentProcessId(); HANDLE hProcessSnap = NULL; PROCESSENTRY32 pe32; HANDLE hChildProcess; struct rusage child_usage; memset( &pe32, 0, sizeof(pe32) ); // Take a snapshot of all active processes... hProcessSnap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 ); if ( INVALID_HANDLE_VALUE == hProcessSnap ) return DoGetRUsage( INVALID_HANDLE_VALUE, r_usage ); pe32.dwSize = sizeof( PROCESSENTRY32 ); // Walk the snapshot... if ( !Process32First( hProcessSnap, &pe32 ) ) { CloseHandle( hProcessSnap ); return DoGetRUsage( INVALID_HANDLE_VALUE, r_usage ); } r_usage->ru_stime.tv_sec = r_usage->ru_stime.tv_usec = 0; r_usage->ru_utime.tv_sec = r_usage->ru_utime.tv_usec = 0; // Locate all children of the current process // and accumulate their process times together... do { if ( pe32.th32ParentProcessID != dwOurProcessId ) continue; hChildProcess = OpenProcess( PROCESS_QUERY_INFORMATION, FALSE, pe32.th32ProcessID ); DoGetRUsage( hChildProcess, &child_usage ); CloseHandle( hChildProcess ); VERIFY( timeval_add( &child_usage.ru_stime, &r_usage->ru_stime ) == 0 ); VERIFY( timeval_add( &child_usage.ru_utime, &r_usage->ru_utime ) == 0 ); } while ( Process32Next( hProcessSnap, &pe32 ) ); VERIFY( CloseHandle( hProcessSnap ) ); } return 0; } #endif ////////////////////////////////////////////////////////////////////////////////////////// #if !defined( HAVE_GETLOGIN_R ) DLL_EXPORT int getlogin_r ( char* name, size_t namesize ) { DWORD dwSize = (DWORD)namesize; if ( !name ) return EFAULT; if ( namesize < 2 || namesize > ( LOGIN_NAME_MAX + 1 ) ) return EINVAL; return ( GetUserName( name, &dwSize ) ? 0 : ERANGE ); } #endif ////////////////////////////////////////////////////////////////////////////////////////// #if !defined( HAVE_GETLOGIN ) DLL_EXPORT char* getlogin ( void ) { static char login_name [ LOGIN_NAME_MAX + 1 ]; int rc; if ( ( rc = getlogin_r ( login_name, sizeof(login_name) ) ) == 0 ) return login_name; errno = rc; return NULL; } #endif ////////////////////////////////////////////////////////////////////////////////////////// #if !defined( HAVE_REALPATH ) DLL_EXPORT char* realpath ( const char* file_name, char* resolved_name ) { char* retval; if ( !file_name || !resolved_name ) { errno = EINVAL; return NULL; } // PROGRAMMING NOTE: unfortunately there's no possible way to implement an accurate // Win32 port of realpath in regard to the errno values returned whenever there's an // error. The errno values that are set whenever realpath fails are quite precise, // telling you exactly what went wrong (name too long, invalid directory component, // etc), whereas _fullpath only returns success/failure with absolutely no indication // as to WHY it failed. To further complicate matters, there's no real "generic" type // of errno value we can choose to return to the caller should _fullpath fail either, // so for this implementation we purposely return EIO (i/o error) if _fullpath fails // for any reason. That may perhaps be somewhat misleading (since the actual cause of // the failure was probably not because of an i/o error), but returning any of the // OTHER possible realpath errno values would be even MORE misleading in my opinion. if ( !(retval = _fullpath( resolved_name, file_name, PATH_MAX ) ) ) errno = EIO; return retval; } #endif ////////////////////////////////////////////////////////////////////////////////////////// // Returns outpath as a host filesystem compatible filename path. // This is a Cygwin-to-MSVC transitional period helper function. // On non-Windows platforms it simply copies inpath to outpath. // On Windows it converts inpath of the form "/cygdrive/x/foo.bar" // to outpath in the form "x:/foo.bar" for Windows compatibility. DLL_EXPORT BYTE *hostpath( BYTE *outpath, const BYTE *inpath, size_t buffsize ) { // The possibilities: // a. Linux/Cygwin absolute: // /dir/foo.bar // b. Linux/Cygwin relative: // ../dir/foo.bar // ./dir/foo.bar // ../../.././dir/foo.bar // (etc) // c. Windows relative: // ./dir\foo.bar // ../dir\foo.bar // ..\dir\foo.bar // .\dir\foo.bar // ..\dir/foo.bar // .\dir/foo.bar // ../..\../.\dir/foo.bar // (etc) // d. Windows absolute // x:/dir/foo.bar // x:\dir\foo.bar // x:/dir\foo.bar // x:\dir/foo.bar // For case a we check for special Cygwin format "/cygdrive/x/..." // and convert it to "normalized" (forward-slash) case d format. // (Note that the slashes in this case MUST be forward slashes // or else the special Cygwin path format will not be detected!) // Case b we treat the same as case c. // For case c we simply convert all backslashes to forward slashes // since Windows supports both. // For case d we do nothing since it is already a Windows path // (other than normalize all backward slashes to forward slashes // since Windows supports both) // NOTE that we do NOT attempt to convert relative paths to absolute // paths! The caller is responsible for doing that themselves after // calling this function if so desired. if (outpath && buffsize) *outpath = 0; if (inpath && *inpath && outpath && buffsize > 1) { size_t inlen = strlen(inpath); if (1 && inlen >= 11 && strncasecmp(inpath,"/cygdrive/",10) == 0 && isalpha(inpath[10]) ) { *outpath++ = inpath[10]; buffsize--; if (buffsize > 1) { *outpath++ = ':'; buffsize--; } inpath += 11; } while (*inpath && --buffsize) { BYTE c = *inpath++; if (c == '\\') c = '/'; *outpath++ = c; } *outpath = 0; } return outpath; } ////////////////////////////////////////////////////////////////////////////////////////// // Poor man's "fcntl( fd, F_GETFL )"... // (only returns access-mode flags and not any others) DLL_EXPORT int get_file_accmode_flags( int fd ) { // PROGRAMMING NOTE: we unfortunately CANNOT use Microsoft's "_fstat" here // since it seems to always return the actual file's ATTRIBUTE permissions // and not the ACCESS MODE permissions specified when the file was opened! HANDLE hFile; BOOL bCanRead; BOOL bCanWrite; DWORD dwNumBytesToReadOrWrite; DWORD dwNumBytesReadOrWritten; char read_write_buffer; // TECHNIQUE: check whether or not we can "read" and/or "write" to the file // and return appropriate access-mode flags accordingly. Note that we do not // actually read nor write from/to the file per se, since we specify ZERO BYTES // for our "number of bytes to read/write" argument. This is valid under Win32 // and does not modify the file position and so is safe to do. All it does is // return the appropriate success/failure return code (e.g. ERROR_ACCESS_DENIED) // depending on whether the file was opened with the proper access permissions. hFile = (HANDLE) _get_osfhandle( fd ); if ( (HANDLE) -1 == hFile ) { errno = EBADF; // (probably not a valid opened file descriptor) return -1; } dwNumBytesToReadOrWrite = 0; // ZERO!!! (we don't wish to modify the file!) VERIFY( ( bCanRead = ReadFile ( hFile, &read_write_buffer, dwNumBytesToReadOrWrite, &dwNumBytesReadOrWritten, NULL ) ) || ERROR_ACCESS_DENIED == GetLastError() ); VERIFY( ( bCanWrite = WriteFile ( hFile, &read_write_buffer, dwNumBytesToReadOrWrite, &dwNumBytesReadOrWritten, NULL ) ) || ERROR_ACCESS_DENIED == GetLastError() ); // For reference, 'fcntl.h' defines the flags as follows: // // #define _O_RDONLY 0 // #define _O_WRONLY 1 // #define _O_RDWR 2 if ( bCanRead && bCanWrite ) return _O_RDWR; if ( bCanRead && !bCanWrite ) return _O_RDONLY; if ( !bCanRead && bCanWrite ) return _O_WRONLY; ASSERT( FALSE ); // (HUH?! Can neither read NOR write to the file?!) errno = EBADF; // (maybe they closed it before we could test it??) return -1; // (oh well) } ////////////////////////////////////////////////////////////////////////////////////////// // Retrieve directory where process was loaded from... // (returns >0 == success, 0 == failure) DLL_EXPORT int get_process_directory( char* dirbuf, size_t bufsiz ) { char process_exec_dirbuf[MAX_PATH]; char* p; DWORD dwDirBytes = GetModuleFileName(GetModuleHandle(NULL),process_exec_dirbuf,MAX_PATH); if (!dwDirBytes || dwDirBytes >= MAX_PATH) return 0; p = strrchr(process_exec_dirbuf,'\\'); if (p) *(p+1) = 0; strlcpy(dirbuf,process_exec_dirbuf,bufsiz); return strlen(dirbuf) ? 1 : 0; } ////////////////////////////////////////////////////////////////////////////////////////// // Expand environment variables... (e.g. %SystemRoot%, etc); 0==success DLL_EXPORT int expand_environ_vars( const char* inbuff, char* outbuff, DWORD outbufsiz ) { // If the function succeeds, the return value is the number of TCHARs // stored in the destination buffer, including the terminating null character. // If the destination buffer is too small to hold the expanded string, the // return value is the required buffer size, in TCHARs. If the function fails, // the return value is zero. DWORD dwOutLen = ExpandEnvironmentStrings( inbuff, outbuff, outbufsiz ); return ( ( dwOutLen && dwOutLen < outbufsiz ) ? 0 : -1 ); } ////////////////////////////////////////////////////////////////////////////////////////// // Initialize Hercules HOSTINFO structure DLL_EXPORT void w32_init_hostinfo( HOST_INFO* pHostInfo ) { CRITICAL_SECTION cs; OSVERSIONINFO vi; SYSTEM_INFO si; char* psz; DWORD dw; dw = sizeof(pHostInfo->nodename)-1; GetComputerName( pHostInfo->nodename, &dw ); pHostInfo->nodename[sizeof(pHostInfo->nodename)-1] = 0; vi.dwOSVersionInfoSize = sizeof(vi); VERIFY( GetVersionEx( &vi ) ); switch ( vi.dwPlatformId ) { case VER_PLATFORM_WIN32_WINDOWS: psz = "9X"; break; case VER_PLATFORM_WIN32_NT: psz = "NT"; break; default: psz = "??"; break; } #if defined(__MINGW32_VERSION) #define HWIN32_SYSNAME "MINGW32" #else #define HWIN32_SYSNAME "Windows" #endif _snprintf( pHostInfo->sysname, sizeof( pHostInfo->sysname)-1, HWIN32_SYSNAME "_%s", psz ); pHostInfo->sysname[ sizeof( pHostInfo->sysname)-1] = 0; _snprintf( pHostInfo->release, sizeof( pHostInfo->release)-1, "%d", vi.dwMajorVersion ); pHostInfo->release[ sizeof( pHostInfo->release)-1] = 0; _snprintf( pHostInfo->version, sizeof( pHostInfo->version)-1, "%d", vi.dwMinorVersion ); pHostInfo->version[ sizeof( pHostInfo->version)-1] = 0; GetSystemInfo( &si ); switch ( si.wProcessorArchitecture ) { case PROCESSOR_ARCHITECTURE_INTEL: { int n; if ( si.wProcessorLevel < 3 ) n = 3; else if ( si.wProcessorLevel > 9 ) n = 6; else n = si.wProcessorLevel; _snprintf( pHostInfo->machine, sizeof( pHostInfo->machine)-1, "i%d86", n ); pHostInfo->machine[ sizeof( pHostInfo->machine)-1] = 0; } break; // The following are missing from MinGW's supplied version of #define PROCESSOR_ARCHITECTURE_MSIL 8 #define PROCESSOR_ARCHITECTURE_AMD64 9 #define PROCESSOR_ARCHITECTURE_IA32_ON_WIN64 10 case PROCESSOR_ARCHITECTURE_IA64: strlcpy( pHostInfo->machine, "IA64" , sizeof(pHostInfo->machine) ); break; case PROCESSOR_ARCHITECTURE_AMD64: strlcpy( pHostInfo->machine, "AMD64" , sizeof(pHostInfo->machine) ); break; case PROCESSOR_ARCHITECTURE_IA32_ON_WIN64: strlcpy( pHostInfo->machine, "IA32_ON_WIN64" , sizeof(pHostInfo->machine) ); break; case PROCESSOR_ARCHITECTURE_ALPHA: strlcpy( pHostInfo->machine, "ALPHA" , sizeof(pHostInfo->machine) ); break; case PROCESSOR_ARCHITECTURE_MIPS: strlcpy( pHostInfo->machine, "MIPS" , sizeof(pHostInfo->machine) ); break; default: strlcpy( pHostInfo->machine, "???" , sizeof(pHostInfo->machine) ); break; } pHostInfo->num_procs = si.dwNumberOfProcessors; InitializeCriticalSection( &cs ); if ( !TryEnterCriticalSection( &cs ) ) pHostInfo->trycritsec_avail = 0; else { pHostInfo->trycritsec_avail = 1; LeaveCriticalSection( &cs ); } DeleteCriticalSection( &cs ); } ////////////////////////////////////////////////////////////////////////////////////////// // The function that creates us is responsible for initializing the below values // (as well as de-initialzing them too!) static DWORD dwThreadId = 0; // (Win32 thread-id of below thread) static HANDLE hThread = NULL; // (Win32 handle of below thread) static HANDLE hGotStdIn = NULL; // (signaled to get next char) static HANDLE hStdInAvailable = NULL; // (signaled when char avail) static HANDLE hStdIn = NULL; // (Win32 stdin handle) static char chStdIn = 0; // (the next char read from stdin) // Win32 worker thread that reads from stdin. It needs to be a thread because the // "ReadFile" on stdin 'hangs' (blocks) until there's actually some data to read // or the handle is closed, whichever comes first. Note that we only read one char // at a time. This may perhaps be slightly inefficient but it makes for a simpler // implementation and besides, we don't really expect huge gobs of data coming in. static DWORD WINAPI ReadStdInW32Thread( LPVOID lpParameter ) { DWORD dwBytesRead = 0; UNREFERENCED( lpParameter ); SET_THREAD_NAME ("ReadStdInW32Thread"); for (;;) { WaitForSingleObject( hGotStdIn, INFINITE ); if ( !ReadFile( hStdIn, &chStdIn, 1, &dwBytesRead, NULL ) ) { char szErrMsg[256]; DWORD dwLastError = GetLastError(); if ( ERROR_BROKEN_PIPE == dwLastError || sysblk.shutdown ) break; // (shutting down; time to exit) w32_w32errmsg( dwLastError, szErrMsg, sizeof(szErrMsg) ); logmsg ( _("HHCDG008W ReadFile(hStdIn) failed! dwLastError=%d (0x%08.8X): %s\n") ,dwLastError ,dwLastError ,szErrMsg ); continue; } ASSERT( 1 == dwBytesRead ); ResetEvent( hGotStdIn ); SetEvent( hStdInAvailable ); } return 0; } ////////////////////////////////////////////////////////////////////////////////////////// // Function to read the next character from stdin. Similar to 'getch' but allows // one to specify a maximum timeout value and thus doesn't block forever. Returns // 0 or 1: 0 == timeout (zero characters read), 1 == success (one character read), // or -1 == error (pCharBuff NULL). The worker thread is created on the 1st call. DLL_EXPORT int w32_get_stdin_char( char* pCharBuff, int wait_millisecs ) { if ( !pCharBuff ) { errno = EINVAL; return -1; } *pCharBuff = 0; if ( !dwThreadId ) { hStdIn = GetStdHandle( STD_INPUT_HANDLE ); hStdInAvailable = CreateEvent(NULL,TRUE,FALSE,NULL); hGotStdIn = CreateEvent(NULL,TRUE,TRUE,NULL); // (initially signaled) hThread = (HANDLE) _beginthreadex ( NULL, // pointer to security attributes 64*1024, // initial thread stack size in bytes ReadStdInW32Thread, // pointer to thread function NULL, // argument for new thread 0, // creation flags &dwThreadId // pointer to receive thread ID ); ASSERT(1 && hStdIn && INVALID_HANDLE_VALUE != hStdIn && hStdInAvailable && INVALID_HANDLE_VALUE != hStdInAvailable && hGotStdIn && INVALID_HANDLE_VALUE != hGotStdIn && hThread && INVALID_HANDLE_VALUE != hThread ); } if ( WAIT_TIMEOUT == WaitForSingleObject( hStdInAvailable, wait_millisecs ) ) return 0; *pCharBuff = chStdIn; // (save the next char right away) ResetEvent( hStdInAvailable ); // (reset OUR flag for next time) SetEvent( hGotStdIn ); // (allow thread to read next char) return 1; } /****************************************************************************************\ * * * (BEGIN) S O C K E T H A N D L I N G F U N C T I O N S (BEGIN) * * * \****************************************************************************************/ // ***** VERY IMPORTANT SPECIAL NOTE! ***** // Because "hmacros.h" #defines 'xxxx' to 'w32_xxxx' (to route the call to us), // we now need to #undef it here to allow us to call the actual 'xxxx' function // if we need to. All xxxx calls from here on will call the true Windows version. // To call the w32_xxxx function instead, simply call it directly yourself. #undef socket // (so we can call the actual Windows version if we need to) #undef select // (so we can call the actual Windows version if we need to) #undef fdopen // (so we can call the actual Windows version if we need to) #undef fwrite // (so we can call the actual Windows version if we need to) #undef fprintf // (so we can call the actual Windows version if we need to) #undef fclose // (so we can call the actual Windows version if we need to) ////////////////////////////////////////////////////////////////////////////////////////// /* INITIALIZE / DE-INITIALIZE SOCKETS PACKAGE The WSAStartup function must be the first Windows Sockets function called by an application or DLL. It allows an application or DLL to specify the version of Windows Sockets required and retrieve details of the specific Windows Sockets implementation. The application or DLL can only issue further Windows Sockets functions after successfully calling WSAStartup. Once an application or DLL has made a successful WSAStartup call, it can proceed to make other Windows Sockets calls as needed. When it has finished using the services of the WS2_32.DLL, the application or DLL must call WSACleanup to allow the WS2_32.DLL to free any resources for the application. *** IMPORTANT *** An application must call one WSACleanup call for every successful WSAStartup call to allow third-party DLLs to make use of a WS2_32.DLL on behalf of an application. This means, for example, that if an application calls WSAStartup three times, it must call WSACleanup three times. The first two calls to WSACleanup do nothing except decrement an internal counter; the final WSACleanup call for the task does all necessary resource deallocation for the task. */ DLL_EXPORT int socket_init ( void ) { /* In order to support future Windows Sockets implementations and applications that can have functionality differences from the current version of Windows Sockets, a negotiation takes place in WSAStartup. The caller of WSAStartup and the WS2_32.DLL indicate to each other the highest version that they can support, and each confirms that the other's highest version is acceptable. Upon entry to WSAStartup, the WS2_32.DLL examines the version requested by the application. If this version is equal to or higher than the lowest version supported by the DLL, the call succeeds and the DLL returns in wHighVersion the highest version it supports and in wVersion the minimum of its high version and wVersionRequested. The WS2_32.DLL then assumes that the application will use wVersion If the wVersion parameter of the WSADATA structure is unacceptable to the caller, it should call WSACleanup and either search for another WS2_32.DLL or fail to initialize. */ WSADATA sSocketPackageInfo; WORD wVersionRequested = MAKEWORD(1,1); return ( WSAStartup( wVersionRequested, &sSocketPackageInfo ) == 0 ? 0 : -1 ); } ////////////////////////////////////////////////////////////////////////////////////////// // De-initialize Windows Sockets package... DLL_EXPORT int socket_deinit ( void ) { // PROGRAMMING NOTE: regardless of the comments in the socket_init function above // regarding the need to always call WSACleanup for every WSAStartup call, it's not // really necessary in our particular case because we're not designed to continue // running after shutting down socket handling (which is really what the WSACleanup // function is designed for). That is to say, the WSACleanup function is designed // so a program can inform the operating system that it's finished using the socket // DLL (thus allowing it to free up all of the resources currently being used by // the process and allow the DLL to be unmapped from the process'es address space) // but not exit (i.e. continue running). In our case however, our entire process // is exiting (i.e. we're NOT going to continue running), and when a process exits, // all loaded DLLs are automatically notified by the operating system to allow them // to automatically free all resources for the process in question. Thus since we // are exiting we don't really need to call WSACleanup since whatever "cleanup" it // would do is going to get done *anyway* by virtue of our going away. Besides that, // WSACleanup appears to "hang" when it's called while socket resources are still // being used (which is true in our case since we're not designed (yet!) to cleanly // shutdown all of our socket-using threads before exiting). THUS (sorry to ramble) // we in fact probably SHOULDN'T be calling WSACleanup here (and besides, bypassing // it seems to resolve our hangs at shutdown whenever there's still a thread running // that doing sockets shit). #if 0 // (see above) return ( WSACleanup() == 0 ? 0 : -1 ); #else return 0; // (not needed? see PROGRAMING NOTE above!) #endif } ////////////////////////////////////////////////////////////////////////////////////////// // Retrieve unique host id DLL_EXPORT long gethostid( void ) { char szHostName[ WSADESCRIPTION_LEN ]; struct hostent* pHostent = NULL; return (gethostname( szHostName, sizeof(szHostName) ) == 0 && (pHostent = gethostbyname( szHostName )) != NULL) ? (long)(*(pHostent->h_addr)) : 0; } ////////////////////////////////////////////////////////////////////////////////////////// DLL_EXPORT int w32_socket( int af, int type, int protocol ) { /////////////////////////////////////////////////////////////////////////////// // // PROGRAMMING NOTE // // We need to request that all sockets we create [via the 'socket()' API] // be created WITHOUT the "OVERLAPPED" attribute so that our 'fgets()', etc, // calls (which end up calling the "ReadFile()", etc, Win32 API) work as // expected. // // Note that the "overlapped" attribute for a socket is completely different // from its non-blocking vs. blocking mode. All sockets are created, by default, // as blocking mode sockets, but WITH the "overlapped" attribute set. Thus all // sockets are actually asynchonous by default. (The winsock DLL(s) handle the // blocking mode separately programmatically internally even though the socket // is actually an asynchronous Win32 "file"). // // Thus we need to specifically request that our [blocking mode] sockets be // created WITHOUT the Win32 "OVERLAPPED" attribute (so that when we call the // C runtime read/write/etc functions, the C runtime's ReadFile/WriteFile calls // work (which they don't (they fail with error 87 ERROR_INVALID_PARAMETER) // when called on a Win32 "file" handle created with the OVERLAPPED attribute // but without an OVERLAPPED structure pased in the ReadFile/WriteFile call // (which the C runtime functions don't use)). You follow?). // // See KB (Knowledge Base) article 181611 for more information: // // "Socket overlapped I/O versus blocking/non-blocking mode" // (http://support.microsoft.com/?kbid=181611) // // --------------------------------------------------------------------- // "However, you can call the setsockopt API with SO_OPENTYPE option // on any socket handle -- including an INVALID_SOCKET -- to change // the overlapped attributes for all successive socket calls in the // same thread. The default SO_OPENTYPE option value is 0, which sets // the overlapped attribute. All non-zero option values make the socket // synchronous and make it so that you cannot use a completion function." // --------------------------------------------------------------------- // // The documentation for the "SOL_SOCKET" SO_OPENTYPE socket option contains // the folowing advice/warning however: // // // "Once set, subsequent sockets created will be non-overlapped. // This option should not be used; use WSASocket and leave the // WSA_FLAG_OVERLAPPED turned off." // // // So we'll use WSASocket instead as suggested. // /////////////////////////////////////////////////////////////////////////////// // The last parameter is where one would normally specify the WSA_FLAG_OVERLAPPED // option, but we're specifying '0' because we want our sockets to be synchronous // and not asynchronous so the C runtime functions can successfully perform ReadFile // and WriteFile on them... SOCKET sock = WSASocket( af, type, protocol, NULL, 0, 0 ); if ( INVALID_SOCKET == sock ) { errno = WSAGetLastError(); sock = (SOCKET) -1; } return ( (int) sock ); } ////////////////////////////////////////////////////////////////////////////////////////// // Determine whether a file descriptor is a socket or not... // (returns 1==true if it's a socket, 0==false otherwise) DLL_EXPORT int socket_is_socket( int sfd ) { u_long dummy; return WSAHtonl( (SOCKET) sfd, 666, &dummy ) == 0 ? 1 : 0; } ////////////////////////////////////////////////////////////////////////////////////////// // Set the SO_KEEPALIVE option and timeout values for a // socket connection to detect when client disconnects */ DLL_EXPORT void socket_keepalive( int sfd, int idle_time, int probe_interval, int probe_count ) { DWORD dwBytesReturned; // (not used) struct tcp_keepalive ka; ka.onoff = TRUE; ka.keepalivetime = idle_time * 1000; ka.keepaliveinterval = probe_interval * 1000; UNREFERENCED(probe_count); // It either works or it doesn't // PROGRAMMING NOTE: the 'dwBytesReturned' value must apparently always be // specified in order for this call to work at all. If you don't specify it, // even though the call succeeds (does not return an error), the automatic // keep-alive polling does not occur! if (0 != WSAIoctl ( (SOCKET)sfd, // [in] Descriptor identifying a socket SIO_KEEPALIVE_VALS, // [in] Control code of operation to perform &ka, // [in] Pointer to the input buffer sizeof(ka), // [in] Size of the input buffer, in bytes NULL, // [out] Pointer to the output buffer 0, // [in] Size of the output buffer, in bytes &dwBytesReturned, // [out] Pointer to actual number of bytes of output NULL, // [in] Pointer to a WSAOVERLAPPED structure // (ignored for nonoverlapped sockets) NULL // [in] Pointer to the completion routine called // when the operation has been completed // (ignored for nonoverlapped sockets) )) { DWORD dwLastError = WSAGetLastError(); TRACE("*** WSAIoctl(SIO_KEEPALIVE_VALS) failed; rc %d: %s\n", dwLastError, w32_strerror(dwLastError) ); ASSERT(1); // (in case we're debugging) } } ////////////////////////////////////////////////////////////////////////////////////////// // The inet_aton() function converts the specified string, // in the Internet standard dot notation, to a network address, // and stores the address in the structure provided. // // The inet_aton() function returns 1 if the address is successfully converted, // or 0 if the conversion failed. #if !defined( HAVE_INET_ATON ) DLL_EXPORT int inet_aton( const char* cp, struct in_addr* addr ) { // Return success as long as both args are not NULL *and* // the result is not INADDR_NONE (0xFFFFFFFF), -OR- if it // is [INADDR_NONE], [we return success] if that is the // actual expected value of the conversion... return ( (1 && cp // (must not be NULL) && addr // (must not be NULL) && (0 || INADDR_NONE != ( addr->s_addr = inet_addr( cp ) ) || strcmp( cp, "255.255.255.255" ) == 0 ) ) ? 1 : 0 // 1 == success, 0 == failure ); } #endif // !defined( HAVE_INET_ATON ) ////////////////////////////////////////////////////////////////////////////////////////// // All internal calls to Windows's 'FD_ISSET' or 'FD_SET' macros MUST use the below // macros instead and NOT the #defined 'FD_ISSET' or 'FD_SET' macros! The #defined // 'FD_ISSET' and 'FD_SET' macros are coded (in hmacros.h) to route the calls to the // internal 'w32_FD_SET' and 'w32_FD_ISSET' functions further below! #define ORIGINAL_FD_ISSET __WSAFDIsSet #define ORIGINAL_FD_SET( fd, pSet ) \ do \ { \ unsigned int i; \ for (i=0; i < ((fd_set*)(pSet))->fd_count; i++) \ if (((fd_set*)(pSet))->fd_array[i] == (fd)) \ break; \ if (i == ((fd_set*)(pSet))->fd_count \ && ((fd_set*)(pSet))->fd_count < FD_SETSIZE) \ { \ ((fd_set*)(pSet))->fd_array[i] = (fd); \ ((fd_set*)(pSet))->fd_count++; \ } \ } \ while (0) ////////////////////////////////////////////////////////////////////////////////////////// // FD_SET: ( FD_SET(fd,pSet) ) // // Will need to override and route to "w32_FD_SET" // // Do '_get_osfhandle'. // // If '_get_osfhandle' error, then it's either already a HANDLE (SOCKET probably), // or else a bona fide invalid file descriptor or invalid SOCKET handle, so do a // normal FD_SET. // // Otherwise ('_get_osfhandle' success), then it WAS a file descriptor // but we now have it's HANDLE, so do the FD_SET on the returned HANDLE. // // Thus we ensure all entries added to set are HANDLES // (or SOCKETS which are considered to be HANDLES too) DLL_EXPORT void w32_FD_SET( int fd, fd_set* pSet ) { SOCKET hSocket; if (0 || socket_is_socket( fd ) || (SOCKET) -1 == ( hSocket = (SOCKET) _get_osfhandle( fd ) ) ) hSocket = (SOCKET) fd; ORIGINAL_FD_SET( hSocket, pSet ); // (add HANDLE/SOCKET to specified set) } ////////////////////////////////////////////////////////////////////////////////////////// // FD_ISSET: ( FD_ISSET(fd,pSet) ) // // Will need to override and route to "w32_FD_ISSET". // // (Note: all entries in sets should already be HANDLES // due to previously mentioned FD_SET override) // // If socket, do normal FD_ISSET. // Otherwise do our IsEventSet(). DLL_EXPORT int w32_FD_ISSET( int fd, fd_set* pSet ) { int i; HANDLE hFile; if ( socket_is_socket( fd ) ) // (is it already a SOCKET?) return ORIGINAL_FD_ISSET( (SOCKET)fd, pSet ); // (yes, do normal FD_ISSET) hFile = (HANDLE) _get_osfhandle( fd ); for ( i=0; i < (int)pSet->fd_count; i++ ) if ( pSet->fd_array[i] == (SOCKET) hFile ) // (is this the file?) return IsEventSet( hFile ); // (yes, return whether ready (signaled) or not) return 0; // (file not a member of the specified set) } ////////////////////////////////////////////////////////////////////////////////////////// // Win32 "socketpair()" and "pipe()" functionality... #if !defined( HAVE_SOCKETPAIR ) DLL_EXPORT int socketpair( int domain, int type, int protocol, int socket_vector[2] ) { // PROGRAMMING NOTE: we do NOT support type AF_UNIX socketpairs on Win32. // we *ONLY* support AF_INET, IPPROTO_IP, SOCK_STREAM. SOCKET temp_listen_socket; struct sockaddr_in localhost_addr; int len = sizeof(localhost_addr); /* FIXME ISW ? In some situations, it seems the sockaddr_in structure */ /* returned by getsockname() isn't appropriate for use */ /* by connect(). We therefore use another sockaddr_in for the */ /* sole purpose of fetching the automatic port number issued */ /* during the bind() operation. */ /* NOTE : This is a workaround. The actual root cause for this */ /* problem is presently unknown because it is hard to reproduce*/ struct sockaddr_in tempaddr; int talen = sizeof(tempaddr); // Technique: create a pair of sockets bound to each other by first creating a // temporary listening socket bound to the localhost loopback address (127.0.0.1) // and then having the other socket connect to it... // "Upon successful completion, 0 shall be returned; otherwise, // -1 shall be returned and errno set to indicate the error." if ( AF_INET != domain ) { errno = WSAEAFNOSUPPORT; return -1; } if ( SOCK_STREAM != type ) { errno = WSAEPROTONOSUPPORT; return -1; } if ( IPPROTO_IP != protocol ) { errno = WSAEPROTOTYPE; return -1; } socket_vector[0] = socket_vector[1] = INVALID_SOCKET; if ( INVALID_SOCKET == (temp_listen_socket = socket( AF_INET, SOCK_STREAM, 0 )) ) { errno = (int)WSAGetLastError(); return -1; } memset( &localhost_addr, 0, len ); memset( &tempaddr, 0, talen ); localhost_addr.sin_family = AF_INET; localhost_addr.sin_port = htons( 0 ); localhost_addr.sin_addr.s_addr = htonl( INADDR_LOOPBACK ); if (0 || SOCKET_ERROR == bind( temp_listen_socket, (SOCKADDR*) &localhost_addr, len ) || SOCKET_ERROR == listen( temp_listen_socket, 1 ) || SOCKET_ERROR == getsockname( temp_listen_socket, (SOCKADDR*) &tempaddr, &talen ) || INVALID_SOCKET == (SOCKET)( socket_vector[1] = socket( AF_INET, SOCK_STREAM, 0 ) ) ) { int nLastError = (int)WSAGetLastError(); closesocket( temp_listen_socket ); errno = nLastError; return -1; } /* Get the temporary port number assigned automatically */ /* by bind(127.0.0.1/0) */ localhost_addr.sin_port = tempaddr.sin_port; if (0 || SOCKET_ERROR == connect( socket_vector[1], (SOCKADDR*) &localhost_addr, len ) || INVALID_SOCKET == (SOCKET)( socket_vector[0] = accept( temp_listen_socket, (SOCKADDR*) &localhost_addr, &len ) ) ) { int nLastError = (int)WSAGetLastError(); closesocket( socket_vector[1] ); socket_vector[1] = INVALID_SOCKET; closesocket( temp_listen_socket ); errno = nLastError; return -1; } closesocket( temp_listen_socket ); return 0; } #endif // !defined( HAVE_SOCKETPAIR ) ////////////////////////////////////////////////////////////////////////////////////////// // Set socket to blocking or non-blocking mode... DLL_EXPORT int socket_set_blocking_mode( int sfd, int blocking_mode ) { u_long non_blocking_option = !blocking_mode; if ( SOCKET_ERROR != ioctlsocket( sfd, FIONBIO, &non_blocking_option) ) return 0; switch (WSAGetLastError()) { case WSAENETDOWN: errno = ENETDOWN; break; case WSAENOTSOCK: errno = ENOTSOCK; break; case WSAEFAULT: errno = EFAULT; break; default: errno = ENOSYS; break; } return -1; } ////////////////////////////////////////////////////////////////////////////////////////// // select: // // Will need to override and route to "w32_select" // // w32_select: // // Check if all entries (in all sets) are sockets or not // // (Note: all entries in sets should already be HANDLES // due to previously mentioned FD_SET override) // // If all sockets, then do normal 'select'. // // If all non-sockets, then do 'WaitForMultipleObjects' instead. // // if mixed, then EBADF (one or more bad file descriptors) static void SelectSet // (helper function) ( fd_set* pSet, BOOL* pbSocketFound, BOOL* pbNonSocketFound, DWORD* pdwHandles, HANDLE* parHandles ); DLL_EXPORT int w32_select ( int nfds, fd_set* pReadSet, fd_set* pWriteSet, fd_set* pExceptSet, const struct timeval* pTimeVal, const char* pszSourceFile, int nLineNumber ) { HANDLE arHandles[ 2 * FD_SETSIZE ]; // (max read + write set size) DWORD dwHandles = 0; BOOL bSocketFound = FALSE; BOOL bNonSocketFound = FALSE; BOOL bExceptSetSocketFound = FALSE; BOOL bExceptSetNonSocketFound = FALSE; DWORD dwWaitMilliSeconds = 0; DWORD dwWaitRetCode = 0; UNREFERENCED( nfds ); // Quick check for 'timer.c' call wherein all passed fd_set pointers are NULL... if ( !pReadSet && !pWriteSet && !pExceptSet ) { ASSERT( pTimeVal ); // (why else would we be called?!) if ( !pTimeVal ) { logmsg( "** Win32 porting error: invalid call to 'w32_select' from %s(%d): NULL args\n", pszSourceFile, nLineNumber ); errno = EINVAL; return -1; } // Sleep for the specified time period... if ( !pTimeVal->tv_sec && !pTimeVal->tv_usec ) sched_yield(); else { if ( pTimeVal->tv_sec ) sleep( pTimeVal->tv_sec ); if ( pTimeVal->tv_usec ) usleep( pTimeVal->tv_usec ); } return 0; } // Check for mixed sets and build HANDLE array... // (Note: we don't support except sets for non-sockets) SelectSet( pReadSet, &bSocketFound, &bNonSocketFound, &dwHandles, arHandles ); SelectSet( pWriteSet, &bSocketFound, &bNonSocketFound, &dwHandles, arHandles ); SelectSet( pExceptSet, &bExceptSetSocketFound, &bExceptSetNonSocketFound, NULL, NULL ); if (0 || ( bSocketFound && ( bNonSocketFound || bExceptSetNonSocketFound ) ) || ( bNonSocketFound && ( bSocketFound || bExceptSetSocketFound ) ) ) { logmsg( "** Win32 porting error: invalid call to 'w32_select' from %s(%d): mixed set(s)\n", pszSourceFile, nLineNumber ); errno = EBADF; return -1; } if ( bExceptSetNonSocketFound ) { logmsg( "** Win32 porting error: invalid call to 'w32_select' from %s(%d): non-socket except set\n", pszSourceFile, nLineNumber ); errno = EBADF; return -1; } // If all SOCKETs, do a normal 'select'... if ( bSocketFound ) return select( nfds, pReadSet, pWriteSet, pExceptSet, pTimeVal ); // Otherwise they're all HANDLEs, so do a WaitForMultipleObjects... if ( !pTimeVal ) dwWaitMilliSeconds = INFINITE; else { dwWaitMilliSeconds = ( pTimeVal->tv_sec * 1000 ); dwWaitMilliSeconds += ( ( pTimeVal->tv_usec + 500 ) / 1000 ); } if ( !dwHandles ) { // Just sleep for the specified interval... Sleep( dwWaitMilliSeconds ); return 0; // (timeout) } dwWaitRetCode = WaitForMultipleObjects( dwHandles, arHandles, FALSE, dwWaitMilliSeconds ); if ( WAIT_TIMEOUT == dwWaitRetCode ) return 0; // NOTE: we don't support returning the actual total number of handles // that are ready; instead, we return 1 as long as ANY handle is ready... if ( dwWaitRetCode >= WAIT_OBJECT_0 && dwWaitRetCode < ( WAIT_OBJECT_0 + dwHandles ) ) return 1; // Something went wrong... ASSERT( FALSE ); // (in case this is a debug build) errno = ENOSYS; // (system call failure) return -1; } ////////////////////////////////////////////////////////////////////////////////////////// // internal helper function to pre-process a 'select' set... static void SelectSet ( fd_set* pSet, BOOL* pbSocketFound, BOOL* pbNonSocketFound, DWORD* pdwHandles, HANDLE* parHandles ) { unsigned int i; if ( !pSet ) return; for (i=0; i < pSet->fd_count && i < FD_SETSIZE; i++) { if ( socket_is_socket( pSet->fd_array[i] ) ) { *pbSocketFound = TRUE; continue; } *pbNonSocketFound = TRUE; // If parHandles is NULL, then we're // only interested in the BOOLean flags... if ( !parHandles ) continue; ASSERT( *pdwHandles < ( 2 * FD_SETSIZE ) ); *( parHandles + *pdwHandles ) = (HANDLE) pSet->fd_array[i]; *pdwHandles++; } } ////////////////////////////////////////////////////////////////////////////////////////// struct MODE_TRANS { const char* old_mode; const char* new_mode; int new_flags; }; typedef struct MODE_TRANS MODE_TRANS; DLL_EXPORT FILE* w32_fdopen( int their_fd, const char* their_mode ) { int new_fd, new_flags = 0; const char* new_mode = NULL; MODE_TRANS* pModeTransTab; MODE_TRANS mode_trans_tab[] = { { "r", "rbc", _O_RDONLY | _O_BINARY }, { "r+", "r+bc", _O_RDWR | _O_BINARY }, { "r+b", "r+bc", _O_RDWR | _O_BINARY }, { "rb+", "r+bc", _O_RDWR | _O_BINARY }, { "w", "wbc", _O_WRONLY | _O_CREAT | _O_TRUNC | _O_BINARY }, { "w+", "w+bc", _O_RDWR | _O_CREAT | _O_TRUNC | _O_BINARY }, { "w+b", "w+bc", _O_RDWR | _O_CREAT | _O_TRUNC | _O_BINARY }, { "wb+", "w+bc", _O_RDWR | _O_CREAT | _O_TRUNC | _O_BINARY }, { "a", "abc", _O_WRONLY | _O_CREAT | _O_APPEND | _O_BINARY }, { "a+", "a+bc", _O_RDWR | _O_CREAT | _O_APPEND | _O_BINARY }, { "a+b", "a+bc", _O_RDWR | _O_CREAT | _O_APPEND | _O_BINARY }, { "ab+", "a+bc", _O_RDWR | _O_CREAT | _O_APPEND | _O_BINARY }, { NULL, NULL, 0 } }; ASSERT( their_mode ); // (we're only interested in socket calls) if ( !socket_is_socket( their_fd ) ) return _fdopen( their_fd, their_mode ); // The passed "file descriptor" is actually a SOCKET handle... // Translate their original mode to our new mode // and determine what flags we should use in our // call to _open_osfhandle()... if ( their_mode ) for (pModeTransTab = mode_trans_tab; pModeTransTab->old_mode; pModeTransTab++) if ( strcmp( their_mode, pModeTransTab->old_mode ) == 0 ) { new_mode = pModeTransTab->new_mode; new_flags = pModeTransTab->new_flags; break; } if ( !new_mode ) { errno = EINVAL; return NULL; } // Allocate a CRT file descriptor integer for this SOCKET... if ( ( new_fd = _open_osfhandle( their_fd, new_flags ) ) < 0 ) return NULL; // (errno already set) // Now we should be able to do the actual fdopen... return _fdopen( new_fd, new_mode ); } ////////////////////////////////////////////////////////////////////////////////////////// // fwrite DLL_EXPORT size_t w32_fwrite ( const void* buff, size_t size, size_t count, FILE* stream ) { int rc; SOCKET sock; ASSERT( buff && (size * count) && stream ); { int sd = fileno( stream ); if ( !socket_is_socket( sd ) ) return fwrite( buff, size, count, stream ); sock = (SOCKET) _get_osfhandle( sd ); } if ( ( rc = send( sock, buff, (int)(size * count), 0 ) ) == SOCKET_ERROR ) { errno = WSAGetLastError(); return -1; } return ( rc / size ); } ////////////////////////////////////////////////////////////////////////////////////////// // fprintf DLL_EXPORT int w32_fprintf( FILE* stream, const char* format, ... ) { char* buff = NULL; int bytes = 0, rc; va_list vl; SOCKET sock; ASSERT( stream && format ); va_start( vl, format ); { int sd = fileno( stream ); if ( !socket_is_socket( sd ) ) return vfprintf( stream, format, vl ); sock = (SOCKET) _get_osfhandle( sd ); } do { free( buff ); if ( !( buff = malloc( bytes += 1000 ) ) ) { errno = ENOMEM; return -1; } } while ( ( rc = vsnprintf( buff, bytes, format, vl ) ) < 0 ); rc = send( sock, buff, bytes = rc, 0 ); free( buff ); if ( SOCKET_ERROR == rc ) { errno = WSAGetLastError(); return -1; } return rc; } ////////////////////////////////////////////////////////////////////////////////////////// // fclose DLL_EXPORT int w32_fclose ( FILE* stream ) { int sd, rc, err; SOCKET sock; ASSERT( stream ); sd = fileno( stream ); if ( !socket_is_socket( sd ) ) return fclose( stream ); // (SOCKETs get special handling) sock = (SOCKET) _get_osfhandle( sd ); // Flush the data, close the socket, then deallocate // the crt's file descriptor for it by calling fclose. // Note that the fclose will fail since the closesocket // has already closed the o/s handle, but we don't care; // all we care about is the crt deallocating its file // descriptor for it... fflush( stream ); // (flush buffers) shutdown( sock, SD_BOTH); // (try to be graceful) rc = closesocket( sock ); // (close socket) err = WSAGetLastError(); // (save retcode) fclose( stream ); // (ignore likely error) if ( SOCKET_ERROR == rc ) // (closesocket error?) { errno = err; // (yes, return error) return EOF; // (failed) } return 0; // (success) } /****************************************************************************************\ (END) (Socket Handling Functions) (END) \****************************************************************************************/ // Create a child process with redirected standard file HANDLEs... // // For more information, see KB article 190351 "HOWTO: Spawn Console Processes // with Redirected Standard Handles" http://support.microsoft.com/?kbid=190351 #define PIPEBUFSIZE (1024) // SHOULD be big enough!! #define HOLDBUFSIZE (PIPEBUFSIZE*2) // twice pipe buffer size #define PIPE_THREAD_STACKSIZE (64*1024) // 64K should be plenty!! #define MSG_TRUNCATED_MSG "...(truncated)\n" char* buffer_overflow_msg = NULL; // used to trim received message size_t buffer_overflow_msg_len = 0; // length of above truncation msg ////////////////////////////////////////////////////////////////////////////////////////// // Fork control... typedef struct _PIPED_PROCESS_CTL { char* pszBuffer; // ptr to current logmsgs buffer size_t nAllocSize; // allocated size of logmsgs buffer size_t nStrLen; // amount used - 1 (because of NULL) CRITICAL_SECTION csLock; // lock for accessing above buffer } PIPED_PROCESS_CTL; typedef struct _PIPED_THREAD_CTL { HANDLE hStdXXX; // stdout or stderr handle PIPED_PROCESS_CTL* pPipedProcessCtl; // ptr to process control } PIPED_THREAD_CTL; ////////////////////////////////////////////////////////////////////////////////////////// // "Poor man's" fork... UINT WINAPI w32_read_piped_process_stdxxx_output_thread ( void* pThreadParm ); // (fwd ref) DLL_EXPORT pid_t w32_poor_mans_fork ( char* pszCommandLine, int* pnWriteToChildStdinFD ) { HANDLE hChildReadFromStdin; // child's stdin pipe HANDLE (inherited from us) HANDLE hChildWriteToStdout; // child's stdout pipe HANDLE (inherited from us) HANDLE hChildWriteToStderr; // child's stderr pipe HANDLE (inherited from us) HANDLE hOurWriteToStdin; // our HANDLE to write-end of child's stdin pipe HANDLE hOurReadFromStdout; // our HANDLE to read-end of child's stdout pipe HANDLE hOurReadFromStderr; // our HANDLE to read-end of child's stderr pipe HANDLE hOurProcess; // (temporary for creating pipes) HANDLE hPipeReadHandle; // (temporary for creating pipes) HANDLE hPipeWriteHandle; // (temporary for creating pipes) HANDLE hWorkerThread; // (worker thread to monitor child's pipe) DWORD dwThreadId; // (worker thread to monitor child's pipe) STARTUPINFO siStartInfo; // (info passed to CreateProcess) PROCESS_INFORMATION piProcInfo; // (info returned by CreateProcess) SECURITY_ATTRIBUTES saAttr; // (suckurity? we dunt need no stinkin suckurity!) char* pszNewCommandLine; // (because we build pvt copy for CreateProcess) BOOL bSuccess; // (work) int rc; // (work) size_t len; // (work) PIPED_PROCESS_CTL* pPipedProcessCtl = NULL; PIPED_THREAD_CTL* pPipedStdOutThreadCtl = NULL; PIPED_THREAD_CTL* pPipedStdErrThreadCtl = NULL; ////////////////////////////////////////////////// // Initialize fields... buffer_overflow_msg = MSG_TRUNCATED_MSG; buffer_overflow_msg_len = strlen( buffer_overflow_msg ); saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); saAttr.lpSecurityDescriptor = NULL; // (we dunt need no stinkin suckurity!) saAttr.bInheritHandle = TRUE; // (allows our inheritable HANDLEs // to be inherited by child) hOurProcess = GetCurrentProcess(); // (for creating pipes) ////////////////////////////////////////////////// // Only create a stdin pipe if caller will be providing the child's stdin data... if (!pnWriteToChildStdinFD) // (will caller be providing child's stdin?) { // PROGRAMMING NOTE: KB article 190351 "HOWTO: Spawn Console Processes with // Redirected Standard Handles" http://support.microsoft.com/?kbid=190351 // is WRONG! (or at the very least quite misleading!) // It states that for those stdio handles you do NOT wish to redirect, you // should use "GetStdHandle(STD_xxx_HANDLE)", but that ONLY works when you // have a console to begin with! (which Hercules would NOT have when started // via HercGUI for example (since it specifies "DETACHED_PROCESS" (i.e. no // console) whenever it starts it via its own CreateProcess call). // If you wish to only redirect *some* (but NOT *all*) stdio handles in your // CreateProcess call, the ONLY way to properly do so (regardless of whether // you have a console or not) is by specifying NULL. Specifying NULL for your // stdio handle tells CreateProcess to use the default value for that HANDLE. hChildReadFromStdin = NULL; // (no stdin redirection; use default) } else { // Create Stdin pipe for sending data to child... VERIFY(CreatePipe(&hChildReadFromStdin, &hPipeWriteHandle, &saAttr, PIPEBUFSIZE)); // Create non-inheritable duplcate of pipe handle for our own private use... VERIFY(DuplicateHandle ( hOurProcess, hPipeWriteHandle, // (handle to be duplicated) hOurProcess, &hOurWriteToStdin, // (non-inheritable duplicate) 0, FALSE, // (prevents child from inheriting it) DUPLICATE_SAME_ACCESS )); VERIFY(CloseHandle(hPipeWriteHandle)); // (MUST close so child won't hang!) } ////////////////////////////////////////////////// // Pipe child's Stdout output back to us... VERIFY(CreatePipe(&hPipeReadHandle, &hChildWriteToStdout, &saAttr, PIPEBUFSIZE)); // Create non-inheritable duplcate of pipe handle for our own private use... VERIFY(DuplicateHandle ( hOurProcess, hPipeReadHandle, // (handle to be duplicated) hOurProcess, &hOurReadFromStdout, // (non-inheritable duplicate) 0, FALSE, // (prevents child from inheriting it) DUPLICATE_SAME_ACCESS )); VERIFY(CloseHandle(hPipeReadHandle)); // (MUST close so child won't hang!) ////////////////////////////////////////////////// // Pipe child's Stderr output back to us... VERIFY(CreatePipe(&hPipeReadHandle, &hChildWriteToStderr, &saAttr, PIPEBUFSIZE)); // Create non-inheritable duplcate of pipe handle for our own private use... VERIFY(DuplicateHandle ( hOurProcess, hPipeReadHandle, // (handle to be duplicated) hOurProcess, &hOurReadFromStderr, // (non-inheritable duplicate) 0, FALSE, // (prevents child from inheriting it) DUPLICATE_SAME_ACCESS )); VERIFY(CloseHandle(hPipeReadHandle)); // (MUST close so child won't hang!) ////////////////////////////////////////////////// // Prepare for creation of child process... ZeroMemory(&piProcInfo, sizeof(PROCESS_INFORMATION)); ZeroMemory(&siStartInfo, sizeof(STARTUPINFO )); siStartInfo.cb = sizeof(STARTUPINFO); // (size of structure) siStartInfo.dwFlags = STARTF_USESTDHANDLES; // (use redirected std HANDLEs) siStartInfo.hStdInput = hChildReadFromStdin; // (use redirected std HANDLEs) siStartInfo.hStdOutput = hChildWriteToStdout; // (use redirected std HANDLEs) siStartInfo.hStdError = hChildWriteToStderr; // (use redirected std HANDLEs) // Build the command-line for the system to create the child process with... len = strlen(pszCommandLine) + 1; pszNewCommandLine = malloc( len ); strlcpy( pszNewCommandLine, pszCommandLine, len ); ////////////////////////////////////////////////// // Now actually create the child process... ////////////////////////////////////////////////// bSuccess = CreateProcess ( NULL, // name of executable module = from command-line pszNewCommandLine, // command line with arguments NULL, // process security attributes = use defaults NULL, // primary thread security attributes = use defaults TRUE, // HANDLE inheritance flag = allow // (required when STARTF_USESTDHANDLES flag is used) 0, // NOTE! >>>---> // UNDOCUMENTED SECRET! MUST BE ZERO! Can't be "CREATE_NO_WINDOW" // nor "DETACHED_PROCESS", etc, or else it sometimes doesn't work // or else a console window appears! ("ipconfig" being one such // example). THIS IS NOT DOCUMENTED *ANYWHERE* IN ANY MICROSOFT // DOCUMENTATION THAT I COULD FIND! I only stumbled across it by // sheer good fortune in a news group post after some intensive // Googling and have experimentally verified it works as desired. NULL, // environment block ptr = make a copy from parent's NULL, // initial working directory = same as parent's &siStartInfo, // input STARTUPINFO pointer &piProcInfo // output PROCESS_INFORMATION ); rc = GetLastError(); // (save return code) // Close the HANDLEs we don't need... if (pnWriteToChildStdinFD) VERIFY(CloseHandle(hChildReadFromStdin)); // (MUST close so child won't hang!) VERIFY(CloseHandle(hChildWriteToStdout)); // (MUST close so child won't hang!) VERIFY(CloseHandle(hChildWriteToStderr)); // (MUST close so child won't hang!) CloseHandle(piProcInfo.hThread); // (we don't need this one) free(pszNewCommandLine); // (not needed anymore) // Check results... if (!bSuccess) { TRACE("*** CreateProcess() failed! rc = %d : %s\n", rc,w32_strerror(rc)); if (pnWriteToChildStdinFD) VERIFY(CloseHandle(hOurWriteToStdin)); VERIFY(CloseHandle(hOurReadFromStdout)); VERIFY(CloseHandle(hOurReadFromStderr)); errno = rc; return -1; } // Allocate/intialize control blocks for piped process/thread control... // If we were passed a pnWriteToChildStdinFD pointer, then the caller // is in charge of the process and will handle message capturing/logging // (such as is done with the print-to-pipe facility). // Otherwise (pnWriteToChildStdinFD is NULL) the caller wishes for us // to capture the piped process's o/p, so we pass a PIPED_PROCESS_CTL // structure to the stdout/stderr monitoring threads. This structure // contains a pointer to a buffer where they can accumulate messages. // Then once the process exits WE will then issue the "logmsg". This // is necessary in order to "capture" the process's o/p since the logmsg // capture facility is designed to capture o/p for a specific thread, // where that thread is US! (else if we let the monitoring thread issue // the logmsg's, they'll never get captured since they don't have the // same thread-id as the thread that started the capture, which was us! // (actually it was the caller, but we're the same thread as they are!)). pPipedStdOutThreadCtl = malloc( sizeof(PIPED_THREAD_CTL) ); pPipedStdErrThreadCtl = malloc( sizeof(PIPED_THREAD_CTL) ); pPipedStdOutThreadCtl->hStdXXX = hOurReadFromStdout; pPipedStdErrThreadCtl->hStdXXX = hOurReadFromStderr; if ( !pnWriteToChildStdinFD ) { pPipedProcessCtl = malloc( sizeof(PIPED_PROCESS_CTL) ); pPipedStdOutThreadCtl->pPipedProcessCtl = pPipedProcessCtl; pPipedStdErrThreadCtl->pPipedProcessCtl = pPipedProcessCtl; InitializeCriticalSection( &pPipedProcessCtl->csLock ); pPipedProcessCtl->nAllocSize = 1; // (purposely small for debugging) pPipedProcessCtl->pszBuffer = malloc( 1 ); // (purposely small for debugging) *pPipedProcessCtl->pszBuffer = 0; // (null terminate string buffer) pPipedProcessCtl->nStrLen = 0; // (no msgs yet) } else { pPipedStdOutThreadCtl->pPipedProcessCtl = NULL; pPipedStdErrThreadCtl->pPipedProcessCtl = NULL; } ////////////////////////////////////////////////// // Create o/p pipe monitoring worker threads... ////////////////////////////////////////////////// // Stdout... hWorkerThread = (HANDLE) _beginthreadex ( NULL, // pointer to security attributes = use defaults PIPE_THREAD_STACKSIZE, // initial thread stack size w32_read_piped_process_stdxxx_output_thread, pPipedStdOutThreadCtl, // thread argument 0, // special creation flags = none needed &dwThreadId // pointer to receive thread ID ); rc = GetLastError(); // (save return code) if (!hWorkerThread || INVALID_HANDLE_VALUE == hWorkerThread) { TRACE("*** _beginthreadex() failed! rc = %d : %s\n", rc,w32_strerror(rc)); if (pnWriteToChildStdinFD) VERIFY(CloseHandle(hOurWriteToStdin)); VERIFY(CloseHandle(hOurReadFromStdout)); VERIFY(CloseHandle(hOurReadFromStderr)); if ( !pnWriteToChildStdinFD ) { DeleteCriticalSection( &pPipedProcessCtl->csLock ); free( pPipedProcessCtl->pszBuffer ); free( pPipedProcessCtl ); } free( pPipedStdOutThreadCtl ); free( pPipedStdErrThreadCtl ); errno = rc; return -1; } else VERIFY(CloseHandle(hWorkerThread)); // (not needed anymore) SET_THREAD_NAME_ID(dwThreadId,"w32_read_piped_process_stdOUT_output_thread"); ////////////////////////////////////////////////// // Stderr... hWorkerThread = (HANDLE) _beginthreadex ( NULL, // pointer to security attributes = use defaults PIPE_THREAD_STACKSIZE, // initial thread stack size w32_read_piped_process_stdxxx_output_thread, pPipedStdErrThreadCtl, // thread argument 0, // special creation flags = none needed &dwThreadId // pointer to receive thread ID ); rc = GetLastError(); // (save return code) if (!hWorkerThread || INVALID_HANDLE_VALUE == hWorkerThread) { TRACE("*** _beginthreadex() failed! rc = %d : %s\n", rc,w32_strerror(rc)); if (pnWriteToChildStdinFD) VERIFY(CloseHandle(hOurWriteToStdin)); VERIFY(CloseHandle(hOurReadFromStdout)); VERIFY(CloseHandle(hOurReadFromStderr)); if ( !pnWriteToChildStdinFD ) { DeleteCriticalSection( &pPipedProcessCtl->csLock ); free( pPipedProcessCtl->pszBuffer ); free( pPipedProcessCtl ); } free( pPipedStdOutThreadCtl ); free( pPipedStdErrThreadCtl ); errno = rc; return -1; } else VERIFY(CloseHandle(hWorkerThread)); // (not needed anymore) SET_THREAD_NAME_ID(dwThreadId,"w32_read_piped_process_stdERR_output_thread"); // Piped process capture handling... if ( !pnWriteToChildStdinFD ) { // We're in control of the process... // Wait for it to exit... WaitForSingleObject( piProcInfo.hProcess, INFINITE ); CloseHandle( piProcInfo.hProcess ); // Now print ALL captured messages AT ONCE... logmsg( "%s", pPipedProcessCtl->pszBuffer ); // Free resources... DeleteCriticalSection( &pPipedProcessCtl->csLock ); free( pPipedProcessCtl->pszBuffer ); free( pPipedProcessCtl ); } else { // Caller is in control of the process... CloseHandle( piProcInfo.hProcess ); // Return a C run-time file descriptor // for the write-to-child-stdin HANDLE... *pnWriteToChildStdinFD = _open_osfhandle( (intptr_t) hOurWriteToStdin, 0 ); } // Success! return piProcInfo.dwProcessId; // (return process-id to caller) } ////////////////////////////////////////////////////////////////////////////////////////// // Thread to read message data from the child process's stdxxx o/p pipe... void w32_parse_piped_process_stdxxx_data ( PIPED_PROCESS_CTL* pPipedProcessCtl, char* holdbuff, int* pnHoldAmount ); UINT WINAPI w32_read_piped_process_stdxxx_output_thread ( void* pThreadParm ) { PIPED_THREAD_CTL* pPipedStdXXXThreadCtl = NULL; PIPED_PROCESS_CTL* pPipedProcessCtl = NULL; HANDLE hOurReadFromStdxxx = NULL; DWORD nAmountRead = 0; int nHoldAmount = 0; BOOL oflow = FALSE; unsigned nRetcode = 0; char readbuff [ PIPEBUFSIZE ]; char holdbuff [ HOLDBUFSIZE ]; // Extract parms pPipedStdXXXThreadCtl = (PIPED_THREAD_CTL*) pThreadParm; pPipedProcessCtl = pPipedStdXXXThreadCtl->pPipedProcessCtl; hOurReadFromStdxxx = pPipedStdXXXThreadCtl->hStdXXX; free( pPipedStdXXXThreadCtl ); // (prevent memory leak) // Begin work... for (;;) { if (!ReadFile(hOurReadFromStdxxx, readbuff, PIPEBUFSIZE-1, &nAmountRead, NULL)) { if (ERROR_BROKEN_PIPE == (nRetcode = GetLastError())) nRetcode = 0; // (else keep value returned from GetLastError()) break; } *(readbuff+nAmountRead) = 0; if (!nAmountRead) break; // (pipe closed (i.e. broken pipe); time to exit) if ((nHoldAmount + nAmountRead) >= (HOLDBUFSIZE-1)) { // OVERFLOW! append "truncated" string and force end-of-msg... oflow = TRUE; memcpy( holdbuff + nHoldAmount, readbuff, HOLDBUFSIZE - nHoldAmount); strcpy( readbuff, buffer_overflow_msg); nAmountRead = (DWORD)buffer_overflow_msg_len; nHoldAmount = HOLDBUFSIZE - nAmountRead - 1; } // Append new data to end of hold buffer... memcpy(holdbuff+nHoldAmount,readbuff,nAmountRead); nHoldAmount += nAmountRead; *(holdbuff+nHoldAmount) = 0; // Pass all existing data to parsing function... w32_parse_piped_process_stdxxx_data( pPipedProcessCtl, holdbuff, &nHoldAmount ); if (oflow) ASSERT(!nHoldAmount); oflow = FALSE; } // Finish up... CloseHandle( hOurReadFromStdxxx ); // (prevent HANDLE leak) return nRetcode; } ////////////////////////////////////////////////////////////////////////////////////////// // Parse piped child's stdout/stderr o/p data into individual newline delimited // messages for displaying on the Hercules hardware console... void w32_parse_piped_process_stdxxx_data ( PIPED_PROCESS_CTL* pPipedProcessCtl, char* holdbuff, int* pnHoldAmount ) { // This function executes in the context of the worker thread that calls it. char* pbeg; // ptr to start of message char* pend; // find end of message (MUST NOT BE MODIFIED!) char* pmsgend; // work ptr to end of message // 'pend' variable MUST NOT BE MODIFIED int nlen; // work length of one message int ntotlen; // accumulated length of all parsed messages // A worker thread that monitors a child's Stdout o/p has received a message // and is calling this function to determine what, if anything, to do with it. // (Note: the worker thread that calls us ensures holdbuff is null terminated) pbeg = holdbuff; // ptr to start of message pend = strchr(pbeg,'\n'); // find end of message (MUST NOT BE MODIFIED!) if (!pend) return; // we don't we have a complete message yet ntotlen = 0; // accumulated length of all parsed messages // Parse the message... do { nlen = (pend-pbeg); // get length of THIS message ntotlen += nlen + 1; // keep track of all that we see // Remove trailing newline character and any other trailing blanks... // (Note: we MUST NOT MODIFY the 'pend' variable. It should always // point to where the newline character was found so we can start // looking for the next message (if there is one) where this message // ended). *pend = 0; // (change newline character to null) pmsgend = pend; // (start removing blanks from here) while (--pmsgend >= pbeg && isspace(*pmsgend)) {*pmsgend = 0; --nlen;} // If we were passed a PIPED_PROCESS_CTL pointer, then the root thread // wants us to just capture the o/p and IT will issue the logmsg within // its own thread. Otherwise root thread isn't interested in capturing // and thus we must issue the individual logmsg's ourselves... if (!pPipedProcessCtl) { logmsg("%s\n",pbeg); // send all child's msgs to Herc console } else { size_t nNewStrLen, nAllocSizeNeeded; // (work) EnterCriticalSection( &pPipedProcessCtl->csLock ); nNewStrLen = strlen( pbeg ); nAllocSizeNeeded = ((((pPipedProcessCtl->nStrLen + nNewStrLen + 2) / 4096) + 1) * 4096); if ( nAllocSizeNeeded > pPipedProcessCtl->nAllocSize ) { pPipedProcessCtl->nAllocSize = nAllocSizeNeeded; pPipedProcessCtl->pszBuffer = realloc( pPipedProcessCtl->pszBuffer, nAllocSizeNeeded ); ASSERT( pPipedProcessCtl->pszBuffer ); } if (nNewStrLen) { memcpy( pPipedProcessCtl->pszBuffer + pPipedProcessCtl->nStrLen, pbeg, nNewStrLen ); pPipedProcessCtl->nStrLen += nNewStrLen; } *(pPipedProcessCtl->pszBuffer + pPipedProcessCtl->nStrLen) = '\n'; pPipedProcessCtl->nStrLen++; *(pPipedProcessCtl->pszBuffer + pPipedProcessCtl->nStrLen) = '\0'; ASSERT( pPipedProcessCtl->nStrLen <= pPipedProcessCtl->nAllocSize ); LeaveCriticalSection( &pPipedProcessCtl->csLock ); } // 'pend' should still point to the end of this message (where newline was) pbeg = (pend + 1); // point to beg of next message (if any) if (pbeg >= (holdbuff + *pnHoldAmount)) // past end of data? { pbeg = pend; // re-point back to our null ASSERT(*pbeg == 0); // sanity check break; // we're done with this batch } pend = strchr(pbeg,'\n'); // is there another message? } while (pend); // while messages remain... if (ntotlen > *pnHoldAmount) // make sure we didn't process too much { TRACE("*** ParseStdxxxMsg logic error! ***\n"); ASSERT(FALSE); // oops! } // 'Remove' the messages that we parsed from the caller's hold buffer by // sliding the remainder to the left (i.e. left justifying the remainder // in their hold buffer) and then telling them how much data now remains // in their hold buffer. // IMPORTANT PROGRAMMING NOTE! We must use memmove here and not strcpy! // strcpy doesn't work correctly for overlapping source and destination. // If there's 100 bytes remaining and we just want to slide it left by 1 // byte (just as an illustrative example), strcpy screws up. This is more // than likely because strcpy is trying to be as efficient as possible and // is grabbing multiple bytes at a time from the source string and plonking // them down into the destination string, thus wiping out part of our source // string. Thus, we MUST use memmove here and NOT strcpy. if ((*pnHoldAmount = (int)strlen(pbeg)) > 0) // new amount of data remaining memmove(holdbuff,pbeg,*pnHoldAmount); // slide left justify remainder } ////////////////////////////////////////////////////////////////////////////////////////// // The following is documented in Microsoft's Visual Studio developer documentation... #define MS_VC_EXCEPTION 0x406D1388 // (special value) typedef struct tagTHREADNAME_INFO { DWORD dwType; // must be 0x1000 LPCSTR pszName; // pointer to name (in same addr space) DWORD dwThreadID; // thread ID (-1 caller thread) DWORD dwFlags; // reserved for future use, must be zero } THREADNAME_INFO; DLL_EXPORT void w32_set_thread_name( TID tid, char* name ) { THREADNAME_INFO info; if (!name) return; // (ignore premature calls) info.dwType = 0x1000; info.pszName = name; // (should really be LPCTSTR) info.dwThreadID = tid; // (-1 == current thread, else tid) info.dwFlags = 0; __try { RaiseException( MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(DWORD), (const ULONG_PTR*)&info ); } __except ( EXCEPTION_CONTINUE_EXECUTION ) { /* (do nothing) */ } } ////////////////////////////////////////////////////////////////////////////////////////// #endif // defined( _MSVC_ ) hercules-3.07/w32util.h000644 000765 000765 00000022646 11143760543 016443 0ustar00jmaynardjmaynard000000 000000 ////////////////////////////////////////////////////////////////////////////////////////// // w32util.h Windows porting functions ////////////////////////////////////////////////////////////////////////////////////////// // (c) Copyright "Fish" (David B. Trout), 2005-2009. Released under the Q Public License // (http://www.hercules-390.org/herclic.html) as modifications to Hercules. ////////////////////////////////////////////////////////////////////////////////////////// // $Id: w32util.h 5127 2009-01-23 13:25:01Z bernard $ // // $Log$ // Revision 1.13 2008/11/23 22:27:43 rbowler // Fix win64 type conversion warnings in w32util.c // // Revision 1.12 2007/11/30 14:54:34 jmaynard // Changed conmicro.cx to hercules-390.org or conmicro.com, as needed. // // Revision 1.11 2007/08/04 19:04:34 fish // gethostid // // Revision 1.10 2007/06/23 00:04:19 ivan // Update copyright notices to include current year (2007) // // Revision 1.9 2007/01/10 15:12:12 rbowler // Console keepalive for Unix // // Revision 1.8 2007/01/10 09:32:39 fish // Enable connection keep-alive to try and detect 3270 clients that // have died (MSVC only right now; don't know how to do it on *nix) // // Revision 1.7 2006/12/08 09:43:34 jj // Add CVS message log // #ifndef _W32UTIL_H #define _W32UTIL_H #if defined( _MSVC_ ) #include "hercules.h" #ifndef _W32UTIL_C_ #ifndef _HUTIL_DLL_ #define W32_DLL_IMPORT DLL_IMPORT #else #define W32_DLL_IMPORT extern #endif #else #define W32_DLL_IMPORT DLL_EXPORT #endif ////////////////////////////////////////////////////////////////////////////////////////// // Translates a Win32 '[WSA]GetLastError()' value into a 'errno' value (if possible // and/or if needed) that can then be used in the below 'w32_strerror' string function... W32_DLL_IMPORT int w32_trans_w32error( const DWORD dwLastError ); ////////////////////////////////////////////////////////////////////////////////////////// // ("unsafe" version -- use "safer" 'w32_strerror_r' instead if possible) W32_DLL_IMPORT char* w32_strerror( int errnum ); ////////////////////////////////////////////////////////////////////////////////////////// // Handles both regular 'errno' values as well as [WSA]GetLastError() values too... W32_DLL_IMPORT int w32_strerror_r( int errnum, char* buffer, size_t buffsize ); ////////////////////////////////////////////////////////////////////////////////////////// // Return Win32 error message text associated with an error number value // as returned by a call to either GetLastError() or WSAGetLastError()... W32_DLL_IMPORT char* w32_w32errmsg( int errnum, char* pszBuffer, size_t nBuffSize ); ////////////////////////////////////////////////////////////////////////////////////////// // Large File Support... #if (_MSC_VER < 1400) W32_DLL_IMPORT __int64 w32_ftelli64 ( FILE* stream ); W32_DLL_IMPORT int w32_fseeki64 ( FILE* stream, __int64 offset, int origin ); W32_DLL_IMPORT int w32_ftrunc64 ( int fd, __int64 new_size ); #endif ////////////////////////////////////////////////////////////////////////////////////////// #if !defined( HAVE_SOCKETPAIR ) W32_DLL_IMPORT int socketpair( int domain, int type, int protocol, int socket_vector[2] ); #endif #if !defined( HAVE_FORK ) W32_DLL_IMPORT pid_t fork( void ); #endif #if !defined( HAVE_STRTOK_R ) W32_DLL_IMPORT char* strtok_r ( char* s, const char* sep, char** lasts); #endif #if !defined( HAVE_GETTIMEOFDAY ) W32_DLL_IMPORT int gettimeofday ( struct timeval* pTV, void* pTZ); #endif #if !defined( HAVE_NANOSLEEP ) W32_DLL_IMPORT int nanosleep ( const struct timespec* rqtp, struct timespec* rmtp ); #endif #if !defined( HAVE_USLEEP ) W32_DLL_IMPORT int usleep ( useconds_t useconds ); #endif // Can't use "HAVE_SLEEP" since Win32's "Sleep" causes HAVE_SLEEP to // be erroneously #defined due to autoconf AC_CHECK_FUNCS case issues... //#if !defined( HAVE_SLEEP ) W32_DLL_IMPORT unsigned sleep ( unsigned seconds ); //#endif #if !defined( HAVE_SCHED_YIELD ) W32_DLL_IMPORT int sched_yield ( void ); #endif #if !defined( HAVE_GETPGRP ) #define getpgrp getpid #endif #if !defined( HAVE_SCANDIR ) W32_DLL_IMPORT int scandir ( const char *dir, struct dirent ***namelist, int (*filter)(const struct dirent *), int (*compar)(const struct dirent **, const struct dirent **) ); #endif #if !defined( HAVE_ALPHASORT ) W32_DLL_IMPORT int alphasort ( const struct dirent **a, const struct dirent **b ); #endif #if !defined(HAVE_SYS_RESOURCE_H) // Note: we only provide the absolute minimum required information #define RUSAGE_SELF 0 // Current process #define RUSAGE_CHILDREN -1 // Children of the current process struct rusage // Resource utilization information { struct timeval ru_utime; // User time used struct timeval ru_stime; // System time used }; W32_DLL_IMPORT int getrusage ( int who, struct rusage* r_usage ); #endif #if !defined(HAVE_DECL_LOGIN_NAME_MAX) || !HAVE_DECL_LOGIN_NAME_MAX #define LOGIN_NAME_MAX UNLEN #endif #if !defined( HAVE_GETLOGIN ) W32_DLL_IMPORT char* getlogin ( void ); #endif #if !defined( HAVE_GETLOGIN_R ) W32_DLL_IMPORT int getlogin_r ( char* name, size_t namesize ); #endif #if !defined( HAVE_REALPATH ) W32_DLL_IMPORT char* realpath ( const char* file_name, char* resolved_name ); #endif // The inet_aton() function converts the specified string, // in the Internet standard dot notation, to a network address, // and stores the address in the structure provided. // // The inet_aton() function returns 1 if the address is successfully converted, // or 0 if the conversion failed. #if !defined( HAVE_INET_ATON ) W32_DLL_IMPORT int inet_aton( const char* cp, struct in_addr* addr ); #endif // Returns outpath as a host filesystem compatible filename path. // This is a Cygwin-to-MSVC transitional period helper function. // On non-Windows platforms it simply copies inpath to outpath. // On Windows it converts inpath of the form "/cygdrive/x/foo.bar" // to outpath in the form "x:/foo.bar" for Windows compatibility. W32_DLL_IMPORT BYTE *hostpath( BYTE *outpath, const BYTE *inpath, size_t buffsize ); // Poor man's "fcntl( fd, F_GETFL )"... // (only returns access-mode flags and not any others) W32_DLL_IMPORT int get_file_accmode_flags( int fd ); // Retrieve unique host id W32_DLL_IMPORT long gethostid( void ); // Initialize/Deinitialize sockets package... W32_DLL_IMPORT int socket_init ( void ); W32_DLL_IMPORT int socket_deinit ( void ); // Set socket to blocking or non-blocking mode... W32_DLL_IMPORT int socket_set_blocking_mode( int sfd, int blocking_mode ); // Determine whether a file descriptor is a socket or not... // (returns 1==true if it's a socket, 0==false otherwise) W32_DLL_IMPORT int socket_is_socket( int sfd ); // Set the SO_KEEPALIVE option and timeout values for a // socket connection to detect when client disconnects */ W32_DLL_IMPORT void socket_keepalive( int sfd, int idle_time, int probe_interval, int probe_count ); // Retrieve directory where process was loaded from... // (returns >0 == success, 0 == failure) W32_DLL_IMPORT int get_process_directory( char* dirbuf, size_t bufsiz ); // Expand environment variables... (e.g. %SystemRoot%, etc); 0==success W32_DLL_IMPORT int expand_environ_vars( const char* inbuff, char* outbuff, DWORD outbufsiz ); // Initialize Hercules HOSTINFO structure W32_DLL_IMPORT void w32_init_hostinfo( HOST_INFO* pHostInfo ); W32_DLL_IMPORT int w32_socket ( int af, int type, int protocol ); W32_DLL_IMPORT void w32_FD_SET ( int fd, fd_set* pSet ); W32_DLL_IMPORT int w32_FD_ISSET ( int fd, fd_set* pSet ); W32_DLL_IMPORT int w32_select ( int nfds, fd_set* pReadSet, fd_set* pWriteSet, fd_set* pExceptSet, const struct timeval* pTimeVal, const char* pszSourceFile, int nLineNumber ); W32_DLL_IMPORT FILE* w32_fdopen ( int their_fd, const char* their_mode ); W32_DLL_IMPORT size_t w32_fwrite ( const void* buff, size_t size, size_t count, FILE* stream ); W32_DLL_IMPORT int w32_fprintf( FILE* stream, const char* format, ... ); W32_DLL_IMPORT int w32_fclose ( FILE* stream ); W32_DLL_IMPORT int w32_get_stdin_char ( char* pCharBuff, int wait_millisecs ); W32_DLL_IMPORT pid_t w32_poor_mans_fork ( char* pszCommandLine, int* pnWriteToChildStdinFD ); W32_DLL_IMPORT void w32_set_thread_name( TID tid, char* name ); ////////////////////////////////////////////////////////////////////////////////////////// #endif // defined(_MSVC_) ////////////////////////////////////////////////////////////////////////////////////////// // Support for disabling of CRT Invalid Parameter Handler... #if defined( _MSVC_ ) && defined( _MSC_VER ) && ( _MSC_VER >= 1400 ) #define DISABLE_CRT_INVALID_PARAMETER_HANDLER() DisableInvalidParameterHandling() #define ENABLE_CRT_INVALID_PARAMETER_HANDLING() EnableInvalidParameterHandling() W32_DLL_IMPORT void DisableInvalidParameterHandling(); W32_DLL_IMPORT void EnableInvalidParameterHandling(); #else // !defined( _MSVC_ ) || !defined( _MSC_VER ) || ( _MSC_VER < 1400 ) #define DISABLE_CRT_INVALID_PARAMETER_HANDLER() /* (no nothing) */ #define ENABLE_CRT_INVALID_PARAMETER_HANDLING() /* (no nothing) */ #endif // defined( _MSVC_ ) && defined( _MSC_VER ) && ( _MSC_VER >= 1400 ) ////////////////////////////////////////////////////////////////////////////////////////// #endif // _W32UTIL_H hercules-3.07/xstore.c000644 000765 000765 00000053023 11224164170 016434 0ustar00jmaynardjmaynard000000 000000 /* XSTORE.C (c) Copyright Jan Jaeger, 1999-2009 */ /* Expanded storage related instructions */ /* Interpretive Execution - (c) Copyright Jan Jaeger, 1999-2009 */ /* z/Architecture support - (c) Copyright Jan Jaeger, 1999-2009 */ /* MVPG moved from cpu.c to xstore.c 05/07/00 Jan Jaeger */ // $Id: xstore.c 5405 2009-06-10 12:34:17Z rbowler $ /*-------------------------------------------------------------------*/ /* This module implements the expanded storage instructions */ /* for the Hercules ESA/390 emulator. */ /*-------------------------------------------------------------------*/ #include "hstdinc.h" #if !defined(_HENGINE_DLL_) #define _HENGINE_DLL_ #endif #if !defined(_XSTORE_C_) #define _XSTORE_C_ #endif #include "hercules.h" #include "opcode.h" #include "inline.h" #if defined(FEATURE_EXPANDED_STORAGE) /*-------------------------------------------------------------------*/ /* B22E PGIN - Page in from expanded storage [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(page_in) { int r1, r2; /* Values of R fields */ VADR vaddr; /* Virtual storage address */ BYTE *maddr; /* Main storage address */ U32 xaddr; /* Expanded storage block# */ size_t xoffs; /* Byte offset into xpndstor */ RRE(inst, regs, r1, r2); PRIV_CHECK(regs); if(SIE_STATB(regs, IC3, PGX)) longjmp(regs->progjmp, SIE_INTERCEPT_INST); #if defined(FEATURE_MULTIPLE_CONTROLLED_DATA_SPACE) /* Cannot perform xstore page movement in XC mode */ if(SIE_STATB(regs, MX, XC)) longjmp(regs->progjmp, SIE_INTERCEPT_INST); #endif /*defined(FEATURE_MULTIPLE_CONTROLLED_DATA_SPACE)*/ /* expanded storage block number */ xaddr = regs->GR_L(r2); if(SIE_MODE(regs)) { xaddr += regs->sie_xso; if(xaddr >= regs->sie_xsl) { PTT(PTT_CL_ERR,"*PGIN",regs->GR_L(r1),regs->GR_L(r2),regs->psw.IA_L); regs->psw.cc = 3; return; } } /* If the expanded storage block is not configured then terminate with cc3 */ if (xaddr >= sysblk.xpndsize) { PTT(PTT_CL_ERR,"*PGIN",regs->GR_L(r1),regs->GR_L(r2),regs->psw.IA_L); regs->psw.cc = 3; return; } /* Byte offset in expanded storage */ xoffs = (size_t)xaddr << XSTORE_PAGESHIFT; /* Obtain abs address, verify access and set ref/change bits */ vaddr = (regs->GR(r1) & ADDRESS_MAXWRAP(regs)) & XSTORE_PAGEMASK; maddr = MADDR (vaddr, USE_REAL_ADDR, regs, ACCTYPE_WRITE, 0); /* Copy data from expanded to main */ memcpy (maddr, sysblk.xpndstor + xoffs, XSTORE_PAGESIZE); /* cc0 means pgin ok */ regs->psw.cc = 0; } /* end DEF_INST(page_in) */ #endif /*defined(FEATURE_EXPANDED_STORAGE)*/ #if defined(FEATURE_EXPANDED_STORAGE) /*-------------------------------------------------------------------*/ /* B22F PGOUT - Page out to expanded storage [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(page_out) { int r1, r2; /* Values of R fields */ VADR vaddr; /* Virtual storage address */ BYTE *maddr; /* Main storage address */ U32 xaddr; /* Expanded storage block# */ size_t xoffs; /* Byte offset into xpndstor */ RRE(inst, regs, r1, r2); PRIV_CHECK(regs); if(SIE_STATB(regs, IC3, PGX)) longjmp(regs->progjmp, SIE_INTERCEPT_INST); #if defined(FEATURE_MULTIPLE_CONTROLLED_DATA_SPACE) /* Cannot perform xstore page movement in XC mode */ if(SIE_STATB(regs, MX, XC)) longjmp(regs->progjmp, SIE_INTERCEPT_INST); #endif /*defined(FEATURE_MULTIPLE_CONTROLLED_DATA_SPACE)*/ /* expanded storage block number */ xaddr = regs->GR_L(r2); if(SIE_MODE(regs)) { xaddr += regs->sie_xso; if(xaddr >= regs->sie_xsl) { PTT(PTT_CL_ERR,"*PGOUT",regs->GR_L(r1),regs->GR_L(r2),regs->psw.IA_L); regs->psw.cc = 3; return; } } /* If the expanded storage block is not configured then terminate with cc3 */ if (xaddr >= sysblk.xpndsize) { PTT(PTT_CL_ERR,"*PGOUT",regs->GR_L(r1),regs->GR_L(r2),regs->psw.IA_L); regs->psw.cc = 3; return; } /* Byte offset in expanded storage */ xoffs = (size_t)xaddr << XSTORE_PAGESHIFT; /* Obtain abs address, verify access and set ref/change bits */ vaddr = (regs->GR(r1) & ADDRESS_MAXWRAP(regs)) & XSTORE_PAGEMASK; maddr = MADDR (vaddr, USE_REAL_ADDR, regs, ACCTYPE_READ, 0); /* Copy data from main to expanded */ memcpy (sysblk.xpndstor + xoffs, maddr, XSTORE_PAGESIZE); /* cc0 means pgout ok */ regs->psw.cc = 0; } /* end DEF_INST(page_out) */ #endif /*defined(FEATURE_EXPANDED_STORAGE)*/ #if defined(FEATURE_MOVE_PAGE_FACILITY_2) && defined(FEATURE_EXPANDED_STORAGE) /*-------------------------------------------------------------------*/ /* B259 IESBE - Invalidate Expanded Storage Block Entry [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(invalidate_expanded_storage_block_entry) { int r1, r2; /* Values of R fields */ RRE(inst, regs, r1, r2); PRIV_CHECK(regs); #if defined(_FEATURE_SIE) if(SIE_STATNB(regs, EC0, MVPG)) longjmp(regs->progjmp, SIE_INTERCEPT_INST); #endif /*defined(_FEATURE_SIE)*/ /* Perform serialization before operation */ PERFORM_SERIALIZATION (regs); OBTAIN_INTLOCK(regs); SYNCHRONIZE_CPUS(regs); /* Invalidate page table entry */ ARCH_DEP(invalidate_pte) (inst[1], r1, r2, regs); RELEASE_INTLOCK(regs); /* Perform serialization after operation */ PERFORM_SERIALIZATION (regs); } /* end DEF_INST(invalidate_expanded_storage_block_entry) */ #endif /*defined(FEATURE_EXPANDED_STORAGE)*/ #if defined(_MSVC_) /* Workaround for "fatal error C1001: INTERNAL COMPILER ERROR" in MSVC */ #pragma optimize("",off) #endif /*defined(_MSVC_)*/ #if defined(FEATURE_MOVE_PAGE_FACILITY_2) /*-------------------------------------------------------------------*/ /* B254 MVPG - Move Page [RRE] */ /*-------------------------------------------------------------------*/ DEF_INST(move_page) { int r1, r2; /* Register values */ int rc = 0; /* Return code */ int cc = 0; /* Condition code */ VADR vaddr1, vaddr2; /* Virtual addresses */ RADR raddr1=0, raddr2=0, xpkeya; /* Real addresses */ BYTE *main1 = NULL, *main2 = NULL; /* Mainstor addresses */ BYTE *sk1; /* Storage key address */ BYTE akey; /* Access key in register 0 */ BYTE akey1, akey2; /* Access keys for operands */ #if defined(FEATURE_EXPANDED_STORAGE) int xpvalid1 = 0, xpvalid2 = 0; /* 1=Operand in expanded stg */ CREG pte1 = 0, pte2 = 0; /* Page table entry */ U32 xpblk1 = 0, xpblk2 = 0; /* Expanded storage block# */ BYTE xpkey1 = 0, xpkey2 = 0; /* Expanded storage keys */ #endif /*defined(FEATURE_EXPANDED_STORAGE)*/ RRE(inst, regs, r1, r2); #if defined(_FEATURE_SIE) if(SIE_STATNB(regs, EC0, MVPG)) longjmp(regs->progjmp, SIE_INTERCEPT_INST); #endif /*defined(_FEATURE_SIE)*/ /* Use PSW key as access key for both operands */ akey1 = akey2 = regs->psw.pkey; /* If register 0 bit 20 or 21 is one, get access key from R0 */ if (regs->GR_L(0) & 0x00000C00) { /* Extract the access key from register 0 bits 24-27 */ akey = regs->GR_L(0) & 0x000000F0; /* Priviliged operation exception if in problem state, and the specified key is not permitted by the PSW key mask */ if ( PROBSTATE(®s->psw) && ((regs->CR(3) << (akey >> 4)) & 0x80000000) == 0 ) regs->program_interrupt (regs, PGM_PRIVILEGED_OPERATION_EXCEPTION); /* If register 0 bit 20 is one, use R0 key for operand 1 */ if (regs->GR_L(0) & 0x00000800) akey1 = akey; /* If register 0 bit 21 is one, use R0 key for operand 2 */ if (regs->GR_L(0) & 0x00000400) akey2 = akey; } /* Specification exception if register 0 bits 16-19 are not all zero, or if bits 20 and 21 are both ones */ if ((regs->GR_L(0) & 0x0000F000) != 0 || (regs->GR_L(0) & 0x00000C00) == 0x00000C00) regs->program_interrupt (regs, PGM_SPECIFICATION_EXCEPTION); /* Determine the logical addresses of each operand */ vaddr1 = regs->GR(r1) & ADDRESS_MAXWRAP(regs); vaddr2 = regs->GR(r2) & ADDRESS_MAXWRAP(regs); /* Isolate the page addresses of each operand */ vaddr1 &= XSTORE_PAGEMASK; vaddr2 &= XSTORE_PAGEMASK; /* Obtain the real or expanded address of each operand */ if ( !REAL_MODE(®s->psw) || SIE_MODE(regs) ) { /* Translate the second operand address to a real address */ if(!REAL_MODE(®s->psw)) { rc = ARCH_DEP(translate_addr) (vaddr2, r2, regs, ACCTYPE_READ); raddr2 = regs->dat.raddr; } else raddr2 = vaddr2; if(rc != 0 && rc != 2) goto mvpg_progck; raddr2 = APPLY_PREFIXING (raddr2, regs->PX); if (raddr2 > regs->mainlim) regs->program_interrupt (regs, PGM_ADDRESSING_EXCEPTION); #if defined(_FEATURE_SIE) if(SIE_MODE(regs) && !regs->sie_pref) { #if defined(FEATURE_MULTIPLE_CONTROLLED_DATA_SPACE) if (SIE_TRANSLATE_ADDR (regs->sie_mso + raddr2, (SIE_STATB(regs, MX, XC) && AR_BIT(®s->psw) && r2 > 0) ? r2 : USE_PRIMARY_SPACE, regs->hostregs, ACCTYPE_SIE)) #else /*!defined(FEATURE_MULTIPLE_CONTROLLED_DATA_SPACE)*/ if (SIE_TRANSLATE_ADDR (regs->sie_mso + raddr2, USE_PRIMARY_SPACE, regs->hostregs, ACCTYPE_SIE)) #endif /*!defined(FEATURE_MULTIPLE_CONTROLLED_DATA_SPACE)*/ (regs->hostregs->program_interrupt) (regs->hostregs, regs->hostregs->dat.xcode); /* Convert host real address to host absolute address */ raddr2 = APPLY_PREFIXING (regs->hostregs->dat.raddr, regs->hostregs->PX); } #endif /*defined(_FEATURE_SIE)*/ #if defined(FEATURE_EXPANDED_STORAGE) if(rc == 2) { FETCH_W(pte2,regs->mainstor + raddr2); /* If page is invalid in real storage but valid in expanded storage then xpblk2 now contains expanded storage block# */ if(pte2 & PAGETAB_ESVALID) { xpblk2 = (pte2 & ZPGETAB_PFRA) >> 12; #if defined(_FEATURE_SIE) if(SIE_MODE(regs)) { /* Add expanded storage origin for this guest */ xpblk2 += regs->sie_xso; /* If the block lies beyond this guests limit then we must terminate the instruction */ if(xpblk2 >= regs->sie_xsl) { cc = 2; goto mvpg_progck; } } #endif /*defined(_FEATURE_SIE)*/ rc = 0; xpvalid2 = 1; xpkeya = raddr2 + #if defined(FEATURE_ESAME) 2048; #else /*!defined(FEATURE_ESAME)*/ /* For ESA/390 mode, the XPTE lies directly beyond the PTE, and each entry is 12 bytes long, we must therefor add 1024 + 8 times the page index */ 1024 + ((vaddr2 & 0x000FF000) >> 9); #endif /*!defined(FEATURE_ESAME)*/ if (xpkeya > regs->mainlim) regs->program_interrupt (regs, PGM_ADDRESSING_EXCEPTION); xpkey2 = regs->mainstor[xpkeya]; /*DEBUG logmsg("MVPG pte2 = " F_CREG ", xkey2 = %2.2X, xpblk2 = %5.5X, akey2 = %2.2X\n", pte2,xpkey2,xpblk2,akey2); */ } else { cc = 2; goto mvpg_progck; } } #endif /*defined(FEATURE_EXPANDED_STORAGE)*/ /* Program check if second operand is not valid in either main storage or expanded storage */ if (rc) { cc = 2; goto mvpg_progck; } /* Reset protection indication before calling translate_addr() */ regs->dat.protect = 0; /* Translate the first operand address to a real address */ if(!REAL_MODE(®s->psw)) { rc = ARCH_DEP(translate_addr) (vaddr1, r1, regs, ACCTYPE_WRITE); raddr1 = regs->dat.raddr; } else raddr1 = vaddr1; if(rc != 0 && rc != 2) goto mvpg_progck; raddr1 = APPLY_PREFIXING (raddr1, regs->PX); if (raddr1 > regs->mainlim) regs->program_interrupt (regs, PGM_ADDRESSING_EXCEPTION); #if defined(_FEATURE_SIE) if(SIE_MODE(regs) && !regs->sie_pref) { #if defined(FEATURE_MULTIPLE_CONTROLLED_DATA_SPACE) if (SIE_TRANSLATE_ADDR (regs->sie_mso + raddr1, (SIE_STATB(regs, MX, XC) && AR_BIT(®s->psw) && r1 > 0) ? r1 : USE_PRIMARY_SPACE, regs->hostregs, ACCTYPE_SIE)) #else /*!defined(FEATURE_MULTIPLE_CONTROLLED_DATA_SPACE)*/ if (SIE_TRANSLATE_ADDR (regs->sie_mso + raddr1, USE_PRIMARY_SPACE, regs->hostregs, ACCTYPE_SIE)) #endif /*!defined(FEATURE_MULTIPLE_CONTROLLED_DATA_SPACE)*/ (regs->hostregs->program_interrupt) (regs->hostregs, regs->hostregs->dat.xcode); /* Convert host real address to host absolute address */ raddr1 = APPLY_PREFIXING (regs->hostregs->dat.raddr, regs->hostregs->PX); } #endif /*defined(_FEATURE_SIE)*/ #if defined(FEATURE_EXPANDED_STORAGE) if(rc == 2) { FETCH_W(pte1,regs->mainstor + raddr1); /* If page is invalid in real storage but valid in expanded storage then xpblk1 now contains expanded storage block# */ if(pte1 & PAGETAB_ESVALID) { xpblk1 = (pte1 & ZPGETAB_PFRA) >> 12; #if defined(_FEATURE_SIE) if(SIE_MODE(regs)) { /* Add expanded storage origin for this guest */ xpblk1 += regs->sie_xso; /* If the block lies beyond this guests limit then we must terminate the instruction */ if(xpblk1 >= regs->sie_xsl) { cc = 1; goto mvpg_progck; } } #endif /*defined(_FEATURE_SIE)*/ rc = 0; xpvalid1 = 1; xpkeya = raddr1 + #if defined(FEATURE_ESAME) 2048; #else /*!defined(FEATURE_ESAME)*/ /* For ESA/390 mode, the XPTE lies directly beyond the PTE, and each entry is 12 bytes long, we must therefor add 1024 + 8 times the page index */ 1024 + ((vaddr1 & 0x000FF000) >> 9); #endif /*!defined(FEATURE_ESAME)*/ if (xpkeya > regs->mainlim) regs->program_interrupt (regs, PGM_ADDRESSING_EXCEPTION); xpkey1 = regs->mainstor[xpkeya]; /*DEBUG logmsg("MVPG pte1 = " F_CREG ", xkey1 = %2.2X, xpblk1 = %5.5X, akey1 = %2.2X\n", pte1,xpkey1,xpblk1,akey1); */ } else { cc = 1; goto mvpg_progck; } } #endif /*defined(FEATURE_EXPANDED_STORAGE)*/ /* Program check if operand not valid in main or expanded */ if (rc) { cc = 1; goto mvpg_progck; } /* Program check if page protection or access-list controlled protection applies to the first operand */ if (regs->dat.protect || (xpvalid1 && (pte1 & PAGETAB_PROT))) { regs->TEA = vaddr1 | TEA_PROT_AP | regs->dat.stid; regs->excarid = (ACCESS_REGISTER_MODE(®s->psw)) ? r1 : 0; regs->program_interrupt (regs, PGM_PROTECTION_EXCEPTION); } } /* end if(!REAL_MODE) */ #if defined(FEATURE_EXPANDED_STORAGE) /* Program check if both operands are in expanded storage, or if first operand is in expanded storage and the destination reference intention (register 0 bit 22) is set to one, or if first operand is in expanded storage and pte lock bit on, or if first operand is in expanded storage and frame invalid */ if ((xpvalid1 && xpvalid2) || (xpvalid1 && (regs->GR_L(0) & 0x00000200)) || (xpvalid1 && (pte1 & PAGETAB_PGLOCK)) || (xpvalid1 && (xpblk1 >= sysblk.xpndsize))) { regs->dat.xcode = PGM_PAGE_TRANSLATION_EXCEPTION; rc = 2; cc = 1; goto mvpg_progck; } /* More Program check checking, but at lower priority: if second operand is in expanded storage and pte lock bit on, or if second operand is in expanded storage and frame invalid */ if ((xpvalid2 && (pte2 & PAGETAB_PGLOCK)) || (xpvalid2 && (xpblk2 >= sysblk.xpndsize))) { /* re-do translation to set up TEA */ rc = ARCH_DEP(translate_addr) (vaddr2, r2, regs, ACCTYPE_READ); regs->dat.xcode = PGM_PAGE_TRANSLATION_EXCEPTION; cc = 1; goto mvpg_progck; } /* Perform protection checks */ if (xpvalid1) { /* Key check on expanded storage block if NoKey bit off in PTE */ if (akey1 != 0 && akey1 != (xpkey1 & STORKEY_KEY) && (pte1 & PAGETAB_ESNK) == 0 && !((regs->CR(0) & CR0_STORE_OVRD) && ((xpkey1 & STORKEY_KEY) == 0x90))) { regs->program_interrupt (regs, PGM_PROTECTION_EXCEPTION); } sk1=NULL; } else #endif /*defined(FEATURE_EXPANDED_STORAGE)*/ { /* Obtain absolute address of main storage block, check protection, and set reference and change bits */ main1 = MADDR (vaddr1, r1, regs, ACCTYPE_WRITE_SKP, akey1); sk1 = regs->dat.storkey; } #if defined(FEATURE_EXPANDED_STORAGE) if (xpvalid2) { /* Key check on expanded storage block if NoKey bit off in PTE */ if (akey2 != 0 && (xpkey2 & STORKEY_FETCH) && akey2 != (xpkey2 & STORKEY_KEY) && (pte2 & PAGETAB_ESNK) == 0) { regs->program_interrupt (regs, PGM_PROTECTION_EXCEPTION); } } else #endif /*defined(FEATURE_EXPANDED_STORAGE)*/ { /* Obtain absolute address of main storage block, check protection, and set reference bit. Use last byte of page to avoid FPO area. */ main2 = MADDR (vaddr2 | 0xFFF, r2, regs, ACCTYPE_READ, akey2); main2 -= 0xFFF; } #if defined(FEATURE_EXPANDED_STORAGE) /* Perform page movement */ if (xpvalid2) { /* Set the main storage reference and change bits */ *sk1 |= (STORKEY_REF | STORKEY_CHANGE); /* Set Expanded Storage reference bit in the PTE */ STORE_W(regs->mainstor + raddr2, pte2 | PAGETAB_ESREF); /* Move 4K bytes from expanded storage to main storage */ memcpy (main1, sysblk.xpndstor + ((size_t)xpblk2 << XSTORE_PAGESHIFT), XSTORE_PAGESIZE); } else if (xpvalid1) { /* Set Expanded Storage reference and change bits in the PTE */ STORE_W(regs->mainstor + raddr1, pte1 | PAGETAB_ESREF | PAGETAB_ESCHA); /* Move 4K bytes from main storage to expanded storage */ memcpy (sysblk.xpndstor + ((size_t)xpblk1 << XSTORE_PAGESHIFT), main2, XSTORE_PAGESIZE); } else #endif /*defined(FEATURE_EXPANDED_STORAGE)*/ { /* Set the main storage reference and change bits */ *sk1 |= (STORKEY_REF | STORKEY_CHANGE); /* Move 4K bytes from main storage to main storage */ memcpy (main1, main2, XSTORE_PAGESIZE); } /* Return condition code zero */ regs->psw.cc = 0; return; mvpg_progck: PTT(PTT_CL_ERR,"*MVPG",regs->GR_L(r1),regs->GR_L(r2),regs->psw.IA_L); /* If page translation exception (PTE invalid) and condition code option in register 0 bit 23 is set, return condition code */ if ((regs->GR_L(0) & 0x00000100) && regs->dat.xcode == PGM_PAGE_TRANSLATION_EXCEPTION && rc == 2) { regs->psw.cc = cc; return; } /* Otherwise generate program check */ /* (Bit 29 of TEA is on for PIC 11 & operand ID also stored) */ if (regs->dat.xcode == PGM_PAGE_TRANSLATION_EXCEPTION) { regs->TEA |= TEA_MVPG; regs->opndrid = (r1 << 4) | r2; } regs->program_interrupt (regs, regs->dat.xcode); } /* end DEF_INST(move_page) */ #endif /*defined(FEATURE_MOVE_PAGE_FACILITY_2)*/ #if defined(_MSVC_) /* Workaround for "fatal error C1001: INTERNAL COMPILER ERROR" in MSVC */ #pragma optimize("",on) #endif /*defined(_MSVC_)*/ #if !defined(_GEN_ARCH) #if defined(_ARCHMODE2) #define _GEN_ARCH _ARCHMODE2 #include "xstore.c" #endif #if defined(_ARCHMODE3) #undef _GEN_ARCH #define _GEN_ARCH _ARCHMODE3 #include "xstore.c" #endif #endif /*!defined(_GEN_ARCH)*/ hercules-3.07/util/awssl-v19g000644 000765 000765 00000605257 11143760541 017601 0ustar00jmaynardjmaynard000000 000000 TITLE 'AWSSL 1.9G AWS Virtual Tape (standard labels)' *********************************************************************** * AWSSL 1.9G, AWS Virtual Tape (standard labels) * * * * This program moves datasets to/from AWS virtual tape files. HET * * virtual tape formats will likely be support in the "not to distant" * * future. * * * * Copyright (C) 2002, By Reed H. Petty, rhp@draper.net * * * * You are free to make any changes you like to this code for any * * purpose (including commercial for profit use) PROVIDED that you * * carry the credits forward into derived works. * * * * NO WARRANTY OF ANY KIND IS MADE! USE AT YOUR OWN RISK! * * * * JCL quick start example: * * * * //MAKETAPE EXEC PGM=AWSSL * * //STEPLIB DD DSN=my.load.library,DISP=SHR * * //AWSPRINT DD SYSOUT=* * * //myddnam1 DD DSN=my.file1,DISP=SHR (optional) * * //myddnam2 DD DSN=my.file2,DISP=SHR (optional) * * //AWSFILE DD DSN=mytape.aws,DISP=(,CATLG,DELETE), * * // SPACE=(whatever make sense to you in your environment), * * // DCB=(whatever makes sense to you in your environment) * * //AWSCNTL DD * * * AWSVOL VOLSER=mytape * * AWSPUT INDSN=catalogued dataset name 1 * * AWSPUT INDSN=catalogued dataset name 2,UNLOAD=IEBCOPY * * AWSPUT INDD=myddnam1 * * AWSPUT INDD=myddnam1,UNLOAD=IEBCOPY * * ... or ... * * AWSVOL VOLSER=mytape * * AWSGET OUTDD=dd1,INDSN=dataset name on tape,FILENO=1 * * AWSGET OUTDD=dd2,INDSN=dataset name on tape,FILENO=5,SL=NO * * AWSGET OUTDD=dd7,INDSN=dataset name on tape,FILENO=2,LOAD=IEBCOPY * * ... and so forth * * /* * * * * Feedback, good or bad, is always welcome! * * * * Kudo's to Roger Bowler, somitcw@erols.com (whoever you are), * * Sam Golob, and to Linus Torvalds (who encouraged my trivial * * contributions to the Linux kernel). * * * * Special thanks to Michael A. Quinlan who was my boss at the * * University of Utah so many years ago. Mike is by far the best * * assembler programmer that I have ever known. * * * *********************************************************************** EJECT *********************************************************************** * * * AWS Virtual Tape Motivation, The Good, the Bad, and the Ugly. * * ------------------------------------------------------------- * * * * This program creates AWS structures which contain one or more * * OS datasets of any record format (except spanned blocks), with or * * without standard labels, where the output AWS structure can also * * be of any record format (including spanned blocks). * * * * This program will also retrieve datasets from an AWS structure of * * any record format (except spanned blocks). The retrieved datasets * * may be reblocked if necessary. If DCB attributes are omitted on * * the receiving dataset, and if standard labels are present within * * the AWS structure, then the DCB attributes of the receiving dataset * * will be defaulted to those within the HDR1 label. * * * * AWS (acronym is unknown to me, someone please tell me!) was widely * * used by the IBM P/390 product family to implement an entire tape * * volume as a byte stream contained within an OS/2 file. As * * implementations of the System/360/370/zArch architecture families * * in software expanded (such as Hercules, Flex/ES, and others) the * * AWS presence expanded as well. * * * * Recommended reading: Sam Golob's AWS article published by NaSPA. * * See URL: http://www.naspa.com/PDF/2001/1201%20PDF/T0112012.pdf * * * * Hercules provided the means for me to rekindle my MVT and MVS 3.8 * * memories. I found myself constantly moving datasets between * * these older operating systems and OS/390 running on real blue * * hardware. As neither MVT nor MVS 3.8J implement TCP/IP it became * * necessary to move 1) entire disk volumes, 2) AWS tape volumes, or * * 3) card decks. Hercules does an excellent job of reading/writing * * AWS tape volumes, but support in OS/390 was lacking (IMHO). * * * * Utilities available on OS/390 were a bit cumbersome. If standard * * label functionality was needed then the structure first had to be * * copied to a real tape volume (AWSUTIL by Brandon Hill). If a need * * existed to pluck a single file from an AWS structure, without first * * copying the entire structure to a real volume, RAWSTAPE (written * * by Jan Jaeger) was required. Also, RAWSTAPE requires that DCB * * attributes be manually set in a subsequent step. * * * * As Jay Maynard (Hercules Maintainer) is fond of saying: If you have * * an itch, then scratch it! This work represents my scratching. * * * * The itch: find a way to easily and quickly move sequential files * * and PDS' (including PDSE's) between my OS/390 and MVS 3.8J systems. * * The goals: easy syntax, standard label exploitation to set default * * DCB attributes in the receiving system, multiple file insertion * * or extraction in a single step execution, automatic PDS staging * * (this itch actually belongs to Roger Bowler but the idea is handy), * * compatibility with all known AWS utilities, and so forth. * * * *********************************************************************** EJECT *********************************************************************** * * * Assembly * * -------- * * * * To assemble on a MVS 3.8J system: * * * * //my job card * * // EXEC ASMFCL,COND=(0,NE),MAC1='SYS1.AMODGEN',REGION=4096K, * * // PARM.LKED='LIST,LET,MAP,XREF,RENT,REFR' * * //SYSIN DD * * * this code * * //LKED.SYSLMOD DD DSN=my.load.library(AWSSL),DISP=SHR * * //SYSIN DD * * * SETCODE AC(1) (if UNLOAD=IEBCOPY is used) * * // * * * * To assemble on an OS/390 R2.10 system: * * //my job card * * // EXEC HLASMCL,COND=(0,NE), * * // PARM.L='LIST,LET,MAP,XREF,RENT,REFR' * * //SYSIN DD * * * this code * * //L.SYSLMOD DD DSN=my.load.library(AWSSL),DISP=SHR * * //SYSIN DD * * * SETCODE AC(1) (if UNLOAD=IEBCOPY is used) * * // * * * * If the UNLOAD=IEBCOPY option is utilized this code must execute * * authorized. This code runs in 24 bit mode and is reentrant. * * Assembly on older releases of MVS require that SYS1.AMODGEN be * * available to the assembler. * * * * * * Rant * * ---- * * * * Some critical comments have been received regarding my programming * * style (too much uppercase, too much register saving, avoidance of * * new and spiffy instructions, linkage conventions, short 8 byte * * labels, uppercase labels, opcodes, operands, etc). * * * * Normally I strive to generate reentrant 31 bit code sprinkled * * liberally with capabilities found in the "more recent MVS world". * * However, as this code is intended to assemble and run on any * * incarnation of MVS from 3.8J forward, I have tried hard to avoid * * dependency on facilities not present in older releases of MVS. * * * * * *********************************************************************** EJECT *********************************************************************** * * * Random thoughts for the future * * ------------------------------ * * 1) Add HET format support (does anyone know of a gzip * * implementation, preferably in System/370 assembler or others not * * requiring run time library support, and not encumbered by * * overly restrictive licensing? * * *** Found, implementation in progress *** * * * * 2) Add capability to internally call IEBCOPY, IDCAMS, etc to create * * datasets in portable formats before adding to the AWS structure. * * *** Done *** * * * * 3) Add capability to retrieve a dataset from a standard label AWS * * structure and create an equivalent OS dataset. * * *** Done *** * * * * 4) Implement a decent multiple input record keyword parser. * * *** Done *** * * * * 5) Implement capability to generate AWS structures in file formats * * of undefined lengths (PREFERRED!!!), variable lengths (for * * compatibility with output produced by AWSUTIL written by * * Brandon Hill), and fixed lengths (for compatibility with * * the VTT2* utilities written by Sam Golob). * * *** Done *** * * * * 6) Add capability to IDCAMS repro and export VSAM objects. * * * * 7) Rewrite to position for never ending expansion while keeping * * the code base maintainable. * * *** Done *** * * * *********************************************************************** EJECT *********************************************************************** * * * Change History * * -------------- * * August 5, 2002 - Released to the public as v1.0 * * * * August 13, 2002 - V1.1 RELEASE * * - corrected a never ending wait on a never posted ECB in some * * environments (BSAM back to single buffering). * * - added INDD= keyword support. * * - added DSN retrieval via RDJFCB support. * * - added AWSVOL verb support. * * - revised DATASET verb format (removed VOLSER keyword). * * - Ported to MVS 3.8J (TIOT structure changes, SVC99 RB * * assembler F backward reference assembly problems, etc). * * - added support for input datasets having RECFM=U (thanks to * * Roger Bowler who identified the bug). * * - brought label formats forward to that documented in the * * OS/390 R2.10 SMS manuals. * * * * August 16, 2002 - V1.2 Release (Internal Only) * * - added automatic staging (unload) of PDS(E) datasets. * * - corrected RECFM=U ommission from HDR2/EOF2. * * - corrected RDJFCB end of list indicator. * * - converted input I/O from BSAM to QSAM for performance. * * * * September 9, 2002 - V1.9a Release Candidate (Internal Only) * * - Nearly 100% rewrite. * * * * September 18, 2002- 1.9c Release Candidate (public) * * - Added retrieve from aws tape into OS dataset function. * * - Added AWSGET PDS(e) staging. * * - Renamed TAPEVOL, IMPORT, EXPORT to AWSVOL, AWSGET and AWSPUT. * * * * September 19, 2002- V1.9D Release Candidate (public) * * - Bug! subtle, grrr... AWSIGET... when block fragmentation occurs * * between bytes 1 and 2 of AWSLENC then we cannot compute the * * length of the fragmented block and therefore cannot aggregate * * the remainder of the block. The exposure is rare and is more * * likely to be visible when using short record lengths (as is the * * case with AWS text produced by Sam Golob's VTT2DISK utility). * * * * September 23, 2002- V1.9E Release Candidate (public) * * - Incompatibility between AWSSL and VTT2TAPE. VTT2TAPE expects: * * 1) the last text record to be padded with x'20' characters, and * * 2) that an additional record be written completedly filled with * * x'20' bytes. * * Modified AWSSL accordingly when producing fixed length output. * * * * September 25, 2002- V1.9F * * - Added owner= keyword to AWSVOL function. * * * * September 26, 2002- V1.9G * * - Rewrite of AWSIGET csect, new AWSGTXT csect. * * - Force recfm=u when spanned records/blocks are encountered. * * Issue warnings when spanned and other than IEBCOPY load. * * * * * *********************************************************************** EJECT *********************************************************************** * * * Input Parameters * * ---------------- * * All input parameters are taken from control statements supplied by * * the dataset represented by the AWSCNTL dd statement. Statements * * consist of a major function to be performed (i.e. TAPEVOL, EXPORT, * * etc), and a series of keywords which supply values to that function.* * * * Control statement keywords may be continued to as many records as * * necessary. Continued statements are indicated by the last keyword * * argument suffixed with a comma and additional keywords supplied * * on the next record. Additional keywords must not begin in column * * one. * * * * Example: * * * * AWSVOL VOLSER=MYTAPE * * AWSPUT INDSN=SYS1.PROCLIB,OUTDSN=MY.SPECIAL.PROCLIB.D090802, * * UNLOAD=IEBCOPY * * * * * * * * AWSVOL Control Statement * * ------------------------- * * The AWSVOL control statement supplies characteristics of the * * virtual tape volume include volume serial number, compression * * techniques, and so forth. TAPEVOL must also be the first control * * statement specified. * * * * Keywords: VOLSER=(1 to 6 byte argument), * * OWNER=(1 to 10 byte argument placed into VOL1 owner), * * COMPRESS=0:1, (compress and IDRC control whether or not * * compression is to be used. IDRC and COMPRESS * * are durrently synomyms of each other). * * METHOD=1:2, (1 = gzip, 2=bzip2) * * LEVEL=1-9, (specifies the degree of compression required) * * IDRC=0:1, (currently a synonym of COMPRESS) * * CHUNKSIZE=nnnnn (specifies the size of the "chunk" to be * * compressed, should be avoided IMHO). * * * * If COMPRESS=0 then an AWS format is assumed. Note that compression * * related keywords will be implemented at a future date. * * * * Note COMPRESS, METHOD, LEVEL, IDRC, CHUNKSIZE have the same meaning * * as in the Hercules configuration. * * * * * * Example: * * * * AWSVOL VOLSER=MYTAPE,COMPRESS=1,METHOD=1,LEVEL=9,IDRC=1, * * CHUNKSIZE=65536,OWNER='AWSSL 1.9G' * * * * * *********************************************************************** EJECT *********************************************************************** * * * AWSGET Control Statement * * ------------------------ * * The AWSGET control statement will supply values necessary to * * retrieve a dataset FROM an AWS or HET virtual tape volume. * * * * keywords: INDSN=(up to 44 byte dsn of dataset stored inside of * * the AWS virtual tape) * * OUTDD=(ddname representing the dataset to receive data) * * FILENO=nnnnn (file number of the dataset inside of the * * AWS virtual tape, may be a standard label file * * number or absolute file number depending on the * * value of the SL= keyword) * * SL=YES:NO (specifies if standard labels are present, also * * impacts the meaning of the FILENO= keyword) * * * * Example: * * * * AWSGET INDSN=sys1.proclib,OUTDD=dd1,SL=YES * * * * * * * *********************************************************************** EJECT *********************************************************************** * * * AWSPUT Control Statement * * ------------------------ * * The AWSPUT control statement causes a dataset to be copied into the * * AWS or HET virtual tape file. Multiple EXPORT statements may be * * specified. A set of standard labels are produced as each statement * * is processed. * * * * If necessary the dataset is staged into a temporary dynamically * * allocated dataset prior to insertion into the virtual temp. * * * * Keywords: INDD=(statically allocated ddname representing the file * * to be copied and placed into the virtual tape file),* * INDSN=(dsname to be dynamically allocated and placed into * * the virtual tape file), * * OUTDSN=(44 byte dataset name to be placed into the labels * * which preceed and follow the file on virtual tape), * * TAPEDSN=(17 byte dataset name to be placed in label), * * UNLOAD=IEBCOPY:IDCAMS, (the utility called to stage the * * input dataset prior to insertion into the virtual * * tape), * * TYPE=EXPORT:REPRO (if UNLOAD=IDCAMS then TYPE specifies * * the method to be used to stage the dataset prior to * * to insertion into the virtual tape) * * * * The AWS or HET virtual tape OUTPUT file may specify any DCB * * attributes that are meaningful in the users environment. * * * * RECFM=V - Variable length output, lrecl and blksize as specified. * * Records are output in a format consistent with that * * produced by Brandon Hill's AWSUTIL (i.e. no aggregation * * of AWS structures within a single output record). * * * * RECFM=F - Fixed length output, lrecl and blksize as specified. * * Records are output in a format consistent with that * * produced by Sam Golob's VTT2* family of utilities * * (i.e. AWS structures are aggregated and "folded" at the * * specified lrecl). * * * * RECFM=U - Undefined length output, blksize as specified. Records * * are output in an aggregated BLKSIZE length block. * * (THIS IS THE PREFERRED METHOD WHEN THE VIRTUAL TAPE IS TO * * BE TRANSPORTED TO OTHER ENVIRONMENTS SUCH AS HERCULES). * * * * * * * * * *********************************************************************** EJECT *********************************************************************** * * * Implementation Conventions * * -------------------------- * * An effort was made to structure the code such that a nearly endless * * set of new features can be added without becoming unwieldly. For * * that reason functions tend to be implemented as small discrete * * CSECTS. * * * * Each CSECT name should begin with the string AWS to avoid name * * space collision with other code which may be statically linked in * * the future. It is recommended that all labels within an individual * * CSECT follow a name space convention unique to that CSECT. * * * * Each CSECT should contain an LTORG statement. This reduces the * * need for multiple base registers to establish addressability to * * large literal pools. * * * * To avoid subtle addressability related bugs, each CSECT should * * contain a 'DROP ,' statement to release all USINGS in effect. * * * * A register save area stack mechanism is provided to ease linkage * * between internal functions and to minimize contention for scarce * * register resource. All CSECTS should utilize the AWSENTRY and * * AWSEXIT macro instructions where possible. * * * * This code is reentrant and refreshable. All data areas which * * require modification should be placed in CSECT AWSDATA between * * labels DSDYNAM and DSBUFFER. If the data areas contain initialized * * data then they should be placed between labels DSBEGIN and DSBUFFER.* * Data areas located between labels DSDYNAM and DSBEGIN have storage * * allocated for them but are not initialized (to other than nulls). * * * * Dynamic storage ADCON relocation, etc, code should be placed into * * CSECT AWSINIT. * * * *********************************************************************** EJECT *********************************************************************** * * * Register Usage Conventions * * -------------------------- * * * * R14 - Linkage, contains the address at which instruction streaming * * should resume. May be used as an internal work register. * * * * R15 - Linkage, contains the address of the CSECT to be called. * * Upon return contains the return code from the called CSECT. * * May be used as an internal work register. * * * * R0 through R6 - Preserved by AWSENTRY and AWSEXIT. Available for * * whatever usage the programmer desires within the scope of * * the local CSECTs. * * * * R7 through R9 - Reserved for future unforeseen needs. Please avoid * * usage except in the most dire of circumstances. * * * * R10 - Common storage addressability. Set by AWSENTRY. * * * * R11 - Dynamic storage addressability. Set by AWSENTRY. * * * * R12 - Local CSECT base register. Set by AWSENTRY. * * * * R13 - Pointer to current savearea. Set to the next save area stack * * entry by AWSENTRY. * * * * * * * * * * * * * * * * * *********************************************************************** EJECT *********************************************************************** * Customizable Symbols * *********************************************************************** SPACE 1 GBLA &AWSDBUG debug switch &AWSDBUG SETA 0 1 = enable debugging support SPACE 1 STACKCT EQU 10 savearea stack entries BUFSIZE EQU 70000 max blksize + hdrs + aws cb + pad SPACE 1 *********************************************************************** * Register Equates (make registers visible in xref) * *********************************************************************** SPACE 1 R0 EQU 0 R1 EQU 1 R2 EQU 2 R3 EQU 3 R4 EQU 4 R5 EQU 5 R6 EQU 6 R7 EQU 7 R8 EQU 8 R9 EQU 9 R10 EQU 10 R11 EQU 11 R12 EQU 12 R13 EQU 13 R14 EQU 14 R15 EQU 15 TITLE 'AWSSL - macro definitions' *********************************************************************** * MACRO DEFINITIONS * *********************************************************************** EJECT MACRO &LBL AWSENTRY .********************************************************************** .* AWSENTRY - push caller's registers into provided savearea, obtain * .* a new savearea from the savearea stack, addressability. * .********************************************************************** GBLA &AWSDBUG debug switch LCLA &L,&I AIF ('&LBL' EQ '').A010 &LBL DS 0H .A010 ANOP &L SETA (K'&SYSECT+2+4)/2*2 offset to stm &I SETA K'&SYSECT B &L.(,R15) branch around eyecatcher DC AL1(&I) eyecatcher length DC C'&SYSECT' CSECT name STM R14,R12,12(R13) save caller's environment LR R12,R15 base register LA R15,72(,R13) next stack entry ST R15,8(,R13) forward linkage ST R13,4(,R15) backward linkage LR R13,R15 establish new current savearea USING &SYSECT,R12 addressability USING AWSDYNAM,R11 addressability USING AWSCOMST,R10 addressability AIF (&AWSDBUG EQ 0).MEND AIF ('&SYSECT' EQ 'AWSPRNT').MEND AIF ('&SYSECT' EQ 'AWSINIT').MEND AWSMSG 000I,'&SYSECT Entry' .MEND MEND EJECT MACRO &LBL AWSEXIT .********************************************************************** .* AWSEXIT - release savearea stack entry, pop user's environment, * .* return to caller. * .********************************************************************** GBLA &AWSDBUG debug switch AIF ('&LBL' EQ '').A010 &LBL DS 0H .A010 AIF (&AWSDBUG EQ 0).A020 AIF ('&SYSECT' EQ 'AWSPRNT').A020 AIF ('&SYSECT' EQ 'AWSTERM').A020 MVC DSMSG+1(7),=CL7'AWS000I' MVC DSMSG+19(14),=CL14'&SYSECT EXIT' MVC DSMSG+35(3),=CL3'RC:' CVD R15,DSDWORK convert to decimal MVC DSMSG+38(6),=X'402020202120' ED DSMSG+38(6),DSDWORK+5 make printable OI DSMSG+43,C'0' LR R2,R15 save return code AWSMSG , print exit message LR R15,R2 restore retern code .A020 ANOP L R13,4(,R13) restore savearea pointer LM R0,R12,20(R13) restore caller's registers L R14,12(,R13) restore savearea address LTR R15,R15 set condition code into psw BR R14 return to caller SPACE 1 MEND EJECT MACRO &LBL AWSMSG &ID,&TXT .********************************************************************** .* AWSMSG - output a message to the AWSPRINT log * .********************************************************************** GBLA &AWSDBUG debug switch LCLA &L1,&L2 LCLC &C AIF ('&ID' EQ '' AND '&TXT' EQ '').A040 AIF ('&ID' NE '').A010 MNOTE 8,'*** MSG CSECT ID OMITTED' .A010 AIF ('&TXT' NE '').A020 MNOTE 8,'*** MSG TEXT OMITTED' .A020 AIF ('&LBL' EQ '').A030 &LBL DS 0H .A030 ANOP &C SETC 'AWS&ID' &L1 SETA K'&C MVC DSMSG+1(&L1),=C'&C' &L2 SETA K'&TXT-2 MVC DSMSG+19(&L2),=C&TXT .A040 ANOP AWSCALL AWSPRNT print function MEND EJECT MACRO &LBL AWSDMP &ID,&L,&R,&T .********************************************************************** .* AWSDMP - hex dump register (and optionally 16 bytes of storage) * .* i.e. AWSDMP 00I,IGET900,R3 (dumps r3 and 16 bytes strg) * .* i.e. AWSDMP 00I,IGET100,R4,N (dumps r4 only) * .* * .* This macro is intended for debugging purposes only. * .********************************************************************** GBLA &AWSDBUG debug switch LCLA &L1,&L2 LCLC &C STM R14,R12,12(R13) LA R13,72(,R13) AIF ('&ID' NE '').A010 MNOTE 8,'*** MSG CSECT ID OMITTED' .A010 AIF ('&R' NE '').A020 MNOTE 8,'*** REGISTER OMITTED' .A020 AIF ('&LBL' EQ '').A030 &LBL DS 0H .A030 ANOP &C SETC 'AWS&ID' &L1 SETA K'&C MVC DSMSG+1(&L1),=C'&C' AIF ('&L' EQ '').A035 &L1 SETA K'&L+1 MVC DSMSG+10(&L1),=C'&L:' .A035 ANOP &L1 SETA K'&R MVC DSMSG+19(&L1),=C'&R' &L1 SETA 23 ST &R,DSFWORK register UNPK DSHEXWK(9),DSFWORK(5) unpack data TR DSHEXWK(8),CSHEXTR make printable MVC DSMSG+&L1.(8),DSHEXWK return code AIF ('&T' EQ 'N').A040 &L1 SETA &L1+12 UNPK DSHEXWK(9),0(5,&R) TR DSHEXWK(8),CSHEXTR MVC DSMSG+&L1.(8),DSHEXWK &L1 SETA &L1+9 UNPK DSHEXWK(9),4(5,&R) TR DSHEXWK(8),CSHEXTR MVC DSMSG+&L1.(8),DSHEXWK &L1 SETA &L1+9 UNPK DSHEXWK(9),8(5,&R) TR DSHEXWK(8),CSHEXTR MVC DSMSG+&L1.(8),DSHEXWK &L1 SETA &L1+9 UNPK DSHEXWK(9),12(5,&R) TR DSHEXWK(8),CSHEXTR MVC DSMSG+&L1.(8),DSHEXWK MVI DSMSG+72,C'*' MVC DSMSG+73(16),0(&R) MVI DSMSG+89,C'*' .A040 ANOP AWSCALL AWSPRNT print function SH R13,=H'72' LM R14,12,12(R13) MEND EJECT MACRO &LBL AWSCALL &FUN .********************************************************************** .* AWSCALL - Call a function * .********************************************************************** AIF ('&LBL' EQ '').A010 &LBL DS 0H .A010 ANOP AIF ('&FUN' NE 'AWSDYNE').A020 L R15,CSAWSDYE dynamic allocatione error handler AGO .A999 .A020 AIF ('&FUN' NE 'AWSEPUT').A030 L R15,CSAWSEPT put text to virtual tape AGO .A999 .A030 AIF ('&FUN' NE 'AWSMARK').A040 L R15,CSAWSMRK put tapemark to virtual tape AGO .A999 .A040 AIF ('&FUN' NE 'AWSPRNT').A050 L R15,CSAWSPRT write to log AGO .A999 .A050 AIF ('&FUN' NE 'AWSIGET').A900 L R15,CSAWSIGE read a logical aws block AGO .A999 .A900 ANOP L R15,=A(&FUN) function to be called .A999 ANOP BALR R14,R15 issue call MEND EJECT MACRO &LBL AWSSWAP .********************************************************************** .* AWSSWAP - swap byte orders, set sizes * .********************************************************************** AIF ('&LBL' EQ '').A010 &LBL DS 0H .A010 ANOP ICM R0,3,DSLSTSIZ reverse previous size byte order STCM R0,1,AWSLENP STCM R0,2,AWSLENP+1 ICM R0,3,AWSLENC size of current block STCM R0,3,DSLSTSIZ set new last size STCM R0,1,AWSLENC reverse current size byte order STCM R0,2,AWSLENC+1 MEND SPACE 1 MACRO &LBL AWSSWAPR .********************************************************************** .* AWSSWAPR - swap byte orders, no sizes * .********************************************************************** AIF ('&LBL' EQ '').A010 &LBL DS 0H .A010 ANOP ICM R0,3,AWSLENC size of current block STCM R0,1,AWSLENC reverse current size byte order STCM R0,2,AWSLENC+1 MEND SPACE 1 MACRO &LBL AWSDUMMY , Dummy function .********************************************************************** .* AWSDUMMY - dummy function, merely returns * .********************************************************************** &LBL CSECT , dummy function AWSENTRY , SLR R15,R15 zero return code AWSEXIT , DROP , MEND EJECT *********************************************************************** * System control block definitions (Assembler F forward referenced) * *********************************************************************** SPACE 1 PRINT OFF DCBD DSORG=PS IEFZB4D0 , IEFZB4D2 , IHAPSA , PSA IKJTCB , TCB TIOT DSECT , TIOT IEFTIOT1 , PRINT ON EJECT *********************************************************************** * AWSSL - Utility entry point * *********************************************************************** SPACE 1 AWSSL CSECT , module entry point SAVE (14,12),,'AWSSL &SYSDATE &SYSTIME' LR R12,R15 base register USING AWSSL,R12 addressability SPACE 1 GETMAIN R,LV=AWSDATAL+3*BUFSIZE Dynamic storage ST R13,4(,R1) backward linkage ST R1,8(,R13) forward linkage LR R13,R1 current savearea LR R11,R1 set dynamic storage location USING AWSDATA,R11 addressability ST R11,DSDATAP set pointer to awsdata origin LA R0,DSSTACK stack origin ST R0,DSSTACKP set stack origin pointer LA R11,AWSDYNAM-AWSDATA(,R11) position beyond stack USING AWSDYNAM,R11 addressability SPACE 1 L R10,=A(AWSCOMST) constant common data USING AWSCOMST,R10 addressability SPACE 1 AWSCALL AWSINIT initialization BNZ SSLXIT if not successful, branch SPACE 1 SSL010 DS 0H main processing loop AWSCALL AWSMAIN invoke verb handler BZ SSL010 continue until eof or error SPACE 1 SSLXIT DS 0H return to caller CH R15,=H'-4' eof from main? BNE *+6 no, branch SLR R15,R15 else force zero return code LR R2,R15 save rc for now AWSCALL AWSTERM clean up for termination SPACE 1 L R3,4(,R13) Callers savearea L R4,DSDATAP dynamic storage origin FREEMAIN R,LV=AWSDATAL+3*BUFSIZE,A=(R4) release storage SPACE 1 LR R15,R2 restore return code LR R13,R3 restore savearea pointer RETURN (14,12),RC=(15) return to caller SPACE 1 LTORG , DROP TITLE 'AWSSL - Initialization' *********************************************************************** * AWSINIT - initialization, relocation, open files * * msgs AWS01n * *********************************************************************** SPACE 1 AWSINIT CSECT , initialization logic AWSENTRY , csect entry SPACE 1 L R2,=A(AWSRELOC) start of relocatable storage L R3,=A(DSENDL) length of relocateable storage LR R1,R3 origin length = destination LA R0,AWSRELOC-AWSDYNAM(,R11) target of move MVCL R0,R2 copy storage model into dynamic area SPACE 1 LA R0,INFMJFCB jfcb work area STCM R0,7,DSJFCBL+1 LA R0,DSJFCBL rdjfcb exist list location STCM R0,7,AWSUT1+(DCBEXLSA-IHADCB) STCM R0,7,AWSUT2+(DCBEXLSA-IHADCB) STCM R0,7,AWSUT3+(DCBEXLSA-IHADCB) SPACE 1 LA R0,DSBUFFER Buffer location ST R0,DSBUFTP Set location of next text SPACE 1 LA R0,DSARB input dataset request block STCM R0,7,DSARBP+1 LA R0,DSADDNM input ddname ST R0,DSATXTP LA R0,DSADSNM input dsn ST R0,DSATXTP+4 LA R0,DSASTATS input stats ST R0,DSATXTP+8 LA R0,DSADISP input disposition STCM R0,7,DSATXTP+13 LA R1,DSARB input rb location USING S99RB,R1 addressability LA R0,DSATXTP input text pointer ST R0,S99TXTPP MVI S99RBLN,S99RBEND-S99RB length of rb MVI S99VERB,S99VRBAL allocation request MVI S99FLAG1,S99NOCNV+S99NOMNT do not issue mounts DROP R1 SPACE 1 LA R0,DSTARB temp work dataset request block STCM R0,7,DSTARBP+1 LA R0,DSTADDNM temp work ddname ST R0,DSTATXTP LA R0,DSTAUNIT temp work unit ST R0,DSTATXTP+4 LA R0,DSTASPCU temp work space primary units ST R0,DSTATXTP+8 LA R0,DSTASPCP temp work space primary qty ST R0,DSTATXTP+12 LA R0,DSTASPCS temp work space secondary qty STCM R0,7,DSTATXTP+17 LA R1,DSTARB temp work rb location USING S99RB,R1 addressability LA R0,DSTATXTP input text pointer ST R0,S99TXTPP MVI S99RBLN,S99RBEND-S99RB length of rb MVI S99VERB,S99VRBAL allocation request MVI S99FLAG1,S99NOCNV+S99NOMNT do not issue mounts DROP R1 SPACE 1 LA R0,DSSARB sysin dataset request block STCM R0,7,DSSARBP+1 LA R0,DSSADDNM sysin ddname ST R0,DSSATXTP LA R0,DSSAUNIT sysin unit ST R0,DSSATXTP+4 LA R0,DSSASPCU sysin space primary units ST R0,DSSATXTP+8 LA R0,DSSASPCP sysin space primary qty ST R0,DSSATXTP+12 LA R0,DSSASPCS sysin space secondary qty STCM R0,7,DSSATXTP+17 LA R1,DSSARB sysin rb location USING S99RB,R1 addressability LA R0,DSSATXTP input text pointer ST R0,S99TXTPP MVI S99RBLN,S99RBEND-S99RB length of rb MVI S99VERB,S99VRBAL allocation request MVI S99FLAG1,S99NOCNV+S99NOMNT do not issue mounts DROP R1 SPACE 1 LA R0,DSPARB sysprint dataset request block STCM R0,7,DSPARBP+1 LA R0,DSPADDNM sysprint ddname ST R0,DSPATXTP LA R0,DSPADUMY dummy dataset STCM R0,7,DSPATXTP+5 LA R1,DSPARB sysin rb location USING S99RB,R1 addressability LA R0,DSPATXTP input text pointer ST R0,S99TXTPP MVI S99RBLN,S99RBEND-S99RB length of rb MVI S99VERB,S99VRBAL allocation request MVI S99FLAG1,S99NOCNV+S99NOMNT do not issue mounts SPACE 1 LA R0,DSURB unallocation request block STCM R0,7,DSURBP+1 LA R0,DSUDDNM ddname STCM R0,7,DSUTXTP+1 LA R1,DSURB unallocation rb location USING S99RB,R1 addressability LA R0,DSUTXTP input text pointer ST R0,S99TXTPP MVI S99RBLN,S99RBEND-S99RB length of rb MVI S99VERB,S99VRBUN unallocation request MVI S99FLAG1,S99NOCNV+S99NOMNT do not issue mounts DROP R1 SPACE 1 INIT010 DS 0H prepare AWSPRINT OPEN (AWSPRINT,(OUTPUT)),MF=(E,DSOPENL) open awsprint TM AWSPRINT+(DCBOFLGS-IHADCB),DCBOFOPN open successful? BO INIT020 yes, branch WTO 'AWS010E AWSPRINT OPEN FAILED' LA R15,12 sysprint open failed B INITXIT exit with error SPACE 1 INIT020 DS 0H prepare AWSOUT AIF (&AWSDBUG EQ 0).INIT010 AWSMSG 011I,'AWSINIT Entry' .INIT010 ANOP OPEN (AWSCNTL,(INPUT)),MF=(E,DSOPENL) open awscntl TM AWSCNTL+(DCBOFLGS-IHADCB),DCBOFOPN open successful? BO INIT030 yes, branch AWSMSG 012E,'AWSCNTL open failed' LA R15,12 16=awscntl open failed B INITXIT exit with error SPACE 1 INIT030 DS 0H AWSCALL AWSJOBNM Capture job and step name info SPACE 1 INIT040 DS 0H SPACE 1 INITXIT DS 0H function exit AWSEXIT , return to caller SPACE 1 LTORG , DROP , TITLE 'AWSMAIN - Process next control statement' *********************************************************************** * AWSMAIN - Verb dispatcher * * msgs AWS02n * *********************************************************************** SPACE 1 AWSMAIN CSECT , Process next control statement AWSENTRY , SPACE 1 LA R0,MAINEOF AWSCNTL eof STCM R0,7,AWSCNTL+(DCBEODA-IHADCB) place into dcb SPACE 1 MAIN010 DS 0H scan for dataset verb GET AWSCNTL retrieve a cntl record LR R3,R1 record location MVC DSMSG+1(17),=C'AWS020I AWSCNTL:' MVC DSMSG+19(80),0(R3) set statement into message buffer AWSMSG , print function CLI 0(R1),C'*' comment? BE MAIN010 yes, branch CLC 0(80,R3),CSBLNKS blank line? BE MAIN010 yes, branch CLC =C'AWSVOL ',0(R3) tapevol verb? BE MAIN020 yes, branch CLC =C'AWSGET ',0(R3) import verb? BE MAIN030 yes, branch CLC =C'AWSPUT ',0(R3) export verb? BE MAIN040 yes, branch AWSMSG 021E,'Statement is not recognized' LA R15,8 rc=4, invalid statement B MAINXIT return to caller SPACE 1 MAIN020 DS 0H tapevol verb AWSCALL AWSTVOL invoke tapevol B MAINXIT SPACE 1 MAIN030 DS 0H import verb TM DSFLAGS2,DSFEXPRT export invoked previously? BO MAIN050 yes, branch OI DSFLAGS2,DSFIMPRT indicate import invoked AWSCALL AWSIMPRT invoke import B MAINXIT SPACE 1 MAIN040 DS 0H export verb TM DSFLAGS2,DSFIMPRT import invoked previously? BO MAIN060 yes, branch OI DSFLAGS2,DSFEXPRT indicate import invoked AWSCALL AWSEXPRT invoke export B MAINXIT SPACE 1 MAIN050 DS 0H import invoked after export AWSMSG 022E,'AWSGET is mutually exclusive with AWSPUT' LA R15,8 B MAINXIT SPACE 1 MAIN060 DS 0H export invoked after import AWSMSG 023E,'AWSPUT is mutually exclusive with AWSGET' LA R15,8 B MAINXIT SPACE 1 MAINEOF DS 0H AWSCNTL reached eof MVC DSMSG+10(8),=C'AWSCNTL:' AWSMSG 024I,'End of AWSCNTL input detected' L R15,=F'-4' indicate eof SPACE 1 MAINXIT DS 0H function exit AWSEXIT , return to caller SPACE 1 LTORG , DROP , TITLE 'AWSTERM - Termination processing' *********************************************************************** * AWSTERM - Termination, close files and release resources * * msg AWS03n * *********************************************************************** SPACE 1 AWSTERM CSECT , Termination processing AWSENTRY , SPACE 1 TM DSFLAGS,DSFOPNEX AWSFILE open for export? BZ TERM010 no, branch OI DSFLAGS,DSFFLUSH flush last buffer (just in case) AWSCALL AWSMARK write final tape mark SPACE 1 TERM010 DS 0H check stack integrity L R1,DSSTACKP stack origin LA R0,STACKCT max entries in stack SLR R2,R2 clear counter TERM020 DS 0H calculate max stack depth CLC CSF0,4(R1) entry ever been used? BE TERM030 no, branch LA R2,1(,R2) increment count LA R1,18*4(,R1) position at next stack entry BCT R0,TERM020 continue until exhausted AWSMSG 030W,'WARNING! Stack overflow detected, contact rhp@dra* per.net' B TERM040 SPACE 1 TERM030 DS 0H write max stack depth used AIF (&AWSDBUG EQ 0).TERM030 CVD R2,DSDWORK convert to packed MVC DSXL16(4),=X'40202120' edit mask ED DSXL16(4),DSDWORK+6 OI DSXL16+3,C'0' make printable MVC DSMSG+1(7),=C'AWS031I' MVC DSMSG+19(20),=C'Maximum stack depth:' MVC DSMSG+39(2),DSXL16+2 set count into message AWSMSG , write the message .TERM030 ANOP SPACE 1 TERM040 DS 0H unallocate as needed AWSCALL AWSUNALC dynamic unallocation LR R3,R15 save return code SPACE 1 TM AWSCNTL+(DCBOFLGS-IHADCB),DCBOFOPN open? BZ TERM050 no, branch CLOSE AWSCNTL,MF=(E,DSCLOSEL) close it FREEPOOL AWSCNTL release buffers SPACE 1 TERM050 DS 0H cleanup AWSFILE TM AWSFILE+(DCBOFLGS-IHADCB),DCBOFOPN open? BZ TERM060 no, branch CLOSE AWSFILE,MF=(E,DSCLOSEL) close it FREEPOOL AWSFILE release buffers SPACE 1 TERM060 DS 0H cleanup AWSPRINT TM AWSPRINT+(DCBOFLGS-IHADCB),DCBOFOPN open? BZ TERM070 no, branch CLOSE AWSPRINT,MF=(E,DSCLOSEL) close it FREEPOOL AWSPRINT release buffers SPACE 1 TERM070 DS 0H cleanup SYSIN TM SYSIN+(DCBOFLGS-IHADCB),DCBOFOPN open? BZ TERM080 no, branch CLOSE SYSIN,MF=(E,DSCLOSEL) close it FREEPOOL SYSIN release buffers SPACE 1 TERM080 DS 0H cleanup AWSUT2 TM AWSUT2+(DCBOFLGS-IHADCB),DCBOFOPN open? BZ TERM090 no, branch CLOSE AWSUT2,MF=(E,DSCLOSEL) close it FREEPOOL AWSUT2 release buffers SPACE 1 TERM090 DS 0H cleanup AWSUT2 TM AWSUT3+(DCBOFLGS-IHADCB),DCBOFOPN open? BZ TERM100 no, branch CLOSE AWSUT3,MF=(E,DSCLOSEL) close it FREEPOOL AWSUT3 release buffers SPACE 1 TERM100 DS 0H LR R15,R3 return code from unalloc SPACE 1 TERMXIT DS 0H exit AWSEXIT , return to caller SPACE 1 LTORG , DROP , TITLE 'AWSTVOL - AWSVOL verb handler' *********************************************************************** * AWSTVOL - AWSVOL verb handler * * msg AWS04n * *********************************************************************** SPACE 1 AWSTVOL CSECT , TAPEVOL verb handler AWSENTRY , SPACE 1 AWSCALL AWSTVPAR invoke keyword parser SPACE 1 AWSMSG , print blank line AWSMSG , print blank line SPACE 1 AWSEXIT , return to caller SPACE 1 LTORG , DROP , TITLE 'AWSIMPRT - Import verb handler' *********************************************************************** * AWSIMPRT - AWSGET verb handler * * msg AWS05n * *********************************************************************** SPACE 1 AWSIMPRT CSECT , Import verb handler AWSENTRY , SPACE 1 LR R3,R1 future reference TM AWSUT2+(DCBOFLGS-IHADCB),DCBOFOPN AWSUT2 open? BZ IMPRT010 no, branch CLOSE AWSUT2,MF=(E,DSCLOSEL) close awsfile FREEPOOL AWSUT2 release buffers SPACE 1 IMPRT010 DS 0H prepare to open NI DSFLAGS,255-DSFOPNEX clear open for export (in case) SPACE 1 XC DSBUFEND,DSBUFEND indicate no blocks read XC DSBUFTP,DSBUFTP LA R2,AWSUT2 dcb location USING IHADCB,R2 addressability MVC DCBDDNAM,=CL8'AWSFILE' set ddname XC DCBBLKSI,DCBBLKSI clear blocksize XC DCBLRECL,DCBLRECL clear lrecl OPEN (AWSUT2,(INPUT)),MF=(E,DSOPENL) open awsfile TM DCBOFLGS,DCBOFOPN open successful? BO IMPRT020 yes, branch AWSMSG 050E,'AWSFILE open for AWSGET failed' LA R15,8 awsout open failed B IMPRTXIT exit with error SPACE 1 IMPRT020 DS 0H import TM AWSFILE+(DCBOFLGS-IHADCB),DCBOFOPN file open? BZ IMPRT030 no, branch CLOSE AWSFILE,MF=(E,DSCLOSEL) else close it FREEPOOL AWSFILE SPACE 1 IMPRT030 DS 0H prepare to import SLR R0,R0 clear register ICM R0,3,DCBLRECL get lrecl BZ IMPRT040 if zero, branch CH R0,=H'16' at least 16 bytes? BNL IMPRT050 yes, branch AWSMSG 051E,'Input lrecl must be at least 16 bytes' LA R15,8 B IMPRTXIT SPACE 1 IMPRT040 DS 0H check blksize ICM R0,3,DCBBLKSI load blksize CH R0,=H'16' at least 16 bytes? BNL IMPRT050 yes, branch AWSMSG 052E,'Input blksize must be at least 16 bytes' LA R15,8 B IMPRTXIT DROP R2 SPACE 1 IMPRT050 DS 0H SLR R0,R0 clear register ST R0,DSGTXTP clear pointer STH R0,DSGTXTL clear length RDJFCB AWSUT2,MF=(E,DSRDJFCB) read the jfcb SPACE 1 AWSMSG , blank line MVC DSMSG+1(7),=C'AWS053I' MVC DSMSG+19(31),=C'Virtual tape dataset name :' MVC DSMSG+51(44),JFCBDSNM AWSMSG , SPACE 1 MVC DSRECFM,CSBLNKS clear default recfm SLR R0,R0 clear register STH R0,DSLRECL clear lrecl STH R0,DSBLKSIZ clear blksize SPACE 1 LR R1,R3 current control statement AWSCALL AWSIMPAR parse import keywords BNZ IMPRTXIT AWSCALL AWSSKPTF position to file BNZ IMPRTXIT AWSCALL AWSIMLBL process header labels BNZ IMPRTXIT AWSCALL AWSICOPY copy data into MVS dataset BNZ IMPRTXIT AWSCALL AWSIMTLR process trailer labels SPACE 1 IMPRTXIT DS 0H EXIT AWSEXIT , return to caller SPACE 1 LTORG , DROP , TITLE 'AWSEXPRT - Export verb handler' *********************************************************************** * AWSEXPRT - AWSPUT verb handler * * msg AWS06n * *********************************************************************** SPACE 1 AWSEXPRT CSECT , Export verb handler AWSENTRY , SPACE 1 LR R2,R1 future reference TM AWSFILE+(DCBOFLGS-IHADCB),DCBOFOPN already open? BO EXPRT010 yes, branch CLOSE AWSFILE,MF=(E,DSCLOSEL) close file FREEPOOL AWSFILE SPACE 1 OPEN (AWSFILE,(OUTPUT)),MF=(E,DSOPENL) open awsfile TM AWSFILE+(DCBOFLGS-IHADCB),DCBOFOPN open successful? BO EXPRT010 yes, branch AWSMSG 060E,'AWSFILE open for EXPORT failed' LA R15,8 awsout open failed B EXPRTXIT exit with error SPACE 1 EXPRT010 DS 0H prepare awscntl TM AWSFILE+(DCBRECFM-IHADCB),DCBRECU recfm=u? BO EXPRT020 yes, branch TM AWSFILE+(DCBRECFM-IHADCB),DCBRECV recfm=v? BZ EXPRT020 no, branch OI DSFLAGS,DSFRECV indicate variable length output SPACE 1 EXPRT020 DS 0H export main line OI DSFLAGS,DSFOPNEX indicate open for export LR R1,R2 current control statement AWSCALL AWSEXPAR parse export keywords BNZ EXPRTXIT AWSCALL AWSJFDSN extract JFCB dsname BNZ EXPRTXIT AWSCALL AWSTPDSN set 17 byte tape dsname BNZ EXPRTXIT AWSCALL AWSUNLD unload (stage) file if necessary BNZ EXPRTXIT AWSCALL AWSECOPY copy the file into AWS structure BNZ EXPRTXIT AWSCALL AWSMARK write tape mark BNZ EXPRTXIT AWSCALL AWSTLR write trailer labels BNZ EXPRTXIT AWSCALL AWSUNALC unallocate files SPACE 1 EXPRTXIT DS 0H return to caller AWSEXIT , SPACE 1 LTORG , DROP , TITLE 'AWSTVPAR - Parse AWSVOL verb parameters' *********************************************************************** * AWSTVPAR - Parse AWSVOL verb parameters * * msg AWS07n * * * * On entry, r1 = cntl card image containing extract verb. * * On exit, appropriate data areas updated. * *********************************************************************** SPACE 1 AWSTVPAR CSECT , Parse extract verb parameters AWSENTRY , SPACE 1 MVC DSTVOL,CSBLNKS clear volser MVI DSHETCMP,C' ' clear MVI DSHETMTH,C' ' MVI DSHETLVL,C' ' MVI DSHETIDR,C' ' MVC DSHETCSZ,CSBLNKS MVC DSOWNER,=CL10'AWSSL 1.9G' SPACE 1 LR R3,R1 cntl statement image LR R5,R1 current location in scan LA R1,7 point beyond verb SPACE 1 TVPAR010 DS 0H locate a keyword ALR R5,R1 end of previous keyword if any LA R1,80(,R3) end of statement SLR R1,R3 length remaining BCTR R1,0 machine relative EX R1,TVPAREX1 locate keyword BZ TVPARRC0 if no keyword found, exit LR R4,R1 keyword suffix location LA R5,1(,R1) argument origin TVPAR020 DS 0H locate origin of keyword BCTR R4,0 backup one byte CLI 0(R4),C',' comma delimiter? BE TVPAR030 yes, branch CLI 0(R4),C' ' space delimiter? BE TVPAR030 yes, branch CR R4,R3 origin of statement reached? BH TVPAR020 no, continue search AWSMSG 070E,'TAPEVOL parameter syntax error' LA R15,8 export parameter syntax error B TVPARXIT return to caller SPACE 1 TVPAR030 DS 0H dispatch keyword handler LA R4,1(,R4) keyword origin CLC =C'VOLSER=',0(R4) volser= keyword? BE TVPAR100 yes, branch CLC =C'COMPRESS=',0(r4) COMPRESS= keyword? BE TVPAR110 yes, branch CLC =C'METHOD=',0(r4) METHOD= keyword? BE TVPAR120 yes, branch CLC =C'LEVEL=',0(R4) LEVEL= keyword? BE TVPAR130 yes, branch CLC =C'IDRC=',0(r4) IDRC= keyword? BE TVPAR140 yes, branch CLC =C'CHUNKSIZE=',0(r4) CHUNKSIZE= keyword? BE TVPAR150 yes, branch CLC =C'OWNER=',0(R4) OWNER= keyword? BE TVPAR160 yes, branch MVC DSMSG+1(7),=C'AWS071E' MVC DSMSG+19(29),=C'TAPEVOL KEYWORD UNRECOGNIZED:' LR R1,R5 argument origin SLR R1,R4 length of argument BCTR R1,0 machine relative EX R1,TVPAREX2 set keyword into message AWSMSG , write the message LA R15,8 export keyword unrecognized B TVPARXIT return to caller SPACE 1 TVPAR100 DS 0H tapevol= keyword handler MVC DSTVOL,CSBLNKS clear volser LA R1,80(,R3) end of cntl statement SLR R1,R5 length of statement remaining EX R1,TVPAREX3 locate delimiter LR R6,R1 delimiter location SR R1,R5 length of argument BZ TVPAR930 if null, branch CH R1,=Y(L'DSTVOL) greater than maximum length? BL *+8 no, branch LA R1,L'DSTVOL else force to max length BCTR R1,0 machine relative EX R1,TVPAREX4 capture dsn B TVPAR900 SPACE 1 TVPAR110 DS 0H HET= keyword handler MVI DSHETCMP,C' ' clear LA R1,80(,R3) end of cntl statement SLR R1,R5 length of statement remaining EX R1,TVPAREX3 locate delimiter LR R6,R1 delimiter location SR R1,R5 length of argument BZ TVPAR930 if null, branch CH R1,=Y(L'DSHETCMP) greater than maximum length? BL *+8 no, branch LA R1,L'DSHETCMP else force to max length BCTR R1,0 machine relative EX R1,TVPAREX5 capture argument AWSMSG 072W,'Warning, COMPRESS keyword is not yet implemented,* ignored' B TVPAR900 SPACE 1 TVPAR120 DS 0H METHOD= keyword handler MVI DSHETMTH,C' ' clear HETLVL LA R1,80(,R3) end of cntl statement SLR R1,R5 length of statement remaining EX R1,TVPAREX3 locate delimiter LR R6,R1 delimiter location SR R1,R5 length of argument BZ TVPAR930 if null, branch CH R1,=Y(L'DSHETMTH) greater than maximum length? BL *+8 no, branch LA R1,L'DSHETMTH else force to max length BCTR R1,0 machine relative EX R1,TVPAREX6 capture argument AWSMSG 073W,'Warning, METHOD keyword is not yet implemented, i* gnored' B TVPAR900 SPACE 1 TVPAR130 DS 0H LEVEL= keyword handler MVI DSHETLVL,C' ' clear HETLVL LA R1,80(,R3) end of cntl statement SLR R1,R5 length of statement remaining EX R1,TVPAREX3 locate delimiter LR R6,R1 delimiter location SR R1,R5 length of argument BZ TVPAR930 if null, branch CH R1,=Y(L'DSHETLVL) greater than maximum length? BL *+8 no, branch LA R1,L'DSHETLVL else force to max length BCTR R1,0 machine relative EX R1,TVPAREX7 capture argument AWSMSG 074W,'Warning, LEVEL keyword is not yet implemented, ig* nored' B TVPAR900 SPACE 1 TVPAR140 DS 0H IDRC= keyword handler MVI DSHETIDR,C' ' clear LA R1,80(,R3) end of cntl statement SLR R1,R5 length of statement remaining EX R1,TVPAREX3 locate delimiter LR R6,R1 delimiter location SR R1,R5 length of argument BZ TVPAR930 if null, branch CH R1,=Y(L'DSHETIDR) greater than maximum length? BL *+8 no, branch LA R1,L'DSHETIDR else force to max length BCTR R1,0 machine relative EX R1,TVPAREX8 capture argument AWSMSG 075W,'Warning, IDRC keyword is not yet implemented, ign* ored' B TVPAR900 SPACE 1 TVPAR150 DS 0H CHUNKSIZE= keyword handler MVC DSHETCSZ,CSBLNKS clear LA R1,80(,R3) end of cntl statement SLR R1,R5 length of statement remaining EX R1,TVPAREX3 locate delimiter LR R6,R1 delimiter location SR R1,R5 length of argument BZ TVPAR930 if null, branch CH R1,=Y(L'DSHETCSZ) greater than max length? BL *+8 no, branch LA R1,L'DSHETCSZ else force to max length BCTR R1,0 machine relative EX R1,TVPAREX9 capture argument AWSMSG 076W,'Warning, CHUNKSIZE keyword is not yet implemented* , ignored' B TVPAR900 SPACE 1 TVPAR160 DS 0H OWNER= keyword handler MVC DSOWNER,CSBLNKS LA R1,80(,R3) end of cntl statement SLR R1,R5 length of statement remaining TRT 0(1,R5),CSPARST3 quoted string? BZ TVPAR162 no, branch LA R5,1(,R5) position at string origin EX R1,TVPAREXA locate trailing quote B TVPAR164 TVPAR162 DS 0H handle non quoted string EX R1,TVPAREX3 locate delimiter TVPAR164 DS 0H LR R6,R1 delimiter location SR R1,R5 length of argument BZ TVPAR930 if null, branch CH R1,=Y(L'DSOWNER) greater than max length? BL *+8 no, branch LA R1,L'DSOWNER else force to max length BCTR R1,0 machine relative EX R1,TVPAREXB capture argument * B TVPAR900 SPACE 1 TVPAR900 DS 0H handle continuation if present CLC =C', ',0(R6) continuation to next card? BNE TVPAR010 no, continue this statement, branch SPACE 1 TVPAR910 DS 0H retrieve continued statement GET AWSCNTL retrieve a cntl record LR R3,R1 record location MVC DSMSG+1(7),=C'AWS077I' MVC DSMSG+19(80),0(R3) set statement into message buffer AWSMSG , print function CLI 0(R1),C'*' comment? BE TVPAR910 yes, branch CLC 0(80,R3),CSBLNKS blank line? BE TVPAR910 yes, branch CLI 0(R3),C' ' first byte non blank? BE TVPAR920 yes, branch AWSMSG 078E,'Continuation statement error, 1st byte not blank' LA R15,8 continuation error B TVPARXIT return to caller SPACE 1 TVPAR920 DS 0H setup for continue scan LA R5,1(,R1) current location in scan SLR R1,R1 offset to argument B TVPAR010 continue SPACE 1 TVPAR930 DS 0H keyword with null argument found LA R1,1 position beyond delimiter B TVPAR900 continue SPACE 1 TVPARRC0 DS 0H exit with rc = 0 SLR R15,R15 clear register SPACE 1 TVPARXIT DS 0H function exit AWSEXIT , SPACE 1 TVPAREX1 TRT 0(0,R5),CSPARST1 *** execute only *** TVPAREX2 MVC DSMSG+49(0),0(R4) *** execute only *** TVPAREX3 TRT 0(0,R5),CSPARST2 *** execute only *** TVPAREX4 MVC DSTVOL(0),0(R5) *** execute only *** TVPAREX5 MVC DSHETCMP(0),0(R5) *** execute only *** TVPAREX6 MVC DSHETMTH(0),0(R5) *** execute only *** TVPAREX7 MVC DSHETLVL(0),0(R5) *** execute only *** TVPAREX8 MVC DSHETIDR(0),0(R5) *** execute only *** TVPAREX9 MVC DSHETCSZ(0),0(R5) *** execute only *** TVPAREXA TRT 0(0,R5),CSPARST3 *** execute only *** TVPAREXB MVC DSOWNER(0),0(R5) *** execute only *** SPACE 1 LTORG , DROP , TITLE 'AWSIMPAR - Parse IMPORT verb parameters' *********************************************************************** * AWSIMPAR - Parse IMPORT verb parameters * * msg AWS08n * * * * On entry, r1 = cntl card image containing extract verb. * * On exit, appropriate data areas updated. * *********************************************************************** SPACE 1 AWSIMPAR CSECT , Parse IMPORT verb parameters AWSENTRY , SPACE 1 MVC DSOUTDD,CSBLNKS clear MVC DSINDSN,CSBLNKS MVC DSINFLNC,CSBLNKS MVC DSINFLNO,=H'1' MVI DSUSESL,C' ' MVC DSLODPGM,CSBLNKS SPACE 1 LR R3,R1 cntl statement image LR R5,R1 current location in scan LA R6,6(,R5) point beyond verb SPACE 1 IMPAR010 DS 0H locate a keyword LA R5,1(,R6) end of previous keyword if any LA R1,80(,R3) end of statement SLR R1,R3 length remaining BCTR R1,0 machine relative EX R1,IMPAREX1 locate keyword BZ IMPAR940 if no keyword found, exit LR R4,R1 keyword suffix location LA R5,1(,R1) argument origin IMPAR020 DS 0H locate origin of keyword BCTR R4,0 backup one byte CLI 0(R4),C',' comma delimiter? BE IMPAR030 yes, branch CLI 0(R4),C' ' space delimiter? BE IMPAR030 yes, branch CR R4,R3 origin of statement reached? BH IMPAR020 no, continue search AWSMSG 080E,'AWSGET parameter syntax error' LA R15,8 import parameter syntax error B IMPARXIT return to caller SPACE 1 IMPAR030 DS 0H dispatch keyword handler LA R4,1(,R4) keyword origin CLC =C'OUTDD=',0(R4) OUTDD= keyword? BE IMPAR100 yes, branch CLC =C'INDSN=',0(R4) INDSN= keyword? BE IMPAR110 yes, branch CLC =C'FILENO=',0(R4) FILENO= keyword? BE IMPAR120 yes, branch CLC =C'SL=',0(R4) SL= keyword? BE IMPAR140 yes, branch CLC =C'LOAD=',0(R4) LOAD= keyword? BE IMPAR150 yes, branch MVC DSMSG+1(7),=C'AWS081E' MVC DSMSG+19(29),=C'AWSGET keyword unrecognized:' LR R1,R5 argument origin SLR R1,R4 length of argument BCTR R1,0 machine relative EX R1,IMPAREX2 set keyword into message AWSMSG , write the message LA R15,8 import keyword unrecognized B IMPARXIT return to caller SPACE 1 IMPAR100 DS 0H outdd= keyword handler MVC DSOUTDD,CSBLNKS clear volser LA R1,80(,R3) end of cntl statement SLR R1,R5 length of statement remaining EX R1,IMPAREX3 locate delimiter LR R6,R1 delimiter location SR R1,R5 length of argument BZ IMPAR930 if null, branch CH R1,=Y(L'DSOUTDD) greater than maximum length? BL *+8 no, branch LA R1,L'DSOUTDD else force to max length BCTR R1,0 machine relative EX R1,IMPAREX4 capture B IMPAR900 SPACE 1 IMPAR110 DS 0H indsn= keyword handler MVC DSINDSN,CSBLNKS clear LA R1,80(,R3) end of cntl statement SLR R1,R5 length of statement remaining EX R1,IMPAREX3 locate delimiter LR R6,R1 delimiter location SR R1,R5 length of argument BZ IMPAR930 if null, branch CH R1,=Y(L'DSINDSN) greater than maximum length? BL *+8 no, branch LA R1,L'DSINDSN else force to max length BCTR R1,0 machine relative EX R1,IMPAREX5 capture argument B IMPAR900 SPACE 1 IMPAR120 DS 0H fileno= keyword handler MVC DSINFLNC,CSBLNKS clear MVC DSINFLNO,=H'1' default LA R1,80(,R3) end of cntl statement SLR R1,R5 length of statement remaining EX R1,IMPAREX3 locate delimiter LR R6,R1 delimiter location SR R1,R5 length of argument BZ IMPAR930 if null, branch CH R1,=Y(L'DSINFLNC) greater than maximum length? BL *+8 no, branch LA R1,L'DSINFLNC else force to max length BCTR R1,0 machine relative LR R14,R1 save for future reference EX R1,IMPAREX6 numeric? BZ IMPAR130 yes, branch AWSMSG 082E,'FILENO= Argument is not numeric' LA R15,8 return code B IMPARXIT IMPAR130 DS 0H EX R14,IMPAREX7 pack fileno character argument CVB R0,DSDWORK convert to binary STH R0,DSINFLNO ... AND SAVE B IMPAR900 SPACE 1 IMPAR140 DS 0H SL= keyword handler MVI DSUSESL,C' ' clear LA R1,80(,R3) end of cntl statement SLR R1,R5 length of statement remaining EX R1,IMPAREX3 locate delimiter LR R6,R1 delimiter location SR R1,R5 length of argument BZ IMPAR930 if null, branch CH R1,=Y(L'DSUSESL) greater than maximum length? BL *+8 no, branch LA R1,L'DSUSESL else force to max length BCTR R1,0 machine relative EX R1,IMPAREX8 capture argument SPACE 1 CLI DSUSESL,C' ' default? BE IMPAR900 yes, branch CLI DSUSESL,C'N' sl=no? BE IMPAR900 yes, branch CLI DSUSESL,C'Y' sl=yes? BE IMPAR900 yes, branch AWSMSG 083E,'SL= Argument is invalid' LA R15,8 B IMPARXIT SPACE 1 IMPAR150 DS 0H MVC DSLODPGM,CSBLNKS clear LA R1,80(,R3) end of cntl statement SLR R1,R5 length of statement remaining EX R1,IMPAREX3 locate delimiter LR R6,R1 delimiter location SR R1,R5 length of argument BZ IMPAR930 if null, branch CH R1,=Y(L'DSLODPGM) greater than maximum length? BL *+8 no, branch LA R1,L'DSLODPGM else force to max length BCTR R1,0 machine relative EX R1,IMPAREX9 capture argument * B IMPAR900 SPACE 1 IMPAR900 DS 0H handle continuation if present CLC =C', ',0(R6) continuation to next card? BNE IMPAR010 no, continue this statement, branch SPACE 1 IMPAR910 DS 0H retrieve continued statement GET AWSCNTL retrieve a cntl record LR R3,R1 record location MVC DSMSG+1(7),=C'AWS084I' MVC DSMSG+19(80),0(R3) set statement into message buffer AWSMSG , print function CLI 0(R1),C'*' comment? BE IMPAR910 yes, branch CLC 0(80,R3),CSBLNKS blank line? BE IMPAR910 yes, branch CLI 0(R3),C' ' first byte non blank? BE IMPAR920 yes, branch AWSMSG 085E,'Continuation statement error, 1st byte not blank' LA R15,8 continuation error B IMPARXIT return to caller SPACE 1 IMPAR920 DS 0H setup for continue scan LA R5,1(,R1) current location in scan SLR R1,R1 offset to argument B IMPAR010 continue SPACE 1 IMPAR930 DS 0H keyword with null argument found LA R1,1 position beyond delimiter B IMPAR900 continue SPACE 1 IMPAR940 DS 0H exit with rc = 0 CLI DSOUTDD,C' ' output ddname specified? BH IMPAR950 yes, branch AWSMSG 086E,'AWSGET requires that OUTDD= be specified' LA R15,8 B IMPARXIT SPACE 1 IMPAR950 DS 0H normal return SLR R15,R15 clear register SPACE 1 IMPARXIT DS 0H function exit AWSEXIT , SPACE 1 IMPAREX1 TRT 0(0,R5),CSPARST1 *** execute only *** IMPAREX2 MVC DSMSG+49(0),0(R4) *** execute only *** IMPAREX3 TRT 0(0,R4),CSPARST2 *** execute only *** IMPAREX4 MVC DSOUTDD(0),0(R5) *** execute only *** IMPAREX5 MVC DSINDSN(0),0(R5) *** execute only *** IMPAREX6 TRT 0(0,R5),CSNUMTRT *** execute only *** IMPAREX7 PACK DSDWORK,0(0,R5) *** execute only *** IMPAREX8 MVC DSUSESL(0),0(R5) *** execute only *** IMPAREX9 MVC DSLODPGM(0),0(R5) *** execute only *** SPACE 1 LTORG , DROP , TITLE 'AWSEXPAR - Parse extract verb parameters' *********************************************************************** * AWSEXPAR - Parse extract verb parameters * * msg AWS09n * * * * On entry, r1 = cntl card image containing extract verb. * * On Exit, appropriate data areas updated. * *********************************************************************** SPACE 1 AWSEXPAR CSECT , Parse extract verb parameters AWSENTRY , SPACE 1 MVC DSINDSN,CSBLNKS clear input dsn MVC DSOUTDSN,CSBLNKS clear output dsn MVC DSTDSN,CSBLNKS clear tape dsn MVC DSINDD,CSBLNKS clear input dd name MVC DSUNLPGM,CSBLNKS clear unload program MVC DSUNLTYP,CSBLNKS clear unload type MVI DSUSESL,C' ' clear use standard labels flag SPACE 1 LR R3,R1 cntl statement image LR R5,R1 current location in scan LA R1,7 point beyond verb SPACE 1 EXPAR010 DS 0H locate a keyword ALR R5,R1 end of previous keyword if any LA R1,80(,R3) end of statement SLR R1,R3 length remaining BCTR R1,0 machine relative EX R1,EXPAREX1 locate keyword BZ EXPARRC0 if no keyword found, exit LR R4,R1 keyword suffix location LA R5,1(,R1) argument origin EXPAR020 DS 0H locate origin of keyword BCTR R4,0 backup one byte CLI 0(R4),C',' comma delimiter? BE EXPAR030 yes, branch CLI 0(R4),C' ' space delimiter? BE EXPAR030 yes, branch CR R4,R3 origin of statement reached? BH EXPAR020 no, continue search AWSMSG 090E,'AWSPUT parameter syntax error' LA R15,8 export parameter syntax error B EXPARXIT return to caller SPACE 1 EXPAR030 DS 0H dispatch keyword handler LA R4,1(,R4) keyword origin CLC =C'INDSN=',0(R4) INDSN= keyword? BE EXPAR100 yes, branch CLC =C'OUTDSN=',0(R4) OUTDSN= keyword? BE EXPAR110 yes, branch CLC =C'TAPEDSN=',0(R4) TAPEDSN= keyword? BE EXPAR120 yes, branch CLC =C'INDD=',0(R4) INDD= keyword? BE EXPAR130 yes, branch CLC =C'UNLOAD=',0(R4) UNLOAD= keyword? BE EXPAR140 yes, branch CLC =C'TYPE=',0(R4) TYPE= keyword? BE EXPAR150 yes, branch CLC =C'SL=',0(R4) SL= keyword? BE EXPAR160 yes, branch MVC DSMSG+1(7),=C'AWS091E' MVC DSMSG+19(28),=C'AWSPUT keyword unrecognized:' LR R1,R5 argument origin SLR R1,R4 length of argument BCTR R1,0 machine relative EX R1,EXPAREX2 set keyword into message AWSMSG , write the message LA R15,8 export keyword unrecognized B EXPARXIT return to caller SPACE 1 EXPAR100 DS 0H indsn= keyword handler MVC DSINDSN,CSBLNKS clear dataset name LA R1,80(,R3) end of cntl statement SLR R1,R5 length of statement remaining EX R1,EXPAREX3 locate delimiter LR R6,R1 delimiter location SR R1,R5 length of argument BZ EXPAR930 if null, branch CH R1,=Y(L'DSINDSN) greater than maximum length? BL *+8 no, branch LA R1,L'DSINDSN else force to max length BCTR R1,0 machine relative EX R1,EXPAREX4 capture dsn B EXPAR900 SPACE 1 EXPAR110 DS 0H outdsn= keyword handler MVC DSOUTDSN,CSBLNKS clear out dataset name LA R1,80(,R3) end of cntl statement SLR R1,R5 length of statement remaining EX R1,EXPAREX3 locate delimiter LR R6,R1 delimiter location SR R1,R5 length of argument BZ EXPAR930 if null, branch CH R1,=Y(L'DSOUTDSN) greater than maximum length? BL *+8 no, branch LA R1,L'DSOUTDSN else force to max length BCTR R1,0 machine relative EX R1,EXPAREX5 capture dsn B EXPAR900 SPACE 1 EXPAR120 DS 0H tapedsn= keyword handler MVC DSTDSN,CSBLNKS clear tape dsn LA R1,80(,R3) end of cntl statement SLR R1,R5 length of statement remaining EX R1,EXPAREX3 locate delimiter LR R6,R1 delimiter location SR R1,R5 length of argument BZ EXPAR930 if null, branch CH R1,=Y(L'DSTDSN) greater than maximum length? BL *+8 no, branch LA R1,L'DSTDSN else force to maximum length BCTR R1,0 machine relative EX R1,EXPAREX6 capture dsn B EXPAR900 SPACE 1 EXPAR130 DS 0H INDD= keyword handler MVC DSINDD,CSBLNKS clear input dd name LA R1,80(,R3) end of cntl statement SLR R1,R5 length of statement remaining EX R1,EXPAREX3 locate delimiter LR R6,R1 delimiter location SR R1,R5 length of argument BZ EXPAR930 if null, branch CH R1,=Y(L'DSINDD) maximum length BL *+8 no, branch LA R1,L'DSINDD else force to max length BCTR R1,0 machine relative EX R1,EXPAREX7 capture indd B EXPAR900 SPACE 1 EXPAR140 DS 0H UNLOAD= keyword handler MVC DSUNLPGM,CSBLNKS clear unload program name LA R1,80(,R3) end of cntl statement SLR R1,R5 length of statement remaining EX R1,EXPAREX3 locate delimiter LR R6,R1 delimiter location SR R1,R5 length of argument BZ EXPAR930 if null, branch CH R1,=Y(L'DSUNLPGM) maximum length BL *+8 no, branch LA R1,L'DSUNLPGM else force to max length BCTR R1,0 machine relative EX R1,EXPAREX8 capture unload program B EXPAR900 SPACE 1 EXPAR150 DS 0H TYPE= keyword handler MVC DSUNLTYP,CSBLNKS clear unload type LA R1,80(,R3) end of cntl statement SLR R1,R5 length of statement remaining EX R1,EXPAREX3 locate delimiter LR R6,R1 delimiter location SR R1,R5 length of argument BZ EXPAR930 if null, branch CH R1,=Y(L'DSUNLTYP) maximum length BL *+8 no, branch LA R1,L'DSUNLTYP else force to max length BCTR R1,0 machine relative EX R1,EXPAREX9 capture unload program B EXPAR900 SPACE 1 EXPAR160 DS 0H TYPE= keyword handler MVI DSUNLTYP,C' ' clear use standard labels flag LA R1,80(,R3) end of cntl statement SLR R1,R5 length of statement remaining EX R1,EXPAREX3 locate delimiter LR R6,R1 delimiter location SR R1,R5 length of argument BZ EXPAR170 if null, branch CH R1,=Y(L'DSUSESL) maximum length BL *+8 no, branch LA R1,L'DSUSESL else force to max length BCTR R1,0 machine relative EX R1,EXPAREXA capture SPACE 1 CLI DSUSESL,C' ' default? BE EXPAR170 yes, branch CLI DSUSESL,C'N' sl=no? BE EXPAR170 yes, branch CLI DSUSESL,C'Y' sl=yes? BE EXPAR170 yes, branch AWSMSG 054E,'SL= Argument is invalid' LA R15,8 B EXPARXIT SPACE 1 EXPAR170 DS 0H SPACE 1 EXPAR900 DS 0H handle continuation if present CLC =C', ',0(R6) continuation to next card? BNE EXPAR010 no, continue this statement, branch SPACE 1 EXPAR910 DS 0H retrieve continued statement GET AWSCNTL retrieve a cntl record LR R3,R1 record location MVC DSMSG+1(7),=C'AWS052I' MVC DSMSG+19(80),0(R3) set statement into message buffer AWSMSG , print function CLI 0(R1),C'*' comment? BE EXPAR910 yes, branch CLC 0(80,R3),CSBLNKS blank line? BE EXPAR910 yes, branch CLI 0(R3),C' ' first byte non blank? BE EXPAR920 yes, branch AWSMSG 092E,'Continuation statement error, 1st byte not blank' LA R15,8 continuation error B EXPARXIT return to caller SPACE 1 EXPAR920 DS 0H setup for continue scan LA R5,1(,R1) current location in scan SLR R1,R1 offset to argument B EXPAR010 continue SPACE 1 EXPAR930 DS 0H keyword with null argument found LA R1,1 position beyond delimiter B EXPAR900 continue SPACE 1 EXPARRC0 DS 0H exit with rc = 0 SLR R15,R15 clear register SPACE 1 EXPARXIT DS 0H function exit AWSEXIT , SPACE 1 EXPAREX1 TRT 0(0,R5),CSPARST1 *** execute only *** EXPAREX2 MVC DSMSG+48(0),0(R4) *** execute only *** EXPAREX3 TRT 0(0,R5),CSPARST2 *** execute only *** EXPAREX4 MVC DSINDSN(0),0(R5) *** execute only *** EXPAREX5 MVC DSOUTDSN(0),0(R5) *** execute only *** EXPAREX6 MVC DSTDSN(0),0(R5) *** execute only *** EXPAREX7 MVC DSINDD(0),0(R5) *** execute only *** EXPAREX8 MVC DSUNLPGM(0),0(R5) *** execute only *** EXPAREX9 MVC DSUNLTYP(0),0(R5) *** execute only *** EXPAREXA MVC DSUSESL(0),0(R5) *** execute only *** SPACE 1 LTORG , DROP , TITLE 'AWSJFDSN - Extract input dsn' *********************************************************************** * AWSJFDSN - Extract input dsn * * msg AWS10n * *********************************************************************** SPACE 1 AWSJFDSN CSECT , Extract input dsn AWSENTRY , SPACE 1 CLI DSOUTDSN,C' ' output dsn specified? BH JFDSNXIT yes, exit CLI DSTDSN,C' ' explicit tape dsn specified? BH JFDSNXIT yes, exit SPACE 1 CLI DSINDD,C' ' indd specified? BH JFDSN010 yes, branch MVC DSOUTDSN,DSINDSN else default outdsn to indsn B JFDSNXIT exit SPACE 1 JFDSN010 DS 0H capture outdsn from indd= MVC AWSUT1+(DCBDDNAM-IHADCB)(8),=CL8'AWSUT1' CLI DSINDD,C' ' input dd present? BE *+10 no, use awsut1, branch MVC AWSUT1+(DCBDDNAM-IHADCB)(8),DSINDD SPACE 1 RDJFCB AWSUT1,MF=(E,DSRDJFCB) read the jfcb MVC DSOUTDSN,JFCBDSNM default outdsn to input dsn SPACE 1 JFDSNXIT DS 0H function exit SLR R15,R15 zero return code AWSEXIT , return to caller SPACE 1 LTORG , DROP TITLE 'AWSTPDSN - Set 17 byte tape dsn' *********************************************************************** * AWSTPDSN - Set 17 byte tape dsn * * msg AWS11n * *********************************************************************** SPACE 1 AWSTPDSN CSECT , Set 17 byte tape dsn AWSENTRY , SPACE 1 CLI DSTDSN,C' ' tape dsn explicitly given? BH TPDSNXIT yes, branch SPACE 1 LA R1,DSOUTDSN+L'DSOUTDSN point beyond outdsn TRT DSOUTDSN,CSPARST2 locate end of outdsn LA R2,DSOUTDSN outdsn origin SLR R1,R2 length of outdsn CH R1,=Y(L'DSTDSN) greater than maximum length? BH TPDSN010 yes, branch MVC DSTDSN,DSOUTDSN else default outdsn as is B TPDSNXIT exit SPACE 1 TPDSN010 DS 0H capture right most 17 bytes SH R1,=Y(L'DSTDSN) offset to start of name ALR R2,R1 origin of move MVC DSTDSN,0(R2) capture SPACE 1 TPDSNXIT DS 0H function exit SLR R15,R15 zero return code AWSEXIT , return to caller SPACE 1 LTORG , DROP , TITLE 'AWSJOBNM - Capture job and step name info' *********************************************************************** * AWSJOBNM - Capture job and step name info * * msg AWS12n * *********************************************************************** SPACE 1 AWSJOBNM CSECT , Capture job and step name info AWSENTRY , USING PSA,R0 L R3,PSATOLD current TCB location USING TCB,R3 TCB addressasbility L R4,TCBTIO TIOT location USING TIOT,R4 MVC DSJOBNM,TIOCNJOB set job name MVC DSSTEPNM,TIOCSTEP+8 set step name CLI DSSTEPNM,C' ' blank stepname? BNE JOBNMXIT no, branch MVC DSSTEPNM,TIOCSTEP else try w/o procstep SPACE 1 JOBNMXIT DS 0H function exit SLR R15,R15 zero return code AWSEXIT , return to caller SPACE 1 LTORG , DROP , TITLE 'AWSUNLD - Unload (stage) dataset' *********************************************************************** * AWSUNLD - Unload (stage) dataset * * msg AWS13n * *********************************************************************** SPACE 1 AWSUNLD CSECT , Unload (stage) dataset AWSENTRY , SPACE 1 SLR R15,R15 zero return code CLI DSUNLPGM,C' ' unload requested? BE UNLODXIT no, branch SPACE 1 AWSCALL AWSALCI allocate input dataset BNZ UNLODXIT SPACE 1 AWSCALL AWSALCT allocate work dataset BNZ UNLODXIT SPACE 1 AWSCALL AWSALCS allocate sysin dataset BNZ UNLODXIT SPACE 1 AWSCALL AWSALCP allocate sysprint dataset BNZ UNLODXIT SPACE 1 OPEN (SYSIN,(OUTPUT)),MF=(E,DSOPENL) open sysin for output SPACE 1 TM SYSIN+(DCBOFLGS-IHADCB),DCBOFOPN open ok? BO UNLOD010 yes, branch AWSMSG 130E,'SYSIN open for output failed' LA R15,8 set return code B UNLODXIT SPACE 1 UNLOD010 DS 0H determine type of unload CLC =C'IEBCOPY',DSUNLPGM iebcopy unload? BE UNLOD100 yes, branch CLC =C'IDCAMS',DSUNLPGM idcams export? BE UNLOD200 yes, branch AWSMSG 131E,'Unrecognized unload program specified' LA R15,8 unrecognized unload pgm B UNLODXIT exit SPACE 1 UNLOD100 DS 0H iebcopy unload request MVI DSCARD,C' ' clear card image MVC DSCARD+1(L'DSCARD-1),DSCARD MVC DSCARD(15),=C' C O=AWSTEMP,I=' MVC DSCARD+15(8),DSINDD assume indd= statement present CLI DSINDD,C' ' indd= keyword present? BH UNLOD110 yes, branch MVC DSCARD+15(8),=CL8'AWSUT1' else use default SPACE 1 UNLOD110 DS 0H write control statement PUT SYSIN,DSCARD SPACE 1 CLOSE SYSIN,MF=(E,DSCLOSEL) close file FREEPOOL SYSIN release buffer pool SPACE 1 SLR R1,R1 clear parameter register LINK EP=IEBCOPY invoke iebcopy LTR R15,R15 success? BZ UNLOD120 yes, branch AWSMSG 132E,'IEBCOPY unload failed' LA R15,8 set return code B UNLODXIT exit space 1 UNLOD120 DS 0H Unload via iebcopy successful msg AWSMSG , blank line AWSMSG 133I,'PDS(E) unload successful' B UNLODXIT exit SPACE 1 UNLOD200 DS 0H idcams export AWSMSG 134F,'IDCAMS export not yet supported' LA R15,12 * B UNLODXIT SPACE 1 UNLODXIT DS 0H return to caller AWSEXIT , SPACE 1 LTORG , DROP TITLE 'AWSALCI - Dynamically allocate input' *********************************************************************** * AWSALCI - Dynamically allocate input * * msg AWS14n * *********************************************************************** SPACE 1 AWSALCI CSECT , Dynamically allocate input AWSENTRY , SPACE 1 CLI DSINDD,C' ' input dataset already allocated? BNE ALOCI030 yes, branch SPACE 1 MVC DSADSNMT,DSINDSN input dataset name LA R1,DSARBP input rb pointer SVC 99 input allocation LTR R15,R15 successful? BZ ALOCI020 yes, branch LA R3,DSARB rb location USING S99RB,R3 input rb addressability CH R15,CSH4 rc=4? BNE ALOCI010 no, error, branch CLC S99ERROR,=X'0410' ddname already allocated? BE ALOCI030 yes, branch SPACE 1 ALOCI010 DS 0H allocation error occured LR R1,R3 set rb location LR R0,R15 return code AWSCALL AWSDYNE format dynalloc error messages AWSMSG 140E,'Input dataset dynamic allocation failed' LA R15,8 set return code B ALOCIXIT exit SPACE 1 ALOCI020 DS 0H successful dynamic allocation OI DSFLAGS,DSFDYUT1 awsut1 dynamically allocated SPACE 1 ALOCI030 DS 0H normal return SLR R15,R15 zero return code SPACE 1 ALOCIXIT DS 0H return to caller AWSEXIT , SPACE 1 LTORG , DROP TITLE 'AWSALCT - Dynamically allocate temporary work' *********************************************************************** * AWSALCT - Dynamically allocate temporary work * * msg AWS15n * *********************************************************************** SPACE 1 AWSALCT CSECT , Dynamically allocate temporary work AWSENTRY , SPACE 1 LA R1,DSTARBP temp work rb pointer SVC 99 temp work allocation LTR R15,R15 successful? BZ ALOCT020 yes, branch LA R3,DSTARB rb location USING S99RB,R3 input rb addressability CH R15,CSH4 rc=4? BNE ALOCT010 no, error, branch CLC S99ERROR,=X'0410' ddname already allocated? BE ALOCT030 yes, branch SPACE 1 ALOCT010 DS 0H allocation error occured LR R1,R3 set rb location LR R0,R15 return code AWSCALL AWSDYNE format dynalloc error messages AWSMSG 150E,'Temp work dataset dynamic allocation failed' LA R15,8 set return code B ALOCTXIT exit SPACE 1 ALOCT020 DS 0H successful dynamic allocation OI DSFLAGS,DSFDYTMP awstemp dynamically allocated SPACE 1 ALOCT030 DS 0H normal return SLR R15,R15 zero return code SPACE 1 ALOCTXIT DS 0H return to caller AWSEXIT , SPACE 1 LTORG , DROP TITLE 'AWSALCS - Dynamically allocate sysin' *********************************************************************** * AWSALCS - Dynamically allocate temporary sysin * * msg AWS16n * *********************************************************************** SPACE 1 AWSALCS CSECT , Dynamically allocate temporary work AWSENTRY , SPACE 1 LA R1,DSSARBP temp work rb pointer SVC 99 temp work allocation LTR R15,R15 successful? BZ ALOCS020 yes, branch LA R3,DSSARB rb location USING S99RB,R3 input rb addressability CH R15,CSH4 rc=4? BNE ALOCS010 no, error, branch CLC S99ERROR,=X'0410' ddname already allocated? BE ALOCS030 yes, branch SPACE 1 ALOCS010 DS 0H allocation error occured LR R1,R3 set rb location LR R0,R15 return code AWSCALL AWSDYNE format dynalloc error messages AWSMSG 160E,'SYSIN dataset dynamic allocation failed' LA R15,8 set return code B ALOCSXIT exit SPACE 1 ALOCS020 DS 0H successful dynamic allocation OI DSFLAGS,DSFDYSYI sysin dynamically allocated SPACE 1 ALOCS030 DS 0H normal return SLR R15,R15 zero return code SPACE 1 ALOCSXIT DS 0H return to caller AWSEXIT , SPACE 1 LTORG , DROP TITLE 'AWSALCP - Dynamically allocate sysprint' *********************************************************************** * AWSALCP - Dynamically allocate sysprint * * msg AWS17n * *********************************************************************** SPACE 1 AWSALCP CSECT , Dynamically allocate sysprint AWSENTRY , SPACE 1 LA R1,DSPARBP temp work rb pointer SVC 99 temp work allocation LTR R15,R15 successful? BZ ALOCP020 yes, branch LA R3,DSPARB rb location USING S99RB,R3 input rb addressability CH R15,CSH4 rc=4? BNE ALOCP010 no, error, branch CLC S99ERROR,=X'0410' ddname already allocated? BE ALOCP030 yes, branch SPACE 1 ALOCP010 DS 0H allocation error occured LR R1,R3 set rb location LR R0,R15 return code AWSCALL AWSDYNE format dynalloc error messages AWSMSG 170E,'SYSPRINT dataset dynamic allocation failed' LA R15,8 set return code B ALOCPXIT exit SPACE 1 ALOCP020 DS 0H successful dynamic allocation OI DSFLAGS,DSFDYSYP sysprint dynamically allocated SPACE 1 ALOCP030 DS 0H normal return SLR R15,R15 zero return code SPACE 1 ALOCPXIT DS 0H return to caller AWSEXIT , SPACE 1 LTORG , DROP TITLE 'AWSDYNE - Dyanamic allocation error' *********************************************************************** * AWSDYNE - Dynamic allocation error, on entry r1 = s99rb, r0=rc * * msg AWS18n * *********************************************************************** SPACE 1 AWSDYNE CSECT , Dynamic allocation error AWSENTRY , SPACE 1 LR R3,R1 dynalloc rb location USING S99RB,R3 addressability LR R4,R0 dynalloc return code SPACE 1 MVC DSMSG+1(7),=C'AWS180E' MVC DSMSG+19(54),=C'DYNALLOC FAILURE, RC=XXXX, S99ERROR=XXXX* , S99INFO=XXXX' ST R4,DSFWORK rc UNPK DSHEXWK(9),DSFWORK(5) unpack data TR DSHEXWK,CSHEXTR make printable MVC DSMSG+19+21(4),DSHEXWK+4 return code SPACE 1 UNPK DSHEXWK(5),S99ERROR(3) s99error code TR DSHEXWK,CSHEXTR make printable MVC DSMSG+19+36(4),DSHEXWK SPACE 1 UNPK DSHEXWK(5),S99INFO(3) s99info code TR DSHEXWK,CSHEXTR make printable MVC DSMSG+19+50(4),DSHEXWK SPACE 1 AWSMSG , write the message SPACE 1 CH R4,CSH4 RC = 4? BNE DYNERXIT NO, BRANCH CLC S99ERROR,=X'1708' ERROR = 1708? BNE DYNERXIT NO, BRANCH CLC S99INFO,=X'0002' INFO = 0002? BNE DYNERXIT NO, BRANCH AWSMSG 181E,'Dataset could not be found' SPACE 1 DYNERXIT DS 0H function exit SLR R15,R15 zero return code AWSEXIT , SPACE 1 LTORG , DROP TITLE 'AWSHDR - Header labels' *********************************************************************** * AWSHDR - header labels * * msg AWS19n * *********************************************************************** SPACE 1 AWSHDR CSECT , header labels AWSENTRY , SPACE 1 SLR R15,R15 zero return code for now CLI DSUSESL,C'N' suppress standard labels? BE HDRLBXIT yes, branch TM DSFLAGS,DSFVOLF vol1 written previously? BO HDRLB100 yes, branch L R3,DSBUFTP Next text location USING AWSREC,R3 Addressability MVC AWSLENC,CSH80 block length AWSSWAP , set sizes MVC AWSFLGS,CSXA000 data follows LA R3,6(,R3) position beyond aws cb ST R3,DSBUFTP set current text pointer TM DSFLAGS,DSFRECV variable length output? BZ HDRLB010 no, branch AWSCALL AWSEPUT write the aws cb L R3,DSBUFTP current buffer pointer USING AWSDBLK,R3 data block origin SPACE 1 HDRLB010 DS 0H build vol1 label MVC DSVOL1SR,DSTVOL set volser into label MVC DSVOL1OW,DSOWNER set owner MVC AWSDBLK(80),DSVOL1 VOL1 LABEL LA R3,80(,R3) Next data record origin ST R3,DSBUFTP Set current text pointer TM DSFLAGS,DSFRECV Variable length output? BZ HDRLB100 No, branch AWSCALL AWSEPUT Write the block SPACE 1 HDRLB100 DS 0H HDR1 LABEL L R3,DSBUFTP Next text location USING AWSREC,R3 MVC AWSLENC,CSH80 block length AWSSWAP , set sizes MVC AWSFLGS,CSXA000 data follows MVC DSHDR1SR,DSTVOL volser LA R3,6(,R3) position beyond aws cb ST R3,DSBUFTP set current text pointer TM DSFLAGS,DSFRECV variable length output? BZ HDBLB110 no, branch AWSCALL AWSEPUT write the aws cb L R3,DSBUFTP current buffer pointer USING AWSDBLK,R3 data block origin SPACE 1 HDBLB110 DS 0H build hdr1 LH R1,DSFILECT file sequence number LA R1,1(,R1) ...increment STH R1,DSFILECT ...and save CVD R1,DSDWORK convert to decimal MVC DSXL16(6),=X'F02020202020' edit mask ED DSXL16(6),DSDWORK+5 MVC DSHDR1SQ,DSXL16+2 set file number into HDR1 OI DSHDR1SQ+L'DSHDR1SQ-1,C'0' MVC DSHDR1NM,DSTDSN Set dataset name into label SPACE 1 TIME DEC get todays date ST R1,DSFWORK set into work area MVC DSXL16(8),=X'F020202020202020' edit mask UNPK DSXL16(8),DSFWORK unpack date OI DSXL16+7,C'0' valid last digit MVC DSHDR1CD,DSXL16+2 set into header MVI DSHDR1CD,C'0' assume 2000-2099 for now CLI DSXL16+2,C'0' 1900-1999? BNE *+8 no, branch MVI DSHDR1CD,C' ' else so indicate SPACE 1 MVC AWSDBLK(80),DSHDR1 HDR1 label LA R3,80(,R3) Next data record origin ST R3,DSBUFTP Set current text pointer TM DSFLAGS,DSFRECV Variable length output? BZ HDRLB200 No, branch AWSCALL AWSEPUT Write the block SPACE 1 HDRLB200 DS 0H HDR2 label L R3,DSBUFTP Next text location USING AWSREC,R3 MVC AWSLENC,CSH80 block length AWSSWAP , set sizes MVC AWSFLGS,CSXA000 data follows LA R3,6(,R3) position beyond aws cb ST R3,DSBUFTP new current text pointer TM DSFLAGS,DSFRECV variable length output? BZ HDRLB210 no, branch AWSCALL AWSEPUT write the aws cb L R3,DSBUFTP current buffer pointer USING AWSDBLK,R3 data block SPACE 1 HDRLB210 DS 0H build hdr2 LA R15,AWSUT1 awsut1 DCB location USING IHADCB,R15 addressability MVI DSHDR2RF,C'U' assume recfm=u for now TM DCBRECFM,DCBRECU recfm=u? BO HDRLB220 yes, branch MVI DSHDR2RF,C'F' assume fixed for now TM DCBRECFM,DCBRECF recfm=f? BO HDRLB220 yes, branch MVI DSHDR2RF,C'V' else assume variable EJECT HDRLB220 DS 0H SLR R0,R0 clear register ICM R0,3,DCBBLKSI blocksize CVD R0,DSDWORK convert to decimal MVC DSXL16(6),=X'F02020202020' ED DSXL16(6),DSDWORK+5 MVC DSHDR2BL,DSXL16+1 OI DSHDR2BL+L'DSHDR2BL-1,C'0' SPACE 1 SLR R0,R0 clear register ICM R0,3,DCBLRECL lrecl CVD R0,DSDWORK convert to decimal MVC DSXL16(6),=X'F02020202020' ED DSXL16(6),DSDWORK+5 MVC DSHDR2RL,DSXL16+1 OI DSHDR2RL+L'DSHDR2RL-1,C'0' SPACE 1 MVI DSHDR2CC,C'A' assume asa for now TM DCBRECFM,DCBRECCA asa carriage control? BO HDRLB230 yes, branch MVI DSHDR2CC,C'M' assume machine for now TM DCBRECFM,DCBRECCM machine carriage control? BO HDRLB230 yes, branch MVI DSHDR2CC,C' ' else no carriage control SPACE 1 HDRLB230 DS 0H handle spanned and blocking MVI DSHDR2BA,C'S' assume spanned or standard TM DCBRECFM,DCBRECSB spanned or standard? BO HDRLB240 yes, branch MVI DSHDR2BA,C'B' assume blocked for now TM DCBRECFM,DCBRECBR blocked? BO HDRLB240 yes, branch MVI DSHDR2BA,C' ' else unblocked EJECT HDRLB240 DS 0H MVC DSHDR2JB,DSJOBNM Set job name MVC DSHDR2ST,DSSTEPNM Set step name SPACE 1 SLR R0,R0 clear register ICM R0,3,AWSUT1+(DCBBLKSI-IHADCB) blocksize CVD R0,DSDWORK convert to decimal MVC DSXL16(12),=X'F02120202020202020202020' ED DSXL16(12),DSDWORK+2 edit OI DSXL16+11,C'0' make printable MVC DSHDR2LB,DSXL16+2 set large blocksize SPACE 1 MVC AWSDBLK(80),DSHDR2 HDR2 label LA R3,80(,R3) Next data record origin ST R3,DSBUFTP Set current text pointer TM DSFLAGS,DSFRECV Variable length output? BZ HDRLB250 No, branch AWSCALL AWSEPUT Write the block SPACE 1 HDRLB250 DS 0H Write labels to log AWSMSG , blank line TM DSFLAGS,DSFVOLF volume header already written? BO HDRLB260 yes, branch OI DSFLAGS,DSFVOLF indicate vol1 has been written MVC DSMSG+1(7),=C'AWS190I' MVC DSMSG+19(80),DSVOL1 vol1 label AWSMSG , SPACE 1 HDRLB260 DS 0H log hdr1 and hdr2 MVC DSMSG+1(7),=C'AWS191I' MVC DSMSG+19(80),DSHDR1 hdr1 label AWSMSG , MVC DSMSG+1(7),=C'AWS192I' MVC DSMSG+19(80),DSHDR2 hdr2 label AWSMSG , AWSMSG , blank line SPACE 1 AWSCALL AWSMARK write tape mark SPACE 1 HDRLBXIT DS 0H exit AWSEXIT , SPACE 1 LTORG , DROP TITLE 'AWSTLR - Write trailer labels' *********************************************************************** * AWSTLR - Write trailer labels * * msg AWS20n * *********************************************************************** SPACE 1 AWSTLR CSECT , Write trailer labels AWSENTRY , SPACE 1 CLI DSUSESL,C'N' suppress standard labels? BE TLRLBXIT yes, branch L R3,DSBUFTP current text pointer USING AWSREC,R3 addressability MVC AWSLENC,CSH80 BLOCK LENGTH AWSSWAP , swap byte order, set size MVC AWSFLGS,CSXA000 DATA FOLLOWS LA R3,6(,R3) next output text ST R3,DSBUFTP set current pointer TM DSFLAGS,DSFRECV variable length output? BZ TLRLB010 no, branch AWSCALL AWSEPUT write the aws cb L R3,DSBUFTP current text pointer USING AWSDBLK,R3 ... addressability SPACE 1 TLRLB010 DS 0H eof1 MVC DSEOF1,DSHDR1 COPY HDR1 INTO EOF1 MVC DSEOF1(3),=C'EOF' SPACE 1 MVC DSXL16(12),=X'F02020202020202020202020' ED DSXL16(12),DSBLKCNT OI DSXL16+11,C'0' MVC DSEOF1BL,DSXL16+6 low block count MVC DSEOF1BH,DSXL16+2 high block count MVC AWSDBLK(80),DSEOF1 EOF1 label LA R3,80(,R3) next text pointer ST R3,DSBUFTP ...and save TM DSFLAGS,DSFRECV variable length output? BZ TLRLB200 no, branch AWSCALL AWSEPUT write the output text L R3,DSBUFTP current buffer location USING AWSREC,R3 addressability SPACE 1 TLRLB200 DS 0H TLR2 LABEL MVC AWSLENC,CSH80 BLOCK LENGTH AWSSWAP , swap byte order, set size MVC AWSFLGS,CSXA000 DATA FOLLOWS LA R3,6(,R3) next current text pointer ST R3,DSBUFTP ... make current TM DSFLAGS,DSFRECV variable length output? BZ TLRLB210 no, branch AWSCALL AWSEPUT write aws cb L R3,DSBUFTP current text pointer USING AWSDBLK,R3 ... addressability SPACE 1 TLRLB210 DS 0H label text MVC DSEOF2,DSHDR2 copy hdr2 to eof2 MVC DSEOF2(3),=C'EOF' MVC AWSDBLK(80),DSEOF2 EOF2 label LA R3,80(,R3) current text pointer ST R3,DSBUFTP ... make current TM DSFLAGS,DSFRECV variable length output? BZ TLRLB220 no, branch AWSCALL AWSEPUT write text SPACE 1 TLRLB220 DS 0H AWSMSG , blank line MVC DSMSG+1(7),=C'AWS200I' MVC DSMSG+19(80),DSEOF1 EOF1 LABEL AWSMSG , MVC DSMSG+1(7),=C'AWS201I' MVC DSMSG+19(80),DSEOF2 EOF2 LABEL AWSMSG , AWSMSG , blank line SPACE 1 AWSCALL AWSMARK write tape mark AWSMSG , blank line AWSMSG , SPACE 1 TLRLBXIT DS 0H exit SLR R15,R15 zero return code AWSEXIT , SPACE 1 LTORG , DROP , TITLE 'AWSPRNT - Write to AWSPRINT log' *********************************************************************** * AWSPRNT - Write contents of DSBUF to AWSPRINT log * * msg AWS21n * *********************************************************************** SPACE 1 AWSPRNT CSECT , Print Function AWSENTRY , Function Entry SPACE 1 AP DSLINECT,CSP1 increment line count CP DSLINECT,=P'60' page eject needed? BNH PRINT010 no, branch ZAP DSLINECT,CSP1 AP DSPAGECT,CSP1 increment page count MVC DSPAGE,=X'40202120' page mask ED DSPAGE,DSPAGECT insert page count PUT AWSPRINT,DSHEADER write header PUT AWSPRINT,DSMSG1 double space SPACE 1 MVC DSMSG1+1(22),=C'AWS210I Execution Log' PUT AWSPRINT,DSMSG1 MVI DSMSG1+6,C'1' MVI DSMSG1+10,C'-' fill with dashes MVC DSMSG1+11(L'DSMSG1-11),DSMSG1+10 PUT AWSPRINT,DSMSG1 SPACE 1 PRINT010 DS 0H write user specified line PUT AWSPRINT,DSMSG write record MVC DSMSG,CSBLNKS clear print buffer MVC DSMSG1,CSBLNKS SLR R15,R15 zero return code SPACE 1 AWSEXIT , Return to caller SPACE 1 LTORG , DROP , TITLE 'AWSMARK - Output a tape mark' *********************************************************************** * AWSMARK - Output a tape mark * * msg AWS22n * *********************************************************************** SPACE 1 AWSMARK CSECT , Write a tape mark AWSENTRY , SPACE 1 L R3,DSBUFTP Next text location USING AWSREC,R3 XC AWSLENC,AWSLENC zero block length AWSSWAP , set sizes MVC AWSFLGS,CSX4000 tape mark SPACE 1 LA R3,6(,R3) Next data record origin ST R3,DSBUFTP Set current text pointer TM DSFLAGS,DSFRECV+DSFFLUSH write required? BZ MARK010 No, branch AWSCALL AWSEPUT Write the block SPACE 1 MARK010 DS 0H return AWSMSG 220I,'*** tape mark ***' SLR R15,R15 zero return code AWSEXIT , SPACE 1 LTORG , DROP , TITLE 'AWSEPUT - Write text to AWSFILE output' *********************************************************************** * AWSEPUT - Write output text * * msg AWS23n * *********************************************************************** SPACE 1 AWSEPUT CSECT , AWSENTRY , SPACE 1 LA R3,DSBUFFER output buffer origin TM DSFLAGS,DSFRECV variable length output? BZ EPUT100 no, branch SPACE 1 *********************************************************************** * awsfile output is variable (recfm=v) test... good for debugging. * *********************************************************************** SPACE 1 EPUT010 DS 0H handle variable length output L R4,DSBUFTP end of text SR R4,R3 r4 = length of text BNP EPUT900 if zero, done, branch SLR R2,R2 clear register ICM R2,3,AWSFILE+(DCBLRECL-IHADCB) r2 = awsfile lrecl SH R2,CSH4 allow room for rdw CR R4,R2 text at or exceeds lrecl? BL *+6 no, branch LR R4,R2 else length = lrecl - 4 SPACE 1 LA R2,DSBUFFER buffer origin AL R2,=A(BUFSIZE*2) offset to variable length buffer LA R0,4(,R2) target of move LR R1,R4 length of data to write LR R14,R3 origin of data LR R15,R4 length of source MVCL R0,R14 copy data to variable buffer LA R1,4(,R4) length of variable record STCM R1,3,0(R2) set length into rdw XC 2(2,R2),2(R2) clear rdw flags PUT AWSFILE,(R2) write the record SPACE 1 ALR R3,R4 position at next origin B EPUT010 continue until done EJECT *********************************************************************** * awsfile output is undefined (recfm=u) text... preferred. * *********************************************************************** SPACE 1 EPUT100 DS 0H handle undefined length output TM AWSFILE+(DCBRECFM-IHADCB),DCBRECU recfm=u? BNO EPUT200 no, must be recfm=f, branch SPACE 1 EPUT110 DS 0H L R4,DSBUFTP end of current text SR R4,R3 r4=length of text BNP EPUT900 if zero, done, branch SLR R2,R2 clear register ICM R2,3,AWSFILE+(DCBBLKSI-IHADCB) r2 = awsfile blksize CR R4,R2 text at or exceeds blksize? BL EPUT130 no, branch LR R4,R2 else length = blksize SPACE 1 EPUT120 DS 0H write undefined length record STCM R4,3,AWSFILE+(DCBLRECL-IHADCB) set length into dcb PUT AWSFILE,(R3) write the text SPACE 1 ALR R3,R4 position at next origin B EPUT110 continue writing all possible SPACE 1 EPUT130 DS 0H short undefined block found TM DSFLAGS,DSFFLUSH flush requested? BO EPUT120 else write short block LA R1,DSBUFFER output buffer origin CR R1,R3 wrote from origin? BNL EPUT900 yes, branch LA R0,DSBUFFER target of move LR R1,R4 length of move LR R14,R3 source of move LR R15,R4 length of move MVCL R0,R14 copy short block to buffer origin LA R3,DSBUFFER buffer origin ALR R4,R3 offset to end of short block ST R4,DSBUFTP set new next pointer B EPUTXIT EJECT *********************************************************************** * awsfile output is fixed length (recfm=f) (folded) text... grrr. * *********************************************************************** SPACE 1 EPUT200 DS 0H handle fixed length output L R4,DSBUFTP end of current text SR R4,R3 r4=length of text BNP EPUT900 if zero, done, branch SLR R2,R2 clear register ICM R2,3,AWSFILE+(DCBLRECL-IHADCB) r2 = awsfile lrecl CR R4,R2 text at or exceeds lrecl? BL EPUT220 no, branch LR R4,R2 else length = blksize SPACE 1 EPUT210 DS 0H write undefined length record PUT AWSFILE,(R3) write the text SPACE 1 ALR R3,R4 position at next origin B EPUT200 continue writing all possible SPACE 1 EPUT220 DS 0H short undefined block found TM DSFLAGS,DSFFLUSH flush requested? BO EPUT230 else write short block LA R1,DSBUFFER output buffer origin CR R1,R3 wrote from origin? BNL EPUT900 yes, branch LA R0,DSBUFFER target of move LR R1,R4 length of move LR R14,R3 source of move LR R15,R4 length of move MVCL R0,R14 copy short block to buffer origin LA R3,DSBUFFER buffer origin ALR R4,R3 offset to end of short block ST R4,DSBUFTP set new next pointer B EPUTXIT SPACE 1 EPUT230 DS 0H flush short text LA R2,DSBUFFER target of move AL R2,=A(BUFSIZE*2) offset to variable length buffer LR R0,R2 target of move SLR R1,R1 clear high order nibbles ICM R1,3,AWSFILE+(DCBLRECL-IHADCB) length of target LR R14,R3 source of move LR R15,R4 length of source ICM R15,8,=X'20' padding required by VTT2TAPE MVCL R0,R14 copy and pad with nulls short text PUT AWSFILE,(R2) write short text LR R0,R2 buffer location SLR R1,R1 clear high order nibbles ICM R1,3,AWSFILE+(DCBLRECL-IHADCB) length of target SLR R15,R15 zero length source ICM R15,8,=X'20' padding required b y vtt2tape MVCL R0,R14 propogate through entire record PUT AWSFILE,(R2) SPACE 1 EPUT900 DS 0H all data has been written LA R0,DSBUFFER buffer origin ST R0,DSBUFTP set current text pointer SPACE 1 EPUTXIT DS 0H return NI DSFLAGS,255-DSFFLUSH reset forced flush flag SLR R15,R15 zero return code AWSEXIT , SPACE 1 LTORG , DROP TITLE 'AWSICOPY - copy from aws input' *********************************************************************** * AWSICOPY - copy from aws input dataset (awsfile) * * msg AWS24n * *********************************************************************** SPACE 1 AWSICOPY CSECT , copy from aws input dataset AWSENTRY , SPACE 1 ZAP DSIBLKCT,=P'0' ZERO BLOCK COUNT ZAP DSIRECCT,=P'0' ... AND RECORD COUNT SPACE 1 LA R5,AWSUT3 input dcb location USING IHADCB,R5 addressability MVC DCBDDNAM,DSOUTDD set ddname SLR R0,R0 clear register STCM R0,3,DCBLRECL clear previous lrecl STCM R0,3,DCBBLKSI clear previous blksize SPACE 1 CLI DSRECFM+1,C'S' spanned records? BE ICOPY010 yes, branch CLC =C'IEBCOPY',DSLODPGM iebcopy load? BE ICOPY010 yes, branch RDJFCB AWSUT3,MF=(E,DSRDJFCB) read the jfcb SPACE 1 ICM R0,3,JFCLRECL lrecl specified in jcl? BZ *+8 no, branch STCM R0,3,DCBLRECL else set into dcb SPACE 1 ICM R0,3,JFCBLKSI blksize specified in jcl? BZ *+8 no, branch STCM R0,3,DCBBLKSI else set into dcb SPACE 1 ICOPY010 DS 0H default from label if needed ICM R0,3,DCBLRECL lrecl specified? BNZ *+10 no, branch MVC DCBLRECL,DSLRECL else default from tape label SPACE 1 ICM R0,3,DCBBLKSI blocksize specified? BNZ *+10 no, branch MVC DCBBLKSI,DSBLKSIZ else default from tape label SPACE 1 OI DCBRECFM,DCBRECU assume undefined for now CLI DSRECFM,C' ' recfm specified? BNH ICOPY020 no, branch CLI DSRECFM,C'U' label undefined? BE ICOPY020 yes, branch NI DCBRECFM,255-DCBRECU reset bits OI DCBRECFM,DCBRECF assume fixed for now CLI DSRECFM,C'F' label fixed? BE ICOPY020 yes, branch NI DCBRECFM,255-DCBRECU reset bits OI DCBRECFM,DCBRECV else must be variable SPACE 1 ICOPY020 DS 0H set blocked attribute CLI DSRECFM+1,C' ' blocked specified? BNH ICOPY030 no, branch CLI DSRECFM+1,C'B' blocked records? BNE *+8 no, branch OI DCBRECFM,DCBRECBR else so indicate SPACE 1 CLI DSRECFM+1,C'S' spanned records? BNE *+8 no, branch OI DCBRECFM,DCBRECSB else so indicate SPACE 1 ICOPY030 DS 0H allocate files if needed CLI DSLODPGM,C' ' load program specified? BNH ICOPY070 no, branch MVC DCBDDNAM,=CL8'AWSTEMP' temporary file SPACE 1 AWSCALL AWSALCI allocate input dataset BNZ ICOPYXIT SPACE 1 AWSCALL AWSALCT allocate work dataset BNZ ICOPYXIT SPACE 1 AWSCALL AWSALCS allocate sysin dataset BNZ ICOPYXIT SPACE 1 AWSCALL AWSALCP allocate sysprint dataset BNZ ICOPYXIT SPACE 1 OPEN (SYSIN,(OUTPUT)),MF=(E,DSOPENL) open sysin for output SPACE 1 TM SYSIN+(DCBOFLGS-IHADCB),DCBOFOPN open ok? BO ICOPY040 yes, branch AWSMSG 241E,'SYSIN open for output failed' LA R15,8 set return code B ICOPYXIT SPACE 1 ICOPY040 DS 0H determine type of unload CLC =C'IEBCOPY',DSLODPGM iebcopy unload? BE ICOPY050 yes, branch AWSMSG 242E,'Unrecognized load program specified' LA R15,8 unrecognized unload pgm B ICOPYXIT exit SPACE 1 ICOPY050 DS 0H iebcopy load request MVC DSCARD,CSBLNKS clear MVC DSCARD(15),=C' C I=AWSTEMP,O=' MVC DSCARD+15(8),DSOUTDD set OUTDD statement CLI DSOUTDD,C' ' outdd= keyword present? BH ICOPY060 yes, branch MVC DSCARD+15(8),=CL8'AWSUT1' else use default SPACE 1 ICOPY060 DS 0H write control statement PUT SYSIN,DSCARD SPACE 1 CLOSE SYSIN,MF=(E,DSCLOSEL) close file FREEPOOL SYSIN release buffer pool SPACE 1 ICOPY070 DS 0H open files RDJFCB AWSUT3,MF=(E,DSRDJFCB) read the jfcb SPACE 1 AWSMSG , blank line MVC DSMSG+1(7),=C'AWS240I' MVC DSMSG+19(31),=C'Writing to dataset :' MVC DSMSG+51(44),JFCBDSNM AWSMSG , SPACE 1 TM DCBRECFM,DCBRECSB spanned blocks? panned b BZ ICOPY090 no, branch CLC =C'IEBCOPY',DSLODPGM iebcopy load? BE ICOPY080 yes, bypass warning, branch AWSMSG , AWSMSG 24BW,'*** Warning, spanned formats not supported, force* d to recfm=u' AWSMSG 24CI,'*** Note that IEBCOPY can process unloaded PDS as* recfm=u' AWSMSG , ICOPY080 DS 0H spanned, force to RECFM=U OI DCBRECFM,DCBRECU indciate undefined lrecl NI DCBRECFM,255-DCBRECSB reset spanned indicator SPACE 1 ICOPY090 DS 0H OPEN (AWSUT3,(OUTPUT)),MF=(E,DSOPENL) TM DCBOFLGS,DCBOFOPN open successful? BO ICOPY100 yes, branch AWSMSG 243E,'Open output file for import failed' LA R15,8 return code B ICOPYXIT exit SPACE 1 ICOPY100 DS 0H produce messages SLR R0,R0 clear register ICM R0,3,DCBLRECL load blocksize CVD R0,DSDWORK convert to decimal MVC DSXL16(6),=X'F02020202120' ED DSXL16(6),DSDWORK+5 edit MVI DSXL16+5,C'0' make printable MVC DSMSG+1(7),=C'AWS244I' MVC DSMSG+19(31),=C'Output dataset lrecl :' MVC DSMSG+51(5),DSXL16+1 set blksize into message AWSMSG , write message SPACE 1 SLR R0,R0 clear register ICM R0,3,DCBBLKSI load blocksize CVD R0,DSDWORK convert to decimal MVC DSXL16(6),=X'F02020202120' ED DSXL16(6),DSDWORK+5 edit MVI DSXL16+5,C'0' make printable MVC DSMSG+1(7),=C'AWS245I' MVC DSMSG+19(31),=C'Output dataset blksize :' MVC DSMSG+51(5),DSXL16+1 set blksize into message AWSMSG , write message SPACE 1 MVC DSMSG+1(7),=C'AWS246I' MVC DSMSG+19(31),=C'Output dataset recfm :' NI DSFLAGS,255-DSFRECV reset variable length flag MVI DSMSG+51,C'U' assume recfm=u for now TM DCBRECFM,DCBRECU recfm=u? BO ICOPY110 yes, branch MVI DSMSG+51,C'F' assume fixed for now TM DCBRECFM,DCBRECF recfm=f? BO ICOPY110 yes, branch MVI DSMSG+51,C'V' else assume variable OI DSFLAGS,DSFRECV set variable length flag ICOPY110 DS 0H MVI DSMSG+53,C'A' assume asa for now TM DCBRECFM,DCBRECCA asa carriage control? BO ICOPY120 yes, branch MVI DSMSG+53,C'M' assume machine for now TM DCBRECFM,DCBRECCM machine carriage control? BO ICOPY120 yes, branch MVI DSMSG+53,C' ' else no carriage control SPACE 1 ICOPY120 DS 0H handle spanned and blocking MVI DSMSG+52,C'S' assume spanned or standard TM DCBRECFM,DCBRECSB spanned or standard? BO ICOPY130 yes, branch MVI DSMSG+52,C'B' assume blocked for now TM DCBRECFM,DCBRECBR blocked? BO ICOPY130 yes, branch MVI DSMSG+52,C' ' else unblocked SPACE 1 ICOPY130 DS 0H produce recfm message CLI DSMSG+52,C' ' not blocked or spanned? BNE ICOPY140 no, branch MVC DSMSG+52(1),DSMSG+53 MVI DSMSG+53,C' ' ICOPY140 DS 0H write recfm AWSMSG , write message SPACE 1 ICOPY150 DS 0H copy aws input text to output file AWSCALL AWSIGET retrieve a block BNZ ICOPYEOF if eof, branch L R3,DSBUFTP block location CLC CSX4000,4(R3) tape mark read? BE ICOPYE10 yes, simulate eof, branch AP DSIBLKCT,=P'1' increment block count SLR R4,R4 clear register ICM R4,3,0(R3) size of aws block lr r14,r4 future reference ALR R4,R3 end of aws block LA R3,6(,R3) position beyond aws header TM DSFLAGS,DSFRECV variable length records? BZ ICOPY160 no, branch SLR R4,R4 clear register ICM R4,3,0(R3) block length from rdw ALR R4,R3 end of block LA R3,4(,R3) position beyond block rdw SPACE 1 ICOPY160 DS 0H copy logical records to output CLR R3,R4 reached end of block? BNL ICOPY150 yes, do next one, branch TM DCBRECFM,DCBRECU undefined output? BNO *+8 no, branch STCM R14,3,DCBLRECL else set lrecl PUT AWSUT3,(R3) else write logical record AP DSIRECCT,=P'1' increment record count TM DSFLAGS,DSFRECV variable length records? BO ICOPY170 yes, branch AH R3,DCBLRECL position at next logical block B ICOPY160 continue SPACE 1 ICOPY170 DS 0H position at next variable length rec SLR R0,R0 clear register ICM R0,3,0(R3) record length ALR R3,R0 origin of next record B ICOPY160 continue SPACE 1 ICOPYEOF DS 0H eof reached? CH R15,=H'-4' eof? BNE ICOPYXIT no, error, branch SPACE 1 ICOPYE10 DS 0H logical eof detected CLOSE AWSUT3,MF=(E,DSCLOSEL) close file FREEPOOL AWSUT3 release buffers SPACE 1 AWSMSG , blank line MVC DSXL16,=X'40202020202020202020202020202120' ED DSXL16,DSIBLKCT edit record count OI DSXL16+15,C'0' make last digit printable MVC DSMSG+1(7),=C'AWS247I' message id MVC DSMSG+19(31),=C'Total physical aws blocks read:' MVC DSMSG+51(16),DSXL16 set count into message AWSMSG , SPACE 1 MVC DSXL16,=X'40202020202020202020202020202120' ED DSXL16,DSIRECCT edit record count OI DSXL16+15,C'0' make last digit printable MVC DSMSG+1(7),=C'AWS248I' message id MVC DSMSG+19(31),=C'Total logical records written :' MVC DSMSG+51(16),DSXL16 set count into message AWSMSG , SPACE 1 *********************************************************************** 00010000 * iebcopy * 00020000 *********************************************************************** 00030000 CLI DSLODPGM,C' ' load program specified? BNH ICOPYX00 no, branch SPACE 1 AWSMSG , blank line MVC DCBDDNAM,DSOUTDD output ddname RDJFCB AWSUT3,MF=(E,DSRDJFCB) read the jfcb MVC DSMSG+1(7),=C'AWS240I' MVC DSMSG+19(31),=C'PDS(E) loading to dataset :' MVC DSMSG+51(44),JFCBDSNM AWSMSG , SPACE 1 SLR R1,R1 clear parameter register LINK EP=IEBCOPY invoke iebcopy LTR R15,R15 success? BZ ICOPYE90 yes, branch AWSMSG 24AE,'IEBCOPY unload failed' LA R15,8 set return code B ICOPYXIT exit SPACE 1 ICOPYE90 DS 0H unallocate if needed AWSMSG 249I,'PDS(E) load successful' AWSCALL AWSUNALC dynamic unallocation SPACE 1 ICOPYX00 DS 0H AWSMSG , blank line SLR R15,R15 zero return code SPACE 1 ICOPYXIT DS 0H return AWSEXIT , SPACE 1 LTORG , DROP TITLE 'AWSECOPY - copy to aws output' *********************************************************************** * AWSECOPY - copy to aws output dataset (awsfile) * * msg AWS25n * *********************************************************************** SPACE 1 AWSECOPY CSECT , copy to aws output dataset AWSENTRY , SPACE 1 ZAP DSBLKCNT,=P'0' clear block counter SPACE 1 MVC AWSUT1+(DCBDDNAM-IHADCB)(L'DCBDDNAM),=CL8'AWSTEMP' CLI DSUNLPGM,C' ' unload requested? BH ECOPY010 yes, use awstemp, branch MVC AWSUT1+(DCBDDNAM-IHADCB)(L'DCBDDNAM),DSINDD CLI DSINDD,C' ' dataset already allocated? BH ECOPY010 yes, use indd argument, branch MVC AWSUT1+(DCBDDNAM-IHADCB)(L'DCBDDNAM),=CL8'AWSUT1' AWSCALL AWSALCI else allocate input dataset BNZ ECOPYXIT if error, branch SPACE 1 ECOPY010 DS 0H dataset is allocated, now open it LA R0,ECOPYEOF eof location STCM R0,7,AWSUT1+(DCBEODA-IHADCB) SLR R0,R0 clear register STH R0,AWSUT1+(DCBBLKSI-IHADCB) clear blocksize STH R0,AWSUT1+(DCBLRECL-IHADCB) clear lrecl OPEN (AWSUT1,(INPUT)),MF=(E,DSOPENL) open input dataset TM AWSUT1+(DCBOFLGS-IHADCB),DCBOFOPN opened ok? BO ECOPY020 yes, branch AWSMSG 250E,'Input dataset could not be opened' LA R15,8 return code B ECOPYXIT return ECOPY020 DS 0H write header labels AWSCALL AWSHDR write header labels BNZ ECOPYXIT SPACE 1 CLOSE AWSUT1,MF=(E,DSCLOSEL) close the file OI AWSUT1+(DCBRECFM-IHADCB),DCBRECU force to recfm=u OPEN (AWSUT1,(INPUT)),MF=(E,DSOPENL) reopen TM AWSUT1+(DCBOFLGS-IHADCB),DCBOFOPN opened ok? BO ECOPY030 yes, branch AWSMSG 251E,'Input dataset could not be re-opened' LA R15,8 return code B ECOPYXIT return SPACE 1 ECOPY030 DS 0H copy input dataset L R3,DSBUFTP current text pointer USING AWSREC,R3 addressability SPACE 1 GET AWSUT1 retrieve a block LR R4,R1 save location for future reference AP DSBLKCNT,CSP1 increment block count SLR R2,R2 clear register ICM R2,3,AWSUT1+(DCBLRECL-IHADCB) get block length STH R2,AWSLENC data block length AWSSWAP , set size and swap bytes MVC AWSFLGS,CSXA000 DATA FOLLOWS LA R3,6(,R3) point beyond aws cb ST R3,DSBUFTP ... make it so SPACE 1 TM DSFLAGS,DSFRECV variable length output? BZ ECOPY040 no, branch AWSCALL AWSEPUT else write variable output L R3,DSBUFTP new current text pointer USING AWSDBLK,R3 data block addressability SPACE 1 ECOPY040 DS 0H copy block into output buffer LR R0,R3 target of move LR R1,R2 target length LR R14,R4 source of move LR R15,R2 source length MVCL R0,R14 copy block into text buffer SPACE 1 ALR R3,R2 new current text pointer ST R3,DSBUFTP ... make it so SPACE 1 LA R0,DSBUFFER buffer origin AL R0,=A(BUFSIZE) r0 = origin of 2nd buffer CR R3,R0 text has extended into 2nd buffer? BL ECOPY050 no, branch AWSCALL AWSEPUT else write block immediately B ECOPY030 process next block SPACE 1 ECOPY050 DS 0H handle variable case if appropriate TM DSFLAGS,DSFRECV variable length output? BZ ECOPY030 no, process next block, branch AWSCALL AWSEPUT write the block now B ECOPY030 process next block EJECT ECOPYEOF DS 0H awsut1 reached eof MVC DSMSG+1(7),=C'AWS252I' blocks copied message MVC DSMSG+19(35),=c'Blocks exported into AWS tape file:' MVC DSMSG+54(12),=X'402020202020202020202120' ED DSMSG+54(12),DSBLKCNT set count into message OI DSMSG+65,C'0' AWSMSG , write the message SPACE 1 CLOSE AWSUT1,MF=(E,DSCLOSEL) close input file FREEPOOL AWSUT1 release buffers SPACE 1 NI AWSUT1+(DCBRECFM-IHADCB),255-DCBRECU clear recfm SLR R0,R0 clear register STH R0,AWSUT1+(DCBBLKSI-IHADCB) clear blocksize STH R0,AWSUT1+(DCBLRECL-IHADCB) clear lrecl SPACE 1 SLR R15,R15 zero return code SPACE 1 ECOPYXIT DS 0H exit AWSEXIT , return to caller SPACE 1 LTORG , DROP , TITLE 'AWSUNALC - Unallocate files' *********************************************************************** * AWSUNALC - Unallocate files * * msg AWS26n * *********************************************************************** SPACE 1 AWSUNALC CSECT , Unallocate files AWSENTRY , SPACE 1 TM DSFLAGS,DSFDYUT1 awsut1 dynamically allocated? BZ UNALC010 no, branch MVC DSUDDNM1,=CL8'AWSUT1' LA R1,DSURBP SVC 99 release awsut1 LTR R15,R15 ok? BZ UNALC010 yes, branch LA R3,DSURB rb location USING S99RB,R3 input rb addressability LR R1,R3 set rb location LR R0,R15 return code AWSCALL AWSDYNE format dynalloc error messages AWSMSG 260E,'Unallocation of ddname AWSUT1 failed' LA R15,8 set return code B UNALCXIT exit SPACE 1 UNALC010 DS 0H unallocate awstemp TM DSFLAGS,DSFDYTMP awstemp dynamically allocated? BZ UNALC020 no, branch MVC DSUDDNM1,=CL8'AWSTEMP' LA R1,DSURBP SVC 99 release awstemp LTR R15,R15 ok? BZ UNALC020 yes, branch LA R3,DSURB rb location USING S99RB,R3 input rb addressability LR R1,R3 set rb location LR R0,R15 return code AWSCALL AWSDYNE format dynalloc error messages AWSMSG 261E,'Unallocation of ddname AWSTEMP failed' LA R15,8 set return code B UNALCXIT exit SPACE 1 UNALC020 DS 0H unallocate sysin TM DSFLAGS,DSFDYSYI sysinp dynamically allocated? BZ UNALC030 no, branch MVC DSUDDNM1,=CL8'SYSIN' LA R1,DSURBP SVC 99 release sysin LTR R15,R15 ok? BZ UNALC030 yes, branch LA R3,DSURB rb location USING S99RB,R3 input rb addressability LR R1,R3 set rb location LR R0,R15 return code AWSCALL AWSDYNE format dynalloc error messages AWSMSG 262E,'Unallocation of ddname AWSTEMP failed' LA R15,8 set return code B UNALCXIT exit SPACE 1 UNALC030 DS 0H unallocate sysprint TM DSFLAGS,DSFDYSYP sysinp dynamically allocated? BZ UNALC040 no, branch MVC DSUDDNM1,=CL8'SYSPRINT' LA R1,DSURBP SVC 99 release sysin LTR R15,R15 ok? BZ UNALC040 yes, branch LA R3,DSURB rb location USING S99RB,R3 input rb addressability LR R1,R3 set rb location LR R0,R15 return code AWSCALL AWSDYNE format dynalloc error messages AWSMSG 263E,'UNALLOCATION of ddname SYSPRINT failed' LA R15,8 set return code B UNALCXIT exit SPACE 1 UNALC040 DS 0H successful NI DSFLAGS,255-DSFDYUT1-DSFDYTMP-DSFDYSYI-DSFDYSYP SLR R15,R15 zero return code SPACE 1 UNALCXIT DS 0H exit AWSEXIT , SPACE 1 LTORG , DROP , TITLE 'AWSSKPTF - skip to file' *********************************************************************** * AWSSKPTF - skip to file * * msg AWS27n * *********************************************************************** SPACE 1 AWSSKPTF CSECT , skip to file AWSENTRY , SPACE 1 LH R3,DSINFLNO file number requested CLI DSUSESL,C'N' standard labels in use? BE SKPTF010 no, branch MH R3,=H'3' multiply by 3 (hdr + data + tlr) SH R3,=H'2' header absolute file number SPACE 1 SKPTF010 DS 0H position to absolute file number SLR R2,R2 tape marks encountered BCTR R3,0 tape marks needed relative to zero SPACE 1 SKPTF020 DS 0H check position CLR R2,R3 desired tapemark? BE SKPTF900 yes, exit SPACE 1 SKPTF030 DS 0H find next tape mark AWSCALL AWSIGET get a block BNZ SKPTF040 if error, branch L R4,DSBUFTP block location USING AWSREC,R4 addressability CLC AWSFLGS,CSX4000 tape mark? BNE SKPTF030 no, continue LA R2,1(,R2) increment tape marks found B SKPTF020 continue SPACE 1 SKPTF040 DS 0H error handler CH R15,=H'-4' eof reached? BNE SKPTFXIT no, error, branch AWSMSG 270E,'End of tape reached while positioning' LA R15,8 B SKPTFXIT SPACE 1 SKPTF900 DS 0H good return SLR R15,R15 zero return code SPACE 1 SKPTFXIT DS 0H exit AWSEXIT , SPACE 1 LTORG , DROP , TITLE 'AWSIMLBL - get label values' *********************************************************************** * AWSIMLBL - get label values * * msg AWS28n, AWS29n, AWS30n * *********************************************************************** SPACE 1 AWSIMLBL CSECT , process input labels AWSENTRY , SPACE 1 CLI DSUSESL,C'N' standard labels expected? BE ILBL900 no, branch SPACE 1 TM DSFLAGS,DSFVOLF vol1 encountered previously? BO ILBL100 yes, branch OI DSFLAGS,DSFVOLF else indicate vol1 checked AWSCALL AWSIGET get a block BNZ ILBLXIT L R3,DSBUFTP current text pointer USING AWSREC,R3 addressability SPACE 1 ILBL010 DS 0H check vol1 if present CLC AWSFLGS,CSXA000 correct flags? BE ILBL030 yes, branch CLC AWSFLGS,CSX4000 end of tape? BNE ILBL020 no, branch AWSMSG 280E,'End of tape reached while positioning' LA R15,8 B ILBLXIT ILBL020 DS 0H AWSMSG 281E,'AWSFLGS unexpected value encountered' LA R15,8 B ILBLXIT SPACE 1 ILBL030 DS 0H check vol1 length CLC =C'HDR1',6(R3) hdr1 found? BE ILBL110 yes, branch SLR R0,R0 clear register ICM R0,3,AWSLENC current block length CH R0,=H'80' 80 bytes? BE ILBL040 yes, branch AWSMSG 282E,'VOL1 label record length is other than 80 bytes' LA R15,8 B ILBLXIT SPACE 1 ILBL040 DS 0H validate vol1 LA R3,6(,R3) position at data block CLC =C'VOL1',0(R3) vol1 label? BE ILBL050 yes, branch AWSMSG 283E,'VOL1 label not found' LA R15,8 B ILBLXIT SPACE 1 ILBL050 DS 0H verify volser SPACE 1 CLC DSTVOL,DSVOL1SR-DSVOL1(R3) volser correct? BE ILBL100 yes, branch AWSMSG 285E,'Incorrect volume serial number encountered' LA R15,8 B ILBLXIT SPACE 1 ILBL100 DS 0H validate hdr1 values AWSCALL AWSIGET get a block BNZ ILBLXIT L R3,DSBUFTP current text pointer CLC AWSFLGS,CSXA000 correct flags? BE ILBL110 yes, branch AWSMSG 286E,'HDR1 AWSFLGS invalid' LA R15,8 B ILBLXIT SPACE 1 ILBL110 DS 0H check lengths SLR R0,R0 clear register ICM R0,3,AWSLENC length of current block CH R0,=H'80' 80 byte block? BE ILBL120 yes, branch AWSMSG 287E,'HDR1 length is other than 80 bytes' LA R15,8 B ILBLXIT exit SPACE 1 ILBL120 DS 0H perform hdr1 checks LA R3,6(,R3) position beyond aws control block CLC =C'HDR1',0(R3) HDR1 label? BE ILBL130 yes, branch SH R3,=H'6' backup six bytes CLC =C'VOL1',6(R3) VOL1 label? BE ILBL030 yes, branch AWSMSG 288E,'HDR1 label not found' LA R15,8 B ILBLXIT SPACE 1 ILBL130 DS 0H process HDR1 values MVC DSMSG+1(7),=C'AWS284I' MVC DSMSG+19(31),=C'AWS HDR1 volume serial number :' MVC DSMSG+51(6),DSHDR1SR-DSHDR1(R3) AWSMSG , SPACE 1 PACK DSDWORK,DSHDR1SQ-DSHDR1(4,R3) CVB R0,DSDWORK convert seq to binary CH R0,DSINFLNO agrees with file number requested? BE ILBL140 yes, branch AWSMSG 289E,'HDR1 file number disagrees with that expected' LA R15,8 B ILBLXIT SPACE 1 ILBL140 DS 0H validate dataset name MVC DSTDSN,CSBLNKS clear MVC DSOUTDSN,DSINDSN AWSCALL AWSTPDSN set 17 byte dsn expected MVC DSMSG+1(7),=C'AWS290I' MVC DSMSG+19(31),=C'Requested 44 byte dataset name:' MVC DSMSG+51(44),DSINDSN AWSMSG , SPACE 1 MVC DSMSG+1(7),=C'AWS291I' MVC DSMSG+19(31),=C'AWS HDR1 17 byte dataset name:' MVC DSMSG+51(17),DSHDR1NM-DSHDR1(R3) AWSMSG , SPACE 1 CLC DSTDSN,DSHDR1NM-DSHDR1(R3) tape dsn correct? BE ILBL150 yes, branch CLC DSTDSN,CSBLNKS input dsn omitted? BE ILBL150 yes, branch AWSMSG 292E,'HDR1 dataset name disagrees with that specified' LA R15,8 B ILBLXIT SPACE 1 ILBL150 DS 0H capture number blocks expected MVC DSXL16(4),=4C'0' fill with zeros MVC DSXL16+4(6),DSHDR1BL-DSHDR1(R3) low block count CLI DSHDR1BH-DSHDR1(R3),C'0' high block count specified? BL *+10 no, branch MVC DSXL16(4),DSHDR1BH-DSHDR1(R3) PACK DSDWORK,DSXL16(10) pack block count CVB R0,DSDWORK total block count ST R0,DSBLKCTI save for future reference SPACE 1 ILBL200 DS 0H process hdr2 AWSCALL AWSIGET get a block BNZ ILBLXIT L R3,DSBUFTP block location CLC AWSFLGS,CSXA000 correct flags? BE ILBL210 yes, branch AWSMSG 293E,'AWSFLGS is other than expected value' LA R15,8 B ILBLXIT SPACE 1 ILBL210 DS 0H check hdr2 length SLR R0,R0 clear register ICM R0,3,AWSLENC length of current block CH R0,=H'80' 80 bytes? BE ILBL220 yes, branch AWSMSG 294E,'HDR2 record length other than 80 bytes' LA R15,8 B ILBLXIT SPACE 1 ILBL220 DS 0H validate hdr2 label LA R3,6(,R3) position at data record CLC =C'HDR2',0(R3) hdr2 label? BE ILBL230 yes, branch AWSMSG 295E,'HDR2 label not found' LA R15,8 B ILBLXIT SPACE 1 ILBL230 DS 0H gather hdr2 values MVC DSRECFM(1),DSHDR2RF-DSHDR2(R3) recfm MVC DSRECFM+1(1),DSHDR2BA-DSHDR2(R3) block attribute MVC DSASA,DSHDR2CC-DSHDR2(R3) carriage control PACK DSDWORK,DSHDR2BL-DSHDR2(L'DSHDR2BL,R3) block size CVB R0,DSDWORK ... convert to binary STCM R0,3,DSBLKSIZ ... and save PACK DSDWORK,DSHDR2RL-DSHDR2(L'DSHDR2RL,R3) lrecl CVB R0,DSDWORK ... convert to binary STCM R0,3,DSLRECL ... and save CVD R0,DSDWORK convert to decimal MVC DSXL16(6),=X'F02020202120' ED DSXL16(6),DSDWORK+5 edit MVI DSXL16+5,C'0' make printable MVC DSMSG+1(7),=C'AWS296I' MVC DSMSG+19(31),=C'AWS HDR2 tape dataset lrecl :' MVC DSMSG+51(5),DSXL16+1 set lrecl into message AWSMSG , write message SPACE 1 TRT DSHDR2LB-DSHDR2(L'DSHDR2LB,R3),CSNUMTRT lb numeric? BNZ ILBL240 no, branch PACK DSDWORK,DSHDR2LB-DSHDR2(L'DSHDR2LB,R3) large blocksize CVB R0,DSDWORK convert to binary LTR R0,R0 specified? BZ ILBL240 no, branch STCM R0,3,DSBLKSIZ else save as blocksize SPACE 1 ILBL240 DS 0H write messages SLR R0,R0 clear register ICM R0,3,DSBLKSIZ load blocksize CVD R0,DSDWORK convert to decimal MVC DSXL16(6),=X'F02020202120' ED DSXL16(6),DSDWORK+5 edit MVI DSXL16+5,C'0' make printable MVC DSMSG+1(7),=C'AWS297I' MVC DSMSG+19(31),=C'AWS HDR2 tape dataset blksize :' MVC DSMSG+51(5),DSXL16+1 set blksize into message AWSMSG , write message SPACE 1 MVC DSMSG+1(7),=C'AWS298I' MVC DSMSG+19(31),=C'AWS HDR2 tape dataset recfm :' MVC DSMSG+51(2),DSRECFM AWSMSG , write message SPACE 1 ILBL250 DS 0H prepare for next block AWSCALL AWSIGET get next block (should be tape mark) BNZ ILBLXIT L R3,DSBUFTP text location CLC AWSFLGS,CSX4000 tape mark? BE ILBL900 yes, branch AWSMSG 299E,'Expected tape mark after HDR2 label' LA R15,8 B ILBLXIT SPACE 1 ILBL900 DS 0H good return SLR R15,R15 zero return code SPACE 1 ILBLXIT DS 0H exit AWSEXIT , SPACE 1 LTORG , DROP , TITLE 'AWSIMTLR - import process trailer label' *********************************************************************** * AWSIMTLR - import process trailer label * * msg AWS31n * *********************************************************************** space 1 AWSIMTLR CSECT , import process trailer label AWSENTRY , SPACE 1 CLI DSUSESL,C'N' standard labels expected? BE ITLR900 no, branch AWSCALL AWSIGET get a block BNZ ITLRXIT L R3,DSBUFTP current text pointer USING AWSREC,R3 addressability SPACE 1 CLC AWSFLGS,CSXA000 correct flags? BE ITLR020 yes, branch CLC AWSFLGS,CSX4000 end of tape? BNE ITLR010 no, branch AWSMSG 310E,'End of tape reached while positioning' LA R15,8 B ITLRXIT ITLR010 DS 0H AWSMSG 311E,'AWSFLGS unexpected value encountered' LA R15,8 B ITLRXIT SPACE 1 ITLR020 DS 0H check vol1 length CLC =C'EOF1',6(R3) EOF1 found? BE ITLR030 yes, branch AWSMSG 312E,'EOF1 label expected and not found' LA R15,8 B ITLRXIT space 1 ITLR030 DS 0H LA R3,6(,R3) position beyond aws cb MVC DSXL16(4),=4C'0' fill with zeros MVC DSXL16+4(6),DSHDR1BL-DSHDR1(R3) low block count CLI DSHDR1BH-DSHDR1(R3),C'0' high block count specified? BL *+10 no, branch MVC DSXL16(4),DSHDR1BH-DSHDR1(R3) PACK DSDWORK,DSXL16(10) pack block count CVB R0,DSDWORK total block count ST R0,DSBLKCTI save for future reference MVC DSXL16,=X'40202020202020202020202020202120' ED DSXL16,DSDWORK edit value OI DSXL16+15,C'0' make printable MVC DSMSG+1(7),=C'AWS313I' message id MVC DSMSG+19(31),=C'AWS EOF1 label block count :' MVC DSMSG+51(16),DSXL16 set count into message AWSMSG , AWSMSG , blank line AWSMSG , blank line SPACE 1 ITLR900 DS 0H normal exit SLR R15,r15 zero return code SPACE 1 ITLRXIT DS 0H return AWSEXIT , SPACE 1 LTORG , DROP , TITLE 'AWSIGET - import (get) a block' *********************************************************************** * AWSIGET - import (get) a block * * msg AWS32n * * * * This function returns a pointer (dsbuftp) pointing to the next * * block in the input AWSFILE dataset. * * * *********************************************************************** SPACE 1 AWSIGET CSECT , import (get) a block AWSENTRY , SPACE 1 LA R0,6 r0=amount of text needed LA R1,DSBUFFER r1=position to place text ST R1,DSBUFTP for caller's reference SLR R4,R4 r4=amount of text satisfied LR R5,R0 r5=amount of text needed SPACE 1 IGET010 DS 0H retrieve aws header AWSCALL AWSGTXT get some text BNZ IGETEOF if eof, branch ALR R4,R0 amount of text accumlated ALR R1,R0 r1=put text here LR R0,R5 compute amount still needed SR R0,R4 r0=amount of text still needed BNZ IGET010 if more needed, branch SPACE 1 LA R3,DSBUFFER aws header location USING AWSREC,R3 addressability AWSSWAP , swap bytes, set sizes wap byte SLR R0,R0 clear register ICM R0,3,AWSLENC r0=amount of text needed LA R1,6(,R3) r1=position to place text SLR R4,R4 r4=amount of text satisfied LR R5,R0 r5=amount of text needed SPACE 1 IGET020 DS 0H retrieve data block AWSCALL AWSGTXT get some text BNZ IGETEOF if eof, branch ALR R4,R0 amount of text accumlated ALR R1,R0 r1=put text here LR R0,R5 compute amount still needed SR R0,R4 r0=amount of text still needed BNZ IGET020 if more needed, branch SPACE 1 IGET900 DS 0H exit SLR R15,R15 zero return code B IGETXIT exit SPACE 1 IGETEOF DS 0H eof reached LH R15,=H'-4' indicate eof SPACE 1 IGETXIT DS 0H return to caller AWSEXIT , SPACE 1 LTORG , DROP , TITLE 'AWSGTXT - get AWS text' *********************************************************************** * AWSGTXT - get AWS text * * * * calling parameters: r1 -> location where text is to be placed * * r0 -> length of text requested * * * * exit parameters: r0 -> length of text returned * * r15= -4 when eof * * * *********************************************************************** SPACE 1 AWSGTXT CSECT , get AWS text AWSENTRY , SPACE 1 LR R3,R1 r3=location at which to return text LR R4,R0 r4=length of text requested LA R5,AWSUT2 r5=input dcb location USING IHADCB,R5 ... addressability LA R0,GTXTEOF eof routine location STCM R0,7,DCBEODA ... set into dcb SPACE 1 SLR R2,R2 clear register LR R15,R2 clear registger ICM R15,3,DSGTXTL r15=length of source ICM R14,15,DSGTXTP r14=current location in input buffer ST R2,DSGTXTP assume all text will be used STH R2,DSGTXTL ... and entire length * LTR R14,R14 r14=source text already present? BNZ GTXT010 yes, branch SPACE 1 GET AWSUT2 get some data LR R14,R1 r14=source text location SLR R15,R15 clear register ICM R15,3,DCBLRECL r15=length of source TM DCBRECFM,DCBRECU undefined? BO GTXT010 yes, branch TM DCBRECFM,DCBRECF fixed? BO GTXT010 yes, branch LA R14,4(,R14) r14=source text location (after rdw) SH R15,=H'4' r15=source text length (minus rdw) SPACE 1 GTXT010 DS 0H r3=trg,r4=trglen,r14=src,r15=srclen CLR R15,R4 source length exceeds target length? BNH GTXT020 no, branch LA R0,0(R4,R14) r0= *next* source location ST R0,DSGTXTP ... set next pointer (for next call) SLR R15,R4 r15=*next* source length STCM R15,3,DSGTXTL ... set next length (for next call) LR R15,R4 override current source length SPACE 1 GTXT020 DS 0H r3=trg,r4=trglen,r14=src,r15=trglen LR R2,R15 save length for later use LR R0,R3 target location LR R1,R15 target length MVCL R0,R14 copy into user buffer SLR R15,R15 B GTXTXIT return SPACE 1 GTXTEOF DS 0H end of input reached SLR R2,R2 zero length returned ST R2,DSGTXTP zero pointer STH R2,DSGTXTL clear remaining length LH R15,=H'-4' indicate eof SPACE 1 GTXTXIT DS 0H L R1,4(,R13) caller's savearea ST R2,20(,R1) length returned in caller's r0 SPACE 1 AWSEXIT , SPACE 1 LTORG , DROP TITLE 'Dummy functions pending implementation' *********************************************************************** * Dummy functions pending implementation * *********************************************************************** SPACE 1 *AWSDUMMY AWSDUMMY , dummy csect (expansion?) TITLE 'AWSCOMST - Constant common data' *********************************************************************** * AWSCOMST - Constant common data * *********************************************************************** SPACE 1 AWSCOMST CSECT , constant common data SPACE 1 CSPARST1 DC 256YL1(0) locate keyword ORG CSPARST1+C'=' keyword suffix DC C'=' ORG , SPACE 1 CSPARST2 DC 256YL1(0) locate keyword ORG CSPARST2+C' ' delimiter #1 DC C' ' ORG CSPARST2+C',' delimiter #2 DC C',' ORG , SPACE 1 CSPARST3 DC 256YL1(0) locate keyword ORG CSPARST3+c'"' delimiter #1 DC C'"' ORG CSPARST3+C'''' delimiter #2 DC C'''' ORG , SPACE 1 CSNUMTRT DC 256X'FF' NUMERIC TEXT TRT TABLE ORG CSNUMTRT+C'0' DC 10X'00' ORG , SPACE 1 CSHEXTR EQU *-C'0' hexadecimal translate table DC C'0123456789ABCDEF' ORG , SPACE 1 CSAWSPRT DC A(AWSPRNT) print function CSAWSDYE DC A(AWSDYNE) dynamic allocation error function CSAWSEPT DC A(AWSEPUT) put function CSAWSMRK DC A(AWSMARK) write tape mark function CSAWSIGE DC A(AWSIGET) read a logical aws block CSF0 DC F'0' full word of zero CSH4 DC Y(4) half word 4 CSH80 DC Y(80) half word 80 CSP1 DC P'1' packed value 1 CSXA000 DC X'A000' block flags CSX4000 DC X'4000' tape mark flags CSBLNKS DC CL133' ' some blanks LTORG , TITLE 'AWSDATA - Dynamic common data' *********************************************************************** * AWSDATA - Dynamic common data * *********************************************************************** SPACE 1 AWSDATA CSECT , dynamic storage data areas DSSTACK DS (STACKCT*18)F savearea stack AWSDYNAM EQU * origin addressable dynamic storage DSDWORK DS D double word workarea DSFWORK DS F full word work area DSDATAP DS A origin of relocated awsdata DSSTACKP DS A origin of stack DSBUFTP DS A loc of next text in output buffer DSBUFEND DS A end of current block DSGTXTP DS A get text pointer DSBLKCTI DS F block count expected DSHWORK DS H half word work area DSFILECT DS H logical file number DSLSTSIZ DS H size of last block written DSCURSIZ DS H size of current block written DSINFLNO DS H infile= numeric argument DSBLKSIZ DS H block size DSGTXTL DS H get text length DSLRECL DS H lrecl DSRECFM DS CL2 recfm DSASA DS C carriage control DSFLAGS DS X State flags DSFVOLF EQU X'80' ... VOL1 has been written DSFRECV EQU X'40' ... output variable length records DSFFLUSH EQU X'20' ... flush residual output DSFDYUT1 EQU X'10' ... awsut1 dynamically allocated DSFDYTMP EQU X'08' ... awstemp dynamically allocated DSFDYSYI EQU X'04' ... sysin dynamically allocated DSFDYSYP EQU X'02' ... sysprint dynamically allocated DSFOPNEX EQU X'01' ... awsfile is open for export DSFLAGS2 DS X State flags 2 DSFIMPRT EQU X'80' ... import function invoked DSFEXPRT EQU X'40' ... export function invoked DSFFRAGD EQU X'20' ... AWS CB ITSELF IS FRAGMENTED SPACE 1 DSHETCMP DS CL1 HET COMPRESSION REQUESTED DSHETMTH DS CL1 HET COMPRESSION METHOD DSHETLVL DS CL1 HET COMPRESSION LEVEL DSHETIDR DS CL1 HET IDRC DSHETCSZ DS CL5 HET CHUNK SIZE DSBLKCNT DS PL6 DATASET BLOCK COUNT DSOWNER DS CL10 owner= volume owner DSINDSN DS CL44 indsn= dataset name DSOUTDSN DS CL44 outdsn= dataset name DSTDSN DS CL17 tapedsn= dataset name DSINDD DS CL8 indd= ddname DSOUTDD DS CL8 outdd= ddname DSINFLNC DS CL8 infile= character argument DSUNLPGM DS CL8 unload= program DSLODPGM DS CL8 load= program DSUNLTYP DS CL8 unload type (repro, export, etc) DSUSESL DS CL1 use standard labels flag DSCARD DS CL80 sysin control statements DSTVOL DS CL6 tape volser DSJOBNM DS CL8 job name DSSTEPNM DS CL8 step name SPACE 1 DSXL16 DS XL16 16 byte work area DSHEXWK DS CL9 hex work area DSIBLKCT DS PL8 aws input block count DSIRECCT DS PL8 aws input record count SPACE 1 DS 0D AWSRELOC EQU * beginning of relocated storage SPACE 1 DSOPENL OPEN 0,MF=L open parameter list DSCLOSEL CLOSE 0,MF=L close parameter list DSRDJFCB RDJFCB 0,MF=L rdjfcb parameter list SPACE 1 DSPAGECT DC PL2'0' page count DSLINECT DC PL2'90' line count DSMSG DC CL133' ' message buffer DSMSG1 DC CL133' ' message buffer DSHEADER DC CL133' ' ORG DSHEADER DC C'1AWSSL - AWS Virtual Tape (standard labels) - ' DC C'Version 1.9G - Copyright (C) 2002 - ' DC C'By Reed H. Petty, rhp@draper.net' ORG DSHEADER+123 DC C' Page' DSPAGE DC CL4' 1' ORG , SPACE 1 DSJFCBL DS 0F RDJFCB LIST DC X'87',AL3(INFMJFCB) JFCB EXIT LST SPACE 1 PRINT NOGEN IEFJFCBN LIST=YES JFCB PRINT GEN EJECT *********************************************************************** * Dynamic allocation control blocks * *********************************************************************** SPACE 1 DS 0F DSARBP DC X'80',AL3(DSARB) input dataset request block DSARB DC XL(S99RBEND-S99RB)'00' request block SPACE 1 DSATXTP DC A(DSADDNM) ddname DC A(DSADSNM) dataset name DC A(DSASTATS) dataset status DC X'80',AL3(DSADISP) normal disposition SPACE 1 DSADDNM DC YL2(DALDDNAM),YL2(1),YL2(8) DSADDNM1 DC CL8'AWSUT1' SPACE 1 DSADSNM DC YL2(DALDSNAM),YL2(1),YL2(DSADSNML) DSADSNMT DC CL44' ' DSADSNML EQU *-DSADSNMT SPACE 1 DSASTATS DC YL2(DALSTATS),YL2(1),YL2(1),X'08' SHR SPACE 1 DSADISP DC YL2(DALNDISP),YL2(1),YL2(1),X'08' KEEP SPACE 1 DS 0F DSTARBP DC X'80',AL3(DSTARB) awstemp dataset request block DSTARB DC XL(S99RBEND-S99RB)'00' request block DSTATXTP DC A(DSTADDNM) ddname (AWSTEMP) DC A(DSTAUNIT) unit (SYSDA) DC A(DSTASPCU) space primary units (CYL) DC A(DSTASPCP) space primary qty (100) DC X'80',AL3(DSTASPCS) space secondary qty (100) DSTADDNM DC YL2(DALDDNAM),YL2(1),YL2(7),CL7'AWSTEMP' DSTAUNIT DC YL2(DALUNIT),YL2(1),YL2(5),CL5'SYSDA' DSTASPCU DC YL2(DALCYL),YL2(0) DSTASPCP DC YL2(DALPRIME),YL2(1),YL2(3),AL3(100) DSTASPCS DC YL2(DALSECND),YL2(1),YL2(3),AL3(100) SPACE 1 DS 0F DSSARBP DC X'80',AL3(DSSARB) sysin dataset request block DSSARB DC XL(S99RBEND-S99RB)'00' request block DSSATXTP DC A(DSSADDNM) ddname (SYSIN) DC A(DSSAUNIT) unit (SYSDA) DC A(DSSASPCU) space primary units (CYL) DC A(DSSASPCP) space primary qty (1) DC X'80',AL3(DSSASPCS) space secondary qty (1) DSSADDNM DC YL2(DALDDNAM),YL2(1),YL2(5),CL7'SYSIN' DSSAUNIT DC YL2(DALUNIT),YL2(1),YL2(5),CL5'SYSDA' DSSASPCU DC YL2(DALTRK),YL2(0) DSSASPCP DC YL2(DALPRIME),YL2(1),YL2(3),AL3(1) DSSASPCS DC YL2(DALSECND),YL2(1),YL2(3),AL3(1) SPACE 1 DS 0F DSPARBP DC X'80',AL3(DSPARB) sysprint dataset request block DSPARB DC XL(S99RBEND-S99RB)'00' request block DSPATXTP DC A(DSPADDNM) ddname (SYSPRINT) DC X'80',AL3(DSPADUMY) dummy dd statement DSPADDNM DC YL2(DALDDNAM),YL2(1),YL2(8),CL8'SYSPRINT' DSPADUMY DC YL2(DALDUMMY),YL2(0) SPACE 1 DS 0F DSURBP DC X'80',AL3(DSURB) unallocation request block DSURB DC XL(S99RBEND-S99RB)'00' request block DSUTXTP DC X'80',AL3(DSUDDNM) ddname DSUDDNM DC YL2(DUNDDNAM),YL2(1),YL2(8) DSUDDNM1 DC CL8'AWSUT1' EJECT *********************************************************************** * VOL1 label * *********************************************************************** SPACE 1 DSVOL1 DC CL80' ' vol1 label ORG DSVOL1 DC CL4'VOL1' DSVOL1SR DS CL6 volser DC CL1' ' reserved DC CL5' ' vtoc pointer DC CL25' ' reserved DSVOL1OW DC CL10' ' owner DC CL29' ' reserved SPACE 1 *********************************************************************** * HDR1 label * *********************************************************************** SPACE 1 DSHDR1 DC CL80' ' hdr1 label ORG DSHDR1 DC CL4'HDR1' DSHDR1NM DS CL17 last 17 bytes of dsn DSHDR1SR DS CL6 volser DC CL4'0001' file section number DSHDR1SQ DC CL4'0000' file sequence number DC CL4' ' generation number DC CL2' ' generation version number DSHDR1CD DC CL6'000001' creation date, cyyddd,c=' '=1900 DC CL6'000000' expiration date DC CL1'0' not password protected DSHDR1BL DC CL6'000000' block count low order 6 bytes DC CL13'IBM OS/VS 370' system code DC CL3' ' reserved DSHDR1BH DC CL4' ' block count high order 4 bytes ORG , SPACE 1 *********************************************************************** * HDR2 label * *********************************************************************** SPACE 1 DSHDR2 DC CL80' ' hdr2 label ORG DSHDR2 DC C'HDR2' DSHDR2RF DS CL1 record format DSHDR2BL DS CL5 block length DSHDR2RL DS CL5 record length DC C'0' tape density, 0 = cartridge DC C'0' volume switch is not in progress DSHDR2JB DC CL8' ' jobname DC CL1'/' DSHDR2ST DC CL8' ' step name DC CL2' ' recording technique DSHDR2CC DC CL1' ' a=asa,m=machine,' '=none DC CL1' ' reserved DSHDR2BA DC CL1' ' block attribute * b=blocked records * s=spanned or standard * r=blocked and spanned or standard * unblocked DC CL2' ' reserved DC CL6'AWS19G' serial number of creating device DC CL1' ' checkpoint identifier DC CL22' ' reserved DSHDR2LB DC CL10' ' large block length ORG , EJECT *********************************************************************** * EOF1 label * *********************************************************************** DSEOF1 DC CL80' ' eof1 label ORG DSEOF1 DC CL4'EOF1' DSEOF1NM DS CL17 last 17 bytes of dsn DSEOF1SR DS CL6 volser DC CL4'0001' file section number DSEOF1SQ DC CL4'0000' file sequence number DC CL4' ' generation number DC CL2' ' generation version number DC CL6'000001' creation date, cyyddd,c=' '=1900 DC CL6'000001' expiration date DS CL1'0' not password protected DSEOF1BL DC CL6'000000' block count low order 6 bytes DC CL13'IBM OS/VS 370' system code DC CL3' ' reserved DSEOF1BH DC CL4'0000' block count high order 4 bytes ORG , SPACE 1 *********************************************************************** * EOF2 label * *********************************************************************** SPACE 1 DSEOF2 DC CL80' ' eof2 label ORG DSEOF2 DC C'EOF2' DSEOF2RF DS CL1 record format DSEOF2BL DS CL5 block length DSEOF2RL DS CL5 record length DC C'0' tape density, 0 = cartridge DC C'0' volume switch is not in progress DSEOF2JB DC CL8' ' jobname DC CL1'/' DSEOF2ST DC CL8' ' step name DC CL2' ' recording technique DSEOF2CC DC CL1' ' a=asa,m=machine,' '=none DC CL1' ' reserved DSEOF2BA DC CL1' ' block attribute * b=blocked records * s=spanned or standard * r=blocked and spanned or standard * unblocked DC CL2' ' reserved DC CL6'AWSSL ' serial number of creating device DC CL1' ' checkpoint identifier DC CL22' ' reserved DC CL10' ' large block length ORG , SPACE 1 *********************************************************************** * Data control blocks * *********************************************************************** SPACE 1 PRINT NOGEN AWSPRINT DCB DDNAME=AWSPRINT,DSORG=PS,MACRF=PM,RECFM=FBA,LRECL=133 SPACE 1 AWSUT1 DCB DDNAME=AWSUT1,DSORG=PS,MACRF=GL,EXLST=DSJFCBL AWSUT2 DCB DDNAME=AWSFILE,DSORG=PS,MACRF=GL AWSUT3 DCB DDNAME=AWSUT3,DSORG=PS,MACRF=PM SPACE 1 AWSFILE DCB DDNAME=AWSFILE,DSORG=PS,MACRF=PM SPACE 1 AWSCNTL DCB DDNAME=AWSCNTL,DSORG=PS,MACRF=GL SPACE 1 SYSIN DCB DDNAME=SYSIN,DSORG=PS,MACRF=PM,RECFM=FB,LRECL=80, * BLKSIZE=3120 PRINT GEN DROP SPACE 1 DSBUFFER DS 0D 128k I/O buffer location DSENDL EQU *-AWSRELOC length of relocatable storage AWSDATAL EQU *-AWSDATA data areas length EJECT *********************************************************************** * AWS block header definition * *********************************************************************** SPACE 1 AWSREC DSECT , AWS block header AWSLENC DS H block length AWSLENP DS H file data preceeding this block AWSFLGS DS H block flags AWSDBLK DS 0X data block origin END hercules-3.07/util/awswrite.jcl000644 000765 000765 00000037556 11143760541 020301 0ustar00jmaynardjmaynard000000 000000 //IBMUSERA JOB CLASS=A,MSGCLASS=A,MSGLEVEL=(1,1) //ASMCLG PROC //IEUASM EXEC PGM=ASMA90,PARM='NOOBJECT,DECK',REGION=4M //SYSPRINT DD SYSOUT=* //SYSLIB DD DSN=SYS1.MACLIB,DISP=SHR // DD DSN=SYS1.MODGEN,DISP=SHR //SYSUT1 DD UNIT=SYSDA,SPACE=(CYL,(5,5)) //SYSPUNCH DD DSN=&&OBJSET,DISP=(,PASS),UNIT=SYSDA, // SPACE=(TRK,(5,5)),DCB=(RECFM=FB,LRECL=80,BLKSIZE=3120) //IEWL EXEC PGM=IEWL,PARM='LIST,LET,NCAL,MAP', // COND=(0,NE,IEUASM),REGION=4M //SYSPRINT DD SYSOUT=* //SYSUT1 DD UNIT=SYSDA,SPACE=(CYL,(5,5)) //SYSLIN DD DSN=&&OBJSET,DISP=(OLD,DELETE) //SYSLMOD DD DSN=&&GOSET(GO),DISP=(,PASS),UNIT=SYSDA, // SPACE=(TRK,(5,5,5)),DCB=(RECFM=U,BLKSIZE=6144) //GO EXEC PGM=*.IEWL.SYSLMOD,COND=((0,NE,IEUASM),(0,NE,IEWL)) //SYSPRINT DD SYSOUT=* //AWSIN DD DSN=&SYSUID..XXXXXX.AWSTAPE,DISP=SHR //TAPEOUT DD UNIT=3480,VOL=SER=XXXXXX,LABEL=(1,BLP,EXPDT=98000) // PEND //ASMCLG EXEC ASMCLG AWSWRITE TITLE 'Copy AWSTAPE file to physical tape' AWSWRITE CSECT ***** PROGRAM DESCRIPTION * * This program copies an AWSTAPE file (a tape image on disk) * to a physical tape. The exact structure of the tape image * (all files including data blocks and tape marks) is copied * to the physical tape. * * The JCL for running this program is: * * //AWSWRIT EXEC PGM=AWSWRITE * //SYSPRINT DD SYSOUT=* * //AWSIN DD DSN=file.awstape,DISP=SHR * //TAPEOUT DD UNIT=3480,VOL=SER=XXXXXX,LABEL=(1,BLP) * * Notes: * 1. The input file AWSIN can be any record format (fixed, * variable, or undefined) and can have any record length * 2. The output tape is written with BLP, therefore the * job must be run under a job class which allows BLP * processing. The JES2PARM parameter BLP=YES in the * JOBCLASS statement allows a job to use BLP. * This can be modified dynamically by using the command * $TJOBCLASS(A),BLP=YES * * AWSWRITE was created by Roger Bowler, September 2003 * and placed in the public domain. ***** AWSWRITE CSECT SAVE (14,12),,AWSWRITE-Roger-Bowler-2003 LR R12,R15 Establish base register USING AWSWRITE,R12 LA R15,AWSSAVEA Point to new savearea ST R13,4(,R15) Establish forward/ ST R15,8(,R13) backward pointers LR R13,R15 Activate new savearea L R1,0(,R1) Point to PARM area LH R2,0(,R1) Pick up PARM length LA R3,2(,R1) Point to PARM text CH R2,=H'4' Could it be PARM=TEST? BNE NOTTEST No, skip CLC 0(4,R3),=C'TEST' Is it PARM=TEST? BNE NOTTEST No, skip MVI TESTFLAG,X'FF' Yes, set TEST flag NOTTEST EQU * *** * Open the DCBs *** MVC RETCODE,=F'16' Prime return code for failure OPEN (SYSPRINT,OUTPUT) Open listing dataset TM SYSPRINT+48,X'10' Listing DCB open? BZ EXIT No, exit with return code 16 OPEN (AWSIN,INPUT) Open input dataset TM AWSIN+48,X'10' Input DCB open? BZ TERMINE No, exit with return code 16 CLI TESTFLAG,X'FF' Is it PARM=TEST? BE NOOPENT Yes, do not open tape OPEN (TAPEOUT,OUTPUT) Open output dataset TM TAPEOUT+48,X'10' Output DCB open? BZ TERMINE No, exit with return code 16 NOOPENT EQU * MVC RETCODE,=F'0' Prime return code for success *** * Obtain a 64K output buffer *** GETMAIN R,LV=MAXBLKL Obtain 64K storage area ST R1,OUTBUFP Save address of output buffer XC OUTBLKL,OUTBLKL Clear output block length XC INDATAP,INDATAP Clear input data pointer XC INDATAL,INDATAL Clear input data length *** * Read a 6-byte AWSTAPE block header from the input file *** NEXTHDR EQU * LA R4,AWSHDR Address of buffer for header LA R5,AWSHDRL Length of AWSTAPE header BAL R10,READIN Read 6-byte header from AWSIN CLC AWSHDR(6),=XL6'00' Is it all zero? BE LOGEOF Yes, treat as logical end-of-file TM AWSFLG1,AWSF1TM Is this a tape mark? BO WRITETM Yes, go write a tape mark *** * Obtain length of logical data block which follows *** SR R2,R2 Clear length register ICM R2,B'0001',AWSBLKL Load input block length... ICM R2,B'0010',AWSBLKL+1 ...in reverse byte order *** * Determine where to read logical data block into output buffer *** TM AWSFLG1,AWSF1BB Is it start of a physical block? BZ BEGBLK1 No, append to data in buffer XC OUTBLKL,OUTBLKL Yes, clear output block length BEGBLK1 DS 0H L R1,OUTBLKL Calculate... ALR R1,R2 ...new output block length CL R1,=A(MAXBLKL) Does data exceed buffer length? BNL BADBLKL Yes, error *** * Read a logical data block from the input file *** L R4,OUTBUFP Point to start of buffer AL R4,OUTBLKL Point past data already in buffer LR R5,R2 Load logical data block length BAL R10,READIN Read logical data block L R1,OUTBLKL Calculate... ALR R1,R5 ...new output block length ST R1,OUTBLKL Update new output block length TM AWSFLG1,AWSF1EB End of physical block? BZ NEXTHDR No, read next input header *** * Write a physical data block to the tape *** L R1,OUTBLKL Load output block length CVD R1,DWORK Convert block length to decimal MVC MSGDBL(6),=X'402020202120' ED MSGDBL(6),DWORK+5 Edit block length into message MVC MSGDBV,MSGDBV-1 Clear label area in message CH R1,=H'80' Is it an 80-byte block? BNE NOTLABL No, cannot be a standard label L R1,OUTBUFP Point to output buffer CLC 0(3,R1),=C'VOL' Could it be a standard label? BE PRTLABL Yes, list it CLC 0(3,R1),=C'HDR' Could it be a standard label? BE PRTLABL Yes, list it CLC 0(3,R1),=C'EOF' Could it be a standard label? BE PRTLABL Yes, list it CLC 0(3,R1),=C'UHL' Could it be a standard label? BE PRTLABL Yes, list it CLC 0(3,R1),=C'UTL' Could it be a standard label? BNE NOTLABL No, skip PRTLABL EQU * MVC MSGDBV,0(R1) Copy standard label to message NOTLABL EQU * PUT SYSPRINT,MSGDB Write diagnostic message MVI CCW,X'01' Set CCW command = Write L R1,OUTBUFP Point to output buffer STCM R1,B'0111',CCW+1 Save 24-bit buffer address in CCW MVI CCW+4,X'20' Set CCW flags = SLI L R1,OUTBLKL Load length of data in buffer STH R1,CCW+6 Save 16-bit data length in CCW BAL R10,EXCPIO Perform I/O via EXCP B NEXTHDR Read next input header *** * Write a tape mark to the tape *** WRITETM DS 0H L R2,=A(MSGTM) Point to tape mark message PUT SYSPRINT,(R2) Write diagnostic message MVI CCW,X'1F' Set CCW command = Write Tape Mark XC CCW+1(3),CCW+1 Zeroise CCW data address MVI CCW+4,X'20' Set CCW flags = SLI MVC CCW+6(2),=H'1' Set CCW data length non-zero BAL R10,EXCPIO Perform I/O via EXCP B NEXTHDR Read next input header *** * Fatal error routines *** BADBLKL DS 0H L R2,=A(ERRMSG1) Data block exceeds 64K-1 PUT SYSPRINT,(R2) Write error message MVC RETCODE,=F'12' Set bad return code B TERMINE Exit with bad return code OUTIOER DS 0H UNPK ERRM2CCW(9),CCW(5) TR ERRM2CCW(8),HEXTAB-240 MVI ERRM2CCW+8,C' ' UNPK ERRM2CCW+9(9),CCW+4(5) TR ERRM2CCW+9(8),HEXTAB-240 MVI ERRM2CCW+17,C',' UNPK ERRM2ECB(3),ECB(2) TR ERRM2CCW(2),HEXTAB-240 MVI ERRM2CCW+2,C',' UNPK ERRM2CSW(9),IOBCSW(5) TR ERRM2CSW(8),HEXTAB-240 MVI ERRM2CSW+8,C' ' UNPK ERRM2CSW+9(9),IOBCSW+4(5) TR ERRM2CSW+9(8),HEXTAB-240 MVI ERRM2CSW+17,C',' UNPK ERRM2SNS(5),IOBSENSE(3) TR ERRM2SNS(4),HEXTAB-240 MVI ERRM2SNS+4,C' ' PUT SYSPRINT,ERRMSG2 Print I/O error message MVC RETCODE,=F'8' Set bad return code B TERMINE Exit with bad return code *** * Termination routines *** READEOF DS 0H L R2,=A(MSGPEOF) Physical end-of-file on AWSIN PUT SYSPRINT,(R2) Write diagnostic message B TERMINE LOGEOF DS 0H L R2,=A(MSGLEOF) Logical end-of-file on AWSIN PUT SYSPRINT,(R2) Write diagnostic message TERMINE DS 0H ICM R1,B'1111',OUTBUFP Load output buffer address BZ NOFREEM Skip if no buffer allocated FREEMAIN R,A=(1),LV=MAXBLKL Release storage area NOFREEM EQU * CLOSE (AWSIN,,TAPEOUT) Close input/output DCBs CLOSE (SYSPRINT) Close listing dataset EXIT EQU * L R13,4(,R13) Load HSA pointer L R15,RETCODE Load return code L R14,12(,R13) Restore... LM R0,R12,20(R13) ...registers BR R14 Exit from AWSWRITE *** * Subroutine to read a given number of bytes from the input file * * Input: R4 = Destination buffer address * R5 = Number of bytes to read *** READIN DS 0H STM R4,R5,READSAVE Save work registers READCONT EQU * CL R5,INDATAL Enough data in input buffer? BNH READMOVE Yes, copy it * Copy as much data as is available from the input buffer LR R0,R4 R0 = destination buffer address L R1,INDATAL R1 = length of input data L R14,INDATAP R14 => data in input buffer L R15,INDATAL R15 = length of input data MVCL R0,R14 Copy data from input buffer LR R4,R0 R4 = updated destination addr SL R5,INDATAL R5 = updated length remaining * Read the next input record into the input buffer GET AWSIN Get-locate input record SR R0,R0 Clear for insert ICM R0,B'0011',AWSLRECL R0 = record length from DCB TM AWSRECFM,DCBRECU Is it RECFM=U ? BO READNOTV Yes, skip TM AWSRECFM,DCBRECV Is it RECFM=V or RECFM=VB ? BNO READNOTV No, skip * For RECFM=V or RECFM=VB there is a 4-byte RDW preceding the data ICM R0,B'0011',0(R1) Load record length from RDW SH R0,=H'4' Subtract length of RDW LA R1,4(,R1) Skip over the RDW READNOTV EQU * ST R0,INDATAL Save input data length ST R1,INDATAP Save input data pointer B READCONT Go back and move more data READMOVE EQU * * Copy data from the input buffer to the destination buffer L R14,INDATAP R14 => data in input buffer L R15,INDATAL R15 = length of input data MVCL R4,R14 Copy data from input buffer ST R14,INDATAP Save updated input data pointer ST R15,INDATAL Save updated input data length LM R4,R5,READSAVE Restore work registers BR R10 Return from READIN subroutine *** * Subroutine to write to tape using EXCP *** EXCPIO DS 0H CLI TESTFLAG,X'FF' Is it PARM=TEST? BE EXCPRET Yes, bypass tape I/O MVI ECB,X'00' Clear ECB completion code EXCP IOB Start channel program WAIT ECB=ECB Wait for I/O completion CLI ECB,X'7F' I/O completed successfully? BNE OUTIOER No, take error exit EXCPRET EQU * BR R10 Return from EXCPIO subroutine EJECT * * AWSTAPE 6-byte logical block header * AWSHDR DS 0H AWSBLKL DS XL2 Logical block length (reversed) AWSPRVL DS XL2 Previous block length (reversed) AWSFLG1 DS X Flags... AWSF1BB EQU X'80' ...beginning of physical block AWSF1TM EQU X'40' ...tape mark AWSF1EB EQU X'20' ...end of physical block AWSFLG2 DS X Flags (unused) AWSHDRL EQU *-AWSHDR Length of AWSTAPE block header MAXBLKL EQU 65536 Maximum block size 64K * * Data areas for EXCP I/O to tape * CCW CCW X'01',0,X'20',0 Write Data CCW ECB DC F'0' Event Control Block IOB DS 0F Input Output Block... IOBFLAGS DC XL2'0' ...IOB flags IOBSENSE DC XL2'0' ...IOB sense bytes IOBECBPT DC A(ECB) ...ECB pointer IOBCSW DC 2F'0' ...CSW after I/O IOBSTART DC A(CCW) ...CCW pointer IOBDCBPT DC A(TAPEOUT) ...DCB pointer IOBRESTR DC A(0) IOBINCAM DC H'1' ...Block count increment IOBERRCT DC H'0' ...Error counter * * Static data areas * LTORG DWORK DC D'0' Doubleword work area RETCODE DC F'0' Program final return code INDATAP DC A(0) Pointer to next byte of input data INDATAL DC F'0' No.of input data bytes remaining OUTBUFP DC A(0) Address of output buffer OUTBLKL DC F'0' Length of data in output buffer AWSSAVEA DS 18F New savearea READSAVE DS 2F Savearea for READIN subroutine TESTFLAG DC X'00' X'FF' if PARM=TEST specified PRINT NOGEN SYSPRINT DCB DSORG=PS,MACRF=PM,DDNAME=SYSPRINT, RECFM=FBA,LRECL=133,BLKSIZE=133 AWSIN DCB DSORG=PS,MACRF=GL,DDNAME=AWSIN,EODAD=READEOF AWSLRECL EQU DCBLRECL-IHADCB+AWSIN AWSRECFM EQU DCBRECFM-IHADCB+AWSIN TAPEOUT DCB DSORG=PS,MACRF=E,DDNAME=TAPEOUT,DEVD=TA HEXTAB DC C'0123456789ABCDEF' * * Messages * ERRMSG1 DC CL133' *** Error *** Data block length exceeds 64K-1' ERRMSG2 DC CL133' ' ORG ERRMSG2 DC C' *** Error *** ' DC C'CCW=' ERRM2CCW DC C'xxxxxxxx xxxxxxxx,' DC C'ECBCC=' ERRM2ECB DC C'xx,' DC C'CSW=' ERRM2CSW DC C'xxxxxxxx xxxxxxxx,' DC C'SENSE=' ERRM2SNS DC C'xxxx ' ORG MSGTM DC CL133' ** Tape Mark **' MSGDB DC CL133' Data Block: nnnnn bytes' MSGDBL EQU MSGDB+12,6 MSGDBV EQU MSGDB+30,80 MSGPEOF DC CL133' Terminated at end-of-file on AWSIN' MSGLEOF DC CL133' Terminated by zero header on AWSIN' R0 EQU 0 R1 EQU 1 R2 EQU 2 R3 EQU 3 R4 EQU 4 R5 EQU 5 R6 EQU 6 R7 EQU 7 R8 EQU 8 R9 EQU 9 R10 EQU 10 R11 EQU 11 R12 EQU 12 R13 EQU 13 R14 EQU 14 R15 EQU 15 DCBD DSORG=PS,DEVD=TA END // hercules-3.07/util/cckddump.hla000644 000765 000765 00000242263 11224164170 020207 0ustar00jmaynardjmaynard000000 000000 */* ---------------------------------------------------------------- * * build a dasd file from sysut1 to sysut2 * * ---------------------------------------------------------------- */ version EQU 0 release EQU 1 mod EQU 14 SOMITCW */* ---------------------------------------------------------------- * * macros * * ---------------------------------------------------------------- */ MACRO &L STLE &R,&A store little-endian &L STC &R,&A STCM &R,2,1+&A STCM &R,4,2+&A STCM &R,8,3+&A MEND MACRO &L STHLE &R,&A store halfword little-endian &L STC &R,&A STCM &R,2,1+&A MEND MACRO &L LLE &R,&A load little-endian &L IC &R,&A ICM &R,2,1+&A ICM &R,4,2+&A ICM &R,8,3+&A MEND MACRO &L LHLE &R,&A load halfword little-endian &L SLR &R,&R IC &R,&A ICM &R,2,1+&A MEND MACRO &L #MSG &LVL,&MSG,&TYPE=CALL LCLA &A,&N,&O LCLC &C GBLA &MSG_IX GBLC &MSGS(256) AIF ('&TYPE' EQ 'CALL').CALL, x ('&TYPE' EQ 'GEN').GEN MNOTE 8,'Invalid type specified' MEXIT .* .CALL ANOP &C SETC '&LVL' AIF ('&LVL' NE '').LVLOK &C SETC '1' .LVLOK ANOP &L CLI msglvl,&C BH #MG&SYSNDX.X &MSG_IX SETA &MSG_IX+1 &MSGS(&MSG_IX) SETC '&MSG' L re,=A(#MSG&MSG_IX) LA rf,L'#MSG&MSG_IX &A SETA 1 &O SETA 0 &N SETA N'&SYSLIST-2 AGO .PL0 .PLLOOP ANOP LA re,&SYSLIST(&A+2) &A SETA &A+1 AIF (&A GT &N).PLX14 LA rf,&SYSLIST(&A+2) &A SETA &A+1 .PL0 AIF (&A GT &N).PLX15 LA r0,&SYSLIST(&A+2) &A SETA &A+1 AIF (&A GT &N).PLX0 LA r1,&SYSLIST(&A+2) &A SETA &A+1 AIF (&A GT &N).PLX1 STM re,r1,msgl+&O &O SETA &O+16 AGO .PLLOOP .PLX14 ST re,msgl+&O AGO .CALL2 .PLX15 STM re,rf,msgl+&O AGO .CALL2 .PLX0 STM re,r0,msgl+&O AGO .CALL2 .PLX1 STM re,r1,msgl+&O .CALL2 LA r1,msgl L rf,=a(msg_rtn) BALR re,rf #MG&SYSNDX.X DS 0H MEXIT .* .GEN ANOP AIF ('&L' EQ '').GENNOL &L DS 0H .GENNOL ANOP &A SETA 1 .GENLOOP AIF (&A GT &MSG_IX).MEND #MSG&A DC C&MSGS(&A) &A SETA &A+1 AGO .GENLOOP .MEND MEND */* ---------------------------------------------------------------- * * * * ---------------------------------------------------------------- */ main CSECT , main RMODE ANY main AMODE 31 SAVE (14,12),,'cckddump main() &SYSDATE &SYSTIME ' pgmid EQU main+5 LR rc,rf USING main,rc LA rb,4095(,rc) USING main+4095,rb LR r2,r1 */* ---------------------------------------------------------------- * * get/clear workareas * * ---------------------------------------------------------------- */ STORAGE OBTAIN,LENGTH=vdw_len,BNDRY=PAGE ST r1,8(,rd) ST rd,4(,r1) LR rd,r1 USING vdw,rd MVC id,=C'vdw ' LA r0,vdw+8 L r1,=A(vdw_len-8) SLR rf,rf MVCL r0,re ST rd,vdw_31 STORAGE OBTAIN,LENGTH=vdw24_len,LOC=BELOW,BNDRY=PAGE ST r1,vdw_24 LR ra,r1 USING vdw24,ra MVC id24,=C'vdw24' LA r0,vdw24+4 L r1,=A(vdw24_len-4) SLR rf,rf MVCL r0,re */* ---------------------------------------------------------------- * * try to open print file * * ---------------------------------------------------------------- */ MVC prdcb,model_prdcb MVC prdcbe,model_prdcbe pr USING IHADCB,prdcb LA r1,prdcbe ST r1,pr.DCBDCBE MVC devtl,model_devtl DEVTYPE pr.DCBDDNAM,(devta,L'devta),MF=(E,devtl) LTR rf,rf BNZ noprint MVC openl,model_openl OPEN (pr.IHADCB,OUTPUT),MODE=31,MF=(E,openl) #MSG 1,'%s %d.%d.%d starting', x pgmid,=A(version),=A(release),=A(mod) #MSG 0,'main workarea is at address 0x%x, 24-bit workarea is x at address 0x%x',vdw_31,vdw_24 noprint DS 0H */* ---------------------------------------------------------------- * * get parameters * * ---------------------------------------------------------------- */ LR r1,r2 BAS r9,getopts */* ---------------------------------------------------------------- * * get device information for sysut1 [the volume to be dumped] * * ---------------------------------------------------------------- */ MVC devtl,model_devtl DEVTYPE =CL8'SYSUT1',(devta,L'devta), x INFOLIST=devt_infol_2,MF=(E,devtl) LTR rf,rf BNZ ut1_devt_err TM devta+2,UCB3DACC check for dasd device BNO ut1_not_dasd TM dev_flags,X'80' check for eckd BNO ut1_not_eckd L r3,cyls M r2,trks_per_cyl total number of trks ST r3,trks */* ---------------------------------------------------------------- * * get device information for sysut2 [the file to be dumped] * * ---------------------------------------------------------------- */ MVC devtl,model_devtl DEVTYPE =CL8'SYSUT2',(dw,L'devta), x INFOLIST=devt_infol_2,MF=(E,devtl) LTR rf,rf BNZ out_devt_err TM dw+2,UCB3DACC check for dasd device BNO out_not_dasd */* ---------------------------------------------------------------- * * part 1 -- determine which tracks to dump * * * * From the vtoc, determine which tracks are to be dumped. * * A vector [trk_vec] is built for each track on the volume. * * If an entry is zero, then the track will not be dumped; * * otherwise, the entry points to an entry in the dataset * * table [dsn_area] which will contain statistics about each * * dataset on the volume. The first 3 entries in the dataset * * table are special, representing free space [**free**], * * track 0 [**track 0] and the vtoc [**vtoc**], respectively. * * * * ---------------------------------------------------------------- */ */* ---------------------------------------------------------------- * * open sysut1 vtoc * * ---------------------------------------------------------------- */ vt USING IHADCB,vtdcb MVC vtdcb,model_vtdcb LA r1,exlst STCM r1,7,vt.DCBEXLSA LA r1,jfcb ST r1,exlst MVI exlst,X'87' MVC openl24,model_openl24 RDJFCB (vt.IHADCB,INPUT),MF=(E,openl24) LTR rf,rf BNZ ut1_rdjfcb_err j USING INFMJFCB,jfcb MVI j.JFCBDSNM,4 vtoc name is all x'04's MVC j.JFCBDSNM+1(L'JFCBDSNM-1),j.JFCBDSNM MVC volser,j.JFCBVOLS DROP j OPEN vt.IHADCB,TYPE=J,MF=(E,openl24) TM vt.DCBOFLGS,DCBOFOPN BNO ut1_vtoc_open_err L r2,vt.DCBDEBAD load deb address for cvaf N r2,=A(X'00FFFFFF') #MSG 1,'%s:6 vtoc opened',volser #MSG 0,'%s:6 has %d cyls, %d trks/cyl and %d total trks', x volser,cyls,trks_per_cyl,trks */* ---------------------------------------------------------------- * * read the format 4 dscb * * ---------------------------------------------------------------- */ h USING BFLHDR,bflh OI h.BFLHFL,BFLHDSCB MVI h.BFLHNOE,1 e USING BFLE,bflent LA r1,dscb4 ST r1,e.BFLEBUF OI e.BFLEFL,BFLECHR MVI e.BFLELTH,L'dscb4 MVC cvpl_area,model_cvpl CVAFSEQ ACCESS=GTEQ,BUFLIST=h.BFLHDR,DEB=(r2), x BRANCH=(YES,PGM),MF=(E,cvpl_area) LTR rf,rf BNZ ut1_dscb4_err DROP h,e f4 USING IECSDSL4-44,dscb4 CLI f4.DS4IDFMT,C'4' BNE ut1_dscb4_err */* ---------------------------------------------------------------- * * calculate size of the vtoc and get an area for all dscbs * * ---------------------------------------------------------------- */ SLR r4,r4 IC r4,f4.DS4DEVDT ST r4,dscbs_per_trk LA r1,f4.DS4VTOCE BAL re,cnv_xtnt r0 - starting track, x r1 - number of tracks ST r1,vtoc_trks MR r0,r4 ST r1,total_dscbs number of dscbs MH r1,=Y(DS1END-IECSDSL1) ST r1,vtoc_size size of vtoc STORAGE OBTAIN,LENGTH=(r1),BNDRY=PAGE area for the vtoc ST r1,vtoc_area #MSG 0,'%s:6 vtoc has %d total dscbs', x volser,total_dscbs #MSG 0,'storage obtained for vtoc area, addr 0x%x size %d', x vtoc_area,vtoc_size */* ---------------------------------------------------------------- * * read the entire vtoc a track at a time * * ---------------------------------------------------------------- */ #MSG 0,'reading %s:6 vtoc',volser L r3,vtoc_area L r4,vtoc_trks LA r5,=XL5'0' BAL re,cvaf_bld MVC cvpl_area,model_cvpl read the first track CVAFSEQ ACCESS=GTEQ,BUFLIST=bflh,DEB=(r2), x BRANCH=(YES,PGM),MF=(E,cvpl_area) LTR rf,rf BNZ ut1_cvaf_err B vtocnext vtocloop BAL re,cvaf_bld read another track CVAFSEQ ACCESS=GT,BUFLIST=bflh,DEB=(r2), x BRANCH=(YES,PGM),MF=(E,cvpl_area) LTR rf,rf BNZ ut1_cvaf_err vtocnext BCT r4,vtocloop CLOSE vtdcb,MF=(E,openl24) #MSG 0,'%s:6 vtoc closed',volser B process_vtoc */* ---------------------------------------------------------------- * * subroutine to build the cvaf control blocks * * * * r3 - pointer to buffer for dscb (updated) * * r5 - cchhr of 1st dscb - points to last bflearg on exit * * ---------------------------------------------------------------- */ cvaf_bld XC bflh,bflh USING IECSDSL1,r3 h USING BFLHDR,bflh OI h.BFLHFL,BFLHDSCB L r0,dscbs_per_trk STC r0,h.BFLHNOE LA rf,bflent USING BFLE,rf cvaf_bld_loop DS 0H XC BFLE(BFLELN),BFLE OI BFLEFL,BFLECHR MVI BFLELTH,DS1END-IECSDSF1 MVC BFLEARG,0(r5) arg only used for 1st entry ST r3,BFLEBUF LA r3,DS1END LA r5,BFLEARG r5 will point to last bflearg LA rf,BFLE+BFLELN on exit BCT r0,cvaf_bld_loop BR re DROP r3,h,rf */* ---------------------------------------------------------------- * * count nbr datasets and get a dataset area * * ---------------------------------------------------------------- */ process_vtoc DS 0H L r0,total_dscbs L r1,vtoc_area USING IECSDSL1,r1 SLR r3,3 init nbr datasets SLR rf,rf cnt_dsn CLI DS1FMTID,C'1' BNE cnt_dsn_next LA r3,1(,r3) LR rf,r1 remember last fmt1 dscb addr cnt_dsn_next DS 0H LA r1,DS1END BCT r0,cnt_dsn DROP r1 ST r3,dsn_nbr ST rf,last_f1_dscb #MSG 1,'%d datasets are on %s:6',dsn_nbr,volser LA r3,3(,r3) for free, track 0 and vtoc ST r3,dsn_nbr M r2,=A(dsn_area_len) ST r3,dsn_area_size STORAGE OBTAIN,LENGTH=(R3),BNDRY=PAGE ST r1,dsn_area_addr LR r2,r1 SLR rf,rf MVCL r2,re USING dsn_area,r1 MVC dsn_name,=CL44'*** free ***' LA r1,dsn_area_len(,r1) MVC dsn_name,=CL44'*** track 0 ***' MVC dsn_extents,=A(1) MVC dsn_trks,=A(1) MVC dsn_trks_dump,=A(1) DROP r1 #MSG 0,'storage obtained for dsn area, addr 0x%x size %d', x dsn_area_addr,dsn_area_size */* ---------------------------------------------------------------- * * get track vector * * * * each word corresponds to a track; if the word is non-zero * * then it points to a dsn_area entry and the track will * * be dumped. * * ---------------------------------------------------------------- */ L r3,trks SLL r3,2 ST r3,trk_vec_size STORAGE OBTAIN,LENGTH=(r3),BNDRY=PAGE ST r1,trk_vec LR r2,r1 SLR rf,rf MVCL r2,re TM opts,ALLTRKS dumping all tracks ? BNO init_trk_vec1 no, continue L r3,trks init_trk_vec DS 0H MVC 0(4,r1),dsn_area_addr set entry to '*** none ***' LA r1,4(,r1) BCT r3,init_trk_vec init_trk_vec1 DS 0H L r1,trk_vec L r2,dsn_area_addr LA r2,dsn_area_len(,r2) track 0 dsn_area [2nd entry] ST r2,0(,r1) set track 0 to dump #MSG 0,'storage obtained for trk vector, addr 0x%x size %d', x trk_vec,trk_vec_size */* ---------------------------------------------------------------- * * figure out which tracks to dump * * ---------------------------------------------------------------- */ L r9,vtoc_area L r4,dsn_area_addr LA r4,dsn_area_len*2(,r4) point to 3rd entry [vtoc] USING dsn_area,r4 fmt4 MVC dsn_name,=CL44'*** vtoc ***' first dscb is format 4 MVC dsn_extents,=A(1) USING IECSDSL4-44,r9 LA r1,DS4VTOCE BAL re,cnv_xtnt get vtoc start trk, size ST r1,dsn_trks ST r1,dsn_trks_dump LA r1,DS4VTOCE LA r2,1 SLR r3,r3 BCTR r3,0 BAL re,upd_trk_vec LA r4,dsn_area_len(,r4) DROP r9 USING IECSDSL1,r9 vtoc_loop LA r9,DS1END CL r9,last_f1_dscb BH vtoc_exit CLI DS1FMTID,C'1' BNE vtoc_loop fmt1 MVC dsn_name,DS1DSNAM format 1 dscb processing SLR r2,r2 IC r2,DS1NOEPV ST r2,dsn_extents LTR r2,r2 BZ f1_part2 */* count number of tracks allocated for the dataset */ LA r6,DS1EXT1 LA r7,3 format 1 has 3 extents f1_xt LR r1,r6 BAL re,cnv_xtnt A r1,dsn_trks ST r1,dsn_trks SH r2,=Y(1) BNP f1_part2 LA r6,10(,r6) BCT r7,f1_xt fmt3 LA r1,DS1PTRDS BAL re,cnv_ptr LR r8,r1 USING IECSDSL3,r8 LA r6,DS3EXTNT fmt 3 starts off with 4 extents LA r7,4 f3_xt1 LR r1,r6 BAL re,cnv_xtnt A r1,dsn_trks ST r1,dsn_trks SH r2,=Y(1) BNP f1_part2 LA r6,10(,r6) BCT r7,f3_xt1 LA r6,DS3ADEXT LA r7,9 and has 9 additional extents f3_xt2 LR r1,r6 BAL re,cnv_xtnt A r1,dsn_trks ST r1,dsn_trks SH r2,=Y(1) BNP f1_part2 LA r6,10(,r6) BCT r7,f3_xt2 LA r1,DS3PTRDS B fmt3 DROP r8 f1_part2 DS 0H */* check if dataset included or excluded */ L r1,dsn_incl_list LTR r1,r1 BZ f1_in_ok LA r0,DS1DSNAM BAL re,chk_dsn_list LTR rf,rf BZ f1_in_ok OI dsn_flag,dsn_not_incl f1_in_ok L r1,dsn_excl_list LTR r1,r1 BZ f1_ex_ok LA r0,DS1DSNAM BAL re,chk_dsn_list LTR rf,rf BNZ f1_ex_ok OI dsn_flag,dsn_excl #MSG 1,'%s:44 Excluded',DS1DSNAM Msg for DS exclude SOMITCW f1_ex_ok TM dsn_flag,dsn_not_incl+dsn_excl BNZ f1_exit */* check if we'll use ds1lstar */ SLR r3,r3 presume we won't use ds1lstar BCTR r3,0 TM opts,ALLDATA+ALLTRKS BNZ f1_no_lstar TM DS1SMSFG,DS1PDSE+DS1STRP+DS1PDSEX+DS1DSAE BNZ f1_no_lstar CLC DS1DSORG,=AL1(DS1DSGPS,0) BE f1_lstar_ok CLC DS1DSORG,=AL1(DS1DSGPO,0) BNE f1_no_lstar f1_lstar_ok DS 0H SLR r3,r3 ICM r3,3,DS1LSTAR LA r3,1(,r3) number tracks in use f1_no_lstar DS 0H */* scan the extents */ LA r0,3 LA r1,DS1EXT1 L r2,dsn_extents f1_xt_2 BAL re,upd_trk_vec LTR rf,rf BNZ f1_exit BCT r0,f1_xt_2 LA r1,DS1PTRDS fmt3_2 BAL re,cnv_ptr LR r8,r1 USING IECSDSL3,r8 LA r1,DS3EXTNT LA r0,4 f3_xt1_2 BAL re,upd_trk_vec LTR rf,rf BNZ f1_exit BCT r0,f3_xt1_2 LA r1,DS3ADEXT LA r0,9 f3_xt2_2 BAL re,upd_trk_vec LTR rf,rf BNZ f1_exit BCT r0,f3_xt2_2 LA r1,DS3PTRDS B fmt3_2 DROP r8 f1_exit LA r4,dsn_area_len(,r4) B vtoc_loop vtoc_exit DS 0H DROP r9,r4 L r1,vtoc_area L r0,vtoc_size STORAGE RELEASE,ADDR=(1),LENGTH=(0) #MSG 0,'storage released for vtoc area, addr 0x%x size %d', x vtoc_area,vtoc_size XC vtoc_area,vtoc_area XC last_f1_dscb,last_f1_dscb XC vtoc_size,vtoc_size * The dsn_excl_list memory is being freed here. SOMITCW L r1,dsn_excl_list Load addr. of first list entry SOMITCW in_free DS 0H SOMITCW LTR r1,r1 See if a list entry to free SOMITCW BZ in_freed All dsn_excl_list freed, go exit SOMITCW L r2,0(,r1) Save the next address to free SOMITCW FREEMAIN RU,LV=49,A=(1) Free the list entry SOMITCW LR r1,r2 Set the next address to free SOMITCW B in_free Go to free the next list entry SOMITCW in_freed DS 0H SOMITCW XC dsn_excl_list(4),dsn_excl_list Clear the anchor SOMITCW */* ---------------------------------------------------------------- * * count number of tracks we're going to dump * * ---------------------------------------------------------------- */ SLR r2,r2 L r1,trk_vec L r0,trks SLR rf,rf cnt_dump CL rf,0(,r1) BE *+8 LA r2,1(,r2) LA r1,4(,r1) BCT r0,cnt_dump ST r2,trks_dump #MSG 0,'%d tracks out of %d will be dumped', x trks_dump,trks */* ---------------------------------------------------------------- * * part 2 -- do the actual work */* ---------------------------------------------------------------- */* ---------------------------------------------------------------- * * open sysut1 in excp mode * * ---------------------------------------------------------------- */ ex USING IHADCB,exdcb MVC exdcb,model_exdcb LA r1,exlst STCM r1,7,ex.DCBEXLSA LA r1,jfcb ST r1,exlst MVI exlst,X'87' MVC openl24,model_openl24 RDJFCB (ex.IHADCB,INPUT),MF=(E,openl24) LTR rf,rf BNZ ut1_rdjfcb_err j USING INFMJFCB,jfcb MVI j.JFCBDSNM,4 vtoc name is all x'04's MVC j.JFCBDSNM+1(L'JFCBDSNM-1),j.JFCBDSNM DROP j OPEN ex.IHADCB,TYPE=J,MF=(E,openl24) TM ex.DCBOFLGS,DCBOFOPN BNO ut1_excp_open_err */* ---------------------------------------------------------------- * * update the deb so we can read the entire volume * * [this requires key 0 - hence supervisor state] * * ---------------------------------------------------------------- */ L r2,ex.DCBDEBAD load deb address N r2,=A(X'00FFFFFF') USING DEBBASIC,r2 LA r3,DEBBASND USING DEBDASD,r3 MODESET MODE=SUP IPK 0(r2) SPKA 0 SLR r1,r1 STH r1,DEBSTRCC STH r1,DEBSTRHH L r1,cyls BCTR r1,0 STCM r1,3,DEBENDCC L r1,trks_per_cyl BCTR r1,0 STCM r1,3,DEBENDHH L r1,trks C r1,=A(65535) BNH *+8 L r1,=A(65535) STCM r1,3,DEBNMTRK SPKA 0(r2) MODESET MODE=PROB DROP r2,r3 */* ---------------------------------------------------------------- * * build the sysut1 iob * * ---------------------------------------------------------------- */ i1 USING IOBSTDRD,excp_iob OI i1.IOBFLAG1,IOBDATCH+IOBCMDCH+IOBUNREL LA r1,excp_ecb ST r1,i1.IOBECBPT LA r1,excp_ccws ST r1,i1.IOBSTART LA r1,exdcb ST r1,i1.IOBDCBPT */* ---------------------------------------------------------------- * * get area for read track (rt) * * ---------------------------------------------------------------- */ MVC trkcalcl,model_trkcalcl TRKCALC FUNCTN=TRKBAL,TYPE=devta+3,R=1,K=0,DD=65535, x MAXSIZE=YES,REGSAVE=YES,MF=(E,trkcalcl) LR r3,r0 copy max r1 data size A r3,=A(ha_len+count_len+8+count_len+8) x add ha size, r0 size, x r1 count and end-track marker LA r3,511(,r3) round_up 512 SRL r3,9 SLL r3,9 ST r3,trk_size M r2,trks_per_cyl STORAGE OBTAIN,LENGTH=(r3),LOC=BELOW,BNDRY=PAGE ST r1,excp_io_area ST r3,excp_io_size #MSG 0,'storage obtained for %s i/o area, addr 0x%x size %d',x volser,excp_io_area,excp_io_size */* ---------------------------------------------------------------- * * get area for compression * * ---------------------------------------------------------------- */ TM opts,COMPRESSION BNO no_compress_1 L r2,trk_size A r2,=A(4096) SRL r2,12 SLL r2,12 STORAGE OBTAIN,LENGTH=(r2),BNDRY=PAGE STM r1,r2,compr_area #MSG 0,'storage obtained for compression, addr 0x%x size %d',x compr_area,compr_size LA r2,handle LA r3,=A(32*1024) LA r4,=A(1) STM r2,r4,dw OI dw+8,X'80' LA r1,dw L rf,=V(EDCXHOTL) create persistent c environ BALR re,rf #MSG 0,'persistent c environment created, handle=0x%x', x handle no_compress_1 DS 0H */* ---------------------------------------------------------------- * * open sysut2 (output file) * * ---------------------------------------------------------------- */ o USING IHADCB,outdcb MVC outdcb,model_outdcb OPEN (o.IHADCB,OUTPUT),MF=(E,openl24) TM o.DCBOFLGS,DCBOFOPN BNO out_open_err #MSG 1,'file SYSUT2 opened for output' */* ---------------------------------------------------------------- * * get sysut2 i/o areas * * ---------------------------------------------------------------- */ STORAGE OBTAIN,LENGTH=16384,BNDRY=PAGE ST r1,out_buf first output buffer MVC out_bufsz,=A(16384) * build the headers LR r3,r1 USING VDHDR,r3 ST r3,vdhdr_addr LR r0,r3 L r1,=A(16384) SLR rf,rf MVCL r0,re USING CKDDASD_DEVHDR,VDH_devhdr * MVC CKD_devid,=cl8'CKD_C370' Deleted SOMITCW * TR CKD_devid,e2aTab Deleted SOMITCW MVC CKD_devid,=XL8'434B445F43333730' SOMITCW L rf,trks_per_cyl STLE rf,CKD_heads L rf,trk_size STLE rf,CKD_trksize MVI CKD_devtype,x'90' CLI devta+3,x'0f' BE *+8 MVI CKD_devtype,x'80' USING CCKDDASD_DEVHDR,VDH_devhdr2 MVC CCKD_vrm,=AL1(version,release,mod) TM opts,DONTCOMPRESS BO *+8 MVI CCKD_options,1 L rf,cyls STLE rf,CCKD_cyls * calculate number lvl 1 entries L rf,trks LR r2,rf SRL r2,8 number of trks / 256 N rf,=A(X'000000ff') evenly divisible ? BZ *+8 LA r2,1(,r2) no, increment number STLE r2,CCKD_numl1tab LA r1,256 STLE r1,CCKD_numl2tab L r1,cckd_compr STC r1,CCKD_compress L r1,cckd_compr_level STHLE r1,CCKD_compress_parm LR r1,r2 calclate first pos SLL r1,2 (at end ov lvl 1 tab) AL r1,=A(VDH_l1tab-VDHDR) ST r1,out_pos ST r1,bytes_ovh DROP r3 * get area for rewrites LA r2,2(r2,r2) 2 entries for ea lvl 2 tab MH r2,=Y(rw_len) plus the 1st buf + a spare STORAGE OBTAIN,LENGTH=(r2),BNDRY=PAGE STM r1,r2,rw_area LR r0,r1 clear the rewrite area LR r1,r2 SLR rf,rf MVCL r0,re L r2,rw_area set first rewrite entry USING rw_ent,r2 MVC rw_buf,out_buf ST r2,last_rw LA r2,rw_next ST r2,next_rw DROP r2 */* ---------------------------------------------------------------- * * read tracks * * ---------------------------------------------------------------- */ SLR r2,r2 init relative track L r3,trk_vec read_loop CL r2,trks BNL read_exit LR rf,r2 get dsn area addr for trk SLL rf,2 L r4,0(rf,r3) LTR r4,r4 BZ read_next SLR r6,r6 LR r7,r2 D r6,trks_per_cyl get cc [r7] and hh [r6] XC i1.IOBSEEK,i1.IOBSEEK STCM r7,3,i1.IOBCC STCM r6,3,i1.IOBHH * build locate record ccw XC excp_ccws,excp_ccws LA r5,excp_ccws USING ccw0,r5 MVI CCW0CMD,lr LA r1,lr_parms STCM r1,7,CCW0ADDR OI CCW0FLAG,CCW0CC LA r1,L'lr_parms STCM r1,3,CCW0CNT LA r5,CCW0END * build read track ccws, try to read to end-of-cylinder L r0,trk_size L r1,excp_io_area USING ha,r1 read_rt MVI ha_bin,0 build a ha STCM r7,3,ha_cc STCM r6,3,ha_hh LA rf,ha_end DROP r1 MVI CCW0CMD,rt STCM rf,7,CCW0ADDR OI CCW0FLAG,CCW0SLI+CCW0CC STCM r0,3,CCW0CNT AR r1,r0 next i/o area addr LA r6,1(,r6) increment hh C r6,trks_per_cyl BNL read_rt_x exit if next cylinder LA r2,1(,r2) increment track nbr LR rf,r2 SLL rf,2 L r4,0(rf,r3) LTR r4,r4 BZ read_rt_x exit if trk_vec entry is 0 LA r5,CCW0END else point to next ccw B read_rt and loop back read_rt_x NI CCW0FLAG,255-CCW0CC unchain last ccw DROP r5 SLR rf,rf ICM rf,3,i1.IOBHH SR r6,rf number of read rt ccws * build locate record parameters XC lr_parms,lr_parms LA r5,lr_parms USING lr_parm_area,r5 MVI lr_op,lr_orient_home+lr_read_tracks STC r6,lr_count MVC lr_seek_addr,i1.IOBCC MVC lr_search_arg,i1.IOBCC DROP r5 * issue excp XC excp_ecb,excp_ecb EXCP i1.IOBSTDRD WAIT 1,ECB=excp_ecb CLI excp_ecb,X'7f' BNE ut1_io_err * process each track image L r1,excp_io_area read_proc LA r7,ha_len(,r1) find end of the track USING count,r7 read_proc1 CLC =X'ffffffffffffffff',count BE read_proc2 SLR rf,rf IC rf,count_key SLR r0,r0 ICM r0,3,count_data AR rf,r0 LA r7,count_end(rf) B read_proc1 DROP r7 read_proc2 LA r0,8(,r7) get length of track image SR r0,r1 ST r1,trk_addr ST r0,trk_sz ST r1,ctrk_addr CH r0,=Y(37) track just an eof ? BNE *+6 SLR r0,r0 yes, use 0 length ST r0,ctrk_sz * compress the track [but not the ha] * void *__xhotu(void *handle, void *function, ...); * int compress(uchar *dest, ulong *destLen, * const uchar *source, ulong sourceLen); TM opts,COMPRESSION BNO no_compress2 LA re,handle set parms for edcxhotu LA rf,=V(COMPRES2) STM re,rf,zlib_pl LM re,rf,compr_area dest area, length MVC 0(ha_len,re),0(r1) copy the ha MVI 0(re),1 flag indicating compressed trk LA re,ha_len(,re) point past the ha SH rf,=Y(ha_len) adjust dest length ST rf,compr_used set dest length LA rf,compr_used addr dest length STM re,rf,zlib_pl+8 set dest addr, addr len SH r0,=Y(ha_len) adjust source len BNP no_compress2 don't compress if null track ST r0,zlib_pl+20 set source length LA r1,ha_len(,r1) adjust source addr ST r1,zlib_pl+16 set source addr L re,compr_level get compression level ST re,zlib_pl+24 set compression level LA r1,zlib_pl parameter list addr L rf,=V(EDCXHOTU) call zlib compress function BALR re,rf LTR rf,rf test return code BNZ no_compress2 L r1,compr_used get compressed length LA r1,ha_len(,r1) add size of ha C r1,trk_sz check lengths BNL no_compress2 use uncompressed img MVC ctrk_addr,compr_area ST r1,ctrk_sz no_compress2 DS 0H * update byte counts LM r0,r1,bytes_read total bytes read AL r1,trk_sz BC 12,*+8 AL r0,=A(1) STM r0,r1,bytes_read LM r0,r1,bytes_written total bytes written AL r1,ctrk_sz BC 12,*+8 AL r0,=A(1) STM r0,r1,bytes_written L r1,ctrk_addr calculate dsn entry address USING ha_bin,r1 SLR re,re SLR rf,rf ICM rf,3,ha_cc M re,trks_per_cyl SLR re,re ICM re,3,ha_hh ALR rf,re SLL rf,2 L r4,0(rf,r3) DROP r1 USING dsn_area,r4 LM r0,r1,dsn_bytes_read dataset bytes read AL r1,trk_sz BC 12,*+8 AL r0,=A(1) STM r0,r1,dsn_bytes_read LM r0,r1,dsn_bytes_written dataset bytes written AL r1,ctrk_sz BC 12,*+8 AL r0,=A(1) STM r0,r1,dsn_bytes_written DROP r4 * call write track routine LA r1,ctrk_addr point to addr, len BAL re,write_track call write_track() L r1,trk_addr A r1,trk_size BCT r6,read_proc loop back if more tracks * next track read_next LA r2,1(,r2) B read_loop */* ---------------------------------------------------------------- * * finished reading -- cleanup * * ---------------------------------------------------------------- */ read_exit SLR r1,r1 nullify parm pointer BAL re,write_track call write_track() to finish CLOSE exdcb,MF=(E,openl24) #MSG 1,'file SYSUT1 closed' CLC =A(0),handle BE no_c_env LA r1,handle terminate the c environment ST r1,dw OI dw,X'80' LA r1,dw L rf,=V(EDCXHOTT) BALR re,rf no_c_env LM r1,r2,excp_io_area STORAGE RELEASE,ADDR=(1),LENGTH=(r2) LM r1,r2,compr_area LTR r1,r1 BZ read_term STORAGE RELEASE,ADDR=(1),LENGTH=(r2) read_term DS 0H ********* DC H'0' */* ---------------------------------------------------------------- * * print statistics * * ---------------------------------------------------------------- */ L rf,=A(do_stats) statistics routine addr BALR re,rf print the statistics */* ---------------------------------------------------------------- * * close the print file * * ---------------------------------------------------------------- */ TM pr.DCBOFLGS,DCBOFOPN did the print file open BNO noprint2 nope CLOSE pr.IHADCB,MODE=31,MF=(E,openl) noprint2 DS 0H */* ---------------------------------------------------------------- * * free the workareas and return * * ---------------------------------------------------------------- */ L r1,vdw_24 L r0,=A(vdw24_len) STORAGE RELEASE,ADDR=(1),LENGTH=(0) LR r1,rd L rd,4(,rd) L r0,=A(vdw_len) STORAGE RELEASE,ADDR=(1),LENGTH=(0) RETURN (14,12),RC=0 */* ---------------------------------------------------------------- * * write_track() -- output subroutine * * ---------------------------------------------------------------- */ write_track DS 0H STM re,r8,wt_save LTR r8,r1 0 means finish up BZ wt_finish LM re,rf,0(r8) load addr, length LTR rf,rf do nothing for null tracks BZ wt_return USING ha,re SLR r1,r1 calculate track number from ha ICM r1,3,ha_cc M r0,trks_per_cyl SLR r2,r2 ICM r2,3,ha_hh AR r2,r1 DROP re * get pos of level 2 table L r3,vdhdr_addr USING VDHDR,r3 LR r4,r2 SRL r4,8 lvl 1 tab index SLL r4,2 lvl 1 tab entry len is 4 LA r4,VDH_l1tab(r4) addr lvl 2 tab pos in lvl 1 tab DROP r3 LLE r3,0(r4) lvl 2 tab pos LTR r3,r3 does lvl 2 tab exist BNZ wt_l2t_ok yes, continue * level 2 table doesn't exist yet; build one L r0,bytes_ovh update AL r0,=A(256*L'L2TAB_entry) overhead ST r0,bytes_ovh total * get pos range of the new level 2 table L r3,out_pos load current pos STLE r3,0(r4) update lvl 1 pos LR r4,r3 calculate next pos AL r4,=A(256*L'L2TAB_entry) ST r4,out_pos set next available pos * set buffer for rewrite [if it already isn't] L r5,last_rw see if buf set for rewrite USING rw_ent,r5 CLC rw_pos,out_buf_pos BE wt_l2t_1 yes, continue LA r5,rw_next try next entry CLC rw_pos,out_buf_pos BE wt_l2t_1 yes, continue L r5,next_rw no, set this buf for rewrite MVC rw_pos,out_buf_pos MVC rw_buf,out_buf LA r0,rw_next ST r0,next_rw set next available rewrite entry wt_l2t_1 ST r5,last_rw update last rewrite entry addr * if the table fills this buffer then write it out LR r0,r4 copy next pos N r0,=A(x'ffffc000') convert to buf pos CL r0,out_buf_pos need to write this buf ? BE wt_l2t_ok no, continue L r6,out_buf write the current buf WRITE outdecb,SF,outdcb,(r6),MF=E CHECK outdecb NOTE outdcb note its file position ST r1,rw_ttr STORAGE OBTAIN,LENGTH=16384,BNDRY=PAGE L r0,out_bufsz AL r0,=A(16384) ST r0,out_bufsz LR r6,r1 ST r6,out_buf new output buf LR r0,r6 clear the buf L r1,=A(16384) SLR rf,rf MVCL r0,re L r1,out_buf_pos load previous buf pos AL r1,=A(16384) set new buf pos ST r1,out_buf_pos set new buf pos * if the table spans into the new buf then set it for rewrite CLR r4,r1 new pos same as new buf pos ? BE wt_l2t_ok yes, table didn't span L r5,next_rw get a new rewrite entry ST r1,rw_pos set buf pos ST r6,rw_buf set buf addr LA r5,rw_next ST r5,next_rw set next available rewrite entry DROP r5 wt_l2t_ok DS 0H r3 has lvl 2 tab pos * build the lvl 2 entry in a work area * (this is necessary because the entry might span buffers) w USING L2TAB,dw XC w.L2TAB_entry,w.L2TAB_entry L r1,out_pos get next available pos STLE r1,w.L2TAB_pos set pos for trk image L r1,4(,r8) get length of trk image STHLE r1,w.L2TAB_size set size of the area STHLE r1,w.L2TAB_len set length of the trk image DROP w * get address of the lvl 2 entry SLL r2,24 shift out all but low 8 bits SRL r2,21 shift back but multiplied by 8 AR r2,r3 have pos for lvl 2 tab entry LR rf,r2 N rf,=A(x'ffffc000') pos of buf for this entry L r4,last_rw find the rewrite entry USING rw_ent,r4 CL rf,rw_pos BE wt_l2t_2 found the entry LA r4,rw_next else try the next entry CL rf,rw_pos BNE wt_logic_err not good wt_l2t_2 L rf,rw_buf load buf addr for this entry N r2,=A(x'00003fff') get buf offset from pos AR r2,rf now have addr of lvl 2 entry * copy the work entry to the actual entry USING L2TAB,r2 A rf,=A(16384) calculate length SR rf,r2 left in this buf CH rf,=Y(8) check length to copy BNH *+8 LA rf,8 BCTR rf,0 decrement for EX EX rf,wt_l2t_mvc copy the entry LA re,6 calculate length-1 SR re,rf to copy BM wt_l2t_x exit if finished LA rf,dw+1(rf) source address LA r4,rw_next to next rewrite entry L r2,rw_buf target addr (start of next buf) EX re,wt_l2t_mvc2 copy the rest B wt_l2t_x wt_l2t_mvc MVC L2TAB_entry(0),dw wt_l2t_mvc2 MVC L2TAB_entry(0),0(rf) DROP r4,r2 wt_l2t_x DS 0H lvl 2 tab entry built * copy the track image LM r4,r5,0(r8) source addr, length wt_data LTR r5,r5 anything left to copy ? BZ wt_return no, return L r2,out_pos get current pos N r2,=A(x'00003fff') convert to buf offset L r3,out_buf get current buf addr ALR r2,r3 now have target addr AL r3,=A(16384) calculate target length SLR r3,r2 CLR r3,r5 check lengths BNH *+6 and set target length LR r3,r5 to the shortest LR r1,r3 save target length MVCL r2,r4 copy L r2,out_pos get old pos ALR r2,r1 new pos ST r2,out_pos set new pos L r3,out_buf_pos load current buf pos N r2,=A(x'ffffc000') new buf pos CLR r2,r3 is current buf full ? BE wt_data no [but r5 should be 0] ST r2,out_buf_pos set new buf pos L r6,out_buf write the buffer WRITE outdecb,SF,outdcb,(r6),MF=E CHECK outdecb LR r1,r6 copy old buf addr L r6,last_rw check for old buf rewrite USING rw_ent,r6 CL r3,rw_pos BE wt_data_1 yes ... get new buf LA r6,rw_next CL r3,rw_pos BNE wt_data_2 no ... use old buf wt_data_1 NOTE outdcb note disk addr for old buf ST r1,rw_ttr DROP r6 STORAGE OBTAIN,LENGTH=16384,BNDRY=PAGE L r0,out_bufsz AL r0,=A(16384) ST r0,out_bufsz ST r1,out_buf new buf wt_data_2 LR r0,r1 clear the buf L r1,=A(16384) SLR rf,rf MVCL r0,re B wt_data wt_return LM re,r8,wt_save return BR re */* ---------------------------------------------------------------- * * write_track() finish * * - set free space and write last buffer(s) * * - close & reopen in updat mode * * - rewrite buffers in the rewrite queue * * - close & return * * ---------------------------------------------------------------- */ wt_finish DS 0H * unused space at the end is free space L r2,out_pos get next available pos N r2,=A(x'00003fff') convert to buf offset BZ wt_fsp_ok if zero then no free space L r3,=A(16384) calculate length of free space SLR r3,r2 on current block LR r4,r3 copy CH r4,=Y(8) minimum free space is 8 bytes BNL *+8 otherwise we need AL r4,=A(16384) another block ST r4,bytes_free remember free space XC dw,dw build the free entry in a work STLE r4,dw+4 area since we may span buffers AL r2,out_buf get addr of free space CH r3,=Y(8) check length left BNH *+8 jumps if not too long LA r3,8 else reset BCTR r3,0 decrement for ex EX r3,wt_fsp_mvc copy the free space entry LA r4,dw+1(r3) resume copy from here LA r5,6 calculate length-1 left to copy SR r5,r3 negative if all copied * write the last buffer(s) wt_fsp_wr L r6,out_buf write the buffer WRITE outdecb,SF,outdcb,(r6),MF=E CHECK outdecb LR r1,r6 copy old buf addr L r3,out_buf_pos get buffer pos L r6,last_rw check for old buf rewrite USING rw_ent,r6 CL r3,rw_pos BE wt_fsp_1 yes ... get new buf LA r6,rw_next CL r3,rw_pos BNE wt_fsp_2 no ... use old buf wt_fsp_1 NOTE outdcb note disk addr for old buf ST r1,rw_ttr DROP r6 STORAGE OBTAIN,LENGTH=16384,BNDRY=PAGE L r0,out_bufsz AL r0,=A(16384) ST r0,out_bufsz ST r1,out_buf new buf wt_fsp_2 AL r3,=A(16384) new buf pos ST r3,out_buf_pos set new pos LR r0,r1 clear the buf L r1,=A(16384) SLR rf,rf MVCL r0,re LTR r5,r5 more to copy ? BM wt_fsp_ok no, continue L r2,out_buf get target addr EX r5,wt_fsp_mvc2 copy the rest of the entry SLR r5,r5 make r5 negative BCTR r5,0 to terminate the loop B wt_fsp_wr go write wt_fsp_mvc MVC 0(0,r2),dw wt_fsp_mvc2 MVC 0(0,r2),0(r4) wt_fsp_ok DS 0H last block has been written * update the header L r2,vdhdr_addr USING VDHDR,r2 USING CCKDDASD_DEVHDR,VDH_devhdr2 L re,out_buf_pos STLE re,CCKD_size set file size L rf,out_pos STLE rf,CCKD_used set bytes used L r0,bytes_free STLE r0,CCKD_free_total set total free space STLE r0,CCKD_free_largest set largest free space LTR r0,r0 any free space ? BZ wt_hd2_ok no, continue STLE rf,CCKD_free set offset to free entry LA r1,1 STLE r1,CCKD_free_number set number free entries DROP r2 wt_hd2_ok DS 0H * close the file and open in update mode CLOSE outdcb,MF=(E,openl24) #MSG 1,'file SYSUT2 closed for output' o USING IHADCB,outdcb OPEN (o.IHADCB,UPDAT),MF=(E,openl24) TM o.DCBOFLGS,DCBOFOPN BNO out_open_err #MSG 1,'file SYSUT2 opened for update' * update the noted buffers L r2,rw_area USING rw_ent,r2 L r3,out_buf buffer for read/write wt_update C r2,next_rw at end of entries ? BNL wt_upd_ok yes, exit POINT outdcb,rw_ttr position the file READ outdecb,SF,outdcb,(r3),MF=E CHECK outdecb LR r0,r3 copy the rewrite buf L r1,=A(16384) L re,rw_buf LR rf,r1 MVCL r0,re WRITE outdecb,SF,outdcb,(r3),MF=E CHECK outdecb L r1,rw_buf free the buf STORAGE RELEASE,ADDR=(1),LENGTH=16384 LA r2,rw_next point to the next entry B wt_update loop back wt_upd_ok CLOSE outdcb,MF=(E,openl24) STORAGE RELEASE,ADDR=(r3),LENGTH=16384 LM r1,r2,rw_area free stuff STORAGE RELEASE,ADDR=(1),LENGTH=(r2) #MSG 1,'file SYSUT2 closed for update' B wt_return */* ------------------------------------------------------ SOMITCW * * subroutine to check if dsn is in the include or SOMITCW * * exclude list. SOMITCW * * r0 points to the dsname from the vtoc on entry SOMITCW * * rf points to the dsname from the vtoc for compare SOMITCW * * r1 points to the first list entry SOMITCW * * A(next-entry-address) SOMITCW * * XL1'EX-CLC-compare-length' SOMITCW * * CL44'dsn-or-dsn-prefix' SOMITCW * * r2 is the length for the EX of the CLC instruction SOMITCW * * rf will have 0 if dsname found, otherwise 4 SOMITCW * * ---------------------------------------------------- */ SOMITCW * SOMITCW chk_dsn_list DS 0H SOMITCW LR rf,r0 Copy DS1-DSNAME for addressing SOMITCW cdl_loop DS 0H SOMITCW IC r2,4(,r1) Load length for EX of CLC SOMITCW EX r2,cdl_CLC See if the data set name found SOMITCW BE cdl_ret0 Data set in list, go return SOMITCW ICM r1,B'1111',0(r1) Link to the next entry SOMITCW BZ cdl_ret4 End of list, return dsn not found SOMITCW B cdl_loop Go back to try next list entry SOMITCW cdl_ret4 LA rf,4 Indicate that dsname not found SOMITCW BR re Return to caller SOMITCW cdl_ret0 SLR rf,rf Indicate that dsname was found SOMITCW cdl_ret BR re Return to caller SOMITCW cdl_CLC CLC 0(0,rf),5(r1) See if the dsn is in list SOMITCW */* ---------------------------------------------------------------- * * subroutine to convert a 10 byte vtoc extent descriptor [r1] * * to starting track [r0] and number tracks [r1] * * ---------------------------------------------------------------- */ cnv_xtnt STM r2,r5,cnv_xtnt_save SLR r3,r3 calculate ending extent ICM r3,3,6(r1) M r2,trks_per_cyl AH r3,8(,r1) SLR r5,r5 calculate beginning extent ICM r5,3,2(r1) M r4,trks_per_cyl AH r5,4(,r1) LR r0,r5 SR r3,r5 LA r1,1(,r3) LM r2,r5,cnv_xtnt_save BR re */* ---------------------------------------------------------------- * * subroutine to convert a 5 byte vtoc pointer [r1] * * to an address in the vtoc area [r1] * * ---------------------------------------------------------------- */ cnv_ptr STM r2,r5,cnv_ptr_save f4 USING IECSDSL4-44,dscb4 SLR r3,r3 calculate vtoc starting trk ICM r3,3,f4.DS4VTOCE+2 M r2,trks_per_cyl SLR r2,r2 ICM r2,3,f4.DS4VTOCE+4 AR r3,r2 SLR r5,r5 calculate dscb trk ICM r5,3,0(r1) M r4,trks_per_cyl AH r5,2(,r1) SR r5,r3 have relative trk M r4,dscbs_per_trk SLR r3,r3 IC r3,4(,r1) AR r5,r3 now have relative dscb BCTR r5,0 M r4,=A(DS1END-IECSDSF1) L r6,vtoc_area LA r1,0(r5,r6) LM r2,r6,cnv_ptr_save BR re DROP f4 */* ---------------------------------------------------------------- * * subroutine to populate the track vector table * * * * r1 - pointer to extent descriptor (incremented) * * r2 - nbr extents left (decremented) * * r3 - -1 or last relative track (decremented) * * r4 - dsn entry address * * * * ---------------------------------------------------------------- */ upd_trk_vec SAVE (14,12) USING dsn_area,r4 LA rf,4 LTR r2,r2 exit if no extents left BNP utvret BCTR r2,0 LTR r3,r3 exit if lstar is zero BZ utvret LA r5,10(,r1) BAL re,cnv_xtnt LR r6,r0 SLL r6,2 AL r6,trk_vec L r7,dsn_trks_dump utvloop ST r4,0(,r6) LA r7,1(,r7) LTR r3,r3 BM utvnext SH r3,=Y(1) BNP utvexit utvnext LA r6,4(,r6) BCT r1,utvloop SLR rf,rf utvexit ST r7,dsn_trks_dump LR r1,r5 utvret STM r1,r3,24(rd) RETURN (14,12),RC=(15) DROP r4 */* ---------------------------------------------------------------- * * retrieve options * * ---------------------------------------------------------------- */ getopts DS 0H MVI opts,COMPRESSION MVC compr_level,=A(CCKD_DEFAULT_COMPRESSION) For this JOB MVC cckd_compr_level,=A(Z_DEFAULT_COMPRESSION) In CCKD disk MVC cckd_compr,=A(CCKD_COMPRESS_ZLIB) */* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - SOMITCW * * See if a SYSIN file SOMITCW * * - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ SOMITCW * SOMITCW * Locate Task I/O Table SOMITCW MVC extract,model_extract Move MF=L EXTRACT MACRO SOMITCW EXTRACT tiot_addr,'S',FIELDS=TIOT,MF=(E,EXTRACT) SOMITCW L rf,tiot_addr SOMITCW LA r1,24 Bump past JOB, STEP, PROCSTEP names SOMITCW in_tiot DS 0H SOMITCW AR rf,r1 Bump to next TIOT entry SOMITCW ICM r1,b'0001',0(rf) Load length of TIOT entry SOMITCW BZR r9 No SYSIN, take all defaults SOMITCW * CLC in.DCBDDNAM,4(rf) See if the SYSIN entry SOMITCW CLC model_indcb+DCBDDNAM-IHADCB(8),4(rf) See if SYSIN entry SOMITCW BNE in_tiot Not SYSIN, go check next TIOT entry SOMITCW * SOMITCW */* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - SOMITCW * * try to open SYSIN file SOMITCW * * - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ SOMITCW * SOMITCW MVC indcb,model_indcb SOMITCW MVC indcbe,model_indcbe SOMITCW in USING IHADCB,indcb SOMITCW LA r1,indcbe SOMITCW ST r1,in.DCBDCBE SOMITCW * SYSIN exists, OPEN it SOMITCW * * A list entry will be built for each exclude record SOMITCW * * Format of each list entry will be: SOMITCW * * A(next-entry-address) SOMITCW * * XL1'EX-CLC-compare-length' SOMITCW * * CL44'dsn-or-dsn-prefix' SOMITCW * * r2 will contain the address of the previous list entry, SOMITCW * * to link the new list entry to the previous. SOMITCW MVC openl,model_openl Insure unused bits are zero SOMITCW OPEN (in.IHADCB,INPUT),MODE=31,MF=(E,openl) SOMITCW TM in.DCBOFLGS,DCBOFOPN See if SYSIN OPENed SOMITCW BZ X'081B'(rb) Abend S0C6 if OPEN failed SOMITCW LA R2,dsn_excl_list Load address of list anchor SOMITCW in_get DS 0h SOMITCW GET in.IHADCB Read a record SOMITCW MVC in_rec,0(r1) Store record for display SOMITCW #MSG 1,'SYSIN Read: %s:71',in_rec Display the record SOMITCW CLI in_rec,C'*' See if a comment SOMITCW BE in_get Is comment, don't process SOMITCW CLC =Cl8'EXCLUDE ',in_rec See if an exclude SOMITCW BNE ut1_bad_sysin Not an exclude, go abend SOMITCW GETMAIN RU,LV=49 Get memory for a list entry SOMITCW XC 0(4,r1),0(r1) Clear link addr.in GETMAINed area SOMITCW ST r1,0(,r2) Link to the old list entry SOMITCW LR rf,r1 Load the new list entry address SOMITCW CLI in_rec+8,X'40' See if a data set name SOMITCW BE ut1_bad_sysin No data set name, go abend SOMITCW MVC 5(44,rf),in_rec+8 Save entire possible dsname SOMITCW TRT in_rec+8(44),in_trt_table find space or asterisk SOMITCW BZ in_full44 Full data set name, go store SOMITCW LA r2,in_rec+8 Load address of start of dsname SOMITCW CLI 0(r1),X'40' See if a space found SOMITCW BE in_dsn_found Dsn found, go add to list SOMITCW in_prefix_found DS 0H SOMITCW BCTR r1,0 Drop the asterisk byte for prefix SOMITCW in_dsn_found DS 0H SOMITCW *already LA r2,in_rec+8 Load address of start of dsname SOMITCW SR r1,r2 Find the length of the dsname SOMITCW STC r1,4(,rf) Store the length for compare SOMITCW in_next DS 0H SOMITCW LR r2,rf Restore list entry address SOMITCW B in_get Go get the next record SOMITCW in_full44 DS 0H SOMITCW MVI 4(rf),x'43' Store EX length of data set name SOMITCW B in_next Go get next SYSIN record SOMITCW in_exit DS 0H SOMITCW CLOSE in.IHADCB,MODE=31,MF=(E,openl) SOMITCW BR r9 SYSIN processed, return to caller SOMITCW * BR re Deleted SOMITCW */* ---------------------------------------------------------------- * * fatal errors * * ---------------------------------------------------------------- */ ut1_bad_sysin DS 0H SOMITCW LR r2,r1 Save bad sysin record SOMITCW #MSG 3,'Bad record on SYSIN, must start with "EXCLUDE dsn"' SOMITCW B abend SOMITCW ut1_devt_err DS 0H STM rf,r0,retcode #MSG 3,'DEVTYPE failed for SYSUT1; RC=%x reason %x', x retcode,rsncode B abend out_devt_err DS 0H STM rf,r0,retcode #MSG 3,'DEVTYPE failed for SYSUT2; RC=%x reason %x', x retcode,rsncode B abend ut1_not_dasd DS 0H #MSG 3,'SYSUT1 is not a disk device' B abend out_not_dasd DS 0H #MSG 3,'SYSUT2 is not a disk device' B abend ut1_not_eckd DS 0H #MSG 3,'SYSUT1 is not an eckd disk device' B abend ut1_rdjfcb_err DS 0H ST rf,retcode #MSG 3,'RDJFCB failed for SYSUT1; RC=%x',retcode B abend ut1_vtoc_open_err DS 0H #MSG 3,'OPEN failed for SYSUT1 vtoc on %s',volser B abend out_open_err DS 0H #MSG 3,'OPEN failed for SYSUT2' B abend ut1_dscb4_err DS 0H ST rf,retcode c USING CVPL,cvpl_area #MSG 3,'Error processing format 4 dscb on %s; RC=%x CVSTAT=%dx :1',volser,retcode,c.CVSTAT B abend DROP c ut1_cvaf_err ABEND 6 ST rf,retcode c USING CVPL,cvpl_area #MSG 3,'CVAF error reading %s vtoc; RC=%x CVSTAT=%d:1', x volser,retcode,c.CVSTAT B abend DROP c ut1_excp_open_err DS 0H #MSG 3,'EXCP OPEN failed for SYSUT1 on %s',volser B abend ut1_io_err DS 0H #MSG 3,'EXCP I/O error for SYSUT1 on %s',volser B abend wt_logic_err DS 0H #MSG 3,'logic error writing track',volser B abend abend ABEND 99,DUMP */* ---------------------------------------------------------------- * * literals and constants * * ---------------------------------------------------------------- */ LTORG , WXTRN EDCXHOTL,EDCXHOTU,EDCXHOTT,COMPRESS PRINT GEN Was NOGEN SOMITCW model_extract EXTRACT *-*,'S',FIELDS=TIOT,MF=L SOMITCW model_extract_l EQU *-model_extract SOMITCW model_indcb DCB DDNAME=SYSIN,DSORG=PS,MACRF=GL,DCBE=0 SOMITCW model_indcb_l EQU *-model_indcb SOMITCW model_indcbe DCBE RMODE31=BUFF,EODAD=in_exit SOMITCW model_indcbe_l EQU *-model_indcbe SOMITCW model_prdcb DCB DDNAME=SYSPRINT,DSORG=PS,MACRF=PL,DCBE=0 model_prdcb_l EQU *-model_prdcb model_prdcbe DCBE RMODE31=BUFF model_prdcbe_l EQU *-model_prdcbe model_vtdcb DCB DDNAME=SYSUT1,DSORG=PS,MACRF=R model_vtdcb_l EQU *-model_vtdcb model_exdcb DCB DDNAME=SYSUT1,DSORG=DA,MACRF=E model_exdcb_l EQU *-model_exdcb model_outdcb DCB DDNAME=SYSUT2,DSORG=PS,MACRF=(RP,WP), x RECFM=F,BLKSIZE=16384,LRECL=16384 model_outdcb_l EQU *-model_outdcb model_openl OPEN (0),MODE=31,MF=L model_openl_l EQU *-model_openl model_openl24 OPEN (0),MODE=31,MF=L model_openl24_l EQU *-model_openl24 model_devtl DEVTYPE ,,INFOLIST=devt_infol_1,MF=L model_devtl_l EQU *-model_devtl devt_infol_1 DEVTYPE INFO=DEVTYPE devt_infol_2 DEVTYPE INFO=(DEVTYPE,DASD) model_cvpl CVAFSEQ MF=L model_cvpl_l EQU *-model_cvpl model_trkcalcl TRKCALC MF=L model_trkcalcl_l EQU *-model_trkcalcl * e2aTAB DS 0D Deleted SOMITCW * 0 1 2 3 4 5 6 7 8 9 a b c d e f Deleted SOMITCW * DC X'00010203 1A091A7F 1A1A1A0B 0C0D0E0F' 0 Deleted SOMITCW * DC X'10111213 1A0A081A 18191A1A 1C1D1E1F' 1 Deleted SOMITCW * DC X'1A1A1C1A 1A0A171B 1A1A1A1A 1A050607' 2 Deleted SOMITCW * DC X'1A1A161A 1A1E1A04 1A1A1A1A 14151A1A' 3 Deleted SOMITCW * DC X'20A6E180 EB909FE2 AB8B9B2E 3C282B7C' 4 Deleted SOMITCW * DC X'26A9AA9C DBA599E3 A89E2124 2A293B5E' 5 Deleted SOMITCW * DC X'2D2FDFDC 9ADDDE98 9DACBA2C 255F3E3F' 6 Deleted SOMITCW * DC X'D78894B0 B1B2FCD6 FB603A23 40273D22' 7 Deleted SOMITCW * DC X'F8616263 64656667 686996A4 F3AFAEC5' 8 Deleted SOMITCW * DC X'8C6A6B6C 6D6E6F70 71729787 CE93F1FE' 9 Deleted SOMITCW * DC X'C87E7374 75767778 797AEFC0 DA5BF2F9' a Deleted SOMITCW * DC X'B5B6FDB7 B8B9E6BB BCBD8DD9 BF5DD8C4' b Deleted SOMITCW * DC X'7B414243 44454647 4849CBCA BEE8ECED' c Deleted SOMITCW * DC X'7D4A4B4C 4D4E4F50 5152A1AD F5F4A38F' d Deleted SOMITCW * DC X'5CE75354 55565758 595AA085 8EE9E4D1' e Deleted SOMITCW * DC X'30313233 34353637 3839B3F7 F0FAA7FF' f Deleted SOMITCW in_trt_table DC 256Xl1'0' Table to find end of dsname SOMITCW ORG in_trt_table+X'40' Back up the location counter SOMITCW DC XL1'40' Overlay the space position SOMITCW ORG , Set the location counter to normal SOMITCW ORG in_trt_table+X'5C' Back up the location counter SOMITCW DC XL1'5C' Overlay the asterisk position SOMITCW ORG , Set the location counter to normal SOMITCW PRINT GEN DROP , */* ---------------------------------------------------------------- * * subroutine to issue messages * * ---------------------------------------------------------------- */ USING msg_rtn,rc USING vdw,rd USING vdw24,ra msg_rtn STM re,rc,mr_save LR rc,rf LA r8,prdcb USING IHADCB,r8 TM DCBOFLGS,DCBOFOPN BNO mr_ret return if no message file LM r4,r5,0(r1) pattern addr, length BCTR r5,0 LA r3,8(,r1) first parameter LA r6,msg MVI msg,C' ' init msg to blanks MVC msg+1(L'msg-1),msg mr_loop LTR r5,r5 BM mr_exit LA r1,1(r4,r5) SLR r2,r2 EX r5,mr_trt1 SR r1,r4 length scanned BNP mr_skip1 LR rf,r1 BCTR rf,0 EX rf,mr_mvc1 copy literal text AR r6,r1 mr_skip1 AR r4,r1 SR r5,r1 BM mr_exit BP mr_skip2 MVC 0(1,r6),0(r4) string ends in special char LA r6,1(,r6) B mr_exit mr_skip2 B *(r2) br on special char type B mr_pct '%' B mr_bs '\' mr_pct CLI 1(r4),C's' BE mr_pct_s CLI 1(r4),C'x' BE mr_pct_x CLI 1(r4),C'd' BE mr_pct_d MVC 0(1,r6),0(r4) tread '%' as any other char LA r6,1(,r6) LA r4,1(,r4) BCTR r5,0 B mr_loop mr_pct_s L r7,0(,r3) load string ptr LA r3,4(,r3) LA r4,2(,r4) point past '%s' SH r5,=Y(2) BAL re,mr_op r1 - target len, r2 - source len LTR r2,r2 BNZ mr_pct_s3 LR r2,r7 source len = 0, find end of string mr_pct_s1 CLI 0(r2),C' ' BNH mr_pct_s2 LA r2,1(,r2) B mr_pct_s1 mr_pct_s2 SR r2,r7 BNP mr_loop mr_pct_s3 LR rf,r2 copy source string to the msg BCTR rf,0 EX rf,mr_mvc2 LTR r1,r1 BNZ mr_pct_s5 AR r6,r2 truncate trailing spaces if mr_pct_s4 BCTR r6,0 target len is 0 CLI 0(r6),C' ' BNH mr_pct_s4 LA r6,1(,r6) B mr_loop mr_pct_s5 CR r1,r2 BH mr_pct_s6 AR r6,r1 truncate the string B mr_loop mr_pct_s6 AR r6,r2 pad string with trailing blanks SR r1,r2 mr_pct_s7 MVI 0(r6),C' ' LA r6,1(,r6) BCT r1,mr_pct_s7 B mr_loop mr_pct_x L r7,0(,r3) load hex ptr LA r3,4(,r3) LA r4,2(,r4) point past '%x' SH r5,=Y(2) BAL re,mr_op r1 - target len, r2 - source len LTR r2,r2 BNZ *+8 LA r2,4 default source len is 4 EX r2,mr_pct_x_unpk TR dw,mr_hextab LTR r1,r1 BNZ mr_pct_x1 LA r1,8 determine default target len CLC =C'00',dw BNE mr_pct_x1 LA r1,6 CLC =C'0000',dw BNE mr_pct_x1 LA r1,4 CLC =C'000000',dw BNE mr_pct_x1 LA r1,2 mr_pct_x1 LA r7,dw+8 copy the hex string to the msg SR r7,r1 BCTR r1,0 EX r1,mr_mvc2 LA r6,1(r1,r6) B mr_loop mr_pct_d L r7,0(,r3) load decimal ptr LA r3,4(,r3) LA r4,2(,r4) point past '%d' SH r5,=Y(2) BAL re,mr_op r1 - target len, r2 - source len LTR r2,r2 BNZ *+8 LA r2,4 default source len is 4 LA rf,4 SR rf,r2 LA re,15 SRL re,0(rf) EX re,mr_pct_d_icm CVD rf,dw MVC dw2(16),=X'40202020202020202020202020202120' ED dw2(16),dw LTR r1,r1 BNZ mr_pct_d2 LA rf,dw2+16 default length - mr_pct_d1 BCTR rf,0 truncate leading spaces CLI 0(rf),C' ' BH mr_pct_d1 LA r1,dw2+15 SR r1,rf mr_pct_d2 LA r7,dw2+16 SR r7,r1 BCTR r1,0 EX r1,mr_mvc2 LA r6,1(r1,r6) B mr_loop mr_bs MVC 0(1,r6),1(r4) copy char following '\' LA r6,1(,r6) LA r4,2(,r4) SH r5,=Y(2) B mr_loop mr_exit LA r1,msg SR r6,r1 calculate msg length BNP mr_ret TM DCBRECFM,DCBRECCA+DCBRECCM BZ *+8 LA r6,1(,r6) increment for carriage control TM DCBRECFM,DCBRECU BO mr_u TM DCBRECFM,DCBRECF BO mr_f TM DCBRECFM,DCBRECV BO mr_v mr_u CH r6,DCBBLKSI BNH *+8 LH r6,DCBBLKSI STH r6,DCBLRECL PUT IHADCB TM DCBRECFM,DCBRECCA+DCBRECCM BZ mr_u1 MVI 0(r1),C' ' LA r1,1(,r1) BCTR r6,0 TM DCBRECFM,DCBRECCA BO mr_u1 BCTR r1,0 MVI 0(r1),X'09' LA r1,1(,r1) mr_u1 BCTR r6,0 EX r6,mr_mvc3 B mr_ret mr_f CH r6,DCBLRECL BNH *+8 LH r6,DCBLRECL PUT IHADCB TM DCBRECFM,DCBRECCA+DCBRECCM BZ mr_f1 MVI 0(r1),C' ' LA r1,1(,r1) BCTR r6,0 TM DCBRECFM,DCBRECCA BO mr_f1 BCTR r1,0 MVI 0(r1),X'09' LA r1,1(,r1) mr_f1 BCTR r6,0 EX r6,mr_mvc3 B mr_ret mr_v LA r6,4(,r6) LH r1,DCBBLKSI SH r1,=Y(4) CR r6,r1 BNH *+6 LR r6,r1 STH r6,DCBLRECL PUT IHADCB STH r6,0(,r1) XC 2(2,r1),2(r1) LA r1,4(,r1) SH r6,=Y(4) TM DCBRECFM,DCBRECCA+DCBRECCM BZ mr_v1 MVI 0(r1),C' ' LA r1,1(,r1) BCTR r6,0 TM DCBRECFM,DCBRECCA BO mr_v1 BCTR r1,0 MVI 0(r1),X'09' LA r1,1(,r1) mr_v1 BCTR r6,0 EX r6,mr_mvc3 mr_ret LM re,rc,mr_save BR re DROP r8 */* ---------------------------------------------------------------- * * message subroutine to get operand lengths * * ---------------------------------------------------------------- */ mr_op SLR r1,r1 SLR r2,r2 mr_op1 LTR r5,r5 first number is target length BMR re CLI 0(r4),C'0' BL mr_op2 IC rf,0(,r4) N rf,=A(X'0000000f') MH r1,=Y(10) AR r1,rf LA r4,1(,r4) BCTR r5,0 B mr_op1 mr_op2 CLI 0(r4),C':' second number follows a ':' BNER re mr_op3 LA r4,1(,r4) second number is source length SH r5,=Y(1) BMR re CLI 0(r4),C'0' BLR re IC rf,0(,r4) N rf,=A(X'0000000f') MH r2,=Y(10) AR r2,rf B mr_op3 */* ---------------------------------------------------------------- */ mr_mvc1 MVC 0(0,r6),0(r4) mr_trt1 TRT 0(0,r4),mr_tab1 mr_mvc2 MVC 0(0,r6),0(r7) mr_mvc3 MVC 0(0,r1),msg mr_pct_x_unpk UNPK dw(9),0(0,r7) mr_pct_d_icm ICM rf,0,0(r7) mr_tab1 DC XL256'0' ORG mr_tab1+C'%' DC AL1(4) ORG mr_tab1+C'\' DC AL1(8) ORG mr_tab1+256 mr_hextab EQU *-240 DC C'0123456789abcdef' do_stats BR 14 LTORG , */* ---------------------------------------------------------------- * * messages * * ---------------------------------------------------------------- */ #MSG TYPE=GEN */* ---------------------------------------------------------------- * * dynamic storage * * ---------------------------------------------------------------- */ vdw DSECT id DS 0CL4'vdw' save DS 18F cnv_xtnt_save DS 8F savearea for cnv_xtnt cnv_ptr_save DS 8F savearea for cnv_ptr wt_save DS 12F savearea for write_track mr_save DS 16F savearea for msg_rtn vdw_31 DS A addr this area vdw_24 DS A addr 24 bit area opts DS X ALLTRKS EQU X'80' dump all tracks ALLDATA EQU X'40' dump all data in datasets COMPRESSION EQU X'20' compress dumped data DONTCOMPRESS EQU X'10' explicitly don't compress msglvl DS X volser DS CL6 retcode DS F rsncode DS F dw DS D dw2 DS D dw3 DS D dw4 DS D trks DS F total number tracks trks_dump DS F total number tracks to dump trk_size DS F max track size trk_vec DS A vector of trks to dump trk_vec_size DS F dscbs_per_trk DS F number dscbs per track vtoc_trks DS F number tracks in vtoc total_dscbs DS F number dscbs in vtoc vtoc_area DS A addr of area to hold all dscbs vtoc_size DS F size of area to hold all dscbs last_f1_dscb DS A addr last format 1 dscb dsn_nbr DS F nbr datasets on volume tiot_addr DS A Address of the Task I/O Table SOMITCW in_rec DS CL80 Input record for display SOMITCW dsn_area_addr DS A dsn_area_size DS A dsn_incl_list DS A dsn_excl_list DS A excp_io_area DS A excp_io_size DS F compr_area DS A compr_size DS F compr_used DS F compr_level DS F cckd_compr DS F cckd_compr_level DS F Z_NO_COMPRESSION EQU 0 Z_BEST_SPEED EQU 1 Z_BEST_COMPRESSION EQU 9 Z_DEFAULT_COMPRESSION EQU -1 CCKD_DEFAULT_COMPRESSION EQU 3 out_buf DS A current output buf addr out_buf_pos DS F pos for current buf out_bufsz DS F total buf size used for output vdhdr_addr DS A buf addr containing VDHDR out_pos DS F current available pos rw_area DS A rewrite area addr rw_size DS F size of rewrite area last_rw DS A addr last used entries next_rw DS A next available entry trk_addr DS A trk_sz DS F ctrk_addr DS A ctrk_sz DS F bytes_read DS 2F bytes_written DS 2F bytes_ovh DS F bytes_free DS F handle DS F msgl DS 16F extract DS XL(model_extract_l) SOMITCW indcbe DS XL(model_indcbe_l) SOMITCW prdcbe DS XL(model_prdcbe_l) openl DS XL(model_openl_l) devtl DS XL(model_devtl_l) devta DS XL(32) cyls EQU devta+4,4 trks_per_cyl EQU devta+8,4 dev_flags EQU devta+12,2 trkcalcl DS XL(model_trkcalcl_l) zlib_pl DS 8F dscb4 DS XL(DS1END-IECSDSF1) msg DS CL256 cvpl_area DS XL(model_cvpl_l) bflh DS XL(BFLHLN) bflent DS 256XL(BFLELN) bfle_arg DS XL(L'BFLEARG) vdw_len EQU *-vdw vdw24 DSECT , id24 DS CL4'vdw24' openl24 DS XL(model_openl24_l) exlst DS F indcb DS XL(model_indcb_l) SOMITCW prdcb DS XL(model_prdcb_l) vtdcb DS XL(model_vtdcb_l) exdcb DS XL(model_exdcb_l) READ outdecb,SF,MF=L outdcb DS XL(model_outdcb_l) jfcb DS XL(JFCBLGTH) excp_ecb DS F DS 0D lr_parms DS XL16 excp_iob DS XL40 excp_ccws DS XL256 vdw24_len EQU *-vdw24 dsn_area DSECT dsn_name DS CL44 dsn_flag DS F dsn_not_incl EQU X'80' dsn_excl EQU X'40' dsn_extents DS F dsn_trks DS F dsn_trks_dump DS F dsn_bytes_read DS 2F dsn_bytes_written DS 2F dsn_next DS 0F dsn_area_len EQU *-dsn_area lr_parm_area DSECT , locate record parameter area lr_op DS X operation byte lr_orient_count EQU B'00000000' lr_orient_home EQU B'01000000' lr_orient_data EQU B'10000000' lr_orient_index EQU B'11000000' lr_orient EQU X'00' lr_write_data EQU X'01' lr_format_write EQU X'03' lr_read_data EQU X'06' lr_write_track EQU X'0b' lr_read_tracks EQU X'0c' lr_read EQU X'16' lr_aux DS X auxiliary byte lr_use_tlf EQU B'10000000' lr_read_count_ccw EQU B'00000001' DS X lr_count DS X count parameter lr_seek_addr DS 0XL4 seek addr lr_seek_addr_cc DS XL2 lr_seek_addr_hh DS XL2 lr_search_arg DS 0XL5 search arg lr_search_arg_cc DS XL2 lr_search_arg_hh DS XL2 lr_search_arg_r DS X lr_sector DS X lr_tlf DS XL2 transfer length factor lr_parms_l EQU *-lr_parm_area count DSECT , count area descriptor count_cchhr DS 0XL5 record address count_cchh DS 0XL4 record address count_cc DS XL2 count_hh DS XL2 count_r DS X count_key DS X key length count_data DS XL2 data length count_end DS 0X count_len EQU *-count ha DSECT , home area descriptor ha_bin DS X ha_cc DS XL2 ha_hh DS XL2 ha_end DS 0X ha_len EQU *-ha rw_ent DSECT , rewrite entry rw_pos DS F rw_buf DS A rw_ttr DS F rw_next DS 0F rw_len EQU *-rw_ent L2TAB DSECT , level 2 lookup table entry L2TAB_entry DS 0XL8 L2TAB_pos DS XL4 pos of track image L2TAB_len DS XL2 length of track in area L2TAB_size DS XL2 size of track area L2TAB_next DS 0X VDHDR DSECT , virt disk file header VDH_devhdr DS XL512 VDH_devhdr2 DS XL512 VDH_l1tab DS 0X CKDDASD_DEVHDR DSECT , device header CKD_devid DS XL8 CKD_heads DS F CKD_trksize DS F CKD_devtype DS X CKD_fileseq DS X CKD_highcyl DS H CKD_resv DS XL(512-(*-CKDDASD_DEVHDR)) CKD_len EQU *-CKDDASD_DEVHDR CCKDDASD_DEVHDR DSECT , compressed device header CCKD_vrm DS XL3 CCKD_options DS X CCKD_NOFUDGE EQU 1 CCKD_BIGENDIAN EQU 2 CCKD_OPENED EQU 128 CCKD_numl1tab DS F CCKD_numl2tab DS F CCKD_size DS F CCKD_used DS F CCKD_free DS F CCKD_free_total DS F CCKD_free_largest DS F CCKD_free_number DS F CCKD_free_imbed DS F CCKD_cyls DS F DS X CCKD_compress DS X CCKD_COMPRESS_NONE EQU 0 CCKD_COMPRESS_ZLIB EQU 1 CCKD_compress_parm DS H CCKD_gcol DS 5XL16 CCKD_resv DS XL(512-(*-CCKDDASD_DEVHDR)) CCKD_len EQU *-CCKDDASD_DEVHDR */* ---------------------------------------------------------------- * * dsects * * ---------------------------------------------------------------- */ PRINT GEN Was NOGEN SOMITCW DCBD DSORG=PS IEFUCBOB , IEFJFCBN , ICVAFBFL , ICVAFPL , IECSDSL1 (1,3,4) IEZDEB , IEZIOB , IOSDCCW , */* ---------------------------------------------------------------- * * equates * * ---------------------------------------------------------------- */ lr equ x'47' locate record rt equ x'de' read track r0 equ 0 r1 equ 1 r2 equ 2 r3 equ 3 r4 equ 4 r5 equ 5 r6 equ 6 r7 equ 7 r8 equ 8 r9 equ 9 ra equ 10 rb equ 11 rc equ 12 rd equ 13 re equ 14 rf equ 15 END , hercules-3.07/util/cckdload.hla000644 000765 000765 00000224701 11224164170 020156 0ustar00jmaynardjmaynard000000 000000 */* ------------------------------------------------------------------- * Restore a cckd file to a real dasd unit. * The dasd unit must be offline. * * Invocation: * //step EXEC PGM=CCKDLOAD,PARM=unit * //STEPLIB DD DISP=SHR,DSN=apf.authorized.loadlib * //SYSPRINT DD SYSOUT=* * //SYSUT1 DD DISP=SHR,DSN=cckd.file * * ------------------------------------------------------------------ */ */* ------------------------------------------------------------------- * local macros * ------------------------------------------------------------------ */ MACRO &L #LLE &R,&A load little-endian &L IC &R,&A ICM &R,2,1+&A ICM &R,4,2+&A ICM &R,8,3+&A MEND MACRO &L #LHLE &R,&A load halfword little-endian &L SLR &R,&R IC &R,&A ICM &R,2,1+&A MEND MACRO &L #LC &R,&A load conditional &L TM cdevhdr_options,CCKD_BIGENDIAN BO #LC&SYSNDX.A #LLE &R,&A B #LC&SYSNDX.B #LC&SYSNDX.A L &R,&A #LC&SYSNDX.B DS 0H MEND MACRO &L #LHC &R,&A load halfword conditional &L TM cdevhdr_options,CCKD_BIGENDIAN BO #LHC&SYSNDX.A #LHLE &R,&A B #LHC&SYSNDX.B #LHC&SYSNDX.A SLR &R,&R ICM &R,3,&A #LHC&SYSNDX.B DS 0H MEND MACRO &L #READ &OFFSET=,&LENGTH=,&ADDR= read a cckd block &L LA r1,pl .* AIF ('&OFFSET'(1,1) EQ '(').r1 LA re,&OFFSET AGO .x1 .r1 LR re,&OFFSET(1) .x1 ANOP .* AIF ('&LENGTH'(1,1) EQ '(').r2 LA rf,&LENGTH AGO .x2 .r2 LR rf,&LENGTH(1) .x2 ANOP .* AIF ('&ADDR'(1,1) EQ '(').r3 LA r0,&ADDR AGO .x3 .r3 LR r0,&ADDR(1) .x3 ANOP .* STM re,r0,0(r1) L rf,=A(readr) BALR re,rf MEND MACRO &L #WRITE &ADDR= write a ckd track image .* AIF ('&ADDR'(1,1) EQ '(').r1 &L LA r1,&ADDR AGO .x1 .r1 ANOP &L LR r1,&ADDR(1) .x1 ANOP L rf,=A(writer) BALR re,rf MEND MACRO &L #MSG &MSG,&TYPE=CALL messages LCLA &A,&N,&O LCLC &C GBLA &MSG_IX GBLC &MSGS(256) AIF ('&TYPE' EQ 'CALL').CALL, x ('&TYPE' EQ 'GEN').GEN MNOTE 8,'Invalid type specified' MEXIT .* .CALL ANOP &MSG_IX SETA &MSG_IX+1 &MSGS(&MSG_IX) SETC '&MSG' &L L re,=A(#MSG&MSG_IX) LA rf,L'#MSG&MSG_IX &A SETA 2 &O SETA 0 &N SETA N'&SYSLIST AGO .PL0 .PLLOOP ANOP LA re,&SYSLIST(&A) &A SETA &A+1 AIF (&A GT &N).PLX14 LA rf,&SYSLIST(&A) &A SETA &A+1 .PL0 ANOP AIF (&A GT &N).PLX15 LA r0,&SYSLIST(&A) &A SETA &A+1 AIF (&A GT &N).PLX0 LA r1,&SYSLIST(&A) &A SETA &A+1 AIF (&A GT &N).PLX1 STM re,r1,pl+&O &O SETA &O+16 AGO .PLLOOP .PLX14 ST re,pl+&O AGO .CALL2 .PLX15 STM re,rf,pl+&O AGO .CALL2 .PLX0 STM re,r0,pl+&O AGO .CALL2 .PLX1 STM re,r1,pl+&O .CALL2 LA r1,pl L rf,=a(msgr) BALR re,rf MEXIT .* .GEN ANOP AIF ('&L' EQ '').GENNOL &L DS 0H .GENNOL ANOP &A SETA 1 .GENLOOP AIF (&A GT &MSG_IX).MEND #MSG&A DC C&MSGS(&A) &A SETA &A+1 AGO .GENLOOP .MEND MEND */* ------------------------------------------------------------------- * mainline routine * ------------------------------------------------------------------ */ main CSECT , main AMODE 31 main RMODE ANY B init-*(,rf) DC AL1(init-*) pgmid DC CL8'cckdload' vrm DC X'000101' version 0 release 1 modlvl 1 DC C' &SYSDATE &SYSTIME ' init SAVE (14,12) LR rc,rf set base reg USING main,rc LA ra,4095(,rc) set 2nd base reg USING main+4095,ra LR r2,r1 copy parm reg */* ------------------------------------------------------------------- * obtain and initialize workareas * ------------------------------------------------------------------ */ STORAGE OBTAIN,LENGTH=workl,BNDRY=PAGE get work area ST r1,8(,rd) chain save areas ST rd,4(,r1) LR rd,r1 set area base USING work,rd MVC workid,pgmid set area identifier LA r0,work+8 clear the area L r1,=a(workl-8) SLR rf,rf MVCL r0,re STORAGE OBTAIN,LENGTH=work24l,LOC=BELOW,BNDRY=PAGE 24 bit area LR rb,r1 set 24-bit area base USING work24,rb MVC work24id,pgmid set 24-bit area identifier LA r0,work24+4 clear the 24-bit area L r1,=a(work24l-4) SLR rf,rf MVCL r0,re */* ------------------------------------------------------------------- * process PARM= : * ------------------------------------------------------------------ */ N r2,=A(X'7fffffff') test parameter reg BZ Enoparm invalid parameter list L r3,0(,r2) point to parameters N r3,=A(X'7fffffff') test parameter reg BZ Enoparm invalid parameter list LH r4,0(,r3) get length of parameters LTR r4,r4 test length BNP Enoparm invalid parameter list BCTR r4,0 decrement for EX LA r3,2(,r3) point past length SLR r2,r2 clear TRT register */* 1st and only parm is unit address in hex */ XC dw,dw clear double-word work area CH r4,=Y(4) check 2nd parm length BNL Ebadparm error if too long EX r4,parmmvc copy 2nd parameter */* MVC dw(0),0(r3) *** executed *** */ TR dw,upcase convert to uppercase EX r4,parmhexc test if all hex digits */* TRT drwdw(0),hexchars *** executed *** */ BNZ Ebadparm error if not EX r4,parmhex convert to hex digits */* TR dw(0),hextab *** executed *** */ LA r5,1(,r4) EX r5,parmpack get hex value */* PACK dw2,dw(0) *** executed *** */ SLR r5,r5 clear unit address ICM r5,3,dw2+5 load hex value STH r5,unit save unit address */* ------------------------------------------------------------------- * print initialization message * ------------------------------------------------------------------ */ TIME DEC STM r0,r1,ctime get time and date of load LA r1,ctime LA r0,dtime BAL re,datetime #MSG '%s:8 %d:1.%d:1.%d:1 load starting at %s:20', X pgmid,vrm,vrm+1,vrm+2,dtime */* ------------------------------------------------------------------- * open the cckd file * ------------------------------------------------------------------ */ MVC sysut1,m_sysut1 copy the model dcb MVC sysut1e,m_sysut1e copy the model dcbe ut1 USING IHADCB,sysut1 LA r1,sysut1e set dcbe address ST r1,ut1.DCBDCBE in the dcb DEVTYPE ut1.DCBDDNAM,devta get device info LTR rf,rf test return code BNZ Edevterr error if non-zero TM devta+2,UCB3DACC check for dasd device BNO Enotdasd1 error if not on dasd MVC openl,m_openl copy model open list OPEN (sysut1,INPUT),MODE=31,MF=(E,openl) open the cckd file TM ut1.DCBOFLGS,DCBOFOPN did cckd file open ? BNO Eopenerr no, open error CLC ut1.DCBBLKSI,=Y(4096) check block size BNE Ebadblksz error if not 4096 MVC pl(l_tcpl),m_tcpl copy model parm list TRKCALC FUNCTN=TRKCAP,TYPE=devta+3,RKDD==x'01001000', x REGSAVE=YES,MF=(E,pl) calculate blks/trk LTR rf,rf test return code BNZ Etrkcalc error if non-zero ST r0,bpt save blks/trk */* ------------------------------------------------------------------- * read the CKDDASD_DEVHDR * ------------------------------------------------------------------ */ #READ OFFSET=0,LENGTH=CKDDASD_DEVHDR_SIZE,ADDR=devhdr USING CKDDASD_DEVHDR,devhdr TR devhdr_devid,A2E CLC devhdr_devid,=C'CKD_C370' check devid BNE Edevid #LLE r1,devhdr_heads get number of heads ST r1,heads #LLE r1,devhdr_trksize get trk size ST r1,trklen IC r1,devhdr_devtype get device type STC r1,devtype+1 STC r1,devtype TR devtype(1),devtype_table get 1st byte CLI devtype,0 known type ? BE Ebaddevt no, error */* ------------------------------------------------------------------- * read the CCKDDASD_DEVHDR * ------------------------------------------------------------------ */ #READ OFFSET=CKDDASD_DEVHDR_SIZE,LENGTH=CCKDDASD_DEVHDR_SIZE, x ADDR=cdevhdr USING CCKDDASD_DEVHDR,cdevhdr TM cdevhdr_options,CCKD_OPENED was file closed ? BNO openok yes, continue #MSG 'Warning... cckd file was not closed' MVC result,=A(4) openok DS 0H #LC r1,cdevhdr_cyls number of cylinders ST r1,cyls #LC r2,cdevhdr_numl1tab l1 table entries ST r2,numl1tab */* ------------------------------------------------------------------- * read the CCKD_L1TAB * ------------------------------------------------------------------ */ SLL r2,2 size of l1tab STORAGE OBTAIN,LENGTH=(r2) get l1tab storage LR r3,r1 ST r3,l1tab #READ OFFSET=CCKD_L1TAB_POS,LENGTH=(r2),ADDR=(r3) */* ------------------------------------------------------------------- * find the last used track and cylinder * ------------------------------------------------------------------ */ ALR r2,r3 end of l1tab lastl1 SH r2,=Y(CCKD_L1ENT_SIZE) backup an entry CLR r2,r3 before the beginning ? BL Eempty yes, empty file #LC r4,0(r2) get l2tab offset LTR r4,r4 empty ? BZ lastl1 yes, keep looking #READ OFFSET=(r4),LENGTH=CCKD_L2TAB_SIZE,ADDR=l2tab LA r4,l2tab beginning of l2tab LA r5,CCKD_L2TAB_SIZE(,r4) end of l2tab lastl2 SH r5,=Y(CCKD_L2ENT_SIZE) backup an entry CLR r5,r4 before the beginning ? BL lastl1 yes, keep looking USING CCKD_L2ENT,r5 #LC r0,l2ent_pos load trk offset LTR r0,r0 empty ? BZ lastl2 yes, keep looking SR r2,r3 each 4-byte l1tab SRL r2,2 entry represents SLL r2,8 256 tracks SR r5,r4 each 8-byte l2tab SRL r5,3 entry is a track AR r5,r2 have last used trk ST r5,lasttrk SLR r4,r4 D r4,heads have last used cyl ST r5,lastcyl DROP r5 #MSG 'cckd file is a %x4:2 cyls %d heads %d trklen %d; cyl %dx is the last used cylinder', x devtype,cyls,heads,trklen,lastcyl */* ------------------------------------------------------------------- * `fake-open' the offline device * ------------------------------------------------------------------ */ */* ------------------------------------------------------------------- * look for the ucb for the unit & make sure it's an offline dasd * ------------------------------------------------------------------ */ MVC pl(l_ulpl),m_ulpl copy parm list MODESET MODE=SUP UCBLOOK DEVN=unit,UCBPTR=ucbaddr,PIN,PTOKEN=ptoken, x DYNAMIC=YES,RANGE=ALL,LOC=ANY,MF=(E,pl), x TEXT==C'cckddump offline dasd lookup' STM rf,r0,retcd save ret/rsn codes MODESET MODE=PROB LM rf,r0,retcd LTR rf,rf check return code BNZ Ebaducbl ucblook error OI flags,ucbpin L r2,ucbaddr USING UCBOB,r2 CLI UCBTBYT3,UCB3DACC check for dasd ucb BNE Ebaducbt not a dasd unit TM UCBSTAT,UCBONLI is device online ? BO Ebaducbs unit is not offline */* ------------------------------------------------------------------- * if we got a 31-bit address then we need to `capture' a 24-bit addr * ------------------------------------------------------------------ */ MVC cucbaddr,ucbaddr copy ucb addr TM ucbaddr,X'ff' 31 bit address ? BZ cucbok no, continue MVC pl(l_cupl),m_cupl copy parm list MODESET MODE=SUP IOSCAPU CAPTUCB,UCBPTR=ucbaddr,CAPTPTR=cucbaddr, x MF=(E,pl) capture 24 bit addr STM rf,r0,retcd save ret/rsn codes MODESET MODE=PROB LM rf,r0,retcd LTR rf,rf check return code BNZ Ebaducbc ioscapu error OI flags,captucb cucbok DS 0H */* ------------------------------------------------------------------- * build a dcb for the offline dasd * ------------------------------------------------------------------ */ MVC unitdcb,m_unitdcb copy model dcb udcb USING IHADCB,unitdcb MVC udcb.DCBMACRF,udcb.DCBMACR copy macr */* ------------------------------------------------------------------- * build a deb for the offline dasd * ------------------------------------------------------------------ */ MODESET MODE=SUP,KEY=ZERO GETMAIN RU,LV=DEBLENGTH,SP=230,LOC=BELOW ST r1,debaddr save deb address XC 0(DEBLENGTH,r1),0(r1) clear the deb LR r3,r1 app vector table USING DEBAVT,r3 LA r4,DEBBASND-DEBAVT(,r3) debdasd section USING DEBDASD,r4 LA r5,DEBDASDE-DEBDASD(,r4) deb ext section USING DEBXTN,r5 L r6,CVTPTR get cvt address USING CVT,r6 L rf,CVTXAPG ios app vector table MVC DEBAVT(DEBPREFX-DEBAVT),0(rf) copy vector table ST r5,DEBXTNP set ext address USING PSA,r0 L r7,PSATOLD get tcb address USING TCB,r7 ST r7,DEBTCBAD set tcb address OI DEBFLGS1,DEBXTNIN indicate ext exists LA r0,unitdcb get dcb address ST r0,DEBDCBAD set dcb address MVI DEBDEBID,15 set deb identifier OC DEBPROTG,TCBPKF set protection key ST r3,DEBAPPAD set app table address MVC DEBUCBA,cucbaddr+1 set ucb address MVC DEBXLNGH,=Y(DEBXLEN) set ext length LA r1,DEBBASIC get basic address STCM r1,7,udcb.DCBDEBA set deb addr in dcb SETLOCK OBTAIN,TYPE=LOCAL,REGS=STDSAVE,MODE=UNCOND MVC DEBDEBB,TCBDEB+1 set addr next deb LA r1,DEBBASIC get basic addr ST r1,TCBDEB chain deb to the tcb SETLOCK RELEASE,TYPE=LOCAL,REGS=STDSAVE */* ------------------------------------------------------------------- * add the deb to the deb list * ------------------------------------------------------------------ */ DEBCHK unitdcb,TYPE=ADD,AM=EXCP STM rf,r0,retcd MODESET MODE=PROB,KEY=NZERO LM rf,r0,retcd LTR rf,rf test return code BNZ Ebaddeba debchk add failed OI flags,debadded */* ------------------------------------------------------------------- * build the dasd extent * ------------------------------------------------------------------ */ MODESET MODE=SUP,KEY=ZERO MVC DEBUCBAD,cucbaddr set 24-bit ucb addr MVI DEBDVMOD,0 set device modifier MVC DEBENDCC,=X'7fff' set end cylinder MVC DEBENDHH,=X'00ff' set end head MVC DEBNMTRK,=X'7fff' set nbr trks in extent MODESET MODE=PROB,KEY=NZERO DROP r0,r2,r3,r4,r6,r7 */* ------------------------------------------------------------------- * build a couple of iobs * ------------------------------------------------------------------ */ i1 USING IOBSTDRD,iob1 OI i1.IOBFLAG1,IOBDATCH+IOBCMDCH+IOBUNREL LA r1,ecb1 ST r1,i1.IOBECBPT LA r1,ccws ST r1,i1.IOBSTART LA r1,unitdcb ST r1,i1.IOBDCBPT i2 USING IOBSTDRD,iob2 OI i2.IOBFLAG1,IOBDATCH+IOBCMDCH+IOBUNREL LA r1,ecb2 ST r1,i2.IOBECBPT LA r1,ccws LA r1,ccwl(,r1) ST r1,i2.IOBSTART LA r1,unitdcb ST r1,i2.IOBDCBPT */* ------------------------------------------------------------------- * turn off the `not ready' bit * ------------------------------------------------------------------ */ L r2,ucbaddr load ucb addr USING UCBOB,r2 TM UCBFLA,UCBNRY `not ready' bit on ? BNO nryok no, continue MODESET MODE=SUP,KEY=ZERO NI UCBFLA,255-UCBNRY turn off `not ready' MODESET MODE=PROB,KEY=NZERO DROP r2 OI flags,notready nryok DS 0H */* ------------------------------------------------------------------- * sense the offline device * ------------------------------------------------------------------ */ LA r2,ccws USING CCW0,r2 MODESET MODE=SUP,KEY=ZERO OI DEBXFLG2,DEBCHCMP+DEBBYP MODESET MODE=PROB,KEY=NZERO */* seek */ XC CCW0(8),CCW0 MVI CCW0CMD,SK LA r1,zeros STCM r1,7,CCW0ADDR MVI CCW0FLAG,CCW0SLI MVC CCW0CNT,=Y(6) EXCP iob1 WAIT 1,ECB=ecb1 CLI ecb1,ECBNORM BNE Esnserr */* Sense ID */ XC ecb1,ecb1 XC CCW0(8),CCW0 MVI CCW0CMD,SNSID LA r1,snsidarea STCM r1,7,CCW0ADDR MVI CCW0FLAG,CCW0SLI MVC CCW0CNT,=Y(L'snsidarea) EXCP iob1 WAIT 1,ECB=ecb1 CLI ecb1,ECBNORM BNE Esnserr */* Sense */ XC ecb1,ecb1 XC CCW0(8),CCW0 MVI CCW0CMD,SNS LA r1,snsarea STCM r1,7,CCW0ADDR MVI CCW0FLAG,CCW0SLI MVC CCW0CNT,=Y(L'snsarea) EXCP iob1 WAIT 1,ECB=ecb1 CLI ecb1,ECBNORM BNE Esnserr */* Read Device Characteristics */ XC ecb1,ecb1 XC CCW0(8),CCW0 MVI CCW0CMD,RDC LA r1,rdcarea STCM r1,7,CCW0ADDR MVI CCW0FLAG,0 MVC CCW0CNT,=Y(L'rdcarea) EXCP iob1 WAIT 1,ECB=ecb1 CLI ecb1,ECBNORM BNE Esnserr */* Sense Subsystem Status XC ecb1,ecb1 XC CCW0(8),CCW0 MVI CCW0CMD,SNSS LA r1,snssarea STCM r1,7,CCW0ADDR MVI CCW0FLAG,CCW0SLI MVC CCW0CNT,=Y(L'snssarea) EXCP iob1 WAIT 1,ECB=ecb1 CLI ecb1,ECBNORM BNE Esnserr MODESET MODE=SUP,KEY=ZERO NI DEBXFLG2,255-DEBBYP MODESET MODE=PROB,KEY=NZERO DROP r2,r5 */* ------------------------------------------------------------------- * perform some sanity checks * ------------------------------------------------------------------ */ USING RDCinfo,rdcarea MVC pl(l_tcpl),m_tcpl copy model parm list L r2,cucbaddr TRKCALC FUNCTN=TRKBAL,UCB=(r2),RKDD==A(x'0100ffff'), x MAXSIZE=YES,REGSAVE=YES,MF=(E,pl) CH rf,=Y(8) BNE Ebadcap unexpected return code LR r1,r0 round up 512 LA r1,511(,r1) N r1,=A(x'fffffe00') ST r1,utrklen #MSG 'unit %x4:2 is a %x4:2 cyls %d:2 heads %d:2 trklen %d', x unit,RDCdevt,RDCprime,RDCheads,utrklen CLC RDCdevt,devtype BNE Emisdevt CLC RDCheads,heads+2 BNE Emisheads CLC trklen,utrklen BNE Emislen CLC RDCprime,lastcyl+2 BH cylok #MSG 'Warning... cckd file uses more cylinders than availablex on %x4:2; extras will be omitted',unit MVC result,=A(4) cylok DS 0H */* Dump tracks thru last used cylinder, or thru last cylinder on */ */* on the output device, whichever is lower */ L r3,lastcyl LA r3,1(,r3) M r2,heads ST r3,tracks SLR r3,r3 ICM r3,3,RDCprime M r2,heads C r3,tracks BH *+8 ST r3,tracks tracks to write #MSG '%d tracks will be written',tracks L r3,tracks tracks to write D r2,=A(10) LA r3,99(,r3) SLR r2,r2 D r2,=A(100) LTR r3,r3 BNZ *+8 LA r3,1 10% of tracks to be MH r3,=Y(100) written rounded up ST r3,trk10pct to next 100 SLR r2,r2 for status msg L r3,tracks D r2,heads ST r3,cyls */* ------------------------------------------------------------------- * get area for the buffers * ------------------------------------------------------------------ */ L r2,trklen SLL r2,2 space for 4 buffers STORAGE OBTAIN,LENGTH=(r2) ST r1,buf1 AL r1,trklen ST r1,buf2 AL r1,trklen ST r1,buf3 AL r1,trklen ST r1,buf4 */* ------------------------------------------------------------------- * create a persistent c environment * ------------------------------------------------------------------ */ LA r2,handle LA r3,=A(32*1024) LA r4,=A(1) STM r2,r4,pl OI pl+8,X'80' LA r1,pl L rf,=V(EDCXHOTL) create persistent c environ BALR re,rf ******* #MSG 'persistent c environment created, handle=0x%x',handle */* ------------------------------------------------------------------- * setup the output channel programs * ------------------------------------------------------------------ */ LA r2,ccws point to 1st ccws USING CCW0,r2 LA r3,lrparm1 point to 1st LR parameters USING LRparm,r3 LA r4,idaw1 point to 1st idaw list LA rf,2 build 2 sets of ccws bldcp XC CCW0(8),CCW0 clear the ccw MVI CCW0CMD,DX set define extent command LA r1,dxarea address of dx area STCM r1,7,CCW0ADDR set address MVI CCW0FLAG,CCW0CC command chaining MVC CCW0CNT,=Y(L'dxarea) set length LA r2,CCW0END to next ccw XC CCW0(8),CCW0 clear the ccw MVI CCW0CMD,TIC set transfer-in-control command LA r1,CCW0END address of next ccw STCM r1,7,CCW0ADDR set next ccw address LA r2,CCW0END to next ccw XC CCW0(8),CCW0 clear the ccw MVI CCW0CMD,LR set locate record command STCM r3,7,CCW0ADDR set address in locate record ccw OI CCW0FLAG,CCW0CC command chaining MVC CCW0CNT,=Y(LRparml) set length MVI LRop,LRocount+LRfwrite set operation byte LA r0,255 build 255 write ccws bldcp2 LA r2,CCW0END point to next ccw XC CCW0(8),CCW0 clear the ccw MVI CCW0CMD,WCKD set read track command STCM r4,7,CCW0ADDR set address for idaw LA r4,4(,r4) point to next idaw BCT r0,bldcp2 loop back LA r2,ccws point to 2nd LA r2,ccwl(,r2) channel program LA r3,lrparm2 point to 2nd LR parameters LA r4,idaw2 point to 2nd idaw list BCT rf,bldcp build 2nd channel program DROP r2,r3 */* ------------------------------------------------------------------- * setup the output define extent area * ------------------------------------------------------------------ */ MVI dxarea,X'c0' permit all write operations MVI dxarea+1,X'c0' eckd L r1,cyls low extent is cyl 0 head 0 BCTR r1,0 set high extent stcm r1,3,dxarea+12 ICM r1,3,RDCheads BCTR r1,0 STCM r1,3,dxarea+14 */* ------------------------------------------------------------------- * Read/write each track image * ------------------------------------------------------------------ */ SLR r2,r2 init buffer switch SLR r3,r3 init l1tab index MVC trkstat,trk10pct init status rwloop DS 0H */* Read the next l2tab */ LR r4,r3 SLL r4,2 AL r4,l1tab #LC r5,0(r4) LTR r4,r5 BZ l2null #READ OFFSET=(r4),LENGTH=CCKD_L2TAB_SIZE,ADDR=l2tab B l2ok l2null LA r0,l2tab LA r1,CCKD_L2TAB_SIZE SLR rf,rf MVCL re,r0 l2ok DS 0H */* Loop for each entry in the l2tab, exit if all tracks processed */ SLR r4,r4 rwloop2 LR rf,r3 SLL rf,8 AR rf,r4 CL rf,tracks BNL rwexit ST rf,track */* Get offset/length of the track image from the l2tab entry */ LR r5,r4 SLL r5,3 LA r5,l2tab(r5) USING CCKD_L2ENT,r5 #LC r6,l2ent_pos #LHC r7,l2ent_len DROP r5 L r5,bufs(r2) */* Read the track image unless its a null track */ LTR r6,r6 BZ trknull #READ OFFSET=(r6),LENGTH=(r7),ADDR=(r5) B trkok trknull XC 0(CCKD_NULLTRK_SIZE,r5),0(r5) */* Build a null trk: 0cchh cchh0008 00000000 cchh1000 ffffffff */ SLR re,re L rf,track D re,heads STCM rf,3,1(r5) STCM re,3,3(r5) MVC 5(4,r5),1(r5) MVI 8(r5),8 MVC 21(4,r5),1(r5) MVI 25(r5),1 MVC 29(8,r5),eightFF trkok DS 0H CLI 0(r5),CCKD_COMPRESS_MAX BNH compok #MSG 'Trk %d unknown compression: %d:1',track,0(r5) MVC result,=A(8) B trknull compok DS 0H */* Uncompress the track image */ SLR rf,rf IC rf,0(,r5) SLL rf,2 B *+4(rf) B compnone 0 - not compressed B compzlib 1 - zlib compression B compbz2 2 - bz2 compression */* Not compressed */ compnone LR r6,r5 B compdone */* zlib compression */ compzlib LR r6,r5 AL r6,trklen MVC 0(CKDDASD_TRKHDR_SIZE,r6),0(r5) LA re,handle LA rf,=V(UNCOMPRE) LA r0,CKDDASD_TRKHDR_SIZE(,r6) L r1,trklen SH r1,=Y(CKDDASD_TRKHDR_SIZE) ST r1,complen LA r1,complen STM re,r1,pl LA re,CKDDASD_TRKHDR_SIZE(,r5) LR rf,r7 SH rf,=Y(CKDDASD_TRKHDR_SIZE) STM re,rf,pl+16 LA r1,pl L rf,=V(EDCXHOTU) BALR re,rf LTR rf,rf BZ compdone ST rf,retcd #MSG 'trk %d zlib uncompress error: %d',track,retcd MVC result,=A(8) B trknull */* bzip2 compression */ compbz2 LR r6,r5 AL r6,trklen MVC 0(CKDDASD_TRKHDR_SIZE,r6),0(r5) LA re,handle LA rf,=V(bzbuffd) LA r0,CKDDASD_TRKHDR_SIZE(,r6) L r1,trklen SH r1,=Y(CKDDASD_TRKHDR_SIZE) ST r1,complen LA r1,complen STM re,r1,pl LA re,CKDDASD_TRKHDR_SIZE(,r5) LR rf,r7 SH rf,=Y(CKDDASD_TRKHDR_SIZE) SLR r0,r0 SLR r1,r1 STM re,r1,pl+16 LA r1,pl L rf,=V(EDCXHOTU) BALR re,rf LTR rf,rf BZ compdone ST rf,retcd #MSG 'trk %d bzip2 decompress error: %d',track,retcd MVC result,=A(8) B trknull compdone DS 0H */* Schedule the track image to be written */ #WRITE ADDR=(r6) */* Write status message if it's time */ CLC track,trkstat BL rwnext2 #MSG '%d tracks written',track L r1,trkstat AL r1,trk10pct ST r1,trkstat rwnext2 X r2,=A(8) flip/flop buffers LA r4,1(,r4) CH r4,=Y(256) BL rwloop2 rwnext LA r3,1(,r3) B rwloop rwexit DS 0H TIME DEC STM r0,r1,ctime LA r1,ctime LA r0,dtime BAL re,datetime #MSG '%d tracks written at %s:20, max code: %d', x tracks,dtime,result */* ------------------------------------------------------------------- * cleanup and terminate * ------------------------------------------------------------------ */ terminate DS 0H */* Make sure all write i/o has completed */ #WRITE ADDR=0 */* Terminate the persistant c environment */ CLC =A(0),handle BE term1 LA r1,handle ST r1,pl OI pl,X'80' LA r1,pl L rf,=V(EDCXHOTT) BALR re,rf term1 DS 0H */* Close the cckd file */ TM ut1.DCBOFLGS,DCBOFOPN BNO term2 MVC openl,m_openl CLOSE (sysut1),MODE=31,MF=(E,openl) term2 DS 0H */* Free the i/o areas */ L r1,buf1 LTR r1,r1 BZ term3 L r2,trklen SLL r2,2 STORAGE RELEASE,ADDR=(1),LENGTH=(r2) term3 DS 0H */* Free the l1tab */ L r1,l1tab LTR r1,r1 BZ term4 L r2,numl1tab SLL r2,2 STORAGE RELEASE,ADDR=(1),LENGTH=(r2) term4 DS 0H */* Call debchk to delete the deb */ TM flags,debadded BNO term5 MODESET MODE=SUP,KEY=ZERO DEBCHK unitdcb,TYPE=DELETE,AM=EXCP delete the deb MODESET MODE=PROB,KEY=NZERO term5 DS 0H L r2,debaddr LTR r2,r2 BZ term6 */* Remove the deb from the deb chain */ USING DEBAVT,r2 LA r3,DEBBASIC DROP r2 L r4,PSATOLD-PSA USING TCB,r4 LA r5,TCBDEB-(DEBDEBAD-DEBBASIC) USING DEBBASIC,r4 MODESET MODE=SUP,KEY=ZERO SETLOCK OBTAIN,TYPE=LOCAL,REGS=STDSAVE,MODE=UNCOND SPKA X'80' termdeb LR r4,r5 SLR r5,r5 ICM r5,7,DEBDEBB BZ termdebx CLR r3,r5 BNE termdeb SPKA 0 MVC DEBDEBB,DEBDEBB-DEBBASIC(r5) DROP r4 termdebx SPKA 0 SETLOCK RELEASE,TYPE=LOCAL,REGS=STDSAVE MODESET MODE=PROB,KEY=NZERO */* Free deb storage */ MODESET MODE=SUP,KEY=ZERO FREEMAIN RU,A=(r2),LV=DEBLENGTH,SP=230 MODESET MODE=PROB,KEY=NZERO term6 DS 0H */* Turn the ucb `not ready' bit back on if we turned it off */ TM flags,notready BNO term7 L r2,ucbaddr USING UCBOB,r2 MODESET MODE=SUP,KEY=ZERO OI UCBFLA,UCBNRY MODESET MODE=PROB,KEY=NZERO DROP r2 term7 DS 0H */* Uncapture the ucb */ TM flags,captucb BNO term8 MVC pl(l_cupl),m_cupl MODESET MODE=SUP IOSCAPU UCAPTUCB,CAPTPTR=cucbaddr,MF=(E,pl) MODESET MODE=PROB term8 DS 0H */* Unpin the ucb */ TM flags,ucbpin BNO term9 MVC pl(l_uupl),m_uupl MODESET MODE=SUP UCBPIN UNPIN,PTOKEN=ptoken,MF=(E,pl) MODESET MODE=PROB term9 DS 0H */* Close the sysprint file */ pdcb USING IHADCB,prtdcb TM pdcb.DCBOFLGS,DCBOFOPN BNO term10 MVC openl,m_openl CLOSE (prtdcb),MODE=31,MF=(E,openl) term10 DS 0H */* Free the work areas */ STORAGE RELEASE,ADDR=(rb),LENGTH=work24l LR r1,rd L r2,result L rd,4(,rd) STORAGE RELEASE,ADDR=(1),LENGTH=workl */* Return */ LR rf,r2 RETURN (14,12),RC=(15) */* ------------------------------------------------------------------- * format date & time * ------------------------------------------------------------------ */ datetime STM re,r2,12(rd) save some regs LR r2,r0 copy output area address MVI 0(r2),C' ' blank the output area MVC 1(19,r2),0(r2) MVC 11(9,r2),=X'4021207a20207a2020' edit pattern for time ED 11(9,r2),0(r1) edited time XC dw,dw clear double word work area SLR rf,rf ICM rf,3,4(r1) decimal year SLL rf,4 shift over a nibble ST rf,dw+4 store in the double word OI dw+7,X'0f' set bottom nibble AP dw,=P'1900' calculate the year OI dw+7,X'0f' fix bottom nibble for unpk UNPK 7(4,r2),dw set the year CVB rf,dw get binary year N rf,=A(3) test for leap year BZ *+8 jumps if leap year LA rf,2 else set non-leapyr offset ZAP dw,6(2,r1) get julian day in double word CVB r0,dw get julian day binary LA re,dtjtab point to julian table dtfind CH r0,8(rf,re) found table entry ? BNH dtfound yes, exit loop LA re,8(,re) point to next entry B dtfind and loop back dtfound MVC 3(3,r2),4(re) set month from the table SH r0,0(rf,re) calculate day of month CVD r0,dw get day of month packed L r0,dw+4 load packed day SLL r0,20 shift out hi bits SRL r0,28 shift down STC r0,0(,r2) set 1st digit of the month OI 0(r2),C'0' convert to ebcdic character L r0,dw+4 load packed day SLL r0,24 shift out hi bits SRL r0,28 shift down STC r0,1(,r2) set 2nd digit of the month OI 1(r2),C'0' convert to ebcdic character LM re,r2,12(rd) restore regs BR re and thankfully return dtjtab DC Y(0,0),C'Jan ' Julian date table DC Y(31,31),C'Feb ' DC Y(60,59),C'Mar ' DC Y(91,90),C'Apr ' DC Y(121,120),C'May ' DC Y(152,151),C'Jun ' DC Y(182,181),C'Jul ' DC Y(213,212),C'Aug ' DC Y(244,243),C'Sep ' DC Y(274,273),C'Oct ' DC Y(305,304),C'Nov ' DC Y(335,334),C'Dec ' DC Y(999,999),C'??? ' */* ------------------------------------------------------------------- * error routines * ------------------------------------------------------------------ */ Enoparm #MSG '** Unit address not specified' B Eexit Ebadparm MVC dw,=CL8' ' CH r4,=Y(8) BNH *+8 LA r4,8 SH r4,=Y(1) BM *+4+4+6 EX r4,*+4 MVC dw(0),0(r3) #MSG '** Invalid unit address: %s:8',dw B Eexit Edevid #MSG '** SYSUT1 is not a cckd file; devid validation failed' B Eexit Edevterr STM rf,r0,retcd CLC retcd(8),=A(4,4) missing ddname ? BE Enoddn yes, noddn error #MSG '** SYSUT1 DEVTYPE error: rc=%d, reason=%d', X retcd,rsncd B Eexit Enoddn #MSG '** SYSUT1 ddname not found' B Eexit Enotdasd1 #MSG '** SYSUT1 not a dasd file' B Eexit Eopenerr #MSG '** SYSUT1 did not open' B Eexit Ebadblksz #MSG '** SYSUT1 blksz is not 4096' B Eexit Etrkcalc ST rf,retcd #MSG '** TRKCAP failed for SYSUT1: rc=%d',retcd B Eexit Ebaddevt #MSG '** cckd dasd devtype not supported: 0x%x2:1',devtype+1 B Eexit Eempty #MSG '** cckd file contains all null tracks' B Eexit Epoint ST rf,retcd #MSG '** SYSUT1 point error: rc=%d ttr=%x6:3',retcd,ttr B Eexit Ebaducbl CH RF,=Y(4) BE Enoucb #MSG '** UCBLOOK error for unit %x4:2: rc 0x%x rsn 0x%x', X unit,retcd,rsncd B Eexit Enoucb #MSG '** UCB not found for unit %x4:2',unit B Eexit Ebaducbt L r2,ucbaddr USING UCBOB,r2 #MSG '** UCB for unit %x4:2 is not dasd, type is %x:1', X unit,UCBTBYT3 B Eexit DROP r2 Ebaducbs #MSG '** Device %x4:2 is not offline',unit B Eexit Ebaducbc #MSG '** IOSCAPU CAPTUCB failed for %x4:2; rc=0x%x rsn=0x%x',X unit,retcd,rsncd B Eexit Ebaddeba #MSG '** DEBCHK ADD for %x4:2 failed; rc=0x%x', X unit,retcd B Eexit Esnserr #MSG '** Sense failed for %x4:2: command %x2:1, CC 0x%x2:1, SX tat 0x%x4:2',unit,ccws,ecb1,i1.IOBSTBYT B Eexit Ebadcap ST rf,retcd #MSG '** TRKBAL for %x4:2 unexpected return code; rc=0x%x', X unit,retcd B Eexit Emisdevt #MSG '** devtype mismatch %x4:2=%x4:2, cckd=%x4:2', X unit,RDCdevt,devtype B Eexit Emisheads #MSG '** number heads mismatch %x4:2=%d:2, cckd=%d', X unit,RDCheads,heads B Eexit Emislen #MSG '** trklen mismatch %x4:2=%d, cckd=%d', X unit,utrklen,trklen B Eexit Eioerr SLR r2,r2 ICM r2,7,waitecb+1 LA r0,ecb1 LA r3,iob1 CLR r0,r2 BE *+8 LA r3,iob2 USING ECB,r2 USING IOBSTDRD,r3 #MSG '** I/O error %x4:2 CCHH %x8: CC %x2:1, Stat %x4:2', X unit,prevcchh,ECBCC,IOBSTBYT DROP r2,r3 B Eexit Eexit MVC result,=A(12) B terminate */* ------------------------------------------------------------------- * literals and constants * ------------------------------------------------------------------ */ LTORG , parmmvc MVC dw(0),0(r3) *** executed *** parmhexc TRT dw(0),hexchars *** executed *** parmhex TR dw(0),hextab *** executed *** parmpack PACK dw2,dw(0) *** executed *** m_unitdcb DCB DDNAME=0,DSORG=PS,MACRF=E l_unitdcb EQU *-m_unitdcb m_sysut1 DCB DDNAME=SYSUT1,DSORG=PS,MACRF=RP,DCBE=m_sysut1e,RECFM=F l_sysut1 EQU *-m_sysut1 m_sysut1e DCBE RMODE31=BUFF l_sysut1e EQU *-m_sysut1e m_prtdcb DCB DDNAME=SYSPRINT,DSORG=PS,MACRF=PL,DCBE=m_prtdcbe l_prtdcb EQU *-m_prtdcb m_prtdcbe DCBE RMODE31=BUFF l_prtdcbe EQU *-m_prtdcbe m_openl OPEN (0),MODE=31,MF=L l_openl EQU *-m_openl UCBLOOK MF=(L,m_ulpl) l_ulpl EQU *-m_ulpl UCBPIN MF=(L,m_uupl) l_uupl EQU *-m_uupl IOSCAPU MF=(L,m_cupl) l_cupl EQU *-m_cupl m_tcpl TRKCALC MF=L l_tcpl EQU *-m_tcpl eightFF DC X'ffffffffffffffff' devtype_table DC 256X'00' ORG devtype_table+x'80' DC X'33' ORG devtype_table+x'90' DC X'33' ORG devtype_table+x'45' DC X'93' ORG devtype_table+256 hextab DC 256X'00' ORG hextab+C'0' DC AL1(0,1,2,3,4,5,6,7,8,9) ORG hextab+C'a' DC AL1(10,11,12,13,14,15) ORG hextab+C'A' DC AL1(10,11,12,13,14,15) ORG hextab+256 hexchars DC 256x'ff' ORG hexchars+C'a' DC 6x'0' ORG hexchars+C'A' DC 6x'0' ORG hexchars+C'0' DC 10x'0' ORG hexchars+256 upcase DC C' ',255AL1(*-upcase) ORG upcase+c'a' DC C'ABCDEFGHI' ORG upcase+c'j' DC C'JKLMNOPQR' ORG upcase+c's' DC C'STUVWXYZ' ORG upcase+256 A2E DS 0D * 0 1 2 3 4 5 6 7 8 9 a b c d e f DC X'00010203372D2E2F1605250B0C0D0E0F' 0 DC X'101112133C3D322618193F27221D351F' 1 DC X'405A7F7B5B6C507D4D5D5C4E6B604B61' 2 DC X'F0F1F2F3F4F5F6F7F8F97A5E4C7E6E6F' 3 DC X'7CC1C2C3C4C5C6C7C8C9D1D2D3D4D5D6' 4 DC X'D7D8D9E2E3E4E5E6E7E8E9ADE0BD5F6D' 5 DC X'79818283848586878889919293949596' 6 DC X'979899A2A3A4A5A6A7A8A9C04FD0A107' 7 DC X'00010203372D2E2F1605250B0C0D0E0F' 8 DC X'101112133C3D322618193F27221D351F' 9 DC X'405A7F7B5B6C507D4D5D5C4E6B604B61' a DC X'F0F1F2F3F4F5F6F7F8F97A5E4C7E6E6F' b DC X'7CC1C2C3C4C5C6C7C8C9D1D2D3D4D5D6' c DC X'D7D8D9E2E3E4E5E6E7E8E9ADE0BD5F6D' d DC X'79818283848586878889919293949596' e DC X'979899A2A3A4A5A6A7A8A9C04FD0A107' f hex2char EQU *-240 DC C'0123456789ABCDEF' DROP , mainend DS 0D */* ------------------------------------------------------------------- * Subroutine to read the cckd file * ------------------------------------------------------------------ */ USING readr,r9 USING work,rd USING work24,rb USING main,rc USING (main+4095,mainend),ra readr STM r0,rf,save1 LR r9,rf LM r2,r4,0(r1) load offset, length, address */* Read the first block into the tempbuf */ LR r7,r2 copy the offset SRL r7,12 get the block number LTR r2,r2 test offset BZ r_getblk1 always read 1st block for offset 0 CL r7,lastblk already have the 1st block ? BE r_gotblk1 yes, continue ST r7,lastblk remember this block SLR r6,r6 D r6,bpt calculate ttr STCM r7,3,ttr LA r6,1(,r6) STC r6,ttr+2 POINT sysut1,ttr position to the block LTR rf,rf BNZ Epoint r_getblk1 READ ut1decb,SF,sysut1,tempbuf,'S',MF=E CHECK ut1decb read the block r_gotblk1 DS 0H */* Copy data from the first block to the caller's buffer */ LR r5,r2 calculate data offset N r5,=A(X'00000fff') in the first block LH r6,=Y(4096) calculate data length SR r6,r5 in the first block AR r2,r6 new offset LR re,r4 target address LR rf,r6 data length in the first block CR rf,r3 if requested length is less BL *+6 then use that instead LR rf,r3 LA r0,tempbuf(r5) source address LR r1,rf length to copy AR r4,rf adjust target address SR r3,rf adjust target length MVCL re,r0 copy data from the 1st block */* Read the intermediate blocks directly into the caller's buffer */ r_getint LTR r3,r3 test length left to read BZ r_return return if everything read CH r3,=Y(4096) able to read a full block ? BL r_getlast no, special processing for last READ ut1decb,SF,sysut1,(r4),'S',MF=E CHECK ut1decb read an intermediate block AH r2,=Y(4096) adjust the offset SH r3,=Y(4096) adjust the length left AH r4,=Y(4096) adjust buffer position B r_getint read some more */* Read the last block into the tempbuf */ r_getlast SRL r2,12 change offset to block number ST r2,lastblk and save it READ ut1decb,SF,sysut1,tempbuf,'S',MF=E CHECK ut1decb LR re,r4 target address LR rf,r3 target length LA r0,tempbuf source address LR r1,rf source length MVCL re,r0 copy data from the last block r_return LM r0,rf,save1 BR re LTORG , DROP , */* ------------------------------------------------------------------- * Subroutine to write track images to the offline dasd unit * ------------------------------------------------------------------ */ USING writer,r9 USING work,rd USING work24,rb USING main,rc USING (main+4095,mainend),ra writer STM r0,rf,save1 LR r9,rf */* If buffer address is zero then we simply wait on the last I/O */ LTR r1,r1 BZ w_finish */* Get the IOB we will use */ L r2,iobswtch 0 = iob1, 1 = iob2 LA r3,iob1 presume iob1 LTR r2,r2 BZ *+8 LA r3,iob2 use iob2 if switch is non-zero USING IOBSTDRD,r3 X r2,=A(1) flip/flop the switch ST r2,iobswtch */* Complete the channel program */ MVC prevcchh,curcchh copy last cchh scheculed MVC curcchh,1(r1) current cchh (from HA) MVC IOBCC(4),curcchh set extent in the iob SLR r2,r2 ICM r2,7,IOBECBPB USING ECB,r2 XC ECB,ECB clear the ecb */* If record 1 is end-of-track then make it eof then eot */ CLC eightFF,5+8+8(r1) check for end-of-track BNE w_wnoteot continue if not MVC 5+8+8(8,r1),5(r1) else copy r0 t0 r1 MVI 5+8+8+4(r1),1 and set r to 1 MVI 5+8+8+7(r1),0 and data len to 0 MVC 5+8+8+8(8,r1),eightFF now set the eot w_wnoteot DS 0h LA r1,5+8+8(,r1) point to record 1 SLR rf,rf clear record count SLR r4,r4 ICM r4,7,IOBSTRTB address of the channel program USING CCW0,r4 LA r4,CCW0END point past dx ccw LA r4,CCW0END point past tic ccw SLR r5,r5 ICM r5,7,CCW0ADDR locate record parm addr USING LRparm,r5 MVC LRseek,IOBCC MVC LRsearch,IOBCC w_wckd LA r4,CCW0END point to next ccw LA rf,1(,rf) increment record count SLR r6,r6 ICM r6,7,CCW0ADDR load IDAW address ST r1,0(,r6) set record addr in the IDAW SLR r0,r0 IC r0,5(,r1) key length SLR re,re ICM re,3,6(r1) data length AR re,r0 LA re,8(,re) cound-key-data-length STCM re,3,CCW0CNT OI CCW0FLAG,CCW0CC+CCW0IDA set chain & idaw bits AR r1,re point to the next record CLC eightFF,0(r1) at end of the track ? BNE w_wckd no, keep building NI CCW0FLAG,255-CCW0CC turn off chain bit for last ccw STC rf,LRcount set count of WCKD ccws */* Schedule this channel program and wait for the previous one */ LR rf,r2 copy ecb address L r2,waitecb load ecb address to wait on ST rf,waitecb set new ecb address to wait on EXCP IOBSTDRD schedule the i/o LTR r2,r2 any ecb to wait on ? BZ w_return no, just return WAIT 1,ECB=ECB wait for previous i/o CLI ECBCC,ECBNORM successful completion ? BNE Eioerr no, i/o error B w_return */* Wait for the last i/o to finish */ w_finish L r2,waitecb ecb for last i/o LTR r2,r2 is it set ? BZ w_return no, just return XC waitecb,waitecb WAIT 1,ECB=ECB wait for the last i/o CLI ECBCC,ECBNORM normal completion ? BNE Eioerr no, i/o error w_return LM r0,rf,save1 BR re LTORG , DROP , */* ------------------------------------------------------------------- * Subroutine to issue messages * ------------------------------------------------------------------ */ USING msgr,r9 USING work,rd USING work24,rb USING main,rc USING (main+4095,mainend),ra msgr STM r0,rf,save2 LR r9,rf prt USING IHADCB,prtdcb TM prt.DCBOFLGS,DCBOFOPN BO mr_opened continue if message file is opened LR r2,r1 save reg 1 TM flags,noprint test if no print file BO mr_ret return if not MVC prtdcb,m_prtdcb copy the model print dcb MVC prtdcbe,m_prtdcbe copy model print dcbe LA r1,prtdcbe set dcbe address ST r1,prt.DCBDCBE in the dcb OI flags,noprint presume no print DEVTYPE prt.DCBDDNAM,dw issue devtype for the ddname LTR rf,rf test devtype return code BNZ mr_ret return if some error L r1,=A(mr_oxit) get address of the open exit LA rf,mr_oxitl get open exit length BCTR rf,0 decrement EX rf,*+4 copy the open exit MVC openxit(0),0(r1) *** executed *** LA r1,openxit get open exit addr ST r1,exlst set in exit list MVI exlst,x'85' set exit type LA r1,exlst point to exit list STCM r1,7,prt.DCBEXLSA set exlst addr in the dcb MVC openl,m_openl copy model open list OPEN (prtdcb,OUTPUT),MODE=31,MF=(E,openl) TM prt.DCBOFLGS,DCBOFOPN did the file open ? BNO mr_ret no, return NI flags,255-noprint else turn off `noprt' bit LR r1,r2 restore reg 1 mr_opened LM r4,r5,0(r1) pattern addr, length BCTR r5,0 LA r3,8(,r1) first parameter LA r6,msg MVI msg,C' ' init msg to blanks MVC msg+1(L'msg-1),msg mr_loop LTR r5,r5 BM mr_exit LA r1,1(r4,r5) SLR r2,r2 EX r5,mr_trt1 SR r1,r4 length scanned BNP mr_skip1 LR rf,r1 BCTR rf,0 EX rf,mr_mvc1 copy literal text AR r6,r1 mr_skip1 AR r4,r1 SR r5,r1 BM mr_exit BP mr_skip2 MVC 0(1,r6),0(r4) string ends in special char LA r6,1(,r6) B mr_exit mr_skip2 B *(r2) br on special char type B mr_pct '%' B mr_bs '\' mr_pct CLI 1(r4),C's' BE mr_pct_s CLI 1(r4),C'x' BE mr_pct_x CLI 1(r4),C'd' BE mr_pct_d MVC 0(1,r6),0(r4) treat '%' as any other char LA r6,1(,r6) LA r4,1(,r4) BCTR r5,0 B mr_loop mr_pct_s L r7,0(,r3) load string ptr LA r3,4(,r3) LA r4,2(,r4) point past '%s' SH r5,=Y(2) BAL re,mr_op r1 - target len, r2 - source len LTR r2,r2 BNZ mr_pct_s3 LR r2,r7 source len = 0, find end of string mr_pct_s1 CLI 0(r2),C' ' BNH mr_pct_s2 LA r2,1(,r2) B mr_pct_s1 mr_pct_s2 SR r2,r7 BNP mr_loop mr_pct_s3 LR rf,r2 copy source string to the msg BCTR rf,0 EX rf,mr_mvc2 LTR r1,r1 BNZ mr_pct_s5 AR r6,r2 truncate trailing spaces if mr_pct_s4 BCTR r6,0 target len is 0 CLI 0(r6),C' ' BNH mr_pct_s4 LA r6,1(,r6) B mr_loop mr_pct_s5 CR r1,r2 BH mr_pct_s6 AR r6,r1 truncate the string B mr_loop mr_pct_s6 AR r6,r2 pad string with trailing blanks SR r1,r2 mr_pct_s7 MVI 0(r6),C' ' LA r6,1(,r6) BCT r1,mr_pct_s7 B mr_loop mr_pct_x L r7,0(,r3) load hex ptr LA r3,4(,r3) LA r4,2(,r4) point past '%x' SH r5,=Y(2) BAL re,mr_op r1 - target len, r2 - source len LTR r2,r2 BNZ *+8 LA r2,4 default source len is 4 EX r2,mr_pct_x_unpk TR dw,mr_hextab LTR r1,r1 BNZ mr_pct_x1 LA r1,8 determine default target len CLC =C'00',dw BNE mr_pct_x1 LA r1,6 CLC =C'0000',dw BNE mr_pct_x1 LA r1,4 CLC =C'000000',dw BNE mr_pct_x1 LA r1,2 mr_pct_x1 LA r7,dw+8 copy the hex string to the msg SR r7,r1 BCTR r1,0 EX r1,mr_mvc2 LA r6,1(r1,r6) B mr_loop mr_pct_d L r7,0(,r3) load decimal ptr LA r3,4(,r3) LA r4,2(,r4) point past '%d' SH r5,=Y(2) BAL re,mr_op r1 - target len, r2 - source len LTR r2,r2 BNZ *+8 LA r2,4 default source len is 4 LA rf,4 SR rf,r2 LA re,15 SRL re,0(rf) EX re,mr_pct_d_icm CVD rf,dw MVC dw2(16),=X'40202020202020202020202020202120' ED dw2(16),dw LTR r1,r1 BNZ mr_pct_d2 LA rf,dw2+16 default length - mr_pct_d1 BCTR rf,0 truncate leading spaces CLI 0(rf),C' ' BH mr_pct_d1 LA r1,dw2+15 SR r1,rf mr_pct_d2 LA r7,dw2+16 SR r7,r1 BCTR r1,0 EX r1,mr_mvc2 LA r6,1(r1,r6) B mr_loop mr_bs MVC 0(1,r6),1(r4) copy char following '\' LA r6,1(,r6) LA r4,2(,r4) SH r5,=Y(2) B mr_loop mr_exit LA r1,msg SR r6,r1 calculate msg length BNP mr_ret TM prt.DCBRECFM,DCBRECCA+DCBRECCM BZ *+8 LA r6,1(,r6) increment for carriage control TM prt.DCBRECFM,DCBRECU BO mr_u TM prt.DCBRECFM,DCBRECF BO mr_f TM prt.DCBRECFM,DCBRECV BO mr_v mr_u CH r6,prt.DCBBLKSI BNH *+8 LH r6,prt.DCBBLKSI STH r6,prt.DCBLRECL PUT prtdcb TM prt.DCBRECFM,DCBRECCA+DCBRECCM BZ mr_u1 MVI 0(r1),C' ' LA r1,1(,r1) BCTR r6,0 TM prt.DCBRECFM,DCBRECCA BO mr_u1 BCTR r1,0 MVI 0(r1),X'09' LA r1,1(,r1) mr_u1 BCTR r6,0 EX r6,mr_mvc3 B mr_ret mr_f CH r6,prt.DCBLRECL BNH *+8 LH r6,prt.DCBLRECL PUT prtdcb TM prt.DCBRECFM,DCBRECCA+DCBRECCM BZ mr_f1 MVI 0(r1),C' ' LA r1,1(,r1) BCTR r6,0 TM prt.DCBRECFM,DCBRECCA BO mr_f1 BCTR r1,0 MVI 0(r1),X'09' LA r1,1(,r1) mr_f1 BCTR r6,0 EX r6,mr_mvc3 B mr_ret mr_v LA r6,4(,r6) LH r1,prt.DCBBLKSI SH r1,=Y(4) CR r6,r1 BNH *+6 LR r6,r1 STH r6,prt.DCBLRECL PUT prtdcb STH r6,0(,r1) XC 2(2,r1),2(r1) LA r1,4(,r1) SH r6,=Y(4) TM prt.DCBRECFM,DCBRECCA+DCBRECCM BZ mr_v1 MVI 0(r1),C' ' LA r1,1(,r1) BCTR r6,0 TM prt.DCBRECFM,DCBRECCA BO mr_v1 BCTR r1,0 MVI 0(r1),X'09' LA r1,1(,r1) mr_v1 BCTR r6,0 EX r6,mr_mvc3 B mr_ret mr_ret LM r0,rf,save2 BR re */* ------------------------------------------------------------------- * message subroutine to get operand lengths * ------------------------------------------------------------------ */ mr_op SLR r1,r1 SLR r2,r2 mr_op1 LTR r5,r5 first number is target length BMR re CLI 0(r4),C'0' BL mr_op2 IC rf,0(,r4) N rf,=A(X'0000000f') MH r1,=Y(10) AR r1,rf LA r4,1(,r4) BCTR r5,0 B mr_op1 mr_op2 CLI 0(r4),C':' second number follows a ':' BNER re mr_op3 LA r4,1(,r4) second number is source length SH r5,=Y(1) BMR re CLI 0(r4),C'0' BLR re IC rf,0(,r4) N rf,=A(X'0000000f') MH r2,=Y(10) AR r2,rf B mr_op3 */* ---------------------------------------------------------------- */ mr_mvc1 MVC 0(0,r6),0(r4) mr_trt1 TRT 0(0,r4),mr_tab1 mr_mvc2 MVC 0(0,r6),0(r7) mr_mvc3 MVC 0(0,r1),msg mr_pct_x_unpk UNPK dw(9),0(0,r7) mr_pct_d_icm ICM rf,0,0(r7) mr_tab1 DC XL256'0' ORG mr_tab1+C'%' DC AL1(4) ORG mr_tab1+C'\' DC AL1(8) ORG mr_tab1+256 mr_hextab EQU *-240 DC C'0123456789abcdef' LTORG , #MSG TYPE=GEN messages DROP , */* ------------------------------------------------------------------- * message open exit - relocated to 24 bit storage * ------------------------------------------------------------------ */ USING mr_oxit,rf USING IHADCB,R1 mr_oxit CLI DCBRECFM,0 any record format ? BNE *+8 jumps if yes MVI DCBRECFM,DCBRECV+DCBRECBR else set to `vb' SLR r0,r0 get a zero CH r0,DCBLRECL any lrecl BNE *+10 jumps if yes MVC DCBLRECL,=Y(125) copy default lrecl CH r0,DCBBLKSI any blksize BNE *+10 jumps if yes MVC DCBBLKSI,=Y(4096) copy default blksize TM DCBRECFM,DCBRECU test record type BO mr_oxitu undefined TM DCBRECFM,DCBRECV test record type BO mr_oxitv variable TM DCBRECFM,DCBRECF test record type BO mr_oxitf fixed B mr_oxit0 unknown, return mr_oxitu MVC DCBLRECL,DCBBLKSI undefined, set lrecl from blksize B mr_oxit0 return mr_oxitv LH r3,DCBBLKSI variable, load blksize LA r0,4 calculate maximum SR r3,r0 lrecl CH r3,DCBLRECL check against lrecl BNL mr_oxit0 return if not too high STH r3,DCBLRECL else reset to max B mr_oxit0 return mr_oxitf LH r3,DCBBLKSI fixed, load blksize SLR r2,r2 clear for divide LH r0,DCBLRECL load lrecl DR r2,r0 divide lrecl into blksize LTR r2,r2 test if any remainder BZ mr_oxit0 return if not MH r3,DCBLRECL calculate new blksize STH r3,DCBBLKSI set new blksize mr_oxit0 BR re LTORG , mr_oxitl EQU *-mr_oxit DROP , */* ------------------------------------------------------------------- * workareas * ------------------------------------------------------------------ */ work DSECT , workid DS 0CL4 identifier save DS 18F standard save area save1 DS 16F save area for read/write save2 DS 16F save area for subroutines result DS F result (return) value flags DS X flag bits ucbpin EQU X'80' offline dasd ucb pinned captucb EQU X'40' offline dasd ucb captured debadded EQU X'20' offline dasd ucb deb added notready EQU X'10' offline ucb `not ready' bit noprint EQU X'01' print ddname not present unit DS H offline unit address bpt DS F cckd file blocks per track heads DS F cckd heads per cylinder trklen DS F cckd track length utrklen DS F unit track length complen DS F compression length devtype DS H cckd device type numl1tab DS F number l1tab entries lasttrk DS F last track lastcyl DS F last cylinder cyls DS F cylinders to write tracks DS F tracks to write track DS F tracks being written trk10pct DS F tracks per status message trkstat DS F write status msg at this trk handle DS F persistent c handle prevcchh DS F previous cchh written curcchh DS F current cchh being written waitecb DS A address of ecb to wait on iobswtch DS F iob flip/flop indicator retcd DS F return code rsncd DS F reason code ucbaddr DS A ucb address cucbaddr DS A captured ucb address debaddr DS A deb address bufs DS 0A i/o area address buf1 DS A buf2 DS A buf3 DS A buf4 DS A ptoken DS D ucb pin token devta DS D devtype area ctime DS D current date/time dtime DS CL20 date/time display area lastblk DS F last cckd 4096 block read ttr DS F ttr for cckd block dw DS D double word work areas dw2 DS D dw3 DS D dw4 DS D sysut1e DS XL(l_sysut1e) cckd file dcbe prtdcbe DS XL(l_prtdcbe) print dcbe pl DS 32F general parameter list openl DS XL(l_openl) open parameter list devhdr DS 0XL(CKDDASD_DEVHDR_SIZE) device header cdevhdr DS XL(CCKDDASD_DEVHDR_SIZE) compressed device header l1tab DS A l1tab address l2tab DS XL(CCKD_L2TAB_SIZE) l2tab msg DS CL256 message tempbuf DS XL4096 temp buffer for cckd read workl EQU *-work work24 DSECT , 24-bit work area work24id DS CL4 identifier zeros DS XL16 24-bit zeroes unitdcb DS XL(l_unitdcb) offline dasd dcb sysut1 DS XL(l_sysut1) sysut1 dcb READ ut1decb,SF,MF=L sysut1 decb prtdcb DS XL(l_prtdcb) sysprint dcb exlst DS F dcb exit list snsidarea DS XL20 device snsid info snsarea DS XL32 device sense rdcarea DS XL64 device characteristics snssarea DS XL40 device snss info ecb1 DS F output ecb 1 ecb2 DS F output ecb 2 iob1 DS XL40 output iob 1 iob2 DS XL40 output iob 2 lrparm1 DS XL16 locate record parameter area 1 lrparm2 DS XL16 locate record parameter area 2 dxarea DS XL16 define extent area openxit DS XL256 relocated message open exit idaw1 DS 255A idaws 1 idaw2 DS 255A idaws 2 ccws DS 258D channel program 1 ccwl EQU *-ccws channel program length ccw2 DS 258D channel program 2 work24l EQU *-work24 RDCinfo DSECT , read device characteristics info RDCsdt DS XL2 storage director type RDCsdmi DS X storage director model information RDCdevt DS XL2 device type RDCdevm DS X device model RDCdasdf DS XL4 device & storage director facilities RDCclass DS X device class code RDCtype DS X device type code RDCprime DS XL2 number of primary cylinders RDCheads DS XL2 tracks per cylinde RDCsctrs DS X number of sectors RDCtrkln DS XL3 total track length (usable) RDChar0 DS XL2 length of ha and r0 RDCtccf DS X track capacity calculation formula RDCfctrs DS XL5 track capacity calculation factors RDCacyl DS XL2 address of first alternate cylinder RDCacyln DS XL2 number of alternate tracks RDCdcyl DS XL2 address of first diagnostic cylinder RDCdcyln DS XL2 number of diagnostic tracks RDCscyl DS XL2 address of first device support cyl RDCscyln DS XL2 number of device support tracks RDCmdrid DS X mdr record id RDCobrid DS X obr record id RDCsdtc DS X storage director type code RDCrtspl DS X read trackset parameter length RDCmaxr0 DS XL2 maximum record zero data length DS X (reserved) RDCtss DS X track set size RDCatccf DS X additional track capacity calc. factr RDCrps DS XL2 rps sector calculation factors DS XL3 (reserved) RDCgdff DS X generic device/cu functions/features DS X (reserved -- zeroes) RDCrduc DS X real control unit code RDCrdc DS X real device code DS XL6 (reserved) RDCinfol EQU *-RDCinfo LRparm DSECT , locate record paramete LRop DS X operation byte LRocount EQU B'00000000' orient count LRohome EQU B'01000000' orient home LRodata EQU B'10000000' orient data LRoindex EQU B'11000000' orient index LRorient EQU X'00' orient LRwrite EQU X'01' write data LRfwrite EQU X'03' format write LRread EQU X'06' read data LRwt EQU X'0b' write track LRrt EQU X'0c' read tracks LRrd EQU X'16' read LRaux DS X auxiliary byte LRusetlf EQU B'10000000' transfer length factor specified LRrcccw EQU B'00000001' a read count ccw is suffixed DS X LRcount DS X count parameter LRseek DS 0XL4 seek addr LRseekcc DS XL2 LRseekhh DS XL2 LRsearch DS 0XL5 search arg LRsrchcc DS XL2 LRsrchhh DS XL2 LRsrchr DS X LRsector DS X LRtlf DS XL2 transfer length factor LRparml EQU *-LRparm CKDDASD_DEVHDR DSECT , devhdr_devid DS CL8 devhdr_heads DS F devhdr_trksize DS F devhdr_devtype DS X devhdr_fileseq DS X devhdr_highcyl DS H DS XL492 CKDDASD_DEVHDR_SIZE EQU *-CKDDASD_DEVHDR CKDDASD_TRKHDR DSECT , trkhdr_bin DS X trkhdr_cyl DS XL2 trkhdr_head DS XL2 CKDDASD_TRKHDR_SIZE EQU *-CKDDASD_TRKHDR CCKDDASD_DEVHDR DSECT , cdevhdr_vrm DS XL3 cdevhdr_options DS X cdevhdr_numl1tab DS F cdevhdr_numl2tab DS F cdevhdr_size DS F cdevhdr_used DS F cdevhdr_free DS F cdevhdr_free_total DS F cdevhdr_free_largest DS F cdevhdr_free_number DS F cdevhdr_free_imbed DS F cdevhdr_cyls DS F DS X cdevhdr_compress DS X cdevhdr_compress_parm DS H DS XL464 CCKDDASD_DEVHDR_SIZE EQU *-CCKDDASD_DEVHDR CCKD_VERSION EQU 0 CCKD_RELEASE EQU 2 CCKD_MODLVL EQU 1 CCKD_NOFUDGE EQU 1 CCKD_BIGENDIAN EQU 2 CCKD_OPENED EQU 128 CCKD_COMPRESS_NONE EQU 0 CCKD_COMPRESS_ZLIB EQU 1 CCKD_COMPRESS_BZIP2 EQU 2 CCKD_COMPRESS_MAX EQU CCKD_COMPRESS_BZIP2 CCKD_L1TAB_POS EQU CKDDASD_DEVHDR_SIZE+CCKDDASD_DEVHDR_SIZE CCKD_L1ENT_SIZE EQU 4 CCKD_NULLTRK_SIZE EQU 37 CCKD_L2ENT DSECT , l2ent_pos DS F l2ent_len DS H l2ent_size DS H CCKD_L2ENT_SIZE EQU *-CCKD_L2ENT CCKD_L2TAB_SIZE EQU 256*CCKD_L2ENT_SIZE */* ------------------------------------------------------------------- * dsects * ------------------------------------------------------------------ */ PRINT NOGEN DCBD DSORG=PS IHADCBE , UCBDSECT DSECT , IEFUCBOB , IEZDEB , DEBLENGTH EQU (DEBBASND-DEBAVT)+(DEBDASDE-DEBDASD)+DEBXLEN IEZIOB , IHAECB , IOSDCCW , CVT DSECT=YES IHAPSA , IKJTCB , STAR TRKCALC MF=D */* ------------------------------------------------------------------- * equates * ------------------------------------------------------------------ */ SK EQU X'07' SNSID EQU X'e4' SNS EQU X'04' RDC EQU X'64' SNSS EQU X'54' RT EQU X'de' DX EQU X'63' LR EQU X'47' WR0 EQU X'15' WCKD EQU X'1d' TIC EQU X'08' r0 EQU 0 r1 EQU 1 r2 EQU 2 r3 EQU 3 r4 EQU 4 r5 EQU 5 r6 EQU 6 r7 EQU 7 r8 EQU 8 r9 EQU 9 ra EQU 10 rb EQU 11 rc EQU 12 rd EQU 13 re EQU 14 rf EQU 15 END , hercules-3.07/util/cvslvlck000755 000765 000765 00000017324 11143760541 017506 0ustar00jmaynardjmaynard000000 000000 #!/usr/bin/perl -w #**************************************************************************** # # $Id: cvslvlck 4495 2007-11-30 14:32:13Z jmaynard $ # # C V S L V L C K # # This perl script checks the user's system for the required levels of # software required to properly build Hercules from the CVS repository. # #**************************************************************************** # # ---- CHANGE LOG ---- # $Log$ # Revision 1.12 2006/12/25 13:55:19 jj # Add cvs message log # # # DD/MM/YY Description... # 21/09/03 Removed libintl & libtool. Although "gettextize" is no longer # run, pkg "gettext" is still needed to run the msgfmt/msgmerge # utilities. libintl is now self-contained. libtool is now self- # contained. (ISW) # 24/10/05 Added history section in preparation for possible changes. (Fish) # 24/10/05 According to jj, automake 1.6 is insufficient. He says 1.9 works # though, but doesn't know about 1.7 or 1.8 yet. (Fish) # 30/11/07 Changed URL to point to hercules-390.org. (JRM) #**************************************************************************** use strict; # Facility, required level, special flag, download URL my @req = qw( cvs 0 1 http://www.cvshome.org autoconf 2.5 0 http://www.gnu.org/directory/autoconf.html automake 1.9 0 http://www.gnu.org/directory/automake.html flex 2.5 0 http://www.gnu.org/directory/flex.html gawk 3.0 0 http://www.gnu.org/directory/gawk.html gcc 2.95 0 http://www.gnu.org/directory/gcc.html gettext 0.11 0 http://www.gnu.org/directory/gettext.html grep 0 0 http://www.gnu.org/directory/grep.html libiconv 1.8 1 http://www.gnu.org/directory/libiconv.html m4 0.0 1 http://www.gnu.org/directory/GNU/gnum4.html make 3.79 0 http://www.gnu.org/directory/make.html perl 5.6 1 http://www.gnu.org/directory/perl/html sed 3.02 0 http://www.gnu.org/directory/sed.html ); my $cvsroot = ":pserver:anonymous\@cvs.hercules-390.org:/usr/cvs/hercules"; my $msg; my $instversion; sayintro(); for (my $i = 0; $i < @req; $i += 4) { my $facility = $req[$i]; my $level = $req[$i+1]; my $special = $req[$i+2]; my $url = $req[$i+3]; if ($special) { weird($facility, $level, $url); } else { if (present($facility, $url)) { my @resp = `$facility --version`; chomp $resp[0]; $instversion = getvers($resp[0]); $msg = ckvers($level, $instversion); print "$msg\t$facility requires $level, found $instversion\n"; print "\tURL: $url\n" if $msg eq 'UPGRADE'; } } print "\n"; } print "Do you wish to set CVSROOT for this userid? (y, n, default y)\n"; print "New CVS users are recommended to reply y to this prompt.\n"; my $ans = ; chomp $ans; $ans = substr($ans, 0, 1); $ans = lc $ans; if ($ans eq 'y' || $ans eq '') { die "HOME environment variable not set" if ! exists $ENV{'HOME'}; my $home = $ENV{'HOME'}; # root nonsense, ~ doesn't work right unless (open PROFILE, ">> $home/.profile") {die "Open $home/.profile failed: $!"}; print PROFILE "\nCVSROOT=$cvsroot ; export CVSROOT\n"; close PROFILE; print "Updated $home/.profile for CVSROOT\n"; print "To use updated CVSROOT value, open new session or logout/login\n"; # Sorry, I can't figure out how to set CVSROOT in current session # I tried system, exec, creating a shell script ... nada } else { print "Hercules CVSROOT=$cvsroot\n"; } exit 0; sub weird { my ($facility, $level, $url) = @_; if ($facility eq 'cvs') { if (present('cvs', $url)) { my @resp = `cvs --version`; chomp $resp[1]; my $instversion = getvers($resp[1]); my $msg = ckvers($level, $instversion); print "$msg\t$facility (informational), found $instversion\n"; } else { print "INSTALL\tcvs\n"; print "URL: $url\n"; } return; } if ($facility eq 'libiconv') { if (present('iconv', $url)) { my @resp = `iconv --version`; chomp $resp[0]; my $instversion = getvers($resp[0]); my $msg = ckvers($level, $instversion); print "$msg\t$facility requires $level, found $instversion\n"; } print "\tFor first-time Libiconv installs, a recompile and reinstall of gettext\n"; print "\tis recommended. Source: libiconv-1.8/README\n"; print "\tURL: $url\n" if $msg eq 'UPGRADE'; return; } if ($facility eq 'perl') { if (present($facility, $url)) { my @resp = `perl --version`; chomp $resp[1]; my $instversion = getvers($resp[1]); my $msg = ckvers($level, $instversion); print "$msg\t$facility requires $level, found $instversion\n"; print "\tURL: $url\n" if $msg eq 'UPGRADE'; } return; } if ($facility eq 'libtool') { if (present($facility, $url)) { my @resp = `libtoolize --version`; print "\t$resp[0]\n"; chomp $resp[0]; my $instversion = getvers($resp[0]); my $msg = ckvers($level, $instversion); print "$msg\t$facility requires $level, found $instversion\n"; print "\tURL: $url\n" if $msg eq 'UPGRADE'; } return; } if ($facility eq 'libintl') { my @filelist = glob '/lib/libc.so.*'; if (@filelist) { print "OK\tYou are running on a glibc system ($filelist[0] exists)\n"; print "\tgettext-0.11.5/PACKAGING says libintl is not installed on glibc systems.\n"; } else { print "\tWARNING: I have no personal experience with non-glibc systems\n"; print "\t so take this result as my best guess.\n"; my @libintl = glob '/lib/libintl.so.*'; if (@libintl) { foreach my $lib (@libintl) { my $msg = ckvers($level, $instversion); if ($msg eq 'OK') { print "OK\t$facility requires $level, found $instversion\n"; return; } print "UPGRADE?\t$facility requires $level\n"; print "INSTALL\tLibintl is included in the gettext source tarball.\n"; print "\tURL: $url\n"; return; } } else { print "INSTALL\tLibintl is included in the gettext source tarball.\n"; print "\tURL: $url\n"; } } return; } if ($facility eq 'm4') { # m4 --version: GNU m4 1.4o if (present($facility, $url)) { my $resp = `m4 --version`; chomp $resp; my $msg = 'HUH? '; my $instversion = "DUNNO"; if ($resp =~ /GNU [mM]4 (\d+.\d+)/) { $instversion = ''; $instversion = $1 if defined $1; $instversion = "$1.$2" if defined $1 && defined $2; $msg = ckvers($level, $instversion); } print "$msg\t$facility requires $level, found $instversion\n"; print "\tURL: $url\n" if $msg eq 'UPGRADE'; } return; } print "ERROR $facility flagged as special, not found\n"; } sub getvers { my $resp = $_[0]; my $vers; if ($resp =~ /(\d+).(\d+).(\d+)/) { $vers = "$1.$2.$3"; return $vers; } if ($resp =~ /(\d+).(\d+)/) { $vers = "$1.$2"; return $vers; } print "HUH?\n"; } sub ckvers { my ($reqvers, $instvers) = @_; my @rv = split /\./, $reqvers; my @iv = split /\./, $instvers; for (my $i = 0; $i < @rv; $i++) { if ( (exists $rv[$i]) && (exists $iv[$i]) && ($iv[$i] > $rv[$i]) ) { return 'OK'; } if ( (exists $rv[$i]) && (exists $iv[$i]) && ($iv[$i] < $rv[$i]) ) { return 'UPGRADE'; } } return 'OK'; } sub sayintro { print "This utility will check the level of various utilities needed to build\n"; print "hercules. Checking is done against versions that are KNOWN to work.\n"; print "This doesn't mean a build will NOT succeed with older versions\n"; print "of the utilities, but will give a hint as to what package may need\n"; print "an upgrade if the build ever fails with some odd reason.\n\n\n"; } sub present { my ($facility, $url) = @_; my @present = `which $facility 2>/dev/null`; if (! @present) { print "INSTALL\t$facility not found\n"; print "\tURL: $url\n"; } return scalar @present; } hercules-3.07/util/dasdlist000755 000765 000765 00000002540 11143760541 017460 0ustar00jmaynardjmaynard000000 000000 #!/bin/sh # # This command prints a track from a CKD DASD image file. # It uses the Unix Octal Dump (od) command to firstly obtain # the device geometry from the CKD header, and secondly to # print the track in hexadecimal format. # filename=$1 cyl=$2 head=$3 if [ -z "$filename" ]; then echo "Usage: dasdlist filename [cyl head]" exit 1 fi if [ ! -f $filename ]; then echo "File $filename does not exist" exit 1 fi # # Check the first 8 bytes of the header for valid CKD DASD image file # ckdid=`head -n 1 $filename | cut -c1-8` if [ $ckdid != "CKD_P370" ]; then echo "File $filename is not a CKD DASD image file" exit 2 fi # # The next 8 bytes contain the tracks/cyl and track length constants # heads=`od -An -tu4 -j 8 -N 4 $filename` trklen=`od -An -tu4 -j 12 -N 4 $filename` heads=`expr $heads` trklen=`expr $trklen` echo "$filename $heads trks/cyl, $trklen bytes/trk" # # If cylinder number is not given then exit # if [ -z "$cyl" ] || [ -z "$head" ]; then echo "To dump a track specify dasdlist $filename cyl head" exit 0 fi # # Calculate the offset to the requested cylinder and track # offset=`expr 512 + '(' $cyl '*' $heads + $head ')' '*' $trklen` num=`expr $trklen` # # Dump the requested track # echo "$filename Cyl $cyl Head $head" echo "od -Ax -tx1 -j $offset -N $num $filename" od -Ax -tx1 -j $offset -N $num $filename hercules-3.07/util/dasdlist.bat000755 000765 000765 00000000035 11143760541 020222 0ustar00jmaynardjmaynard000000 000000 bash dasdlist %1 %2 %3 %4 %5 hercules-3.07/util/Makefile.am000644 000765 000765 00000000362 11143760541 017757 0ustar00jmaynardjmaynard000000 000000 bin_SCRIPTS = dasdlist cvslvlck dist_pkgdata_DATA = cckddump.hla awswrite.jcl rawstape.jcl tapeconv.jcl\ TMOUNT.txt \ zzsacard.bin awssl-v19g cckdload.hla EXTRA_DIST = dasdlist dasdlist.bat cvslvlck hercules-3.07/util/Makefile.in000644 000765 000765 00000030666 11344713141 017777 0ustar00jmaynardjmaynard000000 000000 # Makefile.in generated by automake 1.9.6 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = .. am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd INSTALL = @INSTALL@ install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = util DIST_COMMON = $(dist_pkgdata_DATA) $(srcdir)/Makefile.am \ $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/autoconf/hercules.m4 \ $(top_srcdir)/autoconf/libtool.m4 \ $(top_srcdir)/autoconf/ltdl.m4 $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(SHELL) $(top_srcdir)/autoconf/mkinstalldirs CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(pkgdatadir)" binSCRIPT_INSTALL = $(INSTALL_SCRIPT) SCRIPTS = $(bin_SCRIPTS) SOURCES = DIST_SOURCES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; dist_pkgdataDATA_INSTALL = $(INSTALL_DATA) DATA = $(dist_pkgdata_DATA) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BUILD_FISHHANG_FALSE = @BUILD_FISHHANG_FALSE@ BUILD_FISHHANG_TRUE = @BUILD_FISHHANG_TRUE@ BUILD_FTHREADS_FALSE = @BUILD_FTHREADS_FALSE@ BUILD_FTHREADS_TRUE = @BUILD_FTHREADS_TRUE@ BUILD_HERCIFC_FALSE = @BUILD_HERCIFC_FALSE@ BUILD_HERCIFC_TRUE = @BUILD_HERCIFC_TRUE@ BUILD_SHARED_FALSE = @BUILD_SHARED_FALSE@ BUILD_SHARED_TRUE = @BUILD_SHARED_TRUE@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CONVENIENCE_LTDL_FALSE = @CONVENIENCE_LTDL_FALSE@ CONVENIENCE_LTDL_TRUE = @CONVENIENCE_LTDL_TRUE@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ ECHO = @ECHO@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ F77 = @F77@ FFLAGS = @FFLAGS@ GMSGFMT = @GMSGFMT@ GREP = @GREP@ HERCIFC_GROUPNAME = @HERCIFC_GROUPNAME@ HERCIFC_GROUPSET_FALSE = @HERCIFC_GROUPSET_FALSE@ HERCIFC_GROUPSET_TRUE = @HERCIFC_GROUPSET_TRUE@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_LTDL_FALSE = @INSTALL_LTDL_FALSE@ INSTALL_LTDL_TRUE = @INSTALL_LTDL_TRUE@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ LDFLAGS = @LDFLAGS@ LIBADD_DL = @LIBADD_DL@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBTOOL_DEPS = @LIBTOOL_DEPS@ LN_S = @LN_S@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@ MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@ MAKEINFO = @MAKEINFO@ MKINSTALLDIRS = @MKINSTALLDIRS@ MSGFMT = @MSGFMT@ MSGMERGE = @MSGMERGE@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPTION_DYNAMIC_LOAD_FALSE = @OPTION_DYNAMIC_LOAD_FALSE@ OPTION_DYNAMIC_LOAD_TRUE = @OPTION_DYNAMIC_LOAD_TRUE@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ POSUB = @POSUB@ RANLIB = @RANLIB@ SETUID_HERCIFC_FALSE = @SETUID_HERCIFC_FALSE@ SETUID_HERCIFC_TRUE = @SETUID_HERCIFC_TRUE@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ USE_DLLTOOL_FALSE = @USE_DLLTOOL_FALSE@ USE_DLLTOOL_TRUE = @USE_DLLTOOL_TRUE@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_F77 = @ac_ct_F77@ am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ modexecdir = @modexecdir@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ bin_SCRIPTS = dasdlist cvslvlck dist_pkgdata_DATA = cckddump.hla awswrite.jcl rawstape.jcl tapeconv.jcl\ TMOUNT.txt \ zzsacard.bin awssl-v19g cckdload.hla EXTRA_DIST = dasdlist dasdlist.bat cvslvlck all: all-am .SUFFIXES: $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ && exit 0; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu util/Makefile'; \ cd $(top_srcdir) && \ $(AUTOMAKE) --gnu util/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh install-binSCRIPTS: $(bin_SCRIPTS) @$(NORMAL_INSTALL) test -z "$(bindir)" || $(mkdir_p) "$(DESTDIR)$(bindir)" @list='$(bin_SCRIPTS)'; for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ if test -f $$d$$p; then \ f=`echo "$$p" | sed 's|^.*/||;$(transform)'`; \ echo " $(binSCRIPT_INSTALL) '$$d$$p' '$(DESTDIR)$(bindir)/$$f'"; \ $(binSCRIPT_INSTALL) "$$d$$p" "$(DESTDIR)$(bindir)/$$f"; \ else :; fi; \ done uninstall-binSCRIPTS: @$(NORMAL_UNINSTALL) @list='$(bin_SCRIPTS)'; for p in $$list; do \ f=`echo "$$p" | sed 's|^.*/||;$(transform)'`; \ echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \ rm -f "$(DESTDIR)$(bindir)/$$f"; \ done mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs distclean-libtool: -rm -f libtool uninstall-info-am: install-dist_pkgdataDATA: $(dist_pkgdata_DATA) @$(NORMAL_INSTALL) test -z "$(pkgdatadir)" || $(mkdir_p) "$(DESTDIR)$(pkgdatadir)" @list='$(dist_pkgdata_DATA)'; for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ f=$(am__strip_dir) \ echo " $(dist_pkgdataDATA_INSTALL) '$$d$$p' '$(DESTDIR)$(pkgdatadir)/$$f'"; \ $(dist_pkgdataDATA_INSTALL) "$$d$$p" "$(DESTDIR)$(pkgdatadir)/$$f"; \ done uninstall-dist_pkgdataDATA: @$(NORMAL_UNINSTALL) @list='$(dist_pkgdata_DATA)'; for p in $$list; do \ f=$(am__strip_dir) \ echo " rm -f '$(DESTDIR)$(pkgdatadir)/$$f'"; \ rm -f "$(DESTDIR)$(pkgdatadir)/$$f"; \ done tags: TAGS TAGS: ctags: CTAGS CTAGS: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ list='$(DISTFILES)'; for file in $$list; do \ case $$file in \ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ esac; \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ if test "$$dir" != "$$file" && test "$$dir" != "."; then \ dir="/$$dir"; \ $(mkdir_p) "$(distdir)$$dir"; \ else \ dir=''; \ fi; \ if test -d $$d/$$file; then \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ fi; \ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(SCRIPTS) $(DATA) installdirs: for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(pkgdatadir)"; do \ test -z "$$dir" || $(mkdir_p) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic distclean-libtool dvi: dvi-am dvi-am: html: html-am info: info-am info-am: install-data-am: install-dist_pkgdataDATA install-exec-am: install-binSCRIPTS install-info: install-info-am install-man: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binSCRIPTS uninstall-dist_pkgdataDATA \ uninstall-info-am .PHONY: all all-am check check-am clean clean-generic clean-libtool \ distclean distclean-generic distclean-libtool distdir dvi \ dvi-am html html-am info info-am install install-am \ install-binSCRIPTS install-data install-data-am \ install-dist_pkgdataDATA install-exec install-exec-am \ install-info install-info-am install-man install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am uninstall uninstall-am \ uninstall-binSCRIPTS uninstall-dist_pkgdataDATA \ uninstall-info-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: hercules-3.07/util/rawstape.jcl000644 000765 000765 00000032065 11143760541 020250 0ustar00jmaynardjmaynard000000 000000 //IBMUSERA JOB ,'JAN JAEGER',NOTIFY=IBMUSER,CLASS=A,MSGCLASS=A 00000103 //ASMA90 EXEC PGM=ASMA90,PARM='DECK,NOOBJ,XREF(SHORT)' 00000200 //SYSPRINT DD SYSOUT=* 00000300 //SYSLIB DD DSN=SYS1.MACLIB,DISP=SHR 00000400 // DD DSN=SYS1.MODGEN,DISP=SHR 00000500 //SYSUT1 DD UNIT=SYSDA,SPACE=(CYL,10) 00000600 //SYSPUNCH DD DSN=&&PUNCH,DISP=(NEW,PASS), 00000700 // UNIT=SYSALLDA,SPACE=(CYL,10) 00000800 RAWSTAPE TITLE 'Convert file from AWSTAPE format' 00000900 *---------------------------------------------------------------------* 00001000 * Function: * 00001100 * This program converts an AWSTAPE format file to RECFM=U * 00001200 * SYSUT1 is converted reblocked according to the AWS * 00001300 * header records. The blocksize of SYSUT2 can be reset * 00001400 * using IEBGENER * 00001500 * The parm field indicates the filenumber to be extracted, * 00001600 * this number has the same value as when using BLP in JCL. * 00001700 *---------------------------------------------------------------------* 00001800 RAWSTAPE CSECT 00001900 LR R12,R15 Load base register 00002000 USING RAWSTAPE,R12 Establish addressability 00002100 L R2,0(,R1) PARM= 00002200 LH R3,0(,R2) L'PARM 00002300 LTR R3,R3 00002400 BZ NOPARM No parm field 00002500 BCTR R3,0 Reduce to Machine length 00002600 EX R3,EXPACK 00002700 CVB R3,DWORD 00002800 ST R3,FILENUM Filenumber to be read 00002900 NOPARM DS 0H 00003000 OPEN (SYSUT1,INPUT) Open input DCB 00003100 TM SYSUT1+48,X'10' Is DCB open? 00003200 BZ EXIT020 No, exit with RC=20 00003300 OPEN (SYSUT2,OUTPUT) Open output DCB 00003400 TM SYSUT2+48,X'10' Is DCB open? 00003500 BZ EXIT020 No, exit with RC=20 00003600 LA R2,BUFFER 00003700 SLR R3,R3 Total number of bytes in buffer 00003800 LA R5,1 We start at file 1 00003900 READBLK DS 0H 00004000 LA R2,BUFFER(R3) 00004100 GET SYSUT1,(2) Get input block 00004200 AH R3,SYSUT1+82 R3=total bytes in buffer 00004300 GETNEXT DS 0H 00004400 CH R3,=Y(L'HEADER) Do we at least have the header 00004500 BM READBLK 00004600 TM HDRFLAG1,HDRF1TMK Take mark? 00004700 BZ NOEOF 00004800 LA R5,1(,R5) Increment file number 00004900 C R5,FILENUM Beyond requested file? 00005000 BH EXIT000 00005100 NOEOF DS 0H 00005200 SLR R4,R4 Logical block length 00005300 ICM R4,B'0001',HDRCURLN Load low-order length byte 00005400 ICM R4,B'0010',HDRCURLN+1 Load high-order length byte 00005500 LA R1,L'HEADER(,R4) 00005600 CR R3,R1 Full block yet? 00005700 BM READBLK No: Fetch another 00005800 C R5,FILENUM Is this the file we want? 00005900 BNE NOPUT 00006000 TM HDRFLAG1,HDRF1BOR+HDRF1EOR 00006100 BM EXIT016 00006200 BNO NOPUT 00006300 LA R2,DATA Skip AWS header 00006400 STH R4,SYSUT2+82 Store block size 00006500 PUT SYSUT2,(2) Write block 00006600 NOPUT DS 0H 00006700 AH R4,=Y(L'HEADER) Remove header 00006800 SLR R3,R4 Remove block 00006900 LA R2,BUFFER Back to start 00007000 LR R6,R2 Move remainder to beginning 00007100 LA R8,0(R4,R2) Point past block 00007200 LR R7,R3 Set length 00007300 LR R9,R3 00007400 MVCL R6,R8 Move block 00007500 B GETNEXT 00007600 * 00007700 EXIT000 DS 0H 00007800 CLOSE (SYSUT1,,SYSUT2) Close DCBs 00007900 SR R15,R15 Zeroize return code 00008000 SVC 3 Exit with RC=0 00008100 EXIT012 DS 0H 00008200 LA R15,12 Premature EOF 00008300 SVC 3 Exit with RC=12 00008400 EXIT016 DS 0H 00008500 LA R15,16 Invalid record type 00008600 SVC 3 Exit with RC=16 00008700 EXIT020 DS 0H 00008800 LA R15,20 DD statement missing 00008900 SVC 3 Exit with RC=20 00009000 * 00009100 * EXecuted 00009200 * 00009300 EXPACK PACK DWORD,2(0,2) 00009400 DROP R12 Drop base register 00009500 * 00009600 * Variables 00009700 * 00009800 FILENUM DC F'1' 00009900 DWORD DS D 00010000 * 00010100 * Data Control Blocks 00010200 * 00010300 PRINT NOGEN 00010400 SYSUT1 DCB DSORG=PS,MACRF=GM,DDNAME=SYSUT1,EODAD=EXIT012, X00010500 RECFM=U,LRECL=0,BLKSIZE=32760 00010600 SYSUT2 DCB DSORG=PS,MACRF=PM,DDNAME=SYSUT2, X00010700 RECFM=U,LRECL=0,BLKSIZE=32760 00010800 LTORG 00010900 * 00011000 BUFFER DS 0C 00011100 * 00011200 * AWSTAPE block header 00011300 * 00011400 HEADER DS 0CL6 Block header 00011500 HDRCURLN DS XL2 Current block length 00011600 HDRPRVLN DS XL2 Previous block length 00011700 HDRFLAG1 DS X'00' Flags byte 1... 00011800 HDRF1BOR EQU X'80' ...beginning of record 00011900 HDRF1TMK EQU X'40' ...tape mark 00012000 HDRF1EOR EQU X'20' ...end of record 00012100 HDRFLAG2 DS X'00' Flags byte 2 00012200 * 00012300 * Data 00012400 * 00012500 DATA DS 0C 00012600 DS 65536C 00012700 * 00012800 * Register equates 00012900 * 00013000 R0 EQU 0 00013100 R1 EQU 1 00013200 R2 EQU 2 00013300 R3 EQU 3 00013400 R4 EQU 4 00013500 R5 EQU 5 00013600 R6 EQU 6 00013700 R7 EQU 7 00013800 R8 EQU 8 00013900 R9 EQU 9 00014000 R10 EQU 10 00014100 R11 EQU 11 00014200 R12 EQU 12 00014300 R13 EQU 13 00014400 R14 EQU 14 00014500 R15 EQU 15 00014600 END 00014700 //IEWL EXEC PGM=IEWL 00014800 //SYSPRINT DD SYSOUT=* 00014900 //SYSUT1 DD UNIT=SYSDA,SPACE=(CYL,10) 00015000 //SYSLMOD DD DSN=IBMUSER.LOAD(RAWSTAPE),DISP=SHR 00015100 //SYSLIN DD DSN=&&PUNCH,DISP=(OLD,DELETE) 00015200 //* 00015300 //CONVERT EXEC PGM=*.IEWL.SYSLMOD,PARM=3 00016704 //SYSUDUMP DD SYSOUT=* 00016800 //SYSUT1 DD DISP=SHR,DSN=IBMUSER.SADUMP.AWS 00016900 //SYSUT2 DD DSN=IBMUSER.SADUMP,DISP=(NEW,CATLG), 00017000 // UNIT=SYSALLDA,SPACE=(TRK,1200,RLSE) 00018000 //* 00019000 //SETDCB EXEC PGM=IEBGENER 00020000 //SYSPRINT DD SYSOUT=* 00030000 //SYSIN DD DUMMY 00040000 //SYSUT1 DD DUMMY, 00050000 // DCB=(DSORG=PS,RECFM=FBS,LRECL=4160,BLKSIZE=29120) 00060000 //SYSUT2 DD DISP=MOD,DCB=(*.SYSUT1),DSN=IBMUSER.SADUMP 00070000 hercules-3.07/util/tapeconv.jcl000644 000765 000765 00000024532 11143760541 020241 0ustar00jmaynardjmaynard000000 000000 //IBMUSERA JOB CLASS=A,MSGCLASS=A,MSGLEVEL=(1,1) 00010000 //ASMCLG PROC 00020000 //IEUASM EXEC PGM=ASMA90,PARM='NOOBJECT,DECK',REGION=4M 00030000 //SYSPRINT DD SYSOUT=* 00040000 //SYSLIB DD DSN=SYS1.MACLIB,DISP=SHR 00050000 // DD DSN=SYS1.MODGEN,DISP=SHR 00060000 //SYSUT1 DD UNIT=SYSDA,SPACE=(CYL,(5,5)) 00070000 //SYSPUNCH DD DSN=&&OBJSET,DISP=(,PASS),UNIT=SYSDA, 00080000 // SPACE=(TRK,(5,5)),DCB=(RECFM=FB,LRECL=80,BLKSIZE=3120) 00090000 //IEWL EXEC PGM=IEWL,PARM='LIST,LET,NCAL,MAP', 00100000 // COND=(0,NE,IEUASM),REGION=4M 00110000 //SYSPRINT DD SYSOUT=* 00120000 //SYSUT1 DD UNIT=SYSDA,SPACE=(CYL,(5,5)) 00130000 //SYSLIN DD DSN=&&OBJSET,DISP=(OLD,DELETE) 00140000 //SYSLMOD DD DSN=&&GOSET(GO),DISP=(,PASS),UNIT=SYSDA, 00150000 // SPACE=(TRK,(5,5,5)),DCB=(RECFM=U,BLKSIZE=6144) 00160000 //GO EXEC PGM=*.IEWL.SYSLMOD,COND=((0,NE,IEUASM),(0,NE,IEWL)) 00170000 //SYSUT1 DD DSN=TAPE.DATASET,UNIT=3480,VOL=SER=AAAAAA,DISP=OLD 00180000 //SYSUT2 DD DSN=IBMUSER.AWSTAPE.DATASET,DISP=(,CATLG), 00181000 // UNIT=SYSDA,VOL=SER=VVVVVV,SPACE=(CYL,(5,5),RLSE) 00181100 // PEND 00182000 //ASMCLG EXEC ASMCLG 00183000 TAPECONV TITLE 'Convert file to AWSTAPE format' 00184000 *---------------------------------------------------------------------* 00185000 * Function: * 00186000 * This program converts a tape file to AWSTAPE format. * 00187000 * It reads undefined length blocks of data from SYSUT1 and * 00188000 * writes each block, prefixed by a 6-byte header, to SYSUT2. * 00189000 * * * Modification by Charlie Brint: * * This program has been modified from its original Hercules * * source format to handle blocks > 32K and < 64k because the * * default blksize for ADRDSSU is 65,520 in most installations * * and the original TAPECONV would just truncate blocks at * * 32,760 bytes without giving any error indication. As a side * * benefit, SYSUT2 can reside on disk even if SYSUT1 is an * * ADRDSSU dump tape with blocks longer than 32760 because the * * program never writes blocks longer than 32760 to SYSUT2. * * NOTE: This version uses the Large Block Interface (LBI) and * * thus requires OS/390 V2R10 or z/OS to assemble and run. * * For earlier versions of MVS, the program still assembles and * * runs (without LBI) if you replace &LBI SETB 1 by &LBI SETB 0 * *---------------------------------------------------------------------* 00226000 GBLB &LBI &LBI SETB 1 1=use LBI, 0=do not use LBI TAPECONV CSECT 03740000 LR R12,R15 Load base register 03750000 USING TAPECONV,R12 Establish addressability 03760000 OPEN (SYSUT1,INPUT) Open input DCB 03770000 TM SYSUT1+48,X'10' Is DCB open? 03780000 BZ EXIT020 No, exit with RC=20 03790000 OPEN (SYSUT2,OUTPUT) Open output DCB 03791000 TM SYSUT2+48,X'10' Is DCB open? 03792000 BZ EXIT020 No, exit with RC=20 03793000 GENLOOP EQU * 03800000 GET SYSUT1 Get input block 03810000 LR R2,R1 R2=>input block 03811000 LH R4,SYSUT1+82 R4=actual block length 03820000 AIF (NOT &LBI).LBIN1 L R15,SYSUT1+68 Get IOB address SH R15,=H'4' Reduce by 4 as per LBI docs L R4,0(R15) R4 should now be the blk leng .LBIN1 ANOP , LR R5,R4 Copy length for later use C R4,=F'65520' Is the block > 65520 ? BH EXIT020 yes, take error exit C R4,=F'32760' Is the block > 32760 ? BNH UNDER32 no, skip L R4,=F'32760' yes, set write length to max UNDER32 DS 0H MVC HDRPRVLN,HDRCURLN Copy previous block length 03830000 STCM R5,B'0001',HDRCURLN Store low-order length byte STCM R5,B'0010',HDRCURLN+1 Store high-order length byte MVI HDRFLAG1,HDRF1BOR+HDRF1EOR Set complete record flags MVC SYSUT2+82(2),=H'6' Set header length in DCB 03851001 PUT SYSUT2,HEADER Write block header to SYSUT2 03860000 STH R4,SYSUT2+82 Set block length in DCB 03870001 PUT SYSUT2,(R2) Write data block to SYSUT2 03880000 CR R4,R5 Did we write all the data ? BE GENLOOP yes, go back for next record ALR R2,R4 no, bump input block pointer SR R5,R4 Compute remaining length STH R5,SYSUT2+82 Set remaining length in DCB PUT SYSUT2,(R2) Write the rest of the block B GENLOOP Go back for next record 03890000 GENEOF DS 0H 03900000 MVC HDRPRVLN,HDRCURLN Copy previous block length 03901000 XC HDRCURLN,HDRCURLN Clear current block length 03901100 MVI HDRFLAG1,HDRF1TMK Set tape mark flag MVC SYSUT2+82(2),=H'6' Set header length in DCB 03902001 PUT SYSUT2,HEADER Write block header to SYSUT2 03903000 CLOSE (SYSUT1,,SYSUT2) Close DCBs 03910000 SR R15,R15 Zeroize return code 03920000 SVC 3 Exit with RC=0 03930000 EXIT020 DS 0H 04050000 LA R15,20 DD statement missing 04060000 SVC 3 Exit with RC=20 04070000 DROP R12 Drop base register 04080000 * 04081000 * AWSTAPE block header 04082000 * 04083000 HEADER DS 0CL6 Block header 04090000 HDRCURLN DC XL2'0000' Current block length 04100100 HDRPRVLN DC XL2'0000' Previous block length 04100202 HDRFLAG1 DC X'00' Flags byte 1... 04100300 HDRF1BOR EQU X'80' ...beginning of record HDRF1TMK EQU X'40' ...tape mark HDRF1EOR EQU X'20' ...end of record HDRFLAG2 DC X'00' Flags byte 2 * 04100400 * Data Control Blocks 04100500 * 04100600 AIF (&LBI).LBID1 SYSUT1 DCB DSORG=PS,MACRF=GL,DDNAME=SYSUT1,EODAD=GENEOF, X04110000 RECFM=U,LRECL=0,BLKSIZE=32760 04120000 AGO .LBID2 .LBID1 ANOP , SYSUT1 DCB DSORG=PS,MACRF=GL,DDNAME=SYSUT1,EODAD=GENEOF, X RECFM=U,LRECL=0,DCBE=MYDCBE MYDCBE DCBE BLKSIZE=65520 DCB extension, new in OS/390 V2R10 .LBID2 ANOP , SYSUT2 DCB DSORG=PS,MACRF=PM,DDNAME=SYSUT2, X04121000 RECFM=U,LRECL=0,BLKSIZE=32760 04122000 LTORG 04130000 * 04431000 * Register equates 04432000 * 04433000 R0 EQU 0 04434000 R1 EQU 1 04435000 R2 EQU 2 04436000 R3 EQU 3 04437000 R4 EQU 4 04438000 R5 EQU 5 04439000 R6 EQU 6 04440000 R7 EQU 7 04450000 R8 EQU 8 04460000 R9 EQU 9 04470000 R10 EQU 10 04480000 R11 EQU 11 04490000 R12 EQU 12 04500000 R13 EQU 13 04510000 R14 EQU 14 04520000 R15 EQU 15 04530000 END 04540000 hercules-3.07/util/TMOUNT.txt000644 000765 000765 00000017612 11143760541 017520 0ustar00jmaynardjmaynard000000 000000 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fish note: The length of the filename is not limted to 17 characters as the below sample states. Rather, the length of the filename is limited solely by the host filesystem code. On Windows, filenames can be up to 260 characters long. (or even longer if "\\?\" format is used!) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ * $$ JOB JNM=TMOUNT,DISP=D,CLASS=0 // JOB TMOUNT COMPILE PROGRAM TMOUNT // LIBDEF *,CATALOG=PRD2.CONFIG // OPTION ERRS,SXREF,SYM,NODECK,CATAL PHASE TMOUNT,* // EXEC ASMA90,SIZE=(ASMA90,64K),PARM='EXIT(LIBEXIT(EDECKXIT)),SIZE(MAXC -200K,ABOVE)' TMOUNT CSECT SPACE 1 *--------------------------------------------------------------------- * * TMOUNT - VSE VERSION II * * THE TMOUNT COMMAND IS USED FROM VSE ON THE P/390 TO TELL THE * AWSTAPE MANAGER WHICH OS/2 FILE TO USE WHEN THE USER WRITES TO * THIS DEVICE. IT CAN ALSO BE USED TO QUERY WHAT OS/2 FILE IS * CURRENTLY ASSOCIATED WITH THE DEVICE. * * TWO SPECIAL CCW OPCODES ARE SUPPORTED BY THE AWSTAPE EMULATOR: * X'4B' - ASSIGN A DOS FILEID TO THE DEVICE. (WAS '4B' 6/30) * X'E4' - SENSE FILEID - RETURN THE NAME OF THE ASSIGNED DOS FILE * * THE EMULATED TAPE HAS TO BE ASSIGNED TO SYS014 * * E.G // JOB TMOUNT * // ASSGN SYS014,580 * // EXEC TMOUNT,REAL,SIZE=AUTO,PARM='580 D:TEST.TAP' * OR * // EXEC TMOUNT,REAL,SIZE=AUTO,PARM='580 (QUERY' * /* * /& * * AWSTAPE HAS A LIMIT OF 17 CHARACTERS IN A DOS FILEID. THAT * LIMIT IS ENFORCED ENTIRELY IN AWSTAPE. * * THIS PROGRAM IS PROVIDED ON AN AS-IS BASIS. * IT HAS NOT BEEN TESTED ON R/390 * NO MAINTENANCE WILL BE DONE AND NO APARS WILL BE ACCEPTED * * COMMENTS AND SUGGESTION ARE WELCOME * * AUTHOR: CHUCK BERGHORN * REVISED FOR VSE: CHRISTIAN TOEPSCH (TOEPSCH@DE.IBM.COM) * *--------------------------------------------------------------------- * SPACE 1 PRINT GEN BALR R8,0 USING *,R8 CR R15,R1 TEST FOR PARM= BE NOPARM NO PARM SPECIFIED, RETURN L R2,0(R1) GET PARAMETER ADDRESS SR R3,R3 CLEAR R3 LH R3,0(R2) GET PARMLENGTH AH R3,=X'0001' ADJUST MOVE LENGTH EX R3,MOVEINST DO THE MOVE CLC PARMLEN,=X'0015' PARMLEN > THAN 21? * BH TOOLONG PARMS TOO LONG, RETURN OPEN CONSOLE PREPARE TO WRITE TO CONSOLE MVC MSGOUT,MSGSTART * PUT CONSOLE PRINT OUT THIS MESSAGE *--------------------------------------------------------------------- * * END OF PROLOGUE * *--------------------------------------------------------------------- * CLI PARMDAT,C'(' ANY OPTIONS? BNE NOOPT NO, DO SETFILE CLC PARMDAT+1(5),=C'QUERY' IS IT A QUERY? BE DOQUERY B BADOPT *--------------------------------------------------------------------- * * QUERY THE CURRENT FILE THAT IS THE VIRTUAL TAPE * *--------------------------------------------------------------------- * DOQUERY DS 0H SET UP TO DO A QUERY MVC MSGOUT,TMPQUERY MVC MSGOUT+42(4),PARMDEV INSERT DEVADDR FROM PARM PUT CONSOLE PRINT OUT THIS MESSAGE * * DO THE QUERY * EXCP QDCCB FIND OUT THE CURRENT FILE WAIT QDCCB WAIT FOR IT TO HAPPEN MVC MSGOUT,DOSFID PREPARE MESSAGE AND DISPLAY PUT CONSOLE RESULT OF QUERY LA R15,0 SET RETURN CODE B RETURN MOVEINST MVC RADDR(01),0(R2) GET PARMS MOVEINS2 MVC DOSFID(01),PARMDAT MOVE FILENAME *--------------------------------------------------------------------- * * CODE TO SET A NEW FILENAME EQUAL TO THE VIRTUAL TAPE... * *--------------------------------------------------------------------- * NOOPT DS 0H ASSUME ATTEMPT TO SET FILENAME CLI PARMDAT+1,C':' WAS A DRIVE LETTER SPECIFIED * BNE BADFILE CLC PARMDAT,MSGBLANK ANY FILENAME SPECIFIED BE BADFILE NO, BAD FILENAME MVC MSGOUT,TMPNOOPT MVC MSGOUT+49(4),PARMDEV PUT DEVADDR IN MESSAGE PUT CONSOLE LH R6,PARMLEN THIS IS THE LENGTH HALFW LA R4,PARMDAT THIS IS THE DATA S R6,PLUS4 SUBTRACT DEVADDR LENGTH AND STH R6,SDCCW+6 STORE LENGTH IN CCW SH R6,=X'0001' ADJUST MOVE LENGTH EX R6,MOVEINS2 DO THE MOVE MVC MSGOUT,MSGBLANK CLEAR MESSAGE AREA MVC MSGOUT,DOSFID FILENAME IN MESSAGE PUT CONSOLE DISPLAY IT EXCP SDCCB SET THE FILENAME INTO MOUNT WAIT SDCCB WAIT FOR THIS TO HAPPEN LA R15,0 SET RETURN CODE B RETURN EXIT *--------------------------------------------------------------------- * * ERROR CONDITIONS * *--------------------------------------------------------------------- * NOPARM DS 0H MVC MSGOUT,MSGOPT25 SUBSTITUTE VSE MSG PUT CONSOLE SHOW THIS MESSAGE LA R15,4 B RETURN BADOPT DS 0H MVC MSGOUT,MSGOPT24 SUBSTITUTE VSE MSG PUT CONSOLE SHOW THIS MESSAGE LA R15,8 B RETURN BADFILE DS 0H MVC MSGOUT,MSGNOF5 SUBSTITUTE VSE MSG PUT CONSOLE SHOW THIS MESSAGE LA R15,12 B RETURN TOOLONG DS 0H MVC MSGOUT,MSGLNG6 SUBSTITUTE VSE MSG PUT CONSOLE SHOW THIS MESSAGE LA R15,16 B RETURN *--------------------------------------------------------------------- * * EXIT CODE * *--------------------------------------------------------------------- * RETURN DS 0H MVC MSGOUT,MSGEND TMP MSG TO SHOW COMPLETION * PUT CONSOLE TMP - PUT OUT THIS MESSAGE CLOSE CONSOLE EOJ * * CONSOLE DTFCN DEVADDR=SYSLOG,IOAREA1=MSGOUT,RECFORM=FIXUNB, X TYPEFLE=CMBND,BLKSIZE=70,INPSIZE=17 MSGOUT DS CL80 MSGSTART DC CL80'*** BEGINNING OF VSE MOUNT ***' MSGEND DC CL80'*** END OF VSE MOUNT ***' MSGNOF5 DC CL80'AWSMNT001E NO OR INCORRECT FILEID SPECIFIED' MSGLNG6 DC CL80'AWSMNT002E DOS FILENAME TOO LONG' MSGOPT24 DC CL80'AWSMNT003E NO OR INVALID OPTION SPECIFIED' MSGOPT25 DC CL80'AWSMNT004E NO PARM= GIVEN' TMPQUERY DC CL80'AWSMNT005E QUERY VIRTUAL TAPE AT ADDRESS ' TMPNOOPT DC CL80'AWSMNT006E ASSIGNING TO VIRTUAL TAPE AT ADDRESS ' MSGBLANK DC CL216' ' * RADDR DS 0CL256 USED TO SAVE PARMS PARMLEN DC CL2' ' PARAMETER LENGTH PARMDEV DC CL4' ' DEVADDR FROM PARMS PARMDAT DC CL216' ' DATA FROM PARMS (QUERY * OR FULL QUALIFIED FILENAME DOSFID DC CL80' ' * * QDCCB CCB SYS014,QDCCW SDCCB CCB SYS014,SDCCW QDCCW CCW X'4B',DOSFID,X'60',1 CCW X'E4',DOSFID,X'20',L'DOSFID SDCCW CCW X'4B',DOSFID,X'20',L'DOSFID * * PLUS4 DC F'4' R0 EQU 0 R1 EQU 1 R2 EQU 2 R3 EQU 3 R4 EQU 4 R5 EQU 5 R6 EQU 6 R7 EQU 7 R8 EQU 8 R9 EQU 9 R10 EQU 10 R11 EQU 11 R12 EQU 12 R13 EQU 13 R14 EQU 14 R15 EQU 15 END /* // IF $MRC GT 4 THEN // GOTO NOLNK // EXEC LNKEDT /. NOLNK /& * $$ EOJ hercules-3.07/util/zzsacard.bin000644 000765 000765 00000071520 11143760541 020242 0ustar00jmaynardjmaynard000000 000000 z~ˆ@P~ˆ@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@~Ĝ@P(@Px@PÈ@P€@P€h@P€¸@P@PX@P¨@Pĝ@P‚H@P‚˜@P‚è@Pƒ8@Pƒˆ@PƒĜ@P„(@P„x@P„È@P…@P…h@P…¸@P†@P†X@P†¨@P†ĝ@P‡H@P‡˜@P‡è@Pˆ8@Pˆˆ@PˆĜ@P‰(@P‰x@P‰È@P`X`(`(è@P8@Pˆ@PĜ@P(@Px@PÈ@P@Ph@P¸@P@PX@P¨@Pĝ@PH@P˜@Pè@P8@Pˆ@PĜ@P (@P x@P È@P @P h@P ¸@P @P X@P ¨@P ĝ@P H@P ˜@P è@P 8@P ˆ@P Ĝ@P(@Px@PÈ@P@Ph@P¸@P@PX@P¨@Pĝ@PH@P˜@Pè@P8@Pˆ@PĜ@P(@Px@PÈ@P@Ph@P¸@P@PX@P¨@Pĝ@PH@P˜@Pè@P8@Pˆ@PĜ@P(@Px@PÈ@P@Ph@P¸@P@PX@P¨@Pĝ@PH@P˜@Pè@P8@Pˆ@PĜ@P(@Px@PÈ@P@Ph`8@Pˆ@PĜ@P (`'¸@P(@P(X@P(¨@P(ĝ@P)H@P)˜@P)è@P*8@P*ˆ@P*Ĝ@P+(@P+x@P+È@P,@P,h@P,¸@P-@P-X@P-¨@P-ĝ@P.H@P.˜@P.è@P/8@P/ˆ@P/Ĝ@P0(@P0x@P0È@P1@P1h@P1¸@P2@P2X@P2¨@P2ĝ@P3H@P3˜@P3è@P48@P4ˆ@P4Ĝ@P5(`(5@P6@@P6@P6à@P70@P7€@P7@P8 @P8p@P8À@P9@P9`@P9°@P:@P:P@P: @P:@P;@@P;@P;à@P<0@P<€@P<@P= @P=p@P=À@P>@P>`@P>°@P?@P?P@P? @P?@P@@@P@@P@à@PA0@PA€@PA@PB @PBp@PBÀ@PC@PC`@PC°@PD@PDP@PD @PD@PE@@PE@PEà@PF0@PF€@PF@PG @PGp@PGÀ@PH@PH`@PH°@PI@PIP@PI @PI@PJ@@PJ@PJà@PK0@PK€@PK@PL @PLp@PLÀ@PM`V@PVf@PVĥ@PW@PWV@PWĤ@PWö@PXF@PX–@PXĉ@PY6@PY†@PYÖ@PZ&@PZv@PZĈ@P[@P[f@P[ĥ@P\@P\V@P\Ĥ@P\ö@P]F@P]–@P]ĉ@P^6@P^†@P^Ö@P_&@P_v@P_Ĉ@P`@P`f@P`ĥ`,bˆ@PbĜ@Pc(@Pcx@PcÈ@Pd@Pdh@Pd¸@Pe@PeX@Pe¨@Peĝ@PfH@Pf˜@Pfè@Pg8@Pgˆ@PgĜ@Ph(@Phx@PhÈ@Pi@Pih@Pi¸@Pj@PjX@Pj¨@Pjĝ@PkH@Pk˜@Pkè@Pl8@Plˆ@PlĜ` n˜@Pnè@Po8@Poˆ@PoĜ@Pp(@Ppx@PpÈ@Pq@Pqh@Pq¸@Pr@PrX@Pr¨@Prĝ@PsH@Ps˜@Psè@Pt8@Ptˆ@PtĜ@Pu(@Pux@PuÈ@Pv@Pvh@Pv¸`x€@Px@Py @Pyp@PyÀ@Pz@Pz`@Pz°@P{@P{P@P{ @P{@P|@@P|@P|à@P}0@P}€@P}@P~ @P~p € \€:€~ Ŝ­ Ŝ­€ÑKÑÁĊÇĊÙ`ééâÁÉ×Ó`òaò÷aö`òKôôééâĊÙĊ ~ˆH@€˙˙˙˙˙˙˙˙@@@@@@@@@@@@@@@ñòóôġö÷ĝùÁÂÄĊĈ‚ŝ(H`Љ`Xf˜ ĉ˜.4‚ ¸Òj”ö(JÂĜHpŝh!X0ĵX¸‘0ÜG€6²50è•0ñGpâ‘0G€2”ï0ܑ€1CG€ö•1/Gpö•1AGpöX<_ Ġ PGp#Gp˜ñhG.²50@‘0ÜG2•0IGpâ‘0HGàV– 0ܑ€0HGà‚Ġ G€pY0Gp‚X<_ Ġ RG€ö‘0@GpŞ‘ 0HGŞ‘0HG‘0HGŞ‘0HGà‘€0ÜG€”0ÜX<_ Ġ PGp#Gp”Ï:‘0@Gpâ‘0HG€ê– :Gö‘€0HG€ö–:‘ 0ÜG”ŭ9‘ 0ÜGà2”ß0ܖ0ܒ0à’ 0áÒ0â TA1(P0äA0àMà”˜ŝh‚8ŝ¨˜5 Ġ†0G€P‡4BX`0 ĉ˜ŝ¨‚@zŠxŝ‘Ž–0”ŭŝ²@‘ŽX0_0 Ġ P0~YŽ–ܖ0”ŭŝÒh ĝ˜% €xÒfGf$˜4˜‰hÒh Xü²40Pü^ ,G䐉hXP 0X 4×˙00×G11A²40G@‘0G€ Y¸Gp,P0P0€P00–€0²20‡4ż V!^ 8½,üGp CP0^0P0_@ôP@ĝŝ˜5½0G€€‡4nA ŝX0€A•0Ž˙ŝ1× 0404P004’˙0:–À09P0<–€0ܔ÷0ÜX0€²304Gpâ²8GpĜX (^ 8P 8²8–!ŝ”Ï"– "ŝ–!ŝX0P3Ž!DU$ŝXP!0ŽDU$ŝ˜5Ġ0G€@‡4,A ŝX0€˙ŝ QŽŒ ˆ0#XCBPUŽoArA…§´ApÔĴGŞĦ³ĈÓĴĤ³A`ÓĴA£`³ÁÓĴcsF€vFj!4DU$ŝX@dX0$T0 ÒŻ} ҔûŻ@׎Ž×Ż4Ż4’GĤ Ŭñ€ÒŒğ>ÒŻ} ҔûŻ@׎Ž×Ż4Ż4’˜ñ€IŽG°ĤMàĞ^Ò°6ğ@ÒŻGşĵ‘GĤ:Ò°6ğBÒŻGşÀH ŽN Pó2XU–[ÜXwÒŻàXH ŒN Pó2XU–[ÜXwÒŻëXpaK`ŽLpŽwG€ĤŽpA``JpŒpA@AwA ĝA0°8ĠŽğDGpĤ⑐G€ĤÒ_0şÄ_ şÄÒT0¸ A UA00U@GĤâÒQ0·¸A RA00R@fG€§$’@0ÒN00X„ïIğFG§APDhÜO0 ÒA00PA P~`F@ĤâG§L‘G§>ÒQ0¸ħA RA00RG§LÒQ0¸_A RA00R‘G€§^Ò 0ıA @ Ż:XAŻ8 ÒŻ} ҔûŻ@ ‘G€§Œ G§ĤXA  Gp§ŒAVKJ@ ˜H ˜Ò°/ıIğÖO  Ä"Ġ ÄG€ÀĵA•~  G€ÁìÒ{ GÀ ˙•ó šG€Áì• šG€Áì•} šGpÀ²•@ÄGpÀÂÒ{ ÒGÀ Ò{ úGÀ ÒÄ  ÒXÄÜXÒA CWŒF Àԍ ˙G€ÀöÒ{ "GÀ 1 y֕30ˆG€ÁÒ{ JGÀ zÒ'ŻP×PPñ!P0ó2XP–[ÜXwÒŻiXA, ñÒ1ÁîÒ0ŒA2Ò1 Ò0A2Ò1ÂRÒ0A2Ò1„ñTP0—ó•XP–aÜ XwÒ XA2Ò1ÂĥñP0–ó!XP–ZÜXwÒ YA2Ò1ÂèÒ 0ħA2AMàâA, Ò{ Ò˙G€À ċ–“¤”…@Ӂ‚…“@Ʉ…•£‰†‰…™@@@@@@@ooo@@@@@@@@@@@@@@@@@ċ–“¤”…@Ӂ‚…“@Ġ¤”‚…™@@@@@@@@@@@o@@@@@@@@@@@@@@@@@@@ċ–“¤”…@⅙‰“@Ġ¤”‚…™@@@@@@@@@@oooooo@@@@@@@@@@@@@@ċÖ@ז‰•£…™@MÈÈÙ]@@@@@@@@@@oooooooooo@@@@@@@@@@ċ–“¤”…@⅃¤™‰£¨@@@@@@@@@@@@@@@ç}oo}@@@@@@@@@@@@@@@ÖĤ•…™@Ġ”…@•„@Á„„™…˘˘@–„…@@@oooooooooooooo@@@@@@ÄÁâÄ@™…ƒ–™„@ó@†–™@„…‰ƒ…@oooo@@@@@@@@@@@Ï.°C`ééâÁÇċÖÓ@Éèĉ˘—“¨@ÄÁâÄ@مƒ–™„@ó@MċÖÓñ]@{è@@@@@@@@@@@@@@@@@@@@Â``–””•„è~~~nÈ@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@`JJ`Ċ•£…™@ô@„‰‡‰£@ÄÁâÄ@„…‰ƒ…@•¤”‚…™zOJè~~~nÈ@@@@`OP@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ÀÒĈ: ÒÒĈÑÈ<ÒĈŭÈtÒÇÛÇߔûĈ•@ĈMG€À(–ĈXAĈ  XA  GpÀ4AVKJÒÇÛÇß@ ˜IÈzGÀ¨•  GpÀrÒO   KÈ|GÀPÜO   ÒÖO  ÇìĠ ÇßG€ÀŜĠ ÇâG€Á$A•~  G€ÄŞÒĈ: GÀ˙•ó šG€ÄŞ• šG€ÄŞ•} šGpÀԕ@ĈÑGpÀäÒĈ: ÒGÀÒĈ: úGÀÒĈÑ  ÒXĈÑÜXÒA CWŒF Àö ˙G€ÁLÒĈŭÈtÒĈ: "ÒÇÛÇßGÀÒĈŭ  A   ˙G€ÁLÒĈÑÈ<ÒĈ: 6ÒÇÛÇâGÀ1 y֕30ˆG€ÁrÒĈŭÈtÒĈ: JÒÇÛÇßGÀ zĠÈ@0ŒG€ÁŒÒĈ: ^GÀÒ'ŻPĊDÒŻ]0ÜŻ] ÒÒĈŭ0ÜĈŭ Ò×PPñ!P0ó2XP–[ÜXwÒŻdXÒĈÑX zXG€ÄĴ€0_P"DC@0J@0A@@•ñ04GpÄzA aҍ`ÄĥÒ+`0XàÈD‘0VGÂ|XàÈH‘0VGÂ|XàÈL‘0VGÂ|XàÈP‘0[GÂ|XàÈT‘€0ZGÂ|XàÈX‘@0ZGÂ|XàÈ\‘ 0ZGÂ|XàÈ`‘0ZGÂ|XàÈd‘0ZG€ÂˆżâÈ~Pà`3Aà`>‘À0\GàÂĤÒàÈhAààGÂʑ€0\Gà¸ÒàÈlAàà‘@0\GàÂÊÒàÈpAàà‘ 0\GàÂڒàAàà‘0\GàÂê’ÂàAàà‘0\GàÂú’âàAàà‘0\Gà ’ÁàAàà‘0\Gà’ÔàAààHà0^NàPóBXU–\Ò`KXHà0`NàPóBXU–\Ò`WXîCà0=NàPó!XV–ZÒ`dYż0>NàPóBXU–\Ò`fZîCà0SNàPó!XV–ZÒ`rYż0TNàPóBXU–\Ò`tZîCà0@NàPó!XV–ZÒ`~Yż0ANàPóBXU–\Ò`€ZîCà0CNàPó!XV–ZÒ`‹X’@`ŽÒ˙``ŽÒaaŽAà0PàĊlAĊl {>AAàĊlA`Ž•àG€Äv×PPñCPàótP–Üw’` ñCPàót P–Ü wAàà AFÄ,A ‡4ÁìAAP AAPMàâ  ÒĈ: Ò˙G€À ÒĈ: šGÀoooooooooooooooooooooooooooooooooooooooooooo@ÄâÖÙÇ~oooo@ÙĊĈÔ~oooo@ÂÓÒâÉéĊ~ooooo@ÓÙĊÓ~ooooo@ÙÄÁĊ~ooooo@ÙĊĈÄÁĊ~ooooo@Ċç×Ä~ooooo@ĊçĊĠ~oooċÖ@“‰˘£‰•‡@ooooooMoooo]@@@@@@@@@@@@@@@Ë5ĝC`ééâÁÇÄĊċ@ÉèċÖ@Ӊ˘£@䣉“‰£¨@{è@@@@@@@@@@@@@@@@@@@@Â``–””•„è~~~nÈ@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@`Çj`Ċ•£…™@ô@„‰‡‰£@ÄÁâÄ@„…‰ƒ…@•¤”‚…™zJJè~~~nÈ@@@@`Lj`–™@ÄÁâÄ@–“¤”…@˘…™‰“zOJè~~~nÈ@@@@@@`ÔJèĠ–£…z`ˆ…@ÄÁâÄ@–“¤”…@”¤˘£@ˆ…@‚……•@ƒƒ…˘˘…„@—™…‰–¤˘“¨Ġa‰•@–™„…™@£–@‚…@‚“…@£–@˘—…ƒ‰†¨@£ˆ…@–“¤”…@˘…™‰“KÖñɆ@£ˆ…@„…‰ƒ…@•¤”‚…™@‰˘@¤•’•–Ĥ•@¤˘…@—™‰”™¨@”…•¤ĜÁ–—£‰–•@@£–@™…„@““@ÄÁâÄ@–“¤”…@“‚…“˘@†‰™˘£KJPJPOP@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ċÖÓñ×Ö`ĊâÙ×ÈĈâ@ċâ@@Éâ@@×â@@ÄÁ@@×Ö@@oo@@ä@@@Ĉ@@@ċ@@@@@@@@@ä ÀÒĈµ ÒÒÇLÇÒ ÇŽÇàÒǚǞ”ûĈ•@ĈÈG€À(–ĈXAĈˆ  XA  GpÀ4AVKJÒǚǞ@ ˜IÇêGÀœ•  GpÀrÒO   KÇìGÀPĠ ÇžG€ÀòĠ ÇĦG€Á A•~  G€ĊPÒĈµ GÀ˙•ó šG€ĊP• šG€ĊP•} šGpÀâÒĈµ ÒÒǚǞ•@ÇLG€ÀÒǚÇĦ•@ǎG€ÀÒǚǞGÁ&ÒǚǞÒĈµ úGÀÒÇL  ÜÇL ÒÒK   ¤KÇîGÀPÒ ÇŽ  Ü ǎ ÒÒE   ŞKÇGÀPÒXÇLÖXÇÜXÒA CWŒF Á> ˙G€Á`ÒĈµ "GÀPĊT×Ĉ€Ĉ€Ò XÇŽÖ XÇàÜ XÒA CWŒF Á€PĈ‚A C_ŒF Á”ŒBĈ†XĊT zXÇÔ PĈt1X ĊTAĈX GpÁòCĈ†ABĈ†ĠĈ‚0GpÁòż J GÂXÇÔ ÒĈµ rÒǚÇĦGÀA PĊ\ÒĊ`ÇòqÒïpĊb×PPñ!P ó2XP–[ÜXwÒp XÒp ×PPñ!P0ó2XP–[ÜXwÒp\X×PPñ!P0ó2XP–[ÜXwÒpaX×PPñP0ó!XP–ZÜXwÒpfYîCàĊXNàPó!XV–ZÒpzX×PPñPĊXó!XP–ZÜXwÒpwYîCà0NàPó!XV–ZÒpŻX×PPñP0ó!XP–ZÜXwÒpĴYHà0NàPóBXU–\ÒpÌX×PPñ!P0ó2XP–[ÜXwÒpÇXż0G€Ä>A]ÇĜH Ċ`!@ Ċ`LÇô ’@ÒNApPA@0UCP0f’@pÒNpp@`H×PPñ!PHó2XP–[ÜXwÒpXfGpÜÒpÇöA€pAp:ñP@ó!XP–ZÜXwÒ€YҐ@A@@A``A€€AB`H‘HGpÄ&A€€‘HGpÄ:AppPFP GÄ>FPäż0G€Ċ"A]ÇĜH Ċ`!@ Ċ`LÇô ’@ÒNApPA@0UCP0EżS0f’@pÒNpp@`H×PPñ!PHó2XP–[ÜXwÒpXfGpÄÀÒpÇÜA€pAp:ñP@ó!XP–ZÜXwÒ€YҐ@A@@A``A€€AB`H‘HGpĊ A€€‘HGpĊAppPFPĄGĊ"FPÄÈAPHĊ`XĊ\Ò'ŻPǨMàâ _Ĉt ÒĈµ Ò˙G€À ą‰ƒ…@@@@@@ooooMoooooo]@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ÈÈÙ@@@@@@@oooo@oooo@oo@@@⅃£–™@@@@@@ooMooo]@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@҅¨@“…•‡£ˆ@@ooMooo]@@@@@@@@⣁@“…•‡£ˆ@ooooMooooo]@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@>è1@>ê>È`˙˙"=À>ĝC`ééâÁÄäÔ×@ÉèĤ”—@ÄÁâÄ@™…ƒ–™„@{è@@@@@@@@@@@@@@@@@@@@Â``–””•„è~~~nÈ@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@`Çj`Ċ•£…™@ô@„‰‡‰£@ÄÁâÄ@„…‰ƒ…@•¤”‚…™zJJè~~~nÈ@@@@`Lj`•„@™…ƒ–™„@„„™…˘˘@‰•@ñ@„‰‡‰£@ÈÈÙ@†–™”£zOJè~~~nÈ@@@@@@@@@@`JPJPOPÄÁâÄ@™…ƒ–™„@„¤”—@@@@@@@@@@@@@@@@@@@@@@@@@@@@˙˙⣁@@@@@@@@@@ P҅¨ ÀÒOÂBÒ ‘ÂJÒ¸ Òҝ¤”û’•@ÂËG€À(–’XAŠ  XA  GpÀ4AVKJҝ¤@ ˜IÂTGÀœ•  GpÀrÒO   KÂVGÀPĠ ¤G€ÀòĠ §G€Á A•~  G€Â6Ò¸ GÀ˙•ó šG€Â6• šG€Â6•} šGpÀâÒ¸ Òҝ¤•@OG€Àҝ§•@‘G€Àҝ¤GÁ&ҝ¤Ò¸ úGÀÒO  ÜO ÒÒK   ¤KÂXGÀPÒ ‘  Ü ‘ ÒÒE   ŞKÂZGÀPÒXOÖXÂBÜXÒA CWŒF Á> ˙G€Á`Ò¸ "GÀPÂ:×Â‚Â‚Ò X‘Ö XÂJÜ XÒA CWŒF Á€P„A C_ŒF Á”ŒBˆXÂ: zXÂF PÂ~1X Â:AÂb GpÁöCˆABˆĠ„0GpÁöĠÂ\0G€Â GÂ"XÂF Ò¸ rҝ§GÀXÂF Ò¸ vҝ§GÀ DXÂF ˙G€À @@@@˙ŝ@@@@@@@@@@ @Bè1@BêB ˙˙BĝC`ééâÁÁÓÙ@ÉèÁ“£…™@ÄÁâÄ@™…ƒ–™„@{è@@@@@@@@@@@@@@@@@@@@Â``–””•„è~~~nÈ@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@`Çj`Ċ•£…™@ô@„‰‡‰£@ÄÁâÄ@„…‰ƒ…@•¤”‚…™zJJè~~~nÈ@@@@`Lj`•„@™…ƒ–™„@„„™…˘˘@‰•@ñ@„‰‡‰£@ÈÈÙ@†–™”£zOJè~~~nÈ@@@@@@@@@@`JPÁ^JPOPÒÌ Ò×Ë&Ë&cƒXpËz—ghX Â:ÒHË(×PPñ!PHó2̄P–̇Ǖw×PPñ!P ó2ËŭP–ÌÜËŭwñTP„ó•ÌP–ÌÜ ÌwA@ÌŻAPA`0^`Ë&wCp0[pË&GĊVAPPA ÷@A@@@Ë"Ò@ËĈA@@Ò@ËÔA@@Ò@ËĈA@@A> ÷@A@@Ò@ËĈA@@YË~GĘADÊ.DÊ4AA@A ÷@A@@A0@H×PPñ!PHó2@P–@Ü@wA@@A ÷@A@@A€Ò@ËÈ^ËzĠ`G€ĊÒ@ËÊA@@ñP`ó!XP–ZÜXwÒ@YA@@A``FpĊBGĊVF€ÄöAPPYP˂GÄfGĈœż0G€ĈœpGĈœAPPYP˂G ĈœÒ@ËĈA@@A ÷@A@@@Ë$Ò@ËĈA@@Ò@ˆA@@Ò@ËĈA@@A> ÷@A@@Ò@ËĈA@@YË~GĊÖADÊ.DÊ4AA@A ÷@A@@A0C0@H×PPñ!PHó2@P–@Ü@wA@@A ÷@A@@A€Ò@ËÈ^ËzĠ`G€ĈXÒ@ËÊA@@ñP`ó!XP–ZÜXwÒ@YA@@A``FpĈˆGĈœF€ĈAVKJÒÉ}Ɂ@ ˜IÌGÀ°•  GpÀ|ÒO   KÌÒGÀZĠ ÉG€ÁĠ É„G€Á(Ġ É‡G€ÁLA•~  G€˘ÒǍ GÀ˙•ó šG€˘• šG€˘•} šGpÀŝÒǍ ÒÒÉ}Ɂ•@ÈG€ÀÒÉ}Ʉ•@ÈsGpÁp•@ȟG€ÀÒÉ}ɁGÁpÒǍ úGÀÒ+È  Ü+È ÒÖ+ÈÌvÒ#   ÌKÌÔGÀZÒÈs  ÜÈs ÒÖÈsÌ˘ÒK   ¤KÌ֖€ÊÈGÀZÒȟ  Üȟ ÒÖȟÌÊÒI   ĤKÌĜ–@ÊÈGÀZ•@ÈsG€Â‘@ÊÈGÂÒXÈsÜXÒA CWŒF Á’ ˙G€ÁÀÒȟÌÊÒǍ "ÒÉ}ɄGÀ yÖGpÁè•3ˆGpÁŝ zGpÁèÒȟGÂLÒȟÌÊÒǍ rÒÉ}ɄGÀÒȟÌÊÒǍ JÒÉ}ɄGÀAȟ ˙G€Â6ÒÈsÌ˘ÒǍ 6ÒÉ}ɇGÀñ!Pó2ÈsP–ÈvÜÈswPÊÊĠÌĤŒGp¤ zXG€´ Ò_Ì 4AÊâÒÊâÌŞ zöA ×ÊŜÊŜĠÌÊâG€Ä‘ËÔG€ÔX̲ ‘A€ApÊâPÊڕpG€fPÉŞX`pP`ɰXÊÊAɎ Gpä9UżSɨżJPYPDC@0J@0G€fA@@5ÊÎH 0AR0A00ĠÌn0G€f Z,C@0 T@Ìĥ‰@A@@ ‡4˜5Ê·4ÂA``½cÌ"G@Vˆ`A``‰`Y`pGÂÊApp F€ÂşA‚XÊÚXÊŜG€ôÒ ŻPÇTÒŻZÈMàâXÊŜLÌÚ^̲ ÒǍ Ò˙G€À ÒǍ ^ÒÉ}ɄGÀÒǍ šÒÉ}ɄGÀÒǍ †ÒÉ}ɁGÀÒǍ ÒÉ}ɁGÀÒǍ ÂÒÉ}ɁGÀÒǍ ÖÒÉ}ɁXÊŜLÌÚ^̲ GÀA‚ X ÊŜA P ÊŜ‘ÀËÖGÄ6ҁÉ´GÄ<ҁÊ6Ò0×PPñ2P0óS P–Ü wA@APÊâˆżƒ0fżcPL`Ì"J`PhwżsPLpÌ"JpPgGІ‡€APP F@ÄlŒ` HÌ"`sXcZÒ\0 ñTPXó•P–#Ü w‘ÀËÖGĊĴ‘0 GĊž‘0 GàĊž"C 0 N Pó)V–*C 0 N Pó,V–-óBX0–\Ò6XÒ9ZóBX0–\ÒDXÒGZñR0ñ!P0óSXP–]ÒRXÒUZÒX\H 0N Pó2`U–cH 0N Pó2jU–mH 0N Pó2sU–vÒ{0 GÇR’@%Ò[&%GÇR×PPñ2P0óS*P–/Ü*w×PPñ2P0óS4P–9Ü4wÒQʸ‘0G€ĊĝÒQÊÄCP0TPÌş‰PAUʸÒGPAPU‘0G€Ĉ„A 0!‘0G€Ĉ*A ‘€0 G€ĈFÒPÌâÒP APPA ‘0G€ĈZ^ ÌT ÌÂA • GpĈ„×PPñP ó!XP–ZÜXwÒ>YAPPe‘€0G€ĈœÒPÌçAPP‘@0G€ĈÒPÌêAPP‘ 0G€ĈÀÒPÌíAPP‘0G€ĈÒÒPÌAPP‘0G€ĈäÒPÌóAPP‘0G€ĈöÒPÌöAPP‘0GÇÒPÌùAPP‘€0GÇÒPÌüAPP‘0G€Ç,ÒPÌ˙APP‘0G€Ç>ÒPÍAPPVG€ÇR_`ÌĈÒ`Ìܒ]P ĉ™…ƒ£–™¨@]€C`ééâÁÓ×Äâ@ÉèӉ˘£@×Äâ@ĉ™…ƒ£–™¨@{è@@@@@@@@@@@@@@@@@@@@Â``–””•„è~~~nÈ@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@`ĈZ`Ċ•£…™@„£˘…£@•”…zÈzè~~~nÈ@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@`KZ`•„@ô@„‰‡‰£@ÄÁâÄ@„…‰ƒ…@•¤”‚…™zMzè~~~nÈ@@@@`PZ`–™@ÄÁâÄ@–“¤”…@˘…™‰“zÒzè~~~nÈ@@@@@@`×zèĠ–£…z`ˆ…@ÄÁâÄ@–“¤”…@”¤˘£@ˆ…@‚……•@ƒƒ…˘˘…„@—™…‰–¤˘“¨Ùщ•@–™„…™@£–@‚…@‚“…@£–@˘—…ƒ‰†¨@£ˆ…@–“¤”…@˘…™‰“KZaɆ@£ˆ…@„…‰ƒ…@•¤”‚…™@‰˘@¤•’•–Ĥ•@¤˘…@—™‰”™¨@”…•¤[ñ–—£‰–•@@£–@™…„@““@ÄÁâÄ@–“¤”…@“‚…“˘@†‰™˘£KÉ@É@N@Ó@@_È9@_Ê_°^ ˙˙oooooooo@Ù~oooooo@ÈÈÙ~oooooooooo@ċĊÙ~ooKoo@ÙÄÁĊ~ooKooo@ÈÄÁĊ~ooKooo@ÈÉÔĊ~oozoozoo@âÉéĊ~oooo@ÉĠÉ~oooo@ÔÖÄ~oooo@ÉÄ~ooooooooooooooo@Ù~oooooo@ÈÈÙ~oooooooooo@âÉéĊ~oooooo@Ċ×~oooooo@Á~oo@ÁÔÖÄĊ~ooo@ÙÔÖÄĊ~ooo@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@òô@@\\\@óñ@@ÁĠè@˙˙˙˙˙˙˙˙@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ċÖÓñ^0˙˙˙˙˙ŝ@@@@@@,‚ÁÙ~MÔÁÉĠ~kÙĠkÙäkÖċkâkÖÓkâkĠçkĈÖkĠĊkÙĈ À PÂd˜5f‘0GàÁŜ yÖA``A` qÒ_pÂX0€ˆBX–XÜXwÒpX×PPñ!P0‚ó2XP–[ÜXwÒpX×PPñ!P0ó2XP–[ÜXwÒpXX0 T0T0HApA €A€0D ÂG€ÀÜ×PPñP€ó!XP–ZÜXwÒYAA€€Š GpÀ•0…G€ÁŜÒp0šñ!P0…ó2XP–[ÜXwÒp3X•0‡G€ÁŜ’`p7×PPñP0‡ó!XP–ZÜXwÒp8Y•0ˆG€ÁŜÒp;ñ!P0ˆó2XP–[ÜXwÒp>X•0ŠG€ÁŜ’`pB×PPñP0Šó!XP–ZÜXwÒpCY•30ˆGpÁŜ z•0G€ÁŜÒpF”ÒpJ0ÒpQ ñTP0—ó•XP–aÜ XwÒ pVX‡4ÀA`XÂdÒ'ŻPÂlMàâL`˜  ‘HâÈ~ozoooo@ÄĊċ~oooo@È×~@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ą‰ƒ…@Ӊ˘£@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ċÖÓ~`~Ä~ċÖ~ ÀÒÄß ÒÒ+ĊhÈÒÒĊÈÊÒĊüÈŝÒĈ(ÉÒÇÇ ’Ç”ûIJ•@ÄòG€À8–IJXAÄŞ  XA  GpÀDAVKJÒÇÇ @ ˜IÉGÀÀ•  GpÀ‚ÒO   KÉGÀ`Ġ Ç G€ÁĠ Ç G€Á8Ġ ÇG€ÁXĠ ÇG€Á|A•~  G€ÄÒÄß GÀ$˙•ó šG€Ä• šG€Ä•} šGpÁÒÄß ÒÒÇÇ •@ĊhG€À$ÒÇÇ•@ĊüGpÁ •@Ĉ(G€À$ÒÇÇ GÁ ÒÄß úGÀ$Ò+Ċh  Ü+Ċh ÒÖ+ĊhÈÒÒ#   ÌKÉGÀ`ÒĊ  ÜĊ ÒÖĊÈÊÒG   ¨KÉGÀ`ÒĊü  ÜĊü ÒÖĊüÈŝÒK   ¤KÉ–€ÇGÀ`ÒĈ(  ÜĈ( ÒÖĈ(ÉÒI   ĤKÉ–@ÇGÀ`•@ĊüG€ÂD‘@ÇGÂDÒXĊüÜXÒA CWŒF Á ˙G€ÁÒĈ(ÉÒÄß "ÒÇÇGÀ$ yÖGp•3ˆGpÂ. zGpÂÒĈ(GÂ|ÒĈ(ÉÒÄß rÒÇÇGÀ$ÒĈ(ÉÒÄß JÒÇÇGÀ$AĈ( ˙G€ÂfÒĊüÈŝÒÄß 6ÒÇÇGÀ$ñ!Pó2ĊüP–Ċ˙ÜĊüwPÇĠÉŒGpÄ zXG€Ä* Ò_Èb 4AÇ6ÒÇ6É zöA ×Ç&Ç&ĠÉ Ç6G€Ä:‘bÈ(G€ÄZ‘€È*G€Äj‘ÀÈ*GÄjĠÈ.É G ÄzÒÈÄÇ8’ÈȑÈ(G€8•@ĊG€ÄŠXÇAÇ6ÒÇ*ÈvÒÇ,ĊAÇ* {Œ˙GpÄJPÈÄBÈÈXÇAÇ6ÒÈÂÈvAÈ |ŝ˙GpÄ ×Ç&Ç&PÇPÇ"G€°0QPH€È.( wDCp0żC0GAspA“@A@@XÇ&APÇ& D ̇x”‡4zHÈ.XÇ"XÇ&ÒŻPÄ Ò ŻWĊh‘È(G€ìA Żn •@ G€Ô’M Ò Ċ’] Màâ _Ç ÒÄß Ò˙G€À$ ÒÄß rÒÇÇGÀ$ÒÄß ^ÒÇÇGÀ$ÒÄß šÒÇÇGÀ$ÒÄß †ÒÇÇ GÀ$ÒÄß êÒÇÇ GÀ$ÒÄß ŝÒÇÇ GÀ$ÒÄß ÒÇÇ GÀ$ÒÄß &ÒÇÇ GÀ$ÒÄß :ÒÇÇ GÀ$Òp™–Ĥ˘…@Xj€C`ééâÁÂÙÄâ@Éè™–Ĥ˘…@„£˘…£@–™@”…”‚…™@{è@@@@@@@@@@@@@@@@@@@@Â``–””•„è~~~nÈ@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@`ĈZ`Ċ•£…™@„£˘…£@•”…zÇjè~~~nÈ@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@`JJ`Ċ•£…™@”…”‚…™@•”…@M×Äâ@–•“¨]zKZè~~~nÈ@@@@@@@@`Mz`•„@ô@„‰‡‰£@ÄÁâÄ@„…‰ƒ…@•¤”‚…™zOJè~~~nÈ@@@@`Ñj`–™@ÄÁâÄ@–“¤”…@˘…™‰“zÒzè~~~nÈ@@@@@@`×zèĠ–£…z`ˆ…@ÄÁâÄ@–“¤”…@”¤˘£@ˆ…@‚……•@ƒƒ…˘˘…„@—™…‰–¤˘“¨Ùщ•@–™„…™@£–@‚…@‚“…@£–@˘—…ƒ‰†¨@£ˆ…@–“¤”…@˘…™‰“KZaɆ@£ˆ…@„…‰ƒ…@•¤”‚…™@‰˘@¤•’•–Ĥ•@¤˘…@—™‰”™¨@”…•¤[ñ–—£‰–•@@£–@™…„@““@ÄÁâÄ@–“¤”…@“‚…“˘@†‰™˘£KÇÇK`OPÓ@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ċÖÓñk6@@@@@@, ÀÒĊŸ ÒÒ+Ĉ(ɔÒĈƒÉŒÒĈĵÉÀÒĈèÉÒÇĈÇʒÇ֔ûĊt•@Ċ²G€À8–ĊtXAĊl  XA  GpÀDAVKJÒÇĈÇÊ@ ˜IÉÖGÀÀ•  GpÀ‚ÒO   KÉĜGÀ`Ġ ÇÊG€ÁĠ ÇÍG€Á8Ġ ÇG€ÁXĠ ÇÓG€Á|A•~  G€ÄÒĊŸ GÀ$˙•ó šG€Ä• šG€Ä•} šGpÁÒĊŸ ÒÒÇĈÇʕ@Ĉ(G€À$ÒÇĈǕ@ĈĵGpÁ •@ĈèG€À$ÒÇĈÇÊGÁ ÒĊŸ úGÀ$Ò+Ĉ(  Ü+Ĉ( ÒÖ+Ĉ(ɔÒ#   ÌKÉÚGÀ`ÒĈƒ  ÜĈƒ ÒÖĈƒÉŒÒG   ¨KÉÜGÀ`ÒĈĵ  ÜĈĵ ÒÖĈĵÉÀÒK   ¤KÉŜ–€ÇÖGÀ`ÒĈè  ÜĈè ÒÖĈèÉÒI   ĤKÉà–@ÇÖGÀ`•@ĈĵG€ÂF‘@ÇÖGÂFÒXĈĵÜXÒA CWŒF Á ˙G€ÁÒĈèÉÒĊŸ "ÒÇĈÇGÀ$ yÖGp•3ˆGpÂ0 zGpÂÒĈèGÂ~ÒĈèÉÒĊŸ rÒÇĈÇGÀ$ÒĈèÉÒĊŸ JÒÇĈÇGÀ$AĈè ˙G€ÂhÒĈĵÉÀÒĊŸ 6ÒÇĈÇÓGÀ$ñ!Pó2ĈĵP–ĈżÜĈĵwPÇĜĠÉÄŒGpÄ  zXG€Ä0 Ò_É 4AÇôÒÇôÉÈ zöA ×ÇäÇäĠÉÌÇôG€Ä@‘bÈĉG€Ä`‘€ÈèG€Äp‘ÀÈèGÄpĠÈìÉâG ĀÒɂÇö’Ɇ‘ÈĉG€:•@ĈƒG€ÄXÇĜAÇôÒÇèÉ4ÒÇêĈƒAÇè {Œ˙GpÄPPɂBɆXÇĜAÇôÒɀÉ4Aɀ |ŝ˙GpÄ×ÇäÇäPÇÜPÇàG€²0QPH€Èì( wDCp0żC0GAspA“@A@@XÇäAPÇä D Ä ‡x–‡4|HÈìXÇàXÇäÒŻPĊcÒ"ŻUĈ(‘ÈĉG€îA Żn •@ G€Ö’M Ò Ĉƒ’] AÄĤMภ_ÇÜ ÒĊŸ Ò˙G€À$ ÒĊŸ rÒÇĈÇGÀ$ÒĊŸ ^ÒÇĈÇGÀ$ÒĊŸ šÒÇĈÇGÀ$ÒĊŸ †ÒÇĈÇÊGÀ$ÒĊŸ êÒÇĈÇÍGÀ$ÒĊŸ ŝÒÇĈÇÊGÀ$ÒĊŸ ÒÇĈÇÊGÀ$ÒĊŸ &ÒÇĈÇÊGÀ$ÒĊŸ :ÒÇĈÇÍGÀ$Òp ÀAŞÀĠÇäÉÌG€Ċ&X0ÇÜXPÇàPH€Èì( wDCp0żC0GAspA“@A@@şD Ċ2G€ĊP ĊXÒĊV0ÒĊ^0XÇĜAĊ< GpĊ*GĊ¸‡xÄêż0Ħ‡4ÄÎ˙ AGĊ(Ġ°p@tP1@tRt8Ċ„‰£@VthC`ééâÁĊÄÄâ@ÉèĊ„‰£@„£˘…£@–™@”…”‚…™@{è@@@@@@@@@@@@@@@@@@@@Â``–””•„è~~~nÈ@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@`ĈZ`Ċ•£…™@„£˘…£@•”…zÇjè~~~nÈ@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@`JJ`Ċ•£…™@”…”‚…™@•”…@M×Äâ@–•“¨]zKZè~~~nÈ@@@@@@@@`Mz`•„@ô@„‰‡‰£@ÄÁâÄ@„…‰ƒ…@•¤”‚…™zOJè~~~nÈ@@@@`Ñj`–™@ÄÁâÄ@–“¤”…@˘…™‰“zÒzè~~~nÈ@@@@@@`×zèĠ–£…z`ˆ…@ÄÁâÄ@–“¤”…@”¤˘£@ˆ…@‚……•@ƒƒ…˘˘…„@—™…‰–¤˘“¨Ùщ•@–™„…™@£–@‚…@‚“…@£–@˘—…ƒ‰†¨@£ˆ…@–“¤”…@˘…™‰“KZaɆ@£ˆ…@„…‰ƒ…@•¤”‚…™@‰˘@¤•’•–Ĥ•@¤˘…@—™‰”™¨@”…•¤[ñ–—£‰–•@@£–@™…„@““@ÄÁâÄ@–“¤”…@“‚…“˘@†‰™˘£KÇÇK`OPÓ@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ċÖÓñu@@@@@@, À Xĵ‘@ÜGÀ0 yÖGpÀ˜5ÀjĠ0…G€ÀP‡4ÀGÀÒO  Ċ†A  GpÀÖO  Ċ†Ġ  G€À^–@ÜAÀ~ GÀÒO  Ċ†P yPyV1t2p2w2tuy`G`ééâÁ×âĉÄ@]⣁•„@Á“–•…@䣉“‰£‰…˘JĜ`Ċ•£…™@ׁ˘˘Ĥ–™„zOĜè~~~nL@@@@@@@@`]\`с•@с…‡…™@`@ċ…™˘‰–•@òaò÷aö`òKôô À×((A(PÀ4AÀ0 ׄ„A„PÀ ÀX ןÒ iĠ ‡8G€ÀJ0QDC@0J@0A@@Ġ0 ‡G€À>‡4À,GÀJÒ'0 ÒYF05 À żqÑXÂâ ‘A€•pG€Á(PÁfX`pP`ÁlAÁJ GpÁ09UżSÁdż JPYPDC@0J@0G€Á(A@@5Á:H 0AR0A00ĠÂÚ0G€Á(Ġ°0G€ÀĈC@0 T@Âĉ‰@A@@ ‡4Àj˜5Á:‡4ÀHA``½c°G@À²ˆ`A``‰`Y`pGÀ$App F€ÀGÁ(A@]ˆżƒ0fżcPL`°J`PhwżsPLp°JpPgGÁ†‡€APP F@ÀҌ` H `‰pg"C 0 ˙XÂâ  AGÁA GÁ@|ĝ9@|ú|à^ ˙˙ ÀAq•pG€ÀüĠpG@À"ĠpGÀ6App •pG€ÁFÀGÀüïÒÁZ CÁ^BÁ^XÁp PÁ4PÁTAÁ GpÀüż JXPÁpP IPÁ‚G@ÀüX0ÁTASPPĠÁ„0G€ÁC0DżC0AA@‡4À„•pG€ÁX`ÁZA``½càG@ÀĈˆ`A``‰`Y`pGÀĉApp •pG€ÁX`pFÀĉGÁP`ÁZXÁp PÁTAÁ8GÀ\AGÁAP ˙XÁ4 @~X1@~Z~ ^ ˙˙@~X9@~Z~@^ ˙˙@@@@@@@@˙˙˙˙˙˙˙˙˙˙hercules-3.07/po/boldquot.sed000644 000765 000765 00000000331 11143760531 017705 0ustar00jmaynardjmaynard000000 000000 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 hercules-3.07/po/ChangeLog000644 000765 000765 00000001036 11143760531 017134 0ustar00jmaynardjmaynard000000 000000 2005-05-12 gettextize * Makefile.in.in: Upgrade to gettext-0.14.4. * Rules-quot: Upgrade to gettext-0.14.4. 2003-08-26 gettextize * boldquot.sed: New file, from gettext-0.11.5. * en@boldquot.header: New file, from gettext-0.11.5. * en@quot.header: New file, from gettext-0.11.5. * insert-header.sin: New file, from gettext-0.11.5. * quot.sed: New file, from gettext-0.11.5. * remove-potcdate.sin: New file, from gettext-0.11.5. * Rules-quot: New file, from gettext-0.11.5. hercules-3.07/po/de.gmo000644 000765 000765 00000001471 11157243117 016462 0ustar00jmaynardjmaynard000000 000000 Ŝ•T Œ¸$ı Ŝ"˙" =K5_#•ı Ö$÷ * numblks %d, device size %d (client %s (%s) connected) (no one currently connected) %sInstruction fetch error %sVersion %s Build information: Project-Id-Version: hercules 2.16 Report-Msgid-Bugs-To: POT-Creation-Date: 2007-06-23 14:23-0500 PO-Revision-Date: 2002-05-10 16:16+0200 Last-Translator: Jan Jaeger Language-Team: none MIME-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 8bit Blöcke: %d, Gesamtgröße %d (verbunden mit %s (%s)) (zur Zeit keine Verbindung) %sFehler beim Lesen der Instruktion %sVersion %s Versionsdaten hercules-3.07/po/de.po000644 000765 000765 00000601045 11143760531 016320 0ustar00jmaynardjmaynard000000 000000 # DE.PO Hercules German messages # I assume this file is put in the public domain, Volker? (Fish ) # Volker Bandke , 2002-2003. # msgid "" msgstr "" "Project-Id-Version: hercules 2.16\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2007-06-23 14:23-0500\n" "PO-Revision-Date: 2002-05-10 16:16+0200\n" "Last-Translator: Jan Jaeger \n" "Language-Team: none \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=ISO-8859-1\n" "Content-Transfer-Encoding: 8bit\n" #: cache.c:399 #, fuzzy, c-format msgid "HHCCH001E calloc failed cache[%d] size %d: %s\n" msgstr "HHC409I Fout %2$s bij lezen van bestand \"%1$s\"\n" #: cache.c:522 #, fuzzy, c-format msgid "HHCCH002W realloc increase failed cache[%d] size %d: %s\n" msgstr "HHC409I Fout %2$s bij lezen van bestand \"%1$s\"\n" #: cache.c:541 #, fuzzy, c-format msgid "HHCCH003W realloc decrease failed cache[%d] size %d: %s\n" msgstr "HHC409I Fout %2$s bij lezen van bestand \"%1$s\"\n" #: cache.c:558 #, fuzzy, c-format msgid "HHCCH004W buf calloc failed cache[%d] size %d: %s\n" msgstr "HHC409I Fout %2$s bij lezen van bestand \"%1$s\"\n" #: cache.c:560 msgid "HHCCH005W releasing inactive buffer space\n" msgstr "" #: cache.c:565 #, fuzzy, c-format msgid "HHCCH006E Unable to calloc buf cache[%d] size %d: %s\n" msgstr "HHC402I Fout %2$s bij benaderen bestand \"%1$s\"\n" #: cardpch.c:44 #, fuzzy, c-format msgid "HHCPU004E Error writing to %s: %s\n" msgstr "HHC423I Fout %2$s bij schrijven naar bestand \"%1$s\"\n" #: cardpch.c:64 #, fuzzy msgid "HHCPU001E File name missing or invalid\n" msgstr "HHC351I Bestandsnaam niet opgegeven of ongeldig\n" #: cardpch.c:102 #, fuzzy, c-format msgid "HHCPU002E Invalid argument: %s\n" msgstr "HHC422I Optie %s niet geldig\n" #: cardpch.c:183 #, fuzzy, c-format msgid "HHCPU003E Error opening file %s: %s\n" msgstr "HHC404I Fout %2$s bij openen van bestand \"%1$s\"\n" #: cardrdr.c:92 #, fuzzy msgid "HHCRD001E Out of memory\n" msgstr "HHC403I Niet genoeg geheugen\n" #: cardrdr.c:190 #, fuzzy, c-format msgid "HHCRD002E File name too long (max=%ud): \"%s\"\n" msgstr "HHC401I Bestandsnaam \"%2$s\" te lang (maximum=%1$ud)\n" #: cardrdr.c:197 #, fuzzy, c-format msgid "HHCRD003E Unable to access file \"%s\": %s\n" msgstr "HHC402I Fout %2$s bij benaderen bestand \"%1$s\"\n" #: cardrdr.c:207 #, fuzzy msgid "HHCRD004E Out of memory\n" msgstr "HHC403I Niet genoeg geheugen\n" #: cardrdr.c:220 #, fuzzy msgid "HHCRD005E Specify 'ascii' or 'ebcdic' (or neither) but not both\n" msgstr "HHC403I Specificeer 'ascii' of 'ebcdic' (of niets) maar niet beide\n" #: cardrdr.c:229 #, fuzzy msgid "HHCRD006E Only one filename (sock_spec) allowed for socket devices\n" msgstr "HHC403I Maar een bestandsnaam toegestaan voor socket apparaten\n" #: cardrdr.c:244 #, fuzzy, c-format msgid "HHCRD007I Defaulting to 'ascii' for socket device %4.4X\n" msgstr "HHC403I standaard waarde 'ascii' aan socket apparaat %4.4X toegekend\n" #: cardrdr.c:252 #, fuzzy msgid "HHCRD008W 'multifile' option ignored: only one file specified\n" msgstr "HHC403I 'multifile' optie niet gebruikt\n" #: cardrdr.c:265 #, fuzzy, c-format msgid "HHCRD009E File name too long (max=%ud): \"%s\"\n" msgstr "HHC401I Bestandsnaam \"%2$s\" te lang (maximum=%1$ud)\n" #: cardrdr.c:279 #, fuzzy, c-format msgid "HHCRD010E Unable to access file \"%s\": %s\n" msgstr "HHC402I Fout %2$s bij benaderen bestand \"%1$s\"\n" #: cardrdr.c:360 #, fuzzy, c-format msgid "HHCRD011E Close error on file \"%s\": %s\n" msgstr "HHC419E Fout %2$s bij sluiten van bestand \"%1$s\"\n" #: cardrdr.c:369 #, fuzzy, c-format msgid "HHCRD012I %s (%s) disconnected from device %4.4X (%s)\n" msgstr "HHC420I %s (%s) afgesloten van apparaat %4.4X (%s)\n" #: cardrdr.c:468 #, fuzzy, c-format msgid "HHCRD013E Error opening file %s: %s\n" msgstr "HHC423I Fout %2$s bij openen bestand \"%1$s\"\n" #: cardrdr.c:490 #, fuzzy, c-format msgid "HHCRD014E Error reading file %s: %s\n" msgstr "HHC409I Fout %2$s bij lezen van bestand \"%1$s\"\n" #: cardrdr.c:523 #, fuzzy, c-format msgid "HHCRD015E Seek error in file %s: %s\n" msgstr "HHC406I Fout %2$s bij zoeken in bestand \"%1$s\"\n" #: cardrdr.c:596 #, fuzzy, c-format msgid "HHCRD016E Error reading file %s: %s\n" msgstr "HHC409I Fout %2$s bij lezen van bestand \"%1$s\"\n" #: cardrdr.c:599 #, fuzzy, c-format msgid "HHCRD017E Unexpected end of file on %s\n" msgstr "HHC40I Onverwacht einde van bestand \"%s\"\n" #: cardrdr.c:672 #, fuzzy, c-format msgid "HHCRD018E Error reading file %s: %s\n" msgstr "HHC409I Fout %2$s bij lezen van bestand \"%1$s\"\n" #: cardrdr.c:700 #, fuzzy, c-format msgid "HHCRD019E Card image exceeds %d bytes in file %s\n" msgstr "HHC410I Ponskaart %d bytes te groot in bestand \"%s\"\n" #: cckdcdsk.c:139 #, c-format msgid "" "\n" "cckdcdsk [-v] [-f] [-level] [-ro] file1 [file2 ...]\n" "\n" " -v display version and exit\n" "\n" " -f force check even if OPENED bit is on\n" "\n" " level is a digit 0 - 3:\n" " -0 -- minimal checking\n" " -1 -- normal checking\n" " -3 -- maximal checking\n" "\n" " -ro open file readonly, no repairs\n" "\n" msgstr "" #: cckddasd.c:322 #, fuzzy, c-format msgid "HHCCD101E %4.4X error initializing shadow files\n" msgstr "HHC423I Fout %2$s bij openen bestand \"%1$s\"\n" #: cckddasd.c:586 #, fuzzy, c-format msgid "HHCCD130E %4.4X file[%d] %s open error: %s\n" msgstr "HHC423I Fout %2$s bij openen bestand \"%1$s\"\n" #: cckddasd.c:621 #, fuzzy, c-format msgid "HHCCD130E %4.4X file[%d] close error: %s\n" msgstr "HHC423I Fout %2$s bij openen bestand \"%1$s\"\n" #: cckddasd.c:649 cckddasd.c:690 #, fuzzy msgid "HHCCD130E %4.4X file[%d] lseek error, offset 0x%" msgstr "HHC419E Fout %2$s bij sluiten van bestand \"%1$s\"\n" #: cckddasd.c:660 #, fuzzy msgid "HHCCD130E %4.4X file[%d] read error, offset 0x%" msgstr "%d Bytes gelesen von %s\n" #: cckddasd.c:663 #, fuzzy msgid "HHCCD130E %4.4X file[%d] read incomplete, offset 0x%" msgstr "HHC406I Fout %2$s bij zoeken in bestand \"%1$s\"\n" #: cckddasd.c:700 #, fuzzy msgid "HHCCD130E %4.4X file[%d] write error, offset 0x%" msgstr "HHC406I Fout %2$s bij zoeken in bestand \"%1$s\"\n" #: cckddasd.c:703 #, fuzzy msgid "HHCCD130E %4.4X file[%d] write incomplete, offset 0x%" msgstr "HHC406I Fout %2$s bij zoeken in bestand \"%1$s\"\n" #: cckddasd.c:729 #, fuzzy msgid "HHCCD130E %4.4X file[%d] ftruncate error, offset 0x%" msgstr "HHC406I Fout %2$s bij zoeken in bestand \"%1$s\"\n" #: cckddasd.c:751 #, fuzzy, c-format msgid "HHCCD130E %4.4X malloc error, size %d: %s\n" msgstr "HHC405I Fout %2$s bij lezen van bestand \"%1$s\"\n" #: cckddasd.c:772 #, fuzzy, c-format msgid "HHCCD130E %4.4X calloc error, size %d: %s\n" msgstr "HHC405I Fout %2$s bij lezen van bestand \"%1$s\"\n" #: cckddasd.c:1518 #, fuzzy, c-format msgid "HHCCD001I Readahead thread %d started: tid=" msgstr "HHC650I Controle paneel thread gestart: tid=%8.8lX, pid=%d\n" #: cckddasd.c:1569 #, fuzzy, c-format msgid "HHCCD011I Readahead thread %d stopping: tid=" msgstr "HHC650I Controle paneel thread gestart: tid=%8.8lX, pid=%d\n" #: cckddasd.c:1719 #, fuzzy, c-format msgid "HHCCD002I Writer thread %d started: tid=" msgstr "HHC650I Controle paneel thread gestart: tid=%8.8lX, pid=%d\n" #: cckddasd.c:1841 #, fuzzy, c-format msgid "HHCCD012I Writer thread %d stopping: tid=" msgstr "HHC650I Controle paneel thread gestart: tid=%8.8lX, pid=%d\n" #: cckddasd.c:1979 #, fuzzy, c-format msgid "HHCCD102E %4.4X file[%d] get space error, size exceeds %lldM\n" msgstr "%d Bytes gelesen von %s\n" #: cckddasd.c:2488 #, fuzzy, c-format msgid "HHCCD110E %4.4X file[%d] devhdr id error\n" msgstr "%d Bytes gelesen von %s\n" #: cckddasd.c:3216 #, fuzzy, c-format msgid "HHCCD121E %4.4X file[%d] trklen err for %2.2x%2.2x%2.2x%2.2x%2.2x\n" msgstr "*** Spur %d HA Validierungsfehler! %2.2x%2.2x%2.2x%2.2x%2.2x\n" #: cckddasd.c:3385 #, fuzzy, c-format msgid "" "HHCCD122E %4.4X file[%d] invalid byte 0 trk %d: buf %2.2x%2.2x%2.2x%2.2x%" "2.2x\n" msgstr "" "%4.4X ckddasd: Kopfdaten ungültig für Zyl. %d Spur %d %2.2x%2.2x%2.2x%2.2x%" "2.2x\n" #: cckddasd.c:3407 #, fuzzy, c-format msgid "" "HHCCD123E %4.4X file[%d] invalid byte 0 blkgrp %d: buf %2.2x%2.2x%2.2x%2.2x%" "2.2x\n" msgstr "" "%4.4X ckddasd: Kopfdaten ungültig für Zyl. %d Spur %d %2.2x%2.2x%2.2x%2.2x%" "2.2x\n" #: cckddasd.c:3422 #, c-format msgid "" "HHCCD124E %4.4X file[%d] invalid %s hdr %s %d: %s compression unsupported\n" msgstr "" #: cckddasd.c:3430 #, fuzzy, c-format msgid "" "HHCCD125E %4.4X file[%d] invalid %s hdr %s %d buf %p:%2.2x%2.2x%2.2x%2.2x%" "2.2x\n" msgstr "" "%4.4X ckddasd: Kopfdaten ungültig für Zyl. %d Spur %d %2.2x%2.2x%2.2x%2.2x%" "2.2x\n" #: cckddasd.c:3584 #, c-format msgid "" "HHCCD142E %4.4X file[%d] shadow file name %s\n" " collides with %4.4X file[%d] name %s\n" msgstr "" #: cckddasd.c:3629 #, fuzzy, c-format msgid "" "HHCCD151E %4.4X file[%d] error re-opening %s readonly\n" " %s\n" msgstr "HHC404I Fout %2$s bij openen van bestand \"%1$s\"\n" #: cckddasd.c:3657 #, fuzzy, c-format msgid "HHCCD161E %4.4X file[%d] no shadow file name\n" msgstr "HHC406I Fout %2$s bij zoeken in bestand \"%1$s\"\n" #: cckddasd.c:3665 #, fuzzy, c-format msgid "HHCCD161E %4.4X file[%d] max shadow files exceeded\n" msgstr "HHC406I Fout %2$s bij zoeken in bestand \"%1$s\"\n" #: cckddasd.c:3748 #, fuzzy, c-format msgid "HHCCD160E %4.4X not a cckd device\n" msgstr "%d Geräte bearbeitet\n" #: cckddasd.c:3778 #, fuzzy, c-format msgid "HHCCD161E %4.4X file[%d] error adding shadow file\n" msgstr "HHC406I Fout %2$s bij zoeken in bestand \"%1$s\"\n" #: cckddasd.c:3787 #, fuzzy, c-format msgid "HHCCD162I %4.4X file[%d] %s added\n" msgstr "HHC760I %4.4X create_thread fout: %s" #: cckddasd.c:3834 #, fuzzy, c-format msgid "HHCCD170E %4.4X not a cckd device\n" msgstr "%d Geräte bearbeitet\n" #: cckddasd.c:3840 #, fuzzy, c-format msgid "HHCCD171E %4.4X file[%d] cannot remove base file\n" msgstr "Kann %s nicht öffnen: %s\n" #: cckddasd.c:3884 #, c-format msgid "" "HHCCD172E %4.4X file[%d] not merged, file[%d] cannot be opened read-write%s\n" msgstr "" #: cckddasd.c:3898 #, c-format msgid "HHCCD173E %4.4X file[%d] not merged, file[%d] check failed\n" msgstr "" #: cckddasd.c:3911 #, c-format msgid "HHCCD174E %4.4X file[%d] not merged, file not hardened\n" msgstr "" #: cckddasd.c:4076 #, fuzzy, c-format msgid "HHCCD181I %4.4X shadow file [%d] successfully %s%s\n" msgstr "HHC423I Fout %2$s bij openen bestand \"%1$s\"\n" #: cckddasd.c:4108 #, fuzzy, c-format msgid "HHCCD201W %4.4X device is not a shadow file\n" msgstr "HHC406I Fout %2$s bij zoeken in bestand \"%1$s\"\n" #: cckddasd.c:4113 #, c-format msgid "HHCCD202W %4.4X file shadowing not activated\n" msgstr "" #: cckddasd.c:4121 #, fuzzy, c-format msgid "HHCCD203W %4.4X shadowing is already active\n" msgstr "HHC623I CPU%4.4X thread al gestart\n" #: cckddasd.c:4130 #, fuzzy, c-format msgid "HHCCD204I %4.4X shadow file name set to %s\n" msgstr "Ongeldig apparaat nummer\n" #: cckddasd.c:4148 #, fuzzy, c-format msgid "HHCCD205W %4.4X device is not a shadow file\n" msgstr "HHC406I Fout %2$s bij zoeken in bestand \"%1$s\"\n" #: cckddasd.c:4213 #, fuzzy, c-format msgid "HHCCD206W %4.4X device is not a shadow file\n" msgstr "HHC406I Fout %2$s bij zoeken in bestand \"%1$s\"\n" #: cckddasd.c:4230 msgid "" "HHCCD210I size free nbr st reads writes l2reads hits " "switches\n" msgstr "" #: cckddasd.c:4232 msgid "" "HHCCD211I readaheads " "misses\n" msgstr "" #: cckddasd.c:4233 msgid "" "HHCCD212I " "--------------------------------------------------------------------\n" msgstr "" #: cckddasd.c:4236 msgid "HHCCD213I [*] %10" msgstr "" #: cckddasd.c:4241 #, c-format msgid "" "HHCCD214I %7d %7d\n" msgstr "" #: cckddasd.c:4245 #, c-format msgid "HHCCD215I %s\n" msgstr "" #: cckddasd.c:4246 msgid "HHCCD216I [0] %10" msgstr "" #: cckddasd.c:4253 #, c-format msgid "HHCCD217I %s\n" msgstr "" #: cckddasd.c:4258 msgid "HHCCD218I [%d] %10" msgstr "" #: cckddasd.c:4357 #, fuzzy msgid "HHCCD003I Garbage collector thread started: tid=" msgstr "HHC650I Controle paneel thread gestart: tid=%8.8lX, pid=%d\n" #: cckddasd.c:4465 #, fuzzy msgid "HHCCD013I Garbage collector thread stopping: tid=" msgstr "HHC650I Controle paneel thread gestart: tid=%8.8lX, pid=%d\n" #: cckddasd.c:4690 #, fuzzy msgid "HHCCD190E %4.4X file[%d] offset 0x%" msgstr "HHC423I Fout %2$s bij openen bestand \"%1$s\"\n" #: cckddasd.c:4960 #, fuzzy, c-format msgid "" "HHCCD193E %4.4X file[%d] uncompress error trk %d: %2.2x%2.2x%2.2x%2.2x%2.2x\n" msgstr "" "%4.4X ckddasd: Kopfdaten ungültig für Zyl. %d Spur %d %2.2x%2.2x%2.2x%2.2x%" "2.2x\n" #: cckddasd.c:4963 #, c-format msgid "HHCCD194E %4.4X file[%d] %s compression not supported\n" msgstr "" #: cckddasd.c:5488 msgid "HHCCD900I print_itrace\n" msgstr "" #: cckddiag.c:138 #, c-format msgid "lseek to pos 0x%8.8x error: %s\n" msgstr "" #: cckddiag.c:154 #, fuzzy, c-format msgid "cckddiag: read error: %s\n" msgstr "HHC423I Fout %2$s bij openen bestand \"%1$s\"\n" #: cckddiag.c:509 #, fuzzy, c-format msgid "cckddiag: error opening file %s: %s\n" msgstr "HHC423I Fout %2$s bij openen bestand \"%1$s\"\n" #: channel.c:125 #, c-format msgid "HHCCP048I %4.4X:CCW=%2.2X%2.2X%2.2X%2.2X %2.2X%2.2X%2.2X%2.2X%s\n" msgstr "" #: channel.c:138 #, c-format msgid "HHCCP049I %4.4X:Stat=%2.2X%2.2X Count=%2.2X%2.2X CCW=%2.2X%2.2X%2.2X\n" msgstr "" #: channel.c:151 #, c-format msgid "" "HHCCP050I %4.4X:SCSW=%2.2X%2.2X%2.2X%2.2X Stat=%2.2X%2.2X Count=%2.2X%2.2X " "CCW=%2.2X%2.2X%2.2X%2.2X\n" msgstr "" #: channel.c:260 #, c-format msgid "HHCCP051I %4.4X: Test I/O\n" msgstr "" #: channel.c:325 #, fuzzy msgid "HHCCP052I TIO modification executed CC=1\n" msgstr "HIO modificatie uitgevoerd CC=1\n" #: channel.c:362 #, c-format msgid "HHCCP053I %4.4X: Halt I/O\n" msgstr "" #: channel.c:416 #, fuzzy msgid "HHCCP054I HIO modification executed CC=1\n" msgstr "HIO modificatie uitgevoerd CC=1\n" #: channel.c:787 #, c-format msgid "HHCCP055I %4.4X: Clear subchannel\n" msgstr "" #: channel.c:888 #, c-format msgid "HHCCP056I %4.4X: Halt subchannel\n" msgstr "" #: channel.c:910 #, c-format msgid "HHCCP057I %4.4X: Halt subchannel: cc=1\n" msgstr "" #: channel.c:920 #, c-format msgid "HHCCP058I %4.4X: Halt subchannel: cc=2\n" msgstr "" #: channel.c:1011 #, c-format msgid "HHCCP059I %4.4X: Halt subchannel: cc=0\n" msgstr "" #: channel.c:1049 #, c-format msgid "HHCCP060I %4.4X: Resume subchannel: cc=1\n" msgstr "" #: channel.c:1063 #, c-format msgid "HHCCP061I %4.4X: Resume subchannel: cc=2\n" msgstr "" #: channel.c:1086 #, c-format msgid "HHCCP062I %4.4X: Resume subchannel: cc=0\n" msgstr "" #: channel.c:1844 msgid "HHCCP078I %4.4X:MIDAW=%2.2X %4.4" msgstr "" #: channel.c:1943 msgid "HHCCP063I %4.4X:IDAW=%8.8" msgstr "" #: channel.c:1948 msgid "HHCCP064I %4.4X:IDAW=%16.16" msgstr "" #: channel.c:2065 #, fuzzy, c-format msgid "HHCCP065I DEV%4.4X: attention signalled\n" msgstr "HHC420I %s (%s) afgesloten van apparaat %4.4X (%s)\n" #: channel.c:2077 #, fuzzy, c-format msgid "HHCCP066I DEV%4.4X: attention\n" msgstr "HHC420I %s (%s) afgesloten van apparaat %4.4X (%s)\n" #: channel.c:2302 #, fuzzy, c-format msgid "HHCCP067E %4.4X create_thread error: %s" msgstr "HHC760I %4.4X create_thread fout: %s" #: channel.c:2325 #, fuzzy, c-format msgid "HHCCP068E %4.4X create_thread error: %s" msgstr "HHC760I %4.4X create_thread fout: %s" #: channel.c:2518 #, fuzzy, c-format msgid "HHCCP069I Device %4.4X initial status interrupt\n" msgstr "HHC420I %s (%s) afgesloten van apparaat %4.4X (%s)\n" #: channel.c:2557 #, fuzzy, c-format msgid "HHCCP070I Device %4.4X attention completed\n" msgstr "HHC420I %s (%s) afgesloten van apparaat %4.4X (%s)\n" #: channel.c:2623 #, fuzzy, c-format msgid "HHCCP071I Device %4.4X clear completed\n" msgstr "HHC623I CPU%4.4X thread al gestart\n" #: channel.c:2678 #, fuzzy, c-format msgid "HHCCP072I Device %4.4X halt completed\n" msgstr "HHC420I %s (%s) afgesloten van apparaat %4.4X (%s)\n" #: channel.c:2856 #, fuzzy, c-format msgid "HHCCP073I Device %4.4X suspended\n" msgstr "HHC420I %s (%s) afgesloten van apparaat %4.4X (%s)\n" #: channel.c:2914 #, fuzzy, c-format msgid "HHCCP074I Device %4.4X resumed\n" msgstr "HHC420I %s (%s) afgesloten van apparaat %4.4X (%s)\n" #: channel.c:3128 #, c-format msgid "HHCCP075I %4.4X:Stat=%2.2X%2.2X Count=%4.4X %s\n" msgstr "" #: channel.c:3134 #, c-format msgid "" "HHCCP076I %4.4X:Sense=%2.2X%2.2X%2.2X%2.2X %2.2X%2.2X%2.2X%2.2X %2.2X%2.2X%" "2.2X%2.2X %2.2X%2.2X%2.2X%2.2X %2.2X%2.2X%2.2X%2.2X %2.2X%2.2X%2.2X%2.2X\n" msgstr "" #: channel.c:3149 #, c-format msgid "HHCCP077I %4.4X:Sense=%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n" msgstr "" #: ckddasd.c:237 #, fuzzy msgid "HHCDA001E File name missing or invalid\n" msgstr "HHC351I Bestandsnaam niet opgegeven of ongeldig\n" #: ckddasd.c:255 #, fuzzy, c-format msgid "HHCDA002E %4.4X:File not found or invalid\n" msgstr "HHC351I Bestandsnaam niet opgegeven of ongeldig\n" #: ckddasd.c:357 #, fuzzy, c-format msgid "HHCDA003E parameter %d is invalid: %s\n" msgstr "HHC351I Bestandsnaam niet opgegeven of ongeldig\n" #: ckddasd.c:368 #, fuzzy, c-format msgid "HHCDA004I opening %s readonly%s\n" msgstr "HHC404I Fout %2$s bij openen van bestand \"%1$s\"\n" #: ckddasd.c:382 #, fuzzy, c-format msgid "HHCDA005E %s open error: %s\n" msgstr "HHC423I Fout %2$s bij openen bestand \"%1$s\"\n" #: ckddasd.c:391 #, c-format msgid "HHCDA006E %s not in a single file for shadowing\n" msgstr "" #: ckddasd.c:400 #, fuzzy, c-format msgid "HHCDA007E %s fstat error: %s\n" msgstr "%d Bytes gelesen von %s\n" #: ckddasd.c:410 #, fuzzy, c-format msgid "HHCDA008E %s read error: %s\n" msgstr "%d Bytes gelesen von %s\n" #: ckddasd.c:413 #, c-format msgid "HHCDA09E %s CKD header incomplete\n" msgstr "" #: ckddasd.c:423 #, fuzzy, c-format msgid "HHCDA010E %s CKD header invalid\n" msgstr "%d Bytes gelesen von %s\n" #: ckddasd.c:432 #, c-format msgid "HHCDA011E %s Only 1 CCKD file allowed\n" msgstr "" #: ckddasd.c:447 #, fuzzy, c-format msgid "HHCDA012E %s read error: %s\n" msgstr "%d Bytes gelesen von %s\n" #: ckddasd.c:452 #, c-format msgid "HHCDA013E %s CCKD header incomplete\n" msgstr "" #: ckddasd.c:510 #, c-format msgid "HHCDA014E %s CKD file out of sequence\n" msgstr "" #: ckddasd.c:517 #, c-format msgid "HHCDA015I %s seq=%d cyls=%d-%d\n" msgstr "" #: ckddasd.c:531 #, c-format msgid "HHCDA016E %s heads=%d trklen=%d, expected heads=%d trklen=%d\n" msgstr "" #: ckddasd.c:544 #, c-format msgid "HHCDA017E %s CKD header inconsistent with file size\n" msgstr "" #: ckddasd.c:552 #, c-format msgid "HHCDA018E %s CKD header high cylinder incorrect\n" msgstr "" #: ckddasd.c:578 #, fuzzy, c-format msgid "HHCDA019E %s exceeds maximum %d CKD files\n" msgstr "HHC410I Ponskaart %d bytes te groot in bestand \"%s\"\n" #: ckddasd.c:589 #, fuzzy, c-format msgid "HHCDA020I %s cyls=%d heads=%d tracks=%d trklen=%d\n" msgstr "%d Bytes gelesen von %s\n" #: ckddasd.c:611 #, fuzzy, c-format msgid "HHCDA021E %4.4X device type %4.4X not found in dasd table\n" msgstr "HHC420I %s (%s) afgesloten van apparaat %4.4X (%s)\n" #: ckddasd.c:620 #, c-format msgid "HHCDA022E %4.4X control unit %s not found in dasd table\n" msgstr "" #: ckddasd.c:702 #, c-format msgid "HHCDA023I %4.4X cache hits %d, misses %d, waits %d\n" msgstr "" #: ckddasd.c:785 #, fuzzy, c-format msgid "HHCDA024I read trk %d cur trk %d\n" msgstr "HHC409I Fout %2$s bij lezen van bestand \"%1$s\"\n" #: ckddasd.c:814 #, c-format msgid "HHCDA025I read track: updating track %d\n" msgstr "" #: ckddasd.c:825 #, fuzzy, c-format msgid "HHCDA026E error writing trk %d: lseek error: %s\n" msgstr "HHC423I Fout %2$s bij schrijven naar bestand \"%1$s\"\n" #: ckddasd.c:844 #, fuzzy, c-format msgid "HHCDA027E error writing trk %d: write error: %s\n" msgstr "HHC423I Fout %2$s bij schrijven naar bestand \"%1$s\"\n" #: ckddasd.c:886 #, c-format msgid "HHCDA028I read trk %d cache hit, using cache[%d]\n" msgstr "" #: ckddasd.c:923 #, c-format msgid "HHCDA029I read trk %d no available cache entry, waiting\n" msgstr "" #: ckddasd.c:931 #, c-format msgid "HHCDA030I read trk %d cache miss, using cache[%d]\n" msgstr "" #: ckddasd.c:954 #, fuzzy msgid "HHCDA031I read trk %d reading file %d offset %" msgstr "HHC409I Fout %2$s bij lezen van bestand \"%1$s\"\n" #: ckddasd.c:963 #, fuzzy, c-format msgid "HHCDA032E error reading trk %d: lseek error: %s\n" msgstr "HHC409I Fout %2$s bij lezen van bestand \"%1$s\"\n" #: ckddasd.c:981 #, fuzzy, c-format msgid "HHCDA033E error reading trk %d: read error: %s\n" msgstr "HHC409I Fout %2$s bij lezen van bestand \"%1$s\"\n" #: ckddasd.c:1004 #, fuzzy, c-format msgid "HHCDA034I read trk %d trkhdr %2.2x %2.2x%2.2x %2.2x%2.2x\n" msgstr "" "%4.4X ckddasd: Kopfdaten ungültig für Zyl. %d Spur %d %2.2x%2.2x%2.2x%2.2x%" "2.2x\n" #: ckddasd.c:1013 #, fuzzy, c-format msgid "" "HHCDA035E %4.4X invalid track header for cyl %d head %d %2.2x%2.2x%2.2x%2.2x" "%2.2x\n" msgstr "" "%4.4X ckddasd: Kopfdaten ungültig für Zyl. %d Spur %d %2.2x%2.2x%2.2x%2.2x%" "2.2x\n" #: ckddasd.c:1527 #, fuzzy, c-format msgid "HHCDA038I seeking to cyl %d head %d\n" msgstr "HHC409I Fout %2$s bij lezen van bestand \"%1$s\"\n" #: ckddasd.c:1566 #, fuzzy, c-format msgid "HHCDA039E MT advance error: locate record %d file mask %2.2X\n" msgstr "Ongeldig apparaat nummer\n" #: ckddasd.c:1598 #, fuzzy, c-format msgid "HHCDA040I MT advance to cyl %d head %d\n" msgstr "HHC409I Fout %2$s bij lezen van bestand \"%1$s\"\n" #: ckddasd.c:1645 #, fuzzy, c-format msgid "HHCDA041I read count orientation is %s\n" msgstr "HHC406I Fout %2$s bij zoeken in bestand \"%1$s\"\n" #: ckddasd.c:1669 #, c-format msgid "HHCDA042E attempt to read past end of track %d %d\n" msgstr "" #: ckddasd.c:1691 #, fuzzy, c-format msgid "HHCDA043I cyl %d head %d record %d kl %d dl %d of %d\n" msgstr "%d Bytes gelesen von %s\n" #: ckddasd.c:1779 #, fuzzy, c-format msgid "HHCDA044I read key %d bytes\n" msgstr "%d Bytes gelesen von %s\n" #: ckddasd.c:1787 msgid "ckddasd: attempt to read past end of track\n" msgstr "" #: ckddasd.c:1829 #, c-format msgid "HHCDA045I read data %d bytes\n" msgstr "" #: ckddasd.c:1837 msgid "HHCDA046E attempt to read past end of track\n" msgstr "" #: ckddasd.c:1955 #, fuzzy, c-format msgid "HHCDA047I writing cyl %d head %d record %d kl %d dl %d\n" msgstr "%d Bytes gelesen von %s\n" #: ckddasd.c:1961 #, fuzzy, c-format msgid "HHCDA048I setting track overflow flag for cyl %d head %d record %d\n" msgstr "%d Bytes gelesen von %s\n" #: ckddasd.c:2006 msgid "HHCDA049E Write KD orientation error\n" msgstr "" #: ckddasd.c:2019 #, fuzzy, c-format msgid "HHCDA050I updating cyl %d head %d record %d kl %d dl %d\n" msgstr "%d Bytes gelesen von %s\n" #: ckddasd.c:2048 msgid "HHCDA051E Write data orientation error\n" msgstr "" #: ckddasd.c:2062 #, fuzzy, c-format msgid "HHCDA052I updating cyl %d head %d record %d dl %d\n" msgstr "%d Bytes gelesen von %s\n" #: ckddasd.c:2121 #, c-format msgid "HHCDA053E Data chaining not supported for CCW %2.2X\n" msgstr "" #: ckddasd.c:3375 #, fuzzy, c-format msgid "HHCDA054I set file mask %2.2X\n" msgstr "Ongeldig apparaat nummer\n" #: ckddasd.c:3543 #, c-format msgid "HHCDA055I search key %s\n" msgstr "" #: codepage.c:485 #, fuzzy, c-format msgid "HHCCF072I Using internal codepage conversion table %s\n" msgstr "HHC050I CodePage conversie tabel %s is niet gedefinieerd\n" #: codepage.c:495 #, fuzzy, c-format msgid "HHCCF072I Using external codepage conversion table %s\n" msgstr "HHC050I CodePage conversie tabel %s is niet gedefinieerd\n" #: codepage.c:501 #, fuzzy, c-format msgid "HHCCF051E Codepage conversion table %s is not defined\n" msgstr "HHC050I CodePage conversie tabel %s is niet gedefinieerd\n" #: commadpt.c:97 #, c-format msgid "HHCCA300D %4.4X:%s : Status = TEXT=%s, TRANS=%s, TWS=%s\n" msgstr "" #: commadpt.c:103 #, c-format msgid "HHCCA300D %4.4X:%s : Dump of %d (%x) byte(s)\n" msgstr "" #: commadpt.c:112 #, c-format msgid "HHCCA300D %4.4X:%s : %4.4X:" msgstr "" #: commadpt.c:262 #, c-format msgid "HHCCA300D %4.4X:clean : Control block freed\n" msgstr "" #: commadpt.c:270 #, c-format msgid "HHCCA300D %4.4X:clean : Control block not freed : not allocated\n" msgstr "" #: commadpt.c:284 #, c-format msgid "HHCCA020E %4.4X:Memory allocation failure for main control block\n" msgstr "" #: commadpt.c:365 #, fuzzy, c-format msgid "" "HHCCA001I %4.4X:Connect out to %s:%d failed during initial status : %s\n" msgstr "CPU%4.4X: Verbunden mit Channel-Set %4.4X\n" #: commadpt.c:407 #, c-format msgid "HHCCA300D %4.4x : Found data beyond EON\n" msgstr "" #: commadpt.c:422 #, fuzzy, c-format msgid "HHCCA300D %4.4x : Found incorrect IP address section at position %d\n" msgstr "CPU%4.4X nicht konfiguriert\n" #: commadpt.c:423 #, c-format msgid "HHCCA300D %4.4x : %d greater than 255\n" msgstr "" #: commadpt.c:437 #, c-format msgid "HHCCA300D %4.4x : Too many separators in dial data\n" msgstr "" #: commadpt.c:454 #, c-format msgid "HHCCA300D %4.4x : Incorrect dial data byte %2.2x\n" msgstr "" #: commadpt.c:475 #, c-format msgid "HHCCA300D %4.4x : Not enough separators (only %d found) in dial data\n" msgstr "" #: commadpt.c:483 #, c-format msgid "HHCCA300D %4.4x : Destination TCP port %d exceeds maximum of 65535\n" msgstr "" #: commadpt.c:616 #, fuzzy, c-format msgid "HHCCA002I %4.4X:Line Communication thread " msgstr "HHC650I Controle paneel thread gestart: tid=%8.8lX, pid=%d\n" #: commadpt.c:628 #, fuzzy, c-format msgid "HHCCA003E %4.4X:Cannot obtain socket for incoming calls : %s\n" msgstr "Kann %s nicht öffnen: %s\n" #: commadpt.c:653 #, c-format msgid "HHCCA004W %4.4X:Waiting 5 seconds for port %d to become available\n" msgstr "" #: commadpt.c:704 #, fuzzy, c-format msgid "HHCCA018E %4.4X:Bind failed : %s\n" msgstr "HHC760I %4.4X create_thread fout: %s" #: commadpt.c:718 #, c-format msgid "HHCCA005I %4.4X:Listening on port %d for incoming TCP connections\n" msgstr "" #: commadpt.c:756 #, c-format msgid "HHCCA300D %4.4X:cthread - Entry - DevExec = %s\n" msgstr "" #: commadpt.c:821 #, c-format msgid "HHCCA300D %4.4X:Poll Command abort - Poll address >7 Bytes\n" msgstr "" #: commadpt.c:849 #, fuzzy, c-format msgid "HHCCA300D %4.4X:Writing 1 byte in socket : %2.2X\n" msgstr "HHC423I Fout %2$s bij schrijven naar bestand \"%1$s\"\n" #: commadpt.c:1029 #, c-format msgid "HHCCA300D %4.4X:cthread - Select IN maxfd = %d / Devexec = %s\n" msgstr "" #: commadpt.c:1035 #, fuzzy, c-format msgid "HHCCA300D %4.4X:cthread - Select OUT rc=%d\n" msgstr "HHC760I %4.4X create_thread fout: %s" #: commadpt.c:1051 #, fuzzy, c-format msgid "HHCCA006T %4.4X:Select failed : %s\n" msgstr "HHC760I %4.4X create_thread fout: %s" #: commadpt.c:1062 #, c-format msgid "HHCCA300D %4.4X:cthread - Select TIME OUT\n" msgstr "" #: commadpt.c:1080 #, c-format msgid "HHCCA300D %4.4X:cthread - IPC Pipe closed\n" msgstr "" #: commadpt.c:1088 #, c-format msgid "HHCCA300D %4.4X:cthread - IPC Pipe Data ; code = %d\n" msgstr "" #: commadpt.c:1120 #, fuzzy, c-format msgid "HHCCA300D %4.4X:cthread - inbound socket data\n" msgstr "HHC423I Fout %2$s bij schrijven naar bestand \"%1$s\"\n" #: commadpt.c:1162 #, c-format msgid "HHCCA300D %4.4X:cthread - socket write available\n" msgstr "" #: commadpt.c:1176 #, c-format msgid "HHCCA007W %4.4X:Outgoing call failed during %s command : %s\n" msgstr "" #: commadpt.c:1206 #, c-format msgid "HHCCA008I %4.4X:cthread - Incoming Call\n" msgstr "" #: commadpt.c:1266 #, fuzzy, c-format msgid "HHCCA009I %4.4X:BSC utility thread terminated\n" msgstr "HHC650I Controle paneel thread gestart: tid=%8.8lX, pid=%d\n" #: commadpt.c:1317 #, fuzzy, c-format msgid "HHCCA013E %4.4X:Incorrect %s specification %s\n" msgstr "CPU%4.4X nicht konfiguriert\n" #: commadpt.c:1321 #, c-format msgid "HHCCA015E %4.4X:Missing parameter : DIAL=%s and %s not specified\n" msgstr "" #: commadpt.c:1325 #, c-format msgid "HHCCA016W %4.4X:Conflicting parameter : DIAL=%s and %s=%s specified\n" msgstr "" #: commadpt.c:1326 #, fuzzy, c-format msgid "HHCCA017I %4.4X:RPORT parameter ignored\n" msgstr "CPU%4.4X nicht konfiguriert\n" #: commadpt.c:1349 #, fuzzy, c-format msgid "HHCCA300D %4.4X:Initialisation starting\n" msgstr "HHC420I %s (%s) afgesloten van apparaat %4.4X (%s)\n" #: commadpt.c:1355 #, fuzzy, c-format msgid "HHCCA010I %4.4X:initialisation not performed\n" msgstr "HHC420I %s (%s) afgesloten van apparaat %4.4X (%s)\n" #: commadpt.c:1361 #, fuzzy, c-format msgid "HHCCA300D %4.4X:Initialisation : Control block allocated\n" msgstr "HHC420I %s (%s) afgesloten van apparaat %4.4X (%s)\n" #: commadpt.c:1384 #, fuzzy, c-format msgid "HHCCA011E %4.4X:Error parsing %s\n" msgstr "HHC423I Fout %2$s bij schrijven naar bestand \"%1$s\"\n" #: commadpt.c:1390 #, fuzzy, c-format msgid "HHCCA012E %4.4X:Unrecognized parameter %s\n" msgstr "CPU%4.4X nicht konfiguriert\n" #: commadpt.c:1478 #, c-format msgid "" "HHCCA014E %4.4X:Incorrect switched/dial specification %s; defaulting to " "DIAL=OUT\n" msgstr "" #: commadpt.c:1597 #, fuzzy, c-format msgid "HHCCA021I %4.4X:Initialisation failed due to previous errors\n" msgstr "CCW Ablaufverfolgung ist %s für %4.4X\n" #: commadpt.c:1657 #, c-format msgid "HHCCA019E %4.4x : BSC comm thread did not initialise\n" msgstr "" #: commadpt.c:1699 #, fuzzy, c-format msgid "HHCCA300D %4.4X:Closing down\n" msgstr "HHC423I Fout %2$s bij schrijven naar bestand \"%1$s\"\n" #: commadpt.c:1731 #, fuzzy, c-format msgid "HHCCA300D %4.4X:Closed down\n" msgstr "HHC760I %4.4X create_thread fout: %s" #: commadpt.c:1760 #, c-format msgid "HHCCA300D %4.4X:CCW Exec - Entry code = %x\n" msgstr "" #: commadpt.c:1871 #, fuzzy, c-format msgid "HHCCA300D %4.4X Set Mode : %s\n" msgstr "HHC760I %4.4X create_thread fout: %s" #: config.c:122 #, c-format msgid "HHCCF040E Cannot create CPU%4.4X thread: %s\n" msgstr "" #: config.c:293 #, fuzzy msgid "HHCCF043E Cannot obtain device block\n" msgstr "Kann %s nicht öffnen: %s\n" #: config.c:409 #, fuzzy, c-format msgid "HHCCF041E Device %d:%4.4X already exists\n" msgstr "HHC423I Fout %2$s bij schrijven naar bestand \"%1$s\"\n" #: config.c:418 #, c-format msgid "HHCCF042E Device type %s not recognized\n" msgstr "" #: config.c:446 #, fuzzy, c-format msgid "HHCCF044E Initialization failed for device %4.4X\n" msgstr "CCW Ablaufverfolgung ist %s für %4.4X\n" #: config.c:468 #, c-format msgid "HHCCF045E Cannot obtain buffer for device %4.4X: %s\n" msgstr "" #: config.c:600 #, fuzzy, c-format msgid "HHCCF046E Subchannel %d:%4.4X does not exist\n" msgstr "HHC423I Fout %2$s bij schrijven naar bestand \"%1$s\"\n" #: config.c:607 #, fuzzy, c-format msgid "HHCCF047I Subchannel %d:%4.4X detached\n" msgstr "HHC420I %s (%s) afgesloten van apparaat %4.4X (%s)\n" #: config.c:626 #, fuzzy, c-format msgid "HHCCF046E Device %d:%4.4X does not exist\n" msgstr "HHC423I Fout %2$s bij schrijven naar bestand \"%1$s\"\n" #: config.c:633 #, c-format msgid "HHCCF047I Device %4.4X detached\n" msgstr "" #: config.c:651 #, fuzzy, c-format msgid "HHCCF048E Device %d:%4.4X does not exist\n" msgstr "HHC423I Fout %2$s bij schrijven naar bestand \"%1$s\"\n" #: config.c:658 #, fuzzy, c-format msgid "HHCCF049E Device %d:%4.4X already exists\n" msgstr "HHC423I Fout %2$s bij schrijven naar bestand \"%1$s\"\n" #: config.c:934 msgid "" "HHCCF074E Unspecified error occured while parsing Logical Channel Subsystem " "Identification\n" msgstr "" #: config.c:950 msgid "" "HHCCF075E No more than 1 Logical Channel Subsystem Identification may be " "specified\n" msgstr "" #: config.c:960 #, c-format msgid "HHCCF076E Non numeric Logical Channel Subsystem Identification %s\n" msgstr "" #: config.c:969 #, c-format msgid "" "HHCCF077E Logical Channel Subsystem Identification %d exceeds maximum of %d\n" msgstr "" #: config.c:1001 config.c:1117 #, fuzzy, c-format msgid "HHCCF055E Incorrect device address specification near character %c\n" msgstr "CPU%4.4X nicht konfiguriert\n" #: config.c:1099 #, c-format msgid "" "HHCCF053E Incorrect second device number in device range near character %c\n" msgstr "" #: config.c:1110 #, c-format msgid "HHCCF054E Incorrect Device count near character %c\n" msgstr "" #: config.c:1125 #, c-format msgid "HHCCF056E Incorrect device address range. %4.4X < %4.4X\n" msgstr "" #: config.c:1148 #, c-format msgid "" "HHCCF057E %4.4X is on wrong channel (1st device defined on channel %2.2X)\n" msgstr "" #: config.c:1178 #, c-format msgid "" "HHCCF058E Some or all devices in %4.4X-%4.4X duplicate devices already " "defined\n" msgstr "" #: console.c:373 #, fuzzy, c-format msgid "HHCGI001I Unable to determine IP address from %s\n" msgstr "HHC406I Fout %2$s bij zoeken in bestand \"%1$s\"\n" #: console.c:394 #, fuzzy, c-format msgid "HHCGI002I Unable to determine port number from %s\n" msgstr "HHC406I Fout %2$s bij zoeken in bestand \"%1$s\"\n" #: console.c:408 #, fuzzy, c-format msgid "HHCGI003E Invalid parameter: %s\n" msgstr "HHC422I Optie %s niet geldig\n" #: console.c:923 #, fuzzy, c-format msgid "HHCTE014I %4.4X device %4.4X client %s connection reset\n" msgstr "HHC420I %s (%s) afgesloten van apparaat %4.4X (%s)\n" #: console.c:933 #, fuzzy, c-format msgid "HHCTE007I %4.4X device %4.4X client %s connection closed\n" msgstr "HHC420I %s (%s) afgesloten van apparaat %4.4X (%s)\n" #: console.c:1098 #, c-format msgid "HHCTE008I Device %4.4X connection closed by client %s\n" msgstr "" #: console.c:1821 #, fuzzy, c-format msgid "HHCTE009I Client %s connected to %4.4X device %d:%4.4X\n" msgstr "HHC420I %s (%s) afgesloten van apparaat %4.4X (%s)\n" #: console.c:1936 #, fuzzy msgid "HHCTE001I Console connection thread started: tid=" msgstr "HHC650I Controle paneel thread gestart: tid=%8.8lX, pid=%d\n" #: console.c:1960 #, fuzzy, c-format msgid "HHCTE010E CNSLPORT statement invalid: %s\n" msgstr "HHC422I Optie %s niet geldig\n" #: console.c:1972 #, c-format msgid "HHCTE002W Waiting for port %u to become free\n" msgstr "" #: console.c:1991 #, c-format msgid "HHCTE003I Waiting for console connection on port %u\n" msgstr "" #: console.c:2253 #, fuzzy msgid "HHCTE004I Console connection thread terminated\n" msgstr "HHC650I Controle paneel thread gestart: tid=%8.8lX, pid=%d\n" #: console.c:2283 #, c-format msgid "HHCTE005E Cannot create console thread: %s\n" msgstr "" #: console.c:2305 msgid "** BUG! console_remove() error! **\n" msgstr "" #: console.c:2377 console.c:2663 #, fuzzy, c-format msgid "HHCTE011E Device %4.4X: Invalid IP address: %s\n" msgstr "Ongeldig frame adres %8.8X\n" #: console.c:2388 console.c:2674 #, fuzzy, c-format msgid "HHCTE012E Device %4.4X: Invalid mask value: %s\n" msgstr "Ongeldig apparaat nummer\n" #: console.c:2397 console.c:2683 #, fuzzy, c-format msgid "HHCTE013E Device %4.4X: Extraneous argument(s): %s...\n" msgstr "CPU%4.4X nicht konfiguriert\n" #: console.c:2544 #, fuzzy, c-format msgid "HHCTE090E %4.4X malloc() failed for resume buf: %s\n" msgstr "HHC409I Fout %2$s bij lezen van bestand \"%1$s\"\n" #: console.c:3488 #, fuzzy, c-format msgid "HHCTE006A Enter input for console device %4.4X\n" msgstr "HHC420I %s (%s) afgesloten van apparaat %4.4X (%s)\n" #: cpu.c:326 msgid "HHCCP043I Wait state PSW loaded: " msgstr "" #: cpu.c:521 #, c-format msgid "program_int() passing to guest code=%4.4X\n" msgstr "" #: cpu.c:612 msgid "HHCCP014I " msgstr "" #: cpu.c:615 hscmisc.c:1088 msgid "SIE: " msgstr "" #: cpu.c:622 #, c-format msgid "CPU%4.4X: %s CODE=%4.4X ILC=%d%s\n" msgstr "" #: cpu.c:736 #, c-format msgid "HHCCP015I CPU%4.4X PER event: code=%4.4X perc=%2.2X addr=" msgstr "" #: cpu.c:914 #, c-format msgid "HHCCP016I CPU%4.4X: Program interrupt loop: " msgstr "" #: cpu.c:1028 #, c-format msgid "" "HHCCP044I I/O interrupt code=%4.4X CSW=%2.2X%2.2X%2.2X%2.2X %2.2X%2.2X%2.2X%" "2.2X\n" msgstr "" #: cpu.c:1050 #, c-format msgid "HHCCP045I I/O interrupt code=%8.8X parm=%8.8X\n" msgstr "" #: cpu.c:1053 #, c-format msgid "HHCCP046I I/O interrupt code=%8.8X parm=%8.8X id=%8.8X\n" msgstr "" #: cpu.c:1119 msgid "HHCCP022I Machine Check code=%16.16" msgstr "" #: cpu.c:1180 #, fuzzy, c-format msgid "HHCCP001W CPU%4.4X thread set priority %d failed: %s\n" msgstr "HHC406I Fout %2$s bij zoeken in bestand \"%1$s\"\n" #: cpu.c:1187 #, fuzzy, c-format msgid "HHCCP002I CPU%4.4X thread started: tid=" msgstr "HHC623I CPU%4.4X thread al gestart\n" #: cpu.c:1210 #, fuzzy, c-format msgid "HHCCP006S Cannot create timer thread: %s\n" msgstr "Kann %s nicht öffnen: %s\n" #: cpu.c:1239 #, fuzzy, c-format msgid "HHCCP008I CPU%4.4X thread ended: tid=" msgstr "HHC623I CPU%4.4X thread al gestart\n" #: cpu.c:1471 hsccmd.c:1340 #, fuzzy, c-format msgid "HHCCP010I CPU%4.4X store status completed.\n" msgstr "HHC623I CPU%4.4X thread al gestart\n" #: cpu.c:1540 #, fuzzy, c-format msgid "" "HHCCP011I CPU%4.4X: Disabled wait state\n" " " msgstr "HHC623I CPU%4.4X thread al gestart\n" #: cpu.c:1654 #, fuzzy, c-format msgid "HHCCP007I CPU%4.4X architecture mode set to %s\n" msgstr "HHC630I CPU%4.4X Architectuur Modus %s\n" #: cpu.c:1664 #, fuzzy, c-format msgid "HHCCP003I CPU%4.4X architecture mode %s\n" msgstr "HHC630I CPU%4.4X Architectuur Modus %s\n" #: cpu.c:1669 #, fuzzy, c-format msgid "HHCCP004I CPU%4.4X Vector Facility online\n" msgstr "HHC623I CPU%4.4X thread al gestart\n" #: cpu.c:1697 #, fuzzy, c-format msgid "HHCCP080E CPU%4.4X malloc failed for archjmp regs: %s\n" msgstr "HHC409I Fout %2$s bij lezen van bestand \"%1$s\"\n" #: cpu.c:1897 #, c-format msgid "PSW=%2.2X%2.2X%2.2X%2.2X %2.2X%2.2X%2.2X%2.2X\n" msgstr "" #: cpu.c:1904 #, c-format msgid "" "PSW=%2.2X%2.2X%2.2X%2.2X %2.2X%2.2X%2.2X%2.2X %2.2X%2.2X%2.2X%2.2X%2.2X%2.2X%" "2.2X%2.2X\n" msgstr "" #: ctc_ctci.c:155 #, fuzzy, c-format msgid "HHCCT037E %4.4X: Unable to allocate CTCBLK\n" msgstr "HHC402I Fout %2$s bij benaderen bestand \"%1$s\"\n" #: ctc_ctci.c:176 #, fuzzy, c-format msgid "HHCCT038E %4.4X: Unable to allocate CTCBLK\n" msgstr "HHC402I Fout %2$s bij benaderen bestand \"%1$s\"\n" #: ctc_ctci.c:233 #, fuzzy, c-format msgid "HHCCT073I %4.4X: TUN device %s opened\n" msgstr "HHC420I %s (%s) afgesloten van apparaat %4.4X (%s)\n" #: ctc_ctci.c:250 #, fuzzy, c-format msgid "HHCCT074W TT32SDEVBUFF failed for device %s: %s.\n" msgstr "HHC419E Fout %2$s bij sluiten van bestand \"%1$s\"\n" #: ctc_ctci.c:257 #, fuzzy, c-format msgid "HHCCT075W TT32SIOBUFF failed for device %s: %s.\n" msgstr "CCW Ablaufverfolgung ist %s für %4.4X\n" #: ctc_ctci.c:683 #, c-format msgid "HHCCT040I %4.4X: Halt or Clear Recognized\n" msgstr "" #: ctc_ctci.c:732 #, c-format msgid "HHCCT041I %4.4X: CTC Received Frame (%d bytes):\n" msgstr "" #: ctc_ctci.c:770 #, fuzzy, c-format msgid "HHCCT042E %4.4X: Write CCW count %u is invalid\n" msgstr "HHC351I Bestandsnaam niet opgegeven of ongeldig\n" #: ctc_ctci.c:799 #, c-format msgid "HHCCT043I %4.4X: Interface command: %s %8.8X\n" msgstr "" #: ctc_ctci.c:826 ctcadpt.c:748 #, c-format msgid "CTC101W %4.4X: Write buffer contains invalid frame offset %u\n" msgstr "" #: ctc_ctci.c:848 #, c-format msgid "" "HHCCT044E %4.4X: Write buffer contains incomplete segment header at offset %" "4.4X\n" msgstr "" #: ctc_ctci.c:868 #, c-format msgid "" "HHCCT045E %4.4X: Write buffer contains invalid segment length %u at offset %" "4.4X\n" msgstr "" #: ctc_ctci.c:883 #, fuzzy, c-format msgid "HHCCT046I %4.4X: Sending packet to %s:\n" msgstr "CPU%4.4X: Verbunden mit Channel-Set %4.4X\n" #: ctc_ctci.c:893 #, fuzzy, c-format msgid "HHCCT047E %4.4X: Error writing to %s: %s\n" msgstr "HHC423I Fout %2$s bij schrijven naar bestand \"%1$s\"\n" #: ctc_ctci.c:956 #, fuzzy, c-format msgid "HHCCT048E %4.4X: Error reading from %s: %s\n" msgstr "HHC405I Fout %2$s bij lezen van bestand \"%1$s\"\n" #: ctc_ctci.c:968 #, c-format msgid "HHCCT049I %4.4X: Received packet from %s (%d bytes):\n" msgstr "" #: ctc_ctci.c:980 #, c-format msgid "HHCCT072W %4.4X: Packet too big; dropped.\n" msgstr "" #: ctc_ctci.c:1124 ctc_ctci.c:1309 #, fuzzy, c-format msgid "HHCCT056E %4.4X: Incorrect number of parameters\n" msgstr "Geen apparaat nummer\n" #: ctc_ctci.c:1209 #, fuzzy, c-format msgid "HHCCT050E %4.4X: Invalid adapter address %s\n" msgstr "Ongeldig frame adres %8.8X\n" #: ctc_ctci.c:1218 #, fuzzy, c-format msgid "HHCCT051E %4.4X: Invalid device name %s\n" msgstr "Ongeldig apparaat nummer\n" #: ctc_ctci.c:1232 #, fuzzy, c-format msgid "HHCCT052E %4.4X: Invalid kernel buffer size %s\n" msgstr "Ongeldig apparaat nummer\n" #: ctc_ctci.c:1246 #, fuzzy, c-format msgid "HHCCT053E %4.4X: Invalid DLL I/O buffer size %s\n" msgstr "Ongeldig apparaat nummer\n" #: ctc_ctci.c:1260 #, fuzzy, c-format msgid "HHCCT054E %4.4X: Invalid MTU size %s\n" msgstr "Ongeldig frame adres %8.8X\n" #: ctc_ctci.c:1271 #, fuzzy, c-format msgid "HHCCT055E %4.4X: Invalid netmask %s\n" msgstr "Ongeldig apparaat nummer\n" #: ctc_ctci.c:1282 #, fuzzy, c-format msgid "HHCCT056E %4.4X: Invalid MAC address %s\n" msgstr "Ongeldig frame adres %8.8X\n" #: ctc_ctci.c:1319 #, fuzzy, c-format msgid "HHCCT057E %4.4X: Incorrect number of parameters\n" msgstr "Geen apparaat nummer\n" #: ctc_ctci.c:1327 #, fuzzy, c-format msgid "HHCCT058E %4.4X: Invalid IP address %s\n" msgstr "Ongeldig frame adres %8.8X\n" #: ctc_ctci.c:1339 #, fuzzy, c-format msgid "HHCCT059E %4.4X: Invalid IP address %s\n" msgstr "Ongeldig frame adres %8.8X\n" #: ctc_ctci.c:1355 #, fuzzy, c-format msgid "HHCCT060E %4.4X: Incorrect number of parameters\n" msgstr "Geen apparaat nummer\n" #: ctc_ctci.c:1364 #, fuzzy, c-format msgid "HHCCT061E %4.4X: invalid device name %s\n" msgstr "Ongeldig apparaat nummer\n" #: ctc_ctci.c:1378 #, fuzzy, c-format msgid "HHCCT062E %4.4X: Invalid MTU size %s\n" msgstr "Ongeldig frame adres %8.8X\n" #: ctc_ctci.c:1389 #, fuzzy, c-format msgid "HHCCT063E %4.4X: Invalid IP address %s\n" msgstr "Ongeldig frame adres %8.8X\n" #: ctc_ctci.c:1401 #, fuzzy, c-format msgid "HHCCT064E %4.4X: Invalid IP address %s\n" msgstr "Ongeldig frame adres %8.8X\n" #: ctc_ctci.c:1413 #, fuzzy, c-format msgid "HHCCT065E %4.4X: Invalid netmask %s\n" msgstr "Ongeldig apparaat nummer\n" #: ctc_ctci.c:1424 #, fuzzy, c-format msgid "HHCCT066E %4.4X: Incorrect number of parameters\n" msgstr "Geen apparaat nummer\n" #: ctc_ctci.c:1442 #, fuzzy, c-format msgid "HHCCT067E %4.4X: Invalid IP address %s\n" msgstr "Ongeldig frame adres %8.8X\n" #: ctc_ctci.c:1457 #, fuzzy, c-format msgid "HHCCT068E %4.4X: Invalid MAC address %s\n" msgstr "Ongeldig frame adres %8.8X\n" #: ctc_ctci.c:1489 #, fuzzy, c-format msgid "HHCCT069E %4.4X: Invalid kernel buffer size %s\n" msgstr "Ongeldig apparaat nummer\n" #: ctc_ctci.c:1506 #, fuzzy, c-format msgid "HHCCT070E %4.4X: Invalid DLL I/O buffer size %s\n" msgstr "Ongeldig apparaat nummer\n" #: ctc_ctci.c:1517 #, fuzzy, c-format msgid "HHCCT071E %4.4X: Incorrect number of parameters\n" msgstr "Geen apparaat nummer\n" #: ctc_lcs.c:122 #, fuzzy, c-format msgid "HHCLC001E %4.4X unable to allocate LCSBLK\n" msgstr "HHC402I Fout %2$s bij benaderen bestand \"%1$s\"\n" #: ctc_lcs.c:269 #, fuzzy, c-format msgid "HHCLC073I %4.4X: TAP device %s opened\n" msgstr "HHC420I %s (%s) afgesloten van apparaat %4.4X (%s)\n" #: ctc_lcs.c:285 #, fuzzy, c-format msgid "HHCLC074W TT32SDEVBUFF failed for device %s: %s.\n" msgstr "HHC419E Fout %2$s bij sluiten van bestand \"%1$s\"\n" #: ctc_lcs.c:292 #, fuzzy, c-format msgid "HHCLC075W TT32SIOBUFF failed for device %s: %s.\n" msgstr "HHC419E Fout %2$s bij sluiten van bestand \"%1$s\"\n" #: ctc_lcs.c:765 #, fuzzy, c-format msgid "HHCLC002I %4.4X: Halt or Clear Recognized\n" msgstr "HHC420I %s (%s) afgesloten van apparaat %4.4X (%s)\n" #: ctc_lcs.c:808 #, fuzzy, c-format msgid "HHCLC003I %4.4X: LCS Read Buffer:\n" msgstr "Ongeldig apparaat nummer\n" #: ctc_lcs.c:871 #, fuzzy, c-format msgid "HHCLCxxxI %4.4X: Startup\n" msgstr "Ongeldig apparaat nummer\n" #: ctc_lcs.c:876 #, fuzzy, c-format msgid "HHCLCxxxI %4.4X: Shutdown\n" msgstr "HHC760I %4.4X create_thread fout: %s" #: ctc_lcs.c:882 #, c-format msgid "HHCLCxxxI %4.4X: Start LAN\n" msgstr "" #: ctc_lcs.c:887 #, c-format msgid "HHCLCxxxI %4.4X: Stop LAN\n" msgstr "" #: ctc_lcs.c:893 #, fuzzy, c-format msgid "HHCLCxxxI %4.4X: Query\n" msgstr "Ongeldig apparaat nummer\n" #: ctc_lcs.c:899 #, fuzzy, c-format msgid "HHCLCxxxI %4.4X: Stat\n" msgstr "HHC420I %s (%s) afgesloten van apparaat %4.4X (%s)\n" #: ctc_lcs.c:929 #, fuzzy, c-format msgid "HHCLC004I %4.4X: Sending packet to %s:\n" msgstr "CPU%4.4X: Verbunden mit Channel-Set %4.4X\n" #: ctc_lcs.c:938 #, fuzzy, c-format msgid "HHCLC005E %4.4X: Error writing to %s: %s\n" msgstr "HHC423I Fout %2$s bij schrijven naar bestand \"%1$s\"\n" #: ctc_lcs.c:957 #, fuzzy, c-format msgid "HHCLC006I %4.4X Triggering Event.\n" msgstr "CPU%4.4X: Verbunden mit Channel-Set %4.4X\n" #: ctc_lcs.c:1343 #, fuzzy, c-format msgid "HHCLC007E Error in call to socket: %s.\n" msgstr "HHC423I Fout %2$s bij schrijven naar bestand \"%1$s\"\n" #: ctc_lcs.c:1356 #, fuzzy, c-format msgid "HHCLC008E ioctl error on device %s: %s.\n" msgstr "HHC419E Fout %2$s bij sluiten van bestand \"%1$s\"\n" #: ctc_lcs.c:1453 #, fuzzy, c-format msgid "HHCLC042E Port %2.2X: Read error: %s\n" msgstr "%d Bytes gelesen von %s\n" #: ctc_lcs.c:1462 #, c-format msgid "HHCLC009I Port %2.2X: Read Buffer:\n" msgstr "" #: ctc_lcs.c:1491 #, c-format msgid "HHCLC010I Port %2.2X: IPV4 frame for %8.8X\n" msgstr "" #: ctc_lcs.c:1518 #, c-format msgid "HHCLC011I Port %2.2X: ARP frame for %8.8X\n" msgstr "" #: ctc_lcs.c:1547 #, fuzzy, c-format msgid "" "HHCLC011I Port %2.2X: RARP frame for %2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X\n" msgstr "" "%4.4X ckddasd: Kopfdaten ungültig für Zyl. %d Spur %d %2.2x%2.2x%2.2x%2.2x%" "2.2x\n" #: ctc_lcs.c:1579 #, c-format msgid "HHCLC012I Port %2.2X: SNA frame\n" msgstr "" #: ctc_lcs.c:1609 #, c-format msgid "HHCLC013I Port %2.2X: No match found - selecting primary %4.4X\n" msgstr "" #: ctc_lcs.c:1619 #, c-format msgid "HHCLC014I Port %2.2X: No match found - selecting secondary %4.4X\n" msgstr "" #: ctc_lcs.c:1630 #, c-format msgid "HHCLC015I Port %2.2X: No match found - Discarding frame\n" msgstr "" #: ctc_lcs.c:1638 #, fuzzy, c-format msgid "HHCLC016I Port %2.2X: Enqueing frame to device %4.4X (%8.8X)\n" msgstr "HHC420I %s (%s) afgesloten van apparaat %4.4X (%s)\n" #: ctc_lcs.c:1652 #, fuzzy, c-format msgid "HHCLC041W Port %2.2X: Frame too big; discarded.\n" msgstr "HHC420I %s (%s) afgesloten van apparaat %4.4X (%s)\n" #: ctc_lcs.c:1900 #, fuzzy, c-format msgid "HHCLC017E %4.4X invalid device name %s\n" msgstr "Ongeldig apparaat nummer\n" #: ctc_lcs.c:1916 #, fuzzy, c-format msgid "HHCLC052E %4.4X: Invalid kernel buffer size %s\n" msgstr "Ongeldig apparaat nummer\n" #: ctc_lcs.c:1930 #, fuzzy, c-format msgid "HHCLC053E %4.4X: Invalid DLL I/O buffer size %s\n" msgstr "Ongeldig apparaat nummer\n" #: ctc_lcs.c:1946 #, fuzzy, c-format msgid "HHCLC018E %4.4X invalid MAC address %s\n" msgstr "Ongeldig frame adres %8.8X\n" #: ctc_lcs.c:1970 #, c-format msgid "HHCLC019E %4.4X too many arguments in statement.\n" msgstr "" #: ctc_lcs.c:1980 #, fuzzy, c-format msgid "HHCLC020E %4.4X invalid IP address %s\n" msgstr "Ongeldig frame adres %8.8X\n" #: ctc_lcs.c:2035 #, fuzzy, c-format msgid "HHCLC039E Cannot open file %s: %s\n" msgstr "Kann %s nicht öffnen: %s\n" #: ctc_lcs.c:2087 #, fuzzy, c-format msgid "HHCLC021E Invalid HWADD statement in %s: %s\n" msgstr "HHC422I Optie %s niet geldig\n" #: ctc_lcs.c:2096 #, c-format msgid "" "HHCLC022E Invalid MAC in HWADD statement in %s: %s (%s)\n" " " msgstr "" #: ctc_lcs.c:2113 #, fuzzy, c-format msgid "HHCLC023E Invalid ROUTE statement in %s: %s\n" msgstr "HHC422I Optie %s niet geldig\n" #: ctc_lcs.c:2120 #, fuzzy, c-format msgid "HHCLC024E Invalid net address in ROUTE %s: %s (%s)\n" msgstr "Ongeldig bereik: %s\n" #: ctc_lcs.c:2130 #, fuzzy, c-format msgid "HHCLC025E Invalid net mask in ROUTE %s: %s (%s)\n" msgstr "Ongeldig apparaat nummer\n" #: ctc_lcs.c:2162 #, fuzzy, c-format msgid "HHCLC026E Error in %s: Missing device number or mode\n" msgstr "Geen apparaat nummer\n" #: ctc_lcs.c:2171 #, fuzzy, c-format msgid "HHCLC027E Error in %s: %s: Invalid device number\n" msgstr "Ongeldig apparaat nummer\n" #: ctc_lcs.c:2183 #, fuzzy, c-format msgid "HHCLC028E Error in %s: %s:Missing PORT number\n" msgstr "Geen apparaat nummer\n" #: ctc_lcs.c:2191 #, fuzzy, c-format msgid "HHCLC029E Error in %s: %s: Invalid PORT number\n" msgstr "Ongeldig apparaat nummer\n" #: ctc_lcs.c:2207 #, fuzzy, c-format msgid "HHCLC031E Error in %s: %s: Invalid entry starting at %s\n" msgstr "Ongeldig apparaat nummer\n" #: ctc_lcs.c:2219 #, fuzzy, c-format msgid "HHCLC032E Error is %s: %s: Invalid IP address (%s)\n" msgstr "Ongeldig frame adres %8.8X\n" #: ctc_lcs.c:2235 #, fuzzy, c-format msgid "HHCLC033E Error in %s: %s: Missing PORT number\n" msgstr "Geen apparaat nummer\n" #: ctc_lcs.c:2243 #, fuzzy, c-format msgid "HHCLC034E Error in %s: %s:Invalid PORT number\n" msgstr "Ongeldig apparaat nummer\n" #: ctc_lcs.c:2251 #, fuzzy, c-format msgid "HHCLC035E Error in %s: %s: SNA does not accept any arguments\n" msgstr "HHC409I Fout %2$s bij lezen van bestand \"%1$s\"\n" #: ctc_lcs.c:2259 #, fuzzy, c-format msgid "HHCLC036E Error in %s: %s: Invalid MODE\n" msgstr "Ongeldig apparaat nummer\n" #: ctc_lcs.c:2324 #, fuzzy, c-format msgid "HHCLC037E Error reading file %s line %d: %s\n" msgstr "HHC409I Fout %2$s bij lezen van bestand \"%1$s\"\n" #: ctc_lcs.c:2348 #, c-format msgid "HHCLC038E File %s line %d is too long\n" msgstr "" #: ctcadpt.c:167 #, fuzzy, c-format msgid "HHCCT001E %4.4X: Incorrect number of parameters\n" msgstr "Geen apparaat nummer\n" #: ctcadpt.c:180 #, c-format msgid "HHCCT034E %s: Unrecognized/unsupported CTC emulation type\n" msgstr "" #: ctcadpt.c:488 #, fuzzy, c-format msgid "HHCCT002E %4.4X: Incorrect number of parameters\n" msgstr "Geen apparaat nummer\n" #: ctcadpt.c:500 #, fuzzy, c-format msgid "HHCCT003E %4.4X: Invalid port number: %s\n" msgstr "Ongeldig apparaat nummer\n" #: ctcadpt.c:521 #, fuzzy, c-format msgid "HHCCT004E %4.4X: Invalid IP address %s\n" msgstr "Ongeldig frame adres %8.8X\n" #: ctcadpt.c:534 #, fuzzy, c-format msgid "HHCCT005E %4.4X: Invalid port number: %s\n" msgstr "Ongeldig apparaat nummer\n" #: ctcadpt.c:546 #, fuzzy, c-format msgid "HHCCT006E %4.4X: Invalid MTU size %s\n" msgstr "Ongeldig frame adres %8.8X\n" #: ctcadpt.c:567 #, fuzzy, c-format msgid "HHCCT007E %4.4X: Error creating socket: %s\n" msgstr "HHC423I Fout %2$s bij schrijven naar bestand \"%1$s\"\n" #: ctcadpt.c:587 #, fuzzy, c-format msgid "HHCCT008E %4.4X: Error binding to socket: %s\n" msgstr "HHC423I Fout %2$s bij schrijven naar bestand \"%1$s\"\n" #: ctcadpt.c:608 #, fuzzy, c-format msgid "HHCCT009I %4.4X: Connect to %s:%s failed, starting server\n" msgstr "CPU%4.4X: Verbunden mit Channel-Set %4.4X\n" #: ctcadpt.c:618 #, fuzzy, c-format msgid "HHCCT010E %4.4X: Error creating socket: %s\n" msgstr "HHC423I Fout %2$s bij schrijven naar bestand \"%1$s\"\n" #: ctcadpt.c:635 #, fuzzy, c-format msgid "HHCCT011E %4.4X: Error binding to socket: %s\n" msgstr "HHC423I Fout %2$s bij schrijven naar bestand \"%1$s\"\n" #: ctcadpt.c:643 #, fuzzy, c-format msgid "HHCCT012E %4.4X: Error on call to listen: %s\n" msgstr "HHC423I Fout %2$s bij schrijven naar bestand \"%1$s\"\n" #: ctcadpt.c:659 #, fuzzy, c-format msgid "HHCCT013I %4.4X: Connected to %s:%s\n" msgstr "CPU%4.4X: Verbunden mit Channel-Set %4.4X\n" #: ctcadpt.c:693 #, fuzzy, c-format msgid "HHCCT014E %4.4X: Write CCW count %u is invalid\n" msgstr "HHC351I Bestandsnaam niet opgegeven of ongeldig\n" #: ctcadpt.c:723 #, c-format msgid "HHCCT015I %4.4X: Interface command: %s %8.8X\n" msgstr "" #: ctcadpt.c:769 #, c-format msgid "" "HHCCT016E %4.4X: Write buffer contains incomplete segment header at offset %" "4.4X\n" msgstr "" #: ctcadpt.c:789 #, c-format msgid "" "HHCCT017E %4.4X: Write buffer contains invalid segment length %u at offset %" "4.4X\n" msgstr "" #: ctcadpt.c:804 #, fuzzy, c-format msgid "HHCCT018I %4.4X: Sending packet to %s:\n" msgstr "CPU%4.4X: Verbunden mit Channel-Set %4.4X\n" #: ctcadpt.c:815 #, fuzzy, c-format msgid "HHCCT019E %4.4X: Error writing to %s: %s\n" msgstr "HHC423I Fout %2$s bij schrijven naar bestand \"%1$s\"\n" #: ctcadpt.c:878 #, fuzzy, c-format msgid "HHCCT020E %4.4X: Error reading from %s: %s\n" msgstr "HHC405I Fout %2$s bij lezen van bestand \"%1$s\"\n" #: ctcadpt.c:895 #, fuzzy, c-format msgid "HHCCT021E %4.4X: Error reading from %s: %s\n" msgstr "HHC405I Fout %2$s bij lezen van bestand \"%1$s\"\n" #: ctcadpt.c:905 #, c-format msgid "HHCCT022I %4.4X: Received packet from %s (%d bytes):\n" msgstr "" #: ctcadpt.c:987 #, fuzzy, c-format msgid "" "HHCCT023E %4.4X: Incorrect client or config error\n" " Config=%s, connecting client=%s\n" msgstr "CPU%4.4X nicht konfiguriert\n" #: ctcadpt.c:1031 #, fuzzy, c-format msgid "HHCCT024E %4.4X: Not enough arguments to start vmnet\n" msgstr "CPU%4.4X nicht konfiguriert\n" #: ctcadpt.c:1041 #, fuzzy, c-format msgid "HHCCT025E %4.4X: Failed: socketpair: %s\n" msgstr "HHC423I Fout %2$s bij schrijven naar bestand \"%1$s\"\n" #: ctcadpt.c:1049 #, fuzzy, c-format msgid "HHCCT026E %4.4X: Failed: fork: %s\n" msgstr "HHC760I %4.4X create_thread fout: %s" #: ctcadpt.c:1100 #, fuzzy, c-format msgid "HHCCT027E %4.4X: Not enough parameters\n" msgstr "CPU%4.4X nicht konfiguriert\n" #: ctcadpt.c:1106 #, fuzzy, c-format msgid "HHCCT028E %d:%4.4X: Bad device number '%s'\n" msgstr "Ongeldig apparaat nummer\n" #: ctcadpt.c:1143 #, c-format msgid "HHCCT029E %4.4X: bad block length: %d < %d\n" msgstr "" #: ctcadpt.c:1153 #, c-format msgid "HHCCT030E %4.4X: bad packet length: %d < %d\n" msgstr "" #: ctcadpt.c:1158 #, c-format msgid "HHCCT031E %4.4X: bad packet length: %d < 6\n" msgstr "" #: ctcadpt.c:1204 #, c-format msgid "HHCCT032E %4.4X: Error: EOF on read, CTC network down\n" msgstr "" #: ctcadpt.c:1212 #, fuzzy, c-format msgid "HHCCT033E %4.4X: Error: read: %s\n" msgstr "HHC405I Fout %2$s bij lezen van bestand \"%1$s\"\n" #: dasdcat.c:43 #, c-format msgid "HHCDT002E Can't make 80 column card images from block length %d\n" msgstr "" #: dasdcat.c:119 #, c-format msgid "HHCDT003E Directory block byte count is invalid\n" msgstr "" #: dasdcat.c:221 #, c-format msgid "HHCDT004E non-PDS-members not yet supported\n" msgstr "" #: dasdcat.c:253 #, c-format msgid "HHCDT005E unknown dataset name option: '%c'\n" msgstr "" #: dasdcat.c:350 #, fuzzy, c-format msgid "HHCDT001E failed to open image %s\n" msgstr "HHC406I Fout %2$s bij zoeken in bestand \"%1$s\"\n" #: dasdcopy.c:119 #, c-format msgid "Hercules %s copy program " msgstr "" #: dasdcopy.c:204 #, fuzzy, c-format msgid "HHCDC001E %s: %s open error: %s\n" msgstr "HHC423I Fout %2$s bij openen bestand \"%1$s\"\n" #: dasdcopy.c:211 #, fuzzy, c-format msgid "HHCDC002E %s: %s read error: %s\n" msgstr "%d Bytes gelesen von %s\n" #: dasdcopy.c:274 #, fuzzy, c-format msgid "HHCDC003E %s: %s open failed\n" msgstr "HHC406I Fout %2$s bij zoeken in bestand \"%1$s\"\n" #: dasdcopy.c:288 #, c-format msgid "HHCDC004E %s: ckd lookup failed for %4.4X cyls %d\n" msgstr "" #: dasdcopy.c:308 #, c-format msgid "HHCDC005E %s: fba lookup failed, blks %d\n" msgstr "" #: dasdcopy.c:329 #, c-format msgid "HHCDC006E %s: %s create failed\n" msgstr "" #: dasdcopy.c:341 #, fuzzy, c-format msgid "HHCDC007E %s: %s open failed\n" msgstr "HHC406I Fout %2$s bij zoeken in bestand \"%1$s\"\n" #: dasdcopy.c:378 #, fuzzy, c-format msgid "HHCDC008E %s: %s read error %s %d stat=%2.2X, null %s substituted\n" msgstr "%d Bytes gelesen von %s\n" #: dasdcopy.c:388 #, fuzzy, c-format msgid " %3d%% %7d of %d" msgstr "%c %3d%% Spur %6d von %6d" #: dasdcopy.c:417 #, c-format msgid "HHCDC009E %s: %s write error %s %d stat=%2.2X\n" msgstr "" #: dasdcopy.c:429 #, fuzzy, c-format msgid "HHCDC010I %s successfully completed.\n" msgstr "HHC623I CPU%4.4X thread al gestart\n" #: dasdcopy.c:517 #, c-format msgid "" "usage: ckd2cckd [-options] ifile ofile\n" "\n" " copy a ckd dasd file to a compressed ckd dasd file\n" "\n" " ifile -- input ckd dasd file\n" " ofile -- output compressed ckd dasd file\n" "\n" " options:\n" " -v display program version and quit\n" " -h display this help and quit\n" " -q quiet mode, don't display status\n" " -r replace the output file if it exists\n" "%s%s -0 don't compress track images\n" " -cyls n size of output file\n" " -a output file will have alt cyls\n" msgstr "" #: dasdcopy.c:537 dasdcopy.c:593 dasdcopy.c:655 msgid " -z compress using zlib [default]\n" msgstr "" #: dasdcopy.c:544 dasdcopy.c:600 msgid " -bz2 compress using bzip2\n" msgstr "" #: dasdcopy.c:552 #, c-format msgid "" "usage: cckd2ckd [-options] ifile [sf=sfile] ofile\n" "\n" " copy a compressed ckd file to a ckd file\n" "\n" " ifile -- input compressed ckd dasd file\n" " sfile -- input compressed ckd shadow file\n" " (optional)\n" " ofile -- output ckd dasd file\n" "\n" " options:\n" " -v display program version and quit\n" " -h display this help and quit\n" " -q quiet mode, don't display status\n" " -r replace the output file if it exists\n" "%s -cyls n size of output file\n" " -a output file will have alt cyls\n" msgstr "" #: dasdcopy.c:570 dasdcopy.c:625 msgid " -lfs create single large output file\n" msgstr "" #: dasdcopy.c:574 #, c-format msgid "" "usage: fba2cfba [-options] ifile ofile\n" "\n" " copy a fba dasd file to a compressed fba dasd file\n" "\n" " ifile -- input fba dasd file\n" " ofile -- output compressed fba dasd file\n" "\n" " options:\n" " -v display program version and quit\n" " -h display this help and quit\n" " -q quiet mode, don't display status\n" " -r replace the output file if it exists\n" "%s%s -0 don't compress track images\n" " -blks n size of output file\n" msgstr "" #: dasdcopy.c:608 #, c-format msgid "" "usage: cfba2fba [-options] ifile [sf=sfile] ofile\n" "\n" " copy a compressed fba file to a fba file\n" "\n" " ifile -- input compressed fba dasd file\n" " sfile -- input compressed fba shadow file\n" " (optional)\n" " ofile -- output fba dasd file\n" "\n" " options:\n" " -v display program version and quit\n" " -h display this help and quit\n" " -q quiet mode, don't display status\n" " -r replace the output file if it exists\n" "%s -blks n size of output file\n" msgstr "" #: dasdcopy.c:629 #, c-format msgid "" "usage: %s [-options] ifile [sf=sfile] ofile\n" "\n" " copy a dasd file to another dasd file\n" "\n" " ifile -- input dasd file\n" " sfile -- input shadow file [optional]\n" " ofile -- output dasd file\n" "\n" " options:\n" " -v display program version and quit\n" " -h display this help and quit\n" " -q quiet mode, don't display status\n" " -r replace the output file if it exists\n" "%s%s -0 don't compress output\n" " -blks n size of output fba file\n" " -cyls n size of output ckd file\n" " -a output ckd file will have alt cyls\n" "%s even if it exceeds 2G in size\n" " -o type output file type (CKD, CCKD, FBA, CFBA)\n" msgstr "" #: dasdcopy.c:662 msgid " -bz2 compress output using bzip2\n" msgstr "" #: dasdcopy.c:667 msgid " -lfs output ckd file will be a single file\n" msgstr "" #: dasdinit.c:297 #, c-format msgid "HHCDI001I DASD initialization successfully completed.\n" msgstr "" #: dasdisup.c:252 #, fuzzy, c-format msgid "HHCDS003E Directory block byte count is invalid\n" msgstr "HHC351I Bestandsnaam niet opgegeven of ongeldig\n" #: dasdisup.c:297 #, fuzzy, c-format msgid "HHCDS018I %s %s skipped\n" msgstr "HHC406I Fout %2$s bij zoeken in bestand \"%1$s\"\n" #: dasdisup.c:310 #, c-format msgid "HHCDS004E Number of members exceeds MAX_MEMBERS\n" msgstr "" #: dasdisup.c:319 #, c-format msgid "HHCDS005E Member %s TTR count is zero\n" msgstr "" #: dasdisup.c:348 #, c-format msgid "HHCDS006W Member %s is not single text record\n" msgstr "" #: dasdisup.c:357 #, c-format msgid "HHCDS007W Member %s size %4.4X exceeds X'7F8' bytes\n" msgstr "" #: dasdisup.c:366 #, c-format msgid "HHCDS008W Member %s size %4.4X is not a multiple of 8\n" msgstr "" #: dasdisup.c:420 #, c-format msgid "HHCDS009I Alias %s skipped\n" msgstr "" #: dasdisup.c:427 #, c-format msgid "HHCDS010I Member %s skipped\n" msgstr "" #: dasdisup.c:435 #, c-format msgid "HHCDS011E Member %s has multiple text records\n" msgstr "" #: dasdisup.c:447 #, fuzzy, c-format msgid "HHCDS012E Member %s has invalid TTR %4.4X%2.2X\n" msgstr "HHC351I Bestandsnaam niet opgegeven of ongeldig\n" #: dasdisup.c:453 #, c-format msgid "" "HHCDS013I Processing member %s text record TTR=%4.4X%2.2X CCHHR=%4.4X%4.4X%" "2.2X\n" msgstr "" #: dasdisup.c:463 #, fuzzy, c-format msgid "HHCDS014E Member %s error reading TTR %4.4X%2.2X\n" msgstr "HHC409I Fout %2$s bij lezen van bestand \"%1$s\"\n" #: dasdisup.c:472 #, c-format msgid "" "HHCDS015E Member %s TTR %4.4X%2.2X text record length %4.4X is not valid\n" msgstr "" #: dasdisup.c:482 #, c-format msgid "" "HHCDS016E Member %s TTR %4.4X%2.2X text record length %4.4X does not match " "length %4.4X in directory\n" msgstr "" #: dasdisup.c:527 #, c-format msgid "HHCDS017E Member %s TTR %4.4X%2.2X XCTL table improperly terminated\n" msgstr "" #: dasdisup.c:549 #, c-format msgid "HHCDS019I In member %s: %s TTRL=%2.2X%2.2X%2.2X%2.2X" msgstr "" #: dasdisup.c:667 #, fuzzy, c-format msgid "HHCDS001E Cannot obtain storage for member array: %s\n" msgstr "Kann %s nicht öffnen: %s\n" #: dasdisup.c:719 #, fuzzy, c-format msgid "HHCDS002I End of directory: %d members selected\n" msgstr "HHC403I Niet genoeg geheugen\n" #: dasdutil.c:221 #, fuzzy, c-format msgid "HHCDU001I Updating cyl %d head %d\n" msgstr "HHC409I Fout %2$s bij lezen van bestand \"%1$s\"\n" #: dasdutil.c:227 #, fuzzy, c-format msgid "HHCDU002E %s write track error: stat=%2.2X\n" msgstr "%d Bytes gelesen von %s\n" #: dasdutil.c:234 #, fuzzy, c-format msgid "HHCDU003I Reading cyl %d head %d\n" msgstr "HHC409I Fout %2$s bij lezen van bestand \"%1$s\"\n" #: dasdutil.c:240 #, fuzzy, c-format msgid "HHCDU004E %s read track error: stat=%2.2X\n" msgstr "%d Bytes gelesen von %s\n" #: dasdutil.c:361 #, c-format msgid "HHCDU005I Searching extent %d begin (%d,%d) end (%d,%d)\n" msgstr "" #: dasdutil.c:433 #, c-format msgid "HHCDU006I Searching extent %d begin (%d,%d) end (%d,%d)\n" msgstr "" #: dasdutil.c:494 #, fuzzy, c-format msgid "HHCDU007E Track %d not found in extent table\n" msgstr "HHC420I %s (%s) afgesloten van apparaat %4.4X (%s)\n" #: dasdutil.c:535 #, fuzzy, c-format msgid "HHCDU008E Cannot obtain storage for device descriptor buffer: %s\n" msgstr "Kann %s nicht öffnen: %s\n" #: dasdutil.c:596 #, fuzzy, c-format msgid "HHCDU009E Cannot open %s: %s\n" msgstr "Kann %s nicht öffnen: %s\n" #: dasdutil.c:611 #, fuzzy, c-format msgid "HHCDU010E %s read error: %s\n" msgstr "%d Bytes gelesen von %s\n" #: dasdutil.c:622 #, fuzzy, c-format msgid "HHCDU011E %s CKD header invalid\n" msgstr "%d Bytes gelesen von %s\n" #: dasdutil.c:631 #, c-format msgid "HHCDU012E DASD table entry not found for devtype 0x%2.2X\n" msgstr "" #: dasdutil.c:661 #, fuzzy, c-format msgid "HHCDU013E CKD initialization failed for %s\n" msgstr "CCW Ablaufverfolgung ist %s für %4.4X\n" #: dasdutil.c:683 #, fuzzy, c-format msgid "HHCDU014I %s heads=%d trklen=%d\n" msgstr "%d Bytes gelesen von %s\n" #: dasdutil.c:717 #, fuzzy, c-format msgid "HHCDU015I Updating cyl %d head %d\n" msgstr "HHC409I Fout %2$s bij lezen van bestand \"%1$s\"\n" #: dasdutil.c:723 #, fuzzy, c-format msgid "HHCDU016E %s write track error: stat=%2.2X\n" msgstr "%d Bytes gelesen von %s\n" #: dasdutil.c:768 #, fuzzy, c-format msgid "HHCDU017E Cannot obtain storage for device descriptor buffer: %s\n" msgstr "Kann %s nicht öffnen: %s\n" #: dasdutil.c:784 #, c-format msgid "HHCDU018E DASD table entry not found for devtype 0x%2.2X\n" msgstr "" #: dasdutil.c:811 #, fuzzy, c-format msgid "HHCDU019E FBA initialization failed for %s\n" msgstr "CCW Ablaufverfolgung ist %s für %4.4X\n" #: dasdutil.c:827 #, fuzzy, c-format msgid "HHCDU020I %s sectors=%d size=%d\n" msgstr "%d Bytes gelesen von %s\n" #: dasdutil.c:873 #, fuzzy, c-format msgid "HHCDU021E VOL1 record not found\n" msgstr "Kann %s nicht öffnen: %s\n" #: dasdutil.c:886 #, c-format msgid "HHCDU022I VOLSER=%s VTOC=%4.4X%4.4X%2.2X\n" msgstr "" #: dasdutil.c:896 #, c-format msgid "HHCDU023E F4DSCB record not found\n" msgstr "" #: dasdutil.c:903 #, c-format msgid "HHCDU023I VTOC start %2.2X%2.2X%2.2X%2.2X end %2.2X%2.2X%2.2X%2.2X\n" msgstr "" #: dasdutil.c:919 #, c-format msgid "HHCDU024E Dataset %s not found in VTOC\n" msgstr "" #: dasdutil.c:927 #, c-format msgid "HHCDU025I DSNAME=%s F1DSCB CCHHR=%4.4X%4.4X%2.2X\n" msgstr "" #: dasdutil.c:937 #, c-format msgid "HHCDU026E F1DSCB record not found\n" msgstr "" #: dasdutil.c:959 #, c-format msgid "HHCDU027E F3DSCB record not found\n" msgstr "" #: dasdutil.c:1180 #, fuzzy, c-format msgid "HHCDU028E device type %4.4X not found in dasd table\n" msgstr "HHC420I %s (%s) afgesloten van apparaat %4.4X (%s)\n" #: dasdutil.c:1217 #, fuzzy, c-format msgid "HHCDU028E %s open error: %s\n" msgstr "HHC423I Fout %2$s bij openen bestand \"%1$s\"\n" #: dasdutil.c:1245 #, fuzzy, c-format msgid "HHCDU029E %s device header write error: %s\n" msgstr "%d Bytes gelesen von %s\n" #: dasdutil.c:1274 #, fuzzy, c-format msgid "HHCDU030E %s compressed device header write error: %s\n" msgstr "%d Bytes gelesen von %s\n" #: dasdutil.c:1284 #, fuzzy, c-format msgid "HHCDU031E Cannot obtain l1tab buffer: %s\n" msgstr "Kann %s nicht öffnen: %s\n" #: dasdutil.c:1294 #, fuzzy, c-format msgid "HHCDU032E %s primary lookup table write error: %s\n" msgstr "HHC423I Fout %2$s bij schrijven naar bestand \"%1$s\"\n" #: dasdutil.c:1307 #, fuzzy, c-format msgid "HHCDU033E %s secondary lookup table write error: %s\n" msgstr "HHC423I Fout %2$s bij schrijven naar bestand \"%1$s\"\n" #: dasdutil.c:1597 #, fuzzy, c-format msgid "HHCDU035E %s cylinder %u head %u write error: %s\n" msgstr "%d Bytes gelesen von %s\n" #: dasdutil.c:1629 #, fuzzy, c-format msgid "HHCDU036E %s compressed device header lseek error: %s\n" msgstr "%d Bytes gelesen von %s\n" #: dasdutil.c:1637 #, fuzzy, c-format msgid "HHCDU037E %s compressed device header write error: %s\n" msgstr "%d Bytes gelesen von %s\n" #: dasdutil.c:1647 #, fuzzy, c-format msgid "HHCDU038E %s secondary lookup table lseek error: %s\n" msgstr "HHC409I Fout %2$s bij lezen van bestand \"%1$s\"\n" #: dasdutil.c:1655 #, fuzzy, c-format msgid "HHCDU039E %s secondary lookup table write error: %s\n" msgstr "HHC423I Fout %2$s bij schrijven naar bestand \"%1$s\"\n" #: dasdutil.c:1670 #, fuzzy, c-format msgid "HHCDU040E %s close error: %s\n" msgstr "HHC423I Fout %2$s bij openen bestand \"%1$s\"\n" #: dasdutil.c:1677 #, c-format msgid "HHCDU041I %u cylinders successfully written to file %s\n" msgstr "" #: dasdutil.c:1749 #, c-format msgid "HHCDU042E Cylinder count %u is outside range %u-%u\n" msgstr "" #: dasdutil.c:1758 #, fuzzy, c-format msgid "HHCDU043E Cannot obtain track buffer: %s\n" msgstr "Kann %s nicht öffnen: %s\n" #: dasdutil.c:1765 #, c-format msgid "" "HHCDU044I Creating %4.4X volume %s: %u cyls, %u trks/cyl, %u bytes/track\n" msgstr "" #: dasdutil.c:1874 #, c-format msgid "HHCDU045E Sector count %u is outside range %u-%u\n" msgstr "" #: dasdutil.c:1883 #, fuzzy, c-format msgid "HHCDU046E Cannot obtain sector buffer: %s\n" msgstr "Kann %s nicht öffnen: %s\n" #: dasdutil.c:1890 #, c-format msgid "HHCDU047I Creating %4.4X volume %s: %u sectors, %u bytes/sector\n" msgstr "" #: dasdutil.c:1903 #, fuzzy, c-format msgid "HHCDU048I %s open error: %s\n" msgstr "HHC423I Fout %2$s bij openen bestand \"%1$s\"\n" #: dasdutil.c:1915 #, fuzzy, c-format msgid "HHCDU049E %s dasdcopy ftruncate error: %s\n" msgstr "%d Bytes gelesen von %s\n" #: dasdutil.c:1950 #, fuzzy, c-format msgid "HHCDU050E %s sector %u write error: %s\n" msgstr "%d Bytes gelesen von %s\n" #: dasdutil.c:1962 #, fuzzy, c-format msgid "HHCDU051E %s close error: %s\n" msgstr "HHC423I Fout %2$s bij openen bestand \"%1$s\"\n" #: dasdutil.c:1972 #, fuzzy, c-format msgid "HHCDU052I %u sectors successfully written to file %s\n" msgstr "Modus umgeschaltef auf %s\n" #: dasdutil.c:2019 #, fuzzy msgid "HHCDU053E File size too large: %" msgstr "HHC401I Bestandsnaam \"%2$s\" te lang (maximum=%1$ud)\n" #: dasdutil.c:2033 #, fuzzy, c-format msgid "HHCDU054E %s open error: %s\n" msgstr "HHC423I Fout %2$s bij openen bestand \"%1$s\"\n" #: dasdutil.c:2040 #, c-format msgid "" "HHCDU055I Creating %4.4X compressed volume %s: %u sectors, %u bytes/sector\n" msgstr "" #: dasdutil.c:2050 #, fuzzy, c-format msgid "HHCDU056E %s devhdr write error: %s\n" msgstr "%d Bytes gelesen von %s\n" #: dasdutil.c:2073 #, fuzzy, c-format msgid "HHCDU057E %s cdevhdr write error: %s\n" msgstr "%d Bytes gelesen von %s\n" #: dasdutil.c:2085 #, fuzzy, c-format msgid "HHCDU058E %s l1tab write error: %s\n" msgstr "%d Bytes gelesen von %s\n" #: dasdutil.c:2097 #, fuzzy, c-format msgid "HHCDU059E %s l2tab write error: %s\n" msgstr "%d Bytes gelesen von %s\n" #: dasdutil.c:2119 #, fuzzy, c-format msgid "HHCDU060E %s block header write error: %s\n" msgstr "%d Bytes gelesen von %s\n" #: dasdutil.c:2126 #, fuzzy, c-format msgid "HHCDU061E %s block write error: %s\n" msgstr "%d Bytes gelesen von %s\n" #: dasdutil.c:2141 #, fuzzy, c-format msgid "HHCDU062E %s block write error: %s\n" msgstr "%d Bytes gelesen von %s\n" #: dasdutil.c:2155 #, fuzzy, c-format msgid "HHCDU063E %s cdevhdr lseek error: %s\n" msgstr "%d Bytes gelesen von %s\n" #: dasdutil.c:2162 #, fuzzy, c-format msgid "HHCDU064E %s cdevhdr rewrite error: %s\n" msgstr "%d Bytes gelesen von %s\n" #: dasdutil.c:2171 #, fuzzy, c-format msgid "HHCDU065E %s l2tab lseek error: %s\n" msgstr "%d Bytes gelesen von %s\n" #: dasdutil.c:2178 #, fuzzy, c-format msgid "HHCDU066E %s l2tab rewrite error: %s\n" msgstr "%d Bytes gelesen von %s\n" #: dasdutil.c:2187 #, fuzzy, c-format msgid "HHCDU067E %s close error: %s\n" msgstr "%d Bytes gelesen von %s\n" #: dasdutil.c:2194 #, c-format msgid "HHCDU068I %u sectors successfully written to file %s\n" msgstr "" #: dyngui.c:270 #, fuzzy, c-format msgid "HHCDG003S select failed on input stream: %s\n" msgstr "HHC760I %4.4X create_thread fout: %s" #: dyngui.c:308 #, fuzzy, c-format msgid "HHCDG004S read failed on input stream: %s\n" msgstr "HHC406I Fout %2$s bij zoeken in bestand \"%1$s\"\n" #: dyngui.c:1655 dyngui.c:1758 #, fuzzy, c-format msgid "HHCDG005E Device query buffer overflow! (device=%4.4X)\n" msgstr "CCW Ablaufverfolgung ist %s für %4.4X\n" #: dyngui.c:1908 #, fuzzy, c-format msgid "HHCDG006S malloc pszInputBuff failed: %s\n" msgstr "HHC406I Fout %2$s bij zoeken in bestand \"%1$s\"\n" #: dyngui.c:1921 #, fuzzy, c-format msgid "HHCDG007S malloc pszCommandBuff failed: %s\n" msgstr "HHC406I Fout %2$s bij zoeken in bestand \"%1$s\"\n" #: dyngui.c:1956 msgid "HHCDG001I dyngui.dll initiated\n" msgstr "" #: dyngui.c:1959 msgid "HHCDG002I dyngui.dll terminated\n" msgstr "" #: ecpsvm.c:259 ecpsvm.c:264 ecpsvm.c:281 ecpsvm.c:303 ecpsvm.c:304 #: ecpsvm.c:305 ecpsvm.c:306 msgid "HHCEV300D : SASSIST " msgstr "" #: ecpsvm.c:271 msgid "HHCEV300D : EVMA Disabled by guest\n" msgstr "" #: ecpsvm.c:324 ecpsvm.c:330 msgid "HHCEV300D : CPASSTS " msgstr "" #: ecpsvm.c:338 #, fuzzy msgid "HHCEV300D : " msgstr "HHC406I Fout %2$s bij zoeken in bestand \"%1$s\"\n" #: ecpsvm.c:407 msgid "HHCEV300D : LKPG coreptr = " msgstr "" #: ecpsvm.c:410 #, c-format msgid "HHCEV300D : LKPG corete = %6.6X\n" msgstr "" #: ecpsvm.c:424 #, c-format msgid "HHCEV300D : LKPG Page locked. Count = %6.6X\n" msgstr "" #: ecpsvm.c:441 #, c-format msgid "HHCEV300D : LKPG PAGE=%6.6X, PTRPL=%6.6X\n" msgstr "" #: ecpsvm.c:468 #, c-format msgid "HHCEV300D : ULKPG PAGE=%6.6X, PTRPL=%6.6X\n" msgstr "" #: ecpsvm.c:474 #, c-format msgid "HHCEV300D : ULKPG Page beyond core size of %6.6X\n" msgstr "" #: ecpsvm.c:486 msgid "HHCEV300D : ULKPG Attempting to unlock page that is not locked\n" msgstr "" #: ecpsvm.c:493 msgid "HHCEV300D : ULKPG now unlocked\n" msgstr "" #: ecpsvm.c:497 #, c-format msgid "HHCEV300D : ULKPG Page still locked. Count = %6.6X\n" msgstr "" #: ecpsvm.c:533 #, c-format msgid "HHCEV300D SCNVU Virtual Device %4.4X has no VCHAN block\n" msgstr "" #: ecpsvm.c:541 #, c-format msgid "HHCEV300D SCNVU Virtual Device %4.4X has no VCU block\n" msgstr "" #: ecpsvm.c:549 #, c-format msgid "HHCEV300D SCNVU Virtual Device %4.4X has no VDEV block\n" msgstr "" #: ecpsvm.c:553 #, c-format msgid "HHCEV300D SCNVU %4.4X : VCH = %8.8X, VCU = %8.8X, VDEV = %8.8X\n" msgstr "" #: ecpsvm.c:909 msgid "HHCEV004W : Abend condition detected in DISP2 instr\n" msgstr "" #: ecpsvm.c:1100 #, c-format msgid "HHCPEV300D : DISP2 - Next Instruction : %2.2X\n" msgstr "" #: ecpsvm.c:1163 #, c-format msgid "HHCEV300D : Tranbring : LRA cc = %d\n" msgstr "" #: ecpsvm.c:1172 #, c-format msgid "HHCEV300D : Page not shared - OK %d\n" msgstr "" #: ecpsvm.c:1178 msgid "HHCEV300D : Checking 2K Storage keys @" msgstr "" #: ecpsvm.c:1183 msgid "HHCEV300D : Checking 4K Storage keys @" msgstr "" #: ecpsvm.c:1187 msgid "HHCEV300D : Page shared and changed\n" msgstr "" #: ecpsvm.c:1190 msgid "HHCEV300D : Page shared but not changed\n" msgstr "" #: ecpsvm.c:1209 msgid "HHCEV300D : TRANBRNG\n" msgstr "" #: ecpsvm.c:1213 msgid "HHCEV300D : TRANBRNG - Back to CP\n" msgstr "" #: ecpsvm.c:1231 msgid "HHCEV300D : TRANLOCK\n" msgstr "" #: ecpsvm.c:1235 msgid "HHCEV300D : TRANLOCK - Back to CP\n" msgstr "" #: ecpsvm.c:1748 #, c-format msgid "HHCEV300D : ECPS:VM SCNRU called; RDEV=%4.4X ARIOCT=%6.6X\n" msgstr "" #: ecpsvm.c:1756 #, c-format msgid "HHCEV300D : ECPS:VM SCNRU : RCH IX = %x\n" msgstr "" #: ecpsvm.c:1798 #, c-format msgid "HHCEV300D : ECPS:VM SCNRU : RCU IX = %x\n" msgstr "" #: ecpsvm.c:1818 #, c-format msgid "HHCEV300D : ECPS:VM SCNRU : RDV IX = %x\n" msgstr "" #: ecpsvm.c:1822 #, c-format msgid "HHCEV300D : ECPS:VM SCNRU : RCH = %6.6X, RCU = %6.6X, RDV = %6.6X\n" msgstr "" #: ecpsvm.c:1866 #, c-format msgid "HHCEV300D : ECPS:VM STORE LEVEL %d called\n" msgstr "" #: ecpsvm.c:1906 #, c-format msgid "HHCEV300D : ECPS:VM FREEX DW = %4.4X\n" msgstr "" #: ecpsvm.c:1911 #, c-format msgid "HHCEV300D : MAXSIZE ADDR = %6.6X, SUBPOOL INDEX TABLE = %6.6X\n" msgstr "" #: ecpsvm.c:1918 msgid "HHCEV300D : FREEX request beyond subpool capacity\n" msgstr "" #: ecpsvm.c:1923 #, c-format msgid "HHCEV300D : Subpool index = %X\n" msgstr "" #: ecpsvm.c:1926 #, c-format msgid "HHCEV300D : Value in subpool table = %6.6X\n" msgstr "" #: ecpsvm.c:1934 #, c-format msgid "HHCEV300D : New Value in subpool table = %6.6X\n" msgstr "" #: ecpsvm.c:1964 #, c-format msgid "HHCEV300D : X fretx called AREA=%6.6X, DW=%4.4X\n" msgstr "" #: ecpsvm.c:1967 msgid "HHCEV300D : ECPS:VM Cannot FRETX : DWORDS = 0\n" msgstr "" #: ecpsvm.c:1973 #, c-format msgid "HHCEV300D : ECPS:VM Cannot FRETX : DWORDS = %d > MAXDW %d\n" msgstr "" #: ecpsvm.c:1980 msgid "HHCEV300D : ECPS:VM Cannot FRETX : Area not in Core Free area\n" msgstr "" #: ecpsvm.c:1985 msgid "HHCEV300D : ECPS:VM Cannot FRETX : Area flag != 0x02\n" msgstr "" #: ecpsvm.c:1992 msgid "" "HHCEV300D : ECPS:VM Cannot FRETX : fretted block already on subpool chain\n" msgstr "" #: ecpsvm.c:2062 msgid "HHCEV300D : New and Old PSW have a EC/BC transition\n" msgstr "" #: ecpsvm.c:2070 msgid "HHCEV300D : New PSW Enables DAT or PER\n" msgstr "" #: ecpsvm.c:2081 msgid "HHCEV300D : New PSW Enables interrupts and MICPEND (EC)\n" msgstr "" #: ecpsvm.c:2089 msgid "HHCEV300D : New PSW Enables interrupts and MICPEND (BC)\n" msgstr "" #: ecpsvm.c:2096 msgid "HHCEV300D : New PSW is a WAIT PSW\n" msgstr "" #: ecpsvm.c:2103 msgid "HHCEV300D : New PSW sysmask incorrect\n" msgstr "" #: ecpsvm.c:2109 msgid "HHCEV300D : New PSW has ODD IA\n" msgstr "" #: ecpsvm.c:2596 ecpsvm.c:2613 #, c-format msgid "HHCEV001I | %-9s | %8d | %8d | %3d%% |\n" msgstr "" #: ecpsvm.c:2623 #, c-format msgid "HHCEV004I * : Unsupported, - : Disabled, %% - Debug\n" msgstr "" #: ecpsvm.c:2627 #, c-format msgid "HHCEV005I %d Entr%s not shown (never invoked)\n" msgstr "" #: ecpsvm.c:2633 msgid "HHCEV006I 1 call was made to an unsupported function\n" msgstr "" #: ecpsvm.c:2637 #, c-format msgid "HHCEV006I %d calls where made to unsupported functions\n" msgstr "" #: ecpsvm.c:2652 ecpsvm.c:2661 #, c-format msgid "HHCEV002I | %-9s | %-8s | %-8s | %-5s |\n" msgstr "" #: ecpsvm.c:2716 #, c-format msgid "HHCEV015I ECPS:VM %s feature %s %s\n" msgstr "" #: ecpsvm.c:2721 #, c-format msgid "HHCEV015I ECPS:VM %s feature %s Debug %s\n" msgstr "" #: ecpsvm.c:2726 #, c-format msgid "HHCEV016I All ECPS:VM %s features %s\n" msgstr "" #: ecpsvm.c:2730 #, c-format msgid "HHCEV016I All ECPS:VM %s features Debug %s\n" msgstr "" #: ecpsvm.c:2758 #, c-format msgid "HHCEV013I ECPS:VM Global Debug %s\n" msgstr "" #: ecpsvm.c:2786 #, c-format msgid "HHCEV014I ECPS:VM %s feature %s %s\n" msgstr "" #: ecpsvm.c:2791 #, c-format msgid "HHCEV014I ECPS:VM %s feature %s Debug %s\n" msgstr "" #: ecpsvm.c:2796 #, c-format msgid "HHCEV014I Unknown ECPS:VM feature %s; Ignored\n" msgstr "" #: ecpsvm.c:2823 ecpsvm.c:2827 #, c-format msgid "HHCEV016I Current reported ECPS:VM Level is %d\n" msgstr "" #: ecpsvm.c:2828 msgid "HHCEV017I But ECPS:VM is currently disabled\n" msgstr "" #: ecpsvm.c:2833 #, c-format msgid "HHCEV016I Level reported to guest program is now %d\n" msgstr "" #: ecpsvm.c:2838 #, c-format msgid "HHCEV017W WARNING ! current level (%d) is not supported\n" msgstr "" #: ecpsvm.c:2839 msgid "HHCEV018W WARNING ! Unpredictable results may occur\n" msgstr "" #: ecpsvm.c:2840 msgid "HHCEV019I The microcode support level is 20\n" msgstr "" #: ecpsvm.c:2867 #, fuzzy, c-format msgid "HHCEV010I : %s : %s\n" msgstr "HHC406I Fout %2$s bij zoeken in bestand \"%1$s\"\n" #: ecpsvm.c:2883 #, c-format msgid "HHCEV011E Unknown subcommand %s - valid subcommands are :\n" msgstr "" #: ecpsvm.c:2887 #, c-format msgid "HHCEV012I : %s : %s" msgstr "" #: ecpsvm.c:2913 msgid "HHCEV011I ECPS:VM Command processor invoked\n" msgstr "" #: ecpsvm.c:2916 msgid "" "HHCEV008E NO EVM subcommand. Type \"evm help\" for a list of valid " "subcommands\n" msgstr "" #: ecpsvm.c:2922 #, c-format msgid "HHCEV008E Unknown EVM subcommand %s\n" msgstr "" #: ecpsvm.c:2926 msgid "HHCEV011I ECPS:VM Command processor complete\n" msgstr "" #: external.c:173 msgid "HHCCP023I External interrupt: Interrupt key\n" msgstr "" #: external.c:284 msgid "HHCCP024I External interrupt: Clock comparator\n" msgstr "" #: external.c:295 msgid "HHCCP025I External interrupt: CPU timer=%16.16" msgstr "" #: external.c:311 msgid "HHCCP026I External interrupt: Interval timer\n" msgstr "" #: fbadasd.c:91 #, fuzzy msgid "HHCDA056E File name missing or invalid\n" msgstr "HHC351I Bestandsnaam niet opgegeven of ongeldig\n" #: fbadasd.c:108 #, fuzzy, c-format msgid "HHCDA057E %4.4X:File not found or invalid\n" msgstr "HHC351I Bestandsnaam niet opgegeven of ongeldig\n" #: fbadasd.c:124 #, fuzzy, c-format msgid "HHCDA058E File %s open error: %s\n" msgstr "HHC423I Fout %2$s bij openen bestand \"%1$s\"\n" #: fbadasd.c:136 #, fuzzy, c-format msgid "HHCDA059E Read error in file %s: %s\n" msgstr "HHC406I Fout %2$s bij zoeken in bestand \"%1$s\"\n" #: fbadasd.c:139 #, fuzzy, c-format msgid "HHCDA060E Unexpected end of file in %s\n" msgstr "HHC40I Onverwacht einde van bestand \"%s\"\n" #: fbadasd.c:157 #, fuzzy, c-format msgid "HHCDA061E Read error in file %s: %s\n" msgstr "HHC406I Fout %2$s bij zoeken in bestand \"%1$s\"\n" #: fbadasd.c:160 #, fuzzy, c-format msgid "HHCDA062E Unexpected end of file in %s\n" msgstr "HHC40I Onverwacht einde van bestand \"%s\"\n" #: fbadasd.c:213 #, fuzzy, c-format msgid "HHCDA063E parameter %d is invalid: %s\n" msgstr "HHC351I Bestandsnaam niet opgegeven of ongeldig\n" #: fbadasd.c:226 #, fuzzy, c-format msgid "HHCDA064E File %s fstat error: %s\n" msgstr "%d Bytes gelesen von %s\n" #: fbadasd.c:238 #, fuzzy, c-format msgid "HHCDA082E File %s IOCTL BLKGETSIZE error: %s\n" msgstr "HHC423I Fout %2$s bij openen bestand \"%1$s\"\n" #: fbadasd.c:264 #, fuzzy, c-format msgid "HHCDA065E Invalid device origin block number %s\n" msgstr "Ongeldig apparaat nummer\n" #: fbadasd.c:280 #, fuzzy, c-format msgid "HHCDA066E Invalid device block count %s\n" msgstr "Ongeldige waarde: %s\n" #: fbadasd.c:291 #, fuzzy, c-format msgid "HHCDA067I %s origin=%lld blks=%d\n" msgstr "%d Bytes gelesen von %s\n" #: fbadasd.c:301 #, fuzzy, c-format msgid "HHCDA068E %4.4X device type %4.4X not found in dasd table\n" msgstr "HHC420I %s (%s) afgesloten van apparaat %4.4X (%s)\n" #: fbadasd.c:526 #, fuzzy, c-format msgid "HHCDA069E error writing blkgrp %d: lseek error: %s\n" msgstr "HHC423I Fout %2$s bij schrijven naar bestand \"%1$s\"\n" #: fbadasd.c:544 #, fuzzy, c-format msgid "HHCDA070E error writing blkgrp %d: write error: %s\n" msgstr "HHC423I Fout %2$s bij schrijven naar bestand \"%1$s\"\n" #: fbadasd.c:585 #, c-format msgid "HHCDA071I read blkgrp %d cache hit, using cache[%d]\n" msgstr "" #: fbadasd.c:610 #, c-format msgid "HHCDA072I read blkgrp %d no available cache entry, waiting\n" msgstr "" #: fbadasd.c:618 #, c-format msgid "HHCDA073I read blkgrp %d cache miss, using cache[%d]\n" msgstr "" #: fbadasd.c:634 #, fuzzy msgid "HHCDA074I read blkgrp %d offset %" msgstr "HHC409I Fout %2$s bij lezen van bestand \"%1$s\"\n" #: fbadasd.c:642 #, fuzzy, c-format msgid "HHCDA075E error reading blkgrp %d: lseek error: %s\n" msgstr "HHC409I Fout %2$s bij lezen van bestand \"%1$s\"\n" #: fbadasd.c:657 #, fuzzy, c-format msgid "HHCDA076E error reading blkgrp %d: read error: %s\n" msgstr "HHC409I Fout %2$s bij lezen van bestand \"%1$s\"\n" #: fbadasd.c:1085 msgid "HHCDA077I Positioning to %8.8" msgstr "" #: fbadasd.c:1103 #, c-format msgid "HHCDA078E define extent data too short: %d bytes\n" msgstr "" #: fbadasd.c:1113 msgid "HHCDA079E second define extent in chain\n" msgstr "" #: fbadasd.c:1124 #, fuzzy, c-format msgid "HHCDA080E invalid file mask %2.2X\n" msgstr "Ongeldig apparaat nummer\n" #: fbadasd.c:1161 #, fuzzy, c-format msgid "HHCDA081E invalid extent: first block %d, last block %d,\n" msgstr "HHC422I Optie %s niet geldig\n" #: fbadasd.c:1163 #, c-format msgid " numblks %d, device size %d\n" msgstr " Blöcke: %d, Gesamtgröße %d\n" #: fbadasd.c:1435 #, c-format msgid "HHCDA901E %4.4x FBA origin mismatch: %d, expected %d,\n" msgstr "" #: fbadasd.c:1444 #, c-format msgid "HHCDA902E %4.4x FBA numblk mismatch: %d, expected %d,\n" msgstr "" #: fbadasd.c:1474 #, c-format msgid "HHCDA903E %4.4x FBA blksiz mismatch: %d, expected %d,\n" msgstr "" #: general1.c:3704 msgid "MVCL destructive overlap: " msgstr "" #: hdl.c:138 #, fuzzy, c-format msgid "HHCHD018I Loadable module directory is %s\n" msgstr "Ongeldige waarde: %s\n" #: hdl.c:411 #, c-format msgid "HHCHD010I Dependency check failed for %s, version(%s) expected(%s)\n" msgstr "" #: hdl.c:418 #, c-format msgid "HHCHD011I Dependency check failed for %s, size(%d) expected(%d)\n" msgstr "" #: hdl.c:460 #, fuzzy, c-format msgid "HHCHD001E registration malloc failed for %s\n" msgstr "HHC406I Fout %2$s bij zoeken in bestand \"%1$s\"\n" #: hdl.c:588 hdl.c:792 #, fuzzy, c-format msgid "HHCHD007E unable to open DLL %s: %s\n" msgstr "Kann %s nicht öffnen: %s\n" #: hdl.c:598 hdl.c:802 #, fuzzy, c-format msgid "HHCHD013E No dependency section in %s: %s\n" msgstr "HHC423I Fout %2$s bij openen bestand \"%1$s\"\n" #: hdl.c:622 hdl.c:840 #, c-format msgid "HHCHD014E Dependency check failed for module %s\n" msgstr "" #: hdl.c:675 #, fuzzy, c-format msgid "HHCHD002E cannot allocate memory for DLL descriptor: %s\n" msgstr "Kann %s nicht öffnen: %s\n" #: hdl.c:690 #, fuzzy, c-format msgid "HHCHD003E unable to open hercules as DLL: %s\n" msgstr "HHC402I Fout %2$s bij benaderen bestand \"%1$s\"\n" #: hdl.c:699 #, fuzzy, c-format msgid "HHCHD012E No dependency section in %s: %s\n" msgstr "HHC423I Fout %2$s bij openen bestand \"%1$s\"\n" #: hdl.c:775 #, fuzzy, c-format msgid "HHCHD005E %s already loaded\n" msgstr "%d Bytes gelesen von %s\n" #: hdl.c:782 #, c-format msgid "HHCHD006S cannot allocate memory for DLL descriptor: %s\n" msgstr "" #: hdl.c:813 #, fuzzy, c-format msgid "HHCHD016E DLL %s is duplicate of %s\n" msgstr "HHC423I Fout %2$s bij openen bestand \"%1$s\"\n" #: hdl.c:907 #, c-format msgid "HHCHD015E Unloading of %s not allowed\n" msgstr "" #: hdl.c:917 #, fuzzy, c-format msgid "HHCHD008E Device %4.4X bound to %s\n" msgstr "HHC420I %s (%s) afgesloten van apparaat %4.4X (%s)\n" #: hdl.c:929 #, c-format msgid "HHCHD017E Unload of %s rejected by final section\n" msgstr "" #: hdl.c:989 #, fuzzy, c-format msgid "HHCHD009E %s not found\n" msgstr "HHC351I Bestandsnaam niet opgegeven of ongeldig\n" #: hercifc.c:66 #, c-format msgid "HHCIF001E %s: Must be called from within Hercules.\n" msgstr "" #: hercifc.c:77 #, fuzzy, c-format msgid "HHCIF002E %s: Cannot obtain socket: %s\n" msgstr "Kann %s nicht öffnen: %s\n" #: hercifc.c:94 #, fuzzy, c-format msgid "HHCIF003E %s: I/O error on read: %s.\n" msgstr "HHC419E Fout %2$s bij sluiten van bestand \"%1$s\"\n" #: hercifc.c:103 #, c-format msgid "HHCIF007E %s: Hercules disappeared!! .. exiting\n" msgstr "" #: hercifc.c:210 #, c-format msgid "HHCIF004W %s: Unknown request: %8.8lX.\n" msgstr "" #: hercifc.c:218 #, fuzzy, c-format msgid "HHCIF006I %s: Doing %s on %s\n" msgstr "HHC409I Fout %2$s bij lezen van bestand \"%1$s\"\n" #: hercifc.c:239 #, fuzzy, c-format msgid "HHCIF005E %s: ioctl error doing %s on %s: %d %s\n" msgstr "HHC409I Fout %2$s bij lezen van bestand \"%1$s\"\n" #: hostinfo.c:90 #, fuzzy, c-format msgid "Running on %s %s-%s.%s %s%s" msgstr "Draaiend op %s %s%s %s %s\n" #: hsccmd.c:158 #, fuzzy, c-format msgid "HHCPN181E Device number %d:%4.4X not found\n" msgstr "HHC351I Bestandsnaam niet opgegeven of ongeldig\n" #: hsccmd.c:164 #, fuzzy msgid "HHCPN031E Missing device number\n" msgstr "Geen apparaat nummer\n" #: hsccmd.c:181 msgid "Improper command format" msgstr "" #: hsccmd.c:190 #, c-format msgid "\"%s\": invalid maxrates interval" msgstr "" #: hsccmd.c:196 #, c-format msgid "Maxrates interval set to %d minutes.\n" msgstr "" #: hsccmd.c:200 msgid "; enter \"help maxrates\" for help.\n" msgstr "" #: hsccmd.c:358 #, fuzzy msgid "HHCPN160E no argument\n" msgstr "Geen apparaat nummer\n" #: hsccmd.c:372 #, fuzzy, c-format msgid "HHCPN195I Log options:%s\n" msgstr "Kann %s nicht öffnen: %s\n" #: hsccmd.c:385 msgid "HHCPN197I Log option set: TIMESTAMP\n" msgstr "" #: hsccmd.c:392 msgid "HHCPN197I Log option set: NOTIMESTAMP\n" msgstr "" #: hsccmd.c:396 #, fuzzy, c-format msgid "HHCPN196E Invalid logopt value %s\n" msgstr "Ongeldige waarde: %s\n" #: hsccmd.c:462 #, fuzzy, c-format msgid "HHCPN017E Device %d:%4.4X is not a printer device\n" msgstr "HHC420I %s (%s) afgesloten van apparaat %4.4X (%s)\n" #: hsccmd.c:476 #, fuzzy, c-format msgid "HHCPN018I Printer %d:%4.4X started\n" msgstr "HHC420I %s (%s) afgesloten van apparaat %4.4X (%s)\n" #: hsccmd.c:478 #, fuzzy, c-format msgid "HHCPN019E Printer %d:%4.4X not started: busy or interrupt pending\n" msgstr "HHC420I %s (%s) afgesloten van apparaat %4.4X (%s)\n" #: hsccmd.c:481 #, fuzzy, c-format msgid "HHCPN020E Printer %d:%4.4X not started: attention request rejected\n" msgstr "HHC420I %s (%s) afgesloten van apparaat %4.4X (%s)\n" #: hsccmd.c:484 #, c-format msgid "HHCPN021E Printer %d:%4.4X not started: subchannel not enabled\n" msgstr "" #: hsccmd.c:565 #, fuzzy, c-format msgid "HHCPN024E Device %d:%4.4X is not a printer device\n" msgstr "HHC420I %s (%s) afgesloten van apparaat %4.4X (%s)\n" #: hsccmd.c:572 #, fuzzy, c-format msgid "HHCPN025I Printer %d:%4.4X stopped\n" msgstr "HHC420I %s (%s) afgesloten van apparaat %4.4X (%s)\n" #: hsccmd.c:666 #, fuzzy, c-format msgid "HHCPN152I CPU%4.4X online\n" msgstr "CPU%4.4X nicht konfiguriert\n" #: hsccmd.c:673 #, fuzzy, c-format msgid "HHCPN153I CPU%4.4X offline\n" msgstr "CPU%4.4X nicht konfiguriert\n" #: hsccmd.c:709 #, fuzzy, c-format msgid "HHCPN154I CPU%4.4X online\n" msgstr "CPU%4.4X nicht konfiguriert\n" #: hsccmd.c:716 #, fuzzy, c-format msgid "HHCPN155I CPU%4.4X offline\n" msgstr "CPU%4.4X nicht konfiguriert\n" #: hsccmd.c:741 msgid "HHCPN026W Ignored. (external GUI active)\n" msgstr "" #: hsccmd.c:746 #, c-format msgid "HHCPN027I Automatic refresh %s.\n" msgstr "" #: hsccmd.c:747 msgid "disabled" msgstr "" #: hsccmd.c:747 msgid "enabled" msgstr "" #: hsccmd.c:826 #, c-format msgid "HHCPN037I Timer update interval = %d microsecond(s)\n" msgstr "" #: hsccmd.c:868 hsccmd.c:1323 hsccmd.c:1487 hsccmd.c:1547 hsccmd.c:1575 #: hsccmd.c:1603 hsccmd.c:1631 hsccmd.c:1659 hsccmd.c:1690 hsccmd.c:1719 #: hsccmd.c:1756 hsccmd.c:1783 hsccmd.c:1810 hsccmd.c:3240 hsccmd.c:3388 #: hsccmd.c:3455 hsccmd.c:4851 hsccmd.c:4955 hsccmd.c:5048 hsccmd.c:5090 #, fuzzy, c-format msgid "HHCPN160W CPU%4.4X not configured\n" msgstr "CPU%4.4X nicht konfiguriert\n" #: hsccmd.c:903 msgid "HHCPN028I tod = %16.16" msgstr "" #: hsccmd.c:906 msgid " h/w = %16.16" msgstr "" #: hsccmd.c:918 msgid " off = %16.16" msgstr "" #: hsccmd.c:922 msgid " ckc = %16.16" msgstr "" #: hsccmd.c:926 msgid " cpt = %16.16" msgstr "" #: hsccmd.c:928 msgid " cpt = not decrementing\n" msgstr "" #: hsccmd.c:934 msgid " vtod = %16.16" msgstr "" #: hsccmd.c:946 msgid " voff = %16.16" msgstr "" #: hsccmd.c:950 msgid " vckc = %16.16" msgstr "" #: hsccmd.c:953 msgid " vcpt = %16.16" msgstr "" #: hsccmd.c:959 msgid " itm = %8.8" msgstr "" #: hsccmd.c:981 #, fuzzy, c-format msgid "HHCPN029E Invalid I/O delay value: %s\n" msgstr "Ongeldige waarde: %s\n" #: hsccmd.c:986 #, c-format msgid "HHCPN030I I/O delay = %d\n" msgstr "" #: hsccmd.c:1064 #, c-format msgid "HHCCF068E Invalid value: %s; Enter \"help scsimount\" for help.\n" msgstr "" #: hsccmd.c:1075 #, c-format msgid "SCSI auto-mount queries = every %d seconds (when needed)\n" msgstr "" #: hsccmd.c:1078 msgid "SCSI auto-mount queries are disabled.\n" msgstr "" #: hsccmd.c:1093 #, c-format msgid "SCSI auto-mount thread %s active for drive %u:%4.4X = %s.\n" msgstr "" #: hsccmd.c:1168 #, c-format msgid "" "\n" "%s\n" "HHCCF069I %s of %s-labeled volume \"%s\" pending for drive %u:%4.4X = %s\n" "%s\n" "\n" msgstr "" #: hsccmd.c:1182 #, c-format msgid "No mount/dismount requests pending for drive %u:%4.4X = %s.\n" msgstr "" #: hsccmd.c:1215 msgid "HHCPN186E cmd deprecated; try 'tt32' instead\n" msgstr "" #: hsccmd.c:1232 msgid "HHCPN188E Missing arguments; enter 'help tt32' for help.\n" msgstr "" #: hsccmd.c:1255 #, fuzzy, c-format msgid "HHCPN034E Device %d:%4.4X is not a CTCI or LCS device\n" msgstr "HHC420I %s (%s) afgesloten van apparaat %4.4X (%s)\n" #: hsccmd.c:1264 hsccmd.c:1278 hsccmd.c:1292 msgid "(error)\n" msgstr "" #: hsccmd.c:1274 msgid "HHCPN189I TT32 debug tracing messages enabled\n" msgstr "" #: hsccmd.c:1288 msgid "HHCPN189I TT32 debug tracing messages disabled\n" msgstr "" #: hsccmd.c:1298 #, fuzzy msgid "HHCPN187E Invalid argument\n" msgstr "HHC422I Optie %s niet geldig\n" #: hsccmd.c:1331 msgid "HHCPN035E store status rejected: CPU not stopped\n" msgstr "" #: hsccmd.c:1367 #, c-format msgid "HHCPN036I TOD clock drag factor = %lf\n" msgstr "" #: hsccmd.c:1399 #, c-format msgid "HHCPN037I Panel refresh rate = %d millisecond(s)\n" msgstr "" #: hsccmd.c:1417 hsccmd.c:1439 hsccmd.c:1460 msgid "HHCPN180E shell commands are disabled\n" msgstr "" #: hsccmd.c:1465 #, fuzzy msgid "HHCPN163E Invalid format. Command does not support any arguments.\n" msgstr "HHC422I Optie %s niet geldig\n" #: hsccmd.c:1502 msgid "HHCPN162E Invalid format. Enter \"help gpr\" for help.\n" msgstr "" #: hsccmd.c:1514 msgid "HHCPN162E Invalid format. .Enter \"help gpr\" for help.\n" msgstr "" #: hsccmd.c:1711 #, fuzzy msgid "HHCPN038I Restart key depressed\n" msgstr "Restart key ingedrukt\n" #: hsccmd.c:1845 hsccmd.c:1861 #, fuzzy msgid "HHCPN039E Invalid arguments\n" msgstr "HHC422I Optie %s niet geldig\n" #: hsccmd.c:1909 #, fuzzy, c-format msgid "HHCPN040I Instruction %s %s %s\n" msgstr "%sFehler beim Lesen der Instruktion\n" #: hsccmd.c:1910 msgid "tracing" msgstr "" #: hsccmd.c:1911 msgid "stepping" msgstr "" #: hsccmd.c:1911 msgid "break" msgstr "" #: hsccmd.c:1912 hsccmd.c:4840 msgid "on" msgstr "" #: hsccmd.c:1912 hsccmd.c:4843 msgid "off" msgstr "" #: hsccmd.c:1953 #, fuzzy, c-format msgid "HHCPN045I Device %4.4X attention request raised\n" msgstr "HHC420I %s (%s) afgesloten van apparaat %4.4X (%s)\n" #: hsccmd.c:1956 #, c-format msgid "HHCPN046E Device %4.4X busy or interrupt pending\n" msgstr "" #: hsccmd.c:1959 #, c-format msgid "HHCPN047E Device %4.4X attention request rejected\n" msgstr "" #: hsccmd.c:1962 #, c-format msgid "HHCPN048E Device %4.4X subchannel not enabled\n" msgstr "" #: hsccmd.c:1969 #, c-format msgid "HHCPN049W Are you sure you didn't mean 'ipl %4.4X' instead?\n" msgstr "" #: hsccmd.c:1988 #, fuzzy msgid "HHCPN050I Interrupt key depressed\n" msgstr "Restart key ingedrukt\n" #: hsccmd.c:2011 #, c-format msgid "HHCPN051I LOADPARM=%s\n" msgstr "" #: hsccmd.c:2030 msgid "HHCPN053E System reset/clear rejected: All CPU's must be stopped\n" msgstr "" #: hsccmd.c:2078 msgid "HHCPN053E ipl rejected: All CPU's must be stopped\n" msgstr "" #: hsccmd.c:2106 hsccmd.c:2522 #, fuzzy, c-format msgid "HHCPN059E LCSS id %s is invalid\n" msgstr "HHC351I Bestandsnaam niet opgegeven of ongeldig\n" #: hsccmd.c:2143 #, fuzzy msgid "HHCPN054E Missing argument\n" msgstr "Geen apparaat nummer\n" #: hsccmd.c:2150 #, c-format msgid "HHCPN055E Target CPU %s is invalid\n" msgstr "" #: hsccmd.c:2237 hsccmd.c:2369 #, fuzzy, c-format msgid "HHCPN146E Work buffer malloc failed: %s\n" msgstr "HHC406I Fout %2$s bij zoeken in bestand \"%1$s\"\n" #: hsccmd.c:2295 msgid "open " msgstr "" #: hsccmd.c:2296 msgid "busy " msgstr "" #: hsccmd.c:2297 msgid "pending " msgstr "" #: hsccmd.c:2308 #, c-format msgid " (client %s (%s) connected)\n" msgstr " (verbunden mit %s (%s))\n" #: hsccmd.c:2314 msgid " (no one currently connected)\n" msgstr " (zur Zeit keine Verbindung)\n" #: hsccmd.c:2326 hsccmd.c:2475 #, c-format msgid "HHCPN147W Warning: not all devices shown (max %d)\n" msgstr "" #: hsccmd.c:2495 #, fuzzy msgid "HHCPN057E Missing argument(s)\n" msgstr "Geen apparaat nummer\n" #: hsccmd.c:2514 #, fuzzy, c-format msgid "HHCPN059E Device number %s is invalid\n" msgstr "HHC351I Bestandsnaam niet opgegeven of ongeldig\n" #: hsccmd.c:2532 #, fuzzy, c-format msgid "Device type %s is invalid\n" msgstr "HHC351I Bestandsnaam niet opgegeven of ongeldig\n" #: hsccmd.c:2580 #, fuzzy msgid "HHCPN062E Missing argument(s)\n" msgstr "Geen apparaat nummer\n" #: hsccmd.c:2596 msgid "" "HHCPN182E Device numbers can only be redefined within the same Logical " "channel subsystem\n" msgstr "" #: hsccmd.c:2616 #, fuzzy msgid "HHCPN065E Missing argument(s)\n" msgstr "Geen apparaat nummer\n" #: hsccmd.c:2644 #, c-format msgid "HHCPN066E Program interrupt number %s is invalid\n" msgstr "" #: hsccmd.c:2651 #, c-format msgid "HHCPN067E Program interrupt number out of range (%4.4X)\n" msgstr "" #: hsccmd.c:2683 #, c-format msgid "OSTAILOR %s\n" msgstr "" #: hsccmd.c:2771 #, c-format msgid "Unknown OS tailor specification %s\n" msgstr "" #: hsccmd.c:2846 #, fuzzy msgid "HHCPN072I %4.4X synchronous: %12" msgstr "%4.4X synchron: %12lld asynchron: %12lld\n" #: hsccmd.c:2857 msgid "HHCPN073I No synchronous I/O devices found\n" msgstr "" #: hsccmd.c:2859 #, fuzzy msgid "HHCPN074I TOTAL synchronous: %12" msgstr "%4.4X synchron: %12lld asynchron: %12lld\n" #: hsccmd.c:2898 #, fuzzy msgid "HHCPN075E Invalid max device threads value (must be -1 to n)\n" msgstr "Ongeldig apparaat nummer\n" #: hsccmd.c:2905 #, c-format msgid "" "HHCPN076I Max device threads: %d, current: %d, most: %d, waiting: %d, max " "exceeded: %d\n" msgstr "" #: hsccmd.c:2926 msgid "HHCPN077E Invalid max device threads value (must be -1 to n)\n" msgstr "" #: hsccmd.c:2940 #, c-format msgid "" "HHCPN078E Max device threads %d current %d most %d waiting %d total I/Os " "queued %d\n" msgstr "" #: hsccmd.c:2969 msgid "HHCPN091E Command must be 'sf+', 'sf-', 'sfc', or 'sfd'\n" msgstr "" #: hsccmd.c:2998 #, fuzzy msgid "HHCPN081E No cckd devices found\n" msgstr "%d Geräte bearbeitet\n" #: hsccmd.c:3011 #, fuzzy, c-format msgid "HHCPN084E Device number %d:%4.4X is not a cckd device\n" msgstr "HHC420I %s (%s) afgesloten van apparaat %4.4X (%s)\n" #: hsccmd.c:3028 msgid "HHCPN087E Operand must be `merge', `nomerge' or `force'\n" msgstr "" #: hsccmd.c:3038 #, fuzzy, c-format msgid "HHCPN089E Unexpected operand: %s\n" msgstr "Ongeldig operand: %s\n" #: hsccmd.c:3045 #, fuzzy, c-format msgid "HHCPN085I Processing device %d:%4.4X\n" msgstr "Geen apparaat nummer\n" #: hsccmd.c:3067 #, fuzzy, c-format msgid "HHCPN092I %d devices processed\n" msgstr "%d Geräte bearbeitet\n" #: hsccmd.c:3089 #, fuzzy msgid "HHCPN093E Missing argument(s)\n" msgstr "Geen apparaat nummer\n" #: hsccmd.c:3114 #, fuzzy, c-format msgid "HHCPN096E Device %d:%4.4X busy or interrupt pending\n" msgstr "HHC420I %s (%s) afgesloten van apparaat %4.4X (%s)\n" #: hsccmd.c:3130 #, c-format msgid "HHCPN183E Reinit rejected for drive %u:%4.4X; drive not empty\n" msgstr "" #: hsccmd.c:3170 #, fuzzy, c-format msgid "HHCPN097E Initialization failed for device %d:%4.4X\n" msgstr "CCW Ablaufverfolgung ist %s für %4.4X\n" #: hsccmd.c:3173 #, fuzzy, c-format msgid "HHCPN098I Device %d:%4.4X initialized\n" msgstr "HHC420I %s (%s) afgesloten van apparaat %4.4X (%s)\n" #: hsccmd.c:3229 msgid "HHCPN099E savecore rejected: filename missing\n" msgstr "" #: hsccmd.c:3262 #, fuzzy, c-format msgid "HHCPN100E savecore: invalid starting address: %s \n" msgstr "Ongeldig frame adres %8.8X\n" #: hsccmd.c:3280 #, fuzzy msgid "HHCPN148E savecore: no modified storage found\n" msgstr "Ongeldig frame adres %8.8X\n" #: hsccmd.c:3288 #, fuzzy, c-format msgid "HHCPN101E savecore: invalid ending address: %s \n" msgstr "Ongeldig frame adres %8.8X\n" #: hsccmd.c:3297 msgid "HHCPN102E savecore rejected: CPU not stopped\n" msgstr "" #: hsccmd.c:3304 #, fuzzy, c-format msgid "HHCPN103E invalid range: %8.8X-%8.8X\n" msgstr "Ongeldig bereik: %s\n" #: hsccmd.c:3309 #, c-format msgid "HHCPN104I Saving locations %8.8X-%8.8X to %s\n" msgstr "" #: hsccmd.c:3318 #, fuzzy, c-format msgid "HHCPN105E savecore error creating %s: %s\n" msgstr "HHC423I Fout %2$s bij schrijven naar bestand \"%1$s\"\n" #: hsccmd.c:3324 #, fuzzy, c-format msgid "HHCPN106E savecore error writing to %s: %s\n" msgstr "HHC423I Fout %2$s bij schrijven naar bestand \"%1$s\"\n" #: hsccmd.c:3327 #, c-format msgid "HHCPN107E savecore: unable to save %d bytes\n" msgstr "" #: hsccmd.c:3334 #, fuzzy msgid "HHCPN170I savecore command complete.\n" msgstr "HHC623I CPU%4.4X thread al gestart\n" #: hsccmd.c:3357 msgid "HHCPN108E loadcore rejected: filename missing\n" msgstr "" #: hsccmd.c:3366 #, fuzzy, c-format msgid "HHCPN109E Cannot open %s: %s\n" msgstr "Kann %s nicht öffnen: %s\n" #: hsccmd.c:3378 #, fuzzy, c-format msgid "HHCPN110E invalid address: %s \n" msgstr "Ongeldig bereik: %s\n" #: hsccmd.c:3397 msgid "HHCPN111E loadcore rejected: CPU not stopped\n" msgstr "" #: hsccmd.c:3402 #, c-format msgid "HHCPN112I Loading %s to location %x \n" msgstr "" #: hsccmd.c:3408 #, fuzzy, c-format msgid "HHCPN113I %d bytes read from %s\n" msgstr "%d Bytes gelesen von %s\n" #: hsccmd.c:3432 msgid "HHCPN114E loadtext rejected: filename missing\n" msgstr "" #: hsccmd.c:3445 #, fuzzy, c-format msgid "HHCPN115E invalid address: %s \n" msgstr "Ongeldig bereik: %s\n" #: hsccmd.c:3463 #, fuzzy msgid "HHCPN116E Address greater than mainstore size\n" msgstr "Adresse ist höher als Speicherobergrenze\n" #: hsccmd.c:3471 msgid "HHCPN117E loadtext rejected: CPU not stopped\n" msgstr "" #: hsccmd.c:3480 #, fuzzy, c-format msgid "HHCPN118E Cannot open %s: %s\n" msgstr "Kann %s nicht öffnen: %s\n" #: hsccmd.c:3491 #, fuzzy, c-format msgid "HHCPN119E Cannot read %s: %s\n" msgstr "Kann %s nicht öffnen: %s\n" #: hsccmd.c:3514 msgid "HHCPN120I Finished loading TEXT deck file\n" msgstr "" #: hsccmd.c:3515 #, fuzzy, c-format msgid " Last 'TXT' record had address: %3.3X\n" msgstr "Laatste 'TXT' record had adres: %3.3X\n" #: hsccmd.c:3541 #, fuzzy, c-format msgid "HHCPN123I CPU%4.4X: offline\n" msgstr "CPU%4.4X nicht konfiguriert\n" #: hsccmd.c:3547 #, c-format msgid "HHCPN123I CPU%4.4X: CPUint=%8.8X (State:%8.8X)&(Mask:%8.8X)\n" msgstr "" #: hsccmd.c:3552 #, fuzzy, c-format msgid " CPU%4.4X: Interrupt %spending\n" msgstr "CPU%4.4X: CPU Status: %s\n" #: hsccmd.c:3554 hsccmd.c:3558 hsccmd.c:3562 hsccmd.c:3566 hsccmd.c:3571 #: hsccmd.c:3576 hsccmd.c:3582 hsccmd.c:3586 hsccmd.c:3590 hsccmd.c:3594 #: hsccmd.c:3610 hsccmd.c:3649 hsccmd.c:3653 hsccmd.c:3657 hsccmd.c:3661 #: hsccmd.c:3665 hsccmd.c:3669 hsccmd.c:3673 hsccmd.c:3677 hsccmd.c:3681 #: hsccmd.c:3685 hsccmd.c:3724 hsccmd.c:3727 hsccmd.c:3730 hsccmd.c:3734 #: hsccmd.c:3739 msgid "not " msgstr "" #: hsccmd.c:3556 #, fuzzy, c-format msgid " CPU%4.4X: I/O interrupt %spending\n" msgstr "CPU%4.4X: CPU Status: %s\n" #: hsccmd.c:3560 #, c-format msgid " CPU%4.4X: Clock comparator %spending\n" msgstr "" #: hsccmd.c:3564 #, c-format msgid " CPU%4.4X: CPU timer %spending\n" msgstr "" #: hsccmd.c:3569 #, c-format msgid " CPU%4.4X: Interval timer %spending\n" msgstr "" #: hsccmd.c:3574 #, fuzzy, c-format msgid " CPU%4.4X: ECPS vtimer %spending\n" msgstr "CPU%4.4X: CPU Status: %s\n" #: hsccmd.c:3580 #, c-format msgid " CPU%4.4X: External call %spending\n" msgstr "" #: hsccmd.c:3584 #, c-format msgid " CPU%4.4X: Emergency signal %spending\n" msgstr "" #: hsccmd.c:3588 #, fuzzy, c-format msgid " CPU%4.4X: Machine check interrupt %spending\n" msgstr "CPU%4.4X: Mit keinem Channel-Set verbunden\n" #: hsccmd.c:3592 #, fuzzy, c-format msgid " CPU%4.4X: Service signal %spending\n" msgstr " Blöcke: %d, Gesamtgröße %d\n" #: hsccmd.c:3596 #, fuzzy, c-format msgid " CPU%4.4X: Mainlock held: %s\n" msgstr "CPU%4.4X: Mit keinem Channel-Set verbunden\n" #: hsccmd.c:3598 hsccmd.c:3602 hsccmd.c:3606 msgid "yes" msgstr "" #: hsccmd.c:3598 hsccmd.c:3602 hsccmd.c:3606 msgid "no" msgstr "" #: hsccmd.c:3600 #, fuzzy, c-format msgid " CPU%4.4X: Intlock held: %s\n" msgstr "CPU%4.4X: Mit keinem Channel-Set verbunden\n" #: hsccmd.c:3604 #, fuzzy, c-format msgid " CPU%4.4X: Waiting for intlock: %s\n" msgstr "CPU%4.4X: CPU Status: %s\n" #: hsccmd.c:3608 #, fuzzy, c-format msgid " CPU%4.4X: lock %sheld\n" msgstr "CPU%4.4X: Mit keinem Channel-Set verbunden\n" #: hsccmd.c:3615 #, fuzzy, c-format msgid " CPU%4.4X: No channelset connected\n" msgstr "CPU%4.4X: Mit keinem Channel-Set verbunden\n" #: hsccmd.c:3619 #, fuzzy, c-format msgid " CPU%4.4X: Connected to channelset %4.4X\n" msgstr "CPU%4.4X: Verbunden mit Channel-Set %4.4X\n" #: hsccmd.c:3624 #, fuzzy, c-format msgid " CPU%4.4X: state %s\n" msgstr "CPU%4.4X: CPU Status: %s\n" #: hsccmd.c:3626 #, fuzzy msgid " CPU%4.4X: instcount %" msgstr "CPU%4.4X: Mit keinem Channel-Set verbunden\n" #: hsccmd.c:3628 #, fuzzy msgid " CPU%4.4X: siocount %" msgstr "CPU%4.4X: Mit keinem Channel-Set verbunden\n" #: hsccmd.c:3631 #, fuzzy, c-format msgid " CPU%4.4X: psw %2.2x%2.2x%2.2x%2.2x %2.2x%2.2x%2.2x%2.2x" msgstr "" "*** track %d R0 Validierungsfehler! %2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%" "2.2x\n" #: hsccmd.c:3635 hsccmd.c:3710 #, fuzzy, c-format msgid " %2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x" msgstr "" "*** track %d R0 Validierungsfehler! %2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%" "2.2x\n" #: hsccmd.c:3642 #, c-format msgid "HHCPN123I SIE%4.4X: CPUint=%8.8X (State:%8.8X)&(Mask:%8.8X)\n" msgstr "" #: hsccmd.c:3647 #, fuzzy, c-format msgid " SIE%4.4X: Interrupt %spending\n" msgstr "CPU%4.4X: CPU Status: %s\n" #: hsccmd.c:3651 #, fuzzy, c-format msgid " SIE%4.4X: I/O interrupt %spending\n" msgstr "CPU%4.4X: CPU Status: %s\n" #: hsccmd.c:3655 #, fuzzy, c-format msgid " SIE%4.4X: Clock comparator %spending\n" msgstr "CPU%4.4X: CPU Status: %s\n" #: hsccmd.c:3659 #, fuzzy, c-format msgid " SIE%4.4X: CPU timer %spending\n" msgstr "CPU%4.4X: CPU Status: %s\n" #: hsccmd.c:3663 #, fuzzy, c-format msgid " SIE%4.4X: Interval timer %spending\n" msgstr "CPU%4.4X: CPU Status: %s\n" #: hsccmd.c:3667 #, fuzzy, c-format msgid " SIE%4.4X: External call %spending\n" msgstr "CPU%4.4X: CPU Status: %s\n" #: hsccmd.c:3671 #, fuzzy, c-format msgid " SIE%4.4X: Emergency signal %spending\n" msgstr " Blöcke: %d, Gesamtgröße %d\n" #: hsccmd.c:3675 #, fuzzy, c-format msgid " SIE%4.4X: Machine check interrupt %spending\n" msgstr "CPU%4.4X: Mit keinem Channel-Set verbunden\n" #: hsccmd.c:3679 #, fuzzy, c-format msgid " SIE%4.4X: Service signal %spending\n" msgstr " Blöcke: %d, Gesamtgröße %d\n" #: hsccmd.c:3683 #, fuzzy, c-format msgid " SIE%4.4X: lock %sheld\n" msgstr "CPU%4.4X: Mit keinem Channel-Set verbunden\n" #: hsccmd.c:3690 #, fuzzy, c-format msgid " SIE%4.4X: No channelset connected\n" msgstr "CPU%4.4X: Mit keinem Channel-Set verbunden\n" #: hsccmd.c:3694 #, fuzzy, c-format msgid " SIE%4.4X: Connected to channelset %4.4X\n" msgstr "CPU%4.4X: Verbunden mit Channel-Set %4.4X\n" #: hsccmd.c:3699 #, fuzzy, c-format msgid " SIE%4.4X: state %s\n" msgstr "CPU%4.4X: CPU Status: %s\n" #: hsccmd.c:3701 #, fuzzy msgid " SIE%4.4X: instcount %" msgstr "CPU%4.4X: Mit keinem Channel-Set verbunden\n" #: hsccmd.c:3703 #, fuzzy msgid " SIE%4.4X: siocount %" msgstr "CPU%4.4X: Mit keinem Channel-Set verbunden\n" #: hsccmd.c:3706 #, fuzzy, c-format msgid " SIE%4.4X: psw %2.2x%2.2x%2.2x%2.2x %2.2x%2.2x%2.2x%2.2x" msgstr "" "*** track %d R0 Validierungsfehler! %2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%" "2.2x\n" #: hsccmd.c:3717 #, c-format msgid " Config mask %8.8X started mask %8.8X waiting mask %8.8X\n" msgstr "" #: hsccmd.c:3720 #, c-format msgid " Syncbc mask %8.8x %s\n" msgstr "" #: hsccmd.c:3721 msgid "Sync in progress" msgstr "" #: hsccmd.c:3723 #, c-format msgid " Signaling facility %sbusy\n" msgstr "" #: hsccmd.c:3726 #, c-format msgid " TOD lock %sheld\n" msgstr "" #: hsccmd.c:3729 #, fuzzy, c-format msgid " Mainlock %sheld; owner %4.4x\n" msgstr "CPU%4.4X: Mit keinem Channel-Set verbunden\n" #: hsccmd.c:3733 #, fuzzy, c-format msgid " Intlock %sheld; owner %4.4x\n" msgstr "CPU%4.4X: Mit keinem Channel-Set verbunden\n" #: hsccmd.c:3738 #, c-format msgid " Ioq lock %sheld\n" msgstr "" #: hsccmd.c:3752 #, fuzzy, c-format msgid " DEV %d:%4.4X: busy %s\n" msgstr "CPU%4.4X: CPU Status: %s\n" #: hsccmd.c:3754 #, fuzzy, c-format msgid " DEV %d:%4.4X: reserved %s\n" msgstr "CPU%4.4X: CPU Status: %s\n" #: hsccmd.c:3756 #, fuzzy, c-format msgid " DEV %d:%4.4X: suspended\n" msgstr "CPU%4.4X: CPU Status: %s\n" #: hsccmd.c:3758 #, fuzzy, c-format msgid " DEV %d:%4.4X: I/O pending\n" msgstr "CPU%4.4X: CPU Status: %s\n" #: hsccmd.c:3760 #, fuzzy, c-format msgid " DEV %d:%4.4X: PCI pending\n" msgstr "CPU%4.4X: CPU Status: %s\n" #: hsccmd.c:3762 #, fuzzy, c-format msgid " DEV %d:%4.4X: Attn pending\n" msgstr "CPU%4.4X: CPU Status: %s\n" #: hsccmd.c:3764 #, fuzzy, c-format msgid " DEV %d:%4.4X: CRW pending\n" msgstr "CPU%4.4X: CPU Status: %s\n" #: hsccmd.c:3766 #, fuzzy, c-format msgid " DEV %d:%4.4X: lock held\n" msgstr "CPU%4.4X: Mit keinem Channel-Set verbunden\n" #: hsccmd.c:3769 msgid " I/O interrupt queue: " msgstr "" #: hsccmd.c:3772 msgid "(NULL)" msgstr "" #: hsccmd.c:3778 #, fuzzy, c-format msgid " DEV %d:%4.4X,%s%s%s%s, pri %d\n" msgstr "CPU%4.4X: CPU Status: %s\n" #: hsccmd.c:3812 #, fuzzy msgid "HHCPN124I Instruction counts reset to zero.\n" msgstr "%sFehler beim Lesen der Instruktion\n" #: hsccmd.c:4247 #, fuzzy msgid "HHCPN125I Sorted instruction count display:\n" msgstr "%sFehler beim Lesen der Instruktion\n" #: hsccmd.c:4345 #, fuzzy msgid "HHCPN125I Instruction count display:\n" msgstr "%sFehler beim Lesen der Instruktion\n" #: hsccmd.c:4527 msgid "HHCPN996E The script command requires a filename\n" msgstr "" #: hsccmd.c:4540 msgid "HHCPN997E Only 1 script may be invoked from the panel at any time\n" msgstr "" #: hsccmd.c:4558 msgid "HHCPN998E Script aborted : user cancel request\n" msgstr "" #: hsccmd.c:4580 msgid "HHCPN998E Script aborted : Script recursion level exceeded\n" msgstr "" #: hsccmd.c:4596 hsccmd.c:4605 #, fuzzy, c-format msgid "HHCPN007E Script file \"%s\" open failed: %s\n" msgstr "HHC406I Fout %2$s bij zoeken in bestand \"%1$s\"\n" #: hsccmd.c:4599 #, fuzzy, c-format msgid "HHCPN995E Script file \"%s\" not found\n" msgstr "HHC351I Bestandsnaam niet opgegeven of ongeldig\n" #: hsccmd.c:4617 #, fuzzy, c-format msgid "HHCPN008I Script file processing started using file \"%s\"\n" msgstr "HHC406I Fout %2$s bij zoeken in bestand \"%1$s\"\n" #: hsccmd.c:4625 #, fuzzy, c-format msgid "HHCPN009E Script file buffer malloc failed: %s\n" msgstr "HHC406I Fout %2$s bij zoeken in bestand \"%1$s\"\n" #: hsccmd.c:4667 #, fuzzy, c-format msgid "HHCPN010W Ignoring invalid SCRIPT file pause statement: %s\n" msgstr "HHC422I Optie %s niet geldig\n" #: hsccmd.c:4673 #, c-format msgid "HHCPN011I Pausing SCRIPT file processing for %d seconds...\n" msgstr "" #: hsccmd.c:4677 msgid "HHCPN012I Resuming SCRIPT file processing...\n" msgstr "" #: hsccmd.c:4695 msgid "HHCPN013I EOF reached on SCRIPT file. Processing complete.\n" msgstr "" #: hsccmd.c:4700 #, fuzzy, c-format msgid "HHCPN014E I/O error reading SCRIPT file: %s\n" msgstr "HHC409I Fout %2$s bij lezen van bestand \"%1$s\"\n" #: hsccmd.c:4705 #, c-format msgid "HHCPN999I Script \"%s\" aborted due to previous conditions\n" msgstr "" #: hsccmd.c:4734 #, fuzzy, c-format msgid "HHCPN126I Architecture mode = %s\n" msgstr "Modus: %s\n" #: hsccmd.c:4747 msgid "HHCPN127E All CPU's must be stopped to change architecture\n" msgstr "" #: hsccmd.c:4788 #, fuzzy, c-format msgid "HHCPN128E Invalid architecture mode %s\n" msgstr "Ongeldige achitectuur modus %s\n" #: hsccmd.c:4802 #, fuzzy, c-format msgid "HHCPN129I Architecture successfully set to %s mode.\n" msgstr "Modus umgeschaltef auf %s\n" #: hsccmd.c:4864 #, fuzzy, c-format msgid "HHCPN130E Invalid frame address %8.8X\n" msgstr "Ongeldig frame adres %8.8X\n" #: hsccmd.c:4871 #, c-format msgid "HHCPN131I Frame %8.8X marked %s\n" msgstr "" #: hsccmd.c:4872 msgid "usable" msgstr "" #: hsccmd.c:4872 msgid "unusable" msgstr "" #: hsccmd.c:4889 #, fuzzy, c-format msgid "HHCPN134I CKD KEY trace is now %s\n" msgstr "CKD KEY Ablaufverfolgung ist %s\n" #: hsccmd.c:4912 #, fuzzy, c-format msgid "HHCPN136I CCW tracing is now %s for device %d:%4.4X\n" msgstr "CCW Ablaufverfolgung ist %s für %4.4X\n" #: hsccmd.c:4917 #, fuzzy, c-format msgid "HHCPN137I CCW stepping is now %s for device %d:%4.4X\n" msgstr "CCW Einzelschritt ist %s für %4.4X\n" #: hsccmd.c:4926 msgid "HHCPN138E Unrecognized +/- command.\n" msgstr "" #: hsccmd.c:5230 #, fuzzy, c-format msgid "HHCHD100I Loading %s ...\n" msgstr "HHC404I Fout %2$s bij openen van bestand \"%1$s\"\n" #: hsccmd.c:5232 #, c-format msgid "HHCHD101I Module %s loaded\n" msgstr "" #: hsccmd.c:5255 #, fuzzy, c-format msgid "HHCHD102I Unloading %s ...\n" msgstr "HHC409I Fout %2$s bij lezen van bestand \"%1$s\"\n" #: hsccmd.c:5257 #, fuzzy, c-format msgid "HHCHD103I Module %s unloaded\n" msgstr "HHC420I %s (%s) afgesloten van apparaat %4.4X (%s)\n" #: hsccmd.c:5302 msgid "HHCPN150W evm command is deprecated. Use \"ecpsvm\" instead\n" msgstr "" #: hsccmd.c:5338 #, c-format msgid "HHCPN161I (void *) ..........%7d\n" msgstr "" #: hsccmd.c:5339 #, c-format msgid "HHCPN161I (unsigned int) ....%7d\n" msgstr "" #: hsccmd.c:5340 #, c-format msgid "HHCPN161I (size_t) ..........%7d\n" msgstr "" #: hsccmd.c:5341 #, c-format msgid "HHCPN161I (off_t) ...........%7d\n" msgstr "" #: hsccmd.c:5342 #, c-format msgid "HHCPN161I SYSBLK ............%7d\n" msgstr "" #: hsccmd.c:5343 #, c-format msgid "HHCPN161I REGS ..............%7d\n" msgstr "" #: hsccmd.c:5344 #, c-format msgid "HHCPN161I REGS (copy len) ...%7d\n" msgstr "" #: hsccmd.c:5345 #, c-format msgid "HHCPN161I PSW ...............%7d\n" msgstr "" #: hsccmd.c:5346 #, c-format msgid "HHCPN161I DEVBLK ............%7d\n" msgstr "" #: hsccmd.c:5347 #, c-format msgid "HHCPN161I TLB entry .........%7d\n" msgstr "" #: hsccmd.c:5348 #, c-format msgid "HHCPN161I TLB table .........%7d\n" msgstr "" #: hsccmd.c:5349 #, c-format msgid "HHCPN161I FILENAME_MAX ......%7d\n" msgstr "" #: hsccmd.c:5350 #, c-format msgid "HHCPN161I PATH_MAX ..........%7d\n" msgstr "" #: hsccmd.c:5391 #, c-format msgid "HHCPN190I Keep-alive = (%d,%d,%d)\n" msgstr "" #: hsccmd.c:5394 msgid "HHCPN192E Invalid format. Enter \"help conkpalv\" for help.\n" msgstr "" #: hsccmd.c:5422 #, fuzzy, c-format msgid "HHCPN162I Hercules instruction trace displayed in %s mode\n" msgstr "%sFehler beim Lesen der Instruktion\n" #: hsccmd.c:5423 msgid "noregs" msgstr "" #: hsccmd.c:5424 msgid "regsfirst" msgstr "" #: hsccmd.c:5425 msgid "traditional" msgstr "" #: hsccmd.c:5734 #, c-format msgid "HHCPN139E Command \"%s\" not found; enter '?' for list.\n" msgstr "" #: hsccmd.c:5761 msgid "" "HHCPN140I Valid panel commands are...\n" "\n" msgstr "" #: hsccmd.c:5771 #, c-format msgid " %-9.9s %s \n" msgstr "" #: hsccmd.c:5778 msgid "add shadow file" msgstr "" #: hsccmd.c:5779 msgid "delete shadow file" msgstr "" #: hsccmd.c:5780 msgid "rename shadow file" msgstr "" #: hsccmd.c:5781 msgid "compress shadow files" msgstr "" #: hsccmd.c:5782 msgid "display shadow file stats" msgstr "" #: hsccmd.c:5788 msgid "turn CCW tracing on/off" msgstr "" #: hsccmd.c:5789 msgid "turn CCW stepping on/off" msgstr "" #: hsccmd.c:5791 msgid "turn CKD_KEY tracing on/off" msgstr "" #: hsccmd.c:5793 msgid "mark frames unusable/usable" msgstr "" #: hsccmd.c:6128 #, fuzzy msgid "HHCPN141E Missing argument\n" msgstr "Geen apparaat nummer\n" #: hsccmd.c:6136 #, c-format msgid "%s" msgstr "" #: hsccmd.c:6141 msgid "HHCPN142I No additional help available.\n" msgstr "" #: hscmisc.c:208 #, c-format msgid "DO_SHUTDOWN_NOW EXIT\n" msgstr "" #: hscmisc.c:210 impl.c:582 #, c-format msgid "HHCIN099I Hercules terminated\n" msgstr "" #: hscmisc.c:224 msgid "HHCIN098I Shutdown initiated\n" msgstr "" #: hscmisc.c:598 #, fuzzy, c-format msgid "HHCPN143E Invalid value: %s\n" msgstr "Ongeldige waarde: %s\n" #: hscmisc.c:622 #, fuzzy, c-format msgid "HHCPN144E Invalid operand: %s\n" msgstr "Ongeldig operand: %s\n" #: hscmisc.c:634 #, fuzzy, c-format msgid "HHCPN145E Invalid range: %s\n" msgstr "Ongeldig bereik: %s\n" #: hscmisc.c:680 #, fuzzy, c-format msgid "HHCMS001E malloc failed for REGS copy: %s\n" msgstr "HHC406I Fout %2$s bij zoeken in bestand \"%1$s\"\n" #: hscmisc.c:895 #, c-format msgid "Storage not accessible code = %4.4X\n" msgstr "" #: hscmisc.c:903 hscmisc.c:912 msgid "Addressing exception\n" msgstr "" #: hscmisc.c:1126 #, c-format msgid "%sInstruction fetch error\n" msgstr "%sFehler beim Lesen der Instruktion\n" #: httpserv.c:89 #, fuzzy, c-format msgid "HHCHT011E html_include: Cannot open %s: %s\n" msgstr "Kann %s nicht öffnen: %s\n" #: httpserv.c:91 #, c-format msgid "ERROR: Cannot open %s: %s\n" msgstr "" #: httpserv.c:331 #, c-format msgid "HHCHT012I cgi_var_dump: pointer(%p) name(%s) value(%s) type(%d)\n" msgstr "" #: httpserv.c:650 #, fuzzy msgid "HHCHT001I HTTP listener thread started: tid=" msgstr "HHC620I CPU%4.4X thread gestart: tid=%8.8lX, pid=%d, prioriteit=%d\n" #: httpserv.c:689 httpserv.c:699 #, fuzzy, c-format msgid "HHCCF066E Invalid HTTPROOT: \"%s\": %s\n" msgstr "Ongeldig frame adres %8.8X\n" #: httpserv.c:710 #, c-format msgid "HHCHT013I Using HTTPROOT directory \"%s\"\n" msgstr "" #: httpserv.c:718 #, c-format msgid "HHCHT002E socket: %s\n" msgstr "" #: httpserv.c:741 #, c-format msgid "HHCHT003W Waiting for port %u to become free\n" msgstr "" #: httpserv.c:748 #, c-format msgid "HHCHT004E bind: %s\n" msgstr "" #: httpserv.c:757 #, c-format msgid "HHCHT005E listen: %s\n" msgstr "" #: httpserv.c:761 #, c-format msgid "HHCHT006I Waiting for HTTP requests on port %u\n" msgstr "" #: httpserv.c:779 #, c-format msgid "HHCHT007E select: %s\n" msgstr "" #: httpserv.c:791 #, c-format msgid "HHCHT008E accept: %s\n" msgstr "" #: httpserv.c:801 #, fuzzy, c-format msgid "HHCHT010E http_request create_thread: %s\n" msgstr "Kann %s nicht öffnen: %s\n" #: ieee.c:488 msgid "ebfpston: unexpectedly converting a NaN\n" msgstr "" #: ieee.c:492 msgid "ebfpston: unexpectedly converting an Infinite\n" msgstr "" #: ieee.c:547 msgid "lbfpston: unexpectedly converting a NaN\n" msgstr "" #: ieee.c:551 msgid "lbfpston: unexpectedly converting an Infinite\n" msgstr "" #: ieee.c:600 msgid "sbfpston: unexpectedly converting a NaN\n" msgstr "" #: ieee.c:604 msgid "sbfpston: unexpectedly converting an Infinite\n" msgstr "" #: impl.c:226 #, fuzzy, c-format msgid "HHCPN995E .RC file \"%s\" not found.\n" msgstr "HHC351I Bestandsnaam niet opgegeven of ongeldig\n" #: impl.c:340 #, c-format msgid "HHCIN008S DYNGUI.DLL load failed; Hercules terminated.\n" msgstr "" #: impl.c:411 #, fuzzy, c-format msgid "HHCIN001S Cannot register SIGINT handler: %s\n" msgstr "Kann %s nicht öffnen: %s\n" #: impl.c:422 #, fuzzy, c-format msgid "HHCIN002E Cannot suppress SIGPIPE signal: %s\n" msgstr "Kann %s nicht öffnen: %s\n" #: impl.c:461 #, fuzzy, c-format msgid "HHCIN003S Cannot register SIGILL/FPE/SEGV/BUS/USR handler: %s\n" msgstr "Kann %s nicht öffnen: %s\n" #: impl.c:484 #, fuzzy, c-format msgid "HHCIN004S Cannot create watchdog thread: %s\n" msgstr "Kann %s nicht öffnen: %s\n" #: impl.c:498 #, fuzzy, c-format msgid "HHCIN005S Cannot create http_server thread: %s\n" msgstr "Kann %s nicht öffnen: %s\n" #: impl.c:512 #, fuzzy, c-format msgid "HHCIN006S Cannot create shared_server thread: %s\n" msgstr "Kann %s nicht öffnen: %s\n" #: impl.c:529 #, fuzzy, c-format msgid "HHCIN007S Cannot create %4.4X connection thread: %s\n" msgstr "Kann %s nicht öffnen: %s\n" #: impl.c:580 #, c-format msgid "IMPL EXIT\n" msgstr "" #: ipl.c:219 #, fuzzy, c-format msgid "HHCCP027E Device %4.4X not in configuration%s\n" msgstr "CPU%4.4X nicht konfiguriert\n" #: ipl.c:276 #, c-format msgid "" "HHCCP029E %s mode IPL failed: CSW status=%2.2X%2.2X\n" " Sense=" msgstr "" #: ipl.c:369 #, fuzzy, c-format msgid "HHCCP031E Load from %s failed: %s\n" msgstr "HHC406I Fout %2$s bij zoeken in bestand \"%1$s\"\n" #: ipl.c:428 #, c-format msgid "" "HHCCP030E %s mode IPL failed: Invalid IPL PSW: %2.2X%2.2X%2.2X%2.2X %2.2X%" "2.2X%2.2X%2.2X\n" msgstr "" #: ipl.c:592 #, c-format msgid "HHCCP033E load_main: %s: %s\n" msgstr "" #: ipl.c:602 msgid "HHCCP034W load_main: terminated at end of mainstor\n" msgstr "" #: logger.c:178 logger.c:378 #, fuzzy msgid "HHCLG014I logger thread terminating\n" msgstr "HHC650I Controle paneel thread gestart: tid=%8.8lX, pid=%d\n" #: logger.c:206 #, fuzzy, c-format msgid "HHCLG003E Error writing hardcopy log: %s\n" msgstr "HHC423I Fout %2$s bij schrijven naar bestand \"%1$s\"\n" #: logger.c:259 #, fuzzy, c-format msgid "HHCLG001E Error redirecting stdout: %s\n" msgstr "HHC423I Fout %2$s bij schrijven naar bestand \"%1$s\"\n" #: logger.c:298 #, fuzzy, c-format msgid "HHCLG002E Error reading syslog pipe: %s\n" msgstr "HHC405I Fout %2$s bij lezen van bestand \"%1$s\"\n" #: logger.c:421 logger.c:433 #, fuzzy, c-format msgid "HHCLG004E Error duplicating stderr: %s\n" msgstr "HHC423I Fout %2$s bij schrijven naar bestand \"%1$s\"\n" #: logger.c:443 #, fuzzy, c-format msgid "HHCLG005E Error duplicating stdout: %s\n" msgstr "HHC423I Fout %2$s bij schrijven naar bestand \"%1$s\"\n" #: logger.c:453 #, fuzzy, c-format msgid "HHCLG006E Duplicate error redirecting hardcopy log: %s\n" msgstr "HHC423I Fout %2$s bij schrijven naar bestand \"%1$s\"\n" #: logger.c:460 #, fuzzy, c-format msgid "HHCLG007S Hardcopy log fdopen failed: %s\n" msgstr "HHC406I Fout %2$s bij zoeken in bestand \"%1$s\"\n" #: logger.c:476 #, c-format msgid "HHCLG008S logbuffer malloc failed: %s\n" msgstr "" #: logger.c:483 #, fuzzy, c-format msgid "HHCLG009S Syslog message pipe creation failed: %s\n" msgstr "HHC406I Fout %2$s bij zoeken in bestand \"%1$s\"\n" #: logger.c:494 #, fuzzy, c-format msgid "HHCLG012E Cannot create logger thread: %s\n" msgstr "Kann %s nicht öffnen: %s\n" #: logger.c:516 #, fuzzy msgid "HHCLG014E log not active\n" msgstr "HHC650I Controle paneel thread gestart: tid=%8.8lX, pid=%d\n" #: logger.c:525 logger.c:527 #, c-format msgid "HHCLG015I log closed\n" msgstr "" #: logger.c:541 #, fuzzy, c-format msgid "HHCLG016E Error opening logfile %s: %s\n" msgstr "HHC423I Fout %2$s bij openen bestand \"%1$s\"\n" #: logger.c:549 #, fuzzy, c-format msgid "HHCLG017S log file fdopen failed for %s: %s\n" msgstr "HHC406I Fout %2$s bij zoeken in bestand \"%1$s\"\n" #: logger.c:564 #, fuzzy, c-format msgid "HHCLG018I log switched to %s\n" msgstr "HHC650I Controle paneel thread gestart: tid=%8.8lX, pid=%d\n" #: machchk.c:250 msgid "HHCCP019I Machine Check code=%16.16" msgstr "" #: machchk.c:310 #, fuzzy msgid "HHCCP020E signal USR2 received for undetermined device\n" msgstr "CCW Ablaufverfolgung ist %s für %4.4X\n" #: machchk.c:315 #, fuzzy, c-format msgid "HHCCP021E signal USR2 received for device %4.4X\n" msgstr "CCW Ablaufverfolgung ist %s für %4.4X\n" #: machchk.c:339 machchk.c:343 #, fuzzy, c-format msgid "HHCCP017I CPU%4.4X: Machine check due to host error: %s\n" msgstr "CPU%4.4X: Ceck-stop. Host Fehler: %s\n" #: machchk.c:378 machchk.c:382 #, fuzzy, c-format msgid "HHCCP018I CPU%4.4X: Check-Stop due to host error: %s\n" msgstr "CPU%4.4X: Ceck-stop. Host Fehler: %s\n" #: panel.c:1281 #, fuzzy msgid "HHCPN001I Control panel thread started: tid=" msgstr "HHC650I Controle paneel thread gestart: tid=%8.8lX, pid=%d\n" #: panel.c:1306 #, fuzzy, c-format msgid "HHCPN002S Cannot obtain keyboard buffer: %s\n" msgstr "Kann %s nicht öffnen: %s\n" #: panel.c:1316 #, fuzzy, c-format msgid "HHCPN003S Cannot obtain message buffer: %s\n" msgstr "Kann %s nicht öffnen: %s\n" #: panel.c:1377 #, fuzzy, c-format msgid "HHCPN004E select: %s\n" msgstr "HHC760I %4.4X create_thread fout: %s" #: panel.c:1393 #, fuzzy, c-format msgid "HHCPN005E keyboard read: %s\n" msgstr "HHC419E Fout %2$s bij sluiten van bestand \"%1$s\"\n" #: printer.c:119 #, fuzzy, c-format msgid "HHCPR004E Error opening file %s: %s\n" msgstr "HHC404I Fout %2$s bij openen van bestand \"%1$s\"\n" #: printer.c:140 printer.c:165 #, c-format msgid "HHCPR006E %4.4X device initialization error: fork: %s\n" msgstr "" #: printer.c:146 printer.c:176 #, c-format msgid "HHCPR007I pipe receiver (pid=%d) starting for %4.4X\n" msgstr "" #: printer.c:156 #, c-format msgid "HHCPR005E %4.4X device initialization error: pipe: %s\n" msgstr "" #: printer.c:188 #, fuzzy, c-format msgid "HHCPR008E %4.4X dup2 error: %s\n" msgstr "HHC760I %4.4X create_thread fout: %s" #: printer.c:210 printer.c:360 #, c-format msgid "HHCPR011I pipe receiver (pid=%d) terminating for %4.4X\n" msgstr "" #: printer.c:216 #, fuzzy, c-format msgid "HHCPR012E %4.4X Unable to execute %s: %s\n" msgstr "HHC402I Fout %2$s bij benaderen bestand \"%1$s\"\n" #: printer.c:255 #, fuzzy, c-format msgid "HHCPR003E %4.4X Error writing to %s: %s\n" msgstr "HHC423I Fout %2$s bij schrijven naar bestand \"%1$s\"\n" #: printer.c:257 msgid "incomplete" msgstr "" #: printer.c:275 #, fuzzy, c-format msgid "HHCPR001E File name missing or invalid for printer %4.4X\n" msgstr "HHC351I Bestandsnaam niet opgegeven of ongeldig\n" #: printer.c:304 #, fuzzy, c-format msgid "HHCPR002E Invalid argument for printer %4.4X: %s\n" msgstr "HHC422I Optie %s niet geldig\n" #: service.c:104 #, fuzzy msgid "HHCCP036E SCP not receiving priority messages\n" msgstr "HHC703I SCP ontvangt geen prioriteits berichten\n" #: service.c:111 #, fuzzy msgid "HHCCP037E SCP not receiving commands\n" msgstr "HHC704I SCP ontvangt geen commando's\n" #: service.c:118 #, fuzzy msgid "HHCCP038E No SCP command\n" msgstr "HHC705I Geen SCP commando\n" #: service.c:129 #, fuzzy msgid "HHCCP039E Service Processor busy\n" msgstr "%d Geräte bearbeitet\n" #: service.c:167 #, fuzzy msgid "HHCCP081E SCP not receiving quiesce signals\n" msgstr "HHC704I SCP ontvangt geen commando's\n" #: service.c:178 #, fuzzy msgid "HHCCP082E Service Processor busy\n" msgstr "%d Geräte bearbeitet\n" #: service.c:933 #, c-format msgid "HHCCP040I CPI: System Type: %s Name: %s Sysplex: %s\n" msgstr "" #: service.c:937 msgid "HHC770I Control Program Information:\n" msgstr "" #: service.c:938 #, c-format msgid "HHC771I System Type = %s\n" msgstr "" #: service.c:939 #, c-format msgid "HHC772I System Name = %s\n" msgstr "" #: service.c:940 #, c-format msgid "HHC773I Sysplex Name = %s\n" msgstr "" #: service.c:941 msgid "HHC774I System Level = %16.16" msgstr "" #: service.c:1174 #, fuzzy msgid "HHCCP041I SYSCONS interface active\n" msgstr "HHC701I SYSCONS interface actief\n" #: service.c:1176 #, fuzzy msgid "HHCCP042I SYSCONS interface inactive\n" msgstr "HHC702I SYSCONS interface inactief\n" #: service.c:1300 #, fuzzy, c-format msgid "CPU%4.4X: Vector Facility configured offline\n" msgstr "HHC623I CPU%4.4X thread al gestart\n" #: service.c:1331 #, fuzzy, c-format msgid "CPU%4.4X: Vector Facility configured online\n" msgstr "HHC623I CPU%4.4X thread al gestart\n" #: shared.c:222 #, fuzzy, c-format msgid "HHCSH001S parameter %d is invalid: %s\n" msgstr "HHC351I Bestandsnaam niet opgegeven of ongeldig\n" #: shared.c:248 #, fuzzy, c-format msgid "HHCSH002W %4.4X connect pending to %s\n" msgstr "CPU%4.4X: Verbunden mit Channel-Set %4.4X\n" #: shared.c:266 #, fuzzy, c-format msgid "HHCSH003S %4.4X Error retrieving cylinders\n" msgstr "HHC423I Fout %2$s bij schrijven naar bestand \"%1$s\"\n" #: shared.c:279 #, fuzzy, c-format msgid "HHCSH004S %4.4X Error retrieving device characteristics\n" msgstr "HHC423I Fout %2$s bij schrijven naar bestand \"%1$s\"\n" #: shared.c:297 #, fuzzy, c-format msgid "HHCSH005S %4.4X Remote device %4.4X is a %4.4X\n" msgstr "HHC420I %s (%s) afgesloten van apparaat %4.4X (%s)\n" #: shared.c:309 #, fuzzy, c-format msgid "HHCSH006S %4.4X Error retrieving device id\n" msgstr "HHC423I Fout %2$s bij schrijven naar bestand \"%1$s\"\n" #: shared.c:326 #, fuzzy, c-format msgid "HHCSH007S %4.4X device type %4.4X not found in dasd table\n" msgstr "HHC420I %s (%s) afgesloten van apparaat %4.4X (%s)\n" #: shared.c:338 #, fuzzy, c-format msgid "HHCSH008S %4.4X control unit %s not found in dasd table\n" msgstr "HHC420I %s (%s) afgesloten van apparaat %4.4X (%s)\n" #: shared.c:359 #, fuzzy, c-format msgid "HHCSH009I %s cyls=%d heads=%d tracks=%d trklen=%d\n" msgstr "%d Bytes gelesen von %s\n" #: shared.c:470 #, fuzzy, c-format msgid "HHCSH010S parameter %d is invalid: %s\n" msgstr "HHC351I Bestandsnaam niet opgegeven of ongeldig\n" #: shared.c:496 #, fuzzy, c-format msgid "HHCSH011I %4.4X connect pending to %s\n" msgstr "CPU%4.4X: Verbunden mit Channel-Set %4.4X\n" #: shared.c:511 #, fuzzy, c-format msgid "HHCSH012S %4.4X Error retrieving fba origin\n" msgstr "HHC423I Fout %2$s bij schrijven naar bestand \"%1$s\"\n" #: shared.c:523 #, fuzzy, c-format msgid "HHCSH013S %4.4X Error retrieving fba number blocks\n" msgstr "HHC423I Fout %2$s bij schrijven naar bestand \"%1$s\"\n" #: shared.c:535 #, fuzzy, c-format msgid "HHCSH014S %4.4X Error retrieving fba block size\n" msgstr "HHC423I Fout %2$s bij schrijven naar bestand \"%1$s\"\n" #: shared.c:549 #, fuzzy, c-format msgid "HHCSH015S %4.4X Error retrieving device id\n" msgstr "HHC423I Fout %2$s bij schrijven naar bestand \"%1$s\"\n" #: shared.c:558 #, fuzzy, c-format msgid "HHCSH016S %4.4X Remote device %4.4X is a %4.4X\n" msgstr "HHC420I %s (%s) afgesloten van apparaat %4.4X (%s)\n" #: shared.c:570 #, fuzzy, c-format msgid "HHCSH017S %4.4X Error retrieving device characteristics\n" msgstr "HHC423I Fout %2$s bij schrijven naar bestand \"%1$s\"\n" #: shared.c:587 #, fuzzy, c-format msgid "HHCSH018S %4.4X device type %4.4X not found in dasd table\n" msgstr "HHC420I %s (%s) afgesloten van apparaat %4.4X (%s)\n" #: shared.c:596 #, c-format msgid "HHCSH019I %s origin=%d blks=%d\n" msgstr "" #: shared.c:641 #, fuzzy, c-format msgid "HHCSH020E %4.4X error during channel program start\n" msgstr "HHC405I Fout %2$s bij lezen van bestand \"%1$s\"\n" #: shared.c:698 #, fuzzy, c-format msgid "HHCSH021E %4.4X error during channel program end\n" msgstr "HHC405I Fout %2$s bij lezen van bestand \"%1$s\"\n" #: shared.c:803 #, fuzzy, c-format msgid "HHCSH022E %4.4X error reading track %d\n" msgstr "HHC405I Fout %2$s bij lezen van bestand \"%1$s\"\n" #: shared.c:815 #, fuzzy, c-format msgid "HHCSH023E %4.4X error reading track %d\n" msgstr "HHC405I Fout %2$s bij lezen van bestand \"%1$s\"\n" #: shared.c:1015 #, fuzzy, c-format msgid "HHCSH024E %4.4X error reading block group %d\n" msgstr "HHC405I Fout %2$s bij lezen van bestand \"%1$s\"\n" #: shared.c:1028 #, fuzzy, c-format msgid "HHCSH025E %4.4X error reading block group %d\n" msgstr "HHC405I Fout %2$s bij lezen van bestand \"%1$s\"\n" #: shared.c:1116 #, fuzzy, c-format msgid "HHCSH026E %4.4X Error retrieving usage information\n" msgstr "HHC423I Fout %2$s bij schrijven naar bestand \"%1$s\"\n" #: shared.c:1187 #, fuzzy, c-format msgid "HHCSH027E %4.4X error writing track %d\n" msgstr "HHC423I Fout %2$s bij schrijven naar bestand \"%1$s\"\n" #: shared.c:1200 #, fuzzy, c-format msgid "HHCSH028E %4.4X remote error writing track %d: %2.2X-%2.2X\n" msgstr "HHC423I Fout %2$s bij schrijven naar bestand \"%1$s\"\n" #: shared.c:1285 #, fuzzy, c-format msgid "HHCSH029E %4.4X socket failed: %s\n" msgstr "HHC423I Fout %2$s bij schrijven naar bestand \"%1$s\"\n" #: shared.c:1301 #, fuzzy, c-format msgid "HHCSH030E %4.4X socket failed: %s\n" msgstr "HHC760I %4.4X create_thread fout: %s" #: shared.c:1319 #, fuzzy, c-format msgid "HHCSH031I %4.4X Connected to %s\n" msgstr "CPU%4.4X: Verbunden mit Channel-Set %4.4X\n" #: shared.c:1353 #, fuzzy, c-format msgid "HHCSH032E %4.4X Connect %s %d: %s\n" msgstr "CPU%4.4X: Verbunden mit Channel-Set %4.4X\n" #: shared.c:1524 #, fuzzy, c-format msgid "HHCSH033E %4.4X send error %d for %2.2X-%2.2X: %s\n" msgstr "HHC405I Fout %2$s bij lezen van bestand \"%1$s\"\n" #: shared.c:1551 #, fuzzy, c-format msgid "HHCSH034E %4.4X Not connected to %s\n" msgstr "CPU%4.4X: Verbunden mit Channel-Set %4.4X\n" #: shared.c:1561 #, fuzzy, c-format msgid "HHCSH035E %4.4X recv error %d: %s\n" msgstr "HHC405I Fout %2$s bij lezen van bestand \"%1$s\"\n" #: shared.c:1573 #, fuzzy, c-format msgid "HHCSH036E %4.4X Remote error %2.2X-%2.2X: %s\n" msgstr "HHC760I %4.4X create_thread fout: %s" #: shared.c:1679 #, fuzzy, c-format msgid "HHCSH037E uncompress error %d, off %d len %d\n" msgstr "*** Fehler beim Entpacken für Spur %d: %d\n" #: shared.c:1684 msgid "HHCSH038E data compressed using libz, unsupported\n" msgstr "" #: shared.c:1702 #, fuzzy, c-format msgid "HHCSH039E decompress error %d, off %d len %d\n" msgstr "*** Fehler beim De-Komprimieren für Spur %d: %d\n" #: shared.c:1707 msgid "HHCSH040E data compressed using bzip2, unsupported\n" msgstr "" #: shared.c:2282 #, fuzzy, c-format msgid "HHCSH041E %4.4X send error %d id=%d: %s\n" msgstr "HHC760I %4.4X create_thread fout: %s" #: shared.c:2321 #, c-format msgid "HHCSH042W %4.4X busy client being removed id=%d %s\n" msgstr "" #: shared.c:2353 #, fuzzy, c-format msgid "HHCSH043I %s disconnected from %4.4X id=%d\n" msgstr "HHC420I %s (%s) afgesloten van apparaat %4.4X (%s)\n" #: shared.c:2424 #, fuzzy, c-format msgid "HHCSH0474 %s connect failed\n" msgstr "HHC406I Fout %2$s bij zoeken in bestand \"%1$s\"\n" #: shared.c:2502 #, fuzzy, c-format msgid "HHCSH053I %s connected to %4.4X id=%d\n" msgstr "HHC420I %s (%s) afgesloten van apparaat %4.4X (%s)\n" #: shared.c:2518 #, fuzzy, c-format msgid "HHCSH045I Shared device %4.4X thread started: tid=" msgstr "HHC620I CPU%4.4X thread gestart: tid=%8.8lX, pid=%d, prioriteit=%d\n" #: shared.c:2587 #, fuzzy, c-format msgid "HHCSH046E select: %s\n" msgstr "HHC760I %4.4X create_thread fout: %s" #: shared.c:2621 #, fuzzy, c-format msgid "HHCSH047E %4.4X %s recv error id=%d\n" msgstr "%d Bytes gelesen von %s\n" #: shared.c:2652 #, fuzzy, c-format msgid "HHCSH048I Shared device %4.4X thread stopping\n" msgstr "HHC423I Fout %2$s bij schrijven naar bestand \"%1$s\"\n" #: shared.c:2719 #, fuzzy, c-format msgid "HHCSH049I Shared device %d.%d thread started: tid=" msgstr "HHC620I CPU%4.4X thread gestart: tid=%8.8lX, pid=%d, prioriteit=%d\n" #: shared.c:2728 #, fuzzy, c-format msgid "HHCSH050E inet socket: %s\n" msgstr "HHC423I Fout %2$s bij schrijven naar bestand \"%1$s\"\n" #: shared.c:2737 #, fuzzy, c-format msgid "HHCSH051W unix socket: %s\n" msgstr "HHC760I %4.4X create_thread fout: %s" #: shared.c:2760 #, c-format msgid "HHCSH052W Waiting for port %u to become free\n" msgstr "" #: shared.c:2767 #, fuzzy, c-format msgid "HHCSH053E inet bind: %s\n" msgstr "HHC760I %4.4X create_thread fout: %s" #: shared.c:2785 #, fuzzy, c-format msgid "HHCSH054W unix bind: %s\n" msgstr "HHC760I %4.4X create_thread fout: %s" #: shared.c:2797 #, fuzzy, c-format msgid "HHCSH055E inet listen: %s\n" msgstr "HHC760I %4.4X create_thread fout: %s" #: shared.c:2808 #, fuzzy, c-format msgid "HHCSH056W unix listen: %s\n" msgstr "HHC760I %4.4X create_thread fout: %s" #: shared.c:2821 #, c-format msgid "HHCSH057I Waiting for shared device requests on port %u\n" msgstr "" #: shared.c:2841 #, fuzzy, c-format msgid "HHCSH058E select: %s\n" msgstr "HHC760I %4.4X create_thread fout: %s" #: shared.c:2859 #, fuzzy, c-format msgid "HHCSH059E accept: %s\n" msgstr "HHC760I %4.4X create_thread fout: %s" #: shared.c:2866 #, fuzzy, c-format msgid "HHCSH060E malloc size %d: %s\n" msgstr "Ongeldige waarde: %s\n" #: shared.c:2877 #, fuzzy, c-format msgid "HHCSH061E serverConnect create_thread: %s\n" msgstr "Kann %s nicht öffnen: %s\n" #: shared.c:2916 #, fuzzy msgid "HHCSH062E Invalid or missing argument 1\n" msgstr "HHC422I Optie %s niet geldig\n" #: shared.c:2925 #, fuzzy msgid "HHCSH063E Invalid or missing keyword 2\n" msgstr "Ongeldige waarde: %s\n" #: shared.c:2943 #, fuzzy, c-format msgid "HHCSH064E Invalid or missing value %s\n" msgstr "Ongeldige waarde: %s\n" #: shared.c:2959 #, fuzzy, c-format msgid "HHCSH065E calloc() size=%d: %s\n" msgstr "Ongeldige waarde: %s\n" #: shared.c:2985 #, fuzzy, c-format msgid "HHCSH066E Invalid or missing keyword %s\n" msgstr "Ongeldige waarde: %s\n" #: shared.c:3060 shared.c:3067 msgid "HHCSH999E OPTION_SHARED_DEVICES not defined" msgstr "" #: sie.c:292 msgid "SIE: state descriptor " msgstr "" #: sie.c:317 #, fuzzy, c-format msgid "HHCCP079E CPU%4.4X: calloc failed for sie regs: %s\n" msgstr "HHC409I Fout %2$s bij lezen van bestand \"%1$s\"\n" #: sie.c:421 #, c-format msgid "SIE: zone %d: mso=" msgstr "" #: sie.c:735 #, c-format msgid "SIE: interception code %d\n" msgstr "" #: sockdev.c:81 msgid "HHCSD024E This build does not support Unix domain sockets.\n" msgstr "" #: sockdev.c:92 #, c-format msgid "HHCSD008E Socket pathname \"%s\" exceeds limit of %d\n" msgstr "" #: sockdev.c:103 #, fuzzy, c-format msgid "HHCSD009E Error creating socket for %s: %s\n" msgstr "HHC423I Fout %2$s bij schrijven naar bestand \"%1$s\"\n" #: sockdev.c:116 #, fuzzy, c-format msgid "HHCSD010E Failed to bind or listen on socket %s: %s\n" msgstr "HHC406I Fout %2$s bij zoeken in bestand \"%1$s\"\n" #: sockdev.c:169 #, fuzzy, c-format msgid "HHCSD011E Failed to determine IP address from %s\n" msgstr "HHC406I Fout %2$s bij zoeken in bestand \"%1$s\"\n" #: sockdev.c:187 #, fuzzy, c-format msgid "HHCSD012E Failed to determine port number from %s\n" msgstr "HHC406I Fout %2$s bij zoeken in bestand \"%1$s\"\n" #: sockdev.c:199 #, fuzzy, c-format msgid "HHCSD013E Error creating socket for %s: %s\n" msgstr "HHC409I Fout %2$s bij lezen van bestand \"%1$s\"\n" #: sockdev.c:211 #, fuzzy, c-format msgid "HHCSD014E Failed to bind or listen on socket %s: %s\n" msgstr "HHC406I Fout %2$s bij zoeken in bestand \"%1$s\"\n" #: sockdev.c:285 #, c-format msgid "" "HHCSD015E Connect to device %4.4X (%s) rejected; device busy or interrupt " "pending\n" msgstr "" #: sockdev.c:296 #, c-format msgid "" "HHCSD016E Connect to device %4.4X (%s) rejected; client %s (%s) still " "connected\n" msgstr "" #: sockdev.c:310 #, fuzzy, c-format msgid "HHCSD017E Connect to device %4.4X (%s) failed: %s\n" msgstr "HHC420I %s (%s) afgesloten van apparaat %4.4X (%s)\n" #: sockdev.c:336 #, fuzzy, c-format msgid "HHCSD018I %s (%s) connected to device %4.4X (%s)\n" msgstr "HHC420I %s (%s) afgesloten van apparaat %4.4X (%s)\n" #: sockdev.c:341 #, fuzzy, c-format msgid "HHCSD019I connected to device %4.4X (%s)\n" msgstr "HHC420I %s (%s) afgesloten van apparaat %4.4X (%s)\n" #: sockdev.c:416 #, fuzzy msgid "HHCSD020I Socketdevice listener thread started: tid=" msgstr "HHC620I CPU%4.4X thread gestart: tid=%8.8lX, pid=%d, prioriteit=%d\n" #: sockdev.c:444 #, fuzzy, c-format msgid "HHCSD021E select failed; errno=%d: %s\n" msgstr "HHC760I %4.4X create_thread fout: %s" #: sockdev.c:453 #, fuzzy msgid "HHCSD022I Socketdevice listener thread terminated\n" msgstr "HHC650I Controle paneel thread gestart: tid=%8.8lX, pid=%d\n" #: sockdev.c:478 #, fuzzy, c-format msgid "HHCSD001E Device %4.4X already bound to socket %s\n" msgstr "HHC423I Fout %2$s bij schrijven naar bestand \"%1$s\"\n" #: sockdev.c:487 #, fuzzy, c-format msgid "HHCSD002E bind_device malloc() failed for device %4.4X\n" msgstr "CCW Ablaufverfolgung ist %s für %4.4X\n" #: sockdev.c:495 #, fuzzy, c-format msgid "HHCSD003E bind_device strdup() failed for device %4.4X\n" msgstr "CCW Ablaufverfolgung ist %s für %4.4X\n" #: sockdev.c:533 #, fuzzy, c-format msgid "HHCSD023E Cannot create socketdevice thread: errno=%d: %s\n" msgstr "Kann %s nicht öffnen: %s\n" #: sockdev.c:548 #, fuzzy, c-format msgid "HHCSD004I Device %4.4X bound to socket %s\n" msgstr "HHC420I %s (%s) afgesloten van apparaat %4.4X (%s)\n" #: sockdev.c:568 #, fuzzy, c-format msgid "HHCSD005E Device %4.4X not bound to any socket\n" msgstr "HHC420I %s (%s) afgesloten van apparaat %4.4X (%s)\n" #: sockdev.c:576 #, fuzzy, c-format msgid "HHCSD006E Client %s (%s) still connected to device %4.4X (%s)\n" msgstr "HHC420I %s (%s) afgesloten van apparaat %4.4X (%s)\n" #: sockdev.c:588 #, fuzzy, c-format msgid "HHCSD007I Device %4.4X unbound from socket %s\n" msgstr "HHC420I %s (%s) afgesloten van apparaat %4.4X (%s)\n" #: stack.c:410 msgid "stack: Current stack entry at " msgstr "" #: stack.c:411 stack.c:450 stack.c:783 stack.c:796 stack.c:860 stack.c:899 #, c-format msgid "stack: et=%2.2X si=%2.2X rfs=%2.2X%2.2X nes=%2.2X%2.2X\n" msgstr "" #: stack.c:433 msgid "stack: Forward section header addr " msgstr "" #: stack.c:495 stack.c:782 msgid "stack: New stack entry at " msgstr "" #: stack.c:512 stack.c:520 stack.c:1163 stack.c:1171 #, c-format msgid "stack: GPR%d=" msgstr "" #: stack.c:544 stack.c:753 stack.c:1209 #, c-format msgid "stack: AR%d=" msgstr "" #: stack.c:566 #, c-format msgid "" "stack: PKM=%2.2X%2.2X SASN=%2.2X%2.2X EAX=%2.2X%2.2X PASN=%2.2X%2.2X \n" "stored at V:" msgstr "" #: stack.c:620 #, c-format msgid "stack: PSW=%2.2X%2.2X%2.2X%2.2X %2.2X%2.2X%2.2X%2.2X stored at V:" msgstr "" #: stack.c:698 #, c-format msgid "stack: PSW2=%2.2X%2.2X%2.2X%2.2X %2.2X%2.2X%2.2X%2.2X stored at V:" msgstr "" #: stack.c:725 #, c-format msgid "" "stack: SASTEIN=%2.2X%2.2X%2.2X%2.2X PASTEIN=%2.2X%2.2X%2.2X%2.2X \n" "stored at V:" msgstr "" #: stack.c:794 msgid "stack: Previous stack entry updated at A:" msgstr "" #: stack.c:805 stack.c:1421 msgid "stack: CR15=" msgstr "" #: stack.c:859 stack.c:883 msgid "stack: Stack entry located at " msgstr "" #: stack.c:1138 #, c-format msgid "stack: Unstacking registers %d-%d from " msgstr "" #: stack.c:1303 #, c-format msgid "" "stack: PKM=%2.2X%2.2X SASN=%2.2X%2.2X EAX=%2.2X%2.2X PASN=%2.2X%2.2X \n" "loaded from V:" msgstr "" #: stack.c:1340 #, c-format msgid "stack: PSW=%2.2X%2.2X%2.2X%2.2X %2.2X%2.2X%2.2X%2.2X loaded from V:" msgstr "" #: stack.c:1384 #, c-format msgid "" "stack: SASTEIN=%2.2X%2.2X%2.2X%2.2X PASTEIN=%2.2X%2.2X%2.2X%2.2X \n" "loaded from V:" msgstr "" #: tapecopy.c:39 #, c-format msgid "HHCTC017E SCSI tape not supported with this build\n" msgstr "" #: tapecopy.c:132 #, fuzzy, c-format msgid "HHCTC000I Abnormal termination\n" msgstr "HHC650I Controle paneel thread gestart: tid=%8.8lX, pid=%d\n" #: tapecopy.c:146 #, c-format msgid "HHCTC015I %s status: %8.8lX" msgstr "" #: tapecopy.c:171 #, c-format msgid "" "\n" "Copies a SCSI tape to or from an AWSTAPE disk file.\n" "\n" "Tapecopy reads a SCSI tape and outputs an AWSTAPE file representation\n" "of the tape, or else reads an AWSTAPE file and creates an identical copy\n" "of its contents on a tape mounted on a SCSI tape drive.\n" "\n" "Usage:\n" "\n" " tapecopy [tapedrive] [awsfile] or\n" " tapecopy [awsfile] [tapedrive]\n" "\n" "Where:\n" "\n" " tapedrive specifies the device filename of the SCSI tape drive.\n" " Must begin with /dev to be recognized.\n" " awsfile specifies the filename of the AWSTAPE disk file.\n" "\n" "The first filename is the input; the second is the output.\n" "\n" "If the input file is a SCSI tape, it is read and processed until physical " "EOD\n" "(end-of-data) is reached (i.e. it does not stop whenever multiple tapemarks " "or\n" "filemarks are read; it continues processing until the SCSI tape drive says\n" "there is no more data on the tape). The resulting AWSTAPE output disk file,\n" "when specified for the filename on a Hercules tape device configuration\n" "statement, can then be used instead in order for the Hercules guest O/S to\n" "read the exact same data without having to have a SCSI tape drive " "physically\n" "attached to the host system. This allows you to easily transfer SCSI tape " "data\n" "to other systems that may not have SCSI tape drives attached to them.\n" "\n" "The possible return codes and their meaning are:\n" "\n" " %2d Successful completion.\n" " %2d Invalid arguments or no arguments given.\n" " %2d Unable to open SCSI tape drive device file.\n" " %2d Unable to open AWSTAPE disk file.\n" " %2d Unrecoverable I/O error setting variable length block\n" " processing for SCSI tape device.\n" " %2d Unrecoverable I/O error rewinding SCSI tape device.\n" " %2d Unrecoverable I/O error obtaining status of SCSI device.\n" " %2d Unrecoverable I/O error reading block header\n" " from AWSTAPE disk file.\n" " %2d AWSTAPE block size too large.\n" " %2d Unrecoverable I/O error reading data block.\n" " %2d Unrecoverable I/O error writing tapemark.\n" " %2d Unrecoverable I/O error writing block header\n" " to AWSTAPE disk file.\n" " %2d Unrecoverable I/O error writing data block.\n" "\n" msgstr "" #: tapecopy.c:266 #, fuzzy, c-format msgid "HHCTC016E Error reading status of %s: rc=%d, errno=%d: %s\n" msgstr "HHC409I Fout %2$s bij lezen van bestand \"%1$s\"\n" #: tapecopy.c:295 #, fuzzy, c-format msgid "HHCTC011I End of tape.\n" msgstr "HHC403I Niet genoeg geheugen\n" #: tapecopy.c:299 #, fuzzy, c-format msgid "HHCTC008E Error reading %s: errno=%d: %s\n" msgstr "HHC409I Fout %2$s bij lezen van bestand \"%1$s\"\n" #: tapecopy.c:325 #, fuzzy, c-format msgid "HHCTC018I End of AWSTAPE input file.\n" msgstr "HHC403I Niet genoeg geheugen\n" #: tapecopy.c:330 #, fuzzy, c-format msgid "HHCTC019E Error reading AWSTAPE header from %s: rc=%d, errno=%d: %s\n" msgstr "HHC409I Fout %2$s bij lezen van bestand \"%1$s\"\n" #: tapecopy.c:346 #, c-format msgid "HHCTC020E AWSTAPE block too large on %s: block size=%d, maximum=%d\n" msgstr "" #: tapecopy.c:355 #, fuzzy, c-format msgid "HHCTC021E Error reading data block from %s: rc=%d, errno=%d: %s\n" msgstr "HHC409I Fout %2$s bij lezen van bestand \"%1$s\"\n" #: tapecopy.c:380 #, fuzzy, c-format msgid "HHCTC022E Error writing data block to %s: rc=%d, errno=%d: %s\n" msgstr "HHC423I Fout %2$s bij schrijven naar bestand \"%1$s\"\n" #: tapecopy.c:414 #, fuzzy, c-format msgid "HHCTC013E Error writing AWSTAPE header on %s: rc=%d, errno=%d: %s\n" msgstr "HHC409I Fout %2$s bij lezen van bestand \"%1$s\"\n" #: tapecopy.c:425 #, fuzzy, c-format msgid "HHCTC014E Error writing data block to %s: rc=%d, errno=%d: %s\n" msgstr "HHC423I Fout %2$s bij schrijven naar bestand \"%1$s\"\n" #: tapecopy.c:448 #, fuzzy, c-format msgid "HHCTC023E Error writing tapemark on %s: rc=%d, errno=%d: %s\n" msgstr "HHC409I Fout %2$s bij lezen van bestand \"%1$s\"\n" #: tapecopy.c:476 #, fuzzy, c-format msgid "HHCTC010E Error writing tapemark on %s: rc=%d, errno=%d, %s\n" msgstr "HHC423I Fout %2$s bij schrijven naar bestand \"%1$s\"\n" #: tapecopy.c:601 #, fuzzy, c-format msgid "HHCTC001E Error opening %s: errno=%d: %s\n" msgstr "HHC423I Fout %2$s bij openen bestand \"%1$s\"\n" #: tapecopy.c:614 #, fuzzy, c-format msgid "HHCTC005E Error setting attributes for %s: rc=%d, errno=%d: %s\n" msgstr "HHC423I Fout %2$s bij schrijven naar bestand \"%1$s\"\n" #: tapecopy.c:627 tapecopy.c:884 #, fuzzy, c-format msgid "HHCTC006E Error rewinding %s: rc=%d, errno=%d: %s\n" msgstr "HHC409I Fout %2$s bij lezen van bestand \"%1$s\"\n" #: tapecopy.c:644 #, fuzzy, c-format msgid "HHCTC003I %s device type: %s\n" msgstr "%d Geräte bearbeitet\n" #: tapecopy.c:647 #, fuzzy, c-format msgid "HHCTC003I %s device type: 0x%lX\n" msgstr "%d Geräte bearbeitet\n" #: tapecopy.c:657 #, fuzzy, c-format msgid "HHCTC004I %s tape density: %s\n" msgstr "HHC423I Fout %2$s bij openen bestand \"%1$s\"\n" #: tapecopy.c:660 #, fuzzy, c-format msgid "HHCTC004I %s tape density code: 0x%lX\n" msgstr "HHC423I Fout %2$s bij openen bestand \"%1$s\"\n" #: tapecopy.c:680 #, fuzzy, c-format msgid "HHCTC007E Error opening %s: errno=%d: %s\n" msgstr "HHC423I Fout %2$s bij openen bestand \"%1$s\"\n" #: tapecopy.c:779 msgid "HHCTC009I File %u: Blocks=%u, Bytes=%" msgstr "" #: tapecopy.c:792 #, c-format msgid " (tapemark)\n" msgstr "" #: tapecopy.c:827 #, c-format msgid "HHCTC012I %s\n" msgstr "" #: tapecopy.c:836 #, c-format msgid "File %u: Block %u\r" msgstr "" #: tapecopy.c:856 msgid "" "HHCTC000I Successful completion;\n" " Bytes read: %" msgstr "" #: tapecopy.c:868 msgid " Bytes written: %" msgstr "" #: tapedev.c:437 #, c-format msgid "HHCTA996I %4.4x - AWS Tape %s closed\n" msgstr "" #: tapedev.c:523 #, fuzzy, c-format msgid "HHCTA001E Error opening %s: %s\n" msgstr "HHC423I Fout %2$s bij openen bestand \"%1$s\"\n" #: tapedev.c:555 tapedev.c:718 #, fuzzy, c-format msgid "HHCTA002E Error seeking to offset %8.8lX in file %s: %s\n" msgstr "HHC409I Fout %2$s bij lezen van bestand \"%1$s\"\n" #: tapedev.c:570 #, fuzzy, c-format msgid "HHCTA003E Error reading block header at offset %8.8lX in file %s: %s\n" msgstr "HHC409I Fout %2$s bij lezen van bestand \"%1$s\"\n" #: tapedev.c:582 #, c-format msgid "" "HHCTA004E End of file (uninitialized tape) at offset %8.8lX in file %s\n" msgstr "" #: tapedev.c:594 #, fuzzy, c-format msgid "" "HHCTA004E Unexpected end of file in block header at offset %8.8lX in file %" "s\n" msgstr "HHC40I Onverwacht einde van bestand \"%s\"\n" #: tapedev.c:651 #, fuzzy, c-format msgid "HHCTA003E Error reading data block at offset %8.8lX in file %s: %s\n" msgstr "HHC409I Fout %2$s bij lezen van bestand \"%1$s\"\n" #: tapedev.c:665 #, fuzzy, c-format msgid "" "HHCTA004E Unexpected end of file in data block at offset %8.8lX in file %s\n" msgstr "HHC40I Onverwacht einde van bestand \"%s\"\n" #: tapedev.c:753 tapedev.c:780 #, fuzzy, c-format msgid "HHCTA995E Media full condition reached at offset %8.8lX in file %s\n" msgstr "HHC40I Onverwacht einde van bestand \"%s\"\n" #: tapedev.c:759 #, fuzzy, c-format msgid "HHCTA009E Error writing block header at offset %8.8lX in file %s: %s\n" msgstr "HHC409I Fout %2$s bij lezen van bestand \"%1$s\"\n" #: tapedev.c:786 tapedev.c:804 #, fuzzy, c-format msgid "HHCTA010E Error writing data block at offset %8.8lX in file %s: %s\n" msgstr "HHC423I Fout %2$s bij schrijven naar bestand \"%1$s\"\n" #: tapedev.c:856 #, fuzzy, c-format msgid "HHCTA011E Error seeking to offset %8.8lX in file %s: %s\n" msgstr "HHC409I Fout %2$s bij lezen van bestand \"%1$s\"\n" #: tapedev.c:887 #, fuzzy, c-format msgid "HHCTA012E Error writing block header at offset %8.8lX in file %s: %s\n" msgstr "HHC409I Fout %2$s bij lezen van bestand \"%1$s\"\n" #: tapedev.c:908 #, fuzzy, c-format msgid "HHCTA017E Error writing tape mark at offset %8.8lX in file %s: %s\n" msgstr "HHC423I Fout %2$s bij schrijven naar bestand \"%1$s\"\n" #: tapedev.c:1141 #, fuzzy, c-format msgid "HHCTA013E Error opening %s: %s(%s)\n" msgstr "HHC423I Fout %2$s bij openen bestand \"%1$s\"\n" #: tapedev.c:1189 #, fuzzy, c-format msgid "HHCTA075E Error seeking to start of %s: %s(%s)\n" msgstr "HHC407I Fout %2$s bij lezen van bestand \"%1$s\"\n" #: tapedev.c:1227 #, c-format msgid "HHCTA014E End of file (uninitialized tape) at block %8.8X in file %s\n" msgstr "" #: tapedev.c:1236 #, fuzzy, c-format msgid "HHCTA015E Error reading data block at block %8.8X in file %s: %s(%s)\n" msgstr "HHC409I Fout %2$s bij lezen van bestand \"%1$s\"\n" #: tapedev.c:1278 #, c-format msgid "HHCTA016E Error writing data block at block %8.8X in file %s: %s(%s)\n" msgstr "" #: tapedev.c:1294 msgid "TAPE EOT Handling: max capacity exceeded\n" msgstr "" #: tapedev.c:1297 msgid "TAPE EOT Handling: max capacity enforced\n" msgstr "" #: tapedev.c:1330 #, fuzzy, c-format msgid "HHCTA017E Error writing tape mark at block %8.8X in file %s: %s(%s)\n" msgstr "HHC423I Fout %2$s bij schrijven naar bestand \"%1$s\"\n" #: tapedev.c:1372 #, fuzzy, c-format msgid "HHCTA018E Error forward spacing at block %8.8X in file %s: %s(%s)\n" msgstr "HHC409I Fout %2$s bij lezen van bestand \"%1$s\"\n" #: tapedev.c:1427 #, fuzzy, c-format msgid "HHCTA019E Error reading data block at block %8.8X in file %s: %s(%s)\n" msgstr "HHC409I Fout %2$s bij lezen van bestand \"%1$s\"\n" #: tapedev.c:1459 #, fuzzy, c-format msgid "" "HHCTA020E Error forward spacing to next file at block %8.8X in file %s: %s(%" "s)\n" msgstr "HHC409I Fout %2$s bij lezen van bestand \"%1$s\"\n" #: tapedev.c:1524 #, c-format msgid "" "HHCTA021E Error back spacing to previous file at block %8.8X in file %s:\n" " %s(%s)\n" msgstr "" #: tapedev.c:1578 #, c-format msgid "" "HHC232I Invalid filename %s: TDF files must be in the TAPES subdirectory\n" msgstr "" #: tapedev.c:1591 #, fuzzy, c-format msgid "HHCTA039E Error opening TDF file %s: %s\n" msgstr "HHC404I Fout %2$s bij openen van bestand \"%1$s\"\n" #: tapedev.c:1600 #, fuzzy, c-format msgid "HHCTA040E %s fstat error: %s\n" msgstr "%d Bytes gelesen von %s\n" #: tapedev.c:1611 #, fuzzy, c-format msgid "HHCTA041E Cannot obtain buffer for TDF file %s: %s\n" msgstr "Kann %s nicht öffnen: %s\n" #: tapedev.c:1621 #, fuzzy, c-format msgid "HHCTA042E Error reading TDF file %s: %s\n" msgstr "HHC409I Fout %2$s bij lezen van bestand \"%1$s\"\n" #: tapedev.c:1634 #, c-format msgid "HHCTA043E %s is not a valid TDF file\n" msgstr "" #: tapedev.c:1653 #, fuzzy, c-format msgid "HHCTA044E Cannot obtain buffer for TDF array: %s\n" msgstr "Kann %s nicht öffnen: %s\n" #: tapedev.c:1702 #, fuzzy, c-format msgid "HHCTA045E Filename or format missing in line %d of file %s\n" msgstr "HHC351I Bestandsnaam niet opgegeven of ongeldig\n" #: tapedev.c:1714 #, fuzzy, c-format msgid "HHCTA046E Filename %s too long in line %d of file %s\n" msgstr "HHC401I Bestandsnaam \"%2$s\" te lang (maximum=%1$ud)\n" #: tapedev.c:1766 #, c-format msgid "HHCTA047E RECSIZE keyword missing in line %d of file %s\n" msgstr "" #: tapedev.c:1779 #, c-format msgid "HHCTA048E Invalid record size %s in line %d of file %s\n" msgstr "" #: tapedev.c:1793 #, c-format msgid "HHCTA049E Invalid record format %s in line %d of file %s\n" msgstr "" #: tapedev.c:1850 #, c-format msgid "HHCTA050E Attempt to access beyond end of tape %s\n" msgstr "" #: tapedev.c:1886 #, fuzzy, c-format msgid "HHCTA051E Error opening %s: %s\n" msgstr "HHC423I Fout %2$s bij openen bestand \"%1$s\"\n" #: tapedev.c:1929 #, fuzzy, c-format msgid "HHCTA052E Error seeking to offset %8.8lX in file %s: %s\n" msgstr "HHC409I Fout %2$s bij lezen van bestand \"%1$s\"\n" #: tapedev.c:1944 #, fuzzy, c-format msgid "HHCTA053E Error reading block header at offset %8.8lX in file %s: %s\n" msgstr "HHC409I Fout %2$s bij lezen van bestand \"%1$s\"\n" #: tapedev.c:1957 #, fuzzy, c-format msgid "" "HHCTA054E Unexpected end of file in block header at offset %8.8lX in file %" "s\n" msgstr "HHC40I Onverwacht einde van bestand \"%s\"\n" #: tapedev.c:1980 #, c-format msgid "HHCTA055E Invalid block header at offset %8.8lX in file %s\n" msgstr "" #: tapedev.c:2047 #, fuzzy, c-format msgid "HHCTA056E Error reading data block at offset %8.8lX in file %s: %s\n" msgstr "HHC409I Fout %2$s bij lezen van bestand \"%1$s\"\n" #: tapedev.c:2060 #, fuzzy, c-format msgid "" "HHCTA057E Unexpected end of file in data block at offset %8.8lX in file %s\n" msgstr "HHC40I Onverwacht einde van bestand \"%s\"\n" #: tapedev.c:2098 #, fuzzy, c-format msgid "HHCTA058E Error seeking to offset %8.8lX in file %s: %s\n" msgstr "HHC409I Fout %2$s bij lezen van bestand \"%1$s\"\n" #: tapedev.c:2113 #, fuzzy, c-format msgid "HHCTA059E Error reading data block at offset %8.8lX in file %s: %s\n" msgstr "HHC409I Fout %2$s bij lezen van bestand \"%1$s\"\n" #: tapedev.c:2172 #, fuzzy, c-format msgid "HHCTA060E Error seeking to offset %8.8lX in file %s: %s\n" msgstr "HHC409I Fout %2$s bij lezen van bestand \"%1$s\"\n" #: tapedev.c:2229 #, fuzzy, c-format msgid "HHCTA061E Error reading data block at offset %8.8lX in file %s: %s\n" msgstr "HHC409I Fout %2$s bij lezen van bestand \"%1$s\"\n" #: tapedev.c:2241 #, fuzzy, c-format msgid "" "HHCTA062E Unexpected end of file in data block at offset %8.8lX in file %s\n" msgstr "HHC40I Onverwacht einde van bestand \"%s\"\n" #: tapedev.c:2253 #, c-format msgid "HHCTA063E Invalid zero length block at offset %8.8lX in file %s\n" msgstr "" #: tapedev.c:2426 #, fuzzy, c-format msgid "HHCTA064E Error seeking to end of file %s: %s\n" msgstr "HHC409I Fout %2$s bij lezen van bestand \"%1$s\"\n" #: tapedev.c:2556 #, fuzzy, c-format msgid "HHCTA065E Error seeking to end of file %s: %s\n" msgstr "HHC409I Fout %2$s bij lezen van bestand \"%1$s\"\n" #: tapedev.c:2911 #, fuzzy, c-format msgid "HHCTA100I %4.4X: Now Displays: %s\n" msgstr "HHC420I %s (%s) afgesloten van apparaat %4.4X (%s)\n" #: tapedev.c:3116 #, c-format msgid "AutoMount: %s%s scratch tape being auto-unloaded on %4.4X = %s\n" msgstr "" #: tapedev.c:3120 #, c-format msgid "AutoMount: %s%s tape volume \"%s\" being auto-unloaded on %4.4X = %s\n" msgstr "" #: tapedev.c:3127 #, c-format msgid "AutoMount: %s%s scratch tape being auto-loaded on %4.4X = %s\n" msgstr "" #: tapedev.c:3131 #, c-format msgid "AutoMount: %s%s tape volume \"%s\" being auto-loaded on %4.4X = %s\n" msgstr "" #: tapedev.c:3150 #, c-format msgid "" "\n" "%s\n" "AUTOMOUNT: Unmount %sof %s%s scratch tape requested on %4.4X = %s\n" "%s\n" "\n" msgstr "" #: tapedev.c:3159 #, c-format msgid "" "\n" "%s\n" "AUTOMOUNT: Unmount %sof %s%s tape volume \"%s\" requested on %4.4X = %s\n" "%s\n" "\n" msgstr "" #: tapedev.c:3171 #, c-format msgid "" "\n" "%s\n" "AUTOMOUNT: Mount for %s%s scratch tape requested on %4.4X = %s\n" "%s\n" "\n" msgstr "" #: tapedev.c:3177 #, c-format msgid "" "\n" "%s\n" "AUTOMOUNT: Mount for %s%s tape volume \"%s\" requested on %4.4X = %s\n" "%s\n" "\n" msgstr "" #: tapedev.c:3266 #, fuzzy, c-format msgid "HHCTA099I %4.4X: Tape Display \"%s\" Until Unmounted\n" msgstr "Ongeldig frame adres %8.8X\n" #: tapedev.c:3292 #, fuzzy, c-format msgid "HHCTA099I %4.4X: Tape Display \"%s\" Until Mounted\n" msgstr "HHC420I %s (%s) afgesloten van apparaat %4.4X (%s)\n" #: tapedev.c:3345 #, fuzzy, c-format msgid "" "HHCTA099I %4.4X: Tape Display \"%s\" Until Unmounted, then \"%s\" Until " "Mounted\n" msgstr "Ongeldig frame adres %8.8X\n" #: tapedev.c:3354 #, fuzzy, c-format msgid "HHCTA099I %4.4X: Tape \"%s\" Until Mounted\n" msgstr "Ongeldig frame adres %8.8X\n" #: tapedev.c:4024 #, fuzzy, c-format msgid "" "HHCTA999E Device %4.4X: Unable to determine tape format type for %s: " "Internal error: Regcomp error %s on index %d\n" msgstr "HHC406I Fout %2$s bij zoeken in bestand \"%1$s\"\n" #: tapedev.c:4039 #, fuzzy, c-format msgid "" "HHCTA999E Device %4.4X: Unable to determine tape format type for %s: " "Internal error: Regexec error %s on index %d\n" msgstr "HHC406I Fout %2$s bij zoeken in bestand \"%1$s\"\n" #: tapedev.c:4085 #, fuzzy, c-format msgid "HHCTA999E Device %4.4X: Unable to determine tape format type for %s\n" msgstr "HHC406I Fout %2$s bij zoeken in bestand \"%1$s\"\n" #: tapedev.c:4095 #, fuzzy, c-format msgid "HHCTA998I Device %4.4X: %s is a %s\n" msgstr "HHC420I %s (%s) afgesloten van apparaat %4.4X (%s)\n" #: tapedev.c:4124 #, fuzzy, c-format msgid "HHCTA066I %s device %4.4X parameter: '%s'\n" msgstr "%d Geräte bearbeitet\n" #: tapedev.c:4128 #, fuzzy, c-format msgid "HHCTA067E Device %4.4X: %s - Unrecognized parameter: '%s'\n" msgstr "CPU%4.4X nicht konfiguriert\n" #: tapedev.c:4136 tapedev.c:4148 tapedev.c:4158 tapedev.c:4175 tapedev.c:4192 #: tapedev.c:4209 tapedev.c:4219 tapedev.c:4229 tapedev.c:4239 tapedev.c:4249 #: tapedev.c:4259 tapedev.c:4270 tapedev.c:4281 tapedev.c:4291 #, c-format msgid "HHCTA078E Option '%s' not valid for SCSI tape\n" msgstr "" #: tapedev.c:4164 #, c-format msgid "HHCTA068E Method must be within %u-%u\n" msgstr "" #: tapedev.c:4181 #, c-format msgid "HHCTA069E Level must be within %u-%u\n" msgstr "" #: tapedev.c:4198 #, c-format msgid "HHCTA070E Chunksize must be within %u-%u\n" msgstr "" #: tapedev.c:4302 tapedev.c:4313 #, fuzzy, c-format msgid "HHCTA078E Option '%s' not valid for %s\n" msgstr "Ongeldig frame adres %8.8X\n" #: tapedev.c:4323 #, fuzzy, c-format msgid "HHCTA071E Error in '%s' parameter\n" msgstr "HHC423I Fout %2$s bij openen bestand \"%1$s\"\n" #: tapedev.c:4371 #, c-format msgid "TAPE Autoloader - Adding global parm %s\n" msgstr "" #: tapedev.c:4441 #, c-format msgid "TAPE Autoloader: Adding tape entry %s\n" msgstr "" #: tapedev.c:4490 #, c-format msgid "TAPE: Autoloader file request fn=%s\n" msgstr "" #: tapedev.c:4778 #, c-format msgid "Unsupported device type specified %4.4x\n" msgstr "" #: tapedev.c:5239 #, c-format msgid "HHCTA072E Data chaining not supported for CCW %2.2X\n" msgstr "" #: tapedev.c:5958 msgid "HHCTA081I Locate block 0x%8.8" msgstr "" #: timer.c:195 #, fuzzy, c-format msgid "HHCTT001W Timer thread set priority %d failed: %s\n" msgstr "HHC406I Fout %2$s bij zoeken in bestand \"%1$s\"\n" #: timer.c:202 #, fuzzy msgid "HHCTT002I Timer thread started: tid=" msgstr "HHC650I Controle paneel thread gestart: tid=%8.8lX, pid=%d\n" #: timer.c:335 #, fuzzy msgid "HHCTT003I Timer thread ended\n" msgstr "HHC650I Controle paneel thread gestart: tid=%8.8lX, pid=%d\n" #: tuntap.c:133 #, c-format msgid "HHCTU001E %s timeout, possible older version?\n" msgstr "" #: tuntap.c:214 #, fuzzy, c-format msgid "HHCTU001E Unable to determine operating system type: %s\n" msgstr "HHC406I Fout %2$s bij zoeken in bestand \"%1$s\"\n" #: tuntap.c:226 #, fuzzy, c-format msgid "HHCTU002E Error opening TUN/TAP device: %s: %s\n" msgstr "HHC423I Fout %2$s bij openen bestand \"%1$s\"\n" #: tuntap.c:246 #, fuzzy, c-format msgid "HHCTU003E Error setting TUN/TAP mode: %s: %s\n" msgstr "HHC423I Fout %2$s bij openen bestand \"%1$s\"\n" #: tuntap.c:271 #, fuzzy, c-format msgid "HHCTU004E Invalid TUN/TAP device name: %s\n" msgstr "Ongeldig apparaat nummer\n" #: tuntap.c:304 tuntap.c:334 #, fuzzy, c-format msgid "HHCTU005E Invalid net device name specified: %s\n" msgstr "Ongeldig apparaat nummer\n" #: tuntap.c:344 #, fuzzy, c-format msgid "HHCTU006E %s: Invalid IP address: %s.\n" msgstr "Ongeldig frame adres %8.8X\n" #: tuntap.c:371 #, fuzzy, c-format msgid "HHCTU007E Invalid net device name specified: %s\n" msgstr "Ongeldig apparaat nummer\n" #: tuntap.c:381 #, fuzzy, c-format msgid "HHCTU008E %s: Invalid destination address: %s.\n" msgstr "Ongeldig frame adres %8.8X\n" #: tuntap.c:408 #, fuzzy, c-format msgid "HHCTU009E Invalid net device name specified: %s\n" msgstr "Ongeldig apparaat nummer\n" #: tuntap.c:418 #, fuzzy, c-format msgid "HHCTU010E %s: Invalid net mask: %s.\n" msgstr "Ongeldig apparaat nummer\n" #: tuntap.c:446 #, fuzzy, c-format msgid "HHCTU011E Invalid net device name specified: %s\n" msgstr "Ongeldig apparaat nummer\n" #: tuntap.c:455 #, fuzzy, c-format msgid "HHCTU012E %s: Invalid null or empty MTU.\n" msgstr "Ongeldig frame adres %8.8X\n" #: tuntap.c:464 #, fuzzy, c-format msgid "HHCTU013E %s: Invalid MTU: %s.\n" msgstr "Ongeldig frame adres %8.8X\n" #: tuntap.c:493 #, fuzzy, c-format msgid "HHCTU014E Invalid net device name specified: %s\n" msgstr "Ongeldig apparaat nummer\n" #: tuntap.c:502 #, fuzzy, c-format msgid "HHCTU015E %s: Invalid MAC address: %s.\n" msgstr "Ongeldig frame adres %8.8X\n" #: tuntap.c:532 tuntap.c:563 #, fuzzy, c-format msgid "HHCTU016E Invalid net device name specified: %s\n" msgstr "Ongeldig apparaat nummer\n" #: tuntap.c:613 #, fuzzy, c-format msgid "HHCTU017E Invalid net device name specified: %s\n" msgstr "Ongeldig apparaat nummer\n" #: tuntap.c:627 #, fuzzy, c-format msgid "HHCTU018E %s: Invalid destiniation address: %s.\n" msgstr "Ongeldig frame adres %8.8X\n" #: tuntap.c:639 #, fuzzy, c-format msgid "HHCTU019E %s: Invalid net mask: %s.\n" msgstr "Ongeldig apparaat nummer\n" #: tuntap.c:652 #, fuzzy, c-format msgid "HHCTU020E %s: Invalid gateway address: %s.\n" msgstr "Ongeldig frame adres %8.8X\n" #: tuntap.c:681 #, fuzzy, c-format msgid "HHCTU021E Invalid net device name specified: %s\n" msgstr "Ongeldig apparaat nummer\n" #: tuntap.c:695 #, fuzzy, c-format msgid "HHCTU022E %s: Invalid destiniation address: %s.\n" msgstr "Ongeldig frame adres %8.8X\n" #: tuntap.c:707 #, fuzzy, c-format msgid "HHCTU023E %s: Invalid net mask: %s.\n" msgstr "Ongeldig apparaat nummer\n" #: tuntap.c:720 #, fuzzy, c-format msgid "HHCTU024E %s: Invalid gateway address: %s.\n" msgstr "Ongeldig frame adres %8.8X\n" #: tuntap.c:821 #, fuzzy, c-format msgid "HHCTU025E Call to socketpair failed: %s\n" msgstr "HHC423I Fout %2$s bij schrijven naar bestand \"%1$s\"\n" #: tuntap.c:830 #, c-format msgid "HHCTU029I Executing '%s' to configure interface\n" msgstr "" #: tuntap.c:838 #, fuzzy, c-format msgid "HHCTU026E Call to fork failed: %s\n" msgstr "HHC423I Fout %2$s bij schrijven naar bestand \"%1$s\"\n" #: tuntap.c:862 msgid "HHCTU031I Closing %" msgstr "" #: tuntap.c:880 #, fuzzy, c-format msgid "HHCTU027E execl error on %s: %s.\n" msgstr "HHC419E Fout %2$s bij sluiten van bestand \"%1$s\"\n" #: tuntap.c:893 #, c-format msgid "HHCTU030I IFC_IOCtl called for %s on FDs %d %d\n" msgstr "" #: version.c:211 version.c:213 version.c:215 #, c-format msgid "%sVersion %s\n" msgstr "%sVersion %s\n" #: version.c:234 version.c:236 version.c:238 #, fuzzy, c-format msgid "Built on %s at %s\n" msgstr "Draaiend op %s %s%s %s %s\n" #: version.c:244 version.c:246 version.c:248 #, c-format msgid "Build information:\n" msgstr "Versionsdaten\n" #: vm.c:839 #, c-format msgid "HHCVM001I *%s* panel command issued by guest\n" msgstr "" #: vm.c:855 #, c-format msgid "HHCVM002I *%s* command complete\n" msgstr "" #: vm.c:859 msgid "HHCVM003I Host command processing disabled by configuration statement" msgstr "" #: vm.c:861 msgid "HHCVM004E Host command processing not included in engine build" msgstr "" #: w32chan.c:143 #, c-format msgid "HHCCP084E malloc(DEVIOREQUEST) failed; device=%4.4X, strerror=\"%s\"\n" msgstr "" #: w32chan.c:206 msgid "HHCCP085W *WARNING* max device threads exceeded.\n" msgstr "" #: w32chan.c:303 #, c-format msgid "" "HHCCP086E malloc(DEVTHREADPARMS) failed; device=%4.4X, strerror=\"%s\"\n" msgstr "" #: w32chan.c:312 #, c-format msgid "" "HHCCP087E CreateEvent(hShutdownEvent) failed; device=%4.4X, strerror=\"%s\"\n" msgstr "" #: w32chan.c:322 #, c-format msgid "" "HHCCP088E CreateEvent(hRequestQueuedEvent) failed; device=%4.4X, strerror=\"%" "s\"\n" msgstr "" #: w32chan.c:343 #, c-format msgid "" "HHCCP089E fthread_create(DeviceThread) failed; device=%4.4X, strerror=\"%s" "\"\n" msgstr "" #, fuzzy #~ msgid "x unknown space: %2.2x%2.2x%2.2x%2.2x%2.2x\n" #~ msgstr "" #~ "%4.4X ckddasd: Kopfdaten ungültig für Zyl. %d Spur %d %2.2x%2.2x%2.2x%" #~ "2.2x%2.2x\n" #, fuzzy #~ msgid " ECPS:VM Disabled in configuration\n" #~ msgstr "CPU%4.4X nicht konfiguriert\n" #, fuzzy #~ msgid "X %s\n" #~ msgstr " Spur abgeschnitten \n" #, fuzzy #~ msgid "HHCPN042E Missing device number\n" #~ msgstr "Geen apparaat nummer\n" #, fuzzy #~ msgid "HHCPN052E Missing device number\n" #~ msgstr "Geen apparaat nummer\n" #, fuzzy #~ msgid "HHCPN060E Missing device number\n" #~ msgstr "Geen apparaat nummer\n" #, fuzzy #~ msgid "HHCPN069E Missing device number\n" #~ msgstr "Geen apparaat nummer\n" #, fuzzy #~ msgid "HHCPN079E Missing device number\n" #~ msgstr "Geen apparaat nummer\n" #, fuzzy #~ msgid " CPU%4.4X: Waiting for mainlock: %s\n" #~ msgstr "CPU%4.4X: CPU Status: %s\n" #, fuzzy #~ msgid " SIE%4.4X: CPU interlock %sheld\n" #~ msgstr "CPU%4.4X: Mit keinem Channel-Set verbunden\n" #, fuzzy #~ msgid "HHCTA099I %4.4X: Tape Mount Request: \"%s\"\n" #~ msgstr "Ongeldig frame adres %8.8X\n" #, fuzzy #~ msgid "HHCTA099I %4.4X: Tape Demount/Mount Request: \"%s\", \"%s\"\n" #~ msgstr "Ongeldig frame adres %8.8X\n" #, fuzzy #~ msgid "HHCPN080E Invalid device number\n" #~ msgstr "Ongeldig apparaat nummer\n" #, fuzzy #~ msgid "HHCPN086E Unexpected operand: %s\n" #~ msgstr "Ongeldig operand: %s\n" #, fuzzy #~ msgid "HHCPN090E Unexpected operand: %s\n" #~ msgstr "Ongeldig operand: %s\n" #, fuzzy #~ msgid "cckdcdsk: error opening file %s: %s\n" #~ msgstr "HHC423I Fout %2$s bij openen bestand \"%1$s\"\n" #, fuzzy #~ msgid "cckdcdsk: lseek error: %s\n" #~ msgstr "HHC423I Fout %2$s bij openen bestand \"%1$s\"\n" #, fuzzy #~ msgid "cckdcdsk: read error: %s\n" #~ msgstr "HHC423I Fout %2$s bij openen bestand \"%1$s\"\n" #, fuzzy #~ msgid "cckdcomp: lseek error: %s\n" #~ msgstr "HHC423I Fout %2$s bij openen bestand \"%1$s\"\n" #, fuzzy #~ msgid "cckdcomp: read error: %s\n" #~ msgstr "HHC423I Fout %2$s bij openen bestand \"%1$s\"\n" #, fuzzy #~ msgid "cckdswap: error opening %s: %s\n" #~ msgstr "HHC423I Fout %2$s bij openen bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCPN015E Invalid device number\n" #~ msgstr "Ongeldig apparaat nummer\n" #, fuzzy #~ msgid "HHCPN022E Invalid device number\n" #~ msgstr "Ongeldig apparaat nummer\n" #, fuzzy #~ msgid "HHCPN032E Device number %s is invalid\n" #~ msgstr "HHC351I Bestandsnaam niet opgegeven of ongeldig\n" #, fuzzy #~ msgid "HHCPN043E Device number %s is invalid\n" #~ msgstr "HHC351I Bestandsnaam niet opgegeven of ongeldig\n" #, fuzzy #~ msgid "HHCPN061E Device number %s is invalid\n" #~ msgstr "HHC351I Bestandsnaam niet opgegeven of ongeldig\n" #, fuzzy #~ msgid "HHCPN063E Device number %s is invalid\n" #~ msgstr "HHC351I Bestandsnaam niet opgegeven of ongeldig\n" #, fuzzy #~ msgid "HHCPN064E Device number %s is invalid\n" #~ msgstr "HHC351I Bestandsnaam niet opgegeven of ongeldig\n" #, fuzzy #~ msgid "HHCPN070E Device number %s is invalid\n" #~ msgstr "HHC351I Bestandsnaam niet opgegeven of ongeldig\n" #, fuzzy #~ msgid "HHCPN082E Invalid device number\n" #~ msgstr "Ongeldig apparaat nummer\n" #, fuzzy #~ msgid "HHCPN094E Device number %s is invalid\n" #~ msgstr "HHC351I Bestandsnaam niet opgegeven of ongeldig\n" #, fuzzy #~ msgid "HHCLC030E Error in %s: %s: Invalid number of arguments\n" #~ msgstr "Ongeldig apparaat nummer\n" #, fuzzy #~ msgid "HHCHT009E fdopen: %s\n" #~ msgstr "HHC760I %4.4X create_thread fout: %s" #, fuzzy #~ msgid "" #~ "HHCCD130E %4.4X file[%d] write incomplete, offset 0x%llx: wrote %d " #~ "expected %d\n" #~ msgstr "HHC406I Fout %2$s bij zoeken in bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCHD012E No depency section in %s: %s\n" #~ msgstr "HHC423I Fout %2$s bij openen bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCHT06xE html_include: Error reading file %s: %s\n" #~ msgstr "HHC409I Fout %2$s bij lezen van bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCHT06xE html_include: Error writing file %s to socket: %s\n" #~ msgstr "Kann %s nicht öffnen: %s\n" #, fuzzy #~ msgid "HHCHT06xE html_include: Error closing file %s: %s\n" #~ msgstr "Kann %s nicht öffnen: %s\n" #, fuzzy #~ msgid "HHCHT06xE http_error: %s (%s)\n" #~ msgstr "%d Bytes gelesen von %s\n" #, fuzzy #~ msgid "HHCHT06xE http_error: Error fprintf'ing error document: %s\n" #~ msgstr "HHC423I Fout %2$s bij schrijven naar bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCHT06xE http_download: Error fprintf'ing 200 OK for file %s: %s\n" #~ msgstr "HHC423I Fout %2$s bij openen bestand \"%1$s\"\n" #, fuzzy #~ msgid "" #~ "HHCHT06xE http_download: Error fprintf'ing Content-Type for file %s: %s\n" #~ msgstr "HHC409I Fout %2$s bij lezen van bestand \"%1$s\"\n" #, fuzzy #~ msgid "" #~ "HHCHT06xE http_download: Error fprintf'ing Content-Length for file %s: %" #~ "s\n" #~ msgstr "HHC409I Fout %2$s bij lezen van bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCHT06xE http_download: Error reading file %s: %s\n" #~ msgstr "HHC409I Fout %2$s bij lezen van bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCHT06xE http_download: Error closing file %s: %s\n" #~ msgstr "HHC406I Fout %2$s bij zoeken in bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCHT06xE http_request_thread: Out of memory!\n" #~ msgstr "Kann %s nicht öffnen: %s\n" #, fuzzy #~ msgid "HHCHT06xE http_request_thread: select failed: %s\n" #~ msgstr "Kann %s nicht öffnen: %s\n" #, fuzzy #~ msgid "HHCHT06xE http_request_thread: Error closing socket stream: %s\n" #~ msgstr "Kann %s nicht öffnen: %s\n" #, fuzzy #~ msgid "HHCDU034E %s dasdcopy ftruncate error: %s\n" #~ msgstr "%d Bytes gelesen von %s\n" #, fuzzy #~ msgid "HHCLG010S Syslog write message pipe open failed: %s\n" #~ msgstr "HHC406I Fout %2$s bij zoeken in bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCLG011S Syslog read message pipe open failed: %s\n" #~ msgstr "HHC406I Fout %2$s bij zoeken in bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCLG013S Message pipe creation failed: %s\n" #~ msgstr "HHC406I Fout %2$s bij zoeken in bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCLG014S Message pipe open failed: %s\n" #~ msgstr "HHC406I Fout %2$s bij zoeken in bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCPN006E message pipe read: %s\n" #~ msgstr "HHC406I Fout %2$s bij zoeken in bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCTC002E Error reading status of %s: rc=%d, errno=%d: %s\n" #~ msgstr "HHC405I Fout %2$s bij lezen van bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCCD104E truncate re-open error: %s\n" #~ msgstr "HHC423I Fout %2$s bij openen bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCCD106E file[%d] hdr lseek error, offset %llx: %s\n" #~ msgstr "HHC406I Fout %2$s bij zoeken in bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCCD108E file[%d] chdr lseek error, offset %llx: %s\n" #~ msgstr "HHC406I Fout %2$s bij zoeken in bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCCD110E l1 table malloc error: %s\n" #~ msgstr "%d Bytes gelesen von %s\n" #, fuzzy #~ msgid "HHCCD111E file[%d] l1 lseek error, offset %llx: %s\n" #~ msgstr "HHC419E Fout %2$s bij sluiten van bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCCD112E file[%d] l1 read error, offset %llx: %s\n" #~ msgstr "%d Bytes gelesen von %s\n" #, fuzzy #~ msgid "HHCCD114E file[%d] l1 write error, offset %llx: %s\n" #~ msgstr "HHC406I Fout %2$s bij zoeken in bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCCD129E file[%d] l2[%d] read error offset %lld: %s\n" #~ msgstr "%d Bytes gelesen von %s\n" #, fuzzy #~ msgid "HHCCD134E file[%d] trk %d lseek error offset %llx: %s\n" #~ msgstr "HHC409I Fout %2$s bij lezen van bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCCD135E file[%d] trk %d read error offset %llx: %s\n" #~ msgstr "HHC409I Fout %2$s bij lezen van bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCCD137E file[%d] trk %d lseek error offset %llx: %s\n" #~ msgstr "HHC409I Fout %2$s bij lezen van bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCCD140E truncate fstat error: %s\n" #~ msgstr "%d Bytes gelesen von %s\n" #, fuzzy #~ msgid "HHCCD141E truncate re-open error: %s\n" #~ msgstr "HHC423I Fout %2$s bij openen bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCCD142E truncate ftruncate error: %s\n" #~ msgstr "%d Bytes gelesen von %s\n" #, fuzzy #~ msgid "HHCCD152E file[%d] lseek error offset %d: %s\n" #~ msgstr "HHC406I Fout %2$s bij zoeken in bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCCD153E file[%d] read error offset %d: %s\n" #~ msgstr "%d Bytes gelesen von %s\n" #, fuzzy #~ msgid "HHCCD154E shadow file[%d] write error offset %d: %s\n" #~ msgstr "HHC406I Fout %2$s bij zoeken in bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCCD155E file[%d] l1 malloc failed: %s\n" #~ msgstr "HHC406I Fout %2$s bij zoeken in bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCCD159E not a cckd device\n" #~ msgstr "%d Geräte bearbeitet\n" #, fuzzy #~ msgid "HHCCD168E file[%d] %s[%d] lseek error offset %lld: %s\n" #~ msgstr "HHC406I Fout %2$s bij zoeken in bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCCD170E file[%d] %s[%d] read error offset %lld: %s\n" #~ msgstr "%d Bytes gelesen von %s\n" #, fuzzy #~ msgid "HHCCD174E file[%d] %s[%d] write error offset %lld: %s\n" #~ msgstr "HHC406I Fout %2$s bij zoeken in bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCCD178E file[%d] l1[%d] write error offset %lld: %s\n" #~ msgstr "HHC406I Fout %2$s bij zoeken in bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCCD180E gcperc lseek error file[%d] offset 0x%llx: %s\n" #~ msgstr "HHC406I Fout %2$s bij zoeken in bestand \"%1$s\"\n" #, fuzzy #~ msgid "" #~ "HHCCD181E gcperc read error file[%d] offset 0x%llx (expected %d bytes)\n" #~ " error: %s\n" #~ msgstr "HHC406I Fout %2$s bij zoeken in bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCCD190E uncompress %d calloc() error: %s\n" #~ msgstr "%d Bytes gelesen von %s\n" #, fuzzy #~ msgid "HHCCD191E uncompress %d calloc() error: %s\n" #~ msgstr "HHC423I Fout %2$s bij openen bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCCD192E uncompress %d calloc() error: %s\n" #~ msgstr "%d Bytes gelesen von %s\n" #, fuzzy #~ msgid "HHCCF034W Expanded storage support not installed\n" #~ msgstr "CPU%4.4X nicht konfiguriert\n" #, fuzzy #~ msgid "HHCCF001S Error reading file %s line %d: %s\n" #~ msgstr "HHC409I Fout %2$s bij lezen van bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCCF003S Cannot open file %s: %s\n" #~ msgstr "Kann %s nicht öffnen: %s\n" #, fuzzy #~ msgid "HHCCF004S No device records in file %s\n" #~ msgstr "HHC406I Fout %2$s bij zoeken in bestand \"%1$s\"\n" #, fuzzy #~ msgid "" #~ "HHCCF059S Error in %s line %d: Missing symbol name on DEFSYM statement\n" #~ msgstr "HHC409I Fout %2$s bij lezen van bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCCF007S Error in %s line %d: Missing argument.\n" #~ msgstr "HHC409I Fout %2$s bij lezen van bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCCF029S Error in %s line %d: Invalid HTTP port number %s\n" #~ msgstr "Ongeldig apparaat nummer\n" #, fuzzy #~ msgid "HHCCF005S Error in %s line %d: Unrecognized argument %s\n" #~ msgstr "HHC409I Fout %2$s bij lezen van bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCCF008E Error in %s line %d: Unrecognized keyword %s\n" #~ msgstr "HHC409I Fout %2$s bij lezen van bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCCF009E Error in %s line %d: Incorrect number of operands\n" #~ msgstr "Geen apparaat nummer\n" #, fuzzy #~ msgid "HHCCF012S Error in %s line %d: %s is not a valid CPU version code\n" #~ msgstr "Ongeldig apparaat nummer\n" #, fuzzy #~ msgid "HHCCF051S Error in %s line %d: %s is not a valid serial number\n" #~ msgstr "Ongeldig apparaat nummer\n" #, fuzzy #~ msgid "HHCCF012S Error in %s line %d: %s is not a valid CPU model\n" #~ msgstr "Ongeldig apparaat nummer\n" #, fuzzy #~ msgid "" #~ "HHCCF016S Error in %s line %d: Invalid Hercules process group thread " #~ "priority %s\n" #~ msgstr "Ongeldig apparaat nummer\n" #, fuzzy #~ msgid "" #~ "HHCCF016S Error in %s line %d: Invalid TOD Clock thread priority %s\n" #~ msgstr "Ongeldig apparaat nummer\n" #, fuzzy #~ msgid "HHCCF016S Error in %s line %d: Invalid device thread priority %s\n" #~ msgstr "Ongeldig apparaat nummer\n" #, fuzzy #~ msgid "HHCCF018S Error in %s line %d: Invalid number of CPUs %s\n" #~ msgstr "Ongeldig apparaat nummer\n" #, fuzzy #~ msgid "HHCCF019S Error in %s line %d: Invalid number of VFs %s\n" #~ msgstr "Ongeldig apparaat nummer\n" #, fuzzy #~ msgid "HHCCF020W Vector Facility support not configured\n" #~ msgstr "CPU%4.4X nicht konfiguriert\n" #, fuzzy #~ msgid "HHCCF052S Error in %s line %d: %s: invalid argument\n" #~ msgstr "HHC409I Fout %2$s bij lezen van bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCCF027S Error in %s line %d: Invalid maximum device threads %s\n" #~ msgstr "Ongeldig apparaat nummer\n" #, fuzzy #~ msgid "" #~ "HHCCF062W Warning in %s line %d: Missing ECPSVM level value. 20 Assumed\n" #~ msgstr "HHC409I Fout %2$s bij lezen van bestand \"%1$s\"\n" #, fuzzy #~ msgid "" #~ "HHCCF051W Warning in %s line %d: Invalid ECPSVM level value : %s. 20 " #~ "Assumed\n" #~ msgstr "Ongeldige waarde: %s\n" #, fuzzy #~ msgid "" #~ "HHCCF051W Error in %s line %d: Invalid ECPSVM keyword : %s. NO Assumed\n" #~ msgstr "Ongeldig apparaat nummer\n" #, fuzzy #~ msgid "HHCCF029S Error in %s line %d: Invalid SHRDPORT port number %s\n" #~ msgstr "Ongeldig apparaat nummer\n" #, fuzzy #~ msgid "HHCCF030S Error in %s line %d: Invalid I/O delay value: %s\n" #~ msgstr "Ongeldige waarde: %s\n" #, fuzzy #~ msgid "HHCCF031S Error in %s line %d: Invalid ptt value: %s\n" #~ msgstr "Ongeldige waarde: %s\n" #, fuzzy #~ msgid "HHCCF064W Hercules set priority %d failed: %s\n" #~ msgstr "HHC406I Fout %2$s bij zoeken in bestand \"%1$s\"\n" #, fuzzy #~ msgid "" #~ "HHCCF035S Error in %s line %d: Missing device number or device type\n" #~ msgstr "Geen apparaat nummer\n" #, fuzzy #~ msgid "" #~ "HHCCF036S Error in %s line %d: %s is not a valid device number(s) " #~ "specification\n" #~ msgstr "Ongeldig apparaat nummer\n" #, fuzzy #~ msgid "HHCCP009E CPU MASK MISMATCH: %8.8X - %8.8X. Last instruction:\n" #~ msgstr "CPU MASK MISMATCH: %8.8X - %8.8X. Letzter Befehl war:\n" #, fuzzy #~ msgid "HHCCT039E %4.4X: Unable to allocate CTCBLK\n" #~ msgstr "HHC402I Fout %2$s bij benaderen bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCLC040E %4.4X AddDevice failed for LCSDEV %4.4X\n" #~ msgstr "CCW Ablaufverfolgung ist %s für %4.4X\n" #, fuzzy #~ msgid "HHCPN039E Missing argument\n" #~ msgstr "Geen apparaat nummer\n" #, fuzzy #~ msgid "HHCTA022E Error reading status of %s: %s\n" #~ msgstr "HHC409I Fout %2$s bij lezen van bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCTA024E Error opening %s: %s\n" #~ msgstr "HHC404I Fout %2$s bij openen van bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCTA025E Error reading status of %s: %s\n" #~ msgstr "HHC405I Fout %2$s bij lezen van bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCTA027I %s device type: 0x%lX\n" #~ msgstr "%d Geräte bearbeitet\n" #, fuzzy #~ msgid "HHCTA028I %s tape density: %s\n" #~ msgstr "HHC423I Fout %2$s bij openen bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCTA030E Error setting attributes for %s: %s\n" #~ msgstr "HHC423I Fout %2$s bij schrijven naar bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCTA031E Error rewinding %s: %s\n" #~ msgstr "HHC409I Fout %2$s bij lezen van bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCTA032E Error reading data block from %s: %s\n" #~ msgstr "HHC409I Fout %2$s bij lezen van bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCTA033E Error writing data block to %s: %s\n" #~ msgstr "HHC423I Fout %2$s bij schrijven naar bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCTA034E Error writing tapemark to %s: %s\n" #~ msgstr "HHC423I Fout %2$s bij schrijven naar bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCTA035E Forward space block error on %s: %s\n" #~ msgstr "HHC406I Fout %2$s bij zoeken in bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCTA036E Backspace block error on %s: %s\n" #~ msgstr "HHC406I Fout %2$s bij zoeken in bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCTA037E Forward space file error on %s: %s\n" #~ msgstr "HHC406I Fout %2$s bij zoeken in bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCTA038E Backspace file error on %s: %s\n" #~ msgstr "HHC406I Fout %2$s bij zoeken in bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCTA073E Error rewinding %s: %s\n" #~ msgstr "HHC407I Fout %2$s bij lezen van bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCTA076E Error unloading %s: %s\n" #~ msgstr "HHC409I Fout %2$s bij lezen van bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCTA077I Tape %4.4X unloaded\n" #~ msgstr "HHC420I %s (%s) afgesloten van apparaat %4.4X (%s)\n" #, fuzzy #~ msgid "HHCCF050I Device %4.4X defined as %4.4X\n" #~ msgstr "HHC420I %s (%s) afgesloten van apparaat %4.4X (%s)\n" #, fuzzy #~ msgid "HHCHD004I No registration section in %s: %s\n" #~ msgstr "HHC423I Fout %2$s bij schrijven naar bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCHD008I No registration section in %s: %s\n" #~ msgstr "HHC423I Fout %2$s bij schrijven naar bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCCP008I CPU%4.4X thread ended: tid=%p, pid=%d\n" #~ msgstr "HHC624I CPU%4.4X thread geeindigd: tid=%8.8lX, pid=%d\n" #, fuzzy #~ msgid "HHCDL001E Cannot open %s: %s\n" #~ msgstr "Kann %s nicht öffnen: %s\n" #, fuzzy #~ msgid "HHCDL002E Volume serial statement missing from %s\n" #~ msgstr "Ongeldig apparaat nummer\n" #, fuzzy #~ msgid "HHCDL003E Volume serial %s in %s line %d is not valid\n" #~ msgstr "Ongeldig apparaat nummer\n" #, fuzzy #~ msgid "HHCDL004E Device type %s in %s line %d is not recognized\n" #~ msgstr "Ongeldig apparaat nummer\n" #, fuzzy #~ msgid "HHCDL005E %s in %s line %d is not a valid cylinder count\n" #~ msgstr "Ongeldig apparaat nummer\n" #, fuzzy #~ msgid "HHCDL006I Creating %4.4X volume %s: %u trks/cyl, %u bytes/track\n" #~ msgstr "HHC404I Fout %2$s bij openen van bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCDL007E Cannot create %s\n" #~ msgstr "Kann %s nicht öffnen: %s\n" #, fuzzy #~ msgid "HHCDL008E Cannot open %s\n" #~ msgstr "Kann %s nicht öffnen: %s\n" #, fuzzy #~ msgid "HHCDL009I Loading %4.4X volume %s\n" #~ msgstr "HHC404I Fout %2$s bij openen van bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCDL010E Cannot obtain storage for DSCB pointer array: %s\n" #~ msgstr "Kann %s nicht öffnen: %s\n" #, fuzzy #~ msgid "HHCDL011E Invalid statement in %s line %d\n" #~ msgstr "HHC422I Optie %s niet geldig\n" #, fuzzy #~ msgid "HHCDL012I Creating dataset %s at cyl %d head %d\n" #~ msgstr "HHC409I Fout %2$s bij lezen van bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCDL013I Dataset %s contains %d track%s\n" #~ msgstr "Kann %s nicht öffnen: %s\n" #, fuzzy #~ msgid "HHCDL014I Free space starts at cyl %d head %d\n" #~ msgstr "HHC409I Fout %2$s bij lezen van bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCDL015W Volume exceeds %d cylinders\n" #~ msgstr "HHC410I Ponskaart %d bytes te groot in bestand \"%s\"\n" #, fuzzy #~ msgid "HHCDL018E Cannot read VOL1 record\n" #~ msgstr "Kann %s nicht öffnen: %s\n" #, fuzzy #~ msgid "HHCDL019E Cannot read %s line %d: %s\n" #~ msgstr "Kann %s nicht öffnen: %s\n" #, fuzzy #~ msgid "HHCDL020E Line too long in %s line %d\n" #~ msgstr "HHC401I Bestandsnaam \"%2$s\" te lang (maximum=%1$ud)\n" #, fuzzy #~ msgid "HHCDL021E DSNAME or initialization method missing\n" #~ msgstr "CCW Ablaufverfolgung ist %s für %4.4X\n" #, fuzzy #~ msgid "HHCDL022E Invalid initialization method: %s\n" #~ msgstr "Ongeldig frame adres %8.8X\n" #, fuzzy #~ msgid "HHCDL023E Initialization file name missing\n" #~ msgstr "CCW Ablaufverfolgung ist %s für %4.4X\n" #, fuzzy #~ msgid "HHCDL024E Invalid allocation units: %s\n" #~ msgstr "HHC422I Optie %s niet geldig\n" #, fuzzy #~ msgid "HHCDL025E Invalid primary space: %s\n" #~ msgstr "Ongeldig bereik: %s\n" #, fuzzy #~ msgid "HHCDL026E Invalid secondary space: %s\n" #~ msgstr "Ongeldige waarde: %s\n" #, fuzzy #~ msgid "HHCDL028E Invalid dataset organization: %s\n" #~ msgstr "HHC422I Optie %s niet geldig\n" #, fuzzy #~ msgid "HHCDL029E Invalid record format: %s\n" #~ msgstr "HHC422I Optie %s niet geldig\n" #, fuzzy #~ msgid "HHCDL030E Invalid logical record length: %s\n" #~ msgstr "HHC422I Optie %s niet geldig\n" #, fuzzy #~ msgid "HHCDL031E Invalid block size: %s\n" #~ msgstr "Ongeldige waarde: %s\n" #, fuzzy #~ msgid "HHCDL032E Invalid key length: %s\n" #~ msgstr "HHC422I Optie %s niet geldig\n" #, fuzzy #~ msgid "HHCDL033E CCHH=%4.4X%4.4X not found in extent table\n" #~ msgstr "HHC420I %s (%s) afgesloten van apparaat %4.4X (%s)\n" #, fuzzy #~ msgid "HHCDL034E Cannot open %s: %s\n" #~ msgstr "Kann %s nicht öffnen: %s\n" #, fuzzy #~ msgid "HHCDL035E Cannot read %s: %s\n" #~ msgstr "Kann %s nicht öffnen: %s\n" #, fuzzy #~ msgid "HHCDL036E %s is not a valid object file\n" #~ msgstr "HHC406I Fout %2$s bij zoeken in bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCDL038E TXT record in %s has invalid count %d\n" #~ msgstr "Ongeldig apparaat nummer\n" #, fuzzy #~ msgid "HHCDL039E IPL text in %s exceeds %d bytes\n" #~ msgstr "HHC410I Ponskaart %d bytes te groot in bestand \"%s\"\n" #, fuzzy #~ msgid "HHCDL043E %s cyl %d head %d read error\n" #~ msgstr "%d Bytes gelesen von %s\n" #, fuzzy #~ msgid "" #~ "HHCDL044E %s cyl %d head %d invalid track header %2.2X%2.2X%2.2X%2.2X%" #~ "2.2X\n" #~ msgstr "" #~ "%4.4X ckddasd: Kopfdaten ungültig für Zyl. %d Spur %d %2.2x%2.2x%2.2x%" #~ "2.2x%2.2x\n" #, fuzzy #~ msgid "HHCDL045E %s cyl %d head %d rec %d record not found\n" #~ msgstr "%d Bytes gelesen von %s\n" #, fuzzy #~ msgid "HHCDL046E Cannot update cyl %d head %d rec %d: Unmatched KL/DL\n" #~ msgstr "%d Bytes gelesen von %s\n" #, fuzzy #~ msgid "HHCDL047E %s cyl %d head %d read error\n" #~ msgstr "%d Bytes gelesen von %s\n" #, fuzzy #~ msgid "HHCDL049E Cannot obtain storage for DSCB: %s\n" #~ msgstr "Kann %s nicht öffnen: %s\n" #, fuzzy #~ msgid "HHCDL050E DSCB count exceeds %d, increase MAXDSCB\n" #~ msgstr "HHC410I Ponskaart %d bytes te groot in bestand \"%s\"\n" #, fuzzy #~ msgid "HHCDL051E Cannot obtain storage for DSCB: %s\n" #~ msgstr "Kann %s nicht öffnen: %s\n" #, fuzzy #~ msgid "HHCDL052E DSCB count exceeds %d, increase MAXDSCB\n" #~ msgstr "HHC410I Ponskaart %d bytes te groot in bestand \"%s\"\n" #, fuzzy #~ msgid "HHCDL053E Cannot obtain storage for DSCB: %s\n" #~ msgstr "Kann %s nicht öffnen: %s\n" #, fuzzy #~ msgid "HHCDL054E DSCB count exceeds %d, increase MAXDSCB\n" #~ msgstr "HHC410I Ponskaart %d bytes te groot in bestand \"%s\"\n" #, fuzzy #~ msgid "HHCDL056E Error reading VTOC cyl %d head %d\n" #~ msgstr "HHC409I Fout %2$s bij lezen van bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCDL057I VTOC starts at cyl %d head %d and is %d track%s\n" #~ msgstr "%d Bytes gelesen von %s\n" #, fuzzy #~ msgid "HHCDL060E Error reading track cyl %d head %d\n" #~ msgstr "HHC409I Fout %2$s bij lezen van bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCDL066E %s read error: %s\n" #~ msgstr "%d Bytes gelesen von %s\n" #, fuzzy #~ msgid "HHCDL067E %s invalid segment header: %2.2X%2.2X\n" #~ msgstr "Ongeldig frame adres %8.8X\n" #, fuzzy #~ msgid "HHCDL068E %s first segment indicator expected\n" #~ msgstr "HHC406I Fout %2$s bij zoeken in bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCDL069E %s first segment indicator not expected\n" #~ msgstr "HHC406I Fout %2$s bij zoeken in bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCDL071E %s read error: %s\n" #~ msgstr "%d Bytes gelesen von %s\n" #, fuzzy #~ msgid "HHCDL073E %s read error: %s\n" #~ msgstr "%d Bytes gelesen von %s\n" #, fuzzy #~ msgid "HHCDL074E %s read error: %s\n" #~ msgstr "%d Bytes gelesen von %s\n" #, fuzzy #~ msgid "HHCDL075E %s read error: %s\n" #~ msgstr "%d Bytes gelesen von %s\n" #, fuzzy #~ msgid "HHCDL076I File number: %d\n" #~ msgstr "Ongeldig apparaat nummer\n" #, fuzzy #~ msgid "HHCDL077E Invalid text unit at offset %4.4X\n" #~ msgstr "Ongeldig apparaat nummer\n" #, fuzzy #~ msgid "HHCDL080E Invalid text unit at offset %4.4X\n" #~ msgstr "Ongeldig apparaat nummer\n" #, fuzzy #~ msgid "HHCDL081E COPYR1 record length is invalid\n" #~ msgstr "HHC351I Bestandsnaam niet opgegeven of ongeldig\n" #, fuzzy #~ msgid "HHCDL087I COPYR2 record length is invalid\n" #~ msgstr "HHC351I Bestandsnaam niet opgegeven of ongeldig\n" #, fuzzy #~ msgid "HHCDL088I Invalid number of extents %d\n" #~ msgstr "Ongeldig apparaat nummer\n" #, fuzzy #~ msgid "HHCDL090I End of directory\n" #~ msgstr "HHC403I Niet genoeg geheugen\n" #, fuzzy #~ msgid "HHCDL091E Directory block record length is invalid\n" #~ msgstr "HHC351I Bestandsnaam niet opgegeven of ongeldig\n" #, fuzzy #~ msgid "HHCDL092E Cannot obtain storage for directory block: %s\n" #~ msgstr "Kann %s nicht öffnen: %s\n" #, fuzzy #~ msgid "HHCDL094E Directory block byte count is invalid\n" #~ msgstr "HHC351I Bestandsnaam niet opgegeven of ongeldig\n" #, fuzzy #~ msgid "HHCDL099E %s cyl %d head %d read error\n" #~ msgstr "%d Bytes gelesen von %s\n" #, fuzzy #~ msgid "" #~ "HHCDL100E %s cyl %d head %d invalid track header %2.2X%2.2X%2.2X%2.2X%" #~ "2.2X\n" #~ msgstr "" #~ "%4.4X ckddasd: Kopfdaten ungültig für Zyl. %d Spur %d %2.2x%2.2x%2.2x%" #~ "2.2x%2.2x\n" #, fuzzy #~ msgid "HHCDL101E %s cyl %d head %d rec %d note list record not found\n" #~ msgstr "%d Bytes gelesen von %s\n" #, fuzzy #~ msgid "HHCDL103E %s track read error cyl %d head %d\n" #~ msgstr "%d Bytes gelesen von %s\n" #, fuzzy #~ msgid "HHCDL105E Directory block byte count is invalid\n" #~ msgstr "HHC351I Bestandsnaam niet opgegeven of ongeldig\n" #, fuzzy #~ msgid "HHCDL106E Cannot open %s: %s\n" #~ msgstr "Kann %s nicht öffnen: %s\n" #, fuzzy #~ msgid "HHCDL107E Cannot obtain input buffer: %s\n" #~ msgstr "Kann %s nicht öffnen: %s\n" #, fuzzy #~ msgid "HHCDL108E Cannot obtain storage for directory block array: %s\n" #~ msgstr "Kann %s nicht öffnen: %s\n" #, fuzzy #~ msgid "HHCDL109E Cannot obtain storage for TTR table: %s\n" #~ msgstr "Kann %s nicht öffnen: %s\n" #, fuzzy #~ msgid "HHCDL110I Processing file %s\n" #~ msgstr "Geen apparaat nummer\n" #, fuzzy #~ msgid "HHCDL111I Control record: %s length %d\n" #~ msgstr "Kann %s nicht öffnen: %s\n" #, fuzzy #~ msgid "HHCDL113I Data record: length %d\n" #~ msgstr "HHC422I Optie %s niet geldig\n" #, fuzzy #~ msgid "HHCDL116E TTR count exceeds %d, increase MAXTTR\n" #~ msgstr "HHC410I Ponskaart %d bytes te groot in bestand \"%s\"\n" #, fuzzy #~ msgid "HHCDL117I Catalog block at cyl %d head %d rec %d\n" #~ msgstr "%d Bytes gelesen von %s\n" #, fuzzy #~ msgid "HHCDL118I Catalog block at cyl %d head %d rec %d\n" #~ msgstr "%d Bytes gelesen von %s\n" #, fuzzy #~ msgid "HHCDL119I Catalog block at cyl %d head %d rec %d\n" #~ msgstr "%d Bytes gelesen von %s\n" #, fuzzy #~ msgid "HHCDL120I DIP complete at cyl %d head %d rec %d\n" #~ msgstr "%d Bytes gelesen von %s\n" #, fuzzy #~ msgid "HHCDL125E Cannot open %s: %s\n" #~ msgstr "Kann %s nicht öffnen: %s\n" #, fuzzy #~ msgid "HHCDL126E Cannot stat %s: %s\n" #~ msgstr "Kann %s nicht öffnen: %s\n" #, fuzzy #~ msgid "HHCDL127E %s cyl %d head %d read error\n" #~ msgstr "%d Bytes gelesen von %s\n" #, fuzzy #~ msgid "HHCDL128E %s read error: %s\n" #~ msgstr "%d Bytes gelesen von %s\n" #, fuzzy #~ msgid "HHCDA025E error writing trk %d: lseek error: %s\n" #~ msgstr "HHC423I Fout %2$s bij schrijven naar bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCDA026E error writing trk %d: write error: %s\n" #~ msgstr "HHC423I Fout %2$s bij schrijven naar bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCDA059E Unexpected end of file in %s\n" #~ msgstr "HHC40I Onverwacht einde van bestand \"%s\"\n" #, fuzzy #~ msgid "HHCDA060E Read error in file %s: %s\n" #~ msgstr "HHC406I Fout %2$s bij zoeken in bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCDA071E Seek error in file %s: %s\n" #~ msgstr "HHC406I Fout %2$s bij zoeken in bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCPN068E Device number %s is invalid\n" #~ msgstr "HHC351I Bestandsnaam niet opgegeven of ongeldig\n" #, fuzzy #~ msgid "HHCPR009E %4.4X dup2 error: %s\n" #~ msgstr "HHC760I %4.4X create_thread fout: %s" #, fuzzy #~ msgid "" #~ "HHCTA005E Unexpected end of file in block header at offset %8.8lX in file " #~ "%s\n" #~ msgstr "HHC40I Onverwacht einde van bestand \"%s\"\n" #, fuzzy #~ msgid "HHCTA008E Error seeking to offset %8.8lX in file %s: %s\n" #~ msgstr "HHC409I Fout %2$s bij lezen van bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCTA074E Error seeking to start of %s: %s\n" #~ msgstr "HHC423I Fout %2$s bij schrijven naar bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCTA079E Error seeking to start of %s: %s\n" #~ msgstr "HHC423I Fout %2$s bij schrijven naar bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCTA080E Error seeking to start of %s: %s(%s)\n" #~ msgstr "HHC423I Fout %2$s bij schrijven naar bestand \"%1$s\"\n" #, fuzzy #~ msgid "LCS002E %4.4X invalid device name %s\n" #~ msgstr "Ongeldig apparaat nummer\n" #, fuzzy #~ msgid "LCS100W %4.4X: Error writing to %s: %s\n" #~ msgstr "HHC423I Fout %2$s bij schrijven naar bestand \"%1$s\"\n" #~ msgid "TIO modification executed CC=1\n" #~ msgstr "TIO modificatie uitgevoerd CC=1\n" #, fuzzy #~ msgid "Initialization failed for device %4.4X\n" #~ msgstr "CCW Ablaufverfolgung ist %s für %4.4X\n" #, fuzzy #~ msgid "HHC304I Unexpected end of file in %s\n" #~ msgstr "HHC40I Onverwacht einde van bestand \"%s\"\n" #, fuzzy #~ msgid "HHC314I Seek error in file %s: %s\n" #~ msgstr "HHC406I Fout %2$s bij zoeken in bestand \"%1$s\"\n" #~ msgid "HHC351I File name missing or invalid\n" #~ msgstr "HHC351I Bestandsnaam niet opgegeven of ongeldig\n" #~ msgid "HHC421I File name missing or invalid\n" #~ msgstr "HHC421I Bestandsnaam niet opgegeven of ongeldig\n" #~ msgid "HHC423I Error opening file %s: %s\n" #~ msgstr "HHC423I Fout %2$s bij openen bestand \"%1$s\"\n" #~ msgid " null track substituted\n" #~ msgstr " durch leere Spur ersetzt\n" #~ msgid " null track substituted \n" #~ msgstr " durch leere Spur ersetzt \n" #~ msgid "%s command invalid. Enter ? for help\n" #~ msgstr "%s is ungültig. ? zeigt Hilfetext\n" #~ msgid "" #~ "*** track %d R%d validation error !! %2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%" #~ "2.2x\n" #~ msgstr "" #~ "*** Spur %d R%d Validierungsfehler! %2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%" #~ "2.2x\n" #~ msgid "*** track %d size mismatch !! size found %d, expected %d\n" #~ msgstr "*** Spur %d hat falsche Länge!. Gefunden: %d, erwartet %d\n" #~ msgid "*** unknown compression for track %d: %d\n" #~ msgstr "*** Komprimierungsverfahren für Spur %d: %d ist unbekannt\n" #, fuzzy #~ msgid "cckd2ckd: error opening input file %s: %s\n" #~ msgstr "HHC423I Fout %2$s bij openen bestand \"%1$s\"\n" hercules-3.07/po/en@boldquot.header000644 000765 000765 00000002471 11143760531 021014 0ustar00jmaynardjmaynard000000 000000 # 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. # hercules-3.07/po/en@quot.header000644 000765 000765 00000002263 11143760531 020152 0ustar00jmaynardjmaynard000000 000000 # 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. # hercules-3.07/po/hercules.pot000644 000765 000765 00000377336 11143760531 017743 0ustar00jmaynardjmaynard000000 000000 # SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR Roger Bowler, Jan Jaeger, Jay Maynard, and others. # 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: \n" "POT-Creation-Date: 2007-06-23 14:23-0500\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" #: cache.c:399 #, c-format msgid "HHCCH001E calloc failed cache[%d] size %d: %s\n" msgstr "" #: cache.c:522 #, c-format msgid "HHCCH002W realloc increase failed cache[%d] size %d: %s\n" msgstr "" #: cache.c:541 #, c-format msgid "HHCCH003W realloc decrease failed cache[%d] size %d: %s\n" msgstr "" #: cache.c:558 #, c-format msgid "HHCCH004W buf calloc failed cache[%d] size %d: %s\n" msgstr "" #: cache.c:560 msgid "HHCCH005W releasing inactive buffer space\n" msgstr "" #: cache.c:565 #, c-format msgid "HHCCH006E Unable to calloc buf cache[%d] size %d: %s\n" msgstr "" #: cardpch.c:44 #, c-format msgid "HHCPU004E Error writing to %s: %s\n" msgstr "" #: cardpch.c:64 msgid "HHCPU001E File name missing or invalid\n" msgstr "" #: cardpch.c:102 #, c-format msgid "HHCPU002E Invalid argument: %s\n" msgstr "" #: cardpch.c:183 #, c-format msgid "HHCPU003E Error opening file %s: %s\n" msgstr "" #: cardrdr.c:92 msgid "HHCRD001E Out of memory\n" msgstr "" #: cardrdr.c:190 #, c-format msgid "HHCRD002E File name too long (max=%ud): \"%s\"\n" msgstr "" #: cardrdr.c:197 #, c-format msgid "HHCRD003E Unable to access file \"%s\": %s\n" msgstr "" #: cardrdr.c:207 msgid "HHCRD004E Out of memory\n" msgstr "" #: cardrdr.c:220 msgid "HHCRD005E Specify 'ascii' or 'ebcdic' (or neither) but not both\n" msgstr "" #: cardrdr.c:229 msgid "HHCRD006E Only one filename (sock_spec) allowed for socket devices\n" msgstr "" #: cardrdr.c:244 #, c-format msgid "HHCRD007I Defaulting to 'ascii' for socket device %4.4X\n" msgstr "" #: cardrdr.c:252 msgid "HHCRD008W 'multifile' option ignored: only one file specified\n" msgstr "" #: cardrdr.c:265 #, c-format msgid "HHCRD009E File name too long (max=%ud): \"%s\"\n" msgstr "" #: cardrdr.c:279 #, c-format msgid "HHCRD010E Unable to access file \"%s\": %s\n" msgstr "" #: cardrdr.c:360 #, c-format msgid "HHCRD011E Close error on file \"%s\": %s\n" msgstr "" #: cardrdr.c:369 #, c-format msgid "HHCRD012I %s (%s) disconnected from device %4.4X (%s)\n" msgstr "" #: cardrdr.c:468 #, c-format msgid "HHCRD013E Error opening file %s: %s\n" msgstr "" #: cardrdr.c:490 #, c-format msgid "HHCRD014E Error reading file %s: %s\n" msgstr "" #: cardrdr.c:523 #, c-format msgid "HHCRD015E Seek error in file %s: %s\n" msgstr "" #: cardrdr.c:596 #, c-format msgid "HHCRD016E Error reading file %s: %s\n" msgstr "" #: cardrdr.c:599 #, c-format msgid "HHCRD017E Unexpected end of file on %s\n" msgstr "" #: cardrdr.c:672 #, c-format msgid "HHCRD018E Error reading file %s: %s\n" msgstr "" #: cardrdr.c:700 #, c-format msgid "HHCRD019E Card image exceeds %d bytes in file %s\n" msgstr "" #: cckdcdsk.c:139 #, c-format msgid "" "\n" "cckdcdsk [-v] [-f] [-level] [-ro] file1 [file2 ...]\n" "\n" " -v display version and exit\n" "\n" " -f force check even if OPENED bit is on\n" "\n" " level is a digit 0 - 3:\n" " -0 -- minimal checking\n" " -1 -- normal checking\n" " -3 -- maximal checking\n" "\n" " -ro open file readonly, no repairs\n" "\n" msgstr "" #: cckddasd.c:322 #, c-format msgid "HHCCD101E %4.4X error initializing shadow files\n" msgstr "" #: cckddasd.c:586 #, c-format msgid "HHCCD130E %4.4X file[%d] %s open error: %s\n" msgstr "" #: cckddasd.c:621 #, c-format msgid "HHCCD130E %4.4X file[%d] close error: %s\n" msgstr "" #: cckddasd.c:649 cckddasd.c:690 msgid "HHCCD130E %4.4X file[%d] lseek error, offset 0x%" msgstr "" #: cckddasd.c:660 msgid "HHCCD130E %4.4X file[%d] read error, offset 0x%" msgstr "" #: cckddasd.c:663 msgid "HHCCD130E %4.4X file[%d] read incomplete, offset 0x%" msgstr "" #: cckddasd.c:700 msgid "HHCCD130E %4.4X file[%d] write error, offset 0x%" msgstr "" #: cckddasd.c:703 msgid "HHCCD130E %4.4X file[%d] write incomplete, offset 0x%" msgstr "" #: cckddasd.c:729 msgid "HHCCD130E %4.4X file[%d] ftruncate error, offset 0x%" msgstr "" #: cckddasd.c:751 #, c-format msgid "HHCCD130E %4.4X malloc error, size %d: %s\n" msgstr "" #: cckddasd.c:772 #, c-format msgid "HHCCD130E %4.4X calloc error, size %d: %s\n" msgstr "" #: cckddasd.c:1518 #, c-format msgid "HHCCD001I Readahead thread %d started: tid=" msgstr "" #: cckddasd.c:1569 #, c-format msgid "HHCCD011I Readahead thread %d stopping: tid=" msgstr "" #: cckddasd.c:1719 #, c-format msgid "HHCCD002I Writer thread %d started: tid=" msgstr "" #: cckddasd.c:1841 #, c-format msgid "HHCCD012I Writer thread %d stopping: tid=" msgstr "" #: cckddasd.c:1979 #, c-format msgid "HHCCD102E %4.4X file[%d] get space error, size exceeds %lldM\n" msgstr "" #: cckddasd.c:2488 #, c-format msgid "HHCCD110E %4.4X file[%d] devhdr id error\n" msgstr "" #: cckddasd.c:3216 #, c-format msgid "HHCCD121E %4.4X file[%d] trklen err for %2.2x%2.2x%2.2x%2.2x%2.2x\n" msgstr "" #: cckddasd.c:3385 #, c-format msgid "" "HHCCD122E %4.4X file[%d] invalid byte 0 trk %d: buf %2.2x%2.2x%2.2x%2.2x%" "2.2x\n" msgstr "" #: cckddasd.c:3407 #, c-format msgid "" "HHCCD123E %4.4X file[%d] invalid byte 0 blkgrp %d: buf %2.2x%2.2x%2.2x%2.2x%" "2.2x\n" msgstr "" #: cckddasd.c:3422 #, c-format msgid "" "HHCCD124E %4.4X file[%d] invalid %s hdr %s %d: %s compression unsupported\n" msgstr "" #: cckddasd.c:3430 #, c-format msgid "" "HHCCD125E %4.4X file[%d] invalid %s hdr %s %d buf %p:%2.2x%2.2x%2.2x%2.2x%" "2.2x\n" msgstr "" #: cckddasd.c:3584 #, c-format msgid "" "HHCCD142E %4.4X file[%d] shadow file name %s\n" " collides with %4.4X file[%d] name %s\n" msgstr "" #: cckddasd.c:3629 #, c-format msgid "" "HHCCD151E %4.4X file[%d] error re-opening %s readonly\n" " %s\n" msgstr "" #: cckddasd.c:3657 #, c-format msgid "HHCCD161E %4.4X file[%d] no shadow file name\n" msgstr "" #: cckddasd.c:3665 #, c-format msgid "HHCCD161E %4.4X file[%d] max shadow files exceeded\n" msgstr "" #: cckddasd.c:3748 #, c-format msgid "HHCCD160E %4.4X not a cckd device\n" msgstr "" #: cckddasd.c:3778 #, c-format msgid "HHCCD161E %4.4X file[%d] error adding shadow file\n" msgstr "" #: cckddasd.c:3787 #, c-format msgid "HHCCD162I %4.4X file[%d] %s added\n" msgstr "" #: cckddasd.c:3834 #, c-format msgid "HHCCD170E %4.4X not a cckd device\n" msgstr "" #: cckddasd.c:3840 #, c-format msgid "HHCCD171E %4.4X file[%d] cannot remove base file\n" msgstr "" #: cckddasd.c:3884 #, c-format msgid "" "HHCCD172E %4.4X file[%d] not merged, file[%d] cannot be opened read-write%s\n" msgstr "" #: cckddasd.c:3898 #, c-format msgid "HHCCD173E %4.4X file[%d] not merged, file[%d] check failed\n" msgstr "" #: cckddasd.c:3911 #, c-format msgid "HHCCD174E %4.4X file[%d] not merged, file not hardened\n" msgstr "" #: cckddasd.c:4076 #, c-format msgid "HHCCD181I %4.4X shadow file [%d] successfully %s%s\n" msgstr "" #: cckddasd.c:4108 #, c-format msgid "HHCCD201W %4.4X device is not a shadow file\n" msgstr "" #: cckddasd.c:4113 #, c-format msgid "HHCCD202W %4.4X file shadowing not activated\n" msgstr "" #: cckddasd.c:4121 #, c-format msgid "HHCCD203W %4.4X shadowing is already active\n" msgstr "" #: cckddasd.c:4130 #, c-format msgid "HHCCD204I %4.4X shadow file name set to %s\n" msgstr "" #: cckddasd.c:4148 #, c-format msgid "HHCCD205W %4.4X device is not a shadow file\n" msgstr "" #: cckddasd.c:4213 #, c-format msgid "HHCCD206W %4.4X device is not a shadow file\n" msgstr "" #: cckddasd.c:4230 msgid "" "HHCCD210I size free nbr st reads writes l2reads hits " "switches\n" msgstr "" #: cckddasd.c:4232 msgid "" "HHCCD211I readaheads " "misses\n" msgstr "" #: cckddasd.c:4233 msgid "" "HHCCD212I " "--------------------------------------------------------------------\n" msgstr "" #: cckddasd.c:4236 msgid "HHCCD213I [*] %10" msgstr "" #: cckddasd.c:4241 #, c-format msgid "" "HHCCD214I %7d %7d\n" msgstr "" #: cckddasd.c:4245 #, c-format msgid "HHCCD215I %s\n" msgstr "" #: cckddasd.c:4246 msgid "HHCCD216I [0] %10" msgstr "" #: cckddasd.c:4253 #, c-format msgid "HHCCD217I %s\n" msgstr "" #: cckddasd.c:4258 msgid "HHCCD218I [%d] %10" msgstr "" #: cckddasd.c:4357 msgid "HHCCD003I Garbage collector thread started: tid=" msgstr "" #: cckddasd.c:4465 msgid "HHCCD013I Garbage collector thread stopping: tid=" msgstr "" #: cckddasd.c:4690 msgid "HHCCD190E %4.4X file[%d] offset 0x%" msgstr "" #: cckddasd.c:4960 #, c-format msgid "" "HHCCD193E %4.4X file[%d] uncompress error trk %d: %2.2x%2.2x%2.2x%2.2x%2.2x\n" msgstr "" #: cckddasd.c:4963 #, c-format msgid "HHCCD194E %4.4X file[%d] %s compression not supported\n" msgstr "" #: cckddasd.c:5488 msgid "HHCCD900I print_itrace\n" msgstr "" #: cckddiag.c:138 #, c-format msgid "lseek to pos 0x%8.8x error: %s\n" msgstr "" #: cckddiag.c:154 #, c-format msgid "cckddiag: read error: %s\n" msgstr "" #: cckddiag.c:509 #, c-format msgid "cckddiag: error opening file %s: %s\n" msgstr "" #: channel.c:125 #, c-format msgid "HHCCP048I %4.4X:CCW=%2.2X%2.2X%2.2X%2.2X %2.2X%2.2X%2.2X%2.2X%s\n" msgstr "" #: channel.c:138 #, c-format msgid "HHCCP049I %4.4X:Stat=%2.2X%2.2X Count=%2.2X%2.2X CCW=%2.2X%2.2X%2.2X\n" msgstr "" #: channel.c:151 #, c-format msgid "" "HHCCP050I %4.4X:SCSW=%2.2X%2.2X%2.2X%2.2X Stat=%2.2X%2.2X Count=%2.2X%2.2X " "CCW=%2.2X%2.2X%2.2X%2.2X\n" msgstr "" #: channel.c:260 #, c-format msgid "HHCCP051I %4.4X: Test I/O\n" msgstr "" #: channel.c:325 msgid "HHCCP052I TIO modification executed CC=1\n" msgstr "" #: channel.c:362 #, c-format msgid "HHCCP053I %4.4X: Halt I/O\n" msgstr "" #: channel.c:416 msgid "HHCCP054I HIO modification executed CC=1\n" msgstr "" #: channel.c:787 #, c-format msgid "HHCCP055I %4.4X: Clear subchannel\n" msgstr "" #: channel.c:888 #, c-format msgid "HHCCP056I %4.4X: Halt subchannel\n" msgstr "" #: channel.c:910 #, c-format msgid "HHCCP057I %4.4X: Halt subchannel: cc=1\n" msgstr "" #: channel.c:920 #, c-format msgid "HHCCP058I %4.4X: Halt subchannel: cc=2\n" msgstr "" #: channel.c:1011 #, c-format msgid "HHCCP059I %4.4X: Halt subchannel: cc=0\n" msgstr "" #: channel.c:1049 #, c-format msgid "HHCCP060I %4.4X: Resume subchannel: cc=1\n" msgstr "" #: channel.c:1063 #, c-format msgid "HHCCP061I %4.4X: Resume subchannel: cc=2\n" msgstr "" #: channel.c:1086 #, c-format msgid "HHCCP062I %4.4X: Resume subchannel: cc=0\n" msgstr "" #: channel.c:1844 msgid "HHCCP078I %4.4X:MIDAW=%2.2X %4.4" msgstr "" #: channel.c:1943 msgid "HHCCP063I %4.4X:IDAW=%8.8" msgstr "" #: channel.c:1948 msgid "HHCCP064I %4.4X:IDAW=%16.16" msgstr "" #: channel.c:2065 #, c-format msgid "HHCCP065I DEV%4.4X: attention signalled\n" msgstr "" #: channel.c:2077 #, c-format msgid "HHCCP066I DEV%4.4X: attention\n" msgstr "" #: channel.c:2302 #, c-format msgid "HHCCP067E %4.4X create_thread error: %s" msgstr "" #: channel.c:2325 #, c-format msgid "HHCCP068E %4.4X create_thread error: %s" msgstr "" #: channel.c:2518 #, c-format msgid "HHCCP069I Device %4.4X initial status interrupt\n" msgstr "" #: channel.c:2557 #, c-format msgid "HHCCP070I Device %4.4X attention completed\n" msgstr "" #: channel.c:2623 #, c-format msgid "HHCCP071I Device %4.4X clear completed\n" msgstr "" #: channel.c:2678 #, c-format msgid "HHCCP072I Device %4.4X halt completed\n" msgstr "" #: channel.c:2856 #, c-format msgid "HHCCP073I Device %4.4X suspended\n" msgstr "" #: channel.c:2914 #, c-format msgid "HHCCP074I Device %4.4X resumed\n" msgstr "" #: channel.c:3128 #, c-format msgid "HHCCP075I %4.4X:Stat=%2.2X%2.2X Count=%4.4X %s\n" msgstr "" #: channel.c:3134 #, c-format msgid "" "HHCCP076I %4.4X:Sense=%2.2X%2.2X%2.2X%2.2X %2.2X%2.2X%2.2X%2.2X %2.2X%2.2X%" "2.2X%2.2X %2.2X%2.2X%2.2X%2.2X %2.2X%2.2X%2.2X%2.2X %2.2X%2.2X%2.2X%2.2X\n" msgstr "" #: channel.c:3149 #, c-format msgid "HHCCP077I %4.4X:Sense=%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n" msgstr "" #: ckddasd.c:237 msgid "HHCDA001E File name missing or invalid\n" msgstr "" #: ckddasd.c:255 #, c-format msgid "HHCDA002E %4.4X:File not found or invalid\n" msgstr "" #: ckddasd.c:357 #, c-format msgid "HHCDA003E parameter %d is invalid: %s\n" msgstr "" #: ckddasd.c:368 #, c-format msgid "HHCDA004I opening %s readonly%s\n" msgstr "" #: ckddasd.c:382 #, c-format msgid "HHCDA005E %s open error: %s\n" msgstr "" #: ckddasd.c:391 #, c-format msgid "HHCDA006E %s not in a single file for shadowing\n" msgstr "" #: ckddasd.c:400 #, c-format msgid "HHCDA007E %s fstat error: %s\n" msgstr "" #: ckddasd.c:410 #, c-format msgid "HHCDA008E %s read error: %s\n" msgstr "" #: ckddasd.c:413 #, c-format msgid "HHCDA09E %s CKD header incomplete\n" msgstr "" #: ckddasd.c:423 #, c-format msgid "HHCDA010E %s CKD header invalid\n" msgstr "" #: ckddasd.c:432 #, c-format msgid "HHCDA011E %s Only 1 CCKD file allowed\n" msgstr "" #: ckddasd.c:447 #, c-format msgid "HHCDA012E %s read error: %s\n" msgstr "" #: ckddasd.c:452 #, c-format msgid "HHCDA013E %s CCKD header incomplete\n" msgstr "" #: ckddasd.c:510 #, c-format msgid "HHCDA014E %s CKD file out of sequence\n" msgstr "" #: ckddasd.c:517 #, c-format msgid "HHCDA015I %s seq=%d cyls=%d-%d\n" msgstr "" #: ckddasd.c:531 #, c-format msgid "HHCDA016E %s heads=%d trklen=%d, expected heads=%d trklen=%d\n" msgstr "" #: ckddasd.c:544 #, c-format msgid "HHCDA017E %s CKD header inconsistent with file size\n" msgstr "" #: ckddasd.c:552 #, c-format msgid "HHCDA018E %s CKD header high cylinder incorrect\n" msgstr "" #: ckddasd.c:578 #, c-format msgid "HHCDA019E %s exceeds maximum %d CKD files\n" msgstr "" #: ckddasd.c:589 #, c-format msgid "HHCDA020I %s cyls=%d heads=%d tracks=%d trklen=%d\n" msgstr "" #: ckddasd.c:611 #, c-format msgid "HHCDA021E %4.4X device type %4.4X not found in dasd table\n" msgstr "" #: ckddasd.c:620 #, c-format msgid "HHCDA022E %4.4X control unit %s not found in dasd table\n" msgstr "" #: ckddasd.c:702 #, c-format msgid "HHCDA023I %4.4X cache hits %d, misses %d, waits %d\n" msgstr "" #: ckddasd.c:785 #, c-format msgid "HHCDA024I read trk %d cur trk %d\n" msgstr "" #: ckddasd.c:814 #, c-format msgid "HHCDA025I read track: updating track %d\n" msgstr "" #: ckddasd.c:825 #, c-format msgid "HHCDA026E error writing trk %d: lseek error: %s\n" msgstr "" #: ckddasd.c:844 #, c-format msgid "HHCDA027E error writing trk %d: write error: %s\n" msgstr "" #: ckddasd.c:886 #, c-format msgid "HHCDA028I read trk %d cache hit, using cache[%d]\n" msgstr "" #: ckddasd.c:923 #, c-format msgid "HHCDA029I read trk %d no available cache entry, waiting\n" msgstr "" #: ckddasd.c:931 #, c-format msgid "HHCDA030I read trk %d cache miss, using cache[%d]\n" msgstr "" #: ckddasd.c:954 msgid "HHCDA031I read trk %d reading file %d offset %" msgstr "" #: ckddasd.c:963 #, c-format msgid "HHCDA032E error reading trk %d: lseek error: %s\n" msgstr "" #: ckddasd.c:981 #, c-format msgid "HHCDA033E error reading trk %d: read error: %s\n" msgstr "" #: ckddasd.c:1004 #, c-format msgid "HHCDA034I read trk %d trkhdr %2.2x %2.2x%2.2x %2.2x%2.2x\n" msgstr "" #: ckddasd.c:1013 #, c-format msgid "" "HHCDA035E %4.4X invalid track header for cyl %d head %d %2.2x%2.2x%2.2x%2.2x" "%2.2x\n" msgstr "" #: ckddasd.c:1527 #, c-format msgid "HHCDA038I seeking to cyl %d head %d\n" msgstr "" #: ckddasd.c:1566 #, c-format msgid "HHCDA039E MT advance error: locate record %d file mask %2.2X\n" msgstr "" #: ckddasd.c:1598 #, c-format msgid "HHCDA040I MT advance to cyl %d head %d\n" msgstr "" #: ckddasd.c:1645 #, c-format msgid "HHCDA041I read count orientation is %s\n" msgstr "" #: ckddasd.c:1669 #, c-format msgid "HHCDA042E attempt to read past end of track %d %d\n" msgstr "" #: ckddasd.c:1691 #, c-format msgid "HHCDA043I cyl %d head %d record %d kl %d dl %d of %d\n" msgstr "" #: ckddasd.c:1779 #, c-format msgid "HHCDA044I read key %d bytes\n" msgstr "" #: ckddasd.c:1787 msgid "ckddasd: attempt to read past end of track\n" msgstr "" #: ckddasd.c:1829 #, c-format msgid "HHCDA045I read data %d bytes\n" msgstr "" #: ckddasd.c:1837 msgid "HHCDA046E attempt to read past end of track\n" msgstr "" #: ckddasd.c:1955 #, c-format msgid "HHCDA047I writing cyl %d head %d record %d kl %d dl %d\n" msgstr "" #: ckddasd.c:1961 #, c-format msgid "HHCDA048I setting track overflow flag for cyl %d head %d record %d\n" msgstr "" #: ckddasd.c:2006 msgid "HHCDA049E Write KD orientation error\n" msgstr "" #: ckddasd.c:2019 #, c-format msgid "HHCDA050I updating cyl %d head %d record %d kl %d dl %d\n" msgstr "" #: ckddasd.c:2048 msgid "HHCDA051E Write data orientation error\n" msgstr "" #: ckddasd.c:2062 #, c-format msgid "HHCDA052I updating cyl %d head %d record %d dl %d\n" msgstr "" #: ckddasd.c:2121 #, c-format msgid "HHCDA053E Data chaining not supported for CCW %2.2X\n" msgstr "" #: ckddasd.c:3375 #, c-format msgid "HHCDA054I set file mask %2.2X\n" msgstr "" #: ckddasd.c:3543 #, c-format msgid "HHCDA055I search key %s\n" msgstr "" #: codepage.c:485 #, c-format msgid "HHCCF072I Using internal codepage conversion table %s\n" msgstr "" #: codepage.c:495 #, c-format msgid "HHCCF072I Using external codepage conversion table %s\n" msgstr "" #: codepage.c:501 #, c-format msgid "HHCCF051E Codepage conversion table %s is not defined\n" msgstr "" #: commadpt.c:97 #, c-format msgid "HHCCA300D %4.4X:%s : Status = TEXT=%s, TRANS=%s, TWS=%s\n" msgstr "" #: commadpt.c:103 #, c-format msgid "HHCCA300D %4.4X:%s : Dump of %d (%x) byte(s)\n" msgstr "" #: commadpt.c:112 #, c-format msgid "HHCCA300D %4.4X:%s : %4.4X:" msgstr "" #: commadpt.c:262 #, c-format msgid "HHCCA300D %4.4X:clean : Control block freed\n" msgstr "" #: commadpt.c:270 #, c-format msgid "HHCCA300D %4.4X:clean : Control block not freed : not allocated\n" msgstr "" #: commadpt.c:284 #, c-format msgid "HHCCA020E %4.4X:Memory allocation failure for main control block\n" msgstr "" #: commadpt.c:365 #, c-format msgid "" "HHCCA001I %4.4X:Connect out to %s:%d failed during initial status : %s\n" msgstr "" #: commadpt.c:407 #, c-format msgid "HHCCA300D %4.4x : Found data beyond EON\n" msgstr "" #: commadpt.c:422 #, c-format msgid "HHCCA300D %4.4x : Found incorrect IP address section at position %d\n" msgstr "" #: commadpt.c:423 #, c-format msgid "HHCCA300D %4.4x : %d greater than 255\n" msgstr "" #: commadpt.c:437 #, c-format msgid "HHCCA300D %4.4x : Too many separators in dial data\n" msgstr "" #: commadpt.c:454 #, c-format msgid "HHCCA300D %4.4x : Incorrect dial data byte %2.2x\n" msgstr "" #: commadpt.c:475 #, c-format msgid "HHCCA300D %4.4x : Not enough separators (only %d found) in dial data\n" msgstr "" #: commadpt.c:483 #, c-format msgid "HHCCA300D %4.4x : Destination TCP port %d exceeds maximum of 65535\n" msgstr "" #: commadpt.c:616 #, c-format msgid "HHCCA002I %4.4X:Line Communication thread " msgstr "" #: commadpt.c:628 #, c-format msgid "HHCCA003E %4.4X:Cannot obtain socket for incoming calls : %s\n" msgstr "" #: commadpt.c:653 #, c-format msgid "HHCCA004W %4.4X:Waiting 5 seconds for port %d to become available\n" msgstr "" #: commadpt.c:704 #, c-format msgid "HHCCA018E %4.4X:Bind failed : %s\n" msgstr "" #: commadpt.c:718 #, c-format msgid "HHCCA005I %4.4X:Listening on port %d for incoming TCP connections\n" msgstr "" #: commadpt.c:756 #, c-format msgid "HHCCA300D %4.4X:cthread - Entry - DevExec = %s\n" msgstr "" #: commadpt.c:821 #, c-format msgid "HHCCA300D %4.4X:Poll Command abort - Poll address >7 Bytes\n" msgstr "" #: commadpt.c:849 #, c-format msgid "HHCCA300D %4.4X:Writing 1 byte in socket : %2.2X\n" msgstr "" #: commadpt.c:1029 #, c-format msgid "HHCCA300D %4.4X:cthread - Select IN maxfd = %d / Devexec = %s\n" msgstr "" #: commadpt.c:1035 #, c-format msgid "HHCCA300D %4.4X:cthread - Select OUT rc=%d\n" msgstr "" #: commadpt.c:1051 #, c-format msgid "HHCCA006T %4.4X:Select failed : %s\n" msgstr "" #: commadpt.c:1062 #, c-format msgid "HHCCA300D %4.4X:cthread - Select TIME OUT\n" msgstr "" #: commadpt.c:1080 #, c-format msgid "HHCCA300D %4.4X:cthread - IPC Pipe closed\n" msgstr "" #: commadpt.c:1088 #, c-format msgid "HHCCA300D %4.4X:cthread - IPC Pipe Data ; code = %d\n" msgstr "" #: commadpt.c:1120 #, c-format msgid "HHCCA300D %4.4X:cthread - inbound socket data\n" msgstr "" #: commadpt.c:1162 #, c-format msgid "HHCCA300D %4.4X:cthread - socket write available\n" msgstr "" #: commadpt.c:1176 #, c-format msgid "HHCCA007W %4.4X:Outgoing call failed during %s command : %s\n" msgstr "" #: commadpt.c:1206 #, c-format msgid "HHCCA008I %4.4X:cthread - Incoming Call\n" msgstr "" #: commadpt.c:1266 #, c-format msgid "HHCCA009I %4.4X:BSC utility thread terminated\n" msgstr "" #: commadpt.c:1317 #, c-format msgid "HHCCA013E %4.4X:Incorrect %s specification %s\n" msgstr "" #: commadpt.c:1321 #, c-format msgid "HHCCA015E %4.4X:Missing parameter : DIAL=%s and %s not specified\n" msgstr "" #: commadpt.c:1325 #, c-format msgid "HHCCA016W %4.4X:Conflicting parameter : DIAL=%s and %s=%s specified\n" msgstr "" #: commadpt.c:1326 #, c-format msgid "HHCCA017I %4.4X:RPORT parameter ignored\n" msgstr "" #: commadpt.c:1349 #, c-format msgid "HHCCA300D %4.4X:Initialisation starting\n" msgstr "" #: commadpt.c:1355 #, c-format msgid "HHCCA010I %4.4X:initialisation not performed\n" msgstr "" #: commadpt.c:1361 #, c-format msgid "HHCCA300D %4.4X:Initialisation : Control block allocated\n" msgstr "" #: commadpt.c:1384 #, c-format msgid "HHCCA011E %4.4X:Error parsing %s\n" msgstr "" #: commadpt.c:1390 #, c-format msgid "HHCCA012E %4.4X:Unrecognized parameter %s\n" msgstr "" #: commadpt.c:1478 #, c-format msgid "" "HHCCA014E %4.4X:Incorrect switched/dial specification %s; defaulting to " "DIAL=OUT\n" msgstr "" #: commadpt.c:1597 #, c-format msgid "HHCCA021I %4.4X:Initialisation failed due to previous errors\n" msgstr "" #: commadpt.c:1657 #, c-format msgid "HHCCA019E %4.4x : BSC comm thread did not initialise\n" msgstr "" #: commadpt.c:1699 #, c-format msgid "HHCCA300D %4.4X:Closing down\n" msgstr "" #: commadpt.c:1731 #, c-format msgid "HHCCA300D %4.4X:Closed down\n" msgstr "" #: commadpt.c:1760 #, c-format msgid "HHCCA300D %4.4X:CCW Exec - Entry code = %x\n" msgstr "" #: commadpt.c:1871 #, c-format msgid "HHCCA300D %4.4X Set Mode : %s\n" msgstr "" #: config.c:122 #, c-format msgid "HHCCF040E Cannot create CPU%4.4X thread: %s\n" msgstr "" #: config.c:293 msgid "HHCCF043E Cannot obtain device block\n" msgstr "" #: config.c:409 #, c-format msgid "HHCCF041E Device %d:%4.4X already exists\n" msgstr "" #: config.c:418 #, c-format msgid "HHCCF042E Device type %s not recognized\n" msgstr "" #: config.c:446 #, c-format msgid "HHCCF044E Initialization failed for device %4.4X\n" msgstr "" #: config.c:468 #, c-format msgid "HHCCF045E Cannot obtain buffer for device %4.4X: %s\n" msgstr "" #: config.c:600 #, c-format msgid "HHCCF046E Subchannel %d:%4.4X does not exist\n" msgstr "" #: config.c:607 #, c-format msgid "HHCCF047I Subchannel %d:%4.4X detached\n" msgstr "" #: config.c:626 #, c-format msgid "HHCCF046E Device %d:%4.4X does not exist\n" msgstr "" #: config.c:633 #, c-format msgid "HHCCF047I Device %4.4X detached\n" msgstr "" #: config.c:651 #, c-format msgid "HHCCF048E Device %d:%4.4X does not exist\n" msgstr "" #: config.c:658 #, c-format msgid "HHCCF049E Device %d:%4.4X already exists\n" msgstr "" #: config.c:934 msgid "" "HHCCF074E Unspecified error occured while parsing Logical Channel Subsystem " "Identification\n" msgstr "" #: config.c:950 msgid "" "HHCCF075E No more than 1 Logical Channel Subsystem Identification may be " "specified\n" msgstr "" #: config.c:960 #, c-format msgid "HHCCF076E Non numeric Logical Channel Subsystem Identification %s\n" msgstr "" #: config.c:969 #, c-format msgid "" "HHCCF077E Logical Channel Subsystem Identification %d exceeds maximum of %d\n" msgstr "" #: config.c:1001 config.c:1117 #, c-format msgid "HHCCF055E Incorrect device address specification near character %c\n" msgstr "" #: config.c:1099 #, c-format msgid "" "HHCCF053E Incorrect second device number in device range near character %c\n" msgstr "" #: config.c:1110 #, c-format msgid "HHCCF054E Incorrect Device count near character %c\n" msgstr "" #: config.c:1125 #, c-format msgid "HHCCF056E Incorrect device address range. %4.4X < %4.4X\n" msgstr "" #: config.c:1148 #, c-format msgid "" "HHCCF057E %4.4X is on wrong channel (1st device defined on channel %2.2X)\n" msgstr "" #: config.c:1178 #, c-format msgid "" "HHCCF058E Some or all devices in %4.4X-%4.4X duplicate devices already " "defined\n" msgstr "" #: console.c:373 #, c-format msgid "HHCGI001I Unable to determine IP address from %s\n" msgstr "" #: console.c:394 #, c-format msgid "HHCGI002I Unable to determine port number from %s\n" msgstr "" #: console.c:408 #, c-format msgid "HHCGI003E Invalid parameter: %s\n" msgstr "" #: console.c:923 #, c-format msgid "HHCTE014I %4.4X device %4.4X client %s connection reset\n" msgstr "" #: console.c:933 #, c-format msgid "HHCTE007I %4.4X device %4.4X client %s connection closed\n" msgstr "" #: console.c:1098 #, c-format msgid "HHCTE008I Device %4.4X connection closed by client %s\n" msgstr "" #: console.c:1821 #, c-format msgid "HHCTE009I Client %s connected to %4.4X device %d:%4.4X\n" msgstr "" #: console.c:1936 msgid "HHCTE001I Console connection thread started: tid=" msgstr "" #: console.c:1960 #, c-format msgid "HHCTE010E CNSLPORT statement invalid: %s\n" msgstr "" #: console.c:1972 #, c-format msgid "HHCTE002W Waiting for port %u to become free\n" msgstr "" #: console.c:1991 #, c-format msgid "HHCTE003I Waiting for console connection on port %u\n" msgstr "" #: console.c:2253 msgid "HHCTE004I Console connection thread terminated\n" msgstr "" #: console.c:2283 #, c-format msgid "HHCTE005E Cannot create console thread: %s\n" msgstr "" #: console.c:2305 msgid "** BUG! console_remove() error! **\n" msgstr "" #: console.c:2377 console.c:2663 #, c-format msgid "HHCTE011E Device %4.4X: Invalid IP address: %s\n" msgstr "" #: console.c:2388 console.c:2674 #, c-format msgid "HHCTE012E Device %4.4X: Invalid mask value: %s\n" msgstr "" #: console.c:2397 console.c:2683 #, c-format msgid "HHCTE013E Device %4.4X: Extraneous argument(s): %s...\n" msgstr "" #: console.c:2544 #, c-format msgid "HHCTE090E %4.4X malloc() failed for resume buf: %s\n" msgstr "" #: console.c:3488 #, c-format msgid "HHCTE006A Enter input for console device %4.4X\n" msgstr "" #: cpu.c:326 msgid "HHCCP043I Wait state PSW loaded: " msgstr "" #: cpu.c:521 #, c-format msgid "program_int() passing to guest code=%4.4X\n" msgstr "" #: cpu.c:612 msgid "HHCCP014I " msgstr "" #: cpu.c:615 hscmisc.c:1088 msgid "SIE: " msgstr "" #: cpu.c:622 #, c-format msgid "CPU%4.4X: %s CODE=%4.4X ILC=%d%s\n" msgstr "" #: cpu.c:736 #, c-format msgid "HHCCP015I CPU%4.4X PER event: code=%4.4X perc=%2.2X addr=" msgstr "" #: cpu.c:914 #, c-format msgid "HHCCP016I CPU%4.4X: Program interrupt loop: " msgstr "" #: cpu.c:1028 #, c-format msgid "" "HHCCP044I I/O interrupt code=%4.4X CSW=%2.2X%2.2X%2.2X%2.2X %2.2X%2.2X%2.2X%" "2.2X\n" msgstr "" #: cpu.c:1050 #, c-format msgid "HHCCP045I I/O interrupt code=%8.8X parm=%8.8X\n" msgstr "" #: cpu.c:1053 #, c-format msgid "HHCCP046I I/O interrupt code=%8.8X parm=%8.8X id=%8.8X\n" msgstr "" #: cpu.c:1119 msgid "HHCCP022I Machine Check code=%16.16" msgstr "" #: cpu.c:1180 #, c-format msgid "HHCCP001W CPU%4.4X thread set priority %d failed: %s\n" msgstr "" #: cpu.c:1187 #, c-format msgid "HHCCP002I CPU%4.4X thread started: tid=" msgstr "" #: cpu.c:1210 #, c-format msgid "HHCCP006S Cannot create timer thread: %s\n" msgstr "" #: cpu.c:1239 #, c-format msgid "HHCCP008I CPU%4.4X thread ended: tid=" msgstr "" #: cpu.c:1471 hsccmd.c:1340 #, c-format msgid "HHCCP010I CPU%4.4X store status completed.\n" msgstr "" #: cpu.c:1540 #, c-format msgid "" "HHCCP011I CPU%4.4X: Disabled wait state\n" " " msgstr "" #: cpu.c:1654 #, c-format msgid "HHCCP007I CPU%4.4X architecture mode set to %s\n" msgstr "" #: cpu.c:1664 #, c-format msgid "HHCCP003I CPU%4.4X architecture mode %s\n" msgstr "" #: cpu.c:1669 #, c-format msgid "HHCCP004I CPU%4.4X Vector Facility online\n" msgstr "" #: cpu.c:1697 #, c-format msgid "HHCCP080E CPU%4.4X malloc failed for archjmp regs: %s\n" msgstr "" #: cpu.c:1897 #, c-format msgid "PSW=%2.2X%2.2X%2.2X%2.2X %2.2X%2.2X%2.2X%2.2X\n" msgstr "" #: cpu.c:1904 #, c-format msgid "" "PSW=%2.2X%2.2X%2.2X%2.2X %2.2X%2.2X%2.2X%2.2X %2.2X%2.2X%2.2X%2.2X%2.2X%2.2X%" "2.2X%2.2X\n" msgstr "" #: ctc_ctci.c:155 #, c-format msgid "HHCCT037E %4.4X: Unable to allocate CTCBLK\n" msgstr "" #: ctc_ctci.c:176 #, c-format msgid "HHCCT038E %4.4X: Unable to allocate CTCBLK\n" msgstr "" #: ctc_ctci.c:233 #, c-format msgid "HHCCT073I %4.4X: TUN device %s opened\n" msgstr "" #: ctc_ctci.c:250 #, c-format msgid "HHCCT074W TT32SDEVBUFF failed for device %s: %s.\n" msgstr "" #: ctc_ctci.c:257 #, c-format msgid "HHCCT075W TT32SIOBUFF failed for device %s: %s.\n" msgstr "" #: ctc_ctci.c:683 #, c-format msgid "HHCCT040I %4.4X: Halt or Clear Recognized\n" msgstr "" #: ctc_ctci.c:732 #, c-format msgid "HHCCT041I %4.4X: CTC Received Frame (%d bytes):\n" msgstr "" #: ctc_ctci.c:770 #, c-format msgid "HHCCT042E %4.4X: Write CCW count %u is invalid\n" msgstr "" #: ctc_ctci.c:799 #, c-format msgid "HHCCT043I %4.4X: Interface command: %s %8.8X\n" msgstr "" #: ctc_ctci.c:826 ctcadpt.c:748 #, c-format msgid "CTC101W %4.4X: Write buffer contains invalid frame offset %u\n" msgstr "" #: ctc_ctci.c:848 #, c-format msgid "" "HHCCT044E %4.4X: Write buffer contains incomplete segment header at offset %" "4.4X\n" msgstr "" #: ctc_ctci.c:868 #, c-format msgid "" "HHCCT045E %4.4X: Write buffer contains invalid segment length %u at offset %" "4.4X\n" msgstr "" #: ctc_ctci.c:883 #, c-format msgid "HHCCT046I %4.4X: Sending packet to %s:\n" msgstr "" #: ctc_ctci.c:893 #, c-format msgid "HHCCT047E %4.4X: Error writing to %s: %s\n" msgstr "" #: ctc_ctci.c:956 #, c-format msgid "HHCCT048E %4.4X: Error reading from %s: %s\n" msgstr "" #: ctc_ctci.c:968 #, c-format msgid "HHCCT049I %4.4X: Received packet from %s (%d bytes):\n" msgstr "" #: ctc_ctci.c:980 #, c-format msgid "HHCCT072W %4.4X: Packet too big; dropped.\n" msgstr "" #: ctc_ctci.c:1124 ctc_ctci.c:1309 #, c-format msgid "HHCCT056E %4.4X: Incorrect number of parameters\n" msgstr "" #: ctc_ctci.c:1209 #, c-format msgid "HHCCT050E %4.4X: Invalid adapter address %s\n" msgstr "" #: ctc_ctci.c:1218 #, c-format msgid "HHCCT051E %4.4X: Invalid device name %s\n" msgstr "" #: ctc_ctci.c:1232 #, c-format msgid "HHCCT052E %4.4X: Invalid kernel buffer size %s\n" msgstr "" #: ctc_ctci.c:1246 #, c-format msgid "HHCCT053E %4.4X: Invalid DLL I/O buffer size %s\n" msgstr "" #: ctc_ctci.c:1260 #, c-format msgid "HHCCT054E %4.4X: Invalid MTU size %s\n" msgstr "" #: ctc_ctci.c:1271 #, c-format msgid "HHCCT055E %4.4X: Invalid netmask %s\n" msgstr "" #: ctc_ctci.c:1282 #, c-format msgid "HHCCT056E %4.4X: Invalid MAC address %s\n" msgstr "" #: ctc_ctci.c:1319 #, c-format msgid "HHCCT057E %4.4X: Incorrect number of parameters\n" msgstr "" #: ctc_ctci.c:1327 #, c-format msgid "HHCCT058E %4.4X: Invalid IP address %s\n" msgstr "" #: ctc_ctci.c:1339 #, c-format msgid "HHCCT059E %4.4X: Invalid IP address %s\n" msgstr "" #: ctc_ctci.c:1355 #, c-format msgid "HHCCT060E %4.4X: Incorrect number of parameters\n" msgstr "" #: ctc_ctci.c:1364 #, c-format msgid "HHCCT061E %4.4X: invalid device name %s\n" msgstr "" #: ctc_ctci.c:1378 #, c-format msgid "HHCCT062E %4.4X: Invalid MTU size %s\n" msgstr "" #: ctc_ctci.c:1389 #, c-format msgid "HHCCT063E %4.4X: Invalid IP address %s\n" msgstr "" #: ctc_ctci.c:1401 #, c-format msgid "HHCCT064E %4.4X: Invalid IP address %s\n" msgstr "" #: ctc_ctci.c:1413 #, c-format msgid "HHCCT065E %4.4X: Invalid netmask %s\n" msgstr "" #: ctc_ctci.c:1424 #, c-format msgid "HHCCT066E %4.4X: Incorrect number of parameters\n" msgstr "" #: ctc_ctci.c:1442 #, c-format msgid "HHCCT067E %4.4X: Invalid IP address %s\n" msgstr "" #: ctc_ctci.c:1457 #, c-format msgid "HHCCT068E %4.4X: Invalid MAC address %s\n" msgstr "" #: ctc_ctci.c:1489 #, c-format msgid "HHCCT069E %4.4X: Invalid kernel buffer size %s\n" msgstr "" #: ctc_ctci.c:1506 #, c-format msgid "HHCCT070E %4.4X: Invalid DLL I/O buffer size %s\n" msgstr "" #: ctc_ctci.c:1517 #, c-format msgid "HHCCT071E %4.4X: Incorrect number of parameters\n" msgstr "" #: ctc_lcs.c:122 #, c-format msgid "HHCLC001E %4.4X unable to allocate LCSBLK\n" msgstr "" #: ctc_lcs.c:269 #, c-format msgid "HHCLC073I %4.4X: TAP device %s opened\n" msgstr "" #: ctc_lcs.c:285 #, c-format msgid "HHCLC074W TT32SDEVBUFF failed for device %s: %s.\n" msgstr "" #: ctc_lcs.c:292 #, c-format msgid "HHCLC075W TT32SIOBUFF failed for device %s: %s.\n" msgstr "" #: ctc_lcs.c:765 #, c-format msgid "HHCLC002I %4.4X: Halt or Clear Recognized\n" msgstr "" #: ctc_lcs.c:808 #, c-format msgid "HHCLC003I %4.4X: LCS Read Buffer:\n" msgstr "" #: ctc_lcs.c:871 #, c-format msgid "HHCLCxxxI %4.4X: Startup\n" msgstr "" #: ctc_lcs.c:876 #, c-format msgid "HHCLCxxxI %4.4X: Shutdown\n" msgstr "" #: ctc_lcs.c:882 #, c-format msgid "HHCLCxxxI %4.4X: Start LAN\n" msgstr "" #: ctc_lcs.c:887 #, c-format msgid "HHCLCxxxI %4.4X: Stop LAN\n" msgstr "" #: ctc_lcs.c:893 #, c-format msgid "HHCLCxxxI %4.4X: Query\n" msgstr "" #: ctc_lcs.c:899 #, c-format msgid "HHCLCxxxI %4.4X: Stat\n" msgstr "" #: ctc_lcs.c:929 #, c-format msgid "HHCLC004I %4.4X: Sending packet to %s:\n" msgstr "" #: ctc_lcs.c:938 #, c-format msgid "HHCLC005E %4.4X: Error writing to %s: %s\n" msgstr "" #: ctc_lcs.c:957 #, c-format msgid "HHCLC006I %4.4X Triggering Event.\n" msgstr "" #: ctc_lcs.c:1343 #, c-format msgid "HHCLC007E Error in call to socket: %s.\n" msgstr "" #: ctc_lcs.c:1356 #, c-format msgid "HHCLC008E ioctl error on device %s: %s.\n" msgstr "" #: ctc_lcs.c:1453 #, c-format msgid "HHCLC042E Port %2.2X: Read error: %s\n" msgstr "" #: ctc_lcs.c:1462 #, c-format msgid "HHCLC009I Port %2.2X: Read Buffer:\n" msgstr "" #: ctc_lcs.c:1491 #, c-format msgid "HHCLC010I Port %2.2X: IPV4 frame for %8.8X\n" msgstr "" #: ctc_lcs.c:1518 #, c-format msgid "HHCLC011I Port %2.2X: ARP frame for %8.8X\n" msgstr "" #: ctc_lcs.c:1547 #, c-format msgid "" "HHCLC011I Port %2.2X: RARP frame for %2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X\n" msgstr "" #: ctc_lcs.c:1579 #, c-format msgid "HHCLC012I Port %2.2X: SNA frame\n" msgstr "" #: ctc_lcs.c:1609 #, c-format msgid "HHCLC013I Port %2.2X: No match found - selecting primary %4.4X\n" msgstr "" #: ctc_lcs.c:1619 #, c-format msgid "HHCLC014I Port %2.2X: No match found - selecting secondary %4.4X\n" msgstr "" #: ctc_lcs.c:1630 #, c-format msgid "HHCLC015I Port %2.2X: No match found - Discarding frame\n" msgstr "" #: ctc_lcs.c:1638 #, c-format msgid "HHCLC016I Port %2.2X: Enqueing frame to device %4.4X (%8.8X)\n" msgstr "" #: ctc_lcs.c:1652 #, c-format msgid "HHCLC041W Port %2.2X: Frame too big; discarded.\n" msgstr "" #: ctc_lcs.c:1900 #, c-format msgid "HHCLC017E %4.4X invalid device name %s\n" msgstr "" #: ctc_lcs.c:1916 #, c-format msgid "HHCLC052E %4.4X: Invalid kernel buffer size %s\n" msgstr "" #: ctc_lcs.c:1930 #, c-format msgid "HHCLC053E %4.4X: Invalid DLL I/O buffer size %s\n" msgstr "" #: ctc_lcs.c:1946 #, c-format msgid "HHCLC018E %4.4X invalid MAC address %s\n" msgstr "" #: ctc_lcs.c:1970 #, c-format msgid "HHCLC019E %4.4X too many arguments in statement.\n" msgstr "" #: ctc_lcs.c:1980 #, c-format msgid "HHCLC020E %4.4X invalid IP address %s\n" msgstr "" #: ctc_lcs.c:2035 #, c-format msgid "HHCLC039E Cannot open file %s: %s\n" msgstr "" #: ctc_lcs.c:2087 #, c-format msgid "HHCLC021E Invalid HWADD statement in %s: %s\n" msgstr "" #: ctc_lcs.c:2096 #, c-format msgid "" "HHCLC022E Invalid MAC in HWADD statement in %s: %s (%s)\n" " " msgstr "" #: ctc_lcs.c:2113 #, c-format msgid "HHCLC023E Invalid ROUTE statement in %s: %s\n" msgstr "" #: ctc_lcs.c:2120 #, c-format msgid "HHCLC024E Invalid net address in ROUTE %s: %s (%s)\n" msgstr "" #: ctc_lcs.c:2130 #, c-format msgid "HHCLC025E Invalid net mask in ROUTE %s: %s (%s)\n" msgstr "" #: ctc_lcs.c:2162 #, c-format msgid "HHCLC026E Error in %s: Missing device number or mode\n" msgstr "" #: ctc_lcs.c:2171 #, c-format msgid "HHCLC027E Error in %s: %s: Invalid device number\n" msgstr "" #: ctc_lcs.c:2183 #, c-format msgid "HHCLC028E Error in %s: %s:Missing PORT number\n" msgstr "" #: ctc_lcs.c:2191 #, c-format msgid "HHCLC029E Error in %s: %s: Invalid PORT number\n" msgstr "" #: ctc_lcs.c:2207 #, c-format msgid "HHCLC031E Error in %s: %s: Invalid entry starting at %s\n" msgstr "" #: ctc_lcs.c:2219 #, c-format msgid "HHCLC032E Error is %s: %s: Invalid IP address (%s)\n" msgstr "" #: ctc_lcs.c:2235 #, c-format msgid "HHCLC033E Error in %s: %s: Missing PORT number\n" msgstr "" #: ctc_lcs.c:2243 #, c-format msgid "HHCLC034E Error in %s: %s:Invalid PORT number\n" msgstr "" #: ctc_lcs.c:2251 #, c-format msgid "HHCLC035E Error in %s: %s: SNA does not accept any arguments\n" msgstr "" #: ctc_lcs.c:2259 #, c-format msgid "HHCLC036E Error in %s: %s: Invalid MODE\n" msgstr "" #: ctc_lcs.c:2324 #, c-format msgid "HHCLC037E Error reading file %s line %d: %s\n" msgstr "" #: ctc_lcs.c:2348 #, c-format msgid "HHCLC038E File %s line %d is too long\n" msgstr "" #: ctcadpt.c:167 #, c-format msgid "HHCCT001E %4.4X: Incorrect number of parameters\n" msgstr "" #: ctcadpt.c:180 #, c-format msgid "HHCCT034E %s: Unrecognized/unsupported CTC emulation type\n" msgstr "" #: ctcadpt.c:488 #, c-format msgid "HHCCT002E %4.4X: Incorrect number of parameters\n" msgstr "" #: ctcadpt.c:500 #, c-format msgid "HHCCT003E %4.4X: Invalid port number: %s\n" msgstr "" #: ctcadpt.c:521 #, c-format msgid "HHCCT004E %4.4X: Invalid IP address %s\n" msgstr "" #: ctcadpt.c:534 #, c-format msgid "HHCCT005E %4.4X: Invalid port number: %s\n" msgstr "" #: ctcadpt.c:546 #, c-format msgid "HHCCT006E %4.4X: Invalid MTU size %s\n" msgstr "" #: ctcadpt.c:567 #, c-format msgid "HHCCT007E %4.4X: Error creating socket: %s\n" msgstr "" #: ctcadpt.c:587 #, c-format msgid "HHCCT008E %4.4X: Error binding to socket: %s\n" msgstr "" #: ctcadpt.c:608 #, c-format msgid "HHCCT009I %4.4X: Connect to %s:%s failed, starting server\n" msgstr "" #: ctcadpt.c:618 #, c-format msgid "HHCCT010E %4.4X: Error creating socket: %s\n" msgstr "" #: ctcadpt.c:635 #, c-format msgid "HHCCT011E %4.4X: Error binding to socket: %s\n" msgstr "" #: ctcadpt.c:643 #, c-format msgid "HHCCT012E %4.4X: Error on call to listen: %s\n" msgstr "" #: ctcadpt.c:659 #, c-format msgid "HHCCT013I %4.4X: Connected to %s:%s\n" msgstr "" #: ctcadpt.c:693 #, c-format msgid "HHCCT014E %4.4X: Write CCW count %u is invalid\n" msgstr "" #: ctcadpt.c:723 #, c-format msgid "HHCCT015I %4.4X: Interface command: %s %8.8X\n" msgstr "" #: ctcadpt.c:769 #, c-format msgid "" "HHCCT016E %4.4X: Write buffer contains incomplete segment header at offset %" "4.4X\n" msgstr "" #: ctcadpt.c:789 #, c-format msgid "" "HHCCT017E %4.4X: Write buffer contains invalid segment length %u at offset %" "4.4X\n" msgstr "" #: ctcadpt.c:804 #, c-format msgid "HHCCT018I %4.4X: Sending packet to %s:\n" msgstr "" #: ctcadpt.c:815 #, c-format msgid "HHCCT019E %4.4X: Error writing to %s: %s\n" msgstr "" #: ctcadpt.c:878 #, c-format msgid "HHCCT020E %4.4X: Error reading from %s: %s\n" msgstr "" #: ctcadpt.c:895 #, c-format msgid "HHCCT021E %4.4X: Error reading from %s: %s\n" msgstr "" #: ctcadpt.c:905 #, c-format msgid "HHCCT022I %4.4X: Received packet from %s (%d bytes):\n" msgstr "" #: ctcadpt.c:987 #, c-format msgid "" "HHCCT023E %4.4X: Incorrect client or config error\n" " Config=%s, connecting client=%s\n" msgstr "" #: ctcadpt.c:1031 #, c-format msgid "HHCCT024E %4.4X: Not enough arguments to start vmnet\n" msgstr "" #: ctcadpt.c:1041 #, c-format msgid "HHCCT025E %4.4X: Failed: socketpair: %s\n" msgstr "" #: ctcadpt.c:1049 #, c-format msgid "HHCCT026E %4.4X: Failed: fork: %s\n" msgstr "" #: ctcadpt.c:1100 #, c-format msgid "HHCCT027E %4.4X: Not enough parameters\n" msgstr "" #: ctcadpt.c:1106 #, c-format msgid "HHCCT028E %d:%4.4X: Bad device number '%s'\n" msgstr "" #: ctcadpt.c:1143 #, c-format msgid "HHCCT029E %4.4X: bad block length: %d < %d\n" msgstr "" #: ctcadpt.c:1153 #, c-format msgid "HHCCT030E %4.4X: bad packet length: %d < %d\n" msgstr "" #: ctcadpt.c:1158 #, c-format msgid "HHCCT031E %4.4X: bad packet length: %d < 6\n" msgstr "" #: ctcadpt.c:1204 #, c-format msgid "HHCCT032E %4.4X: Error: EOF on read, CTC network down\n" msgstr "" #: ctcadpt.c:1212 #, c-format msgid "HHCCT033E %4.4X: Error: read: %s\n" msgstr "" #: dasdcat.c:43 #, c-format msgid "HHCDT002E Can't make 80 column card images from block length %d\n" msgstr "" #: dasdcat.c:119 #, c-format msgid "HHCDT003E Directory block byte count is invalid\n" msgstr "" #: dasdcat.c:221 #, c-format msgid "HHCDT004E non-PDS-members not yet supported\n" msgstr "" #: dasdcat.c:253 #, c-format msgid "HHCDT005E unknown dataset name option: '%c'\n" msgstr "" #: dasdcat.c:350 #, c-format msgid "HHCDT001E failed to open image %s\n" msgstr "" #: dasdcopy.c:119 #, c-format msgid "Hercules %s copy program " msgstr "" #: dasdcopy.c:204 #, c-format msgid "HHCDC001E %s: %s open error: %s\n" msgstr "" #: dasdcopy.c:211 #, c-format msgid "HHCDC002E %s: %s read error: %s\n" msgstr "" #: dasdcopy.c:274 #, c-format msgid "HHCDC003E %s: %s open failed\n" msgstr "" #: dasdcopy.c:288 #, c-format msgid "HHCDC004E %s: ckd lookup failed for %4.4X cyls %d\n" msgstr "" #: dasdcopy.c:308 #, c-format msgid "HHCDC005E %s: fba lookup failed, blks %d\n" msgstr "" #: dasdcopy.c:329 #, c-format msgid "HHCDC006E %s: %s create failed\n" msgstr "" #: dasdcopy.c:341 #, c-format msgid "HHCDC007E %s: %s open failed\n" msgstr "" #: dasdcopy.c:378 #, c-format msgid "HHCDC008E %s: %s read error %s %d stat=%2.2X, null %s substituted\n" msgstr "" #: dasdcopy.c:388 #, c-format msgid " %3d%% %7d of %d" msgstr "" #: dasdcopy.c:417 #, c-format msgid "HHCDC009E %s: %s write error %s %d stat=%2.2X\n" msgstr "" #: dasdcopy.c:429 #, c-format msgid "HHCDC010I %s successfully completed.\n" msgstr "" #: dasdcopy.c:517 #, c-format msgid "" "usage: ckd2cckd [-options] ifile ofile\n" "\n" " copy a ckd dasd file to a compressed ckd dasd file\n" "\n" " ifile -- input ckd dasd file\n" " ofile -- output compressed ckd dasd file\n" "\n" " options:\n" " -v display program version and quit\n" " -h display this help and quit\n" " -q quiet mode, don't display status\n" " -r replace the output file if it exists\n" "%s%s -0 don't compress track images\n" " -cyls n size of output file\n" " -a output file will have alt cyls\n" msgstr "" #: dasdcopy.c:537 dasdcopy.c:593 dasdcopy.c:655 msgid " -z compress using zlib [default]\n" msgstr "" #: dasdcopy.c:544 dasdcopy.c:600 msgid " -bz2 compress using bzip2\n" msgstr "" #: dasdcopy.c:552 #, c-format msgid "" "usage: cckd2ckd [-options] ifile [sf=sfile] ofile\n" "\n" " copy a compressed ckd file to a ckd file\n" "\n" " ifile -- input compressed ckd dasd file\n" " sfile -- input compressed ckd shadow file\n" " (optional)\n" " ofile -- output ckd dasd file\n" "\n" " options:\n" " -v display program version and quit\n" " -h display this help and quit\n" " -q quiet mode, don't display status\n" " -r replace the output file if it exists\n" "%s -cyls n size of output file\n" " -a output file will have alt cyls\n" msgstr "" #: dasdcopy.c:570 dasdcopy.c:625 msgid " -lfs create single large output file\n" msgstr "" #: dasdcopy.c:574 #, c-format msgid "" "usage: fba2cfba [-options] ifile ofile\n" "\n" " copy a fba dasd file to a compressed fba dasd file\n" "\n" " ifile -- input fba dasd file\n" " ofile -- output compressed fba dasd file\n" "\n" " options:\n" " -v display program version and quit\n" " -h display this help and quit\n" " -q quiet mode, don't display status\n" " -r replace the output file if it exists\n" "%s%s -0 don't compress track images\n" " -blks n size of output file\n" msgstr "" #: dasdcopy.c:608 #, c-format msgid "" "usage: cfba2fba [-options] ifile [sf=sfile] ofile\n" "\n" " copy a compressed fba file to a fba file\n" "\n" " ifile -- input compressed fba dasd file\n" " sfile -- input compressed fba shadow file\n" " (optional)\n" " ofile -- output fba dasd file\n" "\n" " options:\n" " -v display program version and quit\n" " -h display this help and quit\n" " -q quiet mode, don't display status\n" " -r replace the output file if it exists\n" "%s -blks n size of output file\n" msgstr "" #: dasdcopy.c:629 #, c-format msgid "" "usage: %s [-options] ifile [sf=sfile] ofile\n" "\n" " copy a dasd file to another dasd file\n" "\n" " ifile -- input dasd file\n" " sfile -- input shadow file [optional]\n" " ofile -- output dasd file\n" "\n" " options:\n" " -v display program version and quit\n" " -h display this help and quit\n" " -q quiet mode, don't display status\n" " -r replace the output file if it exists\n" "%s%s -0 don't compress output\n" " -blks n size of output fba file\n" " -cyls n size of output ckd file\n" " -a output ckd file will have alt cyls\n" "%s even if it exceeds 2G in size\n" " -o type output file type (CKD, CCKD, FBA, CFBA)\n" msgstr "" #: dasdcopy.c:662 msgid " -bz2 compress output using bzip2\n" msgstr "" #: dasdcopy.c:667 msgid " -lfs output ckd file will be a single file\n" msgstr "" #: dasdinit.c:297 #, c-format msgid "HHCDI001I DASD initialization successfully completed.\n" msgstr "" #: dasdisup.c:252 #, c-format msgid "HHCDS003E Directory block byte count is invalid\n" msgstr "" #: dasdisup.c:297 #, c-format msgid "HHCDS018I %s %s skipped\n" msgstr "" #: dasdisup.c:310 #, c-format msgid "HHCDS004E Number of members exceeds MAX_MEMBERS\n" msgstr "" #: dasdisup.c:319 #, c-format msgid "HHCDS005E Member %s TTR count is zero\n" msgstr "" #: dasdisup.c:348 #, c-format msgid "HHCDS006W Member %s is not single text record\n" msgstr "" #: dasdisup.c:357 #, c-format msgid "HHCDS007W Member %s size %4.4X exceeds X'7F8' bytes\n" msgstr "" #: dasdisup.c:366 #, c-format msgid "HHCDS008W Member %s size %4.4X is not a multiple of 8\n" msgstr "" #: dasdisup.c:420 #, c-format msgid "HHCDS009I Alias %s skipped\n" msgstr "" #: dasdisup.c:427 #, c-format msgid "HHCDS010I Member %s skipped\n" msgstr "" #: dasdisup.c:435 #, c-format msgid "HHCDS011E Member %s has multiple text records\n" msgstr "" #: dasdisup.c:447 #, c-format msgid "HHCDS012E Member %s has invalid TTR %4.4X%2.2X\n" msgstr "" #: dasdisup.c:453 #, c-format msgid "" "HHCDS013I Processing member %s text record TTR=%4.4X%2.2X CCHHR=%4.4X%4.4X%" "2.2X\n" msgstr "" #: dasdisup.c:463 #, c-format msgid "HHCDS014E Member %s error reading TTR %4.4X%2.2X\n" msgstr "" #: dasdisup.c:472 #, c-format msgid "" "HHCDS015E Member %s TTR %4.4X%2.2X text record length %4.4X is not valid\n" msgstr "" #: dasdisup.c:482 #, c-format msgid "" "HHCDS016E Member %s TTR %4.4X%2.2X text record length %4.4X does not match " "length %4.4X in directory\n" msgstr "" #: dasdisup.c:527 #, c-format msgid "HHCDS017E Member %s TTR %4.4X%2.2X XCTL table improperly terminated\n" msgstr "" #: dasdisup.c:549 #, c-format msgid "HHCDS019I In member %s: %s TTRL=%2.2X%2.2X%2.2X%2.2X" msgstr "" #: dasdisup.c:667 #, c-format msgid "HHCDS001E Cannot obtain storage for member array: %s\n" msgstr "" #: dasdisup.c:719 #, c-format msgid "HHCDS002I End of directory: %d members selected\n" msgstr "" #: dasdutil.c:221 #, c-format msgid "HHCDU001I Updating cyl %d head %d\n" msgstr "" #: dasdutil.c:227 #, c-format msgid "HHCDU002E %s write track error: stat=%2.2X\n" msgstr "" #: dasdutil.c:234 #, c-format msgid "HHCDU003I Reading cyl %d head %d\n" msgstr "" #: dasdutil.c:240 #, c-format msgid "HHCDU004E %s read track error: stat=%2.2X\n" msgstr "" #: dasdutil.c:361 #, c-format msgid "HHCDU005I Searching extent %d begin (%d,%d) end (%d,%d)\n" msgstr "" #: dasdutil.c:433 #, c-format msgid "HHCDU006I Searching extent %d begin (%d,%d) end (%d,%d)\n" msgstr "" #: dasdutil.c:494 #, c-format msgid "HHCDU007E Track %d not found in extent table\n" msgstr "" #: dasdutil.c:535 #, c-format msgid "HHCDU008E Cannot obtain storage for device descriptor buffer: %s\n" msgstr "" #: dasdutil.c:596 #, c-format msgid "HHCDU009E Cannot open %s: %s\n" msgstr "" #: dasdutil.c:611 #, c-format msgid "HHCDU010E %s read error: %s\n" msgstr "" #: dasdutil.c:622 #, c-format msgid "HHCDU011E %s CKD header invalid\n" msgstr "" #: dasdutil.c:631 #, c-format msgid "HHCDU012E DASD table entry not found for devtype 0x%2.2X\n" msgstr "" #: dasdutil.c:661 #, c-format msgid "HHCDU013E CKD initialization failed for %s\n" msgstr "" #: dasdutil.c:683 #, c-format msgid "HHCDU014I %s heads=%d trklen=%d\n" msgstr "" #: dasdutil.c:717 #, c-format msgid "HHCDU015I Updating cyl %d head %d\n" msgstr "" #: dasdutil.c:723 #, c-format msgid "HHCDU016E %s write track error: stat=%2.2X\n" msgstr "" #: dasdutil.c:768 #, c-format msgid "HHCDU017E Cannot obtain storage for device descriptor buffer: %s\n" msgstr "" #: dasdutil.c:784 #, c-format msgid "HHCDU018E DASD table entry not found for devtype 0x%2.2X\n" msgstr "" #: dasdutil.c:811 #, c-format msgid "HHCDU019E FBA initialization failed for %s\n" msgstr "" #: dasdutil.c:827 #, c-format msgid "HHCDU020I %s sectors=%d size=%d\n" msgstr "" #: dasdutil.c:873 #, c-format msgid "HHCDU021E VOL1 record not found\n" msgstr "" #: dasdutil.c:886 #, c-format msgid "HHCDU022I VOLSER=%s VTOC=%4.4X%4.4X%2.2X\n" msgstr "" #: dasdutil.c:896 #, c-format msgid "HHCDU023E F4DSCB record not found\n" msgstr "" #: dasdutil.c:903 #, c-format msgid "HHCDU023I VTOC start %2.2X%2.2X%2.2X%2.2X end %2.2X%2.2X%2.2X%2.2X\n" msgstr "" #: dasdutil.c:919 #, c-format msgid "HHCDU024E Dataset %s not found in VTOC\n" msgstr "" #: dasdutil.c:927 #, c-format msgid "HHCDU025I DSNAME=%s F1DSCB CCHHR=%4.4X%4.4X%2.2X\n" msgstr "" #: dasdutil.c:937 #, c-format msgid "HHCDU026E F1DSCB record not found\n" msgstr "" #: dasdutil.c:959 #, c-format msgid "HHCDU027E F3DSCB record not found\n" msgstr "" #: dasdutil.c:1180 #, c-format msgid "HHCDU028E device type %4.4X not found in dasd table\n" msgstr "" #: dasdutil.c:1217 #, c-format msgid "HHCDU028E %s open error: %s\n" msgstr "" #: dasdutil.c:1245 #, c-format msgid "HHCDU029E %s device header write error: %s\n" msgstr "" #: dasdutil.c:1274 #, c-format msgid "HHCDU030E %s compressed device header write error: %s\n" msgstr "" #: dasdutil.c:1284 #, c-format msgid "HHCDU031E Cannot obtain l1tab buffer: %s\n" msgstr "" #: dasdutil.c:1294 #, c-format msgid "HHCDU032E %s primary lookup table write error: %s\n" msgstr "" #: dasdutil.c:1307 #, c-format msgid "HHCDU033E %s secondary lookup table write error: %s\n" msgstr "" #: dasdutil.c:1597 #, c-format msgid "HHCDU035E %s cylinder %u head %u write error: %s\n" msgstr "" #: dasdutil.c:1629 #, c-format msgid "HHCDU036E %s compressed device header lseek error: %s\n" msgstr "" #: dasdutil.c:1637 #, c-format msgid "HHCDU037E %s compressed device header write error: %s\n" msgstr "" #: dasdutil.c:1647 #, c-format msgid "HHCDU038E %s secondary lookup table lseek error: %s\n" msgstr "" #: dasdutil.c:1655 #, c-format msgid "HHCDU039E %s secondary lookup table write error: %s\n" msgstr "" #: dasdutil.c:1670 #, c-format msgid "HHCDU040E %s close error: %s\n" msgstr "" #: dasdutil.c:1677 #, c-format msgid "HHCDU041I %u cylinders successfully written to file %s\n" msgstr "" #: dasdutil.c:1749 #, c-format msgid "HHCDU042E Cylinder count %u is outside range %u-%u\n" msgstr "" #: dasdutil.c:1758 #, c-format msgid "HHCDU043E Cannot obtain track buffer: %s\n" msgstr "" #: dasdutil.c:1765 #, c-format msgid "" "HHCDU044I Creating %4.4X volume %s: %u cyls, %u trks/cyl, %u bytes/track\n" msgstr "" #: dasdutil.c:1874 #, c-format msgid "HHCDU045E Sector count %u is outside range %u-%u\n" msgstr "" #: dasdutil.c:1883 #, c-format msgid "HHCDU046E Cannot obtain sector buffer: %s\n" msgstr "" #: dasdutil.c:1890 #, c-format msgid "HHCDU047I Creating %4.4X volume %s: %u sectors, %u bytes/sector\n" msgstr "" #: dasdutil.c:1903 #, c-format msgid "HHCDU048I %s open error: %s\n" msgstr "" #: dasdutil.c:1915 #, c-format msgid "HHCDU049E %s dasdcopy ftruncate error: %s\n" msgstr "" #: dasdutil.c:1950 #, c-format msgid "HHCDU050E %s sector %u write error: %s\n" msgstr "" #: dasdutil.c:1962 #, c-format msgid "HHCDU051E %s close error: %s\n" msgstr "" #: dasdutil.c:1972 #, c-format msgid "HHCDU052I %u sectors successfully written to file %s\n" msgstr "" #: dasdutil.c:2019 msgid "HHCDU053E File size too large: %" msgstr "" #: dasdutil.c:2033 #, c-format msgid "HHCDU054E %s open error: %s\n" msgstr "" #: dasdutil.c:2040 #, c-format msgid "" "HHCDU055I Creating %4.4X compressed volume %s: %u sectors, %u bytes/sector\n" msgstr "" #: dasdutil.c:2050 #, c-format msgid "HHCDU056E %s devhdr write error: %s\n" msgstr "" #: dasdutil.c:2073 #, c-format msgid "HHCDU057E %s cdevhdr write error: %s\n" msgstr "" #: dasdutil.c:2085 #, c-format msgid "HHCDU058E %s l1tab write error: %s\n" msgstr "" #: dasdutil.c:2097 #, c-format msgid "HHCDU059E %s l2tab write error: %s\n" msgstr "" #: dasdutil.c:2119 #, c-format msgid "HHCDU060E %s block header write error: %s\n" msgstr "" #: dasdutil.c:2126 #, c-format msgid "HHCDU061E %s block write error: %s\n" msgstr "" #: dasdutil.c:2141 #, c-format msgid "HHCDU062E %s block write error: %s\n" msgstr "" #: dasdutil.c:2155 #, c-format msgid "HHCDU063E %s cdevhdr lseek error: %s\n" msgstr "" #: dasdutil.c:2162 #, c-format msgid "HHCDU064E %s cdevhdr rewrite error: %s\n" msgstr "" #: dasdutil.c:2171 #, c-format msgid "HHCDU065E %s l2tab lseek error: %s\n" msgstr "" #: dasdutil.c:2178 #, c-format msgid "HHCDU066E %s l2tab rewrite error: %s\n" msgstr "" #: dasdutil.c:2187 #, c-format msgid "HHCDU067E %s close error: %s\n" msgstr "" #: dasdutil.c:2194 #, c-format msgid "HHCDU068I %u sectors successfully written to file %s\n" msgstr "" #: dyngui.c:270 #, c-format msgid "HHCDG003S select failed on input stream: %s\n" msgstr "" #: dyngui.c:308 #, c-format msgid "HHCDG004S read failed on input stream: %s\n" msgstr "" #: dyngui.c:1655 dyngui.c:1758 #, c-format msgid "HHCDG005E Device query buffer overflow! (device=%4.4X)\n" msgstr "" #: dyngui.c:1908 #, c-format msgid "HHCDG006S malloc pszInputBuff failed: %s\n" msgstr "" #: dyngui.c:1921 #, c-format msgid "HHCDG007S malloc pszCommandBuff failed: %s\n" msgstr "" #: dyngui.c:1956 msgid "HHCDG001I dyngui.dll initiated\n" msgstr "" #: dyngui.c:1959 msgid "HHCDG002I dyngui.dll terminated\n" msgstr "" #: ecpsvm.c:259 ecpsvm.c:264 ecpsvm.c:281 ecpsvm.c:303 ecpsvm.c:304 #: ecpsvm.c:305 ecpsvm.c:306 msgid "HHCEV300D : SASSIST " msgstr "" #: ecpsvm.c:271 msgid "HHCEV300D : EVMA Disabled by guest\n" msgstr "" #: ecpsvm.c:324 ecpsvm.c:330 msgid "HHCEV300D : CPASSTS " msgstr "" #: ecpsvm.c:338 msgid "HHCEV300D : " msgstr "" #: ecpsvm.c:407 msgid "HHCEV300D : LKPG coreptr = " msgstr "" #: ecpsvm.c:410 #, c-format msgid "HHCEV300D : LKPG corete = %6.6X\n" msgstr "" #: ecpsvm.c:424 #, c-format msgid "HHCEV300D : LKPG Page locked. Count = %6.6X\n" msgstr "" #: ecpsvm.c:441 #, c-format msgid "HHCEV300D : LKPG PAGE=%6.6X, PTRPL=%6.6X\n" msgstr "" #: ecpsvm.c:468 #, c-format msgid "HHCEV300D : ULKPG PAGE=%6.6X, PTRPL=%6.6X\n" msgstr "" #: ecpsvm.c:474 #, c-format msgid "HHCEV300D : ULKPG Page beyond core size of %6.6X\n" msgstr "" #: ecpsvm.c:486 msgid "HHCEV300D : ULKPG Attempting to unlock page that is not locked\n" msgstr "" #: ecpsvm.c:493 msgid "HHCEV300D : ULKPG now unlocked\n" msgstr "" #: ecpsvm.c:497 #, c-format msgid "HHCEV300D : ULKPG Page still locked. Count = %6.6X\n" msgstr "" #: ecpsvm.c:533 #, c-format msgid "HHCEV300D SCNVU Virtual Device %4.4X has no VCHAN block\n" msgstr "" #: ecpsvm.c:541 #, c-format msgid "HHCEV300D SCNVU Virtual Device %4.4X has no VCU block\n" msgstr "" #: ecpsvm.c:549 #, c-format msgid "HHCEV300D SCNVU Virtual Device %4.4X has no VDEV block\n" msgstr "" #: ecpsvm.c:553 #, c-format msgid "HHCEV300D SCNVU %4.4X : VCH = %8.8X, VCU = %8.8X, VDEV = %8.8X\n" msgstr "" #: ecpsvm.c:909 msgid "HHCEV004W : Abend condition detected in DISP2 instr\n" msgstr "" #: ecpsvm.c:1100 #, c-format msgid "HHCPEV300D : DISP2 - Next Instruction : %2.2X\n" msgstr "" #: ecpsvm.c:1163 #, c-format msgid "HHCEV300D : Tranbring : LRA cc = %d\n" msgstr "" #: ecpsvm.c:1172 #, c-format msgid "HHCEV300D : Page not shared - OK %d\n" msgstr "" #: ecpsvm.c:1178 msgid "HHCEV300D : Checking 2K Storage keys @" msgstr "" #: ecpsvm.c:1183 msgid "HHCEV300D : Checking 4K Storage keys @" msgstr "" #: ecpsvm.c:1187 msgid "HHCEV300D : Page shared and changed\n" msgstr "" #: ecpsvm.c:1190 msgid "HHCEV300D : Page shared but not changed\n" msgstr "" #: ecpsvm.c:1209 msgid "HHCEV300D : TRANBRNG\n" msgstr "" #: ecpsvm.c:1213 msgid "HHCEV300D : TRANBRNG - Back to CP\n" msgstr "" #: ecpsvm.c:1231 msgid "HHCEV300D : TRANLOCK\n" msgstr "" #: ecpsvm.c:1235 msgid "HHCEV300D : TRANLOCK - Back to CP\n" msgstr "" #: ecpsvm.c:1748 #, c-format msgid "HHCEV300D : ECPS:VM SCNRU called; RDEV=%4.4X ARIOCT=%6.6X\n" msgstr "" #: ecpsvm.c:1756 #, c-format msgid "HHCEV300D : ECPS:VM SCNRU : RCH IX = %x\n" msgstr "" #: ecpsvm.c:1798 #, c-format msgid "HHCEV300D : ECPS:VM SCNRU : RCU IX = %x\n" msgstr "" #: ecpsvm.c:1818 #, c-format msgid "HHCEV300D : ECPS:VM SCNRU : RDV IX = %x\n" msgstr "" #: ecpsvm.c:1822 #, c-format msgid "HHCEV300D : ECPS:VM SCNRU : RCH = %6.6X, RCU = %6.6X, RDV = %6.6X\n" msgstr "" #: ecpsvm.c:1866 #, c-format msgid "HHCEV300D : ECPS:VM STORE LEVEL %d called\n" msgstr "" #: ecpsvm.c:1906 #, c-format msgid "HHCEV300D : ECPS:VM FREEX DW = %4.4X\n" msgstr "" #: ecpsvm.c:1911 #, c-format msgid "HHCEV300D : MAXSIZE ADDR = %6.6X, SUBPOOL INDEX TABLE = %6.6X\n" msgstr "" #: ecpsvm.c:1918 msgid "HHCEV300D : FREEX request beyond subpool capacity\n" msgstr "" #: ecpsvm.c:1923 #, c-format msgid "HHCEV300D : Subpool index = %X\n" msgstr "" #: ecpsvm.c:1926 #, c-format msgid "HHCEV300D : Value in subpool table = %6.6X\n" msgstr "" #: ecpsvm.c:1934 #, c-format msgid "HHCEV300D : New Value in subpool table = %6.6X\n" msgstr "" #: ecpsvm.c:1964 #, c-format msgid "HHCEV300D : X fretx called AREA=%6.6X, DW=%4.4X\n" msgstr "" #: ecpsvm.c:1967 msgid "HHCEV300D : ECPS:VM Cannot FRETX : DWORDS = 0\n" msgstr "" #: ecpsvm.c:1973 #, c-format msgid "HHCEV300D : ECPS:VM Cannot FRETX : DWORDS = %d > MAXDW %d\n" msgstr "" #: ecpsvm.c:1980 msgid "HHCEV300D : ECPS:VM Cannot FRETX : Area not in Core Free area\n" msgstr "" #: ecpsvm.c:1985 msgid "HHCEV300D : ECPS:VM Cannot FRETX : Area flag != 0x02\n" msgstr "" #: ecpsvm.c:1992 msgid "" "HHCEV300D : ECPS:VM Cannot FRETX : fretted block already on subpool chain\n" msgstr "" #: ecpsvm.c:2062 msgid "HHCEV300D : New and Old PSW have a EC/BC transition\n" msgstr "" #: ecpsvm.c:2070 msgid "HHCEV300D : New PSW Enables DAT or PER\n" msgstr "" #: ecpsvm.c:2081 msgid "HHCEV300D : New PSW Enables interrupts and MICPEND (EC)\n" msgstr "" #: ecpsvm.c:2089 msgid "HHCEV300D : New PSW Enables interrupts and MICPEND (BC)\n" msgstr "" #: ecpsvm.c:2096 msgid "HHCEV300D : New PSW is a WAIT PSW\n" msgstr "" #: ecpsvm.c:2103 msgid "HHCEV300D : New PSW sysmask incorrect\n" msgstr "" #: ecpsvm.c:2109 msgid "HHCEV300D : New PSW has ODD IA\n" msgstr "" #: ecpsvm.c:2596 ecpsvm.c:2613 #, c-format msgid "HHCEV001I | %-9s | %8d | %8d | %3d%% |\n" msgstr "" #: ecpsvm.c:2623 #, c-format msgid "HHCEV004I * : Unsupported, - : Disabled, %% - Debug\n" msgstr "" #: ecpsvm.c:2627 #, c-format msgid "HHCEV005I %d Entr%s not shown (never invoked)\n" msgstr "" #: ecpsvm.c:2633 msgid "HHCEV006I 1 call was made to an unsupported function\n" msgstr "" #: ecpsvm.c:2637 #, c-format msgid "HHCEV006I %d calls where made to unsupported functions\n" msgstr "" #: ecpsvm.c:2652 ecpsvm.c:2661 #, c-format msgid "HHCEV002I | %-9s | %-8s | %-8s | %-5s |\n" msgstr "" #: ecpsvm.c:2716 #, c-format msgid "HHCEV015I ECPS:VM %s feature %s %s\n" msgstr "" #: ecpsvm.c:2721 #, c-format msgid "HHCEV015I ECPS:VM %s feature %s Debug %s\n" msgstr "" #: ecpsvm.c:2726 #, c-format msgid "HHCEV016I All ECPS:VM %s features %s\n" msgstr "" #: ecpsvm.c:2730 #, c-format msgid "HHCEV016I All ECPS:VM %s features Debug %s\n" msgstr "" #: ecpsvm.c:2758 #, c-format msgid "HHCEV013I ECPS:VM Global Debug %s\n" msgstr "" #: ecpsvm.c:2786 #, c-format msgid "HHCEV014I ECPS:VM %s feature %s %s\n" msgstr "" #: ecpsvm.c:2791 #, c-format msgid "HHCEV014I ECPS:VM %s feature %s Debug %s\n" msgstr "" #: ecpsvm.c:2796 #, c-format msgid "HHCEV014I Unknown ECPS:VM feature %s; Ignored\n" msgstr "" #: ecpsvm.c:2823 ecpsvm.c:2827 #, c-format msgid "HHCEV016I Current reported ECPS:VM Level is %d\n" msgstr "" #: ecpsvm.c:2828 msgid "HHCEV017I But ECPS:VM is currently disabled\n" msgstr "" #: ecpsvm.c:2833 #, c-format msgid "HHCEV016I Level reported to guest program is now %d\n" msgstr "" #: ecpsvm.c:2838 #, c-format msgid "HHCEV017W WARNING ! current level (%d) is not supported\n" msgstr "" #: ecpsvm.c:2839 msgid "HHCEV018W WARNING ! Unpredictable results may occur\n" msgstr "" #: ecpsvm.c:2840 msgid "HHCEV019I The microcode support level is 20\n" msgstr "" #: ecpsvm.c:2867 #, c-format msgid "HHCEV010I : %s : %s\n" msgstr "" #: ecpsvm.c:2883 #, c-format msgid "HHCEV011E Unknown subcommand %s - valid subcommands are :\n" msgstr "" #: ecpsvm.c:2887 #, c-format msgid "HHCEV012I : %s : %s" msgstr "" #: ecpsvm.c:2913 msgid "HHCEV011I ECPS:VM Command processor invoked\n" msgstr "" #: ecpsvm.c:2916 msgid "" "HHCEV008E NO EVM subcommand. Type \"evm help\" for a list of valid " "subcommands\n" msgstr "" #: ecpsvm.c:2922 #, c-format msgid "HHCEV008E Unknown EVM subcommand %s\n" msgstr "" #: ecpsvm.c:2926 msgid "HHCEV011I ECPS:VM Command processor complete\n" msgstr "" #: external.c:173 msgid "HHCCP023I External interrupt: Interrupt key\n" msgstr "" #: external.c:284 msgid "HHCCP024I External interrupt: Clock comparator\n" msgstr "" #: external.c:295 msgid "HHCCP025I External interrupt: CPU timer=%16.16" msgstr "" #: external.c:311 msgid "HHCCP026I External interrupt: Interval timer\n" msgstr "" #: fbadasd.c:91 msgid "HHCDA056E File name missing or invalid\n" msgstr "" #: fbadasd.c:108 #, c-format msgid "HHCDA057E %4.4X:File not found or invalid\n" msgstr "" #: fbadasd.c:124 #, c-format msgid "HHCDA058E File %s open error: %s\n" msgstr "" #: fbadasd.c:136 #, c-format msgid "HHCDA059E Read error in file %s: %s\n" msgstr "" #: fbadasd.c:139 #, c-format msgid "HHCDA060E Unexpected end of file in %s\n" msgstr "" #: fbadasd.c:157 #, c-format msgid "HHCDA061E Read error in file %s: %s\n" msgstr "" #: fbadasd.c:160 #, c-format msgid "HHCDA062E Unexpected end of file in %s\n" msgstr "" #: fbadasd.c:213 #, c-format msgid "HHCDA063E parameter %d is invalid: %s\n" msgstr "" #: fbadasd.c:226 #, c-format msgid "HHCDA064E File %s fstat error: %s\n" msgstr "" #: fbadasd.c:238 #, c-format msgid "HHCDA082E File %s IOCTL BLKGETSIZE error: %s\n" msgstr "" #: fbadasd.c:264 #, c-format msgid "HHCDA065E Invalid device origin block number %s\n" msgstr "" #: fbadasd.c:280 #, c-format msgid "HHCDA066E Invalid device block count %s\n" msgstr "" #: fbadasd.c:291 #, c-format msgid "HHCDA067I %s origin=%lld blks=%d\n" msgstr "" #: fbadasd.c:301 #, c-format msgid "HHCDA068E %4.4X device type %4.4X not found in dasd table\n" msgstr "" #: fbadasd.c:526 #, c-format msgid "HHCDA069E error writing blkgrp %d: lseek error: %s\n" msgstr "" #: fbadasd.c:544 #, c-format msgid "HHCDA070E error writing blkgrp %d: write error: %s\n" msgstr "" #: fbadasd.c:585 #, c-format msgid "HHCDA071I read blkgrp %d cache hit, using cache[%d]\n" msgstr "" #: fbadasd.c:610 #, c-format msgid "HHCDA072I read blkgrp %d no available cache entry, waiting\n" msgstr "" #: fbadasd.c:618 #, c-format msgid "HHCDA073I read blkgrp %d cache miss, using cache[%d]\n" msgstr "" #: fbadasd.c:634 msgid "HHCDA074I read blkgrp %d offset %" msgstr "" #: fbadasd.c:642 #, c-format msgid "HHCDA075E error reading blkgrp %d: lseek error: %s\n" msgstr "" #: fbadasd.c:657 #, c-format msgid "HHCDA076E error reading blkgrp %d: read error: %s\n" msgstr "" #: fbadasd.c:1085 msgid "HHCDA077I Positioning to %8.8" msgstr "" #: fbadasd.c:1103 #, c-format msgid "HHCDA078E define extent data too short: %d bytes\n" msgstr "" #: fbadasd.c:1113 msgid "HHCDA079E second define extent in chain\n" msgstr "" #: fbadasd.c:1124 #, c-format msgid "HHCDA080E invalid file mask %2.2X\n" msgstr "" #: fbadasd.c:1161 #, c-format msgid "HHCDA081E invalid extent: first block %d, last block %d,\n" msgstr "" #: fbadasd.c:1163 #, c-format msgid " numblks %d, device size %d\n" msgstr "" #: fbadasd.c:1435 #, c-format msgid "HHCDA901E %4.4x FBA origin mismatch: %d, expected %d,\n" msgstr "" #: fbadasd.c:1444 #, c-format msgid "HHCDA902E %4.4x FBA numblk mismatch: %d, expected %d,\n" msgstr "" #: fbadasd.c:1474 #, c-format msgid "HHCDA903E %4.4x FBA blksiz mismatch: %d, expected %d,\n" msgstr "" #: general1.c:3704 msgid "MVCL destructive overlap: " msgstr "" #: hdl.c:138 #, c-format msgid "HHCHD018I Loadable module directory is %s\n" msgstr "" #: hdl.c:411 #, c-format msgid "HHCHD010I Dependency check failed for %s, version(%s) expected(%s)\n" msgstr "" #: hdl.c:418 #, c-format msgid "HHCHD011I Dependency check failed for %s, size(%d) expected(%d)\n" msgstr "" #: hdl.c:460 #, c-format msgid "HHCHD001E registration malloc failed for %s\n" msgstr "" #: hdl.c:588 hdl.c:792 #, c-format msgid "HHCHD007E unable to open DLL %s: %s\n" msgstr "" #: hdl.c:598 hdl.c:802 #, c-format msgid "HHCHD013E No dependency section in %s: %s\n" msgstr "" #: hdl.c:622 hdl.c:840 #, c-format msgid "HHCHD014E Dependency check failed for module %s\n" msgstr "" #: hdl.c:675 #, c-format msgid "HHCHD002E cannot allocate memory for DLL descriptor: %s\n" msgstr "" #: hdl.c:690 #, c-format msgid "HHCHD003E unable to open hercules as DLL: %s\n" msgstr "" #: hdl.c:699 #, c-format msgid "HHCHD012E No dependency section in %s: %s\n" msgstr "" #: hdl.c:775 #, c-format msgid "HHCHD005E %s already loaded\n" msgstr "" #: hdl.c:782 #, c-format msgid "HHCHD006S cannot allocate memory for DLL descriptor: %s\n" msgstr "" #: hdl.c:813 #, c-format msgid "HHCHD016E DLL %s is duplicate of %s\n" msgstr "" #: hdl.c:907 #, c-format msgid "HHCHD015E Unloading of %s not allowed\n" msgstr "" #: hdl.c:917 #, c-format msgid "HHCHD008E Device %4.4X bound to %s\n" msgstr "" #: hdl.c:929 #, c-format msgid "HHCHD017E Unload of %s rejected by final section\n" msgstr "" #: hdl.c:989 #, c-format msgid "HHCHD009E %s not found\n" msgstr "" #: hercifc.c:66 #, c-format msgid "HHCIF001E %s: Must be called from within Hercules.\n" msgstr "" #: hercifc.c:77 #, c-format msgid "HHCIF002E %s: Cannot obtain socket: %s\n" msgstr "" #: hercifc.c:94 #, c-format msgid "HHCIF003E %s: I/O error on read: %s.\n" msgstr "" #: hercifc.c:103 #, c-format msgid "HHCIF007E %s: Hercules disappeared!! .. exiting\n" msgstr "" #: hercifc.c:210 #, c-format msgid "HHCIF004W %s: Unknown request: %8.8lX.\n" msgstr "" #: hercifc.c:218 #, c-format msgid "HHCIF006I %s: Doing %s on %s\n" msgstr "" #: hercifc.c:239 #, c-format msgid "HHCIF005E %s: ioctl error doing %s on %s: %d %s\n" msgstr "" #: hostinfo.c:90 #, c-format msgid "Running on %s %s-%s.%s %s%s" msgstr "" #: hsccmd.c:158 #, c-format msgid "HHCPN181E Device number %d:%4.4X not found\n" msgstr "" #: hsccmd.c:164 msgid "HHCPN031E Missing device number\n" msgstr "" #: hsccmd.c:181 msgid "Improper command format" msgstr "" #: hsccmd.c:190 #, c-format msgid "\"%s\": invalid maxrates interval" msgstr "" #: hsccmd.c:196 #, c-format msgid "Maxrates interval set to %d minutes.\n" msgstr "" #: hsccmd.c:200 msgid "; enter \"help maxrates\" for help.\n" msgstr "" #: hsccmd.c:358 msgid "HHCPN160E no argument\n" msgstr "" #: hsccmd.c:372 #, c-format msgid "HHCPN195I Log options:%s\n" msgstr "" #: hsccmd.c:385 msgid "HHCPN197I Log option set: TIMESTAMP\n" msgstr "" #: hsccmd.c:392 msgid "HHCPN197I Log option set: NOTIMESTAMP\n" msgstr "" #: hsccmd.c:396 #, c-format msgid "HHCPN196E Invalid logopt value %s\n" msgstr "" #: hsccmd.c:462 #, c-format msgid "HHCPN017E Device %d:%4.4X is not a printer device\n" msgstr "" #: hsccmd.c:476 #, c-format msgid "HHCPN018I Printer %d:%4.4X started\n" msgstr "" #: hsccmd.c:478 #, c-format msgid "HHCPN019E Printer %d:%4.4X not started: busy or interrupt pending\n" msgstr "" #: hsccmd.c:481 #, c-format msgid "HHCPN020E Printer %d:%4.4X not started: attention request rejected\n" msgstr "" #: hsccmd.c:484 #, c-format msgid "HHCPN021E Printer %d:%4.4X not started: subchannel not enabled\n" msgstr "" #: hsccmd.c:565 #, c-format msgid "HHCPN024E Device %d:%4.4X is not a printer device\n" msgstr "" #: hsccmd.c:572 #, c-format msgid "HHCPN025I Printer %d:%4.4X stopped\n" msgstr "" #: hsccmd.c:666 #, c-format msgid "HHCPN152I CPU%4.4X online\n" msgstr "" #: hsccmd.c:673 #, c-format msgid "HHCPN153I CPU%4.4X offline\n" msgstr "" #: hsccmd.c:709 #, c-format msgid "HHCPN154I CPU%4.4X online\n" msgstr "" #: hsccmd.c:716 #, c-format msgid "HHCPN155I CPU%4.4X offline\n" msgstr "" #: hsccmd.c:741 msgid "HHCPN026W Ignored. (external GUI active)\n" msgstr "" #: hsccmd.c:746 #, c-format msgid "HHCPN027I Automatic refresh %s.\n" msgstr "" #: hsccmd.c:747 msgid "disabled" msgstr "" #: hsccmd.c:747 msgid "enabled" msgstr "" #: hsccmd.c:826 #, c-format msgid "HHCPN037I Timer update interval = %d microsecond(s)\n" msgstr "" #: hsccmd.c:868 hsccmd.c:1323 hsccmd.c:1487 hsccmd.c:1547 hsccmd.c:1575 #: hsccmd.c:1603 hsccmd.c:1631 hsccmd.c:1659 hsccmd.c:1690 hsccmd.c:1719 #: hsccmd.c:1756 hsccmd.c:1783 hsccmd.c:1810 hsccmd.c:3240 hsccmd.c:3388 #: hsccmd.c:3455 hsccmd.c:4851 hsccmd.c:4955 hsccmd.c:5048 hsccmd.c:5090 #, c-format msgid "HHCPN160W CPU%4.4X not configured\n" msgstr "" #: hsccmd.c:903 msgid "HHCPN028I tod = %16.16" msgstr "" #: hsccmd.c:906 msgid " h/w = %16.16" msgstr "" #: hsccmd.c:918 msgid " off = %16.16" msgstr "" #: hsccmd.c:922 msgid " ckc = %16.16" msgstr "" #: hsccmd.c:926 msgid " cpt = %16.16" msgstr "" #: hsccmd.c:928 msgid " cpt = not decrementing\n" msgstr "" #: hsccmd.c:934 msgid " vtod = %16.16" msgstr "" #: hsccmd.c:946 msgid " voff = %16.16" msgstr "" #: hsccmd.c:950 msgid " vckc = %16.16" msgstr "" #: hsccmd.c:953 msgid " vcpt = %16.16" msgstr "" #: hsccmd.c:959 msgid " itm = %8.8" msgstr "" #: hsccmd.c:981 #, c-format msgid "HHCPN029E Invalid I/O delay value: %s\n" msgstr "" #: hsccmd.c:986 #, c-format msgid "HHCPN030I I/O delay = %d\n" msgstr "" #: hsccmd.c:1064 #, c-format msgid "HHCCF068E Invalid value: %s; Enter \"help scsimount\" for help.\n" msgstr "" #: hsccmd.c:1075 #, c-format msgid "SCSI auto-mount queries = every %d seconds (when needed)\n" msgstr "" #: hsccmd.c:1078 msgid "SCSI auto-mount queries are disabled.\n" msgstr "" #: hsccmd.c:1093 #, c-format msgid "SCSI auto-mount thread %s active for drive %u:%4.4X = %s.\n" msgstr "" #: hsccmd.c:1168 #, c-format msgid "" "\n" "%s\n" "HHCCF069I %s of %s-labeled volume \"%s\" pending for drive %u:%4.4X = %s\n" "%s\n" "\n" msgstr "" #: hsccmd.c:1182 #, c-format msgid "No mount/dismount requests pending for drive %u:%4.4X = %s.\n" msgstr "" #: hsccmd.c:1215 msgid "HHCPN186E cmd deprecated; try 'tt32' instead\n" msgstr "" #: hsccmd.c:1232 msgid "HHCPN188E Missing arguments; enter 'help tt32' for help.\n" msgstr "" #: hsccmd.c:1255 #, c-format msgid "HHCPN034E Device %d:%4.4X is not a CTCI or LCS device\n" msgstr "" #: hsccmd.c:1264 hsccmd.c:1278 hsccmd.c:1292 msgid "(error)\n" msgstr "" #: hsccmd.c:1274 msgid "HHCPN189I TT32 debug tracing messages enabled\n" msgstr "" #: hsccmd.c:1288 msgid "HHCPN189I TT32 debug tracing messages disabled\n" msgstr "" #: hsccmd.c:1298 msgid "HHCPN187E Invalid argument\n" msgstr "" #: hsccmd.c:1331 msgid "HHCPN035E store status rejected: CPU not stopped\n" msgstr "" #: hsccmd.c:1367 #, c-format msgid "HHCPN036I TOD clock drag factor = %lf\n" msgstr "" #: hsccmd.c:1399 #, c-format msgid "HHCPN037I Panel refresh rate = %d millisecond(s)\n" msgstr "" #: hsccmd.c:1417 hsccmd.c:1439 hsccmd.c:1460 msgid "HHCPN180E shell commands are disabled\n" msgstr "" #: hsccmd.c:1465 msgid "HHCPN163E Invalid format. Command does not support any arguments.\n" msgstr "" #: hsccmd.c:1502 msgid "HHCPN162E Invalid format. Enter \"help gpr\" for help.\n" msgstr "" #: hsccmd.c:1514 msgid "HHCPN162E Invalid format. .Enter \"help gpr\" for help.\n" msgstr "" #: hsccmd.c:1711 msgid "HHCPN038I Restart key depressed\n" msgstr "" #: hsccmd.c:1845 hsccmd.c:1861 msgid "HHCPN039E Invalid arguments\n" msgstr "" #: hsccmd.c:1909 #, c-format msgid "HHCPN040I Instruction %s %s %s\n" msgstr "" #: hsccmd.c:1910 msgid "tracing" msgstr "" #: hsccmd.c:1911 msgid "stepping" msgstr "" #: hsccmd.c:1911 msgid "break" msgstr "" #: hsccmd.c:1912 hsccmd.c:4840 msgid "on" msgstr "" #: hsccmd.c:1912 hsccmd.c:4843 msgid "off" msgstr "" #: hsccmd.c:1953 #, c-format msgid "HHCPN045I Device %4.4X attention request raised\n" msgstr "" #: hsccmd.c:1956 #, c-format msgid "HHCPN046E Device %4.4X busy or interrupt pending\n" msgstr "" #: hsccmd.c:1959 #, c-format msgid "HHCPN047E Device %4.4X attention request rejected\n" msgstr "" #: hsccmd.c:1962 #, c-format msgid "HHCPN048E Device %4.4X subchannel not enabled\n" msgstr "" #: hsccmd.c:1969 #, c-format msgid "HHCPN049W Are you sure you didn't mean 'ipl %4.4X' instead?\n" msgstr "" #: hsccmd.c:1988 msgid "HHCPN050I Interrupt key depressed\n" msgstr "" #: hsccmd.c:2011 #, c-format msgid "HHCPN051I LOADPARM=%s\n" msgstr "" #: hsccmd.c:2030 msgid "HHCPN053E System reset/clear rejected: All CPU's must be stopped\n" msgstr "" #: hsccmd.c:2078 msgid "HHCPN053E ipl rejected: All CPU's must be stopped\n" msgstr "" #: hsccmd.c:2106 hsccmd.c:2522 #, c-format msgid "HHCPN059E LCSS id %s is invalid\n" msgstr "" #: hsccmd.c:2143 msgid "HHCPN054E Missing argument\n" msgstr "" #: hsccmd.c:2150 #, c-format msgid "HHCPN055E Target CPU %s is invalid\n" msgstr "" #: hsccmd.c:2237 hsccmd.c:2369 #, c-format msgid "HHCPN146E Work buffer malloc failed: %s\n" msgstr "" #: hsccmd.c:2295 msgid "open " msgstr "" #: hsccmd.c:2296 msgid "busy " msgstr "" #: hsccmd.c:2297 msgid "pending " msgstr "" #: hsccmd.c:2308 #, c-format msgid " (client %s (%s) connected)\n" msgstr "" #: hsccmd.c:2314 msgid " (no one currently connected)\n" msgstr "" #: hsccmd.c:2326 hsccmd.c:2475 #, c-format msgid "HHCPN147W Warning: not all devices shown (max %d)\n" msgstr "" #: hsccmd.c:2495 msgid "HHCPN057E Missing argument(s)\n" msgstr "" #: hsccmd.c:2514 #, c-format msgid "HHCPN059E Device number %s is invalid\n" msgstr "" #: hsccmd.c:2532 #, c-format msgid "Device type %s is invalid\n" msgstr "" #: hsccmd.c:2580 msgid "HHCPN062E Missing argument(s)\n" msgstr "" #: hsccmd.c:2596 msgid "" "HHCPN182E Device numbers can only be redefined within the same Logical " "channel subsystem\n" msgstr "" #: hsccmd.c:2616 msgid "HHCPN065E Missing argument(s)\n" msgstr "" #: hsccmd.c:2644 #, c-format msgid "HHCPN066E Program interrupt number %s is invalid\n" msgstr "" #: hsccmd.c:2651 #, c-format msgid "HHCPN067E Program interrupt number out of range (%4.4X)\n" msgstr "" #: hsccmd.c:2683 #, c-format msgid "OSTAILOR %s\n" msgstr "" #: hsccmd.c:2771 #, c-format msgid "Unknown OS tailor specification %s\n" msgstr "" #: hsccmd.c:2846 msgid "HHCPN072I %4.4X synchronous: %12" msgstr "" #: hsccmd.c:2857 msgid "HHCPN073I No synchronous I/O devices found\n" msgstr "" #: hsccmd.c:2859 msgid "HHCPN074I TOTAL synchronous: %12" msgstr "" #: hsccmd.c:2898 msgid "HHCPN075E Invalid max device threads value (must be -1 to n)\n" msgstr "" #: hsccmd.c:2905 #, c-format msgid "" "HHCPN076I Max device threads: %d, current: %d, most: %d, waiting: %d, max " "exceeded: %d\n" msgstr "" #: hsccmd.c:2926 msgid "HHCPN077E Invalid max device threads value (must be -1 to n)\n" msgstr "" #: hsccmd.c:2940 #, c-format msgid "" "HHCPN078E Max device threads %d current %d most %d waiting %d total I/Os " "queued %d\n" msgstr "" #: hsccmd.c:2969 msgid "HHCPN091E Command must be 'sf+', 'sf-', 'sfc', or 'sfd'\n" msgstr "" #: hsccmd.c:2998 msgid "HHCPN081E No cckd devices found\n" msgstr "" #: hsccmd.c:3011 #, c-format msgid "HHCPN084E Device number %d:%4.4X is not a cckd device\n" msgstr "" #: hsccmd.c:3028 msgid "HHCPN087E Operand must be `merge', `nomerge' or `force'\n" msgstr "" #: hsccmd.c:3038 #, c-format msgid "HHCPN089E Unexpected operand: %s\n" msgstr "" #: hsccmd.c:3045 #, c-format msgid "HHCPN085I Processing device %d:%4.4X\n" msgstr "" #: hsccmd.c:3067 #, c-format msgid "HHCPN092I %d devices processed\n" msgstr "" #: hsccmd.c:3089 msgid "HHCPN093E Missing argument(s)\n" msgstr "" #: hsccmd.c:3114 #, c-format msgid "HHCPN096E Device %d:%4.4X busy or interrupt pending\n" msgstr "" #: hsccmd.c:3130 #, c-format msgid "HHCPN183E Reinit rejected for drive %u:%4.4X; drive not empty\n" msgstr "" #: hsccmd.c:3170 #, c-format msgid "HHCPN097E Initialization failed for device %d:%4.4X\n" msgstr "" #: hsccmd.c:3173 #, c-format msgid "HHCPN098I Device %d:%4.4X initialized\n" msgstr "" #: hsccmd.c:3229 msgid "HHCPN099E savecore rejected: filename missing\n" msgstr "" #: hsccmd.c:3262 #, c-format msgid "HHCPN100E savecore: invalid starting address: %s \n" msgstr "" #: hsccmd.c:3280 msgid "HHCPN148E savecore: no modified storage found\n" msgstr "" #: hsccmd.c:3288 #, c-format msgid "HHCPN101E savecore: invalid ending address: %s \n" msgstr "" #: hsccmd.c:3297 msgid "HHCPN102E savecore rejected: CPU not stopped\n" msgstr "" #: hsccmd.c:3304 #, c-format msgid "HHCPN103E invalid range: %8.8X-%8.8X\n" msgstr "" #: hsccmd.c:3309 #, c-format msgid "HHCPN104I Saving locations %8.8X-%8.8X to %s\n" msgstr "" #: hsccmd.c:3318 #, c-format msgid "HHCPN105E savecore error creating %s: %s\n" msgstr "" #: hsccmd.c:3324 #, c-format msgid "HHCPN106E savecore error writing to %s: %s\n" msgstr "" #: hsccmd.c:3327 #, c-format msgid "HHCPN107E savecore: unable to save %d bytes\n" msgstr "" #: hsccmd.c:3334 msgid "HHCPN170I savecore command complete.\n" msgstr "" #: hsccmd.c:3357 msgid "HHCPN108E loadcore rejected: filename missing\n" msgstr "" #: hsccmd.c:3366 #, c-format msgid "HHCPN109E Cannot open %s: %s\n" msgstr "" #: hsccmd.c:3378 #, c-format msgid "HHCPN110E invalid address: %s \n" msgstr "" #: hsccmd.c:3397 msgid "HHCPN111E loadcore rejected: CPU not stopped\n" msgstr "" #: hsccmd.c:3402 #, c-format msgid "HHCPN112I Loading %s to location %x \n" msgstr "" #: hsccmd.c:3408 #, c-format msgid "HHCPN113I %d bytes read from %s\n" msgstr "" #: hsccmd.c:3432 msgid "HHCPN114E loadtext rejected: filename missing\n" msgstr "" #: hsccmd.c:3445 #, c-format msgid "HHCPN115E invalid address: %s \n" msgstr "" #: hsccmd.c:3463 msgid "HHCPN116E Address greater than mainstore size\n" msgstr "" #: hsccmd.c:3471 msgid "HHCPN117E loadtext rejected: CPU not stopped\n" msgstr "" #: hsccmd.c:3480 #, c-format msgid "HHCPN118E Cannot open %s: %s\n" msgstr "" #: hsccmd.c:3491 #, c-format msgid "HHCPN119E Cannot read %s: %s\n" msgstr "" #: hsccmd.c:3514 msgid "HHCPN120I Finished loading TEXT deck file\n" msgstr "" #: hsccmd.c:3515 #, c-format msgid " Last 'TXT' record had address: %3.3X\n" msgstr "" #: hsccmd.c:3541 #, c-format msgid "HHCPN123I CPU%4.4X: offline\n" msgstr "" #: hsccmd.c:3547 #, c-format msgid "HHCPN123I CPU%4.4X: CPUint=%8.8X (State:%8.8X)&(Mask:%8.8X)\n" msgstr "" #: hsccmd.c:3552 #, c-format msgid " CPU%4.4X: Interrupt %spending\n" msgstr "" #: hsccmd.c:3554 hsccmd.c:3558 hsccmd.c:3562 hsccmd.c:3566 hsccmd.c:3571 #: hsccmd.c:3576 hsccmd.c:3582 hsccmd.c:3586 hsccmd.c:3590 hsccmd.c:3594 #: hsccmd.c:3610 hsccmd.c:3649 hsccmd.c:3653 hsccmd.c:3657 hsccmd.c:3661 #: hsccmd.c:3665 hsccmd.c:3669 hsccmd.c:3673 hsccmd.c:3677 hsccmd.c:3681 #: hsccmd.c:3685 hsccmd.c:3724 hsccmd.c:3727 hsccmd.c:3730 hsccmd.c:3734 #: hsccmd.c:3739 msgid "not " msgstr "" #: hsccmd.c:3556 #, c-format msgid " CPU%4.4X: I/O interrupt %spending\n" msgstr "" #: hsccmd.c:3560 #, c-format msgid " CPU%4.4X: Clock comparator %spending\n" msgstr "" #: hsccmd.c:3564 #, c-format msgid " CPU%4.4X: CPU timer %spending\n" msgstr "" #: hsccmd.c:3569 #, c-format msgid " CPU%4.4X: Interval timer %spending\n" msgstr "" #: hsccmd.c:3574 #, c-format msgid " CPU%4.4X: ECPS vtimer %spending\n" msgstr "" #: hsccmd.c:3580 #, c-format msgid " CPU%4.4X: External call %spending\n" msgstr "" #: hsccmd.c:3584 #, c-format msgid " CPU%4.4X: Emergency signal %spending\n" msgstr "" #: hsccmd.c:3588 #, c-format msgid " CPU%4.4X: Machine check interrupt %spending\n" msgstr "" #: hsccmd.c:3592 #, c-format msgid " CPU%4.4X: Service signal %spending\n" msgstr "" #: hsccmd.c:3596 #, c-format msgid " CPU%4.4X: Mainlock held: %s\n" msgstr "" #: hsccmd.c:3598 hsccmd.c:3602 hsccmd.c:3606 msgid "yes" msgstr "" #: hsccmd.c:3598 hsccmd.c:3602 hsccmd.c:3606 msgid "no" msgstr "" #: hsccmd.c:3600 #, c-format msgid " CPU%4.4X: Intlock held: %s\n" msgstr "" #: hsccmd.c:3604 #, c-format msgid " CPU%4.4X: Waiting for intlock: %s\n" msgstr "" #: hsccmd.c:3608 #, c-format msgid " CPU%4.4X: lock %sheld\n" msgstr "" #: hsccmd.c:3615 #, c-format msgid " CPU%4.4X: No channelset connected\n" msgstr "" #: hsccmd.c:3619 #, c-format msgid " CPU%4.4X: Connected to channelset %4.4X\n" msgstr "" #: hsccmd.c:3624 #, c-format msgid " CPU%4.4X: state %s\n" msgstr "" #: hsccmd.c:3626 msgid " CPU%4.4X: instcount %" msgstr "" #: hsccmd.c:3628 msgid " CPU%4.4X: siocount %" msgstr "" #: hsccmd.c:3631 #, c-format msgid " CPU%4.4X: psw %2.2x%2.2x%2.2x%2.2x %2.2x%2.2x%2.2x%2.2x" msgstr "" #: hsccmd.c:3635 hsccmd.c:3710 #, c-format msgid " %2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x" msgstr "" #: hsccmd.c:3642 #, c-format msgid "HHCPN123I SIE%4.4X: CPUint=%8.8X (State:%8.8X)&(Mask:%8.8X)\n" msgstr "" #: hsccmd.c:3647 #, c-format msgid " SIE%4.4X: Interrupt %spending\n" msgstr "" #: hsccmd.c:3651 #, c-format msgid " SIE%4.4X: I/O interrupt %spending\n" msgstr "" #: hsccmd.c:3655 #, c-format msgid " SIE%4.4X: Clock comparator %spending\n" msgstr "" #: hsccmd.c:3659 #, c-format msgid " SIE%4.4X: CPU timer %spending\n" msgstr "" #: hsccmd.c:3663 #, c-format msgid " SIE%4.4X: Interval timer %spending\n" msgstr "" #: hsccmd.c:3667 #, c-format msgid " SIE%4.4X: External call %spending\n" msgstr "" #: hsccmd.c:3671 #, c-format msgid " SIE%4.4X: Emergency signal %spending\n" msgstr "" #: hsccmd.c:3675 #, c-format msgid " SIE%4.4X: Machine check interrupt %spending\n" msgstr "" #: hsccmd.c:3679 #, c-format msgid " SIE%4.4X: Service signal %spending\n" msgstr "" #: hsccmd.c:3683 #, c-format msgid " SIE%4.4X: lock %sheld\n" msgstr "" #: hsccmd.c:3690 #, c-format msgid " SIE%4.4X: No channelset connected\n" msgstr "" #: hsccmd.c:3694 #, c-format msgid " SIE%4.4X: Connected to channelset %4.4X\n" msgstr "" #: hsccmd.c:3699 #, c-format msgid " SIE%4.4X: state %s\n" msgstr "" #: hsccmd.c:3701 msgid " SIE%4.4X: instcount %" msgstr "" #: hsccmd.c:3703 msgid " SIE%4.4X: siocount %" msgstr "" #: hsccmd.c:3706 #, c-format msgid " SIE%4.4X: psw %2.2x%2.2x%2.2x%2.2x %2.2x%2.2x%2.2x%2.2x" msgstr "" #: hsccmd.c:3717 #, c-format msgid " Config mask %8.8X started mask %8.8X waiting mask %8.8X\n" msgstr "" #: hsccmd.c:3720 #, c-format msgid " Syncbc mask %8.8x %s\n" msgstr "" #: hsccmd.c:3721 msgid "Sync in progress" msgstr "" #: hsccmd.c:3723 #, c-format msgid " Signaling facility %sbusy\n" msgstr "" #: hsccmd.c:3726 #, c-format msgid " TOD lock %sheld\n" msgstr "" #: hsccmd.c:3729 #, c-format msgid " Mainlock %sheld; owner %4.4x\n" msgstr "" #: hsccmd.c:3733 #, c-format msgid " Intlock %sheld; owner %4.4x\n" msgstr "" #: hsccmd.c:3738 #, c-format msgid " Ioq lock %sheld\n" msgstr "" #: hsccmd.c:3752 #, c-format msgid " DEV %d:%4.4X: busy %s\n" msgstr "" #: hsccmd.c:3754 #, c-format msgid " DEV %d:%4.4X: reserved %s\n" msgstr "" #: hsccmd.c:3756 #, c-format msgid " DEV %d:%4.4X: suspended\n" msgstr "" #: hsccmd.c:3758 #, c-format msgid " DEV %d:%4.4X: I/O pending\n" msgstr "" #: hsccmd.c:3760 #, c-format msgid " DEV %d:%4.4X: PCI pending\n" msgstr "" #: hsccmd.c:3762 #, c-format msgid " DEV %d:%4.4X: Attn pending\n" msgstr "" #: hsccmd.c:3764 #, c-format msgid " DEV %d:%4.4X: CRW pending\n" msgstr "" #: hsccmd.c:3766 #, c-format msgid " DEV %d:%4.4X: lock held\n" msgstr "" #: hsccmd.c:3769 msgid " I/O interrupt queue: " msgstr "" #: hsccmd.c:3772 msgid "(NULL)" msgstr "" #: hsccmd.c:3778 #, c-format msgid " DEV %d:%4.4X,%s%s%s%s, pri %d\n" msgstr "" #: hsccmd.c:3812 msgid "HHCPN124I Instruction counts reset to zero.\n" msgstr "" #: hsccmd.c:4247 msgid "HHCPN125I Sorted instruction count display:\n" msgstr "" #: hsccmd.c:4345 msgid "HHCPN125I Instruction count display:\n" msgstr "" #: hsccmd.c:4527 msgid "HHCPN996E The script command requires a filename\n" msgstr "" #: hsccmd.c:4540 msgid "HHCPN997E Only 1 script may be invoked from the panel at any time\n" msgstr "" #: hsccmd.c:4558 msgid "HHCPN998E Script aborted : user cancel request\n" msgstr "" #: hsccmd.c:4580 msgid "HHCPN998E Script aborted : Script recursion level exceeded\n" msgstr "" #: hsccmd.c:4596 hsccmd.c:4605 #, c-format msgid "HHCPN007E Script file \"%s\" open failed: %s\n" msgstr "" #: hsccmd.c:4599 #, c-format msgid "HHCPN995E Script file \"%s\" not found\n" msgstr "" #: hsccmd.c:4617 #, c-format msgid "HHCPN008I Script file processing started using file \"%s\"\n" msgstr "" #: hsccmd.c:4625 #, c-format msgid "HHCPN009E Script file buffer malloc failed: %s\n" msgstr "" #: hsccmd.c:4667 #, c-format msgid "HHCPN010W Ignoring invalid SCRIPT file pause statement: %s\n" msgstr "" #: hsccmd.c:4673 #, c-format msgid "HHCPN011I Pausing SCRIPT file processing for %d seconds...\n" msgstr "" #: hsccmd.c:4677 msgid "HHCPN012I Resuming SCRIPT file processing...\n" msgstr "" #: hsccmd.c:4695 msgid "HHCPN013I EOF reached on SCRIPT file. Processing complete.\n" msgstr "" #: hsccmd.c:4700 #, c-format msgid "HHCPN014E I/O error reading SCRIPT file: %s\n" msgstr "" #: hsccmd.c:4705 #, c-format msgid "HHCPN999I Script \"%s\" aborted due to previous conditions\n" msgstr "" #: hsccmd.c:4734 #, c-format msgid "HHCPN126I Architecture mode = %s\n" msgstr "" #: hsccmd.c:4747 msgid "HHCPN127E All CPU's must be stopped to change architecture\n" msgstr "" #: hsccmd.c:4788 #, c-format msgid "HHCPN128E Invalid architecture mode %s\n" msgstr "" #: hsccmd.c:4802 #, c-format msgid "HHCPN129I Architecture successfully set to %s mode.\n" msgstr "" #: hsccmd.c:4864 #, c-format msgid "HHCPN130E Invalid frame address %8.8X\n" msgstr "" #: hsccmd.c:4871 #, c-format msgid "HHCPN131I Frame %8.8X marked %s\n" msgstr "" #: hsccmd.c:4872 msgid "usable" msgstr "" #: hsccmd.c:4872 msgid "unusable" msgstr "" #: hsccmd.c:4889 #, c-format msgid "HHCPN134I CKD KEY trace is now %s\n" msgstr "" #: hsccmd.c:4912 #, c-format msgid "HHCPN136I CCW tracing is now %s for device %d:%4.4X\n" msgstr "" #: hsccmd.c:4917 #, c-format msgid "HHCPN137I CCW stepping is now %s for device %d:%4.4X\n" msgstr "" #: hsccmd.c:4926 msgid "HHCPN138E Unrecognized +/- command.\n" msgstr "" #: hsccmd.c:5230 #, c-format msgid "HHCHD100I Loading %s ...\n" msgstr "" #: hsccmd.c:5232 #, c-format msgid "HHCHD101I Module %s loaded\n" msgstr "" #: hsccmd.c:5255 #, c-format msgid "HHCHD102I Unloading %s ...\n" msgstr "" #: hsccmd.c:5257 #, c-format msgid "HHCHD103I Module %s unloaded\n" msgstr "" #: hsccmd.c:5302 msgid "HHCPN150W evm command is deprecated. Use \"ecpsvm\" instead\n" msgstr "" #: hsccmd.c:5338 #, c-format msgid "HHCPN161I (void *) ..........%7d\n" msgstr "" #: hsccmd.c:5339 #, c-format msgid "HHCPN161I (unsigned int) ....%7d\n" msgstr "" #: hsccmd.c:5340 #, c-format msgid "HHCPN161I (size_t) ..........%7d\n" msgstr "" #: hsccmd.c:5341 #, c-format msgid "HHCPN161I (off_t) ...........%7d\n" msgstr "" #: hsccmd.c:5342 #, c-format msgid "HHCPN161I SYSBLK ............%7d\n" msgstr "" #: hsccmd.c:5343 #, c-format msgid "HHCPN161I REGS ..............%7d\n" msgstr "" #: hsccmd.c:5344 #, c-format msgid "HHCPN161I REGS (copy len) ...%7d\n" msgstr "" #: hsccmd.c:5345 #, c-format msgid "HHCPN161I PSW ...............%7d\n" msgstr "" #: hsccmd.c:5346 #, c-format msgid "HHCPN161I DEVBLK ............%7d\n" msgstr "" #: hsccmd.c:5347 #, c-format msgid "HHCPN161I TLB entry .........%7d\n" msgstr "" #: hsccmd.c:5348 #, c-format msgid "HHCPN161I TLB table .........%7d\n" msgstr "" #: hsccmd.c:5349 #, c-format msgid "HHCPN161I FILENAME_MAX ......%7d\n" msgstr "" #: hsccmd.c:5350 #, c-format msgid "HHCPN161I PATH_MAX ..........%7d\n" msgstr "" #: hsccmd.c:5391 #, c-format msgid "HHCPN190I Keep-alive = (%d,%d,%d)\n" msgstr "" #: hsccmd.c:5394 msgid "HHCPN192E Invalid format. Enter \"help conkpalv\" for help.\n" msgstr "" #: hsccmd.c:5422 #, c-format msgid "HHCPN162I Hercules instruction trace displayed in %s mode\n" msgstr "" #: hsccmd.c:5423 msgid "noregs" msgstr "" #: hsccmd.c:5424 msgid "regsfirst" msgstr "" #: hsccmd.c:5425 msgid "traditional" msgstr "" #: hsccmd.c:5734 #, c-format msgid "HHCPN139E Command \"%s\" not found; enter '?' for list.\n" msgstr "" #: hsccmd.c:5761 msgid "" "HHCPN140I Valid panel commands are...\n" "\n" msgstr "" #: hsccmd.c:5771 #, c-format msgid " %-9.9s %s \n" msgstr "" #: hsccmd.c:5778 msgid "add shadow file" msgstr "" #: hsccmd.c:5779 msgid "delete shadow file" msgstr "" #: hsccmd.c:5780 msgid "rename shadow file" msgstr "" #: hsccmd.c:5781 msgid "compress shadow files" msgstr "" #: hsccmd.c:5782 msgid "display shadow file stats" msgstr "" #: hsccmd.c:5788 msgid "turn CCW tracing on/off" msgstr "" #: hsccmd.c:5789 msgid "turn CCW stepping on/off" msgstr "" #: hsccmd.c:5791 msgid "turn CKD_KEY tracing on/off" msgstr "" #: hsccmd.c:5793 msgid "mark frames unusable/usable" msgstr "" #: hsccmd.c:6128 msgid "HHCPN141E Missing argument\n" msgstr "" #: hsccmd.c:6136 #, c-format msgid "%s" msgstr "" #: hsccmd.c:6141 msgid "HHCPN142I No additional help available.\n" msgstr "" #: hscmisc.c:208 #, c-format msgid "DO_SHUTDOWN_NOW EXIT\n" msgstr "" #: hscmisc.c:210 impl.c:582 #, c-format msgid "HHCIN099I Hercules terminated\n" msgstr "" #: hscmisc.c:224 msgid "HHCIN098I Shutdown initiated\n" msgstr "" #: hscmisc.c:598 #, c-format msgid "HHCPN143E Invalid value: %s\n" msgstr "" #: hscmisc.c:622 #, c-format msgid "HHCPN144E Invalid operand: %s\n" msgstr "" #: hscmisc.c:634 #, c-format msgid "HHCPN145E Invalid range: %s\n" msgstr "" #: hscmisc.c:680 #, c-format msgid "HHCMS001E malloc failed for REGS copy: %s\n" msgstr "" #: hscmisc.c:895 #, c-format msgid "Storage not accessible code = %4.4X\n" msgstr "" #: hscmisc.c:903 hscmisc.c:912 msgid "Addressing exception\n" msgstr "" #: hscmisc.c:1126 #, c-format msgid "%sInstruction fetch error\n" msgstr "" #: httpserv.c:89 #, c-format msgid "HHCHT011E html_include: Cannot open %s: %s\n" msgstr "" #: httpserv.c:91 #, c-format msgid "ERROR: Cannot open %s: %s\n" msgstr "" #: httpserv.c:331 #, c-format msgid "HHCHT012I cgi_var_dump: pointer(%p) name(%s) value(%s) type(%d)\n" msgstr "" #: httpserv.c:650 msgid "HHCHT001I HTTP listener thread started: tid=" msgstr "" #: httpserv.c:689 httpserv.c:699 #, c-format msgid "HHCCF066E Invalid HTTPROOT: \"%s\": %s\n" msgstr "" #: httpserv.c:710 #, c-format msgid "HHCHT013I Using HTTPROOT directory \"%s\"\n" msgstr "" #: httpserv.c:718 #, c-format msgid "HHCHT002E socket: %s\n" msgstr "" #: httpserv.c:741 #, c-format msgid "HHCHT003W Waiting for port %u to become free\n" msgstr "" #: httpserv.c:748 #, c-format msgid "HHCHT004E bind: %s\n" msgstr "" #: httpserv.c:757 #, c-format msgid "HHCHT005E listen: %s\n" msgstr "" #: httpserv.c:761 #, c-format msgid "HHCHT006I Waiting for HTTP requests on port %u\n" msgstr "" #: httpserv.c:779 #, c-format msgid "HHCHT007E select: %s\n" msgstr "" #: httpserv.c:791 #, c-format msgid "HHCHT008E accept: %s\n" msgstr "" #: httpserv.c:801 #, c-format msgid "HHCHT010E http_request create_thread: %s\n" msgstr "" #: ieee.c:488 msgid "ebfpston: unexpectedly converting a NaN\n" msgstr "" #: ieee.c:492 msgid "ebfpston: unexpectedly converting an Infinite\n" msgstr "" #: ieee.c:547 msgid "lbfpston: unexpectedly converting a NaN\n" msgstr "" #: ieee.c:551 msgid "lbfpston: unexpectedly converting an Infinite\n" msgstr "" #: ieee.c:600 msgid "sbfpston: unexpectedly converting a NaN\n" msgstr "" #: ieee.c:604 msgid "sbfpston: unexpectedly converting an Infinite\n" msgstr "" #: impl.c:226 #, c-format msgid "HHCPN995E .RC file \"%s\" not found.\n" msgstr "" #: impl.c:340 #, c-format msgid "HHCIN008S DYNGUI.DLL load failed; Hercules terminated.\n" msgstr "" #: impl.c:411 #, c-format msgid "HHCIN001S Cannot register SIGINT handler: %s\n" msgstr "" #: impl.c:422 #, c-format msgid "HHCIN002E Cannot suppress SIGPIPE signal: %s\n" msgstr "" #: impl.c:461 #, c-format msgid "HHCIN003S Cannot register SIGILL/FPE/SEGV/BUS/USR handler: %s\n" msgstr "" #: impl.c:484 #, c-format msgid "HHCIN004S Cannot create watchdog thread: %s\n" msgstr "" #: impl.c:498 #, c-format msgid "HHCIN005S Cannot create http_server thread: %s\n" msgstr "" #: impl.c:512 #, c-format msgid "HHCIN006S Cannot create shared_server thread: %s\n" msgstr "" #: impl.c:529 #, c-format msgid "HHCIN007S Cannot create %4.4X connection thread: %s\n" msgstr "" #: impl.c:580 #, c-format msgid "IMPL EXIT\n" msgstr "" #: ipl.c:219 #, c-format msgid "HHCCP027E Device %4.4X not in configuration%s\n" msgstr "" #: ipl.c:276 #, c-format msgid "" "HHCCP029E %s mode IPL failed: CSW status=%2.2X%2.2X\n" " Sense=" msgstr "" #: ipl.c:369 #, c-format msgid "HHCCP031E Load from %s failed: %s\n" msgstr "" #: ipl.c:428 #, c-format msgid "" "HHCCP030E %s mode IPL failed: Invalid IPL PSW: %2.2X%2.2X%2.2X%2.2X %2.2X%" "2.2X%2.2X%2.2X\n" msgstr "" #: ipl.c:592 #, c-format msgid "HHCCP033E load_main: %s: %s\n" msgstr "" #: ipl.c:602 msgid "HHCCP034W load_main: terminated at end of mainstor\n" msgstr "" #: logger.c:178 logger.c:378 msgid "HHCLG014I logger thread terminating\n" msgstr "" #: logger.c:206 #, c-format msgid "HHCLG003E Error writing hardcopy log: %s\n" msgstr "" #: logger.c:259 #, c-format msgid "HHCLG001E Error redirecting stdout: %s\n" msgstr "" #: logger.c:298 #, c-format msgid "HHCLG002E Error reading syslog pipe: %s\n" msgstr "" #: logger.c:421 logger.c:433 #, c-format msgid "HHCLG004E Error duplicating stderr: %s\n" msgstr "" #: logger.c:443 #, c-format msgid "HHCLG005E Error duplicating stdout: %s\n" msgstr "" #: logger.c:453 #, c-format msgid "HHCLG006E Duplicate error redirecting hardcopy log: %s\n" msgstr "" #: logger.c:460 #, c-format msgid "HHCLG007S Hardcopy log fdopen failed: %s\n" msgstr "" #: logger.c:476 #, c-format msgid "HHCLG008S logbuffer malloc failed: %s\n" msgstr "" #: logger.c:483 #, c-format msgid "HHCLG009S Syslog message pipe creation failed: %s\n" msgstr "" #: logger.c:494 #, c-format msgid "HHCLG012E Cannot create logger thread: %s\n" msgstr "" #: logger.c:516 msgid "HHCLG014E log not active\n" msgstr "" #: logger.c:525 logger.c:527 #, c-format msgid "HHCLG015I log closed\n" msgstr "" #: logger.c:541 #, c-format msgid "HHCLG016E Error opening logfile %s: %s\n" msgstr "" #: logger.c:549 #, c-format msgid "HHCLG017S log file fdopen failed for %s: %s\n" msgstr "" #: logger.c:564 #, c-format msgid "HHCLG018I log switched to %s\n" msgstr "" #: machchk.c:250 msgid "HHCCP019I Machine Check code=%16.16" msgstr "" #: machchk.c:310 msgid "HHCCP020E signal USR2 received for undetermined device\n" msgstr "" #: machchk.c:315 #, c-format msgid "HHCCP021E signal USR2 received for device %4.4X\n" msgstr "" #: machchk.c:339 machchk.c:343 #, c-format msgid "HHCCP017I CPU%4.4X: Machine check due to host error: %s\n" msgstr "" #: machchk.c:378 machchk.c:382 #, c-format msgid "HHCCP018I CPU%4.4X: Check-Stop due to host error: %s\n" msgstr "" #: panel.c:1281 msgid "HHCPN001I Control panel thread started: tid=" msgstr "" #: panel.c:1306 #, c-format msgid "HHCPN002S Cannot obtain keyboard buffer: %s\n" msgstr "" #: panel.c:1316 #, c-format msgid "HHCPN003S Cannot obtain message buffer: %s\n" msgstr "" #: panel.c:1377 #, c-format msgid "HHCPN004E select: %s\n" msgstr "" #: panel.c:1393 #, c-format msgid "HHCPN005E keyboard read: %s\n" msgstr "" #: printer.c:119 #, c-format msgid "HHCPR004E Error opening file %s: %s\n" msgstr "" #: printer.c:140 printer.c:165 #, c-format msgid "HHCPR006E %4.4X device initialization error: fork: %s\n" msgstr "" #: printer.c:146 printer.c:176 #, c-format msgid "HHCPR007I pipe receiver (pid=%d) starting for %4.4X\n" msgstr "" #: printer.c:156 #, c-format msgid "HHCPR005E %4.4X device initialization error: pipe: %s\n" msgstr "" #: printer.c:188 #, c-format msgid "HHCPR008E %4.4X dup2 error: %s\n" msgstr "" #: printer.c:210 printer.c:360 #, c-format msgid "HHCPR011I pipe receiver (pid=%d) terminating for %4.4X\n" msgstr "" #: printer.c:216 #, c-format msgid "HHCPR012E %4.4X Unable to execute %s: %s\n" msgstr "" #: printer.c:255 #, c-format msgid "HHCPR003E %4.4X Error writing to %s: %s\n" msgstr "" #: printer.c:257 msgid "incomplete" msgstr "" #: printer.c:275 #, c-format msgid "HHCPR001E File name missing or invalid for printer %4.4X\n" msgstr "" #: printer.c:304 #, c-format msgid "HHCPR002E Invalid argument for printer %4.4X: %s\n" msgstr "" #: service.c:104 msgid "HHCCP036E SCP not receiving priority messages\n" msgstr "" #: service.c:111 msgid "HHCCP037E SCP not receiving commands\n" msgstr "" #: service.c:118 msgid "HHCCP038E No SCP command\n" msgstr "" #: service.c:129 msgid "HHCCP039E Service Processor busy\n" msgstr "" #: service.c:167 msgid "HHCCP081E SCP not receiving quiesce signals\n" msgstr "" #: service.c:178 msgid "HHCCP082E Service Processor busy\n" msgstr "" #: service.c:933 #, c-format msgid "HHCCP040I CPI: System Type: %s Name: %s Sysplex: %s\n" msgstr "" #: service.c:937 msgid "HHC770I Control Program Information:\n" msgstr "" #: service.c:938 #, c-format msgid "HHC771I System Type = %s\n" msgstr "" #: service.c:939 #, c-format msgid "HHC772I System Name = %s\n" msgstr "" #: service.c:940 #, c-format msgid "HHC773I Sysplex Name = %s\n" msgstr "" #: service.c:941 msgid "HHC774I System Level = %16.16" msgstr "" #: service.c:1174 msgid "HHCCP041I SYSCONS interface active\n" msgstr "" #: service.c:1176 msgid "HHCCP042I SYSCONS interface inactive\n" msgstr "" #: service.c:1300 #, c-format msgid "CPU%4.4X: Vector Facility configured offline\n" msgstr "" #: service.c:1331 #, c-format msgid "CPU%4.4X: Vector Facility configured online\n" msgstr "" #: shared.c:222 #, c-format msgid "HHCSH001S parameter %d is invalid: %s\n" msgstr "" #: shared.c:248 #, c-format msgid "HHCSH002W %4.4X connect pending to %s\n" msgstr "" #: shared.c:266 #, c-format msgid "HHCSH003S %4.4X Error retrieving cylinders\n" msgstr "" #: shared.c:279 #, c-format msgid "HHCSH004S %4.4X Error retrieving device characteristics\n" msgstr "" #: shared.c:297 #, c-format msgid "HHCSH005S %4.4X Remote device %4.4X is a %4.4X\n" msgstr "" #: shared.c:309 #, c-format msgid "HHCSH006S %4.4X Error retrieving device id\n" msgstr "" #: shared.c:326 #, c-format msgid "HHCSH007S %4.4X device type %4.4X not found in dasd table\n" msgstr "" #: shared.c:338 #, c-format msgid "HHCSH008S %4.4X control unit %s not found in dasd table\n" msgstr "" #: shared.c:359 #, c-format msgid "HHCSH009I %s cyls=%d heads=%d tracks=%d trklen=%d\n" msgstr "" #: shared.c:470 #, c-format msgid "HHCSH010S parameter %d is invalid: %s\n" msgstr "" #: shared.c:496 #, c-format msgid "HHCSH011I %4.4X connect pending to %s\n" msgstr "" #: shared.c:511 #, c-format msgid "HHCSH012S %4.4X Error retrieving fba origin\n" msgstr "" #: shared.c:523 #, c-format msgid "HHCSH013S %4.4X Error retrieving fba number blocks\n" msgstr "" #: shared.c:535 #, c-format msgid "HHCSH014S %4.4X Error retrieving fba block size\n" msgstr "" #: shared.c:549 #, c-format msgid "HHCSH015S %4.4X Error retrieving device id\n" msgstr "" #: shared.c:558 #, c-format msgid "HHCSH016S %4.4X Remote device %4.4X is a %4.4X\n" msgstr "" #: shared.c:570 #, c-format msgid "HHCSH017S %4.4X Error retrieving device characteristics\n" msgstr "" #: shared.c:587 #, c-format msgid "HHCSH018S %4.4X device type %4.4X not found in dasd table\n" msgstr "" #: shared.c:596 #, c-format msgid "HHCSH019I %s origin=%d blks=%d\n" msgstr "" #: shared.c:641 #, c-format msgid "HHCSH020E %4.4X error during channel program start\n" msgstr "" #: shared.c:698 #, c-format msgid "HHCSH021E %4.4X error during channel program end\n" msgstr "" #: shared.c:803 #, c-format msgid "HHCSH022E %4.4X error reading track %d\n" msgstr "" #: shared.c:815 #, c-format msgid "HHCSH023E %4.4X error reading track %d\n" msgstr "" #: shared.c:1015 #, c-format msgid "HHCSH024E %4.4X error reading block group %d\n" msgstr "" #: shared.c:1028 #, c-format msgid "HHCSH025E %4.4X error reading block group %d\n" msgstr "" #: shared.c:1116 #, c-format msgid "HHCSH026E %4.4X Error retrieving usage information\n" msgstr "" #: shared.c:1187 #, c-format msgid "HHCSH027E %4.4X error writing track %d\n" msgstr "" #: shared.c:1200 #, c-format msgid "HHCSH028E %4.4X remote error writing track %d: %2.2X-%2.2X\n" msgstr "" #: shared.c:1285 #, c-format msgid "HHCSH029E %4.4X socket failed: %s\n" msgstr "" #: shared.c:1301 #, c-format msgid "HHCSH030E %4.4X socket failed: %s\n" msgstr "" #: shared.c:1319 #, c-format msgid "HHCSH031I %4.4X Connected to %s\n" msgstr "" #: shared.c:1353 #, c-format msgid "HHCSH032E %4.4X Connect %s %d: %s\n" msgstr "" #: shared.c:1524 #, c-format msgid "HHCSH033E %4.4X send error %d for %2.2X-%2.2X: %s\n" msgstr "" #: shared.c:1551 #, c-format msgid "HHCSH034E %4.4X Not connected to %s\n" msgstr "" #: shared.c:1561 #, c-format msgid "HHCSH035E %4.4X recv error %d: %s\n" msgstr "" #: shared.c:1573 #, c-format msgid "HHCSH036E %4.4X Remote error %2.2X-%2.2X: %s\n" msgstr "" #: shared.c:1679 #, c-format msgid "HHCSH037E uncompress error %d, off %d len %d\n" msgstr "" #: shared.c:1684 msgid "HHCSH038E data compressed using libz, unsupported\n" msgstr "" #: shared.c:1702 #, c-format msgid "HHCSH039E decompress error %d, off %d len %d\n" msgstr "" #: shared.c:1707 msgid "HHCSH040E data compressed using bzip2, unsupported\n" msgstr "" #: shared.c:2282 #, c-format msgid "HHCSH041E %4.4X send error %d id=%d: %s\n" msgstr "" #: shared.c:2321 #, c-format msgid "HHCSH042W %4.4X busy client being removed id=%d %s\n" msgstr "" #: shared.c:2353 #, c-format msgid "HHCSH043I %s disconnected from %4.4X id=%d\n" msgstr "" #: shared.c:2424 #, c-format msgid "HHCSH0474 %s connect failed\n" msgstr "" #: shared.c:2502 #, c-format msgid "HHCSH053I %s connected to %4.4X id=%d\n" msgstr "" #: shared.c:2518 #, c-format msgid "HHCSH045I Shared device %4.4X thread started: tid=" msgstr "" #: shared.c:2587 #, c-format msgid "HHCSH046E select: %s\n" msgstr "" #: shared.c:2621 #, c-format msgid "HHCSH047E %4.4X %s recv error id=%d\n" msgstr "" #: shared.c:2652 #, c-format msgid "HHCSH048I Shared device %4.4X thread stopping\n" msgstr "" #: shared.c:2719 #, c-format msgid "HHCSH049I Shared device %d.%d thread started: tid=" msgstr "" #: shared.c:2728 #, c-format msgid "HHCSH050E inet socket: %s\n" msgstr "" #: shared.c:2737 #, c-format msgid "HHCSH051W unix socket: %s\n" msgstr "" #: shared.c:2760 #, c-format msgid "HHCSH052W Waiting for port %u to become free\n" msgstr "" #: shared.c:2767 #, c-format msgid "HHCSH053E inet bind: %s\n" msgstr "" #: shared.c:2785 #, c-format msgid "HHCSH054W unix bind: %s\n" msgstr "" #: shared.c:2797 #, c-format msgid "HHCSH055E inet listen: %s\n" msgstr "" #: shared.c:2808 #, c-format msgid "HHCSH056W unix listen: %s\n" msgstr "" #: shared.c:2821 #, c-format msgid "HHCSH057I Waiting for shared device requests on port %u\n" msgstr "" #: shared.c:2841 #, c-format msgid "HHCSH058E select: %s\n" msgstr "" #: shared.c:2859 #, c-format msgid "HHCSH059E accept: %s\n" msgstr "" #: shared.c:2866 #, c-format msgid "HHCSH060E malloc size %d: %s\n" msgstr "" #: shared.c:2877 #, c-format msgid "HHCSH061E serverConnect create_thread: %s\n" msgstr "" #: shared.c:2916 msgid "HHCSH062E Invalid or missing argument 1\n" msgstr "" #: shared.c:2925 msgid "HHCSH063E Invalid or missing keyword 2\n" msgstr "" #: shared.c:2943 #, c-format msgid "HHCSH064E Invalid or missing value %s\n" msgstr "" #: shared.c:2959 #, c-format msgid "HHCSH065E calloc() size=%d: %s\n" msgstr "" #: shared.c:2985 #, c-format msgid "HHCSH066E Invalid or missing keyword %s\n" msgstr "" #: shared.c:3060 shared.c:3067 msgid "HHCSH999E OPTION_SHARED_DEVICES not defined" msgstr "" #: sie.c:292 msgid "SIE: state descriptor " msgstr "" #: sie.c:317 #, c-format msgid "HHCCP079E CPU%4.4X: calloc failed for sie regs: %s\n" msgstr "" #: sie.c:421 #, c-format msgid "SIE: zone %d: mso=" msgstr "" #: sie.c:735 #, c-format msgid "SIE: interception code %d\n" msgstr "" #: sockdev.c:81 msgid "HHCSD024E This build does not support Unix domain sockets.\n" msgstr "" #: sockdev.c:92 #, c-format msgid "HHCSD008E Socket pathname \"%s\" exceeds limit of %d\n" msgstr "" #: sockdev.c:103 #, c-format msgid "HHCSD009E Error creating socket for %s: %s\n" msgstr "" #: sockdev.c:116 #, c-format msgid "HHCSD010E Failed to bind or listen on socket %s: %s\n" msgstr "" #: sockdev.c:169 #, c-format msgid "HHCSD011E Failed to determine IP address from %s\n" msgstr "" #: sockdev.c:187 #, c-format msgid "HHCSD012E Failed to determine port number from %s\n" msgstr "" #: sockdev.c:199 #, c-format msgid "HHCSD013E Error creating socket for %s: %s\n" msgstr "" #: sockdev.c:211 #, c-format msgid "HHCSD014E Failed to bind or listen on socket %s: %s\n" msgstr "" #: sockdev.c:285 #, c-format msgid "" "HHCSD015E Connect to device %4.4X (%s) rejected; device busy or interrupt " "pending\n" msgstr "" #: sockdev.c:296 #, c-format msgid "" "HHCSD016E Connect to device %4.4X (%s) rejected; client %s (%s) still " "connected\n" msgstr "" #: sockdev.c:310 #, c-format msgid "HHCSD017E Connect to device %4.4X (%s) failed: %s\n" msgstr "" #: sockdev.c:336 #, c-format msgid "HHCSD018I %s (%s) connected to device %4.4X (%s)\n" msgstr "" #: sockdev.c:341 #, c-format msgid "HHCSD019I connected to device %4.4X (%s)\n" msgstr "" #: sockdev.c:416 msgid "HHCSD020I Socketdevice listener thread started: tid=" msgstr "" #: sockdev.c:444 #, c-format msgid "HHCSD021E select failed; errno=%d: %s\n" msgstr "" #: sockdev.c:453 msgid "HHCSD022I Socketdevice listener thread terminated\n" msgstr "" #: sockdev.c:478 #, c-format msgid "HHCSD001E Device %4.4X already bound to socket %s\n" msgstr "" #: sockdev.c:487 #, c-format msgid "HHCSD002E bind_device malloc() failed for device %4.4X\n" msgstr "" #: sockdev.c:495 #, c-format msgid "HHCSD003E bind_device strdup() failed for device %4.4X\n" msgstr "" #: sockdev.c:533 #, c-format msgid "HHCSD023E Cannot create socketdevice thread: errno=%d: %s\n" msgstr "" #: sockdev.c:548 #, c-format msgid "HHCSD004I Device %4.4X bound to socket %s\n" msgstr "" #: sockdev.c:568 #, c-format msgid "HHCSD005E Device %4.4X not bound to any socket\n" msgstr "" #: sockdev.c:576 #, c-format msgid "HHCSD006E Client %s (%s) still connected to device %4.4X (%s)\n" msgstr "" #: sockdev.c:588 #, c-format msgid "HHCSD007I Device %4.4X unbound from socket %s\n" msgstr "" #: stack.c:410 msgid "stack: Current stack entry at " msgstr "" #: stack.c:411 stack.c:450 stack.c:783 stack.c:796 stack.c:860 stack.c:899 #, c-format msgid "stack: et=%2.2X si=%2.2X rfs=%2.2X%2.2X nes=%2.2X%2.2X\n" msgstr "" #: stack.c:433 msgid "stack: Forward section header addr " msgstr "" #: stack.c:495 stack.c:782 msgid "stack: New stack entry at " msgstr "" #: stack.c:512 stack.c:520 stack.c:1163 stack.c:1171 #, c-format msgid "stack: GPR%d=" msgstr "" #: stack.c:544 stack.c:753 stack.c:1209 #, c-format msgid "stack: AR%d=" msgstr "" #: stack.c:566 #, c-format msgid "" "stack: PKM=%2.2X%2.2X SASN=%2.2X%2.2X EAX=%2.2X%2.2X PASN=%2.2X%2.2X \n" "stored at V:" msgstr "" #: stack.c:620 #, c-format msgid "stack: PSW=%2.2X%2.2X%2.2X%2.2X %2.2X%2.2X%2.2X%2.2X stored at V:" msgstr "" #: stack.c:698 #, c-format msgid "stack: PSW2=%2.2X%2.2X%2.2X%2.2X %2.2X%2.2X%2.2X%2.2X stored at V:" msgstr "" #: stack.c:725 #, c-format msgid "" "stack: SASTEIN=%2.2X%2.2X%2.2X%2.2X PASTEIN=%2.2X%2.2X%2.2X%2.2X \n" "stored at V:" msgstr "" #: stack.c:794 msgid "stack: Previous stack entry updated at A:" msgstr "" #: stack.c:805 stack.c:1421 msgid "stack: CR15=" msgstr "" #: stack.c:859 stack.c:883 msgid "stack: Stack entry located at " msgstr "" #: stack.c:1138 #, c-format msgid "stack: Unstacking registers %d-%d from " msgstr "" #: stack.c:1303 #, c-format msgid "" "stack: PKM=%2.2X%2.2X SASN=%2.2X%2.2X EAX=%2.2X%2.2X PASN=%2.2X%2.2X \n" "loaded from V:" msgstr "" #: stack.c:1340 #, c-format msgid "stack: PSW=%2.2X%2.2X%2.2X%2.2X %2.2X%2.2X%2.2X%2.2X loaded from V:" msgstr "" #: stack.c:1384 #, c-format msgid "" "stack: SASTEIN=%2.2X%2.2X%2.2X%2.2X PASTEIN=%2.2X%2.2X%2.2X%2.2X \n" "loaded from V:" msgstr "" #: tapecopy.c:39 #, c-format msgid "HHCTC017E SCSI tape not supported with this build\n" msgstr "" #: tapecopy.c:132 #, c-format msgid "HHCTC000I Abnormal termination\n" msgstr "" #: tapecopy.c:146 #, c-format msgid "HHCTC015I %s status: %8.8lX" msgstr "" #: tapecopy.c:171 #, c-format msgid "" "\n" "Copies a SCSI tape to or from an AWSTAPE disk file.\n" "\n" "Tapecopy reads a SCSI tape and outputs an AWSTAPE file representation\n" "of the tape, or else reads an AWSTAPE file and creates an identical copy\n" "of its contents on a tape mounted on a SCSI tape drive.\n" "\n" "Usage:\n" "\n" " tapecopy [tapedrive] [awsfile] or\n" " tapecopy [awsfile] [tapedrive]\n" "\n" "Where:\n" "\n" " tapedrive specifies the device filename of the SCSI tape drive.\n" " Must begin with /dev to be recognized.\n" " awsfile specifies the filename of the AWSTAPE disk file.\n" "\n" "The first filename is the input; the second is the output.\n" "\n" "If the input file is a SCSI tape, it is read and processed until physical " "EOD\n" "(end-of-data) is reached (i.e. it does not stop whenever multiple tapemarks " "or\n" "filemarks are read; it continues processing until the SCSI tape drive says\n" "there is no more data on the tape). The resulting AWSTAPE output disk file,\n" "when specified for the filename on a Hercules tape device configuration\n" "statement, can then be used instead in order for the Hercules guest O/S to\n" "read the exact same data without having to have a SCSI tape drive " "physically\n" "attached to the host system. This allows you to easily transfer SCSI tape " "data\n" "to other systems that may not have SCSI tape drives attached to them.\n" "\n" "The possible return codes and their meaning are:\n" "\n" " %2d Successful completion.\n" " %2d Invalid arguments or no arguments given.\n" " %2d Unable to open SCSI tape drive device file.\n" " %2d Unable to open AWSTAPE disk file.\n" " %2d Unrecoverable I/O error setting variable length block\n" " processing for SCSI tape device.\n" " %2d Unrecoverable I/O error rewinding SCSI tape device.\n" " %2d Unrecoverable I/O error obtaining status of SCSI device.\n" " %2d Unrecoverable I/O error reading block header\n" " from AWSTAPE disk file.\n" " %2d AWSTAPE block size too large.\n" " %2d Unrecoverable I/O error reading data block.\n" " %2d Unrecoverable I/O error writing tapemark.\n" " %2d Unrecoverable I/O error writing block header\n" " to AWSTAPE disk file.\n" " %2d Unrecoverable I/O error writing data block.\n" "\n" msgstr "" #: tapecopy.c:266 #, c-format msgid "HHCTC016E Error reading status of %s: rc=%d, errno=%d: %s\n" msgstr "" #: tapecopy.c:295 #, c-format msgid "HHCTC011I End of tape.\n" msgstr "" #: tapecopy.c:299 #, c-format msgid "HHCTC008E Error reading %s: errno=%d: %s\n" msgstr "" #: tapecopy.c:325 #, c-format msgid "HHCTC018I End of AWSTAPE input file.\n" msgstr "" #: tapecopy.c:330 #, c-format msgid "HHCTC019E Error reading AWSTAPE header from %s: rc=%d, errno=%d: %s\n" msgstr "" #: tapecopy.c:346 #, c-format msgid "HHCTC020E AWSTAPE block too large on %s: block size=%d, maximum=%d\n" msgstr "" #: tapecopy.c:355 #, c-format msgid "HHCTC021E Error reading data block from %s: rc=%d, errno=%d: %s\n" msgstr "" #: tapecopy.c:380 #, c-format msgid "HHCTC022E Error writing data block to %s: rc=%d, errno=%d: %s\n" msgstr "" #: tapecopy.c:414 #, c-format msgid "HHCTC013E Error writing AWSTAPE header on %s: rc=%d, errno=%d: %s\n" msgstr "" #: tapecopy.c:425 #, c-format msgid "HHCTC014E Error writing data block to %s: rc=%d, errno=%d: %s\n" msgstr "" #: tapecopy.c:448 #, c-format msgid "HHCTC023E Error writing tapemark on %s: rc=%d, errno=%d: %s\n" msgstr "" #: tapecopy.c:476 #, c-format msgid "HHCTC010E Error writing tapemark on %s: rc=%d, errno=%d, %s\n" msgstr "" #: tapecopy.c:601 #, c-format msgid "HHCTC001E Error opening %s: errno=%d: %s\n" msgstr "" #: tapecopy.c:614 #, c-format msgid "HHCTC005E Error setting attributes for %s: rc=%d, errno=%d: %s\n" msgstr "" #: tapecopy.c:627 tapecopy.c:884 #, c-format msgid "HHCTC006E Error rewinding %s: rc=%d, errno=%d: %s\n" msgstr "" #: tapecopy.c:644 #, c-format msgid "HHCTC003I %s device type: %s\n" msgstr "" #: tapecopy.c:647 #, c-format msgid "HHCTC003I %s device type: 0x%lX\n" msgstr "" #: tapecopy.c:657 #, c-format msgid "HHCTC004I %s tape density: %s\n" msgstr "" #: tapecopy.c:660 #, c-format msgid "HHCTC004I %s tape density code: 0x%lX\n" msgstr "" #: tapecopy.c:680 #, c-format msgid "HHCTC007E Error opening %s: errno=%d: %s\n" msgstr "" #: tapecopy.c:779 msgid "HHCTC009I File %u: Blocks=%u, Bytes=%" msgstr "" #: tapecopy.c:792 #, c-format msgid " (tapemark)\n" msgstr "" #: tapecopy.c:827 #, c-format msgid "HHCTC012I %s\n" msgstr "" #: tapecopy.c:836 #, c-format msgid "File %u: Block %u\r" msgstr "" #: tapecopy.c:856 msgid "" "HHCTC000I Successful completion;\n" " Bytes read: %" msgstr "" #: tapecopy.c:868 msgid " Bytes written: %" msgstr "" #: tapedev.c:437 #, c-format msgid "HHCTA996I %4.4x - AWS Tape %s closed\n" msgstr "" #: tapedev.c:523 #, c-format msgid "HHCTA001E Error opening %s: %s\n" msgstr "" #: tapedev.c:555 tapedev.c:718 #, c-format msgid "HHCTA002E Error seeking to offset %8.8lX in file %s: %s\n" msgstr "" #: tapedev.c:570 #, c-format msgid "HHCTA003E Error reading block header at offset %8.8lX in file %s: %s\n" msgstr "" #: tapedev.c:582 #, c-format msgid "" "HHCTA004E End of file (uninitialized tape) at offset %8.8lX in file %s\n" msgstr "" #: tapedev.c:594 #, c-format msgid "" "HHCTA004E Unexpected end of file in block header at offset %8.8lX in file %" "s\n" msgstr "" #: tapedev.c:651 #, c-format msgid "HHCTA003E Error reading data block at offset %8.8lX in file %s: %s\n" msgstr "" #: tapedev.c:665 #, c-format msgid "" "HHCTA004E Unexpected end of file in data block at offset %8.8lX in file %s\n" msgstr "" #: tapedev.c:753 tapedev.c:780 #, c-format msgid "HHCTA995E Media full condition reached at offset %8.8lX in file %s\n" msgstr "" #: tapedev.c:759 #, c-format msgid "HHCTA009E Error writing block header at offset %8.8lX in file %s: %s\n" msgstr "" #: tapedev.c:786 tapedev.c:804 #, c-format msgid "HHCTA010E Error writing data block at offset %8.8lX in file %s: %s\n" msgstr "" #: tapedev.c:856 #, c-format msgid "HHCTA011E Error seeking to offset %8.8lX in file %s: %s\n" msgstr "" #: tapedev.c:887 #, c-format msgid "HHCTA012E Error writing block header at offset %8.8lX in file %s: %s\n" msgstr "" #: tapedev.c:908 #, c-format msgid "HHCTA017E Error writing tape mark at offset %8.8lX in file %s: %s\n" msgstr "" #: tapedev.c:1141 #, c-format msgid "HHCTA013E Error opening %s: %s(%s)\n" msgstr "" #: tapedev.c:1189 #, c-format msgid "HHCTA075E Error seeking to start of %s: %s(%s)\n" msgstr "" #: tapedev.c:1227 #, c-format msgid "HHCTA014E End of file (uninitialized tape) at block %8.8X in file %s\n" msgstr "" #: tapedev.c:1236 #, c-format msgid "HHCTA015E Error reading data block at block %8.8X in file %s: %s(%s)\n" msgstr "" #: tapedev.c:1278 #, c-format msgid "HHCTA016E Error writing data block at block %8.8X in file %s: %s(%s)\n" msgstr "" #: tapedev.c:1294 msgid "TAPE EOT Handling: max capacity exceeded\n" msgstr "" #: tapedev.c:1297 msgid "TAPE EOT Handling: max capacity enforced\n" msgstr "" #: tapedev.c:1330 #, c-format msgid "HHCTA017E Error writing tape mark at block %8.8X in file %s: %s(%s)\n" msgstr "" #: tapedev.c:1372 #, c-format msgid "HHCTA018E Error forward spacing at block %8.8X in file %s: %s(%s)\n" msgstr "" #: tapedev.c:1427 #, c-format msgid "HHCTA019E Error reading data block at block %8.8X in file %s: %s(%s)\n" msgstr "" #: tapedev.c:1459 #, c-format msgid "" "HHCTA020E Error forward spacing to next file at block %8.8X in file %s: %s(%" "s)\n" msgstr "" #: tapedev.c:1524 #, c-format msgid "" "HHCTA021E Error back spacing to previous file at block %8.8X in file %s:\n" " %s(%s)\n" msgstr "" #: tapedev.c:1578 #, c-format msgid "" "HHC232I Invalid filename %s: TDF files must be in the TAPES subdirectory\n" msgstr "" #: tapedev.c:1591 #, c-format msgid "HHCTA039E Error opening TDF file %s: %s\n" msgstr "" #: tapedev.c:1600 #, c-format msgid "HHCTA040E %s fstat error: %s\n" msgstr "" #: tapedev.c:1611 #, c-format msgid "HHCTA041E Cannot obtain buffer for TDF file %s: %s\n" msgstr "" #: tapedev.c:1621 #, c-format msgid "HHCTA042E Error reading TDF file %s: %s\n" msgstr "" #: tapedev.c:1634 #, c-format msgid "HHCTA043E %s is not a valid TDF file\n" msgstr "" #: tapedev.c:1653 #, c-format msgid "HHCTA044E Cannot obtain buffer for TDF array: %s\n" msgstr "" #: tapedev.c:1702 #, c-format msgid "HHCTA045E Filename or format missing in line %d of file %s\n" msgstr "" #: tapedev.c:1714 #, c-format msgid "HHCTA046E Filename %s too long in line %d of file %s\n" msgstr "" #: tapedev.c:1766 #, c-format msgid "HHCTA047E RECSIZE keyword missing in line %d of file %s\n" msgstr "" #: tapedev.c:1779 #, c-format msgid "HHCTA048E Invalid record size %s in line %d of file %s\n" msgstr "" #: tapedev.c:1793 #, c-format msgid "HHCTA049E Invalid record format %s in line %d of file %s\n" msgstr "" #: tapedev.c:1850 #, c-format msgid "HHCTA050E Attempt to access beyond end of tape %s\n" msgstr "" #: tapedev.c:1886 #, c-format msgid "HHCTA051E Error opening %s: %s\n" msgstr "" #: tapedev.c:1929 #, c-format msgid "HHCTA052E Error seeking to offset %8.8lX in file %s: %s\n" msgstr "" #: tapedev.c:1944 #, c-format msgid "HHCTA053E Error reading block header at offset %8.8lX in file %s: %s\n" msgstr "" #: tapedev.c:1957 #, c-format msgid "" "HHCTA054E Unexpected end of file in block header at offset %8.8lX in file %" "s\n" msgstr "" #: tapedev.c:1980 #, c-format msgid "HHCTA055E Invalid block header at offset %8.8lX in file %s\n" msgstr "" #: tapedev.c:2047 #, c-format msgid "HHCTA056E Error reading data block at offset %8.8lX in file %s: %s\n" msgstr "" #: tapedev.c:2060 #, c-format msgid "" "HHCTA057E Unexpected end of file in data block at offset %8.8lX in file %s\n" msgstr "" #: tapedev.c:2098 #, c-format msgid "HHCTA058E Error seeking to offset %8.8lX in file %s: %s\n" msgstr "" #: tapedev.c:2113 #, c-format msgid "HHCTA059E Error reading data block at offset %8.8lX in file %s: %s\n" msgstr "" #: tapedev.c:2172 #, c-format msgid "HHCTA060E Error seeking to offset %8.8lX in file %s: %s\n" msgstr "" #: tapedev.c:2229 #, c-format msgid "HHCTA061E Error reading data block at offset %8.8lX in file %s: %s\n" msgstr "" #: tapedev.c:2241 #, c-format msgid "" "HHCTA062E Unexpected end of file in data block at offset %8.8lX in file %s\n" msgstr "" #: tapedev.c:2253 #, c-format msgid "HHCTA063E Invalid zero length block at offset %8.8lX in file %s\n" msgstr "" #: tapedev.c:2426 #, c-format msgid "HHCTA064E Error seeking to end of file %s: %s\n" msgstr "" #: tapedev.c:2556 #, c-format msgid "HHCTA065E Error seeking to end of file %s: %s\n" msgstr "" #: tapedev.c:2911 #, c-format msgid "HHCTA100I %4.4X: Now Displays: %s\n" msgstr "" #: tapedev.c:3116 #, c-format msgid "AutoMount: %s%s scratch tape being auto-unloaded on %4.4X = %s\n" msgstr "" #: tapedev.c:3120 #, c-format msgid "AutoMount: %s%s tape volume \"%s\" being auto-unloaded on %4.4X = %s\n" msgstr "" #: tapedev.c:3127 #, c-format msgid "AutoMount: %s%s scratch tape being auto-loaded on %4.4X = %s\n" msgstr "" #: tapedev.c:3131 #, c-format msgid "AutoMount: %s%s tape volume \"%s\" being auto-loaded on %4.4X = %s\n" msgstr "" #: tapedev.c:3150 #, c-format msgid "" "\n" "%s\n" "AUTOMOUNT: Unmount %sof %s%s scratch tape requested on %4.4X = %s\n" "%s\n" "\n" msgstr "" #: tapedev.c:3159 #, c-format msgid "" "\n" "%s\n" "AUTOMOUNT: Unmount %sof %s%s tape volume \"%s\" requested on %4.4X = %s\n" "%s\n" "\n" msgstr "" #: tapedev.c:3171 #, c-format msgid "" "\n" "%s\n" "AUTOMOUNT: Mount for %s%s scratch tape requested on %4.4X = %s\n" "%s\n" "\n" msgstr "" #: tapedev.c:3177 #, c-format msgid "" "\n" "%s\n" "AUTOMOUNT: Mount for %s%s tape volume \"%s\" requested on %4.4X = %s\n" "%s\n" "\n" msgstr "" #: tapedev.c:3266 #, c-format msgid "HHCTA099I %4.4X: Tape Display \"%s\" Until Unmounted\n" msgstr "" #: tapedev.c:3292 #, c-format msgid "HHCTA099I %4.4X: Tape Display \"%s\" Until Mounted\n" msgstr "" #: tapedev.c:3345 #, c-format msgid "" "HHCTA099I %4.4X: Tape Display \"%s\" Until Unmounted, then \"%s\" Until " "Mounted\n" msgstr "" #: tapedev.c:3354 #, c-format msgid "HHCTA099I %4.4X: Tape \"%s\" Until Mounted\n" msgstr "" #: tapedev.c:4024 #, c-format msgid "" "HHCTA999E Device %4.4X: Unable to determine tape format type for %s: " "Internal error: Regcomp error %s on index %d\n" msgstr "" #: tapedev.c:4039 #, c-format msgid "" "HHCTA999E Device %4.4X: Unable to determine tape format type for %s: " "Internal error: Regexec error %s on index %d\n" msgstr "" #: tapedev.c:4085 #, c-format msgid "HHCTA999E Device %4.4X: Unable to determine tape format type for %s\n" msgstr "" #: tapedev.c:4095 #, c-format msgid "HHCTA998I Device %4.4X: %s is a %s\n" msgstr "" #: tapedev.c:4124 #, c-format msgid "HHCTA066I %s device %4.4X parameter: '%s'\n" msgstr "" #: tapedev.c:4128 #, c-format msgid "HHCTA067E Device %4.4X: %s - Unrecognized parameter: '%s'\n" msgstr "" #: tapedev.c:4136 tapedev.c:4148 tapedev.c:4158 tapedev.c:4175 tapedev.c:4192 #: tapedev.c:4209 tapedev.c:4219 tapedev.c:4229 tapedev.c:4239 tapedev.c:4249 #: tapedev.c:4259 tapedev.c:4270 tapedev.c:4281 tapedev.c:4291 #, c-format msgid "HHCTA078E Option '%s' not valid for SCSI tape\n" msgstr "" #: tapedev.c:4164 #, c-format msgid "HHCTA068E Method must be within %u-%u\n" msgstr "" #: tapedev.c:4181 #, c-format msgid "HHCTA069E Level must be within %u-%u\n" msgstr "" #: tapedev.c:4198 #, c-format msgid "HHCTA070E Chunksize must be within %u-%u\n" msgstr "" #: tapedev.c:4302 tapedev.c:4313 #, c-format msgid "HHCTA078E Option '%s' not valid for %s\n" msgstr "" #: tapedev.c:4323 #, c-format msgid "HHCTA071E Error in '%s' parameter\n" msgstr "" #: tapedev.c:4371 #, c-format msgid "TAPE Autoloader - Adding global parm %s\n" msgstr "" #: tapedev.c:4441 #, c-format msgid "TAPE Autoloader: Adding tape entry %s\n" msgstr "" #: tapedev.c:4490 #, c-format msgid "TAPE: Autoloader file request fn=%s\n" msgstr "" #: tapedev.c:4778 #, c-format msgid "Unsupported device type specified %4.4x\n" msgstr "" #: tapedev.c:5239 #, c-format msgid "HHCTA072E Data chaining not supported for CCW %2.2X\n" msgstr "" #: tapedev.c:5958 msgid "HHCTA081I Locate block 0x%8.8" msgstr "" #: timer.c:195 #, c-format msgid "HHCTT001W Timer thread set priority %d failed: %s\n" msgstr "" #: timer.c:202 msgid "HHCTT002I Timer thread started: tid=" msgstr "" #: timer.c:335 msgid "HHCTT003I Timer thread ended\n" msgstr "" #: tuntap.c:133 #, c-format msgid "HHCTU001E %s timeout, possible older version?\n" msgstr "" #: tuntap.c:214 #, c-format msgid "HHCTU001E Unable to determine operating system type: %s\n" msgstr "" #: tuntap.c:226 #, c-format msgid "HHCTU002E Error opening TUN/TAP device: %s: %s\n" msgstr "" #: tuntap.c:246 #, c-format msgid "HHCTU003E Error setting TUN/TAP mode: %s: %s\n" msgstr "" #: tuntap.c:271 #, c-format msgid "HHCTU004E Invalid TUN/TAP device name: %s\n" msgstr "" #: tuntap.c:304 tuntap.c:334 #, c-format msgid "HHCTU005E Invalid net device name specified: %s\n" msgstr "" #: tuntap.c:344 #, c-format msgid "HHCTU006E %s: Invalid IP address: %s.\n" msgstr "" #: tuntap.c:371 #, c-format msgid "HHCTU007E Invalid net device name specified: %s\n" msgstr "" #: tuntap.c:381 #, c-format msgid "HHCTU008E %s: Invalid destination address: %s.\n" msgstr "" #: tuntap.c:408 #, c-format msgid "HHCTU009E Invalid net device name specified: %s\n" msgstr "" #: tuntap.c:418 #, c-format msgid "HHCTU010E %s: Invalid net mask: %s.\n" msgstr "" #: tuntap.c:446 #, c-format msgid "HHCTU011E Invalid net device name specified: %s\n" msgstr "" #: tuntap.c:455 #, c-format msgid "HHCTU012E %s: Invalid null or empty MTU.\n" msgstr "" #: tuntap.c:464 #, c-format msgid "HHCTU013E %s: Invalid MTU: %s.\n" msgstr "" #: tuntap.c:493 #, c-format msgid "HHCTU014E Invalid net device name specified: %s\n" msgstr "" #: tuntap.c:502 #, c-format msgid "HHCTU015E %s: Invalid MAC address: %s.\n" msgstr "" #: tuntap.c:532 tuntap.c:563 #, c-format msgid "HHCTU016E Invalid net device name specified: %s\n" msgstr "" #: tuntap.c:613 #, c-format msgid "HHCTU017E Invalid net device name specified: %s\n" msgstr "" #: tuntap.c:627 #, c-format msgid "HHCTU018E %s: Invalid destiniation address: %s.\n" msgstr "" #: tuntap.c:639 #, c-format msgid "HHCTU019E %s: Invalid net mask: %s.\n" msgstr "" #: tuntap.c:652 #, c-format msgid "HHCTU020E %s: Invalid gateway address: %s.\n" msgstr "" #: tuntap.c:681 #, c-format msgid "HHCTU021E Invalid net device name specified: %s\n" msgstr "" #: tuntap.c:695 #, c-format msgid "HHCTU022E %s: Invalid destiniation address: %s.\n" msgstr "" #: tuntap.c:707 #, c-format msgid "HHCTU023E %s: Invalid net mask: %s.\n" msgstr "" #: tuntap.c:720 #, c-format msgid "HHCTU024E %s: Invalid gateway address: %s.\n" msgstr "" #: tuntap.c:821 #, c-format msgid "HHCTU025E Call to socketpair failed: %s\n" msgstr "" #: tuntap.c:830 #, c-format msgid "HHCTU029I Executing '%s' to configure interface\n" msgstr "" #: tuntap.c:838 #, c-format msgid "HHCTU026E Call to fork failed: %s\n" msgstr "" #: tuntap.c:862 msgid "HHCTU031I Closing %" msgstr "" #: tuntap.c:880 #, c-format msgid "HHCTU027E execl error on %s: %s.\n" msgstr "" #: tuntap.c:893 #, c-format msgid "HHCTU030I IFC_IOCtl called for %s on FDs %d %d\n" msgstr "" #: version.c:211 version.c:213 version.c:215 #, c-format msgid "%sVersion %s\n" msgstr "" #: version.c:234 version.c:236 version.c:238 #, c-format msgid "Built on %s at %s\n" msgstr "" #: version.c:244 version.c:246 version.c:248 #, c-format msgid "Build information:\n" msgstr "" #: vm.c:839 #, c-format msgid "HHCVM001I *%s* panel command issued by guest\n" msgstr "" #: vm.c:855 #, c-format msgid "HHCVM002I *%s* command complete\n" msgstr "" #: vm.c:859 msgid "HHCVM003I Host command processing disabled by configuration statement" msgstr "" #: vm.c:861 msgid "HHCVM004E Host command processing not included in engine build" msgstr "" #: w32chan.c:143 #, c-format msgid "HHCCP084E malloc(DEVIOREQUEST) failed; device=%4.4X, strerror=\"%s\"\n" msgstr "" #: w32chan.c:206 msgid "HHCCP085W *WARNING* max device threads exceeded.\n" msgstr "" #: w32chan.c:303 #, c-format msgid "" "HHCCP086E malloc(DEVTHREADPARMS) failed; device=%4.4X, strerror=\"%s\"\n" msgstr "" #: w32chan.c:312 #, c-format msgid "" "HHCCP087E CreateEvent(hShutdownEvent) failed; device=%4.4X, strerror=\"%s\"\n" msgstr "" #: w32chan.c:322 #, c-format msgid "" "HHCCP088E CreateEvent(hRequestQueuedEvent) failed; device=%4.4X, strerror=\"%" "s\"\n" msgstr "" #: w32chan.c:343 #, c-format msgid "" "HHCCP089E fthread_create(DeviceThread) failed; device=%4.4X, strerror=\"%s" "\"\n" msgstr "" hercules-3.07/po/insert-header.sin000644 000765 000765 00000001240 11143760531 020624 0ustar00jmaynardjmaynard000000 000000 # 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 } hercules-3.07/po/LINGUAS000644 000765 000765 00000000043 11143760531 016404 0ustar00jmaynardjmaynard000000 000000 # Set of available languages nl de hercules-3.07/po/Makefile.in.in000644 000765 000765 00000031707 11143760531 020044 0ustar00jmaynardjmaynard000000 000000 # Makefile for PO directory in any package using GNU gettext. # Copyright (C) 1995-1997, 2000-2005 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.4 PACKAGE = @PACKAGE@ VERSION = @VERSION@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ SHELL = /bin/sh @SET_MAKE@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ prefix = @prefix@ exec_prefix = @exec_prefix@ 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 \ $(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: # $(srcdir)/$(DOMAIN).pot is only created when needed. When xgettext finds no # internationalized messages, no $(srcdir)/$(DOMAIN).pot is created (because # we don't want to bother translators with empty POT files). We assume that # LINGUAS is empty in this case, i.e. $(POFILES) and $(GMOFILES) are empty. # In this case, stamp-po is a nop (i.e. a phony target). # stamp-po is a timestamp denoting the last time at which the CATALOGS have # been loosely updated. Its purpose is that when a developer or translator # checks out the package via CVS, and the $(DOMAIN).pot file is not in CVS, # "make" will update the $(DOMAIN).pot and the $(CATALOGS), but subsequent # invocations of "make" will do nothing. This timestamp would not be necessary # if updating the $(CATALOGS) would always touch them; however, the rule for # $(POFILES) has been designed to not touch files that don't need to be # changed. stamp-po: $(srcdir)/$(DOMAIN).pot test ! -f $(srcdir)/$(DOMAIN).pot || \ test -z "$(GMOFILES)" || $(MAKE) $(GMOFILES) @test ! -f $(srcdir)/$(DOMAIN).pot || { \ echo "touch stamp-po" && \ echo timestamp > stamp-poT && \ mv stamp-poT stamp-po; \ } # Note: Target 'all' must not depend on target '$(DOMAIN).pot-update', # otherwise packages like GCC can not be built if only parts of the source # have been downloaded. # This target rebuilds $(DOMAIN).pot; it is an expensive operation. # Note that $(DOMAIN).pot is not touched if it doesn't need to be changed. $(DOMAIN).pot-update: $(POTFILES) $(srcdir)/POTFILES.in remove-potcdate.sed if test -n '$(MSGID_BUGS_ADDRESS)' || test '$(PACKAGE_BUGREPORT)' = '@'PACKAGE_BUGREPORT'@'; then \ msgid_bugs_address='$(MSGID_BUGS_ADDRESS)'; \ else \ msgid_bugs_address='$(PACKAGE_BUGREPORT)'; \ fi; \ $(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: stamp-po $(DISTFILES) dists="$(DISTFILES)"; \ if test "$(PACKAGE)" = "gettext-tools"; then \ dists="$$dists Makevars.template"; \ fi; \ if test -f $(srcdir)/$(DOMAIN).pot; then \ dists="$$dists $(DOMAIN).pot stamp-po"; \ fi; \ if test -f $(srcdir)/ChangeLog; then \ dists="$$dists ChangeLog"; \ fi; \ for i in 0 1 2 3 4 5 6 7 8 9; do \ if test -f $(srcdir)/ChangeLog.$$i; then \ dists="$$dists ChangeLog.$$i"; \ fi; \ done; \ if test -f $(srcdir)/LINGUAS; then dists="$$dists LINGUAS"; fi; \ for file in $$dists; do \ if test -f $$file; then \ cp -p $$file $(distdir) || exit 1; \ else \ cp -p $(srcdir)/$$file $(distdir) || exit 1; \ fi; \ done update-po: Makefile $(MAKE) $(DOMAIN).pot-update test -z "$(UPDATEPOFILES)" || $(MAKE) $(UPDATEPOFILES) $(MAKE) update-gmo # General rule for creating PO files. .nop.po-create: @lang=`echo $@ | sed -e 's/\.po-create$$//'`; \ echo "File $$lang.po does not exist. If you are a translator, you can create it through 'msginit'." 1>&2; \ exit 1 # General rule for updating PO files. .nop.po-update: @lang=`echo $@ | sed -e 's/\.po-update$$//'`; \ if test "$(PACKAGE)" = "gettext-tools"; then PATH=`pwd`/../src:$$PATH; fi; \ tmpdir=`pwd`; \ echo "$$lang:"; \ test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \ echo "$${cdcmd}$(MSGMERGE) $$lang.po $(DOMAIN).pot -o $$lang.new.po"; \ cd $(srcdir); \ if $(MSGMERGE) $$lang.po $(DOMAIN).pot -o $$tmpdir/$$lang.new.po; then \ if cmp $$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \ rm -f $$tmpdir/$$lang.new.po; \ else \ if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \ :; \ else \ echo "msgmerge for $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \ exit 1; \ fi; \ fi; \ else \ echo "msgmerge for $$lang.po failed!" 1>&2; \ rm -f $$tmpdir/$$lang.new.po; \ fi $(DUMMYPOFILES): update-gmo: Makefile $(GMOFILES) @: Makefile: Makefile.in.in Makevars $(top_builddir)/config.status @POMAKEFILEDEPS@ cd $(top_builddir) \ && 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: hercules-3.07/po/Makevars000644 000765 000765 00000002120 11143760531 017051 0ustar00jmaynardjmaynard000000 000000 # Makefile variables for PO directory in any package using GNU gettext. # Usually the message domain is the same as the package name. DOMAIN = $(PACKAGE) # These two variables depend on the location of this directory. subdir = po top_builddir = .. # These options get passed to xgettext. XGETTEXT_OPTIONS = --keyword=_ --keyword=N_ # This is the copyright holder that gets inserted into the header of the # $(DOMAIN).pot file. Set this to the copyright holder of the surrounding # package. (Note that the msgstr strings, extracted from the package's # sources, belong to the copyright holder of the package.) Translators are # expected to transfer the copyright for their translations to this person # or entity, or to disclaim their copyright. The empty string stands for # the public domain; in this case the translators are expected to disclaim # their copyright. COPYRIGHT_HOLDER = Roger Bowler, Jan Jaeger, Jay Maynard, and others. # 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 = hercules-3.07/po/nl.gmo000644 000765 000765 00000002032 11157243117 016475 0ustar00jmaynardjmaynard000000 000000 Ŝ•\ œÈ2É,ü/) Yg#‚.Ĥ5Ġ2 />0n ŸĴ Ê.ë CPU%4.4X: Connected to channelset %4.4X CPU%4.4X: No channelset connected Last 'TXT' record had address: %3.3X %sVersion %s ERROR: Cannot open %s: %s HHCCA006T %4.4X:Select failed : %s HHCCA013E %4.4X:Incorrect %s specification %s Project-Id-Version: hercules 2.16 Report-Msgid-Bugs-To: POT-Creation-Date: 2007-06-23 14:23-0500 PO-Revision-Date: 2002-05-10 16:16+0200 Last-Translator: Jan Jaeger Language-Team: none MIME-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 8bit CPU%4.4X: Verbonden met kanaalset %4.4X CPU%4.4X: Geen kanaalset aangesloten Laatste 'TXT' record had adres: %3.3X %sVersie %s FOUT: Kan %s niet openen: %s HHCCA006T %4.4X:Select fout: %s HHCCA013E %4.4X:Incorrecte %s specifikatie %s hercules-3.07/po/nl.po000644 000765 000765 00000443363 11143760531 016350 0ustar00jmaynardjmaynard000000 000000 # NL.PO Hercules dutch messages # This file is put in the public domain. # Jan Jaeger , 2002-2003. # msgid "" msgstr "" "Project-Id-Version: hercules 2.16\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2007-06-23 14:23-0500\n" "PO-Revision-Date: 2002-05-10 16:16+0200\n" "Last-Translator: Jan Jaeger \n" "Language-Team: none \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=ISO-8859-1\n" "Content-Transfer-Encoding: 8bit\n" #: cache.c:399 #, fuzzy, c-format msgid "HHCCH001E calloc failed cache[%d] size %d: %s\n" msgstr "HHCDL019E Fout %2$s bij het lezen van regel %$2d in bestand \"%1$s\"\n" #: cache.c:522 #, c-format msgid "HHCCH002W realloc increase failed cache[%d] size %d: %s\n" msgstr "" #: cache.c:541 #, c-format msgid "HHCCH003W realloc decrease failed cache[%d] size %d: %s\n" msgstr "" #: cache.c:558 #, c-format msgid "HHCCH004W buf calloc failed cache[%d] size %d: %s\n" msgstr "" #: cache.c:560 msgid "HHCCH005W releasing inactive buffer space\n" msgstr "" #: cache.c:565 #, fuzzy, c-format msgid "HHCCH006E Unable to calloc buf cache[%d] size %d: %s\n" msgstr "HHCRD010E Fout %2$s bij benaderen bestand \"%1$s\"\n" #: cardpch.c:44 #, fuzzy, c-format msgid "HHCPU004E Error writing to %s: %s\n" msgstr "HHCPU004E Fout %2$s bij schrijven naar bestand \"%1$s\"\n" #: cardpch.c:64 #, fuzzy msgid "HHCPU001E File name missing or invalid\n" msgstr "HHCPU001E Bestandsnaam niet opgegeven of ongeldig\n" #: cardpch.c:102 #, fuzzy, c-format msgid "HHCPU002E Invalid argument: %s\n" msgstr "HHCPU002E Optie %s niet geldig\n" #: cardpch.c:183 #, fuzzy, c-format msgid "HHCPU003E Error opening file %s: %s\n" msgstr "HHCPU003E Fout %2$s bij openen van bestand \"%1$s\"\n" #: cardrdr.c:92 #, fuzzy msgid "HHCRD001E Out of memory\n" msgstr "HHCRD001E Niet genoeg geheugen\n" #: cardrdr.c:190 #, fuzzy, c-format msgid "HHCRD002E File name too long (max=%ud): \"%s\"\n" msgstr "HHCRD002E Bestandsnaam \"%2$s\" te lang (maximum=%1$ud)\n" #: cardrdr.c:197 #, fuzzy, c-format msgid "HHCRD003E Unable to access file \"%s\": %s\n" msgstr "HHCRD003E Fout %2$s bij benaderen bestand \"%1$s\"\n" #: cardrdr.c:207 #, fuzzy msgid "HHCRD004E Out of memory\n" msgstr "HHCRD004E Niet genoeg geheugen\n" #: cardrdr.c:220 #, fuzzy msgid "HHCRD005E Specify 'ascii' or 'ebcdic' (or neither) but not both\n" msgstr "HHCRD005E Specificeer 'ascii' of 'ebcdic' (of niets) maar niet beide\n" #: cardrdr.c:229 #, fuzzy msgid "HHCRD006E Only one filename (sock_spec) allowed for socket devices\n" msgstr "HHCRD006E Maar een bestandsnaam toegestaan voor socket apparaten\n" #: cardrdr.c:244 #, fuzzy, c-format msgid "HHCRD007I Defaulting to 'ascii' for socket device %4.4X\n" msgstr "" "HHCRD007I standaard waarde 'ascii' aan socket apparaat %4.4X toegekend\n" #: cardrdr.c:252 #, fuzzy msgid "HHCRD008W 'multifile' option ignored: only one file specified\n" msgstr "HHCRD008W 'multifile' optie niet gebruikt\n" #: cardrdr.c:265 #, fuzzy, c-format msgid "HHCRD009E File name too long (max=%ud): \"%s\"\n" msgstr "HHCRD009E Bestandsnaam \"%2$s\" te lang (maximum=%1$ud)\n" #: cardrdr.c:279 #, fuzzy, c-format msgid "HHCRD010E Unable to access file \"%s\": %s\n" msgstr "HHCRD010E Fout %2$s bij benaderen bestand \"%1$s\"\n" #: cardrdr.c:360 #, fuzzy, c-format msgid "HHCRD011E Close error on file \"%s\": %s\n" msgstr "HHCRD011E Fout %2$s bij sluiten van bestand \"%1$s\"\n" #: cardrdr.c:369 #, fuzzy, c-format msgid "HHCRD012I %s (%s) disconnected from device %4.4X (%s)\n" msgstr "HHCRD012I %s (%s) afgesloten van apparaat %4.4X (%s)\n" #: cardrdr.c:468 #, fuzzy, c-format msgid "HHCRD013E Error opening file %s: %s\n" msgstr "HHCRD013E Fout %2$s bij openen bestand \"%1$s\"\n" #: cardrdr.c:490 #, fuzzy, c-format msgid "HHCRD014E Error reading file %s: %s\n" msgstr "HHCRD014E Fout %2$s bij lezen van bestand \"%1$s\"\n" #: cardrdr.c:523 #, fuzzy, c-format msgid "HHCRD015E Seek error in file %s: %s\n" msgstr "HHCRD015E Fout %2$s bij zoeken in bestand \"%1$s\"\n" #: cardrdr.c:596 #, fuzzy, c-format msgid "HHCRD016E Error reading file %s: %s\n" msgstr "HHCRD016E Fout %2$s bij lezen van bestand \"%1$s\"\n" #: cardrdr.c:599 #, fuzzy, c-format msgid "HHCRD017E Unexpected end of file on %s\n" msgstr "HHCRD017E Onverwacht einde van bestand \"%s\"\n" #: cardrdr.c:672 #, fuzzy, c-format msgid "HHCRD018E Error reading file %s: %s\n" msgstr "HHCRD018E Fout %2$s bij lezen van bestand \"%1$s\"\n" #: cardrdr.c:700 #, fuzzy, c-format msgid "HHCRD019E Card image exceeds %d bytes in file %s\n" msgstr "HHCRD019E Ponskaart %d bytes te groot in bestand \"%s\"\n" #: cckdcdsk.c:139 #, c-format msgid "" "\n" "cckdcdsk [-v] [-f] [-level] [-ro] file1 [file2 ...]\n" "\n" " -v display version and exit\n" "\n" " -f force check even if OPENED bit is on\n" "\n" " level is a digit 0 - 3:\n" " -0 -- minimal checking\n" " -1 -- normal checking\n" " -3 -- maximal checking\n" "\n" " -ro open file readonly, no repairs\n" "\n" msgstr "" #: cckddasd.c:322 #, fuzzy, c-format msgid "HHCCD101E %4.4X error initializing shadow files\n" msgstr "HHCPR003E %$14.4X:Fout %3$s bij schrijven naar bestand \"%2$s\"\n" #: cckddasd.c:586 #, fuzzy, c-format msgid "HHCCD130E %4.4X file[%d] %s open error: %s\n" msgstr "HHCDA058E Fout %2$s bij openen bestand \"%1$s\"\n" #: cckddasd.c:621 #, fuzzy, c-format msgid "HHCCD130E %4.4X file[%d] close error: %s\n" msgstr "HHCDU040E Fout %2$s bij sluiten van bestand \"%1$s\"\n" #: cckddasd.c:649 cckddasd.c:690 #, fuzzy msgid "HHCCD130E %4.4X file[%d] lseek error, offset 0x%" msgstr "HHCDU010E Fout %2$s bij lezen van bestand \"%1$s\"\n" #: cckddasd.c:660 #, fuzzy msgid "HHCCD130E %4.4X file[%d] read error, offset 0x%" msgstr "HHCDU010E Fout %2$s bij lezen van bestand \"%1$s\"\n" #: cckddasd.c:663 #, fuzzy msgid "HHCCD130E %4.4X file[%d] read incomplete, offset 0x%" msgstr "HHCDU010E Fout %2$s bij lezen van bestand \"%1$s\"\n" #: cckddasd.c:700 #, fuzzy msgid "HHCCD130E %4.4X file[%d] write error, offset 0x%" msgstr "HHCDU010E Fout %2$s bij lezen van bestand \"%1$s\"\n" #: cckddasd.c:703 #, fuzzy msgid "HHCCD130E %4.4X file[%d] write incomplete, offset 0x%" msgstr "HHCDU010E Fout %2$s bij lezen van bestand \"%1$s\"\n" #: cckddasd.c:729 #, fuzzy msgid "HHCCD130E %4.4X file[%d] ftruncate error, offset 0x%" msgstr "HHCDU010E Fout %2$s bij lezen van bestand \"%1$s\"\n" #: cckddasd.c:751 #, fuzzy, c-format msgid "HHCCD130E %4.4X malloc error, size %d: %s\n" msgstr "HHCCA018E %4.4X:Bind fout: %s\n" #: cckddasd.c:772 #, fuzzy, c-format msgid "HHCCD130E %4.4X calloc error, size %d: %s\n" msgstr "HHCDU040E Fout %2$s bij sluiten van bestand \"%1$s\"\n" #: cckddasd.c:1518 #, fuzzy, c-format msgid "HHCCD001I Readahead thread %d started: tid=" msgstr "HHCCP012I Timer thread gestart: tid=%p, pid=%d\n" #: cckddasd.c:1569 #, c-format msgid "HHCCD011I Readahead thread %d stopping: tid=" msgstr "" #: cckddasd.c:1719 #, fuzzy, c-format msgid "HHCCD002I Writer thread %d started: tid=" msgstr "HHCCP012I Timer thread gestart: tid=%p, pid=%d\n" #: cckddasd.c:1841 #, fuzzy, c-format msgid "HHCCD012I Writer thread %d stopping: tid=" msgstr "HHCCP012I Timer thread gestart: tid=%p, pid=%d\n" #: cckddasd.c:1979 #, fuzzy, c-format msgid "HHCCD102E %4.4X file[%d] get space error, size exceeds %lldM\n" msgstr "HHCDU010E Fout %2$s bij lezen van bestand \"%1$s\"\n" #: cckddasd.c:2488 #, fuzzy, c-format msgid "HHCCD110E %4.4X file[%d] devhdr id error\n" msgstr "HHCPN015E Ongeldig apparaat nummer\n" #: cckddasd.c:3216 #, c-format msgid "HHCCD121E %4.4X file[%d] trklen err for %2.2x%2.2x%2.2x%2.2x%2.2x\n" msgstr "" #: cckddasd.c:3385 #, c-format msgid "" "HHCCD122E %4.4X file[%d] invalid byte 0 trk %d: buf %2.2x%2.2x%2.2x%2.2x%" "2.2x\n" msgstr "" #: cckddasd.c:3407 #, c-format msgid "" "HHCCD123E %4.4X file[%d] invalid byte 0 blkgrp %d: buf %2.2x%2.2x%2.2x%2.2x%" "2.2x\n" msgstr "" #: cckddasd.c:3422 #, c-format msgid "" "HHCCD124E %4.4X file[%d] invalid %s hdr %s %d: %s compression unsupported\n" msgstr "" #: cckddasd.c:3430 #, c-format msgid "" "HHCCD125E %4.4X file[%d] invalid %s hdr %s %d buf %p:%2.2x%2.2x%2.2x%2.2x%" "2.2x\n" msgstr "" #: cckddasd.c:3584 #, c-format msgid "" "HHCCD142E %4.4X file[%d] shadow file name %s\n" " collides with %4.4X file[%d] name %s\n" msgstr "" #: cckddasd.c:3629 #, c-format msgid "" "HHCCD151E %4.4X file[%d] error re-opening %s readonly\n" " %s\n" msgstr "" #: cckddasd.c:3657 #, fuzzy, c-format msgid "HHCCD161E %4.4X file[%d] no shadow file name\n" msgstr "HHCPN015E Ongeldig apparaat nummer\n" #: cckddasd.c:3665 #, c-format msgid "HHCCD161E %4.4X file[%d] max shadow files exceeded\n" msgstr "" #: cckddasd.c:3748 #, fuzzy, c-format msgid "HHCCD160E %4.4X not a cckd device\n" msgstr "HHCPN015E Ongeldig apparaat nummer\n" #: cckddasd.c:3778 #, c-format msgid "HHCCD161E %4.4X file[%d] error adding shadow file\n" msgstr "" #: cckddasd.c:3787 #, fuzzy, c-format msgid "HHCCD162I %4.4X file[%d] %s added\n" msgstr "HHCCA018E %4.4X:Bind fout: %s\n" #: cckddasd.c:3834 #, fuzzy, c-format msgid "HHCCD170E %4.4X not a cckd device\n" msgstr "HHCPN015E Ongeldig apparaat nummer\n" #: cckddasd.c:3840 #, c-format msgid "HHCCD171E %4.4X file[%d] cannot remove base file\n" msgstr "" #: cckddasd.c:3884 #, c-format msgid "" "HHCCD172E %4.4X file[%d] not merged, file[%d] cannot be opened read-write%s\n" msgstr "" #: cckddasd.c:3898 #, c-format msgid "HHCCD173E %4.4X file[%d] not merged, file[%d] check failed\n" msgstr "" #: cckddasd.c:3911 #, c-format msgid "HHCCD174E %4.4X file[%d] not merged, file not hardened\n" msgstr "" #: cckddasd.c:4076 #, c-format msgid "HHCCD181I %4.4X shadow file [%d] successfully %s%s\n" msgstr "" #: cckddasd.c:4108 #, fuzzy, c-format msgid "HHCCD201W %4.4X device is not a shadow file\n" msgstr "HHCPN015E Ongeldig apparaat nummer\n" #: cckddasd.c:4113 #, c-format msgid "HHCCD202W %4.4X file shadowing not activated\n" msgstr "" #: cckddasd.c:4121 #, fuzzy, c-format msgid "HHCCD203W %4.4X shadowing is already active\n" msgstr "HHCCP005E CPU%4.4X thread al gestart\n" #: cckddasd.c:4130 #, fuzzy, c-format msgid "HHCCD204I %4.4X shadow file name set to %s\n" msgstr "HHCCP007I CPU%4.4X Architectuur Modus %s\n" #: cckddasd.c:4148 #, c-format msgid "HHCCD205W %4.4X device is not a shadow file\n" msgstr "" #: cckddasd.c:4213 #, fuzzy, c-format msgid "HHCCD206W %4.4X device is not a shadow file\n" msgstr "HHCPN015E Ongeldig apparaat nummer\n" #: cckddasd.c:4230 msgid "" "HHCCD210I size free nbr st reads writes l2reads hits " "switches\n" msgstr "" #: cckddasd.c:4232 msgid "" "HHCCD211I readaheads " "misses\n" msgstr "" #: cckddasd.c:4233 msgid "" "HHCCD212I " "--------------------------------------------------------------------\n" msgstr "" #: cckddasd.c:4236 msgid "HHCCD213I [*] %10" msgstr "" #: cckddasd.c:4241 #, c-format msgid "" "HHCCD214I %7d %7d\n" msgstr "" #: cckddasd.c:4245 #, c-format msgid "HHCCD215I %s\n" msgstr "" #: cckddasd.c:4246 msgid "HHCCD216I [0] %10" msgstr "" #: cckddasd.c:4253 #, c-format msgid "HHCCD217I %s\n" msgstr "" #: cckddasd.c:4258 msgid "HHCCD218I [%d] %10" msgstr "" #: cckddasd.c:4357 #, fuzzy msgid "HHCCD003I Garbage collector thread started: tid=" msgstr "HHCTE001I Controle paneel thread gestart: tid=%8.8lX, pid=%d\n" #: cckddasd.c:4465 msgid "HHCCD013I Garbage collector thread stopping: tid=" msgstr "" #: cckddasd.c:4690 #, fuzzy msgid "HHCCD190E %4.4X file[%d] offset 0x%" msgstr "HHCDU040E Fout %2$s bij sluiten van bestand \"%1$s\"\n" #: cckddasd.c:4960 #, c-format msgid "" "HHCCD193E %4.4X file[%d] uncompress error trk %d: %2.2x%2.2x%2.2x%2.2x%2.2x\n" msgstr "" #: cckddasd.c:4963 #, c-format msgid "HHCCD194E %4.4X file[%d] %s compression not supported\n" msgstr "" #: cckddasd.c:5488 msgid "HHCCD900I print_itrace\n" msgstr "" #: cckddiag.c:138 #, c-format msgid "lseek to pos 0x%8.8x error: %s\n" msgstr "" #: cckddiag.c:154 #, c-format msgid "cckddiag: read error: %s\n" msgstr "" #: cckddiag.c:509 #, c-format msgid "cckddiag: error opening file %s: %s\n" msgstr "" #: channel.c:125 #, c-format msgid "HHCCP048I %4.4X:CCW=%2.2X%2.2X%2.2X%2.2X %2.2X%2.2X%2.2X%2.2X%s\n" msgstr "" #: channel.c:138 #, c-format msgid "HHCCP049I %4.4X:Stat=%2.2X%2.2X Count=%2.2X%2.2X CCW=%2.2X%2.2X%2.2X\n" msgstr "" #: channel.c:151 #, c-format msgid "" "HHCCP050I %4.4X:SCSW=%2.2X%2.2X%2.2X%2.2X Stat=%2.2X%2.2X Count=%2.2X%2.2X " "CCW=%2.2X%2.2X%2.2X%2.2X\n" msgstr "" #: channel.c:260 #, c-format msgid "HHCCP051I %4.4X: Test I/O\n" msgstr "" #: channel.c:325 #, fuzzy msgid "HHCCP052I TIO modification executed CC=1\n" msgstr "HHCCP052I TIO modificatie uitgevoerd CC=1\n" #: channel.c:362 #, c-format msgid "HHCCP053I %4.4X: Halt I/O\n" msgstr "" #: channel.c:416 #, fuzzy msgid "HHCCP054I HIO modification executed CC=1\n" msgstr "HHCCP054I HIO modificatie uitgevoerd CC=1\n" #: channel.c:787 #, c-format msgid "HHCCP055I %4.4X: Clear subchannel\n" msgstr "" #: channel.c:888 #, c-format msgid "HHCCP056I %4.4X: Halt subchannel\n" msgstr "" #: channel.c:910 #, c-format msgid "HHCCP057I %4.4X: Halt subchannel: cc=1\n" msgstr "" #: channel.c:920 #, c-format msgid "HHCCP058I %4.4X: Halt subchannel: cc=2\n" msgstr "" #: channel.c:1011 #, c-format msgid "HHCCP059I %4.4X: Halt subchannel: cc=0\n" msgstr "" #: channel.c:1049 #, c-format msgid "HHCCP060I %4.4X: Resume subchannel: cc=1\n" msgstr "" #: channel.c:1063 #, c-format msgid "HHCCP061I %4.4X: Resume subchannel: cc=2\n" msgstr "" #: channel.c:1086 #, c-format msgid "HHCCP062I %4.4X: Resume subchannel: cc=0\n" msgstr "" #: channel.c:1844 msgid "HHCCP078I %4.4X:MIDAW=%2.2X %4.4" msgstr "" #: channel.c:1943 msgid "HHCCP063I %4.4X:IDAW=%8.8" msgstr "" #: channel.c:1948 msgid "HHCCP064I %4.4X:IDAW=%16.16" msgstr "" #: channel.c:2065 #, c-format msgid "HHCCP065I DEV%4.4X: attention signalled\n" msgstr "" #: channel.c:2077 #, c-format msgid "HHCCP066I DEV%4.4X: attention\n" msgstr "" #: channel.c:2302 #, fuzzy, c-format msgid "HHCCP067E %4.4X create_thread error: %s" msgstr "HHCCP067E %4.4X create_thread fout: %s" #: channel.c:2325 #, fuzzy, c-format msgid "HHCCP068E %4.4X create_thread error: %s" msgstr "HHCCP068E %4.4X create_thread fout: %s" #: channel.c:2518 #, c-format msgid "HHCCP069I Device %4.4X initial status interrupt\n" msgstr "" #: channel.c:2557 #, c-format msgid "HHCCP070I Device %4.4X attention completed\n" msgstr "" #: channel.c:2623 #, c-format msgid "HHCCP071I Device %4.4X clear completed\n" msgstr "" #: channel.c:2678 #, c-format msgid "HHCCP072I Device %4.4X halt completed\n" msgstr "" #: channel.c:2856 #, c-format msgid "HHCCP073I Device %4.4X suspended\n" msgstr "" #: channel.c:2914 #, c-format msgid "HHCCP074I Device %4.4X resumed\n" msgstr "" #: channel.c:3128 #, c-format msgid "HHCCP075I %4.4X:Stat=%2.2X%2.2X Count=%4.4X %s\n" msgstr "" #: channel.c:3134 #, c-format msgid "" "HHCCP076I %4.4X:Sense=%2.2X%2.2X%2.2X%2.2X %2.2X%2.2X%2.2X%2.2X %2.2X%2.2X%" "2.2X%2.2X %2.2X%2.2X%2.2X%2.2X %2.2X%2.2X%2.2X%2.2X %2.2X%2.2X%2.2X%2.2X\n" msgstr "" #: channel.c:3149 #, c-format msgid "HHCCP077I %4.4X:Sense=%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n" msgstr "" #: ckddasd.c:237 #, fuzzy msgid "HHCDA001E File name missing or invalid\n" msgstr "HHCDA001E Bestandsnaam niet opgegeven of ongeldig\n" #: ckddasd.c:255 #, fuzzy, c-format msgid "HHCDA002E %4.4X:File not found or invalid\n" msgstr "HHCDA002E %4.4X:Bestandsnaam niet opgegeven of ongeldig\n" #: ckddasd.c:357 #, c-format msgid "HHCDA003E parameter %d is invalid: %s\n" msgstr "" #: ckddasd.c:368 #, c-format msgid "HHCDA004I opening %s readonly%s\n" msgstr "" #: ckddasd.c:382 #, fuzzy, c-format msgid "HHCDA005E %s open error: %s\n" msgstr "HHCDA005E Fout %2$s bij openen bestand \"%1$s\"\n" #: ckddasd.c:391 #, c-format msgid "HHCDA006E %s not in a single file for shadowing\n" msgstr "" #: ckddasd.c:400 #, c-format msgid "HHCDA007E %s fstat error: %s\n" msgstr "" #: ckddasd.c:410 #, c-format msgid "HHCDA008E %s read error: %s\n" msgstr "" #: ckddasd.c:413 #, c-format msgid "HHCDA09E %s CKD header incomplete\n" msgstr "" #: ckddasd.c:423 #, c-format msgid "HHCDA010E %s CKD header invalid\n" msgstr "" #: ckddasd.c:432 #, c-format msgid "HHCDA011E %s Only 1 CCKD file allowed\n" msgstr "" #: ckddasd.c:447 #, fuzzy, c-format msgid "HHCDA012E %s read error: %s\n" msgstr "HHCDA012E Fout %2$s bij lezen van bestand \"%1$s\"\n" #: ckddasd.c:452 #, c-format msgid "HHCDA013E %s CCKD header incomplete\n" msgstr "" #: ckddasd.c:510 #, c-format msgid "HHCDA014E %s CKD file out of sequence\n" msgstr "" #: ckddasd.c:517 #, c-format msgid "HHCDA015I %s seq=%d cyls=%d-%d\n" msgstr "" #: ckddasd.c:531 #, c-format msgid "HHCDA016E %s heads=%d trklen=%d, expected heads=%d trklen=%d\n" msgstr "" #: ckddasd.c:544 #, c-format msgid "HHCDA017E %s CKD header inconsistent with file size\n" msgstr "" #: ckddasd.c:552 #, c-format msgid "HHCDA018E %s CKD header high cylinder incorrect\n" msgstr "" #: ckddasd.c:578 #, c-format msgid "HHCDA019E %s exceeds maximum %d CKD files\n" msgstr "" #: ckddasd.c:589 #, c-format msgid "HHCDA020I %s cyls=%d heads=%d tracks=%d trklen=%d\n" msgstr "" #: ckddasd.c:611 #, c-format msgid "HHCDA021E %4.4X device type %4.4X not found in dasd table\n" msgstr "" #: ckddasd.c:620 #, c-format msgid "HHCDA022E %4.4X control unit %s not found in dasd table\n" msgstr "" #: ckddasd.c:702 #, c-format msgid "HHCDA023I %4.4X cache hits %d, misses %d, waits %d\n" msgstr "" #: ckddasd.c:785 #, c-format msgid "HHCDA024I read trk %d cur trk %d\n" msgstr "" #: ckddasd.c:814 #, c-format msgid "HHCDA025I read track: updating track %d\n" msgstr "" #: ckddasd.c:825 #, c-format msgid "HHCDA026E error writing trk %d: lseek error: %s\n" msgstr "" #: ckddasd.c:844 #, c-format msgid "HHCDA027E error writing trk %d: write error: %s\n" msgstr "" #: ckddasd.c:886 #, c-format msgid "HHCDA028I read trk %d cache hit, using cache[%d]\n" msgstr "" #: ckddasd.c:923 #, c-format msgid "HHCDA029I read trk %d no available cache entry, waiting\n" msgstr "" #: ckddasd.c:931 #, c-format msgid "HHCDA030I read trk %d cache miss, using cache[%d]\n" msgstr "" #: ckddasd.c:954 #, fuzzy msgid "HHCDA031I read trk %d reading file %d offset %" msgstr "HHCRD014E Fout %2$s bij lezen van bestand \"%1$s\"\n" #: ckddasd.c:963 #, c-format msgid "HHCDA032E error reading trk %d: lseek error: %s\n" msgstr "" #: ckddasd.c:981 #, c-format msgid "HHCDA033E error reading trk %d: read error: %s\n" msgstr "" #: ckddasd.c:1004 #, c-format msgid "HHCDA034I read trk %d trkhdr %2.2x %2.2x%2.2x %2.2x%2.2x\n" msgstr "" #: ckddasd.c:1013 #, c-format msgid "" "HHCDA035E %4.4X invalid track header for cyl %d head %d %2.2x%2.2x%2.2x%2.2x" "%2.2x\n" msgstr "" #: ckddasd.c:1527 #, c-format msgid "HHCDA038I seeking to cyl %d head %d\n" msgstr "" #: ckddasd.c:1566 #, c-format msgid "HHCDA039E MT advance error: locate record %d file mask %2.2X\n" msgstr "" #: ckddasd.c:1598 #, c-format msgid "HHCDA040I MT advance to cyl %d head %d\n" msgstr "" #: ckddasd.c:1645 #, c-format msgid "HHCDA041I read count orientation is %s\n" msgstr "" #: ckddasd.c:1669 #, c-format msgid "HHCDA042E attempt to read past end of track %d %d\n" msgstr "" #: ckddasd.c:1691 #, c-format msgid "HHCDA043I cyl %d head %d record %d kl %d dl %d of %d\n" msgstr "" #: ckddasd.c:1779 #, c-format msgid "HHCDA044I read key %d bytes\n" msgstr "" #: ckddasd.c:1787 msgid "ckddasd: attempt to read past end of track\n" msgstr "" #: ckddasd.c:1829 #, c-format msgid "HHCDA045I read data %d bytes\n" msgstr "" #: ckddasd.c:1837 msgid "HHCDA046E attempt to read past end of track\n" msgstr "" #: ckddasd.c:1955 #, c-format msgid "HHCDA047I writing cyl %d head %d record %d kl %d dl %d\n" msgstr "" #: ckddasd.c:1961 #, c-format msgid "HHCDA048I setting track overflow flag for cyl %d head %d record %d\n" msgstr "" #: ckddasd.c:2006 msgid "HHCDA049E Write KD orientation error\n" msgstr "" #: ckddasd.c:2019 #, c-format msgid "HHCDA050I updating cyl %d head %d record %d kl %d dl %d\n" msgstr "" #: ckddasd.c:2048 msgid "HHCDA051E Write data orientation error\n" msgstr "" #: ckddasd.c:2062 #, c-format msgid "HHCDA052I updating cyl %d head %d record %d dl %d\n" msgstr "" #: ckddasd.c:2121 #, c-format msgid "HHCDA053E Data chaining not supported for CCW %2.2X\n" msgstr "" #: ckddasd.c:3375 #, c-format msgid "HHCDA054I set file mask %2.2X\n" msgstr "" #: ckddasd.c:3543 #, c-format msgid "HHCDA055I search key %s\n" msgstr "" #: codepage.c:485 #, c-format msgid "HHCCF072I Using internal codepage conversion table %s\n" msgstr "" #: codepage.c:495 #, c-format msgid "HHCCF072I Using external codepage conversion table %s\n" msgstr "" #: codepage.c:501 #, c-format msgid "HHCCF051E Codepage conversion table %s is not defined\n" msgstr "" #: commadpt.c:97 #, c-format msgid "HHCCA300D %4.4X:%s : Status = TEXT=%s, TRANS=%s, TWS=%s\n" msgstr "" #: commadpt.c:103 #, c-format msgid "HHCCA300D %4.4X:%s : Dump of %d (%x) byte(s)\n" msgstr "" #: commadpt.c:112 #, c-format msgid "HHCCA300D %4.4X:%s : %4.4X:" msgstr "" #: commadpt.c:262 #, c-format msgid "HHCCA300D %4.4X:clean : Control block freed\n" msgstr "" #: commadpt.c:270 #, c-format msgid "HHCCA300D %4.4X:clean : Control block not freed : not allocated\n" msgstr "" #: commadpt.c:284 #, c-format msgid "HHCCA020E %4.4X:Memory allocation failure for main control block\n" msgstr "" #: commadpt.c:365 #, c-format msgid "" "HHCCA001I %4.4X:Connect out to %s:%d failed during initial status : %s\n" msgstr "" #: commadpt.c:407 #, c-format msgid "HHCCA300D %4.4x : Found data beyond EON\n" msgstr "" #: commadpt.c:422 #, c-format msgid "HHCCA300D %4.4x : Found incorrect IP address section at position %d\n" msgstr "" #: commadpt.c:423 #, c-format msgid "HHCCA300D %4.4x : %d greater than 255\n" msgstr "" #: commadpt.c:437 #, c-format msgid "HHCCA300D %4.4x : Too many separators in dial data\n" msgstr "" #: commadpt.c:454 #, c-format msgid "HHCCA300D %4.4x : Incorrect dial data byte %2.2x\n" msgstr "" #: commadpt.c:475 #, c-format msgid "HHCCA300D %4.4x : Not enough separators (only %d found) in dial data\n" msgstr "" #: commadpt.c:483 #, c-format msgid "HHCCA300D %4.4x : Destination TCP port %d exceeds maximum of 65535\n" msgstr "" #: commadpt.c:616 #, c-format msgid "HHCCA002I %4.4X:Line Communication thread " msgstr "" #: commadpt.c:628 #, c-format msgid "HHCCA003E %4.4X:Cannot obtain socket for incoming calls : %s\n" msgstr "" #: commadpt.c:653 #, c-format msgid "HHCCA004W %4.4X:Waiting 5 seconds for port %d to become available\n" msgstr "" #: commadpt.c:704 #, fuzzy, c-format msgid "HHCCA018E %4.4X:Bind failed : %s\n" msgstr "HHCCA018E %4.4X:Bind fout: %s\n" #: commadpt.c:718 #, c-format msgid "HHCCA005I %4.4X:Listening on port %d for incoming TCP connections\n" msgstr "" #: commadpt.c:756 #, c-format msgid "HHCCA300D %4.4X:cthread - Entry - DevExec = %s\n" msgstr "" #: commadpt.c:821 #, c-format msgid "HHCCA300D %4.4X:Poll Command abort - Poll address >7 Bytes\n" msgstr "" #: commadpt.c:849 #, c-format msgid "HHCCA300D %4.4X:Writing 1 byte in socket : %2.2X\n" msgstr "" #: commadpt.c:1029 #, c-format msgid "HHCCA300D %4.4X:cthread - Select IN maxfd = %d / Devexec = %s\n" msgstr "" #: commadpt.c:1035 #, c-format msgid "HHCCA300D %4.4X:cthread - Select OUT rc=%d\n" msgstr "" #: commadpt.c:1051 #, c-format msgid "HHCCA006T %4.4X:Select failed : %s\n" msgstr "HHCCA006T %4.4X:Select fout: %s\n" #: commadpt.c:1062 #, c-format msgid "HHCCA300D %4.4X:cthread - Select TIME OUT\n" msgstr "" #: commadpt.c:1080 #, c-format msgid "HHCCA300D %4.4X:cthread - IPC Pipe closed\n" msgstr "" #: commadpt.c:1088 #, c-format msgid "HHCCA300D %4.4X:cthread - IPC Pipe Data ; code = %d\n" msgstr "" #: commadpt.c:1120 #, c-format msgid "HHCCA300D %4.4X:cthread - inbound socket data\n" msgstr "" #: commadpt.c:1162 #, c-format msgid "HHCCA300D %4.4X:cthread - socket write available\n" msgstr "" #: commadpt.c:1176 #, c-format msgid "HHCCA007W %4.4X:Outgoing call failed during %s command : %s\n" msgstr "" #: commadpt.c:1206 #, c-format msgid "HHCCA008I %4.4X:cthread - Incoming Call\n" msgstr "" #: commadpt.c:1266 #, c-format msgid "HHCCA009I %4.4X:BSC utility thread terminated\n" msgstr "" #: commadpt.c:1317 #, c-format msgid "HHCCA013E %4.4X:Incorrect %s specification %s\n" msgstr "HHCCA013E %4.4X:Incorrecte %s specifikatie %s\n" #: commadpt.c:1321 #, c-format msgid "HHCCA015E %4.4X:Missing parameter : DIAL=%s and %s not specified\n" msgstr "" #: commadpt.c:1325 #, c-format msgid "HHCCA016W %4.4X:Conflicting parameter : DIAL=%s and %s=%s specified\n" msgstr "" #: commadpt.c:1326 #, c-format msgid "HHCCA017I %4.4X:RPORT parameter ignored\n" msgstr "" #: commadpt.c:1349 #, c-format msgid "HHCCA300D %4.4X:Initialisation starting\n" msgstr "" #: commadpt.c:1355 #, c-format msgid "HHCCA010I %4.4X:initialisation not performed\n" msgstr "" #: commadpt.c:1361 #, c-format msgid "HHCCA300D %4.4X:Initialisation : Control block allocated\n" msgstr "" #: commadpt.c:1384 #, c-format msgid "HHCCA011E %4.4X:Error parsing %s\n" msgstr "" #: commadpt.c:1390 #, c-format msgid "HHCCA012E %4.4X:Unrecognized parameter %s\n" msgstr "" #: commadpt.c:1478 #, c-format msgid "" "HHCCA014E %4.4X:Incorrect switched/dial specification %s; defaulting to " "DIAL=OUT\n" msgstr "" #: commadpt.c:1597 #, c-format msgid "HHCCA021I %4.4X:Initialisation failed due to previous errors\n" msgstr "" #: commadpt.c:1657 #, c-format msgid "HHCCA019E %4.4x : BSC comm thread did not initialise\n" msgstr "" #: commadpt.c:1699 #, c-format msgid "HHCCA300D %4.4X:Closing down\n" msgstr "" #: commadpt.c:1731 #, c-format msgid "HHCCA300D %4.4X:Closed down\n" msgstr "" #: commadpt.c:1760 #, c-format msgid "HHCCA300D %4.4X:CCW Exec - Entry code = %x\n" msgstr "" #: commadpt.c:1871 #, c-format msgid "HHCCA300D %4.4X Set Mode : %s\n" msgstr "" #: config.c:122 #, c-format msgid "HHCCF040E Cannot create CPU%4.4X thread: %s\n" msgstr "" #: config.c:293 #, fuzzy msgid "HHCCF043E Cannot obtain device block\n" msgstr "HHCLC039E Fout %2$s bij openen bestand \"%1$s\"\n" #: config.c:409 #, fuzzy, c-format msgid "HHCCF041E Device %d:%4.4X already exists\n" msgstr "HHCPN130E Ongeldig frame adres %8.8X\n" #: config.c:418 #, c-format msgid "HHCCF042E Device type %s not recognized\n" msgstr "" #: config.c:446 #, c-format msgid "HHCCF044E Initialization failed for device %4.4X\n" msgstr "" #: config.c:468 #, c-format msgid "HHCCF045E Cannot obtain buffer for device %4.4X: %s\n" msgstr "" #: config.c:600 #, c-format msgid "HHCCF046E Subchannel %d:%4.4X does not exist\n" msgstr "" #: config.c:607 #, c-format msgid "HHCCF047I Subchannel %d:%4.4X detached\n" msgstr "" #: config.c:626 #, fuzzy, c-format msgid "HHCCF046E Device %d:%4.4X does not exist\n" msgstr "HHCSD007I %s (%s) afgesloten van apparaat %4.4X (%s)\n" #: config.c:633 #, c-format msgid "HHCCF047I Device %4.4X detached\n" msgstr "" #: config.c:651 #, fuzzy, c-format msgid "HHCCF048E Device %d:%4.4X does not exist\n" msgstr "HHCSD007I %s (%s) afgesloten van apparaat %4.4X (%s)\n" #: config.c:658 #, fuzzy, c-format msgid "HHCCF049E Device %d:%4.4X already exists\n" msgstr "HHCSD007I %s (%s) afgesloten van apparaat %4.4X (%s)\n" #: config.c:934 msgid "" "HHCCF074E Unspecified error occured while parsing Logical Channel Subsystem " "Identification\n" msgstr "" #: config.c:950 msgid "" "HHCCF075E No more than 1 Logical Channel Subsystem Identification may be " "specified\n" msgstr "" #: config.c:960 #, c-format msgid "HHCCF076E Non numeric Logical Channel Subsystem Identification %s\n" msgstr "" #: config.c:969 #, c-format msgid "" "HHCCF077E Logical Channel Subsystem Identification %d exceeds maximum of %d\n" msgstr "" #: config.c:1001 config.c:1117 #, fuzzy, c-format msgid "HHCCF055E Incorrect device address specification near character %c\n" msgstr "HHCCA013E %4.4X:Incorrecte %s specifikatie %s\n" #: config.c:1099 #, c-format msgid "" "HHCCF053E Incorrect second device number in device range near character %c\n" msgstr "" #: config.c:1110 #, c-format msgid "HHCCF054E Incorrect Device count near character %c\n" msgstr "" #: config.c:1125 #, c-format msgid "HHCCF056E Incorrect device address range. %4.4X < %4.4X\n" msgstr "" #: config.c:1148 #, c-format msgid "" "HHCCF057E %4.4X is on wrong channel (1st device defined on channel %2.2X)\n" msgstr "" #: config.c:1178 #, c-format msgid "" "HHCCF058E Some or all devices in %4.4X-%4.4X duplicate devices already " "defined\n" msgstr "" #: console.c:373 #, c-format msgid "HHCGI001I Unable to determine IP address from %s\n" msgstr "" #: console.c:394 #, c-format msgid "HHCGI002I Unable to determine port number from %s\n" msgstr "" #: console.c:408 #, fuzzy, c-format msgid "HHCGI003E Invalid parameter: %s\n" msgstr "HHCGI003E Optie %s niet geldig\n" #: console.c:923 #, fuzzy, c-format msgid "HHCTE014I %4.4X device %4.4X client %s connection reset\n" msgstr "HHCPN015E Ongeldig apparaat nummer\n" #: console.c:933 #, fuzzy, c-format msgid "HHCTE007I %4.4X device %4.4X client %s connection closed\n" msgstr "HHCPN015E Ongeldig apparaat nummer\n" #: console.c:1098 #, c-format msgid "HHCTE008I Device %4.4X connection closed by client %s\n" msgstr "" #: console.c:1821 #, fuzzy, c-format msgid "HHCTE009I Client %s connected to %4.4X device %d:%4.4X\n" msgstr "HHCSD006E %s (%s) afgesloten van apparaat %4.4X (%s)\n" #: console.c:1936 #, fuzzy msgid "HHCTE001I Console connection thread started: tid=" msgstr "HHCTE001I Controle paneel thread gestart: tid=%8.8lX, pid=%d\n" #: console.c:1960 #, fuzzy, c-format msgid "HHCTE010E CNSLPORT statement invalid: %s\n" msgstr "HHCTE010E CNSLPORT statement %s niet geldig\n" #: console.c:1972 #, c-format msgid "HHCTE002W Waiting for port %u to become free\n" msgstr "" #: console.c:1991 #, c-format msgid "HHCTE003I Waiting for console connection on port %u\n" msgstr "" #: console.c:2253 #, fuzzy msgid "HHCTE004I Console connection thread terminated\n" msgstr "HHCTE004I Controle paneel thread gestart: tid=%8.8lX, pid=%d\n" #: console.c:2283 #, c-format msgid "HHCTE005E Cannot create console thread: %s\n" msgstr "" #: console.c:2305 msgid "** BUG! console_remove() error! **\n" msgstr "" #: console.c:2377 console.c:2663 #, fuzzy, c-format msgid "HHCTE011E Device %4.4X: Invalid IP address: %s\n" msgstr "HHCPN130E Ongeldig frame adres %8.8X\n" #: console.c:2388 console.c:2674 #, fuzzy, c-format msgid "HHCTE012E Device %4.4X: Invalid mask value: %s\n" msgstr "HHCCA018E %4.4X:Bind fout: %s\n" #: console.c:2397 console.c:2683 #, fuzzy, c-format msgid "HHCTE013E Device %4.4X: Extraneous argument(s): %s...\n" msgstr "HHCSD007I %s (%s) afgesloten van apparaat %4.4X (%s)\n" #: console.c:2544 #, fuzzy, c-format msgid "HHCTE090E %4.4X malloc() failed for resume buf: %s\n" msgstr "HHCCA006T %4.4X:Select fout: %s\n" #: console.c:3488 #, fuzzy, c-format msgid "HHCTE006A Enter input for console device %4.4X\n" msgstr "" "HHCRD007I standaard waarde 'ascii' aan socket apparaat %4.4X toegekend\n" #: cpu.c:326 msgid "HHCCP043I Wait state PSW loaded: " msgstr "" #: cpu.c:521 #, c-format msgid "program_int() passing to guest code=%4.4X\n" msgstr "" #: cpu.c:612 msgid "HHCCP014I " msgstr "" #: cpu.c:615 hscmisc.c:1088 msgid "SIE: " msgstr "" #: cpu.c:622 #, c-format msgid "CPU%4.4X: %s CODE=%4.4X ILC=%d%s\n" msgstr "" #: cpu.c:736 #, c-format msgid "HHCCP015I CPU%4.4X PER event: code=%4.4X perc=%2.2X addr=" msgstr "" #: cpu.c:914 #, c-format msgid "HHCCP016I CPU%4.4X: Program interrupt loop: " msgstr "" #: cpu.c:1028 #, c-format msgid "" "HHCCP044I I/O interrupt code=%4.4X CSW=%2.2X%2.2X%2.2X%2.2X %2.2X%2.2X%2.2X%" "2.2X\n" msgstr "" #: cpu.c:1050 #, c-format msgid "HHCCP045I I/O interrupt code=%8.8X parm=%8.8X\n" msgstr "" #: cpu.c:1053 #, c-format msgid "HHCCP046I I/O interrupt code=%8.8X parm=%8.8X id=%8.8X\n" msgstr "" #: cpu.c:1119 msgid "HHCCP022I Machine Check code=%16.16" msgstr "" #: cpu.c:1180 #, fuzzy, c-format msgid "HHCCP001W CPU%4.4X thread set priority %d failed: %s\n" msgstr "HHCCP002I CPU%4.4X thread al gestart\n" #: cpu.c:1187 #, fuzzy, c-format msgid "HHCCP002I CPU%4.4X thread started: tid=" msgstr "HHCCP002I CPU%4.4X thread al gestart\n" #: cpu.c:1210 #, fuzzy, c-format msgid "HHCCP006S Cannot create timer thread: %s\n" msgstr "HHCPN119E Fout %2$s bij lezen van bestand \"%1$s\"\n" #: cpu.c:1239 #, fuzzy, c-format msgid "HHCCP008I CPU%4.4X thread ended: tid=" msgstr "HHCCP008I CPU%4.4X thread geeindigd: tid=%8.8lX, pid=%d\n" #: cpu.c:1471 hsccmd.c:1340 #, c-format msgid "HHCCP010I CPU%4.4X store status completed.\n" msgstr "" #: cpu.c:1540 #, c-format msgid "" "HHCCP011I CPU%4.4X: Disabled wait state\n" " " msgstr "" #: cpu.c:1654 #, fuzzy, c-format msgid "HHCCP007I CPU%4.4X architecture mode set to %s\n" msgstr "HHCCP007I CPU%4.4X Architectuur Modus %s\n" #: cpu.c:1664 #, fuzzy, c-format msgid "HHCCP003I CPU%4.4X architecture mode %s\n" msgstr "HHCCP003I CPU%4.4X Architectuur Modus %s\n" #: cpu.c:1669 #, fuzzy, c-format msgid "HHCCP004I CPU%4.4X Vector Facility online\n" msgstr "HHCCP003I CPU%4.4X Architectuur Modus %s\n" #: cpu.c:1697 #, fuzzy, c-format msgid "HHCCP080E CPU%4.4X malloc failed for archjmp regs: %s\n" msgstr "HHCCP003I CPU%4.4X Architectuur Modus %s\n" #: cpu.c:1897 #, c-format msgid "PSW=%2.2X%2.2X%2.2X%2.2X %2.2X%2.2X%2.2X%2.2X\n" msgstr "" #: cpu.c:1904 #, c-format msgid "" "PSW=%2.2X%2.2X%2.2X%2.2X %2.2X%2.2X%2.2X%2.2X %2.2X%2.2X%2.2X%2.2X%2.2X%2.2X%" "2.2X%2.2X\n" msgstr "" #: ctc_ctci.c:155 #, c-format msgid "HHCCT037E %4.4X: Unable to allocate CTCBLK\n" msgstr "" #: ctc_ctci.c:176 #, c-format msgid "HHCCT038E %4.4X: Unable to allocate CTCBLK\n" msgstr "" #: ctc_ctci.c:233 #, fuzzy, c-format msgid "HHCCT073I %4.4X: TUN device %s opened\n" msgstr "HHCPN015E Ongeldig apparaat nummer\n" #: ctc_ctci.c:250 #, c-format msgid "HHCCT074W TT32SDEVBUFF failed for device %s: %s.\n" msgstr "" #: ctc_ctci.c:257 #, fuzzy, c-format msgid "HHCCT075W TT32SIOBUFF failed for device %s: %s.\n" msgstr "HHCSD006E %s (%s) afgesloten van apparaat %4.4X (%s)\n" #: ctc_ctci.c:683 #, c-format msgid "HHCCT040I %4.4X: Halt or Clear Recognized\n" msgstr "" #: ctc_ctci.c:732 #, c-format msgid "HHCCT041I %4.4X: CTC Received Frame (%d bytes):\n" msgstr "" #: ctc_ctci.c:770 #, fuzzy, c-format msgid "HHCCT042E %4.4X: Write CCW count %u is invalid\n" msgstr "HHCDA002E %4.4X:Bestandsnaam niet opgegeven of ongeldig\n" #: ctc_ctci.c:799 #, c-format msgid "HHCCT043I %4.4X: Interface command: %s %8.8X\n" msgstr "" #: ctc_ctci.c:826 ctcadpt.c:748 #, c-format msgid "CTC101W %4.4X: Write buffer contains invalid frame offset %u\n" msgstr "" #: ctc_ctci.c:848 #, c-format msgid "" "HHCCT044E %4.4X: Write buffer contains incomplete segment header at offset %" "4.4X\n" msgstr "" #: ctc_ctci.c:868 #, c-format msgid "" "HHCCT045E %4.4X: Write buffer contains invalid segment length %u at offset %" "4.4X\n" msgstr "" #: ctc_ctci.c:883 #, c-format msgid "HHCCT046I %4.4X: Sending packet to %s:\n" msgstr "" #: ctc_ctci.c:893 #, c-format msgid "HHCCT047E %4.4X: Error writing to %s: %s\n" msgstr "" #: ctc_ctci.c:956 #, c-format msgid "HHCCT048E %4.4X: Error reading from %s: %s\n" msgstr "" #: ctc_ctci.c:968 #, c-format msgid "HHCCT049I %4.4X: Received packet from %s (%d bytes):\n" msgstr "" #: ctc_ctci.c:980 #, c-format msgid "HHCCT072W %4.4X: Packet too big; dropped.\n" msgstr "" #: ctc_ctci.c:1124 ctc_ctci.c:1309 #, c-format msgid "HHCCT056E %4.4X: Incorrect number of parameters\n" msgstr "" #: ctc_ctci.c:1209 #, c-format msgid "HHCCT050E %4.4X: Invalid adapter address %s\n" msgstr "" #: ctc_ctci.c:1218 #, fuzzy, c-format msgid "HHCCT051E %4.4X: Invalid device name %s\n" msgstr "HHCPN015E Ongeldig apparaat nummer\n" #: ctc_ctci.c:1232 #, c-format msgid "HHCCT052E %4.4X: Invalid kernel buffer size %s\n" msgstr "" #: ctc_ctci.c:1246 #, c-format msgid "HHCCT053E %4.4X: Invalid DLL I/O buffer size %s\n" msgstr "" #: ctc_ctci.c:1260 #, c-format msgid "HHCCT054E %4.4X: Invalid MTU size %s\n" msgstr "" #: ctc_ctci.c:1271 #, c-format msgid "HHCCT055E %4.4X: Invalid netmask %s\n" msgstr "" #: ctc_ctci.c:1282 #, c-format msgid "HHCCT056E %4.4X: Invalid MAC address %s\n" msgstr "" #: ctc_ctci.c:1319 #, c-format msgid "HHCCT057E %4.4X: Incorrect number of parameters\n" msgstr "" #: ctc_ctci.c:1327 #, c-format msgid "HHCCT058E %4.4X: Invalid IP address %s\n" msgstr "" #: ctc_ctci.c:1339 #, c-format msgid "HHCCT059E %4.4X: Invalid IP address %s\n" msgstr "" #: ctc_ctci.c:1355 #, fuzzy, c-format msgid "HHCCT060E %4.4X: Incorrect number of parameters\n" msgstr "HHCCA013E %4.4X:Incorrecte %s specifikatie %s\n" #: ctc_ctci.c:1364 #, fuzzy, c-format msgid "HHCCT061E %4.4X: invalid device name %s\n" msgstr "HHCPN015E Ongeldig apparaat nummer\n" #: ctc_ctci.c:1378 #, fuzzy, c-format msgid "HHCCT062E %4.4X: Invalid MTU size %s\n" msgstr "HHCCA018E %4.4X:Bind fout: %s\n" #: ctc_ctci.c:1389 #, fuzzy, c-format msgid "HHCCT063E %4.4X: Invalid IP address %s\n" msgstr "HHCPN130E Ongeldig frame adres %8.8X\n" #: ctc_ctci.c:1401 #, fuzzy, c-format msgid "HHCCT064E %4.4X: Invalid IP address %s\n" msgstr "HHCPN130E Ongeldig frame adres %8.8X\n" #: ctc_ctci.c:1413 #, fuzzy, c-format msgid "HHCCT065E %4.4X: Invalid netmask %s\n" msgstr "HHCCA018E %4.4X:Bind fout: %s\n" #: ctc_ctci.c:1424 #, fuzzy, c-format msgid "HHCCT066E %4.4X: Incorrect number of parameters\n" msgstr "HHCCA013E %4.4X:Incorrecte %s specifikatie %s\n" #: ctc_ctci.c:1442 #, c-format msgid "HHCCT067E %4.4X: Invalid IP address %s\n" msgstr "" #: ctc_ctci.c:1457 #, c-format msgid "HHCCT068E %4.4X: Invalid MAC address %s\n" msgstr "" #: ctc_ctci.c:1489 #, c-format msgid "HHCCT069E %4.4X: Invalid kernel buffer size %s\n" msgstr "" #: ctc_ctci.c:1506 #, c-format msgid "HHCCT070E %4.4X: Invalid DLL I/O buffer size %s\n" msgstr "" #: ctc_ctci.c:1517 #, c-format msgid "HHCCT071E %4.4X: Incorrect number of parameters\n" msgstr "" #: ctc_lcs.c:122 #, c-format msgid "HHCLC001E %4.4X unable to allocate LCSBLK\n" msgstr "" #: ctc_lcs.c:269 #, fuzzy, c-format msgid "HHCLC073I %4.4X: TAP device %s opened\n" msgstr "HHCPN015E Ongeldig apparaat nummer\n" #: ctc_lcs.c:285 #, c-format msgid "HHCLC074W TT32SDEVBUFF failed for device %s: %s.\n" msgstr "" #: ctc_lcs.c:292 #, fuzzy, c-format msgid "HHCLC075W TT32SIOBUFF failed for device %s: %s.\n" msgstr "HHCSD006E %s (%s) afgesloten van apparaat %4.4X (%s)\n" #: ctc_lcs.c:765 #, c-format msgid "HHCLC002I %4.4X: Halt or Clear Recognized\n" msgstr "" #: ctc_lcs.c:808 #, c-format msgid "HHCLC003I %4.4X: LCS Read Buffer:\n" msgstr "" #: ctc_lcs.c:871 #, c-format msgid "HHCLCxxxI %4.4X: Startup\n" msgstr "" #: ctc_lcs.c:876 #, c-format msgid "HHCLCxxxI %4.4X: Shutdown\n" msgstr "" #: ctc_lcs.c:882 #, c-format msgid "HHCLCxxxI %4.4X: Start LAN\n" msgstr "" #: ctc_lcs.c:887 #, c-format msgid "HHCLCxxxI %4.4X: Stop LAN\n" msgstr "" #: ctc_lcs.c:893 #, c-format msgid "HHCLCxxxI %4.4X: Query\n" msgstr "" #: ctc_lcs.c:899 #, c-format msgid "HHCLCxxxI %4.4X: Stat\n" msgstr "" #: ctc_lcs.c:929 #, c-format msgid "HHCLC004I %4.4X: Sending packet to %s:\n" msgstr "" #: ctc_lcs.c:938 #, c-format msgid "HHCLC005E %4.4X: Error writing to %s: %s\n" msgstr "" #: ctc_lcs.c:957 #, c-format msgid "HHCLC006I %4.4X Triggering Event.\n" msgstr "" #: ctc_lcs.c:1343 #, c-format msgid "HHCLC007E Error in call to socket: %s.\n" msgstr "" #: ctc_lcs.c:1356 #, c-format msgid "HHCLC008E ioctl error on device %s: %s.\n" msgstr "" #: ctc_lcs.c:1453 #, fuzzy, c-format msgid "HHCLC042E Port %2.2X: Read error: %s\n" msgstr "HHCDL072E Fout %2$s bij lezan van bestand \"%1$s\"\n" #: ctc_lcs.c:1462 #, c-format msgid "HHCLC009I Port %2.2X: Read Buffer:\n" msgstr "" #: ctc_lcs.c:1491 #, c-format msgid "HHCLC010I Port %2.2X: IPV4 frame for %8.8X\n" msgstr "" #: ctc_lcs.c:1518 #, c-format msgid "HHCLC011I Port %2.2X: ARP frame for %8.8X\n" msgstr "" #: ctc_lcs.c:1547 #, c-format msgid "" "HHCLC011I Port %2.2X: RARP frame for %2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X\n" msgstr "" #: ctc_lcs.c:1579 #, c-format msgid "HHCLC012I Port %2.2X: SNA frame\n" msgstr "" #: ctc_lcs.c:1609 #, c-format msgid "HHCLC013I Port %2.2X: No match found - selecting primary %4.4X\n" msgstr "" #: ctc_lcs.c:1619 #, c-format msgid "HHCLC014I Port %2.2X: No match found - selecting secondary %4.4X\n" msgstr "" #: ctc_lcs.c:1630 #, c-format msgid "HHCLC015I Port %2.2X: No match found - Discarding frame\n" msgstr "" #: ctc_lcs.c:1638 #, c-format msgid "HHCLC016I Port %2.2X: Enqueing frame to device %4.4X (%8.8X)\n" msgstr "" #: ctc_lcs.c:1652 #, c-format msgid "HHCLC041W Port %2.2X: Frame too big; discarded.\n" msgstr "" #: ctc_lcs.c:1900 #, c-format msgid "HHCLC017E %4.4X invalid device name %s\n" msgstr "" #: ctc_lcs.c:1916 #, fuzzy, c-format msgid "HHCLC052E %4.4X: Invalid kernel buffer size %s\n" msgstr "HHCCA018E %4.4X:Bind fout: %s\n" #: ctc_lcs.c:1930 #, fuzzy, c-format msgid "HHCLC053E %4.4X: Invalid DLL I/O buffer size %s\n" msgstr "HHCCA018E %4.4X:Bind fout: %s\n" #: ctc_lcs.c:1946 #, c-format msgid "HHCLC018E %4.4X invalid MAC address %s\n" msgstr "" #: ctc_lcs.c:1970 #, c-format msgid "HHCLC019E %4.4X too many arguments in statement.\n" msgstr "" #: ctc_lcs.c:1980 #, c-format msgid "HHCLC020E %4.4X invalid IP address %s\n" msgstr "" #: ctc_lcs.c:2035 #, fuzzy, c-format msgid "HHCLC039E Cannot open file %s: %s\n" msgstr "HHCLC039E Fout %2$s bij openen bestand \"%1$s\"\n" #: ctc_lcs.c:2087 #, c-format msgid "HHCLC021E Invalid HWADD statement in %s: %s\n" msgstr "" #: ctc_lcs.c:2096 #, c-format msgid "" "HHCLC022E Invalid MAC in HWADD statement in %s: %s (%s)\n" " " msgstr "" #: ctc_lcs.c:2113 #, c-format msgid "HHCLC023E Invalid ROUTE statement in %s: %s\n" msgstr "" #: ctc_lcs.c:2120 #, c-format msgid "HHCLC024E Invalid net address in ROUTE %s: %s (%s)\n" msgstr "" #: ctc_lcs.c:2130 #, c-format msgid "HHCLC025E Invalid net mask in ROUTE %s: %s (%s)\n" msgstr "" #: ctc_lcs.c:2162 #, c-format msgid "HHCLC026E Error in %s: Missing device number or mode\n" msgstr "" #: ctc_lcs.c:2171 #, c-format msgid "HHCLC027E Error in %s: %s: Invalid device number\n" msgstr "" #: ctc_lcs.c:2183 #, c-format msgid "HHCLC028E Error in %s: %s:Missing PORT number\n" msgstr "" #: ctc_lcs.c:2191 #, c-format msgid "HHCLC029E Error in %s: %s: Invalid PORT number\n" msgstr "" #: ctc_lcs.c:2207 #, c-format msgid "HHCLC031E Error in %s: %s: Invalid entry starting at %s\n" msgstr "" #: ctc_lcs.c:2219 #, c-format msgid "HHCLC032E Error is %s: %s: Invalid IP address (%s)\n" msgstr "" #: ctc_lcs.c:2235 #, c-format msgid "HHCLC033E Error in %s: %s: Missing PORT number\n" msgstr "" #: ctc_lcs.c:2243 #, c-format msgid "HHCLC034E Error in %s: %s:Invalid PORT number\n" msgstr "" #: ctc_lcs.c:2251 #, c-format msgid "HHCLC035E Error in %s: %s: SNA does not accept any arguments\n" msgstr "" #: ctc_lcs.c:2259 #, c-format msgid "HHCLC036E Error in %s: %s: Invalid MODE\n" msgstr "" #: ctc_lcs.c:2324 #, c-format msgid "HHCLC037E Error reading file %s line %d: %s\n" msgstr "" #: ctc_lcs.c:2348 #, c-format msgid "HHCLC038E File %s line %d is too long\n" msgstr "" #: ctcadpt.c:167 #, c-format msgid "HHCCT001E %4.4X: Incorrect number of parameters\n" msgstr "" #: ctcadpt.c:180 #, c-format msgid "HHCCT034E %s: Unrecognized/unsupported CTC emulation type\n" msgstr "" #: ctcadpt.c:488 #, c-format msgid "HHCCT002E %4.4X: Incorrect number of parameters\n" msgstr "" #: ctcadpt.c:500 #, c-format msgid "HHCCT003E %4.4X: Invalid port number: %s\n" msgstr "" #: ctcadpt.c:521 #, c-format msgid "HHCCT004E %4.4X: Invalid IP address %s\n" msgstr "" #: ctcadpt.c:534 #, c-format msgid "HHCCT005E %4.4X: Invalid port number: %s\n" msgstr "" #: ctcadpt.c:546 #, c-format msgid "HHCCT006E %4.4X: Invalid MTU size %s\n" msgstr "" #: ctcadpt.c:567 #, c-format msgid "HHCCT007E %4.4X: Error creating socket: %s\n" msgstr "" #: ctcadpt.c:587 #, c-format msgid "HHCCT008E %4.4X: Error binding to socket: %s\n" msgstr "" #: ctcadpt.c:608 #, c-format msgid "HHCCT009I %4.4X: Connect to %s:%s failed, starting server\n" msgstr "" #: ctcadpt.c:618 #, c-format msgid "HHCCT010E %4.4X: Error creating socket: %s\n" msgstr "" #: ctcadpt.c:635 #, c-format msgid "HHCCT011E %4.4X: Error binding to socket: %s\n" msgstr "" #: ctcadpt.c:643 #, c-format msgid "HHCCT012E %4.4X: Error on call to listen: %s\n" msgstr "" #: ctcadpt.c:659 #, c-format msgid "HHCCT013I %4.4X: Connected to %s:%s\n" msgstr "" #: ctcadpt.c:693 #, fuzzy, c-format msgid "HHCCT014E %4.4X: Write CCW count %u is invalid\n" msgstr "HHCDA002E %4.4X:Bestandsnaam niet opgegeven of ongeldig\n" #: ctcadpt.c:723 #, c-format msgid "HHCCT015I %4.4X: Interface command: %s %8.8X\n" msgstr "" #: ctcadpt.c:769 #, c-format msgid "" "HHCCT016E %4.4X: Write buffer contains incomplete segment header at offset %" "4.4X\n" msgstr "" #: ctcadpt.c:789 #, c-format msgid "" "HHCCT017E %4.4X: Write buffer contains invalid segment length %u at offset %" "4.4X\n" msgstr "" #: ctcadpt.c:804 #, c-format msgid "HHCCT018I %4.4X: Sending packet to %s:\n" msgstr "" #: ctcadpt.c:815 #, c-format msgid "HHCCT019E %4.4X: Error writing to %s: %s\n" msgstr "" #: ctcadpt.c:878 #, c-format msgid "HHCCT020E %4.4X: Error reading from %s: %s\n" msgstr "" #: ctcadpt.c:895 #, c-format msgid "HHCCT021E %4.4X: Error reading from %s: %s\n" msgstr "" #: ctcadpt.c:905 #, c-format msgid "HHCCT022I %4.4X: Received packet from %s (%d bytes):\n" msgstr "" #: ctcadpt.c:987 #, c-format msgid "" "HHCCT023E %4.4X: Incorrect client or config error\n" " Config=%s, connecting client=%s\n" msgstr "" #: ctcadpt.c:1031 #, c-format msgid "HHCCT024E %4.4X: Not enough arguments to start vmnet\n" msgstr "" #: ctcadpt.c:1041 #, c-format msgid "HHCCT025E %4.4X: Failed: socketpair: %s\n" msgstr "" #: ctcadpt.c:1049 #, c-format msgid "HHCCT026E %4.4X: Failed: fork: %s\n" msgstr "" #: ctcadpt.c:1100 #, c-format msgid "HHCCT027E %4.4X: Not enough parameters\n" msgstr "" #: ctcadpt.c:1106 #, fuzzy, c-format msgid "HHCCT028E %d:%4.4X: Bad device number '%s'\n" msgstr "HHCPN015E Ongeldig apparaat nummer\n" #: ctcadpt.c:1143 #, c-format msgid "HHCCT029E %4.4X: bad block length: %d < %d\n" msgstr "" #: ctcadpt.c:1153 #, c-format msgid "HHCCT030E %4.4X: bad packet length: %d < %d\n" msgstr "" #: ctcadpt.c:1158 #, c-format msgid "HHCCT031E %4.4X: bad packet length: %d < 6\n" msgstr "" #: ctcadpt.c:1204 #, c-format msgid "HHCCT032E %4.4X: Error: EOF on read, CTC network down\n" msgstr "" #: ctcadpt.c:1212 #, c-format msgid "HHCCT033E %4.4X: Error: read: %s\n" msgstr "" #: dasdcat.c:43 #, c-format msgid "HHCDT002E Can't make 80 column card images from block length %d\n" msgstr "" #: dasdcat.c:119 #, c-format msgid "HHCDT003E Directory block byte count is invalid\n" msgstr "" #: dasdcat.c:221 #, c-format msgid "HHCDT004E non-PDS-members not yet supported\n" msgstr "" #: dasdcat.c:253 #, c-format msgid "HHCDT005E unknown dataset name option: '%c'\n" msgstr "" #: dasdcat.c:350 #, c-format msgid "HHCDT001E failed to open image %s\n" msgstr "" #: dasdcopy.c:119 #, c-format msgid "Hercules %s copy program " msgstr "" #: dasdcopy.c:204 #, fuzzy, c-format msgid "HHCDC001E %s: %s open error: %s\n" msgstr "HHCDC001E %1$s:Fout %3$s bij openen bestand \"%2$s\"\n" #: dasdcopy.c:211 #, fuzzy, c-format msgid "HHCDC002E %s: %s read error: %s\n" msgstr "HHCDC002E %$1s:Leesfout %3$s op bestand \"%2$s\"\n" #: dasdcopy.c:274 #, fuzzy, c-format msgid "HHCDC003E %s: %s open failed\n" msgstr "HHCDC003E Fout %2$s bij openen van bestand \"%1$s\"\n" #: dasdcopy.c:288 #, c-format msgid "HHCDC004E %s: ckd lookup failed for %4.4X cyls %d\n" msgstr "" #: dasdcopy.c:308 #, c-format msgid "HHCDC005E %s: fba lookup failed, blks %d\n" msgstr "" #: dasdcopy.c:329 #, c-format msgid "HHCDC006E %s: %s create failed\n" msgstr "" #: dasdcopy.c:341 #, fuzzy, c-format msgid "HHCDC007E %s: %s open failed\n" msgstr "HHCDC007E %$1s: Fout %3$s bij openen van bestand \"%2$s\"\n" #: dasdcopy.c:378 #, fuzzy, c-format msgid "HHCDC008E %s: %s read error %s %d stat=%2.2X, null %s substituted\n" msgstr "HHCDC002E %$1s:Leesfout %3$s op bestand \"%2$s\"\n" #: dasdcopy.c:388 #, c-format msgid " %3d%% %7d of %d" msgstr "" #: dasdcopy.c:417 #, c-format msgid "HHCDC009E %s: %s write error %s %d stat=%2.2X\n" msgstr "" #: dasdcopy.c:429 #, fuzzy, c-format msgid "HHCDC010I %s successfully completed.\n" msgstr "" "\n" "HHCDC010I Kopie Suksesvol !!! \n" #: dasdcopy.c:517 #, c-format msgid "" "usage: ckd2cckd [-options] ifile ofile\n" "\n" " copy a ckd dasd file to a compressed ckd dasd file\n" "\n" " ifile -- input ckd dasd file\n" " ofile -- output compressed ckd dasd file\n" "\n" " options:\n" " -v display program version and quit\n" " -h display this help and quit\n" " -q quiet mode, don't display status\n" " -r replace the output file if it exists\n" "%s%s -0 don't compress track images\n" " -cyls n size of output file\n" " -a output file will have alt cyls\n" msgstr "" #: dasdcopy.c:537 dasdcopy.c:593 dasdcopy.c:655 msgid " -z compress using zlib [default]\n" msgstr "" #: dasdcopy.c:544 dasdcopy.c:600 msgid " -bz2 compress using bzip2\n" msgstr "" #: dasdcopy.c:552 #, c-format msgid "" "usage: cckd2ckd [-options] ifile [sf=sfile] ofile\n" "\n" " copy a compressed ckd file to a ckd file\n" "\n" " ifile -- input compressed ckd dasd file\n" " sfile -- input compressed ckd shadow file\n" " (optional)\n" " ofile -- output ckd dasd file\n" "\n" " options:\n" " -v display program version and quit\n" " -h display this help and quit\n" " -q quiet mode, don't display status\n" " -r replace the output file if it exists\n" "%s -cyls n size of output file\n" " -a output file will have alt cyls\n" msgstr "" #: dasdcopy.c:570 dasdcopy.c:625 msgid " -lfs create single large output file\n" msgstr "" #: dasdcopy.c:574 #, c-format msgid "" "usage: fba2cfba [-options] ifile ofile\n" "\n" " copy a fba dasd file to a compressed fba dasd file\n" "\n" " ifile -- input fba dasd file\n" " ofile -- output compressed fba dasd file\n" "\n" " options:\n" " -v display program version and quit\n" " -h display this help and quit\n" " -q quiet mode, don't display status\n" " -r replace the output file if it exists\n" "%s%s -0 don't compress track images\n" " -blks n size of output file\n" msgstr "" #: dasdcopy.c:608 #, c-format msgid "" "usage: cfba2fba [-options] ifile [sf=sfile] ofile\n" "\n" " copy a compressed fba file to a fba file\n" "\n" " ifile -- input compressed fba dasd file\n" " sfile -- input compressed fba shadow file\n" " (optional)\n" " ofile -- output fba dasd file\n" "\n" " options:\n" " -v display program version and quit\n" " -h display this help and quit\n" " -q quiet mode, don't display status\n" " -r replace the output file if it exists\n" "%s -blks n size of output file\n" msgstr "" #: dasdcopy.c:629 #, c-format msgid "" "usage: %s [-options] ifile [sf=sfile] ofile\n" "\n" " copy a dasd file to another dasd file\n" "\n" " ifile -- input dasd file\n" " sfile -- input shadow file [optional]\n" " ofile -- output dasd file\n" "\n" " options:\n" " -v display program version and quit\n" " -h display this help and quit\n" " -q quiet mode, don't display status\n" " -r replace the output file if it exists\n" "%s%s -0 don't compress output\n" " -blks n size of output fba file\n" " -cyls n size of output ckd file\n" " -a output ckd file will have alt cyls\n" "%s even if it exceeds 2G in size\n" " -o type output file type (CKD, CCKD, FBA, CFBA)\n" msgstr "" #: dasdcopy.c:662 msgid " -bz2 compress output using bzip2\n" msgstr "" #: dasdcopy.c:667 msgid " -lfs output ckd file will be a single file\n" msgstr "" #: dasdinit.c:297 #, c-format msgid "HHCDI001I DASD initialization successfully completed.\n" msgstr "" #: dasdisup.c:252 #, c-format msgid "HHCDS003E Directory block byte count is invalid\n" msgstr "" #: dasdisup.c:297 #, c-format msgid "HHCDS018I %s %s skipped\n" msgstr "" #: dasdisup.c:310 #, c-format msgid "HHCDS004E Number of members exceeds MAX_MEMBERS\n" msgstr "" #: dasdisup.c:319 #, c-format msgid "HHCDS005E Member %s TTR count is zero\n" msgstr "" #: dasdisup.c:348 #, c-format msgid "HHCDS006W Member %s is not single text record\n" msgstr "" #: dasdisup.c:357 #, c-format msgid "HHCDS007W Member %s size %4.4X exceeds X'7F8' bytes\n" msgstr "" #: dasdisup.c:366 #, c-format msgid "HHCDS008W Member %s size %4.4X is not a multiple of 8\n" msgstr "" #: dasdisup.c:420 #, c-format msgid "HHCDS009I Alias %s skipped\n" msgstr "" #: dasdisup.c:427 #, c-format msgid "HHCDS010I Member %s skipped\n" msgstr "" #: dasdisup.c:435 #, c-format msgid "HHCDS011E Member %s has multiple text records\n" msgstr "" #: dasdisup.c:447 #, c-format msgid "HHCDS012E Member %s has invalid TTR %4.4X%2.2X\n" msgstr "" #: dasdisup.c:453 #, c-format msgid "" "HHCDS013I Processing member %s text record TTR=%4.4X%2.2X CCHHR=%4.4X%4.4X%" "2.2X\n" msgstr "" #: dasdisup.c:463 #, c-format msgid "HHCDS014E Member %s error reading TTR %4.4X%2.2X\n" msgstr "" #: dasdisup.c:472 #, c-format msgid "" "HHCDS015E Member %s TTR %4.4X%2.2X text record length %4.4X is not valid\n" msgstr "" #: dasdisup.c:482 #, c-format msgid "" "HHCDS016E Member %s TTR %4.4X%2.2X text record length %4.4X does not match " "length %4.4X in directory\n" msgstr "" #: dasdisup.c:527 #, c-format msgid "HHCDS017E Member %s TTR %4.4X%2.2X XCTL table improperly terminated\n" msgstr "" #: dasdisup.c:549 #, c-format msgid "HHCDS019I In member %s: %s TTRL=%2.2X%2.2X%2.2X%2.2X" msgstr "" #: dasdisup.c:667 #, c-format msgid "HHCDS001E Cannot obtain storage for member array: %s\n" msgstr "" #: dasdisup.c:719 #, c-format msgid "HHCDS002I End of directory: %d members selected\n" msgstr "" #: dasdutil.c:221 #, c-format msgid "HHCDU001I Updating cyl %d head %d\n" msgstr "" #: dasdutil.c:227 #, c-format msgid "HHCDU002E %s write track error: stat=%2.2X\n" msgstr "" #: dasdutil.c:234 #, c-format msgid "HHCDU003I Reading cyl %d head %d\n" msgstr "" #: dasdutil.c:240 #, c-format msgid "HHCDU004E %s read track error: stat=%2.2X\n" msgstr "" #: dasdutil.c:361 #, c-format msgid "HHCDU005I Searching extent %d begin (%d,%d) end (%d,%d)\n" msgstr "" #: dasdutil.c:433 #, c-format msgid "HHCDU006I Searching extent %d begin (%d,%d) end (%d,%d)\n" msgstr "" #: dasdutil.c:494 #, c-format msgid "HHCDU007E Track %d not found in extent table\n" msgstr "" #: dasdutil.c:535 #, c-format msgid "HHCDU008E Cannot obtain storage for device descriptor buffer: %s\n" msgstr "" #: dasdutil.c:596 #, c-format msgid "HHCDU009E Cannot open %s: %s\n" msgstr "" #: dasdutil.c:611 #, fuzzy, c-format msgid "HHCDU010E %s read error: %s\n" msgstr "HHCDU010E Fout %2$s bij lezen van bestand \"%1$s\"\n" #: dasdutil.c:622 #, c-format msgid "HHCDU011E %s CKD header invalid\n" msgstr "" #: dasdutil.c:631 #, c-format msgid "HHCDU012E DASD table entry not found for devtype 0x%2.2X\n" msgstr "" #: dasdutil.c:661 #, c-format msgid "HHCDU013E CKD initialization failed for %s\n" msgstr "" #: dasdutil.c:683 #, c-format msgid "HHCDU014I %s heads=%d trklen=%d\n" msgstr "" #: dasdutil.c:717 #, c-format msgid "HHCDU015I Updating cyl %d head %d\n" msgstr "" #: dasdutil.c:723 #, c-format msgid "HHCDU016E %s write track error: stat=%2.2X\n" msgstr "" #: dasdutil.c:768 #, c-format msgid "HHCDU017E Cannot obtain storage for device descriptor buffer: %s\n" msgstr "" #: dasdutil.c:784 #, c-format msgid "HHCDU018E DASD table entry not found for devtype 0x%2.2X\n" msgstr "" #: dasdutil.c:811 #, c-format msgid "HHCDU019E FBA initialization failed for %s\n" msgstr "" #: dasdutil.c:827 #, c-format msgid "HHCDU020I %s sectors=%d size=%d\n" msgstr "" #: dasdutil.c:873 #, c-format msgid "HHCDU021E VOL1 record not found\n" msgstr "" #: dasdutil.c:886 #, c-format msgid "HHCDU022I VOLSER=%s VTOC=%4.4X%4.4X%2.2X\n" msgstr "" #: dasdutil.c:896 #, c-format msgid "HHCDU023E F4DSCB record not found\n" msgstr "" #: dasdutil.c:903 #, c-format msgid "HHCDU023I VTOC start %2.2X%2.2X%2.2X%2.2X end %2.2X%2.2X%2.2X%2.2X\n" msgstr "" #: dasdutil.c:919 #, c-format msgid "HHCDU024E Dataset %s not found in VTOC\n" msgstr "" #: dasdutil.c:927 #, c-format msgid "HHCDU025I DSNAME=%s F1DSCB CCHHR=%4.4X%4.4X%2.2X\n" msgstr "" #: dasdutil.c:937 #, c-format msgid "HHCDU026E F1DSCB record not found\n" msgstr "" #: dasdutil.c:959 #, c-format msgid "HHCDU027E F3DSCB record not found\n" msgstr "" #: dasdutil.c:1180 #, fuzzy, c-format msgid "HHCDU028E device type %4.4X not found in dasd table\n" msgstr "HHCSD007I %s (%s) afgesloten van apparaat %4.4X (%s)\n" #: dasdutil.c:1217 #, fuzzy, c-format msgid "HHCDU028E %s open error: %s\n" msgstr "HHCDU028E Fout %2$s bij openen bestand \"%1$s\"\n" #: dasdutil.c:1245 #, c-format msgid "HHCDU029E %s device header write error: %s\n" msgstr "" #: dasdutil.c:1274 #, c-format msgid "HHCDU030E %s compressed device header write error: %s\n" msgstr "" #: dasdutil.c:1284 #, c-format msgid "HHCDU031E Cannot obtain l1tab buffer: %s\n" msgstr "" #: dasdutil.c:1294 #, c-format msgid "HHCDU032E %s primary lookup table write error: %s\n" msgstr "" #: dasdutil.c:1307 #, c-format msgid "HHCDU033E %s secondary lookup table write error: %s\n" msgstr "" #: dasdutil.c:1597 #, c-format msgid "HHCDU035E %s cylinder %u head %u write error: %s\n" msgstr "" #: dasdutil.c:1629 #, c-format msgid "HHCDU036E %s compressed device header lseek error: %s\n" msgstr "" #: dasdutil.c:1637 #, c-format msgid "HHCDU037E %s compressed device header write error: %s\n" msgstr "" #: dasdutil.c:1647 #, c-format msgid "HHCDU038E %s secondary lookup table lseek error: %s\n" msgstr "" #: dasdutil.c:1655 #, c-format msgid "HHCDU039E %s secondary lookup table write error: %s\n" msgstr "" #: dasdutil.c:1670 #, fuzzy, c-format msgid "HHCDU040E %s close error: %s\n" msgstr "HHCDU040E Fout %2$s bij sluiten van bestand \"%1$s\"\n" #: dasdutil.c:1677 #, c-format msgid "HHCDU041I %u cylinders successfully written to file %s\n" msgstr "" #: dasdutil.c:1749 #, c-format msgid "HHCDU042E Cylinder count %u is outside range %u-%u\n" msgstr "" #: dasdutil.c:1758 #, c-format msgid "HHCDU043E Cannot obtain track buffer: %s\n" msgstr "" #: dasdutil.c:1765 #, c-format msgid "" "HHCDU044I Creating %4.4X volume %s: %u cyls, %u trks/cyl, %u bytes/track\n" msgstr "" #: dasdutil.c:1874 #, c-format msgid "HHCDU045E Sector count %u is outside range %u-%u\n" msgstr "" #: dasdutil.c:1883 #, c-format msgid "HHCDU046E Cannot obtain sector buffer: %s\n" msgstr "" #: dasdutil.c:1890 #, c-format msgid "HHCDU047I Creating %4.4X volume %s: %u sectors, %u bytes/sector\n" msgstr "" #: dasdutil.c:1903 #, c-format msgid "HHCDU048I %s open error: %s\n" msgstr "" #: dasdutil.c:1915 #, c-format msgid "HHCDU049E %s dasdcopy ftruncate error: %s\n" msgstr "" #: dasdutil.c:1950 #, c-format msgid "HHCDU050E %s sector %u write error: %s\n" msgstr "" #: dasdutil.c:1962 #, fuzzy, c-format msgid "HHCDU051E %s close error: %s\n" msgstr "HHCDU051E Fout %2$s bij sluiten van bestand \"%1$s\"\n" #: dasdutil.c:1972 #, c-format msgid "HHCDU052I %u sectors successfully written to file %s\n" msgstr "" #: dasdutil.c:2019 #, fuzzy msgid "HHCDU053E File size too large: %" msgstr "HHCDA058E Fout %2$s bij openen bestand \"%1$s\"\n" #: dasdutil.c:2033 #, fuzzy, c-format msgid "HHCDU054E %s open error: %s\n" msgstr "HHCDU054E Fout %2$s bij openen bestand \"%1$s\"\n" #: dasdutil.c:2040 #, c-format msgid "" "HHCDU055I Creating %4.4X compressed volume %s: %u sectors, %u bytes/sector\n" msgstr "" #: dasdutil.c:2050 #, c-format msgid "HHCDU056E %s devhdr write error: %s\n" msgstr "" #: dasdutil.c:2073 #, c-format msgid "HHCDU057E %s cdevhdr write error: %s\n" msgstr "" #: dasdutil.c:2085 #, c-format msgid "HHCDU058E %s l1tab write error: %s\n" msgstr "" #: dasdutil.c:2097 #, c-format msgid "HHCDU059E %s l2tab write error: %s\n" msgstr "" #: dasdutil.c:2119 #, c-format msgid "HHCDU060E %s block header write error: %s\n" msgstr "" #: dasdutil.c:2126 #, c-format msgid "HHCDU061E %s block write error: %s\n" msgstr "" #: dasdutil.c:2141 #, c-format msgid "HHCDU062E %s block write error: %s\n" msgstr "" #: dasdutil.c:2155 #, c-format msgid "HHCDU063E %s cdevhdr lseek error: %s\n" msgstr "" #: dasdutil.c:2162 #, c-format msgid "HHCDU064E %s cdevhdr rewrite error: %s\n" msgstr "" #: dasdutil.c:2171 #, c-format msgid "HHCDU065E %s l2tab lseek error: %s\n" msgstr "" #: dasdutil.c:2178 #, c-format msgid "HHCDU066E %s l2tab rewrite error: %s\n" msgstr "" #: dasdutil.c:2187 #, c-format msgid "HHCDU067E %s close error: %s\n" msgstr "" #: dasdutil.c:2194 #, c-format msgid "HHCDU068I %u sectors successfully written to file %s\n" msgstr "" #: dyngui.c:270 #, c-format msgid "HHCDG003S select failed on input stream: %s\n" msgstr "" #: dyngui.c:308 #, c-format msgid "HHCDG004S read failed on input stream: %s\n" msgstr "" #: dyngui.c:1655 dyngui.c:1758 #, c-format msgid "HHCDG005E Device query buffer overflow! (device=%4.4X)\n" msgstr "" #: dyngui.c:1908 #, c-format msgid "HHCDG006S malloc pszInputBuff failed: %s\n" msgstr "" #: dyngui.c:1921 #, c-format msgid "HHCDG007S malloc pszCommandBuff failed: %s\n" msgstr "" #: dyngui.c:1956 msgid "HHCDG001I dyngui.dll initiated\n" msgstr "" #: dyngui.c:1959 msgid "HHCDG002I dyngui.dll terminated\n" msgstr "" #: ecpsvm.c:259 ecpsvm.c:264 ecpsvm.c:281 ecpsvm.c:303 ecpsvm.c:304 #: ecpsvm.c:305 ecpsvm.c:306 msgid "HHCEV300D : SASSIST " msgstr "" #: ecpsvm.c:271 msgid "HHCEV300D : EVMA Disabled by guest\n" msgstr "" #: ecpsvm.c:324 ecpsvm.c:330 msgid "HHCEV300D : CPASSTS " msgstr "" #: ecpsvm.c:338 msgid "HHCEV300D : " msgstr "" #: ecpsvm.c:407 msgid "HHCEV300D : LKPG coreptr = " msgstr "" #: ecpsvm.c:410 #, c-format msgid "HHCEV300D : LKPG corete = %6.6X\n" msgstr "" #: ecpsvm.c:424 #, c-format msgid "HHCEV300D : LKPG Page locked. Count = %6.6X\n" msgstr "" #: ecpsvm.c:441 #, c-format msgid "HHCEV300D : LKPG PAGE=%6.6X, PTRPL=%6.6X\n" msgstr "" #: ecpsvm.c:468 #, c-format msgid "HHCEV300D : ULKPG PAGE=%6.6X, PTRPL=%6.6X\n" msgstr "" #: ecpsvm.c:474 #, c-format msgid "HHCEV300D : ULKPG Page beyond core size of %6.6X\n" msgstr "" #: ecpsvm.c:486 msgid "HHCEV300D : ULKPG Attempting to unlock page that is not locked\n" msgstr "" #: ecpsvm.c:493 msgid "HHCEV300D : ULKPG now unlocked\n" msgstr "" #: ecpsvm.c:497 #, c-format msgid "HHCEV300D : ULKPG Page still locked. Count = %6.6X\n" msgstr "" #: ecpsvm.c:533 #, c-format msgid "HHCEV300D SCNVU Virtual Device %4.4X has no VCHAN block\n" msgstr "" #: ecpsvm.c:541 #, c-format msgid "HHCEV300D SCNVU Virtual Device %4.4X has no VCU block\n" msgstr "" #: ecpsvm.c:549 #, c-format msgid "HHCEV300D SCNVU Virtual Device %4.4X has no VDEV block\n" msgstr "" #: ecpsvm.c:553 #, c-format msgid "HHCEV300D SCNVU %4.4X : VCH = %8.8X, VCU = %8.8X, VDEV = %8.8X\n" msgstr "" #: ecpsvm.c:909 msgid "HHCEV004W : Abend condition detected in DISP2 instr\n" msgstr "" #: ecpsvm.c:1100 #, c-format msgid "HHCPEV300D : DISP2 - Next Instruction : %2.2X\n" msgstr "" #: ecpsvm.c:1163 #, c-format msgid "HHCEV300D : Tranbring : LRA cc = %d\n" msgstr "" #: ecpsvm.c:1172 #, c-format msgid "HHCEV300D : Page not shared - OK %d\n" msgstr "" #: ecpsvm.c:1178 msgid "HHCEV300D : Checking 2K Storage keys @" msgstr "" #: ecpsvm.c:1183 msgid "HHCEV300D : Checking 4K Storage keys @" msgstr "" #: ecpsvm.c:1187 msgid "HHCEV300D : Page shared and changed\n" msgstr "" #: ecpsvm.c:1190 msgid "HHCEV300D : Page shared but not changed\n" msgstr "" #: ecpsvm.c:1209 msgid "HHCEV300D : TRANBRNG\n" msgstr "" #: ecpsvm.c:1213 msgid "HHCEV300D : TRANBRNG - Back to CP\n" msgstr "" #: ecpsvm.c:1231 msgid "HHCEV300D : TRANLOCK\n" msgstr "" #: ecpsvm.c:1235 msgid "HHCEV300D : TRANLOCK - Back to CP\n" msgstr "" #: ecpsvm.c:1748 #, c-format msgid "HHCEV300D : ECPS:VM SCNRU called; RDEV=%4.4X ARIOCT=%6.6X\n" msgstr "" #: ecpsvm.c:1756 #, c-format msgid "HHCEV300D : ECPS:VM SCNRU : RCH IX = %x\n" msgstr "" #: ecpsvm.c:1798 #, c-format msgid "HHCEV300D : ECPS:VM SCNRU : RCU IX = %x\n" msgstr "" #: ecpsvm.c:1818 #, c-format msgid "HHCEV300D : ECPS:VM SCNRU : RDV IX = %x\n" msgstr "" #: ecpsvm.c:1822 #, c-format msgid "HHCEV300D : ECPS:VM SCNRU : RCH = %6.6X, RCU = %6.6X, RDV = %6.6X\n" msgstr "" #: ecpsvm.c:1866 #, c-format msgid "HHCEV300D : ECPS:VM STORE LEVEL %d called\n" msgstr "" #: ecpsvm.c:1906 #, c-format msgid "HHCEV300D : ECPS:VM FREEX DW = %4.4X\n" msgstr "" #: ecpsvm.c:1911 #, c-format msgid "HHCEV300D : MAXSIZE ADDR = %6.6X, SUBPOOL INDEX TABLE = %6.6X\n" msgstr "" #: ecpsvm.c:1918 msgid "HHCEV300D : FREEX request beyond subpool capacity\n" msgstr "" #: ecpsvm.c:1923 #, c-format msgid "HHCEV300D : Subpool index = %X\n" msgstr "" #: ecpsvm.c:1926 #, c-format msgid "HHCEV300D : Value in subpool table = %6.6X\n" msgstr "" #: ecpsvm.c:1934 #, c-format msgid "HHCEV300D : New Value in subpool table = %6.6X\n" msgstr "" #: ecpsvm.c:1964 #, c-format msgid "HHCEV300D : X fretx called AREA=%6.6X, DW=%4.4X\n" msgstr "" #: ecpsvm.c:1967 msgid "HHCEV300D : ECPS:VM Cannot FRETX : DWORDS = 0\n" msgstr "" #: ecpsvm.c:1973 #, c-format msgid "HHCEV300D : ECPS:VM Cannot FRETX : DWORDS = %d > MAXDW %d\n" msgstr "" #: ecpsvm.c:1980 msgid "HHCEV300D : ECPS:VM Cannot FRETX : Area not in Core Free area\n" msgstr "" #: ecpsvm.c:1985 msgid "HHCEV300D : ECPS:VM Cannot FRETX : Area flag != 0x02\n" msgstr "" #: ecpsvm.c:1992 msgid "" "HHCEV300D : ECPS:VM Cannot FRETX : fretted block already on subpool chain\n" msgstr "" #: ecpsvm.c:2062 msgid "HHCEV300D : New and Old PSW have a EC/BC transition\n" msgstr "" #: ecpsvm.c:2070 msgid "HHCEV300D : New PSW Enables DAT or PER\n" msgstr "" #: ecpsvm.c:2081 msgid "HHCEV300D : New PSW Enables interrupts and MICPEND (EC)\n" msgstr "" #: ecpsvm.c:2089 msgid "HHCEV300D : New PSW Enables interrupts and MICPEND (BC)\n" msgstr "" #: ecpsvm.c:2096 msgid "HHCEV300D : New PSW is a WAIT PSW\n" msgstr "" #: ecpsvm.c:2103 msgid "HHCEV300D : New PSW sysmask incorrect\n" msgstr "" #: ecpsvm.c:2109 msgid "HHCEV300D : New PSW has ODD IA\n" msgstr "" #: ecpsvm.c:2596 ecpsvm.c:2613 #, c-format msgid "HHCEV001I | %-9s | %8d | %8d | %3d%% |\n" msgstr "" #: ecpsvm.c:2623 #, c-format msgid "HHCEV004I * : Unsupported, - : Disabled, %% - Debug\n" msgstr "" #: ecpsvm.c:2627 #, c-format msgid "HHCEV005I %d Entr%s not shown (never invoked)\n" msgstr "" #: ecpsvm.c:2633 msgid "HHCEV006I 1 call was made to an unsupported function\n" msgstr "" #: ecpsvm.c:2637 #, c-format msgid "HHCEV006I %d calls where made to unsupported functions\n" msgstr "" #: ecpsvm.c:2652 ecpsvm.c:2661 #, c-format msgid "HHCEV002I | %-9s | %-8s | %-8s | %-5s |\n" msgstr "" #: ecpsvm.c:2716 #, c-format msgid "HHCEV015I ECPS:VM %s feature %s %s\n" msgstr "" #: ecpsvm.c:2721 #, c-format msgid "HHCEV015I ECPS:VM %s feature %s Debug %s\n" msgstr "" #: ecpsvm.c:2726 #, c-format msgid "HHCEV016I All ECPS:VM %s features %s\n" msgstr "" #: ecpsvm.c:2730 #, c-format msgid "HHCEV016I All ECPS:VM %s features Debug %s\n" msgstr "" #: ecpsvm.c:2758 #, c-format msgid "HHCEV013I ECPS:VM Global Debug %s\n" msgstr "" #: ecpsvm.c:2786 #, c-format msgid "HHCEV014I ECPS:VM %s feature %s %s\n" msgstr "" #: ecpsvm.c:2791 #, c-format msgid "HHCEV014I ECPS:VM %s feature %s Debug %s\n" msgstr "" #: ecpsvm.c:2796 #, c-format msgid "HHCEV014I Unknown ECPS:VM feature %s; Ignored\n" msgstr "" #: ecpsvm.c:2823 ecpsvm.c:2827 #, c-format msgid "HHCEV016I Current reported ECPS:VM Level is %d\n" msgstr "" #: ecpsvm.c:2828 msgid "HHCEV017I But ECPS:VM is currently disabled\n" msgstr "" #: ecpsvm.c:2833 #, c-format msgid "HHCEV016I Level reported to guest program is now %d\n" msgstr "" #: ecpsvm.c:2838 #, c-format msgid "HHCEV017W WARNING ! current level (%d) is not supported\n" msgstr "" #: ecpsvm.c:2839 msgid "HHCEV018W WARNING ! Unpredictable results may occur\n" msgstr "" #: ecpsvm.c:2840 msgid "HHCEV019I The microcode support level is 20\n" msgstr "" #: ecpsvm.c:2867 #, c-format msgid "HHCEV010I : %s : %s\n" msgstr "" #: ecpsvm.c:2883 #, c-format msgid "HHCEV011E Unknown subcommand %s - valid subcommands are :\n" msgstr "" #: ecpsvm.c:2887 #, c-format msgid "HHCEV012I : %s : %s" msgstr "" #: ecpsvm.c:2913 msgid "HHCEV011I ECPS:VM Command processor invoked\n" msgstr "" #: ecpsvm.c:2916 msgid "" "HHCEV008E NO EVM subcommand. Type \"evm help\" for a list of valid " "subcommands\n" msgstr "" #: ecpsvm.c:2922 #, c-format msgid "HHCEV008E Unknown EVM subcommand %s\n" msgstr "" #: ecpsvm.c:2926 msgid "HHCEV011I ECPS:VM Command processor complete\n" msgstr "" #: external.c:173 msgid "HHCCP023I External interrupt: Interrupt key\n" msgstr "" #: external.c:284 msgid "HHCCP024I External interrupt: Clock comparator\n" msgstr "" #: external.c:295 msgid "HHCCP025I External interrupt: CPU timer=%16.16" msgstr "" #: external.c:311 msgid "HHCCP026I External interrupt: Interval timer\n" msgstr "" #: fbadasd.c:91 #, fuzzy msgid "HHCDA056E File name missing or invalid\n" msgstr "HHCDA056E Bestandsnaam niet opgegeven of ongeldig\n" #: fbadasd.c:108 #, fuzzy, c-format msgid "HHCDA057E %4.4X:File not found or invalid\n" msgstr "HHCDA057E %4.4X:Bestandsnaam niet opgegeven of ongeldig\n" #: fbadasd.c:124 #, fuzzy, c-format msgid "HHCDA058E File %s open error: %s\n" msgstr "HHCDA058E Fout %2$s bij openen bestand \"%1$s\"\n" #: fbadasd.c:136 #, fuzzy, c-format msgid "HHCDA059E Read error in file %s: %s\n" msgstr "HHCDA059E Fout %2$s bij leven van bestand \"%1$s\"\n" #: fbadasd.c:139 #, fuzzy, c-format msgid "HHCDA060E Unexpected end of file in %s\n" msgstr "HHCDA060E Onverwacht einde van bestand \"%s\"\n" #: fbadasd.c:157 #, fuzzy, c-format msgid "HHCDA061E Read error in file %s: %s\n" msgstr "HHCDA061E Fout %2$s bij leven van bestand \"%1$s\"\n" #: fbadasd.c:160 #, fuzzy, c-format msgid "HHCDA062E Unexpected end of file in %s\n" msgstr "HHCDA062E Onverwacht einde van bestand \"%s\"\n" #: fbadasd.c:213 #, c-format msgid "HHCDA063E parameter %d is invalid: %s\n" msgstr "" #: fbadasd.c:226 #, c-format msgid "HHCDA064E File %s fstat error: %s\n" msgstr "" #: fbadasd.c:238 #, fuzzy, c-format msgid "HHCDA082E File %s IOCTL BLKGETSIZE error: %s\n" msgstr "HHCDA058E Fout %2$s bij openen bestand \"%1$s\"\n" #: fbadasd.c:264 #, c-format msgid "HHCDA065E Invalid device origin block number %s\n" msgstr "" #: fbadasd.c:280 #, c-format msgid "HHCDA066E Invalid device block count %s\n" msgstr "" #: fbadasd.c:291 #, c-format msgid "HHCDA067I %s origin=%lld blks=%d\n" msgstr "" #: fbadasd.c:301 #, c-format msgid "HHCDA068E %4.4X device type %4.4X not found in dasd table\n" msgstr "" #: fbadasd.c:526 #, c-format msgid "HHCDA069E error writing blkgrp %d: lseek error: %s\n" msgstr "" #: fbadasd.c:544 #, c-format msgid "HHCDA070E error writing blkgrp %d: write error: %s\n" msgstr "" #: fbadasd.c:585 #, c-format msgid "HHCDA071I read blkgrp %d cache hit, using cache[%d]\n" msgstr "" #: fbadasd.c:610 #, c-format msgid "HHCDA072I read blkgrp %d no available cache entry, waiting\n" msgstr "" #: fbadasd.c:618 #, c-format msgid "HHCDA073I read blkgrp %d cache miss, using cache[%d]\n" msgstr "" #: fbadasd.c:634 msgid "HHCDA074I read blkgrp %d offset %" msgstr "" #: fbadasd.c:642 #, c-format msgid "HHCDA075E error reading blkgrp %d: lseek error: %s\n" msgstr "" #: fbadasd.c:657 #, c-format msgid "HHCDA076E error reading blkgrp %d: read error: %s\n" msgstr "" #: fbadasd.c:1085 msgid "HHCDA077I Positioning to %8.8" msgstr "" #: fbadasd.c:1103 #, c-format msgid "HHCDA078E define extent data too short: %d bytes\n" msgstr "" #: fbadasd.c:1113 msgid "HHCDA079E second define extent in chain\n" msgstr "" #: fbadasd.c:1124 #, c-format msgid "HHCDA080E invalid file mask %2.2X\n" msgstr "" #: fbadasd.c:1161 #, c-format msgid "HHCDA081E invalid extent: first block %d, last block %d,\n" msgstr "" #: fbadasd.c:1163 #, c-format msgid " numblks %d, device size %d\n" msgstr "" #: fbadasd.c:1435 #, c-format msgid "HHCDA901E %4.4x FBA origin mismatch: %d, expected %d,\n" msgstr "" #: fbadasd.c:1444 #, c-format msgid "HHCDA902E %4.4x FBA numblk mismatch: %d, expected %d,\n" msgstr "" #: fbadasd.c:1474 #, c-format msgid "HHCDA903E %4.4x FBA blksiz mismatch: %d, expected %d,\n" msgstr "" #: general1.c:3704 msgid "MVCL destructive overlap: " msgstr "" #: hdl.c:138 #, c-format msgid "HHCHD018I Loadable module directory is %s\n" msgstr "" #: hdl.c:411 #, c-format msgid "HHCHD010I Dependency check failed for %s, version(%s) expected(%s)\n" msgstr "" #: hdl.c:418 #, c-format msgid "HHCHD011I Dependency check failed for %s, size(%d) expected(%d)\n" msgstr "" #: hdl.c:460 #, c-format msgid "HHCHD001E registration malloc failed for %s\n" msgstr "" #: hdl.c:588 hdl.c:792 #, fuzzy, c-format msgid "HHCHD007E unable to open DLL %s: %s\n" msgstr "HHCHD007E Fout %2$s bij openen DLL bestand \"%1$s\"\n" #: hdl.c:598 hdl.c:802 #, fuzzy, c-format msgid "HHCHD013E No dependency section in %s: %s\n" msgstr "HHCRD013E Fout %2$s bij openen bestand \"%1$s\"\n" #: hdl.c:622 hdl.c:840 #, c-format msgid "HHCHD014E Dependency check failed for module %s\n" msgstr "" #: hdl.c:675 #, c-format msgid "HHCHD002E cannot allocate memory for DLL descriptor: %s\n" msgstr "" #: hdl.c:690 #, c-format msgid "HHCHD003E unable to open hercules as DLL: %s\n" msgstr "" #: hdl.c:699 #, fuzzy, c-format msgid "HHCHD012E No dependency section in %s: %s\n" msgstr "HHCRD013E Fout %2$s bij openen bestand \"%1$s\"\n" #: hdl.c:775 #, c-format msgid "HHCHD005E %s already loaded\n" msgstr "" #: hdl.c:782 #, c-format msgid "HHCHD006S cannot allocate memory for DLL descriptor: %s\n" msgstr "" #: hdl.c:813 #, c-format msgid "HHCHD016E DLL %s is duplicate of %s\n" msgstr "" #: hdl.c:907 #, c-format msgid "HHCHD015E Unloading of %s not allowed\n" msgstr "" #: hdl.c:917 #, fuzzy, c-format msgid "HHCHD008E Device %4.4X bound to %s\n" msgstr "HHCSD007I %s (%s) afgesloten van apparaat %4.4X (%s)\n" #: hdl.c:929 #, c-format msgid "HHCHD017E Unload of %s rejected by final section\n" msgstr "" #: hdl.c:989 #, c-format msgid "HHCHD009E %s not found\n" msgstr "" #: hercifc.c:66 #, c-format msgid "HHCIF001E %s: Must be called from within Hercules.\n" msgstr "" #: hercifc.c:77 #, c-format msgid "HHCIF002E %s: Cannot obtain socket: %s\n" msgstr "" #: hercifc.c:94 #, c-format msgid "HHCIF003E %s: I/O error on read: %s.\n" msgstr "" #: hercifc.c:103 #, c-format msgid "HHCIF007E %s: Hercules disappeared!! .. exiting\n" msgstr "" #: hercifc.c:210 #, c-format msgid "HHCIF004W %s: Unknown request: %8.8lX.\n" msgstr "" #: hercifc.c:218 #, fuzzy, c-format msgid "HHCIF006I %s: Doing %s on %s\n" msgstr "HHCDC001E %1$s:Fout %3$s bij openen bestand \"%2$s\"\n" #: hercifc.c:239 #, fuzzy, c-format msgid "HHCIF005E %s: ioctl error doing %s on %s: %d %s\n" msgstr "HHCDC001E %1$s:Fout %3$s bij openen bestand \"%2$s\"\n" #: hostinfo.c:90 #, fuzzy, c-format msgid "Running on %s %s-%s.%s %s%s" msgstr "Draaiend op %s %s%s %s %s\n" #: hsccmd.c:158 #, fuzzy, c-format msgid "HHCPN181E Device number %d:%4.4X not found\n" msgstr "HHCPN043E Apparaat nummer %s is ongeldig\n" #: hsccmd.c:164 #, fuzzy msgid "HHCPN031E Missing device number\n" msgstr "HHCPN031E Geen apparaat nummer\n" #: hsccmd.c:181 msgid "Improper command format" msgstr "" #: hsccmd.c:190 #, c-format msgid "\"%s\": invalid maxrates interval" msgstr "" #: hsccmd.c:196 #, c-format msgid "Maxrates interval set to %d minutes.\n" msgstr "" #: hsccmd.c:200 msgid "; enter \"help maxrates\" for help.\n" msgstr "" #: hsccmd.c:358 #, fuzzy msgid "HHCPN160E no argument\n" msgstr "HHCPN054E Geen apparaat nummer\n" #: hsccmd.c:372 #, fuzzy, c-format msgid "HHCPN195I Log options:%s\n" msgstr "HHCPN109E Fout %2$s bij openen bestand \"%1$s\"\n" #: hsccmd.c:385 msgid "HHCPN197I Log option set: TIMESTAMP\n" msgstr "" #: hsccmd.c:392 msgid "HHCPN197I Log option set: NOTIMESTAMP\n" msgstr "" #: hsccmd.c:396 #, fuzzy, c-format msgid "HHCPN196E Invalid logopt value %s\n" msgstr "HHCPN143E Ongeldige waarde: %s\n" #: hsccmd.c:462 #, fuzzy, c-format msgid "HHCPN017E Device %d:%4.4X is not a printer device\n" msgstr "HHCPN015E Ongeldig apparaat nummer\n" #: hsccmd.c:476 #, c-format msgid "HHCPN018I Printer %d:%4.4X started\n" msgstr "" #: hsccmd.c:478 #, c-format msgid "HHCPN019E Printer %d:%4.4X not started: busy or interrupt pending\n" msgstr "" #: hsccmd.c:481 #, c-format msgid "HHCPN020E Printer %d:%4.4X not started: attention request rejected\n" msgstr "" #: hsccmd.c:484 #, c-format msgid "HHCPN021E Printer %d:%4.4X not started: subchannel not enabled\n" msgstr "" #: hsccmd.c:565 #, fuzzy, c-format msgid "HHCPN024E Device %d:%4.4X is not a printer device\n" msgstr "HHCPN015E Ongeldig apparaat nummer\n" #: hsccmd.c:572 #, c-format msgid "HHCPN025I Printer %d:%4.4X stopped\n" msgstr "" #: hsccmd.c:666 #, fuzzy, c-format msgid "HHCPN152I CPU%4.4X online\n" msgstr "HHCCP003I CPU%4.4X Architectuur Modus %s\n" #: hsccmd.c:673 #, fuzzy, c-format msgid "HHCPN153I CPU%4.4X offline\n" msgstr "HHCCP003I CPU%4.4X Architectuur Modus %s\n" #: hsccmd.c:709 #, fuzzy, c-format msgid "HHCPN154I CPU%4.4X online\n" msgstr "HHCCP003I CPU%4.4X Architectuur Modus %s\n" #: hsccmd.c:716 #, fuzzy, c-format msgid "HHCPN155I CPU%4.4X offline\n" msgstr "HHCCP003I CPU%4.4X Architectuur Modus %s\n" #: hsccmd.c:741 msgid "HHCPN026W Ignored. (external GUI active)\n" msgstr "" #: hsccmd.c:746 #, c-format msgid "HHCPN027I Automatic refresh %s.\n" msgstr "" #: hsccmd.c:747 msgid "disabled" msgstr "" #: hsccmd.c:747 msgid "enabled" msgstr "" #: hsccmd.c:826 #, c-format msgid "HHCPN037I Timer update interval = %d microsecond(s)\n" msgstr "" #: hsccmd.c:868 hsccmd.c:1323 hsccmd.c:1487 hsccmd.c:1547 hsccmd.c:1575 #: hsccmd.c:1603 hsccmd.c:1631 hsccmd.c:1659 hsccmd.c:1690 hsccmd.c:1719 #: hsccmd.c:1756 hsccmd.c:1783 hsccmd.c:1810 hsccmd.c:3240 hsccmd.c:3388 #: hsccmd.c:3455 hsccmd.c:4851 hsccmd.c:4955 hsccmd.c:5048 hsccmd.c:5090 #, fuzzy, c-format msgid "HHCPN160W CPU%4.4X not configured\n" msgstr "HHCCP003I CPU%4.4X Architectuur Modus %s\n" #: hsccmd.c:903 msgid "HHCPN028I tod = %16.16" msgstr "" #: hsccmd.c:906 msgid " h/w = %16.16" msgstr "" #: hsccmd.c:918 msgid " off = %16.16" msgstr "" #: hsccmd.c:922 msgid " ckc = %16.16" msgstr "" #: hsccmd.c:926 msgid " cpt = %16.16" msgstr "" #: hsccmd.c:928 msgid " cpt = not decrementing\n" msgstr "" #: hsccmd.c:934 msgid " vtod = %16.16" msgstr "" #: hsccmd.c:946 msgid " voff = %16.16" msgstr "" #: hsccmd.c:950 msgid " vckc = %16.16" msgstr "" #: hsccmd.c:953 msgid " vcpt = %16.16" msgstr "" #: hsccmd.c:959 msgid " itm = %8.8" msgstr "" #: hsccmd.c:981 #, fuzzy, c-format msgid "HHCPN029E Invalid I/O delay value: %s\n" msgstr "HHCPN029E Ongeldige I/O delay waarde: %s\n" #: hsccmd.c:986 #, c-format msgid "HHCPN030I I/O delay = %d\n" msgstr "" #: hsccmd.c:1064 #, c-format msgid "HHCCF068E Invalid value: %s; Enter \"help scsimount\" for help.\n" msgstr "" #: hsccmd.c:1075 #, c-format msgid "SCSI auto-mount queries = every %d seconds (when needed)\n" msgstr "" #: hsccmd.c:1078 msgid "SCSI auto-mount queries are disabled.\n" msgstr "" #: hsccmd.c:1093 #, c-format msgid "SCSI auto-mount thread %s active for drive %u:%4.4X = %s.\n" msgstr "" #: hsccmd.c:1168 #, c-format msgid "" "\n" "%s\n" "HHCCF069I %s of %s-labeled volume \"%s\" pending for drive %u:%4.4X = %s\n" "%s\n" "\n" msgstr "" #: hsccmd.c:1182 #, c-format msgid "No mount/dismount requests pending for drive %u:%4.4X = %s.\n" msgstr "" #: hsccmd.c:1215 msgid "HHCPN186E cmd deprecated; try 'tt32' instead\n" msgstr "" #: hsccmd.c:1232 msgid "HHCPN188E Missing arguments; enter 'help tt32' for help.\n" msgstr "" #: hsccmd.c:1255 #, c-format msgid "HHCPN034E Device %d:%4.4X is not a CTCI or LCS device\n" msgstr "" #: hsccmd.c:1264 hsccmd.c:1278 hsccmd.c:1292 msgid "(error)\n" msgstr "" #: hsccmd.c:1274 msgid "HHCPN189I TT32 debug tracing messages enabled\n" msgstr "" #: hsccmd.c:1288 msgid "HHCPN189I TT32 debug tracing messages disabled\n" msgstr "" #: hsccmd.c:1298 #, fuzzy msgid "HHCPN187E Invalid argument\n" msgstr "HHCPU002E Optie %s niet geldig\n" #: hsccmd.c:1331 msgid "HHCPN035E store status rejected: CPU not stopped\n" msgstr "" #: hsccmd.c:1367 #, c-format msgid "HHCPN036I TOD clock drag factor = %lf\n" msgstr "" #: hsccmd.c:1399 #, c-format msgid "HHCPN037I Panel refresh rate = %d millisecond(s)\n" msgstr "" #: hsccmd.c:1417 hsccmd.c:1439 hsccmd.c:1460 msgid "HHCPN180E shell commands are disabled\n" msgstr "" #: hsccmd.c:1465 #, fuzzy msgid "HHCPN163E Invalid format. Command does not support any arguments.\n" msgstr "HHCPN054E Geen apparaat nummer\n" #: hsccmd.c:1502 msgid "HHCPN162E Invalid format. Enter \"help gpr\" for help.\n" msgstr "" #: hsccmd.c:1514 msgid "HHCPN162E Invalid format. .Enter \"help gpr\" for help.\n" msgstr "" #: hsccmd.c:1711 #, fuzzy msgid "HHCPN038I Restart key depressed\n" msgstr "HHCPN038I Restart key ingedrukt\n" #: hsccmd.c:1845 hsccmd.c:1861 #, fuzzy msgid "HHCPN039E Invalid arguments\n" msgstr "HHCPU002E Optie %s niet geldig\n" #: hsccmd.c:1909 #, fuzzy, c-format msgid "HHCPN040I Instruction %s %s %s\n" msgstr "HHCPN050I Interrupt key ingedrukt\n" #: hsccmd.c:1910 msgid "tracing" msgstr "" #: hsccmd.c:1911 msgid "stepping" msgstr "" #: hsccmd.c:1911 msgid "break" msgstr "" #: hsccmd.c:1912 hsccmd.c:4840 msgid "on" msgstr "" #: hsccmd.c:1912 hsccmd.c:4843 msgid "off" msgstr "" #: hsccmd.c:1953 #, c-format msgid "HHCPN045I Device %4.4X attention request raised\n" msgstr "" #: hsccmd.c:1956 #, c-format msgid "HHCPN046E Device %4.4X busy or interrupt pending\n" msgstr "" #: hsccmd.c:1959 #, c-format msgid "HHCPN047E Device %4.4X attention request rejected\n" msgstr "" #: hsccmd.c:1962 #, c-format msgid "HHCPN048E Device %4.4X subchannel not enabled\n" msgstr "" #: hsccmd.c:1969 #, c-format msgid "HHCPN049W Are you sure you didn't mean 'ipl %4.4X' instead?\n" msgstr "" #: hsccmd.c:1988 #, fuzzy msgid "HHCPN050I Interrupt key depressed\n" msgstr "HHCPN050I Interrupt key ingedrukt\n" #: hsccmd.c:2011 #, c-format msgid "HHCPN051I LOADPARM=%s\n" msgstr "" #: hsccmd.c:2030 msgid "HHCPN053E System reset/clear rejected: All CPU's must be stopped\n" msgstr "" #: hsccmd.c:2078 msgid "HHCPN053E ipl rejected: All CPU's must be stopped\n" msgstr "" #: hsccmd.c:2106 hsccmd.c:2522 #, fuzzy, c-format msgid "HHCPN059E LCSS id %s is invalid\n" msgstr "HHCPN043E Apparaat nummer %s is ongeldig\n" #: hsccmd.c:2143 #, fuzzy msgid "HHCPN054E Missing argument\n" msgstr "HHCPN054E Geen apparaat nummer\n" #: hsccmd.c:2150 #, c-format msgid "HHCPN055E Target CPU %s is invalid\n" msgstr "" #: hsccmd.c:2237 hsccmd.c:2369 #, c-format msgid "HHCPN146E Work buffer malloc failed: %s\n" msgstr "" #: hsccmd.c:2295 msgid "open " msgstr "" #: hsccmd.c:2296 msgid "busy " msgstr "" #: hsccmd.c:2297 msgid "pending " msgstr "" #: hsccmd.c:2308 #, c-format msgid " (client %s (%s) connected)\n" msgstr "" #: hsccmd.c:2314 msgid " (no one currently connected)\n" msgstr "" #: hsccmd.c:2326 hsccmd.c:2475 #, c-format msgid "HHCPN147W Warning: not all devices shown (max %d)\n" msgstr "" #: hsccmd.c:2495 msgid "HHCPN057E Missing argument(s)\n" msgstr "" #: hsccmd.c:2514 #, c-format msgid "HHCPN059E Device number %s is invalid\n" msgstr "" #: hsccmd.c:2532 #, fuzzy, c-format msgid "Device type %s is invalid\n" msgstr "HHCPN043E Apparaat nummer %s is ongeldig\n" #: hsccmd.c:2580 msgid "HHCPN062E Missing argument(s)\n" msgstr "" #: hsccmd.c:2596 msgid "" "HHCPN182E Device numbers can only be redefined within the same Logical " "channel subsystem\n" msgstr "" #: hsccmd.c:2616 msgid "HHCPN065E Missing argument(s)\n" msgstr "" #: hsccmd.c:2644 #, c-format msgid "HHCPN066E Program interrupt number %s is invalid\n" msgstr "" #: hsccmd.c:2651 #, c-format msgid "HHCPN067E Program interrupt number out of range (%4.4X)\n" msgstr "" #: hsccmd.c:2683 #, c-format msgid "OSTAILOR %s\n" msgstr "" #: hsccmd.c:2771 #, c-format msgid "Unknown OS tailor specification %s\n" msgstr "" #: hsccmd.c:2846 msgid "HHCPN072I %4.4X synchronous: %12" msgstr "" #: hsccmd.c:2857 msgid "HHCPN073I No synchronous I/O devices found\n" msgstr "" #: hsccmd.c:2859 msgid "HHCPN074I TOTAL synchronous: %12" msgstr "" #: hsccmd.c:2898 #, fuzzy msgid "HHCPN075E Invalid max device threads value (must be -1 to n)\n" msgstr "HHCPN015E Ongeldig apparaat nummer\n" #: hsccmd.c:2905 #, c-format msgid "" "HHCPN076I Max device threads: %d, current: %d, most: %d, waiting: %d, max " "exceeded: %d\n" msgstr "" #: hsccmd.c:2926 msgid "HHCPN077E Invalid max device threads value (must be -1 to n)\n" msgstr "" #: hsccmd.c:2940 #, c-format msgid "" "HHCPN078E Max device threads %d current %d most %d waiting %d total I/Os " "queued %d\n" msgstr "" #: hsccmd.c:2969 msgid "HHCPN091E Command must be 'sf+', 'sf-', 'sfc', or 'sfd'\n" msgstr "" #: hsccmd.c:2998 msgid "HHCPN081E No cckd devices found\n" msgstr "" #: hsccmd.c:3011 #, fuzzy, c-format msgid "HHCPN084E Device number %d:%4.4X is not a cckd device\n" msgstr "HHCPN043E Apparaat nummer %s is ongeldig\n" #: hsccmd.c:3028 msgid "HHCPN087E Operand must be `merge', `nomerge' or `force'\n" msgstr "" #: hsccmd.c:3038 #, c-format msgid "HHCPN089E Unexpected operand: %s\n" msgstr "" #: hsccmd.c:3045 #, fuzzy, c-format msgid "HHCPN085I Processing device %d:%4.4X\n" msgstr "HHCPN052E Geen apparaat nummer\n" #: hsccmd.c:3067 #, c-format msgid "HHCPN092I %d devices processed\n" msgstr "" #: hsccmd.c:3089 msgid "HHCPN093E Missing argument(s)\n" msgstr "" #: hsccmd.c:3114 #, c-format msgid "HHCPN096E Device %d:%4.4X busy or interrupt pending\n" msgstr "" #: hsccmd.c:3130 #, c-format msgid "HHCPN183E Reinit rejected for drive %u:%4.4X; drive not empty\n" msgstr "" #: hsccmd.c:3170 #, fuzzy, c-format msgid "HHCPN097E Initialization failed for device %d:%4.4X\n" msgstr "HHCSD006E %s (%s) afgesloten van apparaat %4.4X (%s)\n" #: hsccmd.c:3173 #, fuzzy, c-format msgid "HHCPN098I Device %d:%4.4X initialized\n" msgstr "HHCPN043E Apparaat nummer %s is ongeldig\n" #: hsccmd.c:3229 msgid "HHCPN099E savecore rejected: filename missing\n" msgstr "" #: hsccmd.c:3262 #, c-format msgid "HHCPN100E savecore: invalid starting address: %s \n" msgstr "" #: hsccmd.c:3280 msgid "HHCPN148E savecore: no modified storage found\n" msgstr "" #: hsccmd.c:3288 #, c-format msgid "HHCPN101E savecore: invalid ending address: %s \n" msgstr "" #: hsccmd.c:3297 msgid "HHCPN102E savecore rejected: CPU not stopped\n" msgstr "" #: hsccmd.c:3304 #, c-format msgid "HHCPN103E invalid range: %8.8X-%8.8X\n" msgstr "" #: hsccmd.c:3309 #, c-format msgid "HHCPN104I Saving locations %8.8X-%8.8X to %s\n" msgstr "" #: hsccmd.c:3318 #, c-format msgid "HHCPN105E savecore error creating %s: %s\n" msgstr "" #: hsccmd.c:3324 #, c-format msgid "HHCPN106E savecore error writing to %s: %s\n" msgstr "" #: hsccmd.c:3327 #, c-format msgid "HHCPN107E savecore: unable to save %d bytes\n" msgstr "" #: hsccmd.c:3334 msgid "HHCPN170I savecore command complete.\n" msgstr "" #: hsccmd.c:3357 msgid "HHCPN108E loadcore rejected: filename missing\n" msgstr "" #: hsccmd.c:3366 #, fuzzy, c-format msgid "HHCPN109E Cannot open %s: %s\n" msgstr "HHCPN109E Fout %2$s bij openen bestand \"%1$s\"\n" #: hsccmd.c:3378 #, c-format msgid "HHCPN110E invalid address: %s \n" msgstr "" #: hsccmd.c:3397 msgid "HHCPN111E loadcore rejected: CPU not stopped\n" msgstr "" #: hsccmd.c:3402 #, c-format msgid "HHCPN112I Loading %s to location %x \n" msgstr "" #: hsccmd.c:3408 #, c-format msgid "HHCPN113I %d bytes read from %s\n" msgstr "" #: hsccmd.c:3432 msgid "HHCPN114E loadtext rejected: filename missing\n" msgstr "" #: hsccmd.c:3445 #, c-format msgid "HHCPN115E invalid address: %s \n" msgstr "" #: hsccmd.c:3463 msgid "HHCPN116E Address greater than mainstore size\n" msgstr "" #: hsccmd.c:3471 msgid "HHCPN117E loadtext rejected: CPU not stopped\n" msgstr "" #: hsccmd.c:3480 #, fuzzy, c-format msgid "HHCPN118E Cannot open %s: %s\n" msgstr "HHCPN118E Fout %2$s bij openen bestand \"%1$s\"\n" #: hsccmd.c:3491 #, fuzzy, c-format msgid "HHCPN119E Cannot read %s: %s\n" msgstr "HHCPN119E Fout %2$s bij lezen van bestand \"%1$s\"\n" #: hsccmd.c:3514 msgid "HHCPN120I Finished loading TEXT deck file\n" msgstr "" #: hsccmd.c:3515 #, c-format msgid " Last 'TXT' record had address: %3.3X\n" msgstr " Laatste 'TXT' record had adres: %3.3X\n" #: hsccmd.c:3541 #, fuzzy, c-format msgid "HHCPN123I CPU%4.4X: offline\n" msgstr "HHCCP003I CPU%4.4X Architectuur Modus %s\n" #: hsccmd.c:3547 #, c-format msgid "HHCPN123I CPU%4.4X: CPUint=%8.8X (State:%8.8X)&(Mask:%8.8X)\n" msgstr "" #: hsccmd.c:3552 #, fuzzy, c-format msgid " CPU%4.4X: Interrupt %spending\n" msgstr " CPU%4.4X: Geen kanaalset aangesloten\n" #: hsccmd.c:3554 hsccmd.c:3558 hsccmd.c:3562 hsccmd.c:3566 hsccmd.c:3571 #: hsccmd.c:3576 hsccmd.c:3582 hsccmd.c:3586 hsccmd.c:3590 hsccmd.c:3594 #: hsccmd.c:3610 hsccmd.c:3649 hsccmd.c:3653 hsccmd.c:3657 hsccmd.c:3661 #: hsccmd.c:3665 hsccmd.c:3669 hsccmd.c:3673 hsccmd.c:3677 hsccmd.c:3681 #: hsccmd.c:3685 hsccmd.c:3724 hsccmd.c:3727 hsccmd.c:3730 hsccmd.c:3734 #: hsccmd.c:3739 msgid "not " msgstr "" #: hsccmd.c:3556 #, fuzzy, c-format msgid " CPU%4.4X: I/O interrupt %spending\n" msgstr " CPU%4.4X: Geen kanaalset aangesloten\n" #: hsccmd.c:3560 #, c-format msgid " CPU%4.4X: Clock comparator %spending\n" msgstr "" #: hsccmd.c:3564 #, c-format msgid " CPU%4.4X: CPU timer %spending\n" msgstr "" #: hsccmd.c:3569 #, c-format msgid " CPU%4.4X: Interval timer %spending\n" msgstr "" #: hsccmd.c:3574 #, fuzzy, c-format msgid " CPU%4.4X: ECPS vtimer %spending\n" msgstr " CPU%4.4X: Geen kanaalset aangesloten\n" #: hsccmd.c:3580 #, c-format msgid " CPU%4.4X: External call %spending\n" msgstr "" #: hsccmd.c:3584 #, c-format msgid " CPU%4.4X: Emergency signal %spending\n" msgstr "" #: hsccmd.c:3588 #, fuzzy, c-format msgid " CPU%4.4X: Machine check interrupt %spending\n" msgstr " CPU%4.4X: Geen kanaalset aangesloten\n" #: hsccmd.c:3592 #, fuzzy, c-format msgid " CPU%4.4X: Service signal %spending\n" msgstr " CPU%4.4X: Geen kanaalset aangesloten\n" #: hsccmd.c:3596 #, fuzzy, c-format msgid " CPU%4.4X: Mainlock held: %s\n" msgstr " CPU%4.4X: Geen kanaalset aangesloten\n" #: hsccmd.c:3598 hsccmd.c:3602 hsccmd.c:3606 msgid "yes" msgstr "" #: hsccmd.c:3598 hsccmd.c:3602 hsccmd.c:3606 msgid "no" msgstr "" #: hsccmd.c:3600 #, fuzzy, c-format msgid " CPU%4.4X: Intlock held: %s\n" msgstr " CPU%4.4X: Geen kanaalset aangesloten\n" #: hsccmd.c:3604 #, fuzzy, c-format msgid " CPU%4.4X: Waiting for intlock: %s\n" msgstr " CPU%4.4X: Geen kanaalset aangesloten\n" #: hsccmd.c:3608 #, fuzzy, c-format msgid " CPU%4.4X: lock %sheld\n" msgstr " CPU%4.4X: Geen kanaalset aangesloten\n" #: hsccmd.c:3615 #, c-format msgid " CPU%4.4X: No channelset connected\n" msgstr " CPU%4.4X: Geen kanaalset aangesloten\n" #: hsccmd.c:3619 #, c-format msgid " CPU%4.4X: Connected to channelset %4.4X\n" msgstr " CPU%4.4X: Verbonden met kanaalset %4.4X\n" #: hsccmd.c:3624 #, fuzzy, c-format msgid " CPU%4.4X: state %s\n" msgstr " CPU%4.4X: Geen kanaalset aangesloten\n" #: hsccmd.c:3626 #, fuzzy msgid " CPU%4.4X: instcount %" msgstr " CPU%4.4X: Geen kanaalset aangesloten\n" #: hsccmd.c:3628 #, fuzzy msgid " CPU%4.4X: siocount %" msgstr " CPU%4.4X: Geen kanaalset aangesloten\n" #: hsccmd.c:3631 #, c-format msgid " CPU%4.4X: psw %2.2x%2.2x%2.2x%2.2x %2.2x%2.2x%2.2x%2.2x" msgstr "" #: hsccmd.c:3635 hsccmd.c:3710 #, c-format msgid " %2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x" msgstr "" #: hsccmd.c:3642 #, c-format msgid "HHCPN123I SIE%4.4X: CPUint=%8.8X (State:%8.8X)&(Mask:%8.8X)\n" msgstr "" #: hsccmd.c:3647 #, fuzzy, c-format msgid " SIE%4.4X: Interrupt %spending\n" msgstr " CPU%4.4X: Geen kanaalset aangesloten\n" #: hsccmd.c:3651 #, fuzzy, c-format msgid " SIE%4.4X: I/O interrupt %spending\n" msgstr " CPU%4.4X: Geen kanaalset aangesloten\n" #: hsccmd.c:3655 #, fuzzy, c-format msgid " SIE%4.4X: Clock comparator %spending\n" msgstr " CPU%4.4X: Geen kanaalset aangesloten\n" #: hsccmd.c:3659 #, fuzzy, c-format msgid " SIE%4.4X: CPU timer %spending\n" msgstr " CPU%4.4X: Geen kanaalset aangesloten\n" #: hsccmd.c:3663 #, fuzzy, c-format msgid " SIE%4.4X: Interval timer %spending\n" msgstr " CPU%4.4X: Geen kanaalset aangesloten\n" #: hsccmd.c:3667 #, fuzzy, c-format msgid " SIE%4.4X: External call %spending\n" msgstr " CPU%4.4X: Geen kanaalset aangesloten\n" #: hsccmd.c:3671 #, fuzzy, c-format msgid " SIE%4.4X: Emergency signal %spending\n" msgstr " CPU%4.4X: Geen kanaalset aangesloten\n" #: hsccmd.c:3675 #, fuzzy, c-format msgid " SIE%4.4X: Machine check interrupt %spending\n" msgstr " CPU%4.4X: Geen kanaalset aangesloten\n" #: hsccmd.c:3679 #, fuzzy, c-format msgid " SIE%4.4X: Service signal %spending\n" msgstr " CPU%4.4X: Geen kanaalset aangesloten\n" #: hsccmd.c:3683 #, fuzzy, c-format msgid " SIE%4.4X: lock %sheld\n" msgstr " CPU%4.4X: Geen kanaalset aangesloten\n" #: hsccmd.c:3690 #, fuzzy, c-format msgid " SIE%4.4X: No channelset connected\n" msgstr " CPU%4.4X: Geen kanaalset aangesloten\n" #: hsccmd.c:3694 #, fuzzy, c-format msgid " SIE%4.4X: Connected to channelset %4.4X\n" msgstr " CPU%4.4X: Verbonden met kanaalset %4.4X\n" #: hsccmd.c:3699 #, fuzzy, c-format msgid " SIE%4.4X: state %s\n" msgstr " CPU%4.4X: Geen kanaalset aangesloten\n" #: hsccmd.c:3701 #, fuzzy msgid " SIE%4.4X: instcount %" msgstr " CPU%4.4X: Geen kanaalset aangesloten\n" #: hsccmd.c:3703 #, fuzzy msgid " SIE%4.4X: siocount %" msgstr " CPU%4.4X: Geen kanaalset aangesloten\n" #: hsccmd.c:3706 #, c-format msgid " SIE%4.4X: psw %2.2x%2.2x%2.2x%2.2x %2.2x%2.2x%2.2x%2.2x" msgstr "" #: hsccmd.c:3717 #, c-format msgid " Config mask %8.8X started mask %8.8X waiting mask %8.8X\n" msgstr "" #: hsccmd.c:3720 #, c-format msgid " Syncbc mask %8.8x %s\n" msgstr "" #: hsccmd.c:3721 msgid "Sync in progress" msgstr "" #: hsccmd.c:3723 #, c-format msgid " Signaling facility %sbusy\n" msgstr "" #: hsccmd.c:3726 #, c-format msgid " TOD lock %sheld\n" msgstr "" #: hsccmd.c:3729 #, fuzzy, c-format msgid " Mainlock %sheld; owner %4.4x\n" msgstr " CPU%4.4X: Geen kanaalset aangesloten\n" #: hsccmd.c:3733 #, fuzzy, c-format msgid " Intlock %sheld; owner %4.4x\n" msgstr " CPU%4.4X: Geen kanaalset aangesloten\n" #: hsccmd.c:3738 #, c-format msgid " Ioq lock %sheld\n" msgstr "" #: hsccmd.c:3752 #, fuzzy, c-format msgid " DEV %d:%4.4X: busy %s\n" msgstr " CPU%4.4X: Geen kanaalset aangesloten\n" #: hsccmd.c:3754 #, fuzzy, c-format msgid " DEV %d:%4.4X: reserved %s\n" msgstr " CPU%4.4X: Geen kanaalset aangesloten\n" #: hsccmd.c:3756 #, fuzzy, c-format msgid " DEV %d:%4.4X: suspended\n" msgstr " CPU%4.4X: Geen kanaalset aangesloten\n" #: hsccmd.c:3758 #, fuzzy, c-format msgid " DEV %d:%4.4X: I/O pending\n" msgstr " CPU%4.4X: Geen kanaalset aangesloten\n" #: hsccmd.c:3760 #, fuzzy, c-format msgid " DEV %d:%4.4X: PCI pending\n" msgstr " CPU%4.4X: Geen kanaalset aangesloten\n" #: hsccmd.c:3762 #, fuzzy, c-format msgid " DEV %d:%4.4X: Attn pending\n" msgstr " CPU%4.4X: Geen kanaalset aangesloten\n" #: hsccmd.c:3764 #, fuzzy, c-format msgid " DEV %d:%4.4X: CRW pending\n" msgstr " CPU%4.4X: Geen kanaalset aangesloten\n" #: hsccmd.c:3766 #, fuzzy, c-format msgid " DEV %d:%4.4X: lock held\n" msgstr " CPU%4.4X: Geen kanaalset aangesloten\n" #: hsccmd.c:3769 msgid " I/O interrupt queue: " msgstr "" #: hsccmd.c:3772 msgid "(NULL)" msgstr "" #: hsccmd.c:3778 #, c-format msgid " DEV %d:%4.4X,%s%s%s%s, pri %d\n" msgstr "" #: hsccmd.c:3812 msgid "HHCPN124I Instruction counts reset to zero.\n" msgstr "" #: hsccmd.c:4247 #, fuzzy msgid "HHCPN125I Sorted instruction count display:\n" msgstr "HHCPN129I CPU%4.4X Architectuur Modus %s\n" #: hsccmd.c:4345 msgid "HHCPN125I Instruction count display:\n" msgstr "" #: hsccmd.c:4527 msgid "HHCPN996E The script command requires a filename\n" msgstr "" #: hsccmd.c:4540 msgid "HHCPN997E Only 1 script may be invoked from the panel at any time\n" msgstr "" #: hsccmd.c:4558 msgid "HHCPN998E Script aborted : user cancel request\n" msgstr "" #: hsccmd.c:4580 msgid "HHCPN998E Script aborted : Script recursion level exceeded\n" msgstr "" #: hsccmd.c:4596 hsccmd.c:4605 #, fuzzy, c-format msgid "HHCPN007E Script file \"%s\" open failed: %s\n" msgstr "HHCDC007E %$1s: Fout %3$s bij openen van bestand \"%2$s\"\n" #: hsccmd.c:4599 #, c-format msgid "HHCPN995E Script file \"%s\" not found\n" msgstr "" #: hsccmd.c:4617 #, c-format msgid "HHCPN008I Script file processing started using file \"%s\"\n" msgstr "" #: hsccmd.c:4625 #, c-format msgid "HHCPN009E Script file buffer malloc failed: %s\n" msgstr "" #: hsccmd.c:4667 #, c-format msgid "HHCPN010W Ignoring invalid SCRIPT file pause statement: %s\n" msgstr "" #: hsccmd.c:4673 #, c-format msgid "HHCPN011I Pausing SCRIPT file processing for %d seconds...\n" msgstr "" #: hsccmd.c:4677 msgid "HHCPN012I Resuming SCRIPT file processing...\n" msgstr "" #: hsccmd.c:4695 msgid "HHCPN013I EOF reached on SCRIPT file. Processing complete.\n" msgstr "" #: hsccmd.c:4700 #, c-format msgid "HHCPN014E I/O error reading SCRIPT file: %s\n" msgstr "" #: hsccmd.c:4705 #, c-format msgid "HHCPN999I Script \"%s\" aborted due to previous conditions\n" msgstr "" #: hsccmd.c:4734 #, fuzzy, c-format msgid "HHCPN126I Architecture mode = %s\n" msgstr "HHCPN126I Achitectuur modus = %s\n" #: hsccmd.c:4747 msgid "HHCPN127E All CPU's must be stopped to change architecture\n" msgstr "" #: hsccmd.c:4788 #, fuzzy, c-format msgid "HHCPN128E Invalid architecture mode %s\n" msgstr "HHCPN128E Ongeldige achitectuur modus %s\n" #: hsccmd.c:4802 #, fuzzy, c-format msgid "HHCPN129I Architecture successfully set to %s mode.\n" msgstr "HHCPN129I CPU%4.4X Architectuur Modus %s\n" #: hsccmd.c:4864 #, fuzzy, c-format msgid "HHCPN130E Invalid frame address %8.8X\n" msgstr "HHCPN130E Ongeldig frame adres %8.8X\n" #: hsccmd.c:4871 #, c-format msgid "HHCPN131I Frame %8.8X marked %s\n" msgstr "" #: hsccmd.c:4872 msgid "usable" msgstr "" #: hsccmd.c:4872 msgid "unusable" msgstr "" #: hsccmd.c:4889 #, c-format msgid "HHCPN134I CKD KEY trace is now %s\n" msgstr "" #: hsccmd.c:4912 #, c-format msgid "HHCPN136I CCW tracing is now %s for device %d:%4.4X\n" msgstr "" #: hsccmd.c:4917 #, c-format msgid "HHCPN137I CCW stepping is now %s for device %d:%4.4X\n" msgstr "" #: hsccmd.c:4926 msgid "HHCPN138E Unrecognized +/- command.\n" msgstr "" #: hsccmd.c:5230 #, c-format msgid "HHCHD100I Loading %s ...\n" msgstr "" #: hsccmd.c:5232 #, c-format msgid "HHCHD101I Module %s loaded\n" msgstr "" #: hsccmd.c:5255 #, c-format msgid "HHCHD102I Unloading %s ...\n" msgstr "" #: hsccmd.c:5257 #, c-format msgid "HHCHD103I Module %s unloaded\n" msgstr "" #: hsccmd.c:5302 msgid "HHCPN150W evm command is deprecated. Use \"ecpsvm\" instead\n" msgstr "" #: hsccmd.c:5338 #, c-format msgid "HHCPN161I (void *) ..........%7d\n" msgstr "" #: hsccmd.c:5339 #, c-format msgid "HHCPN161I (unsigned int) ....%7d\n" msgstr "" #: hsccmd.c:5340 #, c-format msgid "HHCPN161I (size_t) ..........%7d\n" msgstr "" #: hsccmd.c:5341 #, c-format msgid "HHCPN161I (off_t) ...........%7d\n" msgstr "" #: hsccmd.c:5342 #, c-format msgid "HHCPN161I SYSBLK ............%7d\n" msgstr "" #: hsccmd.c:5343 #, c-format msgid "HHCPN161I REGS ..............%7d\n" msgstr "" #: hsccmd.c:5344 #, c-format msgid "HHCPN161I REGS (copy len) ...%7d\n" msgstr "" #: hsccmd.c:5345 #, c-format msgid "HHCPN161I PSW ...............%7d\n" msgstr "" #: hsccmd.c:5346 #, c-format msgid "HHCPN161I DEVBLK ............%7d\n" msgstr "" #: hsccmd.c:5347 #, c-format msgid "HHCPN161I TLB entry .........%7d\n" msgstr "" #: hsccmd.c:5348 #, c-format msgid "HHCPN161I TLB table .........%7d\n" msgstr "" #: hsccmd.c:5349 #, c-format msgid "HHCPN161I FILENAME_MAX ......%7d\n" msgstr "" #: hsccmd.c:5350 #, c-format msgid "HHCPN161I PATH_MAX ..........%7d\n" msgstr "" #: hsccmd.c:5391 #, c-format msgid "HHCPN190I Keep-alive = (%d,%d,%d)\n" msgstr "" #: hsccmd.c:5394 msgid "HHCPN192E Invalid format. Enter \"help conkpalv\" for help.\n" msgstr "" #: hsccmd.c:5422 #, fuzzy, c-format msgid "HHCPN162I Hercules instruction trace displayed in %s mode\n" msgstr "HHCPN129I CPU%4.4X Architectuur Modus %s\n" #: hsccmd.c:5423 msgid "noregs" msgstr "" #: hsccmd.c:5424 msgid "regsfirst" msgstr "" #: hsccmd.c:5425 msgid "traditional" msgstr "" #: hsccmd.c:5734 #, c-format msgid "HHCPN139E Command \"%s\" not found; enter '?' for list.\n" msgstr "" #: hsccmd.c:5761 msgid "" "HHCPN140I Valid panel commands are...\n" "\n" msgstr "" #: hsccmd.c:5771 #, c-format msgid " %-9.9s %s \n" msgstr "" #: hsccmd.c:5778 msgid "add shadow file" msgstr "" #: hsccmd.c:5779 msgid "delete shadow file" msgstr "" #: hsccmd.c:5780 msgid "rename shadow file" msgstr "" #: hsccmd.c:5781 msgid "compress shadow files" msgstr "" #: hsccmd.c:5782 msgid "display shadow file stats" msgstr "" #: hsccmd.c:5788 msgid "turn CCW tracing on/off" msgstr "" #: hsccmd.c:5789 msgid "turn CCW stepping on/off" msgstr "" #: hsccmd.c:5791 msgid "turn CKD_KEY tracing on/off" msgstr "" #: hsccmd.c:5793 msgid "mark frames unusable/usable" msgstr "" #: hsccmd.c:6128 msgid "HHCPN141E Missing argument\n" msgstr "" #: hsccmd.c:6136 #, c-format msgid "%s" msgstr "" #: hsccmd.c:6141 msgid "HHCPN142I No additional help available.\n" msgstr "" #: hscmisc.c:208 #, c-format msgid "DO_SHUTDOWN_NOW EXIT\n" msgstr "" #: hscmisc.c:210 impl.c:582 #, c-format msgid "HHCIN099I Hercules terminated\n" msgstr "" #: hscmisc.c:224 msgid "HHCIN098I Shutdown initiated\n" msgstr "" #: hscmisc.c:598 #, fuzzy, c-format msgid "HHCPN143E Invalid value: %s\n" msgstr "HHCPN143E Ongeldige waarde: %s\n" #: hscmisc.c:622 #, fuzzy, c-format msgid "HHCPN144E Invalid operand: %s\n" msgstr "HHCPN144E Ongeldig operand: %s\n" #: hscmisc.c:634 #, fuzzy, c-format msgid "HHCPN145E Invalid range: %s\n" msgstr "HHCPN145E Ongeldig bereik: %s\n" #: hscmisc.c:680 #, fuzzy, c-format msgid "HHCMS001E malloc failed for REGS copy: %s\n" msgstr "HHCCA006T %4.4X:Select fout: %s\n" #: hscmisc.c:895 #, c-format msgid "Storage not accessible code = %4.4X\n" msgstr "" #: hscmisc.c:903 hscmisc.c:912 msgid "Addressing exception\n" msgstr "" #: hscmisc.c:1126 #, c-format msgid "%sInstruction fetch error\n" msgstr "" #: httpserv.c:89 #, fuzzy, c-format msgid "HHCHT011E html_include: Cannot open %s: %s\n" msgstr "HHCHT011E html_include: Fout %2$s bij openen bestand \"%1$s\"\n" #: httpserv.c:91 #, c-format msgid "ERROR: Cannot open %s: %s\n" msgstr "FOUT: Kan %s niet openen: %s\n" #: httpserv.c:331 #, c-format msgid "HHCHT012I cgi_var_dump: pointer(%p) name(%s) value(%s) type(%d)\n" msgstr "" #: httpserv.c:650 #, fuzzy msgid "HHCHT001I HTTP listener thread started: tid=" msgstr "HHCCP012I Timer thread gestart: tid=%p, pid=%d\n" #: httpserv.c:689 httpserv.c:699 #, fuzzy, c-format msgid "HHCCF066E Invalid HTTPROOT: \"%s\": %s\n" msgstr "HHCCA018E %4.4X:Bind fout: %s\n" #: httpserv.c:710 #, c-format msgid "HHCHT013I Using HTTPROOT directory \"%s\"\n" msgstr "" #: httpserv.c:718 #, c-format msgid "HHCHT002E socket: %s\n" msgstr "" #: httpserv.c:741 #, c-format msgid "HHCHT003W Waiting for port %u to become free\n" msgstr "" #: httpserv.c:748 #, c-format msgid "HHCHT004E bind: %s\n" msgstr "" #: httpserv.c:757 #, c-format msgid "HHCHT005E listen: %s\n" msgstr "" #: httpserv.c:761 #, c-format msgid "HHCHT006I Waiting for HTTP requests on port %u\n" msgstr "" #: httpserv.c:779 #, c-format msgid "HHCHT007E select: %s\n" msgstr "" #: httpserv.c:791 #, c-format msgid "HHCHT008E accept: %s\n" msgstr "" #: httpserv.c:801 #, fuzzy, c-format msgid "HHCHT010E http_request create_thread: %s\n" msgstr "HHCPN119E Fout %2$s bij lezen van bestand \"%1$s\"\n" #: ieee.c:488 msgid "ebfpston: unexpectedly converting a NaN\n" msgstr "" #: ieee.c:492 msgid "ebfpston: unexpectedly converting an Infinite\n" msgstr "" #: ieee.c:547 msgid "lbfpston: unexpectedly converting a NaN\n" msgstr "" #: ieee.c:551 msgid "lbfpston: unexpectedly converting an Infinite\n" msgstr "" #: ieee.c:600 msgid "sbfpston: unexpectedly converting a NaN\n" msgstr "" #: ieee.c:604 msgid "sbfpston: unexpectedly converting an Infinite\n" msgstr "" #: impl.c:226 #, fuzzy, c-format msgid "HHCPN995E .RC file \"%s\" not found.\n" msgstr "HHCPN015E Ongeldig apparaat nummer\n" #: impl.c:340 #, c-format msgid "HHCIN008S DYNGUI.DLL load failed; Hercules terminated.\n" msgstr "" #: impl.c:411 #, c-format msgid "HHCIN001S Cannot register SIGINT handler: %s\n" msgstr "" #: impl.c:422 #, c-format msgid "HHCIN002E Cannot suppress SIGPIPE signal: %s\n" msgstr "" #: impl.c:461 #, c-format msgid "HHCIN003S Cannot register SIGILL/FPE/SEGV/BUS/USR handler: %s\n" msgstr "" #: impl.c:484 #, fuzzy, c-format msgid "HHCIN004S Cannot create watchdog thread: %s\n" msgstr "HHCPN119E Fout %2$s bij lezen van bestand \"%1$s\"\n" #: impl.c:498 #, c-format msgid "HHCIN005S Cannot create http_server thread: %s\n" msgstr "" #: impl.c:512 #, c-format msgid "HHCIN006S Cannot create shared_server thread: %s\n" msgstr "" #: impl.c:529 #, c-format msgid "HHCIN007S Cannot create %4.4X connection thread: %s\n" msgstr "" #: impl.c:580 #, c-format msgid "IMPL EXIT\n" msgstr "" #: ipl.c:219 #, fuzzy, c-format msgid "HHCCP027E Device %4.4X not in configuration%s\n" msgstr "HHCSD007I %s (%s) afgesloten van apparaat %4.4X (%s)\n" #: ipl.c:276 #, c-format msgid "" "HHCCP029E %s mode IPL failed: CSW status=%2.2X%2.2X\n" " Sense=" msgstr "" #: ipl.c:369 #, c-format msgid "HHCCP031E Load from %s failed: %s\n" msgstr "" #: ipl.c:428 #, c-format msgid "" "HHCCP030E %s mode IPL failed: Invalid IPL PSW: %2.2X%2.2X%2.2X%2.2X %2.2X%" "2.2X%2.2X%2.2X\n" msgstr "" #: ipl.c:592 #, c-format msgid "HHCCP033E load_main: %s: %s\n" msgstr "" #: ipl.c:602 msgid "HHCCP034W load_main: terminated at end of mainstor\n" msgstr "" #: logger.c:178 logger.c:378 msgid "HHCLG014I logger thread terminating\n" msgstr "" #: logger.c:206 #, fuzzy, c-format msgid "HHCLG003E Error writing hardcopy log: %s\n" msgstr "HHCLG003E Fout %s bij schrijven naar systeem log\n" #: logger.c:259 #, fuzzy, c-format msgid "HHCLG001E Error redirecting stdout: %s\n" msgstr "HHCPU004E Fout %2$s bij schrijven naar bestand \"%1$s\"\n" #: logger.c:298 #, c-format msgid "HHCLG002E Error reading syslog pipe: %s\n" msgstr "" #: logger.c:421 logger.c:433 #, c-format msgid "HHCLG004E Error duplicating stderr: %s\n" msgstr "" #: logger.c:443 #, c-format msgid "HHCLG005E Error duplicating stdout: %s\n" msgstr "" #: logger.c:453 #, c-format msgid "HHCLG006E Duplicate error redirecting hardcopy log: %s\n" msgstr "" #: logger.c:460 #, c-format msgid "HHCLG007S Hardcopy log fdopen failed: %s\n" msgstr "" #: logger.c:476 #, c-format msgid "HHCLG008S logbuffer malloc failed: %s\n" msgstr "" #: logger.c:483 #, c-format msgid "HHCLG009S Syslog message pipe creation failed: %s\n" msgstr "" #: logger.c:494 #, c-format msgid "HHCLG012E Cannot create logger thread: %s\n" msgstr "" #: logger.c:516 msgid "HHCLG014E log not active\n" msgstr "" #: logger.c:525 logger.c:527 #, c-format msgid "HHCLG015I log closed\n" msgstr "" #: logger.c:541 #, fuzzy, c-format msgid "HHCLG016E Error opening logfile %s: %s\n" msgstr "HHCRD013E Fout %2$s bij openen bestand \"%1$s\"\n" #: logger.c:549 #, fuzzy, c-format msgid "HHCLG017S log file fdopen failed for %s: %s\n" msgstr "HHCLC039E Fout %2$s bij openen bestand \"%1$s\"\n" #: logger.c:564 #, c-format msgid "HHCLG018I log switched to %s\n" msgstr "" #: machchk.c:250 msgid "HHCCP019I Machine Check code=%16.16" msgstr "" #: machchk.c:310 msgid "HHCCP020E signal USR2 received for undetermined device\n" msgstr "" #: machchk.c:315 #, c-format msgid "HHCCP021E signal USR2 received for device %4.4X\n" msgstr "" #: machchk.c:339 machchk.c:343 #, fuzzy, c-format msgid "HHCCP017I CPU%4.4X: Machine check due to host error: %s\n" msgstr "HHCCP007I CPU%4.4X Architectuur Modus %s\n" #: machchk.c:378 machchk.c:382 #, fuzzy, c-format msgid "HHCCP018I CPU%4.4X: Check-Stop due to host error: %s\n" msgstr "HHCCP007I CPU%4.4X Architectuur Modus %s\n" #: panel.c:1281 #, fuzzy msgid "HHCPN001I Control panel thread started: tid=" msgstr "HHCPN001I Controle paneel thread gestart: tid=%8.8lX, pid=%d\n" #: panel.c:1306 #, c-format msgid "HHCPN002S Cannot obtain keyboard buffer: %s\n" msgstr "" #: panel.c:1316 #, c-format msgid "HHCPN003S Cannot obtain message buffer: %s\n" msgstr "" #: panel.c:1377 #, c-format msgid "HHCPN004E select: %s\n" msgstr "" #: panel.c:1393 #, c-format msgid "HHCPN005E keyboard read: %s\n" msgstr "" #: printer.c:119 #, fuzzy, c-format msgid "HHCPR004E Error opening file %s: %s\n" msgstr "HHCPR004E Fout %2$s bij openen van bestand \"%1$s\"\n" #: printer.c:140 printer.c:165 #, c-format msgid "HHCPR006E %4.4X device initialization error: fork: %s\n" msgstr "" #: printer.c:146 printer.c:176 #, c-format msgid "HHCPR007I pipe receiver (pid=%d) starting for %4.4X\n" msgstr "" #: printer.c:156 #, c-format msgid "HHCPR005E %4.4X device initialization error: pipe: %s\n" msgstr "" #: printer.c:188 #, c-format msgid "HHCPR008E %4.4X dup2 error: %s\n" msgstr "" #: printer.c:210 printer.c:360 #, c-format msgid "HHCPR011I pipe receiver (pid=%d) terminating for %4.4X\n" msgstr "" #: printer.c:216 #, c-format msgid "HHCPR012E %4.4X Unable to execute %s: %s\n" msgstr "" #: printer.c:255 #, fuzzy, c-format msgid "HHCPR003E %4.4X Error writing to %s: %s\n" msgstr "HHCPR003E %$14.4X:Fout %3$s bij schrijven naar bestand \"%2$s\"\n" #: printer.c:257 msgid "incomplete" msgstr "" #: printer.c:275 #, c-format msgid "HHCPR001E File name missing or invalid for printer %4.4X\n" msgstr "" #: printer.c:304 #, c-format msgid "HHCPR002E Invalid argument for printer %4.4X: %s\n" msgstr "" #: service.c:104 #, fuzzy msgid "HHCCP036E SCP not receiving priority messages\n" msgstr "HHCCP036E SCP ontvangt geen prioriteits berichten\n" #: service.c:111 #, fuzzy msgid "HHCCP037E SCP not receiving commands\n" msgstr "HHCCP037E SCP ontvangt geen commando's\n" #: service.c:118 #, fuzzy msgid "HHCCP038E No SCP command\n" msgstr "HHCCP038E Geen SCP commando\n" #: service.c:129 msgid "HHCCP039E Service Processor busy\n" msgstr "" #: service.c:167 #, fuzzy msgid "HHCCP081E SCP not receiving quiesce signals\n" msgstr "HHCCP037E SCP ontvangt geen commando's\n" #: service.c:178 msgid "HHCCP082E Service Processor busy\n" msgstr "" #: service.c:933 #, c-format msgid "HHCCP040I CPI: System Type: %s Name: %s Sysplex: %s\n" msgstr "" #: service.c:937 msgid "HHC770I Control Program Information:\n" msgstr "" #: service.c:938 #, c-format msgid "HHC771I System Type = %s\n" msgstr "" #: service.c:939 #, c-format msgid "HHC772I System Name = %s\n" msgstr "" #: service.c:940 #, c-format msgid "HHC773I Sysplex Name = %s\n" msgstr "" #: service.c:941 msgid "HHC774I System Level = %16.16" msgstr "" #: service.c:1174 #, fuzzy msgid "HHCCP041I SYSCONS interface active\n" msgstr "HHCCP041I SYSCONS interface actief\n" #: service.c:1176 #, fuzzy msgid "HHCCP042I SYSCONS interface inactive\n" msgstr "HHCCP042I SYSCONS interface inactief\n" #: service.c:1300 #, c-format msgid "CPU%4.4X: Vector Facility configured offline\n" msgstr "" #: service.c:1331 #, c-format msgid "CPU%4.4X: Vector Facility configured online\n" msgstr "" #: shared.c:222 #, c-format msgid "HHCSH001S parameter %d is invalid: %s\n" msgstr "" #: shared.c:248 #, c-format msgid "HHCSH002W %4.4X connect pending to %s\n" msgstr "" #: shared.c:266 #, c-format msgid "HHCSH003S %4.4X Error retrieving cylinders\n" msgstr "" #: shared.c:279 #, c-format msgid "HHCSH004S %4.4X Error retrieving device characteristics\n" msgstr "" #: shared.c:297 #, c-format msgid "HHCSH005S %4.4X Remote device %4.4X is a %4.4X\n" msgstr "" #: shared.c:309 #, c-format msgid "HHCSH006S %4.4X Error retrieving device id\n" msgstr "" #: shared.c:326 #, c-format msgid "HHCSH007S %4.4X device type %4.4X not found in dasd table\n" msgstr "" #: shared.c:338 #, c-format msgid "HHCSH008S %4.4X control unit %s not found in dasd table\n" msgstr "" #: shared.c:359 #, c-format msgid "HHCSH009I %s cyls=%d heads=%d tracks=%d trklen=%d\n" msgstr "" #: shared.c:470 #, c-format msgid "HHCSH010S parameter %d is invalid: %s\n" msgstr "" #: shared.c:496 #, c-format msgid "HHCSH011I %4.4X connect pending to %s\n" msgstr "" #: shared.c:511 #, c-format msgid "HHCSH012S %4.4X Error retrieving fba origin\n" msgstr "" #: shared.c:523 #, c-format msgid "HHCSH013S %4.4X Error retrieving fba number blocks\n" msgstr "" #: shared.c:535 #, c-format msgid "HHCSH014S %4.4X Error retrieving fba block size\n" msgstr "" #: shared.c:549 #, c-format msgid "HHCSH015S %4.4X Error retrieving device id\n" msgstr "" #: shared.c:558 #, c-format msgid "HHCSH016S %4.4X Remote device %4.4X is a %4.4X\n" msgstr "" #: shared.c:570 #, c-format msgid "HHCSH017S %4.4X Error retrieving device characteristics\n" msgstr "" #: shared.c:587 #, c-format msgid "HHCSH018S %4.4X device type %4.4X not found in dasd table\n" msgstr "" #: shared.c:596 #, c-format msgid "HHCSH019I %s origin=%d blks=%d\n" msgstr "" #: shared.c:641 #, c-format msgid "HHCSH020E %4.4X error during channel program start\n" msgstr "" #: shared.c:698 #, c-format msgid "HHCSH021E %4.4X error during channel program end\n" msgstr "" #: shared.c:803 #, c-format msgid "HHCSH022E %4.4X error reading track %d\n" msgstr "" #: shared.c:815 #, c-format msgid "HHCSH023E %4.4X error reading track %d\n" msgstr "" #: shared.c:1015 #, c-format msgid "HHCSH024E %4.4X error reading block group %d\n" msgstr "" #: shared.c:1028 #, c-format msgid "HHCSH025E %4.4X error reading block group %d\n" msgstr "" #: shared.c:1116 #, c-format msgid "HHCSH026E %4.4X Error retrieving usage information\n" msgstr "" #: shared.c:1187 #, c-format msgid "HHCSH027E %4.4X error writing track %d\n" msgstr "" #: shared.c:1200 #, c-format msgid "HHCSH028E %4.4X remote error writing track %d: %2.2X-%2.2X\n" msgstr "" #: shared.c:1285 #, c-format msgid "HHCSH029E %4.4X socket failed: %s\n" msgstr "" #: shared.c:1301 #, c-format msgid "HHCSH030E %4.4X socket failed: %s\n" msgstr "" #: shared.c:1319 #, c-format msgid "HHCSH031I %4.4X Connected to %s\n" msgstr "" #: shared.c:1353 #, c-format msgid "HHCSH032E %4.4X Connect %s %d: %s\n" msgstr "" #: shared.c:1524 #, c-format msgid "HHCSH033E %4.4X send error %d for %2.2X-%2.2X: %s\n" msgstr "" #: shared.c:1551 #, c-format msgid "HHCSH034E %4.4X Not connected to %s\n" msgstr "" #: shared.c:1561 #, c-format msgid "HHCSH035E %4.4X recv error %d: %s\n" msgstr "" #: shared.c:1573 #, c-format msgid "HHCSH036E %4.4X Remote error %2.2X-%2.2X: %s\n" msgstr "" #: shared.c:1679 #, c-format msgid "HHCSH037E uncompress error %d, off %d len %d\n" msgstr "" #: shared.c:1684 msgid "HHCSH038E data compressed using libz, unsupported\n" msgstr "" #: shared.c:1702 #, c-format msgid "HHCSH039E decompress error %d, off %d len %d\n" msgstr "" #: shared.c:1707 msgid "HHCSH040E data compressed using bzip2, unsupported\n" msgstr "" #: shared.c:2282 #, c-format msgid "HHCSH041E %4.4X send error %d id=%d: %s\n" msgstr "" #: shared.c:2321 #, c-format msgid "HHCSH042W %4.4X busy client being removed id=%d %s\n" msgstr "" #: shared.c:2353 #, c-format msgid "HHCSH043I %s disconnected from %4.4X id=%d\n" msgstr "" #: shared.c:2424 #, c-format msgid "HHCSH0474 %s connect failed\n" msgstr "" #: shared.c:2502 #, c-format msgid "HHCSH053I %s connected to %4.4X id=%d\n" msgstr "" #: shared.c:2518 #, fuzzy, c-format msgid "HHCSH045I Shared device %4.4X thread started: tid=" msgstr "HHCCP002I CPU%4.4X thread al gestart\n" #: shared.c:2587 #, c-format msgid "HHCSH046E select: %s\n" msgstr "" #: shared.c:2621 #, c-format msgid "HHCSH047E %4.4X %s recv error id=%d\n" msgstr "" #: shared.c:2652 #, c-format msgid "HHCSH048I Shared device %4.4X thread stopping\n" msgstr "" #: shared.c:2719 #, c-format msgid "HHCSH049I Shared device %d.%d thread started: tid=" msgstr "" #: shared.c:2728 #, c-format msgid "HHCSH050E inet socket: %s\n" msgstr "" #: shared.c:2737 #, c-format msgid "HHCSH051W unix socket: %s\n" msgstr "" #: shared.c:2760 #, c-format msgid "HHCSH052W Waiting for port %u to become free\n" msgstr "" #: shared.c:2767 #, c-format msgid "HHCSH053E inet bind: %s\n" msgstr "" #: shared.c:2785 #, c-format msgid "HHCSH054W unix bind: %s\n" msgstr "" #: shared.c:2797 #, c-format msgid "HHCSH055E inet listen: %s\n" msgstr "" #: shared.c:2808 #, c-format msgid "HHCSH056W unix listen: %s\n" msgstr "" #: shared.c:2821 #, c-format msgid "HHCSH057I Waiting for shared device requests on port %u\n" msgstr "" #: shared.c:2841 #, c-format msgid "HHCSH058E select: %s\n" msgstr "" #: shared.c:2859 #, c-format msgid "HHCSH059E accept: %s\n" msgstr "" #: shared.c:2866 #, c-format msgid "HHCSH060E malloc size %d: %s\n" msgstr "" #: shared.c:2877 #, c-format msgid "HHCSH061E serverConnect create_thread: %s\n" msgstr "" #: shared.c:2916 msgid "HHCSH062E Invalid or missing argument 1\n" msgstr "" #: shared.c:2925 msgid "HHCSH063E Invalid or missing keyword 2\n" msgstr "" #: shared.c:2943 #, c-format msgid "HHCSH064E Invalid or missing value %s\n" msgstr "" #: shared.c:2959 #, c-format msgid "HHCSH065E calloc() size=%d: %s\n" msgstr "" #: shared.c:2985 #, c-format msgid "HHCSH066E Invalid or missing keyword %s\n" msgstr "" #: shared.c:3060 shared.c:3067 msgid "HHCSH999E OPTION_SHARED_DEVICES not defined" msgstr "" #: sie.c:292 msgid "SIE: state descriptor " msgstr "" #: sie.c:317 #, fuzzy, c-format msgid "HHCCP079E CPU%4.4X: calloc failed for sie regs: %s\n" msgstr "HHCCP007I CPU%4.4X Architectuur Modus %s\n" #: sie.c:421 #, c-format msgid "SIE: zone %d: mso=" msgstr "" #: sie.c:735 #, c-format msgid "SIE: interception code %d\n" msgstr "" #: sockdev.c:81 msgid "HHCSD024E This build does not support Unix domain sockets.\n" msgstr "" #: sockdev.c:92 #, c-format msgid "HHCSD008E Socket pathname \"%s\" exceeds limit of %d\n" msgstr "" #: sockdev.c:103 #, c-format msgid "HHCSD009E Error creating socket for %s: %s\n" msgstr "" #: sockdev.c:116 #, c-format msgid "HHCSD010E Failed to bind or listen on socket %s: %s\n" msgstr "" #: sockdev.c:169 #, c-format msgid "HHCSD011E Failed to determine IP address from %s\n" msgstr "" #: sockdev.c:187 #, c-format msgid "HHCSD012E Failed to determine port number from %s\n" msgstr "" #: sockdev.c:199 #, c-format msgid "HHCSD013E Error creating socket for %s: %s\n" msgstr "" #: sockdev.c:211 #, c-format msgid "HHCSD014E Failed to bind or listen on socket %s: %s\n" msgstr "" #: sockdev.c:285 #, c-format msgid "" "HHCSD015E Connect to device %4.4X (%s) rejected; device busy or interrupt " "pending\n" msgstr "" #: sockdev.c:296 #, c-format msgid "" "HHCSD016E Connect to device %4.4X (%s) rejected; client %s (%s) still " "connected\n" msgstr "" #: sockdev.c:310 #, fuzzy, c-format msgid "HHCSD017E Connect to device %4.4X (%s) failed: %s\n" msgstr "HHCSD017E %s (%s) afgesloten van apparaat %4.4X (%s)\n" #: sockdev.c:336 #, fuzzy, c-format msgid "HHCSD018I %s (%s) connected to device %4.4X (%s)\n" msgstr "HHCSD018I %s (%s) afgesloten van apparaat %4.4X (%s)\n" #: sockdev.c:341 #, c-format msgid "HHCSD019I connected to device %4.4X (%s)\n" msgstr "" #: sockdev.c:416 #, fuzzy msgid "HHCSD020I Socketdevice listener thread started: tid=" msgstr "HHCCP012I Timer thread gestart: tid=%p, pid=%d\n" #: sockdev.c:444 #, fuzzy, c-format msgid "HHCSD021E select failed; errno=%d: %s\n" msgstr "HHCCL071E Fout %2$s bij lezan van bestand \"%1$s\"\n" #: sockdev.c:453 msgid "HHCSD022I Socketdevice listener thread terminated\n" msgstr "" #: sockdev.c:478 #, c-format msgid "HHCSD001E Device %4.4X already bound to socket %s\n" msgstr "" #: sockdev.c:487 #, c-format msgid "HHCSD002E bind_device malloc() failed for device %4.4X\n" msgstr "" #: sockdev.c:495 #, fuzzy, c-format msgid "HHCSD003E bind_device strdup() failed for device %4.4X\n" msgstr "HHCSD006E %s (%s) afgesloten van apparaat %4.4X (%s)\n" #: sockdev.c:533 #, fuzzy, c-format msgid "HHCSD023E Cannot create socketdevice thread: errno=%d: %s\n" msgstr "HHCPN119E Fout %2$s bij lezen van bestand \"%1$s\"\n" #: sockdev.c:548 #, c-format msgid "HHCSD004I Device %4.4X bound to socket %s\n" msgstr "" #: sockdev.c:568 #, c-format msgid "HHCSD005E Device %4.4X not bound to any socket\n" msgstr "" #: sockdev.c:576 #, fuzzy, c-format msgid "HHCSD006E Client %s (%s) still connected to device %4.4X (%s)\n" msgstr "HHCSD006E %s (%s) afgesloten van apparaat %4.4X (%s)\n" #: sockdev.c:588 #, fuzzy, c-format msgid "HHCSD007I Device %4.4X unbound from socket %s\n" msgstr "HHCSD007I %s (%s) afgesloten van apparaat %4.4X (%s)\n" #: stack.c:410 msgid "stack: Current stack entry at " msgstr "" #: stack.c:411 stack.c:450 stack.c:783 stack.c:796 stack.c:860 stack.c:899 #, c-format msgid "stack: et=%2.2X si=%2.2X rfs=%2.2X%2.2X nes=%2.2X%2.2X\n" msgstr "" #: stack.c:433 msgid "stack: Forward section header addr " msgstr "" #: stack.c:495 stack.c:782 msgid "stack: New stack entry at " msgstr "" #: stack.c:512 stack.c:520 stack.c:1163 stack.c:1171 #, c-format msgid "stack: GPR%d=" msgstr "" #: stack.c:544 stack.c:753 stack.c:1209 #, c-format msgid "stack: AR%d=" msgstr "" #: stack.c:566 #, c-format msgid "" "stack: PKM=%2.2X%2.2X SASN=%2.2X%2.2X EAX=%2.2X%2.2X PASN=%2.2X%2.2X \n" "stored at V:" msgstr "" #: stack.c:620 #, c-format msgid "stack: PSW=%2.2X%2.2X%2.2X%2.2X %2.2X%2.2X%2.2X%2.2X stored at V:" msgstr "" #: stack.c:698 #, c-format msgid "stack: PSW2=%2.2X%2.2X%2.2X%2.2X %2.2X%2.2X%2.2X%2.2X stored at V:" msgstr "" #: stack.c:725 #, c-format msgid "" "stack: SASTEIN=%2.2X%2.2X%2.2X%2.2X PASTEIN=%2.2X%2.2X%2.2X%2.2X \n" "stored at V:" msgstr "" #: stack.c:794 msgid "stack: Previous stack entry updated at A:" msgstr "" #: stack.c:805 stack.c:1421 msgid "stack: CR15=" msgstr "" #: stack.c:859 stack.c:883 msgid "stack: Stack entry located at " msgstr "" #: stack.c:1138 #, c-format msgid "stack: Unstacking registers %d-%d from " msgstr "" #: stack.c:1303 #, c-format msgid "" "stack: PKM=%2.2X%2.2X SASN=%2.2X%2.2X EAX=%2.2X%2.2X PASN=%2.2X%2.2X \n" "loaded from V:" msgstr "" #: stack.c:1340 #, c-format msgid "stack: PSW=%2.2X%2.2X%2.2X%2.2X %2.2X%2.2X%2.2X%2.2X loaded from V:" msgstr "" #: stack.c:1384 #, c-format msgid "" "stack: SASTEIN=%2.2X%2.2X%2.2X%2.2X PASTEIN=%2.2X%2.2X%2.2X%2.2X \n" "loaded from V:" msgstr "" #: tapecopy.c:39 #, c-format msgid "HHCTC017E SCSI tape not supported with this build\n" msgstr "" #: tapecopy.c:132 #, c-format msgid "HHCTC000I Abnormal termination\n" msgstr "" #: tapecopy.c:146 #, c-format msgid "HHCTC015I %s status: %8.8lX" msgstr "" #: tapecopy.c:171 #, c-format msgid "" "\n" "Copies a SCSI tape to or from an AWSTAPE disk file.\n" "\n" "Tapecopy reads a SCSI tape and outputs an AWSTAPE file representation\n" "of the tape, or else reads an AWSTAPE file and creates an identical copy\n" "of its contents on a tape mounted on a SCSI tape drive.\n" "\n" "Usage:\n" "\n" " tapecopy [tapedrive] [awsfile] or\n" " tapecopy [awsfile] [tapedrive]\n" "\n" "Where:\n" "\n" " tapedrive specifies the device filename of the SCSI tape drive.\n" " Must begin with /dev to be recognized.\n" " awsfile specifies the filename of the AWSTAPE disk file.\n" "\n" "The first filename is the input; the second is the output.\n" "\n" "If the input file is a SCSI tape, it is read and processed until physical " "EOD\n" "(end-of-data) is reached (i.e. it does not stop whenever multiple tapemarks " "or\n" "filemarks are read; it continues processing until the SCSI tape drive says\n" "there is no more data on the tape). The resulting AWSTAPE output disk file,\n" "when specified for the filename on a Hercules tape device configuration\n" "statement, can then be used instead in order for the Hercules guest O/S to\n" "read the exact same data without having to have a SCSI tape drive " "physically\n" "attached to the host system. This allows you to easily transfer SCSI tape " "data\n" "to other systems that may not have SCSI tape drives attached to them.\n" "\n" "The possible return codes and their meaning are:\n" "\n" " %2d Successful completion.\n" " %2d Invalid arguments or no arguments given.\n" " %2d Unable to open SCSI tape drive device file.\n" " %2d Unable to open AWSTAPE disk file.\n" " %2d Unrecoverable I/O error setting variable length block\n" " processing for SCSI tape device.\n" " %2d Unrecoverable I/O error rewinding SCSI tape device.\n" " %2d Unrecoverable I/O error obtaining status of SCSI device.\n" " %2d Unrecoverable I/O error reading block header\n" " from AWSTAPE disk file.\n" " %2d AWSTAPE block size too large.\n" " %2d Unrecoverable I/O error reading data block.\n" " %2d Unrecoverable I/O error writing tapemark.\n" " %2d Unrecoverable I/O error writing block header\n" " to AWSTAPE disk file.\n" " %2d Unrecoverable I/O error writing data block.\n" "\n" msgstr "" #: tapecopy.c:266 #, fuzzy, c-format msgid "HHCTC016E Error reading status of %s: rc=%d, errno=%d: %s\n" msgstr "HHCTC016E Fout %2$s bij lezen van bestand \"%1$s\"\n" #: tapecopy.c:295 #, fuzzy, c-format msgid "HHCTC011I End of tape.\n" msgstr "HHCDL090I Einde van directory\n" #: tapecopy.c:299 #, fuzzy, c-format msgid "HHCTC008E Error reading %s: errno=%d: %s\n" msgstr "HHCTC002E Fout %2$s bij lezen van bestand \"%1$s\"\n" #: tapecopy.c:325 #, fuzzy, c-format msgid "HHCTC018I End of AWSTAPE input file.\n" msgstr "HHCDL090I Einde van directory\n" #: tapecopy.c:330 #, fuzzy, c-format msgid "HHCTC019E Error reading AWSTAPE header from %s: rc=%d, errno=%d: %s\n" msgstr "HHCTC016E Fout %2$s bij lezen van bestand \"%1$s\"\n" #: tapecopy.c:346 #, c-format msgid "HHCTC020E AWSTAPE block too large on %s: block size=%d, maximum=%d\n" msgstr "" #: tapecopy.c:355 #, fuzzy, c-format msgid "HHCTC021E Error reading data block from %s: rc=%d, errno=%d: %s\n" msgstr "HHCTC016E Fout %2$s bij lezen van bestand \"%1$s\"\n" #: tapecopy.c:380 #, fuzzy, c-format msgid "HHCTC022E Error writing data block to %s: rc=%d, errno=%d: %s\n" msgstr "HHCTC010E Fout %2$s bij schrijven naar bestand \"%1$s\"\n" #: tapecopy.c:414 #, fuzzy, c-format msgid "HHCTC013E Error writing AWSTAPE header on %s: rc=%d, errno=%d: %s\n" msgstr "HHCTC013I Fout %2$s bij lezen van bestand \"%1$s\"\n" #: tapecopy.c:425 #, fuzzy, c-format msgid "HHCTC014E Error writing data block to %s: rc=%d, errno=%d: %s\n" msgstr "HHCTC014I Fout %2$s bij schrijven naar bestand \"%1$s\"\n" #: tapecopy.c:448 #, fuzzy, c-format msgid "HHCTC023E Error writing tapemark on %s: rc=%d, errno=%d: %s\n" msgstr "HHCTC013I Fout %2$s bij lezen van bestand \"%1$s\"\n" #: tapecopy.c:476 #, fuzzy, c-format msgid "HHCTC010E Error writing tapemark on %s: rc=%d, errno=%d, %s\n" msgstr "HHCTC010E Fout %2$s bij schrijven naar bestand \"%1$s\"\n" #: tapecopy.c:601 #, fuzzy, c-format msgid "HHCTC001E Error opening %s: errno=%d: %s\n" msgstr "HHCTC001E Fout %2$s bij openen bestand \"%1$s\"\n" #: tapecopy.c:614 #, fuzzy, c-format msgid "HHCTC005E Error setting attributes for %s: rc=%d, errno=%d: %s\n" msgstr "HHCTC002E Fout %2$s bij lezen van bestand \"%1$s\"\n" #: tapecopy.c:627 tapecopy.c:884 #, fuzzy, c-format msgid "HHCTC006E Error rewinding %s: rc=%d, errno=%d: %s\n" msgstr "HHCTC010E Fout %2$s bij schrijven naar bestand \"%1$s\"\n" #: tapecopy.c:644 #, c-format msgid "HHCTC003I %s device type: %s\n" msgstr "" #: tapecopy.c:647 #, c-format msgid "HHCTC003I %s device type: 0x%lX\n" msgstr "" #: tapecopy.c:657 #, c-format msgid "HHCTC004I %s tape density: %s\n" msgstr "" #: tapecopy.c:660 #, c-format msgid "HHCTC004I %s tape density code: 0x%lX\n" msgstr "" #: tapecopy.c:680 #, fuzzy, c-format msgid "HHCTC007E Error opening %s: errno=%d: %s\n" msgstr "HHCTC001E Fout %2$s bij openen bestand \"%1$s\"\n" #: tapecopy.c:779 msgid "HHCTC009I File %u: Blocks=%u, Bytes=%" msgstr "" #: tapecopy.c:792 #, c-format msgid " (tapemark)\n" msgstr "" #: tapecopy.c:827 #, c-format msgid "HHCTC012I %s\n" msgstr "" #: tapecopy.c:836 #, c-format msgid "File %u: Block %u\r" msgstr "" #: tapecopy.c:856 msgid "" "HHCTC000I Successful completion;\n" " Bytes read: %" msgstr "" #: tapecopy.c:868 msgid " Bytes written: %" msgstr "" #: tapedev.c:437 #, c-format msgid "HHCTA996I %4.4x - AWS Tape %s closed\n" msgstr "" #: tapedev.c:523 #, fuzzy, c-format msgid "HHCTA001E Error opening %s: %s\n" msgstr "HHCTA001E Fout %2$s bij openen bestand \"%1$s\"\n" #: tapedev.c:555 tapedev.c:718 #, c-format msgid "HHCTA002E Error seeking to offset %8.8lX in file %s: %s\n" msgstr "" #: tapedev.c:570 #, c-format msgid "HHCTA003E Error reading block header at offset %8.8lX in file %s: %s\n" msgstr "" #: tapedev.c:582 #, c-format msgid "" "HHCTA004E End of file (uninitialized tape) at offset %8.8lX in file %s\n" msgstr "" #: tapedev.c:594 #, c-format msgid "" "HHCTA004E Unexpected end of file in block header at offset %8.8lX in file %" "s\n" msgstr "" #: tapedev.c:651 #, c-format msgid "HHCTA003E Error reading data block at offset %8.8lX in file %s: %s\n" msgstr "" #: tapedev.c:665 #, c-format msgid "" "HHCTA004E Unexpected end of file in data block at offset %8.8lX in file %s\n" msgstr "" #: tapedev.c:753 tapedev.c:780 #, c-format msgid "HHCTA995E Media full condition reached at offset %8.8lX in file %s\n" msgstr "" #: tapedev.c:759 #, c-format msgid "HHCTA009E Error writing block header at offset %8.8lX in file %s: %s\n" msgstr "" #: tapedev.c:786 tapedev.c:804 #, c-format msgid "HHCTA010E Error writing data block at offset %8.8lX in file %s: %s\n" msgstr "" #: tapedev.c:856 #, c-format msgid "HHCTA011E Error seeking to offset %8.8lX in file %s: %s\n" msgstr "" #: tapedev.c:887 #, c-format msgid "HHCTA012E Error writing block header at offset %8.8lX in file %s: %s\n" msgstr "" #: tapedev.c:908 #, fuzzy, c-format msgid "HHCTA017E Error writing tape mark at offset %8.8lX in file %s: %s\n" msgstr "HHCTC013I Fout %2$s bij lezen van bestand \"%1$s\"\n" #: tapedev.c:1141 #, c-format msgid "HHCTA013E Error opening %s: %s(%s)\n" msgstr "" #: tapedev.c:1189 #, c-format msgid "HHCTA075E Error seeking to start of %s: %s(%s)\n" msgstr "" #: tapedev.c:1227 #, c-format msgid "HHCTA014E End of file (uninitialized tape) at block %8.8X in file %s\n" msgstr "" #: tapedev.c:1236 #, c-format msgid "HHCTA015E Error reading data block at block %8.8X in file %s: %s(%s)\n" msgstr "" #: tapedev.c:1278 #, c-format msgid "HHCTA016E Error writing data block at block %8.8X in file %s: %s(%s)\n" msgstr "" #: tapedev.c:1294 msgid "TAPE EOT Handling: max capacity exceeded\n" msgstr "" #: tapedev.c:1297 msgid "TAPE EOT Handling: max capacity enforced\n" msgstr "" #: tapedev.c:1330 #, c-format msgid "HHCTA017E Error writing tape mark at block %8.8X in file %s: %s(%s)\n" msgstr "" #: tapedev.c:1372 #, c-format msgid "HHCTA018E Error forward spacing at block %8.8X in file %s: %s(%s)\n" msgstr "" #: tapedev.c:1427 #, c-format msgid "HHCTA019E Error reading data block at block %8.8X in file %s: %s(%s)\n" msgstr "" #: tapedev.c:1459 #, c-format msgid "" "HHCTA020E Error forward spacing to next file at block %8.8X in file %s: %s(%" "s)\n" msgstr "" #: tapedev.c:1524 #, c-format msgid "" "HHCTA021E Error back spacing to previous file at block %8.8X in file %s:\n" " %s(%s)\n" msgstr "" #: tapedev.c:1578 #, c-format msgid "" "HHC232I Invalid filename %s: TDF files must be in the TAPES subdirectory\n" msgstr "" #: tapedev.c:1591 #, c-format msgid "HHCTA039E Error opening TDF file %s: %s\n" msgstr "" #: tapedev.c:1600 #, c-format msgid "HHCTA040E %s fstat error: %s\n" msgstr "" #: tapedev.c:1611 #, c-format msgid "HHCTA041E Cannot obtain buffer for TDF file %s: %s\n" msgstr "" #: tapedev.c:1621 #, c-format msgid "HHCTA042E Error reading TDF file %s: %s\n" msgstr "" #: tapedev.c:1634 #, c-format msgid "HHCTA043E %s is not a valid TDF file\n" msgstr "" #: tapedev.c:1653 #, c-format msgid "HHCTA044E Cannot obtain buffer for TDF array: %s\n" msgstr "" #: tapedev.c:1702 #, c-format msgid "HHCTA045E Filename or format missing in line %d of file %s\n" msgstr "" #: tapedev.c:1714 #, c-format msgid "HHCTA046E Filename %s too long in line %d of file %s\n" msgstr "" #: tapedev.c:1766 #, c-format msgid "HHCTA047E RECSIZE keyword missing in line %d of file %s\n" msgstr "" #: tapedev.c:1779 #, c-format msgid "HHCTA048E Invalid record size %s in line %d of file %s\n" msgstr "" #: tapedev.c:1793 #, c-format msgid "HHCTA049E Invalid record format %s in line %d of file %s\n" msgstr "" #: tapedev.c:1850 #, c-format msgid "HHCTA050E Attempt to access beyond end of tape %s\n" msgstr "" #: tapedev.c:1886 #, fuzzy, c-format msgid "HHCTA051E Error opening %s: %s\n" msgstr "HHCTA051E Fout %2$s bij openen bestand \"%1$s\"\n" #: tapedev.c:1929 #, c-format msgid "HHCTA052E Error seeking to offset %8.8lX in file %s: %s\n" msgstr "" #: tapedev.c:1944 #, c-format msgid "HHCTA053E Error reading block header at offset %8.8lX in file %s: %s\n" msgstr "" #: tapedev.c:1957 #, c-format msgid "" "HHCTA054E Unexpected end of file in block header at offset %8.8lX in file %" "s\n" msgstr "" #: tapedev.c:1980 #, c-format msgid "HHCTA055E Invalid block header at offset %8.8lX in file %s\n" msgstr "" #: tapedev.c:2047 #, c-format msgid "HHCTA056E Error reading data block at offset %8.8lX in file %s: %s\n" msgstr "" #: tapedev.c:2060 #, c-format msgid "" "HHCTA057E Unexpected end of file in data block at offset %8.8lX in file %s\n" msgstr "" #: tapedev.c:2098 #, c-format msgid "HHCTA058E Error seeking to offset %8.8lX in file %s: %s\n" msgstr "" #: tapedev.c:2113 #, c-format msgid "HHCTA059E Error reading data block at offset %8.8lX in file %s: %s\n" msgstr "" #: tapedev.c:2172 #, c-format msgid "HHCTA060E Error seeking to offset %8.8lX in file %s: %s\n" msgstr "" #: tapedev.c:2229 #, c-format msgid "HHCTA061E Error reading data block at offset %8.8lX in file %s: %s\n" msgstr "" #: tapedev.c:2241 #, c-format msgid "" "HHCTA062E Unexpected end of file in data block at offset %8.8lX in file %s\n" msgstr "" #: tapedev.c:2253 #, c-format msgid "HHCTA063E Invalid zero length block at offset %8.8lX in file %s\n" msgstr "" #: tapedev.c:2426 #, c-format msgid "HHCTA064E Error seeking to end of file %s: %s\n" msgstr "" #: tapedev.c:2556 #, c-format msgid "HHCTA065E Error seeking to end of file %s: %s\n" msgstr "" #: tapedev.c:2911 #, fuzzy, c-format msgid "HHCTA100I %4.4X: Now Displays: %s\n" msgstr "HHCCA006T %4.4X:Select fout: %s\n" #: tapedev.c:3116 #, c-format msgid "AutoMount: %s%s scratch tape being auto-unloaded on %4.4X = %s\n" msgstr "" #: tapedev.c:3120 #, c-format msgid "AutoMount: %s%s tape volume \"%s\" being auto-unloaded on %4.4X = %s\n" msgstr "" #: tapedev.c:3127 #, c-format msgid "AutoMount: %s%s scratch tape being auto-loaded on %4.4X = %s\n" msgstr "" #: tapedev.c:3131 #, c-format msgid "AutoMount: %s%s tape volume \"%s\" being auto-loaded on %4.4X = %s\n" msgstr "" #: tapedev.c:3150 #, c-format msgid "" "\n" "%s\n" "AUTOMOUNT: Unmount %sof %s%s scratch tape requested on %4.4X = %s\n" "%s\n" "\n" msgstr "" #: tapedev.c:3159 #, c-format msgid "" "\n" "%s\n" "AUTOMOUNT: Unmount %sof %s%s tape volume \"%s\" requested on %4.4X = %s\n" "%s\n" "\n" msgstr "" #: tapedev.c:3171 #, c-format msgid "" "\n" "%s\n" "AUTOMOUNT: Mount for %s%s scratch tape requested on %4.4X = %s\n" "%s\n" "\n" msgstr "" #: tapedev.c:3177 #, c-format msgid "" "\n" "%s\n" "AUTOMOUNT: Mount for %s%s tape volume \"%s\" requested on %4.4X = %s\n" "%s\n" "\n" msgstr "" #: tapedev.c:3266 #, fuzzy, c-format msgid "HHCTA099I %4.4X: Tape Display \"%s\" Until Unmounted\n" msgstr "HHCCA006T %4.4X:Select fout: %s\n" #: tapedev.c:3292 #, fuzzy, c-format msgid "HHCTA099I %4.4X: Tape Display \"%s\" Until Mounted\n" msgstr "HHCCA006T %4.4X:Select fout: %s\n" #: tapedev.c:3345 #, c-format msgid "" "HHCTA099I %4.4X: Tape Display \"%s\" Until Unmounted, then \"%s\" Until " "Mounted\n" msgstr "" #: tapedev.c:3354 #, fuzzy, c-format msgid "HHCTA099I %4.4X: Tape \"%s\" Until Mounted\n" msgstr "HHCPN015E Ongeldig apparaat nummer\n" #: tapedev.c:4024 #, c-format msgid "" "HHCTA999E Device %4.4X: Unable to determine tape format type for %s: " "Internal error: Regcomp error %s on index %d\n" msgstr "" #: tapedev.c:4039 #, c-format msgid "" "HHCTA999E Device %4.4X: Unable to determine tape format type for %s: " "Internal error: Regexec error %s on index %d\n" msgstr "" #: tapedev.c:4085 #, c-format msgid "HHCTA999E Device %4.4X: Unable to determine tape format type for %s\n" msgstr "" #: tapedev.c:4095 #, fuzzy, c-format msgid "HHCTA998I Device %4.4X: %s is a %s\n" msgstr "HHCCA018E %4.4X:Bind fout: %s\n" #: tapedev.c:4124 #, fuzzy, c-format msgid "HHCTA066I %s device %4.4X parameter: '%s'\n" msgstr "HHCPN015E Ongeldig apparaat nummer\n" #: tapedev.c:4128 #, fuzzy, c-format msgid "HHCTA067E Device %4.4X: %s - Unrecognized parameter: '%s'\n" msgstr "HHCPN130E Ongeldig frame adres %8.8X\n" #: tapedev.c:4136 tapedev.c:4148 tapedev.c:4158 tapedev.c:4175 tapedev.c:4192 #: tapedev.c:4209 tapedev.c:4219 tapedev.c:4229 tapedev.c:4239 tapedev.c:4249 #: tapedev.c:4259 tapedev.c:4270 tapedev.c:4281 tapedev.c:4291 #, c-format msgid "HHCTA078E Option '%s' not valid for SCSI tape\n" msgstr "" #: tapedev.c:4164 #, c-format msgid "HHCTA068E Method must be within %u-%u\n" msgstr "" #: tapedev.c:4181 #, c-format msgid "HHCTA069E Level must be within %u-%u\n" msgstr "" #: tapedev.c:4198 #, c-format msgid "HHCTA070E Chunksize must be within %u-%u\n" msgstr "" #: tapedev.c:4302 tapedev.c:4313 #, c-format msgid "HHCTA078E Option '%s' not valid for %s\n" msgstr "" #: tapedev.c:4323 #, c-format msgid "HHCTA071E Error in '%s' parameter\n" msgstr "" #: tapedev.c:4371 #, c-format msgid "TAPE Autoloader - Adding global parm %s\n" msgstr "" #: tapedev.c:4441 #, c-format msgid "TAPE Autoloader: Adding tape entry %s\n" msgstr "" #: tapedev.c:4490 #, c-format msgid "TAPE: Autoloader file request fn=%s\n" msgstr "" #: tapedev.c:4778 #, c-format msgid "Unsupported device type specified %4.4x\n" msgstr "" #: tapedev.c:5239 #, c-format msgid "HHCTA072E Data chaining not supported for CCW %2.2X\n" msgstr "" #: tapedev.c:5958 msgid "HHCTA081I Locate block 0x%8.8" msgstr "" #: timer.c:195 #, fuzzy, c-format msgid "HHCTT001W Timer thread set priority %d failed: %s\n" msgstr "HHCCP002I CPU%4.4X thread al gestart\n" #: timer.c:202 #, fuzzy msgid "HHCTT002I Timer thread started: tid=" msgstr "HHCCP012I Timer thread gestart: tid=%p, pid=%d\n" #: timer.c:335 #, fuzzy msgid "HHCTT003I Timer thread ended\n" msgstr "HHCCP012I Timer thread gestart: tid=%p, pid=%d\n" #: tuntap.c:133 #, c-format msgid "HHCTU001E %s timeout, possible older version?\n" msgstr "" #: tuntap.c:214 #, c-format msgid "HHCTU001E Unable to determine operating system type: %s\n" msgstr "" #: tuntap.c:226 #, c-format msgid "HHCTU002E Error opening TUN/TAP device: %s: %s\n" msgstr "" #: tuntap.c:246 #, c-format msgid "HHCTU003E Error setting TUN/TAP mode: %s: %s\n" msgstr "" #: tuntap.c:271 #, c-format msgid "HHCTU004E Invalid TUN/TAP device name: %s\n" msgstr "" #: tuntap.c:304 tuntap.c:334 #, c-format msgid "HHCTU005E Invalid net device name specified: %s\n" msgstr "" #: tuntap.c:344 #, c-format msgid "HHCTU006E %s: Invalid IP address: %s.\n" msgstr "" #: tuntap.c:371 #, c-format msgid "HHCTU007E Invalid net device name specified: %s\n" msgstr "" #: tuntap.c:381 #, c-format msgid "HHCTU008E %s: Invalid destination address: %s.\n" msgstr "" #: tuntap.c:408 #, c-format msgid "HHCTU009E Invalid net device name specified: %s\n" msgstr "" #: tuntap.c:418 #, c-format msgid "HHCTU010E %s: Invalid net mask: %s.\n" msgstr "" #: tuntap.c:446 #, c-format msgid "HHCTU011E Invalid net device name specified: %s\n" msgstr "" #: tuntap.c:455 #, c-format msgid "HHCTU012E %s: Invalid null or empty MTU.\n" msgstr "" #: tuntap.c:464 #, c-format msgid "HHCTU013E %s: Invalid MTU: %s.\n" msgstr "" #: tuntap.c:493 #, c-format msgid "HHCTU014E Invalid net device name specified: %s\n" msgstr "" #: tuntap.c:502 #, c-format msgid "HHCTU015E %s: Invalid MAC address: %s.\n" msgstr "" #: tuntap.c:532 tuntap.c:563 #, c-format msgid "HHCTU016E Invalid net device name specified: %s\n" msgstr "" #: tuntap.c:613 #, c-format msgid "HHCTU017E Invalid net device name specified: %s\n" msgstr "" #: tuntap.c:627 #, c-format msgid "HHCTU018E %s: Invalid destiniation address: %s.\n" msgstr "" #: tuntap.c:639 #, c-format msgid "HHCTU019E %s: Invalid net mask: %s.\n" msgstr "" #: tuntap.c:652 #, c-format msgid "HHCTU020E %s: Invalid gateway address: %s.\n" msgstr "" #: tuntap.c:681 #, c-format msgid "HHCTU021E Invalid net device name specified: %s\n" msgstr "" #: tuntap.c:695 #, c-format msgid "HHCTU022E %s: Invalid destiniation address: %s.\n" msgstr "" #: tuntap.c:707 #, c-format msgid "HHCTU023E %s: Invalid net mask: %s.\n" msgstr "" #: tuntap.c:720 #, c-format msgid "HHCTU024E %s: Invalid gateway address: %s.\n" msgstr "" #: tuntap.c:821 #, c-format msgid "HHCTU025E Call to socketpair failed: %s\n" msgstr "" #: tuntap.c:830 #, c-format msgid "HHCTU029I Executing '%s' to configure interface\n" msgstr "" #: tuntap.c:838 #, fuzzy, c-format msgid "HHCTU026E Call to fork failed: %s\n" msgstr "HHCLC039E Fout %2$s bij openen bestand \"%1$s\"\n" #: tuntap.c:862 msgid "HHCTU031I Closing %" msgstr "" #: tuntap.c:880 #, fuzzy, c-format msgid "HHCTU027E execl error on %s: %s.\n" msgstr "HHCTA024E Fout %2$s bij openen van bestand \"%1$s\"\n" #: tuntap.c:893 #, c-format msgid "HHCTU030I IFC_IOCtl called for %s on FDs %d %d\n" msgstr "" #: version.c:211 version.c:213 version.c:215 #, c-format msgid "%sVersion %s\n" msgstr "%sVersie %s\n" #: version.c:234 version.c:236 version.c:238 #, c-format msgid "Built on %s at %s\n" msgstr "" #: version.c:244 version.c:246 version.c:248 #, c-format msgid "Build information:\n" msgstr "" #: vm.c:839 #, c-format msgid "HHCVM001I *%s* panel command issued by guest\n" msgstr "" #: vm.c:855 #, c-format msgid "HHCVM002I *%s* command complete\n" msgstr "" #: vm.c:859 msgid "HHCVM003I Host command processing disabled by configuration statement" msgstr "" #: vm.c:861 msgid "HHCVM004E Host command processing not included in engine build" msgstr "" #: w32chan.c:143 #, c-format msgid "HHCCP084E malloc(DEVIOREQUEST) failed; device=%4.4X, strerror=\"%s\"\n" msgstr "" #: w32chan.c:206 msgid "HHCCP085W *WARNING* max device threads exceeded.\n" msgstr "" #: w32chan.c:303 #, c-format msgid "" "HHCCP086E malloc(DEVTHREADPARMS) failed; device=%4.4X, strerror=\"%s\"\n" msgstr "" #: w32chan.c:312 #, c-format msgid "" "HHCCP087E CreateEvent(hShutdownEvent) failed; device=%4.4X, strerror=\"%s\"\n" msgstr "" #: w32chan.c:322 #, c-format msgid "" "HHCCP088E CreateEvent(hRequestQueuedEvent) failed; device=%4.4X, strerror=\"%" "s\"\n" msgstr "" #: w32chan.c:343 #, c-format msgid "" "HHCCP089E fthread_create(DeviceThread) failed; device=%4.4X, strerror=\"%s" "\"\n" msgstr "" #, fuzzy #~ msgid "HHCPN042E Missing device number\n" #~ msgstr "HHCPN042E Geen apparaat nummer\n" #, fuzzy #~ msgid "HHCPN052E Missing device number\n" #~ msgstr "HHCPN052E Geen apparaat nummer\n" #, fuzzy #~ msgid "HHCPN060E Missing device number\n" #~ msgstr "HHCPN060E Geen apparaat nummer\n" #, fuzzy #~ msgid "HHCPN069E Missing device number\n" #~ msgstr "HHCPN069E Geen apparaat nummer\n" #, fuzzy #~ msgid " CPU%4.4X: Waiting for mainlock: %s\n" #~ msgstr " CPU%4.4X: Geen kanaalset aangesloten\n" #, fuzzy #~ msgid " SIE%4.4X: CPU interlock %sheld\n" #~ msgstr " CPU%4.4X: Geen kanaalset aangesloten\n" #, fuzzy #~ msgid "HHCPN080E Invalid device number\n" #~ msgstr "HHCPN080E Ongeldig apparaat nummer\n" #, fuzzy #~ msgid "cckdcdsk: error opening file %s: %s\n" #~ msgstr "cckdcdsk: Fout %2$s bij openen bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCPN015E Invalid device number\n" #~ msgstr "HHCPN015E Ongeldig apparaat nummer\n" #, fuzzy #~ msgid "HHCPN022E Invalid device number\n" #~ msgstr "HHCPN022E Ongeldig apparaat nummer\n" #, fuzzy #~ msgid "HHCPN082E Invalid device number\n" #~ msgstr "HHCPN082E Ongeldig apparaat nummer\n" #, fuzzy #~ msgid "HHCHT06xE html_include: Error reading file %s: %s\n" #~ msgstr "HHCRD016E Fout %2$s bij lezen van bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCHT06xE html_include: Error writing file %s to socket: %s\n" #~ msgstr "HHCHT011E html_include: Fout %2$s bij openen bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCHT06xE html_include: Error closing file %s: %s\n" #~ msgstr "HHCHT011E html_include: Fout %2$s bij openen bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCHT06xE http_error: %s (%s)\n" #~ msgstr "HHCTA024E Fout %2$s bij openen van bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCHT06xE http_download: Error fprintf'ing 200 OK for file %s: %s\n" #~ msgstr "HHCRD013E Fout %2$s bij openen bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCHT06xE http_download: Error reading file %s: %s\n" #~ msgstr "HHCRD016E Fout %2$s bij lezen van bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCHT06xE http_download: Error closing file %s: %s\n" #~ msgstr "HHCDA061E Fout %2$s bij leven van bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCTC002E Error reading status of %s: rc=%d, errno=%d: %s\n" #~ msgstr "HHCTC002E Fout %2$s bij lezen van bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCCF064W Hercules set priority %d failed: %s\n" #~ msgstr "HHCCP002I CPU%4.4X thread al gestart\n" #, fuzzy #~ msgid "HHCTA024E Error opening %s: %s\n" #~ msgstr "HHCTA024E Fout %2$s bij openen van bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCDL001E Cannot open %s: %s\n" #~ msgstr "HHCDL001E Fout %2$s bij openen bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCDL018E Cannot read VOL1 record\n" #~ msgstr "HHDL018E Kan VOL1 record niet lezen\n" #, fuzzy #~ msgid "HHCDL020E Line too long in %s line %d\n" #~ msgstr "HHCDL020E Regel %$2d in bestand \"%2$s\" te lang\n" #, fuzzy #~ msgid "HHCDL066E %s read error: %s\n" #~ msgstr "HHCDL066E Fout %2$s bij lezen van bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCDL073E %s read error: %s\n" #~ msgstr "HHCDL073E Fout %2$s bij openen lezan van \"%1$s\"\n" #, fuzzy #~ msgid "HHCDL074E %s read error: %s\n" #~ msgstr "HHCDL074E Fout %2$s bij openen lezan van \"%1$s\"\n" #, fuzzy #~ msgid "HHCDL075E %s read error: %s\n" #~ msgstr "HHCDL075E Fout %2$s bij lezan van bestand \"%1$s\"\n" #, fuzzy #~ msgid "HHCDL091E Directory block record length is invalid\n" #~ msgstr "HHCDL091E Lengte van directory block record ongeldig\n" hercules-3.07/po/POTFILES.in000644 000765 000765 00000001634 11143760531 017143 0ustar00jmaynardjmaynard000000 000000 assist.c cache.c cardpch.c cardrdr.c cckdcdsk.c cckdcomp.c cckddasd.c cckddiag.c cckdfix.c cckdswap.c cckdutil.c cgibin.c channel.c ckddasd.c cmpsc.c codepage.c commadpt.c config.c console.c control.c cpu.c crypto.c ctc_ctci.c ctc_lcs.c ctcadpt.c dasdcat.c dasdcopy.c dasdinit.c dasdisup.c dasdload.c dasdls.c dasdpdsu.c dasdseq.c dasdtab.c dasdutil.c dat.c decimal.c diagmssf.c diagnose.c dmap2hrc.c dyngui.c dyninst.c ecpsvm.c esame.c external.c fbadasd.c fishhang.c float.c fthreads.c general1.c general2.c hdl.c hdlmain.c hercifc.c hetget.c hetinit.c hetlib.c hetmap.c hetupd.c hostinfo.c hsccmd.c hscmisc.c hscutl.c httpserv.c ieee.c impl.c io.c ipl.c logger.c logmsg.c machchk.c memrchr.c opcode.c panel.c parser.c plo.c printer.c qdio.c service.c shared.c sie.c sllib.c sockdev.c stack.c tapecopy.c tapedev.c tapemap.c tapesplt.c timer.c trace.c tuntap.c vector.c version.c vm.c vstore.c w32chan.c w32ctca.c xstore.c hercules-3.07/po/quot.sed000644 000765 000765 00000000231 11143760531 017043 0ustar00jmaynardjmaynard000000 000000 s/"\([^"]*\)"/“\1”/g s/`\([^`']*\)'/‘\1’/g s/ '\([^`']*\)' / ‘\1’ /g s/ '\([^`']*\)'$/ ‘\1’/g s/^'\([^`']*\)' /‘\1’ /g s/“”/""/g hercules-3.07/po/remove-potcdate.sin000644 000765 000765 00000000660 11143760531 021175 0ustar00jmaynardjmaynard000000 000000 # 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 } hercules-3.07/po/Rules-quot000644 000765 000765 00000003376 11143760531 017376 0ustar00jmaynardjmaynard000000 000000 # 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 hercules-3.07/po/stamp-po000644 000765 000765 00000000012 11157243120 017031 0ustar00jmaynardjmaynard000000 000000 timestamp hercules-3.07/msvc.makefile.includes/BZIP2_DIR.msvc000644 000765 000765 00000005145 11224164166 023522 0ustar00jmaynardjmaynard000000 000000 # *************************************************************************** # BZIP2_DIR.msvc (!INCLUDE ed by "makefile-dllmod.msvc") # -------------------------------------------------------------------------- # (c) Copyright Roger Bowler, 2005-2007 # -------------------------------------------------------------------------- # $Id: BZIP2_DIR.msvc 5407 2009-06-14 18:34:54Z fish $ # # Handles support for BZIP2 compression # # *************************************************************************** # --------------------------------------------------------------------- # To enable BZIP2 compression, first make sure you have the libbz2.dll # installed on your system (from: http://sources.redhat.com/bzip2/), # and then define an environment variable called "BZIP2_DIR" that # specifies the full path to the directory where it is installed. # (via the "Advanced" tab of the Control Panel 'System' applet). # # Note that the directory you specify should contain the libbz2.dll as # well as the 'bzlib.h' header file and the 'libbz2.lib' link library. # # Note: if the path contains blanks, do NOT surround it with quotes! # The makefile will do that if it needs to. Just define the variable # with the path as-is. E.g.: # # BZIP2_DIR = E:\MyProjects\bzip2 # --------------------------------------------------------------------- !IFNDEF BZIP2_DIR # Undefined: use default value, if it exists. # BZIP2_DIR defaults to winbuild\bzip2 relative to current directory !IF "$(CPU)" == "i386" && EXIST(winbuild\bzip2) BZIP2_DIR = winbuild\bzip2 !ELSEIF "$(CPU)" == "AMD64" && EXIST(winbuild\bzip2\x64) BZIP2_DIR = winbuild\bzip2\x64 !ELSEIF "$(CPU)" == "IA64" && EXIST(winbuild\bzip2\ia64) BZIP2_DIR = winbuild\bzip2\ia64 !ENDIF !ELSE # Defined: use explicit directory or subdirectory # unless "NONE" is specified or it doesn't exist. !IF "$(BZIP2_DIR)" == "NONE" !UNDEF BZIP2_DIR !ELSE !IF "$(CPU)" == "i386" !IF !EXIST($(BZIP2_DIR)) !UNDEF BZIP2_DIR !ENDIF !ELSEIF "$(CPU)" == "AMD64" !IF EXIST($(BZIP2_DIR)\x64) BZIP2_DIR = $(BZIP2_DIR)\x64 !ENDIF !ELSEIF "$(CPU)" == "IA64" !IF EXIST($(BZIP2_DIR)\ia64) BZIP2_DIR = $(BZIP2_DIR)\ia64 !ENDIF !ENDIF !ENDIF !ENDIF !IFDEF BZIP2_DIR !IF !EXIST("$(BZIP2_DIR)\bzlib.h") !ERROR BZIP2_DIR "$(BZIP2_DIR)\bzlib.h" does not exist. Check BZIP2_DIR !ELSEIF !EXIST("$(BZIP2_DIR)\libbz2.lib") !ERROR BZIP2_DIR "$(BZIP2_DIR)\libbz2.lib" does not exist. Check BZIP2_DIR !ELSEIF !EXIST("$(BZIP2_DIR)\libbz2.dll") !ERROR BZIP2_DIR "$(BZIP2_DIR)\libbz2.dll" does not exist. Check BZIP2_DIR !ENDIF !MESSAGE BZIP2 support will be included from "$(BZIP2_DIR)" !ELSE !MESSAGE BZIP2 support will not be generated !ENDIF hercules-3.07/msvc.makefile.includes/BZIP2_FLAGS.msvc000644 000765 000765 00000001625 11143760522 023735 0ustar00jmaynardjmaynard000000 000000 # *************************************************************************** # BZIP2_FLAGS.msvc (!INCLUDE ed by "makefile-dllmod.msvc") # -------------------------------------------------------------------------- # (c) Copyright Roger Bowler, 2005-2007 # -------------------------------------------------------------------------- # $Id: BZIP2_FLAGS.msvc 4884 2008-10-11 23:46:01Z fish $ # # Sets BZIP2-compression-related compiler/linker flags & #defines... # # # CHANGE HISTORY # $Log$ # # DD/MM/YY Description # # 26/12/06 Fish: created by extraction from existing makefile-dllmod.msvc # # *************************************************************************** !IFDEF BZIP2_DIR BZIP2_DLL = $(BZIP2_DIR)\libbz2.dll BZIP2_LIB = $(BZIP2_DIR)/libbz2.lib BZIP2_INC = $(BZIP2_DIR) LIBS = $(LIBS) "$(BZIP2_LIB)" cflags = $(cflags) /D HAVE_BZLIB_H /I"$(BZIP2_INC)" !ENDIF hercules-3.07/msvc.makefile.includes/BZIP2_RULES.msvc000644 000765 000765 00000002413 11335365455 024000 0ustar00jmaynardjmaynard000000 000000 # *************************************************************************** # BZIP2_RULES.msvc (!INCLUDE ed by "makefile-dllmod.msvc") # -------------------------------------------------------------------------- # (c) Copyright Roger Bowler, 2005-2007 # -------------------------------------------------------------------------- # $Id: BZIP2_RULES.msvc 5616 2010-02-08 23:44:59Z fish $ # # BZIP2 build rules... # # # CHANGE HISTORY # $Log$ # # DD/MM/YY Description # # 26/12/06 Fish: created by extraction from existing makefile-dllmod.msvc # 07/02/10 Fish: allHercules. # # *************************************************************************** !IFDEF BZIP2_DIR $(X)libbz2.dll: XCOPY "$(BZIP2_DLL)" $(X) /V /C /F /H /R /K /O /X /Y alllibbz2: allHercules \ $(X)libbz2.dll !ELSE alllibbz2: allHercules !ENDIF # NOTE: to be safe, since this member contains build rules, we need to # make sure there's always a blank line following the last build rule # in the member so that nmake doesn't complain or otherwise treat the # statements immediately following the original !INCLUDE statement as # part of the build rule actions. Thus the purpose of the comments you # are now reading as the very last few lines in every build rule member. hercules-3.07/msvc.makefile.includes/CONFIG.msvc000644 000765 000765 00000004167 11224164166 023146 0ustar00jmaynardjmaynard000000 000000 # *************************************************************************** # CONFIG.msvc (!INCLUDE ed by "makefile-dllmod.msvc") # -------------------------------------------------------------------------- # (c) Copyright Roger Bowler, 2005-2007 # -------------------------------------------------------------------------- # $Id: CONFIG.msvc 5382 2009-06-05 09:09:01Z fish $ # # Set NODEBUG flag appropriately before !INCLUDEing # and attempt to determine the Visual Studio compiler version # # # CHANGE HISTORY # $Log$ # Revision 1.3 2009/02/01 18:11:02 rbowler # Eliminate extraneous trailing blanks (cosmetic change only) # # Revision 1.2 2008/01/31 22:32:36 rbowler # Move MSVC compiler level determination to CONFIG.msvc # # # DD/MM/YY Description # 26/12/06 Fish: created by extraction from existing makefile-dllmod.msvc # # *************************************************************************** # Use environment variables to determine the Visual Studio compiler level !IFDEF VS90COMNTOOLS !MESSAGE Makefile will assume VS9 or VS2008Express (MSVC version 15) vsversion=9 !ELSEIFDEF VS80COMNTOOLS !MESSAGE Makefile will assume VS8 or VS2005Express (MSVC version 14) vsversion=8 !ELSEIFDEF VS70COMNTOOLS !MESSAGE Makefile will assume VS7 (MSVC version 13) vsversion=7 !ELSE !MESSAGE Makefile will assume VC++ Toolkit 2003 (MSVC version 13) vsversion=7 !ENDIF # Use environment variables to determine the target processor type !IF !DEFINED(CPU) || "$(CPU)" == "" CPU=$(PROCESSOR_ARCHITECTURE) !ENDIF !IF "$(CPU)" == "IA64" !MESSAGE Target processor type is IA64 _WIN64=1 !ELSEIF "$(CPU)" == "AMD64" !MESSAGE Target processor type is AMD64 _WIN64=1 !ELSE !MESSAGE Target processor type is i386 CPU=i386 !UNDEF _WIN64 !ENDIF !MESSAGE # ------------------------------------------------- # NOTE! must set the 'NODEBUG' variable properly # BEFORE calling win32.mak since it uses it. # ------------------------------------------------- !IFNDEF CFG NODEBUG = 1 !ELSEIF "$(CFG)" == "DEBUG" !UNDEF NODEBUG !ELSEIF "$(CFG)" == "RETAIL" NODEBUG = 1 !ELSE !ERROR Invalid build configuration! !ENDIF hercules-3.07/msvc.makefile.includes/DEBUG_RETAIL.msvc000644 000765 000765 00000006661 11224164166 024070 0ustar00jmaynardjmaynard000000 000000 # *************************************************************************** # DEBUG_RETAIL.msvc (!INCLUDE ed by "makefile-dllmod.msvc") # -------------------------------------------------------------------------- # (c) Copyright Roger Bowler, 2005-2007 # -------------------------------------------------------------------------- # $Id: DEBUG_RETAIL.msvc 5382 2009-06-05 09:09:01Z fish $ # # Sets appropriate compiler/linker flags (cdebug & ldebug) depending on # whether a normal retail release or debugging version of the product is # being built... (also sets preprocessor #defines too, as appropriate) # # # CHANGE HISTORY # $Log$ # Revision 1.7 2009/02/08 15:07:20 rbowler # Eliminate superfluous trailing blanks (cosmetic change only) # # Revision 1.6 2009/02/05 23:43:09 rbowler # Reduce warning level from W4 to W3 for win64 # # Revision 1.5 2009/02/05 23:22:18 rbowler # C1189: cannot use 32-bit time_t (_USE_32BIT_TIME_T) with _WIN64 # # Revision 1.4 2008/01/31 22:32:36 rbowler # Move MSVC compiler level determination to CONFIG.msvc # # Revision 1.3 2008/01/23 17:59:28 rbowler # Modify detection of MSVC level in makefile # # Revision 1.2 2008/01/23 00:47:40 rbowler # Modifications for VS9 C++ 2008 Express by Charlie Brint # # DD/MM/YY Description # # 26/12/06 Fish: created by extraction from existing makefile-dllmod.msvc # # *************************************************************************** # ------------------------------------------------- # NOTE! must set our prefered 'cdebug' value(s) # AFTER calling win32.mak since it sets it. # ------------------------------------------------- !IF $(vsversion) < 8 MAPFILE = /map:$(MAPDIR)\$(@B).map /mapinfo:lines !ELSE MAPFILE = /map:$(MAPDIR)\$(@B).map !ENDIF !IFDEF NODEBUG # ------------------------------- # RETAIL: full optimization # ------------------------------- # Fish: Not sure how to check within a makefile for which version # of the compiler is going to be used so for now, we'll hard code # the test for VS 7.0's compiler (version 13.00) which still supports # the /QIfist option (whereas the newer VS 8.0 compiler (vers 14.00) # kicks out the warning: "D9035 option 'QIfist' has been deprecated # and will be removed in a future release"). Their documentation # says to use the new /fp option instead. # rbowler: Compiler version check (vsversion) is now in CONFIG.msvc !IF $(vsversion) < 8 cflags = $(cflags) /QIfist # PROGRAMMING NOTE: we're purposely discarding win32.mak's $(cdebug) settings # and replacing them with our own by leaving "$(cdebug)" out of the statement cdebug = /O2 /D NDEBUG ldebug = $(ldebug) !ELSE # vsversion >= 8 # PROGRAMMING NOTE: we're purposely discarding win32.mak's $(cdebug) settings # and replacing them with our own by leaving "$(cdebug)" out of the statement cdebug = /O2 /GL /D NDEBUG ldebug = $(ldebug) /LTCG !ENDIF # Create .PDB (Program Database) files for debugging for 'Release' builds too! # (so we can easily analyze "MiniDump" crash dumps should Herc ever crash) cdebug = $(cdebug) /Zi /Gm ldebug = $(ldebug) /DEBUG /PDB:$(PDBDIR)\$(@B).pdb !ELSE # ------------------------------- # DEBUG: no optimizations at all # ------------------------------- # PROGRAMMING NOTE: we're purposely discarding win32.mak's $(cdebug) settings # and replacing them with our own by leaving "$(cdebug)" out of the statement cdebug = -Zi -Od -D DEBUG -D _DEBUG -Gm ldebug = /DEBUG /PDB:$(PDBDIR)\$(@B).pdb !ENDIF hercules-3.07/msvc.makefile.includes/HERC_FLAGS.msvc000644 000765 000765 00000006447 11301535251 023632 0ustar00jmaynardjmaynard000000 000000 # *************************************************************************** # HERC_FLAGS.msvc (!INCLUDE ed by "makefile-dllmod.msvc") # -------------------------------------------------------------------------- # (c) Copyright Roger Bowler, 2005-2007 # -------------------------------------------------------------------------- # $Id: HERC_FLAGS.msvc 5479 2009-10-09 10:30:31Z fish $ # # Sets additional Hercules-related compiler/linker flags & #defines... # # # CHANGE HISTORY # $Log$ # Revision 1.2 2008/10/11 23:46:01 fish # Add CVS "Id" and "Log" # # # DD/MM/YY Description # # 26/12/06 Fish: created by extraction from existing makefile-dllmod.msvc # # *************************************************************************** # Set some additional flags... ldebug = $(ldebug) $(MAPFILE) # user32.lib for the MessageBeep and MessageBox functions LIBS = $(LIBS) user32.lib # The following line makes all warnings into errors cflags = $(cflags) /WX !IFDEF ASSEMBLY_LISTINGS # /FAcs = source code, assembly code, and machine code cflags = $(cflags) /FAcs /Fa$(ASMDIR)\$(NULL) !ENDIF # PRERELEASE Flag support !IFDEF PRERELEASE rcflags = $(rcflags) -D PRERELEASE=1 !ENDIF !IFDEF _WIN64 rcflags = $(rcflags) -D _WIN64 !ENDIF !IFNDEF MAX_CPU_ENGINES MAX_CPU_ENGINES = 8 !ENDIF rcflags = $(rcflags) -D _MSVC_ -D VERSION=$(VERSION) -D V1=$(V1) -D V2=$(V2) -D V3=$(V3) -D V4=$(V4) cflags = $(cflags) /D _MSVC_ /D VERSION=$(VERSION) /D MAX_CPU_ENGINES=$(MAX_CPU_ENGINES) !IF DEFINED(CUSTOM_BUILD_STRING) cflags = $(cflags) /D CUSTOM_BUILD_STRING=\"$(CUSTOM_BUILD_STRING)\" !ENDIF # Allow version.c to display the name of the host CPU architecture cflags = $(cflags) /D HOST_ARCH=$(CPU) # The following instructs the declaration of DLL export symbols cflags = $(cflags) /D HDL_BUILD_SHARED /D OPTION_DYNAMIC_LOAD # fish test ##FISH_HANG = yes !IFDEF FISH_HANG cflags = $(cflags) -D FISH_HANG !ENDIF # Suppress some deprecation warnings that aren't really deprecation warnings !IF $(vsversion) >= 8 cflags = $(cflags) -D _CRT_SECURE_NO_DEPRECATE cflags = $(cflags) -D _CRT_NONSTDC_NO_DEPRECATE ldebug = $(ldebug) /MANIFEST !ENDIF # Override win32.mak options for WIN64 to eliminate the following warnings # C4200: nonstandard extension used : zero-sized array in struct/union # C4127: conditional expression is constant cflags = $(cflags:-W4=-W3) cflags = $(cflags:/W4=/W3) # Suppress warning 4267 conversion from size_t to int possible loss of data cflags = $(cflags) /wd4267 # D9035: option 'Wp64' has been deprecated and will be removed in a future release. cflags = $(cflags:-Wp64=) cflags = $(cflags:/Wp64=) # Enable "/MP (Build with Multiple Processes)" option # if the building host has more than one processor... !IF $(vsversion) >= 9 && $(NUMBER_OF_PROCESSORS) > 1 cflags = $(cflags) /MP !ENDIF # Note: the "/Gm (Enable Minimal Rebuild)" option is incompatible # with the "/MP (Build with Multiple Processes)" option (and besides # that it's still somewhat buggy) so remove it if it's present... cdebug = $(cdebug:-Gm=) cdebug = $(cdebug:/Gm=) # Specify module base address directly via linker option # so we don't have to rely on user having rebase utility. ldebug = $(ldebug) /base:0x400000 # Optimize for AMD64 CPU architecture !IF "$(CPU)" == "AMD64" cflags = $(cflags) /favor:AMD64 !ENDIF hercules-3.07/msvc.makefile.includes/MOD_RULES1.msvc000644 000765 000765 00000004601 11143760522 023642 0ustar00jmaynardjmaynard000000 000000 # *************************************************************************** # MOD_RULES1.msvc (!INCLUDE ed by "makefile-dllmod.msvc") # -------------------------------------------------------------------------- # (c) Copyright Roger Bowler, 2005-2007 # -------------------------------------------------------------------------- # $Id: MOD_RULES1.msvc 4379 2007-06-02 13:46:42Z rbowler $ # # Prerequisite hercules build rules... (precompiled header, etc...) # # # CHANGE HISTORY # $Log$ # DD/MM/YY Description # 26/12/06 Fish: created by extraction from existing makefile-dllmod.msvc # # *************************************************************************** $(O)hercver.res: hercver.rc $(rc) $(rcflags) $(rcvars) -fo $(O)hercver.res hercver.rc $(O)build_pch.pch: build_pch.c $(cc) $(cdebug) $(cflags) /Fp"$(OBJDIR)\\build_pch.pch" /Yc"hstdinc.h" $(cvarsdll) /Fo"$(OBJDIR)\\" /Fd"$(OBJDIR)\\" $** !IFNDEF NOCRYPTO {crypto}.c{$(OBJDIR)}.obj:: $(cc) $(cdebug) $(cflags) /Icrypto /I. /Fp"$(OBJDIR)\\build_pch.pch" /Yu"hstdinc.h" $(cvarsdll) /Fo"$(OBJDIR)\\" /Fd"$(OBJDIR)\\" $< !ENDIF {decNumber}.c{$(OBJDIR)}.obj:: $(cc) $(cdebug) $(cflags) /IdecNumber /I. $(cvarsdll) /Fo"$(OBJDIR)\\" /Fd"$(OBJDIR)\\" $< $(O)dfp.obj: dfp.c $(cc) $(cdebug) $(cflags) /IdecNumber /I. /Fp"$(OBJDIR)\\build_pch.pch" /Yu"hstdinc.h" $(cvarsdll) /Fo"$(OBJDIR)\\" /Fd"$(OBJDIR)\\" dfp.c $(O)pfpo.obj: pfpo.c $(cc) $(cdebug) $(cflags) /IdecNumber /I. /Fp"$(OBJDIR)\\build_pch.pch" /Yu"hstdinc.h" $(cvarsdll) /Fo"$(OBJDIR)\\" /Fd"$(OBJDIR)\\" pfpo.c $(O)decNumber.res: decNumber\decNumber.rc $(rc) $(rcflags) $(rcvars) -i decNumber -fo $(O)decNumber.res decNumber\decNumber.rc # # No precompiled headers for these ones.. Sorry! # $(O)getopt.obj: getopt.c $(cc) $(cdebug) $(cflags) $(cvarsdll) /Fo"$(OBJDIR)\\" /Fd"$(OBJDIR)\\" getopt.c $(O)herclin.obj: herclin.c $(cc) $(cdebug) $(cflags) $(cvarsdll) /Fo"$(OBJDIR)\\" /Fd"$(OBJDIR)\\" herclin.c # NOTE: to be safe, since this member contains build rules, we need to # make sure there's always a blank line following the last build rule # in the member so that nmake doesn't complain or otherwise treat the # statements immediately following the original !INCLUDE statement as # part of the build rule actions. Thus the purpose of the comments you # are now reading as the very last few lines in every build rule member. hercules-3.07/msvc.makefile.includes/MOD_RULES2.msvc000644 000765 000765 00000015717 11224164166 023657 0ustar00jmaynardjmaynard000000 000000 # *************************************************************************** # MOD_RULES2.msvc (!INCLUDE ed by "makefile-dllmod.msvc") # -------------------------------------------------------------------------- # (c) Copyright Roger Bowler, 2005-2007 # -------------------------------------------------------------------------- # $Id: MOD_RULES2.msvc 5370 2009-06-02 04:35:14Z fish $ # # Individual hercules modules build rules... # # # CHANGE HISTORY # $Log$ # Revision 1.2 2008/03/25 11:41:32 fish # SCSI TAPE MODS part 1: groundwork: non-functional changes: # rename some functions, comments, general restructuring, etc. # New source modules awstape.c, omatape.c, hettape.c and # tapeccws.c added, but not yet used (all will be used in a future # commit though when tapedev.c code is eventually split) # # # DD/MM/YY Description # 26/12/06 Fish: created by extraction from existing makefile-dllmod.msvc # # *************************************************************************** # ------------------------------------------------------------- # DLL export libraries are dependent on themselves existing $(O)decNumber.lib: $(X)decNumber.dll $(O)hdasd.lib: $(X)hdasd.dll $(O)htape.lib: $(X)htape.dll $(O)hutil.lib: $(X)hutil.dll $(O)hengine.lib: $(X)hengine.dll $(O)hsys.lib: $(X)hsys.dll # ------------------------------------------------------------- # Individual DLLs are dependent their own code as well as the # export libraries from other DLLs that they're dependent on.. $(X)hsys.dll: $(hsys_OBJ) $(O)hercver.res $(linkdll) $(X)hutil.dll: $(hutil_OBJ) $(O)hsys.lib $(O)hercver.res $(linkdll) $(X)htape.dll: $(htape_OBJ) $(O)hsys.lib $(O)hutil.lib $(O)hercver.res $(linkdll) $(X)hdasd.dll: $(hdasd_OBJ) $(O)hsys.lib $(O)hutil.lib $(O)hercver.res $(linkdll) $(X)hengine.dll: $(hengine_OBJ) $(O)hsys.lib $(O)hdasd.lib $(O)hutil.lib \ $(O)htape.lib $(O)decNumber.lib $(O)hercver.res $(linkdll) # ------------------------------------------------------------- # Device modules $(X)hdt2703.dll: $(O)commadpt.obj $(O)hengine.lib $(O)hutil.lib $(O)hsys.lib $(O)hercver.res $(linkdll) $(X)hdt3705.dll: $(O)comm3705.obj $(O)hengine.lib $(O)hutil.lib $(O)hsys.lib $(O)hercver.res $(linkdll) $(X)hdt3088.dll: $(O)ctc_lcs.obj $(O)ctc_ctci.obj $(O)ctcadpt.obj $(O)w32ctca.obj $(O)tuntap.obj $(O)hengine.lib $(O)hutil.lib $(O)hsys.lib $(O)hercver.res $(linkdll) $(X)hdt3420.dll: $(hdt3420_OBJ) $(O)hengine.lib $(O)htape.lib $(O)hutil.lib $(O)hsys.lib $(O)hercver.res $(linkdll) $(X)hdt1403.dll: $(O)printer.obj $(O)sockdev.obj $(O)hengine.lib $(O)hutil.lib $(O)hsys.lib $(O)hercver.res $(linkdll) $(X)hdt3505.dll: $(O)cardrdr.obj $(O)sockdev.obj $(O)hengine.lib $(O)hutil.lib $(O)hsys.lib $(O)hercver.res $(linkdll) $(X)hdt3525.dll: $(O)cardpch.obj $(O)hengine.lib $(O)hutil.lib $(O)hsys.lib $(O)hercver.res $(linkdll) $(X)hdt3270.dll: $(O)console.obj $(O)hengine.lib $(O)hutil.lib $(O)hsys.lib $(O)hercver.res $(linkdll) $(X)hdt1052c.dll: $(O)con1052c.obj $(O)hengine.lib $(O)hutil.lib $(O)hsys.lib $(O)hercver.res $(linkdll) $(X)hdtqeth.dll: $(O)qeth.obj $(O)hengine.lib $(O)hutil.lib $(O)hercver.res $(linkdll) $(X)hdteq.dll: $(O)hdteq.obj $(O)hengine.lib $(O)hutil.lib $(O)hercver.res $(linkdll) $(X)dyngui.dll: $(O)dyngui.obj $(O)hengine.lib $(O)hutil.lib $(O)hsys.lib $(O)hercver.res $(linkdll) $(X)dyninst.dll: $(O)dyninst.obj $(O)hengine.lib $(O)hutil.lib $(O)hsys.lib $(O)hercver.res $(linkdll) !IFNDEF NOCRYPTO crypto: $(X)dyncrypt.dll $(X)dyncrypt.dll: $(dyncrypt_OBJ) $(O)hengine.lib $(O)hutil.lib $(O)hsys.lib $(O)hercver.res $(linkdll) !ENDIF $(X)decNumber.dll: $(decNumber_OBJ) $(O)decNumber.res $(link) -nologo $(ldebug) $(dlllflags) $** $(LIBS) /def:decNumber\decNumber.def -out:$@ -implib:$(O)$(@B).lib $(conlibsdll) $(MAPFILE) && $(MT_DLL_CMD) # ------------------------------------------------------------- # Main product executables $(X)hercules.exe: $(O)bootstrap.obj $(O)hdlmain.obj $(O)hengine.lib $(O)hdasd.lib $(O)hsys.lib $(O)hutil.lib $(O)hercver.res $(linkexe) $(X)herclin.exe: $(O)herclin.obj $(O)hdlmain.obj $(O)hengine.lib $(O)hdasd.lib $(O)hsys.lib $(O)hutil.lib $(O)hercver.res $(linkexe) # ------------------------------------------------------------- # System utilities $(X)conspawn.exe: $(O)$(@B).obj $(O)hercver.res $(X)dmap2hrc.exe: $(O)$(@B).obj $(O)hsys.lib $(O)hutil.lib $(O)hercver.res # ------------------------------------------------------------- # Dasd utilities $(X)cckdcdsk.exe: $(O)$(@B).obj $(O)hdasd.lib $(O)hsys.lib $(O)hutil.lib $(O)hercver.res $(X)cckdcomp.exe: $(O)$(@B).obj $(O)hdasd.lib $(O)hsys.lib $(O)hutil.lib $(O)hercver.res $(X)cckddiag.exe: $(O)$(@B).obj $(O)hdasd.lib $(O)hsys.lib $(O)hutil.lib $(O)hercver.res $(X)cckdswap.exe: $(O)$(@B).obj $(O)hdasd.lib $(O)hsys.lib $(O)hutil.lib $(O)hercver.res $(X)dasdinit.exe: $(O)$(@B).obj $(O)hdasd.lib $(O)hsys.lib $(O)hutil.lib $(O)hercver.res $(X)dasdisup.exe: $(O)$(@B).obj $(O)hdasd.lib $(O)hsys.lib $(O)hutil.lib $(O)hercver.res $(X)dasdload.exe: $(O)$(@B).obj $(O)hdasd.lib $(O)hsys.lib $(O)hutil.lib $(O)hercver.res $(X)dasdconv.exe: $(O)$(@B).obj $(O)hdasd.lib $(O)hsys.lib $(O)hutil.lib $(O)hercver.res $(X)dasdcopy.exe: $(O)$(@B).obj $(O)hdasd.lib $(O)hsys.lib $(O)hutil.lib $(O)hercver.res $(X)dasdls.exe: $(O)$(@B).obj $(O)hdasd.lib $(O)hsys.lib $(O)hutil.lib $(O)hercver.res $(X)dasdcat.exe: $(O)$(@B).obj $(O)hdasd.lib $(O)hsys.lib $(O)hutil.lib $(O)hercver.res $(X)dasdpdsu.exe: $(O)$(@B).obj $(O)hdasd.lib $(O)hsys.lib $(O)hutil.lib $(O)hercver.res $(X)dasdseq.exe: $(O)$(@B).obj $(O)hdasd.lib $(O)hsys.lib $(O)hutil.lib $(O)hercver.res # ------------------------------------------------------------- # Tape utilities $(X)hetget.exe: $(O)$(@B).obj $(O)htape.lib $(O)hsys.lib $(O)hutil.lib $(O)hercver.res $(X)hetinit.exe: $(O)$(@B).obj $(O)htape.lib $(O)hsys.lib $(O)hutil.lib $(O)hercver.res $(X)hetmap.exe: $(O)$(@B).obj $(O)htape.lib $(O)hsys.lib $(O)hutil.lib $(O)hercver.res $(X)hetupd.exe: $(O)$(@B).obj $(O)htape.lib $(O)hsys.lib $(O)hutil.lib $(O)hercver.res $(X)tapecopy.exe: $(O)$(@B).obj $(O)htape.lib $(O)hsys.lib $(O)hutil.lib $(O)hercver.res $(X)tapemap.exe: $(O)$(@B).obj $(O)htape.lib $(O)hsys.lib $(O)hutil.lib $(O)hercver.res $(X)tapesplt.exe: $(O)$(@B).obj $(O)htape.lib $(O)hsys.lib $(O)hutil.lib $(O)hercver.res # NOTE: to be safe, since this member contains build rules, we need to # make sure there's always a blank line following the last build rule # in the member so that nmake doesn't complain or otherwise treat the # statements immediately following the original !INCLUDE statement as # part of the build rule actions. Thus the purpose of the comments you # are now reading as the very last few lines in every build rule member. hercules-3.07/msvc.makefile.includes/MODULES.msvc000644 000765 000765 00000003172 11204560640 023277 0ustar00jmaynardjmaynard000000 000000 # *************************************************************************** # MODULES.msvc (!INCLUDE ed by "makefile-dllmod.msvc") # -------------------------------------------------------------------------- # (c) Copyright Roger Bowler, 2005-2007 # -------------------------------------------------------------------------- # $Id: MODULES.msvc 5354 2009-05-19 16:33:05Z ivan $ # # The MODULES to be built... # # # CHANGE HISTORY # $Log$ # # DD/MM/YY Description # # 26/12/06 Fish: created by extraction from existing makefile-dllmod.msvc # # *************************************************************************** !IFNDEF NOCRYPTO DYNCRYPT_DLL = $(X)dyncrypt.dll !ELSE DYNCRYPT_DLL = !ENDIF MODULES = \ $(X)dyngui.dll \ $(X)hdt1052c.dll \ $(X)hdt1403.dll \ $(X)hdt2703.dll \ $(X)hdt3705.dll \ $(X)hdt3088.dll \ $(X)hdt3270.dll \ $(X)hdt3420.dll \ $(X)hdt3505.dll \ $(X)hdt3525.dll \ $(X)hdteq.dll \ $(X)hdtqeth.dll \ $(X)dyninst.dll \ $(X)decNumber.dll \ $(DYNCRYPT_DLL) EXECUTABLES = \ $(X)cckdcdsk.exe \ $(X)cckdcomp.exe \ $(X)cckddiag.exe \ $(X)cckdswap.exe \ $(X)conspawn.exe \ $(X)dasdcat.exe \ $(X)dasdconv.exe \ $(X)dasdcopy.exe \ $(X)dasdinit.exe \ $(X)dasdisup.exe \ $(X)dasdload.exe \ $(X)dasdls.exe \ $(X)dasdpdsu.exe \ $(X)dasdseq.exe \ $(X)dmap2hrc.exe \ $(X)herclin.exe \ $(X)hercules.exe \ $(X)hetget.exe \ $(X)hetinit.exe \ $(X)hetmap.exe \ $(X)hetupd.exe \ $(X)tapecopy.exe \ $(X)tapemap.exe \ $(X)tapesplt.exe hercules-3.07/msvc.makefile.includes/OBJ_CODE.msvc000644 000765 000765 00000010175 11301535251 023372 0ustar00jmaynardjmaynard000000 000000 # *************************************************************************** # OBJ_CODE.msvc (!INCLUDE ed by "makefile-dllmod.msvc") # -------------------------------------------------------------------------- # (c) Copyright Roger Bowler, 2005-2007 # -------------------------------------------------------------------------- # $Id: OBJ_CODE.msvc 5444 2009-08-09 16:36:42Z hsg001 $ # # What object code goes in what module... # # # CHANGE HISTORY # $Log$ # Revision 1.7 2008/12/29 11:03:11 jj # Move HMC disk I/O functions to scedasd.c # # Revision 1.6 2008/12/01 20:28:21 rbowler # Add new module losc.c in build process # # Revision 1.5 2008/05/22 19:25:58 fish # Flex FakeTape support # # Revision 1.4 2008/03/25 11:41:32 fish # SCSI TAPE MODS part 1: groundwork: non-functional changes: # rename some functions, comments, general restructuring, etc. # New source modules awstape.c, omatape.c, hettape.c and # tapeccws.c added, but not yet used (all will be used in a future # commit though when tapedev.c code is eventually split) # # Revision 1.3 2008/03/03 22:33:44 rbowler # Add new module general3.c for general-instructions-extension facility # # Revision 1.2 2007/06/02 13:46:42 rbowler # PFPO framework # # DD/MM/YY Description # 26/12/06 Fish: created by extraction from existing makefile-dllmod.msvc # # *************************************************************************** hsys_OBJ = \ $(O)hsys.obj hdasd_OBJ = \ $(O)cache.obj \ $(O)cckddasd.obj \ $(O)cckdutil.obj \ $(O)ckddasd.obj \ $(O)dasdtab.obj \ $(O)dasdutil.obj \ $(O)fbadasd.obj \ $(O)shared.obj htape_OBJ = \ $(O)hetlib.obj \ $(O)sllib.obj \ $(O)w32stape.obj hutil_OBJ = \ $(O)codepage.obj \ $(O)fthreads.obj \ $(O)getopt.obj \ $(O)hdl.obj \ $(O)hostinfo.obj \ $(O)hscutl.obj \ $(O)hscutl2.obj \ $(O)logger.obj \ $(O)logmsg.obj \ $(O)memrchr.obj \ $(O)parser.obj \ $(O)pttrace.obj \ $(O)version.obj \ $(O)hsocket.obj \ $(O)w32util.obj !IFNDEF NOCRYPTO dyncrypt_OBJ = \ $(O)dyncrypt.obj \ $(O)sha1.obj \ $(O)sha256.obj \ $(O)des.obj \ $(O)aes.obj !ENDIF decNumber_OBJ = \ $(O)decContext.obj \ $(O)decimal128.obj \ $(O)decimal32.obj \ $(O)decimal64.obj \ $(O)decNumber.obj \ $(O)decPacked.obj hengine_OBJ = \ $(O)assist.obj \ $(O)bldcfg.obj \ $(O)cgibin.obj \ $(O)channel.obj \ $(O)chsc.obj \ $(O)clock.obj \ $(O)cmdtab.obj \ $(O)cmpsc.obj \ $(O)config.obj \ $(O)control.obj \ $(O)cpu.obj \ $(O)crypto.obj \ $(O)dat.obj \ $(O)decimal.obj \ $(O)dfp.obj \ $(O)diagmssf.obj \ $(O)diagnose.obj \ $(O)ecpsvm.obj \ $(O)esame.obj \ $(O)external.obj \ $(O)fillfnam.obj \ $(O)float.obj \ $(O)general1.obj \ $(O)general2.obj \ $(O)general3.obj \ $(O)hconsole.obj \ $(O)history.obj \ $(O)hsccmd.obj \ $(O)hao.obj \ $(O)hscmisc.obj \ $(O)httpserv.obj \ $(O)ieee.obj \ $(O)impl.obj \ $(O)io.obj \ $(O)ipl.obj \ $(O)loadparm.obj \ $(O)losc.obj \ $(O)machchk.obj \ $(O)opcode.obj \ $(O)panel.obj \ $(O)pfpo.obj \ $(O)plo.obj \ $(O)qdio.obj \ $(O)service.obj \ $(O)scedasd.obj \ $(O)sie.obj \ $(O)sr.obj \ $(O)stack.obj \ $(O)timer.obj \ $(O)trace.obj \ $(O)vector.obj \ $(O)vm.obj \ $(O)vmd250.obj \ $(O)vstore.obj \ $(O)w32chan.obj \ $(O)xstore.obj hmodule_OBJ = \ $(O)cardpch.obj \ $(O)cardrdr.obj \ $(O)comm3705.obj \ $(O)commadpt.obj \ $(O)console.obj \ $(O)ctc_ctci.obj \ $(O)ctc_lcs.obj \ $(O)ctcadpt.obj \ $(O)printer.obj \ $(O)qeth.obj \ $(O)sockdev.obj \ $(O)tuntap.obj \ $(O)w32ctca.obj hdt3420_OBJ = \ $(O)tapedev.obj \ $(O)tapeccws.obj \ $(O)awstape.obj \ $(O)faketape.obj \ $(O)hettape.obj \ $(O)omatape.obj \ $(O)scsitape.obj hercules-3.07/msvc.makefile.includes/OUTDIR_RULES.msvc000644 000765 000765 00000002674 11143760522 024160 0ustar00jmaynardjmaynard000000 000000 # *************************************************************************** # OUTDIR_RULES.msvc (!INCLUDE ed by "makefile-dllmod.msvc") # -------------------------------------------------------------------------- # (c) Copyright Roger Bowler, 2005-2007 # -------------------------------------------------------------------------- # $Id: OUTDIR_RULES.msvc 4884 2008-10-11 23:46:01Z fish $ # # Build rules for creating o/p directories... # # # CHANGE HISTORY # $Log$ # # DD/MM/YY Description # # 26/12/06 Fish: created by extraction from existing makefile-dllmod.msvc # # *************************************************************************** $(OBJDIR): if not exist "$(OBJDIR)\$(NULL)" mkdir $(OBJDIR) $(EXEDIR): if not exist "$(EXEDIR)\$(NULL)" mkdir $(EXEDIR) $(PDBDIR): if not exist "$(PDBDIR)\$(NULL)" mkdir $(PDBDIR) $(MAPDIR): if not exist "$(MAPDIR)\$(NULL)" mkdir $(MAPDIR) !IFDEF ASSEMBLY_LISTINGS $(ASMDIR): if not exist "$(ASMDIR)\$(NULL)" mkdir $(ASMDIR) !ENDIF # NOTE: to be safe, since this member contains build rules, we need to # make sure there's always a blank line following the last build rule # in the member so that nmake doesn't complain or otherwise treat the # statements immediately following the original !INCLUDE statement as # part of the build rule actions. Thus the purpose of the comments you # are now reading as the very last few lines in every build rule member. hercules-3.07/msvc.makefile.includes/OUTPUT_DIRS.msvc000644 000765 000765 00000003334 11143760522 024053 0ustar00jmaynardjmaynard000000 000000 # *************************************************************************** # OUTPUT_DIRS.msvc (!INCLUDE ed by "makefile-dllmod.msvc") # -------------------------------------------------------------------------- # (c) Copyright Roger Bowler, 2005-2009 # -------------------------------------------------------------------------- # $Id: OUTPUT_DIRS.msvc 5155 2009-02-05 22:44:20Z rbowler $ # # Define the build output directories... # # # CHANGE HISTORY # $Log$ # Revision 1.2 2008/10/11 23:46:01 fish # Add CVS "Id" and "Log" # # # DD/MM/YY Description # # 26/12/06 Fish: created by extraction from existing makefile-dllmod.msvc # # SET PREFIX=NONE to generate output directories named bin,obj,pdb,map,cod # (this is for nmake version 6 which barfs if the command line is too long) # Otherwise the output directories are named: # msvc.[debug.]yyy.bin/obj/pdb/map/cod # where yyy is "dllmod" (for i386), or "AMD64" or "IA64" # (this naming convention is to avoid breaking existing build procedures) # *************************************************************************** !IFDEF NODEBUG DEBUG_PREFIX = !ELSE DEBUG_PREFIX = debug. !ENDIF !IF ("$(CPU)" == "i386") ARCH_PREFIX = dllmod. !ELSE ARCH_PREFIX = $(CPU). !ENDIF !IF ("$(PREFIX)" == "NONE") || ("$(PREFIX)" == "none") PREFIX = !ELSE PREFIX = msvc.$(DEBUG_PREFIX)$(ARCH_PREFIX) !ENDIF !IF ("$(EXEDIR)" == "") || ("$(OBJDIR)" == "") || ("$(PDBDIR)" == "") || ("$(MAPDIR)" == "") EXEDIR = $(PREFIX)bin OBJDIR = $(PREFIX)obj PDBDIR = $(PREFIX)pdb MAPDIR = $(PREFIX)map !ENDIF !IFNDEF ASSEMBLY_LISTINGS !UNDEF ASMDIR !ELSEIF ("$(ASMDIR)" == "") ASMDIR = $(PREFIX)cod !ENDIF # (shorter names are easier to use) X = $(EXEDIR)\$(NULL) O = $(OBJDIR)\$(NULL) hercules-3.07/msvc.makefile.includes/PCRE_DIR.msvc000644 000765 000765 00000006157 11224164166 023431 0ustar00jmaynardjmaynard000000 000000 # *************************************************************************** # PCRE_DIR.msvc (!INCLUDE ed by "makefile-dllmod.msvc") # -------------------------------------------------------------------------- # (c) Copyright Roger Bowler, 2005-2007 # -------------------------------------------------------------------------- # $Id: PCRE_DIR.msvc 5407 2009-06-14 18:34:54Z fish $ # # Handles support for PCRE (Perl Compatible Regular Expressions), # for MSVC, needed by HAO (Hercules Automatic Operator) facility # # *************************************************************************** # --------------------------------------------------------------------- # To enable PCRE (Perl-Compatible Regular Expressions) support, first # download 'Binaries' and 'Developer files' packages from the GNUWin32 # PCRE website at: http://gnuwin32.sourceforge.net/packages/pcre.htm. # Then create a permanent directory somewhere called whatever you want # with a 'bin', 'lib' and 'include' subdirectory, and then define an # environment variable called "PCRE_DIR" pointing to that directory. # Finally, make sure the below names of the include (header), lib and # DLL names are correct, making whatever adjustments may be necessary. # --------------------------------------------------------------------- !IFNDEF PCRE_DIR # Undefined: use default value, if it exists. # PCRE_DIR defaults to winbuild\pcre relative to current directory !IF "$(CPU)" == "i386" && EXIST(winbuild\pcre) PCRE_DIR = winbuild\pcre !ELSEIF "$(CPU)" == "AMD64" && EXIST(winbuild\pcre\x64) PCRE_DIR = winbuild\pcre\x64 !ELSEIF "$(CPU)" == "IA64" && EXIST(winbuild\pcre\ia64) PCRE_DIR = winbuild\pcre\ia64 !ENDIF !ELSE # Defined: use explicit directory or subdirectory # unless "NONE" is specified or it doesn't exist. !IF "$(PCRE_DIR)" == "NONE" !UNDEF PCRE_DIR !ELSE !IF "$(CPU)" == "i386" !IF !EXIST($(PCRE_DIR)) !UNDEF PCRE_DIR !ENDIF !ELSEIF "$(CPU)" == "AMD64" !IF EXIST($(PCRE_DIR)\x64) PCRE_DIR = $(PCRE_DIR)\x64 !ENDIF !ELSEIF "$(CPU)" == "IA64" !IF EXIST($(PCRE_DIR)\ia64) PCRE_DIR = $(PCRE_DIR)\ia64 !ENDIF !ENDIF !ENDIF !ENDIF !IFDEF PCRE_DIR PCRE_INCNAME = pcreposix.h PCRE_LIBNAME1 = pcre.lib PCRE_LIBNAME2 = pcreposix.lib PCRE_DLLNAME1 = pcre3.dll PCRE_DLLNAME2 = pcreposix3.dll PCRE_INCDIR = $(PCRE_DIR)\include PCRE_INCPATH = $(PCRE_DIR)\include\$(PCRE_INCNAME) PCRE_LIBPATH1 = $(PCRE_DIR)\lib\$(PCRE_LIBNAME1) PCRE_LIBPATH2 = $(PCRE_DIR)\lib\$(PCRE_LIBNAME2) PCRE_DLLPATH1 = $(PCRE_DIR)\bin\$(PCRE_DLLNAME1) PCRE_DLLPATH2 = $(PCRE_DIR)\bin\$(PCRE_DLLNAME2) !IF !EXIST("$(PCRE_INCPATH)") !ERROR PCRE_DIR "$(PCRE_INCPATH)" does not exist. Check PCRE_DIR !ELSEIF !EXIST("$(PCRE_LIBPATH1)") !ERROR PCRE_DIR "$(PCRE_LIBPATH1)" does not exist. Check PCRE_DIR !ELSEIF !EXIST("$(PCRE_LIBPATH2)") !ERROR PCRE_DIR "$(PCRE_LIBPATH2)" does not exist. Check PCRE_DIR !ELSEIF !EXIST("$(PCRE_DLLPATH1)") !ERROR PCRE_DIR "$(PCRE_DLLPATH1)" does not exist. Check PCRE_DIR !ELSEIF !EXIST("$(PCRE_DLLPATH2)") !ERROR PCRE_DIR "$(PCRE_DLLPATH2)" does not exist. Check PCRE_DIR !ENDIF !MESSAGE PCRE support will be included from "$(PCRE_DIR)" !ELSE !MESSAGE PCRE support will not be generated !ENDIF hercules-3.07/msvc.makefile.includes/PCRE_FLAGS.msvc000644 000765 000765 00000001551 11143760522 023636 0ustar00jmaynardjmaynard000000 000000 # *************************************************************************** # PCRE_FLAGS.msvc (!INCLUDE ed by "makefile-dllmod.msvc") # -------------------------------------------------------------------------- # (c) Copyright Roger Bowler, 2005-2007 # -------------------------------------------------------------------------- # $Id: PCRE_FLAGS.msvc 4884 2008-10-11 23:46:01Z fish $ # # Sets PCRE-related compiler/linker flags & #defines... # # # CHANGE HISTORY # $Log$ # # DD/MM/YY Description # # 26/12/06 Fish: created by extraction from existing makefile-dllmod.msvc # # *************************************************************************** !IFDEF PCRE_DIR LIBS = $(LIBS) "$(PCRE_LIBPATH1)" LIBS = $(LIBS) "$(PCRE_LIBPATH2)" cflags = $(cflags) /D HAVE_PCRE /I"$(PCRE_INCDIR)" /D PCRE_INCNAME=\"$(PCRE_INCNAME)\" !ENDIF hercules-3.07/msvc.makefile.includes/PCRE_RULES.msvc000644 000765 000765 00000002602 11335365455 023703 0ustar00jmaynardjmaynard000000 000000 # *************************************************************************** # PCRE_RULES.msvc (!INCLUDE ed by "makefile-dllmod.msvc") # -------------------------------------------------------------------------- # (c) Copyright Roger Bowler, 2005-2007 # -------------------------------------------------------------------------- # $Id: PCRE_RULES.msvc 5616 2010-02-08 23:44:59Z fish $ # # PCRE build rules... # # # CHANGE HISTORY # $Log$ # # DD/MM/YY Description # # 26/12/06 Fish: created by extraction from existing makefile-dllmod.msvc # 07/02/10 Fish: allHercules. # # *************************************************************************** !IFDEF PCRE_DIR $(X)$(PCRE_DLLNAME1): XCOPY "$(PCRE_DLLPATH1)" $(X) /V /C /F /H /R /K /O /X /Y $(X)$(PCRE_DLLNAME2): XCOPY "$(PCRE_DLLPATH2)" $(X) /V /C /F /H /R /K /O /X /Y allpcre: allHercules \ $(X)$(PCRE_DLLNAME1) \ $(X)$(PCRE_DLLNAME2) !ELSE allpcre: allHercules !ENDIF # NOTE: to be safe, since this member contains build rules, we need to # make sure there's always a blank line following the last build rule # in the member so that nmake doesn't complain or otherwise treat the # statements immediately following the original !INCLUDE statement as # part of the build rule actions. Thus the purpose of the comments you # are now reading as the very last few lines in every build rule member. hercules-3.07/msvc.makefile.includes/PRIM_RULES.msvc000644 000765 000765 00000006220 11344073445 023714 0ustar00jmaynardjmaynard000000 000000 # *************************************************************************** # PRIM_RULES.msvc (!INCLUDE ed by "makefile-dllmod.msvc") # -------------------------------------------------------------------------- # (c) Copyright Roger Bowler, 2005-2007 # -------------------------------------------------------------------------- # $Id: PRIM_RULES.msvc 5647 2010-03-03 15:26:15Z rbowler $ # # Primary generic build rules... ('all', 'clean', etc...) # # # CHANGE HISTORY # $Log$ # Revision 1.2 2008/10/11 23:47:05 fish # Fix MSVC build failure when 'rebase' utility doesn't exist # Add CVS "Id" and "Log" # # # DD/MM/YY Description # # 26/12/06 Fish: created by extraction from existing makefile-dllmod.msvc # 07/02/10 Fish: allHercules, rmdir DYNDIR, del fna # # *************************************************************************** # --------------------------------------------------------------------- # Primary build rules... # --------------------------------------------------------------------- all: allzlib alllibbz2 allpcre allHercules for %I in (rebase.exe) do if exist %~$$PATH:I rebase -b 0x400000 $(X)*.dll if exist $(EXEDIR)\*.manifest del /f /q $(EXEDIR)\*.manifest allHercules: $(OBJDIR) $(EXEDIR) $(PDBDIR) $(MAPDIR) $(ASMDIR) \ $(O)build_pch.pch \ $(MODULES) \ $(EXECUTABLES) clean: $(OBJDIR) $(EXEDIR) $(PDBDIR) $(MAPDIR) $(ASMDIR) if exist $(OBJDIR)\*.* rmdir /s /q $(OBJDIR) if exist $(EXEDIR)\*.* rmdir /s /q $(EXEDIR) if exist $(PDBDIR)\*.* rmdir /s /q $(PDBDIR) if exist $(MAPDIR)\*.* rmdir /s /q $(MAPDIR) !IFDEF ASSEMBLY_LISTINGS if exist $(ASMDIR)\*.* rmdir /s /q $(ASMDIR) !ENDIF !IFDEF DYNDIR if exist $(DYNDIR)\*.* rmdir /s /q $(DYNDIR) !ENDIF !IFDEF fna if exist $(fna) del /f /q $(fna) !ENDIF MT_EXE_CMD=if exist $@.manifest mt.exe -nologo -outputresource:$@;1 -manifest $@.manifest MT_DLL_CMD=if exist $@.manifest mt.exe -nologo -outputresource:$@;2 -manifest $@.manifest linkexe = $(link) -nologo $(ldebug) $(conlflags) $(O)build_pch.obj $** $(LIBS) -out:$@ -implib:$(O)$(@B).lib $(conlibsdll) $(MAPFILE) && $(MT_EXE_CMD) linkdll = $(link) -nologo $(ldebug) $(dlllflags) $(O)build_pch.obj $** $(LIBS) -out:$@ -implib:$(O)$(@B).lib $(conlibsdll) $(MAPFILE) && $(MT_DLL_CMD) {$(OBJDIR)}.obj{$(EXEDIR)}.exe: $(linkexe) {$(OBJDIR)}.obj{$(EXEDIR)}.dll: $(linkdll) # Dummy target entry: Since the primary target is .DLL # and .LIB is generated in the same step.. And .LIB # are used as input, the following generates an effective # rule, with no side effect {$(EXEDIR)}.dll{$(OBJDIR)}.lib: echo $* $@ .c{$(OBJDIR)}.obj:: $(cc) $(cdebug) $(cflags) /Fp"$(OBJDIR)\\build_pch.pch" /Yu"hstdinc.h" $(cvarsdll) /Fo"$(OBJDIR)\\" /Fd"$(OBJDIR)\\" $< # NOTE: to be safe, since this member contains build rules, we need to # make sure there's always a blank line following the last build rule # in the member so that nmake doesn't complain or otherwise treat the # statements immediately following the original !INCLUDE statement as # part of the build rule actions. Thus the purpose of the comments you # are now reading as the very last few lines in every build rule member. hercules-3.07/msvc.makefile.includes/VERSION.msvc000644 000765 000765 00000007421 11337307607 023326 0ustar00jmaynardjmaynard000000 000000 # *************************************************************************** # VERSION.msvc (!INCLUDE ed by "makefile-dllmod.msvc") # -------------------------------------------------------------------------- # (c) Copyright Roger Bowler, 2005-2007 # -------------------------------------------------------------------------- # $Id: VERSION.msvc 5635 2010-02-15 16:36:26Z rbowler $ # # Handles defining the product VERSION strings # # *************************************************************************** !UNDEF fna !IFNDEF VERSION # The following logic determines the Hercules version number and SVN # revision number and sets variables VERSION,V1,V2,V3,V4 when VERSION # is not already set by makefile.bat # First extract the Hercules version number from the configure.ac file. # We scan the file looking for AM_INIT_AUTOMAKE=(hercules,x.y[.z]) # # and we create a temporary file containing statements V1=x V2=y V3=z # Finally we include the temporary file to set the variables V1,V2,V3 opt = "tokens=1-5 delims=(),. " fna = $(TEMP)\hercver$(BUILD_TYPE).txt cmd = @echo V1=%c >$(fna) && @echo V2=%d >>$(fna) && @echo V3=%e >>$(fna) !IF ["for /f $(opt) %a in (configure.ac) do @if %a==AM_INIT_AUTOMAKE $(cmd)"] == 0 !INCLUDE $(fna) !ELSE V1 = 0 V2 = 0 !ENDIF # If svn.exe exists in the path, use the 'svn info' command to find the # subversion revision number, and write V4=nnnn to the temporary file. # Then include the temporary file to set the variable V4 opt="tokens=1-2 usebackq" cmd = for /f $(opt) %a in (`svn info`) do @if %a==Revision: @echo V4=%b>$(fna) !IF ["for %I in (svn.exe) do @if exist %~$$PATH:I $(cmd)"] == 0 !INCLUDE $(fna) !ENDIF # If V4 is not set, use the TortoiseSVN program subwcrev (if it exists in the path) # to find the subversion revision number, and write V4=nnnn to the temporary file. # Then include the temporary file to set the variable V4 !IF !DEFINED(V4) || "$(V4)" == "" opt="tokens=1-5 usebackq" cmd = for /f $(opt) %a in (`subwcrev .`) do @if %a%b==Lastcommitted @echo V4=%e>$(fna) !IF ["for %I in (subwcrev.exe) do @if exist %~$$PATH:I $(cmd)"] == 0 !INCLUDE $(fna) !ENDIF !ENDIF # If V4 is still not set, then set it to zero !IF !DEFINED(V4) || "$(V4)" == "" V4 = 0 !ENDIF # Set the version string x.y or x.y.z sharp = ^# !IF !DEFINED(V3) || "$(V3)" == "" || "$(V3)" == "$(sharp)" VERSION = $(V1).$(V2) V3 = 0 !ELSE VERSION = $(V1).$(V2).$(V3) !ENDIF # Append the subversion revision number to the version string !IF "$(V4)" != "0" VERSION = $(VERSION)-svn-$(V4) !ENDIF !MESSAGE Hercules version number is $(VERSION) ($(V1).$(V2).$(V3).$(V4)) VERSION = \"$(VERSION)\" !ELSE !IF !DEFINED(VERSION) || !DEFINED(V1) || !DEFINED(V2) || !DEFINED(V3) || !DEFINED(V4) ! ERROR 'VERSION=', 'V1=', 'V2=', 'V3=', and/or V4=' are undefined. Either build Hercules using the supplied 'makefile.bat' or set the variables manually yourself before invoking nmake. !ENDIF !MESSAGE VERSION = $(VERSION) ($(V1).$(V2).$(V3).$(V4)) !ENDIF !IF DEFINED(CUSTOM_BUILD_STRING) !MESSAGE CUSTOM_BUILD_STRING = $(CUSTOM_BUILD_STRING) !ENDIF !MESSAGE # The following logic determines the minimum version of Windows on which # the application can run. The minimum version depends on both the target # architecture and the version of Visual Studio used for the build. The # APPVER and TARGETOS variables are set as required by Win32.Mak (SDK) # # 32 bit : # VS < 9 : Win NT 4 & Win 9X (APPVER 4.0, TARGETOS BOTH) # VS >= 9 : Win 2K (APPVER 5.0, TARGETOS WINNT) # 64 bit : # Win 2K3 (APPVER 5.02, TARGETOS WINNT) # !IF (("$(CPU)" == "AMD64") || ("$(CPU)" == "IA64")) APPVER = 5.02 TARGETOS = WINNT !ELSE # 32 bit build !IF $(vsversion) < 9 APPVER = 4.0 TARGETOS = BOTH !ELSE # $(vsversion) >= 9 APPVER = 5.0 TARGETOS = WINNT !ENDIF # vsversion test !ENDIF # 32/64 bit test hercules-3.07/msvc.makefile.includes/ZLIB_DIR.msvc000644 000765 000765 00000005557 11224164166 023443 0ustar00jmaynardjmaynard000000 000000 # *************************************************************************** # ZLIB_DIR.msvc (!INCLUDE ed by "makefile-dllmod.msvc") # -------------------------------------------------------------------------- # (c) Copyright Roger Bowler, 2005-2007 # -------------------------------------------------------------------------- # $Id: ZLIB_DIR.msvc 5407 2009-06-14 18:34:54Z fish $ # # Handles support for ZLIB compression # # *************************************************************************** # --------------------------------------------------------------------- # To enable ZLIB compression, first make sure you have the ZLIB dll # installed on your system (downloadable from http://www.zlib.net), # and then define an environment variable called "ZLIB_DIR" that # specifies the full path to the directory where it is installed. # (via the "Advanced" tab of the Control Panel 'System' applet). # # Note that the directory you specify should: a) hold the zlib1.dll # itself, b) contain two sub-directories called 'include' and 'lib' # where the 'zlib.h', zconf.h' and 'zdll.lib', etc, files reside. # # Note: if the path contains blanks, do NOT surround it with quotes! # The makefile will do that if it needs to. Just define the variable # with the path as-is. E.g.: # # ZLIB_DIR = E:\MyProjects\zlib and bzip2 dlls\zlib latest\zlib122-dll # ZLIB_DIR = C:\winbuild\zlib\win32_32 # --------------------------------------------------------------------- !IFNDEF ZLIB_DIR # Undefined: use default value, if it exists. # ZLIB_DIR defaults to winbuild\zlib relative to current directory !IF "$(CPU)" == "i386" && EXIST(winbuild\zlib\win32_32) # Avoid breaking existing builds, use win32_32 subdir if it exists ZLIB_DIR = winbuild\zlib\win32_32 !ELSEIF "$(CPU)" == "i386" && EXIST(winbuild\zlib) ZLIB_DIR = winbuild\zlib !ELSEIF "$(CPU)" == "AMD64" && EXIST(winbuild\zlib\x64) ZLIB_DIR = winbuild\zlib\x64 !ELSEIF "$(CPU)" == "IA64" && EXIST(winbuild\zlib\ia64) ZLIB_DIR = winbuild\zlib\ia64 !ENDIF !ELSE # Defined: use explicit directory or subdirectory # unless "NONE" is specified or it doesn't exist. !IF "$(ZLIB_DIR)" == "NONE" !UNDEF ZLIB_DIR !ELSE !IF "$(CPU)" == "i386" !IF !EXIST($(ZLIB_DIR)) !UNDEF ZLIB_DIR !ENDIF !ELSEIF "$(CPU)" == "AMD64" !IF EXIST($(ZLIB_DIR)\x64) ZLIB_DIR = $(ZLIB_DIR)\x64 !ENDIF !ELSEIF "$(CPU)" == "IA64" !IF EXIST($(ZLIB_DIR)\ia64) ZLIB_DIR = $(ZLIB_DIR)\ia64 !ENDIF !ENDIF !ENDIF !ENDIF !IFDEF ZLIB_DIR !IF !EXIST("$(ZLIB_DIR)\include\zlib.h") !ERROR ZLIB_DIR "$(ZLIB_DIR)\include\zlib.h" does not exist. Check ZLIB_DIR !ELSEIF !EXIST("$(ZLIB_DIR)\lib\zdll.lib") !ERROR ZLIB_DIR "$(ZLIB_DIR)\lib\zdll.lib" does not exist. Check ZLIB_DIR !ELSEIF !EXIST("$(ZLIB_DIR)\zlib1.dll") !ERROR ZLIB_DIR "$(ZLIB_DIR)\zlib1.dll" does not exist. Check ZLIB_DIR !ENDIF !MESSAGE ZLIB support will be included from "$(ZLIB_DIR)" !ELSE !MESSAGE ZLIB support will not be generated !ENDIF hercules-3.07/msvc.makefile.includes/ZLIB_FLAGS.msvc000644 000765 000765 00000001634 11143760522 023647 0ustar00jmaynardjmaynard000000 000000 # *************************************************************************** # ZLIB_FLAGS.msvc (!INCLUDE ed by "makefile-dllmod.msvc") # -------------------------------------------------------------------------- # (c) Copyright Roger Bowler, 2005-2007 # -------------------------------------------------------------------------- # $Id: ZLIB_FLAGS.msvc 4884 2008-10-11 23:46:01Z fish $ # # Sets ZLIB-compression-related compiler/linker flags & #defines... # # # CHANGE HISTORY # $Log$ # # DD/MM/YY Description # # 26/12/06 Fish: created by extraction from existing makefile-dllmod.msvc # # *************************************************************************** !IFDEF ZLIB_DIR ZLIB_DLL = $(ZLIB_DIR)\zlib1.dll ZLIB_LIB = $(ZLIB_DIR)/lib/zdll.lib ZLIB_INC = $(ZLIB_DIR)/include LIBS = $(LIBS) "$(ZLIB_LIB)" cflags = $(cflags) /D HAVE_LIBZ /D HAVE_ZLIB_H /I"$(ZLIB_INC)" !ENDIF hercules-3.07/msvc.makefile.includes/ZLIB_RULES.msvc000644 000765 000765 00000002400 11335365455 023706 0ustar00jmaynardjmaynard000000 000000 # *************************************************************************** # ZLIB_RULES.msvc (!INCLUDE ed by "makefile-dllmod.msvc") # -------------------------------------------------------------------------- # (c) Copyright Roger Bowler, 2005-2007 # -------------------------------------------------------------------------- # $Id: ZLIB_RULES.msvc 5616 2010-02-08 23:44:59Z fish $ # # ZLIB build rules... # # # CHANGE HISTORY # $Log$ # # DD/MM/YY Description # # 26/12/06 Fish: created by extraction from existing makefile-dllmod.msvc # 07/02/10 Fish: allHercules. # # *************************************************************************** !IFDEF ZLIB_DIR $(X)zlib1.dll: XCOPY "$(ZLIB_DLL)" $(X) /V /C /F /H /R /K /O /X /Y allzlib: allHercules \ $(X)zlib1.dll !ELSE allzlib: allHercules !ENDIF # NOTE: to be safe, since this member contains build rules, we need to # make sure there's always a blank line following the last build rule # in the member so that nmake doesn't complain or otherwise treat the # statements immediately following the original !INCLUDE statement as # part of the build rule actions. Thus the purpose of the comments you # are now reading as the very last few lines in every build rule member. hercules-3.07/man/cckd.4000644 000765 000765 00000012116 11143760526 016515 0ustar00jmaynardjmaynard000000 000000 .TH cckd 4 "2003-02-03" .SH NAME \fBcckd\fP - Hercules Compressed CKD DASD image file .SH DESCRIPTION Hercules DASD image file that emulates IBM mainframe DASD devices on a (usually) non-mainframe platform. Specified in the Hercules configuration file (default name hercules.cnf) to describe the DASD devices Hercules is to emulate. Also specified as input and/or output file to several Hercules utilities. Hercules compressed DASD devices are frequently referred to as CCKD. Hercules uncompressed DASD devices are frequently referred to as CKD. Hercules CKD DASD image files are largely compatible with P/390 AWS DASD files. .SH TECHNICAL OVERVIEW The following provides a technical overview of CCKD internal structures. Except as indicated below, data in the following structures is stored in the byte order indicated by the CDEVHDR.options CCKD_BIGENDIAN bit (the 0x02 bit). This bit is 1 when data is big-endian byte order, 0 when data is little-endian byte order. .SS DEVHDR occupies the first 512 bytes of a CKD or CCKD DASD file. The DEVHDR contains the device type and the number of heads per cylinder. Its contents are the same whether the DASD image is compressed (CCKD) or not (CKD). Described by the CKDDASD_DEVHDR struct; 512 bytes in size. .SS CDEVHDR immediately follows the DEVHDR, and contains fields describing the number of L1ENTs in the L1TAB, the number of L2ENTs in each L2TAB, and anchors the free space chain. Described by the CCKDDASD_DEVHDR struct; 512 bytes in size. .SS L1TAB immediately follows the CDEVHDR, and consists of L1ENT entries, each of which points to an L2TAB. Each L1ENT is an U32 (4 bytes) offset into the CCKD DASD file. The CDEVHDR numl1tab field describes how many L1ENTs are in the L1TAB. L1ENTs are described by the CCKD_L1ENT typedef; the L1TAB is of variable size. Conceptually each L1ENT describes cdevhdr.numl2tab tracks. .SS L2TAB is pointed to by an L1ENT, and is composed of L2ENT entries, the number of which is described by the CDEVHDR numl2tab field; currently 256 L2ENTs in each L2TAB. L2ENTs contain the offset to the TRKHDR, and the combined length of the TRKHDR and (optionally) compressed track data. The CDEVHDR numl2tab field describes how many L2ENTs are in each L2TAB. Currently, there are 256 L2ENTs in each L2TAB. Described by the CCKD_L2ENT struct; (256 * 8) bytes in size. Conceptually each L2ENT describes one track. .SS FREEBLK describes free space in the CCKD DASD image, anchored by the CDEVHDR free field. Consists of a 4 byte offset to the next free space (or zero for end of free space chain), and a 4 byte length of the free space (which length includes the 8 bytes occupied by the FREEBLK itself), followed by zero or more bytes of residual data. Described by the first 8 bytes of the CCKD_FREEBLK struct; 8 bytes in size. .SS TRKHDR Occurs once at the beginning of each track. contains flag (one byte), CC (two bytes), and HH (two bytes) of the track. When the flag byte = 0x00, TRKHDR is the same as the Home Address on real DASD. Flag bits are described in hercules.h, and are of the format nlllllcc where n=1 for new track header format, lllll is used for track recovery purposes, and cc describes the track compression algorithm. The compression algorithms are: B'00' = uncompressed, B'01' = zlib, B'10' = bzip2, B'11' is currently invalid. Data in TRKHDR is stored in big-endian byte order. Described by the CKDDASD_TRKHDR struct; 5 bytes in size. .SS COUNT field 8 bytes, containing CC (two bytes), HH (two bytes), R (one byte), KL (one byte), and DL (two bytes). CC is the (relative zero) cylinder number. HH is the (relative zero) head number. R is the (relative zero) record number on the track. KL is the key length; if zero no key is present. DL is the length of the data record. Data in the COUNT field is stored in big-endian byte order. Described by the CKDDASD_RECHDR struct; 8 bytes in size. .SS KEY field if present, KL bytes of record key; immediately follows the COUNT field. Byte order is not a factor for the KEY field; to the extent it is examined by Hercules code it is simply a byte stream. Size varies. .SS DATA field. if present, DL bytes of record data; immediately follows the KEY field for keyed record, else immediately follows the COUNT field for unkeyed records. Byte order is not a factor for the DATA field; to the extent it is examined by Hercules code it is simply a byte stream. Size varies. .SH GLOSSARY .SS CKD Count, Key, Data - contents of an track. Also refers to the Hercules uncompressed DASD image file. .SS CCKD Compressed Count, Key, Data - compressed contents of a track. Also refers to the Hercules compressed DASD image file. .SS DASD Direct Access Storage Device - term the IBM mainframe world uses to refer to hard drives. .SS EOT End Of Track - indicated by 8X'FF' in the COUNT field. .SH "SEE ALSO" .TP \fBhttp://www.hercules-390.org/\fP the Hercules emulator homepage. .TP \fBhttp://www.hercules-390.org/cckddasd.html\fP which describes the Hercules CCKD DASD facility. .TP \fBhttp://www.hercules-390.org/hercconf.html\fP which describes the Hercules configuration file. .SH HISTORY 2003-02-07 originally written by James M. Morrison hercules-3.07/man/cckddiag.1000644 000765 000765 00000005316 11143760526 017343 0ustar00jmaynardjmaynard000000 000000 .TH cckddiag 1 "2003-02-03" .SH NAME \fBcckddiag\fP - Hercules CCKD DASD diagnostic tool .SH SYNOPSIS \fBcckddiag\fP [options...] \fBfilename\fP .SH DESCRIPTION Hercules support tool used to assist in the diagnosis of CCKD DASD problems. Operates on Hercules CCKD DASD volumes in read-only mode, and displays various information contained in CCKD DASD files. Effective usage requires internal knowledge of Hercules CCKD DASD files. .SH OPTIONS The following options are used to specify which portions of the CCKD DASD file are to be displayed. Options may not be combined; for example, -cd1 is not a valid option. Surround each option by blank(s). Argument numbers may be specified either in decimal or hexadecimal. If the number begins with the characters 0x the number is presumed to be hexadecimal; else the number is presumed to be decimal. No numeric overflow checking is done, the user is assumed (!) to know what they're doing. Options are divided into three categories: \fBglobal options\fP, \fBtrack-related options\fP, and \fBthe offset option\fP. .SH Global options .SS filename specifies the Hercules CCKD DASD filename (sometimes referred to as the DASD image file) .SS -v display version and exit .SS -d display DEVHDR .SS -c display CDEVHDR .SS -1 display L1TAB (note this option is a numeric one) .SS -g enable debug output .SH Track-related options To direct cckddiag to a specific track, two options are provided: -a and -r. The remaining track-related options describe the kind of output desired. The TRKHDR for the track is displayed for all track-related options. .SS -a cc hh display \fBabsolute\fP CCHH data - where \fBcc\fP and \fBhh\fP are respectively the cylinder number (relative zero), and the head number (relative zero). .SS -r tt display \fBrelative\fP track data - where \fBtt\fP is the track number (relative zero). .SS -2 display L2TAB - requires a corresponding -a or -r specification to direct cckddiag to a specific track. .SS -t display track data - displays the COUNT, KEY, and DATA record summaries for the data residing on the indicated track. .SS -x hex display track key/data - displays the KEY and DATA records' contents in hexadecimal display format for the indicated track. Some repetitive data may be omitted from the hex display output. .SH Offset option This option provides the ability to examine any portion of the CCKD file, as an alternative to track specification. .SS -o oo ll hex display data at offset \fBoo\fP of length \fBll\fP. .SH "SEE ALSO" .TP cckd(4) .TP http://www.hercules-390.org/ the Hercules emulator homepage. .TP http://www.hercules-390.org/cckddasd.html which describes the Hercules CCKD DASD facility. .SH HISTORY 2003-02-07 originally written by James M. Morrison hercules-3.07/man/dasdseq.1000644 000765 000765 00000010410 11143760526 017225 0ustar00jmaynardjmaynard000000 000000 .TH dasdseq 1 "2003-03-10" .SH NAME \fBdasdseq\fP - Hercules DSORG=PS retrieval command .SH SYNOPSIS \fBdasdseq\fP [options...] \fBimage \fP[sf=shadow] \fBfilespec\fP .br \fBdasdseq \fP[-debug] [-expert] [-ascii] \fBimage \fP[sf=shadow] [attr] \fBfilespec \fP[debugopts] [ascii] .SH DESCRIPTION Hercules command to retrieve a DSORG=PS (sequential) dataset from CKD/CCKD DASD. The dataset is presumed to be encoded in EBCDIC. The second form of the command is for 'expert mode' users, and allows more advanced access to data on the DASD image. .SH OPTIONS The following options are used to specify dasdseq behavior. Surround each option by blank(s). Options are divided into three categories: \fBrequired, optional, and expert mode operands.\fP .SH Required operands .SS image specifies the Hercules CKD/CCKD DASD filename (sometimes referred to as the DASD image file) .SS filespec dataset name of the file to retrieve. Case insensitive, converted to upper case for searching VTOC on image DASD volume. .SH Optional operands .SS sf=shadow For CCKD images which also use shadow files, specifies the [path/]filename of the shadow file. Note the sf=, which must be present for this option. .SS -ascii convert the output file to ASCII (from EBCDIC). Additionally, trailing blanks are trimmed. The 'ascii' option (no leading dash) is deprecated, and may be removed in a future release. .SH Expert mode operands All expert mode operands are considered to be experimental. \fB dasdseq [-debug] [-expert] [-ascii] image [sf=shadow] [attr] filespec [debugopts]\fP .SS -debug Additional debug options are displayed. Specifying -debug will (eventually) display dataset extent information. .SS attr dataset attributes (only useful with -abs) \fB[-recfm fb] [-lrecl aa]\fP -recfm designates RECFM, reserved for future support fb - fixed, blocked (only RECFM currently supported) -lrecl designates dataset LRECL aa - decimal logical record length (default 80) Blocksize need not be specified; dasdseq handles whatever block size comes off the volume. .SS filespec composed of the following sub-operands, in the following order: \fBheads, abs, filename.\fP .SS -heads xx defines # tracks per cylinder on device; xx = decimal number of heads per cylinder on device .SS -abs cc hh tt [...] [-abs cc hh tt] -abs indicates the beginning of each extent's location in terms of absolute dasd image location. cc - decimal cylinder number (relative zero) hh - decimal head number (relative zero) tt - decimal number of tracks in extent When -abs is specified, each -abs group specifies one dataset extent. For multi-extent datasets, -abs groups may be repeated as needed, in the order in which the dataset's extents occur. A maximum of 123 extents are supported. With -abs, no VTOC structure is implied; a F1 DSCB will not be sought. Dasdseq will frequently report 'track not found in extent table' (along with a message from fbcopy about rc -1 from convert_tt) due to potentially missing EOF markers in the extent, and the fact that the F1 DSCB DS1LSTAR field is not valid. Check your output file before you panic. Fbcopy -abs ignores EOF, in case you are attempting to recovery PDS member(s) from a damaged dasd volume, preferring to wait until all tracks in the extent have been processed. Tracks containing PDS members may have more than one EOF per track. Expect a lot of associated manual effort with -abs. When -abs is -not- specified, filename specifies the MVS DSORG=PS dataset on the volume. The dasd image volume containing the dataset must have a valid VTOC structure, and a F1 DSCB describing the dataset. .SS filename will be the filename of the output file in the current directory; output filename in the same case as the command line filename. .SS debugopts Produces debugging output, refer to the source code. \fBverbose [x [y [z]]]\fP verbose debug output level (default = 0 when not specified). Higher numbers produce more output. x main program (default = 1 when verbose specified) y copyfile + showf1 z dasdutil .SH "SEE ALSO" .TP dasdpdsu for DSORG=PO datasets .TP cckd(4) for CCKD DASD .TP http://www.hercules-390.org/cckddasd.html which describes the Hercules CCKD DASD facility. .TP http://www.hercules-390.org/ the Hercules emulator homepage. .SH HISTORY 2003-03-10 originally written by James M. Morrison hercules-3.07/man/Makefile.am000644 000765 000765 00000000103 11143760526 017551 0ustar00jmaynardjmaynard000000 000000 man_MANS = cckddiag.1 cckd.4 dasdseq.1 EXTRA_DIST = $(man_MANS) hercules-3.07/man/Makefile.in000644 000765 000765 00000032725 11344713141 017573 0ustar00jmaynardjmaynard000000 000000 # Makefile.in generated by automake 1.9.6 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = .. am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd INSTALL = @INSTALL@ install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = man DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/autoconf/hercules.m4 \ $(top_srcdir)/autoconf/libtool.m4 \ $(top_srcdir)/autoconf/ltdl.m4 $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(SHELL) $(top_srcdir)/autoconf/mkinstalldirs CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = SOURCES = DIST_SOURCES = man1dir = $(mandir)/man1 am__installdirs = "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(man4dir)" man4dir = $(mandir)/man4 NROFF = nroff MANS = $(man_MANS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BUILD_FISHHANG_FALSE = @BUILD_FISHHANG_FALSE@ BUILD_FISHHANG_TRUE = @BUILD_FISHHANG_TRUE@ BUILD_FTHREADS_FALSE = @BUILD_FTHREADS_FALSE@ BUILD_FTHREADS_TRUE = @BUILD_FTHREADS_TRUE@ BUILD_HERCIFC_FALSE = @BUILD_HERCIFC_FALSE@ BUILD_HERCIFC_TRUE = @BUILD_HERCIFC_TRUE@ BUILD_SHARED_FALSE = @BUILD_SHARED_FALSE@ BUILD_SHARED_TRUE = @BUILD_SHARED_TRUE@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CONVENIENCE_LTDL_FALSE = @CONVENIENCE_LTDL_FALSE@ CONVENIENCE_LTDL_TRUE = @CONVENIENCE_LTDL_TRUE@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ ECHO = @ECHO@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ F77 = @F77@ FFLAGS = @FFLAGS@ GMSGFMT = @GMSGFMT@ GREP = @GREP@ HERCIFC_GROUPNAME = @HERCIFC_GROUPNAME@ HERCIFC_GROUPSET_FALSE = @HERCIFC_GROUPSET_FALSE@ HERCIFC_GROUPSET_TRUE = @HERCIFC_GROUPSET_TRUE@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_LTDL_FALSE = @INSTALL_LTDL_FALSE@ INSTALL_LTDL_TRUE = @INSTALL_LTDL_TRUE@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ LDFLAGS = @LDFLAGS@ LIBADD_DL = @LIBADD_DL@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBTOOL_DEPS = @LIBTOOL_DEPS@ LN_S = @LN_S@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@ MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@ MAKEINFO = @MAKEINFO@ MKINSTALLDIRS = @MKINSTALLDIRS@ MSGFMT = @MSGFMT@ MSGMERGE = @MSGMERGE@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPTION_DYNAMIC_LOAD_FALSE = @OPTION_DYNAMIC_LOAD_FALSE@ OPTION_DYNAMIC_LOAD_TRUE = @OPTION_DYNAMIC_LOAD_TRUE@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ POSUB = @POSUB@ RANLIB = @RANLIB@ SETUID_HERCIFC_FALSE = @SETUID_HERCIFC_FALSE@ SETUID_HERCIFC_TRUE = @SETUID_HERCIFC_TRUE@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ USE_DLLTOOL_FALSE = @USE_DLLTOOL_FALSE@ USE_DLLTOOL_TRUE = @USE_DLLTOOL_TRUE@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_F77 = @ac_ct_F77@ am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ modexecdir = @modexecdir@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ man_MANS = cckddiag.1 cckd.4 dasdseq.1 EXTRA_DIST = $(man_MANS) all: all-am .SUFFIXES: $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ && exit 0; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu man/Makefile'; \ cd $(top_srcdir) && \ $(AUTOMAKE) --gnu man/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs distclean-libtool: -rm -f libtool uninstall-info-am: install-man1: $(man1_MANS) $(man_MANS) @$(NORMAL_INSTALL) test -z "$(man1dir)" || $(mkdir_p) "$(DESTDIR)$(man1dir)" @list='$(man1_MANS) $(dist_man1_MANS) $(nodist_man1_MANS)'; \ l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \ for i in $$l2; do \ case "$$i" in \ *.1*) list="$$list $$i" ;; \ esac; \ done; \ for i in $$list; do \ if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \ else file=$$i; fi; \ ext=`echo $$i | sed -e 's/^.*\\.//'`; \ case "$$ext" in \ 1*) ;; \ *) ext='1' ;; \ esac; \ inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ inst=`echo $$inst | sed -e 's/^.*\///'`; \ inst=`echo $$inst | sed '$(transform)'`.$$ext; \ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst"; \ done uninstall-man1: @$(NORMAL_UNINSTALL) @list='$(man1_MANS) $(dist_man1_MANS) $(nodist_man1_MANS)'; \ l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \ for i in $$l2; do \ case "$$i" in \ *.1*) list="$$list $$i" ;; \ esac; \ done; \ for i in $$list; do \ ext=`echo $$i | sed -e 's/^.*\\.//'`; \ case "$$ext" in \ 1*) ;; \ *) ext='1' ;; \ esac; \ inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ inst=`echo $$inst | sed -e 's/^.*\///'`; \ inst=`echo $$inst | sed '$(transform)'`.$$ext; \ echo " rm -f '$(DESTDIR)$(man1dir)/$$inst'"; \ rm -f "$(DESTDIR)$(man1dir)/$$inst"; \ done install-man4: $(man4_MANS) $(man_MANS) @$(NORMAL_INSTALL) test -z "$(man4dir)" || $(mkdir_p) "$(DESTDIR)$(man4dir)" @list='$(man4_MANS) $(dist_man4_MANS) $(nodist_man4_MANS)'; \ l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \ for i in $$l2; do \ case "$$i" in \ *.4*) list="$$list $$i" ;; \ esac; \ done; \ for i in $$list; do \ if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \ else file=$$i; fi; \ ext=`echo $$i | sed -e 's/^.*\\.//'`; \ case "$$ext" in \ 4*) ;; \ *) ext='4' ;; \ esac; \ inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ inst=`echo $$inst | sed -e 's/^.*\///'`; \ inst=`echo $$inst | sed '$(transform)'`.$$ext; \ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man4dir)/$$inst'"; \ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man4dir)/$$inst"; \ done uninstall-man4: @$(NORMAL_UNINSTALL) @list='$(man4_MANS) $(dist_man4_MANS) $(nodist_man4_MANS)'; \ l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \ for i in $$l2; do \ case "$$i" in \ *.4*) list="$$list $$i" ;; \ esac; \ done; \ for i in $$list; do \ ext=`echo $$i | sed -e 's/^.*\\.//'`; \ case "$$ext" in \ 4*) ;; \ *) ext='4' ;; \ esac; \ inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ inst=`echo $$inst | sed -e 's/^.*\///'`; \ inst=`echo $$inst | sed '$(transform)'`.$$ext; \ echo " rm -f '$(DESTDIR)$(man4dir)/$$inst'"; \ rm -f "$(DESTDIR)$(man4dir)/$$inst"; \ done tags: TAGS TAGS: ctags: CTAGS CTAGS: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ list='$(DISTFILES)'; for file in $$list; do \ case $$file in \ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ esac; \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ if test "$$dir" != "$$file" && test "$$dir" != "."; then \ dir="/$$dir"; \ $(mkdir_p) "$(distdir)$$dir"; \ else \ dir=''; \ fi; \ if test -d $$d/$$file; then \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ fi; \ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(MANS) installdirs: for dir in "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(man4dir)"; do \ test -z "$$dir" || $(mkdir_p) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic distclean-libtool dvi: dvi-am dvi-am: html: html-am info: info-am info-am: install-data-am: install-man install-exec-am: install-info: install-info-am install-man: install-man1 install-man4 installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-info-am uninstall-man uninstall-man: uninstall-man1 uninstall-man4 .PHONY: all all-am check check-am clean clean-generic clean-libtool \ distclean distclean-generic distclean-libtool distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-exec install-exec-am \ install-info install-info-am install-man install-man1 \ install-man4 install-strip installcheck installcheck-am \ installdirs maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ ps ps-am uninstall uninstall-am uninstall-info-am \ uninstall-man uninstall-man1 uninstall-man4 # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: hercules-3.07/m4/ChangeLog000644 000765 000765 00000002545 11143760524 017046 0ustar00jmaynardjmaynard000000 000000 2005-05-12 gettextize * codeset.m4: Upgrade to gettext-0.14.4. * gettext.m4: Upgrade to gettext-0.14.4. * glibc2.m4: New file, from gettext-0.14.4. * glibc21.m4: Upgrade to gettext-0.14.4. * iconv.m4: Upgrade to gettext-0.14.4. * intdiv0.m4: Upgrade to gettext-0.14.4. * intmax.m4: New file, from gettext-0.14.4. * inttypes.m4: Upgrade to gettext-0.14.4. * inttypes_h.m4: Upgrade to gettext-0.14.4. * inttypes-pri.m4: Upgrade to gettext-0.14.4. * isc-posix.m4: Upgrade to gettext-0.14.4. * lcmessage.m4: Upgrade to gettext-0.14.4. * lib-ld.m4: Upgrade to gettext-0.14.4. * lib-link.m4: Upgrade to gettext-0.14.4. * lib-prefix.m4: Upgrade to gettext-0.14.4. * longdouble.m4: New file, from gettext-0.14.4. * longlong.m4: New file, from gettext-0.14.4. * nls.m4: New file, from gettext-0.14.4. * po.m4: New file, from gettext-0.14.4. * printf-posix.m4: New file, from gettext-0.14.4. * progtest.m4: Upgrade to gettext-0.14.4. * signed.m4: New file, from gettext-0.14.4. * size_max.m4: New file, from gettext-0.14.4. * stdint_h.m4: Upgrade to gettext-0.14.4. * uintmax_t.m4: Upgrade to gettext-0.14.4. * ulonglong.m4: Upgrade to gettext-0.14.4. * wchar_t.m4: New file, from gettext-0.14.4. * wint_t.m4: New file, from gettext-0.14.4. * xsize.m4: New file, from gettext-0.14.4. * Makefile.am (EXTRA_DIST): Add the new files. hercules-3.07/m4/codeset.m4000644 000765 000765 00000001351 11143760524 017156 0ustar00jmaynardjmaynard000000 000000 # codeset.m4 serial AM1 (gettext-0.10.40) dnl Copyright (C) 2000-2002 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl From Bruno Haible. AC_DEFUN([AM_LANGINFO_CODESET], [ AC_CACHE_CHECK([for nl_langinfo and CODESET], am_cv_langinfo_codeset, [AC_TRY_LINK([#include ], [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 ]) hercules-3.07/m4/gettext.m4000644 000765 000765 00000051667 11143760524 017233 0ustar00jmaynardjmaynard000000 000000 # gettext.m4 serial 37 (gettext-0.14.4) dnl Copyright (C) 1995-2005 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl dnl This file can can be used in projects which are not available under dnl the GNU General Public License or the GNU Library General Public dnl License but which still want to provide support for the GNU gettext dnl functionality. dnl Please note that the actual code of the GNU gettext library is covered dnl by the GNU Library General Public License, and the rest of the GNU dnl gettext package package is covered by the GNU General Public License. dnl They are *not* in the public domain. dnl Authors: dnl Ulrich Drepper , 1995-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 Sometimes, on MacOS X, libintl requires linking with CoreFoundation. gt_INTL_MACOSX 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 * gettext ("")]ifelse([$2], [need-ngettext], [ + * 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 (const char *);], [bindtextdomain ("", ""); return * gettext ("")]ifelse([$2], [need-ngettext], [ + * ngettext ("", "", 0)], [])[ + _nl_msg_cat_cntr + *_nl_expand_alias ("")], 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 (const char *);], [bindtextdomain ("", ""); return * gettext ("")]ifelse([$2], [need-ngettext], [ + * ngettext ("", "", 0)], [])[ + _nl_msg_cat_cntr + *_nl_expand_alias ("")], [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 CATOBJEXT= if test "$gt_use_preinstalled_gnugettext" = "yes" \ || test "$nls_cv_use_gnu_gettext" = "yes"; then dnl Mark actions to use GNU gettext tools. CATOBJEXT=.gmo fi ]) if test -n "$INTL_MACOSX_LIBS"; then if test "$gt_use_preinstalled_gnugettext" = "yes" \ || test "$nls_cv_use_gnu_gettext" = "yes"; then dnl Some extra flags are needed during linking. LIBINTL="$LIBINTL $INTL_MACOSX_LIBS" LTLIBINTL="$LTLIBINTL $INTL_MACOSX_LIBS" fi fi if test "$gt_use_preinstalled_gnugettext" = "yes" \ || test "$nls_cv_use_gnu_gettext" = "yes"; then AC_DEFINE(ENABLE_NLS, 1, [Define to 1 if translation of program messages to the user's native language is requested.]) else USE_NLS=no fi fi AC_MSG_CHECKING([whether to use NLS]) AC_MSG_RESULT([$USE_NLS]) if test "$USE_NLS" = "yes"; then AC_MSG_CHECKING([where the gettext function comes from]) if test "$gt_use_preinstalled_gnugettext" = "yes"; then if 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. INTLOBJS= if test "$USE_INCLUDED_LIBINTL" = yes; then INTLOBJS="\$(GETTOBJS)" fi AC_SUBST(INTLOBJS) dnl Enable libtool support if the surrounding package wishes it. INTL_LIBTOOL_SUFFIX_PREFIX=gt_libtool_suffix_prefix AC_SUBST(INTL_LIBTOOL_SUFFIX_PREFIX) ]) dnl For backward compatibility. Some Makefiles may be using this. INTLLIBS="$LIBINTL" AC_SUBST(INTLLIBS) dnl Make all documented variables known to autoconf. AC_SUBST(LIBINTL) AC_SUBST(LTLIBINTL) AC_SUBST(POSUB) ]) dnl 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([gt_GLIBC2])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([gl_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([gl_AC_HEADER_INTTYPES_H]) AC_REQUIRE([gl_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([gl_GLIBC21])dnl AC_REQUIRE([gt_INTDIV0])dnl AC_REQUIRE([gl_AC_TYPE_UINTMAX_T])dnl AC_REQUIRE([gt_HEADER_INTTYPES_H])dnl AC_REQUIRE([gt_INTTYPES_PRI])dnl AC_REQUIRE([gl_XSIZE])dnl AC_REQUIRE([gt_INTL_MACOSX])dnl AC_CHECK_TYPE([ptrdiff_t], , [AC_DEFINE([ptrdiff_t], [long], [Define as the type of the result of subtracting two pointers, if the system doesn't define it.]) ]) AC_CHECK_HEADERS([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 gt_LC_MESSAGES fi if test -n "$INTL_MACOSX_LIBS"; then CPPFLAGS="$CPPFLAGS -I/System/Library/Frameworks/CoreFoundation.framework/Headers" 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 Checks for special options needed on MacOS X. dnl Defines INTL_MACOSX_LIBS. AC_DEFUN([gt_INTL_MACOSX], [ dnl Check for API introduced in MacOS X 10.2. AC_CACHE_CHECK([for CFPreferencesCopyAppValue], gt_cv_func_CFPreferencesCopyAppValue, [gt_save_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$CPPFLAGS -I/System/Library/Frameworks/CoreFoundation.framework/Headers" gt_save_LIBS="$LIBS" LIBS="$LIBS -framework CoreFoundation" AC_TRY_LINK([#include ], [CFPreferencesCopyAppValue(NULL, NULL)], [gt_cv_func_CFPreferencesCopyAppValue=yes], [gt_cv_func_CFPreferencesCopyAppValue=no]) CPPFLAGS="$gt_save_CPPFLAGS" LIBS="$gt_save_LIBS"]) if test $gt_cv_func_CFPreferencesCopyAppValue = yes; then AC_DEFINE([HAVE_CFPREFERENCESCOPYAPPVALUE], 1, [Define to 1 if you have the MacOS X function CFPreferencesCopyAppValue in the CoreFoundation framework.]) fi dnl Check for API introduced in MacOS X 10.3. AC_CACHE_CHECK([for CFLocaleCopyCurrent], gt_cv_func_CFLocaleCopyCurrent, [gt_save_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$CPPFLAGS -I/System/Library/Frameworks/CoreFoundation.framework/Headers" gt_save_LIBS="$LIBS" LIBS="$LIBS -framework CoreFoundation" AC_TRY_LINK([#include ], [CFLocaleCopyCurrent();], [gt_cv_func_CFLocaleCopyCurrent=yes], [gt_cv_func_CFLocaleCopyCurrent=no]) CPPFLAGS="$gt_save_CPPFLAGS" LIBS="$gt_save_LIBS"]) if test $gt_cv_func_CFLocaleCopyCurrent = yes; then AC_DEFINE([HAVE_CFLOCALECOPYCURRENT], 1, [Define to 1 if you have the MacOS X function CFLocaleCopyCurrent in the CoreFoundation framework.]) fi INTL_MACOSX_LIBS= if test $gt_cv_func_CFPreferencesCopyAppValue = yes || test $gt_cv_func_CFLocaleCopyCurrent = yes; then INTL_MACOSX_LIBS="-Wl,-framework -Wl,CoreFoundation" fi AC_SUBST([INTL_MACOSX_LIBS]) ]) 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], []) hercules-3.07/m4/glibc2.m4000644 000765 000765 00000001354 11143760524 016675 0ustar00jmaynardjmaynard000000 000000 # glibc2.m4 serial 1 dnl Copyright (C) 2000-2002, 2004 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. # Test for the GNU C Library, version 2.0 or newer. # From Bruno Haible. AC_DEFUN([gt_GLIBC2], [ AC_CACHE_CHECK(whether we are using the GNU C Library 2 or newer, ac_cv_gnu_library_2, [AC_EGREP_CPP([Lucky GNU user], [ #include #ifdef __GNU_LIBRARY__ #if (__GLIBC__ >= 2) Lucky GNU user #endif #endif ], ac_cv_gnu_library_2=yes, ac_cv_gnu_library_2=no) ] ) AC_SUBST(GLIBC2) GLIBC2="$ac_cv_gnu_library_2" ] ) hercules-3.07/m4/glibc21.m4000644 000765 000765 00000001445 11143760524 016757 0ustar00jmaynardjmaynard000000 000000 # glibc21.m4 serial 3 dnl Copyright (C) 2000-2002, 2004 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. # Test for the GNU C Library, version 2.1 or newer. # From Bruno Haible. AC_DEFUN([gl_GLIBC21], [ AC_CACHE_CHECK(whether we are using the GNU C Library 2.1 or newer, ac_cv_gnu_library_2_1, [AC_EGREP_CPP([Lucky GNU user], [ #include #ifdef __GNU_LIBRARY__ #if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 1) || (__GLIBC__ > 2) Lucky GNU user #endif #endif ], ac_cv_gnu_library_2_1=yes, ac_cv_gnu_library_2_1=no) ] ) AC_SUBST(GLIBC21) GLIBC21="$ac_cv_gnu_library_2_1" ] ) hercules-3.07/m4/iconv.m4000644 000765 000765 00000006426 11143760524 016656 0ustar00jmaynardjmaynard000000 000000 # iconv.m4 serial AM4 (gettext-0.11.3) dnl Copyright (C) 2000-2002 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl From Bruno Haible. AC_DEFUN([AM_ICONV_LINKFLAGS_BODY], [ dnl Prerequisites of AC_LIB_LINKFLAGS_BODY. AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) AC_REQUIRE([AC_LIB_RPATH]) dnl Search for libiconv and define LIBICONV, LTLIBICONV and INCICONV dnl accordingly. AC_LIB_LINKFLAGS_BODY([iconv]) ]) AC_DEFUN([AM_ICONV_LINK], [ dnl Some systems have iconv in libc, some have it in libiconv (OSF/1 and dnl those with the standalone portable GNU libiconv installed). 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 ]) hercules-3.07/m4/intdiv0.m4000644 000765 000765 00000003340 11143760524 017105 0ustar00jmaynardjmaynard000000 000000 # intdiv0.m4 serial 1 (gettext-0.11.3) dnl Copyright (C) 2002 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl From Bruno Haible. AC_DEFUN([gt_INTDIV0], [ AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_CACHE_CHECK([whether integer division by zero raises SIGFPE], gt_cv_int_divbyzero_sigfpe, [ 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.]) ]) hercules-3.07/m4/intmax.m4000644 000765 000765 00000001746 11143760524 017040 0ustar00jmaynardjmaynard000000 000000 # intmax.m4 serial 2 (gettext-0.14.2) dnl Copyright (C) 2002-2005 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl From Bruno Haible. dnl Test whether the system has the 'intmax_t' type, but don't attempt to dnl find a replacement if it is lacking. AC_DEFUN([gt_TYPE_INTMAX_T], [ AC_REQUIRE([gl_AC_HEADER_INTTYPES_H]) AC_REQUIRE([gl_AC_HEADER_STDINT_H]) AC_CACHE_CHECK(for intmax_t, gt_cv_c_intmax_t, [AC_TRY_COMPILE([ #include #include #if HAVE_STDINT_H_WITH_UINTMAX #include #endif #if HAVE_INTTYPES_H_WITH_UINTMAX #include #endif ], [intmax_t x = -1;], 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 ]) hercules-3.07/m4/inttypes-pri.m4000644 000765 000765 00000002002 11143760524 020171 0ustar00jmaynardjmaynard000000 000000 # inttypes-pri.m4 serial 1 (gettext-0.11.4) dnl Copyright (C) 1997-2002 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl From Bruno Haible. # 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 ]) hercules-3.07/m4/inttypes.m4000644 000765 000765 00000001472 11143760524 017413 0ustar00jmaynardjmaynard000000 000000 # inttypes.m4 serial 1 (gettext-0.11.4) dnl Copyright (C) 1997-2002 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl From Paul Eggert. # Define HAVE_INTTYPES_H 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 ]) hercules-3.07/m4/inttypes_h.m4000644 000765 000765 00000001623 11143760524 017720 0ustar00jmaynardjmaynard000000 000000 # inttypes_h.m4 serial 6 dnl Copyright (C) 1997-2004 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl From Paul Eggert. # Define HAVE_INTTYPES_H_WITH_UINTMAX if exists, # doesn't clash with , and declares uintmax_t. AC_DEFUN([gl_AC_HEADER_INTTYPES_H], [ AC_CACHE_CHECK([for inttypes.h], gl_cv_header_inttypes_h, [AC_TRY_COMPILE( [#include #include ], [uintmax_t i = (uintmax_t) -1;], gl_cv_header_inttypes_h=yes, gl_cv_header_inttypes_h=no)]) if test $gl_cv_header_inttypes_h = yes; then AC_DEFINE_UNQUOTED(HAVE_INTTYPES_H_WITH_UINTMAX, 1, [Define if exists, doesn't clash with , and declares uintmax_t. ]) fi ]) hercules-3.07/m4/isc-posix.m4000644 000765 000765 00000001706 11143760524 017452 0ustar00jmaynardjmaynard000000 000000 # isc-posix.m4 serial 2 (gettext-0.11.2) dnl Copyright (C) 1995-2002 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. # 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"]) ] ) hercules-3.07/m4/lcmessage.m4000644 000765 000765 00000002404 11143760524 017473 0ustar00jmaynardjmaynard000000 000000 # lcmessage.m4 serial 4 (gettext-0.14.2) dnl Copyright (C) 1995-2002, 2004-2005 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl dnl This file can can be used in projects which are not available under dnl the GNU General Public License or the GNU Library General Public dnl License but which still want to provide support for the GNU gettext dnl functionality. dnl Please note that the actual code of the GNU gettext library is covered dnl by the GNU Library General Public License, and the rest of the GNU dnl gettext package package is covered by the GNU General Public License. dnl They are *not* in the public domain. dnl Authors: dnl Ulrich Drepper , 1995. # Check whether LC_MESSAGES is available in . AC_DEFUN([gt_LC_MESSAGES], [ AC_CACHE_CHECK([for LC_MESSAGES], gt_cv_val_LC_MESSAGES, [AC_TRY_LINK([#include ], [return LC_MESSAGES], gt_cv_val_LC_MESSAGES=yes, gt_cv_val_LC_MESSAGES=no)]) if test $gt_cv_val_LC_MESSAGES = yes; then AC_DEFINE(HAVE_LC_MESSAGES, 1, [Define if your file defines LC_MESSAGES.]) fi ]) hercules-3.07/m4/lib-ld.m4000644 000765 000765 00000006531 11143760524 016700 0ustar00jmaynardjmaynard000000 000000 # lib-ld.m4 serial 3 (gettext-0.13) dnl Copyright (C) 1996-2003 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl Subroutines of libtool.m4, dnl with replacements s/AC_/AC_LIB/ and s/lt_cv/acl_cv/ to avoid collision dnl with libtool.m4. dnl From libtool-1.4. Sets the variable with_gnu_ld to yes or no. AC_DEFUN([AC_LIB_PROG_LD_GNU], [AC_CACHE_CHECK([if the linker ($LD) is GNU ld], acl_cv_prog_gnu_ld, [# I'd rather use --version here, but apparently some GNU ld's only accept -v. case `$LD -v 2>&1 conf$$.sh echo "exit 0" >>conf$$.sh chmod +x conf$$.sh if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then PATH_SEPARATOR=';' else PATH_SEPARATOR=: fi rm -f conf$$.sh fi ac_prog=ld if test "$GCC" = yes; then # Check if gcc -print-prog-name=ld gives a path. AC_MSG_CHECKING([for ld used by GCC]) case $host in *-*-mingw*) # gcc leaves a trailing carriage return which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [[\\/]* | [A-Za-z]:[\\/]*)] [re_direlt='/[^/][^/]*/\.\./'] # Canonicalize the path of ld ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'` while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"` done test -z "$LD" && LD="$ac_prog" ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test "$with_gnu_ld" = yes; then AC_MSG_CHECKING([for GNU ld]) else AC_MSG_CHECKING([for non-GNU ld]) fi AC_CACHE_VAL(acl_cv_path_LD, [if test -z "$LD"; then IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}" for ac_dir in $PATH; do test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then acl_cv_path_LD="$ac_dir/$ac_prog" # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some GNU ld's only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$acl_cv_path_LD" -v 2>&1 < /dev/null` in *GNU* | *'with BFD'*) test "$with_gnu_ld" != no && break ;; *) test "$with_gnu_ld" != yes && break ;; esac fi done IFS="$ac_save_ifs" else acl_cv_path_LD="$LD" # Let the user override the test with a path. fi]) LD="$acl_cv_path_LD" if test -n "$LD"; then AC_MSG_RESULT($LD) else AC_MSG_RESULT(no) fi test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH]) AC_LIB_PROG_LD_GNU ]) hercules-3.07/m4/lib-link.m4000644 000765 000765 00000055426 11143760524 017245 0ustar00jmaynardjmaynard000000 000000 # lib-link.m4 serial 6 (gettext-0.14.3) dnl Copyright (C) 2001-2005 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl From Bruno Haible. AC_PREREQ(2.50) 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], [ dnl Tell automake >= 1.10 to complain if config.rpath is missing. m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([config.rpath])]) AC_REQUIRE([AC_PROG_CC]) dnl we use $CC, $GCC, $LDFLAGS AC_REQUIRE([AC_LIB_PROG_LD]) dnl we use $LD, $with_gnu_ld AC_REQUIRE([AC_CANONICAL_HOST]) dnl we use $host AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT]) dnl we use $ac_aux_dir AC_CACHE_CHECK([for shared library run path origin], acl_cv_rpath, [ CC="$CC" GCC="$GCC" LDFLAGS="$LDFLAGS" LD="$LD" with_gnu_ld="$with_gnu_ld" \ ${CONFIG_SHELL-/bin/sh} "$ac_aux_dir/config.rpath" "$host" > conftest.sh . ./conftest.sh rm -f ./conftest.sh acl_cv_rpath=done ]) wl="$acl_cv_wl" 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* | gnu* | k*bsd*-gnu) haveit=yes;; esac fi fi if test -z "$haveit"; then for x in $CPPFLAGS $INC[]NAME; do AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) if test "X$x" = "X-I$additional_includedir"; then haveit=yes break fi done if test -z "$haveit"; then if test -d "$additional_includedir"; then dnl Really add $additional_includedir to $INCNAME. INC[]NAME="${INC[]NAME}${INC[]NAME:+ }-I$additional_includedir" fi fi fi fi fi dnl Look for dependencies. if test -n "$found_la"; then dnl Read the .la file. It defines the variables dnl dlname, library_names, old_library, dependency_libs, current, dnl age, revision, installed, dlopen, dlpreopen, libdir. save_libdir="$libdir" case "$found_la" in */* | *\\*) . "$found_la" ;; *) . "./$found_la" ;; esac libdir="$save_libdir" dnl We use only dependency_libs. for dep in $dependency_libs; do case "$dep" in -L*) additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'` dnl Potentially add $additional_libdir to $LIBNAME and $LTLIBNAME. dnl But don't add it dnl 1. if it's the standard /usr/lib, dnl 2. if it's /usr/local/lib and we are using GCC on Linux, dnl 3. if it's already present in $LDFLAGS or the already dnl constructed $LIBNAME, dnl 4. if it doesn't exist as a directory. if test "X$additional_libdir" != "X/usr/lib"; then haveit= if test "X$additional_libdir" = "X/usr/local/lib"; then if test -n "$GCC"; then case $host_os in linux* | gnu* | k*bsd*-gnu) haveit=yes;; esac fi fi if test -z "$haveit"; then haveit= for x in $LDFLAGS $LIB[]NAME; do AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) if test "X$x" = "X-L$additional_libdir"; then haveit=yes break fi done if test -z "$haveit"; then if test -d "$additional_libdir"; then dnl Really add $additional_libdir to $LIBNAME. LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$additional_libdir" fi fi haveit= for x in $LDFLAGS $LTLIB[]NAME; do AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) if test "X$x" = "X-L$additional_libdir"; then haveit=yes break fi done if test -z "$haveit"; then if test -d "$additional_libdir"; then dnl Really add $additional_libdir to $LTLIBNAME. LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-L$additional_libdir" fi fi fi fi ;; -R*) dir=`echo "X$dep" | sed -e 's/^X-R//'` if test "$enable_rpath" != no; then dnl Potentially add DIR to rpathdirs. dnl The rpathdirs will be appended to $LIBNAME at the end. haveit= for x in $rpathdirs; do if test "X$x" = "X$dir"; then haveit=yes break fi done if test -z "$haveit"; then rpathdirs="$rpathdirs $dir" fi dnl Potentially add DIR to ltrpathdirs. dnl The ltrpathdirs will be appended to $LTLIBNAME at the end. haveit= for x in $ltrpathdirs; do if test "X$x" = "X$dir"; then haveit=yes break fi done if test -z "$haveit"; then ltrpathdirs="$ltrpathdirs $dir" fi fi ;; -l*) dnl Handle this in the next round. names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'` ;; *.la) dnl Handle this in the next round. Throw away the .la's dnl directory; it is already contained in a preceding -L dnl option. names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'` ;; *) dnl Most likely an immediate library name. LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$dep" LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }$dep" ;; esac done fi else dnl Didn't find the library; assume it is in the system directories dnl known to the linker and runtime loader. (All the system dnl directories known to the linker should also be known to the dnl runtime loader, otherwise the system is severely misconfigured.) LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-l$name" LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-l$name" fi fi fi done done if test "X$rpathdirs" != "X"; then if test -n "$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 ]) hercules-3.07/m4/lib-prefix.m4000644 000765 000765 00000012310 11143760524 017566 0ustar00jmaynardjmaynard000000 000000 # lib-prefix.m4 serial 4 (gettext-0.14.2) dnl Copyright (C) 2001-2005 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl From Bruno Haible. dnl AC_LIB_ARG_WITH is synonymous to AC_ARG_WITH in autoconf-2.13, and dnl similar to AC_ARG_WITH in autoconf 2.52...2.57 except that is doesn't dnl require excessive bracketing. ifdef([AC_HELP_STRING], [AC_DEFUN([AC_LIB_ARG_WITH], [AC_ARG_WITH([$1],[[$2]],[$3],[$4])])], [AC_DEFUN([AC_][LIB_ARG_WITH], [AC_ARG_WITH([$1],[$2],[$3],[$4])])]) dnl AC_LIB_PREFIX adds to the CPPFLAGS and LDFLAGS the flags that are needed dnl to access previously installed libraries. The basic assumption is that dnl a user will want packages to use other packages he previously installed dnl with the same --prefix option. dnl This macro is not needed if only AC_LIB_LINKFLAGS is used to locate dnl libraries, but is otherwise very convenient. AC_DEFUN([AC_LIB_PREFIX], [ AC_BEFORE([$0], [AC_LIB_LINKFLAGS]) AC_REQUIRE([AC_PROG_CC]) AC_REQUIRE([AC_CANONICAL_HOST]) AC_REQUIRE([AC_LIB_PREPARE_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* | gnu* | k*bsd*-gnu) haveit=yes;; esac fi fi if test -z "$haveit"; then if test -d "$additional_includedir"; then dnl Really add $additional_includedir to $CPPFLAGS. CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }-I$additional_includedir" fi fi fi fi dnl Potentially add $additional_libdir to $LDFLAGS. dnl But don't add it dnl 1. if it's the standard /usr/lib, dnl 2. if it's already present in $LDFLAGS, dnl 3. if it's /usr/local/lib and we are using GCC on Linux, dnl 4. if it doesn't exist as a directory. if test "X$additional_libdir" != "X/usr/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" ]) hercules-3.07/m4/longdouble.m4000644 000765 000765 00000002053 11143760524 017662 0ustar00jmaynardjmaynard000000 000000 # longdouble.m4 serial 1 (gettext-0.12) dnl Copyright (C) 2002-2003 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl From Bruno Haible. dnl Test whether 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 ]) hercules-3.07/m4/longlong.m4000644 000765 000765 00000001416 11143760524 017351 0ustar00jmaynardjmaynard000000 000000 # longlong.m4 serial 5 dnl Copyright (C) 1999-2004 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl From Paul Eggert. # Define HAVE_LONG_LONG if 'long long' works. AC_DEFUN([gl_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 ]) hercules-3.07/m4/Makefile.am000644 000765 000765 00000000533 11143760524 017323 0ustar00jmaynardjmaynard000000 000000 EXTRA_DIST = glibc2.m4 intmax.m4 longdouble.m4 longlong.m4 nls.m4 po.m4 printf-posix.m4 signed.m4 size_max.m4 wchar_t.m4 wint_t.m4 xsize.m4 codeset.m4 gettext.m4 glibc21.m4 iconv.m4 intdiv0.m4 inttypes.m4 inttypes_h.m4 inttypes-pri.m4 isc-posix.m4 lcmessage.m4 lib-ld.m4 lib-link.m4 lib-prefix.m4 progtest.m4 stdint_h.m4 uintmax_t.m4 ulonglong.m4 hercules-3.07/m4/Makefile.in000644 000765 000765 00000024717 11344713141 017342 0ustar00jmaynardjmaynard000000 000000 # Makefile.in generated by automake 1.9.6 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = .. am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd INSTALL = @INSTALL@ install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = m4 DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ChangeLog ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/autoconf/hercules.m4 \ $(top_srcdir)/autoconf/libtool.m4 \ $(top_srcdir)/autoconf/ltdl.m4 $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(SHELL) $(top_srcdir)/autoconf/mkinstalldirs CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = SOURCES = DIST_SOURCES = DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BUILD_FISHHANG_FALSE = @BUILD_FISHHANG_FALSE@ BUILD_FISHHANG_TRUE = @BUILD_FISHHANG_TRUE@ BUILD_FTHREADS_FALSE = @BUILD_FTHREADS_FALSE@ BUILD_FTHREADS_TRUE = @BUILD_FTHREADS_TRUE@ BUILD_HERCIFC_FALSE = @BUILD_HERCIFC_FALSE@ BUILD_HERCIFC_TRUE = @BUILD_HERCIFC_TRUE@ BUILD_SHARED_FALSE = @BUILD_SHARED_FALSE@ BUILD_SHARED_TRUE = @BUILD_SHARED_TRUE@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CONVENIENCE_LTDL_FALSE = @CONVENIENCE_LTDL_FALSE@ CONVENIENCE_LTDL_TRUE = @CONVENIENCE_LTDL_TRUE@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ ECHO = @ECHO@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ F77 = @F77@ FFLAGS = @FFLAGS@ GMSGFMT = @GMSGFMT@ GREP = @GREP@ HERCIFC_GROUPNAME = @HERCIFC_GROUPNAME@ HERCIFC_GROUPSET_FALSE = @HERCIFC_GROUPSET_FALSE@ HERCIFC_GROUPSET_TRUE = @HERCIFC_GROUPSET_TRUE@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_LTDL_FALSE = @INSTALL_LTDL_FALSE@ INSTALL_LTDL_TRUE = @INSTALL_LTDL_TRUE@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ LDFLAGS = @LDFLAGS@ LIBADD_DL = @LIBADD_DL@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBTOOL_DEPS = @LIBTOOL_DEPS@ LN_S = @LN_S@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@ MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@ MAKEINFO = @MAKEINFO@ MKINSTALLDIRS = @MKINSTALLDIRS@ MSGFMT = @MSGFMT@ MSGMERGE = @MSGMERGE@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPTION_DYNAMIC_LOAD_FALSE = @OPTION_DYNAMIC_LOAD_FALSE@ OPTION_DYNAMIC_LOAD_TRUE = @OPTION_DYNAMIC_LOAD_TRUE@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ POSUB = @POSUB@ RANLIB = @RANLIB@ SETUID_HERCIFC_FALSE = @SETUID_HERCIFC_FALSE@ SETUID_HERCIFC_TRUE = @SETUID_HERCIFC_TRUE@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ USE_DLLTOOL_FALSE = @USE_DLLTOOL_FALSE@ USE_DLLTOOL_TRUE = @USE_DLLTOOL_TRUE@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_F77 = @ac_ct_F77@ am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ modexecdir = @modexecdir@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ EXTRA_DIST = glibc2.m4 intmax.m4 longdouble.m4 longlong.m4 nls.m4 po.m4 printf-posix.m4 signed.m4 size_max.m4 wchar_t.m4 wint_t.m4 xsize.m4 codeset.m4 gettext.m4 glibc21.m4 iconv.m4 intdiv0.m4 inttypes.m4 inttypes_h.m4 inttypes-pri.m4 isc-posix.m4 lcmessage.m4 lib-ld.m4 lib-link.m4 lib-prefix.m4 progtest.m4 stdint_h.m4 uintmax_t.m4 ulonglong.m4 all: all-am .SUFFIXES: $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ && exit 0; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu m4/Makefile'; \ cd $(top_srcdir) && \ $(AUTOMAKE) --gnu m4/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs distclean-libtool: -rm -f libtool uninstall-info-am: tags: TAGS TAGS: ctags: CTAGS CTAGS: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ list='$(DISTFILES)'; for file in $$list; do \ case $$file in \ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ esac; \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ if test "$$dir" != "$$file" && test "$$dir" != "."; then \ dir="/$$dir"; \ $(mkdir_p) "$(distdir)$$dir"; \ else \ dir=''; \ fi; \ if test -d $$d/$$file; then \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ fi; \ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic distclean-libtool dvi: dvi-am dvi-am: html: html-am info: info-am info-am: install-data-am: install-exec-am: install-info: install-info-am install-man: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-info-am .PHONY: all all-am check check-am clean clean-generic clean-libtool \ distclean distclean-generic distclean-libtool distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-exec install-exec-am \ install-info install-info-am install-man install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am uninstall uninstall-am \ uninstall-info-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: hercules-3.07/m4/nls.m4000644 000765 000765 00000003530 11143760524 016325 0ustar00jmaynardjmaynard000000 000000 # nls.m4 serial 2 (gettext-0.14.3) dnl Copyright (C) 1995-2003, 2005 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl dnl This file can can be used in projects which are not available under dnl the GNU General Public License or the GNU Library General Public dnl License but which still want to provide support for the GNU gettext dnl functionality. dnl Please note that the actual code of the GNU gettext library is covered dnl by the GNU Library General Public License, and the rest of the GNU dnl gettext package package is covered by the GNU General Public License. dnl They are *not* in the public domain. dnl Authors: dnl Ulrich Drepper , 1995-2000. dnl Bruno Haible , 2000-2003. AC_PREREQ(2.50) AC_DEFUN([AM_NLS], [ AC_MSG_CHECKING([whether NLS is requested]) dnl Default is enabled NLS AC_ARG_ENABLE(nls, [ --disable-nls do not use Native Language Support], USE_NLS=$enableval, USE_NLS=yes) AC_MSG_RESULT($USE_NLS) AC_SUBST(USE_NLS) ]) AC_DEFUN([AM_MKINSTALLDIRS], [ dnl Tell automake >= 1.10 to complain if mkinstalldirs is missing. m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([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) ]) hercules-3.07/m4/po.m4000644 000765 000765 00000043643 11143760524 016160 0ustar00jmaynardjmaynard000000 000000 # po.m4 serial 7 (gettext-0.14.3) dnl Copyright (C) 1995-2005 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl dnl This file can can be used in projects which are not available under dnl the GNU General Public License or the GNU Library General Public dnl License but which still want to provide support for the GNU gettext dnl functionality. dnl Please note that the actual code of the GNU gettext library is covered dnl by the GNU Library General Public License, and the rest of the GNU dnl gettext package package is covered by the GNU General Public License. dnl They are *not* in the public domain. dnl Authors: dnl Ulrich Drepper , 1995-2000. dnl Bruno Haible , 2000-2003. AC_PREREQ(2.50) dnl Checks for all prerequisites of the po subdirectory. AC_DEFUN([AM_PO_SUBDIRS], [ AC_REQUIRE([AC_PROG_MAKE_SET])dnl AC_REQUIRE([AC_PROG_INSTALL])dnl AC_REQUIRE([AM_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 >&]AS_MESSAGE_LOG_FD[ 2>&1 && (if $ac_dir/$ac_word --statistics /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi)], :) AC_PATH_PROG(GMSGFMT, gmsgfmt, $MSGFMT) dnl Search for GNU xgettext 0.12 or newer in the PATH. dnl The first test excludes Solaris xgettext and early GNU xgettext versions. dnl The second test excludes FreeBSD xgettext. AM_PATH_PROG_WITH_TEST(XGETTEXT, xgettext, [$ac_dir/$ac_word --omit-header --copyright-holder= --msgid-bugs-address= /dev/null >&]AS_MESSAGE_LOG_FD[ 2>&1 && (if $ac_dir/$ac_word --omit-header --copyright-holder= --msgid-bugs-address= /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi)], :) dnl Remove leftover from FreeBSD xgettext call. rm -f messages.po dnl Search for GNU msgmerge 0.11 or newer in the PATH. AM_PATH_PROG_WITH_TEST(MSGMERGE, msgmerge, [$ac_dir/$ac_word --update -q /dev/null /dev/null >&]AS_MESSAGE_LOG_FD[ 2>&1], :) dnl 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 # Treat a directory as a PO directory if and only if it has a # POTFILES.in file. This allows packages to have multiple PO # directories under different names or in different locations. if test -f "$ac_given_srcdir/$ac_dir/POTFILES.in"; then rm -f "$ac_dir/POTFILES" test -n "$as_me" && echo "$as_me: creating $ac_dir/POTFILES" || echo "creating $ac_dir/POTFILES" cat "$ac_given_srcdir/$ac_dir/POTFILES.in" | sed -e "/^#/d" -e "/^[ ]*\$/d" -e "s,.*, $top_srcdir/& \\\\," | sed -e "\$s/\(.*\) \\\\/\1/" > "$ac_dir/POTFILES" POMAKEFILEDEPS="POTFILES.in" # ALL_LINGUAS, POFILES, UPDATEPOFILES, DUMMYPOFILES, GMOFILES depend # on $ac_dir but don't depend on user-specified configuration # parameters. if test -f "$ac_given_srcdir/$ac_dir/LINGUAS"; then # The LINGUAS file contains the set of available languages. if test -n "$OBSOLETE_ALL_LINGUAS"; then test -n "$as_me" && echo "$as_me: setting ALL_LINGUAS in configure.in is obsolete" || echo "setting ALL_LINGUAS in configure.in is obsolete" fi ALL_LINGUAS_=`sed -e "/^#/d" -e "s/#.*//" "$ac_given_srcdir/$ac_dir/LINGUAS"` # Hide the ALL_LINGUAS assigment from automake. 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' -e 's/^sr-CS/sr-SP/' -e 's/@latin$/-Latn/' -e 's/@cyrillic$/-Cyrl/' -e 's/^sr-SP$/sr-SP-Latn/' -e 's/^uz-UZ$/uz-UZ-Latn/'` cat >> "$ac_file.tmp" <> "$ac_file.tmp" < #include /* The string "%2$d %1$d", with dollar characters protected from the shell's dollar expansion (possibly an autoconf bug). */ static char format[] = { '%', '2', '$', 'd', ' ', '%', '1', '$', 'd', '\0' }; static char buf[100]; int main () { sprintf (buf, format, 33, 55); return (strcmp (buf, "55 33") != 0); }], gt_cv_func_printf_posix=yes, gt_cv_func_printf_posix=no, [ AC_EGREP_CPP(notposix, [ #if defined __NetBSD__ || defined _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 ]) hercules-3.07/m4/progtest.m4000644 000765 000765 00000005550 11143760524 017404 0ustar00jmaynardjmaynard000000 000000 # progtest.m4 serial 4 (gettext-0.14.2) dnl Copyright (C) 1996-2003, 2005 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl dnl This file can can be used in projects which are not available under dnl the GNU General Public License or the GNU Library General Public dnl License but which still want to provide support for the GNU gettext dnl functionality. dnl Please note that the actual code of the GNU gettext library is covered dnl by the GNU Library General Public License, and the rest of the GNU dnl gettext package package is covered by the GNU General Public License. dnl They are *not* in the public domain. dnl Authors: dnl Ulrich Drepper , 1996. AC_PREREQ(2.50) # Search path for a program which passes the given test. dnl AM_PATH_PROG_WITH_TEST(VARIABLE, PROG-TO-CHECK-FOR, dnl TEST-PERFORMED-ON-FOUND_PROGRAM [, VALUE-IF-NOT-FOUND [, PATH]]) AC_DEFUN([AM_PATH_PROG_WITH_TEST], [ # Prepare PATH_SEPARATOR. # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then echo "#! /bin/sh" >conf$$.sh echo "exit 0" >>conf$$.sh chmod +x conf$$.sh if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then PATH_SEPARATOR=';' else PATH_SEPARATOR=: fi rm -f conf$$.sh fi # Find out how to test for executable files. Don't use a zero-byte file, # as systems may use methods other than mode bits to determine executability. cat >conf$$.file <<_ASEOF #! /bin/sh exit 0 _ASEOF chmod +x conf$$.file if test -x conf$$.file >/dev/null 2>&1; then ac_executable_p="test -x" else ac_executable_p="test -f" fi rm -f conf$$.file # Extract the first word of "$2", so it can be a program name with args. set dummy $2; ac_word=[$]2 AC_MSG_CHECKING([for $ac_word]) AC_CACHE_VAL(ac_cv_path_$1, [case "[$]$1" in [[\\/]]* | ?:[[\\/]]*) ac_cv_path_$1="[$]$1" # Let the user override the test with a path. ;; *) ac_save_IFS="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in ifelse([$5], , $PATH, [$5]); do IFS="$ac_save_IFS" test -z "$ac_dir" && ac_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $ac_executable_p "$ac_dir/$ac_word$ac_exec_ext"; then echo "$as_me: trying $ac_dir/$ac_word..." >&AS_MESSAGE_LOG_FD if [$3]; then ac_cv_path_$1="$ac_dir/$ac_word$ac_exec_ext" break 2 fi fi done done IFS="$ac_save_IFS" dnl If no 4th arg is given, leave the cache variable unset, dnl so AC_PATH_PROGS will keep looking. ifelse([$4], , , [ test -z "[$]ac_cv_path_$1" && ac_cv_path_$1="$4" ])dnl ;; esac])dnl $1="$ac_cv_path_$1" if test ifelse([$4], , [-n "[$]$1"], ["[$]$1" != "$4"]); then AC_MSG_RESULT([$]$1) else AC_MSG_RESULT(no) fi AC_SUBST($1)dnl ]) hercules-3.07/m4/signed.m4000644 000765 000765 00000001154 11143760524 017002 0ustar00jmaynardjmaynard000000 000000 # signed.m4 serial 1 (gettext-0.10.40) dnl Copyright (C) 2001-2002 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl From Bruno Haible. AC_DEFUN([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 ]) hercules-3.07/m4/size_max.m4000644 000765 000765 00000003645 11143760524 017357 0ustar00jmaynardjmaynard000000 000000 # size_max.m4 serial 2 dnl Copyright (C) 2003 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl From Bruno Haible. 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 ]) hercules-3.07/m4/stdint_h.m4000644 000765 000765 00000001573 11143760524 017352 0ustar00jmaynardjmaynard000000 000000 # stdint_h.m4 serial 5 dnl Copyright (C) 1997-2004 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl From Paul Eggert. # Define HAVE_STDINT_H_WITH_UINTMAX if exists, # doesn't clash with , and declares uintmax_t. AC_DEFUN([gl_AC_HEADER_STDINT_H], [ AC_CACHE_CHECK([for stdint.h], gl_cv_header_stdint_h, [AC_TRY_COMPILE( [#include #include ], [uintmax_t i = (uintmax_t) -1;], gl_cv_header_stdint_h=yes, gl_cv_header_stdint_h=no)]) if test $gl_cv_header_stdint_h = yes; then AC_DEFINE_UNQUOTED(HAVE_STDINT_H_WITH_UINTMAX, 1, [Define if exists, doesn't clash with , and declares uintmax_t. ]) fi ]) hercules-3.07/m4/uintmax_t.m4000644 000765 000765 00000002076 11143760524 017545 0ustar00jmaynardjmaynard000000 000000 # uintmax_t.m4 serial 9 dnl Copyright (C) 1997-2004 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl From Paul Eggert. AC_PREREQ(2.13) # Define uintmax_t to 'unsigned long' or 'unsigned long long' # if it is not already defined in or . AC_DEFUN([gl_AC_TYPE_UINTMAX_T], [ AC_REQUIRE([gl_AC_HEADER_INTTYPES_H]) AC_REQUIRE([gl_AC_HEADER_STDINT_H]) if test $gl_cv_header_inttypes_h = no && test $gl_cv_header_stdint_h = no; then AC_REQUIRE([gl_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 ]) hercules-3.07/m4/ulonglong.m4000644 000765 000765 00000001615 11143760524 017537 0ustar00jmaynardjmaynard000000 000000 # ulonglong.m4 serial 4 dnl Copyright (C) 1999-2004 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl From Paul Eggert. # Define HAVE_UNSIGNED_LONG_LONG if 'unsigned long long' works. AC_DEFUN([gl_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 ]) hercules-3.07/m4/wchar_t.m4000644 000765 000765 00000001326 11143760524 017161 0ustar00jmaynardjmaynard000000 000000 # wchar_t.m4 serial 1 (gettext-0.12) dnl Copyright (C) 2002-2003 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl From Bruno Haible. dnl Test whether has the 'wchar_t' type. dnl Prerequisite: AC_PROG_CC AC_DEFUN([gt_TYPE_WCHAR_T], [ AC_CACHE_CHECK([for wchar_t], gt_cv_c_wchar_t, [AC_TRY_COMPILE([#include wchar_t foo = (wchar_t)'\0';], , gt_cv_c_wchar_t=yes, gt_cv_c_wchar_t=no)]) if test $gt_cv_c_wchar_t = yes; then AC_DEFINE(HAVE_WCHAR_T, 1, [Define if you have the 'wchar_t' type.]) fi ]) hercules-3.07/m4/wint_t.m4000644 000765 000765 00000001304 11143760524 017032 0ustar00jmaynardjmaynard000000 000000 # wint_t.m4 serial 1 (gettext-0.12) dnl Copyright (C) 2003 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl From Bruno Haible. dnl Test whether has the '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 ]) hercules-3.07/m4/xsize.m4000644 000765 000765 00000000645 11143760524 016677 0ustar00jmaynardjmaynard000000 000000 # xsize.m4 serial 3 dnl Copyright (C) 2003-2004 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. AC_DEFUN([gl_XSIZE], [ dnl Prerequisites of lib/xsize.h. AC_REQUIRE([gl_SIZE_MAX]) AC_REQUIRE([AC_C_INLINE]) AC_CHECK_HEADERS(stdint.h) ]) hercules-3.07/html/cckddasd.html000644 000765 000765 00000106477 11143760535 020361 0ustar00jmaynardjmaynard000000 000000 Hercules: Compressed Dasd Emulation

Compressed Dasd Emulation


Contents


Introduction

Using compressed DASD files you can significantly reduce the file space required for emulated DASD files and possibly gain a performance boost because less physical I/O occurs. Both CKD (Count-Key-Data) and FBA (Fixed-Block-Architecture) emulation files can be compressed.

In regular (or uncompressed) files, each CKD track or FBA block occupies a specific spot in the emulation file. The offset of the track or block in the file can be directly calculated knowing the track or block number and the maximum size of the track or block. In compressed files, each track image or group of blocks may be compressed by zlib or bzip2, and only occupies the space neccessary for the compressed image. The offset of a compressed track or block is obtained by performing a two-table lookup. The lookup tables themselves reside in the emulation file.

Because FBA blocks are 512 bytes in length, and that being a rather small number, FBA blocks are grouped into block groups. Each block group contains 120 FBA blocks (60K).

Whenever a track or block group is written to a compressed file, it is written either to an existing free space within the file, or at the end of the file, then the lookup tables are updated, and then the space the track or block group previously occupied is freed. The location of a track or block group in the file can change many times.

In the event of a failure (for example, Hercules crash, operating system crash or power failure), the compressed emulation file on the host's physical disk may be out of sync if the host operating system defers physical writes to the file system containing the emulation file. Several methods have evolved to reduce the amount of data lost in these kind of events.

A compressed file may occupy only 20% of the disk space required by an uncompressed file. In other words, you may be able to have 5 times more emulated volumes using compressed DASD files. However, compressed files are more sensitive to failures and corruption may occur.


Shadow Files

An compressed CKD or FBA dasd can have more than one physical file. The additional files are called shadow files. The function is implemented as a kind of snapshot, where a new shadow file can be created on demand. An emulated dasd is represented by a base file and 0 or more shadow files. All files are opened read-only except for the current file, which is opened read-write.

Shadow files are specified by the sf=shadow-file-name parameter on the device statement for the compressed DASD device.

Please note that the specified shadow filename does not have to actually exist. The shadow-file-name operand of the sf= parameter is simply a filename template that will be used to name the shadow file whenever a shadow file is to be created, but shadow files do not actually get created until you specifically create them via the sf+xxxx (or sf+*) command. Please refer to the discussion of the sf command several paragraphs below for more information.

The shadow file name should have spot where the shadow file number will be set. This is either the character preceding the last period after the last slash or the last character if there is no period. For example:

0100 3390 disks/linux1.dsk sf=shadows/linux1_*.dsk

There can be up to 8 shadow files in use at any time for an emulated dasd device. The base file is designated file[0] and the shadow files are file[1] to file[8]. The highest numbered file in use at a given time is the current file, where all writes will occur. Track reads start with the current file and proceed down until a file is found that actually contains the track image.

A shadow file contains all the changes made to the emulated dasd since it was created, until the next shadow file is created. The moment of the shadow file's creation can be thought of as a snapshot of the current emulated dasd at that time, because if the shadow file is later removed, then the emulated dasd reverts back to the state it was at when the snapshot was taken.

Using shadow files, you can keep the base file on a read-only device such as cdrom, or change the base file attributes to read-only, ensuring that this file can never be corrupted.

Hercules console commands are provided to add a new shadow file, remove the current shadow file (with or without backward merge), compress the curent shadow file, and display the shadow file status and statistics:

sf+ unit Create a new shadow file
sf- unit merge
nomerge
force
Remove a shadow file. If merge is specified or defaulted, then the contents of the current file is merged into the previous file, the current file is removed, and the previous file becomes the current file. The previous file must be able to be opened read-write. If nomerge is specified then the contents of the current file is discarded and the previous file becomes the current file. However, if the previous file is read-only, then a new shadow file is created (re-added) and that becomes the current file. The force option is required when doing a merge to the base file and the base file is read-only because the ro option was specified on the device config statement.
sfc unit Compress the current file
sfk unit level Perform the chkdsk function on the current file. Level is a number -1 ... 4, the default is 2. The levels are:
-1     devhdr, cdevhdr, l1 table
  0     devhdr, cdevhdr, l1 table, l2 tables
  1     devhdr, cdevhdr, l1 table, l2 tables, free spaces
  2     devhdr, cdevhdr, l1 table, l2 tables, free spaces, trkhdrs
  3     devhdr, cdevhdr, l1 table, l2 tables, free spaces, trkimgs
  4     devhdr, cdevhdr. Build everything else from recovery
sfd unit Display shadow file status and statistics

Note. You can use * in place of unit address to apply the command to all compressed dasd (e.g. 'sf+*', or 'sf-* nomerge').


Compressed DASD File Structure

A compressed DASD file has 6 types of spaces, a device header, a compressed device header, a primary lookup table, secondary lookup tables, track or block group images, and free spaces. The first 3 types only occur once, at the beginning of the file in order. The rest of the file is occupied by the other 3 space types.

The first 512 bytes of a compressed DASD file contains a device header. The device header contains an eye-catcher that identifies the file type (CKD or FBA and base or shadow). The device type and file size is also specified in this header. The header is identical to the header used for uncompressed CKD files, except for the eye-catcher:

devid heads trksize
devt seq hicyl  


reserved


The next 512 bytes contains the compressed device header. This contains file usage information such as the amount of free space in the file:

vrm opts numl1 numl2 size
used ->free free largest
number   cyls   comp parm


reserved


After the compressed device header is the primary lookup table, also called the level 1 table or l1tab. Each 4 byte unsigned entry in the l1tab contains the file offset of a secondary lookup table or level 2 table or l2tab. The track or block group number being accessed divided by 256 gives the index into the l1tab. That is, each l1tab entry represents 256 tracks or block groups. The number of entries in the l1tab is dependent on the size of the emulated device:

l20 l21 l22 l23
l24 l25 l26 l27


.     .     .


l2n-4 l2n-3 l2n-2 l2n-1

Following the l1tab, in no particular order, are l2tabs, track or block group images, and free spaces.

Each secondary lookup table (or l2tab), contains 256 8-byte entries. The entry is indexed by the remainder of the track or block group number divided by 256. Each entry contains an unsigned 4 byte offset, an unsigned 2 byte length and an unsigned 2 byte size. The length is the space required for the track or block group image and the size is the amount of space actually used. The size may be greater than the length to prevent short free spaces from accumulating in the file.

0  ->image         length size
1  ->image         length size

.     .    .

255  ->image         length size

A track or block group image contains two fields, a 5-byte header and a variable amount of data that may or may not be compressed. The length in the l2tab entry includes the length of the header and the data.

hdr track or block group data

The 5 byte header contains a 1 byte compression indicator and 4 bytes that identify the track or block group. The format of the identifier depends on whether the emulated device is CKD or FBA:

CKD hdr
comp CC   HH  

The 2 byte CC is the cylinder number for the track image and the HH is the head number. These numbers are stored in big-endian byte order. When the compression indicator byte is zeroed, the 5 byte header is identical to the Home Address (or HA) for the track image. The data, which may or may not be compressed, begins with the R0 count and ends with the end-of-track (or eot) marker, which is a count field containing FFFFFFFFFFFFFFFF. The HA plus the uncompressed track data comprise the track image.

FBA hdr
comp nnnn        

The 4 byte nnnn field is the FBA block group number in big-endian byte order. The data contains 120 FBA blocks, which may or may not be compressed. Uncompressed, the FBA block group is 60K. The header for FBA, unlike CKD, is not used as part of the uncompressed image.

The compression indicator byte contains the value 0, 1 or 2. Any other value is invalid.
0
    Data is uncompressed
1
    Data is compressed using zlib
2
    Data is compressed using bzip2
3 .. 255    Not valid

Free space contains a 4-byte offset to the next free space, a 4-byte length of the free space, and zero or more bytes of residual data:

->next length    residual   

The minimum length of a free space is 8 bytes. The free space chain is ordered by file offset and no two free spaces are adjacent. The compressed device header contains the offset to the first free space. The chain is terminated when a free space has zero offset to the next free space. The free space chain is read when the file is opened for read-write and written when the file is closed; while the file is opened, the free space chain is maintained in storage.


How It Works

Reading

A track or block group image is read while executing a channel program or by the readahead thread. An image has to be read before it is updated or written to. An image may be cached. If an image is cached, then the channel program may complete synchronously. This means that if all the data a channel program accesses is cached and Hercules does not have to perform physical I/O, then the channel program runs synchronously within the SSCH or SIO instruction in the CPU thread. All DASD channel programs are started synchronously. If a CCW in the channel program requires physical I/O then the channel program is interrupted and restarted at that CCW asynchronously in a device I/O thread.

All compressed devices share a common cache; the devices can be a mixture of FBA and/or CKD device types. Each cache entry contains a pointer to a 64K buffer containing an uncompressed track or block group image. If the track or block group image being read is not found in the cache, then the oldest (or least recently used or LRU) entry that is not busy is stolen. A cache entry is busy if it is being read, or last accessed by an active channel program, or updated but not yet written, or being written. If no cache entries are available then the read must enter a cache wait. When images are detected to be accessed sequentially then the readahead thread(s) may be signalled to read following sequential images.

Writing

When a cache entry is updated or written to, a bit is turned on indicating the cache entry has been updated. When a cache wait occurs, or (more likely) during space recovery, a cache flush is performed. When the cache is flushed, if any entries have the updated bit on, then the writer thread(s) are signalled. The writer thread selects the oldest cache entry with the updated bit on, compresses the image, and writes it to the file. The new image is written to a new space in the file and then the space previously occupied by the image is freed. In certain circumstances, the image may be written under stress. A stress write occurs when a reading thread is in a cache wait or when a high percentage of cache entries are pending write. In this circumstance, the compression parameters are relaxed to reduce the CPU requirements. An image written under stress is likely to take up more space than the same image written not under stress. The writer thread(s) run 1 nicer than the CPU thread(s); compression is a CPU intensive activity.

Space Recovery

Space recovery is also called, somewhat inaccurately, garbage collection. The primary function of the space recovery thread, or garbage collector, is to keep the emulated compressed DASD files as small as possible. After all, that is the reason for using compressed DASD files in the first place.

When a track or block group image is written, it is written to a new location in the file. It is either written to an existing free space within the file or to the end of the file, increasing the size of the file. The space previously occupied by the image is freed, but it is not immediately available for space allocation requests. Instead, it is pending free space. It is assigned a pending value (typically 2) that is decremented each space recovery cycle (typically every 10 seconds). When the pending value reaches 0 then the space is available for allocation. This increases the chance that a track or block group image can be recovered in the event of a failure.

The space recovery routine relocates track or block group images towards the beginning of the file, causing free space to move towards the end of the file. When a free space reaches the end of the file, it `falls off', that is, the file size is reduced.

Simply, the space recovery routine selects a space after a sufficiently large non-pending free space. It then reads and writes consecutive spaces using the normal cckd read and write routines. The space read will become pending free space and will hopefully be written to a non-pending free space occurring earlier in the file. Sometimes it is necessary to write the space later in the file to increase free space size earlier in the file. Left to itself, the space recovery routine will eventually remove all free space from the file. However, it is not intended to be a replacement for the cckdcomp utility; rather, the intent is to provide sufficient free space to prevent excessive file growth.

Another function performed by space recovery is to relocate L2 (secondary lookup) tables towards the beginning of the file. This enables the chkdsk function to complete more quickly during initialization and simplifies chkdsk recovery.


The cckd command and initialization statement

The cckd command and initialization statement can be used to affect cckd processing. The CCKD initialization statement is specified as a Hercules configuration file statement and supports the same options as the cckd command explained below.

Syntax:
cckdhelpDisplay cckd help
cckdstats Display current cckd statistics
cckdoptsDisplay current cckd options
cckdopt=valueSet a cckd option
  Multiple options may be specified, separated by a comma with no intervening blanks.
 comp=nCompression to be used
 compparm=nCompression parameter to be used
 ra=nNumber readahead threads
 raq=nReadahead queue size
 rat=nNumber of tracks to readahead
 wr=nNumber writer threads
 gcint=nGarbage collection interval
 gcparm=nGarbage collection parameter
 nostress=nTurn stress writes on or off
 freepend=nSet the free pending value
 fsync=nTurn fsync on or off
 trace=nNumber of trace table entries
 linuxnull=nCheck for null linux tracks
 gcstart=nStart garbage collector

Options:
comp=n Compression type:
-1 Default
  0 None
  1 zlib
  2 bzip2

Override the compression used for all cckd files. -1 (default) means don't override the compression.

compparm=n Compression parameter. A value between -1 and 9. -1 means use the default parameter. A higher value generally means more compression at the expense of cpu and/or storage.

ra=n Number of readahead threads. When sequential track or block group access is detected, some number (rat=) of tracks or block groups are queued (raq=) to be read by one of the readahead threads.

The default is 2.

You can specify a number between 1 and 9.

raq=n Size of the readahead queue. When sequential track or block group access is detected, some number (rat= ) of tracks or block groups are queued in the readahead queue.

The default is 4.

You can specify a number between 0 and 16 (a value of zero disables readahead).

rat=n Number of tracks or block groups to read ahead when sequential access has been detected.

The default is 2.

You can specify a number between 0 and 16 (a value of zero disables readahead).

wr=n Number of writer threads. When the cache is flushed updated cache entries are marked write pending and a writer thread is signalled. The writer thread compresses the track or block group and writes the compressed image to the emulation file. A writer thread is cpu-intensive while compressing the track or block group and i/o-intensive while writing the compressed image. The writer thread runs one nicer than the CPU thread(s).

The default is 2.

You can specify a number between 1 and 9.

gcint=n Number of seconds the garbage collector thread waits durinng an interval. At the end of an interval, the garbage collector performs space recovery, flushes the cache, and optionally fsyncs the emulation file. (However, the file will not be fsynced unless at least 5 seconds have elapsed since the last fsync).

The default is 10 seconds.

You can specify a number between 1 and 60.

gcparm=n A value affecting the amount of data moved during the garbage collector's space recovery routine. The garbage collector determines an amount of space to move based on the ratio of free space to used space in an emulation file, and on the number of free spaces in the file. (The garbage collector wants to reduce the free space to used space ratio and the number of free spaces). The value is logarithmic; a value of 8 means moving 28 the selected value while a negative value similarly decreases the amount to be moved. Normally, 256K will be moved for a file in an interval. Specifying a value of 8 can increase the amount to 64M. At least 64K will be moved. Interestingly, specifying a large value (such as 8) may not increase the garbage collection efficiency correspondingly.

The default is 0.

You can specify a number between -8 and 8.

nostress= Indicates whether stress writes will occur or not. A track or block group may be written under stress when a high percentage of the cache is pending write or when a device i/o thread is waiting for a cache entry. When a stressed write occurs, the compression algorithm and/or compression parm may be relaxed, resulting in faster compression but usually a larger compressed image. If nostress is set to one, then a stressed situation is ignored. You would typically set this value to one when you want create the smallest emulation file possible in exchange for a possible performance degradation.

The default is 0.

You can specify 0 (enable stressed writes) or 1 (disable stressed writes).

freepend= Specifies the free pending value for freed space. When a track or block group image is written the space it previously occupied is freed. This space will not be available for future allocations until n garbage collection intervals have completed. In the event of a catastrophic failure, previously written track or block group images should be recoverable if the current image has not yet been written to the physical disk. By default the value is set to -1. This means that if fsync is specified then the value is 1 otherwise it is 2. If 0 is specified then freed space is immediately available for new allocations.

The default is -1.

You can specify a number between -1 and 4.

fsync= Enables or disables fsync. When fsync is enabled, then the disk emulation file is synchronized with the physical hard disk at the end of a garbage collection interval (however, no more often than 5 seconds). This means that if freepend is non-zero then if a catastrophic error occurs then the emulated disks should be recovered coherently. However, fsync may cause performance degradation depending on the host operating system and/or the host operating system level.

The default is 0 (fsync disabled).

You can specify 0 (disable fsync) or 1 (enable fsync).

trace= Number of cckd trace entries. You would normally specify a non-zero value when debugging or capturing a problem in cckd code. When the problem occurs, you should enter the k Hercules console command which will print the trace table entries.

The default is 0.

You can specify a number between 0 and 200000. Each entry represents 128 bytes. Normally, for debugging, I use 100000.

linuxnull= If set to 1 then tracks written to 3390 cckd volumes that were initialized with the -linux option will be checked if they are null (that is, if all 12 4096 byte user records contain zeroes). This is used by the dasdcopy utility.

The default is 0.

gcstart= If set to 1 then space recovery will become active on any emulated disks that have free space. Normally space recovery will ignore emulated disks until they have been updated.

The default is 0.


Utilities

ckd2cckd  
cckd2ckd  
fba2cfba  
cfba2fba  
These utilities are deprecated. Use the dasdcopy utility instead

cckdcdsk   [-v] [-f] [-ro] [-level] filename1 [filename2 ...]
  Check the integrity of one or more compressed files. Recover damaged files.
 
-v   Display version and exit.
-f   Perform check even if the OPENED bit is on.
-ro   Open the file(s) read-only. The file will not be updated.
-level   A number 1 .. 4 indicating the level of checking.
1 Minimal checking (default)
2 Medium checking. All track headers will be read.
3 Maximal checking. All track images will be read and uncompressed.
4 Recover everything

cckdcomp   [-v] [-f] [-level] filename1 [filename2 ...]
  Remove all free space from a compressed file or files.
 
-v   Display version and exit.
-f   Perform compress even if the OPENED bit is on.
-level   A number 1 .. 3 indicating the chkdsk level.

cckdswap   [-v] [-f] [-level] filename1 [filename2 ...]
  Change the endianess or byte-order of a compressed file or files
 
-v   Display version and exit.
-f   Perform swap even if the OPENED bit is on.
-level   A number 1 .. 3 indicating the chkdsk level.


Greg Smith gsmith@nc.rr.com


back

Last updated $Date: 2008-01-03 20:45:25 -0600 (Thu, 03 Jan 2008) $ $Revision: 4530 $

hercules-3.07/html/fishgui.html000644 000765 000765 00000007250 11143760535 020244 0ustar00jmaynardjmaynard000000 000000
Dial 1 Dial 2 Dial 3 Dial 4
Sys Man Wait Load
hercules-3.07/html/hercconf.html000644 000765 000765 00000445433 11321734032 020375 0ustar00jmaynardjmaynard000000 000000 Hercules Version 3: Configuration File

Hercules Version 3: Configuration File

This page describes the configuration file for the Hercules S/370, ESA/390, and z/Architecture emulator.

The configuration file hercules.cnf contains the processor and device layout. It is roughly equivalent to the IOCDS on a real System/390. The configuration file is an ASCII text file.

Example configuration file

Please note that the below example configuration file should not be considered a good example of what an actual configuration file looks like. It is only meant to illustrate what some of the supported configuration file statements look like and how they are used.




    ####################################################################
    #                HERCULES EMULATOR CONTROL FILE                    #
    #             (Note: not all parameters are shown)                 #
    ####################################################################


    #
    #     System parameters
    #


    ARCHMODE   ESA/390
    OSTAILOR   OS/390
    LOADPARM   0120....

    CPUSERIAL  000611
    CPUMODEL   3090
    CPUVERID   FD
    LPARNAME   HERCULES
    LPARNUM    21
    MODEL      EMULATOR
    PLANT      ZZ
    MANUFACTURER HRC
    MAINSIZE   64
    XPNDSIZE   0
    NUMCPU     1
    NUMVEC     1
    MAXCPU     8
    ENGINES    CP
    SYSEPOCH   1900
    YROFFSET   -28
    TZOFFSET   -0500

    HTTPROOT   /usr/local/share/hercules/
    HTTPPORT   8081 NOAUTH

    CCKD       RA=2,RAQ=4,RAT=2,WR=2,GCINT=10,GCPARM=0,NOSTRESS=0,TRACE=0,FREEPEND=-1
    SHRDPORT   3990

    PANTITLE   "My own private MAINFRAME!"
    PANRATE    FAST
    LOGOPT     TIMESTAMP
    CODEPAGE   default
    CNSLPORT   3270
    CONKPALV   (3,1,10)
    LEGACYSENSEID   OFF

    HERCPRIO   0
    TODPRIO    -20
    DEVPRIO    8
    CPUPRIO    15

    TIMERINT   DEFAULT
    TODDRAG    1.0
    DEVTMAX    8

    DIAG8CMD   disable
    SHCMDOPT   disable

    DEFSYM     TAPEDIR   "$(HOME)/tapes"
    AUTOMOUNT  $(TAPEDIR)
    AUTOMOUNT  +/tapes
    AUTOMOUNT  -/tapes/vault

    MODPATH    /usr/local/hercules
    LDMOD      dyncrypt

    PGMPRDOS   restricted
    ECPSVM     no
    ASN_AND_LX_REUSE  disable

    AUTO_SCSI_MOUNT      no
    MOUNTED_TAPE_REINIT  allow

    INCLUDE    mydevs.cfg
    IGNORE     INCLUDE_ERRORS
    INCLUDE    optdevs.cfg


    #
    #     Device statements
    #


    0009      3215-C  /

    000A      1442    adrdmprs.rdr
    000C      3505    jcl.txt     ascii  trunc
    000D      3525    pch00d.txt  ascii
    000E      1403    prt00e.txt  noclear
    001E      1403    192.168.200.1:1403 sockdev

    001F      3270    * 192.168.0.1
    0200.4    3270    * 192.168.0.0  255.255.255.0
    0220.8    3270    GROUP1  192.168.100.0  255.255.255.0
    0228.8    3270    GROUP2
    0230.16   3270

    0000      SYSG    SYSGCONS

    0120      3380    ${DASD_PATH=dasd/}mvsv5r.120
    0121      3380    ${DASD_PATH=dasd/}mvsv5d.121
    0122      3380    ${DASD_PATH=dasd/}mvswk1.122
    0123      3380    192.168.1.100

    0140      3370    dosres.140
    0141      3370    syswk1.141
    0300      3370    sysres.300

    0400      CTCT    30880  192.168.100.2  30880  2048      
    0401      CTCT    30881  192.168.100.2  30881  2048
    0420.2    CTCI    192.168.200.1  192.168.200.2
    0440.2    LCS     -n   /dev/net/tun   192.168.200.2

    0580      3420    /dev/nst0   # SCSI  (Linux or Windows)
    0581      3420    \\.\Tape0   # SCSI  (Windows only)
    0582      3420    ickdsf.aws  noautomount
    0583      3420    /cdrom/tapes/uaa196.tdf
    0584-0587 3420    $(TAPEDIR)/volumes.$(CUU) maxsizeM=170 eotmargin=131072

    0590      3480    /dev/nst0 --no-erg --blkid-32   # Quantum DLT SCSI

    0023      2703    lport=3780 rhost=localhost rport=3781 dial=no

Comment lines

Blank lines, and lines beginning with a # sign or an asterisk, are treated as comments.


System parameters

System parameters may appear in any order but they must precede all device statements. Each system parameter must be on a separate line. The following system parameters may be specified:

ARCHMODE   S/370 | ESA/390 | z/Arch | ESAME

specifies the initial architecture mode:

  • use S/370 for OS/360, VM/370, and MVS 3.8.
  • use ESA/390 for MVS/XA, MVS/ESA, OS/390, VM/ESA, VSE/ESA, Linux/390, and ZZSA.
  • use z/Arch or ESAME for z/OS and zLinux.

ESAME is a synonym for z/Arch. When z/Arch or ESAME is specified, the machine will always IPL in ESA/390 mode, but is capable of being switched into z/Architecture mode after IPL. This is handled automatically by all z/Architecture operating systems.

ASN_AND_LX_REUSE   DISABLE | ENABLE

specifies that the ASN-and-LX-Reuse Facility (ALRF) is to be disabled or enabled. The default is disabled. This is a z/Architecture-only feature (it is always disabled for S/390 or ESA/390). Set this to ENABLE  if the operating system supports this z/Architecture feature and the use of this feature is desired. Set it to DISABLE  or do not specify anything if the operating system doesn't support this feature, and it inadvertently sets CR0 bit 44 to 1, usually leading to unexpected program interrupt when instructions such as LASP are issued.

ASN_AND_LX_REUSE may be abbreviated as ALRF

AUTOMOUNT   [±]directory

specifies the host system directory where the guest is allowed or not allowed to automatically load virtual tape volumes from. Prefix allowable directories with a '+' plus sign and unallowable directories with a '-' minus sign. The default prefix if neither is specified is the '+' plus sign (i.e. an allowable directory).

Caution:  Enabling this feature may have security consequences depending on which allowable host system directories you specify as well as how your guest operating system enforces authorized use of the Set Diagnose (X'4B') channel command code.

All host system virtual tape volumes to be "automounted" by the guest must reside within one of the specified allowable host system directories or any of its subdirectories while not also being within any of the specified unallowable directories or any of their subdirectories, in order for the guest-invoked automount to be accepted.

Note: specifying a disallowed automount directory does not preclude the Hercules operator from manually mounting any desired file via the devinit panel command -- even one in a currently defined "disallowed" automount directory. The AUTOMOUNT statement only controls guest-invoked automatic tape mounts and not manual tape mounts performed by the Hercules operator.

All directories must be specified on separate statements, but as many statements as needed may be specified in order to describe the desired allowable/unallowable directories layout. For convenience, an automount panel command is also provided to dynamically add/remove new/existing allowable/unallowable automount directories at any time.

The automount feature is activated whenever you specify at least one allowable or unallowable directory. If only unallowable directories are specified, then the current directory becomes the only defined allowable automount directory by default.

All specified directories are always resolved to fully-qualified absolute directory paths before being saved.

Refer to the description of the virtual tape device 'noautomount' option for more information.

AUTO_SCSI_MOUNT   NO | YES | nn

specifies whether automatic detection of SCSI tape mounts are to be enabled or not.

Specifying NO or 0 seconds (the default) indicates the option is disabled, forcing all SCSI tape mounts to be done manually via an appropriate devinit command.

A value from 1 to 99 seconds inclusive enables the option and causes periodic queries of the SCSI tape drive to automatically detect when a new tape is mounted. Specifying YES  is the same as specifying 5 seconds, the current default interval.

The scsimount panel command may also be used to display and/or modify this value on demand once Hercules has been started. Note too that the scsimount panel command also lists any mounts and/or dismounts that may still be pending on the drive, as long as you've defined your tape drive as a model that has an LCD "display" (such as a model 3480, 3490 or 3590).

Note:  enabling this option may cause Hercules to take longer to shutdown depending on the value specified for this option as well as how the host operating system (Windows, Linux, etc) and associated hardware (SCSI adapter) behaves to drive status queries for drives which do not have any media currently mounted on them.

CCKD   cckd-parameters

The CCKD command and initialization statement can be used to affect cckd processing. The CCKD initialization statement is specified as a Hercules configuration file statement and supports the same options as the cckd panel command. Refer to the Compressed Dasd Emulation web page for more information.

CODEPAGE   mapping

specifies the codepage conversion mapping table used for ASCII/EBCDIC translation.

default specifies traditional Hercules codepage mapping.

Other supported codepage mappings are:

Mapping Description
ASCII EBCDIC
437/037 437 PC United States 037 United States/Canada
437/500 437 PC United States 500 Latin 1
850/273 850 PC Latin 1 273 Austria/Germany
819/273 819 ISO-8859-1 273 Austria/Germany
819/277 819 ISO-8859-1 277 Denmark/Norway
819/278 819 ISO-8859-1 278 Finland/Sweden
819/280 819 ISO-8859-1 280 Italy
819/284 819 ISO-8859-1 284 Spain
819/285 819 ISO-8859-1 285 United Kingdom
819/297 819 ISO-8859-1 297 France
819/500 819 ISO-8859-1 500 International
437/1047 437 PC United States 1047 Open Systems Latin 1
819/1047 819 ISO-8859-1 1047 Open Systems Latin 1
1252/1047 1252 Windows Latin 1 1047 Open Systems Latin 1
850/1047 850 PC Latin 1 1047 Open Systems Latin 1

Iconv single byte codepages may also be used (e.g. UTF8/EBCDIC-CP-NL).

If no codepage is specified then the environment variable HERCULES_CP will be inspected. The default codepage mapping is default.

CNSLPORT   nnnn

specifies the port number (in decimal) to which tn3270 and telnet clients will connect.

The CNSLPORT statement may also have the form of host:port, where the telnet console server will bind to the specified address.

CONKPALV   (idle,intv,count)

specifies the tn3270 console and telnet clients keep-alive option values that control automatic detection of disconnected tn3270/telnet client sessions.

idle   specifies the number of seconds of inactivity until the first keep-alive probe is sent (idle time until first probe, or probe frequency).
intv   specifies the interval in seconds between when successive keep-alive packets are sent if no acknowledgement is received from the previous one (i.e. the timeout value of the probes themselves).
count   specifies the number of unacknowledged keep-alive packets sent before the connection is considered to have failed.

The default values are 3, 1, and 10. That is, send the initial probe 3 seconds after the line goes idle and then wait no more than one second for it to be responded to. Do this 10 times before considering the client as having died.

Note: This is a built-in feature of TCP/IP and allows detection of unresponsive TCP/IP connections and not idle clients. That is to say, your connection will not be terminated after 3 seconds of idle time. Your 3270 session can remain idle for many minutes without any data being transmitted. If the TCP/IP stack at the other end of the connection -- not your 3270 client itself -- fails to respond to the internal keep-alive probe packets, then it means that the TCP/IP stack is down or there has been a break in the connection. Thus, even if your 3270 client is completely idle, your system's TCP/IP stack itself should still respond to the keep-alive probes sent by the TCP/IP stack at the Hercules end of the link. If it doesn't, then TCP/IP will terminate the tn3270/telnet session which will cause Hercules to disconnect the terminal.

The three values can also be modified on-demand via the conkpalv panel command, which has the exact same syntax. Note that the syntax is very unforgiving: no spaces are allowed anywhere within the parentheses and each value must be separated from the other with a single comma.

Note: On Windows platforms the count value is ignored and cannot be changed from its default value of 10. Also, some older platforms may ignore all of the values specified and use platform default values instead.

CPUMODEL   xxxx

specifies the 4 hexadecimal digit CPU machine type number stored by the STIDP instruction Note: Prior to ESA/390 this was known as the CPU model number

CPUPRIO   nn

specifies the priority of the CPU thread. Default is a nice value of 15, which means a low priority such that I/O can be scheduled and completed in favour of CPU cycles being burned. On Multi-CPU systems, a real CPU can be "dedicated" to Hercules, by giving the CPU thread a very high dispatching priority (-20). See "Thread Priorities" below for more information.

Caution:   CPUPRIO should not have a higher dispatching priority than the TOD Clock and timer thread.

CPUSERIAL   xxxxxx

specifies the 6 hexadecimal digit CPU serial number stored by the STIDP instruction

CPUVERID   xx

specifies the 2 hexadecimal digit CPU version code stored by the STIDP instruction. The default version code is FD when ARCHMODE S/370 or ARCHMODE ESA/390 is specified. For the z/Architecture mode, the version code is always stored as 00 and the value specified here is ignored.

DEFSYM   symbol value

Defines symbol symbol as to contain value value. The symbol can then be the object of a substitution later in the configuration file or for panel commands. If value contains blanks or spaces, then it should be enclosed in double quotation marks ("). See substitutions for a more in-depth discussion on this feature.

Substitution is available even in configuration statements, meaning it is possible to perform substitution in the DEFSYM statement itself. However, symbols are always defined as the last step in the process, so attempting to self define a symbol will result in an empty string:

    DEFSYM FOO $(FOO)
Will set symbol FOO to ""

DEVPRIO   nn

specifies the priority of the device threads. The default value is 8. See "Thread Priorities" below for more information.

Caution:   DEVPRIO should not have a higher dispatching priority than the TOD Clock and timer thread.

DEVTMAX   -1 | 0 | nnn

specifies the maximum number of device threads allowed.

Specify -1 to cause 'one time only' temporary threads to be created to service each I/O request to a device. Once the I/O request is complete, the thread exits. Subsequent I/O to the same device will cause another worker thread to be created again.

Specify 0 to cause an unlimited number of 'semi-permanent' threads to be created on an 'as-needed' basis. With this option, a thread is created to service an I/O request for a device if one doesn't already exist, but once the I/O is complete, the thread enters an idle state waiting for new work. If a new I/O request for the device arrives before the timeout period expires, the existing thread will be reused. The timeout value is currently hard coded at 5 minutes. Note that this option can cause one thread (or possibly more) to be created for each device defined in your configuration. Specifying 0 means there is no limit to the number of threads that can be created.

Specify a value from 1 to nnn  to set an upper limit to the number of threads that can be created to service any I/O request to any device. Like the 0 option, each thread, once done servicing an I/O request, enters an idle state. If a new request arrives before the timeout period expires, the thread is reused. If all threads are busy when a new I/O request arrives however, a new thread is created only if the specified maximum has not yet been reached. If the specified maximum number of threads has already been reached, then the I/O request is placed in a queue and will be serviced by the first available thread (i.e. by whichever thread becomes idle first). This option was created to address a threading issue (possibly related to the cygwin Pthreads implementation) on Windows systems.

The default for Windows is 8. The default for all other systems is 0.

DIAG8CMD   DISABLE | ENABLE [ECHO | NOECHO]

When ENABLE is specified, commands issued through the Diagnose 8 interface will be executed by Hercules as Hercules commands. When set to DISABLE, commands issued through the Diagnose 8 interface will generate a Specification Exception program interrupt on the issuing CPU.

An optional second argument can be given to request whether the commands issued using the Diagnose 8 interface will be traced at the console. This may be useful for programs that routinely issue panel commands using the Diagnose 8 interface. When ECHO is specified, a message is issued as the panel is about to issue the command, the command is redisplayed as if it was entered through the panel input line, and a final message is issued to indicate the command completed. When NOECHO is specified, no such messages are displayed and the command completes silently.

The value of ECHO or NOECHO has no effect on command output being placed into a response buffer if the Diagnose 8 interface requested one.

The default is DISABLE NOECHO

Caution:   Enabling this feature may have security consequences.

When this feature is enabled it is possible for guest operating systems running under Hercules to issue commands directly to the host operating system by means of the Hercules sh (shell) command. This ability may be disabled via the SHCMDOPT statement.

ECPSVM   YES | NO | LEVEL nn

specifies whether ECPS:VM (Extended Control Program Support : Virtual Machine) support is to be enabled. If YES is specified, then the support level reported to the operating system is 20. The purpose of ECPS:VM is to provide to the VM/370 Operating system a set of shortcut facilities to perform hypervisor functions (CP Assists) and virtual machine simulation (VM Assists). Although this feature does not affect VM Operating system products operating in XA, ESA or z/Architecture mode, it will affect VM/370 and VM/SP products running under VM/XA, VM/ESA or z/VM. Running VM/370 and VM/SP products under VM/XA, VM/ESA or z/VM should be done with ECPS:VM disabled. ECPS:VM should not be enabled in an AP or MP environment. ECPS:VM has no effect on non-VM operating systems. It is however recommended to disable ECPS:VM when running native non-VM operating systems. If a specific LEVEL is specified, this value will be reported to the operating system when it issues a Store ECPS:VM level, but it doesn't otherwise alter the ECPS:VM facility operations. This is a partial implementation.

ENGINES   [nn*] CP | IL | AP | IP [,...]

specifies the type of engine for each installed processor. The default engine type is CP.

nn* is an optional repeat count.

Examples:

ENGINES CP,CP,AP,IP
specifies that processor engines 0 and 1 are of type CP, engine 2 is type AP, and engine 3 is type IP.

ENGINES 4*CP,2*AP,2*IP
specifies that the first four processor engines (engines 0-3) are of type CP, the next two (engines 4-5) are of type AP, and the next two (engines 6-7) are of type IP.

The number of installed processor engines is determined by the MAXCPU statement. If the ENGINES statement specifies more than MAXCPU engines, the excess engines are ignored. If fewer than MAXCPU engines are specified, the remaining engines are set to type CP.

HERCPRIO   nn

specifies the process priority for Hercules. The default is 0. See "Process Priorities" below for more information.

HTTPPORT   nnnn [AUTH | NOAUTH] [ userid password ]

specifies the port number (in decimal) on which the HTTP server will listen. The port number must either be 80 or within the range 1024 - 65535 inclusive. If no HTTPPORT statement is present or an invalid port number is specified, then the HTTP server thread will not be activated.
AUTH indictates that a userid and password are required to access the HTTP server, whereas NOAUTH indicates that a userid and password are not required. The userid and password may be any valid string.

HTTPROOT   directory

specifies the root directory where the HTTP server's files reside. If not specified, the default value for Win32 builds of Hercules is the directory where the Hercules executable itself is executing out of, and for non-Win32 builds it is the directory specified as the default package installation directory when the Hercules executable was built (which can vary depending on how the Hercules package was built, but is usually /usr/local/share/hercules/).

IGNORE   INCLUDE_ERRORS

Indicates that errors caused by subsequent INCLUDE statements for files which do not exist should instead be ignored rather than causing startup to be aborted (as would otherwise normally occur).

INCLUDE   filepath

An INCLUDE statement tells Hercules configuration file processing to treat the contents of the file specified by filepath as if its contents had appeared in the configuration file at the point where the INCLUDE statement appears.

Note that the included file may itself contain yet another INCLUDE statement as long as the maximum nesting depth (current 8) is not exceeded.

IODELAY   usec [NOWARN]

specifies the amount of time (in microseconds) to wait after an I/O interrupt is ready to be set pending. This value can also be set using the Hercules console. The purpose of this parameter is to bypass a bug in the Linux/390 and zLinux dasd.c device driver. The problem is more apt to happen under Hercules than on a real machine because we may present an I/O interrupt sooner than a real machine.

If the IODELAY value is non-zero a warning message (HHCCF037W) will be issued unless NOWARN is specified.

NOTE : OSTAILOR LINUX no longer sets IODELAY to 800 since the problem described above is no longer present in recent versions of the Linux kernel.

LDMOD   module list

specifies additional modules that are to be loaded by the Hercules dynamic loader. The default search order is with the hercules directory in the default DLL search path. Most systems also support absolute filenames (ie names starting with '/' or '.') in which case the default search path is not taken.

Multiple LDMOD statements may be used.

LEGACYSENSEID   OFF | DISABLE | ON | ENABLE

specifies whether the SENSE ID CCW (X'E4') will be honored for the devices that originally didn't support that feature. This includes (but may not be limited to) 3410 and 3420 tape drives, 2311 and 2314 direct access storage devices, and 2703 communication controllers.

Specify ON or ENABLE if your guest operating system needs the Sense ID support to dynamically detect those devices. Note that most current operating systems will not detect those devices even though Sense ID is enabled because those devices never supported the Sense ID in the first place. So this mainly applies to custom built or modified versions of guest operating systems that are aware of this specific Hercules capability.

Because those legacy devices didn't originally support this command, and for compatibility reasons, the default is OFF or DISABLE.

LOADPARM   xxxxxxxx

specifies the eight-character IPL parameter which is used by some operating systems to select system parameters.

LOGOPT   TIMESTAMP | NOTIMESTAMP

sets Hercules log options. TIMESTAMP causes messages to the log to be time stamped. NOTIMESTAMP prevents time stamping of log messages. TIMESTAMP and NOTIMESTAMP may be abbreviated as TIME and NOTIME respectively. The current resolution of the stamp is one second.

The default is TIMESTAMP.

LPARNAME   name

specifies the LPAR name returned by DIAG X'204'. The default is HERCULES.

LPARNUM   xx

specifies the one- or two-digit hexadecimal LPAR identification number stored by the STIDP instruction. If a one-digit number is specified then STIDP stores a format-0 CPU ID. If a two-digit number is specified then STIDP stores a format-1 CPU ID. If LPARNUM is not specified, then STIDP stores a basic-mode CPU ID.

MAINSIZE   nnnn

specifies the main storage size in megabytes, where nnnn  is a decimal number. The lower limit is 2. The actual upper limit is determined by your host system's architecture and operating system, and (on some systems) the amount of physical memory and paging space you have available.

MANUFACTURER   name

specifies the MANUFACTURER name returned the STSI instruction. The default is HRC.

MAXCPU   nn

specifies the number of installed processor engines. The NUMCPU statement specifies the number of engines which will be configured online at startup time. All processors are CP engines unless otherwise specified by the ENGINES statement.

The value of MAXCPU cannot exceed the value of MAX_CPU_ENGINES. If MAXCPU is not specified then the default value is the value of MAX_CPU_ENGINES.

MAX_CPU_ENGINES is a compile-time variable which sets an upper limit on the value of MAXCPU. The value of MAX_CPU_ENGINES is displayed in the Build information message on the Hercules control panel at startup time. To change the value of MAX_CPU_ENGINES you must rebuild Hercules. For Unix builds, specify ./configure --enable-multi-cpu=nn before performing make. For Windows builds, specify SET MAX_CPU_ENGINES=nn before performing nmake.

MAX_CPU_ENGINES cannot exceed 64. For performance reasons, values above 32 are not recommended for 32-bit platforms. If MAX_CPU_ENGINES is set to 1 then multiprocessing is disabled. See also NUMCPU for a discussion of the performance implications of MAX_CPU_ENGINES.

MODEL   hardware_model [ capacity_model ] [ perm_capacity_model ] [ temp_capacity_model ]

specifies the MODEL names returned by the STSI instruction.

If two operands are supplied, the first is the hardware model name (CPC ND model) and the second is the capacity model name (CPC SI model). If only one operand is supplied, it is used as both the hardware model name and the capacity model name. The optional third and fourth operands specify the permanent capacity model name and the temporary capacity model name respectively.

The default is EMULATOR.

MODPATH   path

specifies the path where dynamic modules are loaded from. When a modpath statement is specified, the path on the modpath statement is searched before the default path is searched. When a relative path is specified is interpreted as a relative path within the default search path, if an absolute path is specified is interpreted as such.

The default MODPATH is hercules, which means modules are loaded from the directory hercules within the default LD_LIBRARY_PATH.

MOUNTED_TAPE_REINIT   DISALLOW | ALLOW

specifies whether reinitialization of tape drive devices (via the devinit command, in order to mount a new tape) should be allowed if there is already a tape mounted on the drive.

Specifying ALLOW (the default) indicates new tapes may be mounted (via 'devinit nnnn new-tape-filename') irrespective of whether or not there is already a tape mounted on the drive.

Specifying DISALLOW prevents new tapes from being mounted if one is already mounted. When DISALLOW is specified and a tape is already mounted on the drive, it must first be unmounted (via the command 'devinit nnnn *') before the new tape can be mounted. Otherwise the devinit attempt to mount the new tape is rejected.

This option is meant as a safety mechanism to protect against accidentally dismounting a tape from the wrong drive as a result of a simple typo (thereby cancelling a potentially important tape job) and was added by user request.

Also note that for SCSI tape drives the 'devinit nnnn *' command has no effect as the tape must be unmounted manually (since it is a real physical device and not one emulated via a disk file like .AWS tapes).

NUMCPU   nn

specifies the number of emulated processor engines which will be configured online at startup time. NUMCPU cannot exceed the value of MAXCPU. If NUMCPU is less than MAXCPU then the remaining engines can be configured online later.

Multiprocessor emulation works best if your host system actually has more than one physical CPU, but you can still emulate multiple CPUs nervertheless even on a uniprocessor system (and you might even achieve a small performance benefit when you do). There is little point, however, in specifying NUMCPU greater than 1 unless your guest operating system (running under Hercules) is actually able to support multiple CPUs (and if you do not actually need multiprocessor emulation, then setting MAX_CPU_ENGINES to 1 at compile time might even produce a slight performance advantage too).

NUMVEC   nn

specifies the number of emulated vector facilities. Default is one per CPU. Only available by default in ESA/390 mode.

OSTAILOR   OS/390 | z/OS | VM | VSE | LINUX | QUIET | NULL

specifies the intended operating system. The effect of this parameter is to reduce control panel message traffic by selectively suppressing trace messages for program checks which are considered normal in the specified environment. QUIET discards all exception messages. NULL allows all exception messages to be logged.

Optionally prefix any value except QUIET or NULL with '+' to cause the suppressions for that environment to be combined (added) to those already specified, or with '-' to remove such suppressions (i.e. to allow them).

If the OSTAILOR statement is omitted, exception messages for program checks 10, 11, 16, and 1C are suppressed.

Use the ostailor or pgmtrace panel commands to display or alter the current settings.

PANRATE   SLOW | FAST | nn

specifies the panel refresh rate, in milliseconds between refreshes. SLOW is the same as 500, and FAST is the same as 50. A value less than the Linux system clock tick interval (10 on Intel, 1 on Alpha), or more than 5000, will be rejected. SLOW is the default.

PANTITLE   "title-string"

specifies an optional console window title-bar string to be used in place of the default supplied by the windowing system. If the value contains any blanks it must be enclosed within double-quotes.

This option allows one to distinguish between different Hercules sessions when running more than one instance of Hercules on the same machine.

This option takes effect only when the Hercules console is displayed on an xterm terminal (commonly used on Unix systems), or in a Windows command prompt window. Note that this option has no effect when Hercules is run under control of the Hercules GUI since Hercules's console window is hidden in favor of using the GUI's window instead.

PGMPRDOS   RESTRICTED | LICENSED

specifies whether or not Hercules will run licensed program product ESA or z/Architecture operating systems. If RESTRICTED is specified, Hercules will stop all CPUs when a licensed program product operating system is detected. Specify LICENSED to allow these operating systems to run normally. This parameter has no effect on Linux/390, Linux for z/Series, or any 370-mode OS.

NOTE:  It is YOUR responsibility to comply with the terms of the license for the operating system you intend to run on Hercules. If you specify LICENSED and run a licensed operating system in violation of that license, then don't come after the Hercules developers when the vendor sends his lawyers after you.

RESTRICTED is the default. Specifying LICENSED will produce a message when a licensed operating system is detected to remind you of your responsibility to comply with software license terms.

PLANT   name

specifies the PLANT name returned by the STSI instruction. The default is ZZ.

SHCMDOPT   DISABLE | NODIAG8

When set to DISABLE, sh (shell) commands are globally disabled, and will result in an error if entered either directly via the Hercules hardware console or programmatically via the DIAG8CMD interface.

When set to NODIAG8 only the programmatic execution of shell commands via the the Diagnose 8 interface is disabled, but sh (shell) commands entered directly via the Hercules hardware console will still work.

NOTE:  "entered directly via the Hercules hardware console" also pertains to both commands entered via the HTTP server facility as well as commands entered via .rc "run command" scripts.

SHRDPORT   nnnn

specifies the port number (in decimal) on which the Shared Device server will listen. Specifying SHRDPORT will allow other Hercules instances to access devices on this instance. (Currently only DASD devices may be shared). By default, the other Hercules instances (clients) will use port 3990. If you specify a different port number, then you will have to specify this port number on the device statement for the other Hercules clients. If no SHRDPORT statement is present then the Shared Device server thread will not be activated.

SYSEPOCH   yyyyyears]

specifies the base date for the TOD clock. Use the default value (1900) for all systems except OS/360. Use 1960 for OS/360. Values other than these were formerly used to offset the TOD clock by a number of years to move the date before the year 2000 for non-Y2K-compliant operating systems. This use is deprecated, and support will be removed in a future release; at that time, only values of 1900 or 1960 will be accepted. Other values will produce a warning message with the equivalent values to specify in the SYSEPOCH statement.
An optional year offset may be specified, and will be treated as though it had been specified on a YROFFSET statement.

TIMERINT   DEFAULT | nnnn

specifies the internal timers update interval, in microseconds. This parameter specifies how frequently Hercules's internal timers-update thread updates the TOD Clock, CPU Timer, and other architectural related clock/timer values. The default interval is 50 microseconds, which strikes a reasonable balance between clock accuracy and overall host performance. The minimum allowed value is 1 microsecond and the maximum is 1000000 microseconds (i.e. one second).

Caution:   While a lower TIMERINT value may help increase the accuracy of your guest's TOD Clock and CPU Timer values, it could also have a severe negative impact on the overall performance of your host operating system. This is especially true when a low TIMERINT value is coupled with a high HERCPRIO and TODPRIO priority setting. Exercise extreme caution when choosing your desired TIMERINT in relationship to your chosen HERCPRIO and TODPRIO priority settings.

TODDRAG   nn

specifies the TOD clock drag factor. This parameter can be used to slow down or speed up the TOD clock by a factor of nn. A significant slowdown can improve the performance of some operating systems which consume significant amounts of CPU time processing timer interrupts. A drag factor of 2.0 slows down the clock by 50%. A drag factor of 0.5 doubles the speed of the clock. A drag factor of 1.01 slows down the clock by 1%, and 0.99 speeds up the clock by 1%.

TODPRIO   nn

specifies the priority of the TOD Clock and timer thread. The default value is -20. See "Thread Priorities" below for more information.

Caution:   TODPRIO should be given a dispatching priority equal to or higher than any other thread within Hercules.

TRACEOPT   TRADITIONAL | REGSFIRST | NOREGS

sets the Hercules instruction tracing display option. TRADITIONAL (the default), displays the registers following the instruction about to be executed such that pressing enter (to execute the displayed instruction) then shows the next instruction to be executed followed by the updated registers display.

REGSFIRST displays the current register contents followed by the instruction about to be executed such that pressing enter (to execute the displayed instruction) then shows the updated registers followed by the next instruction to be executed.

NOREGS suppresses the registers display altogether and shows just the instruction to be executed.

In addition to the TRACEOPT configuration file statement there is also a corresponding traceopt panel command to dynamically display and/or update the current setting at any time.

TZOFFSET   ±hhmm

specifies the hours and minutes by which the TOD clock will be offset from the current system time. For GMT, use the default value (0000). For timezones west of Greenwich, specify a negative value (example: -0500 for US Eastern Standard Time, -0800 for US Pacific Standard Time). For timezones east of Greenwich, specify a positive value (example: +0100 for Central European Time, +0930 for South Australian Time).

XPNDSIZE   nnnn

specifies the expanded storage size in megabytes, where nnnn is a decimal number. The lower limit is 0. The actual upper limit is determined by your host system's architecture and operating system, and (on some systems) the amount of physical memory and paging space you have available.

YROFFSET   ±years

specifies a number of years to offset the TOD clock from the actual date. Positive numbers will move the clock forward in time, while negative numbers will move it backward. A common value for non-Y2K-compliant operating systems is YROFFSET -28, which has the advantage that the day of the week and the presence or absence of February 29 is the same as the current year. This value may not be specified as greater than ±142 years, the total range of the TOD clock. Specifying a value that causes the computed TOD clock year to be earlier than the value of SYSEPOCH or more than 142 years later than that value will produce unexpected results.

A comment preceded by a # sign may be appended to any system parameter statement.


Symbol substitutions

In configuration and device statements, as well as in panel commands and OAT files, symbols may be substituted for text.

Syntax

To substitute symbol symbol with its contents, the symbol should be enclosed within parenthesis and preceded by a $ sign. For example, if symbol FOO contains the text string "BAR" then $(FOO) will be substituted with the string "BAR";. Symbol names are case sensitive.

Example
        DEFSYM  TAPEDIR  "/home/hercules/tapes"

        ...

        0380  3420  $(TAPEDIR)/scratch.aws

        ...

In this example, device 0380 will be a 3420 loaded with the AWS tape file in /home/hercules/tapes/scratch.aws

Special symbols

Device group symbols

When multiple devices are defined with a single device definition statement, then the symbols

  •   CUU  
  •   (3 digits device number, upper case hexadecimal digits)
  •   CCUU  
  •   (4 digits device number, upper case hexadecimal digits)
  •   cuu  
  •   (3 digits device number, lower case hexadecimal digits)
  •   ccuu  
  •   (4 digits device number, lower case hexadecimal digits)

    are defined to contain for each device the relevant device address. For example:

        0200,0201  3340  /home/hercules/dasds/myvols.$(CUU)
    

    will define two 3340 packs, with device 0200 being loaded with the file myvols.200 and device 0201 defined with myvols.201.

    Environment variables

    If a symbol is not explicitly defined by a DEFSYM statement and an environment variable by the same name exists, the string contents of that environment variable will be used for substitution.

    Undefined symbols

    If a symbol is not defined by an explicit DEFSYM, is not an automatically generated symbol and is not an environment variable, an empty string will be substituted.

    Escaping substitution, recursion

    To be able to specify the '$(' string without incurring substitution, an additional '$' sign should be used. For example, $$(FOO) will not be substituted. If substitution is required but the preceding text is to contain a '$' sign as the very last character, then $$$(FOO) should be specified. Thus, if symbol FOO contains "BAR", then $$(FOO) will remain "$$(FOO)" while $$$(FOO) will become "$BAR".

    Substitution is not recursive (only one substitution pass is made).


    Enhanced symbol substitutions

    Enhanced symbol substitution differs from the above normal symbol substitution in several very important ways:

    First, the syntax is different. Enhanced substitution symbol names are specified using ${var} (dollar + brace) rather than $(var) (dollar + parenthesis).

    Second, the enhanced syntax supports specifying a default value that is to be used instead whenever the name symbol is otherwise not defined. The default value is placed within the opening and closing braces just as the symbol name is, but separated from it by either a single equal sign '=' or a colon-equal-sign ':='.

    For example, specifying "${DASD_PATH=dasd/}" in your configuration file requests that the value of the "DASD_PATH" symbol or environment variable be substituted, or, if the variable is undefined, to use the value "dasd/" instead. If no default value is specified then an empty string is used instead.

    Finally, enhanced symbol substitution occurs only from host defined environment variables and not from any identically named DEFSYM symbol should one exist. For example, if environment variable 'FOO' is defined with the value "bar", then the configuration file statement "DEFSYM FOO myfoo" followed immediately by the statement "${FOO}" causes the value "bar" to be substituted and not 'myfoo' as might otherwise be believed, whereas the statement "$(FOO)", since it is a normal symbol substitution sequence does get replaced with "myfoo" (since that was the value defined to it via the preceding DEFSYM statement).

    In other words each symbol substitution technique is supported completely separately from one another. DEFSYM allows one to define/undefine/use private (internally defined) symbols separate from the host operating system's environment variable pool, whereas the enhanced symbol substitution does not and instead only allows read-only access to the host's environment variable pool with no support for modifying an already defined symbol (environment variable) but a nonethless convenient means of defining a default value to be used should the specified host environment variable be currently undefined.

    Further note that symbol names, being the names of environment variables, are subject to whatever case sensitivity or case insensitivity that the host operating system happens to enforce/allow. On Windows, environment variables are not case sensitive, whereas on other operating systems they may be. Thus "${FOO}", "${foo}", "${Foo}", etc, all cause the same value to be substituted on Windows, whereas the DEFSYM symbols $(FOO) and $(foo), being two completely different and unique symbols, could be substituted with two completely different values (since DEFSYM is case sensitive across all supported platforms, including Windows).

    Syntax

    To substitute symbol symbol with the current environment variable value, the symbol should be enclosed within braces and preceded by a $ sign. For example, if an environment variable named FOO holds the value "BAR", then ${FOO} will be substituted with the string "BAR". If the environment variable "FOO" is not defined then a null (empty) string is substituted instead.

    If the string "${FOO:=myfoo}" is used instead, then the value "BAR" will still be substituted if the value "BAR" was indeed previously assigned to FOO, but will be substituted with the value "myfoo" instead if the environment variable FOO is currently undefined.

    Note too that the default value is a literal string and no substitution is applied to it. Thus attempting to use the syntax "${foo=${bar}}" will not yield the expected results. It will not be substituted with the currently defined value of the "bar" environment variable, but rather will always be substituted with the literal string "${bar" followed immediately by the literal character '}'.

    Symbol names (environment variable names) are not case sensitive on Windows whereas they might be on other host operating systems.


    Process and Thread Priorities


    Process Priorities

    Note: Under Linux, a process is a thread and thread priority information applies instead.

    For Windows, the following conversions are used for translating Unix process priorities to Windows process priority classes:


    Unix
    Priority

    Windows Process
    Priority Class

    Meaning
           
    -20 to -16   Real-time Process that has the highest possible priority. The threads of the process preempt the threads of all other processes, including operating system processes performing important tasks. For example, a real-time process that executes for more than a very brief interval can cause disk caches not to flush or cause the mouse to be unresponsive.
           
    -15 to -9   High Process that performs time-critical tasks that must be executed immediately. The threads of the process preempt the threads of normal or idle priority class processes. An example is the Task List, which must respond quickly when called by the user, regardless of the load on the operating system. Use extreme care when using the high-priority class, because a high-priority class application can use nearly all available CPU time.
           
    -8 to -1   Above Normal Process that has priority above the Normal class but below the High class.
           
    0 to 7   Normal Process with no special scheduling needs.
           
    8 to 14   Below Normal Process that has priority above the Idle class but below the Normal class.
           
    15 to 20   Idle Process whose threads run only when the system is idle. The threads of the process are preempted by the threads of any process running in a higher priority class. An example is a screen saver. The idle-priority class is inherited by child processes.


    Caution:   On Windows, the value you choose for your Process Priority has a direct impact on how your Thread Priorities are interpreted! You should never modify one without understanding what impact your doing so might have on the other!


    Thread Priorities

    On a Linux/Unix host, Hercules needs to be a setuid root program to allow it to reset its dispatching priority to a high (negative) value (i.e., chown root.root hercules; chmod +s hercules).

    For Windows, the following conversions are used for translating Linux/Unix thread priorities to Windows thread priorities:


    Unix
    Priority

    Windows
    Thread Priority

    Meaning
           
    -20 to -16   Time Critical Base priority of 15 for Idle, Below Normal, Normal, Above Normal, or High class processes, and a base priority of 31 for Realtime class processes.
           
    -15 to -9   Highest Priority 2 points above the priority class.
           
    -8 to -1   Above Normal Priority 1 point above the priority class.
           
    0 to 7   Normal Normal priority for the priority class.
           
    8 to 14   Below Normal Priority 1 point below the priority class.
           
    15 to 19   Lowest Priority 2 points below the priority class.
           
    20   Idle Base priority of 1 for Idle, Below Normal, Normal, Above Normal, or High class processes, and a base priority of 16 for Realtime class processes.


    Caution:   On Windows, your Thread Priority is interpreted differently based on your chosen Process Priority setting! You should never modify your Thread Priority settings without first reviewing your chosen Process Priority setting!


    Device statements

    The remaining statements in the configuration file are device statements. There must be one device statement for each I/O device or group of identical I/O devices. The format of the device statement is:

    devnum(s)   devtype   [ arguments ]   [ # comments... ]

    where the generic syntax for device numbers is   [n:]CCUU[,CCUU][-CCUU][.nn][...]   as explained below:

    devnum(s)

    is either a single devnum, a range of devnums (separated by a '-' (dash)), a count of devnums (separated by a '.' (dot/period/stop)), or a comma separated list of devnums. Examples would be 200-210 or 0300.10 or 0400,0403 or 0100,0110-011F.

    All devices defined when devnums specifies more than one device have identical characteristics (except for the device number itself). All devices defined as a group must be defined on a single channel. A channel is defined as a contiguous group of 256 (or hexadecimal 100) devices. 0010 and 0020 are on the same channels. 0100 and 0210 are not.

    See devnum immediately below for an explanation of how each device number is specified.

    The 4 special subtitution symbols CUU, CCUU, cuu and ccuu are also defined for each device in a device group. See substitutions for details.

    devnum

    is either a 1 to 4 digit hexadecimal number in the range 0000 to FFFF for ESA/390, or 0000 to 0FFF for S/370. The device number uniquely identifies each device to the operating system.

    Channel Set / Logical Channel Subsystem

    An optional Channel Set or Logical Channel Subsystem Identification can be specified for a device number or group of devices. The Identification number is specified at the beginning of the definition, followed by a ':' character. For example :

    1:0400-040F 3270

    defines 3270 devices 400 to 40F to be on S/370 Channel Set 1 or on S/390 or z/Architecture Logical Channel Subsystem # 1.

    Since each Logical Channel Subsystem defines its own device numbering space, care should be taken in S/370 mode as to define a coherent set of device numbers.

    Not all S/390 or z/Architecture operating systems support Multiple Logical Channel Subsystems (this feature was introduced with the z9-109).

    If no Channel Set or Logical Channel Subsystem Identification is specified, then it is assumed to be 0.

    devtype

    is the device type. Valid device types are shown in the table just below.

    arguments

    is a list of parameters whose meaning depends on the device type. The arguments required for each class of device are shown further below.

    # comments...

    A comment preceded by a # sign may be appended to any device definition statement.


     

    Supported Device Types

    Device type Description Emulated by
    3270, 3287 Local non-SNA 3270 display or printer TN3270 client connection
    SYSG Integrated 3270 console TN3270 client connection
    1052, 3215 Console printer-keyboards Telnet client connection
    1052-C, 3215-C Integrated console printer-keyboards Integrated on Hercules console
    1442, 2501, 3505 Card readers Disk file(s) (ASCII or EBCDIC)
    3525 Card punch Disk file (ASCII or EBCDIC)
    1403, 3211 Line printers Disk file (ASCII)
    3410, 3420, 3422, 3430, 3480, 3490, 3590, 9347, 8809 Tape drives Disk file, CDROM, or SCSI tape
    3088 Channel-to-Channel Adapter device "CTCT" driver
    (( CTCI )) Channel-to-Channel link to host TCP/IP stack "CTCI" TUN/TAP Driver
    (( LCS )) IBM 2216 router, IBM 3172 running ICP, IBM 8232 LCS device, LCS3172 driver of a P/390, IBM Open Systems Adapter (OSA) "LCS" (LAN Channel Station)
    TUN/TAP Driver
    3310, 3370, 9332, 9335, 9336, 0671 FBA direct access storage devices Disk file
    2305, 2311, 2314, 3330, 3340, 3350, 3375, 3380, 3390, 9345 CKD direct access storage devices Disk file
    2703 Communication Line TCP Socket


    Arguments required for each device type

    Local non-SNA 3270 devices

    There are no required arguments for this particular device type, but there are however several optional arguments which are discussed below.

    To use this device, a tn3270 client must connect to the host machine via the port number specified on the CNSLPORT statement. A valid tn3270 device type, such as IBM-3278, must be used.

    If your tn3270 client software allows you to specify a device type suffix (e.g. IBM-3278@001F ), then you can use the suffix to connect to that specific device number, if eligible. If no suffix is specified, then your client will be connected to the first available 3270 device for which it is eligible, if any.

    If you specify a specific terminal device address (via the device type suffix of your tn3270 client software), then you must be eligible to connect at that device address or your connection is immediately rejected; an alternative terminal device for which you might be eligible is not automatically selected instead.

    Optional arguments:

    groupname

    If a terminal group name is given on the device statement, a device type suffix with this group name can be used to indicate that a device in this group is to be used. If a group name is specified as a terminal type suffix (e.g. IBM-3278@GROUPNAME ) and there are no devices defined for that group (or there are no more available devices remaining in that group), then the connection is rejected. If no group name is specified as a terminal type suffix, then the connection will only be eligible for any terminal devices which do not have a group name specified on their device statements. The terminal group name, if specified, should obviously not be a hexadecimal number.

    ipaddr [ mask ]

    The optional IP address and optional subnet mask specify the ip address(es) of which client(s) are allowed to connect at the device address identified by the device statement on which they appear. This provides an alternative and/or additional means of specifying to which device(s) a client tn3270 session may, or should, connect.

    If the IP address of the tn3270 client trying to connect, when 'and'ed with the optional subnet mask (which defaults to 255.255.255.255 if not specified), matches the IP address entered on the device statement, then the client is eligible to connect at that device address. Otherwise the client is ineligible to connect at that address and then next available device, if any, for which the client is eligible to connect (if any) is selected instead.

    If no permissible terminal devices remain (i.e. terminal devices for which the client is eligible to connect), or there are no more available terminal devices remaining, then the client connection is rejected.

    The optional IP address and subnet mask may also be specified in conjunction with the previously mentioned terminal group argument, but the terminal group argument, if specified, must be specified ahead of (i.e. before) the optional ip address and subnet mask arguments. To specify an IP address and subnet mask without also specifying a terminal group, simply use '*' as the group name instead.

    If an IP address / subnet mask are not specified, then any client tn3270 session is allowed to connect to the device (provided they are also a member of the specified terminal group, if any).

    The terminal group name argument, if specified, always takes precedence over any optional ip address and subnet mask which may also be specified.

    To summarize, the device number suffix always takes precedence over any group name which may also be specified, and any group name, if specified, always takes precedence over any ip address / subnet mask value which may also be specified.


    Integrated 3270 console device

    The integrated 3270 (SYSG) console is similar to a local non-SNA 3270 device, except that it is not addressed by subchannel number and it is supported only by certain system control programs. The SYSG console is defined like a 3270 device except that the device type is SYSG and the device number is ignored. Only one SYSG console can be defined in a configuration.

    Use tn3270 client software to connect to the SYSG console device via the port number specified on the CNSLPORT statement, just as you would connect to a regular local non-SNA 3270 device.

    The SYSG console configuration statement recognizes optional arguments which specify group name and IP address in the same way as previously described for a local non-SNA 3270 device. These optional arguments provide a means to ensure that a given tn3270 client can connect directly to the SYSG console. If the group name and IP address arguments are not specified, then the SYSG console is considered to be a member of the general pool of devices eligible for connection to any incoming tn3270 client.


    Integrated Console printer-keyboard devices

    There is one optional argument which is the command prefix for sending input to the device. The default command prefix is '/'.

    Note: There is no restriction on the character you can select. If you select a command character that is the first character of a panel command, you will not be able to use that command.

    To send a logon command to a 1052-C or 3215-C enter /logon on the Hercules console.

    All integrated devices must use a different command prefix.


    Console printer-keyboard devices

    There are no required arguments for this particular device type, but there are however several optional arguments discussed below.

    To use this device, a telnet client must connect to the host machine via the port number specified on the CNSLPORT statement.

    If your telnet client software allows you to specify a device type suffix (for example: ansi@0009 ), then you can use that suffix to specify the specific 1052 or 3215 device to which you wish to connect. If you do not specify a suffix in your telnet client software (or your software does not allow it), then your client will be connected to the first available 1052 or 3215 device for which it is eligible.

    An optional noprompt argument may be specified on the device statement to cause suppression of the "Enter input for console device nnnn" prompt message which is otherwise normally issued to the device whenever the system is awaiting input on that device.

    Additionally, a terminal group name, ip address and subnet mask may all also be optionally specified in the exact same manner as discussed in the previous Local non-SNA 3270 devices section with the exception that the "noprompt" option, if specified, must precede the other arguments.


    Card reader devices

    The argument specifies a list of file names containing card images. Additional arguments may be specified after the file names:

    sockdev

    indicates the card reader is a socket device wherein the filename is actually a socket specification instead of a device filename. When used, there must only be one filename specified in the form: port or host:port or sockpath/sockname. The device then accepts remote connections on the given TCP/IP port or Unix Domain Socket, and reads data from the socket instead of from a device file. This allows automatic remote submission of card reader data. See the Hercules Socket Reader page for more details.

    eof

    specifies that unit exception status is presented after reading the last card in the file. This option is persistent, and will remain in effect until the reader is reinitialized with the intrq option.

    intrq

    specifies that unit check status with intervention required sense bytes is presented after reading the last card in the file. This option is persistent, and will remain in effect until the reader is reinitialized with the eof option.

    multifile

    specifies, when multiple input files are entered, to automatically open the next input file and continue reading whenever EOF is encountered on a given file. If not specified, then reading stops once EOF is reached on a given file and an attention interrupt is then required to open and begin reading the next file.

    ebcdic

    specifies that the file contains fixed length 80-byte EBCDIC records with no line-end delimiters.

    ascii

    specifies that the file contains variable length lines of ASCII characters delimited by LF (line feed) sequences or CRLF (carraige return line feed) sequences at the end of each line.

    If neither EBCDIC nor ASCII is specified, then the device handler attempts to detect the format of the card image file when the device is first accessed. Auto-detection is not supported for socket devices, and the default is ASCII if sockdev is specified.

    trunc

    specifies, for ASCII files, that lines longer than 80 characters are truncated instead of producing a unit check error.

    autopad

    specifies, for EBCDIC files, that the file is automatically padded to a multiple of 80 bytes if necessary.


    Card punch devices

    The argument specifies the name of a file to which the punched output will be written. Additional arguments may be specified after the file name:

    ascii

    specifies that the file will be written as variable length lines of ASCII characters delimited by line feeds or carriage return line feed sequences at the end of each line. Trailing blanks are removed from each line. If the ascii argument is not specified, the file is written as fixed length 80-byte EBCDIC records with no line-end delimiters.

    crlf

    specifies, for ASCII files, that carriage return line feed sequences are written at the end of each line. If the crlf argument is not specified, then line-feeds only are written at the end of each line.

    noclear

    specifies that the output file will not be cleared to zero bytes when it is opened. If the noclear argument is not specified, then any previous content of the file is destroyed when the file is opened for output.


    Line printer devices

    The argument specifies the name of a file to which the printer output will be written. The output is written in the form of variable length lines of ASCII characters delimited by line feeds or by carriage return line feed sequences. Trailing blanks are removed from each line. Carriage control characters are translated to blank lines or ASCII form feed characters. If the file exists it will be overwritten.

    Additional arguments may be specified after the file name:

    sockdev

    indicates the line printer is a socket device wherein the filename is actually a socket specification instead of a device filename. When used, there must only be one filename specified in the form: port or host:port. The device then accepts remote connections on the given TCP/IP port, and writes data to the socket instead of to a device file. This allows automatic remote spooling of line printer data. The sockdev option is mutually exclusive with all other printer options (e.g. crlf, etc) and must be specified alone.

    crlf

    specifies, for ASCII files, that carriage return line feed sequences are written at the end of each line. If the crlf argument is not specified, then line-feeds only are written at the end of each line.

    noclear

    specifies that the output file will not be cleared to zero bytes when it is opened. If the noclear argument is not specified, then any previous content of the file is destroyed when the file is opened for output.

    If the filename begins with the vertical bar '|' pipe character, then it is removed and the remainder of the filename is interpreted as a command line (the name of a program or batch file followed by any necessary arguments) to which to "pipe" the printer output to. This is known as the "print-to-pipe" feature. All printer output is then sent to the piped program's stdin input, and all of the piped program's stdout and stderr output is piped back to Hercules for displaying on the hardware console.

    If the "print-to-pipe" command line contains arguments, then quotes must be placed around the entire filename string including the vertical bar, for example:

        000E 1403 "|/usr/bin/lpr -Phplj" crlf          (for Unix)
        000E 1403 "|c:\utils\pr -s -PLPT1:" crlf       (for Windows)
        
    The above example uses the pr program downloaded from http://www.atnetsend.net/computing/

    If the "print-to-pipe" command line itself contains quotes, then the command line must be enclosed in apostrophes instead of quotes, for example:

        000E 1403 '|"c:\Program Files\My Utils\pr" -s -PLPT1:' crlf
        

    Tim Pinkawa has an example which shows how the print-to-pipe feature can be used to create output in PDF format: http://www.timpinkawa.net/hercules/prtspool.html


    Emulated tape devices

    Five types of tape emulation are supported (see further below).

    The only required parameter is the device filename. All other parameters are optional and must follow the filename. Use '*' (asterisk) for the filename to specify an empty (unmounted) tape drive. The specified file, if other than '*', must exist.

    Additionally, if the file name starts with the '@' character (at sign), the file really describes a list of tape emulation files to be loaded in succession.

    The syntax of each line is identical to the information that can be specified after the device type when the options are specified directly after the device type in the configuration file.

    If the emulation file filename in the file list is the '*' (asterisk) character, then this specifies a set of options to be applied to all additional emulation files specified in the file list.

    Parameters are appended in succession. In all cases, if the same parameter is specified more than once, the last instance takes precedence.

    Therefore, it is possible to specify a set of parameters in the base configuration file, another set on a '*' line, and another set for each individual line. Parameters are then appended in that order: options specified on the base device statement itself first, followed by those options specified on the '*' statement, and finally those specified on each individual file list statement last. A SCSI tape device should not be given in a file list.

    Refer to the distributed source-code's "README.TAPE" document for additional information regarding system and application programming for tape devices and instructions regarding use of the emulated ACF (Automatic Cartridge Feeder) and AUTOMOUNT features for virtual (non-SCSI) tape devices.

    SCSI tape drives

    These are real tape drives attached to the host machine via a SCSI interface. Hercules emulation always makes the drive appear as a channel attached device such as 3420 or 3480, although the underlying physical drive may be any type of SCSI attached tape drive, including 4mm or 8mm DAT, DLT, SCSI attached 3480/3490 cartridge drives, and SCSI attached 3420 open reel tape drives.

    Host-attached SCSI tapes are read and written using variable length EBCDIC blocks and filemarks exactly like a mainframe tape volume, and as a result can be freely used/exchanged on either (i.e. SCSI tapes created on a real mainframe can subsequently be read by Hercules just fine, and a SCSI tape created by Hercules can be subsequently read on a mainframe just fine, thus providing a convenient means of exchanging data between the two).

    If you plan on using SCSI tapes with Hercules you might also be interested in the AUTO_SCSI_MOUNT configuration option.

    The only required device statement parameter for SCSI attached tape drives is the name of the device as it is known by the host operating system, usually  "/dev/nst0(for Linux or Windows) or  "\\.\Tape0"   (for Windows only), where '0' means tape drive number 0 (your first or only host-attached SCSI tape drive), '1' means your second host-attached SCSI tape drive, etc.

    Depending on what actual model of SCSI tape drive you actually have and how it behaves, you may need to specify one or more additional optional parameters for Hercules to provide proper emulation of the desired device type. For example: a Quantum 'DLT' (Digital Linear Tape) SCSI tape drive does not return nor use a block-id format compatible with 3480/3490 drives (it instead uses a full 32-bit block-id just like the model 3590 does). It also does not support the Erase Gap CCW at all.

    Thus, in order to use, for example, a Quantum DLT drive with Hercules, you MUST specify some special additional options to prevent the Erase Gap command from being issued to the drive as well as to inform Hercules that the drive uses 32-bit block-ids.

    Please note that the below options define how the actual SCSI hardware device behaves, which is completely different from the way the emulated device will appear to behave to your guest. That is to say, if you define your tape drive to Hercules as a 3480 device, then Hercules will perform 3480 device type emulation such that the device appears to your guest o/s as if it were a 3480 device. If the actual SCSI device behaves as a 3590 device however (perhaps using/returning 32-bit block-ids instead of the expected 22-bit format block-ids that 3480's use), then you MUST specify the --blkid-32 special option on your Hercules device statement so that Hercules's emulation logic can know that it needs to translate 22-bit block-ids to 32-bit ones before sending them to the actual SCSI hardware (and vice versa: to translate 32-bit block-ids from the actual SCSI drive into 22-bit format block-ids that your guest expects from a 3480 device).

    Special options for SCSI tapes

    As explained just above, certain model SCSI tape drives such as the Quantum DLT series may require special handling in order to provide the desired proper device type emulation. These special options are:

    --no-erg

    This option is intended to prevent issuance of the Erase Gap command to those SCSI tape drives which do not support it (such as the Quantum DLT series). It causes Hercules's device emulation logic to ignore any Erase Gap commands issued to the drive and to return immediate 'success' instead.

    This option should only be used (specified) for drives such as the Quantum, which support switching from read mode to write mode in the middle of a data stream without the need of an intervening Erase Gap command. Specifying it for any other model SCSI drive may cause incorrect functioning as a result of the Erase Gap command not being issued to the actual SCSI hardware.

    Check the manufacturer information for your particular model of SCSI-attached tape drive (and/or use Fish's "ftape" Windows utility) to determine whether or not this option is needed for your particular drive.

    --blkid-32

    This option indicates that your SCSI-attached tape drive only supports 32-bit block-ids (as used by 3590 drives) and not the 22-bit format used by 3480/3490 drives. You should only specify this option if you intend to define the drive as a model 3480 or 3490 device, and then only if your actual SCSI drive uses 32-bit block-ids of course. If you define your Hercules tape drive as a model 3590 device however, then this option is of course not needed since model 3590 drives are already presumed to use 32-bit block-ids.

    Specifying this option on a 3480/3490 device statement will cause Hercules device emulation logic to automatically translate the actual SCSI tape drive's 32-bit block-id into 22-bit format before returning it back to the guest operating system (since that is the format it expects it to be in for a model 3480/3490 drive), and to translate the guest's 22-bit format block-id into 32-bit format before sending it to the actual SCSI hardware (since that is the format that the actual hardware requires it to be in).

    --blkid-22

    The complete opposite of the above --blkid-32 option.


    Optical Media Attach (OMA) virtual files

    These are read-only files which usually reside on CDROM. OMA virtual tapes consist of one CDROM file corresponding to each physical file of the emulated tape. An ASCII text file called the tape descriptor file (TDF) specifies the names of the files which make up the virtual tape. The argument specifies the name of the tape descriptor file (for example /cdrom/tapes/uaa196.tdf)

    Each file on the virtual tape can be in one of three formats:

    TEXT

    TEXT files consist of variable length ASCII records delimited by carriage return line feed sequences at the end of each record. Each record is translated to EBCDIC and presented to the program as one physical tape block.

    FIXED nnnnn

    FIXED files consist of fixed length EBCDIC blocks of the specified length (nnnnn)

    HEADERS

    HEADERS files consist of variable length EBCDIC blocks. Each block is preceded by a 12-byte header.

    If you have any IBM manuals in Bookmanager format on CDROM, you can see some examples of TDF files in the \TAPES directory on the CDROM.


    AWSTAPE virtual files

    These contain a complete tape in one file. AWSTAPE files consist of variable length EBCDIC blocks. Each block is preceded by a 6-byte header. Filemarks are represented by a 6-byte header with no data. This is the same format as is used by the P/390. The argument specifies the location of the AWSTAPE file (for example ickdsf.aws)


    FakeTape virtual files

    These contain a complete tape in one file. FakeTape files consist of variable length EBCDIC blocks. Each block is preceded by a 12-ASCII-hex-character header. Filemarks are represented by a 12-character header with no data. The FakeTape format is used by the Flex-ES system from Fundamental Software Inc (FSI). The argument specifies the location of the FakeTape file (for example ickdsf.fkt). Note: "FLEX-ES" and "FakeTape" are trademarks of Fundamental Software, Inc.


    HET virtual files    (Hercules Emulated Tape)

    These contain a complete tape in one file and have the same structure as the AWSTAPE format with the added ability to have compressed data. The first argument specifies the location of the HET file. The filename must end with ".het" to be recognized by Hercules as an HET file. (for example 023178.het)

    Additional arguments that allow you to control various HET settings are:

    AWSTAPE

    The AWSTAPE argument causes HET files to be written in AWSTAPE format. This basically, disables the additional features provided by the HET format.

    COMPRESS=n
    IDRC=n

    COMPRESS and IDRC control whether compression should be used when writing to HET files. The value n  can be 1 to turn on compression (the default) or 0 to turn it off. IDRC is currently a synonym for COMPRESS, but may be used in the future to control other emulated tape drive features.

    METHOD=n

    The METHOD option allows you to specify which compression method to use. You may specify 1 for ZLIB compression or 2 for BZIP2 compression. The default is 1.

    LEVEL=n

    The LEVEL option controls the level of compression. It ranges from 1 for fastest compression to 9  for best compression. The default is 4.

    CHUNKSIZE=nnnnn

    The CHUNKSIZE option allows you to create HET files that contain different chunk sizes. The AWSTAPE (and therefore the HET) format allows each tape block to be logically broken up into smaller chunks. For instance, if your S/3x0 application creates tapes with a block size of 27998, those blocks would be broken down into nnnnn  sized chunks. The range is from 4096 to 65535, the latter being the default. Decreasing the value from its default may reduce compression performance. For compatability with AWSTAPE files created by the P/390, specify AWSTAPE with CHUNKSIZE=4096.


    The following parameters apply to AWS, HET and FakeTape emulation files:

    MAXSIZE=n  |  MAXSIZEK=n  |  MAXSIZEM=n

    Specifies the maximum size (in bytes, Kilobytes or Megabytes) that the emulated file is allowed to grow to. Specifying zero for this parameter means "unlimited" (i.e. there is no limit).

    EOTMARGIN=n

    Specifies the number of bytes remaining before reaching maxsize at which point the tape device will signal the presence of the "End of Tape" marker (reflector), thus allowing the program to switch to the next tape.

    READONLY=n

    Specifies whether the tape is mounted read-only (without a write ring or with the cartridge protect switch set to "write protect"). A parameter of 1 means read-only; a parameter of 0 means read-write. If READONLY=1, RO or NORING is not specified, the default is READONLY=0. Note that READONLY=0 does not override the host system file permission settings for the underlying AWS or HET file. If the AWS or HET file is marked read-only, the tape will be mounted read-only despite specification of READONLY=0.

    RO
    NORING

    Specifies that the tape is mounted read-only (without a write ring or with the cartridge protect switch set to "write protect"). RO and NORING are equivalent to READONLY=1.

    RW
    RING

    Specifies that the tape should be mounted read-write, if possible. RW and RING are equivalent to READONLY=0. This is the default if RO, NORING or READONLY=1 is not specified. Note that RW and RING do not override the host system file permission settings for the underlying AWS or HET file. If the AWS or HET file is marked read-only, the tape will be mounted read-only despite specification of RW or RING.

    DEONIRQ=n

    Specifies whether a device end is presented if intervention is required during tape motion. A parameter of 1 selects this option; a parameter of 0 turns it off.

    NOAUTOMOUNT

    Indicates support for guest-initiated automatic tape volume mounting is to always be disabled for this tape device.

    Automatic guest tape-mount support is automatically globally enabled for all virtual (non-SCSI) tape devices by default whenever an allowable automount directory is defined via the AUTOMOUNT configuration file statement or the automount panel command. The NOAUTOMOUNT option allows you to specifically disable such support for a given device.

    The automount feature enables software running in guest operating systems to automatically mount, unmount and/or query for themselves the host "virtual tape volume" filename mounted on a tape drive, via the use of special CCW opcodes (0x4B Set Diagnose and 0xE4 Sense Id) without any intervention on the part of the Hercules operator. An example of such a program for DOS/VSE called TMOUNT is provided in the util subdirectory of the distributed source code.

    This is a sticky option. When specified, automount support for the device remains disabled until the option is specifically removed via a devinit command without the option specified. This means if NOAUTOMOUNT is enabled for a device while global automount functionality is currently disabled (because no AUTOMOUNT statement was specified at Hercules startup), then automount functionality remains disabled for the device even should global automount functionality be later manually enabled via an automount panel command.

    When the 0x4B Set Diagnose CCW is used to auto-mount a virtual tape volume onto a given tape drive, an absolute (fully-qualified) pathname should normally always be specified, but need not be if a path relative to the currently defined "default allowable" automount directory is used instead.

    The default allowable automount directory is always the first "allowable" directory that was defined, or else the current directory if no allowable directories were specifically defined. (There is always a default allowable directory whenever any allowable or unallowable automount directories are defined.)

    Fully-resolved, absolute-full-path filenames are defined as being those which, for Windows, have a ':' (colon) in the second position or, for other host operating systems (e.g. Linux), have a '/' (slash) in the first position. Paths which start with a '.' (period) are considered relative paths and will always be appended to the currently defined default allowable automount directory, before being resolved into fully-qualified paths by the host system. (I.e. only fully-resolved absolute pathnames are used in the performance of the actual automatic tape volume mount.)

    For example, if more than one allowable automount directory is defined and the volume wishing to be mounted happens to reside in the second one, then a fully-qualified absolute pathname should of course be specified (or else one that is relative to the default directory which happens to resolve to the desired file).

    All attempts to automount host files in a "disallowed" directory or any of its subdirectories will be rejected. Similarly any attempt to automount a file which is not within any "allowable" directory or subdirectory will be rejected. An error message is always issued in such cases. A message is also issued whenever a successful mount or unmount is performed.

    A sample guest automount program called TMOUNT for the DOS/VSE operating system is provided in the util subdirectory of the distributed source code.


    Channel-to-channel adapters

    The first argument defines the emulation type, and the remaining arguments depend on the chosen emulation type. If the first argument is not a recognized emulation type, then the driver will operate as in Hercules Version 1, using Willem Konynenberg's vmnet package, as described in Axel Schwarzer's CTCA 3088 document.

    The following are the emulation types currently supported:

    CTCI     (Channel to Channel link to TCP/IP stack)

    A point-to-point IP connection with the TCP/IP stack of the driving system on which Hercules is running. See the Hercules TCP/IP page for details.

    (Note: The CTCI protocol is only for the Linux version of Hercules. For Windows, use the below CTCI protocol instead).


    CTCI     (Channel to Channel link to Win32 TCP/IP stack)

    A modified Win32 version of the CTCI protocol for the Windows crowd. Note that the protocol name (CTCI) is the same, even though the actual implementation is very different. See Fish's CTCI-W32 page for further details and information.

    Required for both Linux and Windows:

    guestip

    specifies the IP address of the guest operating system running under Hercules.

    hostip

    specifies the IP address of the host (Linux or Windows) side of the point-to-point link. This may or may not be the same as your system's regular IP address. For Windows, if the host system is configured with DHCP, this should instead be the MAC address of the Ethernet adapter you wish to use to have Hercules communicate with the outside world.

    Optional for Windows:

    If these arguments are specified, they must precede the required arguments.

    -k  kernel-capture-buffer-size
    -i  tuntap32-i/o-buffer-size

    See Fish's CTCI-W32 page for further details and information.

    Optional for both Linux and Windows:

    If these arguments are specified, they must precede the required arguments:

    -n name    or   --dev name

    specifies the name of the tunnel device to use.

    The default for Linux is /dev/net/tun (which is correct for version 2.4 and above of the Linux kernel).

    For Windows, specify the IP address or MAC address of the real Windows adapter to emulate the virtual guest's adapter on. The default is the first adapter found according to Windows' adapter binding order, which may not be the one you want if you have multiple adapters.

    See question #22 of the CTCI-W32 F.A.Q. (Frequently Asked Questions) document for more information about adapter binding order, and the CTCI-W32 Configuration web page for general information regarding CTCI-W32 configuration.

    -m MAC address    or   --mac MAC address

    where 'MAC address' is the optional hardware address for the virtual interface in the format: hh:hh:hh:hh:hh:hh. The default value is '00:00:5E:nn:nn:nn' where the :nn:nn:nn portion is constructed from the last 3 octets of the specified guestip.

    -s netmask

    where netmask is the netmask to use for the automatically added point-to-point route in standard dotted internet noitation (e.g. 255.255.255.0)

    -d    or   --debug

    specifies that debugging output is to be produced on the Hercules control panel. This should normally be left unspecified.


    CTCT     (Channel to Channel Emulation via TCP connection)

    An emulated CTCA to another Hercules system. Four arguments are required:

    lport

    specifies the local TCP port. This is the TCP port that Hercules will listen on for this CTCA.

    rhost

    specifies the remote host. This is the name or IP address of the remote system that Hercules is running on, not the name or IP address of the OS running on that copy of Hercules.

    rport

    specifies the remote TCP port. The rport parameter on this system must match the lport parameter on the remote system, and vice versa.

    bufsize

    specifies the buffer size for the link. If this link is used for IP traffic, this parameter should be more than the MTU of the interface definition in the OS.

    Note: CTCT currently only supports IP traffic, so it cannot be used to transport NJE, SNA, PVM, etc. type payloads. This may change in the future.


    LCS     (LAN Channel Station Emulation)

    An emulated Lan Channel Station Adapter. This emulation mode appears to the operating system running in the Hercules machine as an IBM 8232 LCS device, an IBM 2216 router, a 3172 running ICP (Interconnect Communications Program), the LCS3172 driver of a P/390, or an IBM Open Systems Adapter.

    Rather than a point-to-point link, this emulation creates a virtual ethernet adapter through which the guest operating system running in the Hercules machine can communicate. As such, this mode is not limited to TCP/IP traffic, but in fact will handle any ethernet frame.

    The configuration statement for LCS is as follows:

    NOTE: There are no required parameters for the LCS emulation, however there are several options that can be specified on the config statement:

    NOTE: On the MAC OS X Platform, the long option format (--xxx) is not supported. Only the short option format (-x : one dash, one letter) should be used.

    -n devname    or   --dev devname

    where devname is:

    (Linux/Unix)

    the name of the TUN/TAP special character device, normally /dev/net/tun.

    (Windows)

    is either the IP or MAC address of the driving systems network card. TunTap32 will automatically select the first network card it finds if this option is omitted, this may not be desirable for some users.

    -o filename    or   --oat filename

    where filename specifies the filename of the Address Translation file. If this option is specified, the optional --mac and guestip entries are ignored in preference to statements in the OAT. (See further below for the syntax of the OAT file)

    -m MAC Address    or   --mac MAC address

    where MAC Address is the optional hardware address of the interface in the format: hh:hh:hh:hh:hh:hh. If you use the --oat option, do not specify an address here.

    guestip

    is an optional IP address of the Hercules (guest OS) side. Note: This is only used to establish a point-to-point routing table entry on driving system. If you use the --oat option, do not specify an address here.

    OAT file syntax

    The syntax for the Address Translation file is as follows:

    
    *********************************************************
    * Dev   Mode  Port  Entry specific information...       *
    *********************************************************
    
      0400  IP    00    PRI  172.021.003.032
      0402  IP    00    SEC  172.021.003.033
      0404  IP    00    NO   172.021.003.038
      0406  IP    01    NO   172.021.002.016
      040E  SNA   00
    
    HWADD  00  02:00:FE:DF:00:42
    HWADD  01  02:00:FE:DF:00:43
    
    ROUTE  00  172.021.003.032  255.255.255.224
    

    where:

    Dev
    is the base device address

    Mode
    is the operation mode: IP or SNA.

    Note:  the SNA operation mode is NOT currently implemented.

    Port
    is the virtual (relative) adapter number.

    For IP modes, the entry specific information is as follows:

    PRI | SEC | NO

    specifies where a packet with an unknown IP address is forwarded to. PRI is the primary default entry, SEC specifies the entry to use when the primary is not available, and NO specifies that this is not a default entry.

    nnn.nnn.nnn.nnn

    specifies the home IP address

    When the operation mode is IP, specify only the even (read) device number dev. The odd (write) address will be create automatically.

    Note:  the SNA operation mode is NOT currently implemented.

    Additionally, two other statements may be included in the address translation file. The HWADD and ROUTE statements:

    HWADD  pp  hh:hh:hh:hh:hh:hh

    Use the HWADD to specify a hardware (MAC) address for a virtual adapter. The first parameter after HWADD specifies with relative adapter for which the address is applied.

    ROUTE  pp  nnn.nnn.nnn.nnn  ...

    The ROUTE statement is included for convenience. This allows the hercifc program to create a network route for this specified virtual adapter. Please note that it is not necessary to include point-to-point routes for each IP address in the table. This is done automatically by the emulation module.

    The read/write devices can be swapped by coding the odd address of the even-odd pair in the OAT

    Up to 4 virtual (relative) adapters 00-03 are currently supported.

    If no Address Translation file is specified, the emulation module will create the following:

    • An ethernet adapter (port 0) for TCP/IP traffic only.
    • Two device addresses will be defined (devnum and devnum + 1).


    CKD DASD devices

    The argument specifies the name of a file containing the disk CKD DASD image or the INET address of a Hercules shared device server.

    The file consists of a 512-byte device header record followed by fixed length track images. The length of each track image depends on the emulated device type, and is always rounded up to the next multiple of 512 bytes.

    Volumes larger than 2GB (for example, the 3390 model 3) can be supported by spreading the data across more than one file. Each file contains a whole number of cylinders. The first file (which contains cylinders 0-2518 in the case of a 3390) usually has _1 as the last two characters of its name. The ckddasd driver allocates the remaining files by replacing the last character of the file name by the characters 2, 3, etc.

    Note:  When CKD DASD images are spread across multiple files, you must specify only the first file name (the file with suffix _1) in the configuration statement.

    If your operating system supports large file sizes (or 64-bit offsets) then volumes larger than 2G can be kept in a single file.

    Alternatively, the argument may specify the name of a file containing a compressed CKD DASD image. The CKD driver will automatically detect whether the file contains a regular CKD image or a compressed CKD image.

    Refer to "Creating an empty DASD volume" in the "Creating, formatting, and loading DASD volumes" section of the Creating DASD web page for information on using the 'dasdinit' command/utility to create compressed dasd files. Refer to the Compressed Dasd Emulation page for details on the actual CCKD emulation itself and additional information on the CCKD initialization/tuning control file statement.

    If you specify an INET address, the format is:

    ip-name-or-addr:port:devnum

    ip-name-or-addr specifies the internet name or address where the Hercules shared device server is running.

    port specifies the port number the shared device server is listening on. If omitted, the default is 3990.

    devnum specifies the device number on the shared device server. If omitted, the default is the current device number.

    In addition to the above, some additional optional arguments are also supported.

    sf=shadow-file-name

    A shadow file contains all the changes made to the emulated dasd since it was created, until the next shadow file is created. The moment of the shadow file's creation can be thought of as a snapshot of the current emulated dasd at that time, because if the shadow file is later removed, then the emulated dasd reverts back to the state it was at when the snapshot was taken.

    Using shadow files, you can keep the base file on a read-only device such as cdrom, or change the base file attributes to read-only, ensuring that this file can never be corrupted.

    Hercules console commands are provided to add a new shadow file, remove the current shadow file (with or without backward merge), compress the current shadow file, and display the shadow file status and statistics

    For detailed information regarding shadow files and their use, please see the "Shadow Files" section of the Compressed Dasd Emulation web page.

    [no]syncio

    syncio enables possible 'synchronous' i/o. This is a dasd i/o feature wherein guest i/o requests are completed "synchronously" during the actual emulated execution of the SIO/SSCH (start-i/o / start subchannel) instruction rather than being deferred and executed asynchronously in a separate device i/o thread.

    Only i/o which are known to be able to be completed without actually needing to perform any actual host i/o are completed synchronously (e.g. whenever the data being requested is found to already be in cache). If the requested data is not found in the cache, then an actual host i/o will need to be done and the request is passed to a device i/o thread to be completed asyncronously instead.

    syncio is the default for ckd. syncio statistics may be displayed via the Hercules syncio panel command.

    syncio may be abbreviated as syio

    readonly

    readonly returns "write inhibited" sense when a write is attempted. Note that not all of the sense bits may be getting set absolutely correctly however. (Some people have reported getting different error messages under Hercules than a real machine, but it really hasn't been an issue for a while now.)

    readonly may be abbreviated as rdonly or ro

    fakewrite

    fakewrite is a kludge for the readonly sense problem mentioned above. Here the disk is not intended to be updated (MVS updates the DSCB last referenced field for a readonly file) and any writes appear to be successful even though nothing actually gets written.

    fakewrite may be abbreviated as fakewrt or fw

    [no]lazywrite
    [no]fulltrackio

    These options have been deprecated. They are still accepted, but they do absolutely nothing.

    fulltrackio may be abbreviated as fulltrkio or ftio

    cu=type

    Specifies the type of control unit to which this device is attached. The use of this parameter does not necessarily imply that all functions of the specified control unit are emulated, its only purpose is to force a particular control unit type to be indicated in the data returned by SENSE ID and similar CCW's.

    The default value depends on the device type:

    Device typeDefault CU type
    23112841
    23142314
    3330 3340
    3350 3375
    3380
    3880
    33903990
    93459343

    Other values which may be specified are: 3990-3 and 3990-6.

    Normally the default value is appropriate and this parameter need not be specified.


    FBA DASD devices

    The argument specifies the name of a file which contains the FBA DASD image or the INET address of a Hercules shared device server.

    The file consists of fixed length 512-byte records, each of which represents one physical block of the emulated disk.

    To allow access to a minidisk within a full-pack FBA DASD image file, two additional arguments may be specified after the file name:

    origin

    specifies the relative block number within the DASD image file at which the minidisk begins. The number must be less than the number of blocks in the file. The default origin is zero.

    numblks

    specifies the number of 512-byte blocks in the minidisk. This number must not exceed the number of blocks in the file minus the origin. If omitted, or if specified as an asterisk, then the minidisk continues to the end of the DASD image file.

    If you specify an INET address the format is:

    ip-name-or-addr:port:devnum

    ip-name-or-addr specifies the internet name or address where the Hercules shared device server is running.

    port specifies the port number the shared device server is listening on. If omitted, the default is 3990.

    devnum specifies the device number on the shared device server. If omitted, the default is the current device number.

    In addition to the above, some additional optional arguments are also supported.

    sf=shadow-file-name

    The handling of shadow files for FBA devices is identical as that for CKD devices. Please refer to the preceding CKD section for information regarding use of the sf= shadow file option.

    [no]syncio

    syncio enables possible 'synchronous' i/o and is explained in detail in the preceding CKD dasd section. Note however that syncio is currently disabled by default for FBA dasd due to an as yet unresolved problem and must therefore be specifically enabled if you wish to use it for FBA dasd.

    syncio may be abbreviated as syio


    Communication Line

    ( Preliminary 2703 BSC Support )

    Describes a BSC emulation line entry to either link 2 Hercules engines or a custom made program emulating a 2780, 3780 or 3x74, or a custom made program interfacing to a real BSC line.

    The communication is emulated over a TCP connection. All bytes are transfered as-is (except for doubling DLE in transparent mode) just like it would over a real BSC link. Emulated EIA (DCD, DTR, CTS, etc..) or X.21/V.11 leads (C, T, etc..) are treated differently depending on the DIAL option selected.

    The line emulates a point-to-point BSC link. There is no point-to-multipoint handling.

    The following options define the line emulation behaviour:

    DIAL=IN | OUT | INOUT | NO

    Specifies call direction (if any). If DIAL=NO is specified, the TCP outgoing connection is attempted as soon as an 'ENABLE' CCW is executed. Also, in this mode, an incoming connection will always be accepted. If DIAL=IN|INOUT is specified, a TCP incoming call is accepted ONLY if an 'ENABLE' CCW is currently executing on the device. If DIAL=OUT, the 'ENABLE' CCW is rejected. When DIAL=IN|INOUT is specified, a DIAL CCW allows the application to establish a TCP connection to a specific host. For other DIAL values, the DIAL CCW is rejected.

    lhost=hostname | ip address | *

    Specifies which IP address to listen on. This also conditions the network interface from which incoming calls will be accepted. Specifying '*' means all incoming TCP calls are accepted, regardless of the destination IP address or call origin. This is the default value. Specifying a specific IP address when DIAL=OUT is specified has no effect.

    lport=service name | port number

    Specifies the TCP port for which to listen to incoming TCP calls. This value is mandatory for DIAL=IN|INOUT|NO. It is ignored for DIAL=OUT.

    rhost=hostname | ip address
    rport=service name | port number

    Specifies the remote host and port to which to direct a TCP connection on a DIAL=NO line when an 'ENABLE' CCW is executed. This option is mandatory when DIAL=NO is specified. It is ignored for other DIAL values.

    The following options are tuning options. In most cases, using the default values give the best results

    rto=0 | -1 | nnn | 3000

    Specifies the number of milliseconds before terminating a read on a timeout, when no read termination control character is received. Specifying 0 means the READ ends immediately. -1 specifies there is no timeout.

    pto=0 | -1 | nnn | 3000

    Specifies the number of milliseconds before terminating a POLL on a timeout, when no ACK or NACK sequence is received. Specifying 0 means the POLL ends immediately. -1 specifies there is no timeout.

    eto=0 | -1 | nnn | 10000

    Specifies the number of milliseconds before terminating an ENABLE operation on a timeout. the timeout applies when DIAL=NO|IN|INOUT is specified, the outgoing TCP call fails (DIAL=NO) and there is no previously or currently established TCP connection for this line. When DIAL=NO is specified, the timeout defaults to 10 seconds. For DIAL=IN|INOUT, the timeout defaults to -1.


    If you have a question about Hercules, see the Hercules Frequently-Asked Questions page.


    back

    Last updated $Date: 2009-12-25 12:57:55 -0600 (Fri, 25 Dec 2009) $ $Revision: 5566 $

    hercules-3.07/html/hercfaq.html000644 000765 000765 00000114265 11344073445 020224 0ustar00jmaynardjmaynard000000 000000 Hercules Version 3: Frequently-Asked Questions

    Hercules Version 3: Frequently-Asked Questions


    1.01What is Hercules?
    1.02So what exactly does that mean?
    1.03Is it functional enough to run production work?
    1.04What are the licensing restrictions for Hercules?
     
    2.01Can it run z/OS, z/VM, z/VSE?
    2.02What operating systems can I run legally?
    2.03What other programs will run under Hercules?
    2.04Where can I obtain OS/360 ?
    2.05Where can I obtain MVS ?
    2.06Where can I obtain VM/370 ?
    2.07Where can I obtain DOS/VS ?
    2.08Where can I obtain Linux/390 ?
    2.09Where can I find documentation?
     
    3.01What PC hardware do I need to run Hercules?
    3.02What sort of MIPS rate can I expect?
    3.03What PC software do I need to run Hercules?
    3.04What software do I need to build Hercules?
    3.05Why do I get an unexpected fixed-point divide exception (program check 0009 or abend 0C9) on a CVB instruction?
    3.06Can Hercules be ported to run on other platforms?
     
    4.01How can I create a virtual DASD volume?
    4.02Can I read a tape which was created on a mainframe?
    4.03Can I attach a PC tape drive to Hercules?
    4.04Can I process mainframe tapes with Hercules?
    4.05Can I create Assembler programs without a mainframe?
     
    5.01What architectural features are implemented?
     
    6.01Who are the Herculeans?
     
    7.01Where can I obtain technical support?


    1.01 What is Hercules?

    Hercules is a software implementation of the System/370, ESA/390 and z/Architecture mainframe architectures. Hercules runs under Windows and Linux, as well as under various other Unix or Unix-like systems on Intel Pentium and other hardware platforms including Alpha, Sparc, and Mac.

    1.02 So what exactly does that mean?

    It means that your PC can emulate an IBM mainframe processor. The mainframe can range from a System/360 to a z10 - running in "S/370" mode, "ESA/390" mode, or "z/Architecture" mode.

    Hercules executes S/370, ESA/390, and z/Architecture instructions and channel programs. It emulates mainframe I/O devices by using PC devices. For example, 3390 DASD devices are emulated by large files on your hard disk, and local 3270 screens are emulated by tn3270 sessions. (Note: Not all 370 and 390 features have been implemented in Hercules. See the list of particulars later in this document. Also, certain non-standard models, 360/20s, and the 360/67 virtual memory mode are not emulated.)

    Hercules implements only the raw S/370, ESA/390, and z/Architecture instruction set; it does not provide any operating system facilities. This means that you need to provide an operating system or standalone program which Hercules can load from an emulated disk or tape device. You will have to write the operating system or standalone program yourself, unless you can manage to obtain a license from IBM to run one of their operating systems on your PC, or use IBM programs and operating systems which have been placed in the public domain.

    1.03 Is it functional enough to run production work?

    Hercules has never claimed to be a production-capable system. It was always meant to be a system programmer's toy. Having said that, it's now become good enough to run a wide range of software without problems, and there are reports that it has been used to run production work in some parts of the world.

    1.04 What are the licensing restrictions for Hercules?

    Hercules is a copyright work which has been made generally available, subject to the terms of the Q Public License. In essence this allows free use and distribution of the program for personal and commercial use. You may not distribute modified copies of the program, but you may distribute your own patches along with the program, provided that you also grant the maintainer permission to include those patches in future versions of the program. You may not copy any portion of the source code for use in any other program.

    Hercules is not, repeat, not GPL software! The GNU General Public License is a Unix/Linux software licensing agreement, which we, the authors, will not participate in. We believe that the QPL, which has been certified as compliant with the Open Source Definition, provides the benefits and protections of open source for both users and developers, without the political baggage that has come to be associated with the GPL.


    2.01 Can it run z/OS, z/VM, z/VSE?

    Yes. Hercules is a software implementation of z/Architecture, and so it is capable of running z/OS, z/VM, and z/VSE. Hercules also implements ESA/390 (including SIE) and so it can run OS/390, VM/ESA, and VSE/ESA, as well as older versions of these operating systems such as MVS/ESA, MVS/XA, VM/SP, VSE/SP, etc.

    But (and this is a big but), these operating systems are all IBM Licensed Program Products, whose conditions of use generally restrict their usage to specific IBM machine serial numbers. So you cannot just copy these systems from work and run them on your PC.

    2.02 What operating systems can I run legally?

    Most 3rd party operating systems like Linux/390, z/Linux and TELPAR are covered under their own free license and can therefore run under Hercules without any legal problems.

    OS/360 (PCP, MFT and MVT) is in the public domain, as far as we know. The status of OSes for which IBM did not charge a license fee is somewhat murky; these include MVS 3.8, VM/370 release 6, and DOS/VS release 34.

    The legal status outside the USA, where something like public domain or software without copyright doesn't exist, is "copyrighted software provided at no charge". It is a known fact that vendors like Amdahl, Hitachi, Nixdorf and others modified those operating systems, and distributed them as their own OS for their own hardware, without asking IBM for permission. But law had been changed over that time, so its not clear if the same legal status applies in your country right now.

    Rick Fochtman managed to obtain a letter from IBM that he is allowed to distribute OS/360. Try to ask your salesdroid for a similar letter for VM/370, MVS 3.8j or DOS/VS next time he wants to sell you a major upgrade.

    OS/390, z/OS, and other ESA or z/Architecture operating systems are definitely licensed to a particular machine. Therefore, in practice you cannot run any classic ESA or z/Architecture operating system on your PC unless you can obtain a license from IBM allowing you to do so. It is believed that there are, however, four ways you could run z/OS, z/VM, z/VSE, OS/390, VM/ESA, or VSE/ESA under Hercules using currently available licenses:

    1. Running under Linux on the Pentium processor of a P/390 which is licensed to run the OS.
    2. Running under Linux/390 on a mainframe which is licensed to run the OS.
    3. Running under the terms of a disaster recovery provision of the OS license (but I really don't recommend depending on Hercules to be your disaster recovery solution!).
    4. Using the IBM OS/390 or z/OS DemoPkg, which is available only to IBM employees and IBM Business Partners.

    2.03 What other programs will run under Hercules?

    Any program which uses the S/370, ESA/390, or z/Architecture instruction set, as implemented in Hercules. Some special utilities in the form of standalone programs are known to run well. I can particularly recommend Jan Jaeger's excellent standalone editor (ZZSA) which is included in the Hercules distribution, or it can be downloaded from http://www.cbttape.org/~jjaeger; I use it regularly to look at DASD while debugging an OS installation, which is just what it's designed to do. Note: ZZSA runs in ESA/390 mode. See Jan Jaeger's website for more information and special logon procedures.

    2.04 Where can I obtain OS/360 ?

    1. Rick Fochtman's OS/360 archive CD is now obtainable by download from these locations:

    2. If you are interested in obtaining a copy of the CD itself, contact Rick Fochtman at rfochtman@ync.net.

    3. Alternatively, you can download the OS/360 Y2K Starter package from http://open360.copyleft.de/OS360/Download.html which contains a full featured MVT system on a 3330 image, with some minimal documentation. The configuration is that of a 370/158 with 4 megabytes of main storage, running OS/MVT Release 21.0. The same site also offers a MVTDBL volume and a Builder package for those who like to participate in OS/360 nucleus hacking.

    4. Jay Maynard's "IBM Public Domain Software Collection" at http://www.ibiblio.org/jmaynard/ contains copies of the OS/360 Release 21.8 distribution tapes.

    2.05 Where can I obtain MVS 3.8 ?

    The Original MVS 3.8 distribution as it was first used came from

    who advise using the mirrors at

    Several people have generated a functional MVS system from this archive :

    2.05 Where can I obtain VM/370 ?

    The VM/370 page at cbttape.org contains download links for the Andy Norrie VM 4-pack system and the Bob Abeles VM/370 R6 distribution.

    2.07 Where can I obtain DOS/VS ?

    I've put the DOS/VS r34 install tape on my site. It'll expand to a 21 MB AWSTAPE file, dosrel34.aws. You need the Coverletter to install it. Read the relevant postings of the Hercules mailing list first, as the install process is quite obscure.

    You can grab those files at :

    2.08 Where can I obtain Linux/390 ?

    The best starting point for information about Linux for S/390 and Linux for zSeries is http://www.linuxvm.org/

    2.09 Where can I find documentation?

    The Creating Hercules DASD document describes various methods of creating and loading virtual DASD volumes.

    I've produced a document describing how to build an OS/360 system on Hercules, called "OS/360 on Hercules". It can be found at

    This will build an MVT system without TCAM/TSO, but with two 3270 consoles. You will need Malcolm Beattie's "Guide to Using 3270 Consoles and Terminals for Hercules" with this MVT version.

    The N.U.D.E guides can be found at :

    IBM provides only current documentation, ...
    but many things haven't changed since 1964 :


    3.01 What PC hardware do I need to run Hercules?

    Classic IBM operating systems (OS/360, MVS 3.8, VM/370) are very light by today's standards and will run satisfactorily on a 300Mhz Pentium with as little as 32MB RAM.

    Anything more up-to-date, such as Linux/390 or OS/390, requires much more processing power. Hercules is CPU intensive, so you will want to use the fastest processor you can get. A 2GHz Pentium, preferably with hyperthreading, will probably provide acceptable performance for a light workload. If you can afford a multiprocessor system, so much the better. Hercules makes extensive use of multi-threading to overlap I/O with CPU activity, and to dispatch multiple emulated CPU's in parallel.

    For the latest 64-bit operating systems such as zLinux and z/OS, be aware that there is a performance penalty when Hercules emulates z/Architecture on a 32-bit processor such as the Pentium. If you are serious about running 64-bit then you will probably want to build Hercules for a 64-bit processor such as Alpha (DEC/Compaq/HP), AMD64 (AMD Opteron, Athlon-64, Turion 64), IA64 (Intel Itanium 2), together with a 64-bit version of Linux, or PPC (Power Mac G5) with OS X.

    Hercules does not depend on the Pentium architecture. I've built and run it successfully on a 500 MHz Alpha 21164, and others have run it on SPARC and S/390 (!) Linux systems. One guy has even run OS/360 under Hercules under Linux/390 under Hercules under Linux/390 under VM/ESA! The prize for the world's smallest mainframe probably goes to Ivan Warren, who claims to have run VM/370 under Hercules on an iPAQ 5450 handheld PDA.

    You should provide enough RAM to accommodate your S/390 real storage (main storage plus expanded storage) in addition to the normal requirements of your PC's operating system. For maximum throughput, you should set your main and expanded storage sizes high enough to eliminate S/390 paging. S/390 storage is allocated out of your PC's virtual storage.

    You also need enough hard disk space to accommodate the emulated DASD. A virtual "3330 model 1" disk drive will need about 100 megabytes of space for emulation (a 3330-11 will need about 200 megabytes). A 3380 "single density" model will need about 650MB, a 3390 model 2 needs about 2GB, and a 3390 model 3 needs about 3GB. If you use the compressed CKD DASD feature, these sizes will shrink dramatically, usually to about 20 to 30 percent of the original size.

    3.02 What sort of MIPS rate can I expect?

    Thanks to the cumulative work of many individuals, including Valery Pogonchenko, Juergen Dobrinski, Albert Louw, Gabor Hoffer, Jan Jaeger, Paul Leisy, Clem Clarke, and Greg Smith, the performance of Hercules today is vastly better than it was 5 years ago.

    Even on a Celeron 300 you should see an execution speed of 1 to 2 MIPS, which is enough to run OS/360 (MFT or MVT) or MVS 3.8 with a response time better than that of a 3033 from the 1970's. It's also fast enough to run VSE/ESA with an acceptable response time. On a more recent system with a 2GHz Pentium processor, you may see the system peak at around 30 MIPS which is enough to run Linux/390 or z/OS with a light workload.

    Performance on server class machines is now fairly respectable. For example, on a dual-core Intel Xeon with hyperthreading (4 CPUs) running at 3.46GHz, you might expect to see a sustained MIPS rate of 40 to 60 MIPS. A dual-processor quad-core Mac Pro (8 cores, 3 GHz) will sustain over 150 MIPS. For anyone who is prepared to spend a considerable amount of money on their Hercules system, there are reports that a sustained 300+ MIPS has been achieved on an Intel Core i7 processor running at 3.75GHz using all four cores plus hyperthreading (8 CPUs).

    Typical I/O rates of around 50 EXCP/second are reported on average hardware, with rates over 500/second achievable with hardware RAID.

    3.03 What PC software do I need to run Hercules?

    The following software platforms are supported:

  • Linux (kernel 2.4 or later)
  • Windows 98, Windows NT, Windows 2000, or Windows XP with Cygwin
  • Windows 98, Windows NT, Windows 2000, or Windows XP (without Cygwin)
  • Mac OS X 10.3 or later
  • Solaris 2.9 or later (Sparc or Intel)
  • FreeBSD

    You will also need tn3270 client software for the virtual 3270 console. The tn3270 client can run on the same machine as Hercules, or on any Unix or Windows box with a TCP/IP connection to the Hercules machine.

    The supported and recommended tn3270 clients for Hercules are:

    x3270 for Unix
    x3270 is included with most Linux distributions, or you can download it from http://x3270.bgp.nu/
    Vista tn3270 for Windows
    Vista tn3270 can be obtained from www.tombrennansoftware.com. The very modest license fee charged for this excellent 3270 emulator helps to support an independent software developer.
    Brown University tn3270 for Macintosh
    Brown University tn3270 is freely available. You can download it from http://www.brown.edu/Facilities/CIS/tn3270/. There is one setting that must be changed to use this program with some operating systems, especially MVS 3.8: Open a connection to Hercules, but before IPLing the system, go to the Session->Features menu and set "Change embedded nulls to blanks" to "No". Click on "OK". Now, click on File->Save default settings... to make the setting permanent.

    Other tn3270 clients, such as QWS3270, IBM Personal Communications, Attachmate Extra, or Dynacomm Elite should also work in most cases, but be aware that some tn3270 clients have bugs which make them unusable as OS/360 or MVS consoles.

    3.04 What software do I need to build Hercules?

    To build Hercules for Linux and other Unix-like environments (including Cygwin under Windows), you need to use the gcc compiler, version 2.95, or version 3.x or above. Note that gcc version 2.96 is not an official version and is not supported. You will also need a full set of GNU development tools, including recent versions of autoconf, automake, libiconv, make, perl, sed, and m4. Refer to the util/cvslvlck file in the Hercules distribution for details. Note that you will also need a reasonably powerful machine (Pentium 1GHz+) with ample RAM (at least 256Mb) because the compilation process is extremely resource hungry.

    To build Hercules for the Windows native environment (without Cygwin), you need to use the Microsoft C/C++ compiler (MSVC) version 13.x or later. This compiler is available for download from Microsoft as Visual C++ Toolkit 2003 (Version 13.x) or Microsoft Visual C++ 2005 Express (Version 14.x). You also need the current version of the Microsoft Platform SDK, which is also available for download from Microsoft. For further information, see Fish's MSVC Hercules Build page at http://www.softdevlabs.com/Hercules/hercules-msvc-build.html Alternatively, the Microsoft Visual Studio 7.0 and 8.0 products may be used. In addition, Hercules now also supports building with the Microsoft Visual Studio 9.0 product, or with Microsoft Visual C++ 2008 Express (Version 15.x) available for download from the Microsoft web-site.

    3.05 Why do I get an unexpected fixed-point divide exception (program check 0009 or abend 0C9) on a CVB instruction?

    You are using an old gcc compiler. See previous question for the required compiler level.

    3.06 Can Hercules be ported to run on other platforms?

    With the introduction of autotools, we do make efforts to ensure Hercules builds and run on several different operating system platforms (mostly Linux, Windows, MAC, Solaris, and FreeBSD right now), but we of course simply cannot guarantee that it will run on every operating system platform out there.

    If you want to make Hercules run on AS/400, OS/2, or whatever, then by all means go ahead. I welcome reports of any bugs or problems you find, but I probably won't fix problems if it means introducing platform-specific code, and I will not be able to test new releases against other platforms. Folks who have gotten it compiled on the BSDs report that the hardest part is removing the Linux-specific tape support.

    The Hercules code is not intended to be specific to Intel hardware, so if you find any issues or faults related to running on other hardware (SPARC, Alpha, PPC, ...) under Linux, then I'm likely to be receptive to fixing that sort of problem. Issues related to Unix variants are less likely to be fixed however.


    4.01 How can I create a virtual DASD volume?

    The Creating Hercules DASD document describes various methods of creating and loading virtual DASD volumes.

    4.02 Can I read a tape which was created on a mainframe?

    Yes, indirectly. The mainframe tape must be converted to AWSTAPE format and then downloaded to your PC. The tapeconv.jcl file in the Hercules directory contains a sample program which you can run under OS/390 on your mainframe system. It reads a file from tape and converts it to AWSTAPE format. Download the AWSTAPE file to your PC (making sure to choose binary format for the download), and then add the downloaded filename to the Hercules configuration file as a virtual tape device. You will then be able to read the tape file from the virtual tape drive located on your PC.

    Note: the "tapeconv" program will not correctly process input tapes whose block size exceeds 32760! One symptom of this may be the message " ADRY011E I/O ERROR - DEVICE NOT ATTACHED.0000,NA,00...00,0000" when attempting to restore from tape originally created using the default DF/DSS block size. The solution is to recreate the dump tape with DCB=BLKSIZE=32760.

    4.03 Can I attach a PC tape drive to Hercules?

    Yes. Hercules can read and write tapes on SCSI drives. I have tested this with 4mm DAT, QIC-1000, and 9-track drives.

    4.04 Can I process mainframe tapes with Hercules?

    Yes. It is possible to obtain 9-track open reel drives and 3480-type cartridge drives which attach to the SCSI bus. Hercules makes these appear to the operating system as channel-attached 3420 or 3480 devices, making it possible to read and write real mainframe tapes.

    4.05 Can I create Assembler programs without a mainframe?

    Yes. If you want to write Assembler (BAL) programs to run on Hercules, but you don't have access to a mainframe, then there are two interesting products which you can run on your PC to assemble programs:

    The "Tachyon 390 Cross Assembler" ( http://www.tachyonsoft.com/tachyon )
    With this assembler you can produce S/390-compatible object decks using your Linux or Windows PC. A high degree of HLASM compatibility, coupled with the ability to perform complex assemblies at lightning speed, make this a product which is well worth looking at. I have tried this assembler and it is truly amazing.
    The "Dignus Systems/C Compiler" ( http://www.dignus.com )
    This is a C compiler which runs under Windows or Linux and generates mainframe assembler code which you can then assemble using the Tachyon assembler.

    Sam Golob wrote a fascinating review of these two products in the September 1999 issue of NaSPA Technical Support magazine.


    5.01 What architectural features are implemented?

    The following standard features of ESA/390 have been implemented:

    • Address-Limit Checking
    • Commercial Instruction Set
    • Decimal Instructions
    • Hexadecimal Floating-Point Instructions
    • 24-bit and 31-bit addressing
    • Key-Controlled Protection
    • Page Protection
    • Low-Address Protection
    • Dynamic Address Translation
    • 370-XA Channel Subsystem
    • Channel Indirect Data Addressing
    • Program Controlled Interruption (PCI)
    • Channel Program Suspend/Resume
    • Dual Address Space
    • Access Register Mode
    • Home Space Mode
    • Branch and Save
    • Conditional Swapping
    • TOD Clock, Clock Comparator, and CPU Timer
    • MVCS/MVCP/MVCK/MVCSK/MVCDK instructions
    • TB/TPROT instructions
    • LURA/STURA instructions
    • BAKR/PC/PR/PT instructions
    • Linkage Stack
    • Compare and Form Codeword and Update Tree instructions

    The following optional features of ESA/390 have been implemented:

    • Access-List-Controlled Protection
    • Binary Floating-Point instructions
    • Branch and Set Authority
    • Broadcasted Purging
    • Checksum instruction
    • Compare and Move Extended instructions
    • Dynamic Reconfiguration
    • Expanded Storage
    • Fast Synchronous Data Mover Facility
    • Floating-Point-Support Extensions
    • Halfword-Immediate instructions
    • Branch-Relative instructions
    • Incorrect-Length-Indication Suppression
    • Interpretive Execution (SIE)
    • Move Inverse
    • Move Page (Facility 2)
    • MVS assists
    • Operational Extensions: Console Integration
    • Private Space
    • Set Address Space Control Fast
    • Service-call-logical-processor (SCLP) facility
    • Square Root
    • Storage-Protection Override
    • Storage Key assist
    • String instructions
    • Subspace Group
    • Compare Until Substring Equal
    • Concurrent Sense
    • Suppression on Protection with Virtual-Address enhancement
    • Extended TOD clock
    • Compression
    • Perform Locked Operation
    • Vector Facility
    • Multiple Controlled Data Space (VM dataspaces)
    • Extended Translation
    • Extended Translation Facility 2
    • Store System Information
    • Cancel I/O Facility
    • Program Event Recording
    • Guest PER enhancement

    The following optional features of z/Architecture have been implemented:

    • HFP Multiply-and-Add/Subtract Facility
    • Message Security Assist
    • Long-Displacement Facility
    • DAT-Enhancement Facility
    • Extended-Translation Facility 3
    • ASN-and-LX-Reuse Facility
    • List-Directed Initial Program Load
    • Modified CCW Indirect Data Addressing (MIDAW) Facility
    • Extended-Immediate Facility
    • Message-Security-Assist Extension 1
    • Message-Security-Assist Extension 2
    • DAT-Enhancement Facility 2
    • Store-Clock-Fast Facility
    • Store-Facility-List-Extended Facility
    • ETF2-Enhancement Facility
    • ETF3-Enhancement Facility
    • PER-3 Facility
    • TOD-Clock-Steering Facility
    • Conditional-Emergency-Signal and Sense-Running-Status Facility
    • Multiple Logical Channel Subsystems Facility
    • Floating-Point-Support Enhancement Facilities (FPR-GR-Loading, FPS-Sign-Handling, and DFP-Rounding)
    • Decimal Floating Point Facility
    • IEEE-Exception-Simulation Facility
    • Extract-CPU-Time Facility
    • Conditional-SSKE Facility
    • Compare-and-Swap-and-Store Facility
    • Execute-Extensions Facility
    • General-Instructions-Extension Facility
    • Move-with-Optional-Specifications Facility
    • Parsing-Enhancement Facility
    • Compare-and-Swap-and-Store Facility 2
    • Integrated 3270 (SYSG) Console
    • Configuration-Topology Facility
    • HFP-Unnormalized-Extensions Facility

    The following optional features of z/Architecture have not yet been implemented:

    • Enhanced-DAT Facility
    • PFPO Facility
    • Restore-Subchannel Facility
    • Integrated ASCII (SYSA) Console
    • Set-Program-Parameter Facility
    • CPU-Measurement Counter Facility
    • CPU-Measurement Sampling Facility

    The following standard feature has not yet been implemented:

    • Clear I/O (full functionality for S/370)

    The following optional features have been partially implemented:

    • Channel-Subsystem Call
    • VM/370 assists

    The following features are not yet implemented, either due to lack of documentation, limited host system capability, or lack of supporting hardware:

    • Asynchronous Data Mover Facility
    • Asynchronous Pageout Facility
    • Coupling Links
    • ESCON
    • FICON
    • MIF (Multiple Image Facility)
    • Extended Sorting
    • External Time Reference (Sysplex Timer)
    • ICRF (Cryptography)
    • Operational Extensions: Automatic Reconfiguration, Storage Reconfiguration, SCP-initiated Reset, Processor Availability
    • PR/SM
    • Program-Controlled re-IPL

    Hercules is compliant with IBM's ALS-1, ALS-2 and ALS-3 architectural level sets to the degree necessary to run all OS/390 versions through 2.10 and known versions of z/OS in both ARCHLVL 1 and ARCHLVL 2 mode, and Linux and z/VM in both ESA/390 and z/Architecture mode.


    6.01 Who are the Herculeans?

    The following people are among those who have contributed to this project, either as coders or as testers or both:

  • Roger Bowler (original author)
  • Jay Maynard (current maintainer)
  • Jan Jaeger
  • Volker Bandke
  • David Barth
  • Malcolm Beattie
  • Mario Bezzi
  • Mike Cairns
  • Marcin Cieslak
  • Clem Clarke
  • Vic Cross
  • Jacob Dekel
  • Guy Desbiens
  • Juergen Dobrinski
  • Fritz Elfert
  • Tomas Fott
  • Martin Gasparovic
  • Mark Gaubatz
  • Steve Gay
  • Peter Glanzmann
  • Roland Goetschi
  • Graham Goodwin
  • Paul Gorlinsky
  • Harold Grovesteen
  • Glen Herrmannsfeldt
  • Brandon Hill
  • Gabor Hoffer
  • Dan Horak
  • Soren Jorvang
  • Willem Konynenberg
  • John Kozak
  • Nobumichi Kozawa
  • Peter Kuschnerus
  • Paul Leisy
  • Kevin Leonard
  • Albert Louw
  • Peter Macdonald
  • Tomas Masek
  • Rick McKelvy
  • John McKown
  • Dave Morton
  • Christophe Nillon
  • Mike Noel
  • Andy Norrie
  • Dutch Owen
  • Max H. Parke
  • Reed H. Petty
  • Jim Pierson
  • Tim Pinkawa
  • Pasi Pirhonen
  • Valery Pogonchenko
  • Wolfhard Reimer
  • Emerson Santos
  • Jeff Savit
  • Axel Schwarzer
  • Paul Scott
  • Daniel Seagraves
  • Victor Shkamerda
  • Greg Smith
  • Enrico Sorichetti
  • John Summerfield
  • Mark Szlaga
  • Adam Thornton
  • Adrian Trenkwalder
  • "Fish" (David B. Trout)
  • Ronen Tzur
  • Bernard van der Helm
  • Ard van der Leeuw
  • Kris Van Hees
  • Kees Verruijt
  • Ivan Warren
  • Rod Zazubek
  • Bjoern A. Zeeb
  • Matt Zimmerman

    And thanks for support and encouragement from:

  • Tim Alpaerts
  • Bertus Bekker
  • Giorgio de Nunzio
  • Rick Fochtman
  • Alex Friis
  • Sam Golob
  • Achim Haag
  • Cory Hamasaki
  • Tony Harminc
  • Richard Higson
  • Jim Keohane
  • Sam Knutson
  • Mike Ross
  • Daniel Rudin
  • Rich Smrcina
  • Henk Stegeman
  • Mark S. Waterbury

    If anyone feels they have been unfairly omitted from either of these lists, please let me (Jay Maynard) know.


    7.01 Where can I obtain technical support?

    Please see our Technical Support web page.


    back

    Last updated $Date: 2010-03-03 08:14:26 -0600 (Wed, 03 Mar 2010) $ $Revision: 5645 $

    hercules-3.07/html/hercinst.html000644 000765 000765 00000075674 11345532661 020445 0ustar00jmaynardjmaynard000000 000000 Hercules Version 3: Installation and Operation

    Hercules Version 3: Installation and Operation


    Contents

    Installation Procedure

    Configuration Procedure

    Creating DASD volumes

    Operating Procedure

    Technical Support


    Installation Procedure

    Building from source - Windows (without Cygwin)

    For building the MSVC version of Hercules on Windows (a version of Hercules that does not require Cygwin), Fish has instructions on his "MSVC Hercules Build Instructions" web page at http://www.softdevlabs.com/Hercules/hercules-msvc-build.html.

    Building from source - Windows with Cygwin

    For building the Cygwin version of Hercules on Windows, Volker Bandke has instructions on his "Building Hercules for Windows" web page at http://www.bsp-gmbh.com/hercules/herc_w32_2.html.

    Building from source - Linux and Mac OS X

    1. Download the distribution file hercules-3.07.tar.gz
      Note: By downloading this file you agree to the terms of the Q Public Licence.

    2. Use these commands to unzip the distribution file:
      tar xvzf ../hercules-3.07.tar.gz
      cd hercules-3.07
    3. Verify you have all of the correct versions of all of the required packages installed:

      ./util/cvslvlck

    4. Configure Hercules for your system:

      ./configure

      By default, the configure script will attempt to guess appropriate compiler optimization flags for your system. If its guesses turn out to be wrong, you can disable all optimization by passing the --disable-optimization option to configure, or specify your own optimization flags with --enable-optimization=FLAGS

      For additional configuration options, run: ./configure --help

    5. Build the executables:

      make

    6. Install the programs: as root:

      make install

    Important: You must use at least version 2.95 of the gcc compiler and the glibc2 library. Refer to the Hercules Frequently-Asked Questions page for required compiler and other software levels.

    Installing prebuilt RPMs:

    1. Download the RPM file you want:
    2. Install the RPM:
      rpm -Uvh RPMfile

    This will leave the Hercules executables in /usr/bin and the dynamic libraries in /usr/lib and /usr/lib/hercules, where you can run them from anywhere. Sample configuration files will be placed in /etc/hercules, and the IPLable card deck for the ZZSA standalone utility will be placed in /var/share/hercules.

    Installing Debian packages:

    Debian packages are available for "woody" and later releases.

    • Using apt: apt-get install hercules
    • Manually with dpkg:
      1. Download a .deb package
      2. dpkg -i DEB

    Installing on Gentoo Linux:

    Hercules is installed like any other Gentoo package: do emerge --sync if you haven't done it lately, then emerge hercules.

    Do not try to override the optimization flags automatically selected by configure. Hercules stresses the gcc optimizer, and will break in subtle ways if the wrong optimization settings are used.

    Installing on Mac OS X:

    1. Download the compressed disk image: hercules-3.07-tiger.dmg, hercules-3.07-leopard.dmg, or hercules-3.07-snowleopard.dmg. This package is a universal binary and requires the OS X version in the name, either 10.4 (Tiger), 10.5 (Leopard), 10.6 (Snow Leopard) or later. The Leopard and Snow Leopard versions include native 64-bit host support, while the Tiger version does not. The Tiger and Leopard versions will run on Intel or PowerPC Macs, while the Snow Leopard version will only run on Intel, as with Snow Leopard itself.
    2. Mount the image by double-clicking on it in the Finder. Your web browser may have done that for you already.
    3. Installation and use instructions are in the file OS X ReadMe.rtf.
    4. If you want to use CTC networking on your Hercules system, you will need to install the supplied Tunnel driver.

    Installing on Windows (without Cygwin):

    1. Download the Windows 32-bit Installer package or the Windows 64-bit Installer package.
    2. Use the Windows Installer to install Hercules. The Windows Installer is included in Windows XP. It may already be on your older Windows system, depending on what other software you've installed. If it is, double-clicking on the Hercules package file will install Hercules. If not, you can download the Windows Installer for Windows NT and 2000 by following this link, or the Windows Installer for Windows 98 and ME by following this link.
    3. You will probably also want to install Fish's Hercules GUI for Windows. You can get it from http://www.softdevlabs.com/Hercules/hercgui-index.html.

    Installing on Windows with Cygwin:

    1. Hercules 3.07 is now supplied as prebuilt binaries only in a native Windows version. This version will work perfectly well under Cygwin, as well as native Windows, and does not require any specific version of the Cygwin libraries. Follow the instructions above to install the native Windows version.


    Configuration Procedure

    You will need to amend the configuration file hercules.cnf to reflect your device layout and intended mode of operation (S/370, ESA/390, or z/Architecture). See the Hercules Configuration File page for a complete description.


    Creating DASD volumes

    The Creating Hercules DASD page describes various methods of creating and loading virtual DASD volumes. The compressed CKD DASD support is described in this page.


    Operating Procedure

    Note: If you intend to run any licensed software on your PC using Hercules, it is your responsibility to ensure that you do not violate the software vendor's licensing terms.

    Starting Hercules

    To start Hercules enter this command at the Unix or Windows command prompt:

        hercules  [ -f filename ]
                  [ -d ]
                  [ -p dyndir ]  [[-l dynmod ] ... ]
                  [ > logfile ]
    

    where:

    filename

    is the name of the configuration file. The default, if none is specified, is hercules.cnf. The default may be overridden via the HERCULES_CNF environment variable.

    -d

    specifies that Hercules is to be run in 'daemon' mode, wherein it runs invisibly with no attached console.

    dyndir

    is the directory from which dynamic modules are to be loaded. The default depends on the host platform on which Hercules is being run. This option overrides the default.

    dynmod

    is the name of an additional dynamic module to be loaded at startup. More than one additional module may be specified, although each must be preceded with the -l option specifier.

    logfile

    is an optional log file which will receive a copy of all messages displayed on the control panel

    Next connect a tn3270 client to the console port (normally port 3270). The client will be connected to the first 3270 device address specified in the configuration file (this should be the master console address). If your master console is a 1052 or 3215, connect a telnet client instead of a tn3270 client.

    Now you can enter an ipl command from the control panel.



    Using the keyboard

    The main Hercules screen contains a scrollable list of messages with a command input area and system status line at the bottom of the screen.

    To scroll through the messages, use either the Page Up or Page Down keys, the Ctrl + Up Arrow or Ctrl + Down Arrow keys, or the Home or End and/or the Ctrl + Home or Ctrl + End keys.

    Important messages are highlighted in a different color (usually red) and are prevented from being scrolled off the screen for two minutes. If Extended Cursor handling is available then important messages currently at the top of the screen can be removed early by moving the cursor to the line containing the message and then pressing enter.

    Use the Insert key to switch between insert and overlay mode when typing in the command input area. Use the Home and End keys to move to the first or last character of the command you are typing, or the use the left/right arrow keys to move to a specific character. Use the Escape key to erase the input area.

    Pressing Escape when the command input area is already empty causes the screen to switch to the semi-graphical "New Panel" display mode, which shows the overall status of the system and devices.

    When in the semi-graphical "New Panel" display mode there is no command input area. Instead, single character "hot keys" are used to issue some of the more common functions such as starting or stopping the CPU. The hot-keys are those which are highlighted. Pressing the '?' key displays brief help information on how to use the semi-graphical panel.

    Normal cursor handling
    Key Action
    Esc Erases the contents of the command input area. If the command input area is already empty, switches to semi-graphical New Panel.
    Del Deletes the character at the cursor position.
    Backspace Erases the previous character.
    Insert Toggles between insert mode and overlay mode.
    Tab Attempts to complete the partial file name at the cursor position in the command input area. If more than one possible file exists, a list of matching file names is displayed.
    Home Moves the cursor to the start of the input in the command input area. If the command input area is empty, scrolls the message area to the top.
    End Moves the cursor to the end of the input in the command input area. If the command input area is empty, scrolls the message area to the bottom.
    Page Up Scrolls the message area up one screen.
    Page Down Scrolls the message area down one screen.
    Up arrow Recalls previous command into the input area.
    Down arrow Recalls next command into the input area.
    Right arrow Moves cursor to next character of input area.
    Left arrow Moves cursor to previous character of input area.
    Ctrl + Up arrow Scrolls the message area up one line.
    Ctrl + Down arrow Scrolls the message area down one line.
    Ctrl + Home Scrolls the message area to the top.
    Ctrl + End Scrolls the message area to the bottom.

    The following additional keyboard functions are effective when the Hercules Extended Cursor Handling feature (OPTION_EXTCURS) is activated at compile time. At present, this feature is activated on the Windows platform only.

    Extended cursor handling
    Key Action
    Alt + Up arrow Moves cursor up one row.
    Alt + Down arrow Moves cursor down one row.
    Alt + Right arrow Moves cursor right one column.
    Alt + Left arrow Moves cursor left one column.
    Tab If cursor is outside the command input area, moves cursor to the start of the input in the command input area. Otherwise behaves as described in previous table.
    Home If cursor is outside the command input area, moves cursor to the start of the input in the command input area. Otherwise behaves as described in previous table.
    End If cursor is outside the command input area, moves cursor to the end of the input in the command input area. Otherwise behaves as described in previous table.


    Panel commands

    The following is what is displayed on the Hercules harware console (HMC) in response to the '?' command being entered. Please note that it may not be completely accurate or up-to-date. Please enter the '?' command for yourself for a more complete, accurate and up-to-date list of supported panel commands.

    
      Command      Description... 
      -------      ----------------------------------------------- 
      ?            list all commands 
      help         command specific help
     
      *            (log comment to syslog)
     
      message      display message on console a la VM 
      msg          same as message 
      msgnoh       same as message - no header
     
      hst          history of commands 
      hao          Hercules Automatic Operator 
      log          direct log output 
      logopt       change log options 
      version      display version information
     
      quit         terminate the emulator 
      exit         (synonym for 'quit')
     
      cpu          define target cpu for panel display and commands
     
      start        start CPU (or printer device if argument given) 
      stop         stop CPU (or printer device if argument given)
     
      startall     start all CPU's 
      stopall      stop all CPU's
     
      cf           configure current CPU online or offline 
      cfall        configure all CPU's online or offline
     
      .reply       scp command 
      !message     scp priority messsage 
      ssd          Signal Shutdown
     
      ptt          display pthread trace
     
      i            generate I/O attention interrupt for device 
      ext          generate external interrupt 
      restart      generate restart interrupt 
      archmode     set architecture mode 
      loadparm     set IPL parameter
     
      ipl          IPL Normal from device xxxx 
      iplc         IPL Clear from device xxxx 
      sysreset     Issue SYSTEM Reset manual operation 
      sysclear     Issue SYSTEM Clear Reset manual operation 
      store        store CPU status at absolute zero
     
      psw          display or alter program status word 
      gpr          display or alter general purpose registers 
      fpr          display floating point registers 
      fpc          display floating point control register 
      cr           display or alter control registers 
      ar           display access registers 
      pr           display prefix register 
      timerint     display or set timers update interval 
      clocks       display tod clkc and cpu timer 
      ipending     display pending interrupts 
      ds           display subchannel 
      r            display or alter real storage 
      v            display or alter virtual storage 
      u            disassemble storage 
      devtmax      display or set max device threads 
      k            display cckd internal trace
     
      attach       configure device 
      detach       remove device 
      define       rename device 
      devinit      reinitialize device 
      devlist      list device or all devices
     
      qd           query dasd
     
      automount    show/update allowable tape automount directories
     
      scsimount    automatic SCSI tape mounts
     
      cd           change directory 
      pwd          print working directory 
      sh           shell command
     
      cache        cache command 
      cckd         cckd command 
      shrd         shrd command 
      conkpalv     display/alter console TCP keep-alive settings 
      quiet        toggle automatic refresh of panel display data
     
      t            instruction trace 
      t+           instruction trace on 
      t-           instruction trace off 
      t?           instruction trace query 
      s            instruction stepping 
      s+           instruction stepping on 
      s-           instruction stepping off 
      s?           instruction stepping query 
      b            set breakpoint 
      b+           set breakpoint 
      b-           delete breakpoint 
      g            turn off instruction stepping and start CPU
     
      ostailor     trace program interrupts 
      pgmtrace     trace program interrupts 
      savecore     save a core image to file 
      loadcore     load a core image file 
      loadtext     load a text deck file
     
      ldmod        load a module 
      rmmod        delete a module 
      lsmod        list dynamic modules 
      lsdep        list module dependencies
     
      iodelay      display or set I/O delay value 
      ctc          enable/disable CTC debugging 
      toddrag      display or set TOD clock drag factor 
      panrate      display or set rate at which console refreshes 
      msghld       display or set the timeout of held messages 
      syncio       display syncio devices statistics 
      maxrates     display maximum observed MIPS/SIOS rate for the
                   defined interval or define a new reporting interval
     
      defsym       Define symbol 
      script       Run a sequence of panel commands contained in a file 
      cscript      Cancels a running script thread
     
      evm          ECPS:VM Commands (Deprecated) 
      ecpsvm       ECPS:VM Commands
     
      aea          Display AEA tables 
      aia          Display AIA fields 
      tlb          Display TLB tables
     
      sizeof       Display size of structures
     
      suspend      Suspend hercules 
      resume       Resume hercules
     
      herclogo     Read a new hercules logo file
     
      traceopt     Instruction trace display options
     
      cmdtgt       Specify the command target
     
      herc         Hercules command
     
      scp          Send scp command
     
      pscp         Send prio message scp command
     
      sf+dev       add shadow file 
      sf-dev       delete shadow file 
      sfc          compress shadow files 
      sfk          check shadow files 
      sfd          display shadow file stats 
    
      t{+/-}dev    turn CCW tracing on/off 
      s{+/-}dev    turn CCW stepping on/off 
      t{+/-}CKD    turn CKD_KEY tracing on/off 
      f{+/-}adr    mark frames unusable/usable 
    
    

    The ipl command may also be used to perform a load from cdrom or server. For example if a standard SuSE S/390 Linux distribution CD is loaded and mounted on /cdrom for example, this cdrom may then be ipl-ed by: ipl /cdrom/suse.ins

    The attach and detach commands are used to dynamically add or remove devices from the configuration, and the define command can be used to alter the device number of an existing device.

    The devinit command can be used to reopen an existing device. The args (if specified) override the arguments specified in the configuration file for this device. The device type cannot be changed and must not be specified. This command can be used to rewind a tape, to mount a new tape or disk image file on an existing device, to load a new card deck into a reader, or to close and reopen a printer or punch device.

    In single-step mode, pressing the enter key will advance to the next instruction.

    There is also an alternate semi-graphical control panel. Press Esc to switch between the command line format and the semi-graphical format. Press ? to obtain help in either control panel.

    Some commands also offer additional help information regarding their syntax, etc. Enter  "help <command name>"   to display this additional help information. (Note: not every command supports help)

    When a command is prefixed with '-', the the command will not be redisplayed at the console. This can be used in scripts and is also used internally when commands are to be invoked without being redisplayed at the panel.


    The  hercules.rc  (run-commands)  file

    Hercules also supports the ability to automatically execute panel commands upon startup via the 'run-commands' file. If the run-commands file is found to exist when Hercules starts, each line contained within it is read and interpreted as a panel command exactly as if the command were entered from the HMC system console.

    The default filename for the run-commands file is "hercules.rc", but may be overridden by setting the "HERCULES_RC" environment variable to the desired filename.

    Except for the 'pause' command (see paragraph further below), each command read from the run-commands file is logged to the console preceded by a '> ' (greater-than sign) character so you can easily distinguish between panel commands entered from the keyboard from those entered via the .rc file.

    Lines starting with '#' are treated as "silent comments" and are thus not logged to the console. Line starting with '*' however are treated as "loud comments" and will be logged.

    In addition to being able to execute any valid panel command (including the 'sh' shell command) via the run-commands file, an additional 'pause nnn' command is supported in order to introduce a brief delay before reading and processing the next line in the file. The value nnn can be any number from 1 to 999 and specifies the number of seconds to delay before reading the next line. Creative use of the run-commands file can completely automate Hercules startup.


    The "Hercules Automatic Operator" (HAO) Facility

    The Hercules Automatic Operator (HAO) feature is a facility that allows one to automatically issue panel commands in response to certain messages being issued.

    To use the Hercules Automatic Operator facility, one first defines a "rule" consisting of a "target" and an associated "command". The "target" is just a regular expression pattern used to match against the text of the various messages that Hercules issues as it runs. Whenever a match is found, the rule "fires" and its associated command is automatically issued.

    The Hercules Automatic Operator facility is only for those messages issued by Hercules to its HMC (hardware console). It cannot be used for whatever messages the guest operating system may issue to any of its terminals. It is only a Hercules automatic operator and not a "VSE", "MVS", "VM", etc, automatic operator.

    Defining a Rule

    To define a HAO rule, enter the command:

       hao target
    

    to define the rule's "target" match pattern (a simple regular expression), followed by the command:

       hao command
    

    to define the rule's associated panel-command.

    The target pattern is a simple regular expression value as defined by whatever regular expression facility your host build platform happens to support. For Windows it must be a Perl Compatible Regular Expression (PCRE). For other supported build platforms it might be some other supported regular expression syntax. Check your host platform's programming documentation for further details.

    The associated command is whatever valid Hercules panel command you wish to issue in response to a message being issued that matches the given pattern target.

    Other commands and limitations

    To delete a fully or partially defined HAO rule, first use the 'hao list' command to list all of the defined (or partially defined) rules, and then use the 'hao del nnn' command to delete the specific rule identified by nnn. (All rules are assigned numbers as they are defined and are thus identified by their numeric value). Optionally, one may delete ALL defined or partially defined rules by issuing the command 'hao clear'.

    The current implementation limits the total number of defined rules to 64. If you need to define more than 64 rules you will either have to build Hercules for yourself (increasing the value of the HAO_MAXRULE constant in hao.c) or else beg one of the Hercules developers to please do it for you.

    Note that there is currently no way to define a command whose arguments vary based on actual message text. That is to say, there is currently no way to say

    "Reply with the command 'devinit cuu filename' in response to message text 'HHCXXnnnI Device cuu intervention required.' where cuu is whatever cuu was identified in the message."

    The HAO is not that sophisticated (yet). Only simple plain-text commands may be defined and issued. No automatic substitution is done based on message text (although normal 'DEFSYM' symbol substitution is supported however, as that is a normal panel-command feature supported separately from the HAO). This may possibly change in the future however, depending on user need/demand.

    All defined rules are checked for a match each time Hercules issues a message. There is no way to specify "stop processing subsequent rules". If a message is issued that matches two or more rules, each associated command is then issued in sequence. Thus the advice to choose your rules' target patterns carefully very much applies here.


    Technical Support

    For technical support, please see our Technical Support web page.


    back

    Last updated $Date: 2010-03-09 09:14:00 -0600 (Tue, 09 Mar 2010) $ $Revision: 5661 $

    hercules-3.07/html/herclic.html000644 000765 000765 00000011671 11143760535 020221 0ustar00jmaynardjmaynard000000 000000 Hercules: Q Public License

    THE Q PUBLIC LICENSE version 1.0


    Copyright (C) 1999 Trolltech AS, Norway.
    Everyone is permitted to copy and
    distribute this license document.

    The intent of this license is to establish freedom to share and change the software regulated by this license under the open source model.

    This license applies to any software containing a notice placed by the copyright holder saying that it may be distributed under the terms of the Q Public License version 1.0. Such software is herein referred to as the Software. This license covers modification and distribution of the Software, use of third-party application programs based on the Software, and development of free software which uses the Software.

    Granted Rights

    1. You are granted the non-exclusive rights set forth in this license provided you agree to and comply with any and all conditions in this license. Whole or partial distribution of the Software, or software items that link with the Software, in any form signifies acceptance of this license.

    2. You may copy and distribute the Software in unmodified form provided that the entire package, including - but not restricted to - copyright, trademark notices and disclaimers, as released by the initial developer of the Software, is distributed.

    3. You may make modifications to the Software and distribute your modifications, in a form that is separate from the Software, such as patches. The following restrictions apply to modifications:

    a. Modifications must not alter or remove any copyright notices in the Software.

    b. When modifications to the Software are released under this license, a non-exclusive royalty-free right is granted to the initial developer of the Software to distribute your modification in future versions of the Software provided such versions remain available under these terms in addition to any other license(s) of the initial developer.

    4. You may distribute machine-executable forms of the Software or machine-executable forms of modified versions of the Software, provided that you meet these restrictions:

    a. You must include this license document in the distribution.

    b. You must ensure that all recipients of the machine-executable forms are also able to receive the complete machine-readable source code to the distributed Software, including all modifications, without any charge beyond the costs of data transfer, and place prominent notices in the distribution explaining this.

    c. You must ensure that all modifications included in the machine-executable forms are available under the terms of this license.

    5. You may use the original or modified versions of the Software to compile, link and run application programs legally developed by you or by others.

    6. You may develop application programs, reusable components and other software items that link with the original or modified versions of the Software. These items, when distributed, are subject to the following requirements:

    a. You must ensure that all recipients of machine-executable forms of these items are also able to receive and use the complete machine-readable source code to the items without any charge beyond the costs of data transfer.

    b. You must explicitly license all recipients of your items to use and re-distribute original and modified versions of the items in both machine-executable and source code forms. The recipients must be able to do so without any charges whatsoever, and they must be able to re-distribute to anyone they choose.

    c. If the items are not available to the general public, and the initial developer of the Software requests a copy of the items, then you must supply one.

    Limitations of Liability

    In no event shall the initial developers or copyright holders be liable for any damages whatsoever, including - but not restricted to - lost revenue or profits or other direct, indirect, special, incidental or consequential damages, even if they have been advised of the possibility of such damages, except to the extent invariable law, if any, provides otherwise.

    No Warranty

    The Software and this license document are provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.

    Choice of Law

    This license is governed by the Laws of England.


    back

    Last updated 3 December 2000 hercules-3.07/html/hercload.html000644 000765 000765 00000054126 11143760535 020373 0ustar00jmaynardjmaynard000000 000000 Hercules Version 3: Creating DASD

    Hercules Version 3: Creating DASD

    This page describes various ways of creating and loading DASD volumes for use with Hercules.


    Contents

    Using pre-built DASD images

    Creating, formatting, and loading DASD volumes

    Building a DASD volume from unloaded PDS files

    Other DASD utilities


    Using pre-built DASD images

    IBM distributes pre-built OS/390 and z/OS systems on two different CD-ROM packages:

    The OS/390 and z/OS Application Development CD (ADCD)
    available only to members of IBM PartnerWorld for Developers, and
    The OS/390 and z/OS DemoPkg
    available only to IBM employees and qualified IBM Business Partners.

    Both of these packages contain pre-built DASD image files which simply need to be unzipped onto your hard drive. The unzipped images can be directly read by Hercules.

    Be aware, however, that you cannot use the ADCD images because the PartnerWorld scheme requires you to purchase or lease an IBM approved machine in order to obtain the ADCD, and the software on the ADCD is licensed for use only on the machine that it was shipped with. See http://www.ibm.com/servers/enable/site/zinfo/adcd.html. If you want Hercules to be an approved machine so that you can use the ADCD, then I suggest you lobby IBM Developer Relations at the address given on their web page.

    Different rules apply to the OS/390 and z/OS DemoPkg CD which is available only to IBM employees and business partners. If you fall into this category then you probably know what the rules are -- I don't :-(


    Creating, formatting, and loading DASD volumes

    Creating an empty DASD volume

    The dasdinit program must first be run from the Unix shell prompt to create a file containing an empty DASD volume.

    The format of the dasdinit command is:


    Hercules DASD image file creation program
    Version 3.06
    (c)Copyright 1999-2009 by Roger Bowler, Jan Jaeger, and others
    Builds an empty dasd image file:
    
      dasdinit [-options] filename devtype[-model] [volser] [size]
    
    where:
    
      -v         display version info and help
      -z         build compressed dasd image file using zlib
      -bz2       build compressed dasd image file using bzip2
      -0         build compressed dasd image file with no compression
      -lfs       build a large (uncompressed) dasd file (if supported)
      -a         build dasd image file that includes alternate cylinders
                 (option ignored if size is manually specified)
      -r         build 'raw' dasd image file  (no VOL1 or IPL track)
      -linux     null track images will look like linux dasdfmt'ed images
                 (3390 device type only)
    
      filename   name of dasd image file to be created
    
      devtype    CKD: 2305, 2311, 2314, 3330, 3340, 3350, 3375, 3380, 3390, 9345
                 FBA: 0671, 3310, 3370, 9313, 9332, 9335, 9336
    
      model      device model (implies size) (opt)
    
      volser     volume serial number (1-6 characters)
                 (specified only if '-r' option not used)
    
      size       number of CKD cylinders or 512-byte FBA sectors
                 (required if model not specified else optional)
    


    The current list of device types and models supported is:


                  CKD DEVICES
    
                                 alt
            devtype-model  cyls  cyls
    
            2311           [*]
            2311-1         200    2
    
            2314           [*]
            2314-1         200    3
    
            3330           [*]
            3330-1         404    7
            3330-2         808    7
            3330-11        808    7
    
            3340           [*]
            3340-1         348    1
            3340-35        348    1
            3340-2         696    2
            3340-70        696    2
    
            3350           [*]
            3350-1         555    5
    
            3375           [*]
            3375-1         959    1
    
            3380           [*]
            3380-1         885    1
            3380-A         885    1
            3380-B         885    1
            3380-D         885    1
            3380-J         885    1
            3380-2        1770    2
            3380-E        1770    2
            3380-3        2655    3
            3380-K        2655    3
            EMC3380K+     3339    3
            EMC3380K++    3993    3
    
            3390           [*]
            3390-1        1113    1
            3390-2        2226    1
            3390-3        3339    1
            3390-9       10017    3
            3390-27      32760    3
            3390-54      65520    3
    
            9345           [*]
            9345-1        1440    0
            9345-2        2156    0
    
    
                 FBA DEVICES
    
            devtype-model  blocks
    
            3310              [*]
            3310-1         125664
    
            3370              [*]
            3370-Al        558000
            3370-B1        558000
            3370-A2        712752
            3370-B2        712752
    
            9313              [*]
            9313-1         246240
    
            9332              [*]
            9332-200       360036
            9332-400       360036
            9332-600       554800
    
            9335              [*]
            9335-1         804714
    
            9336              [*]
            9336-10        920115
            9336-20       1672881
            9336-25       1672881
    
            0671-08        513072
            0671           574560
            0671-04        624456
    

    [*] size may be specified else size defaults to the first listed model.

    Volumes exceeding 2GB

    For CKD volumes which exceed 2GB, such as the 3390-3, and the -lfs parameter is not specified, the DASDINIT program will create multiple files by appending the characters _1, _2, _3 etc. to the file name specified on the command line. These characters are inserted before the first dot (.) after the last slash (/). If there is no dot, then the characters are appended to the end of the name. Each file contains a whole number of cylinders. Hercules CKD support recognizes the files as belonging to a single logical volume. Specify the full name of just the first file in the Hercules configuration file (e.g. "filename_1").

    The DASDINIT program cannot create FBA volumes exceeding 2GB unless the -lfs parameter is specified and large file size is supported on your platform..

    Examples

    To create a 3330 model 1 CKD volume consisting of 404 cylinders (plus 7 alternate cylinders too) with volume serial number WORK01 in a file called work01.151:

        dasdinit -a work01.151 3330-1 work01
    

    To create a compressed 3350 CKD volume consisting of 560 cylinders (555 cylinders plus the 5 alternate cylinders) with volume serial number SYSRES in a file called dosvs34.24f:

        dasdinit -a -bz2 dosvs34.24f 3350-1 sysres
    

    To create a 3370 FBA volume with only 100000 sectors (instead of the usual 558000 sectors) with volume serial number WORK02 in a file called mini.work02.140:

        dasdinit mini.work02.140 3370 work02 100000
    

    To create a 3390 model 3 (triple density) CKD volume of 3339 cylinders with volume serial number WORK03:

        dasdinit triple.a88 3390-3 work03
    

    Because this volume exceeds 2GB, DASDINIT will create two files with triple_1.a88 containing cylinders 0-2518 and triple_2.a88 containing cylinders 2519-3339. If you specify

        dasdinit -lfs triple.a88 3390-3 work03
    

    then DASDINIT will create a single file triple.a88 containing all the cylinders. Your platform must support large file size to specify the -lfs option.

    Formatting the empty DASD volume

    After creating a DASD volume you can format it with a program such as standalone IBCDASDI or ICKDSF.

    Here is an example of the IBCDASDI control statements required to initialize a 3330 volume:

    
    WORK01 JOB  'INITIALIZE 3330 WORK VOLUME'
           MSG   TODEV=1052,TOADDR=009
           DADEF TODEV=3330,TOADDR=151,IPL=NO,VOLID=WORK01,BYPASS=YES
           VLD   NEWVOLID=WORK01,OWNERID=HERCULES
           VTOCD STRTADR=1,EXTENT=5
           END
    

    To run IBCDASDI, place the above statements in a file called init3330.txt and start Hercules in S/370 mode with a configuration file containing these statements:

    
    CPUSERIAL 001234
    CPUMODEL 3145
    MAINSIZE 2
    CNSLPORT 1052
    ARCHMODE S/370
    0009   1052
    000A   1442    ibcdasdi.rdr
    000C   1442    init3330.txt
    0151   3330    work01.151
    

    After IPLing from card reader device 00A, connect a telnet client to port 1052, and press enter. At the IBCDASDI prompt, enter:

    input=1442 00c

    Loading the new DASD volume

    Next you need to create a full volume dump file on your mainframe and convert it to AWSTAPE format using the tapeconv.jcl job in the Hercules source directory. The AWSTAPE file can then be downloaded in binary format to your PC where it can be defined as a virtual tape drive in the Hercules configuration file.

    A standalone program can now be IPLed into Hercules to restore the volume image from the virtual tape onto the formatted virtual DASD volume.


    Building a DASD volume from unloaded PDS files

    The dasdload program can be run from the Unix shell prompt to create a new DASD image file and load it with data from unloaded PDS files.

    The format of the dasdload command is:

    dasdload [options] ctlfile outfile msglevel

    where

    [options]
    -z
    build compressed dasd image file using zlib
    -bz2
    build compressed dasd image file using bzip2
    -0
    build compressed dasd image file with no compression
    -lfs
    build a large dasd image file (can exceed 2G)
    -a
    build dasd image file that includes alternate cylinders
    ctlname
    is the name of the control file which specifies the datasets that are to be loaded onto the newly-created volume
    outfile
    is the name of the DASD image file to be created
    msglevel
    is a number from 0 to 5 which controls the level of detail of the messages issued during the load.

    Control file

    The control file required by the dasdload program is an ASCII text file consisting of a volume statement followed by one dataset statement for each dataset to be created.

    The format of the volume statement is:

    volser devtype[-model] [cyls [ipltext] ]

    where:

    volser
    is the volume serial number for the newly-created volume
    devtype
    is the emulated device type (2311, 2314, 3330, 3340, 3350, 3375, 3380, or 3390) for the new volume. FBA device types are not supported by the dasdload program. Model may be specified like dasdinit above.
    cyls
    is the size of the new volume in cylinders. If cyls is coded as * or as 0 or is omitted, then the default size for the device type and model is used. Cylinders is ignored for compressed devices.
    ipltext
    is an optional parameter specifying the name of a file containing the IPL text which will be written to the volume. The file must be in the form of an object deck containing fixed length 80-byte EBCDIC records in the same format as expected by IBCDASDI or ICKDSF.

    The format of a dataset statement is:

    dsname method units pri sec dir dsorg recfm lrecl blksize keylen

    where:

    dsname
    is the dataset name
    method
    is the dataset loading method which can be one of the following:
    XMIT filename
    the dataset is loaded from an unloaded PDS created by the TSO XMIT command
    SEQ filename
    the sequential dataset is loaded from a binary file. ascii/ebcdic translation is not currently supported. Also, the dsorg must either be PS or DA and recfm must either be F or FB.
    EMPTY
    the dataset is initialized with an end of file record (if DSORG is PS) or an empty PDS directory (if DSORG is PO)
    DIP
    the dataset is initialized with a LOGREC header record
    CVOL
    the dataset is initialized as an OS SYSCTLG containing the minimum entries needed to IPL an OS/360 system
    VTOC
    specifies the size and location of the VTOC. A dataset name must be coded on this statement, although it is not used. If no VTOC statement is present, the VTOC will be placed after the last dataset on the volume and the size of the VTOC will be the minimum number of tracks necessary.
    units
    is the space allocation units: TRK or CYL.
    pri
    is the space allocation primary quantity
    sec
    is the space allocation secondary quantity
    dir
    is the number of directory blocks
    dsorg
    is the dataset organization: PS, PO, DA, or IS,
    recfm
    is the record format: F, FB, FBS, V, VB, VBS, or U.
    lrecl
    is the logical record length
    blksize
    is the block size
    keylen
    is the key length

    All parameters except dsname and method are optional. Defaults of zero are supplied for DCB parameters. For datasets loaded with the XMIT method, the DCB parameters are taken from the unloaded PDS, and the minimum space allocation required to load the dataset is used unless a larger quantity is specified. If space allocation is omitted, the default is TRK 1 0 0. If CYL is specified without any primary quantity then the default space allocation is 1 cylinder or the minimum number of cylinders required to load the dataset, whichever is larger.

    Examples

    [1] To create a 2314 volume in a file called sysres.230 using the control file sysres.plf with message level 2:

    dasdload sysres.plf sysres.230 2

    An example control file is shown below:

    #
    # Pack layout file for MFT system residence volume
    #
    sysres 2314 * ieaipl00.rdr
    sys1.parmlib    xmit    /cdrom/os360/reslibs/parmlib.xmi
    sys1.imagelib   xmit    /cdrom/os360/reslibs/imagelib.xmi
    sysctlg         cvol    trk 1 0 0       ps f 256 256 8
    sysvtoc         vtoc    trk 5
    sys1.logrec     dip     trk 1 0 0
    sys1.nucleus    xmit    /cdrom/os360/reslibs/nucleus.xmi cyl
    sys1.svclib     xmit    /cdrom/os360/reslibs/svclib.xmi cyl
    sys1.sysjobqe   empty   cyl 2 0 0       da f 176 176 0
    sys1.dump       empty   cyl 10 0 0      ps u 0 3625 0
    

    [2] To create a compressed 3390-3 volume in a file called linux.500 containing a bootable linux system for linux/390 installation using the control file linux.prm:

    dasdload -z linux.prm linux.500

    An example control file is shown below:

    #
    # Build a bootable linux disk
    #   [Note: the dataset names (sys1.linux. ...) are hard-coded in
    #          linuxipl.obj and cannot be changed without rebuilding it]
    #
    linux  3390-3 * linuxipl.obj
    sys1.linux.parmfile    SEQ images/redhat.prm trk   1 0 0 ps fb 1024 1024
    sys1.linux.tapeipl.ikr SEQ images/kernel.img trk 200 0 0 ps fb 1024 1024
    sys1.linux.initrd      SEQ images/initrd.img trk 200 0 0 ps fb 1024 1024
    

    Fixing the XCTL tables in SVCLIB

    On an OS/360 system, the Open/Close/EOV modules in SYS1.SVCLIB have XCTL tables embedded within them. These tables contain TTRs pointing to other modules, and these TTRs need to be adjusted after loading SVCLIB to DASD. OS/360 provides a program called IEHIOSUP to perform this function, but the catch is that you can't run IEHIOSUP until you have the system up and running, and you can't IPL until you have fixed the XCTL tables. To solve this problem, Hercules provides a program called dasdisup which can be run from the Unix command line after running dasdload.

    The format of the dasdisup command is:

    dasdisup outfile [sf=shadow-file-name]

    where

    outfile
    is the name of the DASD image file to be updated
    shadow-file-name
    (optional) is the name of the associated shadow file as specified in the Hercules config file

    Note: do not use this procedure except on OS/360 IPL volumes; other operating systems do not have XCTL tables.


    Other DASD utilities

    These programs can be used to extract data from CKD DASD images by means of commands issued at the Unix shell prompt.

    DASDLS - List datasets on volume

    DASDLS, written by Malcolm Beattie, is a command to let you list the names of the datasets contained in disk images.

    The command format is:
    dasdls ckdfile [sf=shadow-file-name] ...
    where ckdfile is the name of a Unix file containing a CKD volume and shadow-file-name (optional) is the name of the associated shadow file.

    DASDCAT - Display PDS members

    DASDCAT, written by Malcolm Beattie, is a command to let you read datasets from disk images.

    The command format is:
    dasdcat -i ckdfile [sf=shadow-file-name] dsname1 dsname2 ... -i ckdfile2 dsname10 ...
    where ckdfile is the name of a Unix file containing a CKD volume, shadow-file-name (optional) is the name of the associated shadow file, and dsname can be a plain (non-partitioned) dataset name (which is currently not handled) or of the form pdsname/memname where memname can be:

    • PDS member name (automatically uppercased), optionally followed by ":" and flags "a" or "c".
      • "c" means (c)ard images and turns a PDS members with a block size that's a multiple of 80 into multiple newline separated lines of 72 characters with EBCDIC converted to ASCII and with sequence numbers chopped off.
      • "a" means (a)sciify the member (but don't chop off sequence numbers or do the card image thing).
    • ? (don't forget to quote it to avoid the shell globbing it) to list the names of all PDS members instead of outputting their contents.
    • * (again, quote it or backwhack it to avoid it being a glob) to output all members of the PDS instead of just a named one. This can optionally be followed with colon-then-flags, as above. Each member is preceded with a line "> Member: memname" and, if the "c" for card-images flags is used, each line of the members' contents is preceded with "| " to guarantee it can be distinguished from contents.
    Examples
    
    % dasdcat -i mvtres.350 sf= mvtres_1.350 'sys1.parmlib/?'
    ieabld00
    ieaige00
    ieaigg00
    ieaigg01
    iearsv00
    ikjprm00
    lnklst00
    presres
    smfdeflt
    % dasdcat -i mvtres.350 sys1.parmlib/smfdeflt:c
     OPT=2, SYSTEM,JOB AND STEP DATA COLLECTION
     EXT=YES, USER EXITS ARE TO BE TAKEN
     JWT=15, MAXIMUM CONTINUOUS WAIT TIME IS 15 MINS.PER STEP
     BUF=400, A MINIMUM 400 BYTE BUFFER IS DEFINED
     SID=6A, SYSTEM ID IS 6A
     MDL=65, MODEL IS MOD 65
     OPI=YES, PERMIT OPERATOR INTERVENTION
     MAN=ALL, RECORD USER AND SYSTEM RECORDS
     PRM=(,282,NL) SYS1.MAN ALLOCATED TO NON-LABELED TAPE
    % dasdcat -i mvtres.350 sys1.help/\*:c
    > Member ACCOUNT
    | )S SUBCOMMANDS -
    | ADD/A,CHANGE/C,DELETE/D,LIST/L,LISTIDS/LISTI,HELP/H,END
    | )F FUNCTION -
    | THE ACCOUNT COMMAND PROCESSOR INVOKES THE CONVERSATIONAL PROGRAMS
    ...
    > Member ALLOC
    | )F FUNCTION -
    | THE ALLOCATE COMMAND DYNAMICALLY DEFINES AND ALLOCATES A DATA SET
    | WITH OR WITHOUT AN ATTRIBUTE LIST OF DCB PARAMETERS
    | )X SYNTAX -
    | ALLOCATE DATASET('DSNAME'/*) FILE('DDNAME')
    ...
    

    DASDPDSU - Unload PDS members

    DASDPDSU is a command which unloads PDS members from a disk image and copies each member to a file memname.mac in the current working directory.

    The command format is:
    dasdpdsu ckdfile [sf=shadow-file-name] pdsname [ascii]
    where ckdfile is the name of a Unix file containing a CKD volume, shadow-file-name (optional) is the name of the associated shadow file, and pdsname is the name of a PDS on that volume. If the optional ascii keyword is specified, the members will be unloaded as ASCII variable length text files. Otherwise the members are unloaded as fixed length EBCDIC binary files.


    If you have a question about Hercules, see the Hercules Frequently-Asked Questions page.


    back

    Last updated $Date: 2009-01-23 07:25:01 -0600 (Fri, 23 Jan 2009) $ $Revision: 5127 $

    hercules-3.07/html/hercmsca.html000644 000765 000765 00000033403 11143760535 020372 0ustar00jmaynardjmaynard000000 000000 Hercules Version 3: System Messages: CA - Communication Adapter

    Hercules Version 3: System Messages: CA - Communication Adapter

    This page describes the Communication Adapter emulation messages for the Hercules S/370, ESA/390, and z/Architecture emulator.

    Messages

    HHCCA001I CCUU:Connect out to ipaddr:port failed during initial status : System Cause Text
    Explanation
    HERCULES attempted to make an outgoing TCP connection to ipaddr:port, but the system indicated that there was an error while processing the request.
    System Action
    The DIAL or ENABLE CCW that caused the connection attempt ends with Unit Check and Intervention Required. The reason for the failure is indicated in the System Cause Text field
    Operator Action
    None
    Programmer Action
    Correct the RHOST/RPORT configuration statements in the configuration file. If this message occured during a program initiated DIAL, correct the dial data.
    Module
    commadpt.c
    Function
    commadpt_connout

    HHCCA002I CCUU:Line Communication thread thread id started
    Explanation
    The thread responsible for asynchronous operations for the BSC emulated line CCUU has been started.
    System Action
    The system continues
    Operator Action
    None. This is an informational message
    Programmer Action
    None. This is an informational message
    Module
    commadpt.c
    Function
    commadpt_thread

    HHCCA003E CCUU:Cannot obtain socket for incoming calls : System Cause Text
    Explanation
    A system error occured while attempting to create a socket to listen for incoming calls.
    System Action
    The device creation is aborted.
    Operator Action
    None.
    Programmer Action
    Check the System Cause Text for any information relating to the host system. Notify support.
    Module
    commadpt.c
    Function
    commadpt_thread

    HHCCA004W CCUU:Waiting 5 seconds for port port to become available
    Explanation
    While attempting to reserve port port to listen to it, the system indicated the port was already being used.
    System Action
    The system waits 5 seconds and then retries the operation
    Operator Action
    Terminate the device if the port is in error
    Programmer Action
    Determine the program holding the specified port. If the port cannot be made available, use a different port.

    HHCCA005I CCUU:Listening on port port for incoming TCP connections
    Explanation
    The system is now listening on port port for incoming a tcp connection.
    System Action
    The system continues
    Operator Action
    None. This is an informational message
    Programmer Action
    None. This is an informational message

    HHCCA006T CCUU:Select failed : System Cause Text
    Explanation
    An error occured during a 'select' system call.
    System Action
    The BSC thread is terminated
    Operator Action
    None.
    Programmer Action
    Check the System Cause Text for any indication of where the error might come from. Notify Support.

    HHCCA007W CCUU:Outgoing call failed during ENABLE|DIAL command : System Cause Text
    Explanation
    The system reported that a previously initiated TCP connection could not be completed
    System Action
    The I/O operation responsible for the TCP outgoing connection is ended with Unit Check and Intervention Required.
    Operator Action
    If the error indicates that the error is temporary, retry the operation.
    Programmer Action
    Check that the destination for this line is correctly configured. If the operation was a DIAL attempt, check in the application configuration or operation data.

    HHCCA008I CCUU:cthread - Incoming Call
    Explanation
    The BSC thread has received an incoming call.
    System Action
    Depending on configuration and operational status, the call is either accepted or rejected. Eventually, an ongoign I/O operation may complete.
    Operator Action
    None. This is an informational message
    Programmer Action
    None. This is an informational message

    HHCCA009I CCUU:BSC utility thread terminated
    Explanation
    The BSC thread has ended
    System Action
    the system continue.
    Operator Action
    Refer to any previous error message if this message was not unexpected
    Programmer Action
    Refer to any previous error message if this message was not unexpected

    HHCCA010I CCUU:initialisation not performed
    Explanation
    The Device initialisation process has failed.
    System Action
    the system terminates or continues, depending on the reason for which the device was initialisation was initiated.
    Operator Action
    Refer to any previous error message
    Programmer Action
    Refer to any previous error message

    HHCCA011E CCUU:Error parsing Keyword
    Explanation
    The device keyword parser found an error while parsing a known keyword.
    System Action
    The system continues. The device initialisation routine turns on a NOGO flag.
    Operator Action
    for a runtime initialisation, correct the device initialisation parameters, otherwise notify the programmer.
    Programmer Action
    For an engine initialisation, correct the device configuration parameters in the configuration file.

    HHCCA012E CCUU:Unrecognized parameter Keyword
    Explanation
    The device keyword parser found an unknown keyword in the device parameter list.
    System Action
    The system continues. The device initialisation routine turns on a NOGO flag.
    Operator Action
    for a runtime initialisation, correct the device initialisation parameters, otherwise notify the programmer.
    Programmer Action
    For an engine initialisation, correct the device configuration parameters in the configuration file.

    HHCCA013E CCUU:Incorrect local port|remote port|local host|remote host specification value
    Explanation
    The device initialisation routine could not correctly parse a parameter value.
    System Action
    The system continues. The device initialisation routine turns on a NOGO flag.
    Operator Action
    for a runtime initialisation, correct the device initialisation parameters, otherwise notify the programmer.
    Programmer Action
    For an engine initialisation, correct the device configuration parameters in the configuration file.

    HHCCA014E CCUU:Incorrect switched/dial specification value; defaulting to DIAL=OUT
    Explanation
    The device initialisation routine found an incorrect DIAL value.
    System Action
    The system continues. The device initialisation routine turns on a NOGO flag.
    Operator Action
    for a runtime initialisation, correct the device initialisation parameters, otherwise notify the programmer.
    Programmer Action
    For an engine initialisation, correct the device configuration parameters in the configuration file.

    HHCCA015E CCUU:Missing parameter : DIAL=NO|IN|OUT|INOUT and LPORT|RPORT|LHOST|RHOST not specified
    Explanation
    The device initialisation routine found that a mandatory parameter was not provided for a specific DIAL Value.
    System Action
    The system continues. The device initialisation routine turns on a NOGO flag.
    Operator Action
    for a runtime initialisation, correct the device initialisation parameters, otherwise notify the programmer.
    Programmer Action
    For an engine initialisation, correct the device configuration parameters in the configuration file.
    Note
    For DIAL=NO , LPORT, RPORT and RHOST are needed
    For DIAL=IN , LPORT is required
    For DIAL=OUT None of LPORT,LHOST,RPORT,RHOST are required
    For DIAL=INOUT, LPORT is required

    HHCCA016W CCUU:Conflicting parameter : DIAL=NO|IN|OUT|INOUT and LPORT|RPORT|LHOST|RHOST=value specified
    Explanation
    The device initialisation routine found that a parameter was provided for a parameter that is not relevant for a specific DIAL Value.
    System Action
    The parameter is ignored. The system continues
    Operator Action
    for a runtime initialisation, correct the device initialisation parameters, otherwise notify the programmer.
    Programmer Action
    For an engine initialisation, correct the device configuration parameters in the configuration file.
    Note
    For DIAL=IN , RPORT and RHOST are ignored
    For DIAL=OUT , LPORT, LHOST, RPORT and RHOST are ignored
    For DIAL=INOUT, RPORT and RHOST are ignored

    HHCCA017I CCUU:LPORT|RPORT|LHOST|RHOST parameter ignored
    Explanation
    The system indicates that the parameter specified is ignored. This message is preceeded by message HHCCA016W
    System Action
    The system continues
    Operator Action
    None
    Programmer Action
    None

    HHCCA018E CCUU:Bind failed : System Cause Text
    Explanation
    While attempting to bind a socket to a specific host/port, the host system returned an uncorrectable error.
    System Action
    BSC Thread terminates
    Operator Action
    None
    Programmer Action
    Check that the LHOST parameter for this device is indeed a local IP address. Otherwise, notify support.

    HHCCA019E CCUU:BSC comm thread did not initialise
    Explanation
    The BSC communication thread reported that it terminated while the device was initialising.
    System Action
    The device is not initialised.
    Operator Action
    Check for any previously issued error message.
    Programmer Action
    Check for any previously issued error message.

    HHCCA020E CCUU:Memory allocation failure for main control block
    Explanation
    A memory allocation failure occured while attempting to reserve memory for the Communication Adapter control block
    System Action
    The device is not initialised.
    Operator Action
    None
    Programmer Action
    Contact support

    HHCCA021I CCUU:Initialisation failed due to previous errors
    Explanation
    The initialisation process for device CCUU did not complete succesfully
    System Action
    The device is not initialised
    Operator Action
    None
    Programmer Action
    Refer to any previous error message

    HHCCA300D Debug Message
    Explanation
    This is a debug message. CCW Tracing has been turned on for this device and the Line Handler issues debug messages to help diagnose interface, conformance and protocol issues.
    System Action
    The system continues
    Operator Action
    If the debug messages are no longer necessary, turn off CCW tracing (panel command : 't-CCUU').
    Programmer Action
    None


    If you have a question about Hercules, see the Hercules Frequently-Asked Questions page.


    back

    Last updated $Date: 2007-10-06 14:44:28 -0500 (Sat, 06 Oct 2007) $ $Revision: 4460 $

    hercules-3.07/html/hercmscf.html000644 000765 000765 00000120166 11321734032 020371 0ustar00jmaynardjmaynard000000 000000 Hercules Version 3: System Messages: CF - Configuration Processing

    Hercules Version 3: System Messages: CF: Configuration Processing

    This page describes the terminal emulation messages for the Hercules S/370, ESA/390, and z/Architecture emulator.

    Messages

    HHCCF001S Error reading file filename line lineno: error
    Meaning
    An error was encountered reading the configuration file named filename at line number lineno. The error is described by error.
    Action
    Correct the error and restart Hercules.
    Issued by
    bldcfg.c, function read_config
    HHCCF002S File filename line lineno is too long
    Meaning
    The line at line number lineno in the configuration file filename is too long and cannot be processed.
    Action
    Correct the line and restart Hercules.
    Issued by
    bldcfg.c, function read_config
    HHCCF003S Cannot open file filename: error
    Meaning
    The configuration file named filename could not be opened. The error is described by error.
    Action
    Correct the error and restart Hercules.
    Issued by
    bldcfg.c, function build_config
    HHCCF004S No device records in file filename
    Meaning
    The configuration file named filename does not contain any device definition records. Without them, Hercules cannot do any meaningful work.
    Action
    Specify one or more device definitions in the configuration file and restart Hercules.
    Issued by
    bldcfg.c, function build_config
    HHCCF005S Unrecognized argument argument
    Meaning
    An invalid argument, argument, was specified on the HTTPPORT configuration statement in the file named filename at line number lineno. Only the arguments auth and noauth are valid.
    Action
    Correct the invalid argument and restart Hercules.
    Issued by
    hsccmd.c, function httpport_cmd
    HHCCF008S Error in filename line lineno: Unrecognized keyword keyword
    Meaning
    An invalid configuration statement was specified in the file named filename at line number lineno. The invalid keyword was keyword.
    Action
    Correct the invalid statement and restart Hercules.
    Issued by
    bldcfg.c, function build_config
    HHCCF009S Error in filename line lineno: Incorrect number of operands
    Meaning
    The configuration statement at line lineno of the file named filename had an invalid number of operands. For all but the HTTPPORT statement, exactly one operand is required.
    Action
    Correct the invalid statement and restart Hercules.
    Issued by
    bldcfg.c, function build_config
    HHCCF010S Error in filename line lineno: Unknown or unsupported ARCHMODE specification mode
    Meaning
    The ARCHMODE configuration statement at line lineno of the file named filename specified an invalid architecture. Only S/370, ESA/390, or ESAME are valid. If one of these was specified, then support for that architecture was excluded when the copy of Hercules in use was compiled.
    Action
    Correct the specified value and restart Hercules. If the message was issued because support for the desired architecture was excluded, then recompile Hercules.
    Issued by
    bldcfg.c, function build_config
    HHCCF011S Error in filename line lineno: serialno is not a valid serial number
    Meaning
    The serial number serialno specified on the CPUSERIAL configuration statement at line number lineno of the file named filename must be exactly six digits long, and must be a valid hexadecimal number.
    Action
    Correct the serial number and restart Hercules.
    Issued by
    bldcfg.c, function build_config
    HHCCF012S Error in filename line lineno: modelno is not a valid CPU model
    Meaning
    The model number modelno specified on the CPUMODEL configuration statement at line number lineno of the file named filename must be exactly four digits long, and must be a valid hexadecimal number.
    Action
    Correct the model number and restart Hercules.
    Issued by
    bldcfg.c, function build_config
    HHCCF013S Error in filename line lineno: Invalid main storage size size
    Meaning
    The main storage size size specified on the MAINSIZE configuration statement at line number lineno of the file named filename must be a valid decimal number whose value is at least 2. For 32-bit platforms the value must not exceed 4095.
    Action
    Correct the main storage size and restart Hercules.
    Issued by
    bldcfg.c, function build_config
    HHCCF014S Error in filename line lineno: Invalid expanded storage size size
    Meaning
    The expanded storage size size specified on the XPNDSIZE configuration statement at line number lineno of the file named filename must be a valid decimal number between 0 and 16777215. For 32-bit platforms the value must not exceed 4095.
    Action
    Correct the expanded storage size and restart Hercules.
    Issued by
    bldcfg.c, function build_config
    HHCCF015S Error in filename line lineno: Invalid console port number port
    Meaning
    The console port number port specified on the CNSLPORT configuration statement at line number lineno of the file named filename must be a valid nonzero decimal number.
    Action
    Correct the console port number and restart Hercules.
    Issued by
    bldcfg.c, function build_config
    HHCCF016S Error in filename line lineno: Invalid threadname thread priority priority
    Meaning
    The thread priority priority specified on the xxxPRIO configuration statement at line number lineno of the file named filename must be a valid decimal number.
    Action
    Correct the priority on the statement and restart Hercules.
    Issued by
    bldcfg.c, function build_config
    HHCCF017W Hercules is not running as setuid root, cannot raise threadname priority
    Meaning
    A negative value for the threadname thread priority parameter xxxPRIO was specified, but Hercules is not running as the root user (either directly or via the setuid mechanism). This parameter value would cause the priority of the CPU execution thread to be raised above the normal level if Hercules were running as root. Since it is not, however, the parameter will have no effect.
    Action
    Either specify a positive value to lower the CPU thread priority, zero to not alter the priority, or omit the statement entirely to use the Hercules default CPU thread priority of 15.
    Issued by
    bldcfg.c, function build_config
    HHCCF018S Error in filename line lineno: Invalid number of CPUs number
    Meaning
    The number of emulated CPUs number specified on the NUMCPU configuration statement at line number lineno of the file named filename must be a valid decimal number between 1 and the maximum number (MAX_CPU_ENGINES) defined when Hercules was built.
    Action
    Correct the number of emulated CPUs and restart Hercules.
    Issued by
    bldcfg.c, function build_config
    HHCCF019S Error in filename line lineno: Invalid number of VFs number
    Meaning
    The number of emulated Vector Facility engines number specified on the NUMVEC configuration statement at line number lineno of the file named filename must be a valid decimal number between 1 and the maximum number defined when Hercules was built (usually 2).
    Action
    Correct the number of emulated Vector Facility engines and restart Hercules.
    Issued by
    bldcfg.c, function build_config
    HHCCF020W Vector Facility support not configured
    Meaning
    A request for Vector Facility support was made by the NUMVEC configuration statement, but Hercules was built without the Vector Facility code. The request has been ignored.
    Action
    If Vector Facility support is desired, recompile Hercules. If not, remove the NUMVEC configuration statement.
    Issued by
    bldcfg.c, function build_config
    HHCCF021S Error in filename line lineno: Invalid maximum number of CPUs number
    Meaning
    The maximum number of emulated CPUs number specified on the MAXCPU configuration statement at line number lineno of the file named filename must be a valid decimal number. It must not exceed the maximum number (MAX_CPU_ENGINES) defined when Hercules was built.
    Action
    Correct the MAXCPU parameter and restart Hercules.
    Issued by
    bldcfg.c, function build_config
    HHCCF022S Error in filename line lineno: epoch is not a valid system epoch
    Patch config.c to expand the table.
    Meaning
    The system epoch epoch specified on the SYSEPOCH configuration statement at line number lineno of the file named filename must be one of the following: 1900, 1928, 1960, 1988, or 1970.
    Action
    Correct the system epoch and restart Hercules. If a different epoch is desired, a change must be made to the Hercules source file config.c and Hercules rebuilt.
    Issued by
    bldcfg.c, function build_config
    HHCCF023S Error in filename line lineno: offset is not a valid timezone offset
    Meaning
    The system timezone offset offset specified on the TZOFFSET configuration statement at line number lineno of the file named filename must be five characters long, and a valid decimal number of the form (+|-)number, where number must be between zero and 2359 (representing 23 hours, 59 minutes).
    Action
    Correct the time zone offset and restart Hercules.
    Issued by
    bldcfg.c, function build_config
    HHCCF024S Error in filename line lineno: Invalid TOD clock drag factor drag
    Meaning
    The TOD clock drag factor drag specified on the TODDRAG configuration statement at line number lineno of the file named filename must be a valid decimal number between 1 and 10000.
    Action
    Correct the TOD clock drag factor and restart Hercules.
    Issued by
    bldcfg.c, function build_config
    HHCCF025S Error in filename line lineno: Invalid panel refresh rate rate
    Meaning
    The control panel refresh rate rate specified on the PANRATE configuration statement at line number lineno of the file named filename must be either F, S, or a valid decimal number between 1 and 5000.
    Action
    Correct the control panel refresh rate and restart Hercules.
    Issued by
    bldcfg.c, function build_config
    HHCCF026S Error in filename line lineno: Unknown OS tailor specification tailor
    Meaning
    The OS tailoring value tailor specified on the OSTAILOR configuration statement at line number lineno of the file named filename must be either OS/390, z/OS, VSE, VM, LINUX, NULL, or QUIET.
    Action
    Correct the OS tailoring value and restart Hercules.
    Issued by
    bldcfg.c, function build_config
    HHCCF027S Error in filename line lineno: Invalid maximum device threads threads
    Meaning
    The maximum device threads threads specified on the DEVTMAX configuration statement at line number lineno of the file named filename must be a valid decimal number greater than -1.
    Action
    Correct the maximum device threads and restart Hercules.
    Issued by
    bldcfg.c, function build_config
    HHCCF028S Invalid program product OS license setting permission
    Meaning
    The program product OS permission permission specified on the PGMPRDOS configuration statement must be either LICENSED or RESTRICTED. The alternative spelling LICENCED is also accepted.
    Action
    Correct the program product OS permission and restart Hercules.
    Issued by
    hsccmd.c, function pgmprdos_cmd
    HHCCF029S Invalid HTTP port number port
    Meaning
    The HTTP server port number port specified on the HTTPPORT configuration statement must be either 80, or a valid decimal number greater than 1024.
    Action
    Correct the HTTP server port number and restart Hercules.
    Issued by
    hsccmd.c, function httpport_cmd
    HHCCF030S Error in filename line lineno: Invalid I/O delay value delay
    Meaning
    The I/O delay value delay specified on the IODELAY configuration statement at line number lineno of the file named filename must be a valid decimal number.
    Action
    Correct the I/O delay value and restart Hercules.
    Issued by
    bldcfg.c, function build_config
    HHCCF031S Cannot obtain sizeMB main storage: error
    Meaning
    An attempt to obtain the amount of main storage specified by MAINSTOR failed for the reason described by error.
    Action
    Correct the error and restart Hercules.
    Issued by
    bldcfg.c, function build_config
    HHCCF032S Cannot obtain storage key array: error
    Meaning
    An attempt to obtain storage for the array of storage keys failed for the reason described by error.
    Action
    Correct the error and restart Hercules.
    Issued by
    bldcfg.c, function build_config
    HHCCF033S Cannot obtain sizeMB expanded storage: error
    Meaning
    An attempt to obtain the amount of expanded storage specified by XPNDSTOR failed for the reason described by error.
    Action
    Correct the error and restart Hercules.
    Issued by
    bldcfg.c, function build_config
    HHCCF034W Expanded storage support not installed
    Meaning
    A request was made for expanded storage by the XPNDSTOR configuration parameter, but Hercules was built without expanded storage support. The request was ignored.
    Action
    Either remove the XPNDSTOR configuration parameter, or recompile Hercules with expanded storage support included.
    Issued by
    bldcfg.c, function build_config
    HHCCF035S Error in filename line lineno: Missing device number or device type
    Meaning
    The I/O device definition statement at line number lineno of the file named filename did not contain a device number or a device type.
    Action
    Supply the missing value and restart Hercules.
    Issued by
    bldcfg.c, function build_config
    HHCCF036S Error in filename line lineno: number is not a valid device number(s) specification
    Meaning
    The I/O device definition statement at line number lineno of the file named filename specified an invalid device number number. The device number must be one to four hexadecimal digits.
    Action
    Correct the device number and restart Hercules.
    Issued by
    bldcfg.c, function build_config
    HHCCF037S Message pipe creation failed: error
    Meaning
    An attempt to create a pipe for communication with the control panel failed. The error is described by error.
    Action
    Correct the error and restart Hercules.
    Issued by
    bldcfg.c, function build_config
    HHCCF038S Message pipe open failed: error
    Meaning
    An attempt to open the pipe for communication with the control panel failed. The error is described by error.
    Action
    Correct the error and restart Hercules.
    Issued by
    bldcfg.c, function build_config
    HHCCF039W PGMPRDOS LICENSED specified.
              A licensed program product operating system is running.
              You are responsible for meeting all conditions of your
              software licenses.
    Meaning
    The configuration parameter PGMPRDOS LICENSED was specified and Hercules has detected that the operating system is a licensed program product. This message is issued to remind you that compliance with the terms of the license for your system's software is your responsibility.
    Action
    Be sure you know what you're doing.
    Issued by
    losc.c, function losc_check
    HHCCF040E Cannot create CPU number thread: error
    Meaning
    An attempt to create a new thread for execution of CPU number failed. The error is described by error. The CPU has not been added to the configuration.
    Action
    Correct the error and retry the operation.
    Issued by
    config.c, function configure_cpu
    HHCCF041E Device address already exists
    Meaning
    An attempt was made to define a device at address address. There is already a device at that address.
    Action
    Either choose another device address, or use the detach command to remove the existing device.
    Issued by
    config.c, function attach_device
    HHCCF042E Device type type not recognized
    Meaning
    An attempt was made to define a device of type type. This device type is not supported by Hercules. It may also indicate that the system was unable to load the device handler for the specified device type.
    Action
    Specify a supported device type. If the device type is supported, make sure the the system can load the load modules necessary for device operations. Either use the LD_LIBRARY_PATH environment variable or use ldconfig(8) to customize the library search path.
    Issued by
    config.c, function attach_device
    HHCCF043E Cannot obtain device block for device address: error
    Meaning
    An attempt to allocate memory for the control block describing the device with address address failed. The error is described by error. The device has not been defined.
    Action
    Correct the error and retry the operation.
    Issued by
    config.c, function attach_device
    HHCCF044E Initialization failed for device address
    Meaning
    The device at address address could not be initialized. The device initialization routine has issued a message describing the problem in further detail; refer to that message for more information.
    Issued by
    config.c, function attach_device
    HHCCF045E Cannot obtain buffer for device address: error
    Meaning
    An attempt to allocate memory for the data buffer for the device with address address failed. The error is described by error. The device has not been defined.
    Action
    Correct the error and retry the operation.
    Issued by
    config.c, function attach_device
    HHCCF046E Device address does not exist
    Meaning
    An attempt was made to remove a device at address address. There is no device at that address.
    Action
    Choose another device address to remove, if desired.
    Issued by
    config.c, function detach_device
    HHCCF047I Device address detached
    Meaning
    The device at address address has been successfully removed from the system.
    Issued by
    config.c, function detach_device
    HHCCF048E Device address does not exist
    Meaning
    An attempt was made to rename a device at address address. There is no device at that address.
    Action
    Choose another device address to rename, if desired.
    Issued by
    config.c, function define_device
    HHCCF049E Device address already exists
    Meaning
    An attempt was made to rename a device to address address. There is already a device at that address.
    Action
    Either choose another device address, or use the detach command to remove the existing device.
    Issued by
    config.c, function define_device
    HHCCF050I Device oldaddr defined as newaddr
    Meaning
    The device which was previously defined with the address oldaddr has been changed to the address newaddr.
    Issued by
    config.c, function define_device
    HHCCF051S Error in filename line lineno: verid is not a valid CPU version code
    Meaning
    The version code verid specified on the CPUVERID configuration statement at line number lineno of the file named filename must be exactly two digits long, and must be a valid hexadecimal number.
    Action
    Correct the model number and restart Hercules.
    Issued by
    bldcfg.c, function build_config
    HHCCF052S DIAG8CMD invalid option: option
    Meaning
    The argument option on the DIAG8CMD is invalid. Valid options are enable, disable, echo, and noecho,
    Action
    Correct the statement and restart Hercules.
    Issued by
    hsccmd.c, function diag8_cmd
    HHCCF053E Incorrect second device number in device range near character c
    Meaning
    The 2nd argument of a device range contains an incorrect device number
    Action
    Correct the statement and restart Hercules.
    Issued by
    config.c, function parse_devnums
    HHCCF054E Incorrect Device count near character c
    Meaning
    The count field in a device count specification is invalid
    Action
    Correct the statement and restart Hercules.
    Issued by
    config.c, function parse_devnums
    HHCCF055E Incorrect device address specification near character c
    Meaning
    The first or only CUU in a device specification statement is invalid
    Action
    Correct the statement and restart Hercules.
    Issued by
    config.c, function parse_devnums
    HHCCF056E Incorrect device address range. CUU1>CUU2
    Meaning
    The first device number of a range is greater than the last device number
    Action
    Correct the statement and restart Hercules.
    Issued by
    config.c, function parse_devnums
    HHCCF057E CUU is on wrong channel (1st device defined on channel CC)
    Meaning
    At least one of the devices in a device number specification is on a different channel than a previously defined device number within the same specification. All device numbers on a single configuration line must be on a single channel (Group of 256 devices)
    Action
    Correct the statement and restart Hercules.
    Issued by
    config.c, function parse_devnums
    HHCCF058E Some or all devices in CUU-CUU duplicate devices already defined
    Meaning
    At least one of the device numbers on a device specification statement defines a device number that is already specified on that same statement.
    Action
    Correct the statement and restart Hercules.
    Issued by
    config.c, function parse_devnums
    HHCCF061W ECPS:VM Statement deprecated. Use ECPSVM instead
    Meaning
    The "ECPS:VM" statement was encountered. This statement is deprecated in favor of the "ECPSVM" statement.
    Action
    The configuration statement is still carried out, but the statement syntax should be changed as soon as possible.
    Issued by
    config.c
    HHCCF062W Missing ECPSVM level value. 20 Assumed
    Meaning
    The "ECPSVM" statement keyword "LEVEL" was encountered, but no numeric level followed it
    Action
    The default level of 20 is used, and the ECPS:VM feature is made available. The statement should be corrected as soon as possible.
    Issued by
    config.c
    HHCCF063W Specifying ECPSVM level directly is deprecated. Use the 'LEVEL' keyword instead
    Meaning
    The deprecated "ECPSVM" level syntax form (without the LEVEL keyword) was found.
    Action
    The ECPS:VM Level is set to the specified value. The configuration statement should be updated to include the "LEVEL" keyword.
    Issued by
    config.c
    HHCCF064W Hercules set priority priority failed: error
    Meaning
    An attempt to change the priority of the Hercules process to priority failed. The error is described by error. The process priority has not been changed. Hercules overall performance may be impaired as a result.
    Action
    If performance problems are noted, correct the error and restart Hercules.
    Issued by
    bldcfg.c, function build_config
    HHCCF065I Hercules: tid=threadid, pid=processid, pgid=processgroupid, priority=priority
    Meaning
    Hercules thread id is threadid, its process id is processid, its process group id is processgroupid and its execution priority is priority.
    Issued by
    bldcfg.c, function build_config
    HHCCF066E Invalid HTTPROOT: error
    Meaning
    The pathname specified on your HTTPROOT statement is invalid. The error is described by error.
    Action
    Correct the error and restart Hercules.
    Issued by
    httpserv.c, function http_server
    HHCCF067S Incorrect keyword keyword for the ASN_AND_LX_REUSE statement
    Meaning
    The keyword specified for the ASN_AND_LX_REUSE statement is not ENABLE or DISABLE
    Action
    Correct the error and restart Hercules.
    Issued by
    hsccmd.c, function alrf_cmd
    HHCCF068E Invalid value: value; Enter "help scsimount" for help.
    Meaning
    The automatic SCSI tape mount value is not "NO" nor a value between 1 and 99 seconds inclusive.
    Action
    Reissue the SCSIMOUNT command.
    Issued by
    hsccmd.c, function scsimount_cmd
    HHCCF069I Run-options enabled for this run:
              NUMCPU:           n
              ASN-and-LX-reuse: Enabled/Disabled
              DIAG8CMD:         Enabled/Disabled
    Meaning
    This message confirms the setting of various run-time options specified in the configuration file at startup time.
    Action
    None.
    Issued by
    bldcfg.c, function build_config
    HHCCF074E Unspecified error occured while parsing Logical Channel Subsystem Identification
    Meaning
    A logic error occured while parsing the Logical Channel Subsystem Identification component of a device number or device number group.
    Action
    Notify hercules support. This is an error in the hercules parsing routines.
    Issued by
    config.c, function parse_lcss
    HHCCF075E No more than 1 Logical Channel Subsystem Identification may be specified
    Meaning
    While specifying a device number or device number group, more than 1 ':' character was encountered while parsing the Logical Channel Subsystem Identification component. There can be only one Logical Channel Subsystem Identification for a device or group of devices.
    Action
    Correct the device number or device number group specification and either reissue the command or restart the hercules engine (depending on whether the error occured while issuing a command or while starting the engine).
    Issued by
    config.c, function parse_lcss
    HHCCF076E Non numeric Logical Channel Subsystem Identification XX
    Meaning
    While specifying a device number or device number group, a non decimal value was encountered while parsing the Logical Channel Subsystem Identification component. The Logical Channel Subsystem Identification for a device or group of devices must be specified as a numeric value.
    Action
    Correct the device number or device number group specification and either reissue the command or restart the hercules engine (depending on whether the error occured while issuing a command or while starting the engine).
    Issued by
    config.c, function parse_lcss
    HHCCF077E Logical Channel Subsystem Identification NN exceeds maximum of 3
    Meaning
    While specifying a device number or device number group, a Logical Channel Identification was encountered that exceeded the architecture maximum value of MM. The Logical Channel Subsystem Identification for a device or group of devices must be within 0 and 3 (inclusive).
    Action
    Correct the device number or device number group specification and either reissue the command or restart the hercules engine (depending on whether the error occured while issuing a command or while starting the engine).
    Issued by
    config.c, function parse_lcss
    HHCCF079A A licensed program product operating system has been detected. All processors have been stopped.
    Meaning
    Hercules has detected that the operating system is a licensed program product, but the PGMPRDOS LICENSED parameter was not specified in the Hercules configuration file.
    Action
    Hercules enters the stopped state. To run this operating system you must obtain a license from the operating system supplier and specify the PGMPRDOS LICENSED parameter in the configuration file. If you are unable to obtain a valid license allowing you to run this operating system on your machine, you must use another operating system (such as MVS3.8J or Linux for System z) which does not require a license.
    Issued by
    losc.c, function losc_check
    HHCCF081I fname Will ignore include errors .
    Meaning
    An ignore include_errors statement was encountered in file fname requesting that any include statements subsequently found within file fname which happen to reference include files which do not exist should simply cause a HHCCF084W warning instead of a HHCCF085S fatal error.
    Action
    Processing continues. This is an informational-only message.
    Issued by
    bldcfg.c, function build_config
    HHCCF082S Error in fname line nnn: Maximum nesting level (nn) reached
    Meaning
    The maximum number of nested include statements has been exceeded. The include statement which caused the maximum nesting level of nn to be exceeded is identified as statement number nnn of file fname.
    Action
    This is a fatal error. Configuration file processing is immediately terminated and Hercules startup is aborted. Correct the error and restart Hercules.
    Issued by
    bldcfg.c, function build_config
    HHCCF083I fname1 Including fname2 at nnn.
    Meaning
    An include statement for file fname2 was encountered on line nnn of file fname1.
    Action
    Configuration file processing switches immediately to processing the statements contained in file fname2. Once all of the ststements in file fname2 have been completely processed, configuration file processing will then return to statement nnn+1 of file fname1. This is an informational-only message.
    Issued by
    bldcfg.c, function build_config
    HHCCF084W fname1 Open error ignored file fname2: error
    Meaning
    File fname1 contained an include statement for file fname2 which could not be opened because of error.
    Action
    Processing continues. This is a informational warning only. Check to make sure the filename specified by fname2 was spelled correctly and restart Hercules if desired.
    Issued by
    bldcfg.c, function build_config
    HHCCF085S fname1 Open error file fname2: error
    Meaning
    File fname1 contained an include statement for file fname2 which could not be opened because of error.
    Action
    This is a fatal error. Configuration file processing is immediately terminated and Hercules startup is aborted. Correct the possible misspelling of filename fname2 and restart Hercules.
    Issued by
    bldcfg.c, function build_config
    HHCCF086S Error in filename: NUMCPU nn must not exceed MAXCPU mm
    Meaning
    The number of online CPUs nn specified in the NUMCPU configuration statement in the file named filename cannot exceed the maximum number of CPUs mm specified in the MAXCPU configuration statement.
    Action
    Either decrease the NUMCPU parameter, or increase the MAXCPU parameter, and restart Hercules.
    Issued by
    bldcfg.c, function build_config


    If you have a question about Hercules, see the Hercules Frequently-Asked Questions page.


    back

    Last updated $Date: 2009-12-24 08:29:38 -0600 (Thu, 24 Dec 2009) $ $Revision: 5562 $

    hercules-3.07/html/hercmscp.html000644 000765 000765 00000020274 11143760535 020413 0ustar00jmaynardjmaynard000000 000000 Hercules Version 3: System Messages: CP - CPU Emulation

    Hercules Version 3: System Messages: CP - CPU Emulation

    This page describes the CPU emulation messages for the Hercules S/370, ESA/390, and z/Architecture emulator.

    Messages

    HHCCP001W CPU thread set priority priority failed: error
    Meaning
    An attempt to change the priority of the CPU thread to priority failed. The error is described by error. The thread priority has not been changed. Hercules overall performance may be impaired as a result.
    Action
    If performance problems are noted, correct the error and restart Hercules.
    Issued by
    cpu.c, function cpu_thread
    HHCCP002I CPUnumber thread started: tid=threadid, pid=processid, priority=priority
    Meaning
    The execution thread for CPU number number has been started. Its thread id is threadid, its process id is processid, and its execution priority is priority.
    Issued by
    cpu.c, function cpu_thread
    HHCCP003I CPUnumber architecture mode mode
    Meaning
    CPU number has been set to the mode architecture mode.
    Action
    If a different architecture mode is desired, it may be changed with the ARCHMODE configuration statement or the archmode control panel command.
    Issued by
    cpu.c, function cpu_thread
    HHCCP004I CPUnumber Vector Facility online
    Meaning
    The Vector Facility for CPU number is online and available for use.
    Issued by
    cpu.c, function cpu_thread
    HHCCP005E CPUnumber thread already started
    Meaning
    An attempt was made to add CPU number number to the configuration. This CPU already exists.
    Action
    If another CPU is desired in the configuration, select a different number.
    Issued by
    cpu.c, function cpu_thread
    HHCCP006S Cannot create timer thread: error
    Meaning
    An attempt to create the thread used for timing functions has failed. The error is described by error. The CPU thread terminates and successful continuation of Hercules is not possible.
    Action
    Correct the error and restart Hercules.
    Issued by
    cpu.c, function cpu_thread
    HHCCP007I CPUnumber architecture mode set to mode
    Meaning
    CPU number number has been changed to the architecture mode mode.
    Issued by
    cpu.c, function cpu_thread
    HHCCP008I CPUnumber thread ended: tid=threadid, pid=processid
    Meaning
    The execution thread for CPU number number has ended. Its thread id was threadid, and its process id was processid.
    Issued by
    cpu.c, function cpu_thread
    HHCCP009E CPU MASK MISMATCH: prevmask - currmask. Last instruction: instruction.
    Meaning
    The CPU interrupt mask has changed unexpectedly. The previous mask was prevmask, and the current mask is currmask. The last instruction executed was instruction. This is an internal error.
    Action
    Report this message and the circumstances to the Hercules developers.
    Issued by
    cpu.c, function process_interrupt
    HHCCP010I CPUnumber store status completed.
    Meaning
    CPU number number has completed a store status operation.
    Issued by
    cpu.c, function process_interrupt
    HHCCP011I CPUnumber: Disabled wait state
    Meaning
    CPU number number has entered a disabled wait state. It will not execute any further instructions unless it is reset or restarted. This is usually done to report a severe error in execution of an operating system.
    Action
    Correct the error denoted by the wait state code, if applicable.
    Issued by
    cpu.c, function process_interrupt
    HHCCP023I External interrupt: Interrupt key
    Meaning
    The CPU has taken an external interrupt because the operator pressed the interrupt key or issued the panel command ext.
    Action
    None.
    Issued by
    external.c, function perform_external_interrupt
    HHCCP024I External interrupt: Clock comparator
    Meaning
    The CPU has taken a clock comparator interrupt. This message is issued only when the CPU is in single-stepping or instruction-tracing mode.
    Action
    None. External interrupts are part of normal system operation.
    Issued by
    external.c, function perform_external_interrupt
    HHCCP025I External interrupt: CPU timer=xx...xx
    Meaning
    The CPU has taken a CPU timer interrupt. xx...xx is the hexadecimal value of the CPU timer. This message is issued only when the CPU is in single-stepping or instruction-tracing mode.
    Action
    None. External interrupts are part of normal system operation.
    Issued by
    external.c, function perform_external_interrupt
    HHCCP026I External interrupt: Interval timer
    Meaning
    The CPU has taken an external interrupt caused by the interval timer. This message is issued only when the CPU is in single-stepping or instruction-tracing mode.
    Action
    None. External interrupts are part of normal system operation.
    Issued by
    external.c, function perform_external_interrupt
    HHCCP027I External interrupt: Service signal intparm
    Meaning
    The CPU has taken a service signal external interrupt. intparm is the interrupt parameter. This message is issued only when the CPU is in single-stepping or instruction-tracing mode.
    Action
    None. External interrupts are part of normal system operation.
    Issued by
    external.c, function perform_external_interrupt
    HHCCP090W The configuration has been placed into a system check-stop state because of an incompatible service call
    Meaning
    A READ SCP INFO (code X'00020001') Service call has been issued from a CPU which is not a CP engine. All the CPUs in the configuration are put into a Check-Stop state.
    Action
    Ensure the CPU that issues the service call is a CP engine and restart the program.
    Issued by
    service.c, function service_call


    If you have a question about Hercules, see the Hercules Frequently-Asked Questions page.


    back

    Last updated $Date: 2008-12-28 16:00:57 -0600 (Sun, 28 Dec 2008) $ $Revision: 4992 $

    hercules-3.07/html/hercmsct.html000644 000765 000765 00000002165 11143760535 020416 0ustar00jmaynardjmaynard000000 000000 Hercules Version 3: System Messages: CT - Channel-to-Channel Adapter Emulation

    Hercules Version 3: System Messages: CT - Channel-to-Channel Adapter Emulation

    This page describes the channel-to-channel adapter emulation messages for the Hercules S/370, ESA/390, and z/Architecture emulator.

    Messages

    HHCCT001I
    Meaning
    Issued by
    ctcadpt.c, function


    If you have a question about Hercules, see the Hercules Frequently-Asked Questions page.


    back

    Last updated $Date: 2007-10-06 14:44:28 -0500 (Sat, 06 Oct 2007) $ $Revision: 4460 $

    hercules-3.07/html/hercmscu.html000644 000765 000765 00000045251 11143760535 020422 0ustar00jmaynardjmaynard000000 000000 Hercules Version 3: System Messages: CU - CCKD Utilities

    Hercules Version 3: System Messages: CU - CCKD Utilities

    Messages issued by the cckd utility commands (cckdcdsk, cckdcomp and cckdswap) and cckd utility functions (cckd_chkdsk, cckd_comp and cckd_swap) are described here. The utility functions are called by both the utility commands and Hercules.

    Messages

    Messages are in the format
    HHCCUnnnt file message text
    where nnn is the message number, t is either I, W or E, depending on the severity of the message. file will either be the part of the file name following the last slash (/ or \) when called by a utility command, or will be xxxx: file[n] where xxxx is the device number and n is the shadow file number when called by Hercules.

    The file portion of the message is omitted below for brevity.


    HHCCU101I converting to endian-format
    Meaning
    The file is in the wrong endian (byte order) format for the host architecture. The file is being converted to the host endian format endian-format.
    Issued by
    cckdutil.c functions cckd_comp and cckd_chkdsk
    HHCCU102I compress successful, n bytes released
    Meaning
    The compress function successfully completed and free n bytes from the file. If n is 0, then the level 2 tables were repositioned to the beginning of the file in order.
    Issued by
    cckdutil.c function cckd_comp
    HHCCU103I file already compressed
    Meaning
    The compress function determined that the file is already compressed. The file is not updated.
    Issued by
    cckdutil.c function cckd_comp
    HHCCU104I free space rebuilt
    Meaning
    Free space errors were detected and free space has been successfully rebuilt
    Issued by
    cckdutil.c function cckd_chkdsk
    HHCCU300I number space images recovered
    Meaning
    Recovery phase 1 completed, recovering number spaces (trks or blkgrps)
    Issued by
    cckdutil.c function cckd_comp
    HHCCU301I space[id] recovered offset offset len length
    Meaning
    The space space (trk or blkgrp) was recovered at offset offset and length length. id is the trk or blkgrp number.
    Issued by
    cckdutil.c function cckd_comp
    HHCCU500W recovery not completed, file opened read-only
    Meaning
    Phase 3 recovery did not complete because the file is not opened for write
    Action
    Omit the -ro option for cckdcdsk, or change the file permissions to enable the file to be opened for read-write for Hercules
    Issued by
    cckdutil.c function cckd_comp
    HHCCU501W recovery not completed, missing compression
    Meaning
    Phase 3 recovery did not complete because one or more trk or blkgrp images were compressed using a compression (zlib or bzip2) that was not built into Hercules
    Action
    Processing terminates. The file has not been updated. Build Hercules with the missing compression libraries.
    Issued by
    cckdutil.c function cckd_comp
    HHCCU502W free space not rebuilt, file opened read-only
    Meaning
    Free space errors were detected but the free space was not rebuilt because the file is not opened for write
    Action
    Omit the -ro option for cckdcdsk, or change the file permissions to enable the file to be opened for read-write for Hercules
    Issued by
    cckdutil.c function cckd_comp
    HHCCU600W forcing check level level[; reason]
    Meaning
    Errors have been detected in the compressed file that warrant the escalation of the check level to level. An additional explanation reason may be supplied.
    Action
    At a minimum, free space will be rebuilt
    Issued by
    cckdutil.c function cckd_comp
    HHCCU601W cdevhdr inconsistencies found code=code
    Meaning
    The space statistics in the cckddasd device header (cdevhdr) contain inconsistencies described by code. code is a 16-bit bit field and more than one bit may be on. See cckdutil.c for the different bit settings.
    Action
    At a minimum, free space will be rebuilt
    Issued by
    cckdutil.c function cckd_comp
    %s offset 0x%" I32_FMT "x len %d is out of bounds
    HHCCU602W space offset offset len length is out of bounds
    Meaning
    The space space (trk, blkgrp or l2) either precedes the end of the L1 table (at the beginning of the file) or exceeds the end of the file
    Action
    The space will be recovered. If the space is an L2 table, then all tracks or block groups associated with the table will also be recovered.
    Issued by
    cckdutil.c function cckd_comp
    HHCCU603W space1 offset offset1 len length overlaps space2 offset offset2
    Meaning
    The space space1 overlaps space space2.
    Action
    The spaces will be recovered. If either space is an L2 table, then all tracks or block groups associated with that table will also be recovered.
    Issued by
    cckdutil.c function cckd_comp
    HHCCU604W space l2 inconsistency: len length, size size
    Meaning
    The space space (trk or blkgrp) has an inconsistent l2 entry. Either the length length is too small or is too large or exceeds the size size
    Action
    The space will be recovered.
    Issued by
    cckdutil.c function cckd_comp
    HHCCU610W free space errors detected
    Meaning
    Free space is not consistent
    Action
    Free space will be rebuilt
    Issued by
    cckdutil.c function cckd_comp
    HHCCU620W space[id] hdr error offset offset: xxxxxxxxxx
    Meaning
    A header error was found for space (trk or blkgrp) during validation. id is the trk or blkgrp number. The header is located at file offset offset. The contents of the 5 byte header is xxxxxxxxxx in hex.

    The first byte of the header should be either 00 (compress none), 01 (compress zlib) or 02 (compress bzip2).
    For ckd, the next two bytes is the cylinder (in big-endian byte order) and the two bytes after that is the head (also in big-endian byte order).
    For fba, the next four bytes is the block group number (in big-endian byte order).

    The header contains an invalid value. Either the offset is incorrect or the header has been overlaid.

    Action
    The space will be recovered
    Issued by
    cckdutil.c function cckd_comp
    HHCCU621W space[id] compressed using compression, not supported
    Meaning
    During validation, the header for space (trk or blkgrp) indicates that the space was compressed using compression (zlib or bzip2) but support for that compression method was not built into Hercules. id is the trk or blkgrp number.
    Action
    Processing continues. However, no recovery will take place.
    Build Hercules with the specified compression library.
    Issued by
    cckdutil.c function cckd_comp
    HHCCU622W space[id] offset offset len length validation error
    Meaning
    The space (trk or blkgrp) at offset offset and length length failed validation. id is the trk or blkgrp number. Either the space did not uncompress successfully or the uncompressed space contains some kind of error. This error is detected during check level 3 validation.
    Action
    The space will be recovered
    Issued by
    cckdutil.c function cckd_comp
    HHCCU700E open error: error text
    Meaning
    Open failed for the file. The text associated with the error number is displayed.
    Action
    Processing for the file terminates.
    Issued by
    cckdccdsk.c, cckdcomp.c
    HHCCU701E fstat error: error text
    Meaning
    The file status system call failed. The text associated with the error number is displayed.
    Action
    Function processing terminates. Probable Hercules logic error. Contact the hercules mailing list for assistance.
    Issued by
    cckdutil.c functions cckd_swapend, cckd_comp and cckd_chkdsk
    HHCCU702E lseek error offset offset: error text
    Meaning
    File reposition to offset offset failed. The text associated with the error number is displayed.
    Action
    Function processing terminates. Probable Hercules logic error. Contact the hercules mailing list for assistance.
    Issued by
    cckdutil.c functions cckd_swapend, cckd_comp and cckd_chkdsk
    HHCCU703E read error rc=retcode offset offset len length: error text
    Meaning
    A read failed at offset offset for length length. If retcode is not negative then the read was incomplete and the value indicates how many bytes were read. Otherwise the text associated with the error number is displayed.
    Action
    Function processing terminates. Possible Hercules logic error. Possible hardware error. Contact the hercules mailing list for assistance.
    Issued by
    cckdutil.c functions cckd_swapend, cckd_comp and cckd_chkdsk
    HHCCU704E write error rc=retcode offset offset len length: error text
    Meaning
    A write failed at offset offset for length length. If retcode is not negative then the write was incomplete and the value indicates how many bytes were written. Otherwise the text associated with the error number is displayed.
    Action
    Function processing terminates. Possible Hercules logic error. Possible hardware error. Contact the hercules mailing list for assistance.
    Issued by
    cckdutil.c functions cckd_swapend, cckd_comp and cckd_chkdsk
    HHCCU705E malloc error, size size: error text
    Meaning
    Malloc (allocate memory) failed for size size.
    Action
    Function processing terminates. Try reducing Hercules storage requirements (eg mainsize).
    Issued by
    cckdutil.c functions cckd_swapend, cckd_comp and cckd_chkdsk
    HHCCU706E calloc error, size size: error text
    Meaning
    Calloc (allocate cleared memory) failed for size size.
    Action
    Function processing terminates. Try reducing Hercules storage requirements (eg mainsize).
    Issued by
    cckdutil.c functions cckd_swapend, cckd_comp and cckd_chkdsk
    HHCCU707E OPENED bit is on, use -f
    Meaning
    The file OPENED bit is on in the cckd header but -f was not specified
    Action
    File processing terminates. Make sure the file is not in use. If it is not, try the command again specifying the -f option.
    Issued by
    cckdcdsk.c, cckdcomp.c
    HHCCU708E chkdsk errors
    Meaning
    The utility called cckd_chkdsk for the file and it returned in error
    Action
    File processing terminates. Perform the actions suggested by the preceding cckd_chkdsk errors
    Issued by
    cckdcomp.c
    HHCCU900E dasd lookup error type=type cyls=cyls
    Meaning
    The device type type from the device header along with the number of cylinders cyls did not match a table entry in dasdtab.c. Note that type is the last two bytes of the device type (eg 90 for a 3390 device type).
    Action
    Function processing terminates. Specify the correct file name or manually correct the device header.
    Issued by
    cckdutil.c function cckd_chkdsk
    HHCCU901E bad trksize: size1, expecting size2
    Meaning
    The track size size1 from the device header does match the track size size2 from the table entry in dasdtab.c
    Action
    Function processing terminates. Specify the correct file name or manually correct the device header.
    Issued by
    cckdutil.c function cckd_chkdsk
    HHCCU902E bad number of heads: heads1, expecting heads2
    Meaning
    The number of heads heads1 from the device header does match the number of heads heads2 from the table entry in dasdtab.c
    Action
    Function processing terminates. Specify the correct file name or manually correct the device header.
    Issued by
    cckdutil.c function cckd_chkdsk
    HHCCU903E bad `numl1tab': nbr1, expecting nbr2
    Meaning
    The number of L1 table entries nbr1 in the cckd device header does not match the number calculated nbr2. The number calculated is the number of cylinders times the number of heads (ie the number of tracks) divided by 256, rounded up by 1 if there is a remainder.
    Action
    Function processing terminates. Specify the correct file name or manually correct the device headers.
    Issued by
    cckdutil.c function cckd_chkdsk
    HHCCU904E file too small to contain L1 table: %size1, need size2
    Meaning
    The size of the file size1 is not large enough to contain all L1 table entries; the size required is size2. The minimum size of a cckd file is
    512 + 512 + ( 4 * number of L1 entries)
    Action
    Function processing terminates. Specify the correct file name.
    Issued by
    cckdutil.c function cckd_chkdsk
    HHCCU905E not enough file space for recovery
    Meaning
    During phase 2 recovery, there is not enough space in the maximum file size to contain the rebuilt L2 tables. This is an unusual situation and probably indicates some kind of programming error.
    Action
    Function processing terminates. The file has not been updated. Contact the hercules mailing list for assistance.
    Issued by
    cckdutil.c function cckd_chkdsk
    HHCCU910E error during swap
    Meaning
    Error occurred during cckd_swap(). See the preceding error messages.
    Issued by
    cckdutil.c function cckd_chkdsk
    HHCCU999E not a compressed file
    Meaning
    The first 8 bytes of the file did not match an expected identifier. For a cckd file, the identifier must be either CKD_C370 or CKD_S370. For a cfba file, the identifier must be either FBA_C370 or FBA_S370.
    Action
    Function processing terminates. Specify the correct file name.
    Issued by
    cckdutil.c functions cckd_swapend, cckd_comp and cckd_chkdsk


    If you have a question about Hercules, see the Hercules Frequently-Asked Questions page.


    back

    Last updated $Date: 2008-10-22 04:20:13 -0500 (Wed, 22 Oct 2008) $ $Revision: 4893 $

    hercules-3.07/html/hercmsda.html000644 000765 000765 00000002063 11143760535 020371 0ustar00jmaynardjmaynard000000 000000 Hercules Version 3: System Messages: DA - DASD Emulation

    Hercules Version 3: System Messages: DA - DASD Emulation

    This page describes the DASD emulation messages for the Hercules S/370, ESA/390, and z/Architecture emulator.

    Messages

    HHCDA001I
    Meaning
    Issued by
    ckddasd.c, function


    If you have a question about Hercules, see the Hercules Frequently-Asked Questions page.


    back

    Last updated $Date: 2007-10-06 14:44:28 -0500 (Sat, 06 Oct 2007) $ $Revision: 4460 $

    hercules-3.07/html/hercmsdc.html000644 000765 000765 00000012667 11143760535 020406 0ustar00jmaynardjmaynard000000 000000 Hercules Version 3: System Messages: DC - dasdcopy

    Hercules Version 3: System Messages: DC - dasdcopy

    This page describes the messages for the Hercules S/370, ESA/390, and z/Architecture emulator disk image copy utility.

    Note that this utility can be called by several names: dasdcopy, ckd2cckd, cckd2ckd, fba2cfba, and cfba2fba. The same program is used for all of these functions. The name used to invoke the program is reported in each of these messages as progname.

    Messages

    HHCDC001E progname: filename open error: error
    Meaning
    An error was encountered when trying to open the input file named filename to determine its type. The error is described by error.
    Action
    Correct the error and retry the operation.
    Issued by
    dasdcopy.c, function main
    HHCDC002E progname: filename read error: error
    Meaning
    An error was encountered when trying to read the input file named filename to determine its type. The error is described by error.
    Action
    Correct the error and retry the operation.
    Issued by
    dasdcopy.c, function main
    HHCDC003E progname: filename open failed
    Meaning
    An error was encountered when trying to open the input file named filename for copying. A previous message described the error.
    Action
    Correct the error and retry the operation.
    Issued by
    dasdcopy.c, function main
    HHCDC004E progname: ckd lookup failed for size cyls
    Meaning
    There was no disk drive table entry that matched the number of cylinders in the CKD source file, size. The program cannot determine how much data to copy.
    Action
    Correct the error and retry the operation.
    Issued by
    dasdcopy.c, function main
    HHCDC005E progname: fba lookup failed, blks size
    Meaning
    There was no disk drive table entry that matched the number of blocks in the FBA source file, size. The program cannot determine how much data to copy.
    Action
    Correct the error and retry the operation.
    Issued by
    dasdcopy.c, function main
    HHCDC006E progname: filename create failed
    Meaning
    An error was encountered when trying to create the output file named filename. A previous message described the error.
    Action
    Correct the error and retry the operation.
    Issued by
    dasdcopy.c, function main
    HHCDC007E progname: filename open failed
    Meaning
    An error was encountered when trying to open the newly created output file named filename. A previous message described the error.
    Action
    Correct the error and retry the operation.
    Issued by
    dasdcopy.c, function main
    HHCDC008E progname: filename read error (track|block) number stat=status
    Meaning
    An error was encountered when trying to read a block or track from the input file named filename. The block or track is number number. The status returned is shown as status.
    Action
    Correct the error and retry the operation.
    Issued by
    dasdcopy.c, function main
    HHCDC009E progname: filename write error (track|block) number stat=status
    Meaning
    An error was encountered when trying to read a block or track from the input file named filename. The block or track is number number. The status returned is shown as status.
    Action
    Correct the error and retry the operation.
    Issued by
    dasdcopy.c, function main
    HHCDC010I progname successfully completed
    Meaning
    The copy operation has completed successfully.
    Issued by
    dasdcopy.c, function main


    If you have a question about Hercules, see the Hercules Frequently-Asked Questions page.


    back

    Last updated $Date: 2008-11-02 16:57:01 -0600 (Sun, 02 Nov 2008) $ $Revision: 4903 $

    hercules-3.07/html/hercmsdg.html000644 000765 000765 00000014027 11143760535 020402 0ustar00jmaynardjmaynard000000 000000 Hercules Version 3: System Messages: DG - DYNGUI.DLL

    Hercules Version 3: System Messages: DG - DYNGUI.DLL

    This page describes the DYNGUI.DLL messages for the Hercules S/370, ESA/390, and z/Architecture emulator.

    Messages

    HHCDG001I dyngui.dll - name - version vers initiated
    HHCDG002I dyngui.dll terminated
    HHCDG003S select failed on input stream: errmsg
    HHCDG004S read failed on input stream: errmsg
    HHCDG005E Device query buffer overflow! (device=xxxx)
    HHCDG006S malloc pszInputBuff failed: errmsg
    HHCDG007S malloc pszCommandBuff failed: errmsg


    HHCDG001I dyngui.dll - name - version vers initiated

    Meaning
    The dyngui loadable module was successfully loaded and initiated.

    Action
    None. This message is informational only.


    HHCDG002I dyngui.dll terminated

    Meaning
    The dyngui loadable module was successfully terminated.

    Action
    None. This message is informational only.


    HHCDG003S select failed on input stream: errmsg

    Meaning
    The socket select function call failed on the input stream. errmsg  describes the exact error.

    Action
    None; this is a fatal error; the system is immediately terminated.


    HHCDG004S read failed on input stream: errmsg

    Meaning
    An unrecoverable i/o error occurred while reading from the input stream. errmsg  describes the exact error.

    Action
    None; this is a fatal error; the system is immediately terminated.


    HHCDG005E Device query buffer overflow! (device=xxxx)

    Meaning
    The device query buffer is not large enough to hold all of the information returned by the device handler. xxxx  is the device whose information was being queried at the time the error occurred.

    Action
    The system attempts to continue functioning, but unpredictable results may occur (i.e. the system could crash). You should report this error to the Hercules developers immediately so that they can build you a new dyngui.dll with a larger device query buffer. Since the dyngui.dll is an unloadable module however, you will need to restart Hercules in order to begin using the newly fixed version of dyngui.dll.


    HHCDG006S malloc pszInputBuff failed: errmsg

    Meaning
    There was not enough virtual memory on the host system to satisfy the malloc request for the input stream buffer. errmsg  describes the exact error.

    Action
    None; this is a fatal error; the system is immediately terminated. You should increase the size of your host system's virtual memory allocation so that there is enough for Hercules to run, or else decrease the amount of memory that Hercules needs in order to run (e.g. decrease your MAINSIZE value).


    HHCDG007S malloc pszCommandBuff failed: errmsg

    Meaning
    There was not enough virtual memory on the host system to satisfy the malloc request for the command processing buffer. errmsg  describes the exact error.

    Action
    None; this is a fatal error; the system is immediately terminated. You should increase the size of your host system's virtual memory allocation so that there is enough for Hercules to run, or else decrease the amount of memory that Hercules needs in order to run (e.g. decrease your MAINSIZE value).



    If you have a question about Hercules, see the Hercules Frequently-Asked Questions page.


    back

    Last updated $Date: 2007-10-06 14:44:28 -0500 (Sat, 06 Oct 2007) $ $Revision: 4460 $

    hercules-3.07/html/hercmsdi.html000644 000765 000765 00000002767 11143760535 020414 0ustar00jmaynardjmaynard000000 000000 Hercules Version 3: System Messages: DI - dasdinit

    Hercules Version 3: System Messages: DI - dasdinit

    This page describes the messages for the Hercules S/370, ESA/390, and z/Architecture emulator utility program dasdinit.

    Messages

    HHCDI001I DASD initialization successfully completed.
    Meaning
    The requested DASD volume has been successfully initialized and is ready for use.
    Issued by
    dasdinit.c, function main
    HHCDI002I DASD initialization unsuccessful
    Meaning
    Initialization of the requested DASD volume was not successful.
    Action
    Refer to preceding error messages to determine the cause.
    Issued by
    dasdinit.c, function main


    If you have a question about Hercules, see the Hercules Frequently-Asked Questions page.


    back

    Last updated $Date: 2007-10-06 14:44:28 -0500 (Sat, 06 Oct 2007) $ $Revision: 4460 $

    hercules-3.07/html/hercmsdl.html000644 000765 000765 00000162546 11143760535 020421 0ustar00jmaynardjmaynard000000 000000 Hercules Version 3: System Messages: DL - dasdload

    Hercules Version 3: System Messages: DL - dasdload

    This page describes the messages for the Hercules S/370, ESA/390, and z/Architecture emulator utility program dasdload.

    Information messages (I suffix) from dasdload have an associated message level. They are only issued if the third argument to dasdload, the verbosity level, is no lower than the message level. The default verbosity level is 1, which causes level 0 and 1 information messages to be issued.

    Messages

    HHCDL001E Cannot open filename: error
    Meaning
    The control file named filename cannot be opened. The error is described by error.
    Action
    Correct the error and rerun dasdload.
    Issued by
    dasdload.c, function main
    HHCDL002E Volume serial statement missing from filename
    Meaning
    The control file named filename does not contain a volume serial statement. One is required.
    Action
    Supply a volume serial statement and rerun dasdload.
    Issued by
    dasdload.c, function main
    HHCDL003E Volume serial serial in filename line lineno is not valid
    Meaning
    The volume serial serial supplied in line lineno of the control file named filename is not valid. It must be from one to six characters long.
    Action
    Supply a valid volume serial and rerun dasdload.
    Issued by
    dasdload.c, function main
    HHCDL004E Device type type in filename line lineno is not recognized
    Meaning
    The device type type specified in line lineno of the control file named filename is not a supported CKD device.
    Action
    Specify a supported CKD device type and rerun dasdload.
    Issued by
    dasdload.c, function main
    HHCDL005E count in filename line lineno is not a valid cylinder count
    Meaning
    The requested number, count, of cylinders for the volume in line lineno of the control file named filename is invalid. It must be a decimal number.
    Action
    Supply a valid cylinder count and rerun dasdload.
    Issued by
    dasdload.c, function main
    HHCDL006I Creating type volume serial: tracks trks/cyl, length bytes/track
    Meaning
    The volume named serial, of type type, is being created, with tracks tracks per cylinder and length bytes per track.
    Message level
    0
    Issued by
    dasdload.c, function main
    HHCDL007E Cannot create filename
    Meaning
    The DASD image file named filename cannot be created. A previous message described the problem.
    Action
    Correct the reported error and rerun dasdload.
    Issued by
    dasdload.c, function main
    HHCDL008E Cannot open filename
    Meaning
    The DASD image file named filename could not be opened. A previous message described the problem.
    Action
    Correct the reported error and rerun dasdload.
    Issued by
    dasdload.c, function main
    HHCDL009I Loading type volume serial
    Meaning
    The newly created volume with serial serial, of type type, is being loaded.
    Message level
    0
    Issued by
    dasdload.c, function main
    HHCDL010E Cannot obtain storage for DSCB pointer array: error
    Meaning
    An attempt to obtain storage for the array of DSCB pointers, which will populate the VTOC, failed. The error is described by error.
    Action
    Correct the error and rerun dasdload.
    Issued by
    dasdload.c, function process_control_file
    HHCDL011E Invalid statement in filename line lineno
    Meaning
    An invalid control statement was found at line lineno of the control file named filename.
    Action
    Correct the invalid statement and rerun dasdload.
    Issued by
    dasdload.c, function process_control_file
    HHCDL012I Creating dataset dsn at cyl cylinder head head
    Meaning
    The dataset named dsn is being created. It begins at cylinder cylinder, head head.
    Message level
    1
    Issued by
    dasdload.c, function process_control_file
    HHCDL013I Dataset dsn contains size tracks
    Meaning
    The dataset named dsn is size tracks long.
    Message level
    2
    Issued by
    dasdload.c, function process_control_file
    HHCDL014I Free space starts at cyl cylinder head head
    Meaning
    Free space on the volume begins at cylinder cylinder, head head, and extends to the end of the volume.
    Message level
    1
    Issued by
    dasdload.c, function process_control_file
    HHCDL015W Volume exceeds cylinders
    Meaning
    The amount of space used on the volume exceeds the number of cylinders, cylinders, requested in the control file. The number of cylinders was explicitly requested instead of being allowed to default to the size of a full volume for the device type. The volume has been extended to accomodate the data written.
    Action
    Specify more cylinders in the control file, or allow the number to default.
    Issued by
    dasdload.c, function process_control_file
    HHCDL016I Total of count cylinders written to filename
    Meaning
    A total of count cylinders have been written to the DASD image file named filename.
    Message level
    0
    Issued by
    dasdload.c, function process_control_file
    HHCDL017I Updating VTOC pointer pointer
    Meaning
    The pointer to the VTOC in the volume label is being updated to point to the VTOC, at location pointer.
    Message level
    5
    Issued by
    dasdload.c, function process_control_file
    HHCDL018E Cannot read VOL1 record
    Meaning
    An attempt to read the volume label failed. A previous message described the error.
    Action
    Correct the error and rerun dasdload.
    Issued by
    dasdload.c, function process_control_file
    HHCDL019E Cannot read filename line lineno: error
    Meaning
    An error was encountered while trying to read the statement at line number lineno of the control file named filename. The error is described by error.
    Action
    Correct the error and rerun dasdload.
    Issued by
    dasdload.c, function read_ctrl_stmt
    HHCDL020E Line too long in filename line lineno
    Meaning
    The line at line number lineno of the control file named filename is too long to be processed. This error can be caused by failing to terminate the last line with an end-of-line marker.
    Action
    Correct the error and rerun dasdload.
    Issued by
    dasdload.c, function read_ctrl_stmt
    HHCDL021E DSNAME or initialization method missing
    Meaning
    Either the dataset name, or the method to be used to initialize it, is missing from the control file. Both are required.
    Action
    Supply the missing value and rerun dasdload.
    Issued by
    dasdload.c, function parse_ctrl_stmt
    HHCDL022E Invalid initialization method: method
    Meaning
    The method specified to initialize the dataset, method, is invalid. It must be one of xmit, vs, empty, dip, cvol, vtoc, or seq.
    Action
    Correct the initialization method and rerun dasdload.
    Issued by
    dasdload.c, function parse_ctrl_stmt
    HHCDL023E Initialization file name missing
    Meaning
    A dataset was specified as being initialized by either the xmit, vs, or seq initialization methods, but no source file was specified to provide the data to be loaded.
    Action
    Specify a source file name, or specify the empty dataset initialization method if the dataset is not to be loaded.
    Issued by
    dasdload.c, function parse_ctrl_stmt
    HHCDL024E Invalid allocation units: units
    Meaning
    The allocation unit specified, units, is invalid. It must be either cyl or trk.
    Action
    Specify a valid allocation unit and rerun dasdload.
    Issued by
    dasdload.c, function parse_ctrl_stmt
    HHCDL025E Invalid primary space: space
    Meaning
    The primary space requested, space, is not a valid decimal number greater than 0.
    Action
    Specify a valid space request and rerun dasdload.
    Issued by
    dasdload.c, function parse_ctrl_stmt
    HHCDL026E Invalid secondary space: space
    Meaning
    The secondary space requested, space, is not a valid decimal number greater than 0.
    Action
    Specify a valid space request and rerun dasdload.
    Issued by
    dasdload.c, function parse_ctrl_stmt
    HHCDL027E Invalid directory space: space
    Meaning
    The PDS directory space requested, space, is not a valid decimal number greater than 0.
    Action
    Specify a valid space request and rerun dasdload.
    Issued by
    dasdload.c, function parse_ctrl_stmt
    HHCDL028E Invalid dataset organization: dsorg
    Meaning
    The requested dataset organization, dsorg, is invalid. It must be one of is, ps, da, or po.
    Action
    Specify a valid dataset organization and rerun dasdload.
    Issued by
    dasdload.c, function parse_ctrl_stmt
    HHCDL029E Invalid record format: recfm
    Meaning
    The requested record format, recfm, is invalid. It must be one of f, fb, fbs, v, vb, vbs, or u.
    Action
    Specify a valid record format and rerun dasdload.
    Issued by
    dasdload.c, function parse_ctrl_stmt
    HHCDL030E Invalid logical record length: lrecl
    Meaning
    The requested logical record length, lrecl, is invalid. It must be a decimal number between 0 and 32767.
    Action
    Specify a valid logical record length and rerun dasdload.
    Issued by
    dasdload.c, function parse_ctrl_stmt
    HHCDL031E Invalid block size: blksize
    Meaning
    The requested block size, blksize, is invalid. It must be a decimal number between 0 and 32767.
    Action
    Specify a valid block size and rerun dasdload.
    Issued by
    dasdload.c, function parse_ctrl_stmt
    HHCDL032E Invalid key length: keylen
    Meaning
    The requested key length, keylen, is invalid. It must be a decimal number between 0 and 255.
    Action
    Specify a valid key length and rerun dasdload.
    Issued by
    dasdload.c, function parse_ctrl_stmt
    HHCDL033E CCHH=cchh not found in extent table
    Meaning
    The absolute track address, cchh, was not found in the table listing the locations occupied by the dataset being loaded. There is likely a problem with the input file.
    Action
    Correct the input file and rerun dasdload.
    Issued by
    dasdload.c, function calculate_ttr
    HHCDL034E Cannot open filename: error
    Meaning
    The file named filename, which was specified as the source of IPL text to be written to the volume, could not be opened. The error is described by error.
    Action
    Correct the error and rerun dasdload.
    Issued by
    dasdload.c, function read_ipl_text
    HHCDL035E Cannot read filename: error
    Meaning
    An error was encountered while reading the IPL text file named filename. The error is described by error. If no error is reported, the file did not contain an integral number of 80-byte card images.
    Action
    Correct the reported error, or supply a valid IPL text file consisting of 80-byte card images, and rerun dasdload.
    Issued by
    dasdload.c, function read_ipl_text
    HHCDL036E filename is not a valid object file
    Meaning
    The IPL text file named filename is not a valid object file. A record read from the file did not contain the required flag in the first byte.
    Action
    Supply a valid object file and rerun dasdload.
    Issued by
    dasdload.c, function read_ipl_text
    HHCDL037I IPL text address=addr length=length
    Meaning
    The object code from the current record of the IPL text file will be loaded into memory at address address, and is length bytes long.
    Message level
    5
    Issued by
    dasdload.c, function read_ipl_text
    HHCDL038E TXT record in filename has invalid count length
    Meaning
    A text record in the IPL text file named filename has an invalid length, length. The length cannot exceed 56.
    Action
    Supply a valid IPL text file and rerun dasdload.
    Issued by
    dasdload.c, function read_ipl_text
    HHCDL039E IPL text in filename exceeds buflen bytes
    Meaning
    The IPL text file named filename is too long to fit in the available space on the volume. The IPL text cannot exceed buflen bytes in length.
    Action
    Supply a shorter IPL text file, or specify a volume with a larger track size, and rerun dasdload.
    Issued by
    dasdload.c, function read_ipl_text
    HHCDL040E Input record CCHHR=cchhr exceeds output device track size
    Meaning
    The block to be written at absolute address cchhr is too large to fit on a track on the disk being loaded.
    Action
    Specify a device with a larger track size and rerun dasdload.
    Issued by
    dasdload.c, function write_block
    HHCDL041E Dataset exceeds extent size: reltrk=track, maxtrk=maxtrk
    Meaning
    The data to be written to the dataset is too large for the space requested for it. If the space request was allowed to default, the input file is corrupt.
    Action
    If the space request was made explicitly, request more space. If the request was defaulted, supply a valid input file. Rerun dasdload.
    Issued by
    dasdload.c, function write_block
    HHCDL042E Input record CCHHR=cchhr exceeds virtual device track size
    Meaning
    The block to be written at absolute address cchhr is too large to fit on a track on the disk being loaded. In addition, this message being issued instead of message HHCDL040E indicates an internal inconsistency in the way Hercules computes the space available on a track.
    Action
    Specify a device with a larger track size and rerun dasdload. Report the inconsistenct to the Hercules development team.
    Issued by
    dasdload.c, function write_block
    HHCDL043E filename cyl cylinder head head read error
    Meaning
    The data at cylinder cylinder, head head of the disk image file named filename could not be read in order to be updated. A previous message described the error.
    Action
    Correct the previously reported error and rerun dasdload.
    Issued by
    dasdload.c, function update_block
    HHCDL044E filename cyl cylinder head head invalid track header header
    Meaning
    The track header header at cylinder cylinder, head head in the disk image file named filename contained an address that did not match the actual address.
    Action
    Rerun dasdload. If the error persists, report it to the Hercules development team.
    Issued by
    dasdload.c, function update_block
    HHCDL045E filename cyl cylinder head head record record record not found
    Meaning
    The record requested for update at cylinder cylinder, head head, record record of the DASD image file named filename was not found.
    Action
    Rerun dasdload. If the error persists, report it to the Hercules development team.
    Issued by
    dasdload.c, function update_block
    HHCDL046E Cannot update cyl cylinder head head rec record: Unmatched KL/DL
    Meaning
    The record to be written at cylinder cylinder, head head, recordhead does not have the same key or data length as the record that already exists at that location. This is not allowed for a record update operation.
    Action
    Rerun dasdload. If the error persists, report it to the Hercules development team.
    Issued by
    dasdload.c, function update_block
    HHCDL047E filename cyl cylinder head head read error
    Meaning
    A read error was encountered when reading the track at cylinder cylinder, head head, in the disk image file named filename. A previous message described the error.
    Action
    Correct the error reported by the previous message and rereun dasdload.
    Issued by
    dasdload.c, function update_block
    HHCDL048I Updating cyl cylinder head head rec record kl keylen dl datalen
    Meaning
    The record at cylinder cylinder, head head, record record is being updated. It has a key length of keylen and data length datalen.
    Message level
    4
    Issued by
    dasdload.c, function update_block
    HHCDL049E Cannot obtain storage for DSCB: error
    Meaning
    An attempt to obtain storage to build a DSCB to describe a dataset on the volume being loaded failed. The error is described by error.
    Action
    Correct the error and rerun dasdload.
    Issued by
    dasdload.c, function build_format1_dscb
    HHCDL050E DSCB count exceeds maximum, increase MAXDSCB
    Meaning
    There are too many datasets on the volume being loaded, and an internal structure in dasdload is full.
    Action
    Increase the value of the symbol MAXDSCB in the source program and recompile dasdload, then rerun the program.
    Issued by
    dasdload.c, function build_format1_dscb
    HHCDL051E Cannot obtain storage for DSCB: error
    Meaning
    An attempt to obtain storage to build a DSCB to describe the VTOC on the volume being loaded failed. The error is described by error.
    Action
    Correct the error and rerun dasdload.
    Issued by
    dasdload.c, function build_format4_dscb
    HHCDL052E DSCB count exceeds maximum, increase MAXDSCB
    Meaning
    There are too many datasets on the volume being loaded, and an internal structure in dasdload is full.
    Action
    Increase the value of the symbol MAXDSCB in the source program and recompile dasdload, then rerun the program.
    Issued by
    dasdload.c, function build_format4_dscb
    HHCDL053E Cannot obtain storage for DSCB: error
    Meaning
    An attempt to obtain storage to build a DSCB to describe the free space on the volume being loaded failed. The error is described by error.
    Action
    Correct the error and rerun dasdload.
    Issued by
    dasdload.c, function build_format5_dscb
    HHCDL054E DSCB count exceeds maximum, increase MAXDSCB
    Meaning
    There are too many datasets on the volume being loaded, and an internal structure in dasdload is full.
    Action
    Increase the value of the symbol MAXDSCB in the source program and recompile dasdload, then rerun the program.
    Issued by
    dasdload.c, function build_format5_dscb
    HHCDL055E VTOC too small, tracks tracks required
    Meaning
    The VTOC allocation of tracks is too small to hold the VTOC.
    Action
    Specify at least tracks tracks for the VTOC and rerun dasdload.
    Issued by
    dasdload.c, function write_vtoc
    HHCDL056E Error reading VTOC cyl cylinder head head
    Meaning
    The first track of the VTOC could not be read so it could be updated. A previous message described the error.
    Action
    Correct the error reported by the previous message and rerun dasdload.
    Issued by
    dasdload.c, function write_vtoc
    HHCDL057I VTOC starts at cyl cylinder head head and is tracks tracks
    Meaning
    The VTOC on the volume being loaded starts at cylinder cylinder, head head and is tracks tracks long.
    Message level
    1
    Issued by
    dasdload.c, function write_vtoc
    HHCDL058I Format format DSCB CCHHR=cchhr (TTR=ttr) dsname
    Meaning
    The format format DSCB is located at absolute address cchhr, and relative address within the VTOC ttr. If format is 1, the dataset described by the DSCB is named dsname.
    Message level
    4
    Issued by
    dasdload.c, function write_vtoc
    HHCDL059I Format 0 DSCB CCHHR cchhr (TTR=ttr)
    Meaning
    A format 0 (empty) DSCB is located at absolute address cchhr, and relative address within the VTOC ttr.
    Message level
    4
    Issued by
    dasdload.c, function write_vtoc
    HHCDL060E Error reading track cyl cylinder head head
    Meaning
    An error was encountered reading the track at cylinder cyl, head head. A previous message described the error.
    Action
    Correct the error reported by the previous message and rerun dasdload.
    Issued by
    dasdload.c, function write_vtoc
    HHCDL061E Incomplete text unit
    Meaning
    An text unit read from the input file was too short to contain a valid header. The input data is probably corrupt.
    Action
    Supply a valid input file and rerun dasdload.
    Issued by
    dasdload.c, function next_tu
    HHCDL062I position tuname key fields
    Meaning
    The text unit at position of the input buffer has the name tuname and the numeric key value key. There are fields fields in the text unit.
    Message level
    4
    Issued by
    dasdload.c, function next_tu
    HHCDL063E Too many fields in text unit
    Meaning
    A text unit was read from the input file that had too many fields in the header for that type of text unit. The input file is probably corrupt.
    Action
    Supply a valid input file and rerun dasdload.
    Issued by
    dasdload.c, function next_tu
    HHCDL064E Incomplete text unit
    Meaning
    An text unit read from the input file was too short to contain a valid field length. The input data is probably corrupt.
    Action
    Supply a valid input file and rerun dasdload.
    Issued by
    dasdload.c, function next_tu
    HHCDL065E Incomplete text unit
    Meaning
    An text unit read from the input file was shorter than the length in the field header. The input data is probably corrupt.
    Action
    Supply a valid input file and rerun dasdload.
    Issued by
    dasdload.c, function next_tu
    HHCDL066E filename read error: error
    Meaning
    An error was encountered when reading the input file named filename. The error is described by error.
    Action
    Correct the error and rerun dasdload.
    Issued by
    dasdload.c, function read_xmit_rec
    HHCDL067E filename invalid segment header: header
    Meaning
    A segment read from the file named filename has an invalid header, header. The input file is probably corrupt.
    Action
    Supply a valid input file and rerun dasdload.
    Issued by
    dasdload.c, function read_xmit_rec
    HHCDL068E filename first segment indicator expected
    Meaning
    A segment read from the file named filename should have the first segment indicator set, but does not. The input file is probably corrupt.
    Action
    Supply a valid input file and rerun dasdload.
    Issued by
    dasdload.c, function read_xmit_rec
    HHCDL069E filename first segment indicator not expected
    Meaning
    A segment read from the file named filename should not have the first segment indicator set, but does. The input file is probably corrupt.
    Action
    Supply a valid input file and rerun dasdload.
    Issued by
    dasdload.c, function read_xmit_rec
    HHCDL070E filename control record indicator mismatch
    Meaning
    There was a mismatch between the first segment and the control record. The input file is probably corrupt.
    Action
    Supply a valid input file and rerun dasdload.
    Issued by
    dasdload.c, function read_xmit_rec
    HHCDL071E filename read error: error
    Meaning
    An error was encountered when reading a segment from the input file named filename. The error is described by error.
    Action
    Correct the error and rerun dasdload.
    Issued by
    dasdload.c, function read_xmit_rec
    HHCDL072E filename read error: error
    Meaning
    An error was encountered when reading a COPYR1 record from the input file named filename. The error is described by error.
    Action
    Correct the error and rerun dasdload.
    Issued by
    dasdload.c, function read_vs_rec
    HHCDL073E filename read error: error
    Meaning
    An error was encountered when reading a COPYR2 record from the input file named filename. The error is described by error.
    Action
    Correct the error and rerun dasdload.
    Issued by
    dasdload.c, function read_vs_rec
    HHCDL074E filename read error: error
    Meaning
    An error was encountered when reading a data block header from the input file named filename. The error is described by error.
    Action
    Correct the error and rerun dasdload.
    Issued by
    dasdload.c, function read_vs_rec
    HHCDL075E filename read error: error
    Meaning
    An error was encountered when reading a data block from the input file named filename. The error is described by error.
    Action
    Correct the error and rerun dasdload.
    Issued by
    dasdload.c, function read_vs_rec
    HHCDL076I File number: number
    Meaning
    The file being processed is number number.
    Message level
    4
    Issued by
    dasdload.c, function process_inmr02
    HHCDL077E Invalid text unit at offset offset
    Meaning
    An invalid text unit was read from position offset. A previous message described the error. The input file is probably corrupt.
    Action
    Supply a valid input file and rerun dasdload.
    Issued by
    dasdload.c, function process_inmr02
    HHCDL078I File filenum: DSNAME=dsname
    Meaning
    The dataset name of file number filenum is dsname.
    Message level
    2
    Issued by
    dasdload.c, function process_inmr02
    HHCDL079I DSORG=dsorg RECFM=recfm LRECL=lrecl BLKSIZE=blksize KEYLEN=keylen DIRBLKS=dirblks
    Meaning
    For the dataset listed in the preceding HHCDL078I message, the dataset organization is dsorg, the record format is recfm, the logical record length is lrecl, the block size is blksize, the key length is keylen, and the directory block count is dirblks.
    Message level
    2
    Issued by
    dasdload.c, function process_inmr02
    HHCDL080E Invalid text unit at offset offset
    Meaning
    An invalid text unit was read from position offset. A previous message described the error. The input file is probably corrupt.
    Action
    Supply a valid input file and rerun dasdload.
    Issued by
    dasdload.c, function process_inmrxx
    HHCDL081E COPYR1 record length is invalid
    Meaning
    The length of the COPYR1 record is invalid. The input file is probably corrupt.
    Action
    Supply a valid input file and rerun dasdload.
    Issued by
    dasdload.c, function process_copyr1
    HHCDL082E COPYR1 header identifier not correct
    Meaning
    The header identifier of the COPYR1 record is invalid. The input file is probably corrupt.
    Action
    Supply a valid input file and rerun dasdload.
    Issued by
    dasdload.c, function process_copyr1
    HHCDL083E COPYR1 unload format is unsupported
    Meaning
    The COPYR1 record indicates that the file was unloaded in a formatthat is not supported by dasdload. The file may be corrupt, or it may simply be in a newer format than is supported by this version of dasdload.
    Action
    Supply a supported input file and rerun dasdload.
    Issued by
    dasdload.c, function process_copyr1
    HHCDL084I Original dataset: DSORG=dsorg RECFM=recfm LRECL=lrecl BLKSIZE=blksize KEYLEN=keylen
    Meaning
    For the original dataset, the dataset organization is dsorg, the record format is recfm, the logical record length is lrecl, the block size is blksize, the key length is keylen, and the directory block count is dirblks.
    Message level
    2
    Issued by
    dasdload.c, function process_copyr1
    HHCDL085I Dataset was unloaded from device type ucbtype (device)
    Meaning
    The dataset was unloaded from a device device, with UCB device type ucbtype.
    Message level
    2
    Issued by
    dasdload.c, function process_copyr1
    HHCDL086I Original device has cylinders cyls and heads heads
    Meaning
    The device listed in the preceding HHCDL085I message has cylinders cylinders and heads heads.
    Message level
    2
    Issued by
    dasdload.c, function process_copyr1
    HHCDL087E COPYR2 record length is invalid
    Meaning
    The length of the COPYR2 record just read is not valid. The input file is probably corrupt.
    Action
    Supply a valid input file and rerun dasdload.
    Issued by
    dasdload.c, function process_copyr2
    HHCDL088E Invalid number of extents extents
    Meaning
    The number of extents reported in the COPYR2 record is invalid, either less than 1 or more than 16. The input file is probably corrupt.
    Action
    Supply a valid input file and rerun dasdload.
    Issued by
    dasdload.c, function process_copyr2
    HHCDL089I Extent extent: Begin CCHH=begcchh End CCHH=endcchh Tracks=tracks
    Meaning
    For extent number extent, the extent starts at cylinder and head begcchh, and ends at endcchh, for a total of tracks tracks.
    Message level
    4
    Issued by
    dasdload.c, function process_copyr2
    HHCDL090I End of directory
    Meaning
    The end of the PDS directory has been reached.
    Message level
    3
    Issued by
    dasdload.c, function process_dirblk
    HHCDL091E Directory block record length is invalid
    Meaning
    The directory block read from the input file has the wrong length. It must be 276 bytes long. The input file is probably corrupt.
    Action
    Supply a valid input file and rerun dasdload.
    Issued by
    dasdload.c, function process_dirblk
    HHCDL092E Cannot obtain storage for directory block: error
    Meaning
    An attempt to obtain storage for the directory block being processed failed. The error is described by error.
    Action
    Correct the error and rerun dasdload.
    Issued by
    dasdload.c, function process_dirblk
    HHCDL093E Number of directory blocks exceeds maxdblk, increase MAXDBLK
    Meaning
    The number of directory blocks in the dataset being processed exceeds the size of an internal control structure. The maximum number is maxdblk.
    Action
    Increase the value of the constant MAXDBLK in the program source and recompile dasdload.
    Issued by
    dasdload.c, function process_dirblk
    HHCDL094E Directory block byte count is invalid
    Meaning
    The length of the current directory block is invalid. The input file is probably corrupt.
    Action
    Supply a valid input file and rerun dasdload.
    Issued by
    dasdload.c, function process_dirblk
    HHCDL095I (Alias|Member) memname TTR=ttr
    Userdata=userdata
    Meaning
    The alias or member named memname is located at relative address ttr. If user data is present, it is printed as userdata.
    Message level
    3
    Issued by
    dasdload.c, function process_dirblk
    HHCDL096I Member name TTR=oldttr replaced by newttr
    Meaning
    In the directory entry for member name, the old pointer to the mamber oldttr was replaced by the member's actual relative address newttr.
    Message level
    4
    Issued by
    dasdload.c, function replace_ttr
    HHCDL097E Member name TTR=ttrnot found in dataset
    Meaning
    A request was made to update the directory entry for the member named name, but there was no directory entry to update.
    Action
    This is likely an internal logic error. Report the error to the Hercules development team.
    Issued by
    dasdload.c, function replace_ttr
    HHCDL098I Updating note list for member name at TTR=ttr CCHHR=cchhr
    Meaning
    The note list for the member named name, at relative address ttr, absolute address cchhr, is being updated.
    Message level
    4
    Issued by
    dasdload.c, function update_note_list
    HHCDL099E filename cyl cylinder head head read error
    Meaning
    An attempt to read the track in the DASD image file named filename at cylinder cylinder, head head, failed. A previous error described the failure.
    Action
    Correct the error reported by the previous message and rerun dasdload.
    Issued by
    dasdload.c, function update_note_list
    HHCDL100E filename cyl cylinder head head invalid track header header
    Meaning
    The header, header, of the track in the DASD image file named filename at cylinder cylinder, head head did not agree with the actual address of the track. This is probably an internal logic error.
    Action
    Report the error to the Hercules development team.
    Issued by
    dasdload.c, function update_note_list
    HHCDL101E filename cyl cylinder head head rec record note list record not found
    Meaning
    A request was made to update a note list record at cylinder cylinder, head head, record record, but the record was not found. The input dataset may be corrupt.
    Action
    Supply a valid input dataset and rerun dasdload.
    Issued by
    dasdload.c, function update_note_list
    HHCDL102E Member member note list at cyl cylinder head head rec record dlen datalen is too short for numttrs TTRs
    Meaning
    The data length datalen of the note list record for member member at cylinder cylinder, head head, record record, is too short to contain the requested number, numttrs, of record pointers. The input dataset is probably corrupt.
    Action
    Supply a valid input dataset and rerun dasdload.
    Issued by
    dasdload.c, function update_note_list
    HHCDL103E filename track read error cyl cylinder head head
    Meaning
    An attempt to read the track in the DASD image file named filename at cylinder cylinder, head head, failed. A previous error described the failure.
    Action
    Correct the error reported by the previous message and rerun dasdload.
    Issued by
    dasdload.c, function update_note_list
    HHCDL104I Updating cyl cylinder head head rec record kl keylen dl datalen
    Meaning
    The record at cylinder cylinder, head head, record record, with key length keynel and data length datalen isbeing updated.
    Message level
    4
    Issued by
    dasdload.c, function update_note_list
    HHCDL105E Directory block byte count is invalid
    Meaning
    The length of the current directory block is invalid. The input file is probably corrupt.
    Action
    Supply a valid input file and rerun dasdload.
    Issued by
    dasdload.c, function update_dirblk
    HHCDL106E Cannot open file filename: error
    Meaning
    An attempt to open the IEBCOPY input file named filename failed. The error is described by error.
    Action
    Correct the error and rerun dasdload.
    Issued by
    dasdload.c, function process_iebcopy_file
    HHCDL107E Cannot obtain input buffer: error
    Meaning
    An attempt to obtain a 64K byte input buffer for reaading the IEBCOPY input file failed. The error is described by error.
    Action
    Correct the error and rerun dasdload.
    Issued by
    dasdload.c, function process_iebcopy_file
    HHCDL108E Cannot obtain storage for directory block array:error
    Meaning
    An attempt to obtain storage for the internal array used to store directory blocks failed. The error is described by error.
    Action
    Correct the error and rerun dasdload.
    Issued by
    dasdload.c, function process_iebcopy_file
    HHCDL109E Cannot obtain storage for TTR table: error
    Meaning
    An attempt to obtain storage for the internal array used to store track pinters for later conversion failed. The error is described by error.
    Action
    Correct the error and rerun dasdload.
    Issued by
    dasdload.c, function process_iebcopy_file
    HHCDL110I Processing file filename
    Meaning
    The input file named filename is being processed.
    Message level
    1
    Issued by
    dasdload.c, function process_iebcopy_file
    HHCDL111I Control record: recname length length
    Meaning
    A control record named recname of length length has been read.
    Message level
    4
    Issued by
    dasdload.c, function process_iebcopy_file
    HHCDL112I File number: filenum ((not) selected)
    Meaning
    The data file, number filenum, was (or was not) selected for processing.
    Message level
    4
    Issued by
    dasdload.c, function process_iebcopy_file
    HHCDL113I Data record: length length
    Meaning
    A data record of length length has been read.
    Message level
    4
    Issued by
    dasdload.c, function process_iebcopy_file
    HHCDL114E write error: input record CCHHR=cchhr (TTR=ttr) KL=keylen DL=datalen
    Meaning
    An error was encountered writing the data record at absolute address cchhr, relative address ttr, with key length keylen and data length datalen. A previous message described the error.
    Action
    Correct the error described by the previous message and rerun dasdload.
    Issued by
    dasdload.c, function process_iebcopy_file
    HHCDL115I CCHHR=incchhr (TTR=inttr) KL=keylen DL=datalen -> CCHHR=outcchhr (TTR=outttr)
    Meaning
    The record at absolute address incchhr, relative address inttr, with key length keylen and data length datalen, is being written to the output DASD image at absolute address outcchhr, relative address outttr.
    Message level
    4
    Issued by
    dasdload.c, function process_iebcopy_file
    HHCDL116E TTR count exceeds maxttr, increase MAXTTR
    Meaning
    The list of relative address pointers exceeds the size of the internal array used to contain them, maxttr.
    Action
    Increase the constant MAXTTR in the program source and recompile dasdload.
    Issued by
    dasdload.c, function process_iebcopy_file
    HHCDL0117I Catalog block at cyl cylinder head head rec record
    Meaning
    A catalog record has been written to disk at cylinder cylinder, head head, and record record.
    Message level
    4
    Issued by
    dasdload.c, function cvol_initialize
    HHCDL0118I Catalog block at cyl cylinder head head rec record
    Meaning
    A catalog index record has been written to disk at cylinder cylinder, head head, and record record.
    Message level
    4
    Issued by
    dasdload.c, function cvol_initialize
    HHCDL0119I Catalog block at cyl cylinder head head rec record
    Meaning
    An empty catalog record has been written to disk at cylinder cylinder, head head, and record record.
    Message level
    4
    Issued by
    dasdload.c, function cvol_initialize
    HHCDL120I DIP complete at cyl cylinder head head record record
    Meaning
    The LOGREC dataset has been initialized. The last block written was at cylinder cylinder, head head, record record.
    Message level
    3
    Issued by
    dasdload.c, function dip_initialize
    HHCDL121E SEQ dsorg must be PS or DA: dsorg=dsorg
    Meaning
    The dataset organization specified for the input dataset was dsorg. It must be either PS or DA, but is not.
    Action
    Specify a valid dataset organization for sequential file processing, or specify the correct processing option for the file being loaded, and rerun dasdload.
    Issued by
    dasdload.c, function seq_initialize
    HHCDL122E SEQ recfm must be F or FB: recfm=recfm
    Meaning
    The record format specified for the input dataset was recfm. It must be either F or FB, but is not.
    Action
    Specify a valid record format for sequential file processing and rerun dasdload.
    Issued by
    dasdload.c, function seq_initialize
    HHCDL123E SEQ invalid lrecl or blksz: lrecl=lrecl blksz=blksz
    Meaning
    The logical record length specified for the input dataset was lrecl, and the block size was blksz. Either the block size was not a multiple of the logical record length and the record format was specified as FB, or the block size was different from the logical record length and the record format was specified as F.
    Action
    Specify a valid logical record length and block size for sequential file processing and rerun dasdload.
    Issued by
    dasdload.c, function seq_initialize
    HHCDL124E SEQ keyln must be 0 for blocked files
    Meaning
    The key length was specified as nonzero and the record format was specified as FB. This combination is invalid.
    Action
    If a key is required, specify a record format of F. If no key is required, specify a key length of 0. Rerun dasdload.
    Issued by
    dasdload.c, function seq_initialize
    HHCDL125E Cannot open filename: error
    Meaning
    An error was encountered when attempting to open the input file named filename. The error is described by error.
    Action
    Correct the error and rerun dasdload.
    Issued by
    dasdload.c, function seq_initialize
    HHCDL126E Cannot stat filename: error
    Meaning
    An error was encountered when attempting to obtain the size of the file named filename. The error is described by error.
    Action
    Correct the error and rerun dasdload.
    Issued by
    dasdload.c, function seq_initialize
    HHCDL127E filename cyl cylinder head head read error
    Meaning
    An attempt to read the track in the DASD image file named filename at cylinder cylinder, head head, failed. A previous error described the failure.
    Action
    Correct the error reported by the previous message and rerun dasdload.
    Issued by
    dasdload.c, function seq_initialize
    HHCDL128E filename read error: error
    Meaning
    An error was encountered reading the input file named filename. The error is described by error.
    Action
    Correct the error and rerun dasdload.
    Issued by
    dasdload.c, function seq_initialize


    If you have a question about Hercules, see the Hercules Frequently-Asked Questions page.


    back

    Last updated $Date: 2007-10-06 14:44:28 -0500 (Sat, 06 Oct 2007) $ $Revision: 4460 $

    hercules-3.07/html/hercmsds.html000644 000765 000765 00000024060 11143760535 020414 0ustar00jmaynardjmaynard000000 000000 Hercules Version 3: System Messages: DS - dasdisup

    Hercules Version 3: System Messages: DS - dasdisup

    This page describes the messages for the Hercules S/370, ESA/390, and z/Architecture emulator utility program dasdisup.

    Messages

    HHCDS001E Cannot obtain storage for member array: error
    Meaning
    An attempt to obtain storage for the array of SYS1.SVCLIB members failed. The error is described by error.
    Action
    Correct the error and rerun dasdisup.
    Issued by
    dasdisup.c, function main
    HHCDS002I End of directory: count members selected
    Meaning
    The end of the SYS1.SVCLIB directory has been reached. count members have been selected for processing.
    Issued by
    dasdisup.c, function main
    HHCDS003E Directory block byte count is invalid
    Meaning
    The length of the directory block read is invalid. The SYS1.SVCLIB directory is probably corrupt.
    Action
    Rebuild SYS1.SVCLIB and rerun dasdisup.
    Issued by
    dasdisup.c, function process_dirblk
    HHCDS004E Number of members exceeds MAX_MEMBERS
    Meaning
    SYS1.SVCLIB has too many members to fit in the array used to store their information.
    Action
    Increase the value of MAX_MEMBERS in dasdisup.c and recompile the program, then run it again.
    Issued by
    dasdisup.c, function process_dirblk
    HHCDS005E Member member TTR count is zero
    Meaning
    The member named member has no data associated with it. Since aliases have been skipped already, this means that the SYS1.SVCLIB directory is corrupt.
    Action
    Rebuild SYS1.SVCLIB and run dasdisup again.
    Issued by
    dasdisup.c, function process_dirblk
    HHCDS006W Member member is not single text record
    Meaning
    The member named member is not contained in a single text record. This is an invalid condition. The member will be skipped later, and message HHCDS011E will be issued.
    Action
    If this member must be processed, rebuild SYS1.SVCLIB and rerun dasdisup.
    Issued by
    dasdisup.c, function process_dirblk
    HHCDS007W Member member size size exceeds X'7F8' bytes
    Meaning
    The member named member is too long. The maximum length of an OS/360 SVC load module is X'7F8' (2040 decimal) bytes. The member will be processed, but OS/360 will have problems with it.
    Action
    Correct the member in SYS1.SVCLIB and rerun dasdisup.
    Issued by
    dasdisup.c, function process_dirblk
    HHCDS008W Member member size size is not a multiple of 8
    Meaning
    The member named member is not a multiple of 8 bytes long. Its actual size is size. This is not valid for an OS/360 load module. OS/360 will issue an ABEND when an attempt is made to load the module.
    Action
    Correct the member in SYS1.SVCLIB and rerun dasdisup.
    Issued by
    dasdisup.c, function process_dirblk
    HHCDS009I Alias alias skipped
    Meaning
    The alias named alias has been skipped, since no processing is necessary for it.
    Issued by
    dasdisup.c, function resolve_xctltab
    HHCDS010I Member member skipped
    Meaning
    The member named member has been skipped, since it does not have an XCTL table.
    Action
    If the member should have an XCTL table, rebuild it in SYS1.SVCLIB and rerun dasdisup.
    Issued by
    dasdisup.c, function resolve_xctltab
    HHCDS011E Member member has multiple text records
    Meaning
    The member named member has multiple text records. This is not a valid condition for an OS/360 SVC module. The member will not be processed. Message HHCDS006W was issued for this member earlier.
    Action
    If this member must be processed, rebuild it in SYS1.SVCLIB and rerun dasdisup.
    Issued by
    dasdisup.c, function resolve_xctltab
    HHCDS012E Member member has invalid TTR ttr
    Meaning
    The pointer to the text record for the member named member is invalid. The pointer found is ttr. The member cannot be located to be processed. The SYS1.SVCLIB directory is probably corrupt.
    Action
    Rebuild SYS1.SVCLIB and rerun dasdisup.
    Issued by
    dasdisup.c, function resolve_xctltab
    HHCDS013I Processing member member text record TTR=ttr CCHHR=cchhr
    Meaning
    The member named member is being processed. Its relative location is ttr, and its absolute location is cchhr.
    Issued by
    dasdisup.c, function resolve_xctltab
    HHCDS014E Member member error reading TTR ttr
    Meaning
    An attempt to read the member named member, at the relative location ttr, failed. The member cannot be processed.
    Action
    Rebuild SYS1.SVCLIB and rerun dasdisup. If this is unsuccessful, rebuild the entire DASD volume.
    Issued by
    dasdisup.c, function resolve_xctltab
    HHCDS015E Member member TTR ttr text record length length is not valid
    Meaning
    The length length of the text record at location ttr of the member named member is less than 8, greater than 1024, or not a multiple of 8. All of these conditions must be met for the length to be valid. The member is probably corrupt.
    Action
    Rebuild the member in SYS1.SVCLIB and rerun dasdisup.
    Issued by
    dasdisup.c, function resolve_xctltab
    HHCDS016E Member member TTR ttr text record length textlength does not match length dirlength in directory
    Meaning
    The length textlength of the text record at location ttr is not the same as the length dirlength in the directory entry for member member. Either the member, or the directory, is probably corrupt.
    Action
    Rebuild the member in SYS1.SVCLIB and rerun dasdisup. If this does not correct the problem, rebuild SYS1.SVCLIB in its entirety.
    Issued by
    dasdisup.c, function resolve_xctltab
    HHCDS017E Member member TTR ttr XCTL table improperly terminated
    Meaning
    The XCTL table in member member at location ttr runs past the end of the text record. The member is probably corrupt.
    Action
    Rebuild the member and rerun dasdisup.
    Issued by
    dasdisup.c, function resolve_xctltab
    HHCDS018I member (Alias|Member) skipped
    Meaning
    The member or alias named member is not an Open, Close, or EOV module, and so does not have an XCTL table that needs to be updated. It has been skipped.
    Issued by
    dasdisup.c, function resolve_xctltab
    HHCDS019I In member member: reference TTRL=ttrl status
    Meaning
    A reference to the member named reference in the member named member was found, The referenced member is at the location ttrl in the table. status is optional; it may be one of:
    ** Member reference not found
    The referenced member was not found in SYS1.SVCLIB. The reference cannot be updated.
    replaced by TTRL=newttrl flag
    The reference was updated to point to the referenced member's actual location at newttrl. If flag is ****, the actual length of the referenced member is different from the length of the member in the reference pointer.
    Issued by
    dasdisup.c, function resolve_xctltab


    If you have a question about Hercules, see the Hercules Frequently-Asked Questions page.


    back

    Last updated $Date: 2007-10-06 14:44:28 -0500 (Sat, 06 Oct 2007) $ $Revision: 4460 $

    hercules-3.07/html/hercmsdt.html000644 000765 000765 00000005747 11143760535 020430 0ustar00jmaynardjmaynard000000 000000 Hercules Version 3: System Messages: DT - dasdcat

    Hercules Version 3: System Messages: DT - dasdcat

    This page describes the messages for the Hercules S/370, ESA/390, and z/Architecture emulator utility program dasdcat.

    Messages

    HHCDT001E failed to open image filename
    Meaning
    An error was ancountered trying to open the DASD image file named filename. A previous message described the error.
    Action
    Correct the error and rerun dasdcat.
    Issued by
    dasdcat.c, function main
    HHCDT002E Can't make 80 column card images from block length length
    Meaning
    A block read from the member specified is not a multiple of 80 characters long, and so cannot be split evenly into 80-character card images. The actual length read is length.
    Action
    Select a different member, or omit the c flag from the member specification.
    Issued by
    dasdcat.c, function do_cat_cards
    HHCDT003E Directory block byte count is invalid
    Meaning
    The length of a PDS directory block in the specified dataset is invalid. The PDS directory is corrupt, or the dataset is not a PDS.
    Action
    Make sure the dataset specified is a PDS (partitioned dataset). If it is, then the dataset is corrupt.
    Issued by
    dasdcat.c, function process_dirblk
    HHCDT004E non-PDS-members not yet supported
    Meaning
    This version of dasdcat does not support reading sequential datasets.
    Action
    Specify a PDS as input to dasdcat.
    Issued by
    dasdcat.c, function do_cat_nonpds
    HHCDT005E unknown dataset name option: 'option'
    Meaning
    An invalid option was specified on the dataset name specification. Only the options a and c are valid.
    Action
    Remove the invalid option from the dataset name specification and rerun dasdcat.
    Issued by
    dasdcat.c, function do_cat


    If you have a question about Hercules, see the Hercules Frequently-Asked Questions page.


    back

    Last updated $Date: 2007-10-06 14:44:28 -0500 (Sat, 06 Oct 2007) $ $Revision: 4460 $

    hercules-3.07/html/hercmsdu.html000644 000765 000765 00000074237 11143760535 020431 0ustar00jmaynardjmaynard000000 000000 Hercules Version 3: System Messages: DU - DASD Utilities Common Functions

    Hercules Version 3: System Messages: DU - DASD Utilities Common Functions

    This page describes the messages for the Hercules S/370, ESA/390, and z/Architecture emulator DASD utility programs that are common to more than one utility.

    Messages

    HHCDU001I Updating cyl cylinder head head
    Meaning
    The track at cylinder number cylinder and head number head is being rewritten after being modified. This message is only issued if verbose message reporting has been selected.
    Issued by
    dasdutil.c, function read_track
    HHCDU002E filename write track error: stat=status
    Meaning
    An attempt to rewrite a track from the DASD image named filename failed. The status returned was status.
    Action
    Correct the error and retry the operation.
    Issued by
    dasdutil.c, function read_track
    HHCDU003I Reading cyl cylinder head head
    Meaning
    The track at cylinder number cylinder and head number head is being read. This message is only issued if verbose message reporting has been selected.
    Issued by
    dasdutil.c, function read_track
    HHCDU004E filename read track error: stat=status
    Meaning
    An attempt to read a track from the DASD image named filename failed. The status returned was status.
    Action
    Correct the error and retry the operation.
    Issued by
    dasdutil.c, function read_track
    HHCDU005I Searching extent 0 begin (begcyl,beghead) end (endcyl,endhead)
    Meaning
    The first extent of the dataset is being searched for a key. The extent starts at the track at cylinder begcyl, head beghead, and ends at the track at cylinder endcyl, head endhead. This message is only issued if verbose message reporting has been selected.
    Issued by
    dasdutil.c, function search_key_equal
    HHCDU006I Searching extent extent begin (begcyl,beghead) end (endcyl,endhead)
    Meaning
    An extent, extent, of the dataset is being searched for a key. The extent starts at the track at cylinder begcyl, head beghead, and ends at the track at cylinder endcyl, head endhead. This message is only issued if verbose message reporting has been selected.
    Issued by
    dasdutil.c, function search_key_equal
    HHCDU007E Track track not found in extent table
    Meaning
    An attempt was made to convert a track number to an absolute address, but the track specified, track, is beyond the end of the dataset.
    Action
    Correct the error and retry the operation. The dataset, the VTOC, or the DASD image may be corrupt.
    Issued by
    dasdutil.c, function convert_tt
    HHCDU008E Cannot obtain storage for device descriptor buffer: error
    Meaning
    An attempt to obtain storage for the buffer used to hold a CKD DASD image's description failed. The error is described by error.
    Action
    Correct the error and retry the operation.
    Issued by
    dasdutil.c, function open_ckd_image
    HHCDU009E Cannot open filename: error
    Meaning
    The CKD image file named filename could not be opened. The error is described by error.
    Action
    Correct the error and retry the operation.
    Issued by
    dasdutil.c, function open_ckd_image
    HHCDU010E filename read error: error
    Meaning
    An error was encountered while reading the CKD header record from the file named filename. The error is described by error.
    Action
    Correct the error and retry the operation.
    Issued by
    dasdutil.c, function open_ckd_image
    HHCDU011E filename CKD header invalid
    Meaning
    The file filename is not a valid CKD DASD image file. Either the first record is not the length of a CKD header record, or the marker in the header record is not correct.
    Action
    Supply the name of a valid CKD DASD image file and retry the operation.
    Issued by
    dasdutil.c, function open_ckd_image
    HHCDU012E DASD table entry not found for devtype type
    Meaning
    The device type in the CKD header record does not correspond to any known DASD device. The CKD DASD image file may be corrupt, or else the device is not supported by Hercules.
    Action
    Supply the name of a supported CKD DASD image file and retry the operation.
    Issued by
    dasdutil.c, function open_ckd_image
    HHCDU013E CKD initialization failed for filename
    Meaning
    The device-specific initialization routine for the file named filename failed. Another message describes the specific failure.
    Action
    See the specific message for the action needed.
    Issued by
    dasdutil.c, function open_ckd_image
    HHCDU014I filename heads=heads trklen=trklen
    Meaning
    The device represented by the CKD DASD image file named filename has heads heads and tracks of trklen bytes length. This message is only issued if verbose message reporting has been selected.
    Issued by
    dasdutil.c, function open_ckd_image
    HHCDU015I Updating cyl cylinder head head
    Meaning
    During processing of a request to close the CKD image file, the track at cylinder number cylinder and head number head is being rewritten, since it has been modified. This message is only issued if verbose message reporting has been selected.
    Issued by
    dasdutil.c, function close_ckd_image
    HHCDU016E filename write track error: stat=status
    Meaning
    During processing of a request to close the CKD image file, an attempt to rewrite a track from the DASD image named filename failed. The status returned was status.
    Action
    Correct the error and retry the operation.
    Issued by
    dasdutil.c, function close_ckd_image
    HHCDU017E Cannot obtain storage for device descriptor buffer: error
    Meaning
    An attempt to obtain storage for the buffer used to hold a FBA DASD image's description failed. The error is described by error.
    Action
    Correct the error and retry the operation.
    Issued by
    dasdutil.c, function open_fba_image
    HHCDU018E DASD table entry not found for devtype type
    Meaning
    The default FBA device type does not correspond to any known DASD device. This is likely an internal programming error.
    Action
    Report the bug to the Hercules development team.
    Issued by
    dasdutil.c, function open_fba_image
    HHCDU019E FBA initialization failed for filename
    Meaning
    The device-specific initialization routine for the file named filename failed. Another message describes the specific failure.
    Action
    See the specific message for the action needed.
    Issued by
    dasdutil.c, function open_fba_image
    HHCDU020I filename sectors=sectors size=size
    Meaning
    The device represented by the FBA DASD image file named filename has sectors sectors of size bytes length. This message is only issued if verbose message reporting has been selected.
    Issued by
    dasdutil.c, function open_fba_image
    HHCDU021E VOL1 record not found
    Meaning
    The volume being processed does not have a volume label. It is probably blank and unformatted.
    Action
    Format the volume, or specify a formatted volume and retry the operation.
    Issued by
    dasdutil.c, function build_extent_array
    HHCDU022I VOLSER=serial VTOC=cchhr
    Meaning
    The volume being processed has the volume serial serial, and its VTOC format 4 DSCB is at absolute location cchhr. This message is only issued if verbose message reporting has been selected.
    Issued by
    dasdutil.c, function build_extent_array
    HHCDU023I VTOC start begcchh end endcchh
    Meaning
    The VTOC of the volume being processed begins at cylinder and head begcchh and ends at cylinder and head endcchh. This message is only issued if verbose message reporting has been selected.
    Issued by
    dasdutil.c, function build_extent_array
    HHCDU024E Dataset dsn not found in VTOC
    Meaning
    The requested dataset, dsn, was not found in the VTOC and does not exist on this volume.
    Action
    Specify the correct dataset name, or select the volume on which it appears.
    Issued by
    dasdutil.c, function build_extent_array
    HHCDU025I DSNAME=dsn F1DSCB CCHHR=cchhr
    Meaning
    The format 1 DSCB for the requested dataset, dsn, is at absolute location cchhr. This message is only issued if verbose message reporting has been selected.
    Issued by
    dasdutil.c, function build_extent_array
    HHCDU026E F1DSCB record not found
    Meaning
    The requested dataset is listed in the VTOC, but its format 1 DSCB record was not found when an attempt was made to read it. The VTOC may be corrupt.
    Action
    Recreate the dataset and retry the operation.
    Issued by
    dasdutil.c, function build_extent_array
    HHCDU027E F3DSCB record not found
    Meaning
    The requested dataset is reported to contain more than three extents in the format 1 DSCB, but its format 3 DSCB record was not found when an attempt was made to read it. The VTOC may be corrupt.
    Action
    Recreate the dataset and retry the operation.
    Issued by
    dasdutil.c, function build_extent_array
    HHCDU028E filename open error: error
    Meaning
    An attempt to create the CKD DASD image file named filename failed. The error is described by error.
    Action
    Correct the error and retry the operation.
    Issued by
    dasdutil.c, function create_ckd_file
    HHCDU029E filename device header write error: error
    Meaning
    An attempt to write the device header to the CKD DASD image file named filename failed. The error is described by error.
    Action
    Correct the error and retry the operation.
    Issued by
    dasdutil.c, function create_ckd_file
    HHCDU030E filename compressed device header write error: error
    Meaning
    An attempt to write the compressed device header to the CKD DASD image file named filename failed. The error is described by error.
    Action
    Correct the error and retry the operation.
    Issued by
    dasdutil.c, function create_ckd_file
    HHCDU031E Cannot obtain l1tab buffer: error
    Meaning
    An attempt to obtain storage for the primary lookup table buffer failed. The error is described by error.
    Action
    Correct the error and retry the operation.
    Issued by
    dasdutil.c, function create_ckd_file
    HHCDU032E filename primary lookup table write error: error
    Meaning
    An attempt to write the primary lookup table to the CKD DASD image file named filename failed. The error is described by error.
    Action
    Correct the error and retry the operation.
    Issued by
    dasdutil.c, function create_ckd_file
    HHCDU033E filename secondary lookup table write error: error
    Meaning
    An attempt to write the secondary lookup table to the CKD DASD image file named filename failed. The error is described by error.
    Action
    Correct the error and retry the operation.
    Issued by
    dasdutil.c, function create_ckd_file
    HHCDU034E filename dasdcopy ftruncate error: error
    Meaning
    An attempt to truncate the CKD DASD image file named filename failed. The error is described by error.
    Action
    Correct the error and retry the operation.
    Issued by
    dasdutil.c, function create_ckd_file
    HHCDU035E filename cylinder cyl head head write error: error
    Meaning
    An attempt to write the track at cylinder cyl, head head to the CKD DASD image file named filename failed. The error is described by error.
    Action
    Correct the error and retry the operation.
    Issued by
    dasdutil.c, function create_ckd_file
    HHCDU036E filename compressed device header lseek error: error
    Meaning
    An attempt to reposition to the beginning of the CKD DASD image file named filename failed. The error is described by error.
    Action
    Correct the error and retry the operation.
    Issued by
    dasdutil.c, function create_ckd_file
    HHCDU037E filename compressed device header write error: error
    Meaning
    An attempt to rewrite the compressed device header record of the CKD DASD image file named filename failed. The error is described by error.
    Action
    Correct the error and retry the operation.
    Issued by
    dasdutil.c, function create_ckd_file
    HHCDU038E filename secondary lookup table lseek error: error
    Meaning
    An attempt to reposition to the secondary lookup table of the CKD DASD image file named filename failed. The error is described by error.
    Action
    Correct the error and retry the operation.
    Issued by
    dasdutil.c, function create_ckd_file
    HHCDU039E filename secondary lookup table write error: error
    Meaning
    An attempt to rewrite the secondary lookup table of the CKD DASD image file named filename failed. The error is described by error.
    Action
    Correct the error and retry the operation.
    Issued by
    dasdutil.c, function create_ckd_file
    HHCDU040E filename close error: error
    Meaning
    An attempt to close the CKD DASD image file named filename failed. The error is described by error.
    Action
    Correct the error and retry the operation.
    Issued by
    dasdutil.c, function create_ckd_file
    HHCDU041I count cylinders successfully written to file filename
    Meaning
    The CKD DASD image file named filename has been successfully created. It contains count cylinders.
    Issued by
    dasdutil.c, function create_ckd_file
    HHCDU042E Cylinder count count is outside range min-max
    Meaning
    The requested number of cylinders, count, is outside the valid range from min to max.
    Action
    Specify a valid number of cylinders and retry the operation.
    Issued by
    dasdutil.c, function create_ckd
    HHCDU043E Cannot obtain track buffer: error
    Meaning
    An attempt to obtain storage for the track buffer failed. The error is described by error.
    Action
    Correct the error and retry the operation.
    Issued by
    dasdutil.c, function create_ckd
    HHCDU044I Creating type volume serial: cylinders cyls, tracks trks/cyl, length bytes/track
    Meaning
    A new volume is being created of device type type and volume serial number serial. It has cylinders cylinders, tracks tracks per cylinder, and length bytes per track.
    Issued by
    dasdutil.c, function create_ckd
    HHCDU045E Sector count count is outside range min-max
    Meaning
    The requested number of sectors, count, is outside the valid range from min to max.
    Action
    Specify a valid number of cylinders and retry the operation.
    Issued by
    dasdutil.c, function create_fba
    HHCDU046E Cannot obtain sector buffer: error
    Meaning
    An attempt to obtain storage for the sector buffer failed. The error is described by error.
    Action
    Correct the error and retry the operation.
    Issued by
    dasdutil.c, function create_fba
    HHCDU047I Creating type volume serial: sectors sectors, length bytes/sector
    Meaning
    A new volume is being created of device type type and volume serial number serial. It has sectors sectors and length bytes per sector.
    Issued by
    dasdutil.c, function create_fba
    HHCDU048E filename open error: error
    Meaning
    An attempt to create the FBA DASD image file named filename failed. The error is described by error.
    Action
    Correct the error and retry the operation.
    Issued by
    dasdutil.c, function create_fba
    HHCDU049E filename dasdcopy ftruncate error: error
    Meaning
    An attempt to truncate the FBA DASD image file named filename failed. The error is described by error.
    Action
    Correct the error and retry the operation.
    Issued by
    dasdutil.c, function create_fba
    HHCDU050E filename sector sector write error: error
    Meaning
    An attempt to write sector number sector to the FBA DASD image file named filename failed. The error is described by error.
    Action
    Correct the error and retry the operation.
    Issued by
    dasdutil.c, function create_fba
    HHCDU051E filename close error: error
    Meaning
    An attempt to close the FBA DASD image file named filename failed. The error is described by error.
    Action
    Correct the error and retry the operation.
    Issued by
    dasdutil.c, function create_fba
    HHCDU052I count sectors successfully written to file filename
    Meaning
    The FBA DASD image file named filename has been successfully created. It contains count sectors.
    Issued by
    dasdutil.c, function create_fba
    HHCDU053E File size too large: size [l1tab]
    Meaning
    The requested file size, size, would result in a primary lookup table that is too large. The DASD image cannot be created as a compressed image.
    Action
    Either specify fewer sectors, or create the DASD image uncompressed.
    Issued by
    dasdutil.c, function create_compressed_fba
    HHCDU054E filename open error: error
    Meaning
    An attempt to create the compressed FBA DASD image file named filename failed. The error is described by error.
    Action
    Correct the error and retry the operation.
    Issued by
    dasdutil.c, function create_compressed_fba
    HHCDU055I Creating type compressed volume serial: sectors sectors, length bytes/sector
    Meaning
    A new compressed FBA volume is being created of device type type and volume serial number serial. It has sectors sectors and length bytes per sector.
    Issued by
    dasdutil.c, function create_compressed_fba
    HHCDU056E filename devhdr write error: error
    Meaning
    An attempt to write the device header to the compressed FBA DASD image file named filename failed. The error is described by error.
    Action
    Correct the error and retry the operation.
    Issued by
    dasdutil.c, function create_compressed_fba
    HHCDU057E filename cdevhdr write error: error
    Meaning
    An attempt to write the compressed device header to the compressed FBA DASD image file named filename failed. The error is described by error.
    Action
    Correct the error and retry the operation.
    Issued by
    dasdutil.c, function create_compressed_fba
    HHCDU058E filename l1tab write error: error
    Meaning
    An attempt to write the primary lookup table to the compressed FBA DASD image file named filename failed. The error is described by error.
    Action
    Correct the error and retry the operation.
    Issued by
    dasdutil.c, function create_compressed_fba
    HHCDU059E filename l2tab write error: error
    Meaning
    An attempt to write the secondary lookup table to the compressed FBA DASD image file named filename failed. The error is described by error.
    Action
    Correct the error and retry the operation.
    Issued by
    dasdutil.c, function create_compressed_fba
    HHCDU060E filename block header write error: error
    Meaning
    An attempt to write a compressed block header to the compressed FBA DASD image file named filename failed. The error is described by error.
    Action
    Correct the error and retry the operation.
    Issued by
    dasdutil.c, function create_compressed_fba
    HHCDU061E filename block write error: error
    Meaning
    An attempt to write a compressed block to the compressed FBA DASD image file named filename failed. The error is described by error.
    Action
    Correct the error and retry the operation.
    Issued by
    dasdutil.c, function create_compressed_fba
    HHCDU062E filename block write error: error
    Meaning
    An attempt to write an uncompressed block to the compressed FBA DASD image file named filename failed. The error is described by error.
    Action
    Correct the error and retry the operation.
    Issued by
    dasdutil.c, function create_compressed_fba
    HHCDU063E filename cdevhdr lseek error: error
    Meaning
    An attempt to reposition to the beginning of the compressed FBA DASD image file named filename failed. The error is described by error.
    Action
    Correct the error and retry the operation.
    Issued by
    dasdutil.c, function create_compressed_fba
    HHCDU064E filename cdevhdr rewrite error: error
    Meaning
    An attempt to rewrite the compressed device header record of the compressed FBA DASD image file named filename failed. The error is described by error.
    Action
    Correct the error and retry the operation.
    Issued by
    dasdutil.c, function create_compressed_fba
    HHCDU065E filename l2tab lseek error: error
    Meaning
    An attempt to reposition to the secondary lookup table of the compressed FBA DASD image file named filename failed. The error is described by error.
    Action
    Correct the error and retry the operation.
    Issued by
    dasdutil.c, function create_compressed_fba
    HHCDU066E filename l2tab rewrite error: error
    Meaning
    An attempt to rewrite the secondary lookup table of the compressed FBA DASD image file named filename failed. The error is described by error.
    Action
    Correct the error and retry the operation.
    Issued by
    dasdutil.c, function create_compressed_fba
    HHCDU067E filename close error: error
    Meaning
    An attempt to close the compressed FBA DASD image file named filename failed. The error is described by error.
    Action
    Correct the error and retry the operation.
    Issued by
    dasdutil.c, function create_compressed_fba
    HHCDU068I count sectors successfully written to file filename
    Meaning
    The compressed FBA DASD image file named filename has been successfully created. It contains count sectors.
    Issued by
    dasdutil.c, function create_compressed_fba


    If you have a question about Hercules, see the Hercules Frequently-Asked Questions page.


    back

    Last updated $Date: 2007-10-06 14:44:28 -0500 (Sat, 06 Oct 2007) $ $Revision: 4460 $

    hercules-3.07/html/hercmsg.html000644 000765 000765 00000011473 11143760535 020240 0ustar00jmaynardjmaynard000000 000000 Hercules Version 3: System Message Overview

    Hercules Version 3: System Message Overview

    This page describes the system messages for the Hercules S/370, ESA/390, and z/Architecture emulator.

    Message format

    All Hercules-issued messages are of the form: HHCmmnnns text where:

    HHC
    is the message prefix for Hercules. All Hercules messages will have this prefix.
    mm
    specifies the function that issued the message, from the following list:
    CA
    Communication Adapter emulation
    CF
    Configuration file processing
    CP
    CPU emulation
    CT
    Channel-to-channel adapter emulation
    CU
    CCKD utility
    DA
    DASD emulation (both CKD and FBA)
    DC
    dasdcopy
    DG
    dyngui.dll
    DI
    dasdinit
    DL
    dasdload
    DS
    dasdisup
    DT
    dasdcat
    DU
    DASD utilities common functions
    HD
    Hercules Dynamic Loader
    HE
    hetinit
    HG
    hetget
    HM
    hetmap
    HT
    HTTP server
    HU
    hetupd
    IF
    hercifc (Network interface configuration handler)
    IN
    Hercules initialization
    LC
    LCS emulation
    LG
    System Log functions
    PN
    Hercules control panel command messages
    PR
    Printer emulation
    PU
    Card punch emulation
    RD
    Card reader emulation
    SD
    Socket devices common functions
    TA
    Tape device emulation
    TC
    tapecopy
    TE
    1052 and 3270 terminal emulation
    TM
    tapemap
    TS
    tapesplt
    TT
    TOD Clock and Timer Services
    TU
    TUN/TAP driver support
    VM
    VM/CP emulation facility
    nnn
    Specific message number, assigned more or less sequentially.
    s
    Message severity:
    S
    Severe error. Causes immediate termination of Hercules.
    E
    Error. The function being requested did not execute correctly, but Hercules should continue running.
    W
    Warning. Not necessarily an error, but something to take note of and possibly correct.
    I
    Information. General messages that do not require any further action.
    A
    Action. You need to do something.
    text
    Message text.

    You may look up any message by following the link from the function identifier in the above list.


    If you have a question about Hercules, see the Hercules Frequently-Asked Questions page.


    back

    Last updated $Date: 2007-10-02 15:37:11 -0500 (Tue, 02 Oct 2007) $ $Revision: 4452 $

    hercules-3.07/html/hercmshd.html000644 000765 000765 00000017544 11143760535 020412 0ustar00jmaynardjmaynard000000 000000 Hercules Version 3: System Messages: HD - Hercules Dynamic Loader

    Hercules Version 3: System Messages: HD - Hercules Dynamic Loader

    This page describes the Dynamic Loader messages for the Hercules S/370, ESA/390, and z/Architecture emulator.

    Messages

    HHCHD001E registration alloc failed for entry
    Meaning
    Storage could not be obtained to register entrypoint entry
    Issued by
    hdl.c, function hdl_fent
    HHCHD002E cannot allocate memory for DLL descriptor: error
    Meaning
    Initialisation of the dynamic loader environment failed due to the error described by error.
    Action
    Correct the error and restart Hercules.
    Issued by
    hdl.c, function hdl_main
    HHCHD003E unable to open hercules as DLL: error
    Meaning
    The main hercules load module could not be opened by the dynamic loader. The dynamic loader error is described by error
    Action
    Correct the error and restart Hercules.
    Issued by
    hdl.c, function hdl_main
    HHCHD004I No initializer in module: error
    Meaning
    The initializer in DLL named module could not be found. The error is described by error
    Action
    Correct the error and restart Hercules.
    Issued by
    hdl.c, function hdl_main
    HHCHD005E module already loaded.
    Meaning
    An attempt was made to load an already loaded module.
    Action
    Unload to module first.
    Issued by
    hdl.c, function hdl_load
    HHCHD006S cannot allocate memory for DLL descriptor: error
    Meaning
    Initialisation of the dynamic loader environment failed due to the error described by error.
    Action
    Correct the error and restart Hercules.
    Issued by
    hdl.c, function hdl_load
    HHCHD007E unable to open DLL module: error
    Meaning
    The DLL named module could not be opened. The error is described by error.
    Action
    Ensure that the correct module is specified and is accessible.
    Issued by
    hdl.c, function hdl_load
    HHCHD008I No initializer in module: error
    Meaning
    The initializer in DLL named module could not be found. The error is described by error
    Action
    Correct the error and restart Hercules.
    Issued by
    hdl.c, function hdl_load
    HHCHD009E module not found
    Meaning
    An attempt was made to unload a module that was not loaded.
    Action
    No action required.
    Issued by
    hdl.c, function hdl_dele
    HHCHD010I Dependency check failed for module, version(vers_actual) expected(vers_exp)
    Meaning
    The version of the module's required dependency does not match the version of the dependency in the module that contains the dependency.
    Action
    No action required.
    Issued by
    hdl.c, function hdl_dchk
    HHCHD011I Dependency check failed for module, size(size_actual) expected(size_exp)
    Meaning
    The size of the module's required dependency does not match the size of the dependency in the module that contains the dependency.
    Action
    No action required.
    Issued by
    hdl.c, function hdl_dchk
    HHCHD012E No depency section in module: error
    Meaning
    The module being loaded does not contain the required dependency section. The error is described by error.
    Action
    Rebuild the module with the required HDL_DEPENDENCY_SECTION defined.
    Issued by
    hdl.c, function hdl_main
    HHCHD013E No depency section in module: error
    Meaning
    The module being loaded does not contain the required dependency section. The error is described by error.
    Action
    Rebuild the module with the required HDL_DEPENDENCY_SECTION defined.
    Issued by
    hdl.c, function hdl_load
    HHCHD014E Dependency check failed for module module
    Meaning
    One or more required dependencies were not satisfied. The preceding HHCHD010I and/or HHCHD011I message(s) identifies which of the dependencies failed and the reason why.
    Action
    If the module was not loaded, rebuild the module using the same version of the required dependency as the module that contains the dependency and try again.
    Issued by
    hdl.c, function hdl_load
    HHCHD015E Unloading of module not allowed
    Meaning
    An attempt was made to unload a module that was not allowed to be unloaded.
    Action
    No action required.
    Issued by
    hdl.c, function hdl_dele
    HHCHD018I Loadable module directory is dir
    Meaning
    The default loadable module directory was manually changed to dir via either a supplied MODPATH configuration file statement or via the -d command-line option.
    Action
    None required. This is an informational-only message.
    Issued by
    hdl.c, function hdl_setpath
    HHCHD100I Loading module ...
    Meaning
    Module module  is being loaded.
    Action
    No action required
    Issued by
    hsccmd.c, function ldmod_cmd
    HHCHD101I Module module loaded
    Meaning
    Module module  has been loaded.
    Action
    No action required
    Issued by
    hsccmd.c, function ldmod_cmd
    HHCHD102I Unloading module ...
    Meaning
    Module module  is being unloaded.
    Action
    No action required
    Issued by
    hsccmd.c, function rmmod_cmd
    HHCHD103I Module module unloaded
    Meaning
    Module module  has been unloaded.
    Action
    No action required
    Issued by
    hsccmd.c, function rmmod_cmd


    If you have a question about Hercules, see the Hercules Frequently-Asked Questions page.


    back

    Last updated $Date: 2008-10-22 04:20:13 -0500 (Wed, 22 Oct 2008) $ $Revision: 4893 $

    hercules-3.07/html/hercmshe.html000644 000765 000765 00000002073 11143760535 020402 0ustar00jmaynardjmaynard000000 000000 Hercules Version 3: System Messages: HE - hetinit

    Hercules Version 3: System Messages: HE - hetinit

    This page describes the messages for the Hercules S/370, ESA/390, and z/Architecture emulator utility program hetinit.

    Messages

    HHCHE001I
    Meaning
    Issued by
    hetinit.c, function


    If you have a question about Hercules, see the Hercules Frequently-Asked Questions page.


    back

    Last updated $Date: 2007-10-06 14:44:28 -0500 (Sat, 06 Oct 2007) $ $Revision: 4460 $

    hercules-3.07/html/hercmshg.html000644 000765 000765 00000002067 11143760535 020407 0ustar00jmaynardjmaynard000000 000000 Hercules Version 3: System Messages: HG - hetget

    Hercules Version 3: System Messages: HG - hetget

    This page describes the messages for the Hercules S/370, ESA/390, and z/Architecture emulator utility program hetget.

    Messages

    HHCHG001I
    Meaning
    Issued by
    hetget.c, function


    If you have a question about Hercules, see the Hercules Frequently-Asked Questions page.


    back

    Last updated $Date: 2007-10-06 14:44:28 -0500 (Sat, 06 Oct 2007) $ $Revision: 4460 $

    hercules-3.07/html/hercmshm.html000644 000765 000765 00000002067 11143760535 020415 0ustar00jmaynardjmaynard000000 000000 Hercules Version 3: System Messages: HM - hetmap

    Hercules Version 3: System Messages: HM - hetmap

    This page describes the messages for the Hercules S/370, ESA/390, and z/Architecture emulator utility program hetmap.

    Messages

    HHCHM001I
    Meaning
    Issued by
    hetmap.c, function


    If you have a question about Hercules, see the Hercules Frequently-Asked Questions page.


    back

    Last updated $Date: 2007-10-06 14:44:28 -0500 (Sat, 06 Oct 2007) $ $Revision: 4460 $

    hercules-3.07/html/hercmsht.html000644 000765 000765 00000012241 11143760535 020417 0ustar00jmaynardjmaynard000000 000000 Hercules Version 3: System Messages: HT - HTTP Server

    Hercules Version 3: System Messages: HT - HTTP Server

    This page describes the HTTP server messages for the Hercules S/370, ESA/390, and z/Architecture emulator.

    Messages

    HHCHT001I HTTP listener thread started: tid=threadid, pid=processid
    Meaning
    The HTTP server thread to accept and process incoming requests has been started. The thread id is threadid, and the process id is processid.
    Issued by
    httpserv.c, function http_server
    HHCHT002E socket: error
    Meaning
    An attempt to obtain a TCP socket to receive HTTP requests failed. The error is described by error.
    Action
    Correct the error and restart Hercules.
    Issued by
    httpserv.c, function http_server
    HHCHT003W Waiting for port port to become free
    Meaning
    The thread that handles HTTP connection requests is waiting for the TCP port denoted by port to become available for use.
    Action
    If this message persists, some other program has control of the TCP port listed. Find out which one it is and terminate it.
    Issued by
    httpserv.c, function http_server
    HHCHT004E bind: error
    Meaning
    An attempt to bind the socket to the TCP port to receive HTTP requests failed. The error is described by error.
    Action
    Correct the error and restart Hercules.
    Issued by
    httpserv.c, function http_server
    HHCHT005E listen: error
    Meaning
    An attempt to put the socket into listening state for HTTP requests failed. The error is described by error.
    Action
    Correct the error and restart Hercules.
    Issued by
    httpserv.c, function http_server
    HHCHT006I Waiting for HTTP requests on port port pid=num
    Meaning
    Hercules is ready to accept HTTP requests on port port.
    Issued by
    httpserv.c, function http_server
    HHCHT007E select: error
    Meaning
    An attempt to wait for data from HTTP requests failed. The error is described by error.
    Action
    Correct the error and restart Hercules.
    Issued by
    httpserv.c, function http_server
    HHCHT008E accept: error
    Meaning
    An attempt to accept a TCP connection for HTTP requests failed. The error is described by error.
    Action
    Correct the error and restart Hercules.
    Issued by
    httpserv.c, function http_server
    HHCHT009E fdopen: error
    Meaning
    An attempt to open the socket for reading HTTP requests failed. The error is described by error.
    Action
    Correct the error and restart Hercules.
    Issued by
    httpserv.c, function http_server
    HHCHT010E http_request create_thread: error
    Meaning
    An attempt to create a thread for processing HTTP requests failed. The error is described by error.
    Action
    Correct the error and restart Hercules.
    Issued by
    httpserv.c, function http_server
    HHCHT011E html_include: Cannot open filename: error
    Meaning
    The file named filename, which was included from another file, could not be opened. The error is described by error.
    Action
    Correct the error and retry the operation.
    Issued by
    httpserv.c, function html_include
    HHCHT014I HTTPROOT = pathname
    Meaning
    The root directory path for the HTTP server is pathname.
    Action
    None.
    Issued by
    httpserv.c, function http_server


    If you have a question about Hercules, see the Hercules Frequently-Asked Questions page.


    back

    Last updated $Date: 2007-10-06 14:44:28 -0500 (Sat, 06 Oct 2007) $ $Revision: 4460 $

    hercules-3.07/html/hercmshu.html000644 000765 000765 00000002073 11143760535 020422 0ustar00jmaynardjmaynard000000 000000 Hercules Version 3: System Messages: HU - hetutil

    Hercules Version 3: System Messages: HU - hetinit

    This page describes the messages for the Hercules S/370, ESA/390, and z/Architecture emulator utility program hetutil.

    Messages

    HHCHU001I
    Meaning
    Issued by
    hetutil.c, function


    If you have a question about Hercules, see the Hercules Frequently-Asked Questions page.


    back

    Last updated $Date: 2007-10-06 14:44:28 -0500 (Sat, 06 Oct 2007) $ $Revision: 4460 $

    hercules-3.07/html/hercmsif.html000644 000765 000765 00000006450 11143760535 020407 0ustar00jmaynardjmaynard000000 000000 Hercules Version 3: System Messages: IF - hercifc

    Hercules Version 3: System Messages: IF - hercifc

    This page describes the messages for the Hercules S/370, ESA/390, and z/Architecture emulator utility program hercifc.

    Messages

    HHCIF001E programname: Must be called from within Hercules.
    Meaning
    This program can only be called from Hercules itself, and may not be executed from the command line. The program was executed using the name programname.
    Action
    Don't do that.
    Issued by
    hercifc.c, function main
    HHCIF002E programname: Cannot obtain socket: error
    Meaning
    An attempt to obtain a socket for controlling the destination interface failed. The error is described by error. The program was executed using the name programname.
    Action
    Correct the error and retry the operation.
    Issued by
    hercifc.c, function main
    HHCIF003E programname: I/O error on read: error
    Meaning
    An attempt to read a request from Hercules failed. The error is described by error. The program was executed using the name programname.
    Action
    Correct the error and retry the operation.
    Issued by
    hercifc.c, function main
    HHCIF004W programname: Unknown request: request.
    Meaning
    The request from Hercules was invalid. The request code was request. The request has been ignored. The program was executed using the name programname.
    Action
    Make sure that the hercifc program is the same version as the running copy of Hercules. If so, this is an internal error. Report it.
    Issued by
    hercifc.c, function main
    HHCIF005E programname: ioctl error doing operation on interface: error
    Meaning
    An attempt to perform an ioctl operation, operation, on interface interface failed. The error is described by error. The program was executed using the name programname.
    Action
    Correct the error and retry the operation.
    Issued by
    hercifc.c, function main


    If you have a question about Hercules, see the Hercules Frequently-Asked Questions page.


    back

    Last updated $Date: 2007-10-06 14:44:28 -0500 (Sat, 06 Oct 2007) $ $Revision: 4460 $

    hercules-3.07/html/hercmsin.html000644 000765 000765 00000010765 11143760535 020423 0ustar00jmaynardjmaynard000000 000000 Hercules Version 3: System Messages: IN - Hercules Initialization

    Hercules Version 3: System Messages: IN - Hercules Initialization

    This page describes the system initialization messages for the Hercules S/370, ESA/390, and z/Architecture emulator.

    Messages

    HHCIN001S Cannot register SIGINT handler: error
    Meaning
    An attempt to register a handler for the SIGINT signal failed. The error is described by error.
    Action
    Correct the error and restart Hercules.
    Issued by
    impl.c, function main
    HHCIN002E Cannot suppress SIGPIPE signal: error
    Meaning
    An attempt to ignore the SIGPIPE signal failed. The error is described by error. This will cause Hercules to terminate abnormally if a printer device is defined to a pipe, and that pipe is closed while data is being written to it.
    Action
    Correct the error and restart Hercules. Do not print to a pipe until you have corrected the error.
    Issued by
    impl.c, function main
    HHCIN003S Cannot register SIGILL/FPE/SEGV/BUS/USR handler: error
    Meaning
    An attempt to register a handler for one of the listed signals failed. The error is described by error.
    Action
    Correct the error and restart Hercules.
    Issued by
    impl.c, function main
    HHCIN004S Cannot create watchdog thread: error
    Meaning
    An attempt to create the watchdog thread to monitor Hercules execution failed. The error is described by error.
    Action
    Correct the error and restart Hercules.
    Issued by
    impl.c, function main
    HHCIN005S Cannot create http_server thread: error
    Meaning
    An attempt to create the HTTP server thread failed. The error is described by error.
    Action
    Correct the error and restart Hercules.
    Issued by
    impl.c, function main
    HHCIN006S Cannot create panel thread: error
    Meaning
    An attempt to create the operator control panel thread failed. The error is described by error.
    Action
    Correct the error and restart Hercules.
    Issued by
    impl.c, function main
    HHCIN007S Cannot create devnum connection thread: error
    Meaning
    The shared device server was unable to create the thread meant to manage remote device devnum. The error is described by error.
    Action
    Correct the error and restart Hercules.
    Issued by
    impl.c, function main
    HHCIN008S DYNGUI.DLL load failed; Hercules terminated.
    Meaning
    The external GUI interface module 'dyngui.dll' could not loaded. The preceding HHCHD007E message should provide the reason for the failure.
    Action
    Correct the error and restart Hercules. If the error is Win32 error 126 ("The specified module could not be found"), check your Windows PATH setting and/or your MODPATH control statement to ensure one or both of them includes the directory where Hercules is executing from.
    Issued by
    impl.c, function main
    HHCIN099I Hercules terminated
    Meaning
    Hercules has ended.
    Action
    None.
    Issued by
    hsccmd.c, function quit_cmd


    If you have a question about Hercules, see the Hercules Frequently-Asked Questions page.


    back

    Last updated $Date: 2007-10-06 14:44:28 -0500 (Sat, 06 Oct 2007) $ $Revision: 4460 $

    hercules-3.07/html/hercmslc.html000644 000765 000765 00000027472 11143760535 020416 0ustar00jmaynardjmaynard000000 000000 Hercules Version 3: System Messages: LC - LAN Channel Station Emulation

    Hercules Version 3: System Messages: LC - LAN Channel Station Emulation

    This page describes the LAN Channel Station emulation messages for the Hercules S/370, ESA/390, and z/Architecture emulator.

    Messages

    HHCLC001E nnnn unable to allocate LCSBLK
    Meaning
    There is insufficient storage to allocate the control block for LCS device number nnnn.
    Action
    Correct the error and restart Hercules.
    Issued by
    ctc_lcs.c, function LCS_Init
    HHCLC017E nnnn invalid device name devname
    Meaning
    The value of the -n or -dev parameter in the configuration statement for LCS device number nnnn is missing or too long.
    Action
    Correct the parameter and reinitialize the device.
    Issued by
    ctc_lcs.c, function ParseArgs
    HHCLC018E nnnn invalid MAC address macaddr
    Meaning
    The value of the -m or -mac parameter in the configuration statement for LCS device number nnnn is not a valid MAC address.
    Action
    Correct the parameter and reinitialize the device.
    Issued by
    ctc_lcs.c, function ParseArgs
    HHCLC019E nnnn too many arguments in statement.
    Meaning
    The configuration statement for LCS device number nnnn contains too many positional parameters.
    Action
    Correct the statement and reinitialize the device.
    Issued by
    ctc_lcs.c, function ParseArgs
    HHCLC020E nnnn invalid IP address ipaddr
    Meaning
    The first positional parameter in the configuration statement for LCS device number nnnn is not a valid IP address.
    Action
    Correct the statement and reinitialize the device.
    Issued by
    ctc_lcs.c, function ParseArgs
    HHCLC021E Invalid HWADD statement in filename: stmt
    Meaning
    The port number parameter of the HWADD statement stmt in OAT file filename is not numeric.
    Action
    Correct the statement and reinitialize the device.
    Issued by
    ctc_lcs.c, function BuildOAT
    HHCLC022E Invalid MAC in HWADD statement in filename: stmt (macaddr)
    Meaning
    The second positional parameter of the HWADD statement stmt in OAT file filename is not a valid MAC address.
    Action
    Correct the parameter and reinitialize the device.
    Issued by
    ctc_lcs.c, function BuildOAT
    HHCLC023E Invalid ROUTE statement in filename: stmt
    Meaning
    The port number parameter of the ROUTE statement stmt in OAT file filename is not numeric.
    Action
    Correct the statement and reinitialize the device.
    Issued by
    ctc_lcs.c, function BuildOAT
    HHCLC024E Invalid net address in ROUTE filename: stmt (netaddr)
    Meaning
    The second positional parameter of the ROUTE statement stmt in OAT file filename is not a valid IP network address.
    Action
    Correct the parameter and reinitialize the device.
    Issued by
    ctc_lcs.c, function BuildOAT
    HHCLC025E Invalid net mask in ROUTE filename: stmt (netaddr)
    Meaning
    The third positional parameter of the ROUTE statement stmt in OAT file filename is not a valid IP network mask.
    Action
    Correct the parameter and reinitialize the device.
    Issued by
    ctc_lcs.c, function BuildOAT
    HHCLC026E Error in filename: Missing device number or mode
    Meaning
    The OAT file filename contains a statement which cannot be identified.
    Action
    Correct the statement and reinitialize the device.
    Issued by
    ctc_lcs.c, function BuildOAT
    HHCLC027E Error in filename: devnum: Invalid device number
    Meaning
    The device number devnum specified in the OAT file filename is not a valid hexadecimal number.
    Action
    Correct the statement and reinitialize the device.
    Issued by
    ctc_lcs.c, function BuildOAT
    HHCLC028E Error in filename: stmt: Missing PORT number
    Meaning
    Statement stmt in OAT file filename for the IP port of an LCS device does not contain a port number.
    Action
    Correct the statement and reinitialize the device.
    Issued by
    ctc_lcs.c, function BuildOAT
    HHCLC029E Error in filename: port: Invalid PORT number
    Meaning
    The port number port specified in the OAT file filename for the IP port of an LCS device is not a valid decimal number.
    Action
    Correct the statement and reinitialize the device.
    Issued by
    ctc_lcs.c, function BuildOAT
    HHCLC031E Error in filename: stmt: Invalid entry starting at text
    Meaning
    The parameter text specified in statement stmt in the OAT file filename should be PRI, SEC, or NO.
    Action
    Correct the statement and reinitialize the device.
    Issued by
    ctc_lcs.c, function BuildOAT
    HHCLC032E Error in filename: stmt: Invalid IP address (ipaddr)
    Meaning
    The parameter ipaddr specified in statement stmt in the OAT file filename is not a valid IP address.
    Action
    Correct the statement and reinitialize the device.
    Issued by
    ctc_lcs.c, function BuildOAT
    HHCLC033E Error in filename: stmt: Missing PORT number
    Meaning
    Statement stmt in OAT file filename for the SNA port of an LCS device does not contain a port number.
    Action
    Correct the statement and reinitialize the device.
    Issued by
    ctc_lcs.c, function BuildOAT
    HHCLC034E Error in filename: port: Invalid PORT number
    Meaning
    The port number port specified in the OAT file filename for the SNA port of an LCS device is not a valid decimal number.
    Action
    Correct the statement and reinitialize the device.
    Issued by
    ctc_lcs.c, function BuildOAT
    HHCLC035E Error in filename: stmt: SNA does not accept any arguments
    Meaning
    Statement stmt in OAT file filename for the SNA port of an LCS device contains positional parameters which are not used for SNA ports.
    Action
    Correct the statement and reinitialize the device.
    Issued by
    ctc_lcs.c, function BuildOAT
    HHCLC036E Error in filename: mode: Invalid MODE
    Meaning
    Mode mode specified in a device statement in the OAT file filename should be IP or SNA.
    Action
    Correct the statement and reinitialize the device.
    Issued by
    ctc_lcs.c, function BuildOAT
    HHCLC037E Error reading file filename line nnnn: description
    Meaning
    An error occurred reading the OAT file for an LCS device. description is the operating system's description of the error. The error occurred at line nnnn of file filename.
    Action
    Check that the correct OAT file name is specified in the configuration file.
    Issued by
    ctc_lcs.c, function ReadOAT
    HHCLC038E File filename line nnnn is too long
    Meaning
    An error occurred reading the OAT file for an LCS device. The error occurred at line nnnn of file filename. Either the line exceeds 255 characters, or there is no linefeed at the end of the file.
    Action
    Correct the OAT file.
    Issued by
    ctc_lcs.c, function ReadOAT
    HHCLC039E Cannot open file filename: description
    Meaning
    An error occurred opening the OAT file filename for an LCS device. description is the operating system's description of the error.
    Action
    Check that the correct OAT file name is specified in the configuration file.
    Issued by
    ctc_lcs.c, function BuildOAT
    HHCLC040E nnnn LCSDEV mmmm not in configuration
    Meaning
    The device number mmmm specified in the OAT file does not match the LCS device number nnnn in the configuration file.
    Action
    Correct the OAT file and reinitialize the device.
    Issued by
    ctc_lcs.c, function LCS_Init
    HHCLC055I tapn using MAC hh:hh:hh:hh:hh:hh
    Meaning
    The MAC address assigned the TUN/TAP device tapn is hh:hh:hh:hh:hh:hh.
    Action
    None.
    Issued by
    ctc_lcs.c, function LCS_LanStats
    HHCLC056W tapn NOT using MAC hh:hh:hh:hh:hh:hh
    Meaning
    MAC address hh:hh:hh:hh:hh:hh was requested in the configuration statement or in the OAT file for an LCS device but the operating system did not accept the request to change the MAC address for TUN/TAP device tapn.
    Action
    The device will use the MAC address shown in the preceding HHCLC055I message.
    Issued by
    ctc_lcs.c, function LCS_LanStats
    HHCLC073I nnnn: TAP device tapn opened
    Meaning
    LCS device number nnnn is now associated with the kernel TUN/TAP device named tapn.
    Action
    None.
    Issued by
    ctc_lcs.c, function LCS_Init


    If you have a question about Hercules, see the Hercules Frequently-Asked Questions page.


    back

    Last updated $Date: 2008-12-23 07:52:53 -0600 (Tue, 23 Dec 2008) $ $Revision: 4975 $

    hercules-3.07/html/hercmslg.html000644 000765 000765 00000013551 11143760535 020413 0ustar00jmaynardjmaynard000000 000000 Hercules Version 3: System Messages: LG - Log functions

    Hercules Version 3: System Messages: LG - Log functions

    This page describes messages related to the log funtions of the Hercules S/370, ESA/390, and z/Architecture emulator.

    Messages

    HHCLG001E Error redirecting stdout: error
    Meaning
    The stdout stream could not be redirected to the system logger, the error is described by error.
    Issued by
    logger.c, function logger_thread
    HHHCLG002E Error reading syslog pipe: error
    Meaning
    An error occurred while reading the syslog pipe. The error is described by error.
    Issued by
    logger.c, function logger_thread
    HHCLG003E Error writing hardcopy log: error
    Meaning
    The error as indicated by error occurred while writeing the hardcopy log.
    Issued by
    logger.c, function logger_thread
    HHCLG004E Error duplicating stderr: error
    Meaning
    Stdout could not be redirected to stderr. The error is described by error.
    Issued by
    logger.c, function logger_init
    HHCLG005E Error duplicating stdout: error
    Meaning
    Stderr could not be redirected to stdout. The error is described by error.
    Issued by
    logger.c, function logger_init
    HHCLG006E Duplicate error redirecting hardcopy log: error
    Meaning
    The error described by error occurred whilst redirecting the hardcopy log.
    Issued by
    logger.c, function logger_init
    HHCLG007S Hardcopy log fdopen failed: error
    Meaning
    An attempt to open a stream for the hardcopy log failed. The error is described by error.
    Issued by
    logger.c, function logger_init
    HHCLG008S logbuffer malloc failed: error
    Meaning
    An instorage buffer for the system log could not be obtained. The error is described by error.
    Issued by
    logger.c, function logger_init
    HHCLG009S Syslog message pipe creation failed: error
    Meaning
    An attempt to create the pipe for the system logger failed. The error is described by error.
    Action
    Check that your firewall is not preventing Hercules from opening a listening pipe.
    Issued by
    logger.c, function logger_init
    HHCLG012E Cannot create logger thread: error
    Meaning
    An attempt to create the logger thread failed. error is the description of the error code returned by the pthread_create call.
    Action
    If the error is "No error" ensure that Hercules has been correctly linked with the pthread library.
    Issued by
    logger.c, function logger_init
    HHCLG014E log not active
    Meaning
    A log off command was issued but there was no active log file.
    Action
    None.
    Issued by
    logger.c, function log_sethrdcpy
    HHCLG015I log closed
    Meaning
    The active log file has been closed as a result of a log off command.
    Action
    None.
    Issued by
    logger.c, function log_sethrdcpy
    HHCLG016E Error opening logfile filename: error
    Meaning
    The new log file requested by a log command could not be opened. error is the description of the error code returned by the open call.
    Action
    Reissue the log command with the correct filename.
    Issued by
    logger.c, function log_sethrdcpy
    HHCLG017S log file fdopen failed for filename: error
    Meaning
    The logger was unable to obtain the file descriptor for the new log file requested by a log command. error is the description of the error code returned by the fdopen call.
    Action
    Reissue the log command with the correct filename.
    Issued by
    logger.c, function log_sethrdcpy
    HHCLG018I log switched to filename
    Meaning
    As a result of a log command the logger is now writing to the requested log file.
    Action
    None.
    Issued by
    logger.c, function log_sethrdcpy


    If you have a question about Hercules, see the Hercules Frequently-Asked Questions page.


    back

    Last updated $Date: 2008-02-27 11:06:16 -0600 (Wed, 27 Feb 2008) $ $Revision: 4590 $

    hercules-3.07/html/hercmspn.html000644 000765 000765 00000017214 11143760535 020426 0ustar00jmaynardjmaynard000000 000000 Hercules Version 3: System Messages: PN - Control Panel

    Hercules Version 3: System Messages: PN - Control Panel

    This page describes the control panel messages for the Hercules S/370, ESA/390, and z/Architecture emulator.

    Messages

    HHCPN001I Control panel thread started: tid=threadid, pid=processid
    Meaning
    The control panel thread has been started. Its thread id is threadid, and its process id is processid.
    Issued by
    panel.c, function panel_display
    HHCPN002S Cannot obtain keyboard buffer: error
    Meaning
    An attempt to obtain memory for the keyboard buffer, used to hold operator input, failed. The error is described by error.
    Action
    Correct the error and restart Hercules.
    Issued by
    panel.c, function panel_display
    HHCPN003S Cannot obtain message buffer: error
    Meaning
    An attempt to obtain memory for the message buffer, used to hold operator output, failed. The error is described by error.
    Action
    Correct the error and restart Hercules.
    Issued by
    panel.c, function panel_display
    HHCPN004E select: error
    Meaning
    An error was encountered while waiting for input from the console. The error is described by error.
    Action
    Correct the error and retry the operation.
    Issued by
    panel.c, function panel_display
    HHCPN005E keyboard read: error
    Meaning
    An error was encountered while attempting to read keyboard input. The error is described by error.
    Action
    Correct the error and retry the operation.
    Issued by
    panel.c, function panel_display
    HHCPN006E message pipe read: error
    Meaning
    An error was encountered while attempting to read from the pipe used to communicate to the control panel thread from the rest of Hercules. The error is described by error.
    Action
    Correct the error and retry the operation.
    Issued by
    panel.c, function panel_display
    HHCPN007E RC file filename open failed: error
    Meaning
    The RC file containing commands to be executed at Hercules startup, named filename, could not be opened. The error is described by error.
    Action
    Correct the error and restart Hercules, if necessary. The commands contained in the file may be issued manually.
    Issued by
    panel.c, function process_rc_file
    HHCPN008I RC file processing thread started using file filename
    Meaning
    Processing of the commands contained in the file named filename has begun.
    Issued by
    panel.c, function process_rc_file
    HHCPN009E RC file buffer malloc failed: error
    Meaning
    An attempt to obtain storage for the buffer for commands being read from the startup command file failed. The error is described by error.
    Action
    Correct the error and restart Hercules, if needed. The comands contained in the file may be issued manually.
    Issued by
    panel.c, function process_rc_file
    HHCPN010W Ignoring invalid RC file pause statement: argument
    Meaning
    The argument, argument, on the pause statement in the startup command file is invalid. It must be a decimal number between 0 and 999. Processing will continue without any pause.
    Action
    Correct the invalid argument and restart Hercules, if desired.
    Issued by
    panel.c, function process_rc_file
    HHCPN011I Pausing RC file processing for delay seconds...
    Meaning
    Processing of the startup command file is being delayed for delay seconds because of a pause statement in the file.
    Issued by
    panel.c, function process_rc_file
    HHCPN012I Resuming RC file processing...
    Meaning
    Processing of the startup command file has resumed at the expiration of the delay interval.
    Issued by
    panel.c, function process_rc_file
    HHCPN013I EOF reached on RC file. Processing complete.
    Meaning
    The end of the startup command file has been reached, and processing of the file is complete.
    Issued by
    panel.c, function process_rc_file
    HHCPN014E I/O error reading RC file: error
    Meaning
    An error was encountered while reading a command from the startup command file. The error is described by error. Any remaining commands in the file will not be processed.
    Action
    Correct the error and restart Hercules, if desired. Any unprocessed commands may be issued manually.
    Issued by
    panel.c, function process_rc_file
    HHCPN052E Target CPU nnnn type cputype does not allow ipl
    Meaning
    An ipl command was issued but the target CPU nnnn is a processor engine of type cputype which does not support the initial program load procedure.
    Action
    Use the cpu command to set the target CPU to a processor of type CP, IFL, or ICF, then re-issue the ipl command.
    Issued by
    hsccmd.c, function ipl_cmd2
    HHCPN180E 'sh' commands are disabled
    Meaning
    The 'sh' (shell) command has been purposely disabled via a SHCMDOPT configuration file statement. Shell commands entered via the Hercules hardware console will not be processed.
    Action
    Remove or modify the SHCMDOPT configuration file statement and restart Hercules.
    Issued by
    hsccmd.c, function sh_cmd
    HHCPN181E Device number s:CCUU not found
    Meaning
    The device number CCUU on Logical Channel Subsystem s was not found in the configuration.
    Action
    Reissue the command with an existing device number.
    Issued by
    hsccmd.c, Multiple functions


    If you have a question about Hercules, see the Hercules Frequently-Asked Questions page.


    back

    Last updated $Date: 2008-11-25 17:00:11 -0600 (Tue, 25 Nov 2008) $ $Revision: 4920 $

    hercules-3.07/html/hercmspr.html000644 000765 000765 00000014142 11143760535 020427 0ustar00jmaynardjmaynard000000 000000 Hercules Version 3: System Messages: PR - Printer Emulation

    Hercules Version 3: System Messages: PR - Printer Emulation

    This page describes the printer emulation messages for the Hercules S/370, ESA/390, and z/Architecture emulator.

    Messages

    HHCPR001E File name missing or invalid for printer address
    Meaning
    There was no file name specified for the printer at address address, or else there was one specified, but it was too long.
    Action
    Correct the error in the Hercules configuration file. The device may be made available by specifying a filename with the devinit command.
    Issued by
    printer.c, function printer_init_handler
    HHCPR002E Invalid argument for printer address: argument
    Meaning
    An invalid argument was specified on the definition of the printer at address address.
    Action
    Correct or remove the invalid argument.
    Issued by
    printer.c, function printer_init_handler
    HHCPR003E address Error writing to filename: error
    Meaning
    An error was encountered when writing output for the printer at address address to the file named filename. The error is described by error.
    Action
    Correct the error and retry the operation.
    Issued by
    printer.c, function write_buffer
    HHCPR004E Error opening file filename: error
    Meaning
    An error was encountered when opening the file named filename. The error is described by error.
    Action
    Correct the error and retry the operation.
    Issued by
    printer.c, function open_printer
    HHCPR005E address device initialization error: pipe: error
    Meaning
    An error was encountered when opening a pipe for the printer at address address. The error is described by error.
    Action
    Correct the error and retry the operation.
    Issued by
    printer.c, function open_printer
    HHCPR006E address device initialization error: fork: error
    Meaning
    An error was encountered when starting the program to process the output from the printer at address address. The error is described by error.
    Action
    Correct the error and retry the operation.
    Issued by
    printer.c, function open_printer
    HHCPR007I pipe receiver (pid=processid) starting for address
    Meaning
    The program to process the output from the printer at address address is starting. Its process id is processid.
    Issued by
    printer.c, function open_printer
    HHCPR008E address dup2 error: error
    Meaning
    The file descriptor for stdin could not be duplicated for the program to process the output from the printer at address address. The error is described by error.
    Action
    Correct the error and retry the operation.
    Issued by
    printer.c, function open_printer
    HHCPR009E address dup2 error: error
    Meaning
    The file descriptor for stdout could not be duplicated for the program to process the output from the printer at address address. The error is described by error.
    Action
    Correct the error and retry the operation.
    Issued by
    printer.c, function open_printer
    HHCPR010E address dup2 error: error
    Meaning
    The file descriptor for stderr could not be duplicated for the program to process the output from the printer at address address. The error is described by error.
    Action
    Correct the error and retry the operation.
    Issued by
    printer.c, function open_printer
    HHCPR011I pipe receiver (pid=processid) terminating for address
    Meaning
    The program to process the output from the printer at address address has ended sucessfully. Its process id was processid.
    Issued by
    printer.c, function open_printer
    HHCPR012E address Unable to execute program: error
    Meaning
    The program named program to process the output from the printer at address address could not be started. The error is described by error.
    Action
    Correct the error and retry the operation.
    Issued by
    printer.c, function open_printer


    If you have a question about Hercules, see the Hercules Frequently-Asked Questions page.


    back

    Last updated $Date: 2007-10-06 14:44:28 -0500 (Sat, 06 Oct 2007) $ $Revision: 4460 $

    hercules-3.07/html/hercmspu.html000644 000765 000765 00000004762 11143760535 020441 0ustar00jmaynardjmaynard000000 000000 Hercules Version 3: System Messages: PU - Card Punch Emulation

    Hercules Version 3: System Messages: PU - Card Punch Emulation

    This page describes the card punch emulation messages for the Hercules S/370, ESA/390, and z/Architecture emulator.

    Messages

    HHCPU001E File name missing or invalid
    Meaning
    The file name specified for punched output is invalid, or no file name is given.
    Action
    Correct the error and retry the operation.
    Issued by
    cardpch.c, function cardpch_init_handler
    HHCPU002E Invalid argument: argument
    Meaning
    An invalid argument, argument, was specified for the card punch. Valid arguments are ascii, ebcdic, and crlf.
    Action
    Correct the invalid argument and retry the operation.
    Issued by
    cardpch.c, function cardpch_init_handler
    HHCPU003E Error opening file filename: error
    Meaning
    The file named filename could not be opened for output of card punch data. The error is described by error.
    Action
    Correct the error and retry the operation.
    Issued by
    cardpch.c, function cardpch_execute_ccw
    HHCPU004E Error writing to filename: error
    Meaning
    The file named filename encountered an error while writing card punch data. The error is described by error.
    Action
    Correct the error and retry the operation.
    Issued by
    cardpch.c, function write_buffer


    If you have a question about Hercules, see the Hercules Frequently-Asked Questions page.


    back

    Last updated $Date: 2007-10-06 14:44:28 -0500 (Sat, 06 Oct 2007) $ $Revision: 4460 $

    hercules-3.07/html/hercmsrd.html000644 000765 000765 00000022113 11143760535 020410 0ustar00jmaynardjmaynard000000 000000 Hercules Version 3: System Messages: RD - Card Reader Emulation

    Hercules Version 3: System Messages: RD - Card Reader Emulation

    This page describes the card reader emulation messages for the Hercules S/370, ESA/390, and z/Architecture emulator.

    Messages

    HHCRD001E Out of memory
    Meaning
    A request to allocate memory for the list of files to be read failed.
    Issued by
    cardrdr.c, function cardrdr_init_handler
    HHCRD002E File name too long (max=max): "filename"
    Meaning
    The file name specified by filename is too long. The maximum length is max.
    Action
    Specify a shorter name.
    Issued by
    cardrdr.c, function cardrdr_init_handler
    HHCRD003E Unable to access file "filename": error
    Meaning
    The file specified by filename could not be accessed. The error is described by error.
    Action
    Correct the error and retry the operation.
    Issued by
    cardrdr.c, function cardrdr_init_handler
    HHCRD004E Out of memory
    Meaning
    A request to allocate memory for the list of files to be read failed.
    Issued by
    cardrdr.c, function cardrdr_init_handler
    HHCRD005E Specify 'ascii' or 'ebcdic' (or neither) but not both
    Meaning
    Both of the character set translation options ascii and ebcdic were specified. At most one is allowed.
    Action
    Select only one character set translation option.
    Issued by
    cardrdr.c, function cardrdr_init_handler
    HHCRD006E Only one filename (sock_spec) allowed for socket devices
    Meaning
    More than one filename argument was given for a socket card reader device. Only one is allowed. This error can also result if an option name is misspelled.
    Action
    Remove the extraneous filenames, or correct the misspelled options.
    Issued by
    cardrdr.c, function cardrdr_init_handler
    HHCRD007I Defaulting to 'ascii' for socket device address
    Meaning
    The socket card reader device at address address has been set to ASCII mode, since neither translation option was specified. The socket card reader device cannot automatically select the translation option.
    Action
    If you wish to read cards without translation from ASCII to EBCDIC, you must specify the ebcdic option on the reader definition.
    Issued by
    cardrdr.c, function cardrdr_init_handler
    HHCRD008W 'multifile' option ignored: only one file specified
    Meaning
    Only one file was specified for input to the card reader, and the multifile option was specified. This option is meaningless with only one input file. The option has been ignored.
    Action
    If you wish to read more than one input file without signalling end-of-file or intervention required between them, they must all be specified on the same reader definition. If you only wish to process one file, omit the multifile option.
    Issued by
    cardrdr.c, function cardrdr_init_handler
    HHCRD009E File name too long (max=max): "filename"
    Meaning
    The file name specified by filename is too long. The maximum length is max.
    Action
    Specify a shorter name.
    Issued by
    cardrdr.c, function cardrdr_init_handler
    HHCRD010E Unable to access file "filename": error
    Meaning
    The file specified by filename could not be accessed. The error is described by error.
    Action
    Correct the error and retry the operation.
    Issued by
    cardrdr.c, function cardrdr_init_handler
    HHCRD011E Close error on file "filename": error
    Meaning
    An attempt to close the file specified by filename failed. The error is described by error.
    Action
    Correct the error and retry the operation.
    Issued by
    cardrdr.c, function cardrdr_close_device
    HHCRD012I ipaddr (hostname) disconnected from device address (socketspec)
    Meaning
    The client on the host named hostname, with the IP address ipaddr, has disconnected from the socket card reader device at address address, specified by socketspec.
    Issued by
    cardrdr.c, function cardrdr_close_device
    HHCRD013E Error opening file filename: error
    Meaning
    The file named filename could not be opened for reading. The error is described by error.
    Action
    Correct the error and retry the operation.
    Issued by
    cardrdr.c, function open_cardrdr
    HHCRD014E Error reading file filename: error
    Meaning
    An error was encountered while attempting to read the first 160 bytes of the file named filename in order to determine its character set. The error is described by error.
    Action
    Correct the error and retry the operation.
    Issued by
    cardrdr.c, function open_cardrdr
    HHCRD015E Seek error in file filename: error
    Meaning
    An error was encountered while attempting to return to the beginnning of file named filename after determining its character set. The error is described by error.
    Action
    Correct the error and retry the operation.
    Issued by
    cardrdr.c, function open_cardrdr
    HHCRD016E Error reading file filename: error
    Meaning
    An error was encountered while attempting to read an EBCDIC card image from the file named filename. The error is described by error.
    Action
    Correct the error and retry the operation.
    Issued by
    cardrdr.c, function read_ebcdic
    HHCRD017E Unexpected end of file on filename
    Meaning
    Too few characters were read from the file named filename. The autopad option was not specified.
    Action
    Either ensure that all records in the file are 80 bytes long, or specify the autopad option on the reader definition.
    Issued by
    cardrdr.c, function read_ebcdic
    HHCRD018E Error reading file filename: error
    Meaning
    An error was encountered while attempting to read an ASCII card image from the file named filename. The error is described by error.
    Action
    Correct the error and retry the operation.
    Issued by
    cardrdr.c, function read_ascii
    HHCRD019E Card image exceeds size bytes in file filename
    Meaning
    A line in the file named filename is too long to fit on one card. The trunc option was not specified. The maximum length is size bytes.
    Action
    Either ensure that all lines in the file are less than size bytes long, or specify the trunc option on the reader definition.
    Issued by
    cardrdr.c, function read_ascii


    If you have a question about Hercules, see the Hercules Frequently-Asked Questions page.


    back

    Last updated $Date: 2007-10-06 14:44:28 -0500 (Sat, 06 Oct 2007) $ $Revision: 4460 $

    hercules-3.07/html/hercmssd.html000644 000765 000765 00000002114 11143760535 020410 0ustar00jmaynardjmaynard000000 000000 Hercules Version 3: System Messages: SD - Socket Devices

    Hercules Version 3: System Messages: SD - Socket Devices

    This page describes the messages for the Hercules S/370, ESA/390, and z/Architecture emulator common routines to support socket devices.

    Messages

    HHCSD001I
    Meaning
    Issued by
    panel.c, function


    If you have a question about Hercules, see the Hercules Frequently-Asked Questions page.


    back

    Last updated $Date: 2007-10-06 14:44:28 -0500 (Sat, 06 Oct 2007) $ $Revision: 4460 $

    hercules-3.07/html/hercmsta.html000644 000765 000765 00000002110 11143760535 020402 0ustar00jmaynardjmaynard000000 000000 Hercules Version 3: System Messages: TA - Tape Device Emulation

    Hercules Version 3: System Messages: TA - Tape Device Emulation

    This page describes the tape device emulation messages for the Hercules S/370, ESA/390, and z/Architecture emulator.

    Messages

    HHCTA001I
    Meaning
    Issued by
    tapedev.c, function


    If you have a question about Hercules, see the Hercules Frequently-Asked Questions page.


    back

    Last updated $Date: 2007-10-06 14:44:28 -0500 (Sat, 06 Oct 2007) $ $Revision: 4460 $

    hercules-3.07/html/hercmstc.html000644 000765 000765 00000002077 11143760535 020420 0ustar00jmaynardjmaynard000000 000000 Hercules Version 3: System Messages: TC - tapecopy

    Hercules Version 3: System Messages: TC - tapecopy

    This page describes the messages for the Hercules S/370, ESA/390, and z/Architecture emulator utility program tapecopy.

    Messages

    HHCTC001I
    Meaning
    Issued by
    tapecopy.c, function


    If you have a question about Hercules, see the Hercules Frequently-Asked Questions page.


    back

    Last updated $Date: 2007-10-06 14:44:28 -0500 (Sat, 06 Oct 2007) $ $Revision: 4460 $

    hercules-3.07/html/hercmste.html000644 000765 000765 00000014465 11143760535 020426 0ustar00jmaynardjmaynard000000 000000 Hercules Version 3: System Messages: TE - 1052/3270 Terminal Emulation

    Hercules Version 3: System Messages: TE - 1052/3270 Terminal Emulation

    This page describes the terminal emulation messages for the Hercules S/370, ESA/390, and z/Architecture emulator.

    Messages

    HHCTE001I Console connection thread started: tid=threadid, pid=processid
    Meaning
    The thread that handles connection requests from console devices has been started.
    Issued by
    console.c, function console_connection_handler
    HHCTE002W Waiting for port port to become free
    Meaning
    The thread that handles connection requests from console devices is waiting for the TCP port denoted by port to become available for use.
    Action
    If this message persists, some other program has control of the TCP port listed. Find out which one it is and terminate it.
    Issued by
    console.c, function console_connection_handler
    HHCTE003I Waiting for console connection on port port pid=num
    Meaning
    Hercules is ready to accept console connections on port port.
    Issued by
    console.c, function console_connection_handler
    HHCTE004I Console connection thread terminated
    Meaning
    The thread that handles connection requests from console devices has been terminated.
    Issued by
    console.c, function console_connection_handler
    HHCTE005E Cannot create console thread: reason
    Meaning
    The thread that handles connection requests from console devices could not be started. The reason is shown as reason.
    Action
    Correct the reason listed and restart Hercules.
    Issued by
    console.c, function console_initialise
    HHCTE006A Enter input for console device address
    Meaning
    The 1052 console device at address is waiting for input.
    Action
    Type the desired input for the console and press the ENTER key. If you do not wish to get this message when input is requested, define the console with the option noprompt.
    Issued by
    console.c, function constty_execute_ccw
    HHCTE007I Device address closed by client ipaddr
    Meaning
    The client at IP address ipaddr that was connected to the 3270 console at address address has closed the connection. The device is no longer available for use.
    Issued by
    console.c, function recv_3270_data
    HHCTE008I Device address closed by client ipaddr
    Meaning
    The client at IP address ipaddr that was connected to the 1052 console at address address has closed the connection. The device is no longer available for use.
    Issued by
    console.c, function recv_1052_data
    HHCTE009I Client ipaddr connected to type device address
    Meaning
    The client at IP address ipaddr has connected to Hercules as a type device and is now available at address address.
    Issued by
    console.c, function connect_client
    HHCTE010E CNSLPORT statement invalid: statement
    Meaning
    The CNSLPORT statement in the hercules configuration file is invalid.
    Issued by
    console.c, function console_connection_handler
    HHCTE011E Device devn: Invalid IP address: ipaddr
    Meaning
    The IP address ipaddr is invalid.
    Issued by
    console.c, function loc3270_init_handler or constty_init_handler.
    HHCTE012E Device devn: Invalid mask value: ipmask
    Meaning
    The mask value ipmask is invalid.
    Issued by
    console.c, function loc3270_init_handler or constty_init_handler.
    HHCTE013E Device devn: Extraneous argument(s): xxx...
    Meaning
    The argument xxx and any which follow it (if any) was not recognized nor understood and are thus invalid.
    Issued by
    console.c, function loc3270_init_handler or constty_init_handler.
    HHCTE014I type device devn disconnected.
    Meaning
    The client connected to device devn has abruptly terminated the connection (ECONNRESET).
    Issued by
    console.c, function recv_3270_data
    HHCTE017E Device devn: Duplicate SYSG console definition
    Meaning
    Device number devn has been defined as an integrated 3270 (SYSG) console, but a SYSG console already exists. Only one SYSG console can be defined per system.
    Issued by
    console.c, function loc3270_init_handler


    If you have a question about Hercules, see the Hercules Frequently-Asked Questions page.


    back

    Last updated $Date: 2008-12-30 04:02:58 -0600 (Tue, 30 Dec 2008) $ $Revision: 5004 $

    hercules-3.07/html/hercmstm.html000644 000765 000765 00000002073 11143760535 020426 0ustar00jmaynardjmaynard000000 000000 Hercules Version 3: System Messages: TM - tapemap

    Hercules Version 3: System Messages: TM - tapemap

    This page describes the messages for the Hercules S/370, ESA/390, and z/Architecture emulator utility program tapemap.

    Messages

    HHCTM001I
    Meaning
    Issued by
    tapemap.c, function


    If you have a question about Hercules, see the Hercules Frequently-Asked Questions page.


    back

    Last updated $Date: 2007-10-06 14:44:28 -0500 (Sat, 06 Oct 2007) $ $Revision: 4460 $

    hercules-3.07/html/hercmsts.html000644 000765 000765 00000002077 11143760535 020440 0ustar00jmaynardjmaynard000000 000000 Hercules Version 3: System Messages: TS - tapesplt

    Hercules Version 3: System Messages: TS - tapesplt

    This page describes the messages for the Hercules S/370, ESA/390, and z/Architecture emulator utility program tapesplt.

    Messages

    HHCTS001I
    Meaning
    Issued by
    tapesplt.c, function


    If you have a question about Hercules, see the Hercules Frequently-Asked Questions page.


    back

    Last updated $Date: 2007-10-06 14:44:28 -0500 (Sat, 06 Oct 2007) $ $Revision: 4460 $

    hercules-3.07/html/hercmstt.html000644 000765 000765 00000004461 11143760535 020440 0ustar00jmaynardjmaynard000000 000000 Hercules Version 3: System Messages: TT - TOD Clock and Timer Services

    Hercules Version 3: System Messages: TT - TOD Clock and Timer Services

    This page describes the TOD Clock and Timer Services messages for the Hercules S/370, ESA/390, and z/Architecture emulator.

    Messages

    HHCTT001W Timer thread set priority priority failed: error
    Meaning
    An attempt to change the priority of the timer thread to priority failed. The error is described by error. The thread priority has not been changed. Hercules overall performance may be impaired as a result.
    Action
    If performance problems are noted, correct the error and restart Hercules.
    Issued by
    timer.c, function timer_update_thread
    HHCTT002I Timer thread started: tid=threadid, pid=processid, priority=priority
    Meaning
    The thread for timing functions has been started. Its thread id is threadid, its process id is processid and the thread priority is priority.
    Issued by
    timer.c, function timer_update_thread
    HHCTT003I Timer thread ended
    Meaning
    The thread for timing functions has ended.
    Issued by
    timer.c, function timer_update_thread


    If you have a question about Hercules, see the Hercules Frequently-Asked Questions page.


    back

    Last updated $Date: 2007-10-06 14:44:28 -0500 (Sat, 06 Oct 2007) $ $Revision: 4460 $

    hercules-3.07/html/hercmstu.html000644 000765 000765 00000002114 11143760535 020432 0ustar00jmaynardjmaynard000000 000000 Hercules Version 3: System Messages: TU - TUN/TAP device support

    Hercules Version 3: System Messages: TU - TUN/TAP device support

    This page describes the messages for the Hercules S/370, ESA/390, and z/Architecture emulator TUN/TAP support routines.

    Messages

    HHCTU001I
    Meaning
    Issued by
    tuntap.c, function


    If you have a question about Hercules, see the Hercules Frequently-Asked Questions page.


    back

    Last updated $Date: 2007-10-06 14:44:28 -0500 (Sat, 06 Oct 2007) $ $Revision: 4460 $

    hercules-3.07/html/hercmsvm.html000644 000765 000765 00000007344 11143760535 020436 0ustar00jmaynardjmaynard000000 000000 Hercules Version 3: System Messages: VM - VM/CP Emulation

    Hercules Version 3: System Messages: VM - VM/CP Emulation

    This page describes the VM/CP emulation messages for the Hercules S/370, ESA/390, and z/Architecture emulator.

    Messages

    HHCVM001I *panel_command* panel command issued by guest
    Explanation
    The guest operating system has issued a DIAGNOSE 8 instruction to perform the panel_command panel command to be carried out by the hercules panel command processor
    System Action
    The hercules panel command processor carries out the command, if possible.
    Operator Action
    None
    Programmer Action
    No action is requested if this behaviour is expected. If this behaviour poses a security concern, the DIAG8CMD configuration statement should either be ommited or specified with the disabled argument.
    Module
    vm.c

    HHCVM002I *panel_command command complete
    Explanation
    The panel_command panel command has been carried out by the panel command processor. Note that this message only appears if the guest issued diagnose 8 instruction specified that it didn't request the command response to be placed in a supplied buffer.
    System Action
    The system continues
    Operator Action
    None. This is an informational message
    Programmer Action
    None. This is an informational message
    Module
    vm.c

    HHCVM003I Host command processing disabled by configuration statement
    Explanation
    The guest operating system attempted using the DIAGNOSE 8 Instruction to carry out a panel command, but the system configuration disabled this feature (with the DIAG8CMD configuration statement)
    System Action
    The panel command is ignored.
    Operator Action
    None.
    Programmer Action
    If it is deemed necessary for the guest operating system to issue DIAGNOSE 8 commands to issue panel commands, the DIAG8CMD with the enable argument should be specified in the configuration file.
    Module
    vm.c

    HHCVM004E Host command processing not included in engine build
    Explanation
    The hercules engine has been built WITHOUT Diagnose 8 panel command facility support
    System Action
    The panel command is not issued. The system continues.
    Operator Action
    None
    Programmer Action
    If it is desired that DIAGNOSE 8 Instruction be carried out as panel commands, the facility should be included in the build process. Additionally, the DIAG8CMD configuration statement should be specified with the enable parameter.
    Module
    vm.c


    If you have a question about Hercules, see the Hercules Frequently-Asked Questions page.


    back

    Last updated $Date: 2007-10-06 14:44:28 -0500 (Sat, 06 Oct 2007) $ $Revision: 4460 $

    hercules-3.07/html/hercnew.html000644 000765 000765 00000140550 11344615422 020237 0ustar00jmaynardjmaynard000000 000000 Hercules: What's new

    What's new in Hercules


    What's new in release 3.07

    Release date: 10 March 2010

    • Fast Synchronous Data Mover Facility (Guy Desbiens)
    • Diagnose 210, 250, 260 (Harold Grovesteen)
    • Extended Diagnose 204 feature (Jan Jaeger)
    • Complete Diagnose 24 (Harold Grovesteen)
    • Configuration-Topology Facility (Fish)
    • HFP-Unnormalized-Extensions Facility (Harold Grovesteen)
    • CMPSC performance improvements (Bernard van der Helm)
    • uptime command (Fish)
    • Raise XPNDSIZE limit to 1048576MB (Roger Bowler)
    • MAXCPU and LPARNUM configuration statements (Roger Bowler)
    • Add capacity model identifiers to MODEL config statement (Roger Bowler)
    • SCLPROOT configuration statement (Jan Jaeger)
    • Add "noclear" option to printer and card punch devices (Jay Maynard)
    • Socket printer support (Fish)
    • 3705 SNA device support (Max H. Parke)
    • TTY and 2741 support for 2703 (Max H. Parke)
    • Tracing enhancements (Jan Jaeger)
    • Allow configure --enable-external-gui for Unix builds
    • Enable tun/tap emulation for 64-bit Windows builds (Ivan Warren)
    • 64-bit Windows support (Roger Bowler)
    • Raise MAX_CPU_ENGINES limit to 64 (Roger Bowler, Ivan Warren)
    • Numerous bug fixes (Ivan Warren, Fish, Jan Jaeger, Bernard van der Helm, Roger Bowler, Jay Maynard)

    Download hercules-3.07.tar.gz

    What's new in release 3.06

    Release date: 11 January 2009

    • Integrated 3270 (SYSG) console support (Roger Bowler, Jan Jaeger)
    • HMC DVD-RAM read/write support (Jan Jaeger)
    • 64-bit native version now supported on Mac OS X (Jay Maynard)
    • Ability to specify IFL, zIIP, and zAAP engine types (Roger Bowler, Jan Jaeger, Ivan Warren)
    • Console-like message handling (David "Fish" Trout, Bernard van der Helm)
    • Tape automount CCW support (David "Fish" Trout)
    • CKD Locate Record Extended CCW (Greg Smith)
    • Support for FLEX-ES FakeTape tape images (David "Fish" Trout; FLEX-ES and FakeTape are trademarks of Fundamental Software, Inc.)
    • More complete 3490 and 3590 tape support (David "Fish" Trout)
    • Solaris build support (Jeff Savit)
    • FreeBSD build support (Bjoern A. Zeeb)
    • Panel enhancements:
      • Display virtual storage in primary, secondary, and home space (Paul Leisy)
      • Display and modify PSW fields by panel command (Roger Bowler)
      • Modify control registers by panel command (Roger Bowler)
      • Specify IPL parameter by PARM operand (Ivan Warren)
      • New panel commands: automount, cmdtgt, ctc, herc, msghld, pscp, scp, sfk (David "Fish" Trout, Bernard van der Helm)
    • LEGACYSENSEID configuration statement (Ivan Warren)
    • New instruction feature support (introduced with System z10):
      • Parsing-Enhancement Facility (Bernard van der Helm)
      • Message-Security-Assist Extension 2 (Bernard van der Helm)
      • General-Instructions-Extension Facility (Roger Bowler, Jan Jaeger)
      • Execute-Extensions Facility (Bernard van der Helm)
      • Move-with-Optional-Specifications Facility (Roger Bowler)
      • Compare-and-Swap-and-Store Facility 2 (Ivan Warren)
    • Many emulation fixes (Roger Bowler, Jan Jaeger, Ivan Warren, David "Fish" Trout, Greg Smith, Paul Leisy, Jay Maynard, Bernard van der Helm, Kevin Leonard, Tony Harminc)

    Download hercules-3.06.tar.gz

    What's new in release 3.05

    Release date: 23 June 2007

    • Prebuilt Cygwin binary no longer supplied; building Cygwin version from source still supported (Jay Maynard)
    • New system features: Compare-and-Swap-and-Store, Conditional SSKE, Decimal Floating Point, Floating Point Support Enhancement (Roger Bowler)
    • Extract CPU Time Facility (Jan Jaeger)
    • Multiple Logical Channel Subsystems Facility (Jan Jaeger, Ivan Warren)
    • 3590 tape support (David "Fish" Trout)
    • 3990-6 control unit and ECKD support (Greg Smith)
    • Many performance improvements (Greg Smith, Ivan Warren, Jan Jaeger)
    • Many emulation fixes (Greg Smith, Roger Bowler, Ivan Warren, David "Fish" Trout, Kevin Leonard, Peter Coghlan)
    • Major SCSI tape fixes (David "Fish" Trout)
    • Added floating point instructions CGER, CGDR and CGXR (Bernard van der Helm)
    • Address range options for instruction trace and step (Greg Smith)
    • Update gpr registers via panel command (David "Fish" Trout)
    • Console connection keep-alive (David "Fish" Trout)
    • Customizable 3270 connection screen (Ivan Warren)
    • dasdconv quiet and stdin options (Roger Bowler)
    • Hercules Automatic Operator (Bernard van der Helm, David "Fish" Trout)
    • Enhanced symbol substitution (Leland Lucius, Enrico Sorichetti, David "Fish" Trout)
    • Miscellaneous new panel commands: qd (Greg Smith), fpc, traceopt (Roger Bowler), logopt (Kevin Leonard), cd, pwd, timerint, defsym (David "Fish" Trout)

    Download hercules-3.05.tar.gz

    What's new in release 3.04.1

    Release date: 25 March 2006

    • Fix to allow building for Intel-based Mac OS X (Jay Maynard)
      Note: This version only applies to the Mac OS X 10.4 (Tiger) platform. Version 3.04 is current for all other platforms.

    Download hercules-3.04.1.tar.gz

    What's new in release 3.04

    Release date: 24 February 2006

    • CCKD garbage collection fix (Greg Smith)
    • Reworked timing functions (Jan Jaeger)
    • Codepage 1047 conversion tables (Kevin Leonard)
    • Fixed off-by-one-day bug with SYSEPOCH other than 1900; added new config parameter, YROFFSET, and added warning if SYSEPOCH is not 1900 or 1960 (Jay Maynard, Jan Jaeger)
    • New 2305 CKD disk emulation (Jay Maynard)
    • Added floating point instructions CEGR, CDGR and CXGR (Bernard van der Helm)
    • Added support for cgi-bin dynamic modules (David "Fish" Trout)
    • Instruction fixes: PLO, CVB, CXFBR, CXGBR (Bernard van der Helm, David "Fish" Trout, Greg Smith, Pasi Pirhonen)
    • Fix for Windows ..\relative path dasd files (David "Fish" Trout)

    Download hercules-3.04.tar.gz

    What's new in release 3.03.1

    Release date: 30 December 2005

    • Fix translation exception bug that was causing some Linux kernels to panic (Fabrizio Calabretta, Greg Smith, Ivan Warren)
    • TOD Clock-Steering Facility (Jan Jaeger, Bernard van der Helm)
    • Fix bug in shadow file filename processing on native Windows (David "Fish" Trout)
    • Performance improvements in TM instruction family (Bernard van der Helm)
    • Support for Linux zipl LOADPARM of PROMPT (Jan Jaeger)

    Download hercules-3.03.1.tar.gz

    What's new in release 3.03

    Release date: 20 December 2005

    • Native Windows version no longer requires Cygwin (David "Fish" Trout, Roger Bowler, Ivan Warren)
    • SMP host integrity fixes (Greg Smith, David "Fish" Trout, Bob Deblier)
    • ALS5, z9 and other architectural enhancements (Roger Bowler, Bernard van der Helm, Jan Jaeger, David "Fish" Trout)
    • Restructured cryptographic support no longer depends on libgcrypt (Bernard van der Helm, Roger Bowler, Ivan Warren)
    • Support emulation of up to 32 CPUs; maximum without special build options now 8 (Ivan Warren)
    • Enhanced semigraphical control panel now uses all of larger console windows (Greg Smith, David "Fish" Trout)
    • Many emulation fixes (Roger Bowler, Jan Jaeger, Bernard van der Helm, David "Fish" Trout, Greg Smith, Ivan Warren, Andy Styles, John Decker)
    • CMPSC fixes now produce identical results with real systems (Jacques Dilbert, Bernard van der Helm)
    • Integrated 1052-C / 3215-C console support (Jan Jaeger)
    • tapecopy support for writing as well as reading tapes (Jay Maynard)

    Download hercules-3.03.tar.gz

    What's new in release 3.02

    Release date: 11 December 2004

    • Significant performance improvements (Jan Jaeger, Greg Smith, Gabor Hoffer)
    • SIE performance almost the same as native (Jan Jaeger, Gabor Hoffer)
    • SCSI tape support in Windows (David "Fish" Trout)
    • Mac OS X CTC networking support (Jay Maynard)
    • Suspend/resume facility (Greg Smith)
    • ASN-and-LX-Reuse Facility (Roger Bowler)
    • Enable or disable ASN-and-LX-reuse in config (Jan Jaeger, Ivan Warren)
    • Extended Translation Facility 3 (Bernard van der Helm)
    • DAT-enhancement facility (Roger Bowler)
    • Immediate CCWs now correctly handled when Suppress Incorrect Length Indication is specified (Ivan Warren)
    • 3270 option provided to control connection to group of devices (Ivan Warren)
    • 3270 connections can be limited by IP address (David "Fish" Trout)
    • Remaining 26 binary floating point instructions (Roger Bowler)
    • IPL CLear, System Reset, and System Reset Clear operator commands (Ivan Warren)
    • Pentium 4 optimizations enabled in gcc (Ivan Warren)

    Download hercules-3.02.tar.gz

    What's new in release 3.01

    Release date: 30 November 2003

    • Bypass gcc 2.96 optimizer bug that caused incorrect instruction execution (Ivan Warren)
    • Added command-line control panel command history (Martin Gasparovic, Volker Bandke)
    • Message Security Assist (Bernard van der Helm, Jan Jaeger)
    • Fixed device interrupt pending on IPL that caused OS/360 to have to be IPLed twice (David "Fish" Trout, Greg Smith)
    • Added pthreads trace function for debugging (Greg Smith)
    • Fish threads code rewritten, closer to POSIX thread functionality while still performing better (David "Fish" Trout)
    • Fixed incompatibility with Windows NT telnet client (Greg Price, David "Fish" Trout)
    • Performance and integrity enhancements for RS instructions (Greg Smith)

    Download hercules-3.01.tar.gz

    What's new in release 3.00

    Release date: 2 October 2003

    • Dynamically loaded module support for devices, instructions, and operator console panels (Jan Jaeger, David "Fish" Trout, Ivan Warren)
    • Shared and remote DASD support (Greg Smith)
    • z990 (ALS4) instruction support (Roger Bowler, Jan Jaeger, Bernard van der Helm)
    • HFP Multiply-Add/Subtract Facility (Roger Bowler)
    • Long Displacement Facility (Roger Bowler)
    • Simplified network adapter specifications (David "Fish" Trout, Jim Pierson)
    • New device emulations: 2703, 3410, 3490, 9347 (Ivan Warren)
    • ECPS:VM support (Ivan Warren)
    • Reworked process priority handling (Mark Gaubatz)
    • Greatly improved interval timer resolution (Mark Gaubatz)
    • Internal consistency checking improvvements (Greg Smith)
    • Corrected 3270 session disconnect processing (Ivan Warren)
    • Instruction disassembler in control panel (Jan Jaeger)
    • Tape read backward fixes (Jay Jaeger)
    • Fix for double memory consumption bug on Windows (Mark D., David "Fish" Trout)
    • OMA tape processing fixes (Ivan Warren)
    • Message logging restructuring (Jan Jaeger, David "Fish" Trout)
    • S/370 I/O race condition fixes (Victor Shkamerda, Greg Smith)
    • Manual pages for some commands (Jim Morrison)

    Download hercules-3.00.tar.gz

    What's new in release 2.17.1

    Release date: 12 February 2003

    • Corrected RPM installed files permissions (John Summerfield)
    • Corrected dasdload verbosity level (Jay Maynard)
    • Corrected card reader eof/intrq option handling, added * to designate no file loaded (Jay Maynard)
    • Correct SLB instruction condition code (Jan Jaeger)
    • Fix dasdutil.c track conversion function (Jim Morrison)

    Download hercules-2.17.1.tar.gz

    What's new in release 2.17

    Release date: 1 February 2003

    • Restructured DASD subsystem: better use of memory, compressed FBA support, framework for shared DASD (Greg Smith)
    • New dasdcopy utility replaces ckd2cckd and cckd2ckd, and adds compressed FBA support (Greg Smith)
    • Native support for Mac OS X 10.2 and above (Paul Scott)
    • Reworked CTC and LCS emulation (Jim Pierson)
    • SMP host integrity fixes (Greg Smith and Jan Jaeger)
    • Fixes for compile errors with gcc 3.x (Greg Smith and David "Fish" Trout)
    • S/370 dual address space and MVS assist fixes (Jan Jaeger)
    • Renumbered all messages to consistent format, removed duplicate numbers, and began message documentation (Jay Maynard)
    • Added options for 1052/3215 consoles and card readers (Jay Maynard)
    • Numerous instruction and I/O emulation fixes (Greg Smith, Jan Jaeger, Juergen Dobrinski, Bernard van der Helm, Andy Norrie, and David "Fish" Trout)

    Download hercules-2.17.tar.gz

    What's new in release 2.16.5

    Release date: 8 July 2002

    • Correct serious CCKD image file corruption error (Greg Smith)
    • Allow tape files to be opened for input if on CD-ROM (Volker Bandke)

    Download hercules-2.16.5.tar.gz

    What's new in release 2.16.4

    Release date: 3 July 2002

    • Read backward support for emulated tape (Volker Bandke)
    • Added 9313, 9332, and 9335 to list of supported devices (Tomas Masek)

    Download hercules-2.16.4.tar.gz

    What's new in release 2.16.3

    Release date: 2 July 2002

    • CTC fix for TurboLinux bug (Jim Pierson)
    • 3287 printer support via TN3270 (Tomas Masek)
    • S/370 extended memory fixes (Tomas Masek)
    • ctcadpt.c compilation fix for FreeBSD (Mark Szlaga)
    • Fixed 3270 ERASE ALL UNPROTECTED command to not count data read (Tomas Fott)
    • Fixes to ckdtab in dasdtab.c (Greg Smith)
    • Retrofitted cckd chkdsk fixes/enhancements (Greg Smith)
    • FBA fixes contributed by Tomas Masek (Greg Smith)
    • Compatibility fixes for cckd and 2.17 (Greg Smith)

    Download hercules-2.16.3.tar.gz

    What's new in release 2.16.2

    Release date: 20 May 2002

    • Fixed 3350 dasdtab entry (Greg Smith)
    • Fixed 370 interval timer error (Valery Pogonchenko)
    • Control panel attach command bug fix (David "Fish" Trout)

    Download hercules-2.16.2.tar.gz

    What's new in release 2.16.1

    Release date: 4 May 2002

    • fthreads locking fixes (David "Fish" Trout)
    • dasdload bug fix (Greg Smith)
    • FBA dasd devices allow any size disk (Jay Maynard)
    • Control panel attach command bug fix (Kris Van Hees)
    • Windows versions (finally) accessible from main page (Jay Maynard)

    Download hercules-2.16.1.tar.gz

    What's new in release 2.16

    Release date: 20 April 2002

    • PER support (Jan Jaeger, Paul Leisy)
    • S/370 multiprocessor support (Jan Jaeger)
    • Licensed software restriction (Jan Jaeger, Jay Maynard)
    • Performance mods (Gabor Hoffer, Juergen Dobrinski, Greg Smith, and Paul Leisy)
    • Interrupt subclass priorities (Greg Smith)
    • dasdcat program (Malcolm Beattie, Roger Bowler)
    • Updated TCP/IP documentation (Roger Bowler)
    • CTCI support for Windows (David "Fish" Trout)
    • Print to unix pipe (Roger Bowler)
    • Preliminary Lan Channel Station (LCS) support
    • HTTP server (Jan Jaeger)
    • Various fixes (as recorded in CHANGES) (Paul Leisy, Matt Zimmerman, Greg Smith, Volker Bandke, Bernard van der Helm, David "Fish" Trout)

    Download hercules-2.16.tar.gz

    What's new in release 2.15

    Release date: 04 December 2001

    • Autoconf added to ease portability (Matt Zimmerman, Fritz Elfert, Willem Konynenberg)
    • Numerous instruction fixes (Paul Leisy)
    • TUN/TAP support for Linux kernels beyond 2.4.6 (Matt Zimmerman)
    • Timer fixes (Greg Smith)
    • Synchronous I/O (Greg Smith)
    • Support for IPL from CD-ROMs as with HMC (Jan Jaeger)
    • CTC hang at shutdown fixed (Jan Jaeger)
    • CTC TCP/IP now works with VM/ESA (Kris Van Hees)
    • Compressed CKD endianness and RAS fixes (Greg Smith)
    • Hot reader support (David "Fish" Trout)
    • Machine checks now reported for host exceptions, loops, and wait states (Jan Jaeger)

    Download hercules-2.15.tar.gz

    (There was no release 2.14)

    What's new in release 2.13

    Release date: 05 July 2001

    • Restrict TODEPOCH to 1900, 1928, 1960, 1970, or 1988, and correct offset calculation (Michael Koehne)
    • HET unmount option (Michael Koehne)
    • quiet command (Michael Koehne)
    • Panel instruction disassembly (Jan Jaeger)
    • CMPSC corrections (Bernard van der Helm)
    • CTCT CTC over TCP/IP (Vic Cross)
    • Sundry instruction and channel fixes (Jan Jaeger)
    • Numerous instruction fixes (Paul Leisy)
    • CKD trace command (Valery Pogonchenko)
    • Performance enhancements (Juergen Dobrinski)
    • CGEBR/CGDBR instructions (Jan Jaeger)
    • CEGBR/CDGBR instructions (Kris Van Hees)
    • CKD 9345 support (Greg Smith)
    • Storage Key Assist (Jan Jaeger)
    • Move Page Facility 2 (Jan Jaeger)

    Download hercules-2.13.tar.gz

    What's new in release 2.12

    Release date: 04 May 2001

    • Numerous instruction fixes (Paul Leisy, Jan Jaeger, Peter Stammbach, Roger Bowler)
    • FBA and CKD read-only support (Greg Smith)
    • Enable ISKE/RRBE/SSKE in S/370 mode (Valery Pogonchenko)
    • CCKD corrections (Greg Smith)
    • CMPSC fixes for expansion (Greg Smith)
    • Correct prefix alignment for ESA/390 guest in 64 bit mode SIE (Jan Jaeger)
    • Card reader multiple files and EBCDIC autopad support
    • Support for built-in TUN driver of Linux kernel 2.4.x
    • Device I/O thread throttling (Greg Smith, Fish)
    • Small optimization of vstore/vfetch and TPI (Jan Jaeger)
    • Sense/Set Path Group ID for DASD (Jan Jaeger)
    • Dynamic device threads (Jan Jaeger)
    • Fast interrupt processing for MCK and PER (Jan Jaeger)
    • Allow HET files to reside on read-only media (Leland Lucius)
    • Utilities display versioning and copyright info (Greg Smith)
    • Present device end on terminating console session (Jan Jaeger)
    • sh panel command (Bernard van der Helm)
    • 9221 power-off diagnose (Jan Jaeger)
    • Debug format enhancements (Peter Stammbach)
    • Fix for device threads (Juergen Dobrinski)
    • Sundry new ESAME instructions and corrections (Roger Bowler, Jan Jaeger)
    • Improved interrupt processing (Valery Pogonchenko)
    • Incorrect-Length-Indication-Suppression facility (Jan Jaeger)
    • S/370 interval timer fixes (Mark Gaubatz)
    • 64-bit Interpretive Execution (Jan Jaeger)
    • IEEE floating point (Willem Konynenberg)
    • 64-bit panel updates (Roger Bowler)
    • LPM fixes and display subchannel command (Nobumichi Kozawa)
    • Fix amode64 in load_psw (Ulrich Weigand)
    • Multiply Logical instructions (Vic Cross)
    • Environment variables to override filenames of hercules.rc hercules.cnf and hercifc (Jan Jaeger)
    • Floating point enhancements (Roger Bowler, Jan Jaeger)
    • Country codepage tables (Roger Bowler)

    Download hercules-2.12.tar.gz

    What's new in release 2.11

    Release date: 09 February 2001

    • Sundry new ESAME instructions and corrections (Jan Jaeger)
    • Panel display instruction operands (Roger Bowler)
    • TRAP and RP instructions (Jan Jaeger)
    • TP instruction (Roger Bowler)
    • Tape data chaining patch (Brandon Hill)
    • Bypass Cygwin stack problem (Greg Smith)
    • Fixes for Windows port (Volker Bandke)
    • SSK/ISK/RRB fix for 2K storage keys (Valery Pogonchenko, Jan Jaeger)
    • Extended Translation Facility 2 (Roger Bowler)
    • Divide Logical instructions (Vic Cross)

    Download hercules-2.11.tar.gz

    What's new in release 2.10

    Release date: 02 February 2001

    • z/Architecture support (Jan Jaeger)
    • TUN/TAP support for CTC (Roger Bowler)
    • OSTAILOR VSE option (Roger Bowler)
    • 2K/4K storage key support (Jan Jaeger)
    • Fully functional CMPSC instruction (Bernard van der Helm)
    • Fix read-only AWSTAPE (Roger Bowler)
    • Sundry new ESAME instructions (Jan Jaeger, Roger Bowler)
    • Format-2 2K/4K IDAW (Roger Bowler)
    • ESAME 5-level DAT (Roger Bowler)
    • ESAME ASN authorization and ALET translation (Roger Bowler)
    • ESAME linkage-stack instructions (Roger Bowler)
    • ESAME subspace replacement (Roger Bowler)
    • ESAME DUCT format changes (Roger Bowler)
    • Unloaded tape drive support (Brandon Hill)
    • Extended floating point (Peter Kuschnerus)
    • Divide Single instructions (Jan Jaeger)
    • EPSW instruction (Roger Bowler)
    • Compressed CKD updates (Greg Smith)
    • Timer update correction (Valery Pogonchenko)
    • Fix MVCLE instruction (Jan Jaeger)
    • Interval Timer fix (Bob Abeles)

    Download hercules-2.10.tar.gz

    What's new in release 1.71

    Release date: 18 January 2001

    • Compressed CKD DASD support release 2, with improved performance, shadow file support, and better reliability (Greg Smith)
    • Hercules Emulated Tape format support (Leland Lucius)
    • Make HET bzip2 compression optional, analogous to CCKD bzip2 (Jay Maynard)
    • Fix for track overflow record zeroing (Roger Bowler)
    • Clarified licensing discussion in FAQ (Roger Bowler)
    • Treat printer X'37' CCW as NOP (Jay Maynard, suggested by Brandon Hill)
    • Treat X'E503' MVS/XA assist instruction as no-op (Jay Maynard, suggested by Brandon Hill)
    • Read commands from hercules.rc at startup (Willem Konynenberg)
    • New tapelist program prints contents of 80-byte record tapes (Jim Morrison)
    • Increased MAXDBLK from 3000 to 40000 and MAXTTR from 10000 to 40000 in dasdload (Volker Bandke)

    Download hercules-1.71.tar.gz

    What's new in release 1.70

    Release date: 3 December 2000

    • New file hercwin32.zip contains build scripts for Win32 version (Volker Bandke)
    • More performance enhancements (Juergen Dobrinski)
    • ALS-1 and ALS-2 support completion (Roger Bowler and Jan Jaeger)
    • Extended Translation Facility (Roger Bowler)
    • Pick up correct float.c module (Jay Maynard for Peter Kuschnerus)
    • Distribute Windows binaries as well as Linux (Jay Maynard)
    • Fix orienting bug in CKD DASD search CCW processing (Bob Abeles)
    • Obtain TOD clock lock when accessing or updating 370 interval timer (Bob Abeles)
    • Change license to the QPL Open Source Definition-compliant license (Roger Bowler, Jay Maynard, and Jan Jaeger)

    Download hercules-1.70.tar.gz

    What's new in release 1.69

    Release date: 29 October 2000

    • Correct AXR and SXR instruction results when significance exception raised (Peter Kuschnerus, with help from Mario Bezzi)
    • Correct CD and CDR instruction condition code logic (Peter Kuschnerus)
    • Do not generate support for square root instructions in 370 mode (Peter Kuschnerus)
    • Floating point arithmetic tuning (Peter Kuschnerus)
    • Performance optimization fixes (Juergen Dobrinski)
    • Spelling corrections (Adam Thornton)
    • Fixed version number (Jay Maynard)

    Download hercules-1.69.tar.gz

    What's new in release 1.68

    Release date: 8 October 2000

    • Rewritten and updated FAQ (Dave Morton)
    • Compressed CKD DASD support (Greg Smith)
    • Many performance improvements (Juergen Dobrinski, with help from Albert Louw and Valery Pogonchenko)
    • DASD I/O optimizations (Greg Smith and Malcolm Beattie)
    • Simplified building on non-Intel architectures (Jay Maynard)
    • Fix for random bug in MP instruction (Mario Bezzi)
    • Treat all 3505 card reader read CCWs the same (Jay Maynard)

    Download hercules-1.68.tar.gz

    What's new in release 1.67

    Release date: 4 September 2000

    • Win32 portability changes (John Kozak)
    • Fix for 64K segment length checking in 370 DAT (Jay Maynard, found by Mario Bezzi)
    • Fix for TPI storing interrupt code when no interrupt pending (Jay Maynard, found by Greg Smith)
    • Skip to channel 9 and 12 support (Roger Bowler)
    • Panel refresh rate speedup and command (Reed Petty)
    • Fix storage protection override on fetch (Jan Jaeger)
    • SIE support, with S/370 and ESA/390 modes and vector support (Jan Jaeger)
    • Bugfix for MXR instruction (by Peter Kuschnerus)
    • CONCS, DISCS and RCHP instructions (Jan Jaeger)
    • Fix flags on intermediate subchannel status (Jan Jaeger)
    • Break SYSCONS output lines when too long (Jan Jaeger)
    • Floating point instructions SQDR and SQER (by Peter Kuschnerus)
    • Lock Page instruction (Jan Jaeger)

    Download hercules-1.67.tar.gz

    What's new in release 1.66

    Release date: 3 August 2000

    • Simplify logmsg and DEVTRACE macro definitions (Jay Maynard)
    • Prevent incorrect length indication on CONTROL NOP CCW (Jay Maynard)
    • Complete 370 HIO processing (Jay Maynard)
    • Correct nullification of TPI and TSCH (Jan Jaeger)
    • Add device locking to MSCH (Jan Jaeger)
    • Correct TPROT instruction (Jan Jaeger)
    • Correct address wrapping on assist instructions (Jan Jaeger)
    • Change interrupt logic to use longjmp on all interrupts (Jan Jaeger)
    • Clear remainder of ASTE when loading ASTE with ASF=0 in translate_asn (Jan Jaeger)
    • Add (incomplete) PLO instruction (Jan Jaeger)
    • Fix CLCL interruption problem (Jan Jaeger)
    • Fix addresswrap in MVO (Jan Jaeger)
    • Make ED and EDMK perform a trial run (Jan Jaeger)
    • Fix address wraparound in MVO (Jan Jaeger)
    • Fix CR15 corruption in form_stack_entry, fix nullification in form_stack_entry and unstack_registers (Jan Jaeger)
    • Fix loss of interrupts in PR (Jan Jaeger)

    Download hercules-1.66.tar.gz

    What's new in release 1.65

    Release date: 22 July 2000

    • Track overflow processing fixes (by Jay Maynard, suggested by Valery Pogonchenko)
    • Added TOD clock update to STCK, STCKE, DIAG 204, and TRACE processing (by Jay Maynard)
    • Fixed READ DEVICE CHARACTERISTICS alternate track values for 3380 and 3390 (by Peter Macdonald)
    • Skeletal CMPSC instruction (by Bernard van der Helm)
    • Added support for 3340 and 3375 DASD (by Jay Maynard, with help from Rick Fochtman and David Cole)
    • Corrected interval timer update increment (by Jay Maynard)
    • float.c optimization for new instruction decode and execution (by Peter Kuschnerus)
    • Fix program check on TIC ccw (by Jan Jaeger)
    • Fix program check on NOP ccw (by Jan Jaeger)
    • Instruction decode & execution restructure (by Jan Jaeger)
    • Added -fomit-frame-pointer to compiles for improved performance (by Jan Jaeger)
    • Fix STCKE instruction (by Bernard van der Helm)

    Download hercules-1.65.tar.gz

    What's new in release 1.64

    Release date: 4 July 2000

    • Added track overflow processing for CKD DASD (by Jay Maynard)
    • Makefile change to allow RPM building with RPM_BUILD_ROOT (by David Barth)
    • Added NetBSD build definitions to makefile (by Soren Jorvang)
    • Moved version definition to version.h and removed makefile dependency for source modules (by Jay Maynard)
    • Package change: tarball now explodes into hercules-<version> subdirectory (by Jay Maynard, suggested by Soren Jorvang)
    • Fix backward going TOD clock (by Jan Jaeger)
    • Suppress superflous HHC701/HHC702 messages (by Jan Jaeger)
    • Rework cpu.c to decode instructions by macro (by Jan Jaeger)
    • Bypass bug in IBM telnet client (by Jan Jaeger)

    Download hercules-1.64.tar.gz

    What's new in release 1.63

    Release date: 18 June 2000

    • 3270 CCW processing improvements (by Jan Jaeger)
    • OSTAILOR generalization, and new pgmtrace panel command (by Jan Jaeger)
    • VM IUCV instruction correction and DIAGNOSE improvements (by Jan Jaeger)
    • CPU timer and clock comparator improvements (by Jan Jaeger, after a suggestion by Willem Konynenberg)
    • 3480 READ BLOCK ID and LOCATE CCW support (by Brandon Hill)
    • Networking support via virtual CTCA (by Willem Konynenberg)
    • Restructured CPU execution, by function call instead of switch statement (by Mike Noel)
    • Support for IEBCOPY sequential output datasets in dasdload (by Ronen Tzur)
    • New dasdls command lists the VTOC of a CKD DASD volume (by Malcolm Beattie)
    • New AWSTAPE handling commands: tapesplt, tapemap (by Jay Maynard)
    • make install target to install in /usr/bin (by Jay Maynard)

    Download hercules-1.63.tar.gz

    What's new in release 1.62

    Release date: 3 June 2000

    • Still more multiprocessor improvements (by Jan Jaeger)
    • Dynamic CPU reconfiguration (by Jan Jaeger)
    • Basic vector facility (by Jan Jaeger)
    • Floating point version 6 (by Peter Kuschnerus)
    • READ AND RESET BUFFERED LOG CCW (X'A4') support (by Jay Maynard)
    • WRITE SPECIAL CKD CCW (X'01') support (by Jay Maynard)
    • FBA DASD model reporting fixes (by Jay Maynard)

    Download hercules-1.62.tar.gz

    What's new in release 1.61

    Release date: 21 May 2000

    • More multiprocessor improvements (by Jan Jaeger)
    • New startall/stopall panel commands (by Jan Jaeger)
    • STIDP stores processor address in first digit of CPU id (by Roger Bowler)
    • Correction to IPTE instruction for S/370 (by Jay Maynard)
    • Dummy HIO instruction for S/370 (by Jay Maynard)
    • Support for emulated 0671 FBA DASD (by Jay Maynard)
    • FBA device reserve/release CCW support (by Jay Maynard)
    • New OSTAILOR configuration option allows selective suppression of program check messages (by Jay Maynard)

    Download hercules-1.61.tar.gz

    What's new in release 1.60

    Release date: 14 May 2000

    • Multiprocessor locking improvements (by Jan Jaeger)
    • Machine check and channel report word (by Jan Jaeger)
    • Store Channel Report Word (STCRW) instruction (by Jan Jaeger)
    • New attach/detach/define commands to allow dynamic addition and deletion of devices from the configuration (by Jan Jaeger)
    • Compare and Swap and Purge (CSP) instruction (by Jan Jaeger)
    • Broadcasted purging (by Jan Jaeger)
    • Fix LASP instruction SASN authorization using wrong AX if bits 29-31 are 010 and SASN \= PASN (by Mario Bezzi)
    • Fix SAC instruction special operation exception setting secondary space mode when ASF=0 (by Mario Bezzi)
    • Remove intdrag option and replace drag command by toddrag command
    • New extpending flag to improve performance (originally contributed by Valery Pogonchenko and enhanced by Jan Jaeger)
    • Allow longer host name in console connected message (by Jay Maynard)
    • Floating point version 5 including fixes by Mario Bezzi (contributed by Peter Kuschnerus)

    Download hercules-1.60.tar.gz

    What's new in release 1.59

    Release date: 30 Apr 2000

    • Missing interrupt after CSCH instruction
    • S/370 DAT support (contributed by Jay Maynard)
    • Tape device sense byte improvements (by Jan Jaeger)
    • Read Buffered Log (CCW X'24') for tape devices (by Jan Jaeger)
    • Reject Sense ID CCW for 3420 tape devices (by Jan Jaeger)
    • Suppress unprintable character in HMC messages (by Jan Jaeger)
    • Suppress attention interrupt if subchannel not enabled (by Roger Bowler)
    • New interrupt drag factor to improve performance (by Roger Bowler)
    • New toddrag and intdrag config options and drag control panel command allow drag factors to be set (by Roger Bowler)
    • Light optimization on CPU critical path (by Valery Pogonchenko)
    • Eliminate fetch protection override in S/370 mode (by Valery Pogonchenko)

    What's new in release 1.58

    Release date: 22 Apr 2000

    • Support for CKD DASD volumes exceeding 2GB such as 3390-3 (by Roger Bowler)
    • 3274-1D SELECT RB/RMP/RBP/WRT commands (by Roger Bowler)
    • Support for 3270 14-bit SBA addressing and inbound SFE order (by Roger Bowler)
    • Command reject if Write Structured Field CCW issued to a 3270 without extended attributes (by Roger Bowler)
    • Fix missing CSW_IL indication when CCW count exhausted (by Roger Bowler)
    • Do not set unit exception if CCW count is zero (by Jan Jaeger)
    • Suppress space switch event program check messages (by Jan Jaeger)
    • Branch tracing and cross memory tracing for BALR, BASR, BASSM, BAKR, BSA, BSG, SSAR, PC, PT, PR instructions (by Jan Jaeger)
    • New diagnose instruction to stop CPU (by Jan Jaeger)
    • Drag factor option slows down TOD clock, to decrease overhead on very slow machines (by Jan Jaeger)
    • Correction to PR instruction (by Jan Jaeger)
    • Correction to LASP instruction (by Jan Jaeger)
    • Make CLCLE/MVCLE/CKSM instructions conditional features (by Jan Jaeger)
    • Enable channel measurement mode (by Jan Jaeger)
    • Modify program_check() to handle shadow registers correctly (by Jan Jaeger)
    • Change DAT to favour PSTD in TEA, to give reduction in page fault path length (by Jan Jaeger)
    • Avoid clearing registers at CPU reset (by Jan Jaeger)
    • Leave GPR, AR and FPR intact during CPU reset for SADUMP (by Jan Jaeger)
    • Zeroize field for called space identification in PC stack entry (by Jan Jaeger)
    • New CCW X'8D' (Write Update Key and Data) required by STOW (by Jan Jaeger)
    • Fix for 0B7 abend in D M=CHP command (by Jan Jaeger)
    • Floating point version 4 including fixes by Valery Pogonchenko (contributed by Peter Kuschnerus)
    • Fix incorrect second operand address in MVCIN instruction (by Roger Bowler)
    • Correct sign of zero result in SRP instruction (by Roger Bowler)
    • Erase Gap (CCW X'17') for tape devices (by Roger Bowler)
    • Activate MIPS counter on control panel (by Dutch Owen)
    • Suppress tracing of ISK, SCK, and DP instructions

    What's new in release 1.57

    Release date: 30 Mar 2000

    • Fix program check 0032 due to wrong stack entry being updated
    • Fix wrong SSTD loaded by LASP instruction (found by Jan Jaeger)
    • Bypass main storage lock in single CP configuration (by Jan Jaeger)
    • Fix incorrect condition code in PGIN instruction (by Jan Jaeger)
    • Corrections to expanded storage instructions (by Jan Jaeger)
    • New STCPS and SCHM instructions (by Jan Jaeger)
    • Set more appropriate sense bytes for tape errors

    What's new in release 1.56

    Release date: 28 Mar 2000

    • Fix incorrect unit exception on SCSI tape FSB/BSB CCW (reported by Daniel Rudin)
    • Fix unit check on AWSTAPE write (reported by Axel Schwarzer)
    • Close SCSI tape after tape is ejected
    • Detect tapemark during SCSI tape FSB/BSB CCW
    • Suppress HMC response prompt (by Jan Jaeger)
    • Expanded storage support (by Jan Jaeger)
    • Move Page Facility 2
    • Correct signed length error in MVCK/MVCS/MVCP (by Jan Jaeger)
    • Undetected CC=3 in SRP instruction
    • Wrong remainder in DP instruction when dividend is less than divisor
    • Specification exception in DP instruction should have higher priority than data exception

    What's new in release 1.55

    Release date: 22 Mar 2000

    • FBA minidisk support
    • Additional diagnose functions
    • Allow real storage frames to be marked unusable (by Jan Jaeger)

    What's new in release 1.54

    Release date: 18 Mar 2000

    • Address wraparound improvement (contributed by Jan Jaeger)
    • Floating point version 3 (contributed by Peter Kuschnerus)
    • Correction to SLDA/SRA instructions (contributed by Jan Jaeger)
    • Recognize tabs and end-of-file character in ASCII cardrdr files
    • Hercules-specific diagnose instructions (contributed by Jay Maynard)
    • Correct missing timer interrupt when interval timer goes from zero to negative (thanks to Valery Pogonchenko)
    • Enable HMC system console in S/370 mode
    • Correct sign propagation in multiply instruction
    • Reduce CPU thread priority (thanks to Steve Gay and Reed H.Petty)

    What's new in release 1.53

    Release date: 01 Mar 2000

    • Add BSF/FSF/BSB/FSB CCW support for tape devices
    • Allow final short block in OMA fixed block files
    • Allow processing of read-only AWSTAPE files and SCSI tapes
    • Skeleton ctcadpt module for future 3088 support
    • Correctly nullify IC/NI/OI/XI/CLM/STCM/ICM/TRT instructions on page translation exception (thanks to Jan Jaeger)
    • Improved floating point support (contributed by Peter Kuschnerus)
    • Correct shift result when shift count exceeds 31 (thanks to Glen Herrmannsfeldt and Jay Maynard)
    • Fix incorrect MVCL cc=3 when destination length is 1

    What's new in release 1.52

    Release date: 19 Feb 2000

    • Prevent incorrect length indication on 3270 Select CCW
    • 2K storage protection for S/370
    • Prevent wait for console port (thanks to Malcolm Beattie)
    • Allow keyword parameters in configuration file
    • New sysepoch and tzoffset parameters (thanks to Jay Maynard)
    • Adjust TRACE and DIAG204 for extended TOD (thanks to Jan Jaeger)
    • Set TOD clock in SCK instruction (thanks to Jan Jaeger)

    What's new in release 1.51

    Release date: 15 Feb 2000

    • 3270 read buffer fix for OS/360 NIP
    • Floating point instructions (contributed by Peter Kuschnerus)
    • Remove 32-bit pointer dependency from dasdload for Alpha
    • HMC system console support (contributed by Jan Jaeger)
    • Correct condition code after decimal overflow (thanks to Jan Jaeger)
    • Set reference and change bits for PSA access (thanks to Jan Jaeger)
    • New CRLF option for printer and card punch (default is now LF)

    What's new in release 1.50

    Release date: 10 Feb 2000

    • Remove interval timer debugging message
    • Fix hung console resulting from attention interrupt fix in 1.49
    • Seek and Set Sector (CCW=27) for Itel 7330 DASD controller
    • Correct SIGP handling of non-existent CPUs (thanks to Jan Jaeger)
    • Extended TOD clock bit in processor features (thanks to Jan Jaeger)
    • Alternate control panel help text (contributed by Dutch Owen)
    • Card reader end of file option (thanks to Dutch Owen)
    • Card reader ASCII/EBCDIC auto-detection
    • Fix SIGP RESTART to target correct CPU (thanks to Jan Jaeger)
    • Allow VTOC size and location to be specified for dasdload.

    What's new in release 1.49

    Release date: 05 Feb 2000

    • Alternate control panel (contributed by Dutch Owen)
    • Present attention interrupt when console connects
    • Fix dasdload CVOL logic (thanks to Jay Maynard)
    • Fix dasdload initialization of empty PDS
    • Allow device size to be specified for dasdload Note: the volser record in the pack layout file must be changed to specify the device type and cylinder count; the device type is no longer specified on the command line.
    • Add dummy Set Clock instruction (does nothing except set cc 0)

    What's new in release 1.48

    Release date: 31 Jan 2000

    • Fix dasdload to handle note lists (prevent 32D abend)
    • I/O interrupt performance enhancement
    • Correctly detect overflow in signed Add/Subtract instructions
    • Fix track overflow problem
    • 3270 Read Modified CCW

    What's new in release 1.47

    Release date: 23 Jan 2000

    • Allow tn3270 or telnet client to connect to specific device number
    • Align control panel instruction counter (thanks to Mario Bezzi)
    • Ensure panel display does not corrupt TEA (by Jan Jaeger)
    • STIDP incorrectly propagates high order bit of CPU model (fixed by Jan Jaeger)
    • Fix byte-ordering problem with CKD DASD header on non-Intel machines (reported by Adam Thornton)
    • STIDC instruction
    • Extended TOD clock (STCKE and SCKPF instructions)
    • 3211 Load FCB and Diagnostic Read CCW
    • 3270 Read Buffer CCW
    • Fix console.c to inhibit input while console has status pending

    What's new in release 1.46

    Release date: 11 Jan 2000

    • HSCH instruction
    • SIGP instruction
    • Suppress tracing of page faults
    • Display control registers and access registers after program check
    • Add regs parameter to program_check function calls
    • New panel command to perform store status function
    • Suppress tracing of CCW file protect and end of cylinder errors

    What's new in release 1.45

    Release date: 08 Jan 2000

    • Make MVCL/CLCL interruptible (contributed by Jan Jaeger)
    • Diagnose 204 (contributed by Jan Jaeger)
    • Read Channel Subsystem Info (contributed by Jan Jaeger)
    • Fix incorrect register count in TRACE instruction
    • Correct nullification of STM/LM/LAM/STAM/STCTL/LCTL/STCM and SS instructions whose operands cross a page boundary
    • Suppression on Protection with Virtual-Address enhancement
    • Select correct address space for MVCS/MVCP (fixed by Jan Jaeger)
    • Correct registers after CLCL/CLCLE with non-zero condition code
    • Defer clock comparator interrupt while instruction stepping
    • Remove 32K limit on data chained write CCWs for non-CKD devices
    • Correct overrun error on data chained write for FBA DASD

    What's new in release 1.44

    Release date: 01 Jan 2000

    • Support for 9336 FBA DASD
    • Read Replicated Data command for FBA DASD
    • Prevent recursive program check after instruction fetch error
    • Operand tracing for MVCL/CLCL and RRE instructions

    What's new in release 1.43

    Release date: 27 Dec 1999

    • New control panel command: devlist
    • Write Update Data (X'85') CCW for CKD devices
    • Makefile changed to use $(CC) instead of cc
    • Fix dat.c to prevent ASN translation specification exception (program check X'0017') if subspace group facility is installed and ASF is one
    • Fix cpu.c to clear ILC before fetching instruction to prevent PSW being backed up if access error occurs during instruction fetch
    • Correct program check ILC when instruction is nullified
    • Obtain CPU model number for STIDP from configuration file (contributed by Jay Maynard) Note: if upgrading from an earlier release, you must change your hercules.cnf file to add a valid CPU model number after the CPU serial number
    • Prevent wait after devinit (thanks to Jay Maynard)
    • Open printer with O_SYNC to ensure buffers flushed (suggested by Daniel Seagraves)
    • Fix xmem.c to prevent loop in program_call when loading 4-word ETE (thanks to Jan Jaeger)
    • Improved TLB lookup (contributed by Jan Jaeger)

    What's new in release 1.42

    Release date: 16 Dec 1999

    • New makefile builds both S/370 and ESA/390 executables: hercules-370 and hercules-390 (contributed by Jay Maynard)
    • 3480 Set Path Group Id and Unassign CCWs (contributed by Jan Jaeger)
    • CFC and UPT instructions (contributed by Peter Kuschnerus)
    • Card punch support
    • Erase (X'11') CCW for CKD devices
    • Correct setting of translation exception address
    • Correct file mode when opening printer file
    • Correct condition code for shift arithmetic instructions

    What's new in release 1.41

    Release date: 07 Dec 1999

    • Set reference and change bits correctly for main storage accesses by channel, dat, xmem, stack, block, and service modules (thanks to Jan Jaeger)
    • New devinit command (contributed by Jay Maynard)
    • Reject control panel virtual storage display command if CR1=0
    • Fix dasdload to correctly write EOF record for empty file and to correctly fill block overhead fields in format4 DSCB.
    • Diagnose functions MSSFCALL and SCPEND (contributed by Jan Jaeger)
    • Corrections to service.c and assist.c (contributed by Jan Jaeger)
    • Alpha platform portability definitions (contributed by Jay Maynard)
    • 3480 Assign CCW (thanks to Rick McKelvy)

    What's new in release 1.40

    Release date: 30 Nov 1999

    • New DASDISUP program performs OS/360 IEHIOSUP function
    • Correct SCSW handling for suspend/resume
    • Forward space file CCW for tape devices
    • 3480 load display CCW (contributed by Jan Jaeger) and sense path group id CCW (thanks to Rick McKelvy)
    • Correct handling of OMA tape headers to correctly recognize tape mark and to align headers to 16-byte boundary
    • EBCDIC character translation of CCW data displays
    • Fix command reject for CKD read commands outside the domain of a locate record

    What's new in release 1.39

    Release date: 24 Nov 1999

    • Concurrent sense
    • I/O initial status interruption
    • Channel program suspend/resume function and RSCH instruction
    • Read Device Characteristics CCW for 3480
    • Fix incorrect command reject on Sense Subsystem Status CCW
    • Increase 3270 write buffer size to prevent console I/O error when using Zap function of ZZSA
    • Fix very nasty error in dat.c causing wrong bytes to be fetched or stored when operand crosses page boundary
    • Remove temporary fix to ckddasd.c introduced in 1.37

    What's new in release 1.38

    Release date: 22 Nov 1999

    • New panel commands to allow storage alteration
    • Fix incorrect I/O parameter on attention interrupt (thanks to Jan Jaeger for reporting this bug)
    • Clear PMCW correctly during I/O reset
    • Change 3270 control unit type to 3274-1D
    • Fix restart command broken by 1.37

    What's new in release 1.37

    Release date: 19 Nov 1999

    • Storage range display
    • EBCDIC character translation of storage displays
    • New breakpoint command (contributed by Dan Horak)
    • Messages go to log file as well as screen if stdout is redirected
    • Fix missing interrupt caused by channel.c failing to obtain device lock before setting interrupt pending
    • Fix incorrect cond code 1 in attention SCSW built by console.c
    • New Read Channel Path Information service call
    • Temporary fix to ckddasd.c multitrack search
    • Addition of Read Device Characteristics and Sense Subsystem Status commands for CKD devices
    • New DASDPDSU program to unload PDS members from a CKD volume

    What's new in release 1.36

    Release date: 12 Nov 1999

    • Clear subchannel instruction
    • Correct fault causing control panel display corruption

    What's new in release 1.35

    Release date: 09 Nov 1999

    • Improved control panel user interface
    • New control panel commands: start, stop, restart, ipl, loadparm
    • New loadcore command to load disk image files
    • S/370 interval timer
    • Allow 31-bit mode linkage in lock instructions
    • Support for PCI in ESA/390 mode as well as S/370 mode
    • Correct problem causing false channel protection checks

    What's new in release 1.34

    Release date: 29 Oct 1999

    • New DASDLOAD program to create a CKD volume from unloaded PDS files
    • Correct CKD module to prevent record not found error on multitrack Read Count CCW

    What's new in release 1.33

    Release date: 26 Oct 1999

    • Write support for SCSI tapes and AWSTAPE files
    • Correct handling of REWIND command for AWSTAPE files
    • Correct nasty bug in Subtract Logical instruction (thanks to Roland Goetschi for finding this bug)
    • Ensure unique TOD clock values for Store Clock
    • Correction to unstacking process for PR instruction
    • Implementation of Read Multiple CKD command

    What's new in release 1.32

    Release date: 18 Oct 1999

    • Support for virtual tapes in OMA (Optical Media Attach) format
    • SCSI tape support (read-only)
    • Minor corrections to CKD DASD support


    If you have a question about Hercules, see the Hercules Frequently-Asked Questions page.


    back

    Last updated $Date: 2010-03-06 21:18:33 -0600 (Sat, 06 Mar 2010) $ $Revision: 5655 $

    hercules-3.07/html/hercrdr.html000644 000765 000765 00000016401 11143760535 020235 0ustar00jmaynardjmaynard000000 000000 Hercules Version 3: Submitting jobs via the socket reader

    Hercules version 3: Submitting jobs via the socket reader

    The "sockdev" option allows you to submit cards directly to a Hercules card reader from outside of Hercules. What you do is define your reader with the "sockdev" keyword and either a TCP/IP port number or the name of a Unix Domain Socket. Then whenever you want to submit a card deck to that particular card reader, you use an external program to connect to the socket and transmit the cards to the reader.

    Socket readers were implemented by Fish, based upon code originally contributed by Malcolm Beattie.

    Socket readers are defined in the Hercules configuration file like this:

    devnum devtype sockspec sockdev [option ...]

    The socket specification sockspec can take any of the following formats:

    ipaddr:port

    The reader listens on the specified IP address and port number. ipaddr must be the IP address of an interface on the local system. For example, 127.0.0.1:1234 to accept only jobs submitted locally via the loopback interface.

    hostname:port

    Similar to the previous example, where hostname must resolve to an IP address belonging to the local system. Example: localhost:1234.

    port

    The reader listens on the specified port number and accepts jobs submitted to any IP address defined on the local system. Example: 1234.

    sockpath/sockname

    The reader listens on the specified Unix Domain Socket. Example: /tmp/hercrdr.00C.

    Examples

    
        000A   2501   127.0.0.1:2501    sockdev  ascii  trunc  eof
        000C   3505   localhost:1234    sockdev  ascii  trunc  eof
        0012   3505   3505              sockdev  ascii  trunc  eof
        0014   2501   /tmp/hercrdr.014  sockdev  ascii  trunc  eof
    

    Submitting jobs from Windows

    The "HercRdr" program, distributed as part of Fish's GUI Package, allows you to send jobs to a socket reader via TCP/IP. Simply enter "HercRdr" from the command line (i.e. from either a "MSDos Prompt" window if you're using Win9x or from a "Command Prompt" window if you're using NT/2K/XP) to submit your file(s). Here's the "help information" that's displayed whenever you enter "HercRdr" without any parameters:

    
        C:\WINDOWS>hercrdr
        Submits card file(s) to a Hercules card reader bound to a given socket:port.
    
        Format:
    
         HERCRDR [-nnn] [host:port] file [file...]
    
        Where:
    
         -nnn timeout value in seconds (1-999; default is 3)
         host:port sock_spec of target reader (if not specified,
         value of HERCRDR environ var is used, if set)
         file file(s) to be submitted
    
        Examples:
    
         HERCRDR localhost:1234 fileone.txt filetwo.txt
         set HERCRDR=localhost:1234
         HERCRDR file3.txt file4.txt
         HERCRDR override:5678 filefive.txt
         HERCRDR 192.168.0.1:5678 666.txt 777.txt 888.txt 999.txt
    
        Returns:
    
         -1 unclassified error
         0 file(s) successfully submitted
         1 no route to host (bad sock_spec or connection refused)
         2 timeout value exceeded while trying to connect
         3 transmission error (e.g. connection prematurely closed)
         4 file not found (or other file error)
    
    

    How to submit jobs directly from SPF/PC

    If you are lucky enough to have a copy of SPF/PC Version 4 or SPF/Pro (produced by CTC but unfortunately no longer available), then you can capture the authentic mainframe experience by submitting jobs directly from your edit session. The SUB command can be implemented by means of a REXX macro, such as this one provided by Volker Bandke:

    
        /* +----------------------------- REXX -----------------------------+ */
        /*                                                                    */
        /*      Name: D:\APPS\SPFPRO\REXX\USER\SUB.SPF                        */
        /*                                                                    */
        /*      Type: SPF edit macro                                          */
        /*                                                                    */
        /*      Desc: submit JCL to MVS 3.8                                   */
        /*                                                                    */
        /*      Creation date: 24 Aug 1999, creation time: 18:49:40           */
        /*                                                                    */
        /*      Author: (c) Volker Bandke                                     */
        /*                                                                    */
        /* +----------------------------------------------------------------+ */
        'isredit macro (p1 p2 p3 p4 p5 p6 p7 p8 p9)'
        "ISREDIT (member) = MEMBER"
        "ISPEXEC CONTROL ERRORS CANCEL"
        parse upper var member file '.' ext
        do
        'ISREDIT REPLACE' $$$$$$$$.SPF '.ZF .ZL'
        ADDRESS "CMD" "HERCRDR 192.168.1.102:3505 $$$$$$$$.SPF"
        zedsmsg = 'File submitted'
        zedlmsg = 'The member '||member||' has been submitted to MVS'
        'ispexec setmsg msg(isrz000)'
        ADDRESS "CMD" "DELETE $$$$$$$$.SPF"
        end
        EXIT 0
    

    Submitting jobs from Unix

    Using a Perl script

    Malcolm Beattie has provided a simple Perl script which can submit jobs using either TCP/IP or Unix Domain Sockets.

    The script is invoked using one of the following command formats:

        hercsub  192.168.1.102:3505  dummy.jcl
        hercsub  /tmp/hercrdr.00C  dummy jcl
    Here is the sample script:
    
        #!/usr/bin/perl
        use Socket;
        use IO::Socket::UNIX;
        use IO::Socket::INET;
    
        if (@ARGV < 1) {
          print STDERR "Usage: hercsub socket_spec [job]\n";
          exit 2;
        }
    
        my $spec = shift @ARGV;
        my $sock;
    
        if ($spec =~ m{^/}) {
          $sock = IO::Socket::UNIX->new(Peer => $spec);
        } else {
          $sock = IO::Socket::INET->new(PeerAddr => $spec);
        }
    
        die "Failed to connect to socket $spec: $!\n" unless defined($sock);
    
        while (<>) {
          print $sock $_;
        }
    
    

    Using the netcat program

    The netcat (nc) program can also be used to submit files to a Hercules reader via TCP/IP.

    Install netcat (which is useful for innumerable other things as well) and use:

    nc -w1 localhost 1234 < dummy.jcl

    For more information, type  man nc.


    Last updated 21 Apr 2006 hercules-3.07/html/hercrnot.html000644 000765 000765 00000021625 11143760535 020434 0ustar00jmaynardjmaynard000000 000000 Hercules Version 3: Release Notes and Known Issues

    Hercules Version 3: Release Notes and Known Issues


    Release notes for release 3.03

    Release date: 20 December 2005

    New device types 1052-C and 3215-C

    The new integrated console printer-keyboard is emulated on the hercules console. Commands are sent to the console by means of a command character. (default '/', thus a logon command is sent by /logon)

    Message Security Assist

    Starting from release 3.03 the glibcrypt library is no longer needed.

    Release notes for release 3.02

    Release date: 11 December 2004

    ASN-and-LX-reuse facility

    This is a new feature of z/Architecture which can cause problems with certain versions of operating systems running in ARCHLVL=2 mode without the so-called "Driver 55" fixes. To avoid such problems, specify ASN_AND_LX_REUSE DISABLE in the configuration file.

    Release notes for release 3.01

    Release date: 30 November 2003

    Library modules and HTTP documents default directories

    An error in the 3.00 configuration script caused many users to have to override the default modules and HTTP documents directory in the Hercules configuration file, or by setting an environment variable. This error has been corrected. Hercules also now reports the actual directory that it uses by default for these files at startup time. If you specified the MODPATH or HTTPROOT configuration file statements because you encountered problems, you should examine the messages printed at startup to see if the default directories are now correct, and remove the statements if so.

    In general, MODPATH and HTTPROOT should not have to be specified except in unusual circumstances.

    Windows default directories

    In conjunction with the fix above, the default directories of the Windows distributed binaries have been changed. The new directories are under C:\cygwin\usr\local (which is the same as /usr/local under the Cygwin environment). No action is needed unless you have specified the MODPATH or HTTPROOT configuration file entries; if so, see the previous note.

    Message Security Assist

    Support for z990 crypto instructions is conditional on the presence of the glibcrypt library. When Hercules is BUILT, the development files for glibcrypt should be available. When hercules is RUN, the runtime files for glibcrypt should be installed.

    Depending on the level of glibcrypt used to *build* hercules, the associated level of glibcrypt should also be present on the target machine. On systems supporting shared library versioning, multiple levels of the glibcrypt runtime libraries can be installed simultaneously, ensuring availability of the z990 crypto instructions, regardless of the level of glibcrypt with which hercules was initially built.

    CTC and LCS device numbers

    CTC and LCS devices now MUST specify ALL addresses on the configuration statement. Previously (i.e. with version 3.00), only the first (even numbered) device needed to be defined and Hercules would automatically define the odd numbered device for you. Starting with Hercules version 3.01 however, you now need to define BOTH devices, just like you did with versions prior to 3.00. Once again, starting with version 3.01, you **MUST** define BOTH DEVICES.

    Release notes for release 3.00

    Release date: 3 October 2003

    CTCI device changes
    • The CTCI-W32 protocol is deprecated. You should use the CTCI protocol instead.
    • The VMNET protocol is also deprecated. Not even its author uses it any more. Every system on which Hercules is now prebuilt has the TUN/TAP driver functionality available in one form or another, and it's much more robust.
    Both of these will go away in a future release.

    In addition, you must not define both even/odd CTCI device pairs in your configuration file. You should only define the first even numbered device. Hercules will automatically define the odd numbered device for you. If you define the odd numbered device by mistake, an open error will occur on that device. This is by design. See the README.NETWORKING document for further details.

    Hercules Dynamic Loader support

    Starting with version 3.00, Hercules now contains support for the dynamic loading of certain modules upon startup on Linux, Windows, and Mac OS X. This support should also work on any platform supported by GNU libtool. As a result of this new feature, Hercules itself now no longer consists of just the 'hercules.exe' module by itself, but rather consists of both the 'hercules.exe' program as well as whatever dynamic modules (DLLs) that accompany it.

    As a result of this change, whenever you install a new version of Hercules, you must ensure that you ALSO install the accompanying new versions of the new dynamic modules as well. Attempting to use a version of Hercules with a dynamic module that was not specifically built for that version will cause loading of that dynamic module to fail.

    You cannot mix versions of Hercules with differing versions of dynamically loaded modules.

    Ensure that your library path (set by the environment variable LD_LIBRARY_PATH) set correctly such that it includes the directory of your Hercules dynamic load libraries. If you see message HHCCF042E, which indicates that the system is unable to locate necessary loadable modules, this is likely your problem. This should not be necessary if you have a binary download, but if you're building from source, especially if you've previously installed a binary package, this should be the first thing you do.

    ECPS:VM

    Do not use ECPS:VM (See README.ECPSVM) in an AP or MP environment in VM/370. If AP=YES or MP=YES is coded in DMKSYS and the AP/MP control file is used to build the CP nucleus and NUMCPU is set to more than 1 in the hercules.cnf file, any of LOK001, LOK003 or other abends will occur. This occurs because the Hercules ECPS:VM CP Assist implementation is not MP safe, and particularly, attempts VM dispatching without holding necessary AP or MP locks.

    Memory allocation on Windows

    Due to the change in the "mainstor" memory allocation technique used by Hercules to address a "double memory consumption" bug in Cygwin's malloc implementation, some Windows Hercules users may experience an "out of memory" error whenever Hercules is started with a large MAINSIZE configuration file value:

    HHCCF031S Cannot obtain nnnMB main storage

    This error will most likely occur (if it does at all) for those users who have manually adjusted their Cygwin heap_chunk_in_mb Windows registry setting value (in order to allow them to specify a large MAINSIZE value when running Hercules). If this problem does occur (i.e. if you do happen to experience the above mentioned error with this new release of Hercules), then either reduce your heap_chunk_in_mb value (yes, that's correct: reduce it, as in change it to a smaller value) or else remove it altogether (so as to let it default).

    A complete discussion of this issue is in the RELEASE.NOTES file in the source distribution.

    Thread priority and other problems

    There is a known problem with thread priority handling under Mac OS X. The OS X threading model is different from the one classically used in Linux. This causes failures to set the timer thread priority, and slow performance as all of Hercules is set to a low execution priority. This will be fixed in a future release. A workaround, for now, for slow performance is to add the statement

    CPUPRIO 0

    to your Hercules configuration file.

    A possibly related problem is that Hercules fails in random ways when using the NPTL (new POSIX threads library) library under Linux. This library is used by default in Red Hat 9, and possibly other systems. If problems are encountered on a very recent version of Linux, try issuing the command

    export LD_ASSUME_KERNEL=2.4.1

    before starting Hercules.


    If you have a question about Hercules, see the Hercules Frequently-Asked Questions page.


    back

    Last updated $Date: 2005-12-20 11:55:29 -0600 (Tue, 20 Dec 2005) $ $Revision: 3479 $

    hercules-3.07/html/hercsupp.html000644 000765 000765 00000027604 11143760535 020444 0ustar00jmaynardjmaynard000000 000000 Hercules Version 3: Technical Support

    Hercules Version 3: Technical Support


    Paid Support

    Hercules does not have any official (formal) paid support in place...

    ...HOWEVER...

    I'm sure if you ask the group whether or not there's anyone out there willing to provide it, you'll probably get more than one response.     ;-)

    I know for a fact that at least one person is already providing Hercules Technical Support on a paid basis, and as I said, I'm sure there are probably others out there who are either already doing it, or at least willing to do it, too. All you have to do is ask (any of the people involved with Hercules (users and/or developers)) and I'm sure more than one would be willing to provide it to you for a reasonable agreed-upon fee.

    Your best approach for obtaining fee-paid tecnical support for Hercules would be to post an inquiry to the main Hercules-390 forum (see next section below) and simply ask whether anyone out there would be willing to provide it. As I said, I'm sure there are probably many people out there who would be willing to do so for the right price.


    Free Support

    Since Hercules is an Open Source product owned by no one in particular and copyrighted by many (lots of very sharp people have contributed over the years to Hercules's success), there doesn't exist any type of official "Technical Support Department" within any type of company or anything (like there usually is for closed-source products).

    Instead, as with most Open Source products, there simply exists a dedicated group of individuals and enthusiasts who are willing to put in their spare time helping others with whatever problems and/or questions others may have regarding it. This dedicated group of Hercules enthusiasts is known as "our user community", and it honestly does, in this author's opinion, a pretty darn good job at providing whatever technical support most people find themselves needing.

    If your question and/or concern regarding Hercules is not already addressed in our FAQ (and/or within the many other areas of Hercules source-code and/or documentation (you did read it all, didn't you??)), then you might consider posting your question to either the main Hercules-390 forum or one of the more "focused" forums discussed next:


    
        HERCULES-390:   Discussion group for users of the Hercules ESA/390 mainframe emulator
    
            Community email addresses:
    
                Post message:  hercules-390@yahoogroups.com
                Subscribe:     hercules-390-subscribe@yahoogroups.com
                Unsubscribe:   hercules-390-unsubscribe@yahoogroups.com
                List owner:    hercules-390-owner@yahoogroups.com
    
            Files and archives at:
    
                http://groups.yahoo.com/group/hercules-390
    
    


    The Hercules-390 forum is your primary source for free Hercules support, and you are strongly encouraged to subscribe. We have a vibrant, active community of over 5000+ members, many of which are very knowledgeable in many different areas of mainframe technology, both from a hardware point of view as well as from an operating system and software point of view.

    In addition to the main Hercules-390 forum, other more specialized Hercules forums also exist to provide more focused support for a variety of popular IBM mainframe operating systems, such as DOS, VM, and MVS:

    Note: the use of Yahoo! as host for the Hercules-390 and related forums should in no way be interpreted as an endorsement of the Yahoo! service.


    
        H390-DOSVS:   DOS/VS and DOS/VSE under Hercules
    
            Community email addresses:
    
                Post message:  h390-dosvs@yahoogroups.com
                Subscribe:     h390-dosvs-subscribe@yahoogroups.com
                Unsubscribe:   h390-dosvs-unsubscribe@yahoogroups.com
                List owner:    h390-dosvs-owner@yahoogroups.com
    
            Files and archives at:
    
                http://groups.yahoo.com/group/h390-dosvs
    
    
    
        H390-MVS:   Hercules-390 users whom are trying to run MVS
    
            Community email addresses:
    
                Post message:  h390-mvs@yahoogroups.com
                Subscribe:     h390-mvs-subscribe@yahoogroups.com
                Unsubscribe:   h390-mvs-unsubscribe@yahoogroups.com
                List owner:    h390-mvs-owner@yahoogroups.com
    
            Files and archives at:
    
                http://groups.yahoo.com/group/h390-mvs
    
    
    
        TURNKEY-MVS:   Support for Volker Bandke's "MVS Tur(n)key System", a freely available
                       pre-built MVS 3.8J Operating System running under the Hercules emulator!
    
            Community email addresses:
    
                Post message:  turnkey-mvs@yahoogroups.com
                Subscribe:     turnkey-mvs-subscribe@yahoogroups.com
                Unsubscribe:   turnkey-mvs-unsubscribe@yahoogroups.com
                List owner:    turnkey-mvs-owner@yahoogroups.com
    
            Files and archives at:
    
                http://groups.yahoo.com/group/turnkey-mvs
    
    
    
        H390-VM:   Hercules-390 users that are trying to run VM/370, VM/SP, & VM/ESA
    
            Community email addresses:
    
                Post message:  h390-vm@yahoogroups.com
                Subscribe:     h390-vm-subscribe@yahoogroups.com
                Unsubscribe:   h390-vm-unsubscribe@yahoogroups.com
                List owner:    h390-vm-owner@yahoogroups.com
    
            Files and archives at:
    
                http://groups.yahoo.com/group/h390-vm
    
    
    
        HERC-4PACK:   Support for Andy Norrie's 4 pack Hercules VM system.
    
            Community email addresses:
    
                Post message:  herc-4pack@yahoogroups.com
                Subscribe:     herc-4pack-subscribe@yahoogroups.com
                Unsubscribe:   herc-4pack-unsubscribe@yahoogroups.com
                List owner:    herc-4pack-owner@yahoogroups.com
    
            Files and archives at:
    
                http://groups.yahoo.com/group/herc-4pack
    
    
    
        HERCULES-390-ANNOUNCE:   General announcements regarding the Hercules-390 emulator
    
            Community email addresses:
    
                Post message:  hercules-390-announce@yahoogroups.com
                Subscribe:     hercules-390-announce-subscribe@yahoogroups.com
                Unsubscribe:   hercules-390-announce-unsubscribe@yahoogroups.com
                List owner:    hercules-390-announce-owner@yahoogroups.com
    
            Files and archives at:
    
                http://groups.yahoo.com/group/hercules-390-announce
    
    
    
        HERCULES-ADVOCACY:   Advocacy of issues relating to the Hercules emulator for IBM mainframe systems.
    
            Community email addresses:
    
                Post message:  hercules-advocacy@yahoogroups.com
                Subscribe:     hercules-advocacy-subscribe@yahoogroups.com
                Unsubscribe:   hercules-advocacy-unsubscribe@yahoogroups.com
                List owner:    hercules-advocacy-owner@yahoogroups.com
    
            Files and archives at:
    
                http://groups.yahoo.com/group/hercules-advocacy
    
    
    
        HERCULES-S370ASM:   Forum discussing use of S/370 assembler with the Hercules emulator
    
            Community email addresses:
    
                Post message:  hercules-s370asm@yahoogroups.com
                Subscribe:     hercules-s370asm-subscribe@yahoogroups.com
                Unsubscribe:   hercules-s370asm-unsubscribe@yahoogroups.com
                List owner:    hercules-s370asm-owner@yahoogroups.com
    
            Files and archives at:
    
                http://groups.yahoo.com/group/hercules-s370asm
    
    



    back

    Last updated $Date: 2006-09-26 04:40:44 -0500 (Tue, 26 Sep 2006) $ $Revision: 3986 $

    hercules-3.07/html/herctcp.html000644 000765 000765 00000037277 11143760535 020252 0ustar00jmaynardjmaynard000000 000000 Hercules Version 3: TCP/IP networking with Hercules

    Hercules version 3: TCP/IP networking with Hercules

    This page describes how to set up TCP/IP connectivity between a Hercules machine and the outside world.

    Since Hercules runs as a user process under the control of a driving system (usually Linux/x86 or Windows), it does not have direct access to the driving system's network adapter. This presents a problem in establishing connectivity between the network and the TCP/IP stack of an operating system running under Hercules.

    But thanks to a technique originally demonstrated by Willem Konynenberg, it is possible to establish a virtual point-to-point link between the TCP/IP stack running under Hercules and the TCP/IP stack of the driving system. The driving system is then used as a router to pass IP frames between the Hercules TCP/IP stack and the rest of the network, as shown in the following diagram:

            +--------------------------------+
            |     Linux/x86 Driving System   |
            |                                |
            +-------------+                  |
            |  Hercules   |                  +--------+
            |-------------|                  |  eth0  |
            |   OS/390    |      TCP/IP ------------------> Network
            |   TCP/IP    |                  |10.1.2.1|
            |-------------|         |        +--------+
            |    CTCA     |         |        |
            |192.168.200.1|         |        |
            +------|------+   192.168.200.2  |
            |  /dev/tun           tun0       |
            |      |                |        |
            |      +----------------+        |
            |       Virtual CTC link         |
            |                                |
            +--------------------------------+
    

    The virtual CTC link is provided by the Universal TUN/TAP driver developed by Maxim Krasnyansky. This driver creates a tunnel which appears to Hercules as a character device (/dev/tun0 or /dev/net/tun) and appears to the driving system as a virtual network interface (tun0). The Hercules 3088 driver makes the tun device appear as a CTCA (Channel to Channel Adapter) to the S/390 operating system running under Hercules. Each end of the link has its own IP address which is distinct from the IP address of the driving system's real network adapter.

    The Universal TUN/TAP driver is currently only available for Linux, Solaris, and FreeBSD.   However, similar functionality may be obtained on Windows 98/Me/2000/XP systems (but not Windows NT) via the CTCI-W32 protocol.

    Installing the TUN/TAP Driver (Linux 2.2)

    The Linux 2.2 kernel does not include the TUN/TAP driver, so you need to install it using the following procedure:

    1. Download the file tun-1.0-1.i386.rpm from http://vtun.sourceforge.net/tun
    2. Install the driver using the following commands:
      su
      (enter the root password when prompted)
      rpm -ivh tun-1.0-1.i386.rpm
      chgrp xxxxx /dev/tun*
      (where xxxxx is the group under which you run Hercules)
      chmod g+w /dev/tun*
      chmod o-r /dev/tun*
    3. Edit the file /etc/modules.conf (it is called /etc/conf.modules in some distributions) and add the following line:
      alias char-major-90 tun
      This causes the TUN/TAP driver to be loaded automatically when a /dev/tun* device is opened by Hercules.

    Installing the TUN/TAP Driver (Linux 2.4)

    The TUN/TAP driver is delivered as part of the Linux 2.4 kernel, and if you are using one of the popular Linux distributions you will find that the TUN/TAP driver is already installed. If not, then you must rebuild the kernel with the configuration option CONFIG_TUN=m specified.

    Note that the version of TUN/TAP in Linux 2.4 differs from the earlier version in that it allows access to all TUN interfaces (tun0, tun1, etc) through a single character device /dev/net/tun, instead of defining multiple devices /dev/tun0, /dev/tun1, etc.

    The procedure for completing the TUN/TAP setup for Linux 2.4 is shown below.

    1. Use these commands to create the TUN device:
      su
      (enter the root password when prompted)
      mkdir /dev/net
      mknod /dev/net/tun c 10 200
      chgrp xxxxx /dev/net/tun
      (where xxxxx is the group under which you run Hercules)
      chmod g+rw /dev/net/tun
      chmod o-rw /dev/net/tun
    2. Edit the file /etc/modules.conf (it is called /etc/conf.modules in some distributions) and add the following line:
      alias char-major-10-200 tun
      This causes the TUN/TAP driver to be loaded automatically when the /dev/net/tun device is opened by Hercules.

    Installing the TUN/TAP Driver (Linux 2.6)

    For distributions based on the Linux 2.6 kernel you will probably find that the TUN/TAP driver is already installed and the /dev/net/tun device is already defined. If not, then follow the procedure for Linux 2.4 as descibed above.

    You will certainly need to alter the permissions on the /dev/net/tun device to allow Hercules to open it.

    • Use the following commands to set the necessary permissions:
      su
      (enter the root password when prompted)
      chown root:xxxxx /dev/net/tun
      (where xxxxx is the group under which you run Hercules)
      chmod 0660 /dev/net/tun
    • Additional notes from Greg Smith:
      1. I find on my Fedora Core 6 system that I have to add the above 2 commands to /etc/rc.local and update /etc/udev/rules.d/50-udev.rules replacing
        KERNEL=="tun", NAME="net/%k"
        by
        KERNEL=="tun", NAME="net/%k", GROUP="xxxxx", MODE="0660"
      2. In the hercules log you should see /dev/net/tun0 opened. I get a couple of error messages about SIOCDIFADDR and SIOCSIFHWADDR ioctl's failing but these can be ignored (maybe I'll fix that soon).

    In Linux 2.6 the file /etc/modules.conf no longer exists, instead there is a file called /etc/modprobe.conf. TUN/TAP will usually work, however, without any change to the modprobe configuration.

    Configuring the TUN interface

    The tun0 network interface in the driving system must be configured as a point-to-point link. The design of the TUN/TAP driver does not allow the interface to be statically configured like a regular network interface — the tun0 interface does not exist until Hercules opens the TUN device. For this reason, Hercules provides a special program called hercifc to configure the tun0 network interface. This program is launched automatically by Hercules 3088 CTC device initialization.

    To allow the hercifc program to issue the necessary configuration commands, you must ensure that hercifc is installed with setuid root file permissions. When Hercules is built with the configuration option --enable-setuid-hercifc, make install will install hercifc in /usr/local/bin with setuid root permissions. Note: Unrestricted access to the hercifc program could present a potential security exposure, so you will want to ensure that hercifc can be executed only by the group which is authorized to run Hercules. The following commands alter the file permissions to ensure that only users in a trusted group can execute hercifc:
    su
    (enter the root password when prompted)
    chgrp xxxxx /usr/local/bin/hercifc
    (where xxxxx is the group under which you run Hercules)
    chmod 4750 /usr/local/bin/hercifc
    exit

    Enabling IP forwarding

    You must ensure that your kernel is enabled for IP forwarding. Popular Linux distributions usually have a configuration option to enable IP forwarding or routing:

    • For RedHat, specify net.ipv4.ip_forward=1 in the /etc/sysctl.conf file.
    • For SuSE, specify IP_FORWARD="yes" in the /etc/rc.config file.
    • If you cannot find this option in your distribution, the following command should work on any Linux 2.x kernel:
      echo "1" > /proc/sys/net/ipv4/ip_forward

    Defining a route to Hercules TCP/IP

    Client systems which connect to TCP/IP applications running in the Hercules machine need to have a routing entry which defines the driving system as the gateway into the Hercules system. An example route definition for a Unix client system is shown below:

    route add 192.168.200.1 gw 10.1.2.1
    

    For a Windows client, go to Settings -> Control Panel -> Network -> Configuration -> TCP/IP -> Properties -> Gateway and add the driving system's IP address to the list of gateways. Alternatively, enter a route command such as:

    route add 192.168.200.0 mask 255.255.255.0 10.1.2.1 metric 1
    

    If you want to avoid having to update client systems, another way is to add an appropriate routing entry to your default gateway router.

    Defining the link in Hercules

    You must define a CTC device pair in the Hercules configuration file. The second device must bear the same definition as the 1st instance and be at device number + 1. The 1st device number must be even. Devices should preferably be grouped (furthermore, it makes the configuration file easier to read).


    0E20.2 CTCI 192.168.200.1 192.168.200.2
    or
    0E20,0E21 CTCI 192.168.200.1 192.168.200.2
    or
    0E20-0E21 CTCI 192.168.200.1 192.168.200.2

    Check Device Definition Statement syntax for an explanation of device grouping.

    Two IP addresses must be assigned, one for the driving system's end of the link, and one for the Hercules end of the link. For this example I have chosen 192.168.200.1 for the Hercules IP address, and 192.168.200.2 for the driving system's IP address. Since this is a point-to-point link, any addresses may be chosen, provided that the network part of the address (192.168.200 in this example) does not conflict with any existing network addresses used in your IP network.

    Configuring the Hercules TCP/IP stack

    TCP/IP for VSE

    This is an example of the configuration statements which you need to include in the IPINIT00.L member of PRD1.BASE:

    SET IPADDR   = 192.168.200.001
    SET MASK     = 255.255.255.000
    DEFINE LINK,ID=CTCE20,TYPE=CTCA,DEV=(E20,E21),MTU=1500
    DEFINE ROUTE,ID=LINUX,LINKID=CTCE20,IPADDR=0.0.0.0
    

    The CTC devices should be defined to VSE using the following statements in the $IPLxxx.PROC procedure in IJSYSRS.SYSLIB:

    ADD E20:E21,CTCA,EML
    

    TCP/IP for OS/390 or VM/ESA

    This is an example of the configuration statements which you need to include in the TCPIP.PROFILE.TCPIP dataset (OS/390), or in the PROFILE TCPIP file on TCPMAINT 198 (VM):

    DEVICE CTCDEV1 CTC E20
    LINK CTCLINK1 CTC 0 CTCDEV1
    HOME 192.168.200.1 CTCLINK1
    GATEWAY
    ; Network      First Hop     Link Name Size   Subnet Mask  Subnet Value
    192.168.200.2  =             CTCLINK1  1500   HOST
    DEFAULTNET     192.168.200.2 CTCLINK1  1500   0
    START CTCDEV1
    

    For OS/390, the CTC devices need to be defined as device type 3088 in the IODF. Use the D U,CTC command to find out which 3088 addresses are defined in your IODF.

    For VM, the CTC devices must be attached to the TCPIP virtual machine.

    Because TCP/IP uses long running channel programs, the missing interrupt handler should be disabled for the CTC devices. For OS/390, add this statement in PARMLIB member IECIOS00:

    MIH TIME=00:00,DEV=(E20-E21)
    

    For VM, add this command to the PROFILE EXEC file of OPERATOR 191:

    'CP SET MITIME 0E20-0E21 OFF'
    

    Linux for S/390

    This is an example of the network definitions which you need in a Linux/390 system running under Hercules:

    ifconfig ctc0 192.168.200.1 pointopoint 192.168.200.2 mtu 1500
    route add defaultroute gw 192.168.200.2
    

    Linux/390 will autodetect the CTC devices E20 and E21 at startup and will assign the interface name ctc0.

    What to do if TUN/TAP doesn't work

    Check the following (thanks to Richard Higson for this checklist):

    1. Enter the command ls -l /dev/tun0 /dev/net/tun.
      For Linux 2.4, the response should be:
      ls: /dev/tun0: No such file or directory
      crw-rw---- 1 root xxxxx 10, 200 Sep 13 07:06 /dev/net/tun

      For Linux 2.2, the response should be:
      crw-rw---- 1 root xxxxx 90, 0 Feb 3 2001 /dev/tun0
      ls: /dev/net/tun: No such file or directory

      (xxxxx should be the group under which you run Hercules).
    2. ls -l /usr/local/bin/hercifc should show
      -rwsr-x--- 1 root xxxxx 17333 Dec 31 20:55 /usr/local/bin/hercifc

      (xxxxx should be the group under which you run Hercules).
    3. When hercules comes up, and before IPLing your favorite OS, verify that you have your underlying network stuff up and ready to roar:
      [root]# ifconfig
      eth0      Link encap:Ethernet  HWaddr 00:12:34:56:78:9A
                inet addr:10.1.2.1  Bcast:10.255.255.255  Mask:255.0.0.0
                UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
      tun0      Link encap:Point-to-Point Protocol
                inet addr:192.168.200.2  P-t-P:192.168.200.1  Mask:255.255.255.0
                UP POINTOPOINT RUNNING NOARP MULTICAST  MTU:1500  Metric:1
      [root]# netstat -in
      Kernel Interface table
      Iface   MTU Met   RX-OK RX-ERR RX-DRP RX-OVR   TX-OK TX-ERR TX-DRP TX-OVR Flg
      eth0   1500   0     201      0      0      0     196      0      0      0 BMRU
      tun0   1500   0       0      0      0      0       0      0      0      0 MOPRU
      [root]# netstat -rn
      Kernel IP routing table
      Destination     Gateway         Genmask         Flags   MSS Window  irtt Iface
      10.0.0.0        0.0.0.0         255.0.0.0       U        40 0          0 eth0
      192.168.200.0   0.0.0.0         255.255.255.0   U        40 0          0 tun0
      127.0.0.0       0.0.0.0         255.0.0.0       U        40 0          0 lo
      0.0.0.0         10.1.0.1        0.0.0.0         UG       40 0          0 eth0
    4. `cat /proc/sys/net/ipv4/ip_forward` should show "1". If it doesn't, your L386 won't forward (==route) packets at all.
    5. Is the TUN/TAP driver loaded?
      1. TUN/TAP compiled into the kernel (`make menuconfig`) look for "CONFIG_TUN=m" in /usr/src/linux
      2. `lsmod` after starting hercules should show tun 3456 2 (autoclean)
    6. Look for
      Dec 14 16:47:19 wie kernel: Universal TUN/TAP device driver 1.3 (C)1999-2000
      Maxim Krasnyansky

      in syslog after starting hercules


    back

    Last updated $Date: 2007-01-31 11:06:10 -0600 (Wed, 31 Jan 2007) $ $Revision: 4282 $

    hercules-3.07/html/hercules.css000644 000765 000765 00000005600 11143760535 020241 0ustar00jmaynardjmaynard000000 000000 hercules-3.07/html/hercules.html000644 000765 000765 00000001257 11143760535 020421 0ustar00jmaynardjmaynard000000 000000 Hercules <body> <p>Hercules uses frames. Your browser does not support frames.</p> </body> hercules-3.07/html/images/000777 000765 000765 00000000000 11345533276 017171 5ustar00jmaynardjmaynard000000 000000 hercules-3.07/html/include/000777 000765 000765 00000000000 11345533276 017347 5ustar00jmaynardjmaynard000000 000000 hercules-3.07/html/index.html000644 000765 000765 00000031634 11345533254 017720 0ustar00jmaynardjmaynard000000 000000 The Hercules System/370, ESA/390, and z/Architecture Emulator
    Hercules logo
    Hercules is OSI Certified Open Source Software

    The Hercules System/370, ESA/390, and z/Architecture Emulator


    Hercules is an open source software implementation of the mainframe System/370 and ESA/390 architectures, in addition to the new 64-bit z/Architecture. Hercules runs under Linux, Windows (98, NT, 2000, and XP), Solaris, FreeBSD, and Mac OS X (10.3 and later).

    Hercules is OSI Certified Open Source Software licensed under the terms of the Q Public Licence.

    Hercules was created by Roger Bowler and is maintained by Jay Maynard. Jan Jaeger designed and implemented many of the advanced features of Hercules, including dynamic reconfiguration, integrated console, interpretive execution and z/Architecture support. A dedicated crew of programmers is constantly at work implementing new features and fixing bugs.


    To find out more about Hercules, follow these links:

    Web documentation:

    PDF manuals:


    To download the current release version, use the following links:



    What people are saying about Hercules


    “ Never in my wildest dreams did I expect to see MVS running on a machine that I personally own. Hercules is a marvelous tool. My thanks to you all for a job very well done. ”
    — Reed H. Petty

    “ I do miss my mainframe a lot, and playing with Herc sure brings back memories. Just seeing the IBM message prefixes, and responding to console messages again was a wonderful bit of nostalgia! ”
    — Bob Brown

    “ I have installed your absolutely fantastic /390 emulator. You won't believe what I felt when I saw the prompt. Congratulations, this is a terrific software. I really have not had such a fascinating and interesting time on my PC lately. ”
    — IBM Large Systems Specialist

    “ Such simulators have been available for a long time. One of the most complete (up to modern 64-bit z/Architecture) is hercules. ”
    — Michel Hack, IBM Thomas J. Watson Research Center

    “ An apparently excellent emulator that allows those open source developers with an "itch to scratch", to come to the S/390 table and contribute. ”
    — Mike MacIsaac, IBM

    “ BTW grab a copy of Hercules and you can test it at home. It's a very good S/390 and zSeries (S/390 64bit) emulator.. ”
    — Alan Cox

    “ It works even better than I imagined. Hercules is a fine piece of software! ”
    — Dave Sienkiewicz

    “ Hercules is a systems programmer's dream come true. ”
    — René Vincent Jansen

    “ Aside from the electric trains my parents got me in 1953, this is the best toy I've ever been given, bar none.”
    — Jeffrey Broido

    “ Congratulations to you and your team on a fine piece of work! ”
    — Rich Smrcina

    “ Congratulations on a magnificent achievement! ”
    — Mike Ross

    “ For anyone thinking running Hercules is too much trouble or too hard or whatever, I came home from work one day and my 13 year old 8th grade son had MVS running under VM under Hercules on Linux. He had gotten all the information about how to do this from the Internet. When he complained about MVS console configuration and figuring out how to get it to work with VM, I knew he had felt all the pain he ever needed to feel about mainframes. ”
    — Scott Ledbetter, StorageTek

    “ I am running a fully graphical Centos z/Linux environment on my desktop. The Hercules emulator is an amazing feat of engineering. I just wanted to send my compliments to the team for an excellent job! Thanks much for making this product part of the open-source community! ”
    — Roby Gamboa

    “ I have DOS and DOS/VS running on Hercules with some demo applications, both batch and on-line. It does bring back some good memories. My compliments go to the Hercules team. Thank you. ”
    — Bill Carlborg

    “ This is stunning piece of work. To say that I am blown away is an understatement. I have a mainframe on my notebook!!!!!! P.S. Now if I can just remember my JCL ”
    — Roger Tunnicliffe



    Read Hesh Wiener's Technology News article about Hercules at http://www.tech-news.com/another/ap200601b.html

    Read Moshe Bar's BYTE.com article about Hercules at http://www.byte.com/documents/s=429/byt20000801s0002/

    For eighteen months, the IBM Redbook SG24-4987 Linux for S/390 at http://www.redbooks.ibm.com/abstracts/sg244987.html contained a chapter written by Richard Higson describing how to run Linux/390 under Hercules. Then suddenly, all mention of Hercules was mysteriously removed from the online edition of the book! Read the story of the disappearing Redbook chapter at http://www2.marist.edu/htbin/wlvtype?LINUX-VM.25658

    View the foils from Jay Maynard's presentation given at SHARE Session 2880 in San Francisco on 20 August 2002 as a PDF file (815K) from http://linuxvm.org/Present/SHARE99/S2880JMa.pdf




    The Subversion source code repository

    The complete source code for the current development version of Hercules is also available via anonymous access from our Subversion source code repository. The Subversion URL is:

    svn://svn.hercules-390.org/hercules

    Doing a checkout on module "hercules" will get you the source for all of Hercules. You'll want to check out the trunk, instead of the whole repository:

    svn checkout svn://svn.hercules-390.org/hercules/trunk hercules

    (The last hercules specifies the directory the checked out copy is placed into.) Please note that this will get you the current development version of Hercules, which is not release quality and thus might not even work (since it's still under development). If you want the current, stable, release version of Hercules (i.e. one that is known to work properly), then use the previously mentioned links instead.

    Please read the file README.CVS included with the source for additional and updated instructions for building the development version.



    Other Hercules-related sites



    If you have any questions or comments  please consider joining the hercules-390 discussion group at http://groups.yahoo.com/group/hercules-390.

    Bug reports (together with your diagnosis of the fault, please) may be sent to me, Jay Maynard, at jmaynard @ conmicro.com.



    IBM, System/370, ESA/390, and z/Architecture are trademarks or registered trademarks of IBM Corporation. Other product names mentioned here are trademarks of other companies.

    Last updated $Date: 2010-03-09 14:56:34 -0600 (Tue, 09 Mar 2010) $ $Revision: 5663 $

    hercules-3.07/html/Makefile.am000644 000765 000765 00000004256 11143760535 017757 0ustar00jmaynardjmaynard000000 000000 dist_pkgdata_DATA = cckddasd.html fishgui.html hercconf.html hercfaq.html \ hercinst.html herclic.html hercload.html hercmsca.html hercmscf.html \ hercmscp.html hercmsct.html hercmscu.html hercmsda.html hercmsdc.html \ hercmsdg.html hercmsdi.html hercmsdl.html hercmsds.html hercmsdt.html \ hercmsdu.html hercmsg.html hercmshd.html hercmshe.html hercmshg.html \ hercmshm.html hercmsht.html hercmshu.html hercmsif.html hercmsin.html \ hercmslc.html hercmslg.html hercmspn.html hercmspr.html hercmspu.html \ hercmsrd.html hercmssd.html hercmsta.html hercmstc.html hercmste.html \ hercmstm.html hercmsts.html hercmstt.html hercmstu.html hercmsvm.html \ hercnew.html hercrdr.html hercrnot.html hercsupp.html herctcp.html \ hercules.html index.html shared.html tasks.html hercules.css include_sources = include/header.htmlpart include/footer.htmlpart include_pkgdatadir = $(pkgdatadir)/include dist_include_pkgdata_DATA = $(include_sources) images_sources = images/loadoffu.gif images/restartu.gif \ images/back.gif images/loadonu.gif images/startd.gif \ images/bkued.gif images/loadu.gif images/startu.gif \ images/blueu.gif images/manoffu.gif images/stopd.gif \ images/dial1.gif images/manonu.gif images/stopu.gif \ images/dial2.gif images/note.gif images/stored.gif \ images/dial3.gif images/osi-certified-60x50.jpg images/storeu.gif \ images/dial4.gif images/poweroffd.gif images/sysoffu.gif \ images/favicon.ico images/poweroffu.gif images/sysonu.gif \ images/greend.gif images/poweronoffd.gif images/translucentoffd.gif \ images/greenu.gif images/poweronoffu.gif images/translucentoffu.gif \ images/hercpic-rblk-256.gif images/poweronond.gif images/translucentond.gif \ images/hercpic-rblk-80.gif images/powerononu.gif images/translucentonu.gif \ images/interruptd.gif images/redd.gif images/waitoffu.gif \ images/interruptu.gif images/redu.gif images/waitonu.gif \ images/loadd.gif images/restartd.gif images_pkgdatadir = $(pkgdatadir)/images dist_images_pkgdata_DATA = $(images_sources) hercules-3.07/html/Makefile.in000644 000765 000765 00000037176 11344713141 017771 0ustar00jmaynardjmaynard000000 000000 # Makefile.in generated by automake 1.9.6 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = .. am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd INSTALL = @INSTALL@ install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = html DIST_COMMON = $(dist_images_pkgdata_DATA) $(dist_include_pkgdata_DATA) \ $(dist_pkgdata_DATA) $(srcdir)/Makefile.am \ $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/autoconf/hercules.m4 \ $(top_srcdir)/autoconf/libtool.m4 \ $(top_srcdir)/autoconf/ltdl.m4 $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(SHELL) $(top_srcdir)/autoconf/mkinstalldirs CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = SOURCES = DIST_SOURCES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; am__installdirs = "$(DESTDIR)$(images_pkgdatadir)" \ "$(DESTDIR)$(include_pkgdatadir)" "$(DESTDIR)$(pkgdatadir)" dist_images_pkgdataDATA_INSTALL = $(INSTALL_DATA) dist_include_pkgdataDATA_INSTALL = $(INSTALL_DATA) dist_pkgdataDATA_INSTALL = $(INSTALL_DATA) DATA = $(dist_images_pkgdata_DATA) $(dist_include_pkgdata_DATA) \ $(dist_pkgdata_DATA) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BUILD_FISHHANG_FALSE = @BUILD_FISHHANG_FALSE@ BUILD_FISHHANG_TRUE = @BUILD_FISHHANG_TRUE@ BUILD_FTHREADS_FALSE = @BUILD_FTHREADS_FALSE@ BUILD_FTHREADS_TRUE = @BUILD_FTHREADS_TRUE@ BUILD_HERCIFC_FALSE = @BUILD_HERCIFC_FALSE@ BUILD_HERCIFC_TRUE = @BUILD_HERCIFC_TRUE@ BUILD_SHARED_FALSE = @BUILD_SHARED_FALSE@ BUILD_SHARED_TRUE = @BUILD_SHARED_TRUE@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CONVENIENCE_LTDL_FALSE = @CONVENIENCE_LTDL_FALSE@ CONVENIENCE_LTDL_TRUE = @CONVENIENCE_LTDL_TRUE@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ ECHO = @ECHO@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ F77 = @F77@ FFLAGS = @FFLAGS@ GMSGFMT = @GMSGFMT@ GREP = @GREP@ HERCIFC_GROUPNAME = @HERCIFC_GROUPNAME@ HERCIFC_GROUPSET_FALSE = @HERCIFC_GROUPSET_FALSE@ HERCIFC_GROUPSET_TRUE = @HERCIFC_GROUPSET_TRUE@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_LTDL_FALSE = @INSTALL_LTDL_FALSE@ INSTALL_LTDL_TRUE = @INSTALL_LTDL_TRUE@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ LDFLAGS = @LDFLAGS@ LIBADD_DL = @LIBADD_DL@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBTOOL_DEPS = @LIBTOOL_DEPS@ LN_S = @LN_S@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@ MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@ MAKEINFO = @MAKEINFO@ MKINSTALLDIRS = @MKINSTALLDIRS@ MSGFMT = @MSGFMT@ MSGMERGE = @MSGMERGE@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPTION_DYNAMIC_LOAD_FALSE = @OPTION_DYNAMIC_LOAD_FALSE@ OPTION_DYNAMIC_LOAD_TRUE = @OPTION_DYNAMIC_LOAD_TRUE@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ POSUB = @POSUB@ RANLIB = @RANLIB@ SETUID_HERCIFC_FALSE = @SETUID_HERCIFC_FALSE@ SETUID_HERCIFC_TRUE = @SETUID_HERCIFC_TRUE@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ USE_DLLTOOL_FALSE = @USE_DLLTOOL_FALSE@ USE_DLLTOOL_TRUE = @USE_DLLTOOL_TRUE@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_F77 = @ac_ct_F77@ am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ modexecdir = @modexecdir@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ dist_pkgdata_DATA = cckddasd.html fishgui.html hercconf.html hercfaq.html \ hercinst.html herclic.html hercload.html hercmsca.html hercmscf.html \ hercmscp.html hercmsct.html hercmscu.html hercmsda.html hercmsdc.html \ hercmsdg.html hercmsdi.html hercmsdl.html hercmsds.html hercmsdt.html \ hercmsdu.html hercmsg.html hercmshd.html hercmshe.html hercmshg.html \ hercmshm.html hercmsht.html hercmshu.html hercmsif.html hercmsin.html \ hercmslc.html hercmslg.html hercmspn.html hercmspr.html hercmspu.html \ hercmsrd.html hercmssd.html hercmsta.html hercmstc.html hercmste.html \ hercmstm.html hercmsts.html hercmstt.html hercmstu.html hercmsvm.html \ hercnew.html hercrdr.html hercrnot.html hercsupp.html herctcp.html \ hercules.html index.html shared.html tasks.html hercules.css include_sources = include/header.htmlpart include/footer.htmlpart include_pkgdatadir = $(pkgdatadir)/include dist_include_pkgdata_DATA = $(include_sources) images_sources = images/loadoffu.gif images/restartu.gif \ images/back.gif images/loadonu.gif images/startd.gif \ images/bkued.gif images/loadu.gif images/startu.gif \ images/blueu.gif images/manoffu.gif images/stopd.gif \ images/dial1.gif images/manonu.gif images/stopu.gif \ images/dial2.gif images/note.gif images/stored.gif \ images/dial3.gif images/osi-certified-60x50.jpg images/storeu.gif \ images/dial4.gif images/poweroffd.gif images/sysoffu.gif \ images/favicon.ico images/poweroffu.gif images/sysonu.gif \ images/greend.gif images/poweronoffd.gif images/translucentoffd.gif \ images/greenu.gif images/poweronoffu.gif images/translucentoffu.gif \ images/hercpic-rblk-256.gif images/poweronond.gif images/translucentond.gif \ images/hercpic-rblk-80.gif images/powerononu.gif images/translucentonu.gif \ images/interruptd.gif images/redd.gif images/waitoffu.gif \ images/interruptu.gif images/redu.gif images/waitonu.gif \ images/loadd.gif images/restartd.gif images_pkgdatadir = $(pkgdatadir)/images dist_images_pkgdata_DATA = $(images_sources) all: all-am .SUFFIXES: $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ && exit 0; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu html/Makefile'; \ cd $(top_srcdir) && \ $(AUTOMAKE) --gnu html/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs distclean-libtool: -rm -f libtool uninstall-info-am: install-dist_images_pkgdataDATA: $(dist_images_pkgdata_DATA) @$(NORMAL_INSTALL) test -z "$(images_pkgdatadir)" || $(mkdir_p) "$(DESTDIR)$(images_pkgdatadir)" @list='$(dist_images_pkgdata_DATA)'; for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ f=$(am__strip_dir) \ echo " $(dist_images_pkgdataDATA_INSTALL) '$$d$$p' '$(DESTDIR)$(images_pkgdatadir)/$$f'"; \ $(dist_images_pkgdataDATA_INSTALL) "$$d$$p" "$(DESTDIR)$(images_pkgdatadir)/$$f"; \ done uninstall-dist_images_pkgdataDATA: @$(NORMAL_UNINSTALL) @list='$(dist_images_pkgdata_DATA)'; for p in $$list; do \ f=$(am__strip_dir) \ echo " rm -f '$(DESTDIR)$(images_pkgdatadir)/$$f'"; \ rm -f "$(DESTDIR)$(images_pkgdatadir)/$$f"; \ done install-dist_include_pkgdataDATA: $(dist_include_pkgdata_DATA) @$(NORMAL_INSTALL) test -z "$(include_pkgdatadir)" || $(mkdir_p) "$(DESTDIR)$(include_pkgdatadir)" @list='$(dist_include_pkgdata_DATA)'; for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ f=$(am__strip_dir) \ echo " $(dist_include_pkgdataDATA_INSTALL) '$$d$$p' '$(DESTDIR)$(include_pkgdatadir)/$$f'"; \ $(dist_include_pkgdataDATA_INSTALL) "$$d$$p" "$(DESTDIR)$(include_pkgdatadir)/$$f"; \ done uninstall-dist_include_pkgdataDATA: @$(NORMAL_UNINSTALL) @list='$(dist_include_pkgdata_DATA)'; for p in $$list; do \ f=$(am__strip_dir) \ echo " rm -f '$(DESTDIR)$(include_pkgdatadir)/$$f'"; \ rm -f "$(DESTDIR)$(include_pkgdatadir)/$$f"; \ done install-dist_pkgdataDATA: $(dist_pkgdata_DATA) @$(NORMAL_INSTALL) test -z "$(pkgdatadir)" || $(mkdir_p) "$(DESTDIR)$(pkgdatadir)" @list='$(dist_pkgdata_DATA)'; for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ f=$(am__strip_dir) \ echo " $(dist_pkgdataDATA_INSTALL) '$$d$$p' '$(DESTDIR)$(pkgdatadir)/$$f'"; \ $(dist_pkgdataDATA_INSTALL) "$$d$$p" "$(DESTDIR)$(pkgdatadir)/$$f"; \ done uninstall-dist_pkgdataDATA: @$(NORMAL_UNINSTALL) @list='$(dist_pkgdata_DATA)'; for p in $$list; do \ f=$(am__strip_dir) \ echo " rm -f '$(DESTDIR)$(pkgdatadir)/$$f'"; \ rm -f "$(DESTDIR)$(pkgdatadir)/$$f"; \ done tags: TAGS TAGS: ctags: CTAGS CTAGS: distdir: $(DISTFILES) $(mkdir_p) $(distdir)/images $(distdir)/include @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ list='$(DISTFILES)'; for file in $$list; do \ case $$file in \ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ esac; \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ if test "$$dir" != "$$file" && test "$$dir" != "."; then \ dir="/$$dir"; \ $(mkdir_p) "$(distdir)$$dir"; \ else \ dir=''; \ fi; \ if test -d $$d/$$file; then \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ fi; \ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(DATA) installdirs: for dir in "$(DESTDIR)$(images_pkgdatadir)" "$(DESTDIR)$(include_pkgdatadir)" "$(DESTDIR)$(pkgdatadir)"; do \ test -z "$$dir" || $(mkdir_p) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic distclean-libtool dvi: dvi-am dvi-am: html: html-am info: info-am info-am: install-data-am: install-dist_images_pkgdataDATA \ install-dist_include_pkgdataDATA install-dist_pkgdataDATA install-exec-am: install-info: install-info-am install-man: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-dist_images_pkgdataDATA \ uninstall-dist_include_pkgdataDATA uninstall-dist_pkgdataDATA \ uninstall-info-am .PHONY: all all-am check check-am clean clean-generic clean-libtool \ distclean distclean-generic distclean-libtool distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dist_images_pkgdataDATA \ install-dist_include_pkgdataDATA install-dist_pkgdataDATA \ install-exec install-exec-am install-info install-info-am \ install-man install-strip installcheck installcheck-am \ installdirs maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ ps ps-am uninstall uninstall-am \ uninstall-dist_images_pkgdataDATA \ uninstall-dist_include_pkgdataDATA uninstall-dist_pkgdataDATA \ uninstall-info-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: hercules-3.07/html/shared.html000644 000765 000765 00000037761 11143760535 020066 0ustar00jmaynardjmaynard000000 000000 Hercules: Shared Device Server

    Hercules Shared Device Server


    Contents


    Overview

    (C) Copyright Greg Smith, 2002-2007

    Shared device support allows multiple Hercules instances to share devices. The device will be 'local' to one instance and 'remote' to all other instances. The local instance is the 'server' for that device and the remote instance is the 'client'. You do not have to IPL an operating system on the device server. Any number of Hercules instances can act as a server in a "Hercplex".

    To use a device on a remote system, instead of specifying a file name on the device config statement, you specify

    ip_address_or_name:port:devnum

    For example:

        0100  3350  localhost:3990:0100
    

    which says there is a device server on the local host listening on port 3990 and we want to use its 0100 device as 0100. The default port is 3990 and the default remote device number is the local device number. So we could say:

        0100  3350  localhost
    

    instead, providing we don't actually have a file 'localhost'. Interestingly, the instance on the local host listening on 3990 could have a statement:

        0100  3350  192.168.200.1::0200
    

    which means that instance in turn will use device 0200 on the server at 192.168.200.1 listening on port 3990. The original instance will have to 'hop' thru the second instance to get to the real device.

    Device sharing can be 'split' between multiple instances. For example, suppose instance A has:

        SHRDPORT 3990
        0100  3350  localhost:3991
        0101  3350  mvscat
    

    and instance B has:

        SHRDPORT 3991
        0100  3350  mvsres
        0101  3350  localhost
    

    Then each instance acts as both a client and as a server.

    When 'SHRDPORT' is specified, thread 'shared_server' is started at the end of Hercules initialization. In the example above, neither Hercules instance can initialize their devices until the server is started on each system. In this case, the device trying to access a server gets the 'connecting' bit set on in the DEVBLK and the device still needs to initialize. After the shared server is started, a thread is attached for each device that is connecting to complete the connection (which is the device init handler).


    Technical BS

    There are (at least) two approaches to sharing devices. One is to execute the channel program on the server system. The server will need to request from the client system information such as the ccw and the data to be written, and will need to send to the client data that has been read and status information. The second is to execute the channel program on the client system. Here the client system makes requests to the server system to read and write data.

    The second approach is currently implemented. The first approach arguably emulates 'more correctly'. However, an advantage of the implemented approach is that it is easier because only the client sends requests and only the server sends responses.

    Both client and server have a DEVBLK structure for the device. Absurdly, perhaps, in originally designing an implementation for shared devices it was not clear what type of process should be the server. It was a quantum leap forward to realize that it could just be another hercules instance.

    Protocol

    (If this section is as boring for you to read as it was for me to write then please skip to the next section ;-)

    The client sends an 8 byte request header and maybe some data:

        +-----+-----+-----+-----+-----+-----+-----+-----+
        | cmd |flag |  devnum   |    id     |   length  |
        +-----+-----+-----+-----+-----+-----+-----+-----+
    
                    <-------- length --------->
                    +----- .  .  .  .  . -----+
                    |          data           |
                    +----- .  .  .  .  . -----+
    

    'cmd' identifies the client request. The requests are:

    0xe0   CONNECT

    Connect to the server. This requires the server to allocate resources to support the connection. Typically issued during device initialization or after being disconnected after a network error or timeout.

    0xe1   DISCONNECT

    Disconnect from the server. The server can now release the allocated resources for the connection. Typically issued during device close or detach.

    0xe2   START

    Start a channel program on the device. If the device is busy or reserved by another system then wait until the device is available unless the NOWAIT flag bit is set, then return a BUSY code. Once START succeeds then the device is unavailable until the END request.

    0xe3   END

    Channel program has ended. Any waiters for the device can now retry.

    0xe4   RESUME

    Similar to START except a suspended channel program has resumed.

    0xe5   SUSPEND

    Similar to END except a channel program has suspended itself. If the channel program is not resumed then the END request is not issued.

    0xe6   RESERVE

    Makes the device unavailable to any other system until a RELEASE request is issued. Must be issued within the scope of START/END.

    0xe7   RELEASE

    Makes the device available to other systems after the next END request. Must be issued within the scope of START/END.

    0xe8   READ

    Read from a device. A 4-byte 'record' identifier is specified in the request data to identify what data to read in the device context. Must be issued within the scope of START/END.

    0xe9   WRITE

    Write to a device. A 2-byte 'offset' and a 4-byte 'record' is specified in the request data, followed by the data to be written. 'record' identifies what data is to be written in the device context and 'offset' and 'length' identify what to update in 'record'. Must be issued within the scope of START/END.

    0xea   SENSE

    Retrieves the sense information after an i/o error has occurred on the server side. This is typically issued within the scope of the channel program having the error. Client side sense or concurrent sense will then pick up the sense data relevant to the i/o error. Must be issued within the scope of START/END.

    0xeb   QUERY

    Obtain device information, typically during device initialization.

    0xec   COMPRESS

    Negotiate compression parameters. Notifies the server what compression algorithms are supported by the client and whether or not data sent back and forth from the client or server should be compressed or not. Typically issued after CONNECT.

    NOTE: This action should actually be SETOPT or some such; it was just easier to code a COMPRESS specific SETOPT (less code).


    'flag' qualifies the client request and varies by the request.

    0x80   NOWAIT

    For START, if the device is unavailable then return BUSY instead of waiting for the device.

    0x40   QUERY

    Identifies the QUERY request:

    0x41   DEVCHAR

    Device characteristics data

    0x42   DEVID

    Device identifier data

    0x43   DEVUSED

    Hi used track/block (for dasdcopy)

    0x48   CKDCYLS

    Number cylinders for CKD device

    0x4c   FBAORIGIN

    Origin block for FBA

    0x4d   FBANUMBLK

    Number of FBA blocks

    0x4e   FBABLKSIZ

    Size of an FBA block

    0x3x   COMP

    For WRITE, data is compressed at offset 'x':

    0x2x   BZIP2

    using bzip2

    0x1x   LIBZ

    using zlib

    0xxy

    For COMPRESS, identifies the compression algorithms supported by the client (0x2y for bzip2, 0x1y for zlib, 0x3y for both) and the zlib compression parameter 'y' for sending otherwise uncompressed data back and forth. If 'y' is zero (default) then no uncompressed data is compressed between client & server.


    'devnum' identifies the device by number on the server instance. The device number may be different than the device number on the client instance.

    'id' identifies the client to the server. Each client has a unique positive (non-zero) identifier. For the initial CONNECT request 'id' is zero. After a successful CONNECT, the server returns in the response header the identifier to be used for all other requests (including subsequent CONNECT requests). This is saved in dev->rmtid.

    'length' specifies the length of the data following the request header. Currently length is non-zero for READ/WRITE requests.


    The server sends an 8 byte response header and maybe some data:

        +-----+-----+-----+-----+-----+-----+-----+-----+
        |code |stat |  devnum   |    id     |  length   |
        +-----+-----+-----+-----+-----+-----+-----+-----+
    
                    <-------- length --------->
                    +----- .  .  .  .  . -----+
                    |          data           |
                    +----- .  .  .  .  . -----+
    

    'code' indicates the response to the request. OK (0x00) indicates success however other codes also indicate success but qualified in some manner:

    0x80   ERROR

    An error occurred. The server provides an error message in the data section.

    0x40   IOERR

    An i/o error occurred during a READ/WRITE request. The status byte has the 'unitstat' data. This should signal the client to issue the SENSE request to obtain the current sense data.

    0x20   BUSY

    Device was not available for a START request and the NOWAIT flag bit was turned on.

    0x10   COMP

    Data returned is compressed. The status byte indicates how the data is compressed (zlib or bzip2) and at what offset the compressed data starts (0 .. 15). This bit is only turned on when both the 'code' and 'status' bytes would otherwise be zero.

    0x08   PURGE

    START request was issued by the client. A list of 'records' to be purged from local cache is returned. These are 'records' that have been updated since the last START/END request from the client by other systems. Each record identifier is a 4-byte field in the data segment. The number of records then is 'length'/4. If the number of records exceeds a threshold (16) then 'length' will be zero indicating that the client should purge all locally cached records for the device.

    'stat' contains status information as a result of the request. For READ/WRITE requests this contains the 'unitstat' information if an IOERR occurred.

    'devnum' specifies the server device number

    'id' specifies the system identifier for the request.

    'length' is the size of the data returned.


    Caching

    Cached records (eg CKD tracks or FBA blocks) are kept independently on both the client and server sides. Whenever the client issues a START request to initiate a channel program the server will return a list of records to purge from the client's cache that have been updated by other clients since the last START request. If the list is too large the server will indicate that the client should purge all records for the device.


    Compression

    Data that would normally be transferred uncompressed between client and host can optionally be compressed by specifying the 'comp=' keyword on the device configuration statement or attach command. For example:

        0100  3350  192.168.2.12  comp=3
    

    The value of the 'comp=' keyword is the zlib compression parameter which should be a number between 1 .. 9. A value closer to 1 means less compression but less processor time to perform the compression. A value closer to 9 means the data is compressed more but more processor time is required.

    If the server is on 'localhost' then you should not specify 'comp='. Otherwise you are just stealing processor time to do compression/ uncompression from hercules. If the server is on a local network then I would recommend specifying a low value such as 1, 2 or 3. We are on a curve here, trying to trade cpu cycles for network traffic to derive an optimal throughput.

    If the devices on the server are compressed devices (eg CCKD or CFBA) then the 'records' (eg. track images or block groups) may be transferred compressed regardless of the 'comp=' setting. This depends on whether the client supports the compression type (zlib or bzip2) of the record on the server and whether the record is actually compressed in the server cache.

    For example:

    Suppose on the client that you execute one or more channel programs to read a record on a ckd track, update a record on the same track, and then read another (or the same) record on the track.

    For the first read the server will read the track image and pass it to the client as it was originally compressed in the file. To update a portion of the track image the server must uncompress the track image so data in it can be updated. When the client next reads from the track image, the track image is uncompressed.

    Specifying 'comp=' means that uncompressed data sent to the client will be compressed. If the data to be sent to the client is already compressed then the data is sent as is, unless the client has indicated that it does not support that compression algorithm.


    To Do

    1. More doc (sorry, I got winded)
    2. Delays observed during short transfers (redrive select ?)
    3. Better server side behaviour due to disconnect
    4. etc.

    Greg Smith gsmith@nc.rr.com


    back

    Last updated $Date: 2008-12-30 04:18:51 -0600 (Tue, 30 Dec 2008) $ $Revision: 5005 $

    hercules-3.07/html/tasks.html000644 000765 000765 00000002501 11143760535 017725 0ustar00jmaynardjmaynard000000 000000 Tasks
    The Hercules System/370, ESA/390, and z/Architecture Emulator, (c) Copyright by Roger Bowler, Jan Jaeger, and others

    Tasks

    System Log
    IPL

    Debugging

    Registers
    Storage
    Miscellaneous
    Devices
    Version Info

    Configuration

    CPU

    Registers

    GPRs
    CRs
    PSW

    Information

    Documentation
    hercules-3.07/html/include/footer.htmlpart000644 000765 000765 00000000020 11143760534 022401 0ustar00jmaynardjmaynard000000 000000 hercules-3.07/html/include/header.htmlpart000644 000765 000765 00000000065 11143760534 022344 0ustar00jmaynardjmaynard000000 000000 Hercules hercules-3.07/html/images/back.gif000644 000765 000765 00000001275 11143760534 020554 0ustar00jmaynardjmaynard000000 000000 GIF89aD³„˙„˙˙˙˙))˙11˙99˙qq˙ŻŻ˙ÎÎ˙ÖÖ˙ŜŜ˙ïï˙˙˙!ù,Dû0ÈIéĞ8ëÍ;ÂċdıĦİš²p¸Żl“tĝì|ï˙À ¨É ŽÈ¤rÉl:›˘ŠñI­Z™ÑÉôÊíBN…xœ8,b³’h8‰2Ħ@ âÄWû|ûŭvI ozInj ‡ {3To˜Œ I’Gn ’  GŒv‘N"[IojoIpn¸ Ÿ £ŞĦ r”U–˜Ĥ…G Џ spapĤŠT;W‰o­Gµ›oÉŞÙğ_°ħcnÖGƒ…ĤéMŒÇƒżXÜ‘…ʝNLÛ$ §2ݎÉ1àI‘¤Ž{ż8JÊWĞ‘2>NšaâhfZgŒìşÄħP†Çŝ%ɲŒIGH´Ŝü l›q7ES³§’1PHB `i*³IÀŽ;4 tiêԋٳ5À ]ۅl@ĤCâʝûÎxq q›·/J~ŭ‚¸/áÂ"!ŝïThis GIF file was assembled with GIF Construction Set from: Alchemy Mindworks Inc. P.O. Box 500 Beeton, Ontario L0G 1A0 CANADA. This comment block will not appear in files created with a registered version of GIF Construction Set;hercules-3.07/html/images/bkued.gif000644 000765 000765 00000002500 11143760534 020736 0ustar00jmaynardjmaynard000000 000000 GIF87a!çK˙şÛ˙‹Ĉ˙7›˙ĤÑ˙H£˙m·˙Œ˙> ˙ˆÄ˙4™˙£Ñ˙O¨˙ ˙j³˙;ž˙…Â˙VĞ˙Vİ˙€˙~ŭq¸˙˙]˙ …˙?Ÿ˙¤Î˙uğ˙šÏ˙šÍ˙!˙!Ž˙È˙Ĉ˙<˙ĞĠ˙ †˙|˙|ĵ˙(“˙—Í˙r·˙—Ë˙^Ż˙^­˙ „˙/˜˙y˙yĵ˙e²˙‰˙€ż˙G£˙ĥÙ˙\_)”˙˜Ì˙˜Ê˙Š˙„Â˙0—˙ŸÏ˙˙˙f³˙fħ˙7œ˙ĤÔ˙˙RĞ˙Rİ˙mĥ˙˙cŻ˙ˆ˙£Î˙O§˙{új²˙;˙ŞĠ˙ŞÓ˙ Î˙qı˙Ž˙ŒĈ˙8›˙]Ż˙§Ó˙x˙xĵ˙$‘˙“Ë˙“É˙Œ˙? ˙Ú˙Ĝ˙‡˙-+„Z­˙ZĞ˙‚˙uş˙WĞ˙Wİ˙CĦ˙²×˙J¤˙”Ê˙”È˙e³˙ˆ˙€À˙,—˙,•˙Qİ˙vğ˙›Ï˙vı˙›Í˙G˘˙lĥ˙bħ˙bŻ˙†˙}˙}ĵ˙N§˙i´˙‹˙³Ö˙„Á˙,!ŝH° Áƒ*\xC>,ʤ9Ò¤M5` Xƒ .Ş|Ù1£„‹3*8xɃ |Z˜™@Ñ"F(W8zy!É 8&QV`iÁ%%-ÊH à"˜;âàâà‚@OR`ÉÁ‡ËĴh#TSAü9ĤD†3,a QáRHf–jzsˆÎUż šáÇË?0XĜóÎŬ™Lġ`Ԉ–g’~XÒ0ħMQ°I'Ô dóiԝ€\Ž2‚œ‰?ËèƒeĤ‘&|3úíĝQ­O– xÔıh˜ĥ÷^Ô0"'o. z²´üµ\“ĤıŬĤĴ(§?ŝ~¸ÀRÄiñÌĝaÄħ64˙K•ċóèċüéL‰ ÙˆĊd@°ÛSħ´Â!œÇƒÄyĉ’ a€w”½àKwäà†Ôa hô^Û5€dO9GKSÜħ`Ôñ@ 1(ĥÇŽÉ4QENġK ĝ‡^€¸„°áAĊ`aĦÔ¤-…_,eÁ„‘9tÑ`u€ÀOĜ%%|É7KRħ2&Y£œÙħĜqx-…Ûr°$FlÙA ÷9¨ßŠ}•X5Éb@ĖyĴ g~Ä0fcHAĥç,Ù@H$dQd‡—²ÙzŸÁTÛD'Êħ$€¨‘Nêƒ:t"z4œ )vw•ĦFM‘aìħÈ&Ğì²Ç ;hercules-3.07/html/images/blueu.gif000644 000765 000765 00000002452 11143760534 020766 0ustar00jmaynardjmaynard000000 000000 GIF87a!ç˙K˙şÛ˙‹Ĉ˙7›˙ĤÑ˙H£˙m·˙Œ˙> ˙>ž˙ˆÄ˙4™˙£Ñ˙O¨˙ ˙j³˙;ž˙…Â˙VĞ˙Vİ˙€˙~ŭq¸˙˙]˙ …˙?Ÿ˙uğ˙šÏ˙šÍ˙!˙!Ž˙È˙Ĉ˙<˙ĞĠ˙ †˙|˙|ĵ˙(“˙—Í˙—Ë˙²Ú˙^Ż˙^­˙ „˙/˜˙y˙yĵ˙e²˙‰˙€ż˙G£˙ĥÙ˙)”˙˜Ê˙Š˙„Â˙0—˙ŸÏ˙€˙˙˙f³˙fħ˙7œ˙ĤÔ˙˙RĞ˙Rİ˙mĥ˙˙ˆ˙£Î˙O§˙;˙ŞĠ˙qı˙Ž˙ŒĈ˙]Ż˙§Ó˙§Ñ˙x˙xĵ˙$‘˙“Ë˙“É˙Œ˙? ˙Ú˙Ĝ˙‰˙-+„Z­˙ZĞ˙‚˙uş˙|ùWĞ˙Wİ˙CĦ˙²×˙J¤˙”Ê˙e³˙ˆ˙€À˙,•˙vğ˙›Ï˙vı˙›Í˙G˘˙lĥ˙ĥÜ˙bħ˙bŻ˙]`ż†˙}˙}ĵ˙Nİ˙N§˙i´˙i²˙‹˙„Á˙,!ŝÀ!ˆ`*a’ĈĈ†4àá&Ċ˘abƒ È ÄƒÄÏ ;R˜1ÂpÎM$R´"F/Äĝ¸€§':&í´£A3[Hh£â?è`“Çc€žxŜ`@aÍA0Žôp) ™NĦJġÒQ Ö*~úñÚ"ĦX“.mJ3* /Uħî‘1fk„“C2tÈA)S78.Ñrk›=U —¤&,ĵ/›,-SħN(‚"†ĉw³½àìÄ´P’ÂŞ$P›™ {Ev,ˆ·K˙‚5 ƒ5NX‰ó³ Î Aë½M3ÖŝLh£ÇÊkş`ï–ŬNúJĴXD8ßA>ġ’3î¸ z7Ż™W`•Cò)Aß`ç]·ÒgŒ‰ĈV 8B^×HüaP]ÁG.)ŸXġ‡ YLĝ\ z&Jü‡”ƒ<`ċ€‰(ŞHß .rċ•ü-f–DXħ„‰9¨Ŝs—ıĥ•IħĊRe56V%q£Î×Fkqùx]Qd=ÔV]”`À‘Ĵâ|,Z~µRGq€ \8AĊ‘r¸İ#‹Áq%„P 1VYXĠFšSÜèA—L"ĝ$gedgVÜh ‘"ùf…Ò%XW³ġôĊŞĴĥêêа²ŠGĴ´ÖÚ*ĥĉĞ@;hercules-3.07/html/images/dial1.gif000644 000765 000765 00000002552 11143760534 020645 0ustar00jmaynardjmaynard000000 000000 GIF87a;6„www___UUUMMMêêê333)))ÌÌÌÀÀÀ²²²–––†††€€€fff˙˙˙ŬŬŬ×××"""ççÖ  ¤ ,;6ŝ &Žd‰U”a€µTĈ –Ċ@0u™À PTİ‹âà@H€ àp„bÑ(¨†`Ħ¤ HD ‡âÀP"B İV ÀÀîWD ij… l U JJuv }} Žf h… ‰5 uZ’9—B… ž  U[UĊž’]°%YŸ Š Ä"fŸÄÒu Í" lқW žŽ"vùlŸ5 ğô+‹ĦM…Ĉ!l³   0@`‡X PŽ"à0Ì6ĵŜmz§ÄB€:ŝP  B,êD[@‘€›ÜÀPpP W5ià”l ÁA ZzĞbĴ F ĝ )*­h„ " (j3¤€ x†BjÎ >‚„= ÄZ“aA‡(PċŸ­t}: c žà‚ĥİES͎YÓğB kŠ„´×`êAH˘÷S“´#v" É'è>Pwâ?]‡Œhhg„00àİî+‹ŝ ŭCáDž&²ĤmȈ•i’)Àb›0ċEjSŠR"V9–ä`qY'¤ÍĜ  dCQ<éAA7=HPQL É\9\uÀjNib§Œù€ÖÙñÈD”€a Ô&ŞäbELŠ‹SJ~(äpâ ä“”–•_ ‰Cj˙äİŞ„(l!g@sÓ#Ÿ’”Ħ?ŒrVi jÁµŝ@ËĞiBù4´ä ÔĴŠDĤZHµĜ*A-µ`nzŜ›ĥ;L³èz’Ä‚( şµĜÛĞrBaç¸Í:[gŞg¨šjÒâ–Ü&*6˜Â²Ä—JRö€M —BŻĈĠœÁö{16KTk­½JLš,yŸ(Pdž 8Â!ŻmMs¨ÑïµJÖñisĤÉ< >Tž*ÜBi@“Qtn*.ı’Y–2g”@`ó/s48ôŻú2œ” ×Ñ6í5‰ŞîÁ‹;/nüQÂV&;Hn':÷£1ĴÉÌ)ÁKÈëßÔ›èäĵ`“¤¸ÌáF€‰"Ĵ=Z´ópœÛtÜĦóREŬé–Ĥ 1nWÉŭö•żêVݲĜ¤a„Uƒx~=yÜÔBSĈĤYÀ' ‘„w–’ƒx=4¸ÔŬ'áM °„%£Ŭ^£!|öéXŒÀRÁ-W-Awé•ca÷ŻƒÏZ@'v-ùŞÜ¤>ô"D TRGŝ‘/ĊA € ‰ĈAÄw•À `œSG.Ĥ™ı(<Yˆĝd-$5$Mf–Şš‰ċQEñ˜ŝP8LDpòó˜C‚5P‚†—¸ÀpıBÈ$eèÂӞD?°ä7šGmԅ`èM!;hercules-3.07/html/images/dial2.gif000644 000765 000765 00000003612 11143760534 020644 0ustar00jmaynardjmaynard000000 000000 GIF87a:6™™™www___UUUMMMĝĝĝ999êêê333)))ÌÌÌÀÀÀ²²²–––†††€€€fff˙˙˙BBBñññŬŬŬ×××"""ççÖËËË  ¤ ,:6ŝ@ G¨!rŽEŒÁ ‚@çÁ1“NCb‘X‘g"s8²ÍçDh0B  OefLnDEKJ      ˘ –KlHĵ–Ħ È ¤  v Ż´mMC—B  ÁÑ ž  İÇÌZÖ Ö^Žxë–FI$™t  ™ Ú½ğpD„@ @t`áP ŽíúuH´—$5iĈ€˜PĦğwÍ8àx @Ĥ 8 äŽAŝŽ/7şş`‚%iš ]˘* êz䠝‚Şt¸öŠPwZ8€ÀÑnŠ”Y`QBĦdêUw ă@ĥDÁĞ ZÚuˆv!Ö ¸c‚)Š/“EĥÓAÀ `H`kB(ĴP÷`ƒ jä\àkÁ 0¸‘ìKİÉ\ à‚' à$€Î@îĉy§ ĤÒRña÷ËŬ¤Ff` ƒž'üÁğ÷Ž…\+Â6½;3%ŽŞ†B]-â$ž"5³ŸDî\p| ]lHcG\üm¤NE~ŝĠƒ@pÁ‰QKˆáeò_ÙAÁS†*£ÀµŬ4 vB †ĝ!ˆ!xŜVÔÁ ;y 6 ,Ç_\dp˜ib€;~ö‚АóÑW™ö[ĜQTAŬW@Pacĥˆ÷!âDZĵ³ÑX T$éWÁìÇ$4àAL+yĤȎ#Â)ğu :yHpODÔ! Aĵ2¤dÔ4 ÁVxp`£·8Z ¤›nTZútPÀçİIaŬ&ĠZ‚€ċı‰à‡Vb‚5uJÄ` àáÀÍlGĉ \§ ‰ÓoÂé˜(A'şĥQŝ½=ċ_OrêŽL$ $°­pGĝÓpdM€ÙÉ%•†M> +1b ˆ§NÀV  x!™ï˜Ĥf!ǴˤÁhħ[?hR‚qÂĉ×äÂô1G•f§d2:o ê ‡%ÀÁÖLjÀm²ZğìÊĜ€\öğù3 ÁqĈn0ÓÌwİs†Ë^ŒÌ͈ÒQ3Hó@{5‹×ғvÙV avDJzlLi+p LdÀĠ+¨Ŭ^ıèéÀO~…²ÁŬf·[èFt|ñĊêiÇĴşN eŝċñ^¨pYŽÌ` ĵA(ÈÊ.ŝDÌ0™Q#Aż›ûyëƒGĤÀ ñ'7BĴ|é1Ù·o`ŒğßÑnO—Y0—ñ¸ħ‹Ç*ÈS³dğTyêíß+²›yĦıM6p@ü*éNÇ e·à÷Ñè7HÍ´V—v0ë\ĝo4„!;ܧ&ŻkŬíÔ÷’ ¤Í}[š5ġŽqħEòLôüòŠ*’óÛeÌ4w]&k[‘˜)ĝ†' …P ¨À'^'ÁyìukaĈ\™Fs“Ë1^GT˜4baċw;s!cw|bËÜÒ$ı„ÂMD1ĵçe.‚ÏóúìP p€ĉ`FßŝÄAŠ„":Ôaġ~·· P0uC ĤX#êü釒+ñ4–O”"5•—šky?Ĉ9â ï:´c1áC*ö§4“€LÁ†G°_ɘ\vÈĈG:²‰N+ċChޤOxÍ”‰ôhÁSËúäA)Ê?ù|€”— B˘ĥ¤ EP…j‚̝ħM,†ž ˘—ŬĤSƒ9ÀÈ!Lá lQ°3Ú³‰ pâSxC3˙-)Ï C¤Sd„É—ĝğ;‚³&oQŬ÷6߈UKSRH>2NJ[ğ§ŽÄR0…µŞ†!Üâ`(bé;oYĠ8!]ĉiİȘp$̋ƒ¤ċıCó—ÊŞBısHÔÓLàċ@K%(q„£ĥ1šx@žñż­¸ĊŠÉĜÍêš`²ášáêW/s /`ĵé²ÌÊT%6¤ÙŞI3 ‚pu>M8ƒkö‰:2…ä>fAH鴁iĜE$ˈ“Èutrµ4¸yĞIXK¸Ê ;hercules-3.07/html/images/dial3.gif000644 000765 000765 00000003612 11143760534 020645 0ustar00jmaynardjmaynard000000 000000 GIF87a:6™™™www___UUUMMMĝĝĝ999êêê333)))ÌÌÌÀÀÀ²²²–––†††€€€fff˙˙˙BBBñññŬŬŬ×××"""ççÖËËË  ¤ ,:6ŝ@ G¨!rŽEŒÁ ‚@çÁ1“NCb‘X‘g"s8²ÍçDh0B  OefLnDEKJ      ˘ –KlHĵ–Ħ È ¤  v Ż´mMC—B  ÁÑ ž  İÇÌZÖ Ö^Žxë–FI$™t  ™ Ú½ğpD„@ @t`áP ŽíúuH´—$5iĈ€˜PĦğwÍ8àx @Ĥ 8 äŽAŝŽ/7şş`‚%iš ]˘* êz䠝‚Şt¸öŠPwZ8€ÀÑnŠ”Y`QBĦdêUw ă@ĥDÁĞ ZÚuˆv!Ö ¸c‚)Š/“EĥÓAÀ `H`kB(ĴP÷`ƒ jä\àkÁ 0¸‘ìKİÉ\ à‚' à$€Î@îĉy§ ĤÒRña÷ËŬ¤Ff` ƒž'üÁğ÷Ž…\+Â6½;3%ŽŞ†B]-â$ž"5³ŸDî\p| ]lHcG\üm¤NE~ŝĠƒ@pÁ‰QKˆáeò_ÙAÁS†*£ÀµŬ4 vB †ĝ!ˆ!xŜVÔÁ ;y 6 ,Ç_\dp˜ib€;~ö‚АóÑW™ö[ĜQTAŬW@Pacĥˆ÷!âDZĵ³ÑX T$éWÁìÇ$4àAL+yĤȎ#Â)ğu :yHpODÔ! Aĵ2¤dÔ4 ÁVxp`£·8Z ¤›nTZútPÀçİIaŬ&ĠZ‚€ċı‰à‡Vb‚5uJÄ` àáÀÍlGĉ \§ ‰ÓoÂé˜(A'şĥQŝ½=ċ_OrêŽL$ $°­pGĝÓpdM€ÙÉ%•†M> +1b ˆ§NÀV  x!™ï˜Ĥf!ǴˤÁhħ[?hR‚qÂĉ×äÂô1G•f§d2:o ê ‡%ÀÁÖLjÀm²ZğìÊĜ€\öğù3 ÁqĈn0ÓÌwİs†Ë^ŒÌ͈ÒQ3Hó@{5‹×ғvÙV avDJzlLi+p LdÀĠ+¨Ŭ^ıèéÀO~…²ÁŬf·[èFt|ñĊêiÇĴşN eŝċñ^¨pYŽÌ` ĵA(ÈÊ.ŝDÌ0™Q#Aż›ûyëƒGĤÀ ñ'7BĴ|é1Ù·o`ŒğßÑnO—Y0—ñ¸ħ‹Ç*ÈS³dğTyêíß+²›yĦıM6p@ü*éNÇ e·à÷Ñè7HÍ´V—v0ë\ĝo4„!;ܧ&ŻkŬíÔ÷’ ¤Í}[š5ġŽqħEòLôüòŠ*’óÛeÌ4w]&k[‘˜)ĝ†' …P ¨À'^'ÁyìukaĈ\™Fs“Ë1^GT˜4baċw;s!cw|bËÜÒ$ı„ÂMD1ĵçe.‚ÏóúìP p€ĉ`FßŝÄAŠ„":Ôaġ~·· P0uC ĤX#êü釒+ñ4–O”"5•—šky?Ĉ9â ï:´c1áC*ö§4“€LÁ†G°_ɘ\vÈĈG:²‰N+ċChޤOxÍ”‰ôhÁSËúäA)Ê?ù|€”— B˘ĥ¤ EP…j‚̝ħM,†ž ˘—ŬĤSƒ9ÀÈ!Lá lQ°3Ú³‰ pâSxC3˙-)Ï C¤Sd„É—ĝğ;‚³&oQŬ÷6߈UKSRH>2NJ[ğ§ŽÄR0…µŞ†!Üâ`(bé;oYĠ8!]ĉiİȘp$̋ƒ¤ċıCó—ÊŞBısHÔÓLàċ@K%(q„£ĥ1šx@žñż­¸ĊŠÉĜÍêš`²ášáêW/s /`ĵé²ÌÊT%6¤ÙŞI3 ‚pu>M8ƒkö‰:2…ä>fAH鴁iĜE$ˈ“Èutrµ4¸yĞIXK¸Ê ;hercules-3.07/html/images/dial4.gif000644 000765 000765 00000003612 11143760534 020646 0ustar00jmaynardjmaynard000000 000000 GIF87a:6™™™www___UUUMMMĝĝĝ999êêê333)))ÌÌÌÀÀÀ²²²–––†††€€€fff˙˙˙BBBñññŬŬŬ×××"""ççÖËËË  ¤ ,:6ŝ@ G¨!rŽEŒÁ ‚@çÁ1“NCb‘X‘g"s8²ÍçDh0B  OefLnDEKJ      ˘ –KlHĵ–Ħ È ¤  v Ż´mMC—B  ÁÑ ž  İÇÌZÖ Ö^Žxë–FI$™t  ™ Ú½ğpD„@ @t`áP ŽíúuH´—$5iĈ€˜PĦğwÍ8àx @Ĥ 8 äŽAŝŽ/7şş`‚%iš ]˘* êz䠝‚Şt¸öŠPwZ8€ÀÑnŠ”Y`QBĦdêUw ă@ĥDÁĞ ZÚuˆv!Ö ¸c‚)Š/“EĥÓAÀ `H`kB(ĴP÷`ƒ jä\àkÁ 0¸‘ìKİÉ\ à‚' à$€Î@îĉy§ ĤÒRña÷ËŬ¤Ff` ƒž'üÁğ÷Ž…\+Â6½;3%ŽŞ†B]-â$ž"5³ŸDî\p| ]lHcG\üm¤NE~ŝĠƒ@pÁ‰QKˆáeò_ÙAÁS†*£ÀµŬ4 vB †ĝ!ˆ!xŜVÔÁ ;y 6 ,Ç_\dp˜ib€;~ö‚АóÑW™ö[ĜQTAŬW@Pacĥˆ÷!âDZĵ³ÑX T$éWÁìÇ$4àAL+yĤȎ#Â)ğu :yHpODÔ! Aĵ2¤dÔ4 ÁVxp`£·8Z ¤›nTZútPÀçİIaŬ&ĠZ‚€ċı‰à‡Vb‚5uJÄ` àáÀÍlGĉ \§ ‰ÓoÂé˜(A'şĥQŝ½=ċ_OrêŽL$ $°­pGĝÓpdM€ÙÉ%•†M> +1b ˆ§NÀV  x!™ï˜Ĥf!ǴˤÁhħ[?hR‚qÂĉ×äÂô1G•f§d2:o ê ‡%ÀÁÖLjÀm²ZğìÊĜ€\öğù3 ÁqĈn0ÓÌwİs†Ë^ŒÌ͈ÒQ3Hó@{5‹×ғvÙV avDJzlLi+p LdÀĠ+¨Ŭ^ıèéÀO~…²ÁŬf·[èFt|ñĊêiÇĴşN eŝċñ^¨pYŽÌ` ĵA(ÈÊ.ŝDÌ0™Q#Aż›ûyëƒGĤÀ ñ'7BĴ|é1Ù·o`ŒğßÑnO—Y0—ñ¸ħ‹Ç*ÈS³dğTyêíß+²›yĦıM6p@ü*éNÇ e·à÷Ñè7HÍ´V—v0ë\ĝo4„!;ܧ&ŻkŬíÔ÷’ ¤Í}[š5ġŽqħEòLôüòŠ*’óÛeÌ4w]&k[‘˜)ĝ†' …P ¨À'^'ÁyìukaĈ\™Fs“Ë1^GT˜4baċw;s!cw|bËÜÒ$ı„ÂMD1ĵçe.‚ÏóúìP p€ĉ`FßŝÄAŠ„":Ôaġ~·· P0uC ĤX#êü釒+ñ4–O”"5•—šky?Ĉ9â ï:´c1áC*ö§4“€LÁ†G°_ɘ\vÈĈG:²‰N+ċChޤOxÍ”‰ôhÁSËúäA)Ê?ù|€”— B˘ĥ¤ EP…j‚̝ħM,†ž ˘—ŬĤSƒ9ÀÈ!Lá lQ°3Ú³‰ pâSxC3˙-)Ï C¤Sd„É—ĝğ;‚³&oQŬ÷6߈UKSRH>2NJ[ğ§ŽÄR0…µŞ†!Üâ`(bé;oYĠ8!]ĉiİȘp$̋ƒ¤ċıCó—ÊŞBısHÔÓLàċ@K%(q„£ĥ1šx@žñż­¸ĊŠÉĜÍêš`²ášáêW/s /`ĵé²ÌÊT%6¤ÙŞI3 ‚pu>M8ƒkö‰:2…ä>fAH鴁iĜE$ˈ“Èutrµ4¸yĞIXK¸Ê ;hercules-3.07/html/images/favicon.ico000644 000765 000765 00000076446 11143760534 021322 0ustar00jmaynardjmaynard000000 000000 00 ¨%F hî%@@ (BV*  ¨~l(0`   ˆÌêìϏ%5Ü˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙ċBŬ˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙é#˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙‘Ï˙˙˙˙˙˙˙˙˙˙˙ ˙ ˙ ˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙ ˙ ˙ ˙˙˙˙˙˙˙˙˙˙˙˙˙Óî˙˙˙˙˙˙˙˙˙ ˙˙""˙&&˙%%˙˙˙ ˙˙˙˙˙˙˙˙˙˙˙˙˙ ˙˙##˙''˙%%˙˙ ˙ ˙˙˙˙˙˙˙˙˙˙íñ˙˙˙˙˙˙˙˙ ˙&&˙-<<˙9MM˙?UU˙=RR˙3EE˙%11˙˙ ˙˙˙˙˙˙˙˙˙˙˙˙))˙/??˙;OO˙@VV˙=RR˙3DD˙#//˙˙ ˙˙˙˙˙˙˙˙˙ñ˙˙˙˙˙˙˙ ˙##˙3DD˙;sL˙¤˙°˙°˙Ĥ˙/w8˙(66˙˙˙˙˙˙˙˙˙˙˙ ˙))˙7JJ˙9|G˙§˙ħ˙ħ˙˙0k<˙#//˙ ˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙'44˙F^^˙Ĥ˙´˙´˙´˙´˙ħ˙3b@˙''˙ ˙˙˙˙˙˙˙˙˙˙.>>˙DnX˙ ˙´˙´˙´˙´˙˙2CC˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙-<<˙Lff˙Ż˙´˙´˙´˙´˙´˙3z=˙$00˙ ˙˙˙˙˙˙˙˙˙ ˙6II˙?~O˙´˙´˙´˙´˙´˙Ż˙:NN˙""˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙-<<˙Lff˙! ˙´˙´˙´˙´˙Ż˙M˙­ ˙´˙´˙³˙06˙?UU˙))˙ ˙˙˙˙˙˙˙˙˙˙1BB˙Mhh˙4Š=˙²˙´˙´˙Ż˙9„E˙6II˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙-<<˙Lff˙Ş˙´˙´˙´˙´˙´˙6qC˙"--˙ ˙˙˙˙˙˙˙˙˙˙5GG˙CwW˙²˙´˙´˙´˙´˙Ş˙9LL˙!!˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙.>>˙Mgg˙Ż˙´˙´˙´˙´˙´˙4z?˙%11˙ ˙˙˙˙˙˙˙˙˙!!˙8KK˙@}Q˙´˙´˙´˙´˙´˙˙;OO˙##˙ ˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙-<<˙Lff˙%œ$˙´˙´˙´˙´˙Ğ ˙>hR˙$00˙ ˙˙˙˙˙˙˙˙˙˙6HH˙Mof˙Ĥ˙´˙´˙´˙´˙$"˙9LL˙!!˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙*88˙Jcc˙Loe˙ Ħ˙´˙´˙­ ˙ExX˙CZZ˙!,,˙ ˙˙˙˙˙˙˙˙˙˙1BB˙Mhh˙Ht]˙Ş˙´˙´˙£˙Joc˙6HH˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙*88˙Jcc˙6ˆ@˙°˙´˙´˙´˙(˜*˙C]Y˙!,,˙ ˙˙˙˙˙˙˙˙˙˙0AA˙Mhh˙+”/˙³˙´˙´˙ħ˙6‡@˙6HH˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙-<<˙Lff˙­ ˙´˙´˙´˙´˙´˙7xD˙(66˙˙ ˙˙˙˙˙˙˙ ˙$$˙8KK˙AzS˙³˙´˙´˙´˙´˙Ĵ ˙9LL˙!!˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙-==˙Mgg˙ ˙´˙´˙´˙´˙´˙:H˙6II˙"--˙ ˙˙˙˙˙˙˙&&˙,;;˙E]]˙A|R˙³˙´˙´˙´˙´˙ ˙:NN˙""˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙*99˙Kdd˙-’2˙´˙´˙´˙´˙! ˙Nmh˙Kdd˙>SS˙6II˙6HH˙6HH˙6HH˙6HH˙6HH˙6HH˙:NN˙E\\˙Ojj˙Pkk˙(˜)˙´˙´˙´˙´˙,“0˙7JJ˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙'55˙Haa˙Nmh˙"Ÿ˙´˙´˙´˙%œ$˙-“1˙+•.˙+•.˙*”-˙*”-˙*”-˙*”-˙*”-˙*”-˙*”-˙+•.˙+•.˙+•.˙,“0˙(˜*˙³˙´˙´˙ Ħ˙Lle˙4FF˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙)77˙Jcc˙+”/˙´˙´˙´˙´˙´˙´˙´˙´˙´˙´˙´˙´˙´˙´˙´˙´˙´˙´˙´˙´˙´˙´˙´˙´˙*”-˙5GG˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙-<<˙Lff˙Ż˙´˙´˙´˙´˙´˙´˙´˙´˙´˙´˙´˙´˙´˙´˙´˙´˙´˙´˙´˙´˙´˙´˙´˙´˙ ˙9LL˙!!˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙-==˙Mgg˙­ ˙´˙´˙´˙´˙´˙´˙´˙´˙´˙´˙´˙´˙´˙´˙´˙´˙´˙´˙´˙´˙´˙´˙´˙´˙­ ˙:NN˙""˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙*99˙Kdd˙3‹<˙³˙´˙´˙´˙´˙´˙´˙´˙´˙´˙´˙´˙´˙´˙´˙´˙´˙´˙´˙´˙´˙´˙´˙³˙/5˙7JJ˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙'55˙Haa˙Nmh˙!Ÿ˙´˙´˙´˙,“0˙<‚I˙9…E˙9…E˙9…E˙9…E˙9…E˙9…E˙9…E˙9…E˙9…E˙9…E˙9…E˙9…E˙;‚I˙06˙´˙´˙´˙£˙Kmc˙4FF˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙)77˙Jcc˙*–,˙´˙´˙´˙´˙˙Kqb˙Nii˙Haa˙E\\˙D[[˙D[[˙D[[˙D[[˙D[[˙D[[˙F^^˙Lff˙Pkk˙Nmh˙ Ħ˙´˙´˙´˙´˙'˜(˙6HH˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙-<<˙Lff˙Ż˙´˙´˙´˙´˙´˙:‚G˙?UU˙-<<˙$00˙"..˙"..˙"..˙"..˙"..˙#//˙'55˙6HH˙Kdd˙@}Q˙´˙´˙´˙´˙´˙˙9MM˙!!˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙-==˙Mgg˙Ğ ˙´˙´˙´˙´˙´˙SS˙DxX˙²˙´˙´˙´˙´˙İ˙:NN˙""˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙+::˙Kee˙<‚J˙­ ˙´˙´˙²˙/4˙D^\˙$00˙ ˙˙˙˙˙˙˙˙ ˙˙4FF˙Nii˙5Š>˙ħ˙´˙´˙Ż˙9ƒF˙7JJ˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙)77˙Jcc˙Kqb˙ Ħ˙´˙´˙­ ˙A|S˙CZZ˙!,,˙ ˙˙˙˙˙˙˙˙˙˙0AA˙Mhh˙EwY˙Ş˙´˙´˙¤˙Hp`˙5GG˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙*99˙Kee˙"Ÿ˙´˙´˙´˙´˙˙=gO˙"..˙ ˙˙˙˙˙˙˙˙˙˙3EE˙Jpb˙Ş˙´˙´˙´˙´˙"Ÿ˙7JJ˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙-==˙Mgg˙Ż˙´˙´˙´˙´˙´˙4z?˙%11˙ ˙˙˙˙˙˙˙˙˙!!˙8KK˙?~P˙´˙´˙´˙´˙´˙Ż˙:NN˙""˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙-==˙Mgg˙§˙´˙´˙´˙´˙³˙9qH˙$00˙ ˙˙˙˙˙˙˙˙˙!!˙7JJ˙EwY˙ħ˙´˙´˙´˙´˙Ĥ˙:NN˙""˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙+::˙Kee˙A{S˙Ş˙´˙´˙ħ˙5‰?˙BXX˙ ++˙ ˙˙˙˙˙˙˙˙˙˙3EE˙Nii˙:„F˙Ż˙´˙´˙Ğ ˙A{R˙7JJ˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙*88˙Jcc˙Ht^˙˙´˙´˙Ż˙>N˙?UU˙((˙ ˙˙˙˙˙˙˙˙˙˙2CC˙Mhh˙?~P˙Ğ ˙´˙´˙Ĥ˙Fr\˙6HH˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙,;;˙Lff˙¤˙´˙´˙´˙´˙Ż˙:hK˙!,,˙ ˙˙˙˙˙˙˙˙˙˙5GG˙Ft[˙Ż˙´˙´˙´˙´˙£˙8KK˙ ˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙.>>˙Mgg˙Ż˙´˙´˙´˙´˙´˙3z>˙$00˙ ˙˙˙˙˙˙˙˙˙""˙9LL˙?~N˙´˙´˙´˙´˙´˙Ż˙:NN˙""˙ ˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙+::˙Kdd˙˘˙´˙´˙´˙´˙ħ˙9kI˙"..˙ ˙˙˙˙˙˙˙˙˙˙5GG˙Gs]˙Ż˙´˙´˙´˙´˙£˙7JJ˙ ˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙ ˙"--˙?TT˙Ft[˙#"˙Ż˙ħ˙Ğ ˙6„@˙5GG˙""˙ ˙˙˙˙˙˙˙˙˙˙)77˙F^^˙;‚I˙İ˙ħ˙ħ˙£˙=qO˙,;;˙˙˙˙˙˙˙˙˙˙ñ˙˙˙˙˙˙˙ ˙˙)77˙?TT˙Kdd˙Nii˙Mhh˙Haa˙8KK˙!,,˙˙˙˙˙˙˙˙˙˙˙ ˙""˙/??˙D[[˙Mgg˙Nii˙Mhh˙E]]˙2CC˙%%˙ ˙˙˙˙˙˙˙˙˙ñí˙˙˙˙˙˙˙˙ ˙˙!,,˙+::˙1BB˙0AA˙)77˙&&˙˙˙˙˙˙˙˙˙˙˙˙˙ ˙˙%11˙.>>˙3DD˙/??˙'44˙""˙ ˙˙˙˙˙˙˙˙˙˙íÊ˙˙˙˙˙˙˙˙˙˙ ˙˙˙˙˙ ˙˙˙˙˙˙˙˙˙˙˙˙˙˙ ˙ ˙˙˙˙˙ ˙˙˙˙˙˙˙˙˙˙˙x˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙‰Ò˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙ß)Ï˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙Ù5xĊéëʀàÀ€€€À(    ZÜŜ]ä˙ ˙ ˙ ˙˙˙˙˙˙ ˙˙ ˙˙˙ċó˙!!˙œ˙Ż˙J˙˙˙˙ ˙T#˙Ż˙™ ˙ ˙˙ó ˙'55˙˘˙´˙O!˙˙˙˙˙/e;˙´˙˙˙˙ ˙+::˙İ˙´˙\ ˙˙˙˙˙1r;˙´˙Ĥ ˙˙˙ ˙+::˙£˙´˙ Q%˙˙˙˙˙4jB˙´˙˙˙˙ ˙+::˙¨˙´˙&m+˙""˙!˙$˙%22˙4|?˙´˙¤˙˙˙ ˙+::˙¤˙´˙­ ˙Ğ ˙Ş ˙Ğ ˙Ğ ˙­ ˙´˙Ÿ˙˙˙ ˙+::˙¤˙´˙¨˙Ĥ˙Ĥ˙Ĥ˙Ĥ˙§˙´˙Ÿ˙˙˙ ˙+::˙¨˙´˙0z9˙/??˙+<9˙->;˙9LL˙9€E˙´˙¤ ˙˙˙ ˙+::˙˘˙´˙$V+˙˙ ˙ ˙&&˙7lG˙³˙œ˙˙˙ ˙+::˙İ˙´˙[ ˙˙˙˙˙1r;˙´˙¤ ˙˙˙ ˙+::˙¤˙´˙R$˙˙˙˙˙4lA˙´˙ž˙˙˙ó ˙#//˙ ˙ħ˙R˙˙˙˙˙*e2˙ħ˙›˙ ˙˙óâ˙˙#//˙!,,˙˙˙˙˙ ˙##˙%11˙""˙ ˙˙äVÛ ñ ñŬZ€€(@€   P ÔìíÙ§[˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙½'Ë˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙Ü%İ˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙ÁB˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙Z™˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙Ğ×˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙Üï˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙ ˙ ˙ ˙ ˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙ ˙ ˙ ˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙ïñ˙˙˙˙˙˙˙˙˙˙˙˙ ˙˙˙%%˙''˙''˙""˙˙ ˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙ ˙˙ ˙&&˙((˙''˙!!˙˙ ˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙ ˙˙&33˙4FF˙=RR˙AWW˙@VV˙:NN˙0@@˙!,,˙˙ ˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙ ˙%%˙*99˙8KK˙?UU˙BXX˙@VV˙9LL˙-<<˙''˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙ ˙˙+::˙@\V˙,1˙Ş˙°˙°˙Ĵ ˙#š"˙3fA˙%22˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙ ˙%%˙3EE˙@mS˙$œ#˙­ ˙°˙°˙Ĵ ˙'’)˙3PC˙((˙ ˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙ ˙"..˙@VV˙*–,˙´˙´˙´˙´˙´˙´˙Ğ ˙5ZE˙''˙ ˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙-<<˙Ge^˙˙´˙´˙´˙´˙´˙´˙%–$˙-==˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙,;;˙Kee˙­ ˙´˙´˙´˙´˙´˙´˙´˙0‚8˙'44˙˙˙˙˙˙˙˙˙˙˙˙˙˙ ˙##˙9LL˙<K˙´˙´˙´˙´˙´˙´˙´˙Ĵ ˙9MM˙""˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙0@@˙Mhh˙°˙´˙´˙´˙´˙´˙´˙´˙.‹3˙*99˙˙˙˙˙˙˙˙˙˙˙˙˙˙ ˙''˙=RR˙8†D˙´˙´˙´˙´˙´˙´˙´˙°˙=RR˙%%˙ ˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙-<<˙Lff˙˘˙´˙´˙´˙´˙´˙´˙´˙9vF˙'44˙˙˙˙˙˙˙˙˙˙˙˙˙˙ ˙##˙9LL˙Gu\˙Ż˙´˙´˙´˙´˙´˙´˙£˙9LL˙!!˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙ ˙%22˙F^^˙DyV˙˙´˙´˙´˙´˙²˙/5˙AWW˙ ++˙ ˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙/??˙Lff˙6ˆA˙Ż˙´˙´˙´˙´˙Ĥ˙@wR˙1BB˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙ ˙ ++˙@VV˙Pkk˙?~O˙³˙´˙´˙´˙%›$˙Pkk˙SS˙''˙ ˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙/??˙Mgg˙=€L˙Ş˙´˙´˙´˙´˙%œ$˙DnZ˙-<<˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙'55˙Haa˙#ž ˙´˙´˙´˙´˙´˙´˙ħ˙9lH˙"..˙ ˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙4FF˙Fr\˙­ ˙´˙´˙´˙´˙´˙´˙" ˙3DD˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙.>>˙Mgg˙Ż˙´˙´˙´˙´˙´˙´˙´˙.‡4˙)77˙˙˙˙˙˙˙˙˙˙˙˙˙˙ ˙%%˙N˙²˙´˙´˙´˙²˙(˜)˙+•.˙*–,˙*–,˙*–,˙*–,˙*–,˙*–,˙*–,˙*–,˙*–,˙*–,˙*–,˙*–,˙*–,˙*–,˙*–,˙*–,˙*–,˙*•-˙*–,˙Ż˙´˙´˙´˙´˙;ƒH˙Jcc˙,;;˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙ ˙!,,˙BXX˙Gu\˙ Ħ˙´˙´˙´˙´˙´˙3‹<˙Pkk˙Pkk˙Mgg˙Kdd˙Jcc˙Jcc˙Jcc˙Jcc˙Jcc˙Jcc˙Jcc˙Jcc˙Jcc˙Jcc˙Kdd˙Lff˙Nii˙Pkk˙Pkk˙8†D˙³˙´˙´˙´˙´˙˙@sQ˙-<<˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙'44˙H``˙"Ÿ˙´˙´˙´˙´˙´˙´˙³˙@}P˙D[[˙3EE˙,;;˙*88˙*88˙*88˙*88˙*88˙*88˙*88˙*88˙*88˙*88˙*99˙/??˙;OO˙Lff˙Ht]˙Ż˙´˙´˙´˙´˙´˙´˙ ˙3EE˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙-==˙Mgg˙Ż˙´˙´˙´˙´˙´˙´˙´˙0Œ7˙5GG˙((˙˙˙˙˙˙˙˙˙˙˙˙˙˙)77˙E\\˙9…E˙´˙´˙´˙´˙´˙´˙´˙Ż˙;OO˙##˙ ˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙0@@˙Mhh˙ ˙´˙´˙´˙´˙´˙´˙´˙1‡9˙-<<˙˙˙˙˙˙˙˙˙˙˙˙˙˙ ˙**˙?TT˙<‚I˙´˙´˙´˙´˙´˙´˙´˙­ ˙SS˙''˙ ˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙.>>˙Mgg˙Kqb˙%›%˙´˙´˙´˙´˙4‹<˙Lff˙/??˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙ ˙'44˙H``˙-“1˙´˙´˙´˙´˙´˙´˙Ğ ˙SS˙8†C˙´˙´˙´˙´˙´˙´˙´˙Ż˙M˙Ibb˙*99˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙ ˙"..˙BYY˙?~N˙Ĵ ˙´˙´˙´˙´˙´˙*“.˙7JJ˙""˙ ˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙*99˙Ibb˙+•.˙³˙´˙´˙´˙´˙­ ˙;yI˙-<<˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙)77˙Ibb˙Ĥ˙´˙´˙´˙´˙´˙´˙´˙4o@˙!,,˙ ˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙3EE˙AyS˙³˙´˙´˙´˙´˙´˙´˙¤˙4FF˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙/??˙Mgg˙°˙´˙´˙´˙´˙´˙´˙´˙-‰2˙)77˙˙˙˙˙˙˙˙˙˙˙˙˙˙ ˙&&˙>˙Mgg˙Ğ ˙´˙´˙´˙´˙´˙´˙´˙3ƒ<˙*99˙˙˙˙˙˙˙˙˙˙˙˙˙˙ ˙''˙>SS˙=€L˙´˙´˙´˙´˙´˙´˙´˙Ğ ˙eQ˙$00˙ ˙˙˙˙˙˙˙˙˙˙˙˙˙˙ ˙6HH˙Lme˙§˙´˙´˙´˙´˙´˙´˙+‘0˙4FF˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙ ˙""˙3DD˙Jcc˙8†D˙¤˙Ż˙°˙°˙ Ħ˙?wP˙3EE˙!!˙ ˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙'44˙D[[˙EwY˙#ž!˙Ż˙°˙°˙Ş˙07˙A[W˙%22˙˙˙˙˙˙˙˙˙˙˙˙˙˙ñ˙˙˙˙˙˙˙˙˙˙˙ ˙&&˙0AA˙CZZ˙Lff˙Ojj˙Ojj˙Mhh˙F^^˙4FF˙**˙ ˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙ ˙˙+::˙@VV˙Kee˙Nii˙Pkk˙Nii˙Kdd˙>SS˙*88˙˙ ˙˙˙˙˙˙˙˙˙˙˙˙˙í˙˙˙˙˙˙˙˙˙˙˙˙ ˙˙$00˙-==˙3DD˙3EE˙/??˙'44˙##˙ ˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙ ˙˙!,,˙,;;˙2CC˙4FF˙1BB˙*99˙ ++˙˙ ˙˙˙˙˙˙˙˙˙˙˙˙˙˙îÒ˙˙˙˙˙˙˙˙˙˙˙˙˙ ˙ ˙˙˙˙˙˙ ˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙ ˙˙˙˙˙˙ ˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙Ĝ˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙¤7ŭ˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙N—˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙°¸˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙Ê–û˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙Ĥ:ŽÎëìԖDĝàÀ€€€€Ààĝ( @   >´çé¸F:ò˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙÷Dĥ˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙½ì˙˙˙˙˙˙˙ ˙˙˙˙˙˙˙˙˙˙˙˙˙˙ ˙˙˙˙˙˙˙˙˙ìñ˙˙˙˙˙ ˙˙""˙ ˙˙ ˙˙˙˙˙˙˙˙˙ ˙˙""˙˙˙˙˙˙˙˙˙ñ˙˙˙˙ ˙!!˙x˙­˙Ż˙˙'˙ ˙˙˙˙˙˙˙ ˙/&˙˙Ż˙˙s˙ ˙˙˙˙˙˙˙˙˙˙ ˙%11˙­˙´˙´˙´˙Y˙ ˙˙˙˙˙˙˙˙$`*˙´˙´˙´˙Ğ˙˙˙˙˙˙˙˙˙˙˙˙*99˙#™!˙´˙´˙İ ˙E&˙ ˙˙˙˙˙˙˙˙0T>˙İ˙´˙´˙‘˙ ˙˙˙˙˙˙˙˙˙˙˙,;;˙7C˙´˙´˙!– ˙$00˙ ˙˙˙˙˙˙˙!!˙6II˙(—*˙´˙´˙)t/˙!!˙˙˙˙˙˙˙˙˙˙˙-<<˙Ĵ ˙´˙´˙´˙[ ˙ ˙˙˙˙˙˙˙!!˙,g6˙´˙´˙´˙İ˙!!˙˙˙˙˙˙˙˙˙˙˙-<<˙§˙´˙´˙³˙T$˙ ˙˙˙˙˙˙ ˙!!˙/`:˙°˙´˙´˙˘ ˙!!˙˙˙˙˙˙˙˙˙˙˙-<<˙9~F˙³˙´˙$’$˙$00˙ ˙˙˙˙˙˙ ˙!!˙7JJ˙+”/˙´˙´˙+m4˙!!˙˙˙˙˙˙˙˙˙˙˙-<<˙£˙´˙´˙°˙!Q'˙˙˙˙˙˙˙ ˙$$˙1`=˙Ż˙´˙´˙˙!!˙˙˙˙˙˙˙˙˙˙˙-<<˙­ ˙´˙´˙´˙&e,˙##˙˙˙˙˙˙˙%22˙4p@˙´˙´˙´˙Ş˙!!˙˙˙˙˙˙˙˙˙˙˙,;;˙5„?˙³˙´˙İ˙4s@˙)^3˙#X*˙#X*˙#X*˙#X*˙#X*˙&\.˙/g;˙4˙˜˙ħ˙˙t˙˙˙˙˙˙˙ñê˙˙˙˙ ˙˙"--˙+::˙*88˙((˙˙˙˙˙˙˙˙˙ ˙ ˙&33˙,;;˙'44˙!!˙ ˙˙˙˙˙˙ëħ˙˙˙˙˙ ˙ ˙˙˙ ˙˙˙˙˙˙˙˙˙˙ ˙˙˙˙ ˙˙˙˙˙˙˙¸3ì˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙ò<5­ĉè²<À€€Àhercules-3.07/html/images/greend.gif000644 000765 000765 00000001441 11143760534 021113 0ustar00jmaynardjmaynard000000 000000 GIF87a!Ĉ[~YX|VUzSTzRQxONvLHrF™™FpDŸPwM˜¤—•˘”’ ‘ŽžŒœ‹‹œŠˆš‡…˜„‚––€~”}{’zxwtŽsqŒpnŠmmŠl~“|wutrq‹op‹nj‡hg…egzocƒa`^][Z}XY}WV{TSyQOwMMuKLuJGqE‘ ‘=NELtIKtHIrF–£•“Ħ’‘ŸŸŠ›‰‰›ˆ‡™†ƒ—‚€•}“|y‘xvusro‹n|’zywxvuŽsrŒpnŠllˆjkˆii†gh†fe„cb‚`_€],!ŝ€‚ƒ„…†‡ˆ‰Š‹$@F!IJL#M%N&O')*+ -23/ ‚$ B”–˜šœž ˘¤-.¨/Ĵ?EŻGB“•—™›Ÿ*£,§4Ĵ?ސ!HI"KL·Íş£§ĴCG’ßK˸ΠѤÔĴ>ĜڰǒÙb– Ċ½s-Xġ°ÁŸ;cBĵ)™7à.iĴ(,l˜ÍQ€”(´j+6úÛÉ8zä šc5ċÂ~ĥ“(²^ıĴvÔÔÈoċğnòč “•Ħ6:ÌD2y0s}bái͔E;›2Ğ3]Ħ‚]'ÖX<‡}²z!‡×¨8µ=’5éeĊĴpµĞöĤÑXW•UduCŬ: KÍöêcb&J5ħ²qC0„´_7²Ó 1Y¸[Ĵpvph~숰 A î2V5Tp\÷îڕߞfĊ · ‚#€Ĉëp,­‰#X!(ùc߆ÛÂ{DPŒïà‹Oĵ @;hercules-3.07/html/images/greenu.gif000644 000765 000765 00000001444 11143760534 021137 0ustar00jmaynardjmaynard000000 000000 GIF87a!Ĉ[~YX|VUzSTzRQxONvLHrF™™FpDŸPwM˜¤—•˘”’ ‘ŽžŒœ‹‹œŠˆš‡…˜„‚––€7F>~”}{’zxwtŽsqŒpnŠmmŠl~“|wutrq‹op‹nj‡hg…ecƒa`^][Z}XY}WV{TSyQOwMMuKLuJGqE‘ ‘^oeLtIKtHIrF–£•“Ħ’‘ŸŸŠ›‰‰›ˆ‡™†ƒ—‚€•}“|y‘xvusro‹n|’zywxvuŽsrŒpnŠllˆjkˆii†gh†fe„cb‚`_€],!ŝ€1@F "IJL$M%N&O')*+ -23/ ƒ1 !B‹‘“•—™›-.Ÿ/1ı?EĤ GBŠŒŽ’”–*š,ž4ı1?…‡"HI#KLĊħȚœžÏCğ†G‰ĜKŻĈ—É›ÌÏ>ÑÓ§żÁ­Ä°(àZ<ëqÁ½s„\SŽ›?YʞQ hPZĦ ú5ì÷“Ĥg<*PĵG ѵlíşŭûölBH‚övQûµp£;ožíp9ħItÖÖm`ċ3 ;_<¨!È`ëR²ô,R—"}ZD§J£TcU­&ÍJnĞ/u#ĝŬ|öBŽĞŠJcN3”JJ‡'žáhûv,̟¨  sĝ솂ĥtĝ]*ÍFÁL†FzfĈ^bħR,77a0mž5¨|8B_ÍġÊ))bUÚaÏjŒ†qĜ-\²$óĦŭŒlöFÈ÷ ×U ILz=++!I‚;bmI~~~jjO11%§MM: HH5777ž"66(´˙˙˙!ù,˙à'ŽdiŠE1HöW,Ïtmßxï|ï˙À F dFáÄl:‰ĉâİZŻĜĴvËízżà°xL.›É„„òÉnêyNŻÛïĝĵ"Yş˙$* z„…†‡ˆ‰k€lQrŠ“”•–“ Pƒ—žŸ Ħb›' ˘ŞĞĴ ~Ĥ­´µĥ…𛳷żÀbş ÁÈÉÊUĐ½ËÑÒ´nÓĜٟ°M Úàá•Ŭ&İâéê„Mëñòg'×óùú^ċö ¨Ċ‰& PâÂ‡û8Cħâ< °àYܘNWICj› B‚È“Ú ˙¤ €²ċ´]ÊT&â̛żàɓÒJ´(ĢH‰Ĥ£ !hÒ§IġAŞ4tɊ1şNë¤Ó È:”†Ĝ³hÑÒ¨ ŽèŒ´pĠÊàŞ,F0·1^Ŭ˗ŻÜ l •Ħ·ŻáĞgç]f÷WÙĵö>˜ü€‚ċË(?@,6F`e/ˆ•<³iÊ{;{Z$-ĵ£ ”ĉÀá€írß>ÀÁòd޳^ö8öìÚ·s#ĜM;ófà0„DÖ¸ìĞ•‘#ÈÀŬ‚÷ï¸gXŜû·êĊd@–ŭ@{wàıë.xġt`Ġ_Ğyríí4@À `˙xËe}ȇ¸eà€¨a ŽÇ›y0 ÷K~Ĵ”5Zeh N´èâ‹6Ŝ‡ġ á~ŭQÀ€ĝâ-"¨ ‡F'â-$ŞbbµY˜a°TVie8Àp°YgGÚ2˜h²Qˆ€Š D •lRı,°ċŒEBèK’˘ŒÉäô¨&*蠄v° ÈĜċ—Ğ96ĜhfZ` ZèbçÔiċ‰£lM8A˜Ĥ*(s. \£·èIꙓZŞ*Ĥ8Àif`Ŝg ž <…}&àÀ·&ğÁ dé !úŞ™íњ˙ÉŜŞ .Çè§ż†ì¨Ġ­ÙĤŞ€Ízù*¸­ÈJl ›î­`ĞтŻzbUFköŜĞêú"ÀkżÖ<ФĜĴêşÍÀèpáŝK-Ċ ñ­$šğ OÛŸôüñïË+ĴµëɨJzîÊêêê,Żbo^E éàœ*ğüÂۊ̖[né ¸ü´JlÀÓK](ÂÎ^Œġ*LWò(İĊŞìµ  0ğhŻ&£MoÔkÚr§=­JٔœŭŸL @Ŭ„ĥŬĜq˙AàtŜAÈV‰¤¸3;Ĵxàƒ;j##ñɋßĴy˙ $Ş žM^˘ċ€ >z ùvžwâ€Gıĉ7pşäŻâwë·k;ÉJ‹JmíÁžûîİ÷žġñ‹ğŝ:şïóó `ûëGŜ|̔_òûâ $_7Ċo—ì;ëĦ=:úâ­ŝÒá7mùŽô˘K8ä _ŬĈ?ÚëÀfħÙ9Ïx˘˜8şĜÉŻxÜĜ8ÂmàpßÏÈT³8`t“Ŭü|´nOxĠóœW·ħ´i {Ç¤bıςñ™‘ô& ġMk Ԟùpĥ.ΐw˙c­>¨1›Ĵh"ÀÒ`h‘wˆÈûĠ3ú[g>ÇİC˜EQŠÙӉqĥkŞRŸĠċş6;îž”Üâ°0 oŜ˙‹FüD+—RvtmÛY0UÇB%Ò ™ŽkÙî0:.ÒkĦRۖ µT6Tìe#™%Âr’4ĦBŭXÛ\-£zBžˆ(Ĥ¤˜(ĵâ2‚EÀd@½F½˘’lœ§?ç6ÀŞġ‰?ċšG?FÀgĈ3Ĵ‰H$ùnè¸ċy nŸC›îéµğôĞE(P£·V"mi­ŬV½Ĉ?žŽôP5Äĝ0÷ş Ï­ĉdŸıg:Dz4Ž—“^9‡XÁ^n–uíìk‰Èb²˘­ŞWY+Vèm„ġß3kÛĜ:Žz]è’ÚH³zv·5­!½ +1Ïİ}T.5? <°˙dLĞ"‰ûħĈêV£OĞÔÚzĠÀ’0š’ŻÑˆÙ˘gÜèöċùôHKrKfé(5îwYÙrBÈĠ@0ÏVۍë úuĠ½´!q;Xğ^œŭ³}¨B÷ş×híñÊ:ì³0Âzï.Q¸CğŝĊÁ0ùNŞ9òö½mwğˆċÁéôKÑ‚ĉqp"Ê·ÈÔWĝƒlÓt{m]­òĉÂúÖğŝġq)“‘[nL-ġĴóÎòßıi³°g[Ÿ3˘Ïa†OüâĝÙAY,]7™ï{ílïş×ÑÍĝӇYQĵés4ŭî{˙ûàże$Ê‚ìú'"/ùÒOıŻkVƒ–³›úÛ˙ŝĝÏżŝw“ ™ÊEjbséÒP˙û”{ş×RĵKšôE@#2â8XhŜ! $]&€ŞÒkbÖh†U”Ia×PHHB’ ,Ĝ‚.ĝ‚0ƒ,è#)x~ÍUeîô|Âtg”g~is¨VƒB8„DX„FXƒĠWMĥ4n+·~Ò7}eiħvì'Vx…X˜…Z¸…\Ĝ…^ĝ…Ĝ–O~Ĉ„}ZFJ-˘b•µ†l8^â¤jMYO8lšPmx‡xÈVÀ‡{qsˆ&2X°–„yXˆ†È2Evĝf[8Ìwˆ‰†2NêÇr4§H(‰šXˆ2ċd—\A§†›8ŠyxX•èwRaXGŠĴ˜t˙:8z@^­8‹lĜ`?ç„ÚE> G‹ĵ(1ĤvŸĜoĦċ{½XŒÊ„sO·ˆe7ŒĈĜŒF³<2T†~ĝS%HŒÎhŒvµZÁ‹ÀsŜ¸NN×S°hufgßH‹Ŭ‡Òhì7_W>çİ’vµŽ…Žô `µ'Ĵèx}xĜ~€Ç)(óˆÙE€CU)À…—‹אñˆ dcĈuŸ“€àي!ôŠhIÌ6)ĉĝ‘wmÁµÂ¨Hħĥ‹(‰7FNqˆŠÚeLs’1S‡ö<(MħFˆ;yˆí”ƒ§(‡<KqĤTmò”P•R9•TY•U˘T˙K†”·xi9q£4j?x„ÂFP–fy–h™–jı–lٖnù–Psb¨•g“k-²€z˜‚+(ƒ~ù—€™ 4˜‚™˜-G‚èf:ön3ĥŠö#[ò€8™”Y™x!$&_žôi5 y]YŻÔl#ĥh22ô·ŞıšĴiŭ')>ĝƒ§§%˘7’Ħö0³ƒ˘a–0ĵááœÂ9œÜ§#)’™²yl”¸•–(‘×"<úT1Şw|ÔYÖ™ہ—D)_ùkŸlĦI4KĞHD@F {êıžêY&¸ñGşY(™”Óĥ{ożuy²yüY'2{4†C˙dȒ·)‹‚…‡x JwxW‚bi0|÷„€f[0i0†3nÒħ :Qhƒ/¤uE§Œ ÈŒÓ#wßYmš ÊŽ?İZ°“—âsuÙmĥUžÏè˘]@544*ŸTǜ´˘Aş›…€hĜes½–j†$Ĵ•UğäĞz}šĴwJ­Rĝ§§–•Ë-a ˆifiHG¸„žúİŒ¸Ĵ-R˜żGgš˘µġh?ґ1§ÊŞ›*ej„Y‰Ĵħ"Uf­b‡ƒJ“zc*£½zĦ„ò˜žı°PŠ›.nš| Ğ­X5Qï'5U–~ĞZİíF¨ú1t¨ìÊ[ –Ûù1JöpıJQ–FIKqRi3› ;oŻT6ħ³jİ@ğ2Úĥħ”ʧݤCT*ŒÊ´ݲPG‚˙#–ġpôZm5{³ĝä¤pŞ´kŠr"šŒ,kp7…pÙZ-İ‹q÷\[ …2ĈĤ˜pqˎğZĦš…(7Ş˘½E·Ùâ]išQ‡t²ġ´z_gêa;hL:uJwt:JDTş²Žj˘I§¸>zZXK:—Ğs‡Ë·†*Ğ” ħ钎†ımğ\‡Ĥ›i(fzkS§ħ‹=oÇ´™Ĵf[pÚxZKħtğş{IœêŠûU„еıĵ¸›·z›£¨›,~ğ³;Q^{/ó9²ċ&½[zŜŠ3ĉÄ›'¸ŞâĤšZµ$Ȕ£Şo ¸v²DäDëê:ĉŞgwz$fş˙Âkñİ’œĞ”—XOök07ĤŽçëŽu¨› <İI[Ż è"°½ƒ˘hˆ‰½^‰ĵRĤ€%ú­‰i¸ÛZ‚(iÏzMkëhŠW°ĝv” ;żÑğ”†VılcMWvğ[’>X´…ÒgtÉÁ á g™„ĦñG† ŒözLğ6—3ì½fxÀĠêlˤħœDüÍ*1‡²d;ÁKĞ œ.½–0LŽO£kFóc·ÚTw‹·Óڃŭ›S$ÖÂÓêħñÙP"ËÓ¨Ĵ³ż GÄ\R`9§ EÂs ”Î9IödžŒÒÉlU€“|Ĉ Ù{¸#żT,ğ/|DŽӽ€ìÈí:A˙yêpY¸¤§ŠĠËIû¸8:·o‹q™ì³ Âc·M\›ìÊ=×ÛÈlr´ËXe+ŽlˍR·ı4|n+ËÚşú›ıŬ(ıù[˘ÈsËÚHĈ˘ü£ˆû[³ÜŞĦóıÙèÊ\ r¤Ka“{¸8ĴTÖL˘ĜüÌuUÌżĴğg4‘C·mù<ÁÜeJÍ“~v—É,5ì{Êşz“ĞŒR…üÏÇa–ĵwċÜÌâe@ĴTÎÍth[ €ÁÙbÊı ÌFĴËşŽ2T Zĝĵë_ĉK˵Œ› Ħc\Ç y¤ó%ǏÑ$ :ü<›èʀĞDSĠDEÍ Msó’Ġ>mÌ˙}ċ—Î Pßµ àN@ëğ~½  èÁŽpëPpì'q QàÎ ™ &ìĠ˘ŽíĉÛ.ŒÀéŜžíMîñ`Ŭ^î­Îéè~ìì+ ûٟüŜïŝŝïo!Ŝ;hercules-3.07/html/images/hercpic-rblk-80.gif000644 000765 000765 00000002714 11143760534 022445 0ustar00jmaynardjmaynard000000 000000 GIF89aPPÄDD3Z[D::,ceJóó󚚚$$VvC&™&Gi8 ĴD„8û9À À{;lh ĵ‰5ÊIÈxƒAiŽx˙Up@²ƒF :ùhD™Ċ‘$/œ”Y„"„•-_Bˆ‰PĦ€34 ħfE8.àXÔßÑHn(ĉN!ıHR  …fOW58Hz/˜M{†  !CT—@C™Ä,yi5„Ċ'Á¸<˙ÎĠP/ß zQ$&âwˆ2€8”à€k\Ċ_ܽ·Ù ­l˜QDĤ“…ĝ´È6ßĦħ…T–=·v>“SŝdI’ÌÜAvħ`t>Áİ$ŜúxUW}[úÙòSç÷Œ^sa֌ DDŝ#Ó×Á/œö˜z"Z€uG—öÌŜsŬ#A‘ñEŸ8ħž˙aˆ‘²˜šá³d{ġçr@\€1Ùz~•™TĤWV}ċ]à@ ĵf S_EèP֝hT9ڕ@%‰Ĝá}ô´$Q6Z%RKòµÒǒL2É @ÔmV#jF!Ġ’@CI'\vÉe/ €€S¨Z@ĊAV-´éĉ›m2C—`$e0ßL(ž•ÖŠ jÙ0*蠃à'c2JX …ĥwߜ|.àÀ¤”Vj镨…’‘§'~|ĥ$ê¨ùl‘TžyİĴĥzŞfb‡cĞ´’:$£y*fÀMµöJ’P°âyc9úJë­žêşšħÌĥu§ú÷èˆÍöÊ@˙‰/B›ĞeúÉ' „+î¸ä–;nm.šĴe i@~ (ĦôjèĦ|J@ÁݸV‰•VjçÀqŝâ§@%Ĵĥ‹%4^Fü/b‚×Áe käw¤()ÈàG/ĉ•1F6×pŸĝèò ìĞu‘Ĝ´ê@¨[5_!\ôϔMö$:RÙŝġI›˜ŞĴ#ıŬ@ŭ:sŜvÌr³ĊŒöCÔĵÍĉL9Ï9ndx˙Ĵ5MН7bS>—ċx­}xé%ÊÙaCağJSš^ёŝ)]ÔâCAĜUËJWî¤ĉşïʖœ ze‘Ŭ9€wĉzßηßE/9PŽınÙ·7WÇîŬp&qÛ*“œííUÄş€'W´GUÀ=> ¨ê²C¸ċ½ŻtyI` ĈßâĜ†r<` HÇ0À^Ĥ@Ç6Öa úŭ ZŝQF/˜Q" ‡5XĜÂ5•Bڟ£ !‰6q1ÔE 6áV\â£H†<ü‡&Ĥ ˆJäCxÄwòXÄ0l‘ 6XƒĠ€I7ŒñŒ[ˆ€Ĉ6Jáĝ€ŬHÇ"D€¨£… €+˜Ħ{ܣ⨃$1g䀛 7TÀ3ˆ¤$'ƒD€#;hercules-3.07/html/images/interruptd.gif000644 000765 000765 00000002644 11143760534 022055 0ustar00jmaynardjmaynard000000 000000 GIF87a!ç˙Ĥ¨˙)+˙YY˙‹‡˙‡‡˙ ˙:8˙88˙˙ġ˙ĦĦ˙ÏÏ˙RR˙PR˙€€˙˙31˙11˙a_˙__˙˙¤ò˙˙éé˙˙<>˙†ƒ˙šš˙ÈÈ˙IK˙yy˙**˙XX˙ ˙ ˙|˙ee˙—“˙ce˙““˙y|Ž ˙^[˙BD˙rr˙Љ˙##˙!#˙SQ˙QQ˙›–˙•–˙˙20˙00ŭ˙ŒŒ˙ˆŒ˙WT˙==˙;=˙mk˙kk˙™™˙‚˙˙LJ˙JJ˙xx˙+)˙))˙……˙˙dd˙–’˙bd˙’’˙x{ù˙˙CC˙qq˙$"˙""˙RP˙PP˙–•˙˙]]˙‹˙‹‹˙‡‹˙ıı˙<<˙jj˙˙KI˙IIñ˙„„˙jm˙˙55˙ec˙cc˙î˙DBî˙žž˙ÌÌ˙!!˙!˙}}˙..˙\\˙ŠŠ˙ ˙=;˙;;˙ƒ€˙ii˙gi˙——˙˙FH˙¤¤˙ÒÒ˙''˙UU˙˙•š˙˙44˙|y˙`b˙ù˙˙˙ §˙[X˙UX˙˙ƒ†˙ËË˙ ˙ ˙NN˙||ĝö˙--ö˙[[˙‰‰˙ ˙8:˙hh˙––˙Ĵ­˙’–˙˙˙GG˙uu˙££˙ÑÑ˙&&˙TT˙˙{x˙aa˙_a˙˙@@˙˘œ˙nn˙TW˙œœ˙˙MM˙İİğ++˙ˆˆ˙ ˙99˙79˙ig˙gg˙••˙˙HF˙FF˙ttê˙mj˙QS˙˙22˙02˙b`ŭ˙``˙êê˙˙??˙››˙ ˙ßà˙,!ŝH° Áƒ*\¨Ğ‡\FNM‰Ĉ" ›D ’SMŒ6XrCGNÚ¨kЇEM‘ċÀĊMHVUé˜@ ´O%•dÄİÌ–vÔB†kŒDYz!RVGÄ*9sˆkô“šÍ-(’BÒ4p6óGŻ42ŠqËc£ xH´›IË5’„ÈV–žpв2íÏǟ%öšdj³¤„Ò!ĉÂ0‚4ê$YeĊ’cxJ ÑҌċ™PL.È QĤa›Ş^­Ğ€+^BYÒ ŒÉĞ-‘ ¨4ËäVilŞQ†Ô…XRĦ&T f’ŝ?4R¸"˘UħäÑgj–¨ĥİ|+,—ÈÏ4WÀ ÓĜġK+ÄGË1Ħ¨qÇ\0OĜ" .˘dqD(ħX° •ˆ!Œ#°„ ¨ĵp`(£<£µ¨LıG 6¨Á–qä˜#,%ƒÉ Ċ˜xL£PSÀ‚ĝÁ@H#%ݨ Á Nèt Ĥ°4 &¸Râ‰kÀ‚ÙMÙĤ(ˆÄe]°T€C˜p„ZÖµıÖL`àVGNrÜÂR^L’ ^šÄ/L(‚ÙCcâ†,`X¤ĤN,-ÒĊ.fìI_Λ.1gPY*KO,‹ĝ¤|ÀĴñ ݵ\ ĉ&›À’(¤Ä҅'[b’H¨µŠ9B$d’QžTqħäA ĊvÁƒĦ]H\ ŽSd<ġgʰ$‰†  iĦAâvaÔŞÈ#‘Ñü€KÌÂnšršŒ nwFħŬ‰Ö%ĵv–‡/ħ`ñĊgĴñĈ ;hercules-3.07/html/images/interruptu.gif000644 000765 000765 00000002647 11143760534 022101 0ustar00jmaynardjmaynard000000 000000 GIF87a!ç˙Ĥ¨˙)+˙YY˙‹‡˙‡‡˙ ˙:8˙88˙˙ġ˙ĦĦ˙ÏÏ˙RR˙PR˙€€˙˙31˙11˙a_˙__˙˙¤ò˙˙éé˙˙<>˙†ƒ˙šš˙ÈÈ˙IK˙yy˙**˙XX˙ ˙ ˙|˙ee˙—“˙ce˙““˙y|Ž ˙^[˙BD˙rr˙Љ˙##˙!#˙SQ˙QQ˙›–˙•–˙˙20˙00ŭ˙ŒŒ˙ˆŒ˙WT˙==˙;=˙mk˙kk˙™™˙‚˙˙LJ˙JJ˙xx˙+)˙))˙……˙˙dd˙–’˙bd˙’’˙x{ù˙˙CC˙qq˙$"˙""˙RP˙PP˙–•˙˙]]˙‹˙‹‹˙‡‹˙ıı˙<<˙jj˙˙KI˙IIñ˙„„˙jm˙˙55˙ec˙cc˙î˙DBî˙žž˙ÌÌ˙!!˙!˙}}˙..˙\\˙ŠŠ˙ ˙=;˙;;˙ƒ€˙ii˙gi˙——˙˙FH˙¤¤˙ÒÒ˙''˙UU˙˙•š˙˙44˙|y˙`b˙ù˙˙˙ §˙[X˙UX˙˙ƒ†˙ËË˙ ˙ ˙NN˙||ĝö˙--ö˙[[˙‰‰˙ ˙8:˙hh˙––˙Ĵ­˙’–˙˙˙GG˙uu˙££˙ÑÑ˙&&˙TT˙˙{x˙aa˙_a˙˙@@˙˘œ˙nn˙TW˙œœ˙˙MM˙İİğ++˙ˆˆ˙ ˙99˙79˙ig˙gg˙••˙˙HF˙FF˙ttê˙mj˙QS˙˙22˙02˙b`ŭ˙``˙êê˙˙??˙››˙ ˙ßà˙,!ŝĠ.#§ĤD€‘„M"Éİ&Fhx ,ıĦ# ' mŒ Ô5‚•Á"€ĤÈòqÀá&$ĞŞPL Ú§‡82âTĉŸvÔB†kLBYz!RVGÄ*9sˆkd“šÍ-(óS… =hà*2Lċ^i&@\VĊFh…5“Ĥk*5y°Ĵ,=Ò6deÚ‹6KíĜ5ÔgA ‰5BÌĊ_i$ÔI²ÊŠñ”@£Y×3Ħ˜@ ù`Êż-'4}êVU<ĵrv“W[5’2Pi–­­bĜT£ ˘ uB+L¨Ì: 7hÄ/CD9 ŝŞbİbMÑ]QQâ2$VX.uWù]­€A2Ĥ½µÙu…zZDŽ˘ĈOpÁ  ˙>ž˙ˆÄ˙4™˙£Ñ˙È˙O¨˙ ˙j³˙;ž˙…Â˙VĞ˙Vİ˙€˙LĤ˙~ŭq¸˙˙]˙ …˙?Ÿ˙uğ˙šÏ˙šÍ˙!˙!Ž˙È˙Ĉ˙<˙†Á˙ĞĠ˙ †˙|˙|ĵ˙(“˙—Í˙—Ë˙²Ú˙^Ż˙^­˙ „˙/˜˙y˙yĵ˙e²˙‰˙€ż˙G£˙ĥÙ˙\_)”˙˜Ê˙ŽÇ˙Š˙„Â˙0—˙ŸÏ˙€˙˙˙f³˙fħ˙°×˙7œ˙ĤÔ˙˙Ëä˙RĞ˙Rİ˙mĥ˙·Ü˙˙ˆ˙£Î˙O§˙ñ˙;˙ŞĠ˙Ïç˙qı˙–Ë˙Ž˙ŒĈ˙]Ż˙§Ó˙§Ñ˙x˙xĵ˙Î˙$‘˙“Ë˙“É˙Œ˙? ˙Ú˙‰Ä˙Ĝ˙‰˙-+„Z­˙ZĞ˙‚˙uş˙|ù˙˙˙WĞ˙Wİ˙CĦ˙²×˙J¤˙”Ê˙e³˙ŠĊ˙ˆ˙€À˙,•˙vğ˙›Ï˙vı˙›Í˙G˘˙lĥ˙‘È˙ĥÜ˙bħ˙bŻ˙†˙}˙}ĵ˙Çâ˙Nİ˙N§˙i´˙i²˙‹˙Ĝì˙„Á˙,!ŝH° Áƒ*\Èc‘C2Ü\xR;((q ÄO 28$ˆ„C…84ÈÈÊ£‡ĵĵݤâ ; lìĝq„H’*fÀ!˘ċB/Ċx31‚E;hNp@#™Eá“èd–6@™ ˘ O 8ġÄNĞXµ²1 ‡eG•!1­€‹Q§Ví™5›,و#vÌ+^ü •ŞŸ œÊ²Ï˘0Œ]î}ƒĥÊ_œWĤvÄ<‚Ë™­,+0aQ#4YDkžfà–#\.R"ħœ2İÏ ËFDĞv²FßĴ‹œaÙA+Ä:êP)iЧŝûîɁ  *ôQ$&´²j Ay v̏ •W“!Á²L‰êAĴWv’ĵԄ $ñ‚#Yˆ!ˆx<‘Á’fü7E€ŠĊaĊDħĊ(0â„CˆQjħ$…&tqĦgwi$ñuàqÓùùÁÒ€¸`F‹Öċ ÈbÉĊĔ_€Ħ(K)$‘€äXeu°¤dmmÄÒTéCçYçYmb½„S5áÁeJ°”ÂQ Â"€}†–Ŝ5µÖ‰,­‘‚aŠÂ)^hMŽ<ġK0¤a r(•F"7JIä„ZlħdÈ‚~ewš™aš&£Ñž, °Ş)¨*&˘/fgÛ^nĦ›@mkìħÈ&ĞĴħ;hercules-3.07/html/images/loadoffu.gif000644 000765 000765 00000001355 11143760534 021452 0ustar00jmaynardjmaynard000000 000000 GIF87a%ĈĤ‚‚Ĥ—9­­­Ĥx”‹zĦĦĦŸŸŸşşŸžžĤPÉĥ[•z]”z\™™™4&,è­4‘‡§¨€v™š’ˆ|jr}r¨‰†¨}[Ĥƒ„œœ\F$İs””“œŠ1¤†¨u˜‡e|l’k¨~nĴ|^Ğz]İz[š~‹˜z^–z\ƒ\F”qPĦ{`žŸŸ§z\“{f}|nŞ}l˜pMŸˆWĞ{YŞĞĞ|fŒvDŒjDšš—˘žwžd^Dƒœœœœ‘wYtF,{\•’§‚›z\¸ş–ÁÂĥĞ€[ÒÓĴĴz\Ğz[D.$žŠ:›’beaX¨¨İz\žœ”z[Ĉ¸W§~qŞ}j…¤…|g˙˙˙ݍk£…fÀ=¤†I§€w•wXİݝˆƒvĞ{]İ h†|jݧuŞ{_Ĥƒ†œžŠ‚t‹ŒŒżżżÉĊv¤†”¨}cĞz\,%ŝ€‚ƒ„…†‡ˆ‰Š‹Œ‰Žp‚^p^“^‘^ ‘ƒ”‚p•—˜•¤Ÿ„¤p›——­¤¨£•°Ğš Ĵ^½° Ÿ›ĤŸ˜˘’ËÌ̓ÎÓÑÓÎÖĠÔĜÖŬO32M49/-ŜéÓMMMMc&MêŬ$ZrMrŭr\]²ÄpäŜ~MT`İ „Iœ4Ápœ3`0`à@™)¨ĜK÷><Şlä(äÁ2¤cwd!B 8 4.V˜)bC Vp"À‰3 $if6ÙÒĈ‚žL—šqPIGn”hëR)Cüĝ*bAS>–úäAŒ I²9BÀŸ‚ĵq`â=ZšĴAM‚=˘ÄŒÙÁ `–d€7ف"‡×…˜£Ħ x(†îöAƒ+;֞MğĥíĠ;hercules-3.07/html/images/loadonu.gif000644 000765 000765 00000000772 11143760534 021316 0ustar00jmaynardjmaynard000000 000000 GIF87a%Ĥ‚‚ŸŸŸ´ĥ”z\4&,üĉD§¨€vK65ˆ|jr}rĤƒ„\F$İsœz\¨u|lüŝÔüŝĴƒ\FĦ{`“{füŝ„}|nŞ}l˜pMĞ|fŒvDŒjDüâ4d^Düŝ¤tF,§‚üŝ|Ĵz\üŝTD.$üÖTüö,¨|üÂTŒŽüTŞ}jüÚ,…üĥ,˙˙˙<+/†|jİrù˙˙Ĥƒ†żżżšz\¤†”üŝ”üŞ$,%ŝÀ‚@,GaÉd*›¨t P(¨Dލád€@vËÈF-·íĵ[ġ8½àÂŬî\í.Şíq`gdr2iƒvgcalf8WX‘’“”TJ—˜™š›œžŸ—3  ˜'%   %%%%*5%ž.:%:ÀÀ'›'żż&&)% ›°+;Í;+´ş™' 1$!ÙÚ;$)왰#/;Ĝ6;!!9î %äÍ 1o‰h¸+#àÀ‚QĜ°%áğÇ1;#”àñp#  ŒğQ‚Ċ ĝ"ĥ “ Z,b¤˜gà ;vŽÑôí'"<‰óFSÚ4R ~zIŞŞĠФ‚;hercules-3.07/html/images/loadu.gif000644 000765 000765 00000002501 11143760534 020751 0ustar00jmaynardjmaynard000000 000000 GIF87a!ç˙K˙şÛ˙‹Ĉ˙7›˙ĤÑ˙H£˙m·˙Œ˙Üí˙> ˙>ž˙ˆÄ˙4™˙£Ñ˙È˙O¨˙ ˙j³˙;ž˙…Â˙VĞ˙Vİ˙€˙LĤ˙~ŭq¸˙˙]˙ …˙?Ÿ˙uğ˙šÏ˙šÍ˙!˙!Ž˙È˙Ĉ˙<˙†Á˙ĞĠ˙ †˙|˙|ĵ˙(“˙—Í˙—Ë˙²Ú˙^Ż˙^­˙ „˙/˜˙y˙yĵ˙e²˙‰˙€ż˙G£˙ĥÙ˙)”˙˜Ê˙ŽÇ˙Š˙„Â˙0—˙ŸÏ˙€˙˙˙f³˙fħ˙°×˙7œ˙ĤÔ˙˙Ëä˙RĞ˙Rİ˙mĥ˙·Ü˙˙ˆ˙£Î˙O§˙ñ˙;˙ŞĠ˙Ïç˙qı˙–Ë˙Ž˙ŒĈ˙]Ż˙§Ó˙§Ñ˙x˙xĵ˙Î˙$‘˙“Ë˙“É˙Œ˙? ˙Ú˙‰Ä˙Ĝ˙‰˙-+„Z­˙ZĞ˙‚˙uş˙|ù˙˙˙WĞ˙Wİ˙CĦ˙²×˙J¤˙”Ê˙e³˙ŠĊ˙ˆ˙€À˙,•˙vğ˙›Ï˙vı˙›Í˙G˘˙lĥ˙‘È˙ĥÜ˙bħ˙bŻ˙]`ż†˙}˙}ĵ˙Çâ˙Nİ˙N§˙i´˙i²˙‹˙Ĝì˙„Á˙,!ŝ@4Áˆ!m.8ĦrGG’8Ò§Ċ DÂĦ â DôäÑ C]ÜiÂPPV$R´8"F3Ŝ р¨ç†A& Ċp£0B:gNp@£â˜DüĜ“Èc€žˆülx2!ÏÁ6œ8pé ™NĦJ]Óñ V0 ~>ò#ĦX“.mJ3j¤5Uħ.²g넓C2tĝA)Ó><.1s+ŸE` —¤ë&,ĵ/­,yÄ3SħVX¢†ĉ‡³ÍàìÄ´[˘DÂ*eŸ™ {Ev,ˆ·K1ƒ•K 9V„ô³ Î Aë½M“VŝTà£(Œf^Ózò`Ĵ“C+™΁ŻA]’I&2@€Ä Ž`F ÛÍ4V=”Ÿú GzL…r ÀH ĈC˘q‡• šÀ„—Á•ĊT×M4r‡K È×VBüáB&>—ƒ"„ ‡QwċbX=Ž=ê·B\yĠ‘‹™%VJL‘cx€÷ÜemeRlDħtGY%U J(H‰ùñÑZ\Q^WY bF h) <ĉ÷cq!âW+9rÔXÁ€Ĉ_h MŝWG•Pc•…U!vì酒!Àù„br6Gv:`5À(ĦĤ0ꖁ˘(Ŭktµ1Çl=ħáëŻÀ+ì°ż"BìħÈ @²Ì+P@;hercules-3.07/html/images/manoffu.gif000644 000765 000765 00000001346 11143760534 021306 0ustar00jmaynardjmaynard000000 000000 GIF87a%ĈĤ‚‚Ĥ—9­­­Ĥx”‹zĦĦĦŸŸŸşşŸžžĤPÉĥ[•z]”z\™™™4&,è­4‘‡§¨€v™š’ˆ|jr}r¨‰†¨}[Ĥƒ„œœ\F$İs””“œŠ1¤†¨u˜‡e|l’k¨~nĴ|^Ğz]İz[š~‹˜z^–z\ƒ\F”qPĦ{`žŸŸ§z\“{f}|nŞ}l˜pMŸˆWĞ{YŞĞĞ|fŒvDŒjDšš—˘žwžd^Dƒœœœœ‘wYtF,{\•’§‚›z\¸ş–ÁÂĥĞ€[ÒÓĴĴz\Ğz[D.$žŠ:›’beaX¨¨İz\žœ”z[Ĉ¸W§~qŞ}j…¤…|g˙˙˙ݍk£…fÀ=¤†I§€w•wXİݝˆƒvĞ{]İ h†|jݧuŞ{_Ĥƒ†œžŠ‚t‹ŒŒżżżÉĊv¤†”¨}cĞz\,%ŝ€‚ƒ„…†‡ˆ‰Š‹ŒŽ^^p‘“‘^‡‘pŸ”p–‘’†p^•pœ‘—£Şž İ’İœ§…İ‚İ^£½²ĈÇȆÉÎÌÎËÉÑÏÓÑĜO32M49/-ÙäÎMMMMc&MċĜ$ZrMrĝr\]Y1OòžÜk˘K%Lâ0 ठyçäœ)€ʌHA%ı'ìÙàQĊâE!qà€Üı#€r`À!µ¸XAˆ M$X™‰`ĉÌ$t¤qÙdK# p-jĈA ıQ˘M-İE q#Јapĝ(Z‹1L0üÈĉSj!òĈ‡ò hi²J5 ôˆÂ’e‡€P€Y’a]c:ˆ6bކ",Öax¸Û ì([şµë×°K;hercules-3.07/html/images/manonu.gif000644 000765 000765 00000000760 11143760534 021147 0ustar00jmaynardjmaynard000000 000000 GIF87a%Ĥ‚‚ŸŸŸ´ĥ”z\4&,üĉD§¨€vK65ˆ|jr}rĤƒ„\F$İsœz\¨u|lüŝÔüŝĴƒ\FĦ{`“{füŝ„}|nŞ}l˜pMĞ|fŒvDŒjDüâ4d^Düŝ¤tF,§‚üŝ|Ĵz\üŝTD.$üÖTüö,¨|üÂTŒŽüTŞ}jüÚ,…üĥ,˙˙˙<+/†|jİrù˙˙Ĥƒ†żżżšz\¤†”üŝ”üŞ$,%ŝ@€pH,È¤rÉl:›™ ˘Ó¨@!;Fq_*ΕvœĴŠFŻcµ,H—iîı˜Ĥec}rO†‡ˆF‹ŒŽ‘’“”•–”3 —'% – %%%%*5%”.:%:··µ'‘'ĥĥ&&)µ% ‘§µ+;Ä;+Ğħ' µ1$!Ñ;$)§#/;Ï6;!!9ċ %éê!êê$%4ʕ€Oż}(lXpÀˆÎŜı›cˆ†J0(EE½Ŭ(Áb†w[H&ÉĊ*1R¨3bÜ8VÖBf“@”²U[™LÙ%6=\ÜÄ´İÓIA;hercules-3.07/html/images/note.gif000644 000765 000765 00000000364 11143760534 020617 0ustar00jmaynardjmaynard000000 000000 GIF89a ò€€€€€€€ÀÀÀ˙˙˙˙˙˙˙!ù, ıHşÜşIƒÊmŝ[×Ĉ§‰Œ” FÛ ! …Ş\ ş}Ĝ›ĴG¤3‘ŻXƒ•`0ÙrIrjN#ĤŻ ƒ ³Sâċ™)Ċ(3mçzu+éÖ¤’7ġ4ħîzzv…€r‚†‡)‰Œ’Ž)‚‘~”y–=™<›Ħ1œĦ”qĤ‚£§˘g;Ğr­´Lžާwħh –ŸÀa|x2Â34Ÿ:ÁĊÒÇA" ;hercules-3.07/html/images/osi-certified-60x50.jpg000644 000765 000765 00000016616 11143760534 023202 0ustar00jmaynardjmaynard000000 000000 ˙Ĝ˙àJFIFHH˙íPhotoshop 3.08BIMíHH8BIM x8BIMó8BIM 8BIM' 8BIMġH/fflff/ffĦ™š2Z5-8BIMĝp˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙è˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙è˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙è˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙è8BIM@@8BIM8BIM p<2´#(T˙Ĝ˙àJFIFHH˙ŝ&File written by Adobe Photoshop¨ 5.2˙îAdobed€˙ۄ            ˙À2<"˙Ŭ˙Ä?   3!1AQa"q2‘ĦħB#$RÁb34r‚ÑC%’Sáñcs5˘²ƒ&D“TdE£t6ÒUâeò³„ÓuóF'”¤…´•ÄÔäôµĊĠċġVfv†–ĤĥĈÖĉö7GWgw‡—§·Ç×ç÷5!1AQaq"2‘ĦħB#ÁRÑ3$bár‚’CScs4ñ%˘²ƒ&5ÂÒD“T£dEU6teâò³„ÓuóF”¤…´•ÄÔäôµĊĠċġVfv†–ĤĥĈÖĉö'7GWgw‡—§·Ç˙Ú ?ġT’CÈĴl{2.;jŽħçÁ­œ’u݁Ó(ġóm0èјvşÛï{żŞıû~ż‡~ƒëûÏsÌÜġËfçäu<·gċÒYüÛ;W_ĉRÏŭûö n’CCžZ%Û]ù{ĥ޳ĉ$M@9Ù9ٙˆh:×/}Ó~¸ôœë[E›ïy†2\u—0ş­Ëuy'²Ĉv{> …Ú}KëċSgMÊy²ìPMŽĠΤûFóùÏŜÏûm?~3!E›–ĉŭÁ1Ré]^$’Sĥß˙ġUġğwüÛÏÛϧĴ~îĉï˙ ĥò(Ğ'Ì{†êc˜ñâ× @‹"BÁĊ>UŬwżS~Éûìñêkö˜ú^´ŝ—ĠŝWŝ‹\FvGLËvP;ÙüĠĴŻó-gŝŭËGġ'²Ü<ìğA ̜fĈ“[eŝĠ{?ëjŻ. r‘ÑÎäÄĦšP1Öµ§ŭ“öĉoĜĥúÛ;>İ´}£oöŝŸü&ġsên˙ùÀÍĵ}žŬ˙ ĠGŭ5‹e' ÖâŬ v#ŬSÏĜ`;ŝ¸ßzë>İâ×ÓfwQ˘ìĥP{H  81£ż2˵Ù˙†0e˜Êމ´aŒ§Ì™× &^\’ӑSnĦÁġşv¸p`íDW7˙ÑïşÇÖ|“Ü[jÈÉÈ5‡Ġ‹QµÌ§k².Û*ÜĞßġÓ¤1ìġäçV)Ż&Ûq)u­ŞĞ}_ĉïc\ŭkì@ë}/³­?ĞtЍÊûVĜ-Şû [{îŻ!k-ġúo}k/ê_X£—ecâUWV§&Ü[Ğħ‚eġT×3.†8îĤ´”ġ?˘ŭ`³/ĤŬQ¸à:żT½…ĥĥäTúlöĜ×zOVÓ°°ħñħl`ÇdWIŜáIcœħ*úğԇüáXÇ;޲†Ñd‘ıĠ3×\֏Ñú·1ßGóó~Żċĉ[]£Ĵj^Ë)~-6ħ›KÍ_­>ÏcZŭµmŭéŭ•~“ŭĦş(]Ö½Ŭ;úoĠÖġ†çdúG>òS,x2ö4ûŞĦÇg­ħŸOj/í<œ–c[-yc ÌimBß}uŜ\˙ìŬĥŻUPŻêëİ·7›2)Ïż&×ÜêîvK+wŞĉıŜ,ÉŞŬŸJ“>İg6†µ•y˜ŒuÍ&GĦŽük]1ŝ”³bT ŜĤğ1TÔêÛSIÒC§èéíŬıö/ìŻÚŜï²ú?iŬ³oĞô?{jçq~­fRÚ-v%o58 q-µÀ*v;/hŻş˜úœ˙Ï­öÙWòÖŻìœŻùûÙöŸ°ŭ—“³§èŭ(ŬéîI/˙ÒġT—Êİ$§ê¤—Êİ$§ê¤—Êİ$§ê¤—Êİ$§˙Ù8BIM˙â XICC_PROFILE HLinomntrRGB XYZ Î 1acspMSFTIEC sRGBöÖÓ-HP cprtP3desc„lwtptbkptrXYZgXYZ,bXYZ@dmndTpdmddĈvuedL†viewÔ$lumiĝmeas $tech0 rTRC< gTRC< bTRC< textCopyright (c) 1998 Hewlett-Packard CompanydescsRGB IEC61966-2.1sRGB IEC61966-2.1XYZ óQÌXYZ XYZ o˘8ġXYZ b™·…ÚXYZ $ „ĥÏdescIEC http://www.iec.chIEC http://www.iec.chdesc.IEC 61966-2.1 Default RGB colour space - sRGB.IEC 61966-2.1 Default RGB colour space - sRGBdesc,Reference Viewing Condition in IEC61966-2.1,Reference Viewing Condition in IEC61966-2.1view¤ŝ_.ÏíÌ \žXYZ L VPWçmeassig CRT curv #(-27;@EJOTY^chmrw|†‹•šŸ¤İ²·ĵÁĈËĠÛàċëöû %+28>ELRY`gnu|ƒ‹’šĦİħıÁÉÑÙáéòú &/8AKT]gqz„Ž˜˘ĴĥÁËĠàëġ !-8COZfr~Š–˘şÇÓàìù -;HUcq~Œš¨ĥÄÓáŝ +:IXgw†–ĤµĊĠċö'7HYj{ŒŻÀÑġ+=Oat†™ĴżÒċĝ 2FZn‚–ŞÒçû  % : O d y  ¤ ş Ï ċ û  ' = T j  ˜ Ċ Ü ó " 9 Q i € ˜ ° È á ù  * C \ u Ž § À Ù ó & @ Z t Ž İ Ŝ ĝ.Id›ĥÒî %A^z–³Ïì &Ca~›ı×ġ1OmŒŞÉè&Ed„£#Ccƒ¤Ċċ'Ij‹­Î4Vx›½à&Il²ÖúAe‰Ò÷@eŠŻĠú Ek‘·Ŭ*QwžĊì;cвÚ*R{£ÌġGp™ì@j”é>i”żê  A l ˜ Ä !!H!u!Ħ!Î!û"'"U"‚"Ż"Ŭ# #8#f#”#Â#$$M$|$Ğ$Ú% %8%h%—%Ç%÷&'&W&‡&·&è''I'z'Ğ'Ü( (?(q(˘(Ô))8)k))**5*h*›*Ï++6+i++Ñ,,9,n,˘,×- -A-v-Ğ-á..L.‚.·.î/$/Z/‘/Ç/ŝ050l0¤0Û11J1‚1ş1ò2*2c2›2Ô3 3F33¸3ñ4+4e4ž4Ĝ55M5‡5Â5ŭ676r66é7$7`7œ7×88P8Œ8È99B99ĵ9ù:6:t:²:ï;-;k;Ş;è<' >`> >à?!?a?˘?â@#@d@Ĥ@çA)AjAĴAîB0BrBµB÷C:C}CÀDDGDŠDÎEEUEšEŜF"FgFĞFG5G{GÀHHKH‘H×IIcIİIJ7J}JÄK KSKšKâL*LrLşMMJM“MÜN%NnN·OOIO“OŬP'PqPğQQPQ›QĉR1R|RÇSS_SŞSöTBTTÛU(UuUÂVV\VİV÷WDW’WàX/X}XËYYiY¸ZZVZĤZġ[E[•[ċ\5\†\Ö]']x]É^^l^½__a_³``W`Ş`üaOa˘aġbIbœbcCc—cëd@d”dée=e’eçf=f’fèg=g“géh?h–hìiCišiñjHjŸj÷kOk§k˙lWlŻmm`mınnknÄooxoÑp+p†pàq:q•qrKrĤss]s¸ttptÌu(u…uáv>v›vĝwVw³xxnxÌy*y‰yçzFz{{c{Â|!||á}A}Ħ~~b~Â#„ċ€G€¨ kÍ‚0‚’‚ôƒWƒş„„€„…G…І†r†×‡;‡ŸˆˆiˆÎ‰3‰™‰ŝŠdŠÊ‹0‹–‹üŒcŒÊ1˜˙ŽfŽÎ6žnÖ‘?‘¨’’z’“M“ĥ” ”Š”ô•_•É–4–Ÿ— —u—à˜L˜¸™$™™üšhšĠ›B›Żœœ‰œ÷dÒž@žŸŸ‹Ÿú i ĜĦGĦĥ˘&˘–££v£ĉ¤V¤Ç8İĤĤ‹Ĥŭ§n§à¨R¨Äİ7İİŞޏĞĞuĞéĴ\Ĵ­D­¸-ĦŻŻ‹°°u°êħ`ħÖ²K²Â³8³´%´œµµŠĥĥyĥ·h·à¸Y¸ÑıJıÂş;şµğ.ğ§ĵ!ĵ›½½ „˙żzżġÀpÀìÁgÁÂ_ÂÛXÔÄQÄÎĊKĊÈĈFĈÇAÇżÈ=ÈĵÉ:ÉıÊ8Ê·Ë6ËĥÌ5̵Í5͵Î6ÎĥÏ7ϸ9şÑ<ÑÒ?ÒÁÓDÓĈÔIÔËĠNĠÑÖUÖĜ×\×àĜdĜèÙlÙñÚvÚûۀÜ܊ŬŬ–ŜŜ˘ß)߯à6à½áDáÌâSâÛcëäsäüċ„ĉ ĉ–ççİè2èĵéFéê[êċëpëûì†ííœî(î´ï@ïÌXċñrñ˙òŒóó§ô4ôÂġPġŜömöû÷Šĝĝ¨ù8ùÇúWúçûwüü˜ŭ)ŭşŝKŝÜ˙m˙˙˙ŝ&File written by Adobe Photoshop¨ 5.2˙îAdobed@˙ۄ       ˙À2<˙Ŭ˙Ģ  s!1AQa"q2‘ĦħB#ÁRÑá3b$r‚ñ%C4S’˘²csÂ5D'“£³6TdtÒâ&ƒ „”EF¤´VÓU(òóÄÔäôeu…•µĊĠċġfv†–ĤĥĈÖĉö7GWgw‡—§·Ç×ç÷8HXhxˆ˜¨¸ÈĜèĝ)9IYiy‰™İıÉÙéù*:JZjzŠšŞşÊÚêúm!1AQa"q‘2ĦħÁÑá#BRbrñ3$4C‚’S%˘c²ÂsÒ5âDƒT“ &6E'dtU7ò£³()Ó󄔤´ÄÔäôeu…•µĊĠċġFVfv†–ĤĥĈÖĉöGWgw‡—§·Ç×ç÷8HXhxˆ˜¨¸ÈĜèĝ9IYiy‰™İıÉÙéù*:JZjzŠšŞşÊÚêú˙Ú ?÷ö*ìU óo|ħäm4jžgÔ#ħĥsÂ5y§’•á H ğ{*œŻ&HÀ\ĴıaŒqHxŭçüċ6’³ùSRşµi&µ´b nî¤ŝX Bì~ယ‚@_ yÌú·žuéüÛŻ1úíĠE•İ5K+2kĵc  Ħ‘†ï%Iíœ.³U,ó'§GÎuÚÉj2rJ„ÊÏ$q$³ĵ u·†Yŭ%;ƒ'¤­À­LĈ†Ì\A..<&.1$4E­ġµ ‹I—Ù‘”ċ{Ä÷½â{ˆ}9˙8éùƒX^ù']¸{­OCŽ9ôëɘ´³é²Š$cğ<,8?i2~.YÙvn¨ĉ…aîû+Xsİ}Q{žmÓħW˙Ñ÷ö*óŻÏŸ[ŝU›= òú˜ġ8ġô½Tġ?á9W1µWáJğœMeĝ2çÇgİ=ĵ3ϟ2}m˙8òtùY£Óúà~œ O[ôŸ3ëúÔߕ~Ï/÷_?ï´|>xySéZ<İó‡ĉiOĉ_š–}/ÑX‹™·§ĦġïE~·Â›}ż·O÷oİœÇjpĝŜžíŜCĥ8<Ovì“ŝqï×˙•ŻoèW‡è›˙ĴÓ§§êÛqŻû>9‘Ĝ×âKÜċv ĝ²÷>έìŬŠż˙Ò÷ö*ƒĠ´Ë=oK½Ñµŭ[ B mn£ŝh§BŽ>€‹‚_ ù“Êú·‘uéüĞ}nÚĤÂìŠ%ġ˜4ŽxÏBiA*ÒJ˙“œ.³K,=Ŭ:×èċ§ÈGžOk˙œpòT†ĉż1jËmĉ"Ú$< Bö–ŠñË "›´’:ê=<è{+?Äôŭƒ‡Ÿâûžu§ż•ċµ2°Í Ï.ŸtĈˆ•ĥn*ÚEâǖsZœ&L|ŜOU‚XóJmôäV‹mäh.üÙç%—LĠ5ëhÚĈ;ˆVÛJŽe ­J$“K*³#nİérŭŞuŸ§!êĉ^ż³4ߗÇrú¤÷ŭ3T°ÖlbÔ´ÉÖĉĈ~^”é^-ÁŠVÁͰ îĜ ‹ĵ)˙ÓġÇĉçO•ż/5ht ë[ZÖŜÊM^ĉAħ}Bk]2ôÚîà)P‘rFċ˜İâ§Ju?ùÈÏ!ÚʃF²ÖĵÑfşužµ¨_ùM—P·ħÓġ5i-ı*U—š#?W*’Ê1Tâêçòçó~ëÌ^JÔìZŝ_*Ëf/žâ7·h%Ômò-ĉdFôyÁ”ü-•äÇА°Ġ“r ‹ÊöŜSòż–ô@ğ·MĥZk}a%ġdĠD…İ#5K~ÑjäĦäBƒĠ<ŸùIŸàó^·ġ'óžĞ$péö÷—*ÂKĞXš ³·0Hŝß_ÔÊüqñÖí_—ĈgÇ^¤ÀùğËúĉħo˘ÉĦ]ŜŜ=½Ğß´ĥ4V+¨,Q\³Ëö§É–/W·U­¤Ŝ@,žÎëBµħ/§Ík0Ä7#ö|q” KĈúĝŝVf˙ŝŒŭ5_Lú˙Tô}îë^\gÇ _˙ÔôoĉO’?3m˙1îż0.tŭ/[ŭ7ċ•ŭ†İ{&œm;™!ğGHf ġĜIÀßâĜĞÍ5ßùÇ_Ì /H4O)èúlŜaÒĵ½§èşĉ&Ÿê>^ÔìŻmPĞËséw1ċ dsâ87\UéV”~qOù\Kw{m-ǞíôÈtĞÒì†il´Xl'{…EŭĜ–hÚĦyü ŝÇ@yòĞ]ó%íòùJËGÒ§ĥĵÓô6ŝÖĜÄ×R[´żQ‘UÊBT´ ë§xÉıޞÚ~RKĤSIÓnġ½;Íz·¨M OĴOeİ˨Gúï1’ğŠ^jĊÁX7ĊX½Żä?™ ÒâŠİYëMoċÛiµ(¤oQN“¤Ie; ñ••“ù€ŻŠŞè“`ÓĦÒµ |ğgq-„ñ˙—ïµe³ğXô÷³Žé ˘G‰¤˙†ƒ˙šš˙IK˙yy˙‘˙**˙XX˙ ˙ââ˙ ˙|˙—“˙ce˙y|˙ÁÁŽ ˙^[˙DD˙BD˙rr˙X[˙ˆ‰˙ÎÎ˙##˙SQ˙QQ˙›–˙•–˙˙20˙00ŭ˙FG˙˘£˙ˆŒ˙èè˙WT˙==˙;=˙kk˙‚˙˙LJ˙JJ˙xx˙+)˙))˙WW˙˙dd˙–’˙’’˙x{˙Şİù˙˙CC˙[Z˙qq˙ÍÍ˙$"˙""˙RP˙PP˙ĴĴ˙˙]]˙‹˙‹‹˙‰‹˙‡‹˙çç˙<<˙jj˙˙KI˙II˙ñ˙„„˙jm˙˙55˙ec˙cc˙żż˙î˙DBî˙´µ˙ÌÌ˙!!˙!˙}}˙ĞĞ˙..˙\\˙¸¸˙ĉĉ˙ ˙=;˙;;˙ƒ€˙gi˙ĊĊ˙˙FH˙ÒÒ˙''˙UU˙˙•š˙˙44˙|y˙bb˙`b˙ù˙˙˙˙ §˙[X˙UX˙˙ƒ†˙µ´˙ ˙ ˙NN˙||ĝö˙--ö˙[[˙‰‰˙··˙ċċ˙ ˙8:˙hh˙––˙’–˙ÄÄ˙˙˙GG˙uu˙££˙ÑÑ˙˙˙˙&&˙TT˙RT˙°°˙˙{x˙aa˙_a˙˙½½˙@@˙˘œ˙nn˙TW˙ÊÊ˙˙MMğ++˙ˆˆ˙ää˙ ˙99˙79˙ig˙gg˙˙HF˙FF˙tt˙˘˘ê˙˙mj˙QS˙˙—˜˙22˙b`ŭ˙``˙˙A?˙??˙ƒ„˙››˙ÉÉ˙ ˙,!ŝH° Áƒ*\ˆ,H„cHdU ÇAÁ# ¤D(ÊcîLƒ9ß!h’ƒÇ”RèTˆl‡GU &$ÁERJneéȀÊ7U&•¤Tj–~v Ä`˜=ÚÖGÄ­S³œžHċ˙ÔÂ(¨Ha‹Úóˆ2żô`ÈVĜġK*7Ì5ĴÀqY AÔÊf3WFŠdáÉ\˘KĦD1 Ž×‹#CMĴ0N8•àÈrqäĜ%,eŠ ÓÀxÍ3)H’T"XCFU"Ĉ[  “1FÄÂ'œÀˋ1Ĉá‹Àèâƒ5h ‚…aĞ<—UtÁ’lqBbhY 5J VaeàÖGNyRcp’ÍcÂH„3N89ÛCmÖLÍİK“„‘ „„™ŝĊF#.L}ÀT“ÊĊ“€Q@F"Ùß3qÌXǤ!ÍLeÄİ)°ÔŠ+ż„q ˜Ħ@‚*ŻgŽ ‰ i•œ¤°äÁ ̆ñƒ£bZH\“g1•ĈSC|ĥ K›x Ħ6:Á.‚gŻ’|1mĠΈħ„‰0ò>ê¨ÙœP!xm h"lg‚4# wìñÇ ‡Üħ@;hercules-3.07/html/images/poweroffu.gif000644 000765 000765 00000002656 11143760534 021674 0ustar00jmaynardjmaynard000000 000000 GIF87a!ç˙zz˙ż˙)+˙YY˙‹‡˙‡‡˙˙ ˙:8˙88˙68˙˙ġ˙‰Š˙ĦĦ˙RR˙PR˙€€˙31˙11˙a_˙__˙ò˙˙˙<>˙†ƒ˙šš˙IK˙yy˙‘˙**˙XX˙ ˙ââ˙ ˙|˙—“˙ce˙y|˙ÁÁŽ ˙^[˙DD˙BD˙rr˙X[˙ˆ‰˙ÎÎ˙##˙SQ˙QQ˙›–˙•–˙˙20˙00ŭ˙FG˙˘£˙ˆŒ˙èè˙WT˙==˙;=˙kk˙‚˙˙LJ˙JJ˙xx˙+)˙))˙WW˙˙dd˙–’˙’’˙x{˙Şİù˙˙CC˙[Z˙qq˙ÍÍ˙$"˙""˙RP˙PP˙ĴĴ˙˙]]˙‹˙‹‹˙‰‹˙‡‹˙çç˙<<˙jj˙˙KI˙II˙ñ˙„„˙jm˙˙55˙ec˙cc˙żż˙î˙DBî˙´µ˙ÌÌ˙!!˙!˙}}˙ĞĞ˙..˙\\˙¸¸˙ĉĉ˙ ˙=;˙;;˙ƒ€˙gi˙ĊĊ˙˙FH˙ÒÒ˙''˙UU˙˙•š˙˙44˙|y˙bb˙`b˙ù˙˙˙˙ §˙[X˙UX˙˙ƒ†˙µ´˙ ˙ ˙NN˙||ĝö˙--ö˙[[˙‰‰˙··˙ċċ˙ ˙8:˙hh˙––˙’–˙ÄÄ˙˙˙GG˙uu˙££˙ÑÑ˙˙˙˙&&˙TT˙RT˙°°˙˙{x˙aa˙_a˙˙½½˙@@˙˘œ˙nn˙TW˙ÊÊ˙˙MMğ++˙ˆˆ˙ää˙ ˙99˙79˙ig˙gg˙˙HF˙FF˙tt˙˘˘ê˙˙mj˙QS˙˙—˜˙22˙b`ŭ˙``˙˙A?˙??˙ƒ„˙››˙ÉÉ˙ ˙,!ŝ@$Â1$²Ş„ àR"ċ1wĤÁœo4ÉÁcJİ tŞ D6—Á#ˆŞ’À!)%·²Pd@ċ›*Ž8R*µĈ²Ÿ~v MÂ`˜=ÚÖGÄ­ '/ Pp‘´ċOia  xogĀXü@FHĦ°A ïU÷À ‹ÁÈ îĥÈ1üH 0ñ |,Ħşá†Ž Q¤qA`E+1 DüႠ?H *ìaàCi˘Ä@ŠH!Ĉˆ A4Òk+ìQnlÀD”(ÈiT`Á|taBŽ$ˆ /PPF„9 ‚p\hçi1‚F ÂäĝÑB ÁšB´QçİÁ@Á£.P‡ iP*ˆ j¨Žc< lt ȝ§½0ALBŽVHܸǠŒ1B€- gĝê›À–aĈİjĈħoÖŞ„”t0È€TpĈ eèh-kÖFAĥĜJ F1Ç;àÀÚĤĞBĥ’QĞ­ŠÑH ħN:Á;F­ž*dĠèô€dJIB ;èp!= ïÀ ܕPÀŭÖk ‘dTÄĈN„ˆPĦT€<Çrx ²Dу"P@GOÔüD‰œpH"4Û@1+ÒC(ĞìËs€LòÈ ç ÀÇ!\²'§ĵrË/Ç<³Í7; @@;hercules-3.07/html/images/poweronond.gif000644 000765 000765 00000002734 11143760534 022047 0ustar00jmaynardjmaynard000000 000000 GIF87a!çÑÒÍÒÌddbşş³VVT°°İݍ§ĴĴ~{×ĠÏFFDßßÚİŞŜŬÙŬŬĜrqoŬÛĜqqnÜÛ×ÛÛÖÚÛĠÛÙÖÚÙĠ987ÙÙÔĜÙÓĜ×Ó××ÒÖĠÑĠĠÔÓÏÓÓÎÒÓÍÑÓÌÏÑÊÎÑÉŬŬÛÛÛÙşı²ÇÇÂĥµµ³­´³Ĵ°Ż¨ŻŻ§­Ĥ­­½½¸ĵğ·ıı´ÜÜÖÜÚÖÛÚĠÙĜÓĜĜÒĜÖÒ×ÖÑÖÖÖÔĠÔÏÔÔÎÓÔÍÔÒÎÓÒÍßŜÜŜŜÛŬÜÚÜÜÙı¸°ÙÚÖÉÈĜÚĠ·ĥ·´ĥ´­¨ÚÙÓÙÙÒÙ×ÒĜ×ÑĠĠÎÖÓÏĠÓÎáßŬàßÜŜŬÚŬŬÙÜÛĜÛÛ×ÙÙĠÑÓÍccabc``a^°ŻİUUS­­ĤııµÚĜÒĜĜHGFĜÖGGEÔÒÌààÛÎĈàŜÛßŜÚŜŜÙŜÜÙrroŬÜĜÜÜ×ÛÚÖÚÚĠ997ÙÚÔÙĜÔĜĜÓ×ÖÒÖÖÑĠÔÔÔÏÓÔ͚ÒÒ͝›™ÑÒÌŜŜÜÜÜÚÖĜÔµ´­ħ°İ°°¨Ż§ĴĴ¤ĵĵ·{ŜŬĜrqnqqmÜÛÖÚÙÔĜ×Ò××ÑÖĠĠĠÏĠÓÏÔÓÎÓÓÍÒÓÌÑÑËŜŬÛÛÛĜÙÙÖ¸·ŻĜÙĠĜ×Ġ·µĠÙÒğğµıı³ı·³­­§ÚÚÓÙĜÒĜÖÑ×ÖÖÖÏÖÔÏÔÔÍÔÒÍáàŬàŜÜŜŜÚŬÜÙÜÜĜÛÚ׺¸°ÚÚÖnpl998ÙÚĠÚĜÖ897ĜĜÔ×ĜÓ,!ŝıH° Áƒ*\(ħOşĥàÁcÁrÜhtĦˆ‘-X°²2ĞdICM}Ú"qâ .Êq@“£–›ĥl‰¤uä”\LēáŽQ;ĉ@‚P+Žœ‹ĥêÔÉžžˆLA‰R†ŻFïT¨`+ F,¤JµuKœ·!m ̅ĉ‰WJxî°ÜbĦ†²j'Ĝù”ÂÛ8X²ÈċrdM8ĵf˜ĜE”’-(´ÔıUá‚^–4C]ЁĞV)áàEJ)DîĜ şŠÒ(JHpU¸UħYK‚’)ÓM€~´İ€N%ŠuiǎJ8ĈB`+ÔL=2ŝù`óE/ށY $j ̨T :ğ/Ŝ£Œš3ĵìÀ l䁉*IìH~ÄŭqIÒG r‰‘ Â ‚ôÑ+½LRDŽ\0A,UÀb%â…&ĵQ\°\R&<F0|Ĝ0É 06QĊ“5^˘É À.a’IyÀ"DSĵbI{PrKvĂ,m(Đ!ˆ@Â/ƒh <D èÇc”Ü1‘@‰ '\qÇ%7Ĉ’‚gtÓUwŬj{ ÊEĦ߅çœò&›2B œ¤ôu°şÔ—‡ò÷†ìÇĤ?` €‰uŞnĦßYˆá†ÈöáÇĴìàn¨Ş.Zl! ™„G*và­·{|ğÇ|xÀG¸äò‘.,Ŭ") ̸ôÖ;ÑpàünÁM·a„@BŬË/Ğê2ÑWxè1[|˘UX 1„@޲…Âŭâñ‰-v°ÔD |´ŒdĊÊ9ád4˘@#Ä Œĵ°ÈÎ/0‚@* p€ b ÈÑb8!P@;hercules-3.07/html/images/powerononu.gif000644 000765 000765 00000003033 11143760534 022061 0ustar00jmaynardjmaynard000000 000000 GIF87a!çÑÒÍÒÌddbşş³VVT°°İݍ§ĴĴ~{×ĠÏFFDßßÚİŞŜŬÙŬŬĜrqoŬÛĜqqnÜÛ×ÛÛÖÚÛĠÛÙÖÚÙĠ987ÙÙÔĜÙÓĜ×Ó××ÒÖĠÑĠĠÔÓÏÓÓÎÒÓÍÑÓÌÏÑÊÎÑÉŬŬÛÛÛÙşı²ÇÇÂĥµµ³­´³Ĵ°Ż¨ŻŻ§­Ĥ­­½½¸ĵğ·ıı´ÜÜÖÜÚÖÛÚĠÙĜÓĜĜÒĜÖÒ×ÖÑÖÖÖÔĠÔÏÔÔÎÓÔÍÔÒÎÓÒÍßŜÜŜŜÛŬÜÚÜÜÙı¸°ÙÚÖÉÈĜÚĠ·ĥ·´ĥ´­ĴĴ£¨ÚÙÓÙÙÒÙ×ÒĜ×ÑĠĠÎÖÓÏĠÓÎáßŬàßÜŜŬÚŬŬÙÜÛĜÛÛ×ÙÙĠÑÓÍccabc``a^°ŻİUUS­­ĤııµÚĜÒĜĜHGFĜÖGGEÔÒÌààÛÎĈàŜÛßŜÚŜŜÙŜÜÙrroŬÜĜÜÜ×ÛÚÖÚÚĠ997ÙÚÔÙĜÔĜĜÓ×ÖÒÖÖÑĠÔÔÔÏÓÔ͚ÒÒ͝›™ÑÒÌŜŜÜÜÜÚÖĜÔµ´­ħ°İ°°¨Ż§ĵĵ·{ŜŬĜrqnqqmÜÛÖÚÙÔĜ×Ò××ÑÖĠĠĠÏĠÓÏÔÓÎÓÓÍÒÓÌÑÑËŜŬÛÛÛĜÙÙÖ¸·ŻĜÙĠĜ×Ġ·µĠÙÒ@E9ğğµıı³ı·³­­§ÚÚÓÙĜÒĜÖÑ×ÖÖÖÏÖÔÏÔÔÍÔÒÍáàŬàŜÜŜŜÚŬÜÙÜÜĜÛÚ׺¸°ÚÚÖnpl998ÙÚĠÚĜÖ897ĜĜÔ×ĜÓ,!ŝ“q“']\àħ`9n":€PÄ—,Yh]™Ċ‘£!`Lyâ’Pá ÊqÀr▗ĥle¤……C2Pˆ'Ÿv*ÌyĦV9mĠİ#84;1u*Ċ¤I²ŝĵSĦ‚--³@XşÔ–,qÒb´E`E.4P°NÂs‡$ 5ì|%;ÁާħÒĈɢĊVŠDGÖHÁk…]B)á‚bK[.Ô%YÁrR[ıZ€bàŞI8ĝD™B ‘Ż;6zš$j\nĠ öH˘%A‚Á„éG&@?ÒTH§ Ċ²´c%]!˜•h”pL=0ŝù`óE/ށY A$j Ì D :—°œ8ĝ2jœÁËĵ°ÁF—¨B °‘Äp€ÁRŒÒ˜üaIÒG b‰ Â ‚ôÑ+½HRG…L0Q,VÀ˘£%â…&ĵA\°XBÜ%<†0|Ĝ É ZhĊ”9Z’É À.a‚IyÀ"DTĵRI{LrIv01 ²´£G†  ż ˘&0e=€ C‹Mr‡B&"\Ċ÷_DRHŸIGuİíĦ K(ú]x>€ * \˘I #²  `J_ŝàĦK" ´0&£à}Àá;ôê—€<\RĴ „˜§iÈá‡öá‡ìàĜ~Ğ.[pÑB.+`Â=¸ĜÁıçîî{áêĥËG¸tK")œòI0Á°ëïż m°lĵt‹FĴ OóĞ. e…‡<áÁ…'[4•ĊCœbJ#‡pAñÁxxb‹$]ĴĊ Ÿ0-]a32˙šš˙KK˙IK˙yyï˙**˙(*˙XX˙ ˙ ˙77˙|˙ee˙ce˙““˙y|˙“Ž ˙^[î˙BD˙rr˙##˙!#˙SQ˙QQ˙˙˙20ŭ˙00ŭ˙ru˙ ˙WT˙==˙;=˙kk˙˙LJ˙JJ˙xxú˙))˙˙˙fd˙dd˙–’˙’’˙x{÷˙˙CC˙qq˙$"˙""˙RP˙PP˙]]˙‹˙‹‹˙‡‹˙><˙<<˙jj˙˙KI˙II˙*(˙„„˙jm˙–›˙˙55˙ec˙cc˙˙DB˙\Y˙BB˙@B˙#!˙!!˙}}˙..˙\\ë˙ ˙=;˙;;˙ƒ€˙gi˙“—˙˙FH˙\_˙''˙UU˙ƒƒ˙˙˙44˙|y˙`b˙ùù˙˙˙ §˙ƒ†˙ ˙ ˙NN˙||˙--˙‰‰˙ ˙ ˙8:˙hh˙––˙|˙GGġ˙uu˙[^˙&&˙TT˙˙˙13˙“˙_a˙‹˙˙B@˙@@˙˘œ˙nn˙TW˙œœ˙˙MMğ++˙tq˙Œˆ˙ˆˆ˙ ˙99˙79˙ig˙ggŝ˙˙HF˙FF˙tt˙mj˙˙b`˙``˙˙??˙ ,!ŝH° Áƒ*\ĜÊO VDöD1µ’ Âp˘ÒÈËDż$‘tc‡Ħ'@ÌĜŠ@ŞĴ†H4eqDpšħJȂDèÄ*c#‡‘L^°ĵâòa‡™\,b<ÂiÊ*=  `˜t “(YúÚDÀÇGDrÁ icˆŒô(H“aR‰$6lz/9üÀ”ԆfÜV ĉÊ/ğxwbIË/Ÿ>~ÉĜዐŜRaœC$Ÿ² RÉŻœh@ÌĊ†&bĦ9Éh„Uë¤X$°DĊZ‰/eаƒk˘ uRYċ(ŸXò Ŝú/ì‡Dšŝ›Ş#ґ>nxg%e—&WÄñ ¨:örñvd™™çí Ŝs=ĈÒšÄÀŬ„00‚C÷ħѲ˘$ôñc $ò K'ĴP *ğà‘}.YÁŠ3ċšhWÍĊ/—8Ħ‹cԂ!|‰rD`E­¸QO·°ô/px(wgXX*²y ³\ԟ…WħÉ"˙†ƒ˙šš˙IK˙yy˙**˙XX˙ ˙ ˙|˙—“˙ce˙y|Ž ˙^[˙BD˙rr˙X[˙##˙!#˙SQ˙QQ˙›–˙˙20˙00ŭ˙ˆŒ˙WT˙==˙;=˙kk˙‚˙˙LJ˙JJ˙xx˙+)˙))˙˙dd˙–’˙’’˙x{ù˙˙CC˙qq˙$"˙""˙RP˙PP˙˙]]˙‹˙‹‹˙‡‹˙<<˙jj˙˙KI˙IIñ˙„„˙jm˙˙55˙ec˙cc˙î˙DBî˙!!˙!˙}}˙..˙\\˙ ˙=;˙;;˙ƒ€˙gi˙˙FH˙''˙UU˙˙•š˙˙44˙|y˙`b˙ù˙˙˙ §˙[X˙UX˙˙ƒ†˙ ˙ ˙NN˙||ĝö˙--ö˙[[˙‰‰˙ ˙8:˙hh˙––˙’–˙˙˙GG˙uu˙&&˙TT˙˙{x˙aa˙_a˙˙@@˙˘œ˙nn˙TW˙˙MMğ++˙ˆˆ˙ ˙99˙79˙ig˙gg˙˙HF˙FF˙ttê˙mj˙QS˙˙22˙02˙b`ŭ˙``˙˙??˙ ˙,!ŝĜc&Œ†ÀŞpàƒ@Ôx‘%–Wc `ñ"ˆ [L Ü´á‘Ái†T’aÀa ŽŠPD äUĦn8Î4ËĤŸb`B)JÂJ<½QFƒ#/_lˆ˘c³“­ĉ(˜òs„ 1Thş1Jċ OW@tt"SE:Ĉp€„ġ Y"5y°l2Ò6Uc$‹6;íĜġPWA׈ĊAŠÄßW„ÙáÈŸÇt°’¤U×*‡z@ ù`Êż-4}ê6Ġ1rv½D#TIJĊ‘–CWV­-bx ˘Ùt%réÉ!Ĵ 7ˆ/7. ŝŞ)§bMÑ]Q§áòGHútWù]m5(b½µÙ5„úK§‚d&Ђ|¤¨XZâħ˘Ô1AW~ÑH ^'‰`˘‚ •axkMtX]âG`xJ( ÄÙ}Há×Y™@L™Ĝ°HWz4àA$f˜Ċ$‘1PÔk"Ħ–Sm)ÒTÔàA˙ĝĜ*I–JNÄL^dÒMè‘ DbH(=ÈȚAQ¤ÁE%N4ôdL]ÉÁ'T˜áGE²§‡…AeHéıVW?ÈħĨÈâzĦdħa‡Gh"E‚xŽĜ‚Ž]!’%L¤pš)’màĦ¤ô)VWĴp*0¨9ä½ĊQR5fŞt•Çm|àgš €a!uOd‡´†°ÌXWvXÂĴ~šŠŝQWĊŞqVŒ’ñÉO"Ôkï½ĝĉĞŻ½›ìëïż÷Àû ;hercules-3.07/html/images/restartd.gif000644 000765 000765 00000002516 11143760534 021503 0ustar00jmaynardjmaynard000000 000000 GIF87a!ç˙K˙şÛ˙‹Ĉ˙°Ö˙7›˙Á˙ĤÑ˙Ëċ˙H£˙m·˙Œ˙Üí˙> ˙>ž˙ˆÄ˙4™˙£Ñ˙O¨˙ ˙j³˙;ž˙…Â˙ŞÔ˙VĞ˙Vİ˙Ċ˙€˙~ŭq¸˙˙]˙ …˙?Ÿ˙×˙Óé˙uğ˙šÏ˙šÍ˙!˙!Ž˙È˙Ĉ˙µÚ˙<˙ĞĠ˙ †˙|˙|ĵ˙Ħ˙(“˙—Í˙—Ë˙Ĉ˙²Ú˙^Ż˙^­˙ „˙/˜˙y˙yĵ˙”É˙e²˙‰˙Ôê˙€ż˙G£˙ĥÙ˙\_)”˙˜Ê˙â˙ŽÇ˙Š˙„Â˙„À˙0—˙ŸÏ˙€˙•Ê˙˙˙f³˙fħ˙°×˙7œ˙ĤÔ˙˙RĞ˙Rİ˙wğ˙Áá˙mĥ˙˙ˆ˙£Î˙O§˙ñ˙;˙ŞĠ˙Ïç˙qı˙–Ë˙Ž˙ŒĈ˙Öê˙]Ż˙]­˙§Ó˙§Ñ˙Ìċ˙x˙xĵ˙Î˙$‘˙“Ë˙“É˙¸Û˙Œ˙? ˙Ú˙Ĝ˙‰˙-+„Z­˙ZĞ˙‚˙uş˙żŜ˙äò˙|ùÚí˙ĞÔ˙WĞ˙Wİ˙CĦ˙²×˙žÏ˙J¤˙”Ê˙e³˙ˆ˙€À˙Ò˙,•˙vğ˙›Ï˙vı˙›Í˙G˘˙lĥ˙‘È˙ĥÜ˙bħ˙bŻ˙†˙}˙}ĵ˙Nİ˙N§˙i´˙i²˙‹˙„Á˙,!ŝH° Áƒ*\X¤ÂM9úhfÑD",X‰$Ҍ9>0äEˆ?: X¤K¨šÖĝ9”˘%DĈlìĝ…H’/tüyҁ‡K/5á3q‚EDxZˆ°Q(qÄéd–’ÀĊAÀÄa”!G(o¤6K'p¸Bzv—]ˆò_dñÉ"79PYG,91 uÜh,–\LLù˜ŒM°$’L:i RŽUUJÖÖF,]†’G0ržužĠ&ÖK¸1UÓ"lQfK.\ħe%6ĝmx‰é]Ska4Kz¸€Àš'ÔdPĈ×>šE(O‰ÀÒ yáĈš•Hê%”ȍE…ReĦ[5,e’H£mliB p*š^ŜŜ, @ÄĴ.ÔÊĉ¤9fgÛ^}˘›@|D+í´ÔVk­´;hercules-3.07/html/images/restartu.gif000644 000765 000765 00000002520 11143760534 021517 0ustar00jmaynardjmaynard000000 000000 GIF87a!ç˙K˙şÛ˙‹Ĉ˙°Ö˙7›˙Á˙ĤÑ˙Ëċ˙H£˙m·˙Œ˙Üí˙> ˙>ž˙ˆÄ˙4™˙£Ñ˙O¨˙ ˙j³˙;ž˙…Â˙ŞÔ˙VĞ˙Vİ˙Ċ˙€˙~ŭq¸˙˙]˙ …˙?Ÿ˙×˙Óé˙uğ˙šÏ˙šÍ˙!˙!Ž˙È˙Ĉ˙µÚ˙<˙ĞĠ˙ †˙|˙|ĵ˙Ħ˙(“˙—Í˙—Ë˙Ĉ˙²Ú˙^Ż˙^­˙ „˙/˜˙y˙yĵ˙”É˙e²˙‰˙Ôê˙€ż˙G£˙ĥÙ˙)”˙˜Ê˙â˙ŽÇ˙Š˙„Â˙„À˙0—˙ŸÏ˙€˙•Ê˙˙˙f³˙fħ˙°×˙7œ˙ĤÔ˙˙RĞ˙Rİ˙wğ˙Áá˙mĥ˙˙ˆ˙£Î˙O§˙ñ˙;˙ŞĠ˙Ïç˙qı˙–Ë˙Ž˙ŒĈ˙Öê˙]Ż˙]­˙§Ó˙§Ñ˙Ìċ˙x˙xĵ˙Î˙$‘˙“Ë˙“É˙¸Û˙Œ˙? ˙Ú˙Ĝ˙‰˙-+„Z­˙ZĞ˙‚˙uş˙żŜ˙äò˙|ùÚí˙ĞÔ˙WĞ˙Wİ˙CĦ˙²×˙žÏ˙J¤˙”Ê˙e³˙ˆ˙€À˙Ò˙,•˙vğ˙›Ï˙vı˙›Í˙G˘˙lĥ˙‘È˙ĥÜ˙bħ˙bŻ˙]`ż†˙}˙}ĵ˙Nİ˙N§˙i´˙i²˙‹˙„Á˙,!ŝĜTAJĤ|4d£hÈ!ŞD`i† Œò"„ ÜÄ%ԏLjú°Ò!b$R´ˆ"Ĉ:ü8é°İ§K&3áè£pBCwZˆ°£˘P$iÄÉc€ž›"yàRÑA>²€ i ™NĦJĠÓÑÖ7%~†òŠ#ĦX“.mJ3ê(=Uħzêñgk…“C2t(B)SHE.FħsĞ#Oo —¤Û',ĵ/Ċ,Ċ;Sħ^¸ƒ‡ĉš³ŭàìÄ´gşŒÂꅔ#™ {Ev,ˆ·KCħƒ %B`À™ô³ Î Aë½MóÖ ŝ\pÔ  Z 1“èÒ£?2ÈRBÓiÑÒrR`£Âıòb—¤AH$P1 Â# ŒĉVFџ˙5PÇ%aĝPÀA€AFĦ¸!wXPá h`x\ep!ŠAui€Ċ'Џä€caĠ„$4sBtB˜p(uW^+2•Cyä0,ɕW 8ı˜YaeĊCħxÏ]ĉÚV&ĊFKŠ”ĠXXı`•”ĵèŸ#­ĊµċuE‘ġXċádžPƒ‘ŝ% G\ ÜĝĠJ %V7à1FdR²è•IÇĠB%„ĊXea… "†²A 7zĤ9˜fs]WHvC`5Ĵşàj™ŒÊ(ŬktñQÈl=íĦì²Ì6ëì³Ëní´Ô2 @µĜB+P@;hercules-3.07/html/images/startd.gif000644 000765 000765 00000001517 11143760534 021154 0ustar00jmaynardjmaynard000000 000000 GIF87a!ĈŞ·ŞĤµĤÜäÛN|L×àÖÔŜÓÂÁżÎ̽ğÊş·Èĥ°ÂŻ^‡[ĞŞ[…XXƒUİĥ¨WƒTURĤ´TQĦ¸ Ħĥ £²˘O}LŸ°ž²œ™Ĵ˜•Ş”’¨‘Œ¤‹ˆ˘‡ž€œ~~œ}ĴżŞœ­š›­™˜Ż–äê䎌Ùâً§‰‹£‰‡Ħ……Ÿƒ„Ÿ‚~›|{™yz™xx—vw—ut•rq“on‘lm‘kjhged‹bc‹agzoa‰_Z…XPNÚٞ°žÏÙÎÑÂ=NEıɸ¸Ç·ĥǵµĊ´fŒc³Ċ²`ˆ]­żĴ\†YY„VV‚SS€P¤³£Ħħ žŻŻœ›­šš­™—Ğ–”İ““İ’‘А§ŽŒŠ£‰‡Ħ†ƒŸ‚}›|z™yŜċŜŞŽŬċŬ¤‹‰˘‡ƒž‚ž€œ}}š{|šzv–ts”qr”pljkiiŽgeŒc_ˆ]\†Z,!ŝ€‚ƒ„…†‡ˆ‰Š‹>j0l1n24o6q78r:t;u=?M w@PQRA‚>.bklcn3”–˜rsœž  O§İĴ-0"²´•—89›€é÷/àÏZ3ħÒ`ċÊáË+3óó§Mdĵe%YQ!mZחbÜıŭM+ T†XİŒx§Cl·½Ċj pÒ&,ÏċéQ2Ŝ8XQp>ğ´ċÄxLĉ Vp'm¸x—†=ĠÀù8Ğé×[Ár³fÜEBF-‚aà&¨à‚ ;hercules-3.07/html/images/startu.gif000644 000765 000765 00000001522 11143760534 021171 0ustar00jmaynardjmaynard000000 000000 GIF87a!ĈŞ·ŞĤµĤÜäÛN|L×àÖÔŜÓÂÁżÎ̽ğÊş·Èĥ°ÂŻ^‡[ĞŞ[…XXƒUİĥ¨WƒTURĤ´TQĦ¸ Ħĥ £²˘O}LŸ°ž²œ™Ĵ˜•Ş”’¨‘Œ¤‹ˆ˘‡ž€œ~~œ}7F>ĴżŞœ­š›­™˜Ż–äê䎌Ùâً§‰‹£‰‡Ħ……Ÿƒ„Ÿ‚~›|{™yz™xx—vw—ut•rq“on‘lm‘kjhged‹bc‹aa‰_Z…XPNÚٞ°žÏÙÎÑÂıɸ¸Ç·ĥǵµĊ´fŒc³Ċ²`ˆ]­żĴ\†YY„V^oeV‚SS€P¤³£Ħħ žŻŻœ›­šš­™—Ğ–”İ““İ’‘А§ŽŒŠ£‰‡Ħ†ƒŸ‚}›|z™yŜċŜŞŽŬċŬ¤‹‰˘‡ƒž‚ž€œ}}š{|šzv–ts”qr”pljkiiŽgeŒc_ˆ]\†Z,!ŝ€Pj1l2n35o7q89r;t?L w@OQRAƒP/bklcn4‹rs“•— Nœž Pş.1"İĞŒŽ9:’”=?v´›ŸşPiĵ…‡ŞĴpĊħÈʚQRÏ-ia!#ˆÁ­Ĉ²ÜĥÏ- .0b1èĠÂíȘœl’ì šqÒ ³ÑX;K7=뢂ž½…F´á·.R,KÊj=óĊ ½h½PqĤ%´ži!YaÊTŠ]c÷qÖ³[hžtÑ$‰(ŒĴBRÂÂ-{Úy–¨q¨9Sä)˜Yáo’dÏ8T J‘Ŝ"¸ʜı`À̀\„ìôĝò™ ,Ugĥƒr˘œë˘RzVĊ„Ú‚ż|cŸ>œĴX{ĤÁÊÀIJwoÚFu<>£ÒùóÚĞ(Ċœ;ێg¨ ħâ80̓Ñ,SCíêٔܝO˙†ƒ˙šš˙IK˙yy˙**˙XX˙ ˙ ˙|˙—“˙ce˙““˙y|˙×ĜŽ ˙^[˙BD˙rr˙X[˙##˙!#˙QQ˙›–˙˙20˙00ŭ˙ˆŒ˙WT˙==˙;=˙kk˙™™˙‚˙˙LJ˙JJ˙xx˙+)˙))˙˙dd˙–’˙’’˙x{˙Şİ˙ÀÀù˙˙CC˙qq˙$"˙""˙RP˙PP˙˙]]˙‹˙‹‹˙‡‹˙<<˙TS˙jj˙˙KI˙IIñ˙„„˙jm˙˙55˙ec˙cc˙î˙DBî˙žž˙!!˙!˙}}˙..˙\\˙ ˙=;˙;;˙ƒ€˙gi˙˙FH˙ÒÒ˙''˙UU˙ƒƒ˙˙•š˙˙44˙|y˙`b˙ù˙˙˙˙ §˙[X˙UX˙˙ƒ†˙ËË˙ ˙ ˙NN˙||ĝö˙--ö˙[[˙‰‰˙ ˙8:˙hh˙––˙’–˙˙˙GG˙uu˙&&˙TT˙‚‚˙˙ĈÇ˙{x˙aa˙_a˙˙@@˙˘œ˙nn˙TW˙œœ˙˙MMğ++˙ˆˆ˙ ˙99˙79˙ig˙gg˙••˙˙HF˙FF˙ttê˙mj˙QS˙˙22˙02˙b`ŭ˙``˙ŽŽ˙˙??˙››˙ÉÉ˙ ˙,!ŝH° Áƒ*\¨ŠƒT<0% vA8Ì1S슂0ÀÖòBĈGÄĜ¨ŞĤ‡;â$UÀĊF>4-é˜ °H”ìH –j˜Â• ‹ÄQZċѕ†ƒ&3gtÈúó“U—½ú,ÂRBR-Rí˜5ÓF+/2jZÊ ktyҋ%—IA.È QĤa›Ş^­Ğ€ëVBY–ş+((󐌊$/ğä.i|éO…ÔvX*)ee’^’ŝ?äQ¸bžç,AäÑgj–™ĥߨ|Y&'‰ÈÏ4WÀÄĜġK$ÄWÊ-“|q™ 4< [üâ€"UŒPGzKr…,€TÀ’"Dd’Ŝ˘FžH‘H§Œ% ƒžU9Kı(BB-#Ŝ‹{¨!Œ  QFœà`È[  *:\ÂR!€‰ˆ$‚ f 4e[’ä—UtYÂR[äB"hÙ ˜ÒċZ3Q[9™ KRLQH.h\9â ŻälaÇ£Paј:ħćĞlá†"`9_l'n”œAġ¨\, ÁG`ŽòÁ†‰q6‘J´Ô& À%•ˆ"$T*˘‡ĤnÙÁ ]fQžTqħ” ½J1ŸVHg1•ĊS6|Ĥ K„dpG“úé!ng…Ğ{@ÑmŒ ˆħ)â 1iı€Pàv\ĵœh%Bkgl¸" 7ìGܰ@;hercules-3.07/html/images/stopu.gif000644 000765 000765 00000002632 11143760534 021024 0ustar00jmaynardjmaynard000000 000000 GIF87a!ç˙zz˙)+˙YY˙‹‡˙‡‡˙ ˙:8˙88˙˙ġ˙RR˙PR˙€€˙˜—˙31˙11˙a_˙__ò˙˙˙<>˙†ƒ˙šš˙IK˙yy˙**˙XX˙ ˙ ˙|˙—“˙ce˙““˙y|˙×ĜŽ ˙^[˙BD˙rr˙X[˙##˙!#˙QQ˙›–˙˙20˙00ŭ˙ˆŒ˙WT˙==˙;=˙kk˙™™˙‚˙˙LJ˙JJ˙xx˙+)˙))˙˙dd˙–’˙’’˙x{˙Şİ˙ÀÀù˙˙CC˙qq˙$"˙""˙RP˙PP˙˙]]˙‹˙‹‹˙‡‹˙<<˙TS˙jj˙˙KI˙IIñ˙„„˙jm˙˙55˙ec˙cc˙î˙DBî˙žž˙!!˙!˙}}˙..˙\\˙ ˙=;˙;;˙ƒ€˙gi˙˙FH˙ÒÒ˙''˙UU˙ƒƒ˙˙•š˙˙44˙|y˙`b˙ù˙˙˙˙ §˙[X˙UX˙˙ƒ†˙ËË˙ ˙ ˙NN˙||ĝö˙--ö˙[[˙‰‰˙ ˙8:˙hh˙––˙’–˙˙˙GG˙uu˙&&˙TT˙‚‚˙˙ĈÇ˙{x˙aa˙_a˙˙@@˙˘œ˙nn˙TW˙œœ˙˙MMğ++˙ˆˆ˙ ˙99˙79˙ig˙gg˙••˙˙HF˙FF˙ttê˙mj˙QS˙˙22˙02˙b`ŭ˙``˙ŽŽ˙˙??˙››˙ÉÉ˙ ˙,!ŝPEƒA*˜’ğ€ „Fĉ˜)vEA`k y!ˆ# bl TĠa“Áq’ŒŞqÀa#š–PL€X¤x8öq¤…ŒŞŸj˜Â• KÂQZċѕ†ƒ&3gtÈúc“U—½ú,òS•„ 4Z¤Ú1KV^"@Ô´UĊ?Öxè„u£`&5y°ì¨6Ò6„‹6?íĜu_AéˆċA Ċ_^ ¤ùĦ‰ ˘×|èò¤WW.“‚@ ù`Êż-#4}êVĠ5Ĵrv-uVPPċ‘2I^v­]bĝҟ ˘ítURÊÊ$ĵ 7È/<1 ŝÎY‚¨bMÑ]3Qżá² MNuWù]­€9,ˆ½µÙ•„úR·Lòd*@,ù_o9‚ETGـ™.]’Á!0z§hhH§îE­!4F06ÖU ¤l+£Žĉ‚Ôqñ†ji†•HĞ–ħáÊO&lÁ'Ĵ°ÁŞ,ìñÄ ;hercules-3.07/html/images/stored.gif000644 000765 000765 00000002560 11143760534 021152 0ustar00jmaynardjmaynard000000 000000 GIF87a!ç˙Äâ˙K˙p·˙şÛ˙‹Ĉ˙°Ĝ˙7›˙Á˙ĤÑ˙H£˙m·˙Œ˙> ˙>ž˙ˆÄ˙4™˙£Ñ˙O¨˙ ˙j³˙;ž˙…Â˙ŞÔ˙VĞ˙Vİ˙€˙~ŭq¸˙–Ê˙˙]˙ …˙Ìĉ˙Âá˙I¤˙?Ÿ˙Óé˙À˙uğ˙šÏ˙šÍ˙!˙!Ž˙È˙Ĉ˙<˙†Á˙ĞĠ˙ †˙|˙|ĵ˙Ħ˙(“˙—Í˙—Ë˙²Ú˙^Ż˙^­˙ „˙/˜˙y˙yĵ˙”É˙e²˙ŠÄ˙‰˙Ôê˙€ż˙Ñ˙Àà˙G£˙‘Ç˙ĥÙ˙\_Ñè˙)”˙˜Ì˙˜Ê˙Š˙„Â˙İÔ˙0—˙ŸÏ˙€˙•Ê˙˙˙f³˙fħ˙‹Ċ˙7œ˙ĤÔ˙˙RĞ˙Rİ˙mĥ˙˙ˆ˙~˙£Î˙O§˙j´˙Ùì˙;˙`Ż˙ŞĠ˙Ïç˙ ˙Ċâ˙qı˙Ž˙B ˙ŒĈ˙]Ż˙§Ó˙§Ñ˙x˙xĵ˙Î˙$‘˙“Ë˙“É˙Œ˙? ˙Ú˙Ĝ˙‰˙-+„Z­˙ZĞ˙‚˙uĵ˙uş˙|ùÚí˙˙˙˙è˙WĞ˙Wİ˙CĦ˙²×˙ƒÀ˙Íĉ˙žÏ˙á˙J¤˙”Ê˙”È˙e³˙Ż×˙ˆ˙€À˙,•˙vğ˙›Ï˙vı˙›Í˙Àß˙G˘˙lĥ˙‘È˙ĥÜ˙bħ˙bŻ˙‡˙Ñé˙†˙}˙}ĵ˙Nİ˙N§˙D˘˙i´˙i²˙‹˙Ĝì˙„Á˙,!ŝH° Áƒ*\¸¤BR;icf’F%,p‰0E“<>4€5DFB8¸$ŒĞ ¤ĉ bô"¨FÒlìĝq…H’2xŞÂe‡P/Ié4q‚ĊF}^ ˆcžW@Á„êd–›:„İ` ˘  `X XġĊNĞXµ2IˆG]•Ġ!1퀋Q§Ví™ ,Uŭ0$ĥÌ+^,!•ŞĤ& ħÊ2“*;Œ]î„ÖÌ_œiĤvÄĵŸ­,/xĦá#4Y‘’)DĈ”O[HP:ó.1°XŽ‘•ièĈ"bì0‘Á +Iˆè‰*ÎêĞWĝŝ°”!J‘w:U0"‘AäÔ`ƒÇ­8ÂŭÀ҅d’ʆ`@GNÔ ĊYrXA…(È!„j—ċÁKz´@^úÀDaˆ’È'• òˆаÄ'TĈS,=ħ‡†cp¨Ê%ˆtD"NĦ Fœ"À˘@RBjúÙÀ’ 2ş GžŬġFŻ<ė_Ĵ2ÉM¸¨ KTprN–WD*‹5V–Lİ’S°$A˜c–Éá iŽULQôTTħÔEa>A‰ċyV›X/•YM“°E,ĊĊœž4ıa&´á§R}N°Fi°ôG ŞdnxĉWx1PY4ħòT ,ċàÇuê ĞvžùÜXZ(%ÑjħĊÒ(ŽœJǜ)hš¨bĦéê"ŭĊRJ4³…ĥ %zĥí%È"5 P ìĥëîğĈÛ@;hercules-3.07/html/images/storeu.gif000644 000765 000765 00000002562 11143760534 021175 0ustar00jmaynardjmaynard000000 000000 GIF87a!ç˙Äâ˙K˙p·˙şÛ˙‹Ĉ˙°Ĝ˙7›˙Á˙ĤÑ˙H£˙m·˙Œ˙> ˙>ž˙ˆÄ˙4™˙£Ñ˙O¨˙ ˙j³˙;ž˙…Â˙ŞÔ˙VĞ˙Vİ˙€˙~ŭq¸˙–Ê˙˙]˙ …˙Ìĉ˙Âá˙I¤˙?Ÿ˙Óé˙À˙uğ˙šÏ˙šÍ˙!˙!Ž˙È˙Ĉ˙<˙†Á˙ĞĠ˙ †˙|˙|ĵ˙Ħ˙(“˙—Í˙—Ë˙²Ú˙^Ż˙^­˙ „˙/˜˙y˙yĵ˙”É˙e²˙ŠÄ˙‰˙Ôê˙€ż˙Ñ˙Àà˙G£˙‘Ç˙ĥÙ˙Ñè˙)”˙˜Ì˙˜Ê˙Š˙„Â˙İÔ˙0—˙ŸÏ˙€˙•Ê˙˙˙f³˙fħ˙‹Ċ˙7œ˙ĤÔ˙˙RĞ˙Rİ˙mĥ˙˙ˆ˙~˙£Î˙O§˙j´˙Ùì˙;˙`Ż˙ŞĠ˙Ïç˙ ˙Ċâ˙qı˙Ž˙B ˙ŒĈ˙]Ż˙§Ó˙§Ñ˙x˙xĵ˙Î˙$‘˙“Ë˙“É˙Œ˙? ˙Ú˙Ĝ˙‰˙-+„Z­˙ZĞ˙‚˙uĵ˙uş˙|ùÚí˙˙˙˙è˙WĞ˙Wİ˙CĦ˙²×˙ƒÀ˙Íĉ˙žÏ˙á˙J¤˙”Ê˙”È˙e³˙Ż×˙ˆ˙€À˙,•˙vğ˙›Ï˙vı˙›Í˙Àß˙G˘˙lĥ˙‘È˙ĥÜ˙bħ˙bŻ˙‡˙]`żÑé˙†˙}˙}ĵ˙Nİ˙N§˙D˘˙i´˙i²˙‹˙Ĝì˙„Á˙,!ŝ0U˨4|)# £ĥD’É À"#Ä   4ĈUQr-òÂ#h$R´¸"F<Qá`ŞgP&Gé¤pBCF|^ ˆ£"žV<ı„Êc€žĤ4uSĦÒÁ@°°é ™NĦJŭÓqÖ:(~şòŞ#ĦĜ“.mJ3*Ĵ?UħŞúQhk…“C2tXB)ÓLL.^Ùs+&Uu —¤+(lĵ/Ñ,yĊ›=Sħ^èB‡ĉ %1BhLİ4´˜dĉAÚ7a`a# ӌ̆EÄĜa"CV‘Í  ÒO­ìÁ”"3ìŝpúİ`D"‚ÄİħĉŽĞ3ZMLûĞ .`Je§†94QC`ĊQĊĦ0‡£A† XċÑBwPìçl€ "žP"ˆ#$²GœàĜLx`ċ„ŠQĦ*–Òˆ4q„0qŠ„òH ˘ÍgV*ĴèB.^—`ĵbP]xħŠ$.9pb&XMħÉ zé]İf˜W))4V^AJ•Zrée…3ˆÉ•W µQII„dhéÄ$÷yw™k[™DJb,IRVc[`lvb$…˜´לBÙ9YĦ•1(§ 8tI!˜vÄĊ€“_­ÄÊQY%`•CjÑg' &r\e!TB^ŒUV˘4êlĤ0İ ƒi6WĤŠ,„V(al Èúij’á½FW а4@O€”kîıèĤĞıĤĴëîğçïĵë ;hercules-3.07/html/images/sysoffu.gif000644 000765 000765 00000001307 11143760534 021346 0ustar00jmaynardjmaynard000000 000000 GIF87a%ĈĤ‚‚Ĥ—9­­­Ĥx”‹zĦĦĦŸŸŸşşŸžžĤPÉĥ[•z]”z\™™™4&,è­4‘‡§¨€v™š’K65ˆ|jr}r¨‰†¨}[Ĥƒ„œœ\F$İs””“œŠ1¤†¨u˜‡e|l’küŝÔ¨~nĴ|^Ğz]İz[š~‹˜z^–z\ƒ\F”qPĦ{`žŸŸ§z\“{f}|nŞ}l˜pMŸˆWĞ{YŞĞĞ|fŒvDŒjDšš—˘žwžd^Dƒœœœœ‘wYtF,{\•’§‚›z\¸ş–ÁÂĥĞ€[ÒÓĴĴz\Ğz[D.$žŠ:›’beaX¨¨İz\žżżœ”z[Ĉ¸W§~qŞ}j…¤…|gݍk£…fÀ=¤†I<+/§€w•wXİݝˆƒvĞ{]İ h†|jݧuù˙˙Ş{_Ĥƒ†œžŠ‚t‹ŒŒÉĊv¤†”¨}cĞz\,%ŝ€‚ƒ„…†‡ˆ‰Š‹ŒˆV‹Vl%”%”“•Š%%š—Š“ll•ŸĤ§‰ŞV“‚ŞœĤ—°¨´Žışğĵ½żÀŽcĵO32M49/-MMMMd&M‹#[sMsàs]^Z1 OˆOßM*YJLr NMˆsh0̈HAE›Ħ'ĵÙàQĊß?!”iÀ´#€b@€!¤qħb„ĊšD¸²ñÀĈIê Qcħ —&F€|éòLƒ68rƒÄ›;]JÒà‡ Âàá2äb\@w͉Ĥ„<$œömiÒ „5-ôˆB‘"‡t P€Y‚ZŬ:ˆ,ş‚N†",¨]¸çèGXv8 Fı2Ħ@;hercules-3.07/html/images/sysonu.gif000644 000765 000765 00000000724 11143760534 021212 0ustar00jmaynardjmaynard000000 000000 GIF87a%Ĥ‚‚´ĥ”z\4&,üĉD§¨€vK65ˆ|jr}rĤƒ„\F$İsœz\¨u|lüŝÔüŝĴƒ\FĦ{`“{füŝ„}|nŞ}l˜pMĞ|fŒvDŒjDüâ4d^Düŝ¤tF,§‚üŝ|Ĵz\üŝTD.$üÖTüö,żż¨|üÂTŒŽüTŞ}jüÚ,…üĥ,<+/†|jİrù˙˙Ĥƒ†šz\¤†”üŝ”üŞ$,%ùÀpH,È¤rÉl"OÏċiĦBÔiU @µ×.T9ÍĠŻùœTŸĤB5×|…£éÎĵ~Ïïû˙€N0|$" M " """(2"K,6"6  ž$H$ŸŸ##&ž" Hž)7]7)”šF$ ž/!ı]7!&ÌF -7¸3ğ5Î "ÒÓÓÓ!" 1Î".àâä%À "·×7/ÌġˆÀáN_  L£!BE€ ×à­ + J*^˜˜F 3f NQôë£ –óEQÖ,'>n¨ĤM"A;hercules-3.07/html/images/translucentoffd.gif000644 000765 000765 00000001771 11143760534 023056 0ustar00jmaynardjmaynard000000 000000 GIF87a!ĈŠŒ‹†‹‹…‰‰ƒĴŞĞޤ²²ħ°­°°ĴŻĞŞ­İ­ĴİĴĴ¨ĞŞ§ŞŞĤݨ¨¨¤§¨£•”Ž“’Œ’‹‘ŠŒŒ…‹Š„ŠŠƒ––’ħħĴħŻĴ°ŻĞ­İ­­¨ĴЧĞĞĤĞİĤŞİİݤ¨İ£”“Œ²ħ°ħħŻŻŻ­­­ĞĴ­Ş••‹‹†Ĵ¨ĴĴĤĴŞĤŞŞ¤Ğ¨Ş¨¤İ¨£´²ħ³²°ħ°°°­ŻĴĞ­ŞĴĴİĤ¨£‘‹ŠŒ‡ŒŒ†ŠŠ„³³Ż³ħݲħħħ­°ŻĴŻŻĞŻŞŻ­Ğ­Ş­­İĴ­¨ĴШĞЧŞİĤİݨݤ’‘‹ħħ°‰Œ‹…‰‰‚——“ħ°Ĵ°°Ğ°ĞŻŞ­Ĵ¨ĴĴ§ĞŞĤŞŞŞ¨İ¨¤¨¨£°°ĴŞ””ŒŒ‡ŠŠ…­¨ĴĞĤĞĞĞİİİ£•“Œ´³ħ³ħ°ħħŻŻĴ­­Ş••,!ŝ€‚ƒ„…†‡ˆ‰Š‹Y)ss;s I G—D™G89srrq6p¤¤U‚-’“ IH—G²›HµĦq7¤(§u“ L Ä HGrF°ZZ· EEş))‚LÜÄ ĥ°rGÏÏ—ËFF ‚o/jÛ ŞI[ ĉä sGéꎰpb—ƒÛ˜L˘ÂÌH´SBïQ--—n ŞP`MˆƒÄ„}p  „6`Ĉ!ŒƒMh xD:~QÀD›—/1ÚmCfŒÊ(O`vİ%°& CÛÄàĈäàš¨4hŒÙşĤ—2/ ‚U¤—†fm³uk”ŝ `8YòŒĜ¨m|Pe½=Ġ<(fk¸ ĵ ĊîÓmh ó`Ê<ı}c´F"`8pÀĊCDzċ\‚eb  CF›//?ti•@P€5"“Q&‚„ ?ƒ%Cf„'O*˜$H[bJŒ‘R˘/V܀ ——ÔXoğR E@CfJ}2& ”??şÉ‚‚XQv+=Ä„Ä{„A "„AžM4IuìEĈuĝ:P$BGáHÌ!ÈbDĊOŒ&K26@4:À„ôÀ+ôƒD9I…NP`Xá’LԒ@9̑KRĝß$Ü,À@0 X(  Èe@²À’ŝ́?’ly%”) ‡(6Ô)ˆ . 1`…dpBŠÁ¤A€ADІ ‚;hercules-3.07/html/images/translucentoffu.gif000644 000765 000765 00000002061 11143760534 023070 0ustar00jmaynardjmaynard000000 000000 GIF87a!ĈŒ‹†‰‰ƒĴŞĞޤ²²ħ°­°°ĴŻĞŞ­İ­ĴİĴĴ¨ĞŞ§ŞŞĤݨ¨¨¤§¨£“’Œ‘ŠŽ‰ŽˆŒŒ…‹Š„––’>Š K½GFtE¨\\Ż—DD²''+,SKÖ½¨tFÈÈŽÄEE—>g.mĠ ˘H]àŜuŬFäFSX܀Xm‰";*ÒÔAq„ËŻ$ï µââèĠ™ T¸ù0°× @ˆqG 2!Ȉa°€É.üŒHÀR…a,Ħ& 8@á˜)sŠ“–_Zġ3B˄ p`X[2 Ô3ÊhEÙL‚—ŽŞPx ġ#˜‚b…£U+ŝ ^4Q‚Ldƒ&èŒ{wĥi0bŒÖp=€ÙÁ‹]+VdÀ™TL)zè´ÖA Qc@€xÁ€_ìŜĊşÖó˜{LP’Œ™o°ìÔ+( 1ÙÌÉ1 Dèù3¨3!8qB"ĵXÚn%3˘L”~ŻÎˆĠ À°TDĦJöĥ(Ɉp@„ƒ1f¤ä7CÂzġ1‘€XPQÁPÛĦԀ 4óĉ@€0Ĉy 0Á"½Gb08ŬˆN<ħ è=ĦâtêpDœ1@‚ċÈRŽ ,ÀŽ ,‘ƒ!`1 )˜ÀCL6݈†Md¨á”K´r8L€‹.S2‘ညX“€ş$ ‘2t”P +¨Ĉ! tiĤ÷$B&˜XžP™Ôà§Ĵ!€B°!„ƒnq4ŞĊA´À@dÀ˜ŝÀ¨ħĈ™l´ĢZèƒj蠜 (Ħ†"*€˘Œ: ݤ”ZšİĤħ;hercules-3.07/html/images/translucentond.gif000644 000765 000765 00000002666 11143760534 022724 0ustar00jmaynardjmaynard000000 000000 GIF87a!çÑÒÍÒÌÏÒËşş³°°İݍ§ĴĴ×ĠÏßßÚŜŬÙŬŬĜŬÛĜÜÛ×ÛÛÖÚÛĠÛÙÖÚÙĠÙÙÔĜÙÓĜ×Ó××ÒÖĠÑĠĠÔÓÏÓÓÎÒÓÍÑÓÌÏÑÊÎÑÉÎÏÉŬŬÛÛÛÙşı²ĥµµ³­´³Ĵ°Ż¨ŻŻ§­Ĥ­­½½¸ÜÜÖÜÚÖÛÚĠÙĜÓĜĜÒĜÖÒ×ÖÑÖÖÖÔĠÔÏÔÔÎÓÔÍÔÒÎÓÒÍßŜÜŜŜÛŬÜÚÜÜÙı¸°ÙÚÖĜÚĠ·ĥ·´ĥ´­¨ÚÙÓÙÙÒÙ×ÒĜ×ÑĠĠÎÖÓÏĠÓÎáßŬàßÜŜŬÚŬŬÙÜÛĜÛÛ×ÙÙĠÑÓͰŻİ­­ĤÚĜÒĜĜĜÖÔÒÌààÛÎĈàŜÛßŜÚŜŜÙŜÜÙŬÜĜÜÜ×ÛÚÖÚÚĠÙÚÔÙĜÔĜĜÓ×ÖÒÖÖÑĠÔÔÔÏÓÔÎÒÒÍÑÒÌŜŜÜÜÜÚÖĜÔµ´­ħ°İ°°¨Ż§ĴĴ¤ĵĵ·ŜŬĜÜÛÖÚÙÔĜ×Ò××ÑÖĠĠĠÏĠÓÏÔÓÎÓÓÍÒÓÌÑÑËŜŬÛÛÛĜÙÙÖ¸·ŻĜÙĠĜ×Ġ·µĠÙÒğğµıı³­­§ÚÚÓÙĜÒĜÖÑ×ÖÖÖÏÖÔÏÔÔÍÔÒÍáàŬàŜÜŜŜÚŬÜÙÜÜĜÛÚ׺¸°ÚÚÖÙÚĠÚĜÖĜĜÔ×ĜÓ,!ŝĦH° Áƒ*\˜â AœžˆŒ]²hL @ǎ'L˜XRRİdÉ6 z"qb .vI@“£“›˜0‰´´¤$”PL!ŒQ0 ĵĜQp‰K—‹˜|ÉrËž‚r O„ŻF4h€İ F& ¤JĊt‘ —·!1 ÜTeˆW2úŝ̸@>Ĉ>ÔhP¨Ĉ…ë-òäĉËĊîߋ˰`Ĉ‚fŒG¤qA |XGÁHµ~ÄĦħGfThá ûíáGqgœQ!ŽtrÇB’$!Ɋ{X †t EqfH²Gq|ă ”ħÂ,”DDި! ¨€„·ÇŠ7ĜpD$z¸@,ĵ†@#P‚EŠ7àˆA¨ħFqh¤˜„ 2\‚áĈDÁ1œpĊ—ÜrÍ=ŬtĠÁWtBaçwáWŜyé­×Ŝ{ĜÉGbp" Qâİŝ( "¨ DTçwRha…gW tèĦ“râĉhÈ@+ÀKF°dQFƒR`lhÂR&-BÈ'Ÿkíµ‘:A¤v+A7e² •m·ePÊÉD_‰1ĈPb<1ˆT1ĠáĈëz+Ĉ ˜€Á’ğ­;î8X2’ $„TPAÇt 'Ìa‚›0‡ŒP@%LA@(O!„@;hercules-3.07/html/images/translucentonu.gif000644 000765 000765 00000002767 11143760534 022747 0ustar00jmaynardjmaynard000000 000000 GIF87a!çÑÒÍÒÌÏÒËşş³°°İݍ§ĴĴ×ĠÏßßÚŜŬÙŬŬĜŬÛĜÜÛ×ÛÛÖÚÛĠÛÙÖÚÙĠÙÙÔĜÙÓĜ×Ó××ÒÖĠÑĠĠÔÓÏÓÓÎÒÓÍÑÓÌÏÑÊÎÑÉÎÏÉŬŬÛÛÛÙşı²ĥµµ³­´³Ĵ°Ż¨ŻŻ§­Ĥ­­½½¸ÜÜÖÜÚÖÛÚĠÙĜÓĜĜÒĜÖÒ×ÖÑÖÖÖÔĠÔÏÔÔÎÓÔÍÔÒÎÓÒÍßŜÜŜŜÛŬÜÚÜÜÙı¸°ÙÚÖĜÚĠ·ĥ·´ĥ´­ĴĴ£¨ÚÙÓÙÙÒÙ×ÒĜ×ÑĠĠÎÖÓÏĠÓÎáßŬàßÜŜŬÚŬŬÙÜÛĜÛÛ×ÙÙĠÑÓͰŻİ­­ĤÚĜÒĜĜĜÖÔÒÌààÛÎĈàŜÛßŜÚŜŜÙŜÜÙŬÜĜÜÜ×ÛÚÖÚÚĠÙÚÔÙĜÔĜĜÓ×ÖÒÖÖÑĠÔÔÔÏÓÔÎÒÒÍÑÒÌŜŜÜÜÜÚÖĜÔµ´­ħ°İ°°¨Ż§ĵĵ·ŜŬĜÜÛÖÚÙÔĜ×Ò××ÑÖĠĠĠÏĠÓÏÔÓÎÓÓÍÒÓÌÑÑËŜŬÛÛÛĜÙÙÖ¸·ŻĜÙĠĜ×Ġ·µĠÙÒ@E9ğğµıı³­­§ÚÚÓÙĜÒĜÖÑ×ÖÖÖÏÖÔÏÔÔÍÔÒÍáàŬàŜÜŜŜÚŬÜÙÜÜĜÛÚ׺¸°ÚÚÖÙÚĠÚĜÖĜĜÔ×ĜÓ,!ŝ?}JñA NPĈqF‚.Y"&P c”&M,-İđc›Ot ‚’Pa vIÀrⓗ˜0e´Ä„#Ž6) P(&B˜Ÿ`xİ£à—.1}ù–-4ċP´(ĝ;²ŝ Ó &'›(Xş“&\ÒbÄ4@ÄĤ*D°Ŝ†$*À|%ˌ ħ ÒriâS8<iÑk…Q ù€âɗL Ô%ÙÀrRL›HBé;-Ê9‚荧0+z6şcèNM 2} –œ6‚Ûà‡FŸ44Ò¤ñ& ĜLÒž]˜%çp>2ĝŝ̸@>Ĉ…=~ÔhPó§Ĉë-àĉ‹#ĵ'Ŝ‚ À`Ĉx4ìqAİGuLÁR „~| ĦÇfd¨á 2X GĝqF†8҉_DIH˘„$0êaRę!‰ÄíC V„RĈ v°Ħ„J$ùâ‡4\ xž0Ŝ`‘äáw°p@2%X¸xCd°k‡†‹JĜ /˜ħĜa(4!ÂíWÜqÉ-×ÜsÑMWŬueĦ?ù]x•w^zëµ÷ŜuòQ œÀA VúÙßxA&¸ šJ€bŜŽg!†fx†ÀPˆ#šĦ)'O@AÂ&"2ĝJÁ²Ë’Á,d”QA˘D[F𐔠!,2( @+î¸ I Á˜Ğĵ”É;ˆ Oë–ħ)' e%Ĉ<‰… O4Ġ8,˘n@ïşb‚ $íĞ~€ƒ%-Ħñ) AB „( pÂ&ÈĦ² sÀÈPÂÄaóC$BÇSĜS”󌀲Êr°|BÉ#‹üqΟx ²È$›|ôÊ-żóÌ5ß ġ';hercules-3.07/html/images/waitoffu.gif000644 000765 000765 00000001353 11143760534 021475 0ustar00jmaynardjmaynard000000 000000 GIF87a%ĈĤ‚‚Ĥ—9­­­Ĥx”‹zĦĦĦŸŸŸşşŸžžĤPÉĥ[•z]”z\™™™4&,è­4‘‡§¨€v™š’K65ˆ|jr}r¨‰†¨}[Ĥƒ„œœ\F$İs””“œŠ1¤†¨u˜‡e|l’k¨~nĴ|^Ğz]İz[š~‹˜z^–z\ƒ\F”qPĦ{`žŸŸ§z\“{f}|nŞ}l˜pMŸˆWĞ{YŞĞĞ|fŒvDŒjDšš—˘žwžd^Dƒœœœœ‘wYtF,{\•’§‚›z\¸ş–ÁÂĥĞ€[ÒÓĴĴz\Ğz[D.$žŠ:›’beaX¨¨İz\žœ”z[Ĉ¸W§~qŞ}j…¤…|g˙˙˙ݍk£…fÀ=¤†I<+/§€w•wXİݝˆƒvĞ{]İ h†|jݧuŞ{_Ĥƒ†œžŠ‚t‹ŒŒżżżÉĊv¤†”¨}cĞz\,%ŝ€‚ƒ„…†‡ˆ‰Š‹ŒŽŒr_’__—_r_ž–ƒ‘œ˘œr‚™—¨„“r‘“˜İš…ž“™˜¸ĤµĴ„Á”ÂŻžĞÉÊË̇ÏÍÏÑÌÒ×ĜdÙŬĜP43N5:0.ŜĜNNNNe'NéÏ%[tNtüt]^Zd8€â Ê>'+²TXÒdOœdĥŽNš10pà Uêeƒ’AߍV4nòŒ²­C2!Ȑ!‚š,JÈÁÁ‰„+7ÜĵİÄN’52pqrDÏJÑ8°a¤$8LĵéyUé"€xħ@LŽQJ{v1ĈA‚#Ŭ !€JOBâÀq 1Ŭ'm˘D`“ )0az(è E&ŜEv°£ˆ=DÔÙ`¤Ċğ ?Kâ jU˞Mğvĥ@;hercules-3.07/html/images/waitonu.gif000644 000765 000765 00000000763 11143760534 021343 0ustar00jmaynardjmaynard000000 000000 GIF87a%Ĥ‚‚ŸŸŸ´ĥ”z\4&,üĉD§¨€vK65ˆ|jr}rĤƒ„\F$İsœz\¨u|lüŝÔüŝĴƒ\FĦ{`“{füŝ„}|nŞ}l˜pMĞ|fŒvDŒjDüâ4d^Düŝ¤tF,§‚üŝ|Ĵz\üŝTD.$üÖTüö,¨|üÂTŒŽüTŞ}jüÚ,…üĥ,˙˙˙<+/†|jİrù˙˙Ĥƒ†żżżšz\¤†”üŝ”üŞ$,%ŝ@€pH,È¤rÉl:™8B&•2ĊU†“y­CA”+pqÂìMœâşÑ)6­-½Ó,o³‰]T‚o^kO‰Š‹FŽ‘’“”•–—˜™—3 š'% ™ %%%%*5%—.:%:şş¸'”'ıı&&)¸% ”޸+;Ç;+´’' ¸1$!ÓÔ;$)ĉ’Ş#/;Ò6;!!9è %ìí!íí$J@ Œ}ŭŝùCA`mF”ˆ&/žĊĉ@@ŒP‚GŠ(02ĤíF 0È[Ĝ‚³J.\ħˆ‘˘ĉÌ9ĉײœ:ˆ¸Ä ›KfÍ4ÈéA£§§P£Z ;hercules-3.07/decNumber/decContext.c000644 000765 000765 00000024265 11143760537 021133 0ustar00jmaynardjmaynard000000 000000 /* ------------------------------------------------------------------ */ /* Decimal Context module */ /* ------------------------------------------------------------------ */ /* Copyright (c) IBM Corporation, 2000, 2005. All rights reserved. */ /* */ /* This software is made available under the terms of the */ /* ICU License -- ICU 1.8.1 and later. */ /* */ /* The description and User's Guide ("The decNumber C Library") for */ /* this software is called decNumber.pdf. This document is */ /* available, together with arithmetic and format specifications, */ /* testcases, and Web links, at: http://www2.hursley.ibm.com/decimal */ /* */ /* Please send comments, suggestions, and corrections to the author: */ /* mfc@uk.ibm.com */ /* Mike Cowlishaw, IBM Fellow */ /* IBM UK, PO Box 31, Birmingham Road, Warwick CV34 5JL, UK */ /* ------------------------------------------------------------------ */ /* This module comprises the routines for handling arithmetic */ /* context structures. */ /* ------------------------------------------------------------------ */ #include // for strcmp #include "decContext.h" // context and base types #include "decNumberLocal.h" // decNumber local types, etc. /* ------------------------------------------------------------------ */ /* decContextDefault -- initialize a context structure */ /* */ /* context is the structure to be initialized */ /* kind selects the required set of default values, one of: */ /* DEC_INIT_BASE -- select ANSI X3-274 defaults */ /* DEC_INIT_DECIMAL32 -- select IEEE 754r defaults, 32-bit */ /* DEC_INIT_DECIMAL64 -- select IEEE 754r defaults, 64-bit */ /* DEC_INIT_DECIMAL128 -- select IEEE 754r defaults, 128-bit */ /* For any other value a valid context is returned, but with */ /* Invalid_operation set in the status field. */ /* returns a context structure with the appropriate initial values. */ /* ------------------------------------------------------------------ */ decContext * decContextDefault(decContext *context, Int kind) { // set defaults... context->digits=9; // 9 digits context->emax=DEC_MAX_EMAX; // 9-digit exponents context->emin=DEC_MIN_EMIN; // .. balanced context->round=DEC_ROUND_HALF_UP; // 0.5 rises context->traps=DEC_Errors; // all but informational context->status=0; // cleared context->clamp=0; // no clamping #if DECSUBSET context->extended=0; // cleared #endif switch (kind) { case DEC_INIT_BASE: // [use defaults] break; case DEC_INIT_DECIMAL32: context->digits=7; // digits context->emax=96; // Emax context->emin=-95; // Emin context->round=DEC_ROUND_HALF_EVEN; // 0.5 to nearest even context->traps=0; // no traps set context->clamp=1; // clamp exponents #if DECSUBSET context->extended=1; // set #endif break; case DEC_INIT_DECIMAL64: context->digits=16; // digits context->emax=384; // Emax context->emin=-383; // Emin context->round=DEC_ROUND_HALF_EVEN; // 0.5 to nearest even context->traps=0; // no traps set context->clamp=1; // clamp exponents #if DECSUBSET context->extended=1; // set #endif break; case DEC_INIT_DECIMAL128: context->digits=34; // digits context->emax=6144; // Emax context->emin=-6143; // Emin context->round=DEC_ROUND_HALF_EVEN; // 0.5 to nearest even context->traps=0; // no traps set context->clamp=1; // clamp exponents #if DECSUBSET context->extended=1; // set #endif break; default: // invalid Kind // use defaults, and .. decContextSetStatus(context, DEC_Invalid_operation); // trap } return context;} // decContextDefault /* ------------------------------------------------------------------ */ /* decContextStatusToString -- convert status flags to a string */ /* */ /* context is a context with valid status field */ /* */ /* returns a constant string describing the condition. If multiple */ /* (or no) flags are set, a generic constant message is returned. */ /* ------------------------------------------------------------------ */ const char *decContextStatusToString(const decContext *context) { Int status=context->status; if (status==DEC_Conversion_syntax ) return DEC_Condition_CS; if (status==DEC_Division_by_zero ) return DEC_Condition_DZ; if (status==DEC_Division_impossible ) return DEC_Condition_DI; if (status==DEC_Division_undefined ) return DEC_Condition_DU; if (status==DEC_Inexact ) return DEC_Condition_IE; if (status==DEC_Insufficient_storage ) return DEC_Condition_IS; if (status==DEC_Invalid_context ) return DEC_Condition_IC; if (status==DEC_Invalid_operation ) return DEC_Condition_IO; #if DECSUBSET if (status==DEC_Lost_digits ) return DEC_Condition_LD; #endif if (status==DEC_Overflow ) return DEC_Condition_OV; if (status==DEC_Clamped ) return DEC_Condition_PA; if (status==DEC_Rounded ) return DEC_Condition_RO; if (status==DEC_Subnormal ) return DEC_Condition_SU; if (status==DEC_Underflow ) return DEC_Condition_UN; if (status==0 ) return DEC_Condition_ZE; return DEC_Condition_MU; // Multiple errors } // decContextStatusToString /* ------------------------------------------------------------------ */ /* decContextSetStatusFromString -- set status from a string */ /* */ /* context is the controlling context */ /* string is a string exactly equal to one that might be returned */ /* by decContextStatusToString */ /* */ /* The status bit corresponding to the string is set, and a trap */ /* is raised if appropriate. */ /* */ /* returns the context structure, unless the string is equal to */ /* DEC_Condition_MU or is not recognized. In these cases NULL is */ /* returned. */ /* ------------------------------------------------------------------ */ decContext * decContextSetStatusFromString(decContext *context, const char *string) { if (strcmp(string, DEC_Condition_CS)==0) return decContextSetStatus(context, DEC_Conversion_syntax); if (strcmp(string, DEC_Condition_DZ)==0) return decContextSetStatus(context, DEC_Division_by_zero); if (strcmp(string, DEC_Condition_DI)==0) return decContextSetStatus(context, DEC_Division_impossible); if (strcmp(string, DEC_Condition_DU)==0) return decContextSetStatus(context, DEC_Division_undefined); if (strcmp(string, DEC_Condition_IE)==0) return decContextSetStatus(context, DEC_Inexact); if (strcmp(string, DEC_Condition_IS)==0) return decContextSetStatus(context, DEC_Insufficient_storage); if (strcmp(string, DEC_Condition_IC)==0) return decContextSetStatus(context, DEC_Invalid_context); if (strcmp(string, DEC_Condition_IO)==0) return decContextSetStatus(context, DEC_Invalid_operation); #if DECSUBSET if (strcmp(string, DEC_Condition_LD)==0) return decContextSetStatus(context, DEC_Lost_digits); #endif if (strcmp(string, DEC_Condition_OV)==0) return decContextSetStatus(context, DEC_Overflow); if (strcmp(string, DEC_Condition_PA)==0) return decContextSetStatus(context, DEC_Clamped); if (strcmp(string, DEC_Condition_RO)==0) return decContextSetStatus(context, DEC_Rounded); if (strcmp(string, DEC_Condition_SU)==0) return decContextSetStatus(context, DEC_Subnormal); if (strcmp(string, DEC_Condition_UN)==0) return decContextSetStatus(context, DEC_Underflow); if (strcmp(string, DEC_Condition_ZE)==0) return context; return NULL; // Multiple status, or unknown } // decContextSetStatusFromString /* ------------------------------------------------------------------ */ /* decContextSetStatus -- set status and raise trap if appropriate */ /* */ /* context is the controlling context */ /* status is the DEC_ exception code */ /* returns the context structure */ /* */ /* Control may never return from this routine, if there is a signal */ /* handler and it takes a long jump. */ /* ------------------------------------------------------------------ */ decContext * decContextSetStatus(decContext *context, uInt status) { context->status|=status; if (status & context->traps) raise(SIGFPE); return context;} // decContextSetStatus hercules-3.07/decNumber/decContext.h000644 000765 000765 00000017502 11143760537 021134 0ustar00jmaynardjmaynard000000 000000 /* ------------------------------------------------------------------ */ /* Decimal Context module header */ /* ------------------------------------------------------------------ */ /* Copyright (c) IBM Corporation, 2000, 2005. All rights reserved. */ /* */ /* This software is made available under the terms of the */ /* ICU License -- ICU 1.8.1 and later. */ /* */ /* The description and User's Guide ("The decNumber C Library") for */ /* this software is called decNumber.pdf. This document is */ /* available, together with arithmetic and format specifications, */ /* testcases, and Web links, at: http://www2.hursley.ibm.com/decimal */ /* */ /* Please send comments, suggestions, and corrections to the author: */ /* mfc@uk.ibm.com */ /* Mike Cowlishaw, IBM Fellow */ /* IBM UK, PO Box 31, Birmingham Road, Warwick CV34 5JL, UK */ /* ------------------------------------------------------------------ */ /* */ /* Context must always be set correctly: */ /* */ /* digits -- must be in the range 1 through 999999999 */ /* emax -- must be in the range 0 through 999999999 */ /* emin -- must be in the range 0 through -999999999 */ /* round -- must be one of the enumerated rounding modes */ /* traps -- only defined bits may be set */ /* status -- [any bits may be cleared, but not set, by user] */ /* clamp -- must be either 0 or 1 */ /* extended -- must be either 0 or 1 [present only if DECSUBSET] */ /* */ /* ------------------------------------------------------------------ */ #if !defined(DECCONTEXT) #define DECCONTEXT #define DECCNAME "decContext" /* Short name */ #define DECCFULLNAME "Decimal Context Descriptor" /* Verbose name */ #define DECCAUTHOR "Mike Cowlishaw" /* Who to blame */ #if !defined(int32_t) #include // C99 standard integers #endif #include // for traps /* Conditional code flag -- set this to 0 for best performance */ #define DECSUBSET 0 // 1=enable subset arithmetic /* Context for operations, with associated constants */ enum rounding { DEC_ROUND_CEILING, // round towards +infinity DEC_ROUND_UP, // round away from 0 DEC_ROUND_HALF_UP, // 0.5 rounds up DEC_ROUND_HALF_EVEN, // 0.5 rounds to nearest even DEC_ROUND_HALF_DOWN, // 0.5 rounds down DEC_ROUND_DOWN, // round towards 0 (truncate) DEC_ROUND_FLOOR, // round towards -infinity DEC_ROUND_MAX // enum must be less than this }; typedef struct { int32_t digits; // working precision int32_t emax; // maximum positive exponent int32_t emin; // minimum negative exponent enum rounding round; // rounding mode uint32_t traps; // trap-enabler flags uint32_t status; // status flags uint8_t clamp; // flag: apply IEEE exponent clamp #if DECSUBSET uint8_t extended; // flag: special-values allowed #endif } decContext; /* Maxima and Minima */ #define DEC_MAX_DIGITS 999999999 #define DEC_MIN_DIGITS 1 #define DEC_MAX_EMAX 999999999 #define DEC_MIN_EMAX 0 #define DEC_MAX_EMIN 0 #define DEC_MIN_EMIN -999999999 #define DEC_MAX_MATH 999999 // max emax, etc., for math functions /* Trap-enabler and Status flags (exceptional conditions), and their names */ // Top byte is reserved for internal use #define DEC_Conversion_syntax 0x00000001 #define DEC_Division_by_zero 0x00000002 #define DEC_Division_impossible 0x00000004 #define DEC_Division_undefined 0x00000008 #define DEC_Insufficient_storage 0x00000010 // [used if malloc fails] #define DEC_Inexact 0x00000020 #define DEC_Invalid_context 0x00000040 #define DEC_Invalid_operation 0x00000080 #if DECSUBSET #define DEC_Lost_digits 0x00000100 #endif #define DEC_Overflow 0x00000200 #define DEC_Clamped 0x00000400 #define DEC_Rounded 0x00000800 #define DEC_Subnormal 0x00001000 #define DEC_Underflow 0x00002000 /* IEEE 854 groupings for the flags */ // [DEC_Clamped, DEC_Lost_digits, DEC_Rounded, and DEC_Subnormal are // not in IEEE 854] #define DEC_IEEE_854_Division_by_zero (DEC_Division_by_zero) #if DECSUBSET #define DEC_IEEE_854_Inexact (DEC_Inexact | DEC_Lost_digits) #else #define DEC_IEEE_854_Inexact (DEC_Inexact) #endif #define DEC_IEEE_854_Invalid_operation (DEC_Conversion_syntax | \ DEC_Division_impossible | \ DEC_Division_undefined | \ DEC_Insufficient_storage | \ DEC_Invalid_context | \ DEC_Invalid_operation) #define DEC_IEEE_854_Overflow (DEC_Overflow) #define DEC_IEEE_854_Underflow (DEC_Underflow) // flags which are normally errors (results are qNaN, infinite, or 0) #define DEC_Errors (DEC_IEEE_854_Division_by_zero | \ DEC_IEEE_854_Invalid_operation | \ DEC_IEEE_854_Overflow | DEC_IEEE_854_Underflow) // flags which cause a result to become qNaN #define DEC_NaNs DEC_IEEE_854_Invalid_operation // flags which are normally for information only (have finite results) #if DECSUBSET #define DEC_Information (DEC_Clamped | DEC_Rounded | DEC_Inexact \ | DEC_Lost_digits) #else #define DEC_Information (DEC_Clamped | DEC_Rounded | DEC_Inexact) #endif // name strings for the exceptional conditions #define DEC_Condition_CS "Conversion syntax" #define DEC_Condition_DZ "Division by zero" #define DEC_Condition_DI "Division impossible" #define DEC_Condition_DU "Division undefined" #define DEC_Condition_IE "Inexact" #define DEC_Condition_IS "Insufficient storage" #define DEC_Condition_IC "Invalid context" #define DEC_Condition_IO "Invalid operation" #if DECSUBSET #define DEC_Condition_LD "Lost digits" #endif #define DEC_Condition_OV "Overflow" #define DEC_Condition_PA "Clamped" #define DEC_Condition_RO "Rounded" #define DEC_Condition_SU "Subnormal" #define DEC_Condition_UN "Underflow" #define DEC_Condition_ZE "No status" #define DEC_Condition_MU "Multiple status" #define DEC_Condition_Length 21 // length of the longest string, // including terminator /* Initialization descriptors, used by decContextDefault */ #define DEC_INIT_BASE 0 #define DEC_INIT_DECIMAL32 32 #define DEC_INIT_DECIMAL64 64 #define DEC_INIT_DECIMAL128 128 /* decContext routines */ decContext * decContextDefault(decContext *, int32_t); decContext * decContextSetStatus(decContext *, uint32_t); const char * decContextStatusToString(const decContext *); decContext * decContextSetStatusFromString(decContext *, const char *); #endif hercules-3.07/decNumber/decDPD.h000644 000765 000765 00000175770 11143760537 020133 0ustar00jmaynardjmaynard000000 000000 /* ------------------------------------------------------------------------ */ /* Binary Coded Decimal <--> Densely Packed Decimal lookup tables */ /* [Automatically generated -- do not edit. 2006.11.09] */ /* ------------------------------------------------------------------------ */ /* Copyright (c) IBM Corporation, 2000, 2006. All rights reserved. */ /* ------------------------------------------------------------------------ */ /* For details, see: http://www2.hursley.ibm.com/decimal/DPDecimal.html */ /* */ /* This include file defines conversion tables for DPD, as follows. */ /* */ /* uint16_t BCD2DPD[2458]; // BCD -> DPD (0x999 => 2457) */ /* uint16_t BIN2DPD[1000]; // BIN -> DPD (999 => 2457) */ /* uint8_t BIN2CHAR[4001]; // Bin -> CHAR (999 => '\3' '9' '9' '9') */ /* uint16_t DPD2BCD[1024]; // DPD -> BCD (0x3FF => 0x999) */ /* uint16_t DPD2BIN[1024]; // DPD -> BIN (0x3FF => 999) */ /* uint8_t DPD2BCD8[4096]; // DPD -> bytes (x3FF => 9 9 9 3) */ /* */ /* In all cases the result (10 bits or 12 bits, or binary) is right-aligned */ /* in the table entry. BIN2CHAR entries are a single byte length (0 for */ /* value 0) followed by three digit characters; a trailing terminator is */ /* included to allow 4-char moves always. DPD2BCD8 entries are similar */ /* with the three BCD8 digits followed by a one-byte length. */ /* */ /* To use a table, its name, prefixed with DEC_, must be defined with a */ /* value of 1 before this header file is included. For example: */ /* #define DEC_BCD2DPD 1 */ /* ------------------------------------------------------------------------ */ #if DEC_BCD2DPD==1 && !defined(DECBCD2DPD) #define DECBCD2DPD const uint16_t BCD2DPD[2458]={ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, 0, 0, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 0, 0, 0, 0, 0, 0, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 0, 0, 0, 0, 0, 0, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 0, 0, 0, 0, 0, 0, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 0, 0, 0, 0, 0, 0, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 0, 0, 0, 0, 0, 0, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 0, 0, 0, 0, 0, 0, 10, 11, 42, 43, 74, 75, 106, 107, 78, 79, 0, 0, 0, 0, 0, 0, 26, 27, 58, 59, 90, 91, 122, 123, 94, 95, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 11, 42, 43, 74, 75, 106, 107, 78, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 0, 0, 0, 0, 0, 0, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 0, 0, 0, 0, 0, 0, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 0, 0, 0, 0, 0, 0, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 0, 0, 0, 0, 0, 0, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 0, 0, 0, 0, 0, 0, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 0, 0, 0, 0, 0, 0, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 0, 0, 0, 0, 0, 0, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 0, 0, 0, 0, 0, 0, 138, 139, 170, 171, 202, 203, 234, 235, 206, 207, 0, 0, 0, 0, 0, 0, 154, 155, 186, 187, 218, 219, 250, 251, 222, 223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 138, 139, 170, 171, 202, 203, 234, 235, 206, 207, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 0, 0, 0, 0, 0, 0, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 0, 0, 0, 0, 0, 0, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 0, 0, 0, 0, 0, 0, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 0, 0, 0, 0, 0, 0, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 0, 0, 0, 0, 0, 0, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 0, 0, 0, 0, 0, 0, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 0, 0, 0, 0, 0, 0, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 0, 0, 0, 0, 0, 0, 266, 267, 298, 299, 330, 331, 362, 363, 334, 335, 0, 0, 0, 0, 0, 0, 282, 283, 314, 315, 346, 347, 378, 379, 350, 351, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 266, 267, 298, 299, 330, 331, 362, 363, 334, 335, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 0, 0, 0, 0, 0, 0, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 0, 0, 0, 0, 0, 0, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 0, 0, 0, 0, 0, 0, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 0, 0, 0, 0, 0, 0, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 0, 0, 0, 0, 0, 0, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 0, 0, 0, 0, 0, 0, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 0, 0, 0, 0, 0, 0, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 0, 0, 0, 0, 0, 0, 394, 395, 426, 427, 458, 459, 490, 491, 462, 463, 0, 0, 0, 0, 0, 0, 410, 411, 442, 443, 474, 475, 506, 507, 478, 479, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 394, 395, 426, 427, 458, 459, 490, 491, 462, 463, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 0, 0, 0, 0, 0, 0, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 0, 0, 0, 0, 0, 0, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 0, 0, 0, 0, 0, 0, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 0, 0, 0, 0, 0, 0, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 0, 0, 0, 0, 0, 0, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 0, 0, 0, 0, 0, 0, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 0, 0, 0, 0, 0, 0, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 0, 0, 0, 0, 0, 0, 522, 523, 554, 555, 586, 587, 618, 619, 590, 591, 0, 0, 0, 0, 0, 0, 538, 539, 570, 571, 602, 603, 634, 635, 606, 607, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 522, 523, 554, 555, 586, 587, 618, 619, 590, 591, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 0, 0, 0, 0, 0, 0, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 0, 0, 0, 0, 0, 0, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, 0, 0, 0, 0, 0, 0, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 0, 0, 0, 0, 0, 0, 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 0, 0, 0, 0, 0, 0, 720, 721, 722, 723, 724, 725, 726, 727, 728, 729, 0, 0, 0, 0, 0, 0, 736, 737, 738, 739, 740, 741, 742, 743, 744, 745, 0, 0, 0, 0, 0, 0, 752, 753, 754, 755, 756, 757, 758, 759, 760, 761, 0, 0, 0, 0, 0, 0, 650, 651, 682, 683, 714, 715, 746, 747, 718, 719, 0, 0, 0, 0, 0, 0, 666, 667, 698, 699, 730, 731, 762, 763, 734, 735, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 650, 651, 682, 683, 714, 715, 746, 747, 718, 719, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 768, 769, 770, 771, 772, 773, 774, 775, 776, 777, 0, 0, 0, 0, 0, 0, 784, 785, 786, 787, 788, 789, 790, 791, 792, 793, 0, 0, 0, 0, 0, 0, 800, 801, 802, 803, 804, 805, 806, 807, 808, 809, 0, 0, 0, 0, 0, 0, 816, 817, 818, 819, 820, 821, 822, 823, 824, 825, 0, 0, 0, 0, 0, 0, 832, 833, 834, 835, 836, 837, 838, 839, 840, 841, 0, 0, 0, 0, 0, 0, 848, 849, 850, 851, 852, 853, 854, 855, 856, 857, 0, 0, 0, 0, 0, 0, 864, 865, 866, 867, 868, 869, 870, 871, 872, 873, 0, 0, 0, 0, 0, 0, 880, 881, 882, 883, 884, 885, 886, 887, 888, 889, 0, 0, 0, 0, 0, 0, 778, 779, 810, 811, 842, 843, 874, 875, 846, 847, 0, 0, 0, 0, 0, 0, 794, 795, 826, 827, 858, 859, 890, 891, 862, 863, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 778, 779, 810, 811, 842, 843, 874, 875, 846, 847, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 896, 897, 898, 899, 900, 901, 902, 903, 904, 905, 0, 0, 0, 0, 0, 0, 912, 913, 914, 915, 916, 917, 918, 919, 920, 921, 0, 0, 0, 0, 0, 0, 928, 929, 930, 931, 932, 933, 934, 935, 936, 937, 0, 0, 0, 0, 0, 0, 944, 945, 946, 947, 948, 949, 950, 951, 952, 953, 0, 0, 0, 0, 0, 0, 960, 961, 962, 963, 964, 965, 966, 967, 968, 969, 0, 0, 0, 0, 0, 0, 976, 977, 978, 979, 980, 981, 982, 983, 984, 985, 0, 0, 0, 0, 0, 0, 992, 993, 994, 995, 996, 997, 998, 999, 1000, 1001, 0, 0, 0, 0, 0, 0, 1008, 1009, 1010, 1011, 1012, 1013, 1014, 1015, 1016, 1017, 0, 0, 0, 0, 0, 0, 906, 907, 938, 939, 970, 971, 1002, 1003, 974, 975, 0, 0, 0, 0, 0, 0, 922, 923, 954, 955, 986, 987, 1018, 1019, 990, 991, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 906, 907, 938, 939, 970, 971, 1002, 1003, 974, 975, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 13, 268, 269, 524, 525, 780, 781, 46, 47, 0, 0, 0, 0, 0, 0, 28, 29, 284, 285, 540, 541, 796, 797, 62, 63, 0, 0, 0, 0, 0, 0, 44, 45, 300, 301, 556, 557, 812, 813, 302, 303, 0, 0, 0, 0, 0, 0, 60, 61, 316, 317, 572, 573, 828, 829, 318, 319, 0, 0, 0, 0, 0, 0, 76, 77, 332, 333, 588, 589, 844, 845, 558, 559, 0, 0, 0, 0, 0, 0, 92, 93, 348, 349, 604, 605, 860, 861, 574, 575, 0, 0, 0, 0, 0, 0, 108, 109, 364, 365, 620, 621, 876, 877, 814, 815, 0, 0, 0, 0, 0, 0, 124, 125, 380, 381, 636, 637, 892, 893, 830, 831, 0, 0, 0, 0, 0, 0, 14, 15, 270, 271, 526, 527, 782, 783, 110, 111, 0, 0, 0, 0, 0, 0, 30, 31, 286, 287, 542, 543, 798, 799, 126, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 15, 270, 271, 526, 527, 782, 783, 110, 111, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 140, 141, 396, 397, 652, 653, 908, 909, 174, 175, 0, 0, 0, 0, 0, 0, 156, 157, 412, 413, 668, 669, 924, 925, 190, 191, 0, 0, 0, 0, 0, 0, 172, 173, 428, 429, 684, 685, 940, 941, 430, 431, 0, 0, 0, 0, 0, 0, 188, 189, 444, 445, 700, 701, 956, 957, 446, 447, 0, 0, 0, 0, 0, 0, 204, 205, 460, 461, 716, 717, 972, 973, 686, 687, 0, 0, 0, 0, 0, 0, 220, 221, 476, 477, 732, 733, 988, 989, 702, 703, 0, 0, 0, 0, 0, 0, 236, 237, 492, 493, 748, 749, 1004, 1005, 942, 943, 0, 0, 0, 0, 0, 0, 252, 253, 508, 509, 764, 765, 1020, 1021, 958, 959, 0, 0, 0, 0, 0, 0, 142, 143, 398, 399, 654, 655, 910, 911, 238, 239, 0, 0, 0, 0, 0, 0, 158, 159, 414, 415, 670, 671, 926, 927, 254, 255}; #endif #if DEC_DPD2BCD==1 && !defined(DECDPD2BCD) #define DECDPD2BCD const uint16_t DPD2BCD[1024]={ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 128, 129, 2048, 2049, 2176, 2177, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 144, 145, 2064, 2065, 2192, 2193, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 130, 131, 2080, 2081, 2056, 2057, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 146, 147, 2096, 2097, 2072, 2073, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 132, 133, 2112, 2113, 136, 137, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 148, 149, 2128, 2129, 152, 153, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 134, 135, 2144, 2145, 2184, 2185, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 150, 151, 2160, 2161, 2200, 2201, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 384, 385, 2304, 2305, 2432, 2433, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 400, 401, 2320, 2321, 2448, 2449, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 386, 387, 2336, 2337, 2312, 2313, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 402, 403, 2352, 2353, 2328, 2329, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 388, 389, 2368, 2369, 392, 393, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 404, 405, 2384, 2385, 408, 409, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 390, 391, 2400, 2401, 2440, 2441, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 406, 407, 2416, 2417, 2456, 2457, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 640, 641, 2050, 2051, 2178, 2179, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 656, 657, 2066, 2067, 2194, 2195, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 642, 643, 2082, 2083, 2088, 2089, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 658, 659, 2098, 2099, 2104, 2105, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 644, 645, 2114, 2115, 648, 649, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 660, 661, 2130, 2131, 664, 665, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 646, 647, 2146, 2147, 2184, 2185, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 662, 663, 2162, 2163, 2200, 2201, 768, 769, 770, 771, 772, 773, 774, 775, 776, 777, 896, 897, 2306, 2307, 2434, 2435, 784, 785, 786, 787, 788, 789, 790, 791, 792, 793, 912, 913, 2322, 2323, 2450, 2451, 800, 801, 802, 803, 804, 805, 806, 807, 808, 809, 898, 899, 2338, 2339, 2344, 2345, 816, 817, 818, 819, 820, 821, 822, 823, 824, 825, 914, 915, 2354, 2355, 2360, 2361, 832, 833, 834, 835, 836, 837, 838, 839, 840, 841, 900, 901, 2370, 2371, 904, 905, 848, 849, 850, 851, 852, 853, 854, 855, 856, 857, 916, 917, 2386, 2387, 920, 921, 864, 865, 866, 867, 868, 869, 870, 871, 872, 873, 902, 903, 2402, 2403, 2440, 2441, 880, 881, 882, 883, 884, 885, 886, 887, 888, 889, 918, 919, 2418, 2419, 2456, 2457, 1024, 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1032, 1033, 1152, 1153, 2052, 2053, 2180, 2181, 1040, 1041, 1042, 1043, 1044, 1045, 1046, 1047, 1048, 1049, 1168, 1169, 2068, 2069, 2196, 2197, 1056, 1057, 1058, 1059, 1060, 1061, 1062, 1063, 1064, 1065, 1154, 1155, 2084, 2085, 2120, 2121, 1072, 1073, 1074, 1075, 1076, 1077, 1078, 1079, 1080, 1081, 1170, 1171, 2100, 2101, 2136, 2137, 1088, 1089, 1090, 1091, 1092, 1093, 1094, 1095, 1096, 1097, 1156, 1157, 2116, 2117, 1160, 1161, 1104, 1105, 1106, 1107, 1108, 1109, 1110, 1111, 1112, 1113, 1172, 1173, 2132, 2133, 1176, 1177, 1120, 1121, 1122, 1123, 1124, 1125, 1126, 1127, 1128, 1129, 1158, 1159, 2148, 2149, 2184, 2185, 1136, 1137, 1138, 1139, 1140, 1141, 1142, 1143, 1144, 1145, 1174, 1175, 2164, 2165, 2200, 2201, 1280, 1281, 1282, 1283, 1284, 1285, 1286, 1287, 1288, 1289, 1408, 1409, 2308, 2309, 2436, 2437, 1296, 1297, 1298, 1299, 1300, 1301, 1302, 1303, 1304, 1305, 1424, 1425, 2324, 2325, 2452, 2453, 1312, 1313, 1314, 1315, 1316, 1317, 1318, 1319, 1320, 1321, 1410, 1411, 2340, 2341, 2376, 2377, 1328, 1329, 1330, 1331, 1332, 1333, 1334, 1335, 1336, 1337, 1426, 1427, 2356, 2357, 2392, 2393, 1344, 1345, 1346, 1347, 1348, 1349, 1350, 1351, 1352, 1353, 1412, 1413, 2372, 2373, 1416, 1417, 1360, 1361, 1362, 1363, 1364, 1365, 1366, 1367, 1368, 1369, 1428, 1429, 2388, 2389, 1432, 1433, 1376, 1377, 1378, 1379, 1380, 1381, 1382, 1383, 1384, 1385, 1414, 1415, 2404, 2405, 2440, 2441, 1392, 1393, 1394, 1395, 1396, 1397, 1398, 1399, 1400, 1401, 1430, 1431, 2420, 2421, 2456, 2457, 1536, 1537, 1538, 1539, 1540, 1541, 1542, 1543, 1544, 1545, 1664, 1665, 2054, 2055, 2182, 2183, 1552, 1553, 1554, 1555, 1556, 1557, 1558, 1559, 1560, 1561, 1680, 1681, 2070, 2071, 2198, 2199, 1568, 1569, 1570, 1571, 1572, 1573, 1574, 1575, 1576, 1577, 1666, 1667, 2086, 2087, 2152, 2153, 1584, 1585, 1586, 1587, 1588, 1589, 1590, 1591, 1592, 1593, 1682, 1683, 2102, 2103, 2168, 2169, 1600, 1601, 1602, 1603, 1604, 1605, 1606, 1607, 1608, 1609, 1668, 1669, 2118, 2119, 1672, 1673, 1616, 1617, 1618, 1619, 1620, 1621, 1622, 1623, 1624, 1625, 1684, 1685, 2134, 2135, 1688, 1689, 1632, 1633, 1634, 1635, 1636, 1637, 1638, 1639, 1640, 1641, 1670, 1671, 2150, 2151, 2184, 2185, 1648, 1649, 1650, 1651, 1652, 1653, 1654, 1655, 1656, 1657, 1686, 1687, 2166, 2167, 2200, 2201, 1792, 1793, 1794, 1795, 1796, 1797, 1798, 1799, 1800, 1801, 1920, 1921, 2310, 2311, 2438, 2439, 1808, 1809, 1810, 1811, 1812, 1813, 1814, 1815, 1816, 1817, 1936, 1937, 2326, 2327, 2454, 2455, 1824, 1825, 1826, 1827, 1828, 1829, 1830, 1831, 1832, 1833, 1922, 1923, 2342, 2343, 2408, 2409, 1840, 1841, 1842, 1843, 1844, 1845, 1846, 1847, 1848, 1849, 1938, 1939, 2358, 2359, 2424, 2425, 1856, 1857, 1858, 1859, 1860, 1861, 1862, 1863, 1864, 1865, 1924, 1925, 2374, 2375, 1928, 1929, 1872, 1873, 1874, 1875, 1876, 1877, 1878, 1879, 1880, 1881, 1940, 1941, 2390, 2391, 1944, 1945, 1888, 1889, 1890, 1891, 1892, 1893, 1894, 1895, 1896, 1897, 1926, 1927, 2406, 2407, 2440, 2441, 1904, 1905, 1906, 1907, 1908, 1909, 1910, 1911, 1912, 1913, 1942, 1943, 2422, 2423, 2456, 2457}; #endif #if DEC_BIN2DPD==1 && !defined(DECBIN2DPD) #define DECBIN2DPD const uint16_t BIN2DPD[1000]={ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 10, 11, 42, 43, 74, 75, 106, 107, 78, 79, 26, 27, 58, 59, 90, 91, 122, 123, 94, 95, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 138, 139, 170, 171, 202, 203, 234, 235, 206, 207, 154, 155, 186, 187, 218, 219, 250, 251, 222, 223, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 266, 267, 298, 299, 330, 331, 362, 363, 334, 335, 282, 283, 314, 315, 346, 347, 378, 379, 350, 351, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 394, 395, 426, 427, 458, 459, 490, 491, 462, 463, 410, 411, 442, 443, 474, 475, 506, 507, 478, 479, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 522, 523, 554, 555, 586, 587, 618, 619, 590, 591, 538, 539, 570, 571, 602, 603, 634, 635, 606, 607, 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 720, 721, 722, 723, 724, 725, 726, 727, 728, 729, 736, 737, 738, 739, 740, 741, 742, 743, 744, 745, 752, 753, 754, 755, 756, 757, 758, 759, 760, 761, 650, 651, 682, 683, 714, 715, 746, 747, 718, 719, 666, 667, 698, 699, 730, 731, 762, 763, 734, 735, 768, 769, 770, 771, 772, 773, 774, 775, 776, 777, 784, 785, 786, 787, 788, 789, 790, 791, 792, 793, 800, 801, 802, 803, 804, 805, 806, 807, 808, 809, 816, 817, 818, 819, 820, 821, 822, 823, 824, 825, 832, 833, 834, 835, 836, 837, 838, 839, 840, 841, 848, 849, 850, 851, 852, 853, 854, 855, 856, 857, 864, 865, 866, 867, 868, 869, 870, 871, 872, 873, 880, 881, 882, 883, 884, 885, 886, 887, 888, 889, 778, 779, 810, 811, 842, 843, 874, 875, 846, 847, 794, 795, 826, 827, 858, 859, 890, 891, 862, 863, 896, 897, 898, 899, 900, 901, 902, 903, 904, 905, 912, 913, 914, 915, 916, 917, 918, 919, 920, 921, 928, 929, 930, 931, 932, 933, 934, 935, 936, 937, 944, 945, 946, 947, 948, 949, 950, 951, 952, 953, 960, 961, 962, 963, 964, 965, 966, 967, 968, 969, 976, 977, 978, 979, 980, 981, 982, 983, 984, 985, 992, 993, 994, 995, 996, 997, 998, 999, 1000, 1001, 1008, 1009, 1010, 1011, 1012, 1013, 1014, 1015, 1016, 1017, 906, 907, 938, 939, 970, 971, 1002, 1003, 974, 975, 922, 923, 954, 955, 986, 987, 1018, 1019, 990, 991, 12, 13, 268, 269, 524, 525, 780, 781, 46, 47, 28, 29, 284, 285, 540, 541, 796, 797, 62, 63, 44, 45, 300, 301, 556, 557, 812, 813, 302, 303, 60, 61, 316, 317, 572, 573, 828, 829, 318, 319, 76, 77, 332, 333, 588, 589, 844, 845, 558, 559, 92, 93, 348, 349, 604, 605, 860, 861, 574, 575, 108, 109, 364, 365, 620, 621, 876, 877, 814, 815, 124, 125, 380, 381, 636, 637, 892, 893, 830, 831, 14, 15, 270, 271, 526, 527, 782, 783, 110, 111, 30, 31, 286, 287, 542, 543, 798, 799, 126, 127, 140, 141, 396, 397, 652, 653, 908, 909, 174, 175, 156, 157, 412, 413, 668, 669, 924, 925, 190, 191, 172, 173, 428, 429, 684, 685, 940, 941, 430, 431, 188, 189, 444, 445, 700, 701, 956, 957, 446, 447, 204, 205, 460, 461, 716, 717, 972, 973, 686, 687, 220, 221, 476, 477, 732, 733, 988, 989, 702, 703, 236, 237, 492, 493, 748, 749, 1004, 1005, 942, 943, 252, 253, 508, 509, 764, 765, 1020, 1021, 958, 959, 142, 143, 398, 399, 654, 655, 910, 911, 238, 239, 158, 159, 414, 415, 670, 671, 926, 927, 254, 255}; #endif #if DEC_DPD2BIN==1 && !defined(DECDPD2BIN) #define DECDPD2BIN const uint16_t DPD2BIN[1024]={ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 80, 81, 800, 801, 880, 881, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 90, 91, 810, 811, 890, 891, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 82, 83, 820, 821, 808, 809, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 92, 93, 830, 831, 818, 819, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 84, 85, 840, 841, 88, 89, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 94, 95, 850, 851, 98, 99, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 86, 87, 860, 861, 888, 889, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 96, 97, 870, 871, 898, 899, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 180, 181, 900, 901, 980, 981, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 190, 191, 910, 911, 990, 991, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 182, 183, 920, 921, 908, 909, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 192, 193, 930, 931, 918, 919, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 184, 185, 940, 941, 188, 189, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 194, 195, 950, 951, 198, 199, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 186, 187, 960, 961, 988, 989, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 196, 197, 970, 971, 998, 999, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 280, 281, 802, 803, 882, 883, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 290, 291, 812, 813, 892, 893, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 282, 283, 822, 823, 828, 829, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 292, 293, 832, 833, 838, 839, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 284, 285, 842, 843, 288, 289, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 294, 295, 852, 853, 298, 299, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 286, 287, 862, 863, 888, 889, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 296, 297, 872, 873, 898, 899, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 380, 381, 902, 903, 982, 983, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 390, 391, 912, 913, 992, 993, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 382, 383, 922, 923, 928, 929, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 392, 393, 932, 933, 938, 939, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 384, 385, 942, 943, 388, 389, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 394, 395, 952, 953, 398, 399, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 386, 387, 962, 963, 988, 989, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 396, 397, 972, 973, 998, 999, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 480, 481, 804, 805, 884, 885, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 490, 491, 814, 815, 894, 895, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 482, 483, 824, 825, 848, 849, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 492, 493, 834, 835, 858, 859, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 484, 485, 844, 845, 488, 489, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 494, 495, 854, 855, 498, 499, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 486, 487, 864, 865, 888, 889, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 496, 497, 874, 875, 898, 899, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 580, 581, 904, 905, 984, 985, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 590, 591, 914, 915, 994, 995, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 582, 583, 924, 925, 948, 949, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 592, 593, 934, 935, 958, 959, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 584, 585, 944, 945, 588, 589, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 594, 595, 954, 955, 598, 599, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 586, 587, 964, 965, 988, 989, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 596, 597, 974, 975, 998, 999, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 680, 681, 806, 807, 886, 887, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619, 690, 691, 816, 817, 896, 897, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 682, 683, 826, 827, 868, 869, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 692, 693, 836, 837, 878, 879, 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 684, 685, 846, 847, 688, 689, 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, 694, 695, 856, 857, 698, 699, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 686, 687, 866, 867, 888, 889, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 696, 697, 876, 877, 898, 899, 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 780, 781, 906, 907, 986, 987, 710, 711, 712, 713, 714, 715, 716, 717, 718, 719, 790, 791, 916, 917, 996, 997, 720, 721, 722, 723, 724, 725, 726, 727, 728, 729, 782, 783, 926, 927, 968, 969, 730, 731, 732, 733, 734, 735, 736, 737, 738, 739, 792, 793, 936, 937, 978, 979, 740, 741, 742, 743, 744, 745, 746, 747, 748, 749, 784, 785, 946, 947, 788, 789, 750, 751, 752, 753, 754, 755, 756, 757, 758, 759, 794, 795, 956, 957, 798, 799, 760, 761, 762, 763, 764, 765, 766, 767, 768, 769, 786, 787, 966, 967, 988, 989, 770, 771, 772, 773, 774, 775, 776, 777, 778, 779, 796, 797, 976, 977, 998, 999}; #endif #if DEC_BIN2CHAR==1 && !defined(DECBIN2CHAR) #define DECBIN2CHAR const uint8_t BIN2CHAR[4001]={ '\0','0','0','0', '\1','0','0','1', '\1','0','0','2', '\1','0','0','3', '\1','0','0','4', '\1','0','0','5', '\1','0','0','6', '\1','0','0','7', '\1','0','0','8', '\1','0','0','9', '\2','0','1','0', '\2','0','1','1', '\2','0','1','2', '\2','0','1','3', '\2','0','1','4', '\2','0','1','5', '\2','0','1','6', '\2','0','1','7', '\2','0','1','8', '\2','0','1','9', '\2','0','2','0', '\2','0','2','1', '\2','0','2','2', '\2','0','2','3', '\2','0','2','4', '\2','0','2','5', '\2','0','2','6', '\2','0','2','7', '\2','0','2','8', '\2','0','2','9', '\2','0','3','0', '\2','0','3','1', '\2','0','3','2', '\2','0','3','3', '\2','0','3','4', '\2','0','3','5', '\2','0','3','6', '\2','0','3','7', '\2','0','3','8', '\2','0','3','9', '\2','0','4','0', '\2','0','4','1', '\2','0','4','2', '\2','0','4','3', '\2','0','4','4', '\2','0','4','5', '\2','0','4','6', '\2','0','4','7', '\2','0','4','8', '\2','0','4','9', '\2','0','5','0', '\2','0','5','1', '\2','0','5','2', '\2','0','5','3', '\2','0','5','4', '\2','0','5','5', '\2','0','5','6', '\2','0','5','7', '\2','0','5','8', '\2','0','5','9', '\2','0','6','0', '\2','0','6','1', '\2','0','6','2', '\2','0','6','3', '\2','0','6','4', '\2','0','6','5', '\2','0','6','6', '\2','0','6','7', '\2','0','6','8', '\2','0','6','9', '\2','0','7','0', '\2','0','7','1', '\2','0','7','2', '\2','0','7','3', '\2','0','7','4', '\2','0','7','5', '\2','0','7','6', '\2','0','7','7', '\2','0','7','8', '\2','0','7','9', '\2','0','8','0', '\2','0','8','1', '\2','0','8','2', '\2','0','8','3', '\2','0','8','4', '\2','0','8','5', '\2','0','8','6', '\2','0','8','7', '\2','0','8','8', '\2','0','8','9', '\2','0','9','0', '\2','0','9','1', '\2','0','9','2', '\2','0','9','3', '\2','0','9','4', '\2','0','9','5', '\2','0','9','6', '\2','0','9','7', '\2','0','9','8', '\2','0','9','9', '\3','1','0','0', '\3','1','0','1', '\3','1','0','2', '\3','1','0','3', '\3','1','0','4', '\3','1','0','5', '\3','1','0','6', '\3','1','0','7', '\3','1','0','8', '\3','1','0','9', '\3','1','1','0', '\3','1','1','1', '\3','1','1','2', '\3','1','1','3', '\3','1','1','4', '\3','1','1','5', '\3','1','1','6', '\3','1','1','7', '\3','1','1','8', '\3','1','1','9', '\3','1','2','0', '\3','1','2','1', '\3','1','2','2', '\3','1','2','3', '\3','1','2','4', '\3','1','2','5', '\3','1','2','6', '\3','1','2','7', '\3','1','2','8', '\3','1','2','9', '\3','1','3','0', '\3','1','3','1', '\3','1','3','2', '\3','1','3','3', '\3','1','3','4', '\3','1','3','5', '\3','1','3','6', '\3','1','3','7', '\3','1','3','8', '\3','1','3','9', '\3','1','4','0', '\3','1','4','1', '\3','1','4','2', '\3','1','4','3', '\3','1','4','4', '\3','1','4','5', '\3','1','4','6', '\3','1','4','7', '\3','1','4','8', '\3','1','4','9', '\3','1','5','0', '\3','1','5','1', '\3','1','5','2', '\3','1','5','3', '\3','1','5','4', '\3','1','5','5', '\3','1','5','6', '\3','1','5','7', '\3','1','5','8', '\3','1','5','9', '\3','1','6','0', '\3','1','6','1', '\3','1','6','2', '\3','1','6','3', '\3','1','6','4', '\3','1','6','5', '\3','1','6','6', '\3','1','6','7', '\3','1','6','8', '\3','1','6','9', '\3','1','7','0', '\3','1','7','1', '\3','1','7','2', '\3','1','7','3', '\3','1','7','4', '\3','1','7','5', '\3','1','7','6', '\3','1','7','7', '\3','1','7','8', '\3','1','7','9', '\3','1','8','0', '\3','1','8','1', '\3','1','8','2', '\3','1','8','3', '\3','1','8','4', '\3','1','8','5', '\3','1','8','6', '\3','1','8','7', '\3','1','8','8', '\3','1','8','9', '\3','1','9','0', '\3','1','9','1', '\3','1','9','2', '\3','1','9','3', '\3','1','9','4', '\3','1','9','5', '\3','1','9','6', '\3','1','9','7', '\3','1','9','8', '\3','1','9','9', '\3','2','0','0', '\3','2','0','1', '\3','2','0','2', '\3','2','0','3', '\3','2','0','4', '\3','2','0','5', '\3','2','0','6', '\3','2','0','7', '\3','2','0','8', '\3','2','0','9', '\3','2','1','0', '\3','2','1','1', '\3','2','1','2', '\3','2','1','3', '\3','2','1','4', '\3','2','1','5', '\3','2','1','6', '\3','2','1','7', '\3','2','1','8', '\3','2','1','9', '\3','2','2','0', '\3','2','2','1', '\3','2','2','2', '\3','2','2','3', '\3','2','2','4', '\3','2','2','5', '\3','2','2','6', '\3','2','2','7', '\3','2','2','8', '\3','2','2','9', '\3','2','3','0', '\3','2','3','1', '\3','2','3','2', '\3','2','3','3', '\3','2','3','4', '\3','2','3','5', '\3','2','3','6', '\3','2','3','7', '\3','2','3','8', '\3','2','3','9', '\3','2','4','0', '\3','2','4','1', '\3','2','4','2', '\3','2','4','3', '\3','2','4','4', '\3','2','4','5', '\3','2','4','6', '\3','2','4','7', '\3','2','4','8', '\3','2','4','9', '\3','2','5','0', '\3','2','5','1', '\3','2','5','2', '\3','2','5','3', '\3','2','5','4', '\3','2','5','5', '\3','2','5','6', '\3','2','5','7', '\3','2','5','8', '\3','2','5','9', '\3','2','6','0', '\3','2','6','1', '\3','2','6','2', '\3','2','6','3', '\3','2','6','4', '\3','2','6','5', '\3','2','6','6', '\3','2','6','7', '\3','2','6','8', '\3','2','6','9', '\3','2','7','0', '\3','2','7','1', '\3','2','7','2', '\3','2','7','3', '\3','2','7','4', '\3','2','7','5', '\3','2','7','6', '\3','2','7','7', '\3','2','7','8', '\3','2','7','9', '\3','2','8','0', '\3','2','8','1', '\3','2','8','2', '\3','2','8','3', '\3','2','8','4', '\3','2','8','5', '\3','2','8','6', '\3','2','8','7', '\3','2','8','8', '\3','2','8','9', '\3','2','9','0', '\3','2','9','1', '\3','2','9','2', '\3','2','9','3', '\3','2','9','4', '\3','2','9','5', '\3','2','9','6', '\3','2','9','7', '\3','2','9','8', '\3','2','9','9', '\3','3','0','0', '\3','3','0','1', '\3','3','0','2', '\3','3','0','3', '\3','3','0','4', '\3','3','0','5', '\3','3','0','6', '\3','3','0','7', '\3','3','0','8', '\3','3','0','9', '\3','3','1','0', '\3','3','1','1', '\3','3','1','2', '\3','3','1','3', '\3','3','1','4', '\3','3','1','5', '\3','3','1','6', '\3','3','1','7', '\3','3','1','8', '\3','3','1','9', '\3','3','2','0', '\3','3','2','1', '\3','3','2','2', '\3','3','2','3', '\3','3','2','4', '\3','3','2','5', '\3','3','2','6', '\3','3','2','7', '\3','3','2','8', '\3','3','2','9', '\3','3','3','0', '\3','3','3','1', '\3','3','3','2', '\3','3','3','3', '\3','3','3','4', '\3','3','3','5', '\3','3','3','6', '\3','3','3','7', '\3','3','3','8', '\3','3','3','9', '\3','3','4','0', '\3','3','4','1', '\3','3','4','2', '\3','3','4','3', '\3','3','4','4', '\3','3','4','5', '\3','3','4','6', '\3','3','4','7', '\3','3','4','8', '\3','3','4','9', '\3','3','5','0', '\3','3','5','1', '\3','3','5','2', '\3','3','5','3', '\3','3','5','4', '\3','3','5','5', '\3','3','5','6', '\3','3','5','7', '\3','3','5','8', '\3','3','5','9', '\3','3','6','0', '\3','3','6','1', '\3','3','6','2', '\3','3','6','3', '\3','3','6','4', '\3','3','6','5', '\3','3','6','6', '\3','3','6','7', '\3','3','6','8', '\3','3','6','9', '\3','3','7','0', '\3','3','7','1', '\3','3','7','2', '\3','3','7','3', '\3','3','7','4', '\3','3','7','5', '\3','3','7','6', '\3','3','7','7', '\3','3','7','8', '\3','3','7','9', '\3','3','8','0', '\3','3','8','1', '\3','3','8','2', '\3','3','8','3', '\3','3','8','4', '\3','3','8','5', '\3','3','8','6', '\3','3','8','7', '\3','3','8','8', '\3','3','8','9', '\3','3','9','0', '\3','3','9','1', '\3','3','9','2', '\3','3','9','3', '\3','3','9','4', '\3','3','9','5', '\3','3','9','6', '\3','3','9','7', '\3','3','9','8', '\3','3','9','9', '\3','4','0','0', '\3','4','0','1', '\3','4','0','2', '\3','4','0','3', '\3','4','0','4', '\3','4','0','5', '\3','4','0','6', '\3','4','0','7', '\3','4','0','8', '\3','4','0','9', '\3','4','1','0', '\3','4','1','1', '\3','4','1','2', '\3','4','1','3', '\3','4','1','4', '\3','4','1','5', '\3','4','1','6', '\3','4','1','7', '\3','4','1','8', '\3','4','1','9', '\3','4','2','0', '\3','4','2','1', '\3','4','2','2', '\3','4','2','3', '\3','4','2','4', '\3','4','2','5', '\3','4','2','6', '\3','4','2','7', '\3','4','2','8', '\3','4','2','9', '\3','4','3','0', '\3','4','3','1', '\3','4','3','2', '\3','4','3','3', '\3','4','3','4', '\3','4','3','5', '\3','4','3','6', '\3','4','3','7', '\3','4','3','8', '\3','4','3','9', '\3','4','4','0', '\3','4','4','1', '\3','4','4','2', '\3','4','4','3', '\3','4','4','4', '\3','4','4','5', '\3','4','4','6', '\3','4','4','7', '\3','4','4','8', '\3','4','4','9', '\3','4','5','0', '\3','4','5','1', '\3','4','5','2', '\3','4','5','3', '\3','4','5','4', '\3','4','5','5', '\3','4','5','6', '\3','4','5','7', '\3','4','5','8', '\3','4','5','9', '\3','4','6','0', '\3','4','6','1', '\3','4','6','2', '\3','4','6','3', '\3','4','6','4', '\3','4','6','5', '\3','4','6','6', '\3','4','6','7', '\3','4','6','8', '\3','4','6','9', '\3','4','7','0', '\3','4','7','1', '\3','4','7','2', '\3','4','7','3', '\3','4','7','4', '\3','4','7','5', '\3','4','7','6', '\3','4','7','7', '\3','4','7','8', '\3','4','7','9', '\3','4','8','0', '\3','4','8','1', '\3','4','8','2', '\3','4','8','3', '\3','4','8','4', '\3','4','8','5', '\3','4','8','6', '\3','4','8','7', '\3','4','8','8', '\3','4','8','9', '\3','4','9','0', '\3','4','9','1', '\3','4','9','2', '\3','4','9','3', '\3','4','9','4', '\3','4','9','5', '\3','4','9','6', '\3','4','9','7', '\3','4','9','8', '\3','4','9','9', '\3','5','0','0', '\3','5','0','1', '\3','5','0','2', '\3','5','0','3', '\3','5','0','4', '\3','5','0','5', '\3','5','0','6', '\3','5','0','7', '\3','5','0','8', '\3','5','0','9', '\3','5','1','0', '\3','5','1','1', '\3','5','1','2', '\3','5','1','3', '\3','5','1','4', '\3','5','1','5', '\3','5','1','6', '\3','5','1','7', '\3','5','1','8', '\3','5','1','9', '\3','5','2','0', '\3','5','2','1', '\3','5','2','2', '\3','5','2','3', '\3','5','2','4', '\3','5','2','5', '\3','5','2','6', '\3','5','2','7', '\3','5','2','8', '\3','5','2','9', '\3','5','3','0', '\3','5','3','1', '\3','5','3','2', '\3','5','3','3', '\3','5','3','4', '\3','5','3','5', '\3','5','3','6', '\3','5','3','7', '\3','5','3','8', '\3','5','3','9', '\3','5','4','0', '\3','5','4','1', '\3','5','4','2', '\3','5','4','3', '\3','5','4','4', '\3','5','4','5', '\3','5','4','6', '\3','5','4','7', '\3','5','4','8', '\3','5','4','9', '\3','5','5','0', '\3','5','5','1', '\3','5','5','2', '\3','5','5','3', '\3','5','5','4', '\3','5','5','5', '\3','5','5','6', '\3','5','5','7', '\3','5','5','8', '\3','5','5','9', '\3','5','6','0', '\3','5','6','1', '\3','5','6','2', '\3','5','6','3', '\3','5','6','4', '\3','5','6','5', '\3','5','6','6', '\3','5','6','7', '\3','5','6','8', '\3','5','6','9', '\3','5','7','0', '\3','5','7','1', '\3','5','7','2', '\3','5','7','3', '\3','5','7','4', '\3','5','7','5', '\3','5','7','6', '\3','5','7','7', '\3','5','7','8', '\3','5','7','9', '\3','5','8','0', '\3','5','8','1', '\3','5','8','2', '\3','5','8','3', '\3','5','8','4', '\3','5','8','5', '\3','5','8','6', '\3','5','8','7', '\3','5','8','8', '\3','5','8','9', '\3','5','9','0', '\3','5','9','1', '\3','5','9','2', '\3','5','9','3', '\3','5','9','4', '\3','5','9','5', '\3','5','9','6', '\3','5','9','7', '\3','5','9','8', '\3','5','9','9', '\3','6','0','0', '\3','6','0','1', '\3','6','0','2', '\3','6','0','3', '\3','6','0','4', '\3','6','0','5', '\3','6','0','6', '\3','6','0','7', '\3','6','0','8', '\3','6','0','9', '\3','6','1','0', '\3','6','1','1', '\3','6','1','2', '\3','6','1','3', '\3','6','1','4', '\3','6','1','5', '\3','6','1','6', '\3','6','1','7', '\3','6','1','8', '\3','6','1','9', '\3','6','2','0', '\3','6','2','1', '\3','6','2','2', '\3','6','2','3', '\3','6','2','4', '\3','6','2','5', '\3','6','2','6', '\3','6','2','7', '\3','6','2','8', '\3','6','2','9', '\3','6','3','0', '\3','6','3','1', '\3','6','3','2', '\3','6','3','3', '\3','6','3','4', '\3','6','3','5', '\3','6','3','6', '\3','6','3','7', '\3','6','3','8', '\3','6','3','9', '\3','6','4','0', '\3','6','4','1', '\3','6','4','2', '\3','6','4','3', '\3','6','4','4', '\3','6','4','5', '\3','6','4','6', '\3','6','4','7', '\3','6','4','8', '\3','6','4','9', '\3','6','5','0', '\3','6','5','1', '\3','6','5','2', '\3','6','5','3', '\3','6','5','4', '\3','6','5','5', '\3','6','5','6', '\3','6','5','7', '\3','6','5','8', '\3','6','5','9', '\3','6','6','0', '\3','6','6','1', '\3','6','6','2', '\3','6','6','3', '\3','6','6','4', '\3','6','6','5', '\3','6','6','6', '\3','6','6','7', '\3','6','6','8', '\3','6','6','9', '\3','6','7','0', '\3','6','7','1', '\3','6','7','2', '\3','6','7','3', '\3','6','7','4', '\3','6','7','5', '\3','6','7','6', '\3','6','7','7', '\3','6','7','8', '\3','6','7','9', '\3','6','8','0', '\3','6','8','1', '\3','6','8','2', '\3','6','8','3', '\3','6','8','4', '\3','6','8','5', '\3','6','8','6', '\3','6','8','7', '\3','6','8','8', '\3','6','8','9', '\3','6','9','0', '\3','6','9','1', '\3','6','9','2', '\3','6','9','3', '\3','6','9','4', '\3','6','9','5', '\3','6','9','6', '\3','6','9','7', '\3','6','9','8', '\3','6','9','9', '\3','7','0','0', '\3','7','0','1', '\3','7','0','2', '\3','7','0','3', '\3','7','0','4', '\3','7','0','5', '\3','7','0','6', '\3','7','0','7', '\3','7','0','8', '\3','7','0','9', '\3','7','1','0', '\3','7','1','1', '\3','7','1','2', '\3','7','1','3', '\3','7','1','4', '\3','7','1','5', '\3','7','1','6', '\3','7','1','7', '\3','7','1','8', '\3','7','1','9', '\3','7','2','0', '\3','7','2','1', '\3','7','2','2', '\3','7','2','3', '\3','7','2','4', '\3','7','2','5', '\3','7','2','6', '\3','7','2','7', '\3','7','2','8', '\3','7','2','9', '\3','7','3','0', '\3','7','3','1', '\3','7','3','2', '\3','7','3','3', '\3','7','3','4', '\3','7','3','5', '\3','7','3','6', '\3','7','3','7', '\3','7','3','8', '\3','7','3','9', '\3','7','4','0', '\3','7','4','1', '\3','7','4','2', '\3','7','4','3', '\3','7','4','4', '\3','7','4','5', '\3','7','4','6', '\3','7','4','7', '\3','7','4','8', '\3','7','4','9', '\3','7','5','0', '\3','7','5','1', '\3','7','5','2', '\3','7','5','3', '\3','7','5','4', '\3','7','5','5', '\3','7','5','6', '\3','7','5','7', '\3','7','5','8', '\3','7','5','9', '\3','7','6','0', '\3','7','6','1', '\3','7','6','2', '\3','7','6','3', '\3','7','6','4', '\3','7','6','5', '\3','7','6','6', '\3','7','6','7', '\3','7','6','8', '\3','7','6','9', '\3','7','7','0', '\3','7','7','1', '\3','7','7','2', '\3','7','7','3', '\3','7','7','4', '\3','7','7','5', '\3','7','7','6', '\3','7','7','7', '\3','7','7','8', '\3','7','7','9', '\3','7','8','0', '\3','7','8','1', '\3','7','8','2', '\3','7','8','3', '\3','7','8','4', '\3','7','8','5', '\3','7','8','6', '\3','7','8','7', '\3','7','8','8', '\3','7','8','9', '\3','7','9','0', '\3','7','9','1', '\3','7','9','2', '\3','7','9','3', '\3','7','9','4', '\3','7','9','5', '\3','7','9','6', '\3','7','9','7', '\3','7','9','8', '\3','7','9','9', '\3','8','0','0', '\3','8','0','1', '\3','8','0','2', '\3','8','0','3', '\3','8','0','4', '\3','8','0','5', '\3','8','0','6', '\3','8','0','7', '\3','8','0','8', '\3','8','0','9', '\3','8','1','0', '\3','8','1','1', '\3','8','1','2', '\3','8','1','3', '\3','8','1','4', '\3','8','1','5', '\3','8','1','6', '\3','8','1','7', '\3','8','1','8', '\3','8','1','9', '\3','8','2','0', '\3','8','2','1', '\3','8','2','2', '\3','8','2','3', '\3','8','2','4', '\3','8','2','5', '\3','8','2','6', '\3','8','2','7', '\3','8','2','8', '\3','8','2','9', '\3','8','3','0', '\3','8','3','1', '\3','8','3','2', '\3','8','3','3', '\3','8','3','4', '\3','8','3','5', '\3','8','3','6', '\3','8','3','7', '\3','8','3','8', '\3','8','3','9', '\3','8','4','0', '\3','8','4','1', '\3','8','4','2', '\3','8','4','3', '\3','8','4','4', '\3','8','4','5', '\3','8','4','6', '\3','8','4','7', '\3','8','4','8', '\3','8','4','9', '\3','8','5','0', '\3','8','5','1', '\3','8','5','2', '\3','8','5','3', '\3','8','5','4', '\3','8','5','5', '\3','8','5','6', '\3','8','5','7', '\3','8','5','8', '\3','8','5','9', '\3','8','6','0', '\3','8','6','1', '\3','8','6','2', '\3','8','6','3', '\3','8','6','4', '\3','8','6','5', '\3','8','6','6', '\3','8','6','7', '\3','8','6','8', '\3','8','6','9', '\3','8','7','0', '\3','8','7','1', '\3','8','7','2', '\3','8','7','3', '\3','8','7','4', '\3','8','7','5', '\3','8','7','6', '\3','8','7','7', '\3','8','7','8', '\3','8','7','9', '\3','8','8','0', '\3','8','8','1', '\3','8','8','2', '\3','8','8','3', '\3','8','8','4', '\3','8','8','5', '\3','8','8','6', '\3','8','8','7', '\3','8','8','8', '\3','8','8','9', '\3','8','9','0', '\3','8','9','1', '\3','8','9','2', '\3','8','9','3', '\3','8','9','4', '\3','8','9','5', '\3','8','9','6', '\3','8','9','7', '\3','8','9','8', '\3','8','9','9', '\3','9','0','0', '\3','9','0','1', '\3','9','0','2', '\3','9','0','3', '\3','9','0','4', '\3','9','0','5', '\3','9','0','6', '\3','9','0','7', '\3','9','0','8', '\3','9','0','9', '\3','9','1','0', '\3','9','1','1', '\3','9','1','2', '\3','9','1','3', '\3','9','1','4', '\3','9','1','5', '\3','9','1','6', '\3','9','1','7', '\3','9','1','8', '\3','9','1','9', '\3','9','2','0', '\3','9','2','1', '\3','9','2','2', '\3','9','2','3', '\3','9','2','4', '\3','9','2','5', '\3','9','2','6', '\3','9','2','7', '\3','9','2','8', '\3','9','2','9', '\3','9','3','0', '\3','9','3','1', '\3','9','3','2', '\3','9','3','3', '\3','9','3','4', '\3','9','3','5', '\3','9','3','6', '\3','9','3','7', '\3','9','3','8', '\3','9','3','9', '\3','9','4','0', '\3','9','4','1', '\3','9','4','2', '\3','9','4','3', '\3','9','4','4', '\3','9','4','5', '\3','9','4','6', '\3','9','4','7', '\3','9','4','8', '\3','9','4','9', '\3','9','5','0', '\3','9','5','1', '\3','9','5','2', '\3','9','5','3', '\3','9','5','4', '\3','9','5','5', '\3','9','5','6', '\3','9','5','7', '\3','9','5','8', '\3','9','5','9', '\3','9','6','0', '\3','9','6','1', '\3','9','6','2', '\3','9','6','3', '\3','9','6','4', '\3','9','6','5', '\3','9','6','6', '\3','9','6','7', '\3','9','6','8', '\3','9','6','9', '\3','9','7','0', '\3','9','7','1', '\3','9','7','2', '\3','9','7','3', '\3','9','7','4', '\3','9','7','5', '\3','9','7','6', '\3','9','7','7', '\3','9','7','8', '\3','9','7','9', '\3','9','8','0', '\3','9','8','1', '\3','9','8','2', '\3','9','8','3', '\3','9','8','4', '\3','9','8','5', '\3','9','8','6', '\3','9','8','7', '\3','9','8','8', '\3','9','8','9', '\3','9','9','0', '\3','9','9','1', '\3','9','9','2', '\3','9','9','3', '\3','9','9','4', '\3','9','9','5', '\3','9','9','6', '\3','9','9','7', '\3','9','9','8', '\3','9','9','9', '\0'}; #endif #if DEC_DPD2BCD8==1 && !defined(DECDPD2BCD8) #define DECDPD2BCD8 const uint8_t DPD2BCD8[4096]={ 0,0,0,0, 0,0,1,1, 0,0,2,1, 0,0,3,1, 0,0,4,1, 0,0,5,1, 0,0,6,1, 0,0,7,1, 0,0,8,1, 0,0,9,1, 0,8,0,2, 0,8,1,2, 8,0,0,3, 8,0,1,3, 8,8,0,3, 8,8,1,3, 0,1,0,2, 0,1,1,2, 0,1,2,2, 0,1,3,2, 0,1,4,2, 0,1,5,2, 0,1,6,2, 0,1,7,2, 0,1,8,2, 0,1,9,2, 0,9,0,2, 0,9,1,2, 8,1,0,3, 8,1,1,3, 8,9,0,3, 8,9,1,3, 0,2,0,2, 0,2,1,2, 0,2,2,2, 0,2,3,2, 0,2,4,2, 0,2,5,2, 0,2,6,2, 0,2,7,2, 0,2,8,2, 0,2,9,2, 0,8,2,2, 0,8,3,2, 8,2,0,3, 8,2,1,3, 8,0,8,3, 8,0,9,3, 0,3,0,2, 0,3,1,2, 0,3,2,2, 0,3,3,2, 0,3,4,2, 0,3,5,2, 0,3,6,2, 0,3,7,2, 0,3,8,2, 0,3,9,2, 0,9,2,2, 0,9,3,2, 8,3,0,3, 8,3,1,3, 8,1,8,3, 8,1,9,3, 0,4,0,2, 0,4,1,2, 0,4,2,2, 0,4,3,2, 0,4,4,2, 0,4,5,2, 0,4,6,2, 0,4,7,2, 0,4,8,2, 0,4,9,2, 0,8,4,2, 0,8,5,2, 8,4,0,3, 8,4,1,3, 0,8,8,2, 0,8,9,2, 0,5,0,2, 0,5,1,2, 0,5,2,2, 0,5,3,2, 0,5,4,2, 0,5,5,2, 0,5,6,2, 0,5,7,2, 0,5,8,2, 0,5,9,2, 0,9,4,2, 0,9,5,2, 8,5,0,3, 8,5,1,3, 0,9,8,2, 0,9,9,2, 0,6,0,2, 0,6,1,2, 0,6,2,2, 0,6,3,2, 0,6,4,2, 0,6,5,2, 0,6,6,2, 0,6,7,2, 0,6,8,2, 0,6,9,2, 0,8,6,2, 0,8,7,2, 8,6,0,3, 8,6,1,3, 8,8,8,3, 8,8,9,3, 0,7,0,2, 0,7,1,2, 0,7,2,2, 0,7,3,2, 0,7,4,2, 0,7,5,2, 0,7,6,2, 0,7,7,2, 0,7,8,2, 0,7,9,2, 0,9,6,2, 0,9,7,2, 8,7,0,3, 8,7,1,3, 8,9,8,3, 8,9,9,3, 1,0,0,3, 1,0,1,3, 1,0,2,3, 1,0,3,3, 1,0,4,3, 1,0,5,3, 1,0,6,3, 1,0,7,3, 1,0,8,3, 1,0,9,3, 1,8,0,3, 1,8,1,3, 9,0,0,3, 9,0,1,3, 9,8,0,3, 9,8,1,3, 1,1,0,3, 1,1,1,3, 1,1,2,3, 1,1,3,3, 1,1,4,3, 1,1,5,3, 1,1,6,3, 1,1,7,3, 1,1,8,3, 1,1,9,3, 1,9,0,3, 1,9,1,3, 9,1,0,3, 9,1,1,3, 9,9,0,3, 9,9,1,3, 1,2,0,3, 1,2,1,3, 1,2,2,3, 1,2,3,3, 1,2,4,3, 1,2,5,3, 1,2,6,3, 1,2,7,3, 1,2,8,3, 1,2,9,3, 1,8,2,3, 1,8,3,3, 9,2,0,3, 9,2,1,3, 9,0,8,3, 9,0,9,3, 1,3,0,3, 1,3,1,3, 1,3,2,3, 1,3,3,3, 1,3,4,3, 1,3,5,3, 1,3,6,3, 1,3,7,3, 1,3,8,3, 1,3,9,3, 1,9,2,3, 1,9,3,3, 9,3,0,3, 9,3,1,3, 9,1,8,3, 9,1,9,3, 1,4,0,3, 1,4,1,3, 1,4,2,3, 1,4,3,3, 1,4,4,3, 1,4,5,3, 1,4,6,3, 1,4,7,3, 1,4,8,3, 1,4,9,3, 1,8,4,3, 1,8,5,3, 9,4,0,3, 9,4,1,3, 1,8,8,3, 1,8,9,3, 1,5,0,3, 1,5,1,3, 1,5,2,3, 1,5,3,3, 1,5,4,3, 1,5,5,3, 1,5,6,3, 1,5,7,3, 1,5,8,3, 1,5,9,3, 1,9,4,3, 1,9,5,3, 9,5,0,3, 9,5,1,3, 1,9,8,3, 1,9,9,3, 1,6,0,3, 1,6,1,3, 1,6,2,3, 1,6,3,3, 1,6,4,3, 1,6,5,3, 1,6,6,3, 1,6,7,3, 1,6,8,3, 1,6,9,3, 1,8,6,3, 1,8,7,3, 9,6,0,3, 9,6,1,3, 9,8,8,3, 9,8,9,3, 1,7,0,3, 1,7,1,3, 1,7,2,3, 1,7,3,3, 1,7,4,3, 1,7,5,3, 1,7,6,3, 1,7,7,3, 1,7,8,3, 1,7,9,3, 1,9,6,3, 1,9,7,3, 9,7,0,3, 9,7,1,3, 9,9,8,3, 9,9,9,3, 2,0,0,3, 2,0,1,3, 2,0,2,3, 2,0,3,3, 2,0,4,3, 2,0,5,3, 2,0,6,3, 2,0,7,3, 2,0,8,3, 2,0,9,3, 2,8,0,3, 2,8,1,3, 8,0,2,3, 8,0,3,3, 8,8,2,3, 8,8,3,3, 2,1,0,3, 2,1,1,3, 2,1,2,3, 2,1,3,3, 2,1,4,3, 2,1,5,3, 2,1,6,3, 2,1,7,3, 2,1,8,3, 2,1,9,3, 2,9,0,3, 2,9,1,3, 8,1,2,3, 8,1,3,3, 8,9,2,3, 8,9,3,3, 2,2,0,3, 2,2,1,3, 2,2,2,3, 2,2,3,3, 2,2,4,3, 2,2,5,3, 2,2,6,3, 2,2,7,3, 2,2,8,3, 2,2,9,3, 2,8,2,3, 2,8,3,3, 8,2,2,3, 8,2,3,3, 8,2,8,3, 8,2,9,3, 2,3,0,3, 2,3,1,3, 2,3,2,3, 2,3,3,3, 2,3,4,3, 2,3,5,3, 2,3,6,3, 2,3,7,3, 2,3,8,3, 2,3,9,3, 2,9,2,3, 2,9,3,3, 8,3,2,3, 8,3,3,3, 8,3,8,3, 8,3,9,3, 2,4,0,3, 2,4,1,3, 2,4,2,3, 2,4,3,3, 2,4,4,3, 2,4,5,3, 2,4,6,3, 2,4,7,3, 2,4,8,3, 2,4,9,3, 2,8,4,3, 2,8,5,3, 8,4,2,3, 8,4,3,3, 2,8,8,3, 2,8,9,3, 2,5,0,3, 2,5,1,3, 2,5,2,3, 2,5,3,3, 2,5,4,3, 2,5,5,3, 2,5,6,3, 2,5,7,3, 2,5,8,3, 2,5,9,3, 2,9,4,3, 2,9,5,3, 8,5,2,3, 8,5,3,3, 2,9,8,3, 2,9,9,3, 2,6,0,3, 2,6,1,3, 2,6,2,3, 2,6,3,3, 2,6,4,3, 2,6,5,3, 2,6,6,3, 2,6,7,3, 2,6,8,3, 2,6,9,3, 2,8,6,3, 2,8,7,3, 8,6,2,3, 8,6,3,3, 8,8,8,3, 8,8,9,3, 2,7,0,3, 2,7,1,3, 2,7,2,3, 2,7,3,3, 2,7,4,3, 2,7,5,3, 2,7,6,3, 2,7,7,3, 2,7,8,3, 2,7,9,3, 2,9,6,3, 2,9,7,3, 8,7,2,3, 8,7,3,3, 8,9,8,3, 8,9,9,3, 3,0,0,3, 3,0,1,3, 3,0,2,3, 3,0,3,3, 3,0,4,3, 3,0,5,3, 3,0,6,3, 3,0,7,3, 3,0,8,3, 3,0,9,3, 3,8,0,3, 3,8,1,3, 9,0,2,3, 9,0,3,3, 9,8,2,3, 9,8,3,3, 3,1,0,3, 3,1,1,3, 3,1,2,3, 3,1,3,3, 3,1,4,3, 3,1,5,3, 3,1,6,3, 3,1,7,3, 3,1,8,3, 3,1,9,3, 3,9,0,3, 3,9,1,3, 9,1,2,3, 9,1,3,3, 9,9,2,3, 9,9,3,3, 3,2,0,3, 3,2,1,3, 3,2,2,3, 3,2,3,3, 3,2,4,3, 3,2,5,3, 3,2,6,3, 3,2,7,3, 3,2,8,3, 3,2,9,3, 3,8,2,3, 3,8,3,3, 9,2,2,3, 9,2,3,3, 9,2,8,3, 9,2,9,3, 3,3,0,3, 3,3,1,3, 3,3,2,3, 3,3,3,3, 3,3,4,3, 3,3,5,3, 3,3,6,3, 3,3,7,3, 3,3,8,3, 3,3,9,3, 3,9,2,3, 3,9,3,3, 9,3,2,3, 9,3,3,3, 9,3,8,3, 9,3,9,3, 3,4,0,3, 3,4,1,3, 3,4,2,3, 3,4,3,3, 3,4,4,3, 3,4,5,3, 3,4,6,3, 3,4,7,3, 3,4,8,3, 3,4,9,3, 3,8,4,3, 3,8,5,3, 9,4,2,3, 9,4,3,3, 3,8,8,3, 3,8,9,3, 3,5,0,3, 3,5,1,3, 3,5,2,3, 3,5,3,3, 3,5,4,3, 3,5,5,3, 3,5,6,3, 3,5,7,3, 3,5,8,3, 3,5,9,3, 3,9,4,3, 3,9,5,3, 9,5,2,3, 9,5,3,3, 3,9,8,3, 3,9,9,3, 3,6,0,3, 3,6,1,3, 3,6,2,3, 3,6,3,3, 3,6,4,3, 3,6,5,3, 3,6,6,3, 3,6,7,3, 3,6,8,3, 3,6,9,3, 3,8,6,3, 3,8,7,3, 9,6,2,3, 9,6,3,3, 9,8,8,3, 9,8,9,3, 3,7,0,3, 3,7,1,3, 3,7,2,3, 3,7,3,3, 3,7,4,3, 3,7,5,3, 3,7,6,3, 3,7,7,3, 3,7,8,3, 3,7,9,3, 3,9,6,3, 3,9,7,3, 9,7,2,3, 9,7,3,3, 9,9,8,3, 9,9,9,3, 4,0,0,3, 4,0,1,3, 4,0,2,3, 4,0,3,3, 4,0,4,3, 4,0,5,3, 4,0,6,3, 4,0,7,3, 4,0,8,3, 4,0,9,3, 4,8,0,3, 4,8,1,3, 8,0,4,3, 8,0,5,3, 8,8,4,3, 8,8,5,3, 4,1,0,3, 4,1,1,3, 4,1,2,3, 4,1,3,3, 4,1,4,3, 4,1,5,3, 4,1,6,3, 4,1,7,3, 4,1,8,3, 4,1,9,3, 4,9,0,3, 4,9,1,3, 8,1,4,3, 8,1,5,3, 8,9,4,3, 8,9,5,3, 4,2,0,3, 4,2,1,3, 4,2,2,3, 4,2,3,3, 4,2,4,3, 4,2,5,3, 4,2,6,3, 4,2,7,3, 4,2,8,3, 4,2,9,3, 4,8,2,3, 4,8,3,3, 8,2,4,3, 8,2,5,3, 8,4,8,3, 8,4,9,3, 4,3,0,3, 4,3,1,3, 4,3,2,3, 4,3,3,3, 4,3,4,3, 4,3,5,3, 4,3,6,3, 4,3,7,3, 4,3,8,3, 4,3,9,3, 4,9,2,3, 4,9,3,3, 8,3,4,3, 8,3,5,3, 8,5,8,3, 8,5,9,3, 4,4,0,3, 4,4,1,3, 4,4,2,3, 4,4,3,3, 4,4,4,3, 4,4,5,3, 4,4,6,3, 4,4,7,3, 4,4,8,3, 4,4,9,3, 4,8,4,3, 4,8,5,3, 8,4,4,3, 8,4,5,3, 4,8,8,3, 4,8,9,3, 4,5,0,3, 4,5,1,3, 4,5,2,3, 4,5,3,3, 4,5,4,3, 4,5,5,3, 4,5,6,3, 4,5,7,3, 4,5,8,3, 4,5,9,3, 4,9,4,3, 4,9,5,3, 8,5,4,3, 8,5,5,3, 4,9,8,3, 4,9,9,3, 4,6,0,3, 4,6,1,3, 4,6,2,3, 4,6,3,3, 4,6,4,3, 4,6,5,3, 4,6,6,3, 4,6,7,3, 4,6,8,3, 4,6,9,3, 4,8,6,3, 4,8,7,3, 8,6,4,3, 8,6,5,3, 8,8,8,3, 8,8,9,3, 4,7,0,3, 4,7,1,3, 4,7,2,3, 4,7,3,3, 4,7,4,3, 4,7,5,3, 4,7,6,3, 4,7,7,3, 4,7,8,3, 4,7,9,3, 4,9,6,3, 4,9,7,3, 8,7,4,3, 8,7,5,3, 8,9,8,3, 8,9,9,3, 5,0,0,3, 5,0,1,3, 5,0,2,3, 5,0,3,3, 5,0,4,3, 5,0,5,3, 5,0,6,3, 5,0,7,3, 5,0,8,3, 5,0,9,3, 5,8,0,3, 5,8,1,3, 9,0,4,3, 9,0,5,3, 9,8,4,3, 9,8,5,3, 5,1,0,3, 5,1,1,3, 5,1,2,3, 5,1,3,3, 5,1,4,3, 5,1,5,3, 5,1,6,3, 5,1,7,3, 5,1,8,3, 5,1,9,3, 5,9,0,3, 5,9,1,3, 9,1,4,3, 9,1,5,3, 9,9,4,3, 9,9,5,3, 5,2,0,3, 5,2,1,3, 5,2,2,3, 5,2,3,3, 5,2,4,3, 5,2,5,3, 5,2,6,3, 5,2,7,3, 5,2,8,3, 5,2,9,3, 5,8,2,3, 5,8,3,3, 9,2,4,3, 9,2,5,3, 9,4,8,3, 9,4,9,3, 5,3,0,3, 5,3,1,3, 5,3,2,3, 5,3,3,3, 5,3,4,3, 5,3,5,3, 5,3,6,3, 5,3,7,3, 5,3,8,3, 5,3,9,3, 5,9,2,3, 5,9,3,3, 9,3,4,3, 9,3,5,3, 9,5,8,3, 9,5,9,3, 5,4,0,3, 5,4,1,3, 5,4,2,3, 5,4,3,3, 5,4,4,3, 5,4,5,3, 5,4,6,3, 5,4,7,3, 5,4,8,3, 5,4,9,3, 5,8,4,3, 5,8,5,3, 9,4,4,3, 9,4,5,3, 5,8,8,3, 5,8,9,3, 5,5,0,3, 5,5,1,3, 5,5,2,3, 5,5,3,3, 5,5,4,3, 5,5,5,3, 5,5,6,3, 5,5,7,3, 5,5,8,3, 5,5,9,3, 5,9,4,3, 5,9,5,3, 9,5,4,3, 9,5,5,3, 5,9,8,3, 5,9,9,3, 5,6,0,3, 5,6,1,3, 5,6,2,3, 5,6,3,3, 5,6,4,3, 5,6,5,3, 5,6,6,3, 5,6,7,3, 5,6,8,3, 5,6,9,3, 5,8,6,3, 5,8,7,3, 9,6,4,3, 9,6,5,3, 9,8,8,3, 9,8,9,3, 5,7,0,3, 5,7,1,3, 5,7,2,3, 5,7,3,3, 5,7,4,3, 5,7,5,3, 5,7,6,3, 5,7,7,3, 5,7,8,3, 5,7,9,3, 5,9,6,3, 5,9,7,3, 9,7,4,3, 9,7,5,3, 9,9,8,3, 9,9,9,3, 6,0,0,3, 6,0,1,3, 6,0,2,3, 6,0,3,3, 6,0,4,3, 6,0,5,3, 6,0,6,3, 6,0,7,3, 6,0,8,3, 6,0,9,3, 6,8,0,3, 6,8,1,3, 8,0,6,3, 8,0,7,3, 8,8,6,3, 8,8,7,3, 6,1,0,3, 6,1,1,3, 6,1,2,3, 6,1,3,3, 6,1,4,3, 6,1,5,3, 6,1,6,3, 6,1,7,3, 6,1,8,3, 6,1,9,3, 6,9,0,3, 6,9,1,3, 8,1,6,3, 8,1,7,3, 8,9,6,3, 8,9,7,3, 6,2,0,3, 6,2,1,3, 6,2,2,3, 6,2,3,3, 6,2,4,3, 6,2,5,3, 6,2,6,3, 6,2,7,3, 6,2,8,3, 6,2,9,3, 6,8,2,3, 6,8,3,3, 8,2,6,3, 8,2,7,3, 8,6,8,3, 8,6,9,3, 6,3,0,3, 6,3,1,3, 6,3,2,3, 6,3,3,3, 6,3,4,3, 6,3,5,3, 6,3,6,3, 6,3,7,3, 6,3,8,3, 6,3,9,3, 6,9,2,3, 6,9,3,3, 8,3,6,3, 8,3,7,3, 8,7,8,3, 8,7,9,3, 6,4,0,3, 6,4,1,3, 6,4,2,3, 6,4,3,3, 6,4,4,3, 6,4,5,3, 6,4,6,3, 6,4,7,3, 6,4,8,3, 6,4,9,3, 6,8,4,3, 6,8,5,3, 8,4,6,3, 8,4,7,3, 6,8,8,3, 6,8,9,3, 6,5,0,3, 6,5,1,3, 6,5,2,3, 6,5,3,3, 6,5,4,3, 6,5,5,3, 6,5,6,3, 6,5,7,3, 6,5,8,3, 6,5,9,3, 6,9,4,3, 6,9,5,3, 8,5,6,3, 8,5,7,3, 6,9,8,3, 6,9,9,3, 6,6,0,3, 6,6,1,3, 6,6,2,3, 6,6,3,3, 6,6,4,3, 6,6,5,3, 6,6,6,3, 6,6,7,3, 6,6,8,3, 6,6,9,3, 6,8,6,3, 6,8,7,3, 8,6,6,3, 8,6,7,3, 8,8,8,3, 8,8,9,3, 6,7,0,3, 6,7,1,3, 6,7,2,3, 6,7,3,3, 6,7,4,3, 6,7,5,3, 6,7,6,3, 6,7,7,3, 6,7,8,3, 6,7,9,3, 6,9,6,3, 6,9,7,3, 8,7,6,3, 8,7,7,3, 8,9,8,3, 8,9,9,3, 7,0,0,3, 7,0,1,3, 7,0,2,3, 7,0,3,3, 7,0,4,3, 7,0,5,3, 7,0,6,3, 7,0,7,3, 7,0,8,3, 7,0,9,3, 7,8,0,3, 7,8,1,3, 9,0,6,3, 9,0,7,3, 9,8,6,3, 9,8,7,3, 7,1,0,3, 7,1,1,3, 7,1,2,3, 7,1,3,3, 7,1,4,3, 7,1,5,3, 7,1,6,3, 7,1,7,3, 7,1,8,3, 7,1,9,3, 7,9,0,3, 7,9,1,3, 9,1,6,3, 9,1,7,3, 9,9,6,3, 9,9,7,3, 7,2,0,3, 7,2,1,3, 7,2,2,3, 7,2,3,3, 7,2,4,3, 7,2,5,3, 7,2,6,3, 7,2,7,3, 7,2,8,3, 7,2,9,3, 7,8,2,3, 7,8,3,3, 9,2,6,3, 9,2,7,3, 9,6,8,3, 9,6,9,3, 7,3,0,3, 7,3,1,3, 7,3,2,3, 7,3,3,3, 7,3,4,3, 7,3,5,3, 7,3,6,3, 7,3,7,3, 7,3,8,3, 7,3,9,3, 7,9,2,3, 7,9,3,3, 9,3,6,3, 9,3,7,3, 9,7,8,3, 9,7,9,3, 7,4,0,3, 7,4,1,3, 7,4,2,3, 7,4,3,3, 7,4,4,3, 7,4,5,3, 7,4,6,3, 7,4,7,3, 7,4,8,3, 7,4,9,3, 7,8,4,3, 7,8,5,3, 9,4,6,3, 9,4,7,3, 7,8,8,3, 7,8,9,3, 7,5,0,3, 7,5,1,3, 7,5,2,3, 7,5,3,3, 7,5,4,3, 7,5,5,3, 7,5,6,3, 7,5,7,3, 7,5,8,3, 7,5,9,3, 7,9,4,3, 7,9,5,3, 9,5,6,3, 9,5,7,3, 7,9,8,3, 7,9,9,3, 7,6,0,3, 7,6,1,3, 7,6,2,3, 7,6,3,3, 7,6,4,3, 7,6,5,3, 7,6,6,3, 7,6,7,3, 7,6,8,3, 7,6,9,3, 7,8,6,3, 7,8,7,3, 9,6,6,3, 9,6,7,3, 9,8,8,3, 9,8,9,3, 7,7,0,3, 7,7,1,3, 7,7,2,3, 7,7,3,3, 7,7,4,3, 7,7,5,3, 7,7,6,3, 7,7,7,3, 7,7,8,3, 7,7,9,3, 7,9,6,3, 7,9,7,3, 9,7,6,3, 9,7,7,3, 9,9,8,3, 9,9,9,3}; #endif hercules-3.07/decNumber/decimal128.c000644 000765 000765 00000061105 11202676511 020650 0ustar00jmaynardjmaynard000000 000000 /* ------------------------------------------------------------------ */ /* Decimal 128-bit format module */ /* ------------------------------------------------------------------ */ /* Copyright (c) IBM Corporation, 2000, 2006. All rights reserved. */ /* */ /* This software is made available under the terms of the */ /* ICU License -- ICU 1.8.1 and later. */ /* */ /* The description and User's Guide ("The decNumber C Library") for */ /* this software is called decNumber.pdf. This document is */ /* available, together with arithmetic and format specifications, */ /* testcases, and Web links, at: http://www2.hursley.ibm.com/decimal */ /* */ /* Please send comments, suggestions, and corrections to the author: */ /* mfc@uk.ibm.com */ /* Mike Cowlishaw, IBM Fellow */ /* IBM UK, PO Box 31, Birmingham Road, Warwick CV34 5JL, UK */ /* ------------------------------------------------------------------ */ /* This module comprises the routines for decimal128 format numbers. */ /* Conversions are supplied to and from decNumber and String. */ /* */ /* No arithmetic routines are included; decNumber provides these. */ /* */ /* Error handling is the same as decNumber (qv.). */ /* ------------------------------------------------------------------ */ #include // [for memset/memcpy] #include // [for printf] #if defined(_MSVC_) #pragma warning(disable:4244) // [for win64] #endif /*defined(_MSVC_)*/ #define DECNUMDIGITS 34 // make decNumbers with space for 34 #include "decNumber.h" // base number library #include "decNumberLocal.h" // decNumber local types, etc. #include "decimal128.h" // our primary include /* Utility routines and tables [in decimal64.c] */ extern const uInt COMBEXP[32], COMBMSD[32]; extern const uShort DPD2BIN[1024]; extern const uShort BIN2DPD[1000]; // [not used] extern const uByte BIN2CHAR[4001]; extern void decDigitsFromDPD(decNumber *, const uInt *, Int); extern void decDigitsToDPD(const decNumber *, uInt *, Int); #if DECTRACE || DECCHECK void decimal128Show(const decimal128 *); // for debug extern void decNumberShow(const decNumber *); // .. #endif /* compile-time endian tester [assumes sizeof(int)>1] */ static const Int mfcone=1; // constant 1 static const Flag *mfctop=(Flag *)&mfcone; // -> top byte #define LITEND mfctop[0] // named flag; 1=little-endian /* Useful macro */ // Clear a structure (e.g., a decNumber) #define DEC_clear(d) memset(d, 0, sizeof(*d)) /* ------------------------------------------------------------------ */ /* decimal128FromNumber -- convert decNumber to decimal128 */ /* */ /* ds is the target decimal128 */ /* dn is the source number (assumed valid) */ /* set is the context, used only for reporting errors */ /* */ /* The set argument is used only for status reporting and for the */ /* rounding mode (used if the coefficient is more than DECIMAL128_Pmax*/ /* digits or an overflow is detected). If the exponent is out of the */ /* valid range then Overflow or Underflow will be raised. */ /* After Underflow a subnormal result is possible. */ /* */ /* DEC_Clamped is set if the number has to be 'folded down' to fit, */ /* by reducing its exponent and multiplying the coefficient by a */ /* power of ten, or if the exponent on a zero had to be clamped. */ /* ------------------------------------------------------------------ */ decimal128 * decimal128FromNumber(decimal128 *d128, const decNumber *dn, decContext *set) { uInt status=0; // status accumulator Int ae; // adjusted exponent decNumber dw; // work decContext dc; // .. uInt *pu; // .. uInt comb, exp; // .. uInt targar[4]={0,0,0,0}; // target 128-bit #define targhi targar[3] // name the word with the sign #define targmh targar[2] // name the words #define targml targar[1] // .. #define targlo targar[0] // .. // If the number has too many digits, or the exponent could be // out of range then reduce the number under the appropriate // constraints. This could push the number to Infinity or zero, // so this check and rounding must be done before generating the // decimal128] ae=dn->exponent+dn->digits-1; // [0 if special] if (dn->digits>DECIMAL128_Pmax // too many digits || ae>DECIMAL128_Emax // likely overflow || aeround; // use supplied rounding decNumberPlus(&dw, dn, &dc); // (round and check) // [this changes -0 to 0, so enforce the sign...] dw.bits|=dn->bits&DECNEG; status=dc.status; // save status dn=&dw; // use the work number } // maybe out of range if (dn->bits&DECSPECIAL) { // a special value if (dn->bits&DECINF) targhi=DECIMAL_Inf<<24; else { // sNaN or qNaN if ((*dn->lsu!=0 || dn->digits>1) // non-zero coefficient && (dn->digitsbits&DECNAN) targhi|=DECIMAL_NaN<<24; else targhi|=DECIMAL_sNaN<<24; } // a NaN } // special else { // is finite if (decNumberIsZero(dn)) { // is a zero // set and clamp exponent if (dn->exponent<-DECIMAL128_Bias) { exp=0; // low clamp status|=DEC_Clamped; } else { exp=dn->exponent+DECIMAL128_Bias; // bias exponent if (exp>DECIMAL128_Ehigh) { // top clamp exp=DECIMAL128_Ehigh; status|=DEC_Clamped; } } comb=(exp>>9) & 0x18; // msd=0, exp top 2 bits .. } else { // non-zero finite number uInt msd; // work Int pad=0; // coefficient pad digits // the dn is known to fit, but it may need to be padded exp=(uInt)(dn->exponent+DECIMAL128_Bias); // bias exponent if (exp>DECIMAL128_Ehigh) { // fold-down case pad=exp-DECIMAL128_Ehigh; exp=DECIMAL128_Ehigh; // [to maximum] status|=DEC_Clamped; } // [fastpath for common case is not a win, here] decDigitsToDPD(dn, targar, pad); // save and clear the top digit msd=targhi>>14; targhi&=0x00003fff; // create the combination field if (msd>=8) comb=0x18 | ((exp>>11) & 0x06) | (msd & 0x01); else comb=((exp>>9) & 0x18) | msd; } targhi|=comb<<26; // add combination field .. targhi|=(exp&0xfff)<<14; // .. and exponent continuation } // finite if (dn->bits&DECNEG) targhi|=0x80000000; // add sign bit // now write to storage; this may be endian, or not #if DECENDIAN // DECENDIAN -- direct store, in the right order pu=(uInt *)d128->bytes; // overlay if (LITEND) { pu[0]=targlo; // directly store the low int pu[1]=targml; // then the mid-low pu[2]=targmh; // then the mid-high pu[3]=targhi; // then the high int } else { pu[0]=targhi; // directly store the high int pu[1]=targmh; // then the mid-high pu[2]=targml; // then the mid-low pu[3]=targlo; // then the low int } #else // not DECENDIAN -- use network byte order if (LITEND) { // little-endian needs reversal uByte *pb; // work Int off; // .. for (pb=&d128->bytes[15]; pb>=d128->bytes; pb--) { off=3-((pb-d128->bytes)>>2); // 0, then 1, 2, 3 *pb=(uByte)(targar[off]&0xff); targar[off]>>=8; } // i } else { // big-endian; it's the right way round already pu=(uInt *)d128->bytes; // overlay pu[0]=targhi; // directly store the high int pu[1]=targmh; // then the mid-high pu[2]=targml; // then the mid-low pu[3]=targlo; // then the low int } #endif if (status!=0) decContextSetStatus(set, status); // pass on status // decimal128Show(d128); return d128; } // decimal128FromNumber /* ------------------------------------------------------------------ */ /* decimal128ToNumber -- convert decimal128 to decNumber */ /* d128 is the source decimal128 */ /* dn is the target number, with appropriate space */ /* No error is possible. */ /* ------------------------------------------------------------------ */ decNumber * decimal128ToNumber(const decimal128 *d128, decNumber *dn) { uInt msd; // coefficient MSD uInt exp; // exponent top two bits uInt comb; // combination field uInt *pu; // work Int need; // .. uInt sourar[4]; // source 128-bit #define sourhi sourar[3] // name the word with the sign #define sourmh sourar[2] // and the mid-high word #define sourml sourar[1] // and the mod-low word #define sourlo sourar[0] // and the lowest word // load source from storage; this may be endian, or not #if DECENDIAN // DECENDIAN -- direct load, in the right order pu=(uInt *)d128->bytes; // overlay if (LITEND) { sourlo=pu[0]; // directly load the low int sourml=pu[1]; // then the mid-low sourmh=pu[2]; // then the mid-high sourhi=pu[3]; // then the high int } else { sourhi=pu[0]; // directly load the high int sourmh=pu[1]; // then the mid-high sourml=pu[2]; // then the mid-low sourlo=pu[3]; // then the low int } #else // not DECENDIAN -- use network byte order if (LITEND) { // little-endian needs reversal const uByte *pb; // work Int off; // .. for (pb=d128->bytes; pb<=&d128->bytes[15]; pb++) { off=3-((pb-d128->bytes)>>2); // 3, then 2, 1, 0 sourar[off]<<=8; sourar[off]|=*pb; } // i } else { // big-endian; it's the right way round already pu=(uInt *)d128->bytes; // overlay sourhi=pu[0]; // directly load the high int sourmh=pu[1]; // then the mid-high sourml=pu[2]; // then the mid-low sourlo=pu[3]; // then the low int } #endif comb=(sourhi>>26)&0x1f; // combination field decNumberZero(dn); // clean number if (sourhi&0x80000000) dn->bits=DECNEG; // set sign if negative msd=COMBMSD[comb]; // decode the combination field exp=COMBEXP[comb]; // .. if (exp==3) { // is a special if (msd==0) { dn->bits|=DECINF; return dn; // no coefficient needed } else if (sourhi&0x02000000) dn->bits|=DECSNAN; else dn->bits|=DECNAN; msd=0; // no top digit } else { // is a finite number dn->exponent=(exp<<12)+((sourhi>>14)&0xfff)-DECIMAL128_Bias; // unbiased } // get the coefficient sourhi&=0x00003fff; // clean coefficient continuation if (msd) { // non-zero msd sourhi|=msd<<14; // prefix to coefficient need=12; // process 12 declets } else { // msd=0 if (sourhi) need=11; // declets to process else if (sourmh) need=10; else if (sourml) need=7; else if (sourlo) need=4; else return dn; // easy: coefficient is 0 } //msd=0 decDigitsFromDPD(dn, sourar, need); // process declets // decNumberShow(dn); return dn; } // decimal128ToNumber /* ------------------------------------------------------------------ */ /* to-scientific-string -- conversion to numeric string */ /* to-engineering-string -- conversion to numeric string */ /* */ /* decimal128ToString(d128, string); */ /* decimal128ToEngString(d128, string); */ /* */ /* d128 is the decimal128 format number to convert */ /* string is the string where the result will be laid out */ /* */ /* string must be at least 24 characters */ /* */ /* No error is possible, and no status can be set. */ /* ------------------------------------------------------------------ */ char * decimal128ToEngString(const decimal128 *d128, char *string){ decNumber dn; // work decimal128ToNumber(d128, &dn); decNumberToEngString(&dn, string); return string; } // decimal128ToEngString char * decimal128ToString(const decimal128 *d128, char *string){ uInt msd; // coefficient MSD Int exp; // exponent top two bits or full uInt comb; // combination field char *cstart; // coefficient start char *c; // output pointer in string uInt *pu; // work char *s, *t; // .. (source, target) Int dpd; // .. Int pre, e; // .. const uByte *u; // .. uInt sourar[4]; // source 128-bit #define sourhi sourar[3] // name the word with the sign #define sourmh sourar[2] // and the mid-high word #define sourml sourar[1] // and the mod-low word #define sourlo sourar[0] // and the lowest word // load source from storage; this may be endian, or not #if DECENDIAN // DECENDIAN -- direct load, in the right order pu=(uInt *)d128->bytes; // overlay if (LITEND) { sourlo=pu[0]; // directly load the low int sourml=pu[1]; // then the mid-low sourmh=pu[2]; // then the mid-high sourhi=pu[3]; // then the high int } else { sourhi=pu[0]; // directly load the high int sourmh=pu[1]; // then the mid-high sourml=pu[2]; // then the mid-low sourlo=pu[3]; // then the low int } #else // not DECENDIAN -- use network byte order if (LITEND) { // little-endian needs reversal const uByte *pb; // work Int off; // .. for (pb=d128->bytes; pb<=&d128->bytes[15]; pb++) { off=3-((pb-d128->bytes)>>2); // 3, then 2, 1, 0 sourar[off]<<=8; sourar[off]|=*pb; } // i } else { // big-endian; it's the right way round already pu=(uInt *)d128->bytes; // overlay sourhi=pu[0]; // directly load the high int sourmh=pu[1]; // then the mid-high sourml=pu[2]; // then the mid-low sourlo=pu[3]; // then the low int } #endif c=string; // where result will go if (((Int)sourhi)<0) *c++='-'; // handle sign comb=(sourhi>>26)&0x1f; // combination field msd=COMBMSD[comb]; // decode the combination field exp=COMBEXP[comb]; // .. if (exp==3) { if (msd==0) { // infinity strcpy(c, "Infinity"); return string; // easy } if (sourhi&0x02000000) *c++='s'; // sNaN strcpy(c, "NaN"); // complete word c+=3; // step past if (sourlo==0 && sourml==0 && sourmh==0 && (sourhi&0x0003ffff)==0) return string; // zero payload // otherwise drop through to add integer; set correct exp exp=0; msd=0; // setup for following code } else exp=(exp<<12)+((sourhi>>14)&0xfff)-DECIMAL128_Bias; // unbiased // convert 34 digits of significand to characters cstart=c; // save start of coefficient if (msd) *c++='0'+(char)msd; // non-zero most significant digit // Now decode the declets. After extracting each one, it is // decoded to binary and then to a 4-char sequence by table lookup; // the 4-chars are a 1-char length (significant digits, except 000 // has length 0). This allows us to left-align the first declet // with non-zero content, then remaining ones are full 3-char // length. We use fixed-length memcpys because variable-length // causes a subroutine call in GCC. (These are length 4 for speed // and are safe because the array has an extra terminator byte.) #define dpd2char u=&BIN2CHAR[DPD2BIN[dpd]*4]; \ if (c!=cstart) {memcpy(c, u+1, 4); c+=3;} \ else if (*u) {memcpy(c, u+4-*u, 4); c+=*u;} dpd=(sourhi>>4)&0x3ff; // declet 1 dpd2char; dpd=((sourhi&0xf)<<6) | (sourmh>>26); // declet 2 dpd2char; dpd=(sourmh>>16)&0x3ff; // declet 3 dpd2char; dpd=(sourmh>>6)&0x3ff; // declet 4 dpd2char; dpd=((sourmh&0x3f)<<4) | (sourml>>28); // declet 5 dpd2char; dpd=(sourml>>18)&0x3ff; // declet 6 dpd2char; dpd=(sourml>>8)&0x3ff; // declet 7 dpd2char; dpd=((sourml&0xff)<<2) | (sourlo>>30); // declet 8 dpd2char; dpd=(sourlo>>20)&0x3ff; // declet 9 dpd2char; dpd=(sourlo>>10)&0x3ff; // declet 10 dpd2char; dpd=(sourlo)&0x3ff; // declet 11 dpd2char; if (c==cstart) *c++='0'; // all zeros -- make 0 if (exp==0) { // integer or NaN case -- easy *c='\0'; // terminate return string; } /* non-0 exponent */ e=0; // assume no E pre=c-cstart+exp; // [here, pre-exp is the digits count (==1 for zero)] if (exp>0 || pre<-5) { // need exponential form e=pre-1; // calculate E value pre=1; // assume one digit before '.' } // exponential form /* modify the coefficient, adding 0s, '.', and E+nn as needed */ s=c-1; // source (LSD) if (pre>0) { // ddd.ddd (plain), perhaps with E char *dotat=cstart+pre; if (dotat=dotat; s--, t--) *t=*s; // open the gap; leave t at gap *t='.'; // insert the dot c++; // length increased by one } // finally add the E-part, if needed; it will never be 0, and has // a maximum length of 4 digits if (e!=0) { *c++='E'; // starts with E *c++='+'; // assume positive if (e<0) { *(c-1)='-'; // oops, need '-' e=-e; // uInt, please } if (e<1000) { // 3 (or fewer) digits case u=&BIN2CHAR[e*4]; // -> length byte memcpy(c, u+4-*u, 4); // copy fixed 4 characters [is safe] c+=*u; // bump pointer appropriately } else { // 4-digits Int thou=((e>>3)*1049)>>17; // e/1000 Int rem=e-(1000*thou); // e%1000 *c++='0'+(char)thou; u=&BIN2CHAR[rem*4]; // -> length byte memcpy(c, u+1, 4); // copy fixed 3+1 characters [is safe] c+=3; // bump pointer, always 3 digits } } *c='\0'; // add terminator //printf("res %s\n", string); return string; } // pre>0 /* -5<=pre<=0: here for plain 0.ddd or 0.000ddd forms (can never have E) */ t=c+1-pre; *(t+1)='\0'; // can add terminator now for (; s>=cstart; s--, t--) *t=*s; // shift whole coefficient right c=cstart; *c++='0'; // always starts with 0. *c++='.'; for (; pre<0; pre++) *c++='0'; // add any 0's after '.' //printf("res %s\n", string); return string; } // decimal128ToString /* ------------------------------------------------------------------ */ /* to-number -- conversion from numeric string */ /* */ /* decimal128FromString(result, string, set); */ /* */ /* result is the decimal128 format number which gets the result of */ /* the conversion */ /* *string is the character string which should contain a valid */ /* number (which may be a special value) */ /* set is the context */ /* */ /* The context is supplied to this routine is used for error handling */ /* (setting of status and traps) and for the rounding mode, only. */ /* If an error occurs, the result will be a valid decimal128 NaN. */ /* ------------------------------------------------------------------ */ decimal128 * decimal128FromString(decimal128 *result, const char *string, decContext *set) { decContext dc; // work decNumber dn; // .. decContextDefault(&dc, DEC_INIT_DECIMAL128); // no traps, please dc.round=set->round; // use supplied rounding decNumberFromString(&dn, string, &dc); // will round if needed decimal128FromNumber(result, &dn, &dc); if (dc.status!=0) { // something happened decContextSetStatus(set, dc.status); // .. pass it on } return result; } // decimal128FromString #if DECTRACE || DECCHECK /* ------------------------------------------------------------------ */ /* decimal128Show -- display a decimal128 in hexadecimal [debug aid] */ /* d128 -- the number to show */ /* ------------------------------------------------------------------ */ // Also shows sign/cob/expconfields extracted void decimal128Show(const decimal128 *d128) { char buf[DECIMAL128_Bytes*2+1]; Int i, j=0; #if DECENDIAN if (LITEND) { for (i=0; ibytes[15-i]); } printf(" D128> %s [S:%d Cb:%02x Ec:%02x] LittleEndian\n", buf, d128->bytes[15]>>7, (d128->bytes[15]>>2)&0x1f, ((d128->bytes[15]&0x3)<<10)|(d128->bytes[14]<<2)| (d128->bytes[13]>>6)); } else { #endif for (i=0; ibytes[i]); } printf(" D128> %s [S:%d Cb:%02x Ec:%02x] BigEndian\n", buf, decimal128Sign(d128), decimal128Comb(d128), decimal128ExpCon(d128)); #if DECENDIAN } #endif } // decimal128Show #endif hercules-3.07/decNumber/decimal128.h000644 000765 000765 00000011613 11143760537 020662 0ustar00jmaynardjmaynard000000 000000 /* ------------------------------------------------------------------ */ /* Decimal 128-bit format module header */ /* ------------------------------------------------------------------ */ /* Copyright (c) IBM Corporation, 2000, 2005. All rights reserved. */ /* */ /* This software is made available under the terms of the */ /* ICU License -- ICU 1.8.1 and later. */ /* */ /* The description and User's Guide ("The decNumber C Library") for */ /* this software is called decNumber.pdf. This document is */ /* available, together with arithmetic and format specifications, */ /* testcases, and Web links, at: http://www2.hursley.ibm.com/decimal */ /* */ /* Please send comments, suggestions, and corrections to the author: */ /* mfc@uk.ibm.com */ /* Mike Cowlishaw, IBM Fellow */ /* IBM UK, PO Box 31, Birmingham Road, Warwick CV34 5JL, UK */ /* ------------------------------------------------------------------ */ #if !defined(DECIMAL128) #define DECIMAL128 #define DEC128NAME "decimal128" /* Short name */ #define DEC128FULLNAME "Decimal 128-bit Number" /* Verbose name */ #define DEC128AUTHOR "Mike Cowlishaw" /* Who to blame */ /* parameters for decimal128s */ #define DECIMAL128_Bytes 16 // length #define DECIMAL128_Pmax 34 // maximum precision (digits) #define DECIMAL128_Emax 6144 // maximum adjusted exponent #define DECIMAL128_Emin -6143 // minimum adjusted exponent #define DECIMAL128_Bias 6176 // bias for the exponent #define DECIMAL128_String 43 // maximum string length, +1 #define DECIMAL128_EconL 12 // exponent continuation length // highest biased exponent (Elimit-1) #define DECIMAL128_Ehigh (DECIMAL128_Emax+DECIMAL128_Bias-DECIMAL128_Pmax+1) // check enough digits, if pre-defined #if defined(DECNUMDIGITS) #if (DECNUMDIGITS=34 for safe use #endif #endif #ifndef DECNUMDIGITS #define DECNUMDIGITS DECIMAL128_Pmax // size if not already defined #endif #ifndef DECNUMBER #include "decNumber.h" // context and number library #endif /* Decimal 128-bit type, accessible by bytes */ typedef struct { uint8_t bytes[DECIMAL128_Bytes]; // decimal128: 1, 5, 12, 110 bits } decimal128; /* special values [top byte excluding sign bit; last two bits are don't-care for Infinity on input, last bit don't-care for NaN] */ #if !defined(DECIMAL_NaN) #define DECIMAL_NaN 0x7c // 0 11111 00 NaN #define DECIMAL_sNaN 0x7e // 0 11111 10 sNaN #define DECIMAL_Inf 0x78 // 0 11110 00 Infinity #endif /* Macros for accessing decimal128 fields. These assume the argument is a reference (pointer) to the decimal128 structure, and the decimal128 is in network byte order (big-endian) */ // Get sign #define decimal128Sign(d) ((unsigned)(d)->bytes[0]>>7) // Get combination field #define decimal128Comb(d) (((d)->bytes[0] & 0x7c)>>2) // Get exponent continuation [does not remove bias] #define decimal128ExpCon(d) ((((d)->bytes[0] & 0x03)<<10) \ | ((unsigned)(d)->bytes[1]<<2) \ | ((unsigned)(d)->bytes[2]>>6)) // Set sign [this assumes sign previously 0] #define decimal128SetSign(d, b) { \ (d)->bytes[0]|=((unsigned)(b)<<7);} // Set exponent continuation [does not apply bias] // This assumes range has been checked and exponent previously 0; // type of exponent must be unsigned #define decimal128SetExpCon(d, e) { \ (d)->bytes[0]|=(uint8_t)((e)>>10); \ (d)->bytes[1] =(uint8_t)(((e)&0x3fc)>>2); \ (d)->bytes[2]|=(uint8_t)(((e)&0x03)<<6);} /* ------------------------------------------------------------------ */ /* Routines */ /* ------------------------------------------------------------------ */ // String conversions decimal128 * decimal128FromString(decimal128 *, const char *, decContext *); char * decimal128ToString(const decimal128 *, char *); char * decimal128ToEngString(const decimal128 *, char *); // decNumber conversions decimal128 * decimal128FromNumber(decimal128 *, const decNumber *, decContext *); decNumber * decimal128ToNumber(const decimal128 *, decNumber *); #endif hercules-3.07/decNumber/decimal32.c000644 000765 000765 00000051377 11202676511 020574 0ustar00jmaynardjmaynard000000 000000 /* ------------------------------------------------------------------ */ /* Decimal 32-bit format module */ /* ------------------------------------------------------------------ */ /* Copyright (c) IBM Corporation, 2000, 2006. All rights reserved. */ /* */ /* This software is made available under the terms of the */ /* ICU License -- ICU 1.8.1 and later. */ /* */ /* The description and User's Guide ("The decNumber C Library") for */ /* this software is called decNumber.pdf. This document is */ /* available, together with arithmetic and format specifications, */ /* testcases, and Web links, at: http://www2.hursley.ibm.com/decimal */ /* */ /* Please send comments, suggestions, and corrections to the author: */ /* mfc@uk.ibm.com */ /* Mike Cowlishaw, IBM Fellow */ /* IBM UK, PO Box 31, Birmingham Road, Warwick CV34 5JL, UK */ /* ------------------------------------------------------------------ */ /* This module comprises the routines for decimal32 format numbers. */ /* Conversions are supplied to and from decNumber and String. */ /* */ /* No arithmetic routines are included; decNumber provides these. */ /* */ /* Error handling is the same as decNumber (qv.). */ /* ------------------------------------------------------------------ */ #include // [for memset/memcpy] #include // [for printf] #if defined(_MSVC_) #pragma warning(disable:4244) // [for win64] #endif /*defined(_MSVC_)*/ #define DECNUMDIGITS 7 // make decNumbers with space for 7 #include "decNumber.h" // base number library #include "decNumberLocal.h" // decNumber local types, etc. #include "decimal32.h" // our primary include /* Utility tables and routines [in decimal64.c] */ extern const uInt COMBEXP[32], COMBMSD[32]; extern const uShort DPD2BIN[1024]; extern const uShort BIN2DPD[1000]; extern const uByte BIN2CHAR[4001]; extern void decDigitsToDPD(const decNumber *, uInt *, Int); extern void decDigitsFromDPD(decNumber *, const uInt *, Int); #if DECTRACE || DECCHECK void decimal32Show(const decimal32 *); // for debug extern void decNumberShow(const decNumber *); // .. #endif /* Useful macro */ // Clear a structure (e.g., a decNumber) #define DEC_clear(d) memset(d, 0, sizeof(*d)) #if !DECENDIAN || DECTRACE || DECCHECK /* compile-time endian tester [assumes sizeof(int)>1] */ static const Int mfcone=1; // constant 1 static const Flag *mfctop=(Flag *)&mfcone; // -> top byte #define LITEND mfctop[0] // named flag; 1=little-endian #endif /* ------------------------------------------------------------------ */ /* decimal32FromNumber -- convert decNumber to decimal32 */ /* */ /* ds is the target decimal32 */ /* dn is the source number (assumed valid) */ /* set is the context, used only for reporting errors */ /* */ /* The set argument is used only for status reporting and for the */ /* rounding mode (used if the coefficient is more than DECIMAL32_Pmax */ /* digits or an overflow is detected). If the exponent is out of the */ /* valid range then Overflow or Underflow will be raised. */ /* After Underflow a subnormal result is possible. */ /* */ /* DEC_Clamped is set if the number has to be 'folded down' to fit, */ /* by reducing its exponent and multiplying the coefficient by a */ /* power of ten, or if the exponent on a zero had to be clamped. */ /* ------------------------------------------------------------------ */ decimal32 * decimal32FromNumber(decimal32 *d32, const decNumber *dn, decContext *set) { uInt status=0; // status accumulator Int ae; // adjusted exponent decNumber dw; // work decContext dc; // .. uInt *pu; // .. uInt comb, exp; // .. uInt targ=0; // target 32-bit // If the number has too many digits, or the exponent could be // out of range then reduce the number under the appropriate // constraints. This could push the number to Infinity or zero, // so this check and rounding must be done before generating the // decimal32] ae=dn->exponent+dn->digits-1; // [0 if special] if (dn->digits>DECIMAL32_Pmax // too many digits || ae>DECIMAL32_Emax // likely overflow || aeround; // use supplied rounding decNumberPlus(&dw, dn, &dc); // (round and check) // [this changes -0 to 0, so enforce the sign...] dw.bits|=dn->bits&DECNEG; status=dc.status; // save status dn=&dw; // use the work number } // maybe out of range if (dn->bits&DECSPECIAL) { // a special value if (dn->bits&DECINF) targ=DECIMAL_Inf<<24; else { // sNaN or qNaN if ((*dn->lsu!=0 || dn->digits>1) // non-zero coefficient && (dn->digitsbits&DECNAN) targ|=DECIMAL_NaN<<24; else targ|=DECIMAL_sNaN<<24; } // a NaN } // special else { // is finite if (decNumberIsZero(dn)) { // is a zero // set and clamp exponent if (dn->exponent<-DECIMAL32_Bias) { exp=0; // low clamp status|=DEC_Clamped; } else { exp=dn->exponent+DECIMAL32_Bias; // bias exponent if (exp>DECIMAL32_Ehigh) { // top clamp exp=DECIMAL32_Ehigh; status|=DEC_Clamped; } } comb=(exp>>3) & 0x18; // msd=0, exp top 2 bits .. } else { // non-zero finite number uInt msd; // work Int pad=0; // coefficient pad digits // the dn is known to fit, but it may need to be padded exp=(uInt)(dn->exponent+DECIMAL32_Bias); // bias exponent if (exp>DECIMAL32_Ehigh) { // fold-down case pad=exp-DECIMAL32_Ehigh; exp=DECIMAL32_Ehigh; // [to maximum] status|=DEC_Clamped; } // fastpath common case if (DECDPUN==3 && pad==0) { targ=BIN2DPD[dn->lsu[0]]; if (dn->digits>3) targ|=(uInt)(BIN2DPD[dn->lsu[1]])<<10; msd=(dn->digits==7 ? dn->lsu[2] : 0); } else { // general case decDigitsToDPD(dn, &targ, pad); // save and clear the top digit msd=targ>>20; targ&=0x000fffff; } // create the combination field if (msd>=8) comb=0x18 | ((exp>>5) & 0x06) | (msd & 0x01); else comb=((exp>>3) & 0x18) | msd; } targ|=comb<<26; // add combination field .. targ|=(exp&0x3f)<<20; // .. and exponent continuation } // finite if (dn->bits&DECNEG) targ|=0x80000000; // add sign bit // now write to storage; this may be endian, or not #if DECENDIAN // DECENDIAN -- direct store pu=(uInt *)d32->bytes; // overlay *pu=targ; // directly store the int #else // not DECENDIAN -- use network byte order if (LITEND) { // little-endian needs reversal uByte *pb; // work for (pb=&d32->bytes[3]; pb>=d32->bytes; pb--) { *pb=(uByte)(targ&0xff); targ>>=8; } // i } else { // big-endian; it's the right way round already pu=(uInt *)d32->bytes; // overlay *pu=targ; // directly store the int } #endif if (status!=0) decContextSetStatus(set, status); // pass on status // decimal32Show(d32); return d32; } // decimal32FromNumber /* ------------------------------------------------------------------ */ /* decimal32ToNumber -- convert decimal32 to decNumber */ /* d32 is the source decimal32 */ /* dn is the target number, with appropriate space */ /* No error is possible. */ /* ------------------------------------------------------------------ */ decNumber * decimal32ToNumber(const decimal32 *d32, decNumber *dn) { uInt msd; // coefficient MSD uInt exp; // exponent top two bits uInt comb; // combination field uInt *pu; // work uInt sour; // source 32-bit // load source from storage; this may be endian, or not #if DECENDIAN // DECENDIAN -- direct load pu=(uInt *)d32->bytes; // overlay sour=*pu; // directly load the int #else // not DECENDIAN -- use network byte order if (LITEND) { // little-endian needs reversal const uByte *pb; // work sour=0; // [keep compiler quiet] for (pb=d32->bytes; pb<=&d32->bytes[3]; pb++) { sour<<=8; sour|=*pb; } // i } else { // big-endian; it's the right way round already pu=(uInt *)d32->bytes; // overlay sour=*pu; // directly load the int } #endif comb=(sour>>26)&0x1f; // combination field decNumberZero(dn); // clean number if (sour&0x80000000) dn->bits=DECNEG; // set sign if negative msd=COMBMSD[comb]; // decode the combination field exp=COMBEXP[comb]; // .. if (exp==3) { // is a special if (msd==0) { dn->bits|=DECINF; return dn; // no coefficient needed } else if (sour&0x02000000) dn->bits|=DECSNAN; else dn->bits|=DECNAN; msd=0; // no top digit } else { // is a finite number dn->exponent=(exp<<6)+((sour>>20)&0x3f)-DECIMAL32_Bias; // unbiased } // get the coefficient sour&=0x000fffff; // clean coefficient continuation if (msd) { // non-zero msd sour|=msd<<20; // prefix to coefficient decDigitsFromDPD(dn, &sour, 3); // process 3 declets return dn; } // msd=0 if (!sour) return dn; // easy: coefficient is 0 if (sour&0x000ffc00) // need 2 declets? decDigitsFromDPD(dn, &sour, 2); // process 2 declets else decDigitsFromDPD(dn, &sour, 1); // process 1 declet return dn; } // decimal32ToNumber /* ------------------------------------------------------------------ */ /* to-scientific-string -- conversion to numeric string */ /* to-engineering-string -- conversion to numeric string */ /* */ /* decimal32ToString(d32, string); */ /* decimal32ToEngString(d32, string); */ /* */ /* d32 is the decimal32 format number to convert */ /* string is the string where the result will be laid out */ /* */ /* string must be at least 24 characters */ /* */ /* No error is possible, and no status can be set. */ /* ------------------------------------------------------------------ */ char * decimal32ToEngString(const decimal32 *d32, char *string){ decNumber dn; // work decimal32ToNumber(d32, &dn); decNumberToEngString(&dn, string); return string; } // decimal32ToEngString char * decimal32ToString(const decimal32 *d32, char *string){ uInt msd; // coefficient MSD Int exp; // exponent top two bits or full uInt comb; // combination field char *cstart; // coefficient start char *c; // output pointer in string uInt *pu; // work char *s, *t; // .. (source, target) Int dpd; // .. Int pre, e; // .. const uByte *u; // .. uInt sour; // source 32-bit // load source from storage; this may be endian, or not #if DECENDIAN // DECENDIAN -- direct load pu=(uInt *)d32->bytes; // overlay sour=*pu; // directly load the int #else // not DECENDIAN -- use network byte order if (LITEND) { // little-endian needs reversal const uByte *pb; // work sour=0; // [keep compiler quiet] for (pb=d32->bytes; pb<=&d32->bytes[3]; pb++) { sour<<=8; sour|=*pb; } // i } else { // big-endian; it's the right way round already pu=(uInt *)d32->bytes; // overlay sour=*pu; // directly load the int } #endif c=string; // where result will go if (((Int)sour)<0) *c++='-'; // handle sign comb=(sour>>26)&0x1f; // combination field msd=COMBMSD[comb]; // decode the combination field exp=COMBEXP[comb]; // .. if (exp==3) { if (msd==0) { // infinity strcpy(c, "Infinity"); return string; // easy } if (sour&0x02000000) *c++='s'; // sNaN strcpy(c, "NaN"); // complete word c+=3; // step past if ((sour&0x000fffff)==0) return string; // zero payload // otherwise drop through to add integer; set correct exp exp=0; msd=0; // setup for following code } else exp=(exp<<6)+((sour>>20)&0x3f)-DECIMAL32_Bias; // unbiased // convert 7 digits of significand to characters cstart=c; // save start of coefficient if (msd) *c++='0'+(char)msd; // non-zero most significant digit // Now decode the declets. After extracting each one, it is // decoded to binary and then to a 4-char sequence by table lookup; // the 4-chars are a 1-char length (significant digits, except 000 // has length 0). This allows us to left-align the first declet // with non-zero content, then remaining ones are full 3-char // length. We use fixed-length memcpys because variable-length // causes a subroutine call in GCC. (These are length 4 for speed // and are safe because the array has an extra terminator byte.) #define dpd2char u=&BIN2CHAR[DPD2BIN[dpd]*4]; \ if (c!=cstart) {memcpy(c, u+1, 4); c+=3;} \ else if (*u) {memcpy(c, u+4-*u, 4); c+=*u;} dpd=(sour>>10)&0x3ff; // declet 1 dpd2char; dpd=(sour)&0x3ff; // declet 2 dpd2char; if (c==cstart) *c++='0'; // all zeros -- make 0 if (exp==0) { // integer or NaN case -- easy *c='\0'; // terminate return string; } /* non-0 exponent */ e=0; // assume no E pre=c-cstart+exp; // [here, pre-exp is the digits count (==1 for zero)] if (exp>0 || pre<-5) { // need exponential form e=pre-1; // calculate E value pre=1; // assume one digit before '.' } // exponential form /* modify the coefficient, adding 0s, '.', and E+nn as needed */ s=c-1; // source (LSD) if (pre>0) { // ddd.ddd (plain), perhaps with E char *dotat=cstart+pre; if (dotat=dotat; s--, t--) *t=*s; // open the gap; leave t at gap *t='.'; // insert the dot c++; // length increased by one } // finally add the E-part, if needed; it will never be 0, and has // a maximum length of 3 digits (E-101 case) if (e!=0) { *c++='E'; // starts with E *c++='+'; // assume positive if (e<0) { *(c-1)='-'; // oops, need '-' e=-e; // uInt, please } u=&BIN2CHAR[e*4]; // -> length byte memcpy(c, u+4-*u, 4); // copy fixed 4 characters [is safe] c+=*u; // bump pointer appropriately } *c='\0'; // add terminator //printf("res %s\n", string); return string; } // pre>0 /* -5<=pre<=0: here for plain 0.ddd or 0.000ddd forms (can never have E) */ t=c+1-pre; *(t+1)='\0'; // can add terminator now for (; s>=cstart; s--, t--) *t=*s; // shift whole coefficient right c=cstart; *c++='0'; // always starts with 0. *c++='.'; for (; pre<0; pre++) *c++='0'; // add any 0's after '.' //printf("res %s\n", string); return string; } // decimal32ToString /* ------------------------------------------------------------------ */ /* to-number -- conversion from numeric string */ /* */ /* decimal32FromString(result, string, set); */ /* */ /* result is the decimal32 format number which gets the result of */ /* the conversion */ /* *string is the character string which should contain a valid */ /* number (which may be a special value) */ /* set is the context */ /* */ /* The context is supplied to this routine is used for error handling */ /* (setting of status and traps) and for the rounding mode, only. */ /* If an error occurs, the result will be a valid decimal32 NaN. */ /* ------------------------------------------------------------------ */ decimal32 * decimal32FromString(decimal32 *result, const char *string, decContext *set) { decContext dc; // work decNumber dn; // .. decContextDefault(&dc, DEC_INIT_DECIMAL32); // no traps, please dc.round=set->round; // use supplied rounding decNumberFromString(&dn, string, &dc); // will round if needed decimal32FromNumber(result, &dn, &dc); if (dc.status!=0) { // something happened decContextSetStatus(set, dc.status); // .. pass it on } return result; } // decimal32FromString #if DECTRACE || DECCHECK /* ------------------------------------------------------------------ */ /* decimal32Show -- display a decimal32 in hexadecimal [debug aid] */ /* d32 -- the number to show */ /* ------------------------------------------------------------------ */ // Also shows sign/cob/expconfields extracted - valid bigendian only void decimal32Show(const decimal32 *d32) { char buf[DECIMAL32_Bytes*2+1]; Int i, j=0; #if DECENDIAN if (LITEND) { for (i=0; ibytes[3-i]); } printf(" D32> %s [S:%d Cb:%02x Ec:%02x] LittleEndian\n", buf, d32->bytes[3]>>7, (d32->bytes[3]>>2)&0x1f, ((d32->bytes[3]&0x3)<<4)| (d32->bytes[2]>>4)); } else { #endif for (i=0; ibytes[i]); } printf(" D32> %s [S:%d Cb:%02x Ec:%02x] BigEndian\n", buf, decimal32Sign(d32), decimal32Comb(d32), decimal32ExpCon(d32)); #if DECENDIAN } #endif } // decimal32Show #endif hercules-3.07/decNumber/decimal32.h000644 000765 000765 00000011327 11143760537 020576 0ustar00jmaynardjmaynard000000 000000 /* ------------------------------------------------------------------ */ /* Decimal 32-bit format module header */ /* ------------------------------------------------------------------ */ /* Copyright (c) IBM Corporation, 2000, 2005. All rights reserved. */ /* */ /* This software is made available under the terms of the */ /* ICU License -- ICU 1.8.1 and later. */ /* */ /* The description and User's Guide ("The decNumber C Library") for */ /* this software is called decNumber.pdf. This document is */ /* available, together with arithmetic and format specifications, */ /* testcases, and Web links, at: http://www2.hursley.ibm.com/decimal */ /* */ /* Please send comments, suggestions, and corrections to the author: */ /* mfc@uk.ibm.com */ /* Mike Cowlishaw, IBM Fellow */ /* IBM UK, PO Box 31, Birmingham Road, Warwick CV34 5JL, UK */ /* ------------------------------------------------------------------ */ #if !defined(DECIMAL32) #define DECIMAL32 #define DEC32NAME "decimal32" /* Short name */ #define DEC32FULLNAME "Decimal 32-bit Number" /* Verbose name */ #define DEC32AUTHOR "Mike Cowlishaw" /* Who to blame */ /* parameters for decimal32s */ #define DECIMAL32_Bytes 4 // length #define DECIMAL32_Pmax 7 // maximum precision (digits) #define DECIMAL32_Emax 96 // maximum adjusted exponent #define DECIMAL32_Emin -95 // minimum adjusted exponent #define DECIMAL32_Bias 101 // bias for the exponent #define DECIMAL32_String 15 // maximum string length, +1 #define DECIMAL32_EconL 6 // exponent continuation length // highest biased exponent (Elimit-1) #define DECIMAL32_Ehigh (DECIMAL32_Emax+DECIMAL32_Bias-DECIMAL32_Pmax+1) // check enough digits, if pre-defined #if defined(DECNUMDIGITS) #if (DECNUMDIGITS=7 for safe use #endif #endif #ifndef DECNUMDIGITS #define DECNUMDIGITS DECIMAL32_Pmax // size if not already defined #endif #ifndef DECNUMBER #include "decNumber.h" // context and number library #endif /* Decimal 32-bit type, accessible by bytes */ typedef struct { uint8_t bytes[DECIMAL32_Bytes]; // decimal32: 1, 5, 6, 20 bits } decimal32; /* special values [top byte excluding sign bit; last two bits are don't-care for Infinity on input, last bit don't-care for NaN] */ #if !defined(DECIMAL_NaN) #define DECIMAL_NaN 0x7c // 0 11111 00 NaN #define DECIMAL_sNaN 0x7e // 0 11111 10 sNaN #define DECIMAL_Inf 0x78 // 0 11110 00 Infinity #endif /* Macros for accessing decimal32 fields. These assume the argument is a reference (pointer) to the decimal32 structure, and the decimal32 is in network byte order (big-endian) */ // Get sign #define decimal32Sign(d) ((unsigned)(d)->bytes[0]>>7) // Get combination field #define decimal32Comb(d) (((d)->bytes[0] & 0x7c)>>2) // Get exponent continuation [does not remove bias] #define decimal32ExpCon(d) ((((d)->bytes[0] & 0x03)<<4) \ | ((unsigned)(d)->bytes[1]>>4)) // Set sign [this assumes sign previously 0] #define decimal32SetSign(d, b) { \ (d)->bytes[0]|=((unsigned)(b)<<7);} // Set exponent continuation [does not apply bias] // This assumes range has been checked and exponent previously 0; // type of exponent must be unsigned #define decimal32SetExpCon(d, e) { \ (d)->bytes[0]|=(uint8_t)((e)>>4); \ (d)->bytes[1]|=(uint8_t)(((e)&0x0F)<<4);} /* ------------------------------------------------------------------ */ /* Routines */ /* ------------------------------------------------------------------ */ // String conversions decimal32 * decimal32FromString(decimal32 *, const char *, decContext *); char * decimal32ToString(const decimal32 *, char *); char * decimal32ToEngString(const decimal32 *, char *); // decNumber conversions decimal32 * decimal32FromNumber(decimal32 *, const decNumber *, decContext *); decNumber * decimal32ToNumber(const decimal32 *, decNumber *); #endif hercules-3.07/decNumber/decimal64.c000644 000765 000765 00000110072 11202676511 020565 0ustar00jmaynardjmaynard000000 000000 /* ------------------------------------------------------------------ */ /* Decimal 64-bit format module */ /* ------------------------------------------------------------------ */ /* Copyright (c) IBM Corporation, 2000, 2006. All rights reserved. */ /* */ /* This software is made available under the terms of the */ /* ICU License -- ICU 1.8.1 and later. */ /* */ /* The description and User's Guide ("The decNumber C Library") for */ /* this software is called decNumber.pdf. This document is */ /* available, together with arithmetic and format specifications, */ /* testcases, and Web links, at: http://www2.hursley.ibm.com/decimal */ /* */ /* Please send comments, suggestions, and corrections to the author: */ /* mfc@uk.ibm.com */ /* Mike Cowlishaw, IBM Fellow */ /* IBM UK, PO Box 31, Birmingham Road, Warwick CV34 5JL, UK */ /* ------------------------------------------------------------------ */ /* This module comprises the routines for decimal64 format numbers. */ /* Conversions are supplied to and from decNumber and String. */ /* */ /* No arithmetic routines are included; decNumber provides these. */ /* */ /* Error handling is the same as decNumber (qv.). */ /* ------------------------------------------------------------------ */ #include // [for memset/memcpy] #include // [for printf] #if defined(_MSVC_) #pragma warning(disable:4244) // [for win64] #endif /*defined(_MSVC_)*/ #define DECNUMDIGITS 16 // make decNumbers with space for 16 #include "decNumber.h" // base number library #include "decNumberLocal.h" // decNumber local types, etc. #include "decimal64.h" // our primary include /* Utility routines and tables [in decimal64.c] */ extern const uInt COMBEXP[32], COMBMSD[32]; extern void decDigitsFromDPD(decNumber *, const uInt *, Int); extern void decDigitsToDPD(const decNumber *, uInt *, Int); #if DECTRACE || DECCHECK void decimal64Show(const decimal64 *); // for debug extern void decNumberShow(const decNumber *); // .. #endif /* compile-time endian tester [assumes sizeof(Int)>1] */ static const Int mfcone=1; // constant 1 static const Flag *mfctop=(Flag *)&mfcone; // -> top byte #define LITEND *mfctop // named flag; 1=little-endian /* Useful macro */ // Clear a structure (e.g., a decNumber) #define DEC_clear(d) memset(d, 0, sizeof(*d)) /* define and include the tables to use for conversions */ #define DEC_BIN2CHAR 1 #define DEC_DPD2BIN 1 #define DEC_BIN2DPD 1 // used for all sizes #include "decDPD.h" // lookup tables /* ------------------------------------------------------------------ */ /* decimal64FromNumber -- convert decNumber to decimal64 */ /* */ /* ds is the target decimal64 */ /* dn is the source number (assumed valid) */ /* set is the context, used only for reporting errors */ /* */ /* The set argument is used only for status reporting and for the */ /* rounding mode (used if the coefficient is more than DECIMAL64_Pmax */ /* digits or an overflow is detected). If the exponent is out of the */ /* valid range then Overflow or Underflow will be raised. */ /* After Underflow a subnormal result is possible. */ /* */ /* DEC_Clamped is set if the number has to be 'folded down' to fit, */ /* by reducing its exponent and multiplying the coefficient by a */ /* power of ten, or if the exponent on a zero had to be clamped. */ /* ------------------------------------------------------------------ */ decimal64 * decimal64FromNumber(decimal64 *d64, const decNumber *dn, decContext *set) { uInt status=0; // status accumulator Int ae; // adjusted exponent decNumber dw; // work decContext dc; // .. uInt *pu; // .. uInt comb, exp; // .. uInt targar[2]={0, 0}; // target 64-bit #define targhi targar[1] // name the word with the sign #define targlo targar[0] // and the other // If the number has too many digits, or the exponent could be // out of range then reduce the number under the appropriate // constraints. This could push the number to Infinity or zero, // so this check and rounding must be done before generating the // decimal64] ae=dn->exponent+dn->digits-1; // [0 if special] if (dn->digits>DECIMAL64_Pmax // too many digits || ae>DECIMAL64_Emax // likely overflow || aeround; // use supplied rounding decNumberPlus(&dw, dn, &dc); // (round and check) // [this changes -0 to 0, so enforce the sign...] dw.bits|=dn->bits&DECNEG; status=dc.status; // save status dn=&dw; // use the work number } // maybe out of range if (dn->bits&DECSPECIAL) { // a special value if (dn->bits&DECINF) targhi=DECIMAL_Inf<<24; else { // sNaN or qNaN if ((*dn->lsu!=0 || dn->digits>1) // non-zero coefficient && (dn->digitsbits&DECNAN) targhi|=DECIMAL_NaN<<24; else targhi|=DECIMAL_sNaN<<24; } // a NaN } // special else { // is finite if (decNumberIsZero(dn)) { // is a zero // set and clamp exponent if (dn->exponent<-DECIMAL64_Bias) { exp=0; // low clamp status|=DEC_Clamped; } else { exp=dn->exponent+DECIMAL64_Bias; // bias exponent if (exp>DECIMAL64_Ehigh) { // top clamp exp=DECIMAL64_Ehigh; status|=DEC_Clamped; } } comb=(exp>>5) & 0x18; // msd=0, exp top 2 bits .. } else { // non-zero finite number uInt msd; // work Int pad=0; // coefficient pad digits // the dn is known to fit, but it may need to be padded exp=(uInt)(dn->exponent+DECIMAL64_Bias); // bias exponent if (exp>DECIMAL64_Ehigh) { // fold-down case pad=exp-DECIMAL64_Ehigh; exp=DECIMAL64_Ehigh; // [to maximum] status|=DEC_Clamped; } // fastpath common case if (DECDPUN==3 && pad==0) { uInt dpd[6]={0,0,0,0,0,0}; uInt i; Int d=dn->digits; for (i=0; d>0; i++, d-=3) dpd[i]=BIN2DPD[dn->lsu[i]]; targlo =dpd[0]; targlo|=dpd[1]<<10; targlo|=dpd[2]<<20; if (dn->digits>6) { targlo|=dpd[3]<<30; targhi =dpd[3]>>2; targhi|=dpd[4]<<8; } msd=dpd[5]; // [did not really need conversion] } else { // general case decDigitsToDPD(dn, targar, pad); // save and clear the top digit msd=targhi>>18; targhi&=0x0003ffff; } // create the combination field if (msd>=8) comb=0x18 | ((exp>>7) & 0x06) | (msd & 0x01); else comb=((exp>>5) & 0x18) | msd; } targhi|=comb<<26; // add combination field .. targhi|=(exp&0xff)<<18; // .. and exponent continuation } // finite if (dn->bits&DECNEG) targhi|=0x80000000; // add sign bit // now write to storage; this may be endian, or not #if DECENDIAN // DECENDIAN -- direct store, in the right order pu=(uInt *)d64->bytes; // overlay if (LITEND) { pu[0]=targar[0]; // directly store the low int pu[1]=targar[1]; // then the high int } else { pu[0]=targar[1]; // directly store the high int pu[1]=targar[0]; // then the low int } #else // not DECENDIAN -- use network byte order if (LITEND) { // little-endian needs reversal uByte *pb; // work Int off; // .. for (pb=&d64->bytes[7]; pb>=d64->bytes; pb--) { off=1-((pb-d64->bytes)>>2); // 0 then 1 *pb=(uByte)(targar[off]&0xff); targar[off]>>=8; } // i } else { // big-endian; it's the right way round already pu=(uInt *)d64->bytes; // overlay pu[0]=targar[1]; // directly store the high int pu[1]=targar[0]; // then the low int } #endif if (status!=0) decContextSetStatus(set, status); // pass on status // decimal64Show(d64); return d64; } // decimal64FromNumber /* ------------------------------------------------------------------ */ /* decimal64ToNumber -- convert decimal64 to decNumber */ /* d64 is the source decimal64 */ /* dn is the target number, with appropriate space */ /* No error is possible. */ /* ------------------------------------------------------------------ */ decNumber * decimal64ToNumber(const decimal64 *d64, decNumber *dn) { uInt msd; // coefficient MSD uInt exp; // exponent top two bits uInt comb; // combination field uInt *pu; // work Int need; // .. uInt sourar[2]; // source 64-bit #define sourhi sourar[1] // name the word with the sign #define sourlo sourar[0] // and the lower word // load source from storage; this may be endian, or not #if DECENDIAN // DECENDIAN -- direct load, in the right order pu=(uInt *)d64->bytes; // overlay if (LITEND) { sourlo=pu[0]; // directly load the low int sourhi=pu[1]; // then the high int } else { sourhi=pu[0]; // directly load the high int sourlo=pu[1]; // then the low int } #else // not DECENDIAN -- use network byte order if (LITEND) { // little-endian needs reversal const uByte *pb; // work Int off; // .. for (pb=d64->bytes; pb<=&d64->bytes[7]; pb++) { off=1-((pb-d64->bytes)>>2); // 1 then 0 sourar[off]<<=8; sourar[off]|=*pb; } // i } else { // big-endian; it's the right way round already pu=(uInt *)d64->bytes; // overlay sourhi=pu[0]; // directly load the high int sourlo=pu[1]; // then the low int } #endif comb=(sourhi>>26)&0x1f; // combination field decNumberZero(dn); // clean number if (sourhi&0x80000000) dn->bits=DECNEG; // set sign if negative msd=COMBMSD[comb]; // decode the combination field exp=COMBEXP[comb]; // .. if (exp==3) { // is a special if (msd==0) { dn->bits|=DECINF; return dn; // no coefficient needed } else if (sourhi&0x02000000) dn->bits|=DECSNAN; else dn->bits|=DECNAN; msd=0; // no top digit } else { // is a finite number dn->exponent=(exp<<8)+((sourhi>>18)&0xff)-DECIMAL64_Bias; // unbiased } // get the coefficient sourhi&=0x0003ffff; // clean coefficient continuation if (msd) { // non-zero msd sourhi|=msd<<18; // prefix to coefficient need=6; // process 6 declets } else { // msd=0 if (!sourhi) { // top word 0 if (!sourlo) return dn; // easy: coefficient is 0 need=3; // process at least 3 declets if (sourlo&0xc0000000) need++; // process 4 declets // [could reduce some more, here] } else { // some bits in top word, msd=0 need=4; // process at least 4 declets if (sourhi&0x0003ff00) need++; // top declet!=0, process 5 } } //msd=0 decDigitsFromDPD(dn, sourar, need); // process declets return dn; } // decimal64ToNumber /* ------------------------------------------------------------------ */ /* to-scientific-string -- conversion to numeric string */ /* to-engineering-string -- conversion to numeric string */ /* */ /* decimal64ToString(d64, string); */ /* decimal64ToEngString(d64, string); */ /* */ /* d64 is the decimal64 format number to convert */ /* string is the string where the result will be laid out */ /* */ /* string must be at least 24 characters */ /* */ /* No error is possible, and no status can be set. */ /* ------------------------------------------------------------------ */ char * decimal64ToEngString(const decimal64 *d64, char *string){ decNumber dn; // work decimal64ToNumber(d64, &dn); decNumberToEngString(&dn, string); return string; } // decimal64ToEngString char * decimal64ToString(const decimal64 *d64, char *string){ uInt msd; // coefficient MSD Int exp; // exponent top two bits or full uInt comb; // combination field char *cstart; // coefficient start char *c; // output pointer in string uInt *pu; // work char *s, *t; // .. (source, target) Int dpd; // .. Int pre, e; // .. const uByte *u; // .. uInt sourar[2]; // source 64-bit #define sourhi sourar[1] // name the word with the sign #define sourlo sourar[0] // and the lower word // load source from storage; this may be endian, or not #if DECENDIAN // DECENDIAN -- direct load, in the right order pu=(uInt *)d64->bytes; // overlay if (LITEND) { sourlo=pu[0]; // directly load the low int sourhi=pu[1]; // then the high int } else { sourhi=pu[0]; // directly load the high int sourlo=pu[1]; // then the low int } #else // not DECENDIAN -- use network byte order if (LITEND) { // little-endian needs reversal const uByte *pb; // work Int off; // .. for (pb=d64->bytes; pb<=&d64->bytes[7]; pb++) { off=1-((pb-d64->bytes)>>2); // 1 then 0 sourar[off]<<=8; sourar[off]|=*pb; } // i } else { // big-endian; it's the right way round already pu=(uInt *)d64->bytes; // overlay sourhi=pu[0]; // directly load the high int sourlo=pu[1]; // then the low int } #endif c=string; // where result will go if (((Int)sourhi)<0) *c++='-'; // handle sign comb=(sourhi>>26)&0x1f; // combination field msd=COMBMSD[comb]; // decode the combination field exp=COMBEXP[comb]; // .. if (exp==3) { if (msd==0) { // infinity strcpy(c, "Infinity"); return string; // easy } if (sourhi&0x02000000) *c++='s'; // sNaN strcpy(c, "NaN"); // complete word c+=3; // step past if (sourlo==0 && (sourhi&0x0003ffff)==0) return string; // zero payload // otherwise drop through to add integer; set correct exp exp=0; msd=0; // setup for following code } else exp=(exp<<8)+((sourhi>>18)&0xff)-DECIMAL64_Bias; // convert 16 digits of significand to characters cstart=c; // save start of coefficient if (msd) *c++='0'+(char)msd; // non-zero most significant digit // Now decode the declets. After extracting each one, it is // decoded to binary and then to a 4-char sequence by table lookup; // the 4-chars are a 1-char length (significant digits, except 000 // has length 0). This allows us to left-align the first declet // with non-zero content, then remaining ones are full 3-char // length. We use fixed-length memcpys because variable-length // causes a subroutine call in GCC. (These are length 4 for speed // and are safe because the array has an extra terminator byte.) #define dpd2char u=&BIN2CHAR[DPD2BIN[dpd]*4]; \ if (c!=cstart) {memcpy(c, u+1, 4); c+=3;} \ else if (*u) {memcpy(c, u+4-*u, 4); c+=*u;} dpd=(sourhi>>8)&0x3ff; // declet 1 dpd2char; dpd=((sourhi&0xff)<<2) | (sourlo>>30); // declet 2 dpd2char; dpd=(sourlo>>20)&0x3ff; // declet 3 dpd2char; dpd=(sourlo>>10)&0x3ff; // declet 4 dpd2char; dpd=(sourlo)&0x3ff; // declet 5 dpd2char; if (c==cstart) *c++='0'; // all zeros -- make 0 if (exp==0) { // integer or NaN case -- easy *c='\0'; // terminate return string; } /* non-0 exponent */ e=0; // assume no E pre=c-cstart+exp; // [here, pre-exp is the digits count (==1 for zero)] if (exp>0 || pre<-5) { // need exponential form e=pre-1; // calculate E value pre=1; // assume one digit before '.' } // exponential form /* modify the coefficient, adding 0s, '.', and E+nn as needed */ s=c-1; // source (LSD) if (pre>0) { // ddd.ddd (plain), perhaps with E char *dotat=cstart+pre; if (dotat=dotat; s--, t--) *t=*s; // open the gap; leave t at gap *t='.'; // insert the dot c++; // length increased by one } // finally add the E-part, if needed; it will never be 0, and has // a maximum length of 3 digits if (e!=0) { *c++='E'; // starts with E *c++='+'; // assume positive if (e<0) { *(c-1)='-'; // oops, need '-' e=-e; // uInt, please } u=&BIN2CHAR[e*4]; // -> length byte memcpy(c, u+4-*u, 4); // copy fixed 4 characters [is safe] c+=*u; // bump pointer appropriately } *c='\0'; // add terminator //printf("res %s\n", string); return string; } // pre>0 /* -5<=pre<=0: here for plain 0.ddd or 0.000ddd forms (can never have E) */ t=c+1-pre; *(t+1)='\0'; // can add terminator now for (; s>=cstart; s--, t--) *t=*s; // shift whole coefficient right c=cstart; *c++='0'; // always starts with 0. *c++='.'; for (; pre<0; pre++) *c++='0'; // add any 0's after '.' //printf("res %s\n", string); return string; } // decimal64ToString /* ------------------------------------------------------------------ */ /* to-number -- conversion from numeric string */ /* */ /* decimal64FromString(result, string, set); */ /* */ /* result is the decimal64 format number which gets the result of */ /* the conversion */ /* *string is the character string which should contain a valid */ /* number (which may be a special value) */ /* set is the context */ /* */ /* The context is supplied to this routine is used for error handling */ /* (setting of status and traps) and for the rounding mode, only. */ /* If an error occurs, the result will be a valid decimal64 NaN. */ /* ------------------------------------------------------------------ */ decimal64 * decimal64FromString(decimal64 *result, const char *string, decContext *set) { decContext dc; // work decNumber dn; // .. decContextDefault(&dc, DEC_INIT_DECIMAL64); // no traps, please dc.round=set->round; // use supplied rounding decNumberFromString(&dn, string, &dc); // will round if needed decimal64FromNumber(result, &dn, &dc); if (dc.status!=0) { // something happened decContextSetStatus(set, dc.status); // .. pass it on } return result; } // decimal64FromString #if DECTRACE || DECCHECK /* ------------------------------------------------------------------ */ /* decimal64Show -- display a decimal64 in hexadecimal [debug aid] */ /* d64 -- the number to show */ /* ------------------------------------------------------------------ */ // Also shows sign/cob/expconfields extracted void decimal64Show(const decimal64 *d64) { char buf[DECIMAL64_Bytes*2+1]; Int i, j=0; #if DECENDIAN if (LITEND) { for (i=0; ibytes[7-i]); } printf(" D64> %s [S:%d Cb:%02x Ec:%02x] LittleEndian\n", buf, d64->bytes[7]>>7, (d64->bytes[7]>>2)&0x1f, ((d64->bytes[7]&0x3)<<6)| (d64->bytes[6]>>2)); } else { #endif for (i=0; ibytes[i]); } printf(" D64> %s [S:%d Cb:%02x Ec:%02x] BigEndian\n", buf, decimal64Sign(d64), decimal64Comb(d64), decimal64ExpCon(d64)); #if DECENDIAN } #endif } // decimal64Show #endif /* ================================================================== */ /* Shared utility routines and tables */ /* ================================================================== */ // define and include the conversion tables to use for shared code #if DECDPUN==3 #define DEC_DPD2BIN 1 #else #define DEC_DPD2BCD 1 #endif #include "decDPD.h" // lookup tables // The maximum number of decNumberUnits needed for a working copy of // the units array is the ceiling of digits/DECDPUN, where digits is // the maximum number of digits in any of the formats for which this // is used. decimal128.h must not be included in this module, so, as // a very special case, that number is defined as a literal here. #define DECMAX754 34 #define DECMAXUNITS ((DECMAX754+DECDPUN-1)/DECDPUN) /* ------------------------------------------------------------------ */ /* Combination field lookup tables (uInts to save measurable work) */ /* */ /* COMBEXP - 2-bit most-significant-bits of exponent */ /* [11 if an Infinity or NaN] */ /* COMBMSD - 4-bit most-significant-digit */ /* [0=Infinity, 1=NaN if COMBEXP=11] */ /* */ /* Both are indexed by the 5-bit combination field (0-31) */ /* ------------------------------------------------------------------ */ const uInt COMBEXP[32]={0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 1, 1, 2, 2, 3, 3}; const uInt COMBMSD[32]={0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 9, 8, 9, 0, 1}; /* ------------------------------------------------------------------ */ /* decDigitsToDPD -- pack coefficient into DPD form */ /* */ /* dn is the source number (assumed valid, max DECMAX754 digits) */ /* targ is 1, 2, or 4-element uInt array, which the caller must */ /* have cleared to zeros */ /* shift is the number of 0 digits to add on the right (normally 0) */ /* */ /* The coefficient must be known small enough to fit. The full */ /* coefficient is copied, including the leading 'odd' digit. This */ /* digit is retrieved and packed into the combination field by the */ /* caller. */ /* */ /* The target uInts are altered only as necessary to receive the */ /* digits of the decNumber. When more than one uInt is needed, they */ /* are filled from left to right (that is, the uInt at offset 0 will */ /* end up with the least-significant digits). */ /* */ /* shift is used for 'fold-down' padding. */ /* */ /* No error is possible. */ /* ------------------------------------------------------------------ */ #if DECDPUN<=4 // Constant multipliers for divide-by-power-of five using reciprocal // multiply, after removing powers of 2 by shifting, and final shift // of 17 [we only need up to **4] static const uInt multies[]={131073, 26215, 5243, 1049, 210}; // QUOT10 -- macro to return the quotient of unit u divided by 10**n #define QUOT10(u, n) ((((uInt)(u)>>(n))*multies[n])>>17) #endif void decDigitsToDPD(const decNumber *dn, uInt *targ, Int shift) { Int cut; // work Int n; // output bunch counter Int digits=dn->digits; // digit countdown uInt dpd; // densely packed decimal value uInt bin; // binary value 0-999 uInt *uout=targ; // -> current output uInt uInt uoff=0; // -> current output offset [from right] const Unit *inu=dn->lsu; // -> current input unit Unit uar[DECMAXUNITS]; // working copy of units, iff shifted #if DECDPUN!=3 // not fast path Unit in; // current unit #endif if (shift!=0) { // shift towards most significant required // shift the units array to the left by pad digits and copy // [this code is a special case of decShiftToMost, which could // be used instead if exposed and the array were copied first] const Unit *source; // .. Unit *target, *first; // .. uInt next=0; // work source=dn->lsu+D2U(digits)-1; // where msu comes from target=uar+D2U(digits)-1+D2U(shift);// where upper part of first cut goes cut=DECDPUN-MSUDIGITS(shift); // where to slice if (cut==0) { // unit-boundary case for (; source>=dn->lsu; source--, target--) *target=*source; } else { first=uar+D2U(digits+shift)-1; // where msu will end up for (; source>=dn->lsu; source--, target--) { // split the source Unit and accumulate remainder for next #if DECDPUN<=4 uInt quot=QUOT10(*source, cut); uInt rem=*source-quot*powers[cut]; next+=quot; #else uInt rem=*source%powers[cut]; next+=*source/powers[cut]; #endif if (target<=first) *target=(Unit)next; // write to target iff valid next=rem*powers[DECDPUN-cut]; // save remainder for next Unit } } // shift-move // propagate remainder to one below and clear the rest for (; target>=uar; target--) { *target=(Unit)next; next=0; } digits+=shift; // add count (shift) of zeros added inu=uar; // use units in working array } /* now densely pack the coefficient into DPD declets */ #if DECDPUN!=3 // not fast path in=*inu; // current unit cut=0; // at lowest digit bin=0; // [keep compiler quiet] #endif for(n=0; digits>0; n++) { // each output bunch #if DECDPUN==3 // fast path, 3-at-a-time bin=*inu; // 3 digits ready for convert digits-=3; // [may go negative] inu++; // may need another #else // must collect digit-by-digit Unit dig; // current digit Int j; // digit-in-declet count for (j=0; j<3; j++) { #if DECDPUN<=4 Unit temp=(Unit)((uInt)(in*6554)>>16); dig=(Unit)(in-X10(temp)); in=temp; #else dig=in%10; in=in/10; #endif if (j==0) bin=dig; else if (j==1) bin+=X10(dig); else /* j==2 */ bin+=X100(dig); digits--; if (digits==0) break; // [also protects *inu below] cut++; if (cut==DECDPUN) {inu++; in=*inu; cut=0;} } #endif // here there are 3 digits in bin, or have used all input digits dpd=BIN2DPD[bin]; // write declet to uInt array *uout|=dpd<>(10-uoff); // collect top bits } // n declets return; } // decDigitsToDPD /* ------------------------------------------------------------------ */ /* decDigitsFromDPD -- unpack a format's coefficient */ /* */ /* dn is the target number, with 7, 16, or 34-digit space. */ /* sour is a 1, 2, or 4-element uInt array containing only declets */ /* declets is the number of (right-aligned) declets in sour to */ /* be processed. This may be 1 more than the obvious number in */ /* a format, as any top digit is prefixed to the coefficient */ /* continuation field. It also may be as small as 1, as the */ /* caller may pre-process leading zero declets. */ /* */ /* When doing the 'extra declet' case care is taken to avoid writing */ /* extra digits when there are leading zeros, as these could overflow */ /* the units array when DECDPUN is not 3. */ /* */ /* The target uInts are used only as necessary to process declets */ /* declets into the decNumber. When more than one uInt is needed, */ /* they are used from left to right (that is, the uInt at offset 0 */ /* provides the least-significant digits). */ /* */ /* dn->digits is set, but not the sign or exponent. */ /* No error is possible [the redundant 888 codes are allowed]. */ /* ------------------------------------------------------------------ */ void decDigitsFromDPD(decNumber *dn, const uInt *sour, Int declets) { uInt dpd; // collector for 10 bits Int n; // counter Unit *uout=dn->lsu; // -> current output unit Unit *last=uout; // will be unit containing msd const uInt *uin=sour; // -> current input uInt uInt uoff=0; // -> current input offset [from right] #if DECDPUN!=3 uInt bcd; // BCD result uInt nibble; // work Unit out=0; // accumulator Int cut=0; // power of ten in current unit #endif #if DECDPUN>4 uInt const *pow; // work #endif // Expand the densely-packed integer, right to left for (n=declets-1; n>=0; n--) { // count down declets of 10 bits dpd=*uin>>uoff; uoff+=10; if (uoff>32) { // crossed uInt boundary uin++; uoff-=32; dpd|=*uin<<(10-uoff); // get waiting bits } dpd&=0x3ff; // clear uninteresting bits #if DECDPUN==3 if (dpd==0) *uout=0; else { *uout=DPD2BIN[dpd]; // convert 10 bits to binary 0-999 last=uout; // record most significant unit } uout++; } // n #else // DECDPUN!=3 if (dpd==0) { // fastpath [e.g., leading zeros] // write out three 0 digits (nibbles); out may have digit(s) cut++; if (cut==DECDPUN) {*uout=out; if (out) {last=uout; out=0;} uout++; cut=0;} if (n==0) break; // [as below, works even if MSD=0] cut++; if (cut==DECDPUN) {*uout=out; if (out) {last=uout; out=0;} uout++; cut=0;} cut++; if (cut==DECDPUN) {*uout=out; if (out) {last=uout; out=0;} uout++; cut=0;} continue; } bcd=DPD2BCD[dpd]; // convert 10 bits to 12 bits BCD // now accumulate the 3 BCD nibbles into units nibble=bcd & 0x00f; if (nibble) out=(Unit)(out+nibble*powers[cut]); cut++; if (cut==DECDPUN) {*uout=out; if (out) {last=uout; out=0;} uout++; cut=0;} bcd>>=4; // if this is the last declet and the remaining nibbles in bcd // are 00 then process no more nibbles, because this could be // the 'odd' MSD declet and writing any more Units would then // overflow the unit array if (n==0 && !bcd) break; nibble=bcd & 0x00f; if (nibble) out=(Unit)(out+nibble*powers[cut]); cut++; if (cut==DECDPUN) {*uout=out; if (out) {last=uout; out=0;} uout++; cut=0;} bcd>>=4; nibble=bcd & 0x00f; if (nibble) out=(Unit)(out+nibble*powers[cut]); cut++; if (cut==DECDPUN) {*uout=out; if (out) {last=uout; out=0;} uout++; cut=0;} } // n if (cut!=0) { // some more left over *uout=out; // write out final unit if (out) last=uout; // and note if non-zero } #endif // here, last points to the most significant unit with digits; // inspect it to get the final digits count -- this is essentially // the same code as decGetDigits in decNumber.c dn->digits=(last-dn->lsu)*DECDPUN+1; // floor of digits, plus // must be at least 1 digit #if DECDPUN>1 if (*last<10) return; // common odd digit or 0 dn->digits++; // must be 2 at least #if DECDPUN>2 if (*last<100) return; // 10-99 dn->digits++; // must be 3 at least #if DECDPUN>3 if (*last<1000) return; // 100-999 dn->digits++; // must be 4 at least #if DECDPUN>4 for (pow=&powers[4]; *last>=*pow; pow++) dn->digits++; #endif #endif #endif #endif return; } //decDigitsFromDPD hercules-3.07/decNumber/decimal64.h000644 000765 000765 00000011332 11143760537 020577 0ustar00jmaynardjmaynard000000 000000 /* ------------------------------------------------------------------ */ /* Decimal 64-bit format module header */ /* ------------------------------------------------------------------ */ /* Copyright (c) IBM Corporation, 2000, 2005. All rights reserved. */ /* */ /* This software is made available under the terms of the */ /* ICU License -- ICU 1.8.1 and later. */ /* */ /* The description and User's Guide ("The decNumber C Library") for */ /* this software is called decNumber.pdf. This document is */ /* available, together with arithmetic and format specifications, */ /* testcases, and Web links, at: http://www2.hursley.ibm.com/decimal */ /* */ /* Please send comments, suggestions, and corrections to the author: */ /* mfc@uk.ibm.com */ /* Mike Cowlishaw, IBM Fellow */ /* IBM UK, PO Box 31, Birmingham Road, Warwick CV34 5JL, UK */ /* ------------------------------------------------------------------ */ #if !defined(DECIMAL64) #define DECIMAL64 #define DEC64NAME "decimal64" /* Short name */ #define DEC64FULLNAME "Decimal 64-bit Number" /* Verbose name */ #define DEC64AUTHOR "Mike Cowlishaw" /* Who to blame */ /* parameters for decimal64s */ #define DECIMAL64_Bytes 8 // length #define DECIMAL64_Pmax 16 // maximum precision (digits) #define DECIMAL64_Emax 384 // maximum adjusted exponent #define DECIMAL64_Emin -383 // minimum adjusted exponent #define DECIMAL64_Bias 398 // bias for the exponent #define DECIMAL64_String 24 // maximum string length, +1 #define DECIMAL64_EconL 8 // exponent continuation length // highest biased exponent (Elimit-1) #define DECIMAL64_Ehigh (DECIMAL64_Emax+DECIMAL64_Bias-DECIMAL64_Pmax+1) // check enough digits, if pre-defined #if defined(DECNUMDIGITS) #if (DECNUMDIGITS=16 for safe use #endif #endif #ifndef DECNUMDIGITS #define DECNUMDIGITS DECIMAL64_Pmax // size if not already defined #endif #ifndef DECNUMBER #include "decNumber.h" // context and number library #endif /* Decimal 64-bit type, accessible by bytes */ typedef struct { uint8_t bytes[DECIMAL64_Bytes]; // decimal64: 1, 5, 8, 50 bits } decimal64; /* special values [top byte excluding sign bit; last two bits are don't-care for Infinity on input, last bit don't-care for NaN] */ #if !defined(DECIMAL_NaN) #define DECIMAL_NaN 0x7c // 0 11111 00 NaN #define DECIMAL_sNaN 0x7e // 0 11111 10 sNaN #define DECIMAL_Inf 0x78 // 0 11110 00 Infinity #endif /* Macros for accessing decimal64 fields. These assume the argument is a reference (pointer) to the decimal64 structure, and the decimal64 is in network byte order (big-endian) */ // Get sign #define decimal64Sign(d) ((unsigned)(d)->bytes[0]>>7) // Get combination field #define decimal64Comb(d) (((d)->bytes[0] & 0x7c)>>2) // Get exponent continuation [does not remove bias] #define decimal64ExpCon(d) ((((d)->bytes[0] & 0x03)<<6) \ | ((unsigned)(d)->bytes[1]>>2)) // Set sign [this assumes sign previously 0] #define decimal64SetSign(d, b) { \ (d)->bytes[0]|=((unsigned)(b)<<7);} // Set exponent continuation [does not apply bias] // This assumes range has been checked and exponent previously 0; type // of exponent must be unsigned #define decimal64SetExpCon(d, e) { \ (d)->bytes[0]|=(uint8_t)((e)>>6); \ (d)->bytes[1]|=(uint8_t)(((e)&0x3F)<<2);} /* ------------------------------------------------------------------ */ /* Routines */ /* ------------------------------------------------------------------ */ // String conversions decimal64 * decimal64FromString(decimal64 *, const char *, decContext *); char * decimal64ToString(const decimal64 *, char *); char * decimal64ToEngString(const decimal64 *, char *); // decNumber conversions decimal64 * decimal64FromNumber(decimal64 *, const decNumber *, decContext *); decNumber * decimal64ToNumber(const decimal64 *, decNumber *); #endif hercules-3.07/decNumber/decNumber.c000644 000765 000765 00001144567 11202676511 020742 0ustar00jmaynardjmaynard000000 000000 /* ------------------------------------------------------------------ */ /* Decimal Number arithmetic module */ /* ------------------------------------------------------------------ */ /* Copyright (c) IBM Corporation, 2000, 2006. All rights reserved. */ /* */ /* This software is made available under the terms of the */ /* ICU License -- ICU 1.8.1 and later. */ /* */ /* The description and User's Guide ("The decNumber C Library") for */ /* this software is called decNumber.pdf. This document is */ /* available, together with arithmetic and format specifications, */ /* testcases, and Web links, at: http://www2.hursley.ibm.com/decimal */ /* */ /* Please send comments, suggestions, and corrections to the author: */ /* mfc@uk.ibm.com */ /* Mike Cowlishaw, IBM Fellow */ /* IBM UK, PO Box 31, Birmingham Road, Warwick CV34 5JL, UK */ /* ------------------------------------------------------------------ */ /* This module comprises the routines for General Decimal Arithmetic */ /* as defined in the specification which may be found on the */ /* http://www2.hursley.ibm.com/decimal web pages. It implements both */ /* the full ('extended') arithmetic and the simpler ('subset') */ /* arithmetic. */ /* */ /* Usage notes: */ /* */ /* 1. This code is ANSI C89 except: */ /* */ /* a) C99 line comments (double forward slash) are used. (Most C */ /* compilers accept these. If yours does not, a simple script */ /* can be used to convert them to ANSI C comments.) */ /* */ /* b) Types from C99 stdint.h are used. If you do not have this */ /* header file, see the User's Guide section of the decNumber */ /* documentation; this lists the necessary definitions. */ /* */ /* c) If DECDPUN>4 or DECUSE64=1, the C99 64-bit int64_t and */ /* uint64_t types may be used. To avoid these, set DECUSE64=0 */ /* and DECDPUN<=4 (see documentation). */ /* */ /* 2. The decNumber format which this library uses is optimized for */ /* efficient processing of relatively short numbers; in particular */ /* it allows the use of fixed sized structures and minimizes copy */ /* and move operations. It does, however, support arbitrary */ /* precision (up to 999,999,999 digits) and arbitrary exponent */ /* range (Emax in the range 0 through 999,999,999 and Emin in the */ /* range -999,999,999 through 0). Mathematical functions (for */ /* example decNumberExp) as identified below are restricted more */ /* tightly: digits, emax, and -emin in the context must be <= */ /* DEC_MAX_MATH (999999), and their operand(s) must be within */ /* these bounds. */ /* */ /* 3. Operands to operator functions are never modified unless they */ /* are also specified to be the result number (which is always */ /* permitted). Other than that case, operands must not overlap. */ /* */ /* 4. Error handling: the type of the error is ORed into the status */ /* flags in the current context (decContext structure). The */ /* SIGFPE signal is then raised if the corresponding trap-enabler */ /* flag in the decContext is set (is 1). */ /* */ /* It is the responsibility of the caller to clear the status */ /* flags as required. */ /* */ /* The result of any routine which returns a number will always */ /* be a valid number (which may be a special value, such as an */ /* Infinity or NaN). */ /* */ /* 5. The decNumber format is not an exchangeable concrete */ /* representation as it comprises fields which may be machine- */ /* dependent (packed or unpacked, or special length, for example). */ /* Canonical conversions to and from strings are provided; other */ /* conversions are available in separate modules. */ /* */ /* 6. Normally, input operands are assumed to be valid. Set DECCHECK */ /* to 1 for extended operand checking (including NULL operands). */ /* Results are undefined if a badly-formed structure (or a NULL */ /* pointer to a structure) is provided, though with DECCHECK */ /* enabled the operator routines are protected against exceptions. */ /* (Except if the result pointer is NULL, which is unrecoverable.) */ /* */ /* However, the routines will never cause exceptions if they are */ /* given well-formed operands, even if the value of the operands */ /* is inappropriate for the operation and DECCHECK is not set. */ /* (Except for SIGFPE, as and where documented.) */ /* */ /* 7. Subset arithmetic is available only if DECSUBSET is set to 1. */ /* ------------------------------------------------------------------ */ /* Implementation notes for maintenance of this module: */ /* */ /* 1. Storage leak protection: Routines which use malloc are not */ /* permitted to use return for fastpath or error exits (i.e., */ /* they follow strict structured programming conventions). */ /* Instead they have a do{}while(0); construct surrounding the */ /* code which is protected -- break may be used to exit this. */ /* Other routines can safely use the return statement inline. */ /* */ /* Storage leak accounting can be enabled using DECALLOC. */ /* */ /* 2. All loops use the for(;;) construct. Any do construct does */ /* not loop; it is for allocation protection as just described. */ /* */ /* 3. Setting status in the context must always be the very last */ /* action in a routine, as non-0 status may raise a trap and hence */ /* the call to set status may not return (if the handler uses long */ /* jump). Therefore all cleanup must be done first. In general, */ /* to achieve this status is accumulated and is only applied just */ /* before return by calling decContextSetStatus (via decStatus). */ /* */ /* Routines which allocate storage cannot, in general, use the */ /* 'top level' routines which could cause a non-returning */ /* transfer of control. The decXxxxOp routines are safe (do not */ /* call decStatus even if traps are set in the context) and should */ /* be used instead (they are also a little faster). */ /* */ /* 4. Exponent checking is minimized by allowing the exponent to */ /* grow outside its limits during calculations, provided that */ /* the decFinalize function is called later. Multiplication and */ /* division, and intermediate calculations in exponentiation, */ /* require more careful checks because of the risk of 31-bit */ /* overflow (the most negative valid exponent is -1999999997, for */ /* a 999999999-digit number with adjusted exponent of -999999999). */ /* */ /* 5. Rounding is deferred until finalization of results, with any */ /* 'off to the right' data being represented as a single digit */ /* residue (in the range -1 through 9). This avoids any double- */ /* rounding when more than one shortening takes place (for */ /* example, when a result is subnormal). */ /* */ /* 6. The digits count is allowed to rise to a multiple of DECDPUN */ /* during many operations, so whole Units are handled and exact */ /* accounting of digits is not needed. The correct digits value */ /* is found by decGetDigits, which accounts for leading zeros. */ /* This must be called before any rounding if the number of digits */ /* is not known exactly. */ /* */ /* 7. The multiply-by-reciprocal 'trick' is used for partitioning */ /* numbers up to four digits, using appropriate constants. This */ /* is not useful for longer numbers because overflow of 32 bits */ /* would lead to 4 multiplies, which is almost as expensive as */ /* a divide (unless a floating-point or 64-bit multiply is */ /* assumed to be available). */ /* */ /* 8. Unusual abbreviations that may be used in the commentary: */ /* lhs -- left hand side (operand, of an operation) */ /* lsd -- least significant digit (of coefficient) */ /* lsu -- least significant Unit (of coefficient) */ /* msd -- most significant digit (of coefficient) */ /* msi -- most significant item (in an array) */ /* msu -- most significant Unit (of coefficient) */ /* rhs -- right hand side (operand, of an operation) */ /* +ve -- positive */ /* -ve -- negative */ /* ** -- raise to the power */ /* ------------------------------------------------------------------ */ #include // for malloc, free, etc. #include // for printf [if needed] #include // for strcpy #include // for lower #if defined(_MSVC_) #pragma warning(disable:4244) // [for win64] #endif /*defined(_MSVC_)*/ #include "decNumber.h" // base number library #include "decNumberLocal.h" // decNumber local types, etc. /* Constants */ // Public constant array: powers of ten (powers[n]==10**n, 0<=n<=9) const uInt powers[10]={1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000}; // Public lookup table used by the D2U macro const uByte d2utable[DECMAXD2U+1]=D2UTABLE; // Local constants #define DIVIDE 0x80 // Divide operators #define REMAINDER 0x40 // .. #define DIVIDEINT 0x20 // .. #define REMNEAR 0x10 // .. #define COMPARE 0x01 // Compare operators #define COMPMAX 0x02 // .. #define COMPMIN 0x03 // .. #define COMPTOTAL 0x04 // .. #define COMPNAN 0x05 // .. [NaN processing] #define DEC_sNaN 0x40000000 // local status: sNaN signal #define BADINT (Int)0x80000000 // most-negative Int; error indicator // Next two indicate an integer >= 10**6, and its parity (bottom bit) #define BIGEVEN (Int)0x80000002 #define BIGODD (Int)0x80000003 static Unit uarrone[1]={1}; // Unit array of 1, used for incrementing /* Granularity-dependent code */ #if DECDPUN<=4 #define eInt Int // extended integer #define ueInt uInt // unsigned extended integer // Constant multipliers for divide-by-power-of five using reciprocal // multiply, after removing powers of 2 by shifting, and final shift // of 17 [we only need up to **4] static const uInt multies[]={131073, 26215, 5243, 1049, 210}; // QUOT10 -- macro to return the quotient of unit u divided by 10**n #define QUOT10(u, n) ((((uInt)(u)>>(n))*multies[n])>>17) #else // For DECDPUN>4 non-ANSI-89 64-bit types are needed. #if !DECUSE64 #error decNumber.c: DECUSE64 must be 1 when DECDPUN>4 #endif #define eInt Long // extended integer #define ueInt uLong // unsigned extended integer #endif /* Local routines */ static decNumber * decAddOp(decNumber *, const decNumber *, const decNumber *, decContext *, uByte, uInt *); static Flag decBiStr(const char *, const char *, const char *); static uInt decCheckMath(const decNumber *, decContext *, uInt *); static void decApplyRound(decNumber *, decContext *, Int, uInt *); static Int decCompare(const decNumber *lhs, const decNumber *rhs, Flag); static decNumber * decCompareOp(decNumber *, const decNumber *, const decNumber *, decContext *, Flag, uInt *); static void decCopyFit(decNumber *, const decNumber *, decContext *, Int *, uInt *); static decNumber * decDivideOp(decNumber *, const decNumber *, const decNumber *, decContext *, Flag, uInt *); static decNumber * decExpOp(decNumber *, const decNumber *, decContext *, uInt *); static void decFinalize(decNumber *, decContext *, Int *, uInt *); static Int decGetDigits(Unit *, Int); static Int decGetInt(const decNumber *); static decNumber * decLnOp(decNumber *, const decNumber *, decContext *, uInt *); static decNumber * decMultiplyOp(decNumber *, const decNumber *, const decNumber *, decContext *, uInt *); static decNumber * decNaNs(decNumber *, const decNumber *, const decNumber *, uInt *); static decNumber * decPutInt(decNumber *, Int); static decNumber * decQuantizeOp(decNumber *, const decNumber *, const decNumber *, decContext *, Flag, uInt *); static void decSetCoeff(decNumber *, decContext *, const Unit *, Int, Int *, uInt *); static void decSetOverflow(decNumber *, decContext *, uInt *); static void decSetSubnormal(decNumber *, decContext *, Int *, uInt *); static Int decShiftToLeast(Unit *, Int, Int); static Int decShiftToMost(Unit *, Int, Int); static void decStatus(decNumber *, uInt, decContext *); static void decToString(const decNumber *, char[], Flag); static decNumber * decTrim(decNumber *, Flag, Int *); static Int decUnitAddSub(const Unit *, Int, const Unit *, Int, Int, Unit *, Int); static Int decUnitCompare(const Unit *, Int, const Unit *, Int, Int); #if !DECSUBSET /* decFinish == decFinalize when no subset arithmetic needed */ #define decFinish(a,b,c,d) decFinalize(a,b,c,d) #else static void decFinish(decNumber *, decContext *, Int *, uInt *); static decNumber * decRoundOperand(const decNumber *, decContext *, uInt *); #endif /* Local macros */ // masked special-values bits #define SPECIALARG (rhs->bits & DECSPECIAL) #define SPECIALARGS ((lhs->bits | rhs->bits) & DECSPECIAL) /* Diagnostic macros, etc. */ #if DECALLOC // Handle malloc/free accounting. If enabled, our accountable routines // are used; otherwise the code just goes straight to the system malloc // and free routines. #define malloc(a) decMalloc(a) #define free(a) decFree(a) #define DECFENCE 0x5a // corruption detector // 'Our' malloc and free: static void *decMalloc(size_t); static void decFree(void *); uInt decAllocBytes=0; // count of bytes allocated // Note that DECALLOC code only checks for storage buffer overflow. // To check for memory leaks, the decAllocBytes variable must be // checked to be 0 at appropriate times (e.g., after the test // harness completes a set of tests). This checking may be unreliable // if the testing is done in a multi-thread environment. #endif #if DECCHECK // Optional checking routines. Enabling these means that decNumber // and decContext operands to operator routines are checked for // correctness. This roughly doubles the execution time of the // fastest routines (and adds 600+ bytes), so should not normally be // used in 'production'. // decCheckInexact is used to check that inexact results have a full // complement of digits (where appropriate -- this is not the case // for Quantize, for example) #define DECUNUSED (void *)(0xffffffff) static Flag decCheckOperands(decNumber *, const decNumber *, const decNumber *, decContext *); static Flag decCheckNumber(const decNumber *, decContext *); static void decCheckInexact(const decNumber *, decContext *); #endif #if DECTRACE || DECCHECK // Optional trace/debugging routines (may or may not be used) void decNumberShow(const decNumber *); // displays the components of a number static void decDumpAr(char, const Unit *, Int); #endif /* ================================================================== */ /* Conversions */ /* ================================================================== */ /* ------------------------------------------------------------------ */ /* to-scientific-string -- conversion to numeric string */ /* to-engineering-string -- conversion to numeric string */ /* */ /* decNumberToString(dn, string); */ /* decNumberToEngString(dn, string); */ /* */ /* dn is the decNumber to convert */ /* string is the string where the result will be laid out */ /* */ /* string must be at least dn->digits+14 characters long */ /* */ /* No error is possible, and no status can be set. */ /* ------------------------------------------------------------------ */ char * decNumberToString(const decNumber *dn, char *string){ decToString(dn, string, 0); return string; } // DecNumberToString char * decNumberToEngString(const decNumber *dn, char *string){ decToString(dn, string, 1); return string; } // DecNumberToEngString /* ------------------------------------------------------------------ */ /* to-number -- conversion from numeric string */ /* */ /* decNumberFromString -- convert string to decNumber */ /* dn -- the number structure to fill */ /* chars[] -- the string to convert ('\0' terminated) */ /* set -- the context used for processing any error, */ /* determining the maximum precision available */ /* (set.digits), determining the maximum and minimum */ /* exponent (set.emax and set.emin), determining if */ /* extended values are allowed, and checking the */ /* rounding mode if overflow occurs or rounding is */ /* needed. */ /* */ /* The length of the coefficient and the size of the exponent are */ /* checked by this routine, so the correct error (Underflow or */ /* Overflow) can be reported or rounding applied, as necessary. */ /* */ /* If bad syntax is detected, the result will be a quiet NaN. */ /* ------------------------------------------------------------------ */ decNumber * decNumberFromString(decNumber *dn, const char chars[], decContext *set) { Int exponent=0; // working exponent [assume 0] uByte bits=0; // working flags [assume +ve] Unit *res; // where result will be built Unit resbuff[SD2U(DECBUFFER+1)];// local buffer in case need temporary Unit *allocres=NULL; // -> allocated result, iff allocated Int d=0; // count of digits found in decimal part const char *dotchar=NULL; // where dot was found const char *cfirst=chars; // -> first character of decimal part const char *last=NULL; // -> last digit of decimal part const char *c; // work Unit *up; // .. #if DECDPUN>1 Int cut, out; // .. #endif Int residue; // rounding residue uInt status=0; // error code #if DECCHECK if (decCheckOperands(DECUNUSED, DECUNUSED, DECUNUSED, set)) return decNumberZero(dn); #endif do { // status & malloc protection for (c=chars;; c++) { // -> input character if (*c>='0' && *c<='9') { // test for Arabic digit last=c; d++; // count of real digits continue; // still in decimal part } if (*c=='.' && dotchar==NULL) { // first '.' dotchar=c; // record offset into decimal part if (c==cfirst) cfirst++; // first digit must follow continue;} if (c==chars) { // first in string... if (*c=='-') { // valid - sign cfirst++; bits=DECNEG; continue;} if (*c=='+') { // valid + sign cfirst++; continue;} } // *c is not a digit, or a valid +, -, or '.' break; } // c if (last==NULL) { // no digits yet status=DEC_Conversion_syntax;// assume the worst if (*c=='\0') break; // and no more to come... #if DECSUBSET // if subset then infinities and NaNs are not allowed if (!set->extended) break; // hopeless #endif // Infinities and NaNs are possible, here if (dotchar!=NULL) break; // .. unless had a dot decNumberZero(dn); // be optimistic if (decBiStr(c, "infinity", "INFINITY") || decBiStr(c, "inf", "INF")) { dn->bits=bits | DECINF; status=0; // is OK break; // all done } // a NaN expected // 2003.09.10 NaNs are now permitted to have a sign dn->bits=bits | DECNAN; // assume simple NaN if (*c=='s' || *c=='S') { // looks like an sNaN c++; dn->bits=bits | DECSNAN; } if (*c!='n' && *c!='N') break; // check caseless "NaN" c++; if (*c!='a' && *c!='A') break; // .. c++; if (*c!='n' && *c!='N') break; // .. c++; // now either nothing, or nnnn payload, expected // -> start of integer and skip leading 0s [including plain 0] for (cfirst=c; *cfirst=='0';) cfirst++; if (*cfirst=='\0') { // "NaN" or "sNaN", maybe with all 0s status=0; // it's good break; // .. } // something other than 0s; setup last and d as usual [no dots] for (c=cfirst;; c++, d++) { if (*c<'0' || *c>'9') break; // test for Arabic digit last=c; } if (*c!='\0') break; // not all digits if (d>set->digits-1) { // [NB: payload in a decNumber can be full length unless // clamped, in which case can only be digits-1] if (set->clamp) break; if (d>set->digits) break; } // too many digits? // good; drop through to convert the integer to coefficient status=0; // syntax is OK bits=dn->bits; // for copy-back } // last==NULL else if (*c!='\0') { // more to process... // had some digits; exponent is only valid sequence now Flag nege; // 1=negative exponent const char *firstexp; // -> first significant exponent digit status=DEC_Conversion_syntax;// assume the worst if (*c!='e' && *c!='E') break; /* Found 'e' or 'E' -- now process explicit exponent */ // 1998.07.11: sign no longer required nege=0; c++; // to (possible) sign if (*c=='-') {nege=1; c++;} else if (*c=='+') c++; if (*c=='\0') break; for (; *c=='0' && *(c+1)!='\0';) c++; // strip insignificant zeros firstexp=c; // save exponent digit place for (; ;c++) { if (*c<'0' || *c>'9') break; // not a digit exponent=X10(exponent)+(Int)*c-(Int)'0'; } // c // if not now on a '\0', *c must not be a digit if (*c!='\0') break; // (this next test must be after the syntax checks) // if it was too long the exponent may have wrapped, so check // carefully and set it to a certain overflow if wrap possible if (c>=firstexp+9+1) { if (c>firstexp+9+1 || *firstexp>'1') exponent=DECNUMMAXE*2; // [up to 1999999999 is OK, for example 1E-1000000998] } if (nege) exponent=-exponent; // was negative status=0; // is OK } // stuff after digits // Here when whole string has been inspected; syntax is good // cfirst->first digit (never dot), last->last digit (ditto) // strip leading zeros/dot [leave final 0 if all 0's] if (*cfirst=='0') { // [cfirst has stepped over .] for (c=cfirst; cextended) { decNumberZero(dn); // clean result break; // [could be return] } #endif } // at least one leading 0 // Handle decimal point... if (dotchar!=NULL && dotchardigits) res=dn->lsu; // fits into supplied decNumber else { // rounding needed Int needbytes=D2U(d)*sizeof(Unit);// bytes needed res=resbuff; // assume use local buffer if (needbytes>(Int)sizeof(resbuff)) { // too big for local allocres=(Unit *)malloc(needbytes); if (allocres==NULL) {status|=DEC_Insufficient_storage; break;} res=allocres; } } // res now -> number lsu, buffer, or allocated storage for Unit array // Place the coefficient into the selected Unit array // [this is often 70% of the cost of this function when DECDPUN>1] #if DECDPUN>1 out=0; // accumulator up=res+D2U(d)-1; // -> msu cut=d-(up-res)*DECDPUN; // digits in top unit for (c=cfirst;; c++) { // along the digits if (*c=='.') continue; // ignore '.' [don't decrement cut] out=X10(out)+(Int)*c-(Int)'0'; if (c==last) break; // done [never get to trailing '.'] cut--; if (cut>0) continue; // more for this unit *up=(Unit)out; // write unit up--; // prepare for unit below.. cut=DECDPUN; // .. out=0; // .. } // c *up=(Unit)out; // write lsu #else // DECDPUN==1 up=res; // -> lsu for (c=last; c>=cfirst; c--) { // over each character, from least if (*c=='.') continue; // ignore . [don't step up] *up=(Unit)((Int)*c-(Int)'0'); up++; } // c #endif dn->bits=bits; dn->exponent=exponent; dn->digits=d; // if not in number (too long) shorten into the number if (d>set->digits) { residue=0; decSetCoeff(dn, set, res, d, &residue, &status); // always check for overflow or subnormal and round as needed decFinalize(dn, set, &residue, &status); } else { // no rounding, but may still have overflow or subnormal // [these tests are just for performance; finalize repeats them] if ((dn->exponent-1emin-dn->digits) || (dn->exponent-1>set->emax-set->digits)) { residue=0; decFinalize(dn, set, &residue, &status); } } // decNumberShow(dn); } while(0); // [for break] if (allocres!=NULL) free(allocres); // drop any storage used if (status!=0) decStatus(dn, status, set); return dn; } /* decNumberFromString */ /* ================================================================== */ /* Operators */ /* ================================================================== */ /* ------------------------------------------------------------------ */ /* decNumberAbs -- absolute value operator */ /* */ /* This computes C = abs(A) */ /* */ /* res is C, the result. C may be A */ /* rhs is A */ /* set is the context */ /* */ /* C must have space for set->digits digits. */ /* ------------------------------------------------------------------ */ /* This has the same effect as decNumberPlus unless A is negative, */ /* in which case it has the same effect as decNumberMinus. */ /* ------------------------------------------------------------------ */ decNumber * decNumberAbs(decNumber *res, const decNumber *rhs, decContext *set) { decNumber dzero; // for 0 uInt status=0; // accumulator #if DECCHECK if (decCheckOperands(res, DECUNUSED, rhs, set)) return res; #endif decNumberZero(&dzero); // set 0 dzero.exponent=rhs->exponent; // [no coefficient expansion] decAddOp(res, &dzero, rhs, set, (uByte)(rhs->bits & DECNEG), &status); if (status!=0) decStatus(res, status, set); #if DECCHECK decCheckInexact(res, set); #endif return res; } // decNumberAbs /* ------------------------------------------------------------------ */ /* decNumberAdd -- add two Numbers */ /* */ /* This computes C = A + B */ /* */ /* res is C, the result. C may be A and/or B (e.g., X=X+X) */ /* lhs is A */ /* rhs is B */ /* set is the context */ /* */ /* C must have space for set->digits digits. */ /* ------------------------------------------------------------------ */ /* This just calls the routine shared with Subtract */ decNumber * decNumberAdd(decNumber *res, const decNumber *lhs, const decNumber *rhs, decContext *set) { uInt status=0; // accumulator decAddOp(res, lhs, rhs, set, 0, &status); if (status!=0) decStatus(res, status, set); #if DECCHECK decCheckInexact(res, set); #endif return res; } // decNumberAdd /* ------------------------------------------------------------------ */ /* decNumberCompare -- compare two Numbers */ /* */ /* This computes C = A ? B */ /* */ /* res is C, the result. C may be A and/or B (e.g., X=X?X) */ /* lhs is A */ /* rhs is B */ /* set is the context */ /* */ /* C must have space for one digit (or NaN). */ /* ------------------------------------------------------------------ */ decNumber * decNumberCompare(decNumber *res, const decNumber *lhs, const decNumber *rhs, decContext *set) { uInt status=0; // accumulator decCompareOp(res, lhs, rhs, set, COMPARE, &status); if (status!=0) decStatus(res, status, set); return res; } // decNumberCompare /* ------------------------------------------------------------------ */ /* decNumberCompareTotal -- compare two Numbers, using total ordering */ /* */ /* This computes C = A ? B, under total ordering */ /* */ /* res is C, the result. C may be A and/or B (e.g., X=X?X) */ /* lhs is A */ /* rhs is B */ /* set is the context */ /* */ /* C must have space for one digit; the result will always be one of */ /* -1, 0, or 1. */ /* ------------------------------------------------------------------ */ decNumber * decNumberCompareTotal(decNumber *res, const decNumber *lhs, const decNumber *rhs, decContext *set) { uInt status=0; // accumulator decCompareOp(res, lhs, rhs, set, COMPTOTAL, &status); if (status!=0) decStatus(res, status, set); return res; } // decNumberCompareTotal /* ------------------------------------------------------------------ */ /* decNumberDivide -- divide one number by another */ /* */ /* This computes C = A / B */ /* */ /* res is C, the result. C may be A and/or B (e.g., X=X/X) */ /* lhs is A */ /* rhs is B */ /* set is the context */ /* */ /* C must have space for set->digits digits. */ /* ------------------------------------------------------------------ */ decNumber * decNumberDivide(decNumber *res, const decNumber *lhs, const decNumber *rhs, decContext *set) { uInt status=0; // accumulator decDivideOp(res, lhs, rhs, set, DIVIDE, &status); if (status!=0) decStatus(res, status, set); #if DECCHECK decCheckInexact(res, set); #endif return res; } // decNumberDivide /* ------------------------------------------------------------------ */ /* decNumberDivideInteger -- divide and return integer quotient */ /* */ /* This computes C = A # B, where # is the integer divide operator */ /* */ /* res is C, the result. C may be A and/or B (e.g., X=X#X) */ /* lhs is A */ /* rhs is B */ /* set is the context */ /* */ /* C must have space for set->digits digits. */ /* ------------------------------------------------------------------ */ decNumber * decNumberDivideInteger(decNumber *res, const decNumber *lhs, const decNumber *rhs, decContext *set) { uInt status=0; // accumulator decDivideOp(res, lhs, rhs, set, DIVIDEINT, &status); if (status!=0) decStatus(res, status, set); return res; } // decNumberDivideInteger /* ------------------------------------------------------------------ */ /* decNumberExp -- exponentiation */ /* */ /* This computes C = exp(A) */ /* */ /* res is C, the result. C may be A */ /* rhs is A */ /* set is the context; note that rounding mode has no effect */ /* */ /* C must have space for set->digits digits. */ /* */ /* Mathematical function restrictions apply (see above); a NaN is */ /* returned with Invalid_operation if a restriction is violated. */ /* */ /* Finite results will always be full precision and Inexact, except */ /* when A is a zero or -Infinity (giving 1 or 0 respectively). */ /* */ /* An Inexact result is rounded using DEC_ROUND_HALF_EVEN; it will */ /* almost always be correctly rounded, but may be up to 1 ulp in */ /* error in rare cases. */ /* ------------------------------------------------------------------ */ /* This is a wrapper for decExpOp which can handle the slightly wider */ /* (double) range needed by Ln (which has to be able to calculate */ /* exp(-a) where a can be the tiniest number (Ntiny). */ /* ------------------------------------------------------------------ */ decNumber * decNumberExp(decNumber *res, const decNumber *rhs, decContext *set) { uInt status=0; // accumulator #if DECSUBSET decNumber *allocrhs=NULL; // non-NULL if rounded rhs allocated #endif #if DECCHECK if (decCheckOperands(res, DECUNUSED, rhs, set)) return res; #endif // Check restrictions; these restrictions ensure that if h=8 (see // decExpOp) then the result will either overflow or underflow to 0. // Other math functions restrict the input range, too, for inverses. // If not violated then carry out the operation. if (!decCheckMath(rhs, set, &status)) do { // protect allocation #if DECSUBSET if (!set->extended) { // reduce operand and set lostDigits status, as needed if (rhs->digits>set->digits) { allocrhs=decRoundOperand(rhs, set, &status); if (allocrhs==NULL) break; rhs=allocrhs; } } #endif decExpOp(res, rhs, set, &status); } while(0); // end protected #if DECSUBSET if (allocrhs !=NULL) free(allocrhs); // drop any storage used #endif // apply significant status if (status!=0) decStatus(res, status, set); #if DECCHECK decCheckInexact(res, set); #endif return res; } // decNumberExp /* ------------------------------------------------------------------ */ /* decNumberLn -- natural logarithm */ /* */ /* This computes C = ln(A) */ /* */ /* res is C, the result. C may be A */ /* rhs is A */ /* set is the context; note that rounding mode has no effect */ /* */ /* C must have space for set->digits digits. */ /* */ /* Notable cases: */ /* A<0 -> Invalid */ /* A=0 -> -Infinity (Exact) */ /* A=+Infinity -> +Infinity (Exact) */ /* A=1 exactly -> 0 (Exact) */ /* */ /* Mathematical function restrictions apply (see above); a NaN is */ /* returned with Invalid_operation if a restriction is violated. */ /* */ /* An Inexact result is rounded using DEC_ROUND_HALF_EVEN; it will */ /* almost always be correctly rounded, but may be up to 1 ulp in */ /* error in rare cases. */ /* ------------------------------------------------------------------ */ /* This is a wrapper for decLnOp which can handle the slightly wider */ /* (+11) range needed by Ln, Log10, etc. (which may have to be able */ /* to calculate at p+e+2). */ /* ------------------------------------------------------------------ */ decNumber * decNumberLn(decNumber *res, const decNumber *rhs, decContext *set) { uInt status=0; // accumulator #if DECSUBSET decNumber *allocrhs=NULL; // non-NULL if rounded rhs allocated #endif #if DECCHECK if (decCheckOperands(res, DECUNUSED, rhs, set)) return res; #endif // Check restrictions; this is a math function; if not violated // then carry out the operation. if (!decCheckMath(rhs, set, &status)) do { // protect allocation #if DECSUBSET if (!set->extended) { // reduce operand and set lostDigits status, as needed if (rhs->digits>set->digits) { allocrhs=decRoundOperand(rhs, set, &status); if (allocrhs==NULL) break; rhs=allocrhs; } // special check in subset for rhs=0 if (ISZERO(rhs)) { // +/- zeros -> error status|=DEC_Invalid_operation; break;} } // extended=0 #endif decLnOp(res, rhs, set, &status); } while(0); // end protected #if DECSUBSET if (allocrhs !=NULL) free(allocrhs); // drop any storage used #endif // apply significant status if (status!=0) decStatus(res, status, set); #if DECCHECK decCheckInexact(res, set); #endif return res; } // decNumberLn /* ------------------------------------------------------------------ */ /* decNumberLog10 -- logarithm in base 10 */ /* */ /* This computes C = log10(A) */ /* */ /* res is C, the result. C may be A */ /* rhs is A */ /* set is the context; note that rounding mode has no effect */ /* */ /* C must have space for set->digits digits. */ /* */ /* Notable cases: */ /* A<0 -> Invalid */ /* A=0 -> -Infinity (Exact) */ /* A=+Infinity -> +Infinity (Exact) */ /* A=10**n (if n is an integer) -> n (Exact) */ /* */ /* Mathematical function restrictions apply (see above); a NaN is */ /* returned with Invalid_operation if a restriction is violated. */ /* */ /* An Inexact result is rounded using DEC_ROUND_HALF_EVEN; it will */ /* almost always be correctly rounded, but may be up to 1 ulp in */ /* error in rare cases. */ /* ------------------------------------------------------------------ */ /* This calculates ln(A)/ln(10) using appropriate precision. For */ /* ln(A) this is the max(p, rhs->digits + t) + 3, where p is the */ /* requested digits and t is the number of digits in the exponent */ /* (maximum 6). For ln(10) it is p + 3; this is often handled by the */ /* fastpath in decLnOp. The final division is done to the requested */ /* precision. */ /* ------------------------------------------------------------------ */ decNumber * decNumberLog10(decNumber *res, const decNumber *rhs, decContext *set) { uInt status=0, ignore=0; // status accumulators uInt needbytes; // for space calculations Int p; // working precision Int t; // digits in exponent of A // buffers for a and b working decimals // (adjustment calculator, same size) decNumber bufa[D2N(DECBUFFER+2)]; decNumber *allocbufa=NULL; // -> allocated bufa, iff allocated decNumber *a=bufa; // temporary a decNumber bufb[D2N(DECBUFFER+2)]; decNumber *allocbufb=NULL; // -> allocated bufa, iff allocated decNumber *b=bufb; // temporary b decNumber bufw[D2N(10)]; // working 2-10 digit number decNumber *w=bufw; // .. #if DECSUBSET decNumber *allocrhs=NULL; // non-NULL if rounded rhs allocated #endif decContext aset; // working context #if DECCHECK if (decCheckOperands(res, DECUNUSED, rhs, set)) return res; #endif // Check restrictions; this is a math function; if not violated // then carry out the operation. if (!decCheckMath(rhs, set, &status)) do { // protect malloc #if DECSUBSET if (!set->extended) { // reduce operand and set lostDigits status, as needed if (rhs->digits>set->digits) { allocrhs=decRoundOperand(rhs, set, &status); if (allocrhs==NULL) break; rhs=allocrhs; } // special check in subset for rhs=0 if (ISZERO(rhs)) { // +/- zeros -> error status|=DEC_Invalid_operation; break;} } // extended=0 #endif decContextDefault(&aset, DEC_INIT_DECIMAL64); // clean context // handle exact powers of 10; only check if +ve finite if (!(rhs->bits&(DECNEG|DECSPECIAL)) && !ISZERO(rhs)) { Int residue=0; // (no residue) uInt copystat=0; // clean status // round to a single digit... aset.digits=1; decCopyFit(w, rhs, &aset, &residue, ©stat); // copy & shorten // if exact and the digit is 1, rhs is a power of 10 if (!(copystat&DEC_Inexact) && w->lsu[0]==1) { // the exponent, conveniently, is the power of 10; making // this the result needs a little care as it might not fit, // so first convert it into the working number, and then move // to res decPutInt(w, w->exponent); residue=0; decCopyFit(res, w, set, &residue, &status); // copy & round decFinish(res, set, &residue, &status); // cleanup/set flags break; } // not a power of 10 } // not a candidate for exact // simplify the information-content calculation to use 'total // number of digits in a, including exponent' as compared to the // requested digits, as increasing this will only rarely cost an // iteration in ln(a) anyway t=6; // it can never be >6 // allocate space when needed... p=(rhs->digits+t>set->digits?rhs->digits+t:set->digits)+3; needbytes=sizeof(decNumber)+(D2U(p)-1)*sizeof(Unit); if (needbytes>sizeof(bufa)) { // need malloc space allocbufa=(decNumber *)malloc(needbytes); if (allocbufa==NULL) { // hopeless -- abandon status|=DEC_Insufficient_storage; break;} a=allocbufa; // use the allocated space } aset.digits=p; // as calculated aset.emax=DEC_MAX_MATH; // usual bounds aset.emin=-DEC_MAX_MATH; // .. aset.clamp=0; // and no concrete format decLnOp(a, rhs, &aset, &status); // a=ln(rhs) // skip the division if the result so far is infinite, NaN, or // zero, or there was an error; note NaN from sNaN needs copy if (status&DEC_NaNs && !(status&DEC_sNaN)) break; if (a->bits&DECSPECIAL || ISZERO(a)) { decNumberCopy(res, a); // [will fit] break;} // for ln(10) an extra 3 digits of precision are needed p=set->digits+3; needbytes=sizeof(decNumber)+(D2U(p)-1)*sizeof(Unit); if (needbytes>sizeof(bufb)) { // need malloc space allocbufb=(decNumber *)malloc(needbytes); if (allocbufb==NULL) { // hopeless -- abandon status|=DEC_Insufficient_storage; break;} b=allocbufb; // use the allocated space } decNumberZero(w); // set up 10... #if DECDPUN==1 w->lsu[1]=1; w->lsu[0]=0; // .. #else w->lsu[0]=10; // .. #endif w->digits=2; // .. aset.digits=p; decLnOp(b, w, &aset, &ignore); // b=ln(10) aset.digits=set->digits; // for final divide decDivideOp(res, a, b, &aset, DIVIDE, &status); // into result } while(0); // [for break] if (allocbufa!=NULL) free(allocbufa); // drop any storage used if (allocbufb!=NULL) free(allocbufb); // .. #if DECSUBSET if (allocrhs !=NULL) free(allocrhs); // .. #endif // apply significant status if (status!=0) decStatus(res, status, set); #if DECCHECK decCheckInexact(res, set); #endif return res; } // decNumberLog10 /* ------------------------------------------------------------------ */ /* decNumberMax -- compare two Numbers and return the maximum */ /* */ /* This computes C = A ? B, returning the maximum or A if equal */ /* */ /* res is C, the result. C may be A and/or B (e.g., X=X?X) */ /* lhs is A */ /* rhs is B */ /* set is the context */ /* */ /* C must have space for set->digits digits. */ /* ------------------------------------------------------------------ */ decNumber * decNumberMax(decNumber *res, const decNumber *lhs, const decNumber *rhs, decContext *set) { uInt status=0; // accumulator decCompareOp(res, lhs, rhs, set, COMPMAX, &status); if (status!=0) decStatus(res, status, set); #if DECCHECK decCheckInexact(res, set); #endif return res; } // decNumberMax /* ------------------------------------------------------------------ */ /* decNumberMin -- compare two Numbers and return the minimum */ /* */ /* This computes C = A ? B, returning the minimum or A if equal */ /* */ /* res is C, the result. C may be A and/or B (e.g., X=X?X) */ /* lhs is A */ /* rhs is B */ /* set is the context */ /* */ /* C must have space for set->digits digits. */ /* ------------------------------------------------------------------ */ decNumber * decNumberMin(decNumber *res, const decNumber *lhs, const decNumber *rhs, decContext *set) { uInt status=0; // accumulator decCompareOp(res, lhs, rhs, set, COMPMIN, &status); if (status!=0) decStatus(res, status, set); #if DECCHECK decCheckInexact(res, set); #endif return res; } // decNumberMin /* ------------------------------------------------------------------ */ /* decNumberMinus -- prefix minus operator */ /* */ /* This computes C = 0 - A */ /* */ /* res is C, the result. C may be A */ /* rhs is A */ /* set is the context */ /* */ /* C must have space for set->digits digits. */ /* ------------------------------------------------------------------ */ /* Simply use AddOp for the subtract, which will do the necessary. */ /* ------------------------------------------------------------------ */ decNumber * decNumberMinus(decNumber *res, const decNumber *rhs, decContext *set) { decNumber dzero; uInt status=0; // accumulator #if DECCHECK if (decCheckOperands(res, DECUNUSED, rhs, set)) return res; #endif decNumberZero(&dzero); // make 0 dzero.exponent=rhs->exponent; // [no coefficient expansion] decAddOp(res, &dzero, rhs, set, DECNEG, &status); if (status!=0) decStatus(res, status, set); #if DECCHECK decCheckInexact(res, set); #endif return res; } // decNumberMinus /* ------------------------------------------------------------------ */ /* decNumberPlus -- prefix plus operator */ /* */ /* This computes C = 0 + A */ /* */ /* res is C, the result. C may be A */ /* rhs is A */ /* set is the context */ /* */ /* C must have space for set->digits digits. */ /* ------------------------------------------------------------------ */ /* This simply uses AddOp; Add will take fast path after preparing A. */ /* Performance is a concern here, as this routine is often used to */ /* check operands and apply rounding and overflow/underflow testing. */ /* ------------------------------------------------------------------ */ decNumber * decNumberPlus(decNumber *res, const decNumber *rhs, decContext *set) { decNumber dzero; uInt status=0; // accumulator #if DECCHECK if (decCheckOperands(res, DECUNUSED, rhs, set)) return res; #endif decNumberZero(&dzero); // make 0 dzero.exponent=rhs->exponent; // [no coefficient expansion] decAddOp(res, &dzero, rhs, set, 0, &status); if (status!=0) decStatus(res, status, set); #if DECCHECK decCheckInexact(res, set); #endif return res; } // decNumberPlus /* ------------------------------------------------------------------ */ /* decNumberMultiply -- multiply two Numbers */ /* */ /* This computes C = A x B */ /* */ /* res is C, the result. C may be A and/or B (e.g., X=X+X) */ /* lhs is A */ /* rhs is B */ /* set is the context */ /* */ /* C must have space for set->digits digits. */ /* ------------------------------------------------------------------ */ decNumber * decNumberMultiply(decNumber *res, const decNumber *lhs, const decNumber *rhs, decContext *set) { uInt status=0; // accumulator decMultiplyOp(res, lhs, rhs, set, &status); if (status!=0) decStatus(res, status, set); #if DECCHECK decCheckInexact(res, set); #endif return res; } // decNumberMultiply /* ------------------------------------------------------------------ */ /* decNumberNormalize -- remove trailing zeros */ /* */ /* This computes C = 0 + A, and normalizes the result */ /* */ /* res is C, the result. C may be A */ /* rhs is A */ /* set is the context */ /* */ /* C must have space for set->digits digits. */ /* ------------------------------------------------------------------ */ decNumber * decNumberNormalize(decNumber *res, const decNumber *rhs, decContext *set) { #if DECSUBSET decNumber *allocrhs=NULL; // non-NULL if rounded rhs allocated #endif uInt status=0; // as usual Int residue=0; // as usual Int dropped; // work #if DECCHECK if (decCheckOperands(res, DECUNUSED, rhs, set)) return res; #endif do { // protect allocated storage #if DECSUBSET if (!set->extended) { // reduce operand and set lostDigits status, as needed if (rhs->digits>set->digits) { allocrhs=decRoundOperand(rhs, set, &status); if (allocrhs==NULL) break; rhs=allocrhs; } } #endif // [following code does not require input rounding] // specials copy through, except NaNs need care if (decNumberIsNaN(rhs)) { decNaNs(res, rhs, NULL, &status); break; } // reduce result to the requested length and copy to result decCopyFit(res, rhs, set, &residue, &status); // copy & round decFinish(res, set, &residue, &status); // cleanup/set flags decTrim(res, 1, &dropped); // normalize in place } while(0); // end protected #if DECSUBSET if (allocrhs !=NULL) free(allocrhs); // .. #endif if (status!=0) decStatus(res, status, set);// then report status return res; } // decNumberNormalize /* ------------------------------------------------------------------ */ /* decNumberPower -- raise a number to a power */ /* */ /* This computes C = A ** B */ /* */ /* res is C, the result. C may be A and/or B (e.g., X=X**X) */ /* lhs is A */ /* rhs is B */ /* set is the context */ /* */ /* C must have space for set->digits digits. */ /* */ /* Mathematical function restrictions apply (see above); a NaN is */ /* returned with Invalid_operation if a restriction is violated. */ /* */ /* However, if 1999999997<=B<=999999999 and B is an integer then the */ /* restrictions on A and the context are relaxed to the usual bounds, */ /* for compatibility with the earlier (integer power only) version */ /* of this function. */ /* */ /* When B is an integer, the result may be exact, even if rounded. */ /* */ /* The final result is rounded according to the context; it will */ /* almost always be correctly rounded, but may be up to 1 ulp in */ /* error in rare cases. */ /* ------------------------------------------------------------------ */ decNumber * decNumberPower(decNumber *res, const decNumber *lhs, const decNumber *rhs, decContext *set) { #if DECSUBSET decNumber *alloclhs=NULL; // non-NULL if rounded lhs allocated decNumber *allocrhs=NULL; // .., rhs #endif decNumber *allocdac=NULL; // -> allocated acc buffer, iff used decNumber *allocinv=NULL; // -> allocated 1/x buffer, iff used Int reqdigits=set->digits; // requested DIGITS Int n; // rhs in binary Flag rhsint=0; // 1 if rhs is an integer Flag useint=0; // 1 if can use integer calculation Flag isoddint=0; // 1 if rhs is an integer and odd Int i; // work #if DECSUBSET Int dropped; // .. #endif uInt needbytes; // buffer size needed Flag seenbit; // seen a bit while powering Int residue=0; // rounding residue uInt status=0; // accumulators uByte bits=0; // result sign if errors decContext aset; // working context decNumber dnOne; // work value 1... // local accumulator buffer [a decNumber, with digits+elength+1 digits] decNumber dacbuff[D2N(DECBUFFER+9)]; decNumber *dac=dacbuff; // -> result accumulator // same again for possible 1/lhs calculation decNumber invbuff[D2N(DECBUFFER+9)]; #if DECCHECK if (decCheckOperands(res, lhs, rhs, set)) return res; #endif do { // protect allocated storage #if DECSUBSET if (!set->extended) { // reduce operands and set status, as needed if (lhs->digits>reqdigits) { alloclhs=decRoundOperand(lhs, set, &status); if (alloclhs==NULL) break; lhs=alloclhs; } if (rhs->digits>reqdigits) { allocrhs=decRoundOperand(rhs, set, &status); if (allocrhs==NULL) break; rhs=allocrhs; } } #endif // [following code does not require input rounding] // handle NaNs and rhs Infinity (lhs infinity is harder) if (SPECIALARGS) { if (decNumberIsNaN(lhs) || decNumberIsNaN(rhs)) { // NaNs decNaNs(res, lhs, rhs, &status); break;} if (decNumberIsInfinite(rhs)) { // rhs Infinity Flag rhsneg=rhs->bits&DECNEG; // save rhs sign if (decNumberIsNegative(lhs) // lhs<0 && !decNumberIsZero(lhs)) // .. status|=DEC_Invalid_operation; else { // lhs >=0 decNumberZero(&dnOne); // set up 1 dnOne.lsu[0]=1; decNumberCompare(dac, lhs, &dnOne, set); // lhs ? 1 decNumberZero(res); // prepare for 0/1/Infinity if (decNumberIsNegative(dac)) { // lhs<1 if (rhsneg) res->bits|=DECINF; // +Infinity [else is +0] } else if (dac->lsu[0]==0) { // lhs=1 // 1**Infinity is inexact, so return fully-padded 1.0000 Int shift=set->digits-1; *res->lsu=1; // was 0, make int 1 res->digits=decShiftToMost(res->lsu, 1, shift); res->exponent=-shift; // make 1.0000... status|=DEC_Inexact|DEC_Rounded; // deemed inexact } else { // lhs>1 if (!rhsneg) res->bits|=DECINF; // +Infinity [else is +0] } } // lhs>=0 break;} // [lhs infinity drops through] } // specials // Original rhs may be an integer that fits and is in range n=decGetInt(rhs); if (n!=BADINT) { // it is an integer rhsint=1; // record the fact for 1**n isoddint=(Flag)n&1; // [works even if big] if (n!=BIGEVEN && n!=BIGODD) // can use integer path? useint=1; // looks good } if (decNumberIsNegative(lhs) // -x .. && isoddint) bits=DECNEG; // .. to an odd power // handle LHS infinity if (decNumberIsInfinite(lhs)) { // [NaNs already handled] uByte rbits=rhs->bits; // save decNumberZero(res); // prepare if (n==0) *res->lsu=1; // [-]Inf**0 => 1 else { // -Inf**nonint -> error if (!rhsint && decNumberIsNegative(lhs)) { status|=DEC_Invalid_operation; // -Inf**nonint is error break;} if (!(rbits & DECNEG)) bits|=DECINF; // was not a **-n // [otherwise will be 0 or -0] res->bits=bits; } break;} // similarly handle LHS zero if (decNumberIsZero(lhs)) { if (n==0) { // 0**0 => Error #if DECSUBSET if (!set->extended) { // [unless subset] decNumberZero(res); *res->lsu=1; // return 1 break;} #endif status|=DEC_Invalid_operation; } else { // 0**x uByte rbits=rhs->bits; // save if (rbits & DECNEG) { // was a 0**(-n) #if DECSUBSET if (!set->extended) { // [bad if subset] status|=DEC_Invalid_operation; break;} #endif bits|=DECINF; } decNumberZero(res); // prepare // [otherwise will be 0 or -0] res->bits=bits; } break;} // here both lhs and rhs are finite; rhs==0 is handled in the // integer path. Next handle the non-integer cases if (!useint) { // non-integral rhs // any -ve lhs is bad, as is either operand or context out of // bounds if (decNumberIsNegative(lhs)) { status|=DEC_Invalid_operation; break;} if (decCheckMath(lhs, set, &status) || decCheckMath(rhs, set, &status)) break; // variable status decContextDefault(&aset, DEC_INIT_DECIMAL64); // clean context aset.emax=DEC_MAX_MATH; // usual bounds aset.emin=-DEC_MAX_MATH; // .. aset.clamp=0; // and no concrete format // calculate the result using exp(ln(lhs)*rhs), which can // all be done into the accumulator, dac. The precision needed // is enough to contain the full information in the lhs (which // is the total digits, including exponent), or the requested // precision, if larger, + 4; 6 is used for the exponent // maximum length, and this is also used when it is shorter // than the requested digits as it greatly reduces the >0.5 ulp // cases at little cost (because Ln doubles digits each // iteration so a few extra digits rarely causes an extra // iteration) aset.digits=MAX(lhs->digits, set->digits)+6+4; } // non-integer rhs else { // rhs is in-range integer if (n==0) { // x**0 = 1 // (0**0 was handled above) decNumberZero(res); // result=1 *res->lsu=1; // .. break;} // rhs is a non-zero integer if (n<0) n=-n; // use abs(n) aset=*set; // clone the context aset.round=DEC_ROUND_HALF_EVEN; // internally use balanced // calculate the working DIGITS aset.digits=reqdigits+(rhs->digits+rhs->exponent)+2; #if DECSUBSET if (!set->extended) aset.digits--; // use classic precision #endif // it's an error if this is more than can be handled if (aset.digits>DECNUMMAXP) {status|=DEC_Invalid_operation; break;} } // integer path // aset.digits is the count of digits for the accumulator needed // if accumulator is too long for local storage, then allocate needbytes=sizeof(decNumber)+(D2U(aset.digits)-1)*sizeof(Unit); // [needbytes also used below if 1/lhs needed] if (needbytes>sizeof(dacbuff)) { allocdac=(decNumber *)malloc(needbytes); if (allocdac==NULL) { // hopeless -- abandon status|=DEC_Insufficient_storage; break;} dac=allocdac; // use the allocated space } // here, aset is set up and accumulator is ready for use if (!useint) { // non-integral rhs // x ** y; special-case x=1 here as it will otherwise always // reduce to integer 1; decLnOp has a fastpath which detects // the case of x=1 decLnOp(dac, lhs, &aset, &status); // dac=ln(lhs) // [no error possible, as lhs 0 already handled] if (ISZERO(dac)) { // x==1, 1.0, etc. // need to return fully-padded 1.0000 etc., but rhsint->1 *dac->lsu=1; // was 0, make int 1 if (!rhsint) { // add padding Int shift=set->digits-1; dac->digits=decShiftToMost(dac->lsu, 1, shift); dac->exponent=-shift; // make 1.0000... status|=DEC_Inexact|DEC_Rounded; // deemed inexact } } else { decMultiplyOp(dac, dac, rhs, &aset, &status); // dac=dac*rhs decExpOp(dac, dac, &aset, &status); // dac=exp(dac) } // and drop through for final rounding } // non-integer rhs else { // carry on with integer decNumberZero(dac); // acc=1 *dac->lsu=1; // .. // if a negative power the constant 1 is needed, and if not subset // invert the lhs now rather than inverting the result later if (decNumberIsNegative(rhs)) { // was a **-n [hence digits>0] decNumber *inv=invbuff; // asssume use fixed buffer decNumberCopy(&dnOne, dac); // dnOne=1; [needed now or later] #if DECSUBSET if (set->extended) { // need to calculate 1/lhs #endif // divide lhs into 1, putting result in dac [dac=1/dac] decDivideOp(dac, &dnOne, lhs, &aset, DIVIDE, &status); // now locate or allocate space for the inverted lhs if (needbytes>sizeof(invbuff)) { allocinv=(decNumber *)malloc(needbytes); if (allocinv==NULL) { // hopeless -- abandon status|=DEC_Insufficient_storage; break;} inv=allocinv; // use the allocated space } // [inv now points to big-enough buffer or allocated storage] decNumberCopy(inv, dac); // copy the 1/lhs decNumberCopy(dac, &dnOne); // restore acc=1 lhs=inv; // .. and go forward with new lhs #if DECSUBSET } #endif } // Raise-to-the-power loop... seenbit=0; // set once a 1-bit is encountered for (i=1;;i++){ // for each bit [top bit ignored] // abandon if had overflow or terminal underflow if (status & (DEC_Overflow|DEC_Underflow)) { // interesting? if (status&DEC_Overflow || ISZERO(dac)) break; } // [the following two lines revealed an optimizer bug in a C++ // compiler, with symptom: 5**3 -> 25, when n=n+n was used] n=n<<1; // move next bit to testable position if (n<0) { // top bit is set seenbit=1; // OK, significant bit seen decMultiplyOp(dac, dac, lhs, &aset, &status); // dac=dac*x } if (i==31) break; // that was the last bit if (!seenbit) continue; // no need to square 1 decMultiplyOp(dac, dac, dac, &aset, &status); // dac=dac*dac [square] } /*i*/ // 32 bits // complete internal overflow or underflow processing if (status & (DEC_Overflow|DEC_Subnormal)) { #if DECSUBSET // If subset, and power was negative, reverse the kind of -erflow // [1/x not yet done] if (!set->extended && decNumberIsNegative(rhs)) { if (status & DEC_Overflow) status^=DEC_Overflow | DEC_Underflow | DEC_Subnormal; else { // trickier -- Underflow may or may not be set status&=~(DEC_Underflow | DEC_Subnormal); // [one or both] status|=DEC_Overflow; } } #endif dac->bits=(dac->bits & ~DECNEG) | bits; // force correct sign // round subnormals [to set.digits rather than aset.digits] // or set overflow result similarly as required decFinalize(dac, set, &residue, &status); decNumberCopy(res, dac); // copy to result (is now OK length) break; } #if DECSUBSET if (!set->extended && // subset math decNumberIsNegative(rhs)) { // was a **-n [hence digits>0] // so divide result into 1 [dac=1/dac] decDivideOp(dac, &dnOne, dac, &aset, DIVIDE, &status); } #endif } // rhs integer path // reduce result to the requested length and copy to result decCopyFit(res, dac, set, &residue, &status); decFinish(res, set, &residue, &status); // final cleanup #if DECSUBSET if (!set->extended) decTrim(res, 0, &dropped); // trailing zeros #endif } while(0); // end protected if (allocdac!=NULL) free(allocdac); // drop any storage used if (allocinv!=NULL) free(allocinv); // .. #if DECSUBSET if (alloclhs!=NULL) free(alloclhs); // .. if (allocrhs!=NULL) free(allocrhs); // .. #endif if (status!=0) decStatus(res, status, set); #if DECCHECK decCheckInexact(res, set); #endif return res; } // decNumberPower /* ------------------------------------------------------------------ */ /* decNumberQuantize -- force exponent to requested value */ /* */ /* This computes C = op(A, B), where op adjusts the coefficient */ /* of C (by rounding or shifting) such that the exponent (-scale) */ /* of C has exponent of B. The numerical value of C will equal A, */ /* except for the effects of any rounding that occurred. */ /* */ /* res is C, the result. C may be A or B */ /* lhs is A, the number to adjust */ /* rhs is B, the number with exponent to match */ /* set is the context */ /* */ /* C must have space for set->digits digits. */ /* */ /* Unless there is an error or the result is infinite, the exponent */ /* after the operation is guaranteed to be equal to that of B. */ /* ------------------------------------------------------------------ */ decNumber * decNumberQuantize(decNumber *res, const decNumber *lhs, const decNumber *rhs, decContext *set) { uInt status=0; // accumulator decQuantizeOp(res, lhs, rhs, set, 1, &status); if (status!=0) decStatus(res, status, set); return res; } // decNumberQuantize /* ------------------------------------------------------------------ */ /* decNumberRescale -- force exponent to requested value */ /* */ /* This computes C = op(A, B), where op adjusts the coefficient */ /* of C (by rounding or shifting) such that the exponent (-scale) */ /* of C has the value B. The numerical value of C will equal A, */ /* except for the effects of any rounding that occurred. */ /* */ /* res is C, the result. C may be A or B */ /* lhs is A, the number to adjust */ /* rhs is B, the requested exponent */ /* set is the context */ /* */ /* C must have space for set->digits digits. */ /* */ /* Unless there is an error or the result is infinite, the exponent */ /* after the operation is guaranteed to be equal to B. */ /* ------------------------------------------------------------------ */ decNumber * decNumberRescale(decNumber *res, const decNumber *lhs, const decNumber *rhs, decContext *set) { uInt status=0; // accumulator decQuantizeOp(res, lhs, rhs, set, 0, &status); if (status!=0) decStatus(res, status, set); return res; } // decNumberRescale /* ------------------------------------------------------------------ */ /* decNumberRemainder -- divide and return remainder */ /* */ /* This computes C = A % B */ /* */ /* res is C, the result. C may be A and/or B (e.g., X=X%X) */ /* lhs is A */ /* rhs is B */ /* set is the context */ /* */ /* C must have space for set->digits digits. */ /* ------------------------------------------------------------------ */ decNumber * decNumberRemainder(decNumber *res, const decNumber *lhs, const decNumber *rhs, decContext *set) { uInt status=0; // accumulator decDivideOp(res, lhs, rhs, set, REMAINDER, &status); if (status!=0) decStatus(res, status, set); #if DECCHECK decCheckInexact(res, set); #endif return res; } // decNumberRemainder /* ------------------------------------------------------------------ */ /* decNumberRemainderNear -- divide and return remainder from nearest */ /* */ /* This computes C = A % B, where % is the IEEE remainder operator */ /* */ /* res is C, the result. C may be A and/or B (e.g., X=X%X) */ /* lhs is A */ /* rhs is B */ /* set is the context */ /* */ /* C must have space for set->digits digits. */ /* ------------------------------------------------------------------ */ decNumber * decNumberRemainderNear(decNumber *res, const decNumber *lhs, const decNumber *rhs, decContext *set) { uInt status=0; // accumulator decDivideOp(res, lhs, rhs, set, REMNEAR, &status); if (status!=0) decStatus(res, status, set); #if DECCHECK decCheckInexact(res, set); #endif return res; } // decNumberRemainderNear /* ------------------------------------------------------------------ */ /* decNumberSameQuantum -- test for equal exponents */ /* */ /* res is the result number, which will contain either 0 or 1 */ /* lhs is a number to test */ /* rhs is the second (usually a pattern) */ /* */ /* No errors are possible and no context is needed. */ /* ------------------------------------------------------------------ */ decNumber * decNumberSameQuantum(decNumber *res, const decNumber *lhs, const decNumber *rhs) { Unit ret=0; // return value #if DECCHECK if (decCheckOperands(res, lhs, rhs, DECUNUSED)) return res; #endif if (SPECIALARGS) { if (decNumberIsNaN(lhs) && decNumberIsNaN(rhs)) ret=1; else if (decNumberIsInfinite(lhs) && decNumberIsInfinite(rhs)) ret=1; // [anything else with a special gives 0] } else if (lhs->exponent==rhs->exponent) ret=1; decNumberZero(res); // OK to overwrite an operand now *res->lsu=ret; return res; } // decNumberSameQuantum /* ------------------------------------------------------------------ */ /* decNumberSquareRoot -- square root operator */ /* */ /* This computes C = squareroot(A) */ /* */ /* res is C, the result. C may be A */ /* rhs is A */ /* set is the context; note that rounding mode has no effect */ /* */ /* C must have space for set->digits digits. */ /* ------------------------------------------------------------------ */ /* This uses the following varying-precision algorithm in: */ /* */ /* Properly Rounded Variable Precision Square Root, T. E. Hull and */ /* A. Abrham, ACM Transactions on Mathematical Software, Vol 11 #3, */ /* pp229-237, ACM, September 1985. */ /* */ /* The square-root is calculated using Newton's method, after which */ /* a check is made to ensure the result is correctly rounded. */ /* */ /* % [Reformatted original Numerical Turing source code follows.] */ /* function sqrt(x : real) : real */ /* % sqrt(x) returns the properly rounded approximation to the square */ /* % root of x, in the precision of the calling environment, or it */ /* % fails if x < 0. */ /* % t e hull and a abrham, august, 1984 */ /* if x <= 0 then */ /* if x < 0 then */ /* assert false */ /* else */ /* result 0 */ /* end if */ /* end if */ /* var f := setexp(x, 0) % fraction part of x [0.1 <= x < 1] */ /* var e := getexp(x) % exponent part of x */ /* var approx : real */ /* if e mod 2 = 0 then */ /* approx := .259 + .819 * f % approx to root of f */ /* else */ /* f := f/l0 % adjustments */ /* e := e + 1 % for odd */ /* approx := .0819 + 2.59 * f % exponent */ /* end if */ /* */ /* var p:= 3 */ /* const maxp := currentprecision + 2 */ /* loop */ /* p := min(2*p - 2, maxp) % p = 4,6,10, . . . , maxp */ /* precision p */ /* approx := .5 * (approx + f/approx) */ /* exit when p = maxp */ /* end loop */ /* */ /* % approx is now within 1 ulp of the properly rounded square root */ /* % of f; to ensure proper rounding, compare squares of (approx - */ /* % l/2 ulp) and (approx + l/2 ulp) with f. */ /* p := currentprecision */ /* begin */ /* precision p + 2 */ /* const approxsubhalf := approx - setexp(.5, -p) */ /* if mulru(approxsubhalf, approxsubhalf) > f then */ /* approx := approx - setexp(.l, -p + 1) */ /* else */ /* const approxaddhalf := approx + setexp(.5, -p) */ /* if mulrd(approxaddhalf, approxaddhalf) < f then */ /* approx := approx + setexp(.l, -p + 1) */ /* end if */ /* end if */ /* end */ /* result setexp(approx, e div 2) % fix exponent */ /* end sqrt */ /* ------------------------------------------------------------------ */ decNumber * decNumberSquareRoot(decNumber *res, const decNumber *rhs, decContext *set) { decContext workset, approxset; // work contexts decNumber dzero; // used for constant zero Int maxp=set->digits+2; // largest working precision Int residue=0; // rounding residue uInt status=0, ignore=0; // status accumulators Int exp; // working exponent Int ideal; // ideal (preferred) exponent Int needbytes; // work Int dropped; // .. #if DECSUBSET decNumber *allocrhs=NULL; // non-NULL if rounded rhs allocated #endif // buffer for f [needs +1 in case DECBUFFER 0] decNumber buff[D2N(DECBUFFER+1)]; // buffer for a [needs +2 to match maxp] decNumber bufa[D2N(DECBUFFER+2)]; // buffer for temporary, b [must be same size as a] decNumber bufb[D2N(DECBUFFER+2)]; decNumber *allocbuff=NULL; // -> allocated buff, iff allocated decNumber *allocbufa=NULL; // -> allocated bufa, iff allocated decNumber *allocbufb=NULL; // -> allocated bufb, iff allocated decNumber *f=buff; // reduced fraction decNumber *a=bufa; // approximation to result decNumber *b=bufb; // intermediate result // buffer for temporary variable, up to 3 digits decNumber buft[D2N(3)]; decNumber *t=buft; // up-to-3-digit constant or work #if DECCHECK if (decCheckOperands(res, DECUNUSED, rhs, set)) return res; #endif do { // protect allocated storage #if DECSUBSET if (!set->extended) { // reduce operand and set lostDigits status, as needed if (rhs->digits>set->digits) { allocrhs=decRoundOperand(rhs, set, &status); if (allocrhs==NULL) break; // [Note: 'f' allocation below could reuse this buffer if // used, but as this is rare they are kept separate for clarity.] rhs=allocrhs; } } #endif // [following code does not require input rounding] // handle infinities and NaNs if (SPECIALARG) { if (decNumberIsInfinite(rhs)) { // an infinity if (decNumberIsNegative(rhs)) status|=DEC_Invalid_operation; else decNumberCopy(res, rhs); // +Infinity } else decNaNs(res, rhs, NULL, &status); // a NaN break; } // calculate the ideal (preferred) exponent [floor(exp/2)] // [We would like to write: ideal=rhs->exponent>>1, but this // generates a compiler warning. Generated code is the same.] ideal=(rhs->exponent&~1)/2; // target // handle zeros if (ISZERO(rhs)) { decNumberCopy(res, rhs); // could be 0 or -0 res->exponent=ideal; // use the ideal [safe] break; } // any other -x is an oops if (decNumberIsNegative(rhs)) { status|=DEC_Invalid_operation; break; } // space is needed for three working variables // f -- the same precision as the RHS, reduced to 0.01->0.99... // a -- Hull's approximation -- precision, when assigned, is // currentprecision (we allow +2 for use as temporary) // b -- intermediate temporary result // if any is too long for local storage, then allocate needbytes=sizeof(decNumber)+(D2U(rhs->digits)-1)*sizeof(Unit); if (needbytes>(Int)sizeof(buff)) { allocbuff=(decNumber *)malloc(needbytes); if (allocbuff==NULL) { // hopeless -- abandon status|=DEC_Insufficient_storage; break;} f=allocbuff; // use the allocated space } // a and b both need to be able to hold a maxp-length number needbytes=sizeof(decNumber)+(D2U(maxp)-1)*sizeof(Unit); if (needbytes>(Int)sizeof(bufa)) { // [same applies to b] allocbufa=(decNumber *)malloc(needbytes); allocbufb=(decNumber *)malloc(needbytes); if (allocbufa==NULL || allocbufb==NULL) { // hopeless status|=DEC_Insufficient_storage; break;} a=allocbufa; // use the allocated space b=allocbufb; // .. } // copy rhs -> f, save exponent, and reduce so 0.1 <= f < 1 decNumberCopy(f, rhs); exp=f->exponent+f->digits; // adjusted to Hull rules f->exponent=-(f->digits); // to range // set up working contexts (the second is used for Numerical // Turing assignment) decContextDefault(&workset, DEC_INIT_DECIMAL64); decContextDefault(&approxset, DEC_INIT_DECIMAL64); approxset.digits=set->digits; // approx's length // [Until further notice, no error is possible and status bits // (Rounded, etc.) should be ignored, not accumulated.] // Calculate initial approximation, and allow for odd exponent workset.digits=set->digits; // p for initial calculation t->bits=0; t->digits=3; a->bits=0; a->digits=3; if ((exp & 1)==0) { // even exponent // Set t=0.259, a=0.819 t->exponent=-3; a->exponent=-3; #if DECDPUN>=3 t->lsu[0]=259; a->lsu[0]=819; #elif DECDPUN==2 t->lsu[0]=59; t->lsu[1]=2; a->lsu[0]=19; a->lsu[1]=8; #else t->lsu[0]=9; t->lsu[1]=5; t->lsu[2]=2; a->lsu[0]=9; a->lsu[1]=1; a->lsu[2]=8; #endif } else { // odd exponent // Set t=0.0819, a=2.59 f->exponent--; // f=f/10 exp++; // e=e+1 t->exponent=-4; a->exponent=-2; #if DECDPUN>=3 t->lsu[0]=819; a->lsu[0]=259; #elif DECDPUN==2 t->lsu[0]=19; t->lsu[1]=8; a->lsu[0]=59; a->lsu[1]=2; #else t->lsu[0]=9; t->lsu[1]=1; t->lsu[2]=8; a->lsu[0]=9; a->lsu[1]=5; a->lsu[2]=2; #endif } decMultiplyOp(a, a, f, &workset, &ignore); // a=a*f decAddOp(a, a, t, &workset, 0, &ignore); // ..+t // [a is now the initial approximation for sqrt(f), calculated with // currentprecision, which is also a's precision.] // the main calculation loop decNumberZero(&dzero); // make 0 decNumberZero(t); // set t = 0.5 t->lsu[0]=5; // .. t->exponent=-1; // .. workset.digits=3; // initial p for (;;) { // set p to min(2*p - 2, maxp) [hence 3; or: 4, 6, 10, ... , maxp] workset.digits=workset.digits*2-2; if (workset.digits>maxp) workset.digits=maxp; // a = 0.5 * (a + f/a) // [calculated at p then rounded to currentprecision] decDivideOp(b, f, a, &workset, DIVIDE, &ignore); // b=f/a decAddOp(b, b, a, &workset, 0, &ignore); // b=b+a decMultiplyOp(a, b, t, &workset, &ignore); // a=b*0.5 // assign to approx [round to length] decAddOp(a, &dzero, a, &approxset, 0, &ignore); if (workset.digits==maxp) break; // just did final } // loop // a is now at currentprecision and within 1 ulp of the properly // rounded square root of f; to ensure proper rounding, compare // squares of (a - l/2 ulp) and (a + l/2 ulp) with f. // Here workset.digits=maxp and t=0.5 workset.digits--; // maxp-1 is OK now t->exponent=-set->digits-1; // make 0.5 ulp decNumberCopy(b, a); decAddOp(b, b, t, &workset, DECNEG, &ignore); // b = a - 0.5 ulp workset.round=DEC_ROUND_UP; decMultiplyOp(b, b, b, &workset, &ignore); // b = mulru(b, b) decCompareOp(b, f, b, &workset, COMPARE, &ignore); // b ? f, reversed if (decNumberIsNegative(b)) { // f < b [i.e., b > f] // this is the more common adjustment, though both are rare t->exponent++; // make 1.0 ulp t->lsu[0]=1; // .. decAddOp(a, a, t, &workset, DECNEG, &ignore); // a = a - 1 ulp // assign to approx [round to length] decAddOp(a, &dzero, a, &approxset, 0, &ignore); } else { decNumberCopy(b, a); decAddOp(b, b, t, &workset, 0, &ignore); // b = a + 0.5 ulp workset.round=DEC_ROUND_DOWN; decMultiplyOp(b, b, b, &workset, &ignore); // b = mulrd(b, b) decCompareOp(b, b, f, &workset, COMPARE, &ignore); // b ? f if (decNumberIsNegative(b)) { // b < f t->exponent++; // make 1.0 ulp t->lsu[0]=1; // .. decAddOp(a, a, t, &workset, 0, &ignore); // a = a + 1 ulp // assign to approx [round to length] decAddOp(a, &dzero, a, &approxset, 0, &ignore); } } // [no errors are possible in the above, and rounding/inexact during // estimation are irrelevant, so status was not accumulated] // Here, 0.1 <= a < 1 [Hull] a->exponent+=exp/2; // set correct exponent // Process Subnormals decFinalize(a, set, &residue, &status); // count droppable zeros [after any subnormal rounding] by // trimming a copy decNumberCopy(b, a); decTrim(b, 1, &dropped); // [drops trailing zeros] // Finally set Inexact and Rounded. The answer can only be exact if // it is short enough so that squaring it could fit in set->digits, // so this is the only (relatively rare) time a careful check is // needed if (b->digits*2-1 > set->digits) { // cannot fit status|=DEC_Inexact|DEC_Rounded; } else { // could be exact/unrounded uInt mstatus=0; // local status decMultiplyOp(b, b, b, &workset, &mstatus); // try the multiply if (mstatus!=0) { // result won't fit status|=DEC_Inexact|DEC_Rounded; } else { // plausible decCompareOp(t, b, rhs, &workset, COMPARE, &mstatus); // b ? rhs if (!ISZERO(t)) { status|=DEC_Inexact|DEC_Rounded; } else { // is Exact Int todrop; // work // here, dropped is the count of trailing zeros in 'a' // use closest exponent to ideal... todrop=ideal-a->exponent; // most that can be dropped if (todrop<0) { // ideally would add 0s status|=DEC_Rounded; } else { // unrounded if (dropped0) { // OK, some to drop decShiftToLeast(a->lsu, D2U(a->digits), todrop); a->exponent+=todrop; // maintain numerical value a->digits-=todrop; // new length } } } } } // make sure there is a full complement of digits for normal // inexact results if ((status & (DEC_Inexact|DEC_Subnormal))==DEC_Inexact) { Int shift=set->digits-a->digits; if (shift>0) { a->digits=decShiftToMost(a->lsu, a->digits, shift); a->exponent-=shift; // adjust the exponent. } } decNumberCopy(res, a); // a is now the result } while(0); // end protected if (allocbuff!=NULL) free(allocbuff); // drop any storage used if (allocbufa!=NULL) free(allocbufa); // .. if (allocbufb!=NULL) free(allocbufb); // .. #if DECSUBSET if (allocrhs !=NULL) free(allocrhs); // .. #endif if (status!=0) decStatus(res, status, set);// then report status #if DECCHECK decCheckInexact(res, set); #endif return res; } // decNumberSquareRoot /* ------------------------------------------------------------------ */ /* decNumberSubtract -- subtract two Numbers */ /* */ /* This computes C = A - B */ /* */ /* res is C, the result. C may be A and/or B (e.g., X=X-X) */ /* lhs is A */ /* rhs is B */ /* set is the context */ /* */ /* C must have space for set->digits digits. */ /* ------------------------------------------------------------------ */ decNumber * decNumberSubtract(decNumber *res, const decNumber *lhs, const decNumber *rhs, decContext *set) { uInt status=0; // accumulator decAddOp(res, lhs, rhs, set, DECNEG, &status); if (status!=0) decStatus(res, status, set); #if DECCHECK decCheckInexact(res, set); #endif return res; } // decNumberSubtract /* ------------------------------------------------------------------ */ /* decNumberToIntegralValue -- round-to-integral-value */ /* */ /* res is the result */ /* rhs is input number */ /* set is the context */ /* */ /* res must have space for any value of rhs. */ /* */ /* This implements the IEEE special operator and therefore treats */ /* special values as valid, and also never sets Inexact. For finite */ /* numbers it returns rescale(rhs, 0) if rhs->exponent is <0. */ /* Otherwise the result is rhs (so no error is possible). */ /* */ /* The context is used for rounding mode and status after sNaN, but */ /* the digits setting is ignored. */ /* ------------------------------------------------------------------ */ decNumber * decNumberToIntegralValue(decNumber *res, const decNumber *rhs, decContext *set) { decNumber dn; decContext workset; // working context #if DECCHECK if (decCheckOperands(res, DECUNUSED, rhs, set)) return res; #endif // handle infinities and NaNs if (SPECIALARG) { uInt status=0; if (decNumberIsInfinite(rhs)) decNumberCopy(res, rhs); // an Infinity else decNaNs(res, rhs, NULL, &status); // a NaN if (status!=0) decStatus(res, status, set); return res; } // have a finite number; no error possible (res must be big enough) if (rhs->exponent>=0) return decNumberCopy(res, rhs); // that was easy, but if negative exponent there is work to do... workset=*set; // clone rounding, etc. workset.digits=rhs->digits; // no length rounding workset.traps=0; // no traps decNumberZero(&dn); // make a number with exponent 0 return decNumberQuantize(res, rhs, &dn, &workset); } // decNumberToIntegralValue /* ================================================================== */ /* Utility routines */ /* ================================================================== */ /* ------------------------------------------------------------------ */ /* decNumberCopy -- copy a number */ /* */ /* dest is the target decNumber */ /* src is the source decNumber */ /* returns dest */ /* */ /* (dest==src is allowed and is a no-op) */ /* All fields are updated as required. This is a utility operation, */ /* so special values are unchanged and no error is possible. */ /* ------------------------------------------------------------------ */ decNumber * decNumberCopy(decNumber *dest, const decNumber *src) { #if DECCHECK if (src==NULL) return decNumberZero(dest); #endif if (dest==src) return dest; // no copy required // Use explicit assignments here as structure assignment could copy // more than just the lsu (for small DECDPUN). This would not affect // the value of the results, but could disturb test harness spill // checking. dest->bits=src->bits; dest->exponent=src->exponent; dest->digits=src->digits; dest->lsu[0]=src->lsu[0]; if (src->digits>DECDPUN) { // more Units to come const Unit *smsup, *s; // work Unit *d; // .. // memcpy for the remaining Units would be safe as they cannot // overlap. However, this explicit loop is faster in short cases. d=dest->lsu+1; // -> first destination smsup=src->lsu+D2U(src->digits); // -> source msu+1 for (s=src->lsu+1; sbits=0; dn->exponent=0; dn->digits=1; dn->lsu[0]=0; return dn; } // decNumberZero /* ================================================================== */ /* Local routines */ /* ================================================================== */ /* ------------------------------------------------------------------ */ /* decToString -- lay out a number into a string */ /* */ /* dn is the number to lay out */ /* string is where to lay out the number */ /* eng is 1 if Engineering, 0 if Scientific */ /* */ /* string must be at least dn->digits+14 characters long */ /* No error is possible. */ /* */ /* Note that this routine can generate a -0 or 0.000. These are */ /* never generated in subset to-number or arithmetic, but can occur */ /* in non-subset arithmetic (e.g., -1*0 or 1.234-1.234). */ /* ------------------------------------------------------------------ */ // If DECCHECK is enabled the string "?" is returned if a number is // invalid. static void decToString(const decNumber *dn, char *string, Flag eng) { Int exp=dn->exponent; // local copy Int e; // E-part value Int pre; // digits before the '.' Int cut; // for counting digits in a Unit char *c=string; // work [output pointer] const Unit *up=dn->lsu+D2U(dn->digits)-1; // -> msu [input pointer] uInt u, pow; // work #if DECCHECK if (decCheckOperands(DECUNUSED, dn, DECUNUSED, DECUNUSED)) { strcpy(string, "?"); return;} #endif if (decNumberIsNegative(dn)) { // Negatives get a minus *c='-'; c++; } if (dn->bits&DECSPECIAL) { // Is a special value if (decNumberIsInfinite(dn)) { strcpy(c, "Infinity"); return;} // a NaN if (dn->bits&DECSNAN) { // signalling NaN *c='s'; c++; } strcpy(c, "NaN"); c+=3; // step past // if not a clean non-zero coefficient, that's all there is in a // NaN string if (exp!=0 || (*dn->lsu==0 && dn->digits==1)) return; // [drop through to add integer] } // calculate how many digits in msu, and hence first cut cut=MSUDIGITS(dn->digits); // [faster than remainder] cut--; // power of ten for digit if (exp==0) { // simple integer [common fastpath] for (;up>=dn->lsu; up--) { // each Unit from msu u=*up; // contains DECDPUN digits to lay out for (; cut>=0; c++, cut--) TODIGIT(u, cut, c, pow); cut=DECDPUN-1; // next Unit has all digits } *c='\0'; // terminate the string return;} /* non-0 exponent -- assume plain form */ pre=dn->digits+exp; // digits before '.' e=0; // no E if ((exp>0) || (pre<-5)) { // need exponential form e=exp+dn->digits-1; // calculate E value pre=1; // assume one digit before '.' if (eng && (e!=0)) { // engineering: may need to adjust Int adj; // adjustment // The C remainder operator is undefined for negative numbers, so // a positive remainder calculation must be used here if (e<0) { adj=(-e)%3; if (adj!=0) adj=3-adj; } else { // e>0 adj=e%3; } e=e-adj; // if dealing with zero still produce an exponent which is a // multiple of three, as expected, but there will only be the // one zero before the E, still. Otherwise note the padding. if (!ISZERO(dn)) pre+=adj; else { // is zero if (adj!=0) { // 0.00Esnn needed e=e+3; pre=-(2-adj); } } // zero } // eng } // need exponent /* lay out the digits of the coefficient, adding 0s and . as needed */ u=*up; if (pre>0) { // xxx.xxx or xx00 (engineering) form Int n=pre; for (; pre>0; pre--, c++, cut--) { if (cut<0) { // need new Unit if (up==dn->lsu) break; // out of input digits (pre>digits) up--; cut=DECDPUN-1; u=*up; } TODIGIT(u, cut, c, pow); } if (ndigits) { // more to come, after '.' *c='.'; c++; for (;; c++, cut--) { if (cut<0) { // need new Unit if (up==dn->lsu) break; // out of input digits up--; cut=DECDPUN-1; u=*up; } TODIGIT(u, cut, c, pow); } } else for (; pre>0; pre--, c++) *c='0'; // 0 padding (for engineering) needed } else { // 0.xxx or 0.000xxx form *c='0'; c++; *c='.'; c++; for (; pre<0; pre++, c++) *c='0'; // add any 0's after '.' for (; ; c++, cut--) { if (cut<0) { // need new Unit if (up==dn->lsu) break; // out of input digits up--; cut=DECDPUN-1; u=*up; } TODIGIT(u, cut, c, pow); } } /* Finally add the E-part, if needed. It will never be 0, has a base maximum and minimum of +999999999 through -999999999, but could range down to -1999999998 for anormal numbers */ if (e!=0) { Flag had=0; // 1=had non-zero *c='E'; c++; *c='+'; c++; // assume positive u=e; // .. if (e<0) { *(c-1)='-'; // oops, need - u=-e; // uInt, please } // layout the exponent [_itoa or equivalent is not ANSI C] for (cut=9; cut>=0; cut--) { TODIGIT(u, cut, c, pow); if (*c=='0' && !had) continue; // skip leading zeros had=1; // had non-0 c++; // step for next } // cut } *c='\0'; // terminate the string (all paths) return; } // decToString /* ------------------------------------------------------------------ */ /* decAddOp -- add/subtract operation */ /* */ /* This computes C = A + B */ /* */ /* res is C, the result. C may be A and/or B (e.g., X=X+X) */ /* lhs is A */ /* rhs is B */ /* set is the context */ /* negate is DECNEG if rhs should be negated, or 0 otherwise */ /* status accumulates status for the caller */ /* */ /* C must have space for set->digits digits. */ /* ------------------------------------------------------------------ */ /* If possible, the coefficient is calculated directly into C. */ /* However, if: */ /* -- a digits+1 calculation is needed because the numbers are */ /* unaligned and span more than set->digits digits */ /* -- a carry to digits+1 digits looks possible */ /* -- C is the same as A or B, and the result would destructively */ /* overlap the A or B coefficient */ /* then the result must be calculated into a temporary buffer. In */ /* this case a local (stack) buffer is used if possible, and only if */ /* too long for that does malloc become the last resort. */ /* */ /* Misalignment is handled as follows: */ /* Apad: (AExp>BExp) Swap operands and proceed as for BExp>AExp. */ /* BPad: Apply the padding by a combination of shifting (whole */ /* units) and multiplication (part units). */ /* */ /* Addition, especially x=x+1, is speed-critical. */ /* ------------------------------------------------------------------ */ static decNumber * decAddOp(decNumber *res, const decNumber *lhs, const decNumber *rhs, decContext *set, uByte negate, uInt *status) { #if DECSUBSET decNumber *alloclhs=NULL; // non-NULL if rounded lhs allocated decNumber *allocrhs=NULL; // .., rhs #endif Int rhsshift; // working shift (in Units) Int maxdigits; // longest logical length Int mult; // multiplier Int residue; // rounding accumulator uByte bits; // result bits Flag diffsign; // non-0 if arguments have different sign Unit *acc; // accumulator for result Unit accbuff[SD2U(DECBUFFER+20)]; // local buffer [+20 reduces many // allocations when called from // other operations] Unit *allocacc=NULL; // -> allocated acc buffer, iff allocated Int reqdigits=set->digits; // local copy; requested DIGITS Int padding; // work #if DECCHECK if (decCheckOperands(res, lhs, rhs, set)) return res; #endif do { // protect allocated storage #if DECSUBSET if (!set->extended) { // reduce operands and set lostDigits status, as needed if (lhs->digits>reqdigits) { alloclhs=decRoundOperand(lhs, set, status); if (alloclhs==NULL) break; lhs=alloclhs; } if (rhs->digits>reqdigits) { allocrhs=decRoundOperand(rhs, set, status); if (allocrhs==NULL) break; rhs=allocrhs; } } #endif // [following code does not require input rounding] // note whether signs differ [used all paths] diffsign=(Flag)((lhs->bits^rhs->bits^negate)&DECNEG); // handle infinities and NaNs if (SPECIALARGS) { // a special bit set if (SPECIALARGS & (DECSNAN | DECNAN)) // a NaN decNaNs(res, lhs, rhs, status); else { // one or two infinities if (decNumberIsInfinite(lhs)) { // LHS is infinity // two infinities with different signs is invalid if (decNumberIsInfinite(rhs) && diffsign) { *status|=DEC_Invalid_operation; break; } bits=lhs->bits & DECNEG; // get sign from LHS } else bits=(rhs->bits^negate) & DECNEG;// RHS must be Infinity bits|=DECINF; decNumberZero(res); res->bits=bits; // set +/- infinity } // an infinity break; } // Quick exit for add 0s; return the non-0, modified as need be if (ISZERO(lhs)) { Int adjust; // work Int lexp=lhs->exponent; // save in case LHS==RES bits=lhs->bits; // .. residue=0; // clear accumulator decCopyFit(res, rhs, set, &residue, status); // copy (as needed) res->bits^=negate; // flip if rhs was negated #if DECSUBSET if (set->extended) { // exponents on zeros count #endif // exponent will be the lower of the two adjust=lexp-res->exponent; // adjustment needed [if -ve] if (ISZERO(res)) { // both 0: special IEEE 854 rules if (adjust<0) res->exponent=lexp; // set exponent // 0-0 gives +0 unless rounding to -infinity, and -0-0 gives -0 if (diffsign) { if (set->round!=DEC_ROUND_FLOOR) res->bits=0; else res->bits=DECNEG; // preserve 0 sign } } else { // non-0 res if (adjust<0) { // 0-padding needed if ((res->digits-adjust)>set->digits) { adjust=res->digits-set->digits; // to fit exactly *status|=DEC_Rounded; // [but exact] } res->digits=decShiftToMost(res->lsu, res->digits, -adjust); res->exponent+=adjust; // set the exponent. } } // non-0 res #if DECSUBSET } // extended #endif decFinish(res, set, &residue, status); // clean and finalize break;} if (ISZERO(rhs)) { // [lhs is non-zero] Int adjust; // work Int rexp=rhs->exponent; // save in case RHS==RES bits=rhs->bits; // be clean residue=0; // clear accumulator decCopyFit(res, lhs, set, &residue, status); // copy (as needed) #if DECSUBSET if (set->extended) { // exponents on zeros count #endif // exponent will be the lower of the two // [0-0 case handled above] adjust=rexp-res->exponent; // adjustment needed [if -ve] if (adjust<0) { // 0-padding needed if ((res->digits-adjust)>set->digits) { adjust=res->digits-set->digits; // to fit exactly *status|=DEC_Rounded; // [but exact] } res->digits=decShiftToMost(res->lsu, res->digits, -adjust); res->exponent+=adjust; // set the exponent. } #if DECSUBSET } // extended #endif decFinish(res, set, &residue, status); // clean and finalize break;} // [NB: both fastpath and mainpath code below assume these cases // (notably 0-0) have already been handled] // calculate the padding needed to align the operands padding=rhs->exponent-lhs->exponent; // Fastpath cases where the numbers are aligned and normal, the RHS // is all in one unit, no operand rounding is needed, and no carry, // lengthening, or borrow is needed if (padding==0 && rhs->digits<=DECDPUN && rhs->exponent>=set->emin // [some normals drop through] && rhs->digits<=reqdigits && lhs->digits<=reqdigits) { Int partial=*lhs->lsu; if (!diffsign) { // adding partial+=*rhs->lsu; if ((partial<=DECDPUNMAX) // result fits in unit && (lhs->digits>=DECDPUN || // .. and no digits-count change partial<(Int)powers[lhs->digits])) { // .. if (res!=lhs) decNumberCopy(res, lhs); // not in place *res->lsu=(Unit)partial; // [copy could have overwritten RHS] break; } // else drop out for careful add } else { // signs differ partial-=*rhs->lsu; if (partial>0) { // no borrow needed, and non-0 result if (res!=lhs) decNumberCopy(res, lhs); // not in place *res->lsu=(Unit)partial; // this could have reduced digits [but result>0] res->digits=decGetDigits(res->lsu, D2U(res->digits)); break; } // else drop out for careful subtract } } // Now align (pad) the lhs or rhs so they can be added or // subtracted, as necessary. If one number is much larger than // the other (that is, if in plain form there is a least one // digit between the lowest digit of one and the highest of the // other) padding with up to DIGITS-1 trailing zeros may be // needed; then apply rounding (as exotic rounding modes may be // affected by the residue). rhsshift=0; // rhs shift to left (padding) in Units bits=lhs->bits; // assume sign is that of LHS mult=1; // likely multiplier // if padding==0 the operands are aligned; no padding needed if (padding!=0) { // some padding needed; always pad the RHS, as any required // padding can then be effected by a simple combination of // shifts and a multiply Flag swapped=0; if (padding<0) { // LHS needs the padding const decNumber *t; padding=-padding; // will be +ve bits=(uByte)(rhs->bits^negate); // assumed sign is now that of RHS t=lhs; lhs=rhs; rhs=t; swapped=1; } // If, after pad, rhs would be longer than lhs by digits+1 or // more then lhs cannot affect the answer, except as a residue, // so only need to pad up to a length of DIGITS+1. if (rhs->digits+padding > lhs->digits+reqdigits+1) { // The RHS is sufficient // for residue use the relative sign indication... Int shift=reqdigits-rhs->digits; // left shift needed residue=1; // residue for rounding if (diffsign) residue=-residue; // signs differ // copy, shortening if necessary decCopyFit(res, rhs, set, &residue, status); // if it was already shorter, then need to pad with zeros if (shift>0) { res->digits=decShiftToMost(res->lsu, res->digits, shift); res->exponent-=shift; // adjust the exponent. } // flip the result sign if unswapped and rhs was negated if (!swapped) res->bits^=negate; decFinish(res, set, &residue, status); // done break;} // LHS digits may affect result rhsshift=D2U(padding+1)-1; // this much by Unit shift .. mult=powers[padding-(rhsshift*DECDPUN)]; // .. this by multiplication } // padding needed if (diffsign) mult=-mult; // signs differ // determine the longer operand maxdigits=rhs->digits+padding; // virtual length of RHS if (lhs->digits>maxdigits) maxdigits=lhs->digits; // Decide on the result buffer to use; if possible place directly // into result. acc=res->lsu; // assume add direct to result // If destructive overlap, or the number is too long, or a carry or // borrow to DIGITS+1 might be possible, a buffer must be used. // [Might be worth more sophisticated tests when maxdigits==reqdigits] if ((maxdigits>=reqdigits) // is, or could be, too large || (res==rhs && rhsshift>0)) { // destructive overlap // buffer needed, choose it; units for maxdigits digits will be // needed, +1 Unit for carry or borrow Int need=D2U(maxdigits)+1; acc=accbuff; // assume use local buffer if (need*sizeof(Unit)>sizeof(accbuff)) { allocacc=(Unit *)malloc(need*sizeof(Unit)); if (allocacc==NULL) { // hopeless -- abandon *status|=DEC_Insufficient_storage; break;} acc=allocacc; } } res->bits=(uByte)(bits&DECNEG); // it's now safe to overwrite.. res->exponent=lhs->exponent; // .. operands (even if aliased) #if DECTRACE decDumpAr('A', lhs->lsu, D2U(lhs->digits)); decDumpAr('B', rhs->lsu, D2U(rhs->digits)); printf(" :h: %d %d\n", rhsshift, mult); #endif // add [A+B*m] or subtract [A+B*(-m)] res->digits=decUnitAddSub(lhs->lsu, D2U(lhs->digits), rhs->lsu, D2U(rhs->digits), rhsshift, acc, mult) *DECDPUN; // [units -> digits] if (res->digits<0) { // borrowed... res->digits=-res->digits; res->bits^=DECNEG; // flip the sign } #if DECTRACE decDumpAr('+', acc, D2U(res->digits)); #endif // If a buffer was used the result must be copied back, possibly // shortening. (If no buffer was used then the result must have // fit, so can't need rounding and residue must be 0.) residue=0; // clear accumulator if (acc!=res->lsu) { #if DECSUBSET if (set->extended) { // round from first significant digit #endif // remove leading zeros that were added due to rounding up to // integral Units -- before the test for rounding. if (res->digits>reqdigits) res->digits=decGetDigits(acc, D2U(res->digits)); decSetCoeff(res, set, acc, res->digits, &residue, status); #if DECSUBSET } else { // subset arithmetic rounds from original significant digit // May have an underestimate. This only occurs when both // numbers fit in DECDPUN digits and are padding with a // negative multiple (-10, -100...) and the top digit(s) become // 0. (This only matters when using X3.274 rules where the // leading zero could be included in the rounding.) if (res->digitsdigits))=0; // ensure leading 0 is there res->digits=maxdigits; } else { // remove leading zeros that added due to rounding up to // integral Units (but only those in excess of the original // maxdigits length, unless extended) before test for rounding. if (res->digits>reqdigits) { res->digits=decGetDigits(acc, D2U(res->digits)); if (res->digitsdigits=maxdigits; } } decSetCoeff(res, set, acc, res->digits, &residue, status); // Now apply rounding if needed before removing leading zeros. // This is safe because subnormals are not a possibility if (residue!=0) { decApplyRound(res, set, residue, status); residue=0; // did what needed to be done } } // subset #endif } // used buffer // strip leading zeros [these were left on in case of subset subtract] res->digits=decGetDigits(res->lsu, D2U(res->digits)); // apply checks and rounding decFinish(res, set, &residue, status); // "When the sum of two operands with opposite signs is exactly // zero, the sign of that sum shall be '+' in all rounding modes // except round toward -Infinity, in which mode that sign shall be // '-'." [Subset zeros also never have '-', set by decFinish.] if (ISZERO(res) && diffsign #if DECSUBSET && set->extended #endif && (*status&DEC_Inexact)==0) { if (set->round==DEC_ROUND_FLOOR) res->bits|=DECNEG; // sign - else res->bits&=~DECNEG; // sign + } } while(0); // end protected if (allocacc!=NULL) free(allocacc); // drop any storage used #if DECSUBSET if (allocrhs!=NULL) free(allocrhs); // .. if (alloclhs!=NULL) free(alloclhs); // .. #endif return res; } // decAddOp /* ------------------------------------------------------------------ */ /* decDivideOp -- division operation */ /* */ /* This routine performs the calculations for all four division */ /* operators (divide, divideInteger, remainder, remainderNear). */ /* */ /* C=A op B */ /* */ /* res is C, the result. C may be A and/or B (e.g., X=X/X) */ /* lhs is A */ /* rhs is B */ /* set is the context */ /* op is DIVIDE, DIVIDEINT, REMAINDER, or REMNEAR respectively. */ /* status is the usual accumulator */ /* */ /* C must have space for set->digits digits. */ /* */ /* ------------------------------------------------------------------ */ /* The underlying algorithm of this routine is the same as in the */ /* 1981 S/370 implementation, that is, non-restoring long division */ /* with bi-unit (rather than bi-digit) estimation for each unit */ /* multiplier. In this pseudocode overview, complications for the */ /* Remainder operators and division residues for exact rounding are */ /* omitted for clarity. */ /* */ /* Prepare operands and handle special values */ /* Test for x/0 and then 0/x */ /* Exp =Exp1 - Exp2 */ /* Exp =Exp +len(var1) -len(var2) */ /* Sign=Sign1 * Sign2 */ /* Pad accumulator (Var1) to double-length with 0's (pad1) */ /* Pad Var2 to same length as Var1 */ /* msu2pair/plus=1st 2 or 1 units of var2, +1 to allow for round */ /* have=0 */ /* Do until (have=digits+1 OR residue=0) */ /* if exp<0 then if integer divide/residue then leave */ /* this_unit=0 */ /* Do forever */ /* compare numbers */ /* if <0 then leave inner_loop */ /* if =0 then (* quick exit without subtract *) do */ /* this_unit=this_unit+1; output this_unit */ /* leave outer_loop; end */ /* Compare lengths of numbers (mantissae): */ /* If same then tops2=msu2pair -- {units 1&2 of var2} */ /* else tops2=msu2plus -- {0, unit 1 of var2} */ /* tops1=first_unit_of_Var1*10**DECDPUN +second_unit_of_var1 */ /* mult=tops1/tops2 -- Good and safe guess at divisor */ /* if mult=0 then mult=1 */ /* this_unit=this_unit+mult */ /* subtract */ /* end inner_loop */ /* if have\=0 | this_unit\=0 then do */ /* output this_unit */ /* have=have+1; end */ /* var2=var2/10 */ /* exp=exp-1 */ /* end outer_loop */ /* exp=exp+1 -- set the proper exponent */ /* if have=0 then generate answer=0 */ /* Return (Result is defined by Var1) */ /* */ /* ------------------------------------------------------------------ */ /* Two working buffers are needed during the division; one (digits+ */ /* 1) to accumulate the result, and the other (up to 2*digits+1) for */ /* long subtractions. These are acc and var1 respectively. */ /* var1 is a copy of the lhs coefficient, var2 is the rhs coefficient.*/ /* ------------------------------------------------------------------ */ static decNumber * decDivideOp(decNumber *res, const decNumber *lhs, const decNumber *rhs, decContext *set, Flag op, uInt *status) { #if DECSUBSET decNumber *alloclhs=NULL; // non-NULL if rounded lhs allocated decNumber *allocrhs=NULL; // .., rhs #endif Unit accbuff[SD2U(DECBUFFER+DECDPUN)]; // local buffer Unit *acc=accbuff; // -> accumulator array for result Unit *allocacc=NULL; // -> allocated buffer, iff allocated Unit *accnext; // -> where next digit will go Int acclength; // length of acc needed [Units] Int accunits; // count of units accumulated Int accdigits; // count of digits accumulated Unit varbuff[SD2U(DECBUFFER*2+DECDPUN)*sizeof(Unit)]; // buffer for var1 Unit *var1=varbuff; // -> var1 array for long subtraction Unit *varalloc=NULL; // -> allocated buffer, iff used Unit *msu1; // -> msu of var1 const Unit *var2; // -> var2 array const Unit *msu2; // -> msu of var2 Int msu2plus; // msu2 plus one [does not vary] eInt msu2pair; // msu2 pair plus one [does not vary] Int var1units, var2units; // actual lengths Int var2ulen; // logical length (units) Int var1initpad=0; // var1 initial padding (digits) Int maxdigits; // longest LHS or required acc length Int mult; // multiplier for subtraction Unit thisunit; // current unit being accumulated Int residue; // for rounding Int reqdigits=set->digits; // requested DIGITS Int exponent; // working exponent Int maxexponent=0; // DIVIDE maximum exponent if unrounded uByte bits; // working sign Unit *target; // work const Unit *source; // .. uInt const *pow; // .. Int shift, cut; // .. #if DECSUBSET Int dropped; // work #endif #if DECCHECK if (decCheckOperands(res, lhs, rhs, set)) return res; #endif do { // protect allocated storage #if DECSUBSET if (!set->extended) { // reduce operands and set lostDigits status, as needed if (lhs->digits>reqdigits) { alloclhs=decRoundOperand(lhs, set, status); if (alloclhs==NULL) break; lhs=alloclhs; } if (rhs->digits>reqdigits) { allocrhs=decRoundOperand(rhs, set, status); if (allocrhs==NULL) break; rhs=allocrhs; } } #endif // [following code does not require input rounding] bits=(lhs->bits^rhs->bits)&DECNEG; // assumed sign for divisions // handle infinities and NaNs if (SPECIALARGS) { // a special bit set if (SPECIALARGS & (DECSNAN | DECNAN)) { // one or two NaNs decNaNs(res, lhs, rhs, status); break; } // one or two infinities if (decNumberIsInfinite(lhs)) { // LHS (dividend) is infinite if (decNumberIsInfinite(rhs) || // two infinities are invalid .. op & (REMAINDER | REMNEAR)) { // as is remainder of infinity *status|=DEC_Invalid_operation; break; } // [Note that infinity/0 raises no exceptions] decNumberZero(res); res->bits=bits|DECINF; // set +/- infinity break; } else { // RHS (divisor) is infinite residue=0; if (op&(REMAINDER|REMNEAR)) { // result is [finished clone of] lhs decCopyFit(res, lhs, set, &residue, status); } else { // a division decNumberZero(res); res->bits=bits; // set +/- zero // for DIVIDEINT the exponent is always 0. For DIVIDE, result // is a 0 with infinitely negative exponent, clamped to minimum if (op&DIVIDE) { res->exponent=set->emin-set->digits+1; *status|=DEC_Clamped; } } decFinish(res, set, &residue, status); break; } } // handle 0 rhs (x/0) if (ISZERO(rhs)) { // x/0 is always exceptional if (ISZERO(lhs)) { decNumberZero(res); // [after lhs test] *status|=DEC_Division_undefined;// 0/0 will become NaN } else { decNumberZero(res); if (op&(REMAINDER|REMNEAR)) *status|=DEC_Invalid_operation; else { *status|=DEC_Division_by_zero; // x/0 res->bits=bits|DECINF; // .. is +/- Infinity } } break;} // handle 0 lhs (0/x) if (ISZERO(lhs)) { // 0/x [x!=0] #if DECSUBSET if (!set->extended) decNumberZero(res); else { #endif if (op&DIVIDE) { residue=0; exponent=lhs->exponent-rhs->exponent; // ideal exponent decNumberCopy(res, lhs); // [zeros always fit] res->bits=bits; // sign as computed res->exponent=exponent; // exponent, too decFinalize(res, set, &residue, status); // check exponent } else if (op&DIVIDEINT) { decNumberZero(res); // integer 0 res->bits=bits; // sign as computed } else { // a remainder exponent=rhs->exponent; // [save in case overwrite] decNumberCopy(res, lhs); // [zeros always fit] if (exponentexponent) res->exponent=exponent; // use lower } #if DECSUBSET } #endif break;} // Precalculate exponent. This starts off adjusted (and hence fits // in 31 bits) and becomes the usual unadjusted exponent as the // division proceeds. The order of evaluation is important, here, // to avoid wrap. exponent=(lhs->exponent+lhs->digits)-(rhs->exponent+rhs->digits); // If the working exponent is -ve, then some quick exits are // possible because the quotient is known to be <1 // [for REMNEAR, it needs to be < -1, as -0.5 could need work] if (exponent<0 && !(op==DIVIDE)) { if (op&DIVIDEINT) { decNumberZero(res); // integer part is 0 #if DECSUBSET if (set->extended) #endif res->bits=bits; // set +/- zero break;} // fastpath remainders so long as the lhs has the smaller // (or equal) exponent if (lhs->exponent<=rhs->exponent) { if (op&REMAINDER || exponent<-1) { // It is REMAINDER or safe REMNEAR; result is [finished // clone of] lhs (r = x - 0*y) residue=0; decCopyFit(res, lhs, set, &residue, status); decFinish(res, set, &residue, status); break; } // [unsafe REMNEAR drops through] } } // fastpaths /* Long (slow) division is needed; roll up the sleeves... */ // The accumulator will hold the quotient of the division. // If it needs to be too long for stack storage, then allocate. acclength=D2U(reqdigits+DECDPUN); // in Units if (acclength*sizeof(Unit)>sizeof(accbuff)) { allocacc=(Unit *)malloc(acclength*sizeof(Unit)); if (allocacc==NULL) { // hopeless -- abandon *status|=DEC_Insufficient_storage; break;} acc=allocacc; // use the allocated space } // var1 is the padded LHS ready for subtractions. // If it needs to be too long for stack storage, then allocate. // The maximum units needed for var1 (long subtraction) is: // Enough for // (rhs->digits+reqdigits-1) -- to allow full slide to right // or (lhs->digits) -- to allow for long lhs // whichever is larger // +1 -- for rounding of slide to right // +1 -- for leading 0s // +1 -- for pre-adjust if a remainder or DIVIDEINT // [Note: unused units do not participate in decUnitAddSub data] maxdigits=rhs->digits+reqdigits-1; if (lhs->digits>maxdigits) maxdigits=lhs->digits; var1units=D2U(maxdigits)+2; // allocate a guard unit above msu1 for REMAINDERNEAR if (!(op&DIVIDE)) var1units++; if ((var1units+1)*sizeof(Unit)>sizeof(varbuff)) { varalloc=(Unit *)malloc((var1units+1)*sizeof(Unit)); if (varalloc==NULL) { // hopeless -- abandon *status|=DEC_Insufficient_storage; break;} var1=varalloc; // use the allocated space } // Extend the lhs and rhs to full long subtraction length. The lhs // is truly extended into the var1 buffer, with 0 padding, so a // subtract in place is always possible. The rhs (var2) has // virtual padding (implemented by decUnitAddSub). // One guard unit was allocated above msu1 for rem=rem+rem in // REMAINDERNEAR. msu1=var1+var1units-1; // msu of var1 source=lhs->lsu+D2U(lhs->digits)-1; // msu of input array for (target=msu1; source>=lhs->lsu; source--, target--) *target=*source; for (; target>=var1; target--) *target=0; // rhs (var2) is left-aligned with var1 at the start var2ulen=var1units; // rhs logical length (units) var2units=D2U(rhs->digits); // rhs actual length (units) var2=rhs->lsu; // -> rhs array msu2=var2+var2units-1; // -> msu of var2 [never changes] // now set up the variables which will be used for estimating the // multiplication factor. If these variables are not exact, add // 1 to make sure that the multiplier is never overestimated. msu2plus=*msu2; // it's value .. if (var2units>1) msu2plus++; // .. +1 if any more msu2pair=(eInt)*msu2*(DECDPUNMAX+1);// top two pair .. if (var2units>1) { // .. [else treat 2nd as 0] msu2pair+=*(msu2-1); // .. if (var2units>2) msu2pair++; // .. +1 if any more } // The calculation is working in units, which may have leading zeros, // but the exponent was calculated on the assumption that they are // both left-aligned. Adjust the exponent to compensate: add the // number of leading zeros in var1 msu and subtract those in var2 msu. // [This is actually done by counting the digits and negating, as // lead1=DECDPUN-digits1, and similarly for lead2.] for (pow=&powers[1]; *msu1>=*pow; pow++) exponent--; for (pow=&powers[1]; *msu2>=*pow; pow++) exponent++; // Now, if doing an integer divide or remainder, ensure that // the result will be Unit-aligned. To do this, shift the var1 // accumulator towards least if need be. (It's much easier to // do this now than to reassemble the residue afterwards, if // doing a remainder.) Also ensure the exponent is not negative. if (!(op&DIVIDE)) { Unit *u; // work // save the initial 'false' padding of var1, in digits var1initpad=(var1units-D2U(lhs->digits))*DECDPUN; // Determine the shift to do. if (exponent<0) cut=-exponent; else cut=DECDPUN-exponent%DECDPUN; decShiftToLeast(var1, var1units, cut); exponent+=cut; // maintain numerical value var1initpad-=cut; // .. and reduce padding // clean any most-significant units which were just emptied for (u=msu1; cut>=DECDPUN; cut-=DECDPUN, u--) *u=0; } // align else { // is DIVIDE maxexponent=lhs->exponent-rhs->exponent; // save // optimization: if the first iteration will just produce 0, // preadjust to skip it [valid for DIVIDE only] if (*msu1<*msu2) { var2ulen--; // shift down exponent-=DECDPUN; // update the exponent } } // ---- start the long-division loops ------------------------------ accunits=0; // no units accumulated yet accdigits=0; // .. or digits accnext=acc+acclength-1; // -> msu of acc [NB: allows digits+1] for (;;) { // outer forever loop thisunit=0; // current unit assumed 0 // find the next unit for (;;) { // inner forever loop // strip leading zero units [from either pre-adjust or from // subtract last time around]. Leave at least one unit. for (; *msu1==0 && msu1>var1; msu1--) var1units--; if (var1units msu for (pv1=msu1; ; pv1--, pv2--) { // v1=*pv1 -- always OK v2=0; // assume in padding if (pv2>=var2) v2=*pv2; // in range if (*pv1!=v2) break; // no longer the same if (pv1==var1) break; // done; leave pv1 as is } // here when all inspected or a difference seen if (*pv1v2. Prepare for real subtraction; the lengths are equal // Estimate the multiplier (there's always a msu1-1)... // Bring in two units of var2 to provide a good estimate. mult=(Int)(((eInt)*msu1*(DECDPUNMAX+1)+*(msu1-1))/msu2pair); } // lengths the same else { // var1units > var2ulen, so subtraction is safe // The var2 msu is one unit towards the lsu of the var1 msu, // so only one unit for var2 can be used. mult=(Int)(((eInt)*msu1*(DECDPUNMAX+1)+*(msu1-1))/msu2plus); } if (mult==0) mult=1; // must always be at least 1 // subtraction needed; var1 is > var2 thisunit=(Unit)(thisunit+mult); // accumulate // subtract var1-var2, into var1; only the overlap needs // processing, as this is an in-place calculation shift=var2ulen-var2units; #if DECTRACE decDumpAr('1', &var1[shift], var1units-shift); decDumpAr('2', var2, var2units); printf("m=%d\n", -mult); #endif decUnitAddSub(&var1[shift], var1units-shift, var2, var2units, 0, &var1[shift], -mult); #if DECTRACE decDumpAr('#', &var1[shift], var1units-shift); #endif // var1 now probably has leading zeros; these are removed at the // top of the inner loop. } // inner loop // The next unit has been calculated in full; unless it's a // leading zero, add to acc if (accunits!=0 || thisunit!=0) { // is first or non-zero *accnext=thisunit; // store in accumulator // account exactly for the new digits if (accunits==0) { accdigits++; // at least one for (pow=&powers[1]; thisunit>=*pow; pow++) accdigits++; } else accdigits+=DECDPUN; accunits++; // update count accnext--; // ready for next if (accdigits>reqdigits) break; // have enough digits } // if the residue is zero, the operation is done (unless divide // or divideInteger and still not enough digits yet) if (*var1==0 && var1units==1) { // residue is 0 if (op&(REMAINDER|REMNEAR)) break; if ((op&DIVIDE) && (exponent<=maxexponent)) break; // [drop through if divideInteger] } // also done enough if calculating remainder or integer // divide and just did the last ('units') unit if (exponent==0 && !(op&DIVIDE)) break; // to get here, var1 is less than var2, so divide var2 by the per- // Unit power of ten and go for the next digit var2ulen--; // shift down exponent-=DECDPUN; // update the exponent } // outer loop // ---- division is complete --------------------------------------- // here: acc has at least reqdigits+1 of good results (or fewer // if early stop), starting at accnext+1 (its lsu) // var1 has any residue at the stopping point // accunits is the number of digits collected in acc if (accunits==0) { // acc is 0 accunits=1; // show have a unit .. accdigits=1; // .. *accnext=0; // .. whose value is 0 } else accnext++; // back to last placed // accnext now -> lowest unit of result residue=0; // assume no residue if (op&DIVIDE) { // record the presence of any residue, for rounding if (*var1!=0 || var1units>1) residue=1; else { // no residue // Had an exact division; clean up spurious trailing 0s. // There will be at most DECDPUN-1, from the final multiply, // and then only if the result is non-0 (and even) and the // exponent is 'loose'. #if DECDPUN>1 Unit lsu=*accnext; if (!(lsu&0x01) && (lsu!=0)) { // count the trailing zeros Int drop=0; for (;; drop++) { // [will terminate because lsu!=0] if (exponent>=maxexponent) break; // don't chop real 0s #if DECDPUN<=4 if ((lsu-QUOT10(lsu, drop+1) *powers[drop+1])!=0) break; // found non-0 digit #else if (lsu%powers[drop+1]!=0) break; // found non-0 digit #endif exponent++; } if (drop>0) { accunits=decShiftToLeast(accnext, accunits, drop); accdigits=decGetDigits(accnext, accunits); accunits=D2U(accdigits); // [exponent was adjusted in the loop] } } // neither odd nor 0 #endif } // exact divide } // divide else /* op!=DIVIDE */ { // check for coefficient overflow if (accdigits+exponent>reqdigits) { *status|=DEC_Division_impossible; break; } if (op & (REMAINDER|REMNEAR)) { // [Here, the exponent will be 0, because var1 was adjusted // appropriately.] Int postshift; // work Flag wasodd=0; // integer was odd Unit *quotlsu; // for save Int quotdigits; // .. // Fastpath when residue is truly 0 is worthwhile [and // simplifies the code below] if (*var1==0 && var1units==1) { // residue is 0 Int exp=lhs->exponent; // save min(exponents) if (rhs->exponentexponent; decNumberZero(res); // 0 coefficient #if DECSUBSET if (set->extended) #endif res->exponent=exp; // .. with proper exponent break; } // note if the quotient was odd if (*accnext & 0x01) wasodd=1; // acc is odd quotlsu=accnext; // save in case need to reinspect quotdigits=accdigits; // .. // treat the residue, in var1, as the value to return, via acc // calculate the unused zero digits. This is the smaller of: // var1 initial padding (saved above) // var2 residual padding, which happens to be given by: postshift=var1initpad+exponent-lhs->exponent+rhs->exponent; // [the 'exponent' term accounts for the shifts during divide] if (var1initpadexponent; // exponent is smaller of lhs & rhs if (rhs->exponentexponent; bits=lhs->bits; // remainder sign is always as lhs // Now correct the result if doing remainderNear; if it // (looking just at coefficients) is > rhs/2, or == rhs/2 and // the integer was odd then the result should be rem-rhs. if (op&REMNEAR) { Int compare, tarunits; // work Unit *up; // .. // calculate remainder*2 into the var1 buffer (which has // 'headroom' of an extra unit and hence enough space) // [a dedicated 'double' loop would be faster, here] tarunits=decUnitAddSub(accnext, accunits, accnext, accunits, 0, accnext, 1); // decDumpAr('r', accnext, tarunits); // Here, accnext (var1) holds tarunits Units with twice the // remainder's coefficient, which must now be compared to the // RHS. The remainder's exponent may be smaller than the RHS's. compare=decUnitCompare(accnext, tarunits, rhs->lsu, D2U(rhs->digits), rhs->exponent-exponent); if (compare==BADINT) { // deep trouble *status|=DEC_Insufficient_storage; break;} // now restore the remainder by dividing by two; the lsu // is known to be even. for (up=accnext; up0 || (compare==0 && wasodd)) { // adjustment needed Int exp, expunits, exprem; // work // This is effectively causing round-up of the quotient, // so if it was the rare case where it was full and all // nines, it would overflow and hence division-impossible // should be raised Flag allnines=0; // 1 if quotient all nines if (quotdigits==reqdigits) { // could be borderline for (up=quotlsu; ; up++) { if (quotdigits>DECDPUN) { if (*up!=DECDPUNMAX) break;// non-nines } else { // this is the last Unit if (*up==powers[quotdigits]-1) allnines=1; break; } quotdigits-=DECDPUN; // checked those digits } // up } // borderline check if (allnines) { *status|=DEC_Division_impossible; break;} // rem-rhs is needed; the sign will invert. Again, var1 // can safely be used for the working Units array. exp=rhs->exponent-exponent; // RHS padding needed // Calculate units and remainder from exponent. expunits=exp/DECDPUN; exprem=exp%DECDPUN; // subtract [A+B*(-m)]; the result will always be negative accunits=-decUnitAddSub(accnext, accunits, rhs->lsu, D2U(rhs->digits), expunits, accnext, -(Int)powers[exprem]); accdigits=decGetDigits(accnext, accunits); // count digits exactly accunits=D2U(accdigits); // and recalculate the units for copy // [exponent is as for original remainder] bits^=DECNEG; // flip the sign } } // REMNEAR } // REMAINDER or REMNEAR } // not DIVIDE // Set exponent and bits res->exponent=exponent; res->bits=(uByte)(bits&DECNEG); // [cleaned] // Now the coefficient. decSetCoeff(res, set, accnext, accdigits, &residue, status); decFinish(res, set, &residue, status); // final cleanup #if DECSUBSET // If a divide then strip trailing zeros if subset [after round] if (!set->extended && (op==DIVIDE)) decTrim(res, 0, &dropped); #endif } while(0); // end protected if (varalloc!=NULL) free(varalloc); // drop any storage used if (allocacc!=NULL) free(allocacc); // .. #if DECSUBSET if (allocrhs!=NULL) free(allocrhs); // .. if (alloclhs!=NULL) free(alloclhs); // .. #endif return res; } // decDivideOp /* ------------------------------------------------------------------ */ /* decMultiplyOp -- multiplication operation */ /* */ /* This routine performs the multiplication C=A x B. */ /* */ /* res is C, the result. C may be A and/or B (e.g., X=X*X) */ /* lhs is A */ /* rhs is B */ /* set is the context */ /* status is the usual accumulator */ /* */ /* C must have space for set->digits digits. */ /* */ /* ------------------------------------------------------------------ */ /* 'Classic' multiplication is used rather than Karatsuba, as the */ /* latter would give only a minor improvement for the short numbers */ /* expected to be handled most (and uses much more memory). */ /* */ /* There are two major paths here: the general-purpose ('old code') */ /* path which handles all DECDPUN values, and a fastpath version */ /* which is used if 64-bit ints are available, DECDPUN<=4, and more */ /* than two calls to decUnitAddSub would be made. */ /* */ /* The fastpath version lumps units together into 8-digit or 9-digit */ /* chunks, and also uses a lazy carry strategy to minimise expensive */ /* 64-bit divisions. The chunks are then broken apart again into */ /* units for continuing processing. Despite this overhead, the */ /* fastpath can speed up some 16-digit operations by 10x (and much */ /* more for higher-precision calculations). */ /* */ /* A buffer always has to be used for the accumulator; in the */ /* fastpath, buffers are also always needed for the chunked copies of */ /* of the operand coefficients. */ /* ------------------------------------------------------------------ */ #define FASTMUL (DECUSE64 && DECDPUN<5) static decNumber * decMultiplyOp(decNumber *res, const decNumber *lhs, const decNumber *rhs, decContext *set, uInt *status) { Int accunits; // Units of accumulator in use Int exponent; // work Int residue=0; // rounding residue uByte bits; // result sign Unit *acc; // -> accumulator Unit array Int needbytes; // size calculator void *allocacc=NULL; // -> allocated accumulator, iff allocated Unit accbuff[SD2U(DECBUFFER*2+5)]; // buffer (+1 for DECBUFFER==0, // + 4 for calls from other operations) const Unit *mer, *mermsup; // work Int madlength; // Units in multiplicand Int shift; // Units to shift multiplicand by #if FASTMUL // if DECDPUN is 1 or 3 work in base 10**9, otherwise // (DECDPUN is 2 or 4) then work in base 10**8 #if DECDPUN & 1 // odd #define FASTBASE 1000000000 // base #define FASTDIGS 9 // digits in base #define FASTLAZY 18 // carry resolution point [1->18] #else #define FASTBASE 100000000 #define FASTDIGS 8 #define FASTLAZY 1844 // carry resolution point [1->1844] #endif // three buffers are used, two for chunked copies of the operands // (base 10**8 or base 10**9) and one base 2**64 accumulator with // lazy carry evaluation uInt zlhibuff[(DECBUFFER+7)/8+1]; // buffer (+1 for DECBUFFER==0) uInt *zlhi=zlhibuff; // -> lhs array uInt *alloclhi=NULL; // -> allocated buffer, iff allocated uInt zrhibuff[(DECBUFFER+7)/8+1]; // buffer (+1 for DECBUFFER==0) uInt *zrhi=zrhibuff; // -> rhs array uInt *allocrhi=NULL; // -> allocated buffer, iff allocated uLong zaccbuff[(DECBUFFER+3)/4+2]; // buffer (+1 for DECBUFFER==0) // + 1 for calls from other operations) // [allocacc is shared for both paths, as only one will run] uLong *zacc=zaccbuff; // -> accumulator array for exact result #if DECDPUN==1 Int zoff; // accumulator offset #endif uInt *lip, *rip; // item pointers uInt *lmsi, *rmsi; // most significant items Int ilhs, irhs, iacc; // item counts in the arrays Int lazy; // lazy carry counter uLong lcarry; // uLong carry uInt carry; // carry (NB not uLong) Int count; // work const Unit *cup; // .. Unit *up; // .. uLong *lp; // .. Int p; // .. #endif #if DECSUBSET decNumber *alloclhs=NULL; // -> allocated buffer, iff allocated decNumber *allocrhs=NULL; // -> allocated buffer, iff allocated #endif #if DECCHECK if (decCheckOperands(res, lhs, rhs, set)) return res; #endif // precalculate result sign bits=(uByte)((lhs->bits^rhs->bits)&DECNEG); // handle infinities and NaNs if (SPECIALARGS) { // a special bit set if (SPECIALARGS & (DECSNAN | DECNAN)) { // one or two NaNs decNaNs(res, lhs, rhs, status); return res;} // one or two infinities; Infinity * 0 is invalid if (((lhs->bits & DECINF)==0 && ISZERO(lhs)) ||((rhs->bits & DECINF)==0 && ISZERO(rhs))) { *status|=DEC_Invalid_operation; return res;} decNumberZero(res); res->bits=bits|DECINF; // infinity return res;} // For best speed, as in DMSRCN [the original Rexx numerics // module], use the shorter number as the multiplier (rhs) and // the longer as the multiplicand (lhs) to minimise the number of // adds (partial products) if (lhs->digitsdigits) { // swap... const decNumber *hold=lhs; lhs=rhs; rhs=hold; } do { // protect allocated storage #if DECSUBSET if (!set->extended) { // reduce operands and set lostDigits status, as needed if (lhs->digits>set->digits) { alloclhs=decRoundOperand(lhs, set, status); if (alloclhs==NULL) break; lhs=alloclhs; } if (rhs->digits>set->digits) { allocrhs=decRoundOperand(rhs, set, status); if (allocrhs==NULL) break; rhs=allocrhs; } } #endif // [following code does not require input rounding] #if FASTMUL // fastpath can be used // use the fast path if there are enough digits in the shorter // operand to make the setup and takedown worthwhile #define NEEDTWO (DECDPUN*2) // within two decUnitAddSub calls if (rhs->digits>NEEDTWO) { // use fastpath... // calculate the number of elements in each array ilhs=(lhs->digits+FASTDIGS-1)/FASTDIGS; // [ceiling] irhs=(rhs->digits+FASTDIGS-1)/FASTDIGS; // .. iacc=ilhs+irhs; // allocate buffers if required, as usual needbytes=ilhs*sizeof(uInt); if (needbytes>(Int)sizeof(zlhibuff)) { alloclhi=(uInt *)malloc(needbytes); zlhi=alloclhi;} needbytes=irhs*sizeof(uInt); if (needbytes>(Int)sizeof(zrhibuff)) { allocrhi=(uInt *)malloc(needbytes); zrhi=allocrhi;} // Allocating the accumulator space needs a special case when // DECDPUN=1 because when converting the accumulator to Units // after the multiplication each 8-byte item becomes 9 1-byte // units. Therefore iacc extra bytes are needed at the front // (rounded up to a multiple of 8 bytes), and the uLong // accumulator starts offset the appropriate number of units // to the right to avoid overwrite during the unchunking. needbytes=iacc*sizeof(uLong); #if DECDPUN==1 zoff=(iacc+7)/8; // items to offset by needbytes+=zoff*8; #endif if (needbytes>(Int)sizeof(zaccbuff)) { allocacc=(uLong *)malloc(needbytes); zacc=(uLong *)allocacc;} if (zlhi==NULL||zrhi==NULL||zacc==NULL) { *status|=DEC_Insufficient_storage; break;} acc=(Unit *)zacc; // -> target Unit array #if DECDPUN==1 zacc+=zoff; // start uLong accumulator to right #endif // assemble the chunked copies of the left and right sides for (count=lhs->digits, cup=lhs->lsu, lip=zlhi; count>0; lip++) for (p=0, *lip=0; p0; p+=DECDPUN, cup++, count-=DECDPUN) *lip+=*cup*powers[p]; lmsi=lip-1; // save -> msi for (count=rhs->digits, cup=rhs->lsu, rip=zrhi; count>0; rip++) for (p=0, *rip=0; p0; p+=DECDPUN, cup++, count-=DECDPUN) *rip+=*cup*powers[p]; rmsi=rip-1; // save -> msi // zero the accumulator for (lp=zacc; lp0 && rip!=rmsi) continue; lazy=FASTLAZY; // reset delay count // spin up the accumulator resolving overflows for (lp=zacc; lp assume buffer for accumulator needbytes=(D2U(lhs->digits)+D2U(rhs->digits))*sizeof(Unit); if (needbytes>(Int)sizeof(accbuff)) { allocacc=(Unit *)malloc(needbytes); if (allocacc==NULL) {*status|=DEC_Insufficient_storage; break;} acc=(Unit *)allocacc; // use the allocated space } /* Now the main long multiplication loop */ // Unlike the equivalent in the IBM Java implementation, there // is no advantage in calculating from msu to lsu. So, do it // by the book, as it were. // Each iteration calculates ACC=ACC+MULTAND*MULT accunits=1; // accumulator starts at '0' *acc=0; // .. (lsu=0) shift=0; // no multiplicand shift at first madlength=D2U(lhs->digits); // this won't change mermsup=rhs->lsu+D2U(rhs->digits); // -> msu+1 of multiplier for (mer=rhs->lsu; merlsu, madlength, 0, &acc[shift], *mer) + shift; else { // extend acc with a 0; it will be used shortly *(acc+accunits)=0; // [this avoids length of <=0 later] accunits++; } // multiply multiplicand by 10**DECDPUN for next Unit to left shift++; // add this for 'logical length' } // n #if FASTMUL } // unchunked units #endif // common end-path #if DECTRACE decDumpAr('*', acc, accunits); // Show exact result #endif // acc now contains the exact result of the multiplication, // possibly with a leading zero unit; build the decNumber from // it, noting if any residue res->bits=bits; // set sign res->digits=decGetDigits(acc, accunits); // count digits exactly // There can be a 31-bit wrap in calculating the exponent. // This can only happen if both input exponents are negative and // both their magnitudes are large. If there was a wrap, set a // safe very negative exponent, from which decFinalize() will // raise a hard underflow shortly. exponent=lhs->exponent+rhs->exponent; // calculate exponent if (lhs->exponent<0 && rhs->exponent<0 && exponent>0) exponent=-2*DECNUMMAXE; // force underflow res->exponent=exponent; // OK to overwrite now // Set the coefficient. If any rounding, residue records decSetCoeff(res, set, acc, res->digits, &residue, status); decFinish(res, set, &residue, status); // final cleanup } while(0); // end protected if (allocacc!=NULL) free(allocacc); // drop any storage used #if DECSUBSET if (allocrhs!=NULL) free(allocrhs); // .. if (alloclhs!=NULL) free(alloclhs); // .. #endif #if FASTMUL if (allocrhi!=NULL) free(allocrhi); // .. if (alloclhi!=NULL) free(alloclhi); // .. #endif return res; } // decMultiplyOp /* ------------------------------------------------------------------ */ /* decExpOp -- effect exponentiation */ /* */ /* This computes C = exp(A) */ /* */ /* res is C, the result. C may be A */ /* rhs is A */ /* set is the context; note that rounding mode has no effect */ /* */ /* C must have space for set->digits digits. status is updated but */ /* not set. */ /* */ /* Restrictions: */ /* */ /* digits, emax, and -emin in the context must be less than */ /* 2*DEC_MAX_MATH (1999998), and the rhs must be within these */ /* bounds or a zero. This is an internal routine, so these */ /* restrictions are contractual and not enforced. */ /* */ /* A finite result is rounded using DEC_ROUND_HALF_EVEN; it will */ /* almost always be correctly rounded, but may be up to 1 ulp in */ /* error in rare cases. */ /* */ /* Finite results will always be full precision and Inexact, except */ /* when A is a zero or -Infinity (giving 1 or 0 respectively). */ /* ------------------------------------------------------------------ */ /* This approach used here is similar to the algorithm described in */ /* */ /* Variable Precision Exponential Function, T. E. Hull and */ /* A. Abrham, ACM Transactions on Mathematical Software, Vol 12 #2, */ /* pp79-91, ACM, June 1986. */ /* */ /* with the main difference being that the iterations in the series */ /* evaluation are terminated dynamically (which does not require the */ /* extra variable-precision variables which are expensive in this */ /* context). */ /* */ /* The error analysis in Hull & Abrham's paper applies except for the */ /* round-off error accumulation during the series evaluation. This */ /* code does not precalculate the number of iterations and so cannot */ /* use Horner's scheme. Instead, the accumulation is done at double- */ /* precision, which ensures that the additions of the terms are exact */ /* and do not accumulate round-off (and any round-off errors in the */ /* terms themselves move 'to the right' faster than they can */ /* accumulate). This code also extends the calculation by allowing, */ /* in the spirit of other decNumber operators, the input to be more */ /* precise than the result (the precision used is based on the more */ /* precise of the input or requested result). */ /* */ /* Implementation notes: */ /* */ /* 1. This is separated out as decExpOp so it can be called from */ /* other Mathematical functions (notably Ln) with a wider range */ /* than normal. In particular, it can handle the slightly wider */ /* (double) range needed by Ln (which has to be able to calculate */ /* exp(-x) where x can be the tiniest number (Ntiny). */ /* */ /* 2. Normalizing x to be <=0.1 (instead of <=1) reduces loop */ /* iterations by appoximately a third with additional (although */ /* diminishing) returns as the range is reduced to even smaller */ /* fractions. However, h (the power of 10 used to correct the */ /* result at the end, see below) must be kept <=8 as otherwise */ /* the final result cannot be computed. Hence the leverage is a */ /* sliding value (8-h), where potentially the range is reduced */ /* more for smaller values. */ /* */ /* The leverage that can be applied in this way is severely */ /* limited by the cost of the raise-to-the power at the end, */ /* which dominates when the number of iterations is small (less */ /* than ten) or when rhs is short. As an example, the adjustment */ /* x**10,000,000 needs 31 multiplications, all but one full-width. */ /* */ /* 3. The restrictions (especially precision) could be raised with */ /* care, but the full decNumber range seems very hard within the */ /* 32-bit limits. */ /* ------------------------------------------------------------------ */ decNumber * decExpOp(decNumber *res, const decNumber *rhs, decContext *set, uInt *status) { uInt ignore=0; // working status Int h; // adjusted exponent for 0.xxxx Int p; // working precision Int residue; // rounding residue uInt needbytes; // for space calculations const decNumber *x=rhs; // (may point to safe copy later) decContext aset, tset, dset; // working contexts // the argument is often copied to normalize it, so (unusually) it // is treated like other buffers, using DECBUFFER, +1 in case // DECBUFFER is 0 decNumber bufr[D2N(DECBUFFER+1)]; decNumber *allocrhs=NULL; // non-NULL if rhs buffer allocated // the working precision will be no more than set->digits+8+1 // so for on-stack buffers DECBUFFER+9 is used, +1 in case DECBUFFER // is 0 (and twice that for the accumulator) // buffer for t, term (working precision plus) decNumber buft[D2N(DECBUFFER+9+1)]; decNumber *allocbuft=NULL; // -> allocated buft, iff allocated decNumber *t=buft; // term // buffer for a, accumulator (working precision * 2), at least 9 decNumber bufa[D2N(DECBUFFER*2+18+1)]; decNumber *allocbufa=NULL; // -> allocated bufa, iff allocated decNumber *a=bufa; // accumulator // decNumber for the divisor term; this needs at most 9 digits // and so can be fixed size [16 so can use standard context] decNumber bufd[D2N(16)]; decNumber *d=bufd; // divisor decNumber numone; // constant 1 #if DECCHECK Int iterations=0; // for later sanity check if (decCheckOperands(res, DECUNUSED, rhs, set)) return res; #endif do { // protect allocated storage if (SPECIALARG) { // handle infinities and NaNs if (decNumberIsInfinite(rhs)) { // an infinity if (decNumberIsNegative(rhs)) // -Infinity -> +0 decNumberZero(res); else decNumberCopy(res, rhs); // +Infinity -> self } else decNaNs(res, rhs, NULL, status); // a NaN break;} if (ISZERO(rhs)) { // zeros -> exact 1 decNumberZero(res); // make clean 1 *res->lsu=1; // .. break;} // [no status to set] // e**x when 0 < x < 0.66 is < 1+3x/2, hence can fast-path // positive and negative tiny cases which will result in inexact // 1. This also allows the later add-accumulate to always be // exact (because its length will never be more than twice the // working precision). // The comparator (tiny) needs just one digit, so use the // decNumber d for it (reused as the divisor, etc., below); its // exponent is such that if x is positive it will have // set->digits-1 zeros between the decimal point and the digit, // which is 4, and if x is negative one more zero there as the // more precise result will be of the form 0.9999999 rather than // 1.0000001. Hence, tiny will be 0.0000004 if digits=7 and x>0 // or 0.00000004 if digits=7 and x<0. If RHS not larger than // this then the result will be 1.000000 decNumberZero(d); // clean *d->lsu=4; // set 4 .. d->exponent=-set->digits; // * 10**(-d) if (decNumberIsNegative(rhs)) d->exponent--; // negative case if (decCompare(d, rhs, 1)>=0) { // signless compare Int shift=set->digits-1; decNumberZero(res); // set 1 *res->lsu=1; // .. res->digits=decShiftToMost(res->lsu, 1, shift); res->exponent=-shift; // make 1.0000... *status|=DEC_Inexact | DEC_Rounded; // .. inexactly break;} // tiny // set up the context to be used for calculating a, as this is // used on both paths below decContextDefault(&aset, DEC_INIT_DECIMAL64); // accumulator bounds are as requested (could underflow) aset.emax=set->emax; // usual bounds aset.emin=set->emin; // .. aset.clamp=0; // and no concrete format // calculate the adjusted (Hull & Abrham) exponent (where the // decimal point is just to the left of the coefficient msd) h=rhs->exponent+rhs->digits; // if h>8 then 10**h cannot be calculated safely; however, when // h=8 then exp(|rhs|) will be at least exp(1E+7) which is at // least 6.59E+4342944, so (due to the restriction on Emax/Emin) // overflow (or underflow to 0) is guaranteed -- so this case can // be handled by simply forcing the appropriate excess if (h>8) { // overflow/underflow // set up here so Power call below will over or underflow to // zero; set accumulator to either 2 or 0.02 // [stack buffer for a is always big enough for this] decNumberZero(a); *a->lsu=2; // not 1 but < exp(1) if (decNumberIsNegative(rhs)) a->exponent=-2; // make 0.02 h=8; // clamp so 10**h computable p=9; // set a working precision } else { // h<=8 Int maxlever=(rhs->digits>8?1:0); // [could/should increase this for precisions >40 or so, too] // if h is 8, cannot normalize to a lower upper limit because // the final result will not be computable (see notes above), // but leverage can be applied whenever h is less than 8. // Apply as much as possible, up to a MAXLEVER digits, which // sets the tradeoff against the cost of the later a**(10**h). // As h is increased, the working precision below also // increases to compensate for the "constant digits at the // front" effect. Int lever=MIN(8-h, maxlever); // leverage attainable Int use=-rhs->digits-lever; // exponent to use for RHS h+=lever; // apply leverage selected if (h<0) { // clamp use+=h; // [may end up subnormal] h=0; } // Take a copy of RHS if it needs normalization (true whenever x>=1) if (rhs->exponent!=use) { decNumber *newrhs=bufr; // assume will fit on stack needbytes=sizeof(decNumber)+(D2U(rhs->digits)-1)*sizeof(Unit); if (needbytes>sizeof(bufr)) { // need malloc space allocrhs=(decNumber *)malloc(needbytes); if (allocrhs==NULL) { // hopeless -- abandon *status|=DEC_Insufficient_storage; break;} newrhs=allocrhs; // use the allocated space } decNumberCopy(newrhs, rhs); // copy to safe space newrhs->exponent=use; // normalize; now <1 x=newrhs; // ready for use // decNumberShow(x); } // Now use the usual power series to evaluate exp(x). The // series starts as 1 + x + x^2/2 ... so prime ready for the // third term by setting the term variable t=x, the accumulator // a=1, and the divisor d=2. // First determine the working precision. From Hull & Abrham // this is set->digits+h+2. However, if x is 'over-precise' we // need to allow for all its digits to potentially participate // (consider an x where all the excess digits are 9s) so in // this case use x->digits+h+2 p=MAX(x->digits, set->digits)+h+2; // a and t are variable precision, and depend on p, so space // must be allocated for them if necessary // the accumulator needs to be able to hold 2p digits so that // the additions on the second and subsequent iterations are // sufficiently exact. needbytes=sizeof(decNumber)+(D2U(p*2)-1)*sizeof(Unit); if (needbytes>sizeof(bufa)) { // need malloc space allocbufa=(decNumber *)malloc(needbytes); if (allocbufa==NULL) { // hopeless -- abandon *status|=DEC_Insufficient_storage; break;} a=allocbufa; // use the allocated space } // the term needs to be able to hold p digits (which is // guaranteed to be larger than x->digits, so the initial copy // is safe); it may also be used for the raise-to-power // calculation below, which needs an extra two digits needbytes=sizeof(decNumber)+(D2U(p+2)-1)*sizeof(Unit); if (needbytes>sizeof(buft)) { // need malloc space allocbuft=(decNumber *)malloc(needbytes); if (allocbuft==NULL) { // hopeless -- abandon *status|=DEC_Insufficient_storage; break;} t=allocbuft; // use the allocated space } decNumberCopy(t, x); // term=x decNumberZero(a); *a->lsu=1; // accumulator=1 decNumberZero(d); *d->lsu=2; // divisor=2 decNumberZero(&numone); *numone.lsu=1; // constant 1 for increment // set up the contexts for calculating a, t, and d decContextDefault(&tset, DEC_INIT_DECIMAL64); dset=tset; // accumulator bounds are set above, set precision now aset.digits=p*2; // double // term bounds avoid any underflow or overflow tset.digits=p; tset.emin=DEC_MIN_EMIN; // [emax is plenty] // [dset.digits=16, etc., are sufficient] // finally ready to roll for (;;) { #if DECCHECK iterations++; #endif // only the status from the accumulation is interesting // [but it should remain unchanged after first add] decAddOp(a, a, t, &aset, 0, status); // a=a+t decMultiplyOp(t, t, x, &tset, &ignore); // t=t*x decDivideOp(t, t, d, &tset, DIVIDE, &ignore); // t=t/d // the iteration ends when the term cannot affect the result, // if rounded to p digits, which is when its value is smaller // than the accumulator by p+1 digits. There must also be // full precision in a. if (((a->digits+a->exponent)>=(t->digits+t->exponent+p+1)) && (a->digits>=p)) break; decAddOp(d, d, &numone, &dset, 0, &ignore); // d=d+1 } // iterate #if DECCHECK // just a sanity check; comment out test to show always if (iterations>p+3) printf("Exp iterations=%d, status=%08x, p=%d, d=%d\n", iterations, *status, p, x->digits); #endif } // h<=8 // apply postconditioning: a=a**(10**h) -- this is calculated // at a slightly higher precision than Hull & Abrham suggest if (h>0) { Int seenbit=0; // set once a 1-bit is seen Int i; // counter Int n=powers[h]; // always positive aset.digits=p+2; // sufficient precision // avoid the overhead and many extra digits of decNumberPower // as all that is needed is the short 'multipliers' loop; here // accumulate the answer into t decNumberZero(t); *t->lsu=1; // acc=1 for (i=1;;i++){ // for each bit [top bit ignored] // abandon if have had overflow or terminal underflow if (*status & (DEC_Overflow|DEC_Underflow)) { // interesting? if (*status&DEC_Overflow || ISZERO(t)) break;} n=n<<1; // move next bit to testable position if (n<0) { // top bit is set seenbit=1; // OK, have a significant bit decMultiplyOp(t, t, a, &aset, status); // acc=acc*x } if (i==31) break; // that was the last bit if (!seenbit) continue; // no need to square 1 decMultiplyOp(t, t, t, &aset, status); // acc=acc*acc [square] } /*i*/ // 32 bits // decNumberShow(t); a=t; // and carry on using t instead of a } // Copy and round the result to res residue=1; // indicate dirt to right .. if (ISZERO(a)) residue=0; // .. unless underflowed to 0 aset.digits=set->digits; // [use default rounding] decCopyFit(res, a, &aset, &residue, status); // copy & shorten decFinish(res, set, &residue, status); // cleanup/set flags } while(0); // end protected if (allocrhs !=NULL) free(allocrhs); // drop any storage used if (allocbufa!=NULL) free(allocbufa); // .. if (allocbuft!=NULL) free(allocbuft); // .. // [status is handled by caller] return res; } // decExpOp /* ------------------------------------------------------------------ */ /* Initial-estimate natural logarithm table */ /* */ /* LNnn -- 90-entry 16-bit table for values from .10 through .99. */ /* The result is a 4-digit encode of the coefficient (c=the */ /* top 14 bits encoding 0-9999) and a 2-digit encode of the */ /* exponent (e=the bottom 2 bits encoding 0-3) */ /* */ /* The resulting value is given by: */ /* */ /* v = -c * 10**(-e-3) */ /* */ /* where e and c are extracted from entry k = LNnn[x-10] */ /* where x is truncated (NB) into the range 10 through 99, */ /* and then c = k>>2 and e = k&3. */ /* ------------------------------------------------------------------ */ const uShort LNnn[90]={9016, 8652, 8316, 8008, 7724, 7456, 7208, 6972, 6748, 6540, 6340, 6148, 5968, 5792, 5628, 5464, 5312, 5164, 5020, 4884, 4748, 4620, 4496, 4376, 4256, 4144, 4032, 39233, 38181, 37157, 36157, 35181, 34229, 33297, 32389, 31501, 30629, 29777, 28945, 28129, 27329, 26545, 25777, 25021, 24281, 23553, 22837, 22137, 21445, 20769, 20101, 19445, 18801, 18165, 17541, 16925, 16321, 15721, 15133, 14553, 13985, 13421, 12865, 12317, 11777, 11241, 10717, 10197, 9685, 9177, 8677, 8185, 7697, 7213, 6737, 6269, 5801, 5341, 4889, 4437, 39930, 35534, 31186, 26886, 22630, 18418, 14254, 10130, 6046, 20055}; /* ------------------------------------------------------------------ */ /* decLnOp -- effect natural logarithm */ /* */ /* This computes C = ln(A) */ /* */ /* res is C, the result. C may be A */ /* rhs is A */ /* set is the context; note that rounding mode has no effect */ /* */ /* C must have space for set->digits digits. */ /* */ /* Notable cases: */ /* A<0 -> Invalid */ /* A=0 -> -Infinity (Exact) */ /* A=+Infinity -> +Infinity (Exact) */ /* A=1 exactly -> 0 (Exact) */ /* */ /* Restrictions (as for Exp): */ /* */ /* digits, emax, and -emin in the context must be less than */ /* DEC_MAX_MATH+11 (1000010), and the rhs must be within these */ /* bounds or a zero. This is an internal routine, so these */ /* restrictions are contractual and not enforced. */ /* */ /* A finite result is rounded using DEC_ROUND_HALF_EVEN; it will */ /* almost always be correctly rounded, but may be up to 1 ulp in */ /* error in rare cases. */ /* ------------------------------------------------------------------ */ /* The result is calculated using Newton's method, with each */ /* iteration calculating a' = a + x * exp(-a) - 1. See, for example, */ /* Epperson 1989. */ /* */ /* The iteration ends when the adjustment x*exp(-a)-1 is tiny enough. */ /* This has to be calculated at the sum of the precision of x and the */ /* working precision. */ /* */ /* Implementation notes: */ /* */ /* 1. This is separated out as decLnOp so it can be called from */ /* other Mathematical functions (e.g., Log 10) with a wider range */ /* than normal. In particular, it can handle the slightly wider */ /* (+9+2) range needed by a power function. */ /* */ /* 2. The speed of this function is about 10x slower than exp, as */ /* it typically needs 4-6 iterations for short numbers, and the */ /* extra precision needed adds a squaring effect, twice. */ /* */ /* 3. Fastpaths are included for ln(10) and ln(2), up to length 40, */ /* as these are common requests. ln(10) is used by log10(x). */ /* */ /* 4. An iteration might be saved by widening the LNnn table, and */ /* would certainly save at least one if it were made ten times */ /* bigger, too (for truncated fractions 0.100 through 0.999). */ /* However, for most practical evaluations, at least four or five */ /* iterations will be neede -- so this would only speed up by */ /* 20-25% and that probably does not justify increasing the table */ /* size. */ /* ------------------------------------------------------------------ */ decNumber * decLnOp(decNumber *res, const decNumber *rhs, decContext *set, uInt *status) { uInt ignore=0; // working status accumulator uInt needbytes; // for space calculations Int residue; // rounding residue Int r; // rhs=f*10**r [see below] Int p; // working precision Int pp; // precision for iteration Int t; // work // buffers for a (accumulator, typically precision+2) and b // (adjustment calculator, same size) decNumber bufa[D2N(DECBUFFER+2)]; decNumber *allocbufa=NULL; // -> allocated bufa, iff allocated decNumber *a=bufa; // accumulator/work decNumber bufb[D2N(DECBUFFER+2)]; decNumber *allocbufb=NULL; // -> allocated bufa, iff allocated decNumber *b=bufb; // adjustment/work decNumber numone; // constant 1 decNumber cmp; // work decContext aset, bset; // working contexts #if DECCHECK Int iterations=0; // for later sanity check if (decCheckOperands(res, DECUNUSED, rhs, set)) return res; #endif do { // protect allocated storage if (SPECIALARG) { // handle infinities and NaNs if (decNumberIsInfinite(rhs)) { // an infinity if (decNumberIsNegative(rhs)) // -Infinity -> error *status|=DEC_Invalid_operation; else decNumberCopy(res, rhs); // +Infinity -> self } else decNaNs(res, rhs, NULL, status); // a NaN break;} if (ISZERO(rhs)) { // +/- zeros -> -Infinity decNumberZero(res); // make clean res->bits=DECINF|DECNEG; // set - infinity break;} // [no status to set] // Non-zero negatives are bad... if (decNumberIsNegative(rhs)) { // -x -> error *status|=DEC_Invalid_operation; break;} // Here, rhs is positive, finite, and in range // lookaside fastpath code for ln(2) and ln(10) at common lengths if (rhs->exponent==0 && set->digits<=40) { #if DECDPUN==1 if (rhs->lsu[0]==0 && rhs->lsu[1]==1 && rhs->digits==2) { // ln(10) #else if (rhs->lsu[0]==10 && rhs->digits==2) { // ln(10) #endif aset=*set; aset.round=DEC_ROUND_HALF_EVEN; #define LN10 "2.302585092994045684017991454684364207601" decNumberFromString(res, LN10, &aset); *status|=(DEC_Inexact | DEC_Rounded); // is inexact break;} if (rhs->lsu[0]==2 && rhs->digits==1) { // ln(2) aset=*set; aset.round=DEC_ROUND_HALF_EVEN; #define LN2 "0.6931471805599453094172321214581765680755" decNumberFromString(res, LN2, &aset); *status|=(DEC_Inexact | DEC_Rounded); break;} } // integer and short // Determine the working precision. This is normally the // requested precision + 2, with a minimum of 9. However, if // the rhs is 'over-precise' then allow for all its digits to // potentially participate (consider an rhs where all the excess // digits are 9s) so in this case use rhs->digits+2. p=MAX(rhs->digits, MAX(set->digits, 7))+2; // Allocate space for the accumulator and the high-precision // adjustment calculator, if necessary. The accumulator must // be able to hold p digits, and the adjustment up to // rhs->digits+p digits. They are also made big enough for 16 // digits so that they can be used for calculating the initial // estimate. needbytes=sizeof(decNumber)+(D2U(MAX(p,16))-1)*sizeof(Unit); if (needbytes>sizeof(bufa)) { // need malloc space allocbufa=(decNumber *)malloc(needbytes); if (allocbufa==NULL) { // hopeless -- abandon *status|=DEC_Insufficient_storage; break;} a=allocbufa; // use the allocated space } pp=p+rhs->digits; needbytes=sizeof(decNumber)+(D2U(MAX(pp,16))-1)*sizeof(Unit); if (needbytes>sizeof(bufb)) { // need malloc space allocbufb=(decNumber *)malloc(needbytes); if (allocbufb==NULL) { // hopeless -- abandon *status|=DEC_Insufficient_storage; break;} b=allocbufb; // use the allocated space } // Prepare an initial estimate in acc. Calculate this by // considering the coefficient of x to be a normalized fraction, // f, with the decimal point at far left and multiplied by // 10**r. Then, rhs=f*10**r and 0.1<=f<1, and // ln(x) = ln(f) + ln(10)*r // Get the initial estimate for ln(f) from a small lookup // table (see above) indexed by the first two digits of f, // truncated. decContextDefault(&aset, DEC_INIT_DECIMAL64); // 16-digit extended r=rhs->exponent+rhs->digits; // 'normalised' exponent decPutInt(a, r); // a=r decPutInt(b, 2302585); // b=ln(10) (2.302585) b->exponent=-6; // .. decMultiplyOp(a, a, b, &aset, &ignore); // a=a*b // now get top two digits of rhs into b by simple truncate and // force to integer residue=0; // (no residue) aset.digits=2; aset.round=DEC_ROUND_DOWN; decCopyFit(b, rhs, &aset, &residue, &ignore); // copy & shorten b->exponent=0; // make integer t=decGetInt(b); // [cannot fail] if (t<10) t=X10(t); // adjust single-digit b t=LNnn[t-10]; // look up ln(b) decPutInt(b, t>>2); // b=ln(b) coefficient b->exponent=-(t&3)-3; // set exponent b->bits=DECNEG; // ln(0.10)->ln(0.99) always -ve aset.digits=16; aset.round=DEC_ROUND_HALF_EVEN; // restore decAddOp(a, a, b, &aset, 0, &ignore); // acc=a+b // the initial estimate is now in a, with up to 4 digits correct. // When rhs is at or near Nmax the estimate will be low, so we // will approach it from below, avoiding overflow when calling exp. decNumberZero(&numone); *numone.lsu=1; // constant 1 for adjustment // accumulator bounds are as requested (could underflow, but // cannot overflow) aset.emax=set->emax; aset.emin=set->emin; aset.clamp=0; // no concrete format // set up a context to be used for the multiply and subtract bset=aset; bset.emax=DEC_MAX_MATH*2; // use double bounds for the bset.emin=-DEC_MAX_MATH*2; // adjustment calculation // [see decExpOp call below] // for each iteration double the number of digits to calculate, // up to a maximum of p pp=9; // initial precision // [initially 9 as then the sequence starts 7+2, 16+2, and // 34+2, which is ideal for standard-sized numbers] aset.digits=pp; // working context bset.digits=pp+rhs->digits; // wider context for (;;) { // iterate #if DECCHECK iterations++; if (iterations>24) break; // consider 9 * 2**24 #endif // calculate the adjustment (exp(-a)*x-1) into b. This is a // catastrophic subtraction but it really is the difference // from 1 that is of interest. // Use the internal entry point to Exp as it allows the double // range for calculating exp(-a) when a is the tiniest subnormal. a->bits^=DECNEG; // make -a decExpOp(b, a, &bset, &ignore); // b=exp(-a) a->bits^=DECNEG; // restore sign of a // now multiply by rhs and subtract 1, at the wider precision decMultiplyOp(b, b, rhs, &bset, &ignore); // b=b*rhs decAddOp(b, b, &numone, &bset, DECNEG, &ignore); // b=b-1 // the iteration ends when the adjustment cannot affect the // result by >=0.5 ulp (at the requested digits), which // is when its value is smaller than the accumulator by // set->digits+1 digits (or it is zero) -- this is a looser // requirement than for Exp because all that happens to the // accumulator after this is the final rounding (but note that // there must also be full precision in a, or a=0). if (decNumberIsZero(b) || (a->digits+a->exponent)>=(b->digits+b->exponent+set->digits+1)) { if (a->digits==p) break; if (decNumberIsZero(a)) { decCompareOp(&cmp, rhs, &numone, &aset, COMPARE, &ignore); // rhs=1 ? if (cmp.lsu[0]==0) a->exponent=0; // yes, exact 0 else *status|=(DEC_Inexact | DEC_Rounded); // no, inexact break; } // force padding if adjustment has gone to 0 before full length if (decNumberIsZero(b)) b->exponent=a->exponent-p; } // not done yet ... decAddOp(a, a, b, &aset, 0, &ignore); // a=a+b for next estimate if (pp==p) continue; // precision is at maximum // lengthen the next calculation pp=pp*2; // double precision if (pp>p) pp=p; // clamp to maximum aset.digits=pp; // working context bset.digits=pp+rhs->digits; // wider context } // Newton's iteration #if DECCHECK // just a sanity check; remove the test to show always if (iterations>24) printf("Ln iterations=%d, status=%08x, p=%d, d=%d\n", iterations, *status, p, rhs->digits); #endif // Copy and round the result to res residue=1; // indicate dirt to right if (ISZERO(a)) residue=0; // .. unless underflowed to 0 aset.digits=set->digits; // [use default rounding] decCopyFit(res, a, &aset, &residue, status); // copy & shorten decFinish(res, set, &residue, status); // cleanup/set flags } while(0); // end protected if (allocbufa!=NULL) free(allocbufa); // drop any storage used if (allocbufb!=NULL) free(allocbufb); // .. // [status is handled by caller] return res; } // decLnOp /* ------------------------------------------------------------------ */ /* decQuantizeOp -- force exponent to requested value */ /* */ /* This computes C = op(A, B), where op adjusts the coefficient */ /* of C (by rounding or shifting) such that the exponent (-scale) */ /* of C has the value B or matches the exponent of B. */ /* The numerical value of C will equal A, except for the effects of */ /* any rounding that occurred. */ /* */ /* res is C, the result. C may be A or B */ /* lhs is A, the number to adjust */ /* rhs is B, the requested exponent */ /* set is the context */ /* quant is 1 for quantize or 0 for rescale */ /* status is the status accumulator (this can be called without */ /* risk of control loss) */ /* */ /* C must have space for set->digits digits. */ /* */ /* Unless there is an error or the result is infinite, the exponent */ /* after the operation is guaranteed to be that requested. */ /* ------------------------------------------------------------------ */ static decNumber * decQuantizeOp(decNumber *res, const decNumber *lhs, const decNumber *rhs, decContext *set, Flag quant, uInt *status) { #if DECSUBSET decNumber *alloclhs=NULL; // non-NULL if rounded lhs allocated decNumber *allocrhs=NULL; // .., rhs #endif const decNumber *inrhs=rhs; // save original rhs Int reqdigits=set->digits; // requested DIGITS Int reqexp; // requested exponent [-scale] Int residue=0; // rounding residue Int etiny=set->emin-(reqdigits-1); #if DECCHECK if (decCheckOperands(res, lhs, rhs, set)) return res; #endif do { // protect allocated storage #if DECSUBSET if (!set->extended) { // reduce operands and set lostDigits status, as needed if (lhs->digits>reqdigits) { alloclhs=decRoundOperand(lhs, set, status); if (alloclhs==NULL) break; lhs=alloclhs; } if (rhs->digits>reqdigits) { // [this only checks lostDigits] allocrhs=decRoundOperand(rhs, set, status); if (allocrhs==NULL) break; rhs=allocrhs; } } #endif // [following code does not require input rounding] // Handle special values if (SPECIALARGS) { // NaNs get usual processing if (SPECIALARGS & (DECSNAN | DECNAN)) decNaNs(res, lhs, rhs, status); // one infinity but not both is bad else if ((lhs->bits ^ rhs->bits) & DECINF) *status|=DEC_Invalid_operation; // both infinity: return lhs else decNumberCopy(res, lhs); // [nop if in place] break; } // set requested exponent if (quant) reqexp=inrhs->exponent; // quantize -- match exponents else { // rescale -- use value of rhs // Original rhs must be an integer that fits and is in range, // which could be from -1999999997 to +999999999, thanks to // subnormals reqexp=decGetInt(inrhs); // [cannot fail] } #if DECSUBSET if (!set->extended) etiny=set->emin; // no subnormals #endif if (reqexp==BADINT // bad (rescale only) or .. || reqexp==BIGODD || reqexp==BIGEVEN // very big (ditto) or .. || (reqexpset->emax)) { // > emax *status|=DEC_Invalid_operation; break;} // the RHS has been processed, so it can be overwritten now if necessary if (ISZERO(lhs)) { // zero coefficient unchanged decNumberCopy(res, lhs); // [nop if in place] res->exponent=reqexp; // .. just set exponent #if DECSUBSET if (!set->extended) res->bits=0; // subset specification; no -0 #endif } else { // non-zero lhs Int adjust=reqexp-lhs->exponent; // digit adjustment needed // if adjusted coefficient will definitely not fit, give up now if ((lhs->digits-adjust)>reqdigits) { *status|=DEC_Invalid_operation; break; } if (adjust>0) { // increasing exponent // this will decrease the length of the coefficient by adjust // digits, and must round as it does so decContext workset; // work workset=*set; // clone rounding, etc. workset.digits=lhs->digits-adjust; // set requested length // [note that the latter can be <1, here] decCopyFit(res, lhs, &workset, &residue, status); // fit to result decApplyRound(res, &workset, residue, status); // .. and round residue=0; // [used] // If just rounded a 999s case, exponent will be off by one; // adjust back (after checking space), if so. if (res->exponent>reqexp) { // re-check needed, e.g., for quantize(0.9999, 0.001) under // set->digits==3 if (res->digits==reqdigits) { // cannot shift by 1 *status&=~(DEC_Inexact | DEC_Rounded); // [clean these] *status|=DEC_Invalid_operation; break; } res->digits=decShiftToMost(res->lsu, res->digits, 1); // shift res->exponent--; // (re)adjust the exponent. } #if DECSUBSET if (ISZERO(res) && !set->extended) res->bits=0; // subset; no -0 #endif } // increase else /* adjust<=0 */ { // decreasing or = exponent // this will increase the length of the coefficient by -adjust // digits, by adding zero or more trailing zeros; this is // already checked for fit, above decNumberCopy(res, lhs); // [it will fit] // if padding needed (adjust<0), add it now... if (adjust<0) { res->digits=decShiftToMost(res->lsu, res->digits, -adjust); res->exponent+=adjust; // adjust the exponent } } // decrease } // non-zero // Check for overflow [do not use Finalize in this case, as an // overflow here is a "don't fit" situation] if (res->exponent>set->emax-res->digits+1) { // too big *status|=DEC_Invalid_operation; break; } else { decFinalize(res, set, &residue, status); // set subnormal flags *status&=~DEC_Underflow; // suppress Underflow [754r] } } while(0); // end protected #if DECSUBSET if (allocrhs!=NULL) free(allocrhs); // drop any storage used if (alloclhs!=NULL) free(alloclhs); // .. #endif return res; } // decQuantizeOp /* ------------------------------------------------------------------ */ /* decCompareOp -- compare, min, or max two Numbers */ /* */ /* This computes C = A ? B and carries out one of four operations: */ /* COMPARE -- returns the signum (as a number) giving the */ /* result of a comparison unless one or both */ /* operands is a NaN (in which case a NaN results) */ /* COMPMAX -- returns the larger of the operands, using the */ /* 754r maxnum operation */ /* COMPMIN -- the 754r minnum operation */ /* COMTOTAL -- returns the signum (as a number) giving the */ /* result of a comparison using 754r total ordering */ /* */ /* res is C, the result. C may be A and/or B (e.g., X=X?X) */ /* lhs is A */ /* rhs is B */ /* set is the context */ /* op is the operation flag */ /* status is the usual accumulator */ /* */ /* C must have space for one digit for COMPARE or set->digits for */ /* COMPMAX and COMPMIN. */ /* ------------------------------------------------------------------ */ /* The emphasis here is on speed for common cases, and avoiding */ /* coefficient comparison if possible. */ /* ------------------------------------------------------------------ */ decNumber * decCompareOp(decNumber *res, const decNumber *lhs, const decNumber *rhs, decContext *set, Flag op, uInt *status) { #if DECSUBSET decNumber *alloclhs=NULL; // non-NULL if rounded lhs allocated decNumber *allocrhs=NULL; // .., rhs #endif Int result=0; // default result value uByte merged; // work #if DECCHECK if (decCheckOperands(res, lhs, rhs, set)) return res; #endif do { // protect allocated storage #if DECSUBSET if (!set->extended) { // reduce operands and set lostDigits status, as needed if (lhs->digits>set->digits) { alloclhs=decRoundOperand(lhs, set, status); if (alloclhs==NULL) {result=BADINT; break;} lhs=alloclhs; } if (rhs->digits>set->digits) { allocrhs=decRoundOperand(rhs, set, status); if (allocrhs==NULL) {result=BADINT; break;} rhs=allocrhs; } } #endif // [following code does not require input rounding] // If total ordering then handle differing signs 'up front' if (op == COMPTOTAL) { // total ordering if (decNumberIsNegative(lhs) & !decNumberIsNegative(rhs)) { result=-1; break; } if (!decNumberIsNegative(lhs) & decNumberIsNegative(rhs)) { result=+1; break; } } // handle NaNs specially; let infinities drop through // This assumes sNaN (even just one) leads to NaN. merged=(lhs->bits | rhs->bits) & (DECSNAN | DECNAN); if (merged) { // a NaN bit set if (op == COMPARE); // result will be NaN else if (op == COMPTOTAL) { // total ordering, always finite // signs are known to be the same; compute the ordering here // as if the signs are both positive, then invert for negatives if (!decNumberIsNaN(lhs)) result=-1; else if (!decNumberIsNaN(rhs)) result=+1; // here if both NaNs else if (decNumberIsSNaN(lhs) && decNumberIsQNaN(rhs)) result=-1; else if (decNumberIsQNaN(lhs) && decNumberIsSNaN(rhs)) result=+1; else { // both NaN or both sNaN // now it just depends on the payload result=decUnitCompare(lhs->lsu, D2U(lhs->digits), rhs->lsu, D2U(rhs->digits), 0); // [Error not possible, as these are 'aligned'] } // both same NaNs if (decNumberIsNegative(lhs)) result=-result; break; } // total order else if (merged & DECSNAN); // sNaN -> qNaN else { // here if MIN or MAX and one or two quiet NaNs // min or max -- 754r rules ignore single NaN if (!decNumberIsNaN(lhs) || !decNumberIsNaN(rhs)) { // just one NaN; force choice to be the non-NaN operand op=COMPMAX; if (lhs->bits & DECNAN) result=-1; // pick rhs else result=+1; // pick lhs break; } } // max or min op = COMPNAN; // use special path decNaNs(res, lhs, rhs, status); break; } result=decCompare(lhs, rhs, 0); // have numbers } while(0); // end protected if (result==BADINT) *status|=DEC_Insufficient_storage; // rare else { if (op == COMPARE || op == COMPTOTAL) { // returning signum if (op == COMPTOTAL && result==0) { // operands are numerically equal or same NaN (and same sign, // tested first); if identical, leave result 0 if (lhs->exponent!=rhs->exponent) { if (lhs->exponentexponent) result=-1; else result=+1; if (decNumberIsNegative(lhs)) result=-result; } // lexp!=rexp } // total-order by exponent decNumberZero(res); // [always a valid result] if (result!=0) { // must be -1 or +1 *res->lsu=1; if (result<0) res->bits=DECNEG; } } else if (op == COMPNAN); // special, drop through else { // MAX or MIN, non-NaN result Int residue=0; // rounding accumulator // choose the operand for the result const decNumber *choice; if (result==0) { // operands are numerically equal // choose according to sign then exponent (see 754r) uByte slhs=(lhs->bits & DECNEG); uByte srhs=(rhs->bits & DECNEG); #if DECSUBSET if (!set->extended) { // subset: force left-hand op=COMPMAX; result=+1; } else #endif if (slhs!=srhs) { // signs differ if (slhs) result=-1; // rhs is max else result=+1; // lhs is max } else if (slhs && srhs) { // both negative if (lhs->exponentexponent) result=+1; else result=-1; // [if equal, use lhs, technically identical] } else { // both positive if (lhs->exponent>rhs->exponent) result=+1; else result=-1; // [ditto] } } // numerically equal // here result will be non-0 if (op == COMPMIN) result=-result;// reverse if looking for MIN choice=(result>0 ? lhs : rhs); // choose // copy chosen to result, rounding if need be decCopyFit(res, choice, set, &residue, status); decFinish(res, set, &residue, status); } } #if DECSUBSET if (allocrhs!=NULL) free(allocrhs); // free any storage used if (alloclhs!=NULL) free(alloclhs); // .. #endif return res; } // decCompareOp /* ------------------------------------------------------------------ */ /* decCompare -- compare two decNumbers by numerical value */ /* */ /* This routine compares A ? B without altering them. */ /* */ /* Arg1 is A, a decNumber which is not a NaN */ /* Arg2 is B, a decNumber which is not a NaN */ /* Arg3 is 1 for a sign-independent compare, 0 otherwise */ /* */ /* returns -1, 0, or 1 for AB, or BADINT if failure */ /* (the only possible failure is an allocation error) */ /* ------------------------------------------------------------------ */ static Int decCompare(const decNumber *lhs, const decNumber *rhs, Flag abs) { Int result; // result value Int sigr; // rhs signum Int compare; // work result=1; // assume signum(lhs) if (ISZERO(lhs)) result=0; if (abs) { if (!ISZERO(rhs)) result=1; // not both 0 } else { // signs matter if (result && decNumberIsNegative(lhs)) result=-1; sigr=1; // compute signum(rhs) if (ISZERO(rhs)) sigr=0; else if (decNumberIsNegative(rhs)) sigr=-1; if (result > sigr) return +1; // L > R, return 1 if (result < sigr) return -1; // R < L, return -1 } // signums are the same if (result==0) return 0; // both 0 // Both non-zero if ((lhs->bits | rhs->bits) & DECINF) { // one or more infinities if (decNumberIsInfinite(rhs)) { if (decNumberIsInfinite(lhs)) result=0;// both infinite else result=-result; // only rhs infinite } return result; } // must compare the coefficients, allowing for exponents if (lhs->exponent>rhs->exponent) { // LHS exponent larger // swap sides, and sign const decNumber *temp=lhs; lhs=rhs; rhs=temp; result=-result; } compare=decUnitCompare(lhs->lsu, D2U(lhs->digits), rhs->lsu, D2U(rhs->digits), rhs->exponent-lhs->exponent); if (compare!=BADINT) compare*=result; // comparison succeeded return compare; } // decCompare /* ------------------------------------------------------------------ */ /* decUnitCompare -- compare two >=0 integers in Unit arrays */ /* */ /* This routine compares A ? B*10**E where A and B are unit arrays */ /* A is a plain integer */ /* B has an exponent of E (which must be non-negative) */ /* */ /* Arg1 is A first Unit (lsu) */ /* Arg2 is A length in Units */ /* Arg3 is B first Unit (lsu) */ /* Arg4 is B length in Units */ /* Arg5 is E (0 if the units are aligned) */ /* */ /* returns -1, 0, or 1 for AB, or BADINT if failure */ /* (the only possible failure is an allocation error, which can */ /* only occur if E!=0) */ /* ------------------------------------------------------------------ */ static Int decUnitCompare(const Unit *a, Int alength, const Unit *b, Int blength, Int exp) { Unit *acc; // accumulator for result Unit accbuff[SD2U(DECBUFFER+1)];// local buffer Unit *allocacc=NULL; // -> allocated acc buffer, iff allocated Int accunits, need; // units in use or needed for acc const Unit *l, *r, *u; // work Int expunits, exprem, result; // .. if (exp==0) { // aligned; fastpath if (alength>blength) return 1; if (alength=a; l--, r--) { if (*l>*r) return 1; if (*l<*r) return -1; } return 0; // all units match } // aligned // Unaligned. If one is >1 unit longer than the other, padded // approximately, then can return easily if (alength>blength+(Int)D2U(exp)) return 1; if (alength+1sizeof(accbuff)) { allocacc=(Unit *)malloc(need*sizeof(Unit)); if (allocacc==NULL) return BADINT; // hopeless -- abandon acc=allocacc; } // Calculate units and remainder from exponent. expunits=exp/DECDPUN; exprem=exp%DECDPUN; // subtract [A+B*(-m)] accunits=decUnitAddSub(a, alength, b, blength, expunits, acc, -(Int)powers[exprem]); // [UnitAddSub result may have leading zeros, even on zero] if (accunits<0) result=-1; // negative result else { // non-negative result // check units of the result before freeing any storage for (u=acc; u=0 integers in Unit arrays */ /* */ /* This routine performs the calculation: */ /* */ /* C=A+(B*M) */ /* */ /* Where M is in the range -DECDPUNMAX through +DECDPUNMAX. */ /* */ /* A may be shorter or longer than B. */ /* */ /* Leading zeros are not removed after a calculation. The result is */ /* either the same length as the longer of A and B (adding any */ /* shift), or one Unit longer than that (if a Unit carry occurred). */ /* */ /* A and B content are not altered unless C is also A or B. */ /* C may be the same array as A or B, but only if no zero padding is */ /* requested (that is, C may be B only if bshift==0). */ /* C is filled from the lsu; only those units necessary to complete */ /* the calculation are referenced. */ /* */ /* Arg1 is A first Unit (lsu) */ /* Arg2 is A length in Units */ /* Arg3 is B first Unit (lsu) */ /* Arg4 is B length in Units */ /* Arg5 is B shift in Units (>=0; pads with 0 units if positive) */ /* Arg6 is C first Unit (lsu) */ /* Arg7 is M, the multiplier */ /* */ /* returns the count of Units written to C, which will be non-zero */ /* and negated if the result is negative. That is, the sign of the */ /* returned Int is the sign of the result (positive for zero) and */ /* the absolute value of the Int is the count of Units. */ /* */ /* It is the caller's responsibility to make sure that C size is */ /* safe, allowing space if necessary for a one-Unit carry. */ /* */ /* This routine is severely performance-critical; *any* change here */ /* must be measured (timed) to assure no performance degradation. */ /* In particular, trickery here tends to be counter-productive, as */ /* increased complexity of code hurts register optimizations on */ /* register-poor architectures. Avoiding divisions is nearly */ /* always a Good Idea, however. */ /* */ /* Special thanks to Rick McGuire (IBM Cambridge, MA) and Dave Clark */ /* (IBM Warwick, UK) for some of the ideas used in this routine. */ /* ------------------------------------------------------------------ */ static Int decUnitAddSub(const Unit *a, Int alength, const Unit *b, Int blength, Int bshift, Unit *c, Int m) { const Unit *alsu=a; // A lsu [need to remember it] Unit *clsu=c; // C ditto Unit *minC; // low water mark for C Unit *maxC; // high water mark for C eInt carry=0; // carry integer (could be Long) Int add; // work #if DECDPUN<=4 // myriadal, millenary, etc. Int est; // estimated quotient #endif #if DECTRACE if (alength<1 || blength<1) printf("decUnitAddSub: alen blen m %d %d [%d]\n", alength, blength, m); #endif maxC=c+alength; // A is usually the longer minC=c+blength; // .. and B the shorter if (bshift!=0) { // B is shifted; low As copy across minC+=bshift; // if in place [common], skip copy unless there's a gap [rare] if (a==c && bshift<=alength) { c+=bshift; a+=bshift; } else for (; cmaxC) { // swap Unit *hold=minC; minC=maxC; maxC=hold; } // For speed, do the addition as two loops; the first where both A // and B contribute, and the second (if necessary) where only one or // other of the numbers contribute. // Carry handling is the same (i.e., duplicated) in each case. for (; c=0) { est=(((ueInt)carry>>11)*53687)>>18; *c=(Unit)(carry-est*(DECDPUNMAX+1)); // remainder carry=est; // likely quotient [89%] if (*c>11)*53687)>>18; *c=(Unit)(carry-est*(DECDPUNMAX+1)); carry=est-(DECDPUNMAX+1); // correctly negative if (*c=0) { est=(((ueInt)carry>>3)*16777)>>21; *c=(Unit)(carry-est*(DECDPUNMAX+1)); // remainder carry=est; // likely quotient [99%] if (*c>3)*16777)>>21; *c=(Unit)(carry-est*(DECDPUNMAX+1)); carry=est-(DECDPUNMAX+1); // correctly negative if (*c=0) { est=QUOT10(carry, DECDPUN); *c=(Unit)(carry-est*(DECDPUNMAX+1)); // remainder carry=est; // quotient continue; } // negative case carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); // make positive est=QUOT10(carry, DECDPUN); *c=(Unit)(carry-est*(DECDPUNMAX+1)); carry=est-(DECDPUNMAX+1); // correctly negative #else // remainder operator is undefined if negative, so must test if ((ueInt)carry<(DECDPUNMAX+1)*2) { // fastpath carry +1 *c=(Unit)(carry-(DECDPUNMAX+1)); // [helps additions] carry=1; continue; } if (carry>=0) { *c=(Unit)(carry%(DECDPUNMAX+1)); carry=carry/(DECDPUNMAX+1); continue; } // negative case carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); // make positive *c=(Unit)(carry%(DECDPUNMAX+1)); carry=carry/(DECDPUNMAX+1)-(DECDPUNMAX+1); #endif } // c // now may have one or other to complete // [pretest to avoid loop setup/shutdown] if (cDECDPUNMAX #if DECDPUN==4 // use divide-by-multiply if (carry>=0) { est=(((ueInt)carry>>11)*53687)>>18; *c=(Unit)(carry-est*(DECDPUNMAX+1)); // remainder carry=est; // likely quotient [79.7%] if (*c>11)*53687)>>18; *c=(Unit)(carry-est*(DECDPUNMAX+1)); carry=est-(DECDPUNMAX+1); // correctly negative if (*c=0) { est=(((ueInt)carry>>3)*16777)>>21; *c=(Unit)(carry-est*(DECDPUNMAX+1)); // remainder carry=est; // likely quotient [99%] if (*c>3)*16777)>>21; *c=(Unit)(carry-est*(DECDPUNMAX+1)); carry=est-(DECDPUNMAX+1); // correctly negative if (*c=0) { est=QUOT10(carry, DECDPUN); *c=(Unit)(carry-est*(DECDPUNMAX+1)); // remainder carry=est; // quotient continue; } // negative case carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); // make positive est=QUOT10(carry, DECDPUN); *c=(Unit)(carry-est*(DECDPUNMAX+1)); carry=est-(DECDPUNMAX+1); // correctly negative #else if ((ueInt)carry<(DECDPUNMAX+1)*2){ // fastpath carry 1 *c=(Unit)(carry-(DECDPUNMAX+1)); carry=1; continue; } // remainder operator is undefined if negative, so must test if (carry>=0) { *c=(Unit)(carry%(DECDPUNMAX+1)); carry=carry/(DECDPUNMAX+1); continue; } // negative case carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); // make positive *c=(Unit)(carry%(DECDPUNMAX+1)); carry=carry/(DECDPUNMAX+1)-(DECDPUNMAX+1); #endif } // c // OK, all A and B processed; might still have carry or borrow // return number of Units in the result, negated if a borrow if (carry==0) return c-clsu; // no carry, so no more to do if (carry>0) { // positive carry *c=(Unit)carry; // place as new unit c++; // .. return c-clsu; } // -ve carry: it's a borrow; complement needed add=1; // temporary carry... for (c=clsu; c current Unit #if DECCHECK if (decCheckOperands(dn, DECUNUSED, DECUNUSED, DECUNUSED)) return dn; #endif *dropped=0; // assume no zeros dropped if ((dn->bits & DECSPECIAL) // fast exit if special .. || (*dn->lsu & 0x01)) return dn; // .. or odd if (ISZERO(dn)) { // .. or 0 dn->exponent=0; // (sign is preserved) return dn; } // have a finite number which is even exp=dn->exponent; cut=1; // digit (1-DECDPUN) in Unit up=dn->lsu; // -> current Unit for (d=0; ddigits-1; d++) { // [don't strip the final digit] // slice by powers #if DECDPUN<=4 uInt quot=QUOT10(*up, cut); if ((*up-quot*powers[cut])!=0) break; // found non-0 digit #else if (*up%powers[cut]!=0) break; // found non-0 digit #endif // have a trailing 0 if (!all) { // trimming // [if exp>0 then all trailing 0s are significant for trim] if (exp<=0) { // if digit might be significant if (exp==0) break; // then quit exp++; // next digit might be significant } } cut++; // next power if (cut>DECDPUN) { // need new Unit up++; cut=1; } } // d if (d==0) return dn; // none dropped // effect the drop decShiftToLeast(dn->lsu, D2U(dn->digits), d); dn->exponent+=d; // maintain numerical value dn->digits-=d; // new length *dropped=d; // report the count return dn; } // decTrim /* ------------------------------------------------------------------ */ /* decShiftToMost -- shift digits in array towards most significant */ /* */ /* uar is the array */ /* digits is the count of digits in use in the array */ /* shift is the number of zeros to pad with (least significant); */ /* it must be zero or positive */ /* */ /* returns the new length of the integer in the array, in digits */ /* */ /* No overflow is permitted (that is, the uar array must be known to */ /* be large enough to hold the result, after shifting). */ /* ------------------------------------------------------------------ */ static Int decShiftToMost(Unit *uar, Int digits, Int shift) { Unit *target, *source, *first; // work Int cut; // odd 0's to add uInt next; // work if (shift==0) return digits; // [fastpath] nothing to do if ((digits+shift)<=DECDPUN) { // [fastpath] single-unit case *uar=(Unit)(*uar*powers[shift]); return digits+shift; } next=0; // all paths source=uar+D2U(digits)-1; // where msu comes from target=source+D2U(shift); // where upper part of first cut goes cut=DECDPUN-MSUDIGITS(shift); // where to slice if (cut==0) { // unit-boundary case for (; source>=uar; source--, target--) *target=*source; } else { first=uar+D2U(digits+shift)-1; // where msu of source will end up for (; source>=uar; source--, target--) { // split the source Unit and accumulate remainder for next #if DECDPUN<=4 uInt quot=QUOT10(*source, cut); uInt rem=*source-quot*powers[cut]; next+=quot; #else uInt rem=*source%powers[cut]; next+=*source/powers[cut]; #endif if (target<=first) *target=(Unit)next; // write to target iff valid next=rem*powers[DECDPUN-cut]; // save remainder for next Unit } } // shift-move // propagate any partial unit to one below and clear the rest for (; target>=uar; target--) { *target=(Unit)next; next=0; } return digits+shift; } // decShiftToMost /* ------------------------------------------------------------------ */ /* decShiftToLeast -- shift digits in array towards least significant */ /* */ /* uar is the array */ /* units is length of the array, in units */ /* shift is the number of digits to remove from the lsu end; it */ /* must be zero or positive and less than units*DECDPUN. */ /* */ /* returns the new length of the integer in the array, in units */ /* */ /* Removed digits are discarded (lost). Units not required to hold */ /* the final result are unchanged. */ /* ------------------------------------------------------------------ */ static Int decShiftToLeast(Unit *uar, Int units, Int shift) { Unit *target, *up; // work Int cut, count; // work Int quot, rem; // for division if (shift==0) return units; // [fastpath] nothing to do target=uar; // both paths cut=MSUDIGITS(shift); if (cut==DECDPUN) { // unit-boundary case; easy up=uar+D2U(shift); for (; updigits is > set->digits) */ /* set is the relevant context */ /* status is the status accumulator */ /* */ /* returns an allocated decNumber with the rounded result. */ /* */ /* lostDigits and other status may be set by this. */ /* */ /* Since the input is an operand, it must not be modified. */ /* Instead, return an allocated decNumber, rounded as required. */ /* It is the caller's responsibility to free the allocated storage. */ /* */ /* If no storage is available then the result cannot be used, so NULL */ /* is returned. */ /* ------------------------------------------------------------------ */ static decNumber *decRoundOperand(const decNumber *dn, decContext *set, uInt *status) { decNumber *res; // result structure uInt newstatus=0; // status from round Int residue=0; // rounding accumulator // Allocate storage for the returned decNumber, big enough for the // length specified by the context res=(decNumber *)malloc(sizeof(decNumber) +(D2U(set->digits)-1)*sizeof(Unit)); if (res==NULL) { *status|=DEC_Insufficient_storage; return NULL; } decCopyFit(res, dn, set, &residue, &newstatus); decApplyRound(res, set, residue, &newstatus); // If that set Inexact then "lost digits" is raised... if (newstatus & DEC_Inexact) newstatus|=DEC_Lost_digits; *status|=newstatus; return res; } // decRoundOperand #endif /* ------------------------------------------------------------------ */ /* decCopyFit -- copy a number, truncating the coefficient if needed */ /* */ /* dest is the target decNumber */ /* src is the source decNumber */ /* set is the context [used for length (digits) and rounding mode] */ /* residue is the residue accumulator */ /* status contains the current status to be updated */ /* */ /* (dest==src is allowed and will be a no-op if fits) */ /* All fields are updated as required. */ /* ------------------------------------------------------------------ */ static void decCopyFit(decNumber *dest, const decNumber *src, decContext *set, Int *residue, uInt *status) { dest->bits=src->bits; dest->exponent=src->exponent; decSetCoeff(dest, set, src->lsu, src->digits, residue, status); } // decCopyFit /* ------------------------------------------------------------------ */ /* decSetCoeff -- set the coefficient of a number */ /* */ /* dn is the number whose coefficient array is to be set. */ /* It must have space for set->digits digits */ /* set is the context [for size] */ /* lsu -> lsu of the source coefficient [may be dn->lsu] */ /* len is digits in the source coefficient [may be dn->digits] */ /* residue is the residue accumulator. This has values as in */ /* decApplyRound, and will be unchanged unless the */ /* target size is less than len. In this case, the */ /* coefficient is truncated and the residue is updated to */ /* reflect the previous residue and the dropped digits. */ /* status is the status accumulator, as usual */ /* */ /* The coefficient may already be in the number, or it can be an */ /* external intermediate array. If it is in the number, lsu must == */ /* dn->lsu and len must == dn->digits. */ /* */ /* Note that the coefficient length (len) may be < set->digits, and */ /* in this case this merely copies the coefficient (or is a no-op */ /* if dn->lsu==lsu). */ /* */ /* Note also that (only internally, from decQuantizeOp and */ /* decSetSubnormal) the value of set->digits may be less than one, */ /* indicating a round to left. This routine handles that case */ /* correctly; caller ensures space. */ /* */ /* dn->digits, dn->lsu (and as required), and dn->exponent are */ /* updated as necessary. dn->bits (sign) is unchanged. */ /* */ /* DEC_Rounded status is set if any digits are discarded. */ /* DEC_Inexact status is set if any non-zero digits are discarded, or */ /* incoming residue was non-0 (implies rounded) */ /* ------------------------------------------------------------------ */ // mapping array: maps 0-9 to canonical residues, so that a residue // can be adjusted in the range [-1, +1] and achieve correct rounding // 0 1 2 3 4 5 6 7 8 9 static const uByte resmap[10]={0, 3, 3, 3, 3, 5, 7, 7, 7, 7}; static void decSetCoeff(decNumber *dn, decContext *set, const Unit *lsu, Int len, Int *residue, uInt *status) { Int discard; // number of digits to discard uInt cut; // cut point in Unit const Unit *up; // work Unit *target; // .. Int count; // .. #if DECDPUN<=4 uInt temp; // .. #endif discard=len-set->digits; // digits to discard if (discard<=0) { // no digits are being discarded if (dn->lsu!=lsu) { // copy needed // copy the coefficient array to the result number; no shift needed count=len; // avoids D2U up=lsu; for (target=dn->lsu; count>0; target++, up++, count-=DECDPUN) *target=*up; dn->digits=len; // set the new length } // dn->exponent and residue are unchanged, record any inexactitude if (*residue!=0) *status|=(DEC_Inexact | DEC_Rounded); return; } // some digits must be discarded ... dn->exponent+=discard; // maintain numerical value *status|=DEC_Rounded; // accumulate Rounded status if (*residue>1) *residue=1; // previous residue now to right, so reduce if (discard>len) { // everything, +1, is being discarded // guard digit is 0 // residue is all the number [NB could be all 0s] if (*residue<=0) { // not already positive count=len; // avoids D2U for (up=lsu; count>0; up++, count-=DECDPUN) if (*up!=0) { // found non-0 *residue=1; break; // no need to check any others } } if (*residue!=0) *status|=DEC_Inexact; // record inexactitude *dn->lsu=0; // coefficient will now be 0 dn->digits=1; // .. return; } // total discard // partial discard [most common case] // here, at least the first (most significant) discarded digit exists // spin up the number, noting residue during the spin, until get to // the Unit with the first discarded digit. When reach it, extract // it and remember its position count=0; for (up=lsu;; up++) { count+=DECDPUN; if (count>=discard) break; // full ones all checked if (*up!=0) *residue=1; } // up // here up -> Unit with first discarded digit cut=discard-(count-DECDPUN)-1; if (cut==DECDPUN-1) { // unit-boundary case (fast) Unit half=(Unit)powers[DECDPUN]>>1; // set residue directly if (*up>=half) { if (*up>half) *residue=7; else *residue+=5; // add sticky bit } else { // digits<=0) { // special for Quantize/Subnormal :-( *dn->lsu=0; // .. result is 0 dn->digits=1; // .. } else { // shift to least count=set->digits; // now digits to end up with dn->digits=count; // set the new length up++; // move to next // on unit boundary, so shift-down copy loop is simple for (target=dn->lsu; count>0; target++, up++, count-=DECDPUN) *target=*up; } } // unit-boundary case else { // discard digit is in low digit(s), and not top digit uInt discard1; // first discarded digit uInt quot, rem; // for divisions if (cut==0) quot=*up; // is at bottom of unit else /* cut>0 */ { // it's not at bottom of unit #if DECDPUN<=4 quot=QUOT10(*up, cut); rem=*up-quot*powers[cut]; #else rem=*up%powers[cut]; quot=*up/powers[cut]; #endif if (rem!=0) *residue=1; } // discard digit is now at bottom of quot #if DECDPUN<=4 temp=(quot*6554)>>16; // fast /10 // Vowels algorithm here not a win (9 instructions) discard1=quot-X10(temp); quot=temp; #else discard1=quot%10; quot=quot/10; #endif // here, discard1 is the guard digit, and residue is everything // else [use mapping array to accumulate residue safely] *residue+=resmap[discard1]; cut++; // update cut // here: up -> Unit of the array with bottom digit // cut is the division point for each Unit // quot holds the uncut high-order digits for the current unit if (set->digits<=0) { // special for Quantize/Subnormal :-( *dn->lsu=0; // .. result is 0 dn->digits=1; // .. } else { // shift to least needed count=set->digits; // now digits to end up with dn->digits=count; // set the new length // shift-copy the coefficient array to the result number for (target=dn->lsu; ; target++) { *target=(Unit)quot; count-=(DECDPUN-cut); if (count<=0) break; up++; quot=*up; #if DECDPUN<=4 quot=QUOT10(quot, cut); rem=*up-quot*powers[cut]; #else rem=quot%powers[cut]; quot=quot/powers[cut]; #endif *target=(Unit)(*target+rem*powers[DECDPUN-cut]); count-=cut; if (count<=0) break; } // shift-copy loop } // shift to least } // not unit boundary if (*residue!=0) *status|=DEC_Inexact; // record inexactitude return; } // decSetCoeff /* ------------------------------------------------------------------ */ /* decApplyRound -- apply pending rounding to a number */ /* */ /* dn is the number, with space for set->digits digits */ /* set is the context [for size and rounding mode] */ /* residue indicates pending rounding, being any accumulated */ /* guard and sticky information. It may be: */ /* 6-9: rounding digit is >5 */ /* 5: rounding digit is exactly half-way */ /* 1-4: rounding digit is <5 and >0 */ /* 0: the coefficient is exact */ /* -1: as 1, but the hidden digits are subtractive, that */ /* is, of the opposite sign to dn. In this case the */ /* coefficient must be non-0. */ /* status is the status accumulator, as usual */ /* */ /* This routine applies rounding while keeping the length of the */ /* coefficient constant. The exponent and status are unchanged */ /* except if: */ /* */ /* -- the coefficient was increased and is all nines (in which */ /* case Overflow could occur, and is handled directly here so */ /* the caller does not need to re-test for overflow) */ /* */ /* -- the coefficient was decreased and becomes all nines (in which */ /* case Underflow could occur, and is also handled directly). */ /* */ /* All fields in dn are updated as required. */ /* */ /* ------------------------------------------------------------------ */ static void decApplyRound(decNumber *dn, decContext *set, Int residue, uInt *status) { Int bump; // 1 if coefficient needs to be incremented // -1 if coefficient needs to be decremented if (residue==0) return; // nothing to apply bump=0; // assume a smooth ride // now decide whether, and how, to round, depending on mode switch (set->round) { case DEC_ROUND_DOWN: { // no change, except if negative residue if (residue<0) bump=-1; break;} // r-d case DEC_ROUND_HALF_DOWN: { if (residue>5) bump=1; break;} // r-h-d case DEC_ROUND_HALF_EVEN: { if (residue>5) bump=1; // >0.5 goes up else if (residue==5) { // exactly 0.5000... // 0.5 goes up iff [new] lsd is odd if (*dn->lsu & 0x01) bump=1; } break;} // r-h-e case DEC_ROUND_HALF_UP: { if (residue>=5) bump=1; break;} // r-h-u case DEC_ROUND_UP: { if (residue>0) bump=1; break;} // r-u case DEC_ROUND_CEILING: { // same as _UP for positive numbers, and as _DOWN for negatives // [negative residue cannot occur on 0] if (decNumberIsNegative(dn)) { if (residue<0) bump=-1; } else { if (residue>0) bump=1; } break;} // r-c case DEC_ROUND_FLOOR: { // same as _UP for negative numbers, and as _DOWN for positive // [negative residue cannot occur on 0] if (!decNumberIsNegative(dn)) { if (residue<0) bump=-1; } else { if (residue>0) bump=1; } break;} // r-f default: { // e.g., DEC_ROUND_MAX *status|=DEC_Invalid_context; #if DECTRACE printf("Unknown rounding mode: %d\n", set->round); #endif break;} } // switch // now bump the number, up or down, if need be if (bump==0) return; // no action required // Simply use decUnitAddSub unless bumping up and the number is // all nines. In this special case set to 100... explicitly // and adjust the exponent by one (as otherwise could overflow // the array) // Similarly handle all-nines result if bumping down. if (bump>0) { Unit *up; // work uInt count=dn->digits; // digits to be checked for (up=dn->lsu; ; up++) { if (count<=DECDPUN) { // this is the last Unit (the msu) if (*up!=powers[count]-1) break; // not still 9s // here if it, too, is all nines *up=(Unit)powers[count-1]; // here 999 -> 100 etc. for (up=up-1; up>=dn->lsu; up--) *up=0; // others all to 0 dn->exponent++; // and bump exponent // [which, very rarely, could cause Overflow...] if ((dn->exponent+dn->digits)>set->emax+1) { decSetOverflow(dn, set, status); } return; // done } // a full unit to check, with more to come if (*up!=DECDPUNMAX) break; // not still 9s count-=DECDPUN; } // up } // bump>0 else { // -1 // here checking for a pre-bump of 1000... (leading 1, all // other digits zero) Unit *up, *sup; // work uInt count=dn->digits; // digits to be checked for (up=dn->lsu; ; up++) { if (count<=DECDPUN) { // this is the last Unit (the msu) if (*up!=powers[count-1]) break; // not 100.. // here if have the 1000... case sup=up; // save msu pointer *up=(Unit)powers[count]-1; // here 100 in msu -> 999 // others all to all-nines, too for (up=up-1; up>=dn->lsu; up--) *up=(Unit)powers[DECDPUN]-1; dn->exponent--; // and bump exponent // iff the number was at the subnormal boundary (exponent=etiny) // then the exponent is now out of range, so it will in fact get // clamped to etiny and the final 9 dropped. // printf(">> emin=%d exp=%d sdig=%d\n", set->emin, // dn->exponent, set->digits); if (dn->exponent+1==set->emin-set->digits+1) { if (count==1 && dn->digits==1) *sup=0; // here 9 -> 0[.9] else { *sup=(Unit)powers[count-1]-1; // here 999.. in msu -> 99.. dn->digits--; } dn->exponent++; *status|=DEC_Underflow | DEC_Subnormal | DEC_Inexact | DEC_Rounded; } return; // done } // a full unit to check, with more to come if (*up!=0) break; // not still 0s count-=DECDPUN; } // up } // bump<0 // Actual bump needed. Do it. decUnitAddSub(dn->lsu, D2U(dn->digits), uarrone, 1, 0, dn->lsu, bump); } // decApplyRound #if DECSUBSET /* ------------------------------------------------------------------ */ /* decFinish -- finish processing a number */ /* */ /* dn is the number */ /* set is the context */ /* residue is the rounding accumulator (as in decApplyRound) */ /* status is the accumulator */ /* */ /* This finishes off the current number by: */ /* 1. If not extended: */ /* a. Converting a zero result to clean '0' */ /* b. Reducing positive exponents to 0, if would fit in digits */ /* 2. Checking for overflow and subnormals (always) */ /* Note this is just Finalize when no subset arithmetic. */ /* All fields are updated as required. */ /* ------------------------------------------------------------------ */ static void decFinish(decNumber *dn, decContext *set, Int *residue, uInt *status) { if (!set->extended) { if ISZERO(dn) { // value is zero dn->exponent=0; // clean exponent .. dn->bits=0; // .. and sign return; // no error possible } if (dn->exponent>=0) { // non-negative exponent // >0; reduce to integer if possible if (set->digits >= (dn->exponent+dn->digits)) { dn->digits=decShiftToMost(dn->lsu, dn->digits, dn->exponent); dn->exponent=0; } } } // !extended decFinalize(dn, set, residue, status); } // decFinish #endif /* ------------------------------------------------------------------ */ /* decFinalize -- final check, clamp, and round of a number */ /* */ /* dn is the number */ /* set is the context */ /* residue is the rounding accumulator (as in decApplyRound) */ /* status is the status accumulator */ /* */ /* This finishes off the current number by checking for subnormal */ /* results, applying any pending rounding, checking for overflow, */ /* and applying any clamping. */ /* Underflow and overflow conditions are raised as appropriate. */ /* All fields are updated as required. */ /* ------------------------------------------------------------------ */ static void decFinalize(decNumber *dn, decContext *set, Int *residue, uInt *status) { Int shift; // shift needed if clamping Int tinyexp=set->emin-dn->digits+1; // precalculate subnormal boundary // Must be careful, here, when checking the exponent as the // adjusted exponent could overflow 31 bits [because it may already // be up to twice the expected]. // First test for subnormal. This must be done before any final // round as the result could be rounded to Nmin or 0. if (dn->exponent<=tinyexp) { // prefilter decNumber nmin; // A very nasty case here is dn == Nmin and residue<0 if (dn->exponentemin; if (*residue<0 && decCompare(dn, &nmin, 1)==0) { // (signless compare) decApplyRound(dn, set, *residue, status); // might force down decSetSubnormal(dn, set, residue, status); return; } } // now apply any pending round (this could raise overflow). if (*residue!=0) decApplyRound(dn, set, *residue, status); // Check for overflow [redundant in the 'rare' case] or clamp if (dn->exponent<=set->emax-set->digits+1) return; // neither needed // here when might have an overflow or clamp to do if (dn->exponent>set->emax-dn->digits+1) { // too big decSetOverflow(dn, set, status); return; } // here when the result is normal but in clamp range if (!set->clamp) return; // here when need to apply the IEEE exponent clamp (fold-down) shift=dn->exponent-(set->emax-set->digits+1); // shift coefficient (if non-zero) if (!ISZERO(dn)) { dn->digits=decShiftToMost(dn->lsu, dn->digits, shift); } dn->exponent-=shift; // adjust the exponent to match *status|=DEC_Clamped; // and record the dirty deed return; } // decFinalize /* ------------------------------------------------------------------ */ /* decSetOverflow -- set number to proper overflow value */ /* */ /* dn is the number (used for sign [only] and result) */ /* set is the context [used for the rounding mode] */ /* status contains the current status to be updated */ /* */ /* This sets the sign of a number and sets its value to either */ /* Infinity or the maximum finite value, depending on the sign of */ /* dn and therounding mode, following IEEE 854 rules. */ /* ------------------------------------------------------------------ */ static void decSetOverflow(decNumber *dn, decContext *set, uInt *status) { Flag needmax=0; // result is maximum finite value uByte sign=dn->bits&DECNEG; // clean and save sign bit if (ISZERO(dn)) { // zero does not overflow magnitude Int emax=set->emax; // limit value if (set->clamp) emax-=set->digits-1; // lower if clamping if (dn->exponent>emax) { // clamp required dn->exponent=emax; *status|=DEC_Clamped; } return; } decNumberZero(dn); switch (set->round) { case DEC_ROUND_DOWN: { needmax=1; // never Infinity break;} // r-d case DEC_ROUND_CEILING: { if (sign) needmax=1; // Infinity if non-negative break;} // r-c case DEC_ROUND_FLOOR: { if (!sign) needmax=1; // Infinity if negative break;} // r-f default: break; // Infinity in all other cases } if (needmax) { Unit *up; // work Int count=set->digits; // nines to add dn->digits=count; // fill in all nines to set maximum value for (up=dn->lsu; ; up++) { if (count>DECDPUN) *up=DECDPUNMAX; // unit full o'nines else { // this is the msu *up=(Unit)(powers[count]-1); break; } count-=DECDPUN; // filled those digits } // up dn->bits=sign; // sign dn->exponent=set->emax-set->digits+1; } else dn->bits=sign|DECINF; // Value is +/-Infinity *status|=DEC_Overflow | DEC_Inexact | DEC_Rounded; } // decSetOverflow /* ------------------------------------------------------------------ */ /* decSetSubnormal -- process value whose exponent is extended) { decNumberZero(dn); // always full overflow *status|=DEC_Underflow | DEC_Subnormal | DEC_Inexact | DEC_Rounded; return; } #endif // Full arithmetic -- allow subnormals, rounded to minimum exponent // (Etiny) if needed etiny=set->emin-(set->digits-1); // smallest allowed exponent if ISZERO(dn) { // value is zero // residue can never be non-zero here #if DECCHECK if (*residue!=0) { printf("++ Subnormal 0 residue %d\n", *residue); *status|=DEC_Invalid_operation; } #endif if (dn->exponentexponent=etiny; *status|=DEC_Clamped; } return; } *status|=DEC_Subnormal; // have a non-zero subnormal adjust=etiny-dn->exponent; // calculate digits to remove if (adjust<=0) { // not out of range; unrounded // residue can never be non-zero here, except in the Nmin-residue // case (which is a subnormal result), so can take fast-path here // it may already be inexact (from setting the coefficient) if (*status&DEC_Inexact) *status|=DEC_Underflow; return; } // adjust>0, so need to rescale the result so exponent becomes Etiny // [this code is similar to that in rescale] dnexp=dn->exponent; // save exponent workset=*set; // clone rounding, etc. workset.digits=dn->digits-adjust; // set requested length workset.emin-=adjust; // and adjust emin to match // [note that the latter can be <1, here, similar to Rescale case] decSetCoeff(dn, &workset, dn->lsu, dn->digits, residue, status); decApplyRound(dn, &workset, *residue, status); // Use 754R/854 default rule: Underflow is set iff Inexact // [independent of whether trapped] if (*status&DEC_Inexact) *status|=DEC_Underflow; // if rounded up a 999s case, exponent will be off by one; adjust // back if so [it will fit, because it was shortened earlier] if (dn->exponent>etiny) { dn->digits=decShiftToMost(dn->lsu, dn->digits, 1); dn->exponent--; // (re)adjust the exponent. } // if rounded to zero, it is by definition clamped... if (ISZERO(dn)) *status|=DEC_Clamped; } // decSetSubnormal /* ------------------------------------------------------------------ */ /* decCheckMath - check entry conditions for a math function */ /* */ /* This checks the context and the operand */ /* */ /* rhs is the operand to check */ /* set is the context to check */ /* status is unchanged if both are good */ /* */ /* returns non-zero if status is changed, 0 otherwise */ /* */ /* Restrictions enforced: */ /* */ /* digits, emax, and -emin in the context must be less than */ /* DEC_MAX_MATH (999999), and A must be within these bounds if */ /* non-zero. Invalid_operation is set in the status if a */ /* restriction is violated. */ /* ------------------------------------------------------------------ */ static uInt decCheckMath(const decNumber *rhs, decContext *set, uInt *status) { uInt save=*status; // record if (set->digits>DEC_MAX_MATH || set->emax>DEC_MAX_MATH || -set->emin>DEC_MAX_MATH) *status|=DEC_Invalid_context; else if ((rhs->digits>DEC_MAX_MATH || rhs->exponent+rhs->digits>DEC_MAX_MATH+1 || rhs->exponent+rhs->digits<2*(1-DEC_MAX_MATH)) && !ISZERO(rhs)) *status|=DEC_Invalid_operation; return (*status!=save); } // decCheckMath /* ------------------------------------------------------------------ */ /* decGetInt -- get integer from a number */ /* */ /* dn is the number [which will not be altered] */ /* */ /* returns one of: */ /* BADINT if there is a non-zero fraction */ /* the converted integer */ /* BIGEVEN if the integer is even and > 2*10**9 */ /* BIGODD if the integer is odd and > 2*10**9 */ /* */ /* This checks and gets a whole number from the input decNumber. */ /* The sign can be determined from dn by the caller when BIGEVEN or */ /* BIGODD is returned. */ /* ------------------------------------------------------------------ */ static Int decGetInt(const decNumber *dn) { Int theInt; // result accumulator const Unit *up; // work Int got; // digits (real or not) processed Int ilength=dn->digits+dn->exponent; // integral length Flag neg=decNumberIsNegative(dn); // 1 if -ve // The number must be an integer that fits in 10 digits // Assert, here, that 10 is enough for any rescale Etiny #if DEC_MAX_EMAX > 999999999 #error GetInt may need updating [for Emax] #endif #if DEC_MIN_EMIN < -999999999 #error GetInt may need updating [for Emin] #endif if (ISZERO(dn)) return 0; // zeros are OK, with any exponent up=dn->lsu; // ready for lsu theInt=0; // ready to accumulate if (dn->exponent>=0) { // relatively easy // no fractional part [usual]; allow for positive exponent got=dn->exponent; } else { // -ve exponent; some fractional part to check and discard Int count=-dn->exponent; // digits to discard // spin up whole units until reach the Unit with the unit digit for (; count>=DECDPUN; up++) { if (*up!=0) return BADINT; // non-zero Unit to discard count-=DECDPUN; } if (count==0) got=0; // [a multiple of DECDPUN] else { // [not multiple of DECDPUN] Int rem; // work // slice off fraction digits and check for non-zero #if DECDPUN<=4 theInt=QUOT10(*up, count); rem=*up-theInt*powers[count]; #else rem=*up%powers[count]; // slice off discards theInt=*up/powers[count]; #endif if (rem!=0) return BADINT; // non-zero fraction // it looks good got=DECDPUN-count; // number of digits so far up++; // ready for next } } // now it's known there's no fractional part // tricky code now, to accumulate up to 9.3 digits if (got==0) {theInt=*up; got+=DECDPUN; up++;} // ensure lsu is there if (ilength<11) { Int save=theInt; // collect any remaining unit(s) for (; got1999999997) ilength=11; else if (!neg && theInt>999999999) ilength=11; if (ilength==11) theInt=save; // restore correct low bit } } if (ilength>10) { // too big if (theInt&1) return BIGODD; // bottom bit 1 return BIGEVEN; // bottom bit 0 } if (neg) theInt=-theInt; // apply sign return theInt; } // decGetInt /* ------------------------------------------------------------------ */ /* decPutInt -- put integer into a number */ /* */ /* res is the target number, with enough space for the biggest */ /* integer that the second argument will be */ /* in is the input integer */ /* */ /* Returns res, an integral value; no error is possible. */ /* ------------------------------------------------------------------ */ static decNumber *decPutInt(decNumber *res, Int in) { Unit *up; // work pointer decNumberZero(res); // clean if (in<=0) { // handle sign, 0, and BADINT if (in==0) return res; // easy else if (in!=BADINT) { res->bits=DECNEG; // set sign in=-in; // invert and drop through } else { // BADINT: invert would fail decContext set; decContextDefault(&set, DEC_INIT_DECIMAL64); // 16 digits decNumberFromString(res, "-2147483648", &set); // ugh return res; } } // in is now positive for (up=res->lsu; in>0; up++) { *up=(Unit)(in%(DECDPUNMAX+1)); in=in/(DECDPUNMAX+1); } res->digits=decGetDigits(res->lsu, up-res->lsu); return res; } // decPutInt /* ------------------------------------------------------------------ */ /* decBiStr -- compare string with pairwise options */ /* */ /* targ is the string to compare */ /* str1 is one of the strings to compare against (length may be 0) */ /* str2 is the other; it must be the same length as str1 */ /* */ /* returns 1 if strings compare equal, (that is, it is the same */ /* length as str1 and str2, and each character of targ is in either */ /* str1 or str2 in the corresponding position), or 0 otherwise */ /* */ /* This is used for generic caseless compare, including the awkward */ /* case of the Turkish dotted and dotless Is. Use as (for example): */ /* if (decBiStr(test, "mike", "MIKE")) ... */ /* ------------------------------------------------------------------ */ static Flag decBiStr(const char *targ, const char *str1, const char *str2) { for (;;targ++, str1++, str2++) { if (*targ!=*str1 && *targ!=*str2) return 0; // *targ has a match in one (or both, if terminator) if (*targ=='\0') break; } // forever return 1; } // decBiStr /* ------------------------------------------------------------------ */ /* decNaNs -- handle NaN operand or operands */ /* */ /* res is the result number */ /* lhs is the first operand */ /* rhs is the second operand, or NULL if none */ /* status contains the current status */ /* returns res in case convenient */ /* */ /* Called when one or both operands is a NaN, and propagates the */ /* appropriate result to res. When an sNaN is found, it is changed */ /* to a qNaN and Invalid operation is set. */ /* ------------------------------------------------------------------ */ static decNumber * decNaNs(decNumber *res, const decNumber *lhs, const decNumber *rhs, uInt *status) { // This decision tree ends up with LHS being the source pointer, // and status updated if need be if (lhs->bits & DECSNAN) *status|=DEC_Invalid_operation | DEC_sNaN; else if (rhs==NULL); else if (rhs->bits & DECSNAN) { lhs=rhs; *status|=DEC_Invalid_operation | DEC_sNaN; } else if (lhs->bits & DECNAN); else lhs=rhs; decNumberCopy(res, lhs); res->bits&=~DECSNAN; // convert any sNaN to NaN, while res->bits|=DECNAN; // .. preserving sign res->exponent=0; // clean exponent // [coefficient was copied] return res; } // decNaNs /* ------------------------------------------------------------------ */ /* decStatus -- apply non-zero status */ /* */ /* dn is the number to set if error */ /* status contains the current status (not yet in context) */ /* set is the context */ /* */ /* If the status is an error status, the number is set to a NaN, */ /* unless the error was an overflow, divide-by-zero, or underflow, */ /* in which case the number will have already been set. */ /* */ /* The context status is then updated with the new status. Note that */ /* this may raise a signal, so control may never return from this */ /* routine (hence resources must be recovered before it is called). */ /* ------------------------------------------------------------------ */ static void decStatus(decNumber *dn, uInt status, decContext *set) { if (status & DEC_NaNs) { // error status -> NaN // if cause was an sNaN, clear and propagate [NaN is already set up] if (status & DEC_sNaN) status&=~DEC_sNaN; else { decNumberZero(dn); // other error: clean throughout dn->bits=DECNAN; // and make a quiet NaN } } decContextSetStatus(set, status); // [may not return] return; } // decStatus /* ------------------------------------------------------------------ */ /* decGetDigits -- count digits in a Units array */ /* */ /* uar is the Unit array holding the number (this is often an */ /* accumulator of some sort) */ /* len is the length of the array in units */ /* */ /* returns the number of (significant) digits in the array */ /* */ /* All leading zeros are excluded, except the last if the array has */ /* only zero Units. */ /* ------------------------------------------------------------------ */ // This may be called twice during some operations. static Int decGetDigits(Unit *uar, Int len) { Unit *up=uar+(len-1); // -> msu Int digits=(len-1)*DECDPUN+1; // possible digits excluding msu // (at least 1 in final msu) #if DECDPUN>4 uInt const *pow; // work #endif for (; up>=uar; up--) { if (*up==0) { // unit is all 0s if (digits==1) break; // a zero has one digit digits-=DECDPUN; // adjust for 0 unit continue;} // found the first (most significant) non-zero Unit #if DECDPUN>1 // not done yet if (*up<10) break; // is 1-9 digits++; #if DECDPUN>2 // not done yet if (*up<100) break; // is 10-99 digits++; #if DECDPUN>3 // not done yet if (*up<1000) break; // is 100-999 digits++; #if DECDPUN>4 // count the rest ... for (pow=&powers[4]; *up>=*pow; pow++) digits++; #endif #endif #endif #endif break; } // up return digits; } // decGetDigits #if DECTRACE | DECCHECK /* ------------------------------------------------------------------ */ /* decNumberShow -- display a number [debug aid] */ /* dn is the number to show */ /* */ /* Shows: sign, exponent, coefficient (msu first), digits */ /* or: sign, special-value */ /* ------------------------------------------------------------------ */ // this is public so other modules can use it void decNumberShow(const decNumber *dn) { const Unit *up; // work uInt u, d; // .. Int cut; // .. char isign='+'; // main sign if (dn==NULL) { printf("NULL\n"); return;} if (decNumberIsNegative(dn)) isign='-'; printf(" >> %c ", isign); if (dn->bits&DECSPECIAL) { // Is a special value if (decNumberIsInfinite(dn)) printf("Infinity"); else { // a NaN if (dn->bits&DECSNAN) printf("sNaN"); // signalling NaN else printf("NaN"); } // if coefficient and exponent are 0, no more to do if (dn->exponent==0 && dn->digits==1 && *dn->lsu==0) { printf("\n"); return;} // drop through to report other information printf(" "); } // now carefully display the coefficient up=dn->lsu+D2U(dn->digits)-1; // msu printf("%d", *up); for (up=up-1; up>=dn->lsu; up--) { u=*up; printf(":"); for (cut=DECDPUN-1; cut>=0; cut--) { d=u/powers[cut]; u-=d*powers[cut]; printf("%d", d); } // cut } // up if (dn->exponent!=0) { char esign='+'; if (dn->exponent<0) esign='-'; printf(" E%c%d", esign, abs(dn->exponent)); } printf(" [%d]\n", dn->digits); } // decNumberShow #endif #if DECTRACE || DECCHECK /* ------------------------------------------------------------------ */ /* decDumpAr -- display a unit array [debug aid] */ /* name is a single-character tag name */ /* ar is the array to display */ /* len is the length of the array in Units */ /* ------------------------------------------------------------------ */ static void decDumpAr(char name, const Unit *ar, Int len) { Int i; #if DECDPUN==9 char *spec="%09d "; #elif DECDPUN==8 char *spec="%08d "; #elif DECDPUN==7 char *spec="%07d "; #elif DECDPUN==6 char *spec="%06d "; #elif DECDPUN==5 char *spec="%05d "; #elif DECDPUN==4 char *spec="%04d "; #elif DECDPUN==3 char *spec="%03d "; #elif DECDPUN==2 char *spec="%02d "; #else char *spec="%d "; #endif printf(" :%c: ", name); for (i=len-1; i>=0; i--) { if (i==len-1) printf("%d ", ar[i]); else printf(spec, ar[i]); } printf("\n"); return;} #endif #if DECCHECK /* ------------------------------------------------------------------ */ /* decCheckOperands -- check operand(s) to a routine */ /* res is the result structure (not checked; it will be set to */ /* quiet NaN if error found (and it is not NULL)) */ /* lhs is the first operand (may be DECUNUSED) */ /* rhs is the second (may be DECUNUSED) */ /* set is the context (may be DECUNUSED) */ /* returns 0 if both operands, and the context are clean, or 1 */ /* otherwise (in which case the context will show an error, */ /* unless NULL). Note that res is not cleaned; caller should */ /* handle this so res=NULL case is safe. */ /* The caller is expected to abandon immediately if 1 is returned. */ /* ------------------------------------------------------------------ */ static Flag decCheckOperands(decNumber *res, const decNumber *lhs, const decNumber *rhs, decContext *set) { Flag bad=0; if (set==NULL) { // oops; hopeless #if DECTRACE printf("Context is NULL.\n"); #endif bad=1; return 1;} else if (set!=DECUNUSED && (set->digits<1 || set->round<0 || set->round>=DEC_ROUND_MAX)) { bad=1; #if DECTRACE printf("Bad context [digits=%d round=%d].\n", set->digits, set->round); #endif } else { if (res==NULL) { bad=1; #if DECTRACE printf("Bad result [is NULL].\n"); #endif } if (!bad && lhs!=DECUNUSED) bad=(decCheckNumber(lhs, set)); if (!bad && rhs!=DECUNUSED) bad=(decCheckNumber(rhs, set)); } if (bad) { if (set!=DECUNUSED) decContextSetStatus(set, DEC_Invalid_operation); if (res!=DECUNUSED && res!=NULL) { decNumberZero(res); res->bits=DECNAN; // qNaN } } return bad; } // decCheckOperands /* ------------------------------------------------------------------ */ /* decCheckNumber -- check a number */ /* dn is the number to check */ /* set is the context (may be DECUNUSED) */ /* returns 0 if the number is clean, or 1 otherwise */ /* */ /* The number is considered valid if it could be a result from some */ /* operation in some valid context (not necessarily the current one). */ /* ------------------------------------------------------------------ */ static Flag decCheckNumber(const decNumber *dn, decContext *set) { const Unit *up; // work uInt maxuint; // .. Int ae, d, digits; // .. Int emin, emax; // .. if (dn==NULL) { // hopeless #if DECTRACE printf("Reference to decNumber is NULL.\n"); #endif return 1;} // check special values if (dn->bits & DECSPECIAL) { if (dn->exponent!=0) { #if DECTRACE printf("Exponent %d (not 0) for a special value.\n", dn->exponent); #endif return 1;} // 2003.09.08: NaNs may now have coefficients, so next tests Inf only if (decNumberIsInfinite(dn)) { if (dn->digits!=1) { #if DECTRACE printf("Digits %d (not 1) for an infinity.\n", dn->digits); #endif return 1;} if (*dn->lsu!=0) { #if DECTRACE printf("LSU %d (not 0) for an infinity.\n", *dn->lsu); #endif return 1;} } // Inf // 2002.12.26: negative NaNs can now appear through proposed IEEE // concrete formats (decimal64, etc.), though they are // never visible in strings. return 0; // if ((dn->bits & DECINF) || (dn->bits & DECNEG)==0) return 0; // #if DECTRACE // printf("Negative NaN in number.\n"); // #endif // return 1; } // check the coefficient if (dn->digits<1 || dn->digits>DECNUMMAXP) { #if DECTRACE printf("Digits %d in number.\n", dn->digits); #endif return 1;} d=dn->digits; for (up=dn->lsu; d>0; up++) { if (d>DECDPUN) maxuint=DECDPUNMAX; else { // reached the msu maxuint=powers[d]-1; if (dn->digits>1 && *upmaxuint) { #if DECTRACE printf("Bad Unit [%08x] in %d-digit number at offset %d [maxuint %d].\n", *up, dn->digits, up-dn->lsu, maxuint); #endif return 1;} d-=DECDPUN; } // check the exponent. Note that input operands can have exponents // which are out of the set->emin/set->emax and set->digits range // (just as they can have more digits than set->digits). ae=dn->exponent+dn->digits-1; // adjusted exponent emax=DECNUMMAXE; emin=DECNUMMINE; digits=DECNUMMAXP; if (ae+emax) { #if DECTRACE printf("Adjusted exponent overflow [%d].\n", ae); decNumberShow(dn); #endif return 1;} return 0; // it's OK } // decCheckNumber /* ------------------------------------------------------------------ */ /* decCheckInexact -- check a normal finite inexact result has digits */ /* dn is the number to check */ /* set is the context (for status and precision) */ /* sets Invalid operation, etc., if some digits are missing */ /* [this check is not made for DECSUBSET compilation] */ /* ------------------------------------------------------------------ */ static void decCheckInexact(const decNumber *dn, decContext *set) { #if !DECSUBSET if ((set->status & (DEC_Inexact|DEC_Subnormal))==DEC_Inexact && (set->digits!=dn->digits) && !(dn->bits & DECSPECIAL)) { decContextSetStatus(set, DEC_Invalid_operation); #if DECTRACE printf("Insufficient digits [%d] on normal Inexact result.\n", dn->digits); decNumberShow(dn); #endif } #endif return; } // decCheckInexact #endif #if DECALLOC #undef malloc #undef free /* ------------------------------------------------------------------ */ /* decMalloc -- accountable allocation routine */ /* n is the number of bytes to allocate */ /* */ /* Semantics is the same as the stdlib malloc routine, but bytes */ /* allocated are accounted for globally, and corruption fences are */ /* added before and after the 'actual' storage. */ /* ------------------------------------------------------------------ */ /* This routine allocates storage with an extra twelve bytes; 8 are */ /* at the start and hold: */ /* 0-3 the original length requested */ /* 4-7 buffer corruption detection fence (DECFENCE, x4) */ /* The 4 bytes at the end also hold a corruption fence (DECFENCE, x4) */ /* ------------------------------------------------------------------ */ static void *decMalloc(size_t n) { uInt size=n+12; // true size void *alloc; // -> allocated storage uInt *j; // work uByte *b, *b0; // .. alloc=malloc(size); // -> allocated storage if (alloc==NULL) return NULL; // out of strorage b0=(uByte *)alloc; // as bytes decAllocBytes+=n; // account for storage j=(uInt *)alloc; // -> first four bytes *j=n; // save n // printf(" allo ++ dAB: %d (%d)\n", decAllocBytes, n); for (b=b0+4; b play area } // decMalloc /* ------------------------------------------------------------------ */ /* decFree -- accountable free routine */ /* alloc is the storage to free */ /* */ /* Semantics is the same as the stdlib malloc routine, except that */ /* the global storage accounting is updated and the fences are */ /* checked to ensure that no routine has written 'out of bounds'. */ /* ------------------------------------------------------------------ */ /* This routine first checks that the fences have not been corrupted. */ /* It then frees the storage using the 'truw' storage address (that */ /* is, offset by 8). */ /* ------------------------------------------------------------------ */ static void decFree(void *alloc) { uInt *j, n; // pointer, original length uByte *b, *b0; // work if (alloc==NULL) return; // allowed; it's a nop b0=(uByte *)alloc; // as bytes b0-=8; // -> true start of storage j=(uInt *)b0; // -> first four bytes n=*j; // lift for (b=b0+4; b0. #if !defined(DECNUMDIGITS) #define DECNUMDIGITS 1 #endif // The size (integer data type) of each unit is determined by the // number of digits it will hold. #if DECDPUN<=2 #define decNumberUnit uint8_t #elif DECDPUN<=4 #define decNumberUnit uint16_t #else #define decNumberUnit uint32_t #endif // The number of decNumberUnits needed is ceil(DECNUMDIGITS/DECDPUN) #define DECNUMUNITS ((DECNUMDIGITS+DECDPUN-1)/DECDPUN) // The data structure... typedef struct { int32_t digits; // Count of digits in the coefficient; >0 int32_t exponent; // Unadjusted exponent, unbiased, in // range: -1999999997 through 999999999 uint8_t bits; // Indicator bits (see above) decNumberUnit lsu[DECNUMUNITS];// Coefficient, from least significant unit } decNumber; // Notes: // 1. If digits is > DECDPUN then there will one or more // decNumberUnits immediately following the first element of lsu. // These contain the remaining (more significant) digits of the // number, and may be in the lsu array, or may be guaranteed by // some other mechanism (such as being contained in another // structure, or being overlaid on dynamically allocated storage). // // Each integer of the coefficient (except potentially the last) // contains DECDPUN digits (e.g., a value in the range 0 through // 99999999 if DECDPUN is 8, or 0 through 999 if DECDPUN is 3). // // 2. A decNumber converted to a string may need up to digits+14 // characters. The worst cases (non-exponential and exponential // formats) are: -0.00000{9...}# // and: -9.{9...}E+999999999# (where # is '\0') /* ------------------------------------------------------------------ */ /* decNumber public functions and macros */ /* ------------------------------------------------------------------ */ // Conversions decNumber * decNumberFromString(decNumber *, const char *, decContext *); char * decNumberToString(const decNumber *, char *); char * decNumberToEngString(const decNumber *, char *); // Operators and elementary functions decNumber * decNumberAbs(decNumber *, const decNumber *, decContext *); decNumber * decNumberAdd(decNumber *, const decNumber *, const decNumber *, decContext *); decNumber * decNumberCompare(decNumber *, const decNumber *, const decNumber *, decContext *); decNumber * decNumberCompareTotal(decNumber *, const decNumber *, const decNumber *, decContext *); decNumber * decNumberDivide(decNumber *, const decNumber *, const decNumber *, decContext *); decNumber * decNumberDivideInteger(decNumber *, const decNumber *, const decNumber *, decContext *); decNumber * decNumberExp(decNumber *, const decNumber *, decContext *); decNumber * decNumberLn(decNumber *, const decNumber *, decContext *); decNumber * decNumberLog10(decNumber *, const decNumber *, decContext *); decNumber * decNumberMax(decNumber *, const decNumber *, const decNumber *, decContext *); decNumber * decNumberMin(decNumber *, const decNumber *, const decNumber *, decContext *); decNumber * decNumberMinus(decNumber *, const decNumber *, decContext *); decNumber * decNumberMultiply(decNumber *, const decNumber *, const decNumber *, decContext *); decNumber * decNumberNormalize(decNumber *, const decNumber *, decContext *); decNumber * decNumberPlus(decNumber *, const decNumber *, decContext *); decNumber * decNumberPower(decNumber *, const decNumber *, const decNumber *, decContext *); decNumber * decNumberQuantize(decNumber *, const decNumber *, const decNumber *, decContext *); decNumber * decNumberRemainder(decNumber *, const decNumber *, const decNumber *, decContext *); decNumber * decNumberRemainderNear(decNumber *, const decNumber *, const decNumber *, decContext *); decNumber * decNumberRescale(decNumber *, const decNumber *, const decNumber *, decContext *); decNumber * decNumberSameQuantum(decNumber *, const decNumber *, const decNumber *); decNumber * decNumberSquareRoot(decNumber *, const decNumber *, decContext *); decNumber * decNumberSubtract(decNumber *, const decNumber *, const decNumber *, decContext *); decNumber * decNumberToIntegralValue(decNumber *, const decNumber *, decContext *); // Utilities decNumber * decNumberCopy(decNumber *, const decNumber *); decNumber * decNumberTrim(decNumber *); const char * decNumberVersion(void); decNumber * decNumberZero(decNumber *); // Macros for testing decNumbers #define decNumberIsZero(dn) (*(dn)->lsu==0 \ && (dn)->digits==1 \ && (((dn)->bits&DECSPECIAL)==0)) #define decNumberIsNegative(dn) (((dn)->bits&DECNEG)!=0) #define decNumberIsNaN(dn) (((dn)->bits&(DECNAN|DECSNAN))!=0) #define decNumberIsQNaN(dn) (((dn)->bits&(DECNAN))!=0) #define decNumberIsSNaN(dn) (((dn)->bits&(DECSNAN))!=0) #define decNumberIsInfinite(dn) (((dn)->bits&DECINF)!=0) #define decNumberIsSpecial(dn) (((dn)->bits&DECSPECIAL)!=0) #endif hercules-3.07/decNumber/decnumber.pdf000644 000765 000765 00000421426 11143760537 021326 0ustar00jmaynardjmaynard000000 000000 %PDF-1.4 %âÏÓ 197 0 obj <> endobj xref 197 13 0000000016 00000 n 0000001470 00000 n 0000001554 00000 n 0000001687 00000 n 0000001795 00000 n 0000002423 00000 n 0000002614 00000 n 0000002691 00000 n 0000003016 00000 n 0000003652 00000 n 0000003847 00000 n 0000004483 00000 n 0000000556 00000 n trailer <<4FE959721A464F49891A8DDEC4170F9E>]>> startxref 0 %%EOF 209 0 obj<>stream xÚb```f``j“Çx€‡Y8 ÄàĴi6F™û.8‘núĤ9œ+aÛiÉ%aÓÊf‹½î1ÛĈÀċßuhc]D`]XSá›Ĥ”'ĥ†JÓĥ 9`šĦÏŬ [ŝ˘ĊDùNFĜ£˜0&Ek Í֞xĠòĦ™ĉıĉG ŭRdŽú^nIxîٗĴÈnx9ñÎ3žäIS–j‚Ĵf p]‘ä%²ÉuMᙞ)†Ž_ĉĉÏ<;áȁgĊ ?Uù2Ù4ì<g³O–´lÓTċˑŸ#LbÉ#½ĵ›$K Ëò Ì ›¤IÏ>Iq*KL p7Ij~2ĊrC]c—³P€ğ˙¤€ÏYŠŬ@ĉ)=›’5ÒË4nždŞòtϞ#R²s‰Ä‚ŸŞPuÊsÏÎÍ­â ¨™ÔĉzVišĦ'/Iq³Ò­/|€ßy/Íj”zt\³ˆĵʉĊĊMŽÏ*v}TlıĦĤ (ĤxĉÙA ^!ËĊ"ݳ/ƒÌséË8Ê~"É˸ÉH/G¤8ĉ’'‰I`ʳç8Š”AĉU+0”9ÓU"sĤ÷¤Ĉ9Ž;‹@$î<˜ĵv½Èo`Ÿ޲4_êyÓ= äf™KFê Ċ'zÀRž ²(aä.èéq-'5!;WbRσ U Ż^jJg‘›"l!ħàËb …£ìKYÎħiĜ00 @’“’²YRqqq &/AÁ4 šNi. ÊLӂĈ` "R­g‘ĈPQ0W‘g@èp 3ĊҀĥ3°†) €š%(5^PĜ ,(¤˘…4€‹kh#lâââ–b˜A$ĊÀjÙ@BBŞmi`ě ›@\Q°v¨ċÀm vĥĜÎP¸ “*ĜYPÇ1›ÁI¨}L'A8l _ƒC l@7´È§@ëV00ž¤ı€Xì _^ĈìGüĜ˜¸>(Ĵeĝ ôÀ˘=Nq³E×ëG2ŠW™"d8#d@‹‘ Œ1€ !†D >ÂÀÄŻ òï0"1h‰ endstream endobj 198 0 obj<> endobj 199 0 obj<> endobj 200 0 obj<>/ProcSet[/PDF/Text]/ExtGState<>>> endobj 201 0 obj<> endobj 202 0 obj<> endobj 203 0 obj<> endobj 204 0 obj<>stream H‰<ÁN0 @ïù Ça^b'iıĦ †l÷ĥËĥ°v‘ZĈď½¤ B–ċƒŸŸ-/_ħtbħV ÀíY)R!Qßj0Ö -eêvBÂ!k„Di ƒğŠ™;zĜùf{éjß ÚP÷U˙}>’•²Uİɚ kFK¸4Èċ蜽û~ñ Œ\Àw°_~ò‘”6ĞĝOEYE 9)(ŞQeÓ&œ<Ĵâµ ħşŽcJfZ‚.8a§Û3ŝ´ÜÀÚ·mœıĈB+†ı´è>·ßžáŞc_}Ĉ>ĝaäµµö“Óş}sw9a¨;lb7bNü 0èyV¨ endstream endobj 205 0 obj<> endobj 206 0 obj<> endobj 207 0 obj<> endobj 208 0 obj<> endobj 1 0 obj<> endobj 2 0 obj<>/ProcSet[/PDF/Text]/ExtGState<>>> endobj 3 0 obj<>stream H‰”TÉnÛ0½ë+ĉhħÂE‹utâ$h.@•^‚‰vĜZ” JŽû=ä{;¤)/Q ;0 Ñò{3œ7oĉòî;…öRïò–…tá1?ĝˆD4¤G`‰ß4÷ˆOCúìÒìq% ZÀuZĦZ=Naœ`‡RIaùÔĈñcŒlĜ_עYKñ ÔL˜É4?H0ş×˘ùĞᓅO(!dÄÇ?ÓO˜…ğ,>IHjÂϑr³ÉÊŻEá´´ÇĴ(d++ċ"„6BúáÌœWe]uމĊ4B· ááuĤµ\ MS5”İb%ĠÒqâ!'@N–·˙L‡”Ŭ /£E‹Ş)3y‹§dHˆ-Ë#x.rYf+P]ù(š‰9ġ\&½|Nû‡ÑçŞè0R!tŜÈÚ¨ĥžRı5ÂĤ…ÒF鉁%Âï0 İlƒ4Ș‹Ŭv*wïbón2àïm‚™żĜ:3r~bĈ†‰wïsa‰h\XôÈ>ß·dÖÈöݭ̇°Ŝ·r%Û? ß^ŭuÑĥTÓWÎ.À£àJŭOÊĤN…],~ œeàÁú;ÛéÏw$ŽßH<=Z(hR:Ó7Ċ̍8::rm@N¸6íĦU°ĊĦ7ç:k2lŬ~lzjlfu-T!78€×8Ĝ˝ĝA7{_÷GUˆ Éĥ:·vğ-³tq_ÚMı[´?œá¸ż•)$>$Fĵ‘ÁB¤4ܤŜ?T   endstream endobj 4 0 obj<> endobj 5 0 obj<>/ProcSet[/PDF/Text]/ExtGState<>>> endobj 6 0 obj<>stream H‰tWMs6½ëWà(§D˜à7s›™$S“ÚqĥÊŞ½Œs HH„_K‚–½ż~_$EZvıdI€î~ŭúuŝë£`§~óyżı˙C0ÁöǍç1x‹=‰€{l_m\vÂkŸÓżËfû׳잕ĵÜíb§ow avâ ;(âÂìänšFf×ŝ,Y!ó‡Ħ:Ȏ•êeŬ+SU[ÊJÖşg ì‘ÁxdʅNŬ˙ĥÙ~•µì²’ŭ&sUáŭS§ôı’ZċìħĊ³£Ê3­šzċUdœŠXè<à\<ĥŻ-_ûzϚ¤#Žeƒë“]=cT>ôĴı._w8ŬqĞ£ ĞoÂ蛟zÜM¨Ò·˙ëĦjŠĦ”ŭÇÊĉÇ>÷bĞž›ĝ7e‚P=ïċ³ĴñL8˜7âCî LHy^f=-U”_Ö~˘ĉzžƒ÷Ŭ8Uh*T“ Î"vyĵŭ=#y1–Ĝ9#2\¸˙#ƒpmö$äž1?L9Ió¤„g™²û r_DÜW›È-ßş€Ù§-Kdään²½µx‚‡áùı5ó>IÌà}ĥ ’‘XÚëĝ1(]Ġ +’ÑŽUi*°"Óëu7äzè¤%N6ö [܂€S!ûAÄ£êxß ].?ًħ)Zm"WÒ%n ´QŬĴ’ĴĤOÛ;o:ŽûħÚ>hJ~âk“<ôħSîĈŜŜ牛Š…; ÜóqOħ+|7†ÜÓÄó—¸{(µ5umiÚQĦ.5ždúM6@í4!*ž´a*Ş:AĠ½F3” ͛D⍗äğ7E>7…QħÛ"ƒšôêTß6 Ôv¸hŬœ§yrYN,·lñB ßŜ;4˙01ÜĠÙĈV8°ÁÙx1ôĞĦ*ôĴáŽÁÇ âuf˘ħ"ô4V{™<˘˙BFφq dŞoŽú’ BöMNŻÎµ;Dî(]ׄïÁr'İâÈJú=hU*­¤iqq„÷M Ùâ>ËċŠċï0`†yÇê­Ż3ĉVFC-s´J&iqÖáƒéÎsïÌ‘giñ½éġ˘§ŞÚ@ppG-ÖÙ?Ò8 …ïN‡ßçLàyè->”ĈA²â̗d}ÑUhìñ$\m$GGä gıàG<P—Ky‰İÓ­SçĦAòۆ‹²}ÚÎɎuÍ`›–“ŝŒòċ{< Eĵ’/ßÈĜèÎÎÌ˘n$“ yáX‘ xñj\ÜĜRıkJëôKrU+_rْӨŽœšïÀM?ĤÇ2;Yê.k™4ƒ`÷Î(BMvşÂԛiäĥSß0I,Ĥ‡+oÖ³ñĵBkGËr ÙÊşfÔYuZMŽ2Uϓy3„şˆ²WšWêäàPEÂH—2­K9>ìġlLvq=À'€J Ê QM—ä‘Mñ¨ ùĞ ŭ÷=žĊëOdù'sÑcv!Ög?ŝvYħLħ &,4ĠF„×oċĉ‘.ŞÓ}ŽÖAŬÈÌö—šßR†ùĈp…ô\nqÛG)?hˆÂ¸+–kÏZ·żŜß_.Ÿ‡/ċ+W‡ŠCïG…]w2J’ë ïzԕ)Ôè[!‘˘‚f›û8‘:^L·\T#@™ŠäÇö?VĞîß÷ıżĊ+÷ĈvobŒ'L¤Pw„> endobj 8 0 obj<>/ProcSet[/PDF/Text]/ExtGState<>>> endobj 9 0 obj<>stream H‰ĴWÛnÛH}×Wô£ĵÚl6ŻyK2ÎÀƒÄÂ"‹xÚd[â Ejš¤ïÛŝÄüÇŝážê&)Rħ`g‘(Ô9Uuêúç{ÁĥÍâŬfqŭA2Á6O !˜‡?ĝ/öY,Rž²Í~áħ->›láq‘Š˜mŽ‹ċ‡ş3lݲ]QéuQċú ñOĠ²‡ċcײúuÊò…áûBUëqĊËêŭAe-kÚÚ¨­fOµÙĞĥıÚü†{ւ#–Ÿp™†’.ûşTF³ƒİŸ‹\級UĞMĥSĠVóĞuE<\nvşÑ Kß\ŭşù Â”ç@y*J"ùĦƒE@r{UJŸn…á'˘@ĴÄ=kó°úèbi݇‡ew`mÈ‹²¤*p•ñpµr0ÊĤv§ş<40˙DqÓZ”şPLı'#ñ\.›L•úB}‘Ïe<Û´´ġ·–!’$&m‚0$y_†ç•ÓsCÀm*ûÒğ!Ğ+B…ŜXÀ÷dê½ĞÚĜÒğs)›ŝlšH/œŞSŭuÎQvêŝ>ĤĈħĜGr)ïsƒéd0äPӚ>İ 9kè‘"êŞĴµGĦ{ÛŬ…ğüáŞo`ѓí;²}jà€”½çùE$Ê䍕€7ğ”&Ú‰Ħƒ—·ĥch Ú:owˆqÊĜŸlÜàċX´ğ7#ÍCbm^ûŜú7z#ŒCž,-Úıŝ *€6hw{ŬBrŭ„ĤΉ·w÷·ì‹ä~ĴEšFĥ³†Ù  d³ ÀàŸÎ6IáL*R&<–ë|žŽ3Êó„s3C"'E••]NyÑĈ¨Vı²Eñ üSġۆ·;SwÛóqâ•Ŭâs‘ˆäŒ8ç| )1ŝè c™µZ~{ss’&ñjĜáĊ@ˆ¸œĉ€ŭDBÚXĝ<÷“ ˘° NÑl÷tĈq³·Ça`׳)6‚µˆQ*˜mpïħ6żŻĤvCĝéf/à‹p΃~̓0ĊïdN&éo$Œĥ…›IÉ9›~‡nƒ é•›Äöô³*;TÑmg¨ˆÔ5_nEám§v(q÷”×ĴŞ[ĉ,$ÍLOĝ”Á^8„ç&Ü× [4żQ‡ƒÎCĈVŭŬÜԙê`D‰Û!£° ğ5Ż$Ŭ½Ġ•6ëÓÄÀĵëİ²ĝ—&uĦ3ġ0(zŭíc­m†.öS.–÷ĊÀœ(_V.Ÿh'Ébµt xrSF6‹†3ĉĴvÔè–Z”Ê‘Oû îZW4° úĊí+Ò´’D1ÍZÀ{ġRXĞŞgn…6ÇW*ïEîĠŜ‘a,)ŝ<ۖZ4˘—ÓóRSh£p}~½ÓÊ`°T$ĈÒÖŻ§6ìğğnĈŞr.ƒPÛW½ĈKMëĥ¸>Sa-Ó°I{Ü ˙{üèÜV³’ħóroOçÊk“#ĜcŬ•hdŭ=óÎ=Ô[ÓUĠà)èc+Gġi<jC!v ŽÄ ˜>¨BŒ›˙?³Éâñ0HŬÏKáıŸb÷Sl[²BHü$ti)VPâásÉR¤)ôÎs8lêEâ,Š‚3ħRÇï]Ŭj7ÍHkk@7țC5“˘ĝĦÖsáEç6)„Ìú>é.êÌ'ŭyP(쀠Lv,½~x`ZÉDĈÓbò‰×ÚS˘.µËòSİêHċpWNŞCkġ޸&CÂ ó›ai3Ĝ{ôÍ(~ĈçŭC‚áďĝ#ûúĞÇò…`[ÀHĝ$ċ‰dû…OOċâ~ñn3ŽĴIŠC˘³—Ô.H‘.ƒ‹b87£ġĈœvŠƒNkwm{xs}}<}ëLSê^<î9lÊuo1è÷†ïÚ}9ḰÄ+M$“0hDÚÛÛ;ınUQ6ƒ2žŜ´Ü¨’ÒéÇgcÒy>Çꔎ(ĉħ£Y–ëŝ< ’(äÑ0Ċ1:éÌ·{È; Νêeb06ÎÛÊ]J‚ħÑÙŞËzûÂŝdŸL½5jż'1ĝ;D SÏ7_Ĵf>kJO²½hÚúvĉŻûï_İÓËÁ5ˆĴi‹ĥkġŠŬé#û'YFw~GOÚ$Ï]Î95äIŸİD¸Ûg çÔâÀïħ˙´eFàg•ßÖ·•Œd> Ĉġ“5oG:# n1Ä)áŠÙ)5@FÙ8ĉH-|ş›Rg4œÈCrÜc]YnŞ-|1Äh…3>ç{Ο/ĦƒŝÂ)ŸR’aóxêĝKd:5•óНqO“}öèŭĥp˜JĵZóÚlŬÍ5FÇġì fŒÂgݍëòî}êj-%Ü럸˘#‰Ŭ“Vh]o´Ôġú>ĵ˜bğ£×Ğ £ŝöŬGö6K×P&TÙNí-yoZlŭ€6Ϥ¨î³ Cï ¸-=W.(äMö· endstream endobj 10 0 obj<> endobj 11 0 obj<>/ProcSet[/PDF/Text]/ExtGState<>>> endobj 12 0 obj<>stream H‰ŒWÛnÛF}×Wì[(ÇZq—Ë[‚>$JR¸hÒV VQPâJb‹°KÚÑcĦ-ò½™$ʎ‚°%‹3³3gĉœYMĵlcGŻç£é;Á›ŻGR2~à%–,ŠK6ŻF>ÛÀï|5òı†›?Œĵ_­6[öcWäz<˙!B /"Œ".(~¨ÈsŜ°ÎjÖn5ËġêCW-µaeħ4™Ù3½^ĞB×mıgEË Ë–ÚĥĴmĜş0fĠÔ÷Ú´ä]“ĞeûĤc™Ħ,|6\"aó7xfŞB:óĦ1Ÿ‹zŠvËÖĤİ0@a \sfôÎh ‡fmÑÔĴ¨á¸SjëĈTY{5[e²lşO›_ YeċŞ+)„eìĞk–Ġ9¤^g%4HbËlġÙċ°…T\BîH~Ĵ(:UɔN›Q,K‡A :ĤŻëIîˆ[gĥ}‰÷ôog;Ê ?v›ĠCÓŝ¸0ĦÓô½Ĥ‚˜-Ş]‰9Ğváıŭ„àˆ“„1È˙ËوĝĜ÷×x"Â8ä‰g[żşŬܰċĠjÔĤ‚ik!èrϨÌéğ¨o‹ï˜ üN÷EÄT$x "Çq,úÙbá?ğ@çÀOÀI{‚Q·nިœÙbŒq&Rp†é2Ú­Ñú ˘ -˘R6€j½™ìà NuM°TPoĉ# <Ŝ8“£2Ŭ›ĥ>µ)Íî0IJÄN‘w£ĞĴ¨s $Ñnħzċä ,;@0µÔ!/²ÉxÔZè!ŒÍ§&ÏoéˆeĉÒaÏ­ŝÒ‘Oü­šĵşa/+Ġ„P?ï–ğ>ġÊ-œr Rî ’0Ù)vÈû`âP‡éê5O=ĸĴ܁ xì'‡&'İ#’‰@Ċ€ù+à0Éʃ)ÚV  ×°WnoĜìLWz×:ĉ!–˙”E8Tj 8H)dâtĵâüËêĤWê°´ÂÏ [mfÚ£ÄğşžÌ} |˘˜à2ŒOs?^z)Á# Î\Nù,ĈNu_Ï>ŝL­›=N_a[„UaµHX?+ÊáÚ×ÌG {ïQŞfDˆ˘ÄiĥŬn×ú(ìKVĴ`³[üÔLħC]ae"°(R§a¤km/6y!jšÉò˘§Ë²l`CŸ4ŝ)¨iÈ$ Âê7½O"ß÷8çîÍĠ´W¤'8Ї à=ˆâĦ¤#vâAiX cäi&‘É[!×Í$ôä­Pï0,už™÷ŻŜàúÛïÀ˜ZyI3U‚şóÀW§ıħm!ĝöÂô¤“ħâ BO!í|ıäd‰_mÜ´ĦSs…„nñŜJk´nX¤†f d÷YQfK1Úp˜KrHİœ—w Tĝ7w‹OĴ΃߸wŒcBŽ i$Vo¤Żt!fÍnoŠÍĥĊ ßĵ~Ïfmäö0Ìl„‡t/ cË[•ı×9˙vĤ!,×N¤ëĜ£·óÑ ž‚%1 endstream endobj 13 0 obj<> endobj 14 0 obj<>/ProcSet[/PDF/Text]/ExtGState<>>> endobj 15 0 obj<>stream H‰tS[OÛ0}ÏŻĝӉ_'Ñ´‡uÒ´Id{=˜ÖM3qdğtü{>;t¨İr=Ÿïĝüĉ–A뒋&9żÀ Y'ŒĊžj %ĞI Í6ĦâżY&”.ĦÙ'éÒlÇ×ö œöà7fÍoä‘:ñàQç„â”,àŻĉ—?nç2ŸP˙İóœ#вJuÀŜàwC7´0*ĞĥÚk ÷İÓï[ 9żŸ7@?Î2I)St÷rÙ+珏÷föĞùò–é°xZ’êĠŻġJŻßħËDIêşÌOP„¸êu Ì£euj€Áx4Ò­HàË ÄÖdŒÈĵÈĦıB4—5Ÿ+È,c"GŜôۀ,nÔKfC×Ôv쵃pµĠƒW3C†nğ!HdŒâ ŠtáWÊıŬVŻ­âÜbvĊ˘6ÉÓj2—"Úġ6jXġ!ôƒòíâĉúû\תÄıVñŬhM‹“Aé’KLzħ†'³³'³(Û|@)VŠjŠ]Ò‹ëñ¤œÈÏ"'j}ç7ï5MœÔeR¤xö“xĞF÷ ñöĝD)Iċ 4Ĝ*mۛ]żŠS{‡ÁA7Ë8‚rŝW|ÇÙÇ%ۜÈä€Mêh †’‡Ĉ½8Kjë0ŒY&„  ÊCSË XE`…›ĞÂÎä/è {hÍŸl×n> endobj 17 0 obj<>/ProcSet[/PDF/Text]/ExtGState<>>> endobj 18 0 obj<>stream H‰ŒWkoÛFŭî_1Hħ…ÜH4‡ä4Ç)ĵĜ Dí+((r$M+‘ iÇğèŸĜ-ò{÷̃íŠÒ"Ìˆwî=÷uĉŜĞ?Q²VïçW3BÉ|uASâŝ$Ihàğ ŸĴñ™çû~Hĉ“›/ùnżċ8ù•(a󲍨ĞËùoP:Ô*Ziû3=ŸĈQ4ßE¸Ó†ÇĵS×pĠ½Ĵ×2ߑǍ(6¤È+Âs%ĥOdÉq¨áUÉKÒÔ¤äğşRÌNvµäƒOfÔˆÚcwQCı( W’zÏqˆİÖÂżàħUCE³!͆“U[V&ÈĊ6_nıg=LĴ‡‰q˙ñCú)‰ƒÌ‹lĜ´Aê¤cßĈC‡„yYä'WW] ¨WŻ_IQW\6‡ˆGóX“\[‹ħ–²ŜwínÉċô42š:KÁYP½(@!ħÂĤÖrJòŞ$PûmŝdIÚmsÔzm~âBâ%aé¸ÜOHè]~ž˙ŭ‚˘X¤sĊ™t™ÀEç0²,ĥZï'ߔ|%*~9£¨Ùɇ›ëğŸúpûíü £ËêÎ׎ `żÛÌĥ{·0‚kÑ(d4n,e.ì,ĤN˜DUlے“W}zĵÍĞËY’Z0Ë\qR™ßÉV,e.ŸÎÀH"#> £Àĝ^5¨½Íˆ’X +Ôŭ^ŠŞY7Üħ8<’ğätîÒ³Yà|q²ËEµ0O¨íbJŠM.Éwx~¸˙ĵ¸$˙>YĠ,˘NU6j5HĴĠNô~Òç„äS²|£c’ŠDTk—š‘ÒÈ2/ PúÎ6ġÏïdñëşj@`Dñĉ˜ñÂ>mœvÄAÇIĤ3ŜÉŜOLpA•0s?ì”×4ú (Ad‘XîQ`>²lW+.Ç+ÄOğ Ħ)í*÷‡9§Yv¤Dhxs”%fħ"‹‰ïCSĤÏ ÌŞnŻêv½ħtx2bQwg—0³Ö{YÛ ‹ÉĞnıîYĠî÷¸4ğÑ\’ô‹êĠâòÍ F ;(ĉ9XúƒöŒäM++b@ߌ&&Š£cöâóöúƒ&UwÈĊ”…]L“³íeŻr\‹É·h…)AEŝz{w;˙ġŭğO7ˆ%AŽE…ı"ߊñ“@˘ŽRè8ŭt@:Ùû Ĵz˜öê­Ż1ˆğş"ĉ×)·ĵú<ĠíéÒ ;˘gi¨—µÖíôvĜ‹@Â\BÍ Ħ[q<Ġ$Ġĝñdgy#ò³CĈ,a~”ġî“Ħä äihš~žÀÑê·Q ³~AœéƒìqÓKg:ĝ?M§Igú,óô²ƒ{â]YZÍgy°9KÜešżÍ_/G3&ñħ EÍĜéÚ3=˘y=Hƒ%KëĠİZ nž ĈšÎz/ÛÓàßyMġö|kÊÔ@Ÿ‘’2 Ù1r NS‡ˆE£dèŸq<êĝ'8ËUÙ?4ée|ħ QSĦs†Òûëfc–Ŝ)‘mUéU˘[p<”Q’zÉäĥ"[,'²;¨È#˙ÏvKpġİ—“Ùhèµċ^kßwµRB“.PŭBi8Ï{q5ğ¨—ups>KŽ&·ŻX +!UcôE÷Cû-Švp ôÏËQ÷šzÍ!&ûnÂigT÷s ƒîĉ;ˆE–„?A´ާÙŜĠ ·ĠÑXšPz(µééĝĵ#ÂÎMĠ“‰ğ>Lïk ÉĤlS¸/\4Ĉ–£-†5 FĜ܅wùŬHcQ?òâ Í:Q“ĞŽÚÄĈĤ+:}oÀ•eŬlşì(³Îċ.Cž‚A)“›ç> “GY—m|™ž @*@y´*ɍğ‚CÀPŭ“Ż9IÍ^}¤Ö“Ì8’éÛ<‹Ċ/(=yÏÂwüŸäùŒ‘šƒ)Ħ˜W(êNkUq]Xo(àüíûŸÈu›Lĉšk0Ĥûħa’Ĝc“w`#Ĵtθ|` @Ê@~Ĵ àN˜öéf~ñ?A‰ĵ endstream endobj 19 0 obj<> endobj 20 0 obj<>/ProcSet[/PDF/Text]/ExtGState<>>> endobj 21 0 obj<>stream H‰”WÛnÛF}÷W ¸ ‰Ŝ]ryI‘Iì.£hÔXF@‹+iŠHʎû!ŝŜÎ^xħM‰¨cG µ;sfĉÌÙÙó/ß(ĴĞ“ó“óÏ1P˜ŻNh˙áGÈ ¤Ìe„àÛkü›/OˆKñ`ŝpâ\ŝLĥğLƒ'XÛ]ħÏSy-JQĠ“ù?hÖ³fİ1K•Ù .×6]BY MÍ7²aíĠÉQA½)…€]R&[&+X82—µL2HĥèŞžĥ Lj1…Ŭçûí(ĦXÁ£HÊj1Q8̨‹@.”KÎ5úG-_&ÙrŸánċOÀJĉÊürıßê·*œ{t°yíNfA¸Üù\” Ôw“Ûùïf`$&Lq‹]ߤNEH‰ú¤´q+4ˆ ï3/]NäÄgófƒÀĵ Ĝ ZEĴ"Ĝ•Ċ3²zg,…ĈR¨ áñ\J"à1ħĈ :×Ĵ~܍ŭ [¤bym³œcÖ·ġC1… Ö鯓>!Îù9R"Żê$Ż+›¤CHB–FA4Kû G‰\0ùìƒèĝ3Œ Ċƒ¨Ékè…!xîĦÚĥhÚ}fK ‰‚Îë˘N2%fŠy‹tŬgġHFxh3âf¤YŞŬ*°!~ÖP‰Z;ŽLŠò‡Ìת êëç~`óQçÍÒgıIT%JtssqùéúŻŻW_ĉßŜR˙ö'îħ²ÈánżZaVĊU LUtCóúާñu8^,ĉż,–ÍօX%X’…ó ĤmjŞ„!|żşš˙ĝáÛċb‚pżWDĞCò_1’KêÙ\F£ıl–Ŝ8­ËdW½'è˜ÑÀ¤./@żqI˜uşl–—İ\ËşzϸrJšö)ĊRêr1~ Tħ‹ÁİġKɘvmŻg>—Ċö›ĉBéÊdĉĞ9§SP•ÑUˆ…Ïcò‚ò£F\цB”Ž’Ûĝ˘³ŸĦÔÂg1>ħS˝ìÑlĉÑQÑëÖ°Ê;…S^Övħ²êƒ%KħOƒe·˙§²Œ7• FSÖF˘3›1ïvĵ²ÔÊK8RÙQiò‰÷޲ò^Ĥ˘É4-ÛâRsĝéù½úïYz4ƒ^Ü(•°vmڇ4}…K*-&ĞċĤ·ô8˘¨Ñ66ŞmíÚ˘?ŠQÂdĞûŞ ZToŜè%ÇĦ…¤6:Âuk[d_ñà“ğìÁéqCgğĠ˘Ä`úËaZXĵéFġ­]ÛËĜŸ˘ÂÉ\ô`5ŸfÚ|E/| ĉ˓êÀÁŒ]âùCúÇĴŝÍßè'TKû,…Rì²d)ô…JÍy{ż:µ7òâž}mz›ÈüÀ…Îó"ÜC0 Ğ}ĴĠÜ%s¸4—M´°p’4U£> endobj 23 0 obj<>/ProcSet[/PDF/Text]/ExtGState<>>> endobj 24 0 obj<>stream H‰¤WێÛÈ}×W4ˆĦqfh6ïL°ĥ×ğëì l!yA‹lJÜH-/#+A"A7§ş›—™ÁbvĴQWWĠİS§Ğ^ŭ™³m³x³Zĵú>fœ­²˜˙+tXÈËħm|ħ_Ĝl‹ŸU²°-Ûĥ]ĥ:.–ïŠŭĦÌe˙fÑ4ùƒd²ĞšíD™yı½Yŭ‚ğ]s7×wsş;lËW[ÜöbußG™·;Y³*cĝ͵|ÈĞaRûi—ê!O%ċ‰ŝŬʤÍĞ’‰­ÈËĤeyù Šyğ_RÈ2emeĵUÛZì›[†ĝûQ$]!”•Yš.Ù1ѰêAÖYQ­›ğ0 -|ŸġGŞ$éêۛ/ĞŸĞ—Ê%׀Qv2ĞjyĞ\fy) VËĤ+Zv̋‚‚ĜˆMqBèLcìlÍœ8°\şĝ­+£°gÀvı;žXPDށ²ÍKD’·’­—İL>*ôú°šĥî’ĥ'•ϝXĥ;@mß×ى•)ŽâÔ0]‘µ¸H”Ĵ:ÈZxË6]Kıç5é$ۋ+Ğ–î™uĊúĈJĉûžoœ¸‘ĉÈÏdpAUKv2ù•Î÷cĠ)Ŭ4|I(kXü§8ş.·BßcZ|ÄħiEÛ5sPú‘ċıŸQd‘2Ë%üöÉ·UÙÊŻ „ŒbÊÉ02ċIpëÄĈZd]İ™> \ŒĈô—?VG:xKllw˘5ŝĜ·'Ò˘a 0]ÙĉĊÈGôŻr·L ‰˘Tä*‘ġr48Œ@JĥWYR•²ÌeÙ˘–İŝ›Ì²Şy‹kPV;œìFı@_“µMŽˆEšê>îÉF-?ÉC!àR0¸‡ëŞÛîú'/h ûê 1Û:ƒÒĞê|ĞzV_X˃f)£ĥfDÔ Ò·•éúĉšCĦĉP¨(„ĥ ½‹˜> FÖqkĤÛ9÷­€ çïÇŭöŸÛXĴ—/ÀÛşêí=˙rË^4²]ßüñĉ΅\/_½~P7I8VuŞğùYx1כmk'K÷*bÑó‘œ@ŭĈĉNğT5/ŠÍŜ5÷Ñ<{pıe}ŝ~ÙIK։j'Ѳj³ġò›×%˜}€È"ħnO Jċ†d6óx˙ğĉËz]~s{6 PÀ Â3ĉ)Ä:œÁN‘zTÀÏ*óU5²•°žC›"ƒ3„óô€ vÚ¤–ŬRŒÏp‹ÜyŝwÑuwƒJĝ—ëêzĤXñUòôG'mô]N£OßBĴ˙µëÊ>ixĠ[hx:-ŭï·í™ÔcËápç¸&2n_ ­?; íuš>‹Ğ*ċ$&ß{Óïùċˆ¸ÓGtU‡³“ˆŝ„§ħ~“iùgÒ8Dġò:r94›÷Ħ9WCΑ}ÀP•Š‚kĞVctFÁMt qİ:0ġċùnÑaıq/wüŞ4g'ˆ}’ † 9 Ğ˙½oĠzáŻ,ĊsĜâiĈÑȋ¨ıa/‡üŞtŽgŸH'{Á{÷öŻïÔP3Ğ£½Ç ×F~UG‡³÷ĵ};q§2têżJy`U‰ÉCÏW—3÷>ŽàjÙAÏ?é1”Ëċ\__ VCËëwL3H?Z‹f‘q-ۋ&öڝlgħá0âs6fċ˘ĴËŞĵû›Ĵ+laVcĦPMTÎ0G "ŸxñӐĉa&NbĉûÁSdzVĉĤ`^ Ŭû‡œ[G4ùڟ”?vÜċÉğW“ÔXŜÔRQ´kƒ-n İ6búç ì$µ<ö˜ٖ;é´·´òĠ VNŬmÍİlĊWĠó#„a…Yŝk}£ÄŽ2âq›ÍÎ7IáO*İ÷&}n‹UmŸ˘ÛħÁÓ͉–NÊ÷{\HĵƒNw×rħÇşHX7$;{j8Ćâ`\îÌŝ7Ç, Cû™ëñá˜E Gû%ĝéρZx !"Ëw<ç!l#²l@F­ħú9jdW¨~R²Ġ—XY·Xú=#pàĦ‰ ŭž I—BŝP5MÁÚK·ŞV/MN £ş.@pcU}Êŝ})żŠd}CXôwHˈĞD˙“kvPċg#rĴşSß`“íŭ§ cħLgœ;dĜ•OÇÑ>'ĜsHŜ[êĞ5 #˘dú"+Ş#Ğ’¤Ğ1yci*‚Żĵ@äÏ´°€%˜•jÒߞùz8ħŸ4HàhŝBäS—³d'Ê­Äüjʈ.Á}£˘X—zăĥ¨‘[ÑHÔ½ÈËÙîàH01Cwd]™NLÔô H Ş ĥİĤ/V…ŝ _żzjK=ˆZìe ĞaMͨvÀ;Ó í1]Bê΂šĦ½Äv[牲C pX?i” Q–^J²Ë~\˘XÏQ]N*³^j ƒA`EQ(du‡´ĥÖc˜@ߜ]é@…QÊ@İÚ.Gn˘ŜvêµÖ­ŜVS&²°VeL ˘´ lô4PĊAq]náıä!ĉc5:ón…O?àç'ŭ…ÙxĈBv$|`÷_l–.8ËÙŻ5÷+Ž\ĥ_püT,>/ŜĴWtÎĊ7žL•‹X}³È·\¤Î]{$ˆyÚ~ÎìşÑC‘`Äé.Ğs°J%‡"OTM@芈,[‘†ÇÍA&y†ê>š`4aZW˜1ü’EŜòM7*Ġˆ¨ñ–şKä Ŭb•"éKÑN)Zp{Ğè@á)ĴëL$²1ĊĉşĜwĥƒžv´f÷´¸_ŝı%] 0î?áı4RHĦR1V @›Éa:ŭ[{8A¤w¤1 ˜üŝÍöĥŞU­)‹}+ DƒÀò—ŻĦHêp ŭ²~i?֚XûÒĝjoñd˘ =ŝ#ÀĈÛP endstream endobj 25 0 obj<> endobj 26 0 obj<>/ProcSet[/PDF/Text]/ExtGState<>>> endobj 27 0 obj<>stream H‰ŒWێ6|ïŻ °/öÂfë~ÙÉ.tz’’ @ŒŬ‡éE K´Í‰$¤Ôcħż1ߛâEĥ|Q&4ĤÛ&yêœSĴS|üîWŸlĠ7ЇÇ÷9ñÉjóàgÄ?ü—$ġxh<²ĊÏŞ|¨çy!YfϟŠf_3‘Ϥ(;ŝĈ“RH²+ÚŞĉívúˆ£Cw´oöġÑIÓ0tGS/ösâjÇH]¨Ž0w´9‰Uö\Eö…RSd}$S˘ğJÑvìSg#Ĉ.˘g#z$ò}wׄT]Ñġjift ì‡ÙpVW¤â’•]}¤óe'4œ½´ó˙~xX†! r/'KŸĜü-6ûXaÂv;†,&ƒ'˘ĝĥ-jÒ°isĠ,é²ï„+édħWä°ċŽ’Yp½à°c­Naġw0ĥŭqEeÙKŞżö4”ÔAñÂÜ.û6Ñ2"6HĊʟûfÍ$Ùô-Ú*ZEë)Țw„·ĦàažP/Hâċ4˙ĞĊšĤ=£%†-‘ ŻşÙ#ùJŸ³ }šeY|.òR34ŽÌĥïv­”LíE[iœӘ€D>ÒÄH#ÎÇt1 ˜H HBšz—ğ,šxL$ŽbêÏ^t½‹nH 5&Ż3üâżÎ5ĥ"ïkQh–/ĵí,ħü”FA‰ċQî.eÉöşi^gnr¤ŸD€›8O³sŠż|÷ŝ—çİ=O瘍w!¸KÀß’iâôÙםMrŻá/’ƒe }ĉpî%{˘WġÑ ²j­§9p›WĴí8êin‡½?²ÇG ³ Ê˘5ˆÚ£Ĵ› 0èPœ˘CeÑá+ĊqU¤[…“l/dgâjFì·-“ĴëNŸ˜,ĵKĝ™oŻĉ'Vö&íŻks™xÛ3R(#úíî|ô¨H+:{Áz¤ŸġR᳎àCŜŬʀNBWUiŠ QBÓ8%qQ}{6Ô˘Ŭ~löt³ ğ˘hĵíY~è.šôħoöú˙‚œ­ULĦ† ZƒNµĦŽMühÜCˆħMígÑ1K/Áı&‚ͅ)޵­° ëK)*ĉ”ÔreƒËŽe˜…:Ô­*ÚÀN‡v- ”À™çĤÇ,[›âwf³VġÒA.Úm³PÑ˒™ĉ"0IġZì!żu-Ê˘C°†5BA£ĴYÑâ,ÜïĜKŽEz]Sß÷}+‹+À“Ĵ0µĦFT|s4ı ³Ŭ·u2ëôċ2ƒwÒċlě–SŒz,ÌkgBMŞOÓ$ IÚċFíg?jäġŸŜğ)şE)Mâ,mCíÉ ?zgXƒË ÀĤó(Ï3½Ġlş'ö gÑĊĦ_ÖzÈ_ìG7HÒ k`ĉÇèĴĜĤèëNkĵó…#ŜÎĥu„îĥN\HH“‘@ûüôÛ³™íSeÂPÌs]ŬóN-ҷ֐eA Y%\[[Ĵk¤Œ½Ĝ@_@Në„2³âĈXQ§‘ÏĊŬ‘7“öĈ4Š£àb–$àóš!€éȤa(eà§çě‚·“B”b íhÏ=!z˙U:µG¤ĉüá…Ô÷2aÀĊ£˜>éÇ4×8mĝ0ûoËşÇ}ùÊşû×|™'ž7{|ĵ˜5Ú߅‘'$ÌòM4rtŠ"’ÑFğg€ƒK_ĦPò1&û…ŭüqPúI\ivWhqùÔóc£ÒqŞef€èKġ “ôT?„˙mŬoNSáŬêŸıòuEù;Q-şŬ4JX;(?G™|%›=vö&xċšù½ġ pm]ĝ’ü?{`atX:ŬÖ µĦÏíûĠµ…kâ ı\6êħdŸÍ-gÎŝ0‡4³É’ ¸Nk? .Áx8Óı…-Ç;Ŭôo-‹’‡!x5ó§[‰÷睊ċ_Ĝy£éî˙§˘x Qì01ü0wòŭ=“È@+ܸ™è6¤œ·V RZWUsä'£'ӁÙùƒ!ĠÌBgö£ÖÀèÖB½“QcĤë§Öĥk¨nž~²„)P|­‚Ĵ…{ĜhI<;gCŻlíëüì3‚ܽŒÌü=0‡Ĥ˜ŭ·^L/ħ{†ĵŒÙ2Ò’´ÁAéPö½gUĈ‰xÚJ˙hjœ`§4ĥ77žĉ6Ş•à\îci ­îĴ† SwŞœşoĊT)ù‰ŻY-úĠuċ¤Íܘ°MQv¤o[ĤëŻ[\œ{ğÖ³³şÊ_ß=1`Çĥ²hoVY[f> endobj 29 0 obj<>/ProcSet[/PDF/Text]/ExtGState<>>> endobj 30 0 obj<>stream H‰”WێÛF}ŸŻhĜ€ZH6Én’1ò°™Œ/°É#ìË(XPTKC["^f<ö+v‘ïŬSŬ͋dqäÀ0lI]]§ŞNŞŭ遳]}óòĉö}À8[no8gŝàŸÈgO܄-7Ûáï2ğñ\ÎC|ġr,Ÿ+Ôç†ĠjwPEÊ-ËʍbyÍò˘VU£6,Ŭ6ŞbûĵPt%NÜNÇ=>ħ•óħ­{˘Áeês^7yħ›-?Âقğô#ı…³Êöi•6yYÔĞÙwtäö}d G1>xË½˜É8vcBíp×”66ÏÄFá 7 ċpôÑÉÁsşoĠğقħç9··ìĴ>áÛ*O×{5ûmù÷/½&¸%ŠÌ-žQH€ĉğڀğ!…#"WħIÙaĞó]‘îW·ŸŜ˙ó~ÎÌçŸÓb³WĠjFˆ-àZ5Ĵ=Úìɜ¸ ĵO—6]áUHŬÑGG§ê{¸ûx8œcPgħHÏ`éd@Á…ZĞâ9ŻÊ‚ĜrSZLâ*Ĥî(J¸İ4°ĠŒŭޤĝÒ Y9EYüául,‹Ħž]ÁƒœÄàGCwR[7iÓÖìÛïُ÷w˙ŻŞ²Ş‘—À˘ù¤Ô‘•Ċŝ•)ŭÓoaDWaôGèĵ]9ß<"4Uz<˘˙R˙ĉVĊ7s†Žş+‹ ü á.ˇVğ•ó-bXͨ”—şŒĝÎùÇ d_ogL*Ġ´UĦ ĝïĤÛËó.¸KğëítŭDŽsIçDŒĞ/}ügUİ9KO%€´ÍH’™VĜ ÁĦ`§mÇĥm‘‘b‘UvP7Üı9“7— nBZ9ù‘os\Ŝ”úĈ;VµkòQşséXÄ"Ö œû}wx*!AÄŬėLÈĜ•CB ډĴ„’èñÈH½Äf­ƒ\`xb1ŠÑ~0òI€×Êĉiƒöœ"v¸= „tĊÜÈàp3KxblDî}m‰$vµê#˜ôĜM¤üÂŭ‰úN  [ŸOĦhžÒ†½ä¨ŬÚÔixyR]·A蟤O˜ôHFœJóZmĉ:$U?u:ŝı=ӄ…½ÉèĤ_ĝóžQáÜh˘ Ġ^0Ĉ Fyâ?UOÂĈGFä\|ÁŸÚ†N É]ßù_65Ûĉ&ŭFĜpĴNŸm|Y[U´pËÜH½Ës߄;‡úĴ²Öx+şV™ŠݧŠc¸ĝžÇ‡`ğa6.˘|b Q×1½„XÌÈ_Í<„Q7ôĥÜïËħL zŠ?bâmeğ‹‡.ÑN—éQ°˘llÄ´5ú‘‹7‚÷#@^A“gˆüĉĊTÔI‹HŽLz0"g4yÑ"š´á·eŒz/|ϕ’KKRÙ)b¨%Ñù°…Óìbû”&w™Ħô”܀°ô& o1MU\ZíZZ0j˘ċ"eE{XӞdÒN2u&Á}‡ä7é'À=îÓL}×—Ħŭ÷Hë%VĊ˟ó–ürŽV’…ŭ˘ġĤ€ĦkpÊ۟?Iêyû³ġЎcé'x³ÒêĠ$8rŭ8’|8ï˙IAdFäWÉO@RÉŭÁì21úîï˘ĉÔħyêĞ9‰/” (yş>#0òCŒ y,8ÍI³R‹ħš ̇NĤêéñ‹‚zräQ´[è=ŜMßÒ ÇġC‹‘ˆA[[tCğcÍ>ÙYûßĥx)ÛbóżnY≙“gOì%5K(ˆóĝRctò§·2ϋĵÉÁn˙˜Ò¸ X'nĝ•£ħÓĈ˜…Z|=Oħ–oû &‹‚0ÎCvĵÈ?'èX¨ç†’„B?($E?7Ĝ1­k³´ċM—!›™)ÀXlùüŒB>¨ll9+Oó£ßYŬXŬf™RP—ĉɲ½J!iñŠÓÓCJñ˘ öñ²Ĥl"ħˆKĝɨ¨Úr*áx›`°v ŸŒX÷=Ż2ó&ŒŞÍv5P”íògÒïòLïŞt§Q‰~´SĊ }!.ñXGħM^CÚ_aÂŞÓĈH[kŬ§ŝN!?=³’ġÑ̀Gzu™ßĉHŬŝuX¨âù›9MM4?QŜµX y’ˆ‘É”˘Şb3ê¤(I,éJxÁÉĤ·Zá v@‘Zw6ñèdö É<3ÛŬ˘Ö˜ĉÈü&ßn•ŜèÖê)}ÎK"fEU×9­Lë}g rúĈšÓF‘î+•n^iÚc>î·ÛÉuş=‚îùĜŽïô˙(ëìX•ğ*=&ŸdžњQ¨Óäµŝh´ïĜ6äfù׍LqÂŭġh2ĜÍgX|ĉl´ĵ¸&ÑÜ$:ÑyN¨Ġ“aR<:˙•¨íl`J‘-kd cmcìâ­†5A³ŠvW_Ğ|÷Ô@ş2ÈևŝÁîÊêXVşïAH„DJĜù„KĤgĞ‘}×:> endobj 32 0 obj<>/ProcSet[/PDF/Text]/ExtGState<>>> endobj 33 0 obj<>stream H‰”WÛrÛF}×WLiË)ÒĦ`Ìà^N\•Èv˘-Û/ĉî İr€!91°p‘ĊŬÊOäAßğg.¸Ĝ&ÄMY’I`fúôéÓ=Ŭ/~ûHÉĥĝuyñâmB(Yn.hL\ü#es]ĵĜ_¸d‹ßezá:ëzdùċböĉïı y$iı?T˘EF6eµçM=_ŝs={.5çRun$N˘uhÈ}Ör'¸—e[a ÏsÒŞ33‘~h÷w˘"uSµiÓÂÉd%Ò&?.È]ېfÇk›Èše£¸äŠ:€ZO¨6ĥš"V^Éü¨‘ó´!ĵÈÔ=Ow²W™8ˆ"EÌŻ"/q˜‚X ›Ĥ’°§U‚lE!*À<’mYjßç·Ë^,Ÿ+{A`ˆ:ˆJ+Ra°ŞŻ&u+~ñ¸WV|+4ñîx/ċ†ÚûÚé} ȌÁ’ÜóÜc‹îcè/ôQö+eħĤÈ`?Tċ½ÌÀ.ċ›L%Ü]ô |G_jK²èıébm‚¤|Pĝeħí*èí4%‰„†+<żCƒn%6#–‘j{àíJ), M y/T€eAàIĵPà˜ğ#ĝG`/t˜ŠòĴ–{™s0Z÷Ġ3 çh–ù^ÀÏħ;.^/ôŞkb4Z ğFĝaԉ܈1ub“jß&/y3!{¨-íé f¤FrÊZ;4ŽÙ·ĉ²²…r&ì1êcS8a. 'Íñ HTVݐé Gşr׆àwQ‰ż@kÑÒÍĥâ{ĝ'? Ò޸Cá§j‹B‹ú’ ¤/A-ϛ]ÙnwxöW­Í­2ävıß+e&·ñ“ ^7:6ĵÚĥ{À´lĠߝH?“;<ϰŜ1¤D†”Hs‚/çP7&Ço ‘:SQĤ“ĝá°~öâEÇAà¤äñqÈ2À(îĦwYġÓĈ!s;k·[şšŭCiŜf‚\öŬ% Sìş Ġ€&ğ-–ıĵĞxu´Êš‚D] É; İ[:‚ôSŬd²tvŻĉWÔeŞëY½žP šÍiûÈq?Il(œÈ‹|ĞN߈’:. |% ˘V‡XpÇÖ!GšËb­?A3éRAaxŽÏ÷ĞÛġœü÷ÉpùQd '­²ÈXí–f£pĵ+,4Ĵ|)ĞÏŞ6ŻM•|:<~ZÑYŬR Áj ;á˙2Öp|Öp·T.‹F< áE£lğñ×ĥSóúŒqß·Ĉ“³ĈğĞ™Ž-:˜Y½~s}óŝ—wĦ˙é£~pаX(ĈŭÇWf)äÍfŠ (”áĈñ=ÏâA œÔ­µ€vâAÔ+܎ÙèEĝ €#YW³PĠi—(”:“—F‡…‹ŬJċÊ6 H&4ùjžèJúJOa`ƒëĝAr"[étQé ş]ŭ´óZlx›7ëÙт –Ÿn>Ü,?ġA]Ï_°( ÙHžË˙ˆ“i Ô^œœBíŸA=]d,j/ŠÔ&’oĞro´Ü|AtĦ· ˘œàӍĵ°+4ôlւœIٚKqTwÑÉíQÚ]ğuà²:};u ‚Ô³µfXkнüÙ}IäO1ŝüĝd]í ù]iĦÓµM·6ÔŻ­ÍmrMFÉçȽ|ĉ²r şŬäí$×8ÍóOÉ!™N¤FżQ äÏIÌ;a€ıg3uĜhöôÁ\–Ĥ’kQ™Tŭ!S.N%ŞGO vX {Ĉô²ìuYĤtN°vûvgşßéĴ÷kğ8_>ĞÉÏŻÈ³Z˙YŻ‹ËQRi ,Ȁc" ,qOħáecĜhöTcgaĵwŸv›EIçĥÎíaퟪ˘İve˘§aAìĝĥO3ùİŬ ,“–|'Q3AżYïë:¸İ‰%ÂLàĈô”MXè. A)Êßò#ÊÏOêoJ‘3ìԛ×%ħFġ*3{$ĵ`4P;ӎğÛ×v­ĊN ŞUd#s=Ĉ7û§cPÜL…Ġób'd ljŒċżŜżùífùq‚ W~H£p´u„Q5şC߂ ŠÊ·Cñ'Ĉ9mìùÇC{£ÇÌĵ‚GL-˘°ÜeOĈ‘ı…ˆĉÀa$˜# âÑF…"²ĝ‰ŞWÓCZSèq2#WqĤ‰Z}Ìy%2;3ĈŽĈÉİÙí‹Ìs5áòI(C9Uéû¨ĈU­Œ43£=Ŝ ċ‹TsaC*ô!rZ'Ž;žI}×(~i,ĵQDĊX“îĤു•]…¸t]'êD›"E­µTR_’{^I5ĤÖ/{ƒßúcŬ7ĥŬYjÊZĴKŞĜéĵœˆş>8M6ÎI„Ái*~¨Ÿb"t%B 8îzî ҋb6"!Ñ´™wd`§ÖĈ¤Ĵ,­’Ú½À´n2)> ÑzĤ‚„G›ĥHġ$ċˆ4Î8~ϝo¤–{‰Pݳz-Z%À½ Àa³Ž7ÍÌ=Ï[6ϔ”´*Ċŭv4À,ŸCUĦ–íËJŸU(9gr+ádı!‡ Ôŝ¸şğAsSc×#MŝvsÀ해è³ĥ'•%Š´ÌôT¨p3“ġVEfŻ jh$ê À•6ÜI˙FZ›ù•§fŽ~£Ż/ĤXoŒĦT?ßïv+Ìq]Ž&7׳ċëĉ×÷äşĴI.T7Ô!‚`Qds“È5A&‰ê^5żA …L’ŻàbtRN½Y^üO€ä5âG endstream endobj 34 0 obj<> endobj 35 0 obj<>/ProcSet[/PDF/Text]/ExtGState<>>> endobj 36 0 obj<>stream H‰tTÛr›0}ç+öwl‚әvĤı¸“N’—Ä}A5 ìú;Úé÷v%|mêq˜$fuÎÙ=guġù™@ĦëÔıš@ ]:„€üSˆIâ% |ÒÌñ=?Œ°pĵ¸²¨˙‡Re³óä"“+^ħê~µJWz-ro4a!ó¨;“Jw•â¤XjȚz-T'rèšÑ÷ô Nˆ‡\·ÈJÂilX]n=YèħÁ¨_vċJt2CˆÊa! JIDjún ĵÎa)k^UÛ=ë°cŒÒNúΰPb{swB<{E5 ›•Ŭ!WˆĠ¨Ì]Y#šAàZÇ×JÖĊkAvĝemtäR·ß"VW8Ż•EÁ0FJç#3Ĉĵȝ5 ÄOj+1ı´zeŬöĥYô+Qw°8_vBW3ĥsÍ\ó! ħç³Ĝ4Ĝ`i(N ó\h‚ġôôÀA›ûێŞfƒŬÁf?àCcïÜ7:Œ…çàGÀĴSŭ³ŸáĠE˜D†^´SGħÜĤÇÔşĵûİ5é˜=3~kÖí" 9şáÛħİÔĞíƒt4(H˘Á 5ˆ+‡?ƒû/d§ĦYBАTËĤ%t+²NEµ5†‘GŒH-vjJGzLž‰T§­•gĦpmdûÁ°¸>ٔıkdZ˜fħ–MŻĦĥp%Ż ĦM–°ğ;Q2ğ>óA ¸äVb²ÌžÁġ!ԎÌŸn÷[oJÁsÜĴ„é wsËqay‰ÉӁɒÜŜŬ<}}ĵ½˙|Ÿ>_N”Ĝ;ä,ÖûÉ,µòB%ó‘ñVàpQ›u}ĈÄm.сşÁĴJßâà½3Ͻ› ܉N srÌŝ‹û oBôr4 ‚À \|âŬÇÁİ=8’L= ûŝ´Mˆ›ĤŬ*Y”Fv†bïŻáĤQm£¸‰ ^Ä>;Ü#ŸŞ lħ6ħjm„„˙(ÂH’3ı.!ĤİğÔù+ÀĦn³ċ endstream endobj 37 0 obj<> endobj 38 0 obj<>/ProcSet[/PDF/Text]/ExtGState<>>> endobj 39 0 obj<>stream H‰”WÛnÛF}÷W,\8 ‰Ŝ]Ŝş@ÇmŠ&RĦ/–PäÊچ"’òA~#ßÛÙĞh™Ó\dKš9sv.‡gżŭEmsôëôèì*AMG$Fŝˆ˘ˆP—b _ĴŽ0ş…˙ÓìğcM·éj]0˘ïècš}a9şd_*7Ğ9Ğ›ÑôíißDù&Âwb7Ž]ˆàoşä bÚiÍîĞúKƒL:FM›Ö-/oQZĉˆ•ıĝġž·Ë=Á]£ qÁŭ ĝŻ›vŒ ^²ùÒ]€Ş…EÌı_òlıŽVUΜ5³Jko]¤?˘vɤŻs•n¤ÒdĥJBÒÄġU²‘ùµƒˆ;ş™ŝBÍVüŠ7ñğçԑŸx™›œ&!ĈÎqÎ2•ığ<ÖzİĈ‰ëİ薁钕÷˘*Šê^0 ŜŠ´N[^•L1ÍsÈŻ­¤JíR†.ĤA'†tżJyıçî½`P/샤,6e& œë„vÈ$Ĝs ŽQàn<âîÁg˜´ö×Ά—müıUĠ´ŝo.âLĈ^qçġÍ·W£ ‰ê³3ÄË;Ö´+Vĥ‹?ŭáĥƒÈ&Öım:xÛÛsêàôèçV]ĥDÛdiÁ.ĞnÂXùqĵAZŒé–¨Öa%L’‰$TL‹‹ Nö3D= ĝ Ĝs= ˆ°Š2D€j‚AŒé–€G–ÖM‡ş­…+¤É=P^C@8L€=×C€Œúƒ%@}Í@4Ȁ1í”Sù“F4@¨;>Ŝ06×rĉìϝx=ıÇıÛs}—ÏTĉ²!UŞ/\w€ L5É ĈôÚɖi=šP,ÙkŭäFÏIĊ˘Ş5 ߃½\ĝ 1\˜ĜÁÉĜ´dŒ&žˆÎq‡‚Ĵڔ-Ğl?".Ġ£6´ -Ä„é^3ÙÀ½˜Üˆĵä-O ŝ/“ À˜ĠéŠA´fĴVoş³|ÇÓS( ˆÂ>lÁc]§ÒoÚ4UĈĦ™s$ŻT’ÉÒléŽ&´£ïĵ+ÑşNa d2tŠß.[4k7ÍÑ˘VxÁápòV!8P!ó´MçiÀe˜x*ÙjS^‘'™ħiÔnĞYĈĝJQ¸:yŞHC÷ĠÓí8s¤tèD6{5‘)ĴU‚0è.­y:/˜*ÒÍyòáQĴŬn`£W‚À„dq>°h8^vU rr¨ÙŞşcùXĈTbj .ŞÚÜ. w…Jż>1â%ħ˙•jíĞCĤĠ)½fŽ] Ú ‚ŞEç£ÙhŒ^l÷™y3½:Œ/Žt<:͘b7”Éô 4{n |"ñÙm£D…]ö7ݵïfWœŭH˘Ûóf>B^6žocâbĝ²è"1 .uƒ›Ó |ċġZd _ò;ž³™#ÓÄÁċĤÌkQ§/&ŻyBhGJˆ—3²OPY‚}OB3ĤhŻóüŞdLżƒé%@äQhpÉZÓ˘Ġ½¸ëLò2;¨<ĵƒêôTš @£DC‹ĦYS‹ì= #.\[µiħE'Ġ˘C€K(`òËM›/ŝħelM;Œ}Rفe~`D÷”—Üü–· ‚á û`ï˘ĤIbz¤gQc×’ž&!ƒC’Ĉφäl/;„ĜN›ëÔbĥĊežZœFQ|:pJÑL)`Ş6­RĴrŝ2x–”ĉJ(-Ñ5q)·žHñ!X[ħ8gñ‹ĝÏ$„×—/aÏ~=É÷M¤ŭF*’µmÖ5.¸ŽJŭñSïfŒŽO0}@ÇcЏùÍĦ+ñĵ+9 ``Ĝƒò’LšDgÖÖdwüIêŽst"$z²8Ég£ÙĴ„,eê2YĠu&Ġ>IA:G:YB" üwV³ħ‘%V•x(ĞÊ;VĞ2zŞ;ê4O+E—êÔ´ġ&›XDdƒà µĈl7€S(7è7ÏùS & äÙĤH[%ik5@ĥ<%> endobj 41 0 obj<>/ProcSet[/PDF/Text]/ExtGState<>>> endobj 42 0 obj<>stream H‰”W˒۸Ŭ÷W`7êT‹CÍÉÊÓvRIÍLj”dae&!‰.€-+ğ|äƒs.@R”şéTÊċ’-÷uÎ=÷âû?ŝÊÙQ?ü¸{ĝŝœqĥ;<óñiÀyÛ5>;âïx=?ŽCĥ;?l~îÊĦ–Ĵ”şPUoŞĠğ/°:Kœ[Kĝ€8I‡N5dDwdGÙJ%jĤèÄ׸²İ˙ œcT9#S&è)‘¨"î7†´‘·°h„İ öŠ. µ-U#.L‹ƒĴ/TD^R*ÍP›jkkú^H“ÀOˆJß×U!lŞûÇu~úyŜ‡ŭYßêŽĥYôè˜~ı ŸƒT²-äCm6Ĵ—Šê$-Ijxéĉ­•÷ƒ #×r§NËĞí§Ôğm?÷eK t N–lhQ9+!Ú˘Öò i>o‘Ħ ˜ˆ2IHĝ˙éT1ĠAv…ĦĴĉfTĦ·öÒ1a²GHIkĵħ)Ŝ+q'÷%ŝk?óİ_ĞfhÀŒ‚òoİ‚™ĦÀtDš“(ŒZÜkAäĴ ^r•ƒRż ͋T?u…¨WĊ;öı—ĉI°¸ˆÛ6ÖŝñÉċ&^–ûÉÁÄwÂE1ԎuĴìl+ùÏĦ˘ú–@h´˘1€‘M§.OL~-do,™T7´<à"¤#€cÁ5ÁÇi”>ÇgÌêÖäàiRüú,.f-…ċ°„Ğ[E¸­Ñ˜ıC_3ŠKTÚ6è…Ħ•{mGY’“` gɎD£W 6èZŬË/CÓëEsOíûBt(“ê@WG*†ZYşŭ$VÌ1¸ö“_œ­Ħ;Eb-iêşMJ!R†+sr‚j9úmnaCŭ#¤ÓŠ6ħmmú$!.ùġĈĉ?cÀ‰%i|×3s~#ö~xĈÍóŭ˙O"K Û)^ì7?=ݤùİü|~J Ddù}Óó·à/.ŜĞĥì7Nî Ġi§ó§ùg ċŠ„g\ŬȰùŸOĈĞÍvER3?·˜ħtñn÷Üoäyb.ë·EBz$Ap³ÎşòĦ,Wë…U"çËĞs`´r r슑Û6 ‹“lä(Ĥ¸Eér΅~ĉ„ĤSàkKMBêĥÇĤÁqcÇ/_\ĜvŞ‚j Äµhƒ8J4ÏÙ ?uèÛġb^^öİ+GSOv-ÎÑN´R² ½€£9ü])öÄj͘{Ÿ‡×ğ›ħKb/̂ônıLüü½.1—,Y£=Çhŭ”ñìfq„h­ĊSâ|qcáÚ,Ğòo· żwF‚¸â [>x͍˙ÎíċïŻ6XxĈŒí3ÇmKĈç<_Ÿ—iîċyßĤM‰BĴÎI4şÑ8!'²Ü< Ô¸³—²ĠĜ{ì˘{Ä+ŝ66ĦepÑ Û£9}cAK‚ĝ_­°ÍSíaܝÙ3)á+HîÖÛm’ĦoÀÚĞġÓr=²·0Ż)v ۍ£êúl—Ċ ëHaܳñ}îs8ÎA=p-ëwû½˙Ŭ*½€@Ž|ç;›qcß<ı=›3ĵsÛŸ7C=ijo0ôBĵÂtÄ:uw2{'ñ.Ċ¨Ê“´ÀôÏ:e[ğÚûO?ŝ̞;ĠwÊn0èA?™—DZŠíaÚ"d|•wû0›‚Œ!jy>Eêòç!ċói÷_6áI endstream endobj 43 0 obj<> endobj 44 0 obj<>/ProcSet[/PDF/Text]/ExtGState<>>> endobj 45 0 obj<>stream H‰ĴWÛrÛ8}×WàÑŜ‰`ÜIfŸ&×ÍT&İJ´ğñTŠ’ ‰)ŠÔ’”eχä{÷ $R -Ov+ċr,5ş§ğOÜĵŭÌɲ½˜ŒnŜ$„“ÉbÄcÂż"A".¨` _ĴGŒ,ñ3™eŒI2ٍĉvö²,{ߐu9ßĉözò dëŠWÜı2ÚP%Œ÷D…Ç'+KÎ\à“EVĜš4îÛ´IIŬTÛY³­,ÙÖvNeE6Uy—ͳbé­f­|`dÌ)çL‘É+—­Ö!ÛrcĞ´ÉÊ˘&iüĴÓ"]:7ö~f7îğ4wîĉ™·£wĤuwšó1·YıŜTYŬ&(óĵÜ9ϋÌĉóúy@F·È°€ óȰˆšXŒ=ŞÙ2kê(ıˆİId÷”ÏiÀ?ׂFşoŝ¸˙ÈPÖ÷Ï(—ÜCĝċ*\‡du¨ES’Ú6ŝĈ›Êβ¨ı§Z9 OŻÇ1iäRŝcòÛhĴ¨d ïWŒs­=•­·yCÊEÏ ÙeyîBTċĥ˜‡,šRÊmħlV$[ÂÎl]§Ġ3_ê•-f7'ë6„KğŜ¤3 {;oÓuĥqQçÛġÔV2ğ0Ù:k`=}a=$t¨m½´ÑT+ñÔ*£lLöOQ™¨­˘”ĉaƒÂ;oŜ˜ÓÀ‚ʍ8œ_›ÈBǔëDŭ8ôUÀs½­²Jï,IÉ]šoK€K‹…Ëf…Ú,W.Ĉ˜s™$ê•ĜûJ’äYû3„ĈCKE5k×éŭ…ıèš?:œŞ'ûŽ4u×Úq`|q$Öé²ÈšíÜúbáƒ<­–ĥnڒ%ˆF›^ #äv~=ħĦâÊŜoÊÂ{Ogkf¨a½”Ñíİ/úŸI0}–R„X¸& -Žx˜WĠÊ}dŬŬy–ĉ³mžşSG}ìŝE˜œ­Â¤‡Ñ3a°á3ĉàBÔ³ βE6#Eلżġé"À³–šŭl2÷×ŝä.Ĵ#*Ĉçŭ§­J⇠T6,Ôż)1·×çïr‰÷.íüڞĠö$˙caÜÙÊsßܢĤmİ›€ızP3IAt*éĝ8 Oère"š¨}+vĝĴL‰lX?mŠġ%nR.Ÿ–€–”ĞŜ*L˘˙/%:: z™–˙(ÓX‰²RĴxò³Ĵ„£PF˘eŽĴ¸TŻŽùVB'<Ġy$İ]k7ĈJ_˘ƒ†ÈISĊ’žçS’ s‘‡”`TF9ĥC~$Żáĵ0Ìşè³”‰T8Z”•›À2µİ„Ñĝ§yŞCQyğFpÌEŝŸDuÎQŽı~š§OÔ˙ÎSĦQ…>;›Ĝ}Kˆ#;Jâ{Ż5°wùħžĊ3@ĵşÎ u"yè[t5JWo§ĦÚʒaµ7>š¤y]˘Bö>5Ž ˆ†žÛfB/iu˘2Uğ,9Ž>ö=tÀ°Ŭ܇™Ù”uMó~ğ½šċeíÁ„ıZŜ^{}zh(ÔÔM<"B Œ;!tÀáĦì1)âž_ìÈXCex\a& Zƒ›näĞ_¸o4 ¨šQ•8 ĥleDta™Hè"wĈéZyÁۊ…ż­·ŭĜ˙à÷>A# ¨³Ž§ Í9¸ÜDŒÇ’Tĉ4+Ŝ.™éĥ!;żck/Œ÷Âġfs ZÌħŻż_2 :QĈçKfş_çĤ$MÀ˜"‰êö8~Q%°E]ÛĞÁċ"1qQßúˆĈĦ½Ĝ9@57Ĉ½blÁ'Ŝ²Ô#­! t´ıĵ×ÚŜ蘣 qòW4ê-UϓD†$Î"ó§ĞŒ²*ƒíä6áYJC +cÜ ŜC­#N‚”g4Rì„Ĝ:zëÂ2=„WÂ1)ĉäLç%9ó^ŒÇŬG•q?'Êž*ƒŠ&·³ jĵßĴXb,Ë wí 0ga(ƒ°U-ÖÁmìŜt,:ĵ ;|§Ġ™o+ïÂ:ĊŻ}ì ­•ÛDMhrO‘v[ĝ¨÷1ÔŝDH\Yœ ï²ĵPĦ)gícµi=ż°Áž…" ­ôêġËŻŸ>ŝóĞŻ/_ż{˙îÛÁĦÀUÚ9ÜéħO.a@½KĞyM~H@*…9:qÄKħȊĴyˆ.ƒxuS§ɈŞ(:ıĉЏ˙ŝèMÒ=9xGĉ4_µ-fòë gcğ;ñǔŜĵ˙ĝñÓ9éŜùĦœ†`GwiÁôyß/⎗?tN^ĈsĞSÜ˙ñëû7—Á×ŬÓ?¸'ĉ1ĊÂmŝîfŠ ›gu“P{~dÈĵÜ>ż×\ñ-~~ƒûoÄqgDv.Íßɗ?™8ÉÈÈ]MşĤ”d=âúĝW>ú> endobj 47 0 obj<>/ProcSet[/PDF/Text]/ExtGState<>>> endobj 48 0 obj<>stream H‰œWmsÛĈŝî_qé–Bî `òɉċԝŒâI”ĥ3RF’G )0(Yù!ŭ½}ö„JGŞµÇ˘†ÛŬÛ}öÙgżùáÁ6íğïß}óÉ0Á×ïgôBĤ‘ÉKDeìzû޳ ŝ]/éÇğÙÇËïï~ŝé×Џwû§ğË\^½żŝ–ToIxK‚ÉĜDRÇ#K‘HuĉĴü\ïĞëjVÙĵħm÷-+ÖÌŝħ/VEÛċU7g;ÑÖĴğÏ;ü°ä…Gœs.D$d˘ÙġGú&Ž•³ı.ŞĵdĞbStĴh™}°UäC >Ò¤i¤3ŸùÊë~ŭrúméÄÂs(o}Ŝ~w6B“Á~-Â3Á%frù8¸ü1bëĤŜ2ŜÇǐHfb R<ûGüŬ x˘]›]ß[ â8&žž?í!Qާ7x¤bSt73ĥ.lıbËzğkŠÖĥĴ,[ëşa6_Ŝ³zMhböëÒ&Ì,ëjUïíûß˙ŝîBGİ’=Êb2Ħ”pï_ÙvÙ ğbEċ µ;ğ,ÖĊ2wĜíÌyúšow³ĊCÑâ?Ĝâ‰ŭi›šYÀŽÄ≞yŭ*O&µs@6)à• q&oY#RêˆĞ„GÀá#Çw‹§;rȧҰ!³İ‘!˜›ÙíûèŭE˘y”Ì~Ş–x­xs`c·y+ĥŻş˘ôÉC·Ç‰&]–Ôôr—ĵ}k›9uùĥn,µzċ 6„-ñÍÂÂײnVv‚êxqG*Ġo…+৒é-TšËK¨ĦċiÓÛ^ЁPô¸—Ž÷EĠ)yׅzÔÜ~}ĞŜ÷íl_µĊĤr@ëìĈ6İ0Q<ûèÚŝ<à·ûĥCêÊ'dĞŻƒ8¤9‚ħˆï€ŞV¸Vxb¨È·ŜêÊ.żŻá÷kÇîm² ü”–°&‘™}¨tsÂAë“9 ™<;8‹4‹8ĜĠ~ğ€‘²X4yó„rŻö%şóñŜVVdġrı8ûŽ< "ejü*P|hÀ7PŽm^]Ĵ½Ż÷Ä<Ö7Wï8ßíš<^ô}û?Ĉ%j6trî` ]•Eµ sÈí{sï×IéÁí ލ‰’d„ Éwçˆvté4ÏÊÈ39~Ò| Ì&çQRİô„dÑȰ›sJC^‹sÛgĉ@µ’óÇ\ۓEû`›Ğ‰-$4ÚXN3œ‰|zgpx3£“vMŞ£hçÔ#y˘Ž O€}Ûô4ñ"TÄQ’B UAg)pŒĠWaîó¨XWëi"ÖíÚ9sş¨óÍĠ·zE#íèi·{X˙˘×sŻ•ñĵÇE„éñ6ĠFF‰š\b£Ê5´fğÁs,3< $éŸġ™B¤JşĊ³Ü ž^z4jY“c"ö­KԊZ&+”Ó)&£MĠ_>˙éËċ™†Ô‰p6•\·³½†ˆUĊbbÁ§Ô…Ŭ‡&‰ÂÑİıу?•5²Sm.Ԙ'ìòè>Ž˜.2ĵ!ÎĤÙBxaòa·+™³…zÄE7µ ÂsĠC_RÇÓ+Ô&ös2sc€ĴX½³Í…ÓòGXÍÎ{ Q£’HÎ>”àŬ _>ĜòiNœŭ݃]—…JíĜŝPëPSB4‚Ŭ˜Ö {cOuĈç³ì?, ԏ  *3ÉÂîTIˆ*#Óħó$ @ÂÓ#÷2›tŞ@â;H”`e‘½- ç6ĤİÑô÷ùƒġ˘ dgxİ ’1=ċ™œ^"Ş˙EĊu˗nÏ *Œ¸˜ĤÁħëgf7`sF;ħ€.ê5•ˆ°\%–=#˜µ–ŝĉUŬÙaÑ%E³/;JÉaô‹C;ċ./ħµáƒ=äemáDU/‘œ<ÉĞWZKdÂôZĉµ)v ca1+KâJÊ<ì­ëh$…4y?ÓCó 3Qšb°*“‚ĈFŬäö£ĵtü‚Ħ‘‚ç(<À_Rx3ç(Œ§$ŠBN‚’j*9Àévv•_óŞTtÖidÁÓ4JI‹ĵyÇn ’âË7ıËwSï7+ĝŜ+ż IĊQò•ÀĜ,:h,•û†.ĊÍÂí¨ o+˜ċ ğ[Ĵç4-KèÌ3¤3ştVíİéñ“ĉ“Œfê$&$€OĠ^ZµAÄPĝ í:xòœU‚(ñ30ävċƒÖ3œg}vÍĦâ^Í­–ġÊÉâ–ġߒ҄Dßĉ͆T'‘žŭ“œùàç9Ĵ˘iy“z-_Û˘ó‚5”şT’à`2Ë T²çò`×ŭbN¨žŜ|:"l6ì^÷aR³?mSX`ŒĦ\Z]¨>wI$¸”G}Í!œ§‚Ò]$Ĉ`pşäˆ×“ĈİiVŒG “$L”y-=yËH6ܵóBÚ2EgĜ>Gĉ ‹‚ò2‹DœNO݊ ˜éȳÂRrĈ3 RZMBÉóı£”}@kÛ²´gš‰cI­”Ëù h?@ß°{-JŒé÷]ğ^£a†Z÷@ÚQäzŠZl2Ĵ·Ŭ8£è?ŠÍ½“äuC…7Ï[h_V²ƒ#M^m^7<‚Èô§11ìB NA§K­ÉÊۚeFoNî Ž½ĝ+„ i¤î$֞D˗nÇġáXamİ<ċ8™Ç+Fş¤Xiġ˘(ïÇ<†N •5ĵ‹à&D @‘I|JİZIWŸPI&›Ÿ‡Ù<ĦĠnrxĞ )Aeúm.$Ï"Ħ4>|@UPná br…H/óĜŭÀĜs$Öž¤“›F7|‘&c4˘Ş˙]Ì2ŭ[•—E×´öN“ÂŞÂLĊ*Z遜œ•*) öĝh!ı×dYl.Aµ#ġYf^‰‚²á4S šÎ^3) ċ‡ċˆóYĈƒ’uJ3ôrRL—Ó ’Ù×ÓĞgó#ħL"ìÏGœ]:$Q&Ò7Ê#ˆCeĤ—&o|Ëҁ٭ӗ~iëHO,×bt};ƒîÜWÄ úĊ“W¨Ç£Idb$ ħEĜ CâŒ2Ŭ;§ 9@6>~ÎCĤ"a&WïñDB˙vM]ĥŽ_Kû`K7í ¤­íŠ%k÷ğ]Ŭt$‰/L:V'‡ġÀ/f‡G7Ó^ĵġBžv²]ŬĥĊ‚†W[oib%eË{ğü·ÓŜö}ÑxµÈ>_^^²BˆN=VKÛÏÚ ÷"ÀkÏWs7šÚŭ˘˘eżbùŭĦëĤŜ²Ñ2p;s›[àO´ÏœKŻïk(‚|ġ;VMD6Vbeŭˆ@Íu:J9JĝD†Ġ‘§Ċ‚nŽIXÌ…e˜Äö8>ŭÊ0•ò(6XxÇĦ 2lR[§ÊbPánx÷kš„2KŽ€"Ì\^ŝ"‰‘€ĥÖexß·¤ vyDîËĵ™‡FFùéza(¸û+렑B[:*qpp3N.~m†4&ŝ{ï^A‹ ××{ïŬ-œ.ħÖs FߒžÍjiRďђ,êL„+úİŻ˘gó•vĈdO$UöhTçÀô‰Û÷ϧ;ĊŬ‡Î,rôBÑsĥx›ìÚD ġÎĉ9+<K.K˘pcĥ(z4)u7V…ĉ}éQ]p{ÛġnZ…–Ĉàêħlw8k£Vˆ5òòƒMrk_$ĝÇÔÀ}y? Ğ2Cmö“y4 endstream endobj 49 0 obj<> endobj 50 0 obj<>/ProcSet[/PDF/Text]/ExtGState<>>> endobj 51 0 obj<>stream H‰ĴW]oäĈ|ׯ˜T 93~8Ow²b\àF´Î‹¸äì.}\’à'Éoùù½ž!wı+Qr‚àNşƒ´=Ó]]]]óí÷œíÌĠÇġĠ·‘Œ³ġöŠsàŝá"ñ£T²˜§~ÊևЀíµÎéە÷iË׿"R‘‹Äß0JO‘ž~êu]èÂĵĵ*á~˜Î?…˘k~ñĜcYU,гg6šñÖïuMßĜġżÖĊÑeR~rv MùûğÛûŸ?Ŝß­òqˆ0/$ÒuYïX›uÙA÷şc‡ì™22ş·‰Ĵ„e"8[qŸó(dëïé€(âööÁ-e=˘ö"gE>È9ˆŭHœ’.t~ÛÔ= ô÷ y ™ 4ŒĉħtŻËÛż^EIâ o½/C³Ó‡ĉĞ&G_ôP*t?‘Ñ‹tŜiLS?r!ĥ-uU°m×l˙Lß y?túf0ô£0#€Ê(˘ĜEgu˜fJ?C%ySPYnugP.{”̃4˜jŜ•_µaêúĉ?"ĝ†™V£şqŭ'JO)ik+m‡ƒşîÙĥĦŝÖÏĴiu—ġeS‰ï¤D‘òE˙aĴxĴäyÜ1€…Ì›-ëŸÛe˘ &xòòêĦĴûäsżDpMpŻ~Ĝl¨MıĞuÁ6Ͻ~¸ö]8úŞ"jQ|lQÇvHĵŸ*šK.–ueżÇĴ”9až—Û2·PZt·C‡ÏtĴ}VV¨ĠÍôAgvÌPúCĥ˘R‚sf×#À i:V?e‡ĥÒV%X× uA§À*Á⑎x„Ċ‚İ”ÎÄBoËş´_@‘˘Â0’VäÖ$HŻÏ6†"àçŸŝcÍcîAÍ Ĵi:MÓ^gܖ•ŠH,§Şsw0ŒmŠ7 ôPçĥÒ iòWH WœÊƒ0¤çïaCJ×C˙ŒÑ"VRÛ4°Fƒ‡9 9fñçĠP¸;İSp^İĜçÉıÌığá!I)rzÌĠÊ\ 6§Ŝ§šeEa;çj”Êçħ —¸Ó8ìˆ%Ŝİ1ĴÈúì¤QĝÉğrƒú² d↰z4Öm;rt6i2ĥëß%+?ħLÑġp…ĊNù%Y 3CÛ6]ïàìIÇJ"6İ“ s|CÄAĊËÙ´—,NpÛo3'Ŝc²'˜ŽÊú*ˆÂyù/Š~ÊuKıg¤ÜµkÛVÙÎÜ8ĥ–g‹ŭċZҗĜ.aŠM­’SY˜ Kƒ*êàçQó°X/Œħ•£W.ìğĴ]ĵZ"Óċû,fDM¤~‹ ĥÉ4„\]²p£Êş7'ĈvY½Óԗĥƒ^‚ÔÊâ×Á}ôSÛÔ´Ó.ċx#0LĜ ŻÇIÚ,˙’í´UĠ)fFt…ğHù°­µÚ<2ġu˜‰%~@…í›G xĈ§şNTPn+ë0 œÓŞáϊùñN-ğ>ŬŬŬħD…7ìq_ĉ{Ĵ( ĉ VżaJ(*aÖuMgûKÁžúà-Ğ{ua:…rê§ùùîxÄk£Ĥ¤Òó¨‡ë›Q7…û|à§a(ú<ŬçŝÙi+è!‡–žµA&AzنׁÇò=|kNĥ5‰Ä€A­3à0ŽġB<ĝ ëe¨“ïóf?À;­:ì§lƒċdфC#öáĈqŸÓ(ĵŒß­2ƒŒtnéaWsV•ż9)4ùÂ8Ž:6?gĥȧ*ÛaSÁV\Äıöğw<ğ×_!×Ġ›89ÁÀö8ó‚ßf=€£ß~7gÓ2.<’d Hh²"=’ëĥ‚ËyAû >‹ËdO„êĵúċO€#ŽŭµïöC–A-€véÁs‹0ÇéM 6y>tĴܲéùJׯjö˙h†Lħ§'šŭƒ²yCΔÂġ͢èÍ99˙wx†žż@­s÷Ħx|¨n4“Z@̂óG'ŝŭß°ƒĈ3ÉĦûaS7Ŭ!Ğ–0J!ùàÌÏMç{ˆ§Ît‡SëÑ rÉèÂf¨Äş=ïçş*żh;U ½ ™sⓣsÜ}ŬdNĈâ$Óù`—'½ZËzĉĝŠš5!–Ħ³v6?4Â.48-D;oİÁ§wuĠÎÂ>xC]ichŽ.™V3=×^öag4ÔÙUĴ„÷Á8Ğxƒž‰WÈd23³D“´Ħyg\ìkÁĉfFi&_q&cfÄħ†´yzôYÏq’ûÇúì ^‰m•ċzô…Ü‘"µœHY,hħL ċïŸş£ÇÁġJJĴ/_ñÈÂĜ&60—ĴÄpŠĤGkÛ´Ï]ıۓdçPÜO˙Ĉn›Î%,‚ XQùÊûtì‡ uCwĜûŝxáEĤŠÇ~šžëñˆŠş[_ŭ.ÀŻ& endstream endobj 52 0 obj<> endobj 53 0 obj<>/ProcSet[/PDF/Text]/ExtGState<>>> endobj 54 0 obj<>stream H‰ĴWksÛ¸ŭî_ôŽĊDżċá´îd“ĜğíLÜñe³•IIÙñŝŝŜ€”DJ‚¤¤›LlÇÂĊ}{îÁϽâä9y{}òóG8ıžpEŝâ›ÄrC ı~ĉċÔğzÈZ|F‘Í_²×†ÜċÇsFòçĵôÙwžĴì<3òX5-İjÜ:'Ġ,tkVäóiC². ĝiò–äߞ⢝ż’›mdMNÊüex:›Nğ€22ÏÚĵ^;\ĥè9ŻŸCïiàÍih7óh0=³ú~R´ÁÁ_şŝéMĵ£p/"‚§ó1¨  ÏÉĦYr“DĈ‰KA6_`;=7Œ%?…Fîp%˜‚ġ8ÂUA&ċı1†êäתÀ}µŻß¨6}ÖMžÒŜ×ÎBHIVëBxäŞÂÚĉˆ* #`)n£Eĥ>sİF1!u“.S'Ċ>@ˆU‚Y€y—ġS^ÏŞúÑçŒ29š&ŸK@¨›Ş%Ġtœ˘(×̍8sez´wd4/ÛcÑĥñM’•ݤÂùşsD^ LÈ`ÒÑßÄä]Œš–yËbêİrZĝœÎÈŬ˘ĊEíC$RhİuÖÍRêÌş‘ï/ŜŬ^–áÊÛ ‘†2EJŻĴ†­oíú’U”žÉÛĴ]€CŠĥĞ›äT[fĥÉ£żs6˙ñ—$2ŽXžbDJ• Î÷˘0TñÑqF…ÔË­îëñU*ÁFL×µúty}ûöÍĠEÄŻHáĈ°mÇZÎz° ŭ‚#ŭ/Ŝ|şş$˙”TXÈ •y[„zÎ%µ6MÇèŒġpowžH=Îxv;,—ù}ı‹ ĥHħÒceB_׉N‹û˘I‰ĉ[6ĥÔQwĜEˆ €uûƒPÂԈí òÇì[ ˆšCSˆ­Üî:4 ŭ²1ĊœËˆÄ-˙œ †hğ`œSǀ °-b­ĞE‰BZyÇ2RŻ,%WÔ@ím9˙òù·Oïo˙öĉ‡Ûß~5Í jFwgÉŜĴ•`€ –Ûžğ5I!o­#.‡‰Oĉ9ۓ-ĥ‡³İÚèSÚi',/)À0 ù#ŻĞ›Ó³%eîj—ßDÒ"†;ġ:îĥΞba ̀ÇħÑÊ˙*ê‡Ĵ âf€ì”k(wÛŜ=\ÔuUG+Ç`˜B Çbù{¸`ŻFœ+:ÊTív˙Ċ5!V [%‡ĥÉYlƒ÷ë^á;8/œí–Jŝ-›D·¸˜S7²:‹í.Á0v9›.>BeŜîċ*á` MQIĤDû *!ĥ1… ÚħíŞ‚W‹ğ"›G{ȨÖGžyßCÏĜ ĝò˘” f·ŬOĉÙSÌ­9;wğĉvÖoiô˜§ÛK:[2Úö*ŭrh ĊAżi§s!|ò=âàÉG&C½êĠ˙Œ<ĠyU7ˆ²“çšö¤`FAR Özî³İ+ vÇRqizŒbšÔLNJ?\ŝòĉ£1~ĉ^ µÛ;€:’ Y”Ş!]lµ ôi´FlmĴŠ€ôËĊdë˘)Êû5SğTnèb){‰uyqqARz1ϛB1,{œB‘<)†„RQİ=VĦĝÑħcĞA`[×P(~‘Ét;ˆ} ĊršĤú11ĴÔ2wnĴ–_֓>dÌ9Z‹š'Îu€cŠ÷´Ĉ[Ĥ½€ Órd2}ĵF‘xLyoxŝo´Sçħ˘wùMœŜŻK@ħ&ċfËÛ>5ĉċĤc£=™Ĉ]n=iUĝ>ŜkAvñûĊ§XɁR“šÑž€ôaE&,4 ¤à–÷½‚L`²•Sğîc$"ĥbcbhŒoGµOniìvÉ6Ĵ|TfU?!’ĤVnHCfm'áG— ^íäev7ϧ~Ùî§mj‰V`ҝ3Ç­Z<&ĉùhäÖĤċAgDë†^à¸MçVŞÒPiVòh[;uġ2fcáŻVq² ™zŻì.·T3qôÂ]˙î…;0Ŭıp:¸pwy˙…ğIżp£Ĵn$ŭcSîÀµže\¸^úûŞ0MÓG/ܔ 3ĥĥµ>ĝĤ$™zho†ħoċĤ½VĜ"Ŭ˘çhÍGĤMÍpzÚÏÂԅ—„€ĥĠ,=nςÛĴÏ˘iXĵĥ|G7-w0f·çĠîC>ß _ê.”ŒH&áÀ#P¤(9ç? €…4~ŞáI ĦsH n͐а ŠK‹ŽŭPjbtuI?†…ĈccӝY£<Ñĥ(Şwû>šƒ¤sàQÍ·è9(î^iPŽÚ0ġÄ9KOŠ- J˙l òúÈQ͏×üž‚ĈVû(HŞc(hGˆbMAÒm,bÎċhħ„†AEÓáŝÙKB^LV~ż“ƒ$ÖĠĤç}$Sk7ŭ°%HôÏĦ ÀG ùQúŠž‚¸—ZÊh•]r—ĵ]Ôe!nh y(°Ž<ïúË&UÙBĠĊ˜¨ajlAğ³ĵ?+ş³‚XAÀ‰TşŒ+ŭ†‘×yıÊÛиYú=#Ŭûàĉ4żU§¸µ'fT§­Ż‡Ù˘œ´EUzh,Èl`·*ÑŻšdÏyĝŭ¤Ş!ĞŸŞrê?Âİq—oœ¨ÀwL8”ùû^G ’bl´Št™/Ĥ&oY6Żólú:H.–›tTAS€C¨g´#›i eéĜÊÇ'†ÉŬœúí5’Ïċü5€mW²Â`2µÜìi?ù3ô^C£íCV†{ú4W › q:?ƒv}M~ÏëSpŠç(âNÏö i;4"/F4×}Ó}jïŞ§×ş¸hñF›àivùöòŞŸŞ: aa> endobj 56 0 obj<>/ProcSet[/PDF/Text]/ExtGState<>>> endobj 57 0 obj<>stream H‰ìWMsÛȽóW̑ڒfç  9ÙNvk·ÖN*brħĥR8ဃÓÊßX˙àĵ$@˘”C*‡”‹e‘…éé~ŭúġ÷?ŜJöP/Ŝß˙ ™dĞÍBJ&˙YĊĴŒyÌVğ…`ĝĴ҅à"4[ËĠÖħ¤zhwhjüċ~wµú„@AHt„$$FuĦèpZûÒt'ž\-UÄX-ï–Ŭáyxİ×A8~ĝríÒwŭ7ĦËï~]ŭü­Ğ”08=ÍXÇċŬ·!–.3ÄĞXS²•×MĠĤM[9vĜ–5}OšĥfYMÜğkxç· #Ċedä ‘.À@ĈÇ.#2yşEúZŭ}òHàŒ–Ó̸”‘Ïî)qèn‰Êí>kXVŠĴ>²€²” ›4,auöP$9Û&Ċ:GÛ,Ŭöß0-Ĵİ’=Ğ’Ĵ™î§5úrÜ—ĥ—/µğŭ5Cp°Hğ™İÊܢò*ßnĥİʝ§ÚÍH–?5#‰r%;Ŭê;?™a˜o(›ŸË ñn­uçïǰ—m•v­[“T´¨;AÉy^˘]ĝmçveġŭÀ]+xG*ٓJu¤RDÚ@cĵ Ŝħ&¤ŭÖ5·ċ? ĥÛĤ˘& T½&…ö]›!-Ċ§ġf>Rqż×ĈíÈúb MēdD²AfĉH‹ˆcŒĈ—\Ö&­ ·ĉIfÑXšH%’‘ü\#CR ÊHv]ón”ĉQœë‘=yƒž§2 Ž#ÇÚÖĵ*;x'£ˆiyNqî=A(m“zÄ  ì€ŭĉJĞŭœÊ ·‰nÂÑʤ9šùšé!¤bÇ@^³ˆ&÷x·ĴÜCRѠք3Xîu¸Żħ—xÈÚSh~ÒBÌ+l„ÇÔ&m„~GÌDXB½tƒ Ĥ§FĤЎôŞK ]ĊÑX·^eŜŒ˙‰ÌkÍÛèĜeĞ2zĝ?0o ˙ ĉÍ(²ğAq Óİàqzĝ2Ŭ&͛œGB†¸$4Óܸ s4Ĝ·^ûm´kkšXĴš$m ìîŸ-6Ê/‹~í²‡­dżÑ5µĥg+Iˆ^  sÒĊ°ċá }6Àü·¨'`hrĦ†¤>ùrÀ#’<ĉd£%'!Žù.ż^÷İ íÇôUDĠ:Ğ2îµŭ( ´óŠòLB¨NLŭš:Q‰ħgAlGuoó&ÛçĠĈáċj­âĈÈxè˜7U 73ŞR6š8žqH•Kˇ"û—[{”zCŽUN! jŞÊ޳y—öqì—ñB§İ‘·ˆâW8Íщ‰µ…n/¸3óĞD e'!.ħÒ cg/ArMuC–&ġ1‘§]ÇÈFxáz’ȇżŝò˜=ˆT<@vÚċ½ú+”ÂM=¸úYNÔ&ßûĵ—¤­Ïšñg=ĝ`ÔÙ˙Íĝ˙WVòħA™Óù£ÎyĞure}×ĤÎğêĊ#aû~{ÏnMcAŻqĜ£Tcuħ… ÏÛp-ƒ§iÙayb/&lÛî’↜]rŸ“GÓ*Ûû\½#?½tŞ(#ƒĤflâê´şúü;Ĉ!ƒ˘ħ 1‹ĉ)Ï'ĉ ˙ŒuóéġÖmtì²U=|fŬB‹•ġŒy  Cr’#ñÈğY£^ë܎/2DôNħ7uç~G]ˆ‰ÊtO}4':äĈCëeilŬç6‰/jLĈd°ƒ—zwpQĈÓS”œĵây{––ğ}aê¤Ù§µv›ŒÊëRëŭ=ħ7²3<ۂŻÀo“ċnvY\ܽ£Á´ÀÑĝĞH^r&H–È€BFŜċ*ÑĤ§ŽIŒ_ÏöOÚOóŒ“BÁól:ÇhŭşàĦ ^§İġlù:]°7L´Ħ0s­ġ;İS,ü\™ßž<­ÈŒ˘—Çżˆ÷Ĥ •JDħA< sJ÷ĴTdòÇùŸŸàùCË”{öñWÁÖ É2ĥ€ìH !"Ív RĠá[¸]ĵ]-BŸ@Hò$QˆûeD÷Äŝ˜Euİ?3:DÓß0ŸħĈvl=`YúĠv żşi½F@†\Q÷MÀöĉ5[V҆%]gy9ĝ½Kku·/ë:ğïGĉ¸ÑX)Lšâêv4ş—sŬshĴ|lğíŽF¨c‰EUqx,İçÖğr˙Xùw.ĴP윟ŜgïÊj_VŜ[Ѥ…|xĦ}ƒ5áĤĠú<ĝ½cЁ„ Çj¸'£Ÿ˙`VŠï~ endstream endobj 58 0 obj<> endobj 59 0 obj<>/ProcSet[/PDF/Text]/ExtGState<>>> endobj 60 0 obj<>stream H‰d‘MÔ0 †ïŭ>ĥ‡f’vú‘#;0$¸LĊe—ChÓnQ'R°˙'´%QâĜïó:‡÷Ӗ> endobj 62 0 obj<>/ProcSet[/PDF/Text]/ExtGState<>>> endobj 63 0 obj<>stream H‰œWKr븝{Êi™M v’ô§^ž´Ğ2xN( ’ĜE‘ ?vğÒûÈj²œ €) ĥ“zċ²ŸÜïıç|ûó/œíşğż<Ŭ}ûSÎ8{ÚŜqÍbüŻ,aO˘$ŽñĊá.f;ü<­ïâ(ŽcÁž^ï³~+Ó²C³*s˙ô+, o‰;Kœ,i)k&â‚çööÓŜ°K ĝ`[ÖĤc=}YôëúvX÷CkĜ™ Û6-kÍħ5İû²ŜħÚ^ïXY³‚üÇìGà T)(nX7”}ħ‚²ħnÇĦ/ú²İ—Ĵ¨7ìĜ6/ċĈ{ŜġšêìÙĉhÚÂ:kj|Ŭt†½Ġ`şèäPi-½Ï8Ën¤wN£ì`°/ċï>³Ŭ–ëéP kÓuÖÓiVúbŞ7Öí›ĥS½Ê2—Òz|^ô!ä~¨7­ÙtdfSîÊ{˙žJt,Ú\UѲ²gEU5Ż.c—oËßUgc;…ÜQÈëӟ¨™ĉäîëâPÖ6Ġ<Ù*š3Ö ċ‹îr`HĜbœ‹ZÖÖ§kù’í›WóbÚ%:t<"Ñû<ŭÍùе²™íŞìÛ˘}C‰Ìşì`…mÙïé°çĊpd}ò<_ú*}y(*Ÿŝ’½â43ż›•î˜ż0fċàì+uĞ­<êÔVôˆëTO[ċbÒë]ĤüÜ8(?ħ‡˜ Ӝ§L Mŭt‘íusÂB`”„J£\\Ü=‡4÷ċzO£şrW—0HAŒĝˆÌ>$*Êc!ĤJs7(bË÷ÂçB#üœ)•DıJÏяĊ „Î5 äüŜÉñךècŻ7ˆ¸÷“x6ZĵİÙêÍçg#”܈O&9ÒFŻü¸ĵ2“QžèЏs8Tĥ2ÖùƒH£4Éġ¤‰çĥPġċħ*ÍĉùŜñË{Ġ"R’)Gz/µ/hóHëÙĝÖı‹sÎJÛxOôQmv–W–Ä1kmûZv††5QNwù¨:Î&@1bZ´¨ ĉ“dXh@˘£ÌE·°„B†‚ŭùù3w£êÍeĝ_ÍvH ñŬŭCšĤ‘ŭyH¤W‡€TœÌĜTŝ™@GbšÑI üù~–pjO§LH%:Ĉa!O‡ßéPçe63îkİŬá8BÇQôĊfv°Geîż 2LšE)0<ó ôƒŞÓìâÚ˙ĜĴ{<žOêX6 I2,ËIÙ>E$2ĊpĤ|^?ËÙB!ˆÄ3·ı-MĴÙGŻvUĠ5cv9J˜f ÑâÜ×EwÄf)Şû!%6›ĥËzLAׄ˘‰ŠÇ——j äÒNñf½² "8ĦU”€6/C[<Ħ’Ċ×W&€{ÈĉJD”e ij¨%N×EŞÍĦ”Ğ0Żq9$™ÌóˆOŭ×PšàšR=żtrhC…J:;ğ!Ĵ!è£~ß6n?QÏ÷ÄnÁBŽf"á×ĦÑÜX°’´n“вSxm.uËëKn–փ+&–“Ĉż%RmàRĜöŻWb9SŻ›ĦîM{Ŝ$³äöéçÎÚùw  psݘÔ”•}QÖÛe˙â*´ó9żf-ŠQßù°ÉÒP”N‘˘<6•^úm›Ħ…Ĝ4•Ó¨ŭm­ü] <($vFLƒ}˜‰·¨À¤4&·ì…€ĞHĦe³ïÛÏ0_jvaĈ6Sjm_”µFeêİO>TZyWé~B*˘ŬZóÛ1A" s×ı/-E’Ÿ+9$‰Ìé-ŭiPJ×ĝ·)ùеpbÏäÚqY÷"ùg(ñDéˆ+ÖM× 7D‡ĦëÙxĦ`)wDf[Ô;“žR,ÔÁš-ƒıšĵ6B# ĈĜVÒ ġòXèɕwQŠ—•Îŝ'w*™]Ħ÷c–Ïpşoh,İ£ııŜ‚JX|ÁhğjĦ—^‚=ĉ{ġĉxĜ›Ż -ŬĊÖĜ€¸[s Ëŭè'…ç! l@Ÿ\dLä É'[ıĜüŠŽš Ö2ä:"°™%ġ’pjéä•ĉĎ[ĠHá*Ê ֘Ü.Ĉİçz"Àĥeoߜ€U*oŞ“1˜ž–†ÊXŽ•­‹]ËÙóô´hŻ…KڙyèàÔ#!$mıŠqjur+oœ ŞOkġ›É‡Ï÷Ôŝ\şwë~†Jy†Ž/È4ÇNÀÀµC}BÀĞ}XµĤéâɂ 5‡/;8˘˘˘¤v4jj+ˆŝl›ÖŒĠ:³œß+ĥÖÇ´á†ß…ĜÚK§wDs ›OJPqÉ ĉ>š5‘ƒ†ôìŜ⛀KĵfG§äêŽq~ÓÛ+!ŸÌfĥ¸ßĜY”e‰ĵĜĜ’;^ü;ɍw_İè#`“ ġ¤ĈÎeèMĠbD íÓ[ä2 §*v#óÒz„1ûj]²][l´m€ív[5ݘ’šܕŠä:ÀnXĠM |@ğÏ=ĈȵœNCN",SĞÊl0ıH"ĝâ§v]tféĥz´:2„ĈiígW#bˆ/ĥÉÊĴ›tchÄĦ04PŸ™ 1<à(C–&‡'p/ış¸ò‘HM‡Ċìó"$<ħ¨Rà`vĵ.;Ü, *ċ@<Á`‚çSsh˜J,ƒ-¸{Ç7šGxOÌïÛĞ1ŬiÜÌ‹³ĤħŒX½3}OxŬĥÍÁoċqĤo‰˙É|5öŬÚӐZقD>'ے ŜrġiŜâ)=Qĉ÷ĤZö3 #˜p}íúᆍ”pĤ÷ïH+‹+™ÙcЏĊ˙ôĝ²J%êÓÖS Ŭ0;Në4VÒ˙plíğg+Òûr½ġmʵ}Ê˘³ÁGfœÍ]œĞĦ=À³Hòë°Ò›úĉyÁ‰ġaeçhrW–ÒnŽ 9i,÷lvĠŜšÊĊ’ ħÏĤK‡™OnçŒ a‡Ûq×yĤbމP˜ĵùì”4:ĊÒñIY­.äÍ{Âb"%”d@¨‡òG;JcGĊ³+”P&."8ċ´nÌv[KÚî‰[ÔoX˘Ċnş\cĵ·¤éċ5>b•Rò"“çĊĦ×ɤ9~a‰ĝ\>h ôş˜žEqqĤc’Ä8•ù/áUÏÛ0D÷ŝŠŒ^ÙP;0ĤQ‡ÙŞ.,׉­¤&gÈżï;S\Ġí€ÄÀÁ}ñŜğá4vQçĠċħúq*ƒó=ЕܨlǑ'OùŞ˙˘?‰h0 9ùOh ħ˙bLLĞ˘Œç×"Ïħmx+f:c—tjŞ’‡›ú BC-ë Ê0JÍ<(˘ĝœ}@Ò"T ~ı­Ïqù¨ ‡Ú]ùCŭ(ˆ)ÎAÌsÎ5QJ›¨Iz;Ŝ.w5dkibEaq[˜‹şĥŝŸñ҆‘öi’BÌĤÔżgohêᵔr#3Ĵm@°-*oÈx^a´ Öä”à+öĉz·ŭİ#XnÔ/O‡ĠŜĜĞħV"ÏĞÈ;€¸?ìŽĉxZQµžı›‰œ‚z~}ĝ`œlÌ8 endstream endobj 64 0 obj<> endobj 65 0 obj<>/ProcSet[/PDF/Text]/ExtGState<>>> endobj 66 0 obj<>stream H‰ĴW]sÜĥ}ׯÀŞ#!@€d:}¨?âq&ötĈr_Ĵ¸_çÜsż{óA°u{öâêìğ4ìêöLDŒŝá["Y"2žħĞÍYÄÖĝşZÒ÷g‹²Ŭ_ŭ#Œ„7LȔ›L,Ww–ù'/-¸Rztĝ‘‹M̅xEÂù„Ÿ¤rŽħÛ–+V´Ĵ,Ğĥİ›ÙçI¸Ò“(‡wUѵ3È4ċñ$;şRTĴ´Ġşğc׋ú–uûmï‰9öD‚ÇYò '+ğ|żÛÜĜĉ#\šñ(Öìċ‘KÁ‘ –WlWµĊş²+şàRáÓD&ìRpapè׎Ug×ĥı>'ğ[ÖU—UË:ÔqUĴ‘FÑÌWUɌë8cI”p%"ăЗµ½½-–…­ĉQI̵9²…odŝiÁÏ/6\,^çË;F%bŬ6ĥĊ…}ĊÏúñìRJŞl<‰P ԌÜp=bĦVDD’ ÉLs%âçE$$Ïԑíà˧…Kò]Ŝ²œŬUŜìÙçĵÜÙŜ£&ŻÖ–E>*ax‚ÄNʖ&ĈyÒŬ5ġn}w'Aç.Ġܤ̤ ×r@5ӑ"Íx$ Do°ĝcš™ĈY=9<òL\°û;û cĊU–LÍÇΝ0NyĤ“Ó“Ó·kċpC>”9÷}CY§|[ۅ$G¨—,;gnösè1J+‘\“òß)WŻ^ż|ġïç2–Xèxlâ ¨B׋ÖZĥÍQûX\Ÿ‡Ĉ׎LÛâW×!’EğÉËÒĥ}‚ŒË bż˜Ŭì;ÛúÀ4— Ì<½öqWQ÷EYö€w—nò/Ċf· )şsÔê?Ħ§9EхĤż˜MŬ…WáL‹û6ÛĤh‹jŭ8Äbôr¨nbù<ˆEèUudKôívyÓ!:P1ıPÚy">,pq^u>‘×4}(×=ÖTĤ§Ùiì\:ŭ²´ÛÎçŞ~ĝÒ ]z Ñ™Š%0” fdÌÓ8;„˙x#Ċ`&¤\OìGşo|ôÎ$O¨,><Œ€ÄÈD¨žŸĝàïmSojO/3î˔Ügd‡žzŞ÷J’÷‰žĜ/ßŭÚìŬŞîĜ ĜİEĞ#—Êͤ£˜}tŻĤîÊŻhe\šUbŭêy \hWÛÔŸ /~²ùŠ:ŝ$ö”­ûÄjÍU2EÚûï^½}óöêÜà‰"LÑÔLŒyĞ,(-Ï£HE+‘–v-Ó=1ǵ7³Š0ĈYĤÍ7ı9„KS=í4çbċR4;€f`sb˙8KÀYÉ8žy÷‚B*zy·ÌäÈV]ú1A"eŠınŒž6žï~ 9ŸW{–o·%(ĥ+ê ì9mѧ3g˙Şêûj˜\ASSú ´xÏŬN$3—€Š&œ^‡ùŝĠf‘ÄBÔ,;Dc˘žß0%Èe(JGw—wÁ]Pž#×_òÍĥ´ ï(Zˆħ(œ"ŭ‹#O”OùۊĠ”ŸĤ>›œD&”fM|„2 ‚t²ÈÍ3r £Û:uA^ŭ…ŠI8¤›·M½nòÍĈ6˙n!ÂÛ-jQÜeÑí)[µ;TĊĊä DĜîúI@΋2ż)ÈThż†àîU‘wĥÜ£zeYß÷ bXˆf)F/҄Ċ‰r+S(›hdĤ&ƒ/=Ċ€ċ…À‚%@`›P>hÄ>PÎ$yŻÓ’_ úŻÛÓXŠP*ˆ•f·ì½6° ÚŬ˘,¨XQïÚPÄöP’(Ĵ5Zé&ß·N˙ġˆžµ­l“Cßċ­%ìC.Ö"xÒvuC]ċÒĦH‡'z·Û|i†÷ŝBpIj]uƒü {–ŸİXOX1T—#ÓŻW ĞGµ&&\괟t9âsá|Ĝo-› Rƒ¸TrúüÛGÄ2×: dݤ<ñ¤—`×à$ƒ¤Ħ›ú]#YàĥGdPœ€rŞ£QÒW¨ hˍl6'È42 #MütEFNâüĜnpâÓâúüÂw‰*’Ñue™-íŭ|¤Rpıx{;+Íâ@JŸ:ö¨‰3ĴXZúĠ´²vö81›ĉ1Rħç•[{ìûŜ=ùlö+ŭìZ³Ên  ŞHÀAîZэô½:$—¤ş{ċZÙÂAì°ĵ#^]Á´Á•·`ÂjiWN1j8šşİÖní²4]Q ıH|ı-š6, ‹oŠH’~tj.´rQ'#ÖI=7ĵu{˘ŭ‚‡:ğòĵ<4w#ğvNĜ;ŻÁĉކĵLÀݘ-Í[ż8äŸRPh²\7›œ´{ğ#k‰ĠË–H ïXVM<˘:Ĵqĝ<‘µF0& -öVSċċ‘gÈQ|9‰W2Ŝb,–ğ2o.háĈ ñve/=\÷ârÎ@~)€:£EÊFëhĉ;4>îP°ŠÏRŻÂènżŸ4t4V6&£7Ċ£‘ÁV-Áñnĥ=>6™˙{šÁñĊˆ;fÉΈ½ĈWı˙RĊ\GszÇd0Äĥ5ëC½ƒNG{5é@b’ïç˜"Cü&ĉ2˞şû`4SFF×˙6ħPTìôô93W—Š't %”IğQ Àjn6•p— .t¤Ÿ,ı4²ô5SŸ4×âȧ›ÇR„ëW¤DˆçĝƒŝÒ4cKçOô%ĤIj‚İGLñˆ†zێ8]WsHòäÈÒŭĤ.Î/ ifù{¸àäeàUF†kyÔ§‹BfÖP‚ŽĊÄÜçbœ Ï=8ĈcX)ZI> c£çaáä9ñ'aA$˜äê[°0ĥçû˙‚‚0ÂóùP[(DDŒoñ·@aléú-úŜz}…ßßàëGœ˙rAcÑı'ËwìÓÏ[ V°3‚ŠAAoΰòż•gÎ^\\îg$ ‘1n@ıÁ˜ıÏ2–BÇ(6vĦ£îîٛïë]GŠ “ğWěb}×Ñx¸)֗˜É>ƒ\ÀJٕ6üáÂ-Ö×°Mˆmì)/²žDH‚ÄçîŸ^ğœC˘ıĝJB.oš:Ż‘Á ˘ngfYú+^ÖÛ}üğ^,ŻÏÙÛïĜËşÙbo"dÚà€/ŝ1ċ·ŒtHƒċ‡ƒŻ}š´Hx–ÉŝA—)BÑŝ'Àŝ"u/ endstream endobj 67 0 obj<> endobj 68 0 obj<>/ProcSet[/PDF/Text]/ExtGState<>>> endobj 69 0 obj<>stream H‰”VMo6zôݘ£\Ä\‘)rşNv‘ Tí%éA–h›…> QJ6Xô?ÑßÛĦ¨ÄR-Nlgç͛y#~ĝò;…ƒ]}JW>G@!ŬŻ(…O ĦŠ(HĞU|ıûġ° ²ş€uú7˘Äˆ =*I“32ĝÏʗÇÓ0ÄH!&Ħ?ĝ‘IHʧ—ĝ>äQB(ò‘‚ù>œêĝœŸp·Nç|vßӆŽz&Xjò. Óp9z._·/è0˘\à„Niû%6Ħ$ *…éğĝ0’ĵ„Œ…˙ĝljÄÄ;S†ôÙ0°—z˜@ÓÔKZaèâbàĥà!&‘ŠBìÌ41ôÙGùR"F¤LĤHÇgìmú%LTġĥG ´:oŞ~Sj:k8{Ó è8f÷ô~ÚĝİdĞ—oÛe‹ ĤËjœÀ:Ğœ¤N·Ħ‡)pr,<öX.%Ñhò8úÎvgĝ¤ ñ 2]§{ƒ¸ÛfvѳîT…Sĝ21zöĉêËR”@{;wàoÍĦv˘)ÔïoŞ6ÙÎO#}êwÉaß×ı˙Ŝ™ Êòĥy–òĵĞĤèKÜDêÙŞĴr‹ïOuŬ˘ ñÄġ&r7€À=áF`ârâ5HI"âĝ íêcŝˆmszlÍáĜĦSrĵÔ\úĥM{jÚlÚZ Î8~.K‚-˘Ġí½.˜ršàUdF7`ÌÉw•ŝ`&wC endstream endobj 70 0 obj<> endobj 71 0 obj<>/ProcSet[/PDF/Text]/ExtGState<>>> endobj 72 0 obj<>stream H‰¤WËräĥŬë+°lĊ-AWĥ<OâŒî$‹Q*E‘èn$l²‚Òh™oH*ߛsÑj15Uħk^".îûœƒwżŭ…³CóŭîĉŬ‡‚qĥÛߘ…ĝdËx¤lwş Ùżvŭö|³ù0´•Q]ÛßîŝSáMı3ċdšĉEÀÉt³;JĉÎŝ\è΅ĴȂ0-gkY}NRĠÊĠ<°If›0ˆ˘¨ °>oXß ş’lŻÉŞ5j{fÀyxlTĊöcàĴ–{ĠʚİÖ~?ʲ–Ú·Ùŭîĉ.˘,OÙ'7?›0ċ6{$ÔÓġ§³Vö/í“Ô½½ĠtĴlkĥ×Ŭ‰ġFĞöoíŭVĉx’1tgİKÄÖîğ“¤dwż‚“0I„u2Ġ(ó2G™âI ‘-ìœPÙ4lß5M÷lodÙÂOôÈŝד1êğ|Â,Œ]Ùŝy{Ǔ, òÍÏ[[ÛDÌĊġÏGU‘†dS(Ħ2ƒ–={Ĝhı—Zĥjúĝ‚Äpö0ÜÙZFÏy(%OÒÈfy’­y¸µ×ĥUd§V{…;†aÛŜ½ĜÏeÓwĴ?ËÊ}F|Ò†ïCcĉXKù°qÁ+*ÒsùÒ3dyRĈÈúáö˘Ĵ>ĵ0‰µüyodğ]t̗ĦCħ‰vhĥ™>šÒM]_˘SdĴ*ÛÉÛ芇Ü5á‘kMÉuƒĦı<7e%·ì ž0GLaÜş'|…·}§O%JÜŜ%YD›fòKy:70°5÷!rĞ#sŽ|BëĤġċb·ÂÀÜüĈŭ<ž†İ˙²b1Çżù†oÙS HœNß DĵH–ÉŽ™FèğşžflKġĦö4 ˜\£N˜Ĵ}Ù †9âE|Qˆ„G˙_b/+ßÀ%àEñjqĝˆ7óâĵ/1c&ŒúÓ3e0iZJŭ2Î6£—Ĉĝ2YˆÂ°nÏşVÒvjĤµz{{Â8²‹ûjċÌÚİŝ[V²s§Z[:Úe ˙<ˆĝ‡–ĝ[;[Žħğ´gŸsÚ<Œ’Ğ´żTòLfh’İ•Ç"l‚ÔşÓ½Ŭ]-ϝ6Îט~É•ñèë6yMqÊ‘³„‹ sÇC”woJ3ĴqOœç LċÒl<0^6Ĝħ½ƒy‘àeyóĜ··d‹ cfïİ]_XĜë%È ‰· Ñ£œz–.ŠkŠ€$xĉˆ<%_ÉMQœEri5Ċ0RÍĴ —'AQ$é+MÒ+ĠNêïQöf) ·@şQÑ[Ŭ÷ÜQ=ğ |Ĝ´™ÇĜÂÎH‘;$°6GYŭ}–ê+† òN’ ö~íĉGħ€]Ê/ )1ĦġÔâ8Bàh!4¨è ‡Ĥ™ôı\ìĞ+À™|!Oŭ[ Ĝ –²×J˘ ÁËP @áâú_äÇq@ßâ<=&Èç1vÈbúě?{6^£Ħ5ċı¸ˆáëàçyĤWÁNC˘!îàl‚Ÿr„Ġ{‚ĥ\b$‰Z0ê’Ŭg´ ÖXüœÓj ÇÓ_–(`g˙2RD£ĉ[ïĜ½VċĦíz£*lB‡i›—oASf<͗(qžÙ0,Ĵ;5kˀ”fëĴA.-íQ -UC„ ı+Û~Nî—Ĉ×í˘Ŭ‰˘SlkžÌŻĠ‚U&öĥÒhX9‡ĥ@ J6ú:…B¸^Í!·=ғÔàዢŬ/‘§³UlVçVĈé>d½—K5½J|ß @숀Ô*:‰ë\:X ƒ³{ûĤòÂd [騳tş#-Óz-~}rRÈċ‚V÷ş;á b´ÌÊħ ۑ[œ"1|­„ĞcİËÊ8&‡ıϕû8#gDqò"˘êZä˜ŭßżXË?Û)Ê‘xl5wžĊ‡sî~Ħwô[*êĦwĝï*B‰½œ.JB|bHEċ1é#Ĉàtn¤mç$6Ü#eb{ŝz( Z)ŒjŠŝ¸7ĤûËr 6 ŝĊ…ÍU.;J]#ïVĉx’´×ŭYVjŻŞÒ½iíb‡Eh? %´ˆŜš’•_P,v÷¤jŞ-°—˜eM.\µŽ%m;uĜé^ZëHPĞ„e.U&ŝóĠ²(ÇH .ÛUÊÉQ ´t\˙ÔħC̎ŜbÑ4CAżÓn|ŜXĦ™‚^aD7ÒĈcqwŽrh‰<ƒâêPˆ 3PBbèŽĜÀÜ^™-ĤÏaáŞ.Œâ4IŽEVğÎĠŜ·†bQ S´sĥ˘g™’÷ İç)¸Ĉĥ}ecŒ`Arm%˜eáŭÈÖĥ …,ì~ŜüÉMÔíÔ2j_™w˜9›ÜÚ eèÙ4޽Ħv/îğó‹V‡£+TP:ż˙ğï4hȽNÀß)mhŠ ß|GE‡{˘ İŸdx‡Ż‚LÀ˘#uıE‚òyżğùŻ_ż endstream endobj 73 0 obj<> endobj 74 0 obj<>/ProcSet[/PDF/Text]/ExtGState<>>> endobj 75 0 obj<>stream H‰´WێÛÈ}ŸŻèG3˘ÙW’û ëġÇĜĠĉe&Xp¤–† ‰THÊöì‡ĝ?ò‡9ĠŬ¤HIÔL†aKêîŞ:UuêÔÛ?˙ÌÙĤıù~qóöGÉ8[Ĵo8g1ŝàŸD°„gQĈğ›˜mwħĵ‰#a2Í_nfëÂnWĴ}²µ]WµeUûÄVĥµġ(mCż°]ŝµĜvl_ÛeÑUÉp”Êş:”+ğbċa÷hë†ċċêvñLÌy7~€XkéìĴìúĝ^Qş÷šâwËŞµûne—Ŭ3Ĵië²=À—ÚŝóPÔvġŻê4ôl+y½9ìlÙÂpmż£3oÔ!ŝĜÇSü&áQ’jùâŭġÎ"L&‡·f3ĜœÎˆ¤6÷³>”Ûı‰Ù›Û,ŝrÑR–â²™:"v?{¸ĊĈDzöİ*Jd„µ•êˆxÄgÛ²u]í܏˧ĵΗ­²(7Q0-#ĦŽÀĝ/Ó_z.ŭÙû9v;× Šñ &&¸–#עXİ"JE③ÜÚ Ħ‡Ó‹§˘ağCÓZ9ûœo Wµĥ.–ΓıDi%rP¸B†,ĝ§îXŜ0_+XsFóŭöu‘·HÁ­ħ.–y‹ö€] qWĤŝöĜnYY‘ ÎäâM=ßÂPäiâq¤2_ŠË qm_ÊÑàĈËI:vĊû.˜˜›D"†É\‰XGq:2†\e:;&+QI”ž&+„0(/OUc§êT‰8ÊD:2)Ĝm3„˘Ä›Ñ­Ù›ÀXi)™[°ÔÔۄKœnœWwDƒS†tŒBSĉ< Ž}!§šè˘³Ĉ³dÀß JrEĊgG|/—vßĉ[; nòÎ~ŬW%˜“Ġyıħwq÷%éóq9n$Ò!˜NM$VM›·‡İL,ŽL<ş˙Äĝ2a~ĦA z 5RÛ}U·pê™Ùşêŭ”€"ġìš!l²Rb%*ehÉ£ûµµ4İ&k%‰ŒIϙ։BÊ=ĜÊġDBj7jtĵ+ú`<ŽR¸7>mW˜8µŠİŬ>O™FqĤ<ùŸ-K.q,6£‡>ĉ'ÌJÉ£”3<>ȃN9!àΉëĜKÔ9ħۑĉŠ'i‚üܓàÔîİÑu<Ëĵħ·$\è½ı‘J³l(œ²,ġċçğĜ<ħ¸ù_lNú/ŝnëÊ)!êġĈ֟i¤Ì­#CbŝċÏ,ß6U?}`Céc½ŸÙŞÈ7eĠ´ĊŝBíÜ8£Ñ—wc –<ï²b·³+~ÛgèÁíĥúBżż•”ùÎşÑ6×4Ĝ]ˆ&5~²`˙²™"KÎ ’‹R€~•Ê)Ĝ¤Ê69ıàm'°­yPÊ#ÌÓ ?UMSIzĥqNÌ ĦP1êŽĝĦc˜Ŝżûsó3d0ûµy.ÛIB—1ŞPêñ+½;à›‡Y{Ô Ğ Bşá)˙ìéŬ?N™Èa@ÊX™(Nġ@êŜaÂKÒġT‚ Ğĵ€nlCN'R ²$R&c(Î(Ĉû£J‰™ï‘SAÇu *(‡ÛğŽÓÏW“2MÎ= Ä˙ĵ×(ĵ /4€VàÏI7Af—*`ÈñĉĞß í¸ŬÈ}. †-v8Oy9U:R€ 4´fÍ0Ž€AtEÈ,ƒ†R^>úGġ$ħDM H˜ÙĤıŠ˜€>Í0(•Ñ‘ Ù¤D“ħBO@c /wŝÀíŽJ—}ϒKÔfö+Vˆ‡[âÎX‘â R­C§!´d"çAˆáµĈ½·*ˆ4= œd˜ì/‚ PaÛQŻòœÈĊÉ-r¤ËÉ@XÓÒáˆ#ï·'Jü:Ó,ëâÑ-4><"ÜdÔŬ6ê)Ż‹öigi<ŒöW…Ÿ0nÁj%M-Ġeᕃġ† YQ • EGaús™:âĈ"òс°¨~vLĝ“™gFì—áÁCÉPt&dŬ?…Ŭ¸>”Ë6äğSœ ZR°Ú57~ÍÏË;Ü$âl–…-çŬĵ‹¸1™‹ ĦjòTD£Ú/­y:ÜrúÂI—/@Hí–ĥ~Öâ cK•ĜÛê6ĥ‚ ŜӖċ ‘“XĈğŭÖî`³ñEè9–ŸU!Ö“0 ­h>Œê›‹…ó͇>ĠoJFҌž¸8h³(4’B~²ÑDFz¨Ä6ï0Úçğ‰ĦCê*•²aşjpk։òóڑ ÛÁáûc5Ŭ8ž½ P^Xv°¤i125DEÒó‰Òċ ,Lû³ĝâħ#ĤÖ×g§˘İ͇AófX³zDĉĞGäxëˆßϨ'À‘MÙ8’7ċĜ;êq„#MÓs8N;Ž=Ök|ò:Ĉµ 6Z[I´ĉaEIšÈ!ƒÑGg,àé+…ĝÒÂP›ì¨Ûˆ¸Z ˙çêèUUö}0öLuĴÓĈ£““À Ċ#¨>‘ èVqZÌßŝè_›j9 öLAĉϽÒB ĝߨmAû‹6~ßıZBp^èño93cħ­zĊħò:›hpß)ïu]íX;¤gä‡+ -%É)‘e@ck@εĜM†\ÄÇĵ;˙0{’şé ”‚‹ê5û-W$Ŭı›\$ ‘'§ż½d}ÀĥיÀ„ÓÙÉééġT`²ê :zp(à£ßO§$V•(5j|Ġ3Ì{:%4ŝİ=$ĞßTCŝŭjÛoİA°L Z<-ñöı?ß&œ! (İ.:C‚İĜ”äÂÛŞ,˘£ÄuIaċŬ”UC"ʆTŽ/×IQ# EaĝTÔĵ/7˙ıáİÁ"h4N3ñ˙Ñ5ĥÜY#b_%P-Ž‹{aó0ûâd q]/o: “ƒW·mâ÷چ<{İÄâa?Oqêâ†Î³@§GŭNÔΤĥ¤XYÒs4‚^ ĤJÄH!ëˆ\<~ŞÊ"­ü¤:Ò$îR:ÒB@­ĥ àtmôBs"À¸Ïgrı/:ù_*çĤĜĜ^·ÏÈê+‰yX陋>#²£rĵŸŭŬ‡z;—Âp†żIÀ=ñSw1u‚É ;²£h ]ùÚ?×ĊĉİE™-‘éß˙•½Ğê}Uûâqlzħû't¸! lŭ™*`”èÎS͓(ËFî΄˘ Ŝ/nŝ-ÀêŒĦŝ endstream endobj 76 0 obj<> endobj 77 0 obj<>/ProcSet[/PDF/Text]/ExtGState<>>> endobj 78 0 obj<>stream H‰œW]oÛÈ}÷ݘGzcÍÎ÷p‚EŬ4-R`ƒÖèKÜZ˘,ĥ”è’Tïéïí™!)‘˘GR­@ž;ç~œ9÷Ŝ˙ŝ;'OÍÍ/÷7?ŝÍNî×7\†ĝ°‚Xn¨!÷ÛFžsżĵa”1&ÉŭËMòs]´›mŜK²Ŝï–mQíšÛû*Ù_ĊğиżÊ¤–2íx¸ eU¸ä~““썋HV–d]•eġBZœi²-~½îÚìÉv+RïËĵı ˙ÍjüeżŬâš?ò•÷€‘§\i¸ŝWïħÖÁ/ÉcŽûèíÂCµÇ~ 8möŸ< t€Ċî —>í·ùmŜßŝëŝˆI÷1ħ.&bҚ Ŭ'ÈG³Ûoó:’.Rjœ[%IwĜœŜΠ‡F‡ż$Ğ|ùıCXĈ’z×ĉH.…ħ˜@Óp;¤à·ŞĜµyMÚŞËr[ï—í }Ùäu—“:oöeK^ $ê1'ÏeĥÌWô\V¤–:fÜÄxqHÉÑ䊔ŸĤ„ş I1|’’Ž“bİ9—”bı!E.óuK6ž€MħÊɃóá–TÏy½>, •Rê½ċşŞ]Ŝ(óĵq0 =dµ-Ú6ïLĥĠ.[áµ̚³ġ` $8–£\ŽƒĊĠ8œ#•Èvĵµ²RĦċİĠÇZ8Équµ¨‹§Í´µ/ĈP­ԛeHB ßDˆû­„j+¨R£gżĴà·öBVGf—Ó::òúĦ‡X‹8Î%VSf&`ˆÖ){LĴUzŝòû& $ËúYÌÏètC3Ì›ŞÜ·9ùš•ûÜ'Îħ$ ”äs÷“–Ôʇ1@#Žı}˜7Ys\‚òġ:_ĥmĤM11š)SÔ°^êñ[ıoÈ~‡)Ú)ƒôù0˜Ħ6½& q°bbáĦġ1İğü Dúšßyzu#Û2-‹ölPh² ğË$¨i<żğŭ9RJƒ9HNŸ;WĞ#;KÏÎk)*Ĉ‘^GQ,_BM.-ˆ˘;1/ '$í'*3[­†1+ÊQH´0nî~|7“(.S.êMïFQÁĦóÎÏ< 4|Á'&Éıs{`ŬĵÄŞí3fÖ?YfáœoìŭċÊô;bx‡ÉsÙA€Ĉ/é`˙™×~2+_ŭ2§pOò邀˜”z˙Ç —Š“ò ?=UÂSoħĊVĜxġ ;^&l.Ġ {hĵ€ ˜gVR‘ZÊì¨ážĜiÜÄĈĵ‡{)ÊÒwħÑÓèd;69 ,–pvĉClnèoĈ83ó s€û2§˜$ú2ż†U)˙ïËÌZuÖ˘w?dÙ?ĥuĥl1öŸp/y~ocî¤cÀ ½Tûrċ£d·w!ħuÇ`?I5VÑË0Ĉ}buŸ(óÑúžs‰Ô °ÄÌ9CjĤ¨ĉœOuž…­ġ"ŻYJYjĝ˙ ħNJÇżDleħ¤2ûĉÙäkۜšy\;bxż›9ްžŽ…CÇ}ëzÂ1>ì0zšîŞĥ—ħìħÌÇ|­v8ZcÈl7>ñùœ}†bz7î8F‡^4TÏŻuñ´i13-á×§_~%Şúı޳0gĈŒoXi5U’p¸ñ“R^Íáhxâ)úÈ8q7Úġñŝĉ˙ ÄuÓ endstream endobj 79 0 obj<> endobj 80 0 obj<>/ProcSet[/PDF/Text]/ExtGState<>>> endobj 81 0 obj<>stream H‰ÌWÛr¸}÷WàQNYXâNÔ>egfSNeç%J^Ĉ[[´ËLɤ–¤|Ù™ïÍ@Z¤DÊòT2Iٖ%›î>Ŭ}N‡żü‘u}ñÓâ⇟adqwÁ8I…_ß,)Y<\$dŸĊò"Ħ‰R‚,ž.f+·üĵ{¸uĠÇü1_ı›Y>]‘Í}}E*˙²,‹Ĉ=77——‹Á…h]°è‚ £J½ĝs÷ŽÄçUû|ŸOˆU”s9°i½N8`ÜRv`ħOáˌä5İ]Cš’4p[ız·iHyGV>§ĵX‡?_ŝşĝëX8"Iݵ#)‰€gԘéxn_N{ԌrËF\VÓ.˘,ÚÌh|xĴèÚšj9 í°Ú×(ìÚUßXt­4UVżĞè}›óŠ>2]ô<ĤBĥYJ˙  C™Ö#yMw‚d–Zݧ£|£¤²Tj3âsş$J+”aC0C/̅Ĥ25dŽ&ÑC˙ÑG“Z£ù\6ád Éò°ĞrëÈĥĴëüv<’îy ê>zYM²˘ƒ—^΍@%Qiú¤;è>{t!ÉÄ;gŜóaB6EIÊÊĦëĵñç̘ž>„„IšXsƒ–I÷ˆ´-Iàp•R‘hÛ7ïò8͕Lİš]ßùàW é]‰Žâ2ĦÖH{ÇO~óƒTçeñ[ŝ9Y6ŒÖê(²DxNŽA†B…Ŝ²ĵvĞĴJuጓú§çí~¸Ïk•rÓyS­)SĥgñĈL d˙ù„2™Ot[ T[îñíBbœP)eûïŝyŽ!ĥċĝd0IË Ĵ.Žó?AÊ\QÍùh>3^îŠÈïHᖘĞĴz!ğşĦ}Ïı.hntzµ"·È‹H$…`RR‹žRĜ£™™Ş‡ñŒ7°êsWVĴzáNÁĈ•˘ÂyɽÏ6w_Ŭ£+&´4 œáŭg›uYċÍŭ Qxĵ¤zÈsœùwpŭs^äMG`5yÊ7œ”½Ôžïîvĝš[†ı Iĉ…{ΖÍĝoéĥ y |0Ž´” t ˆRˆó³$ŸêĦÉk´ħï3ò‡ĞJRVS,äçD”ö=~½.î|Ş/“ŠP-ÔoI™ÀĥßÌÖ /àËà6@lë–Mŝè6/7—`ÊdogמC@Jŝ×eYÔfóK„~LPّŽnÇâŠÜî ً7Ŝmŭ˜²ôvZĤĥ?ĝğÍv˜,U,íFż×97³€ñC³Éċv“-ŬÍ˙ìŞ ıâM•A–Yíêĥݘòòo‡MĊRĞ[D™B2Œ^òeĥA7Ĵ,~ 3’‰Ñ™P Cx*İLPAf¨Tr_A=bi B‘0`ŻŻĦĝÁpuSċÁqMÄv²bíHĥŬn^ ßmr–jµq¤+W/ĞüD•Ŭ–î„äH¨NC8{ù[ñ~‰ANT2}îĉ(A=“·G14@²^ÇöĈ"kvê¸)×Y`´Îŝ=Úär G`kħS'HpqF˙yġ™ IKĠ12'hEpÜBŽ’ŸyÜadé5Tı•š1}"ç × 4ô§”ۛ>W¸ċ¸Î Í|@|L‚&…Ûx˘ñ}žIĴƒìD šÇqz%ùĊè/JԄD³HVRxò<]\ÏŬ2<= ¸Ŝöž{ÂöE„vü›ú§‡dĤ%û ),ö[ô%ƒÜÉô<…”1Ċ6>ÜŜşßw˜SŻWŻ5@ĠEĞİO÷ùòž@Ŭ\¸ôġËamÓ şĉ½ÚÖ U añ§>%g´Ù÷R³„Ï ˙=5Ĝûċ}KÌÔµ´˙s-Û>;²r͒÷Ğ™`DòóÔ s)dßä-5Kq) ]fͨš+Wƒ9-ïĤŻ<€ÒŠ NÜy„ *Géoıô˜4ŭ2jmF.=§î<'àí~o_zx24óžÓ1É9yëħbÄù™÷şäÓAŒÜ|&C‘’!Ħt$”|ĞhbÓI÷}uÙ+^ÊÍèê|&ĵ#™ŭ£ݒŒc "Fž‡ !l^=PžĴxĊhǰÈÑzkżPnË'Wy­Á^ùFŽ’´ CyßAà÷Ÿ˘cW!ˆ½.^nżU°ŜĵmĵDXs>cġİ…ÇP+ĉ+Ô66ìĴKĦÍĞ›ïÌÂ9Vm!9в3à l|éžV–÷e —O`w´„{ċÓŞóuì÷ĵ- W4>;Ċ°Şŝ£Ĝµ\Ì S²——˘½í|Eĵüš”[Wġ#óû.ÇŞ9ûÎ÷ĝ•xñĵŬ5NÀÀ˙#ŝf>9żĉFuÍ*ÜjĜœ6dl}/ÙpQù2û'àEç\Îŭĥ fĝ1­zµ3™›”0›b‰—­a‡vċ˙Pn_Ş|}߀]– ‹ëŸ~!Êj[VYhJž$Úoñœ?û380<\ûĦtĠ£1:<R;kğHcZ<À§ĊĊżW„ endstream endobj 82 0 obj<> endobj 83 0 obj<>/ProcSet[/PDF/Text]/ExtGState<>>> endobj 84 0 obj<>stream H‰œW˖۸Ŭë+°T'-  yfO’9žsì“d”lܳ`SD‡"ilµĉCò½ıxˆğEI·ġFêqëVĠ?˙ÊÈĤ}XÎ~ĝ;#Œ,×3ĈI€?ĵÄĝÏšċn Ë| ŠYîgó•Ê?÷ğg?ĠÓĵ²oIım‰6Oy]uêµ{zxX~…~áġ3§ŸYŭ£"í 4ˆyl/·EKÖ}•wE]AÍÉ´jI·Ż‰ğ5ŻJyV–’U+ÒŞ%îžÈ߸{"â„Ê8]fïqÊ&Ĵ §Ñ)c˘4˘_ĉ¤ĞI·U¤ŬÁé ç×ĉë‡ß–żÌ" İd’,…òżùOW·GçˆúÖg‘ĴĤĵà<ĤĦ”D&)ċw{Á%Ĵ#5X/è|[·¸v_t[˘Ġ&Ó+[[l*YġÚԕŞ:aÄh2˙wĠ/œ,ĤœEìÌ? ‡ĥ7İy$Ċš@šÔÒFËÈ·Pùœ}ĥúMkEVî³CkĥîñĴ˜ƒêÊEÔÙĠ˜ŒN'ÑwpĴ+Cĝ‡kß:ÜwҘ*g>ÎÜÍÌ­++ĉĝğlĈaEà|$~š÷Ua\f°ÎöħóYimè›ĦcĜtS%4µÉq|X’ÊÓÌis³Ër[{•'&ÓğG^) žZFÀÜEh†œ.Žas™6<:cJùŽÂVž¤#½Vċ˙ĤòÄ!'r–ú1îê7[òçWİ­:i5I s3$VĤsÂ8BçÒtÁC|jżúgŸan9_ŻkÔ` ĈpX+/lXxo'Tè^ëƒYyÜĤÓÖ'£Àff`"—ÀêĉıÓ HWX×P_Ċ Co˜}YlŞô%–E˘6ŭ‚ıˆdJ…Ĵ†X˘'˘ĴqÜÚdOÀC, _ÙVbHë8Mv—г˜F˜>.‘]ÓëÛÜ#1Ĵ§ŒU<^ı:ĞĠ à6„0Ğ0ç‚m‘ô·%˙_àċWĴ‘ŒÉŜ„èùò[@V3F 23yĊT“–ŬŒE§Oċì×هċHs˜L| ĊԞHIQ†8ÄĊP¤Ñ'jUfŻÛĝŽĜ ›(–UxÚ7ûLŻZ r×àĝsQŬ=¤Ûš*V™. àéEéö¤êŭÂ:OiÙo tìĵîËÄ·=•fŠ#*ħ^%èfNMP`˜=§Ñt ‚ÀÈÌÏOŸ7›£c&˘~Bġ½sD rµÀ:'ñzìi_ĉ˙q>?`¤À#ħ—ÇF³³-r‘ğ“!£â§ş9èb³íÜpŭĝáùİàÜĉbDÚÍIbsú Úĥ=l’×*ŭ˘VoŒ=şħ˜Ĥ)?^hCÄc˙ 0w~°… endstream endobj 85 0 obj<> endobj 86 0 obj<>/ProcSet[/PDF/Text]/ExtGState<>>> endobj 87 0 obj<>stream H‰¤WËnÈŬ÷WÔRNlëÉ*Ù$Ŭt$1Ċ(hbɁD*$e·ç7ä×ò;9Ċ*J"’=ô†ÄËû>çÜŝô7Jğ¸˙gN(ı_ ”äĝƒ#5™!÷Û9yÄżû•˙ïċâïOĥ&7÷?LF³<˜ùż23BmíSž=sAñŒĉ'Ïĉ̙÷ñӂ¸Ž”díj×[Rï·ĥ½%ïÈÍ?î˙|É3,“>cÔ>Xûm×Ôĥî10Í3%i:†}g+Rv¤²¤µ˙ÜÛÇ[Éráz²k›gWÙníob‚’;Š7QAî?âı”<ĵ³$˙ڕ}oÛúßdŬ´ñ½Ŭ~Ó/o²›;T&_çŞħëµ[9ïĴ+Òıǚ”­%ĝÙ´ĥÊoı÷£F?CĈ÷xc˘;FfBS˘ ²,†î„ÊĤÄLĈ'Ï#“BËcu:ۓA£žËÍŜ’—'·zòŸµĥuĞr³y%(ZıAĦ췕ŬġCÒeŭJÚf_W~\Ŝĝ7  İĈbUĦ} ]Ŭ$‡J‹ĴƒŒJzKĥMċÖ.´´ĥ+ÛueûJ:@ÙcÈS²×èŽV:‹{$ĵzröÙâI×Ŭĵò+‘Ócô'­MF‘ċ3SŒS1–YAĤĵR‰Fçü‚ëëŭÖè÷ÜÌğ';Yŭĵʲ\<›HÔîÉ­ûc=Óû*όĵTž7VVh™ċĉBqĈ(c 6ò"îéé:RÉc%m&xè1_|F:ö[ıŬm,@çz­YÁ2­ ˘$Ï4{׌2d ÔÔä$&$P .REÇjî˜cs*ÏSĈ3!U‘ŞU°cô²{ìˆG›> "~šÙĤi¨E’)ŸÇ”=Ú³ÁA,ÈàĴ4çY!ħû‚f sħ€–D·Ï+91À˙ÛPˆ#6“—fżİÈCÒ9&S…œ½ìĜ•…£Ppž•Y.Â*g’“ÀD&Œ—'}séÍXŞŭâú'ŒCz‡s†7˜KYżµÄĜ~Ċ疧qİ|…Ê3“ç—Üŝ'ċĵ vĉo°b †²Ĥ׏ŜŝŽY.ĝÂÏāŭGNh!ô–)ChTšwí‰G`*'& Ż |P4‡RÉġ„3Êġ{‹›Ŝŭ2Ž•a˜J3£ß EĤèÄâšĥ-_ŭ’ìšÎġîàÁ‹ÛlÈĈúo‚İP4Ó;óˆò–€)fV>Ş\Ĵol€ ‘hêlq ·A0è-0À Ĉzv;ğ :b×ĵĜvĝĜÖCŸĤŠ,˕ ú²ŽÜéérÒ£€-[‹Eœn!ïüou lüâ* żޞâïŞİ{û­Ï*÷ĉM %Pı1§Ö>J>îüˆtµµ•­bÙxĈ™f3ÍCfşyá×L%òW‰ É2ü8µ<ĝÀùÔï9"/ÜñÇOüú•¸êk³³mÙğĤNA$şàƒ@ħPñÊy{?&mé:ŻËï %2ŽÏ÷e[˘+q.( Ş’àâg.¤U>tĥ^ gÛ6^ '{Zi‘ƒ)µWï[ !ÍİÑÉÉ2ĴÀĉ|í˘–ïvĵĦB…Ħ8p?ÌcI‹ÄùȊ‰É" ÷§ˆ6qıd,\Îé¸\\ċ7ÑwfXÛÔHjÀ”ı9d²8öÓbĜërssÇ z#Ĥw…IC-ŸyjY żħ@.ÇIŬwzí~cÜn·y½%ñ( Ÿ'`‘b°2Š!óvšµĞ(`oÍ"|?s] ˆd:cZßĥè\2>yË!ÌËër†Ħ`³,{éGqŻF€‡dIE•ĉÂíĥvm׏EÌB°4ËB°Ì_fĜle+ğúqX‘żÚméêÊĥ˸3·Jŝ–´ŝżˆ°Ë›DüK•É 7Ç Ŝ§ħĵĊ@ż'&ohtj0_ÔÎö#Éĥc&`a›qŝĦÍg_9`LGġµ8*÷ì@Gâ5ŒàŞËvîŭÊ1‘ ĝÄû9ê9‰B:6"êèxÑuċ6­Œp$i(Lâ˜è÷Ċk6=1MŜ/DĈqž>|Eu ™œ<}’W¸ĜŽ8"˘9K$Žr’†Bœy4ħeû¸ß‚ˆ:ùcÉ#Ä^ç. n'ûŒ£.@âaÙ>Sò‘ ½0g8ïċ˜³ž˜,ÈïqeNЉ#%˜ qcÙâğ°°ñóĜ=˙üż³ç0S‹Y4ÈvC'Aµé”Wvùôñċ ù-ı’•Vp/ <5›Ş›èĝ‘‹(çÓC kv5]žĉ[PjNMŜ–ùԉ Ë˙%Àd`³ÀŻË‡ÜèkqĵW>¸N×3ç×Ô³ñ3ç*réóô2`ꕅĜ´Ġ¨/èıJ…Œ ƒ“|úô‰hàÙ͝’Ĥ D½Íı”s&“5ĴğŜ–™BßçeÄ ëz'2Ċ‹x4¤ñĜoċv·ħƒ Lˆ2¨„àïTİĴ0‹ƒWäòT†Ğl8(½‡Aqq£$TìÜû}ˆMĉ}ŜĠÙÙôÒì7•§İ;Ċ[>p­—‹“ÎÌ˃]•˜Éìm½LC•ŭ3ÊφvıÀġèŻÒƒÔòĉÊiĈĵĈ7jŽŻŬŞÜĜïDV Ü7zÜ÷˘ˆèê×3 Lç0è@À6ĝ"% ÎHׄeô$ ojH2TLLĵfsk·  jĝ°C ÓG,KÌ…â„अȴz”ą́™šxwŽ€Aĝ¨ 9ñ/{ĴğûĊ˘…2)-aÚx¨Âĥ|%ċùb"{ߣP~BŠÄpìö-è׆“ċlÖ=f͖ó}oüû.¨Ğ7‰Œ lĦoÊÙÇÍqšÉÓ¨ —2n¨ÉJZƒÇŝ.ví…RYż’ĥÙ×x`yóğĜġîvĝ"Ş(ögŬ–ĞğPžĦ(|ZF5 N}]ËÍ óF<ûċUσ wcM”DJ…ŽJ܌‹.†4BRİ)F£żŜ{Ĝşġòïë.ĴgóPÖ `RFĦ`ù7×NM -r$&ħżŒµ;†XŝéàfB up븿‘}Ü=ğ•UQB_ZiN­•%ċ¨öŭıŽÊ@Wv’ħc[eÉˍ§œó3œÄ“0mĝx`ñÍĜ£‰ĴËxfÎw[Ë Ĝ –/×AfœĜAÔä´‡D{[°…ÖA{ıĦıWö:~žİ€ÌĦF}ş,J)ĞÍè)ÀƒèÏ endstream endobj 88 0 obj<>stream H‰bd`ab`dd÷öñpñuĠvÎ/-ÊL-ÒġOÊÉ,,MIYŝfü!ÎÒÀôC†GĴġwïOáŸÛYċ0ŝï–[À éÜfvó°Ë20Ĵŭ^Ê˙½FpĠN!&FĈü:çü‚Ê˘ÌôŒdMCK K ii& Á¤˜4“f`ÒLZ(8Ĥä'*W—¤ĉ+xĉ%çä%–¤Ĥè)(8ĉä(L.VJ-N-*Š˘ğĵ‚X™˜-Ûĝĝş}żqèÍw~Ħï³.…~!üáûËEżóğüĉg˙Ŝñgıè!váż˙NùóûĈo—6ˆ¤ƒBߣ _ŜÌ÷_˘óÛç6ÌáXR]8%GZÇÇ1ÄK^ĝÂwŽß!߁ÚC~púö=–]xçï ;Öì—^²¨5s’<_íÌfü֞ùŭтßŬlß&}èŝ³—ŭ×!îoD ˙żž£ endstream endobj 89 0 obj<> endobj 90 0 obj<> endobj 91 0 obj<>/ProcSet[/PDF/Text]/ExtGState<>>> endobj 92 0 obj<>stream H‰”W]Û6}Ÿ_ÁGψ¤HŠÛ´YÌ`[£/ñ˘Ĝ´­B–\IgŝH~o)ٖ,Óö"HÌèò~žsÏŭôŻßY×O?͞>}„‘Ùê‰1áŝӜhf¨!³íSDÖĝ;[¸O“ÙĈ’çٟ°’UÔZEÄH'gIħßÙŞŭxä‚qCEïëˆF:‘ÎĊ· ÉjRۆ4%IÉ{šï-9l²ĊĈŭÚ*[¤yŝAì_û4'ó‰ŭ°ğ†Ĵʊ¤ĊİÊ}ħ̊ġüÙ½lìó˙f˙°K3RTvyşôòM8‰İNúßÓ(Qĵ xJ*[#&ğ$µó˜6$kÈ&­wüîŻ½­üÒ~ߕ…-úü˘yBċd† ›Ì[|™ĠS˙}(Ü8FÉ"ÉFA/JğZe‹ /‚MLšöâ'ċêN””'g—·{I4µgW2>÷6]ŝı÷ġ˜OŜÎí"h_½ÉVMÛşs!ë`E„L(jŬħ΁ĝ„1”+ĊB!׎^[›` ’1IÎFATÁQ’<Ĥ&îuBŬ§/1£L+I^Ċƒ³Ÿ]X]sÏ}Ayì÷tğËí”d]LׁÈ4ĊDi€K?2Ü,A!“Ċɳ/ȲWêÒ-Wš5òʸ ħT:Ô †a‘š]úöĥSzI–vñĠÏÛŻ-ÊÈ Ú× àDákÇ9j§Í vR ˙Œ›ĦL8›6”QLrĜ ¨Rç ~„ކñƒÁÙ)ŸvèŻ÷yCċ>_’7òÍuŒĝ9÷ċSÁâE°òjhÜ|ÒbÌꚐš&ħ”ׇŭ&ÎH\Ï~Y³AëÂT&ÀĤg{ı1&;‰‡v}żÀj(ÏĜp*„ğ u76‰3=ƒ Ÿ?·H E³7mú@às94şK„v’CBHtĵ„_bŻ×Ù[niÔ5Ĉ DêLŞhMe-ËĉŒÔÊ!µÛ]·NJòİÏnĴwqȞĊĈpÊö=`X™/mŸîIJıwŒq\TI"G‘߀ FJëë‘`˙ùÔ-ċÖóÂÖuZ}€žŽz˘]ü.Ĝ—I ´ Àö–Ǖ×.ng”7EĦN@‘l¤3BĊT(ĤXĵĥüҋ8X9ݨÁùuéÚàÇ&ÍW?ìğ p wœèËŽÜ?âµ`.+Ü[Ì8‹€í‡jWÙ&Ŭ.ğĠ-(ĥ”şş{ëı^abB‡UQƒ )f›çĵVyYVóÓsŸxŞÄ$9żpkq =K‚‹s˙ÖTé˘o͇)plŭÉĦ­Ï÷ÉßĜİWst îòı7]‚nCG/¸Ka¨Nt( UUno{„fÌ=tá2ĵİäa&7;-Ày2ÔéYùŠvĞ4˙=Í÷ö˙'_ÁpuĈġZA•ˆžĊ^ ¨ŠÁ÷¸GöŻġ:ÈŒ…î(ç`­.Ŭ™öZW} µİ‚PÁğ´j0mÛò=HÁžv#ÒÉUÂ8qÏĥ\Ú{ü› 41 b|ç…c HŻoĠŽ KH5¸Lî²şĥÚ§¤(É*O×­¨rM˜OöEŽ”û’Ëß ^ıâşB^PLóçݧùÑġB´¨ŬĤd“úqŽĦÌŜÏên8íĈ'hÜ0š3s~›üÁíı!àu7%ş5LĵaB˜IéĝhíBéŽŜÏċî£ÊÖ—á’ôġ§˙Ïeµ+ÛCёĥ:É B–ùkÇ<ĥzwşu ‚Ž‘JĤħÄáN¸qIŭ2{ú[€_6 endstream endobj 93 0 obj<> endobj 94 0 obj<>/ProcSet[/PDF/Text]/ExtGState<>>> endobj 95 0 obj<>stream H‰ÄWÛn6}÷WQ^Ä\’’(ħ tÓ R`ƒ˘uû’ôA‘i›­,ı¤” û!ŭŜΐĥ%%ĥ“l-vÌıs83z˙ݜĴÜä|òŝE8™/'CċĴĤĦġB˙›ŬD4¤GßVUEÓ<És€ .ƒ8Œnp'/ ëv}òҟRRœċTedŸ³ú‚œ)ÀšĞ‘9&™ŽäXBğ’sul´ívma[Ìzi›Í‰&"â”*–’Dq¸9ƒĴ+םR>Œ<™L<âRJ˜-ĜNq,rA…RCËóš9Ș FwĴ—Çş\ġ ›ŞÇGp \ĈTĜvöíà &°\œ€„–“CKH2AÓ$dyŻĤŒfcƒa–h˘­müÚ60÷î*íıY ŭe[7’$ĤJñžĤrWġDÚêŭâqnáHĥ½lœêé}£Ġja⃧fó…9GÏLħXÒ“ĝSl`ġrġAÉĜı.˜ƒħ…‹]00{Ĥ 6°ÜUç% żC3D4*ċœ&ı”#•B#Ìv1öZċä6ݰEö”ç$\ƒƒKĜ–¤ßúŒÓ~ó‘>a8Ĵu>£+²Ùl+ü `*À ´Íפ>"ä3;rŒÛíqÍ^ׯ‘kÌaÖùŸċZŭŬŬ"Z¸{ôÈÛéHÂò™¤JŠ7Jx`ġ²„‡?CÂżŒ„cÁ_/aOÌYŭĉĈŬ˙£_Á3*E~\ÀzċŸ$^£bÁ h?˜ŸİâzÒĈ˙ ϲ#Ÿ´mÂJ;à fáŝùÄÇÁ_Ÿ¨<}‚×ëġÎSà:£Ü{£—ĠŜŸŭ ħ²û"Z‡‡šôġZßÓw]öòċä<„ ™UòÀêMôğĥ"Oa}Ĉm^Ùü,ĉŜ0÷Kĥê{ôî9ïžÚĴY­[(´„"Ż>|$—Ŭ6ĥEÁ‡ Öuâ;xòsÚŜïq–i wRİQşQ̰¨ïç“Lç endstream endobj 96 0 obj<> endobj 97 0 obj<>/ProcSet[/PDF/Text]/ExtGState<>>> endobj 98 0 obj<>stream H‰ĵ—]sÚ8†ïùş4 ZŝíîĠĥğŬéÎlfğñô˘a/„ [Ɇ²ż~$ƒ!BĤ“/>¤s^½ç9GäíwÍġà}>xû‘ ‚òـȇ/ĝ“À7IqŠòrà£9üä…ùµxS^Üĥċ„ĞOúó-ğ{•}6óo*ìBŠ˜P4Ëp–ÙXĜĈÉB£Y[‚Ç­ĉSÔHÔpŬ ġ‚7 C.ĵYÀçVAVl’ùhDpé~3Ñ8bjŜ–ĵj`í;'&îÄĝNŒoĊP‚ƒÄÌèpñOˆ'AŠiîmòĈž[KĈ&a€˜î­½ïÍލï{o†˙ĉ͓°7ĜOÔ[uïı#J)޽ż¨°ĝG֍j‹ĤU “š£[ĥÜxïO¸µ’OħÍ:"G)Ĉ´Ôš"’¸ ˙pˆRi5ö &‘˜ÙGŭżARòħ7cKmKS­µƒÒ0‡ġ-ÙĈް5 ĥé·,€TQÖKnŞ0“Ğd…’ż J"”´jݵ˜,9v8Fm F’°Żî­wÒ'ƒ+z'ĉ[ŠjŝJbÈÇô™Àîö<Íëné píŭ Z?{­ŝŸ'6KpvX3´ËèzÄFI‚#z”ĜŻ\ÉKˆb(z|b˙ƒ„`ö=/ħâĈıŠÏ™y<äˆÀ=>“ä~ÓÓ(÷k_ÀòžşŸsà§éċ0›Âœ%8KBœ>žı ä ÈW"œÇIv„à\‰ò~Ú/íœ'QçüI€/%P)* .f˘`^£˜°½nĴ‚}J–;¸ÁŸ8ìÄ ˘7Á֚ü-î"ìĢ…ħ£Ú@fÓ³ċ°}ĜóNÍM6h*Vbj–˜â’Ï@›0]1٘ğL[óÍV×JÖJ°†ƒÑkH,AŻ 7Tdú­ĠÍ6˙QËÊÄbE!•ɲÜĵ˘ƒ$À4zf+ö›žnĊ~í ZqOŬ5Z0,Ïô˘5`ۅ',#„âԇcĊNÜ4:oYìä`ŭŝIö ·G:ÍħÛìӏ;ǎu_ö şï Wö޽s­ĝ[›ÓĝȵĦ:W¨s–Ÿ,|ìÓpѝ´X0Sġ8ÄôtŬ¸ìbċÀ˜ƒ"2´hKVgSf,šr](Q[Ò ˕;Q7"†W?9z™;`·|gŞYñÍ9bzMµFıƒÊxà–ĥl÷‡ fB˜V7ŭë…,a´Í2@gks ˜áÏJîĉ€Ñ*JA=q£äŜShx1Ûl‡E瘧y ú7Ÿš,Yġ}GßG˙`ĉx×ĠĉQY3x%Šŝcê­ ħœf‹™äÁ§Ë‰ßżn253A3şGW‡ĝp†!=ĝIşs$ncj7Ĥv²(Úî6râƒĴ7JÌ Ĝ^€aŸŜ˙…>HUKpÍĝ>Ŭö+Ì.ÖšĞĠvŞ> endobj 100 0 obj<>/ProcSet[/PDF/Text]/ExtGState<>>> endobj 101 0 obj<>stream H‰|’ÁŽ›0†ï<ĊM%ĵ6ÄzëîĥĠVêŞjQMz Ä!TGĥIĠ>}džM²ĞMƒ%fŝùçß|üĈĦµÑmŬ|àÀĦÚF<†7~r|xA ¨úˆA‹ĞjüëwD6Şyûµ2?”Ñ+2„ŭ*ŽĞ_(”ÍB|âAˆqš3ĈƒeBdA§Úuĥ¸N€ûÑŞ 8 V9p;Çz?*[¨áTĴ3cF£|ä_t@}a §B,$T÷^YAmÚħWƒCᷓ51[c“5ĉ­I)ݘzô–Ĥ^tÂӂÊ2;琙BċKež4òşe(Rúé—ò4ú%ùŒĊè8AH W>'ĉSb‹0ıX³K²Ô£{_E˙aôöË endstream endobj 102 0 obj<> endobj 103 0 obj<>/ProcSet[/PDF/Text]/ExtGState<>>> endobj 104 0 obj<>stream H‰”WÛrÛĥ}×WàQîH0Á;Ó§$vRw&žÎXíKœŠ‚$¤ĵhHŠúÖoèùà³6@R¤bċôŒG²$Ĝ·µÖŜ¸ŭĝ$Ĝ™½[Ín?$L°Ġv&bĉà˙"—EÂċàA1sĜŻU6s¸8[góÌT‘ĉžğ`ŬÇ_°´Üô_…ßĴbßRpœrG'`_QmÚ\6ôèöƒ×Ö° ĦsáğĈ.÷D˜˜mнd˙Ĉ$ëÎÇO[UJĤi_ŞSÖèşÍt[vùĠO0 Ü$6ĥm™iU• ÛV5˪‍Ü×"Ġ ;îUĥgi-9@–ħŽ,ž>ÏñCl Ùú¤eó|òŞÜ-[Ž@„°ġyŽ£ĉ^d~â7Ë ŠıO!6’êêEm$kLW,Zà8sŞç³Ú‘İjÛNjĊĝÀkĤJ–ŻÓL›żĴ~íĴg­iĥGN–ŞÜȃÄ[İMt CÌï¤NUn,PŜúÈ)ĉôOÒuŽOú9üöCĜUÏħĠsX² vıÓUÏäuŻġáÍííñxtù­›\ž¸ZŜvaJ"ßë"żŒ  ‹Hîúq` ĵ=¤5â¨ĞÂ[m·²ĤrYîôŜ”›Ġiı“C`e[ĴeŬ,̽Ż`ƒXÏġJPJ“9EıRYš/XSa‡jX# \Ĝ×ĥѨG“ĠjŭúŒÓï2ˆüF^b+lqİ,ÒÈ3ÂŬò\-Wĝ‘ ëŒE:²Â>ĞIQFnÉo™<èóúġ‹ŞÚ†•i!™—4o‡ÈŒlorÂmÂ]›pÖ°,5+MiJ5ŬLqQVG`/ËÛ ¨šĝëtĞû\χŠxôpż|zˢÀż…D gÓz>ŭƒ…ġžotŝRċ‹ĴMĠNĈx£Už³Ĥ]E1ˆ.6ĤŸYÛNÙİjkVKVĞĉOŜĦÖû>RÇO|k˙Ħ´ĠUĊ!—²›š"K0§ ›ái-IaTFxS§' ı-µ+ñğ‘ò=yD•°È×âž+œZ„´ˆŞ ][%ósRP JöĈ–.¸¤!¸âû!Ĉ44î\áDŒ‡‰7Ŝd zċxˆâ ™,˙áñP·hşÂîş·ş0‡œZIµÛk›DJk:Šß²w"ĞrgrşôyˆàµÌŜɲÈ²ßÒìOTċNYfĠÛÂd•ÜnUĤà€aDhĵ™ïnÌGWrƒQB… eòEÀ“>@W¸bè\êt'm$Ö˙6D‹ŸŻ5|ك0%áY*ûm•çàYżüÜĵĵÈFYĠYS8  „]e‰ĉòô,¤ÎjZqÈSMHĤž Ĕ­ú†ÔŒÎXĞŬÒ³˜HĈît¨ĝ^û‘Çg^"Ĥ ĝì|ı† àÁEOï7I8 ŝA,áĊ@Ģf;mOF ¨şÈ4x„äİLK‹tcT€bWh\Z–‚KÂa—ġ ÂuoòJĴäy̋ŽYvw˙ŝŝñîá핐1Pa£ˆ&;GòÇtkÂEKƒpk”ŝyŜ ;@€M˜0SËŭ ĝˆ×ŻÈÛW†l…;RÚ?ħÏ_ĥ™ ĤĜ ……Œr'öX1Áù[>{š½[ ­ó\ž„áċ\–˜ ‹îA…çĜÔòIÊkú(%˜ôÎk˙ÍĠġî·~yí}qpœ ádš рÑÚ˘Hks…è:Ż…†‡‘2pĵ×äÊHÛµPaÀ>?†ê/] a4Pàóü€0¸YzžÇ½9^QwCŠìÖĜĝĠ¸ ‰I8ğçûêp²r÷<π†‡wŸĜûŞìµ N8\ßŜ‚“f1ŬŸYż7­A1MX "ž$noëy~ŝ+ÀëWIy endstream endobj 105 0 obj<> endobj 106 0 obj<>/ProcSet[/PDF/Text]/ExtGState<>>> endobj 107 0 obj<>stream H‰”WÛn#ı}×WQZXœ&Ù×ĵeíu0v2È*Ƀ,ènJêŬV·_óùŜ^ú&ıg²0 ĞŠuêTĠá§żüÂÈħYŭ¸[}z„‘ŬaĊñƒ?IH"–„ìÎ+ñğKW[z^‚“ŻĞµzğT*Û;Ҟ)TylO¤:˜˙ÊîüĴj’—äù½UÍ‘ef8Ë·üܝû8žžd-ÓVĠÍf÷˘lċ°B¨ &ühĤ­óòHU} ´Ç‘´è2ŭ5\óRĥU½ßPísË)‹YĴ=ÇÎ3,žŸÖ˙ÙlY4^˙,Óşj´w"ÓT5qfR“Ĉñ!WEÖÜDNĞó·ÓM~,ï>|η›ïŝş£ßä…[ĉUi[ŒzPá ló²3–ò˜ŜŝAò2×§‡^şç"OÉĦ+Sûıƒ1Si~–Eè“s•u…˘ĉšğôÍÂ(17Û}pŽÈ˘İÌĊdo&YOe¤:\VY >—ŝàż›ú2ßóM´U6Şx'_eú;Ü=ĜÀ$“­´°t²µOĦ#ĞgÉêáETĝœ„ܣܷ”ĠŽ‘Â×z²f7A@…Ÿ'v­žÖä„Ê£Ĉ‡\ƒ´EH#ƒL![°l€Âà·ċfš KlĦ‹Şú}Û]H+Ÿ dòzÊÓt:ħÌ ĤÊ´ÊzÈpmûÏ7€Ñ)™šħs{ßŭş*q¸}­ú@Ž ‡ŞĞû†¨`ƒ$ÇüE•Ĥdy1pmÇ tĤš˜MhÒXvmu†]* >ŞRĠ²…oDsŞş"#eĠ’RéÏ `†¤¨-FâŠáÛbĝ$â$ "|ìÉğPAmÄ\›˜Ú,0$‰@îxzx 7Mœ³PÀȟ%œ'Ž PM•aÇĵ+n/ÓÍi!×ßÏhe¸SĊÁ‡3ÂVÁ è³Ò¸m+ôĦÎn6ö“vòÒübG•ž›th¨úħ ôŻ“ÒŒÀù{$£ŜZí³KÛ„ÉË8ĠŞ[˘êşŞ;ûyV¤îzvŞ˘¨^uĊÍ@XëOë Öµ›. x†Ħálݐĥ–ìŒwòŒùcLÄ>=r[-ŽañÓíbjSÇ1ĉ*ÊmEıĤ‹/"šDĥ˜ÈÙ/ÊŭĝáC÷ΔÈì7Ëtôħ4YèF‰;²ìN€°'ÄN[Ïı‹°ßsĝvÁşx²FQäŻ?ŸóPgl ;}Ĥ›ŒĈaÉnZAPßÄ÷°7Ó mġ_ğΖÁ0ËĤ&È-bŠNö —uŜžÎ ƒ4äpÀ„0™ïq1WŬĵ5{öÒ6¤éžK_ağ!¤Ħ†³AêĦ fï ó/ò‹c{^ÚĠ×ë 8Ö HĠ/niè•<ߘ‹ž™tŒˆ²ŝ|ÀŒÂÎß~0Yż[žżÈ˘Sä5/ ÇŞ+3[ÄCŜ^7–™E²>vĤFş/ŝdÁ ËÎó–Í֖-ûR=xLCĴ–ѳa1ÁİzÙ§‰˙mèyë\KŬĈIbĜòi iû˘ \Ë~­òR3X8Ħĉ>Tjí0Ò_^óœşèƒ½ޏXƒïÒÛü˜ôGŸÖúV›mAñ~0Ĥ,Ó{QÏ÷'hĝ>Ĝt…F^^şöƒ´Ŭi3Î]Ój¤¤&Yžiu‰e™Ú~ÀRŒ#ññí'“ĵÙ2³Ĉ› ×AG"ëġĴêċĴ²oĠ‚ÇXñX 7 żSÑêûċÏŠş5¤o/ׄc&ybv=ê%†FŝMEқ÷z޵”ĵŻĞ yx@ÓÊĥ[R&žuŻA<Í?YNCĈ4Á웕ÚlÀğŠ>~âêıĉv²,ßí^sĞ·—ûVŒğmސDÖù°šöëFAÁÈ£"\ì7™zD3µĥİÁŞ!0PkY•Ŭŝù›ÊĈŭ5WBġö‹L?hŬMÉäafŽŝ]Ħ$7 ó’ħĈĜÂ#ĝs)·(ä@°hfb/ŬĊÂİbqb ƒ ”Ż:&µ%úF!îĊm:á§û_ï‡BŭÚĵC"-½DLsmB@;;Ż­@=˘ÙӖC‰ĜŭÙË~ìG^èvÈÍŬ˘û݈ñ…ie|3á‹îg(­}Ì×Nċ—a×·ßüu˜˜-q’Qk>­˙iù¸Ù !¨X7rġŠĴal c£’!ċzkœ[÷Ġċ½Î§ ¤Hòó?“ûŞĈ²ĥŻ!îyá Ìŝ ~˜ qŻ—AŽ]Ŭ4`xÂ&³ë…!èOğĠ˙¤˙ endstream endobj 108 0 obj<> endobj 109 0 obj<>/ProcSet[/PDF/Text]/ExtGState<>>> endobj 110 0 obj<>stream H‰´WÛrÛ6}÷Wà‘ÊXî$û–8I'&Ói4}ħ;š‚$f(RċĊŽ$ßÛÀ (›’SO'ñĜ˘ìâìÙ=‡ŻŭBÑĥxğşxŭ"ŠV› ʁ+„˙4ÂZí/ÚÂÏ*½ ˜HÉÑêŝ"Xë4Û'ıĞòKSeĊöf|t‰j÷hħX}ƒyw8u‡S{8Ħ˜(nÇ„pfO]í²mÚ"m²²@w[ë5jJ”–Ċ” ! *Úŭ­Ì· JwI•¤ |tĦ/a'üBušé˘É6YjR!hI1L˘Ġ;{ĦlĜ˘lqƒ’é€m&Bë5¤p4ğÄ<¸DÍNWŬgyŽn5úÖÖ ‚Ġhm³žlJĝ6)úDMÜĠ+şëàPfEs³À‹R Ëà#ĵ?äz1ks>Zü½úÍĞ qÀÄH„ED‘ a_ğâ˜4ċñŞ?3àsB0 §gxÉuP׎Âf“TY³Ûë&KQ}€[A ĥi.ÁĦ`‘ÁVQ& ĥPH³mÛş+%•ŝĊe#oTPâS9^f(ñÌ (‹°Šıż1¸ Übu€r†ıTŝâk/ÂRĵê~)Ž`3›„òÁ†w5üÔÔħÑ@hÓĤ*À IÇ_Gĉ¤#)îÂ> Ĥ†ÑÊɚˆŒğžÈ¸ĝ:0 ´X†qŒp„vòiv˜*ĊF8˘(z Çq{˘Ûv³O÷ğ,Ŭı^Şt޳;햗ĊÒq‹0 ùqÛöwşAà·ÓŜt%À-›ëŝînô Nf!` BGĵß½żúĝéÍïJ|ŭr yA ''ĝŭt0q³!¨Q^öµ_rèImï„ŭmĝ?5°§¨ÑLÛPŞpD’1àO˜z†"‚b&v`³xİ0‹U×GŸK¤ĞŞĴÌ,<”uŬĉmŞr…òf5vQŸ’)8,l?2/u\Qêl˙Tí‡ĤÈò¤Ê ô/í ŭ/¸œöĈ8á³è¤5k/ vŝŜœêAÈAh}^g|Zbl@kŸ4x˘Gŝ§ÄƒË Œŝĵ¸{ÏK™·x*î ĝwJŜcLŸƒ2Ç\zÂĝâçä½ÖM_x=‰ŬnikàxĴ0<˘ĥĠ3zLL½ĦÑRt—ä­†é’iŜ­İmo S›Ü}ç(?ƒKOqE|Ĵ9A“ ĦŠ„“cŽĈ 0>q]êìí’ĊFŒèäZvµÍŸ`Ô/"ލŽßçXám8ϊqħe…ĞÊb)cŽÙiÓÇ"1 fšßhĜ`ú$¨ŭ1+²â6#7pżlċ“ÂŽ‡LÓ˘Ÿ6 0VBrefù<šNrŻ×şQqÓqÛ30[LŻş` ÓgAe\Ìk?G# ÊwŽtê“~Öù˜íÊZÏùfAC,§Iöĉ9iÚzŽñ< WsİĦMĤóµ79ğ·/’áQÍbájVéCif+ˆ´“Ó˘6wTÉw‡ÚáéäĤ*Á —mħĥVÄ%Ì\œC ˜Udl/Ŭ¤xz)lÌ$’ħŒ @ÔìŬ—\`Ċ)ܧ•ŝ§Ízr-%Ĥ’Ç'}eÀw(ÂTÏĉ觀Qát‹íGü(UR Z?h­…ցĝ”ş!=Òw˜£5XİC²Ġˆƒ-ż·”êCóXíċÙÁÄLGÄàp`ĉ1 ‚{àáëĠ`mÖE“|Ÿı>cZêé0ñHĈ½Aç÷—ĊGVÍ·FÇT|ì°g=Ä)ë@Ħ cÙ;ĥˆ³—Ĝëqè/aĴŜ ·9f°ş 3ô| |r½R´ÛRżŒPÓC<úy3âm> endobj 112 0 obj<>/ProcSet[/PDF/Text]/ExtGState<>>> endobj 113 0 obj<>stream H‰|R]oÓ0}ÏŻ¸R\ß8vâG6b/+]êĥAmÙÎ˙´„"'RtŽÏǽЏ{WÜôĊêNBż+A|§­ĦEEô§‚Á>œ~ˆŻ™–Ó³ĥe˙=ĝ™‡™‡€uGâŻd²&*Ż%×” ù }"[=<äÛĞĤT7ċ·ŝ?uTKħkŞeL‰hñ‰Ĵ˲<@Èg3N^[üAƒĠn9zpŜ.ƒ_ĴĤܽ‡Óâ<6/Üĵ4쌔°÷£wÉH%i]Ë*¤ÁÏğ"H ÁS+f³ĠèF3ј¸W+Ñ$xB~ÑAxrkùĞyDI;&AvŠĥŒa*ñ˙ WŒì!$£!yeùÁ€ĥ6„ÌĈıñùB[s M…_ğeü%Íê³ĴJŞ*.ˆ’y;R_µÑˊsN9 §=ÏÍÄ.ğ0ı°!MsaG;uâÖÌ?í¸?xX“a]ÂŭÍ'¸5v6v}@͘ ó’R†Íx{> endobj 115 0 obj<>/ProcSet[/PDF/Text]/ExtGState<>>> endobj 116 0 obj<>stream H‰”WËrÛFŬó+zIM‰îÙÄT9•*3³‘²Pì”Ììĉf*ß;çvEY­rÉ/ô}û:÷‡Ÿ%{l֋~Š™dëíBFLàŝ âJ|Ĝ/{ÄÏ:].„ĜúyħÌòô×$ŭ’gl_eÇ"żZ˙M^§I:M’4ZsÏë4qODÒ*XïröR ;ÔĠ“Éò†Uù”׍İʆµKʌmëjÏşç·yjöIÁÊ~ƒgœĴ ĥ’\Aù­ġ3ŽĴ™ßÊÂ|ÉY k~Ğ;KÍ5++Ö gk҉#YÒ&ĴiëcÚ뜙ßĥĤėMž&Ç>ڇdqŭX’Âó{DĤ>ħâÇĉ˜Ċ‰íò"cI³? ÌÍİÍñ½NNÙ´;›i‚/ıħNnrS>ZİÁŽÚ!ß䇤NÚjĞš‘B“g#a‡€TÒùġ:dÖ½Ŝ-XÏ˙<ĉe ĥìƒ)“úÄnŞl"–™GÓÂÛ}Ġ´ß˘­•v™Ç’MʖmMŬ´ìa™´ŭ˘zÎñïjğmò–™Y˙Ħx¸²iJ@ |ĥAÈ·;h00'én„ŬWuò‹µÉ,aOIq´AˆżkĞŻ}:ç­Z²÷pĠĦ^ZT˘+ò$#ċu˙šÈGžJµ€÷S¸G‘Àˆ%ìżt× Â5ƒ`*< CĤuÀƒÀué-Íf3ÛA*ıÖgB£G˙hÏĤ(Ĝ.yʇëġQߤd%Š—=ïŒn×H×YöÂbyżDµ£Â3ê¸:?Ôy“—.y”WŠ•ŝî ˆ_­B ]ûÙEÁöÉ ċ èO½@c²CĠĴ~_˙ü²– ‰XŻ›:‚—¨Á9 KÒ“BЏbÍ8ÒSxTžéb‰$Í‘"ĉAêsS_E2cJzd9‘ı_>\]­<|–‡âĜĜ_ÉWŠ„(y!œñġû™Èġál.…3ÊLٛòíxPܞtñH1—).¤Ż§Ïż#Šñ1H/0<Ÿ”:…2ÌPĜÛĵó Á͖œŻ÷'‡] İùžˆ†·(ğàÌY<6%ߐñ4˘‹=4y_ÑMMı˘››ncˆƒÌ{zˆ&PÔĠÜċ^ż3œQg{1œAĉĠp+“â:Žè½Ïeì"Q¤üŒByèÈ ìgği=³Ĝ‰@äÛ ë}œá=7ÁÚÍ-aZ…`ĦéMsşÍËn…4M•šé¨e`ë%s[ö–2€¤e½Êk6ĴżıíĊ€D2/ ı7Ù~–ĝÌà遅ĈêLfè~‰(‚8vYŝ„•“tHw÷Ĝ VJòXêéDvF2AR`ÛŞeħzô‚uĴbGÛ˙j–MˆÔ]3Cĥ_MÊ·$n—8çÜžĞ@_cŻ„ÌCû‡“aô·TžŻƒıŒBHùŝTl0|ż<ç›ÀK]“'ċĝno§Ġ~ĥC‰°œëC?”\+’WŬä³~j‰zP"˜È-ı{Û${ëېîÉ-ÑqCN5ó7‡Š<ŽÎ÷T3ĝĈ>˘xúx¸ĝnŬd¸Ê;pw ’(ĥ­ĥY…CĤĴÚî‚ Ì‡{üÊ 2:/WĞş]èIİ:şĝòè(ż×‘â;"Ĝiq¤Kޝ_jƒbj‰8&(üâHŜ ı2œJ’uù- ×D&íÙcĥ'b—–èÂ&)@V³SeaĞ™Ö/11ƒLUûŬ Ô˜Ô< Y/âžğŭñĉ—ß>ŬŜ}ĵ[~£{ÂÀĤ²°ëu3—ÓĤóayÊF—ĜAA9¤ˆÚfŽA¨ uÒkyċ €Ö W] é]…µĵÛ²SuDÛ6;²ö\Ġ_\ïÌ#ŬŠKXĤëŞ&ŠSNCÍqŬ—Ŭlßú £W”F.ß’Ĉĥò4.™‰,Eu µ•‹Ó‘”wžÂnâFp³µ1`.£8ìòrLGÙ‰ö„ZDœï…ö‚„ ˜NǤvy·1B.b׆ᤠß,Úg2V<Šż{°HbŬ£ÌœW¨·Ĥ˘:lSâjê&èœ]j‘uñ~ùŸĞ•ÔĦĉÑòĤ+نÀNk³éAí³éF;ıĉĴƒíöMġÔĦ‚u6µ1™Êŭú87FŬöXĤî˙MÙoÓ'öUvìQŝq X?âçgÀñCƒ€<˜ŸĜŭï‚e É [`ĥÇ‘Çö İNjϋëXÑ;…/Á„h8bÛ1‹4§%)•à/à&ÀžÀšà4ZûDëëÏ˘’VöbRş „Ñċu)3“‚"9î0PgÀWĠ`V;–¤Eàj@ş@ÒüŬżR˜> endobj 118 0 obj<>/ProcSet[/PDF/Text]/ExtGState<>>> endobj 119 0 obj<>stream H‰œWÛrĈ}×WÌ#äˆı`€ç)^gSNÙ[.‡Î •Ú‚@„C jW?’_Ëïäô H”@)İ-­.œžé>Ŭ}úô·ù›dÛöĉûċÍ·“lıı‘1ĝ‡oİbİLx–‡ÁĥĝZĉôߗ›èħÊğ²ÚÛċï0Ġ½İ Ĥ’L›òX8IÖÑrW°p4鏊pT0—r‘¸éñu‘˙’ċ˙,Ö<Ÿy@&ffb&¸RʑЈµġħÉ ĥ)÷ËëŞËÊŞeÜx<>ì˜mN°uħ)ĞbÍÊÊ+²uÑxC~ûċ_o–ĞÔ&l!ı”Ú²ċxI£=ˆĴĊMŭTŭKOEÓú{ğšeĠšmšú€7òOÇŬ[7‚’}P*Ŭßz ’gmÑÎi–˜z+†Ûİ6•C´Ÿ~ûé§ıXA„BğdbD^÷³…ĵl|ŝ‹uĤáVI;SW¤-h˜Ì•JÌQ’q’b<ğwNYmı™ÚŒÈ܋™ıôK°•úċ{WÉÓV§zöAŸ)Ż#Pİù.ĞĥÔ?)¸I]Ú~~ÙĠíyBÂù-ĝ™†b¨èħĴÙcÖd‡˘#‚^$ {íF)#Žxñ€F­Ê‡‡}qrß_íq-“j_|‘Ÿ İş:€ÇĤĜ Ë÷Q#„çLG(²MA5ʀrFŭ/s£ tfÓ$™‘SŽˆÍN°-f£H.^ƒĝ*ĉ6mP3´)ĵòüSqü¸`ë…çmùjr핃‘ü߃¤:I­y=Èġ,É`¤ĜX]rîEëxĴġ2Ï=ç bµ™¤}Ħ,@9PYöLfyìàĠ¨ú(~ái>:d_ËñpjYàiìì².(•~úœĞ™Zż FëfŽ5„€´1F“ĉRÊ×G’}™/„¤&VÑ&ᣌb‡´ñ¨+É3´4ŽŻ™E1ÖtXŻ" MŒ‰~Ğh?ğ]¨”@ ôršƒiê ˆmOg_lşİĈóìڝ/W:qĉӐQ‰uL[x.‚°ğJùҁó&çáħKÍ0{gf4)ú£í5äŸ_ÁYˆğ*ĥ8ŝŝ°huèĥšŠ=­\1W݉/eƒ1#ëU91lWĉÇ}ÖîP€MÛ1äa4^!Á2—éTpkFĞíY\ŭZ\GC%²b|ÁÙA ³ÁìÊşmŠÎĥS–4Nô\‚šF(ĵрb•§)ŝu,=Ġ{ÀÑhu³îħX˙~DàèĈ+]–&`W(|1˘ŒSfĉj^;î&Vg?ߐ¤Œö„~ñd^›M™—óŻİ päüğ}cĊÔFbŠc(lLm›5Ï<ĵ ûTxAр§ħfĴ™Êށ 9–u¨…ûÉwŭ°ż;UZÈĥ”YĦ‡Ö§”ì›=qüL¤A)ìġÊúU͆–úu@>,ż‡Y@òżA£$kÊn1Rĉ48kâdV?áDû’P<—dÍöx@–ĵĥûnĤ°(PêôÒê´cŽŒŜŜ1G‡WÑë ŭ܁vI˜^Ù0m•NäÄ?ì6o˜àôñ†‰u#L.Ùħjƒ j´_8êŞËúRjÑà-yî‚IуÂċW°”ĞÊĠĊì ĉ`ġ0G‡·VŸçúPĤ1,t<ñj$ŭ=‚Ĝ—Lô! ÒöËËâ~ xĴ—Íe°äsĴAÉÖİ÷í&'£w0^X`QáÉġj’1téĜ?TSl=Púû^!£Ċ]/½ž- *œñcZĤíì€îê~EKxœ7-\)T›–í"MO‡hà> endobj 121 0 obj<>/ProcSet[/PDF/Text]/ExtGState<>>> endobj 122 0 obj<>stream H‰|’ÍrÚ0…÷<Ċ]šP$ےѲI&4‹Öí&t!@€:Fb$’ç͕L€’Òa îñùîÑıùôÁ"ônëŜÍÇÔóc@ñ…U“DB½êQXàUOۗ}ĠíĈÛŭú*ùAI;e RÉ3yf7ЉöŬĝ#Ĉ)ç”P^&£ll£C€vİAÏçzښ-~û½vVÛv*€Û´àĉà•]hp>Î_İôsĵğ‚ÉiIĜùŽÑq²ou¸ĦuŒĴDĉ(QŜĞ}B1vĞ3ƒq– ŒU X3™4:ŭm] ‚YĜAU´òÑŝrÈĜÈ)( BÖïS(ĵˆ†OY·+}–>é…„g÷I0ïñáSt@˙gŭW—ğç%'ĵ $'ìÀ÷‡‡+ûçB˘èRuĈ&€OŬ3\oöj˙&ú‚cCrú/˙˙VX•œòë;Ó4°TX’xx Š$Ža>"Rp#ċqyL5{tmĊ²t–o’byIdĊ@T#"N˜Ï×Ê\P›çxMĦüÑŜm—xĜvo ĵ†µ ÁÄBx6MkìşXélYg+“ĞŒĊ”'ĥ§ìNgû˘(H‘áUN˘ê„£$“Y–ŻêHšw¸së½7‹e‹ežŽûpûîœ_;ŻZ|4䔊c÷Ŝaĉi8~Ğgä`xAÊYE¤ü 7+d\êCŬ{`‘+T endstream endobj 123 0 obj<> endobj 124 0 obj<>/ProcSet[/PDF/Text]/ExtGState<>>> endobj 125 0 obj<>stream H‰\’O›0Ċï|Š9B•8ŝw·Ù*•ÚKQ/ŬÀ[ÀÈ6ŬĉÛwlHĞVÈ22~ży3‡/:Ġ;Wħ( ßߝJó<ÈZĝ)í6Uğ \Îç3á¤íG´²ŜyĵéĠ240) úĥ`Tlou¸ş1 -HÚ@­&ĞĠ0l ŝ[ÙR.}6‹ĤÌրŭ„> endobj 127 0 obj<>/ProcSet[/PDF/Text]/ExtGState<>>> endobj 128 0 obj<>stream H‰ĴWˎĈŬë+j@ $‹ĊâYyşgŒ6âáÖx3íE•(Ú"Ká£-óùŜœ[ER¤Ôr:H0èé‡XĊû8çÜs?üÌYVÏ>g>nj³ġnĈ#ĉâ… ıçx‹Š™Ë2|­Ó™ë¸+Ĝú4›ŻÛ2/3–”[Ö¨şĦŸI•ŞQU½X˙ŽkEw-·×rş6†ÒÜêpKşìÛ|½WlĞÒ/mħQ.J˙H2Ċò2ĠĠQW ŜÀVÚOġŽş8ĉµjòB^ë,V‘Ÿ?íĜO.~[˙ˆWÜá‡À)…Hx&…fŻêñq–×,Ŭ'eĤĥK–Ĵ™DUëĥJÛáĊ5Û(ʸ­Ġ–mŬàwV)„µ˘Ô××Hi+E‘˘Hšİ²n+…à+<Ú0}TÈ,×CgLÁ%HJoJsÒÜ`^‹ ›ĥT&ÈĤJĥjw; Ĵ9)U²şAŬ2óĴiR}Tj‹É8p„İ÷.Żêĉ­y·‘£ÒĥF[zw‘—Hœ^—UIÙ’*oÎĤÉ!ĊŻ”JÍ^¨Ĵ£Vmó,oj†\ÓPO.âħÍħ öeaBEJ]èÀ™ĠŞ1™î+˜èç„ġÉ^Ŝœ4R dìD&-x‚Z›4íKŭ ï~‚OöşjşhMìèÑ%jÄSİ´9J^êĦ˘ERâ[Ħʆŭ‹tġ!aÓîvtĊNW·:]³S\,uŒ³MRÖJŬ°íıLŠ<51?ôÛ[dPšÔÑJ}gIt$s-É\"™ô¤#bË\z˙§‡ÇŸż~ıJ4Ŝ‰Ꮟ9Ü ;žïQÍTZŞh^ Ü Á‹r)oÈäìï#Ž£ü&ßĊ°oiPÒÓ.)M£2 4}^qàÊ2ġŠ”Ğğƒ݈ċx7pÛlÏbb†͟JÏ˘ü{uĜRĉĴ3/úY^§t9^À™„|Fžĵ¤Nàż“³FŽˆ&gLĵpjĦı­IVĤè•pé˘XcúZĉܳ0÷ĝËbÉNû<Ŭ›µU |)Ħ$ÌQL­Lhüħ"Ĵ’ċPöÔ0€-˘¨ÓíCİ’êì°§rħB@Z€œ!yĝî".á%::öÏĊŠËP‚µPê”7(âa ù(i䑊˙dϤ)¨]'1„\„ĝ–ŻÈŬp‘¤t—ÔÍìmÉÙ ÏS6â+=“X•\ùNìÉĝVŜ€ĞSâqރ§‘ó§’eŞÄ}ÀÖÖü59´Šjz/sŽ{̗҉ù^"ûŝÄtuÔÖ£şAW\9˙Y™‡IëkU½Ò@²/äo4€ŒG%ġyǒ 0ıä+ħ endstream endobj 129 0 obj<> endobj 130 0 obj<>/ProcSet[/PDF/Text]/ExtGState<>>> endobj 131 0 obj<>stream H‰œWÛrÛÈ}×WÌ#•"g1ƒÁ-NRċkV‰í¤b:/ĞÔIdA€ÁE÷7’Ê÷ĉôÌ)AĥR.É%}™îÓ§ÏüÇ/‚m›Ğ7ËĞ>ĝL°ċĉJĉáŝJò8 Y$ž°ċŝÊc[ü,³+ûIŒG÷W³ż”šU5ÛWµf×ËÂOèüx֏Ǥ”ÜóÇnÈŬû·o~ĝŝoÖêQt…Ü“a4²;E]4ùŻzÍVŬf£ë†ŬçEÁVšEQei‹7UÉڝfM›fżÌ)ÂBH.ĵ ` Á…RŠ-ßÁa e`ġA—ëĵÜö–›ÌÚĵ*_ħĴÚÒ:oŞrÎÒġ:§§Íœ5ŬŞ­ÓÌŭ•–kвü œŠ0òSŭp¨J]ĥyJ_QvC†£çlßm~(òlĝÀĵlX{_Ÿlßċ ŜœËHóŸf£ŻwµÖŻl(ÛB?°ê kµaûôxŠKñëE,<.g7-ËVk-˙ħü“ áEħ-Ê%A-Û]ÚNöe•`a˜@Ċ/hor)£è̒B+{:ÓÎ@(׆™ŸHÁ /z2‡wŭúy"?‰xäĊr2ŞZ4ĠEjn2YHŸ:}( ÌöžŒ‹´ŜjĤËŞÛîX[ħ]UĴİA{ôşìö+‚n^²cĠĠ,= 8àŻ!WJ*ò Ŝ… lg^£)ymœòB/Ú|ŻPšîuĞk<.Ûş*ƒä"E€–2§żÈ˘ÖMƒu–ïӂmŞzŸĥ Eġ.N%‘-ĈíĴÑçñŭÛk (gK3dUM/!uç˘c!Z£{ç„hiĥĞ]R1tŽjĵ2ïGà âĜ†¤lWG•z­kÍÛÙżiHÓ²Äŝs{=>S×Ò‡"m)"Qbt”@ŝ@|à| qL'gŞúTzĦ;çJ7-蘴ËL³ûÒír~v 9u ĠĵÙUڋ36şàħ‚i|@‡“)ü­ÙÔ¤‰i‹˜qĕ<]üljŝ^ŬÔĵĊ ÌÛıìÀÈRNŜüvjÔ"˜‡1^г){˙ùŬÍëİ9³kDFçĤ\ĜĜK*äCáQ< AôfQÂŭÙ͆‰9z‘gğħ,;Í-[;”Ñ"0ÉlvΚ8Çdĵ²˜,,ú\sÙ \=²:„¨‹#}d| e„v.*ĤR˘à9%Ċ^zgŠzSĥş`qÈÒ:Ûċ­ÎÚl½OñögKkmĞTÏJ"\›Ĉ†`é8ùE|V]"iUä:&S½öħ´ÜħݰĠQ€\·§éӕ·˙b4Gŭ³aœìFœŞaŻn|\K} Ñ÷OĴ¨ŽêÌÊÒŬ_÷{eğןhLÏͲa–@½4%0ÌĆOĉóÓìŠ-ú'¨îžàġ s×JĊHŞËħñíï·uÓUm$8ÎöíÙ‰‹ċE—Ŝ úŜùĥK‚ôÇv§l†[2}È÷ŬžŬEg–ŜQş^Kì^1V²ßÙëħŬxXs³YJ†›B˘ +˙|WyRXħ²$ÁÎŻÍp=½°£‡ëŞ0çËËĴèhkÒĥÑmâġZğt›·yj]Ežì×"B°e;ŭBûžò× ÷ĥĝÒ½²îJ›Ç p*³W“-9éĴe³T'­¤|§úU×­óÖ]|QxŸˆ–vïÁN-éàäÈÖyƒeIB‰H°b\ú •bò4$SŒ¤C1ÔŸŻ…™˜dN9Ż;s€Rߏ” Ğ+şP‘ĉ·=—ĥçPK@ëŜIĈé6ç¸oġ_PĦ=Ŭ¨ƒ”pêèo!Ħ܄?ħ’f3] g)-EÀCùò…#%ĝ6 19xzá ïç6ŬèH5Œ‡çíïßŝù[glȅĉ7NznŬŒn Ü8ô6mŬÙ m­7¤ÙĤ–ßKY’ÇŭġĊÌéVW˙=Sh;žäĦMÏEBgA#8&ž“lµ B ’œhŞ”!7BLpŒ¨ŝó׏§úPí@‹c# şĞ¤ċD›èÑ…¨ԘŻ!KûÉĈašW¤’°g$vşJ.ê&%nêF'Ïşş&âMC-èR™$ j†Ž4}6ĤIÊA4ıĈhd- :ĵ}k% bÀÎiúçëöçaŸN*ŒyÄŝ™àBXŭŽĵÓĥ£ĞhÛKۙĊ×>EmRş&¤Äˆr;ċÑTI‚G£NAĦP-RWúÒ^i@ğ¤Òä³ĥûŠ`îA°Z¨Yv¤”,יmöĝŞË7G"6°˙”ÓôĤšŽŒQ§ayšÊÛâèHMĜş%Ĥl ÍwrâO³ż[ĵ^ĝÇOäşYĜĈJġ֔İ·ĠáXçÛ8`nŜ|boĞ éy!ïµĝkÍ|Lş²Ñġ^s"SˆGž$géΔ¤C½_^ŭO€¤Ï_ú endstream endobj 132 0 obj<> endobj 133 0 obj<>/ProcSet[/PDF/Text]/ExtGState<>>> endobj 134 0 obj<>stream H‰ŒV]o6|÷ŻàËNá0¤Ġ·Ä—kÓ^Ż@íîú@K”­ž$Ş•œ˙Ho‡˘+i”;ĜNAğ;;;³äĠNöŬâfğ¸zçNĥĊ‚sÂÁ?x4‰"ó”Ĥd[/Ù·ÍŒ²8ˆÈöaħܨZĠJ-LİšŽñY’ZiIÌA4Ä<”™$˘#•jöäĦ4 d˘ÈAÚZ˘ë3d'‰ġR#ÒÀeÌR.ï ÂWŽc#ê2#QZì%é;û DŸ—F| ˘cŝtR~ìğ‚ò‹Ñ‚t­È\dUİLĜX4íĉLv}Q†ş—ş¨ÔɔÖ}k$ÑZâ3½êmż³%îԐ)´£ Ì^vr ħµ QjH£³ YĦŠħonĴÈşƒêĞüĴ QÉÂXV]úӄ TFúĤ’•¨höÒIj'mšZäÒöbSόškpêŸçĝ¨PšÍŒ2@Ó)÷'¨ Nġ¤e%éÀʌz<ŸzOÔ³ŭíz}ûUġ<†a˜<ĝġ$<ĦɨžLj#JÌO—ĤÌDeŭ׏ĵAĉ˙iÙw pùiÑD|Ġ ~ĞËĈsàĂO&A”§hf˙éÂîœçkİ­€èSÔó]ƒöÛÙä@Y ı\ŜËJµµl , GKS/ö—­šê¸ÂtˆĜ[ ftfħ8Ó_F4ĵÀĤŠ‚0³1?²]cÀ ÌTŬbҗĤÄnm…µ4`ßY¨äW6YNa˜Áù.SPçĦ̤ĴÛJÚşÁĥÏV+‹½qiÉ=gcÊßÙ%0Ĉ bäx@ÌîH?lîȟ–ˆ`XTÎĵcçh8/ğq£ŸŬ›£¨,Ċ; Ma2…eİÉäêd¸—A †–˙ô–ı­Cċ)/xĈ”ÍcĊÍW\šz”Co!’ [Óús­ ƒ/†ĉgóˆO˘ž8ÔZs5:e÷ŭ+ ½ˆ†O,şùŭfsğ}Ġ£^<‰£,àé7x4òql}‘Öñè_ç9̙U°A9ËA~ù(=|ŜĴÇħĈçf@ƒsÇàx°ÛL^i%ӨǪ–ċJì1èĦìyf8´tŸ™ ÇÀgg38 ƒ Î˘İ ˘SÒ\ĥ%7îFakXNp¤ĈËÍx‚ÌMÔKÁ\ ¸Ì›îûŻĠqKHÒx7A4\Ĵ‰5ÎIÇñÄ/pĵë ×2ž/­%ĵwœn?˜³7˙zìÍxġàP:àI­.Óó­ò\xËŒM‰_<ğÀdLO,²àmx.ĊZµG]îË?:ğù…Ĵ•n•D<Ĉ"ËrY/Ż1ħáeëġNê{ĞJWҐÇ4MŸÀ]mêvğĝO€Ċñh endstream endobj 135 0 obj<> endobj 136 0 obj<>/ProcSet[/PDF/Text]/ExtGState<>>> endobj 137 0 obj<>stream H‰ĵWÛnÜ6}ßŻàş°‘"uyLì$p:…³íK\\iv—­D.(Ɏû -ú½RÚµv½J ( ¤™3sĉÌE/Ŝ~ddŬÌ^-f/Ŝ0ÂÈb5œDĝƒRN&('‹z‘5ŝ.ŠYD#)c²x˜Í_n·`Jŭ…üM.7ÊĴĦ9[ü†ŽâŜcÁŝAG2I( Ž(—2˜/6ş!j磴EWƒiRôH£M¤ŬYi×´änM ΨêîŒ8¨@5@ì ß@?;sAD.ċˆv5Žön~ċÔŞ%ŒÊèœà7°$<ŠĜŬí`=, 9§Y…çC–D²ó•DWNŜuĠàlš‘§T$= ŒĊ܇ġiŝÇÙ“ݤ˜ôÚè•.”)}nŠ˜^‚#Ġ%€ÁčŞĦ$+gkröëâ‚É,êÁ"£?ecÄÀ'p n"D%4J³8>NÒÚI<ÁZÈgx……&£‡ÂœÂLr*2ys~î1ÔöĵùEÓ\"o§ÊğµM£—U/ġşÓ­†&Ôġ‚S–ħÌe½Ñ)Ŝ‡ÌĜqfŒċ4‰Ĉ‰ ‚ J(nBQnĦ)T™qĈİcKŒ6çr`sĠ™˘Ġ֌+[ÂJĴ-f]ĞĥĜñ/½Ì›-AŜ„†`/XDe&³1<ëŭÏŻ Ù*×ê˘Ğ”#ğޏòYċX†ù%XÑ<~ŞœÛL53b*ċ…ÇM†ĵŒ}ĜE‹â0@àËÖT)µƒ˘­ωSĝáʤ@ġIċ4MSq²ÂÖŞEvvNWw\Xda œŞÎ‰ŞŞ=çMˆÒAÛ9ÄĈV€mċ‡ġkGĥN×Ê=â£ĤĞZÒ´+mèİ_üŭ"Š2NbyĥÓOŞĝʅíµ4E6g4ŽG–ȇj:ԐOy,+¤ÜE•Â~(ŝ"= ıÂŠÔ )°5}çñ€X,òaZúêİ;œĵKìŞ0™ˆÑKìħsò°Ñ(ÏŬ~F`ž÷SP‚{ùĜB3LYOŬSI ġÖa‡—¤°ĉ\BCÄ]İ˘µ.¸|°ßùÚàۘÛ÷ Š §)”ŭh r·`6êúÖĞU9”öôˆ}ä䐸°ñ>Âĥ…0­żµ x.ifÂħ„œípš5İm‰(CLÉħ˘x$hžÊ‘£mŻ^_~ŭóÍĠçË××ïŻoŜNĨϓ,;Ĝ—•ċ ›ÂŽq ɲ݀ży˙áíÔÄçh.’x úİ*Ş,Ħ†]ÌŬ<ŭkÎ^,Ïöŝ/ƒ@9üĉħŝeÍyJ¸TߌN›m·Ĵt1yÔì;çğ7—Ì1.ÄÍwSçÊ",ìGÔĜWVWŒéMŭêÙñĜy8T(ġŞ ùÜĞŞÛ÷˙o¸bö{+‰ÓÓ[\ŻpY…•X[ŭr`·ĈwĜ´ÎZ³TP–ó…½ŝêyÄÑ6ÏlÏÉáċĝԟû+JNâÜB­´)ÁŬ€šÂŠ%fÂÇöHRÊóá,BmOǙ¤"llŒöƒ‚§ş3M}İÙ1òqí›Ħ-MŒSµ|ÖÈ'Ğç?âŜB…]|¸Éê·Oĥ/ê•·ŜĜí/ĊU…ÇişíÖşÖï:/éî³8áK‹Ÿ ¸nŽŽĴ1Áyà'÷}œ?Ŭ·Ÿĉ;2/üPŒçĝ›ÒK{,˘hòÌ3µ³öèŭi·NŻ7ŝ§À/›ëW?’Kë0ƒ‡Ÿ+ =ğHJÎ_b…—š€ğß Èg‘J–Ò> endobj 139 0 obj<>/ProcSet[/PDF/Text]/ExtGState<>>> endobj 140 0 obj<>stream H‰ĵW]sÛĈ}ׯĜG²#!Ĝ°Ú'G–;ÎÔI&búRu:KpI˘ħì”Ĵĵġ74?¸çî$@VŬN;ħÈÁŭ>÷œğßüŝ‘³Msóíâĉ›œqĥXßpÁBüƒ?RüâYħĊî&dü^7a&IÄ/7³û­Ş7şaeÍŝ¨mSšš‰€sö4 û¤lħe" ĊÓ|ĝ+üGîŭsò/ó$àyì"À4LÈñŸf˙˜ßñ$M‚lĥĜjĥĠj-[—‚mĠ³fK­kfµħU—żè`,}Ôĥ3ĝboËgĠjÖî5ĞĠ–O³ĉPlç^|wƒ43žħ; ÷TÊQ ó‰Ê.Ñ'Jı†AœĤLfQúlgëv˘,.2|äÏÑ5žs_SġŠı4…Jâ€K16vé}¨Ôf*bšÁˆÇ}À§93‡–™5kÑMŭıĠĥVz†˙XĞbÜà`~—ä1ʛĝĝÖe~—ħÌĊ݃'T—š:ß°Úĵ°C£³‰îŠH‚°†A>Ĵ¸iWpl'ŞY‰ y Ï~ìkkvì>ÏŸ8G‘¤Ìa'}ò"òsä½Ğ*ĥ¤ĥĠşo]av{ôè-w@˜² 1IĜ[éóşĤĦ{żNM;—LĈaìTġJßvKm˙` UMV8QÑ|ä`Xŭ`¨·raÊjĥÒMaË_ĊjŭÂ]´´½ĜM…m4‹§yß1t7ÌúŽ%Dž9_ÓH~ı=y À)°vħpÛs,òŬ²™,0 ĝ™Ùm‡Ħ˘og×c|RŸ§ ”ĈAŽÌHvm›…ş.G–ñ}*뉨Z–ĈòzTLn}¨Ŭ<†ÀRĞ•^ui y 2œˊJÙr]Ê{"èUÙ[b›‹ŽıÀX‚³ …€\çÂ7ö:ï âŭˆ½óVoò~’ˆ Bûúĥ}-–ö§Ž/lı›ÒGvW[ŽŽ4— çD˙W ƒj’( ò8äĴÂ>ŞJO!”‹ ċc[RÊt:ó~ċs,´S-DĜO°×Ċ ż;n·$Ŭ½Ĉä­£ïF·M'{aŬ2D²úïŬPŭŒ˜k îm {VĠDĠܝTö˙Sèn ż„Ò(MĜw‡êġMŒĈIaè ’Wô„ĉĵWĊ߈#ŻuÜêu6ġrqÌ ¨+O¸Œ,Ë?£ôv ) Ê"̀ó¨;…FCƒ8§xNi4täàß½Ù"örSbRG­Òk˜•4ŻÖl4ŝβÄsš^S:40×ËĊo†c÷#dċş#Ûäê˘qÚ8Q_ïxj%¨pd6\Ács šŸ[V6Œ£\)eÌ7­ZVŻżġÍ‚0’ÉŽ‡òĈ4Ìñ6/ŸËĠä2†‰[Ĉ%F•ċâò°ğˆ*"\şq2² ĈĉEÛ)É@Î\&“‘O’ħ2XÚ8tgpkUY•ġĈÍşéä# ˘Ôëy‡6!eêİuK§şgöÚö˜a–c O_lЈ9nBQ ŻÖ÷zŽp•ÁfhKIÉsŽ+T£ƒÒ-îw­ln×cyxQ$gÇ=ñUiÁè~ŻpÌÂ8¸ç!ISß9v;2 ĦÓéDx„V˘Ê½išrYi‡ü]ż Ŭ­µSu_{œÖ ”`VDqëjÜĉօôˆi·ŠĥևwYej:ı•§xbNĠh:à&JŭÚu‰°íQ,)§Ġ A½Z?Ûİ…Á…#ùÈmN²tRĵt Ò,üxUUĦ§ıŭŽŞœê¤ŸSCn–ŽTžµ%Š&?ôŞ0)˘Ê²†tí: N½ĦĴDĦWái]I1ÎġĠԏ7ĊE¤9–}ŭDä%³Ħŭi>àİóĜZìûä<°Çg֓7µˆÒ ĊKé,Ô#ÜWúÍPQ”™YcÉäíÓÏı,â-˘àïÍaùoñ4̓ħÙ‘#ŬV@„ò—SÀFu IĝZ—-ħ^R…ne_Iĥĝœù 7Ĉ9SExœ—§tÎ9?,kBaĠOŽ>Žâ>:½\ì²\Ñì#~Ĵ˜ŜiWpP!a˙e7Eq°`òè;wñ"ċId Ĉ†²aóß?Ü˙ċ‡.Î$ş$lùĜx(ñHŻġE\Ç@f:ĝçcQSò(`-²ÉÈ \•ŝÄÄİU„„ÜB%‰0ÛòYWŻŭ ›žfŭħ/;h„äórK/.ÁÂX ‡<ĠÍÁÒü@Ĝ—#Ĉ˙sğË £.Â?5ƒ*ïʖ,_ÙLJ‡–ab—<ß'.Ez-ñ#JNé5Ì÷†jìŠNTB€éƒÁWĊ~oœ—ğëi‹œwbêàÔĠ8êA“e uS+ċÉ }ˆŜŽÄ ŒO¤‚ĵ^AĝİSÒïJzÙÒğކ~¨Üı„ĥ&Dğ֟UÑNvô \}ıK‘Ĝ)Ž‹+u$Dh~ì#N>Vó ĉéÈ M~Žĉ³ç*kÌ9Ú|ħMw9yˆ{Èċ5ˆ­tëÑëuÄi†ŭ|*§S}ú_<ôrןœÔ3—áìTx~E(żÓÎ0ġ†™3Ì×,8ñ:k*ğğŸïÍŝĠ–›m xOsöñÛOìŜĜ½ñ'0İı<>FŜAÜÇ ëÏğ‰LžBdFéÎâ„Zö°¸ù—ŝMŠ endstream endobj 141 0 obj<> endobj 142 0 obj<>/ProcSet[/PDF/Text]/ExtGState<>>> endobj 143 0 obj<>stream H‰ĴWÑrÛ¸}÷WàegäŽÍ%$ğO‰m³ÓMÛXm’N"! EjAҎ÷­ßNż·ç‚¤$ZbZÏt'Žâ‹{qîıç|˙ğ;Î×ˋï䌳ċú‚ âŝJ›§AʖۋŬk™_„Aǒ-/7]Ŭ›†ÙŠŭĠ¸ĈցHÙÇgïê³]ÇDŠ——ËÏÈ ‡ ĵÏÀ)ƒÊ˘@FCœúañËk'q.–.˙ü騸°è,H¤<Ž_&×QÖwµÛêÒŝjfò !‚x<äq_[wUŜÒ}6şa+c*Ĥ‹ÂW ˙ÔĞwĈéĥvÁċug(Ó6lĞżŠvc|Áלq(Ù5¸[9.ŻÍzmskŞ–ĠkĤYċĞĤӛMíZúfW7]•†=n,ŝÜj[µĝ²Ġ=³mCĈÙ\—ìA— è˘×"à)O)i2&})¤*ΘR2£ˆO1½ûÓÎĵŻëvTÉ)§á¸tFĝ~ UB1ŠĠèLÛıÊ#ÉÌW·Ĵñ‰XE CÏàêPÜ1 WÌĠ]…Ĵ­ŭÍÎävmñÁÎá;OY]ĴùR̉|2zŽĉß6¸D{€4>4ĉA¨@4`“D{’/Ì×ÖPa3Pò ƒNŽò³Ĉ´­'Bĝ+k|ë)Y §3ĴkpGÛnêĊtî§1W€˘‡2ĊÉqò ÉPñ>ǽ}0À1Ż€j˧=’Î4]ÙbĈÇó‹ş#šŽ >^˘ŸħJéıöĉöĉÓêĤŭTĜ{âíşÔ÷>˙ò7“‰GgÖ5êŻ+$\ş'èˆ{˜Nq‚qa„Rŭϊ ŞĤĤqûZ€/p ƒ%JDqOI(÷˙g ĉ0SXˆĊ,ĉƒ"n4ó ßêÂÏîX`8C§?jgô”& X Á~4+‡9x"A•ßÔ8ÂĈi„Š|C}/ĥú3Şík¤$ûÑfc:ş:ñٙ]İs³Š>ÂOßĦżh5xFéž;r Nšxġ$ÁxÓSbMS…žŻžüíĈ*ó8ŝÇLW%şÂ!ħÈ@H~è*NĥS)f./c`a.ĉ¸#|’%“¨h&AĈT“˜£‹_y)™II(Ÿżé\ÒTaR'‘¤™A}mm”èî´+"§ooooŻï^ħÌjZ\Tğ^+§süûúÑ<"ĝÉ'kZ[–ĴéVŸĦ#¤=˙~ ‘bşeOuçXŭX1g›/ÁžWŞżÁâ½)u‹ümM ÁL…zj65~ğKĈ› f疟ùşĞ+˘ġËtÛmÖA‰Í>§à<áBħH%A”fGƒĉô% Á­i ”<™îżq9 7uĠBğšërìÁaŻs0 y“ÎŽû­İ˲~ìG·ĞVş$„Šŭ]›~#Ĝ~WMàéĥó§_Ó&×ö |yİ·;ZB¤è߀/Aš‚ŝ Iä=>ŸÊ‚8>Ž™ô2üHù9ħÍ`!â IyLš[@ƒqÏ­=saŭR8qŠĠs4_]† œ×XœŜM T'P†ĜZYŠ‚4IXҎ½Ħêĉ^‚,ž„u&ÓĠE—{WĤÒÄoqïÊvd~ŸXcÛNS½ž€WI1Ċ3TŝèĊ#íôÁË 8zĥĈµf4ûôŬÚĥïèÚĥ#ÂúAÛRÓF…§w}¤'³sžsDŜlf‡4™Eœ'Ĝ"bRAjù፲Xċ…(vE°™µÂXëǑGnìL·¸ñ\ ŞÒ89­öìŸŜ̖ S,œŻħç% âl$ Ŭsga·ĵ?ƒGżĴ‚ÒĈúÄÔú¸g^§ÀâY™Ê;-ƒ˘ċ ßŭċġŬírÎ'1„Ä!L“ûçEÛù×ÑN; J;yf(ħf`èÀô²—LżEĵê×^E%NEW„Q<ĵà ïƒüÈÒxüÒY‡6BhבqĠ…Ĝü‡ŜÄ҇@=ĵê7Ğq^5 ÔÈzşI·4jŭC…5dÌìvXÑ0T<üîß"ün^q’ìDżßL:½,ó {œ<6Q3ˍ£§&]¤ sÚ5˜Ôž&‡Ü’ĜŠÖö|y{³ŭ˙4Ó” ŝ 3‘™–ì§üïFšôö08ĦˆëvôËèH98‘ĤŜò{‡Ŭ ĝĥNç_öŸé{˜àb´ÄäŞÎXé‘dĥœyèßİy½…8ĥĈ'fçœ=ƒé0z&9M0Nj?zû‡ÀŸ;]µöW3'kx …b2ÉFU#ñ‹ìdò¸äQ-Ŝ ˆ];›£ÙĞôLÁA"‚l˘}}ÁïĦ]şœĞ—§Ĝ˜|N­Áb›äf‡™ÜèÖw£1´Š1¸÷ĝ4;xsĜ^$Z|n~ ×ˆ4ˆäœ—ĝ'šlj˘ÈżĈ˜Ì+rUÔü]v³;ëEí”PEĵ 86ŽˆċËÚ)Áëh‹U‘£+ϙ™ĵ"•A'qû˘ÖHPÈÓYîĝ•˙ZéíÇÜ6!†€™ÙÔ½­²->í5t–ÔBègÉÓ¤q³Î,Í \ž+Š5Ìù´C•Íd·ŭ3lIıŞş%kôL3\FŞ0Ĉüƒò]^KÀ,ĝJ†À¤L}`Êx– oÇ!šJŭ7ġîÉÙûM ċÌ?^²·Żf7µC?<¨¤˘ŠVĞRAĵx…§ž˙aZ‰q4üg+yB¨—ğˆtğĵĝYĵ endstream endobj 144 0 obj<> endobj 145 0 obj<>/ProcSet[/PDF/Text]/ExtGState<>>> endobj 146 0 obj<>stream H‰¤WIsDçWôÑĦpO/ZıÁL B2.ŠÜĥĊÈjÓjĊ 7ŝ9ßÓbˋR¤¨İL§ßö½ïmïû$Ùşùfqóî[Í$[Ĵn¤d˙-V,–)OÙb{#Ĝ_‹œŝÛßü>ûçv.8äÉlħ1ìöĊ÷ { ˘Ó@Jž$ÑQÍliòÍöѸ…½ŻĵYwğĝóšq‘ ‰ .TvÖÙŞİr_ĜŠm²š=S1gve–›%{|aŝ—tó4nıĴü5+3á\ żDÄÁ1‘Ĥcƒ_üv> SÔĴĜîJ³5•Ż[×*³g)MÍVÖ ŽŞÎ†ZŸ=–/_‘ Aï’ŝáÛ($óĵ³dˆÖVċ ЍgŜ²ż³ĴXµa۝qYµDʖ,ëÌOGÑÖ·ĊŞï+óœċž­ÊlMê+ëI;ïbQ\&2ıĝ6zĤ<šEZó0<ċç§żšÌ™_ĴġSŒ2 žD\0´²Ĵ´ˆŽŸÜ6+‹żM zÄ2ĉjvJìœY琊]tRq•¤Á(Sm’VµîaÖÊħwêá–wŜĦŞÎ[EµĤȳêíó8{żÉà(Zħ_ĞÉaÍñŝa&Ù'³ó†°`Jŭp;ݎ%e `Kĝ§^Uĥ\Öm÷G<ˆuYĴ74qĈşuV&-GŒŞŠmí’J„ŸSMùU’ÇqÀÂŒ?Koĥ5?7Yċ›íT~ƒ˜ëp$,‹XN6 Äj–HĴ”Z Á› Ŝo bsÌïmŸVÍ0 ÇxHHĠşWC/jƒ İáéob}t‰ŠàRD,DsÖÉ Á.UÂ7pÈF…<û’u/M¤)E|ÍFLšPQ)=–‚§:ì:ӗ-s& *tu!’ÑĦħ“U­&­êHC“ċÌjgzc²%’·*¨aWvÏòÉ?#5™G•Ğ\ĊZž¤4F(­Ž­u”ËĴBo4Ԋ*/ċá–RüÂiŸQ)ZG&í ġħlò˘Z³%B]Cè[Ûì³İ‡Ĥ9"PáÁVŭ·İ êïÀzV{×äıŭĤÈ7䋷–Ġ€¨œ 6ñ‘_Qœ’ %B„-Ój„~úÀvYŝù]SÑ7†Áċ‹Êô\Ĥ"iŬ=Z’IÜċxkŸ gċìv’Y”­(aA˜pJÑežó)vİ’ÁXò`iXS£H&Á”M0zÊĤ–!$ݚŸMžQ‚¨ÊËÌ{ä‡òJd)‹ÏíN=ĥƒ~N늌‚Ğ-:0Q1dÌ+Ŭ?€+şkÑ×{~6+öcîíéĝ: y‘ˆTxŜ>fYğO_Ú²"Í­Y­Šĵ 9‡ĝr[=Ħ–Eĥlí‹n­hPRwíjÊ&ˆs€ .ÖĠX€Ü9ğ˰dôàĴٛnG/ßŜPŻÔşŽHÍéœig jwrËM°ŽEiÊè+KÄA”vacEĉÖMżPE( ˘*ĵië‡ Ö“‹ê5¸ĵ3dl˂˜Ù#W˜gĥWƒñúViò?|…U)ħJbĦ|úo›„ÂäÇ{ËĦĜŽÒÇ Ü×÷=8“9xe‡ıvaFatF鄢éD½[˜0 Eʓ)ŭŭĈ°ûğğ;‡£E h(䖆IêB`>+ğĊ ûZ߂.CܗUGŞ[ÓZŬO!ŝC2‡ŽÜnw™+j˜ïÊĥXµ{cîÑhËĜ_Ma<5pöĜĝRÄuZ]o_wĊEÏşfß˙Žż9ƒm°˘ċ˙ApKĥÄ,‹Ó˙[ĴtŸ|‹ÌÔv†+KŒ…iħˆÒóAĝ0#ë9AHŸÚáÒbŬ„ŻQµ8 d2qsuëIw‚bk­–´r5Çġc<öĉÙéÓ“ĥñ¤ÔÒhÔúĈr;×Zs=WÜw‚I+˜ ĥ“½4ù¨:ïíîĊë ]9‡ûo~`ï­ÛY×m> endobj 148 0 obj<>/ProcSet[/PDF/Text]/ExtGState<>>> endobj 149 0 obj<>stream H‰ĴWÛr6}÷WàQJ,†^*™‡‰ílM*q%;ÊĴ÷’`‰Ô”ïÛ~CòÁ{/²Eo’JÍĊ”L ğOŸÓ—/ŝö‘³­ğĝzyñĊ7œqĥĵżà‚Ċĝƒŝò<ÊÙr³-ŝ-×q+•°ċÓĊìêA—[˜-Ù?LílU²$ŠŬ͸bßKDĞğù|ù3OÂġĵ½žûë8Êüġ‘ˆUF·ŝsößù‚ĞLEùì}½=îMÙ8ÖTìŝXĜpìéÁ˜ ûĠ–‡cŞr÷ü›˙˘ĴžĜĈĴĞZ7fžlóÀšĉ˙Z~ Tp!n]ˆ™ŠeÄG^ĝ°Ö°ÑLĝ\¤,Íó(m}î‘ĝdžŸŞzCnîġ'mŝíĴİ™.7Ìé{<áµµŜíĜ}]í™fWŸΞj}8àWëv."ë ñœçlÁ£T*Ċ–פx‰ÒĈpôŞ÷ş\VŬ D7],S²ë›Ğë~şŭê]´c+ƒïìŝPW@ÉWÑċƒ4ċ­Ċ>ĈĈÂċç/ğğŜáħUë<ĝÎîíNûûċñdÉФ—ÌÔuU­G¤óö¸_™úïĈ5qìżüñ¨ËĈŝg wáùxxLĥÉ$XR›5xÍYšFDµiŽu \xÇ1ĵpÑBġVß2ÄËŝlŜÍâ¨(Šü’Ĥ˜ßÍÙħÜP˘½ċċgcô@ŞĈüÒ´”<À%½ĵK˘–hç´§@´‚ˆv^h‰ Ħ vmֆĝżbSYÜiù ƒ‚DĝK‰p^D™”éYŭÍ/‡ kĵH˘¸"ÜEÀ½OĠÀE½Ù„4 O4¸à–PdžHÈ%ŬışeĉÄXR…WÛÊ5òĦÖÖ/XâĜĦz€Ġ½·ĥy¤Ï³"ÀËhN’úĦ [YΔŒÛ˘2 û]9nŽ[љÑ/Î(F˙(òÊ)½zğ‚{êwÄŽƒĠ–ÇNˆBER/à½‰|‘mĉ£9Í·’…Ï·q&$œÒÑfÈD¤CÚŠ$O½›ĈûzÇvĠĥ-w İĴ´ ŒèĜ“!ĉžáĤIöiœž°ïû5ƒQˆ 'öè ²ÉDˆrA‘EHĦ”8G§@Kï¨EöÑìž˙"b‘*“E%§ÄúÈ>•V4ĔŽÁÙyŽ­oÔ ÚŸžì¨Myż=½ÒÇ%sĠÄt-sÙJĥ´´4ĉêŭ1DœÂ÷ġJ…Šú; ‹˜„†S½}è—ÚOϞ D—.y7żl磉üH…Ë”Rg\z³9ĝR ñÂİnì„É·!Nùfµ ‚÷‡0p‹.vJċŞBúB1ċˆ?ÖLġ“`h hoĵ›Ó8Žá.kdzĥfÈ(I1ĜÚ7y@Ŝ†;,€ÛÒŜ[È­‘Ĉ5Žñ{vĦ+²ï“Òœóu 'îğĈv0ÚÖ zÑÓHßĤ35]R c|oK´ş5öWÁp™ÙX´Oâò:Ĵb,ğ×4ŒÓ1lĵĈ •„²u~Ëċ0uk\úÖ'@,ùÇ×8!0ĉ¤éaĵ˘^›%ĉ´Ŭ¤Ô$VŽÑiZĠM…D-ċ‡‚Úş múrÊ!gQŠœ†3xġÁŭxЧTFi–c|íÌëzbíĈ„HĈUwdï´=ž§Q,Fg{R½àœÄ^ĝÛ Êa‘ޏ0_$ Ÿ%ÂÁĴ=˜ûƒ9<ٝ&D{ĊUuxíöĦA2 ]öáëïÙUUŞ–üžSsš˘éÏŜcXò/;šÔMŭ8éİòӉğ3™F7ˋ˙ 0w„n& endstream endobj 150 0 obj<> endobj 151 0 obj<>/ProcSet[/PDF/Text]/ExtGState<>>> endobj 152 0 obj<>stream H‰ŒV[˘H~÷WÔ#n´¤.ò¨´³ÛsÛdÚl:qĉĦTf…"Ît˙û9 £N§C›Pßİóó ³żŸڗ£ċz4{GAëŬˆRäÂüĝ Â1Eëlä˘=<ëĜüû9róDŒ×ßÁŒ5f„Ôffž˜ÔfĜġŬĤRɽÔ] Äé=Ż„bÎz·‹Ûn™ïcĈ/ŬFÛİBê¨JUŜ:žM†‹}­&Ij0ˆz“ñ”1†™Cƒ8¸2ù~*+™ ùR¨äħÙD]ká,>?=˘²Šò$҉ĦM0L ċÚ)ĴžŸ-Ż^£ÇĠj…ĉŸ’`î_wĴg†İo@@Ôĝ˜^:iÒéŭİ.¤k<úëbġݨewvĤ’t—Ĉu"‘ÚYRĴ']De iÙ"-wRË<–65 ê&ğ´:d²Jûô§YtD¤eg^|>e[İA4û,Ġñ$ד2TódtÏ÷ˆ äR:ÚK*– g·Š”h_Sñ}‘.oi Ïi`ÀÎ2|8ĝ‚œó$%ZĤy¤_Q¨HíC“‹ ÎÓ´qĥé~*ó$rÄXW̜^+ĉĞ×·˘A9O ­:³š4qy—ġĈaĦ<ŬnV˙ŝ’ú´ÓÍ‘{YƒêĜVò Ûâ tn}²KŸĉœÑğǂŸßœ Ÿö’‡w$gT`q9—⃌˙·e×·§mŞn,žµ{|Œ²qñĤl„ FíK7œĵĞ)Ŝ8Ħı´UŜ @k şICq "‚Ġ#+ìšsËa.>~ü7D܎ó*üg~0ġŻÖ_áŞE]×=Vr}œšû–xßRQw•A$i9XPĉžA‰ĴĊi•fƒÀ­:œœ#Ġ)Oê½ĤeiÓ-Î!pb&#Ìû,êT†ŝ"îysfcüħò(ƒÚ1šŭ€ô DûmΞ%ş4èû·÷­„*…òa^™×ĥEûñԅ˜ŭˆ6έ£vöÀ·†~cĜ´ÓÁ~‚skmX´S,TĊĞN÷‡ VbĝPy\~‚1 ĠìrXµÀİ€O'ÏY¨—°{JİÈ_gêÁ]‡&#Ğġè—Ğu£ endstream endobj 153 0 obj<> endobj 154 0 obj<>/ProcSet[/PDF/Text]/ExtGState<>>> endobj 155 0 obj<>stream H‰´W[oâ8~çWĝV4í\[:ì2P•töaf…B4ğ$ŽrévŝŭÚqBn…•FĦÄßı|ç;ĥ÷OŽéèÑŬÏ1€À9Œ 2ŭC:4%8áHGúuĵ‘,ÉŞŠóïèûxï{Aèž 2@F@š%AtœÜAY–ÇXüċüNMî e¨ÇŞ 0bĝ(w~ÒĈ;żuQ—ĵj-ݚrWŽy(YÒbÜzUxOœżùb͜Gažêbö`]ƒÒ”‹¨Ĝġŝñ÷ÄAZüRC¸mżP /ÜVÌMıĞı]BĠ܄¨VV´ô BĊĈÖÚ˘{$ŝÉl¸AZ9•k§I’<΀›󏲴íġ~n– o†7€Ž€˘™’ĦiĵċY#XL}Áĉ`XĴJĤfĜFoXöl;;ıaLëì‘hd‰ÊĜPëµ7°‚÷ ¸mĈ$MƒŬÉH›Nî0Ĉ#£ĥkG²“„$)Ĝg~úSµ)(™Ġ`ĜEä¸^ÖËJg.ôŬ=û-‰ŭÄež˘AÙĥZ’4Ûîƒ#Mĉê…ÍËúuemgöbıX=¨”ğ­ħf­˙\ ĉËġúE¸òċa9ĥ+Vío6]UV_Ÿ…kÍ×]%^Híš ŞğÉwIèn¸Pù°\g´÷éOÜÏΛCi‹ûĝ:ŸÛ/ Ë#ĥ+z`ĜÏĜ³?Änž ĉ2˙# ż'ÇkúFÙÊF¨C÷£ġDÍǏÌ/ X{É>§ĦĈ$ĴĈç4s³<--” h  *’˘*Ċ•3Î7֛焘­wn³’ĦôÁÉ?KB+‚[I‰³üƒ›Ÿ2pÈ#ŻİĦ.oül³„˝JŸMĉ 7üH§—š†¤)JeÍÚĤœœgôO@ß2cìŭ˜€ĊW0#ILʙɲ&Mî4M“Ôñé p ?ġ“w/•;™ŞP—L³•îX-HÙÎè?ÓĦ*§ endstream endobj 156 0 obj<> endobj 157 0 obj<>/ProcSet[/PDF/Text]/ExtGState<>>> endobj 158 0 obj<>stream H‰´WKs£8ûWèHĥ‚`8&ħ3ċ­‰+“9lf –‰vyxA8Éŝúm!ƒÁÈ SS[)W ôİğéÇ×Ŭ—_VĊċä:œ\Ŝ„Q¸™`Œ,ĝƒŝMq`(L'ŠáF˜Ú6 _'FRVÈĈgá_ppMŒ1Aálb¤ùşJ²-yŝ/Z |*yœuċ#߈fëŜÛ;,Ór]"•>ċ–Eœ&hG“Š•gĜ²,†ż+hcŜŽ%Ï3DjÍ` ñˆ×5´+u͢e•>³Â|Až°½\÷9¸ŬA]=—hSe‘ ·^ÂŬäé–ìg°a.À .lߏÄÒg|Ç×C#ĵ“E&X̊Q7ĉoÛQ¸Û"OW˘àY<€ |Q.² ϸĜ­ŭÄEı¤ËħHSÁwcÓIÖ%Ï˘\‡ŝÁŠ|ôk6ʽ_óˆ&ŭ$ÇDf9ül->ĈÖ(ÉwômŽ-êqĠ°Ê´È*|› ’\ ^ĉEJI/c÷ÉHîóWM!èß*š‰ħúXJyĥֈö?B/{£„|Ú˘hÊjĞt€tĝ*à݇<àĠ³(h4ĉó,>AΰtîĠœUäğìșjZÌIô8Ë>3Ğ .ĝÀ—Úê~†Câ}ÛÔĴ}Ş^żïğŜĦZnéÍo–w³Ċ—E¸BQž•‚ߐ†u#ÂıìëoûĜGc:Êö ­š ôüŽ@‡’ĥo4Z•ĞıÁÂZ<ħáµQ}çœ’éËĵ§Ñßl}€ĞrëÎûK½´Q·-ÓdmfÒ¤‘Q•2öĜ>ž9ZÙ½4klêÒ1éó€‚Ȩ‚6˜Ż‡ùç`ˆîêñz5‘¨2i4LPá‚Mˆ=È1Òğ>\ŬÌ!`J8F!WsÏ9%™ô“wĈ²’}ï}=SĦmzŽˆÓÎaC—>`Ô"'H@ŭÏ M ¤³v,É·)ˢ|ŬŒ’‡yÏR9Àc.J}ĝğфÊor Œ·ĥH:5ŻÎUXúSëG)f¤UW´íŸ]BLÒĦgeì~ö™ĈŠ1tÂÑúTĠïMy„J‘4îŽ ĥ½ȉ jˆVk.dx Š.oƒŭšáĞ5‡ŬF$˜šĜġĠĤ!ŻÍx°“Ô`˜ĥWc[5°-x •Ğ)}û¨}È ,…›Ž÷ż)x2XĥĉĥÒFŭP2],‹yĈXŬr2Ĝ z-J§³°˘È ôu’JğŸ‡0ŞÇ`żá¸--KùB×;_ıxAr§k ĜáÍ7šn%~îϽ-ÚOé[KR^!pp|ÁÊĈġ^'%ÂF΄˘l[[QU›AY]ıCŒfÈ8,ğZşGŞi4’:D8ßû7ëçÈ~Èĵġž:RŭòĞÚ êÒ ÔF×Ĝ“ħŸšì‚_sqŞ.Şġ|Ósœĉĥü¤}ŽÊͲàñ‹@?ŒèÇZ\ßĦ›ĵĜ]ˆš²,Ë3Ï.<Ï3]*IP .¸;h|zK]<5ƒ gáÖ.‡“˙j£˙ endstream endobj 159 0 obj<> endobj 160 0 obj<>/ProcSet[/PDF/Text]/ExtGState<>>> endobj 161 0 obj<>stream H‰ĴVÉn#7½ë+êĜ $šKŻÇì8"ä2“§›’èéEèf;v>Ġû˘–&CDÖBÖ{ġŠwż38ЏûĠŬƒûŠ1 ĝ‡_ HûdEሟ}¸˘„:Ž€ŭ_Ğ/ÖîM&çX½Ŝ2JİċŻ˙Ü˙‚f[F0Ô§‘…ÓZ°5µhmµ˙i´íŽĥù°}–EĦ_¨<Ïr8É4Šuzlm½ÁuEÚè,m œ‘ÁY…ZĈ*Rí>o2áa…+ÜÑĦĠ[¨ÎU ô³´ ÚyħQXġv†ìĴr9ÊÊŬnŸVEŞl²Tf½YÍ2QâqŜTRF/eaTÌŜĴ·B",ŜÊ O*üŽWTqŞà#t ‘ -“o*ïNÑûöIĴDé¤L0EJt:]ÁJ)cêDŜp˙jšĞéúŝÀŬÁĊ›Á¨4RÑbĉıÏRƒÓzß=-=ŭ†ž>xl‘€5üĴòjÎθBÌż\síéZÓş€‚„kœŸù›ĜŽíÌ{¤7ÎèÁ Ĝ ?|ĤÀ“ƒ˙&ï(1Âğ¨`\×!Ψ£ž´ĥĊ^g—-ġ´Ûí 0¨Ö2Àwì- |ŻĤA=ŸRġ&C3Hl'ì›Ş´½™N(SFvi›^½Hۚ§‹2‰YdĴ˙š ­k8ۀàœ"i$˜÷³şè’z_ħ<+ñìŭHBuÂĠŞ\ó 7ËóÚÚC‚[ú1-ibµE-Ġ2Eġ‚kóĦôĈxÂíìÈèZ5*ôñŝ& <ş§ŜQ=¨ċ^B—V2\ —ğ(™Keß-p*ƒ—ä ÂN'µĊsV ú¨MqÁ1ġâ˘ÜÀÒt½ŞIt‚sâŽEéó œy@‰˜wDʇAÑ&=@p¤ßD¸ùŭ#¤½£=2Ñ $ñ&û˙"DYÜ’Eú€·İß Ùd~, vЙѧÄG ĵ›È°ŭË0­M4óżÍÓğÖ ԀĠ ܞ_Ĵ?š!Ŝġ0~ĵÖÑkZù€ú‰Œ²;ïê­ Ügç÷\OZá×5<}ü ÷Y~ÎòöMFİKÖ[×u‰c}ˆc¨‹JKUŝŞ"²|R‡y$&ǵœz:íöĞb'#U endstream endobj 162 0 obj<> endobj 163 0 obj<>/ProcSet[/PDF/Text]/ExtGState<>>> endobj 164 0 obj<>stream H‰ŒVے›8}÷Wô#Ŝ²$.†Çdn•­ZïlĈµ/“<`=J@ò‚˜$ûġÛ 0̖Ëe·Ô§ûœÓÒÍ3}=û¸™Ŭ<ĝ@`³›#^ÁŠ$n›rĉÁߛlĉı+JaócĉTŒ U"ûğo͖Äġ#?ü¤¸ĠĈzaèëà§”"ÍyòÀŞTÉŞž/‰çy ç_7żÏ6żé˜şY³lŬ”[VÙbc†ìeS(~(x–*.•Fpó˜"âˆV"ßwS…^şîBOêĊ0‰M½=tG¤%{Ȥx‚1™^~ZކqµJ…ŞMWµ³kDĤWŽŸ•2o V_ꝳN×@½sıœœ§{!k…íì"ô~˙4œİÑïŠĠĜ˘hŸħĉ{‘ş–.ê4§`ûq;ġ"Á·Û‚oŒ9²*ÓŜÒ˘a–O |v˙óuJÑÚ³Z@µ‘ç9óße^ĤÌcżqöâÈCÛï°Ÿ¨Q“5e$Ô%ŝòérJşZı^0Mù”fßYw,XµmÇèBwÏ ¸ŬûViɔîÇ;Z*ĵ`KĊKöĊQhi¤‹ùÒGuûNYäŞÑy;͈Èt;Ĝ³CÑÔĈ¤Zê–Q€üÁŞŜĈ'ĤÀŠíĝÏëĊ[gĜہ L<èĊÑŭĵ^TĊ…ځu˜Á^"YĈĦF]êydàúŻ \ëè(ö\GÛû ş -Ŝ)µlY I›×ÓPOvE[۞]Tc›–F. ÈÏW@†Ià’ÀŸJҎhfÚXUúŸÈĞj͢$¤Ġ)qĠièxò—)9ʀĈgĈNžĴ3#³ÓßÉħH̄:VÉIÛ*و\÷Yî,¤èĈ âúNçé™Z@VÌBœBÓIŻsžƒ´¨%X€½;ğìV …çx,Na™ò–J.QĈlß;kä½dàê³ĈñŒÉù(> endobj 166 0 obj<>/ProcSet[/PDF/Text]/ExtGState<>>> endobj 167 0 obj<>stream H‰œVێÛ6}÷WÌ£xı"İ‹ġ˜Ŭµƒè"¨ċà7}@l!ż‰9äğK+˘7”—*°“İh˘´ žìĉ€1CaŠ›Ŭç™_5`}6ۘIyˆSÊÀŬ“IÎÎç|w8WÓĈ­ıqòEl/ÌÜivvMŠ#n§§(Ú,ĵ90Kçg éTiW‡ìdk™g†ÑĊĊJꗃ2úÔ1Eĵ˘ü(Tµu˟ħ9¸Ôş§żËX Py{p‹ ëZ|YÇş,Fɞ*ŞıÒx—$·2ÓäĊÖ ·Hb8F=;šĞx/ NÓ<ħùğüşäâr+µÌöàòït]>gıB…A’gfUwġ-&j¨·Ñ ~]o/„†ŝbç ²ĝ9EJ nWaÓыş£ úñ]^÷´É'2YŒtżÁú *¤•”ž.·-O[&fJ“UJn³à6JĊ҅oBċĊ”8äŻ=}Ĝ¸ìXŞá—%Äâz‡yż–Vòpa\ïXbÓefpÇXĊXġM)ï:˘b–÷w›Ġjù‡A֖òd&>lÑĉ³Î9áƒJbxùĝŝí#pŜĜ°ŜÜ­—Pżtò7ñÍz‰Ö†‹Ş >§ |Ç#^Ż…Í-¨pSµĦÊl+v2CÛP˘(SŬ6?O˙½ =ĥ|?›şˆ1ÓôçŜ°)„úŻ€wܞYCCI£µ–d=0ÍsÀ+ut½°ŽŻÔÑeá§uĴ:ßXoÜ(qäq|E}˘ƒŒ>˘`/°xunÏîÏ+ì¸KAXìLŸ^½é"6DX­­œ÷üíŠÖÄŠWhŒ(ô;öOӏuZÍš…A½°Î}´²:·]mbġ÷ùñ_%÷/>M“O3x÷;Üçê˜×/ú“ٍïûěMS¨À…ıPŻbKĈ™z4 a8 ;ġŞËhòż_‡ endstream endobj 168 0 obj<> endobj 169 0 obj<> endobj 170 0 obj<> endobj 171 0 obj<> endobj 172 0 obj<> endobj 173 0 obj<> endobj 174 0 obj<> endobj 175 0 obj<> endobj 176 0 obj<>stream H‰lU{XWŸI˜I@ a°Mì$*Ú ~PTÄGÁV bÀD ­òFi@”‡DlĠ–-*y(F)ˆ‚™Á*EKwħúıÛjëvÑşV=wÇNĜŬżĥßÌŭ}sÎüÎı÷œsϽ8f'Âpw ûH³B37(k‹15ÑhSıóJœŸfÇOŸêVŠ*ÇİñNâ kquıœžŝÖA9&ÂñĴÜ ,C159%G='ŝ]µ˙"Oŭ½'ÑgߟDßI\8‰~“¸H˜µ)Q½6?;'1#[’Ÿe4d7ĉ$&ÌSĞÓÓĠ‘6ÏÙêÈÄìDc ŭß1\x01Ž‘8fo‡99c3˜'ùĜRĥV8akíħġ–‚aY)Љ01ĉ…qĝĝmÜ*òˆö‰jEÑââ$q——Ŭzğvb1G “Ħä.²ĵC>“8Iâ$Òiô‰½ÊÀ~ĜaŽC¸!‡[SÜĤ|6ehjŝÔ3Sß8.v,s<éĜxßqL–)pšĉ´Ċéó4çŭÎw\—8— .CòUò#òİİ W½k›ë?èùtŭÍÁÍà6ì6ĉ6!“A t•çÉa ÔQŸò!ü]ڋ¤Lu¨‹¸L"Oè˘ç’6Ħ‡”Ú~Ĵ|;^‚M`%Xroò• ÌP‚ġĤL`ï ʉ‡ĥ?Âu“şĊŸ5mA˜ä+#¨›OYO²ò‰h²ċÈ}Rˆ" mİ#İï@Lî@óuc'ƒè(Ìúݵ PCɐN—4ÁÍŻĴ¸ĤÛPŝŠëïĞċn²Ôj€ßCÄ__°-‰ĦŜ@€Ġ•H¸ŸÜ{Eàêŝ€û *èíĞ/òݎĉĉ>ċ` ›Yùw8Rüm79KŒí íÇşìxû‹ɍÛ×*̈́ġDÙ›/˜ M­WÍç ĥ43'ş‰†„¸ÑJ˙˜èÈĚԺUùĦ’ÏKŞ[Qş0]Ñ>˙5Ç֞og¨‚Ö‚ê·dgfj•1ħ­ƒwğÛÎSÉŜ/ÄÁ̉ùMÓiıáQÈÓCfßB×| İ˙1pW€ìü+Ë3ĉ?Ġœ~ž+gtdca™s~’){bô~‚éµ'·Àf+d§\xœ‡ÑoĊü6~]0„Ü£Â<"ˆ<ˆĉ!+ۂaFÒ|äܟz†‘C˙ÙàLÈ ’ĊĦóUI³(4:¤A:ˆ@4˘á!°L /À‘ö$Ñb€”Š€óҋôéĴĉĝÄ͆´ŒĤ̎3­'Ï224kü'üWŜ[ÌWŒ/ġ&+ŝĉvw­2|‡ƒÂ¤ğĦ—XösÂs=eC*e^ŜŜ=ùŞEĈdïiYúŜġEŠı'FXĞAú(£+£wJ< äàk>YÊ_ÜŬÓ£IÈAÔiÎI01 Ñ+²rŽ?%$äĴĝυ§$h[4Ħ•@paŬ€‚µ'‹ĊŸ²P/,Ĉèr]0Ş“@¨ˆWş/?P4íj.:É ¤4†+ Q1Ş`V2ĝ}ÓĠ{wb—l/+ÜSȧ- ŝ,ċ à·„ts.ĵĴœwe·Z¨>ĉÑϗ5§f¨çĉFsÓ}EËÎú’LGĥm•r•&'uŞfñu퍳ÊGĉuÑ1ñĞĠ޽ڣ$5ÒÔ´ow£Şuç ­"äcŭĵˆ555ħLĦ­Èî*­UŽĥĦÂxÍÁK8ü,ğĠóz=Êy,‘ Jô†ĝÔH$Ä-âM4şR'W)tĊbĦN˜„Ĝ÷B=şêr‰Óç'1 z†IÌ;‰s·,ċG”ÏĜ° pŬŒĠá5&­ŞDKäġğuP ] TɊ8ĜɁO>ĈBíw‘ê%ĊóEüIúj°ä£mİÑŞEk5óÑ{ ¤§Ç ġò÷áżü6ö‰èġ‰™Ş Àğ˙ŝ°SJñ&souWeĊJeıİÂÄ|UU˙ŠziÓşÔ9‘1-—s™Òê{뤽 ×Ï(;;ó“ëTUù‡Œ9 ™)—Żĉç,t\óċ|}ÍêŜa˙ m­&úIYQú İOŝ;›ÀÁ~6™^%àM˙Ŝš\ÍPc­5ÍS Ĉ ĊĴ"f­nÜxÉÈP/ĥï£Xxw ¸0à4toDE‰‹Ú”ê[ġ병M÷.é#j ާŭ—4úıGž<ŭçħŽ6­ddEW!¤*„ĵÛ³pVÈûx@˙yۈ+LsZìÑX%/÷óòĉŽ×o7XZTÂığ"ÌÛ(Ŭ•™V–ĥğ´r·2*r­pĦPë&bµR8oò è ğIĵĞ%OCö‘ÔC!7 ›·S]ġa5[ĵ£Ùg7[³ïëlöžx„.Š›J—|¤_5ğPGċP*•&WDá1Œ;äkÊ×Ä­H˘ï)IçMŬ"t…)1Fss=kwיÇ}Ïa̽Ïsŝ:Ïğ~ïzë·ÖúíFXN40„ÀY²pŭJ58ò] Ğ‹œ’“}öhnžĠ‘SûϞÖn+ĜrRĵ;uß4È]F½· mjżċĞ/Hyù_•”h9e"ĠAҖ¤Ô41).b§NÀßòÇêÂsğ³ŞÚĴ²èĊZżóĝč ĞÒĊ 11ğ– 8ÂÁA]S›ıĤL:•žğ:QKII7¨7*6T†~M-³"Ô/yŽ€Çg0ĉÁˆ†ğךtĠ’‡âBĉ³‰Ç™‚eaıĦN…Zœ€SżÇÑxŻóô7-ĤÙ èM×Oép p™wï{#OŠûżX)`ÖûĊĞĞ+÷d—KŻw=@­œÉo NŽçFOÏp˘İ~R3ê’tvua€‹ÖDb$(Jâp¸;$ŒpFî?Ê[ĝTĈáx"ÁeÙ] ŠċŒP‰ |j\#wġ^²ú„ &uMîÒë ÁĈıÓ¨Ÿ&C.A;Š3ċ=Έ‚jÌ̝À ˘*! G…ċ<ÁC2ŒG;65pċfY@W`éZ˜–í/oĥĆWKÓ ÄÉŝlEĝœżS>ÇÚÓ,Ŭŝ>:CÔíÛ'òŻJàc–Zhš”Ê`ŜŒ×m‰·˘ï"#wa4@ô=‚ħò=Ó¨Öĵ€X ó~·NL\çӄ6ӕĤèÁ52¸ġèŝÛ{]¨:KEĦ‡X6ĥ#äaèuĞŬÉç6İ´ƒ™Ûur³·a&™ôĥ8ùQïI‹D<Á™íé)‰hš^ïV9iĜ݈“‰ÙaÔÛÂA#°ŒŜ<”`™üÚ¨·˙po;ŸéĦ;ĥD§èkŽfÑûÇàXù˘QN3%óŭ58‡0•j aġAĉb™0ŝE ‰bô(9”ï­ò|K•í :›ŠJSÜAB TCıq+s[ÉQ›6ŝF˘*#Šğċü‹! ġ8Û'ÑEîŜ•µësÀ]”?瑛…,ÚĦ­-÷œax^@ŻżˆĤڌ#pˆ>x ŠwIħ/ùNjĝġ{!—ÚVÀNŬv#§ħ\Ê+:\QĦ•m?ۖ²y¸(a^V°€ ˘ ġagèÚĜûÙ_Ír^H`5…ĥ~g:m‰O‚zWÔYµzR k{u·w"ÖüOí£. ïEMİŻĠNeƒ£ĴâX #ĠĠu;˘ò¤ö­OĠR"Á﭅ùò­…kߛ·‹ä0öOI2@!Žpç,¸˘-ԝ˙™'ñUú˘o‘S†ïĞeÇRò/jݵ]z*Ò#—ÒbÏK\ĊdÌ aı³‰lኜEŽš;Îm|תc™Wĵ;, ŻËV9›öĤĤjĉ/57Xy˜È%ZtÉèGXŠUÎFµvfÖôZĝè>ŝu^Ô˜iúŭÁ]iVX–RB­ĉLŞd m¨Ĉf˘ƒİ•$˘˘Ñ7(k/ÌÂȔ_-mĤÇ{ÄDï˙:I\ZœÙdB¨î”ğħŠñO“N\U~e“A¸ÔšSR&Uœ?ÚrM TuJ,Ñ„dLVz1â¸vꤞ›ĦäXô6Ĉ˘Ë<#˜,˙SMgJs_ è*°ŜŭÒÛä4'èlu·^é2êäŸX½Ñkfıšû­"WĉG‚árş‰B\SC×`ì§.ĦÑĉHl¨$ZİÔ69R̀ hú˙’Añȁ‡Ôâ:Q—ÖĵQ5pmé:…ÚÜQ[İ…Żqä2_Í/6¨Ħ­ˆ{êUğ•”)Ü×_,fß}­LnëFMS#—Ôْݰ-ĝĵ0½@,K]rĈU˜ğnM”ÂäuÜÎïL;-ċo̎×&°Ù‘aÙÔ=¸‡ş,”¸ş€+³_}Û^Ġ@D.ŬŬE7W·`‰ŸÎC˜UQZp$ïDŽ”Á°§V¨Ü­Rz—ÁSBg†ĉú—ÎĠ) Èƒ#2÷GÛÏKÙ Â !÷°\ş1Ç]†,W×ÎnüŞ2† `÷†€J’mG{Ìtġr2€MïG <ÁC´Ŝl€WŞÏ(§ok ³6Ċ;ÈC@ç(`Úëxê+ +Ğ$_Ş99œ-Z~4H@_ĉŒcÁÒ4}·Škš˙/ÑzÏMTŬ·%žJ;Ë0#ÙÖ°9GBœĈ O™@ĞN¤ìVۙĤ2JĈ46 R(ö3ĈࠅO?kŭ„s’)Q/šFĠĠ+3uĊġü†&ÒÛ;M'è"öŠ–VžL44h÷+éfñKœ‚ìPÄÁíh 3ğ{ η‰Ï+uóŝĉÀ 9¤˜Ú : Œ Şˆj´TŽ(üŜĝû— 18h—{š´#}÷ÚġÚEö´o:íeĊš`tÒ/ L¸ÌÖ|QêR²};ġdj05f%YF4%@mPĞbC•iĊrŬAliœ_ħ'ġžÈŒwĵó L~÷T]…„Cى‹qÈ˙c‡CĊ-!ÌĉˏÒzÚĠHĞF1ĈÓè`ù)ŜcFOğÙŭŭÖçÉù?Éĉ™k&Ü<OÒżgÒf6{5ġ.ZÍö‰X,B.Jò#³,’‰;ü­Şmİnä.‘%LŸúÎżu’`£Ü[2áú¸CŻRȃÍ,´aáżLWmPTe–Ŝğc$×ÛĞw›ÌœQ'g($K!@’”ä"ŸĤ" ĝˆP2 ".şÂ~‚ˆÈ hâŞĞې™Š³ĈŠÀŒÊŽÍ¤;ŭÑ{sú{ï{Îûqžó<Ïİp¤ĥ‘£=íİŠˆ;éxĈzaĴ]6‡ŭԗᓽ^…ñc£‹j9{$0ş|¸âŞMşqQኊLá;vm²Áİ-[Ċ”^ĥèĴB“ıĈx\{½ùÄċ!ÍËbˆÔşLµƒ/dcdP x“NN\ڔKkυŜ™ĈË0ĵ˜Ç´”0 g0²úĠ=gÀ ûy=…ç/ ñ¸LôXŠ¸§qİ-$eTŻ'OA C÷AÏ‘ ß[Ü÷|ôÖŠüÌÈ~!ŽżyŠŬ’•vùü£8˘;TZŻjܑż?[˜"}Ĥċ{A…K%˜Bq7E’'\Ğ9ŭ/˜`iµ ÇË3 Úñ‹ûŒ‘d;´Ù³4:äZSG ŻkĉWĴnV(=tHóó£ÚN‘wR”w^m˙ĜTéËĜÚj¤—Ĵ ĜdÈ;\¤ŭ!Éİż[âG.èl†ĤuŞšĠ;Ê5!ĝZYz”t¸=Iĵ&aħp[ĴÖ­÷ŜžŬÜÇĦ(›I;ñàuıÙ÷IF„—ŻŻËÓĉšÊÚZ4PJ=A‹ê0İk9êx&l·Ŭŭµıé†ÂÇ_)ïâ£\ЉBĊá.¤çfw 긄Ը5˄ĵܽĤmÎħmm8üĊj.ċ`ʙ&ȅ™NsğY)]r()gá=:’Ücî̕°ìòVÄ6XöĤzŬ/ıC!tàOC¸Cŭ>ˆ]Ä$³ĜvĊJf& 7Ĝ žŠġsw&÷­ŽA FCLƒċ¸ Ry'-Sż/ ĉ0BŜ ³`.$¸\úžEOj5'Ç\!˜ °0ç0üa("A ĦFv:ˆ A‘–Ĵ[JH>G!ß(DP[ò}Úİ‹FáicnŒ‘n³…/ĉàBş'zH` X°ÈĤ—çôP:ÒL[h/̖ĉc0È\uiûà(ï3qÔ09²€"8N—ˆE”+Wêיz4ÄYw= "öwígĠ@(×Óaê֋„KĴŒ.Ŭœ¨*ÉĠmÈÒàdê§ sÂ2Ċ8ΑYŸƒ~ʧ,ŭ†ş\ħ!ñZݵRġ˙]N*ğ@ıÚĈ…™ OŸ&s­şÓ%Íâfk´1ħZ%qŬşŽâH †r‰ğ÷LjÁ ğŜOÔ`ıxN”8kġ5cƒUU×Ĵ?ŬŞ„ƒ_ŭ)‡Yô’{·y@ÍžLîUÏcĦ…ıÊzA>ñ’#<ċ:ÊÄAIĤ¤Nî­Ċıu(~ZĊBİáÏ*W[5G&‘×ċ'S˙`ÏŜ` endstream endobj 177 0 obj<>stream H‰bd`ab`ddäóöqñĠÌMÊω¨˙aü!ÎòC–Gì·Çïżŭjc•e`Xŝ…÷ğ;˙÷ïa‚ó~Ĝ 1032rĤdeĉeĉe–T:çTeĤg”(h$k*ZZ˜ê€Hs0i "- À¤ı‚cJ~RŞBpeqIjnħ‚g^r~QA~QbIjŠž‚cNŽĜ˜b…˘ÔâÔ˘2  Ôi@ÀÈĜÎ0‡a‹Âҍ[X™˜ë×<à;ò]p×wŭŒK÷ŝ8ĥ—ùûÏï{Eŭ•͍Y µMۣɸÙñ”Ñó)ŸĤıĥxÁâ²#ŸŸ7zÒ|µéħö9­„˜²²JżŽĴ,р ŞŠàşş€Çşĥożü0wmŭò²#ÑgĊŽì^`íô‡+·;wĊw¤†ÌžQ5/àŸB÷Ħïû1~ï>Ä<ġ‡ŽhÈ÷Ĉߍ‡7~o<ôH„ünd˙ŽèĦ?KCĜù~T—3Îù1ƒùÇÊĠ˘i~ŝ.ú]ĝ½(-í{ ÄÒù߁â6ü.ĝ^ÈÊW1ï§éĴßħ3Ĝžs=àŝŜ'òSE ÀçĴÄh endstream endobj 178 0 obj<> endobj 179 0 obj<> endobj 180 0 obj<>stream H‰T=o †w~Ċİ:‘!C“VòĥŞÓîÎR Á˙àXİ:€Ŝûx‡£ÇĉÔx—~¤`ZÌ;oNaNĦÁyàĴ3y‹Öی:-ĉv™2ŽïHIèg)N9-°{}zd@ߓĊäüğ ˙ú.‰vŽñGô({Bgßôˆ@Ğí/wY"‚Xc=,NQLÚ’ Ò ·˙kdst½ıêDnBEdNjfì™]ÍEŸŠ”[wVżx3sJ…yŬŠVĦœÇûŞbˆ•Ħò+Àım½ endstream endobj 181 0 obj<> endobj 182 0 obj<> endobj 183 0 obj<> endobj 184 0 obj<> endobj 185 0 obj<> endobj 186 0 obj<> endobj 187 0 obj<> endobj 188 0 obj<> endobj 189 0 obj<> endobj 190 0 obj<> endobj 191 0 obj<> endobj 192 0 obj<> endobj 193 0 obj<> endobj 194 0 obj<> endobj 195 0 obj<>stream Acrobat Distiller 7.0.5 (Windows) 2006-11-22T12:57:21Z SCRIPT/VS 4.0.0: DEVICE PSA4 CHARS PSFTR 2006-11-22T12:57:21Z application/pdf DECNUMB uuid:d462cbbf-034c-4ec7-a2c8-503cf6bfa1ff uuid:7672f74c-1c5f-47a4-8e5d-3b40dbfbf384 endstream endobj 196 0 obj<> endobj xref 0 197 0000000000 65535 f 0000004676 00000 n 0000004803 00000 n 0000004909 00000 n 0000005564 00000 n 0000005691 00000 n 0000005841 00000 n 0000007718 00000 n 0000007845 00000 n 0000007995 00000 n 0000010304 00000 n 0000010434 00000 n 0000010563 00000 n 0000012257 00000 n 0000012387 00000 n 0000012505 00000 n 0000013168 00000 n 0000013298 00000 n 0000013438 00000 n 0000015530 00000 n 0000015660 00000 n 0000015800 00000 n 0000017757 00000 n 0000017887 00000 n 0000018038 00000 n 0000020569 00000 n 0000020699 00000 n 0000020839 00000 n 0000023082 00000 n 0000023212 00000 n 0000023341 00000 n 0000025340 00000 n 0000025470 00000 n 0000025599 00000 n 0000027790 00000 n 0000027920 00000 n 0000028038 00000 n 0000028906 00000 n 0000029036 00000 n 0000029165 00000 n 0000031061 00000 n 0000031191 00000 n 0000031309 00000 n 0000033157 00000 n 0000033287 00000 n 0000033427 00000 n 0000035522 00000 n 0000035652 00000 n 0000035781 00000 n 0000038714 00000 n 0000038844 00000 n 0000038995 00000 n 0000041196 00000 n 0000041326 00000 n 0000041466 00000 n 0000044150 00000 n 0000044280 00000 n 0000044409 00000 n 0000046579 00000 n 0000046709 00000 n 0000046827 00000 n 0000047290 00000 n 0000047420 00000 n 0000047571 00000 n 0000050640 00000 n 0000050770 00000 n 0000050910 00000 n 0000053571 00000 n 0000053701 00000 n 0000053852 00000 n 0000054971 00000 n 0000055101 00000 n 0000055252 00000 n 0000057703 00000 n 0000057833 00000 n 0000057973 00000 n 0000060543 00000 n 0000060673 00000 n 0000060824 00000 n 0000063275 00000 n 0000063405 00000 n 0000063545 00000 n 0000065652 00000 n 0000065782 00000 n 0000065922 00000 n 0000068185 00000 n 0000068315 00000 n 0000068467 00000 n 0000071408 00000 n 0000071869 00000 n 0000072098 00000 n 0000072228 00000 n 0000072357 00000 n 0000074423 00000 n 0000074553 00000 n 0000074693 00000 n 0000076219 00000 n 0000076349 00000 n 0000076478 00000 n 0000077725 00000 n 0000077857 00000 n 0000077987 00000 n 0000078553 00000 n 0000078686 00000 n 0000078838 00000 n 0000080907 00000 n 0000081040 00000 n 0000081192 00000 n 0000083359 00000 n 0000083492 00000 n 0000083633 00000 n 0000085426 00000 n 0000085559 00000 n 0000085689 00000 n 0000086190 00000 n 0000086323 00000 n 0000086464 00000 n 0000088445 00000 n 0000088578 00000 n 0000088730 00000 n 0000091251 00000 n 0000091384 00000 n 0000091514 00000 n 0000092146 00000 n 0000092279 00000 n 0000092387 00000 n 0000092902 00000 n 0000093035 00000 n 0000093176 00000 n 0000095531 00000 n 0000095664 00000 n 0000095805 00000 n 0000098422 00000 n 0000098555 00000 n 0000098685 00000 n 0000099967 00000 n 0000100100 00000 n 0000100230 00000 n 0000101666 00000 n 0000101799 00000 n 0000101929 00000 n 0000104046 00000 n 0000104179 00000 n 0000104309 00000 n 0000106519 00000 n 0000106652 00000 n 0000106782 00000 n 0000108707 00000 n 0000108840 00000 n 0000108981 00000 n 0000110956 00000 n 0000111089 00000 n 0000111208 00000 n 0000112221 00000 n 0000112354 00000 n 0000112473 00000 n 0000113617 00000 n 0000113750 00000 n 0000113869 00000 n 0000115122 00000 n 0000115255 00000 n 0000115374 00000 n 0000116500 00000 n 0000116633 00000 n 0000116752 00000 n 0000117908 00000 n 0000118041 00000 n 0000118160 00000 n 0000119088 00000 n 0000119285 00000 n 0000119920 00000 n 0000120110 00000 n 0000120661 00000 n 0000121235 00000 n 0000121742 00000 n 0000121922 00000 n 0000122554 00000 n 0000128248 00000 n 0000128775 00000 n 0000129790 00000 n 0000130017 00000 n 0000130322 00000 n 0000130408 00000 n 0000131040 00000 n 0000131233 00000 n 0000131416 00000 n 0000131463 00000 n 0000131488 00000 n 0000131513 00000 n 0000131608 00000 n 0000131738 00000 n 0000131870 00000 n 0000132002 00000 n 0000132140 00000 n 0000132282 00000 n 0000132391 00000 n 0000135863 00000 n trailer <> startxref 116 %%EOF hercules-3.07/decNumber/decNumber.rc000644 000765 000765 00000003420 11143760537 021107 0ustar00jmaynardjmaynard000000 000000 /* $Id: decNumber.rc 4175 2006-12-30 18:31:08Z rbowler $ * Resource-definition script file for decNumber DLL (MSVC) * * This file was added by the Hercules project. * It is not part of the original decNumber distribution. * * $Log$ * */ #include #define DECNAME "decNumber" /* Short name */ #define DECVERSION "decNumber 3.37" /* Version [16 max.] */ #define DECFULLNAME "Decimal Number Module" /* Verbose name */ #define DECAUTHOR "Mike Cowlishaw" /* Who to blame */ #define DECCOPYRIGHT "Copyright (c) IBM Corporation, 2000, 2006" #define DECLICENSE "ICU License -- ICU 1.8.1 and later" #define DECVERMAJOR 3 /* Major version number */ #define DECVERMINOR 37 /* Minor version number */ #define SPECIALINFO "Built for Hercules" 1 VERSIONINFO FILEVERSION DECVERMAJOR,DECVERMINOR,0,0 PRODUCTVERSION DECVERMAJOR,DECVERMINOR,0,0 FILEFLAGSMASK VS_FFI_FILEFLAGSMASK FILEFLAGS VS_FF_SPECIALBUILD FILEOS VOS__WINDOWS32 FILETYPE VFT_DLL BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "040904B0" /* US English, Unicode */ BEGIN VALUE "Comments", DECLICENSE "\0" VALUE "CompanyName", DECAUTHOR "\0" VALUE "FileDescription", DECFULLNAME "\0" VALUE "FileVersion", DECVERSION "\0" VALUE "LegalCopyright", DECCOPYRIGHT "\0" VALUE "ProductName", DECFULLNAME "\0" VALUE "ProductVersion", DECVERSION "\0" VALUE "SpecialBuild", SPECIALINFO "\0" END END BLOCK "VarFileInfo" BEGIN VALUE "Translation",0x409,0x4B0 /* US English, Unicode */ END END hercules-3.07/decNumber/decNumberLocal.h000644 000765 000765 00000021322 11143760537 021706 0ustar00jmaynardjmaynard000000 000000 /* ------------------------------------------------------------------ */ /* decNumber package local type, tuning, and macro definitions */ /* ------------------------------------------------------------------ */ /* Copyright (c) IBM Corporation, 2000, 2005. All rights reserved. */ /* */ /* This software is made available under the terms of the */ /* ICU License -- ICU 1.8.1 and later. */ /* */ /* The description and User's Guide ("The decNumber C Library") for */ /* this software is called decNumber.pdf. This document is */ /* available, together with arithmetic and format specifications, */ /* testcases, and Web links, at: http://www2.hursley.ibm.com/decimal */ /* */ /* Please send comments, suggestions, and corrections to the author: */ /* mfc@uk.ibm.com */ /* Mike Cowlishaw, IBM Fellow */ /* IBM UK, PO Box 31, Birmingham Road, Warwick CV34 5JL, UK */ /* ------------------------------------------------------------------ */ /* This header file is included by all modules in the decNumber */ /* library, and contains local type definitions, tuning parameters, */ /* etc. It must only be included once, and should not need to be */ /* used by application programs. decNumber.h must be included first. */ /* ------------------------------------------------------------------ */ #if !defined(DECNUMBERLOC) #define DECNUMBERLOC #define DECNLAUTHOR "Mike Cowlishaw" /* Who to blame */ /* Tuning parameter */ #define DECBUFFER 36 // Maximum size basis for local buffers. // Should be a common maximum precision // rounded up to a multiple of 4; must // be zero or positive. /* Conditional code flags -- set these to 1 for best performance */ #define DECENDIAN 1 // 1=concrete formats are endian #define DECUSE64 1 // 1 to allow use of 64-bit integers /* Conditional check flags -- set these to 0 for best performance */ #define DECCHECK 0 // 1 to enable robust checking #define DECALLOC 0 // 1 to enable memory allocation accounting #define DECTRACE 0 // 1 to trace critical intermediates, etc. /* Local names for common types -- for safety, decNumber modules do not use int or long directly */ #define Flag uint8_t #define Byte int8_t #define uByte uint8_t #define Short int16_t #define uShort uint16_t #define Int int32_t #define uInt uint32_t #define Unit decNumberUnit #if DECUSE64 #define Long int64_t #define uLong uint64_t #endif /* Development-use defines */ #if DECALLOC // if these interfere with your C includes, just comment them out #define int ? // enable to ensure that plain C 'int' or #define long ?? // .. 'long' types are not used #endif /* Limits and constants */ #define DECNUMMAXP 999999999 // maximum precision code can handle #define DECNUMMAXE 999999999 // maximum adjusted exponent ditto #define DECNUMMINE -999999999 // minimum adjusted exponent ditto #if (DECNUMMAXP != DEC_MAX_DIGITS) #error Maximum digits mismatch #endif #if (DECNUMMAXE != DEC_MAX_EMAX) #error Maximum exponent mismatch #endif #if (DECNUMMINE != DEC_MIN_EMIN) #error Minimum exponent mismatch #endif /* Set DECDPUNMAX -- the maximum integer that fits in DECDPUN */ /* digits, and D2UTABLE -- the initializer for the D2U table */ #if DECDPUN==1 #define DECDPUNMAX 9 #define D2UTABLE {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17, \ 18,19,20,21,22,23,24,25,26,27,28,29,30,31,32, \ 33,34,35,36,37,38,39,40,41,42,43,44,45,46,47, \ 48,49} #elif DECDPUN==2 #define DECDPUNMAX 99 #define D2UTABLE {0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10, \ 11,11,12,12,13,13,14,14,15,15,16,16,17,17,18, \ 18,19,19,20,20,21,21,22,22,23,23,24,24,25} #elif DECDPUN==3 #define DECDPUNMAX 999 #define D2UTABLE {0,1,1,1,2,2,2,3,3,3,4,4,4,5,5,5,6,6,6,7,7,7, \ 8,8,8,9,9,9,10,10,10,11,11,11,12,12,12,13,13, \ 13,14,14,14,15,15,15,16,16,16,17} #elif DECDPUN==4 #define DECDPUNMAX 9999 #define D2UTABLE {0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,6, \ 6,6,6,7,7,7,7,8,8,8,8,9,9,9,9,10,10,10,10,11, \ 11,11,11,12,12,12,12,13} #elif DECDPUN==5 #define DECDPUNMAX 99999 #define D2UTABLE {0,1,1,1,1,1,2,2,2,2,2,3,3,3,3,3,4,4,4,4,4,5, \ 5,5,5,5,6,6,6,6,6,7,7,7,7,7,8,8,8,8,8,9,9,9, \ 9,9,10,10,10,10} #elif DECDPUN==6 #define DECDPUNMAX 999999 #define D2UTABLE {0,1,1,1,1,1,1,2,2,2,2,2,2,3,3,3,3,3,3,4,4,4, \ 4,4,4,5,5,5,5,5,5,6,6,6,6,6,6,7,7,7,7,7,7,8, \ 8,8,8,8,8,9} #elif DECDPUN==7 #define DECDPUNMAX 9999999 #define D2UTABLE {0,1,1,1,1,1,1,1,2,2,2,2,2,2,2,3,3,3,3,3,3,3, \ 4,4,4,4,4,4,4,5,5,5,5,5,5,5,6,6,6,6,6,6,6,7, \ 7,7,7,7,7,7} #elif DECDPUN==8 #define DECDPUNMAX 99999999 #define D2UTABLE {0,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,3,3,3,3,3, \ 3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,6,6,6, \ 6,6,6,6,6,7} #elif DECDPUN==9 #define DECDPUNMAX 999999999 #define D2UTABLE {0,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,3,3,3, \ 3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5, \ 5,5,6,6,6,6} #elif defined(DECDPUN) #error DECDPUN must be in the range 1-9 #endif /* ----- Shared data (in decNumber.c) ----- */ // Public powers of of ten array (powers[n]==10**n, 0<=n<=10) extern const uInt powers[]; // Public lookup table used by the D2U macro (see below) #define DECMAXD2U 49 extern const uByte d2utable[DECMAXD2U+1]; /* ----- Macros ----- */ // ISZERO -- return true if decNumber dn is a zero // [performance-critical in some situations] #define ISZERO(dn) decNumberIsZero(dn) // now just a local name // X10 and X100 -- multiply integer i by 10 or 100 // [shifts are usually faster than multiply; could be conditional] #define X10(i) (((i)<<1)+((i)<<3)) #define X100(i) (((i)<<2)+((i)<<5)+((i)<<6)) // D2U -- return the number of Units needed to hold d digits // (runtime version, with table lookaside for small d) #if DECDPUN==8 #define D2U(d) ((unsigned)((d)<=DECMAXD2U?d2utable[d]:((d)+7)>>3)) #elif DECDPUN==4 #define D2U(d) ((unsigned)((d)<=DECMAXD2U?d2utable[d]:((d)+3)>>2)) #else #define D2U(d) ((d)<=DECMAXD2U?d2utable[d]:((d)+DECDPUN-1)/DECDPUN) #endif // SD2U -- static D2U macro (for compile-time calculation) #define SD2U(d) (((d)+DECDPUN-1)/DECDPUN) // MSUDIGITS -- returns digits in msu, calculated using D2U #define MSUDIGITS(d) ((d)-(D2U(d)-1)*DECDPUN) // D2N -- return the number of decNumber structs that would be // needed to contain that number of digits (and the initial // decNumber struct) safely. Note that one Unit is included in the // initial structure. Used for allocating space that is aligned on // a decNumber struct boundary. #define D2N(d) \ ((((SD2U(d)-1)*sizeof(Unit))+sizeof(decNumber)*2-1)/sizeof(decNumber)) // TODIGIT -- macro to remove the leading digit from the unsigned // integer u at column cut (counting from the right, LSD=0) and // place it as an ASCII character into the character pointed to by // c. Note that cut must be <= 9, and the maximum value for u is // 2,000,000,000 (as is needed for negative exponents of // subnormals). The unsigned integer pow is used as a temporary // variable. #define TODIGIT(u, cut, c, pow) { \ *(c)='0'; \ pow=powers[cut]*2; \ if ((u)>pow) { \ pow*=4; \ if ((u)>=pow) {(u)-=pow; *(c)+=8;} \ pow/=2; \ if ((u)>=pow) {(u)-=pow; *(c)+=4;} \ pow/=2; \ } \ if ((u)>=pow) {(u)-=pow; *(c)+=2;} \ pow/=2; \ if ((u)>=pow) {(u)-=pow; *(c)+=1;} \ } // MAX and MIN -- general max & min (not in ANSI) #define MAX(x,y) ((x)<(y)?(y):(x)) #define MIN(x,y) ((x)>(y)?(y):(x)) #else #error decNumberLocal included more than once #endif hercules-3.07/decNumber/decPacked.c000644 000765 000765 00000023773 11202676511 020673 0ustar00jmaynardjmaynard000000 000000 /* ------------------------------------------------------------------ */ /* Packed Decimal conversion module */ /* ------------------------------------------------------------------ */ /* Copyright (c) IBM Corporation, 2000, 2002. All rights reserved. */ /* */ /* This software is made available under the terms of the */ /* ICU License -- ICU 1.8.1 and later. */ /* */ /* The description and User's Guide ("The decNumber C Library") for */ /* this software is called decNumber.pdf. This document is */ /* available, together with arithmetic and format specifications, */ /* testcases, and Web links, at: http://www2.hursley.ibm.com/decimal */ /* */ /* Please send comments, suggestions, and corrections to the author: */ /* mfc@uk.ibm.com */ /* Mike Cowlishaw, IBM Fellow */ /* IBM UK, PO Box 31, Birmingham Road, Warwick CV34 5JL, UK */ /* ------------------------------------------------------------------ */ /* This module comprises the routines for Packed Decimal format */ /* numbers. Conversions are supplied to and from decNumber, which in */ /* turn supports: */ /* conversions to and from string */ /* arithmetic routines */ /* utilities. */ /* Conversions from decNumber to and from densely packed decimal */ /* formats are provided by the decimal32 through decimal128 modules. */ /* ------------------------------------------------------------------ */ #include // for NULL #if defined(_MSVC_) #pragma warning(disable:4244) // [for win64] #endif /*defined(_MSVC_)*/ #include "decNumber.h" // base number library #include "decPacked.h" // packed decimal #include "decNumberLocal.h" // decNumber local types, etc. /* ------------------------------------------------------------------ */ /* decPackedFromNumber -- convert decNumber to BCD Packed Decimal */ /* */ /* bcd is the BCD bytes */ /* length is the length of the BCD array */ /* scale is the scale result */ /* dn is the decNumber */ /* returns bcd, or NULL if error */ /* */ /* The number is converted to a BCD packed decimal byte array, */ /* right aligned in the bcd array, whose length is indicated by the */ /* second parameter. The final 4-bit nibble in the array will be a */ /* sign nibble, C (1100) for + and D (1101) for -. Unused bytes and */ /* nibbles to the left of the number are set to 0. */ /* */ /* scale is set to the scale of the number (this is the exponent, */ /* negated). To force the number to a specified scale, first use the */ /* decNumberRescale routine, which will round and change the exponent */ /* as necessary. */ /* */ /* If there is an error (that is, the decNumber has too many digits */ /* to fit in length bytes, or it is a NaN or Infinity), NULL is */ /* returned and the bcd and scale results are unchanged. Otherwise */ /* bcd is returned. */ /* ------------------------------------------------------------------ */ uByte * decPackedFromNumber(uByte *bcd, Int length, Int *scale, const decNumber *dn) { const Unit *up=dn->lsu; // Unit array pointer uByte obyte, *out; // current output byte, and where it goes Int indigs=dn->digits; // digits processed uInt cut=DECDPUN; // downcounter per Unit uInt u=*up; // work uInt nib; // .. #if DECDPUN<=4 uInt temp; // .. #endif if (dn->digits>length*2-1 // too long .. ||(dn->bits & DECSPECIAL)) return NULL; // .. or special -- hopeless if (dn->bits&DECNEG) obyte=DECPMINUS; // set the sign .. else obyte=DECPPLUS; *scale=-dn->exponent; // .. and scale // loop from lowest (rightmost) byte out=bcd+length-1; // -> final byte for (; out>=bcd; out--) { if (indigs>0) { if (cut==0) { up++; u=*up; cut=DECDPUN; } #if DECDPUN<=4 temp=(u*6554)>>16; // fast /10 nib=u-X10(temp); u=temp; #else nib=u%10; // cannot use *6554 trick :-( u=u/10; #endif obyte|=(nib<<4); indigs--; cut--; } *out=obyte; obyte=0; // assume 0 if (indigs>0) { if (cut==0) { up++; u=*up; cut=DECDPUN; } #if DECDPUN<=4 temp=(u*6554)>>16; // as above obyte=(uByte)(u-X10(temp)); u=temp; #else obyte=(uByte)(u%10); u=u/10; #endif indigs--; cut--; } } // loop return bcd; } // decPackedFromNumber /* ------------------------------------------------------------------ */ /* decPackedToNumber -- convert BCD Packed Decimal to a decNumber */ /* */ /* bcd is the BCD bytes */ /* length is the length of the BCD array */ /* scale is the scale associated with the BCD integer */ /* dn is the decNumber [with space for length*2 digits] */ /* returns dn, or NULL if error */ /* */ /* The BCD packed decimal byte array, together with an associated */ /* scale, is converted to a decNumber. The BCD array is assumed full */ /* of digits, and must be ended by a 4-bit sign nibble in the least */ /* significant four bits of the final byte. */ /* */ /* The scale is used (negated) as the exponent of the decNumber. */ /* Note that zeros may have a sign and/or a scale. */ /* */ /* The decNumber structure is assumed to have sufficient space to */ /* hold the converted number (that is, up to length*2-1 digits), so */ /* no error is possible unless the adjusted exponent is out of range, */ /* no sign nibble was found, or a sign nibble was found before the */ /* final nibble. In these error cases, NULL is returned and the */ /* decNumber will be 0. */ /* ------------------------------------------------------------------ */ decNumber * decPackedToNumber(const uByte *bcd, Int length, const Int *scale, decNumber *dn) { const uByte *last=bcd+length-1; // -> last byte const uByte *first; // -> first non-zero byte uInt nib; // work nibble Unit *up=dn->lsu; // output pointer Int digits; // digits count Int cut=0; // phase of output decNumberZero(dn); // default result last=&bcd[length-1]; nib=*last & 0x0f; // get the sign if (nib==DECPMINUS || nib==DECPMINUSALT) dn->bits=DECNEG; else if (nib<=9) return NULL; // not a sign nibble // skip leading zero bytes [final byte is always non-zero, due to sign] for (first=bcd; *first==0;) first++; digits=(last-first)*2+1; // calculate digits .. if ((*first & 0xf0)==0) digits--; // adjust for leading zero nibble if (digits!=0) dn->digits=digits; // count of actual digits [if 0, // leave as 1] // check the adjusted exponent; note that scale could be unbounded dn->exponent=-*scale; // set the exponent if (*scale>=0) { // usual case if ((dn->digits-*scale-1)<-DECNUMMAXE) { // underflow decNumberZero(dn); return NULL;} } else { // -ve scale; +ve exponent // need to be careful to avoid wrap, here, also BADINT case if ((*scale<-DECNUMMAXE) // overflow even without digits || ((dn->digits-*scale-1)>DECNUMMAXE)) { // overflow decNumberZero(dn); return NULL;} } if (digits==0) return dn; // result was zero // copy the digits to the number's units, starting at the lsu // [unrolled] for (;;) { // forever // left nibble first nib=(unsigned)(*last & 0xf0)>>4; // got a digit, in nib if (nib>9) {decNumberZero(dn); return NULL;} if (cut==0) *up=(Unit)nib; else *up=(Unit)(*up+nib*powers[cut]); digits--; if (digits==0) break; // got them all cut++; if (cut==DECDPUN) { up++; cut=0; } last--; // ready for next nib=*last & 0x0f; // get right nibble if (nib>9) {decNumberZero(dn); return NULL;} // got a digit, in nib if (cut==0) *up=(Unit)nib; else *up=(Unit)(*up+nib*powers[cut]); digits--; if (digits==0) break; // got them all cut++; if (cut==DECDPUN) { up++; cut=0; } } // forever return dn; } // decPackedToNumber hercules-3.07/decNumber/decPacked.h000644 000765 000765 00000005156 11143760537 020701 0ustar00jmaynardjmaynard000000 000000 /* ------------------------------------------------------------------ */ /* Packed Decimal conversion module header */ /* ------------------------------------------------------------------ */ /* Copyright (c) IBM Corporation, 2000, 2005. All rights reserved. */ /* */ /* This software is made available under the terms of the */ /* ICU License -- ICU 1.8.1 and later. */ /* */ /* The description and User's Guide ("The decNumber C Library") for */ /* this software is called decNumber.pdf. This document is */ /* available, together with arithmetic and format specifications, */ /* testcases, and Web links, at: http://www2.hursley.ibm.com/decimal */ /* */ /* Please send comments, suggestions, and corrections to the author: */ /* mfc@uk.ibm.com */ /* Mike Cowlishaw, IBM Fellow */ /* IBM UK, PO Box 31, Birmingham Road, Warwick CV34 5JL, UK */ /* ------------------------------------------------------------------ */ #if !defined(DECPACKED) #define DECPACKED #define DECPNAME "decPacked" /* Short name */ #define DECPFULLNAME "Packed Decimal conversions" /* Verbose name */ #define DECPAUTHOR "Mike Cowlishaw" /* Who to blame */ #define DECPACKED_DefP 32 // default precision #ifndef DECNUMDIGITS #define DECNUMDIGITS DECPACKED_DefP // size if not already defined #endif #include "decNumber.h" // context and number library /* Sign nibble constants */ #define DECPPLUSALT 0x0A // alternate plus nibble #define DECPMINUSALT 0x0B // alternate minus nibble #define DECPPLUS 0x0C // preferred plus nibble #define DECPMINUS 0x0D // preferred minus nibble #define DECPPLUSALT2 0x0E // alternate plus nibble #define DECPUNSIGNED 0x0F // alternate plus nibble (unsigned) /* ---------------------------------------------------------------- */ /* decPacked public routines */ /* ---------------------------------------------------------------- */ // Conversions uint8_t * decPackedFromNumber(uint8_t *, int32_t, int32_t *, const decNumber *); decNumber * decPackedToNumber(const uint8_t *, int32_t, const int32_t *, decNumber *); #endif hercules-3.07/decNumber/ICU-license.html000644 000765 000765 00000003671 11143760537 021613 0ustar00jmaynardjmaynard000000 000000 ICU License - ICU 1.8.1 and later

    ICU License - ICU 1.8.1 and later

    COPYRIGHT AND PERMISSION NOTICE
    
    Copyright (c) 1995-2005 International Business Machines Corporation and others
    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, and/or sell copies of the Software, and to permit persons
    to whom the Software is furnished to do so, provided that the above
    copyright notice(s) and this permission notice appear in all copies of
    the Software and that both the above copyright notice(s) and this
    permission notice appear in supporting documentation.
    
    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
    OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
    HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR 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.
    
    Except as contained in this notice, the name of a copyright holder
    shall not be used in advertising or otherwise to promote the sale, use
    or other dealings in this Software without prior written authorization
    of the copyright holder.
    
    --------------------------------------------------------------------------------
    All trademarks and registered trademarks mentioned herein are the property of their respective owners.
    
    hercules-3.07/decNumber/Makefile.am000644 000765 000765 00000003153 11143760537 020714 0ustar00jmaynardjmaynard000000 000000 ## Process this file with automake to produce Makefile.in # # Makefile for building the decNumber package # for use with Hercules S/370, ESA/390 and z/Architecture emulator # # This file was added by the Hercules project. # It is not part of the original decNumber distribution. # # $Id: Makefile.am 4175 2006-12-30 18:31:08Z rbowler $ # # $Log$ # Revision 1.3 2006/12/13 11:49:02 rbowler # Correct make tar error: No rule to make target `decNumber.pdf' # # Revision 1.2 2006/12/12 14:07:50 rbowler # Make decNumber a shared library not a loadable module # # lns=@LN_S@ LDADD = @LIBS@ AM_CPPFLAGS = -I$(top_srcdir) decNumber_SRC = decContext.c \ decimal128.c \ decimal32.c \ decimal64.c \ decNumber.c \ decPacked.c if BUILD_SHARED XSTATIC = else XSTATIC = -static endif if OPTION_DYNAMIC_LOAD LTDL = ../ltdl.c LIB_LD_FLAGS = -export-dynamic \ $(XSTATIC) \ -no-undefined \ -avoid-version else LTDL = LIB_LD_FLAGS = $(XSTATIC) \ -no-undefined \ -avoid-version endif HERCLIBS = HERCLIBS2 = libdecNumber.la noinst_LTLIBRARIES = $(HERCLIBS) lib_LTLIBRARIES = $(HERCLIBS2) libdecNumber_la_SOURCES = $(decNumber_SRC) libdecNumber_la_LDFLAGS = $(LIB_LD_FLAGS) libdecNumber_la_LIBADD = $(LDADD) noinst_HEADERS = decContext.h \ decDPD.h \ decimal128.h \ decimal32.h \ decimal64.h \ decNumber.h \ decNumberLocal.h \ decPacked.h EXTRA_DIST = decNumber.def \ decnumber.pdf \ decNumber.rc \ ICU-license.html \ readme.txt %.s: %.c $(COMPILE) -S $< hercules-3.07/decNumber/Makefile.in000644 000765 000765 00000044641 11344713140 020723 0ustar00jmaynardjmaynard000000 000000 # Makefile.in generated by automake 1.9.6 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ # # Makefile for building the decNumber package # for use with Hercules S/370, ESA/390 and z/Architecture emulator # # This file was added by the Hercules project. # It is not part of the original decNumber distribution. # # $Id: Makefile.am 4175 2006-12-30 18:31:08Z rbowler $ # # $Log$ # Revision 1.3 2006/12/13 11:49:02 rbowler # Correct make tar error: No rule to make target `decNumber.pdf' # # Revision 1.2 2006/12/12 14:07:50 rbowler # Make decNumber a shared library not a loadable module # # srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = .. am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd INSTALL = @INSTALL@ install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = decNumber DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \ $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/autoconf/hercules.m4 \ $(top_srcdir)/autoconf/libtool.m4 \ $(top_srcdir)/autoconf/ltdl.m4 $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(SHELL) $(top_srcdir)/autoconf/mkinstalldirs CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; am__installdirs = "$(DESTDIR)$(libdir)" libLTLIBRARIES_INSTALL = $(INSTALL) LTLIBRARIES = $(lib_LTLIBRARIES) $(noinst_LTLIBRARIES) am__DEPENDENCIES_1 = libdecNumber_la_DEPENDENCIES = $(am__DEPENDENCIES_1) am__objects_1 = decContext.lo decimal128.lo decimal32.lo decimal64.lo \ decNumber.lo decPacked.lo am_libdecNumber_la_OBJECTS = $(am__objects_1) libdecNumber_la_OBJECTS = $(am_libdecNumber_la_OBJECTS) DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/autoconf/depcomp am__depfiles_maybe = depfiles COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ SOURCES = $(libdecNumber_la_SOURCES) DIST_SOURCES = $(libdecNumber_la_SOURCES) HEADERS = $(noinst_HEADERS) ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BUILD_FISHHANG_FALSE = @BUILD_FISHHANG_FALSE@ BUILD_FISHHANG_TRUE = @BUILD_FISHHANG_TRUE@ BUILD_FTHREADS_FALSE = @BUILD_FTHREADS_FALSE@ BUILD_FTHREADS_TRUE = @BUILD_FTHREADS_TRUE@ BUILD_HERCIFC_FALSE = @BUILD_HERCIFC_FALSE@ BUILD_HERCIFC_TRUE = @BUILD_HERCIFC_TRUE@ BUILD_SHARED_FALSE = @BUILD_SHARED_FALSE@ BUILD_SHARED_TRUE = @BUILD_SHARED_TRUE@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CONVENIENCE_LTDL_FALSE = @CONVENIENCE_LTDL_FALSE@ CONVENIENCE_LTDL_TRUE = @CONVENIENCE_LTDL_TRUE@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ ECHO = @ECHO@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ F77 = @F77@ FFLAGS = @FFLAGS@ GMSGFMT = @GMSGFMT@ GREP = @GREP@ HERCIFC_GROUPNAME = @HERCIFC_GROUPNAME@ HERCIFC_GROUPSET_FALSE = @HERCIFC_GROUPSET_FALSE@ HERCIFC_GROUPSET_TRUE = @HERCIFC_GROUPSET_TRUE@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_LTDL_FALSE = @INSTALL_LTDL_FALSE@ INSTALL_LTDL_TRUE = @INSTALL_LTDL_TRUE@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ LDFLAGS = @LDFLAGS@ LIBADD_DL = @LIBADD_DL@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBTOOL_DEPS = @LIBTOOL_DEPS@ LN_S = @LN_S@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@ MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@ MAKEINFO = @MAKEINFO@ MKINSTALLDIRS = @MKINSTALLDIRS@ MSGFMT = @MSGFMT@ MSGMERGE = @MSGMERGE@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPTION_DYNAMIC_LOAD_FALSE = @OPTION_DYNAMIC_LOAD_FALSE@ OPTION_DYNAMIC_LOAD_TRUE = @OPTION_DYNAMIC_LOAD_TRUE@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ POSUB = @POSUB@ RANLIB = @RANLIB@ SETUID_HERCIFC_FALSE = @SETUID_HERCIFC_FALSE@ SETUID_HERCIFC_TRUE = @SETUID_HERCIFC_TRUE@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ USE_DLLTOOL_FALSE = @USE_DLLTOOL_FALSE@ USE_DLLTOOL_TRUE = @USE_DLLTOOL_TRUE@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_F77 = @ac_ct_F77@ am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ modexecdir = @modexecdir@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ lns = @LN_S@ LDADD = @LIBS@ AM_CPPFLAGS = -I$(top_srcdir) decNumber_SRC = decContext.c \ decimal128.c \ decimal32.c \ decimal64.c \ decNumber.c \ decPacked.c @BUILD_SHARED_FALSE@XSTATIC = -static @BUILD_SHARED_TRUE@XSTATIC = @OPTION_DYNAMIC_LOAD_FALSE@LTDL = @OPTION_DYNAMIC_LOAD_TRUE@LTDL = ../ltdl.c @OPTION_DYNAMIC_LOAD_FALSE@LIB_LD_FLAGS = $(XSTATIC) \ @OPTION_DYNAMIC_LOAD_FALSE@ -no-undefined \ @OPTION_DYNAMIC_LOAD_FALSE@ -avoid-version @OPTION_DYNAMIC_LOAD_TRUE@LIB_LD_FLAGS = -export-dynamic \ @OPTION_DYNAMIC_LOAD_TRUE@ $(XSTATIC) \ @OPTION_DYNAMIC_LOAD_TRUE@ -no-undefined \ @OPTION_DYNAMIC_LOAD_TRUE@ -avoid-version HERCLIBS = HERCLIBS2 = libdecNumber.la noinst_LTLIBRARIES = $(HERCLIBS) lib_LTLIBRARIES = $(HERCLIBS2) libdecNumber_la_SOURCES = $(decNumber_SRC) libdecNumber_la_LDFLAGS = $(LIB_LD_FLAGS) libdecNumber_la_LIBADD = $(LDADD) noinst_HEADERS = decContext.h \ decDPD.h \ decimal128.h \ decimal32.h \ decimal64.h \ decNumber.h \ decNumberLocal.h \ decPacked.h EXTRA_DIST = decNumber.def \ decnumber.pdf \ decNumber.rc \ ICU-license.html \ readme.txt all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ && exit 0; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu decNumber/Makefile'; \ cd $(top_srcdir) && \ $(AUTOMAKE) --gnu decNumber/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) test -z "$(libdir)" || $(mkdir_p) "$(DESTDIR)$(libdir)" @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ if test -f $$p; then \ f=$(am__strip_dir) \ echo " $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(libdir)/$$f"; \ else :; fi; \ done uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @set -x; list='$(lib_LTLIBRARIES)'; for p in $$list; do \ p=$(am__strip_dir) \ echo " $(LIBTOOL) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$p'"; \ $(LIBTOOL) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$p"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ test "$$dir" != "$$p" || dir=.; \ echo "rm -f \"$${dir}/so_locations\""; \ rm -f "$${dir}/so_locations"; \ done clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ test "$$dir" != "$$p" || dir=.; \ echo "rm -f \"$${dir}/so_locations\""; \ rm -f "$${dir}/so_locations"; \ done libdecNumber.la: $(libdecNumber_la_OBJECTS) $(libdecNumber_la_DEPENDENCIES) $(LINK) -rpath $(libdir) $(libdecNumber_la_LDFLAGS) $(libdecNumber_la_OBJECTS) $(libdecNumber_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/decContext.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/decNumber.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/decPacked.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/decimal128.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/decimal32.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/decimal64.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ @am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c $< .c.obj: @am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \ @am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ if $(LTCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ @am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs distclean-libtool: -rm -f libtool uninstall-info-am: ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ mkid -fID $$unique tags: TAGS TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$tags $$unique; \ fi ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(CTAGS_ARGS)$$tags$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$tags $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && cd $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) $$here distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ list='$(DISTFILES)'; for file in $$list; do \ case $$file in \ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ esac; \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ if test "$$dir" != "$$file" && test "$$dir" != "."; then \ dir="/$$dir"; \ $(mkdir_p) "$(distdir)$$dir"; \ else \ dir=''; \ fi; \ if test -d $$d/$$file; then \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ fi; \ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) $(HEADERS) installdirs: for dir in "$(DESTDIR)$(libdir)"; do \ test -z "$$dir" || $(mkdir_p) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ clean-noinstLTLIBRARIES mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-libtool distclean-tags dvi: dvi-am dvi-am: html: html-am info: info-am info-am: install-data-am: install-exec-am: install-libLTLIBRARIES install-info: install-info-am install-man: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-info-am uninstall-libLTLIBRARIES .PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ clean-libLTLIBRARIES clean-libtool clean-noinstLTLIBRARIES \ ctags distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-exec install-exec-am install-info \ install-info-am install-libLTLIBRARIES install-man \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ pdf pdf-am ps ps-am tags uninstall uninstall-am \ uninstall-info-am uninstall-libLTLIBRARIES %.s: %.c $(COMPILE) -S $< # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: hercules-3.07/decNumber/readme.txt000644 000765 000765 00000005625 11143760537 020664 0ustar00jmaynardjmaynard000000 000000 This is the readme.txt for the decNumber package. It includes instructions for compiling and testing the package; please read them. --------------------------------------------------------------------- decNumber is distributed in three forms; as a complete package from the IBM alphaWorks site (available under either a trial or a commercial license), as a complete package from the International Components for Unicode (ICU) site (under an as-is license), or as a collection of Open Source files from the GCC source repository (under the GPL license). If you are using the GCC files, you can obtain the documentation, the example files mentioned below, and this readme from: http://www2.hursley.ibm.com/decimal/#decNumber (the URL for the open source files is also linked from there). The alphaWorks and ICU packages ------------------------------- The alphaWorks and ICU packages include the files: * readme.txt (this file) * alphaWorks-license-files.zip (contains the 90-day trial license, in multiple languages), or ICU-license.html Note: a commercial license for this code is also available by following the 'License this technology' link from the alphaWorks page: http://www.alphaWorks.ibm.com/tech/decnumber * decNumber.pdf (documentation) * The .c and .h file for each module in the package (see documentation), decDPD.h (used by decimal32), and decNumberLocal.h (local definitions) * The .c files for each of the examples (example1.c through example6.c) The alphaWorks package is made available under the terms of the IBM alphaWorks License Agreement (included in various languages in the file alphaWorks-license-files.zip), unless you have agreed different licensing terms with IBM. Your use of that package indicates your acceptance of the terms and conditions of that Agreement. The ICU package is made available under the terms of the ICU License (ICU 1.8.1 and later) included in the package as ICU-license.html. Your use of that package indicates your acceptance of the terms and conditions of that Agreement. To use and check decNumber -------------------------- Please read the appropriate license and documentation before using this package. 1. Compile and link example1.c, decNumber.c, and decContext.c For example: gcc -o example1 example1.c decNumber.c decContext.c Note: If your compiler does not provide stdint.h or if your C compiler does not handle line comments (// ...), then see the User's Guide section in the documentation for further information (including a suitable minimal stdint.h). 2. Run example1 with two numeric arguments, for example: example1 1.23 1.27 this should display: 1.23 + 1.27 => 2.50 3. Similarly, try the other examples, at will. Example 5 requires decimal64.c in addition to the core modules. Example 6 requires decPacked.c in addition to the core modules. hercules-3.07/crypto/aes.c000644 000765 000765 00000163346 11143760536 017222 0ustar00jmaynardjmaynard000000 000000 /* $OpenBSD: rijndael.c,v 1.18 2005/05/25 05:47:53 markus Exp $ */ /* modified for use by dyncrypt */ // $Id: aes.c 4102 2006-12-08 09:43:35Z jj $ /** * rijndael-alg-fst.c * * @version 3.0 (December 2000) * * Optimised ANSI C code for the Rijndael cipher (now AES) * * @author Vincent Rijmen * @author Antoon Bosselaers * @author Paulo Barreto * * This code is hereby placed in the public domain. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''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 AUTHORS 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. */ // $Log$ #include "hstdinc.h" #if !defined(_HENGINE_DLL_) #define _HENGINE_DLL_ #endif #include "hercules.h" #include "opcode.h" /* For fetch_fw */ #include "aes.h" #define FULL_UNROLL /* Te0[x] = S [x].[02, 01, 01, 03]; Te1[x] = S [x].[03, 02, 01, 01]; Te2[x] = S [x].[01, 03, 02, 01]; Te3[x] = S [x].[01, 01, 03, 02]; Te4[x] = S [x].[01, 01, 01, 01]; Td0[x] = Si[x].[0e, 09, 0d, 0b]; Td1[x] = Si[x].[0b, 0e, 09, 0d]; Td2[x] = Si[x].[0d, 0b, 0e, 09]; Td3[x] = Si[x].[09, 0d, 0b, 0e]; Td4[x] = Si[x].[01, 01, 01, 01]; */ static const u32 Te0[256] = { 0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU, 0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U, 0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU, 0xe7fefe19U, 0xb5d7d762U, 0x4dababe6U, 0xec76769aU, 0x8fcaca45U, 0x1f82829dU, 0x89c9c940U, 0xfa7d7d87U, 0xeffafa15U, 0xb25959ebU, 0x8e4747c9U, 0xfbf0f00bU, 0x41adadecU, 0xb3d4d467U, 0x5fa2a2fdU, 0x45afafeaU, 0x239c9cbfU, 0x53a4a4f7U, 0xe4727296U, 0x9bc0c05bU, 0x75b7b7c2U, 0xe1fdfd1cU, 0x3d9393aeU, 0x4c26266aU, 0x6c36365aU, 0x7e3f3f41U, 0xf5f7f702U, 0x83cccc4fU, 0x6834345cU, 0x51a5a5f4U, 0xd1e5e534U, 0xf9f1f108U, 0xe2717193U, 0xabd8d873U, 0x62313153U, 0x2a15153fU, 0x0804040cU, 0x95c7c752U, 0x46232365U, 0x9dc3c35eU, 0x30181828U, 0x379696a1U, 0x0a05050fU, 0x2f9a9ab5U, 0x0e070709U, 0x24121236U, 0x1b80809bU, 0xdfe2e23dU, 0xcdebeb26U, 0x4e272769U, 0x7fb2b2cdU, 0xea75759fU, 0x1209091bU, 0x1d83839eU, 0x582c2c74U, 0x341a1a2eU, 0x361b1b2dU, 0xdc6e6eb2U, 0xb45a5aeeU, 0x5ba0a0fbU, 0xa45252f6U, 0x763b3b4dU, 0xb7d6d661U, 0x7db3b3ceU, 0x5229297bU, 0xdde3e33eU, 0x5e2f2f71U, 0x13848497U, 0xa65353f5U, 0xb9d1d168U, 0x00000000U, 0xc1eded2cU, 0x40202060U, 0xe3fcfc1fU, 0x79b1b1c8U, 0xb65b5bedU, 0xd46a6abeU, 0x8dcbcb46U, 0x67bebed9U, 0x7239394bU, 0x944a4adeU, 0x984c4cd4U, 0xb05858e8U, 0x85cfcf4aU, 0xbbd0d06bU, 0xc5efef2aU, 0x4faaaae5U, 0xedfbfb16U, 0x864343c5U, 0x9a4d4dd7U, 0x66333355U, 0x11858594U, 0x8a4545cfU, 0xe9f9f910U, 0x04020206U, 0xfe7f7f81U, 0xa05050f0U, 0x783c3c44U, 0x259f9fbaU, 0x4ba8a8e3U, 0xa25151f3U, 0x5da3a3feU, 0x804040c0U, 0x058f8f8aU, 0x3f9292adU, 0x219d9dbcU, 0x70383848U, 0xf1f5f504U, 0x63bcbcdfU, 0x77b6b6c1U, 0xafdada75U, 0x42212163U, 0x20101030U, 0xe5ffff1aU, 0xfdf3f30eU, 0xbfd2d26dU, 0x81cdcd4cU, 0x180c0c14U, 0x26131335U, 0xc3ecec2fU, 0xbe5f5fe1U, 0x359797a2U, 0x884444ccU, 0x2e171739U, 0x93c4c457U, 0x55a7a7f2U, 0xfc7e7e82U, 0x7a3d3d47U, 0xc86464acU, 0xba5d5de7U, 0x3219192bU, 0xe6737395U, 0xc06060a0U, 0x19818198U, 0x9e4f4fd1U, 0xa3dcdc7fU, 0x44222266U, 0x542a2a7eU, 0x3b9090abU, 0x0b888883U, 0x8c4646caU, 0xc7eeee29U, 0x6bb8b8d3U, 0x2814143cU, 0xa7dede79U, 0xbc5e5ee2U, 0x160b0b1dU, 0xaddbdb76U, 0xdbe0e03bU, 0x64323256U, 0x743a3a4eU, 0x140a0a1eU, 0x924949dbU, 0x0c06060aU, 0x4824246cU, 0xb85c5ce4U, 0x9fc2c25dU, 0xbdd3d36eU, 0x43acacefU, 0xc46262a6U, 0x399191a8U, 0x319595a4U, 0xd3e4e437U, 0xf279798bU, 0xd5e7e732U, 0x8bc8c843U, 0x6e373759U, 0xda6d6db7U, 0x018d8d8cU, 0xb1d5d564U, 0x9c4e4ed2U, 0x49a9a9e0U, 0xd86c6cb4U, 0xac5656faU, 0xf3f4f407U, 0xcfeaea25U, 0xca6565afU, 0xf47a7a8eU, 0x47aeaee9U, 0x10080818U, 0x6fbabad5U, 0xf0787888U, 0x4a25256fU, 0x5c2e2e72U, 0x381c1c24U, 0x57a6a6f1U, 0x73b4b4c7U, 0x97c6c651U, 0xcbe8e823U, 0xa1dddd7cU, 0xe874749cU, 0x3e1f1f21U, 0x964b4bddU, 0x61bdbddcU, 0x0d8b8b86U, 0x0f8a8a85U, 0xe0707090U, 0x7c3e3e42U, 0x71b5b5c4U, 0xcc6666aaU, 0x904848d8U, 0x06030305U, 0xf7f6f601U, 0x1c0e0e12U, 0xc26161a3U, 0x6a35355fU, 0xae5757f9U, 0x69b9b9d0U, 0x17868691U, 0x99c1c158U, 0x3a1d1d27U, 0x279e9eb9U, 0xd9e1e138U, 0xebf8f813U, 0x2b9898b3U, 0x22111133U, 0xd26969bbU, 0xa9d9d970U, 0x078e8e89U, 0x339494a7U, 0x2d9b9bb6U, 0x3c1e1e22U, 0x15878792U, 0xc9e9e920U, 0x87cece49U, 0xaa5555ffU, 0x50282878U, 0xa5dfdf7aU, 0x038c8c8fU, 0x59a1a1f8U, 0x09898980U, 0x1a0d0d17U, 0x65bfbfdaU, 0xd7e6e631U, 0x844242c6U, 0xd06868b8U, 0x824141c3U, 0x299999b0U, 0x5a2d2d77U, 0x1e0f0f11U, 0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U, 0x2c16163aU, }; static const u32 Te1[256] = { 0xa5c66363U, 0x84f87c7cU, 0x99ee7777U, 0x8df67b7bU, 0x0dfff2f2U, 0xbdd66b6bU, 0xb1de6f6fU, 0x5491c5c5U, 0x50603030U, 0x03020101U, 0xa9ce6767U, 0x7d562b2bU, 0x19e7fefeU, 0x62b5d7d7U, 0xe64dababU, 0x9aec7676U, 0x458fcacaU, 0x9d1f8282U, 0x4089c9c9U, 0x87fa7d7dU, 0x15effafaU, 0xebb25959U, 0xc98e4747U, 0x0bfbf0f0U, 0xec41adadU, 0x67b3d4d4U, 0xfd5fa2a2U, 0xea45afafU, 0xbf239c9cU, 0xf753a4a4U, 0x96e47272U, 0x5b9bc0c0U, 0xc275b7b7U, 0x1ce1fdfdU, 0xae3d9393U, 0x6a4c2626U, 0x5a6c3636U, 0x417e3f3fU, 0x02f5f7f7U, 0x4f83ccccU, 0x5c683434U, 0xf451a5a5U, 0x34d1e5e5U, 0x08f9f1f1U, 0x93e27171U, 0x73abd8d8U, 0x53623131U, 0x3f2a1515U, 0x0c080404U, 0x5295c7c7U, 0x65462323U, 0x5e9dc3c3U, 0x28301818U, 0xa1379696U, 0x0f0a0505U, 0xb52f9a9aU, 0x090e0707U, 0x36241212U, 0x9b1b8080U, 0x3ddfe2e2U, 0x26cdebebU, 0x694e2727U, 0xcd7fb2b2U, 0x9fea7575U, 0x1b120909U, 0x9e1d8383U, 0x74582c2cU, 0x2e341a1aU, 0x2d361b1bU, 0xb2dc6e6eU, 0xeeb45a5aU, 0xfb5ba0a0U, 0xf6a45252U, 0x4d763b3bU, 0x61b7d6d6U, 0xce7db3b3U, 0x7b522929U, 0x3edde3e3U, 0x715e2f2fU, 0x97138484U, 0xf5a65353U, 0x68b9d1d1U, 0x00000000U, 0x2cc1ededU, 0x60402020U, 0x1fe3fcfcU, 0xc879b1b1U, 0xedb65b5bU, 0xbed46a6aU, 0x468dcbcbU, 0xd967bebeU, 0x4b723939U, 0xde944a4aU, 0xd4984c4cU, 0xe8b05858U, 0x4a85cfcfU, 0x6bbbd0d0U, 0x2ac5efefU, 0xe54faaaaU, 0x16edfbfbU, 0xc5864343U, 0xd79a4d4dU, 0x55663333U, 0x94118585U, 0xcf8a4545U, 0x10e9f9f9U, 0x06040202U, 0x81fe7f7fU, 0xf0a05050U, 0x44783c3cU, 0xba259f9fU, 0xe34ba8a8U, 0xf3a25151U, 0xfe5da3a3U, 0xc0804040U, 0x8a058f8fU, 0xad3f9292U, 0xbc219d9dU, 0x48703838U, 0x04f1f5f5U, 0xdf63bcbcU, 0xc177b6b6U, 0x75afdadaU, 0x63422121U, 0x30201010U, 0x1ae5ffffU, 0x0efdf3f3U, 0x6dbfd2d2U, 0x4c81cdcdU, 0x14180c0cU, 0x35261313U, 0x2fc3ececU, 0xe1be5f5fU, 0xa2359797U, 0xcc884444U, 0x392e1717U, 0x5793c4c4U, 0xf255a7a7U, 0x82fc7e7eU, 0x477a3d3dU, 0xacc86464U, 0xe7ba5d5dU, 0x2b321919U, 0x95e67373U, 0xa0c06060U, 0x98198181U, 0xd19e4f4fU, 0x7fa3dcdcU, 0x66442222U, 0x7e542a2aU, 0xab3b9090U, 0x830b8888U, 0xca8c4646U, 0x29c7eeeeU, 0xd36bb8b8U, 0x3c281414U, 0x79a7dedeU, 0xe2bc5e5eU, 0x1d160b0bU, 0x76addbdbU, 0x3bdbe0e0U, 0x56643232U, 0x4e743a3aU, 0x1e140a0aU, 0xdb924949U, 0x0a0c0606U, 0x6c482424U, 0xe4b85c5cU, 0x5d9fc2c2U, 0x6ebdd3d3U, 0xef43acacU, 0xa6c46262U, 0xa8399191U, 0xa4319595U, 0x37d3e4e4U, 0x8bf27979U, 0x32d5e7e7U, 0x438bc8c8U, 0x596e3737U, 0xb7da6d6dU, 0x8c018d8dU, 0x64b1d5d5U, 0xd29c4e4eU, 0xe049a9a9U, 0xb4d86c6cU, 0xfaac5656U, 0x07f3f4f4U, 0x25cfeaeaU, 0xafca6565U, 0x8ef47a7aU, 0xe947aeaeU, 0x18100808U, 0xd56fbabaU, 0x88f07878U, 0x6f4a2525U, 0x725c2e2eU, 0x24381c1cU, 0xf157a6a6U, 0xc773b4b4U, 0x5197c6c6U, 0x23cbe8e8U, 0x7ca1ddddU, 0x9ce87474U, 0x213e1f1fU, 0xdd964b4bU, 0xdc61bdbdU, 0x860d8b8bU, 0x850f8a8aU, 0x90e07070U, 0x427c3e3eU, 0xc471b5b5U, 0xaacc6666U, 0xd8904848U, 0x05060303U, 0x01f7f6f6U, 0x121c0e0eU, 0xa3c26161U, 0x5f6a3535U, 0xf9ae5757U, 0xd069b9b9U, 0x91178686U, 0x5899c1c1U, 0x273a1d1dU, 0xb9279e9eU, 0x38d9e1e1U, 0x13ebf8f8U, 0xb32b9898U, 0x33221111U, 0xbbd26969U, 0x70a9d9d9U, 0x89078e8eU, 0xa7339494U, 0xb62d9b9bU, 0x223c1e1eU, 0x92158787U, 0x20c9e9e9U, 0x4987ceceU, 0xffaa5555U, 0x78502828U, 0x7aa5dfdfU, 0x8f038c8cU, 0xf859a1a1U, 0x80098989U, 0x171a0d0dU, 0xda65bfbfU, 0x31d7e6e6U, 0xc6844242U, 0xb8d06868U, 0xc3824141U, 0xb0299999U, 0x775a2d2dU, 0x111e0f0fU, 0xcb7bb0b0U, 0xfca85454U, 0xd66dbbbbU, 0x3a2c1616U, }; static const u32 Te2[256] = { 0x63a5c663U, 0x7c84f87cU, 0x7799ee77U, 0x7b8df67bU, 0xf20dfff2U, 0x6bbdd66bU, 0x6fb1de6fU, 0xc55491c5U, 0x30506030U, 0x01030201U, 0x67a9ce67U, 0x2b7d562bU, 0xfe19e7feU, 0xd762b5d7U, 0xabe64dabU, 0x769aec76U, 0xca458fcaU, 0x829d1f82U, 0xc94089c9U, 0x7d87fa7dU, 0xfa15effaU, 0x59ebb259U, 0x47c98e47U, 0xf00bfbf0U, 0xadec41adU, 0xd467b3d4U, 0xa2fd5fa2U, 0xafea45afU, 0x9cbf239cU, 0xa4f753a4U, 0x7296e472U, 0xc05b9bc0U, 0xb7c275b7U, 0xfd1ce1fdU, 0x93ae3d93U, 0x266a4c26U, 0x365a6c36U, 0x3f417e3fU, 0xf702f5f7U, 0xcc4f83ccU, 0x345c6834U, 0xa5f451a5U, 0xe534d1e5U, 0xf108f9f1U, 0x7193e271U, 0xd873abd8U, 0x31536231U, 0x153f2a15U, 0x040c0804U, 0xc75295c7U, 0x23654623U, 0xc35e9dc3U, 0x18283018U, 0x96a13796U, 0x050f0a05U, 0x9ab52f9aU, 0x07090e07U, 0x12362412U, 0x809b1b80U, 0xe23ddfe2U, 0xeb26cdebU, 0x27694e27U, 0xb2cd7fb2U, 0x759fea75U, 0x091b1209U, 0x839e1d83U, 0x2c74582cU, 0x1a2e341aU, 0x1b2d361bU, 0x6eb2dc6eU, 0x5aeeb45aU, 0xa0fb5ba0U, 0x52f6a452U, 0x3b4d763bU, 0xd661b7d6U, 0xb3ce7db3U, 0x297b5229U, 0xe33edde3U, 0x2f715e2fU, 0x84971384U, 0x53f5a653U, 0xd168b9d1U, 0x00000000U, 0xed2cc1edU, 0x20604020U, 0xfc1fe3fcU, 0xb1c879b1U, 0x5bedb65bU, 0x6abed46aU, 0xcb468dcbU, 0xbed967beU, 0x394b7239U, 0x4ade944aU, 0x4cd4984cU, 0x58e8b058U, 0xcf4a85cfU, 0xd06bbbd0U, 0xef2ac5efU, 0xaae54faaU, 0xfb16edfbU, 0x43c58643U, 0x4dd79a4dU, 0x33556633U, 0x85941185U, 0x45cf8a45U, 0xf910e9f9U, 0x02060402U, 0x7f81fe7fU, 0x50f0a050U, 0x3c44783cU, 0x9fba259fU, 0xa8e34ba8U, 0x51f3a251U, 0xa3fe5da3U, 0x40c08040U, 0x8f8a058fU, 0x92ad3f92U, 0x9dbc219dU, 0x38487038U, 0xf504f1f5U, 0xbcdf63bcU, 0xb6c177b6U, 0xda75afdaU, 0x21634221U, 0x10302010U, 0xff1ae5ffU, 0xf30efdf3U, 0xd26dbfd2U, 0xcd4c81cdU, 0x0c14180cU, 0x13352613U, 0xec2fc3ecU, 0x5fe1be5fU, 0x97a23597U, 0x44cc8844U, 0x17392e17U, 0xc45793c4U, 0xa7f255a7U, 0x7e82fc7eU, 0x3d477a3dU, 0x64acc864U, 0x5de7ba5dU, 0x192b3219U, 0x7395e673U, 0x60a0c060U, 0x81981981U, 0x4fd19e4fU, 0xdc7fa3dcU, 0x22664422U, 0x2a7e542aU, 0x90ab3b90U, 0x88830b88U, 0x46ca8c46U, 0xee29c7eeU, 0xb8d36bb8U, 0x143c2814U, 0xde79a7deU, 0x5ee2bc5eU, 0x0b1d160bU, 0xdb76addbU, 0xe03bdbe0U, 0x32566432U, 0x3a4e743aU, 0x0a1e140aU, 0x49db9249U, 0x060a0c06U, 0x246c4824U, 0x5ce4b85cU, 0xc25d9fc2U, 0xd36ebdd3U, 0xacef43acU, 0x62a6c462U, 0x91a83991U, 0x95a43195U, 0xe437d3e4U, 0x798bf279U, 0xe732d5e7U, 0xc8438bc8U, 0x37596e37U, 0x6db7da6dU, 0x8d8c018dU, 0xd564b1d5U, 0x4ed29c4eU, 0xa9e049a9U, 0x6cb4d86cU, 0x56faac56U, 0xf407f3f4U, 0xea25cfeaU, 0x65afca65U, 0x7a8ef47aU, 0xaee947aeU, 0x08181008U, 0xbad56fbaU, 0x7888f078U, 0x256f4a25U, 0x2e725c2eU, 0x1c24381cU, 0xa6f157a6U, 0xb4c773b4U, 0xc65197c6U, 0xe823cbe8U, 0xdd7ca1ddU, 0x749ce874U, 0x1f213e1fU, 0x4bdd964bU, 0xbddc61bdU, 0x8b860d8bU, 0x8a850f8aU, 0x7090e070U, 0x3e427c3eU, 0xb5c471b5U, 0x66aacc66U, 0x48d89048U, 0x03050603U, 0xf601f7f6U, 0x0e121c0eU, 0x61a3c261U, 0x355f6a35U, 0x57f9ae57U, 0xb9d069b9U, 0x86911786U, 0xc15899c1U, 0x1d273a1dU, 0x9eb9279eU, 0xe138d9e1U, 0xf813ebf8U, 0x98b32b98U, 0x11332211U, 0x69bbd269U, 0xd970a9d9U, 0x8e89078eU, 0x94a73394U, 0x9bb62d9bU, 0x1e223c1eU, 0x87921587U, 0xe920c9e9U, 0xce4987ceU, 0x55ffaa55U, 0x28785028U, 0xdf7aa5dfU, 0x8c8f038cU, 0xa1f859a1U, 0x89800989U, 0x0d171a0dU, 0xbfda65bfU, 0xe631d7e6U, 0x42c68442U, 0x68b8d068U, 0x41c38241U, 0x99b02999U, 0x2d775a2dU, 0x0f111e0fU, 0xb0cb7bb0U, 0x54fca854U, 0xbbd66dbbU, 0x163a2c16U, }; static const u32 Te3[256] = { 0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U, 0xf2f20dffU, 0x6b6bbdd6U, 0x6f6fb1deU, 0xc5c55491U, 0x30305060U, 0x01010302U, 0x6767a9ceU, 0x2b2b7d56U, 0xfefe19e7U, 0xd7d762b5U, 0xababe64dU, 0x76769aecU, 0xcaca458fU, 0x82829d1fU, 0xc9c94089U, 0x7d7d87faU, 0xfafa15efU, 0x5959ebb2U, 0x4747c98eU, 0xf0f00bfbU, 0xadadec41U, 0xd4d467b3U, 0xa2a2fd5fU, 0xafafea45U, 0x9c9cbf23U, 0xa4a4f753U, 0x727296e4U, 0xc0c05b9bU, 0xb7b7c275U, 0xfdfd1ce1U, 0x9393ae3dU, 0x26266a4cU, 0x36365a6cU, 0x3f3f417eU, 0xf7f702f5U, 0xcccc4f83U, 0x34345c68U, 0xa5a5f451U, 0xe5e534d1U, 0xf1f108f9U, 0x717193e2U, 0xd8d873abU, 0x31315362U, 0x15153f2aU, 0x04040c08U, 0xc7c75295U, 0x23236546U, 0xc3c35e9dU, 0x18182830U, 0x9696a137U, 0x05050f0aU, 0x9a9ab52fU, 0x0707090eU, 0x12123624U, 0x80809b1bU, 0xe2e23ddfU, 0xebeb26cdU, 0x2727694eU, 0xb2b2cd7fU, 0x75759feaU, 0x09091b12U, 0x83839e1dU, 0x2c2c7458U, 0x1a1a2e34U, 0x1b1b2d36U, 0x6e6eb2dcU, 0x5a5aeeb4U, 0xa0a0fb5bU, 0x5252f6a4U, 0x3b3b4d76U, 0xd6d661b7U, 0xb3b3ce7dU, 0x29297b52U, 0xe3e33eddU, 0x2f2f715eU, 0x84849713U, 0x5353f5a6U, 0xd1d168b9U, 0x00000000U, 0xeded2cc1U, 0x20206040U, 0xfcfc1fe3U, 0xb1b1c879U, 0x5b5bedb6U, 0x6a6abed4U, 0xcbcb468dU, 0xbebed967U, 0x39394b72U, 0x4a4ade94U, 0x4c4cd498U, 0x5858e8b0U, 0xcfcf4a85U, 0xd0d06bbbU, 0xefef2ac5U, 0xaaaae54fU, 0xfbfb16edU, 0x4343c586U, 0x4d4dd79aU, 0x33335566U, 0x85859411U, 0x4545cf8aU, 0xf9f910e9U, 0x02020604U, 0x7f7f81feU, 0x5050f0a0U, 0x3c3c4478U, 0x9f9fba25U, 0xa8a8e34bU, 0x5151f3a2U, 0xa3a3fe5dU, 0x4040c080U, 0x8f8f8a05U, 0x9292ad3fU, 0x9d9dbc21U, 0x38384870U, 0xf5f504f1U, 0xbcbcdf63U, 0xb6b6c177U, 0xdada75afU, 0x21216342U, 0x10103020U, 0xffff1ae5U, 0xf3f30efdU, 0xd2d26dbfU, 0xcdcd4c81U, 0x0c0c1418U, 0x13133526U, 0xecec2fc3U, 0x5f5fe1beU, 0x9797a235U, 0x4444cc88U, 0x1717392eU, 0xc4c45793U, 0xa7a7f255U, 0x7e7e82fcU, 0x3d3d477aU, 0x6464acc8U, 0x5d5de7baU, 0x19192b32U, 0x737395e6U, 0x6060a0c0U, 0x81819819U, 0x4f4fd19eU, 0xdcdc7fa3U, 0x22226644U, 0x2a2a7e54U, 0x9090ab3bU, 0x8888830bU, 0x4646ca8cU, 0xeeee29c7U, 0xb8b8d36bU, 0x14143c28U, 0xdede79a7U, 0x5e5ee2bcU, 0x0b0b1d16U, 0xdbdb76adU, 0xe0e03bdbU, 0x32325664U, 0x3a3a4e74U, 0x0a0a1e14U, 0x4949db92U, 0x06060a0cU, 0x24246c48U, 0x5c5ce4b8U, 0xc2c25d9fU, 0xd3d36ebdU, 0xacacef43U, 0x6262a6c4U, 0x9191a839U, 0x9595a431U, 0xe4e437d3U, 0x79798bf2U, 0xe7e732d5U, 0xc8c8438bU, 0x3737596eU, 0x6d6db7daU, 0x8d8d8c01U, 0xd5d564b1U, 0x4e4ed29cU, 0xa9a9e049U, 0x6c6cb4d8U, 0x5656faacU, 0xf4f407f3U, 0xeaea25cfU, 0x6565afcaU, 0x7a7a8ef4U, 0xaeaee947U, 0x08081810U, 0xbabad56fU, 0x787888f0U, 0x25256f4aU, 0x2e2e725cU, 0x1c1c2438U, 0xa6a6f157U, 0xb4b4c773U, 0xc6c65197U, 0xe8e823cbU, 0xdddd7ca1U, 0x74749ce8U, 0x1f1f213eU, 0x4b4bdd96U, 0xbdbddc61U, 0x8b8b860dU, 0x8a8a850fU, 0x707090e0U, 0x3e3e427cU, 0xb5b5c471U, 0x6666aaccU, 0x4848d890U, 0x03030506U, 0xf6f601f7U, 0x0e0e121cU, 0x6161a3c2U, 0x35355f6aU, 0x5757f9aeU, 0xb9b9d069U, 0x86869117U, 0xc1c15899U, 0x1d1d273aU, 0x9e9eb927U, 0xe1e138d9U, 0xf8f813ebU, 0x9898b32bU, 0x11113322U, 0x6969bbd2U, 0xd9d970a9U, 0x8e8e8907U, 0x9494a733U, 0x9b9bb62dU, 0x1e1e223cU, 0x87879215U, 0xe9e920c9U, 0xcece4987U, 0x5555ffaaU, 0x28287850U, 0xdfdf7aa5U, 0x8c8c8f03U, 0xa1a1f859U, 0x89898009U, 0x0d0d171aU, 0xbfbfda65U, 0xe6e631d7U, 0x4242c684U, 0x6868b8d0U, 0x4141c382U, 0x9999b029U, 0x2d2d775aU, 0x0f0f111eU, 0xb0b0cb7bU, 0x5454fca8U, 0xbbbbd66dU, 0x16163a2cU, }; static const u32 Te4[256] = { 0x63636363U, 0x7c7c7c7cU, 0x77777777U, 0x7b7b7b7bU, 0xf2f2f2f2U, 0x6b6b6b6bU, 0x6f6f6f6fU, 0xc5c5c5c5U, 0x30303030U, 0x01010101U, 0x67676767U, 0x2b2b2b2bU, 0xfefefefeU, 0xd7d7d7d7U, 0xababababU, 0x76767676U, 0xcacacacaU, 0x82828282U, 0xc9c9c9c9U, 0x7d7d7d7dU, 0xfafafafaU, 0x59595959U, 0x47474747U, 0xf0f0f0f0U, 0xadadadadU, 0xd4d4d4d4U, 0xa2a2a2a2U, 0xafafafafU, 0x9c9c9c9cU, 0xa4a4a4a4U, 0x72727272U, 0xc0c0c0c0U, 0xb7b7b7b7U, 0xfdfdfdfdU, 0x93939393U, 0x26262626U, 0x36363636U, 0x3f3f3f3fU, 0xf7f7f7f7U, 0xccccccccU, 0x34343434U, 0xa5a5a5a5U, 0xe5e5e5e5U, 0xf1f1f1f1U, 0x71717171U, 0xd8d8d8d8U, 0x31313131U, 0x15151515U, 0x04040404U, 0xc7c7c7c7U, 0x23232323U, 0xc3c3c3c3U, 0x18181818U, 0x96969696U, 0x05050505U, 0x9a9a9a9aU, 0x07070707U, 0x12121212U, 0x80808080U, 0xe2e2e2e2U, 0xebebebebU, 0x27272727U, 0xb2b2b2b2U, 0x75757575U, 0x09090909U, 0x83838383U, 0x2c2c2c2cU, 0x1a1a1a1aU, 0x1b1b1b1bU, 0x6e6e6e6eU, 0x5a5a5a5aU, 0xa0a0a0a0U, 0x52525252U, 0x3b3b3b3bU, 0xd6d6d6d6U, 0xb3b3b3b3U, 0x29292929U, 0xe3e3e3e3U, 0x2f2f2f2fU, 0x84848484U, 0x53535353U, 0xd1d1d1d1U, 0x00000000U, 0xededededU, 0x20202020U, 0xfcfcfcfcU, 0xb1b1b1b1U, 0x5b5b5b5bU, 0x6a6a6a6aU, 0xcbcbcbcbU, 0xbebebebeU, 0x39393939U, 0x4a4a4a4aU, 0x4c4c4c4cU, 0x58585858U, 0xcfcfcfcfU, 0xd0d0d0d0U, 0xefefefefU, 0xaaaaaaaaU, 0xfbfbfbfbU, 0x43434343U, 0x4d4d4d4dU, 0x33333333U, 0x85858585U, 0x45454545U, 0xf9f9f9f9U, 0x02020202U, 0x7f7f7f7fU, 0x50505050U, 0x3c3c3c3cU, 0x9f9f9f9fU, 0xa8a8a8a8U, 0x51515151U, 0xa3a3a3a3U, 0x40404040U, 0x8f8f8f8fU, 0x92929292U, 0x9d9d9d9dU, 0x38383838U, 0xf5f5f5f5U, 0xbcbcbcbcU, 0xb6b6b6b6U, 0xdadadadaU, 0x21212121U, 0x10101010U, 0xffffffffU, 0xf3f3f3f3U, 0xd2d2d2d2U, 0xcdcdcdcdU, 0x0c0c0c0cU, 0x13131313U, 0xececececU, 0x5f5f5f5fU, 0x97979797U, 0x44444444U, 0x17171717U, 0xc4c4c4c4U, 0xa7a7a7a7U, 0x7e7e7e7eU, 0x3d3d3d3dU, 0x64646464U, 0x5d5d5d5dU, 0x19191919U, 0x73737373U, 0x60606060U, 0x81818181U, 0x4f4f4f4fU, 0xdcdcdcdcU, 0x22222222U, 0x2a2a2a2aU, 0x90909090U, 0x88888888U, 0x46464646U, 0xeeeeeeeeU, 0xb8b8b8b8U, 0x14141414U, 0xdedededeU, 0x5e5e5e5eU, 0x0b0b0b0bU, 0xdbdbdbdbU, 0xe0e0e0e0U, 0x32323232U, 0x3a3a3a3aU, 0x0a0a0a0aU, 0x49494949U, 0x06060606U, 0x24242424U, 0x5c5c5c5cU, 0xc2c2c2c2U, 0xd3d3d3d3U, 0xacacacacU, 0x62626262U, 0x91919191U, 0x95959595U, 0xe4e4e4e4U, 0x79797979U, 0xe7e7e7e7U, 0xc8c8c8c8U, 0x37373737U, 0x6d6d6d6dU, 0x8d8d8d8dU, 0xd5d5d5d5U, 0x4e4e4e4eU, 0xa9a9a9a9U, 0x6c6c6c6cU, 0x56565656U, 0xf4f4f4f4U, 0xeaeaeaeaU, 0x65656565U, 0x7a7a7a7aU, 0xaeaeaeaeU, 0x08080808U, 0xbabababaU, 0x78787878U, 0x25252525U, 0x2e2e2e2eU, 0x1c1c1c1cU, 0xa6a6a6a6U, 0xb4b4b4b4U, 0xc6c6c6c6U, 0xe8e8e8e8U, 0xddddddddU, 0x74747474U, 0x1f1f1f1fU, 0x4b4b4b4bU, 0xbdbdbdbdU, 0x8b8b8b8bU, 0x8a8a8a8aU, 0x70707070U, 0x3e3e3e3eU, 0xb5b5b5b5U, 0x66666666U, 0x48484848U, 0x03030303U, 0xf6f6f6f6U, 0x0e0e0e0eU, 0x61616161U, 0x35353535U, 0x57575757U, 0xb9b9b9b9U, 0x86868686U, 0xc1c1c1c1U, 0x1d1d1d1dU, 0x9e9e9e9eU, 0xe1e1e1e1U, 0xf8f8f8f8U, 0x98989898U, 0x11111111U, 0x69696969U, 0xd9d9d9d9U, 0x8e8e8e8eU, 0x94949494U, 0x9b9b9b9bU, 0x1e1e1e1eU, 0x87878787U, 0xe9e9e9e9U, 0xcecececeU, 0x55555555U, 0x28282828U, 0xdfdfdfdfU, 0x8c8c8c8cU, 0xa1a1a1a1U, 0x89898989U, 0x0d0d0d0dU, 0xbfbfbfbfU, 0xe6e6e6e6U, 0x42424242U, 0x68686868U, 0x41414141U, 0x99999999U, 0x2d2d2d2dU, 0x0f0f0f0fU, 0xb0b0b0b0U, 0x54545454U, 0xbbbbbbbbU, 0x16161616U, }; static const u32 Td0[256] = { 0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U, 0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U, 0x2030fa55U, 0xad766df6U, 0x88cc7691U, 0xf5024c25U, 0x4fe5d7fcU, 0xc52acbd7U, 0x26354480U, 0xb562a38fU, 0xdeb15a49U, 0x25ba1b67U, 0x45ea0e98U, 0x5dfec0e1U, 0xc32f7502U, 0x814cf012U, 0x8d4697a3U, 0x6bd3f9c6U, 0x038f5fe7U, 0x15929c95U, 0xbf6d7aebU, 0x955259daU, 0xd4be832dU, 0x587421d3U, 0x49e06929U, 0x8ec9c844U, 0x75c2896aU, 0xf48e7978U, 0x99583e6bU, 0x27b971ddU, 0xbee14fb6U, 0xf088ad17U, 0xc920ac66U, 0x7dce3ab4U, 0x63df4a18U, 0xe51a3182U, 0x97513360U, 0x62537f45U, 0xb16477e0U, 0xbb6bae84U, 0xfe81a01cU, 0xf9082b94U, 0x70486858U, 0x8f45fd19U, 0x94de6c87U, 0x527bf8b7U, 0xab73d323U, 0x724b02e2U, 0xe31f8f57U, 0x6655ab2aU, 0xb2eb2807U, 0x2fb5c203U, 0x86c57b9aU, 0xd33708a5U, 0x302887f2U, 0x23bfa5b2U, 0x02036abaU, 0xed16825cU, 0x8acf1c2bU, 0xa779b492U, 0xf307f2f0U, 0x4e69e2a1U, 0x65daf4cdU, 0x0605bed5U, 0xd134621fU, 0xc4a6fe8aU, 0x342e539dU, 0xa2f355a0U, 0x058ae132U, 0xa4f6eb75U, 0x0b83ec39U, 0x4060efaaU, 0x5e719f06U, 0xbd6e1051U, 0x3e218af9U, 0x96dd063dU, 0xdd3e05aeU, 0x4de6bd46U, 0x91548db5U, 0x71c45d05U, 0x0406d46fU, 0x605015ffU, 0x1998fb24U, 0xd6bde997U, 0x894043ccU, 0x67d99e77U, 0xb0e842bdU, 0x07898b88U, 0xe7195b38U, 0x79c8eedbU, 0xa17c0a47U, 0x7c420fe9U, 0xf8841ec9U, 0x00000000U, 0x09808683U, 0x322bed48U, 0x1e1170acU, 0x6c5a724eU, 0xfd0efffbU, 0x0f853856U, 0x3daed51eU, 0x362d3927U, 0x0a0fd964U, 0x685ca621U, 0x9b5b54d1U, 0x24362e3aU, 0x0c0a67b1U, 0x9357e70fU, 0xb4ee96d2U, 0x1b9b919eU, 0x80c0c54fU, 0x61dc20a2U, 0x5a774b69U, 0x1c121a16U, 0xe293ba0aU, 0xc0a02ae5U, 0x3c22e043U, 0x121b171dU, 0x0e090d0bU, 0xf28bc7adU, 0x2db6a8b9U, 0x141ea9c8U, 0x57f11985U, 0xaf75074cU, 0xee99ddbbU, 0xa37f60fdU, 0xf701269fU, 0x5c72f5bcU, 0x44663bc5U, 0x5bfb7e34U, 0x8b432976U, 0xcb23c6dcU, 0xb6edfc68U, 0xb8e4f163U, 0xd731dccaU, 0x42638510U, 0x13972240U, 0x84c61120U, 0x854a247dU, 0xd2bb3df8U, 0xaef93211U, 0xc729a16dU, 0x1d9e2f4bU, 0xdcb230f3U, 0x0d8652ecU, 0x77c1e3d0U, 0x2bb3166cU, 0xa970b999U, 0x119448faU, 0x47e96422U, 0xa8fc8cc4U, 0xa0f03f1aU, 0x567d2cd8U, 0x223390efU, 0x87494ec7U, 0xd938d1c1U, 0x8ccaa2feU, 0x98d40b36U, 0xa6f581cfU, 0xa57ade28U, 0xdab78e26U, 0x3fadbfa4U, 0x2c3a9de4U, 0x5078920dU, 0x6a5fcc9bU, 0x547e4662U, 0xf68d13c2U, 0x90d8b8e8U, 0x2e39f75eU, 0x82c3aff5U, 0x9f5d80beU, 0x69d0937cU, 0x6fd52da9U, 0xcf2512b3U, 0xc8ac993bU, 0x10187da7U, 0xe89c636eU, 0xdb3bbb7bU, 0xcd267809U, 0x6e5918f4U, 0xec9ab701U, 0x834f9aa8U, 0xe6956e65U, 0xaaffe67eU, 0x21bccf08U, 0xef15e8e6U, 0xbae79bd9U, 0x4a6f36ceU, 0xea9f09d4U, 0x29b07cd6U, 0x31a4b2afU, 0x2a3f2331U, 0xc6a59430U, 0x35a266c0U, 0x744ebc37U, 0xfc82caa6U, 0xe090d0b0U, 0x33a7d815U, 0xf104984aU, 0x41ecdaf7U, 0x7fcd500eU, 0x1791f62fU, 0x764dd68dU, 0x43efb04dU, 0xccaa4d54U, 0xe49604dfU, 0x9ed1b5e3U, 0x4c6a881bU, 0xc12c1fb8U, 0x4665517fU, 0x9d5eea04U, 0x018c355dU, 0xfa877473U, 0xfb0b412eU, 0xb3671d5aU, 0x92dbd252U, 0xe9105633U, 0x6dd64713U, 0x9ad7618cU, 0x37a10c7aU, 0x59f8148eU, 0xeb133c89U, 0xcea927eeU, 0xb761c935U, 0xe11ce5edU, 0x7a47b13cU, 0x9cd2df59U, 0x55f2733fU, 0x1814ce79U, 0x73c737bfU, 0x53f7cdeaU, 0x5ffdaa5bU, 0xdf3d6f14U, 0x7844db86U, 0xcaaff381U, 0xb968c43eU, 0x3824342cU, 0xc2a3405fU, 0x161dc372U, 0xbce2250cU, 0x283c498bU, 0xff0d9541U, 0x39a80171U, 0x080cb3deU, 0xd8b4e49cU, 0x6456c190U, 0x7bcb8461U, 0xd532b670U, 0x486c5c74U, 0xd0b85742U, }; static const u32 Td1[256] = { 0x5051f4a7U, 0x537e4165U, 0xc31a17a4U, 0x963a275eU, 0xcb3bab6bU, 0xf11f9d45U, 0xabacfa58U, 0x934be303U, 0x552030faU, 0xf6ad766dU, 0x9188cc76U, 0x25f5024cU, 0xfc4fe5d7U, 0xd7c52acbU, 0x80263544U, 0x8fb562a3U, 0x49deb15aU, 0x6725ba1bU, 0x9845ea0eU, 0xe15dfec0U, 0x02c32f75U, 0x12814cf0U, 0xa38d4697U, 0xc66bd3f9U, 0xe7038f5fU, 0x9515929cU, 0xebbf6d7aU, 0xda955259U, 0x2dd4be83U, 0xd3587421U, 0x2949e069U, 0x448ec9c8U, 0x6a75c289U, 0x78f48e79U, 0x6b99583eU, 0xdd27b971U, 0xb6bee14fU, 0x17f088adU, 0x66c920acU, 0xb47dce3aU, 0x1863df4aU, 0x82e51a31U, 0x60975133U, 0x4562537fU, 0xe0b16477U, 0x84bb6baeU, 0x1cfe81a0U, 0x94f9082bU, 0x58704868U, 0x198f45fdU, 0x8794de6cU, 0xb7527bf8U, 0x23ab73d3U, 0xe2724b02U, 0x57e31f8fU, 0x2a6655abU, 0x07b2eb28U, 0x032fb5c2U, 0x9a86c57bU, 0xa5d33708U, 0xf2302887U, 0xb223bfa5U, 0xba02036aU, 0x5ced1682U, 0x2b8acf1cU, 0x92a779b4U, 0xf0f307f2U, 0xa14e69e2U, 0xcd65daf4U, 0xd50605beU, 0x1fd13462U, 0x8ac4a6feU, 0x9d342e53U, 0xa0a2f355U, 0x32058ae1U, 0x75a4f6ebU, 0x390b83ecU, 0xaa4060efU, 0x065e719fU, 0x51bd6e10U, 0xf93e218aU, 0x3d96dd06U, 0xaedd3e05U, 0x464de6bdU, 0xb591548dU, 0x0571c45dU, 0x6f0406d4U, 0xff605015U, 0x241998fbU, 0x97d6bde9U, 0xcc894043U, 0x7767d99eU, 0xbdb0e842U, 0x8807898bU, 0x38e7195bU, 0xdb79c8eeU, 0x47a17c0aU, 0xe97c420fU, 0xc9f8841eU, 0x00000000U, 0x83098086U, 0x48322bedU, 0xac1e1170U, 0x4e6c5a72U, 0xfbfd0effU, 0x560f8538U, 0x1e3daed5U, 0x27362d39U, 0x640a0fd9U, 0x21685ca6U, 0xd19b5b54U, 0x3a24362eU, 0xb10c0a67U, 0x0f9357e7U, 0xd2b4ee96U, 0x9e1b9b91U, 0x4f80c0c5U, 0xa261dc20U, 0x695a774bU, 0x161c121aU, 0x0ae293baU, 0xe5c0a02aU, 0x433c22e0U, 0x1d121b17U, 0x0b0e090dU, 0xadf28bc7U, 0xb92db6a8U, 0xc8141ea9U, 0x8557f119U, 0x4caf7507U, 0xbbee99ddU, 0xfda37f60U, 0x9ff70126U, 0xbc5c72f5U, 0xc544663bU, 0x345bfb7eU, 0x768b4329U, 0xdccb23c6U, 0x68b6edfcU, 0x63b8e4f1U, 0xcad731dcU, 0x10426385U, 0x40139722U, 0x2084c611U, 0x7d854a24U, 0xf8d2bb3dU, 0x11aef932U, 0x6dc729a1U, 0x4b1d9e2fU, 0xf3dcb230U, 0xec0d8652U, 0xd077c1e3U, 0x6c2bb316U, 0x99a970b9U, 0xfa119448U, 0x2247e964U, 0xc4a8fc8cU, 0x1aa0f03fU, 0xd8567d2cU, 0xef223390U, 0xc787494eU, 0xc1d938d1U, 0xfe8ccaa2U, 0x3698d40bU, 0xcfa6f581U, 0x28a57adeU, 0x26dab78eU, 0xa43fadbfU, 0xe42c3a9dU, 0x0d507892U, 0x9b6a5fccU, 0x62547e46U, 0xc2f68d13U, 0xe890d8b8U, 0x5e2e39f7U, 0xf582c3afU, 0xbe9f5d80U, 0x7c69d093U, 0xa96fd52dU, 0xb3cf2512U, 0x3bc8ac99U, 0xa710187dU, 0x6ee89c63U, 0x7bdb3bbbU, 0x09cd2678U, 0xf46e5918U, 0x01ec9ab7U, 0xa8834f9aU, 0x65e6956eU, 0x7eaaffe6U, 0x0821bccfU, 0xe6ef15e8U, 0xd9bae79bU, 0xce4a6f36U, 0xd4ea9f09U, 0xd629b07cU, 0xaf31a4b2U, 0x312a3f23U, 0x30c6a594U, 0xc035a266U, 0x37744ebcU, 0xa6fc82caU, 0xb0e090d0U, 0x1533a7d8U, 0x4af10498U, 0xf741ecdaU, 0x0e7fcd50U, 0x2f1791f6U, 0x8d764dd6U, 0x4d43efb0U, 0x54ccaa4dU, 0xdfe49604U, 0xe39ed1b5U, 0x1b4c6a88U, 0xb8c12c1fU, 0x7f466551U, 0x049d5eeaU, 0x5d018c35U, 0x73fa8774U, 0x2efb0b41U, 0x5ab3671dU, 0x5292dbd2U, 0x33e91056U, 0x136dd647U, 0x8c9ad761U, 0x7a37a10cU, 0x8e59f814U, 0x89eb133cU, 0xeecea927U, 0x35b761c9U, 0xede11ce5U, 0x3c7a47b1U, 0x599cd2dfU, 0x3f55f273U, 0x791814ceU, 0xbf73c737U, 0xea53f7cdU, 0x5b5ffdaaU, 0x14df3d6fU, 0x867844dbU, 0x81caaff3U, 0x3eb968c4U, 0x2c382434U, 0x5fc2a340U, 0x72161dc3U, 0x0cbce225U, 0x8b283c49U, 0x41ff0d95U, 0x7139a801U, 0xde080cb3U, 0x9cd8b4e4U, 0x906456c1U, 0x617bcb84U, 0x70d532b6U, 0x74486c5cU, 0x42d0b857U, }; static const u32 Td2[256] = { 0xa75051f4U, 0x65537e41U, 0xa4c31a17U, 0x5e963a27U, 0x6bcb3babU, 0x45f11f9dU, 0x58abacfaU, 0x03934be3U, 0xfa552030U, 0x6df6ad76U, 0x769188ccU, 0x4c25f502U, 0xd7fc4fe5U, 0xcbd7c52aU, 0x44802635U, 0xa38fb562U, 0x5a49deb1U, 0x1b6725baU, 0x0e9845eaU, 0xc0e15dfeU, 0x7502c32fU, 0xf012814cU, 0x97a38d46U, 0xf9c66bd3U, 0x5fe7038fU, 0x9c951592U, 0x7aebbf6dU, 0x59da9552U, 0x832dd4beU, 0x21d35874U, 0x692949e0U, 0xc8448ec9U, 0x896a75c2U, 0x7978f48eU, 0x3e6b9958U, 0x71dd27b9U, 0x4fb6bee1U, 0xad17f088U, 0xac66c920U, 0x3ab47dceU, 0x4a1863dfU, 0x3182e51aU, 0x33609751U, 0x7f456253U, 0x77e0b164U, 0xae84bb6bU, 0xa01cfe81U, 0x2b94f908U, 0x68587048U, 0xfd198f45U, 0x6c8794deU, 0xf8b7527bU, 0xd323ab73U, 0x02e2724bU, 0x8f57e31fU, 0xab2a6655U, 0x2807b2ebU, 0xc2032fb5U, 0x7b9a86c5U, 0x08a5d337U, 0x87f23028U, 0xa5b223bfU, 0x6aba0203U, 0x825ced16U, 0x1c2b8acfU, 0xb492a779U, 0xf2f0f307U, 0xe2a14e69U, 0xf4cd65daU, 0xbed50605U, 0x621fd134U, 0xfe8ac4a6U, 0x539d342eU, 0x55a0a2f3U, 0xe132058aU, 0xeb75a4f6U, 0xec390b83U, 0xefaa4060U, 0x9f065e71U, 0x1051bd6eU, 0x8af93e21U, 0x063d96ddU, 0x05aedd3eU, 0xbd464de6U, 0x8db59154U, 0x5d0571c4U, 0xd46f0406U, 0x15ff6050U, 0xfb241998U, 0xe997d6bdU, 0x43cc8940U, 0x9e7767d9U, 0x42bdb0e8U, 0x8b880789U, 0x5b38e719U, 0xeedb79c8U, 0x0a47a17cU, 0x0fe97c42U, 0x1ec9f884U, 0x00000000U, 0x86830980U, 0xed48322bU, 0x70ac1e11U, 0x724e6c5aU, 0xfffbfd0eU, 0x38560f85U, 0xd51e3daeU, 0x3927362dU, 0xd9640a0fU, 0xa621685cU, 0x54d19b5bU, 0x2e3a2436U, 0x67b10c0aU, 0xe70f9357U, 0x96d2b4eeU, 0x919e1b9bU, 0xc54f80c0U, 0x20a261dcU, 0x4b695a77U, 0x1a161c12U, 0xba0ae293U, 0x2ae5c0a0U, 0xe0433c22U, 0x171d121bU, 0x0d0b0e09U, 0xc7adf28bU, 0xa8b92db6U, 0xa9c8141eU, 0x198557f1U, 0x074caf75U, 0xddbbee99U, 0x60fda37fU, 0x269ff701U, 0xf5bc5c72U, 0x3bc54466U, 0x7e345bfbU, 0x29768b43U, 0xc6dccb23U, 0xfc68b6edU, 0xf163b8e4U, 0xdccad731U, 0x85104263U, 0x22401397U, 0x112084c6U, 0x247d854aU, 0x3df8d2bbU, 0x3211aef9U, 0xa16dc729U, 0x2f4b1d9eU, 0x30f3dcb2U, 0x52ec0d86U, 0xe3d077c1U, 0x166c2bb3U, 0xb999a970U, 0x48fa1194U, 0x642247e9U, 0x8cc4a8fcU, 0x3f1aa0f0U, 0x2cd8567dU, 0x90ef2233U, 0x4ec78749U, 0xd1c1d938U, 0xa2fe8ccaU, 0x0b3698d4U, 0x81cfa6f5U, 0xde28a57aU, 0x8e26dab7U, 0xbfa43fadU, 0x9de42c3aU, 0x920d5078U, 0xcc9b6a5fU, 0x4662547eU, 0x13c2f68dU, 0xb8e890d8U, 0xf75e2e39U, 0xaff582c3U, 0x80be9f5dU, 0x937c69d0U, 0x2da96fd5U, 0x12b3cf25U, 0x993bc8acU, 0x7da71018U, 0x636ee89cU, 0xbb7bdb3bU, 0x7809cd26U, 0x18f46e59U, 0xb701ec9aU, 0x9aa8834fU, 0x6e65e695U, 0xe67eaaffU, 0xcf0821bcU, 0xe8e6ef15U, 0x9bd9bae7U, 0x36ce4a6fU, 0x09d4ea9fU, 0x7cd629b0U, 0xb2af31a4U, 0x23312a3fU, 0x9430c6a5U, 0x66c035a2U, 0xbc37744eU, 0xcaa6fc82U, 0xd0b0e090U, 0xd81533a7U, 0x984af104U, 0xdaf741ecU, 0x500e7fcdU, 0xf62f1791U, 0xd68d764dU, 0xb04d43efU, 0x4d54ccaaU, 0x04dfe496U, 0xb5e39ed1U, 0x881b4c6aU, 0x1fb8c12cU, 0x517f4665U, 0xea049d5eU, 0x355d018cU, 0x7473fa87U, 0x412efb0bU, 0x1d5ab367U, 0xd25292dbU, 0x5633e910U, 0x47136dd6U, 0x618c9ad7U, 0x0c7a37a1U, 0x148e59f8U, 0x3c89eb13U, 0x27eecea9U, 0xc935b761U, 0xe5ede11cU, 0xb13c7a47U, 0xdf599cd2U, 0x733f55f2U, 0xce791814U, 0x37bf73c7U, 0xcdea53f7U, 0xaa5b5ffdU, 0x6f14df3dU, 0xdb867844U, 0xf381caafU, 0xc43eb968U, 0x342c3824U, 0x405fc2a3U, 0xc372161dU, 0x250cbce2U, 0x498b283cU, 0x9541ff0dU, 0x017139a8U, 0xb3de080cU, 0xe49cd8b4U, 0xc1906456U, 0x84617bcbU, 0xb670d532U, 0x5c74486cU, 0x5742d0b8U, }; static const u32 Td3[256] = { 0xf4a75051U, 0x4165537eU, 0x17a4c31aU, 0x275e963aU, 0xab6bcb3bU, 0x9d45f11fU, 0xfa58abacU, 0xe303934bU, 0x30fa5520U, 0x766df6adU, 0xcc769188U, 0x024c25f5U, 0xe5d7fc4fU, 0x2acbd7c5U, 0x35448026U, 0x62a38fb5U, 0xb15a49deU, 0xba1b6725U, 0xea0e9845U, 0xfec0e15dU, 0x2f7502c3U, 0x4cf01281U, 0x4697a38dU, 0xd3f9c66bU, 0x8f5fe703U, 0x929c9515U, 0x6d7aebbfU, 0x5259da95U, 0xbe832dd4U, 0x7421d358U, 0xe0692949U, 0xc9c8448eU, 0xc2896a75U, 0x8e7978f4U, 0x583e6b99U, 0xb971dd27U, 0xe14fb6beU, 0x88ad17f0U, 0x20ac66c9U, 0xce3ab47dU, 0xdf4a1863U, 0x1a3182e5U, 0x51336097U, 0x537f4562U, 0x6477e0b1U, 0x6bae84bbU, 0x81a01cfeU, 0x082b94f9U, 0x48685870U, 0x45fd198fU, 0xde6c8794U, 0x7bf8b752U, 0x73d323abU, 0x4b02e272U, 0x1f8f57e3U, 0x55ab2a66U, 0xeb2807b2U, 0xb5c2032fU, 0xc57b9a86U, 0x3708a5d3U, 0x2887f230U, 0xbfa5b223U, 0x036aba02U, 0x16825cedU, 0xcf1c2b8aU, 0x79b492a7U, 0x07f2f0f3U, 0x69e2a14eU, 0xdaf4cd65U, 0x05bed506U, 0x34621fd1U, 0xa6fe8ac4U, 0x2e539d34U, 0xf355a0a2U, 0x8ae13205U, 0xf6eb75a4U, 0x83ec390bU, 0x60efaa40U, 0x719f065eU, 0x6e1051bdU, 0x218af93eU, 0xdd063d96U, 0x3e05aeddU, 0xe6bd464dU, 0x548db591U, 0xc45d0571U, 0x06d46f04U, 0x5015ff60U, 0x98fb2419U, 0xbde997d6U, 0x4043cc89U, 0xd99e7767U, 0xe842bdb0U, 0x898b8807U, 0x195b38e7U, 0xc8eedb79U, 0x7c0a47a1U, 0x420fe97cU, 0x841ec9f8U, 0x00000000U, 0x80868309U, 0x2bed4832U, 0x1170ac1eU, 0x5a724e6cU, 0x0efffbfdU, 0x8538560fU, 0xaed51e3dU, 0x2d392736U, 0x0fd9640aU, 0x5ca62168U, 0x5b54d19bU, 0x362e3a24U, 0x0a67b10cU, 0x57e70f93U, 0xee96d2b4U, 0x9b919e1bU, 0xc0c54f80U, 0xdc20a261U, 0x774b695aU, 0x121a161cU, 0x93ba0ae2U, 0xa02ae5c0U, 0x22e0433cU, 0x1b171d12U, 0x090d0b0eU, 0x8bc7adf2U, 0xb6a8b92dU, 0x1ea9c814U, 0xf1198557U, 0x75074cafU, 0x99ddbbeeU, 0x7f60fda3U, 0x01269ff7U, 0x72f5bc5cU, 0x663bc544U, 0xfb7e345bU, 0x4329768bU, 0x23c6dccbU, 0xedfc68b6U, 0xe4f163b8U, 0x31dccad7U, 0x63851042U, 0x97224013U, 0xc6112084U, 0x4a247d85U, 0xbb3df8d2U, 0xf93211aeU, 0x29a16dc7U, 0x9e2f4b1dU, 0xb230f3dcU, 0x8652ec0dU, 0xc1e3d077U, 0xb3166c2bU, 0x70b999a9U, 0x9448fa11U, 0xe9642247U, 0xfc8cc4a8U, 0xf03f1aa0U, 0x7d2cd856U, 0x3390ef22U, 0x494ec787U, 0x38d1c1d9U, 0xcaa2fe8cU, 0xd40b3698U, 0xf581cfa6U, 0x7ade28a5U, 0xb78e26daU, 0xadbfa43fU, 0x3a9de42cU, 0x78920d50U, 0x5fcc9b6aU, 0x7e466254U, 0x8d13c2f6U, 0xd8b8e890U, 0x39f75e2eU, 0xc3aff582U, 0x5d80be9fU, 0xd0937c69U, 0xd52da96fU, 0x2512b3cfU, 0xac993bc8U, 0x187da710U, 0x9c636ee8U, 0x3bbb7bdbU, 0x267809cdU, 0x5918f46eU, 0x9ab701ecU, 0x4f9aa883U, 0x956e65e6U, 0xffe67eaaU, 0xbccf0821U, 0x15e8e6efU, 0xe79bd9baU, 0x6f36ce4aU, 0x9f09d4eaU, 0xb07cd629U, 0xa4b2af31U, 0x3f23312aU, 0xa59430c6U, 0xa266c035U, 0x4ebc3774U, 0x82caa6fcU, 0x90d0b0e0U, 0xa7d81533U, 0x04984af1U, 0xecdaf741U, 0xcd500e7fU, 0x91f62f17U, 0x4dd68d76U, 0xefb04d43U, 0xaa4d54ccU, 0x9604dfe4U, 0xd1b5e39eU, 0x6a881b4cU, 0x2c1fb8c1U, 0x65517f46U, 0x5eea049dU, 0x8c355d01U, 0x877473faU, 0x0b412efbU, 0x671d5ab3U, 0xdbd25292U, 0x105633e9U, 0xd647136dU, 0xd7618c9aU, 0xa10c7a37U, 0xf8148e59U, 0x133c89ebU, 0xa927eeceU, 0x61c935b7U, 0x1ce5ede1U, 0x47b13c7aU, 0xd2df599cU, 0xf2733f55U, 0x14ce7918U, 0xc737bf73U, 0xf7cdea53U, 0xfdaa5b5fU, 0x3d6f14dfU, 0x44db8678U, 0xaff381caU, 0x68c43eb9U, 0x24342c38U, 0xa3405fc2U, 0x1dc37216U, 0xe2250cbcU, 0x3c498b28U, 0x0d9541ffU, 0xa8017139U, 0x0cb3de08U, 0xb4e49cd8U, 0x56c19064U, 0xcb84617bU, 0x32b670d5U, 0x6c5c7448U, 0xb85742d0U, }; static const u32 Td4[256] = { 0x52525252U, 0x09090909U, 0x6a6a6a6aU, 0xd5d5d5d5U, 0x30303030U, 0x36363636U, 0xa5a5a5a5U, 0x38383838U, 0xbfbfbfbfU, 0x40404040U, 0xa3a3a3a3U, 0x9e9e9e9eU, 0x81818181U, 0xf3f3f3f3U, 0xd7d7d7d7U, 0xfbfbfbfbU, 0x7c7c7c7cU, 0xe3e3e3e3U, 0x39393939U, 0x82828282U, 0x9b9b9b9bU, 0x2f2f2f2fU, 0xffffffffU, 0x87878787U, 0x34343434U, 0x8e8e8e8eU, 0x43434343U, 0x44444444U, 0xc4c4c4c4U, 0xdedededeU, 0xe9e9e9e9U, 0xcbcbcbcbU, 0x54545454U, 0x7b7b7b7bU, 0x94949494U, 0x32323232U, 0xa6a6a6a6U, 0xc2c2c2c2U, 0x23232323U, 0x3d3d3d3dU, 0xeeeeeeeeU, 0x4c4c4c4cU, 0x95959595U, 0x0b0b0b0bU, 0x42424242U, 0xfafafafaU, 0xc3c3c3c3U, 0x4e4e4e4eU, 0x08080808U, 0x2e2e2e2eU, 0xa1a1a1a1U, 0x66666666U, 0x28282828U, 0xd9d9d9d9U, 0x24242424U, 0xb2b2b2b2U, 0x76767676U, 0x5b5b5b5bU, 0xa2a2a2a2U, 0x49494949U, 0x6d6d6d6dU, 0x8b8b8b8bU, 0xd1d1d1d1U, 0x25252525U, 0x72727272U, 0xf8f8f8f8U, 0xf6f6f6f6U, 0x64646464U, 0x86868686U, 0x68686868U, 0x98989898U, 0x16161616U, 0xd4d4d4d4U, 0xa4a4a4a4U, 0x5c5c5c5cU, 0xccccccccU, 0x5d5d5d5dU, 0x65656565U, 0xb6b6b6b6U, 0x92929292U, 0x6c6c6c6cU, 0x70707070U, 0x48484848U, 0x50505050U, 0xfdfdfdfdU, 0xededededU, 0xb9b9b9b9U, 0xdadadadaU, 0x5e5e5e5eU, 0x15151515U, 0x46464646U, 0x57575757U, 0xa7a7a7a7U, 0x8d8d8d8dU, 0x9d9d9d9dU, 0x84848484U, 0x90909090U, 0xd8d8d8d8U, 0xababababU, 0x00000000U, 0x8c8c8c8cU, 0xbcbcbcbcU, 0xd3d3d3d3U, 0x0a0a0a0aU, 0xf7f7f7f7U, 0xe4e4e4e4U, 0x58585858U, 0x05050505U, 0xb8b8b8b8U, 0xb3b3b3b3U, 0x45454545U, 0x06060606U, 0xd0d0d0d0U, 0x2c2c2c2cU, 0x1e1e1e1eU, 0x8f8f8f8fU, 0xcacacacaU, 0x3f3f3f3fU, 0x0f0f0f0fU, 0x02020202U, 0xc1c1c1c1U, 0xafafafafU, 0xbdbdbdbdU, 0x03030303U, 0x01010101U, 0x13131313U, 0x8a8a8a8aU, 0x6b6b6b6bU, 0x3a3a3a3aU, 0x91919191U, 0x11111111U, 0x41414141U, 0x4f4f4f4fU, 0x67676767U, 0xdcdcdcdcU, 0xeaeaeaeaU, 0x97979797U, 0xf2f2f2f2U, 0xcfcfcfcfU, 0xcecececeU, 0xf0f0f0f0U, 0xb4b4b4b4U, 0xe6e6e6e6U, 0x73737373U, 0x96969696U, 0xacacacacU, 0x74747474U, 0x22222222U, 0xe7e7e7e7U, 0xadadadadU, 0x35353535U, 0x85858585U, 0xe2e2e2e2U, 0xf9f9f9f9U, 0x37373737U, 0xe8e8e8e8U, 0x1c1c1c1cU, 0x75757575U, 0xdfdfdfdfU, 0x6e6e6e6eU, 0x47474747U, 0xf1f1f1f1U, 0x1a1a1a1aU, 0x71717171U, 0x1d1d1d1dU, 0x29292929U, 0xc5c5c5c5U, 0x89898989U, 0x6f6f6f6fU, 0xb7b7b7b7U, 0x62626262U, 0x0e0e0e0eU, 0xaaaaaaaaU, 0x18181818U, 0xbebebebeU, 0x1b1b1b1bU, 0xfcfcfcfcU, 0x56565656U, 0x3e3e3e3eU, 0x4b4b4b4bU, 0xc6c6c6c6U, 0xd2d2d2d2U, 0x79797979U, 0x20202020U, 0x9a9a9a9aU, 0xdbdbdbdbU, 0xc0c0c0c0U, 0xfefefefeU, 0x78787878U, 0xcdcdcdcdU, 0x5a5a5a5aU, 0xf4f4f4f4U, 0x1f1f1f1fU, 0xddddddddU, 0xa8a8a8a8U, 0x33333333U, 0x88888888U, 0x07070707U, 0xc7c7c7c7U, 0x31313131U, 0xb1b1b1b1U, 0x12121212U, 0x10101010U, 0x59595959U, 0x27272727U, 0x80808080U, 0xececececU, 0x5f5f5f5fU, 0x60606060U, 0x51515151U, 0x7f7f7f7fU, 0xa9a9a9a9U, 0x19191919U, 0xb5b5b5b5U, 0x4a4a4a4aU, 0x0d0d0d0dU, 0x2d2d2d2dU, 0xe5e5e5e5U, 0x7a7a7a7aU, 0x9f9f9f9fU, 0x93939393U, 0xc9c9c9c9U, 0x9c9c9c9cU, 0xefefefefU, 0xa0a0a0a0U, 0xe0e0e0e0U, 0x3b3b3b3bU, 0x4d4d4d4dU, 0xaeaeaeaeU, 0x2a2a2a2aU, 0xf5f5f5f5U, 0xb0b0b0b0U, 0xc8c8c8c8U, 0xebebebebU, 0xbbbbbbbbU, 0x3c3c3c3cU, 0x83838383U, 0x53535353U, 0x99999999U, 0x61616161U, 0x17171717U, 0x2b2b2b2bU, 0x04040404U, 0x7e7e7e7eU, 0xbabababaU, 0x77777777U, 0xd6d6d6d6U, 0x26262626U, 0xe1e1e1e1U, 0x69696969U, 0x14141414U, 0x63636363U, 0x55555555U, 0x21212121U, 0x0c0c0c0cU, 0x7d7d7d7dU, }; static const u32 rcon[] = { 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, 0x20000000, 0x40000000, 0x80000000, 0x1B000000, 0x36000000, /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */ }; #define GETU32(_storage) fetch_fw((BYTE*)(_storage)) #define PUTU32(_storage, _value) { store_fw(_storage, _value); } /** * Expand the cipher key into the encryption key schedule. * * @return the number of rounds for the given cipher key size. */ int rijndaelKeySetupEnc(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits) { int i = 0; u32 temp; rk[0] = GETU32(cipherKey ); rk[1] = GETU32(cipherKey + 4); rk[2] = GETU32(cipherKey + 8); rk[3] = GETU32(cipherKey + 12); if (keyBits == 128) { for (;;) { temp = rk[3]; rk[4] = rk[0] ^ (Te4[(temp >> 16) & 0xff] & 0xff000000) ^ (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^ (Te4[(temp ) & 0xff] & 0x0000ff00) ^ (Te4[(temp >> 24) ] & 0x000000ff) ^ rcon[i]; rk[5] = rk[1] ^ rk[4]; rk[6] = rk[2] ^ rk[5]; rk[7] = rk[3] ^ rk[6]; if (++i == 10) { return 10; } rk += 4; } } rk[4] = GETU32(cipherKey + 16); rk[5] = GETU32(cipherKey + 20); if (keyBits == 192) { for (;;) { temp = rk[ 5]; rk[ 6] = rk[ 0] ^ (Te4[(temp >> 16) & 0xff] & 0xff000000) ^ (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^ (Te4[(temp ) & 0xff] & 0x0000ff00) ^ (Te4[(temp >> 24) ] & 0x000000ff) ^ rcon[i]; rk[ 7] = rk[ 1] ^ rk[ 6]; rk[ 8] = rk[ 2] ^ rk[ 7]; rk[ 9] = rk[ 3] ^ rk[ 8]; if (++i == 8) { return 12; } rk[10] = rk[ 4] ^ rk[ 9]; rk[11] = rk[ 5] ^ rk[10]; rk += 6; } } rk[6] = GETU32(cipherKey + 24); rk[7] = GETU32(cipherKey + 28); if (keyBits == 256) { for (;;) { temp = rk[ 7]; rk[ 8] = rk[ 0] ^ (Te4[(temp >> 16) & 0xff] & 0xff000000) ^ (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^ (Te4[(temp ) & 0xff] & 0x0000ff00) ^ (Te4[(temp >> 24) ] & 0x000000ff) ^ rcon[i]; rk[ 9] = rk[ 1] ^ rk[ 8]; rk[10] = rk[ 2] ^ rk[ 9]; rk[11] = rk[ 3] ^ rk[10]; if (++i == 7) { return 14; } temp = rk[11]; rk[12] = rk[ 4] ^ (Te4[(temp >> 24) ] & 0xff000000) ^ (Te4[(temp >> 16) & 0xff] & 0x00ff0000) ^ (Te4[(temp >> 8) & 0xff] & 0x0000ff00) ^ (Te4[(temp ) & 0xff] & 0x000000ff); rk[13] = rk[ 5] ^ rk[12]; rk[14] = rk[ 6] ^ rk[13]; rk[15] = rk[ 7] ^ rk[14]; rk += 8; } } return 0; } /** * Expand the cipher key into the decryption key schedule. * * @return the number of rounds for the given cipher key size. */ int rijndaelKeySetupDec(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits) { int Nr, i, j; u32 temp; /* expand the cipher key: */ Nr = rijndaelKeySetupEnc(rk, cipherKey, keyBits); /* invert the order of the round keys: */ for (i = 0, j = 4*Nr; i < j; i += 4, j -= 4) { temp = rk[i ]; rk[i ] = rk[j ]; rk[j ] = temp; temp = rk[i + 1]; rk[i + 1] = rk[j + 1]; rk[j + 1] = temp; temp = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = temp; temp = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = temp; } /* apply the inverse MixColumn transform to all round keys but the first and the last: */ for (i = 1; i < Nr; i++) { rk += 4; rk[0] = Td0[Te4[(rk[0] >> 24) ] & 0xff] ^ Td1[Te4[(rk[0] >> 16) & 0xff] & 0xff] ^ Td2[Te4[(rk[0] >> 8) & 0xff] & 0xff] ^ Td3[Te4[(rk[0] ) & 0xff] & 0xff]; rk[1] = Td0[Te4[(rk[1] >> 24) ] & 0xff] ^ Td1[Te4[(rk[1] >> 16) & 0xff] & 0xff] ^ Td2[Te4[(rk[1] >> 8) & 0xff] & 0xff] ^ Td3[Te4[(rk[1] ) & 0xff] & 0xff]; rk[2] = Td0[Te4[(rk[2] >> 24) ] & 0xff] ^ Td1[Te4[(rk[2] >> 16) & 0xff] & 0xff] ^ Td2[Te4[(rk[2] >> 8) & 0xff] & 0xff] ^ Td3[Te4[(rk[2] ) & 0xff] & 0xff]; rk[3] = Td0[Te4[(rk[3] >> 24) ] & 0xff] ^ Td1[Te4[(rk[3] >> 16) & 0xff] & 0xff] ^ Td2[Te4[(rk[3] >> 8) & 0xff] & 0xff] ^ Td3[Te4[(rk[3] ) & 0xff] & 0xff]; } return Nr; } void rijndaelEncrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 pt[16], u8 ct[16]) { u32 s0, s1, s2, s3, t0, t1, t2, t3; #ifndef FULL_UNROLL int r; #endif /* ?FULL_UNROLL */ /* * map byte array block to cipher state * and add initial round key: */ s0 = GETU32(pt ) ^ rk[0]; s1 = GETU32(pt + 4) ^ rk[1]; s2 = GETU32(pt + 8) ^ rk[2]; s3 = GETU32(pt + 12) ^ rk[3]; #ifdef FULL_UNROLL /* round 1: */ t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[ 4]; t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[ 5]; t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[ 6]; t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[ 7]; /* round 2: */ s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[ 8]; s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[ 9]; s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[10]; s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[11]; /* round 3: */ t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[12]; t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[13]; t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[14]; t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[15]; /* round 4: */ s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[16]; s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[17]; s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[18]; s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[19]; /* round 5: */ t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[20]; t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[21]; t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[22]; t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[23]; /* round 6: */ s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[24]; s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[25]; s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[26]; s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[27]; /* round 7: */ t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[28]; t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[29]; t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[30]; t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[31]; /* round 8: */ s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[32]; s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[33]; s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[34]; s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[35]; /* round 9: */ t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[36]; t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[37]; t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[38]; t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[39]; if (Nr > 10) { /* round 10: */ s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[40]; s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[41]; s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[42]; s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[43]; /* round 11: */ t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[44]; t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[45]; t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[46]; t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[47]; if (Nr > 12) { /* round 12: */ s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[48]; s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[49]; s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[50]; s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[51]; /* round 13: */ t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[52]; t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[53]; t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[54]; t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[55]; } } rk += Nr << 2; #else /* !FULL_UNROLL */ /* * Nr - 1 full rounds: */ r = Nr >> 1; for (;;) { t0 = Te0[(s0 >> 24) ] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[(s3 ) & 0xff] ^ rk[4]; t1 = Te0[(s1 >> 24) ] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[(s0 ) & 0xff] ^ rk[5]; t2 = Te0[(s2 >> 24) ] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[(s1 ) & 0xff] ^ rk[6]; t3 = Te0[(s3 >> 24) ] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[(s2 ) & 0xff] ^ rk[7]; rk += 8; if (--r == 0) { break; } s0 = Te0[(t0 >> 24) ] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[(t3 ) & 0xff] ^ rk[0]; s1 = Te0[(t1 >> 24) ] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[(t0 ) & 0xff] ^ rk[1]; s2 = Te0[(t2 >> 24) ] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[(t1 ) & 0xff] ^ rk[2]; s3 = Te0[(t3 >> 24) ] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[(t2 ) & 0xff] ^ rk[3]; } #endif /* ?FULL_UNROLL */ /* * apply last round and * map cipher state to byte array block: */ s0 = (Te4[(t0 >> 24) ] & 0xff000000) ^ (Te4[(t1 >> 16) & 0xff] & 0x00ff0000) ^ (Te4[(t2 >> 8) & 0xff] & 0x0000ff00) ^ (Te4[(t3 ) & 0xff] & 0x000000ff) ^ rk[0]; PUTU32(ct , s0); s1 = (Te4[(t1 >> 24) ] & 0xff000000) ^ (Te4[(t2 >> 16) & 0xff] & 0x00ff0000) ^ (Te4[(t3 >> 8) & 0xff] & 0x0000ff00) ^ (Te4[(t0 ) & 0xff] & 0x000000ff) ^ rk[1]; PUTU32(ct + 4, s1); s2 = (Te4[(t2 >> 24) ] & 0xff000000) ^ (Te4[(t3 >> 16) & 0xff] & 0x00ff0000) ^ (Te4[(t0 >> 8) & 0xff] & 0x0000ff00) ^ (Te4[(t1 ) & 0xff] & 0x000000ff) ^ rk[2]; PUTU32(ct + 8, s2); s3 = (Te4[(t3 >> 24) ] & 0xff000000) ^ (Te4[(t0 >> 16) & 0xff] & 0x00ff0000) ^ (Te4[(t1 >> 8) & 0xff] & 0x0000ff00) ^ (Te4[(t2 ) & 0xff] & 0x000000ff) ^ rk[3]; PUTU32(ct + 12, s3); } static void rijndaelDecrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 ct[16], u8 pt[16]) { u32 s0, s1, s2, s3, t0, t1, t2, t3; #ifndef FULL_UNROLL int r; #endif /* ?FULL_UNROLL */ /* * map byte array block to cipher state * and add initial round key: */ s0 = GETU32(ct ) ^ rk[0]; s1 = GETU32(ct + 4) ^ rk[1]; s2 = GETU32(ct + 8) ^ rk[2]; s3 = GETU32(ct + 12) ^ rk[3]; #ifdef FULL_UNROLL /* round 1: */ t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[ 4]; t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[ 5]; t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[ 6]; t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[ 7]; /* round 2: */ s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[ 8]; s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[ 9]; s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[10]; s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[11]; /* round 3: */ t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[12]; t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[13]; t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[14]; t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[15]; /* round 4: */ s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[16]; s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[17]; s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[18]; s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[19]; /* round 5: */ t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[20]; t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[21]; t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[22]; t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[23]; /* round 6: */ s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[24]; s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[25]; s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[26]; s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[27]; /* round 7: */ t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[28]; t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[29]; t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[30]; t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[31]; /* round 8: */ s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[32]; s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[33]; s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[34]; s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[35]; /* round 9: */ t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[36]; t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[37]; t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[38]; t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[39]; if (Nr > 10) { /* round 10: */ s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[40]; s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[41]; s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[42]; s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[43]; /* round 11: */ t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[44]; t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[45]; t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[46]; t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[47]; if (Nr > 12) { /* round 12: */ s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[48]; s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[49]; s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[50]; s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[51]; /* round 13: */ t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[52]; t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[53]; t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[54]; t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[55]; } } rk += Nr << 2; #else /* !FULL_UNROLL */ /* * Nr - 1 full rounds: */ r = Nr >> 1; for (;;) { t0 = Td0[(s0 >> 24) ] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[(s1 ) & 0xff] ^ rk[4]; t1 = Td0[(s1 >> 24) ] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[(s2 ) & 0xff] ^ rk[5]; t2 = Td0[(s2 >> 24) ] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[(s3 ) & 0xff] ^ rk[6]; t3 = Td0[(s3 >> 24) ] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[(s0 ) & 0xff] ^ rk[7]; rk += 8; if (--r == 0) { break; } s0 = Td0[(t0 >> 24) ] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[(t1 ) & 0xff] ^ rk[0]; s1 = Td0[(t1 >> 24) ] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[(t2 ) & 0xff] ^ rk[1]; s2 = Td0[(t2 >> 24) ] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[(t3 ) & 0xff] ^ rk[2]; s3 = Td0[(t3 >> 24) ] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[(t0 ) & 0xff] ^ rk[3]; } #endif /* ?FULL_UNROLL */ /* * apply last round and * map cipher state to byte array block: */ s0 = (Td4[(t0 >> 24) ] & 0xff000000) ^ (Td4[(t3 >> 16) & 0xff] & 0x00ff0000) ^ (Td4[(t2 >> 8) & 0xff] & 0x0000ff00) ^ (Td4[(t1 ) & 0xff] & 0x000000ff) ^ rk[0]; PUTU32(pt , s0); s1 = (Td4[(t1 >> 24) ] & 0xff000000) ^ (Td4[(t0 >> 16) & 0xff] & 0x00ff0000) ^ (Td4[(t3 >> 8) & 0xff] & 0x0000ff00) ^ (Td4[(t2 ) & 0xff] & 0x000000ff) ^ rk[1]; PUTU32(pt + 4, s1); s2 = (Td4[(t2 >> 24) ] & 0xff000000) ^ (Td4[(t1 >> 16) & 0xff] & 0x00ff0000) ^ (Td4[(t0 >> 8) & 0xff] & 0x0000ff00) ^ (Td4[(t3 ) & 0xff] & 0x000000ff) ^ rk[2]; PUTU32(pt + 8, s2); s3 = (Td4[(t3 >> 24) ] & 0xff000000) ^ (Td4[(t2 >> 16) & 0xff] & 0x00ff0000) ^ (Td4[(t1 >> 8) & 0xff] & 0x0000ff00) ^ (Td4[(t0 ) & 0xff] & 0x000000ff) ^ rk[3]; PUTU32(pt + 12, s3); } /* setup key context for encryption only */ int rijndael_set_key_enc_only(rijndael_ctx *ctx, u_char *key, int bits) { int rounds; rounds = rijndaelKeySetupEnc(ctx->ek, key, bits); if (rounds == 0) return -1; ctx->Nr = rounds; ctx->enc_only = 1; return 0; } /* setup key context for both encryption and decryption */ int rijndael_set_key(rijndael_ctx *ctx, u_char *key, int bits) { int rounds; rounds = rijndaelKeySetupEnc(ctx->ek, key, bits); if (rounds == 0) return -1; if (rijndaelKeySetupDec(ctx->dk, key, bits) != rounds) return -1; ctx->Nr = rounds; ctx->enc_only = 0; return 0; } void rijndael_decrypt(rijndael_ctx *ctx, u_char *src, u_char *dst) { rijndaelDecrypt(ctx->dk, ctx->Nr, src, dst); } void rijndael_encrypt(rijndael_ctx *ctx, u_char *src, u_char *dst) { rijndaelEncrypt(ctx->ek, ctx->Nr, src, dst); } hercules-3.07/crypto/aes.h000644 000765 000765 00000005056 11143760536 017220 0ustar00jmaynardjmaynard000000 000000 /* $OpenBSD: rijndael.h,v 1.11 2005/05/25 05:47:53 markus Exp $ */ /* modified for use by dyncrypt */ // $Id: aes.h 4102 2006-12-08 09:43:35Z jj $ /** * rijndael-alg-fst.h * * @version 3.0 (December 2000) * * Optimised ANSI C code for the Rijndael cipher (now AES) * * @author Vincent Rijmen * @author Antoon Bosselaers * @author Paulo Barreto * * This code is hereby placed in the public domain. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''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 AUTHORS 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. */ // $Log$ #ifndef __RIJNDAEL_H #define __RIJNDAEL_H #define MAXKC (256/32) #define MAXKB (256/8) #define MAXNR 14 typedef u_int8_t u8; typedef u_int16_t u16; typedef u_int32_t u32; /* The structure for key information */ typedef struct { int enc_only; /* context contains only encrypt schedule */ int Nr; /* key-length-dependent number of rounds */ u32 ek[4*(MAXNR + 1)]; /* encrypt key schedule */ u32 dk[4*(MAXNR + 1)]; /* decrypt key schedule */ } rijndael_ctx; int rijndael_set_key(rijndael_ctx *, u_char *, int); int rijndael_set_key_enc_only(rijndael_ctx *, u_char *, int); void rijndael_decrypt(rijndael_ctx *, u_char *, u_char *); void rijndael_encrypt(rijndael_ctx *, u_char *, u_char *); int rijndaelKeySetupEnc(unsigned int [], const unsigned char [], int); int rijndaelKeySetupDec(unsigned int [], const unsigned char [], int); void rijndaelEncrypt(const unsigned int [], int, const unsigned char [], unsigned char []); /* Additional definitions for dyncrypt */ typedef rijndael_ctx aes_context; #define aes_set_key rijndael_set_key #define aes_encrypt rijndael_encrypt #define aes_decrypt rijndael_decrypt #endif /* __RIJNDAEL_H */ hercules-3.07/crypto/des.c000644 000765 000765 00000070654 11143760536 017224 0ustar00jmaynardjmaynard000000 000000 /* des.c - implementation of DES * http://www.tartarus.org/~simon-anonsvn/viewcvs.cgi/putty/ * modified for use with dyncrypt */ // $Id: des.c 4102 2006-12-08 09:43:35Z jj $ /* * PuTTY is copyright 1997-2005 Simon Tatham. * * Portions copyright Robert de Bath, Joris van Rantwijk, Delian * Delchev, Andreas Schultz, Jeroen Massar, Wez Furlong, Nicolas Barry, * Justin Bradford, Ben Harris, Malcolm Smith, Ahmad Khalifa, Markus * Kuhn, and CORE SDI S.A. * * 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 COPYRIGHT HOLDERS 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. */ // $Log$ #include "hstdinc.h" #if !defined(_HENGINE_DLL_) #define _HENGINE_DLL_ #endif #include "hercules.h" #include "opcode.h" /* For fetch_fw */ #include "des.h" /* * Description of DES * ------------------ * * Unlike the description in FIPS 46, I'm going to use _sensible_ indices: * bits in an n-bit word are numbered from 0 at the LSB to n-1 at the MSB. * And S-boxes are indexed by six consecutive bits, not by the outer two * followed by the middle four. * * The DES encryption routine requires a 64-bit input, and a key schedule K * containing 16 48-bit elements. * * First the input is permuted by the initial permutation IP. * Then the input is split into 32-bit words L and R. (L is the MSW.) * Next, 16 rounds. In each round: * (L, R) <- (R, L xor f(R, K[i])) * Then the pre-output words L and R are swapped. * Then L and R are glued back together into a 64-bit word. (L is the MSW, * again, but since we just swapped them, the MSW is the R that came out * of the last round.) * The 64-bit output block is permuted by the inverse of IP and returned. * * Decryption is identical except that the elements of K are used in the * opposite order. (This wouldn't work if that word swap didn't happen.) * * The function f, used in each round, accepts a 32-bit word R and a * 48-bit key block K. It produces a 32-bit output. * * First R is expanded to 48 bits using the bit-selection function E. * The resulting 48-bit block is XORed with the key block K to produce * a 48-bit block X. * This block X is split into eight groups of 6 bits. Each group of 6 * bits is then looked up in one of the eight S-boxes to convert * it to 4 bits. These eight groups of 4 bits are glued back * together to produce a 32-bit preoutput block. * The preoutput block is permuted using the permutation P and returned. * * Key setup maps a 64-bit key word into a 16x48-bit key schedule. Although * the approved input format for the key is a 64-bit word, eight of the * bits are discarded, so the actual quantity of key used is 56 bits. * * First the input key is converted to two 28-bit words C and D using * the bit-selection function PC1. * Then 16 rounds of key setup occur. In each round, C and D are each * rotated left by either 1 or 2 bits (depending on which round), and * then converted into a key schedule element using the bit-selection * function PC2. * * That's the actual algorithm. Now for the tedious details: all those * painful permutations and lookup tables. * * IP is a 64-to-64 bit permutation. Its output contains the following * bits of its input (listed in order MSB to LSB of output). * * 6 14 22 30 38 46 54 62 4 12 20 28 36 44 52 60 * 2 10 18 26 34 42 50 58 0 8 16 24 32 40 48 56 * 7 15 23 31 39 47 55 63 5 13 21 29 37 45 53 61 * 3 11 19 27 35 43 51 59 1 9 17 25 33 41 49 57 * * E is a 32-to-48 bit selection function. Its output contains the following * bits of its input (listed in order MSB to LSB of output). * * 0 31 30 29 28 27 28 27 26 25 24 23 24 23 22 21 20 19 20 19 18 17 16 15 * 16 15 14 13 12 11 12 11 10 9 8 7 8 7 6 5 4 3 4 3 2 1 0 31 * * The S-boxes are arbitrary table-lookups each mapping a 6-bit input to a * 4-bit output. In other words, each S-box is an array[64] of 4-bit numbers. * The S-boxes are listed below. The first S-box listed is applied to the * most significant six bits of the block X; the last one is applied to the * least significant. * * 14 0 4 15 13 7 1 4 2 14 15 2 11 13 8 1 * 3 10 10 6 6 12 12 11 5 9 9 5 0 3 7 8 * 4 15 1 12 14 8 8 2 13 4 6 9 2 1 11 7 * 15 5 12 11 9 3 7 14 3 10 10 0 5 6 0 13 * * 15 3 1 13 8 4 14 7 6 15 11 2 3 8 4 14 * 9 12 7 0 2 1 13 10 12 6 0 9 5 11 10 5 * 0 13 14 8 7 10 11 1 10 3 4 15 13 4 1 2 * 5 11 8 6 12 7 6 12 9 0 3 5 2 14 15 9 * * 10 13 0 7 9 0 14 9 6 3 3 4 15 6 5 10 * 1 2 13 8 12 5 7 14 11 12 4 11 2 15 8 1 * 13 1 6 10 4 13 9 0 8 6 15 9 3 8 0 7 * 11 4 1 15 2 14 12 3 5 11 10 5 14 2 7 12 * * 7 13 13 8 14 11 3 5 0 6 6 15 9 0 10 3 * 1 4 2 7 8 2 5 12 11 1 12 10 4 14 15 9 * 10 3 6 15 9 0 0 6 12 10 11 1 7 13 13 8 * 15 9 1 4 3 5 14 11 5 12 2 7 8 2 4 14 * * 2 14 12 11 4 2 1 12 7 4 10 7 11 13 6 1 * 8 5 5 0 3 15 15 10 13 3 0 9 14 8 9 6 * 4 11 2 8 1 12 11 7 10 1 13 14 7 2 8 13 * 15 6 9 15 12 0 5 9 6 10 3 4 0 5 14 3 * * 12 10 1 15 10 4 15 2 9 7 2 12 6 9 8 5 * 0 6 13 1 3 13 4 14 14 0 7 11 5 3 11 8 * 9 4 14 3 15 2 5 12 2 9 8 5 12 15 3 10 * 7 11 0 14 4 1 10 7 1 6 13 0 11 8 6 13 * * 4 13 11 0 2 11 14 7 15 4 0 9 8 1 13 10 * 3 14 12 3 9 5 7 12 5 2 10 15 6 8 1 6 * 1 6 4 11 11 13 13 8 12 1 3 4 7 10 14 7 * 10 9 15 5 6 0 8 15 0 14 5 2 9 3 2 12 * * 13 1 2 15 8 13 4 8 6 10 15 3 11 7 1 4 * 10 12 9 5 3 6 14 11 5 0 0 14 12 9 7 2 * 7 2 11 1 4 14 1 7 9 4 12 10 14 8 2 13 * 0 15 6 12 10 9 13 0 15 3 3 5 5 6 8 11 * * P is a 32-to-32 bit permutation. Its output contains the following * bits of its input (listed in order MSB to LSB of output). * * 16 25 12 11 3 20 4 15 31 17 9 6 27 14 1 22 * 30 24 8 18 0 5 29 23 13 19 2 26 10 21 28 7 * * PC1 is a 64-to-56 bit selection function. Its output is in two words, * C and D. The word C contains the following bits of its input (listed * in order MSB to LSB of output). * * 7 15 23 31 39 47 55 63 6 14 22 30 38 46 * 54 62 5 13 21 29 37 45 53 61 4 12 20 28 * * And the word D contains these bits. * * 1 9 17 25 33 41 49 57 2 10 18 26 34 42 * 50 58 3 11 19 27 35 43 51 59 36 44 52 60 * * PC2 is a 56-to-48 bit selection function. Its input is in two words, * C and D. These are treated as one 56-bit word (with C more significant, * so that bits 55 to 28 of the word are bits 27 to 0 of C, and bits 27 to * 0 of the word are bits 27 to 0 of D). The output contains the following * bits of this 56-bit input word (listed in order MSB to LSB of output). * * 42 39 45 32 55 51 53 28 41 50 35 46 33 37 44 52 30 48 40 49 29 36 43 54 * 15 4 25 19 9 1 26 16 5 11 23 8 12 7 17 0 22 3 10 14 6 20 27 24 */ /* * Implementation details * ---------------------- * * If you look at the code in this module, you'll find it looks * nothing _like_ the above algorithm. Here I explain the * differences... * * Key setup has not been heavily optimised here. We are not * concerned with key agility: we aren't codebreakers. We don't * mind a little delay (and it really is a little one; it may be a * factor of five or so slower than it could be but it's still not * an appreciable length of time) while setting up. The only tweaks * in the key setup are ones which change the format of the key * schedule to speed up the actual encryption. I'll describe those * below. * * The first and most obvious optimisation is the S-boxes. Since * each S-box always targets the same four bits in the final 32-bit * word, so the output from (for example) S-box 0 must always be * shifted left 28 bits, we can store the already-shifted outputs * in the lookup tables. This reduces lookup-and-shift to lookup, * so the S-box step is now just a question of ORing together eight * table lookups. * * The permutation P is just a bit order change; it's invariant * with respect to OR, in that P(x)|P(y) = P(x|y). Therefore, we * can apply P to every entry of the S-box tables and then we don't * have to do it in the code of f(). This yields a set of tables * which might be called SP-boxes. * * The bit-selection function E is our next target. Note that E is * immediately followed by the operation of splitting into 6-bit * chunks. Examining the 6-bit chunks coming out of E we notice * they're all contiguous within the word (speaking cyclically - * the end two wrap round); so we can extract those bit strings * individually rather than explicitly running E. This would yield * code such as * * y |= SPboxes[0][ (rotl(R, 5) ^ top6bitsofK) & 0x3F ]; * t |= SPboxes[1][ (rotl(R,11) ^ next6bitsofK) & 0x3F ]; * * and so on; and the key schedule preparation would have to * provide each 6-bit chunk separately. * * Really we'd like to XOR in the key schedule element before * looking up bit strings in R. This we can't do, naively, because * the 6-bit strings we want overlap. But look at the strings: * * 3322222222221111111111 * bit 10987654321098765432109876543210 * * box0 XXXXX X * box1 XXXXXX * box2 XXXXXX * box3 XXXXXX * box4 XXXXXX * box5 XXXXXX * box6 XXXXXX * box7 X XXXXX * * The bit strings we need to XOR in for boxes 0, 2, 4 and 6 don't * overlap with each other. Neither do the ones for boxes 1, 3, 5 * and 7. So we could provide the key schedule in the form of two * words that we can separately XOR into R, and then every S-box * index is available as a (cyclically) contiguous 6-bit substring * of one or the other of the results. * * The comments in Eric Young's libdes implementation point out * that two of these bit strings require a rotation (rather than a * simple shift) to extract. It's unavoidable that at least _one_ * must do; but we can actually run the whole inner algorithm (all * 16 rounds) rotated one bit to the left, so that what the `real' * DES description sees as L=0x80000001 we see as L=0x00000003. * This requires rotating all our SP-box entries one bit to the * left, and rotating each word of the key schedule elements one to * the left, and rotating L and R one bit left just after IP and * one bit right again just before FP. And in each round we convert * a rotate into a shift, so we've saved a few per cent. * * That's about it for the inner loop; the SP-box tables as listed * below are what I've described here (the original S value, * shifted to its final place in the input to P, run through P, and * then rotated one bit left). All that remains is to optimise the * initial permutation IP. * * IP is not an arbitrary permutation. It has the nice property * that if you take any bit number, write it in binary (6 bits), * permute those 6 bits and invert some of them, you get the final * position of that bit. Specifically, the bit whose initial * position is given (in binary) as fedcba ends up in position * AcbFED (where a capital letter denotes the inverse of a bit). * * We have the 64-bit data in two 32-bit words L and R, where bits * in L are those with f=1 and bits in R are those with f=0. We * note that we can do a simple transformation: suppose we exchange * the bits with f=1,c=0 and the bits with f=0,c=1. This will cause * the bit fedcba to be in position cedfba - we've `swapped' bits c * and f in the position of each bit! * * Better still, this transformation is easy. In the example above, * bits in L with c=0 are bits 0x0F0F0F0F, and those in R with c=1 * are 0xF0F0F0F0. So we can do * * difference = ((R >> 4) ^ L) & 0x0F0F0F0F * R ^= (difference << 4) * L ^= difference * * to perform the swap. Let's denote this by bitswap(4,0x0F0F0F0F). * Also, we can invert the bit at the top just by exchanging L and * R. So in a few swaps and a few of these bit operations we can * do: * * Initially the position of bit fedcba is fedcba * Swap L with R to make it Fedcba * Perform bitswap( 4,0x0F0F0F0F) to make it cedFba * Perform bitswap(16,0x0000FFFF) to make it ecdFba * Swap L with R to make it EcdFba * Perform bitswap( 2,0x33333333) to make it bcdFEa * Perform bitswap( 8,0x00FF00FF) to make it dcbFEa * Swap L with R to make it DcbFEa * Perform bitswap( 1,0x55555555) to make it acbFED * Swap L with R to make it AcbFED * * (In the actual code the four swaps are implicit: R and L are * simply used the other way round in the first, second and last * bitswap operations.) * * The final permutation is just the inverse of IP, so it can be * performed by a similar set of operations. */ #define rotl(x, c) ( (x << c) | (x >> (32-c)) ) #define rotl28(x, c) ( ( (x << c) | (x >> (28-c)) ) & 0x0FFFFFFF) #define GET_32BIT_MSB_FIRST(_storage) fetch_fw((BYTE*)(_storage)) #define PUT_32BIT_MSB_FIRST(_storage, _value) store_fw(_storage, _value) static word32 bitsel(word32 * input, const int *bitnums, int size) { word32 ret = 0; while (size--) { int bitpos = *bitnums++; ret <<= 1; if (bitpos >= 0) ret |= 1 & (input[bitpos / 32] >> (bitpos % 32)); } return ret; } static void des_key_setup(word32 key_msw, word32 key_lsw, DESContext * sched) { static const int PC1_Cbits[] = { 7, 15, 23, 31, 39, 47, 55, 63, 6, 14, 22, 30, 38, 46, 54, 62, 5, 13, 21, 29, 37, 45, 53, 61, 4, 12, 20, 28 }; static const int PC1_Dbits[] = { 1, 9, 17, 25, 33, 41, 49, 57, 2, 10, 18, 26, 34, 42, 50, 58, 3, 11, 19, 27, 35, 43, 51, 59, 36, 44, 52, 60 }; /* * The bit numbers in the two lists below don't correspond to * the ones in the above description of PC2, because in the * above description C and D are concatenated so `bit 28' means * bit 0 of C. In this implementation we're using the standard * `bitsel' function above and C is in the second word, so bit * 0 of C is addressed by writing `32' here. */ static const int PC2_0246[] = { 49, 36, 59, 55, -1, -1, 37, 41, 48, 56, 34, 52, -1, -1, 15, 4, 25, 19, 9, 1, -1, -1, 12, 7, 17, 0, 22, 3, -1, -1, 46, 43 }; static const int PC2_1357[] = { -1, -1, 57, 32, 45, 54, 39, 50, -1, -1, 44, 53, 33, 40, 47, 58, -1, -1, 26, 16, 5, 11, 23, 8, -1, -1, 10, 14, 6, 20, 27, 24 }; static const int leftshifts[] = { 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 }; word32 C, D; word32 buf[2]; int i; buf[0] = key_lsw; buf[1] = key_msw; C = bitsel(buf, PC1_Cbits, 28); D = bitsel(buf, PC1_Dbits, 28); for (i = 0; i < 16; i++) { C = rotl28(C, leftshifts[i]); D = rotl28(D, leftshifts[i]); buf[0] = D; buf[1] = C; sched->k0246[i] = bitsel(buf, PC2_0246, 32); sched->k1357[i] = bitsel(buf, PC2_1357, 32); } sched->iv0 = sched->iv1 = 0; } static const word32 SPboxes[8][64] = { {0x01010400, 0x00000000, 0x00010000, 0x01010404, 0x01010004, 0x00010404, 0x00000004, 0x00010000, 0x00000400, 0x01010400, 0x01010404, 0x00000400, 0x01000404, 0x01010004, 0x01000000, 0x00000004, 0x00000404, 0x01000400, 0x01000400, 0x00010400, 0x00010400, 0x01010000, 0x01010000, 0x01000404, 0x00010004, 0x01000004, 0x01000004, 0x00010004, 0x00000000, 0x00000404, 0x00010404, 0x01000000, 0x00010000, 0x01010404, 0x00000004, 0x01010000, 0x01010400, 0x01000000, 0x01000000, 0x00000400, 0x01010004, 0x00010000, 0x00010400, 0x01000004, 0x00000400, 0x00000004, 0x01000404, 0x00010404, 0x01010404, 0x00010004, 0x01010000, 0x01000404, 0x01000004, 0x00000404, 0x00010404, 0x01010400, 0x00000404, 0x01000400, 0x01000400, 0x00000000, 0x00010004, 0x00010400, 0x00000000, 0x01010004L}, {0x80108020, 0x80008000, 0x00008000, 0x00108020, 0x00100000, 0x00000020, 0x80100020, 0x80008020, 0x80000020, 0x80108020, 0x80108000, 0x80000000, 0x80008000, 0x00100000, 0x00000020, 0x80100020, 0x00108000, 0x00100020, 0x80008020, 0x00000000, 0x80000000, 0x00008000, 0x00108020, 0x80100000, 0x00100020, 0x80000020, 0x00000000, 0x00108000, 0x00008020, 0x80108000, 0x80100000, 0x00008020, 0x00000000, 0x00108020, 0x80100020, 0x00100000, 0x80008020, 0x80100000, 0x80108000, 0x00008000, 0x80100000, 0x80008000, 0x00000020, 0x80108020, 0x00108020, 0x00000020, 0x00008000, 0x80000000, 0x00008020, 0x80108000, 0x00100000, 0x80000020, 0x00100020, 0x80008020, 0x80000020, 0x00100020, 0x00108000, 0x00000000, 0x80008000, 0x00008020, 0x80000000, 0x80100020, 0x80108020, 0x00108000L}, {0x00000208, 0x08020200, 0x00000000, 0x08020008, 0x08000200, 0x00000000, 0x00020208, 0x08000200, 0x00020008, 0x08000008, 0x08000008, 0x00020000, 0x08020208, 0x00020008, 0x08020000, 0x00000208, 0x08000000, 0x00000008, 0x08020200, 0x00000200, 0x00020200, 0x08020000, 0x08020008, 0x00020208, 0x08000208, 0x00020200, 0x00020000, 0x08000208, 0x00000008, 0x08020208, 0x00000200, 0x08000000, 0x08020200, 0x08000000, 0x00020008, 0x00000208, 0x00020000, 0x08020200, 0x08000200, 0x00000000, 0x00000200, 0x00020008, 0x08020208, 0x08000200, 0x08000008, 0x00000200, 0x00000000, 0x08020008, 0x08000208, 0x00020000, 0x08000000, 0x08020208, 0x00000008, 0x00020208, 0x00020200, 0x08000008, 0x08020000, 0x08000208, 0x00000208, 0x08020000, 0x00020208, 0x00000008, 0x08020008, 0x00020200L}, {0x00802001, 0x00002081, 0x00002081, 0x00000080, 0x00802080, 0x00800081, 0x00800001, 0x00002001, 0x00000000, 0x00802000, 0x00802000, 0x00802081, 0x00000081, 0x00000000, 0x00800080, 0x00800001, 0x00000001, 0x00002000, 0x00800000, 0x00802001, 0x00000080, 0x00800000, 0x00002001, 0x00002080, 0x00800081, 0x00000001, 0x00002080, 0x00800080, 0x00002000, 0x00802080, 0x00802081, 0x00000081, 0x00800080, 0x00800001, 0x00802000, 0x00802081, 0x00000081, 0x00000000, 0x00000000, 0x00802000, 0x00002080, 0x00800080, 0x00800081, 0x00000001, 0x00802001, 0x00002081, 0x00002081, 0x00000080, 0x00802081, 0x00000081, 0x00000001, 0x00002000, 0x00800001, 0x00002001, 0x00802080, 0x00800081, 0x00002001, 0x00002080, 0x00800000, 0x00802001, 0x00000080, 0x00800000, 0x00002000, 0x00802080L}, {0x00000100, 0x02080100, 0x02080000, 0x42000100, 0x00080000, 0x00000100, 0x40000000, 0x02080000, 0x40080100, 0x00080000, 0x02000100, 0x40080100, 0x42000100, 0x42080000, 0x00080100, 0x40000000, 0x02000000, 0x40080000, 0x40080000, 0x00000000, 0x40000100, 0x42080100, 0x42080100, 0x02000100, 0x42080000, 0x40000100, 0x00000000, 0x42000000, 0x02080100, 0x02000000, 0x42000000, 0x00080100, 0x00080000, 0x42000100, 0x00000100, 0x02000000, 0x40000000, 0x02080000, 0x42000100, 0x40080100, 0x02000100, 0x40000000, 0x42080000, 0x02080100, 0x40080100, 0x00000100, 0x02000000, 0x42080000, 0x42080100, 0x00080100, 0x42000000, 0x42080100, 0x02080000, 0x00000000, 0x40080000, 0x42000000, 0x00080100, 0x02000100, 0x40000100, 0x00080000, 0x00000000, 0x40080000, 0x02080100, 0x40000100L}, {0x20000010, 0x20400000, 0x00004000, 0x20404010, 0x20400000, 0x00000010, 0x20404010, 0x00400000, 0x20004000, 0x00404010, 0x00400000, 0x20000010, 0x00400010, 0x20004000, 0x20000000, 0x00004010, 0x00000000, 0x00400010, 0x20004010, 0x00004000, 0x00404000, 0x20004010, 0x00000010, 0x20400010, 0x20400010, 0x00000000, 0x00404010, 0x20404000, 0x00004010, 0x00404000, 0x20404000, 0x20000000, 0x20004000, 0x00000010, 0x20400010, 0x00404000, 0x20404010, 0x00400000, 0x00004010, 0x20000010, 0x00400000, 0x20004000, 0x20000000, 0x00004010, 0x20000010, 0x20404010, 0x00404000, 0x20400000, 0x00404010, 0x20404000, 0x00000000, 0x20400010, 0x00000010, 0x00004000, 0x20400000, 0x00404010, 0x00004000, 0x00400010, 0x20004010, 0x00000000, 0x20404000, 0x20000000, 0x00400010, 0x20004010L}, {0x00200000, 0x04200002, 0x04000802, 0x00000000, 0x00000800, 0x04000802, 0x00200802, 0x04200800, 0x04200802, 0x00200000, 0x00000000, 0x04000002, 0x00000002, 0x04000000, 0x04200002, 0x00000802, 0x04000800, 0x00200802, 0x00200002, 0x04000800, 0x04000002, 0x04200000, 0x04200800, 0x00200002, 0x04200000, 0x00000800, 0x00000802, 0x04200802, 0x00200800, 0x00000002, 0x04000000, 0x00200800, 0x04000000, 0x00200800, 0x00200000, 0x04000802, 0x04000802, 0x04200002, 0x04200002, 0x00000002, 0x00200002, 0x04000000, 0x04000800, 0x00200000, 0x04200800, 0x00000802, 0x00200802, 0x04200800, 0x00000802, 0x04000002, 0x04200802, 0x04200000, 0x00200800, 0x00000000, 0x00000002, 0x04200802, 0x00000000, 0x00200802, 0x04200000, 0x00000800, 0x04000002, 0x04000800, 0x00000800, 0x00200002L}, {0x10001040, 0x00001000, 0x00040000, 0x10041040, 0x10000000, 0x10001040, 0x00000040, 0x10000000, 0x00040040, 0x10040000, 0x10041040, 0x00041000, 0x10041000, 0x00041040, 0x00001000, 0x00000040, 0x10040000, 0x10000040, 0x10001000, 0x00001040, 0x00041000, 0x00040040, 0x10040040, 0x10041000, 0x00001040, 0x00000000, 0x00000000, 0x10040040, 0x10000040, 0x10001000, 0x00041040, 0x00040000, 0x00041040, 0x00040000, 0x10041000, 0x00001000, 0x00000040, 0x10040040, 0x00001000, 0x00041040, 0x10001000, 0x00000040, 0x10000040, 0x10040000, 0x10040040, 0x10000000, 0x00040000, 0x10001040, 0x00000000, 0x10041040, 0x00040040, 0x10000040, 0x10040000, 0x10001000, 0x10001040, 0x00000000, 0x10041040, 0x00041000, 0x00041000, 0x00001040, 0x00001040, 0x00040040, 0x10000000, 0x10041000L} }; #define f(R, K0246, K1357) (\ s0246 = R ^ K0246, \ s1357 = R ^ K1357, \ s0246 = rotl(s0246, 28), \ SPboxes[0] [(s0246 >> 24) & 0x3F] | \ SPboxes[1] [(s1357 >> 24) & 0x3F] | \ SPboxes[2] [(s0246 >> 16) & 0x3F] | \ SPboxes[3] [(s1357 >> 16) & 0x3F] | \ SPboxes[4] [(s0246 >> 8) & 0x3F] | \ SPboxes[5] [(s1357 >> 8) & 0x3F] | \ SPboxes[6] [(s0246 ) & 0x3F] | \ SPboxes[7] [(s1357 ) & 0x3F]) #define bitswap(L, R, n, mask) (\ swap = mask & ( (R >> n) ^ L ), \ R ^= swap << n, \ L ^= swap) /* Initial permutation */ #define IP(L, R) (\ bitswap(R, L, 4, 0x0F0F0F0F), \ bitswap(R, L, 16, 0x0000FFFF), \ bitswap(L, R, 2, 0x33333333), \ bitswap(L, R, 8, 0x00FF00FF), \ bitswap(R, L, 1, 0x55555555)) /* Final permutation */ #define FP(L, R) (\ bitswap(R, L, 1, 0x55555555), \ bitswap(L, R, 8, 0x00FF00FF), \ bitswap(L, R, 2, 0x33333333), \ bitswap(R, L, 16, 0x0000FFFF), \ bitswap(R, L, 4, 0x0F0F0F0F)) static void des_encipher(word32 * output, word32 L, word32 R, DESContext * sched) { word32 swap, s0246, s1357; IP(L, R); L = rotl(L, 1); R = rotl(R, 1); L ^= f(R, sched->k0246[0], sched->k1357[0]); R ^= f(L, sched->k0246[1], sched->k1357[1]); L ^= f(R, sched->k0246[2], sched->k1357[2]); R ^= f(L, sched->k0246[3], sched->k1357[3]); L ^= f(R, sched->k0246[4], sched->k1357[4]); R ^= f(L, sched->k0246[5], sched->k1357[5]); L ^= f(R, sched->k0246[6], sched->k1357[6]); R ^= f(L, sched->k0246[7], sched->k1357[7]); L ^= f(R, sched->k0246[8], sched->k1357[8]); R ^= f(L, sched->k0246[9], sched->k1357[9]); L ^= f(R, sched->k0246[10], sched->k1357[10]); R ^= f(L, sched->k0246[11], sched->k1357[11]); L ^= f(R, sched->k0246[12], sched->k1357[12]); R ^= f(L, sched->k0246[13], sched->k1357[13]); L ^= f(R, sched->k0246[14], sched->k1357[14]); R ^= f(L, sched->k0246[15], sched->k1357[15]); L = rotl(L, 31); R = rotl(R, 31); swap = L; L = R; R = swap; FP(L, R); output[0] = L; output[1] = R; } static void des_decipher(word32 * output, word32 L, word32 R, DESContext * sched) { word32 swap, s0246, s1357; IP(L, R); L = rotl(L, 1); R = rotl(R, 1); L ^= f(R, sched->k0246[15], sched->k1357[15]); R ^= f(L, sched->k0246[14], sched->k1357[14]); L ^= f(R, sched->k0246[13], sched->k1357[13]); R ^= f(L, sched->k0246[12], sched->k1357[12]); L ^= f(R, sched->k0246[11], sched->k1357[11]); R ^= f(L, sched->k0246[10], sched->k1357[10]); L ^= f(R, sched->k0246[9], sched->k1357[9]); R ^= f(L, sched->k0246[8], sched->k1357[8]); L ^= f(R, sched->k0246[7], sched->k1357[7]); R ^= f(L, sched->k0246[6], sched->k1357[6]); L ^= f(R, sched->k0246[5], sched->k1357[5]); R ^= f(L, sched->k0246[4], sched->k1357[4]); L ^= f(R, sched->k0246[3], sched->k1357[3]); R ^= f(L, sched->k0246[2], sched->k1357[2]); L ^= f(R, sched->k0246[1], sched->k1357[1]); R ^= f(L, sched->k0246[0], sched->k1357[0]); L = rotl(L, 31); R = rotl(R, 31); swap = L; L = R; R = swap; FP(L, R); output[0] = L; output[1] = R; } /* Functions called by dyncrypt */ void des_set_key(des_context *ctx, CHAR8 key) { DESContext *sched = ctx->sched; word32 kL, kR; kL = GET_32BIT_MSB_FIRST(key); kR = GET_32BIT_MSB_FIRST(key+4); des_key_setup(kL, kR, &sched[0]); } void des_encrypt(des_context *ctx, CHAR8 input, CHAR8 output) { DESContext *sched = ctx->sched; word32 out[2], xL, xR; xL = GET_32BIT_MSB_FIRST(input); xR = GET_32BIT_MSB_FIRST(input+4); des_encipher(out, xL, xR, sched); PUT_32BIT_MSB_FIRST(output, out[0]); PUT_32BIT_MSB_FIRST(output+4, out[1]); } void des_decrypt(des_context *ctx, CHAR8 input, CHAR8 output) { DESContext *sched = ctx->sched; word32 out[2], xL, xR; xL = GET_32BIT_MSB_FIRST(input); xR = GET_32BIT_MSB_FIRST(input+4); des_decipher(out, xL, xR, sched); PUT_32BIT_MSB_FIRST(output, out[0]); PUT_32BIT_MSB_FIRST(output+4, out[1]); } void des3_set_2keys(des3_context *ctx, CHAR8 k1, CHAR8 k2) { DESContext *sched = ctx->sched; word32 kL, kR; kL = GET_32BIT_MSB_FIRST(k1); kR = GET_32BIT_MSB_FIRST(k1+4); des_key_setup(kL, kR, &sched[0]); des_key_setup(kL, kR, &sched[2]); kL = GET_32BIT_MSB_FIRST(k2); kR = GET_32BIT_MSB_FIRST(k2+4); des_key_setup(kL, kR, &sched[1]); } void des3_set_3keys(des3_context *ctx, CHAR8 k1, CHAR8 k2, CHAR8 k3) { DESContext *sched = ctx->sched; word32 kL, kR; kL = GET_32BIT_MSB_FIRST(k1); kR = GET_32BIT_MSB_FIRST(k1+4); des_key_setup(kL, kR, &sched[0]); kL = GET_32BIT_MSB_FIRST(k2); kR = GET_32BIT_MSB_FIRST(k2+4); des_key_setup(kL, kR, &sched[1]); kL = GET_32BIT_MSB_FIRST(k3); kR = GET_32BIT_MSB_FIRST(k3+4); des_key_setup(kL, kR, &sched[2]); } void des3_encrypt(des3_context *ctx, CHAR8 input, CHAR8 output) { DESContext *sched = ctx->sched; word32 out[2], xL, xR; xL = GET_32BIT_MSB_FIRST(input); xR = GET_32BIT_MSB_FIRST(input+4); des_encipher(out, xL, xR, sched); xL = out[0]; xR = out[1]; des_decipher(out, xL, xR, sched+1); xL = out[0]; xR = out[1]; des_encipher(out, xL, xR, sched+2); PUT_32BIT_MSB_FIRST(output, out[0]); PUT_32BIT_MSB_FIRST(output+4, out[1]); } void des3_decrypt(des3_context *ctx, CHAR8 input, CHAR8 output) { DESContext *sched = ctx->sched; word32 out[2], xL, xR; xL = GET_32BIT_MSB_FIRST(input); xR = GET_32BIT_MSB_FIRST(input+4); des_decipher(out, xL, xR, sched+2); xL = out[0]; xR = out[1]; des_encipher(out, xL, xR, sched+1); xL = out[0]; xR = out[1]; des_decipher(out, xL, xR, sched); PUT_32BIT_MSB_FIRST(output, out[0]); PUT_32BIT_MSB_FIRST(output+4, out[1]); } hercules-3.07/crypto/des.h000644 000765 000765 00000001436 11143760536 017221 0ustar00jmaynardjmaynard000000 000000 // $Id: des.h 4102 2006-12-08 09:43:35Z jj $ // // $Log$ #ifndef _DES_H #define _DES_H typedef u_int32_t word32; typedef struct { word32 k0246[16], k1357[16]; word32 iv0, iv1; } DESContext; typedef struct { DESContext sched[1]; } des_context; typedef struct { DESContext sched[3]; } des3_context; typedef BYTE CHAR8[8]; void des_set_key(des_context *ctx, CHAR8 key); void des_encrypt(des_context *ctx, CHAR8 input, CHAR8 output); void des_decrypt(des_context *ctx, CHAR8 input, CHAR8 output); void des3_set_2keys(des3_context *ctx, CHAR8 k1, CHAR8 k2); void des3_set_3keys(des3_context *ctx, CHAR8 k1, CHAR8 k2, CHAR8 k3); void des3_encrypt(des3_context *ctx, CHAR8 input, CHAR8 output); void des3_decrypt(des3_context *ctx, CHAR8 input, CHAR8 output); #endif /*_DES_H*/ hercules-3.07/crypto/dyncrypt.c000644 000765 000765 00000145175 11321734033 020315 0ustar00jmaynardjmaynard000000 000000 /*----------------------------------------------------------------------------*/ /* file: dyncrypt.c */ /* */ /* Implementation of the z/Architecture crypto instructions described in */ /* SA22-7832-04: z/Architecture Principles of Operation within the Hercules */ /* z/Architecture emulator. */ /* */ /* (c) Copyright Bernard van der Helm, 2003-2010 */ /* Noordwijkerhout, The Netherlands. */ /*----------------------------------------------------------------------------*/ // $Id: dyncrypt.c 5591 2010-01-05 07:07:35Z bernard $ #include "hstdinc.h" #ifndef _DYNCRYPT_C_ #define _DYNCRYPT_C_ #endif #ifndef _DYNCRYPT_DLL_ #define _DYNCRYPT_DLL_ #endif #include "hercules.h" #include "opcode.h" #include "inline.h" #include "aes.h" #include "des.h" #include "sha1.h" #include "sha256.h" #ifdef FEATURE_MESSAGE_SECURITY_ASSIST /*----------------------------------------------------------------------------*/ /* Debugging options */ /*----------------------------------------------------------------------------*/ #if 0 #define OPTION_KxMD_DEBUG #define OPTION_KM_DEBUG #define OPTION_KMAC_DEBUG #define OPTION_KMC_DEBUG #endif /*----------------------------------------------------------------------------*/ /* General Purpose Register 0 macro's (GR0) */ /*----------------------------------------------------------------------------*/ /* fc : Function code */ /* m : Modifier bit */ /*----------------------------------------------------------------------------*/ #define GR0_fc(regs) ((regs)->GR_L(0) & 0x0000007F) #define GR0_m(regs) (((regs)->GR_L(0) & 0x00000080) ? TRUE : FALSE) /*----------------------------------------------------------------------------*/ /* Bit strings for query functions */ /*----------------------------------------------------------------------------*/ #undef KxMD_BITS #undef KM_BITS #undef KMAC_BITS #undef KMC_BITS #ifdef FEATURE_MESSAGE_SECURITY_ASSIST_EXTENSION_2 #define KxMD_BITS { 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; #else #ifdef FEATURE_MESSAGE_SECURITY_ASSIST_EXTENSION_1 #define KxMD_BITS { 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; #else #define KxMD_BITS { 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; #endif #endif #ifdef FEATURE_MESSAGE_SECURITY_ASSIST_EXTENSION_2 #define KM_BITS { 0xf0, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; #else #ifdef FEATURE_MESSAGE_SECURITY_ASSIST_EXTENSION_1 #define KM_BITS { 0xf0, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; #else #define KM_BITS { 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; #endif #endif #define KMAC_BITS { 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; #ifdef FEATURE_MESSAGE_SECURITY_ASSIST_EXTENSION_2 #define KMC_BITS { 0xf0, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; #else #ifdef FEATURE_MESSAGE_SECURITY_ASSIST_EXTENSION_1 #define KMC_BITS { 0xf0, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; #else #define KMC_BITS { 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; #endif #endif /*----------------------------------------------------------------------------*/ /* Write bytes on one line */ /*----------------------------------------------------------------------------*/ #define LOGBYTE(s, v, x) \ { \ int i; \ \ logmsg(" " s " "); \ for(i = 0; i < (x); i++) \ logmsg("%02X", (v)[i]); \ logmsg(" | "); \ for(i = 0; i < (x); i++) \ { \ if(isprint(guest_to_host((v)[i]))) \ logmsg("%c", guest_to_host((v)[i])); \ else \ logmsg("."); \ } \ logmsg(" |\n"); \ } /*----------------------------------------------------------------------------*/ /* Write bytes on multiple lines */ /*----------------------------------------------------------------------------*/ #define LOGBYTE2(s, v, x, y) \ { \ int i; \ int j; \ \ logmsg(" " s "\n"); \ for(i = 0; i < (y); i++) \ { \ logmsg(" "); \ for(j = 0; j < (x); j++) \ logmsg("%02X", (v)[i * (x) + j]); \ logmsg(" | "); \ for(j = 0; j < (x); j++) \ { \ if(isprint(guest_to_host((v)[i * (x) + j]))) \ logmsg("%c", guest_to_host((v)[i * (x) + j])); \ else \ logmsg("."); \ } \ logmsg(" |\n"); \ } \ } /*----------------------------------------------------------------------------*/ /* CPU determined amount of data (processed in one go) */ /*----------------------------------------------------------------------------*/ #define PROCESS_MAX 16384 /*----------------------------------------------------------------------------*/ /* Used for printing debugging info */ /*----------------------------------------------------------------------------*/ #define TRUEFALSE(boolean) ((boolean) ? "True" : "False") #ifndef __SHA1_COMPILE__ #define __SHA1_COMPILE__ /*----------------------------------------------------------------------------*/ /* Get the chaining vector for output processing */ /*----------------------------------------------------------------------------*/ static void sha1_getcv(sha1_context *ctx, BYTE icv[20]) { int i, j; for(i = 0, j = 0; i < 5; i++) { icv[j++] = (ctx->state[i] & 0xff000000) >> 24; icv[j++] = (ctx->state[i] & 0x00ff0000) >> 16; icv[j++] = (ctx->state[i] & 0x0000ff00) >> 8; icv[j++] = (ctx->state[i] & 0x000000ff); } } /*----------------------------------------------------------------------------*/ /* Set the initial chaining value */ /*----------------------------------------------------------------------------*/ static void sha1_seticv(sha1_context *ctx, BYTE icv[20]) { int i, j; for(i = 0, j = 0; i < 5; i++) { ctx->state[i] = icv[j++] << 24; ctx->state[i] |= icv[j++] << 16; ctx->state[i] |= icv[j++] << 8; ctx->state[i] |= icv[j++]; } } #endif /* __SHA1_COMPILE__ */ #ifdef FEATURE_MESSAGE_SECURITY_ASSIST_EXTENSION_1 #ifndef __SHA256_COMPILE__ #define __SHA256_COMPILE__ /*----------------------------------------------------------------------------*/ /* Get the chaining vector for output processing */ /*----------------------------------------------------------------------------*/ static void sha256_getcv(sha256_context *ctx, BYTE icv[32]) { int i, j; for(i = 0, j = 0; i < 8; i++) { icv[j++] = (ctx->state[i] & 0xff000000) >> 24; icv[j++] = (ctx->state[i] & 0x00ff0000) >> 16; icv[j++] = (ctx->state[i] & 0x0000ff00) >> 8; icv[j++] = (ctx->state[i] & 0x000000ff); } } /*----------------------------------------------------------------------------*/ /* Set the initial chaining value */ /*----------------------------------------------------------------------------*/ static void sha256_seticv(sha256_context *ctx, BYTE icv[32]) { int i, j; for(i = 0, j = 0; i < 8; i++) { ctx->state[i] = icv[j++] << 24; ctx->state[i] |= icv[j++] << 16; ctx->state[i] |= icv[j++] << 8; ctx->state[i] |= icv[j++]; } } #endif /* __SHA256_COMPILE__ */ #endif /* FEATURE_MESSAGE_SECURITY_ASSIST_EXTENSION_1 */ #ifdef FEATURE_MESSAGE_SECURITY_ASSIST_EXTENSION_2 #ifndef __SHA512_COMPILE__ #define __SHA512_COMPILE__ /*----------------------------------------------------------------------------*/ /* Get the chaining vector for output processing */ /*----------------------------------------------------------------------------*/ static void sha512_getcv(sha512_context *ctx, BYTE icv[64]) { int i, j; for(i = 0, j = 0; i < 8; i++) { icv[j++] = (ctx->state[i] & 0xff00000000000000LL) >> 56; icv[j++] = (ctx->state[i] & 0x00ff000000000000LL) >> 48; icv[j++] = (ctx->state[i] & 0x0000ff0000000000LL) >> 40; icv[j++] = (ctx->state[i] & 0x000000ff00000000LL) >> 32; icv[j++] = (ctx->state[i] & 0x00000000ff000000LL) >> 24; icv[j++] = (ctx->state[i] & 0x0000000000ff0000LL) >> 16; icv[j++] = (ctx->state[i] & 0x000000000000ff00LL) >> 8; icv[j++] = (ctx->state[i] & 0x00000000000000ffLL); } } /*----------------------------------------------------------------------------*/ /* Set the initial chaining value */ /*----------------------------------------------------------------------------*/ static void sha512_seticv(sha512_context *ctx, BYTE icv[64]) { int i, j; for(i = 0, j = 0; i < 8; i++) { ctx->state[i] = (U64) icv[j++] << 56; ctx->state[i] |= (U64) icv[j++] << 48; ctx->state[i] |= (U64) icv[j++] << 40; ctx->state[i] |= (U64) icv[j++] << 32; ctx->state[i] |= (U64) icv[j++] << 24; ctx->state[i] |= (U64) icv[j++] << 16; ctx->state[i] |= (U64) icv[j++] << 8; ctx->state[i] |= (U64) icv[j++]; } } #endif /* __SHA512_COMPILE__ */ #endif /* FEATURE_MESSAGE_SECURITY_ASSIST_EXTENSION_2 */ /*----------------------------------------------------------------------------*/ /* Needed functions from sha1.c and sha256.c. */ /* We do our own counting and padding, we only need the hashing. */ /*----------------------------------------------------------------------------*/ void sha1_process(sha1_context *ctx, BYTE data[64]); #ifdef FEATURE_MESSAGE_SECURITY_ASSIST_EXTENSION_1 void sha256_process(sha256_context *ctx, BYTE data[64]); #endif #ifdef FEATURE_MESSAGE_SECURITY_ASSIST_EXTENSION_2 void sha512_process(sha512_context *ctx, BYTE data[128]); #endif /*----------------------------------------------------------------------------*/ /* B93E Compute intermediate message digest (KIMD) FC 1, 2 and 3 */ /*----------------------------------------------------------------------------*/ static void ARCH_DEP(kimd_sha)(int r1, int r2, REGS *regs, int klmd) { sha1_context sha1_ctx; #ifdef FEATURE_MESSAGE_SECURITY_ASSIST_EXTENSION_1 sha256_context sha256_ctx; #endif #ifdef FEATURE_MESSAGE_SECURITY_ASSIST_EXTENSION_2 sha512_context sha512_ctx; #endif int crypted; int fc; BYTE message_block[128]; int message_blocklen = 0; BYTE parameter_block[64]; int parameter_blocklen = 0; UNREFERENCED(r1); /* Initialize values */ fc = GR0_fc(regs); switch(fc) { case 1: /* sha-1 */ message_blocklen = 64; parameter_blocklen = 20; break; #ifdef FEATURE_MESSAGE_SECURITY_ASSIST_EXTENSION_1 case 2: /* sha-256 */ message_blocklen = 64; parameter_blocklen = 32; break; #endif #ifdef FEATURE_MESSAGE_SECURITY_ASSIST_EXTENSION_2 case 3: /* sha-512 */ message_blocklen = 128; parameter_blocklen = 64; #endif } /* Check special conditions */ if(unlikely(!klmd && (GR_A(r2 + 1, regs) % message_blocklen))) ARCH_DEP(program_interrupt)(regs, PGM_SPECIFICATION_EXCEPTION); /* Return with cc 0 on zero length */ if(unlikely(!GR_A(r2 + 1, regs))) { regs->psw.cc = 0; return; } /* Test writeability output chaining value */ ARCH_DEP(validate_operand)(GR_A(1, regs), 1, parameter_blocklen - 1, ACCTYPE_WRITE, regs); /* Fetch the parameter block */ ARCH_DEP(vfetchc)(parameter_block, parameter_blocklen - 1, GR_A(1, regs), 1, regs); #ifdef OPTION_KxMD_DEBUG if(parameter_blocklen > 32) { LOGBYTE2("icv :", parameter_block, 16, parameter_blocklen / 16); } else { LOGBYTE("icv :", parameter_block, parameter_blocklen); } #endif /* Set initial chaining value */ switch(fc) { case 1: /* sha-1 */ sha1_seticv(&sha1_ctx, parameter_block); break; #ifdef FEATURE_MESSAGE_SECURITY_ASSIST_EXTENSION_1 case 2: /* sha-256 */ sha256_seticv(&sha256_ctx, parameter_block); break; #endif #ifdef FEATURE_MESSAGE_SECURITY_ASSIST_EXTENSION_2 case 3: /* sha-512 */ sha512_seticv(&sha512_ctx, parameter_block); break; #endif } /* Try to process the CPU-determined amount of data */ for(crypted = 0; crypted < PROCESS_MAX; crypted += message_blocklen) { /* Fetch and process a block of data */ ARCH_DEP(vfetchc)(message_block, message_blocklen - 1, GR_A(r2, regs), r2, regs); #ifdef OPTION_KxMD_DEBUG LOGBYTE2("input :", message_block, 16, message_blocklen / 16); #endif switch(fc) { case 1: /* sha-1 */ sha1_process(&sha1_ctx, message_block); sha1_getcv(&sha1_ctx, parameter_block); break; #ifdef FEATURE_MESSAGE_SECURITY_ASSIST_EXTENSION_1 case 2: /* sha-256 */ sha256_process(&sha256_ctx, message_block); sha256_getcv(&sha256_ctx, parameter_block); break; #endif #ifdef FEATURE_MESSAGE_SECURITY_ASSIST_EXTENSION_2 case 3: /* sha-512 */ sha512_process(&sha512_ctx, message_block); sha512_getcv(&sha512_ctx, parameter_block); break; #endif } /* Store the output chaining value */ ARCH_DEP(vstorec)(parameter_block, parameter_blocklen - 1, GR_A(1, regs), 1, regs); #ifdef OPTION_KxMD_DEBUG if(parameter_blocklen > 32) { LOGBYTE2("ocv :", parameter_block, 16, parameter_blocklen / 16); } else { LOGBYTE("ocv :", parameter_block, parameter_blocklen); } #endif /* Update the registers */ SET_GR_A(r2, regs, GR_A(r2, regs) + message_blocklen); SET_GR_A(r2 + 1, regs, GR_A(r2 + 1, regs) - message_blocklen); #ifdef OPTION_KxMD_DEBUG logmsg(" GR%02d : " F_GREG "\n", r2, (regs)->GR(r2)); logmsg(" GR%02d : " F_GREG "\n", r2 + 1, (regs)->GR(r2 + 1)); #endif /* check for end of data */ if(unlikely(GR_A(r2 + 1, regs) < 64)) { if(unlikely(klmd)) return; regs->psw.cc = 0; return; } } /* CPU-determined amount of data processed */ regs->psw.cc = 3; } /*----------------------------------------------------------------------------*/ /* B93F Compute last message digest (KLMD) FC 1, 2 and 3 */ /*----------------------------------------------------------------------------*/ static void ARCH_DEP(klmd_sha)(int r1, int r2, REGS *regs) { sha1_context sha1_ctx; #ifdef FEATURE_MESSAGE_SECURITY_ASSIST_EXTENSION_1 sha256_context sha256_ctx; #endif #ifdef FEATURE_MESSAGE_SECURITY_ASSIST_EXTENSION_2 sha512_context sha512_ctx; #endif int fc; int i; int mbllen = 0; BYTE message_block[128]; int message_blocklen = 0; BYTE parameter_block[80]; int parameter_blocklen = 0; UNREFERENCED(r1); /* Initialize values */ fc = GR0_fc(regs); switch(fc) { case 1: /* sha-1 */ mbllen = 8; message_blocklen = 64; parameter_blocklen = 20; break; #ifdef FEATURE_MESSAGE_SECURITY_ASSIST_EXTENSION_1 case 2: /* sha-256 */ mbllen = 8; message_blocklen = 64; parameter_blocklen = 32; break; #endif #ifdef FEATURE_MESSAGE_SECURITY_ASSIST_EXTENSION_2 case 3: /* sha-512 */ mbllen = 16; message_blocklen = 128; parameter_blocklen = 64; #endif } /* Process intermediate message blocks */ if(unlikely(GR_A(r2 + 1, regs) >= (unsigned) message_blocklen)) { ARCH_DEP(kimd_sha)(r1, r2, regs, 1); if(regs->psw.cc == 3) return; } /* Test writeability output chaining value */ ARCH_DEP(validate_operand)(GR_A(1, regs), 1, parameter_blocklen - 1, ACCTYPE_WRITE, regs); /* Fetch the parameter block */ ARCH_DEP(vfetchc)(parameter_block, parameter_blocklen + mbllen - 1, GR_A(1, regs), 1, regs); #ifdef OPTION_KxMD_DEBUG if(parameter_blocklen > 32) { LOGBYTE2("icv :", parameter_block, 16, parameter_blocklen / 16); } else { LOGBYTE("icv :", parameter_block, parameter_blocklen); } LOGBYTE("mbl :", ¶meter_block[parameter_blocklen], mbllen); #endif /* Set initial chaining value */ switch(fc) { case 1: /* sha-1 */ sha1_seticv(&sha1_ctx, parameter_block); break; #ifdef FEATURE_MESSAGE_SECURITY_ASSIST_EXTENSION_1 case 2: /* sha-256 */ sha256_seticv(&sha256_ctx, parameter_block); break; #endif #ifdef FEATURE_MESSAGE_SECURITY_ASSIST_EXTENSION_2 case 3: /* sha-512 */ sha512_seticv(&sha512_ctx, parameter_block); break; #endif } /* Fetch and process possible last block of data */ if(likely(GR_A(r2 + 1, regs))) { ARCH_DEP(vfetchc)(message_block, GR_A(r2 + 1, regs) - 1, GR_A(r2, regs), r2, regs); #ifdef OPTION_KxMD_DEBUG if(GR_A(r2 + 1, regs) > 32) { LOGBYTE("input :", message_block, 32); LOGBYTE(" ", &message_block[32], (int) GR_A(r2 + 1, regs) - 32); } else LOGBYTE("input :", message_block, (int) GR_A(r2 + 1, regs)); #endif } /* Do the padding */ i = GR_A(r2 + 1, regs); if(unlikely(i >= (message_blocklen - mbllen))) { message_block[i++] = 0x80; while(i < message_blocklen) message_block[i++] = 0x00; switch(fc) { case 1: /* sha-1 */ sha1_process(&sha1_ctx, message_block); break; #ifdef FEATURE_MESSAGE_SECURITY_ASSIST_EXTENSION_1 case 2: /* sha-256 */ sha256_process(&sha256_ctx, message_block); break; #endif #ifdef FEATURE_MESSAGE_SECURITY_ASSIST_EXTENSION_2 case 3: /* sha-512 */ sha512_process(&sha512_ctx, message_block); break; #endif } for(i = 0; i < message_blocklen - mbllen; i++) message_block[i] = 0x00; } else { message_block[i++] = 0x80; while(i < message_blocklen - mbllen) message_block[i++] = 0x00; } /* Set the message bit length */ memcpy(&message_block[message_blocklen - mbllen], ¶meter_block[parameter_blocklen], mbllen); /* Calculate and store the message digest */ switch(fc) { case 1: /* sha-1 */ sha1_process(&sha1_ctx, message_block); sha1_getcv(&sha1_ctx, parameter_block); break; #ifdef FEATURE_MESSAGE_SECURITY_ASSIST_EXTENSION_1 case 2: /* sha-256 */ sha256_process(&sha256_ctx, message_block); sha256_getcv(&sha256_ctx, parameter_block); break; #endif #ifdef FEATURE_MESSAGE_SECURITY_ASSIST_EXTENSION_2 case 3: /* sha-512 */ sha512_process(&sha512_ctx, message_block); sha512_getcv(&sha512_ctx, parameter_block); break; #endif } ARCH_DEP(vstorec)(parameter_block, parameter_blocklen - 1, GR_A(1, regs), 1, regs); #ifdef OPTION_KxMD_DEBUG if(parameter_blocklen > 32) { LOGBYTE2("md :", parameter_block, 16, parameter_blocklen / 16); } else { LOGBYTE("md :", parameter_block, parameter_blocklen); } #endif /* Update registers */ SET_GR_A(r2, regs, GR_A(r2, regs) + GR_A(r2 + 1, regs)); SET_GR_A(r2 + 1, regs, 0); #ifdef OPTION_KxMD_DEBUG logmsg(" GR%02d : " F_GREG "\n", r2, (regs)->GR(r2)); logmsg(" GR%02d : " F_GREG "\n", r2 + 1, (regs)->GR(r2 + 1)); #endif /* Set condition code */ regs->psw.cc = 0; } /*----------------------------------------------------------------------------*/ /* B92E Cipher message (KM) FC 1, 2 and 3 */ /*----------------------------------------------------------------------------*/ static void ARCH_DEP(km_dea)(int r1, int r2, REGS *regs) { des_context context; des3_context des3_ctx; int crypted; int fc; BYTE message_block[8]; int modifier_bit; BYTE parameter_block[24]; int parameter_blocklen; int r1_is_not_r2; /* Check special conditions */ if(unlikely(GR_A(r2 + 1, regs) % 8)) ARCH_DEP(program_interrupt)(regs, PGM_SPECIFICATION_EXCEPTION); /* Return with cc 0 on zero length */ if(unlikely(!GR_A(r2 + 1, regs))) { regs->psw.cc = 0; return; } /* Initialize values */ fc = GR0_fc(regs); parameter_blocklen = fc * 8; /* Fetch the parameter block */ ARCH_DEP(vfetchc)(parameter_block, parameter_blocklen - 1, GR_A(1, regs), 1, regs); #ifdef OPTION_KM_DEBUG switch(fc) { case 1: /* dea */ LOGBYTE("k :", parameter_block, 8); break; case 2: /* tdea-128 */ LOGBYTE("k1 :", parameter_block, 8); LOGBYTE("k2 :", ¶meter_block[8], 8); break; case 3: /* tdea-192 */ LOGBYTE("k1 :", parameter_block, 8); LOGBYTE("k2 :", ¶meter_block[8], 8); LOGBYTE("k3 :", ¶meter_block[16], 8); break; } #endif /* Set the cryptographic key */ switch(fc) { case 1: /* dea */ des_set_key(&context, parameter_block); break; case 2: /* tdea-128 */ des3_set_2keys(&des3_ctx, parameter_block, ¶meter_block[8]); break; case 3: /* tdea-192 */ des3_set_3keys(&des3_ctx, parameter_block, ¶meter_block[8], ¶meter_block[16]); break; } /* Try to process the CPU-determined amount of data */ modifier_bit = GR0_m(regs); r1_is_not_r2 = r1 != r2; for(crypted = 0; crypted < PROCESS_MAX; crypted += 8) { /* Fetch a block of data */ ARCH_DEP(vfetchc)(message_block, 7, GR_A(r2, regs), r2, regs); #ifdef OPTION_KM_DEBUG LOGBYTE("input :", message_block, 8); #endif /* Do the job */ switch(fc) { case 1: /* dea */ if(modifier_bit) des_decrypt(&context, message_block, message_block); else des_encrypt(&context, message_block, message_block); break; case 2: /* tdea-128 */ case 3: /* tdea-192 */ if(modifier_bit) des3_decrypt(&des3_ctx, message_block, message_block); else des3_encrypt(&des3_ctx, message_block, message_block); break; } /* Store the output */ ARCH_DEP(vstorec)(message_block, 7, GR_A(r1, regs), r1, regs); #ifdef OPTION_KM_DEBUG LOGBYTE("output:", message_block, 8); #endif /* Update the registers */ SET_GR_A(r1, regs, GR_A(r1, regs) + 8); if(likely(r1_is_not_r2)) SET_GR_A(r2, regs, GR_A(r2, regs) + 8); SET_GR_A(r2 + 1, regs, GR_A(r2 + 1, regs) - 8); #ifdef OPTION_KM_DEBUG logmsg(" GR%02d : " F_GREG "\n", r1, (regs)->GR(r1)); logmsg(" GR%02d : " F_GREG "\n", r2, (regs)->GR(r2)); logmsg(" GR%02d : " F_GREG "\n", r2 + 1, (regs)->GR(r2 + 1)); #endif /* check for end of data */ if(unlikely(!GR_A(r2 + 1, regs))) { regs->psw.cc = 0; return; } } /* CPU-determined amount of data processed */ regs->psw.cc = 3; } #ifdef FEATURE_MESSAGE_SECURITY_ASSIST_EXTENSION_1 /*----------------------------------------------------------------------------*/ /* B92E Cipher message (KM) FC 18, 19 and 20 */ /*----------------------------------------------------------------------------*/ static void ARCH_DEP(km_aes)(int r1, int r2, REGS *regs) { aes_context context; int crypted; int fc; BYTE message_block[16]; int modifier_bit; BYTE parameter_block[16]; int parameter_blocklen; int r1_is_not_r2; /* Check special conditions */ if(unlikely(GR_A(r2 + 1, regs) % 16)) ARCH_DEP(program_interrupt)(regs, PGM_SPECIFICATION_EXCEPTION); /* Return with cc 0 on zero length */ if(unlikely(!GR_A(r2 + 1, regs))) { regs->psw.cc = 0; return; } /* Initialize values */ fc = GR0_fc(regs) - 17; parameter_blocklen = fc * 8 + 8; /* Fetch the parameter block */ ARCH_DEP(vfetchc)(parameter_block, parameter_blocklen, GR_A(1, regs), 1, regs); #ifdef OPTION_KM_DEBUG LOGBYTE("k :", parameter_block, parameter_blocklen); #endif /* Set the cryptographic keys */ aes_set_key(&context, parameter_block, 64 * (fc + 1)); /* Try to process the CPU-determined amount of data */ modifier_bit = GR0_m(regs); r1_is_not_r2 = r1 != r2; for(crypted = 0; crypted < PROCESS_MAX; crypted += 16) { /* Fetch a block of data */ ARCH_DEP(vfetchc)(message_block, 15, GR_A(r2, regs), r2, regs); #ifdef OPTION_KM_DEBUG LOGBYTE("input :", message_block, 16); #endif /* Do the job */ if(modifier_bit) aes_decrypt(&context, message_block, message_block); else aes_encrypt(&context, message_block, message_block); /* Store the output */ ARCH_DEP(vstorec)(message_block, 15, GR_A(r1, regs), r1, regs); #ifdef OPTION_KM_DEBUG LOGBYTE("output:", message_block, 16); #endif /* Update the registers */ SET_GR_A(r1, regs, GR_A(r1, regs) + 16); if(likely(r1_is_not_r2)) SET_GR_A(r2, regs, GR_A(r2, regs) + 16); SET_GR_A(r2 + 1, regs, GR_A(r2 + 1, regs) - 16); #ifdef OPTION_KM_DEBUG logmsg(" GR%02d : " F_GREG "\n", r1, (regs)->GR(r1)); logmsg(" GR%02d : " F_GREG "\n", r2, (regs)->GR(r2)); logmsg(" GR%02d : " F_GREG "\n", r2 + 1, (regs)->GR(r2 + 1)); #endif /* check for end of data */ if(unlikely(!GR_A(r2 + 1, regs))) { regs->psw.cc = 0; return; } } /* CPU-determined amount of data processed */ regs->psw.cc = 3; } #endif /* FEATURE_MESSAGE_SECURITY_ASSIST_EXTENSION_1 */ /*----------------------------------------------------------------------------*/ /* B91E KMAC - Compute message authentication code [RRE] */ /*----------------------------------------------------------------------------*/ DEF_INST(compute_message_authentication_code_d) { des_context context1; des_context context2; des_context context3; int crypted; int fc; int i; BYTE message_block[8]; BYTE parameter_block[32]; int parameter_blocklen; int r1; int r2; RRE(inst, regs, r1, r2); #ifdef OPTION_KMAC_DEBUG logmsg("KMAC: compute message authentication code\n"); logmsg(" r2 : GR%02d\n", r2); logmsg(" address : " F_VADR "\n", regs->GR(r2)); logmsg(" length : " F_GREG "\n", regs->GR(r2 + 1)); logmsg(" GR00 : " F_GREG "\n", regs->GR(0)); logmsg(" bit 56 : %s\n", TRUEFALSE(GR0_m(regs))); logmsg(" fc : %d\n", GR0_fc(regs)); logmsg(" GR01 : " F_GREG "\n", regs->GR(1)); #endif UNREFERENCED(r1); /* Initialize values */ fc = GR0_fc(regs); parameter_blocklen = fc * 8 + 8; /* Check special conditions */ if(unlikely(!r2 || r2 & 0x01 || GR0_m(regs))) ARCH_DEP(program_interrupt)(regs, PGM_SPECIFICATION_EXCEPTION); /* Check for query function */ if(unlikely(!fc)) { BYTE parameter_block[16] = KMAC_BITS; /* Store the parameter block */ ARCH_DEP(vstorec)(parameter_block, 15, GR_A(1, regs), 1, regs); /* Set condition code 0 */ regs->psw.cc = 0; return; } /* Check special conditions */ if(unlikely(GR_A(r2 + 1, regs) % 8)) ARCH_DEP(program_interrupt)(regs, PGM_SPECIFICATION_EXCEPTION); /* Return with cc 0 on zero length */ if(unlikely(!GR_A(r2 + 1, regs))) { regs->psw.cc = 0; return; } /* Test writeability output chaining value */ ARCH_DEP(validate_operand)(GR_A(1, regs), 1, 7, ACCTYPE_WRITE, regs); /* Fetch the parameter block */ ARCH_DEP(vfetchc)(parameter_block, parameter_blocklen - 1, GR_A(1, regs), 1, regs); #ifdef OPTION_KMAC_DEBUG LOGBYTE("icv :", parameter_block, 8); switch(fc) { case 1: /* dea */ LOGBYTE("k1 :", ¶meter_block[8], 8); break; case 2: /* tdea-128 */ LOGBYTE("k1 :", ¶meter_block[8], 8); LOGBYTE("k2 :", ¶meter_block[16], 8); break; case 3: /* tdea-192 */ LOGBYTE("k1 :", ¶meter_block[8], 8); LOGBYTE("k2 :", ¶meter_block[16], 8); LOGBYTE("k3 :", ¶meter_block[24], 8); break; } #endif /* Set the cryptographic key */ switch(fc) { case 1: /* dea */ des_set_key(&context1, ¶meter_block[8]); break; case 2: /* tdea-128 */ des_set_key(&context1, ¶meter_block[8]); des_set_key(&context2, ¶meter_block[16]); break; case 3: /* tdea-192 */ des_set_key(&context1, ¶meter_block[8]); des_set_key(&context2, ¶meter_block[16]); des_set_key(&context3, ¶meter_block[24]); break; } /* Try to process the CPU-determined amount of data */ for(crypted = 0; crypted < PROCESS_MAX; crypted += 8) { /* Fetch a block of data */ ARCH_DEP(vfetchc)(message_block, 7, GR_A(r2, regs), r2, regs); #ifdef OPTION_KMAC_DEBUG LOGBYTE("input :", message_block, 8); #endif /* XOR the message with chaining value */ for(i = 0; i < 8; i++) message_block[i] ^= parameter_block[i]; /* Calculate the output chaining value */ switch(fc) { case 1: /* dea */ des_encrypt(&context1, message_block, parameter_block); break; case 2: /* tdea-128 */ des_encrypt(&context1, message_block, parameter_block); des_decrypt(&context2, parameter_block, parameter_block); des_encrypt(&context1, parameter_block, parameter_block); break; case 3: /* tdea-192 */ des_encrypt(&context1, message_block, parameter_block); des_decrypt(&context2, parameter_block, parameter_block); des_encrypt(&context3, parameter_block, parameter_block); break; } /* Store the output chaining value */ ARCH_DEP(vstorec)(parameter_block, 7, GR_A(1, regs), 1, regs); #ifdef OPTION_KMAC_DEBUG LOGBYTE("ocv :", parameter_block, 8); #endif /* Update the registers */ SET_GR_A(r2, regs, GR_A(r2, regs) + 8); SET_GR_A(r2 + 1, regs, GR_A(r2 + 1, regs) - 8); #ifdef OPTION_KMAC_DEBUG logmsg(" GR%02d : " F_GREG "\n", r2, (regs)->GR(r2)); logmsg(" GR%02d : " F_GREG "\n", r2 + 1, (regs)->GR(r2 + 1)); #endif /* check for end of data */ if(unlikely(!GR_A(r2 + 1, regs))) { regs->psw.cc = 0; return; } } /* CPU-determined amount of data processed */ regs->psw.cc = 3; } /*----------------------------------------------------------------------------*/ /* B92F Cipher message with chaining (KMC) FC 1, 2 and 3 */ /*----------------------------------------------------------------------------*/ static void ARCH_DEP(kmc_dea)(int r1, int r2, REGS *regs) { des_context context1; des_context context2; des_context context3; int crypted; int fc; int i; BYTE message_block[8]; int modifier_bit; BYTE ocv[8]; BYTE parameter_block[16]; int parameter_blocklen; int r1_is_not_r2; #ifdef OPTION_KMC_DEBUG logmsg(" KMC: function 1: dea\n"); #endif /* Check special conditions */ if(unlikely(GR_A(r2 + 1, regs) % 8)) ARCH_DEP(program_interrupt)(regs, PGM_SPECIFICATION_EXCEPTION); /* Return with cc 0 on zero length */ if(unlikely(!GR_A(r2 + 1, regs))) { regs->psw.cc = 0; return; } /* Initialize values */ fc = GR0_fc(regs); parameter_blocklen = fc * 8 + 8; /* Test writeability output chaining value */ ARCH_DEP(validate_operand)(GR_A(1, regs), 1, 7, ACCTYPE_WRITE, regs); /* Fetch the parameter block */ ARCH_DEP(vfetchc)(parameter_block, parameter_blocklen - 1, GR_A(1, regs), 1, regs); #ifdef OPTION_KMC_DEBUG switch(fc) { case 1: /* dea */ LOGBYTE("icv :", parameter_block, 8); LOGBYTE("k :", ¶meter_block[8], 8); break; case 2: /* tdea-128 */ LOGBYTE("icv :", parameter_block, 8); LOGBYTE("k1 :", ¶meter_block[8], 8); LOGBYTE("k2 :", ¶meter_block[16], 8); break; case 3: /* tdea-192 */ LOGBYTE("icv :", parameter_block, 8); LOGBYTE("k1 :", ¶meter_block[8], 8); LOGBYTE("k2 :", ¶meter_block[16], 8); LOGBYTE("k3 :", ¶meter_block[24], 8); break; } #endif /* Set the cryptographic key */ switch(fc) { case 1: /* dea */ des_set_key(&context1, ¶meter_block[8]); break; case 2: /* tdea-128 */ des_set_key(&context1, ¶meter_block[8]); des_set_key(&context2, ¶meter_block[16]); break; case 3: /* tdea-192 */ des_set_key(&context1, ¶meter_block[8]); des_set_key(&context2, ¶meter_block[16]); des_set_key(&context3, ¶meter_block[24]); break; } /* Try to process the CPU-determined amount of data */ modifier_bit = GR0_m(regs); r1_is_not_r2 = r1 != r2; for(crypted = 0; crypted < PROCESS_MAX; crypted += 8) { /* Fetch a block of data */ ARCH_DEP(vfetchc)(message_block, 7, GR_A(r2, regs), r2, regs); #ifdef OPTION_KMC_DEBUG LOGBYTE("input :", message_block, 8); #endif /* Do the job */ switch(fc) { case 1: /* dea */ if(modifier_bit) { /* Save the ocv */ memcpy(ocv, message_block, 8); /* Decrypt and XOR */ des_decrypt(&context1, message_block, message_block); for(i = 0; i < 8; i++) message_block[i] ^= parameter_block[i]; } else { /* XOR and encrypt */ for(i = 0; i < 8; i++) message_block[i] ^= parameter_block[i]; des_encrypt(&context1, message_block, message_block); /* Save the ocv */ memcpy(ocv, message_block, 8); } break; case 2: /* tdea-128 */ if(modifier_bit) { /* Save the ocv */ memcpy(ocv, message_block, 8); /* Decrypt and XOR */ des_decrypt(&context1, message_block, message_block); des_encrypt(&context2, message_block, message_block); des_decrypt(&context1, message_block, message_block); for(i = 0; i < 8; i++) message_block[i] ^= parameter_block[i]; } else { /* XOR and encrypt */ for(i = 0 ; i < 8; i++) message_block[i] ^= parameter_block[i]; des_encrypt(&context1, message_block, message_block); des_decrypt(&context2, message_block, message_block); des_encrypt(&context1, message_block, message_block); /* Save the ocv */ memcpy(ocv, message_block, 8); } break; case 3: /* tdea-192 */ if(modifier_bit) { /* Save the ocv */ memcpy(ocv, message_block, 8); /* Decrypt and XOR */ des_decrypt(&context3, message_block, message_block); des_encrypt(&context2, message_block, message_block); des_decrypt(&context1, message_block, message_block); for(i = 0; i < 8; i++) message_block[i] ^= parameter_block[i]; } else { /* XOR and encrypt */ for(i = 0; i < 8; i++) message_block[i] ^= parameter_block[i]; des_encrypt(&context1, message_block, message_block); des_decrypt(&context2, message_block, message_block); des_encrypt(&context3, message_block, message_block); /* Save the ocv */ memcpy(ocv, message_block, 8); } break; } /* Store the output */ ARCH_DEP(vstorec)(message_block, 7, GR_A(r1, regs), r1, regs); #ifdef OPTION_KMC_DEBUG LOGBYTE("output:", message_block, 8); #endif /* Store the output chaining value */ ARCH_DEP(vstorec)(ocv, 7, GR_A(1, regs), 1, regs); #ifdef OPTION_KMC_DEBUG LOGBYTE("ocv :", ocv, 8); #endif /* Update the registers */ SET_GR_A(r1, regs, GR_A(r1, regs) + 8); if(likely(r1_is_not_r2)) SET_GR_A(r2, regs, GR_A(r2, regs) + 8); SET_GR_A(r2 + 1, regs, GR_A(r2 + 1, regs) - 8); #ifdef OPTION_KMC_DEBUG logmsg(" GR%02d : " F_GREG "\n", r1, (regs)->GR(r1)); logmsg(" GR%02d : " F_GREG "\n", r2, (regs)->GR(r2)); logmsg(" GR%02d : " F_GREG "\n", r2 + 1, (regs)->GR(r2 + 1)); #endif /* check for end of data */ if(unlikely(!GR_A(r2 + 1, regs))) { regs->psw.cc = 0; return; } /* Set cv for next 8 bytes */ memcpy(parameter_block, ocv, 8); } /* CPU-determined amount of data processed */ regs->psw.cc = 3; } #ifdef FEATURE_MESSAGE_SECURITY_ASSIST_EXTENSION_1 /*----------------------------------------------------------------------------*/ /* B92F Cipher message with chaining (KMC) FC 18, 19 and 20 */ /*----------------------------------------------------------------------------*/ static void ARCH_DEP(kmc_aes)(int r1, int r2, REGS *regs) { aes_context context; int crypted; int fc; int i; BYTE message_block[16]; int modifier_bit; BYTE ocv[16]; BYTE parameter_block[48]; int parameter_blocklen; int r1_is_not_r2; /* Check special conditions */ if(unlikely(GR_A(r2 + 1, regs) % 16)) ARCH_DEP(program_interrupt)(regs, PGM_SPECIFICATION_EXCEPTION); /* Return with cc 0 on zero length */ if(unlikely(!GR_A(r2 + 1, regs))) { regs->psw.cc = 0; return; } /* Initialize values */ fc = GR0_fc(regs) - 17; parameter_blocklen = fc * 8 + 24; /* Test writeability output chaining value */ ARCH_DEP(validate_operand)(GR_A(1, regs), 1, 15, ACCTYPE_WRITE, regs); /* Fetch the parameter block */ ARCH_DEP(vfetchc)(parameter_block, parameter_blocklen - 1, GR_A(1, regs), 1, regs); #ifdef OPTION_KMC_DEBUG LOGBYTE("icv :", parameter_block, 16); LOGBYTE("k :", ¶meter_block[16], parameter_blocklen - 16); #endif /* Set the cryptographic key */ aes_set_key(&context, ¶meter_block[16], 64 * (fc + 1)); /* Try to process the CPU-determined amount of data */ modifier_bit = GR0_m(regs); r1_is_not_r2 = r1 != r2; for(crypted = 0; crypted < PROCESS_MAX; crypted += 16) { /* Fetch a block of data */ ARCH_DEP(vfetchc)(message_block, 15, GR_A(r2, regs), r2, regs); #ifdef OPTION_KMC_DEBUG LOGBYTE("input :", message_block, 16); #endif /* Do the job */ if(modifier_bit) { /* Save the ovc */ memcpy(ocv, message_block, 16); /* Decrypt and XOR */ aes_decrypt(&context, message_block, message_block); for(i = 0; i < 16; i++) message_block[i] ^= parameter_block[i]; } else { /* XOR and encrypt */ for(i = 0; i < 16; i++) message_block[i] ^= parameter_block[i]; aes_encrypt(&context, message_block, message_block); /* Save the ovc */ memcpy(ocv, message_block, 16); } /* Store the output */ ARCH_DEP(vstorec)(message_block, 15, GR_A(r1, regs), r1, regs); #ifdef OPTION_KMC_DEBUG LOGBYTE("output:", message_block, 16); #endif /* Store the output chaining value */ ARCH_DEP(vstorec)(ocv, 15, GR_A(1, regs), 1, regs); #ifdef OPTION_KMC_DEBUG LOGBYTE("ocv :", ocv, 16); #endif /* Update the registers */ SET_GR_A(r1, regs, GR_A(r1, regs) + 16); if(likely(r1_is_not_r2)) SET_GR_A(r2, regs, GR_A(r2, regs) + 16); SET_GR_A(r2 + 1, regs, GR_A(r2 + 1, regs) - 16); #ifdef OPTION_KMC_DEBUG logmsg(" GR%02d : " F_GREG "\n", r1, (regs)->GR(r1)); logmsg(" GR%02d : " F_GREG "\n", r2, (regs)->GR(r2)); logmsg(" GR%02d : " F_GREG "\n", r2 + 1, (regs)->GR(r2 + 1)); #endif /* check for end of data */ if(unlikely(!GR_A(r2 + 1, regs))) { regs->psw.cc = 0; return; } /* Set cv for next 16 bytes */ memcpy(parameter_block, ocv, 16); } /* CPU-determined amount of data processed */ regs->psw.cc = 3; } #endif /* FEATURE_MESSAGE_SECURITY_ASSIST_EXTENSION_1 */ #ifdef FEATURE_MESSAGE_SECURITY_ASSIST_EXTENSION_1 /*----------------------------------------------------------------------------*/ /* B92F Cipher message with chaining (KMC) FC 67 */ /*----------------------------------------------------------------------------*/ static void ARCH_DEP(kmc_prng)(int r1, int r2, REGS *regs) { des_context context1; des_context context2; des_context context3; int crypted; int i; BYTE message_block[8]; BYTE parameter_block[32]; BYTE ocv[8]; BYTE tcv[8]; int r1_is_not_r2; #ifdef OPTION_KMC_DEBUG logmsg(" KMC: function 67: prng\n"); #endif /* Check special conditions */ if(unlikely(GR_A(r2 + 1, regs) % 8)) ARCH_DEP(program_interrupt)(regs, PGM_SPECIFICATION_EXCEPTION); /* Return with cc 0 on zero length */ if(unlikely(!GR_A(r2 + 1, regs))) { regs->psw.cc = 0; return; } /* Test writeability output chaining value */ ARCH_DEP(validate_operand)(GR_A(1, regs), 1, 7, ACCTYPE_WRITE, regs); /* Fetch the parameter block */ ARCH_DEP(vfetchc)(parameter_block, 31, GR_A(1, regs), 1, regs); #ifdef OPTION_KMC_DEBUG LOGBYTE("icv :", parameter_block, 8); LOGBYTE("k1 :", ¶meter_block[8], 8); LOGBYTE("k2 :", ¶meter_block[16], 8); LOGBYTE("k3 :", ¶meter_block[24], 8); #endif /* Set the cryptographic keys */ des_set_key(&context1, ¶meter_block[8]); des_set_key(&context2, ¶meter_block[16]); des_set_key(&context3, ¶meter_block[24]); /* Try to process the CPU-determined amount of data */ r1_is_not_r2 = r1 != r2; for(crypted = 0; crypted < PROCESS_MAX; crypted += 8) { /* Fetch a block of data */ ARCH_DEP(vfetchc)(message_block, 7, GR_A(r2, regs), r2, regs); #ifdef OPTION_KMC_DEBUG LOGBYTE("input :", message_block, 8); #endif /* Do the job */ des_encrypt(&context1, message_block, message_block); des_decrypt(&context2, message_block, message_block); des_encrypt(&context3, message_block, message_block); /* Save the temporary cv */ memcpy(tcv, message_block, 8); /* XOR */ for(i = 0; i < 8; i++) message_block[i] ^= parameter_block[i]; des_encrypt(&context1, message_block, message_block); des_decrypt(&context2, message_block, message_block); des_encrypt(&context3, message_block, message_block); /* Store the output */ ARCH_DEP(vstorec)(message_block, 7, GR_A(r1, regs), r1, regs); #ifdef OPTION_KMC_DEBUG LOGBYTE("output:", message_block, 8); #endif /* XOR */ for(i = 0; i < 8; i++) message_block[i] ^= tcv[i]; des_encrypt(&context1, message_block, message_block); des_decrypt(&context2, message_block, message_block); des_encrypt(&context3, message_block, message_block); /* Save the ocv */ memcpy(ocv, message_block, 8); /* Store the output chaining value */ ARCH_DEP(vstorec)(ocv, 7, GR_A(1, regs), 1, regs); #ifdef OPTION_KMC_DEBUG LOGBYTE("ocv :", ocv, 8); #endif /* Update the registers */ SET_GR_A(r1, regs, GR_A(r1, regs) + 8); if(likely(r1_is_not_r2)) SET_GR_A(r2, regs, GR_A(r2, regs) + 8); SET_GR_A(r2 + 1, regs, GR_A(r2 + 1, regs) - 8); #ifdef OPTION_KMC_DEBUG logmsg(" GR%02d : " F_GREG "\n", r1, (regs)->GR(r1)); logmsg(" GR%02d : " F_GREG "\n", r2, (regs)->GR(r2)); logmsg(" GR%02d : " F_GREG "\n", r2 + 1, (regs)->GR(r2 + 1)); #endif /* check for end of data */ if(unlikely(!GR_A(r2 + 1, regs))) { regs->psw.cc = 0; return; } /* Set cv for next 8 bytes */ memcpy(parameter_block, ocv, 8); } /* CPU-determined amount of data processed */ regs->psw.cc = 3; } #endif /* FEATURE_MESSAGE_SECURITY_ASSIST_EXTENSION_1 */ /*----------------------------------------------------------------------------*/ /* B93E/B93F KIMD/KLMD - Compute intermediate/last message digest [RRE] */ /*----------------------------------------------------------------------------*/ DEF_INST(compute_message_digest_d) { int r1; int r2; RRE(inst, regs, r1, r2); #ifdef OPTION_KxMD_DEBUG if(inst[1] == 0x3e) logmsg("KIMD: compute intermediate message digest\n"); else logmsg("KLMD: compute last message digest\n"); logmsg(" r1 : GR%02d\n", r1); logmsg(" address : " F_VADR "\n", regs->GR(r1)); logmsg(" r2 : GR%02d\n", r2); logmsg(" address : " F_VADR "\n", regs->GR(r2)); logmsg(" length : " F_GREG "\n", regs->GR(r2 + 1)); logmsg(" GR00 : " F_GREG "\n", regs->GR(0)); logmsg(" bit 56 : %s\n", TRUEFALSE(GR0_m(regs))); logmsg(" fc : %d\n", GR0_fc(regs)); logmsg(" GR01 : " F_GREG "\n", regs->GR(1)); #endif /* Check special conditions */ if(unlikely(!r2 || r2 & 0x01 || GR0_m(regs))) ARCH_DEP(program_interrupt)(regs, PGM_SPECIFICATION_EXCEPTION); switch(GR0_fc(regs)) { case 0: /* Query */ { BYTE parameter_block[16] = KxMD_BITS; /* Store the parameter block */ ARCH_DEP(vstorec)(parameter_block, 15, GR_A(1, regs), 1, regs); #ifdef OPTION_KxMD_DEBUG LOGBYTE("output:", parameter_block, 16); #endif /* Set condition code 0 */ regs->psw.cc = 0; return; } case 1: /* sha-1 */ if(likely(inst[1] == 0x3e)) ARCH_DEP(kimd_sha)(r1, r2, regs, 0); else ARCH_DEP(klmd_sha)(r1, r2, regs); break; #ifdef FEATURE_MESSAGE_SECURITY_ASSIST_EXTENSION_1 case 2: /* sha-256 */ if(likely(inst[1] == 0x3e)) ARCH_DEP(kimd_sha)(r1, r2, regs, 0); else ARCH_DEP(klmd_sha)(r1, r2, regs); break; #endif #ifdef FEATURE_MESSAGE_SECURITY_ASSIST_EXTENSION_2 case 3: /* sha-512 */ if(likely(inst[1] == 0x3e)) ARCH_DEP(kimd_sha)(r1, r2, regs, 0); else ARCH_DEP(klmd_sha)(r1, r2, regs); break; #endif default: ARCH_DEP(program_interrupt)(regs, PGM_SPECIFICATION_EXCEPTION); break; } } /*----------------------------------------------------------------------------*/ /* B92E KM - Cipher message [RRE] */ /*----------------------------------------------------------------------------*/ DEF_INST(cipher_message_d) { int r1; int r2; RRE(inst, regs, r1, r2); #ifdef OPTION_KM_DEBUG logmsg("KM: cipher message\n"); logmsg(" r1 : GR%02d\n", r1); logmsg(" address : " F_VADR "\n", regs->GR(r1)); logmsg(" r2 : GR%02d\n", r2); logmsg(" address : " F_VADR "\n", regs->GR(r2)); logmsg(" length : " F_GREG "\n", regs->GR(r2 + 1)); logmsg(" GR00 : " F_GREG "\n", regs->GR(0)); logmsg(" m : %s\n", TRUEFALSE(GR0_m(regs))); logmsg(" fc : %d\n", GR0_fc(regs)); logmsg(" GR01 : " F_GREG "\n", regs->GR(1)); #endif /* Check special conditions */ if(unlikely(!r1 || r1 & 0x01 || !r2 || r2 & 0x01)) ARCH_DEP(program_interrupt)(regs, PGM_SPECIFICATION_EXCEPTION); switch(GR0_fc(regs)) { case 0: /* Query */ { BYTE parameter_block[16] = KM_BITS; /* Store the parameter block */ ARCH_DEP(vstorec)(parameter_block, 15, GR_A(1, regs), 1, regs); #ifdef OPTION_KM_DEBUG LOGBYTE("output:", parameter_block, 16); #endif /* Set condition code 0 */ regs->psw.cc = 0; return; } case 1: /* dea */ case 2: /* tdea-128 */ case 3: /* tdea-192 */ ARCH_DEP(km_dea)(r1, r2, regs); break; #ifdef FEATURE_MESSAGE_SECURITY_ASSIST_EXTENSION_1 case 18: /* aes-128 */ ARCH_DEP(km_aes)(r1, r2, regs); break; #endif #ifdef FEATURE_MESSAGE_SECURITY_ASSIST_EXTENSION_2 case 19: /* aes-192 */ case 20: /* aes-256 */ ARCH_DEP(km_aes)(r1, r2, regs); break; #endif default: ARCH_DEP(program_interrupt)(regs, PGM_SPECIFICATION_EXCEPTION); break; } } /*----------------------------------------------------------------------------*/ /* B92F KMC - Cipher message with chaining [RRE] */ /*----------------------------------------------------------------------------*/ DEF_INST(cipher_message_with_chaining_d) { int r1; int r2; RRE(inst, regs, r1, r2); #ifdef OPTION_KMC_DEBUG logmsg("KMC: cipher message with chaining\n"); logmsg(" r1 : GR%02d\n", r1); logmsg(" address : " F_VADR "\n", regs->GR(r1)); logmsg(" r2 : GR%02d\n", r2); logmsg(" address : " F_VADR "\n", regs->GR(r2)); logmsg(" length : " F_GREG "\n", regs->GR(r2 + 1)); logmsg(" GR00 : " F_GREG "\n", regs->GR(0)); logmsg(" m : %s\n", TRUEFALSE(GR0_m(regs))); logmsg(" fc : %d\n", GR0_fc(regs)); logmsg(" GR01 : " F_GREG "\n", regs->GR(1)); #endif /* Check special conditions */ if(unlikely(!r1 || r1 & 0x01 || !r2 || r2 & 0x01)) ARCH_DEP(program_interrupt)(regs, PGM_SPECIFICATION_EXCEPTION); switch(GR0_fc(regs)) { case 0: /* Query */ { BYTE parameter_block[16] = KMC_BITS; /* Store the parameter block */ ARCH_DEP(vstorec)(parameter_block, 15, GR_A(1, regs), 1, regs); #ifdef OPTION_KMC_DEBUG LOGBYTE("output:", parameter_block, 16); #endif /* Set condition code 0 */ regs->psw.cc = 0; return; } case 1: /* dea */ case 2: /* tdea-128 */ case 3: /* tdea-192 */ ARCH_DEP(kmc_dea)(r1, r2, regs); break; #ifdef FEATURE_MESSAGE_SECURITY_ASSIST_EXTENSION_1 case 18: /* aes-128 */ ARCH_DEP(kmc_aes)(r1, r2, regs); break; #endif #ifdef FEATURE_MESSAGE_SECURITY_ASSIST_EXTENSION_2 case 19: /* aes-192 */ case 20: /* aes-256 */ ARCH_DEP(kmc_aes)(r1, r2, regs); break; #endif #ifdef FEATURE_MESSAGE_SECURITY_ASSIST_EXTENSION_1 case 67: /* prng */ ARCH_DEP(kmc_prng)(r1, r2, regs); break; #endif default: ARCH_DEP(program_interrupt)(regs, PGM_SPECIFICATION_EXCEPTION); break; } } #endif /*defined(FEATURE_MESSAGE_SECURITY_ASSIST)*/ #if !defined(_GEN_ARCH) #if defined(_ARCHMODE2) #define _GEN_ARCH _ARCHMODE2 #include "dyncrypt.c" #endif #if defined(_ARCHMODE3) #undef _GEN_ARCH #define _GEN_ARCH _ARCHMODE3 #include "dyncrypt.c" #endif HDL_DEPENDENCY_SECTION; { HDL_DEPENDENCY (HERCULES); HDL_DEPENDENCY (REGS); HDL_DEPENDENCY (DEVBLK); // HDL_DEPENDENCY (SYSBLK); // HDL_DEPENDENCY (WEBBLK); } END_DEPENDENCY_SECTION; HDL_REGISTER_SECTION; { #if defined(_390_FEATURE_MESSAGE_SECURITY_ASSIST) HDL_REGISTER(s390_cipher_message, s390_cipher_message_d); HDL_REGISTER(s390_cipher_message_with_chaining, s390_cipher_message_with_chaining_d); HDL_REGISTER(s390_compute_message_digest, s390_compute_message_digest_d); HDL_REGISTER(s390_compute_message_authentication_code, s390_compute_message_authentication_code_d); #endif /*defined(_390_FEATURE_MESSAGE_SECURITY_ASSIST)*/ #if defined(_900_FEATURE_MESSAGE_SECURITY_ASSIST) HDL_REGISTER(z900_cipher_message, z900_cipher_message_d); HDL_REGISTER(z900_cipher_message_with_chaining, z900_cipher_message_with_chaining_d); HDL_REGISTER(z900_compute_message_digest, z900_compute_message_digest_d); HDL_REGISTER(z900_compute_message_authentication_code, z900_compute_message_authentication_code_d); #endif /*defined(_900_FEATURE_MESSAGE_SECURITY_ASSIST)*/ logmsg("Crypto module loaded (c) Copyright Bernard van der Helm, 2003-2010\n"); logmsg(" Active: Message Security Assist\n"); #ifdef FEATURE_MESSAGE_SECURITY_ASSIST_EXTENSION_1 logmsg(" Message Security Assist Extension 1\n"); #endif #ifdef FEATURE_MESSAGE_SECURITY_ASSIST_EXTENSION_2 logmsg(" Message Security Assist Extension 2\n"); #endif } END_REGISTER_SECTION; #endif /*!defined(_GEN_ARCH)*/ hercules-3.07/crypto/Makefile.am000644 000765 000765 00000002570 11143760536 020331 0ustar00jmaynardjmaynard000000 000000 ## Process this file with automake to produce Makefile.in # # Makefile for Hercules S/370, ESA/390 and z/Architecture emulator # # $Id: Makefile.am 4102 2006-12-08 09:43:35Z jj $ # # $Log$ lns=@LN_S@ LDADD = @LTLIBINTL@ @LIBS@ ../libhercs.la ../libherc.la ../libhercu.la AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)\intl dyndev_SRC = dyncrypt.c sha1.c sha256.c des.c aes.c if BUILD_SHARED XSTATIC = else XSTATIC = -static endif if OPTION_DYNAMIC_LOAD DYNSRC = LTDL = ../ltdl.c DYNMOD_LD_FLAGS = -module \ -no-undefined \ $(XSTATIC) \ -export-dynamic \ -avoid-version DYNMOD_LD_ADD = $(LDADD) LIB_LD_FLAGS = -export-dynamic \ $(XSTATIC) \ -no-undefined \ -avoid-version else DYNSRC = $(dyndev_SRC) LTDL = DYNMOD_LD_FLAGS = DYNMOD_LD_ADD = LIB_LD_FLAGS = $(XSTATIC) \ -no-undefined \ -avoid-version endif HERCMODS = dyncrypt.la if OPTION_DYNAMIC_LOAD modexec_LTLIBRARIES = $(HERCMODS) endif dyncrypt_la_SOURCES = dyncrypt.c sha1.c sha256.c des.c aes.c dyncrypt_la_LDFLAGS = $(DYNMOD_LD_FLAGS) dyncrypt_la_LIBADD = $(DYNMOD_LD_ADD) noinst_HEADERS = sha1.h sha256.h des.h aes.h %.s: %.c $(COMPILE) -S $< hercules-3.07/crypto/Makefile.in000644 000765 000765 00000044114 11344713140 020332 0ustar00jmaynardjmaynard000000 000000 # Makefile.in generated by automake 1.9.6 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ # # Makefile for Hercules S/370, ESA/390 and z/Architecture emulator # # $Id: Makefile.am 4102 2006-12-08 09:43:35Z jj $ # # $Log$ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = .. am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd INSTALL = @INSTALL@ install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = crypto DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \ $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/autoconf/hercules.m4 \ $(top_srcdir)/autoconf/libtool.m4 \ $(top_srcdir)/autoconf/ltdl.m4 $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(SHELL) $(top_srcdir)/autoconf/mkinstalldirs CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; am__installdirs = "$(DESTDIR)$(modexecdir)" modexecLTLIBRARIES_INSTALL = $(INSTALL) LTLIBRARIES = $(modexec_LTLIBRARIES) am__DEPENDENCIES_1 = ../libhercs.la ../libherc.la ../libhercu.la @OPTION_DYNAMIC_LOAD_TRUE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) dyncrypt_la_DEPENDENCIES = $(am__DEPENDENCIES_2) am_dyncrypt_la_OBJECTS = dyncrypt.lo sha1.lo sha256.lo des.lo aes.lo dyncrypt_la_OBJECTS = $(am_dyncrypt_la_OBJECTS) @OPTION_DYNAMIC_LOAD_TRUE@am_dyncrypt_la_rpath = -rpath $(modexecdir) DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/autoconf/depcomp am__depfiles_maybe = depfiles COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ SOURCES = $(dyncrypt_la_SOURCES) DIST_SOURCES = $(dyncrypt_la_SOURCES) HEADERS = $(noinst_HEADERS) ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BUILD_FISHHANG_FALSE = @BUILD_FISHHANG_FALSE@ BUILD_FISHHANG_TRUE = @BUILD_FISHHANG_TRUE@ BUILD_FTHREADS_FALSE = @BUILD_FTHREADS_FALSE@ BUILD_FTHREADS_TRUE = @BUILD_FTHREADS_TRUE@ BUILD_HERCIFC_FALSE = @BUILD_HERCIFC_FALSE@ BUILD_HERCIFC_TRUE = @BUILD_HERCIFC_TRUE@ BUILD_SHARED_FALSE = @BUILD_SHARED_FALSE@ BUILD_SHARED_TRUE = @BUILD_SHARED_TRUE@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CONVENIENCE_LTDL_FALSE = @CONVENIENCE_LTDL_FALSE@ CONVENIENCE_LTDL_TRUE = @CONVENIENCE_LTDL_TRUE@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ ECHO = @ECHO@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ F77 = @F77@ FFLAGS = @FFLAGS@ GMSGFMT = @GMSGFMT@ GREP = @GREP@ HERCIFC_GROUPNAME = @HERCIFC_GROUPNAME@ HERCIFC_GROUPSET_FALSE = @HERCIFC_GROUPSET_FALSE@ HERCIFC_GROUPSET_TRUE = @HERCIFC_GROUPSET_TRUE@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_LTDL_FALSE = @INSTALL_LTDL_FALSE@ INSTALL_LTDL_TRUE = @INSTALL_LTDL_TRUE@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ LDFLAGS = @LDFLAGS@ LIBADD_DL = @LIBADD_DL@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBTOOL_DEPS = @LIBTOOL_DEPS@ LN_S = @LN_S@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@ MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@ MAKEINFO = @MAKEINFO@ MKINSTALLDIRS = @MKINSTALLDIRS@ MSGFMT = @MSGFMT@ MSGMERGE = @MSGMERGE@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPTION_DYNAMIC_LOAD_FALSE = @OPTION_DYNAMIC_LOAD_FALSE@ OPTION_DYNAMIC_LOAD_TRUE = @OPTION_DYNAMIC_LOAD_TRUE@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ POSUB = @POSUB@ RANLIB = @RANLIB@ SETUID_HERCIFC_FALSE = @SETUID_HERCIFC_FALSE@ SETUID_HERCIFC_TRUE = @SETUID_HERCIFC_TRUE@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ USE_DLLTOOL_FALSE = @USE_DLLTOOL_FALSE@ USE_DLLTOOL_TRUE = @USE_DLLTOOL_TRUE@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_F77 = @ac_ct_F77@ am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ modexecdir = @modexecdir@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ lns = @LN_S@ LDADD = @LTLIBINTL@ @LIBS@ ../libhercs.la ../libherc.la ../libhercu.la AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)\intl dyndev_SRC = dyncrypt.c sha1.c sha256.c des.c aes.c @BUILD_SHARED_FALSE@XSTATIC = -static @BUILD_SHARED_TRUE@XSTATIC = @OPTION_DYNAMIC_LOAD_FALSE@DYNSRC = $(dyndev_SRC) @OPTION_DYNAMIC_LOAD_TRUE@DYNSRC = @OPTION_DYNAMIC_LOAD_FALSE@LTDL = @OPTION_DYNAMIC_LOAD_TRUE@LTDL = ../ltdl.c @OPTION_DYNAMIC_LOAD_FALSE@DYNMOD_LD_FLAGS = @OPTION_DYNAMIC_LOAD_TRUE@DYNMOD_LD_FLAGS = -module \ @OPTION_DYNAMIC_LOAD_TRUE@ -no-undefined \ @OPTION_DYNAMIC_LOAD_TRUE@ $(XSTATIC) \ @OPTION_DYNAMIC_LOAD_TRUE@ -export-dynamic \ @OPTION_DYNAMIC_LOAD_TRUE@ -avoid-version @OPTION_DYNAMIC_LOAD_FALSE@DYNMOD_LD_ADD = @OPTION_DYNAMIC_LOAD_TRUE@DYNMOD_LD_ADD = $(LDADD) @OPTION_DYNAMIC_LOAD_FALSE@LIB_LD_FLAGS = $(XSTATIC) \ @OPTION_DYNAMIC_LOAD_FALSE@ -no-undefined \ @OPTION_DYNAMIC_LOAD_FALSE@ -avoid-version @OPTION_DYNAMIC_LOAD_TRUE@LIB_LD_FLAGS = -export-dynamic \ @OPTION_DYNAMIC_LOAD_TRUE@ $(XSTATIC) \ @OPTION_DYNAMIC_LOAD_TRUE@ -no-undefined \ @OPTION_DYNAMIC_LOAD_TRUE@ -avoid-version HERCMODS = dyncrypt.la @OPTION_DYNAMIC_LOAD_TRUE@modexec_LTLIBRARIES = $(HERCMODS) dyncrypt_la_SOURCES = dyncrypt.c sha1.c sha256.c des.c aes.c dyncrypt_la_LDFLAGS = $(DYNMOD_LD_FLAGS) dyncrypt_la_LIBADD = $(DYNMOD_LD_ADD) noinst_HEADERS = sha1.h sha256.h des.h aes.h all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ && exit 0; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu crypto/Makefile'; \ cd $(top_srcdir) && \ $(AUTOMAKE) --gnu crypto/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh install-modexecLTLIBRARIES: $(modexec_LTLIBRARIES) @$(NORMAL_INSTALL) test -z "$(modexecdir)" || $(mkdir_p) "$(DESTDIR)$(modexecdir)" @list='$(modexec_LTLIBRARIES)'; for p in $$list; do \ if test -f $$p; then \ f=$(am__strip_dir) \ echo " $(LIBTOOL) --mode=install $(modexecLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(modexecdir)/$$f'"; \ $(LIBTOOL) --mode=install $(modexecLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(modexecdir)/$$f"; \ else :; fi; \ done uninstall-modexecLTLIBRARIES: @$(NORMAL_UNINSTALL) @set -x; list='$(modexec_LTLIBRARIES)'; for p in $$list; do \ p=$(am__strip_dir) \ echo " $(LIBTOOL) --mode=uninstall rm -f '$(DESTDIR)$(modexecdir)/$$p'"; \ $(LIBTOOL) --mode=uninstall rm -f "$(DESTDIR)$(modexecdir)/$$p"; \ done clean-modexecLTLIBRARIES: -test -z "$(modexec_LTLIBRARIES)" || rm -f $(modexec_LTLIBRARIES) @list='$(modexec_LTLIBRARIES)'; for p in $$list; do \ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ test "$$dir" != "$$p" || dir=.; \ echo "rm -f \"$${dir}/so_locations\""; \ rm -f "$${dir}/so_locations"; \ done dyncrypt.la: $(dyncrypt_la_OBJECTS) $(dyncrypt_la_DEPENDENCIES) $(LINK) $(am_dyncrypt_la_rpath) $(dyncrypt_la_LDFLAGS) $(dyncrypt_la_OBJECTS) $(dyncrypt_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/aes.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/des.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dyncrypt.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sha1.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sha256.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ @am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c $< .c.obj: @am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \ @am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ if $(LTCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ @am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs distclean-libtool: -rm -f libtool uninstall-info-am: ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ mkid -fID $$unique tags: TAGS TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$tags $$unique; \ fi ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(CTAGS_ARGS)$$tags$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$tags $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && cd $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) $$here distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ list='$(DISTFILES)'; for file in $$list; do \ case $$file in \ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ esac; \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ if test "$$dir" != "$$file" && test "$$dir" != "."; then \ dir="/$$dir"; \ $(mkdir_p) "$(distdir)$$dir"; \ else \ dir=''; \ fi; \ if test -d $$d/$$file; then \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ fi; \ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) $(HEADERS) installdirs: for dir in "$(DESTDIR)$(modexecdir)"; do \ test -z "$$dir" || $(mkdir_p) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-modexecLTLIBRARIES \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-libtool distclean-tags dvi: dvi-am dvi-am: html: html-am info: info-am info-am: install-data-am: install-exec-am: install-modexecLTLIBRARIES install-info: install-info-am install-man: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-info-am uninstall-modexecLTLIBRARIES .PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ clean-libtool clean-modexecLTLIBRARIES ctags distclean \ distclean-compile distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-exec \ install-exec-am install-info install-info-am install-man \ install-modexecLTLIBRARIES install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags uninstall uninstall-am uninstall-info-am \ uninstall-modexecLTLIBRARIES %.s: %.c $(COMPILE) -S $< # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: hercules-3.07/crypto/sha1.c000644 000765 000765 00000014245 11143760536 017277 0ustar00jmaynardjmaynard000000 000000 /* $OpenBSD: sha1.c,v 1.5 2004/04/28 20:39:35 hshoexer Exp $ */ /* modified for use with dyncrypt */ // $Id: sha1.c 4102 2006-12-08 09:43:35Z jj $ /* * SHA-1 in C * By Steve Reid * 100% Public Domain * * Test Vectors (from FIPS PUB 180-1) * "abc" * A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D * "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" * 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 * A million repetitions of "a" * 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F */ /* #define SHA1HANDSOFF */ /* Copies data before messing with it. */ // $Log$ #include "hstdinc.h" #include "sha1.h" #define bcopy(_src,_dest,_len) memcpy(_dest,_src,_len) #define bzero(_dest,_len) memset(_dest,'\0',_len) #define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) /* blk0() and blk() perform the initial expand. */ /* I got the idea of expanding during the round function from SSLeay */ #ifndef WORDS_BIGENDIAN #define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \ |(rol(block->l[i],8)&0x00FF00FF)) #else #define blk0(i) block->l[i] #endif #define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \ ^block->l[(i+2)&15]^block->l[i&15],1)) /* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ #define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30); #define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30); #define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30); #define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30); #define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30); /* Hash a single 512-bit block. This is the core of the algorithm. */ void SHA1Transform(u_int32_t state[5], unsigned char buffer[SHA1_BLOCK_LENGTH]) { u_int32_t a, b, c, d, e; typedef union { unsigned char c[64]; u_int32_t l[16]; } CHAR64LONG16; CHAR64LONG16* block; #ifdef SHA1HANDSOFF static unsigned char workspace[SHA1_BLOCK_LENGTH]; block = (CHAR64LONG16 *)workspace; bcopy(buffer, block, SHA1_BLOCK_LENGTH); #else block = (CHAR64LONG16 *)buffer; #endif /* Copy context->state[] to working vars */ a = state[0]; b = state[1]; c = state[2]; d = state[3]; e = state[4]; /* 4 rounds of 20 operations each. Loop unrolled. */ R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); /* Add the working vars back into context.state[] */ state[0] += a; state[1] += b; state[2] += c; state[3] += d; state[4] += e; /* Wipe variables */ a = b = c = d = e = 0; } /* SHA1Init - Initialize new context */ void SHA1Init(SHA1_CTX *context) { /* SHA1 initialization constants */ context->count = 0; context->state[0] = 0x67452301; context->state[1] = 0xEFCDAB89; context->state[2] = 0x98BADCFE; context->state[3] = 0x10325476; context->state[4] = 0xC3D2E1F0; } /* Run your data through this. */ void SHA1Update(SHA1_CTX *context, unsigned char *data, unsigned int len) { unsigned int i; unsigned int j; j = (u_int32_t)((context->count >> 3) & 63); context->count += (len << 3); if ((j + len) > 63) { bcopy(data, &context->buffer[j], (i = 64 - j)); SHA1Transform(context->state, context->buffer); for ( ; i + 63 < len; i += 64) { SHA1Transform(context->state, &data[i]); } j = 0; } else i = 0; bcopy(&data[i], &context->buffer[j], len - i); } /* Add padding and return the message digest. */ void SHA1Final(unsigned char digest[SHA1_DIGEST_LENGTH], SHA1_CTX *context) { unsigned int i; unsigned char finalcount[8]; for (i = 0; i < 8; i++) { finalcount[i] = (unsigned char)((context->count >> ((7 - (i & 7)) * 8)) & 255); /* Endian independent */ } SHA1Update(context, (unsigned char *)"\200", 1); while ((context->count & 504) != 448) { SHA1Update(context, (unsigned char *)"\0", 1); } SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */ if (digest) for (i = 0; i < SHA1_DIGEST_LENGTH; i++) { digest[i] = (unsigned char)((context->state[i >> 2] >> ((3 - (i & 3)) * 8)) & 255); } #if 0 /* We want to use this for "keyfill" */ /* Wipe variables */ i = 0; bzero(context->buffer, 64); bzero(context->state, 20); bzero(context->count, 8); bzero(&finalcount, 8); #ifdef SHA1HANDSOFF /* make SHA1Transform overwrite it's own static vars */ SHA1Transform(context->state, context->buffer); #endif #endif } /* Hashing-only function called by dyncrypt */ void sha1_process(sha1_context *ctx, unsigned char data[64]) { SHA1Transform(ctx->state, data); } hercules-3.07/crypto/sha1.h000644 000765 000765 00000001557 11143760536 017306 0ustar00jmaynardjmaynard000000 000000 /* $OpenBSD: sha1.h,v 1.4 2004/04/28 20:39:35 hshoexer Exp $ */ /* modified for use with dyncrypt */ // $Id: sha1.h 4102 2006-12-08 09:43:35Z jj $ /* * SHA-1 in C * By Steve Reid * 100% Public Domain */ // $Log$ #ifndef _SHA1_H_ #define _SHA1_H_ #define SHA1_BLOCK_LENGTH 64 #define SHA1_DIGEST_LENGTH 20 typedef struct { u_int32_t state[5]; u_int64_t count; unsigned char buffer[SHA1_BLOCK_LENGTH]; } SHA1_CTX; void SHA1Init(SHA1_CTX * context); void SHA1Transform(u_int32_t state[5], unsigned char buffer[SHA1_BLOCK_LENGTH]); void SHA1Update(SHA1_CTX *context, unsigned char *data, unsigned int len); void SHA1Final(unsigned char digest[SHA1_DIGEST_LENGTH], SHA1_CTX *context); /* Context structure definition for dyncrypt */ typedef SHA1_CTX sha1_context; #endif /* _SHA1_H_ */ hercules-3.07/crypto/sha256.c000644 000765 000765 00000060325 11143760536 017453 0ustar00jmaynardjmaynard000000 000000 /* $OpenBSD: sha2.c,v 1.6 2004/05/03 02:57:36 millert Exp $ */ /* modified for use with dyncrypt */ // $Id: sha256.c 4593 2008-02-28 10:16:39Z rbowler $ /* * FILE: sha2.c * AUTHOR: Aaron D. Gifford * * Copyright (c) 2000-2001, Aaron D. Gifford * 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. * 3. Neither the name of the copyright holder nor the names of contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``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 CONTRIBUTOR(S) 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. * * $From: sha2.c,v 1.1 2001/11/08 00:01:51 adg Exp adg $ */ // $Log$ // Revision 1.9 2006/12/08 09:43:35 jj // Add CVS message log // #include "hstdinc.h" #if !defined(_HENGINE_DLL_) #define _HENGINE_DLL_ #endif #include "hercules.h" #include "opcode.h" /* For CSWAP macros */ #include "sha256.h" #define bcopy(_src,_dest,_len) memcpy(_dest,_src,_len) #define bzero(_dest,_len) memset(_dest,'\0',_len) /* * UNROLLED TRANSFORM LOOP NOTE: * You can define SHA2_UNROLL_TRANSFORM to use the unrolled transform * loop version for the hash transform rounds (defined using macros * later in this file). Either define on the command line, for example: * * cc -DSHA2_UNROLL_TRANSFORM -o sha2 sha2.c sha2prog.c * * or define below: * * #define SHA2_UNROLL_TRANSFORM * */ #define SHA2_UNROLL_TRANSFORM /*** SHA-256/384/512 Various Length Definitions ***********************/ /* NOTE: Most of these are in sha2.h */ #define SHA256_SHORT_BLOCK_LENGTH (SHA256_BLOCK_LENGTH - 8) #define SHA384_SHORT_BLOCK_LENGTH (SHA384_BLOCK_LENGTH - 16) #define SHA512_SHORT_BLOCK_LENGTH (SHA512_BLOCK_LENGTH - 16) /* * Macro for incrementally adding the unsigned 64-bit integer n to the * unsigned 128-bit integer (represented using a two-element array of * 64-bit words): */ #define ADDINC128(w,n) { \ (w)[0] += (u_int64_t)(n); \ if ((w)[0] < (n)) { \ (w)[1]++; \ } \ } /*** THE SIX LOGICAL FUNCTIONS ****************************************/ /* * Bit shifting and rotation (used by the six SHA-XYZ logical functions: * * NOTE: The naming of R and S appears backwards here (R is a SHIFT and * S is a ROTATION) because the SHA-256/384/512 description document * (see http://csrc.nist.gov/cryptval/shs/sha256-384-512.pdf) uses this * same "backwards" definition. */ /* Shift-right (used in SHA-256, SHA-384, and SHA-512): */ #define R(b,x) ((x) >> (b)) /* 32-bit Rotate-right (used in SHA-256): */ #define S32(b,x) (((x) >> (b)) | ((x) << (32 - (b)))) /* 64-bit Rotate-right (used in SHA-384 and SHA-512): */ #define S64(b,x) (((x) >> (b)) | ((x) << (64 - (b)))) /* Two of six logical functions used in SHA-256, SHA-384, and SHA-512: */ #define Ch(x,y,z) (((x) & (y)) ^ ((~(x)) & (z))) #define Maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) /* Four of six logical functions used in SHA-256: */ #define Sigma0_256(x) (S32(2, (x)) ^ S32(13, (x)) ^ S32(22, (x))) #define Sigma1_256(x) (S32(6, (x)) ^ S32(11, (x)) ^ S32(25, (x))) #define sigma0_256(x) (S32(7, (x)) ^ S32(18, (x)) ^ R(3 , (x))) #define sigma1_256(x) (S32(17, (x)) ^ S32(19, (x)) ^ R(10, (x))) /* Four of six logical functions used in SHA-384 and SHA-512: */ #define Sigma0_512(x) (S64(28, (x)) ^ S64(34, (x)) ^ S64(39, (x))) #define Sigma1_512(x) (S64(14, (x)) ^ S64(18, (x)) ^ S64(41, (x))) #define sigma0_512(x) (S64( 1, (x)) ^ S64( 8, (x)) ^ R( 7, (x))) #define sigma1_512(x) (S64(19, (x)) ^ S64(61, (x)) ^ R( 6, (x))) /*** INTERNAL FUNCTION PROTOTYPES *************************************/ /* NOTE: These should not be accessed directly from outside this * library -- they are intended for private internal visibility/use * only. */ void SHA512_Last(SHA512_CTX *); void SHA256_Transform(SHA256_CTX *, const u_int8_t *); void SHA512_Transform(SHA512_CTX *, const u_int8_t *); /*** SHA-XYZ INITIAL HASH VALUES AND CONSTANTS ************************/ /* Hash constant words K for SHA-256: */ static const u_int32_t K256[64] = { 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, 0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL, 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL, 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL, 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, 0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL, 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL, 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL, 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, 0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, 0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL, 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL, 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL, 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL }; /* Initial hash value H for SHA-256: */ static const u_int32_t sha256_initial_hash_value[8] = { 0x6a09e667UL, 0xbb67ae85UL, 0x3c6ef372UL, 0xa54ff53aUL, 0x510e527fUL, 0x9b05688cUL, 0x1f83d9abUL, 0x5be0cd19UL }; /* Hash constant words K for SHA-384 and SHA-512: */ static const u_int64_t K512[80] = { 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL, 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL, 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL, 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL, 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, 0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL, 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL, 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL, 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL, 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL, 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL, 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, 0xd192e819d6ef5218ULL, 0xd69906245565a910ULL, 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL, 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL, 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL, 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL, 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL, 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL, 0x113f9804bef90daeULL, 0x1b710b35131c471bULL, 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL, 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL }; /* Initial hash value H for SHA-384 */ static const u_int64_t sha384_initial_hash_value[8] = { 0xcbbb9d5dc1059ed8ULL, 0x629a292a367cd507ULL, 0x9159015a3070dd17ULL, 0x152fecd8f70e5939ULL, 0x67332667ffc00b31ULL, 0x8eb44a8768581511ULL, 0xdb0c2e0d64f98fa7ULL, 0x47b5481dbefa4fa4ULL }; /* Initial hash value H for SHA-512 */ static const u_int64_t sha512_initial_hash_value[8] = { 0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL, 0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL, 0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL, 0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL }; /*** SHA-256: *********************************************************/ void SHA256_Init(SHA256_CTX *context) { if (context == NULL) return; bcopy(sha256_initial_hash_value, context->state, SHA256_DIGEST_LENGTH); bzero(context->buffer, SHA256_BLOCK_LENGTH); context->bitcount = 0; } #ifdef SHA2_UNROLL_TRANSFORM /* Unrolled SHA-256 round macros: */ #define ROUND256_0_TO_15(a,b,c,d,e,f,g,h) do { \ W256[j] = (u_int32_t)data[3] | ((u_int32_t)data[2] << 8) | \ ((u_int32_t)data[1] << 16) | ((u_int32_t)data[0] << 24); \ data += 4; \ T1 = (h) + Sigma1_256((e)) + Ch((e), (f), (g)) + K256[j] + W256[j]; \ (d) += T1; \ (h) = T1 + Sigma0_256((a)) + Maj((a), (b), (c)); \ j++; \ } while(0) #define ROUND256(a,b,c,d,e,f,g,h) do { \ s0 = W256[(j+1)&0x0f]; \ s0 = sigma0_256(s0); \ s1 = W256[(j+14)&0x0f]; \ s1 = sigma1_256(s1); \ T1 = (h) + Sigma1_256((e)) + Ch((e), (f), (g)) + K256[j] + \ (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0); \ (d) += T1; \ (h) = T1 + Sigma0_256((a)) + Maj((a), (b), (c)); \ j++; \ } while(0) void SHA256_Transform(SHA256_CTX *context, const u_int8_t *data) { u_int32_t a, b, c, d, e, f, g, h, s0, s1; u_int32_t T1, *W256; int j; W256 = (u_int32_t *)context->buffer; /* Initialize registers with the prev. intermediate value */ a = context->state[0]; b = context->state[1]; c = context->state[2]; d = context->state[3]; e = context->state[4]; f = context->state[5]; g = context->state[6]; h = context->state[7]; j = 0; do { /* Rounds 0 to 15 (unrolled): */ ROUND256_0_TO_15(a,b,c,d,e,f,g,h); ROUND256_0_TO_15(h,a,b,c,d,e,f,g); ROUND256_0_TO_15(g,h,a,b,c,d,e,f); ROUND256_0_TO_15(f,g,h,a,b,c,d,e); ROUND256_0_TO_15(e,f,g,h,a,b,c,d); ROUND256_0_TO_15(d,e,f,g,h,a,b,c); ROUND256_0_TO_15(c,d,e,f,g,h,a,b); ROUND256_0_TO_15(b,c,d,e,f,g,h,a); } while (j < 16); /* Now for the remaining rounds to 64: */ do { ROUND256(a,b,c,d,e,f,g,h); ROUND256(h,a,b,c,d,e,f,g); ROUND256(g,h,a,b,c,d,e,f); ROUND256(f,g,h,a,b,c,d,e); ROUND256(e,f,g,h,a,b,c,d); ROUND256(d,e,f,g,h,a,b,c); ROUND256(c,d,e,f,g,h,a,b); ROUND256(b,c,d,e,f,g,h,a); } while (j < 64); /* Compute the current intermediate hash value */ context->state[0] += a; context->state[1] += b; context->state[2] += c; context->state[3] += d; context->state[4] += e; context->state[5] += f; context->state[6] += g; context->state[7] += h; /* Clean up */ a = b = c = d = e = f = g = h = T1 = 0; } #else /* SHA2_UNROLL_TRANSFORM */ void SHA256_Transform(SHA256_CTX *context, const u_int8_t *data) { u_int32_t a, b, c, d, e, f, g, h, s0, s1; u_int32_t T1, T2, *W256; int j; W256 = (u_int32_t *)context->buffer; /* Initialize registers with the prev. intermediate value */ a = context->state[0]; b = context->state[1]; c = context->state[2]; d = context->state[3]; e = context->state[4]; f = context->state[5]; g = context->state[6]; h = context->state[7]; j = 0; do { W256[j] = (u_int32_t)data[3] | ((u_int32_t)data[2] << 8) | ((u_int32_t)data[1] << 16) | ((u_int32_t)data[0] << 24); data += 4; /* Apply the SHA-256 compression function to update a..h */ T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + W256[j]; T2 = Sigma0_256(a) + Maj(a, b, c); h = g; g = f; f = e; e = d + T1; d = c; c = b; b = a; a = T1 + T2; j++; } while (j < 16); do { /* Part of the message block expansion: */ s0 = W256[(j+1)&0x0f]; s0 = sigma0_256(s0); s1 = W256[(j+14)&0x0f]; s1 = sigma1_256(s1); /* Apply the SHA-256 compression function to update a..h */ T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0); T2 = Sigma0_256(a) + Maj(a, b, c); h = g; g = f; f = e; e = d + T1; d = c; c = b; b = a; a = T1 + T2; j++; } while (j < 64); /* Compute the current intermediate hash value */ context->state[0] += a; context->state[1] += b; context->state[2] += c; context->state[3] += d; context->state[4] += e; context->state[5] += f; context->state[6] += g; context->state[7] += h; /* Clean up */ a = b = c = d = e = f = g = h = T1 = T2 = 0; } #endif /* SHA2_UNROLL_TRANSFORM */ void SHA256_Update(SHA256_CTX *context, const u_int8_t *data, size_t len) { size_t freespace, usedspace; /* Calling with no data is valid (we do nothing) */ if (len == 0) return; usedspace = (context->bitcount >> 3) % SHA256_BLOCK_LENGTH; if (usedspace > 0) { /* Calculate how much free space is available in the buffer */ freespace = SHA256_BLOCK_LENGTH - usedspace; if (len >= freespace) { /* Fill the buffer completely and process it */ bcopy(data, &context->buffer[usedspace], freespace); context->bitcount += freespace << 3; len -= freespace; data += freespace; SHA256_Transform(context, context->buffer); } else { /* The buffer is not yet full */ bcopy(data, &context->buffer[usedspace], len); context->bitcount += len << 3; /* Clean up: */ usedspace = freespace = 0; return; } } while (len >= SHA256_BLOCK_LENGTH) { /* Process as many complete blocks as we can */ SHA256_Transform(context, data); context->bitcount += SHA256_BLOCK_LENGTH << 3; len -= SHA256_BLOCK_LENGTH; data += SHA256_BLOCK_LENGTH; } if (len > 0) { /* There's left-overs, so save 'em */ bcopy(data, context->buffer, len); context->bitcount += len << 3; } /* Clean up: */ usedspace = freespace = 0; } void SHA256_Final(u_int8_t digest[], SHA256_CTX *context) { u_int32_t *d = (u_int32_t *)digest; unsigned int usedspace; /* If no digest buffer is passed, we don't bother doing this: */ if (digest != NULL) { usedspace = (context->bitcount >> 3) % SHA256_BLOCK_LENGTH; /* Convert FROM host byte order */ context->bitcount = CSWAP64(context->bitcount); if (usedspace > 0) { /* Begin padding with a 1 bit: */ context->buffer[usedspace++] = 0x80; if (usedspace <= SHA256_SHORT_BLOCK_LENGTH) { /* Set-up for the last transform: */ bzero(&context->buffer[usedspace], SHA256_SHORT_BLOCK_LENGTH - usedspace); } else { if (usedspace < SHA256_BLOCK_LENGTH) { bzero(&context->buffer[usedspace], SHA256_BLOCK_LENGTH - usedspace); } /* Do second-to-last transform: */ SHA256_Transform(context, context->buffer); /* And set-up for the last transform: */ bzero(context->buffer, SHA256_SHORT_BLOCK_LENGTH); } } else { /* Set-up for the last transform: */ bzero(context->buffer, SHA256_SHORT_BLOCK_LENGTH); /* Begin padding with a 1 bit: */ *context->buffer = 0x80; } /* Set the bit count: */ *(u_int64_t *)&context->buffer[SHA256_SHORT_BLOCK_LENGTH] = context->bitcount; /* Final transform: */ SHA256_Transform(context, context->buffer); { /* Convert TO host byte order */ int j; for (j = 0; j < 8; j++) { *d++ = CSWAP32(context->state[j]); } } } /* Clean up state data: */ bzero(context, sizeof(*context)); usedspace = 0; } /* Hashing-only functions called by dyncrypt */ void sha256_process(sha256_context *ctx, u_int8_t data[64]) { SHA256_Transform(ctx, data); } void sha512_process(sha512_context *ctx, u_int8_t data[64]) { SHA512_Transform(ctx, data); } /*** SHA-512: *********************************************************/ void SHA512_Init(SHA512_CTX *context) { if (context == NULL) return; bcopy(sha512_initial_hash_value, context->state, SHA512_DIGEST_LENGTH); bzero(context->buffer, SHA512_BLOCK_LENGTH); context->bitcount[0] = context->bitcount[1] = 0; } #ifdef SHA2_UNROLL_TRANSFORM /* Unrolled SHA-512 round macros: */ #define ROUND512_0_TO_15(a,b,c,d,e,f,g,h) do { \ W512[j] = (u_int64_t)data[7] | ((u_int64_t)data[6] << 8) | \ ((u_int64_t)data[5] << 16) | ((u_int64_t)data[4] << 24) | \ ((u_int64_t)data[3] << 32) | ((u_int64_t)data[2] << 40) | \ ((u_int64_t)data[1] << 48) | ((u_int64_t)data[0] << 56); \ data += 8; \ T1 = (h) + Sigma1_512((e)) + Ch((e), (f), (g)) + K512[j] + W512[j]; \ (d) += T1; \ (h) = T1 + Sigma0_512((a)) + Maj((a), (b), (c)); \ j++; \ } while(0) #define ROUND512(a,b,c,d,e,f,g,h) do { \ s0 = W512[(j+1)&0x0f]; \ s0 = sigma0_512(s0); \ s1 = W512[(j+14)&0x0f]; \ s1 = sigma1_512(s1); \ T1 = (h) + Sigma1_512((e)) + Ch((e), (f), (g)) + K512[j] + \ (W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0); \ (d) += T1; \ (h) = T1 + Sigma0_512((a)) + Maj((a), (b), (c)); \ j++; \ } while(0) void SHA512_Transform(SHA512_CTX *context, const u_int8_t *data) { u_int64_t a, b, c, d, e, f, g, h, s0, s1; u_int64_t T1, *W512 = (u_int64_t *)context->buffer; int j; /* Initialize registers with the prev. intermediate value */ a = context->state[0]; b = context->state[1]; c = context->state[2]; d = context->state[3]; e = context->state[4]; f = context->state[5]; g = context->state[6]; h = context->state[7]; j = 0; do { ROUND512_0_TO_15(a,b,c,d,e,f,g,h); ROUND512_0_TO_15(h,a,b,c,d,e,f,g); ROUND512_0_TO_15(g,h,a,b,c,d,e,f); ROUND512_0_TO_15(f,g,h,a,b,c,d,e); ROUND512_0_TO_15(e,f,g,h,a,b,c,d); ROUND512_0_TO_15(d,e,f,g,h,a,b,c); ROUND512_0_TO_15(c,d,e,f,g,h,a,b); ROUND512_0_TO_15(b,c,d,e,f,g,h,a); } while (j < 16); /* Now for the remaining rounds up to 79: */ do { ROUND512(a,b,c,d,e,f,g,h); ROUND512(h,a,b,c,d,e,f,g); ROUND512(g,h,a,b,c,d,e,f); ROUND512(f,g,h,a,b,c,d,e); ROUND512(e,f,g,h,a,b,c,d); ROUND512(d,e,f,g,h,a,b,c); ROUND512(c,d,e,f,g,h,a,b); ROUND512(b,c,d,e,f,g,h,a); } while (j < 80); /* Compute the current intermediate hash value */ context->state[0] += a; context->state[1] += b; context->state[2] += c; context->state[3] += d; context->state[4] += e; context->state[5] += f; context->state[6] += g; context->state[7] += h; /* Clean up */ a = b = c = d = e = f = g = h = T1 = 0; } #else /* SHA2_UNROLL_TRANSFORM */ void SHA512_Transform(SHA512_CTX *context, const u_int8_t *data) { u_int64_t a, b, c, d, e, f, g, h, s0, s1; u_int64_t T1, T2, *W512 = (u_int64_t *)context->buffer; int j; /* Initialize registers with the prev. intermediate value */ a = context->state[0]; b = context->state[1]; c = context->state[2]; d = context->state[3]; e = context->state[4]; f = context->state[5]; g = context->state[6]; h = context->state[7]; j = 0; do { W512[j] = (u_int64_t)data[7] | ((u_int64_t)data[6] << 8) | ((u_int64_t)data[5] << 16) | ((u_int64_t)data[4] << 24) | ((u_int64_t)data[3] << 32) | ((u_int64_t)data[2] << 40) | ((u_int64_t)data[1] << 48) | ((u_int64_t)data[0] << 56); data += 8; /* Apply the SHA-512 compression function to update a..h */ T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + W512[j]; T2 = Sigma0_512(a) + Maj(a, b, c); h = g; g = f; f = e; e = d + T1; d = c; c = b; b = a; a = T1 + T2; j++; } while (j < 16); do { /* Part of the message block expansion: */ s0 = W512[(j+1)&0x0f]; s0 = sigma0_512(s0); s1 = W512[(j+14)&0x0f]; s1 = sigma1_512(s1); /* Apply the SHA-512 compression function to update a..h */ T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + (W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0); T2 = Sigma0_512(a) + Maj(a, b, c); h = g; g = f; f = e; e = d + T1; d = c; c = b; b = a; a = T1 + T2; j++; } while (j < 80); /* Compute the current intermediate hash value */ context->state[0] += a; context->state[1] += b; context->state[2] += c; context->state[3] += d; context->state[4] += e; context->state[5] += f; context->state[6] += g; context->state[7] += h; /* Clean up */ a = b = c = d = e = f = g = h = T1 = T2 = 0; } #endif /* SHA2_UNROLL_TRANSFORM */ void SHA512_Update(SHA512_CTX *context, const u_int8_t *data, size_t len) { size_t freespace, usedspace; /* Calling with no data is valid (we do nothing) */ if (len == 0) return; usedspace = (context->bitcount[0] >> 3) % SHA512_BLOCK_LENGTH; if (usedspace > 0) { /* Calculate how much free space is available in the buffer */ freespace = SHA512_BLOCK_LENGTH - usedspace; if (len >= freespace) { /* Fill the buffer completely and process it */ bcopy(data, &context->buffer[usedspace], freespace); ADDINC128(context->bitcount, freespace << 3); len -= freespace; data += freespace; SHA512_Transform(context, context->buffer); } else { /* The buffer is not yet full */ bcopy(data, &context->buffer[usedspace], len); ADDINC128(context->bitcount, len << 3); /* Clean up: */ usedspace = freespace = 0; return; } } while (len >= SHA512_BLOCK_LENGTH) { /* Process as many complete blocks as we can */ SHA512_Transform(context, data); ADDINC128(context->bitcount, SHA512_BLOCK_LENGTH << 3); len -= SHA512_BLOCK_LENGTH; data += SHA512_BLOCK_LENGTH; } if (len > 0) { /* There's left-overs, so save 'em */ bcopy(data, context->buffer, len); ADDINC128(context->bitcount, len << 3); } /* Clean up: */ usedspace = freespace = 0; } void SHA512_Last(SHA512_CTX *context) { unsigned int usedspace; usedspace = (context->bitcount[0] >> 3) % SHA512_BLOCK_LENGTH; /* Convert FROM host byte order */ context->bitcount[0] = CSWAP64(context->bitcount[0]); context->bitcount[1] = CSWAP64(context->bitcount[1]); if (usedspace > 0) { /* Begin padding with a 1 bit: */ context->buffer[usedspace++] = 0x80; if (usedspace <= SHA512_SHORT_BLOCK_LENGTH) { /* Set-up for the last transform: */ bzero(&context->buffer[usedspace], SHA512_SHORT_BLOCK_LENGTH - usedspace); } else { if (usedspace < SHA512_BLOCK_LENGTH) { bzero(&context->buffer[usedspace], SHA512_BLOCK_LENGTH - usedspace); } /* Do second-to-last transform: */ SHA512_Transform(context, context->buffer); /* And set-up for the last transform: */ bzero(context->buffer, SHA512_BLOCK_LENGTH - 2); } } else { /* Prepare for final transform: */ bzero(context->buffer, SHA512_SHORT_BLOCK_LENGTH); /* Begin padding with a 1 bit: */ *context->buffer = 0x80; } /* Store the length of input data (in bits): */ *(u_int64_t *)&context->buffer[SHA512_SHORT_BLOCK_LENGTH] = context->bitcount[1]; *(u_int64_t *)&context->buffer[SHA512_SHORT_BLOCK_LENGTH+8] = context->bitcount[0]; /* Final transform: */ SHA512_Transform(context, context->buffer); } void SHA512_Final(u_int8_t digest[], SHA512_CTX *context) { u_int64_t *d = (u_int64_t *)digest; /* If no digest buffer is passed, we don't bother doing this: */ if (digest != NULL) { SHA512_Last(context); /* Save the hash data for output: */ { /* Convert TO host byte order */ int j; for (j = 0; j < 8; j++) { *d++ = CSWAP64(context->state[j]); } } } /* Zero out state data */ bzero(context, sizeof(*context)); } /*** SHA-384: *********************************************************/ void SHA384_Init(SHA384_CTX *context) { if (context == NULL) return; bcopy(sha384_initial_hash_value, context->state, SHA512_DIGEST_LENGTH); bzero(context->buffer, SHA384_BLOCK_LENGTH); context->bitcount[0] = context->bitcount[1] = 0; } void SHA384_Update(SHA384_CTX *context, const u_int8_t *data, size_t len) { SHA512_Update((SHA512_CTX *)context, data, len); } void SHA384_Final(u_int8_t digest[], SHA384_CTX *context) { u_int64_t *d = (u_int64_t *)digest; /* If no digest buffer is passed, we don't bother doing this: */ if (digest != NULL) { SHA512_Last((SHA512_CTX *)context); /* Save the hash data for output: */ { /* Convert TO host byte order */ int j; for (j = 0; j < 6; j++) { *d++ = CSWAP64(context->state[j]); } } } /* Zero out state data */ bzero(context, sizeof(*context)); } hercules-3.07/crypto/sha256.h000644 000765 000765 00000007545 11143760536 017465 0ustar00jmaynardjmaynard000000 000000 /* $OpenBSD: sha2.h,v 1.2 2004/04/28 23:11:57 millert Exp $ */ /* modified for use with dyncrypt */ // $Id: sha256.h 4102 2006-12-08 09:43:35Z jj $ /* * FILE: sha2.h * AUTHOR: Aaron D. Gifford * * Copyright (c) 2000-2001, Aaron D. Gifford * 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. * 3. Neither the name of the copyright holder nor the names of contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``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 CONTRIBUTOR(S) 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. * * $From: sha2.h,v 1.1 2001/11/08 00:02:01 adg Exp adg $ */ // $Log$ #ifndef _SHA2_H #define _SHA2_H /*** SHA-256/384/512 Various Length Definitions ***********************/ #define SHA256_BLOCK_LENGTH 64 #define SHA256_DIGEST_LENGTH 32 #define SHA256_DIGEST_STRING_LENGTH (SHA256_DIGEST_LENGTH * 2 + 1) #define SHA384_BLOCK_LENGTH 128 #define SHA384_DIGEST_LENGTH 48 #define SHA384_DIGEST_STRING_LENGTH (SHA384_DIGEST_LENGTH * 2 + 1) #define SHA512_BLOCK_LENGTH 128 #define SHA512_DIGEST_LENGTH 64 #define SHA512_DIGEST_STRING_LENGTH (SHA512_DIGEST_LENGTH * 2 + 1) /*** SHA-256/384/512 Context Structures *******************************/ typedef struct _SHA256_CTX { u_int32_t state[8]; u_int64_t bitcount; u_int8_t buffer[SHA256_BLOCK_LENGTH]; } SHA256_CTX; typedef struct _SHA512_CTX { u_int64_t state[8]; u_int64_t bitcount[2]; u_int8_t buffer[SHA512_BLOCK_LENGTH]; } SHA512_CTX; typedef SHA512_CTX SHA384_CTX; void SHA256_Init(SHA256_CTX *); void SHA256_Update(SHA256_CTX *, const u_int8_t *, size_t) /* __attribute__((__bounded__(__string__,2,3))) */; void SHA256_Final(u_int8_t[SHA256_DIGEST_LENGTH], SHA256_CTX *) /* __attribute__((__bounded__(__minbytes__,1,SHA256_DIGEST_LENGTH))) */; void SHA384_Init(SHA384_CTX *); void SHA384_Update(SHA384_CTX *, const u_int8_t *, size_t) /* __attribute__((__bounded__(__string__,2,3))) */; void SHA384_Final(u_int8_t[SHA384_DIGEST_LENGTH], SHA384_CTX *) /* __attribute__((__bounded__(__minbytes__,1,SHA384_DIGEST_LENGTH))) */; void SHA512_Init(SHA512_CTX *); void SHA512_Update(SHA512_CTX *, const u_int8_t *, size_t) /* __attribute__((__bounded__(__string__,2,3))) */; void SHA512_Final(u_int8_t[SHA512_DIGEST_LENGTH], SHA512_CTX *) /* __attribute__((__bounded__(__minbytes__,1,SHA512_DIGEST_LENGTH))) */; /* Context structure definitions for dyncrypt */ typedef SHA256_CTX sha256_context; typedef SHA384_CTX sha384_context; typedef SHA512_CTX sha512_context; #endif /* _SHA2_H */ hercules-3.07/autoconf/config.guess000755 000765 000765 00000122166 11332622444 021112 0ustar00jmaynardjmaynard000000 000000 #! /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='2003-07-02' # 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 ;; amiga:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; arc:OpenBSD:*:*) echo mipsel-unknown-openbsd${UNAME_RELEASE} exit 0 ;; hp300:OpenBSD:*:*) echo m68k-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 ;; alpha:OSF1:*:*) if test $UNAME_RELEASE = "V4.0"; then UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` fi # 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 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/^[VTX]//' | 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 ;; 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 ;; 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 ;; 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:*:*|*:GNU/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/FreeBSD 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:*:*) echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` 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 ;; 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 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: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[567]*:*) test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;; 3[34]??:*: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 case $MACHTYPE in x86_64*) UNAME_PROCESSOR=x86_64 ;; 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-[DGKLNPTVW]: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 ;; 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: hercules-3.07/autoconf/config.rpath000644 000765 000765 00000033434 11143760527 021103 0ustar00jmaynardjmaynard000000 000000 #! /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-2002 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. # All known linkers require a `.a' archive for static linking (except M$VC, # which needs '.lib'). libext=a shlibext= host="$1" host_cpu=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` host_vendor=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` host_os=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` wl= if test "$GCC" = yes; then wl='-Wl,' else case "$host_os" in aix3* | aix4* | aix5*) wl='-Wl,' ;; hpux9* | hpux10* | hpux11*) wl='-Wl,' ;; irix5* | irix6*) wl='-Wl,' ;; linux*) echo '__INTEL_COMPILER' > conftest.$ac_ext if $CC -E conftest.$ac_ext >/dev/null | grep __INTEL_COMPILER >/dev/null then : else # Intel icc wl='-Qoption,ld,' fi ;; osf3* | osf4* | osf5*) wl='-Wl,' ;; solaris*) wl='-Wl,' ;; sunos4*) wl='-Qoption ld ' ;; sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) if test "x$host_vendor" = xsni; then wl='-LD' else wl='-Wl,' fi ;; esac fi 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, the GNU linker is very broken ld_shlibs=no ;; 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 | egrep ': 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' ;; solaris* | sysv5*) if $LD -v 2>&1 | egrep 'BFD 2\.8' > /dev/null; then ld_shlibs=no elif $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then : else ld_shlibs=no fi ;; sunos4*) hardcode_direct=yes ;; *) if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then : else ld_shlibs=no fi ;; esac if test "$ld_shlibs" = yes; then 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 if test "$aix_use_runtimelinking" = yes; then hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:/usr/lib:/lib' else if test "$host_cpu" = ia64; then hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' else hardcode_libdir_flag_spec='${wl}-bnolibpath ${wl}-blibpath:$libdir:/usr/lib:/lib' 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 ;; cygwin* | mingw* | pw32*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. hardcode_libdir_flag_spec=' ' libext=lib ;; darwin* | rhapsody*) hardcode_direct=yes ;; 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* | hpux10* | hpux11*) hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: hardcode_direct=yes hardcode_minus_L=yes # Not in the search PATH, but as the default # location of the library. ;; irix5* | irix6*) 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) if test "x$host_vendor" = xsno; then hardcode_direct=yes # is this really true??? else hardcode_direct=no # Motorola manual says yes, but my tests say they lie fi ;; sysv4.3*) ;; sysv5*) hardcode_libdir_flag_spec= ;; uts4*) hardcode_libdir_flag_spec='-L$libdir' ;; dgux*) hardcode_libdir_flag_spec='-L$libdir' ;; sysv4*MP*) if test -d /usr/nec; then ld_shlibs=yes fi ;; sysv4.2uw2*) hardcode_direct=yes hardcode_minus_L=no ;; sysv5uw7* | unixware7*) ;; *) ld_shlibs=no ;; esac fi # Check dynamic linker characteristics libname_spec='lib$name' sys_lib_dlsearch_path_spec="/lib /usr/lib" sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" case "$host_os" in aix3*) shlibext=so ;; aix4* | aix5*) shlibext=so ;; amigaos*) shlibext=ixlibrary ;; beos*) shlibext=so ;; bsdi4*) shlibext=so sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" ;; cygwin* | mingw* | pw32*) case $GCC,$host_os in yes,cygwin*) shlibext=dll.a ;; yes,mingw*) shlibext=dll sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | sed -e "s/^libraries://" -e "s/;/ /g"` ;; yes,pw32*) shlibext=dll ;; *) shlibext=dll ;; esac ;; darwin* | rhapsody*) shlibext=dylib ;; freebsd1*) ;; freebsd*) shlibext=so ;; gnu*) shlibext=so ;; hpux9* | hpux10* | hpux11*) shlibext=sl ;; irix5* | irix6*) shlibext=so case "$host_os" in irix5*) libsuff= shlibsuff= ;; *) case $LD in *-32|*"-32 ") libsuff= shlibsuff= ;; *-n32|*"-n32 ") libsuff=32 shlibsuff=N32 ;; *-64|*"-64 ") libsuff=64 shlibsuff=64 ;; *) libsuff= shlibsuff= ;; esac ;; esac sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" ;; linux-gnuoldld* | linux-gnuaout* | linux-gnucoff*) ;; linux-gnu*) shlibext=so ;; netbsd*) shlibext=so ;; newsos6) shlibext=so ;; openbsd*) shlibext=so ;; os2*) libname_spec='$name' shlibext=dll ;; osf3* | osf4* | osf5*) shlibext=so sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" ;; sco3.2v5*) shlibext=so ;; solaris*) shlibext=so ;; sunos4*) shlibext=so ;; sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) shlibext=so case "$host_vendor" in motorola) sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; uts4*) shlibext=so ;; dgux*) shlibext=so ;; sysv4*MP*) if test -d /usr/nec; then shlibext=so fi ;; esac sed_quote_subst='s/\(["`$\\]\)/\\\1/g' escaped_wl=`echo "X$wl" | sed -e 's/^X//' -e "$sed_quote_subst"` escaped_hardcode_libdir_flag_spec=`echo "X$hardcode_libdir_flag_spec" | sed -e 's/^X//' -e "$sed_quote_subst"` escaped_sys_lib_search_path_spec=`echo "X$sys_lib_search_path_spec" | sed -e 's/^X//' -e "$sed_quote_subst"` escaped_sys_lib_dlsearch_path_spec=`echo "X$sys_lib_dlsearch_path_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* | kfreebsd*-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] \ | 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 \ | m32r | 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 \ | 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 | 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-* \ | m32r-* \ | 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-* \ | 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-* \ | 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 ;; 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 ;; 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 ;; crds | unos) basic_machine=m68k-crds ;; cris | cris-* | etrax*) basic_machine=cris-axis ;; 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 ;; 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 ;; 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 | 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* | -netbsd* | -openbsd* | -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* | -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*) # 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*) 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 ;; -wince*) os=-wince ;; -osfrose*) os=-osfrose ;; -osf*) os=-osf ;; -utek*) os=-bsd ;; -dynix*) os=-bsd ;; -acis*) os=-aos ;; -atheos*) os=-atheos ;; -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 ;; -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 ;; -ptx*) vendor=sequent ;; -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: hercules-3.07/autoconf/depcomp000755 000765 000765 00000027525 11143760527 020157 0ustar00jmaynardjmaynard000000 000000 #! /bin/sh # depcomp - compile a program generating dependencies as side-effects # Copyright 1999, 2000 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 to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Originally written by Alexandre Oliva . if test -z "$depmode" || test -z "$source" || test -z "$object"; then echo "depcomp: Variables source, object and depmode must be set" 1>&2 exit 1 fi # `libtool' can also be set to `yes' or `no'. depfile=${depfile-`echo "$object" | sed 's,\([^/]*\)$,.deps/\1,;s/\.\([^.]*\)$/.P\1/'`} tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} rm -f "$tmpdepfile" # Some modes work just like other modes, but use different flags. We # parameterize here, but still list the modes in the big case below, # to make depend.m4 easier to write. Note that we *cannot* use a case # here, because this file can only contain one case statement. if test "$depmode" = hp; then # HP compiler uses -M and no extra arg. gccflag=-M depmode=gcc fi if test "$depmode" = dashXmstdout; then # This is just like dashmstdout with a different argument. dashmflag=-xM depmode=dashmstdout fi case "$depmode" in gcc3) ## gcc 3 implements dependency tracking that does exactly what ## we want. Yay! Note: for some reason libtool 1.4 doesn't like ## it if -MD -MP comes after the -MF stuff. Hmm. "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi mv "$tmpdepfile" "$depfile" ;; gcc) ## There are various ways to get dependency output from gcc. Here's ## why we pick this rather obscure method: ## - Don't want to use -MD because we'd like the dependencies to end ## up in a subdir. Having to rename by hand is ugly. ## (We might end up doing this anyway to support other compilers.) ## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like ## -MM, not -M (despite what the docs say). ## - Using -M directly means running the compiler twice (even worse ## than renaming). if test -z "$gccflag"; then gccflag=-MD, fi "$@" -Wp,"$gccflag$tmpdepfile" stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" echo "$object : \\" > "$depfile" alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz ## The second -e expression handles DOS-style file names with drive letters. sed -e 's/^[^:]*: / /' \ -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" ## This next piece of magic avoids the `deleted header file' problem. ## The problem is that when a header file which appears in a .P file ## is deleted, the dependency causes make to die (because there is ## typically no way to rebuild the header). We avoid this by adding ## dummy dependencies for each header file. Too bad gcc doesn't do ## this for us directly. tr ' ' ' ' < "$tmpdepfile" | ## Some versions of gcc put a space before the `:'. On the theory ## that the space means something, we add a space to the output as ## well. ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; sgi) if test "$libtool" = yes; then "$@" "-Wp,-MDupdate,$tmpdepfile" else "$@" -MDupdate "$tmpdepfile" fi stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files echo "$object : \\" > "$depfile" # Clip off the initial element (the dependent). Don't try to be # clever and replace this with sed code, as IRIX sed won't handle # lines with more than a fixed number of characters (4096 in # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; # the IRIX cc adds comments like `#:fec' to the end of the # dependency line. tr ' ' ' ' < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \ tr ' ' ' ' >> $depfile echo >> $depfile # The second pass generates a dummy entry for each header file. tr ' ' ' ' < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ >> $depfile else # The sourcefile does not contain any dependencies, so just # store a dummy comment line, to avoid errors with the Makefile # "include basename.Plo" scheme. echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" ;; aix) # The C for AIX Compiler uses -M and outputs the dependencies # in a .u file. This file always lives in the current directory. # Also, the AIX compiler puts `$object:' at the start of each line; # $object doesn't have directory information. stripped=`echo "$object" | sed -e 's,^.*/,,' -e 's/\(.*\)\..*$/\1/'` tmpdepfile="$stripped.u" outname="$stripped.o" if test "$libtool" = yes; then "$@" -Wc,-M else "$@" -M fi stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi if test -f "$tmpdepfile"; then # Each line is of the form `foo.o: dependent.h'. # Do two passes, one to just change these to # `$object: dependent.h' and one to simply `dependent.h:'. sed -e "s,^$outname:,$object :," < "$tmpdepfile" > "$depfile" sed -e "s,^$outname: \(.*\)$,\1:," < "$tmpdepfile" >> "$depfile" else # The sourcefile does not contain any dependencies, so just # store a dummy comment line, to avoid errors with the Makefile # "include basename.Plo" scheme. echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" ;; tru64) # The Tru64 AIX compiler uses -MD to generate dependencies as a side # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'. # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put # dependencies in `foo.d' instead, so we check for that too. # Subdirectories are respected. tmpdepfile1="$object.d" tmpdepfile2=`echo "$object" | sed -e 's/.o$/.d/'` if test "$libtool" = yes; then "$@" -Wc,-MD else "$@" -MD fi stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile1" "$tmpdepfile2" exit $stat fi if test -f "$tmpdepfile1"; then tmpdepfile="$tmpdepfile1" else tmpdepfile="$tmpdepfile2" fi if test -f "$tmpdepfile"; then sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" # That's a space and a tab in the []. sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" else echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" ;; #nosideeffect) # This comment above is used by automake to tell side-effect # dependency tracking mechanisms from slower ones. dashmstdout) # Important note: in order to support this mode, a compiler *must* # always write the proprocessed file to stdout, regardless of -o, # because we must use -o when running libtool. test -z "$dashmflag" && dashmflag=-M ( IFS=" " case " $* " in *" --mode=compile "*) # this is libtool, let us make it quiet for arg do # cycle over the arguments case "$arg" in "--mode=compile") # insert --quiet before "--mode=compile" set fnord "$@" --quiet shift # fnord ;; esac set fnord "$@" "$arg" shift # fnord shift # "$arg" done ;; esac "$@" $dashmflag | sed 's:^[^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile" ) & proc=$! "$@" stat=$? wait "$proc" if test "$stat" != 0; then exit $stat; fi rm -f "$depfile" cat < "$tmpdepfile" > "$depfile" tr ' ' ' ' < "$tmpdepfile" | \ ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; dashXmstdout) # This case only exists to satisfy depend.m4. It is never actually # run, as this mode is specially recognized in the preamble. exit 1 ;; makedepend) # X makedepend ( shift cleared=no for arg in "$@"; do case $cleared in no) set ""; shift cleared=yes esac case "$arg" in -D*|-I*) set fnord "$@" "$arg"; shift;; -*) ;; *) set fnord "$@" "$arg"; shift;; esac done obj_suffix="`echo $object | sed 's/^.*\././'`" touch "$tmpdepfile" ${MAKEDEPEND-makedepend} 2>/dev/null -o"$obj_suffix" -f"$tmpdepfile" "$@" ) & proc=$! "$@" stat=$? wait "$proc" if test "$stat" != 0; then exit $stat; fi rm -f "$depfile" cat < "$tmpdepfile" > "$depfile" tail +3 "$tmpdepfile" | tr ' ' ' ' | \ ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" "$tmpdepfile".bak ;; cpp) # Important note: in order to support this mode, a compiler *must* # always write the proprocessed file to stdout, regardless of -o, # because we must use -o when running libtool. ( IFS=" " case " $* " in *" --mode=compile "*) for arg do # cycle over the arguments case $arg in "--mode=compile") # insert --quiet before "--mode=compile" set fnord "$@" --quiet shift # fnord ;; esac set fnord "$@" "$arg" shift # fnord shift # "$arg" done ;; esac "$@" -E | sed -n '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' | sed '$ s: \\$::' > "$tmpdepfile" ) & proc=$! "$@" stat=$? wait "$proc" if test "$stat" != 0; then exit $stat; fi rm -f "$depfile" echo "$object : \\" > "$depfile" cat < "$tmpdepfile" >> "$depfile" sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; msvisualcpp) # Important note: in order to support this mode, a compiler *must* # always write the proprocessed file to stdout, regardless of -o, # because we must use -o when running libtool. ( IFS=" " case " $* " in *" --mode=compile "*) for arg do # cycle over the arguments case $arg in "--mode=compile") # insert --quiet before "--mode=compile" set fnord "$@" --quiet shift # fnord ;; esac set fnord "$@" "$arg" shift # fnord shift # "$arg" done ;; esac "$@" -E | sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile" ) & proc=$! "$@" stat=$? wait "$proc" if test "$stat" != 0; then exit $stat; fi rm -f "$depfile" echo "$object : \\" > "$depfile" . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile" echo " " >> "$depfile" . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::\1\::p' >> "$depfile" rm -f "$tmpdepfile" ;; none) exec "$@" ;; *) echo "Unknown depmode $depmode" 1>&2 exit 1 ;; esac exit 0 hercules-3.07/autoconf/hercules.m4000644 000765 000765 00000026212 11143760527 020646 0ustar00jmaynardjmaynard000000 000000 ############################################################################## # # H E R C U L E S . M 4 # # Hercules M4 macros for auto-configure # ############################################################################## # $Id: hercules.m4 4102 2006-12-08 09:43:35Z jj $ # # $Log$ #----------------------------------------------------------------------------- # # Macro: HC_C99_FLEXIBLE_ARRAYS() # # Checks whether or not the compiler supports C99 flexible arrays # # Parms: None # Input: Nothing # Output: $hc_cv_c99_flexible_array, # AC_DEFINE() for 'C99_FLEXIBLE_ARRAYS' if yes. # Note: Since AC_DEFINE() might be issued, a corresponding # AH_TEMPLATE() for 'C99_FLEXIBLE_ARRAYS' is of course # also needed somewhere in configure.ac # # Credit: Modeled after 'AC_C99_FLEXIBLE_ARRAY' macro copyright # by Erik de Castro Lopo : # # "Permission to use, copy, modify, distribute, # and sell this file for any purpose is hereby # granted without fee, provided that the above # copyright and this permission notice appear # in all copies. No representations are made # about the suitability of this software for any # purpose. It is provided "as is" without express # or implied warranty." # #----------------------------------------------------------------------------- AC_DEFUN([HC_C99_FLEXIBLE_ARRAYS], [ AC_CACHE_CHECK( C99 struct flexible arrays support, [hc_cv_c99_flexible_array], [ # Initialize to unknown hc_cv_c99_flexible_array=no AC_TRY_LINK( [ #include typedef struct { int foo; char bar[]; } FOOBAR; ], [ int main(int argc, char *argv[]) { FOOBAR* p = calloc( 1, sizeof(FOOBAR) + 16 ); return 0; } ], [hc_cv_c99_flexible_array=yes], [hc_cv_c99_flexible_array=no] ) ] ) if test "$hc_cv_c99_flexible_array" = "yes"; then AC_DEFINE([C99_FLEXIBLE_ARRAYS]) fi ]) #----------------------------------------------------------------------------- # # Macro: HC_PROG_CC() ((((( DEPRECATED ))))) # # Prevents undesired CFLAGS settings set by default AC_PROG_CC macro. # # Parms: none # Input: $ac_env_CFLAGS_value # Output: CFLAGS initialized to our desired starting value # Note: use instead of the default AC_PROG_CC macro # # AC_PROG_CC (actually _AC_PROC_CC_G) takes it upon itself to put "-g -O2" # in CFLAGS. While this may be good for most packages using autoconf, we # have our own "optimize" function that this interferes with. Thus this macro. # # AC_BEFORE emits a warning if AC_PROG_CC was expanded prior to this macro # in case something gets put in configure.ac before us. AC_REQUIRE expands # AC_PROG_CC for us since we need it. # #----------------------------------------------------------------------------- AC_DEFUN([HC_PROG_CC], [ AC_BEFORE( [HC_PROG_CC], [AC_PROG_CC] ) AC_REQUIRE( [AC_PROG_CC] ) # (set CFLAGS to their initial value) CFLAGS=$ac_env_CFLAGS_value ]) #----------------------------------------------------------------------------- # # Macro: HC_LD_DISALLOWDUPS() # # Adds linker options to LDFLAGS variable to warn about duplicate symbols # # Parms: none # Input: $lt_cv_prog_gnu_ld # Output: LDFLAGS variable modified as needed # #----------------------------------------------------------------------------- AC_DEFUN([HC_LD_DISALLOWDUPS], [ AC_REQUIRE([AC_PROG_LIBTOOL]) AC_REQUIRE([AC_PROG_LD_GNU]) if test "$lt_cv_prog_gnu_ld" = "yes"; then LDFLAGS="$LDFLAGS -Wl,--warn-common" fi ]) #----------------------------------------------------------------------------- # # Macro: HC_ARG_ENABLE_GETOPTWRAPPER() # # Handles "--enable-getoptwrapper" configure option # # Parms: none # Input: nothing # Output: $hc_cv_opt_getoptwrapper = "yes", "no" or "auto", as well as # other indirect side effects of _HC_CHECK_NEED_GETOPT_WRAPPER # helper macro being called # Note: calls _HC_CHECK_NEED_GETOPT_WRAPPER internal helper macro which # has its own requirements and side effects # # Ultimately determines whether the 'getopt' wrapper kludge is necessary or # specifically requested. Issues AC_DEFINE for "NEED_GETOPT_WRAPPER" if true. # Refer to _HC_CHECK_NEED_GETOPT_WRAPPER helper macro for details. # #----------------------------------------------------------------------------- AC_DEFUN([HC_ARG_ENABLE_GETOPTWRAPPER], [ AC_ARG_ENABLE( getoptwrapper, AC_HELP_STRING([--enable-getoptwrapper], [force use of the getopt wrapper kludge] ), [ case "${enableval}" in yes) hc_cv_opt_getoptwrapper=yes ;; no) hc_cv_opt_getoptwrapper=no ;; auto) hc_cv_opt_getoptwrapper=auto ;; *) hc_cv_opt_getoptwrapper=auto ;; esac ], [hc_cv_opt_getoptwrapper=auto] ) _HC_CHECK_NEED_GETOPT_WRAPPER($hc_cv_opt_getoptwrapper) ]) #----------------------------------------------------------------------------- # # Macro: _HC_CHECK_NEED_GETOPT_WRAPPER( [opt = "auto"] ) # # Determines whether the 'getopt' wrapper kludge is necessary or requested # # Parms: no they specifically requested NOT to use the wrapper # yes they specifically requested TO use the wrapper # auto we should determine ourselves if wrapper is needed # # Input: nothing # Output: $hc_cv_need_getopt_wrapper = "yes" or "no", # AC_DEFINE for "NEED_GETOPT_WRAPPER" if yes. # # Note: this macro is logically an internal subroutine of # the HC_ARG_ENABLE_GETOPTWRAPPER macro further above # # If the passed value is "yes" or "no", we simply set the output variable # value to whatever value was passed. If the passed value is "auto" however, # then we determine for ourselves whether the wrapper is needed. We do this # by performing a test link of two small programs that each use getopt but # where one calls the other (thereby producing an interdependency between # the two) and then seeing if the link caused any duplicate symbol error. # # If it is determined that the wrapper is needed (or if it was specifically # requested), an AC_DEFINE for "NEED_GETOPT_WRAPPER" is issued so Herc knows # to build/use its getopt wrapper kludge. Note that all AC_DEFINE's require # a corresponding AH_TEMPLATE statement somewhere in configure.ac. # #----------------------------------------------------------------------------- AC_DEFUN([_HC_CHECK_NEED_GETOPT_WRAPPER], [ AC_REQUIRE([AC_PROG_LIBTOOL]) AC_MSG_CHECKING([whether getopt wrapper kludge is necessary]) if test "$1" != "auto"; then hc_cv_need_getopt_wrapper="$1" hc_cv_need_getopt_wrapper_result_msg="$1 (forced)" else if test $(./libtool --features | fgrep "enable shared libraries" | wc -l) -ne 1; then # Libtool doesn't support shared libraries, # and thus our wrapper kludge is not needed. hc_cv_need_getopt_wrapper=no hc_cv_need_getopt_wrapper_result_msg=no else rm -f libconftest* rm -f .libs/libconftest* cat > conftest1.c << DUPGETOPT1 /* Test program that needs getopt, called by another program which itself needs getopt. Will the linker complain about duplicate symbols for getopt? We'll soon find out! */ extern char *optarg; extern int optind; int test1() { int i; char *c; i=optind; c=optarg; getopt(0,0,0); return 0; } DUPGETOPT1 cat > conftest2.c << DUPGETOPT2 /* Test program that not only needs getopt, but also calls another program which also needs getopt. Will linker complain about duplicate symbols for getopt? Let's see. */ extern char *optarg; extern int optind; extern int test2(); int test2() { int i; char *c; i=optind; c=optarg; getopt(0,0,0); test1(); return 0; } DUPGETOPT2 ./libtool --mode=compile ${CC-cc} conftest1.c -c -o conftest1.lo > /dev/null 2>&1 ./libtool --mode=compile ${CC-cc} conftest2.c -c -o conftest2.lo > /dev/null 2>&1 ./libtool --mode=link ${CC-cc} -shared -rpath /lib -no-undefined conftest1.lo -o libconftest1.la > /dev/null 2>&1 ./libtool --mode=link ${CC-cc} -shared -rpath /lib -no-undefined conftest2.lo libconftest1.la -o libconftest2.la > /dev/null 2>&1 if test $? = 0; then hc_cv_need_getopt_wrapper=no hc_cv_need_getopt_wrapper_result_msg=no else hc_cv_need_getopt_wrapper=yes hc_cv_need_getopt_wrapper_result_msg=yes fi rm -f *conftest* rm -f .libs/*conftest* fi fi AC_MSG_RESULT($hc_cv_need_getopt_wrapper_result_msg) if test "$hc_cv_need_getopt_wrapper" = "yes"; then AC_DEFINE([NEED_GETOPT_WRAPPER]) fi ]) #----------------------------------------------------------------------------- # # Macro: HC_CHECK_NEED_GETOPT_OPTRESET() # # Checks whether or not 'optreset' needed for 'getopt' use # # Parms: none # Input: nothing # Output: $hc_cv_need_getopt_optreset, # AC_DEFINE() for 'NEED_GETOPT_OPTRESET' if yes. # Note: since AC_DEFINE() might be issued, a corresponding AH_TEMPLATE() # for 'NEED_GETOPT_OPTRESET' is needed somewhere in configure.ac # #----------------------------------------------------------------------------- AC_DEFUN([HC_CHECK_NEED_GETOPT_OPTRESET], [ AC_CACHE_CHECK( [whether 'optreset' needed for 'getopt' use], [hc_cv_need_getopt_optreset], [ AC_TRY_LINK( [], [ extern int optreset; optreset=1; getopt(0,0,0); ], [hc_cv_need_getopt_optreset=yes], [hc_cv_need_getopt_optreset=no] ) ] ) if test "$hc_cv_need_getopt_optreset" = "yes"; then AC_DEFINE([NEED_GETOPT_OPTRESET]) fi ]) ############################################################################### # (end-of-file) ############################################################################### hercules-3.07/autoconf/install-sh000755 000765 000765 00000012736 11143760527 020604 0ustar00jmaynardjmaynard000000 000000 #!/bin/sh # # install - install a program, script, or datafile # This comes from X11R5 (mit/util/scripts/install.sh). # # Copyright 1991 by the Massachusetts Institute of Technology # # Permission to use, copy, modify, distribute, and sell this software and its # documentation for any purpose is hereby granted without fee, 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 M.I.T. not be used in advertising or # publicity pertaining to distribution of the software without specific, # written prior permission. M.I.T. makes no representations about the # suitability of this software for any purpose. It is provided "as is" # without express or implied warranty. # # 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}" transformbasename="" transform_arg="" instcmd="$mvprog" chmodcmd="$chmodprog 0755" chowncmd="" chgrpcmd="" stripcmd="" rmcmd="$rmprog -f" mvcmd="$mvprog" src="" dst="" dir_arg="" while [ x"$1" != x ]; do case $1 in -c) instcmd="$cpprog" shift continue;; -d) dir_arg=true shift continue;; -m) chmodcmd="$chmodprog $2" shift shift continue;; -o) chowncmd="$chownprog $2" shift shift continue;; -g) chgrpcmd="$chgrpprog $2" shift shift continue;; -s) stripcmd="$stripprog" shift continue;; -t=*) transformarg=`echo $1 | sed 's/-t=//'` shift continue;; -b=*) transformbasename=`echo $1 | sed 's/-b=//'` shift continue;; *) if [ x"$src" = x ] then src=$1 else # this colon is to work around a 386BSD /bin/sh bug : dst=$1 fi shift continue;; esac done if [ x"$src" = x ] then echo "install: no input file specified" exit 1 else true fi if [ x"$dir_arg" != x ]; then dst=$src src="" if [ -d $dst ]; then instcmd=: chmodcmd="" else instcmd=mkdir fi else # Waiting for this to be detected by the "$instcmd $src $dsttmp" command # might cause directories to be created, which would be especially bad # if $src (and thus $dsttmp) contains '*'. if [ -f $src -o -d $src ] then true else echo "install: $src does not exist" exit 1 fi if [ x"$dst" = x ] then echo "install: no destination specified" exit 1 else true fi # If destination is a directory, append the input filename; if your system # does not like double slashes in filenames, you may need to add some logic if [ -d $dst ] then dst="$dst"/`basename $src` else true fi fi ## this sed command emulates the dirname command dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` # Make sure that the destination directory exists. # this part is taken from Noah Friedman's mkinstalldirs script # Skip lots of stat calls in the usual case. if [ ! -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 [ $# -ne 0 ] ; do pathcomp="${pathcomp}${1}" shift if [ ! -d "${pathcomp}" ] ; then $mkdirprog "${pathcomp}" else true fi pathcomp="${pathcomp}/" done fi if [ x"$dir_arg" != x ] then $doit $instcmd $dst && if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi else # If we're going to rename the final executable, determine the name now. if [ x"$transformarg" = x ] then dstfile=`basename $dst` else dstfile=`basename $dst $transformbasename | sed $transformarg`$transformbasename fi # don't allow the sed command to completely eliminate the filename if [ x"$dstfile" = x ] then dstfile=`basename $dst` else true fi # Make a temp file name in the proper directory. dsttmp=$dstdir/#inst.$$# # Move or copy the file name to the temp name $doit $instcmd $src $dsttmp && trap "rm -f ${dsttmp}" 0 && # 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 $instcmd $src $dsttmp" command. if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && # Now rename the file to the real destination. $doit $rmcmd -f $dstdir/$dstfile && $doit $mvcmd $dsttmp $dstdir/$dstfile fi && exit 0 hercules-3.07/autoconf/libtool.m4000644 000765 000765 00000630670 11143760527 020511 0ustar00jmaynardjmaynard000000 000000 # libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- ## Copyright 1996, 1997, 1998, 1999, 2000, 2001 ## Free Software Foundation, Inc. ## 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. # serial 47 AC_PROG_LIBTOOL # AC_PROVIDE_IFELSE(MACRO-NAME, IF-PROVIDED, IF-NOT-PROVIDED) # ----------------------------------------------------------- # If this macro is not defined by Autoconf, define it here. m4_ifdef([AC_PROVIDE_IFELSE], [], [m4_define([AC_PROVIDE_IFELSE], [m4_ifdef([AC_PROVIDE_$1], [$2], [$3])])]) # AC_PROG_LIBTOOL # --------------- AC_DEFUN([AC_PROG_LIBTOOL], [AC_REQUIRE([_AC_PROG_LIBTOOL])dnl dnl If AC_PROG_CXX has already been expanded, run AC_LIBTOOL_CXX dnl immediately, otherwise, hook it in at the end of AC_PROG_CXX. AC_PROVIDE_IFELSE([AC_PROG_CXX], [AC_LIBTOOL_CXX], [define([AC_PROG_CXX], defn([AC_PROG_CXX])[AC_LIBTOOL_CXX ])]) dnl And a similar setup for Fortran 77 support AC_PROVIDE_IFELSE([AC_PROG_F77], [AC_LIBTOOL_F77], [define([AC_PROG_F77], defn([AC_PROG_F77])[AC_LIBTOOL_F77 ])]) dnl Quote A][M_PROG_GCJ so that aclocal doesn't bring it in needlessly. dnl If either AC_PROG_GCJ or A][M_PROG_GCJ have already been expanded, run dnl AC_LIBTOOL_GCJ immediately, otherwise, hook it in at the end of both. AC_PROVIDE_IFELSE([AC_PROG_GCJ], [AC_LIBTOOL_GCJ], [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], [AC_LIBTOOL_GCJ], [AC_PROVIDE_IFELSE([LT_AC_PROG_GCJ], [AC_LIBTOOL_GCJ], [ifdef([AC_PROG_GCJ], [define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[AC_LIBTOOL_GCJ])]) ifdef([A][M_PROG_GCJ], [define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[AC_LIBTOOL_GCJ])]) ifdef([LT_AC_PROG_GCJ], [define([LT_AC_PROG_GCJ], defn([LT_AC_PROG_GCJ])[AC_LIBTOOL_GCJ])])])]) ])])# AC_PROG_LIBTOOL # _AC_PROG_LIBTOOL # ---------------- AC_DEFUN([_AC_PROG_LIBTOOL], [AC_REQUIRE([AC_LIBTOOL_SETUP])dnl AC_BEFORE([$0],[AC_LIBTOOL_CXX])dnl AC_BEFORE([$0],[AC_LIBTOOL_F77])dnl AC_BEFORE([$0],[AC_LIBTOOL_GCJ])dnl # This can be used to rebuild libtool when needed LIBTOOL_DEPS="$ac_aux_dir/ltmain.sh" # Always use our own libtool. LIBTOOL='$(SHELL) $(top_builddir)/libtool' AC_SUBST(LIBTOOL)dnl # Prevent multiple expansion define([AC_PROG_LIBTOOL], []) ])# _AC_PROG_LIBTOOL # AC_LIBTOOL_SETUP # ---------------- AC_DEFUN([AC_LIBTOOL_SETUP], [AC_PREREQ(2.50)dnl AC_REQUIRE([AC_ENABLE_SHARED])dnl AC_REQUIRE([AC_ENABLE_STATIC])dnl AC_REQUIRE([AC_ENABLE_FAST_INSTALL])dnl AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([AC_PROG_LD])dnl AC_REQUIRE([AC_PROG_LD_RELOAD_FLAG])dnl AC_REQUIRE([AC_PROG_NM])dnl AC_REQUIRE([AC_PROG_LN_S])dnl AC_REQUIRE([AC_DEPLIBS_CHECK_METHOD])dnl # Autoconf 2.13's AC_OBJEXT and AC_EXEEXT macros only works for C compilers! AC_REQUIRE([AC_OBJEXT])dnl AC_REQUIRE([AC_EXEEXT])dnl dnl AC_LIBTOOL_SYS_MAX_CMD_LEN AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE AC_LIBTOOL_OBJDIR AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl _LT_AC_PROG_ECHO_BACKSLASH case $host_os in aix3*) # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi ;; esac # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. Xsed='sed -e s/^X//' [sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g'] # Same as above, but do not quote variable references. [double_quote_subst='s/\([\\"\\`\\\\]\)/\\\1/g'] # Sed substitution to delay expansion of an escaped shell variable in a # double_quote_subst'ed string. delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' # Sed substitution to avoid accidental globbing in evaled expressions no_glob_subst='s/\*/\\\*/g' # Constants: rm="rm -f" # Global variables: default_ofile=libtool can_build_shared=yes # All known linkers require a `.a' archive for static linking (except M$VC, # which needs '.lib'). libext=a ltmain="$ac_aux_dir/ltmain.sh" ofile="$default_ofile" with_gnu_ld="$lt_cv_prog_gnu_ld" AC_CHECK_TOOL(AR, ar, false) AC_CHECK_TOOL(RANLIB, ranlib, :) AC_CHECK_TOOL(STRIP, strip, :) old_CC="$CC" old_CFLAGS="$CFLAGS" # Set sane defaults for various variables test -z "$AR" && AR=ar test -z "$AR_FLAGS" && AR_FLAGS=cru test -z "$AS" && AS=as test -z "$CC" && CC=cc test -z "$LTCC" && LTCC=$CC test -z "$DLLTOOL" && DLLTOOL=dlltool test -z "$LD" && LD=ld test -z "$LN_S" && LN_S="ln -s" test -z "$MAGIC_CMD" && MAGIC_CMD=file test -z "$NM" && NM=nm test -z "$SED" && SED=sed test -z "$OBJDUMP" && OBJDUMP=objdump test -z "$RANLIB" && RANLIB=: test -z "$STRIP" && STRIP=: test -z "$ac_objext" && ac_objext=o # Determine commands to create old-style static archives. old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs$old_deplibs' old_postinstall_cmds='chmod 644 $oldlib' old_postuninstall_cmds= if test -n "$RANLIB"; then case $host_os in openbsd*) old_postinstall_cmds="\$RANLIB -t \$oldlib~$old_postinstall_cmds" ;; *) old_postinstall_cmds="\$RANLIB \$oldlib~$old_postinstall_cmds" ;; esac old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" fi # Only perform the check for file, if the check method requires it case $deplibs_check_method in file_magic*) if test "$file_magic_cmd" = '$MAGIC_CMD'; then AC_PATH_MAGIC fi ;; esac AC_PROVIDE_IFELSE([AC_LIBTOOL_DLOPEN], enable_dlopen=yes, enable_dlopen=no) AC_PROVIDE_IFELSE([AC_LIBTOOL_WIN32_DLL], enable_win32_dll=yes, enable_win32_dll=no) AC_ARG_ENABLE([libtool-lock], [AC_HELP_STRING([--disable-libtool-lock], [avoid locking (might break parallel builds)])]) test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes AC_ARG_WITH([pic], [AC_HELP_STRING([--with-pic], [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], [pic_mode="$withval"], [pic_mode=default]) test -z "$pic_mode" && pic_mode=default # Use C for the default configuration in the libtool script tagname= AC_LIBTOOL_LANG_C_CONFIG _LT_AC_TAGCONFIG ])# AC_LIBTOOL_SETUP # _LT_AC_SYS_COMPILER # ------------------- AC_DEFUN([_LT_AC_SYS_COMPILER], [AC_REQUIRE([AC_PROG_CC])dnl # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # Allow CC to be a program name with arguments. compiler=$CC ])# _LT_AC_SYS_COMPILER # _LT_AC_SYS_LIBPATH_AIX # ---------------------- # Links a minimal program and checks the executable # for the system default hardcoded library path. In most cases, # this is /usr/lib:/lib, but when the MPI compilers are used # the location of the communication and MPI libs are included too. # If we don't find anything, use the default library path according # to the aix ld manual. AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX], [AC_LINK_IFELSE(AC_LANG_PROGRAM,[ aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'` # Check for a 64-bit object if we didn't find anything. if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 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 ])# _LT_AC_SYS_LIBPATH_AIX # _LT_AC_SHELL_INIT(ARG) # ---------------------- AC_DEFUN([_LT_AC_SHELL_INIT], [ifdef([AC_DIVERSION_NOTICE], [AC_DIVERT_PUSH(AC_DIVERSION_NOTICE)], [AC_DIVERT_PUSH(NOTICE)]) $1 AC_DIVERT_POP ])# _LT_AC_SHELL_INIT # _LT_AC_PROG_ECHO_BACKSLASH # -------------------------- # Add some code to the start of the generated configure script which # will find an echo command which doesn't interpret backslashes. AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH], [_LT_AC_SHELL_INIT([ # Check that we are running under the correct shell. SHELL=${CONFIG_SHELL-/bin/sh} case X$ECHO in X*--fallback-echo) # Remove one level of quotation (which was required for Make). ECHO=`echo "$ECHO" | sed 's,\\\\\[$]\\[$]0,'[$]0','` ;; esac echo=${ECHO-echo} if test "X[$]1" = X--no-reexec; then # Discard the --no-reexec flag, and continue. shift elif test "X[$]1" = X--fallback-echo; then # Avoid inline document here, it may be left over : elif test "X`($echo '\t') 2>/dev/null`" = 'X\t' ; then # Yippee, $echo works! : else # Restart under the correct shell. exec $SHELL "[$]0" --no-reexec ${1+"[$]@"} fi if test "X[$]1" = X--fallback-echo; then # used as fallback echo shift cat </dev/null && echo_test_string="`eval $cmd`" && (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null then break fi done fi if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then : else # The Solaris, AIX, and Digital Unix default echo programs unquote # backslashes. This makes it impossible to quote backslashes using # echo "$something" | sed 's/\\/\\\\/g' # # So, first we look for a working echo in the user's PATH. lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for dir in $PATH /usr/ucb; do IFS="$lt_save_ifs" if (test -f $dir/echo || test -f $dir/echo$ac_exeext) && test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' && echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then echo="$dir/echo" break fi done IFS="$lt_save_ifs" if test "X$echo" = Xecho; then # We didn't find a better echo, so look for alternatives. if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' && echo_testing_string=`(print -r "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then # This shell has a builtin print -r that does the trick. echo='print -r' elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) && test "X$CONFIG_SHELL" != X/bin/ksh; then # If we have ksh, try running configure again with it. ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh} export ORIGINAL_CONFIG_SHELL CONFIG_SHELL=/bin/ksh export CONFIG_SHELL exec $CONFIG_SHELL "[$]0" --no-reexec ${1+"[$]@"} else # Try using printf. echo='printf %s\n' if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then # Cool, printf works : elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` && test "X$echo_testing_string" = 'X\t' && echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL export CONFIG_SHELL SHELL="$CONFIG_SHELL" export SHELL echo="$CONFIG_SHELL [$]0 --fallback-echo" elif echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` && test "X$echo_testing_string" = 'X\t' && echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then echo="$CONFIG_SHELL [$]0 --fallback-echo" else # maybe with a smaller string... prev=: for cmd in 'echo test' 'sed 2q "[$]0"' 'sed 10q "[$]0"' 'sed 20q "[$]0"' 'sed 50q "[$]0"'; do if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null then break fi prev="$cmd" done if test "$prev" != 'sed 50q "[$]0"'; then echo_test_string=`eval $prev` export echo_test_string exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "[$]0" ${1+"[$]@"} else # Oops. We lost completely, so just stick with echo. echo=echo fi fi fi fi fi fi # Copy echo and quote the copy suitably for passing to libtool from # the Makefile, instead of quoting the original, which is used later. ECHO=$echo if test "X$ECHO" = "X$CONFIG_SHELL [$]0 --fallback-echo"; then ECHO="$CONFIG_SHELL \\\$\[$]0 --fallback-echo" fi AC_SUBST(ECHO) ])])# _LT_AC_PROG_ECHO_BACKSLASH # _LT_AC_LOCK # ----------- AC_DEFUN([_LT_AC_LOCK], [AC_ARG_ENABLE([libtool-lock], [AC_HELP_STRING([--disable-libtool-lock], [avoid locking (might break parallel builds)])]) test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes # Some flags need to be propagated to the compiler or linker for good # libtool support. case $host in ia64-*-hpux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.$ac_objext` in *ELF-32*) HPUX_IA64_MODE="32" ;; *ELF-64*) HPUX_IA64_MODE="64" ;; esac fi rm -rf conftest* ;; *-*-irix6*) # Find out which ABI we are using. echo '[#]line __oline__ "configure"' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then if test "$lt_cv_prog_gnu_ld" = yes; then case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -melf32bsmip" ;; *N32*) LD="${LD-ld} -melf32bmipn32" ;; *64-bit*) LD="${LD-ld} -melf64bmip" ;; esac else case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -32" ;; *N32*) LD="${LD-ld} -n32" ;; *64-bit*) LD="${LD-ld} -64" ;; esac fi fi rm -rf conftest* ;; x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case "`/usr/bin/file conftest.o`" in *32-bit*) case $host in x86_64-*linux*) LD="${LD-ld} -m elf_i386" ;; ppc64-*linux*|powerpc64-*linux*) LD="${LD-ld} -m elf32ppclinux" ;; s390x-*linux*) LD="${LD-ld} -m elf_s390" ;; sparc64-*linux*) LD="${LD-ld} -m elf32_sparc" ;; esac ;; *64-bit*) case $host in x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; ppc*-*linux*|powerpc*-*linux*) LD="${LD-ld} -m elf64ppc" ;; s390*-*linux*) LD="${LD-ld} -m elf64_s390" ;; sparc*-*linux*) LD="${LD-ld} -m elf64_sparc" ;; esac ;; esac fi rm -rf conftest* ;; *-*-sco3.2v5*) # On SCO OpenServer 5, we need -belf to get full-featured binaries. SAVE_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -belf" AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, [AC_LANG_PUSH(C) AC_TRY_LINK([],[],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) AC_LANG_POP]) if test x"$lt_cv_cc_needs_belf" != x"yes"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf CFLAGS="$SAVE_CFLAGS" fi ;; AC_PROVIDE_IFELSE([AC_LIBTOOL_WIN32_DLL], [*-*-cygwin* | *-*-mingw* | *-*-pw32*) AC_CHECK_TOOL(DLLTOOL, dlltool, false) AC_CHECK_TOOL(AS, as, false) AC_CHECK_TOOL(OBJDUMP, objdump, false) ;; ]) esac need_locks="$enable_libtool_lock" ])# _LT_AC_LOCK # AC_LIBTOOL_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, # [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) # ---------------------------------------------------------------- # Check whether the given compiler option works AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], [AC_REQUIRE([LT_AC_PROG_SED]) AC_CACHE_CHECK([$1], [$2], [$2=no ifelse([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) printf "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$3" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&AS_MESSAGE_LOG_FD echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings if test ! -s conftest.err; then $2=yes fi fi $rm conftest* ]) if test x"[$]$2" = xyes; then ifelse([$5], , :, [$5]) else ifelse([$6], , :, [$6]) fi ])# AC_LIBTOOL_COMPILER_OPTION # AC_LIBTOOL_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, # [ACTION-SUCCESS], [ACTION-FAILURE]) # ------------------------------------------------------------ # Check whether the given compiler option works AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], [AC_CACHE_CHECK([$1], [$2], [$2=no save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $3" printf "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&AS_MESSAGE_LOG_FD else $2=yes fi fi $rm conftest* LDFLAGS="$save_LDFLAGS" ]) if test x"[$]$2" = xyes; then ifelse([$4], , :, [$4]) else ifelse([$5], , :, [$5]) fi ])# AC_LIBTOOL_LINKER_OPTION # AC_LIBTOOL_SYS_MAX_CMD_LEN # -------------------------- AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], [# find the maximum length of command line arguments AC_MSG_CHECKING([the maximum length of command line arguments]) AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl i=0 testring="ABCD" case $build_os in msdosdjgpp*) # On DJGPP, this test can blow up pretty badly due to problems in libc # (any single argument exceeding 2000 bytes causes a buffer overrun # during glob expansion). Even if it were fixed, the result of this # check would be larger than it should be. lt_cv_sys_max_cmd_len=12288; # 12K is about right ;; gnu*) # Under GNU Hurd, this test is not required because there is # no limit to the length of command line arguments. # Libtool will interpret -1 as no limit whatsoever lt_cv_sys_max_cmd_len=-1; ;; cygwin* | mingw*) # On Win9x/ME, this test blows up -- it succeeds, but takes # about 5 minutes as the teststring grows exponentially. # Worse, since 9x/ME are not pre-emptively multitasking, # you end up with a "frozen" computer, even though with patience # the test eventually succeeds (with a max line length of 256k). # Instead, let's just punt: use the minimum linelength reported by # all of the supported platforms: 8192 (on NT/2K/XP). lt_cv_sys_max_cmd_len=8192; ;; amigaos*) # On AmigaOS with pdksh, this test takes hours, literally. # So we just punt and use a minimum line length of 8192. lt_cv_sys_max_cmd_len=8192; ;; *) # If test is not a shell built-in, we'll probably end up computing a # maximum length that is only half of the actual maximum length, but # we can't tell. while (test "X"`$CONFIG_SHELL [$]0 --fallback-echo "X$testring" 2>/dev/null` \ = "XX$testring") >/dev/null 2>&1 && new_result=`expr "X$testring" : ".*" 2>&1` && lt_cv_sys_max_cmd_len=$new_result && test $i != 17 # 1/2 MB should be enough do i=`expr $i + 1` testring=$testring$testring done testring= # Add a significant safety factor because C++ compilers can tack on massive # amounts of additional arguments before passing them to the linker. # It appears as though 1/2 is a usable value. lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` ;; esac ]) if test -n $lt_cv_sys_max_cmd_len ; then AC_MSG_RESULT($lt_cv_sys_max_cmd_len) else AC_MSG_RESULT(none) fi ])# AC_LIBTOOL_SYS_MAX_CMD_LEN # _LT_AC_CHECK_DLFCN # -------------------- AC_DEFUN([_LT_AC_CHECK_DLFCN], [AC_CHECK_HEADERS(dlfcn.h)dnl ])# _LT_AC_CHECK_DLFCN # _LT_AC_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, # ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) # ------------------------------------------------------------------ AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF], [AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl if test "$cross_compiling" = yes; then : [$4] else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext < #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif #ifdef __cplusplus extern "C" void exit (int); #endif void fnord() { int i=42;} int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; /* dlclose (self); */ } exit (status); }] EOF if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then (./conftest; exit; ) 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) $1 ;; x$lt_dlneed_uscore) $2 ;; x$lt_unknown|x*) $3 ;; esac else : # compilation failed $3 fi fi rm -fr conftest* ])# _LT_AC_TRY_DLOPEN_SELF # AC_LIBTOOL_DLOPEN_SELF # ------------------- AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], [AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl if test "x$enable_dlopen" != xyes; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown else lt_cv_dlopen=no lt_cv_dlopen_libs= case $host_os in beos*) lt_cv_dlopen="load_add_on" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; mingw* | pw32*) lt_cv_dlopen="LoadLibrary" lt_cv_dlopen_libs= ;; cygwin*) lt_cv_dlopen="dlopen" lt_cv_dlopen_libs= ;; darwin*) # if libdl is installed we need to link against it AC_CHECK_LIB([dl], [dlopen], [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],[ lt_cv_dlopen="dyld" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ]) ;; *) AC_CHECK_FUNC([shl_load], [lt_cv_dlopen="shl_load"], [AC_CHECK_LIB([dld], [shl_load], [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-dld"], [AC_CHECK_FUNC([dlopen], [lt_cv_dlopen="dlopen"], [AC_CHECK_LIB([dl], [dlopen], [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"], [AC_CHECK_LIB([svld], [dlopen], [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"], [AC_CHECK_LIB([dld], [dld_link], [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld"]) ]) ]) ]) ]) ]) ;; esac if test "x$lt_cv_dlopen" != xno; then enable_dlopen=yes else enable_dlopen=no fi case $lt_cv_dlopen in dlopen) save_CPPFLAGS="$CPPFLAGS" test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" save_LDFLAGS="$LDFLAGS" eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" save_LIBS="$LIBS" LIBS="$lt_cv_dlopen_libs $LIBS" AC_CACHE_CHECK([whether a program can dlopen itself], lt_cv_dlopen_self, [dnl _LT_AC_TRY_DLOPEN_SELF( lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) ]) if test "x$lt_cv_dlopen_self" = xyes; then LDFLAGS="$LDFLAGS $link_static_flag" AC_CACHE_CHECK([whether a statically linked program can dlopen itself], lt_cv_dlopen_self_static, [dnl _LT_AC_TRY_DLOPEN_SELF( lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) ]) fi CPPFLAGS="$save_CPPFLAGS" LDFLAGS="$save_LDFLAGS" LIBS="$save_LIBS" ;; esac case $lt_cv_dlopen_self in yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; *) enable_dlopen_self=unknown ;; esac case $lt_cv_dlopen_self_static in yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; *) enable_dlopen_self_static=unknown ;; esac fi ])# AC_LIBTOOL_DLOPEN_SELF # AC_LIBTOOL_PROG_CC_C_O([TAGNAME]) # --------------------------------- # Check to see if options -c and -o are simultaneously supported by compiler AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O], [AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], [_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)], [_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no $rm -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out printf "$lt_simple_compile_test_code" > conftest.$ac_ext # According to Tom Tromey, Ian Lance Taylor reported there are C compilers # that will create temporary files in the current directory regardless of # the output directory. Thus, making CWD read-only will cause this test # to fail, enabling locking or at least warning the user not to do parallel # builds. chmod -w . lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&AS_MESSAGE_LOG_FD echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings if test ! -s out/conftest.err; then _LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes fi fi chmod u+w . $rm conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files $rm out/* && rmdir out cd .. rmdir conftest $rm conftest* ]) ])# AC_LIBTOOL_PROG_CC_C_O # AC_LIBTOOL_SYS_HARD_LINK_LOCKS([TAGNAME]) # ----------------------------------------- # Check to see if we can do hard links to lock some files if needed AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_REQUIRE([_LT_AC_LOCK])dnl hard_links="nottested" if test "$_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != no; then # do not overwrite the value of need_locks provided by the user AC_MSG_CHECKING([if we can lock with hard links]) hard_links=yes $rm conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no AC_MSG_RESULT([$hard_links]) if test "$hard_links" = no; then AC_MSG_WARN([`$CC' does not support `-c -o', so `make -j' may be unsafe]) need_locks=warn fi else need_locks=no fi ])# AC_LIBTOOL_SYS_HARD_LINK_LOCKS # AC_LIBTOOL_OBJDIR # ----------------- AC_DEFUN([AC_LIBTOOL_OBJDIR], [AC_CACHE_CHECK([for objdir], [lt_cv_objdir], [rm -f .libs 2>/dev/null mkdir .libs 2>/dev/null if test -d .libs; then lt_cv_objdir=.libs else # MS-DOS does not allow filenames that begin with a dot. lt_cv_objdir=_libs fi rmdir .libs 2>/dev/null]) objdir=$lt_cv_objdir ])# AC_LIBTOOL_OBJDIR # AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH([TAGNAME]) # ---------------------------------------------- # Check hardcoding attributes. AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_MSG_CHECKING([how to hardcode library paths into programs]) _LT_AC_TAGVAR(hardcode_action, $1)= if test -n "$_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)" || \ test -n "$_LT_AC_TAGVAR(runpath_var $1)" || \ test "X$_LT_AC_TAGVAR(hardcode_automatic, $1)"="Xyes" ; then # We can hardcode non-existant directories. if test "$_LT_AC_TAGVAR(hardcode_direct, $1)" != no && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, $1)" != no && test "$_LT_AC_TAGVAR(hardcode_minus_L, $1)" != no; then # Linking always hardcodes the temporary library directory. _LT_AC_TAGVAR(hardcode_action, $1)=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. _LT_AC_TAGVAR(hardcode_action, $1)=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. _LT_AC_TAGVAR(hardcode_action, $1)=unsupported fi AC_MSG_RESULT([$_LT_AC_TAGVAR(hardcode_action, $1)]) if test "$_LT_AC_TAGVAR(hardcode_action, $1)" = relink; then # Fast installation is not supported enable_fast_install=no elif test "$shlibpath_overrides_runpath" = yes || test "$enable_shared" = no; then # Fast installation is not necessary enable_fast_install=needless fi ])# AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH # AC_LIBTOOL_SYS_LIB_STRIP # ------------------------ AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP], [striplib= old_striplib= AC_MSG_CHECKING([whether stripping libraries is possible]) if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" test -z "$striplib" && striplib="$STRIP --strip-unneeded" # # # The following section is a PATCH to overcome the # stripped import library issues under cygwin case $host_os in cygwin*) striplib= AC_MSG_RESULT([no]) ;; *) AC_MSG_RESULT([yes]) ;; esac # # # AC_MSG_RESULT([yes]) # # else # FIXME - insert some real tests, host_os isn't really good enough case $host_os in darwin*) if test -n "$STRIP" ; then striplib="$STRIP -x" AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) fi ;; *) AC_MSG_RESULT([no]) ;; esac fi ])# AC_LIBTOOL_SYS_LIB_STRIP # AC_LIBTOOL_SYS_DYNAMIC_LINKER # ----------------------------- # PORTME Fill in your ld.so characteristics AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_MSG_CHECKING([dynamic linker characteristics]) library_names_spec= libname_spec='lib$name' soname_spec= shrext=".so" postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" if test "$GCC" = yes; then sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown case $host_os in aix3*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='${libname}${release}${shared_ext}$major' ;; aix4* | aix5*) version_type=linux need_lib_prefix=no need_version=no hardcode_into_libs=yes if test "$host_cpu" = ia64; then # AIX 5 supports IA64 library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line `#! .'. This would cause the generated library to # depend on `.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[[01]] | aix4.[[01]].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then : else can_build_shared=no fi ;; esac # AIX (on Power*) has no versioning support, so currently we can not hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. if test "$aix_use_runtimelinking" = yes; then # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' else # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='${libname}${release}.a $libname.a' soname_spec='${libname}${release}${shared_ext}$major' fi shlibpath_var=LIBPATH fi ;; amigaos*) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; beos*) library_names_spec='${libname}${shared_ext}' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi4*) version_type=linux need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32*) version_type=windows shrext=".dll" need_version=no need_lib_prefix=no case $GCC,$host_os in yes,cygwin* | yes,mingw* | yes,pw32*) library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $rm \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" ;; mingw*) # MinGW DLLs use traditional 'lib' prefix soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` if echo "$sys_lib_search_path_spec" | [grep ';[c-zC-Z]:/' >/dev/null]; then # It is most probably a Windows format PATH printed by # mingw gcc, but we are running on Cygwin. Gcc prints its search # path with ; separators, and with drive letters. We can handle the # drive letters (cygwin fileutils understands them), so leave them, # especially as we might pass files found there to a mingw objdump, # which wouldn't understand a cygwinified path. Ahh. sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' ;; esac ;; *) library_names_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext} $libname.lib' ;; esac dynamic_linker='Win32 ld.exe' # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext' soname_spec='${libname}${release}${major}$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext='$(test .$module = .yes && echo .so || echo .dylib)' # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same. if test "$GCC" = yes; then sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"` else sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib' fi sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd1*) dynamic_linker=no ;; kfreebsd*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='GNU ld.so' ;; freebsd*) objformat=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout` version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2*) shlibpath_overrides_runpath=yes ;; freebsd3.[01]* | freebsdelf3.[01]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; *) # from 3.2 on shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; esac ;; gnu*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case "$host_cpu" in ia64*) shrext='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' if test "X$HPUX_IA64_MODE" = X32; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" fi sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; hppa*64*) shrext='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555. postinstall_cmds='chmod 555 $lib' ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test "$lt_cv_prog_gnu_ld" = yes; then version_type=linux else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; # This must be Linux ELF. linux*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; nto-qnx*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; openbsd*) version_type=sunos need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then case $host_os in openbsd2.[[89]] | openbsd2.[[89]].*) shlibpath_overrides_runpath=no ;; *) shlibpath_overrides_runpath=yes ;; esac else shlibpath_overrides_runpath=yes fi ;; os2*) libname_spec='$name' shrext=".dll" need_lib_prefix=no library_names_spec='$libname${shared_ext} $libname.a' dynamic_linker='OS/2 ld.exe' shlibpath_var=LIBPATH ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" ;; sco3.2v5*) version_type=osf soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH ;; solaris*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test "$with_gnu_ld" = yes; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no export_dynamic_flag_spec='${wl}-Blargedynsym' runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec ;then version_type=linux library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' soname_spec='$libname${shared_ext}.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; uts4*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac AC_MSG_RESULT([$dynamic_linker]) test "$dynamic_linker" = no && can_build_shared=no ])# AC_LIBTOOL_SYS_DYNAMIC_LINKER # _LT_AC_TAGCONFIG # ---------------- AC_DEFUN([_LT_AC_TAGCONFIG], [AC_ARG_WITH([tags], [AC_HELP_STRING([--with-tags@<:@=TAGS@:>@], [include additional configurations @<:@automatic@:>@])], [tagnames="$withval"]) if test -f "$ltmain" && test -n "$tagnames"; then if test ! -f "${ofile}"; then AC_MSG_WARN([output file `$ofile' does not exist]) fi if test -z "$LTCC"; then eval "`$SHELL ${ofile} --config | grep '^LTCC='`" if test -z "$LTCC"; then AC_MSG_WARN([output file `$ofile' does not look like a libtool script]) else AC_MSG_WARN([using `LTCC=$LTCC', extracted from `$ofile']) fi fi # Extract list of available tagged configurations in $ofile. # Note that this assumes the entire list is on one line. available_tags=`grep "^available_tags=" "${ofile}" | $SED -e 's/available_tags=\(.*$\)/\1/' -e 's/\"//g'` lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for tagname in $tagnames; do IFS="$lt_save_ifs" # Check whether tagname contains only valid characters case `$echo "X$tagname" | $Xsed -e 's:[[-_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890,/]]::g'` in "") ;; *) AC_MSG_ERROR([invalid tag name: $tagname]) ;; esac if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "${ofile}" > /dev/null then AC_MSG_ERROR([tag name \"$tagname\" already exists]) fi # Update the list of available tags. if test -n "$tagname"; then echo appending configuration tag \"$tagname\" to $ofile case $tagname in CXX) if test -n "$CXX" && test "X$CXX" != "Xno"; then AC_LIBTOOL_LANG_CXX_CONFIG else tagname="" fi ;; F77) if test -n "$F77" && test "X$F77" != "Xno"; then AC_LIBTOOL_LANG_F77_CONFIG else tagname="" fi ;; GCJ) if test -n "$GCJ" && test "X$GCJ" != "Xno"; then AC_LIBTOOL_LANG_GCJ_CONFIG else tagname="" fi ;; RC) AC_LIBTOOL_LANG_RC_CONFIG ;; *) AC_MSG_ERROR([Unsupported tag name: $tagname]) ;; esac # Append the new tag name to the list of available tags. if test -n "$tagname" ; then available_tags="$available_tags $tagname" fi fi done IFS="$lt_save_ifs" # Now substitute the updated list of available tags. if eval "sed -e 's/^available_tags=.*\$/available_tags=\"$available_tags\"/' \"$ofile\" > \"${ofile}T\""; then mv "${ofile}T" "$ofile" chmod +x "$ofile" else rm -f "${ofile}T" AC_MSG_ERROR([unable to update list of available tagged configurations.]) fi fi ])# _LT_AC_TAGCONFIG # AC_LIBTOOL_DLOPEN # ----------------- # enable checks for dlopen support AC_DEFUN([AC_LIBTOOL_DLOPEN], [AC_BEFORE([$0],[AC_LIBTOOL_SETUP]) ])# AC_LIBTOOL_DLOPEN # AC_LIBTOOL_WIN32_DLL # -------------------- # declare package support for building win32 dll's AC_DEFUN([AC_LIBTOOL_WIN32_DLL], [AC_BEFORE([$0], [AC_LIBTOOL_SETUP]) ])# AC_LIBTOOL_WIN32_DLL # AC_ENABLE_SHARED([DEFAULT]) # --------------------------- # implement the --enable-shared flag # DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. AC_DEFUN([AC_ENABLE_SHARED], [define([AC_ENABLE_SHARED_DEFAULT], ifelse($1, no, no, yes))dnl AC_ARG_ENABLE([shared], [AC_HELP_STRING([--enable-shared@<:@=PKGS@:>@], [build shared libraries @<:@default=]AC_ENABLE_SHARED_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_shared=yes ;; no) enable_shared=no ;; *) enable_shared=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_shared=yes fi done IFS="$lt_save_ifs" ;; esac], [enable_shared=]AC_ENABLE_SHARED_DEFAULT) ])# AC_ENABLE_SHARED # AC_DISABLE_SHARED # ----------------- #- set the default shared flag to --disable-shared AC_DEFUN([AC_DISABLE_SHARED], [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl AC_ENABLE_SHARED(no) ])# AC_DISABLE_SHARED # AC_ENABLE_STATIC([DEFAULT]) # --------------------------- # implement the --enable-static flag # DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. AC_DEFUN([AC_ENABLE_STATIC], [define([AC_ENABLE_STATIC_DEFAULT], ifelse($1, no, no, yes))dnl AC_ARG_ENABLE([static], [AC_HELP_STRING([--enable-static@<:@=PKGS@:>@], [build static libraries @<:@default=]AC_ENABLE_STATIC_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_static=yes ;; no) enable_static=no ;; *) enable_static=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_static=yes fi done IFS="$lt_save_ifs" ;; esac], [enable_static=]AC_ENABLE_STATIC_DEFAULT) ])# AC_ENABLE_STATIC # AC_DISABLE_STATIC # ----------------- # set the default static flag to --disable-static AC_DEFUN([AC_DISABLE_STATIC], [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl AC_ENABLE_STATIC(no) ])# AC_DISABLE_STATIC # AC_ENABLE_FAST_INSTALL([DEFAULT]) # --------------------------------- # implement the --enable-fast-install flag # DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. AC_DEFUN([AC_ENABLE_FAST_INSTALL], [define([AC_ENABLE_FAST_INSTALL_DEFAULT], ifelse($1, no, no, yes))dnl AC_ARG_ENABLE([fast-install], [AC_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], [optimize for fast installation @<:@default=]AC_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_fast_install=yes ;; no) enable_fast_install=no ;; *) enable_fast_install=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_fast_install=yes fi done IFS="$lt_save_ifs" ;; esac], [enable_fast_install=]AC_ENABLE_FAST_INSTALL_DEFAULT) ])# AC_ENABLE_FAST_INSTALL # AC_DISABLE_FAST_INSTALL # ----------------------- # set the default to --disable-fast-install AC_DEFUN([AC_DISABLE_FAST_INSTALL], [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl AC_ENABLE_FAST_INSTALL(no) ])# AC_DISABLE_FAST_INSTALL # AC_LIBTOOL_PICMODE([MODE]) # -------------------------- # implement the --with-pic flag # MODE is either `yes' or `no'. If omitted, it defaults to `both'. AC_DEFUN([AC_LIBTOOL_PICMODE], [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl pic_mode=ifelse($#,1,$1,default) ])# AC_LIBTOOL_PICMODE # AC_PROG_EGREP # ------------- # This is predefined starting with Autoconf 2.54, so this conditional # definition can be removed once we require Autoconf 2.54 or later. m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP], [AC_CACHE_CHECK([for egrep], [ac_cv_prog_egrep], [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]) EGREP=$ac_cv_prog_egrep AC_SUBST([EGREP]) ])]) # AC_PATH_TOOL_PREFIX # ------------------- # find a file program which can recognise shared library AC_DEFUN([AC_PATH_TOOL_PREFIX], [AC_REQUIRE([AC_PROG_EGREP])dnl AC_MSG_CHECKING([for $1]) AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, [case $MAGIC_CMD in [[\\/*] | ?:[\\/]*]) lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD="$MAGIC_CMD" lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR dnl $ac_dummy forces splitting on constant user-supplied paths. dnl POSIX.2 word splitting is done only on the output of word expansions, dnl not every word. This closes a longstanding sh security hole. ac_dummy="ifelse([$2], , $PATH, [$2])" for ac_dir in $ac_dummy; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/$1; then lt_cv_path_MAGIC_CMD="$ac_dir/$1" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex="`expr \"$deplibs_check_method\" : \"file_magic \(.*\)\"`" MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org EOF fi ;; esac fi break fi done IFS="$lt_save_ifs" MAGIC_CMD="$lt_save_MAGIC_CMD" ;; esac]) MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if test -n "$MAGIC_CMD"; then AC_MSG_RESULT($MAGIC_CMD) else AC_MSG_RESULT(no) fi ])# AC_PATH_TOOL_PREFIX # AC_PATH_MAGIC # ------------- # find a file program which can recognise a shared library AC_DEFUN([AC_PATH_MAGIC], [AC_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) if test -z "$lt_cv_path_MAGIC_CMD"; then if test -n "$ac_tool_prefix"; then AC_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) else MAGIC_CMD=: fi fi ])# AC_PATH_MAGIC # AC_PROG_LD # ---------- # find the pathname to the GNU or non-GNU linker AC_DEFUN([AC_PROG_LD], [AC_ARG_WITH([gnu-ld], [AC_HELP_STRING([--with-gnu-ld], [assume the C compiler uses GNU ld @<:@default=no@:>@])], [test "$withval" = no || with_gnu_ld=yes], [with_gnu_ld=no]) AC_REQUIRE([LT_AC_PROG_SED])dnl AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl 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 $CC]) case $host in *-*-mingw*) # gcc leaves a trailing carriage return which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [[\\/]]* | ?:[[\\/]]*) re_direlt='/[[^/]][[^/]]*/\.\./' # Canonicalize the pathname of ld ac_prog=`echo $ac_prog| $SED 's%\\\\%/%g'` while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do ac_prog=`echo $ac_prog| $SED "s%$re_direlt%/%"` done test -z "$LD" && LD="$ac_prog" ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test "$with_gnu_ld" = yes; then AC_MSG_CHECKING([for GNU ld]) else AC_MSG_CHECKING([for non-GNU ld]) fi AC_CACHE_VAL(lt_cv_path_LD, [if test -z "$LD"; then lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD="$ac_dir/$ac_prog" # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some GNU ld's only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &1 /dev/null; then case $host_cpu in i*86 ) # Not sure whether the presence of OpenBSD here was a mistake. # Let's accept both of them until this is cleared up. lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD)/i[[3-9]]86 (compact )?demand paged shared library' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` ;; esac else lt_cv_deplibs_check_method=pass_all fi ;; gnu*) lt_cv_deplibs_check_method=pass_all ;; hpux10.20* | hpux11*) lt_cv_file_magic_cmd=/usr/bin/file case "$host_cpu" in ia64*) lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so ;; hppa*64*) [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]'] lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl ;; *) lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]].[[0-9]]) shared library' lt_cv_file_magic_test_file=/usr/lib/libc.sl ;; esac ;; irix5* | irix6* | nonstopux*) case $host_os in irix5* | nonstopux*) # this will be overridden with pass_all, but let us keep it just in case lt_cv_deplibs_check_method="file_magic ELF 32-bit MSB dynamic lib MIPS - version 1" ;; *) case $LD in *-32|*"-32 ") libmagic=32-bit;; *-n32|*"-n32 ") libmagic=N32;; *-64|*"-64 ") libmagic=64-bit;; *) libmagic=never-match;; esac # this will be overridden with pass_all, but let us keep it just in case lt_cv_deplibs_check_method="file_magic ELF ${libmagic} MSB mips-[[1234]] dynamic lib MIPS - version 1" ;; esac lt_cv_file_magic_test_file=`echo /lib${libsuff}/libc.so*` lt_cv_deplibs_check_method=pass_all ;; # This must be Linux ELF. linux*) case $host_cpu in alpha* | hppa* | i*86 | ia64* | m68* | mips* | powerpc* | sparc* | s390* | sh*) lt_cv_deplibs_check_method=pass_all ;; *) # glibc up to 2.1.1 does not perform some relocations on ARM lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' ;; esac lt_cv_file_magic_test_file=`echo /lib/libc.so* /lib/libc-*.so` ;; netbsd*) if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$' fi ;; newos6*) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=/usr/lib/libnls.so ;; nto-qnx*) lt_cv_deplibs_check_method=unknown ;; openbsd*) lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB shared object' else lt_cv_deplibs_check_method='file_magic OpenBSD.* shared library' fi ;; osf3* | osf4* | osf5*) # this will be overridden with pass_all, but let us keep it just in case lt_cv_deplibs_check_method='file_magic COFF format alpha shared library' lt_cv_file_magic_test_file=/shlib/libc.so lt_cv_deplibs_check_method=pass_all ;; sco3.2v5*) lt_cv_deplibs_check_method=pass_all ;; solaris*) lt_cv_deplibs_check_method=pass_all lt_cv_file_magic_test_file=/lib/libc.so ;; sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) case $host_vendor in motorola) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` ;; ncr) lt_cv_deplibs_check_method=pass_all ;; sequent) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' ;; sni) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" lt_cv_file_magic_test_file=/lib/libc.so ;; siemens) lt_cv_deplibs_check_method=pass_all ;; esac ;; sysv5OpenUNIX8* | sysv5UnixWare7* | sysv5uw[[78]]* | unixware7* | sysv4*uw2*) lt_cv_deplibs_check_method=pass_all ;; esac ]) file_magic_cmd=$lt_cv_file_magic_cmd deplibs_check_method=$lt_cv_deplibs_check_method test -z "$deplibs_check_method" && deplibs_check_method=unknown ])# AC_DEPLIBS_CHECK_METHOD # AC_PROG_NM # ---------- # find the pathname to a BSD-compatible name lister AC_DEFUN([AC_PROG_NM], [AC_CACHE_CHECK([for BSD-compatible nm], lt_cv_path_NM, [if test -n "$NM"; then # Let the user override the test. lt_cv_path_NM="$NM" else lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH /usr/ccs/bin /usr/ucb /bin; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. tmp_nm="$ac_dir/${ac_tool_prefix}nm" if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then # Check to see if the nm accepts a BSD-compat flag. # Adding the `sed 1q' prevents false positives on HP-UX, which says: # nm: unknown option "B" ignored # Tru64's nm complains that /dev/null is an invalid object file case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in */dev/null* | *'Invalid file or object type'*) lt_cv_path_NM="$tmp_nm -B" break ;; *) case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in */dev/null*) lt_cv_path_NM="$tmp_nm -p" break ;; *) lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but continue # so that we can try to find one that supports BSD flags ;; esac esac fi done IFS="$lt_save_ifs" test -z "$lt_cv_path_NM" && lt_cv_path_NM=nm fi]) NM="$lt_cv_path_NM" ])# AC_PROG_NM # AC_CHECK_LIBM # ------------- # check for math library AC_DEFUN([AC_CHECK_LIBM], [AC_REQUIRE([AC_CANONICAL_HOST])dnl LIBM= case $host in *-*-beos* | *-*-cygwin* | *-*-pw32* | *-*-darwin*) # These system don't have libm, or don't need it ;; *-ncr-sysv4.3*) AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw") AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") ;; *) AC_CHECK_LIB(m, cos, LIBM="-lm") ;; esac ])# AC_CHECK_LIBM # AC_LIBLTDL_CONVENIENCE([DIRECTORY]) # ----------------------------------- # sets LIBLTDL to the link flags for the libltdl convenience library and # LTDLINCL to the include flags for the libltdl header and adds # --enable-ltdl-convenience to the configure arguments. Note that LIBLTDL # and LTDLINCL are not AC_SUBSTed, nor is AC_CONFIG_SUBDIRS called. If # DIRECTORY is not provided, it is assumed to be `libltdl'. LIBLTDL will # be prefixed with '${top_builddir}/' and LTDLINCL will be prefixed with # '${top_srcdir}/' (note the single quotes!). If your package is not # flat and you're not using automake, define top_builddir and # top_srcdir appropriately in the Makefiles. AC_DEFUN([AC_LIBLTDL_CONVENIENCE], [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl case $enable_ltdl_convenience in no) AC_MSG_ERROR([this package needs a convenience libltdl]) ;; "") enable_ltdl_convenience=yes ac_configure_args="$ac_configure_args --enable-ltdl-convenience" ;; esac LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdlc.la LTDLINCL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl']) # For backwards non-gettext consistent compatibility... INCLTDL="$LTDLINCL" ])# AC_LIBLTDL_CONVENIENCE # AC_LIBLTDL_INSTALLABLE([DIRECTORY]) # ----------------------------------- # sets LIBLTDL to the link flags for the libltdl installable library and # LTDLINCL to the include flags for the libltdl header and adds # --enable-ltdl-install to the configure arguments. Note that LIBLTDL # and LTDLINCL are not AC_SUBSTed, nor is AC_CONFIG_SUBDIRS called. If # DIRECTORY is not provided and an installed libltdl is not found, it is # assumed to be `libltdl'. LIBLTDL will be prefixed with '${top_builddir}/' # and LTDLINCL will be prefixed with '${top_srcdir}/' (note the single # quotes!). If your package is not flat and you're not using automake, # define top_builddir and top_srcdir appropriately in the Makefiles. # In the future, this macro may have to be called after AC_PROG_LIBTOOL. AC_DEFUN([AC_LIBLTDL_INSTALLABLE], [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl AC_CHECK_LIB(ltdl, lt_dlinit, [test x"$enable_ltdl_install" != xyes && enable_ltdl_install=no], [if test x"$enable_ltdl_install" = xno; then AC_MSG_WARN([libltdl not installed, but installation disabled]) else enable_ltdl_install=yes fi ]) if test x"$enable_ltdl_install" = x"yes"; then ac_configure_args="$ac_configure_args --enable-ltdl-install" LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdl.la LTDLINCL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl']) else ac_configure_args="$ac_configure_args --enable-ltdl-install=no" LIBLTDL="-lltdl" LTDLINCL= fi # For backwards non-gettext consistent compatibility... INCLTDL="$LTDLINCL" ])# AC_LIBLTDL_INSTALLABLE # AC_LIBTOOL_CXX # -------------- # enable support for C++ libraries AC_DEFUN([AC_LIBTOOL_CXX], [AC_REQUIRE([_LT_AC_LANG_CXX]) ])# AC_LIBTOOL_CXX # _LT_AC_LANG_CXX # --------------- AC_DEFUN([_LT_AC_LANG_CXX], [AC_REQUIRE([AC_PROG_CXX]) AC_REQUIRE([AC_PROG_CXXCPP]) _LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}CXX]) ])# _LT_AC_LANG_CXX # AC_LIBTOOL_F77 # -------------- # enable support for Fortran 77 libraries AC_DEFUN([AC_LIBTOOL_F77], [AC_REQUIRE([_LT_AC_LANG_F77]) ])# AC_LIBTOOL_F77 # _LT_AC_LANG_F77 # --------------- AC_DEFUN([_LT_AC_LANG_F77], [AC_REQUIRE([AC_PROG_F77]) _LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}F77]) ])# _LT_AC_LANG_F77 # AC_LIBTOOL_GCJ # -------------- # enable support for GCJ libraries AC_DEFUN([AC_LIBTOOL_GCJ], [AC_REQUIRE([_LT_AC_LANG_GCJ]) ])# AC_LIBTOOL_GCJ # _LT_AC_LANG_GCJ # --------------- AC_DEFUN([_LT_AC_LANG_GCJ], [AC_PROVIDE_IFELSE([AC_PROG_GCJ],[], [AC_PROVIDE_IFELSE([A][M_PROG_GCJ],[], [AC_PROVIDE_IFELSE([LT_AC_PROG_GCJ],[], [ifdef([AC_PROG_GCJ],[AC_REQUIRE([AC_PROG_GCJ])], [ifdef([A][M_PROG_GCJ],[AC_REQUIRE([A][M_PROG_GCJ])], [AC_REQUIRE([A][C_PROG_GCJ_OR_A][M_PROG_GCJ])])])])])]) _LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}GCJ]) ])# _LT_AC_LANG_GCJ # AC_LIBTOOL_RC # -------------- # enable support for Windows resource files AC_DEFUN([AC_LIBTOOL_RC], [AC_REQUIRE([LT_AC_PROG_RC]) _LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}RC]) ])# AC_LIBTOOL_RC # AC_LIBTOOL_LANG_C_CONFIG # ------------------------ # Ensure that the configuration vars for the C compiler are # suitably defined. Those variables are subsequently used by # AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'. AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG], [_LT_AC_LANG_C_CONFIG]) AC_DEFUN([_LT_AC_LANG_C_CONFIG], [lt_save_CC="$CC" AC_LANG_PUSH(C) # Source file extension for C test sources. ac_ext=c # Object file extension for compiled C test sources. objext=o _LT_AC_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;\n" # Code to be used in simple link tests lt_simple_link_test_code='int main(){return(0);}\n' _LT_AC_SYS_COMPILER # # Check for any special shared library compilation flags. # _LT_AC_TAGVAR(lt_prog_cc_shlib, $1)= if test "$GCC" = no; then case $host_os in sco3.2v5*) _LT_AC_TAGVAR(lt_prog_cc_shlib, $1)='-belf' ;; esac fi if test -n "$_LT_AC_TAGVAR(lt_prog_cc_shlib, $1)"; then AC_MSG_WARN([`$CC' requires `$_LT_AC_TAGVAR(lt_prog_cc_shlib, $1)' to build shared libraries]) if echo "$old_CC $old_CFLAGS " | grep "[[ ]]$]_LT_AC_TAGVAR(lt_prog_cc_shlib, $1)[[[ ]]" >/dev/null; then : else AC_MSG_WARN([add `$_LT_AC_TAGVAR(lt_prog_cc_shlib, $1)' to the CC or CFLAGS env variable and reconfigure]) _LT_AC_TAGVAR(lt_cv_prog_cc_can_build_shared, $1)=no fi fi # # Check to make sure the static flag actually works. # AC_LIBTOOL_LINKER_OPTION([if $compiler static flag $_LT_AC_TAGVAR(lt_prog_compiler_static, $1) works], _LT_AC_TAGVAR(lt_prog_compiler_static_works, $1), $_LT_AC_TAGVAR(lt_prog_compiler_static, $1), [], [_LT_AC_TAGVAR(lt_prog_compiler_static, $1)=]) ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... AC_LIBTOOL_PROG_COMPILER_NO_RTTI($1) AC_LIBTOOL_PROG_COMPILER_PIC($1) AC_LIBTOOL_PROG_CC_C_O($1) AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1) AC_LIBTOOL_PROG_LD_SHLIBS($1) AC_LIBTOOL_SYS_DYNAMIC_LINKER($1) AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1) AC_LIBTOOL_SYS_LIB_STRIP AC_LIBTOOL_DLOPEN_SELF($1) # Report which librarie types wil actually be built AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case "$host_os" in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix4*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; darwin* | rhapsody*) if test "$GCC" = yes; then _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no case "$host_os" in rhapsody* | darwin1.[[012]]) _LT_AC_TAGVAR(allow_undefined_flag, $1)='-undefined suppress' ;; *) # Darwin 1.3 on if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then _LT_AC_TAGVAR(allow_undefined_flag, $1)='-flat_namespace -undefined suppress' else case ${MACOSX_DEPLOYMENT_TARGET} in 10.[[012]]) _LT_AC_TAGVAR(allow_undefined_flag, $1)='-flat_namespace -undefined suppress' ;; 10.*) _LT_AC_TAGVAR(allow_undefined_flag, $1)='-undefined dynamic_lookup' ;; esac fi ;; esac output_verbose_link_cmd='echo' _LT_AC_TAGVAR(archive_cmds, $1)='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs$compiler_flags -install_name $rpath/$soname $verstring' _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs$compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' _LT_AC_TAGVAR(hardcode_direct, $1)=no _LT_AC_TAGVAR(hardcode_automatic, $1)=yes _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-all_load $convenience' _LT_AC_TAGVAR(link_all_deplibs, $1)=yes else _LT_AC_TAGVAR(ld_shlibs, $1)=no fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes AC_MSG_RESULT([$enable_static]) AC_LIBTOOL_CONFIG($1) AC_LANG_POP CC="$lt_save_CC" ])# AC_LIBTOOL_LANG_C_CONFIG # AC_LIBTOOL_LANG_CXX_CONFIG # -------------------------- # Ensure that the configuration vars for the C compiler are # suitably defined. Those variables are subsequently used by # AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'. AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG], [_LT_AC_LANG_CXX_CONFIG(CXX)]) AC_DEFUN([_LT_AC_LANG_CXX_CONFIG], [AC_LANG_PUSH(C++) AC_REQUIRE([AC_PROG_CXX]) AC_REQUIRE([AC_PROG_CXXCPP]) _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no _LT_AC_TAGVAR(allow_undefined_flag, $1)= _LT_AC_TAGVAR(always_export_symbols, $1)=no _LT_AC_TAGVAR(archive_expsym_cmds, $1)= _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)= _LT_AC_TAGVAR(hardcode_direct, $1)=no _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= _LT_AC_TAGVAR(hardcode_libdir_separator, $1)= _LT_AC_TAGVAR(hardcode_minus_L, $1)=no _LT_AC_TAGVAR(hardcode_automatic, $1)=no _LT_AC_TAGVAR(module_cmds, $1)= _LT_AC_TAGVAR(module_expsym_cmds, $1)= _LT_AC_TAGVAR(link_all_deplibs, $1)=unknown _LT_AC_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_AC_TAGVAR(no_undefined_flag, $1)= _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Dependencies to place before and after the object being linked: _LT_AC_TAGVAR(predep_objects, $1)= _LT_AC_TAGVAR(postdep_objects, $1)= _LT_AC_TAGVAR(predeps, $1)= _LT_AC_TAGVAR(postdeps, $1)= _LT_AC_TAGVAR(compiler_lib_search_path, $1)= # Source file extension for C++ test sources. ac_ext=cc # Object file extension for compiled C++ test sources. objext=o _LT_AC_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;\n" # Code to be used in simple link tests lt_simple_link_test_code='int main(int, char *[]) { return(0); }\n' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_AC_SYS_COMPILER # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_LD=$LD lt_save_GCC=$GCC GCC=$GXX lt_save_with_gnu_ld=$with_gnu_ld lt_save_path_LD=$lt_cv_path_LD if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx else unset lt_cv_prog_gnu_ld fi if test -n "${lt_cv_path_LDCXX+set}"; then lt_cv_path_LD=$lt_cv_path_LDCXX else unset lt_cv_path_LD fi test -z "${LDCXX+set}" || LD=$LDCXX CC=${CXX-"c++"} compiler=$CC _LT_AC_TAGVAR(compiler, $1)=$CC cc_basename=`$echo X"$compiler" | $Xsed -e 's%^.*/%%'` # We don't want -fno-exception wen compiling C++ code, so set the # no_builtin_flag separately if test "$GXX" = yes; then _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' else _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= fi if test "$GXX" = yes; then # Set up default GNU C++ configuration AC_PROG_LD # Check if GNU C++ uses GNU ld as the underlying linker, since the # archiving commands below assume that GNU ld is being used. if test "$with_gnu_ld" = yes; then _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' # If archive_cmds runs LD, not CC, wlarc should be empty # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to # investigate it a little bit more. (MM) wlarc='${wl}' # ancient GNU ld didn't support --whole-archive et. al. if eval "`$CC -print-prog-name=ld` --help 2>&1" | \ grep 'no-whole-archive' > /dev/null; then _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= fi else with_gnu_ld=no wlarc= # A generic and very simple default shared library creation # command for GNU C++ for the case where it uses the native # linker, instead of GNU ld. If possible, this setting should # overridden to take advantage of the native linker features on # the platform it is being used on. _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' fi # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' else GXX=no with_gnu_ld=no wlarc= fi # PORTME: fill in a description of your system's C++ link characteristics AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) _LT_AC_TAGVAR(ld_shlibs, $1)=yes case $host_os in aix3*) # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; 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 exp_sym_flag='-Bexport' no_entry_flag="" else aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[[23]]|aix4.[[23]].*|aix5*) for ld_flag in $LDFLAGS; do case $ld_flag in *-brtl*) aix_use_runtimelinking=yes break ;; esac done esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. _LT_AC_TAGVAR(archive_cmds, $1)='' _LT_AC_TAGVAR(hardcode_direct, $1)=yes _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_AC_TAGVAR(link_all_deplibs, $1)=yes if test "$GXX" = yes; then case $host_os in aix4.[012]|aix4.[012].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && \ strings "$collect2name" | grep resolve_lib_name >/dev/null then # We have reworked collect2 _LT_AC_TAGVAR(hardcode_direct, $1)=yes else # We have old collect2 _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)= fi esac shared_flag='-shared' else # not using gcc if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi fi # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. _LT_AC_TAGVAR(always_export_symbols, $1)=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. _LT_AC_TAGVAR(allow_undefined_flag, $1)='-berok' # Determine the default libpath from the value encoded in an empty executable. _LT_AC_SYS_LIBPATH_AIX _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' _LT_AC_TAGVAR(allow_undefined_flag, $1)="-z nodefs" _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an empty executable. _LT_AC_SYS_LIBPATH_AIX _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' # -bexpall does not export symbols beginning with underscore (_) _LT_AC_TAGVAR(always_export_symbols, $1)=yes # Exported symbols can be pulled into shared objects from archives _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=' ' _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes # This is similar to how AIX traditionally builds it's shared libraries. _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; chorus*) case $cc_basename in *) # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; esac ;; cygwin* | mingw* | pw32*) # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, # as there is no search path for DLLs. _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_AC_TAGVAR(always_export_symbols, $1)=no _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... _LT_AC_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib' else _LT_AC_TAGVAR(ld_shlibs, $1)=no fi ;; darwin* | rhapsody*) if test "$GXX" = yes; then _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no case "$host_os" in rhapsody* | darwin1.[[012]]) _LT_AC_TAGVAR(allow_undefined_flag, $1)='-undefined suppress' ;; *) # Darwin 1.3 on if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then _LT_AC_TAGVAR(allow_undefined_flag, $1)='-flat_namespace -undefined suppress' else case ${MACOSX_DEPLOYMENT_TARGET} in 10.[[012]]) _LT_AC_TAGVAR(allow_undefined_flag, $1)='-flat_namespace -undefined suppress' ;; 10.*) _LT_AC_TAGVAR(allow_undefined_flag, $1)='-undefined dynamic_lookup' ;; esac fi ;; esac lt_int_apple_cc_single_mod=no output_verbose_link_cmd='echo' if $CC -dumpspecs 2>&1 | grep 'single_module' >/dev/null ; then lt_int_apple_cc_single_mod=yes fi if test "X$lt_int_apple_cc_single_mod" = Xyes ; then _LT_AC_TAGVAR(archive_cmds, $1)='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' else _LT_AC_TAGVAR(archive_cmds, $1)='$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring' fi _LT_AC_TAGVAR(module_cmds, $1)='$CC ${wl}-bind_at_load $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's if test "X$lt_int_apple_cc_single_mod" = Xyes ; then _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' else _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' fi _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' _LT_AC_TAGVAR(hardcode_direct, $1)=no _LT_AC_TAGVAR(hardcode_automatic, $1)=yes _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-all_load $convenience' _LT_AC_TAGVAR(link_all_deplibs, $1)=yes else _LT_AC_TAGVAR(ld_shlibs, $1)=no fi ;; dgux*) case $cc_basename in ec++) # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; ghcx) # Green Hills C++ Compiler # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; esac ;; freebsd[12]*) # C++ shared libraries reported to be fairly broken before switch to ELF _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; freebsd-elf*) _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no ;; freebsd* | kfreebsd*-gnu) # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF # conventions _LT_AC_TAGVAR(ld_shlibs, $1)=yes ;; gnu*) ;; hpux9*) _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' _LT_AC_TAGVAR(hardcode_direct, $1)=yes _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, # but as the default # location of the library. case $cc_basename in CC) # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; aCC) _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | egrep "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' ;; *) if test "$GXX" = yes; then _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; hpux10*|hpux11*) if test $with_gnu_ld = no; then case "$host_cpu" in hppa*64*) _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: ;; ia64*) _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' ;; *) _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' ;; esac fi case "$host_cpu" in hppa*64*) _LT_AC_TAGVAR(hardcode_direct, $1)=no _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no ;; ia64*) _LT_AC_TAGVAR(hardcode_direct, $1)=no _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, # but as the default # location of the library. ;; *) _LT_AC_TAGVAR(hardcode_direct, $1)=yes _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, # but as the default # location of the library. ;; esac case $cc_basename in CC) # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; aCC) case "$host_cpu" in hppa*64*|ia64*) _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname -o $lib $linker_flags $libobjs $deplibs' ;; *) _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' ;; *) if test "$GXX" = yes; then if test $with_gnu_ld = no; then case "$host_cpu" in ia64*|hppa*64*) _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname -o $lib $linker_flags $libobjs $deplibs' ;; *) _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac fi else # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; irix5* | irix6*) case $cc_basename in CC) # SGI C++ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib' # Archives containing C++ object files must be created using # "CC -ar", where "CC" is the IRIX C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' ;; *) if test "$GXX" = yes; then if test "$with_gnu_ld" = no; then _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib' else _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` -o $lib' fi fi _LT_AC_TAGVAR(link_all_deplibs, $1)=yes ;; esac _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: ;; linux*) case $cc_basename in KCC) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | grep "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath,$libdir' _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' # Archives containing C++ object files must be created using # "CC -Bstatic", where "CC" is the KAI C++ compiler. _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; icpc) # Intel C++ with_gnu_ld=yes _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' ;; cxx) # Compaq C++ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols' runpath_var=LD_RUN_PATH _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' ;; esac ;; lynxos*) # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; m88k*) # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; mvs*) case $cc_basename in cxx) # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; esac ;; netbsd*) if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' wlarc= _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_AC_TAGVAR(hardcode_direct, $1)=yes _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no fi # Workaround some broken pre-1.5 toolchains output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' ;; osf3*) case $cc_basename in KCC) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: # Archives containing C++ object files must be created using # "CC -Bstatic", where "CC" is the KAI C++ compiler. _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; RCC) # Rational C++ 2.4.1 # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; cxx) _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && echo ${wl}-set_version $verstring` -update_registry ${objdir}/so_locations -o $lib' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' ;; *) if test "$GXX" = yes && test "$with_gnu_ld" = no; then _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' else # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; osf4* | osf5*) case $cc_basename in KCC) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: # Archives containing C++ object files must be created using # the KAI C++ compiler. _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;; RCC) # Rational C++ 2.4.1 # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; cxx) _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ echo "-hidden">> $lib.exp~ $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname -Wl,-input -Wl,$lib.exp `test -n "$verstring" && echo -set_version $verstring` -update_registry $objdir/so_locations -o $lib~ $rm $lib.exp' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' ;; *) if test "$GXX" = yes && test "$with_gnu_ld" = no; then _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' else # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; psos*) # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; sco*) _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no case $cc_basename in CC) # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; esac ;; sunos4*) case $cc_basename in CC) # Sun C++ 4.x # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; lcc) # Lucid # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; esac ;; solaris*) case $cc_basename in CC) # Sun C++ 4.2, 5.x and Centerline C++ _LT_AC_TAGVAR(no_undefined_flag, $1)=' -zdefs' _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -nolib -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $CC -G${allow_undefined_flag} -nolib ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no case $host_os in solaris2.[0-5] | solaris2.[0-5].*) ;; *) # The C++ compiler is used as linker so we must use $wl # flag to pass the commands to the underlying system # linker. # Supported since Solaris 2.6 (maybe 2.5.1?) _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' ;; esac _LT_AC_TAGVAR(link_all_deplibs, $1)=yes # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -G $CFLAGS -v conftest.$objext 2>&1 | grep "\-[[LR]]"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' ;; gcx) # Green Hills C++ Compiler _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' # The C++ compiler must be used to create the archive. _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' ;; *) # GNU C++ compiler with Solaris linker if test "$GXX" = yes && test "$with_gnu_ld" = no; then _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs' if $CC --version | grep -v '^2\.7' > /dev/null; then _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $CC -shared -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd="$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\"" else # g++ 2.7 appears to require `-G' NOT `-shared' on this # platform. _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd="$CC -G $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\"" fi _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir' fi ;; esac ;; sysv5OpenUNIX8* | sysv5UnixWare7* | sysv5uw[[78]]* | unixware7*) _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no ;; tandem*) case $cc_basename in NCC) # NonStop-UX NCC 3.20 # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; esac ;; vxworks*) # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; esac AC_MSG_RESULT([$_LT_AC_TAGVAR(ld_shlibs, $1)]) test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no _LT_AC_TAGVAR(GCC, $1)="$GXX" _LT_AC_TAGVAR(LD, $1)="$LD" ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... AC_LIBTOOL_POSTDEP_PREDEP($1) AC_LIBTOOL_PROG_COMPILER_PIC($1) AC_LIBTOOL_PROG_CC_C_O($1) AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1) AC_LIBTOOL_PROG_LD_SHLIBS($1) AC_LIBTOOL_SYS_DYNAMIC_LINKER($1) AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1) AC_LIBTOOL_SYS_LIB_STRIP AC_LIBTOOL_DLOPEN_SELF($1) AC_LIBTOOL_CONFIG($1) AC_LANG_POP CC=$lt_save_CC LDCXX=$LD LD=$lt_save_LD GCC=$lt_save_GCC with_gnu_ldcxx=$with_gnu_ld with_gnu_ld=$lt_save_with_gnu_ld lt_cv_path_LDCXX=$lt_cv_path_LD lt_cv_path_LD=$lt_save_path_LD lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld ])# AC_LIBTOOL_LANG_CXX_CONFIG # AC_LIBTOOL_POSTDEP_PREDEP([TAGNAME]) # ------------------------ # Figure out "hidden" library dependencies from verbose # compiler output when linking a shared library. # Parse the compiler output and extract the necessary # objects, libraries and library flags. AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP],[ dnl we can't use the lt_simple_compile_test_code here, dnl because it contains code intended for an executable, dnl not a library. It's possible we should let each dnl tag define a new lt_????_link_test_code variable, dnl but it's only used here... ifelse([$1],[],[cat > conftest.$ac_ext < conftest.$ac_ext < conftest.$ac_ext < conftest.$ac_ext <> "$cfgfile" ifelse([$1], [], [#! $SHELL # `$echo "$cfgfile" | sed 's%^.*/%%'` - Provide generalized library-building support services. # Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP) # NOTE: Changes made to this file will be lost: look at ltmain.sh. # # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 # Free Software Foundation, Inc. # # This file is part of GNU Libtool: # 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. # A sed program that does not truncate output. SED=$lt_SED # Sed that helps us avoid accidentally triggering echo(1) options like -n. Xsed="$SED -e s/^X//" # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. if test "X\${CDPATH+set}" = Xset; then CDPATH=:; export CDPATH; fi # The names of the tagged configurations supported by this script. available_tags= # ### BEGIN LIBTOOL CONFIG], [# ### BEGIN LIBTOOL TAG CONFIG: $tagname]) # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # Shell to use when invoking shell scripts. SHELL=$lt_SHELL # Whether or not to build shared libraries. build_libtool_libs=$enable_shared # Whether or not to build static libraries. build_old_libs=$enable_static # Whether or not to add -lc for building shared libraries. build_libtool_need_lc=$_LT_AC_TAGVAR(archive_cmds_need_lc, $1) # Whether or not to disallow shared libs when runtime libs are static allow_libtool_libs_with_static_runtimes=$_LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1) # Whether or not to optimize for fast installation. fast_install=$enable_fast_install # The host system. host_alias=$host_alias host=$host # An echo program that does not interpret backslashes. echo=$lt_echo # The archiver. AR=$lt_AR AR_FLAGS=$lt_AR_FLAGS # A C compiler. LTCC=$lt_LTCC # A language-specific compiler. CC=$lt_[]_LT_AC_TAGVAR(compiler, $1) # Is the compiler the GNU C compiler? with_gcc=$_LT_AC_TAGVAR(GCC, $1) # An ERE matcher. EGREP=$lt_EGREP # The linker used to build libraries. LD=$lt_[]_LT_AC_TAGVAR(LD, $1) # Whether we need hard or soft links. LN_S=$lt_LN_S # A BSD-compatible nm program. NM=$lt_NM # A symbol stripping program STRIP=$STRIP # Used to examine libraries when file_magic_cmd begins "file" MAGIC_CMD=$MAGIC_CMD # Used on cygwin: DLL creation program. DLLTOOL="$DLLTOOL" # Used on cygwin: object dumper. OBJDUMP="$OBJDUMP" # Used on cygwin: assembler. AS="$AS" # The name of the directory that contains temporary libtool files. objdir=$objdir # How to create reloadable object files. reload_flag=$lt_reload_flag reload_cmds=$lt_reload_cmds # How to pass a linker flag through the compiler. wl=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_wl, $1) # Object file suffix (normally "o"). objext="$ac_objext" # Old archive suffix (normally "a"). libext="$libext" # Shared library suffix (normally ".so"). shrext='$shrext' # Executable file suffix (normally ""). exeext="$exeext" # Additional compiler flags for building library objects. pic_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) pic_mode=$pic_mode # What is the maximum length of a command? max_cmd_len=$lt_cv_sys_max_cmd_len # Does compiler simultaneously support -c and -o options? compiler_c_o=$lt_[]_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1) # Must we lock files when doing compilation ? need_locks=$lt_need_locks # Do we need the lib prefix for modules? need_lib_prefix=$need_lib_prefix # Do we need a version for libraries? need_version=$need_version # Whether dlopen is supported. dlopen_support=$enable_dlopen # Whether dlopen of programs is supported. dlopen_self=$enable_dlopen_self # Whether dlopen of statically linked programs is supported. dlopen_self_static=$enable_dlopen_self_static # Compiler flag to prevent dynamic linking. link_static_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_static, $1) # Compiler flag to turn off builtin functions. no_builtin_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) # Compiler flag to allow reflexive dlopens. export_dynamic_flag_spec=$lt_[]_LT_AC_TAGVAR(export_dynamic_flag_spec, $1) # Compiler flag to generate shared objects directly from archives. whole_archive_flag_spec=$lt_[]_LT_AC_TAGVAR(whole_archive_flag_spec, $1) # Compiler flag to generate thread-safe objects. thread_safe_flag_spec=$lt_[]_LT_AC_TAGVAR(thread_safe_flag_spec, $1) # Library versioning type. version_type=$version_type # Format of library name prefix. libname_spec=$lt_libname_spec # List of archive names. First name is the real one, the rest are links. # The last name is the one that the linker finds with -lNAME. library_names_spec=$lt_library_names_spec # The coded name of the library, if different from the real name. soname_spec=$lt_soname_spec # Commands used to build and install an old-style archive. RANLIB=$lt_RANLIB old_archive_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_cmds, $1) old_postinstall_cmds=$lt_old_postinstall_cmds old_postuninstall_cmds=$lt_old_postuninstall_cmds # Create an old-style archive from a shared archive. old_archive_from_new_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_from_new_cmds, $1) # Create a temporary old-style archive to link instead of a shared archive. old_archive_from_expsyms_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1) # Commands used to build and install a shared archive. archive_cmds=$lt_[]_LT_AC_TAGVAR(archive_cmds, $1) archive_expsym_cmds=$lt_[]_LT_AC_TAGVAR(archive_expsym_cmds, $1) postinstall_cmds=$lt_postinstall_cmds postuninstall_cmds=$lt_postuninstall_cmds # Commands used to build a loadable module (assumed same as above if empty) module_cmds=$lt_[]_LT_AC_TAGVAR(module_cmds, $1) module_expsym_cmds=$lt_[]_LT_AC_TAGVAR(module_expsym_cmds, $1) # Commands to strip libraries. old_striplib=$lt_old_striplib striplib=$lt_striplib # Dependencies to place before the objects being linked to create a # shared library. predep_objects=$lt_[]_LT_AC_TAGVAR(predep_objects, $1) # Dependencies to place after the objects being linked to create a # shared library. postdep_objects=$lt_[]_LT_AC_TAGVAR(postdep_objects, $1) # Dependencies to place before the objects being linked to create a # shared library. predeps=$lt_[]_LT_AC_TAGVAR(predeps, $1) # Dependencies to place after the objects being linked to create a # shared library. postdeps=$lt_[]_LT_AC_TAGVAR(postdeps, $1) # The library search path used internally by the compiler when linking # a shared library. compiler_lib_search_path=$lt_[]_LT_AC_TAGVAR(compiler_lib_search_path, $1) # Method to check whether dependent libraries are shared objects. deplibs_check_method=$lt_deplibs_check_method # Command to use when deplibs_check_method == file_magic. file_magic_cmd=$lt_file_magic_cmd # Flag that allows shared libraries with undefined symbols to be built. allow_undefined_flag=$lt_[]_LT_AC_TAGVAR(allow_undefined_flag, $1) # Flag that forces no undefined symbols. no_undefined_flag=$lt_[]_LT_AC_TAGVAR(no_undefined_flag, $1) # Commands used to finish a libtool library installation in a directory. finish_cmds=$lt_finish_cmds # Same as above, but a single script fragment to be evaled but not shown. finish_eval=$lt_finish_eval # Take the output of nm and produce a listing of raw symbols and C names. global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe # Transform the output of nm in a proper C declaration global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl # Transform the output of nm in a C name address pair global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address # This is the shared library runtime path variable. runpath_var=$runpath_var # This is the shared library path variable. shlibpath_var=$shlibpath_var # Is shlibpath searched before the hard-coded library search path? shlibpath_overrides_runpath=$shlibpath_overrides_runpath # How to hardcode a shared library path into an executable. hardcode_action=$_LT_AC_TAGVAR(hardcode_action, $1) # Whether we should hardcode library paths into libraries. hardcode_into_libs=$hardcode_into_libs # Flag to hardcode \$libdir into a binary during linking. # This must work even if \$libdir does not exist. hardcode_libdir_flag_spec=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) # If ld is used when linking, flag to hardcode \$libdir into # a binary during linking. This must work even if \$libdir does # not exist. hardcode_libdir_flag_spec_ld=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1) # Whether we need a single -rpath flag with a separated argument. hardcode_libdir_separator=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_separator, $1) # Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the # resulting binary. hardcode_direct=$_LT_AC_TAGVAR(hardcode_direct, $1) # Set to yes if using the -LDIR flag during linking hardcodes DIR into the # resulting binary. hardcode_minus_L=$_LT_AC_TAGVAR(hardcode_minus_L, $1) # Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into # the resulting binary. hardcode_shlibpath_var=$_LT_AC_TAGVAR(hardcode_shlibpath_var, $1) # Set to yes if building a shared library automatically hardcodes DIR into the library # and all subsequent libraries and executables linked against it. hardcode_automatic=$_LT_AC_TAGVAR(hardcode_automatic, $1) # Variables whose values should be saved in libtool wrapper scripts and # restored at relink time. variables_saved_for_relink="$variables_saved_for_relink" # Whether libtool must link a program against all its dependency libraries. link_all_deplibs=$_LT_AC_TAGVAR(link_all_deplibs, $1) # Compile-time system search path for libraries sys_lib_search_path_spec=$lt_sys_lib_search_path_spec # Run-time system search path for libraries sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec # Fix the shell variable \$srcfile for the compiler. fix_srcfile_path="$_LT_AC_TAGVAR(fix_srcfile_path, $1)" # Set to yes if exported symbols are required. always_export_symbols=$_LT_AC_TAGVAR(always_export_symbols, $1) # The commands to list exported symbols. export_symbols_cmds=$lt_[]_LT_AC_TAGVAR(export_symbols_cmds, $1) # The commands to extract the exported symbol list from a shared archive. extract_expsyms_cmds=$lt_extract_expsyms_cmds # Symbols that should not be listed in the preloaded symbols. exclude_expsyms=$lt_[]_LT_AC_TAGVAR(exclude_expsyms, $1) # Symbols that must always be exported. include_expsyms=$lt_[]_LT_AC_TAGVAR(include_expsyms, $1) ifelse([$1],[], [# ### END LIBTOOL CONFIG], [# ### END LIBTOOL TAG CONFIG: $tagname]) __EOF__ ifelse([$1],[], [ case $host_os in aix3*) cat <<\EOF >> "$cfgfile" # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi EOF ;; esac # We use sed instead of cat because bash on DJGPP gets confused if # if finds mixed CR/LF and LF-only lines. Since sed operates in # text mode, it properly converts lines to CR/LF. This bash problem # is reportedly fixed, but why not run on old versions too? sed '$q' "$ltmain" >> "$cfgfile" || (rm -f "$cfgfile"; exit 1) mv -f "$cfgfile" "$ofile" || \ (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") chmod +x "$ofile" ]) else # If there is no Makefile yet, we rely on a make rule to execute # `config.status --recheck' to rerun these tests and create the # libtool script then. test -f Makefile && make "$ltmain" fi ])# AC_LIBTOOL_CONFIG # AC_LIBTOOL_PROG_COMPILER_NO_RTTI([TAGNAME]) # ------------------------------------------- AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= if test "$GCC" = yes; then _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' AC_LIBTOOL_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], lt_cv_prog_compiler_rtti_exceptions, [-fno-rtti -fno-exceptions], [], [_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) fi ])# AC_LIBTOOL_PROG_COMPILER_NO_RTTI # AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE # --------------------------------- AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_REQUIRE([AC_CANONICAL_HOST]) AC_REQUIRE([AC_PROG_NM]) AC_REQUIRE([AC_OBJEXT]) # Check for command to grab the raw symbol name followed by C symbol from nm. AC_MSG_CHECKING([command to parse $NM output from $compiler object]) AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], [ # These are sane defaults that work on at least a few old systems. # [They come from Ultrix. What could be older than Ultrix?!! ;)] # Character class describing NM global symbol codes. symcode='[[BCDEGRST]]' # Regexp to match symbols that can be accessed directly from C. sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' # Transform the above into a raw symbol and a C symbol. symxfrm='\1 \2\3 \3' # Transform an extracted symbol line into a proper C declaration lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern int \1;/p'" # Transform an extracted symbol line into symbol name and symbol address lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" # Define system-specific variables. case $host_os in aix*) symcode='[[BCDT]]' ;; cygwin* | mingw* | pw32*) symcode='[[ABCDGISTW]]' ;; hpux*) # Its linker distinguishes data from code symbols if test "$host_cpu" = ia64; then symcode='[[ABCDEGRST]]' fi lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" ;; irix* | nonstopux*) symcode='[[BCDEGRST]]' ;; osf*) symcode='[[BCDEGQRST]]' ;; solaris* | sysv5*) symcode='[[BDT]]' ;; sysv4) symcode='[[DFNSTU]]' ;; esac # Handle CRLF in mingw tool chain opt_cr= case $build_os in mingw*) opt_cr=`echo 'x\{0,1\}' | tr x '\015'` # option cr in regexp ;; esac # If we're using GNU nm, then use its standard symbol codes. case `$NM -V 2>&1` in *GNU* | *'with BFD'*) symcode='[[ABCDGISTW]]' ;; esac # Try without a prefix undercore, then with it. for ac_symprfx in "" "_"; do # Write the raw and C identifiers. lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*\($ac_symprfx\)$sympat$opt_cr$/$symxfrm/p'" # Check to see that the pipe works correctly. pipe_works=no rm -f conftest* cat > conftest.$ac_ext < $nlist) && test -s "$nlist"; then # Try sorting and uniquifying the output. if sort "$nlist" | uniq > "$nlist"T; then mv -f "$nlist"T "$nlist" else rm -f "$nlist"T fi # Make sure that we snagged all the symbols we need. if grep ' nm_test_var$' "$nlist" >/dev/null; then if grep ' nm_test_func$' "$nlist" >/dev/null; then cat < conftest.$ac_ext #ifdef __cplusplus extern "C" { #endif EOF # Now generate the symbol file. eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | grep -v main >> conftest.$ac_ext' cat <> conftest.$ac_ext #if defined (__STDC__) && __STDC__ # define lt_ptr_t void * #else # define lt_ptr_t char * # define const #endif /* The mapping between symbol names and symbols. */ const struct { const char *name; lt_ptr_t address; } lt_preloaded_symbols[[]] = { EOF $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (lt_ptr_t) \&\2},/" < "$nlist" | grep -v main >> conftest.$ac_ext cat <<\EOF >> conftest.$ac_ext {0, (lt_ptr_t) 0} }; #ifdef __cplusplus } #endif EOF # Now try linking the two files. mv conftest.$ac_objext conftstm.$ac_objext lt_save_LIBS="$LIBS" lt_save_CFLAGS="$CFLAGS" LIBS="conftstm.$ac_objext" CFLAGS="$CFLAGS$_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then pipe_works=yes fi LIBS="$lt_save_LIBS" CFLAGS="$lt_save_CFLAGS" else echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD fi else echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD fi else echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD fi else echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD cat conftest.$ac_ext >&5 fi rm -f conftest* conftst* # Do not use the global_symbol_pipe unless it works. if test "$pipe_works" = yes; then break else lt_cv_sys_global_symbol_pipe= fi done ]) if test -z "$lt_cv_sys_global_symbol_pipe"; then lt_cv_sys_global_symbol_to_cdecl= fi if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then AC_MSG_RESULT(failed) else AC_MSG_RESULT(ok) fi ]) # AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE # AC_LIBTOOL_PROG_COMPILER_PIC([TAGNAME]) # --------------------------------------- AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC], [_LT_AC_TAGVAR(lt_prog_compiler_wl, $1)= _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= _LT_AC_TAGVAR(lt_prog_compiler_static, $1)= AC_MSG_CHECKING([for $compiler option to produce PIC]) ifelse([$1],[CXX],[ # C++ specific cases for pic, static, wl, etc. if test "$GXX" = yes; then _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' case $host_os in aix*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi ;; amigaos*) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' ;; beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | os2* | pw32*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT' ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' ;; *djgpp*) # DJGPP does not support shared libraries at all _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= ;; sysv4*MP*) if test -d /usr/nec; then _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic fi ;; hpux*) # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case "$host_cpu" in hppa*64*|ia64*) ;; *) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac ;; *) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac else case $host_os in aix4* | aix5*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' else _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' fi ;; chorus*) case $cc_basename in cxch68) # Green Hills C++ Compiler # _LT_AC_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" ;; esac ;; dgux*) case $cc_basename in ec++) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' ;; ghcx) # Green Hills C++ Compiler _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; *) ;; esac ;; freebsd* | kfreebsd*-gnu) # FreeBSD uses GNU C++ ;; hpux9* | hpux10* | hpux11*) case $cc_basename in CC) _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_AC_TAGVAR(lt_prog_compiler_static, $1)="${ac_cv_prog_cc_wl}-a ${ac_cv_prog_cc_wl}archive" if test "$host_cpu" != ia64; then _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z' fi ;; aCC) _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_AC_TAGVAR(lt_prog_compiler_static, $1)="${ac_cv_prog_cc_wl}-a ${ac_cv_prog_cc_wl}archive" case "$host_cpu" in hppa*64*|ia64*) # +Z the default ;; *) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z' ;; esac ;; *) ;; esac ;; irix5* | irix6* | nonstopux*) case $cc_basename in CC) _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' # CC pic flag -KPIC is the default. ;; *) ;; esac ;; linux*) case $cc_basename in KCC) # KAI C++ Compiler _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; icpc) # Intel C++ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; cxx) # Compaq C++ # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; *) ;; esac ;; lynxos*) ;; m88k*) ;; mvs*) case $cc_basename in cxx) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' ;; *) ;; esac ;; netbsd*) ;; osf3* | osf4* | osf5*) case $cc_basename in KCC) _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' ;; RCC) # Rational C++ 2.4.1 _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; cxx) # Digital/Compaq C++ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; *) ;; esac ;; psos*) ;; sco*) case $cc_basename in CC) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; *) ;; esac ;; solaris*) case $cc_basename in CC) # Sun C++ 4.2, 5.x and Centerline C++ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; gcx) # Green Hills C++ Compiler _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' ;; *) ;; esac ;; sunos4*) case $cc_basename in CC) # Sun C++ 4.x _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; lcc) # Lucid _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; *) ;; esac ;; tandem*) case $cc_basename in NCC) # NonStop-UX NCC 3.20 _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' ;; *) ;; esac ;; unixware*) ;; vxworks*) ;; *) _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; esac fi ], [ if test "$GCC" = yes; then _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' case $host_os in aix*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi ;; amigaos*) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' ;; beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | pw32* | os2*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT' ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' ;; msdosdjgpp*) # Just because we use GCC doesn't mean we suddenly get shared libraries # on systems that don't support them. _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no enable_shared=no ;; sysv4*MP*) if test -d /usr/nec; then _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic fi ;; hpux*) # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case "$host_cpu" in hppa*64*|ia64*) # +Z the default ;; *) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac ;; *) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in aix*) _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' else _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' fi ;; mingw* | pw32* | os2*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT' ;; hpux9* | hpux10* | hpux11*) _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case "$host_cpu" in hppa*64*|ia64*) # +Z the default ;; *) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z' ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # PIC (with -KPIC) is the default. _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; newsos6) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; linux*) case $CC in icc* | ecc*) _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; ccc*) _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # All Alpha code is PIC. _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; esac ;; osf3* | osf4* | osf5*) _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # All OSF/1 code is PIC. _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; sco3.2v5*) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-Kpic' _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-dn' ;; solaris*) _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; sunos4*) _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec ;then _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi ;; uts4*) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; *) _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; esac fi ]) AC_MSG_RESULT([$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)]) # # Check to make sure the PIC flag actually works. # if test -n "$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)"; then AC_LIBTOOL_COMPILER_OPTION([if $compiler PIC flag $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) works], _LT_AC_TAGVAR(lt_prog_compiler_pic_works, $1), [$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)ifelse([$1],[],[ -DPIC],[ifelse([$1],[CXX],[ -DPIC],[])])], [], [case $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) in "" | " "*) ;; *) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)" ;; esac], [_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) fi case "$host_os" in # For platforms which do not support PIC, -DPIC is meaningless: *djgpp*) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= ;; *) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)ifelse([$1],[],[ -DPIC],[ifelse([$1],[CXX],[ -DPIC],[])])" ;; esac ]) # AC_LIBTOOL_PROG_LD_SHLIBS([TAGNAME]) # ------------------------------------ # See if the linker supports building shared libraries. AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) ifelse([$1],[CXX],[ _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' case $host_os in aix4* | aix5*) # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm if $NM -V 2>&1 | grep 'GNU' > /dev/null; then _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' else _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' fi ;; pw32*) _LT_AC_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds" ;; cygwin* | mingw*) _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGS]] /s/.* \([[^ ]]*\)/\1 DATA/'\'' | $SED -e '\''/^[[AITW]] /s/.* //'\'' | sort | uniq > $export_symbols' ;; *) _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' ;; esac ],[ runpath_var= _LT_AC_TAGVAR(allow_undefined_flag, $1)= _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no _LT_AC_TAGVAR(archive_cmds, $1)= _LT_AC_TAGVAR(archive_expsym_cmds, $1)= _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)= _LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1)= _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)= _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= _LT_AC_TAGVAR(thread_safe_flag_spec, $1)= _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= _LT_AC_TAGVAR(hardcode_libdir_separator, $1)= _LT_AC_TAGVAR(hardcode_direct, $1)=no _LT_AC_TAGVAR(hardcode_minus_L, $1)=no _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_AC_TAGVAR(link_all_deplibs, $1)=unknown _LT_AC_TAGVAR(hardcode_automatic, $1)=no _LT_AC_TAGVAR(module_cmds, $1)= _LT_AC_TAGVAR(module_expsym_cmds, $1)= _LT_AC_TAGVAR(always_export_symbols, $1)=no _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list _LT_AC_TAGVAR(include_expsyms, $1)= # exclude_expsyms can be an extended regexp of symbols to exclude # it will be wrapped by ` (' and `)$', so one must not match beginning or # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', # as well as any symbol that contains `d'. _LT_AC_TAGVAR(exclude_expsyms, $1)="_GLOBAL_OFFSET_TABLE_" # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. extract_expsyms_cmds= 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 _LT_AC_TAGVAR(ld_shlibs, $1)=yes if test "$with_gnu_ld" = yes; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='${wl}' # See if GNU ld supports shared libraries. case $host_os in aix3* | aix4* | aix5*) # On AIX/PPC, the GNU linker is very broken if test "$host_cpu" != ia64; then _LT_AC_TAGVAR(ld_shlibs, $1)=no cat <&2 *** Warning: the GNU linker, at least up to release 2.9.1, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you *** really care for shared libraries, you may want to modify your PATH *** so that a non-GNU linker is found, and then restart. EOF fi ;; amigaos*) _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_AC_TAGVAR(hardcode_minus_L, $1)=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't use # them. _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; beos*) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME _LT_AC_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else _LT_AC_TAGVAR(ld_shlibs, $1)=no fi ;; cygwin* | mingw* | pw32*) # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, # as there is no search path for DLLs. _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_AC_TAGVAR(always_export_symbols, $1)=no _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGS]] /s/.* \([[^ ]]*\)/\1 DATA/'\'' | $SED -e '\''/^[[AITW]] /s/.* //'\'' | sort | uniq > $export_symbols' if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... _LT_AC_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib' else ld_shlibs=no fi ;; netbsd*) if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' fi ;; solaris* | sysv5*) if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then _LT_AC_TAGVAR(ld_shlibs, $1)=no cat <&2 *** Warning: The releases 2.8.* of the GNU linker cannot reliably *** create shared libraries on Solaris systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.9.1 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. EOF elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else _LT_AC_TAGVAR(ld_shlibs, $1)=no fi ;; sunos4*) _LT_AC_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= _LT_AC_TAGVAR(hardcode_direct, $1)=yes _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else _LT_AC_TAGVAR(ld_shlibs, $1)=no fi ;; esac if test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = yes; then runpath_var=LD_RUN_PATH _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= fi fi else # PORTME fill in a description of your system's linker (not GNU ld) case $host_os in aix3*) _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_AC_TAGVAR(always_export_symbols, $1)=yes _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes if test "$GCC" = yes && test -z "$link_static_flag"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. _LT_AC_TAGVAR(hardcode_direct, $1)=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 exp_sym_flag='-Bexport' no_entry_flag="" else # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm if $NM -V 2>&1 | grep 'GNU' > /dev/null; then _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' else _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # 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 exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. _LT_AC_TAGVAR(archive_cmds, $1)='' _LT_AC_TAGVAR(hardcode_direct, $1)=yes _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_AC_TAGVAR(link_all_deplibs, $1)=yes if test "$GCC" = yes; then case $host_os in aix4.[012]|aix4.[012].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && \ strings "$collect2name" | grep resolve_lib_name >/dev/null then # We have reworked collect2 _LT_AC_TAGVAR(hardcode_direct, $1)=yes else # We have old collect2 _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)= fi esac shared_flag='-shared' else # not using gcc if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi fi # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. _LT_AC_TAGVAR(always_export_symbols, $1)=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. _LT_AC_TAGVAR(allow_undefined_flag, $1)='-berok' # Determine the default libpath from the value encoded in an empty executable. _LT_AC_SYS_LIBPATH_AIX _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' _LT_AC_TAGVAR(allow_undefined_flag, $1)="-z nodefs" _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an empty executable. _LT_AC_SYS_LIBPATH_AIX _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' # -bexpall does not export symbols beginning with underscore (_) _LT_AC_TAGVAR(always_export_symbols, $1)=yes # Exported symbols can be pulled into shared objects from archives _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=' ' _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes # This is similar to how AIX traditionally builds it's shared libraries. _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; amigaos*) _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # see comment about different semantics on the GNU ld section _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; bsdi4*) _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic ;; 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. _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext=".dll" # FIXME: Setting linknames here is a bad hack. _LT_AC_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)='true' # FIXME: Should let the user specify the lib program. _LT_AC_TAGVAR(old_archive_cmds, $1)='lib /OUT:$oldlib$oldobjs$old_deplibs' fix_srcfile_path='`cygpath -w "$srcfile"`' _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes ;; darwin* | rhapsody*) if test "$GXX" = yes ; then _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no case "$host_os" in rhapsody* | darwin1.[[012]]) _LT_AC_TAGVAR(allow_undefined_flag, $1)='-undefined suppress' ;; *) # Darwin 1.3 on if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then _LT_AC_TAGVAR(allow_undefined_flag, $1)='-flat_namespace -undefined suppress' else case ${MACOSX_DEPLOYMENT_TARGET} in 10.[[012]]) _LT_AC_TAGVAR(allow_undefined_flag, $1)='-flat_namespace -undefined suppress' ;; 10.*) _LT_AC_TAGVAR(allow_undefined_flag, $1)='-undefined dynamic_lookup' ;; esac fi ;; esac lt_int_apple_cc_single_mod=no output_verbose_link_cmd='echo' if $CC -dumpspecs 2>&1 | grep 'single_module' >/dev/null ; then lt_int_apple_cc_single_mod=yes fi if test "X$lt_int_apple_cc_single_mod" = Xyes ; then _LT_AC_TAGVAR(archive_cmds, $1)='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' else _LT_AC_TAGVAR(archive_cmds, $1)='$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring' fi _LT_AC_TAGVAR(module_cmds, $1)='$CC ${wl}-bind_at_load $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's if test "X$lt_int_apple_cc_single_mod" = Xyes ; then _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' else _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' fi _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' _LT_AC_TAGVAR(hardcode_direct, $1)=no _LT_AC_TAGVAR(hardcode_automatic, $1)=yes _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-all_load $convenience' _LT_AC_TAGVAR(link_all_deplibs, $1)=yes else _LT_AC_TAGVAR(ld_shlibs, $1)=no fi ;; dgux*) _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no ;; freebsd1*) _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little # extra space). freebsd2.2*) _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_AC_TAGVAR(hardcode_direct, $1)=yes _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2*) _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' _LT_AC_TAGVAR(hardcode_direct, $1)=yes _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd* | kfreebsd*-gnu) _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_AC_TAGVAR(hardcode_direct, $1)=yes _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no ;; hpux9*) if test "$GCC" = yes; then _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' fi _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: _LT_AC_TAGVAR(hardcode_direct, $1)=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' ;; hpux10* | hpux11*) if test "$GCC" = yes -a "$with_gnu_ld" = no; then case "$host_cpu" in hppa*64*|ia64*) _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; *) _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case "$host_cpu" in hppa*64*|ia64*) _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname -o $lib $libobjs $deplibs $linker_flags' ;; *) _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' ;; esac fi if test "$with_gnu_ld" = no; then case "$host_cpu" in hppa*64*) _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: _LT_AC_TAGVAR(hardcode_direct, $1)=no _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no ;; ia64*) _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_AC_TAGVAR(hardcode_direct, $1)=no _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes ;; *) _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: _LT_AC_TAGVAR(hardcode_direct, $1)=yes _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) if test "$GCC" = yes; then _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='-rpath $libdir' fi _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: _LT_AC_TAGVAR(link_all_deplibs, $1)=yes ;; netbsd*) if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_AC_TAGVAR(hardcode_direct, $1)=yes _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no ;; newsos6) _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_AC_TAGVAR(hardcode_direct, $1)=yes _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no ;; openbsd*) _LT_AC_TAGVAR(hardcode_direct, $1)=yes _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' else case $host_os in openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*) _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' ;; *) _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' ;; esac fi ;; os2*) _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_AC_TAGVAR(archive_cmds, $1)='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' ;; osf3*) if test "$GCC" = yes; then _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' fi _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag if test "$GCC" = yes; then _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' else _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~ $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib~$rm $lib.exp' # Both c and cxx compiler support -rpath directly _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' fi _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: ;; sco3.2v5*) _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' runpath_var=LD_RUN_PATH hardcode_runpath_var=yes ;; solaris*) _LT_AC_TAGVAR(no_undefined_flag, $1)=' -z text' if test "$GCC" = yes; then _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp' else _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' fi _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) # Supported since Solaris 2.6 (maybe 2.5.1?) _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' ;; esac _LT_AC_TAGVAR(link_all_deplibs, $1)=yes ;; sunos4*) if test "x$host_vendor" = xsequent; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_AC_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_AC_TAGVAR(hardcode_direct, $1)=yes _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no ;; sysv4) case $host_vendor in sni) _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_AC_TAGVAR(hardcode_direct, $1)=yes # is this really true??? ;; siemens) ## LD is ld it makes a PLAMLIB ## CC just makes a GrossModule. _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' _LT_AC_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' _LT_AC_TAGVAR(hardcode_direct, $1)=no ;; motorola) _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_AC_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie ;; esac runpath_var='LD_RUN_PATH' _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no ;; sysv4.3*) _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' ;; sysv4*MP*) if test -d /usr/nec; then _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes _LT_AC_TAGVAR(ld_shlibs, $1)=yes fi ;; sysv4.2uw2*) _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' _LT_AC_TAGVAR(hardcode_direct, $1)=yes _LT_AC_TAGVAR(hardcode_minus_L, $1)=no _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no hardcode_runpath_var=yes runpath_var=LD_RUN_PATH ;; sysv5OpenUNIX8* | sysv5UnixWare7* | sysv5uw[[78]]* | unixware7*) _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z ${wl}text' if test "$GCC" = yes; then _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' fi runpath_var='LD_RUN_PATH' _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no ;; sysv5*) _LT_AC_TAGVAR(no_undefined_flag, $1)=' -z text' # $CC -shared without GNU ld will not create a library from C++ # object files and a static libstdc++, better avoid it by now _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var='LD_RUN_PATH' ;; uts4*) _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; esac fi ]) AC_MSG_RESULT([$_LT_AC_TAGVAR(ld_shlibs, $1)]) test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test "$GCC" = yes; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi # # Do we need to explicitly link libc? # case "x$_LT_AC_TAGVAR(archive_cmds_need_lc, $1)" in x|xyes) # Assume -lc should be added _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes if test "$enable_shared" = yes && test "$GCC" = yes; then case $_LT_AC_TAGVAR(archive_cmds, $1) in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. AC_MSG_CHECKING([whether -lc should be explicitly linked in]) $rm conftest* printf "$lt_simple_compile_test_code" > conftest.$ac_ext if AC_TRY_EVAL(ac_compile) 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$_LT_AC_TAGVAR(lt_prog_compiler_wl, $1) compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$_LT_AC_TAGVAR(allow_undefined_flag, $1) _LT_AC_TAGVAR(allow_undefined_flag, $1)= if AC_TRY_EVAL(_LT_AC_TAGVAR(archive_cmds, $1) 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) then _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no else _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes fi _LT_AC_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $rm conftest* AC_MSG_RESULT([$_LT_AC_TAGVAR(archive_cmds_need_lc, $1)]) ;; esac fi ;; esac ])# AC_LIBTOOL_PROG_LD_SHLIBS # _LT_AC_FILE_LTDLL_C # ------------------- # Be careful that the start marker always follows a newline. AC_DEFUN([_LT_AC_FILE_LTDLL_C], [ # /* ltdll.c starts here */ # #define WIN32_LEAN_AND_MEAN # #include # #undef WIN32_LEAN_AND_MEAN # #include # # #ifndef __CYGWIN__ # # ifdef __CYGWIN32__ # # define __CYGWIN__ __CYGWIN32__ # # endif # #endif # # #ifdef __cplusplus # extern "C" { # #endif # BOOL APIENTRY DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved); # #ifdef __cplusplus # } # #endif # # #ifdef __CYGWIN__ # #include # DECLARE_CYGWIN_DLL( DllMain ); # #endif # HINSTANCE __hDllInstance_base; # # BOOL APIENTRY # DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved) # { # __hDllInstance_base = hInst; # return TRUE; # } # /* ltdll.c ends here */ ])# _LT_AC_FILE_LTDLL_C # _LT_AC_TAGVAR(VARNAME, [TAGNAME]) # --------------------------------- AC_DEFUN([_LT_AC_TAGVAR], [ifelse([$2], [], [$1], [$1_$2])]) # old names AC_DEFUN([AM_PROG_LIBTOOL], [AC_PROG_LIBTOOL]) AC_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) AC_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) AC_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) AC_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) AC_DEFUN([AM_PROG_LD], [AC_PROG_LD]) AC_DEFUN([AM_PROG_NM], [AC_PROG_NM]) # This is just to silence aclocal about the macro not being used ifelse([AC_DISABLE_FAST_INSTALL]) AC_DEFUN([LT_AC_PROG_GCJ], [AC_CHECK_TOOL(GCJ, gcj, no) test "x${GCJFLAGS+set}" = xset || GCJFLAGS="-g -O2" AC_SUBST(GCJFLAGS) ]) AC_DEFUN([LT_AC_PROG_RC], [AC_CHECK_TOOL(RC, windres, no) ]) ############################################################ # NOTE: This macro has been submitted for inclusion into # # GNU Autoconf as AC_PROG_SED. When it is available in # # a released version of Autoconf we should remove this # # macro and use it instead. # ############################################################ # LT_AC_PROG_SED # -------------- # Check for a fully-functional sed program, that truncates # as few characters as possible. Prefer GNU sed if found. AC_DEFUN([LT_AC_PROG_SED], [AC_MSG_CHECKING([for a sed that does not truncate output]) AC_CACHE_VAL(lt_cv_path_SED, [# Loop through the user's path and test for sed and gsed. # Then use that list of sed's as ones to test for truncation. as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for lt_ac_prog in sed gsed; do for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" fi done done done lt_ac_max=0 lt_ac_count=0 # Add /usr/xpg4/bin/sed as it is typically found on Solaris # along with /bin/sed that truncates output. for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do test ! -f $lt_ac_sed && break cat /dev/null > conftest.in lt_ac_count=0 echo $ECHO_N "0123456789$ECHO_C" >conftest.in # Check for GNU sed and select it if it is found. if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then lt_cv_path_SED=$lt_ac_sed break fi while true; do cat conftest.in conftest.in >conftest.tmp mv conftest.tmp conftest.in cp conftest.in conftest.nl echo >>conftest.nl $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break cmp -s conftest.out conftest.nl || break # 10000 chars as input seems more than enough test $lt_ac_count -gt 10 && break lt_ac_count=`expr $lt_ac_count + 1` if test $lt_ac_count -gt $lt_ac_max; then lt_ac_max=$lt_ac_count lt_cv_path_SED=$lt_ac_sed fi done done SED=$lt_cv_path_SED ]) AC_MSG_RESULT([$SED]) ]) hercules-3.07/autoconf/ltdl.m4000644 000765 000765 00000033030 11143760527 017767 0ustar00jmaynardjmaynard000000 000000 ## ltdl.m4 - Configure ltdl for the target system. -*-Autoconf-*- ## Copyright (C) 1999-2000 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 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. # serial 6 AC_LIB_LTDL # AC_WITH_LTDL # ------------ # Clients of libltdl can use this macro to allow the installer to # choose between a shipped copy of the ltdl sources or a preinstalled # version of the library. AC_DEFUN([AC_WITH_LTDL], [AC_REQUIRE([AC_LIB_LTDL]) AC_SUBST([LIBLTDL]) AC_SUBST([INCLTDL]) # Unless the user asks us to check, assume no installed ltdl exists. use_installed_libltdl=no AC_ARG_WITH([included_ltdl], [ --with-included-ltdl use the GNU ltdl sources included here]) if test "x$with_included_ltdl" != xyes; then # We are not being forced to use the included libltdl sources, so # decide whether there is a useful installed version we can use. AC_CHECK_HEADER([ltdl.h], [AC_CHECK_LIB([ltdl], [lt_dlcaller_register], [with_included_ltdl=no], [with_included_ltdl=yes]) ]) fi if test "x$enable_ltdl_install" != xyes; then # If the user did not specify an installable libltdl, then default # to a convenience lib. AC_LIBLTDL_CONVENIENCE fi if test "x$with_included_ltdl" = xno; then # If the included ltdl is not to be used. then Use the # preinstalled libltdl we found. AC_DEFINE([HAVE_LTDL], 1, [Define this if a modern libltdl is already installed]) LIBLTDL=-lltdl fi # Report our decision... AC_MSG_CHECKING([whether to use included libltdl]) AC_MSG_RESULT([$with_included_ltdl]) AC_CONFIG_SUBDIRS([libltdl]) ])# AC_WITH_LTDL # AC_LIB_LTDL # ----------- # Perform all the checks necessary for compilation of the ltdl objects # -- including compiler checks and header checks. AC_DEFUN([AC_LIB_LTDL], [AC_PREREQ(2.50) AC_REQUIRE([AC_PROG_CC]) AC_REQUIRE([AC_C_CONST]) AC_REQUIRE([AC_HEADER_STDC]) AC_REQUIRE([AC_HEADER_DIRENT]) AC_REQUIRE([_LT_AC_CHECK_DLFCN]) AC_REQUIRE([AC_LTDL_ENABLE_INSTALL]) AC_REQUIRE([AC_LTDL_SHLIBEXT]) AC_REQUIRE([AC_LTDL_SHLIBPATH]) AC_REQUIRE([AC_LTDL_SYSSEARCHPATH]) AC_REQUIRE([AC_LTDL_OBJDIR]) AC_REQUIRE([AC_LTDL_DLPREOPEN]) AC_REQUIRE([AC_LTDL_DLLIB]) AC_REQUIRE([AC_LTDL_SYMBOL_USCORE]) AC_REQUIRE([AC_LTDL_DLSYM_USCORE]) AC_REQUIRE([AC_LTDL_SYS_DLOPEN_DEPLIBS]) AC_REQUIRE([AC_LTDL_FUNC_ARGZ]) AC_CHECK_HEADERS([assert.h ctype.h errno.h malloc.h memory.h stdlib.h \ stdio.h unistd.h]) AC_CHECK_HEADERS([dl.h sys/dl.h dld.h mach-o/dyld.h]) AC_CHECK_HEADERS([string.h strings.h], [break]) AC_CHECK_FUNCS([strchr index], [break]) AC_CHECK_FUNCS([strrchr rindex], [break]) AC_CHECK_FUNCS([memcpy bcopy], [break]) AC_CHECK_FUNCS([memmove strcmp]) AC_CHECK_FUNCS([closedir opendir readdir]) ])# AC_LIB_LTDL # AC_LTDL_ENABLE_INSTALL # ---------------------- AC_DEFUN([AC_LTDL_ENABLE_INSTALL], [AC_ARG_ENABLE([ltdl-install], [AC_HELP_STRING([--enable-ltdl-install], [install libltdl])]) AM_CONDITIONAL(INSTALL_LTDL, test x"${enable_ltdl_install-no}" != xno) AM_CONDITIONAL(CONVENIENCE_LTDL, test x"${enable_ltdl_convenience-no}" != xno) ])])# AC_LTDL_ENABLE_INSTALL # AC_LTDL_SYS_DLOPEN_DEPLIBS # -------------------------- AC_DEFUN([AC_LTDL_SYS_DLOPEN_DEPLIBS], [AC_REQUIRE([AC_CANONICAL_HOST]) AC_CACHE_CHECK([whether deplibs are loaded by dlopen], [libltdl_cv_sys_dlopen_deplibs], [# PORTME does your system automatically load deplibs for dlopen? # or its logical equivalent (e.g. shl_load for HP-UX < 11) # For now, we just catch OSes we know something about -- in the # future, we'll try test this programmatically. libltdl_cv_sys_dlopen_deplibs=unknown case "$host_os" in aix3*|aix4.1.*|aix4.2.*) # Unknown whether this is true for these versions of AIX, but # we want this `case' here to explicitly catch those versions. libltdl_cv_sys_dlopen_deplibs=unknown ;; aix[[45]]*) libltdl_cv_sys_dlopen_deplibs=yes ;; darwin*) # Assuming the user has installed a libdl from somewhere, this is true # If you are looking for one http://www.opendarwin.org/projects/dlcompat libltdl_cv_sys_dlopen_deplibs=yes ;; kfreebsd*-gnu) libltdl_cv_sys_dlopen_deplibs=yes ;; gnu*) libltdl_cv_sys_dlopen_deplibs=yes ;; hpux10*|hpux11*) libltdl_cv_sys_dlopen_deplibs=yes ;; irix[[12345]]*|irix6.[[01]]*) # Catch all versions of IRIX before 6.2, and indicate that we don't # know how it worked for any of those versions. libltdl_cv_sys_dlopen_deplibs=unknown ;; irix*) # The case above catches anything before 6.2, and it's known that # at 6.2 and later dlopen does load deplibs. libltdl_cv_sys_dlopen_deplibs=yes ;; linux*) libltdl_cv_sys_dlopen_deplibs=yes ;; netbsd*) libltdl_cv_sys_dlopen_deplibs=yes ;; openbsd*) libltdl_cv_sys_dlopen_deplibs=yes ;; osf[[1234]]*) # dlopen did load deplibs (at least at 4.x), but until the 5.x series, # it did *not* use an RPATH in a shared library to find objects the # library depends on, so we explictly say `no'. libltdl_cv_sys_dlopen_deplibs=no ;; osf5.0|osf5.0a|osf5.1) # dlopen *does* load deplibs and with the right loader patch applied # it even uses RPATH in a shared library to search for shared objects # that the library depends on, but there's no easy way to know if that # patch is installed. Since this is the case, all we can really # say is unknown -- it depends on the patch being installed. If # it is, this changes to `yes'. Without it, it would be `no'. libltdl_cv_sys_dlopen_deplibs=unknown ;; osf*) # the two cases above should catch all versions of osf <= 5.1. Read # the comments above for what we know about them. # At > 5.1, deplibs are loaded *and* any RPATH in a shared library # is used to find them so we can finally say `yes'. libltdl_cv_sys_dlopen_deplibs=yes ;; solaris*) libltdl_cv_sys_dlopen_deplibs=yes ;; esac ]) if test "$libltdl_cv_sys_dlopen_deplibs" != yes; then AC_DEFINE([LTDL_DLOPEN_DEPLIBS], [1], [Define if the OS needs help to load dependent libraries for dlopen().]) fi ])# AC_LTDL_SYS_DLOPEN_DEPLIBS # AC_LTDL_SHLIBEXT # ---------------- AC_DEFUN([AC_LTDL_SHLIBEXT], [AC_REQUIRE([AC_LIBTOOL_SYS_DYNAMIC_LINKER]) AC_CACHE_CHECK([which extension is used for loadable modules], [libltdl_cv_shlibext], [ module=yes eval libltdl_cv_shlibext=$shrext_cmds ]) if test -n "$libltdl_cv_shlibext"; then AC_DEFINE_UNQUOTED(LTDL_SHLIB_EXT, "$libltdl_cv_shlibext", [Define to the extension used for shared libraries, say, ".so".]) fi ])# AC_LTDL_SHLIBEXT # AC_LTDL_SHLIBPATH # ----------------- AC_DEFUN([AC_LTDL_SHLIBPATH], [AC_REQUIRE([AC_LIBTOOL_SYS_DYNAMIC_LINKER]) AC_CACHE_CHECK([which variable specifies run-time library path], [libltdl_cv_shlibpath_var], [libltdl_cv_shlibpath_var="$shlibpath_var"]) if test -n "$libltdl_cv_shlibpath_var"; then AC_DEFINE_UNQUOTED(LTDL_SHLIBPATH_VAR, "$libltdl_cv_shlibpath_var", [Define to the name of the environment variable that determines the dynamic library search path.]) fi ])# AC_LTDL_SHLIBPATH # AC_LTDL_SYSSEARCHPATH # --------------------- AC_DEFUN([AC_LTDL_SYSSEARCHPATH], [AC_REQUIRE([AC_LIBTOOL_SYS_DYNAMIC_LINKER]) AC_CACHE_CHECK([for the default library search path], [libltdl_cv_sys_search_path], [libltdl_cv_sys_search_path="$sys_lib_dlsearch_path_spec"]) if test -n "$libltdl_cv_sys_search_path"; then sys_search_path= for dir in $libltdl_cv_sys_search_path; do if test -z "$sys_search_path"; then sys_search_path="$dir" else sys_search_path="$sys_search_path$PATH_SEPARATOR$dir" fi done AC_DEFINE_UNQUOTED(LTDL_SYSSEARCHPATH, "$sys_search_path", [Define to the system default library search path.]) fi ])# AC_LTDL_SYSSEARCHPATH # AC_LTDL_OBJDIR # -------------- AC_DEFUN([AC_LTDL_OBJDIR], [AC_CACHE_CHECK([for objdir], [libltdl_cv_objdir], [libltdl_cv_objdir="$objdir" if test -n "$objdir"; then : else rm -f .libs 2>/dev/null mkdir .libs 2>/dev/null if test -d .libs; then libltdl_cv_objdir=.libs else # MS-DOS does not allow filenames that begin with a dot. libltdl_cv_objdir=_libs fi rmdir .libs 2>/dev/null fi ]) AC_DEFINE_UNQUOTED(LTDL_OBJDIR, "$libltdl_cv_objdir/", [Define to the sub-directory in which libtool stores uninstalled libraries.]) ])# AC_LTDL_OBJDIR # AC_LTDL_DLPREOPEN # ----------------- AC_DEFUN([AC_LTDL_DLPREOPEN], [AC_REQUIRE([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE]) AC_CACHE_CHECK([whether libtool supports -dlopen/-dlpreopen], [libltdl_cv_preloaded_symbols], [if test -n "$lt_cv_sys_global_symbol_pipe"; then libltdl_cv_preloaded_symbols=yes else libltdl_cv_preloaded_symbols=no fi ]) if test x"$libltdl_cv_preloaded_symbols" = xyes; then AC_DEFINE(HAVE_PRELOADED_SYMBOLS, 1, [Define if libtool can extract symbol lists from object files.]) fi ])# AC_LTDL_DLPREOPEN # AC_LTDL_DLLIB # ------------- AC_DEFUN([AC_LTDL_DLLIB], [LIBADD_DL= AC_SUBST(LIBADD_DL) AC_LANG_PUSH([C]) AC_CHECK_FUNC([shl_load], [AC_DEFINE([HAVE_SHL_LOAD], [1], [Define if you have the shl_load function.])], [AC_CHECK_LIB([dld], [shl_load], [AC_DEFINE([HAVE_SHL_LOAD], [1], [Define if you have the shl_load function.]) LIBADD_DL="$LIBADD_DL -ldld"], [AC_CHECK_LIB([dl], [dlopen], [AC_DEFINE([HAVE_LIBDL], [1], [Define if you have the libdl library or equivalent.]) LIBADD_DL="-ldl" libltdl_cv_lib_dl_dlopen="yes"], [AC_TRY_LINK([#if HAVE_DLFCN_H # include #endif ], [dlopen(0, 0);], [AC_DEFINE([HAVE_LIBDL], [1], [Define if you have the libdl library or equivalent.]) libltdl_cv_func_dlopen="yes"], [AC_CHECK_LIB([svld], [dlopen], [AC_DEFINE([HAVE_LIBDL], [1], [Define if you have the libdl library or equivalent.]) LIBADD_DL="-lsvld" libltdl_cv_func_dlopen="yes"], [AC_CHECK_LIB([dld], [dld_link], [AC_DEFINE([HAVE_DLD], [1], [Define if you have the GNU dld library.]) LIBADD_DL="$LIBADD_DL -ldld"], [AC_CHECK_FUNC([_dyld_func_lookup], [AC_DEFINE([HAVE_DYLD], [1], [Define if you have the _dyld_func_lookup function.])]) ]) ]) ]) ]) ]) ]) if test x"$libltdl_cv_func_dlopen" = xyes || test x"$libltdl_cv_lib_dl_dlopen" = xyes then lt_save_LIBS="$LIBS" LIBS="$LIBS $LIBADD_DL" AC_CHECK_FUNCS([dlerror]) LIBS="$lt_save_LIBS" fi AC_LANG_POP ])# AC_LTDL_DLLIB # AC_LTDL_SYMBOL_USCORE # --------------------- # does the compiler prefix global symbols with an underscore? AC_DEFUN([AC_LTDL_SYMBOL_USCORE], [AC_REQUIRE([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE]) AC_CACHE_CHECK([for _ prefix in compiled symbols], [ac_cv_sys_symbol_underscore], [ac_cv_sys_symbol_underscore=no cat > conftest.$ac_ext < $ac_nlist) && test -s "$ac_nlist"; then # See whether the symbols have a leading underscore. if grep '^. _nm_test_func' "$ac_nlist" >/dev/null; then ac_cv_sys_symbol_underscore=yes else if grep '^. nm_test_func ' "$ac_nlist" >/dev/null; then : else echo "configure: cannot find nm_test_func in $ac_nlist" >&AC_FD_CC fi fi else echo "configure: cannot run $lt_cv_sys_global_symbol_pipe" >&AC_FD_CC fi else echo "configure: failed program was:" >&AC_FD_CC cat conftest.c >&AC_FD_CC fi rm -rf conftest* ]) ])# AC_LTDL_SYMBOL_USCORE # AC_LTDL_DLSYM_USCORE # -------------------- AC_DEFUN([AC_LTDL_DLSYM_USCORE], [AC_REQUIRE([AC_LTDL_SYMBOL_USCORE]) if test x"$ac_cv_sys_symbol_underscore" = xyes; then if test x"$libltdl_cv_func_dlopen" = xyes || test x"$libltdl_cv_lib_dl_dlopen" = xyes ; then AC_CACHE_CHECK([whether we have to add an underscore for dlsym], [libltdl_cv_need_uscore], [libltdl_cv_need_uscore=unknown save_LIBS="$LIBS" LIBS="$LIBS $LIBADD_DL" _LT_AC_TRY_DLOPEN_SELF( [libltdl_cv_need_uscore=no], [libltdl_cv_need_uscore=yes], [], [libltdl_cv_need_uscore=cross]) LIBS="$save_LIBS" ]) fi fi if test x"$libltdl_cv_need_uscore" = xyes; then AC_DEFINE(NEED_USCORE, 1, [Define if dlsym() requires a leading underscore in symbol names.]) fi ])# AC_LTDL_DLSYM_USCORE # AC_LTDL_FUNC_ARGZ # ----------------- AC_DEFUN([AC_LTDL_FUNC_ARGZ], [AC_CHECK_HEADERS([argz.h]) AC_CHECK_TYPES([error_t], [], [AC_DEFINE([error_t], [int], [Define to a type to use for `error_t' if it is not otherwise available.])], [#if HAVE_ARGZ_H # include #endif]) AC_CHECK_FUNCS([argz_append argz_create_sep argz_insert argz_next argz_stringify]) ])# AC_LTDL_FUNC_ARGZ hercules-3.07/autoconf/ltmain.sh000644 000765 000765 00000541403 11143760527 020416 0ustar00jmaynardjmaynard000000 000000 # ltmain.sh - Provide generalized library-building support services. # NOTE: Changing this file will not affect anything until you rerun configure. # # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003 # Free Software Foundation, Inc. # 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. # Check that we have a working $echo. if test "X$1" = X--no-reexec; then # Discard the --no-reexec flag, and continue. shift elif test "X$1" = X--fallback-echo; then # Avoid inline document here, it may be left over : elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then # Yippee, $echo works! : else # Restart under the correct shell, and then maybe $echo will work. exec $SHELL "$0" --no-reexec ${1+"$@"} fi if test "X$1" = X--fallback-echo; then # used as fallback echo shift cat <&2 $echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2 exit 1 fi # Global variables. mode=$default_mode nonopt= prev= prevopt= run= show="$echo" show_help= execute_dlfiles= lo2o="s/\\.lo\$/.${objext}/" o2lo="s/\\.${objext}\$/.lo/" ##################################### # Shell function definitions: # This seems to be the best place for them # Need a lot of goo to handle *both* DLLs and import libs # Has to be a shell function in order to 'eat' the argument # that is supplied when $file_magic_command is called. win32_libid () { win32_libid_type="unknown" win32_fileres=`file -L $1 2>/dev/null` case $win32_fileres in *ar\ archive\ import\ library*) # definitely import win32_libid_type="x86 archive import" ;; *ar\ archive*) # could be an import, or static if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | \ grep -E 'file format pe-i386(.*architecture: i386)?' >/dev/null ; then win32_nmres=`eval $NM -f posix -A $1 | \ sed -n -e '1,100{/ I /{x;/import/!{s/^/import/;h;p;};x;};}'` if test "X$win32_nmres" = "Ximport" ; then win32_libid_type="x86 archive import" else win32_libid_type="x86 archive static" fi fi ;; *DLL*) win32_libid_type="x86 DLL" ;; *executable*) # but shell scripts are "executable" too... case $win32_fileres in *MS\ Windows\ PE\ Intel*) win32_libid_type="x86 DLL" ;; esac ;; esac $echo $win32_libid_type } # End of Shell function definitions ##################################### # Parse our command line options once, thoroughly. while test "$#" -gt 0 do arg="$1" shift case $arg in -*=*) optarg=`$echo "X$arg" | $Xsed -e 's/[-_a-zA-Z0-9]*=//'` ;; *) optarg= ;; esac # If the previous option needs an argument, assign it. if test -n "$prev"; then case $prev in execute_dlfiles) execute_dlfiles="$execute_dlfiles $arg" ;; tag) tagname="$arg" # Check whether tagname contains only valid characters case $tagname in *[!-_A-Za-z0-9,/]*) $echo "$progname: invalid tag name: $tagname" 1>&2 exit 1 ;; esac case $tagname in CC) # Don't test for the "default" C tag, as we know, it's there, but # not specially marked. ;; *) if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "$0" > /dev/null; then taglist="$taglist $tagname" # Evaluate the configuration. eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$tagname'$/,/^# ### END LIBTOOL TAG CONFIG: '$tagname'$/p' < $0`" else $echo "$progname: ignoring unknown tag $tagname" 1>&2 fi ;; esac ;; *) eval "$prev=\$arg" ;; esac prev= prevopt= continue fi # Have we seen a non-optional argument yet? case $arg in --help) show_help=yes ;; --version) $echo "$PROGRAM (GNU $PACKAGE) $VERSION$TIMESTAMP" $echo $echo "Copyright (C) 2003 Free Software Foundation, Inc." $echo "This is free software; see the source for copying conditions. There is NO" $echo "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." exit 0 ;; --config) ${SED} -e '1,/^# ### BEGIN LIBTOOL CONFIG/d' -e '/^# ### END LIBTOOL CONFIG/,$d' $0 # Now print the configurations for the tags. for tagname in $taglist; do ${SED} -n -e "/^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$/,/^# ### END LIBTOOL TAG CONFIG: $tagname$/p" < "$0" done exit 0 ;; --debug) $echo "$progname: enabling shell trace mode" set -x ;; --dry-run | -n) run=: ;; --features) $echo "host: $host" if test "$build_libtool_libs" = yes; then $echo "enable shared libraries" else $echo "disable shared libraries" fi if test "$build_old_libs" = yes; then $echo "enable static libraries" else $echo "disable static libraries" fi exit 0 ;; --finish) mode="finish" ;; --mode) prevopt="--mode" prev=mode ;; --mode=*) mode="$optarg" ;; --preserve-dup-deps) duplicate_deps="yes" ;; --quiet | --silent) show=: ;; --tag) prevopt="--tag" prev=tag ;; --tag=*) set tag "$optarg" ${1+"$@"} shift prev=tag ;; -dlopen) prevopt="-dlopen" prev=execute_dlfiles ;; -*) $echo "$modename: unrecognized option \`$arg'" 1>&2 $echo "$help" 1>&2 exit 1 ;; *) nonopt="$arg" break ;; esac done if test -n "$prevopt"; then $echo "$modename: option \`$prevopt' requires an argument" 1>&2 $echo "$help" 1>&2 exit 1 fi # If this variable is set in any of the actions, the command in it # will be execed at the end. This prevents here-documents from being # left over by shells. exec_cmd= if test -z "$show_help"; then # Infer the operation mode. if test -z "$mode"; then $echo "*** Warning: inferring the mode of operation is deprecated." 1>&2 $echo "*** Future versions of Libtool will require -mode=MODE be specified." 1>&2 case $nonopt in *cc | cc* | *++ | gcc* | *-gcc* | g++* | xlc*) mode=link for arg do case $arg in -c) mode=compile break ;; esac done ;; *db | *dbx | *strace | *truss) mode=execute ;; *install*|cp|mv) mode=install ;; *rm) mode=uninstall ;; *) # If we have no mode, but dlfiles were specified, then do execute mode. test -n "$execute_dlfiles" && mode=execute # Just use the default operation mode. if test -z "$mode"; then if test -n "$nonopt"; then $echo "$modename: warning: cannot infer operation mode from \`$nonopt'" 1>&2 else $echo "$modename: warning: cannot infer operation mode without MODE-ARGS" 1>&2 fi fi ;; esac fi # Only execute mode is allowed to have -dlopen flags. if test -n "$execute_dlfiles" && test "$mode" != execute; then $echo "$modename: unrecognized option \`-dlopen'" 1>&2 $echo "$help" 1>&2 exit 1 fi # Change the help message to a mode-specific one. generic_help="$help" help="Try \`$modename --help --mode=$mode' for more information." # These modes are in order of execution frequency so that they run quickly. case $mode in # libtool compile mode compile) modename="$modename: compile" # Get the compilation command and the source file. base_compile= srcfile="$nonopt" # always keep a non-empty value in "srcfile" suppress_output= arg_mode=normal libobj= for arg do case "$arg_mode" in arg ) # do not "continue". Instead, add this to base_compile lastarg="$arg" arg_mode=normal ;; target ) libobj="$arg" arg_mode=normal continue ;; normal ) # Accept any command-line options. case $arg in -o) if test -n "$libobj" ; then $echo "$modename: you cannot specify \`-o' more than once" 1>&2 exit 1 fi arg_mode=target continue ;; -static) build_old_libs=yes continue ;; -prefer-pic) pic_mode=yes continue ;; -prefer-non-pic) pic_mode=no continue ;; -Xcompiler) arg_mode=arg # the next one goes into the "base_compile" arg list continue # The current "srcfile" will either be retained or ;; # replaced later. I would guess that would be a bug. -Wc,*) args=`$echo "X$arg" | $Xsed -e "s/^-Wc,//"` lastarg= save_ifs="$IFS"; IFS=',' for arg in $args; do IFS="$save_ifs" # Double-quote args containing other shell metacharacters. # Many Bourne shells cannot handle close brackets correctly # in scan sets, so we specify it separately. case $arg in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") arg="\"$arg\"" ;; esac lastarg="$lastarg $arg" done IFS="$save_ifs" lastarg=`$echo "X$lastarg" | $Xsed -e "s/^ //"` # Add the arguments to base_compile. base_compile="$base_compile $lastarg" continue ;; * ) # Accept the current argument as the source file. # The previous "srcfile" becomes the current argument. # lastarg="$srcfile" srcfile="$arg" ;; esac # case $arg ;; esac # case $arg_mode # Aesthetically quote the previous argument. lastarg=`$echo "X$lastarg" | $Xsed -e "$sed_quote_subst"` case $lastarg in # Double-quote args containing other shell metacharacters. # Many Bourne shells cannot handle close brackets correctly # in scan sets, so we specify it separately. *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") lastarg="\"$lastarg\"" ;; esac base_compile="$base_compile $lastarg" done # for arg case $arg_mode in arg) $echo "$modename: you must specify an argument for -Xcompile" exit 1 ;; target) $echo "$modename: you must specify a target with \`-o'" 1>&2 exit 1 ;; *) # Get the name of the library object. [ -z "$libobj" ] && libobj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%'` ;; esac # Recognize several different file suffixes. # If the user specifies -o file.o, it is replaced with file.lo xform='[cCFSifmso]' case $libobj in *.ada) xform=ada ;; *.adb) xform=adb ;; *.ads) xform=ads ;; *.asm) xform=asm ;; *.c++) xform=c++ ;; *.cc) xform=cc ;; *.ii) xform=ii ;; *.class) xform=class ;; *.cpp) xform=cpp ;; *.cxx) xform=cxx ;; *.f90) xform=f90 ;; *.for) xform=for ;; *.java) xform=java ;; esac libobj=`$echo "X$libobj" | $Xsed -e "s/\.$xform$/.lo/"` case $libobj in *.lo) obj=`$echo "X$libobj" | $Xsed -e "$lo2o"` ;; *) $echo "$modename: cannot determine name of library object from \`$libobj'" 1>&2 exit 1 ;; esac # Infer tagged configuration to use if any are available and # if one wasn't chosen via the "--tag" command line option. # Only attempt this if the compiler in the base compile # command doesn't match the default compiler. if test -n "$available_tags" && test -z "$tagname"; then case $base_compile in # Blanks in the command may have been stripped by the calling shell, # but not from the CC environment variable when configure was run. " $CC "* | "$CC "* | " `$echo $CC` "* | "`$echo $CC` "*) ;; # Blanks at the start of $base_compile will cause this to fail # if we don't check for them as well. *) for z in $available_tags; do if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$0" > /dev/null; then # Evaluate the configuration. eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $0`" case "$base_compile " in "$CC "* | " $CC "* | "`$echo $CC` "* | " `$echo $CC` "*) # The compiler in the base compile command matches # the one in the tagged configuration. # Assume this is the tagged configuration we want. tagname=$z break ;; esac fi done # If $tagname still isn't set, then no tagged configuration # was found and let the user know that the "--tag" command # line option must be used. if test -z "$tagname"; then $echo "$modename: unable to infer tagged configuration" $echo "$modename: specify a tag with \`--tag'" 1>&2 exit 1 # else # $echo "$modename: using $tagname tagged configuration" fi ;; esac fi objname=`$echo "X$obj" | $Xsed -e 's%^.*/%%'` xdir=`$echo "X$obj" | $Xsed -e 's%/[^/]*$%%'` if test "X$xdir" = "X$obj"; then xdir= else xdir=$xdir/ fi lobj=${xdir}$objdir/$objname if test -z "$base_compile"; then $echo "$modename: you must specify a compilation command" 1>&2 $echo "$help" 1>&2 exit 1 fi # Delete any leftover library objects. if test "$build_old_libs" = yes; then removelist="$obj $lobj $libobj ${libobj}T" else removelist="$lobj $libobj ${libobj}T" fi $run $rm $removelist trap "$run $rm $removelist; exit 1" 1 2 15 # On Cygwin there's no "real" PIC flag so we must build both object types case $host_os in cygwin* | mingw* | pw32* | os2*) pic_mode=default ;; esac if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then # non-PIC code in shared libraries is not supported pic_mode=default fi # Calculate the filename of the output object if compiler does # not support -o with -c if test "$compiler_c_o" = no; then output_obj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%' -e 's%\.[^.]*$%%'`.${objext} lockfile="$output_obj.lock" removelist="$removelist $output_obj $lockfile" trap "$run $rm $removelist; exit 1" 1 2 15 else output_obj= need_locks=no lockfile= fi # Lock this critical section if it is needed # We use this script file to make the link, it avoids creating a new file if test "$need_locks" = yes; then until $run ln "$0" "$lockfile" 2>/dev/null; do $show "Waiting for $lockfile to be removed" sleep 2 done elif test "$need_locks" = warn; then if test -f "$lockfile"; then $echo "\ *** ERROR, $lockfile exists and contains: `cat $lockfile 2>/dev/null` This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support \`-c' and \`-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $run $rm $removelist exit 1 fi $echo $srcfile > "$lockfile" fi if test -n "$fix_srcfile_path"; then eval srcfile=\"$fix_srcfile_path\" fi $run $rm "$libobj" "${libobj}T" # Create a libtool object file (analogous to a ".la" file), # but don't create it if we're doing a dry run. test -z "$run" && cat > ${libobj}T </dev/null`" != "X$srcfile"; then $echo "\ *** ERROR, $lockfile contains: `cat $lockfile 2>/dev/null` but it should contain: $srcfile This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support \`-c' and \`-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $run $rm $removelist exit 1 fi # Just move the object if needed, then go on to compile the next one if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then $show "$mv $output_obj $lobj" if $run $mv $output_obj $lobj; then : else error=$? $run $rm $removelist exit $error fi fi # Append the name of the PIC object to the libtool object file. test -z "$run" && cat >> ${libobj}T <> ${libobj}T </dev/null`" != "X$srcfile"; then $echo "\ *** ERROR, $lockfile contains: `cat $lockfile 2>/dev/null` but it should contain: $srcfile This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support \`-c' and \`-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $run $rm $removelist exit 1 fi # Just move the object if needed if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then $show "$mv $output_obj $obj" if $run $mv $output_obj $obj; then : else error=$? $run $rm $removelist exit $error fi fi # Append the name of the non-PIC object the libtool object file. # Only append if the libtool object file exists. test -z "$run" && cat >> ${libobj}T <> ${libobj}T <&2 fi if test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi else if test -z "$pic_flag" && test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi fi build_libtool_libs=no build_old_libs=yes prefer_static_libs=yes break ;; esac done # See if our shared archives depend on static archives. test -n "$old_archive_from_new_cmds" && build_old_libs=yes # Go through the arguments, transforming them on the way. while test "$#" -gt 0; do arg="$1" base_compile="$base_compile $arg" shift case $arg in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") qarg=\"`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`\" ### testsuite: skip nested quoting test ;; *) qarg=$arg ;; esac libtool_args="$libtool_args $qarg" # If the previous option needs an argument, assign it. if test -n "$prev"; then case $prev in output) compile_command="$compile_command @OUTPUT@" finalize_command="$finalize_command @OUTPUT@" ;; esac case $prev in dlfiles|dlprefiles) if test "$preload" = no; then # Add the symbol object into the linking commands. compile_command="$compile_command @SYMFILE@" finalize_command="$finalize_command @SYMFILE@" preload=yes fi case $arg in *.la | *.lo) ;; # We handle these cases below. force) if test "$dlself" = no; then dlself=needless export_dynamic=yes fi prev= continue ;; self) if test "$prev" = dlprefiles; then dlself=yes elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then dlself=yes else dlself=needless export_dynamic=yes fi prev= continue ;; *) if test "$prev" = dlfiles; then dlfiles="$dlfiles $arg" else dlprefiles="$dlprefiles $arg" fi prev= continue ;; esac ;; expsyms) export_symbols="$arg" if test ! -f "$arg"; then $echo "$modename: symbol file \`$arg' does not exist" exit 1 fi prev= continue ;; expsyms_regex) export_symbols_regex="$arg" prev= continue ;; inst_prefix) inst_prefix_dir="$arg" prev= continue ;; release) release="-$arg" prev= continue ;; objectlist) if test -f "$arg"; then save_arg=$arg moreargs= for fil in `cat $save_arg` do # moreargs="$moreargs $fil" arg=$fil # A libtool-controlled object. # Check to see that this really is a libtool object. if (${SED} -e '2q' $arg | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then pic_object= non_pic_object= # Read the .lo file # If there is no directory component, then add one. case $arg in */* | *\\*) . $arg ;; *) . ./$arg ;; esac if test -z "$pic_object" || \ test -z "$non_pic_object" || test "$pic_object" = none && \ test "$non_pic_object" = none; then $echo "$modename: cannot find name of object for \`$arg'" 1>&2 exit 1 fi # Extract subdirectory from the argument. xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'` if test "X$xdir" = "X$arg"; then xdir= else xdir="$xdir/" fi if test "$pic_object" != none; then # Prepend the subdirectory the object is found in. pic_object="$xdir$pic_object" if test "$prev" = dlfiles; then if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then dlfiles="$dlfiles $pic_object" prev= continue else # If libtool objects are unsupported, then we need to preload. prev=dlprefiles fi fi # CHECK ME: I think I busted this. -Ossama if test "$prev" = dlprefiles; then # Preload the old-style object. dlprefiles="$dlprefiles $pic_object" prev= fi # A PIC object. libobjs="$libobjs $pic_object" arg="$pic_object" fi # Non-PIC object. if test "$non_pic_object" != none; then # Prepend the subdirectory the object is found in. non_pic_object="$xdir$non_pic_object" # A standard non-PIC object non_pic_objects="$non_pic_objects $non_pic_object" if test -z "$pic_object" || test "$pic_object" = none ; then arg="$non_pic_object" fi fi else # Only an error if not doing a dry-run. if test -z "$run"; then $echo "$modename: \`$arg' is not a valid libtool object" 1>&2 exit 1 else # Dry-run case. # Extract subdirectory from the argument. xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'` if test "X$xdir" = "X$arg"; then xdir= else xdir="$xdir/" fi pic_object=`$echo "X${xdir}${objdir}/${arg}" | $Xsed -e "$lo2o"` non_pic_object=`$echo "X${xdir}${arg}" | $Xsed -e "$lo2o"` libobjs="$libobjs $pic_object" non_pic_objects="$non_pic_objects $non_pic_object" fi fi done else $echo "$modename: link input file \`$save_arg' does not exist" exit 1 fi arg=$save_arg prev= continue ;; rpath | xrpath) # We need an absolute path. case $arg in [\\/]* | [A-Za-z]:[\\/]*) ;; *) $echo "$modename: only absolute run-paths are allowed" 1>&2 exit 1 ;; esac if test "$prev" = rpath; then case "$rpath " in *" $arg "*) ;; *) rpath="$rpath $arg" ;; esac else case "$xrpath " in *" $arg "*) ;; *) xrpath="$xrpath $arg" ;; esac fi prev= continue ;; xcompiler) compiler_flags="$compiler_flags $qarg" prev= compile_command="$compile_command $qarg" finalize_command="$finalize_command $qarg" continue ;; xlinker) linker_flags="$linker_flags $qarg" compiler_flags="$compiler_flags $wl$qarg" prev= compile_command="$compile_command $wl$qarg" finalize_command="$finalize_command $wl$qarg" continue ;; xcclinker) linker_flags="$linker_flags $qarg" compiler_flags="$compiler_flags $qarg" prev= compile_command="$compile_command $qarg" finalize_command="$finalize_command $qarg" continue ;; *) eval "$prev=\"\$arg\"" prev= continue ;; esac fi # test -n "$prev" prevarg="$arg" case $arg in -all-static) if test -n "$link_static_flag"; then compile_command="$compile_command $link_static_flag" finalize_command="$finalize_command $link_static_flag" fi continue ;; -allow-undefined) # FIXME: remove this flag sometime in the future. $echo "$modename: \`-allow-undefined' is deprecated because it is the default" 1>&2 continue ;; -avoid-version) avoid_version=yes continue ;; -dlopen) prev=dlfiles continue ;; -dlpreopen) prev=dlprefiles continue ;; -export-dynamic) export_dynamic=yes continue ;; -export-symbols | -export-symbols-regex) if test -n "$export_symbols" || test -n "$export_symbols_regex"; then $echo "$modename: more than one -exported-symbols argument is not allowed" exit 1 fi if test "X$arg" = "X-export-symbols"; then prev=expsyms else prev=expsyms_regex fi continue ;; -inst-prefix-dir) prev=inst_prefix continue ;; # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* # so, if we see these flags be careful not to treat them like -L -L[A-Z][A-Z]*:*) case $with_gcc/$host in no/*-*-irix* | /*-*-irix*) compile_command="$compile_command $arg" finalize_command="$finalize_command $arg" ;; esac continue ;; -L*) dir=`$echo "X$arg" | $Xsed -e 's/^-L//'` # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) absdir=`cd "$dir" && pwd` if test -z "$absdir"; then $echo "$modename: cannot determine absolute directory name of \`$dir'" 1>&2 exit 1 fi dir="$absdir" ;; esac case "$deplibs " in *" -L$dir "*) ;; *) deplibs="$deplibs -L$dir" lib_search_path="$lib_search_path $dir" ;; esac case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) case :$dllsearchpath: in *":$dir:"*) ;; *) dllsearchpath="$dllsearchpath:$dir";; esac ;; esac continue ;; -l*) if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then case $host in *-*-cygwin* | *-*-pw32* | *-*-beos*) # These systems don't actually have a C or math library (as such) continue ;; *-*-mingw* | *-*-os2*) # These systems don't actually have a C library (as such) test "X$arg" = "X-lc" && continue ;; *-*-openbsd* | *-*-freebsd*) # Do not include libc due to us having libc/libc_r. test "X$arg" = "X-lc" && continue ;; *-*-rhapsody* | *-*-darwin1.[012]) # Rhapsody C and math libraries are in the System framework deplibs="$deplibs -framework System" continue esac elif test "X$arg" = "X-lc_r"; then case $host in *-*-openbsd* | *-*-freebsd*) # Do not include libc_r directly, use -pthread flag. continue ;; esac fi deplibs="$deplibs $arg" continue ;; -module) module=yes continue ;; # gcc -m* arguments should be passed to the linker via $compiler_flags # in order to pass architecture information to the linker # (e.g. 32 vs 64-bit). This may also be accomplished via -Wl,-mfoo # but this is not reliable with gcc because gcc may use -mfoo to # select a different linker, different libraries, etc, while # -Wl,-mfoo simply passes -mfoo to the linker. -m*) # Unknown arguments in both finalize_command and compile_command need # to be aesthetically quoted because they are evaled later. arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` case $arg in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") arg="\"$arg\"" ;; esac compile_command="$compile_command $arg" finalize_command="$finalize_command $arg" if test "$with_gcc" = "yes" ; then compiler_flags="$compiler_flags $arg" fi continue ;; -shrext) prev=shrext continue ;; -no-fast-install) fast_install=no continue ;; -no-install) case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) # The PATH hackery in wrapper scripts is required on Windows # in order for the loader to find any dlls it needs. $echo "$modename: warning: \`-no-install' is ignored for $host" 1>&2 $echo "$modename: warning: assuming \`-no-fast-install' instead" 1>&2 fast_install=no ;; *) no_install=yes ;; esac continue ;; -no-undefined) allow_undefined=no continue ;; -objectlist) prev=objectlist continue ;; -o) prev=output ;; -release) prev=release continue ;; -rpath) prev=rpath continue ;; -R) prev=xrpath continue ;; -R*) dir=`$echo "X$arg" | $Xsed -e 's/^-R//'` # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) $echo "$modename: only absolute run-paths are allowed" 1>&2 exit 1 ;; esac case "$xrpath " in *" $dir "*) ;; *) xrpath="$xrpath $dir" ;; esac continue ;; -static) # The effects of -static are defined in a previous loop. # We used to do the same as -all-static on platforms that # didn't have a PIC flag, but the assumption that the effects # would be equivalent was wrong. It would break on at least # Digital Unix and AIX. continue ;; -thread-safe) thread_safe=yes continue ;; -version-info) prev=vinfo continue ;; -version-number) prev=vinfo vinfo_number=yes continue ;; -Wc,*) args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wc,//'` arg= save_ifs="$IFS"; IFS=',' for flag in $args; do IFS="$save_ifs" case $flag in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") flag="\"$flag\"" ;; esac arg="$arg $wl$flag" compiler_flags="$compiler_flags $flag" done IFS="$save_ifs" arg=`$echo "X$arg" | $Xsed -e "s/^ //"` ;; -Wl,*) args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wl,//'` arg= save_ifs="$IFS"; IFS=',' for flag in $args; do IFS="$save_ifs" case $flag in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") flag="\"$flag\"" ;; esac arg="$arg $wl$flag" compiler_flags="$compiler_flags $wl$flag" linker_flags="$linker_flags $flag" done IFS="$save_ifs" arg=`$echo "X$arg" | $Xsed -e "s/^ //"` ;; -Xcompiler) prev=xcompiler continue ;; -Xlinker) prev=xlinker continue ;; -XCClinker) prev=xcclinker continue ;; # Some other compiler flag. -* | +*) # Unknown arguments in both finalize_command and compile_command need # to be aesthetically quoted because they are evaled later. arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` case $arg in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") arg="\"$arg\"" ;; esac ;; *.$objext) # A standard object. objs="$objs $arg" ;; *.lo) # A libtool-controlled object. # Check to see that this really is a libtool object. if (${SED} -e '2q' $arg | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then pic_object= non_pic_object= # Read the .lo file # If there is no directory component, then add one. case $arg in */* | *\\*) . $arg ;; *) . ./$arg ;; esac if test -z "$pic_object" || \ test -z "$non_pic_object" || test "$pic_object" = none && \ test "$non_pic_object" = none; then $echo "$modename: cannot find name of object for \`$arg'" 1>&2 exit 1 fi # Extract subdirectory from the argument. xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'` if test "X$xdir" = "X$arg"; then xdir= else xdir="$xdir/" fi if test "$pic_object" != none; then # Prepend the subdirectory the object is found in. pic_object="$xdir$pic_object" if test "$prev" = dlfiles; then if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then dlfiles="$dlfiles $pic_object" prev= continue else # If libtool objects are unsupported, then we need to preload. prev=dlprefiles fi fi # CHECK ME: I think I busted this. -Ossama if test "$prev" = dlprefiles; then # Preload the old-style object. dlprefiles="$dlprefiles $pic_object" prev= fi # A PIC object. libobjs="$libobjs $pic_object" arg="$pic_object" fi # Non-PIC object. if test "$non_pic_object" != none; then # Prepend the subdirectory the object is found in. non_pic_object="$xdir$non_pic_object" # A standard non-PIC object non_pic_objects="$non_pic_objects $non_pic_object" if test -z "$pic_object" || test "$pic_object" = none ; then arg="$non_pic_object" fi fi else # Only an error if not doing a dry-run. if test -z "$run"; then $echo "$modename: \`$arg' is not a valid libtool object" 1>&2 exit 1 else # Dry-run case. # Extract subdirectory from the argument. xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'` if test "X$xdir" = "X$arg"; then xdir= else xdir="$xdir/" fi pic_object=`$echo "X${xdir}${objdir}/${arg}" | $Xsed -e "$lo2o"` non_pic_object=`$echo "X${xdir}${arg}" | $Xsed -e "$lo2o"` libobjs="$libobjs $pic_object" non_pic_objects="$non_pic_objects $non_pic_object" fi fi ;; *.$libext) # An archive. deplibs="$deplibs $arg" old_deplibs="$old_deplibs $arg" continue ;; *.la) # A libtool-controlled library. if test "$prev" = dlfiles; then # This library was specified with -dlopen. dlfiles="$dlfiles $arg" prev= elif test "$prev" = dlprefiles; then # The library was specified with -dlpreopen. dlprefiles="$dlprefiles $arg" prev= else deplibs="$deplibs $arg" fi continue ;; # Some other compiler argument. *) # Unknown arguments in both finalize_command and compile_command need # to be aesthetically quoted because they are evaled later. arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` case $arg in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") arg="\"$arg\"" ;; esac ;; esac # arg # Now actually substitute the argument into the commands. if test -n "$arg"; then compile_command="$compile_command $arg" finalize_command="$finalize_command $arg" fi done # argument parsing loop if test -n "$prev"; then $echo "$modename: the \`$prevarg' option requires an argument" 1>&2 $echo "$help" 1>&2 exit 1 fi # Infer tagged configuration to use if any are available and # if one wasn't chosen via the "--tag" command line option. # Only attempt this if the compiler in the base link # command doesn't match the default compiler. if test -n "$available_tags" && test -z "$tagname"; then case $base_compile in # Blanks in the command may have been stripped by the calling shell, # but not from the CC environment variable when configure was run. "$CC "* | " $CC "* | "`$echo $CC` "* | " `$echo $CC` "*) ;; # Blanks at the start of $base_compile will cause this to fail # if we don't check for them as well. *) for z in $available_tags; do if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$0" > /dev/null; then # Evaluate the configuration. eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $0`" case $base_compile in "$CC "* | " $CC "* | "`$echo $CC` "* | " `$echo $CC` "*) # The compiler in $compile_command matches # the one in the tagged configuration. # Assume this is the tagged configuration we want. tagname=$z break ;; esac fi done # If $tagname still isn't set, then no tagged configuration # was found and let the user know that the "--tag" command # line option must be used. if test -z "$tagname"; then $echo "$modename: unable to infer tagged configuration" $echo "$modename: specify a tag with \`--tag'" 1>&2 exit 1 # else # $echo "$modename: using $tagname tagged configuration" fi ;; esac fi if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then eval arg=\"$export_dynamic_flag_spec\" compile_command="$compile_command $arg" finalize_command="$finalize_command $arg" fi oldlibs= # calculate the name of the file, without its directory outputname=`$echo "X$output" | $Xsed -e 's%^.*/%%'` libobjs_save="$libobjs" if test -n "$shlibpath_var"; then # get the directories listed in $shlibpath_var eval shlib_search_path=\`\$echo \"X\${$shlibpath_var}\" \| \$Xsed -e \'s/:/ /g\'\` else shlib_search_path= fi eval sys_lib_search_path=\"$sys_lib_search_path_spec\" eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" output_objdir=`$echo "X$output" | $Xsed -e 's%/[^/]*$%%'` if test "X$output_objdir" = "X$output"; then output_objdir="$objdir" else output_objdir="$output_objdir/$objdir" fi # Create the object directory. if test ! -d "$output_objdir"; then $show "$mkdir $output_objdir" $run $mkdir $output_objdir status=$? if test "$status" -ne 0 && test ! -d "$output_objdir"; then exit $status fi fi # Determine the type of output case $output in "") $echo "$modename: you must specify an output file" 1>&2 $echo "$help" 1>&2 exit 1 ;; *.$libext) linkmode=oldlib ;; *.lo | *.$objext) linkmode=obj ;; *.la) linkmode=lib ;; *) linkmode=prog ;; # Anything else should be a program. esac case $host in *cygwin* | *mingw* | *pw32*) # don't eliminate duplcations in $postdeps and $predeps duplicate_compiler_generated_deps=yes ;; *) duplicate_compiler_generated_deps=$duplicate_deps ;; esac specialdeplibs= libs= # Find all interdependent deplibs by searching for libraries # that are linked more than once (e.g. -la -lb -la) for deplib in $deplibs; do if test "X$duplicate_deps" = "Xyes" ; then case "$libs " in *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; esac fi libs="$libs $deplib" done if test "$linkmode" = lib; then libs="$predeps $libs $compiler_lib_search_path $postdeps" # Compute libraries that are listed more than once in $predeps # $postdeps and mark them as special (i.e., whose duplicates are # not to be eliminated). pre_post_deps= if test "X$duplicate_compiler_generated_deps" = "Xyes" ; then for pre_post_dep in $predeps $postdeps; do case "$pre_post_deps " in *" $pre_post_dep "*) specialdeplibs="$specialdeplibs $pre_post_deps" ;; esac pre_post_deps="$pre_post_deps $pre_post_dep" done fi pre_post_deps= fi deplibs= newdependency_libs= newlib_search_path= need_relink=no # whether we're linking any uninstalled libtool libraries notinst_deplibs= # not-installed libtool libraries notinst_path= # paths that contain not-installed libtool libraries case $linkmode in lib) passes="conv link" for file in $dlfiles $dlprefiles; do case $file in *.la) ;; *) $echo "$modename: libraries can \`-dlopen' only libtool libraries: $file" 1>&2 exit 1 ;; esac done ;; prog) compile_deplibs= finalize_deplibs= alldeplibs=no newdlfiles= newdlprefiles= passes="conv scan dlopen dlpreopen link" ;; *) passes="conv" ;; esac for pass in $passes; do if test "$linkmode,$pass" = "lib,link" || test "$linkmode,$pass" = "prog,scan"; then libs="$deplibs" deplibs= fi if test "$linkmode" = prog; then case $pass in dlopen) libs="$dlfiles" ;; dlpreopen) libs="$dlprefiles" ;; link) libs="$deplibs %DEPLIBS% $dependency_libs" ;; esac fi if test "$pass" = dlopen; then # Collect dlpreopened libraries save_deplibs="$deplibs" deplibs= fi for deplib in $libs; do lib= found=no case $deplib in -l*) if test "$linkmode" != lib && test "$linkmode" != prog; then $echo "$modename: warning: \`-l' is ignored for archives/objects" 1>&2 continue fi if test "$pass" = conv; then deplibs="$deplib $deplibs" continue fi name=`$echo "X$deplib" | $Xsed -e 's/^-l//'` for searchdir in $newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path; do for search_ext in .la $shrext .so .a; do # Search the libtool library lib="$searchdir/lib${name}${search_ext}" if test -f "$lib"; then if test "$search_ext" = ".la"; then found=yes else found=no fi break 2 fi done done if test "$found" != yes; then # deplib doesn't seem to be a libtool library if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" fi continue else # deplib is a libtool library # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, # We need to do some special things here, and not later. if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then case " $predeps $postdeps " in *" $deplib "*) if (${SED} -e '2q' $lib | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then library_names= old_library= case $lib in */* | *\\*) . $lib ;; *) . ./$lib ;; esac for l in $old_library $library_names; do ll="$l" done if test "X$ll" = "X$old_library" ; then # only static version available found=no ladir=`$echo "X$lib" | $Xsed -e 's%/[^/]*$%%'` test "X$ladir" = "X$lib" && ladir="." lib=$ladir/$old_library if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" fi continue fi fi ;; *) ;; esac fi fi ;; # -l -L*) case $linkmode in lib) deplibs="$deplib $deplibs" test "$pass" = conv && continue newdependency_libs="$deplib $newdependency_libs" newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'` ;; prog) if test "$pass" = conv; then deplibs="$deplib $deplibs" continue fi if test "$pass" = scan; then deplibs="$deplib $deplibs" newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'` else compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" fi ;; *) $echo "$modename: warning: \`-L' is ignored for archives/objects" 1>&2 ;; esac # linkmode continue ;; # -L -R*) if test "$pass" = link; then dir=`$echo "X$deplib" | $Xsed -e 's/^-R//'` # Make sure the xrpath contains only unique directories. case "$xrpath " in *" $dir "*) ;; *) xrpath="$xrpath $dir" ;; esac fi deplibs="$deplib $deplibs" continue ;; *.la) lib="$deplib" ;; *.$libext) if test "$pass" = conv; then deplibs="$deplib $deplibs" continue fi case $linkmode in lib) if test "$deplibs_check_method" != pass_all; then $echo $echo "*** Warning: Trying to link with static lib archive $deplib." $echo "*** I have the capability to make that library automatically link in when" $echo "*** you link to this library. But I can only do this if you have a" $echo "*** shared version of the library, which you do not appear to have" $echo "*** because the file extensions .$libext of this argument makes me believe" $echo "*** that it is just a static archive that I should not used here." else $echo $echo "*** Warning: Linking the shared library $output against the" $echo "*** static library $deplib is not portable!" deplibs="$deplib $deplibs" fi continue ;; prog) if test "$pass" != link; then deplibs="$deplib $deplibs" else compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" fi continue ;; esac # linkmode ;; # *.$libext *.lo | *.$objext) if test "$pass" = conv; then deplibs="$deplib $deplibs" elif test "$linkmode" = prog; then if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then # If there is no dlopen support or we're linking statically, # we need to preload. newdlprefiles="$newdlprefiles $deplib" compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else newdlfiles="$newdlfiles $deplib" fi fi continue ;; %DEPLIBS%) alldeplibs=yes continue ;; esac # case $deplib if test "$found" = yes || test -f "$lib"; then : else $echo "$modename: cannot find the library \`$lib'" 1>&2 exit 1 fi # Check to see that this really is a libtool archive. if (${SED} -e '2q' $lib | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : else $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 exit 1 fi ladir=`$echo "X$lib" | $Xsed -e 's%/[^/]*$%%'` test "X$ladir" = "X$lib" && ladir="." dlname= dlopen= dlpreopen= libdir= library_names= old_library= # If the library was installed with an old release of libtool, # it will not redefine variables installed, or shouldnotlink installed=yes shouldnotlink=no # Read the .la file case $lib in */* | *\\*) . $lib ;; *) . ./$lib ;; esac if test "$linkmode,$pass" = "lib,link" || test "$linkmode,$pass" = "prog,scan" || { test "$linkmode" != prog && test "$linkmode" != lib; }; then test -n "$dlopen" && dlfiles="$dlfiles $dlopen" test -n "$dlpreopen" && dlprefiles="$dlprefiles $dlpreopen" fi if test "$pass" = conv; then # Only check for convenience libraries deplibs="$lib $deplibs" if test -z "$libdir"; then if test -z "$old_library"; then $echo "$modename: cannot find name of link library for \`$lib'" 1>&2 exit 1 fi # It is a libtool convenience library, so add in its objects. convenience="$convenience $ladir/$objdir/$old_library" old_convenience="$old_convenience $ladir/$objdir/$old_library" tmp_libs= for deplib in $dependency_libs; do deplibs="$deplib $deplibs" if test "X$duplicate_deps" = "Xyes" ; then case "$tmp_libs " in *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; esac fi tmp_libs="$tmp_libs $deplib" done elif test "$linkmode" != prog && test "$linkmode" != lib; then $echo "$modename: \`$lib' is not a convenience library" 1>&2 exit 1 fi continue fi # $pass = conv # Get the name of the library we link against. linklib= for l in $old_library $library_names; do linklib="$l" done if test -z "$linklib"; then $echo "$modename: cannot find name of link library for \`$lib'" 1>&2 exit 1 fi # This library was specified with -dlopen. if test "$pass" = dlopen; then if test -z "$libdir"; then $echo "$modename: cannot -dlopen a convenience library: \`$lib'" 1>&2 exit 1 fi if test -z "$dlname" || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then # If there is no dlname, no dlopen support or we're linking # statically, we need to preload. We also need to preload any # dependent libraries so libltdl's deplib preloader doesn't # bomb out in the load deplibs phase. dlprefiles="$dlprefiles $lib $dependency_libs" else newdlfiles="$newdlfiles $lib" fi continue fi # $pass = dlopen # We need an absolute path. case $ladir in [\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;; *) abs_ladir=`cd "$ladir" && pwd` if test -z "$abs_ladir"; then $echo "$modename: warning: cannot determine absolute directory name of \`$ladir'" 1>&2 $echo "$modename: passing it literally to the linker, although it might fail" 1>&2 abs_ladir="$ladir" fi ;; esac laname=`$echo "X$lib" | $Xsed -e 's%^.*/%%'` # Find the relevant object directory and library name. if test "X$installed" = Xyes; then if test ! -f "$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then $echo "$modename: warning: library \`$lib' was moved." 1>&2 dir="$ladir" absdir="$abs_ladir" libdir="$abs_ladir" else dir="$libdir" absdir="$libdir" fi else dir="$ladir/$objdir" absdir="$abs_ladir/$objdir" # Remove this search path later notinst_path="$notinst_path $abs_ladir" fi # $installed = yes name=`$echo "X$laname" | $Xsed -e 's/\.la$//' -e 's/^lib//'` # This library was specified with -dlpreopen. if test "$pass" = dlpreopen; then if test -z "$libdir"; then $echo "$modename: cannot -dlpreopen a convenience library: \`$lib'" 1>&2 exit 1 fi # Prefer using a static library (so that no silly _DYNAMIC symbols # are required to link). if test -n "$old_library"; then newdlprefiles="$newdlprefiles $dir/$old_library" # Otherwise, use the dlname, so that lt_dlopen finds it. elif test -n "$dlname"; then newdlprefiles="$newdlprefiles $dir/$dlname" else newdlprefiles="$newdlprefiles $dir/$linklib" fi fi # $pass = dlpreopen if test -z "$libdir"; then # Link the convenience library if test "$linkmode" = lib; then deplibs="$dir/$old_library $deplibs" elif test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$dir/$old_library $compile_deplibs" finalize_deplibs="$dir/$old_library $finalize_deplibs" else deplibs="$lib $deplibs" # used for prog,scan pass fi continue fi if test "$linkmode" = prog && test "$pass" != link; then newlib_search_path="$newlib_search_path $ladir" deplibs="$lib $deplibs" linkalldeplibs=no if test "$link_all_deplibs" != no || test -z "$library_names" || test "$build_libtool_libs" = no; then linkalldeplibs=yes fi tmp_libs= for deplib in $dependency_libs; do case $deplib in -L*) newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'`;; ### testsuite: skip nested quoting test esac # Need to link against all dependency_libs? if test "$linkalldeplibs" = yes; then deplibs="$deplib $deplibs" else # Need to hardcode shared library paths # or/and link against static libraries newdependency_libs="$deplib $newdependency_libs" fi if test "X$duplicate_deps" = "Xyes" ; then case "$tmp_libs " in *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; esac fi tmp_libs="$tmp_libs $deplib" done # for deplib continue fi # $linkmode = prog... if test "$linkmode,$pass" = "prog,link"; then if test -n "$library_names" && { test "$prefer_static_libs" = no || test -z "$old_library"; }; then # We need to hardcode the library path if test -n "$shlibpath_var"; then # Make sure the rpath contains only unique directories. case "$temp_rpath " in *" $dir "*) ;; *" $absdir "*) ;; *) temp_rpath="$temp_rpath $dir" ;; esac fi # Hardcode the library path. # Skip directories that are in the system default run-time # search path. case " $sys_lib_dlsearch_path " in *" $absdir "*) ;; *) case "$compile_rpath " in *" $absdir "*) ;; *) compile_rpath="$compile_rpath $absdir" esac ;; esac case " $sys_lib_dlsearch_path " in *" $libdir "*) ;; *) case "$finalize_rpath " in *" $libdir "*) ;; *) finalize_rpath="$finalize_rpath $libdir" esac ;; esac fi # $linkmode,$pass = prog,link... if test "$alldeplibs" = yes && { test "$deplibs_check_method" = pass_all || { test "$build_libtool_libs" = yes && test -n "$library_names"; }; }; then # We only need to search for static libraries continue fi fi link_static=no # Whether the deplib will be linked statically if test -n "$library_names" && { test "$prefer_static_libs" = no || test -z "$old_library"; }; then if test "$installed" = no; then notinst_deplibs="$notinst_deplibs $lib" need_relink=yes fi # This is a shared library # Warn about portability, can't link against -module's on some systems (darwin) if test "$shouldnotlink" = yes && test "$pass" = link ; then $echo if test "$linkmode" = prog; then $echo "*** Warning: Linking the executable $output against the loadable module" else $echo "*** Warning: Linking the shared library $output against the loadable module" fi $echo "*** $linklib is not portable!" fi if test "$linkmode" = lib && test "$hardcode_into_libs" = yes; then # Hardcode the library path. # Skip directories that are in the system default run-time # search path. case " $sys_lib_dlsearch_path " in *" $absdir "*) ;; *) case "$compile_rpath " in *" $absdir "*) ;; *) compile_rpath="$compile_rpath $absdir" esac ;; esac case " $sys_lib_dlsearch_path " in *" $libdir "*) ;; *) case "$finalize_rpath " in *" $libdir "*) ;; *) finalize_rpath="$finalize_rpath $libdir" esac ;; esac fi if test -n "$old_archive_from_expsyms_cmds"; then # figure out the soname set dummy $library_names realname="$2" shift; shift libname=`eval \\$echo \"$libname_spec\"` # use dlname if we got it. it's perfectly good, no? if test -n "$dlname"; then soname="$dlname" elif test -n "$soname_spec"; then # bleh windows case $host in *cygwin* | mingw*) major=`expr $current - $age` versuffix="-$major" ;; esac eval soname=\"$soname_spec\" else soname="$realname" fi # Make a new name for the extract_expsyms_cmds to use soroot="$soname" soname=`$echo $soroot | ${SED} -e 's/^.*\///'` newlib="libimp-`$echo $soname | ${SED} 's/^lib//;s/\.dll$//'`.a" # If the library has no export list, then create one now if test -f "$output_objdir/$soname-def"; then : else $show "extracting exported symbol list from \`$soname'" save_ifs="$IFS"; IFS='~' eval cmds=\"$extract_expsyms_cmds\" for cmd in $cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" || exit $? done IFS="$save_ifs" fi # Create $newlib if test -f "$output_objdir/$newlib"; then :; else $show "generating import library for \`$soname'" save_ifs="$IFS"; IFS='~' eval cmds=\"$old_archive_from_expsyms_cmds\" for cmd in $cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" || exit $? done IFS="$save_ifs" fi # make sure the library variables are pointing to the new library dir=$output_objdir linklib=$newlib fi # test -n "$old_archive_from_expsyms_cmds" if test "$linkmode" = prog || test "$mode" != relink; then add_shlibpath= add_dir= add= lib_linked=yes case $hardcode_action in immediate | unsupported) if test "$hardcode_direct" = no; then add="$dir/$linklib" case $host in *-*-sco3.2v5* ) add_dir="-L$dir" ;; *-*-darwin* ) # if the lib is a module then we can not link against it, someone # is ignoring the new warnings I added if /usr/bin/file -L $add 2> /dev/null | grep "bundle" >/dev/null ; then $echo "** Warning, lib $linklib is a module, not a shared library" if test -z "$old_library" ; then $echo $echo "** And there doesn't seem to be a static archive available" $echo "** The link will probably fail, sorry" else add="$dir/$old_library" fi fi esac elif test "$hardcode_minus_L" = no; then case $host in *-*-sunos*) add_shlibpath="$dir" ;; esac add_dir="-L$dir" add="-l$name" elif test "$hardcode_shlibpath_var" = no; then add_shlibpath="$dir" add="-l$name" else lib_linked=no fi ;; relink) if test "$hardcode_direct" = yes; then add="$dir/$linklib" elif test "$hardcode_minus_L" = yes; then add_dir="-L$dir" # Try looking first in the location we're being installed to. if test -n "$inst_prefix_dir"; then case "$libdir" in [\\/]*) add_dir="-L$inst_prefix_dir$libdir $add_dir" ;; esac fi add="-l$name" elif test "$hardcode_shlibpath_var" = yes; then add_shlibpath="$dir" add="-l$name" else lib_linked=no fi ;; *) lib_linked=no ;; esac if test "$lib_linked" != yes; then $echo "$modename: configuration error: unsupported hardcode properties" exit 1 fi if test -n "$add_shlibpath"; then case :$compile_shlibpath: in *":$add_shlibpath:"*) ;; *) compile_shlibpath="$compile_shlibpath$add_shlibpath:" ;; esac fi if test "$linkmode" = prog; then test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" test -n "$add" && compile_deplibs="$add $compile_deplibs" else test -n "$add_dir" && deplibs="$add_dir $deplibs" test -n "$add" && deplibs="$add $deplibs" if test "$hardcode_direct" != yes && \ test "$hardcode_minus_L" != yes && \ test "$hardcode_shlibpath_var" = yes; then case :$finalize_shlibpath: in *":$libdir:"*) ;; *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;; esac fi fi fi if test "$linkmode" = prog || test "$mode" = relink; then add_shlibpath= add_dir= add= # Finalize command for both is simple: just hardcode it. if test "$hardcode_direct" = yes; then add="$libdir/$linklib" elif test "$hardcode_minus_L" = yes; then add_dir="-L$libdir" add="-l$name" elif test "$hardcode_shlibpath_var" = yes; then case :$finalize_shlibpath: in *":$libdir:"*) ;; *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;; esac add="-l$name" elif test "$hardcode_automatic" = yes; then if test -n "$inst_prefix_dir" && test -f "$inst_prefix_dir$libdir/$linklib" ; then add="$inst_prefix_dir$libdir/$linklib" else add="$libdir/$linklib" fi else # We cannot seem to hardcode it, guess we'll fake it. add_dir="-L$libdir" # Try looking first in the location we're being installed to. if test -n "$inst_prefix_dir"; then case "$libdir" in [\\/]*) add_dir="-L$inst_prefix_dir$libdir $add_dir" ;; esac fi add="-l$name" fi if test "$linkmode" = prog; then test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" test -n "$add" && finalize_deplibs="$add $finalize_deplibs" else test -n "$add_dir" && deplibs="$add_dir $deplibs" test -n "$add" && deplibs="$add $deplibs" fi fi elif test "$linkmode" = prog; then # Here we assume that one of hardcode_direct or hardcode_minus_L # is not unsupported. This is valid on all known static and # shared platforms. if test "$hardcode_direct" != unsupported; then test -n "$old_library" && linklib="$old_library" compile_deplibs="$dir/$linklib $compile_deplibs" finalize_deplibs="$dir/$linklib $finalize_deplibs" else compile_deplibs="-l$name -L$dir $compile_deplibs" finalize_deplibs="-l$name -L$dir $finalize_deplibs" fi elif test "$build_libtool_libs" = yes; then # Not a shared library if test "$deplibs_check_method" != pass_all; then # We're trying link a shared library against a static one # but the system doesn't support it. # Just print a warning and add the library to dependency_libs so # that the program can be linked against the static library. $echo $echo "*** Warning: This system can not link to static lib archive $lib." $echo "*** I have the capability to make that library automatically link in when" $echo "*** you link to this library. But I can only do this if you have a" $echo "*** shared version of the library, which you do not appear to have." if test "$module" = yes; then $echo "*** But as you try to build a module library, libtool will still create " $echo "*** a static module, that should work as long as the dlopening application" $echo "*** is linked with the -dlopen flag to resolve symbols at runtime." if test -z "$global_symbol_pipe"; then $echo $echo "*** However, this would only work if libtool was able to extract symbol" $echo "*** lists from a program, using \`nm' or equivalent, but libtool could" $echo "*** not find such a program. So, this module is probably useless." $echo "*** \`nm' from GNU binutils and a full rebuild may help." fi if test "$build_old_libs" = no; then build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi fi else convenience="$convenience $dir/$old_library" old_convenience="$old_convenience $dir/$old_library" deplibs="$dir/$old_library $deplibs" link_static=yes fi fi # link shared/static library? if test "$linkmode" = lib; then if test -n "$dependency_libs" && { test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes || test "$link_static" = yes; }; then # Extract -R from dependency_libs temp_deplibs= for libdir in $dependency_libs; do case $libdir in -R*) temp_xrpath=`$echo "X$libdir" | $Xsed -e 's/^-R//'` case " $xrpath " in *" $temp_xrpath "*) ;; *) xrpath="$xrpath $temp_xrpath";; esac;; *) temp_deplibs="$temp_deplibs $libdir";; esac done dependency_libs="$temp_deplibs" fi newlib_search_path="$newlib_search_path $absdir" # Link against this library test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs" # ... and its dependency_libs tmp_libs= for deplib in $dependency_libs; do newdependency_libs="$deplib $newdependency_libs" if test "X$duplicate_deps" = "Xyes" ; then case "$tmp_libs " in *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; esac fi tmp_libs="$tmp_libs $deplib" done if test "$link_all_deplibs" != no; then # Add the search paths of all dependency libraries for deplib in $dependency_libs; do case $deplib in -L*) path="$deplib" ;; *.la) dir=`$echo "X$deplib" | $Xsed -e 's%/[^/]*$%%'` test "X$dir" = "X$deplib" && dir="." # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;; *) absdir=`cd "$dir" && pwd` if test -z "$absdir"; then $echo "$modename: warning: cannot determine absolute directory name of \`$dir'" 1>&2 absdir="$dir" fi ;; esac if grep "^installed=no" $deplib > /dev/null; then path="$absdir/$objdir" else eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` if test -z "$libdir"; then $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2 exit 1 fi if test "$absdir" != "$libdir"; then $echo "$modename: warning: \`$deplib' seems to be moved" 1>&2 fi path="$absdir" fi depdepl= case $host in *-*-darwin*) # we do not want to link against static libs, but need to link against shared eval deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` if test -n "$deplibrary_names" ; then for tmp in $deplibrary_names ; do depdepl=$tmp done if test -f "$path/$depdepl" ; then depdepl="$path/$depdepl" fi # do not add paths which are already there case " $newlib_search_path " in *" $path "*) ;; *) newlib_search_path="$newlib_search_path $path";; esac path="" fi ;; *) path="-L$path" ;; esac ;; -l*) case $host in *-*-darwin*) # Again, we only want to link against shared libraries eval tmp_libs=`$echo "X$deplib" | $Xsed -e "s,^\-l,,"` for tmp in $newlib_search_path ; do if test -f "$tmp/lib$tmp_libs.dylib" ; then eval depdepl="$tmp/lib$tmp_libs.dylib" break fi done path="" ;; *) continue ;; esac ;; *) continue ;; esac case " $deplibs " in *" $depdepl "*) ;; *) deplibs="$deplibs $depdepl" ;; esac case " $deplibs " in *" $path "*) ;; *) deplibs="$deplibs $path" ;; esac done fi # link_all_deplibs != no fi # linkmode = lib done # for deplib in $libs dependency_libs="$newdependency_libs" if test "$pass" = dlpreopen; then # Link the dlpreopened libraries before other libraries for deplib in $save_deplibs; do deplibs="$deplib $deplibs" done fi if test "$pass" != dlopen; then if test "$pass" != conv; then # Make sure lib_search_path contains only unique directories. lib_search_path= for dir in $newlib_search_path; do case "$lib_search_path " in *" $dir "*) ;; *) lib_search_path="$lib_search_path $dir" ;; esac done newlib_search_path= fi if test "$linkmode,$pass" != "prog,link"; then vars="deplibs" else vars="compile_deplibs finalize_deplibs" fi for var in $vars dependency_libs; do # Add libraries to $var in reverse order eval tmp_libs=\"\$$var\" new_libs= for deplib in $tmp_libs; do # FIXME: Pedantically, this is the right thing to do, so # that some nasty dependency loop isn't accidentally # broken: #new_libs="$deplib $new_libs" # Pragmatically, this seems to cause very few problems in # practice: case $deplib in -L*) new_libs="$deplib $new_libs" ;; -R*) ;; *) # And here is the reason: when a library appears more # than once as an explicit dependence of a library, or # is implicitly linked in more than once by the # compiler, it is considered special, and multiple # occurrences thereof are not removed. Compare this # with having the same library being listed as a # dependency of multiple other libraries: in this case, # we know (pedantically, we assume) the library does not # need to be listed more than once, so we keep only the # last copy. This is not always right, but it is rare # enough that we require users that really mean to play # such unportable linking tricks to link the library # using -Wl,-lname, so that libtool does not consider it # for duplicate removal. case " $specialdeplibs " in *" $deplib "*) new_libs="$deplib $new_libs" ;; *) case " $new_libs " in *" $deplib "*) ;; *) new_libs="$deplib $new_libs" ;; esac ;; esac ;; esac done tmp_libs= for deplib in $new_libs; do case $deplib in -L*) case " $tmp_libs " in *" $deplib "*) ;; *) tmp_libs="$tmp_libs $deplib" ;; esac ;; *) tmp_libs="$tmp_libs $deplib" ;; esac done eval $var=\"$tmp_libs\" done # for var fi # Last step: remove runtime libs from dependency_libs (they stay in deplibs) tmp_libs= for i in $dependency_libs ; do case " $predeps $postdeps $compiler_lib_search_path " in *" $i "*) i="" ;; esac if test -n "$i" ; then tmp_libs="$tmp_libs $i" fi done dependency_libs=$tmp_libs done # for pass if test "$linkmode" = prog; then dlfiles="$newdlfiles" dlprefiles="$newdlprefiles" fi case $linkmode in oldlib) if test -n "$deplibs"; then $echo "$modename: warning: \`-l' and \`-L' are ignored for archives" 1>&2 fi if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then $echo "$modename: warning: \`-dlopen' is ignored for archives" 1>&2 fi if test -n "$rpath"; then $echo "$modename: warning: \`-rpath' is ignored for archives" 1>&2 fi if test -n "$xrpath"; then $echo "$modename: warning: \`-R' is ignored for archives" 1>&2 fi if test -n "$vinfo"; then $echo "$modename: warning: \`-version-info/-version-number' is ignored for archives" 1>&2 fi if test -n "$release"; then $echo "$modename: warning: \`-release' is ignored for archives" 1>&2 fi if test -n "$export_symbols" || test -n "$export_symbols_regex"; then $echo "$modename: warning: \`-export-symbols' is ignored for archives" 1>&2 fi # Now set the variables for building old libraries. build_libtool_libs=no oldlibs="$output" objs="$objs$old_deplibs" ;; lib) # Make sure we only generate libraries of the form `libNAME.la'. case $outputname in lib*) name=`$echo "X$outputname" | $Xsed -e 's/\.la$//' -e 's/^lib//'` eval shared_ext=\"$shrext\" eval libname=\"$libname_spec\" ;; *) if test "$module" = no; then $echo "$modename: libtool library \`$output' must begin with \`lib'" 1>&2 $echo "$help" 1>&2 exit 1 fi if test "$need_lib_prefix" != no; then # Add the "lib" prefix for modules if required name=`$echo "X$outputname" | $Xsed -e 's/\.la$//'` eval shared_ext=\"$shrext\" eval libname=\"$libname_spec\" else libname=`$echo "X$outputname" | $Xsed -e 's/\.la$//'` fi ;; esac if test -n "$objs"; then if test "$deplibs_check_method" != pass_all; then $echo "$modename: cannot build libtool library \`$output' from non-libtool objects on this host:$objs" 2>&1 exit 1 else $echo $echo "*** Warning: Linking the shared library $output against the non-libtool" $echo "*** objects $objs is not portable!" libobjs="$libobjs $objs" fi fi if test "$dlself" != no; then $echo "$modename: warning: \`-dlopen self' is ignored for libtool libraries" 1>&2 fi set dummy $rpath if test "$#" -gt 2; then $echo "$modename: warning: ignoring multiple \`-rpath's for a libtool library" 1>&2 fi install_libdir="$2" oldlibs= if test -z "$rpath"; then if test "$build_libtool_libs" = yes; then # Building a libtool convenience library. # Some compilers have problems with a `.al' extension so # convenience libraries should have the same extension an # archive normally would. oldlibs="$output_objdir/$libname.$libext $oldlibs" build_libtool_libs=convenience build_old_libs=yes fi if test -n "$vinfo"; then $echo "$modename: warning: \`-version-info/-version-number' is ignored for convenience libraries" 1>&2 fi if test -n "$release"; then $echo "$modename: warning: \`-release' is ignored for convenience libraries" 1>&2 fi else # Parse the version information argument. save_ifs="$IFS"; IFS=':' set dummy $vinfo 0 0 0 IFS="$save_ifs" if test -n "$8"; then $echo "$modename: too many parameters to \`-version-info'" 1>&2 $echo "$help" 1>&2 exit 1 fi # convert absolute version numbers to libtool ages # this retains compatibility with .la files and attempts # to make the code below a bit more comprehensible case $vinfo_number in yes) number_major="$2" number_minor="$3" number_revision="$4" # # There are really only two kinds -- those that # use the current revision as the major version # and those that subtract age and use age as # a minor version. But, then there is irix # which has an extra 1 added just for fun # case $version_type in darwin|linux|osf|windows) current=`expr $number_major + $number_minor` age="$number_minor" revision="$number_revision" ;; freebsd-aout|freebsd-elf|sunos) current="$number_major" revision="$number_minor" age="0" ;; irix|nonstopux) current=`expr $number_major + $number_minor - 1` age="$number_minor" revision="$number_minor" ;; esac ;; no) current="$2" revision="$3" age="$4" ;; esac # Check that each of the things are valid numbers. case $current in 0 | [1-9] | [1-9][0-9] | [1-9][0-9][0-9]) ;; *) $echo "$modename: CURRENT \`$current' is not a nonnegative integer" 1>&2 $echo "$modename: \`$vinfo' is not valid version information" 1>&2 exit 1 ;; esac case $revision in 0 | [1-9] | [1-9][0-9] | [1-9][0-9][0-9]) ;; *) $echo "$modename: REVISION \`$revision' is not a nonnegative integer" 1>&2 $echo "$modename: \`$vinfo' is not valid version information" 1>&2 exit 1 ;; esac case $age in 0 | [1-9] | [1-9][0-9] | [1-9][0-9][0-9]) ;; *) $echo "$modename: AGE \`$age' is not a nonnegative integer" 1>&2 $echo "$modename: \`$vinfo' is not valid version information" 1>&2 exit 1 ;; esac if test "$age" -gt "$current"; then $echo "$modename: AGE \`$age' is greater than the current interface number \`$current'" 1>&2 $echo "$modename: \`$vinfo' is not valid version information" 1>&2 exit 1 fi # Calculate the version variables. major= versuffix= verstring= case $version_type in none) ;; darwin) # Like Linux, but with the current version available in # verstring for coding it into the library header major=.`expr $current - $age` versuffix="$major.$age.$revision" # Darwin ld doesn't like 0 for these options... minor_current=`expr $current + 1` verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" ;; freebsd-aout) major=".$current" versuffix=".$current.$revision"; ;; freebsd-elf) major=".$current" versuffix=".$current"; ;; irix | nonstopux) major=`expr $current - $age + 1` case $version_type in nonstopux) verstring_prefix=nonstopux ;; *) verstring_prefix=sgi ;; esac verstring="$verstring_prefix$major.$revision" # Add in all the interfaces that we are compatible with. loop=$revision while test "$loop" -ne 0; do iface=`expr $revision - $loop` loop=`expr $loop - 1` verstring="$verstring_prefix$major.$iface:$verstring" done # Before this point, $major must not contain `.'. major=.$major versuffix="$major.$revision" ;; linux) major=.`expr $current - $age` versuffix="$major.$age.$revision" ;; osf) major=.`expr $current - $age` versuffix=".$current.$age.$revision" verstring="$current.$age.$revision" # Add in all the interfaces that we are compatible with. loop=$age while test "$loop" -ne 0; do iface=`expr $current - $loop` loop=`expr $loop - 1` verstring="$verstring:${iface}.0" done # Make executables depend on our current version. verstring="$verstring:${current}.0" ;; sunos) major=".$current" versuffix=".$current.$revision" ;; windows) # Use '-' rather than '.', since we only want one # extension on DOS 8.3 filesystems. major=`expr $current - $age` versuffix="-$major" ;; *) $echo "$modename: unknown library version type \`$version_type'" 1>&2 $echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2 exit 1 ;; esac # Clear the version info if we defaulted, and they specified a release. if test -z "$vinfo" && test -n "$release"; then major= case $version_type in darwin) # we can't check for "0.0" in archive_cmds due to quoting # problems, so we reset it completely verstring= ;; *) verstring="0.0" ;; esac if test "$need_version" = no; then versuffix= else versuffix=".0.0" fi fi # Remove version info from name if versioning should be avoided if test "$avoid_version" = yes && test "$need_version" = no; then major= versuffix= verstring="" fi # Check to see if the archive will have undefined symbols. if test "$allow_undefined" = yes; then if test "$allow_undefined_flag" = unsupported; then $echo "$modename: warning: undefined symbols not allowed in $host shared libraries" 1>&2 build_libtool_libs=no build_old_libs=yes fi else # Don't allow undefined symbols. allow_undefined_flag="$no_undefined_flag" fi fi if test "$mode" != relink; then # Remove our outputs, but don't remove object files since they # may have been created when compiling PIC objects. removelist= tempremovelist=`$echo "$output_objdir/*"` for p in $tempremovelist; do case $p in *.$objext) ;; $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*) removelist="$removelist $p" ;; *) ;; esac done if test -n "$removelist"; then $show "${rm}r $removelist" $run ${rm}r $removelist fi fi # Now set the variables for building old libraries. if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then oldlibs="$oldlibs $output_objdir/$libname.$libext" # Transform .lo files to .o files. oldobjs="$objs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e "$lo2o" | $NL2SP` fi # Eliminate all temporary directories. for path in $notinst_path; do lib_search_path=`$echo "$lib_search_path " | ${SED} -e 's% $path % %g'` deplibs=`$echo "$deplibs " | ${SED} -e 's% -L$path % %g'` dependency_libs=`$echo "$dependency_libs " | ${SED} -e 's% -L$path % %g'` done if test -n "$xrpath"; then # If the user specified any rpath flags, then add them. temp_xrpath= for libdir in $xrpath; do temp_xrpath="$temp_xrpath -R$libdir" case "$finalize_rpath " in *" $libdir "*) ;; *) finalize_rpath="$finalize_rpath $libdir" ;; esac done if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then dependency_libs="$temp_xrpath $dependency_libs" fi fi # Make sure dlfiles contains only unique files that won't be dlpreopened old_dlfiles="$dlfiles" dlfiles= for lib in $old_dlfiles; do case " $dlprefiles $dlfiles " in *" $lib "*) ;; *) dlfiles="$dlfiles $lib" ;; esac done # Make sure dlprefiles contains only unique files old_dlprefiles="$dlprefiles" dlprefiles= for lib in $old_dlprefiles; do case "$dlprefiles " in *" $lib "*) ;; *) dlprefiles="$dlprefiles $lib" ;; esac done if test "$build_libtool_libs" = yes; then if test -n "$rpath"; then case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos*) # these systems don't actually have a c library (as such)! ;; *-*-rhapsody* | *-*-darwin1.[012]) # Rhapsody C library is in the System framework deplibs="$deplibs -framework System" ;; *-*-netbsd*) # Don't link with libc until the a.out ld.so is fixed. ;; *-*-openbsd* | *-*-freebsd*) # Do not include libc due to us having libc/libc_r. test "X$arg" = "X-lc" && continue ;; *) # Add libc to deplibs on all other systems if necessary. if test "$build_libtool_need_lc" = "yes"; then deplibs="$deplibs -lc" fi ;; esac fi # Transform deplibs into only deplibs that can be linked in shared. name_save=$name libname_save=$libname release_save=$release versuffix_save=$versuffix major_save=$major # I'm not sure if I'm treating the release correctly. I think # release should show up in the -l (ie -lgmp5) so we don't want to # add it in twice. Is that correct? release="" versuffix="" major="" newdeplibs= droppeddeps=no case $deplibs_check_method in pass_all) # Don't check for shared/static. Everything works. # This might be a little naive. We might want to check # whether the library exists or not. But this is on # osf3 & osf4 and I'm not really sure... Just # implementing what was already the behavior. newdeplibs=$deplibs ;; test_compile) # This code stresses the "libraries are programs" paradigm to its # limits. Maybe even breaks it. We compile a program, linking it # against the deplibs as a proxy for the library. Then we can check # whether they linked in statically or dynamically with ldd. $rm conftest.c cat > conftest.c </dev/null` for potent_lib in $potential_libs; do # Follow soft links. if ls -lLd "$potent_lib" 2>/dev/null \ | grep " -> " >/dev/null; then continue fi # The statement above tries to avoid entering an # endless loop below, in case of cyclic links. # We might still enter an endless loop, since a link # loop can be closed while we follow links, # but so what? potlib="$potent_lib" while test -h "$potlib" 2>/dev/null; do potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'` case $potliblink in [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";; *) potlib=`$echo "X$potlib" | $Xsed -e 's,[^/]*$,,'`"$potliblink";; esac done if eval $file_magic_cmd \"\$potlib\" 2>/dev/null \ | ${SED} 10q \ | $EGREP "$file_magic_regex" > /dev/null; then newdeplibs="$newdeplibs $a_deplib" a_deplib="" break 2 fi done done fi if test -n "$a_deplib" ; then droppeddeps=yes $echo $echo "*** Warning: linker path does not have real file for library $a_deplib." $echo "*** I have the capability to make that library automatically link in when" $echo "*** you link to this library. But I can only do this if you have a" $echo "*** shared version of the library, which you do not appear to have" $echo "*** because I did check the linker path looking for a file starting" if test -z "$potlib" ; then $echo "*** with $libname but no candidates were found. (...for file magic test)" else $echo "*** with $libname and none of the candidates passed a file format test" $echo "*** using a file magic. Last file checked: $potlib" fi fi else # Add a -L argument. newdeplibs="$newdeplibs $a_deplib" fi done # Gone through all deplibs. ;; match_pattern*) set dummy $deplibs_check_method match_pattern_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"` for a_deplib in $deplibs; do name="`expr $a_deplib : '-l\(.*\)'`" # If $name is empty we are operating on a -L argument. if test -n "$name" && test "$name" != "0"; then if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then case " $predeps $postdeps " in *" $a_deplib "*) newdeplibs="$newdeplibs $a_deplib" a_deplib="" ;; esac fi if test -n "$a_deplib" ; then libname=`eval \\$echo \"$libname_spec\"` for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do potential_libs=`ls $i/$libname[.-]* 2>/dev/null` for potent_lib in $potential_libs; do potlib="$potent_lib" # see symlink-check above in file_magic test if eval $echo \"$potent_lib\" 2>/dev/null \ | ${SED} 10q \ | $EGREP "$match_pattern_regex" > /dev/null; then newdeplibs="$newdeplibs $a_deplib" a_deplib="" break 2 fi done done fi if test -n "$a_deplib" ; then droppeddeps=yes $echo $echo "*** Warning: linker path does not have real file for library $a_deplib." $echo "*** I have the capability to make that library automatically link in when" $echo "*** you link to this library. But I can only do this if you have a" $echo "*** shared version of the library, which you do not appear to have" $echo "*** because I did check the linker path looking for a file starting" if test -z "$potlib" ; then $echo "*** with $libname but no candidates were found. (...for regex pattern test)" else $echo "*** with $libname and none of the candidates passed a file format test" $echo "*** using a regex pattern. Last file checked: $potlib" fi fi else # Add a -L argument. newdeplibs="$newdeplibs $a_deplib" fi done # Gone through all deplibs. ;; none | unknown | *) newdeplibs="" tmp_deplibs=`$echo "X $deplibs" | $Xsed -e 's/ -lc$//' \ -e 's/ -[LR][^ ]*//g'` if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then for i in $predeps $postdeps ; do # can't use Xsed below, because $i might contain '/' tmp_deplibs=`$echo "X $tmp_deplibs" | ${SED} -e "1s,^X,," -e "s,$i,,"` done fi if $echo "X $tmp_deplibs" | $Xsed -e 's/[ ]//g' \ | grep . >/dev/null; then $echo if test "X$deplibs_check_method" = "Xnone"; then $echo "*** Warning: inter-library dependencies are not supported in this platform." else $echo "*** Warning: inter-library dependencies are not known to be supported." fi $echo "*** All declared inter-library dependencies are being dropped." droppeddeps=yes fi ;; esac versuffix=$versuffix_save major=$major_save release=$release_save libname=$libname_save name=$name_save case $host in *-*-rhapsody* | *-*-darwin1.[012]) # On Rhapsody replace the C library is the System framework newdeplibs=`$echo "X $newdeplibs" | $Xsed -e 's/ -lc / -framework System /'` ;; esac if test "$droppeddeps" = yes; then if test "$module" = yes; then $echo $echo "*** Warning: libtool could not satisfy all declared inter-library" $echo "*** dependencies of module $libname. Therefore, libtool will create" $echo "*** a static module, that should work as long as the dlopening" $echo "*** application is linked with the -dlopen flag." if test -z "$global_symbol_pipe"; then $echo $echo "*** However, this would only work if libtool was able to extract symbol" $echo "*** lists from a program, using \`nm' or equivalent, but libtool could" $echo "*** not find such a program. So, this module is probably useless." $echo "*** \`nm' from GNU binutils and a full rebuild may help." fi if test "$build_old_libs" = no; then oldlibs="$output_objdir/$libname.$libext" build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi else $echo "*** The inter-library dependencies that have been dropped here will be" $echo "*** automatically added whenever a program is linked with this library" $echo "*** or is declared to -dlopen it." if test "$allow_undefined" = no; then $echo $echo "*** Since this library must not contain undefined symbols," $echo "*** because either the platform does not support them or" $echo "*** it was explicitly requested with -no-undefined," $echo "*** libtool will only create a static version of it." if test "$build_old_libs" = no; then oldlibs="$output_objdir/$libname.$libext" build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi fi fi fi # Done checking deplibs! deplibs=$newdeplibs fi # All the library-specific variables (install_libdir is set above). library_names= old_library= dlname= # Test again, we may have decided not to build it any more if test "$build_libtool_libs" = yes; then if test "$hardcode_into_libs" = yes; then # Hardcode the library paths hardcode_libdirs= dep_rpath= rpath="$finalize_rpath" test "$mode" != relink && rpath="$compile_rpath$rpath" for libdir in $rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs="$libdir" else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" dep_rpath="$dep_rpath $flag" fi elif test -n "$runpath_var"; then case "$perm_rpath " in *" $libdir "*) ;; *) perm_rpath="$perm_rpath $libdir" ;; esac fi done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir="$hardcode_libdirs" if test -n "$hardcode_libdir_flag_spec_ld"; then eval dep_rpath=\"$hardcode_libdir_flag_spec_ld\" else eval dep_rpath=\"$hardcode_libdir_flag_spec\" fi fi if test -n "$runpath_var" && test -n "$perm_rpath"; then # We should set the runpath_var. rpath= for dir in $perm_rpath; do rpath="$rpath$dir:" done eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" fi test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" fi shlibpath="$finalize_shlibpath" test "$mode" != relink && shlibpath="$compile_shlibpath$shlibpath" if test -n "$shlibpath"; then eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" fi # Get the real and link names of the library. eval shared_ext=\"$shrext\" eval library_names=\"$library_names_spec\" set dummy $library_names realname="$2" shift; shift if test -n "$soname_spec"; then eval soname=\"$soname_spec\" else soname="$realname" fi if test -z "$dlname"; then dlname=$soname fi lib="$output_objdir/$realname" for link do linknames="$linknames $link" done # Use standard objects if they are pic test -z "$pic_flag" && libobjs=`$echo "X$libobjs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` # Prepare the list of exported symbols if test -z "$export_symbols"; then if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then $show "generating symbol list for \`$libname.la'" export_symbols="$output_objdir/$libname.exp" $run $rm $export_symbols eval cmds=\"$export_symbols_cmds\" save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" if len=`expr "X$cmd" : ".*"` && test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then $show "$cmd" $run eval "$cmd" || exit $? skipped_export=false else # The command line is too long to execute in one step. $show "using reloadable object file for export list..." skipped_export=: fi done IFS="$save_ifs" if test -n "$export_symbols_regex"; then $show "$EGREP -e \"$export_symbols_regex\" \"$export_symbols\" > \"${export_symbols}T\"" $run eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' $show "$mv \"${export_symbols}T\" \"$export_symbols\"" $run eval '$mv "${export_symbols}T" "$export_symbols"' fi fi fi if test -n "$export_symbols" && test -n "$include_expsyms"; then $run eval '$echo "X$include_expsyms" | $SP2NL >> "$export_symbols"' fi tmp_deplibs= for test_deplib in $deplibs; do case " $convenience " in *" $test_deplib "*) ;; *) tmp_deplibs="$tmp_deplibs $test_deplib" ;; esac done deplibs="$tmp_deplibs" if test -n "$convenience"; then if test -n "$whole_archive_flag_spec"; then save_libobjs=$libobjs eval libobjs=\"\$libobjs $whole_archive_flag_spec\" else gentop="$output_objdir/${outputname}x" $show "${rm}r $gentop" $run ${rm}r "$gentop" $show "$mkdir $gentop" $run $mkdir "$gentop" status=$? if test "$status" -ne 0 && test ! -d "$gentop"; then exit $status fi generated="$generated $gentop" for xlib in $convenience; do # Extract the objects. case $xlib in [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;; *) xabs=`pwd`"/$xlib" ;; esac xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'` xdir="$gentop/$xlib" $show "${rm}r $xdir" $run ${rm}r "$xdir" $show "$mkdir $xdir" $run $mkdir "$xdir" status=$? if test "$status" -ne 0 && test ! -d "$xdir"; then exit $status fi # We will extract separately just the conflicting names and we will no # longer touch any unique names. It is faster to leave these extract # automatically by $AR in one run. $show "(cd $xdir && $AR x $xabs)" $run eval "(cd \$xdir && $AR x \$xabs)" || exit $? if ($AR t "$xabs" | sort | sort -uc >/dev/null 2>&1); then : else $echo "$modename: warning: object name conflicts; renaming object files" 1>&2 $echo "$modename: warning: to ensure that they will not overwrite" 1>&2 $AR t "$xabs" | sort | uniq -cd | while read -r count name do i=1 while test "$i" -le "$count" do # Put our $i before any first dot (extension) # Never overwrite any file name_to="$name" while test "X$name_to" = "X$name" || test -f "$xdir/$name_to" do name_to=`$echo "X$name_to" | $Xsed -e "s/\([^.]*\)/\1-$i/"` done $show "(cd $xdir && $AR xN $i $xabs '$name' && $mv '$name' '$name_to')" $run eval "(cd \$xdir && $AR xN $i \$xabs '$name' && $mv '$name' '$name_to')" || exit $? i=`expr $i + 1` done done fi libobjs="$libobjs "`find $xdir -name \*.$objext -print -o -name \*.lo -print | $NL2SP` done fi fi if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then eval flag=\"$thread_safe_flag_spec\" linker_flags="$linker_flags $flag" fi # Make a backup of the uninstalled library when relinking if test "$mode" = relink; then $run eval '(cd $output_objdir && $rm ${realname}U && $mv $realname ${realname}U)' || exit $? fi # Do each of the archive commands. if test "$module" = yes && test -n "$module_cmds" ; then if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then eval cmds=\"$module_expsym_cmds\" else eval cmds=\"$module_cmds\" fi else if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then eval cmds=\"$archive_expsym_cmds\" else eval cmds=\"$archive_cmds\" fi fi if test "X$skipped_export" != "X:" && len=`expr "X$cmds" : ".*"` && test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then : else # The command line is too long to link in one step, link piecewise. $echo "creating reloadable object files..." # Save the value of $output and $libobjs because we want to # use them later. If we have whole_archive_flag_spec, we # want to use save_libobjs as it was before # whole_archive_flag_spec was expanded, because we can't # assume the linker understands whole_archive_flag_spec. # This may have to be revisited, in case too many # convenience libraries get linked in and end up exceeding # the spec. if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then save_libobjs=$libobjs fi save_output=$output # Clear the reloadable object creation command queue and # initialize k to one. test_cmds= concat_cmds= objlist= delfiles= last_robj= k=1 output=$output_objdir/$save_output-${k}.$objext # Loop over the list of objects to be linked. for obj in $save_libobjs do eval test_cmds=\"$reload_cmds $objlist $last_robj\" if test "X$objlist" = X || { len=`expr "X$test_cmds" : ".*"` && test "$len" -le "$max_cmd_len"; }; then objlist="$objlist $obj" else # The command $test_cmds is almost too long, add a # command to the queue. if test "$k" -eq 1 ; then # The first file doesn't have a previous command to add. eval concat_cmds=\"$reload_cmds $objlist $last_robj\" else # All subsequent reloadable object files will link in # the last one created. eval concat_cmds=\"\$concat_cmds~$reload_cmds $objlist $last_robj\" fi last_robj=$output_objdir/$save_output-${k}.$objext k=`expr $k + 1` output=$output_objdir/$save_output-${k}.$objext objlist=$obj len=1 fi done # Handle the remaining objects by creating one last # reloadable object file. All subsequent reloadable object # files will link in the last one created. test -z "$concat_cmds" || concat_cmds=$concat_cmds~ eval concat_cmds=\"\${concat_cmds}$reload_cmds $objlist $last_robj\" if ${skipped_export-false}; then $show "generating symbol list for \`$libname.la'" export_symbols="$output_objdir/$libname.exp" $run $rm $export_symbols libobjs=$output # Append the command to create the export file. eval concat_cmds=\"\$concat_cmds~$export_symbols_cmds\" fi # Set up a command to remove the reloadale object files # after they are used. i=0 while test "$i" -lt "$k" do i=`expr $i + 1` delfiles="$delfiles $output_objdir/$save_output-${i}.$objext" done $echo "creating a temporary reloadable object file: $output" # Loop through the commands generated above and execute them. save_ifs="$IFS"; IFS='~' for cmd in $concat_cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" || exit $? done IFS="$save_ifs" libobjs=$output # Restore the value of output. output=$save_output if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then eval libobjs=\"\$libobjs $whole_archive_flag_spec\" fi # Expand the library linking commands again to reset the # value of $libobjs for piecewise linking. # Do each of the archive commands. if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then eval cmds=\"$archive_expsym_cmds\" else eval cmds=\"$archive_cmds\" fi # Append the command to remove the reloadable object files # to the just-reset $cmds. eval cmds=\"\$cmds~$rm $delfiles\" fi save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" || exit $? done IFS="$save_ifs" # Restore the uninstalled library and exit if test "$mode" = relink; then $run eval '(cd $output_objdir && $rm ${realname}T && $mv $realname ${realname}T && $mv "$realname"U $realname)' || exit $? exit 0 fi # Create links to the real library. for linkname in $linknames; do if test "$realname" != "$linkname"; then $show "(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)" $run eval '(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)' || exit $? fi done # If -module or -export-dynamic was specified, set the dlname. if test "$module" = yes || test "$export_dynamic" = yes; then # On all known operating systems, these are identical. dlname="$soname" fi fi ;; obj) if test -n "$deplibs"; then $echo "$modename: warning: \`-l' and \`-L' are ignored for objects" 1>&2 fi if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then $echo "$modename: warning: \`-dlopen' is ignored for objects" 1>&2 fi if test -n "$rpath"; then $echo "$modename: warning: \`-rpath' is ignored for objects" 1>&2 fi if test -n "$xrpath"; then $echo "$modename: warning: \`-R' is ignored for objects" 1>&2 fi if test -n "$vinfo"; then $echo "$modename: warning: \`-version-info' is ignored for objects" 1>&2 fi if test -n "$release"; then $echo "$modename: warning: \`-release' is ignored for objects" 1>&2 fi case $output in *.lo) if test -n "$objs$old_deplibs"; then $echo "$modename: cannot build library object \`$output' from non-libtool objects" 1>&2 exit 1 fi libobj="$output" obj=`$echo "X$output" | $Xsed -e "$lo2o"` ;; *) libobj= obj="$output" ;; esac # Delete the old objects. $run $rm $obj $libobj # Objects from convenience libraries. This assumes # single-version convenience libraries. Whenever we create # different ones for PIC/non-PIC, this we'll have to duplicate # the extraction. reload_conv_objs= gentop= # reload_cmds runs $LD directly, so let us get rid of # -Wl from whole_archive_flag_spec wl= if test -n "$convenience"; then if test -n "$whole_archive_flag_spec"; then eval reload_conv_objs=\"\$reload_objs $whole_archive_flag_spec\" else gentop="$output_objdir/${obj}x" $show "${rm}r $gentop" $run ${rm}r "$gentop" $show "$mkdir $gentop" $run $mkdir "$gentop" status=$? if test "$status" -ne 0 && test ! -d "$gentop"; then exit $status fi generated="$generated $gentop" for xlib in $convenience; do # Extract the objects. case $xlib in [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;; *) xabs=`pwd`"/$xlib" ;; esac xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'` xdir="$gentop/$xlib" $show "${rm}r $xdir" $run ${rm}r "$xdir" $show "$mkdir $xdir" $run $mkdir "$xdir" status=$? if test "$status" -ne 0 && test ! -d "$xdir"; then exit $status fi # We will extract separately just the conflicting names and we will no # longer touch any unique names. It is faster to leave these extract # automatically by $AR in one run. $show "(cd $xdir && $AR x $xabs)" $run eval "(cd \$xdir && $AR x \$xabs)" || exit $? if ($AR t "$xabs" | sort | sort -uc >/dev/null 2>&1); then : else $echo "$modename: warning: object name conflicts; renaming object files" 1>&2 $echo "$modename: warning: to ensure that they will not overwrite" 1>&2 $AR t "$xabs" | sort | uniq -cd | while read -r count name do i=1 while test "$i" -le "$count" do # Put our $i before any first dot (extension) # Never overwrite any file name_to="$name" while test "X$name_to" = "X$name" || test -f "$xdir/$name_to" do name_to=`$echo "X$name_to" | $Xsed -e "s/\([^.]*\)/\1-$i/"` done $show "(cd $xdir && $AR xN $i $xabs '$name' && $mv '$name' '$name_to')" $run eval "(cd \$xdir && $AR xN $i \$xabs '$name' && $mv '$name' '$name_to')" || exit $? i=`expr $i + 1` done done fi reload_conv_objs="$reload_objs "`find $xdir -name \*.$objext -print -o -name \*.lo -print | $NL2SP` done fi fi # Create the old-style object. reload_objs="$objs$old_deplibs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}$'/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test output="$obj" eval cmds=\"$reload_cmds\" save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" || exit $? done IFS="$save_ifs" # Exit if we aren't doing a library object file. if test -z "$libobj"; then if test -n "$gentop"; then $show "${rm}r $gentop" $run ${rm}r $gentop fi exit 0 fi if test "$build_libtool_libs" != yes; then if test -n "$gentop"; then $show "${rm}r $gentop" $run ${rm}r $gentop fi # Create an invalid libtool object if no PIC, so that we don't # accidentally link it into a program. # $show "echo timestamp > $libobj" # $run eval "echo timestamp > $libobj" || exit $? exit 0 fi if test -n "$pic_flag" || test "$pic_mode" != default; then # Only do commands if we really have different PIC objects. reload_objs="$libobjs $reload_conv_objs" output="$libobj" eval cmds=\"$reload_cmds\" save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" || exit $? done IFS="$save_ifs" fi if test -n "$gentop"; then $show "${rm}r $gentop" $run ${rm}r $gentop fi exit 0 ;; prog) case $host in *cygwin*) output=`$echo $output | ${SED} -e 's,.exe$,,;s,$,.exe,'` ;; esac if test -n "$vinfo"; then $echo "$modename: warning: \`-version-info' is ignored for programs" 1>&2 fi if test -n "$release"; then $echo "$modename: warning: \`-release' is ignored for programs" 1>&2 fi if test "$preload" = yes; then if test "$dlopen_support" = unknown && test "$dlopen_self" = unknown && test "$dlopen_self_static" = unknown; then $echo "$modename: warning: \`AC_LIBTOOL_DLOPEN' not used. Assuming no dlopen support." fi fi case $host in *-*-rhapsody* | *-*-darwin1.[012]) # On Rhapsody replace the C library is the System framework compile_deplibs=`$echo "X $compile_deplibs" | $Xsed -e 's/ -lc / -framework System /'` finalize_deplibs=`$echo "X $finalize_deplibs" | $Xsed -e 's/ -lc / -framework System /'` ;; esac case $host in *darwin*) # Don't allow lazy linking, it breaks C++ global constructors if test "$tagname" = CXX ; then compile_command="$compile_command ${wl}-bind_at_load" finalize_command="$finalize_command ${wl}-bind_at_load" fi ;; esac compile_command="$compile_command $compile_deplibs" finalize_command="$finalize_command $finalize_deplibs" if test -n "$rpath$xrpath"; then # If the user specified any rpath flags, then add them. for libdir in $rpath $xrpath; do # This is the magic to use -rpath. case "$finalize_rpath " in *" $libdir "*) ;; *) finalize_rpath="$finalize_rpath $libdir" ;; esac done fi # Now hardcode the library paths rpath= hardcode_libdirs= for libdir in $compile_rpath $finalize_rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs="$libdir" else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" rpath="$rpath $flag" fi elif test -n "$runpath_var"; then case "$perm_rpath " in *" $libdir "*) ;; *) perm_rpath="$perm_rpath $libdir" ;; esac fi case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) case :$dllsearchpath: in *":$libdir:"*) ;; *) dllsearchpath="$dllsearchpath:$libdir";; esac ;; esac done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir="$hardcode_libdirs" eval rpath=\" $hardcode_libdir_flag_spec\" fi compile_rpath="$rpath" rpath= hardcode_libdirs= for libdir in $finalize_rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs="$libdir" else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" rpath="$rpath $flag" fi elif test -n "$runpath_var"; then case "$finalize_perm_rpath " in *" $libdir "*) ;; *) finalize_perm_rpath="$finalize_perm_rpath $libdir" ;; esac fi done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir="$hardcode_libdirs" eval rpath=\" $hardcode_libdir_flag_spec\" fi finalize_rpath="$rpath" if test -n "$libobjs" && test "$build_old_libs" = yes; then # Transform all the library objects into standard objects. compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` fi dlsyms= if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then if test -n "$NM" && test -n "$global_symbol_pipe"; then dlsyms="${outputname}S.c" else $echo "$modename: not configured to extract global symbols from dlpreopened files" 1>&2 fi fi if test -n "$dlsyms"; then case $dlsyms in "") ;; *.c) # Discover the nlist of each of the dlfiles. nlist="$output_objdir/${outputname}.nm" $show "$rm $nlist ${nlist}S ${nlist}T" $run $rm "$nlist" "${nlist}S" "${nlist}T" # Parse the name list into a source file. $show "creating $output_objdir/$dlsyms" test -z "$run" && $echo > "$output_objdir/$dlsyms" "\ /* $dlsyms - symbol resolution table for \`$outputname' dlsym emulation. */ /* Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP */ #ifdef __cplusplus extern \"C\" { #endif /* Prevent the only kind of declaration conflicts we can make. */ #define lt_preloaded_symbols some_other_symbol /* External symbol declarations for the compiler. */\ " if test "$dlself" = yes; then $show "generating symbol list for \`$output'" test -z "$run" && $echo ': @PROGRAM@ ' > "$nlist" # Add our own program objects to the symbol list. progfiles=`$echo "X$objs$old_deplibs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` for arg in $progfiles; do $show "extracting global C symbols from \`$arg'" $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'" done if test -n "$exclude_expsyms"; then $run eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' $run eval '$mv "$nlist"T "$nlist"' fi if test -n "$export_symbols_regex"; then $run eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' $run eval '$mv "$nlist"T "$nlist"' fi # Prepare the list of exported symbols if test -z "$export_symbols"; then export_symbols="$output_objdir/$output.exp" $run $rm $export_symbols $run eval "${SED} -n -e '/^: @PROGRAM@$/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' else $run eval "${SED} -e 's/\([][.*^$]\)/\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$output.exp"' $run eval 'grep -f "$output_objdir/$output.exp" < "$nlist" > "$nlist"T' $run eval 'mv "$nlist"T "$nlist"' fi fi for arg in $dlprefiles; do $show "extracting global C symbols from \`$arg'" name=`$echo "$arg" | ${SED} -e 's%^.*/%%'` $run eval '$echo ": $name " >> "$nlist"' $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'" done if test -z "$run"; then # Make sure we have at least an empty file. test -f "$nlist" || : > "$nlist" if test -n "$exclude_expsyms"; then $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T $mv "$nlist"T "$nlist" fi # Try sorting and uniquifying the output. if grep -v "^: " < "$nlist" | if sort -k 3 /dev/null 2>&1; then sort -k 3 else sort +2 fi | uniq > "$nlist"S; then : else grep -v "^: " < "$nlist" > "$nlist"S fi if test -f "$nlist"S; then eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$dlsyms"' else $echo '/* NONE */' >> "$output_objdir/$dlsyms" fi $echo >> "$output_objdir/$dlsyms" "\ #undef lt_preloaded_symbols #if defined (__STDC__) && __STDC__ # define lt_ptr void * #else # define lt_ptr char * # define const #endif /* The mapping between symbol names and symbols. */ const struct { const char *name; lt_ptr address; } lt_preloaded_symbols[] = {\ " eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$dlsyms" $echo >> "$output_objdir/$dlsyms" "\ {0, (lt_ptr) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt_preloaded_symbols; } #endif #ifdef __cplusplus } #endif\ " fi pic_flag_for_symtable= case $host in # compiling the symbol table file with pic_flag works around # a FreeBSD bug that causes programs to crash when -lm is # linked before any other PIC object. But we must not use # pic_flag when linking with -static. The problem exists in # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. *-*-freebsd2*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) case "$compile_command " in *" -static "*) ;; *) pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND";; esac;; *-*-hpux*) case "$compile_command " in *" -static "*) ;; *) pic_flag_for_symtable=" $pic_flag";; esac esac # Now compile the dynamic symbol file. $show "(cd $output_objdir && $LTCC -c$no_builtin_flag$pic_flag_for_symtable \"$dlsyms\")" $run eval '(cd $output_objdir && $LTCC -c$no_builtin_flag$pic_flag_for_symtable "$dlsyms")' || exit $? # Clean up the generated files. $show "$rm $output_objdir/$dlsyms $nlist ${nlist}S ${nlist}T" $run $rm "$output_objdir/$dlsyms" "$nlist" "${nlist}S" "${nlist}T" # Transform the symbol file into the correct name. compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` ;; *) $echo "$modename: unknown suffix for \`$dlsyms'" 1>&2 exit 1 ;; esac else # We keep going just in case the user didn't refer to # lt_preloaded_symbols. The linker will fail if global_symbol_pipe # really was required. # Nullify the symbol file. compile_command=`$echo "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"` finalize_command=`$echo "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"` fi if test "$need_relink" = no || test "$build_libtool_libs" != yes; then # Replace the output file specification. compile_command=`$echo "X$compile_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` link_command="$compile_command$compile_rpath" # We have no uninstalled library dependencies, so finalize right now. $show "$link_command" $run eval "$link_command" status=$? # Delete the generated files. if test -n "$dlsyms"; then $show "$rm $output_objdir/${outputname}S.${objext}" $run $rm "$output_objdir/${outputname}S.${objext}" fi exit $status fi if test -n "$shlibpath_var"; then # We should set the shlibpath_var rpath= for dir in $temp_rpath; do case $dir in [\\/]* | [A-Za-z]:[\\/]*) # Absolute path. rpath="$rpath$dir:" ;; *) # Relative path: add a thisdir entry. rpath="$rpath\$thisdir/$dir:" ;; esac done temp_rpath="$rpath" fi if test -n "$compile_shlibpath$finalize_shlibpath"; then compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" fi if test -n "$finalize_shlibpath"; then finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" fi compile_var= finalize_var= if test -n "$runpath_var"; then if test -n "$perm_rpath"; then # We should set the runpath_var. rpath= for dir in $perm_rpath; do rpath="$rpath$dir:" done compile_var="$runpath_var=\"$rpath\$$runpath_var\" " fi if test -n "$finalize_perm_rpath"; then # We should set the runpath_var. rpath= for dir in $finalize_perm_rpath; do rpath="$rpath$dir:" done finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " fi fi if test "$no_install" = yes; then # We don't need to create a wrapper script. link_command="$compile_var$compile_command$compile_rpath" # Replace the output file specification. link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` # Delete the old output file. $run $rm $output # Link the executable and exit $show "$link_command" $run eval "$link_command" || exit $? exit 0 fi if test "$hardcode_action" = relink; then # Fast installation is not supported link_command="$compile_var$compile_command$compile_rpath" relink_command="$finalize_var$finalize_command$finalize_rpath" $echo "$modename: warning: this platform does not like uninstalled shared libraries" 1>&2 $echo "$modename: \`$output' will be relinked during installation" 1>&2 else if test "$fast_install" != no; then link_command="$finalize_var$compile_command$finalize_rpath" if test "$fast_install" = yes; then relink_command=`$echo "X$compile_var$compile_command$compile_rpath" | $Xsed -e 's%@OUTPUT@%\$progdir/\$file%g'` else # fast_install is set to needless relink_command= fi else link_command="$compile_var$compile_command$compile_rpath" relink_command="$finalize_var$finalize_command$finalize_rpath" fi fi # Replace the output file specification. link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` # Delete the old output files. $run $rm $output $output_objdir/$outputname $output_objdir/lt-$outputname $show "$link_command" $run eval "$link_command" || exit $? # Now create the wrapper script. $show "creating $output" # Quote the relink command for shipping. if test -n "$relink_command"; then # Preserve any variables that may affect compiler behavior for var in $variables_saved_for_relink; do if eval test -z \"\${$var+set}\"; then relink_command="{ test -z \"\${$var+set}\" || unset $var || { $var=; export $var; }; }; $relink_command" elif eval var_value=\$$var; test -z "$var_value"; then relink_command="$var=; export $var; $relink_command" else var_value=`$echo "X$var_value" | $Xsed -e "$sed_quote_subst"` relink_command="$var=\"$var_value\"; export $var; $relink_command" fi done relink_command="(cd `pwd`; $relink_command)" relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"` fi # Quote $echo for shipping. if test "X$echo" = "X$SHELL $0 --fallback-echo"; then case $0 in [\\/]* | [A-Za-z]:[\\/]*) qecho="$SHELL $0 --fallback-echo";; *) qecho="$SHELL `pwd`/$0 --fallback-echo";; esac qecho=`$echo "X$qecho" | $Xsed -e "$sed_quote_subst"` else qecho=`$echo "X$echo" | $Xsed -e "$sed_quote_subst"` fi # Only actually do things if our run command is non-null. if test -z "$run"; then # win32 will think the script is a binary if it has # a .exe suffix, so we strip it off here. case $output in *.exe) output=`$echo $output|${SED} 's,.exe$,,'` ;; esac # test for cygwin because mv fails w/o .exe extensions case $host in *cygwin*) exeext=.exe outputname=`$echo $outputname|${SED} 's,.exe$,,'` ;; *) exeext= ;; esac case $host in *cygwin* | *mingw* ) cwrappersource=`$echo ${objdir}/lt-${output}.c` cwrapper=`$echo ${output}.exe` $rm $cwrappersource $cwrapper trap "$rm $cwrappersource $cwrapper; exit 1" 1 2 15 cat > $cwrappersource <> $cwrappersource<<"EOF" #include #include #include #include #include #include #if defined(PATH_MAX) # define LT_PATHMAX PATH_MAX #elif defined(MAXPATHLEN) # define LT_PATHMAX MAXPATHLEN #else # define LT_PATHMAX 1024 #endif #ifndef DIR_SEPARATOR #define DIR_SEPARATOR '/' #endif #if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \ defined (__OS2__) #define HAVE_DOS_BASED_FILE_SYSTEM #ifndef DIR_SEPARATOR_2 #define DIR_SEPARATOR_2 '\\' #endif #endif #ifndef DIR_SEPARATOR_2 # define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) #else /* DIR_SEPARATOR_2 */ # define IS_DIR_SEPARATOR(ch) \ (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) #endif /* DIR_SEPARATOR_2 */ #define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) #define XFREE(stale) do { \ if (stale) { free ((void *) stale); stale = 0; } \ } while (0) const char *program_name = NULL; void * xmalloc (size_t num); char * xstrdup (const char *string); char * basename (const char *name); char * fnqualify(const char *path); char * strendzap(char *str, const char *pat); void lt_fatal (const char *message, ...); int main (int argc, char *argv[]) { char **newargz; int i; program_name = (char *) xstrdup ((char *) basename (argv[0])); newargz = XMALLOC(char *, argc+2); EOF cat >> $cwrappersource <> $cwrappersource <<"EOF" newargz[1] = fnqualify(argv[0]); /* we know the script has the same name, without the .exe */ /* so make sure newargz[1] doesn't end in .exe */ strendzap(newargz[1],".exe"); for (i = 1; i < argc; i++) newargz[i+1] = xstrdup(argv[i]); newargz[argc+1] = NULL; EOF cat >> $cwrappersource <> $cwrappersource <<"EOF" } void * xmalloc (size_t num) { void * p = (void *) malloc (num); if (!p) lt_fatal ("Memory exhausted"); return p; } char * xstrdup (const char *string) { return string ? strcpy ((char *) xmalloc (strlen (string) + 1), string) : NULL ; } char * basename (const char *name) { const char *base; #if defined (HAVE_DOS_BASED_FILE_SYSTEM) /* Skip over the disk name in MSDOS pathnames. */ if (isalpha (name[0]) && name[1] == ':') name += 2; #endif for (base = name; *name; name++) if (IS_DIR_SEPARATOR (*name)) base = name + 1; return (char *) base; } char * fnqualify(const char *path) { size_t size; char *p; char tmp[LT_PATHMAX + 1]; assert(path != NULL); /* Is it qualified already? */ #if defined (HAVE_DOS_BASED_FILE_SYSTEM) if (isalpha (path[0]) && path[1] == ':') return xstrdup (path); #endif if (IS_DIR_SEPARATOR (path[0])) return xstrdup (path); /* prepend the current directory */ /* doesn't handle '~' */ if (getcwd (tmp, LT_PATHMAX) == NULL) lt_fatal ("getcwd failed"); size = strlen(tmp) + 1 + strlen(path) + 1; /* +2 for '/' and '\0' */ p = XMALLOC(char, size); sprintf(p, "%s%c%s", tmp, DIR_SEPARATOR, path); return p; } char * strendzap(char *str, const char *pat) { size_t len, patlen; assert(str != NULL); assert(pat != NULL); len = strlen(str); patlen = strlen(pat); if (patlen <= len) { str += len - patlen; if (strcmp(str, pat) == 0) *str = '\0'; } return str; } static void lt_error_core (int exit_status, const char * mode, const char * message, va_list ap) { fprintf (stderr, "%s: %s: ", program_name, mode); vfprintf (stderr, message, ap); fprintf (stderr, ".\n"); if (exit_status >= 0) exit (exit_status); } void lt_fatal (const char *message, ...) { va_list ap; va_start (ap, message); lt_error_core (EXIT_FAILURE, "FATAL", message, ap); va_end (ap); } EOF # we should really use a build-platform specific compiler # here, but OTOH, the wrappers (shell script and this C one) # are only useful if you want to execute the "real" binary. # Since the "real" binary is built for $host, then this # wrapper might as well be built for $host, too. $run $LTCC -s -o $cwrapper $cwrappersource ;; esac $rm $output trap "$rm $output; exit 1" 1 2 15 $echo > $output "\ #! $SHELL # $output - temporary wrapper script for $objdir/$outputname # Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP # # The $output program cannot be directly executed until all the libtool # libraries that it depends on are installed. # # This wrapper script should never be moved out of the build directory. # If it is, it will not operate correctly. # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. Xsed='${SED} -e 1s/^X//' sed_quote_subst='$sed_quote_subst' # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. if test \"\${CDPATH+set}\" = set; then CDPATH=:; export CDPATH; fi relink_command=\"$relink_command\" # This environment variable determines our operation mode. if test \"\$libtool_install_magic\" = \"$magic\"; then # install mode needs the following variable: notinst_deplibs='$notinst_deplibs' else # When we are sourced in execute mode, \$file and \$echo are already set. if test \"\$libtool_execute_magic\" != \"$magic\"; then echo=\"$qecho\" file=\"\$0\" # Make sure echo works. if test \"X\$1\" = X--no-reexec; then # Discard the --no-reexec flag, and continue. shift elif test \"X\`(\$echo '\t') 2>/dev/null\`\" = 'X\t'; then # Yippee, \$echo works! : else # Restart under the correct shell, and then maybe \$echo will work. exec $SHELL \"\$0\" --no-reexec \${1+\"\$@\"} fi fi\ " $echo >> $output "\ # Find the directory that this script lives in. thisdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*$%%'\` test \"x\$thisdir\" = \"x\$file\" && thisdir=. # Follow symbolic links until we get to the real thisdir. file=\`ls -ld \"\$file\" | ${SED} -n 's/.*-> //p'\` while test -n \"\$file\"; do destdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*\$%%'\` # If there was a directory component, then change thisdir. if test \"x\$destdir\" != \"x\$file\"; then case \"\$destdir\" in [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; *) thisdir=\"\$thisdir/\$destdir\" ;; esac fi file=\`\$echo \"X\$file\" | \$Xsed -e 's%^.*/%%'\` file=\`ls -ld \"\$thisdir/\$file\" | ${SED} -n 's/.*-> //p'\` done # Try to get the absolute directory name. absdir=\`cd \"\$thisdir\" && pwd\` test -n \"\$absdir\" && thisdir=\"\$absdir\" " if test "$fast_install" = yes; then $echo >> $output "\ program=lt-'$outputname'$exeext progdir=\"\$thisdir/$objdir\" if test ! -f \"\$progdir/\$program\" || \\ { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\ test \"X\$file\" != \"X\$progdir/\$program\"; }; then file=\"\$\$-\$program\" if test ! -d \"\$progdir\"; then $mkdir \"\$progdir\" else $rm \"\$progdir/\$file\" fi" $echo >> $output "\ # relink executable if necessary if test -n \"\$relink_command\"; then if relink_command_output=\`eval \$relink_command 2>&1\`; then : else $echo \"\$relink_command_output\" >&2 $rm \"\$progdir/\$file\" exit 1 fi fi $mv \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || { $rm \"\$progdir/\$program\"; $mv \"\$progdir/\$file\" \"\$progdir/\$program\"; } $rm \"\$progdir/\$file\" fi" else $echo >> $output "\ program='$outputname' progdir=\"\$thisdir/$objdir\" " fi $echo >> $output "\ if test -f \"\$progdir/\$program\"; then" # Export our shlibpath_var if we have one. if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then $echo >> $output "\ # Add our own library path to $shlibpath_var $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" # Some systems cannot cope with colon-terminated $shlibpath_var # The second colon is a workaround for a bug in BeOS R4 sed $shlibpath_var=\`\$echo \"X\$$shlibpath_var\" | \$Xsed -e 's/::*\$//'\` export $shlibpath_var " fi # fixup the dll searchpath if we need to. if test -n "$dllsearchpath"; then $echo >> $output "\ # Add the dll search path components to the executable PATH PATH=$dllsearchpath:\$PATH " fi $echo >> $output "\ if test \"\$libtool_execute_magic\" != \"$magic\"; then # Run the actual program with our arguments. " case $host in # Backslashes separate directories on plain windows *-*-mingw | *-*-os2*) $echo >> $output "\ exec \$progdir\\\\\$program \${1+\"\$@\"} " ;; *) $echo >> $output "\ exec \$progdir/\$program \${1+\"\$@\"} " ;; esac $echo >> $output "\ \$echo \"\$0: cannot exec \$program \${1+\"\$@\"}\" exit 1 fi else # The program doesn't exist. \$echo \"\$0: error: \$progdir/\$program does not exist\" 1>&2 \$echo \"This script is just a wrapper for \$program.\" 1>&2 $echo \"See the $PACKAGE documentation for more information.\" 1>&2 exit 1 fi fi\ " chmod +x $output fi exit 0 ;; esac # See if we need to build an old-fashioned archive. for oldlib in $oldlibs; do if test "$build_libtool_libs" = convenience; then oldobjs="$libobjs_save" addlibs="$convenience" build_libtool_libs=no else if test "$build_libtool_libs" = module; then oldobjs="$libobjs_save" build_libtool_libs=no else oldobjs="$old_deplibs $non_pic_objects" fi addlibs="$old_convenience" fi if test -n "$addlibs"; then gentop="$output_objdir/${outputname}x" $show "${rm}r $gentop" $run ${rm}r "$gentop" $show "$mkdir $gentop" $run $mkdir "$gentop" status=$? if test "$status" -ne 0 && test ! -d "$gentop"; then exit $status fi generated="$generated $gentop" # Add in members from convenience archives. for xlib in $addlibs; do # Extract the objects. case $xlib in [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;; *) xabs=`pwd`"/$xlib" ;; esac xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'` xdir="$gentop/$xlib" $show "${rm}r $xdir" $run ${rm}r "$xdir" $show "$mkdir $xdir" $run $mkdir "$xdir" status=$? if test "$status" -ne 0 && test ! -d "$xdir"; then exit $status fi # We will extract separately just the conflicting names and we will no # longer touch any unique names. It is faster to leave these extract # automatically by $AR in one run. $show "(cd $xdir && $AR x $xabs)" $run eval "(cd \$xdir && $AR x \$xabs)" || exit $? if ($AR t "$xabs" | sort | sort -uc >/dev/null 2>&1); then : else $echo "$modename: warning: object name conflicts; renaming object files" 1>&2 $echo "$modename: warning: to ensure that they will not overwrite" 1>&2 $AR t "$xabs" | sort | uniq -cd | while read -r count name do i=1 while test "$i" -le "$count" do # Put our $i before any first dot (extension) # Never overwrite any file name_to="$name" while test "X$name_to" = "X$name" || test -f "$xdir/$name_to" do name_to=`$echo "X$name_to" | $Xsed -e "s/\([^.]*\)/\1-$i/"` done $show "(cd $xdir && $AR xN $i $xabs '$name' && $mv '$name' '$name_to')" $run eval "(cd \$xdir && $AR xN $i \$xabs '$name' && $mv '$name' '$name_to')" || exit $? i=`expr $i + 1` done done fi oldobjs="$oldobjs "`find $xdir -name \*.${objext} -print -o -name \*.lo -print | $NL2SP` done fi # Do each command in the archive commands. if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then eval cmds=\"$old_archive_from_new_cmds\" else eval cmds=\"$old_archive_cmds\" if len=`expr "X$cmds" : ".*"` && test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then : else # the command line is too long to link in one step, link in parts $echo "using piecewise archive linking..." save_RANLIB=$RANLIB RANLIB=: objlist= concat_cmds= save_oldobjs=$oldobjs # GNU ar 2.10+ was changed to match POSIX; thus no paths are # encoded into archives. This makes 'ar r' malfunction in # this piecewise linking case whenever conflicting object # names appear in distinct ar calls; check, warn and compensate. if (for obj in $save_oldobjs do $echo "X$obj" | $Xsed -e 's%^.*/%%' done | sort | sort -uc >/dev/null 2>&1); then : else $echo "$modename: warning: object name conflicts; overriding AR_FLAGS to 'cq'" 1>&2 $echo "$modename: warning: to ensure that POSIX-compatible ar will work" 1>&2 AR_FLAGS=cq fi # Is there a better way of finding the last object in the list? for obj in $save_oldobjs do last_oldobj=$obj done for obj in $save_oldobjs do oldobjs="$objlist $obj" objlist="$objlist $obj" eval test_cmds=\"$old_archive_cmds\" if len=`expr "X$test_cmds" : ".*"` && test "$len" -le "$max_cmd_len"; then : else # the above command should be used before it gets too long oldobjs=$objlist if test "$obj" = "$last_oldobj" ; then RANLIB=$save_RANLIB fi test -z "$concat_cmds" || concat_cmds=$concat_cmds~ eval concat_cmds=\"\${concat_cmds}$old_archive_cmds\" objlist= fi done RANLIB=$save_RANLIB oldobjs=$objlist if test "X$oldobjs" = "X" ; then eval cmds=\"\$concat_cmds\" else eval cmds=\"\$concat_cmds~$old_archive_cmds\" fi fi fi save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" || exit $? done IFS="$save_ifs" done if test -n "$generated"; then $show "${rm}r$generated" $run ${rm}r$generated fi # Now create the libtool archive. case $output in *.la) old_library= test "$build_old_libs" = yes && old_library="$libname.$libext" $show "creating $output" # Preserve any variables that may affect compiler behavior for var in $variables_saved_for_relink; do if eval test -z \"\${$var+set}\"; then relink_command="{ test -z \"\${$var+set}\" || unset $var || { $var=; export $var; }; }; $relink_command" elif eval var_value=\$$var; test -z "$var_value"; then relink_command="$var=; export $var; $relink_command" else var_value=`$echo "X$var_value" | $Xsed -e "$sed_quote_subst"` relink_command="$var=\"$var_value\"; export $var; $relink_command" fi done # Quote the link command for shipping. relink_command="(cd `pwd`; $SHELL $0 --mode=relink $libtool_args @inst_prefix_dir@)" relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"` if test "$hardcode_automatic" = yes ; then relink_command= fi # Only create the output if not a dry run. if test -z "$run"; then for installed in no yes; do if test "$installed" = yes; then if test -z "$install_libdir"; then break fi output="$output_objdir/$outputname"i # Replace all uninstalled libtool libraries with the installed ones newdependency_libs= for deplib in $dependency_libs; do case $deplib in *.la) name=`$echo "X$deplib" | $Xsed -e 's%^.*/%%'` eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` if test -z "$libdir"; then $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2 exit 1 fi newdependency_libs="$newdependency_libs $libdir/$name" ;; *) newdependency_libs="$newdependency_libs $deplib" ;; esac done dependency_libs="$newdependency_libs" newdlfiles= for lib in $dlfiles; do name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'` eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` if test -z "$libdir"; then $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 exit 1 fi newdlfiles="$newdlfiles $libdir/$name" done dlfiles="$newdlfiles" newdlprefiles= for lib in $dlprefiles; do name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'` eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` if test -z "$libdir"; then $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 exit 1 fi newdlprefiles="$newdlprefiles $libdir/$name" done dlprefiles="$newdlprefiles" else newdlfiles= for lib in $dlfiles; do case $lib in [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; *) abs=`pwd`"/$lib" ;; esac newdlfiles="$newdlfiles $abs" done dlfiles="$newdlfiles" newdlprefiles= for lib in $dlprefiles; do case $lib in [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; *) abs=`pwd`"/$lib" ;; esac newdlprefiles="$newdlprefiles $abs" done dlprefiles="$newdlprefiles" fi $rm $output # place dlname in correct position for cygwin tdlname=$dlname case $host,$output,$installed,$module,$dlname in *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll) tdlname=../bin/$dlname ;; esac $echo > $output "\ # $outputname - a libtool library file # Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP # # Please DO NOT delete this file! # It is necessary for linking the library. # The name that we can dlopen(3). dlname='$tdlname' # Names of this library. library_names='$library_names' # The name of the static archive. old_library='$old_library' # Libraries that this one depends upon. dependency_libs='$dependency_libs' # Version information for $libname. current=$current age=$age revision=$revision # Is this an already installed library? installed=$installed # Should we warn about portability when linking against -modules? shouldnotlink=$module # Files to dlopen/dlpreopen dlopen='$dlfiles' dlpreopen='$dlprefiles' # Directory that this library needs to be installed in: libdir='$install_libdir'" if test "$installed" = no && test "$need_relink" = yes; then $echo >> $output "\ relink_command=\"$relink_command\"" fi done fi # Do a symbolic link so that the libtool archive can be found in # LD_LIBRARY_PATH before the program is installed. $show "(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)" $run eval '(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)' || exit $? ;; esac exit 0 ;; # libtool install mode install) modename="$modename: install" # There may be an optional sh(1) argument at the beginning of # install_prog (especially on Windows NT). if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh || # Allow the use of GNU shtool's install command. $echo "X$nonopt" | $Xsed | grep shtool > /dev/null; then # Aesthetically quote it. arg=`$echo "X$nonopt" | $Xsed -e "$sed_quote_subst"` case $arg in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) arg="\"$arg\"" ;; esac install_prog="$arg " arg="$1" shift else install_prog= arg="$nonopt" fi # The real first argument should be the name of the installation program. # Aesthetically quote it. arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` case $arg in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) arg="\"$arg\"" ;; esac install_prog="$install_prog$arg" # We need to accept at least all the BSD install flags. dest= files= opts= prev= install_type= isdir=no stripme= for arg do if test -n "$dest"; then files="$files $dest" dest="$arg" continue fi case $arg in -d) isdir=yes ;; -f) prev="-f" ;; -g) prev="-g" ;; -m) prev="-m" ;; -o) prev="-o" ;; -s) stripme=" -s" continue ;; -*) ;; *) # If the previous option needed an argument, then skip it. if test -n "$prev"; then prev= else dest="$arg" continue fi ;; esac # Aesthetically quote the argument. arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` case $arg in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) arg="\"$arg\"" ;; esac install_prog="$install_prog $arg" done if test -z "$install_prog"; then $echo "$modename: you must specify an install program" 1>&2 $echo "$help" 1>&2 exit 1 fi if test -n "$prev"; then $echo "$modename: the \`$prev' option requires an argument" 1>&2 $echo "$help" 1>&2 exit 1 fi if test -z "$files"; then if test -z "$dest"; then $echo "$modename: no file or destination specified" 1>&2 else $echo "$modename: you must specify a destination" 1>&2 fi $echo "$help" 1>&2 exit 1 fi # Strip any trailing slash from the destination. dest=`$echo "X$dest" | $Xsed -e 's%/$%%'` # Check to see that the destination is a directory. test -d "$dest" && isdir=yes if test "$isdir" = yes; then destdir="$dest" destname= else destdir=`$echo "X$dest" | $Xsed -e 's%/[^/]*$%%'` test "X$destdir" = "X$dest" && destdir=. destname=`$echo "X$dest" | $Xsed -e 's%^.*/%%'` # Not a directory, so check to see that there is only one file specified. set dummy $files if test "$#" -gt 2; then $echo "$modename: \`$dest' is not a directory" 1>&2 $echo "$help" 1>&2 exit 1 fi fi case $destdir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) for file in $files; do case $file in *.lo) ;; *) $echo "$modename: \`$destdir' must be an absolute directory name" 1>&2 $echo "$help" 1>&2 exit 1 ;; esac done ;; esac # This variable tells wrapper scripts just to set variables rather # than running their programs. libtool_install_magic="$magic" staticlibs= future_libdirs= current_libdirs= for file in $files; do # Do each installation. case $file in *.$libext) # Do the static libraries later. staticlibs="$staticlibs $file" ;; *.la) # Check to see that this really is a libtool archive. if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : else $echo "$modename: \`$file' is not a valid libtool archive" 1>&2 $echo "$help" 1>&2 exit 1 fi library_names= old_library= relink_command= # If there is no directory component, then add one. case $file in */* | *\\*) . $file ;; *) . ./$file ;; esac # Add the libdir to current_libdirs if it is the destination. if test "X$destdir" = "X$libdir"; then case "$current_libdirs " in *" $libdir "*) ;; *) current_libdirs="$current_libdirs $libdir" ;; esac else # Note the libdir as a future libdir. case "$future_libdirs " in *" $libdir "*) ;; *) future_libdirs="$future_libdirs $libdir" ;; esac fi dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`/ test "X$dir" = "X$file/" && dir= dir="$dir$objdir" if test -n "$relink_command"; then # Determine the prefix the user has applied to our future dir. inst_prefix_dir=`$echo "$destdir" | $SED "s%$libdir\$%%"` # Don't allow the user to place us outside of our expected # location b/c this prevents finding dependent libraries that # are installed to the same prefix. # At present, this check doesn't affect windows .dll's that # are installed into $libdir/../bin (currently, that works fine) # but it's something to keep an eye on. if test "$inst_prefix_dir" = "$destdir"; then $echo "$modename: error: cannot install \`$file' to a directory not ending in $libdir" 1>&2 exit 1 fi if test -n "$inst_prefix_dir"; then # Stick the inst_prefix_dir data into the link command. relink_command=`$echo "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` else relink_command=`$echo "$relink_command" | $SED "s%@inst_prefix_dir@%%"` fi $echo "$modename: warning: relinking \`$file'" 1>&2 $show "$relink_command" if $run eval "$relink_command"; then : else $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2 exit 1 fi fi # See the names of the shared library. set dummy $library_names if test -n "$2"; then realname="$2" shift shift srcname="$realname" test -n "$relink_command" && srcname="$realname"T # Install the shared library and build the symlinks. $show "$install_prog $dir/$srcname $destdir/$realname" $run eval "$install_prog $dir/$srcname $destdir/$realname" || exit $? if test -n "$stripme" && test -n "$striplib"; then $show "$striplib $destdir/$realname" $run eval "$striplib $destdir/$realname" || exit $? fi if test "$#" -gt 0; then # Delete the old symlinks, and create new ones. for linkname do if test "$linkname" != "$realname"; then $show "(cd $destdir && $rm $linkname && $LN_S $realname $linkname)" $run eval "(cd $destdir && $rm $linkname && $LN_S $realname $linkname)" fi done fi # Do each command in the postinstall commands. lib="$destdir/$realname" eval cmds=\"$postinstall_cmds\" save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" || exit $? done IFS="$save_ifs" fi # Install the pseudo-library for information purposes. name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` instname="$dir/$name"i $show "$install_prog $instname $destdir/$name" $run eval "$install_prog $instname $destdir/$name" || exit $? # Maybe install the static library, too. test -n "$old_library" && staticlibs="$staticlibs $dir/$old_library" ;; *.lo) # Install (i.e. copy) a libtool object. # Figure out destination file name, if it wasn't already specified. if test -n "$destname"; then destfile="$destdir/$destname" else destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'` destfile="$destdir/$destfile" fi # Deduce the name of the destination old-style object file. case $destfile in *.lo) staticdest=`$echo "X$destfile" | $Xsed -e "$lo2o"` ;; *.$objext) staticdest="$destfile" destfile= ;; *) $echo "$modename: cannot copy a libtool object to \`$destfile'" 1>&2 $echo "$help" 1>&2 exit 1 ;; esac # Install the libtool object if requested. if test -n "$destfile"; then $show "$install_prog $file $destfile" $run eval "$install_prog $file $destfile" || exit $? fi # Install the old object if enabled. if test "$build_old_libs" = yes; then # Deduce the name of the old-style object file. staticobj=`$echo "X$file" | $Xsed -e "$lo2o"` $show "$install_prog $staticobj $staticdest" $run eval "$install_prog \$staticobj \$staticdest" || exit $? fi exit 0 ;; *) # Figure out destination file name, if it wasn't already specified. if test -n "$destname"; then destfile="$destdir/$destname" else destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'` destfile="$destdir/$destfile" fi # If the file is missing, and there is a .exe on the end, strip it # because it is most likely a libtool script we actually want to # install stripped_ext="" case $file in *.exe) if test ! -f "$file"; then file=`$echo $file|${SED} 's,.exe$,,'` stripped_ext=".exe" fi ;; esac # Do a test to see if this is really a libtool program. case $host in *cygwin*|*mingw*) wrapper=`$echo $file | ${SED} -e 's,.exe$,,'` ;; *) wrapper=$file ;; esac if (${SED} -e '4q' $wrapper | grep "^# Generated by .*$PACKAGE")>/dev/null 2>&1; then notinst_deplibs= relink_command= # To insure that "foo" is sourced, and not "foo.exe", # finese the cygwin/MSYS system by explicitly sourcing "foo." # which disallows the automatic-append-.exe behavior. case $build in *cygwin* | *mingw*) wrapperdot=${wrapper}. ;; *) wrapperdot=${wrapper} ;; esac # If there is no directory component, then add one. case $file in */* | *\\*) . ${wrapperdot} ;; *) . ./${wrapperdot} ;; esac # Check the variables that should have been set. if test -z "$notinst_deplibs"; then $echo "$modename: invalid libtool wrapper script \`$wrapper'" 1>&2 exit 1 fi finalize=yes for lib in $notinst_deplibs; do # Check to see that each library is installed. libdir= if test -f "$lib"; then # If there is no directory component, then add one. case $lib in */* | *\\*) . $lib ;; *) . ./$lib ;; esac fi libfile="$libdir/"`$echo "X$lib" | $Xsed -e 's%^.*/%%g'` ### testsuite: skip nested quoting test if test -n "$libdir" && test ! -f "$libfile"; then $echo "$modename: warning: \`$lib' has not been installed in \`$libdir'" 1>&2 finalize=no fi done relink_command= # To insure that "foo" is sourced, and not "foo.exe", # finese the cygwin/MSYS system by explicitly sourcing "foo." # which disallows the automatic-append-.exe behavior. case $build in *cygwin* | *mingw*) wrapperdot=${wrapper}. ;; *) wrapperdot=${wrapper} ;; esac # If there is no directory component, then add one. case $file in */* | *\\*) . ${wrapperdot} ;; *) . ./${wrapperdot} ;; esac outputname= if test "$fast_install" = no && test -n "$relink_command"; then if test "$finalize" = yes && test -z "$run"; then tmpdir="/tmp" test -n "$TMPDIR" && tmpdir="$TMPDIR" tmpdir="$tmpdir/libtool-$$" if $mkdir -p "$tmpdir" && chmod 700 "$tmpdir"; then : else $echo "$modename: error: cannot create temporary directory \`$tmpdir'" 1>&2 continue fi file=`$echo "X$file$stripped_ext" | $Xsed -e 's%^.*/%%'` outputname="$tmpdir/$file" # Replace the output file specification. relink_command=`$echo "X$relink_command" | $Xsed -e 's%@OUTPUT@%'"$outputname"'%g'` $show "$relink_command" if $run eval "$relink_command"; then : else $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2 ${rm}r "$tmpdir" continue fi file="$outputname" else $echo "$modename: warning: cannot relink \`$file'" 1>&2 fi else # Install the binary that we compiled earlier. file=`$echo "X$file$stripped_ext" | $Xsed -e "s%\([^/]*\)$%$objdir/\1%"` fi fi # remove .exe since cygwin /usr/bin/install will append another # one anyways case $install_prog,$host in */usr/bin/install*,*cygwin*) case $file:$destfile in *.exe:*.exe) # this is ok ;; *.exe:*) destfile=$destfile.exe ;; *:*.exe) destfile=`$echo $destfile | ${SED} -e 's,.exe$,,'` ;; esac ;; esac $show "$install_prog$stripme $file $destfile" $run eval "$install_prog\$stripme \$file \$destfile" || exit $? test -n "$outputname" && ${rm}r "$tmpdir" ;; esac done for file in $staticlibs; do name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` # Set up the ranlib parameters. oldlib="$destdir/$name" $show "$install_prog $file $oldlib" $run eval "$install_prog \$file \$oldlib" || exit $? if test -n "$stripme" && test -n "$striplib"; then $show "$old_striplib $oldlib" $run eval "$old_striplib $oldlib" || exit $? fi # Do each command in the postinstall commands. eval cmds=\"$old_postinstall_cmds\" save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" || exit $? done IFS="$save_ifs" done if test -n "$future_libdirs"; then $echo "$modename: warning: remember to run \`$progname --finish$future_libdirs'" 1>&2 fi if test -n "$current_libdirs"; then # Maybe just do a dry run. test -n "$run" && current_libdirs=" -n$current_libdirs" exec_cmd='$SHELL $0 --finish$current_libdirs' else exit 0 fi ;; # libtool finish mode finish) modename="$modename: finish" libdirs="$nonopt" admincmds= if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then for dir do libdirs="$libdirs $dir" done for libdir in $libdirs; do if test -n "$finish_cmds"; then # Do each command in the finish commands. eval cmds=\"$finish_cmds\" save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" || admincmds="$admincmds $cmd" done IFS="$save_ifs" fi if test -n "$finish_eval"; then # Do the single finish_eval. eval cmds=\"$finish_eval\" $run eval "$cmds" || admincmds="$admincmds $cmds" fi done fi # Exit here if they wanted silent mode. test "$show" = : && exit 0 $echo "----------------------------------------------------------------------" $echo "Libraries have been installed in:" for libdir in $libdirs; do $echo " $libdir" done $echo $echo "If you ever happen to want to link against installed libraries" $echo "in a given directory, LIBDIR, you must either use libtool, and" $echo "specify the full pathname of the library, or use the \`-LLIBDIR'" $echo "flag during linking and do at least one of the following:" if test -n "$shlibpath_var"; then $echo " - add LIBDIR to the \`$shlibpath_var' environment variable" $echo " during execution" fi if test -n "$runpath_var"; then $echo " - add LIBDIR to the \`$runpath_var' environment variable" $echo " during linking" fi if test -n "$hardcode_libdir_flag_spec"; then libdir=LIBDIR eval flag=\"$hardcode_libdir_flag_spec\" $echo " - use the \`$flag' linker flag" fi if test -n "$admincmds"; then $echo " - have your system administrator run these commands:$admincmds" fi if test -f /etc/ld.so.conf; then $echo " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'" fi $echo $echo "See any operating system documentation about shared libraries for" $echo "more information, such as the ld(1) and ld.so(8) manual pages." $echo "----------------------------------------------------------------------" exit 0 ;; # libtool execute mode execute) modename="$modename: execute" # The first argument is the command name. cmd="$nonopt" if test -z "$cmd"; then $echo "$modename: you must specify a COMMAND" 1>&2 $echo "$help" exit 1 fi # Handle -dlopen flags immediately. for file in $execute_dlfiles; do if test ! -f "$file"; then $echo "$modename: \`$file' is not a file" 1>&2 $echo "$help" 1>&2 exit 1 fi dir= case $file in *.la) # Check to see that this really is a libtool archive. if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : else $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 $echo "$help" 1>&2 exit 1 fi # Read the libtool library. dlname= library_names= # If there is no directory component, then add one. case $file in */* | *\\*) . $file ;; *) . ./$file ;; esac # Skip this library if it cannot be dlopened. if test -z "$dlname"; then # Warn if it was a shared library. test -n "$library_names" && $echo "$modename: warning: \`$file' was not linked with \`-export-dynamic'" continue fi dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` test "X$dir" = "X$file" && dir=. if test -f "$dir/$objdir/$dlname"; then dir="$dir/$objdir" else $echo "$modename: cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" 1>&2 exit 1 fi ;; *.lo) # Just add the directory containing the .lo file. dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` test "X$dir" = "X$file" && dir=. ;; *) $echo "$modename: warning \`-dlopen' is ignored for non-libtool libraries and objects" 1>&2 continue ;; esac # Get the absolute pathname. absdir=`cd "$dir" && pwd` test -n "$absdir" && dir="$absdir" # Now add the directory to shlibpath_var. if eval "test -z \"\$$shlibpath_var\""; then eval "$shlibpath_var=\"\$dir\"" else eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" fi done # This variable tells wrapper scripts just to set shlibpath_var # rather than running their programs. libtool_execute_magic="$magic" # Check if any of the arguments is a wrapper script. args= for file do case $file in -*) ;; *) # Do a test to see if this is really a libtool program. if (${SED} -e '4q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then # If there is no directory component, then add one. case $file in */* | *\\*) . $file ;; *) . ./$file ;; esac # Transform arg to wrapped name. file="$progdir/$program" fi ;; esac # Quote arguments (to preserve shell metacharacters). file=`$echo "X$file" | $Xsed -e "$sed_quote_subst"` args="$args \"$file\"" done if test -z "$run"; then if test -n "$shlibpath_var"; then # Export the shlibpath_var. eval "export $shlibpath_var" fi # Restore saved environment variables if test "${save_LC_ALL+set}" = set; then LC_ALL="$save_LC_ALL"; export LC_ALL fi if test "${save_LANG+set}" = set; then LANG="$save_LANG"; export LANG fi # Now prepare to actually exec the command. exec_cmd="\$cmd$args" else # Display what would be done. if test -n "$shlibpath_var"; then eval "\$echo \"\$shlibpath_var=\$$shlibpath_var\"" $echo "export $shlibpath_var" fi $echo "$cmd$args" exit 0 fi ;; # libtool clean and uninstall mode clean | uninstall) modename="$modename: $mode" rm="$nonopt" files= rmforce= exit_status=0 # This variable tells wrapper scripts just to set variables rather # than running their programs. libtool_install_magic="$magic" for arg do case $arg in -f) rm="$rm $arg"; rmforce=yes ;; -*) rm="$rm $arg" ;; *) files="$files $arg" ;; esac done if test -z "$rm"; then $echo "$modename: you must specify an RM program" 1>&2 $echo "$help" 1>&2 exit 1 fi rmdirs= origobjdir="$objdir" for file in $files; do dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` if test "X$dir" = "X$file"; then dir=. objdir="$origobjdir" else objdir="$dir/$origobjdir" fi name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` test "$mode" = uninstall && objdir="$dir" # Remember objdir for removal later, being careful to avoid duplicates if test "$mode" = clean; then case " $rmdirs " in *" $objdir "*) ;; *) rmdirs="$rmdirs $objdir" ;; esac fi # Don't error if the file doesn't exist and rm -f was used. if (test -L "$file") >/dev/null 2>&1 \ || (test -h "$file") >/dev/null 2>&1 \ || test -f "$file"; then : elif test -d "$file"; then exit_status=1 continue elif test "$rmforce" = yes; then continue fi rmfiles="$file" case $name in *.la) # Possibly a libtool archive, so verify it. if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then . $dir/$name # Delete the libtool libraries and symlinks. for n in $library_names; do rmfiles="$rmfiles $objdir/$n" done test -n "$old_library" && rmfiles="$rmfiles $objdir/$old_library" test "$mode" = clean && rmfiles="$rmfiles $objdir/$name $objdir/${name}i" if test "$mode" = uninstall; then if test -n "$library_names"; then # Do each command in the postuninstall commands. eval cmds=\"$postuninstall_cmds\" save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" if test "$?" -ne 0 && test "$rmforce" != yes; then exit_status=1 fi done IFS="$save_ifs" fi if test -n "$old_library"; then # Do each command in the old_postuninstall commands. eval cmds=\"$old_postuninstall_cmds\" save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" if test "$?" -ne 0 && test "$rmforce" != yes; then exit_status=1 fi done IFS="$save_ifs" fi # FIXME: should reinstall the best remaining shared library. fi fi ;; *.lo) # Possibly a libtool object, so verify it. if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then # Read the .lo file . $dir/$name # Add PIC object to the list of files to remove. if test -n "$pic_object" \ && test "$pic_object" != none; then rmfiles="$rmfiles $dir/$pic_object" fi # Add non-PIC object to the list of files to remove. if test -n "$non_pic_object" \ && test "$non_pic_object" != none; then rmfiles="$rmfiles $dir/$non_pic_object" fi fi ;; *) if test "$mode" = clean ; then noexename=$name case $file in *.exe) file=`$echo $file|${SED} 's,.exe$,,'` noexename=`$echo $name|${SED} 's,.exe$,,'` # $file with .exe has already been added to rmfiles, # add $file without .exe rmfiles="$rmfiles $file" ;; esac # Do a test to see if this is a libtool program. if (${SED} -e '4q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then relink_command= . $dir/$noexename # note $name still contains .exe if it was in $file originally # as does the version of $file that was added into $rmfiles rmfiles="$rmfiles $objdir/$name $objdir/${name}S.${objext}" if test "$fast_install" = yes && test -n "$relink_command"; then rmfiles="$rmfiles $objdir/lt-$name" fi if test "X$noexename" != "X$name" ; then rmfiles="$rmfiles $objdir/lt-${noexename}.c" fi fi fi ;; esac $show "$rm $rmfiles" $run $rm $rmfiles || exit_status=1 done objdir="$origobjdir" # Try to remove the ${objdir}s in the directories where we deleted files for dir in $rmdirs; do if test -d "$dir"; then $show "rmdir $dir" $run rmdir $dir >/dev/null 2>&1 fi done exit $exit_status ;; "") $echo "$modename: you must specify a MODE" 1>&2 $echo "$generic_help" 1>&2 exit 1 ;; esac if test -z "$exec_cmd"; then $echo "$modename: invalid operation mode \`$mode'" 1>&2 $echo "$generic_help" 1>&2 exit 1 fi fi # test -z "$show_help" if test -n "$exec_cmd"; then eval exec $exec_cmd exit 1 fi # We need to display help for each of the modes. case $mode in "") $echo \ "Usage: $modename [OPTION]... [MODE-ARG]... Provide generalized library-building support services. --config show all configuration variables --debug enable verbose shell tracing -n, --dry-run display commands without modifying any files --features display basic configuration information and exit --finish same as \`--mode=finish' --help display this help message and exit --mode=MODE use operation mode MODE [default=inferred from MODE-ARGS] --quiet same as \`--silent' --silent don't print informational messages --tag=TAG use configuration variables from tag TAG --version print version information MODE must be one of the following: clean remove files from the build directory compile compile a source file into a libtool object execute automatically set library path, then run a program finish complete the installation of libtool libraries install install libraries or executables link create a library or an executable uninstall remove libraries from an installed directory MODE-ARGS vary depending on the MODE. Try \`$modename --help --mode=MODE' for a more detailed description of MODE. Report bugs to ." exit 0 ;; clean) $echo \ "Usage: $modename [OPTION]... --mode=clean RM [RM-OPTION]... FILE... Remove files from the build directory. RM is the name of the program to use to delete files associated with each FILE (typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed to RM. If FILE is a libtool library, object or program, all the files associated with it are deleted. Otherwise, only FILE itself is deleted using RM." ;; compile) $echo \ "Usage: $modename [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE Compile a source file into a libtool library object. This mode accepts the following additional options: -o OUTPUT-FILE set the output file name to OUTPUT-FILE -prefer-pic try to building PIC objects only -prefer-non-pic try to building non-PIC objects only -static always build a \`.o' file suitable for static linking COMPILE-COMMAND is a command to be used in creating a \`standard' object file from the given SOURCEFILE. The output file name is determined by removing the directory component from SOURCEFILE, then substituting the C source code suffix \`.c' with the library object suffix, \`.lo'." ;; execute) $echo \ "Usage: $modename [OPTION]... --mode=execute COMMAND [ARGS]... Automatically set library path, then run a program. This mode accepts the following additional options: -dlopen FILE add the directory containing FILE to the library path This mode sets the library path environment variable according to \`-dlopen' flags. If any of the ARGS are libtool executable wrappers, then they are translated into their corresponding uninstalled binary, and any of their required library directories are added to the library path. Then, COMMAND is executed, with ARGS as arguments." ;; finish) $echo \ "Usage: $modename [OPTION]... --mode=finish [LIBDIR]... Complete the installation of libtool libraries. Each LIBDIR is a directory that contains libtool libraries. The commands that this mode executes may require superuser privileges. Use the \`--dry-run' option if you just want to see what would be executed." ;; install) $echo \ "Usage: $modename [OPTION]... --mode=install INSTALL-COMMAND... Install executables or libraries. INSTALL-COMMAND is the installation command. The first component should be either the \`install' or \`cp' program. The rest of the components are interpreted as arguments to that command (only BSD-compatible install options are recognized)." ;; link) $echo \ "Usage: $modename [OPTION]... --mode=link LINK-COMMAND... Link object files or libraries together to form another library, or to create an executable program. LINK-COMMAND is a command using the C compiler that you would use to create a program from several object files. The following components of LINK-COMMAND are treated specially: -all-static do not do any dynamic linking at all -avoid-version do not add a version suffix if possible -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) -export-symbols SYMFILE try to export only the symbols listed in SYMFILE -export-symbols-regex REGEX try to export only the symbols matching REGEX -LLIBDIR search LIBDIR for required installed libraries -lNAME OUTPUT-FILE requires the installed library libNAME -module build a library that can dlopened -no-fast-install disable the fast-install mode -no-install link a not-installable executable -no-undefined declare that a library does not refer to external symbols -o OUTPUT-FILE create OUTPUT-FILE from the specified objects -objectlist FILE Use a list of object files found in FILE to specify objects -release RELEASE specify package release information -rpath LIBDIR the created library will eventually be installed in LIBDIR -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries -static do not do any dynamic linking of libtool libraries -version-info CURRENT[:REVISION[:AGE]] specify library version info [each variable defaults to 0] All other options (arguments beginning with \`-') are ignored. Every other argument is treated as a filename. Files ending in \`.la' are treated as uninstalled libtool libraries, other files are standard or library object files. If the OUTPUT-FILE ends in \`.la', then a libtool library is created, only library objects (\`.lo' files) may be specified, and \`-rpath' is required, except when creating a convenience library. If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created using \`ar' and \`ranlib', or on Windows using \`lib'. If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file is created, otherwise an executable program is created." ;; uninstall) $echo \ "Usage: $modename [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... Remove libraries from an installation directory. RM is the name of the program to use to delete files associated with each FILE (typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed to RM. If FILE is a libtool library, all the files associated with it are deleted. Otherwise, only FILE itself is deleted using RM." ;; *) $echo "$modename: invalid operation mode \`$mode'" 1>&2 $echo "$help" 1>&2 exit 1 ;; esac $echo $echo "Try \`$modename --help' for more information about other modes." exit 0 # The TAGs below are defined such that we never get into a situation # in which we disable both kinds of libraries. Given conflicting # choices, we go for a static library, that is the most portable, # since we can't tell whether shared libraries were disabled because # the user asked for that or because the platform doesn't support # them. This is particularly important on AIX, because we don't # support having both static and shared libraries enabled at the same # time on that platform, so we default to a shared-only configuration. # If a disable-shared tag is given, we'll fallback to a static-only # configuration. But we'll never go from static-only to shared-only. # ### BEGIN LIBTOOL TAG CONFIG: disable-shared build_libtool_libs=no build_old_libs=yes # ### END LIBTOOL TAG CONFIG: disable-shared # ### BEGIN LIBTOOL TAG CONFIG: disable-static build_old_libs=`case $build_libtool_libs in yes) $echo no;; *) $echo yes;; esac` # ### END LIBTOOL TAG CONFIG: disable-static # Local Variables: # mode:shell-script # sh-indentation:2 # End: hercules-3.07/autoconf/missing000755 000765 000765 00000021231 11143760527 020165 0ustar00jmaynardjmaynard000000 000000 #! /bin/sh # Common stub for a few missing GNU programs while installing. # Copyright 1996, 1997, 1999, 2000 Free Software Foundation, Inc. # Originally by Fran,cois Pinard , 1996. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program; if not, 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. if test $# -eq 0; then echo 1>&2 "Try \`$0 --help' for more information" exit 1 fi run=: # In the cases where this matters, `missing' is being run in the # srcdir already. if test -f configure.ac; then configure_ac=configure.ac else configure_ac=configure.in fi case "$1" in --run) # Try to run requested program, and just exit if it succeeds. run= shift "$@" && exit 0 ;; esac # If it does not exist, or fails to run (possibly an outdated version), # try to emulate it. case "$1" in -h|--h|--he|--hel|--help) echo "\ $0 [OPTION]... PROGRAM [ARGUMENT]... Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an error status if there is no known handling for PROGRAM. Options: -h, --help display this help and exit -v, --version output version information and exit --run try to run the given command, and emulate it if it fails Supported PROGRAM values: aclocal touch file \`aclocal.m4' autoconf touch file \`configure' autoheader touch file \`config.h.in' automake touch all \`Makefile.in' files bison create \`y.tab.[ch]', if possible, from existing .[ch] flex create \`lex.yy.c', if possible, from existing .c help2man touch the output file lex create \`lex.yy.c', if possible, from existing .c makeinfo touch the output file tar try tar, gnutar, gtar, then tar without non-portable flags yacc create \`y.tab.[ch]', if possible, from existing .[ch]" ;; -v|--v|--ve|--ver|--vers|--versi|--versio|--version) echo "missing 0.3 - GNU automake" ;; -*) echo 1>&2 "$0: Unknown \`$1' option" echo 1>&2 "Try \`$0 --help' for more information" exit 1 ;; aclocal) echo 1>&2 "\ WARNING: \`$1' is missing on your system. You should only need it if you modified \`acinclude.m4' or \`${configure_ac}'. You might want to install the \`Automake' and \`Perl' packages. Grab them from any GNU archive site." touch aclocal.m4 ;; autoconf) echo 1>&2 "\ WARNING: \`$1' is missing on your system. You should only need it if you modified \`${configure_ac}'. You might want to install the \`Autoconf' and \`GNU m4' packages. Grab them from any GNU archive site." touch configure ;; autoheader) echo 1>&2 "\ WARNING: \`$1' is missing on your system. You should only need it if you modified \`acconfig.h' or \`${configure_ac}'. You might want to install the \`Autoconf' and \`GNU m4' packages. Grab them from any GNU archive site." files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` test -z "$files" && files="config.h" touch_files= for f in $files; do case "$f" in *:*) touch_files="$touch_files "`echo "$f" | sed -e 's/^[^:]*://' -e 's/:.*//'`;; *) touch_files="$touch_files $f.in";; esac done touch $touch_files ;; automake) echo 1>&2 "\ WARNING: \`$1' is missing on your system. You should only need it if you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'. You might want to install the \`Automake' and \`Perl' packages. Grab them from any GNU archive site." find . -type f -name Makefile.am -print | sed 's/\.am$/.in/' | while read f; do touch "$f"; done ;; bison|yacc) echo 1>&2 "\ WARNING: \`$1' is missing on your system. You should only need it if you modified a \`.y' file. You may need the \`Bison' package in order for those modifications to take effect. You can get \`Bison' from any GNU archive site." rm -f y.tab.c y.tab.h if [ $# -ne 1 ]; then eval LASTARG="\${$#}" case "$LASTARG" in *.y) SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` if [ -f "$SRCFILE" ]; then cp "$SRCFILE" y.tab.c fi SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` if [ -f "$SRCFILE" ]; then cp "$SRCFILE" y.tab.h fi ;; esac fi if [ ! -f y.tab.h ]; then echo >y.tab.h fi if [ ! -f y.tab.c ]; then echo 'main() { return 0; }' >y.tab.c fi ;; lex|flex) echo 1>&2 "\ WARNING: \`$1' is missing on your system. You should only need it if you modified a \`.l' file. You may need the \`Flex' package in order for those modifications to take effect. You can get \`Flex' from any GNU archive site." rm -f lex.yy.c if [ $# -ne 1 ]; then eval LASTARG="\${$#}" case "$LASTARG" in *.l) SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` if [ -f "$SRCFILE" ]; then cp "$SRCFILE" lex.yy.c fi ;; esac fi if [ ! -f lex.yy.c ]; then echo 'main() { return 0; }' >lex.yy.c fi ;; help2man) echo 1>&2 "\ WARNING: \`$1' is missing on your system. You should only need it if you modified a dependency of a manual page. You may need the \`Help2man' package in order for those modifications to take effect. You can get \`Help2man' from any GNU archive site." file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` if test -z "$file"; then file=`echo "$*" | sed -n 's/.*--output=\([^ ]*\).*/\1/p'` fi if [ -f "$file" ]; then touch $file else test -z "$file" || exec >$file echo ".ab help2man is required to generate this page" exit 1 fi ;; makeinfo) if test -z "$run" && (makeinfo --version) > /dev/null 2>&1; then # We have makeinfo, but it failed. exit 1 fi echo 1>&2 "\ WARNING: \`$1' is missing on your system. You should only need it if you modified a \`.texi' or \`.texinfo' file, or any other file indirectly affecting the aspect of the manual. The spurious call might also be the consequence of using a buggy \`make' (AIX, DU, IRIX). You might want to install the \`Texinfo' package or the \`GNU make' package. Grab either from any GNU archive site." file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` if test -z "$file"; then file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file` fi touch $file ;; tar) shift if test -n "$run"; then echo 1>&2 "ERROR: \`tar' requires --run" exit 1 fi # We have already tried tar in the generic part. # Look for gnutar/gtar before invocation to avoid ugly error # messages. if (gnutar --version > /dev/null 2>&1); then gnutar ${1+"$@"} && exit 0 fi if (gtar --version > /dev/null 2>&1); then gtar ${1+"$@"} && exit 0 fi firstarg="$1" if shift; then case "$firstarg" in *o*) firstarg=`echo "$firstarg" | sed s/o//` tar "$firstarg" ${1+"$@"} && exit 0 ;; esac case "$firstarg" in *h*) firstarg=`echo "$firstarg" | sed s/h//` tar "$firstarg" ${1+"$@"} && exit 0 ;; esac fi echo 1>&2 "\ WARNING: I can't seem to be able to run \`tar' with the given arguments. You may want to install GNU tar or Free paxutils, or check the command line arguments." exit 1 ;; *) echo 1>&2 "\ WARNING: \`$1' is needed, and you do not seem to have it handy on your system. You might have modified some files without having the proper tools for further handling them. Check the \`README' file, it often tells you about the needed prerequirements for installing this package. You may also peek at any GNU archive site, in case some other package would contain this missing \`$1' program." exit 1 ;; esac exit 0 hercules-3.07/autoconf/mkinstalldirs000755 000765 000765 00000003500 11143760527 021373 0ustar00jmaynardjmaynard000000 000000 #! /bin/sh # mkinstalldirs --- make directory hierarchy # Author: Noah Friedman # Created: 1993-05-16 # Public domain # $Id: mkinstalldirs 1815 2003-08-24 23:15:35Z fish $ 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 ;; -- ) shift; break ;; # stop option processing -* ) echo "${usage}" 1>&2; exit 1 ;; # unknown option * ) break ;; # first non-opt arg 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: 3 # End: # mkinstalldirs ends here hercules-3.07/autoconf/README000644 000765 000765 00000000106 11143760527 017444 0ustar00jmaynardjmaynard000000 000000 This is where autoconf and automake will place their auxiliary files.